From 2bded3aac3eb68836f9e5706ded2609d613bedb1 Mon Sep 17 00:00:00 2001 From: Daniel Richards Date: Tue, 16 May 2023 12:29:19 +0800 Subject: [PATCH] Synchronise inner block attribute updates to the parent pattern block - Use a BlockEdit filter to optionally wrap the setAttributes function when a partially synced pattern block exits - Merge inner block attributes updates into a pattern block `content` attribute - Batch the updates into one action` --- docs/reference-guides/core-blocks.md | 2 +- packages/block-library/src/pattern/block.json | 3 + packages/block-library/src/pattern/edit.js | 99 ++++++++++++++++++- 3 files changed, 101 insertions(+), 3 deletions(-) diff --git a/docs/reference-guides/core-blocks.md b/docs/reference-guides/core-blocks.md index 04710602d28f0..320a9814e1c6e 100644 --- a/docs/reference-guides/core-blocks.md +++ b/docs/reference-guides/core-blocks.md @@ -465,7 +465,7 @@ Show a block pattern. ([Source](https://github.com/WordPress/gutenberg/tree/trun - **Name:** core/pattern - **Category:** theme - **Supports:** ~~html~~, ~~inserter~~ -- **Attributes:** slug, syncStatus +- **Attributes:** content, slug, syncStatus ## Post Author diff --git a/packages/block-library/src/pattern/block.json b/packages/block-library/src/pattern/block.json index 82372fe168098..d4f0fe3c18f94 100644 --- a/packages/block-library/src/pattern/block.json +++ b/packages/block-library/src/pattern/block.json @@ -17,6 +17,9 @@ "syncStatus": { "type": [ "string", "boolean" ], "enum": [ "full", "partial" ] + }, + "content": { + "type": "object" } } } diff --git a/packages/block-library/src/pattern/edit.js b/packages/block-library/src/pattern/edit.js index c22536a59eb03..dd345d5208864 100644 --- a/packages/block-library/src/pattern/edit.js +++ b/packages/block-library/src/pattern/edit.js @@ -2,13 +2,17 @@ * WordPress dependencies */ import { cloneBlock } from '@wordpress/blocks'; -import { useSelect, useDispatch } from '@wordpress/data'; -import { useEffect } from '@wordpress/element'; +import { createHigherOrderComponent } from '@wordpress/compose'; +import { useSelect, useDispatch, useRegistry } from '@wordpress/data'; +import { useEffect, useCallback } from '@wordpress/element'; import { store as blockEditorStore, useBlockProps, useInnerBlocksProps, } from '@wordpress/block-editor'; +import { addFilter } from '@wordpress/hooks'; + +const EMPTY_OBJECT = {}; const PatternEdit = ( { attributes, clientId } ) => { const { slug, syncStatus } = attributes; @@ -81,3 +85,94 @@ const PatternEdit = ( { attributes, clientId } ) => { }; export default PatternEdit; + +/** + * Override the default edit UI to include layout controls + * + * @param {Function} BlockEdit Original component. + * + * @return {Function} Wrapped component. + */ +export const withChildContentAttributes = createHigherOrderComponent( + ( BlockEdit ) => ( props ) => { + const { name: blockName, clientId, setAttributes } = props; + + const registry = useRegistry(); + + const { patternClientId, patternSyncStatus, patternContent } = + useSelect( + ( select ) => { + const { getBlockParentsByBlockName, getBlockAttributes } = + select( blockEditorStore ); + + const patternBlockParents = getBlockParentsByBlockName( + clientId, + 'core/pattern' + ); + + const parentPatternClientId = patternBlockParents?.[ 0 ]; + + if ( ! parentPatternClientId ) { + return EMPTY_OBJECT; + } + + const { syncStatus, content } = getBlockAttributes( + parentPatternClientId + ); + + return { + patternClientId: parentPatternClientId, + patternSyncStatus: syncStatus, + patternContent: content, + }; + }, + [ clientId ] + ); + + const { updateBlockAttributes } = useDispatch( blockEditorStore ); + + if ( patternSyncStatus !== 'partial' ) { + return ; + } + + const setContentAttributes = useCallback( + ( newAttributes ) => { + registry.batch( () => { + // Sync any attribute updates to a partially synced pattern parent. + // todo + // - Only set `role: 'content' attributes. + // - Handle multiple blocks of the same type. + updateBlockAttributes( patternClientId, { + content: { + ...patternContent, + [ blockName ]: { + ...patternContent?.[ blockName ], + ...newAttributes, + }, + }, + } ); + setAttributes( newAttributes ); + } ); + }, + [ + blockName, + patternClientId, + patternContent, + registry, + setAttributes, + updateBlockAttributes, + ] + ); + + return ( + + ); + }, + 'withInspectorControls' +); + +addFilter( + 'editor.BlockEdit', + 'core/block-library/pattern/with-child-content-attributes', + withChildContentAttributes +);