From a5ab8749e8efec6d91c956407d3550d9b37a012b Mon Sep 17 00:00:00 2001 From: Robert Anderson Date: Fri, 9 Jun 2023 11:00:20 +1000 Subject: [PATCH] DRY up ContentBlocksList and BlockInspectorLockedBlocks (#51281) * DRY up ContentBlocksList and BlockInspectorLockedBlocks Extract BlockQuickNavigation out of ContentBlocksList and BlockInspectorLockedBlocks so that we're not repeating the same code that outputs a list of block navigation links. * Add back check that ensures list items don't appear in list * Remove unnecessary CSS * Reduce amount of rerendering * Update __experimentalGetGlobalBlocksByName --- .../src/components/block-inspector/index.js | 110 +++--------------- .../src/components/block-inspector/style.scss | 5 - .../block-quick-navigation/index.js | 74 ++++++++++++ packages/block-editor/src/private-apis.js | 2 + packages/block-editor/src/store/selectors.js | 5 +- .../page-panels/content-blocks-list.js | 77 ------------ .../sidebar-edit-mode/page-panels/index.js | 4 +- .../page-panels/page-content.js | 27 +++++ 8 files changed, 127 insertions(+), 177 deletions(-) create mode 100644 packages/block-editor/src/components/block-quick-navigation/index.js delete mode 100644 packages/edit-site/src/components/sidebar-edit-mode/page-panels/content-blocks-list.js create mode 100644 packages/edit-site/src/components/sidebar-edit-mode/page-panels/page-content.js diff --git a/packages/block-editor/src/components/block-inspector/index.js b/packages/block-editor/src/components/block-inspector/index.js index b6ac55afa6712..64f6229034014 100644 --- a/packages/block-editor/src/components/block-inspector/index.js +++ b/packages/block-editor/src/components/block-inspector/index.js @@ -8,16 +8,8 @@ import { hasBlockSupport, store as blocksStore, } from '@wordpress/blocks'; -import { - FlexItem, - PanelBody, - __experimentalHStack as HStack, - __experimentalVStack as VStack, - Button, - __unstableMotion as motion, -} from '@wordpress/components'; -import { useSelect, useDispatch } from '@wordpress/data'; -import { useMemo, useCallback } from '@wordpress/element'; +import { PanelBody, __unstableMotion as motion } from '@wordpress/components'; +import { useSelect } from '@wordpress/data'; /** * Internal dependencies @@ -28,7 +20,6 @@ import MultiSelectionInspector from '../multi-selection-inspector'; import BlockVariationTransforms from '../block-variation-transforms'; import useBlockDisplayInformation from '../use-block-display-information'; import { store as blockEditorStore } from '../../store'; -import BlockIcon from '../block-icon'; import BlockStyles from '../block-styles'; import DefaultStylePicker from '../default-style-picker'; import { default as InspectorControls } from '../inspector-controls'; @@ -38,77 +29,26 @@ import AdvancedControls from '../inspector-controls-tabs/advanced-controls-panel import PositionControls from '../inspector-controls-tabs/position-controls-panel'; import useBlockInspectorAnimationSettings from './useBlockInspectorAnimationSettings'; import BlockInfo from '../block-info-slot-fill'; - -function useContentBlocks( blockTypes, block ) { - const contentBlocksObjectAux = useMemo( () => { - return blockTypes.reduce( ( result, blockType ) => { - if ( - blockType.name !== 'core/list-item' && - Object.entries( blockType.attributes ).some( - ( [ , { __experimentalRole } ] ) => - __experimentalRole === 'content' - ) - ) { - result[ blockType.name ] = true; - } - return result; - }, {} ); - }, [ blockTypes ] ); - const isContentBlock = useCallback( - ( blockName ) => { - return !! contentBlocksObjectAux[ blockName ]; - }, - [ contentBlocksObjectAux ] - ); - return useMemo( () => { - return getContentBlocks( [ block ], isContentBlock ); - }, [ block, isContentBlock ] ); -} - -function getContentBlocks( blocks, isContentBlock ) { - const result = []; - for ( const block of blocks ) { - if ( isContentBlock( block.name ) ) { - result.push( block ); - } - result.push( ...getContentBlocks( block.innerBlocks, isContentBlock ) ); - } - return result; -} - -function BlockNavigationButton( { blockTypes, block, selectedBlock } ) { - const { selectBlock } = useDispatch( blockEditorStore ); - const blockType = blockTypes.find( ( { name } ) => name === block.name ); - const isSelected = - selectedBlock && selectedBlock.clientId === block.clientId; - return ( - - ); -} +import BlockQuickNavigation from '../block-quick-navigation'; +import { unlock } from '../../lock-unlock'; function BlockInspectorLockedBlocks( { topLevelLockedBlock } ) { - const { blockTypes, block, selectedBlock } = useSelect( + const contentClientIds = useSelect( ( select ) => { - return { - blockTypes: select( blocksStore ).getBlockTypes(), - block: select( blockEditorStore ).getBlock( - topLevelLockedBlock - ), - selectedBlock: select( blockEditorStore ).getSelectedBlock(), - }; + const { + getClientIdsOfDescendants, + getBlockName, + getBlockEditingMode, + } = unlock( select( blockEditorStore ) ); + return getClientIdsOfDescendants( [ topLevelLockedBlock ] ).filter( + ( clientId ) => + getBlockName( clientId ) !== 'core/list-item' && + getBlockEditingMode( clientId ) === 'contentOnly' + ); }, [ topLevelLockedBlock ] ); const blockInformation = useBlockDisplayInformation( topLevelLockedBlock ); - const contentBlocks = useContentBlocks( blockTypes, block ); return (
- -

- { __( 'Content' ) } -

- { contentBlocks.map( ( contentBlock ) => ( - - ) ) } -
+ + +
); } diff --git a/packages/block-editor/src/components/block-inspector/style.scss b/packages/block-editor/src/components/block-inspector/style.scss index 07701f2e4b91d..5cf4a8b382f99 100644 --- a/packages/block-editor/src/components/block-inspector/style.scss +++ b/packages/block-editor/src/components/block-inspector/style.scss @@ -55,8 +55,3 @@ .block-editor-block-inspector__tab-item { flex: 1 1 0px; } - -.block-editor-block-inspector__block-buttons-container { - border-top: $border-width solid $gray-200; - padding: $grid-unit-20; -} diff --git a/packages/block-editor/src/components/block-quick-navigation/index.js b/packages/block-editor/src/components/block-quick-navigation/index.js new file mode 100644 index 0000000000000..35f24255b9ba6 --- /dev/null +++ b/packages/block-editor/src/components/block-quick-navigation/index.js @@ -0,0 +1,74 @@ +/** + * WordPress dependencies + */ +import { useSelect, useDispatch } from '@wordpress/data'; +import { + Button, + __experimentalVStack as VStack, + __experimentalHStack as HStack, + FlexItem, +} from '@wordpress/components'; +import { getBlockType, __experimentalGetBlockLabel } from '@wordpress/blocks'; + +/** + * Internal dependencies + */ +import { store as blockEditorStore } from '../../store'; +import BlockIcon from '../block-icon'; + +export default function BlockQuickNavigation( { clientIds } ) { + if ( ! clientIds.length ) { + return null; + } + return ( + + { clientIds.map( ( clientId ) => ( + + ) ) } + + ); +} + +function BlockQuickNavigationItem( { clientId } ) { + const { name, attributes, isSelected } = useSelect( + ( select ) => { + const { + getBlockName, + getBlockAttributes, + isBlockSelected, + hasSelectedInnerBlock, + } = select( blockEditorStore ); + return { + name: getBlockName( clientId ), + attributes: getBlockAttributes( clientId ), + isSelected: + isBlockSelected( clientId ) || + hasSelectedInnerBlock( clientId, /* deep: */ true ), + }; + }, + [ clientId ] + ); + const { selectBlock } = useDispatch( blockEditorStore ); + const blockType = getBlockType( name ); + return ( + + ); +} diff --git a/packages/block-editor/src/private-apis.js b/packages/block-editor/src/private-apis.js index 0572a67dbbd24..00bce45892ccd 100644 --- a/packages/block-editor/src/private-apis.js +++ b/packages/block-editor/src/private-apis.js @@ -11,6 +11,7 @@ import BlockInfo from './components/block-info-slot-fill'; import { useShouldContextualToolbarShow } from './utils/use-should-contextual-toolbar-show'; import { cleanEmptyObject } from './hooks/utils'; import { useBlockEditingMode } from './components/block-editing-mode'; +import BlockQuickNavigation from './components/block-quick-navigation'; /** * Private @wordpress/block-editor APIs. @@ -26,4 +27,5 @@ lock( privateApis, { useShouldContextualToolbarShow, cleanEmptyObject, useBlockEditingMode, + BlockQuickNavigation, } ); diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index 5b615f67defbd..10bf42ec23094 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -303,10 +303,13 @@ export const __experimentalGetGlobalBlocksByName = createSelector( if ( ! blockName ) { return EMPTY_ARRAY; } + const blockNames = Array.isArray( blockName ) + ? blockName + : [ blockName ]; const clientIds = getClientIdsWithDescendants( state ); const foundBlocks = clientIds.filter( ( clientId ) => { const block = state.blocks.byClientId.get( clientId ); - return block.name === blockName; + return blockNames.includes( block.name ); } ); return foundBlocks.length > 0 ? foundBlocks : EMPTY_ARRAY; }, diff --git a/packages/edit-site/src/components/sidebar-edit-mode/page-panels/content-blocks-list.js b/packages/edit-site/src/components/sidebar-edit-mode/page-panels/content-blocks-list.js deleted file mode 100644 index 66f8ba28bcf14..0000000000000 --- a/packages/edit-site/src/components/sidebar-edit-mode/page-panels/content-blocks-list.js +++ /dev/null @@ -1,77 +0,0 @@ -/** - * WordPress dependencies - */ -import { useSelect, useDispatch } from '@wordpress/data'; -import { - Button, - __experimentalVStack as VStack, - __experimentalHStack as HStack, - FlexItem, -} from '@wordpress/components'; -import { getBlockType, __experimentalGetBlockLabel } from '@wordpress/blocks'; -import { store as blockEditorStore, BlockIcon } from '@wordpress/block-editor'; - -/** - * Internal dependencies - */ -import { PAGE_CONTENT_BLOCK_TYPES } from '../../page-content-focus/constants'; - -// TODO: This overlaps a lot with BlockInspectorLockedBlocks in -// @wordpress/block-editor. DRY them into a single component. -export default function ContentBlocksList() { - const contentBlocks = useSelect( ( select ) => { - const { - getClientIdsWithDescendants, - getBlockName, - getBlock, - isBlockSelected, - hasSelectedInnerBlock, - } = select( blockEditorStore ); - return getClientIdsWithDescendants().flatMap( ( clientId ) => { - const blockName = getBlockName( clientId ); - if ( ! PAGE_CONTENT_BLOCK_TYPES.includes( blockName ) ) { - return []; - } - return [ - { - block: getBlock( clientId ), - isSelected: - isBlockSelected( clientId ) || - hasSelectedInnerBlock( clientId, /* deep: */ true ), - }, - ]; - } ); - }, [] ); - - const { selectBlock } = useDispatch( blockEditorStore ); - - if ( ! contentBlocks.length ) { - return null; - } - - return ( - - { contentBlocks.map( ( { block, isSelected } ) => { - const blockType = getBlockType( block.name ); - return ( - - ); - } ) } - - ); -} diff --git a/packages/edit-site/src/components/sidebar-edit-mode/page-panels/index.js b/packages/edit-site/src/components/sidebar-edit-mode/page-panels/index.js index 3a0b501f9271a..c2df78f4185af 100644 --- a/packages/edit-site/src/components/sidebar-edit-mode/page-panels/index.js +++ b/packages/edit-site/src/components/sidebar-edit-mode/page-panels/index.js @@ -20,7 +20,7 @@ import { useMemo } from '@wordpress/element'; import { store as editSiteStore } from '../../../store'; import useEditedEntityRecord from '../../use-edited-entity-record'; import SidebarCard from '../sidebar-card'; -import ContentBlocksList from './content-blocks-list'; +import PageContent from './page-content'; export default function PagePanels() { const context = useSelect( @@ -62,7 +62,7 @@ export default function PagePanels() { /> - + diff --git a/packages/edit-site/src/components/sidebar-edit-mode/page-panels/page-content.js b/packages/edit-site/src/components/sidebar-edit-mode/page-panels/page-content.js new file mode 100644 index 0000000000000..fad6a2c3a8cf2 --- /dev/null +++ b/packages/edit-site/src/components/sidebar-edit-mode/page-panels/page-content.js @@ -0,0 +1,27 @@ +/** + * WordPress dependencies + */ +import { useSelect } from '@wordpress/data'; +import { + store as blockEditorStore, + privateApis as blockEditorPrivateApis, +} from '@wordpress/block-editor'; + +/** + * Internal dependencies + */ +import { PAGE_CONTENT_BLOCK_TYPES } from '../../page-content-focus/constants'; +import { unlock } from '../../../private-apis'; + +const { BlockQuickNavigation } = unlock( blockEditorPrivateApis ); + +export default function PageContent() { + const clientIds = useSelect( + ( select ) => + select( blockEditorStore ).__experimentalGetGlobalBlocksByName( + PAGE_CONTENT_BLOCK_TYPES + ), + [] + ); + return ; +}