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,158 @@
1
+ import React from "react";
2
+ import { SortableItemProps, SortableHandleProps } from "../types/sortable";
3
+ /**
4
+ * A component for individual items within a sortable list.
5
+ *
6
+ * SortableItem provides the drag-and-drop functionality for individual list items,
7
+ * handling gesture recognition, position animations, and reordering logic.
8
+ * It can be used with or without drag handles for different interaction patterns.
9
+ *
10
+ * @template T - The type of data associated with this sortable item
11
+ * @param props - Configuration props for the sortable item
12
+ *
13
+ * @example
14
+ * Basic sortable item (entire item is draggable):
15
+ * ```typescript
16
+ * import { SortableItem } from './components/SortableItem';
17
+ *
18
+ * function TaskItem({ task, positions, ...sortableProps }) {
19
+ * return (
20
+ * <SortableItem
21
+ * id={task.id}
22
+ * data={task}
23
+ * positions={positions}
24
+ * {...sortableProps}
25
+ * onMove={(id, from, to) => {
26
+ * console.log(`Task ${id} moved from ${from} to ${to}`);
27
+ * reorderTasks(id, from, to);
28
+ * }}
29
+ * >
30
+ * <View style={styles.taskContainer}>
31
+ * <Text style={styles.taskTitle}>{task.title}</Text>
32
+ * <Text style={styles.taskStatus}>{task.completed ? 'Done' : 'Pending'}</Text>
33
+ * </View>
34
+ * </SortableItem>
35
+ * );
36
+ * }
37
+ * ```
38
+ *
39
+ * @example
40
+ * Sortable item with drag handle:
41
+ * ```typescript
42
+ * function TaskItemWithHandle({ task, positions, ...sortableProps }) {
43
+ * return (
44
+ * <SortableItem
45
+ * id={task.id}
46
+ * data={task}
47
+ * positions={positions}
48
+ * {...sortableProps}
49
+ * >
50
+ * <View style={styles.taskContainer}>
51
+ * <View style={styles.taskContent}>
52
+ * <Text style={styles.taskTitle}>{task.title}</Text>
53
+ * <Text style={styles.taskDescription}>{task.description}</Text>
54
+ * </View>
55
+ *
56
+ * {/* Only this handle can initiate dragging *\/}
57
+ * <SortableItem.Handle style={styles.dragHandle}>
58
+ * <View style={styles.handleIcon}>
59
+ * <View style={styles.handleLine} />
60
+ * <View style={styles.handleLine} />
61
+ * <View style={styles.handleLine} />
62
+ * </View>
63
+ * </SortableItem.Handle>
64
+ * </View>
65
+ * </SortableItem>
66
+ * );
67
+ * }
68
+ * ```
69
+ *
70
+ * @example
71
+ * Sortable item with callbacks and state tracking:
72
+ * ```typescript
73
+ * function AdvancedTaskItem({ task, positions, ...sortableProps }) {
74
+ * const [isDragging, setIsDragging] = useState(false);
75
+ *
76
+ * return (
77
+ * <SortableItem
78
+ * id={task.id}
79
+ * data={task}
80
+ * positions={positions}
81
+ * {...sortableProps}
82
+ * onDragStart={(id, position) => {
83
+ * setIsDragging(true);
84
+ * hapticFeedback();
85
+ * analytics.track('drag_start', { taskId: id, position });
86
+ * }}
87
+ * onDrop={(id, position) => {
88
+ * setIsDragging(false);
89
+ * analytics.track('drag_end', { taskId: id, position });
90
+ * }}
91
+ * onDragging={(id, overItemId, yPosition) => {
92
+ * if (overItemId) {
93
+ * // Show visual feedback for item being hovered over
94
+ * highlightItem(overItemId);
95
+ * }
96
+ * }}
97
+ * style={[
98
+ * styles.taskItem,
99
+ * isDragging && styles.draggingItem
100
+ * ]}
101
+ * >
102
+ * <View style={styles.taskContent}>
103
+ * <Text style={styles.taskTitle}>{task.title}</Text>
104
+ * <Text style={styles.taskPriority}>Priority: {task.priority}</Text>
105
+ * {isDragging && (
106
+ * <Text style={styles.dragIndicator}>Dragging...</Text>
107
+ * )}
108
+ * </View>
109
+ * </SortableItem>
110
+ * );
111
+ * }
112
+ * ```
113
+ *
114
+ * @example
115
+ * Sortable item with custom animations:
116
+ * ```typescript
117
+ * function AnimatedTaskItem({ task, positions, ...sortableProps }) {
118
+ * return (
119
+ * <SortableItem
120
+ * id={task.id}
121
+ * data={task}
122
+ * positions={positions}
123
+ * {...sortableProps}
124
+ * animatedStyle={{
125
+ * // Custom animated styles can be applied here
126
+ * shadowOpacity: 0.3,
127
+ * shadowRadius: 10,
128
+ * shadowColor: '#000',
129
+ * shadowOffset: { width: 0, height: 5 }
130
+ * }}
131
+ * >
132
+ * <Animated.View style={[
133
+ * styles.taskContainer,
134
+ * {
135
+ * backgroundColor: task.priority === 'high' ? '#ffebee' : '#f5f5f5'
136
+ * }
137
+ * ]}>
138
+ * <Text style={styles.taskTitle}>{task.title}</Text>
139
+ * <View style={styles.taskMeta}>
140
+ * <Text style={styles.taskDue}>{task.dueDate}</Text>
141
+ * <Text style={styles.taskAssignee}>{task.assignee}</Text>
142
+ * </View>
143
+ * </Animated.View>
144
+ * </SortableItem>
145
+ * );
146
+ * }
147
+ * ```
148
+ *
149
+ * @see {@link SortableItem.Handle} for creating drag handles
150
+ * @see {@link useSortable} for the underlying hook
151
+ * @see {@link Sortable} for the parent sortable list component
152
+ * @see {@link UseSortableOptions} for configuration options
153
+ * @see {@link UseSortableReturn} for hook return details
154
+ */
155
+ export declare function SortableItem<T>({ id, data, positions, lowerBound, autoScrollDirection, itemsCount, itemHeight, containerHeight, children, style, animatedStyle: customAnimatedStyle, onMove, onDragStart, onDrop, onDragging, }: SortableItemProps<T>): React.JSX.Element;
156
+ export declare namespace SortableItem {
157
+ var Handle: ({ children, style }: SortableHandleProps) => React.JSX.Element;
158
+ }
@@ -0,0 +1,251 @@
1
+ import React, { createContext, useContext } from "react";
2
+ import Animated from "react-native-reanimated";
3
+ import { PanGestureHandler } from "react-native-gesture-handler";
4
+ import { useSortable } from "../hooks/useSortable";
5
+ // Create a context to share gesture between SortableItem and SortableHandle
6
+ const SortableContext = createContext(null);
7
+ /**
8
+ * A handle component that can be used within SortableItem to create a specific
9
+ * draggable area. When a SortableHandle is present, only the handle area can
10
+ * initiate dragging, while the rest of the item remains non-draggable.
11
+ *
12
+ * @param props - Props for the handle component
13
+ *
14
+ * @example
15
+ * Basic drag handle:
16
+ * ```typescript
17
+ * <SortableItem id="item-1" {...sortableProps}>
18
+ * <View style={styles.itemContent}>
19
+ * <Text>Item content (not draggable)</Text>
20
+ *
21
+ * <SortableItem.Handle style={styles.dragHandle}>
22
+ * <Icon name="drag-handle" size={20} />
23
+ * </SortableItem.Handle>
24
+ * </View>
25
+ * </SortableItem>
26
+ * ```
27
+ *
28
+ * @example
29
+ * Custom styled handle:
30
+ * ```typescript
31
+ * <SortableItem id="item-2" {...sortableProps}>
32
+ * <View style={styles.card}>
33
+ * <Text style={styles.title}>Card Title</Text>
34
+ * <Text style={styles.content}>Card content...</Text>
35
+ *
36
+ * <SortableItem.Handle style={styles.customHandle}>
37
+ * <View style={styles.handleDots}>
38
+ * <View style={styles.dot} />
39
+ * <View style={styles.dot} />
40
+ * <View style={styles.dot} />
41
+ * </View>
42
+ * </SortableItem.Handle>
43
+ * </View>
44
+ * </SortableItem>
45
+ * ```
46
+ */
47
+ const SortableHandle = ({ children, style }) => {
48
+ const sortableContext = useContext(SortableContext);
49
+ if (!sortableContext) {
50
+ console.warn("SortableHandle must be used within a SortableItem component");
51
+ return <>{children}</>;
52
+ }
53
+ return (<PanGestureHandler onGestureEvent={sortableContext.panGestureHandler}>
54
+ <Animated.View style={style}>{children}</Animated.View>
55
+ </PanGestureHandler>);
56
+ };
57
+ /**
58
+ * A component for individual items within a sortable list.
59
+ *
60
+ * SortableItem provides the drag-and-drop functionality for individual list items,
61
+ * handling gesture recognition, position animations, and reordering logic.
62
+ * It can be used with or without drag handles for different interaction patterns.
63
+ *
64
+ * @template T - The type of data associated with this sortable item
65
+ * @param props - Configuration props for the sortable item
66
+ *
67
+ * @example
68
+ * Basic sortable item (entire item is draggable):
69
+ * ```typescript
70
+ * import { SortableItem } from './components/SortableItem';
71
+ *
72
+ * function TaskItem({ task, positions, ...sortableProps }) {
73
+ * return (
74
+ * <SortableItem
75
+ * id={task.id}
76
+ * data={task}
77
+ * positions={positions}
78
+ * {...sortableProps}
79
+ * onMove={(id, from, to) => {
80
+ * console.log(`Task ${id} moved from ${from} to ${to}`);
81
+ * reorderTasks(id, from, to);
82
+ * }}
83
+ * >
84
+ * <View style={styles.taskContainer}>
85
+ * <Text style={styles.taskTitle}>{task.title}</Text>
86
+ * <Text style={styles.taskStatus}>{task.completed ? 'Done' : 'Pending'}</Text>
87
+ * </View>
88
+ * </SortableItem>
89
+ * );
90
+ * }
91
+ * ```
92
+ *
93
+ * @example
94
+ * Sortable item with drag handle:
95
+ * ```typescript
96
+ * function TaskItemWithHandle({ task, positions, ...sortableProps }) {
97
+ * return (
98
+ * <SortableItem
99
+ * id={task.id}
100
+ * data={task}
101
+ * positions={positions}
102
+ * {...sortableProps}
103
+ * >
104
+ * <View style={styles.taskContainer}>
105
+ * <View style={styles.taskContent}>
106
+ * <Text style={styles.taskTitle}>{task.title}</Text>
107
+ * <Text style={styles.taskDescription}>{task.description}</Text>
108
+ * </View>
109
+ *
110
+ * {/* Only this handle can initiate dragging *\/}
111
+ * <SortableItem.Handle style={styles.dragHandle}>
112
+ * <View style={styles.handleIcon}>
113
+ * <View style={styles.handleLine} />
114
+ * <View style={styles.handleLine} />
115
+ * <View style={styles.handleLine} />
116
+ * </View>
117
+ * </SortableItem.Handle>
118
+ * </View>
119
+ * </SortableItem>
120
+ * );
121
+ * }
122
+ * ```
123
+ *
124
+ * @example
125
+ * Sortable item with callbacks and state tracking:
126
+ * ```typescript
127
+ * function AdvancedTaskItem({ task, positions, ...sortableProps }) {
128
+ * const [isDragging, setIsDragging] = useState(false);
129
+ *
130
+ * return (
131
+ * <SortableItem
132
+ * id={task.id}
133
+ * data={task}
134
+ * positions={positions}
135
+ * {...sortableProps}
136
+ * onDragStart={(id, position) => {
137
+ * setIsDragging(true);
138
+ * hapticFeedback();
139
+ * analytics.track('drag_start', { taskId: id, position });
140
+ * }}
141
+ * onDrop={(id, position) => {
142
+ * setIsDragging(false);
143
+ * analytics.track('drag_end', { taskId: id, position });
144
+ * }}
145
+ * onDragging={(id, overItemId, yPosition) => {
146
+ * if (overItemId) {
147
+ * // Show visual feedback for item being hovered over
148
+ * highlightItem(overItemId);
149
+ * }
150
+ * }}
151
+ * style={[
152
+ * styles.taskItem,
153
+ * isDragging && styles.draggingItem
154
+ * ]}
155
+ * >
156
+ * <View style={styles.taskContent}>
157
+ * <Text style={styles.taskTitle}>{task.title}</Text>
158
+ * <Text style={styles.taskPriority}>Priority: {task.priority}</Text>
159
+ * {isDragging && (
160
+ * <Text style={styles.dragIndicator}>Dragging...</Text>
161
+ * )}
162
+ * </View>
163
+ * </SortableItem>
164
+ * );
165
+ * }
166
+ * ```
167
+ *
168
+ * @example
169
+ * Sortable item with custom animations:
170
+ * ```typescript
171
+ * function AnimatedTaskItem({ task, positions, ...sortableProps }) {
172
+ * return (
173
+ * <SortableItem
174
+ * id={task.id}
175
+ * data={task}
176
+ * positions={positions}
177
+ * {...sortableProps}
178
+ * animatedStyle={{
179
+ * // Custom animated styles can be applied here
180
+ * shadowOpacity: 0.3,
181
+ * shadowRadius: 10,
182
+ * shadowColor: '#000',
183
+ * shadowOffset: { width: 0, height: 5 }
184
+ * }}
185
+ * >
186
+ * <Animated.View style={[
187
+ * styles.taskContainer,
188
+ * {
189
+ * backgroundColor: task.priority === 'high' ? '#ffebee' : '#f5f5f5'
190
+ * }
191
+ * ]}>
192
+ * <Text style={styles.taskTitle}>{task.title}</Text>
193
+ * <View style={styles.taskMeta}>
194
+ * <Text style={styles.taskDue}>{task.dueDate}</Text>
195
+ * <Text style={styles.taskAssignee}>{task.assignee}</Text>
196
+ * </View>
197
+ * </Animated.View>
198
+ * </SortableItem>
199
+ * );
200
+ * }
201
+ * ```
202
+ *
203
+ * @see {@link SortableItem.Handle} for creating drag handles
204
+ * @see {@link useSortable} for the underlying hook
205
+ * @see {@link Sortable} for the parent sortable list component
206
+ * @see {@link UseSortableOptions} for configuration options
207
+ * @see {@link UseSortableReturn} for hook return details
208
+ */
209
+ export function SortableItem({ id, data, positions, lowerBound, autoScrollDirection, itemsCount, itemHeight, containerHeight, children, style, animatedStyle: customAnimatedStyle, onMove, onDragStart, onDrop, onDragging, }) {
210
+ // Use our custom hook for all the sortable logic
211
+ const sortableOptions = {
212
+ id,
213
+ positions,
214
+ lowerBound,
215
+ autoScrollDirection,
216
+ itemsCount,
217
+ itemHeight,
218
+ containerHeight,
219
+ onMove,
220
+ onDragStart,
221
+ onDrop,
222
+ onDragging,
223
+ children,
224
+ handleComponent: SortableHandle,
225
+ };
226
+ const { animatedStyle, panGestureHandler, isMoving, hasHandle } = useSortable(sortableOptions);
227
+ // Combine the default animated style with any custom styles
228
+ const combinedAnimatedStyle = [animatedStyle, customAnimatedStyle];
229
+ // Create the context value
230
+ const contextValue = {
231
+ panGestureHandler,
232
+ };
233
+ // Always provide the context to avoid issues when toggling handle modes
234
+ const content = (<Animated.View style={combinedAnimatedStyle}>
235
+ <SortableContext.Provider value={contextValue}>
236
+ <Animated.View style={style}>{children}</Animated.View>
237
+ </SortableContext.Provider>
238
+ </Animated.View>);
239
+ // If a handle is found, let the handle control the dragging
240
+ // Otherwise, the entire component is draggable with PanGestureHandler
241
+ if (hasHandle) {
242
+ return content;
243
+ }
244
+ else {
245
+ return (<PanGestureHandler onGestureEvent={panGestureHandler} activateAfterLongPress={200} shouldCancelWhenOutside={false}>
246
+ {content}
247
+ </PanGestureHandler>);
248
+ }
249
+ }
250
+ // Attach the SortableHandle as a static property
251
+ SortableItem.Handle = SortableHandle;
@@ -0,0 +1,21 @@
1
+ import { SharedValue } from "react-native-reanimated";
2
+ export declare enum ScrollDirection {
3
+ None = "none",
4
+ Up = "up",
5
+ Down = "down"
6
+ }
7
+ export declare function clamp(value: number, lowerBound: number, upperBound: number): number;
8
+ export declare function objectMove(object: {
9
+ [id: string]: number;
10
+ }, from: number, to: number): {
11
+ [id: string]: number;
12
+ };
13
+ export declare function listToObject<T extends {
14
+ id: string;
15
+ }>(list: T[]): {
16
+ [id: string]: number;
17
+ };
18
+ export declare function setPosition(positionY: number, itemsCount: number, positions: SharedValue<{
19
+ [id: string]: number;
20
+ }>, id: string, itemHeight: number): void;
21
+ export declare function setAutoScroll(positionY: number, lowerBound: number, upperBound: number, scrollThreshold: number, autoScroll: SharedValue<ScrollDirection>): void;
@@ -0,0 +1,50 @@
1
+ export var ScrollDirection;
2
+ (function (ScrollDirection) {
3
+ ScrollDirection["None"] = "none";
4
+ ScrollDirection["Up"] = "up";
5
+ ScrollDirection["Down"] = "down";
6
+ })(ScrollDirection || (ScrollDirection = {}));
7
+ export function clamp(value, lowerBound, upperBound) {
8
+ "worklet";
9
+ return Math.max(lowerBound, Math.min(value, upperBound));
10
+ }
11
+ export function objectMove(object, from, to) {
12
+ "worklet";
13
+ const newObject = Object.assign({}, object);
14
+ for (const id in object) {
15
+ if (object[id] === from) {
16
+ newObject[id] = to;
17
+ }
18
+ if (object[id] === to) {
19
+ newObject[id] = from;
20
+ }
21
+ }
22
+ return newObject;
23
+ }
24
+ export function listToObject(list) {
25
+ const values = Object.values(list);
26
+ const object = {};
27
+ for (let i = 0; i < values.length; i++) {
28
+ object[values[i].id] = i;
29
+ }
30
+ return object;
31
+ }
32
+ export function setPosition(positionY, itemsCount, positions, id, itemHeight) {
33
+ "worklet";
34
+ const newPosition = clamp(Math.floor(positionY / itemHeight), 0, itemsCount - 1);
35
+ if (newPosition !== positions.value[id]) {
36
+ positions.value = objectMove(positions.value, positions.value[id], newPosition);
37
+ }
38
+ }
39
+ export function setAutoScroll(positionY, lowerBound, upperBound, scrollThreshold, autoScroll) {
40
+ "worklet";
41
+ if (positionY <= lowerBound + scrollThreshold) {
42
+ autoScroll.value = ScrollDirection.Up;
43
+ }
44
+ else if (positionY >= upperBound - scrollThreshold) {
45
+ autoScroll.value = ScrollDirection.Down;
46
+ }
47
+ else {
48
+ autoScroll.value = ScrollDirection.None;
49
+ }
50
+ }
@@ -0,0 +1,118 @@
1
+ import React from "react";
2
+ import { DropProviderProps, DropProviderRef } from "../types/context";
3
+ /**
4
+ * Provider component that enables drag-and-drop functionality for its children.
5
+ *
6
+ * The DropProvider creates the context necessary for draggable and droppable components
7
+ * to communicate with each other. It manages the registration of drop zones, tracks
8
+ * active hover states, handles collision detection, and maintains the state of dropped items.
9
+ *
10
+ * @example
11
+ * Basic setup:
12
+ * ```typescript
13
+ * import { DropProvider } from './context/DropContext';
14
+ * import { Draggable, Droppable } from './components';
15
+ *
16
+ * function App() {
17
+ * return (
18
+ * <DropProvider>
19
+ * <View style={styles.container}>
20
+ * <Draggable data={{ id: '1', name: 'Item 1' }}>
21
+ * <Text>Drag me!</Text>
22
+ * </Draggable>
23
+ *
24
+ * <Droppable onDrop={(data) => console.log('Dropped:', data)}>
25
+ * <Text>Drop zone</Text>
26
+ * </Droppable>
27
+ * </View>
28
+ * </DropProvider>
29
+ * );
30
+ * }
31
+ * ```
32
+ *
33
+ * @example
34
+ * With callbacks and ref:
35
+ * ```typescript
36
+ * function AdvancedApp() {
37
+ * const dropProviderRef = useRef<DropProviderRef>(null);
38
+ * const [droppedItems, setDroppedItems] = useState({});
39
+ *
40
+ * const handleLayoutChange = () => {
41
+ * // Trigger position update after layout changes
42
+ * dropProviderRef.current?.requestPositionUpdate();
43
+ * };
44
+ *
45
+ * return (
46
+ * <DropProvider
47
+ * ref={dropProviderRef}
48
+ * onDroppedItemsUpdate={setDroppedItems}
49
+ * onDragStart={(data) => console.log('Drag started:', data)}
50
+ * onDragEnd={(data) => console.log('Drag ended:', data)}
51
+ * onDragging={({ x, y, itemData }) => {
52
+ * console.log(`${itemData.name} at (${x}, ${y})`);
53
+ * }}
54
+ * >
55
+ * <ScrollView onLayout={handleLayoutChange}>
56
+ * {/* Your draggable and droppable components *\/}
57
+ * </ScrollView>
58
+ * </DropProvider>
59
+ * );
60
+ * }
61
+ * ```
62
+ *
63
+ * @example
64
+ * Multiple drop zones with capacity:
65
+ * ```typescript
66
+ * function TaskBoard() {
67
+ * const [tasks, setTasks] = useState(initialTasks);
68
+ *
69
+ * return (
70
+ * <DropProvider
71
+ * onDroppedItemsUpdate={(dropped) => {
72
+ * // Update task positions based on drops
73
+ * updateTaskPositions(dropped);
74
+ * }}
75
+ * >
76
+ * <View style={styles.board}>
77
+ * {tasks.map(task => (
78
+ * <Draggable key={task.id} data={task}>
79
+ * <TaskCard task={task} />
80
+ * </Draggable>
81
+ * ))}
82
+ *
83
+ * <Droppable
84
+ * droppableId="todo"
85
+ * capacity={10}
86
+ * onDrop={(task) => moveTask(task.id, 'todo')}
87
+ * >
88
+ * <Column title="To Do" />
89
+ * </Droppable>
90
+ *
91
+ * <Droppable
92
+ * droppableId="in-progress"
93
+ * capacity={5}
94
+ * onDrop={(task) => moveTask(task.id, 'in-progress')}
95
+ * >
96
+ * <Column title="In Progress" />
97
+ * </Droppable>
98
+ *
99
+ * <Droppable
100
+ * droppableId="done"
101
+ * onDrop={(task) => moveTask(task.id, 'done')}
102
+ * >
103
+ * <Column title="Done" />
104
+ * </Droppable>
105
+ * </View>
106
+ * </DropProvider>
107
+ * );
108
+ * }
109
+ * ```
110
+ *
111
+ * @see {@link Draggable} for draggable components
112
+ * @see {@link Droppable} for droppable components
113
+ * @see {@link useDraggable} for draggable hook
114
+ * @see {@link useDroppable} for droppable hook
115
+ * @see {@link DropProviderRef} for imperative handle interface
116
+ * @see {@link DroppedItemsMap} for dropped items data structure
117
+ */
118
+ export declare const DropProvider: React.ForwardRefExoticComponent<DropProviderProps & React.RefAttributes<DropProviderRef>>;