diff --git a/packages/block-library/src/image/edit.js b/packages/block-library/src/image/edit.js index fb11b3f50a5b6..b7c25595dcfcc 100644 --- a/packages/block-library/src/image/edit.js +++ b/packages/block-library/src/image/edit.js @@ -23,6 +23,7 @@ import { useEffect, useRef, useState } from '@wordpress/element'; import { __, sprintf } from '@wordpress/i18n'; import { image as icon, plugins as pluginsIcon } from '@wordpress/icons'; import { store as noticesStore } from '@wordpress/notices'; +import { useResizeObserver } from '@wordpress/compose'; /** * Internal dependencies @@ -109,6 +110,9 @@ export function ImageEdit( { } = attributes; const [ temporaryURL, setTemporaryURL ] = useState( attributes.blob ); + const [ contentResizeListener, { width: containerWidth } ] = + useResizeObserver(); + const altRef = useRef(); useEffect( () => { altRef.current = alt; @@ -364,35 +368,43 @@ export function ImageEdit( { }; return ( -
- - } - onSelect={ onSelectImage } - onSelectURL={ onSelectURL } - onError={ onUploadError } - placeholder={ placeholder } - accept="image/*" - allowedTypes={ ALLOWED_MEDIA_TYPES } - value={ { id, src } } - mediaPreview={ mediaPreview } - disableMediaButtons={ temporaryURL || url } - /> -
+ <> +
+ + } + onSelect={ onSelectImage } + onSelectURL={ onSelectURL } + onError={ onUploadError } + placeholder={ placeholder } + accept="image/*" + allowedTypes={ ALLOWED_MEDIA_TYPES } + value={ { id, src } } + mediaPreview={ mediaPreview } + disableMediaButtons={ temporaryURL || url } + /> +
+ { + // The listener cannot be placed as the first element as it will break the in-between inserter. + // See https://github.com/WordPress/gutenberg/blob/71134165868298fc15e22896d0c28b41b3755ff7/packages/block-editor/src/components/block-list/use-in-between-inserter.js#L120 + contentResizeListener + } + ); } diff --git a/packages/block-library/src/image/image.js b/packages/block-library/src/image/image.js index 646299bb7e089..3ad12d8dca4b6 100644 --- a/packages/block-library/src/image/image.js +++ b/packages/block-library/src/image/image.js @@ -109,6 +109,7 @@ export default function Image( { clientId, blockEditingMode, parentLayoutType, + containerWidth, } ) { const { url = '', @@ -928,6 +929,7 @@ export default function Image( { // @todo It would be good to revisit this once a content-width variable // becomes available. const maxWidthBuffer = maxWidth * 2.5; + const maxContentWidth = containerWidth || maxWidthBuffer; let showRightHandle = false; let showLeftHandle = false; @@ -973,9 +975,9 @@ export default function Image( { } } showHandle={ isSingleSelected } minWidth={ minWidth } - maxWidth={ maxWidthBuffer } + maxWidth={ maxContentWidth } minHeight={ minHeight } - maxHeight={ maxWidthBuffer / ratio } + maxHeight={ maxContentWidth / ratio } lockAspectRatio={ ratio } enable={ { top: false, @@ -986,6 +988,21 @@ export default function Image( { onResizeStart={ onResizeStart } onResizeStop={ ( event, direction, elt ) => { onResizeStop(); + + // Clear hardcoded width if the resized width is close to the max-content width. + if ( + // Only do this if the image is bigger than the container to prevent it from being squished. + // TODO: Remove this check if the image support setting 100% width. + naturalWidth >= maxContentWidth && + Math.abs( elt.offsetWidth - maxContentWidth ) < 10 + ) { + setAttributes( { + width: undefined, + height: undefined, + } ); + return; + } + // Since the aspect ratio is locked when resizing, we can // use the width of the resized element to calculate the // height in CSS to prevent stretching when the max-width