diff --git a/assets/js/blocks/featured-product/block.js b/assets/js/blocks/featured-product/block.js index 023ef71118a..a0126cd3665 100644 --- a/assets/js/blocks/featured-product/block.js +++ b/assets/js/blocks/featured-product/block.js @@ -3,7 +3,7 @@ /** * External dependencies */ -import { useCallback, useState } from 'react'; +import { useCallback, useEffect, useState } from 'react'; import { __ } from '@wordpress/i18n'; import { AlignmentToolbar, @@ -13,6 +13,8 @@ import { MediaReplaceFlow, RichText, __experimentalGetSpacingClassesAndStyles as getSpacingClassesAndStyles, + __experimentalImageEditingProvider as ImageEditingProvider, + __experimentalImageEditor as ImageEditor, __experimentalPanelColorGradientSettings as PanelColorGradientSettings, __experimentalUseGradient as useGradient, } from '@wordpress/block-editor'; @@ -26,6 +28,7 @@ import { ResizableBox, Spinner, ToggleControl, + ToolbarButton, ToolbarGroup, withSpokenMessages, __experimentalToggleGroupControl as ToggleGroupControl, @@ -40,7 +43,7 @@ import ProductControl from '@woocommerce/editor-components/product-control'; import ErrorPlaceholder from '@woocommerce/editor-components/error-placeholder'; import TextToolbarButton from '@woocommerce/editor-components/text-toolbar-button'; import { withProduct } from '@woocommerce/block-hocs'; -import { Icon, starEmpty } from '@wordpress/icons'; +import { crop, Icon, starEmpty } from '@wordpress/icons'; /** * Internal dependencies @@ -52,6 +55,11 @@ import { } from '../../utils/products'; import { useThrottle } from '../../utils/useThrottle'; +const DEFAULT_EDITOR_SIZE = { + height: 500, + width: 500, +}; + export const ConstrainedResizable = ( { className = '', onResize, @@ -110,10 +118,18 @@ const FeaturedProduct = ( { setAttributes, triggerUrlUpdate = () => void null, } ) => { + const { mediaId, mediaSrc } = attributes; + + const [ isEditingImage, setIsEditingImage ] = useState( false ); + const [ backgroundImageSize, setBackgroundImageSize ] = useState( {} ); const { setGradient } = useGradient( { gradientAttribute: 'overlayGradient', customGradientAttribute: 'overlayGradient', } ); + + const backgroundImageSrc = mediaSrc || getImageSrcFromProduct( product ); + const backgroundImageId = mediaId || getImageIdFromProduct( product ); + const onResize = useCallback( ( _event, _direction, elt ) => { setAttributes( { minHeight: parseInt( elt.style.height, 10 ) } ); @@ -130,6 +146,10 @@ const FeaturedProduct = ( { /> ); + useEffect( () => { + setIsEditingImage( false ); + }, [ isSelected ] ); + const renderEditMode = () => { const onDone = () => { setAttributes( { editMode: false } ); @@ -180,8 +200,7 @@ const FeaturedProduct = ( { }; const getBlockControls = () => { - const { contentAlign, editMode, mediaSrc } = attributes; - const mediaId = attributes.mediaId || getImageIdFromProduct( product ); + const { contentAlign, editMode } = attributes; return ( @@ -192,8 +211,18 @@ const FeaturedProduct = ( { } } /> + { ! isEditingImage && ( + setIsEditingImage( true ) } + icon={ crop } + label={ __( + 'Edit product image', + 'woo-gutenberg-products-block' + ) } + /> + ) } { @@ -204,7 +233,7 @@ const FeaturedProduct = ( { } } allowedTypes={ [ 'image' ] } /> - { mediaId && mediaSrc ? ( + { backgroundImageId && mediaSrc ? ( setAttributes( { mediaId: 0, mediaSrc: '' } ) @@ -400,7 +429,6 @@ const FeaturedProduct = ( { dimRatio, focalPoint, imageFit, - mediaSrc, minHeight, overlayColor, overlayGradient, @@ -430,9 +458,6 @@ const FeaturedProduct = ( { minHeight, }; - const backgroundImageSrc = - mediaSrc || getImageSrcFromProduct( product ); - const backgroundImageStyle = { ...calculateBackgroundImagePosition( focalPoint ), objectFit: imageFit, @@ -465,6 +490,12 @@ const FeaturedProduct = ( { className="wc-block-featured-product__background-image" src={ backgroundImageSrc } style={ backgroundImageStyle } + onLoad={ ( e ) => { + setBackgroundImageSize( { + height: e.target?.naturalHeight, + width: e.target?.naturalWidth, + } ); + } } />

+ { + setAttributes( { mediaId: id, mediaSrc: url } ); + } } + isEditing={ isEditingImage } + onFinishEditing={ () => setIsEditingImage( false ) } + > + + + + ); + } + return ( <> { getBlockControls() } diff --git a/assets/js/blocks/featured-product/style.scss b/assets/js/blocks/featured-product/style.scss index 093c1eb6ae9..75b71078946 100644 --- a/assets/js/blocks/featured-product/style.scss +++ b/assets/js/blocks/featured-product/style.scss @@ -16,6 +16,21 @@ height: auto !important; } } + + // Applying image edits + .is-applying { + .components-spinner { + position: absolute; + top: 50%; + left: 50%; + margin-top: -9px; + margin-left: -9px; + } + + img { + opacity: 0.3; + } + } } .wc-block-featured-product {