From a7998ceaa9a98417e5bf7b1495d44e7d6c921cce Mon Sep 17 00:00:00 2001 From: Glen Davies Date: Fri, 21 Apr 2023 10:25:20 +1200 Subject: [PATCH 01/14] Initial attempt to leave a pattern block wrapped around a pattern --- packages/block-library/src/pattern/edit.js | 39 ++++++++++++++------- packages/block-library/src/pattern/index.js | 2 ++ packages/block-library/src/pattern/save.js | 12 +++++++ 3 files changed, 40 insertions(+), 13 deletions(-) create mode 100644 packages/block-library/src/pattern/save.js diff --git a/packages/block-library/src/pattern/edit.js b/packages/block-library/src/pattern/edit.js index be0b778eb4ae1..56343e5e05382 100644 --- a/packages/block-library/src/pattern/edit.js +++ b/packages/block-library/src/pattern/edit.js @@ -6,18 +6,25 @@ 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 { selectedPattern, innerBlocks } = useSelect( + ( select ) => { + return { + selectedPattern: select( + blockEditorStore + ).__experimentalGetParsedPattern( attributes.slug ), + innerBlocks: + select( blockEditorStore ).getBlock( clientId ) + ?.innerBlocks, + }; + }, + [ attributes.slug, clientId ] ); - const { replaceBlocks, __unstableMarkNextChangeAsNotPersistent } = + const { replaceInnerBlocks, __unstableMarkNextChangeAsNotPersistent } = useDispatch( blockEditorStore ); // Run this effect when the component loads. @@ -25,7 +32,7 @@ const PatternEdit = ( { attributes, clientId } ) => { // 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 +40,20 @@ const PatternEdit = ( { attributes, clientId } ) => { // inner blocks but doesn't have blockSettings in the state. window.queueMicrotask( () => { __unstableMarkNextChangeAsNotPersistent(); - replaceBlocks( clientId, selectedPattern.blocks ); + replaceInnerBlocks( clientId, selectedPattern.blocks ); } ); } - }, [ clientId, selectedPattern?.blocks ] ); + }, [ + clientId, + selectedPattern?.blocks, + replaceInnerBlocks, + __unstableMarkNextChangeAsNotPersistent, + innerBlocks, + ] ); - const props = useBlockProps(); - - return
; + const blockProps = useBlockProps(); + const innerBlocksProps = useInnerBlocksProps( blockProps, {} ); + return <> { innerBlocksProps.children } ; }; export default PatternEdit; diff --git a/packages/block-library/src/pattern/index.js b/packages/block-library/src/pattern/index.js index e4af712da8bb2..4a7f933d5052d 100644 --- a/packages/block-library/src/pattern/index.js +++ b/packages/block-library/src/pattern/index.js @@ -4,12 +4,14 @@ import initBlock from '../utils/init-block'; import metadata from './block.json'; import PatternEdit from './edit'; +import PatternSave from './save'; const { name } = metadata; export { metadata, name }; export const settings = { edit: PatternEdit, + save: PatternSave, }; export const init = () => initBlock( { name, metadata, settings } ); diff --git a/packages/block-library/src/pattern/save.js b/packages/block-library/src/pattern/save.js new file mode 100644 index 0000000000000..59d73888ecd5e --- /dev/null +++ b/packages/block-library/src/pattern/save.js @@ -0,0 +1,12 @@ +/** + * WordPress dependencies + */ +import { InnerBlocks } from '@wordpress/block-editor'; + +export default function save() { + return ( + <> + + + ); +} From 189b1943925e3c73e3845b2e26af36ba1228b827 Mon Sep 17 00:00:00 2001 From: Glen Davies Date: Fri, 21 Apr 2023 12:30:57 +1200 Subject: [PATCH 02/14] Add a wrapper div --- packages/block-library/src/pattern/edit.js | 3 +-- packages/block-library/src/pattern/save.js | 6 +++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/packages/block-library/src/pattern/edit.js b/packages/block-library/src/pattern/edit.js index 56343e5e05382..74da44584efd3 100644 --- a/packages/block-library/src/pattern/edit.js +++ b/packages/block-library/src/pattern/edit.js @@ -23,7 +23,6 @@ const PatternEdit = ( { attributes, clientId } ) => { }, [ attributes.slug, clientId ] ); - const { replaceInnerBlocks, __unstableMarkNextChangeAsNotPersistent } = useDispatch( blockEditorStore ); @@ -53,7 +52,7 @@ const PatternEdit = ( { attributes, clientId } ) => { const blockProps = useBlockProps(); const innerBlocksProps = useInnerBlocksProps( blockProps, {} ); - return <> { innerBlocksProps.children } ; + return
{ innerBlocksProps.children }
; }; export default PatternEdit; diff --git a/packages/block-library/src/pattern/save.js b/packages/block-library/src/pattern/save.js index 59d73888ecd5e..000acdcd4a605 100644 --- a/packages/block-library/src/pattern/save.js +++ b/packages/block-library/src/pattern/save.js @@ -1,12 +1,12 @@ /** * WordPress dependencies */ -import { InnerBlocks } from '@wordpress/block-editor'; +import { InnerBlocks, useBlockProps } from '@wordpress/block-editor'; export default function save() { return ( - <> +
- +
); } From eef4498683583c6a3b7408755211c48d068f747a Mon Sep 17 00:00:00 2001 From: Glen Davies Date: Fri, 21 Apr 2023 16:47:41 +1200 Subject: [PATCH 03/14] Add rough prototype of sync versus unsynced --- packages/block-library/src/pattern/block.json | 4 ++++ packages/block-library/src/pattern/edit.js | 17 +++++++++++++++-- packages/block-library/src/pattern/save.js | 13 ++++++++----- 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/packages/block-library/src/pattern/block.json b/packages/block-library/src/pattern/block.json index da023142403c8..3068c9ec71a6e 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" + }, + "unsynced": { + "type": "boolean", + "default": false } } } diff --git a/packages/block-library/src/pattern/edit.js b/packages/block-library/src/pattern/edit.js index 74da44584efd3..e740bcb4afa86 100644 --- a/packages/block-library/src/pattern/edit.js +++ b/packages/block-library/src/pattern/edit.js @@ -7,9 +7,11 @@ import { store as blockEditorStore, useBlockProps, useInnerBlocksProps, + BlockControls, } from '@wordpress/block-editor'; +import { ToolbarButton } from '@wordpress/components'; -const PatternEdit = ( { attributes, clientId } ) => { +const PatternEdit = ( { attributes, clientId, setAttributes } ) => { const { selectedPattern, innerBlocks } = useSelect( ( select ) => { return { @@ -52,7 +54,18 @@ const PatternEdit = ( { attributes, clientId } ) => { const blockProps = useBlockProps(); const innerBlocksProps = useInnerBlocksProps( blockProps, {} ); - return
{ innerBlocksProps.children }
; + return ( + <> +
+ + setAttributes( { unsynced: true } ) } + > + Unsync + + + + ); }; export default PatternEdit; diff --git a/packages/block-library/src/pattern/save.js b/packages/block-library/src/pattern/save.js index 000acdcd4a605..a08121117ce09 100644 --- a/packages/block-library/src/pattern/save.js +++ b/packages/block-library/src/pattern/save.js @@ -1,12 +1,15 @@ /** * WordPress dependencies */ -import { InnerBlocks, useBlockProps } from '@wordpress/block-editor'; +import { useBlockProps, useInnerBlocksProps } from '@wordpress/block-editor'; -export default function save() { +export default function save( { attributes } ) { + if ( ! attributes.unsynced ) { + return null; + } + const blockProps = useBlockProps.save(); + const innerBlocksProps = useInnerBlocksProps.save( blockProps ); return ( -
- -
+
{ innerBlocksProps.children }
); } From 0e2aab15a7ef5b9969c6cd3b9cd8aa71476f75e2 Mon Sep 17 00:00:00 2001 From: Glen Davies Date: Mon, 1 May 2023 10:24:08 +1200 Subject: [PATCH 04/14] Pattern Block: Make enhancement explorations a Gutenberg experiment --- docs/reference-guides/core-blocks.md | 2 +- lib/experimental/editor-settings.php | 3 ++ lib/experiments-page.php | 12 +++++ packages/block-library/src/pattern/index.js | 10 ++-- packages/block-library/src/pattern/v1/edit.js | 51 +++++++++++++++++++ 5 files changed, 72 insertions(+), 6 deletions(-) create mode 100644 packages/block-library/src/pattern/v1/edit.js diff --git a/docs/reference-guides/core-blocks.md b/docs/reference-guides/core-blocks.md index 6c6879d36107a..0d51c5dca2806 100644 --- a/docs/reference-guides/core-blocks.md +++ b/docs/reference-guides/core-blocks.md @@ -483,7 +483,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, unsynced ## Post Author diff --git a/lib/experimental/editor-settings.php b/lib/experimental/editor-settings.php index 0fd28025582dd..bf9acb7b70d4d 100644 --- a/lib/experimental/editor-settings.php +++ b/lib/experimental/editor-settings.php @@ -98,6 +98,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 64b2ece7aa2a3..b313c7d372fc9 100644 --- a/lib/experiments-page.php +++ b/lib/experiments-page.php @@ -113,6 +113,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/index.js b/packages/block-library/src/pattern/index.js index 4a7f933d5052d..8cedbdd94f92b 100644 --- a/packages/block-library/src/pattern/index.js +++ b/packages/block-library/src/pattern/index.js @@ -3,15 +3,15 @@ */ import initBlock from '../utils/init-block'; import metadata from './block.json'; -import PatternEdit from './edit'; +import PatternEditV1 from './v1/edit'; +import PatternEditV2 from './edit'; import PatternSave from './save'; const { name } = metadata; export { metadata, name }; -export const settings = { - edit: PatternEdit, - save: PatternSave, -}; +export const settings = window?.__experimentalEnablePatternEnhancements + ? { edit: PatternEditV2, save: PatternSave } + : { edit: PatternEditV1 }; export const init = () => initBlock( { name, metadata, settings } ); diff --git a/packages/block-library/src/pattern/v1/edit.js b/packages/block-library/src/pattern/v1/edit.js new file mode 100644 index 0000000000000..aa475809ccb44 --- /dev/null +++ b/packages/block-library/src/pattern/v1/edit.js @@ -0,0 +1,51 @@ +/** + * WordPress dependencies + */ +import { useSelect, useDispatch } from '@wordpress/data'; +import { useEffect } from '@wordpress/element'; +import { + store as blockEditorStore, + useBlockProps, +} from '@wordpress/block-editor'; + +const PatternEdit = ( { attributes, clientId } ) => { + const selectedPattern = useSelect( + ( select ) => + select( blockEditorStore ).__experimentalGetParsedPattern( + attributes.slug + ), + [ attributes.slug ] + ); + + const { replaceBlocks, __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 ) { + // 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, + // because nested pattern blocks cannot be inserted if the parent block supports + // inner blocks but doesn't have blockSettings in the state. + window.queueMicrotask( () => { + __unstableMarkNextChangeAsNotPersistent(); + replaceBlocks( clientId, selectedPattern.blocks ); + } ); + } + }, [ + clientId, + selectedPattern?.blocks, + __unstableMarkNextChangeAsNotPersistent, + replaceBlocks, + ] ); + + const props = useBlockProps(); + + return
; +}; + +export default PatternEdit; From dc6eaef036751f3a1757e241a4f29ba4aa150e83 Mon Sep 17 00:00:00 2001 From: Glen Davies Date: Wed, 26 Apr 2023 10:47:25 +1200 Subject: [PATCH 05/14] Add default layout attributes and change sync status to enum --- packages/block-library/src/pattern/block.json | 21 ++++++++++++++----- packages/block-library/src/pattern/edit.js | 4 +++- packages/block-library/src/pattern/save.js | 2 +- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/packages/block-library/src/pattern/block.json b/packages/block-library/src/pattern/block.json index 3068c9ec71a6e..08efa70914612 100644 --- a/packages/block-library/src/pattern/block.json +++ b/packages/block-library/src/pattern/block.json @@ -6,17 +6,28 @@ "category": "theme", "description": "Show a block pattern.", "supports": { - "html": false, - "inserter": false + "align": [ "wide", "full" ], + "__experimentalLayout": true }, "textdomain": "default", "attributes": { "slug": { "type": "string" }, - "unsynced": { - "type": "boolean", - "default": false + "align": { + "type": "string", + "default": "full" + }, + "layout": { + "type": "object", + "default": { + "type": "constrained" + } + }, + "syncStatus": { + "type": [ "string", "boolean" ], + "enum": [ "synced", "unsynced" ], + "default": "synced" } } } diff --git a/packages/block-library/src/pattern/edit.js b/packages/block-library/src/pattern/edit.js index e740bcb4afa86..7cb6b2b0f5b1b 100644 --- a/packages/block-library/src/pattern/edit.js +++ b/packages/block-library/src/pattern/edit.js @@ -59,7 +59,9 @@ const PatternEdit = ( { attributes, clientId, setAttributes } ) => {
setAttributes( { unsynced: true } ) } + onClick={ () => + setAttributes( { syncStatus: 'unsynced' } ) + } > Unsync diff --git a/packages/block-library/src/pattern/save.js b/packages/block-library/src/pattern/save.js index a08121117ce09..6461785a9be9e 100644 --- a/packages/block-library/src/pattern/save.js +++ b/packages/block-library/src/pattern/save.js @@ -4,7 +4,7 @@ import { useBlockProps, useInnerBlocksProps } from '@wordpress/block-editor'; export default function save( { attributes } ) { - if ( ! attributes.unsynced ) { + if ( attributes.syncStatus === 'synced' ) { return null; } const blockProps = useBlockProps.save(); From 00d381d2d205cf754ae6900ea9ed9d544a2c81dd Mon Sep 17 00:00:00 2001 From: Glen Davies Date: Thu, 27 Apr 2023 15:22:09 +1200 Subject: [PATCH 06/14] Remove wrapper div from frontend --- packages/block-library/src/pattern/block.json | 4 +++- packages/block-library/src/pattern/save.js | 4 +--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/block-library/src/pattern/block.json b/packages/block-library/src/pattern/block.json index 08efa70914612..12eea9aed09aa 100644 --- a/packages/block-library/src/pattern/block.json +++ b/packages/block-library/src/pattern/block.json @@ -7,7 +7,9 @@ "description": "Show a block pattern.", "supports": { "align": [ "wide", "full" ], - "__experimentalLayout": true + "__experimentalLayout": { + "allowEditing": false + } }, "textdomain": "default", "attributes": { diff --git a/packages/block-library/src/pattern/save.js b/packages/block-library/src/pattern/save.js index 6461785a9be9e..05c3328904c45 100644 --- a/packages/block-library/src/pattern/save.js +++ b/packages/block-library/src/pattern/save.js @@ -9,7 +9,5 @@ export default function save( { attributes } ) { } const blockProps = useBlockProps.save(); const innerBlocksProps = useInnerBlocksProps.save( blockProps ); - return ( -
{ innerBlocksProps.children }
- ); + return <>{ innerBlocksProps.children }; } From 2e9ef80ac84186bac97ebdc8f5a03e11df9add1a Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Thu, 27 Apr 2023 13:48:05 +1000 Subject: [PATCH 07/14] Pattern Enhancements: Render unsynced pattern content (#50114) --- docs/reference-guides/core-blocks.md | 4 ++-- packages/block-library/src/pattern/index.php | 9 +++++++-- packages/block-library/src/pattern/save.js | 1 + test/integration/fixtures/blocks/core__pattern.json | 7 ++++++- 4 files changed, 16 insertions(+), 5 deletions(-) diff --git a/docs/reference-guides/core-blocks.md b/docs/reference-guides/core-blocks.md index 0d51c5dca2806..fb5b0005c1c91 100644 --- a/docs/reference-guides/core-blocks.md +++ b/docs/reference-guides/core-blocks.md @@ -482,8 +482,8 @@ Show a block pattern. ([Source](https://github.com/WordPress/gutenberg/tree/trun - **Name:** core/pattern - **Category:** theme -- **Supports:** ~~html~~, ~~inserter~~ -- **Attributes:** slug, unsynced +- **Supports:** align (full, wide) +- **Attributes:** align, layout, slug, syncStatus ## Post Author diff --git a/packages/block-library/src/pattern/index.php b/packages/block-library/src/pattern/index.php index 32a08601ca808..b60df3d43fdce 100644 --- a/packages/block-library/src/pattern/index.php +++ b/packages/block-library/src/pattern/index.php @@ -22,15 +22,20 @@ 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 ''; } + if ( isset( $attributes['syncStatus'] ) && 'unsynced' === $attributes['syncStatus'] ) { + return $content; + } + $slug = $attributes['slug']; $registry = WP_Block_Patterns_Registry::get_instance(); if ( ! $registry->is_registered( $slug ) ) { diff --git a/packages/block-library/src/pattern/save.js b/packages/block-library/src/pattern/save.js index 05c3328904c45..a58adc56f8006 100644 --- a/packages/block-library/src/pattern/save.js +++ b/packages/block-library/src/pattern/save.js @@ -7,6 +7,7 @@ export default function save( { attributes } ) { if ( attributes.syncStatus === 'synced' ) { return null; } + const blockProps = useBlockProps.save(); const innerBlocksProps = useInnerBlocksProps.save( blockProps ); return <>{ innerBlocksProps.children }; diff --git a/test/integration/fixtures/blocks/core__pattern.json b/test/integration/fixtures/blocks/core__pattern.json index 3bb2c0891b06e..a92b57163082f 100644 --- a/test/integration/fixtures/blocks/core__pattern.json +++ b/test/integration/fixtures/blocks/core__pattern.json @@ -3,7 +3,12 @@ "name": "core/pattern", "isValid": true, "attributes": { - "slug": "core/text-two-columns" + "align": "full", + "layout": { + "type": "constrained" + }, + "slug": "core/text-two-columns", + "syncStatus": "synced" }, "innerBlocks": [] } From 4834b460e11e32be35576fc3157aa204a2aea1a5 Mon Sep 17 00:00:00 2001 From: Glen Davies Date: Thu, 27 Apr 2023 20:18:39 +1200 Subject: [PATCH 08/14] Use a fixed custom align attrib so block toolbar align button doesn't appear on pattern block (#50118) --------- Co-authored-by: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> --- docs/reference-guides/core-blocks.md | 4 ++-- packages/block-library/src/pattern/block.json | 3 +-- packages/block-library/src/pattern/edit.js | 14 +++++++++----- .../integration/fixtures/blocks/core__pattern.json | 2 +- 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/docs/reference-guides/core-blocks.md b/docs/reference-guides/core-blocks.md index fb5b0005c1c91..cf1b7d722b445 100644 --- a/docs/reference-guides/core-blocks.md +++ b/docs/reference-guides/core-blocks.md @@ -482,8 +482,8 @@ Show a block pattern. ([Source](https://github.com/WordPress/gutenberg/tree/trun - **Name:** core/pattern - **Category:** theme -- **Supports:** align (full, wide) -- **Attributes:** align, layout, slug, syncStatus +- **Supports:** +- **Attributes:** forcedAlignment, layout, slug, syncStatus ## Post Author diff --git a/packages/block-library/src/pattern/block.json b/packages/block-library/src/pattern/block.json index 12eea9aed09aa..ff006d50b52a4 100644 --- a/packages/block-library/src/pattern/block.json +++ b/packages/block-library/src/pattern/block.json @@ -6,7 +6,6 @@ "category": "theme", "description": "Show a block pattern.", "supports": { - "align": [ "wide", "full" ], "__experimentalLayout": { "allowEditing": false } @@ -16,7 +15,7 @@ "slug": { "type": "string" }, - "align": { + "forcedAlignment": { "type": "string", "default": "full" }, diff --git a/packages/block-library/src/pattern/edit.js b/packages/block-library/src/pattern/edit.js index 7cb6b2b0f5b1b..8cbabc5dd3684 100644 --- a/packages/block-library/src/pattern/edit.js +++ b/packages/block-library/src/pattern/edit.js @@ -12,18 +12,20 @@ import { import { ToolbarButton } from '@wordpress/components'; const PatternEdit = ( { attributes, clientId, setAttributes } ) => { + const { forcedAlignment, slug } = attributes; const { selectedPattern, innerBlocks } = useSelect( ( select ) => { return { - selectedPattern: select( - blockEditorStore - ).__experimentalGetParsedPattern( attributes.slug ), + selectedPattern: + select( blockEditorStore ).__experimentalGetParsedPattern( + slug + ), innerBlocks: select( blockEditorStore ).getBlock( clientId ) ?.innerBlocks, }; }, - [ attributes.slug, clientId ] + [ slug, clientId ] ); const { replaceInnerBlocks, __unstableMarkNextChangeAsNotPersistent } = useDispatch( blockEditorStore ); @@ -52,7 +54,9 @@ const PatternEdit = ( { attributes, clientId, setAttributes } ) => { innerBlocks, ] ); - const blockProps = useBlockProps(); + const blockProps = useBlockProps( { + className: forcedAlignment && `align${ forcedAlignment }`, + } ); const innerBlocksProps = useInnerBlocksProps( blockProps, {} ); return ( <> diff --git a/test/integration/fixtures/blocks/core__pattern.json b/test/integration/fixtures/blocks/core__pattern.json index a92b57163082f..f1101dc950e46 100644 --- a/test/integration/fixtures/blocks/core__pattern.json +++ b/test/integration/fixtures/blocks/core__pattern.json @@ -3,7 +3,7 @@ "name": "core/pattern", "isValid": true, "attributes": { - "align": "full", + "forcedAlignment": "full", "layout": { "type": "constrained" }, From f4105c73438bc11249c077e30517a996df71c801 Mon Sep 17 00:00:00 2001 From: Glen Davies Date: Mon, 1 May 2023 10:17:39 +1200 Subject: [PATCH 09/14] Fix issue with duplicated block toolbar and inspector controls by cloning the inner blocks --- packages/block-library/src/pattern/edit.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/block-library/src/pattern/edit.js b/packages/block-library/src/pattern/edit.js index 8cbabc5dd3684..0547236ba81ee 100644 --- a/packages/block-library/src/pattern/edit.js +++ b/packages/block-library/src/pattern/edit.js @@ -1,6 +1,7 @@ /** * WordPress dependencies */ +import { cloneBlock } from '@wordpress/blocks'; import { useSelect, useDispatch } from '@wordpress/data'; import { useEffect } from '@wordpress/element'; import { @@ -43,7 +44,12 @@ const PatternEdit = ( { attributes, clientId, setAttributes } ) => { // inner blocks but doesn't have blockSettings in the state. window.queueMicrotask( () => { __unstableMarkNextChangeAsNotPersistent(); - replaceInnerBlocks( clientId, selectedPattern.blocks ); + replaceInnerBlocks( + clientId, + selectedPattern.blocks.map( ( block ) => + cloneBlock( block ) + ) + ); } ); } }, [ From 7e0b617189744357b1baaaef88fe72901464ec40 Mon Sep 17 00:00:00 2001 From: Glen Davies Date: Mon, 1 May 2023 17:26:13 +1200 Subject: [PATCH 10/14] Add wrapper to frontend and add pattern slug to use as selector --- packages/block-library/src/pattern/edit.js | 2 +- packages/block-library/src/pattern/index.php | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/block-library/src/pattern/edit.js b/packages/block-library/src/pattern/edit.js index 0547236ba81ee..60c6346acf4c1 100644 --- a/packages/block-library/src/pattern/edit.js +++ b/packages/block-library/src/pattern/edit.js @@ -66,7 +66,7 @@ const PatternEdit = ( { attributes, clientId, setAttributes } ) => { const innerBlocksProps = useInnerBlocksProps( blockProps, {} ); return ( <> -
+
diff --git a/packages/block-library/src/pattern/index.php b/packages/block-library/src/pattern/index.php index b60df3d43fdce..4afed4cca5c91 100644 --- a/packages/block-library/src/pattern/index.php +++ b/packages/block-library/src/pattern/index.php @@ -32,8 +32,10 @@ function render_block_core_pattern( $attributes, $content ) { return ''; } + $wrapper = '
%s
'; + if ( isset( $attributes['syncStatus'] ) && 'unsynced' === $attributes['syncStatus'] ) { - return $content; + return sprintf( $wrapper, $content ); } $slug = $attributes['slug']; @@ -43,7 +45,7 @@ function render_block_core_pattern( $attributes, $content ) { } $pattern = $registry->get_registered( $slug ); - return do_blocks( $pattern['content'] ); + return sprintf( $wrapper, do_blocks( $pattern['content'] ) ); } add_action( 'init', 'register_block_core_pattern' ); From 6ab1c718ad0d7fed635deb3a93269e08d7485fe8 Mon Sep 17 00:00:00 2001 From: Glen Davies Date: Tue, 2 May 2023 13:03:12 +1200 Subject: [PATCH 11/14] Add ability to sync and unsync --- packages/block-library/src/pattern/edit.js | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/packages/block-library/src/pattern/edit.js b/packages/block-library/src/pattern/edit.js index 60c6346acf4c1..b655c082fc9d5 100644 --- a/packages/block-library/src/pattern/edit.js +++ b/packages/block-library/src/pattern/edit.js @@ -11,9 +11,10 @@ import { BlockControls, } from '@wordpress/block-editor'; import { ToolbarButton } from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; const PatternEdit = ( { attributes, clientId, setAttributes } ) => { - const { forcedAlignment, slug } = attributes; + const { forcedAlignment, slug, syncStatus } = attributes; const { selectedPattern, innerBlocks } = useSelect( ( select ) => { return { @@ -70,10 +71,17 @@ const PatternEdit = ( { attributes, clientId, setAttributes } ) => { - setAttributes( { syncStatus: 'unsynced' } ) + setAttributes( { + syncStatus: + syncStatus === 'unsynced' + ? 'synced' + : 'unsynced', + } ) } > - Unsync + { syncStatus === 'unsynced' + ? __( 'Sync' ) + : __( 'Unsync' ) } From e9e9308a79ac75c95422749a4e067d9e6391a38c Mon Sep 17 00:00:00 2001 From: Glen Davies Date: Tue, 2 May 2023 14:18:46 +1200 Subject: [PATCH 12/14] Make reverting to `Sync` revert to saved pattern blocks --- packages/block-library/src/pattern/edit.js | 26 +++++++++++++--------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/packages/block-library/src/pattern/edit.js b/packages/block-library/src/pattern/edit.js index b655c082fc9d5..db7da2ffa5577 100644 --- a/packages/block-library/src/pattern/edit.js +++ b/packages/block-library/src/pattern/edit.js @@ -65,23 +65,27 @@ const PatternEdit = ( { attributes, clientId, setAttributes } ) => { className: forcedAlignment && `align${ forcedAlignment }`, } ); const innerBlocksProps = useInnerBlocksProps( blockProps, {} ); + + const handleSync = () => { + if ( syncStatus === 'synced' ) { + setAttributes( { syncStatus: 'unsynced' } ); + } else { + setAttributes( { syncStatus: 'synced' } ); + replaceInnerBlocks( + clientId, + selectedPattern.blocks.map( ( block ) => cloneBlock( block ) ) + ); + } + }; + return ( <>
- - setAttributes( { - syncStatus: - syncStatus === 'unsynced' - ? 'synced' - : 'unsynced', - } ) - } - > + { syncStatus === 'unsynced' ? __( 'Sync' ) - : __( 'Unsync' ) } + : __( 'Desync' ) } From 0d1f42ee6226c43db393b0853e7610dce97d8468 Mon Sep 17 00:00:00 2001 From: Glen Davies Date: Wed, 3 May 2023 12:47:46 +1200 Subject: [PATCH 13/14] Change default syncStatus to unsynced for barckwards compat --- packages/block-library/src/pattern/block.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-library/src/pattern/block.json b/packages/block-library/src/pattern/block.json index ff006d50b52a4..369024d10c49c 100644 --- a/packages/block-library/src/pattern/block.json +++ b/packages/block-library/src/pattern/block.json @@ -28,7 +28,7 @@ "syncStatus": { "type": [ "string", "boolean" ], "enum": [ "synced", "unsynced" ], - "default": "synced" + "default": "unsynced" } } } From 2fab7907e041dca599bff79e7bd642d88425a337 Mon Sep 17 00:00:00 2001 From: Glen Davies Date: Wed, 3 May 2023 15:18:36 +1200 Subject: [PATCH 14/14] Get widest align from child blocks (#50230) --- packages/block-library/src/pattern/edit.js | 29 ++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/packages/block-library/src/pattern/edit.js b/packages/block-library/src/pattern/edit.js index db7da2ffa5577..01beff026c6ee 100644 --- a/packages/block-library/src/pattern/edit.js +++ b/packages/block-library/src/pattern/edit.js @@ -61,6 +61,35 @@ const PatternEdit = ( { attributes, clientId, setAttributes } ) => { innerBlocks, ] ); + useEffect( () => { + const alignments = [ 'wide', 'full' ]; + const blocks = + syncStatus === 'synced' ? selectedPattern?.blocks : innerBlocks; + if ( ! blocks || blocks.length === 0 ) { + return; + } + // Determine the widest setting of all the contained blocks. + const widestAlignment = blocks.reduce( ( accumulator, block ) => { + const { align } = block.attributes; + return alignments.indexOf( align ) > + alignments.indexOf( accumulator ) + ? align + : accumulator; + }, undefined ); + + // Set the attribute of the Pattern block to match the widest + // alignment. + setAttributes( { + forcedAlignment: widestAlignment ?? '', + } ); + }, [ + innerBlocks, + selectedPattern?.blocks, + setAttributes, + syncStatus, + forcedAlignment, + ] ); + const blockProps = useBlockProps( { className: forcedAlignment && `align${ forcedAlignment }`, } );