Skip to content

Commit

Permalink
Adds Aspect ratio control on Image blocks in Grids (#62891)
Browse files Browse the repository at this point in the history
Co-authored-by: amitraj2203 <[email protected]>
Co-authored-by: tellthemachines <[email protected]>
Co-authored-by: ndiego <[email protected]>
  • Loading branch information
4 people authored Jun 28, 2024
1 parent 55f3a98 commit 535c74f
Show file tree
Hide file tree
Showing 2 changed files with 121 additions and 94 deletions.
186 changes: 97 additions & 89 deletions packages/block-editor/src/components/dimensions-tool/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ function DimensionsTool( {
scaleOptions, // Default options handled by ScaleTool.
defaultScale = 'fill', // Match CSS default value for object-fit.
unitsOptions, // Default options handled by UnitControl.
tools = [ 'aspectRatio', 'widthHeight', 'scale' ],
} ) {
// Coerce undefined and CSS default values to be null.
const width =
Expand Down Expand Up @@ -92,95 +93,102 @@ function DimensionsTool( {

return (
<>
<AspectRatioTool
panelId={ panelId }
options={ aspectRatioOptions }
defaultValue={ defaultAspectRatio }
value={ aspectRatioValue }
onChange={ ( nextAspectRatio ) => {
const nextValue = { ...value };

// 'auto' is CSS default, so it gets treated as null.
nextAspectRatio =
nextAspectRatio === 'auto' ? null : nextAspectRatio;

setLastAspectRatio( nextAspectRatio );

// Update aspectRatio.
if ( ! nextAspectRatio ) {
delete nextValue.aspectRatio;
} else {
nextValue.aspectRatio = nextAspectRatio;
}

// Auto-update scale.
if ( ! nextAspectRatio ) {
delete nextValue.scale;
} else if ( lastScale ) {
nextValue.scale = lastScale;
} else {
nextValue.scale = defaultScale;
setLastScale( defaultScale );
}

// Auto-update width and height.
if ( 'custom' !== nextAspectRatio && width && height ) {
delete nextValue.height;
}

onChange( nextValue );
} }
/>
<WidthHeightTool
panelId={ panelId }
units={ unitsOptions }
value={ { width, height } }
onChange={ ( { width: nextWidth, height: nextHeight } ) => {
const nextValue = { ...value };

// 'auto' is CSS default, so it gets treated as null.
nextWidth = nextWidth === 'auto' ? null : nextWidth;
nextHeight = nextHeight === 'auto' ? null : nextHeight;

// Update width.
if ( ! nextWidth ) {
delete nextValue.width;
} else {
nextValue.width = nextWidth;
}

// Update height.
if ( ! nextHeight ) {
delete nextValue.height;
} else {
nextValue.height = nextHeight;
}

// Auto-update aspectRatio.
if ( nextWidth && nextHeight ) {
delete nextValue.aspectRatio;
} else if ( lastAspectRatio ) {
nextValue.aspectRatio = lastAspectRatio;
} else {
// No setting defaultAspectRatio here, because
// aspectRatio is optional in this scenario,
// unlike scale.
}

// Auto-update scale.
if ( ! lastAspectRatio && !! nextWidth !== !! nextHeight ) {
delete nextValue.scale;
} else if ( lastScale ) {
nextValue.scale = lastScale;
} else {
nextValue.scale = defaultScale;
setLastScale( defaultScale );
}

onChange( nextValue );
} }
/>
{ showScaleControl && (
{ tools.includes( 'aspectRatio' ) && (
<AspectRatioTool
panelId={ panelId }
options={ aspectRatioOptions }
defaultValue={ defaultAspectRatio }
value={ aspectRatioValue }
onChange={ ( nextAspectRatio ) => {
const nextValue = { ...value };

// 'auto' is CSS default, so it gets treated as null.
nextAspectRatio =
nextAspectRatio === 'auto' ? null : nextAspectRatio;

setLastAspectRatio( nextAspectRatio );

// Update aspectRatio.
if ( ! nextAspectRatio ) {
delete nextValue.aspectRatio;
} else {
nextValue.aspectRatio = nextAspectRatio;
}

// Auto-update scale.
if ( ! nextAspectRatio ) {
delete nextValue.scale;
} else if ( lastScale ) {
nextValue.scale = lastScale;
} else {
nextValue.scale = defaultScale;
setLastScale( defaultScale );
}

// Auto-update width and height.
if ( 'custom' !== nextAspectRatio && width && height ) {
delete nextValue.height;
}

onChange( nextValue );
} }
/>
) }
{ tools.includes( 'widthHeight' ) && (
<WidthHeightTool
panelId={ panelId }
units={ unitsOptions }
value={ { width, height } }
onChange={ ( { width: nextWidth, height: nextHeight } ) => {
const nextValue = { ...value };

// 'auto' is CSS default, so it gets treated as null.
nextWidth = nextWidth === 'auto' ? null : nextWidth;
nextHeight = nextHeight === 'auto' ? null : nextHeight;

// Update width.
if ( ! nextWidth ) {
delete nextValue.width;
} else {
nextValue.width = nextWidth;
}

// Update height.
if ( ! nextHeight ) {
delete nextValue.height;
} else {
nextValue.height = nextHeight;
}

// Auto-update aspectRatio.
if ( nextWidth && nextHeight ) {
delete nextValue.aspectRatio;
} else if ( lastAspectRatio ) {
nextValue.aspectRatio = lastAspectRatio;
} else {
// No setting defaultAspectRatio here, because
// aspectRatio is optional in this scenario,
// unlike scale.
}

// Auto-update scale.
if (
! lastAspectRatio &&
!! nextWidth !== !! nextHeight
) {
delete nextValue.scale;
} else if ( lastScale ) {
nextValue.scale = lastScale;
} else {
nextValue.scale = defaultScale;
setLastScale( defaultScale );
}

onChange( nextValue );
} }
/>
) }
{ tools.includes( 'scale' ) && showScaleControl && (
<ScaleTool
panelId={ panelId }
options={ scaleOptions }
Expand Down
29 changes: 24 additions & 5 deletions packages/block-library/src/image/image.js
Original file line number Diff line number Diff line change
Expand Up @@ -182,8 +182,7 @@ export default function Image( {
allowResize &&
hasNonContentControls &&
! isWideAligned &&
isLargeViewport &&
parentLayoutType !== 'grid';
isLargeViewport;
const imageSizeOptions = imageSizes
.filter(
( { slug } ) => image?.media_details?.sizes?.[ slug ]?.source_url
Expand Down Expand Up @@ -405,6 +404,20 @@ export default function Image( {
/>
);

const aspectRatioControl = (
<DimensionsTool
value={ { aspectRatio } }
onChange={ ( { aspectRatio: newAspectRatio } ) => {
setAttributes( {
aspectRatio: newAspectRatio,
scale: 'cover',
} );
} }
defaultAspectRatio="auto"
tools={ [ 'aspectRatio' ] }
/>
);

const resetAll = () => {
setAttributes( {
alt: undefined,
Expand All @@ -423,7 +436,10 @@ export default function Image( {
resetAll={ resetAll }
dropdownMenuProps={ dropdownMenuProps }
>
{ isResizable && dimensionsControl }
{ isResizable &&
( parentLayoutType === 'grid'
? aspectRatioControl
: dimensionsControl ) }
</ToolsPanel>
</InspectorControls>
);
Expand Down Expand Up @@ -738,7 +754,10 @@ export default function Image( {
/>
</ToolsPanelItem>
) }
{ isResizable && dimensionsControl }
{ isResizable &&
( parentLayoutType === 'grid'
? aspectRatioControl
: dimensionsControl ) }
{ !! imageSizeOptions.length && (
<ResolutionTool
value={ sizeSlug }
Expand Down Expand Up @@ -848,7 +867,7 @@ export default function Image( {
/>
</ImageWrapper>
);
} else if ( ! isResizable ) {
} else if ( ! isResizable || parentLayoutType === 'grid' ) {
img = (
<div style={ { width, height, aspectRatio } }>
<ImageWrapper href={ href }>{ img }</ImageWrapper>
Expand Down

0 comments on commit 535c74f

Please sign in to comment.