react-native-reanimated-dnd 1.0.1

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.
Files changed (37) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +633 -0
  3. package/lib/components/Draggable.d.ts +5 -0
  4. package/lib/components/Draggable.js +265 -0
  5. package/lib/components/Droppable.d.ts +264 -0
  6. package/lib/components/Droppable.js +284 -0
  7. package/lib/components/Sortable.d.ts +184 -0
  8. package/lib/components/Sortable.js +225 -0
  9. package/lib/components/SortableItem.d.ts +158 -0
  10. package/lib/components/SortableItem.js +251 -0
  11. package/lib/components/sortableUtils.d.ts +21 -0
  12. package/lib/components/sortableUtils.js +50 -0
  13. package/lib/context/DropContext.d.ts +118 -0
  14. package/lib/context/DropContext.js +233 -0
  15. package/lib/hooks/index.d.ts +4 -0
  16. package/lib/hooks/index.js +5 -0
  17. package/lib/hooks/useDraggable.d.ts +101 -0
  18. package/lib/hooks/useDraggable.js +567 -0
  19. package/lib/hooks/useDroppable.d.ts +129 -0
  20. package/lib/hooks/useDroppable.js +261 -0
  21. package/lib/hooks/useSortable.d.ts +174 -0
  22. package/lib/hooks/useSortable.js +361 -0
  23. package/lib/hooks/useSortableList.d.ts +182 -0
  24. package/lib/hooks/useSortableList.js +211 -0
  25. package/lib/index.d.ts +11 -0
  26. package/lib/index.js +16 -0
  27. package/lib/types/context.d.ts +166 -0
  28. package/lib/types/context.js +80 -0
  29. package/lib/types/draggable.d.ts +313 -0
  30. package/lib/types/draggable.js +31 -0
  31. package/lib/types/droppable.d.ts +197 -0
  32. package/lib/types/droppable.js +1 -0
  33. package/lib/types/index.d.ts +4 -0
  34. package/lib/types/index.js +8 -0
  35. package/lib/types/sortable.d.ts +432 -0
  36. package/lib/types/sortable.js +6 -0
  37. package/package.json +59 -0
@@ -0,0 +1,432 @@
1
+ import { StyleProp, ViewStyle } from "react-native";
2
+ import { SharedValue } from "react-native-reanimated";
3
+ import { DropProviderRef } from "../types/context";
4
+ import { ReactNode } from "react";
5
+ export declare enum ScrollDirection {
6
+ None = "none",
7
+ Up = "up",
8
+ Down = "down"
9
+ }
10
+ /**
11
+ * Configuration options for the useSortable hook.
12
+ *
13
+ * @template T - The type of data associated with the sortable item
14
+ */
15
+ export interface UseSortableOptions<T> {
16
+ /**
17
+ * Unique identifier for this sortable item. Must be unique within the sortable list.
18
+ * Used for tracking position changes and managing reordering logic.
19
+ *
20
+ * @example
21
+ * ```typescript
22
+ * const itemId = `task-${task.id}`;
23
+ * ```
24
+ */
25
+ id: string;
26
+ /**
27
+ * Shared value containing the current positions of all items in the sortable list.
28
+ * This is typically managed by the parent sortable list component.
29
+ *
30
+ * @example
31
+ * ```typescript
32
+ * // Managed by useSortableList hook
33
+ * const positions = useSharedValue({
34
+ * 'item-1': 0,
35
+ * 'item-2': 1,
36
+ * 'item-3': 2
37
+ * });
38
+ * ```
39
+ */
40
+ positions: SharedValue<{
41
+ [id: string]: number;
42
+ }>;
43
+ /**
44
+ * Shared value representing the current scroll position (lower bound) of the container.
45
+ * Used for auto-scrolling during drag operations.
46
+ */
47
+ lowerBound: SharedValue<number>;
48
+ /**
49
+ * Shared value indicating the current auto-scroll direction.
50
+ * Used to trigger automatic scrolling when dragging near container edges.
51
+ */
52
+ autoScrollDirection: SharedValue<ScrollDirection>;
53
+ /**
54
+ * Total number of items in the sortable list.
55
+ * Used for boundary calculations and position validation.
56
+ */
57
+ itemsCount: number;
58
+ /**
59
+ * Height of each item in pixels. All items must have the same height.
60
+ * Used for position calculations and auto-scrolling.
61
+ *
62
+ * @example
63
+ * ```typescript
64
+ * const ITEM_HEIGHT = 60; // 60px per item
65
+ * ```
66
+ */
67
+ itemHeight: number;
68
+ /**
69
+ * Height of the scrollable container in pixels.
70
+ * Used for auto-scroll calculations and determining scroll boundaries.
71
+ *
72
+ * @default 500
73
+ */
74
+ containerHeight?: number;
75
+ /**
76
+ * Callback fired when an item's position changes within the list.
77
+ * This is called for both the moved item and any items that were displaced.
78
+ *
79
+ * @param id - The ID of the item that moved
80
+ * @param from - The previous position index
81
+ * @param to - The new position index
82
+ *
83
+ * @example
84
+ * ```typescript
85
+ * const handleMove = (id: string, from: number, to: number) => {
86
+ * console.log(`Item ${id} moved from position ${from} to ${to}`);
87
+ * // Update your data model
88
+ * reorderItems(id, from, to);
89
+ * };
90
+ * ```
91
+ */
92
+ onMove?: (id: string, from: number, to: number) => void;
93
+ /**
94
+ * Callback fired when dragging starts for this item.
95
+ *
96
+ * @param id - The ID of the item being dragged
97
+ * @param position - The current position index of the item
98
+ *
99
+ * @example
100
+ * ```typescript
101
+ * const handleDragStart = (id: string, position: number) => {
102
+ * console.log(`Started dragging item ${id} from position ${position}`);
103
+ * setDraggingItem(id);
104
+ * hapticFeedback();
105
+ * };
106
+ * ```
107
+ */
108
+ onDragStart?: (id: string, position: number) => void;
109
+ /**
110
+ * Callback fired when dragging ends for this item.
111
+ *
112
+ * @param id - The ID of the item that was being dragged
113
+ * @param position - The final position index of the item
114
+ *
115
+ * @example
116
+ * ```typescript
117
+ * const handleDrop = (id: string, position: number) => {
118
+ * console.log(`Dropped item ${id} at position ${position}`);
119
+ * setDraggingItem(null);
120
+ * saveNewOrder();
121
+ * };
122
+ * ```
123
+ */
124
+ onDrop?: (id: string, position: number) => void;
125
+ /**
126
+ * Callback fired continuously while dragging, providing real-time position updates.
127
+ * Useful for showing visual feedback or updating UI during drag operations.
128
+ *
129
+ * @param id - The ID of the item being dragged
130
+ * @param overItemId - The ID of the item currently being hovered over (null if none)
131
+ * @param yPosition - The current Y position of the dragged item
132
+ *
133
+ * @example
134
+ * ```typescript
135
+ * const handleDragging = (id: string, overItemId: string | null, yPosition: number) => {
136
+ * if (overItemId) {
137
+ * console.log(`Item ${id} is hovering over ${overItemId}`);
138
+ * setHoverTarget(overItemId);
139
+ * } else {
140
+ * setHoverTarget(null);
141
+ * }
142
+ * };
143
+ * ```
144
+ */
145
+ onDragging?: (id: string, overItemId: string | null, yPosition: number) => void;
146
+ /**
147
+ * Children elements - used internally for handle detection.
148
+ * @internal
149
+ */
150
+ children?: React.ReactNode;
151
+ /**
152
+ * Handle component type - used internally for handle detection.
153
+ * @internal
154
+ */
155
+ handleComponent?: React.ComponentType<any>;
156
+ }
157
+ /**
158
+ * Return value from the useSortable hook.
159
+ */
160
+ export interface UseSortableReturn {
161
+ /**
162
+ * Animated style to apply to the sortable item.
163
+ * Contains position transforms and visual effects for dragging state.
164
+ */
165
+ animatedStyle: StyleProp<ViewStyle>;
166
+ /**
167
+ * Pan gesture handler for drag interactions.
168
+ * Attach this to a PanGestureHandler to enable dragging.
169
+ */
170
+ panGestureHandler: any;
171
+ /**
172
+ * Whether this item is currently being moved/dragged.
173
+ * Useful for conditional styling or behavior.
174
+ */
175
+ isMoving: boolean;
176
+ /**
177
+ * Whether this sortable item has a handle component.
178
+ * When true, only the handle can initiate dragging.
179
+ * When false, the entire item is draggable.
180
+ */
181
+ hasHandle: boolean;
182
+ }
183
+ /**
184
+ * Configuration options for the useSortableList hook.
185
+ *
186
+ * @template TData - The type of data items in the sortable list
187
+ */
188
+ export interface UseSortableListOptions<TData> {
189
+ /**
190
+ * Array of data items to be rendered as sortable list items.
191
+ * Each item must have an `id` property for tracking.
192
+ *
193
+ * @example
194
+ * ```typescript
195
+ * const tasks = [
196
+ * { id: '1', title: 'Task 1', completed: false },
197
+ * { id: '2', title: 'Task 2', completed: true },
198
+ * { id: '3', title: 'Task 3', completed: false }
199
+ * ];
200
+ * ```
201
+ */
202
+ data: TData[];
203
+ /**
204
+ * Height of each item in pixels. All items must have the same height
205
+ * for proper position calculations and smooth animations.
206
+ *
207
+ * @example
208
+ * ```typescript
209
+ * const ITEM_HEIGHT = 80; // Each list item is 80px tall
210
+ * ```
211
+ */
212
+ itemHeight: number;
213
+ /**
214
+ * Function to extract a unique key from each data item.
215
+ * If not provided, defaults to using the `id` property.
216
+ *
217
+ * @param item - The data item
218
+ * @param index - The index of the item in the array
219
+ * @returns Unique string identifier for the item
220
+ *
221
+ * @default (item) => item.id
222
+ *
223
+ * @example
224
+ * ```typescript
225
+ * // Custom key extractor for items without id property
226
+ * const keyExtractor = (item, index) => `${item.type}-${item.name}-${index}`;
227
+ *
228
+ * // Using a compound key
229
+ * const keyExtractor = (item) => `${item.category}_${item.id}`;
230
+ * ```
231
+ */
232
+ itemKeyExtractor?: (item: TData, index: number) => string;
233
+ }
234
+ /**
235
+ * Return value from the useSortableList hook.
236
+ *
237
+ * @template TData - The type of data items in the sortable list
238
+ */
239
+ export interface UseSortableListReturn<TData> {
240
+ /**
241
+ * Shared value containing the current positions of all items.
242
+ * Maps item IDs to their current position indices.
243
+ *
244
+ * @example
245
+ * ```typescript
246
+ * // positions.value might look like:
247
+ * {
248
+ * 'item-1': 0,
249
+ * 'item-2': 1,
250
+ * 'item-3': 2
251
+ * }
252
+ * ```
253
+ */
254
+ positions: any;
255
+ /**
256
+ * Shared value tracking the current scroll position.
257
+ * Used for auto-scrolling during drag operations.
258
+ */
259
+ scrollY: any;
260
+ /**
261
+ * Shared value indicating the current auto-scroll direction.
262
+ * Used to trigger automatic scrolling when dragging near edges.
263
+ */
264
+ autoScroll: any;
265
+ /**
266
+ * Animated ref for the scroll view component.
267
+ * Used for programmatic scrolling during drag operations.
268
+ */
269
+ scrollViewRef: any;
270
+ /**
271
+ * Ref for the drop provider context.
272
+ * Used for triggering position updates after scroll events.
273
+ */
274
+ dropProviderRef: React.RefObject<DropProviderRef>;
275
+ /**
276
+ * Animated scroll handler to attach to the ScrollView.
277
+ * Tracks scroll position for auto-scroll calculations.
278
+ */
279
+ handleScroll: any;
280
+ /**
281
+ * Callback to call when scrolling ends.
282
+ * Triggers position recalculation for accurate drop zone detection.
283
+ */
284
+ handleScrollEnd: () => void;
285
+ /**
286
+ * Total height of the scrollable content.
287
+ * Calculated as `data.length * itemHeight`.
288
+ */
289
+ contentHeight: number;
290
+ /**
291
+ * Helper function to get props for individual sortable items.
292
+ *
293
+ * @param item - The data item
294
+ * @param index - The index of the item in the array
295
+ * @returns Props object to pass to the sortable item component
296
+ *
297
+ * @example
298
+ * ```typescript
299
+ * {data.map((item, index) => {
300
+ * const itemProps = getItemProps(item, index);
301
+ * return (
302
+ * <SortableItem key={itemProps.id} {...itemProps}>
303
+ * <Text>{item.title}</Text>
304
+ * </SortableItem>
305
+ * );
306
+ * })}
307
+ * ```
308
+ */
309
+ getItemProps: (item: TData, index: number) => {
310
+ /** Unique identifier for the item */
311
+ id: string;
312
+ /** Shared positions object */
313
+ positions: any;
314
+ /** Shared scroll position */
315
+ lowerBound: any;
316
+ /** Shared auto-scroll direction */
317
+ autoScrollDirection: any;
318
+ /** Total number of items */
319
+ itemsCount: number;
320
+ /** Height of each item */
321
+ itemHeight: number;
322
+ };
323
+ }
324
+ /**
325
+ * Props interface for the SortableItem component.
326
+ *
327
+ * @template T - The type of data associated with the sortable item
328
+ *
329
+ * @see {@link SortableItem} for component usage
330
+ * @see {@link useSortable} for the underlying hook
331
+ * @see {@link UseSortableOptions} for hook configuration options
332
+ * @see {@link UseSortableReturn} for hook return details
333
+ */
334
+ export interface SortableItemProps<T> {
335
+ /** Unique identifier for this sortable item */
336
+ id: string;
337
+ /** Data associated with this sortable item */
338
+ data: T;
339
+ /** Shared value containing positions of all items in the list */
340
+ positions: SharedValue<{
341
+ [id: string]: number;
342
+ }>;
343
+ /** Shared value representing the current scroll position */
344
+ lowerBound: SharedValue<number>;
345
+ /** Shared value indicating the current auto-scroll direction */
346
+ autoScrollDirection: SharedValue<ScrollDirection>;
347
+ /** Total number of items in the sortable list */
348
+ itemsCount: number;
349
+ /** Height of each item in pixels */
350
+ itemHeight: number;
351
+ /** Height of the scrollable container (optional) */
352
+ containerHeight?: number;
353
+ /** Child components to render inside the sortable item */
354
+ children: ReactNode;
355
+ /** Style to apply to the item container */
356
+ style?: StyleProp<ViewStyle>;
357
+ /** Additional animated style to apply */
358
+ animatedStyle?: StyleProp<ViewStyle>;
359
+ /** Callback fired when item position changes */
360
+ onMove?: (id: string, from: number, to: number) => void;
361
+ /** Callback fired when dragging starts */
362
+ onDragStart?: (id: string, position: number) => void;
363
+ /** Callback fired when dragging ends */
364
+ onDrop?: (id: string, position: number) => void;
365
+ /** Callback fired during dragging with position updates */
366
+ onDragging?: (id: string, overItemId: string | null, yPosition: number) => void;
367
+ }
368
+ /**
369
+ * Props interface for the Sortable component.
370
+ *
371
+ * @template TData - The type of data items in the sortable list
372
+ *
373
+ * @see {@link Sortable} for component usage
374
+ * @see {@link useSortableList} for the underlying hook
375
+ * @see {@link UseSortableListOptions} for hook configuration options
376
+ * @see {@link UseSortableListReturn} for hook return details
377
+ */
378
+ export interface SortableProps<TData> {
379
+ /** Array of data items to render as sortable list */
380
+ data: TData[];
381
+ /** Function to render each sortable item */
382
+ renderItem: (props: SortableRenderItemProps<TData>) => ReactNode;
383
+ /** Height of each item in pixels */
384
+ itemHeight: number;
385
+ /** Style to apply to the scroll view */
386
+ style?: StyleProp<ViewStyle>;
387
+ /** Style to apply to the scroll view content container */
388
+ contentContainerStyle?: StyleProp<ViewStyle>;
389
+ /** Function to extract unique key from each item */
390
+ itemKeyExtractor?: (item: TData, index: number) => string;
391
+ }
392
+ /**
393
+ * Props passed to the renderItem function in Sortable component.
394
+ *
395
+ * @template TData - The type of data item being rendered
396
+ *
397
+ * @see {@link SortableProps} for usage
398
+ * @see {@link Sortable} for component usage
399
+ * @see {@link SortableItem} for individual item component
400
+ */
401
+ export interface SortableRenderItemProps<TData> {
402
+ /** The data item being rendered */
403
+ item: TData;
404
+ /** Index of the item in the original data array */
405
+ index: number;
406
+ /** Unique identifier for this item */
407
+ id: string;
408
+ /** Shared value containing positions of all items */
409
+ positions: SharedValue<{
410
+ [id: string]: number;
411
+ }>;
412
+ /** Shared value representing the current scroll position */
413
+ lowerBound: SharedValue<number>;
414
+ /** Shared value indicating the current auto-scroll direction */
415
+ autoScrollDirection: SharedValue<ScrollDirection>;
416
+ /** Total number of items in the list */
417
+ itemsCount: number;
418
+ /** Height of each item in pixels */
419
+ itemHeight: number;
420
+ }
421
+ export interface SortableContextValue {
422
+ panGestureHandler: any;
423
+ }
424
+ /**
425
+ * Props for the SortableHandle component.
426
+ */
427
+ export interface SortableHandleProps {
428
+ /** The content to render inside the handle */
429
+ children: React.ReactNode;
430
+ /** Optional style to apply to the handle */
431
+ style?: StyleProp<ViewStyle>;
432
+ }
@@ -0,0 +1,6 @@
1
+ export var ScrollDirection;
2
+ (function (ScrollDirection) {
3
+ ScrollDirection["None"] = "none";
4
+ ScrollDirection["Up"] = "up";
5
+ ScrollDirection["Down"] = "down";
6
+ })(ScrollDirection || (ScrollDirection = {}));
package/package.json ADDED
@@ -0,0 +1,59 @@
1
+ {
2
+ "name": "react-native-reanimated-dnd",
3
+ "version": "1.0.1",
4
+ "description": "A powerful drag-and-drop library for React Native using Reanimated 3",
5
+ "main": "lib/index.js",
6
+ "module": "lib/index.js",
7
+ "types": "lib/index.d.ts",
8
+ "type": "module",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./lib/index.d.ts",
12
+ "import": "./lib/index.js",
13
+ "default": "./lib/index.js"
14
+ }
15
+ },
16
+ "sideEffects": false,
17
+ "scripts": {
18
+ "build": "tsc",
19
+ "type-check": "tsc --noEmit",
20
+ "format": "prettier --write \"**/*.{js,jsx,ts,tsx,json,md,yml,yaml}\" --ignore-path .prettierignore",
21
+ "format:check": "prettier --check \"**/*.{js,jsx,ts,tsx,json,md,yml,yaml}\" --ignore-path .prettierignore"
22
+ },
23
+ "keywords": [
24
+ "react-native",
25
+ "drag-and-drop",
26
+ "reanimated",
27
+ "sortable",
28
+ "dnd",
29
+ "gesture-handler"
30
+ ],
31
+ "author": "Vishesh Raheja <github.com/entropyconquers>",
32
+ "license": "MIT",
33
+ "repository": {
34
+ "type": "git",
35
+ "url": "git+https://github.com/entropyconquers/react-native-reanimated-dnd.git"
36
+ },
37
+ "peerDependencies": {
38
+ "react": ">=16.8.0",
39
+ "react-native": ">=0.60.0",
40
+ "react-native-reanimated": ">=3.0.0",
41
+ "react-native-gesture-handler": ">=2.0.0"
42
+ },
43
+ "devDependencies": {
44
+ "@types/react": "^18.2.0",
45
+ "@types/react-native": "^0.72.0",
46
+ "@types/node": "^20.0.0",
47
+ "typescript": "^5.0.0",
48
+ "react": "^18.2.0",
49
+ "react-native": "^0.72.0",
50
+ "react-native-reanimated": "^3.5.0",
51
+ "react-native-gesture-handler": "^2.13.0",
52
+ "prettier": "^3.5.3"
53
+ },
54
+ "files": [
55
+ "lib/",
56
+ "README.md",
57
+ "LICENSE"
58
+ ]
59
+ }