Skip to content

Commit

Permalink
Fix resizing to max width in classic themes (WordPress#64819)
Browse files Browse the repository at this point in the history
co-authored-by: kevin940726 <[email protected]>Co-authored-by: aaronrobertshaw <[email protected]>Co-authored-by: andrewserong <[email protected]>Co-authored-by: ramonjd <[email protected]>
* Fix resizing to max width in classic themes

* Fix padding and max-width

* Reverse the condition

* Try ignoring if layout doesn't exist
  • Loading branch information
kevin940726 authored Sep 11, 2024
1 parent ec58c51 commit 6a60081
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 12 deletions.
24 changes: 16 additions & 8 deletions packages/block-library/src/image/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ 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
Expand All @@ -32,6 +31,7 @@ import { unlock } from '../lock-unlock';
import { useUploadMediaFromBlobURL } from '../utils/hooks';
import Image from './image';
import { isValidFileType } from './utils';
import { useMaxWidthObserver } from './use-max-width-observer';

/**
* Module constants
Expand Down Expand Up @@ -111,10 +111,15 @@ export function ImageEdit( {
} = attributes;

const [ temporaryURL, setTemporaryURL ] = useState( attributes.blob );
const figureRef = useRef();

const [ contentResizeListener, { width: containerWidth } ] =
useResizeObserver();
const containerRef = useRef();
// Only observe the max width from the parent container when the parent layout is not flex nor grid.
// This won't work for them because the container width changes with the image.
// TODO: Find a way to observe the container width for flex and grid layouts.
const isMaxWidthContainerWidth =
! parentLayout ||
( parentLayout.type !== 'flex' && parentLayout.type !== 'grid' );
const [ maxWidthObserver, maxContentWidth ] = useMaxWidthObserver();

const [ placeholderResizeListener, { width: placeholderWidth } ] =
useResizeObserver();
Expand Down Expand Up @@ -166,7 +171,7 @@ export function ImageEdit( {
}

function onSelectImagesList( images ) {
const win = figureRef.current?.ownerDocument.defaultView;
const win = containerRef.current?.ownerDocument.defaultView;

if ( images.every( ( file ) => file instanceof win.File ) ) {
/** @type {File[]} */
Expand Down Expand Up @@ -354,7 +359,10 @@ export function ImageEdit( {
Object.keys( borderProps.style ).length > 0 ),
} );

const blockProps = useBlockProps( { ref: figureRef, className: classes } );
const blockProps = useBlockProps( {
ref: containerRef,
className: classes,
} );

// Much of this description is duplicated from MediaPlaceholder.
const { lockUrlControls = false, lockUrlControlsMessage } = useSelect(
Expand Down Expand Up @@ -445,7 +453,7 @@ export function ImageEdit( {
clientId={ clientId }
blockEditingMode={ blockEditingMode }
parentLayoutType={ parentLayout?.type }
containerWidth={ containerWidth }
maxContentWidth={ maxContentWidth }
/>
<MediaPlaceholder
icon={ <BlockIcon icon={ icon } /> }
Expand All @@ -464,7 +472,7 @@ export function ImageEdit( {
{
// 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
isSingleSelected && isMaxWidthContainerWidth && maxWidthObserver
}
</>
);
Expand Down
5 changes: 5 additions & 0 deletions packages/block-library/src/image/editor.scss
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,11 @@ figure.wp-block-image:not(.wp-block) {
text-align: center;
}

// Relatively position the alignment container to support the content resizer.
.wp-block[data-align]:has(> .wp-block-image) {
position: relative;
}

.wp-block-image__crop-area {
position: relative;
max-width: 100%;
Expand Down
9 changes: 5 additions & 4 deletions packages/block-library/src/image/image.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ export default function Image( {
clientId,
blockEditingMode,
parentLayoutType,
containerWidth,
maxContentWidth,
} ) {
const {
url = '',
Expand Down Expand Up @@ -938,7 +938,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;
const maxResizeWidth = maxContentWidth || maxWidthBuffer;

let showRightHandle = false;
let showLeftHandle = false;
Expand Down Expand Up @@ -984,9 +984,9 @@ export default function Image( {
} }
showHandle={ isSingleSelected }
minWidth={ minWidth }
maxWidth={ maxContentWidth }
maxWidth={ maxResizeWidth }
minHeight={ minHeight }
maxHeight={ maxContentWidth / ratio }
maxHeight={ maxResizeWidth / ratio }
lockAspectRatio={ ratio }
enable={ {
top: false,
Expand All @@ -1000,6 +1000,7 @@ export default function Image( {

// Clear hardcoded width if the resized width is close to the max-content width.
if (
maxContentWidth &&
// 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 &&
Expand Down
32 changes: 32 additions & 0 deletions packages/block-library/src/image/use-max-width-observer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* WordPress dependencies
*/
import { useRef } from '@wordpress/element';
import { useResizeObserver } from '@wordpress/compose';

function useMaxWidthObserver() {
const [ contentResizeListener, { width } ] = useResizeObserver();
const observerRef = useRef();

const maxWidthObserver = (
<div
// Some themes set max-width on blocks.
className="wp-block"
aria-hidden="true"
style={ {
position: 'absolute',
inset: 0,
width: '100%',
height: 0,
margin: 0,
} }
ref={ observerRef }
>
{ contentResizeListener }
</div>
);

return [ maxWidthObserver, width ];
}

export { useMaxWidthObserver };

0 comments on commit 6a60081

Please sign in to comment.