diff --git a/plugins/woocommerce-blocks/assets/js/blocks/featured-items/image-editor.tsx b/plugins/woocommerce-blocks/assets/js/blocks/featured-items/image-editor.tsx index bf3bfa34209..ad570eae85f 100644 --- a/plugins/woocommerce-blocks/assets/js/blocks/featured-items/image-editor.tsx +++ b/plugins/woocommerce-blocks/assets/js/blocks/featured-items/image-editor.tsx @@ -3,6 +3,7 @@ /** * External dependencies */ +import { useCallback, useEffect, useRef, useState } from '@wordpress/element'; import { WP_REST_API_Category } from 'wp-types'; import { ProductResponseItem } from '@woocommerce/types'; import { @@ -18,7 +19,7 @@ import { BLOCK_NAMES, DEFAULT_EDITOR_SIZE } from './constants'; import { EditorBlock } from './types'; import { useBackgroundImage } from './use-background-image'; -type MediaAttributes = { mediaId: number; mediaSrc: string }; +type MediaAttributes = { align: string; mediaId: number; mediaSrc: string }; type MediaSize = { height: number; width: number }; interface WithImageEditorRequiredProps< T > { @@ -45,24 +46,70 @@ type WithImageEditorProps< T extends EditorBlock< T > > = | ( T & WithImageEditorProductProps< T > ); interface ImageEditorProps { + align: string; backgroundImageId: number; backgroundImageSize: MediaSize; backgroundImageSrc: string; + containerRef: React.RefObject< HTMLDivElement >; isEditingImage: boolean; setAttributes: ( attrs: MediaAttributes ) => void; setIsEditingImage: ( value: boolean ) => void; } +// Adapted from: +// https://github.com/WordPress/gutenberg/blob/v15.6.1/packages/block-library/src/image/use-client-width.js +function useClientWidth( + ref: React.RefObject< HTMLDivElement >, + dependencies: string[] +) { + const [ clientWidth, setClientWidth ]: [ + number | undefined, + Dispatch< SetStateAction< number | undefined > > + ] = useState(); + + const calculateClientWidth = useCallback( () => { + setClientWidth( ref.current?.clientWidth ); + }, [ ref ] ); + + useEffect( calculateClientWidth, [ + calculateClientWidth, + ...dependencies, + ] ); + useEffect( () => { + if ( ! ref.current ) { + return; + } + const { defaultView } = ref.current.ownerDocument; + + if ( ! defaultView ) { + return; + } + defaultView.addEventListener( 'resize', calculateClientWidth ); + + return () => { + defaultView.removeEventListener( 'resize', calculateClientWidth ); + }; + }, [ ref, calculateClientWidth ] ); + + return clientWidth; +} + export const ImageEditor = ( { + align, backgroundImageId, backgroundImageSize, backgroundImageSrc, + containerRef, isEditingImage, setAttributes, setIsEditingImage, }: ImageEditorProps ) => { - return ( - <> + const clientWidth = useClientWidth( containerRef, [ align ] ); + + // Fallback for WP 6.1 or lower. In WP 6.2. ImageEditingProvider was merged + // with ImageEditor, see: https://github.com/WordPress/gutenberg/pull/47171 + if ( typeof ImageEditingProvider === 'function' ) { + return ( - + ); + } + + return ( + { + setAttributes( { mediaId: id, mediaSrc: url } ); + } } + onFinishEditing={ () => setIsEditingImage( false ) } + clientWidth={ clientWidth } + /> ); }; @@ -97,6 +160,8 @@ export const withImageEditor = ( props: WithImageEditorProps< T > ) => { const [ isEditingImage, setIsEditingImage ] = props.useEditingImage; + const ref = useRef< HTMLDivElement >( null ); + const { attributes, backgroundImageSize, name, setAttributes } = props; const { mediaId, mediaSrc } = attributes; const item = @@ -113,14 +178,18 @@ export const withImageEditor = if ( isEditingImage ) { return ( - +
+ +
); }