UNPKG

@react-querybuilder/dnd

Version:

Drag-and-drop-enabled version of react-querybuilder (DnD-library-agnostic)

91 lines (90 loc) 3.46 kB
import { createContext } from "react"; import { getParentPath, group, move } from "react-querybuilder"; //#region src/DragPreviewContext.ts // v8 ignore next const noop = () => {}; /** @group Components */ const DragPreviewContext = createContext({ dragPreviewState: null, updatePreviewPosition: noop, commitDrag: noop, cancelDrag: noop }); //#endregion //#region src/shadowQuery.ts /** * Computes the destination path for a quadrant-based drag target. * * - **Rule, upper quadrant**: Insert before the target rule. * - **Rule, lower quadrant**: Insert after the target rule. * - **RuleGroup header**: Insert as first child of the group (position 0). */ const computeDestinationFromQuadrant = (targetPath, targetType, quadrant) => { if (targetType === "ruleGroup") return [...targetPath, 0]; const parentPath = getParentPath(targetPath); const targetIndex = targetPath.at(-1); if (quadrant === "upper") return [...parentPath, targetIndex]; return [...parentPath, targetIndex + 1]; }; /** * Checks whether the dragged item is already at the computed destination, * meaning no visual change would occur. */ const isNoOp = (draggedPath, destinationPath) => { if (draggedPath.length !== destinationPath.length) return false; const parentDragged = getParentPath(draggedPath); const parentDest = getParentPath(destinationPath); // v8 ignore next -- unreachable: paths of equal length always have equal-length parents if (parentDragged.length !== parentDest.length) return false; for (let i = 0; i < parentDragged.length; i++) if (parentDragged[i] !== parentDest[i]) return false; const dragIdx = draggedPath.at(-1); const destIdx = destinationPath.at(-1); return destIdx === dragIdx || destIdx === dragIdx + 1; }; /** * Computes a shadow query given the current drag state and target position. * * Uses the existing `move()` and `group()` utilities from `@react-querybuilder/core` * to produce an immutable preview of the query with the dragged item at its * prospective position. * * @returns The shadow query and the path where the dragged item now lives, * or `null` if the move would be a no-op. */ const computeShadowQuery = ({ originalQuery, draggedPath, targetPath, targetType, quadrant, dropEffect, groupItems }) => { const destinationPath = computeDestinationFromQuadrant(targetPath, targetType, quadrant); const isClone = dropEffect === "copy"; if (groupItems) try { return { shadowQuery: group(originalQuery, draggedPath, targetPath, { clone: isClone }), previewPath: targetPath }; } catch (_unused) { // v8 ignore next return null; } if (!isClone && isNoOp(draggedPath, destinationPath)) return null; try { const shadowQuery = move(originalQuery, draggedPath, destinationPath, { clone: isClone }); let previewPath = destinationPath; if (!isClone) { const parentDragged = getParentPath(draggedPath); const parentDest = getParentPath(destinationPath); if (parentDragged.length === parentDest.length && parentDragged.every((v, i) => v === parentDest[i])) { const dragIdx = draggedPath.at(-1); const destIdx = destinationPath.at(-1); if (dragIdx < destIdx) previewPath = [...parentDest, destIdx - 1]; } } return { shadowQuery, previewPath }; } catch (_unused2) { // v8 ignore next return null; } }; //#endregion export { computeShadowQuery as n, DragPreviewContext as r, computeDestinationFromQuadrant as t }; //# sourceMappingURL=shadowQuery-B6n89EFI.js.map