UNPKG

@react-querybuilder/dnd

Version:

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

282 lines (281 loc) 10.2 kB
//#region \0rolldown/runtime.js 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 __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) { key = keys[i]; if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: ((k) => from[k]).bind(null, key), enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod)); //#endregion let react_querybuilder = require("react-querybuilder"); //#region src/isHotkeyPressed.ts /** * Adapted from * https://github.com/JohannesKlauss/react-hotkeys-hook/blob/bc55a281f1d212d09de786aeb5cd236c58d9531d/src/isHotkeyPressed.ts * and * https://github.com/JohannesKlauss/react-hotkeys-hook/blob/bc55a281f1d212d09de786aeb5cd236c58d9531d/src/parseHotkey.ts */ const reservedModifierKeywords = new Set([ "shift", "alt", "meta", "mod", "ctrl" ]); const mappedKeys = { esc: "escape", return: "enter", ".": "period", ",": "comma", "-": "slash", " ": "space", "`": "backquote", "#": "backslash", "+": "bracketright", ShiftLeft: "shift", ShiftRight: "shift", AltLeft: "alt", AltRight: "alt", MetaLeft: "meta", MetaRight: "meta", OSLeft: "meta", OSRight: "meta", ControlLeft: "ctrl", ControlRight: "ctrl" }; const mapKey = (key) => (0, react_querybuilder.lc)((key && mappedKeys[key] || key || "").trim()).replace(/key|digit|numpad|arrow/, ""); const isHotkeyModifier = (key) => reservedModifierKeywords.has(key); const keyAliases = { "⌘": "meta", cmd: "meta", command: "meta", "⊞": "meta", win: "meta", windows: "meta", "⇧": "shift", "⌥": "alt", "⌃": "ctrl", control: "ctrl" }; (() => { if (typeof document !== "undefined") { document.addEventListener("keydown", (e) => { if (e.key === void 0) return; pushToCurrentlyPressedKeys([mapKey(e.key), mapKey(e.code)]); }); document.addEventListener("keyup", (e) => { if (e.key === void 0) return; removeFromCurrentlyPressedKeys([mapKey(e.key), mapKey(e.code)]); }); } if (typeof window !== "undefined") window.addEventListener("blur", () => { currentlyPressedKeys.clear(); }); })(); const currentlyPressedKeys = /* @__PURE__ */ new Set(); const isReadonlyArray = (value) => Array.isArray(value); const isHotkeyPressed = (key, splitKey = ",") => (isReadonlyArray(key) ? key : key.split(splitKey)).every((hotkey) => { const hk = (0, react_querybuilder.lc)(hotkey.trim()); return currentlyPressedKeys.has(keyAliases[hk] ?? hk); }); const pushToCurrentlyPressedKeys = (key) => { const hotkeyArray = Array.isArray(key) ? key : [key]; if (currentlyPressedKeys.has("meta")) { for (const k of currentlyPressedKeys) if (!isHotkeyModifier(k)) currentlyPressedKeys.delete((0, react_querybuilder.lc)(k)); } for (const hotkey of hotkeyArray) currentlyPressedKeys.add((0, react_querybuilder.lc)(hotkey)); }; const removeFromCurrentlyPressedKeys = (key) => { const hotkeyArray = Array.isArray(key) ? key : [key]; if (key === "meta") currentlyPressedKeys.clear(); else for (const hotkey of hotkeyArray) currentlyPressedKeys.delete((0, react_querybuilder.lc)(hotkey)); }; //#endregion //#region src/dndLogic.ts /** * Determines whether a drag item can be dropped on a rule target. */ const canDropOnRule = ({ dragging, path, schema, canDrop, groupModeModifierKey, disabled, rule }) => { if (isHotkeyPressed(groupModeModifierKey) && disabled || dragging && typeof canDrop === "function" && !canDrop({ dragging, hovering: { ...rule, path, qbId: schema.qbId } })) return false; if (schema.qbId !== dragging.qbId) return true; const parentHoverPath = (0, react_querybuilder.getParentPath)(path); const parentItemPath = (0, react_querybuilder.getParentPath)(dragging.path); const hoverIndex = path.at(-1); const itemIndex = dragging.path.at(-1); return !((0, react_querybuilder.isAncestor)(dragging.path, path) || (0, react_querybuilder.pathsAreEqual)(path, dragging.path) || !isHotkeyPressed(groupModeModifierKey) && (0, react_querybuilder.pathsAreEqual)(parentHoverPath, parentItemPath) && (hoverIndex === itemIndex - 1 || schema.independentCombinators && hoverIndex === itemIndex - 2)); }; /** * Determines whether a drag item can be dropped on a rule group target. */ const canDropOnRuleGroup = ({ dragging, path, schema, canDrop, disabled, ruleGroup }) => { if (disabled || dragging && typeof canDrop === "function" && !canDrop({ dragging, hovering: { ...ruleGroup, path, qbId: schema.qbId } })) return false; if (schema.qbId !== dragging.qbId) return true; const parentItemPath = (0, react_querybuilder.getParentPath)(dragging.path); const itemIndex = dragging.path.at(-1); return !((0, react_querybuilder.isAncestor)(dragging.path, path) || (0, react_querybuilder.pathsAreEqual)(path, parentItemPath) && itemIndex === 0 || (0, react_querybuilder.pathsAreEqual)(path, dragging.path)); }; /** * Determines whether a drag item can be dropped on an inline combinator target. */ const canDropOnInlineCombinator = ({ dragging, path, schema, canDrop, groupModeModifierKey, hoveringItem }) => { const { path: itemPath } = dragging; if (isHotkeyPressed(groupModeModifierKey) || dragging && typeof canDrop === "function" && !canDrop({ dragging, hovering: { ...hoveringItem, path, qbId: schema.qbId } })) return false; const parentHoverPath = (0, react_querybuilder.getParentPath)(path); const parentItemPath = (0, react_querybuilder.getParentPath)(itemPath); const hoverIndex = path.at(-1); const itemIndex = itemPath.at(-1); return !((0, react_querybuilder.isAncestor)(itemPath, path) || (0, react_querybuilder.pathsAreEqual)(itemPath, path) || (0, react_querybuilder.pathsAreEqual)(parentHoverPath, parentItemPath) && hoverIndex - 1 === itemIndex || schema.independentCombinators && (0, react_querybuilder.pathsAreEqual)(parentHoverPath, parentItemPath) && hoverIndex === itemIndex - 1); }; /** * Builds a {@link DropResult} for a given target. */ const buildDropResult = ({ type, path, schema, copyModeModifierKey, groupModeModifierKey, copyModeOverride, groupModeOverride }) => { const { qbId, getQuery, dispatchQuery } = schema; return { type, path, qbId, getQuery, dispatchQuery, groupItems: groupModeOverride || isHotkeyPressed(groupModeModifierKey), dropEffect: copyModeOverride || isHotkeyPressed(copyModeModifierKey) ? "copy" : "move" }; }; /** * Computes the destination path for a drop operation based on the drop target * type and whether grouping mode is active. */ const getDestinationPath = (dropResult, groupItems) => { const parentHoverPath = (0, react_querybuilder.getParentPath)(dropResult.path); const hoverIndex = dropResult.path.at(-1); if (groupItems) return dropResult.path; if (dropResult.type === "ruleGroup") return [...dropResult.path, 0]; if (dropResult.type === "inlineCombinator") return [...parentHoverPath, hoverIndex]; return [...parentHoverPath, hoverIndex + 1]; }; /** * Handles the actual query mutation when a drop completes. * Supports move, copy, group, and cross-query-builder operations. */ const handleDrop = ({ item, dropResult, schema, actions, copyModeModifierKey, groupModeModifierKey, copyModeOverride, groupModeOverride, onRuleDrop }) => { if (!dropResult) return; const dropEffect = copyModeOverride || isHotkeyPressed(copyModeModifierKey) ? "copy" : "move"; const groupItems = groupModeOverride || isHotkeyPressed(groupModeModifierKey); const destinationPath = getDestinationPath(dropResult, groupItems); const isCrossBuilder = schema.qbId !== dropResult.qbId; if (!isCrossBuilder) if (groupItems) actions.groupRule(item.path, destinationPath, dropEffect === "copy"); else actions.moveRule(item.path, destinationPath, dropEffect === "copy"); else { const otherBuilderQuery = dropResult.getQuery(); // v8 ignore else if (otherBuilderQuery) { if (groupItems) dropResult.dispatchQuery((0, react_querybuilder.group)((0, react_querybuilder.add)(otherBuilderQuery, item, []), [otherBuilderQuery.rules.length], destinationPath, { clone: false })); else dropResult.dispatchQuery((0, react_querybuilder.insert)(otherBuilderQuery, item, destinationPath)); // v8 ignore else if (dropEffect !== "copy") actions.onRuleRemove(item.path); } } onRuleDrop?.({ draggedItem: item, sourceQbId: schema.qbId, targetQbId: dropResult.qbId, sourcePath: item.path, targetPath: destinationPath, dropEffect, groupItems, isCrossBuilder }); }; /** * Creates the drag item from the current path and schema, used by * drag-start callbacks. */ const getDragItem = (path, schema) => ({ ...(0, react_querybuilder.findPath)(path, schema.getQuery()), path, qbId: schema.qbId }); //#endregion Object.defineProperty(exports, "__toESM", { enumerable: true, get: function() { return __toESM; } }); Object.defineProperty(exports, "buildDropResult", { enumerable: true, get: function() { return buildDropResult; } }); Object.defineProperty(exports, "canDropOnInlineCombinator", { enumerable: true, get: function() { return canDropOnInlineCombinator; } }); Object.defineProperty(exports, "canDropOnRule", { enumerable: true, get: function() { return canDropOnRule; } }); Object.defineProperty(exports, "canDropOnRuleGroup", { enumerable: true, get: function() { return canDropOnRuleGroup; } }); Object.defineProperty(exports, "getDragItem", { enumerable: true, get: function() { return getDragItem; } }); Object.defineProperty(exports, "handleDrop", { enumerable: true, get: function() { return handleDrop; } }); Object.defineProperty(exports, "isHotkeyPressed", { enumerable: true, get: function() { return isHotkeyPressed; } }); //# sourceMappingURL=dndLogic-DRubwv4d.js.map