From d53b542b50a9a9c56f2b1e7d1244165761155dd4 Mon Sep 17 00:00:00 2001 From: George Mamadashvili Date: Wed, 1 Nov 2023 15:19:13 +0400 Subject: [PATCH] Block Editor: Optimize layout style renderer subscription --- packages/block-editor/src/hooks/layout.js | 221 ++++++++++++---------- 1 file changed, 120 insertions(+), 101 deletions(-) diff --git a/packages/block-editor/src/hooks/layout.js b/packages/block-editor/src/hooks/layout.js index 068af349d467dc..260f81ed6bb883 100644 --- a/packages/block-editor/src/hooks/layout.js +++ b/packages/block-editor/src/hooks/layout.js @@ -345,6 +345,70 @@ export const withInspectorControls = createHigherOrderComponent( 'withInspectorControls' ); +function BlockListWithLayoutStyles( { block: BlockListBlock, props } ) { + const { name, attributes } = props; + const disableLayoutStyles = useSelect( ( select ) => { + const { getSettings } = select( blockEditorStore ); + return !! getSettings().disableLayoutStyles; + } ); + + const id = useInstanceId( BlockListBlock ); + const { layout } = attributes; + const { default: defaultBlockLayout } = + getBlockSupport( name, layoutBlockSupportKey ) || {}; + const usedLayout = + layout?.inherit || layout?.contentSize || layout?.wideSize + ? { ...layout, type: 'constrained' } + : layout || defaultBlockLayout || {}; + const layoutClasses = useLayoutClasses( attributes, name ); + + // Higher specificity to override defaults from theme.json. + const selector = `.wp-container-${ id }.wp-container-${ id }`; + const [ blockGapSupport ] = useSettings( 'spacing.blockGap' ); + const hasBlockGapSupport = blockGapSupport !== null; + + // Get CSS string for the current layout type. + // The CSS and `style` element is only output if it is not empty. + let css; + if ( ! disableLayoutStyles ) { + const fullLayoutType = getLayoutType( usedLayout?.type || 'default' ); + css = fullLayoutType?.getLayoutStyle?.( { + blockName: name, + selector, + layout: usedLayout, + style: attributes?.style, + hasBlockGapSupport, + } ); + } + + // Attach a `wp-container-` id-based class name as well as a layout class name such as `is-layout-flex`. + const layoutClassNames = classnames( + { + [ `wp-container-${ id }` ]: ! disableLayoutStyles && !! css, // Only attach a container class if there is generated CSS to be attached. + }, + layoutClasses + ); + + const { setStyleOverride, deleteStyleOverride } = unlock( + useDispatch( blockEditorStore ) + ); + + useEffect( () => { + if ( ! css ) return; + setStyleOverride( selector, { css } ); + return () => { + deleteStyleOverride( selector ); + }; + }, [ selector, css, setStyleOverride, deleteStyleOverride ] ); + + return ( + + ); +} + /** * Override the default block element to add the layout styles. * @@ -354,76 +418,63 @@ export const withInspectorControls = createHigherOrderComponent( */ export const withLayoutStyles = createHigherOrderComponent( ( BlockListBlock ) => ( props ) => { - const { name, attributes } = props; - const blockSupportsLayout = hasLayoutBlockSupport( name ); - const disableLayoutStyles = useSelect( ( select ) => { - const { getSettings } = select( blockEditorStore ); - return !! getSettings().disableLayoutStyles; - } ); - const shouldRenderLayoutStyles = - blockSupportsLayout && ! disableLayoutStyles; - const id = useInstanceId( BlockListBlock ); - const { layout } = attributes; - const { default: defaultBlockLayout } = - getBlockSupport( name, layoutBlockSupportKey ) || {}; - const usedLayout = - layout?.inherit || layout?.contentSize || layout?.wideSize - ? { ...layout, type: 'constrained' } - : layout || defaultBlockLayout || {}; - const layoutClasses = blockSupportsLayout - ? useLayoutClasses( attributes, name ) - : null; - // Higher specificity to override defaults from theme.json. - const selector = `.wp-container-${ id }.wp-container-${ id }`; - const [ blockGapSupport ] = useSettings( 'spacing.blockGap' ); - const hasBlockGapSupport = blockGapSupport !== null; - - // Get CSS string for the current layout type. - // The CSS and `style` element is only output if it is not empty. - let css; - if ( shouldRenderLayoutStyles ) { - const fullLayoutType = getLayoutType( - usedLayout?.type || 'default' - ); - css = fullLayoutType?.getLayoutStyle?.( { - blockName: name, - selector, - layout: usedLayout, - style: attributes?.style, - hasBlockGapSupport, - } ); + if ( ! hasLayoutBlockSupport( props.name ) ) { + return ; } - // Attach a `wp-container-` id-based class name as well as a layout class name such as `is-layout-flex`. - const layoutClassNames = classnames( - { - [ `wp-container-${ id }` ]: shouldRenderLayoutStyles && !! css, // Only attach a container class if there is generated CSS to be attached. - }, - layoutClasses - ); - - const { setStyleOverride, deleteStyleOverride } = unlock( - useDispatch( blockEditorStore ) - ); - - useEffect( () => { - if ( ! css ) return; - setStyleOverride( selector, { css } ); - return () => { - deleteStyleOverride( selector ); - }; - }, [ selector, css, setStyleOverride, deleteStyleOverride ] ); - return ( - ); }, 'withLayoutStyles' ); +function BlockListWithChildLayoutStyles( { block: BlockListBlock, props } ) { + const { style: { layout = {} } = {} } = props.attributes; + const { selfStretch, flexSize } = layout; + const disableLayoutStyles = useSelect( ( select ) => { + const { getSettings } = select( blockEditorStore ); + return !! getSettings().disableLayoutStyles; + } ); + + const id = useInstanceId( BlockListBlock ); + const selector = `.wp-container-content-${ id }`; + + let css = ''; + if ( selfStretch === 'fixed' && flexSize ) { + css += `${ selector } { + flex-basis: ${ flexSize }; + box-sizing: border-box; + }`; + } else if ( selfStretch === 'fill' ) { + css += `${ selector } { + flex-grow: 1; + }`; + } + + // Attach a `wp-container-content` id-based classname. + const className = classnames( props?.className, { + [ `wp-container-content-${ id }` ]: ! disableLayoutStyles && !! css, // Only attach a container class if there is generated CSS to be attached. + } ); + + const { setStyleOverride, deleteStyleOverride } = unlock( + useDispatch( blockEditorStore ) + ); + + useEffect( () => { + if ( ! css ) return; + setStyleOverride( selector, { css } ); + return () => { + deleteStyleOverride( selector ); + }; + }, [ selector, css, setStyleOverride, deleteStyleOverride ] ); + + return ; +} + /** * Override the default block element to add the child layout styles. * @@ -433,52 +484,20 @@ export const withLayoutStyles = createHigherOrderComponent( */ export const withChildLayoutStyles = createHigherOrderComponent( ( BlockListBlock ) => ( props ) => { - const { attributes } = props; - const { style: { layout = {} } = {} } = attributes; + const { style: { layout = {} } = {} } = props.attributes; const { selfStretch, flexSize } = layout; const hasChildLayout = selfStretch || flexSize; - const disableLayoutStyles = useSelect( ( select ) => { - const { getSettings } = select( blockEditorStore ); - return !! getSettings().disableLayoutStyles; - } ); - const shouldRenderChildLayoutStyles = - hasChildLayout && ! disableLayoutStyles; - - const id = useInstanceId( BlockListBlock ); - const selector = `.wp-container-content-${ id }`; - let css = ''; - - if ( selfStretch === 'fixed' && flexSize ) { - css += `${ selector } { - flex-basis: ${ flexSize }; - box-sizing: border-box; - }`; - } else if ( selfStretch === 'fill' ) { - css += `${ selector } { - flex-grow: 1; - }`; + if ( ! hasChildLayout ) { + return ; } - // Attach a `wp-container-content` id-based classname. - const className = classnames( props?.className, { - [ `wp-container-content-${ id }` ]: - shouldRenderChildLayoutStyles && !! css, // Only attach a container class if there is generated CSS to be attached. - } ); - - const { setStyleOverride, deleteStyleOverride } = unlock( - useDispatch( blockEditorStore ) + return ( + ); - - useEffect( () => { - if ( ! css ) return; - setStyleOverride( selector, { css } ); - return () => { - deleteStyleOverride( selector ); - }; - }, [ selector, css, setStyleOverride, deleteStyleOverride ] ); - - return ; }, 'withChildLayoutStyles' );