diff --git a/docs/how-to-guides/block-tutorial/nested-blocks-inner-blocks.md b/docs/how-to-guides/block-tutorial/nested-blocks-inner-blocks.md index 94d4ea67d8cf99..b90b4668530797 100644 --- a/docs/how-to-guides/block-tutorial/nested-blocks-inner-blocks.md +++ b/docs/how-to-guides/block-tutorial/nested-blocks-inner-blocks.md @@ -38,14 +38,16 @@ registerBlockType( 'gutenberg-examples/example-06', { ## Allowed blocks -Using the `allowedBlocks` property, you can define the set of blocks allowed in your InnerBlock. This restricts the blocks that can be included only to those listed, all other blocks will not show in the inserter. +Using the `allowedBlocks` prop, you can further limit, in addition to the `allowedBlocks` field in `block.json`, which blocks can be inserted as direct descendants of this block. It is useful to determine the list of allowed blocks dynamically, individually for each block. For example, determined by a block attribute: ```js -const ALLOWED_BLOCKS = [ 'core/image', 'core/paragraph' ]; +const { allowedBlocks } = attributes; //... -; +; ``` +If the list of allowed blocks is always the same, prefer the [`allowedBlocks` block setting](#defining-a-children-block-relationship) instead. + ## Orientation By default, `InnerBlocks` expects its blocks to be shown in a vertical list. A valid use-case is to style inner blocks to appear horizontally, for instance by adding CSS flex or grid properties to the inner blocks wrapper. When blocks are styled in such a way, the `orientation` prop can be set to indicate that a horizontal layout is being used: @@ -109,12 +111,13 @@ add_action( 'init', function() { } ); ``` -## Using parent and ancestor relationships in blocks +## Using parent, ancestor and children relationships in blocks -A common pattern for using InnerBlocks is to create a custom block that will be only be available if its parent block is inserted. This allows builders to establish a relationship between blocks, while limiting a nested block's discoverability. Currently, there are two relationships builders can use: `parent` and `ancestor`. The differences are: +A common pattern for using InnerBlocks is to create a custom block that will only be available if its parent block is inserted. This allows builders to establish a relationship between blocks, while limiting a nested block's discoverability. There are three relationships that builders can use: `parent`, `ancestor` and `allowedBlocks`. The differences are: - If you assign a `parent` then you’re stating that the nested block can only be used and inserted as a __direct descendant of the parent__. - If you assign an `ancestor` then you’re stating that the nested block can only be used and inserted as a __descendent of the parent__. +- If you assign the `allowedBlocks` then you’re stating a relationship in the opposite direction, i.e., which blocks can be used and inserted as __direct descendants of this block__. The key difference between `parent` and `ancestor` is `parent` has finer specificity, while an `ancestor` has greater flexibility in its nested hierarchy. @@ -150,6 +153,23 @@ When defining a descendent block, use the `ancestor` block setting. This prevent } ``` +### Defining a children block relationship + +An example of this is the Navigation block, which is assigned the `allowedBlocks` block setting. This makes only a certain subset of block types to be available as direct descendants of the Navigation block. See [Navigation code for reference](https://github.com/WordPress/gutenberg/tree/HEAD/packages/block-library/src/navigation). + +The `allowedBlocks` setting can be extended by builders of custom blocks. The custom block can hook into the `blocks.registerBlockType` filter and add itself to the available children of the Navigation. + +When defining a set of possible descendant blocks, use the `allowedBlocks` block setting. This limits what blocks are showing in the inserter when inserting a new child block. + +```json +{ + "title": "Navigation", + "name": "core/navigation", + "allowedBlocks": [ "core/navigation-link", "core/search", "core/social-links", "core/page-list", "core/spacer" ], + // ... +} +``` + ## Using a React hook You can use a react hook called `useInnerBlocksProps` instead of the `InnerBlocks` component. This hook allows you to take more control over the markup of inner blocks areas. diff --git a/docs/reference-guides/block-api/block-metadata.md b/docs/reference-guides/block-api/block-metadata.md index f89257f52d0446..6e786a2ff6322c 100644 --- a/docs/reference-guides/block-api/block-metadata.md +++ b/docs/reference-guides/block-api/block-metadata.md @@ -186,6 +186,20 @@ Setting `parent` lets a block require that it is only available when nested with The `ancestor` property makes a block available inside the specified block types at any position of the ancestor block subtree. That allows, for example, to place a ‘Comment Content’ block inside a ‘Column’ block, as long as ‘Column’ is somewhere within a ‘Comment Template’ block. In comparison to the `parent` property blocks that specify their `ancestor` can be placed anywhere in the subtree whilst blocks with a specified `parent` need to be direct children. +### Allowed Blocks + +- Type: `string[]` +- Optional +- Localized: No +- Property: `allowedBlocks` +- Since: `WordPress 6.5.0` + +```json +{ "allowedBlocks": [ "my-block/product" ] } +``` + +The `allowedBlocks` specifies which block types can be the direct children of the block. For example, a ‘List’ block can allow only ‘List Item’ blocks as children. + ### Icon - Type: `string` diff --git a/docs/reference-guides/block-api/block-registration.md b/docs/reference-guides/block-api/block-registration.md index bec9bbd871cbae..7af276d242509a 100644 --- a/docs/reference-guides/block-api/block-registration.md +++ b/docs/reference-guides/block-api/block-registration.md @@ -275,7 +275,19 @@ The `ancestor` property makes a block available inside the specified block types ancestor: [ 'core/columns' ], ``` -#### Block Hooks (optional) +#### allowedBlocks (optional) + +- **Type:** `Array` +- **Since**: `WordPress 6.5.0` + +Setting the `allowedBlocks` property will limit which block types can be nested as direct children of the block. + +```js +// Only allow the Columns block to be nested as direct child of this block +allowedBlocks: [ 'core/columns' ], +``` + +#### blockHooks (optional) - **Type:** `Object` - **Since**: `WordPress 6.4.0` diff --git a/lib/compat/wordpress-6.4/block-hooks.php b/lib/compat/wordpress-6.4/block-hooks.php index 9cf6d2414926a5..46115d5b6c629c 100644 --- a/lib/compat/wordpress-6.4/block-hooks.php +++ b/lib/compat/wordpress-6.4/block-hooks.php @@ -73,6 +73,7 @@ function gutenberg_add_hooked_blocks( $settings, $metadata ) { 'keywords' => 'keywords', 'example' => 'example', 'variations' => 'variations', + 'allowed_blocks' => 'allowedBlocks', ); // Add `block_hooks` to the list of fields to pick. $fields_to_pick['block_hooks'] = 'blockHooks'; diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index 0f6f7c33a91fa0..7964f86a5e782c 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -1563,14 +1563,30 @@ const canInsertBlockTypeUnmemoized = ( return false; } - const parentAllowedBlocks = parentBlockListSettings?.allowedBlocks; - const hasParentAllowedBlock = checkAllowList( - parentAllowedBlocks, + const parentName = getBlockName( state, rootClientId ); + const parentBlockType = getBlockType( parentName ); + + // Look at the `blockType.allowedBlocks` field to determine whether this is an allowed child block. + const parentAllowedChildBlocks = parentBlockType?.allowedBlocks; + let hasParentAllowedBlock = checkAllowList( + parentAllowedChildBlocks, blockName ); + // The `allowedBlocks` block list setting can further limit which blocks are allowed children. + if ( hasParentAllowedBlock !== false ) { + const parentAllowedBlocks = parentBlockListSettings?.allowedBlocks; + const hasParentListAllowedBlock = checkAllowList( + parentAllowedBlocks, + blockName + ); + // Never downgrade the result from `true` to `null` + if ( hasParentListAllowedBlock !== null ) { + hasParentAllowedBlock = hasParentListAllowedBlock; + } + } + const blockAllowedParentBlocks = blockType.parent; - const parentName = getBlockName( state, rootClientId ); const hasBlockAllowedParent = checkAllowList( blockAllowedParentBlocks, parentName diff --git a/packages/block-library/src/buttons/block.json b/packages/block-library/src/buttons/block.json index 4dc420bd418855..fde85ae72a316d 100644 --- a/packages/block-library/src/buttons/block.json +++ b/packages/block-library/src/buttons/block.json @@ -4,6 +4,7 @@ "name": "core/buttons", "title": "Buttons", "category": "design", + "allowedBlocks": [ "core/button" ], "description": "Prompt visitors to take action with a group of button-style links.", "keywords": [ "link" ], "textdomain": "default", diff --git a/packages/block-library/src/buttons/edit.js b/packages/block-library/src/buttons/edit.js index dce160dfb2fea8..0b9d2fe148ddd8 100644 --- a/packages/block-library/src/buttons/edit.js +++ b/packages/block-library/src/buttons/edit.js @@ -14,15 +14,8 @@ import { import { useSelect } from '@wordpress/data'; import { store as blocksStore } from '@wordpress/blocks'; -/** - * Internal dependencies - */ -import { name as buttonBlockName } from '../button'; - -const ALLOWED_BLOCKS = [ buttonBlockName ]; - const DEFAULT_BLOCK = { - name: buttonBlockName, + name: 'core/button', attributesToCopy: [ 'backgroundColor', 'border', @@ -48,24 +41,22 @@ function ButtonsEdit( { attributes, className } ) { select( blockEditorStore ).getSettings() .__experimentalPreferredStyleVariations; const buttonVariations = select( blocksStore ).getBlockVariations( - buttonBlockName, + 'core/button', 'inserter' ); return { - preferredStyle: - preferredStyleVariations?.value?.[ buttonBlockName ], + preferredStyle: preferredStyleVariations?.value?.[ 'core/button' ], hasButtonVariations: buttonVariations.length > 0, }; }, [] ); const innerBlocksProps = useInnerBlocksProps( blockProps, { - allowedBlocks: ALLOWED_BLOCKS, defaultBlock: DEFAULT_BLOCK, // This check should be handled by the `Inserter` internally to be consistent across all blocks that use it. directInsert: ! hasButtonVariations, template: [ [ - buttonBlockName, + 'core/button', { className: preferredStyle && `is-style-${ preferredStyle }` }, ], ], diff --git a/packages/block-library/src/buttons/edit.native.js b/packages/block-library/src/buttons/edit.native.js index bb73d085a8f481..821d6d1932ecc5 100644 --- a/packages/block-library/src/buttons/edit.native.js +++ b/packages/block-library/src/buttons/edit.native.js @@ -21,11 +21,8 @@ import { alignmentHelpers } from '@wordpress/components'; /** * Internal dependencies */ -import { name as buttonBlockName } from '../button/'; import styles from './editor.scss'; -const ALLOWED_BLOCKS = [ buttonBlockName ]; - const layoutProp = { type: 'default', alignments: [] }; const POPOVER_PROPS = { @@ -76,7 +73,7 @@ export default function ButtonsEdit( { const preferredStyleVariations = select( blockEditorStore ).getSettings() .__experimentalPreferredStyleVariations; - return preferredStyleVariations?.value?.[ buttonBlockName ]; + return preferredStyleVariations?.value?.[ 'core/button' ]; }, [] ); const { getBlockOrder } = useSelect( blockEditorStore ); @@ -147,10 +144,9 @@ export default function ButtonsEdit( { ) } { resizeObserver } 1 ? 'horizontal' : undefined } horizontal={ columnsInRow > 1 } - allowedBlocks={ ALLOWED_BLOCKS } contentResizeMode="stretch" onAddBlock={ onAddBlock } onDeleteBlock={ diff --git a/packages/block-library/src/comments-pagination/block.json b/packages/block-library/src/comments-pagination/block.json index a11decd201e94f..e4a1a3c3a15d97 100644 --- a/packages/block-library/src/comments-pagination/block.json +++ b/packages/block-library/src/comments-pagination/block.json @@ -5,6 +5,11 @@ "title": "Comments Pagination", "category": "theme", "parent": [ "core/comments" ], + "allowedBlocks": [ + "core/comments-pagination-previous", + "core/comments-pagination-numbers", + "core/comments-pagination-next" + ], "description": "Displays a paginated navigation to next/previous set of comments, when applicable.", "textdomain": "default", "attributes": { diff --git a/packages/block-library/src/comments-pagination/edit.js b/packages/block-library/src/comments-pagination/edit.js index 9837dda14e6810..aba29233064978 100644 --- a/packages/block-library/src/comments-pagination/edit.js +++ b/packages/block-library/src/comments-pagination/edit.js @@ -22,11 +22,6 @@ const TEMPLATE = [ [ 'core/comments-pagination-numbers' ], [ 'core/comments-pagination-next' ], ]; -const ALLOWED_BLOCKS = [ - 'core/comments-pagination-previous', - 'core/comments-pagination-numbers', - 'core/comments-pagination-next', -]; export default function QueryPaginationEdit( { attributes: { paginationArrow }, @@ -52,7 +47,6 @@ export default function QueryPaginationEdit( { const blockProps = useBlockProps(); const innerBlocksProps = useInnerBlocksProps( blockProps, { template: TEMPLATE, - allowedBlocks: ALLOWED_BLOCKS, } ); // Get the Discussion settings diff --git a/packages/block-library/src/form-submit-button/block.json b/packages/block-library/src/form-submit-button/block.json index b3fbd0ccee69c2..97ced49e70b22a 100644 --- a/packages/block-library/src/form-submit-button/block.json +++ b/packages/block-library/src/form-submit-button/block.json @@ -7,6 +7,7 @@ "category": "common", "icon": "button", "ancestor": [ "core/form" ], + "allowedBlocks": [ "core/buttons", "core/button" ], "description": "A submission button for forms.", "keywords": [ "submit", "button", "form" ], "textdomain": "default", diff --git a/packages/block-library/src/form-submit-button/edit.js b/packages/block-library/src/form-submit-button/edit.js index 4b22b26fd4755c..e2bcbe067c70ca 100644 --- a/packages/block-library/src/form-submit-button/edit.js +++ b/packages/block-library/src/form-submit-button/edit.js @@ -23,7 +23,6 @@ const TEMPLATE = [ const Edit = () => { const blockProps = useBlockProps(); const innerBlocksProps = useInnerBlocksProps( blockProps, { - allowedBlocks: TEMPLATE, template: TEMPLATE, templateLock: 'all', } ); diff --git a/packages/block-library/src/form/block.json b/packages/block-library/src/form/block.json index 0c6451f4959a48..fa5212822cc71e 100644 --- a/packages/block-library/src/form/block.json +++ b/packages/block-library/src/form/block.json @@ -5,6 +5,15 @@ "name": "core/form", "title": "Form", "category": "common", + "allowedBlocks": [ + "core/paragraph", + "core/heading", + "core/form-input", + "core/form-submit-button", + "core/form-submission-notification", + "core/group", + "core/columns" + ], "description": "A form.", "keywords": [ "container", "wrapper", "row", "section" ], "textdomain": "default", diff --git a/packages/block-library/src/form/edit.js b/packages/block-library/src/form/edit.js index 7fded64837de9d..bea513a3785dcd 100644 --- a/packages/block-library/src/form/edit.js +++ b/packages/block-library/src/form/edit.js @@ -20,16 +20,6 @@ import { formSubmissionNotificationError, } from './utils.js'; -const ALLOWED_BLOCKS = [ - 'core/paragraph', - 'core/heading', - 'core/form-input', - 'core/form-submit-button', - 'core/form-submission-notification', - 'core/group', - 'core/columns', -]; - const TEMPLATE = [ formSubmissionNotificationSuccess, formSubmissionNotificationError, @@ -76,7 +66,6 @@ const Edit = ( { attributes, setAttributes, clientId } ) => { ); const innerBlocksProps = useInnerBlocksProps( blockProps, { - allowedBlocks: ALLOWED_BLOCKS, template: TEMPLATE, renderAppender: hasInnerBlocks ? undefined diff --git a/packages/block-library/src/gallery/block.json b/packages/block-library/src/gallery/block.json index a5425c55381f94..bfeeb792a7fa02 100644 --- a/packages/block-library/src/gallery/block.json +++ b/packages/block-library/src/gallery/block.json @@ -4,6 +4,7 @@ "name": "core/gallery", "title": "Gallery", "category": "media", + "allowedBlocks": [ "core/image" ], "description": "Display multiple images in a rich gallery.", "keywords": [ "images", "photos" ], "textdomain": "default", diff --git a/packages/block-library/src/gallery/edit.js b/packages/block-library/src/gallery/edit.js index 4a646ce8362233..e2a836ae35f6cc 100644 --- a/packages/block-library/src/gallery/edit.js +++ b/packages/block-library/src/gallery/edit.js @@ -64,7 +64,6 @@ const linkOptions = [ }, ]; const ALLOWED_MEDIA_TYPES = [ 'image' ]; -const allowedBlocks = [ 'core/image' ]; const PLACEHOLDER_TEXT = Platform.isNative ? __( 'Add media' ) @@ -512,7 +511,6 @@ function GalleryEdit( props ) { }; const innerBlocksProps = useInnerBlocksProps( blockProps, { - allowedBlocks, orientation: 'horizontal', renderAppender: false, ...nativeInnerBlockProps, diff --git a/packages/block-library/src/gallery/gallery.native.js b/packages/block-library/src/gallery/gallery.native.js index 8979d814a8da00..49531325247b7e 100644 --- a/packages/block-library/src/gallery/gallery.native.js +++ b/packages/block-library/src/gallery/gallery.native.js @@ -64,7 +64,6 @@ export const Gallery = ( props ) => { {}, { contentResizeMode: 'stretch', - allowedBlocks: [ 'core/image' ], orientation: 'horizontal', renderAppender: false, numColumns: displayedColumns, diff --git a/packages/block-library/src/list-item/block.json b/packages/block-library/src/list-item/block.json index 06997c2ac23f8e..0857aaac45d9a2 100644 --- a/packages/block-library/src/list-item/block.json +++ b/packages/block-library/src/list-item/block.json @@ -5,6 +5,7 @@ "title": "List item", "category": "text", "parent": [ "core/list" ], + "allowedBlocks": [ "core/list" ], "description": "Create a list item.", "textdomain": "default", "attributes": { diff --git a/packages/block-library/src/list-item/edit.js b/packages/block-library/src/list-item/edit.js index 7733a762807528..46cbd3a94831d5 100644 --- a/packages/block-library/src/list-item/edit.js +++ b/packages/block-library/src/list-item/edit.js @@ -81,7 +81,6 @@ export default function ListItemEdit( { const { placeholder, content } = attributes; const blockProps = useBlockProps( { ref: useCopy( clientId ) } ); const innerBlocksProps = useInnerBlocksProps( blockProps, { - allowedBlocks: [ 'core/list' ], renderAppender: false, __unstableDisableDropZone: true, } ); diff --git a/packages/block-library/src/list-item/edit.native.js b/packages/block-library/src/list-item/edit.native.js index cf2e77c08d2e83..854cc8ce15214b 100644 --- a/packages/block-library/src/list-item/edit.native.js +++ b/packages/block-library/src/list-item/edit.native.js @@ -90,7 +90,6 @@ export default function ListItemEdit( { } ); const innerBlocksProps = useInnerBlocksProps( blockProps, { - allowedBlocks: [ 'core/list' ], renderAppender: false, } ); diff --git a/packages/block-library/src/list/block.json b/packages/block-library/src/list/block.json index e2fb9e4c9e3b0d..a7dcf36cf4ad74 100644 --- a/packages/block-library/src/list/block.json +++ b/packages/block-library/src/list/block.json @@ -4,6 +4,7 @@ "name": "core/list", "title": "List", "category": "text", + "allowedBlocks": [ "core/list-item" ], "description": "Create a bulleted or numbered list.", "keywords": [ "bullet list", "ordered list", "numbered list" ], "textdomain": "default", diff --git a/packages/block-library/src/list/edit.js b/packages/block-library/src/list/edit.js index e1d29d517a5ffe..ad294de93e77b1 100644 --- a/packages/block-library/src/list/edit.js +++ b/packages/block-library/src/list/edit.js @@ -125,7 +125,6 @@ export default function Edit( { attributes, setAttributes, clientId, style } ) { } ); const innerBlocksProps = useInnerBlocksProps( blockProps, { - allowedBlocks: [ 'core/list-item' ], template: TEMPLATE, templateLock: false, templateInsertUpdatesSelection: true, diff --git a/packages/block-library/src/navigation-link/block.json b/packages/block-library/src/navigation-link/block.json index d8f2fe31aef9dd..94a11217d51393 100644 --- a/packages/block-library/src/navigation-link/block.json +++ b/packages/block-library/src/navigation-link/block.json @@ -5,6 +5,11 @@ "title": "Custom Link", "category": "design", "parent": [ "core/navigation" ], + "allowedBlocks": [ + "core/navigation-link", + "core/navigation-submenu", + "core/page-list" + ], "description": "Add a page, link, or another item to your navigation.", "textdomain": "default", "attributes": { diff --git a/packages/block-library/src/navigation-link/edit.js b/packages/block-library/src/navigation-link/edit.js index f6936e8ecfe362..ecf170c3697f78 100644 --- a/packages/block-library/src/navigation-link/edit.js +++ b/packages/block-library/src/navigation-link/edit.js @@ -45,6 +45,8 @@ import { LinkUI } from './link-ui'; import { updateAttributes } from './update-attributes'; import { getColors } from '../navigation/edit/utils'; +const DEFAULT_BLOCK = { name: 'core/navigation-link' }; + /** * A React hook to determine if it's dragging within the target element. * @@ -355,22 +357,12 @@ export default function NavigationLinkEdit( { onKeyDown, } ); - const ALLOWED_BLOCKS = [ - 'core/navigation-link', - 'core/navigation-submenu', - 'core/page-list', - ]; - const DEFAULT_BLOCK = { - name: 'core/navigation-link', - }; - const innerBlocksProps = useInnerBlocksProps( { ...blockProps, className: 'remove-outline', // Remove the outline from the inner blocks container. }, { - allowedBlocks: ALLOWED_BLOCKS, defaultBlock: DEFAULT_BLOCK, directInsert: true, renderAppender: false, diff --git a/packages/block-library/src/navigation/block.json b/packages/block-library/src/navigation/block.json index 36817a5e1c35b1..eef6af390de78a 100644 --- a/packages/block-library/src/navigation/block.json +++ b/packages/block-library/src/navigation/block.json @@ -4,6 +4,19 @@ "name": "core/navigation", "title": "Navigation", "category": "theme", + "allowedBlocks": [ + "core/navigation-link", + "core/search", + "core/social-links", + "core/page-list", + "core/spacer", + "core/home-link", + "core/site-title", + "core/site-logo", + "core/navigation-submenu", + "core/loginout", + "core/buttons" + ], "description": "A collection of blocks that allow visitors to get around your site.", "keywords": [ "menu", "navigation", "links" ], "textdomain": "default", diff --git a/packages/block-library/src/navigation/constants.js b/packages/block-library/src/navigation/constants.js index c712bc4000c36d..ff13309d1e4e78 100644 --- a/packages/block-library/src/navigation/constants.js +++ b/packages/block-library/src/navigation/constants.js @@ -2,20 +2,6 @@ export const DEFAULT_BLOCK = { name: 'core/navigation-link', }; -export const ALLOWED_BLOCKS = [ - 'core/navigation-link', - 'core/search', - 'core/social-links', - 'core/page-list', - 'core/spacer', - 'core/home-link', - 'core/site-title', - 'core/site-logo', - 'core/navigation-submenu', - 'core/loginout', - 'core/buttons', -]; - export const PRIORITIZED_INSERTER_BLOCKS = [ 'core/navigation-link/page', 'core/navigation-link', diff --git a/packages/block-library/src/navigation/edit/inner-blocks.js b/packages/block-library/src/navigation/edit/inner-blocks.js index 19258213f26e5f..4bb5429cf8c04a 100644 --- a/packages/block-library/src/navigation/edit/inner-blocks.js +++ b/packages/block-library/src/navigation/edit/inner-blocks.js @@ -14,11 +14,7 @@ import { useMemo } from '@wordpress/element'; * Internal dependencies */ import PlaceholderPreview from './placeholder/placeholder-preview'; -import { - DEFAULT_BLOCK, - ALLOWED_BLOCKS, - PRIORITIZED_INSERTER_BLOCKS, -} from '../constants'; +import { DEFAULT_BLOCK, PRIORITIZED_INSERTER_BLOCKS } from '../constants'; export default function NavigationInnerBlocks( { clientId, @@ -96,7 +92,6 @@ export default function NavigationInnerBlocks( { value: blocks, onInput, onChange, - allowedBlocks: ALLOWED_BLOCKS, prioritizedInserterBlocks: PRIORITIZED_INSERTER_BLOCKS, defaultBlock: DEFAULT_BLOCK, directInsert: shouldDirectInsert, diff --git a/packages/block-library/src/navigation/edit/unsaved-inner-blocks.js b/packages/block-library/src/navigation/edit/unsaved-inner-blocks.js index e2ad08c2a99ab1..61c5eb32aed16f 100644 --- a/packages/block-library/src/navigation/edit/unsaved-inner-blocks.js +++ b/packages/block-library/src/navigation/edit/unsaved-inner-blocks.js @@ -11,11 +11,7 @@ import { useContext, useEffect, useRef, useMemo } from '@wordpress/element'; * Internal dependencies */ import { areBlocksDirty } from './are-blocks-dirty'; -import { - DEFAULT_BLOCK, - ALLOWED_BLOCKS, - SELECT_NAVIGATION_MENUS_ARGS, -} from '../constants'; +import { DEFAULT_BLOCK, SELECT_NAVIGATION_MENUS_ARGS } from '../constants'; const EMPTY_OBJECT = {}; @@ -67,7 +63,6 @@ export default function UnsavedInnerBlocks( { }, { renderAppender: hasSelection ? undefined : false, - allowedBlocks: ALLOWED_BLOCKS, defaultBlock: DEFAULT_BLOCK, directInsert: shouldDirectInsert, } diff --git a/packages/block-library/src/page-list/block.json b/packages/block-library/src/page-list/block.json index 7f4f2ce86c425f..5035d5611e32e7 100644 --- a/packages/block-library/src/page-list/block.json +++ b/packages/block-library/src/page-list/block.json @@ -4,6 +4,7 @@ "name": "core/page-list", "title": "Page List", "category": "widgets", + "allowedBlocks": [ "core/page-list-item" ], "description": "Display a list of all pages.", "keywords": [ "menu", "navigation" ], "textdomain": "default", diff --git a/packages/block-library/src/page-list/edit.js b/packages/block-library/src/page-list/edit.js index 8f21f781396c6f..34b35d61a7fa65 100644 --- a/packages/block-library/src/page-list/edit.js +++ b/packages/block-library/src/page-list/edit.js @@ -286,7 +286,6 @@ export default function PageListEdit( { } ); const innerBlocksProps = useInnerBlocksProps( blockProps, { - allowedBlocks: [ 'core/page-list-item' ], renderAppender: false, __unstableDisableDropZone: true, templateLock: isChildOfNavigation ? false : 'all', diff --git a/packages/block-library/src/post-comment/block.json b/packages/block-library/src/post-comment/block.json index 85bdb7dd6cf327..558f0e3496eff8 100644 --- a/packages/block-library/src/post-comment/block.json +++ b/packages/block-library/src/post-comment/block.json @@ -5,6 +5,14 @@ "name": "core/post-comment", "title": "Comment (deprecated)", "category": "theme", + "allowedBlocks": [ + "core/avatar", + "core/comment-author-name", + "core/comment-content", + "core/comment-date", + "core/comment-edit-link", + "core/comment-reply-link" + ], "description": "This block is deprecated. Please use the Comments block instead.", "textdomain": "default", "attributes": { diff --git a/packages/block-library/src/post-comment/edit.js b/packages/block-library/src/post-comment/edit.js index 35c0eee93308f4..54ad72be30d7c0 100644 --- a/packages/block-library/src/post-comment/edit.js +++ b/packages/block-library/src/post-comment/edit.js @@ -7,14 +7,6 @@ import { useState } from '@wordpress/element'; import { blockDefault } from '@wordpress/icons'; import { useBlockProps, useInnerBlocksProps } from '@wordpress/block-editor'; -const ALLOWED_BLOCKS = [ - 'core/avatar', - 'core/comment-author-name', - 'core/comment-content', - 'core/comment-date', - 'core/comment-edit-link', - 'core/comment-reply-link', -]; const TEMPLATE = [ [ 'core/avatar' ], [ 'core/comment-author-name' ], @@ -29,7 +21,6 @@ export default function Edit( { attributes: { commentId }, setAttributes } ) { const blockProps = useBlockProps(); const innerBlocksProps = useInnerBlocksProps( blockProps, { template: TEMPLATE, - allowedBlocks: ALLOWED_BLOCKS, } ); if ( ! commentId ) { diff --git a/packages/block-library/src/query-pagination/block.json b/packages/block-library/src/query-pagination/block.json index e32a9ba9b495ff..973e9486bce6a0 100644 --- a/packages/block-library/src/query-pagination/block.json +++ b/packages/block-library/src/query-pagination/block.json @@ -5,6 +5,11 @@ "title": "Pagination", "category": "theme", "parent": [ "core/query" ], + "allowedBlocks": [ + "core/query-pagination-previous", + "core/query-pagination-numbers", + "core/query-pagination-next" + ], "description": "Displays a paginated navigation to next/previous set of posts, when applicable.", "textdomain": "default", "attributes": { diff --git a/packages/block-library/src/query-pagination/edit.js b/packages/block-library/src/query-pagination/edit.js index 7598eba5c1cacf..e051c2e67e7e5a 100644 --- a/packages/block-library/src/query-pagination/edit.js +++ b/packages/block-library/src/query-pagination/edit.js @@ -23,11 +23,6 @@ const TEMPLATE = [ [ 'core/query-pagination-numbers' ], [ 'core/query-pagination-next' ], ]; -const ALLOWED_BLOCKS = [ - 'core/query-pagination-previous', - 'core/query-pagination-numbers', - 'core/query-pagination-next', -]; export default function QueryPaginationEdit( { attributes: { paginationArrow, showLabel }, @@ -54,7 +49,6 @@ export default function QueryPaginationEdit( { const blockProps = useBlockProps(); const innerBlocksProps = useInnerBlocksProps( blockProps, { template: TEMPLATE, - allowedBlocks: ALLOWED_BLOCKS, } ); // Always show label text if paginationArrow is set to 'none'. useEffect( () => { diff --git a/packages/block-library/src/social-links/block.json b/packages/block-library/src/social-links/block.json index 20206511a4c96c..1aea3684d0c63d 100644 --- a/packages/block-library/src/social-links/block.json +++ b/packages/block-library/src/social-links/block.json @@ -4,6 +4,7 @@ "name": "core/social-links", "title": "Social Icons", "category": "widgets", + "allowedBlocks": [ "core/social-link" ], "description": "Display icons linking to your social media profiles or sites.", "keywords": [ "links" ], "textdomain": "default", diff --git a/packages/block-library/src/social-links/edit.js b/packages/block-library/src/social-links/edit.js index 03bcd59573aec2..38a68e7f2dab2c 100644 --- a/packages/block-library/src/social-links/edit.js +++ b/packages/block-library/src/social-links/edit.js @@ -27,8 +27,6 @@ import { import { __ } from '@wordpress/i18n'; import { check } from '@wordpress/icons'; -const ALLOWED_BLOCKS = [ 'core/social-link' ]; - const sizeOptions = [ { name: __( 'Small' ), value: 'has-small-icon-size' }, { name: __( 'Normal' ), value: 'has-normal-icon-size' }, @@ -106,7 +104,6 @@ export function SocialLinksEdit( props ) { const blockProps = useBlockProps( { className } ); const innerBlocksProps = useInnerBlocksProps( blockProps, { - allowedBlocks: ALLOWED_BLOCKS, placeholder: isSelected ? SelectedSocialPlaceholder : SocialPlaceholder, templateLock: false, orientation: attributes.layout?.orientation ?? 'horizontal', diff --git a/packages/block-library/src/social-links/edit.native.js b/packages/block-library/src/social-links/edit.native.js index 8236eef0814775..f49a672a7de8ff 100644 --- a/packages/block-library/src/social-links/edit.native.js +++ b/packages/block-library/src/social-links/edit.native.js @@ -17,11 +17,6 @@ import { compose, usePreferredColorSchemeStyle } from '@wordpress/compose'; * Internal dependencies */ import styles from './editor.scss'; -import variations from '../social-link/variations'; - -const ALLOWED_BLOCKS = variations.map( - ( v ) => `core/social-link-${ v.name }` -); // Template contains the links that show when start. const TEMPLATE = [ @@ -95,7 +90,6 @@ function SocialLinksEdit( { return ( = 6.5. + if ( + serverDefinition.allowedBlocks === undefined && + blockType.allowedBlocks + ) { + newDefinition = { + ...serverDefinition, + ...newDefinition, + allowedBlocks: blockType.allowedBlocks, + }; + } } else { newDefinition = Object.fromEntries( Object.entries( blockType ) diff --git a/schemas/json/block.json b/schemas/json/block.json index 5658361d7aab64..b75a7b295fe293 100644 --- a/schemas/json/block.json +++ b/schemas/json/block.json @@ -73,6 +73,13 @@ "type": "string" } }, + "allowedBlocks": { + "type": "array", + "description": "The `allowedBlocks` property specifies that only the listed block types can be the children of this block. For example, a ‘List’ block allows only ‘List Item’ blocks as direct children.", + "items": { + "type": "string" + } + }, "icon": { "type": "string", "description": "An icon property should be specified to make it easier to identify a block. These can be any of WordPress’ Dashicons (slug serving also as a fallback in non-js contexts)."