diff --git a/packages/block-editor/src/components/block-navigation/block-slot.js b/packages/block-editor/src/components/block-navigation/block-slot.js index 9be9795317e6c7..9615d214b2c1b4 100644 --- a/packages/block-editor/src/components/block-navigation/block-slot.js +++ b/packages/block-editor/src/components/block-navigation/block-slot.js @@ -9,6 +9,7 @@ import classnames from 'classnames'; import { getBlockType } from '@wordpress/blocks'; import { Fill, Slot, VisuallyHidden } from '@wordpress/components'; import { useInstanceId } from '@wordpress/compose'; +import { useSelect } from '@wordpress/data'; import { Children, cloneElement, @@ -24,12 +25,17 @@ import BlockIcon from '../block-icon'; import { BlockListBlockContext } from '../block-list/block'; import BlockNavigationBlockSelectButton from './block-select-button'; import { getBlockPositionDescription } from './utils'; +import { store as blockEditorStore } from '../../store'; const getSlotName = ( clientId ) => `BlockNavigationBlock-${ clientId }`; function BlockNavigationBlockSlot( props, ref ) { - const instanceId = useInstanceId( BlockNavigationBlockSlot ); const { clientId } = props.block; + const { name } = useSelect( + ( select ) => select( blockEditorStore ).getBlockName( clientId ), + [ clientId ] + ); + const instanceId = useInstanceId( BlockNavigationBlockSlot ); return ( @@ -45,7 +51,6 @@ function BlockNavigationBlockSlot( props, ref ) { const { className, - block, isSelected, position, siblingBlockCount, @@ -54,7 +59,6 @@ function BlockNavigationBlockSlot( props, ref ) { onFocus, } = props; - const { name } = block; const blockType = getBlockType( name ); const descriptionId = `block-navigation-block-slot__${ instanceId }`; const blockPositionDescription = getBlockPositionDescription( diff --git a/packages/block-editor/src/components/block-navigation/index.js b/packages/block-editor/src/components/block-navigation/index.js index 0f3991cd92242d..f6121bac8c6fc5 100644 --- a/packages/block-editor/src/components/block-navigation/index.js +++ b/packages/block-editor/src/components/block-navigation/index.js @@ -6,8 +6,7 @@ import { noop } from 'lodash'; /** * WordPress dependencies */ -import { withSelect, withDispatch } from '@wordpress/data'; -import { compose } from '@wordpress/compose'; +import { useDispatch, useSelect } from '@wordpress/data'; import { __ } from '@wordpress/i18n'; /** @@ -16,13 +15,41 @@ import { __ } from '@wordpress/i18n'; import BlockNavigationTree from './tree'; import { store as blockEditorStore } from '../../store'; -function BlockNavigation( { - rootBlock, - rootBlocks, - selectedBlockClientId, - selectBlock, +export default function BlockNavigation( { + onSelect = noop, __experimentalFeatures, } ) { + const { rootBlock, rootBlocks, selectedBlockClientId } = useSelect( + ( select ) => { + const { + getBlockHierarchyRootClientId, + getSelectedBlockClientId, + __unstableGetClientIdsTree, + __unstableGetClientIdWithClientIdsTree, + } = select( blockEditorStore ); + + const _selectedBlockClientId = getSelectedBlockClientId(); + const _rootBlocks = __unstableGetClientIdsTree(); + const _rootBlock = _selectedBlockClientId + ? __unstableGetClientIdWithClientIdsTree( + getBlockHierarchyRootClientId( _selectedBlockClientId ) + ) + : null; + + return { + rootBlock: _rootBlock, + rootBlocks: _rootBlocks, + selectedBlockClientId: _selectedBlockClientId, + }; + } + ); + const { selectBlock } = useDispatch( blockEditorStore ); + + function selectEditorBlock( clientId ) { + selectBlock( clientId ); + onSelect( clientId ); + } + if ( ! rootBlocks || rootBlocks.length === 0 ) { return null; } @@ -41,39 +68,10 @@ function BlockNavigation( { ); } - -export default compose( - withSelect( ( select ) => { - const { - getSelectedBlockClientId, - getBlockHierarchyRootClientId, - __unstableGetBlockWithBlockTree, - __unstableGetBlockTree, - } = select( blockEditorStore ); - const selectedBlockClientId = getSelectedBlockClientId(); - return { - rootBlocks: __unstableGetBlockTree(), - rootBlock: selectedBlockClientId - ? __unstableGetBlockWithBlockTree( - getBlockHierarchyRootClientId( selectedBlockClientId ) - ) - : null, - selectedBlockClientId, - }; - } ), - withDispatch( ( dispatch, { onSelect = noop } ) => { - return { - selectBlock( clientId ) { - dispatch( blockEditorStore ).selectBlock( clientId ); - onSelect( clientId ); - }, - }; - } ) -)( BlockNavigation ); diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index 1e6e1a2073ae3f..fdb74c6bcfe837 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -265,6 +265,41 @@ export const __unstableGetBlockTree = createSelector( ] ); +/** + * Returns a stripped down block object containing only its client ID, + * and its inner blocks' client IDs. + * + * @param {Object} state Editor state. + * @param {string} clientId Client ID of the block to get. + * + * @return {Object} Client IDs of the post blocks. + */ +export const __unstableGetClientIdWithClientIdsTree = createSelector( + ( state, clientId ) => ( { + clientId, + innerBlocks: __unstableGetClientIdsTree( state, clientId ), + } ), + ( state ) => [ state.blocks.order ] +); + +/** + * Returns the block tree represented in the block-editor store from the + * given root, consisting of stripped down block objects containing only + * their client IDs, and their inner blocks' client IDs. + * + * @param {Object} state Editor state. + * @param {?string} rootClientId Optional root client ID of block list. + * + * @return {Object[]} Client IDs of the post blocks. + */ +export const __unstableGetClientIdsTree = createSelector( + ( state, rootClientId = '' ) => + map( getBlockOrder( state, rootClientId ), ( clientId ) => + __unstableGetClientIdWithClientIdsTree( state, clientId ) + ), + ( state ) => [ state.blocks.order ] +); + /** * Returns an array containing the clientIds of all descendants * of the blocks given. diff --git a/packages/block-editor/src/store/test/selectors.js b/packages/block-editor/src/store/test/selectors.js index 3d2e058dd844f6..817b1ffc31990f 100644 --- a/packages/block-editor/src/store/test/selectors.js +++ b/packages/block-editor/src/store/test/selectors.js @@ -73,6 +73,8 @@ const { __experimentalGetParsedReusableBlock, __experimentalGetAllowedPatterns, __experimentalGetScopedBlockPatterns, + __unstableGetClientIdWithClientIdsTree, + __unstableGetClientIdsTree, } = selectors; describe( 'selectors', () => { @@ -3535,3 +3537,76 @@ describe( 'getInserterItems with core blocks prioritization', () => { expect( items.map( ( { name } ) => name ) ).toEqual( expectedResult ); } ); } ); + +describe( '__unstableGetClientIdWithClientIdsTree', () => { + it( "should return a stripped down block object containing only its client ID and its inner blocks' client IDs", () => { + const state = { + blocks: { + order: { + '': [ 'foo' ], + foo: [ 'bar', 'baz' ], + bar: [ 'qux' ], + }, + }, + }; + + expect( + __unstableGetClientIdWithClientIdsTree( state, 'foo' ) + ).toEqual( { + clientId: 'foo', + innerBlocks: [ + { + clientId: 'bar', + innerBlocks: [ { clientId: 'qux', innerBlocks: [] } ], + }, + { clientId: 'baz', innerBlocks: [] }, + ], + } ); + } ); +} ); +describe( '__unstableGetClientIdsTree', () => { + it( "should return the full content tree starting from the given root, consisting of stripped down block object containing only its client ID and its inner blocks' client IDs", () => { + const state = { + blocks: { + order: { + '': [ 'foo' ], + foo: [ 'bar', 'baz' ], + bar: [ 'qux' ], + }, + }, + }; + + expect( __unstableGetClientIdsTree( state, 'foo' ) ).toEqual( [ + { + clientId: 'bar', + innerBlocks: [ { clientId: 'qux', innerBlocks: [] } ], + }, + { clientId: 'baz', innerBlocks: [] }, + ] ); + } ); + + it( "should return the full content tree starting from the root, consisting of stripped down block object containing only its client ID and its inner blocks' client IDs", () => { + const state = { + blocks: { + order: { + '': [ 'foo' ], + foo: [ 'bar', 'baz' ], + bar: [ 'qux' ], + }, + }, + }; + + expect( __unstableGetClientIdsTree( state ) ).toEqual( [ + { + clientId: 'foo', + innerBlocks: [ + { + clientId: 'bar', + innerBlocks: [ { clientId: 'qux', innerBlocks: [] } ], + }, + { clientId: 'baz', innerBlocks: [] }, + ], + }, + ] ); + } ); +} ); diff --git a/packages/block-library/src/navigation/block-navigation-list.js b/packages/block-library/src/navigation/block-navigation-list.js index 638609067ea9d0..43dfc64518d676 100644 --- a/packages/block-library/src/navigation/block-navigation-list.js +++ b/packages/block-library/src/navigation/block-navigation-list.js @@ -11,14 +11,15 @@ export default function BlockNavigationList( { clientId, __experimentalFeatures, } ) { - const { block, selectedBlockClientId } = useSelect( + const { blocks, selectedBlockClientId } = useSelect( ( select ) => { - const { getSelectedBlockClientId, getBlock } = select( - blockEditorStore - ); + const { + getSelectedBlockClientId, + __unstableGetClientIdsTree, + } = select( blockEditorStore ); return { - block: getBlock( clientId ), + blocks: __unstableGetClientIdsTree( clientId ), selectedBlockClientId: getSelectedBlockClientId(), }; }, @@ -29,7 +30,7 @@ export default function BlockNavigationList( { return ( <__experimentalBlockNavigationTree - blocks={ block.innerBlocks } + blocks={ blocks } selectedBlockClientId={ selectedBlockClientId } selectBlock={ selectBlock } __experimentalFeatures={ __experimentalFeatures } diff --git a/packages/edit-site/src/components/editor/index.js b/packages/edit-site/src/components/editor/index.js index eff877009255f2..9a7255a1d2b250 100644 --- a/packages/edit-site/src/components/editor/index.js +++ b/packages/edit-site/src/components/editor/index.js @@ -2,7 +2,7 @@ * WordPress dependencies */ import { useEffect, useState, useMemo, useCallback } from '@wordpress/element'; -import { useSelect, useDispatch } from '@wordpress/data'; +import { AsyncModeProvider, useSelect, useDispatch } from '@wordpress/data'; import { SlotFillProvider, DropZoneProvider, @@ -158,7 +158,11 @@ function Editor( { initialSettings } ) { return ; } if ( isListViewOpen ) { - return ; + return ( + + + + ); } return null; }; diff --git a/packages/edit-site/src/components/secondary-sidebar/list-view-sidebar.js b/packages/edit-site/src/components/secondary-sidebar/list-view-sidebar.js index 0deaffc1f64b4d..efc93f8a957869 100644 --- a/packages/edit-site/src/components/secondary-sidebar/list-view-sidebar.js +++ b/packages/edit-site/src/components/secondary-sidebar/list-view-sidebar.js @@ -23,12 +23,12 @@ import { ESCAPE } from '@wordpress/keycodes'; import { store as editSiteStore } from '../../store'; export default function ListViewSidebar() { - const { rootBlocks, selectedBlockClientId } = useSelect( ( select ) => { - const { getSelectedBlockClientId, __unstableGetBlockTree } = select( + const { clientIdsTree, selectedBlockClientId } = useSelect( ( select ) => { + const { __unstableGetClientIdsTree, getSelectedBlockClientId } = select( blockEditorStore ); return { - rootBlocks: __unstableGetBlockTree(), + clientIdsTree: __unstableGetClientIdsTree(), selectedBlockClientId: getSelectedBlockClientId(), }; } ); @@ -72,7 +72,7 @@ export default function ListViewSidebar() { ref={ useMergeRefs( [ focusReturnRef, focusOnMountRef ] ) } >