react-reorder-list 0.8.4 → 0.8.6

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.
package/README.md CHANGED
@@ -181,26 +181,38 @@ export default function App() {
181
181
  }
182
182
  ```
183
183
 
184
- ## ReorderList Component API Reference
184
+ ## API Reference
185
+
186
+ ### ReorderList Component
185
187
 
186
188
  Here is the full API for the `<ReorderList>` component, these properties can be set on an instance of ReorderList:
187
- | Parameter | Type | Required | Default | Description |
188
- | - | - | - | - | - |
189
- | `useOnlyIconToDrag` | `boolean` | No | false | See [usage with ReorderIcon](#usage-with-reordericon) |
190
- | `selectedItemOpacity` | `number (0 to 1)` | No | 0.5 | This determines the opacity of the item being dragged, until released. |
191
- | `animationDuration` | `number` | No | 400 | The duration (in ms) of swapping animation between items. If set to 0, animation will be disabled. |
192
- | `watchChildrenUpdates` | `boolean` | No | false | Enable this to listen to any updates in children of `<ReorderList>` and update the state accordingly. See [listen to children updates](#listen-to-children-updates) |
193
- | `preserveOrder` | `boolean` | No | false | Works along woth `watchChildrenUpdates` to determine whether to preserve existing order or not. See [listen to children updates](#listen-to-children-updates) |
194
- | `onPositionChange` | [`PositionChangeHandler`](#positionchangehandler) | No | - | Function to be executed on item position change. |
195
- | `disabled` | `boolean` | No | false | When set to true, `<ReorderList>` will work as a plain `div` with no functionality. |
196
- | `props` | `React.DetailedHTMLProps` | No | - | Props to customize the `<ReorderList>` component. |
197
189
 
198
- ### Types
190
+ | Parameter | Type | Required | Default | Description |
191
+ | ---------------------- | ------------------------------------------------- | -------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
192
+ | `useOnlyIconToDrag` | `boolean` | No | false | See [usage with ReorderIcon](#usage-with-reordericon) |
193
+ | `selectedItemOpacity` | `number (0 to 1)` | No | 0.5 | This determines the opacity of the item being dragged, until released. |
194
+ | `animationDuration` | `number` | No | 300 | The duration (in ms) of swapping animation between items. If set to 0, animation will be disabled. |
195
+ | `watchChildrenUpdates` | `boolean` | No | false | Enable this to listen to any updates in children of `<ReorderList>` and update the state accordingly. See [listen to children updates](#listen-to-children-updates) |
196
+ | `preserveOrder` | `boolean` | No | false | Works along woth `watchChildrenUpdates` to determine whether to preserve existing order or not. See [listen to children updates](#listen-to-children-updates) |
197
+ | `onPositionChange` | [`PositionChangeHandler`](#positionchangehandler) | No | - | Function to be executed on item position change. |
198
+ | `disabled` | `boolean` | No | false | When set to true, `<ReorderList>` will work as a plain `div` with no functionality. |
199
+ | `props` | [`DivProps`](#divprops) | No | - | Props to customize the `<ReorderList>` component. |
200
+
201
+ ## Types
202
+
203
+ ### DivProps
204
+
205
+ ```typescript
206
+ import type { DetailedHTMLProps, HTMLAttributes } from "react";
207
+
208
+ type DivProps = DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>;
209
+ ```
199
210
 
200
- #### PositionChangeHandler
211
+ ### PositionChangeHandler
201
212
 
202
213
  ```typescript
203
- import { ReactNode } from "react";
214
+ import type { ReactNode } from "react";
215
+
204
216
  type RevertHandler = () => void;
205
217
  type PositionChangeParams = {
206
218
  start?: number; // Index of the item being dragged
@@ -0,0 +1,235 @@
1
+ import React2, { useRef, useState, Children, useMemo, createRef, useEffect, isValidElement, 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
+ function useDraggable(initValue = false) {
35
+ const [draggable, setDraggable] = useState(initValue);
36
+ const enableDragging = useCallback(() => setDraggable(true), []);
37
+ const disableDragging = useCallback(() => setDraggable(false), []);
38
+ return { draggable, onMouseEnter: enableDragging, onMouseLeave: disableDragging, onTouchStart: enableDragging, onTouchEnd: disableDragging };
39
+ }
40
+ function useStateWithHistory(initValue) {
41
+ const [state, setState] = useState(initValue);
42
+ const [prevState, setPrevState] = useState();
43
+ function setStateWithHistory(value) {
44
+ setPrevState(state);
45
+ setState(value);
46
+ }
47
+ return [state, prevState, setStateWithHistory];
48
+ }
49
+ var getKey = (child) => {
50
+ var _a;
51
+ return (_a = child == null ? void 0 : child.key) == null ? void 0 : _a.split("/.")[0];
52
+ };
53
+ function calculateBoundingBoxes(children) {
54
+ const boundingBoxes = {};
55
+ Children.forEach(children, (child) => {
56
+ const key = getKey(child);
57
+ if (key) boundingBoxes[key] = child.props.ref.current.getBoundingClientRect();
58
+ });
59
+ return boundingBoxes;
60
+ }
61
+
62
+ // src/constants.ts
63
+ var scrollThreshold = { x: 10, y: 100 };
64
+ function PiDotsSixVerticalBold(props) {
65
+ 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" })));
66
+ }
67
+
68
+ // src/lib/utils.ts
69
+ function swap(array, i, j) {
70
+ const temp = array[i];
71
+ array[i] = array[j];
72
+ array[j] = temp;
73
+ }
74
+
75
+ // src/components.tsx
76
+ if (typeof window !== "undefined") import('drag-drop-touch');
77
+ function Animation({ duration, children }) {
78
+ const [boundingBox, prevBoundingBox, setBoundingBox] = useStateWithHistory({});
79
+ useLayoutEffect(() => {
80
+ if (duration > 0) setBoundingBox(calculateBoundingBoxes(children));
81
+ else setBoundingBox({});
82
+ }, [children]);
83
+ useLayoutEffect(() => {
84
+ if (duration > 0 && prevBoundingBox && Object.keys(prevBoundingBox).length)
85
+ Children.forEach(children, (child) => {
86
+ const key = getKey(child);
87
+ if (!key) return;
88
+ const domNode = child.props.ref.current;
89
+ const { left: prevLeft, top: prevTop } = prevBoundingBox[key] || {};
90
+ const { left, top } = boundingBox[key];
91
+ const changeInX = prevLeft - left, changeInY = prevTop - top;
92
+ if (changeInX || changeInY)
93
+ requestAnimationFrame(() => {
94
+ domNode.style.transform = `translate(${changeInX}px, ${changeInY}px)`;
95
+ domNode.style.transition = "none";
96
+ requestAnimationFrame(() => {
97
+ domNode.style.transform = "";
98
+ domNode.style.transition = `transform ${duration}ms`;
99
+ });
100
+ });
101
+ });
102
+ }, [boundingBox]);
103
+ return children;
104
+ }
105
+ function ReorderIcon(_a) {
106
+ var _b = _a, { children = /* @__PURE__ */ React2.createElement(PiDotsSixVerticalBold, null), style } = _b, props = __objRest(_b, ["children", "style"]);
107
+ return /* @__PURE__ */ React2.createElement("span", __spreadValues({ style: __spreadValues({ cursor: "grab" }, style) }, props), children);
108
+ }
109
+ function ReorderItem(_a) {
110
+ var _b = _a, { useOnlyIconToDrag, disable, ref, style, children, onTouchEnd: propOnTouchEnd } = _b, events = __objRest(_b, ["useOnlyIconToDrag", "disable", "ref", "style", "children", "onTouchEnd"]);
111
+ const _a2 = useDraggable(), { draggable, onTouchEnd: draggableOnTouchEnd } = _a2, draggableProps = __objRest(_a2, ["draggable", "onTouchEnd"]);
112
+ const recursiveClone = (children2) => Children.map(children2, (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__ */ React2.createElement(
118
+ "div",
119
+ __spreadValues({
120
+ ref,
121
+ draggable: !disable && draggable,
122
+ style: __spreadProps(__spreadValues({}, style), { touchAction: "pan-y", cursor: useOnlyIconToDrag ? "default" : "grab" })
123
+ }, !disable && __spreadProps(__spreadValues(__spreadValues({}, events), !useOnlyIconToDrag && draggableProps), {
124
+ onTouchEnd: (event) => {
125
+ draggableOnTouchEnd(event);
126
+ propOnTouchEnd(event);
127
+ }
128
+ })),
129
+ recursiveChildren
130
+ );
131
+ }
132
+ function ReorderList({ useOnlyIconToDrag = false, selectedItemOpacity = 0.5, animationDuration = 300, watchChildrenUpdates = false, preserveOrder = false, onPositionChange, disabled = false, props, children }) {
133
+ const ref = useRef(null);
134
+ const [start, setStart] = useState(-1);
135
+ const [selected, setSelected] = useState(-1);
136
+ const [items, setItems] = useState(Children.toArray(children));
137
+ const [temp, setTemp] = useState({ items: [] });
138
+ const [isAnimating, setIsAnimating] = useState(false);
139
+ const [scroll, setScroll] = useState();
140
+ const [refs, disableArr] = useMemo(
141
+ () => items.reduce(
142
+ ([refs2, disableArr2], item) => {
143
+ var _a;
144
+ return [refs2.concat(createRef()), disableArr2.concat((_a = item == null ? void 0 : item.props) == null ? void 0 : _a["data-disable-reorder"])];
145
+ },
146
+ [[], []]
147
+ ),
148
+ [items]
149
+ );
150
+ const findIndex = (key) => key ? items.findIndex((item) => (item == null ? void 0 : item.key) === key) : -1;
151
+ useEffect(() => {
152
+ if (!watchChildrenUpdates) return;
153
+ if (selected !== -1) handleDragEnd(null, selected, preserveOrder);
154
+ const items2 = [];
155
+ const newItems = [];
156
+ Children.forEach(children, (child, index) => {
157
+ if (preserveOrder) index = findIndex(child == null ? void 0 : child.key);
158
+ if (index === -1) newItems.push(child);
159
+ else items2[index] = child;
160
+ });
161
+ setItems(items2.filter((item) => item !== void 0).concat(newItems));
162
+ }, [children]);
163
+ useEffect(() => {
164
+ if (!scroll) return;
165
+ const { left, top } = scroll;
166
+ const { scrollWidth, scrollHeight } = document.body;
167
+ const interval = setInterval(() => {
168
+ if (left < 0 || top < 0 || scrollWidth - scrollX > innerWidth - left || scrollHeight - scrollY > innerHeight - top) scrollBy({ left, top, behavior: "instant" });
169
+ }, 20);
170
+ return () => clearInterval(interval);
171
+ }, [scroll]);
172
+ function handleDragEnd(event, end = selected, handlePositionChange = true) {
173
+ event == null ? void 0 : event.stopPropagation();
174
+ if (handlePositionChange && end !== start) onPositionChange == null ? void 0 : onPositionChange({ start, end, oldItems: temp.items, newItems: items, revert: () => setItems(temp.items) });
175
+ setStart(-1);
176
+ setSelected(-1);
177
+ }
178
+ return /* @__PURE__ */ React2.createElement("div", __spreadValues({ ref }, props), disabled ? children : /* @__PURE__ */ React2.createElement(Animation, { duration: +(start !== -1 && !scroll) && animationDuration }, items.map((child, i) => {
179
+ if (!isValidElement(child)) return child;
180
+ return /* @__PURE__ */ React2.createElement(
181
+ ReorderItem,
182
+ {
183
+ key: child.key,
184
+ ref: refs[i],
185
+ useOnlyIconToDrag,
186
+ disable: disableArr[i],
187
+ style: { opacity: selected === i ? selectedItemOpacity : 1 },
188
+ onDragStart: (event) => {
189
+ var _a, _b;
190
+ event.stopPropagation();
191
+ setStart(i);
192
+ setSelected(i);
193
+ setTemp({ items, rect: ((_b = (_a = ref.current.childNodes[i]).getBoundingClientRect) == null ? void 0 : _b.call(_a)) || {} });
194
+ },
195
+ onDragEnter: (event) => {
196
+ event.stopPropagation();
197
+ if (start === -1 || selected === i || isAnimating) return;
198
+ const { width: startWidth, height: startHeight } = temp.rect;
199
+ const { left, top, width, height } = event.target.getBoundingClientRect();
200
+ if (event.clientX - left > Math.min(startWidth, width) || event.clientY - top > Math.min(startHeight, height)) return;
201
+ setSelected(i);
202
+ setItems(() => {
203
+ const items2 = temp.items.slice();
204
+ const shiftForward = start < i;
205
+ const increment = shiftForward ? 1 : -1;
206
+ let key = start;
207
+ for (let index = start + increment; shiftForward ? index <= i : index >= i; index += increment) {
208
+ if (disableArr[index]) continue;
209
+ swap(items2, key, index);
210
+ key = index;
211
+ }
212
+ return items2;
213
+ });
214
+ setIsAnimating(true);
215
+ setTimeout(() => setIsAnimating(false), animationDuration);
216
+ },
217
+ onDragEnd: handleDragEnd,
218
+ onTouchMove: (event) => {
219
+ if (start === -1) return;
220
+ const { clientX, screenX, clientY, screenY } = event.touches[0];
221
+ let left = 0, top = 0;
222
+ if (clientX < scrollThreshold.x) left = -5;
223
+ else if (innerWidth - screenX < scrollThreshold.x) left = 5;
224
+ if (clientY < scrollThreshold.y) top = -10;
225
+ else if (innerHeight - screenY < scrollThreshold.y) top = 10;
226
+ setScroll(left || top ? { left, top } : void 0);
227
+ },
228
+ onTouchEnd: () => setScroll(void 0)
229
+ },
230
+ child
231
+ );
232
+ })));
233
+ }
234
+
235
+ export { ReorderIcon, ReorderList };
@@ -0,0 +1,7 @@
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, watchChildrenUpdates, preserveOrder, onPositionChange, disabled, props, children }: ReorderListProps): JSX.Element;
6
+
7
+ export { ReorderIcon, ReorderList as default };
@@ -0,0 +1 @@
1
+ export { ReorderIcon, ReorderList as default } from './chunks/chunk-6VGR3NNS.js';
package/dist/index.d.ts CHANGED
@@ -1,37 +1,3 @@
1
- import { CSSProperties, DetailedHTMLProps, DragEventHandler, HTMLAttributes, JSX, ReactNode, RefObject, TouchEventHandler } from "react";
2
- export type Props = DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>;
3
- export type PositionChangeHandler = (event: {
4
- start: number;
5
- end: number;
6
- oldItems: ReactNode[];
7
- newItems: ReactNode[];
8
- revert: Function;
9
- }) => void;
10
- export type ReorderListProps = {
11
- useOnlyIconToDrag?: boolean;
12
- selectedItemOpacity?: number;
13
- animationDuration?: number;
14
- watchChildrenUpdates?: boolean;
15
- preserveOrder?: boolean;
16
- onPositionChange?: PositionChangeHandler;
17
- disabled?: boolean;
18
- props?: Props;
19
- children?: ReactNode;
20
- };
21
- export type DivDragEventHandler = DragEventHandler<HTMLDivElement>;
22
- export type DivTouchEventHandler = TouchEventHandler<HTMLDivElement>;
23
- export type ReorderItemProps = {
24
- useOnlyIconToDrag: boolean;
25
- disable: boolean;
26
- ref: RefObject<HTMLDivElement | null>;
27
- style: CSSProperties;
28
- onDragStart?: DivDragEventHandler;
29
- onDragEnter: DivDragEventHandler;
30
- onDragEnd: DivDragEventHandler;
31
- onTouchMove: DivTouchEventHandler;
32
- onTouchEnd: DivTouchEventHandler;
33
- children: ReactNode;
34
- };
35
- export type { IconProps } from "./icons.js";
36
- export declare function ReorderIcon({ children, style, ...props }: Props): JSX.Element;
37
- export default function ReorderList({ useOnlyIconToDrag, selectedItemOpacity, animationDuration, watchChildrenUpdates, preserveOrder, onPositionChange, disabled, props, children }: ReorderListProps): JSX.Element;
1
+ export { ReorderIcon, default } from './components.js';
2
+ import 'react';
3
+ import './types.js';
package/dist/index.js CHANGED
@@ -1,140 +1 @@
1
- var __rest = (this && this.__rest) || function (s, e) {
2
- var t = {};
3
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
- t[p] = s[p];
5
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
- t[p[i]] = s[p[i]];
9
- }
10
- return t;
11
- };
12
- import React, { Children, cloneElement, createRef, isValidElement, useEffect, useMemo, useRef, useState } from "react";
13
- import Animation from "./animation.js";
14
- import { scrollThreshold } from "./constants.js";
15
- import { useDraggable } from "./hooks.js";
16
- import { PiDotsSixVerticalBold } from "./icons.js";
17
- import { swap } from "./utils.js";
18
- if (typeof window !== "undefined")
19
- import("drag-drop-touch");
20
- export function ReorderIcon(_a) {
21
- var { children = React.createElement(PiDotsSixVerticalBold, null), style } = _a, props = __rest(_a, ["children", "style"]);
22
- return (React.createElement("span", Object.assign({ style: Object.assign({ cursor: "grab" }, style) }, props), children));
23
- }
24
- function ReorderItem(_a) {
25
- var { useOnlyIconToDrag, disable, ref, style, children, onTouchEnd: propOnTouchEnd } = _a, events = __rest(_a, ["useOnlyIconToDrag", "disable", "ref", "style", "children", "onTouchEnd"]);
26
- const [draggable, _b] = useDraggable(), { onTouchEnd: draggableOnTouchEnd } = _b, draggableProps = __rest(_b, ["onTouchEnd"]);
27
- if (!draggable)
28
- events.onDragStart = undefined;
29
- const recursiveClone = (children) => Children.map(children, (child) => {
30
- if (!isValidElement(child))
31
- return child;
32
- return cloneElement(child, child.type === ReorderIcon ? draggableProps : {}, recursiveClone(child.props.children));
33
- });
34
- const recursiveChildren = useMemo(() => (useOnlyIconToDrag ? recursiveClone(children) : children), [useOnlyIconToDrag, children]);
35
- return (React.createElement("div", Object.assign({ ref: ref, draggable: !disable && draggable, style: Object.assign(Object.assign({}, style), { touchAction: "pan-y", cursor: useOnlyIconToDrag ? "default" : "grab" }) }, (!disable && Object.assign(Object.assign(Object.assign({}, events), (!useOnlyIconToDrag && draggableProps)), { onTouchEnd: (event) => {
36
- draggableOnTouchEnd();
37
- propOnTouchEnd(event);
38
- } }))), recursiveChildren));
39
- }
40
- export default function ReorderList({ useOnlyIconToDrag = false, selectedItemOpacity = 0.5, animationDuration = 400, watchChildrenUpdates = false, preserveOrder = false, onPositionChange, disabled = false, props, children }) {
41
- const ref = useRef(null);
42
- const [start, setStart] = useState(-1);
43
- const [selected, setSelected] = useState(-1);
44
- const [items, setItems] = useState(Children.toArray(children));
45
- const [temp, setTemp] = useState({ items: [] });
46
- const [isAnimating, setIsAnimating] = useState(false);
47
- const [scroll, setScroll] = useState();
48
- const [refs, disableArr] = useMemo(() => items.reduce(([refs, disableArr], item) => {
49
- var _a;
50
- return [refs.concat(createRef()), disableArr.concat((_a = item === null || item === void 0 ? void 0 : item.props) === null || _a === void 0 ? void 0 : _a["data-disable-reorder"])];
51
- }, [[], []]), [items]);
52
- const findIndex = (key) => (key ? items.findIndex((item) => { var _a; return ((_a = item === null || item === void 0 ? void 0 : item.key) === null || _a === void 0 ? void 0 : _a.split(".$").at(-1)) === key; }) : -1);
53
- useEffect(() => {
54
- if (!watchChildrenUpdates)
55
- return;
56
- if (selected !== -1)
57
- handleDragEnd(null, selected, preserveOrder);
58
- if (preserveOrder) {
59
- const items = [];
60
- const newItems = [];
61
- Children.forEach(children, (child) => {
62
- const index = findIndex(child === null || child === void 0 ? void 0 : child.key);
63
- if (index === -1)
64
- newItems.push(child);
65
- else
66
- items[index] = child;
67
- });
68
- setItems(items.filter((item) => item !== undefined).concat(newItems));
69
- }
70
- else
71
- setItems(Children.toArray(children));
72
- }, [children]);
73
- useEffect(() => {
74
- if (!scroll)
75
- return;
76
- const { left, top } = scroll;
77
- const { scrollWidth, scrollHeight } = document.body;
78
- const interval = setInterval(() => {
79
- if (left < 0 || top < 0 || scrollWidth - scrollX > innerWidth - left || scrollHeight - scrollY > innerHeight - top)
80
- scrollBy({ left, top, behavior: "instant" });
81
- }, 20);
82
- return () => clearInterval(interval);
83
- }, [scroll]);
84
- function handleDragEnd(event, end = selected, handlePositionChange = true) {
85
- event === null || event === void 0 ? void 0 : event.stopPropagation();
86
- if (handlePositionChange && end !== start)
87
- onPositionChange === null || onPositionChange === void 0 ? void 0 : onPositionChange({ start, end, oldItems: temp.items, newItems: items, revert: () => setItems(temp.items) });
88
- setStart(-1);
89
- setSelected(-1);
90
- }
91
- return (React.createElement("div", Object.assign({ ref: ref }, props), disabled ? (children) : (React.createElement(Animation, { duration: +(start !== -1 && !scroll) && animationDuration }, items.map((child, i) => {
92
- if (!isValidElement(child))
93
- return child;
94
- return (React.createElement(ReorderItem, { key: child.key, ref: refs[i], useOnlyIconToDrag: useOnlyIconToDrag, disable: disableArr[i], style: { opacity: selected === i ? selectedItemOpacity : 1 }, onDragStart: (event) => {
95
- var _a, _b;
96
- event.stopPropagation();
97
- setStart(i);
98
- setSelected(i);
99
- setTemp({ items, rect: ((_b = (_a = ref.current.childNodes[i]).getBoundingClientRect) === null || _b === void 0 ? void 0 : _b.call(_a)) || {} });
100
- }, onDragEnter: (event) => {
101
- event.stopPropagation();
102
- if (start === -1 || selected === i || isAnimating)
103
- return;
104
- const { width: startWidth, height: startHeight } = temp.rect;
105
- const { left, top, width, height } = event.target.getBoundingClientRect();
106
- if (event.clientX - left > Math.min(startWidth, width) || event.clientY - top > Math.min(startHeight, height))
107
- return;
108
- setSelected(i);
109
- setItems(() => {
110
- const items = temp.items.slice();
111
- const shiftForward = start < i;
112
- const increment = shiftForward ? 1 : -1;
113
- let key = start;
114
- for (let index = start + increment; shiftForward ? index <= i : index >= i; index += increment) {
115
- if (disableArr[index])
116
- continue;
117
- swap(items, key, index);
118
- key = index;
119
- }
120
- return items;
121
- });
122
- setIsAnimating(true);
123
- setTimeout(() => setIsAnimating(false), animationDuration);
124
- }, onDragEnd: handleDragEnd, onTouchMove: (event) => {
125
- if (start === -1)
126
- return;
127
- const { clientX, screenX, clientY, screenY } = event.touches[0];
128
- let left = 0, top = 0;
129
- if (clientX < scrollThreshold.x)
130
- left = -5;
131
- else if (innerWidth - screenX < scrollThreshold.x)
132
- left = 5;
133
- if (clientY < scrollThreshold.y)
134
- top = -10;
135
- else if (innerHeight - screenY < scrollThreshold.y)
136
- top = 10;
137
- setScroll(left || top ? { left, top } : undefined);
138
- }, onTouchEnd: () => setScroll(undefined) }, child));
139
- })))));
140
- }
1
+ export { ReorderIcon, ReorderList as default } from './chunks/chunk-6VGR3NNS.js';
@@ -0,0 +1,49 @@
1
+ import { ReactNode, DetailedHTMLProps, HTMLAttributes, ReactElement, RefObject, DragEventHandler, MouseEventHandler, TouchEventHandler, CSSProperties } from 'react';
2
+
3
+ type BoundingBox = {
4
+ [key: string]: DOMRect;
5
+ };
6
+ type Child = ReactElement<{
7
+ ref: RefObject<HTMLElement>;
8
+ }>;
9
+ type AnimationProps = {
10
+ duration: number;
11
+ children: ReactNode;
12
+ };
13
+ type IconProps = React.DetailedHTMLProps<React.HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>;
14
+ type DivDragEventHandler = DragEventHandler<HTMLDivElement>;
15
+ type DivMouseEventHandler = MouseEventHandler<HTMLDivElement>;
16
+ type DivProps = DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>;
17
+ type DivTouchEventHandler = TouchEventHandler<HTMLDivElement>;
18
+ type PositionChangeHandler = (event: {
19
+ start: number;
20
+ end: number;
21
+ oldItems: ReactNode[];
22
+ newItems: ReactNode[];
23
+ revert: Function;
24
+ }) => void;
25
+ type ReorderItemProps = {
26
+ useOnlyIconToDrag: boolean;
27
+ disable: boolean;
28
+ ref: RefObject<HTMLDivElement | null>;
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
+ watchChildrenUpdates?: boolean;
42
+ preserveOrder?: boolean;
43
+ onPositionChange?: PositionChangeHandler;
44
+ disabled?: boolean;
45
+ props?: DivProps;
46
+ children?: ReactNode;
47
+ };
48
+
49
+ export type { AnimationProps, BoundingBox, Child, DivDragEventHandler, DivMouseEventHandler, DivProps, DivTouchEventHandler, IconProps, PositionChangeHandler, ReorderItemProps, ReorderListProps };
package/dist/types.js ADDED
@@ -0,0 +1 @@
1
+
package/package.json CHANGED
@@ -1,41 +1,60 @@
1
1
  {
2
2
  "name": "react-reorder-list",
3
- "version": "0.8.4",
3
+ "version": "0.8.6",
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
- "type": "module",
6
- "main": "dist/index.js",
7
- "types": "dist/index.d.ts",
5
+ "license": "MIT",
6
+ "author": "Sahil Aggarwal <aggarwalsahil2004@gmail.com>",
7
+ "contributors": [],
8
+ "homepage": "https://github.com/SahilAggarwal2004/react-reorder-list#readme",
8
9
  "repository": {
9
10
  "type": "git",
10
11
  "url": "git+https://github.com/SahilAggarwal2004/react-reorder-list.git"
11
12
  },
12
- "keywords": [
13
- "react-reorder-list",
14
- "react",
15
- "reorder",
16
- "list",
17
- "component",
18
- "drag-and-drop",
19
- "dnd",
20
- "typescript"
21
- ],
22
- "author": "Sahil Aggarwal",
23
- "license": "MIT",
24
13
  "bugs": {
25
14
  "url": "https://github.com/SahilAggarwal2004/react-reorder-list/issues"
26
15
  },
27
- "homepage": "https://github.com/SahilAggarwal2004/react-reorder-list#readme",
16
+ "type": "module",
17
+ "exports": {
18
+ ".": "./dist/index.js",
19
+ "./types": "./dist/types.js"
20
+ },
21
+ "main": "dist/index.js",
22
+ "files": [
23
+ "dist"
24
+ ],
25
+ "sideEffects": true,
26
+ "types": "dist/index.d.ts",
27
+ "dependencies": {
28
+ "drag-drop-touch": "^1.3.1"
29
+ },
28
30
  "peerDependencies": {
29
31
  "react": "^19.0.0"
30
32
  },
31
33
  "devDependencies": {
32
- "@types/react": "^19.1.3",
33
- "typescript": "^5.8.3"
34
- },
35
- "dependencies": {
36
- "drag-drop-touch": "^1.3.1"
34
+ "@release-it/conventional-changelog": "^10.0.4",
35
+ "@types/react": "^19.2.7",
36
+ "prettier-package-json": "^2.8.0",
37
+ "release-it": "^19.2.2",
38
+ "tsup": "^8.5.1",
39
+ "typescript": "^5.9.3"
37
40
  },
41
+ "keywords": [
42
+ "component",
43
+ "dnd",
44
+ "drag-and-drop",
45
+ "list",
46
+ "react",
47
+ "react-reorder-list",
48
+ "reorder",
49
+ "typescript"
50
+ ],
38
51
  "scripts": {
39
- "build": "pnpm i && tsc"
52
+ "build": "pnpm i && pnpm run compile",
53
+ "compile": "tsup",
54
+ "dev": "tsup --watch",
55
+ "dry-release": "release-it --ci --dry-run",
56
+ "prettier": "prettier-package-json --write package.json",
57
+ "pub": "pnpm login && pnpm publish",
58
+ "release": "release-it --ci"
40
59
  }
41
60
  }
@@ -1,7 +0,0 @@
1
- import { ReactNode } from "react";
2
- type AnimationProps = {
3
- duration: number;
4
- children: ReactNode;
5
- };
6
- export default function Animation({ duration, children }: AnimationProps): ReactNode;
7
- export {};
package/dist/animation.js DELETED
@@ -1,43 +0,0 @@
1
- import { useLayoutEffect, Children } from "react";
2
- import { useStateWithHistory } from "./hooks.js";
3
- import { getKey } from "./utils.js";
4
- function calculateBoundingBoxes(children) {
5
- const boundingBoxes = {};
6
- Children.forEach(children, (child) => {
7
- const key = getKey(child);
8
- if (key)
9
- boundingBoxes[key] = child.props.ref.current.getBoundingClientRect();
10
- });
11
- return boundingBoxes;
12
- }
13
- export default function Animation({ duration, children }) {
14
- const [boundingBox, prevBoundingBox, setBoundingBox] = useStateWithHistory({});
15
- useLayoutEffect(() => {
16
- if (duration > 0)
17
- setBoundingBox(calculateBoundingBoxes(children));
18
- else
19
- setBoundingBox({});
20
- }, [children]);
21
- useLayoutEffect(() => {
22
- if (duration > 0 && prevBoundingBox && Object.keys(prevBoundingBox).length)
23
- Children.forEach(children, (child) => {
24
- const key = getKey(child);
25
- if (!key)
26
- return;
27
- const domNode = child.props.ref.current;
28
- const { left: prevLeft, top: prevTop } = prevBoundingBox[key] || {};
29
- const { left, top } = boundingBox[key];
30
- const changeInX = prevLeft - left, changeInY = prevTop - top;
31
- if (changeInX || changeInY)
32
- requestAnimationFrame(() => {
33
- domNode.style.transform = `translate(${changeInX}px, ${changeInY}px)`;
34
- domNode.style.transition = "none";
35
- requestAnimationFrame(() => {
36
- domNode.style.transform = "";
37
- domNode.style.transition = `transform ${duration}ms`;
38
- });
39
- });
40
- });
41
- }, [boundingBox]);
42
- return children;
43
- }
@@ -1,4 +0,0 @@
1
- export declare const scrollThreshold: {
2
- x: number;
3
- y: number;
4
- };
package/dist/constants.js DELETED
@@ -1 +0,0 @@
1
- export const scrollThreshold = { x: 10, y: 100 };
package/dist/hooks.d.ts DELETED
@@ -1,7 +0,0 @@
1
- export declare function useDraggable(initValue?: boolean): readonly [boolean, {
2
- onMouseEnter: () => void;
3
- onMouseLeave: () => void;
4
- onTouchStart: () => void;
5
- onTouchEnd: () => void;
6
- }];
7
- export declare function useStateWithHistory<T>(initValue: T): readonly [T, T | undefined, (value: T) => void];
package/dist/hooks.js DELETED
@@ -1,17 +0,0 @@
1
- import { useState } from "react";
2
- export function useDraggable(initValue = false) {
3
- const [draggable, setDraggable] = useState(initValue);
4
- const enableDragging = () => setDraggable(true);
5
- const disableDragging = () => setDraggable(false);
6
- const draggableProps = { onMouseEnter: enableDragging, onMouseLeave: disableDragging, onTouchStart: enableDragging, onTouchEnd: disableDragging };
7
- return [draggable, draggableProps];
8
- }
9
- export function useStateWithHistory(initValue) {
10
- const [state, setState] = useState(initValue);
11
- const [prevState, setPrevState] = useState();
12
- function setStateWithHistory(value) {
13
- setPrevState(state);
14
- setState(value);
15
- }
16
- return [state, prevState, setStateWithHistory];
17
- }
package/dist/icons.d.ts DELETED
@@ -1,3 +0,0 @@
1
- import React from "react";
2
- export type IconProps = React.DetailedHTMLProps<React.HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>;
3
- export declare function PiDotsSixVerticalBold(props: IconProps): React.JSX.Element;
package/dist/icons.js DELETED
@@ -1,6 +0,0 @@
1
- import React from "react";
2
- export function PiDotsSixVerticalBold(props) {
3
- return (React.createElement("span", Object.assign({}, props),
4
- React.createElement("svg", { viewBox: "0 0 256 256", fill: "currentColor", width: "1.25rem", height: "1.25rem" },
5
- 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" }))));
6
- }
package/dist/utils.d.ts DELETED
@@ -1,3 +0,0 @@
1
- import { ReactNode } from "react";
2
- export declare const getKey: (child: ReactNode) => string | undefined;
3
- export declare function swap(array: any[], i: number, j: number): void;
package/dist/utils.js DELETED
@@ -1,6 +0,0 @@
1
- export const getKey = (child) => { var _a; return (_a = child === null || child === void 0 ? void 0 : child.key) === null || _a === void 0 ? void 0 : _a.split("/.")[0]; };
2
- export function swap(array, i, j) {
3
- const temp = array[i];
4
- array[i] = array[j];
5
- array[j] = temp;
6
- }