-
Notifications
You must be signed in to change notification settings - Fork 4.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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
- Loading branch information
Showing
10 changed files
with
424 additions
and
284 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
266 changes: 6 additions & 260 deletions
266
packages/block-editor/src/components/list-view/index.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,281 +1,27 @@ | ||
/** | ||
* WordPress dependencies | ||
*/ | ||
import { | ||
useInstanceId, | ||
useMergeRefs, | ||
__experimentalUseFixedWindowList as useFixedWindowList, | ||
} from '@wordpress/compose'; | ||
import { __experimentalTreeGrid as TreeGrid } from '@wordpress/components'; | ||
import { AsyncModeProvider, useSelect } from '@wordpress/data'; | ||
import deprecated from '@wordpress/deprecated'; | ||
import { | ||
useCallback, | ||
useEffect, | ||
useMemo, | ||
useRef, | ||
useReducer, | ||
forwardRef, | ||
} from '@wordpress/element'; | ||
import { __ } from '@wordpress/i18n'; | ||
import { forwardRef } from '@wordpress/element'; | ||
|
||
/** | ||
* Internal dependencies | ||
*/ | ||
import ListViewBranch from './branch'; | ||
import { ListViewContext } from './context'; | ||
import ListViewDropIndicator from './drop-indicator'; | ||
import useBlockSelection from './use-block-selection'; | ||
import useListViewClientIds from './use-list-view-client-ids'; | ||
import useListViewDropZone from './use-list-view-drop-zone'; | ||
import useListViewExpandSelectedItem from './use-list-view-expand-selected-item'; | ||
import { store as blockEditorStore } from '../../store'; | ||
import { BlockSettingsDropdown } from '../block-settings-menu/block-settings-dropdown'; | ||
import { unlock } from '../../lock-unlock'; | ||
import { privateApis as blockEditorPrivateApis } from '../../private-apis'; | ||
|
||
const expanded = ( state, action ) => { | ||
if ( Array.isArray( action.clientIds ) ) { | ||
return { | ||
...state, | ||
...action.clientIds.reduce( | ||
( newState, id ) => ( { | ||
...newState, | ||
[ id ]: action.type === 'expand', | ||
} ), | ||
{} | ||
), | ||
}; | ||
} | ||
return state; | ||
}; | ||
export { BLOCK_LIST_ITEM_HEIGHT } from './private-list-view'; | ||
|
||
export const BLOCK_LIST_ITEM_HEIGHT = 36; | ||
|
||
/** @typedef {import('react').ComponentType} ComponentType */ | ||
/** @typedef {import('react').Ref<HTMLElement>} Ref */ | ||
|
||
/** | ||
* Show a hierarchical list of blocks. | ||
* | ||
* @param {Object} props Components props. | ||
* @param {string} props.id An HTML element id for the root element of ListView. | ||
* @param {Array} props.blocks _deprecated_ Custom subset of block client IDs to be used instead of the default hierarchy. | ||
* @param {?boolean} props.showBlockMovers Flag to enable block movers. Defaults to `false`. | ||
* @param {?boolean} props.isExpanded Flag to determine whether nested levels are expanded by default. Defaults to `false`. | ||
* @param {?boolean} props.showAppender Flag to show or hide the block appender. Defaults to `false`. | ||
* @param {?ComponentType} props.blockSettingsMenu Optional more menu substitution. Defaults to the standard `BlockSettingsDropdown` component. | ||
* @param {string} props.rootClientId The client id of the root block from which we determine the blocks to show in the list. | ||
* @param {string} props.description Optional accessible description for the tree grid component. | ||
* @param {?Function} props.onSelect Optional callback to be invoked when a block is selected. Receives the block object that was selected. | ||
* @param {Function} props.renderAdditionalBlockUI Function that renders additional block content UI. | ||
* @param {Ref} ref Forwarded ref | ||
*/ | ||
function ListViewComponent( | ||
{ | ||
id, | ||
blocks, | ||
showBlockMovers = false, | ||
isExpanded = false, | ||
showAppender = false, | ||
blockSettingsMenu: BlockSettingsMenu = BlockSettingsDropdown, | ||
rootClientId, | ||
description, | ||
onSelect, | ||
renderAdditionalBlockUI, | ||
}, | ||
ref | ||
) { | ||
// This can be removed once we no longer need to support the blocks prop. | ||
if ( blocks ) { | ||
deprecated( | ||
'`blocks` property in `wp.blockEditor.__experimentalListView`', | ||
{ | ||
since: '6.3', | ||
alternative: '`rootClientId` property', | ||
} | ||
); | ||
} | ||
|
||
const instanceId = useInstanceId( ListViewComponent ); | ||
const { clientIdsTree, draggedClientIds, selectedClientIds } = | ||
useListViewClientIds( { blocks, rootClientId } ); | ||
|
||
const { getBlock } = useSelect( blockEditorStore ); | ||
const { visibleBlockCount, shouldShowInnerBlocks } = useSelect( | ||
( select ) => { | ||
const { | ||
getGlobalBlockCount, | ||
getClientIdsOfDescendants, | ||
__unstableGetEditorMode, | ||
} = select( blockEditorStore ); | ||
const draggedBlockCount = | ||
draggedClientIds?.length > 0 | ||
? getClientIdsOfDescendants( draggedClientIds ).length + 1 | ||
: 0; | ||
return { | ||
visibleBlockCount: getGlobalBlockCount() - draggedBlockCount, | ||
shouldShowInnerBlocks: __unstableGetEditorMode() !== 'zoom-out', | ||
}; | ||
}, | ||
[ draggedClientIds ] | ||
); | ||
|
||
const { updateBlockSelection } = useBlockSelection(); | ||
|
||
const [ expandedState, setExpandedState ] = useReducer( expanded, {} ); | ||
|
||
const { ref: dropZoneRef, target: blockDropTarget } = useListViewDropZone(); | ||
const elementRef = useRef(); | ||
const treeGridRef = useMergeRefs( [ elementRef, dropZoneRef, ref ] ); | ||
|
||
const isMounted = useRef( false ); | ||
const { setSelectedTreeId } = useListViewExpandSelectedItem( { | ||
firstSelectedBlockClientId: selectedClientIds[ 0 ], | ||
setExpandedState, | ||
} ); | ||
const selectEditorBlock = useCallback( | ||
( event, blockClientId ) => { | ||
updateBlockSelection( event, blockClientId ); | ||
setSelectedTreeId( blockClientId ); | ||
if ( onSelect ) { | ||
onSelect( getBlock( blockClientId ) ); | ||
} | ||
}, | ||
[ setSelectedTreeId, updateBlockSelection, onSelect, getBlock ] | ||
); | ||
useEffect( () => { | ||
isMounted.current = true; | ||
}, [] ); | ||
|
||
// List View renders a fixed number of items and relies on each having a fixed item height of 36px. | ||
// If this value changes, we should also change the itemHeight value set in useFixedWindowList. | ||
// See: https://github.com/WordPress/gutenberg/pull/35230 for additional context. | ||
const [ fixedListWindow ] = useFixedWindowList( | ||
elementRef, | ||
BLOCK_LIST_ITEM_HEIGHT, | ||
visibleBlockCount, | ||
{ | ||
useWindowing: true, | ||
windowOverscan: 40, | ||
} | ||
); | ||
|
||
const expand = useCallback( | ||
( clientId ) => { | ||
if ( ! clientId ) { | ||
return; | ||
} | ||
setExpandedState( { type: 'expand', clientIds: [ clientId ] } ); | ||
}, | ||
[ setExpandedState ] | ||
); | ||
const collapse = useCallback( | ||
( clientId ) => { | ||
if ( ! clientId ) { | ||
return; | ||
} | ||
setExpandedState( { type: 'collapse', clientIds: [ clientId ] } ); | ||
}, | ||
[ setExpandedState ] | ||
); | ||
const expandRow = useCallback( | ||
( row ) => { | ||
expand( row?.dataset?.block ); | ||
}, | ||
[ expand ] | ||
); | ||
const collapseRow = useCallback( | ||
( row ) => { | ||
collapse( row?.dataset?.block ); | ||
}, | ||
[ collapse ] | ||
); | ||
const focusRow = useCallback( | ||
( event, startRow, endRow ) => { | ||
if ( event.shiftKey ) { | ||
updateBlockSelection( | ||
event, | ||
startRow?.dataset?.block, | ||
endRow?.dataset?.block | ||
); | ||
} | ||
}, | ||
[ updateBlockSelection ] | ||
); | ||
|
||
const contextValue = useMemo( | ||
() => ( { | ||
isTreeGridMounted: isMounted.current, | ||
draggedClientIds, | ||
expandedState, | ||
expand, | ||
collapse, | ||
BlockSettingsMenu, | ||
listViewInstanceId: instanceId, | ||
renderAdditionalBlockUI, | ||
} ), | ||
[ | ||
draggedClientIds, | ||
expandedState, | ||
expand, | ||
collapse, | ||
BlockSettingsMenu, | ||
instanceId, | ||
renderAdditionalBlockUI, | ||
] | ||
); | ||
|
||
// If there are no blocks to show, do not render the list view. | ||
if ( ! clientIdsTree.length ) { | ||
return null; | ||
} | ||
|
||
return ( | ||
<AsyncModeProvider value={ true }> | ||
<ListViewDropIndicator | ||
listViewRef={ elementRef } | ||
blockDropTarget={ blockDropTarget } | ||
/> | ||
<TreeGrid | ||
id={ id } | ||
className="block-editor-list-view-tree" | ||
aria-label={ __( 'Block navigation structure' ) } | ||
ref={ treeGridRef } | ||
onCollapseRow={ collapseRow } | ||
onExpandRow={ expandRow } | ||
onFocusRow={ focusRow } | ||
applicationAriaLabel={ __( 'Block navigation structure' ) } | ||
// eslint-disable-next-line jsx-a11y/aria-props | ||
aria-description={ description } | ||
> | ||
<ListViewContext.Provider value={ contextValue }> | ||
<ListViewBranch | ||
blocks={ clientIdsTree } | ||
parentId={ rootClientId } | ||
selectBlock={ selectEditorBlock } | ||
showBlockMovers={ showBlockMovers } | ||
fixedListWindow={ fixedListWindow } | ||
selectedClientIds={ selectedClientIds } | ||
isExpanded={ isExpanded } | ||
shouldShowInnerBlocks={ shouldShowInnerBlocks } | ||
showAppender={ showAppender } | ||
/> | ||
</ListViewContext.Provider> | ||
</TreeGrid> | ||
</AsyncModeProvider> | ||
); | ||
} | ||
export const PrivateListView = forwardRef( ListViewComponent ); | ||
const { PrivateListView } = unlock( blockEditorPrivateApis ); | ||
|
||
export default forwardRef( ( props, ref ) => { | ||
return ( | ||
<PrivateListView | ||
ref={ ref } | ||
{ ...props } | ||
showAppender={ false } | ||
blockSettingsMenu={ BlockSettingsDropdown } | ||
rootClientId={ null } | ||
onSelect={ null } | ||
renderAdditionalBlockUICallback={ null } | ||
renderAdditionalBlockUI={ null } | ||
/> | ||
); | ||
} ); |
Oops, something went wrong.