@mantine/core
Version:
React components library focused on usability, accessibility and developer experience
170 lines (169 loc) • 6.64 kB
JavaScript
"use client";
require("../../../_virtual/_rolldown/runtime.cjs");
const require_move_pill = require("./move-pill.cjs");
let react = require("react");
//#region packages/@mantine/core/src/components/Combobox/use-pills-reorder/use-pills-reorder.ts
const findSearchInput = (container) => {
const lastChild = container.lastElementChild;
if (!lastChild) return null;
if (lastChild instanceof HTMLInputElement) return lastChild;
return lastChild.querySelector("input");
};
const valuesMatch = (a, b) => {
if (a === b) return true;
if (a.length !== b.length) return false;
for (let i = 0; i < a.length; i += 1) if (a[i] !== b[i]) return false;
return true;
};
function usePillsReorder({ value, onChange, enabled }) {
const dragStateRef = (0, react.useRef)({
draggedIndex: null,
currentDropTarget: null
});
const pendingFocusRef = (0, react.useRef)(null);
const containerRef = (0, react.useRef)(null);
const valueRef = (0, react.useRef)(value);
valueRef.current = value;
(0, react.useEffect)(() => {
const pending = pendingFocusRef.current;
if (!pending) return;
pendingFocusRef.current = null;
if (!valuesMatch(valueRef.current, pending.expectedValue)) return;
pending.container?.querySelector(`[data-mantine-pill-index="${pending.index}"]`)?.focus();
});
const setContainer = (0, react.useCallback)((node) => {
containerRef.current = node;
}, []);
const getListProps = () => {
if (!enabled) return {};
return { ref: setContainer };
};
const handleInputKeyDown = (event) => {
if (!enabled || event.key !== "ArrowLeft") return;
const input = event.currentTarget;
if (!(input.value.length === 0 || input.selectionStart === 0 && input.selectionEnd === 0)) return;
const container = containerRef.current;
if (!container) return;
const pills = container.querySelectorAll("[data-mantine-pill-index]");
if (pills.length === 0) return;
event.preventDefault();
pills[pills.length - 1].focus();
};
const getPillProps = (index) => {
if (!enabled) return;
return {
draggable: true,
tabIndex: -1,
"data-mantine-pill-index": index,
"aria-keyshortcuts": "Alt+ArrowLeft Alt+ArrowRight",
onMouseDown: (event) => {
if (event.button === 0) event.stopPropagation();
},
onDragStart: (event) => {
event.stopPropagation();
event.dataTransfer.effectAllowed = "move";
event.dataTransfer.setData("text/plain", String(index));
dragStateRef.current.draggedIndex = index;
const target = event.currentTarget;
const rect = target.getBoundingClientRect();
const ghost = target.cloneNode(true);
ghost.removeAttribute("data-dragging");
ghost.removeAttribute("data-drag-over");
ghost.style.position = "fixed";
ghost.style.top = "-9999px";
ghost.style.left = "-9999px";
ghost.style.width = `${rect.width}px`;
ghost.style.height = `${rect.height}px`;
ghost.style.pointerEvents = "none";
document.body.appendChild(ghost);
event.dataTransfer.setDragImage(ghost, event.clientX - rect.left, event.clientY - rect.top);
setTimeout(() => ghost.parentNode?.removeChild(ghost), 0);
requestAnimationFrame(() => {
target.setAttribute("data-dragging", "true");
});
},
onDragOver: (event) => {
const { draggedIndex } = dragStateRef.current;
if (draggedIndex === null || draggedIndex === index) return;
const target = event.currentTarget;
const rect = target.getBoundingClientRect();
const x = event.clientX - rect.left;
const position = (getComputedStyle(target).direction === "rtl" ? x > rect.width / 2 : x < rect.width / 2) ? "before" : "after";
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;
},
onDragLeave: (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;
},
onDrop: (event) => {
event.preventDefault();
event.stopPropagation();
const target = event.currentTarget;
const position = target.getAttribute("data-drag-over");
target.removeAttribute("data-drag-over");
const { draggedIndex } = dragStateRef.current;
if (draggedIndex !== null && position && draggedIndex !== index) {
const nextValue = require_move_pill.movePill(valueRef.current, draggedIndex, index, position);
if (nextValue !== valueRef.current) onChange(nextValue);
}
dragStateRef.current.draggedIndex = null;
dragStateRef.current.currentDropTarget = null;
},
onDragEnd: (event) => {
event.currentTarget.removeAttribute("data-dragging");
const prevTarget = dragStateRef.current.currentDropTarget;
if (prevTarget) prevTarget.removeAttribute("data-drag-over");
dragStateRef.current.draggedIndex = null;
dragStateRef.current.currentDropTarget = null;
},
onKeyDown: (event) => {
if (event.key !== "ArrowLeft" && event.key !== "ArrowRight") return;
const target = event.currentTarget;
const movingForward = getComputedStyle(target).direction === "rtl" ? event.key === "ArrowLeft" : event.key === "ArrowRight";
const targetIndex = movingForward ? index + 1 : index - 1;
if (event.altKey) {
if (targetIndex < 0 || targetIndex >= valueRef.current.length) return;
event.preventDefault();
event.stopPropagation();
const position = movingForward ? "after" : "before";
const nextValue = require_move_pill.movePill(valueRef.current, index, targetIndex, position);
if (nextValue === valueRef.current) return;
pendingFocusRef.current = {
container: target.parentElement,
index: targetIndex,
expectedValue: nextValue
};
onChange(nextValue);
return;
}
if (targetIndex < 0) return;
const container = target.parentElement;
if (!container) return;
event.preventDefault();
event.stopPropagation();
if (targetIndex >= valueRef.current.length) {
findSearchInput(container)?.focus();
return;
}
container.querySelector(`[data-mantine-pill-index="${targetIndex}"]`)?.focus();
}
};
};
return {
getPillProps,
getListProps,
handleInputKeyDown
};
}
//#endregion
exports.usePillsReorder = usePillsReorder;
//# sourceMappingURL=use-pills-reorder.cjs.map