From 8effddec047bdb78e2ec1dbd6dd6f583b21e7652 Mon Sep 17 00:00:00 2001 From: Joe Bailey-Roberts Date: Fri, 23 Feb 2024 16:36:54 +0000 Subject: [PATCH] Add usePostThumbnail hook --- src/hooks/usePostThumbnail/README.md | 49 +++++++++++++++++++++++++++ src/hooks/usePostThumbnail/index.js | 50 ++++++++++++++++++++++++++++ src/index.js | 1 + 3 files changed, 100 insertions(+) create mode 100644 src/hooks/usePostThumbnail/README.md create mode 100644 src/hooks/usePostThumbnail/index.js diff --git a/src/hooks/usePostThumbnail/README.md b/src/hooks/usePostThumbnail/README.md new file mode 100644 index 0000000..31d78a6 --- /dev/null +++ b/src/hooks/usePostThumbnail/README.md @@ -0,0 +1,49 @@ +# usePostThumbnail + +The `usePostThumbnail` hook allows for easy use and updates of the post thumbnail from within a + +## Usage + +The `usePostThumbnail` hook provides 2 values, and a setter function + +```js +import { usePostThumbnail } from '@humanmade/block-editor-components'; + +function BlockEdit() { + const { postThumbnail, postThumbnailId, setPostThumbnail } = usePostThumbnail(); + + return ( + <> + + + setPostThumbnail( media.id ) + } + allowedTypes={ ALLOWED_MEDIA_TYPES } + value={ postThumbnailId } + render={ ( { open } ) => ( + + ) } + /> + + { + <> + ); +} +``` + +## Return + +The `usePostThumbnail` hook returns an object with 3 properties: + +- `postThumbnail` - The full media object for the post thumbnail (as returned from `select( 'core' ).getMedia()`) +- `postThumbnailId` - The ID of the thumbnail as an integer +- `setPostThumbnail` - A function to set the current post's thumbnail by ID + + +## Dependencies + +The `usePostThumbnail` hook requires the following dependencies, which are expected to be available: + +- `@wordpress/data` +- `@wordpress/element` diff --git a/src/hooks/usePostThumbnail/index.js b/src/hooks/usePostThumbnail/index.js new file mode 100644 index 0000000..d6ef416 --- /dev/null +++ b/src/hooks/usePostThumbnail/index.js @@ -0,0 +1,50 @@ +import { + useDispatch, + useSelect, +} from '@wordpress/data'; +import { useCallback } from '@wordpress/element'; + +/** + * @typedef {object} postThumbnailUtils + * @property {?object} postThumbnail The post thumbnail object + * @property {?number} postThumbnailId The post thumbnail ID + * @property {Function} setPostThumbnail Function to set the post thumbnail + */ + +/** + * Get the post thumbnail and a function to set it. + * + * @returns {postThumbnailUtils} The post thumbnail data and setter function + */ +export default function usePostThumbnail() { + + const { editPost } = useDispatch( 'core/editor' ); + + const postThumbnailId = useSelect( + ( select ) => select( 'core/editor' ).getEditedPostAttribute( 'featured_media' ) + ); + + const postThumbnail = useSelect( + ( select ) => { + if ( ! postThumbnailId ) { + return null; + } + return select( 'core' ).getMedia( postThumbnailId ); + }, + [ postThumbnailId ] + ); + + const setPostThumbnail = useCallback( + ( mediaId ) => { + // If the image has been removed, we can remove the post thumbnail. + editPost( { featured_media: mediaId } ); + }, + [ editPost ] + ); + + return { + postThumbnail, + postThumbnailId, + setPostThumbnail, + }; +} diff --git a/src/index.js b/src/index.js index 7b8733e..0759158 100644 --- a/src/index.js +++ b/src/index.js @@ -21,6 +21,7 @@ export { default as useActiveBlockStyle } from './hooks/useActiveBlockStyle'; export { default as useBlockStyles } from './hooks/useBlockStyles'; export { default as useDisallowedBlocks } from './hooks/useDisallowedBlocks'; export { default as useMeta } from './hooks/useMeta'; +export { default as usePostThumbnail } from './hooks/usePostThumbnail'; export { default as useRenderAppenderWithBlockLimit } from './hooks/useRenderAppenderWithBlockLimit'; export { default as useSelectBlock } from './hooks/useSelectBlock'; export { default as useSetAttribute } from './hooks/useSetAttribute';