diff --git a/packages/block-editor/src/components/block-navigation/dropdown.js b/packages/block-editor/src/components/block-navigation/dropdown.js index bb3fd2eb453dd2..de7345280387ad 100644 --- a/packages/block-editor/src/components/block-navigation/dropdown.js +++ b/packages/block-editor/src/components/block-navigation/dropdown.js @@ -10,7 +10,7 @@ import { listView } from '@wordpress/icons'; /** * Internal dependencies */ -import BlockNavigation from './'; +import BlockNavigationTree from './tree'; import { store as blockEditorStore } from '../../store'; function BlockNavigationDropdownToggle( { @@ -60,9 +60,17 @@ function BlockNavigationDropdown( /> ) } renderContent={ () => ( - +
+

+ { __( 'List view' ) } +

+ + +
) } /> ); diff --git a/packages/block-editor/src/components/block-navigation/index.js b/packages/block-editor/src/components/block-navigation/index.js deleted file mode 100644 index 48c20ae9ae1444..00000000000000 --- a/packages/block-editor/src/components/block-navigation/index.js +++ /dev/null @@ -1,81 +0,0 @@ -/** - * External dependencies - */ -import { isArray, noop } from 'lodash'; - -/** - * WordPress dependencies - */ -import { useDispatch, useSelect } from '@wordpress/data'; -import { __ } from '@wordpress/i18n'; - -/** - * Internal dependencies - */ -import BlockNavigationTree from './tree'; -import { isClientIdSelected } from './utils'; -import { store as blockEditorStore } from '../../store'; - -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 && ! isArray( _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; - } - - const hasHierarchy = - rootBlock && - ( ! isClientIdSelected( rootBlock.clientId, selectedBlockClientId ) || - ( rootBlock.innerBlocks && rootBlock.innerBlocks.length !== 0 ) ); - - return ( -
-

- { __( 'List view' ) } -

- - -
- ); -} diff --git a/packages/block-editor/src/components/block-navigation/tree.js b/packages/block-editor/src/components/block-navigation/tree.js index e1a9b4a8302b71..f8e64233935b6b 100644 --- a/packages/block-editor/src/components/block-navigation/tree.js +++ b/packages/block-editor/src/components/block-navigation/tree.js @@ -3,29 +3,56 @@ */ import { __experimentalTreeGrid as TreeGrid } from '@wordpress/components'; -import { useEffect, useMemo, useRef } from '@wordpress/element'; +import { useDispatch } from '@wordpress/data'; +import { useCallback, useEffect, useMemo, useRef } from '@wordpress/element'; import { __ } from '@wordpress/i18n'; + /** * Internal dependencies */ import BlockNavigationBranch from './branch'; import { BlockNavigationContext } from './context'; +import useBlockNavigationClientIds from './use-block-navigation-client-ids'; import useBlockNavigationDropZone from './use-block-navigation-drop-zone'; +import { store as blockEditorStore } from '../../store'; + +const noop = () => {}; /** * Wrap `BlockNavigationRows` with `TreeGrid`. BlockNavigationRows is a * recursive component (it renders itself), so this ensures TreeGrid is only * present at the very top of the navigation grid. * - * @param {Object} props Components props. - * @param {boolean} props.__experimentalFeatures Flag to enable experimental features. - * @param {boolean} props.__experimentalPersistentListViewFeatures Flag to enable features for the Persistent List View experiment. + * @param {Object} props Components props. + * @param {Array} props.blocks Custom subset of block client IDs to be used instead of the default hierarchy. + * @param {Function} props.onSelect Block selection callback. + * @param {boolean} props.showNestedBlocks Flag to enable displaying nested blocks. + * @param {boolean} props.showOnlyCurrentHierarchy Flag to limit the list to the current hierarchy of blocks. + * @param {boolean} props.__experimentalFeatures Flag to enable experimental features. + * @param {boolean} props.__experimentalPersistentListViewFeatures Flag to enable features for the Persistent List View experiment. */ export default function BlockNavigationTree( { + blocks, + showOnlyCurrentHierarchy, + onSelect = noop, __experimentalFeatures, __experimentalPersistentListViewFeatures, ...props } ) { + const { clientIdsTree, selectedClientIds } = useBlockNavigationClientIds( + blocks, + showOnlyCurrentHierarchy, + __experimentalPersistentListViewFeatures + ); + const { selectBlock } = useDispatch( blockEditorStore ); + const selectEditorBlock = useCallback( + ( clientId ) => { + selectBlock( clientId ); + onSelect( clientId ); + }, + [ selectBlock, onSelect ] + ); + let { ref: treeGridRef, target: blockDropTarget, @@ -62,7 +89,12 @@ export default function BlockNavigationTree( { ref={ treeGridRef } > - + ); diff --git a/packages/block-editor/src/components/block-navigation/use-block-navigation-client-ids.js b/packages/block-editor/src/components/block-navigation/use-block-navigation-client-ids.js new file mode 100644 index 00000000000000..e68cadf582de84 --- /dev/null +++ b/packages/block-editor/src/components/block-navigation/use-block-navigation-client-ids.js @@ -0,0 +1,88 @@ +/** + * WordPress dependencies + */ + +import { useSelect } from '@wordpress/data'; + +/** + * Internal dependencies + */ +import { isClientIdSelected } from './utils'; +import { store as blockEditorStore } from '../../store'; + +const useBlockNavigationSelectedClientIds = ( + __experimentalPersistentListViewFeatures +) => + useSelect( + ( select ) => { + const { + getSelectedBlockClientId, + getSelectedBlockClientIds, + } = select( blockEditorStore ); + + if ( __experimentalPersistentListViewFeatures ) { + return getSelectedBlockClientIds(); + } + + return getSelectedBlockClientId(); + }, + [ __experimentalPersistentListViewFeatures ] + ); + +const useBlockNavigationClientIdsTree = ( + blocks, + selectedClientIds, + showOnlyCurrentHierarchy +) => + useSelect( + ( select ) => { + const { + getBlockHierarchyRootClientId, + __unstableGetClientIdsTree, + __unstableGetClientIdWithClientIdsTree, + } = select( blockEditorStore ); + + if ( blocks ) { + return blocks; + } + + const isSingleBlockSelected = + selectedClientIds && ! Array.isArray( selectedClientIds ); + if ( ! showOnlyCurrentHierarchy || ! isSingleBlockSelected ) { + return __unstableGetClientIdsTree(); + } + + const rootBlock = __unstableGetClientIdWithClientIdsTree( + getBlockHierarchyRootClientId( selectedClientIds ) + ); + if ( ! rootBlock ) { + return __unstableGetClientIdsTree(); + } + + const hasHierarchy = + ! isClientIdSelected( rootBlock.clientId, selectedClientIds ) || + ( rootBlock.innerBlocks && rootBlock.innerBlocks.length !== 0 ); + if ( hasHierarchy ) { + return [ rootBlock ]; + } + + return __unstableGetClientIdsTree(); + }, + [ blocks, selectedClientIds, showOnlyCurrentHierarchy ] + ); + +export default function useBlockNavigationClientIds( + blocks, + showOnlyCurrentHierarchy, + __experimentalPersistentListViewFeatures +) { + const selectedClientIds = useBlockNavigationSelectedClientIds( + __experimentalPersistentListViewFeatures + ); + const clientIdsTree = useBlockNavigationClientIdsTree( + blocks, + selectedClientIds, + showOnlyCurrentHierarchy + ); + return { clientIdsTree, selectedClientIds }; +} diff --git a/packages/block-library/src/navigation/block-navigation-list.js b/packages/block-library/src/navigation/block-navigation-list.js index 057c4e6396b049..4b3f68470ed1df 100644 --- a/packages/block-library/src/navigation/block-navigation-list.js +++ b/packages/block-library/src/navigation/block-navigation-list.js @@ -5,38 +5,25 @@ import { __experimentalBlockNavigationTree, store as blockEditorStore, } from '@wordpress/block-editor'; -import { useSelect, useDispatch } from '@wordpress/data'; +import { useSelect } from '@wordpress/data'; export default function BlockNavigationList( { clientId, __experimentalFeatures, } ) { - const { blocks, selectedBlockClientId } = useSelect( - ( select ) => { - const { - getSelectedBlockClientId, - __unstableGetClientIdsTree, - } = select( blockEditorStore ); - - return { - blocks: __unstableGetClientIdsTree( clientId ), - selectedBlockClientId: getSelectedBlockClientId(), - }; - }, + const blocks = useSelect( + ( select ) => + select( blockEditorStore ).__unstableGetClientIdsTree( clientId ), [ clientId ] ); - const { selectBlock } = useDispatch( blockEditorStore ); - return ( <__experimentalBlockNavigationTree blocks={ blocks } - selectedBlockClientIds={ [ selectedBlockClientId ] } - selectBlock={ selectBlock } - __experimentalFeatures={ __experimentalFeatures } - showNestedBlocks showAppender showBlockMovers + showNestedBlocks + __experimentalFeatures={ __experimentalFeatures } /> ); } diff --git a/packages/edit-post/src/components/secondary-sidebar/list-view-sidebar.js b/packages/edit-post/src/components/secondary-sidebar/list-view-sidebar.js index 332ba89857358e..d7947e437c4c56 100644 --- a/packages/edit-post/src/components/secondary-sidebar/list-view-sidebar.js +++ b/packages/edit-post/src/components/secondary-sidebar/list-view-sidebar.js @@ -12,7 +12,7 @@ import { useInstanceId, useMergeRefs, } from '@wordpress/compose'; -import { useDispatch, useSelect } from '@wordpress/data'; +import { useDispatch } from '@wordpress/data'; import { __ } from '@wordpress/i18n'; import { closeSmall } from '@wordpress/icons'; import { ESCAPE } from '@wordpress/keycodes'; @@ -23,16 +23,6 @@ import { ESCAPE } from '@wordpress/keycodes'; import { store as editPostStore } from '../../store'; export default function ListViewSidebar() { - const { clientIdsTree, selectedBlockClientIds } = useSelect( ( select ) => { - const { - __unstableGetClientIdsTree, - getSelectedBlockClientIds, - } = select( blockEditorStore ); - return { - clientIdsTree: __unstableGetClientIdsTree(), - selectedBlockClientIds: getSelectedBlockClientIds(), - }; - }, [] ); const { setIsListViewOpened } = useDispatch( editPostStore ); const { clearSelectedBlock, selectBlock } = useDispatch( blockEditorStore ); @@ -73,9 +63,7 @@ export default function ListViewSidebar() { ref={ useMergeRefs( [ focusReturnRef, focusOnMountRef ] ) } > 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 217a4bf192ffa5..86bdf3bf05bb4f 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 @@ -12,7 +12,7 @@ import { useInstanceId, useMergeRefs, } from '@wordpress/compose'; -import { useDispatch, useSelect } from '@wordpress/data'; +import { useDispatch } from '@wordpress/data'; import { __ } from '@wordpress/i18n'; import { closeSmall } from '@wordpress/icons'; import { ESCAPE } from '@wordpress/keycodes'; @@ -23,16 +23,6 @@ import { ESCAPE } from '@wordpress/keycodes'; import { store as editSiteStore } from '../../store'; export default function ListViewSidebar() { - const { clientIdsTree, selectedBlockClientIds } = useSelect( ( select ) => { - const { - __unstableGetClientIdsTree, - getSelectedBlockClientIds, - } = select( blockEditorStore ); - return { - clientIdsTree: __unstableGetClientIdsTree(), - selectedBlockClientIds: getSelectedBlockClientIds(), - }; - }, [] ); const { setIsListViewOpened } = useDispatch( editSiteStore ); const { clearSelectedBlock, selectBlock } = useDispatch( blockEditorStore ); @@ -73,9 +63,7 @@ export default function ListViewSidebar() { ref={ useMergeRefs( [ focusReturnRef, focusOnMountRef ] ) } >