@mantine/core
Version:
React components library focused on usability, accessibility and developer experience
127 lines (126 loc) • 4.9 kB
JavaScript
"use client";
require("../../_virtual/_rolldown/runtime.cjs");
const require_get_children_nodes_values = require("./get-children-nodes-values/get-children-nodes-values.cjs");
let react = require("react");
//#region packages/@mantine/core/src/components/Tree/use-tree-node-drag-drop.ts
function isDescendantOf(data, ancestorValue, descendantValue) {
const ancestor = require_get_children_nodes_values.findTreeNode(ancestorValue, data);
if (!ancestor || !ancestor.children) return false;
function check(nodes) {
for (const node of nodes) {
if (node.value === descendantValue) return true;
if (node.children && check(node.children)) return true;
}
return false;
}
return check(ancestor.children);
}
function getDragDropPosition(event, element, hasChildren) {
const rect = element.getBoundingClientRect();
const y = event.clientY - rect.top;
const height = rect.height;
if (hasChildren) {
if (y < height * .25) return "before";
if (y > height * .75) return "after";
return "inside";
}
if (y < height * .5) return "before";
return "after";
}
const EMPTY_DRAG_PROPS = {
elementProps: {},
dragHandleProps: void 0
};
function useTreeNodeDragDrop({ nodeValue, hasChildren, data, onDragDrop, dragStateRef, allowDrop, withDragHandle }) {
const [isDragHandleActive, setIsDragHandleActive] = (0, react.useState)(false);
(0, react.useEffect)(() => {
if (!withDragHandle || !isDragHandleActive) return;
const handleWindowMouseUp = () => setIsDragHandleActive(false);
window.addEventListener("mouseup", handleWindowMouseUp);
return () => window.removeEventListener("mouseup", handleWindowMouseUp);
}, [withDragHandle, isDragHandleActive]);
if (!onDragDrop) return EMPTY_DRAG_PROPS;
const handleDragStart = (event) => {
if (withDragHandle && !isDragHandleActive) return;
event.stopPropagation();
event.dataTransfer.effectAllowed = "move";
event.dataTransfer.setData("text/plain", nodeValue);
dragStateRef.current.draggedValue = nodeValue;
const target = event.currentTarget;
requestAnimationFrame(() => {
target.setAttribute("data-dragging", "true");
});
};
const handleDragOver = (event) => {
const draggedValue = dragStateRef.current.draggedValue;
if (!draggedValue || draggedValue === nodeValue) return;
if (isDescendantOf(data, draggedValue, nodeValue)) return;
const target = event.currentTarget;
const position = getDragDropPosition(event, target, hasChildren);
if (allowDrop && !allowDrop({
draggedNode: draggedValue,
targetNode: nodeValue,
position
})) {
const prevTarget = dragStateRef.current.currentDropTarget;
if (prevTarget && prevTarget !== target) prevTarget.removeAttribute("data-drag-over");
target.removeAttribute("data-drag-over");
dragStateRef.current.currentDropTarget = null;
return;
}
event.preventDefault();
event.stopPropagation();
event.dataTransfer.dropEffect = "move";
const prevTarget = dragStateRef.current.currentDropTarget;
if (prevTarget && prevTarget !== target) prevTarget.removeAttribute("data-drag-over");
target.setAttribute("data-drag-over", position);
dragStateRef.current.currentDropTarget = target;
};
const handleDragLeave = (event) => {
const target = event.currentTarget;
const related = event.relatedTarget;
if (related && target.contains(related)) return;
target.removeAttribute("data-drag-over");
if (dragStateRef.current.currentDropTarget === target) dragStateRef.current.currentDropTarget = null;
};
const handleDrop = (event) => {
event.preventDefault();
event.stopPropagation();
const target = event.currentTarget;
const position = target.getAttribute("data-drag-over");
target.removeAttribute("data-drag-over");
const draggedValue = dragStateRef.current.draggedValue;
if (draggedValue && position && draggedValue !== nodeValue) {
const payload = {
draggedNode: draggedValue,
targetNode: nodeValue,
position
};
if (!allowDrop || allowDrop(payload)) onDragDrop(payload);
}
dragStateRef.current.draggedValue = null;
dragStateRef.current.currentDropTarget = null;
};
const handleDragEnd = (event) => {
event.currentTarget.removeAttribute("data-dragging");
const prevTarget = dragStateRef.current.currentDropTarget;
if (prevTarget) prevTarget.removeAttribute("data-drag-over");
dragStateRef.current.draggedValue = null;
dragStateRef.current.currentDropTarget = null;
if (withDragHandle) setIsDragHandleActive(false);
};
return {
elementProps: {
draggable: withDragHandle ? isDragHandleActive : true,
onDragStart: handleDragStart,
onDragOver: handleDragOver,
onDragLeave: handleDragLeave,
onDrop: handleDrop,
onDragEnd: handleDragEnd
},
dragHandleProps: withDragHandle ? { onMouseDown: () => setIsDragHandleActive(true) } : void 0
};
}
//#endregion
exports.useTreeNodeDragDrop = useTreeNodeDragDrop;
//# sourceMappingURL=use-tree-node-drag-drop.cjs.map