diff --git a/lib/blocks.php b/lib/blocks.php index 3e35685e0c7a90..d0f6dede5a3134 100644 --- a/lib/blocks.php +++ b/lib/blocks.php @@ -36,6 +36,7 @@ function gutenberg_reregister_core_block_types() { 'navigation-link', 'navigation-submenu', 'nextpage', + 'pattern', 'paragraph', 'preformatted', 'pullquote', @@ -69,6 +70,7 @@ function gutenberg_reregister_core_block_types() { 'social-link.php' => 'core/social-link', 'tag-cloud.php' => 'core/tag-cloud', 'page-list.php' => 'core/page-list', + 'pattern.php' => 'core/pattern', 'post-author.php' => 'core/post-author', 'post-comment.php' => 'core/post-comment', 'post-comment-author.php' => 'core/post-comment-author', diff --git a/packages/block-library/src/index.js b/packages/block-library/src/index.js index 27ff83cdb817ae..acc997d899ef2b 100644 --- a/packages/block-library/src/index.js +++ b/packages/block-library/src/index.js @@ -42,6 +42,7 @@ import * as list from './list'; import * as missing from './missing'; import * as more from './more'; import * as nextpage from './nextpage'; +import * as pattern from './pattern'; import * as pageList from './page-list'; import * as preformatted from './preformatted'; import * as pullquote from './pullquote'; @@ -195,6 +196,7 @@ export const __experimentalGetCoreBlocks = () => [ postTerms, logInOut, + pattern, ]; /** diff --git a/packages/block-library/src/pattern/block.json b/packages/block-library/src/pattern/block.json new file mode 100644 index 00000000000000..78423e8d491232 --- /dev/null +++ b/packages/block-library/src/pattern/block.json @@ -0,0 +1,17 @@ +{ + "apiVersion": 2, + "name": "core/pattern", + "title": "Pattern", + "category": "design", + "description": "Show a block pattern.", + "supports": { + "html": false, + "inserter": false + }, + "textdomain": "default", + "attributes": { + "slug": { + "type": "string" + } + } +} diff --git a/packages/block-library/src/pattern/edit.js b/packages/block-library/src/pattern/edit.js new file mode 100644 index 00000000000000..e0cab9c7b86e4d --- /dev/null +++ b/packages/block-library/src/pattern/edit.js @@ -0,0 +1,64 @@ +/** + * WordPress dependencies + */ +import { useSelect, useDispatch } from '@wordpress/data'; +import { useEffect } from '@wordpress/element'; +import { + store as blockEditorStore, + useBlockProps, + __experimentalUseInnerBlocksProps as useInnerBlocksProps, +} from '@wordpress/block-editor'; +import { createBlock } from '@wordpress/blocks'; + +const PatternEdit = ( { attributes, clientId, isSelected } ) => { + const selectedPattern = useSelect( + ( select ) => + select( blockEditorStore ).__experimentalGetParsedPattern( + attributes.slug + ), + [ attributes.slug ] + ); + + const hasSelection = useSelect( + ( select ) => + isSelected || + select( blockEditorStore ).hasSelectedInnerBlock( clientId, true ), + [ isSelected, clientId ] + ); + + const { + replaceBlocks, + replaceInnerBlocks, + __unstableMarkNextChangeAsNotPersistent, + } = useDispatch( blockEditorStore ); + + // Run this effect when the block, or any of its InnerBlocks are selected. + // This replaces the Pattern block wrapper with a Group block. + // This ensures the markup structure and alignment are consistent between editor and view. + // This change won't be saved unless further changes are made to the InnerBlocks. + useEffect( () => { + if ( hasSelection && selectedPattern?.blocks ) { + __unstableMarkNextChangeAsNotPersistent(); + replaceBlocks( + clientId, + createBlock( 'core/group', {}, selectedPattern.blocks ) + ); + } + }, [ hasSelection, selectedPattern?.blocks ] ); + + // Run this effect when the component loads. + // This adds the Pattern block template as InnerBlocks. + // This change won't be saved. + useEffect( () => { + if ( selectedPattern?.blocks ) { + __unstableMarkNextChangeAsNotPersistent(); + replaceInnerBlocks( clientId, selectedPattern.blocks ); + } + }, [ selectedPattern?.blocks ] ); + + const props = useInnerBlocksProps( useBlockProps(), {} ); + + return
; +}; + +export default PatternEdit; diff --git a/packages/block-library/src/pattern/index.js b/packages/block-library/src/pattern/index.js new file mode 100644 index 00000000000000..5ab74fdd0c967a --- /dev/null +++ b/packages/block-library/src/pattern/index.js @@ -0,0 +1,12 @@ +/** + * Internal dependencies + */ +import metadata from './block.json'; +import PatternEdit from './edit'; + +const { name } = metadata; +export { metadata, name }; + +export const settings = { + edit: PatternEdit, +}; diff --git a/packages/block-library/src/pattern/index.php b/packages/block-library/src/pattern/index.php new file mode 100644 index 00000000000000..3c2888a9a77274 --- /dev/null +++ b/packages/block-library/src/pattern/index.php @@ -0,0 +1,44 @@ + 'render_block_core_pattern', + ) + ); +} + +/** + * Renders the `core/pattern` block on the server. + * + * @param array $attributes Block attributes. + * + * @return string Returns the output of the pattern. + */ +function render_block_core_pattern( $attributes ) { + if ( empty( $attributes['slug'] ) ) { + return ''; + } + + $slug = $attributes['slug']; + $registry = WP_Block_Patterns_Registry::get_instance(); + if ( ! $registry->is_registered( $slug ) ) { + return ''; + } + + $pattern = $registry->get_registered( $slug ); + return do_blocks( '