UNPKG

react-beautiful-dragify

Version:

React drag and drop library alternatie of react-beautiful-dnd

301 lines (292 loc) 12.1 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var React = require('react'); function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } var React__default = /*#__PURE__*/_interopDefaultLegacy(React); var DragifyContext = React.createContext(undefined); var DragifyProvider = function (_a) { var children = _a.children, onDragStart = _a.onDragStart, onDragEnd = _a.onDragEnd; var _b = React.useState(null), draggedItem = _b[0], setDraggedItem = _b[1]; var _c = React.useState(false), isDragging = _c[0], setIsDragging = _c[1]; var handleDragStart = React.useCallback(function (start) { onDragStart === null || onDragStart === void 0 ? void 0 : onDragStart(start); }, [onDragStart]); var handleDragEnd = React.useCallback(function (result) { setIsDragging(false); setDraggedItem(null); onDragEnd(result); }, [onDragEnd]); return (React__default["default"].createElement(DragifyContext.Provider, { value: { isDragging: isDragging, draggedItem: draggedItem, setDraggedItem: setDraggedItem, setIsDragging: setIsDragging, onDragStart: handleDragStart, onDragEnd: handleDragEnd } }, children)); }; var useDragifyContext = function () { var context = React.useContext(DragifyContext); if (!context) { throw new Error('useDragifyContext must be used within a DragifyProvider'); } return context; }; var TRANSITION_DURATION = 200; var useDraggable = function (options) { var id = options.id, type = options.type, index = options.index, _a = options.isDragDisabled, isDragDisabled = _a === void 0 ? false : _a; options.disableInteractiveElementBlocking; var data = options.data; var _c = useDragifyContext(), setDraggedItem = _c.setDraggedItem, setIsDragging = _c.setIsDragging, onDragStart = _c.onDragStart, onDragEnd = _c.onDragEnd; var elementRef = React.useRef(null); var initialPosition = React.useRef(null); React.useEffect(function () { return function () { initialPosition.current = null; }; }, []); var getDragHandleProps = React.useCallback(function () { return ({ 'data-draghandle': true, tabIndex: 0, role: 'button', 'aria-grabbed': false, onKeyDown: function (e) { if (isDragDisabled) return; switch (e.key) { case ' ': case 'Enter': e.preventDefault(); e.stopPropagation(); startDrag(e); break; case 'Escape': e.preventDefault(); e.stopPropagation(); cancelDrag(); break; } } }); }, [isDragDisabled]); var startDrag = React.useCallback(function (e) { var _a, _b; if (isDragDisabled) return; var element = elementRef.current; if (!element) return; var rect = element.getBoundingClientRect(); initialPosition.current = { x: rect.left, y: rect.top }; setIsDragging(true); setDraggedItem({ id: id, type: type, index: index, droppableId: ((_a = element.closest('[data-droppable]')) === null || _a === void 0 ? void 0 : _a.getAttribute('data-droppable')) || '', data: data }); onDragStart === null || onDragStart === void 0 ? void 0 : onDragStart({ draggableId: id, type: type, source: { droppableId: ((_b = element.closest('[data-droppable]')) === null || _b === void 0 ? void 0 : _b.getAttribute('data-droppable')) || '', index: index } }); // Only set drag image if this is a DragEvent (not a keyboard event) if ('dataTransfer' in e && e.dataTransfer) { var dragImage_1 = element.cloneNode(true); dragImage_1.style.position = 'fixed'; dragImage_1.style.top = '-1000px'; document.body.appendChild(dragImage_1); e.dataTransfer.setDragImage(dragImage_1, 0, 0); setTimeout(function () { return document.body.removeChild(dragImage_1); }, 0); } }, [id, type, index, isDragDisabled, data, setDraggedItem, setIsDragging, onDragStart]); var cancelDrag = React.useCallback(function () { var _a; var element = elementRef.current; if (!element || !initialPosition.current) return; element.style.transition = "transform ".concat(TRANSITION_DURATION, "ms cubic-bezier(0.2, 0, 0, 1)"); element.style.transform = 'translate(0, 0)'; setTimeout(function () { element.style.transition = ''; element.style.transform = ''; }, TRANSITION_DURATION); setIsDragging(false); setDraggedItem(null); initialPosition.current = null; onDragEnd({ draggableId: id, type: type, source: { droppableId: ((_a = element.closest('[data-droppable]')) === null || _a === void 0 ? void 0 : _a.getAttribute('data-droppable')) || '', index: index }, destination: null, reason: 'CANCEL' }); }, [id, type, index, setDraggedItem, setIsDragging, onDragEnd]); return { draggableProps: { ref: elementRef, draggable: !isDragDisabled, 'data-draggable': id, 'data-index': index, onDragStart: startDrag, onDragEnd: cancelDrag, }, dragHandleProps: getDragHandleProps(), }; }; var SCROLL_SPEED = 20; var AUTOSCROLL_THRESHOLD = 50; var useDroppable = function (options) { var id = options.id, type = options.type, _a = options.direction, direction = _a === void 0 ? 'vertical' : _a, _b = options.isDropDisabled, isDropDisabled = _b === void 0 ? false : _b; options.isCombineEnabled; var _d = options.ignoreContainerClipping, ignoreContainerClipping = _d === void 0 ? false : _d; var _e = useDragifyContext(), draggedItem = _e.draggedItem, isDragging = _e.isDragging, onDragEnd = _e.onDragEnd; var dropZoneRef = React.useRef(null); var autoScrollInterval = React.useRef(null); React.useEffect(function () { return function () { if (autoScrollInterval.current) { window.clearInterval(autoScrollInterval.current); } }; }, []); var startAutoScroll = React.useCallback(function (direction) { if (autoScrollInterval.current) return; autoScrollInterval.current = window.setInterval(function () { var element = dropZoneRef.current; if (!element) return; var amount = direction === 'up' ? -SCROLL_SPEED : SCROLL_SPEED; element.scrollTop += amount; }, 16); }, []); var stopAutoScroll = React.useCallback(function () { if (autoScrollInterval.current) { window.clearInterval(autoScrollInterval.current); autoScrollInterval.current = null; } }, []); var handleDragOver = React.useCallback(function (e) { e.preventDefault(); if (isDropDisabled || !isDragging) return; var element = dropZoneRef.current; if (!element) return; var rect = element.getBoundingClientRect(); var mouseY = e.clientY; // Auto-scrolling logic if (mouseY - rect.top < AUTOSCROLL_THRESHOLD) { startAutoScroll('up'); } else if (rect.bottom - mouseY < AUTOSCROLL_THRESHOLD) { startAutoScroll('down'); } else { stopAutoScroll(); } // Calculate drop position var items = Array.from(element.querySelectorAll('[data-draggable]')); var hoveredItem = items.find(function (item) { var itemRect = item.getBoundingClientRect(); return direction === 'vertical' ? mouseY >= itemRect.top && mouseY <= itemRect.bottom : e.clientX >= itemRect.left && e.clientX <= itemRect.right; }); if (hoveredItem) { var hoverIndex_1 = parseInt(hoveredItem.getAttribute('data-index') || '0', 10); var itemRect = hoveredItem.getBoundingClientRect(); var hoverMiddleY = (itemRect.bottom - itemRect.top) / 2; var hoverClientY = mouseY - itemRect.top; if (draggedItem && draggedItem.index < hoverIndex_1 && hoverClientY < hoverMiddleY) { return; } if (draggedItem && draggedItem.index > hoverIndex_1 && hoverClientY > hoverMiddleY) { return; } // Update position styles items.forEach(function (item) { var itemIndex = parseInt(item.getAttribute('data-index') || '0', 10); if (draggedItem && itemIndex > draggedItem.index && itemIndex <= hoverIndex_1) { item.style.transform = direction === 'vertical' ? 'translateY(-100%)' : 'translateX(-100%)'; } else if (draggedItem && itemIndex < draggedItem.index && itemIndex >= hoverIndex_1) { item.style.transform = direction === 'vertical' ? 'translateY(100%)' : 'translateX(100%)'; } else { item.style.transform = ''; } }); } }, [isDropDisabled, isDragging, draggedItem, direction, startAutoScroll, stopAutoScroll]); var handleDrop = React.useCallback(function (e) { e.preventDefault(); stopAutoScroll(); if (isDropDisabled || !draggedItem) return; var element = dropZoneRef.current; if (!element) return; var items = Array.from(element.querySelectorAll('[data-draggable]')); items.forEach(function (item) { item.style.transform = ''; }); var dropIndex = Math.max(0, items.findIndex(function (item) { var itemRect = item.getBoundingClientRect(); return direction === 'vertical' ? e.clientY <= itemRect.bottom : e.clientX <= itemRect.right; })); onDragEnd({ draggableId: draggedItem.id, type: draggedItem.type, source: { droppableId: draggedItem.droppableId, index: draggedItem.index }, destination: { droppableId: id, index: dropIndex }, reason: 'DROP' }); }, [isDropDisabled, draggedItem, direction, id, onDragEnd, stopAutoScroll]); var handleDragLeave = React.useCallback(function (e) { var element = dropZoneRef.current; if (!element) return; var rect = element.getBoundingClientRect(); if (e.clientX < rect.left || e.clientX >= rect.right || e.clientY < rect.top || e.clientY >= rect.bottom) { stopAutoScroll(); } }, [stopAutoScroll]); return { droppableProps: { ref: dropZoneRef, 'data-droppable': id, 'data-type': type, 'data-direction': direction, onDragOver: handleDragOver, onDrop: handleDrop, onDragLeave: handleDragLeave, style: { position: 'relative', overflow: ignoreContainerClipping ? 'visible' : 'auto', } } }; }; exports.DragifyProvider = DragifyProvider; exports.useDraggable = useDraggable; exports.useDroppable = useDroppable; //# sourceMappingURL=index.js.map