@react-querybuilder/dnd
Version:
Drag-and-drop-enabled version of react-querybuilder (DnD-library-agnostic)
282 lines (281 loc) • 10.2 kB
JavaScript
//#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