UNPKG

@wordpress/block-editor

Version:
336 lines (334 loc) 12.4 kB
"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // packages/block-editor/src/components/list-view/use-list-view-drop-zone.js var use_list_view_drop_zone_exports = {}; __export(use_list_view_drop_zone_exports, { NESTING_LEVEL_INDENTATION: () => NESTING_LEVEL_INDENTATION, default: () => useListViewDropZone, getListViewDropTarget: () => getListViewDropTarget }); module.exports = __toCommonJS(use_list_view_drop_zone_exports); var import_data = require("@wordpress/data"); var import_element = require("@wordpress/element"); var import_compose = require("@wordpress/compose"); var import_i18n = require("@wordpress/i18n"); var import_math = require("../../utils/math.cjs"); var import_use_on_block_drop = __toESM(require("../use-on-block-drop/index.cjs")); var import_store = require("../../store/index.cjs"); var NESTING_LEVEL_INDENTATION = 24; function isUpGesture(point, rect, nestingLevel = 1, rtl = false) { const blockIndentPosition = rtl ? rect.right - nestingLevel * NESTING_LEVEL_INDENTATION : rect.left + nestingLevel * NESTING_LEVEL_INDENTATION; return rtl ? point.x > blockIndentPosition : point.x < blockIndentPosition; } function getDesiredRelativeParentLevel(point, rect, nestingLevel = 1, rtl = false) { const blockIndentPosition = rtl ? rect.right - nestingLevel * NESTING_LEVEL_INDENTATION : rect.left + nestingLevel * NESTING_LEVEL_INDENTATION; const distanceBetweenPointAndBlockIndentPosition = rtl ? blockIndentPosition - point.x : point.x - blockIndentPosition; const desiredParentLevel = Math.round( distanceBetweenPointAndBlockIndentPosition / NESTING_LEVEL_INDENTATION ); return Math.abs(desiredParentLevel); } function getCandidateBlockParents(candidateBlockData, blocksData) { const candidateBlockParents = []; let currentBlockData = candidateBlockData; while (currentBlockData) { candidateBlockParents.push({ ...currentBlockData }); currentBlockData = blocksData.find( (blockData) => blockData.clientId === currentBlockData.rootClientId ); } return candidateBlockParents; } function getNextNonDraggedBlock(blocksData, index) { const nextBlockData = blocksData[index + 1]; if (nextBlockData && nextBlockData.isDraggedBlock) { return getNextNonDraggedBlock(blocksData, index + 1); } return nextBlockData; } function isNestingGesture(point, rect, nestingLevel = 1, rtl = false) { const blockIndentPosition = rtl ? rect.right - nestingLevel * NESTING_LEVEL_INDENTATION : rect.left + nestingLevel * NESTING_LEVEL_INDENTATION; const isNestingHorizontalGesture = rtl ? point.x < blockIndentPosition - NESTING_LEVEL_INDENTATION : point.x > blockIndentPosition + NESTING_LEVEL_INDENTATION; return isNestingHorizontalGesture && point.y < rect.bottom; } var ALLOWED_DROP_EDGES = ["top", "bottom"]; function getListViewDropTarget(blocksData, position, rtl = false) { let candidateEdge; let candidateBlockData; let candidateDistance; let candidateRect; let candidateBlockIndex; for (let i = 0; i < blocksData.length; i++) { const blockData = blocksData[i]; if (blockData.isDraggedBlock) { continue; } const rect = blockData.element.getBoundingClientRect(); const [distance, edge] = (0, import_math.getDistanceToNearestEdge)( position, rect, ALLOWED_DROP_EDGES ); const isCursorWithinBlock = (0, import_math.isPointContainedByRect)(position, rect); if (candidateDistance === void 0 || distance < candidateDistance || isCursorWithinBlock) { candidateDistance = distance; const index = blocksData.indexOf(blockData); const previousBlockData = blocksData[index - 1]; if (edge === "top" && previousBlockData && previousBlockData.rootClientId === blockData.rootClientId && !previousBlockData.isDraggedBlock) { candidateBlockData = previousBlockData; candidateEdge = "bottom"; candidateRect = previousBlockData.element.getBoundingClientRect(); candidateBlockIndex = index - 1; } else { candidateBlockData = blockData; candidateEdge = edge; candidateRect = rect; candidateBlockIndex = index; } if (isCursorWithinBlock) { break; } } } if (!candidateBlockData) { return; } const candidateBlockParents = getCandidateBlockParents( candidateBlockData, blocksData ); const isDraggingBelow = candidateEdge === "bottom"; if (isDraggingBelow && candidateBlockData.canInsertDraggedBlocksAsChild && (candidateBlockData.innerBlockCount > 0 && candidateBlockData.isExpanded || isNestingGesture( position, candidateRect, candidateBlockParents.length, rtl ))) { const newBlockIndex = candidateBlockData.isExpanded ? 0 : candidateBlockData.innerBlockCount || 0; return { rootClientId: candidateBlockData.clientId, clientId: candidateBlockData.clientId, blockIndex: newBlockIndex, dropPosition: "inside" }; } if (isDraggingBelow && candidateBlockData.rootClientId && isUpGesture( position, candidateRect, candidateBlockParents.length, rtl )) { const nextBlock = getNextNonDraggedBlock( blocksData, candidateBlockIndex ); const currentLevel = candidateBlockData.nestingLevel; const nextLevel = nextBlock ? nextBlock.nestingLevel : 1; if (currentLevel && nextLevel) { const desiredRelativeLevel = getDesiredRelativeParentLevel( position, candidateRect, candidateBlockParents.length, rtl ); const targetParentIndex = Math.max( Math.min(desiredRelativeLevel, currentLevel - nextLevel), 0 ); if (candidateBlockParents[targetParentIndex]) { let newBlockIndex = candidateBlockData.blockIndex; if (candidateBlockParents[targetParentIndex].nestingLevel === nextBlock?.nestingLevel) { newBlockIndex = nextBlock?.blockIndex; } else { for (let i = candidateBlockIndex; i >= 0; i--) { const blockData = blocksData[i]; if (blockData.rootClientId === candidateBlockParents[targetParentIndex].rootClientId) { newBlockIndex = blockData.blockIndex + 1; break; } } } return { rootClientId: candidateBlockParents[targetParentIndex].rootClientId, clientId: candidateBlockData.clientId, blockIndex: newBlockIndex, dropPosition: candidateEdge }; } } } if (!candidateBlockData.canInsertDraggedBlocksAsSibling) { return; } const offset = isDraggingBelow ? 1 : 0; return { rootClientId: candidateBlockData.rootClientId, clientId: candidateBlockData.clientId, blockIndex: candidateBlockData.blockIndex + offset, dropPosition: candidateEdge }; } var EXPAND_THROTTLE_OPTIONS = { leading: false, // Don't call the function immediately on the first call. trailing: true // Do call the function on the last call. }; function useListViewDropZone({ dropZoneElement, expandedState, setExpandedState }) { const { getBlockRootClientId, getBlockIndex, getBlockCount, getDraggedBlockClientIds, canInsertBlocks } = (0, import_data.useSelect)(import_store.store); const [target, setTarget] = (0, import_element.useState)(); const { rootClientId: targetRootClientId, blockIndex: targetBlockIndex } = target || {}; const onBlockDrop = (0, import_use_on_block_drop.default)(targetRootClientId, targetBlockIndex); const rtl = (0, import_i18n.isRTL)(); const previousRootClientId = (0, import_compose.usePrevious)(targetRootClientId); const maybeExpandBlock = (0, import_element.useCallback)( (_expandedState, _target) => { const { rootClientId } = _target || {}; if (!rootClientId) { return; } if (_target?.dropPosition === "inside" && !_expandedState[rootClientId]) { setExpandedState({ type: "expand", clientIds: [rootClientId] }); } }, [setExpandedState] ); const throttledMaybeExpandBlock = (0, import_compose.useThrottle)( maybeExpandBlock, 500, EXPAND_THROTTLE_OPTIONS ); (0, import_element.useEffect)(() => { if (target?.dropPosition !== "inside" || previousRootClientId !== target?.rootClientId) { throttledMaybeExpandBlock.cancel(); return; } throttledMaybeExpandBlock(expandedState, target); }, [ expandedState, previousRootClientId, target, throttledMaybeExpandBlock ]); const draggedBlockClientIds = getDraggedBlockClientIds(); const throttled = (0, import_compose.useThrottle)( (0, import_element.useCallback)( (event, currentTarget) => { const position = { x: event.clientX, y: event.clientY }; const isBlockDrag = !!draggedBlockClientIds?.length; const blockElements = Array.from( currentTarget.querySelectorAll("[data-block]") ); const blocksData = blockElements.map((blockElement) => { const clientId = blockElement.dataset.block; const isExpanded = blockElement.dataset.expanded === "true"; const isDraggedBlock = blockElement.classList.contains("is-dragging"); const nestingLevel = parseInt( blockElement.getAttribute("aria-level"), 10 ); const rootClientId = getBlockRootClientId(clientId); return { clientId, isExpanded, rootClientId, blockIndex: getBlockIndex(clientId), element: blockElement, nestingLevel: nestingLevel || void 0, isDraggedBlock: isBlockDrag ? isDraggedBlock : false, innerBlockCount: getBlockCount(clientId), canInsertDraggedBlocksAsSibling: isBlockDrag ? canInsertBlocks( draggedBlockClientIds, rootClientId ) : true, canInsertDraggedBlocksAsChild: isBlockDrag ? canInsertBlocks(draggedBlockClientIds, clientId) : true }; }); const newTarget = getListViewDropTarget( blocksData, position, rtl ); if (newTarget) { setTarget(newTarget); } }, [ canInsertBlocks, draggedBlockClientIds, getBlockCount, getBlockIndex, getBlockRootClientId, rtl ] ), 50 ); const ref = (0, import_compose.__experimentalUseDropZone)({ dropZoneElement, onDrop(event) { throttled.cancel(); if (target) { onBlockDrop(event); } setTarget(void 0); }, onDragLeave() { throttled.cancel(); setTarget(null); }, onDragOver(event) { throttled(event, event.currentTarget); }, onDragEnd() { throttled.cancel(); setTarget(void 0); } }); return { ref, target }; } // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { NESTING_LEVEL_INDENTATION, getListViewDropTarget }); //# sourceMappingURL=use-list-view-drop-zone.cjs.map