diff --git a/packages/block-editor/src/components/inserter/hooks/use-patterns-state.js b/packages/block-editor/src/components/inserter/hooks/use-patterns-state.js index 91b34c0ec72c3..13dae7f2ed7c0 100644 --- a/packages/block-editor/src/components/inserter/hooks/use-patterns-state.js +++ b/packages/block-editor/src/components/inserter/hooks/use-patterns-state.js @@ -13,7 +13,7 @@ import { store as noticesStore } from '@wordpress/notices'; import { store as blockEditorStore } from '../../../store'; import { unlock } from '../../../lock-unlock'; import { INSERTER_PATTERN_TYPES } from '../block-patterns-tab/utils'; -import { isFiltered } from '../../../store/utils'; +import { getParsedPattern } from '../../../store/utils'; /** * Retrieves the block patterns inserter state. @@ -31,34 +31,48 @@ const usePatternsState = ( selectedCategory, isQuick ) => { - const options = useMemo( - () => ( { [ isFiltered ]: !! isQuick } ), - [ isQuick ] - ); - const { patternCategories, patterns, userPatternCategories } = useSelect( + const { patternCategories, allPatterns, userPatternCategories } = useSelect( ( select ) => { - const { getSettings, __experimentalGetAllowedPatterns } = unlock( - select( blockEditorStore ) - ); + const { + getAllPatterns, + getSettings, + __experimentalGetAllowedPatterns, + } = unlock( select( blockEditorStore ) ); const { __experimentalUserPatternCategories, __experimentalBlockPatternCategories, } = getSettings(); return { - patterns: __experimentalGetAllowedPatterns( - rootClientId, - options - ), + allPatterns: isQuick + ? __experimentalGetAllowedPatterns() + : getAllPatterns(), userPatternCategories: __experimentalUserPatternCategories, patternCategories: __experimentalBlockPatternCategories, }; }, - [ rootClientId, options ] + [ isQuick ] ); const { getClosestAllowedInsertionPointForPattern } = unlock( useSelect( blockEditorStore ) ); + const patterns = useMemo( + () => + isQuick + ? allPatterns + : allPatterns + .filter( ( { inserter = true } ) => !! inserter ) + .map( ( pattern ) => { + return { + ...pattern, + get blocks() { + return getParsedPattern( pattern ).blocks; + }, + }; + } ), + [ isQuick, allPatterns ] + ); + const allCategories = useMemo( () => { const categories = [ ...patternCategories ]; userPatternCategories?.forEach( ( userCategory ) => { diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index 6cf6aae296141..7bb002661565b 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -1540,59 +1540,6 @@ export function getTemplateLock( state, rootClientId ) { return getBlockListSettings( state, rootClientId )?.templateLock ?? false; } -/** - * Determines if the given block type is visible in the inserter. - * Note that this is different than whether a block is allowed to be inserted. - * In some cases, the block is not allowed in a given position but - * it should still be visible in the inserter to be able to add it - * to a different position. - * - * @param {Object} state Editor state. - * @param {string|Object} blockNameOrType The block type object, e.g., the response - * from the block directory; or a string name of - * an installed block type, e.g.' core/paragraph'. - * - * @return {boolean} Whether the given block type is allowed to be inserted. - */ -const isBlockVisibleInTheInserter = ( state, blockNameOrType ) => { - let blockType; - let blockName; - if ( blockNameOrType && 'object' === typeof blockNameOrType ) { - blockType = blockNameOrType; - blockName = blockNameOrType.name; - } else { - blockType = getBlockType( blockNameOrType ); - blockName = blockNameOrType; - } - if ( ! blockType ) { - return false; - } - - const { allowedBlockTypes } = getSettings( state ); - - const isBlockAllowedInEditor = checkAllowList( - allowedBlockTypes, - blockName, - true - ); - if ( ! isBlockAllowedInEditor ) { - return false; - } - - // If parent blocks are not visible, child blocks should be hidden too. - if ( !! blockType.parent?.length ) { - return blockType.parent.some( - ( name ) => - isBlockVisibleInTheInserter( state, name ) || - // Exception for blocks with post-content parent, - // the root level is often consider as "core/post-content". - // This exception should only apply to the post editor ideally though. - name === 'core/post-content' - ); - } - return true; -}; - /** * Determines if the given block type is allowed to be inserted into the block list. * This function is not exported and not memoized because using a memoized selector @@ -1611,10 +1558,6 @@ const canInsertBlockTypeUnmemoized = ( blockName, rootClientId = null ) => { - if ( ! isBlockVisibleInTheInserter( state, blockName ) ) { - return false; - } - let blockType; if ( blockName && 'object' === typeof blockName ) { blockType = blockName; @@ -1622,6 +1565,20 @@ const canInsertBlockTypeUnmemoized = ( } else { blockType = getBlockType( blockName ); } + if ( ! blockType ) { + return false; + } + + const { allowedBlockTypes } = getSettings( state ); + + const isBlockAllowedInEditor = checkAllowList( + allowedBlockTypes, + blockName, + true + ); + if ( ! isBlockAllowedInEditor ) { + return false; + } const isLocked = !! getTemplateLock( state, rootClientId ); if ( isLocked ) { @@ -2015,7 +1972,6 @@ const buildBlockTypeItem = description: blockType.description, category: blockType.category, keywords: blockType.keywords, - parent: blockType.parent, variations: inserterVariations, example: blockType.example, utility: 1, // Deprecated. @@ -2111,18 +2067,16 @@ export const getInserterItems = createRegistrySelector( ( select ) => ) ); } else { - blockTypeInserterItems = blockTypeInserterItems - .filter( ( blockType ) => - isBlockVisibleInTheInserter( state, blockType ) - ) - .map( ( blockType ) => ( { + blockTypeInserterItems = blockTypeInserterItems.map( + ( blockType ) => ( { ...blockType, isAllowedInCurrentRoot: canIncludeBlockTypeInInserter( state, blockType, rootClientId ), - } ) ); + } ) + ); } const items = blockTypeInserterItems.reduce( @@ -2394,50 +2348,37 @@ const getAllowedPatternsDependants = ( select ) => ( state, rootClientId ) => [ */ export const __experimentalGetAllowedPatterns = createRegistrySelector( ( select ) => { - return createSelector( - ( - state, - rootClientId = null, - options = DEFAULT_INSERTER_OPTIONS - ) => { - const { getAllPatterns } = unlock( select( STORE_NAME ) ); - const patterns = getAllPatterns(); - const { allowedBlockTypes } = getSettings( state ); - const parsedPatterns = patterns - .filter( ( { inserter = true } ) => !! inserter ) - .map( ( pattern ) => { - return { - ...pattern, - get blocks() { - return getParsedPattern( pattern ).blocks; - }, - }; - } ); - - const availableParsedPatterns = parsedPatterns.filter( - ( pattern ) => - checkAllowListRecursive( - getGrammar( pattern ), - allowedBlockTypes - ) - ); - const patternsAllowed = availableParsedPatterns.filter( - ( pattern ) => - getGrammar( pattern ).every( ( { blockName: name } ) => - options[ isFiltered ] !== false - ? canInsertBlockType( - state, - name, - rootClientId - ) - : isBlockVisibleInTheInserter( state, name ) - ) - ); + return createSelector( ( state, rootClientId = null ) => { + const { getAllPatterns } = unlock( select( STORE_NAME ) ); + const patterns = getAllPatterns(); + const { allowedBlockTypes } = getSettings( state ); + const parsedPatterns = patterns + .filter( ( { inserter = true } ) => !! inserter ) + .map( ( pattern ) => { + return { + ...pattern, + get blocks() { + return getParsedPattern( pattern ).blocks; + }, + }; + } ); + + const availableParsedPatterns = parsedPatterns.filter( + ( pattern ) => + checkAllowListRecursive( + getGrammar( pattern ), + allowedBlockTypes + ) + ); + const patternsAllowed = availableParsedPatterns.filter( + ( pattern ) => + getGrammar( pattern ).every( ( { blockName: name } ) => + canInsertBlockType( state, name, rootClientId ) + ) + ); - return patternsAllowed; - }, - getAllowedPatternsDependants( select ) - ); + return patternsAllowed; + }, getAllowedPatternsDependants( select ) ); } ); diff --git a/test/e2e/specs/editor/various/allowed-patterns.spec.js b/test/e2e/specs/editor/various/allowed-patterns.spec.js index 83d44403d60ee..894f143d19bb8 100644 --- a/test/e2e/specs/editor/various/allowed-patterns.spec.js +++ b/test/e2e/specs/editor/various/allowed-patterns.spec.js @@ -54,7 +54,7 @@ test.describe( 'Allowed Patterns', () => { ); } ); - test( 'should hide patterns with only hidden blocks', async ( { + test( 'should show all patterns even if not allowed', async ( { admin, page, } ) => { @@ -77,7 +77,11 @@ test.describe( 'Allowed Patterns', () => { page .getByRole( 'listbox', { name: 'Block patterns' } ) .getByRole( 'option' ) - ).toHaveText( [ 'Test: Single heading' ] ); + ).toHaveText( [ + 'Test: Single heading', + 'Test: Single paragraph', + 'Test: Paragraph inside group', + ] ); } ); } ); } );