From 871b7edc99439398f9b3cafd446d1bcdb65629bd Mon Sep 17 00:00:00 2001 From: Jorge Date: Fri, 15 Apr 2022 19:37:47 +0100 Subject: [PATCH] Use metadata object attribute (+3 squashed commits) Squashed commits: [c1bd86cd5d] Use section object [7667d1715e] Add unit test [e7d647eb76] Add: Section concept --- .../block-api/block-supports.md | 14 +++++++ .../src/components/block-switcher/index.js | 14 ++++--- .../src/components/block-title/test/index.js | 22 ++++++++++ .../block-title/use-block-display-title.js | 4 +- packages/block-editor/src/hooks/index.js | 1 + packages/block-editor/src/hooks/metadata.js | 40 +++++++++++++++++++ packages/block-library/src/group/block.json | 1 + 7 files changed, 90 insertions(+), 6 deletions(-) create mode 100644 packages/block-editor/src/hooks/metadata.js diff --git a/docs/reference-guides/block-api/block-supports.md b/docs/reference-guides/block-api/block-supports.md index 5ca033cff021f4..fbd9e55965263b 100644 --- a/docs/reference-guides/block-api/block-supports.md +++ b/docs/reference-guides/block-api/block-supports.md @@ -664,3 +664,17 @@ attributes: { } } ``` + +### __experimentalMetadata + +- Type: `boolean` +- Default value: `false` + +The block gets the `metadata` attribute added to the block definition when `__experimentalMetadata` is true. The `metadata` attribute has the type `object` without a default value provided. Blocks can manually add this attribute and set their defaults. +The metadata attribute contains information related to the block. + +For now, the following metadata properties are available: +- `name` - Contains a descriptive name of the block shown on the block switcher and blocklist view. E.g., A group block may be named "404 Section". + +This functionality is experimental, and the properties could be added or removed. +In the future, `__experimentalMetadata` support may not exist, and the `metadata` attribute may be added unconditionally to all the blocks. diff --git a/packages/block-editor/src/components/block-switcher/index.js b/packages/block-editor/src/components/block-switcher/index.js index c0292914e180ec..c56012281a7991 100644 --- a/packages/block-editor/src/components/block-switcher/index.js +++ b/packages/block-editor/src/components/block-switcher/index.js @@ -43,18 +43,19 @@ export const BlockSwitcherDropdownMenu = ( { clientIds, blocks } ) => { icon, blockTitle, patterns, + hasBlockName, } = useSelect( ( select ) => { const { getBlockRootClientId, getBlockTransformItems, __experimentalGetPatternTransformItems, + getBlockAttributes, } = select( blockEditorStore ); const { getBlockStyles, getBlockType } = select( blocksStore ); const { canRemoveBlocks } = select( blockEditorStore ); - const rootClientId = getBlockRootClientId( - castArray( clientIds )[ 0 ] - ); + const clientId = castArray( clientIds )[ 0 ]; + const rootClientId = getBlockRootClientId( clientId ); const [ { name: firstBlockName } ] = blocks; const _isSingleBlockSelected = blocks.length === 1; const styles = @@ -84,6 +85,7 @@ export const BlockSwitcherDropdownMenu = ( { clientIds, blocks } ) => { blocks, rootClientId ), + hasBlockName: !! getBlockAttributes( clientId ).metadata?.name, }; }, [ clientIds, blocks, blockInformation?.icon ] @@ -111,7 +113,7 @@ export const BlockSwitcherDropdownMenu = ( { clientIds, blocks } ) => { icon={ <> - { ( isReusable || isTemplate ) && ( + { ( hasBlockName || isReusable || isTemplate ) && ( { className="block-editor-block-switcher__toggle" showColors /> - { ( isReusable || isTemplate ) && ( + { ( isReusable || + isTemplate || + hasBlockName ) && ( { case 'name-with-long-label': return { title: 'Block With Long Label' }; + case 'name-with-section': + return { title: 'Block With Section Support' }; } }, __experimentalGetBlockLabel( { title } ) { @@ -48,6 +50,11 @@ jest.mock( '@wordpress/blocks', () => { return title; } }, + hasBlockSupport( name, support, defaultSupport = false ) { + if ( support === '__experimentalMetadata' ) { + return name === 'name-with-section' ? true : defaultSupport; + } + }, }; } ); @@ -178,4 +185,19 @@ describe( 'BlockTitle', () => { 'This is a longer label than typical for blocks to have.' ); } ); + + it( 'should return section title if the block supports it', () => { + useSelect.mockImplementation( () => ( { + name: 'name-with-section', + attributes: { + metadata: { name: 'My custom section' }, + }, + } ) ); + + const wrapper = shallow( + + ); + + expect( wrapper.text() ).toBe( 'My custom section' ); + } ); } ); diff --git a/packages/block-editor/src/components/block-title/use-block-display-title.js b/packages/block-editor/src/components/block-title/use-block-display-title.js index 12942839bcb4e3..cbb1e21fce11ea 100644 --- a/packages/block-editor/src/components/block-title/use-block-display-title.js +++ b/packages/block-editor/src/components/block-title/use-block-display-title.js @@ -71,7 +71,9 @@ export default function useBlockDisplayTitle( clientId, maximumLength ) { ? getBlockLabel( blockType, attributes ) : null; - const label = reusableBlockTitle || blockLabel; + const blockName = attributes?.metadata?.name; + + const label = blockName || reusableBlockTitle || blockLabel; // Label will fallback to the title if no label is defined for the current // label context. If the label is defined we prioritize it over a // possible block variation title match. diff --git a/packages/block-editor/src/hooks/index.js b/packages/block-editor/src/hooks/index.js index 36c3181092a17a..f17d3ac52acb4c 100644 --- a/packages/block-editor/src/hooks/index.js +++ b/packages/block-editor/src/hooks/index.js @@ -4,6 +4,7 @@ import './compat'; import './align'; import './lock'; +import './metadata'; import './anchor'; import './custom-class-name'; import './generated-class-name'; diff --git a/packages/block-editor/src/hooks/metadata.js b/packages/block-editor/src/hooks/metadata.js new file mode 100644 index 00000000000000..ae02565390dcfb --- /dev/null +++ b/packages/block-editor/src/hooks/metadata.js @@ -0,0 +1,40 @@ +/** + * External dependencies + */ +import { has } from 'lodash'; + +/** + * WordPress dependencies + */ +import { addFilter } from '@wordpress/hooks'; +import { hasBlockSupport } from '@wordpress/blocks'; + +/** + * Filters registered block settings, extending attributes to include `metadata` in blocks declaring section support. + * + * @param {Object} blockTypeSettings Original block settings. + * + * @return {Object} Filtered block settings. + */ +export function addAttribute( blockTypeSettings ) { + if ( + hasBlockSupport( blockTypeSettings, '__experimentalMetadata', false ) + ) { + // Allow blocks to specify their own metadata attribute definition with default value if needed. + if ( ! has( blockTypeSettings.attributes, [ 'metadata' ] ) ) { + blockTypeSettings.attributes = { + ...blockTypeSettings.attributes, + metadata: { + type: 'object', + }, + }; + } + } + return blockTypeSettings; +} + +addFilter( + 'blocks.registerBlockType', + 'core/metadata/addAttribute', + addAttribute +); diff --git a/packages/block-library/src/group/block.json b/packages/block-library/src/group/block.json index 3e89f14dc938b5..dcbed342ddfeda 100644 --- a/packages/block-library/src/group/block.json +++ b/packages/block-library/src/group/block.json @@ -22,6 +22,7 @@ "align": [ "wide", "full" ], "anchor": true, "html": false, + "__experimentalMetadata": true, "color": { "gradients": true, "link": true,