UNPKG

@kietpt2003/react-native-core-ui

Version:
249 lines (248 loc) 12.5 kB
var __rest = (this && this.__rest) || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; /// <reference lib="dom" /> TODO: DO NOT REMOVE THIS LINE import React from "react"; import { DEFAULT_PROPS } from "../constants/DraggableFlatList/constants"; import { CellProvider } from "../context/DraggableFlatList/cellContext"; import DraggableFlatListProvider from "../context/DraggableFlatList/draggableFlatListContext"; function DraggableFlatListWeb(_a) { var { data, renderItem, keyExtractor, onDragEnd, onDragBegin, onRelease, onPlaceholderIndexChange, activationDistance = DEFAULT_PROPS.activationDistance, containerStyle, horizontal = false } = _a, props = __rest(_a, ["data", "renderItem", "keyExtractor", "onDragEnd", "onDragBegin", "onRelease", "onPlaceholderIndexChange", "activationDistance", "containerStyle", "horizontal"]); const [draggedIndex, setDraggedIndex] = React.useState(null); const [tempData, setTempData] = React.useState(null); const placeholderIndexRef = React.useRef(null); const containerRef = React.useRef(null); const itemRefs = React.useRef(new Map()); const currentIndexRef = React.useRef(null); const draggedKeyRef = React.useRef(null); const positionsRef = React.useRef(new Map()); const lastReorderIndexRef = React.useRef(null); const lastPointerRef = React.useRef(null); const dragAnchorRef = React.useRef(null); const containerRectRef = React.useRef(null); const [dragGhost, setDragGhost] = React.useState(null); const activeKey = draggedKeyRef.current; const getKey = React.useCallback((item, index) => { return keyExtractor(item, index); }, [keyExtractor]); const handleDragStart = React.useCallback((e, index) => { var _a, _b; setDraggedIndex(index); const key = keyExtractor(data[index], index); draggedKeyRef.current = key; currentIndexRef.current = index; setTempData([...data]); placeholderIndexRef.current = index; onDragBegin === null || onDragBegin === void 0 ? void 0 : onDragBegin(index); e.dataTransfer.effectAllowed = "move"; e.dataTransfer.setData("text/plain", index.toString()); const el = itemRefs.current.get(key); if (el) { const rect = el.getBoundingClientRect(); const container = containerRef.current; if (container) { containerRectRef.current = container.getBoundingClientRect(); } const img = new Image(); img.src = "data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'></svg>"; e.dataTransfer.setDragImage(img, 0, 0); const mouseY = e.clientY; const mouseX = e.clientX; const anchor = dragAnchorRef.current; setDragGhost({ x: e.clientX, y: e.clientY, offsetX: (_a = anchor === null || anchor === void 0 ? void 0 : anchor.offsetX) !== null && _a !== void 0 ? _a : rect.width / 2, offsetY: (_b = anchor === null || anchor === void 0 ? void 0 : anchor.offsetY) !== null && _b !== void 0 ? _b : rect.height / 2, width: rect.width, height: rect.height, item: data[index], index, key, }); } }, [onDragBegin, data, keyExtractor]); const handleDragEnd = React.useCallback(() => { if (draggedIndex !== null) { onRelease === null || onRelease === void 0 ? void 0 : onRelease(draggedIndex); } placeholderIndexRef.current = null; lastPointerRef.current = null; setDraggedIndex(null); setDragGhost(null); lastReorderIndexRef.current = null; }, [draggedIndex, onRelease]); const handleContainerDragOver = React.useCallback((e) => { e.preventDefault(); setDragGhost((prev) => { const rect = containerRectRef.current; if (!prev || !rect) return prev; return Object.assign(Object.assign({}, prev), { x: e.clientX - rect.left, y: e.clientY - rect.top }); }); if (!tempData || !draggedKeyRef.current) return; const mouseY = e.clientY; const mouseX = e.clientX; let nextIndex = null; if (lastPointerRef.current) { const dx = Math.abs(mouseX - lastPointerRef.current.x); const dy = Math.abs(mouseY - lastPointerRef.current.y); if (dx < 2 && dy < 2) { return; } } lastPointerRef.current = { x: mouseX, y: mouseY }; for (let i = 0; i < tempData.length; i++) { const key = keyExtractor(tempData[i], i); const el = itemRefs.current.get(key); if (!el) continue; const rect = el.getBoundingClientRect(); const isInside = horizontal ? mouseX >= rect.left && mouseX <= rect.right : mouseY >= rect.top && mouseY <= rect.bottom; if (!isInside) continue; const isAfter = horizontal ? mouseX > rect.left + rect.width / 1.5 : mouseY > rect.top + rect.height / 1.5; nextIndex = isAfter ? i + 1 : i; break; } if (nextIndex === null || placeholderIndexRef.current === nextIndex || lastReorderIndexRef.current === nextIndex) { return; } positionsRef.current.clear(); tempData.forEach((item, index) => { const key = keyExtractor(item, index); const el = itemRefs.current.get(key); if (el) positionsRef.current.set(key, el.getBoundingClientRect()); }); placeholderIndexRef.current = nextIndex; onPlaceholderIndexChange === null || onPlaceholderIndexChange === void 0 ? void 0 : onPlaceholderIndexChange(nextIndex); setTempData((prev) => { if (!prev || !draggedKeyRef.current) return prev; const from = prev.findIndex((item, index) => keyExtractor(item, index) === draggedKeyRef.current); if (from === -1 || from === nextIndex) return prev; const arr = [...prev]; const [item] = arr.splice(from, 1); arr.splice(nextIndex, 0, item); return arr; }); lastReorderIndexRef.current = nextIndex; requestAnimationFrame(() => { positionsRef.current.forEach((prevRect, key) => { if (key === draggedKeyRef.current) return; const el = itemRefs.current.get(key); if (!el) return; const nextRect = el.getBoundingClientRect(); const dx = prevRect.left - nextRect.left; const dy = prevRect.top - nextRect.top; if (!dx && !dy) return; el.style.transform = `translate(${dx}px, ${dy}px)`; el.style.transition = "none"; requestAnimationFrame(() => { el.style.transform = ""; el.style.transition = "transform 220ms cubic-bezier(0.22, 1, 0.36, 1)"; }); }); }); }, [tempData, horizontal, keyExtractor, onPlaceholderIndexChange]); const workingData = tempData !== null && tempData !== void 0 ? tempData : data; const getItemStyle = (key) => key === draggedKeyRef.current ? { opacity: 0 } : {}; React.useLayoutEffect(() => { if (draggedKeyRef.current !== null) return; itemRefs.current.forEach((el) => { el.style.transform = ""; el.style.transition = ""; }); }, [workingData]); return (_jsx(DraggableFlatListProvider, { activeKey: activeKey, keyExtractor: keyExtractor, horizontal: !!horizontal, layoutAnimationDisabled: false, children: _jsxs("div", Object.assign({ ref: containerRef, style: Object.assign({ display: horizontal ? "flex" : "block", overflow: horizontal ? "auto" : "visible", minHeight: horizontal ? "auto" : "100%" }, containerStyle), onDragOver: handleContainerDragOver, onDrop: (e) => { e.preventDefault(); if (!tempData || !draggedKeyRef.current) return; const from = data.findIndex((item) => keyExtractor(item, 0) === draggedKeyRef.current); const to = placeholderIndexRef.current; if (from === -1 || to == null) return; const newData = [...data]; const [item] = newData.splice(from, 1); newData.splice(to, 0, item); onDragEnd === null || onDragEnd === void 0 ? void 0 : onDragEnd({ from, to, data: newData }); draggedKeyRef.current = null; currentIndexRef.current = null; placeholderIndexRef.current = null; setDragGhost(null); setDraggedIndex(null); setTempData(null); lastReorderIndexRef.current = null; itemRefs.current.forEach((el) => { el.style.transform = ""; el.style.transition = ""; }); lastPointerRef.current = null; onRelease === null || onRelease === void 0 ? void 0 : onRelease(from); } }, props, { children: [workingData.map((item, index) => { const key = getKey(item, index); const isActive = key === draggedKeyRef.current; return (_jsx(CellProvider, { isActive: isActive, children: _jsx("div", { ref: (el) => { if (el) { itemRefs.current.set(key, el); } else { itemRefs.current.delete(key); } }, draggable: draggedIndex === null, onMouseDown: (e) => { const el = itemRefs.current.get(key); if (!el) return; const rect = el.getBoundingClientRect(); dragAnchorRef.current = { offsetX: e.clientX - rect.left, offsetY: e.clientY - rect.top, }; }, onDragStart: (e) => { handleDragStart(e, index); }, onDragEnd: handleDragEnd, style: Object.assign({ cursor: draggedIndex === null ? "grab" : "grabbing", userSelect: "none", position: "relative" }, getItemStyle(key)), children: renderItem({ item, getIndex: () => index, drag: () => { }, isActive, }) }) }, key)); }), dragGhost && (_jsx(CellProvider, { isActive: true, children: _jsx("div", { style: { position: "absolute", left: dragGhost.x - dragGhost.offsetX, top: dragGhost.y - dragGhost.offsetY, width: dragGhost.width, height: dragGhost.height, pointerEvents: "none", zIndex: 9999, }, children: renderItem({ item: dragGhost.item, getIndex: () => dragGhost.index, drag: () => { }, isActive: true, }) }) }))] })) })); } export default DraggableFlatListWeb;