@mapples/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.
- package/README.md +390 -0
- package/dist/components/DnDRootView.d.ts +13 -0
- package/dist/components/DnDRootView.d.ts.map +1 -0
- package/dist/components/DnDRootView.js +98 -0
- package/dist/components/DnDRootView.js.map +1 -0
- package/dist/components/DropArea.d.ts +13 -0
- package/dist/components/DropArea.d.ts.map +1 -0
- package/dist/components/DropArea.js +16 -0
- package/dist/components/DropArea.js.map +1 -0
- package/dist/components/index.d.ts +3 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/index.js +3 -0
- package/dist/components/index.js.map +1 -0
- package/dist/constants/index.d.ts +15 -0
- package/dist/constants/index.d.ts.map +1 -0
- package/dist/constants/index.js +16 -0
- package/dist/constants/index.js.map +1 -0
- package/dist/context/DnDContext.d.ts +14 -0
- package/dist/context/DnDContext.d.ts.map +1 -0
- package/dist/context/DnDContext.js +22 -0
- package/dist/context/DnDContext.js.map +1 -0
- package/dist/context/DropContext.d.ts +17 -0
- package/dist/context/DropContext.d.ts.map +1 -0
- package/dist/context/DropContext.js +16 -0
- package/dist/context/DropContext.js.map +1 -0
- package/dist/context/index.d.ts +5 -0
- package/dist/context/index.d.ts.map +1 -0
- package/dist/context/index.js +5 -0
- package/dist/context/index.js.map +1 -0
- package/dist/hooks/index.d.ts +5 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/index.js +5 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/hooks/useDnD.d.ts +13 -0
- package/dist/hooks/useDnD.d.ts.map +1 -0
- package/dist/hooks/useDnD.js +16 -0
- package/dist/hooks/useDnD.js.map +1 -0
- package/dist/hooks/useDrag.d.ts +24 -0
- package/dist/hooks/useDrag.d.ts.map +1 -0
- package/dist/hooks/useDrag.js +74 -0
- package/dist/hooks/useDrag.js.map +1 -0
- package/dist/hooks/useDrop.d.ts +31 -0
- package/dist/hooks/useDrop.d.ts.map +1 -0
- package/dist/hooks/useDrop.js +108 -0
- package/dist/hooks/useDrop.js.map +1 -0
- package/dist/hooks/useDropContext.d.ts +12 -0
- package/dist/hooks/useDropContext.d.ts.map +1 -0
- package/dist/hooks/useDropContext.js +14 -0
- package/dist/hooks/useDropContext.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/monitor/Monitor.d.ts +223 -0
- package/dist/monitor/Monitor.d.ts.map +1 -0
- package/dist/monitor/Monitor.js +573 -0
- package/dist/monitor/Monitor.js.map +1 -0
- package/dist/monitor/index.d.ts +3 -0
- package/dist/monitor/index.d.ts.map +1 -0
- package/dist/monitor/index.js +3 -0
- package/dist/monitor/index.js.map +1 -0
- package/dist/types/index.d.ts +208 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +33 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/index.d.ts +11 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +13 -0
- package/dist/utils/index.js.map +1 -0
- package/package.json +62 -0
package/README.md
ADDED
|
@@ -0,0 +1,390 @@
|
|
|
1
|
+
# @mapples/dnd
|
|
2
|
+
|
|
3
|
+
A powerful and flexible drag and drop library for React Native applications. This package provides a complete drag and drop system with gesture handling, hit detection, and hierarchical drop targets.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🎯 **Precise Hit Detection** - Advanced collision detection with configurable padding
|
|
8
|
+
- 🌳 **Hierarchical Drop Targets** - Support for nested drop areas with parent-child relationships
|
|
9
|
+
- 📱 **React Native Gesture Handler** - Smooth gesture recognition and handling
|
|
10
|
+
- 🎨 **Customizable Drag Elements** - Support for custom drag previews and animations
|
|
11
|
+
- 📊 **TypeScript Support** - Full type safety with comprehensive TSDoc documentation
|
|
12
|
+
- 🔄 **Real-time Updates** - Live layout updates and position tracking
|
|
13
|
+
- 🎛️ **Flexible Configuration** - Configurable drop targets with layout options
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install @mapples/dnd
|
|
19
|
+
# or
|
|
20
|
+
yarn add @mapples/dnd
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Quick Start
|
|
24
|
+
|
|
25
|
+
### Basic Setup
|
|
26
|
+
|
|
27
|
+
```tsx
|
|
28
|
+
import React from 'react';
|
|
29
|
+
import { View, Text } from 'react-native';
|
|
30
|
+
import { DnDRootView, useDrag, useDrop } from '@mapples/dnd';
|
|
31
|
+
|
|
32
|
+
interface MyData {
|
|
33
|
+
id: string;
|
|
34
|
+
title: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const DraggableItem = ({ data }: { data: MyData }) => {
|
|
38
|
+
const ref = useRef<View>(null);
|
|
39
|
+
const { isDragging } = useDrag(ref, {
|
|
40
|
+
type: 'item',
|
|
41
|
+
label: data.title,
|
|
42
|
+
data: data,
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<View
|
|
47
|
+
ref={ref}
|
|
48
|
+
style={{
|
|
49
|
+
backgroundColor: isDragging ? '#e3f2fd' : '#f5f5f5',
|
|
50
|
+
padding: 16,
|
|
51
|
+
margin: 8,
|
|
52
|
+
borderRadius: 8,
|
|
53
|
+
}}
|
|
54
|
+
>
|
|
55
|
+
<Text>{data.title}</Text>
|
|
56
|
+
</View>
|
|
57
|
+
);
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const DropZone = ({ children }: { children: React.ReactNode }) => {
|
|
61
|
+
const ref = useRef<View>(null);
|
|
62
|
+
const { isOver, dropTarget } = useDrop<MyData>(ref, {
|
|
63
|
+
canDrop: true,
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
return (
|
|
67
|
+
<View
|
|
68
|
+
ref={ref}
|
|
69
|
+
style={{
|
|
70
|
+
backgroundColor: isOver ? '#e8f5e8' : '#ffffff',
|
|
71
|
+
borderWidth: 2,
|
|
72
|
+
borderColor: isOver ? '#4caf50' : '#e0e0e0',
|
|
73
|
+
borderStyle: 'dashed',
|
|
74
|
+
padding: 20,
|
|
75
|
+
minHeight: 100,
|
|
76
|
+
}}
|
|
77
|
+
>
|
|
78
|
+
{children}
|
|
79
|
+
</View>
|
|
80
|
+
);
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
const App = () => {
|
|
84
|
+
const handleDrop = (event, item) => {
|
|
85
|
+
console.log('Dropped:', item.data);
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
return (
|
|
89
|
+
<DnDRootView<MyData> onDrop={handleDrop}>
|
|
90
|
+
<View style={{ flex: 1, padding: 20 }}>
|
|
91
|
+
<DropZone>
|
|
92
|
+
<Text>Drop items here</Text>
|
|
93
|
+
</DropZone>
|
|
94
|
+
|
|
95
|
+
<View style={{ marginTop: 20 }}>
|
|
96
|
+
<DraggableItem data={{ id: '1', title: 'Item 1' }} />
|
|
97
|
+
<DraggableItem data={{ id: '2', title: 'Item 2' }} />
|
|
98
|
+
</View>
|
|
99
|
+
</View>
|
|
100
|
+
</DnDRootView>
|
|
101
|
+
);
|
|
102
|
+
};
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## API Reference
|
|
106
|
+
|
|
107
|
+
### Components
|
|
108
|
+
|
|
109
|
+
#### `DnDRootView<T>`
|
|
110
|
+
|
|
111
|
+
The root component that provides drag and drop functionality to its children.
|
|
112
|
+
|
|
113
|
+
**Props:**
|
|
114
|
+
|
|
115
|
+
- `children` - Child components
|
|
116
|
+
- `DragElement?` - Optional custom drag element renderer
|
|
117
|
+
- `onDrop?` - Callback fired when a drop operation completes
|
|
118
|
+
|
|
119
|
+
**Example:**
|
|
120
|
+
|
|
121
|
+
```tsx
|
|
122
|
+
<DnDRootView<MyDataType> onDrop={handleDrop}>
|
|
123
|
+
{/* Your draggable and droppable components */}
|
|
124
|
+
</DnDRootView>
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
#### `DropArea`
|
|
128
|
+
|
|
129
|
+
Component that creates a drop area context for establishing parent-child relationships in the drop target hierarchy.
|
|
130
|
+
|
|
131
|
+
**Props:**
|
|
132
|
+
|
|
133
|
+
- `forId` - The ID of the parent drop target this area belongs to
|
|
134
|
+
- `children` - Child components
|
|
135
|
+
|
|
136
|
+
**Example:**
|
|
137
|
+
|
|
138
|
+
```tsx
|
|
139
|
+
<DropArea forId={parentId}>
|
|
140
|
+
<DropZone />
|
|
141
|
+
</DropArea>
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Hooks
|
|
145
|
+
|
|
146
|
+
#### `useDrag<DragData, DropData>(ref, item)`
|
|
147
|
+
|
|
148
|
+
Makes a view draggable within the drag and drop system.
|
|
149
|
+
|
|
150
|
+
**Parameters:**
|
|
151
|
+
|
|
152
|
+
- `ref` - Reference to the view element that should be draggable
|
|
153
|
+
- `item` - The drag item configuration with data and metadata
|
|
154
|
+
|
|
155
|
+
**Returns:**
|
|
156
|
+
|
|
157
|
+
- `id` - The unique ID of the drag element
|
|
158
|
+
- `updateLayout` - Function to update the element's layout information
|
|
159
|
+
- `isDragging` - Whether this element is currently being dragged
|
|
160
|
+
|
|
161
|
+
**Example:**
|
|
162
|
+
|
|
163
|
+
```tsx
|
|
164
|
+
const { isDragging, updateLayout } = useDrag(ref, {
|
|
165
|
+
type: 'item',
|
|
166
|
+
label: 'My Item',
|
|
167
|
+
data: { id: '1', name: 'Item 1' },
|
|
168
|
+
});
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
#### `useDrop<DragData, DropData>(ref, config?, data?)`
|
|
172
|
+
|
|
173
|
+
Makes a view a drop target within the drag and drop system.
|
|
174
|
+
|
|
175
|
+
**Parameters:**
|
|
176
|
+
|
|
177
|
+
- `ref` - Reference to the view element that should be a drop target
|
|
178
|
+
- `config?` - Optional configuration for the drop target behavior
|
|
179
|
+
- `data?` - Optional data associated with this drop target
|
|
180
|
+
|
|
181
|
+
**Returns:**
|
|
182
|
+
|
|
183
|
+
- `id` - The unique ID of the drop element
|
|
184
|
+
- `isOver` - Whether a drag is currently over this drop target
|
|
185
|
+
- `dropTarget` - The current drop target information
|
|
186
|
+
- `dropTargetIndex` - The index position within the drop target
|
|
187
|
+
- `isDragging` - Whether any drag operation is currently active
|
|
188
|
+
- `updateLayout` - Function to update the element's layout information
|
|
189
|
+
|
|
190
|
+
**Example:**
|
|
191
|
+
|
|
192
|
+
```tsx
|
|
193
|
+
const { isOver, dropTarget } = useDrop<MyDataType>(
|
|
194
|
+
ref,
|
|
195
|
+
{
|
|
196
|
+
canDrop: true,
|
|
197
|
+
index: 0,
|
|
198
|
+
zIndex: 1,
|
|
199
|
+
},
|
|
200
|
+
{ category: 'items' },
|
|
201
|
+
);
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
#### `useDnD<DragData, DropData>()`
|
|
205
|
+
|
|
206
|
+
Hook to access the drag and drop context.
|
|
207
|
+
|
|
208
|
+
**Returns:**
|
|
209
|
+
|
|
210
|
+
- `monitor` - The monitor instance that tracks drag and drop operations
|
|
211
|
+
- `isDragging` - Whether a drag operation is currently active
|
|
212
|
+
- `sv` - Shared value for drag coordinates
|
|
213
|
+
- `svOverLayout` - Shared value for overlay layout information
|
|
214
|
+
|
|
215
|
+
#### `useDropContext()`
|
|
216
|
+
|
|
217
|
+
Hook to access the drop context for establishing hierarchy.
|
|
218
|
+
|
|
219
|
+
**Returns:**
|
|
220
|
+
|
|
221
|
+
- `parent` - The parent drop target ID
|
|
222
|
+
|
|
223
|
+
### Types
|
|
224
|
+
|
|
225
|
+
#### `DragItem<T>`
|
|
226
|
+
|
|
227
|
+
Interface representing a draggable item with metadata and data.
|
|
228
|
+
|
|
229
|
+
```tsx
|
|
230
|
+
interface DragItem<T> {
|
|
231
|
+
type: string; // The type identifier for the drag item
|
|
232
|
+
label: string; // The display label for the drag item
|
|
233
|
+
icon?: FC<SvgProps>; // Optional icon component for the drag item
|
|
234
|
+
data: T; // The data payload associated with the drag item
|
|
235
|
+
}
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
#### `DropTargetConfig`
|
|
239
|
+
|
|
240
|
+
Interface for configuring drop target behavior and layout.
|
|
241
|
+
|
|
242
|
+
```tsx
|
|
243
|
+
interface DropTargetConfig {
|
|
244
|
+
canDrop?: boolean; // Whether this drop target can accept drops
|
|
245
|
+
index?: number; // The index position within the parent container
|
|
246
|
+
zIndex?: number; // The z-index for layering
|
|
247
|
+
flexDirection?: FlexDirection; // The flex direction for child elements
|
|
248
|
+
}
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
#### `DnDEvent<DragData, DropData>`
|
|
252
|
+
|
|
253
|
+
Interface representing a drag and drop event with associated data.
|
|
254
|
+
|
|
255
|
+
```tsx
|
|
256
|
+
interface DnDEvent<DragData, DropData> {
|
|
257
|
+
type: DnDEventType; // The type of drag and drop event
|
|
258
|
+
target?: number | null; // The ID of the drag target element
|
|
259
|
+
dropTarget?: DropTarget<DropData> | null; // The drop target that the drag is currently over
|
|
260
|
+
dropTargetIndex?: number | null; // The index position within the drop target
|
|
261
|
+
data?: DragData | null; // The data associated with the drag operation
|
|
262
|
+
dragCoords?: DragCoords | null; // The current coordinates of the drag operation
|
|
263
|
+
}
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
## Advanced Usage
|
|
267
|
+
|
|
268
|
+
### Hierarchical Drop Targets
|
|
269
|
+
|
|
270
|
+
```tsx
|
|
271
|
+
const NestedDropExample = () => {
|
|
272
|
+
const parentRef = useRef<View>(null);
|
|
273
|
+
const childRef = useRef<View>(null);
|
|
274
|
+
|
|
275
|
+
const { isOver: parentIsOver } = useDrop(parentRef, { canDrop: true });
|
|
276
|
+
const { isOver: childIsOver } = useDrop(childRef, { canDrop: true });
|
|
277
|
+
|
|
278
|
+
return (
|
|
279
|
+
<DnDRootView>
|
|
280
|
+
<View
|
|
281
|
+
ref={parentRef}
|
|
282
|
+
style={{ backgroundColor: parentIsOver ? 'lightblue' : 'white' }}
|
|
283
|
+
>
|
|
284
|
+
<Text>Parent Drop Zone</Text>
|
|
285
|
+
|
|
286
|
+
<DropArea forId={/* parent ID */}>
|
|
287
|
+
<View
|
|
288
|
+
ref={childRef}
|
|
289
|
+
style={{ backgroundColor: childIsOver ? 'lightgreen' : 'white' }}
|
|
290
|
+
>
|
|
291
|
+
<Text>Child Drop Zone</Text>
|
|
292
|
+
</View>
|
|
293
|
+
</DropArea>
|
|
294
|
+
</View>
|
|
295
|
+
</DnDRootView>
|
|
296
|
+
);
|
|
297
|
+
};
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
### Custom Drag Element
|
|
301
|
+
|
|
302
|
+
```tsx
|
|
303
|
+
const CustomDragElement = ({ data }: { data: DragItem<MyData> }) => (
|
|
304
|
+
<View
|
|
305
|
+
style={{ backgroundColor: 'rgba(0,0,0,0.8)', padding: 10, borderRadius: 5 }}
|
|
306
|
+
>
|
|
307
|
+
<Text style={{ color: 'white' }}>{data.label}</Text>
|
|
308
|
+
</View>
|
|
309
|
+
);
|
|
310
|
+
|
|
311
|
+
const App = () => (
|
|
312
|
+
<DnDRootView<MyData> DragElement={CustomDragElement}>
|
|
313
|
+
{/* Your components */}
|
|
314
|
+
</DnDRootView>
|
|
315
|
+
);
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
### Event Handling
|
|
319
|
+
|
|
320
|
+
```tsx
|
|
321
|
+
const App = () => {
|
|
322
|
+
const handleDrop = (event: DnDEvent<MyData>, item: DragItem<MyData>) => {
|
|
323
|
+
console.log('Drop event:', event);
|
|
324
|
+
console.log('Dropped item:', item);
|
|
325
|
+
|
|
326
|
+
// Handle the drop logic
|
|
327
|
+
if (event.dropTarget) {
|
|
328
|
+
// Move item to new position
|
|
329
|
+
moveItem(item.data, event.dropTargetIndex);
|
|
330
|
+
}
|
|
331
|
+
};
|
|
332
|
+
|
|
333
|
+
return (
|
|
334
|
+
<DnDRootView<MyData> onDrop={handleDrop}>
|
|
335
|
+
{/* Your components */}
|
|
336
|
+
</DnDRootView>
|
|
337
|
+
);
|
|
338
|
+
};
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
## Configuration
|
|
342
|
+
|
|
343
|
+
### Monitor Configuration
|
|
344
|
+
|
|
345
|
+
The monitor can be configured with padding and outside tracking:
|
|
346
|
+
|
|
347
|
+
```tsx
|
|
348
|
+
// In DnDRootView, the monitor is created with:
|
|
349
|
+
const monitor = new Monitor({
|
|
350
|
+
padding: 5, // Padding around drop targets for hit detection
|
|
351
|
+
trackOutside: false, // Whether to track drag operations outside the root element
|
|
352
|
+
});
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
### Drop Target Configuration
|
|
356
|
+
|
|
357
|
+
```tsx
|
|
358
|
+
const config: DropTargetConfig = {
|
|
359
|
+
canDrop: true, // Allow drops
|
|
360
|
+
index: 0, // Position in parent
|
|
361
|
+
zIndex: 1, // Layering
|
|
362
|
+
flexDirection: FlexDirection.Row, // Layout direction
|
|
363
|
+
};
|
|
364
|
+
|
|
365
|
+
const { isOver } = useDrop(ref, config);
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
## Performance Considerations
|
|
369
|
+
|
|
370
|
+
- Use `updateLayout()` sparingly and only when necessary
|
|
371
|
+
- Consider using `useCallback` for event handlers to prevent unnecessary re-renders
|
|
372
|
+
- The monitor automatically handles cleanup when components unmount
|
|
373
|
+
- Hit detection is optimized with spatial indexing
|
|
374
|
+
|
|
375
|
+
## TypeScript Support
|
|
376
|
+
|
|
377
|
+
This package is written in TypeScript and provides full type safety. All APIs are documented with TSDoc comments for excellent IDE support and IntelliSense.
|
|
378
|
+
|
|
379
|
+
## Contributing
|
|
380
|
+
|
|
381
|
+
Contributions are welcome! Please ensure that:
|
|
382
|
+
|
|
383
|
+
1. All new APIs include comprehensive TSDoc documentation
|
|
384
|
+
2. TypeScript types are properly defined
|
|
385
|
+
3. Tests are added for new functionality
|
|
386
|
+
4. The README is updated for any new features
|
|
387
|
+
|
|
388
|
+
## License
|
|
389
|
+
|
|
390
|
+
MIT License - see LICENSE file for details.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { DnDRootViewProps } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Root component that provides drag and drop functionality to its children.
|
|
4
|
+
* This component sets up the gesture handling, context, and monitor for the entire drag and drop system.
|
|
5
|
+
*
|
|
6
|
+
* @template T - The type of data being dragged
|
|
7
|
+
* @param props - The component props
|
|
8
|
+
* @returns The rendered drag and drop root view
|
|
9
|
+
* @public
|
|
10
|
+
*/
|
|
11
|
+
declare const DnDRootView: <T extends object>({ children, DragElement, onDrop, ...props }: DnDRootViewProps<T>) => import("react").JSX.Element;
|
|
12
|
+
export default DnDRootView;
|
|
13
|
+
//# sourceMappingURL=DnDRootView.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DnDRootView.d.ts","sourceRoot":"","sources":["../../src/components/DnDRootView.tsx"],"names":[],"mappings":"AAiBA,OAAO,EAAgB,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAG1D;;;;;;;;GAQG;AACH,QAAA,MAAM,WAAW,GAAI,CAAC,SAAS,MAAM,EAAE,6CAKpC,gBAAgB,CAAC,CAAC,CAAC,gCAgGrB,CAAC;AAEF,eAAe,WAAW,CAAC"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { useEffect, useRef, useState } from 'react';
|
|
2
|
+
import { Gesture, GestureDetector, GestureHandlerRootView, } from 'react-native-gesture-handler';
|
|
3
|
+
import { runOnJS, useSharedValue } from 'react-native-reanimated';
|
|
4
|
+
import { filter } from 'rxjs';
|
|
5
|
+
import { initialDragCoords, initialOverLayout } from '../constants';
|
|
6
|
+
import { DnDContextProvider } from '../context';
|
|
7
|
+
import { Monitor } from '../monitor';
|
|
8
|
+
import { DnDEventType } from '../types';
|
|
9
|
+
import { filterEvents } from '../utils';
|
|
10
|
+
/**
|
|
11
|
+
* Root component that provides drag and drop functionality to its children.
|
|
12
|
+
* This component sets up the gesture handling, context, and monitor for the entire drag and drop system.
|
|
13
|
+
*
|
|
14
|
+
* @template T - The type of data being dragged
|
|
15
|
+
* @param props - The component props
|
|
16
|
+
* @returns The rendered drag and drop root view
|
|
17
|
+
* @public
|
|
18
|
+
*/
|
|
19
|
+
const DnDRootView = ({ children, DragElement, onDrop, ...props }) => {
|
|
20
|
+
const [isDragging, setIsDragging] = useState(false);
|
|
21
|
+
const monitor = useRef(new Monitor({ padding: 5 })).current;
|
|
22
|
+
const sv = useSharedValue(initialDragCoords);
|
|
23
|
+
const svOverLayout = useSharedValue(initialOverLayout);
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
const subscription = monitor.events
|
|
26
|
+
.pipe(filter(filterEvents(DnDEventType.DragStart, DnDEventType.DragEnd)))
|
|
27
|
+
.subscribe((e) => {
|
|
28
|
+
if (e.type === DnDEventType.DragStart) {
|
|
29
|
+
setIsDragging(true);
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
if (e.type === DnDEventType.DragEnd) {
|
|
33
|
+
setIsDragging(false);
|
|
34
|
+
if (onDrop) {
|
|
35
|
+
if (!e.target)
|
|
36
|
+
return;
|
|
37
|
+
const target = monitor.getDragTargetData(e.target);
|
|
38
|
+
if (!target)
|
|
39
|
+
return;
|
|
40
|
+
onDrop(e, target.item);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
return () => {
|
|
45
|
+
subscription.unsubscribe();
|
|
46
|
+
};
|
|
47
|
+
}, [monitor, onDrop]);
|
|
48
|
+
/**
|
|
49
|
+
* Handles pan gesture events for drag operations.
|
|
50
|
+
* @param type - The type of pan event (start, end, or drag)
|
|
51
|
+
* @param e - The gesture event payload
|
|
52
|
+
*/
|
|
53
|
+
const handlePanEvents = (type, e) => {
|
|
54
|
+
monitor[type]({ x: e.absoluteX, y: e.absoluteY });
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* Handles tap gesture events for selection.
|
|
58
|
+
* @param e - The tap gesture event payload
|
|
59
|
+
*/
|
|
60
|
+
const handleSelect = (e) => {
|
|
61
|
+
monitor.onSelect({ x: e.absoluteX, y: e.absoluteY });
|
|
62
|
+
};
|
|
63
|
+
const tap = Gesture.Tap().onEnd((e) => {
|
|
64
|
+
runOnJS(handleSelect)(e);
|
|
65
|
+
});
|
|
66
|
+
const pan = Gesture.Pan()
|
|
67
|
+
.onStart((e) => {
|
|
68
|
+
sv.set({
|
|
69
|
+
x: e.x,
|
|
70
|
+
y: e.y,
|
|
71
|
+
});
|
|
72
|
+
runOnJS(handlePanEvents)('onDragStart', e);
|
|
73
|
+
})
|
|
74
|
+
.onChange((e) => {
|
|
75
|
+
sv.set({
|
|
76
|
+
x: e.x,
|
|
77
|
+
y: e.y,
|
|
78
|
+
});
|
|
79
|
+
runOnJS(handlePanEvents)('onDrag', e);
|
|
80
|
+
})
|
|
81
|
+
.onEnd((e) => {
|
|
82
|
+
sv.set(initialDragCoords);
|
|
83
|
+
runOnJS(handlePanEvents)('onDragEnd', e);
|
|
84
|
+
});
|
|
85
|
+
const composed = Gesture.Race(pan, tap);
|
|
86
|
+
return (<DnDContextProvider value={{
|
|
87
|
+
monitor,
|
|
88
|
+
isDragging,
|
|
89
|
+
sv,
|
|
90
|
+
svOverLayout,
|
|
91
|
+
}}>
|
|
92
|
+
<GestureHandlerRootView {...props}>
|
|
93
|
+
<GestureDetector gesture={composed}>{children}</GestureDetector>
|
|
94
|
+
</GestureHandlerRootView>
|
|
95
|
+
</DnDContextProvider>);
|
|
96
|
+
};
|
|
97
|
+
export default DnDRootView;
|
|
98
|
+
//# sourceMappingURL=DnDRootView.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DnDRootView.js","sourceRoot":"","sources":["../../src/components/DnDRootView.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { FC, PropsWithChildren } from 'react';
|
|
2
|
+
import { DropAreaProps } from '../types';
|
|
3
|
+
/**
|
|
4
|
+
* Component that creates a drop area context for its children.
|
|
5
|
+
* This component establishes a parent-child relationship in the drop target hierarchy.
|
|
6
|
+
*
|
|
7
|
+
* @param props - The component props
|
|
8
|
+
* @returns The rendered drop area with context
|
|
9
|
+
* @public
|
|
10
|
+
*/
|
|
11
|
+
declare const DropArea: FC<PropsWithChildren<DropAreaProps>>;
|
|
12
|
+
export default DropArea;
|
|
13
|
+
//# sourceMappingURL=DropArea.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DropArea.d.ts","sourceRoot":"","sources":["../../src/components/DropArea.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAG9C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC;;;;;;;GAOG;AACH,QAAA,MAAM,QAAQ,EAAE,EAAE,CAAC,iBAAiB,CAAC,aAAa,CAAC,CASlD,CAAC;AAEF,eAAe,QAAQ,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { DropContextProvider } from '../context';
|
|
2
|
+
/**
|
|
3
|
+
* Component that creates a drop area context for its children.
|
|
4
|
+
* This component establishes a parent-child relationship in the drop target hierarchy.
|
|
5
|
+
*
|
|
6
|
+
* @param props - The component props
|
|
7
|
+
* @returns The rendered drop area with context
|
|
8
|
+
* @public
|
|
9
|
+
*/
|
|
10
|
+
const DropArea = ({ children, forId, }) => {
|
|
11
|
+
return (<DropContextProvider value={{ parent: forId }}>
|
|
12
|
+
{children}
|
|
13
|
+
</DropContextProvider>);
|
|
14
|
+
};
|
|
15
|
+
export default DropArea;
|
|
16
|
+
//# sourceMappingURL=DropArea.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DropArea.js","sourceRoot":"","sources":["../../src/components/DropArea.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAGjD;;;;;;;GAOG;AACH,MAAM,QAAQ,GAAyC,CAAC,EACtD,QAAQ,EACR,KAAK,GACN,EAAE,EAAE;IACH,OAAO,CACL,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAC5C;MAAA,CAAC,QAAQ,CACX;IAAA,EAAE,mBAAmB,CAAC,CACvB,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,QAAQ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { LayoutRectangle } from 'react-native';
|
|
2
|
+
/**
|
|
3
|
+
* Initial drag coordinates when no drag operation is active.
|
|
4
|
+
* @public
|
|
5
|
+
*/
|
|
6
|
+
export declare const initialDragCoords: {
|
|
7
|
+
x: number;
|
|
8
|
+
y: number;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Initial layout rectangle for overlay elements when no drag operation is active.
|
|
12
|
+
* @public
|
|
13
|
+
*/
|
|
14
|
+
export declare const initialOverLayout: LayoutRectangle;
|
|
15
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/constants/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/C;;;GAGG;AACH,eAAO,MAAM,iBAAiB;;;CAAiB,CAAC;AAEhD;;;GAGG;AACH,eAAO,MAAM,iBAAiB,EAAE,eAK/B,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Initial drag coordinates when no drag operation is active.
|
|
3
|
+
* @public
|
|
4
|
+
*/
|
|
5
|
+
export const initialDragCoords = { x: 0, y: 0 };
|
|
6
|
+
/**
|
|
7
|
+
* Initial layout rectangle for overlay elements when no drag operation is active.
|
|
8
|
+
* @public
|
|
9
|
+
*/
|
|
10
|
+
export const initialOverLayout = {
|
|
11
|
+
x: 0,
|
|
12
|
+
y: 0,
|
|
13
|
+
width: 0,
|
|
14
|
+
height: 0,
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/constants/index.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;AAEhD;;;GAGG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAoB;IAChD,CAAC,EAAE,CAAC;IACJ,CAAC,EAAE,CAAC;IACJ,KAAK,EAAE,CAAC;IACR,MAAM,EAAE,CAAC;CACV,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { DnDContextType } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* React context for drag and drop functionality.
|
|
4
|
+
* Provides access to the monitor, drag state, and shared values throughout the component tree.
|
|
5
|
+
* @public
|
|
6
|
+
*/
|
|
7
|
+
declare const DnDContext: import("react").Context<DnDContextType<any, any>>;
|
|
8
|
+
/**
|
|
9
|
+
* Provider component for the drag and drop context.
|
|
10
|
+
* @public
|
|
11
|
+
*/
|
|
12
|
+
export declare const DnDContextProvider: import("react").Provider<DnDContextType<any, any>>;
|
|
13
|
+
export default DnDContext;
|
|
14
|
+
//# sourceMappingURL=DnDContext.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DnDContext.d.ts","sourceRoot":"","sources":["../../src/context/DnDContext.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE1C;;;;GAIG;AACH,QAAA,MAAM,UAAU,mDAKd,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,kBAAkB,oDAAsB,CAAC;AAEtD,eAAe,UAAU,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { createContext } from 'react';
|
|
2
|
+
import { makeMutable } from 'react-native-reanimated';
|
|
3
|
+
import { initialDragCoords, initialOverLayout } from '../constants';
|
|
4
|
+
import { Monitor } from '../monitor';
|
|
5
|
+
/**
|
|
6
|
+
* React context for drag and drop functionality.
|
|
7
|
+
* Provides access to the monitor, drag state, and shared values throughout the component tree.
|
|
8
|
+
* @public
|
|
9
|
+
*/
|
|
10
|
+
const DnDContext = createContext({
|
|
11
|
+
monitor: new Monitor({ padding: 10 }),
|
|
12
|
+
isDragging: false,
|
|
13
|
+
sv: makeMutable(initialDragCoords),
|
|
14
|
+
svOverLayout: makeMutable(initialOverLayout),
|
|
15
|
+
});
|
|
16
|
+
/**
|
|
17
|
+
* Provider component for the drag and drop context.
|
|
18
|
+
* @public
|
|
19
|
+
*/
|
|
20
|
+
export const DnDContextProvider = DnDContext.Provider;
|
|
21
|
+
export default DnDContext;
|
|
22
|
+
//# sourceMappingURL=DnDContext.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DnDContext.js","sourceRoot":"","sources":["../../src/context/DnDContext.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAEtC,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAEtD,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACpE,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAGrC;;;;GAIG;AACH,MAAM,UAAU,GAAG,aAAa,CAA2B;IACzD,OAAO,EAAE,IAAI,OAAO,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;IACrC,UAAU,EAAE,KAAK;IACjB,EAAE,EAAE,WAAW,CAAC,iBAAiB,CAAC;IAClC,YAAY,EAAE,WAAW,CAAC,iBAAiB,CAAC;CAC7C,CAAC,CAAC;AAEH;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,UAAU,CAAC,QAAQ,CAAC;AAEtD,eAAe,UAAU,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* React context for drop area hierarchy.
|
|
3
|
+
* Provides access to the parent drop target ID for establishing parent-child relationships.
|
|
4
|
+
* @public
|
|
5
|
+
*/
|
|
6
|
+
declare const DropContext: import("react").Context<{
|
|
7
|
+
parent: number | null;
|
|
8
|
+
}>;
|
|
9
|
+
/**
|
|
10
|
+
* Provider component for the drop context.
|
|
11
|
+
* @public
|
|
12
|
+
*/
|
|
13
|
+
export declare const DropContextProvider: import("react").Provider<{
|
|
14
|
+
parent: number | null;
|
|
15
|
+
}>;
|
|
16
|
+
export default DropContext;
|
|
17
|
+
//# sourceMappingURL=DropContext.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DropContext.d.ts","sourceRoot":"","sources":["../../src/context/DropContext.tsx"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,QAAA,MAAM,WAAW;YAA2B,MAAM,GAAG,IAAI;EAEvD,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,mBAAmB;YARY,MAAM,GAAG,IAAI;EAQF,CAAC;AAExD,eAAe,WAAW,CAAC"}
|