diff --git a/docs/reference-guides/core-blocks.md b/docs/reference-guides/core-blocks.md index e5d20bb7b1edd..04710602d28f0 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 +- **Attributes:** slug, syncStatus ## Post Author diff --git a/lib/experimental/editor-settings.php b/lib/experimental/editor-settings.php index c7dd5850a505c..8d4046530fbc9 100644 --- a/lib/experimental/editor-settings.php +++ b/lib/experimental/editor-settings.php @@ -101,6 +101,9 @@ function gutenberg_enable_experiments() { if ( $gutenberg_experiments && array_key_exists( 'gutenberg-theme-previews', $gutenberg_experiments ) ) { wp_add_inline_script( 'wp-block-editor', 'window.__experimentalEnableThemePreviews = true', 'before' ); } + if ( $gutenberg_experiments && array_key_exists( 'gutenberg-pattern-enhancements', $gutenberg_experiments ) ) { + wp_add_inline_script( 'wp-block-editor', 'window.__experimentalEnablePatternEnhancements = true', 'before' ); + } } diff --git a/lib/experiments-page.php b/lib/experiments-page.php index ee51f5bea49f9..e39a9dbefb9c1 100644 --- a/lib/experiments-page.php +++ b/lib/experiments-page.php @@ -125,6 +125,18 @@ function gutenberg_initialize_experiments_settings() { ) ); + add_settings_field( + 'gutenberg-pattern-enhancements', + __( 'Pattern enhancements', 'gutenberg' ), + 'gutenberg_display_experiment_field', + 'gutenberg-experiments', + 'gutenberg_experiments_section', + array( + 'label' => __( 'Test the Pattern block enhancements', 'gutenberg' ), + 'id' => 'gutenberg-pattern-enhancements', + ) + ); + register_setting( 'gutenberg-experiments', 'gutenberg-experiments' diff --git a/packages/block-library/src/pattern/block.json b/packages/block-library/src/pattern/block.json index da023142403c8..82372fe168098 100644 --- a/packages/block-library/src/pattern/block.json +++ b/packages/block-library/src/pattern/block.json @@ -13,6 +13,10 @@ "attributes": { "slug": { "type": "string" + }, + "syncStatus": { + "type": [ "string", "boolean" ], + "enum": [ "full", "partial" ] } } } diff --git a/packages/block-library/src/pattern/edit.js b/packages/block-library/src/pattern/edit.js index be0b778eb4ae1..5072d577172b0 100644 --- a/packages/block-library/src/pattern/edit.js +++ b/packages/block-library/src/pattern/edit.js @@ -1,31 +1,41 @@ /** * WordPress dependencies */ +import { cloneBlock } from '@wordpress/blocks'; import { useSelect, useDispatch } from '@wordpress/data'; import { useEffect } from '@wordpress/element'; import { store as blockEditorStore, useBlockProps, + useInnerBlocksProps, } from '@wordpress/block-editor'; const PatternEdit = ( { attributes, clientId } ) => { - const selectedPattern = useSelect( - ( select ) => - select( blockEditorStore ).__experimentalGetParsedPattern( - attributes.slug - ), - [ attributes.slug ] + const { slug, syncStatus } = attributes; + const { selectedPattern, innerBlocks } = useSelect( + ( select ) => { + return { + selectedPattern: + select( blockEditorStore ).__experimentalGetParsedPattern( + slug + ), + innerBlocks: + select( blockEditorStore ).getBlock( clientId ) + ?.innerBlocks, + }; + }, + [ slug, clientId ] ); - - const { replaceBlocks, __unstableMarkNextChangeAsNotPersistent } = - useDispatch( blockEditorStore ); + const { + replaceBlocks, + replaceInnerBlocks, + __unstableMarkNextChangeAsNotPersistent, + } = useDispatch( blockEditorStore ); // Run this effect when the component loads. // This adds the Pattern's contents to the post. - // This change won't be saved. - // It will continue to pull from the pattern file unless changes are made to its respective template part. useEffect( () => { - if ( selectedPattern?.blocks ) { + if ( selectedPattern?.blocks && ! innerBlocks?.length ) { // We batch updates to block list settings to avoid triggering cascading renders // for each container block included in a tree and optimize initial render. // Since the above uses microtasks, we need to use a microtask here as well, @@ -33,14 +43,39 @@ const PatternEdit = ( { attributes, clientId } ) => { // inner blocks but doesn't have blockSettings in the state. window.queueMicrotask( () => { __unstableMarkNextChangeAsNotPersistent(); + if ( syncStatus === 'partial' ) { + replaceInnerBlocks( + clientId, + selectedPattern.blocks.map( ( block ) => + cloneBlock( block ) + ) + ); + return; + } replaceBlocks( clientId, selectedPattern.blocks ); } ); } - }, [ clientId, selectedPattern?.blocks ] ); + }, [ + clientId, + selectedPattern?.blocks, + replaceInnerBlocks, + __unstableMarkNextChangeAsNotPersistent, + innerBlocks, + syncStatus, + replaceBlocks, + ] ); + + const blockProps = useBlockProps(); + + const innerBlocksProps = useInnerBlocksProps( blockProps, { + templateLock: syncStatus === 'partial' ? 'contentOnly' : false, + } ); - const props = useBlockProps(); + if ( syncStatus !== 'partial' ) { + return
; + } - return ; + return ; }; export default PatternEdit; diff --git a/packages/block-library/src/pattern/index.js b/packages/block-library/src/pattern/index.js index e4af712da8bb2..27e74510eb597 100644 --- a/packages/block-library/src/pattern/index.js +++ b/packages/block-library/src/pattern/index.js @@ -3,13 +3,14 @@ */ import initBlock from '../utils/init-block'; import metadata from './block.json'; -import PatternEdit from './edit'; +import PatternEditV1 from './v1/edit'; +import PatternEditV2 from './edit'; const { name } = metadata; export { metadata, name }; -export const settings = { - edit: PatternEdit, -}; +export const settings = window?.__experimentalEnablePatternEnhancements + ? { edit: PatternEditV2 } + : { edit: PatternEditV1 }; export const init = () => initBlock( { name, metadata, settings } ); diff --git a/packages/block-library/src/pattern/index.php b/packages/block-library/src/pattern/index.php index 32a08601ca808..4af986c423d01 100644 --- a/packages/block-library/src/pattern/index.php +++ b/packages/block-library/src/pattern/index.php @@ -22,14 +22,22 @@ function register_block_core_pattern() { /** * Renders the `core/pattern` block on the server. * - * @param array $attributes Block attributes. + * @param array $attributes Block attributes. + * @param string $content The block rendered content. * * @return string Returns the output of the pattern. */ -function render_block_core_pattern( $attributes ) { +function render_block_core_pattern( $attributes, $content ) { if ( empty( $attributes['slug'] ) ) { return ''; } + $slug_classname = str_replace( '/', '-', $attributes['slug'] ); + $classnames = isset( $attributes['className'] ) ? $attributes['className'] . ' ' . $slug_classname : $slug_classname; + $wrapper = '