react-dragdrop-kit 1.3.0 → 1.4.0
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 +269 -264
- package/dist/index.esm.js +1 -1
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/kanban.esm.js.map +1 -1
- package/dist/kanban.js.map +1 -1
- package/dist/src/components/DragDropList.d.ts +1 -1
- package/dist/src/hooks/useDragDropMonitor.d.ts +4 -2
- package/dist/src/hooks/useDragDropMonitor.logic.d.ts +39 -0
- package/dist/src/types/index.d.ts +1 -0
- package/package.json +10 -11
package/README.md
CHANGED
|
@@ -1,110 +1,112 @@
|
|
|
1
|
-
# react-dragdrop-kit
|
|
2
|
-
|
|
3
|
-
A flexible, lightweight drag-and-drop toolkit for React.
|
|
4
|
-
Build sortable lists, grids, and Kanban boards with a controlled API and minimal overhead.
|
|
5
|
-
|
|
1
|
+
# react-dragdrop-kit
|
|
2
|
+
|
|
3
|
+
A flexible, lightweight drag-and-drop toolkit for React.
|
|
4
|
+
Build sortable lists, grids, and Kanban boards with a controlled API and minimal overhead.
|
|
5
|
+
|
|
6
6
|
[](https://www.npmjs.com/package/react-dragdrop-kit)
|
|
7
7
|
[](https://www.npmjs.com/package/react-dragdrop-kit)
|
|
8
|
-
[](https://www.npmjs.com/package/react-dragdrop-kit)
|
|
9
9
|
[](https://github.com/Yourstruggle11/react-dragdrop-kit)
|
|
10
10
|
[](https://deepwiki.com/Yourstruggle11/react-dragdrop-kit)
|
|
11
|
-
|
|
12
|
-
## Why this library
|
|
13
|
-
|
|
14
|
-
`react-dragdrop-kit` is designed around a controlled data model:
|
|
15
|
-
|
|
16
|
-
- You own state.
|
|
17
|
-
- The library reports drag intent and reorder results.
|
|
18
|
-
- You decide what to persist and render.
|
|
19
|
-
|
|
20
|
-
This keeps behavior predictable and easy to integrate with app-specific rules.
|
|
21
|
-
|
|
22
|
-
## Feature overview
|
|
23
|
-
|
|
24
|
-
### List and grid drag-and-drop
|
|
25
|
-
|
|
26
|
-
- Vertical and horizontal list support
|
|
27
|
-
- Controlled reorder callback: `onReorder(newItems, orderUpdates)`
|
|
28
|
-
- Optional visual drop indicator
|
|
11
|
+
|
|
12
|
+
## Why this library
|
|
13
|
+
|
|
14
|
+
`react-dragdrop-kit` is designed around a controlled data model:
|
|
15
|
+
|
|
16
|
+
- You own state.
|
|
17
|
+
- The library reports drag intent and reorder results.
|
|
18
|
+
- You decide what to persist and render.
|
|
19
|
+
|
|
20
|
+
This keeps behavior predictable and easy to integrate with app-specific rules.
|
|
21
|
+
|
|
22
|
+
## Feature overview
|
|
23
|
+
|
|
24
|
+
### List and grid drag-and-drop
|
|
25
|
+
|
|
26
|
+
- Vertical and horizontal list support
|
|
27
|
+
- Controlled reorder callback: `onReorder(newItems, orderUpdates)`
|
|
28
|
+
- Optional visual drop indicator
|
|
29
29
|
- Optional custom drag preview style/class
|
|
30
30
|
- Optional handle-only dragging via `dragHandle`
|
|
31
31
|
- Optional multi-item drag with `selectedIds` + `multiDragEnabled`
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
- Card
|
|
37
|
-
-
|
|
38
|
-
-
|
|
32
|
+
- Optional live list reordering during drag-over via `liveReorder`
|
|
33
|
+
|
|
34
|
+
### Kanban module
|
|
35
|
+
|
|
36
|
+
- Card reorder within columns
|
|
37
|
+
- Card movement across columns
|
|
38
|
+
- Column reordering
|
|
39
|
+
- Headless rendering (`renderColumn`, `renderCard`)
|
|
39
40
|
- Accessibility helpers (`AnnouncerProvider`, `useAnnouncer`, `announcements`)
|
|
40
41
|
- Keyboard drag-reorder is planned, not fully shipped yet
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
-
|
|
46
|
-
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
import {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
{ id: "
|
|
84
|
-
{ id: "
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
42
|
+
- Live-reorder preview for Kanban is not shipped yet (drop-commit only)
|
|
43
|
+
|
|
44
|
+
### General
|
|
45
|
+
|
|
46
|
+
- TypeScript-first API
|
|
47
|
+
- Lightweight runtime and tree-shakeable exports
|
|
48
|
+
- Built on `@atlaskit/pragmatic-drag-and-drop`
|
|
49
|
+
|
|
50
|
+
## Installation
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
npm install react-dragdrop-kit
|
|
54
|
+
# or
|
|
55
|
+
pnpm add react-dragdrop-kit
|
|
56
|
+
# or
|
|
57
|
+
yarn add react-dragdrop-kit
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Package entry points
|
|
61
|
+
|
|
62
|
+
```ts
|
|
63
|
+
import { DragDropList } from "react-dragdrop-kit";
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
```ts
|
|
67
|
+
import { KanbanBoard, applyDragResult } from "react-dragdrop-kit/kanban";
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Quick start: sortable list
|
|
71
|
+
|
|
72
|
+
```tsx
|
|
73
|
+
import { useState } from "react";
|
|
74
|
+
import { DragDropList } from "react-dragdrop-kit";
|
|
75
|
+
|
|
76
|
+
interface Todo {
|
|
77
|
+
id: string;
|
|
78
|
+
position: number;
|
|
79
|
+
title: string;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export default function TodoList() {
|
|
83
|
+
const [items, setItems] = useState<Todo[]>([
|
|
84
|
+
{ id: "1", position: 0, title: "Design" },
|
|
85
|
+
{ id: "2", position: 1, title: "Build" },
|
|
86
|
+
{ id: "3", position: 2, title: "Ship" },
|
|
87
|
+
]);
|
|
88
|
+
|
|
89
|
+
return (
|
|
90
|
+
<DragDropList
|
|
91
|
+
items={items}
|
|
92
|
+
onReorder={(next) =>
|
|
93
|
+
setItems(next.map((item, index) => ({ ...item, position: index })))
|
|
94
|
+
}
|
|
95
|
+
renderItem={(item) => (
|
|
96
|
+
<div style={{ padding: 12, border: "1px solid #e5e7eb", borderRadius: 8 }}>
|
|
97
|
+
{item.title}
|
|
98
|
+
</div>
|
|
99
|
+
)}
|
|
100
|
+
showDropIndicator
|
|
101
|
+
gap={8}
|
|
102
|
+
/>
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Quick start: drag handle and multi-drag
|
|
108
|
+
|
|
109
|
+
```tsx
|
|
108
110
|
<DragDropList
|
|
109
111
|
items={items}
|
|
110
112
|
onReorder={handleReorder}
|
|
@@ -112,178 +114,181 @@ export default function TodoList() {
|
|
|
112
114
|
dragHandle="[data-drag-handle]"
|
|
113
115
|
selectedIds={selectedIds}
|
|
114
116
|
multiDragEnabled
|
|
117
|
+
liveReorder
|
|
115
118
|
/>
|
|
116
119
|
```
|
|
117
|
-
|
|
118
|
-
Behavior notes:
|
|
119
|
-
|
|
120
|
+
|
|
121
|
+
Behavior notes:
|
|
122
|
+
|
|
120
123
|
- `dragHandle` is optional. If provided, drag starts only from matching descendants.
|
|
121
124
|
- `multiDragEnabled` is opt-in. Without it, behavior remains single-item drag.
|
|
122
125
|
- `selectedIds` is consumed only when multi-drag is enabled.
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
import {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
type
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
{ id: "
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
"task-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
|
188
|
-
|
|
|
189
|
-
| `
|
|
190
|
-
| `
|
|
191
|
-
| `
|
|
192
|
-
| `
|
|
193
|
-
| `
|
|
194
|
-
| `
|
|
195
|
-
| `
|
|
196
|
-
| `
|
|
197
|
-
| `
|
|
198
|
-
| `
|
|
199
|
-
| `
|
|
200
|
-
| `
|
|
201
|
-
| `
|
|
202
|
-
| `
|
|
203
|
-
| `
|
|
204
|
-
| `
|
|
205
|
-
| `
|
|
126
|
+
- `liveReorder` is opt-in. Without it, reorder commits on drop (existing behavior).
|
|
127
|
+
|
|
128
|
+
## Quick start: Kanban board
|
|
129
|
+
|
|
130
|
+
```tsx
|
|
131
|
+
import { useCallback, useState } from "react";
|
|
132
|
+
import {
|
|
133
|
+
KanbanBoard,
|
|
134
|
+
applyDragResult,
|
|
135
|
+
type DropResult,
|
|
136
|
+
type KanbanBoardState,
|
|
137
|
+
} from "react-dragdrop-kit/kanban";
|
|
138
|
+
|
|
139
|
+
export default function Board() {
|
|
140
|
+
const [state, setState] = useState<KanbanBoardState>({
|
|
141
|
+
columns: [
|
|
142
|
+
{ id: "todo", title: "To Do", cardIds: ["task-1", "task-2"] },
|
|
143
|
+
{ id: "done", title: "Done", cardIds: [] },
|
|
144
|
+
],
|
|
145
|
+
cards: {
|
|
146
|
+
"task-1": { id: "task-1", title: "Design landing page" },
|
|
147
|
+
"task-2": { id: "task-2", title: "Implement auth" },
|
|
148
|
+
},
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
const handleDragEnd = useCallback(
|
|
152
|
+
(result: DropResult, stateBefore: KanbanBoardState) => {
|
|
153
|
+
if (!result.destination) return;
|
|
154
|
+
setState(applyDragResult(stateBefore, result));
|
|
155
|
+
},
|
|
156
|
+
[]
|
|
157
|
+
);
|
|
158
|
+
|
|
159
|
+
return (
|
|
160
|
+
<KanbanBoard
|
|
161
|
+
state={state}
|
|
162
|
+
onDragEnd={handleDragEnd}
|
|
163
|
+
renderColumn={(column) => <div style={{ padding: 12 }}>{column.title}</div>}
|
|
164
|
+
renderCard={(card) => <div style={{ padding: 12 }}>{card.title}</div>}
|
|
165
|
+
/>
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
## API reference: list module
|
|
171
|
+
|
|
172
|
+
### Core types
|
|
173
|
+
|
|
174
|
+
```ts
|
|
175
|
+
type DraggableItem = {
|
|
176
|
+
id: string;
|
|
177
|
+
position: number;
|
|
178
|
+
[key: string]: any;
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
type OrderUpdate = {
|
|
182
|
+
id: string;
|
|
183
|
+
newPosition: number;
|
|
184
|
+
moved?: boolean;
|
|
185
|
+
};
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### DragDropList props
|
|
189
|
+
|
|
190
|
+
| Prop | Type | Default | Description |
|
|
191
|
+
| --- | --- | --- | --- |
|
|
192
|
+
| `items` | `T[]` | Required | Controlled items. Each item must include `id` and `position`. |
|
|
193
|
+
| `onReorder` | `(newItems: T[], orderUpdates: OrderUpdate[]) => void` | Required | Fired after successful drop/reorder. |
|
|
194
|
+
| `renderItem` | `(item: T, index: number) => ReactNode` | Required | Item renderer. |
|
|
195
|
+
| `containerClassName` | `string` | `""` | Class name for container. |
|
|
196
|
+
| `containerStyle` | `React.CSSProperties` | `{}` | Inline style for container. |
|
|
197
|
+
| `itemClassName` | `string` | `""` | Class for each draggable wrapper. |
|
|
198
|
+
| `itemStyle` | `React.CSSProperties` | `{}` | Style for each draggable wrapper. |
|
|
199
|
+
| `dragPreviewClassName` | `string` | `""` | Class for generated drag preview. |
|
|
200
|
+
| `dragPreviewStyle` | `React.CSSProperties` | `{}` | Style for generated drag preview. |
|
|
201
|
+
| `onDragStart` | `(item: T, index: number) => void` | `undefined` | Callback on item drag start. |
|
|
202
|
+
| `onDragEnd` | `(item: T, index: number) => void` | `undefined` | Callback on item drag end. |
|
|
203
|
+
| `disabled` | `boolean` | `false` | Disables list drag/drop. |
|
|
204
|
+
| `gap` | `number \| string` | `undefined` | Gap applied to container. |
|
|
205
|
+
| `direction` | `"vertical" \| "horizontal"` | `"vertical"` | Layout and closest-edge interpretation. |
|
|
206
|
+
| `showDropIndicator` | `boolean` | `false` | Enables drop indicator line. |
|
|
207
|
+
| `dropIndicatorClassName` | `string` | `""` | Class for drop indicator. |
|
|
208
|
+
| `dropIndicatorStyle` | `React.CSSProperties` | `{}` | Style for drop indicator. |
|
|
209
|
+
| `dropIndicatorPosition` | `"top" \| "bottom"` | `"bottom"` | Indicator position for hovered target item. |
|
|
206
210
|
| `dragHandle` | `string` | `undefined` | CSS selector for handle-only dragging. |
|
|
207
211
|
| `selectedIds` | `string[]` | `[]` | Selected IDs used by multi-drag. |
|
|
208
212
|
| `multiDragEnabled` | `boolean` | `false` | Enables grouped drag behavior. |
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
-
|
|
218
|
-
-
|
|
219
|
-
-
|
|
220
|
-
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
- `examples/
|
|
228
|
-
- `examples/
|
|
229
|
-
- `examples/
|
|
230
|
-
- `examples/
|
|
231
|
-
- `examples/kanban/
|
|
232
|
-
- `examples/kanban/
|
|
233
|
-
- `examples/kanban/
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
-
|
|
239
|
-
|
|
240
|
-
- `apps/demo/src/examples/
|
|
241
|
-
- `apps/demo/src/examples/
|
|
242
|
-
- `apps/demo/src/examples/
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
- `
|
|
252
|
-
- `
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
- `react-dragdrop-kit
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
- [
|
|
278
|
-
- [
|
|
279
|
-
- [
|
|
280
|
-
- [
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
- [
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
213
|
+
| `liveReorder` | `boolean` | `false` | Reorders list in real time during drag-over. |
|
|
214
|
+
|
|
215
|
+
## API reference: Kanban module
|
|
216
|
+
|
|
217
|
+
The full Kanban API is documented in [docs/kanban.md](./docs/kanban.md).
|
|
218
|
+
|
|
219
|
+
Exports:
|
|
220
|
+
|
|
221
|
+
- Components: `KanbanBoard`, `KanbanColumnView`, `KanbanCardView`
|
|
222
|
+
- Hooks: `useKanbanDnd`, `useAutoscroll`
|
|
223
|
+
- A11y: `AnnouncerProvider`, `useAnnouncer`, `announcements`
|
|
224
|
+
- Utils: `applyDragResult`, `reorderArray`
|
|
225
|
+
- Types: `KanbanBoardState`, `DropResult`, `KanbanCard`, `KanbanColumn`, and more
|
|
226
|
+
|
|
227
|
+
## Examples
|
|
228
|
+
|
|
229
|
+
### Repository examples
|
|
230
|
+
|
|
231
|
+
- `examples/basic-example.tsx`
|
|
232
|
+
- `examples/advanced-features.tsx`
|
|
233
|
+
- `examples/material-ui-example.tsx`
|
|
234
|
+
- `examples/tailwind-example.tsx`
|
|
235
|
+
- `examples/kanban/basic-kanban.tsx`
|
|
236
|
+
- `examples/kanban/rich-cards-kanban.tsx`
|
|
237
|
+
- `examples/kanban/themed-kanban.tsx`
|
|
238
|
+
- `examples/kanban/accessible-kanban.tsx`
|
|
239
|
+
|
|
240
|
+
### Demo examples
|
|
241
|
+
|
|
242
|
+
- List/grid examples under `apps/demo/src/examples/*`
|
|
243
|
+
- Kanban demos:
|
|
244
|
+
- `apps/demo/src/examples/BasicKanban/index.tsx`
|
|
245
|
+
- `apps/demo/src/examples/RichKanban/index.tsx`
|
|
246
|
+
- `apps/demo/src/examples/SwimlanesKanban/index.tsx`
|
|
247
|
+
- `apps/demo/src/examples/WipLimitsKanban/index.tsx`
|
|
248
|
+
|
|
249
|
+
## Migration notes
|
|
250
|
+
|
|
251
|
+
### From react-beautiful-dnd
|
|
252
|
+
|
|
253
|
+
High-level mapping for Kanban use cases:
|
|
254
|
+
|
|
255
|
+
- `DragDropContext` -> `KanbanBoard`
|
|
256
|
+
- `Droppable` -> `KanbanColumnView`
|
|
257
|
+
- `Draggable` -> `KanbanCardView`
|
|
258
|
+
|
|
259
|
+
Important differences:
|
|
260
|
+
|
|
261
|
+
1. State is normalized (`columns` + `cards`) instead of nested.
|
|
262
|
+
2. IDs are explicit and owned by your app.
|
|
263
|
+
3. Rendering is done via render functions (`renderColumn`, `renderCard`).
|
|
264
|
+
|
|
265
|
+
## Development notes
|
|
266
|
+
|
|
267
|
+
### React Strict Mode
|
|
268
|
+
|
|
269
|
+
In development, React Strict Mode can mount effects twice.
|
|
270
|
+
Ensure listener setup and cleanup are idempotent when integrating custom logic.
|
|
271
|
+
|
|
272
|
+
## Bundle size
|
|
273
|
+
|
|
274
|
+
Approximate minified sizes:
|
|
275
|
+
|
|
276
|
+
- `react-dragdrop-kit`: about 5KB
|
|
277
|
+
- `react-dragdrop-kit/kanban`: about 9KB
|
|
278
|
+
|
|
279
|
+
## Documentation and links
|
|
280
|
+
|
|
281
|
+
- [Kanban guide](./docs/kanban.md)
|
|
282
|
+
- [Known issues](./KNOWN_ISSUES.md)
|
|
283
|
+
- [Changelog](./packages/react-dragdrop-kit/CHANGELOG.md)
|
|
284
|
+
- [Examples folder](./examples)
|
|
285
|
+
- [Demo app](https://react-dragdrop-kit.netlify.app/)
|
|
286
|
+
|
|
287
|
+
## Support
|
|
288
|
+
|
|
289
|
+
- [Report issues](https://github.com/Yourstruggle11/react-dragdrop-kit/issues)
|
|
290
|
+
- [Request features](https://github.com/Yourstruggle11/react-dragdrop-kit/issues/new)
|
|
291
|
+
|
|
292
|
+
## License
|
|
293
|
+
|
|
289
294
|
MIT
|
package/dist/index.esm.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import e,{useRef as t,useState as n,useCallback as a,useEffect as r}from"react";import{draggable as i,dropTargetForElements as o,monitorForElements as d}from"@atlaskit/pragmatic-drag-and-drop/element/adapter";import{combine as s}from"@atlaskit/pragmatic-drag-and-drop/combine";import{attachClosestEdge as l,extractClosestEdge as c}from"@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge";const g={container:{default:{minHeight:"200px",transition:"all 0.2s ease",borderRadius:"8px",border:"1px solid #e2e8f0",backgroundColor:"#ffffff",display:"flex",flexDirection:"column",gap:"16px",padding:"16px"},dragging:{backgroundColor:"rgba(66, 153, 225, 0.05)",borderColor:"#3182ce"},horizontal:{flexDirection:"row",flexWrap:"wrap"}},item:{default:{transition:"all 0.2s ease",cursor:"grab",userSelect:"none",position:"relative"},dragging:{opacity:.5,cursor:"grabbing"},hover:{transform:"scale(1.02)",boxShadow:"0 4px 6px rgba(0, 0, 0, 0.1)"},disabled:{cursor:"not-allowed",opacity:.6}},preview:{position:"fixed",pointerEvents:"none",zIndex:9999,opacity:.8,transform:"rotate(2deg)",boxShadow:"0 10px 20px rgba(0, 0, 0, 0.15)"},dropIndicator:{position:"absolute",height:"2px",backgroundColor:"#3182ce",left:0,right:0,zIndex:10,transition:"all 0.2s ease"}},m="draggable-item";function u({item:d,index:c,children:u,className:p="",style:f={},dragPreviewClassName:b="",dragPreviewStyle:v={},onDragStart:h,onDragEnd:x,disabled:D=!1,showDropIndicator:y=!1,dropIndicatorClassName:I="",dropIndicatorStyle:w={},dropIndicatorPosition:S="bottom",direction:j="vertical",dragHandle:O}){const N=t(null),[C,E]=n(!1),[P,M]=n(!1),[k,z]=n(null),H=a(e=>{if(D)return()=>{};const t=O?e.querySelector(O):void 0;return i({element:e,dragHandle:null!=t?t:void 0,canDrag:()=>!O||Boolean(t),getInitialData:()=>({type:m,id:d.id,index:c}),onGenerateDragPreview:({nativeSetDragImage:t})=>{const n=e.cloneNode(!0),a=Object.assign(Object.assign({},g.preview),v);b&&(n.className=b),Object.assign(n.style,a,{width:`${(null==e?void 0:e.offsetWidth)||100}px`,height:`${(null==e?void 0:e.offsetHeight)||50}px`}),document.body.appendChild(n),t&&t(n,20,20),requestAnimationFrame(()=>n.remove())},onDragStart:()=>{E(!0),null==h||h(d,c)},onDrop:()=>{E(!1),null==x||x(d,c)}})},[d,c,O,b,v,h,x,D]),L=a(e=>D?()=>{}:o({element:e,getData:({input:e,element:t})=>{const n={type:m,id:d.id,index:c};return l(n,{input:e,element:t,allowedEdges:[..."horizontal"===j?["left","right"]:["top","bottom"]]})},canDrop:({source:e})=>{var t;return(null===(t=e.data)||void 0===t?void 0:t.type)===m},getIsSticky:()=>!0,onDragEnter:({source:e,self:t})=>{var n,a;(null===(n=e.data)||void 0===n?void 0:n.id)!==(null===(a=t.data)||void 0===a?void 0:a.id)&&(M(!0),y&&z(S))},onDragLeave:()=>{M(!1),z(null)},onDrop:()=>{M(!1),z(null)}}),[d.id,c,j,D,y,S]);return r(()=>{const e=N.current;if(e)return e.setAttribute("data-index",c.toString()),D?()=>{}:s(H(e),L(e))},[c,H,L,D]),e.createElement("div",{ref:N,className:p,style:(()=>{const e=Object.assign({},g.item.default);return D?Object.assign(e,g.item.disabled):C?Object.assign(e,g.item.dragging):P&&Object.assign(e,g.item.hover),Object.assign(Object.assign({},e),f)})()},y&&"top"===k&&e.createElement("div",{className:I,style:Object.assign(Object.assign(Object.assign({},g.dropIndicator),w),{top:-1})}),u,y&&"bottom"===k&&e.createElement("div",{className:I,style:Object.assign(Object.assign(Object.assign({},g.dropIndicator),w),{bottom:-1})}))}function p(e,t,n){const a=Array.from(e),[r]=a.splice(t,1);return a.splice(n,0,r),a}function f(e){const{itemCount:t,sourceIndex:n,rawDestinationIndex:a,isSameList:r}=e;if(t<=0)return 0;const i=t,o=Math.max(0,Math.min(a,i)),d=r&&n<o?o-1:o,s=r?t-1:t;return Math.max(0,Math.min(d,s))}function b({items:e,onReorder:t,disabled:n=!1,direction:i="vertical",selectedIds:o=[],multiDragEnabled:s=!1}){const l=a(({location:n,source:a})=>{var r,d,l;const g=null===(r=a.data)||void 0===r?void 0:r.id,m=null===(d=a.data)||void 0===d?void 0:d.index;if(void 0===g||void 0===m)return;const{dropTargets:u}=n.current,b=u.find(e=>{var t,n;return"draggable-item"===(null===(t=e.data)||void 0===t?void 0:t.type)&&(null===(n=e.data)||void 0===n?void 0:n.id)!==g}),v=u.find(e=>{var t;return"container"===(null===(t=e.data)||void 0===t?void 0:t.type)});if(!b&&!v)return;let h=e.length;if(b){const e=Number(null===(l=b.data)||void 0===l?void 0:l.index);if(!Number.isFinite(e))return;const t=c(b.data);h="bottom"===t||"horizontal"===i&&"right"===t?e+1:e}const x=[...e];let D=e;if(s){const t=new Set(o);t.has(g)||t.clear(),t.add(g);const n=e.map((e,n)=>t.has(e.id)?n:-1).filter(e=>-1!==e);if(n.length>1)D=function(e,t,n){const a=Array.from(new Set(t.filter(t=>t>=0&&t<e.length))).sort((e,t)=>e-t);if(0===a.length)return e;const r=new Set(a),i=a.map(t=>e[t]),o=e.filter((e,t)=>!r.has(t)),d=Math.max(0,Math.min(n,e.length)),s=a.filter(e=>e<d).length,l=Math.max(0,Math.min(d-s,o.length)),c=[...o];return c.splice(l,0,...i),c}(e,n,h);else{const t=f({itemCount:e.length,sourceIndex:m,rawDestinationIndex:h,isSameList:!0});D=p(e,m,t)}}else{const t=f({itemCount:e.length,sourceIndex:m,rawDestinationIndex:h,isSameList:!0});D=p(e,m,t)}const y=D.some((e,t)=>{var n;return e.id!==(null===(n=x[t])||void 0===n?void 0:n.id)});if(!y)return;const I=function(e,t){const n=new Map(e.map((e,t)=>[e.id,t]));return t.flatMap((e,t)=>{const a=n.get(e.id);return void 0===a||a===t?[]:[{id:e.id,newPosition:t,moved:!0}]})}(x,D);t(D,I)},[e,t,i,o,s]);return r(()=>{if(!n)return d({onDrop:l})},[n,l]),a(()=>{},[])}function v({items:i,onReorder:d,renderItem:s,containerClassName:l="",containerStyle:c={},itemClassName:m="",itemStyle:p={},dragPreviewClassName:f="",dragPreviewStyle:v={},onDragStart:h,onDragEnd:x,disabled:D=!1,gap:y,direction:I="vertical",showDropIndicator:w=!1,dropIndicatorClassName:S="",dropIndicatorStyle:j={},dropIndicatorPosition:O="bottom",dragHandle:N,selectedIds:C=[],multiDragEnabled:E=!1}){const P=t(null);b({items:i,onReorder:d,disabled:D,direction:I,selectedIds:C,multiDragEnabled:E});const[M,k]=n(!1),z=a(e=>D?()=>{}:o({element:e,getData:()=>({type:"container"}),onDragEnter:()=>k(!0),onDragLeave:()=>k(!1),onDrop:()=>k(!1)}),[D]);return r(()=>{const e=P.current;if(e&&!D)return z(e)},[z,D]),e.createElement("div",{ref:P,className:l,style:(()=>{const e=Object.assign({},g.container.default);return"horizontal"===I&&Object.assign(e,g.container.horizontal),M&&Object.assign(e,g.container.dragging),void 0!==y&&(e.gap="number"==typeof y?`${y}px`:y),Object.assign(Object.assign({},e),c)})()},i.map((t,n)=>e.createElement(u,{key:t.id,item:t,index:n,className:m,style:p,dragPreviewClassName:f,dragPreviewStyle:v,onDragStart:h,onDragEnd:x,disabled:D,showDropIndicator:w,dropIndicatorClassName:S,dropIndicatorStyle:j,dropIndicatorPosition:O,direction:I,dragHandle:N},s(t,n))))}export{v as DragDropList,u as DraggableItemWrapper,g as defaultStyles,b as useDragDropMonitor};
|
|
1
|
+
import e,{useRef as t,useState as n,useCallback as r,useEffect as i}from"react";import{draggable as o,dropTargetForElements as a,monitorForElements as d}from"@atlaskit/pragmatic-drag-and-drop/element/adapter";import{combine as l}from"@atlaskit/pragmatic-drag-and-drop/combine";import{attachClosestEdge as s,extractClosestEdge as c}from"@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge";const u={container:{default:{minHeight:"200px",transition:"all 0.2s ease",borderRadius:"8px",border:"1px solid #e2e8f0",backgroundColor:"#ffffff",display:"flex",flexDirection:"column",gap:"16px",padding:"16px"},dragging:{backgroundColor:"rgba(66, 153, 225, 0.05)",borderColor:"#3182ce"},horizontal:{flexDirection:"row",flexWrap:"wrap"}},item:{default:{transition:"all 0.2s ease",cursor:"grab",userSelect:"none",position:"relative"},dragging:{opacity:.5,cursor:"grabbing"},hover:{transform:"scale(1.02)",boxShadow:"0 4px 6px rgba(0, 0, 0, 0.1)"},disabled:{cursor:"not-allowed",opacity:.6}},preview:{position:"fixed",pointerEvents:"none",zIndex:9999,opacity:.8,transform:"rotate(2deg)",boxShadow:"0 10px 20px rgba(0, 0, 0, 0.15)"},dropIndicator:{position:"absolute",height:"2px",backgroundColor:"#3182ce",left:0,right:0,zIndex:10,transition:"all 0.2s ease"}},g="draggable-item";function m({item:d,index:c,children:m,className:p="",style:v={},dragPreviewClassName:f="",dragPreviewStyle:I={},onDragStart:b,onDragEnd:h,disabled:x=!1,showDropIndicator:w=!1,dropIndicatorClassName:D="",dropIndicatorStyle:y={},dropIndicatorPosition:S="bottom",direction:E="vertical",dragHandle:O}){const R=t(null),[j,C]=n(!1),[N,P]=n(!1),[M,z]=n(null),K=r(e=>{if(x)return()=>{};const t=O?e.querySelector(O):void 0;return o({element:e,dragHandle:null!=t?t:void 0,canDrag:()=>!O||Boolean(t),getInitialData:()=>({type:g,id:d.id,index:c}),onGenerateDragPreview:({nativeSetDragImage:t})=>{const n=e.cloneNode(!0),r=Object.assign(Object.assign({},u.preview),I);f&&(n.className=f),Object.assign(n.style,r,{width:`${(null==e?void 0:e.offsetWidth)||100}px`,height:`${(null==e?void 0:e.offsetHeight)||50}px`}),document.body.appendChild(n),t&&t(n,20,20),requestAnimationFrame(()=>n.remove())},onDragStart:()=>{C(!0),null==b||b(d,c)},onDrop:()=>{C(!1),null==h||h(d,c)}})},[d,c,O,f,I,b,h,x]),k=r(e=>x?()=>{}:a({element:e,getData:({input:e,element:t})=>{const n={type:g,id:d.id,index:c};return s(n,{input:e,element:t,allowedEdges:[..."horizontal"===E?["left","right"]:["top","bottom"]]})},canDrop:({source:e})=>{var t,n;return(null===(t=e.data)||void 0===t?void 0:t.type)===g&&(null===(n=e.data)||void 0===n?void 0:n.id)!==d.id},onDragEnter:({source:e,self:t})=>{var n,r;(null===(n=e.data)||void 0===n?void 0:n.id)!==(null===(r=t.data)||void 0===r?void 0:r.id)&&(P(!0),w&&z(S))},onDragLeave:()=>{P(!1),z(null)},onDrop:()=>{P(!1),z(null)}}),[d.id,c,E,x,w,S]);return i(()=>{const e=R.current;if(e)return x?()=>{}:l(K(e),k(e))},[c,K,k,x]),e.createElement("div",{ref:R,"data-index":c,"data-rdk-item-id":d.id,className:p,style:(()=>{const e=Object.assign({},u.item.default);return x?Object.assign(e,u.item.disabled):j?Object.assign(e,u.item.dragging):N&&Object.assign(e,u.item.hover),Object.assign(Object.assign({},e),v)})()},w&&"top"===M&&e.createElement("div",{className:D,style:Object.assign(Object.assign(Object.assign({},u.dropIndicator),y),{top:-1})}),m,w&&"bottom"===M&&e.createElement("div",{className:D,style:Object.assign(Object.assign(Object.assign({},u.dropIndicator),y),{bottom:-1})}))}function p(e,t){const n=new Map(e.map((e,t)=>[e.id,t]));return t.flatMap((e,t)=>{const r=n.get(e.id);return void 0===r||r===t?[]:[{id:e.id,newPosition:t,moved:!0}]})}function v(e,t){const n=e.element.getBoundingClientRect(),r=n.left+n.width/2,i=n.top+n.height/2;return Math.pow(t.clientX-r,2)+Math.pow(t.clientY-i,2)}function f(e,t){return e.length!==t.length||t.some((t,n)=>{var r;return t.id!==(null===(r=e[n])||void 0===r?void 0:r.id)})}function I(e){const{items:t,sourceId:n,selectedIds:r,multiDragEnabled:i}=e;if(!i)return new Set([n]);const o=new Set(t.map(e=>e.id)),a=new Set(r.filter(e=>o.has(e)));return a.has(n)?a:new Set([n])}function b(e){const{items:t,sourceId:n,sourceIndex:r,rawDestinationIndex:i,selectedIds:o,multiDragEnabled:a}=e;if(a){const e=new Set(o);e.has(n)||e.clear(),e.add(n);const r=t.map((t,n)=>e.has(t.id)?n:-1).filter(e=>-1!==e);if(r.length>1)return function(e,t,n){const r=Array.from(new Set(t.filter(t=>t>=0&&t<e.length))).sort((e,t)=>e-t);if(0===r.length)return e;const i=new Set(r),o=r.map(t=>e[t]),a=e.filter((e,t)=>!i.has(t)),d=Math.max(0,Math.min(n,e.length)),l=r.filter(e=>e<d).length,s=Math.max(0,Math.min(d-l,a.length)),c=[...a];return c.splice(s,0,...o),c}(t,r,i)}const d=function(e){const{itemCount:t,sourceIndex:n,rawDestinationIndex:r,isSameList:i}=e;if(t<=0)return 0;const o=t,a=Math.max(0,Math.min(r,o)),d=i&&n<a?a-1:a,l=i?t-1:t;return Math.max(0,Math.min(d,l))}({itemCount:t.length,sourceIndex:r,rawDestinationIndex:i,isSameList:!0});return function(e,t,n){const r=Array.from(e),[i]=r.splice(t,1);return r.splice(n,0,i),r}(t,r,d)}function h(e){var t,n;const{location:r,sourceId:i,sourceIndex:o,direction:a,items:d,excludedIds:l}=e,{dropTargets:s,input:u}=r,g=function(e){const{dropTargets:t,input:n,sourceId:r,excludedIds:i}=e,o=t.filter(e=>{var t,n,o;if("draggable-item"!==(null===(t=e.data)||void 0===t?void 0:t.type))return!1;const a=String(null!==(o=null===(n=e.data)||void 0===n?void 0:n.id)&&void 0!==o?o:"");return!(!a||a===r||i.has(a))});return 0===o.length?null:1===o.length?o[0]:o.reduce((e,t)=>v(t,n)<v(e,n)?t:e)}({dropTargets:s,input:u,sourceId:i,excludedIds:l}),m=s.find(e=>{var t;return"container"===(null===(t=e.data)||void 0===t?void 0:t.type)});if(!g&&!m)return null;if(!g){if(!m)return null;const e=function(e){const{containerElement:t,input:n,direction:r,items:i,excludedIds:o}=e,a=new Map(i.map((e,t)=>[e.id,t])),d=Array.from(t.querySelectorAll("[data-rdk-item-id]"));if(0===d.length)return 0;const l="horizontal"===r?n.clientX:n.clientY,s=d.map(e=>{const t=e.getAttribute("data-rdk-item-id");if(!t||o.has(t))return null;const i=a.get(t);if(void 0===i)return null;const d=e.getBoundingClientRect(),l=d.left+d.width/2,s=d.top+d.height/2;return{index:i,distance:Math.pow(n.clientX-l,2)+Math.pow(n.clientY-s,2),centerOnAxis:"horizontal"===r?l:s}}).filter(e=>null!==e);if(0===s.length)return null;const c=s.reduce((e,t)=>t.distance<e.distance?t:e);return l>=c.centerOnAxis?c.index+1:c.index}({containerElement:m.element,input:u,direction:a,items:d,excludedIds:l}),t=null!=e?e:d.length;return{rawDestinationIndex:t,previewKey:`container:${t}`}}const p=String(null!==(n=null===(t=g.data)||void 0===t?void 0:t.id)&&void 0!==n?n:"");if(!p)return null;const f=d.findIndex(e=>e.id===p);if(-1===f)return null;const I=c(g.data);let b;if(o<f)b=!0;else if(o>f)b=!1;else if(null===I){const e=g.element.getBoundingClientRect(),t="horizontal"===a?e.left+e.width/2:e.top+e.height/2;b=("horizontal"===a?u.clientX:u.clientY)>=t}else b="bottom"===I||"horizontal"===a&&"right"===I;return{rawDestinationIndex:b?f+1:f,previewKey:`item:${p}:${b?"after":"before"}`}}function x({items:e,onReorder:n,disabled:o=!1,direction:a="vertical",selectedIds:l=[],multiDragEnabled:s=!1,liveReorder:c=!1}){const u=t(e),g=t(n),m=t({direction:a,selectedIds:l,multiDragEnabled:s,liveReorder:c}),v=t({sourceId:null,movingIds:null,originalItems:null,didLiveReorder:!1,lastPreviewKey:null});i(()=>{u.current=e,g.current=n,m.current={direction:a,selectedIds:l,multiDragEnabled:s,liveReorder:c}},[e,n,a,l,s,c]);const x=r(()=>{v.current={sourceId:null,movingIds:null,originalItems:null,didLiveReorder:!1,lastPreviewKey:null}},[]),w=r((e,t)=>{const n=u.current.findIndex(t=>t.id===e);if(-1!==n)return n;const r=Number(t);return Number.isFinite(r)?r:-1},[]),D=r(e=>{const t=u.current,{selectedIds:n,multiDragEnabled:r}=m.current;return I({items:t,sourceId:e,selectedIds:n,multiDragEnabled:r})},[]),y=r(e=>{const t=v.current.movingIds;return t?new Set(t):D(e)},[D]),S=r(({sourceId:e,sourceIndex:t,rawDestinationIndex:n})=>{const r=[...u.current],{selectedIds:i,multiDragEnabled:o}=m.current,a=b({items:r,sourceId:e,sourceIndex:t,rawDestinationIndex:n,selectedIds:i,multiDragEnabled:o});if(!f(r,a))return!1;const d=p(r,a);return u.current=a,g.current(a,d),!0},[]),E=r(({source:e})=>{var t,n;if("draggable-item"!==(null===(t=e.data)||void 0===t?void 0:t.type))return;const r=null===(n=e.data)||void 0===n?void 0:n.id;if(!r)return;const i=u.current,{selectedIds:o,multiDragEnabled:a}=m.current,d=I({items:i,sourceId:r,selectedIds:o,multiDragEnabled:a});v.current={sourceId:r,movingIds:d,originalItems:m.current.liveReorder?[...i]:null,didLiveReorder:!1,lastPreviewKey:null}},[]),O=r(({location:e,source:t})=>{var n,r,i;if("draggable-item"!==(null===(n=t.data)||void 0===n?void 0:n.type))return;const{direction:o,liveReorder:a}=m.current;if(!a)return;const d=null===(r=t.data)||void 0===r?void 0:r.id;if(!d)return;const l=w(d,null===(i=t.data)||void 0===i?void 0:i.index);if(l<0)return;const s=u.current,c=y(d),g=h({location:e.current,sourceId:d,sourceIndex:l,direction:o,items:s,excludedIds:c});if(!g)return;if(v.current.lastPreviewKey===g.previewKey)return;const p=S({sourceId:d,sourceIndex:l,rawDestinationIndex:g.rawDestinationIndex});v.current.lastPreviewKey=g.previewKey,p&&(v.current.didLiveReorder=!0)},[w,y,S]),R=r(({location:e,source:t})=>{var n,r,i;if("draggable-item"!==(null===(n=t.data)||void 0===n?void 0:n.type))return void x();const o=null===(r=t.data)||void 0===r?void 0:r.id;if(!o)return void x();const{direction:a,liveReorder:d}=m.current,l=u.current,s=y(o),c=w(o,null===(i=t.data)||void 0===i?void 0:i.index);if(c<0)return void x();const I=h({location:e.current,sourceId:o,sourceIndex:c,direction:a,items:l,excludedIds:s});if(!I){const{originalItems:e,didLiveReorder:t}=v.current;if(d&&t&&e){const t=[...u.current];if(f(t,e)){const n=p(t,e);u.current=e,g.current(e,n)}}return void x()}const{didLiveReorder:b,lastPreviewKey:D}=v.current;d&&b&&D===I.previewKey||S({sourceId:o,sourceIndex:c,rawDestinationIndex:I.rawDestinationIndex}),x()},[y,w,S,x]);return i(()=>{if(!o)return d({onDragStart:E,onDropTargetChange:O,onDrop:R})},[o,E,O,R]),r(()=>{},[])}function w({items:o,onReorder:d,renderItem:l,containerClassName:s="",containerStyle:c={},itemClassName:g="",itemStyle:p={},dragPreviewClassName:v="",dragPreviewStyle:f={},onDragStart:I,onDragEnd:b,disabled:h=!1,gap:w,direction:D="vertical",showDropIndicator:y=!1,dropIndicatorClassName:S="",dropIndicatorStyle:E={},dropIndicatorPosition:O="bottom",dragHandle:R,selectedIds:j=[],multiDragEnabled:C=!1,liveReorder:N=!1}){const P=t(null);x({items:o,onReorder:d,disabled:h,direction:D,selectedIds:j,multiDragEnabled:C,liveReorder:N});const[M,z]=n(!1),K=r(e=>h?()=>{}:a({element:e,getData:()=>({type:"container"}),onDragEnter:()=>z(!0),onDragLeave:()=>z(!1),onDrop:()=>z(!1)}),[h]);return i(()=>{const e=P.current;if(e&&!h)return K(e)},[K,h]),e.createElement("div",{ref:P,className:s,style:(()=>{const e=Object.assign({},u.container.default);return"horizontal"===D&&Object.assign(e,u.container.horizontal),M&&Object.assign(e,u.container.dragging),void 0!==w&&(e.gap="number"==typeof w?`${w}px`:w),Object.assign(Object.assign({},e),c)})()},o.map((t,n)=>e.createElement(m,{key:t.id,item:t,index:n,className:g,style:p,dragPreviewClassName:v,dragPreviewStyle:f,onDragStart:I,onDragEnd:b,disabled:h,showDropIndicator:y,dropIndicatorClassName:S,dropIndicatorStyle:E,dropIndicatorPosition:O,direction:D,dragHandle:R},l(t,n))))}export{w as DragDropList,m as DraggableItemWrapper,u as defaultStyles,x as useDragDropMonitor};
|
|
2
2
|
//# sourceMappingURL=index.esm.js.map
|