From 6a73eae44fdb894bc8a7f9203f6840925b9dc1e4 Mon Sep 17 00:00:00 2001 From: tellthemachines Date: Tue, 20 Feb 2024 17:46:45 +1100 Subject: [PATCH 01/14] Add Width and Height controls to children of flex, flow and constrained layouts. --- .../src/components/block-edit/index.js | 8 +- .../components/child-layout-control/index.js | 351 ++++++++++++++---- .../global-styles/dimensions-panel.js | 5 + .../src/components/inner-blocks/index.js | 20 +- .../block-editor/src/hooks/layout-child.js | 121 +++++- 5 files changed, 431 insertions(+), 74 deletions(-) diff --git a/packages/block-editor/src/components/block-edit/index.js b/packages/block-editor/src/components/block-edit/index.js index 4e94a8a427510..fcac905c084f5 100644 --- a/packages/block-editor/src/components/block-edit/index.js +++ b/packages/block-editor/src/components/block-edit/index.js @@ -42,11 +42,14 @@ export default function BlockEdit( { attributes = {}, __unstableLayoutClassNames, } = props; - const { layout = null, metadata = {} } = attributes; + const { layout = null, align = null, metadata = {} } = attributes; const { bindings } = metadata; const layoutSupport = hasBlockSupport( name, 'layout', false ) || hasBlockSupport( name, '__experimentalLayout', false ); + + const hasAlignSupport = hasBlockSupport( name, 'align', false ); + return ( { + let selectedValue; + if ( isFlowOrConstrained ) { + // Replace "full" with "fill" for full width alignments. + if ( alignWidth === 'full' ) { + selectedValue = 'fill'; + } else if ( alignWidth === 'wide' ) { + selectedValue = 'wide'; + } else if ( selfAlign === 'fixedNoShrink' ) { + selectedValue = 'fixedNoShrink'; + } else if ( selfAlign === 'fit' ) { + selectedValue = 'fit'; + } else { + selectedValue = 'content'; + } + } else if ( + parentLayoutType === 'flex' && + orientation === 'vertical' + ) { + const defaultSelfAlign = + justifyContent === 'stretch' ? 'fill' : 'fit'; + selectedValue = selfAlign || defaultSelfAlign; + } else if ( + parentLayoutType === 'flex' && + orientation === 'horizontal' + ) { + selectedValue = selfStretch || 'fit'; + } else { + selectedValue = 'fill'; + } + + return widthOptions.find( ( _value ) => _value?.key === selectedValue ); + }; + + const selectedHeight = () => { + let selectedValue; + if ( + isFlowOrConstrained || + ( parentLayoutType === 'flex' && orientation === 'vertical' ) + ) { + selectedValue = childLayout[ heightProp ] || 'fit'; + } else if ( parentLayoutType === 'flex' ) { + const defaultSelfAlign = + verticalAlignment === 'stretch' ? 'fill' : 'fit'; + selectedValue = childLayout[ heightProp ] || defaultSelfAlign; + } else { + selectedValue = 'fit'; + } + return heightOptions.find( + ( _value ) => _value?.key === selectedValue + ); + }; + + const onChangeWidth = ( newWidth ) => { + const { selectedItem } = newWidth; + const { key } = selectedItem; + if ( isFlowOrConstrained ) { + if ( key === 'fill' ) { + onChange( { [ widthProp ]: key } ); + onChangeAlign( { align: 'full' } ); + } else if ( key === 'wide' ) { + onChange( { [ widthProp ]: key } ); + onChangeAlign( { align: 'wide' } ); + } else if ( key === 'fixedNoShrink' ) { + onChange( { + ...childLayout, + [ widthProp ]: key, + } ); + onChangeAlign( { align: 'none' } ); + } else { + onChange( { [ widthProp ]: key } ); + onChangeAlign( { align: 'none' } ); + } + } else if ( parentLayoutType === 'flex' ) { + onChange( { + ...childLayout, + [ widthProp ]: key, + } ); + } + }; + + const onChangeHeight = ( newHeight ) => { + onChange( { + ...childLayout, + [ heightProp ]: newHeight.selectedItem.key, + } ); + }; + useEffect( () => { if ( selfStretch === 'fixed' && ! flexSize ) { onChange( { @@ -58,52 +273,64 @@ export default function ChildLayoutControl( { return ( <> - { parentLayoutType === 'flex' && ( + { parentLayoutType !== 'grid' && ( <> - { - const newFlexSize = - value !== 'fixed' ? null : flexSize; - onChange( { - selfStretch: value, - flexSize: newFlexSize, - } ); - } } - isBlock={ true } - > - - - - - { selfStretch === 'fixed' && ( - { - onChange( { - selfStretch, - flexSize: value, - } ); - } } - value={ flexSize } - /> - ) } + + + + + + { ( childLayout[ widthProp ] === 'fixed' || + childLayout[ widthProp ] === 'fixedNoShrink' ) && ( + + { + onChange( { + ...childLayout, + width: _value, + } ); + } } + value={ width } + /> + + ) } + + + + + + + { ( childLayout[ heightProp ] === 'fixed' || + childLayout[ heightProp ] === 'fixedNoShrink' ) && ( + + { + onChange( { + ...childLayout, + height: _value, + } ); + } } + value={ height } + /> + + ) } + ) } { parentLayoutType === 'grid' && ( diff --git a/packages/block-editor/src/components/global-styles/dimensions-panel.js b/packages/block-editor/src/components/global-styles/dimensions-panel.js index 1386df0dfe289..5681a6ae5ab49 100644 --- a/packages/block-editor/src/components/global-styles/dimensions-panel.js +++ b/packages/block-editor/src/components/global-styles/dimensions-panel.js @@ -414,6 +414,10 @@ export default function DimensionsPanel( { }, } ); }; + const setChildLayoutAlign = ( newChildLayoutAlign ) => { + onChange( newChildLayoutAlign ); + }; + const resetChildLayoutValue = () => { setChildLayout( { selfStretch: undefined, @@ -665,6 +669,7 @@ export default function DimensionsPanel( { diff --git a/packages/block-editor/src/components/inner-blocks/index.js b/packages/block-editor/src/components/inner-blocks/index.js index deb4328212b10..9d7964f91bc1a 100644 --- a/packages/block-editor/src/components/inner-blocks/index.js +++ b/packages/block-editor/src/components/inner-blocks/index.js @@ -70,6 +70,7 @@ function UncontrolledInnerBlocks( props ) { renderAppender, orientation, placeholder, + align, layout, name, blockType, @@ -104,19 +105,18 @@ function UncontrolledInnerBlocks( props ) { getBlockSupport( name, '__experimentalLayout' ) || EMPTY_OBJECT; - const { allowSizingOnChildren = false } = defaultLayoutBlockSupport; - const usedLayout = layout || defaultLayoutBlockSupport; - const memoedLayout = useMemo( () => ( { - // Default layout will know about any content/wide size defined by the theme. + // Default layout contains theme.json settings such as content and wide size. ...defaultLayout, - ...usedLayout, - ...( allowSizingOnChildren && { - allowSizingOnChildren: true, - } ), + // Any layout settings added to the block. + ...layout, + // The layout settings from the block's block.json. + ...defaultLayoutBlockSupport, + // Any alignment set on the block. + ...( align && { alignWidth: align } ), } ), - [ defaultLayout, usedLayout, allowSizingOnChildren ] + [ defaultLayout, layout, defaultLayoutBlockSupport, align ] ); // For controlled inner blocks, we don't want a change in blocks to @@ -185,6 +185,7 @@ export function useInnerBlocksProps( props = {}, options = {} ) { } = options; const { clientId, + align = null, layout = null, __unstableLayoutClassNames: layoutClassNames = '', } = useBlockEditContext(); @@ -259,6 +260,7 @@ export function useInnerBlocksProps( props = {}, options = {} ) { const innerBlocksProps = { __experimentalCaptureToolbars, + align, layout, name, blockType, diff --git a/packages/block-editor/src/hooks/layout-child.js b/packages/block-editor/src/hooks/layout-child.js index d8333e8e0e830..4694ab2c2a2e1 100644 --- a/packages/block-editor/src/hooks/layout-child.js +++ b/packages/block-editor/src/hooks/layout-child.js @@ -17,12 +17,34 @@ function useBlockPropsChildLayoutStyles( { style } ) { return ! select( blockEditorStore ).getSettings().disableLayoutStyles; } ); const layout = style?.layout ?? {}; - const { selfStretch, flexSize, columnSpan, rowSpan } = layout; + const { selfStretch, flexSize, columnSpan, rowSpan, height, width } = + layout; const parentLayout = useLayout() || {}; - const { columnCount, minimumColumnWidth } = parentLayout; + const { + columnCount, + minimumColumnWidth, + orientation, + type: parentType, + default: { type: defaultParentType = 'default' } = {}, + } = parentLayout; + const parentLayoutType = parentType || defaultParentType; const id = useInstanceId( useBlockPropsChildLayoutStyles ); const selector = `.wp-container-content-${ id }`; + const isFlowOrConstrained = + parentLayout.type === 'constrained' || + parentLayout.type === 'default' || + parentLayout.type === undefined; + + const widthProp = + isFlowOrConstrained || orientation === 'vertical' + ? 'selfAlign' + : 'selfStretch'; + const heightProp = + isFlowOrConstrained || orientation === 'vertical' + ? 'selfStretch' + : 'selfAlign'; + let css = ''; if ( shouldRenderChildLayoutStyles ) { if ( selfStretch === 'fixed' && flexSize ) { @@ -39,6 +61,101 @@ function useBlockPropsChildLayoutStyles( { style } ) { grid-column: span ${ columnSpan }; }`; } + if ( isFlowOrConstrained || orientation === 'vertical' ) { + // set width + if ( layout[ widthProp ] === 'fixed' && width ) { + css += `${ selector } { + max-width: ${ width }; + }`; + } else if ( layout[ widthProp ] === 'fixedNoShrink' && width ) { + css += `${ selector } { + width: ${ width }; + }`; + } else if ( layout[ widthProp ] === 'fill' ) { + css += `${ selector } { + align-self: stretch; + }`; + } else if ( layout[ widthProp ] === 'fit' ) { + css += `${ selector } { + width: fit-content; + }`; + } + + // set height + if ( layout[ heightProp ] === 'fixed' && height ) { + css += `${ selector } { + max-height: ${ height }; + flex-grow: 0; + flex-shrink: 1; + flex-basis: ${ height }; + }`; + } else if ( layout[ heightProp ] === 'fixedNoShrink' && height ) { + css += `${ selector } { + height: ${ height }; + flex-shrink: 0; + flex-grow: 0; + flex-basis: auto; + }`; + } else if ( layout[ heightProp ] === 'fill' ) { + css += `${ selector } { + flex-grow: 1; + flex-shrink: 1; + }`; + } else if ( layout[ heightProp ] === 'fit' ) { + css += `${ selector } { + flex-grow: 0; + flex-shrink: 0; + flex-basis: auto; + height: auto; + }`; + } + } else if ( parentLayoutType !== 'grid' ) { + // set width + if ( layout[ widthProp ] === 'fixed' && width ) { + css += `${ selector } { + max-width: ${ width }; + flex-grow: 0; + flex-shrink: 1; + flex-basis: ${ width }; + + }`; + } else if ( layout[ widthProp ] === 'fixedNoShrink' && width ) { + css += `${ selector } { + width: ${ width }; + flex-shrink: 0; + flex-grow: 0; + flex-basis: auto; + }`; + } else if ( layout[ widthProp ] === 'fill' ) { + css += `${ selector } { + flex-grow: 1; + flex-shrink: 1; + flex-basis: 100%; + }`; + } else if ( layout[ widthProp ] === 'fit' ) { + css += `${ selector } { + flex-grow: 0; + flex-shrink: 0; + flex-basis: auto; + width: fit-content; + }`; + } + + // set height + if ( layout[ heightProp ] === 'fill' ) { + css += `${ selector } { + align-self: stretch; + }`; + } else if ( layout[ heightProp ] === 'fit' ) { + css += `${ selector } { + height: fit-content; + }`; + } else if ( layout[ heightProp ] === 'fixedNoShrink' ) { + css += `${ selector } { + height: ${ height }; + }`; + } + } /** * If minimumColumnWidth is set on the parent, or if no * columnCount is set, the grid is responsive so a From 82f68ff6f7d0285bac62aec3da581fdba863d005 Mon Sep 17 00:00:00 2001 From: tellthemachines Date: Tue, 20 Feb 2024 17:58:26 +1100 Subject: [PATCH 02/14] Show child layout panel for all layout types --- .../components/global-styles/dimensions-panel.js | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/packages/block-editor/src/components/global-styles/dimensions-panel.js b/packages/block-editor/src/components/global-styles/dimensions-panel.js index 5681a6ae5ab49..a9c4a990490e2 100644 --- a/packages/block-editor/src/components/global-styles/dimensions-panel.js +++ b/packages/block-editor/src/components/global-styles/dimensions-panel.js @@ -85,18 +85,9 @@ function useHasAspectRatio( settings ) { } function useHasChildLayout( settings ) { - const { - type: parentLayoutType = 'default', - default: { type: defaultParentLayoutType = 'default' } = {}, - allowSizingOnChildren = false, - } = settings?.parentLayout ?? {}; + const { allowSizingOnChildren = false } = settings?.parentLayout ?? {}; - const support = - ( defaultParentLayoutType === 'flex' || - parentLayoutType === 'flex' || - defaultParentLayoutType === 'grid' || - parentLayoutType === 'grid' ) && - allowSizingOnChildren; + const support = allowSizingOnChildren; return !! settings?.layout && support; } From a271953c9e22cf3f768bced909ba223b36ecc179 Mon Sep 17 00:00:00 2001 From: tellthemachines Date: Wed, 21 Feb 2024 16:00:39 +1100 Subject: [PATCH 03/14] Fix booboos --- .../components/child-layout-control/index.js | 36 +++++++++++++------ .../global-styles/dimensions-panel.js | 14 +++----- packages/block-editor/src/hooks/dimensions.js | 27 ++++++++++++-- 3 files changed, 53 insertions(+), 24 deletions(-) diff --git a/packages/block-editor/src/components/child-layout-control/index.js b/packages/block-editor/src/components/child-layout-control/index.js index bf081fab71e7c..b7526ce92f69e 100644 --- a/packages/block-editor/src/components/child-layout-control/index.js +++ b/packages/block-editor/src/components/child-layout-control/index.js @@ -18,14 +18,15 @@ import { useEffect } from '@wordpress/element'; * @param {Object} props.value The child layout value. * @param {Function} props.onChange Function to update the child layout value. * @param {Object} props.parentLayout The parent layout value. + * @param {Object} props.alignments * * @return {Element} child layout edit element. */ export default function ChildLayoutControl( { value: childLayout = {}, onChange, - onChangeAlign, parentLayout, + alignments, } ) { const { selfStretch, @@ -36,13 +37,20 @@ export default function ChildLayoutControl( { height, width, } = childLayout; + + const { + current: currentAlignment, + supported: supportedAlignments, + onChangeAlignment, + } = alignments || {}; + const { orientation = 'horizontal', type: parentType, default: { type: defaultParentType = 'default' } = {}, justifyContent = 'left', verticalAlignment = 'center', - alignWidth = 'none', + alignWidth: parentAlignment = 'none', } = parentLayout ?? {}; const parentLayoutType = parentType || defaultParentType; @@ -68,14 +76,20 @@ export default function ChildLayoutControl( { value: 'content', name: __( 'Default' ), } ); - if ( alignWidth === 'wide' ) { + if ( + supportedAlignments?.includes( 'wide' ) && + ( parentAlignment === 'wide' || parentAlignment === 'full' ) + ) { widthOptions.push( { key: 'wide', value: 'wide', name: __( 'Wide' ), } ); } - if ( alignWidth === 'full' ) { + if ( + supportedAlignments?.includes( 'full' ) && + parentAlignment === 'full' + ) { widthOptions.push( { key: 'fill', value: 'fill', @@ -91,7 +105,7 @@ export default function ChildLayoutControl( { { key: 'fixedNoShrink', value: 'fixedNoShrink', - name: __( 'Custom' ), + name: __( 'Fixed' ), } ); } else if ( @@ -178,9 +192,9 @@ export default function ChildLayoutControl( { let selectedValue; if ( isFlowOrConstrained ) { // Replace "full" with "fill" for full width alignments. - if ( alignWidth === 'full' ) { + if ( currentAlignment === 'full' ) { selectedValue = 'fill'; - } else if ( alignWidth === 'wide' ) { + } else if ( currentAlignment === 'wide' ) { selectedValue = 'wide'; } else if ( selfAlign === 'fixedNoShrink' ) { selectedValue = 'fixedNoShrink'; @@ -233,19 +247,19 @@ export default function ChildLayoutControl( { if ( isFlowOrConstrained ) { if ( key === 'fill' ) { onChange( { [ widthProp ]: key } ); - onChangeAlign( { align: 'full' } ); + onChangeAlignment( 'full' ); } else if ( key === 'wide' ) { onChange( { [ widthProp ]: key } ); - onChangeAlign( { align: 'wide' } ); + onChangeAlignment( 'wide' ); } else if ( key === 'fixedNoShrink' ) { onChange( { ...childLayout, [ widthProp ]: key, } ); - onChangeAlign( { align: 'none' } ); + onChangeAlignment( null ); } else { onChange( { [ widthProp ]: key } ); - onChangeAlign( { align: 'none' } ); + onChangeAlignment( null ); } } else if ( parentLayoutType === 'flex' ) { onChange( { diff --git a/packages/block-editor/src/components/global-styles/dimensions-panel.js b/packages/block-editor/src/components/global-styles/dimensions-panel.js index a9c4a990490e2..62f82254c7fdb 100644 --- a/packages/block-editor/src/components/global-styles/dimensions-panel.js +++ b/packages/block-editor/src/components/global-styles/dimensions-panel.js @@ -199,6 +199,7 @@ const DEFAULT_CONTROLS = { export default function DimensionsPanel( { as: Wrapper = DimensionsToolsPanel, value, + alignments = null, onChange, inheritedValue = value, settings, @@ -397,16 +398,9 @@ export default function DimensionsPanel( { orientation === 'horizontal' ? __( 'Width' ) : __( 'Height' ); const childLayoutResetLabel = parentLayoutType === 'flex' ? flexResetLabel : __( 'Grid spans' ); + const setChildLayout = ( newChildLayout ) => { - onChange( { - ...value, - layout: { - ...newChildLayout, - }, - } ); - }; - const setChildLayoutAlign = ( newChildLayoutAlign ) => { - onChange( newChildLayoutAlign ); + onChange( setImmutably( value, [ 'layout' ], newChildLayout ) ); }; const resetChildLayoutValue = () => { @@ -660,8 +654,8 @@ export default function DimensionsPanel( { ) } diff --git a/packages/block-editor/src/hooks/dimensions.js b/packages/block-editor/src/hooks/dimensions.js index f78a39230e89b..e79e95b2967c4 100644 --- a/packages/block-editor/src/hooks/dimensions.js +++ b/packages/block-editor/src/hooks/dimensions.js @@ -70,11 +70,19 @@ function DimensionsInspectorControl( { children, resetAllFilter } ) { export function DimensionsPanel( { clientId, name, setAttributes, settings } ) { const isEnabled = useHasDimensionsPanel( settings ); - const value = useSelect( - ( select ) => - select( blockEditorStore ).getBlockAttributes( clientId )?.style, + const { value, align } = useSelect( + ( select ) => { + const blockAttributes = + select( blockEditorStore ).getBlockAttributes( clientId ); + + return { + value: blockAttributes?.style, + align: blockAttributes?.align, + }; + }, [ clientId ] ); + const [ visualizedProperty, setVisualizedProperty ] = useVisualizer(); const onChange = ( newStyle ) => { setAttributes( { @@ -99,6 +107,14 @@ export function DimensionsPanel( { clientId, name, setAttributes, settings } ) { ...defaultSpacingControls, }; + /** + * Alignments are needed for the child layout control. + */ + const supportedAlignments = getBlockSupport( name, 'align' ); + const onChangeAlignment = ( newAlign ) => { + setAttributes( { align: newAlign } ); + }; + return ( <> Date: Wed, 21 Feb 2024 16:10:41 +1100 Subject: [PATCH 04/14] Fix default width for flow children --- .../src/components/child-layout-control/index.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/block-editor/src/components/child-layout-control/index.js b/packages/block-editor/src/components/child-layout-control/index.js index b7526ce92f69e..0270fe50cd26a 100644 --- a/packages/block-editor/src/components/child-layout-control/index.js +++ b/packages/block-editor/src/components/child-layout-control/index.js @@ -200,8 +200,10 @@ export default function ChildLayoutControl( { selectedValue = 'fixedNoShrink'; } else if ( selfAlign === 'fit' ) { selectedValue = 'fit'; - } else { + } else if ( parentLayoutType === 'constrained' ) { selectedValue = 'content'; + } else { + selectedValue = 'fill'; } } else if ( parentLayoutType === 'flex' && @@ -256,10 +258,10 @@ export default function ChildLayoutControl( { ...childLayout, [ widthProp ]: key, } ); - onChangeAlignment( null ); + onChangeAlignment( undefined ); } else { onChange( { [ widthProp ]: key } ); - onChangeAlignment( null ); + onChangeAlignment( undefined ); } } else if ( parentLayoutType === 'flex' ) { onChange( { From 8bef78520e38ecc4be7dd577399e9899234e3523 Mon Sep 17 00:00:00 2001 From: tellthemachines Date: Thu, 22 Feb 2024 13:37:38 +1100 Subject: [PATCH 05/14] Remove legacy attribs and ensure correct output. --- .../components/child-layout-control/index.js | 32 +++++++++++++++---- .../block-editor/src/hooks/layout-child.js | 12 ++++--- 2 files changed, 33 insertions(+), 11 deletions(-) diff --git a/packages/block-editor/src/components/child-layout-control/index.js b/packages/block-editor/src/components/child-layout-control/index.js index 0270fe50cd26a..39625da4c0331 100644 --- a/packages/block-editor/src/components/child-layout-control/index.js +++ b/packages/block-editor/src/components/child-layout-control/index.js @@ -192,9 +192,15 @@ export default function ChildLayoutControl( { let selectedValue; if ( isFlowOrConstrained ) { // Replace "full" with "fill" for full width alignments. - if ( currentAlignment === 'full' ) { + if ( + currentAlignment === 'full' && + parentLayoutType === 'constrained' + ) { selectedValue = 'fill'; - } else if ( currentAlignment === 'wide' ) { + } else if ( + currentAlignment === 'wide' && + parentLayoutType === 'constrained' + ) { selectedValue = 'wide'; } else if ( selfAlign === 'fixedNoShrink' ) { selectedValue = 'fixedNoShrink'; @@ -248,10 +254,17 @@ export default function ChildLayoutControl( { const { key } = selectedItem; if ( isFlowOrConstrained ) { if ( key === 'fill' ) { - onChange( { [ widthProp ]: key } ); - onChangeAlignment( 'full' ); + onChange( { ...childLayout, [ widthProp ]: key } ); + /** + * Fill exists for both flow and constrained layouts but + * should only change alignment for constrained layouts. + * "fill" in flow layout is the default state of its children. + */ + if ( parentLayoutType === 'constrained' ) { + onChangeAlignment( 'full' ); + } } else if ( key === 'wide' ) { - onChange( { [ widthProp ]: key } ); + onChange( { ...childLayout, [ widthProp ]: key } ); onChangeAlignment( 'wide' ); } else if ( key === 'fixedNoShrink' ) { onChange( { @@ -260,21 +273,28 @@ export default function ChildLayoutControl( { } ); onChangeAlignment( undefined ); } else { - onChange( { [ widthProp ]: key } ); + onChange( { ...childLayout, [ widthProp ]: key } ); onChangeAlignment( undefined ); } } else if ( parentLayoutType === 'flex' ) { + // if the layout is horizontal, reset any flexSize when changing width. + const resetFlexSize = + orientation !== 'vertical' ? undefined : flexSize; onChange( { ...childLayout, [ widthProp ]: key, + flexSize: resetFlexSize, } ); } }; const onChangeHeight = ( newHeight ) => { + // If the layout is vertical, reset any flexSize when changing height. + const resetFlexSize = orientation === 'vertical' ? undefined : flexSize; onChange( { ...childLayout, [ heightProp ]: newHeight.selectedItem.key, + flexSize: resetFlexSize, } ); }; diff --git a/packages/block-editor/src/hooks/layout-child.js b/packages/block-editor/src/hooks/layout-child.js index 4694ab2c2a2e1..827bd8485ba6f 100644 --- a/packages/block-editor/src/hooks/layout-child.js +++ b/packages/block-editor/src/hooks/layout-child.js @@ -47,15 +47,13 @@ function useBlockPropsChildLayoutStyles( { style } ) { let css = ''; if ( shouldRenderChildLayoutStyles ) { + // Flex size should still be output for back compat. if ( selfStretch === 'fixed' && flexSize ) { css = `${ selector } { flex-basis: ${ flexSize }; box-sizing: border-box; }`; - } else if ( selfStretch === 'fill' ) { - css = `${ selector } { - flex-grow: 1; - }`; + // Grid type styles. } else if ( columnSpan ) { css = `${ selector } { grid-column: span ${ columnSpan }; @@ -150,10 +148,14 @@ function useBlockPropsChildLayoutStyles( { style } ) { css += `${ selector } { height: fit-content; }`; - } else if ( layout[ heightProp ] === 'fixedNoShrink' ) { + } else if ( layout[ heightProp ] === 'fixedNoShrink' && height ) { css += `${ selector } { height: ${ height }; }`; + } else if ( layout[ heightProp ] === 'fixed' && height ) { + css += `${ selector } { + max-height: ${ height }; + }`; } } /** From 3112204bb337da4bae4c68f6dc3bd71c6cfb4636 Mon Sep 17 00:00:00 2001 From: tellthemachines Date: Thu, 22 Feb 2024 15:40:25 +1100 Subject: [PATCH 06/14] Implement front end styles --- lib/block-supports/layout.php | 61 ++++++++++++ .../components/child-layout-control/index.js | 18 +++- .../block-editor/src/hooks/layout-child.js | 99 +++++++------------ 3 files changed, 114 insertions(+), 64 deletions(-) diff --git a/lib/block-supports/layout.php b/lib/block-supports/layout.php index 48cb206fd7894..66e731b76599a 100644 --- a/lib/block-supports/layout.php +++ b/lib/block-supports/layout.php @@ -573,7 +573,22 @@ function gutenberg_render_layout_support_flag( $block_content, $block ) { $child_layout_styles = array(); $self_stretch = isset( $block['attrs']['style']['layout']['selfStretch'] ) ? $block['attrs']['style']['layout']['selfStretch'] : null; + $self_align = isset( $block['attrs']['style']['layout']['selfAlign'] ) ? $block['attrs']['style']['layout']['selfAlign'] : null; + $height = isset( $block['attrs']['style']['layout']['height'] ) ? $block['attrs']['style']['layout']['height'] : null; + $width = isset( $block['attrs']['style']['layout']['width'] ) ? $block['attrs']['style']['layout']['width'] : null; + + $parent_layout_type = 'default'; + if ( isset( $block['parentLayout']['type'] ) ) { + $parent_layout_type = $block['parentLayout']['type']; + } elseif ( isset( $block['parentLayout']['default']['type'] ) ) { + $parent_layout_type = $block['parentLayout']['default']['type']; + } + + // Orientation is only used for flex layouts so its default is horizontal. + $parent_orientation = isset( $block['parentLayout']['orientation'] ) ? $block['parentLayout']['orientation'] : 'horizontal'; + $vertical_parent_layout = in_array( $parent_layout_type, array( 'constrained', 'default' ), true ) || ( 'flex' === $parent_layout_type && 'vertical' === $parent_orientation ); + // Support for legacy flexSize value. if ( 'fixed' === $self_stretch && isset( $block['attrs']['style']['layout']['flexSize'] ) ) { $child_layout_declarations['flex-basis'] = $block['attrs']['style']['layout']['flexSize']; $child_layout_declarations['box-sizing'] = 'border-box'; @@ -581,6 +596,49 @@ function gutenberg_render_layout_support_flag( $block_content, $block ) { $child_layout_declarations['flex-grow'] = '1'; } + if ( $vertical_parent_layout ) { + // Width styles. + if ( 'fixed' === $self_align && $width ) { + $child_layout_declarations['max-width'] = $width; + } elseif ( 'fixedNoShrink' === $self_align && $width ) { + $child_layout_declarations['width'] = $width; + } elseif ( 'fill' === $self_align ) { + $child_layout_declarations['align-self'] = 'stretch'; + } elseif ( 'fit' === $self_align ) { + $child_layout_declarations['width'] = 'fit-content'; + } + // Height styles. + if ( 'fixed' === $self_stretch && $height ) { + $child_layout_declarations['max-height'] = $height; + $child_layout_declarations['flex-basis'] = $height; + } elseif ( 'fixedNoShrink' === $self_stretch && $height ) { + $child_layout_declarations['height'] = $height; + $child_layout_declarations['flex-shrink'] = '0'; + $child_layout_declarations['flex-basis'] = $height; + } elseif ( 'fill' === $self_stretch ) { + $child_layout_declarations['flex-grow'] = '1'; + } + } elseif ( 'grid' !== $parent_layout_type ) { + // Width styles. + if ( 'fixed' === $self_stretch && $width ) { + $child_layout_declarations['flex-basis'] = $width; + } elseif ( 'fixedNoShrink' === $self_stretch && $width ) { + $child_layout_declarations['flex-shrink'] = '0'; + $child_layout_declarations['flex-basis'] = $width; + } elseif ( 'fill' === $self_stretch ) { + $child_layout_declarations['flex-grow'] = '1'; + } + // Height styles. + if ( 'fixed' === $self_align && $height ) { + $child_layout_declarations['max-height'] = $height; + } elseif ( 'fixedNoShrink' === $self_align && $height ) { + $child_layout_declarations['height'] = $height; + } elseif ( 'fill' === $self_align ) { + $child_layout_declarations['align-self'] = 'stretch'; + } + } + + // Grid specific styles. if ( isset( $block['attrs']['style']['layout']['columnSpan'] ) ) { $column_span = $block['attrs']['style']['layout']['columnSpan']; $child_layout_declarations['grid-column'] = "span $column_span"; @@ -589,6 +647,7 @@ function gutenberg_render_layout_support_flag( $block_content, $block ) { $row_span = $block['attrs']['style']['layout']['rowSpan']; $child_layout_declarations['grid-row'] = "span $row_span"; } + $child_layout_styles[] = array( 'selector' => ".$container_content_class", 'declarations' => $child_layout_declarations, @@ -902,6 +961,8 @@ function ( $parsed_block, $source_block, $parent_block ) { */ if ( $parent_block && isset( $parent_block->parsed_block['attrs']['layout'] ) ) { $parsed_block['parentLayout'] = $parent_block->parsed_block['attrs']['layout']; + } elseif ( $parent_block && isset( $parent_block->block_type->supports['layout'] ) ) { + $parsed_block['parentLayout'] = $parent_block->block_type->supports['layout']; } return $parsed_block; }, diff --git a/packages/block-editor/src/components/child-layout-control/index.js b/packages/block-editor/src/components/child-layout-control/index.js index 39625da4c0331..bfa7d6510c0c6 100644 --- a/packages/block-editor/src/components/child-layout-control/index.js +++ b/packages/block-editor/src/components/child-layout-control/index.js @@ -299,10 +299,24 @@ export default function ChildLayoutControl( { }; useEffect( () => { - if ( selfStretch === 'fixed' && ! flexSize ) { + if ( + ( childLayout[ heightProp ] === 'fixed' || + childLayout[ heightProp ] === 'fixedNoShrink' ) && + ! height + ) { + onChange( { + ...childLayout, + [ heightProp ]: undefined, + } ); + } + if ( + ( childLayout[ widthProp ] === 'fixed' || + childLayout[ widthProp ] === 'fixedNoShrink' ) && + ! width + ) { onChange( { ...childLayout, - selfStretch: 'fit', + [ widthProp ]: undefined, } ); } }, [] ); diff --git a/packages/block-editor/src/hooks/layout-child.js b/packages/block-editor/src/hooks/layout-child.js index 827bd8485ba6f..d09655608312a 100644 --- a/packages/block-editor/src/hooks/layout-child.js +++ b/packages/block-editor/src/hooks/layout-child.js @@ -17,8 +17,15 @@ function useBlockPropsChildLayoutStyles( { style } ) { return ! select( blockEditorStore ).getSettings().disableLayoutStyles; } ); const layout = style?.layout ?? {}; - const { selfStretch, flexSize, columnSpan, rowSpan, height, width } = - layout; + const { + selfStretch, + selfAlign, + flexSize, + columnSpan, + rowSpan, + height, + width, + } = layout; const parentLayout = useLayout() || {}; const { columnCount, @@ -31,19 +38,11 @@ function useBlockPropsChildLayoutStyles( { style } ) { const id = useInstanceId( useBlockPropsChildLayoutStyles ); const selector = `.wp-container-content-${ id }`; - const isFlowOrConstrained = + const isVerticalLayout = parentLayout.type === 'constrained' || parentLayout.type === 'default' || - parentLayout.type === undefined; - - const widthProp = - isFlowOrConstrained || orientation === 'vertical' - ? 'selfAlign' - : 'selfStretch'; - const heightProp = - isFlowOrConstrained || orientation === 'vertical' - ? 'selfStretch' - : 'selfAlign'; + parentLayout.type === undefined || + orientation === 'vertical'; let css = ''; if ( shouldRenderChildLayoutStyles ) { @@ -59,100 +58,76 @@ function useBlockPropsChildLayoutStyles( { style } ) { grid-column: span ${ columnSpan }; }`; } - if ( isFlowOrConstrained || orientation === 'vertical' ) { - // set width - if ( layout[ widthProp ] === 'fixed' && width ) { + // All vertical layout types have the same styles. + if ( isVerticalLayout ) { + if ( selfAlign === 'fixed' && width ) { css += `${ selector } { max-width: ${ width }; }`; - } else if ( layout[ widthProp ] === 'fixedNoShrink' && width ) { + } else if ( selfAlign === 'fixedNoShrink' && width ) { css += `${ selector } { width: ${ width }; }`; - } else if ( layout[ widthProp ] === 'fill' ) { + } else if ( selfAlign === 'fill' ) { + /** + * This style is only needed for flex layouts because + * constrained children have alignment set and flow + * children are 100% width by default. + */ css += `${ selector } { align-self: stretch; }`; - } else if ( layout[ widthProp ] === 'fit' ) { + } else if ( selfAlign === 'fit' ) { css += `${ selector } { width: fit-content; }`; } - // set height - if ( layout[ heightProp ] === 'fixed' && height ) { + if ( selfStretch === 'fixed' && height ) { + // Max-height is needed for flow and constrained children. css += `${ selector } { max-height: ${ height }; - flex-grow: 0; - flex-shrink: 1; flex-basis: ${ height }; }`; - } else if ( layout[ heightProp ] === 'fixedNoShrink' && height ) { + } else if ( selfStretch === 'fixedNoShrink' && height ) { + // Height is needed for flow and constrained children. css += `${ selector } { height: ${ height }; flex-shrink: 0; - flex-grow: 0; - flex-basis: auto; + flex-basis: ${ height }; }`; - } else if ( layout[ heightProp ] === 'fill' ) { + } else if ( selfStretch === 'fill' ) { css += `${ selector } { flex-grow: 1; - flex-shrink: 1; - }`; - } else if ( layout[ heightProp ] === 'fit' ) { - css += `${ selector } { - flex-grow: 0; - flex-shrink: 0; - flex-basis: auto; - height: auto; }`; } + // Everything else that isn't a grid is a horizontal layout. } else if ( parentLayoutType !== 'grid' ) { - // set width - if ( layout[ widthProp ] === 'fixed' && width ) { + if ( selfStretch === 'fixed' && width ) { css += `${ selector } { - max-width: ${ width }; - flex-grow: 0; - flex-shrink: 1; flex-basis: ${ width }; }`; - } else if ( layout[ widthProp ] === 'fixedNoShrink' && width ) { + } else if ( selfStretch === 'fixedNoShrink' && width ) { css += `${ selector } { - width: ${ width }; flex-shrink: 0; - flex-grow: 0; - flex-basis: auto; + flex-basis: ${ width }; }`; - } else if ( layout[ widthProp ] === 'fill' ) { + } else if ( selfStretch === 'fill' ) { css += `${ selector } { flex-grow: 1; - flex-shrink: 1; - flex-basis: 100%; - }`; - } else if ( layout[ widthProp ] === 'fit' ) { - css += `${ selector } { - flex-grow: 0; - flex-shrink: 0; - flex-basis: auto; - width: fit-content; }`; } - // set height - if ( layout[ heightProp ] === 'fill' ) { + if ( selfAlign === 'fill' ) { css += `${ selector } { align-self: stretch; }`; - } else if ( layout[ heightProp ] === 'fit' ) { - css += `${ selector } { - height: fit-content; - }`; - } else if ( layout[ heightProp ] === 'fixedNoShrink' && height ) { + } else if ( selfAlign === 'fixedNoShrink' && height ) { css += `${ selector } { height: ${ height }; }`; - } else if ( layout[ heightProp ] === 'fixed' && height ) { + } else if ( selfAlign === 'fixed' && height ) { css += `${ selector } { max-height: ${ height }; }`; From cacc45f56e72c1e16f187fd409429ca76409ced2 Mon Sep 17 00:00:00 2001 From: tellthemachines Date: Fri, 23 Feb 2024 17:01:20 +1100 Subject: [PATCH 07/14] Address feedback --- lib/block-supports/layout.php | 20 +++++++++---------- .../block-editor/src/hooks/layout-child.js | 6 +++--- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/lib/block-supports/layout.php b/lib/block-supports/layout.php index 66e731b76599a..279fcb2b3670d 100644 --- a/lib/block-supports/layout.php +++ b/lib/block-supports/layout.php @@ -572,10 +572,10 @@ function gutenberg_render_layout_support_flag( $block_content, $block ) { $child_layout_declarations = array(); $child_layout_styles = array(); - $self_stretch = isset( $block['attrs']['style']['layout']['selfStretch'] ) ? $block['attrs']['style']['layout']['selfStretch'] : null; - $self_align = isset( $block['attrs']['style']['layout']['selfAlign'] ) ? $block['attrs']['style']['layout']['selfAlign'] : null; - $height = isset( $block['attrs']['style']['layout']['height'] ) ? $block['attrs']['style']['layout']['height'] : null; - $width = isset( $block['attrs']['style']['layout']['width'] ) ? $block['attrs']['style']['layout']['width'] : null; + $self_stretch = isset( $child_layout['selfStretch'] ) ? $child_layout['selfStretch'] : null; + $self_align = isset( $child_layout['selfAlign'] ) ? $child_layout['selfAlign'] : null; + $height = isset( $child_layout['height'] ) ? $child_layout['height'] : null; + $width = isset( $child_layout['width'] ) ? $child_layout['width'] : null; $parent_layout_type = 'default'; if ( isset( $block['parentLayout']['type'] ) ) { @@ -589,8 +589,8 @@ function gutenberg_render_layout_support_flag( $block_content, $block ) { $vertical_parent_layout = in_array( $parent_layout_type, array( 'constrained', 'default' ), true ) || ( 'flex' === $parent_layout_type && 'vertical' === $parent_orientation ); // Support for legacy flexSize value. - if ( 'fixed' === $self_stretch && isset( $block['attrs']['style']['layout']['flexSize'] ) ) { - $child_layout_declarations['flex-basis'] = $block['attrs']['style']['layout']['flexSize']; + if ( 'fixed' === $self_stretch && isset( $child_layout['flexSize'] ) ) { + $child_layout_declarations['flex-basis'] = $child_layout['flexSize']; $child_layout_declarations['box-sizing'] = 'border-box'; } elseif ( 'fill' === $self_stretch ) { $child_layout_declarations['flex-grow'] = '1'; @@ -639,12 +639,12 @@ function gutenberg_render_layout_support_flag( $block_content, $block ) { } // Grid specific styles. - if ( isset( $block['attrs']['style']['layout']['columnSpan'] ) ) { - $column_span = $block['attrs']['style']['layout']['columnSpan']; + if ( isset( $child_layout['columnSpan'] ) ) { + $column_span = $child_layout['columnSpan']; $child_layout_declarations['grid-column'] = "span $column_span"; } - if ( isset( $block['attrs']['style']['layout']['rowSpan'] ) ) { - $row_span = $block['attrs']['style']['layout']['rowSpan']; + if ( isset( $child_layout['rowSpan'] ) ) { + $row_span = $child_layout['rowSpan']; $child_layout_declarations['grid-row'] = "span $row_span"; } diff --git a/packages/block-editor/src/hooks/layout-child.js b/packages/block-editor/src/hooks/layout-child.js index d09655608312a..ebb011803e42f 100644 --- a/packages/block-editor/src/hooks/layout-child.js +++ b/packages/block-editor/src/hooks/layout-child.js @@ -39,9 +39,9 @@ function useBlockPropsChildLayoutStyles( { style } ) { const selector = `.wp-container-content-${ id }`; const isVerticalLayout = - parentLayout.type === 'constrained' || - parentLayout.type === 'default' || - parentLayout.type === undefined || + parentLayoutType === 'constrained' || + parentLayoutType === 'default' || + parentLayoutType === undefined || orientation === 'vertical'; let css = ''; From 083ce0618741c94e85c7ce82466c364635bb0e87 Mon Sep 17 00:00:00 2001 From: tellthemachines Date: Fri, 23 Feb 2024 17:49:31 +1100 Subject: [PATCH 08/14] Fix issue where align support is boolean. --- .../components/child-layout-control/index.js | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/child-layout-control/index.js b/packages/block-editor/src/components/child-layout-control/index.js index bfa7d6510c0c6..72695d0505767 100644 --- a/packages/block-editor/src/components/child-layout-control/index.js +++ b/packages/block-editor/src/components/child-layout-control/index.js @@ -40,10 +40,26 @@ export default function ChildLayoutControl( { const { current: currentAlignment, - supported: supportedAlignments, + supported, onChangeAlignment, } = alignments || {}; + /** + * If supported alignments is true, it means that the block supports + * both wide and full alignments. If false, it supports neither. + */ + let supportedAlignments; + switch ( supported ) { + case true: + supportedAlignments = [ 'wide', 'full' ]; + break; + case false: + supportedAlignments = []; + break; + default: + supportedAlignments = supported; + } + const { orientation = 'horizontal', type: parentType, From d8130bd549f525a31100f7b0c7441f2028f99f5d Mon Sep 17 00:00:00 2001 From: tellthemachines Date: Mon, 26 Feb 2024 14:23:21 +1100 Subject: [PATCH 09/14] rename var --- lib/block-supports/layout.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/block-supports/layout.php b/lib/block-supports/layout.php index 279fcb2b3670d..8895cb60a4f37 100644 --- a/lib/block-supports/layout.php +++ b/lib/block-supports/layout.php @@ -585,8 +585,8 @@ function gutenberg_render_layout_support_flag( $block_content, $block ) { } // Orientation is only used for flex layouts so its default is horizontal. - $parent_orientation = isset( $block['parentLayout']['orientation'] ) ? $block['parentLayout']['orientation'] : 'horizontal'; - $vertical_parent_layout = in_array( $parent_layout_type, array( 'constrained', 'default' ), true ) || ( 'flex' === $parent_layout_type && 'vertical' === $parent_orientation ); + $parent_orientation = isset( $block['parentLayout']['orientation'] ) ? $block['parentLayout']['orientation'] : 'horizontal'; + $has_vertical_parent_layout = in_array( $parent_layout_type, array( 'constrained', 'default' ), true ) || ( 'flex' === $parent_layout_type && 'vertical' === $parent_orientation ); // Support for legacy flexSize value. if ( 'fixed' === $self_stretch && isset( $child_layout['flexSize'] ) ) { @@ -596,7 +596,7 @@ function gutenberg_render_layout_support_flag( $block_content, $block ) { $child_layout_declarations['flex-grow'] = '1'; } - if ( $vertical_parent_layout ) { + if ( $has_vertical_parent_layout ) { // Width styles. if ( 'fixed' === $self_align && $width ) { $child_layout_declarations['max-width'] = $width; From 22382a8b7c4a8cae65777c2d9838cb0518bf8ebd Mon Sep 17 00:00:00 2001 From: tellthemachines Date: Mon, 26 Feb 2024 14:53:09 +1100 Subject: [PATCH 10/14] Add Max width control for vertical layouts. --- .../src/components/child-layout-control/index.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/packages/block-editor/src/components/child-layout-control/index.js b/packages/block-editor/src/components/child-layout-control/index.js index 72695d0505767..4da6ce7d4422d 100644 --- a/packages/block-editor/src/components/child-layout-control/index.js +++ b/packages/block-editor/src/components/child-layout-control/index.js @@ -122,6 +122,11 @@ export default function ChildLayoutControl( { key: 'fixedNoShrink', value: 'fixedNoShrink', name: __( 'Fixed' ), + }, + { + key: 'fixed', + value: 'fixed', + name: __( 'Max Width' ), } ); } else if ( @@ -143,6 +148,11 @@ export default function ChildLayoutControl( { key: 'fixedNoShrink', value: 'fixedNoShrink', name: __( 'Fixed' ), + }, + { + key: 'fixed', + value: 'fixed', + name: __( 'Max Width' ), } ); } else if ( parentLayoutType === 'flex' && orientation === 'horizontal' ) { @@ -220,6 +230,8 @@ export default function ChildLayoutControl( { selectedValue = 'wide'; } else if ( selfAlign === 'fixedNoShrink' ) { selectedValue = 'fixedNoShrink'; + } else if ( selfAlign === 'fixed' ) { + selectedValue = 'fixed'; } else if ( selfAlign === 'fit' ) { selectedValue = 'fit'; } else if ( parentLayoutType === 'constrained' ) { @@ -231,6 +243,7 @@ export default function ChildLayoutControl( { parentLayoutType === 'flex' && orientation === 'vertical' ) { + // If the parent layout is justified stretch, children should be fill by default. const defaultSelfAlign = justifyContent === 'stretch' ? 'fill' : 'fit'; selectedValue = selfAlign || defaultSelfAlign; From d14e3eb8686fd8a891d22e6853ac90f0d3b5e39b Mon Sep 17 00:00:00 2001 From: tellthemachines Date: Mon, 26 Feb 2024 16:19:29 +1100 Subject: [PATCH 11/14] =?UTF-8?q?Add=20some=20!importants=20=F0=9F=99=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/block-supports/layout.php | 10 +++++++++- packages/block-editor/src/hooks/layout-child.js | 15 ++++++++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/lib/block-supports/layout.php b/lib/block-supports/layout.php index 8895cb60a4f37..92c143bd36053 100644 --- a/lib/block-supports/layout.php +++ b/lib/block-supports/layout.php @@ -599,9 +599,17 @@ function gutenberg_render_layout_support_flag( $block_content, $block ) { if ( $has_vertical_parent_layout ) { // Width styles. if ( 'fixed' === $self_align && $width ) { - $child_layout_declarations['max-width'] = $width; + /** + * !important is a (hopefully) temporary override for + * the constrained layout styles, the specificity of + * which should be lowered soon. + */ + $child_layout_declarations['max-width'] = "$width !important"; } elseif ( 'fixedNoShrink' === $self_align && $width ) { $child_layout_declarations['width'] = $width; + if ( 'constrained' === $parent_layout_type ) { + $child_layout_declarations['max-width'] = 'none !important'; + } } elseif ( 'fill' === $self_align ) { $child_layout_declarations['align-self'] = 'stretch'; } elseif ( 'fit' === $self_align ) { diff --git a/packages/block-editor/src/hooks/layout-child.js b/packages/block-editor/src/hooks/layout-child.js index ebb011803e42f..e43ff9e5ac4bd 100644 --- a/packages/block-editor/src/hooks/layout-child.js +++ b/packages/block-editor/src/hooks/layout-child.js @@ -61,13 +61,26 @@ function useBlockPropsChildLayoutStyles( { style } ) { // All vertical layout types have the same styles. if ( isVerticalLayout ) { if ( selfAlign === 'fixed' && width ) { + /** + * Once layout rule specificity is lowered, + * the !important can be removed. + */ css += `${ selector } { - max-width: ${ width }; + max-width: ${ width } !important; }`; } else if ( selfAlign === 'fixedNoShrink' && width ) { css += `${ selector } { width: ${ width }; }`; + /** + * A max-width reset is needed to override constrained + * layout styles. + */ + if ( parentLayoutType === 'constrained' ) { + css += `${ selector } { + max-width: none !important; + }`; + } } else if ( selfAlign === 'fill' ) { /** * This style is only needed for flex layouts because From 9e455bac5027015bc332364955e8c2f06a4cc733 Mon Sep 17 00:00:00 2001 From: tellthemachines Date: Tue, 27 Feb 2024 15:48:19 +1100 Subject: [PATCH 12/14] Make resets work properly. --- .../components/child-layout-control/index.js | 79 +++++++++++++++++-- .../global-styles/dimensions-panel.js | 44 +++-------- 2 files changed, 80 insertions(+), 43 deletions(-) diff --git a/packages/block-editor/src/components/child-layout-control/index.js b/packages/block-editor/src/components/child-layout-control/index.js index 4da6ce7d4422d..c442c73d55722 100644 --- a/packages/block-editor/src/components/child-layout-control/index.js +++ b/packages/block-editor/src/components/child-layout-control/index.js @@ -7,6 +7,7 @@ import { __experimentalUnitControl as UnitControl, __experimentalInputControl as InputControl, __experimentalHStack as HStack, + __experimentalToolsPanelItem as ToolsPanelItem, } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; import { useEffect } from '@wordpress/element'; @@ -14,12 +15,14 @@ import { useEffect } from '@wordpress/element'; /** * Form to edit the child layout value. * - * @param {Object} props Props. - * @param {Object} props.value The child layout value. - * @param {Function} props.onChange Function to update the child layout value. - * @param {Object} props.parentLayout The parent layout value. + * @param {Object} props Props. + * @param {Object} props.value The child layout value. + * @param {Function} props.onChange Function to update the child layout value. + * @param {Object} props.parentLayout The parent layout value. * @param {Object} props.alignments * + * @param {boolean} props.isShownByDefault + * @param {string} props.panelId * @return {Element} child layout edit element. */ export default function ChildLayoutControl( { @@ -27,6 +30,8 @@ export default function ChildLayoutControl( { onChange, parentLayout, alignments, + isShownByDefault, + panelId, } ) { const { selfStretch, @@ -36,7 +41,7 @@ export default function ChildLayoutControl( { selfAlign, height, width, - } = childLayout; + } = childLayout || {}; const { current: currentAlignment, @@ -84,6 +89,41 @@ export default function ChildLayoutControl( { ? 'selfStretch' : 'selfAlign'; + //ToolsPanelItem-specific functions. + const resetWidthValue = () => { + // If alignment has been set via the width control, unset it. + if ( + ( selfAlign === 'wide' && currentAlignment === 'wide' ) || + ( selfAlign === 'fill' && currentAlignment === 'full' ) + ) { + onChangeAlignment( undefined ); + } + onChange( { + selfStretch: undefined, + flexSize: undefined, + selfAlign: undefined, + width: undefined, + } ); + }; + const resetHeightValue = () => { + onChange( { + selfStretch: undefined, + flexSize: undefined, + selfAlign: undefined, + height: undefined, + } ); + }; + const resetGridSpanValue = () => { + onChange( { + columnSpan: undefined, + rowSpan: undefined, + } ); + }; + const hasWidthValue = () => !! childLayout[ widthProp ]; + const hasHeightValue = () => !! childLayout[ heightProp ]; + const hasGridSpanValue = () => + !! ( childLayout.columnSpan || childLayout.rowSpan ); + const widthOptions = []; if ( parentLayoutType === 'constrained' ) { @@ -354,7 +394,15 @@ export default function ChildLayoutControl( { <> { parentLayoutType !== 'grid' && ( <> - + ) } - + ) } { parentLayoutType === 'grid' && ( - + { onChange( setImmutably( value, [ 'layout' ], newChildLayout ) ); }; - const resetChildLayoutValue = () => { - setChildLayout( { - selfStretch: undefined, - flexSize: undefined, - columnSpan: undefined, - rowSpan: undefined, - } ); - }; - const hasChildLayoutValue = () => !! value?.layout; - const resetAllFilter = useCallback( ( previousValue ) => { return { ...previousValue, @@ -422,6 +401,9 @@ export default function DimensionsPanel( { wideSize: undefined, selfStretch: undefined, flexSize: undefined, + selfAlign: undefined, + width: undefined, + height: undefined, columnSpan: undefined, rowSpan: undefined, } ), @@ -639,25 +621,17 @@ export default function DimensionsPanel( { ) } { showChildLayoutControl && ( - - - + /> ) } { showMinHeightControl && ( Date: Mon, 18 Mar 2024 15:42:02 +1100 Subject: [PATCH 13/14] Check if content and wide widths are defined in the theme --- .../components/child-layout-control/index.js | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/packages/block-editor/src/components/child-layout-control/index.js b/packages/block-editor/src/components/child-layout-control/index.js index 3b0913dde1704..608b09015baa5 100644 --- a/packages/block-editor/src/components/child-layout-control/index.js +++ b/packages/block-editor/src/components/child-layout-control/index.js @@ -52,7 +52,6 @@ export default function ChildLayoutControl( { supported, onChangeAlignment, } = alignments || {}; - /** * If supported alignments is true, it means that the block supports * both wide and full alignments. If false, it supports neither. @@ -76,6 +75,8 @@ export default function ChildLayoutControl( { justifyContent = 'left', verticalAlignment = 'center', alignWidth: parentAlignment = 'none', + contentSize, + wideSize, } = parentLayout ?? {}; const parentLayoutType = parentType || defaultParentType; @@ -137,12 +138,15 @@ export default function ChildLayoutControl( { const widthOptions = []; if ( parentLayoutType === 'constrained' ) { - widthOptions.push( { - key: 'content', - value: 'content', - name: __( 'Default' ), - } ); + if ( contentSize ) { + widthOptions.push( { + key: 'content', + value: 'content', + name: __( 'Default' ), + } ); + } if ( + wideSize && supportedAlignments?.includes( 'wide' ) && ( parentAlignment === 'wide' || parentAlignment === 'full' ) ) { @@ -152,9 +156,11 @@ export default function ChildLayoutControl( { name: __( 'Wide' ), } ); } + // If no contentSize is defined, fill should be the default. if ( - supportedAlignments?.includes( 'full' ) && - parentAlignment === 'full' + ( supportedAlignments?.includes( 'full' ) && + parentAlignment === 'full' ) || + ! contentSize ) { widthOptions.push( { key: 'fill', @@ -274,6 +280,7 @@ export default function ChildLayoutControl( { ) { selectedValue = 'fill'; } else if ( + wideSize && currentAlignment === 'wide' && parentLayoutType === 'constrained' ) { From 7d0e0ab5af1fb5d0c69918282274f3c6b2faf949 Mon Sep 17 00:00:00 2001 From: tellthemachines Date: Mon, 18 Mar 2024 16:49:02 +1100 Subject: [PATCH 14/14] In classic themes, show width and height only for flex children. --- .../global-styles/dimensions-panel.js | 31 +++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/components/global-styles/dimensions-panel.js b/packages/block-editor/src/components/global-styles/dimensions-panel.js index 7313308fdd5e7..d4907b6ce0d42 100644 --- a/packages/block-editor/src/components/global-styles/dimensions-panel.js +++ b/packages/block-editor/src/components/global-styles/dimensions-panel.js @@ -18,6 +18,7 @@ import { } from '@wordpress/components'; import { Icon, positionCenter, stretchWide } from '@wordpress/icons'; import { useCallback, Platform } from '@wordpress/element'; +import { useSelect } from '@wordpress/data'; /** * Internal dependencies @@ -29,6 +30,7 @@ import ChildLayoutControl from '../child-layout-control'; import AspectRatioTool from '../dimensions-tool/aspect-ratio-tool'; import { cleanEmptyObject } from '../../hooks/utils'; import { setImmutably } from '../../utils/object'; +import { store as blockEditorStore } from '../../store'; const AXIAL_SIDES = [ 'horizontal', 'vertical' ]; @@ -84,10 +86,35 @@ function useHasAspectRatio( settings ) { } function useHasChildLayout( settings ) { - const { allowSizingOnChildren = false } = settings?.parentLayout ?? {}; + const { themeSupportsLayout } = useSelect( ( select ) => { + const { getSettings } = select( blockEditorStore ); + return { + themeSupportsLayout: getSettings().supportsLayout, + }; + }, [] ); + + const { + allowSizingOnChildren = false, + type, + default: { type: defaultType = 'default' } = {}, + } = settings?.parentLayout ?? {}; + const layoutType = type || defaultType; + const isFlowOrConstrained = + layoutType === 'default' || layoutType === 'constrained'; const support = allowSizingOnChildren; - return !! settings?.layout && support; + + /* + * If the theme supports layout and parent block supports sizing on children, + * the child layout control is always shown. + * If the theme does not support layout, the child layout control is shown + * only if the parent layout is not flow or constrained. + */ + return ( + !! settings?.layout && + support && + ( themeSupportsLayout || ! isFlowOrConstrained ) + ); } function useHasSpacingPresets( settings ) {