UNPKG

@gechiui/block-editor

Version:
179 lines (165 loc) 6.35 kB
import _extends from "@babel/runtime/helpers/esm/extends"; import { createElement } from "@gechiui/element"; /** * GeChiUI dependencies */ import { useMergeRefs, __experimentalUseFixedWindowList as useFixedWindowList } from '@gechiui/compose'; import { __experimentalTreeGrid as TreeGrid } from '@gechiui/components'; import { AsyncModeProvider, useDispatch, useSelect } from '@gechiui/data'; import { useCallback, useEffect, useMemo, useRef, useReducer, forwardRef } from '@gechiui/element'; import { __ } from '@gechiui/i18n'; /** * Internal dependencies */ import ListViewBranch from './branch'; import { ListViewContext } from './context'; import ListViewDropIndicator from './drop-indicator'; import useListViewClientIds from './use-list-view-client-ids'; import useListViewDropZone from './use-list-view-drop-zone'; import { store as blockEditorStore } from '../../store'; const noop = () => {}; const expanded = (state, action) => { switch (action.type) { case 'expand': return { ...state, ...{ [action.clientId]: true } }; case 'collapse': return { ...state, ...{ [action.clientId]: false } }; default: return state; } }; /** * Wrap `ListViewRows` with `TreeGrid`. ListViewRows 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 {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.showBlockMovers Flag to enable block movers * @param {boolean} props.__experimentalFeatures Flag to enable experimental features. * @param {boolean} props.__experimentalPersistentListViewFeatures Flag to enable features for the Persistent List View experiment. * @param {boolean} props.__experimentalHideContainerBlockActions Flag to hide actions of top level blocks (like core/widget-area) * @param {Object} ref Forwarded ref */ function ListView(_ref, ref) { let { blocks, onSelect = noop, __experimentalFeatures, __experimentalPersistentListViewFeatures, __experimentalHideContainerBlockActions, showNestedBlocks, showBlockMovers, ...props } = _ref; const { clientIdsTree, draggedClientIds, selectedClientIds } = useListViewClientIds(blocks); const { selectBlock } = useDispatch(blockEditorStore); const { visibleBlockCount } = useSelect(select => { const { getGlobalBlockCount, getClientIdsOfDescendants } = select(blockEditorStore); const draggedBlockCount = (draggedClientIds === null || draggedClientIds === void 0 ? void 0 : draggedClientIds.length) > 0 ? getClientIdsOfDescendants(draggedClientIds).length + 1 : 0; return { visibleBlockCount: getGlobalBlockCount() - draggedBlockCount }; }, [draggedClientIds]); const selectEditorBlock = useCallback(clientId => { selectBlock(clientId); onSelect(clientId); }, [selectBlock, onSelect]); const [expandedState, setExpandedState] = useReducer(expanded, {}); const { ref: dropZoneRef, target: blockDropTarget } = useListViewDropZone(); const elementRef = useRef(); const treeGridRef = useMergeRefs([elementRef, dropZoneRef, ref]); const isMounted = useRef(false); 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/GeChiUI/gutenberg/pull/35230 for additional context. const [fixedListWindow] = useFixedWindowList(elementRef, 36, visibleBlockCount, { useWindowing: __experimentalPersistentListViewFeatures, windowOverscan: 40 }); const expand = useCallback(clientId => { if (!clientId) { return; } setExpandedState({ type: 'expand', clientId }); }, [setExpandedState]); const collapse = useCallback(clientId => { if (!clientId) { return; } setExpandedState({ type: 'collapse', clientId }); }, [setExpandedState]); const expandRow = useCallback(row => { var _row$dataset; expand(row === null || row === void 0 ? void 0 : (_row$dataset = row.dataset) === null || _row$dataset === void 0 ? void 0 : _row$dataset.block); }, [expand]); const collapseRow = useCallback(row => { var _row$dataset2; collapse(row === null || row === void 0 ? void 0 : (_row$dataset2 = row.dataset) === null || _row$dataset2 === void 0 ? void 0 : _row$dataset2.block); }, [collapse]); const contextValue = useMemo(() => ({ __experimentalFeatures, __experimentalPersistentListViewFeatures, __experimentalHideContainerBlockActions, isTreeGridMounted: isMounted.current, draggedClientIds, expandedState, expand, collapse }), [__experimentalFeatures, __experimentalPersistentListViewFeatures, __experimentalHideContainerBlockActions, isMounted.current, draggedClientIds, expandedState, expand, collapse]); return createElement(AsyncModeProvider, { value: true }, createElement(ListViewDropIndicator, { listViewRef: elementRef, blockDropTarget: blockDropTarget }), createElement(TreeGrid, { className: "block-editor-list-view-tree", "aria-label": __('区块导航结构'), ref: treeGridRef, onCollapseRow: collapseRow, onExpandRow: expandRow }, createElement(ListViewContext.Provider, { value: contextValue }, createElement(ListViewBranch, _extends({ blocks: clientIdsTree, selectBlock: selectEditorBlock, showNestedBlocks: showNestedBlocks, showBlockMovers: showBlockMovers, fixedListWindow: fixedListWindow, selectedClientIds: selectedClientIds }, props))))); } export default forwardRef(ListView); //# sourceMappingURL=index.js.map