@gechiui/block-editor
Version:
155 lines (134 loc) • 5.15 kB
JavaScript
import { createElement, Fragment } from "@gechiui/element";
/**
* External dependencies
*/
import { compact } from 'lodash';
/**
* GeChiUI dependencies
*/
import { memo } from '@gechiui/element';
import { AsyncModeProvider } from '@gechiui/data';
/**
* Internal dependencies
*/
import ListViewBlock from './block';
import { useListViewContext } from './context';
import { isClientIdSelected } from './utils';
/**
* Given a block, returns the total number of blocks in that subtree. This is used to help determine
* the list position of a block.
*
* When a block is collapsed, we do not count their children as part of that total. In the current drag
* implementation dragged blocks and their children are not counted.
*
* @param {Object} block block tree
* @param {Object} expandedState state that notes which branches are collapsed
* @param {Array} draggedClientIds a list of dragged client ids
* @return {number} block count
*/
function countBlocks(block, expandedState, draggedClientIds) {
var _expandedState$block$;
const isDragged = draggedClientIds === null || draggedClientIds === void 0 ? void 0 : draggedClientIds.includes(block.clientId);
if (isDragged) {
return 0;
}
const isExpanded = (_expandedState$block$ = expandedState[block.clientId]) !== null && _expandedState$block$ !== void 0 ? _expandedState$block$ : true;
if (isExpanded) {
return 1 + block.innerBlocks.reduce(countReducer(expandedState, draggedClientIds), 0);
}
return 1;
}
const countReducer = (expandedState, draggedClientIds) => (count, block) => {
var _expandedState$block$2;
const isDragged = draggedClientIds === null || draggedClientIds === void 0 ? void 0 : draggedClientIds.includes(block.clientId);
if (isDragged) {
return count;
}
const isExpanded = (_expandedState$block$2 = expandedState[block.clientId]) !== null && _expandedState$block$2 !== void 0 ? _expandedState$block$2 : true;
if (isExpanded && block.innerBlocks.length > 0) {
return count + countBlocks(block, expandedState, draggedClientIds);
}
return count + 1;
};
function ListViewBranch(props) {
const {
blocks,
selectBlock,
showBlockMovers,
showNestedBlocks,
selectedClientIds,
level = 1,
path = '',
isBranchSelected = false,
listPosition = 0,
fixedListWindow
} = props;
const {
expandedState,
draggedClientIds,
__experimentalPersistentListViewFeatures
} = useListViewContext();
const filteredBlocks = compact(blocks);
const blockCount = filteredBlocks.length;
let nextPosition = listPosition;
return createElement(Fragment, null, filteredBlocks.map((block, index) => {
var _expandedState$client;
const {
clientId,
innerBlocks
} = block;
if (index > 0) {
nextPosition += countBlocks(filteredBlocks[index - 1], expandedState, draggedClientIds);
}
const usesWindowing = __experimentalPersistentListViewFeatures;
const {
itemInView
} = fixedListWindow;
const blockInView = !usesWindowing || itemInView(nextPosition);
const position = index + 1;
const updatedPath = path.length > 0 ? `${path}_${position}` : `${position}`;
const hasNestedBlocks = showNestedBlocks && !!innerBlocks && !!innerBlocks.length;
const isExpanded = hasNestedBlocks ? (_expandedState$client = expandedState[clientId]) !== null && _expandedState$client !== void 0 ? _expandedState$client : true : undefined;
const isDragged = !!(draggedClientIds !== null && draggedClientIds !== void 0 && draggedClientIds.includes(clientId));
const showBlock = isDragged || blockInView; // Make updates to the selected or dragged blocks synchronous,
// but asynchronous for any other block.
const isSelected = isClientIdSelected(clientId, selectedClientIds);
const isSelectedBranch = isBranchSelected || isSelected && hasNestedBlocks;
return createElement(AsyncModeProvider, {
key: clientId,
value: !isSelected
}, showBlock && createElement(ListViewBlock, {
block: block,
selectBlock: selectBlock,
isSelected: isSelected,
isBranchSelected: isSelectedBranch,
isDragged: isDragged,
level: level,
position: position,
rowCount: blockCount,
siblingBlockCount: blockCount,
showBlockMovers: showBlockMovers,
path: updatedPath,
isExpanded: isExpanded,
listPosition: nextPosition
}), !showBlock && createElement("tr", null, createElement("td", {
className: "block-editor-list-view-placeholder"
})), hasNestedBlocks && isExpanded && !isDragged && createElement(ListViewBranch, {
blocks: innerBlocks,
selectBlock: selectBlock,
showBlockMovers: showBlockMovers,
showNestedBlocks: showNestedBlocks,
level: level + 1,
path: updatedPath,
listPosition: nextPosition + 1,
fixedListWindow: fixedListWindow,
isBranchSelected: isSelectedBranch,
selectedClientIds: selectedClientIds
}));
}));
}
ListViewBranch.defaultProps = {
selectBlock: () => {}
};
export default memo(ListViewBranch);
//# sourceMappingURL=branch.js.map