react-reorder-list 0.10.1 → 0.10.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ import { DivProps, ReorderListProps } from "./types.mjs";
2
+ import { JSX } from "react";
3
+
4
+ //#region src/components.d.ts
5
+ declare function ReorderIcon({
6
+ children,
7
+ style,
8
+ ...props
9
+ }: DivProps): JSX.Element;
10
+ declare function ReorderList({
11
+ useOnlyIconToDrag,
12
+ selectedItemOpacity,
13
+ animationDuration,
14
+ preserveOrder,
15
+ onPositionChange,
16
+ disabled,
17
+ props,
18
+ children
19
+ }: ReorderListProps): JSX.Element;
20
+ //#endregion
21
+ export { ReorderIcon, ReorderList as default };
package/dist/index.mjs ADDED
@@ -0,0 +1,284 @@
1
+ import React, { Children, cloneElement, createRef, isValidElement, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
2
+
3
+ //#region src/constants.ts
4
+ const scrollThreshold = {
5
+ x: 10,
6
+ y: 100
7
+ };
8
+
9
+ //#endregion
10
+ //#region src/hooks.ts
11
+ function useDraggable(initValue = false) {
12
+ const [draggable, setDraggable] = useState(initValue);
13
+ const enableDragging = useCallback(() => setDraggable(true), []);
14
+ const disableDragging = useCallback(() => setDraggable(false), []);
15
+ return {
16
+ draggable,
17
+ onMouseEnter: enableDragging,
18
+ onMouseLeave: disableDragging,
19
+ onTouchStart: enableDragging,
20
+ onTouchEnd: disableDragging
21
+ };
22
+ }
23
+ function useStateWithHistory(initValue) {
24
+ const [state, setState] = useState(initValue);
25
+ const [prevState, setPrevState] = useState();
26
+ function setStateWithHistory(value) {
27
+ setPrevState(state);
28
+ setState(value);
29
+ }
30
+ return [
31
+ state,
32
+ prevState,
33
+ setStateWithHistory
34
+ ];
35
+ }
36
+
37
+ //#endregion
38
+ //#region src/icons.tsx
39
+ function PiDotsSixVerticalBold(props) {
40
+ return /* @__PURE__ */ React.createElement("span", props, /* @__PURE__ */ React.createElement("svg", {
41
+ viewBox: "0 0 256 256",
42
+ fill: "currentColor",
43
+ width: "1.25rem",
44
+ height: "1.25rem"
45
+ }, /* @__PURE__ */ React.createElement("path", { d: "M108,60A16,16,0,1,1,92,44,16,16,0,0,1,108,60Zm56,16a16,16,0,1,0-16-16A16,16,0,0,0,164,76ZM92,112a16,16,0,1,0,16,16A16,16,0,0,0,92,112Zm72,0a16,16,0,1,0,16,16A16,16,0,0,0,164,112ZM92,180a16,16,0,1,0,16,16A16,16,0,0,0,92,180Zm72,0a16,16,0,1,0,16,16A16,16,0,0,0,164,180Z" })));
46
+ }
47
+
48
+ //#endregion
49
+ //#region src/lib/react.ts
50
+ function calculateBoundingBoxes(children) {
51
+ const boundingBoxes = {};
52
+ Children.forEach(children, (child) => {
53
+ const { key } = child;
54
+ if (key) boundingBoxes[key] = child.props.ref.current.getBoundingClientRect();
55
+ });
56
+ return boundingBoxes;
57
+ }
58
+
59
+ //#endregion
60
+ //#region src/lib/utils.ts
61
+ const areOrdersEqual = (a, b) => a.length === b.length && a.every((key, index) => key === b[index]);
62
+ function swap(array, i, j) {
63
+ const temp = array[i];
64
+ array[i] = array[j];
65
+ array[j] = temp;
66
+ }
67
+
68
+ //#endregion
69
+ //#region src/components.tsx
70
+ if (typeof window !== "undefined") import("drag-drop-touch");
71
+ function Animation({ duration, children }) {
72
+ const [boundingBox, prevBoundingBox, setBoundingBox] = useStateWithHistory({});
73
+ useLayoutEffect(() => {
74
+ if (duration > 0) setBoundingBox(calculateBoundingBoxes(children));
75
+ else setBoundingBox({});
76
+ }, [children]);
77
+ useLayoutEffect(() => {
78
+ if (duration <= 0 || !prevBoundingBox || !Object.keys(prevBoundingBox).length) return;
79
+ children.forEach((child) => {
80
+ const { key } = child;
81
+ if (!key) return;
82
+ const domNode = child.props.ref.current;
83
+ if (!domNode) return;
84
+ const { left: prevLeft, top: prevTop } = prevBoundingBox[key] || {};
85
+ const { left, top } = boundingBox[key] || {};
86
+ const changeInX = prevLeft - left;
87
+ const changeInY = prevTop - top;
88
+ if (!changeInX && !changeInY) return;
89
+ requestAnimationFrame(() => {
90
+ domNode.style.transform = `translate(${changeInX}px, ${changeInY}px)`;
91
+ domNode.style.transition = "none";
92
+ requestAnimationFrame(() => {
93
+ domNode.style.transform = "";
94
+ domNode.style.transition = `transform ${duration}ms`;
95
+ });
96
+ });
97
+ });
98
+ }, [boundingBox]);
99
+ return children;
100
+ }
101
+ function ReorderIcon({ children = /* @__PURE__ */ React.createElement(PiDotsSixVerticalBold, null), style, ...props }) {
102
+ return /* @__PURE__ */ React.createElement("span", {
103
+ style: {
104
+ cursor: "grab",
105
+ ...style
106
+ },
107
+ ...props
108
+ }, children);
109
+ }
110
+ function ReorderItem({ useOnlyIconToDrag, disable, ref, style, children, onTouchEnd: propOnTouchEnd, ...events }) {
111
+ const { draggable, onTouchEnd: draggableOnTouchEnd, ...draggableProps } = useDraggable();
112
+ const recursiveClone = (children) => Children.map(children, (child) => {
113
+ if (!isValidElement(child)) return child;
114
+ return cloneElement(child, child.type === ReorderIcon ? draggableProps : {}, recursiveClone(child.props.children));
115
+ });
116
+ const recursiveChildren = useMemo(() => useOnlyIconToDrag ? recursiveClone(children) : children, [useOnlyIconToDrag, children]);
117
+ return /* @__PURE__ */ React.createElement("div", {
118
+ ref,
119
+ draggable: !disable && draggable,
120
+ style: {
121
+ ...style,
122
+ touchAction: "pan-y",
123
+ cursor: useOnlyIconToDrag ? "default" : "grab"
124
+ },
125
+ ...!disable && {
126
+ ...events,
127
+ ...!useOnlyIconToDrag && draggableProps,
128
+ onTouchEnd: (event) => {
129
+ draggableOnTouchEnd(event);
130
+ propOnTouchEnd(event);
131
+ }
132
+ }
133
+ }, recursiveChildren);
134
+ }
135
+ function ReorderList({ useOnlyIconToDrag = false, selectedItemOpacity = .5, animationDuration = 300, preserveOrder = true, onPositionChange, disabled = false, props, children }) {
136
+ const containerRef = useRef(null);
137
+ const itemRefs = useRef(/* @__PURE__ */ new Map());
138
+ const [order, setOrder] = useState([]);
139
+ const [dragState, setDragState] = useState();
140
+ const [isAnimating, setIsAnimating] = useState(false);
141
+ const [scroll, setScroll] = useState();
142
+ const childMap = useMemo(() => {
143
+ const map = /* @__PURE__ */ new Map();
144
+ Children.forEach(children, (child) => {
145
+ if (!isValidElement(child)) return;
146
+ const { key, props } = child;
147
+ if (!key) return;
148
+ map.set(key, {
149
+ child,
150
+ disabled: props["data-disable-reorder"]
151
+ });
152
+ });
153
+ return map;
154
+ }, [children]);
155
+ const orderedChildren = useMemo(() => {
156
+ if (!order.length) return [];
157
+ return order.flatMap((key, orderIndex) => {
158
+ const { child, disabled } = childMap.get(key) || {};
159
+ if (!isValidElement(child)) return [];
160
+ const ref = getRef(key);
161
+ const isSelected = dragState?.currentIndex === orderIndex;
162
+ return /* @__PURE__ */ React.createElement(ReorderItem, {
163
+ key,
164
+ ref,
165
+ useOnlyIconToDrag,
166
+ disable: disabled,
167
+ style: { opacity: isSelected ? selectedItemOpacity : 1 },
168
+ onDragStart: (event) => {
169
+ event.stopPropagation();
170
+ setDragState({
171
+ startIndex: orderIndex,
172
+ currentIndex: orderIndex,
173
+ startOrder: [...order],
174
+ startRect: ref.current?.getBoundingClientRect?.() || void 0
175
+ });
176
+ },
177
+ onDragEnter: (event) => {
178
+ event.stopPropagation();
179
+ if (!dragState || dragState.currentIndex === orderIndex || isAnimating) return;
180
+ const { width: startWidth, height: startHeight } = dragState.startRect || {
181
+ width: 0,
182
+ height: 0
183
+ };
184
+ const { left, top, width, height } = event.currentTarget.getBoundingClientRect();
185
+ if (event.clientX - left > Math.min(startWidth, width) || event.clientY - top > Math.min(startHeight, height)) return;
186
+ setDragState((prev) => prev ? {
187
+ ...prev,
188
+ currentIndex: orderIndex
189
+ } : void 0);
190
+ setOrder(() => {
191
+ const newOrder = [...dragState.startOrder];
192
+ const shiftForward = dragState.startIndex < orderIndex;
193
+ const increment = shiftForward ? 1 : -1;
194
+ let currentPos = dragState.startIndex;
195
+ for (let index = dragState.startIndex + increment; shiftForward ? index <= orderIndex : index >= orderIndex; index += increment) {
196
+ const key = dragState.startOrder[index];
197
+ if (childMap.get(key)?.disabled) continue;
198
+ swap(newOrder, currentPos, index);
199
+ currentPos = index;
200
+ }
201
+ return newOrder;
202
+ });
203
+ setIsAnimating(true);
204
+ setTimeout(() => setIsAnimating(false), animationDuration);
205
+ },
206
+ onDragEnd: handleDragEnd,
207
+ onTouchMove: (event) => {
208
+ if (!dragState) return;
209
+ const { clientX, screenX, clientY, screenY } = event.touches[0];
210
+ const left = clientX < scrollThreshold.x ? -5 : innerWidth - screenX < scrollThreshold.x ? 5 : 0;
211
+ const top = clientY < scrollThreshold.y ? -10 : innerHeight - screenY < scrollThreshold.y ? 10 : 0;
212
+ setScroll(left || top ? {
213
+ left,
214
+ top
215
+ } : void 0);
216
+ },
217
+ onTouchEnd: () => setScroll(void 0)
218
+ }, child);
219
+ });
220
+ }, [
221
+ childMap,
222
+ order,
223
+ dragState,
224
+ isAnimating,
225
+ useOnlyIconToDrag,
226
+ selectedItemOpacity,
227
+ animationDuration
228
+ ]);
229
+ function getRef(key) {
230
+ if (!itemRefs.current.has(key)) itemRefs.current.set(key, createRef());
231
+ return itemRefs.current.get(key);
232
+ }
233
+ function handleDragEnd(event) {
234
+ if (event) {
235
+ event.stopPropagation();
236
+ if (dragState && dragState.currentIndex !== dragState.startIndex) onPositionChange?.({
237
+ start: dragState.startIndex,
238
+ end: dragState.currentIndex,
239
+ oldOrder: dragState.startOrder,
240
+ newOrder: order,
241
+ revert: () => setOrder(dragState.startOrder)
242
+ });
243
+ }
244
+ setDragState(void 0);
245
+ setScroll(void 0);
246
+ }
247
+ useEffect(() => {
248
+ const currentKeys = [];
249
+ Children.forEach(children, (child) => {
250
+ const { key } = child;
251
+ if (key) currentKeys.push(key);
252
+ });
253
+ let newOrder;
254
+ if (preserveOrder) {
255
+ const currentKeySet = new Set(currentKeys);
256
+ const newKeys = currentKeys.filter((key) => !order.includes(key));
257
+ newOrder = [...order.filter((key) => currentKeySet.has(key)), ...newKeys];
258
+ } else newOrder = currentKeys;
259
+ if (!areOrdersEqual(order, newOrder)) {
260
+ if (dragState) setDragState(void 0);
261
+ setOrder(newOrder);
262
+ }
263
+ }, [children]);
264
+ useEffect(() => {
265
+ if (!scroll) return;
266
+ const { left, top } = scroll;
267
+ const { scrollWidth, scrollHeight } = document.body;
268
+ const interval = setInterval(() => {
269
+ if (left < 0 || top < 0 || scrollWidth - scrollX > innerWidth - left || scrollHeight - scrollY > innerHeight - top) scrollBy({
270
+ left,
271
+ top,
272
+ behavior: "instant"
273
+ });
274
+ }, 20);
275
+ return () => clearInterval(interval);
276
+ }, [scroll]);
277
+ return /* @__PURE__ */ React.createElement("div", {
278
+ ref: containerRef,
279
+ ...props
280
+ }, disabled ? children : /* @__PURE__ */ React.createElement(Animation, { duration: dragState && !scroll ? animationDuration : 0 }, orderedChildren));
281
+ }
282
+
283
+ //#endregion
284
+ export { ReorderIcon, ReorderList as default };
@@ -0,0 +1,50 @@
1
+ import { CSSProperties, DetailedHTMLProps, DragEventHandler, HTMLAttributes, Key, MouseEventHandler, ReactElement, ReactNode, RefObject, TouchEventHandler } from "react";
2
+
3
+ //#region src/types.d.ts
4
+ type AnimationProps = {
5
+ duration: number;
6
+ children: Child[];
7
+ };
8
+ type BoundingBox = Record<string, DOMRect>;
9
+ type Child = ReactElement<{
10
+ ref: RefObject<HTMLElement>;
11
+ }>;
12
+ type Order = Key[];
13
+ type DivDragEventHandler = DragEventHandler<HTMLDivElement>;
14
+ type DivMouseEventHandler = MouseEventHandler<HTMLDivElement>;
15
+ type DivProps = DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>;
16
+ type DivRef = RefObject<HTMLDivElement | null>;
17
+ type DivTouchEventHandler = TouchEventHandler<HTMLDivElement>;
18
+ type PositionChangeHandler = (event: {
19
+ start: number;
20
+ end: number;
21
+ oldOrder: Order;
22
+ newOrder: Order;
23
+ revert: RevertHandler;
24
+ }) => void;
25
+ type ReorderItemProps = {
26
+ useOnlyIconToDrag: boolean;
27
+ disable?: boolean;
28
+ ref: DivRef;
29
+ style: CSSProperties;
30
+ onDragStart?: DivDragEventHandler;
31
+ onDragEnter: DivDragEventHandler;
32
+ onDragEnd: DivDragEventHandler;
33
+ onTouchMove: DivTouchEventHandler;
34
+ onTouchEnd: DivTouchEventHandler;
35
+ children: ReactNode;
36
+ };
37
+ type ReorderListProps = {
38
+ useOnlyIconToDrag?: boolean;
39
+ selectedItemOpacity?: number;
40
+ animationDuration?: number;
41
+ preserveOrder?: boolean;
42
+ onPositionChange?: PositionChangeHandler;
43
+ disabled?: boolean;
44
+ props?: DivProps;
45
+ children?: ReactNode;
46
+ };
47
+ type RevertHandler = () => void;
48
+ type IconProps = React.DetailedHTMLProps<React.HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>;
49
+ //#endregion
50
+ export { AnimationProps, BoundingBox, Child, DivDragEventHandler, DivMouseEventHandler, DivProps, DivRef, DivTouchEventHandler, IconProps, Order, PositionChangeHandler, ReorderItemProps, ReorderListProps, RevertHandler };
package/dist/types.mjs ADDED
@@ -0,0 +1 @@
1
+ export { };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-reorder-list",
3
- "version": "0.10.1",
3
+ "version": "0.10.2",
4
4
  "description": "A simple react component that facilitates the reordering of JSX/HTML elements through drag-and-drop functionality, allowing for easy position changes.",
5
5
  "license": "MIT",
6
6
  "author": "Sahil Aggarwal <aggarwalsahil2004@gmail.com>",
@@ -15,10 +15,10 @@
15
15
  },
16
16
  "type": "module",
17
17
  "exports": {
18
- ".": "./dist/index.js",
19
- "./types": "./dist/types.js"
18
+ ".": "./dist/index.mjs",
19
+ "./types": "./dist/types.mjs"
20
20
  },
21
- "main": "dist/index.js",
21
+ "main": "dist/index.mjs",
22
22
  "files": [
23
23
  "dist"
24
24
  ],
@@ -35,7 +35,7 @@
35
35
  "@types/react": "^19.2.14",
36
36
  "prettier-package-json": "^2.8.0",
37
37
  "release-it": "^19.2.4",
38
- "tsup": "^8.5.1",
38
+ "tsdown": "^0.20.3",
39
39
  "typescript": "^5.9.3"
40
40
  },
41
41
  "keywords": [
@@ -50,8 +50,8 @@
50
50
  ],
51
51
  "scripts": {
52
52
  "build": "pnpm i && pnpm run compile",
53
- "compile": "tsup",
54
- "dev": "tsup --watch",
53
+ "compile": "tsdown",
54
+ "dev": "tsdown --watch",
55
55
  "dry-release": "release-it --ci --dry-run",
56
56
  "prettier": "prettier-package-json --write package.json",
57
57
  "pub": "pnpm login && pnpm publish",
@@ -1,248 +0,0 @@
1
- import React2, { useRef, useState, useMemo, Children, isValidElement, createRef, useEffect, useLayoutEffect, useCallback, cloneElement } from 'react';
2
-
3
- var __defProp = Object.defineProperty;
4
- var __defProps = Object.defineProperties;
5
- var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
6
- var __getOwnPropSymbols = Object.getOwnPropertySymbols;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __propIsEnum = Object.prototype.propertyIsEnumerable;
9
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
10
- var __spreadValues = (a, b) => {
11
- for (var prop in b || (b = {}))
12
- if (__hasOwnProp.call(b, prop))
13
- __defNormalProp(a, prop, b[prop]);
14
- if (__getOwnPropSymbols)
15
- for (var prop of __getOwnPropSymbols(b)) {
16
- if (__propIsEnum.call(b, prop))
17
- __defNormalProp(a, prop, b[prop]);
18
- }
19
- return a;
20
- };
21
- var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
22
- var __objRest = (source, exclude) => {
23
- var target = {};
24
- for (var prop in source)
25
- if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
26
- target[prop] = source[prop];
27
- if (source != null && __getOwnPropSymbols)
28
- for (var prop of __getOwnPropSymbols(source)) {
29
- if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
30
- target[prop] = source[prop];
31
- }
32
- return target;
33
- };
34
-
35
- // src/constants.ts
36
- var scrollThreshold = { x: 10, y: 100 };
37
- function useDraggable(initValue = false) {
38
- const [draggable, setDraggable] = useState(initValue);
39
- const enableDragging = useCallback(() => setDraggable(true), []);
40
- const disableDragging = useCallback(() => setDraggable(false), []);
41
- return { draggable, onMouseEnter: enableDragging, onMouseLeave: disableDragging, onTouchStart: enableDragging, onTouchEnd: disableDragging };
42
- }
43
- function useStateWithHistory(initValue) {
44
- const [state, setState] = useState(initValue);
45
- const [prevState, setPrevState] = useState();
46
- function setStateWithHistory(value) {
47
- setPrevState(state);
48
- setState(value);
49
- }
50
- return [state, prevState, setStateWithHistory];
51
- }
52
- function PiDotsSixVerticalBold(props) {
53
- return /* @__PURE__ */ React2.createElement("span", __spreadValues({}, props), /* @__PURE__ */ React2.createElement("svg", { viewBox: "0 0 256 256", fill: "currentColor", width: "1.25rem", height: "1.25rem" }, /* @__PURE__ */ React2.createElement("path", { d: "M108,60A16,16,0,1,1,92,44,16,16,0,0,1,108,60Zm56,16a16,16,0,1,0-16-16A16,16,0,0,0,164,76ZM92,112a16,16,0,1,0,16,16A16,16,0,0,0,92,112Zm72,0a16,16,0,1,0,16,16A16,16,0,0,0,164,112ZM92,180a16,16,0,1,0,16,16A16,16,0,0,0,92,180Zm72,0a16,16,0,1,0,16,16A16,16,0,0,0,164,180Z" })));
54
- }
55
- function calculateBoundingBoxes(children) {
56
- const boundingBoxes = {};
57
- Children.forEach(children, (child) => {
58
- const { key } = child;
59
- if (key) boundingBoxes[key] = child.props.ref.current.getBoundingClientRect();
60
- });
61
- return boundingBoxes;
62
- }
63
-
64
- // src/lib/utils.ts
65
- var areOrdersEqual = (a, b) => a.length === b.length && a.every((key, index) => key === b[index]);
66
- function swap(array, i, j) {
67
- const temp = array[i];
68
- array[i] = array[j];
69
- array[j] = temp;
70
- }
71
-
72
- // src/components.tsx
73
- if (typeof window !== "undefined") import('drag-drop-touch');
74
- function Animation({ duration, children }) {
75
- const [boundingBox, prevBoundingBox, setBoundingBox] = useStateWithHistory({});
76
- useLayoutEffect(() => {
77
- if (duration > 0) setBoundingBox(calculateBoundingBoxes(children));
78
- else setBoundingBox({});
79
- }, [children]);
80
- useLayoutEffect(() => {
81
- if (duration <= 0 || !prevBoundingBox || !Object.keys(prevBoundingBox).length) return;
82
- children.forEach((child) => {
83
- const { key } = child;
84
- if (!key) return;
85
- const domNode = child.props.ref.current;
86
- if (!domNode) return;
87
- const { left: prevLeft, top: prevTop } = prevBoundingBox[key] || {};
88
- const { left, top } = boundingBox[key] || {};
89
- const changeInX = prevLeft - left;
90
- const changeInY = prevTop - top;
91
- if (!changeInX && !changeInY) return;
92
- requestAnimationFrame(() => {
93
- domNode.style.transform = `translate(${changeInX}px, ${changeInY}px)`;
94
- domNode.style.transition = "none";
95
- requestAnimationFrame(() => {
96
- domNode.style.transform = "";
97
- domNode.style.transition = `transform ${duration}ms`;
98
- });
99
- });
100
- });
101
- }, [boundingBox]);
102
- return children;
103
- }
104
- function ReorderIcon(_a) {
105
- var _b = _a, { children = /* @__PURE__ */ React2.createElement(PiDotsSixVerticalBold, null), style } = _b, props = __objRest(_b, ["children", "style"]);
106
- return /* @__PURE__ */ React2.createElement("span", __spreadValues({ style: __spreadValues({ cursor: "grab" }, style) }, props), children);
107
- }
108
- function ReorderItem(_a) {
109
- var _b = _a, { useOnlyIconToDrag, disable, ref, style, children, onTouchEnd: propOnTouchEnd } = _b, events = __objRest(_b, ["useOnlyIconToDrag", "disable", "ref", "style", "children", "onTouchEnd"]);
110
- const _a2 = useDraggable(), { draggable, onTouchEnd: draggableOnTouchEnd } = _a2, draggableProps = __objRest(_a2, ["draggable", "onTouchEnd"]);
111
- const recursiveClone = (children2) => Children.map(children2, (child) => {
112
- if (!isValidElement(child)) return child;
113
- return cloneElement(child, child.type === ReorderIcon ? draggableProps : {}, recursiveClone(child.props.children));
114
- });
115
- const recursiveChildren = useMemo(() => useOnlyIconToDrag ? recursiveClone(children) : children, [useOnlyIconToDrag, children]);
116
- return /* @__PURE__ */ React2.createElement(
117
- "div",
118
- __spreadValues({
119
- ref,
120
- draggable: !disable && draggable,
121
- style: __spreadProps(__spreadValues({}, style), { touchAction: "pan-y", cursor: useOnlyIconToDrag ? "default" : "grab" })
122
- }, !disable && __spreadProps(__spreadValues(__spreadValues({}, events), !useOnlyIconToDrag && draggableProps), {
123
- onTouchEnd: (event) => {
124
- draggableOnTouchEnd(event);
125
- propOnTouchEnd(event);
126
- }
127
- })),
128
- recursiveChildren
129
- );
130
- }
131
- function ReorderList({ useOnlyIconToDrag = false, selectedItemOpacity = 0.5, animationDuration = 300, preserveOrder = true, onPositionChange, disabled = false, props, children }) {
132
- const containerRef = useRef(null);
133
- const itemRefs = useRef(/* @__PURE__ */ new Map());
134
- const [order, setOrder] = useState([]);
135
- const [dragState, setDragState] = useState();
136
- const [isAnimating, setIsAnimating] = useState(false);
137
- const [scroll, setScroll] = useState();
138
- const childMap = useMemo(() => {
139
- const map = /* @__PURE__ */ new Map();
140
- Children.forEach(children, (child) => {
141
- if (!isValidElement(child)) return;
142
- const { key, props: props2 } = child;
143
- if (!key) return;
144
- map.set(key, { child, disabled: props2["data-disable-reorder"] });
145
- });
146
- return map;
147
- }, [children]);
148
- const orderedChildren = useMemo(() => {
149
- if (!order.length) return [];
150
- return order.flatMap((key, orderIndex) => {
151
- const { child, disabled: disabled2 } = childMap.get(key) || {};
152
- if (!isValidElement(child)) return [];
153
- const ref = getRef(key);
154
- const isSelected = (dragState == null ? void 0 : dragState.currentIndex) === orderIndex;
155
- return /* @__PURE__ */ React2.createElement(
156
- ReorderItem,
157
- {
158
- key,
159
- ref,
160
- useOnlyIconToDrag,
161
- disable: disabled2,
162
- style: { opacity: isSelected ? selectedItemOpacity : 1 },
163
- onDragStart: (event) => {
164
- var _a, _b;
165
- event.stopPropagation();
166
- setDragState({ startIndex: orderIndex, currentIndex: orderIndex, startOrder: [...order], startRect: ((_b = (_a = ref.current) == null ? void 0 : _a.getBoundingClientRect) == null ? void 0 : _b.call(_a)) || void 0 });
167
- },
168
- onDragEnter: (event) => {
169
- event.stopPropagation();
170
- if (!dragState || dragState.currentIndex === orderIndex || isAnimating) return;
171
- const { width: startWidth, height: startHeight } = dragState.startRect || { width: 0, height: 0 };
172
- const { left, top, width, height } = event.currentTarget.getBoundingClientRect();
173
- if (event.clientX - left > Math.min(startWidth, width) || event.clientY - top > Math.min(startHeight, height)) return;
174
- setDragState((prev) => prev ? __spreadProps(__spreadValues({}, prev), { currentIndex: orderIndex }) : void 0);
175
- setOrder(() => {
176
- var _a;
177
- const newOrder = [...dragState.startOrder];
178
- const shiftForward = dragState.startIndex < orderIndex;
179
- const increment = shiftForward ? 1 : -1;
180
- let currentPos = dragState.startIndex;
181
- for (let index = dragState.startIndex + increment; shiftForward ? index <= orderIndex : index >= orderIndex; index += increment) {
182
- const key2 = dragState.startOrder[index];
183
- if ((_a = childMap.get(key2)) == null ? void 0 : _a.disabled) continue;
184
- swap(newOrder, currentPos, index);
185
- currentPos = index;
186
- }
187
- return newOrder;
188
- });
189
- setIsAnimating(true);
190
- setTimeout(() => setIsAnimating(false), animationDuration);
191
- },
192
- onDragEnd: handleDragEnd,
193
- onTouchMove: (event) => {
194
- if (!dragState) return;
195
- const { clientX, screenX, clientY, screenY } = event.touches[0];
196
- const left = clientX < scrollThreshold.x ? -5 : innerWidth - screenX < scrollThreshold.x ? 5 : 0;
197
- const top = clientY < scrollThreshold.y ? -10 : innerHeight - screenY < scrollThreshold.y ? 10 : 0;
198
- setScroll(left || top ? { left, top } : void 0);
199
- },
200
- onTouchEnd: () => setScroll(void 0)
201
- },
202
- child
203
- );
204
- });
205
- }, [childMap, order, dragState, isAnimating, useOnlyIconToDrag, selectedItemOpacity, animationDuration]);
206
- function getRef(key) {
207
- if (!itemRefs.current.has(key)) itemRefs.current.set(key, createRef());
208
- return itemRefs.current.get(key);
209
- }
210
- function handleDragEnd(event) {
211
- if (event) {
212
- event.stopPropagation();
213
- if (dragState && dragState.currentIndex !== dragState.startIndex) onPositionChange == null ? void 0 : onPositionChange({ start: dragState.startIndex, end: dragState.currentIndex, oldOrder: dragState.startOrder, newOrder: order, revert: () => setOrder(dragState.startOrder) });
214
- }
215
- setDragState(void 0);
216
- setScroll(void 0);
217
- }
218
- useEffect(() => {
219
- const currentKeys = [];
220
- Children.forEach(children, (child) => {
221
- const { key } = child;
222
- if (key) currentKeys.push(key);
223
- });
224
- let newOrder;
225
- if (preserveOrder) {
226
- const currentKeySet = new Set(currentKeys);
227
- const newKeys = currentKeys.filter((key) => !order.includes(key));
228
- const filteredOrder = order.filter((key) => currentKeySet.has(key));
229
- newOrder = [...filteredOrder, ...newKeys];
230
- } else newOrder = currentKeys;
231
- if (!areOrdersEqual(order, newOrder)) {
232
- if (dragState) setDragState(void 0);
233
- setOrder(newOrder);
234
- }
235
- }, [children]);
236
- useEffect(() => {
237
- if (!scroll) return;
238
- const { left, top } = scroll;
239
- const { scrollWidth, scrollHeight } = document.body;
240
- const interval = setInterval(() => {
241
- if (left < 0 || top < 0 || scrollWidth - scrollX > innerWidth - left || scrollHeight - scrollY > innerHeight - top) scrollBy({ left, top, behavior: "instant" });
242
- }, 20);
243
- return () => clearInterval(interval);
244
- }, [scroll]);
245
- return /* @__PURE__ */ React2.createElement("div", __spreadValues({ ref: containerRef }, props), disabled ? children : /* @__PURE__ */ React2.createElement(Animation, { duration: dragState && !scroll ? animationDuration : 0 }, orderedChildren));
246
- }
247
-
248
- export { ReorderIcon, ReorderList };
@@ -1,7 +0,0 @@
1
- import { JSX } from 'react';
2
- import { ReorderListProps, DivProps } from './types.js';
3
-
4
- declare function ReorderIcon({ children, style, ...props }: DivProps): JSX.Element;
5
- declare function ReorderList({ useOnlyIconToDrag, selectedItemOpacity, animationDuration, preserveOrder, onPositionChange, disabled, props, children }: ReorderListProps): JSX.Element;
6
-
7
- export { ReorderIcon, ReorderList as default };
@@ -1 +0,0 @@
1
- export { ReorderIcon, ReorderList as default } from './chunks/chunk-RWSH3ATP.js';
package/dist/index.d.ts DELETED
@@ -1,3 +0,0 @@
1
- export { ReorderIcon, default } from './components.js';
2
- import 'react';
3
- import './types.js';
package/dist/index.js DELETED
@@ -1 +0,0 @@
1
- export { ReorderIcon, ReorderList as default } from './chunks/chunk-RWSH3ATP.js';
package/dist/types.d.ts DELETED
@@ -1,49 +0,0 @@
1
- import { Key, DetailedHTMLProps, HTMLAttributes, ReactNode, ReactElement, RefObject, DragEventHandler, MouseEventHandler, TouchEventHandler, CSSProperties } from 'react';
2
-
3
- type AnimationProps = {
4
- duration: number;
5
- children: Child[];
6
- };
7
- type BoundingBox = Record<string, DOMRect>;
8
- type Child = ReactElement<{
9
- ref: RefObject<HTMLElement>;
10
- }>;
11
- type Order = Key[];
12
- type DivDragEventHandler = DragEventHandler<HTMLDivElement>;
13
- type DivMouseEventHandler = MouseEventHandler<HTMLDivElement>;
14
- type DivProps = DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>;
15
- type DivRef = RefObject<HTMLDivElement | null>;
16
- type DivTouchEventHandler = TouchEventHandler<HTMLDivElement>;
17
- type PositionChangeHandler = (event: {
18
- start: number;
19
- end: number;
20
- oldOrder: Order;
21
- newOrder: Order;
22
- revert: RevertHandler;
23
- }) => void;
24
- type ReorderItemProps = {
25
- useOnlyIconToDrag: boolean;
26
- disable?: boolean;
27
- ref: DivRef;
28
- style: CSSProperties;
29
- onDragStart?: DivDragEventHandler;
30
- onDragEnter: DivDragEventHandler;
31
- onDragEnd: DivDragEventHandler;
32
- onTouchMove: DivTouchEventHandler;
33
- onTouchEnd: DivTouchEventHandler;
34
- children: ReactNode;
35
- };
36
- type ReorderListProps = {
37
- useOnlyIconToDrag?: boolean;
38
- selectedItemOpacity?: number;
39
- animationDuration?: number;
40
- preserveOrder?: boolean;
41
- onPositionChange?: PositionChangeHandler;
42
- disabled?: boolean;
43
- props?: DivProps;
44
- children?: ReactNode;
45
- };
46
- type RevertHandler = () => void;
47
- type IconProps = React.DetailedHTMLProps<React.HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>;
48
-
49
- export type { AnimationProps, BoundingBox, Child, DivDragEventHandler, DivMouseEventHandler, DivProps, DivRef, DivTouchEventHandler, IconProps, Order, PositionChangeHandler, ReorderItemProps, ReorderListProps, RevertHandler };
package/dist/types.js DELETED
@@ -1 +0,0 @@
1
-