Skip to content

Commit

Permalink
Navigtion: Use the ListView in the Navigation block inspector controls
Browse files Browse the repository at this point in the history
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
scruffian committed May 11, 2023
1 parent d24ac78 commit 7555b87
Show file tree
Hide file tree
Showing 10 changed files with 424 additions and 284 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { forwardRef } from '@wordpress/element';
/**
* Internal dependencies
*/
import { unlock } from '../../lock-unlock';
import ListViewBlockSelectButton from './block-select-button';
import BlockDraggable from '../block-draggable';
import { store as blockEditorStore } from '../../store';
Expand All @@ -38,7 +39,7 @@ const ListViewBlockContents = forwardRef(
const { blockMovingClientId, selectedBlockInBlockEditor } = useSelect(
( select ) => {
const { hasBlockMovingClientId, getSelectedBlockClientId } =
select( blockEditorStore );
unlock( select( blockEditorStore ) );
return {
blockMovingClientId: hasBlockMovingClientId(),
selectedBlockInBlockEditor: getSelectedBlockClientId(),
Expand Down
266 changes: 6 additions & 260 deletions packages/block-editor/src/components/list-view/index.js
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 }
/>
);
} );
Loading

0 comments on commit 7555b87

Please sign in to comment.