From 69be2abede1c89e15d26d84902ecfb3d6f4ec57a Mon Sep 17 00:00:00 2001 From: ntsekouras Date: Fri, 4 Dec 2020 11:00:41 +0200 Subject: [PATCH 01/32] getBlockTypeWithVariationInfo selector, BlockDescription component and first changes to display the proper info --- .../developers/data/data-core-blocks.md | 4 ++ packages/block-editor/README.md | 26 ++++++++++ .../src/components/block-card/index.js | 13 +++-- .../components/block-description/README.md | 1 + .../src/components/block-description/index.js | 31 +++++++++++ .../src/components/block-icon/index.js | 25 ++++++--- .../src/components/block-inspector/index.js | 2 +- .../block-navigation/block-select-button.js | 15 ++---- .../src/components/block-switcher/index.js | 15 ++---- .../src/components/block-title/index.js | 51 +++---------------- packages/block-editor/src/components/index.js | 1 + packages/block-library/src/embed/index.js | 4 ++ .../block-library/src/social-link/index.js | 4 ++ packages/blocks/src/store/selectors.js | 49 ++++++++++++++++++ 14 files changed, 165 insertions(+), 76 deletions(-) create mode 100644 packages/block-editor/src/components/block-description/README.md create mode 100644 packages/block-editor/src/components/block-description/index.js diff --git a/docs/designers-developers/developers/data/data-core-blocks.md b/docs/designers-developers/developers/data/data-core-blocks.md index 655c4f0d7a339..a96165580d8f6 100644 --- a/docs/designers-developers/developers/data/data-core-blocks.md +++ b/docs/designers-developers/developers/data/data-core-blocks.md @@ -59,6 +59,10 @@ _Returns_ - `Array`: Block Types. +# **getBlockTypeWithVariationInfo** + +Undocumented declaration. + # **getBlockVariations** Returns block variations by block name. diff --git a/packages/block-editor/README.md b/packages/block-editor/README.md index cfadf407b3b65..e422459abee4b 100644 --- a/packages/block-editor/README.md +++ b/packages/block-editor/README.md @@ -118,6 +118,31 @@ _Parameters_ Undocumented declaration. +# **BlockDescription** + +Renders the block's configured description as a string, or empty if the description +cannot be determined. + +_Usage_ + +```jsx + +``` + +```jsx + +``` + +_Parameters_ + +- _props_ `Object`: +- _props.clientId_ `string`: Client ID of block. +- _props.description_ `string`: Description override. + +_Returns_ + +- `?string`: Block Description. + # **BlockEdit** Undocumented declaration. @@ -201,6 +226,7 @@ _Parameters_ - _props_ `Object`: - _props.clientId_ `string`: Client ID of block. +- _props.title_ `string`: Title override. _Returns_ diff --git a/packages/block-editor/src/components/block-card/index.js b/packages/block-editor/src/components/block-card/index.js index c209ea39b5c73..53e102a745373 100644 --- a/packages/block-editor/src/components/block-card/index.js +++ b/packages/block-editor/src/components/block-card/index.js @@ -2,15 +2,20 @@ * Internal dependencies */ import BlockIcon from '../block-icon'; +import BlockTitle from '../block-title'; +import BlockDescription from '../block-description'; -function BlockCard( { blockType: { icon, title, description } } ) { +function BlockCard( { clientId, blockType } ) { + const props = ( clientId && { clientId } ) || blockType; return (
- +
-

{ title }

+

+ +

- { description } +
diff --git a/packages/block-editor/src/components/block-description/README.md b/packages/block-editor/src/components/block-description/README.md new file mode 100644 index 0000000000000..70b786d12ed05 --- /dev/null +++ b/packages/block-editor/src/components/block-description/README.md @@ -0,0 +1 @@ +// TODO diff --git a/packages/block-editor/src/components/block-description/index.js b/packages/block-editor/src/components/block-description/index.js new file mode 100644 index 0000000000000..9d74d00302399 --- /dev/null +++ b/packages/block-editor/src/components/block-description/index.js @@ -0,0 +1,31 @@ +/** + * WordPress dependencies + */ +import { useSelect } from '@wordpress/data'; + +/** + * Renders the block's configured description as a string, or empty if the description + * cannot be determined. + * + * @example + * + * ```jsx + * + * ``` + * ```jsx + * + * ``` + * @param {Object} props + * @param {string} props.clientId Client ID of block. + * @param {string} props.description Description override. + * @return {?string} Block Description. + */ +export default function BlockDescription( { clientId, description } ) { + const { description: blockDescription } = useSelect( + ( select ) => + select( 'core/blocks' ).getBlockTypeWithVariationInfo( clientId ) || + {}, + [ clientId ] + ); + return description || blockDescription || null; +} diff --git a/packages/block-editor/src/components/block-icon/index.js b/packages/block-editor/src/components/block-icon/index.js index f605e7f375d5d..2f8cfab88f309 100644 --- a/packages/block-editor/src/components/block-icon/index.js +++ b/packages/block-editor/src/components/block-icon/index.js @@ -6,24 +6,37 @@ import classnames from 'classnames'; /** * WordPress dependencies */ +import { useSelect } from '@wordpress/data'; import { Icon } from '@wordpress/components'; import { blockDefault } from '@wordpress/icons'; -export default function BlockIcon( { icon, showColors = false, className } ) { +export default function BlockIcon( { + clientId, + icon, + showColors = false, + className, +} ) { if ( icon?.src === 'block-default' ) { icon = { src: blockDefault, }; } - - const renderedIcon = ; + const { icon: blockIcon } = useSelect( + ( select ) => + select( 'core/blocks' ).getBlockTypeWithVariationInfo( clientId ) || + {}, + [ clientId ] + ); + if ( blockIcon && ! icon ) { + icon = blockIcon; + } + const renderedIcon = ; const style = showColors ? { - backgroundColor: icon && icon.background, - color: icon && icon.foreground, + backgroundColor: icon?.background, + color: icon?.foreground, } : {}; - return ( - + { hasBlockStyles && (
diff --git a/packages/block-editor/src/components/block-navigation/block-select-button.js b/packages/block-editor/src/components/block-navigation/block-select-button.js index 2e9956d5387e1..33faabde47813 100644 --- a/packages/block-editor/src/components/block-navigation/block-select-button.js +++ b/packages/block-editor/src/components/block-navigation/block-select-button.js @@ -6,10 +6,6 @@ import classnames from 'classnames'; /** * WordPress dependencies */ -import { - __experimentalGetBlockLabel as getBlockLabel, - getBlockType, -} from '@wordpress/blocks'; import { Button, VisuallyHidden } from '@wordpress/components'; import { useInstanceId } from '@wordpress/compose'; import { forwardRef } from '@wordpress/element'; @@ -19,12 +15,13 @@ import { __ } from '@wordpress/i18n'; * Internal dependencies */ import BlockIcon from '../block-icon'; +import BlockTitle from '../block-title'; import { getBlockPositionDescription } from './utils'; function BlockNavigationBlockSelectButton( { className, - block, + block: { clientId }, isSelected, onClick, position, @@ -38,10 +35,6 @@ function BlockNavigationBlockSelectButton( }, ref ) { - const { name, attributes } = block; - - const blockType = getBlockType( name ); - const blockDisplayName = getBlockLabel( blockType, attributes ); const instanceId = useInstanceId( BlockNavigationBlockSelectButton ); const descriptionId = `block-navigation-block-select-button__${ instanceId }`; const blockPositionDescription = getBlockPositionDescription( @@ -66,8 +59,8 @@ function BlockNavigationBlockSelectButton( onDragEnd={ onDragEnd } draggable={ draggable } > - - { blockDisplayName } + + { isSelected && ( { __( '(selected block)' ) } diff --git a/packages/block-editor/src/components/block-switcher/index.js b/packages/block-editor/src/components/block-switcher/index.js index 7ebb59c16cda3..e1444dcde5468 100644 --- a/packages/block-editor/src/components/block-switcher/index.js +++ b/packages/block-editor/src/components/block-switcher/index.js @@ -118,14 +118,9 @@ export class BlockSwitcher extends Component { const isSelectionOfSameType = uniq( map( blocks, 'name' ) ).length === 1; - let icon; - if ( isSelectionOfSameType ) { - const sourceBlockName = hoveredBlock.name; - const blockType = getBlockType( sourceBlockName ); - icon = blockType.icon; - } else { - icon = stack; - } + const blockIconProps = isSelectionOfSameType + ? { clientId: hoveredBlock.clientId } + : { icon: stack }; const hasPossibleBlockTransformations = !! possibleBlockTransformations.length; @@ -136,7 +131,7 @@ export class BlockSwitcher extends Component { disabled className="block-editor-block-switcher__no-switcher-icon" title={ __( 'Block icon' ) } - icon={ } + icon={ } /> ); @@ -170,7 +165,7 @@ export class BlockSwitcher extends Component { } } icon={ diff --git a/packages/block-editor/src/components/block-title/index.js b/packages/block-editor/src/components/block-title/index.js index 3a36d53e12e17..091e22713ce4c 100644 --- a/packages/block-editor/src/components/block-title/index.js +++ b/packages/block-editor/src/components/block-title/index.js @@ -1,16 +1,7 @@ -/** - * External dependencies - */ -import { truncate } from 'lodash'; - /** * WordPress dependencies */ import { useSelect } from '@wordpress/data'; -import { - getBlockType, - __experimentalGetBlockLabel as getBlockLabel, -} from '@wordpress/blocks'; /** * Renders the block's configured title as a string, or empty if the title @@ -21,45 +12,17 @@ import { * ```jsx * * ``` - * * @param {Object} props * @param {string} props.clientId Client ID of block. - * + * @param {string} props.title Title override. * @return {?string} Block title. */ -export default function BlockTitle( { clientId } ) { - const { attributes, name } = useSelect( - ( select ) => { - if ( ! clientId ) { - return {}; - } - const { getBlockName, getBlockAttributes } = select( - 'core/block-editor' - ); - return { - attributes: getBlockAttributes( clientId ), - name: getBlockName( clientId ), - }; - }, +export default function BlockTitle( { clientId, title } ) { + const { title: blockTitle } = useSelect( + ( select ) => + select( 'core/blocks' ).getBlockTypeWithVariationInfo( clientId ) || + {}, [ clientId ] ); - - if ( ! name ) { - return null; - } - - const blockType = getBlockType( name ); - if ( ! blockType ) { - return null; - } - - const { title } = blockType; - const label = getBlockLabel( blockType, attributes ); - - // Label will often fall back to the title if no label is defined for the - // current label context. We do not want "Paragraph: Paragraph". - if ( label !== title ) { - return `${ title }: ${ truncate( label, { length: 15 } ) }`; - } - return title; + return title || blockTitle || null; } diff --git a/packages/block-editor/src/components/index.js b/packages/block-editor/src/components/index.js index 3e845204bed82..68bbd56ef097b 100644 --- a/packages/block-editor/src/components/index.js +++ b/packages/block-editor/src/components/index.js @@ -89,6 +89,7 @@ export { export { default as BlockSettingsMenu } from './block-settings-menu'; export { default as BlockSettingsMenuControls } from './block-settings-menu-controls'; export { default as BlockTitle } from './block-title'; +export { default as BlockDescription } from './block-description'; export { default as BlockToolbar } from './block-toolbar'; export { default as CopyHandler, diff --git a/packages/block-library/src/embed/index.js b/packages/block-library/src/embed/index.js index 3b1ed4d9bdb9c..afd577be5e649 100644 --- a/packages/block-library/src/embed/index.js +++ b/packages/block-library/src/embed/index.js @@ -28,4 +28,8 @@ export const settings = { transforms, variations, deprecated, + variationMatcher: ( blockAttributes, variation ) => { + const { providerNameSlug } = blockAttributes || {}; + return variation.name === providerNameSlug; + }, }; diff --git a/packages/block-library/src/social-link/index.js b/packages/block-library/src/social-link/index.js index 142b2e616a9b6..805d961b3e446 100644 --- a/packages/block-library/src/social-link/index.js +++ b/packages/block-library/src/social-link/index.js @@ -23,4 +23,8 @@ export const settings = { 'Display an icon linking to a social media profile or website.' ), variations, + variationMatcher: ( blockAttributes, variation ) => { + const { service } = blockAttributes || {}; + return variation.name === service; + }, }; diff --git a/packages/blocks/src/store/selectors.js b/packages/blocks/src/store/selectors.js index 5513ff4e4c488..1136aa306d23d 100644 --- a/packages/blocks/src/store/selectors.js +++ b/packages/blocks/src/store/selectors.js @@ -12,8 +12,19 @@ import { includes, map, some, + truncate, } from 'lodash'; +/** + * WordPress dependencies + */ +import { createRegistrySelector } from '@wordpress/data'; + +/** + * Internal dependencies + */ +import { __experimentalGetBlockLabel as getBlockLabel } from '../api'; + /** @typedef {import('../api/registration').WPBlockVariation} WPBlockVariation */ /** @typedef {import('../api/registration').WPBlockVariationScope} WPBlockVariationScope */ /** @typedef {import('./reducer').WPBlockCategory} WPBlockCategory */ @@ -95,6 +106,44 @@ export function getBlockVariations( state, blockName, scope ) { } ); } +// TODO jsdoc and experimental and tests +export const getBlockTypeWithVariationInfo = createRegistrySelector( + ( select ) => ( state, clientId ) => { + const { + __unstableGetBlockWithoutInnerBlocks, + getSelectedBlockClientId, + } = select( 'core/block-editor' ); + const _clientId = clientId || getSelectedBlockClientId(); + const { name, attributes } = + __unstableGetBlockWithoutInnerBlocks( _clientId ) || {}; + + if ( ! name ) return null; + const variations = state.blockVariations[ name ]; + const blockType = getBlockType( state, name ); + + const label = getBlockLabel( blockType, attributes ); + // Label will often fall back to the title if no label is defined for the + // current label context. We do not want "Paragraph: Paragraph". + if ( label !== blockType.title ) { + blockType.title = `${ blockType.title }: ${ truncate( label, { + length: 15, + } ) }`; + } + + if ( ! variations || ! blockType?.variationMatcher ) return blockType; + const match = variations.find( ( variation ) => + blockType.variationMatcher( attributes, variation ) + ); + if ( ! match ) return blockType; + return { + ...blockType, + title: match.title || blockType.title, + icon: match.icon || blockType.icon, + description: match.description || blockType.description, + }; + } +); + /** * Returns the default block variation for the given block type. * When there are multiple variations annotated as the default one, From 20eeea36942bb1b912794257268c0b8a21ea6719 Mon Sep 17 00:00:00 2001 From: ntsekouras Date: Thu, 10 Dec 2020 11:02:09 +0200 Subject: [PATCH 02/32] revert BlockCard component and make the passed attributes top level with depracation --- .../src/components/block-card/index.js | 24 ++++++++++++------- .../src/components/block-inspector/index.js | 2 +- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/packages/block-editor/src/components/block-card/index.js b/packages/block-editor/src/components/block-card/index.js index 53e102a745373..60f8616b5f49d 100644 --- a/packages/block-editor/src/components/block-card/index.js +++ b/packages/block-editor/src/components/block-card/index.js @@ -1,21 +1,27 @@ +/** + * WordPress dependencies + */ +import deprecated from '@wordpress/deprecated'; + /** * Internal dependencies */ import BlockIcon from '../block-icon'; -import BlockTitle from '../block-title'; -import BlockDescription from '../block-description'; -function BlockCard( { clientId, blockType } ) { - const props = ( clientId && { clientId } ) || blockType; +function BlockCard( { title, icon, description, blockType } ) { + if ( blockType ) { + deprecated( '`blockType` property in `BlockCard component`', { + alternative: '`title, icon and description` properties', + } ); + ( { title, icon, description } = blockType ); + } return (
- +
-

- -

+

{ title }

- + { description }
diff --git a/packages/block-editor/src/components/block-inspector/index.js b/packages/block-editor/src/components/block-inspector/index.js index f7bfffefe5723..be2433edbe39d 100644 --- a/packages/block-editor/src/components/block-inspector/index.js +++ b/packages/block-editor/src/components/block-inspector/index.js @@ -67,7 +67,7 @@ const BlockInspector = ( { return (
- + { hasBlockStyles && (
From 1647ae0a2944bc35eac4e202211d43923da118b6 Mon Sep 17 00:00:00 2001 From: ntsekouras Date: Thu, 10 Dec 2020 11:09:30 +0200 Subject: [PATCH 03/32] remove BlockDescription --- packages/block-editor/README.md | 25 --------------- .../components/block-description/README.md | 1 - .../src/components/block-description/index.js | 31 ------------------- packages/block-editor/src/components/index.js | 1 - 4 files changed, 58 deletions(-) delete mode 100644 packages/block-editor/src/components/block-description/README.md delete mode 100644 packages/block-editor/src/components/block-description/index.js diff --git a/packages/block-editor/README.md b/packages/block-editor/README.md index e422459abee4b..1ea44b5b982cd 100644 --- a/packages/block-editor/README.md +++ b/packages/block-editor/README.md @@ -118,31 +118,6 @@ _Parameters_ Undocumented declaration. -# **BlockDescription** - -Renders the block's configured description as a string, or empty if the description -cannot be determined. - -_Usage_ - -```jsx - -``` - -```jsx - -``` - -_Parameters_ - -- _props_ `Object`: -- _props.clientId_ `string`: Client ID of block. -- _props.description_ `string`: Description override. - -_Returns_ - -- `?string`: Block Description. - # **BlockEdit** Undocumented declaration. diff --git a/packages/block-editor/src/components/block-description/README.md b/packages/block-editor/src/components/block-description/README.md deleted file mode 100644 index 70b786d12ed05..0000000000000 --- a/packages/block-editor/src/components/block-description/README.md +++ /dev/null @@ -1 +0,0 @@ -// TODO diff --git a/packages/block-editor/src/components/block-description/index.js b/packages/block-editor/src/components/block-description/index.js deleted file mode 100644 index 9d74d00302399..0000000000000 --- a/packages/block-editor/src/components/block-description/index.js +++ /dev/null @@ -1,31 +0,0 @@ -/** - * WordPress dependencies - */ -import { useSelect } from '@wordpress/data'; - -/** - * Renders the block's configured description as a string, or empty if the description - * cannot be determined. - * - * @example - * - * ```jsx - * - * ``` - * ```jsx - * - * ``` - * @param {Object} props - * @param {string} props.clientId Client ID of block. - * @param {string} props.description Description override. - * @return {?string} Block Description. - */ -export default function BlockDescription( { clientId, description } ) { - const { description: blockDescription } = useSelect( - ( select ) => - select( 'core/blocks' ).getBlockTypeWithVariationInfo( clientId ) || - {}, - [ clientId ] - ); - return description || blockDescription || null; -} diff --git a/packages/block-editor/src/components/index.js b/packages/block-editor/src/components/index.js index 68bbd56ef097b..3e845204bed82 100644 --- a/packages/block-editor/src/components/index.js +++ b/packages/block-editor/src/components/index.js @@ -89,7 +89,6 @@ export { export { default as BlockSettingsMenu } from './block-settings-menu'; export { default as BlockSettingsMenuControls } from './block-settings-menu-controls'; export { default as BlockTitle } from './block-title'; -export { default as BlockDescription } from './block-description'; export { default as BlockToolbar } from './block-toolbar'; export { default as CopyHandler, From 4d5b176e970f18446284ca92155cccc4cc3976aa Mon Sep 17 00:00:00 2001 From: ntsekouras Date: Thu, 10 Dec 2020 11:22:55 +0200 Subject: [PATCH 04/32] change InserterPreviewPanel to use BlockCard with passing top level properties --- .../src/components/inserter/preview-panel.js | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/packages/block-editor/src/components/inserter/preview-panel.js b/packages/block-editor/src/components/inserter/preview-panel.js index 11c87d647097d..3242ca306ffae 100644 --- a/packages/block-editor/src/components/inserter/preview-panel.js +++ b/packages/block-editor/src/components/inserter/preview-panel.js @@ -16,11 +16,13 @@ import BlockCard from '../block-card'; import BlockPreview from '../block-preview'; function InserterPreviewPanel( { item } ) { - const hoveredItemBlockType = getBlockType( item.name ); + const { name, title, icon, description, initialAttributes } = item; + const hoveredItemBlockType = getBlockType( name ); + const isReusable = isReusableBlock( item ); return (
- { isReusableBlock( item ) || hoveredItemBlockType.example ? ( + { isReusable || hoveredItemBlockType.example ? (
@@ -53,7 +52,13 @@ function InserterPreviewPanel( { item } ) {
) }
- { ! isReusableBlock( item ) && } + { ! isReusable && ( + + ) }
); } From 23d0f61aa0d73c482ce743aded2a983266e8574a Mon Sep 17 00:00:00 2001 From: ntsekouras Date: Thu, 10 Dec 2020 13:10:59 +0200 Subject: [PATCH 05/32] create new custom hook for block's display information --- .../developers/data/data-core-blocks.md | 4 ++ packages/block-editor/src/components/index.js | 1 + .../README.md | 6 +++ .../index.js | 54 +++++++++++++++++++ packages/blocks/src/store/selectors.js | 26 ++++++++- 5 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 packages/block-editor/src/components/use-matching-variation-information/README.md create mode 100644 packages/block-editor/src/components/use-matching-variation-information/index.js diff --git a/docs/designers-developers/developers/data/data-core-blocks.md b/docs/designers-developers/developers/data/data-core-blocks.md index a96165580d8f6..f11f52120a4b6 100644 --- a/docs/designers-developers/developers/data/data-core-blocks.md +++ b/docs/designers-developers/developers/data/data-core-blocks.md @@ -6,6 +6,10 @@ Namespace: `core/blocks`. +# **getBlockDisplayInformation** + +Undocumented declaration. + # **getBlockStyles** Returns block styles by block name. diff --git a/packages/block-editor/src/components/index.js b/packages/block-editor/src/components/index.js index 3e845204bed82..b87e9975e47f0 100644 --- a/packages/block-editor/src/components/index.js +++ b/packages/block-editor/src/components/index.js @@ -118,6 +118,7 @@ export { export { default as Warning } from './warning'; export { default as WritingFlow } from './writing-flow'; export { useCanvasClickRedirect as __unstableUseCanvasClickRedirect } from './use-canvas-click-redirect'; +export { useMatchingVariationInformation as __experimentalUseMatchingVariationInformation } from './use-matching-variation-information'; /* * State Related Components diff --git a/packages/block-editor/src/components/use-matching-variation-information/README.md b/packages/block-editor/src/components/use-matching-variation-information/README.md new file mode 100644 index 0000000000000..203f40425100e --- /dev/null +++ b/packages/block-editor/src/components/use-matching-variation-information/README.md @@ -0,0 +1,6 @@ +`useMatchingVariationInformation` +=========== + +`useMatchingVariationInformation` + +# TODO diff --git a/packages/block-editor/src/components/use-matching-variation-information/index.js b/packages/block-editor/src/components/use-matching-variation-information/index.js new file mode 100644 index 0000000000000..8accfb8f91e24 --- /dev/null +++ b/packages/block-editor/src/components/use-matching-variation-information/index.js @@ -0,0 +1,54 @@ +/** + * WordPress dependencies + */ +import { useSelect } from '@wordpress/data'; + +/** + * @typedef {Object} BlockDisplayInformation Contains block's information for display reasons. + * @property {string} title Block's title or block variation match's title, if found. + * @property {JSX.Element} icon Block's icon or block variation match's icon, if found. + * @property {string} description Block's description or block variation match's description, if found. + */ + +/** + * Hook used to try to find a matching block variation and return + * the appropriate information for display reasons. In order to + * to try to find a match we need to things: + * 1. Block's client id to extract it's current attributes. + * 2. Block should have in it's settings a `variationMatcher` function. + * + * If for any reason a block variaton match cannot be found, + * the returned information come from the Block Type. + * + * @param {string} clientId Block's client id. + * @return {BlockDisplayInformation} Block's display information. + * + */ + +// TODO write jsdoc example +// TODO write tests +export default function useMatchingVariationInformation( clientId ) { + const { attributes, name } = useSelect( + ( select ) => { + if ( ! clientId ) return {}; + const { getBlockName, getBlockAttributes } = select( + 'core/block-editor' + ); + return { + attributes: getBlockAttributes( clientId ), + name: getBlockName( clientId ), + }; + }, + [ clientId ] + ); + const displayInformation = useSelect( + ( select ) => { + if ( ! ( name && attributes ) ) return null; + const { getBlockDisplayInformation } = select( 'core/blocks' ); + return getBlockDisplayInformation( name, attributes ); + }, + [ name, attributes ] + ); + + return displayInformation; +} diff --git a/packages/blocks/src/store/selectors.js b/packages/blocks/src/store/selectors.js index 1136aa306d23d..2eddaf162cca5 100644 --- a/packages/blocks/src/store/selectors.js +++ b/packages/blocks/src/store/selectors.js @@ -106,7 +106,31 @@ export function getBlockVariations( state, blockName, scope ) { } ); } -// TODO jsdoc and experimental and tests +// TODO check createSelector +// TODOjsdoc +// TODO tests +// TODO check performance +export const getBlockDisplayInformation = ( state, name, attributes ) => { + const variations = state.blockVariations[ name ]; + const blockType = getBlockType( state, name ); + const blockTypeInfo = { + title: blockType.title, + icon: blockType.icon, + description: blockType.description, + }; + if ( ! variations || ! blockType?.variationMatcher ) return blockTypeInfo; + const match = variations.find( ( variation ) => + blockType.variationMatcher( attributes, variation ) + ); + if ( ! match ) return blockTypeInfo; + return { + title: match.title || blockType.title, + icon: match.icon || blockType.icon, + description: match.description || blockType.description, + }; +}; + +// TODO remove export const getBlockTypeWithVariationInfo = createRegistrySelector( ( select ) => ( state, clientId ) => { const { From 93013a8850955aa21825ec464796667507ee7ba1 Mon Sep 17 00:00:00 2001 From: ntsekouras Date: Thu, 10 Dec 2020 13:12:05 +0200 Subject: [PATCH 06/32] use new hook in BlockInspector --- .../src/components/block-inspector/index.js | 30 ++++++++++++++----- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/packages/block-editor/src/components/block-inspector/index.js b/packages/block-editor/src/components/block-inspector/index.js index be2433edbe39d..998b0869c0c41 100644 --- a/packages/block-editor/src/components/block-inspector/index.js +++ b/packages/block-editor/src/components/block-inspector/index.js @@ -25,6 +25,8 @@ import BlockStyles from '../block-styles'; import MultiSelectionInspector from '../multi-selection-inspector'; import DefaultStylePicker from '../default-style-picker'; import BlockVariationTransforms from '../block-variation-transforms'; +import useMatchingVariationInformation from '../use-matching-variation-information'; + const BlockInspector = ( { blockType, count, @@ -64,22 +66,36 @@ const BlockInspector = ( { } return null; } + return ( + + ); +}; +const BlockInspectorSingleBlock = ( { + clientId, + blockName, + hasBlockStyles, + bubblesVirtually, +} ) => { + const blockInformation = useMatchingVariationInformation( clientId ); return (
- - + + { hasBlockStyles && (
- + { hasBlockSupport( - blockType.name, + blockName, 'defaultStylePicker', true - ) && ( - - ) } + ) && }
) } From 5fab0e58554f3ab83fd575003fe0685993f2afbe Mon Sep 17 00:00:00 2001 From: ntsekouras Date: Thu, 10 Dec 2020 14:09:23 +0200 Subject: [PATCH 07/32] revert BlockIcon and augment BlockTitle --- packages/block-editor/README.md | 1 - .../src/components/block-icon/index.js | 25 +++------ .../src/components/block-title/index.js | 52 ++++++++++++++++--- .../index.js | 1 - 4 files changed, 51 insertions(+), 28 deletions(-) diff --git a/packages/block-editor/README.md b/packages/block-editor/README.md index 1ea44b5b982cd..cfadf407b3b65 100644 --- a/packages/block-editor/README.md +++ b/packages/block-editor/README.md @@ -201,7 +201,6 @@ _Parameters_ - _props_ `Object`: - _props.clientId_ `string`: Client ID of block. -- _props.title_ `string`: Title override. _Returns_ diff --git a/packages/block-editor/src/components/block-icon/index.js b/packages/block-editor/src/components/block-icon/index.js index 2f8cfab88f309..f605e7f375d5d 100644 --- a/packages/block-editor/src/components/block-icon/index.js +++ b/packages/block-editor/src/components/block-icon/index.js @@ -6,37 +6,24 @@ import classnames from 'classnames'; /** * WordPress dependencies */ -import { useSelect } from '@wordpress/data'; import { Icon } from '@wordpress/components'; import { blockDefault } from '@wordpress/icons'; -export default function BlockIcon( { - clientId, - icon, - showColors = false, - className, -} ) { +export default function BlockIcon( { icon, showColors = false, className } ) { if ( icon?.src === 'block-default' ) { icon = { src: blockDefault, }; } - const { icon: blockIcon } = useSelect( - ( select ) => - select( 'core/blocks' ).getBlockTypeWithVariationInfo( clientId ) || - {}, - [ clientId ] - ); - if ( blockIcon && ! icon ) { - icon = blockIcon; - } - const renderedIcon = ; + + const renderedIcon = ; const style = showColors ? { - backgroundColor: icon?.background, - color: icon?.foreground, + backgroundColor: icon && icon.background, + color: icon && icon.foreground, } : {}; + return ( * ``` + * * @param {Object} props * @param {string} props.clientId Client ID of block. - * @param {string} props.title Title override. + * * @return {?string} Block title. */ -export default function BlockTitle( { clientId, title } ) { - const { title: blockTitle } = useSelect( - ( select ) => - select( 'core/blocks' ).getBlockTypeWithVariationInfo( clientId ) || - {}, +export default function BlockTitle( { clientId } ) { + const { attributes, name } = useSelect( + ( select ) => { + if ( ! clientId ) { + return {}; + } + const { getBlockName, getBlockAttributes } = select( + 'core/block-editor' + ); + return { + attributes: getBlockAttributes( clientId ), + name: getBlockName( clientId ), + }; + }, [ clientId ] ); - return title || blockTitle || null; + + const blockInformation = useSelect( + ( select ) => { + if ( ! ( name && attributes ) ) return null; + const { getBlockDisplayInformation } = select( 'core/blocks' ); + return getBlockDisplayInformation( name, attributes ); + }, + [ name, attributes ] + ); + if ( ! blockInformation ) return null; + const blockType = getBlockType( name ); + const label = getBlockLabel( blockType, attributes ); + // Label will fallback to the title if no label is defined for the + // current label context. We do not want "Paragraph: Paragraph". + // If label is defined we prioritize it over possible possible + // block variation match title. + if ( label !== blockType.title ) { + return `${ blockType.title }: ${ truncate( label, { length: 15 } ) }`; + } + return blockInformation.title; } diff --git a/packages/block-editor/src/components/use-matching-variation-information/index.js b/packages/block-editor/src/components/use-matching-variation-information/index.js index 8accfb8f91e24..7c803a8da2510 100644 --- a/packages/block-editor/src/components/use-matching-variation-information/index.js +++ b/packages/block-editor/src/components/use-matching-variation-information/index.js @@ -49,6 +49,5 @@ export default function useMatchingVariationInformation( clientId ) { }, [ name, attributes ] ); - return displayInformation; } From 42271d8c6ec4f7c1ae280a94a7a2edb0a6379045 Mon Sep 17 00:00:00 2001 From: ntsekouras Date: Thu, 10 Dec 2020 14:23:35 +0200 Subject: [PATCH 08/32] Navigation List View update --- .../block-navigation/block-select-button.js | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/packages/block-editor/src/components/block-navigation/block-select-button.js b/packages/block-editor/src/components/block-navigation/block-select-button.js index 33faabde47813..fe107cc7a6db5 100644 --- a/packages/block-editor/src/components/block-navigation/block-select-button.js +++ b/packages/block-editor/src/components/block-navigation/block-select-button.js @@ -6,6 +6,10 @@ import classnames from 'classnames'; /** * WordPress dependencies */ +import { + __experimentalGetBlockLabel as getBlockLabel, + getBlockType, +} from '@wordpress/blocks'; import { Button, VisuallyHidden } from '@wordpress/components'; import { useInstanceId } from '@wordpress/compose'; import { forwardRef } from '@wordpress/element'; @@ -15,13 +19,13 @@ import { __ } from '@wordpress/i18n'; * Internal dependencies */ import BlockIcon from '../block-icon'; -import BlockTitle from '../block-title'; +import useMatchingVariationInformation from '../use-matching-variation-information'; import { getBlockPositionDescription } from './utils'; function BlockNavigationBlockSelectButton( { className, - block: { clientId }, + block: { clientId, name, attributes }, isSelected, onClick, position, @@ -35,8 +39,15 @@ function BlockNavigationBlockSelectButton( }, ref ) { + const blockInformation = useMatchingVariationInformation( clientId ); const instanceId = useInstanceId( BlockNavigationBlockSelectButton ); const descriptionId = `block-navigation-block-select-button__${ instanceId }`; + const blockType = getBlockType( name ); + const blockLabel = getBlockLabel( blockType, attributes ); + // If label is defined we prioritize it over possible possible + // block variation match title. + const blockDisplayName = + blockLabel !== blockType.title ? blockLabel : blockInformation.title; const blockPositionDescription = getBlockPositionDescription( position, siblingBlockCount, @@ -59,8 +70,8 @@ function BlockNavigationBlockSelectButton( onDragEnd={ onDragEnd } draggable={ draggable } > - - + + { blockDisplayName } { isSelected && ( { __( '(selected block)' ) } From c94f11cda2ee45eeffa0ff2330566fd08c73f4cd Mon Sep 17 00:00:00 2001 From: ntsekouras Date: Thu, 10 Dec 2020 14:33:21 +0200 Subject: [PATCH 09/32] remove previous selector --- .../developers/data/data-core-blocks.md | 4 -- packages/blocks/src/store/selectors.js | 49 ------------------- 2 files changed, 53 deletions(-) diff --git a/docs/designers-developers/developers/data/data-core-blocks.md b/docs/designers-developers/developers/data/data-core-blocks.md index f11f52120a4b6..169d32de487d5 100644 --- a/docs/designers-developers/developers/data/data-core-blocks.md +++ b/docs/designers-developers/developers/data/data-core-blocks.md @@ -63,10 +63,6 @@ _Returns_ - `Array`: Block Types. -# **getBlockTypeWithVariationInfo** - -Undocumented declaration. - # **getBlockVariations** Returns block variations by block name. diff --git a/packages/blocks/src/store/selectors.js b/packages/blocks/src/store/selectors.js index 2eddaf162cca5..0af96d91b2cb8 100644 --- a/packages/blocks/src/store/selectors.js +++ b/packages/blocks/src/store/selectors.js @@ -12,19 +12,8 @@ import { includes, map, some, - truncate, } from 'lodash'; -/** - * WordPress dependencies - */ -import { createRegistrySelector } from '@wordpress/data'; - -/** - * Internal dependencies - */ -import { __experimentalGetBlockLabel as getBlockLabel } from '../api'; - /** @typedef {import('../api/registration').WPBlockVariation} WPBlockVariation */ /** @typedef {import('../api/registration').WPBlockVariationScope} WPBlockVariationScope */ /** @typedef {import('./reducer').WPBlockCategory} WPBlockCategory */ @@ -130,44 +119,6 @@ export const getBlockDisplayInformation = ( state, name, attributes ) => { }; }; -// TODO remove -export const getBlockTypeWithVariationInfo = createRegistrySelector( - ( select ) => ( state, clientId ) => { - const { - __unstableGetBlockWithoutInnerBlocks, - getSelectedBlockClientId, - } = select( 'core/block-editor' ); - const _clientId = clientId || getSelectedBlockClientId(); - const { name, attributes } = - __unstableGetBlockWithoutInnerBlocks( _clientId ) || {}; - - if ( ! name ) return null; - const variations = state.blockVariations[ name ]; - const blockType = getBlockType( state, name ); - - const label = getBlockLabel( blockType, attributes ); - // Label will often fall back to the title if no label is defined for the - // current label context. We do not want "Paragraph: Paragraph". - if ( label !== blockType.title ) { - blockType.title = `${ blockType.title }: ${ truncate( label, { - length: 15, - } ) }`; - } - - if ( ! variations || ! blockType?.variationMatcher ) return blockType; - const match = variations.find( ( variation ) => - blockType.variationMatcher( attributes, variation ) - ); - if ( ! match ) return blockType; - return { - ...blockType, - title: match.title || blockType.title, - icon: match.icon || blockType.icon, - description: match.description || blockType.description, - }; - } -); - /** * Returns the default block variation for the given block type. * When there are multiple variations annotated as the default one, From 9926c72c269e0500e908019e9cc881758c0c4a89 Mon Sep 17 00:00:00 2001 From: ntsekouras Date: Thu, 10 Dec 2020 16:56:40 +0200 Subject: [PATCH 10/32] refactor BlockSwitcher to function component and use the new hook --- .../block-switcher/block-styles-menu.js | 36 ++ .../src/components/block-switcher/index.js | 348 +++++++----------- .../block-switcher/preview-block-popover.js | 57 +++ 3 files changed, 221 insertions(+), 220 deletions(-) create mode 100644 packages/block-editor/src/components/block-switcher/block-styles-menu.js create mode 100644 packages/block-editor/src/components/block-switcher/preview-block-popover.js diff --git a/packages/block-editor/src/components/block-switcher/block-styles-menu.js b/packages/block-editor/src/components/block-switcher/block-styles-menu.js new file mode 100644 index 0000000000000..01d47a66e462f --- /dev/null +++ b/packages/block-editor/src/components/block-switcher/block-styles-menu.js @@ -0,0 +1,36 @@ +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; +import { MenuGroup } from '@wordpress/components'; +import { useState } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import BlockStyles from '../block-styles'; +import PreviewBlockPopover from './preview-block-popover'; + +const BlockStylesMenu = ( { hoveredBlock, onSwitch } ) => { + const [ hoveredClassName, setHoveredClassName ] = useState(); + return ( + + { hoveredClassName && ( + + ) } + + + ); +}; +export default BlockStylesMenu; diff --git a/packages/block-editor/src/components/block-switcher/index.js b/packages/block-editor/src/components/block-switcher/index.js index e1444dcde5468..6694ac1795092 100644 --- a/packages/block-editor/src/components/block-switcher/index.js +++ b/packages/block-editor/src/components/block-switcher/index.js @@ -1,7 +1,7 @@ /** * External dependencies */ -import { castArray, filter, mapKeys, orderBy, uniq, map } from 'lodash'; +import { castArray, filter, mapKeys, orderBy, uniq } from 'lodash'; /** * WordPress dependencies @@ -12,247 +12,155 @@ import { ToolbarButton, ToolbarGroup, ToolbarItem, - MenuGroup, - Popover, } from '@wordpress/components'; import { - getBlockType, getPossibleBlockTransformations, switchToBlockType, - cloneBlock, - getBlockFromExample, store as blocksStore, } from '@wordpress/blocks'; -import { Component } from '@wordpress/element'; -import { withSelect, withDispatch } from '@wordpress/data'; -import { compose } from '@wordpress/compose'; +import { useSelect, useDispatch } from '@wordpress/data'; import { stack } from '@wordpress/icons'; /** * Internal dependencies */ import BlockIcon from '../block-icon'; -import BlockStyles from '../block-styles'; -import BlockPreview from '../block-preview'; import BlockTransformationsMenu from './block-transformations-menu'; +import BlockStylesMenu from './block-styles-menu'; +import useMatchingVariationInformation from '../use-matching-variation-information'; -function PreviewBlockPopover( { hoveredBlock, hoveredClassName } ) { - const hoveredBlockType = getBlockType( hoveredBlock.name ); - return ( -
-
- -
-
- { __( 'Preview' ) } -
- -
-
-
-
+const BlockSwitcher = ( { clientIds } ) => { + const blocks = useSelect( + ( select ) => + select( 'core/block-editor' ).getBlocksByClientId( clientIds ), + [ clientIds ] ); -} - -export class BlockSwitcher extends Component { - constructor() { - super( ...arguments ); - this.state = { - hoveredClassName: null, - }; - this.onHoverClassName = this.onHoverClassName.bind( this ); - } - - onHoverClassName( className ) { - this.setState( { hoveredClassName: className } ); - } - - render() { - const { - blocks, - onTransform, - inserterItems, - hasBlockStyles, - } = this.props; - const { hoveredClassName } = this.state; - - if ( ! Array.isArray( blocks ) || ! blocks.length ) { - return null; - } + return blocks?.length ? ( + + ) : null; +}; - const [ hoveredBlock ] = blocks; - const itemsByName = mapKeys( inserterItems, ( { name } ) => name ); - const possibleBlockTransformations = orderBy( - filter( - getPossibleBlockTransformations( blocks ), - ( block ) => block && !! itemsByName[ block.name ] - ), - ( block ) => itemsByName[ block.name ].frecency, - 'desc' - ); - - // When selection consists of blocks of multiple types, display an - // appropriate icon to communicate the non-uniformity. - const isSelectionOfSameType = - uniq( map( blocks, 'name' ) ).length === 1; - - const blockIconProps = isSelectionOfSameType - ? { clientId: hoveredBlock.clientId } - : { icon: stack }; - - const hasPossibleBlockTransformations = !! possibleBlockTransformations.length; - - if ( ! hasBlockStyles && ! hasPossibleBlockTransformations ) { - return ( - - } - /> - +const BlockSwitcherDropdownMenu = ( { clientIds, blocks } ) => { + const { replaceBlocks } = useDispatch( 'core/block-editor' ); + const { inserterItems, hasBlockStyles } = useSelect( + ( select ) => { + const { getBlockRootClientId, getInserterItems } = select( + 'core/block-editor' + ); + const { getBlockStyles } = select( blocksStore ); + const rootClientId = getBlockRootClientId( + castArray( clientIds )[ 0 ] ); - } + const firstBlock = blocks.length === 1 ? blocks[ 0 ] : null; + const styles = firstBlock && getBlockStyles( firstBlock.name ); + return { + inserterItems: getInserterItems( rootClientId ), + hasBlockStyles: !! styles?.length, + }; + }, + [ clientIds, blocks ] + ); + const [ hoveredBlock ] = blocks; + const blockInformation = useMatchingVariationInformation( + hoveredBlock.clientId + ); + const onTransform = ( name ) => + replaceBlocks( clientIds, switchToBlockType( blocks, name ) ); - const blockSwitcherLabel = - 1 === blocks.length - ? __( 'Change block type or style' ) - : sprintf( - /* translators: %s: number of blocks. */ - _n( - 'Change type of %d block', - 'Change type of %d blocks', - blocks.length - ), - blocks.length - ); + // When selection consists of blocks of multiple types, display an + // appropriate icon to communicate the non-uniformity. + const isSelectionOfSameType = + uniq( blocks.map( ( { name } ) => name ) ).length === 1; + const icon = isSelectionOfSameType ? blockInformation.icon : stack; + const itemsByName = mapKeys( inserterItems, ( { name } ) => name ); + const possibleBlockTransformations = orderBy( + filter( + getPossibleBlockTransformations( blocks ), + ( block ) => block && !! itemsByName[ block.name ] + ), + ( block ) => itemsByName[ block.name ].frecency, + 'desc' + ); + const hasPossibleBlockTransformations = !! possibleBlockTransformations.length; + if ( ! hasBlockStyles && ! hasPossibleBlockTransformations ) { return ( - - { ( toggleProps ) => ( - - } - toggleProps={ toggleProps } - menuProps={ { orientation: 'both' } } - > - { ( { onClose } ) => - ( hasBlockStyles || - hasPossibleBlockTransformations ) && ( -
- { hasPossibleBlockTransformations && ( - { - onTransform( blocks, name ); - onClose(); - } } - /> - ) } - { hasBlockStyles && ( - - { hoveredClassName !== null && ( - - ) } - - - ) } -
- ) - } -
- ) } -
+ } + />
); } -} -export default compose( - withSelect( ( select, { clientIds } ) => { - const { - getBlocksByClientId, - getBlockRootClientId, - getInserterItems, - } = select( 'core/block-editor' ); - const { getBlockStyles } = select( blocksStore ); - const rootClientId = getBlockRootClientId( - castArray( clientIds )[ 0 ] - ); - const blocks = getBlocksByClientId( clientIds ); - const firstBlock = blocks && blocks.length === 1 ? blocks[ 0 ] : null; - const styles = firstBlock && getBlockStyles( firstBlock.name ); - return { - blocks, - inserterItems: getInserterItems( rootClientId ), - hasBlockStyles: styles && styles.length > 0, - }; - } ), - withDispatch( ( dispatch, ownProps ) => ( { - onTransform( blocks, name ) { - dispatch( 'core/block-editor' ).replaceBlocks( - ownProps.clientIds, - switchToBlockType( blocks, name ) - ); - }, - } ) ) -)( BlockSwitcher ); + const blockSwitcherLabel = + 1 === blocks.length + ? __( 'Change block type or style' ) + : sprintf( + /* translators: %s: number of blocks. */ + _n( + 'Change type of %d block', + 'Change type of %d blocks', + blocks.length + ), + blocks.length + ); + + return ( + + + { ( toggleProps ) => ( + + } + toggleProps={ toggleProps } + menuProps={ { orientation: 'both' } } + > + { ( { onClose } ) => + ( hasBlockStyles || + hasPossibleBlockTransformations ) && ( +
+ { hasPossibleBlockTransformations && ( + { + onTransform( name ); + onClose(); + } } + /> + ) } + { hasBlockStyles && ( + + ) } +
+ ) + } +
+ ) } +
+
+ ); +}; + +export default BlockSwitcher; diff --git a/packages/block-editor/src/components/block-switcher/preview-block-popover.js b/packages/block-editor/src/components/block-switcher/preview-block-popover.js new file mode 100644 index 0000000000000..4e8e0cd0b6684 --- /dev/null +++ b/packages/block-editor/src/components/block-switcher/preview-block-popover.js @@ -0,0 +1,57 @@ +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; +import { Popover } from '@wordpress/components'; +import { + getBlockType, + cloneBlock, + getBlockFromExample, +} from '@wordpress/blocks'; +/** + * Internal dependencies + */ +import BlockPreview from '../block-preview'; + +export default function PreviewBlockPopover( { + hoveredBlock, + hoveredClassName, +} ) { + const hoveredBlockType = getBlockType( hoveredBlock.name ); + return ( +
+
+ +
+
+ { __( 'Preview' ) } +
+ +
+
+
+
+ ); +} From ae9f53a62b6a8e56989f5e0f81c7e92b3c12c043 Mon Sep 17 00:00:00 2001 From: ntsekouras Date: Thu, 10 Dec 2020 17:17:39 +0200 Subject: [PATCH 11/32] change hook --- .../block-navigation/block-select-button.js | 2 +- .../index.js | 25 ++++++++----------- 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/packages/block-editor/src/components/block-navigation/block-select-button.js b/packages/block-editor/src/components/block-navigation/block-select-button.js index fe107cc7a6db5..e1fb6e0d2cf9f 100644 --- a/packages/block-editor/src/components/block-navigation/block-select-button.js +++ b/packages/block-editor/src/components/block-navigation/block-select-button.js @@ -47,7 +47,7 @@ function BlockNavigationBlockSelectButton( // If label is defined we prioritize it over possible possible // block variation match title. const blockDisplayName = - blockLabel !== blockType.title ? blockLabel : blockInformation.title; + blockLabel !== blockType.title ? blockLabel : blockInformation?.title; const blockPositionDescription = getBlockPositionDescription( position, siblingBlockCount, diff --git a/packages/block-editor/src/components/use-matching-variation-information/index.js b/packages/block-editor/src/components/use-matching-variation-information/index.js index 7c803a8da2510..c24b2c35f3055 100644 --- a/packages/block-editor/src/components/use-matching-variation-information/index.js +++ b/packages/block-editor/src/components/use-matching-variation-information/index.js @@ -28,26 +28,21 @@ import { useSelect } from '@wordpress/data'; // TODO write jsdoc example // TODO write tests export default function useMatchingVariationInformation( clientId ) { - const { attributes, name } = useSelect( + return useSelect( ( select ) => { - if ( ! clientId ) return {}; + if ( ! clientId ) return null; const { getBlockName, getBlockAttributes } = select( 'core/block-editor' ); - return { - attributes: getBlockAttributes( clientId ), - name: getBlockName( clientId ), - }; - }, - [ clientId ] - ); - const displayInformation = useSelect( - ( select ) => { - if ( ! ( name && attributes ) ) return null; const { getBlockDisplayInformation } = select( 'core/blocks' ); - return getBlockDisplayInformation( name, attributes ); + const attributes = getBlockAttributes( clientId ); + const name = getBlockName( clientId ); + return ( + name && + attributes && + getBlockDisplayInformation( name, attributes ) + ); }, - [ name, attributes ] + [ clientId ] ); - return displayInformation; } From 1697329f5329084a97e312b79cd8474b9e07b133 Mon Sep 17 00:00:00 2001 From: ntsekouras Date: Fri, 11 Dec 2020 12:52:46 +0200 Subject: [PATCH 12/32] use CreateSelector and declare WPBlockDisplayInformation typedef --- .../index.js | 9 +--- packages/blocks/src/api/registration.js | 10 ++++ packages/blocks/src/store/selectors.js | 54 +++++++++++-------- 3 files changed, 45 insertions(+), 28 deletions(-) diff --git a/packages/block-editor/src/components/use-matching-variation-information/index.js b/packages/block-editor/src/components/use-matching-variation-information/index.js index c24b2c35f3055..067a7fa935180 100644 --- a/packages/block-editor/src/components/use-matching-variation-information/index.js +++ b/packages/block-editor/src/components/use-matching-variation-information/index.js @@ -3,12 +3,7 @@ */ import { useSelect } from '@wordpress/data'; -/** - * @typedef {Object} BlockDisplayInformation Contains block's information for display reasons. - * @property {string} title Block's title or block variation match's title, if found. - * @property {JSX.Element} icon Block's icon or block variation match's icon, if found. - * @property {string} description Block's description or block variation match's description, if found. - */ +/** @typedef {import('@wordpress/blocks').WPBlockDisplayInformation} WPBlockDisplayInformation */ /** * Hook used to try to find a matching block variation and return @@ -21,7 +16,7 @@ import { useSelect } from '@wordpress/data'; * the returned information come from the Block Type. * * @param {string} clientId Block's client id. - * @return {BlockDisplayInformation} Block's display information. + * @return {WPBlockDisplayInformation} Block's display information. * */ diff --git a/packages/blocks/src/api/registration.js b/packages/blocks/src/api/registration.js index d628cdfae0306..9e64ebb2a01c5 100644 --- a/packages/blocks/src/api/registration.js +++ b/packages/blocks/src/api/registration.js @@ -126,6 +126,16 @@ import { store as blocksStore } from '../store'; * then no preview is shown. */ +/** + * A subset of `WPBlock` type. Contains basic block's information for display reasons. + * + * @typedef {Object} WPBlockDisplayInformation + * + * @property {string} title Human-readable block type label. + * @property {JSX.Element} icon Block type icon. + * @property {string} description A detailed block type description. + */ + /** * Mapping of legacy category slugs to their latest normal values, used to * accommodate updates of the default set of block categories. diff --git a/packages/blocks/src/store/selectors.js b/packages/blocks/src/store/selectors.js index 0af96d91b2cb8..cce26e1104561 100644 --- a/packages/blocks/src/store/selectors.js +++ b/packages/blocks/src/store/selectors.js @@ -16,6 +16,7 @@ import { /** @typedef {import('../api/registration').WPBlockVariation} WPBlockVariation */ /** @typedef {import('../api/registration').WPBlockVariationScope} WPBlockVariationScope */ +/** @typedef {import('../api/registration').WPBlockDisplayInformation} WPBlockDisplayInformation */ /** @typedef {import('./reducer').WPBlockCategory} WPBlockCategory */ /** @@ -95,29 +96,40 @@ export function getBlockVariations( state, blockName, scope ) { } ); } -// TODO check createSelector -// TODOjsdoc +/** + * Returns an array with the child blocks of a given block. + * + * @param {Object} state Data state. + * @param {string} name Block type name. + * @param {Object} attributes Block's attributes + * + * @return {WPBlockDisplayInformation} Block's display information. + */ // TODO tests // TODO check performance -export const getBlockDisplayInformation = ( state, name, attributes ) => { - const variations = state.blockVariations[ name ]; - const blockType = getBlockType( state, name ); - const blockTypeInfo = { - title: blockType.title, - icon: blockType.icon, - description: blockType.description, - }; - if ( ! variations || ! blockType?.variationMatcher ) return blockTypeInfo; - const match = variations.find( ( variation ) => - blockType.variationMatcher( attributes, variation ) - ); - if ( ! match ) return blockTypeInfo; - return { - title: match.title || blockType.title, - icon: match.icon || blockType.icon, - description: match.description || blockType.description, - }; -}; +export const getBlockDisplayInformation = createSelector( + ( state, name, attributes ) => { + const variations = state.blockVariations[ name ]; + const blockType = getBlockType( state, name ); + const blockTypeInfo = { + title: blockType.title, + icon: blockType.icon, + description: blockType.description, + }; + if ( ! variations || ! blockType?.variationMatcher ) + return blockTypeInfo; + const match = variations.find( ( variation ) => + blockType.variationMatcher( attributes, variation ) + ); + if ( ! match ) return blockTypeInfo; + return { + title: match.title || blockType.title, + icon: match.icon || blockType.icon, + description: match.description || blockType.description, + }; + }, + ( state ) => [ state.blockTypes, state.blockVariations ] +); /** * Returns the default block variation for the given block type. From 0784acf69a5006574c97c215095f81a3331a7de4 Mon Sep 17 00:00:00 2001 From: ntsekouras Date: Tue, 15 Dec 2020 13:55:57 +0200 Subject: [PATCH 13/32] revert BlockSwitcher to handle in separate PR --- .../block-switcher/block-styles-menu.js | 36 -- .../src/components/block-switcher/index.js | 353 +++++++++++------- .../block-switcher/preview-block-popover.js | 57 --- 3 files changed, 225 insertions(+), 221 deletions(-) delete mode 100644 packages/block-editor/src/components/block-switcher/block-styles-menu.js delete mode 100644 packages/block-editor/src/components/block-switcher/preview-block-popover.js diff --git a/packages/block-editor/src/components/block-switcher/block-styles-menu.js b/packages/block-editor/src/components/block-switcher/block-styles-menu.js deleted file mode 100644 index 01d47a66e462f..0000000000000 --- a/packages/block-editor/src/components/block-switcher/block-styles-menu.js +++ /dev/null @@ -1,36 +0,0 @@ -/** - * WordPress dependencies - */ -import { __ } from '@wordpress/i18n'; -import { MenuGroup } from '@wordpress/components'; -import { useState } from '@wordpress/element'; - -/** - * Internal dependencies - */ -import BlockStyles from '../block-styles'; -import PreviewBlockPopover from './preview-block-popover'; - -const BlockStylesMenu = ( { hoveredBlock, onSwitch } ) => { - const [ hoveredClassName, setHoveredClassName ] = useState(); - return ( - - { hoveredClassName && ( - - ) } - - - ); -}; -export default BlockStylesMenu; diff --git a/packages/block-editor/src/components/block-switcher/index.js b/packages/block-editor/src/components/block-switcher/index.js index 6694ac1795092..7ebb59c16cda3 100644 --- a/packages/block-editor/src/components/block-switcher/index.js +++ b/packages/block-editor/src/components/block-switcher/index.js @@ -1,7 +1,7 @@ /** * External dependencies */ -import { castArray, filter, mapKeys, orderBy, uniq } from 'lodash'; +import { castArray, filter, mapKeys, orderBy, uniq, map } from 'lodash'; /** * WordPress dependencies @@ -12,155 +12,252 @@ import { ToolbarButton, ToolbarGroup, ToolbarItem, + MenuGroup, + Popover, } from '@wordpress/components'; import { + getBlockType, getPossibleBlockTransformations, switchToBlockType, + cloneBlock, + getBlockFromExample, store as blocksStore, } from '@wordpress/blocks'; -import { useSelect, useDispatch } from '@wordpress/data'; +import { Component } from '@wordpress/element'; +import { withSelect, withDispatch } from '@wordpress/data'; +import { compose } from '@wordpress/compose'; import { stack } from '@wordpress/icons'; /** * Internal dependencies */ import BlockIcon from '../block-icon'; +import BlockStyles from '../block-styles'; +import BlockPreview from '../block-preview'; import BlockTransformationsMenu from './block-transformations-menu'; -import BlockStylesMenu from './block-styles-menu'; -import useMatchingVariationInformation from '../use-matching-variation-information'; -const BlockSwitcher = ( { clientIds } ) => { - const blocks = useSelect( - ( select ) => - select( 'core/block-editor' ).getBlocksByClientId( clientIds ), - [ clientIds ] +function PreviewBlockPopover( { hoveredBlock, hoveredClassName } ) { + const hoveredBlockType = getBlockType( hoveredBlock.name ); + return ( +
+
+ +
+
+ { __( 'Preview' ) } +
+ +
+
+
+
); - return blocks?.length ? ( - - ) : null; -}; +} -const BlockSwitcherDropdownMenu = ( { clientIds, blocks } ) => { - const { replaceBlocks } = useDispatch( 'core/block-editor' ); - const { inserterItems, hasBlockStyles } = useSelect( - ( select ) => { - const { getBlockRootClientId, getInserterItems } = select( - 'core/block-editor' - ); - const { getBlockStyles } = select( blocksStore ); - const rootClientId = getBlockRootClientId( - castArray( clientIds )[ 0 ] +export class BlockSwitcher extends Component { + constructor() { + super( ...arguments ); + this.state = { + hoveredClassName: null, + }; + this.onHoverClassName = this.onHoverClassName.bind( this ); + } + + onHoverClassName( className ) { + this.setState( { hoveredClassName: className } ); + } + + render() { + const { + blocks, + onTransform, + inserterItems, + hasBlockStyles, + } = this.props; + const { hoveredClassName } = this.state; + + if ( ! Array.isArray( blocks ) || ! blocks.length ) { + return null; + } + + const [ hoveredBlock ] = blocks; + const itemsByName = mapKeys( inserterItems, ( { name } ) => name ); + const possibleBlockTransformations = orderBy( + filter( + getPossibleBlockTransformations( blocks ), + ( block ) => block && !! itemsByName[ block.name ] + ), + ( block ) => itemsByName[ block.name ].frecency, + 'desc' + ); + + // When selection consists of blocks of multiple types, display an + // appropriate icon to communicate the non-uniformity. + const isSelectionOfSameType = + uniq( map( blocks, 'name' ) ).length === 1; + + let icon; + if ( isSelectionOfSameType ) { + const sourceBlockName = hoveredBlock.name; + const blockType = getBlockType( sourceBlockName ); + icon = blockType.icon; + } else { + icon = stack; + } + + const hasPossibleBlockTransformations = !! possibleBlockTransformations.length; + + if ( ! hasBlockStyles && ! hasPossibleBlockTransformations ) { + return ( + + } + /> + ); - const firstBlock = blocks.length === 1 ? blocks[ 0 ] : null; - const styles = firstBlock && getBlockStyles( firstBlock.name ); - return { - inserterItems: getInserterItems( rootClientId ), - hasBlockStyles: !! styles?.length, - }; - }, - [ clientIds, blocks ] - ); - const [ hoveredBlock ] = blocks; - const blockInformation = useMatchingVariationInformation( - hoveredBlock.clientId - ); - const onTransform = ( name ) => - replaceBlocks( clientIds, switchToBlockType( blocks, name ) ); + } - // When selection consists of blocks of multiple types, display an - // appropriate icon to communicate the non-uniformity. - const isSelectionOfSameType = - uniq( blocks.map( ( { name } ) => name ) ).length === 1; - const icon = isSelectionOfSameType ? blockInformation.icon : stack; + const blockSwitcherLabel = + 1 === blocks.length + ? __( 'Change block type or style' ) + : sprintf( + /* translators: %s: number of blocks. */ + _n( + 'Change type of %d block', + 'Change type of %d blocks', + blocks.length + ), + blocks.length + ); - const itemsByName = mapKeys( inserterItems, ( { name } ) => name ); - const possibleBlockTransformations = orderBy( - filter( - getPossibleBlockTransformations( blocks ), - ( block ) => block && !! itemsByName[ block.name ] - ), - ( block ) => itemsByName[ block.name ].frecency, - 'desc' - ); - const hasPossibleBlockTransformations = !! possibleBlockTransformations.length; - if ( ! hasBlockStyles && ! hasPossibleBlockTransformations ) { return ( - } - /> + + { ( toggleProps ) => ( + + } + toggleProps={ toggleProps } + menuProps={ { orientation: 'both' } } + > + { ( { onClose } ) => + ( hasBlockStyles || + hasPossibleBlockTransformations ) && ( +
+ { hasPossibleBlockTransformations && ( + { + onTransform( blocks, name ); + onClose(); + } } + /> + ) } + { hasBlockStyles && ( + + { hoveredClassName !== null && ( + + ) } + + + ) } +
+ ) + } +
+ ) } +
); } +} - const blockSwitcherLabel = - 1 === blocks.length - ? __( 'Change block type or style' ) - : sprintf( - /* translators: %s: number of blocks. */ - _n( - 'Change type of %d block', - 'Change type of %d blocks', - blocks.length - ), - blocks.length - ); - - return ( - - - { ( toggleProps ) => ( - - } - toggleProps={ toggleProps } - menuProps={ { orientation: 'both' } } - > - { ( { onClose } ) => - ( hasBlockStyles || - hasPossibleBlockTransformations ) && ( -
- { hasPossibleBlockTransformations && ( - { - onTransform( name ); - onClose(); - } } - /> - ) } - { hasBlockStyles && ( - - ) } -
- ) - } -
- ) } -
-
- ); -}; - -export default BlockSwitcher; +export default compose( + withSelect( ( select, { clientIds } ) => { + const { + getBlocksByClientId, + getBlockRootClientId, + getInserterItems, + } = select( 'core/block-editor' ); + const { getBlockStyles } = select( blocksStore ); + const rootClientId = getBlockRootClientId( + castArray( clientIds )[ 0 ] + ); + const blocks = getBlocksByClientId( clientIds ); + const firstBlock = blocks && blocks.length === 1 ? blocks[ 0 ] : null; + const styles = firstBlock && getBlockStyles( firstBlock.name ); + return { + blocks, + inserterItems: getInserterItems( rootClientId ), + hasBlockStyles: styles && styles.length > 0, + }; + } ), + withDispatch( ( dispatch, ownProps ) => ( { + onTransform( blocks, name ) { + dispatch( 'core/block-editor' ).replaceBlocks( + ownProps.clientIds, + switchToBlockType( blocks, name ) + ); + }, + } ) ) +)( BlockSwitcher ); diff --git a/packages/block-editor/src/components/block-switcher/preview-block-popover.js b/packages/block-editor/src/components/block-switcher/preview-block-popover.js deleted file mode 100644 index 4e8e0cd0b6684..0000000000000 --- a/packages/block-editor/src/components/block-switcher/preview-block-popover.js +++ /dev/null @@ -1,57 +0,0 @@ -/** - * WordPress dependencies - */ -import { __ } from '@wordpress/i18n'; -import { Popover } from '@wordpress/components'; -import { - getBlockType, - cloneBlock, - getBlockFromExample, -} from '@wordpress/blocks'; -/** - * Internal dependencies - */ -import BlockPreview from '../block-preview'; - -export default function PreviewBlockPopover( { - hoveredBlock, - hoveredClassName, -} ) { - const hoveredBlockType = getBlockType( hoveredBlock.name ); - return ( -
-
- -
-
- { __( 'Preview' ) } -
- -
-
-
-
- ); -} From 88fd61075b690f1f960d626be20883966dd2aef2 Mon Sep 17 00:00:00 2001 From: ntsekouras Date: Tue, 15 Dec 2020 14:58:51 +0200 Subject: [PATCH 14/32] remove getBlockDisplayInformation selector --- .../developers/data/data-core-blocks.md | 4 --- .../src/components/block-title/index.js | 14 ++++---- .../src/components/block-title/test/index.js | 1 + .../index.js | 36 +++++++++++++------ packages/blocks/src/store/selectors.js | 35 ------------------ 5 files changed, 33 insertions(+), 57 deletions(-) diff --git a/docs/designers-developers/developers/data/data-core-blocks.md b/docs/designers-developers/developers/data/data-core-blocks.md index 169d32de487d5..655c4f0d7a339 100644 --- a/docs/designers-developers/developers/data/data-core-blocks.md +++ b/docs/designers-developers/developers/data/data-core-blocks.md @@ -6,10 +6,6 @@ Namespace: `core/blocks`. -# **getBlockDisplayInformation** - -Undocumented declaration. - # **getBlockStyles** Returns block styles by block name. diff --git a/packages/block-editor/src/components/block-title/index.js b/packages/block-editor/src/components/block-title/index.js index 2960d65b1ee9d..527fe561a1eda 100644 --- a/packages/block-editor/src/components/block-title/index.js +++ b/packages/block-editor/src/components/block-title/index.js @@ -12,6 +12,11 @@ import { __experimentalGetBlockLabel as getBlockLabel, } from '@wordpress/blocks'; +/** + * Internal dependencies + */ +import useMatchingVariationInformation from '../use-matching-variation-information'; + /** * Renders the block's configured title as a string, or empty if the title * cannot be determined. @@ -44,14 +49,7 @@ export default function BlockTitle( { clientId } ) { [ clientId ] ); - const blockInformation = useSelect( - ( select ) => { - if ( ! ( name && attributes ) ) return null; - const { getBlockDisplayInformation } = select( 'core/blocks' ); - return getBlockDisplayInformation( name, attributes ); - }, - [ name, attributes ] - ); + const blockInformation = useMatchingVariationInformation( clientId ); if ( ! blockInformation ) return null; const blockType = getBlockType( name ); const label = getBlockLabel( blockType, attributes ); diff --git a/packages/block-editor/src/components/block-title/test/index.js b/packages/block-editor/src/components/block-title/test/index.js index d268699d09668..c597f55faf07c 100644 --- a/packages/block-editor/src/components/block-title/test/index.js +++ b/packages/block-editor/src/components/block-title/test/index.js @@ -42,6 +42,7 @@ jest.mock( '@wordpress/blocks', () => { return title; } }, + getBlockVariations() {}, }; } ); diff --git a/packages/block-editor/src/components/use-matching-variation-information/index.js b/packages/block-editor/src/components/use-matching-variation-information/index.js index 067a7fa935180..61aa6df068cc3 100644 --- a/packages/block-editor/src/components/use-matching-variation-information/index.js +++ b/packages/block-editor/src/components/use-matching-variation-information/index.js @@ -2,6 +2,7 @@ * WordPress dependencies */ import { useSelect } from '@wordpress/data'; +import { getBlockType, getBlockVariations } from '@wordpress/blocks'; /** @typedef {import('@wordpress/blocks').WPBlockDisplayInformation} WPBlockDisplayInformation */ @@ -23,21 +24,36 @@ import { useSelect } from '@wordpress/data'; // TODO write jsdoc example // TODO write tests export default function useMatchingVariationInformation( clientId ) { - return useSelect( + const { name, attributes } = useSelect( ( select ) => { - if ( ! clientId ) return null; + if ( ! clientId ) return {}; const { getBlockName, getBlockAttributes } = select( 'core/block-editor' ); - const { getBlockDisplayInformation } = select( 'core/blocks' ); - const attributes = getBlockAttributes( clientId ); - const name = getBlockName( clientId ); - return ( - name && - attributes && - getBlockDisplayInformation( name, attributes ) - ); + return { + name: getBlockName( clientId ), + attributes: getBlockAttributes( clientId ), + }; }, [ clientId ] ); + const blockType = getBlockType( name ); + if ( ! blockType ) return null; + + const blockTypeInfo = { + title: blockType.title, + icon: blockType.icon, + description: blockType.description, + }; + const variations = getBlockVariations( name ); + if ( ! variations || ! blockType.variationMatcher ) return blockTypeInfo; + const match = variations.find( ( variation ) => + blockType.variationMatcher( attributes, variation ) + ); + if ( ! match ) return blockTypeInfo; + return { + title: match.title || blockType.title, + icon: match.icon || blockType.icon, + description: match.description || blockType.description, + }; } diff --git a/packages/blocks/src/store/selectors.js b/packages/blocks/src/store/selectors.js index cce26e1104561..a9dde842fc117 100644 --- a/packages/blocks/src/store/selectors.js +++ b/packages/blocks/src/store/selectors.js @@ -96,41 +96,6 @@ export function getBlockVariations( state, blockName, scope ) { } ); } -/** - * Returns an array with the child blocks of a given block. - * - * @param {Object} state Data state. - * @param {string} name Block type name. - * @param {Object} attributes Block's attributes - * - * @return {WPBlockDisplayInformation} Block's display information. - */ -// TODO tests -// TODO check performance -export const getBlockDisplayInformation = createSelector( - ( state, name, attributes ) => { - const variations = state.blockVariations[ name ]; - const blockType = getBlockType( state, name ); - const blockTypeInfo = { - title: blockType.title, - icon: blockType.icon, - description: blockType.description, - }; - if ( ! variations || ! blockType?.variationMatcher ) - return blockTypeInfo; - const match = variations.find( ( variation ) => - blockType.variationMatcher( attributes, variation ) - ); - if ( ! match ) return blockTypeInfo; - return { - title: match.title || blockType.title, - icon: match.icon || blockType.icon, - description: match.description || blockType.description, - }; - }, - ( state ) => [ state.blockTypes, state.blockVariations ] -); - /** * Returns the default block variation for the given block type. * When there are multiple variations annotated as the default one, From 6b8169b0888cec9bc8ed432d20226fae4db0a7d2 Mon Sep 17 00:00:00 2001 From: ntsekouras Date: Tue, 15 Dec 2020 16:43:38 +0200 Subject: [PATCH 15/32] add `isActive` API for block variations to use for trying to find a match --- .../use-matching-variation-information/index.js | 4 ++-- packages/block-library/src/embed/index.js | 4 ---- packages/block-library/src/embed/variations.js | 11 +++++++++++ packages/block-library/src/social-link/index.js | 4 ---- packages/block-library/src/social-link/variations.js | 11 +++++++++++ 5 files changed, 24 insertions(+), 10 deletions(-) diff --git a/packages/block-editor/src/components/use-matching-variation-information/index.js b/packages/block-editor/src/components/use-matching-variation-information/index.js index 61aa6df068cc3..2e6042a1ee2c1 100644 --- a/packages/block-editor/src/components/use-matching-variation-information/index.js +++ b/packages/block-editor/src/components/use-matching-variation-information/index.js @@ -46,9 +46,9 @@ export default function useMatchingVariationInformation( clientId ) { description: blockType.description, }; const variations = getBlockVariations( name ); - if ( ! variations || ! blockType.variationMatcher ) return blockTypeInfo; + if ( ! variations ) return blockTypeInfo; const match = variations.find( ( variation ) => - blockType.variationMatcher( attributes, variation ) + variation.isActive?.( attributes ) ); if ( ! match ) return blockTypeInfo; return { diff --git a/packages/block-library/src/embed/index.js b/packages/block-library/src/embed/index.js index afd577be5e649..3b1ed4d9bdb9c 100644 --- a/packages/block-library/src/embed/index.js +++ b/packages/block-library/src/embed/index.js @@ -28,8 +28,4 @@ export const settings = { transforms, variations, deprecated, - variationMatcher: ( blockAttributes, variation ) => { - const { providerNameSlug } = blockAttributes || {}; - return variation.name === providerNameSlug; - }, }; diff --git a/packages/block-library/src/embed/variations.js b/packages/block-library/src/embed/variations.js index 34a1b8f66f43c..7a751477857f8 100644 --- a/packages/block-library/src/embed/variations.js +++ b/packages/block-library/src/embed/variations.js @@ -339,4 +339,15 @@ const variations = [ }, ]; +/** + * Add `isActive` function to all `embed` variations, if not defined. + * `isActive` function is used to find a variation match from a created + * Block by providing its attributes. + */ +variations.forEach( ( variation ) => { + if ( variation.isActive ) return; + variation.isActive = ( { providerNameSlug } ) => + providerNameSlug === variation.attributes.providerNameSlug; +} ); + export default variations; diff --git a/packages/block-library/src/social-link/index.js b/packages/block-library/src/social-link/index.js index 805d961b3e446..142b2e616a9b6 100644 --- a/packages/block-library/src/social-link/index.js +++ b/packages/block-library/src/social-link/index.js @@ -23,8 +23,4 @@ export const settings = { 'Display an icon linking to a social media profile or website.' ), variations, - variationMatcher: ( blockAttributes, variation ) => { - const { service } = blockAttributes || {}; - return variation.name === service; - }, }; diff --git a/packages/block-library/src/social-link/variations.js b/packages/block-library/src/social-link/variations.js index 4297ced3c4171..74c262fb828de 100644 --- a/packages/block-library/src/social-link/variations.js +++ b/packages/block-library/src/social-link/variations.js @@ -304,4 +304,15 @@ const variations = [ }, ]; +/** + * Add `isActive` function to all `social link` variations, if not defined. + * `isActive` function is used to find a variation match from a created + * Block by providing its attributes. + */ +variations.forEach( ( variation ) => { + if ( variation.isActive ) return; + variation.isActive = ( { service } ) => + service === variation.attributes.service; +} ); + export default variations; From ec4aa294745694e7931fd009e497c8f79ba2661e Mon Sep 17 00:00:00 2001 From: ntsekouras Date: Tue, 15 Dec 2020 17:07:47 +0200 Subject: [PATCH 16/32] doc for `isActive` in block variation --- .../block-api/block-registration.md | 34 ++++++++++--------- packages/blocks/src/api/registration.js | 7 ++++ 2 files changed, 25 insertions(+), 16 deletions(-) diff --git a/docs/designers-developers/developers/block-api/block-registration.md b/docs/designers-developers/developers/block-api/block-registration.md index 4656097189065..599d8e4894831 100644 --- a/docs/designers-developers/developers/block-api/block-registration.md +++ b/docs/designers-developers/developers/block-api/block-registration.md @@ -222,7 +222,7 @@ example: { #### variations (optional) -- **Type:** `Object[]` +- **Type:** `Object[]` Similarly to how the block's style variations can be declared, a block type can define block variations that the user can pick from. The difference is that, rather than changing only the visual appearance, this field provides a way to apply initial custom attributes and inner blocks at the time when a block is inserted. @@ -256,19 +256,20 @@ variations: [ An object describing a variation defined for the block type can contain the following fields: -- `name` (type `string`) – The unique and machine-readable name. -- `title` (type `string`) – A human-readable variation title. -- `description` (optional, type `string`) – A detailed variation description. -- `icon` (optional, type `string` | `Object`) – An icon helping to visualize the variation. It can have the same shape as the block type. -- `isDefault` (optional, type `boolean`) – Indicates whether the current variation is the default one. Defaults to `false`. -- `attributes` (optional, type `Object`) – Values that override block attributes. -- `innerBlocks` (optional, type `Array[]`) – Initial configuration of nested blocks. -- `example` (optional, type `Object`) – Example provides structured data for the block preview. You can set to `undefined` to disable the preview shown for the block type. -- `scope` (optional, type `WPBlockVariationScope[]`) - the list of scopes where the variation is applicable. When not provided, it defaults to `block` and `inserter`. Available options: - - `inserter` - Block Variation is shown on the inserter. - - `block` - Used by blocks to filter specific block variations. Mostly used in Placeholder patterns like `Columns` block. - - `transform` - Block Variation will be shown in the component for Block Variations transformations. -- `keywords` (optional, type `string[]`) - An array of terms (which can be translated) that help users discover the variation while searching. +- `name` (type `string`) – The unique and machine-readable name. +- `title` (type `string`) – A human-readable variation title. +- `description` (optional, type `string`) – A detailed variation description. +- `icon` (optional, type `string` | `Object`) – An icon helping to visualize the variation. It can have the same shape as the block type. +- `isDefault` (optional, type `boolean`) – Indicates whether the current variation is the default one. Defaults to `false`. +- `attributes` (optional, type `Object`) – Values that override block attributes. +- `innerBlocks` (optional, type `Array[]`) – Initial configuration of nested blocks. +- `example` (optional, type `Object`) – Example provides structured data for the block preview. You can set to `undefined` to disable the preview shown for the block type. +- `scope` (optional, type `WPBlockVariationScope[]`) - the list of scopes where the variation is applicable. When not provided, it defaults to `block` and `inserter`. Available options: + - `inserter` - Block Variation is shown on the inserter. + - `block` - Used by blocks to filter specific block variations. Mostly used in Placeholder patterns like `Columns` block. + - `transform` - Block Variation will be shown in the component for Block Variations transformations. +- `keywords` (optional, type `string[]`) - An array of terms (which can be translated) that help users discover the variation while searching. +- `isActive` (optional, type `Function`) - A function that accepts a block's attributes and determines if a variation is active. This function doesn't try to find a match dynamically based on all block's attributes, as in many cases some attributes are irrelevant. An example would be for `embed` block where we only care about `providerNameSlug` attribute's value. It's also possible to override the default block style variation using the `className` attribute when defining block variations. @@ -278,15 +279,16 @@ variations: [ name: 'blue', title: __( 'Blue Quote' ), isDefault: true, - attributes: { className: 'is-style-blue-quote' }, + attributes: { color: 'blue', className: 'is-style-blue-quote' }, icon: 'format-quote', + isActive: ( blockAttributes ) => blockAttributes.color === 'blue' }, ], ``` #### supports (optional) -- ***Type:*** `Object` +- **_Type:_** `Object` Supports contains as set of options to control features used in the editor. See the [the supports documentation](/docs/designers-developers/developers/block-api/block-supports.md) for more details. diff --git a/packages/blocks/src/api/registration.js b/packages/blocks/src/api/registration.js index 9e64ebb2a01c5..6ed81ae8c28c3 100644 --- a/packages/blocks/src/api/registration.js +++ b/packages/blocks/src/api/registration.js @@ -97,6 +97,13 @@ import { store as blocksStore } from '../store'; * @property {string[]} [keywords] An array of terms (which can be translated) * that help users discover the variation * while searching. + * @property {Function} [isActive] A function that accepts a block's attributes + * and determines if a variation is active. This + * function doesn't try to find a match dynamically + * based on all block's attributes, as in many cases + * some attributes are irrelevant. An example would + * be for `embed` block where we only care about + * `providerNameSlug` attribute's value. */ /** From 4b261bbdf55bbb18872875f2267cf94a7ad2b004 Mon Sep 17 00:00:00 2001 From: ntsekouras Date: Tue, 15 Dec 2020 17:15:00 +0200 Subject: [PATCH 17/32] jsdoc fix --- .../src/components/use-matching-variation-information/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/use-matching-variation-information/index.js b/packages/block-editor/src/components/use-matching-variation-information/index.js index 2e6042a1ee2c1..85b75c52db77b 100644 --- a/packages/block-editor/src/components/use-matching-variation-information/index.js +++ b/packages/block-editor/src/components/use-matching-variation-information/index.js @@ -11,7 +11,7 @@ import { getBlockType, getBlockVariations } from '@wordpress/blocks'; * the appropriate information for display reasons. In order to * to try to find a match we need to things: * 1. Block's client id to extract it's current attributes. - * 2. Block should have in it's settings a `variationMatcher` function. + * 2. A block variation should have set `isActive` prop to a proper function. * * If for any reason a block variaton match cannot be found, * the returned information come from the Block Type. From 37949ca664d839013e1a6d18d0d592e7b66fc773 Mon Sep 17 00:00:00 2001 From: ntsekouras Date: Wed, 16 Dec 2020 16:21:48 +0200 Subject: [PATCH 18/32] address review feedback part 1 --- .../block-api/block-registration.md | 5 +++-- .../index.js | 13 ++++++------ .../block-library/src/embed/variations.js | 5 +++-- .../src/social-link/variations.js | 4 ++-- packages/blocks/src/api/registration.js | 21 ++++++++++--------- 5 files changed, 26 insertions(+), 22 deletions(-) diff --git a/docs/designers-developers/developers/block-api/block-registration.md b/docs/designers-developers/developers/block-api/block-registration.md index 599d8e4894831..ffe0981510eb1 100644 --- a/docs/designers-developers/developers/block-api/block-registration.md +++ b/docs/designers-developers/developers/block-api/block-registration.md @@ -269,7 +269,7 @@ An object describing a variation defined for the block type can contain the foll - `block` - Used by blocks to filter specific block variations. Mostly used in Placeholder patterns like `Columns` block. - `transform` - Block Variation will be shown in the component for Block Variations transformations. - `keywords` (optional, type `string[]`) - An array of terms (which can be translated) that help users discover the variation while searching. -- `isActive` (optional, type `Function`) - A function that accepts a block's attributes and determines if a variation is active. This function doesn't try to find a match dynamically based on all block's attributes, as in many cases some attributes are irrelevant. An example would be for `embed` block where we only care about `providerNameSlug` attribute's value. +- `isActive` (optional, type `Function`) - A function that accepts a block's attributes and the variation's attributes and determines if a variation is active. This function doesn't try to find a match dynamically based on all block's attributes, as in many cases some attributes are irrelevant. An example would be for `embed` block where we only care about `providerNameSlug` attribute's value. It's also possible to override the default block style variation using the `className` attribute when defining block variations. @@ -281,7 +281,8 @@ variations: [ isDefault: true, attributes: { color: 'blue', className: 'is-style-blue-quote' }, icon: 'format-quote', - isActive: ( blockAttributes ) => blockAttributes.color === 'blue' + isActive: ( blockAttributes, variationAttributes ) => + blockAttributes.color === variationAttributes.color }, ], ``` diff --git a/packages/block-editor/src/components/use-matching-variation-information/index.js b/packages/block-editor/src/components/use-matching-variation-information/index.js index 85b75c52db77b..f9769a4a80a05 100644 --- a/packages/block-editor/src/components/use-matching-variation-information/index.js +++ b/packages/block-editor/src/components/use-matching-variation-information/index.js @@ -2,7 +2,7 @@ * WordPress dependencies */ import { useSelect } from '@wordpress/data'; -import { getBlockType, getBlockVariations } from '@wordpress/blocks'; +import { store as blocksStore } from '@wordpress/blocks'; /** @typedef {import('@wordpress/blocks').WPBlockDisplayInformation} WPBlockDisplayInformation */ @@ -21,23 +21,25 @@ import { getBlockType, getBlockVariations } from '@wordpress/blocks'; * */ -// TODO write jsdoc example // TODO write tests export default function useMatchingVariationInformation( clientId ) { - const { name, attributes } = useSelect( + const { attributes, blockType, variations } = useSelect( ( select ) => { if ( ! clientId ) return {}; const { getBlockName, getBlockAttributes } = select( 'core/block-editor' ); + const { getBlockType, getBlockVariations } = select( blocksStore ); + const blockName = getBlockName( clientId ); return { name: getBlockName( clientId ), attributes: getBlockAttributes( clientId ), + blockType: getBlockType( blockName ), + variations: getBlockVariations( blockName ), }; }, [ clientId ] ); - const blockType = getBlockType( name ); if ( ! blockType ) return null; const blockTypeInfo = { @@ -45,10 +47,9 @@ export default function useMatchingVariationInformation( clientId ) { icon: blockType.icon, description: blockType.description, }; - const variations = getBlockVariations( name ); if ( ! variations ) return blockTypeInfo; const match = variations.find( ( variation ) => - variation.isActive?.( attributes ) + variation.isActive?.( attributes, variation.attributes ) ); if ( ! match ) return blockTypeInfo; return { diff --git a/packages/block-library/src/embed/variations.js b/packages/block-library/src/embed/variations.js index 7a751477857f8..02c68d0cb88ca 100644 --- a/packages/block-library/src/embed/variations.js +++ b/packages/block-library/src/embed/variations.js @@ -346,8 +346,9 @@ const variations = [ */ variations.forEach( ( variation ) => { if ( variation.isActive ) return; - variation.isActive = ( { providerNameSlug } ) => - providerNameSlug === variation.attributes.providerNameSlug; + variation.isActive = ( blockAttributes, variationAttributes ) => + blockAttributes.providerNameSlug === + variationAttributes.providerNameSlug; } ); export default variations; diff --git a/packages/block-library/src/social-link/variations.js b/packages/block-library/src/social-link/variations.js index 74c262fb828de..a2f259feaaabb 100644 --- a/packages/block-library/src/social-link/variations.js +++ b/packages/block-library/src/social-link/variations.js @@ -311,8 +311,8 @@ const variations = [ */ variations.forEach( ( variation ) => { if ( variation.isActive ) return; - variation.isActive = ( { service } ) => - service === variation.attributes.service; + variation.isActive = ( blockAttributes, variationAttributes ) => + blockAttributes.service === variationAttributes.service; } ); export default variations; diff --git a/packages/blocks/src/api/registration.js b/packages/blocks/src/api/registration.js index 6ed81ae8c28c3..78689337a9bbf 100644 --- a/packages/blocks/src/api/registration.js +++ b/packages/blocks/src/api/registration.js @@ -97,13 +97,14 @@ import { store as blocksStore } from '../store'; * @property {string[]} [keywords] An array of terms (which can be translated) * that help users discover the variation * while searching. - * @property {Function} [isActive] A function that accepts a block's attributes - * and determines if a variation is active. This - * function doesn't try to find a match dynamically - * based on all block's attributes, as in many cases - * some attributes are irrelevant. An example would - * be for `embed` block where we only care about - * `providerNameSlug` attribute's value. + * @property {Function} [isActive] A function that accepts a block's attributes + * and the variation's attributes and determines + * if a variation is active. This function doesn't + * try to find a match dynamically based on all + * block's attributes, as in many cases some + * attributes are irrelevant. An example would + * be for `embed` block where we only care about + * `providerNameSlug` attribute's value. */ /** @@ -138,9 +139,9 @@ import { store as blocksStore } from '../store'; * * @typedef {Object} WPBlockDisplayInformation * - * @property {string} title Human-readable block type label. - * @property {JSX.Element} icon Block type icon. - * @property {string} description A detailed block type description. + * @property {string} title Human-readable block type label. + * @property {WPIcon} icon Block type icon. + * @property {string} description A detailed block type description. */ /** From 2f6598ef427ff78cddd6d0ac10a03fedfaf77921 Mon Sep 17 00:00:00 2001 From: ntsekouras Date: Wed, 16 Dec 2020 18:35:09 +0200 Subject: [PATCH 19/32] fix BlockTitle tests --- .../src/components/block-title/test/index.js | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/packages/block-editor/src/components/block-title/test/index.js b/packages/block-editor/src/components/block-title/test/index.js index c597f55faf07c..3a6d512840a45 100644 --- a/packages/block-editor/src/components/block-title/test/index.js +++ b/packages/block-editor/src/components/block-title/test/index.js @@ -42,10 +42,18 @@ jest.mock( '@wordpress/blocks', () => { return title; } }, - getBlockVariations() {}, }; } ); +jest.mock( '../../use-matching-variation-information', () => { + const resultsMap = { + 'id-name-exists': { title: 'Block Title' }, + 'id-name-with-label': { title: 'Block With Label' }, + 'id-name-with-long-label': { title: 'Block With Long Label' }, + }; + return jest.fn( ( clientId ) => resultsMap[ clientId ] ); +} ); + jest.mock( '@wordpress/data/src/components/use-select', () => { // This allows us to tweak the returned value on each test const mock = jest.fn(); @@ -82,9 +90,7 @@ describe( 'BlockTitle', () => { attributes: null, } ) ); - const wrapper = shallow( - - ); + const wrapper = shallow( ); expect( wrapper.text() ).toBe( 'Block Title' ); } ); @@ -95,9 +101,7 @@ describe( 'BlockTitle', () => { attributes: null, } ) ); - const wrapper = shallow( - - ); + const wrapper = shallow( ); expect( wrapper.text() ).toBe( 'Block With Label: Test Label' ); } ); @@ -109,7 +113,7 @@ describe( 'BlockTitle', () => { } ) ); const wrapper = shallow( - + ); expect( wrapper.text() ).toBe( From a8a830271054e4955be15ee8472601b2bd1d1ef7 Mon Sep 17 00:00:00 2001 From: ntsekouras Date: Wed, 16 Dec 2020 19:01:43 +0200 Subject: [PATCH 20/32] rename hook to `useBlockDisplayInformation` --- .../src/components/block-inspector/index.js | 4 ++-- .../block-navigation/block-select-button.js | 4 ++-- .../src/components/block-title/index.js | 4 ++-- .../src/components/block-title/test/index.js | 2 +- packages/block-editor/src/components/index.js | 2 +- .../use-block-display-information/README.md | 6 ++++++ .../index.js | 14 ++++++++++++-- .../use-matching-variation-information/README.md | 6 ------ packages/blocks/src/api/registration.js | 10 ---------- packages/blocks/src/store/selectors.js | 1 - 10 files changed, 26 insertions(+), 27 deletions(-) create mode 100644 packages/block-editor/src/components/use-block-display-information/README.md rename packages/block-editor/src/components/{use-matching-variation-information => use-block-display-information}/index.js (80%) delete mode 100644 packages/block-editor/src/components/use-matching-variation-information/README.md diff --git a/packages/block-editor/src/components/block-inspector/index.js b/packages/block-editor/src/components/block-inspector/index.js index 998b0869c0c41..dd6edc46f5be0 100644 --- a/packages/block-editor/src/components/block-inspector/index.js +++ b/packages/block-editor/src/components/block-inspector/index.js @@ -25,7 +25,7 @@ import BlockStyles from '../block-styles'; import MultiSelectionInspector from '../multi-selection-inspector'; import DefaultStylePicker from '../default-style-picker'; import BlockVariationTransforms from '../block-variation-transforms'; -import useMatchingVariationInformation from '../use-matching-variation-information'; +import useBlockDisplayInformation from '../use-block-display-information'; const BlockInspector = ( { blockType, @@ -82,7 +82,7 @@ const BlockInspectorSingleBlock = ( { hasBlockStyles, bubblesVirtually, } ) => { - const blockInformation = useMatchingVariationInformation( clientId ); + const blockInformation = useBlockDisplayInformation( clientId ); return (
diff --git a/packages/block-editor/src/components/block-navigation/block-select-button.js b/packages/block-editor/src/components/block-navigation/block-select-button.js index e1fb6e0d2cf9f..e6f40a1ed6209 100644 --- a/packages/block-editor/src/components/block-navigation/block-select-button.js +++ b/packages/block-editor/src/components/block-navigation/block-select-button.js @@ -19,7 +19,7 @@ import { __ } from '@wordpress/i18n'; * Internal dependencies */ import BlockIcon from '../block-icon'; -import useMatchingVariationInformation from '../use-matching-variation-information'; +import useBlockDisplayInformation from '../use-block-display-information'; import { getBlockPositionDescription } from './utils'; function BlockNavigationBlockSelectButton( @@ -39,7 +39,7 @@ function BlockNavigationBlockSelectButton( }, ref ) { - const blockInformation = useMatchingVariationInformation( clientId ); + const blockInformation = useBlockDisplayInformation( clientId ); const instanceId = useInstanceId( BlockNavigationBlockSelectButton ); const descriptionId = `block-navigation-block-select-button__${ instanceId }`; const blockType = getBlockType( name ); diff --git a/packages/block-editor/src/components/block-title/index.js b/packages/block-editor/src/components/block-title/index.js index 527fe561a1eda..d99bd1e83170e 100644 --- a/packages/block-editor/src/components/block-title/index.js +++ b/packages/block-editor/src/components/block-title/index.js @@ -15,7 +15,7 @@ import { /** * Internal dependencies */ -import useMatchingVariationInformation from '../use-matching-variation-information'; +import useBlockDisplayInformation from '../use-block-display-information'; /** * Renders the block's configured title as a string, or empty if the title @@ -49,7 +49,7 @@ export default function BlockTitle( { clientId } ) { [ clientId ] ); - const blockInformation = useMatchingVariationInformation( clientId ); + const blockInformation = useBlockDisplayInformation( clientId ); if ( ! blockInformation ) return null; const blockType = getBlockType( name ); const label = getBlockLabel( blockType, attributes ); diff --git a/packages/block-editor/src/components/block-title/test/index.js b/packages/block-editor/src/components/block-title/test/index.js index 3a6d512840a45..23af6288130e0 100644 --- a/packages/block-editor/src/components/block-title/test/index.js +++ b/packages/block-editor/src/components/block-title/test/index.js @@ -45,7 +45,7 @@ jest.mock( '@wordpress/blocks', () => { }; } ); -jest.mock( '../../use-matching-variation-information', () => { +jest.mock( '../../use-block-display-information', () => { const resultsMap = { 'id-name-exists': { title: 'Block Title' }, 'id-name-with-label': { title: 'Block With Label' }, diff --git a/packages/block-editor/src/components/index.js b/packages/block-editor/src/components/index.js index b87e9975e47f0..3283a08a67caa 100644 --- a/packages/block-editor/src/components/index.js +++ b/packages/block-editor/src/components/index.js @@ -118,7 +118,7 @@ export { export { default as Warning } from './warning'; export { default as WritingFlow } from './writing-flow'; export { useCanvasClickRedirect as __unstableUseCanvasClickRedirect } from './use-canvas-click-redirect'; -export { useMatchingVariationInformation as __experimentalUseMatchingVariationInformation } from './use-matching-variation-information'; +export { useBlockDisplayInformation as __experimentalUseBlockDisplayInformation } from './use-block-display-information'; /* * State Related Components diff --git a/packages/block-editor/src/components/use-block-display-information/README.md b/packages/block-editor/src/components/use-block-display-information/README.md new file mode 100644 index 0000000000000..50760e086e776 --- /dev/null +++ b/packages/block-editor/src/components/use-block-display-information/README.md @@ -0,0 +1,6 @@ +`useBlockDisplayInformation` +=========== + +`useBlockDisplayInformation` + +# TODO diff --git a/packages/block-editor/src/components/use-matching-variation-information/index.js b/packages/block-editor/src/components/use-block-display-information/index.js similarity index 80% rename from packages/block-editor/src/components/use-matching-variation-information/index.js rename to packages/block-editor/src/components/use-block-display-information/index.js index f9769a4a80a05..24aef04c6a2b9 100644 --- a/packages/block-editor/src/components/use-matching-variation-information/index.js +++ b/packages/block-editor/src/components/use-block-display-information/index.js @@ -4,7 +4,17 @@ import { useSelect } from '@wordpress/data'; import { store as blocksStore } from '@wordpress/blocks'; -/** @typedef {import('@wordpress/blocks').WPBlockDisplayInformation} WPBlockDisplayInformation */ +/** @typedef {import('@wordpress/blocks').WPIcon} WPIcon */ + +/** + * Contains basic block's information for display reasons. + * + * @typedef {Object} WPBlockDisplayInformation + * + * @property {string} title Human-readable block type label. + * @property {WPIcon} icon Block type icon. + * @property {string} description A detailed block type description. + */ /** * Hook used to try to find a matching block variation and return @@ -22,7 +32,7 @@ import { store as blocksStore } from '@wordpress/blocks'; */ // TODO write tests -export default function useMatchingVariationInformation( clientId ) { +export default function useBlockDisplayInformation( clientId ) { const { attributes, blockType, variations } = useSelect( ( select ) => { if ( ! clientId ) return {}; diff --git a/packages/block-editor/src/components/use-matching-variation-information/README.md b/packages/block-editor/src/components/use-matching-variation-information/README.md deleted file mode 100644 index 203f40425100e..0000000000000 --- a/packages/block-editor/src/components/use-matching-variation-information/README.md +++ /dev/null @@ -1,6 +0,0 @@ -`useMatchingVariationInformation` -=========== - -`useMatchingVariationInformation` - -# TODO diff --git a/packages/blocks/src/api/registration.js b/packages/blocks/src/api/registration.js index 78689337a9bbf..7c1ce2c164338 100644 --- a/packages/blocks/src/api/registration.js +++ b/packages/blocks/src/api/registration.js @@ -134,16 +134,6 @@ import { store as blocksStore } from '../store'; * then no preview is shown. */ -/** - * A subset of `WPBlock` type. Contains basic block's information for display reasons. - * - * @typedef {Object} WPBlockDisplayInformation - * - * @property {string} title Human-readable block type label. - * @property {WPIcon} icon Block type icon. - * @property {string} description A detailed block type description. - */ - /** * Mapping of legacy category slugs to their latest normal values, used to * accommodate updates of the default set of block categories. diff --git a/packages/blocks/src/store/selectors.js b/packages/blocks/src/store/selectors.js index a9dde842fc117..5513ff4e4c488 100644 --- a/packages/blocks/src/store/selectors.js +++ b/packages/blocks/src/store/selectors.js @@ -16,7 +16,6 @@ import { /** @typedef {import('../api/registration').WPBlockVariation} WPBlockVariation */ /** @typedef {import('../api/registration').WPBlockVariationScope} WPBlockVariationScope */ -/** @typedef {import('../api/registration').WPBlockDisplayInformation} WPBlockDisplayInformation */ /** @typedef {import('./reducer').WPBlockCategory} WPBlockCategory */ /** From 9675f07857ad1a58af3ab7d82918f82a6e0da938 Mon Sep 17 00:00:00 2001 From: ntsekouras Date: Wed, 16 Dec 2020 19:15:48 +0200 Subject: [PATCH 21/32] fix export --- packages/block-editor/src/components/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/index.js b/packages/block-editor/src/components/index.js index 3283a08a67caa..0c5a94b6c19a6 100644 --- a/packages/block-editor/src/components/index.js +++ b/packages/block-editor/src/components/index.js @@ -118,7 +118,7 @@ export { export { default as Warning } from './warning'; export { default as WritingFlow } from './writing-flow'; export { useCanvasClickRedirect as __unstableUseCanvasClickRedirect } from './use-canvas-click-redirect'; -export { useBlockDisplayInformation as __experimentalUseBlockDisplayInformation } from './use-block-display-information'; +export { default as __experimentalUseBlockDisplayInformation } from './use-block-display-information'; /* * State Related Components From 113f761ad06da3888eae21f00cd56db6212d2b01 Mon Sep 17 00:00:00 2001 From: ntsekouras Date: Wed, 16 Dec 2020 19:38:53 +0200 Subject: [PATCH 22/32] useBlockDisplayInformation README --- .../use-block-display-information/README.md | 46 +++++++++++++++++-- .../use-block-display-information/index.js | 3 +- 2 files changed, 44 insertions(+), 5 deletions(-) diff --git a/packages/block-editor/src/components/use-block-display-information/README.md b/packages/block-editor/src/components/use-block-display-information/README.md index 50760e086e776..1fa0076036d18 100644 --- a/packages/block-editor/src/components/use-block-display-information/README.md +++ b/packages/block-editor/src/components/use-block-display-information/README.md @@ -1,6 +1,44 @@ -`useBlockDisplayInformation` -=========== +# useBlockDisplayInformation -`useBlockDisplayInformation` +A React Hook that tries to find a matching block variation and returns the appropriate information for display reasons. In order to try to find a match we need to things: -# TODO +1. Block's client id to extract it's current attributes. +2. A block variation should have set `isActive` prop to a proper function. + +If for any reason a block variaton match cannot be found, the returned information come from the Block Type. + +Note that this is currently experimental, and is available as `__experimentalUseBlockDisplayInformation`. + +### Usage + +The hook returns an object which contains block's title, icon and description. If no blockType is found with the provided `clientId`, returns `null`. + +```jsx +import { + BlockIcon, + __experimentalUseBlockDisplayInformation as useBlockDisplayInformation, +} from '@wordpress/block-editor'; + +function DemoBlockCard( { clientId } ) { + const blockInformation = useBlockDisplayInformation( clientId ); + const { title, icon, description } = blockInformation; + return ( +
+ +

{ title }

+

{ description }

+
+ ); +} +``` + +## Props + +The hook accepts the following props. + +### clientId + +A block's clientId + +- Type: `String` +- Required: Yes diff --git a/packages/block-editor/src/components/use-block-display-information/index.js b/packages/block-editor/src/components/use-block-display-information/index.js index 24aef04c6a2b9..ab21eebd6d9ed 100644 --- a/packages/block-editor/src/components/use-block-display-information/index.js +++ b/packages/block-editor/src/components/use-block-display-information/index.js @@ -25,9 +25,10 @@ import { store as blocksStore } from '@wordpress/blocks'; * * If for any reason a block variaton match cannot be found, * the returned information come from the Block Type. + * If no blockType is found with the provided clientId, returns null. * * @param {string} clientId Block's client id. - * @return {WPBlockDisplayInformation} Block's display information. + * @return {?WPBlockDisplayInformation} Block's display information. * */ From 0f720b66b6644d4984ae206bbd597a78bb07dd81 Mon Sep 17 00:00:00 2001 From: ntsekouras Date: Thu, 17 Dec 2020 13:18:33 +0200 Subject: [PATCH 23/32] move login in useSelect --- .../use-block-display-information/index.js | 42 +++++++++---------- 1 file changed, 19 insertions(+), 23 deletions(-) diff --git a/packages/block-editor/src/components/use-block-display-information/index.js b/packages/block-editor/src/components/use-block-display-information/index.js index ab21eebd6d9ed..5d2d66bab315f 100644 --- a/packages/block-editor/src/components/use-block-display-information/index.js +++ b/packages/block-editor/src/components/use-block-display-information/index.js @@ -34,38 +34,34 @@ import { store as blocksStore } from '@wordpress/blocks'; // TODO write tests export default function useBlockDisplayInformation( clientId ) { - const { attributes, blockType, variations } = useSelect( + return useSelect( ( select ) => { - if ( ! clientId ) return {}; + if ( ! clientId ) return null; const { getBlockName, getBlockAttributes } = select( 'core/block-editor' ); const { getBlockType, getBlockVariations } = select( blocksStore ); const blockName = getBlockName( clientId ); + const blockType = getBlockType( blockName ); + if ( ! blockType ) return null; + const variations = getBlockVariations( blockName ); + const blockTypeInfo = { + title: blockType.title, + icon: blockType.icon, + description: blockType.description, + }; + if ( ! variations ) return blockTypeInfo; + const attributes = getBlockAttributes( clientId ); + const match = variations.find( ( variation ) => + variation.isActive?.( attributes, variation.attributes ) + ); + if ( ! match ) return blockTypeInfo; return { - name: getBlockName( clientId ), - attributes: getBlockAttributes( clientId ), - blockType: getBlockType( blockName ), - variations: getBlockVariations( blockName ), + title: match.title || blockType.title, + icon: match.icon || blockType.icon, + description: match.description || blockType.description, }; }, [ clientId ] ); - if ( ! blockType ) return null; - - const blockTypeInfo = { - title: blockType.title, - icon: blockType.icon, - description: blockType.description, - }; - if ( ! variations ) return blockTypeInfo; - const match = variations.find( ( variation ) => - variation.isActive?.( attributes, variation.attributes ) - ); - if ( ! match ) return blockTypeInfo; - return { - title: match.title || blockType.title, - icon: match.icon || blockType.icon, - description: match.description || blockType.description, - }; } From 410fc743fd70dbaf9e73d8a390dcfb9f4a4a59f9 Mon Sep 17 00:00:00 2001 From: ntsekouras Date: Thu, 17 Dec 2020 16:08:11 +0200 Subject: [PATCH 24/32] e2e tests --- .../use-block-display-information/index.js | 1 - .../plugins/block-variations/index.js | 4 + .../specs/editor/plugins/block-variations.js | 73 +++++++++++++++++++ 3 files changed, 77 insertions(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/use-block-display-information/index.js b/packages/block-editor/src/components/use-block-display-information/index.js index 5d2d66bab315f..a71ff4f846d33 100644 --- a/packages/block-editor/src/components/use-block-display-information/index.js +++ b/packages/block-editor/src/components/use-block-display-information/index.js @@ -32,7 +32,6 @@ import { store as blocksStore } from '@wordpress/blocks'; * */ -// TODO write tests export default function useBlockDisplayInformation( clientId ) { return useSelect( ( select ) => { diff --git a/packages/e2e-tests/plugins/block-variations/index.js b/packages/e2e-tests/plugins/block-variations/index.js index 3a76ae7d42db6..219eedd6bec5e 100644 --- a/packages/e2e-tests/plugins/block-variations/index.js +++ b/packages/e2e-tests/plugins/block-variations/index.js @@ -40,6 +40,8 @@ }, icon: 'yes-alt', scope: [ 'inserter' ], + isActive: ( { backgroundColor }, variationAttributes ) => + backgroundColor === variationAttributes.backgroundColor, } ); registerBlockVariation( 'core/paragraph', { @@ -52,6 +54,8 @@ }, icon: 'warning', scope: [ 'inserter' ], + isActive: ( { backgroundColor }, variationAttributes ) => + backgroundColor === variationAttributes.backgroundColor, } ); registerBlockVariation( 'core/columns', { diff --git a/packages/e2e-tests/specs/editor/plugins/block-variations.js b/packages/e2e-tests/specs/editor/plugins/block-variations.js index ef4a17360284a..81862f42a5e30 100644 --- a/packages/e2e-tests/specs/editor/plugins/block-variations.js +++ b/packages/e2e-tests/specs/editor/plugins/block-variations.js @@ -7,6 +7,8 @@ import { deactivatePlugin, insertBlock, searchForBlock, + pressKeyWithModifier, + openDocumentSettingsSidebar, } from '@wordpress/e2e-test-utils'; describe( 'Block variations', () => { @@ -103,4 +105,75 @@ describe( 'Block variations', () => { ) ).toHaveLength( 4 ); } ); + // @see @wordpres/block-editor/src/components/use-block-display-information (`useBlockDisplayInformation` hook). + describe( 'testing block display information with matching variations', () => { + const getActiveBreadcrumb = async () => + page.evaluate( + () => + document.querySelector( + '.block-editor-block-breadcrumb__current' + ).textContent + ); + const getFirstNavigationItem = async () => { + await pressKeyWithModifier( 'access', 'o' ); + // This also returns the visually hidden text `(selected block)`. + // For example `Paragraph(selected block)`. In order to hide this + // implementation detail and search for childNodes, we choose to + // test with `String.prototype.startsWith()`. + return page.evaluate( + () => + document.querySelector( + '.block-editor-block-navigation-block-select-button' + ).textContent + ); + }; + const getBlockCardDescription = async () => { + await openDocumentSettingsSidebar(); + return page.evaluate( + () => + document.querySelector( + '.block-editor-block-card__description' + ).textContent + ); + }; + + it( 'should show block information when no matching variation is found', async () => { + await insertBlock( 'Large Quote' ); + const breadcrumb = await getActiveBreadcrumb(); + expect( breadcrumb ).toEqual( 'Quote' ); + const navigationItem = await getFirstNavigationItem(); + expect( navigationItem.startsWith( 'Quote' ) ).toBeTruthy(); + const description = await getBlockCardDescription(); + expect( description ).toEqual( + 'Give quoted text visual emphasis. "In quoting others, we cite ourselves." — Julio Cortázar' + ); + } ); + it( 'should display variations info if all declared', async () => { + await insertBlock( 'Success Message' ); + const breadcrumb = await getActiveBreadcrumb(); + expect( breadcrumb ).toEqual( 'Success Message' ); + const navigationItem = await getFirstNavigationItem(); + expect( + navigationItem.startsWith( 'Success Message' ) + ).toBeTruthy(); + const description = await getBlockCardDescription(); + expect( description ).toEqual( + 'This block displays a success message. This description overrides the default one provided for the Paragraph block.' + ); + } ); + it( 'should display mixed block and variation match information', async () => { + // Warning Message variation is missing the `description`. + await insertBlock( 'Warning Message' ); + const breadcrumb = await getActiveBreadcrumb(); + expect( breadcrumb ).toEqual( 'Warning Message' ); + const navigationItem = await getFirstNavigationItem(); + expect( + navigationItem.startsWith( 'Warning Message' ) + ).toBeTruthy(); + const description = await getBlockCardDescription(); + expect( description ).toEqual( + 'Start with the building block of all narrative.' + ); + } ); + } ); } ); From 8501b3451d86cfb62a4389d58ab0db7e42e15870 Mon Sep 17 00:00:00 2001 From: ntsekouras Date: Thu, 17 Dec 2020 17:38:53 +0200 Subject: [PATCH 25/32] blockTitle extra safeguard that existed before --- packages/block-editor/src/components/block-title/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/block-title/index.js b/packages/block-editor/src/components/block-title/index.js index d99bd1e83170e..c7701527e07a0 100644 --- a/packages/block-editor/src/components/block-title/index.js +++ b/packages/block-editor/src/components/block-title/index.js @@ -50,7 +50,7 @@ export default function BlockTitle( { clientId } ) { ); const blockInformation = useBlockDisplayInformation( clientId ); - if ( ! blockInformation ) return null; + if ( ! name || ! blockInformation ) return null; const blockType = getBlockType( name ); const label = getBlockLabel( blockType, attributes ); // Label will fallback to the title if no label is defined for the From 176395985903975248606fe16b4c6d3c17abfbdf Mon Sep 17 00:00:00 2001 From: Nik Tsekouras Date: Wed, 23 Dec 2020 09:04:38 +0200 Subject: [PATCH 26/32] Update docs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Greg Ziółkowski --- .../src/components/use-block-display-information/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/use-block-display-information/README.md b/packages/block-editor/src/components/use-block-display-information/README.md index 1fa0076036d18..3d4e8db239be9 100644 --- a/packages/block-editor/src/components/use-block-display-information/README.md +++ b/packages/block-editor/src/components/use-block-display-information/README.md @@ -1,6 +1,6 @@ # useBlockDisplayInformation -A React Hook that tries to find a matching block variation and returns the appropriate information for display reasons. In order to try to find a match we need to things: +A React Hook that tries to find a matching block variation and returns the appropriate information for display reasons. In order to try to find a match we need two things: 1. Block's client id to extract it's current attributes. 2. A block variation should have set `isActive` prop to a proper function. From 65a89102ba0ecbfd23959878f577db41c072d97d Mon Sep 17 00:00:00 2001 From: Nik Tsekouras Date: Wed, 23 Dec 2020 09:04:58 +0200 Subject: [PATCH 27/32] Update docs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Greg Ziółkowski --- .../src/components/use-block-display-information/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/use-block-display-information/README.md b/packages/block-editor/src/components/use-block-display-information/README.md index 3d4e8db239be9..be8257e79a6ef 100644 --- a/packages/block-editor/src/components/use-block-display-information/README.md +++ b/packages/block-editor/src/components/use-block-display-information/README.md @@ -2,7 +2,7 @@ A React Hook that tries to find a matching block variation and returns the appropriate information for display reasons. In order to try to find a match we need two things: -1. Block's client id to extract it's current attributes. +1. Block's client id to extract its current attributes. 2. A block variation should have set `isActive` prop to a proper function. If for any reason a block variaton match cannot be found, the returned information come from the Block Type. From 9ec01e66e8c84e8375a1dc7b8d23e38e2b89c4ca Mon Sep 17 00:00:00 2001 From: Nik Tsekouras Date: Wed, 23 Dec 2020 09:07:33 +0200 Subject: [PATCH 28/32] Update docs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Greg Ziółkowski --- .../src/components/use-block-display-information/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/use-block-display-information/README.md b/packages/block-editor/src/components/use-block-display-information/README.md index be8257e79a6ef..fcdc7f42b5c9b 100644 --- a/packages/block-editor/src/components/use-block-display-information/README.md +++ b/packages/block-editor/src/components/use-block-display-information/README.md @@ -3,7 +3,7 @@ A React Hook that tries to find a matching block variation and returns the appropriate information for display reasons. In order to try to find a match we need two things: 1. Block's client id to extract its current attributes. -2. A block variation should have set `isActive` prop to a proper function. +2. A block variation has `isActive` prop defined with a matcher function. If for any reason a block variaton match cannot be found, the returned information come from the Block Type. From 9ec1bee48aac92b825678f4faabf74963a893b2d Mon Sep 17 00:00:00 2001 From: Nik Tsekouras Date: Wed, 23 Dec 2020 09:09:08 +0200 Subject: [PATCH 29/32] Update docs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Greg Ziółkowski --- .../src/components/use-block-display-information/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/use-block-display-information/README.md b/packages/block-editor/src/components/use-block-display-information/README.md index fcdc7f42b5c9b..c32880688dcb5 100644 --- a/packages/block-editor/src/components/use-block-display-information/README.md +++ b/packages/block-editor/src/components/use-block-display-information/README.md @@ -23,7 +23,7 @@ function DemoBlockCard( { clientId } ) { const blockInformation = useBlockDisplayInformation( clientId ); const { title, icon, description } = blockInformation; return ( -
+

{ title }

{ description }

From 89c480ce9ab508ceca4c2b849541419556e3fd3d Mon Sep 17 00:00:00 2001 From: ntsekouras Date: Wed, 23 Dec 2020 09:25:30 +0200 Subject: [PATCH 30/32] rewordings --- .../src/components/use-block-display-information/README.md | 2 +- .../src/components/use-block-display-information/index.js | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/block-editor/src/components/use-block-display-information/README.md b/packages/block-editor/src/components/use-block-display-information/README.md index c32880688dcb5..905d78685aad8 100644 --- a/packages/block-editor/src/components/use-block-display-information/README.md +++ b/packages/block-editor/src/components/use-block-display-information/README.md @@ -11,7 +11,7 @@ Note that this is currently experimental, and is available as `__experimentalUse ### Usage -The hook returns an object which contains block's title, icon and description. If no blockType is found with the provided `clientId`, returns `null`. +The hook returns an object which contains the block's title, icon, and description. If no block type is found for the provided `clientId`, it returns `null`. ```jsx import { diff --git a/packages/block-editor/src/components/use-block-display-information/index.js b/packages/block-editor/src/components/use-block-display-information/index.js index a71ff4f846d33..30f42d9038f2e 100644 --- a/packages/block-editor/src/components/use-block-display-information/index.js +++ b/packages/block-editor/src/components/use-block-display-information/index.js @@ -28,8 +28,7 @@ import { store as blocksStore } from '@wordpress/blocks'; * If no blockType is found with the provided clientId, returns null. * * @param {string} clientId Block's client id. - * @return {?WPBlockDisplayInformation} Block's display information. - * + * @return {?WPBlockDisplayInformation} Block's display information, or `null` when the block or its type not found. */ export default function useBlockDisplayInformation( clientId ) { From 438831abae2844237940c1840f1dea99cd27e6d0 Mon Sep 17 00:00:00 2001 From: ntsekouras Date: Wed, 23 Dec 2020 09:26:43 +0200 Subject: [PATCH 31/32] remove experimental status --- packages/block-editor/README.md | 24 +++++++++++++++++-- packages/block-editor/src/components/index.js | 2 +- .../use-block-display-information/README.md | 4 +--- 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/packages/block-editor/README.md b/packages/block-editor/README.md index cfadf407b3b65..2e605177bf29f 100644 --- a/packages/block-editor/README.md +++ b/packages/block-editor/README.md @@ -19,12 +19,12 @@ import { BlockEditorProvider, BlockList, WritingFlow, - ObserveTyping + ObserveTyping, } from '@wordpress/block-editor'; import { SlotFillProvider, Popover } from '@wordpress/components'; import { useState } from '@wordpress/element'; -function MyEditorComponent () { +function MyEditorComponent() { const [ blocks, updateBlocks ] = useState( [] ); return ( @@ -569,6 +569,26 @@ _Related_ - +# **useBlockDisplayInformation** + +Hook used to try to find a matching block variation and return +the appropriate information for display reasons. In order to +to try to find a match we need to things: +1\. Block's client id to extract it's current attributes. +2\. A block variation should have set `isActive` prop to a proper function. + +If for any reason a block variaton match cannot be found, +the returned information come from the Block Type. +If no blockType is found with the provided clientId, returns null. + +_Parameters_ + +- _clientId_ `string`: Block's client id. + +_Returns_ + +- `?WPBlockDisplayInformation`: Block's display information, or `null` when the block or its type not found. + # **useBlockEditContext** Undocumented declaration. diff --git a/packages/block-editor/src/components/index.js b/packages/block-editor/src/components/index.js index 0c5a94b6c19a6..551f83f8b4d66 100644 --- a/packages/block-editor/src/components/index.js +++ b/packages/block-editor/src/components/index.js @@ -118,7 +118,7 @@ export { export { default as Warning } from './warning'; export { default as WritingFlow } from './writing-flow'; export { useCanvasClickRedirect as __unstableUseCanvasClickRedirect } from './use-canvas-click-redirect'; -export { default as __experimentalUseBlockDisplayInformation } from './use-block-display-information'; +export { default as useBlockDisplayInformation } from './use-block-display-information'; /* * State Related Components diff --git a/packages/block-editor/src/components/use-block-display-information/README.md b/packages/block-editor/src/components/use-block-display-information/README.md index 905d78685aad8..6d52ee452cc48 100644 --- a/packages/block-editor/src/components/use-block-display-information/README.md +++ b/packages/block-editor/src/components/use-block-display-information/README.md @@ -7,8 +7,6 @@ A React Hook that tries to find a matching block variation and returns the appro If for any reason a block variaton match cannot be found, the returned information come from the Block Type. -Note that this is currently experimental, and is available as `__experimentalUseBlockDisplayInformation`. - ### Usage The hook returns an object which contains the block's title, icon, and description. If no block type is found for the provided `clientId`, it returns `null`. @@ -16,7 +14,7 @@ The hook returns an object which contains the block's title, icon, and descripti ```jsx import { BlockIcon, - __experimentalUseBlockDisplayInformation as useBlockDisplayInformation, + useBlockDisplayInformation, } from '@wordpress/block-editor'; function DemoBlockCard( { clientId } ) { From bef032bac4b37e133c55edb185351a1e48f6b7d8 Mon Sep 17 00:00:00 2001 From: ntsekouras Date: Wed, 23 Dec 2020 09:37:31 +0200 Subject: [PATCH 32/32] small refactoring --- .../components/use-block-display-information/index.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/components/use-block-display-information/index.js b/packages/block-editor/src/components/use-block-display-information/index.js index 30f42d9038f2e..7ee0d350ffef8 100644 --- a/packages/block-editor/src/components/use-block-display-information/index.js +++ b/packages/block-editor/src/components/use-block-display-information/index.js @@ -4,6 +4,11 @@ import { useSelect } from '@wordpress/data'; import { store as blocksStore } from '@wordpress/blocks'; +/** + * Internal dependencies + */ +import { store as blockEditorStore } from '../../store'; + /** @typedef {import('@wordpress/blocks').WPIcon} WPIcon */ /** @@ -36,7 +41,7 @@ export default function useBlockDisplayInformation( clientId ) { ( select ) => { if ( ! clientId ) return null; const { getBlockName, getBlockAttributes } = select( - 'core/block-editor' + blockEditorStore ); const { getBlockType, getBlockVariations } = select( blocksStore ); const blockName = getBlockName( clientId ); @@ -48,7 +53,7 @@ export default function useBlockDisplayInformation( clientId ) { icon: blockType.icon, description: blockType.description, }; - if ( ! variations ) return blockTypeInfo; + if ( ! variations?.length ) return blockTypeInfo; const attributes = getBlockAttributes( clientId ); const match = variations.find( ( variation ) => variation.isActive?.( attributes, variation.attributes )