Skip to content

Commit 7555b87

Browse files
committed
Navigtion: Use the ListView in the Navigation block inspector controls
use the hook from list view remove prop drilling remove prop drilling Allow list view to scroll add custom scrollbars on hover update navigation block tests to account for using the list view fix test List View: Add a new prop to allow blocks in the inserter to be prioritized add another prop to list view Don't bother sorting if there are no proitizedInnerBlocks Open LinkUI popover after appending link from Navigation side block inserter The behavior when adding a link from the appender button on the OffCanvasEditor is to open a link control popover. This commit copies over several files from the OffCanvasEditor that was required for that to work in the ListView. The behavior is buggy, IMO, but it does match what is in trunk. inverted colors for the scrollbar Moved files related to navigation block outside of list-view. Remove unused link-ui from list-view Fix webpack runtime error For some reason keeping both exports in the same file caused an error that PrivateListView was used before initialization remove unneeded code to prioritize the blocks in the inserter remove unused prop move the inline function to a separate definition remove unneccessary change
1 parent d24ac78 commit 7555b87

10 files changed

Lines changed: 424 additions & 284 deletions

File tree

packages/block-editor/src/components/list-view/block-contents.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { forwardRef } from '@wordpress/element';
1212
/**
1313
* Internal dependencies
1414
*/
15+
import { unlock } from '../../lock-unlock';
1516
import ListViewBlockSelectButton from './block-select-button';
1617
import BlockDraggable from '../block-draggable';
1718
import { store as blockEditorStore } from '../../store';
@@ -38,7 +39,7 @@ const ListViewBlockContents = forwardRef(
3839
const { blockMovingClientId, selectedBlockInBlockEditor } = useSelect(
3940
( select ) => {
4041
const { hasBlockMovingClientId, getSelectedBlockClientId } =
41-
select( blockEditorStore );
42+
unlock( select( blockEditorStore ) );
4243
return {
4344
blockMovingClientId: hasBlockMovingClientId(),
4445
selectedBlockInBlockEditor: getSelectedBlockClientId(),
Lines changed: 6 additions & 260 deletions
Original file line numberDiff line numberDiff line change
@@ -1,281 +1,27 @@
11
/**
22
* WordPress dependencies
33
*/
4-
import {
5-
useInstanceId,
6-
useMergeRefs,
7-
__experimentalUseFixedWindowList as useFixedWindowList,
8-
} from '@wordpress/compose';
9-
import { __experimentalTreeGrid as TreeGrid } from '@wordpress/components';
10-
import { AsyncModeProvider, useSelect } from '@wordpress/data';
11-
import deprecated from '@wordpress/deprecated';
12-
import {
13-
useCallback,
14-
useEffect,
15-
useMemo,
16-
useRef,
17-
useReducer,
18-
forwardRef,
19-
} from '@wordpress/element';
20-
import { __ } from '@wordpress/i18n';
4+
import { forwardRef } from '@wordpress/element';
215

226
/**
237
* Internal dependencies
248
*/
25-
import ListViewBranch from './branch';
26-
import { ListViewContext } from './context';
27-
import ListViewDropIndicator from './drop-indicator';
28-
import useBlockSelection from './use-block-selection';
29-
import useListViewClientIds from './use-list-view-client-ids';
30-
import useListViewDropZone from './use-list-view-drop-zone';
31-
import useListViewExpandSelectedItem from './use-list-view-expand-selected-item';
32-
import { store as blockEditorStore } from '../../store';
33-
import { BlockSettingsDropdown } from '../block-settings-menu/block-settings-dropdown';
9+
import { unlock } from '../../lock-unlock';
10+
import { privateApis as blockEditorPrivateApis } from '../../private-apis';
3411

35-
const expanded = ( state, action ) => {
36-
if ( Array.isArray( action.clientIds ) ) {
37-
return {
38-
...state,
39-
...action.clientIds.reduce(
40-
( newState, id ) => ( {
41-
...newState,
42-
[ id ]: action.type === 'expand',
43-
} ),
44-
{}
45-
),
46-
};
47-
}
48-
return state;
49-
};
12+
export { BLOCK_LIST_ITEM_HEIGHT } from './private-list-view';
5013

51-
export const BLOCK_LIST_ITEM_HEIGHT = 36;
52-
53-
/** @typedef {import('react').ComponentType} ComponentType */
54-
/** @typedef {import('react').Ref<HTMLElement>} Ref */
55-
56-
/**
57-
* Show a hierarchical list of blocks.
58-
*
59-
* @param {Object} props Components props.
60-
* @param {string} props.id An HTML element id for the root element of ListView.
61-
* @param {Array} props.blocks _deprecated_ Custom subset of block client IDs to be used instead of the default hierarchy.
62-
* @param {?boolean} props.showBlockMovers Flag to enable block movers. Defaults to `false`.
63-
* @param {?boolean} props.isExpanded Flag to determine whether nested levels are expanded by default. Defaults to `false`.
64-
* @param {?boolean} props.showAppender Flag to show or hide the block appender. Defaults to `false`.
65-
* @param {?ComponentType} props.blockSettingsMenu Optional more menu substitution. Defaults to the standard `BlockSettingsDropdown` component.
66-
* @param {string} props.rootClientId The client id of the root block from which we determine the blocks to show in the list.
67-
* @param {string} props.description Optional accessible description for the tree grid component.
68-
* @param {?Function} props.onSelect Optional callback to be invoked when a block is selected. Receives the block object that was selected.
69-
* @param {Function} props.renderAdditionalBlockUI Function that renders additional block content UI.
70-
* @param {Ref} ref Forwarded ref
71-
*/
72-
function ListViewComponent(
73-
{
74-
id,
75-
blocks,
76-
showBlockMovers = false,
77-
isExpanded = false,
78-
showAppender = false,
79-
blockSettingsMenu: BlockSettingsMenu = BlockSettingsDropdown,
80-
rootClientId,
81-
description,
82-
onSelect,
83-
renderAdditionalBlockUI,
84-
},
85-
ref
86-
) {
87-
// This can be removed once we no longer need to support the blocks prop.
88-
if ( blocks ) {
89-
deprecated(
90-
'`blocks` property in `wp.blockEditor.__experimentalListView`',
91-
{
92-
since: '6.3',
93-
alternative: '`rootClientId` property',
94-
}
95-
);
96-
}
97-
98-
const instanceId = useInstanceId( ListViewComponent );
99-
const { clientIdsTree, draggedClientIds, selectedClientIds } =
100-
useListViewClientIds( { blocks, rootClientId } );
101-
102-
const { getBlock } = useSelect( blockEditorStore );
103-
const { visibleBlockCount, shouldShowInnerBlocks } = useSelect(
104-
( select ) => {
105-
const {
106-
getGlobalBlockCount,
107-
getClientIdsOfDescendants,
108-
__unstableGetEditorMode,
109-
} = select( blockEditorStore );
110-
const draggedBlockCount =
111-
draggedClientIds?.length > 0
112-
? getClientIdsOfDescendants( draggedClientIds ).length + 1
113-
: 0;
114-
return {
115-
visibleBlockCount: getGlobalBlockCount() - draggedBlockCount,
116-
shouldShowInnerBlocks: __unstableGetEditorMode() !== 'zoom-out',
117-
};
118-
},
119-
[ draggedClientIds ]
120-
);
121-
122-
const { updateBlockSelection } = useBlockSelection();
123-
124-
const [ expandedState, setExpandedState ] = useReducer( expanded, {} );
125-
126-
const { ref: dropZoneRef, target: blockDropTarget } = useListViewDropZone();
127-
const elementRef = useRef();
128-
const treeGridRef = useMergeRefs( [ elementRef, dropZoneRef, ref ] );
129-
130-
const isMounted = useRef( false );
131-
const { setSelectedTreeId } = useListViewExpandSelectedItem( {
132-
firstSelectedBlockClientId: selectedClientIds[ 0 ],
133-
setExpandedState,
134-
} );
135-
const selectEditorBlock = useCallback(
136-
( event, blockClientId ) => {
137-
updateBlockSelection( event, blockClientId );
138-
setSelectedTreeId( blockClientId );
139-
if ( onSelect ) {
140-
onSelect( getBlock( blockClientId ) );
141-
}
142-
},
143-
[ setSelectedTreeId, updateBlockSelection, onSelect, getBlock ]
144-
);
145-
useEffect( () => {
146-
isMounted.current = true;
147-
}, [] );
148-
149-
// List View renders a fixed number of items and relies on each having a fixed item height of 36px.
150-
// If this value changes, we should also change the itemHeight value set in useFixedWindowList.
151-
// See: https://github.com/WordPress/gutenberg/pull/35230 for additional context.
152-
const [ fixedListWindow ] = useFixedWindowList(
153-
elementRef,
154-
BLOCK_LIST_ITEM_HEIGHT,
155-
visibleBlockCount,
156-
{
157-
useWindowing: true,
158-
windowOverscan: 40,
159-
}
160-
);
161-
162-
const expand = useCallback(
163-
( clientId ) => {
164-
if ( ! clientId ) {
165-
return;
166-
}
167-
setExpandedState( { type: 'expand', clientIds: [ clientId ] } );
168-
},
169-
[ setExpandedState ]
170-
);
171-
const collapse = useCallback(
172-
( clientId ) => {
173-
if ( ! clientId ) {
174-
return;
175-
}
176-
setExpandedState( { type: 'collapse', clientIds: [ clientId ] } );
177-
},
178-
[ setExpandedState ]
179-
);
180-
const expandRow = useCallback(
181-
( row ) => {
182-
expand( row?.dataset?.block );
183-
},
184-
[ expand ]
185-
);
186-
const collapseRow = useCallback(
187-
( row ) => {
188-
collapse( row?.dataset?.block );
189-
},
190-
[ collapse ]
191-
);
192-
const focusRow = useCallback(
193-
( event, startRow, endRow ) => {
194-
if ( event.shiftKey ) {
195-
updateBlockSelection(
196-
event,
197-
startRow?.dataset?.block,
198-
endRow?.dataset?.block
199-
);
200-
}
201-
},
202-
[ updateBlockSelection ]
203-
);
204-
205-
const contextValue = useMemo(
206-
() => ( {
207-
isTreeGridMounted: isMounted.current,
208-
draggedClientIds,
209-
expandedState,
210-
expand,
211-
collapse,
212-
BlockSettingsMenu,
213-
listViewInstanceId: instanceId,
214-
renderAdditionalBlockUI,
215-
} ),
216-
[
217-
draggedClientIds,
218-
expandedState,
219-
expand,
220-
collapse,
221-
BlockSettingsMenu,
222-
instanceId,
223-
renderAdditionalBlockUI,
224-
]
225-
);
226-
227-
// If there are no blocks to show, do not render the list view.
228-
if ( ! clientIdsTree.length ) {
229-
return null;
230-
}
231-
232-
return (
233-
<AsyncModeProvider value={ true }>
234-
<ListViewDropIndicator
235-
listViewRef={ elementRef }
236-
blockDropTarget={ blockDropTarget }
237-
/>
238-
<TreeGrid
239-
id={ id }
240-
className="block-editor-list-view-tree"
241-
aria-label={ __( 'Block navigation structure' ) }
242-
ref={ treeGridRef }
243-
onCollapseRow={ collapseRow }
244-
onExpandRow={ expandRow }
245-
onFocusRow={ focusRow }
246-
applicationAriaLabel={ __( 'Block navigation structure' ) }
247-
// eslint-disable-next-line jsx-a11y/aria-props
248-
aria-description={ description }
249-
>
250-
<ListViewContext.Provider value={ contextValue }>
251-
<ListViewBranch
252-
blocks={ clientIdsTree }
253-
parentId={ rootClientId }
254-
selectBlock={ selectEditorBlock }
255-
showBlockMovers={ showBlockMovers }
256-
fixedListWindow={ fixedListWindow }
257-
selectedClientIds={ selectedClientIds }
258-
isExpanded={ isExpanded }
259-
shouldShowInnerBlocks={ shouldShowInnerBlocks }
260-
showAppender={ showAppender }
261-
/>
262-
</ListViewContext.Provider>
263-
</TreeGrid>
264-
</AsyncModeProvider>
265-
);
266-
}
267-
export const PrivateListView = forwardRef( ListViewComponent );
14+
const { PrivateListView } = unlock( blockEditorPrivateApis );
26815

26916
export default forwardRef( ( props, ref ) => {
27017
return (
27118
<PrivateListView
27219
ref={ ref }
27320
{ ...props }
27421
showAppender={ false }
275-
blockSettingsMenu={ BlockSettingsDropdown }
27622
rootClientId={ null }
27723
onSelect={ null }
278-
renderAdditionalBlockUICallback={ null }
24+
renderAdditionalBlockUI={ null }
27925
/>
28026
);
28127
} );

0 commit comments

Comments
 (0)