diff --git a/lib/blocks.php b/lib/blocks.php
index bbee108b71c5f5..60a7688f2ad53e 100644
--- a/lib/blocks.php
+++ b/lib/blocks.php
@@ -32,6 +32,7 @@ function gutenberg_reregister_core_block_types() {
'more',
'nextpage',
'paragraph',
+ 'pattern-part',
'preformatted',
'pullquote',
'quote',
diff --git a/packages/block-library/src/index.js b/packages/block-library/src/index.js
index a0c7b75eac19b8..243681d1257521 100644
--- a/packages/block-library/src/index.js
+++ b/packages/block-library/src/index.js
@@ -67,6 +67,7 @@ import * as navigationLink from './navigation-link';
import * as navigationSubmenu from './navigation-submenu';
import * as nextpage from './nextpage';
import * as pattern from './pattern';
+import * as patternPart from './pattern-part';
import * as pageList from './page-list';
import * as pageListItem from './page-list-item';
import * as paragraph from './paragraph';
@@ -160,6 +161,7 @@ const getAllBlocks = () => {
pageList,
pageListItem,
pattern,
+ patternPart,
preformatted,
pullquote,
reusableBlock,
diff --git a/packages/block-library/src/pattern-part/block.json b/packages/block-library/src/pattern-part/block.json
new file mode 100644
index 00000000000000..1f08838b8aae8e
--- /dev/null
+++ b/packages/block-library/src/pattern-part/block.json
@@ -0,0 +1,19 @@
+{
+ "$schema": "https://schemas.wp.org/trunk/block.json",
+ "apiVersion": 2,
+ "name": "core/pattern-part",
+ "title": "Pattern part",
+ "category": "text",
+ "description": "A wrapper for a pattern's inner blocks",
+ "keywords": [ "bob" ],
+ "textdomain": "default",
+ "attributes": {
+ "slug": {
+ "type": "string"
+ }
+ },
+ "supports": {
+ "html": false,
+ "inserter": false
+ }
+}
diff --git a/packages/block-library/src/pattern-part/edit.js b/packages/block-library/src/pattern-part/edit.js
new file mode 100644
index 00000000000000..79d9f4d33ffbdb
--- /dev/null
+++ b/packages/block-library/src/pattern-part/edit.js
@@ -0,0 +1,10 @@
+/**
+ * WordPress dependencies
+ */
+import { useInnerBlocksProps, useBlockProps } from '@wordpress/block-editor';
+export default function Edit() {
+ const blockProps = useBlockProps();
+ const innerBlocksProps = useInnerBlocksProps( blockProps );
+ console.log( 'innerBlocksProps', innerBlocksProps.children );
+ return
;
+}
diff --git a/packages/block-library/src/pattern-part/index.js b/packages/block-library/src/pattern-part/index.js
new file mode 100644
index 00000000000000..fdb5204ecf30aa
--- /dev/null
+++ b/packages/block-library/src/pattern-part/index.js
@@ -0,0 +1,19 @@
+/**
+ * Internal dependencies
+ */
+import initBlock from '../utils/init-block';
+import edit from './edit';
+import metadata from './block.json';
+import save from './save';
+
+const { name } = metadata;
+
+export { metadata, name };
+
+const settings = {
+ edit,
+ save,
+};
+
+export { settings };
+export const init = () => initBlock( { name, metadata, settings } );
diff --git a/packages/block-library/src/pattern-part/init.js b/packages/block-library/src/pattern-part/init.js
new file mode 100644
index 00000000000000..79f0492c2cb2f8
--- /dev/null
+++ b/packages/block-library/src/pattern-part/init.js
@@ -0,0 +1,6 @@
+/**
+ * Internal dependencies
+ */
+import { init } from './';
+
+export default init();
diff --git a/packages/block-library/src/pattern-part/save.js b/packages/block-library/src/pattern-part/save.js
new file mode 100644
index 00000000000000..3adb917114f584
--- /dev/null
+++ b/packages/block-library/src/pattern-part/save.js
@@ -0,0 +1,10 @@
+/**
+ * WordPress dependencies
+ */
+import { useInnerBlocksProps, useBlockProps } from '@wordpress/block-editor';
+
+export default function save() {
+ const blockProps = useBlockProps.save();
+ const innerBlocksProps = useInnerBlocksProps.save( blockProps );
+ return { innerBlocksProps.children }
;
+}
diff --git a/packages/block-library/src/pattern-part/style.scss b/packages/block-library/src/pattern-part/style.scss
new file mode 100644
index 00000000000000..a60bae49374fbe
--- /dev/null
+++ b/packages/block-library/src/pattern-part/style.scss
@@ -0,0 +1,3 @@
+.wp-block-pattern-part {
+ display: contents;
+}
diff --git a/packages/block-library/src/pattern/edit.js b/packages/block-library/src/pattern/edit.js
index c22536a59eb03f..5f998027e38bb5 100644
--- a/packages/block-library/src/pattern/edit.js
+++ b/packages/block-library/src/pattern/edit.js
@@ -1,7 +1,7 @@
/**
* WordPress dependencies
*/
-import { cloneBlock } from '@wordpress/blocks';
+import { cloneBlock, createBlock } from '@wordpress/blocks';
import { useSelect, useDispatch } from '@wordpress/data';
import { useEffect } from '@wordpress/element';
import {
@@ -35,6 +35,24 @@ const PatternEdit = ( { attributes, clientId } ) => {
// Run this effect when the component loads.
// This adds the Pattern's contents to the post.
useEffect( () => {
+ function clonePatternBlock( block ) {
+ let newInnerBlocks = [];
+ if ( block.innerBlocks.length > 0 ) {
+ newInnerBlocks = block.innerBlocks.map( ( innerBlock ) => {
+ let nestedInnerBlocks = [];
+ if ( innerBlock.innerBlocks.length > 0 ) {
+ nestedInnerBlocks =
+ innerBlock.innerBlocks.map( clonePatternBlock );
+ }
+ return createBlock( 'core/pattern-part', {}, [
+ cloneBlock( innerBlock, {}, nestedInnerBlocks ),
+ ] );
+ } );
+ }
+ return createBlock( 'core/pattern-part', {}, [
+ cloneBlock( block, {}, newInnerBlocks ),
+ ] );
+ }
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.
@@ -44,9 +62,8 @@ const PatternEdit = ( { attributes, clientId } ) => {
window.queueMicrotask( () => {
// Clone blocks from the pattern before insertion to ensure they receive
// distinct client ids. See https://github.com/WordPress/gutenberg/issues/50628.
- const clonedBlocks = selectedPattern.blocks.map( ( block ) =>
- cloneBlock( block )
- );
+ const clonedBlocks =
+ selectedPattern.blocks.map( clonePatternBlock );
__unstableMarkNextChangeAsNotPersistent();
if ( syncStatus === 'partial' ) {
replaceInnerBlocks( clientId, clonedBlocks );
@@ -70,7 +87,7 @@ const PatternEdit = ( { attributes, clientId } ) => {
} );
const innerBlocksProps = useInnerBlocksProps( blockProps, {
- templateLock: syncStatus === 'partial' ? 'contentOnly' : false,
+ templateLock: syncStatus === 'partial' ? false : false,
} );
if ( syncStatus !== 'partial' ) {
diff --git a/packages/block-library/src/pattern/index.js b/packages/block-library/src/pattern/index.js
index 27e74510eb5972..a7445c8b6e857d 100644
--- a/packages/block-library/src/pattern/index.js
+++ b/packages/block-library/src/pattern/index.js
@@ -5,12 +5,13 @@ import initBlock from '../utils/init-block';
import metadata from './block.json';
import PatternEditV1 from './v1/edit';
import PatternEditV2 from './edit';
+import save from './save';
const { name } = metadata;
export { metadata, name };
export const settings = window?.__experimentalEnablePatternEnhancements
- ? { edit: PatternEditV2 }
+ ? { edit: PatternEditV2, save }
: { edit: PatternEditV1 };
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 00000000000000..83034aa1b4ba69
--- /dev/null
+++ b/packages/block-library/src/pattern/save.js
@@ -0,0 +1,19 @@
+/**
+ * WordPress dependencies
+ */
+import { useBlockProps, useInnerBlocksProps } from '@wordpress/block-editor';
+
+export default function save( {
+ attributes: { syncStatus, slug },
+ innerBlocks,
+} ) {
+ if ( innerBlocks?.length === 0 || syncStatus !== 'partial' ) {
+ return;
+ }
+ //test
+ const blockProps = useBlockProps.save( {
+ className: slug?.replace( '/', '-' ),
+ } );
+ const innerBlocksProps = useInnerBlocksProps.save( blockProps );
+ return { innerBlocksProps.children }
;
+}
diff --git a/packages/block-library/src/style.scss b/packages/block-library/src/style.scss
index 387dd84b8f238c..21d1e04987c781 100644
--- a/packages/block-library/src/style.scss
+++ b/packages/block-library/src/style.scss
@@ -27,6 +27,7 @@
@import "./navigation-link/style.scss";
@import "./page-list/style.scss";
@import "./paragraph/style.scss";
+@import "./pattern-part/style.scss";
@import "./post-author/style.scss";
@import "./post-comments-form/style.scss";
@import "./post-date/style.scss";