diff --git a/packages/block-editor/src/components/block-switcher/pattern-transformations-menu.js b/packages/block-editor/src/components/block-switcher/pattern-transformations-menu.js index f7f5a7c745ff17..97423148244dd0 100644 --- a/packages/block-editor/src/components/block-switcher/pattern-transformations-menu.js +++ b/packages/block-editor/src/components/block-switcher/pattern-transformations-menu.js @@ -81,7 +81,7 @@ function PatternTransformationsMenu( { if ( replaceInnerBlocksMode ) { _patterns = statePatterns.map( ( statePattern ) => ( { ...statePattern, - transformedBlocks: statePattern.contentBlocks.map( ( block ) => + transformedBlocks: statePattern.blocks.map( ( block ) => cloneBlock( block ) ), } ) ); @@ -91,8 +91,8 @@ function PatternTransformationsMenu( { // to mutate this prop. const pattern = { ...statePattern, - transformedBlocks: statePattern.contentBlocks.map( - ( block ) => cloneBlock( block ) + transformedBlocks: statePattern.blocks.map( ( block ) => + cloneBlock( block ) ), }; const { transformedBlocks: patternBlocks } = pattern; diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index d0d688aa9136ec..a35e5b035ad774 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -1845,30 +1845,44 @@ export const __experimentalGetAllowedPatterns = createSelector( /** * Returns the list of patterns based on specific `scope` and - * a block's name. - * `inserter` scope should be handled differently, probably in - * combination with `__experimentalGetAllowedPatterns`. - * For now `__experimentalGetScopedBlockPatterns` handles properly - * all other scopes. - * Since both APIs are experimental we should revisit this. + * a block's name or array of block names to find matching pattens. + * Internally is used `__experimentalGetAllowedPatterns` to have a + * single entry point for getting allowed patterns based on the `rootClientId`. + * TODO Since both APIs are experimental we should probably revisit this. * * @param {Object} state Editor state. * @param {string} scope Block pattern scope. - * @param {string} blockName Block's name. + * @param {string|string[]} blockNames Block's name or array of block names to find matching pattens. * @param {?string} rootClientId Optional target root client ID. * * @return {Array} The list of matched block patterns based on provided scope and block name. */ +// TODO add tests export const __experimentalGetScopedBlockPatterns = createSelector( - ( state, scope, blockName, rootClientId = null ) => { - if ( ! ( scope && blockName ) ) return EMPTY_ARRAY; + ( state, scope, blockNames, rootClientId = null ) => { + if ( ! ( scope && blockNames ) ) return EMPTY_ARRAY; const patterns = __experimentalGetAllowedPatterns( state, rootClientId ); - return patterns.filter( ( pattern ) => - pattern.scope?.[ scope ]?.includes?.( blockName ) - ); + const normalizedBlockNames = Array.isArray( blockNames ) + ? blockNames + : [ blockNames ]; + return patterns.reduce( ( accumulator, pattern ) => { + const match = pattern?.scope?.[ scope ]?.some?.( ( blockName ) => + normalizedBlockNames.includes( blockName ) + ); + if ( ! match ) return accumulator; + // If no `rootClientId` is provided, __experimentalGetAllowedPatterns are not + // filled with the `blocks` property that are the parsed blocks. In that case + // parse them. + accumulator.push( + rootClientId + ? pattern + : __experimentalGetParsedPattern( state, pattern.name ) + ); + return accumulator; + }, [] ); }, ( state, rootClientId ) => [ state.settings.__experimentalBlockPatterns, @@ -1937,10 +1951,12 @@ export const __experimentalGetPatternTransformItems = createSelector( } // Create a Set of the selected block names that is used in patterns filtering. - const selectedBlockNames = blocks.reduce( ( accumulator, block ) => { - accumulator.add( block.name ); - return accumulator; - }, new Set() ); + const selectedBlockNames = Array.from( + blocks.reduce( ( accumulator, block ) => { + accumulator.add( block.name ); + return accumulator; + }, new Set() ) + ); // If a selected block is nested (with InnerBlocks like Group or Columns) // return an EMPTY_ARRAY, as it doesn't make sense to try to be too smart. @@ -1955,7 +1971,7 @@ export const __experimentalGetPatternTransformItems = createSelector( ]; if ( blocksToSkip.some( ( blockName ) => - selectedBlockNames.has( blockName ) + selectedBlockNames.includes( blockName ) ) ) { return EMPTY_ARRAY; @@ -1967,15 +1983,12 @@ export const __experimentalGetPatternTransformItems = createSelector( // and try to find matches from the selected blocks. // Now this happens in the consumer to avoid heavy operations // in the selector. - const allowedPatterns = __experimentalGetAllowedPatterns( + return __experimentalGetScopedBlockPatterns( state, + 'transform', + selectedBlockNames, rootClientId ); - return allowedPatterns.filter( ( pattern ) => - pattern.scope?.transform?.some?.( ( blockName ) => - selectedBlockNames.has( blockName ) - ) - ); }, ( state, rootClientId ) => [ state.settings.__experimentalBlockPatterns, diff --git a/packages/block-library/src/query/edit/block-setup/layout-step.js b/packages/block-library/src/query/edit/block-setup/layout-step.js index a2a206dbb0dde8..01fc8db08d1363 100644 --- a/packages/block-library/src/query/edit/block-setup/layout-step.js +++ b/packages/block-library/src/query/edit/block-setup/layout-step.js @@ -2,8 +2,8 @@ * WordPress dependencies */ import { useSelect } from '@wordpress/data'; -import { useState, useMemo } from '@wordpress/element'; -import { parse, store as blocksStore } from '@wordpress/blocks'; +import { useState } from '@wordpress/element'; +import { store as blocksStore } from '@wordpress/blocks'; import { useInstanceId } from '@wordpress/compose'; import { BlockPreview, @@ -126,8 +126,7 @@ const LayoutSetupStep = ( { }; function BlockPattern( { pattern, onSelect, composite } ) { - const { content, viewportWidth } = pattern; - const blocks = useMemo( () => parse( content ), [ content ] ); + const { viewportWidth, blocks } = pattern; const descriptionId = useInstanceId( BlockPattern, 'block-setup-block-layout-list__item-description'