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 ] ) }
>