UNPKG

@react-querybuilder/dnd

Version:

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

271 lines (270 loc) 10.3 kB
import { add, findPath, getParentPath, group, insert, isAncestor, lc, pathsAreEqual } from "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) => 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) => { var _keyAliases$hk; const hk = lc(hotkey.trim()); return currentlyPressedKeys.has((_keyAliases$hk = keyAliases[hk]) !== null && _keyAliases$hk !== void 0 ? _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(lc(k)); } for (const hotkey of hotkeyArray) currentlyPressedKeys.add(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(lc(hotkey)); }; //#endregion //#region \0@oxc-project+runtime@0.134.0/helpers/esm/typeof.js function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o) { return typeof o; } : function(o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } //#endregion //#region \0@oxc-project+runtime@0.134.0/helpers/esm/toPrimitive.js function toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } //#endregion //#region \0@oxc-project+runtime@0.134.0/helpers/esm/toPropertyKey.js function toPropertyKey(t) { var i = toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } //#endregion //#region \0@oxc-project+runtime@0.134.0/helpers/esm/defineProperty.js function _defineProperty(e, r, t) { return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } //#endregion //#region \0@oxc-project+runtime@0.134.0/helpers/esm/objectSpread2.js function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function(r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread2(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function(r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function(r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } //#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: _objectSpread2(_objectSpread2({}, rule), {}, { path, qbId: schema.qbId }) })) return false; if (schema.qbId !== dragging.qbId) return true; const parentHoverPath = getParentPath(path); const parentItemPath = getParentPath(dragging.path); const hoverIndex = path.at(-1); const itemIndex = dragging.path.at(-1); return !(isAncestor(dragging.path, path) || pathsAreEqual(path, dragging.path) || !isHotkeyPressed(groupModeModifierKey) && 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: _objectSpread2(_objectSpread2({}, ruleGroup), {}, { path, qbId: schema.qbId }) })) return false; if (schema.qbId !== dragging.qbId) return true; const parentItemPath = getParentPath(dragging.path); const itemIndex = dragging.path.at(-1); return !(isAncestor(dragging.path, path) || pathsAreEqual(path, parentItemPath) && itemIndex === 0 || 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: _objectSpread2(_objectSpread2({}, hoveringItem), {}, { path, qbId: schema.qbId }) })) return false; const parentHoverPath = getParentPath(path); const parentItemPath = getParentPath(itemPath); const hoverIndex = path.at(-1); const itemIndex = itemPath.at(-1); return !(isAncestor(itemPath, path) || pathsAreEqual(itemPath, path) || pathsAreEqual(parentHoverPath, parentItemPath) && hoverIndex - 1 === itemIndex || schema.independentCombinators && 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 = 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(group(add(otherBuilderQuery, item, []), [otherBuilderQuery.rules.length], destinationPath, { clone: false })); else dropResult.dispatchQuery(insert(otherBuilderQuery, item, destinationPath)); // v8 ignore else if (dropEffect !== "copy") actions.onRuleRemove(item.path); } } onRuleDrop === null || onRuleDrop === void 0 || 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) => _objectSpread2(_objectSpread2({}, findPath(path, schema.getQuery())), {}, { path, qbId: schema.qbId }); //#endregion export { getDragItem as a, isHotkeyPressed as c, canDropOnRuleGroup as i, canDropOnInlineCombinator as n, handleDrop as o, canDropOnRule as r, _objectSpread2 as s, buildDropResult as t }; //# sourceMappingURL=dndLogic-CX9kFh1l.js.map