react-dragdrop-kit 1.0.0 → 1.2.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 +223 -82
- 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/jest.setup.d.ts +1 -0
- package/dist/kanban.esm.js +2 -0
- package/dist/kanban.esm.js.map +1 -0
- package/dist/kanban.js +2 -0
- package/dist/kanban.js.map +1 -0
- package/dist/{components → src/components}/DragDropList.d.ts +1 -2
- package/dist/{components → src/components}/DraggableItemWrapper.d.ts +1 -2
- package/dist/{hooks → src/hooks}/useDragDropMonitor.d.ts +0 -1
- package/dist/{index.d.ts → src/index.d.ts} +0 -1
- package/dist/src/kanban/a11y/Announcer.d.ts +37 -0
- package/dist/src/kanban/a11y/useLiveRegion.d.ts +17 -0
- package/dist/src/kanban/components/KanbanBoard.d.ts +8 -0
- package/dist/src/kanban/components/KanbanCardView.d.ts +8 -0
- package/dist/src/kanban/components/KanbanColumnView.d.ts +8 -0
- package/dist/src/kanban/context.d.ts +13 -0
- package/dist/src/kanban/hooks/useAutoscroll.d.ts +10 -0
- package/dist/src/kanban/hooks/useKanbanDnd.d.ts +16 -0
- package/dist/src/kanban/index.d.ts +15 -0
- package/dist/src/kanban/types.d.ts +185 -0
- package/dist/src/kanban/utils/dndMath.d.ts +61 -0
- package/dist/src/kanban/utils/dom.d.ts +62 -0
- package/dist/src/kanban/utils/reorder.d.ts +32 -0
- package/dist/{styles → src/styles}/defaultStyles.d.ts +0 -1
- package/dist/{types → src/types}/index.d.ts +2 -1
- package/dist/{utils → src/utils}/order.d.ts +0 -1
- package/package.json +15 -5
- package/dist/components/DragDropList.d.ts.map +0 -1
- package/dist/components/DraggableItemWrapper.d.ts.map +0 -1
- package/dist/hooks/useDragDropMonitor.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/styles/defaultStyles.d.ts.map +0 -1
- package/dist/types/index.d.ts.map +0 -1
- package/dist/utils/order.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# react-dragdrop-kit
|
|
2
2
|
|
|
3
|
-
A flexible and lightweight **drag-and-drop toolkit for React**. Build **sortable lists, grids, and boards** with a simple, fully-controlled API and customizable previews. Powered by Atlassian
|
|
3
|
+
A flexible and lightweight **drag-and-drop toolkit for React**. Build **sortable lists, grids, and Kanban boards** with a simple, fully-controlled API and customizable previews. Powered by Atlassian's pragmatic drag-and-drop under the hood.
|
|
4
4
|
|
|
5
5
|
<p>
|
|
6
6
|
<a href="https://www.npmjs.com/package/react-dragdrop-kit"><img alt="npm" src="https://img.shields.io/npm/v/react-dragdrop-kit.svg?label=react-dragdrop-kit"></a>
|
|
@@ -12,12 +12,25 @@ A flexible and lightweight **drag-and-drop toolkit for React**. Build **sortable
|
|
|
12
12
|
|
|
13
13
|
## ✨ Features
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
### Drag & Drop Lists
|
|
16
|
+
- 🔁 **Sortable** lists (vertical / horizontal)
|
|
16
17
|
- 🎯 **Controlled**: you own the array, update on `onReorder`
|
|
17
18
|
- 🧩 **Custom render** per item (cards, compact, detailed… anything)
|
|
18
19
|
- 🧲 **Drop indicator** + optional **custom drag preview**
|
|
20
|
+
|
|
21
|
+
### 🆕 Kanban Boards (v1.2.0+)
|
|
22
|
+
- 📋 **Full-featured Kanban board** with column and card management
|
|
23
|
+
- 🔄 **Cross-column dragging** - Move cards between columns seamlessly
|
|
24
|
+
- 🎨 **Headless architecture** - Complete styling control
|
|
25
|
+
- ♿ **Accessible** - Screen reader announcements and keyboard support
|
|
26
|
+
- 📱 **Touch-friendly** - Works on mobile devices
|
|
27
|
+
- 🎯 **TypeScript-first** - Full type safety
|
|
28
|
+
|
|
29
|
+
### General
|
|
19
30
|
- 🧪 **TypeScript** types included
|
|
20
|
-
- ⚡
|
|
31
|
+
- ⚡ **Tiny bundles** (~5KB main, ~9KB Kanban)
|
|
32
|
+
- 🎨 **Framework agnostic styling** - Works with Tailwind, MUI, Chakra, etc.
|
|
33
|
+
- 📚 **Comprehensive documentation**
|
|
21
34
|
|
|
22
35
|
---
|
|
23
36
|
|
|
@@ -29,54 +42,32 @@ npm i react-dragdrop-kit
|
|
|
29
42
|
yarn add react-dragdrop-kit
|
|
30
43
|
# or
|
|
31
44
|
pnpm add react-dragdrop-kit
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
## 🚀 Quick Start (Basic Example)
|
|
36
|
-
|
|
37
|
-
```tsx
|
|
38
|
-
// examples/basic-example.tsx
|
|
45
|
+
```
|
|
39
46
|
|
|
40
|
-
|
|
41
|
-
import { DragDropList, type DraggableItem, type OrderUpdate } from "react-dragdrop-kit";
|
|
47
|
+
---
|
|
42
48
|
|
|
43
|
-
|
|
44
|
-
title: string;
|
|
45
|
-
completed: boolean;
|
|
46
|
-
}
|
|
49
|
+
## 🚀 Quick Start
|
|
47
50
|
|
|
48
|
-
|
|
49
|
-
{ id: "1", position: 0, title: "Learn React", completed: false },
|
|
50
|
-
{ id: "2", position: 1, title: "Build awesome app", completed: false },
|
|
51
|
-
{ id: "3", position: 2, title: "Deploy to production", completed: false },
|
|
52
|
-
];
|
|
51
|
+
### Sortable List
|
|
53
52
|
|
|
54
|
-
|
|
55
|
-
|
|
53
|
+
```tsx
|
|
54
|
+
import { useState } from "react";
|
|
55
|
+
import { DragDropList } from "react-dragdrop-kit";
|
|
56
56
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
57
|
+
function App() {
|
|
58
|
+
const [items, setItems] = useState([
|
|
59
|
+
{ id: "1", position: 0, title: "Learn React" },
|
|
60
|
+
{ id: "2", position: 1, title: "Build awesome app" },
|
|
61
|
+
{ id: "3", position: 2, title: "Deploy to production" },
|
|
62
|
+
]);
|
|
63
63
|
|
|
64
64
|
return (
|
|
65
65
|
<DragDropList
|
|
66
|
-
items={
|
|
67
|
-
onReorder={
|
|
66
|
+
items={items}
|
|
67
|
+
onReorder={(next) => setItems(next.map((it, i) => ({ ...it, position: i })))}
|
|
68
68
|
renderItem={(item) => (
|
|
69
69
|
<div style={{ padding: 12, border: "1px solid #e5e7eb", borderRadius: 8 }}>
|
|
70
|
-
|
|
71
|
-
type="checkbox"
|
|
72
|
-
checked={item.completed}
|
|
73
|
-
onChange={() =>
|
|
74
|
-
setTodos((prev) =>
|
|
75
|
-
prev.map((t) => (t.id === item.id ? { ...t, completed: !t.completed } : t))
|
|
76
|
-
)
|
|
77
|
-
}
|
|
78
|
-
/>
|
|
79
|
-
<span style={{ marginLeft: 8 }}>{item.title}</span>
|
|
70
|
+
{item.title}
|
|
80
71
|
</div>
|
|
81
72
|
)}
|
|
82
73
|
showDropIndicator
|
|
@@ -86,22 +77,64 @@ export default function BasicExample() {
|
|
|
86
77
|
}
|
|
87
78
|
```
|
|
88
79
|
|
|
80
|
+
### Kanban Board
|
|
81
|
+
|
|
82
|
+
```tsx
|
|
83
|
+
import { useState } from 'react';
|
|
84
|
+
import {
|
|
85
|
+
KanbanBoard,
|
|
86
|
+
applyDragResult,
|
|
87
|
+
AnnouncerProvider,
|
|
88
|
+
} from 'react-dragdrop-kit/kanban';
|
|
89
|
+
|
|
90
|
+
function App() {
|
|
91
|
+
const [state, setState] = useState({
|
|
92
|
+
columns: [
|
|
93
|
+
{ id: 'todo', title: 'To Do', cardIds: ['task-1', 'task-2'] },
|
|
94
|
+
{ id: 'done', title: 'Done', cardIds: [] },
|
|
95
|
+
],
|
|
96
|
+
cards: {
|
|
97
|
+
'task-1': { id: 'task-1', title: 'Design landing page' },
|
|
98
|
+
'task-2': { id: 'task-2', title: 'Implement auth' },
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
const handleDragEnd = (result) => {
|
|
103
|
+
if (!result.destination) return;
|
|
104
|
+
setState(applyDragResult(state, result));
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
return (
|
|
108
|
+
<AnnouncerProvider>
|
|
109
|
+
<KanbanBoard
|
|
110
|
+
state={state}
|
|
111
|
+
onDragEnd={handleDragEnd}
|
|
112
|
+
renderColumn={(col) => <div style={{ padding: 16 }}>{col.title}</div>}
|
|
113
|
+
renderCard={(card) => (
|
|
114
|
+
<div style={{ padding: 12, background: '#fff', borderRadius: 8 }}>
|
|
115
|
+
{card.title}
|
|
116
|
+
</div>
|
|
117
|
+
)}
|
|
118
|
+
/>
|
|
119
|
+
</AnnouncerProvider>
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
89
124
|
---
|
|
90
125
|
|
|
91
|
-
## 🎨 Styled
|
|
126
|
+
## 🎨 Styled Examples
|
|
92
127
|
|
|
93
|
-
|
|
94
|
-
// examples/tailwind-example.tsx
|
|
128
|
+
### With Tailwind CSS
|
|
95
129
|
|
|
96
|
-
|
|
130
|
+
```tsx
|
|
97
131
|
import { DragDropList } from "react-dragdrop-kit";
|
|
98
132
|
|
|
99
133
|
export default function TailwindExample() {
|
|
100
|
-
const [items, setItems] =
|
|
134
|
+
const [items, setItems] = useState([
|
|
101
135
|
{ id: "1", position: 0, name: "Dashboard", icon: "📊" },
|
|
102
136
|
{ id: "2", position: 1, name: "Projects", icon: "📁" },
|
|
103
137
|
{ id: "3", position: 2, name: "Team", icon: "👥" },
|
|
104
|
-
{ id: "4", position: 3, name: "Calendar", icon: "📅" },
|
|
105
138
|
]);
|
|
106
139
|
|
|
107
140
|
return (
|
|
@@ -110,18 +143,12 @@ export default function TailwindExample() {
|
|
|
110
143
|
onReorder={(next) => setItems(next.map((it, i) => ({ ...it, position: i })))}
|
|
111
144
|
containerClassName="bg-gray-50 rounded-xl p-6 space-y-2"
|
|
112
145
|
itemClassName="bg-white rounded-lg shadow-sm hover:shadow-lg transition-all duration-200 cursor-move"
|
|
113
|
-
dragPreviewClassName="bg-blue-100 rounded-lg shadow-2xl"
|
|
114
146
|
showDropIndicator
|
|
115
147
|
dropIndicatorClassName="bg-blue-500"
|
|
116
148
|
renderItem={(item) => (
|
|
117
149
|
<div className="flex items-center p-4 space-x-3">
|
|
118
150
|
<span className="text-2xl">{item.icon}</span>
|
|
119
151
|
<span className="font-medium text-gray-700">{item.name}</span>
|
|
120
|
-
<div className="ml-auto">
|
|
121
|
-
<svg className="w-5 h-5 text-gray-400" fill="currentColor" viewBox="0 0 20 20">
|
|
122
|
-
<path d="M10 6a2 2 0 110-4 2 2 0 010 4zM10 12a2 2 0 110-4 2 2 0 010 4zM10 18a2 2 0 110-4 2 2 0 010 4z" />
|
|
123
|
-
</svg>
|
|
124
|
-
</div>
|
|
125
152
|
</div>
|
|
126
153
|
)}
|
|
127
154
|
/>
|
|
@@ -131,66 +158,180 @@ export default function TailwindExample() {
|
|
|
131
158
|
|
|
132
159
|
---
|
|
133
160
|
|
|
134
|
-
##
|
|
161
|
+
## 📚 API Reference
|
|
135
162
|
|
|
136
|
-
###
|
|
163
|
+
### DragDropList Component
|
|
137
164
|
|
|
138
165
|
| Prop | Type | Default | Description |
|
|
139
166
|
| ------------------------ | --------------------------------------------- | ------------ | ------------------------------------------------------------------------------------------------------ |
|
|
140
|
-
| `items` | `Array<DraggableItem & T>` | — | Items to render. Must include `{ id: string; position: number }`.
|
|
167
|
+
| `items` | `Array<DraggableItem & T>` | — | Items to render. Must include `{ id: string; position: number }`. |
|
|
141
168
|
| `onReorder` | `(next: T[], updates: OrderUpdate[]) => void` | — | Called after drop. `next` is the new array; `updates` has id + newPosition. |
|
|
142
169
|
| `renderItem` | `(item: T) => React.ReactNode` | — | Custom renderer for each item. |
|
|
143
170
|
| `direction` | `"vertical" \| "horizontal"` | `"vertical"` | Drag axis + layout. |
|
|
144
171
|
| `gap` | `number` | `0` | Gap (px) between items. |
|
|
145
172
|
| `disabled` | `boolean` | `false` | Disable dragging. |
|
|
146
173
|
| `showDropIndicator` | `boolean` | `false` | Show a drop indicator while dragging. |
|
|
174
|
+
| `dropIndicatorPosition` | `"top" \| "bottom"` | `"bottom"` | Position of drop indicator relative to target item. |
|
|
147
175
|
| `dropIndicatorClassName` | `string` | — | CSS class applied to the drop indicator element. |
|
|
148
176
|
| `dragPreviewStyle` | `React.CSSProperties` | — | Inline styles for custom drag preview. |
|
|
149
177
|
| `containerClassName` | `string` | — | Class applied to the container. |
|
|
150
178
|
| `itemClassName` | `string` | — | Class applied to each item wrapper. |
|
|
151
|
-
| `containerStyle` | `React.CSSProperties` | — | Inline styles for the container. |
|
|
152
|
-
| `itemStyle` | `React.CSSProperties` | — | Inline styles for each item wrapper. |
|
|
153
|
-
| `onDragStart` | `(item: T, index: number) => void` | — | Optional callback when drag starts. |
|
|
154
|
-
| `onDragEnd` | `(item: T, index: number) => void` | — | Optional callback when drag ends. |
|
|
155
|
-
|
|
156
|
-
#### Types
|
|
157
|
-
|
|
158
|
-
```ts
|
|
159
|
-
export type DraggableItem = {
|
|
160
|
-
id: string;
|
|
161
|
-
position: number; // 0-based
|
|
162
|
-
};
|
|
163
|
-
|
|
164
|
-
export type OrderUpdate = {
|
|
165
|
-
id: string;
|
|
166
|
-
newPosition: number;
|
|
167
|
-
// Extend in your app if you need: { oldPosition, moved }
|
|
168
|
-
};
|
|
169
|
-
```
|
|
170
179
|
|
|
171
|
-
|
|
180
|
+
### Kanban Components
|
|
172
181
|
|
|
173
|
-
|
|
182
|
+
See the [Kanban Documentation](./docs/kanban.md) for complete API reference, including:
|
|
183
|
+
- `KanbanBoard` - High-level component
|
|
184
|
+
- `KanbanColumnView` - Headless column component
|
|
185
|
+
- `KanbanCardView` - Headless card component
|
|
186
|
+
- `AnnouncerProvider` - Accessibility provider
|
|
187
|
+
- Helper utilities and types
|
|
174
188
|
|
|
175
|
-
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## 🗂️ Kanban Board Features
|
|
192
|
+
|
|
193
|
+
### Core Functionality
|
|
194
|
+
- ✅ **Drag cards** within and between columns
|
|
195
|
+
- ✅ **Reorder columns** by dragging headers
|
|
196
|
+
- ✅ **Empty column support** - Drop into columns with no cards
|
|
197
|
+
- ✅ **Cancel drag** - Drop outside board to cancel
|
|
198
|
+
- ✅ **Normalized state** - Efficient data structure
|
|
199
|
+
|
|
200
|
+
### Accessibility (a11y)
|
|
201
|
+
- ♿ **Screen reader support** with live announcements
|
|
202
|
+
- 🎹 **Keyboard navigation** (infrastructure ready)
|
|
203
|
+
- 🏷️ **Proper ARIA attributes**
|
|
204
|
+
- 📢 **Context-aware messages**
|
|
205
|
+
|
|
206
|
+
### Developer Experience
|
|
207
|
+
- 📘 **Full TypeScript support**
|
|
208
|
+
- 🎨 **Headless architecture** - Style with any framework
|
|
209
|
+
- 🔧 **Helper utilities** - `applyDragResult`, reorder functions
|
|
210
|
+
- 📖 **Migration guide** from react-beautiful-dnd
|
|
211
|
+
|
|
212
|
+
### Customization
|
|
213
|
+
The Kanban board is completely headless, giving you full control:
|
|
214
|
+
- Custom card designs
|
|
215
|
+
- Custom column headers
|
|
216
|
+
- Theme support
|
|
217
|
+
- Animation styles
|
|
218
|
+
- Responsive layouts
|
|
176
219
|
|
|
177
220
|
---
|
|
178
221
|
|
|
179
|
-
##
|
|
222
|
+
## 📂 Examples
|
|
180
223
|
|
|
181
|
-
This repo includes
|
|
224
|
+
This repo includes comprehensive examples:
|
|
182
225
|
|
|
226
|
+
### Drag & Drop Lists
|
|
183
227
|
* [Basic Example](./examples/basic-example.tsx)
|
|
184
228
|
* [Tailwind Example](./examples/tailwind-example.tsx)
|
|
185
229
|
* [Material UI Example](./examples/material-ui-example.tsx)
|
|
186
|
-
* [Horizontal Kanban](./examples/horizontal-kanban.tsx)
|
|
187
230
|
* [Advanced Features](./examples/advanced-features.tsx)
|
|
188
|
-
* [Styled Components
|
|
231
|
+
* [Styled Components](./examples/styled-components-example.tsx)
|
|
232
|
+
|
|
233
|
+
### Kanban Boards
|
|
234
|
+
* [Basic Kanban](./examples/kanban/basic-kanban.tsx)
|
|
235
|
+
* [Rich Cards with Tags & Avatars](./examples/kanban/rich-cards-kanban.tsx)
|
|
236
|
+
* [Multi-theme Kanban](./examples/kanban/themed-kanban.tsx)
|
|
237
|
+
* [Kanban with Accessibility](./examples/kanban/accessible-kanban.tsx)
|
|
189
238
|
|
|
190
239
|
👉 Explore the [`examples/`](./examples) folder for the complete code.
|
|
191
240
|
|
|
241
|
+
🎮 **Live Demo**: Check out our [interactive demo app](https://react-dragdrop-kit.netlify.app/) with full Kanban showcase!
|
|
242
|
+
|
|
243
|
+
---
|
|
244
|
+
|
|
245
|
+
## 🧠 Advanced Usage
|
|
246
|
+
|
|
247
|
+
### TypeScript
|
|
248
|
+
|
|
249
|
+
```tsx
|
|
250
|
+
import type { DraggableItem, OrderUpdate, KanbanBoardState, DropResult } from 'react-dragdrop-kit';
|
|
251
|
+
import type { KanbanCard, KanbanColumn } from 'react-dragdrop-kit/kanban';
|
|
252
|
+
|
|
253
|
+
// Extend with custom fields
|
|
254
|
+
interface TodoItem extends DraggableItem {
|
|
255
|
+
title: string;
|
|
256
|
+
completed: boolean;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
interface ProjectCard extends KanbanCard {
|
|
260
|
+
priority: 'low' | 'medium' | 'high';
|
|
261
|
+
assignee: string;
|
|
262
|
+
tags: string[];
|
|
263
|
+
}
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### React Strict Mode (React 19)
|
|
267
|
+
|
|
268
|
+
In dev, React Strict Mode **double-mounts** to surface side effects. If you see duplicate `onReorder` calls in development, ensure your event listeners clean up correctly and keep callback identities stable with `useCallback`. Production builds call once.
|
|
269
|
+
|
|
270
|
+
---
|
|
271
|
+
|
|
272
|
+
## 📊 Bundle Size
|
|
273
|
+
|
|
274
|
+
| Module | Size (Minified) |
|
|
275
|
+
|--------|-----------------|
|
|
276
|
+
| `react-dragdrop-kit` (Main) | ~5KB |
|
|
277
|
+
| `react-dragdrop-kit/kanban` | ~9KB |
|
|
278
|
+
|
|
279
|
+
Tree-shakeable exports mean you only pay for what you use!
|
|
280
|
+
|
|
281
|
+
---
|
|
282
|
+
|
|
283
|
+
## 🔄 Migration Guides
|
|
284
|
+
|
|
285
|
+
### From react-beautiful-dnd
|
|
286
|
+
|
|
287
|
+
See our comprehensive [Kanban migration guide](./docs/kanban.md#migration-from-react-beautiful-dnd) for step-by-step instructions on migrating from `react-beautiful-dnd`.
|
|
288
|
+
|
|
289
|
+
Key differences:
|
|
290
|
+
- Normalized state structure
|
|
291
|
+
- No auto-generated IDs
|
|
292
|
+
- Render props instead of children
|
|
293
|
+
- Better TypeScript support
|
|
294
|
+
|
|
295
|
+
---
|
|
296
|
+
|
|
297
|
+
## 🤝 Contributing
|
|
298
|
+
|
|
299
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
300
|
+
|
|
192
301
|
---
|
|
193
302
|
|
|
194
303
|
## 📝 License
|
|
195
304
|
|
|
196
305
|
MIT © [Yourstruggle11](https://github.com/Yourstruggle11)
|
|
306
|
+
|
|
307
|
+
---
|
|
308
|
+
|
|
309
|
+
## 🙏 Credits
|
|
310
|
+
|
|
311
|
+
Built with:
|
|
312
|
+
- [`@atlaskit/pragmatic-drag-and-drop`](https://atlassian.design/components/pragmatic-drag-and-drop) - Performance-focused drag and drop
|
|
313
|
+
- Inspired by `react-beautiful-dnd` API design
|
|
314
|
+
- Community feedback and contributions
|
|
315
|
+
|
|
316
|
+
---
|
|
317
|
+
|
|
318
|
+
## 📖 Documentation
|
|
319
|
+
|
|
320
|
+
- [Kanban Board Guide](./docs/kanban.md)
|
|
321
|
+
- [CHANGELOG](./CHANGELOG.md)
|
|
322
|
+
- [Examples](./examples/)
|
|
323
|
+
- [Demo Application](https://react-dragdrop-kit.netlify.app/)
|
|
324
|
+
|
|
325
|
+
---
|
|
326
|
+
|
|
327
|
+
## 💬 Support
|
|
328
|
+
|
|
329
|
+
- 🐛 [Report Issues](https://github.com/Yourstruggle11/react-dragdrop-kit/issues)
|
|
330
|
+
- 💡 [Request Features](https://github.com/Yourstruggle11/react-dragdrop-kit/issues/new)
|
|
331
|
+
- ⭐ [Star on GitHub](https://github.com/Yourstruggle11/react-dragdrop-kit)
|
|
332
|
+
|
|
333
|
+
---
|
|
334
|
+
|
|
335
|
+
<div align="center">
|
|
336
|
+
<strong>Made with ❤️ by <a href="https://github.com/Yourstruggle11" target="_blank" rel="noopener noreferrer">Yourstruggle11</a> for the React community</strong>
|
|
337
|
+
</div>
|
package/dist/index.esm.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import e,{useRef as t,useState as a,useCallback as r,useEffect as o}from"react";import{combine as i}from"@atlaskit/pragmatic-drag-and-drop/combine";import{draggable as n,dropTargetForElements as d,monitorForElements as s}from"@atlaskit/pragmatic-drag-and-drop/element/adapter";import{extractClosestEdge as l}from"@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge";const c={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 p({item:s,index:l,children:p,className:m="",style:u={},dragPreviewClassName:b="",dragPreviewStyle:v={},onDragStart:f,onDragEnd:x,disabled:y=!1,showDropIndicator:D=!1,dropIndicatorClassName:h="",dropIndicatorStyle:
|
|
1
|
+
import e,{useRef as t,useState as a,useCallback as r,useEffect as o}from"react";import{combine as i}from"@atlaskit/pragmatic-drag-and-drop/combine";import{draggable as n,dropTargetForElements as d,monitorForElements as s}from"@atlaskit/pragmatic-drag-and-drop/element/adapter";import{extractClosestEdge as l}from"@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge";const c={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 p({item:s,index:l,children:p,className:m="",style:u={},dragPreviewClassName:b="",dragPreviewStyle:v={},onDragStart:f,onDragEnd:x,disabled:y=!1,showDropIndicator:D=!1,dropIndicatorClassName:h="",dropIndicatorStyle:I={},dropIndicatorPosition:j="bottom"}){const O=t(null),[w,S]=a(!1),[N,C]=a(!1),[E,P]=a(null),k=r(e=>y?()=>{}:n({element:e,getInitialData:()=>({type:g,id:s.id,index:l}),onGenerateDragPreview:({nativeSetDragImage:t})=>{const a=e.cloneNode(!0),r=Object.assign(Object.assign({},c.preview),v);b&&(a.className=b),Object.assign(a.style,r,{width:`${(null==e?void 0:e.offsetWidth)||100}px`,height:`${(null==e?void 0:e.offsetHeight)||50}px`}),document.body.appendChild(a),t&&t(a,20,20),requestAnimationFrame(()=>a.remove())},onDragStart:()=>{S(!0),null==f||f(s,l)},onDrop:()=>{S(!1),null==x||x(s,l)}}),[s,l,b,v,f,x,y]),z=r(e=>y?()=>{}:d({element:e,getData:()=>({type:g,id:s.id,index:l}),canDrop:e=>{var t;return(null===(t=e.source.data)||void 0===t?void 0:t.type)===g},getIsSticky:()=>!0,onDragEnter:({source:e,self:t})=>{var a,r;(null===(a=e.data)||void 0===a?void 0:a.id)!==(null===(r=t.data)||void 0===r?void 0:r.id)&&(C(!0),D&&P(j))},onDragLeave:()=>{C(!1),P(null)},onDrop:()=>{C(!1),P(null)}}),[s.id,l,y,D,j]);return o(()=>{const e=O.current;if(e)return e.setAttribute("data-index",l.toString()),y?()=>{}:i(k(e),z(e))},[l,k,z,y]),e.createElement("div",{ref:O,className:m,style:(()=>{const e=Object.assign({},c.item.default);return y?Object.assign(e,c.item.disabled):w?Object.assign(e,c.item.dragging):N&&Object.assign(e,c.item.hover),Object.assign(Object.assign({},e),u)})()},D&&"top"===E&&e.createElement("div",{className:h,style:Object.assign(Object.assign(Object.assign({},c.dropIndicator),I),{top:-1})}),p,D&&"bottom"===E&&e.createElement("div",{className:h,style:Object.assign(Object.assign(Object.assign({},c.dropIndicator),I),{bottom:-1})}))}function m({items:e,onReorder:t,disabled:a=!1}){if(a)return()=>{};return s({onDrop:({location:a,source:r})=>{var o;const i=null===(o=r.data)||void 0===o?void 0:o.index;if(void 0===i)return;const{dropTargets:n}=a.current,d=n.find(e=>{var t,a,o;return"draggable-item"===(null===(t=e.data)||void 0===t?void 0:t.type)&&(null===(a=e.data)||void 0===a?void 0:a.id)!==(null===(o=r.data)||void 0===o?void 0:o.id)});if(!d)return;const s=l(d),c=Number(d.element.getAttribute("data-index")),g="bottom"===s?c+1:c;if(i!==g){const a=[...e],r=function(e,t,a){const r=Array.from(e),[o]=r.splice(t,1);return r.splice(a,0,o),r}(e,i,g),o=function(e,t){const a=t.filter((t,a)=>{var r;return t.id!==(null===(r=e[a])||void 0===r?void 0:r.id)}),r=a.slice().sort((e,t)=>e.position-t.position).map(e=>e.position);return a.map((e,t)=>({id:e.id,newPosition:r[t]}))}(a,r);t(r,o)}}})}function u({items:n,onReorder:s,renderItem:l,containerClassName:g="",containerStyle:u={},itemClassName:b="",itemStyle:v={},dragPreviewClassName:f="",dragPreviewStyle:x={},onDragStart:y,onDragEnd:D,disabled:h=!1,gap:I,direction:j="vertical",showDropIndicator:O=!1,dropIndicatorClassName:w="",dropIndicatorStyle:S={},dropIndicatorPosition:N="bottom"}){const C=t(null),E=m({items:n,onReorder:s,disabled:h}),[P,k]=a(!1),z=r(e=>h?()=>{}:d({element:e,getData:()=>({type:"container"}),onDragEnter:()=>k(!0),onDragLeave:()=>k(!1),onDrop:()=>k(!1)}),[h]);return o(()=>{const e=C.current;if(e&&!h)return i(z(e),E)},[z,E,h]),e.createElement("div",{ref:C,className:g,style:(()=>{const e=Object.assign({},c.container.default);return"horizontal"===j&&Object.assign(e,c.container.horizontal),P&&Object.assign(e,c.container.dragging),void 0!==I&&(e.gap="number"==typeof I?`${I}px`:I),Object.assign(Object.assign({},e),u)})()},n.map((t,a)=>e.createElement(p,{key:t.id,item:t,index:a,className:b,style:v,dragPreviewClassName:f,dragPreviewStyle:x,onDragStart:y,onDragEnd:D,disabled:h,showDropIndicator:O,dropIndicatorClassName:w,dropIndicatorStyle:S,dropIndicatorPosition:N},l(t,a))))}export{u as DragDropList,p as DraggableItemWrapper,c as defaultStyles,m as useDragDropMonitor};
|
|
2
2
|
//# sourceMappingURL=index.esm.js.map
|
package/dist/index.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.esm.js","sources":["../src/styles/defaultStyles.ts","../src/components/DraggableItemWrapper.tsx","../src/hooks/useDragDropMonitor.ts","../src/components/DragDropList.tsx"],"sourcesContent":["export const defaultStyles = {\r\n container: {\r\n default: {\r\n minHeight: \"200px\",\r\n transition: \"all 0.2s ease\",\r\n borderRadius: \"8px\",\r\n border: \"1px solid #e2e8f0\",\r\n backgroundColor: \"#ffffff\",\r\n display: \"flex\",\r\n flexDirection: \"column\" as const,\r\n gap: \"16px\",\r\n padding: \"16px\",\r\n },\r\n dragging: {\r\n backgroundColor: \"rgba(66, 153, 225, 0.05)\",\r\n borderColor: \"#3182ce\",\r\n },\r\n horizontal: {\r\n flexDirection: \"row\" as const,\r\n flexWrap: \"wrap\" as const,\r\n },\r\n },\r\n item: {\r\n default: {\r\n transition: \"all 0.2s ease\",\r\n cursor: \"grab\",\r\n userSelect: \"none\" as const,\r\n position: \"relative\" as const,\r\n },\r\n dragging: {\r\n opacity: 0.5,\r\n cursor: \"grabbing\",\r\n },\r\n hover: {\r\n transform: \"scale(1.02)\",\r\n boxShadow: \"0 4px 6px rgba(0, 0, 0, 0.1)\",\r\n },\r\n disabled: {\r\n cursor: \"not-allowed\",\r\n opacity: 0.6,\r\n },\r\n },\r\n preview: {\r\n position: \"fixed\" as const,\r\n pointerEvents: \"none\" as const,\r\n zIndex: 9999,\r\n opacity: 0.8,\r\n transform: \"rotate(2deg)\",\r\n boxShadow: \"0 10px 20px rgba(0, 0, 0, 0.15)\",\r\n },\r\n dropIndicator: {\r\n position: \"absolute\" as const,\r\n height: \"2px\",\r\n backgroundColor: \"#3182ce\",\r\n left: 0,\r\n right: 0,\r\n zIndex: 10,\r\n transition: \"all 0.2s ease\",\r\n },\r\n};\r\n","import React, { useEffect, useRef, useState, useCallback } from \"react\";\r\nimport { combine } from \"@atlaskit/pragmatic-drag-and-drop/combine\";\r\nimport {\r\n draggable,\r\n dropTargetForElements,\r\n} from \"@atlaskit/pragmatic-drag-and-drop/element/adapter\";\r\nimport type { DraggableItemWrapperProps, DraggableItem } from \"../types\";\r\nimport { defaultStyles } from \"../styles/defaultStyles\";\r\n\r\nconst DRAGGABLE_ITEM = \"draggable-item\";\r\n\r\nexport function DraggableItemWrapper<T extends DraggableItem>({\r\n item,\r\n index,\r\n children,\r\n className = \"\",\r\n style = {},\r\n dragPreviewClassName = \"\",\r\n dragPreviewStyle = {},\r\n onDragStart,\r\n onDragEnd,\r\n disabled = false,\r\n showDropIndicator = false,\r\n dropIndicatorClassName = \"\",\r\n dropIndicatorStyle = {},\r\n}: DraggableItemWrapperProps<T>) {\r\n const elementRef = useRef<HTMLDivElement>(null);\r\n const [isDragging, setIsDragging] = useState(false);\r\n const [isHovered, setIsHovered] = useState(false);\r\n const [dropPosition, setDropPosition] = useState<\"top\" | \"bottom\" | null>(\r\n null\r\n );\r\n\r\n const getItemStyles = (): React.CSSProperties => {\r\n const baseStyle = { ...defaultStyles.item.default };\r\n\r\n if (disabled) {\r\n Object.assign(baseStyle, defaultStyles.item.disabled);\r\n } else if (isDragging) {\r\n Object.assign(baseStyle, defaultStyles.item.dragging);\r\n } else if (isHovered) {\r\n Object.assign(baseStyle, defaultStyles.item.hover);\r\n }\r\n\r\n return { ...baseStyle, ...style };\r\n };\r\n\r\n const getPreviewStyles = (): React.CSSProperties => {\r\n return { ...defaultStyles.preview, ...dragPreviewStyle };\r\n };\r\n\r\n const createDraggable = useCallback(\r\n (element: HTMLElement) => {\r\n if (disabled) return () => {};\r\n\r\n return draggable({\r\n element,\r\n getInitialData: () => ({\r\n type: DRAGGABLE_ITEM,\r\n id: item.id,\r\n index,\r\n }),\r\n onGenerateDragPreview: ({ nativeSetDragImage }) => {\r\n const previewElement = element.cloneNode(true) as HTMLElement;\r\n const previewStyles = getPreviewStyles();\r\n\r\n // Apply custom preview class if provided\r\n if (dragPreviewClassName) {\r\n previewElement.className = dragPreviewClassName;\r\n }\r\n\r\n Object.assign(previewElement.style, previewStyles, {\r\n width: `${element?.offsetWidth || 100}px`,\r\n height: `${element?.offsetHeight || 50}px`,\r\n });\r\n\r\n document.body.appendChild(previewElement);\r\n if (nativeSetDragImage) {\r\n nativeSetDragImage(previewElement, 20, 20);\r\n }\r\n requestAnimationFrame(() => previewElement.remove());\r\n },\r\n onDragStart: () => {\r\n setIsDragging(true);\r\n onDragStart?.(item, index);\r\n },\r\n onDrop: () => {\r\n setIsDragging(false);\r\n onDragEnd?.(item, index);\r\n },\r\n });\r\n },\r\n [\r\n item,\r\n index,\r\n dragPreviewClassName,\r\n dragPreviewStyle,\r\n onDragStart,\r\n onDragEnd,\r\n disabled,\r\n ]\r\n );\r\n\r\n const createDropTarget = useCallback(\r\n (element: HTMLElement) => {\r\n if (disabled) return () => {};\r\n\r\n return dropTargetForElements({\r\n element,\r\n getData: () => ({\r\n type: DRAGGABLE_ITEM,\r\n id: item.id,\r\n index,\r\n }),\r\n canDrop: (args: any) => args.source.data?.type === DRAGGABLE_ITEM,\r\n getIsSticky: () => true,\r\n onDragEnter: ({ source, self, location }: any) => {\r\n if (source.data?.id !== self.data?.id) {\r\n setIsHovered(true);\r\n if (showDropIndicator) {\r\n const edge = location.current.dropTargets[0]?.edge;\r\n setDropPosition(edge === \"top\" ? \"top\" : \"bottom\");\r\n }\r\n }\r\n },\r\n onDragLeave: () => {\r\n setIsHovered(false);\r\n setDropPosition(null);\r\n },\r\n onDrop: () => {\r\n setIsHovered(false);\r\n setDropPosition(null);\r\n },\r\n });\r\n },\r\n [item.id, index, disabled, showDropIndicator]\r\n );\r\n\r\n// useEffect(() => {\r\n// const element = elementRef.current;\r\n// if (!element) return;\r\n\r\n// element.setAttribute(\"data-index\", index.toString());\r\n\r\n// if (!disabled) {\r\n// return combine(createDraggable(element), createDropTarget(element));\r\n// }\r\n// }, [index, createDraggable, createDropTarget, disabled]);\r\n\r\n useEffect(() => {\r\n const element = elementRef.current;\r\n if (!element) return;\r\n\r\n element.setAttribute(\"data-index\", index.toString());\r\n\r\n if (disabled) {\r\n // provide a no-op cleanup to satisfy all code paths\r\n return () => {};\r\n }\r\n\r\n // normal draggable + droptarget setup\r\n return combine(createDraggable(element), createDropTarget(element));\r\n }, [index, createDraggable, createDropTarget, disabled]);\r\n\r\n return (\r\n <div ref={elementRef} className={className} style={getItemStyles()}>\r\n {showDropIndicator && dropPosition === \"top\" && (\r\n <div\r\n className={dropIndicatorClassName}\r\n style={{\r\n ...defaultStyles.dropIndicator,\r\n ...dropIndicatorStyle,\r\n top: -1,\r\n }}\r\n />\r\n )}\r\n {children}\r\n {showDropIndicator && dropPosition === \"bottom\" && (\r\n <div\r\n className={dropIndicatorClassName}\r\n style={{\r\n ...defaultStyles.dropIndicator,\r\n ...dropIndicatorStyle,\r\n bottom: -1,\r\n }}\r\n />\r\n )}\r\n </div>\r\n );\r\n}\r\n","import { monitorForElements } from \"@atlaskit/pragmatic-drag-and-drop/element/adapter\";\r\nimport { extractClosestEdge } from \"@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge\";\r\nimport type { DraggableItem, OrderUpdate } from \"../types\";\r\n\r\nexport function useDragDropMonitor<T extends DraggableItem>({\r\n items,\r\n onReorder,\r\n disabled = false,\r\n}: {\r\n items: T[];\r\n onReorder: (newItems: T[], orderUpdates: OrderUpdate[]) => void;\r\n disabled?: boolean;\r\n}) {\r\n if (disabled) {\r\n return () => {};\r\n }\r\n\r\n const reorder = (list: T[], startIndex: number, endIndex: number) => {\r\n const result = Array.from(list);\r\n const [removed] = result.splice(startIndex, 1);\r\n result.splice(endIndex, 0, removed);\r\n return result;\r\n };\r\n\r\n const calculateOrderUpdates = (\r\n oldItems: T[],\r\n newItems: T[]\r\n ): OrderUpdate[] => {\r\n const affectedItems = newItems.filter(\r\n (item, index) => item.id !== oldItems[index]?.id\r\n );\r\n const orderList = affectedItems\r\n .slice()\r\n .sort((a, b) => a.position - b.position)\r\n .map((item) => item.position);\r\n\r\n return affectedItems.map((item, index) => ({\r\n id: item.id,\r\n newPosition: orderList[index],\r\n }));\r\n };\r\n\r\n const handleDrop = ({ location, source }: any) => {\r\n const sourceIndex = source.data?.index as number;\r\n if (sourceIndex === undefined) return;\r\n\r\n const { dropTargets } = location.current;\r\n const destinationTarget = dropTargets.find(\r\n (target: any) =>\r\n target.data?.type === \"draggable-item\" &&\r\n target.data?.id !== source.data?.id\r\n );\r\n\r\n if (!destinationTarget) return;\r\n\r\n const edge = extractClosestEdge(destinationTarget);\r\n const targetIndex = Number(\r\n destinationTarget.element.getAttribute(\"data-index\")\r\n );\r\n const destinationIndex = edge === \"bottom\" ? targetIndex + 1 : targetIndex;\r\n\r\n if (sourceIndex !== destinationIndex) {\r\n const oldItems = [...items];\r\n const newItems = reorder(items, sourceIndex, destinationIndex);\r\n const orderUpdates = calculateOrderUpdates(oldItems, newItems);\r\n onReorder(newItems, orderUpdates);\r\n }\r\n };\r\n\r\n return monitorForElements({\r\n onDrop: handleDrop,\r\n });\r\n}\r\n","import React, { useEffect, useRef, useState, useCallback } from \"react\";\r\nimport { combine } from \"@atlaskit/pragmatic-drag-and-drop/combine\";\r\nimport { dropTargetForElements } from \"@atlaskit/pragmatic-drag-and-drop/element/adapter\";\r\nimport { DraggableItemWrapper } from \"./DraggableItemWrapper\";\r\nimport type { DragDropListProps, DraggableItem } from \"../types\";\r\nimport { useDragDropMonitor } from \"../hooks/useDragDropMonitor\";\r\nimport { defaultStyles } from \"../styles/defaultStyles\";\r\n\r\nexport function DragDropList<T extends DraggableItem>({\r\n items,\r\n onReorder,\r\n renderItem,\r\n containerClassName = \"\",\r\n containerStyle = {},\r\n itemClassName = \"\",\r\n itemStyle = {},\r\n dragPreviewClassName = \"\",\r\n dragPreviewStyle = {},\r\n onDragStart,\r\n onDragEnd,\r\n disabled = false,\r\n gap,\r\n direction = \"vertical\",\r\n showDropIndicator = false,\r\n dropIndicatorClassName = \"\",\r\n dropIndicatorStyle = {},\r\n}: DragDropListProps<T>) {\r\n const containerRef = useRef<HTMLDivElement>(null);\r\n const monitor = useDragDropMonitor({ items, onReorder, disabled });\r\n const [isDraggingOver, setIsDraggingOver] = useState(false);\r\n\r\n const getContainerStyles = (): React.CSSProperties => {\r\n const baseStyle = { ...defaultStyles.container.default };\r\n\r\n if (direction === \"horizontal\") {\r\n Object.assign(baseStyle, defaultStyles.container.horizontal);\r\n }\r\n\r\n if (isDraggingOver) {\r\n Object.assign(baseStyle, defaultStyles.container.dragging);\r\n }\r\n\r\n if (gap !== undefined) {\r\n baseStyle.gap = typeof gap === \"number\" ? `${gap}px` : gap;\r\n }\r\n\r\n return { ...baseStyle, ...containerStyle };\r\n };\r\n\r\n const createDropTarget = useCallback(\r\n (element: HTMLElement) => {\r\n if (disabled) return () => {};\r\n\r\n return dropTargetForElements({\r\n element,\r\n getData: () => ({ type: \"container\" }),\r\n onDragEnter: () => setIsDraggingOver(true),\r\n onDragLeave: () => setIsDraggingOver(false),\r\n onDrop: () => setIsDraggingOver(false),\r\n });\r\n },\r\n [disabled]\r\n );\r\n\r\n useEffect(() => {\r\n const element = containerRef.current;\r\n if (!element || disabled) return;\r\n\r\n return combine(createDropTarget(element), monitor);\r\n }, [createDropTarget, monitor, disabled]);\r\n\r\n return (\r\n <div\r\n ref={containerRef}\r\n className={containerClassName}\r\n style={getContainerStyles()}\r\n >\r\n {items.map((item, index) => (\r\n <DraggableItemWrapper\r\n key={item.id}\r\n item={item}\r\n index={index}\r\n className={itemClassName}\r\n style={itemStyle}\r\n dragPreviewClassName={dragPreviewClassName}\r\n dragPreviewStyle={dragPreviewStyle}\r\n onDragStart={onDragStart}\r\n onDragEnd={onDragEnd}\r\n disabled={disabled}\r\n showDropIndicator={showDropIndicator}\r\n dropIndicatorClassName={dropIndicatorClassName}\r\n dropIndicatorStyle={dropIndicatorStyle}\r\n >\r\n {renderItem(item, index)}\r\n </DraggableItemWrapper>\r\n ))}\r\n </div>\r\n );\r\n}\r\n"],"names":["defaultStyles","container","default","minHeight","transition","borderRadius","border","backgroundColor","display","flexDirection","gap","padding","dragging","borderColor","horizontal","flexWrap","item","cursor","userSelect","position","opacity","hover","transform","boxShadow","disabled","preview","pointerEvents","zIndex","dropIndicator","height","left","right","DRAGGABLE_ITEM","DraggableItemWrapper","index","children","className","style","dragPreviewClassName","dragPreviewStyle","onDragStart","onDragEnd","showDropIndicator","dropIndicatorClassName","dropIndicatorStyle","elementRef","useRef","isDragging","setIsDragging","useState","isHovered","setIsHovered","dropPosition","setDropPosition","createDraggable","useCallback","element","draggable","getInitialData","type","id","onGenerateDragPreview","nativeSetDragImage","previewElement","cloneNode","previewStyles","Object","assign","width","offsetWidth","offsetHeight","document","body","appendChild","requestAnimationFrame","remove","onDrop","createDropTarget","dropTargetForElements","getData","canDrop","args","_a","source","data","getIsSticky","onDragEnter","self","location","_b","edge","_c","current","dropTargets","onDragLeave","useEffect","setAttribute","toString","combine","React","createElement","ref","baseStyle","getItemStyles","top","bottom","useDragDropMonitor","items","onReorder","monitorForElements","sourceIndex","undefined","destinationTarget","find","target","extractClosestEdge","targetIndex","Number","getAttribute","destinationIndex","oldItems","newItems","list","startIndex","endIndex","result","Array","from","removed","splice","reorder","orderUpdates","affectedItems","filter","orderList","slice","sort","a","b","map","newPosition","calculateOrderUpdates","DragDropList","renderItem","containerClassName","containerStyle","itemClassName","itemStyle","direction","containerRef","monitor","isDraggingOver","setIsDraggingOver","getContainerStyles","key"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":["../src/styles/defaultStyles.ts","../src/components/DraggableItemWrapper.tsx","../src/hooks/useDragDropMonitor.ts","../src/utils/order.ts","../src/components/DragDropList.tsx"],"sourcesContent":["export const defaultStyles = {\r\n container: {\r\n default: {\r\n minHeight: \"200px\",\r\n transition: \"all 0.2s ease\",\r\n borderRadius: \"8px\",\r\n border: \"1px solid #e2e8f0\",\r\n backgroundColor: \"#ffffff\",\r\n display: \"flex\",\r\n flexDirection: \"column\" as const,\r\n gap: \"16px\",\r\n padding: \"16px\",\r\n },\r\n dragging: {\r\n backgroundColor: \"rgba(66, 153, 225, 0.05)\",\r\n borderColor: \"#3182ce\",\r\n },\r\n horizontal: {\r\n flexDirection: \"row\" as const,\r\n flexWrap: \"wrap\" as const,\r\n },\r\n },\r\n item: {\r\n default: {\r\n transition: \"all 0.2s ease\",\r\n cursor: \"grab\",\r\n userSelect: \"none\" as const,\r\n position: \"relative\" as const,\r\n },\r\n dragging: {\r\n opacity: 0.5,\r\n cursor: \"grabbing\",\r\n },\r\n hover: {\r\n transform: \"scale(1.02)\",\r\n boxShadow: \"0 4px 6px rgba(0, 0, 0, 0.1)\",\r\n },\r\n disabled: {\r\n cursor: \"not-allowed\",\r\n opacity: 0.6,\r\n },\r\n },\r\n preview: {\r\n position: \"fixed\" as const,\r\n pointerEvents: \"none\" as const,\r\n zIndex: 9999,\r\n opacity: 0.8,\r\n transform: \"rotate(2deg)\",\r\n boxShadow: \"0 10px 20px rgba(0, 0, 0, 0.15)\",\r\n },\r\n dropIndicator: {\r\n position: \"absolute\" as const,\r\n height: \"2px\",\r\n backgroundColor: \"#3182ce\",\r\n left: 0,\r\n right: 0,\r\n zIndex: 10,\r\n transition: \"all 0.2s ease\",\r\n },\r\n};\r\n","import React, { useEffect, useRef, useState, useCallback } from \"react\";\r\nimport { combine } from \"@atlaskit/pragmatic-drag-and-drop/combine\";\r\nimport {\r\n draggable,\r\n dropTargetForElements,\r\n} from \"@atlaskit/pragmatic-drag-and-drop/element/adapter\";\r\nimport type { DraggableItemWrapperProps, DraggableItem } from \"../types\";\r\nimport { defaultStyles } from \"../styles/defaultStyles\";\r\n\r\nconst DRAGGABLE_ITEM = \"draggable-item\";\r\n\r\nexport function DraggableItemWrapper<T extends DraggableItem>({\r\n item,\r\n index,\r\n children,\r\n className = \"\",\r\n style = {},\r\n dragPreviewClassName = \"\",\r\n dragPreviewStyle = {},\r\n onDragStart,\r\n onDragEnd,\r\n disabled = false,\r\n showDropIndicator = false,\r\n dropIndicatorClassName = \"\",\r\n dropIndicatorStyle = {},\r\n dropIndicatorPosition = \"bottom\",\r\n}: DraggableItemWrapperProps<T>) {\r\n const elementRef = useRef<HTMLDivElement>(null);\r\n const [isDragging, setIsDragging] = useState(false);\r\n const [isHovered, setIsHovered] = useState(false);\r\n const [dropPosition, setDropPosition] = useState<\"top\" | \"bottom\" | null>(\r\n null\r\n );\r\n\r\n const getItemStyles = (): React.CSSProperties => {\r\n const baseStyle = { ...defaultStyles.item.default };\r\n\r\n if (disabled) {\r\n Object.assign(baseStyle, defaultStyles.item.disabled);\r\n } else if (isDragging) {\r\n Object.assign(baseStyle, defaultStyles.item.dragging);\r\n } else if (isHovered) {\r\n Object.assign(baseStyle, defaultStyles.item.hover);\r\n }\r\n\r\n return { ...baseStyle, ...style };\r\n };\r\n\r\n const getPreviewStyles = (): React.CSSProperties => {\r\n return { ...defaultStyles.preview, ...dragPreviewStyle };\r\n };\r\n\r\n const createDraggable = useCallback(\r\n (element: HTMLElement) => {\r\n if (disabled) return () => {};\r\n\r\n return draggable({\r\n element,\r\n getInitialData: () => ({\r\n type: DRAGGABLE_ITEM,\r\n id: item.id,\r\n index,\r\n }),\r\n onGenerateDragPreview: ({ nativeSetDragImage }) => {\r\n const previewElement = element.cloneNode(true) as HTMLElement;\r\n const previewStyles = getPreviewStyles();\r\n\r\n // Apply custom preview class if provided\r\n if (dragPreviewClassName) {\r\n previewElement.className = dragPreviewClassName;\r\n }\r\n\r\n Object.assign(previewElement.style, previewStyles, {\r\n width: `${element?.offsetWidth || 100}px`,\r\n height: `${element?.offsetHeight || 50}px`,\r\n });\r\n\r\n document.body.appendChild(previewElement);\r\n if (nativeSetDragImage) {\r\n nativeSetDragImage(previewElement, 20, 20);\r\n }\r\n requestAnimationFrame(() => previewElement.remove());\r\n },\r\n onDragStart: () => {\r\n setIsDragging(true);\r\n onDragStart?.(item, index);\r\n },\r\n onDrop: () => {\r\n setIsDragging(false);\r\n onDragEnd?.(item, index);\r\n },\r\n });\r\n },\r\n [\r\n item,\r\n index,\r\n dragPreviewClassName,\r\n dragPreviewStyle,\r\n onDragStart,\r\n onDragEnd,\r\n disabled,\r\n ]\r\n );\r\n\r\n const createDropTarget = useCallback(\r\n (element: HTMLElement) => {\r\n if (disabled) return () => {};\r\n\r\n return dropTargetForElements({\r\n element,\r\n getData: () => ({\r\n type: DRAGGABLE_ITEM,\r\n id: item.id,\r\n index,\r\n }),\r\n canDrop: (args: any) => args.source.data?.type === DRAGGABLE_ITEM,\r\n getIsSticky: () => true,\r\n onDragEnter: ({ source, self }: any) => {\r\n if (source.data?.id !== self.data?.id) {\r\n setIsHovered(true);\r\n if (showDropIndicator) {\r\n setDropPosition(dropIndicatorPosition);\r\n }\r\n }\r\n },\r\n onDragLeave: () => {\r\n setIsHovered(false);\r\n setDropPosition(null);\r\n },\r\n onDrop: () => {\r\n setIsHovered(false);\r\n setDropPosition(null);\r\n },\r\n });\r\n },\r\n [item.id, index, disabled, showDropIndicator, dropIndicatorPosition]\r\n );\r\n\r\n useEffect(() => {\r\n const element = elementRef.current;\r\n if (!element) return;\r\n\r\n element.setAttribute(\"data-index\", index.toString());\r\n\r\n if (disabled) {\r\n // provide a no-op cleanup to satisfy all code paths\r\n return () => {};\r\n }\r\n\r\n // normal draggable + droptarget setup\r\n return combine(createDraggable(element), createDropTarget(element));\r\n }, [index, createDraggable, createDropTarget, disabled]);\r\n\r\n return (\r\n <div ref={elementRef} className={className} style={getItemStyles()}>\r\n {showDropIndicator && dropPosition === \"top\" && (\r\n <div\r\n className={dropIndicatorClassName}\r\n style={{\r\n ...defaultStyles.dropIndicator,\r\n ...dropIndicatorStyle,\r\n top: -1,\r\n }}\r\n />\r\n )}\r\n {children}\r\n {showDropIndicator && dropPosition === \"bottom\" && (\r\n <div\r\n className={dropIndicatorClassName}\r\n style={{\r\n ...defaultStyles.dropIndicator,\r\n ...dropIndicatorStyle,\r\n bottom: -1,\r\n }}\r\n />\r\n )}\r\n </div>\r\n );\r\n}\r\n","import { monitorForElements } from \"@atlaskit/pragmatic-drag-and-drop/element/adapter\";\r\nimport { extractClosestEdge } from \"@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge\";\r\nimport type { DraggableItem, OrderUpdate } from \"../types\";\r\nimport { reorder, calculateOrderUpdates } from \"../utils/order\";\r\n\r\nexport function useDragDropMonitor<T extends DraggableItem>({\r\n items,\r\n onReorder,\r\n disabled = false,\r\n}: {\r\n items: T[];\r\n onReorder: (newItems: T[], orderUpdates: OrderUpdate[]) => void;\r\n disabled?: boolean;\r\n}) {\r\n if (disabled) {\r\n return () => {};\r\n }\r\n\r\n\r\n const handleDrop = ({ location, source }: any) => {\r\n const sourceIndex = source.data?.index as number;\r\n if (sourceIndex === undefined) return;\r\n\r\n const { dropTargets } = location.current;\r\n const destinationTarget = dropTargets.find(\r\n (target: any) =>\r\n target.data?.type === \"draggable-item\" &&\r\n target.data?.id !== source.data?.id\r\n );\r\n\r\n if (!destinationTarget) return;\r\n\r\n const edge = extractClosestEdge(destinationTarget);\r\n const targetIndex = Number(\r\n destinationTarget.element.getAttribute(\"data-index\")\r\n );\r\n const destinationIndex = edge === \"bottom\" ? targetIndex + 1 : targetIndex;\r\n\r\n if (sourceIndex !== destinationIndex) {\r\n const oldItems = [...items];\r\n const newItems = reorder(items, sourceIndex, destinationIndex);\r\n const orderUpdates = calculateOrderUpdates(oldItems, newItems);\r\n onReorder(newItems, orderUpdates);\r\n }\r\n };\r\n\r\n return monitorForElements({\r\n onDrop: handleDrop,\r\n });\r\n}\r\n","import type { DraggableItem, OrderUpdate } from '../types';\r\n\r\nexport function reorder<T>(list: T[], startIndex: number, endIndex: number): T[] {\r\n const result = Array.from(list);\r\n const [removed] = result.splice(startIndex, 1);\r\n result.splice(endIndex, 0, removed);\r\n return result;\r\n}\r\n\r\nexport function calculateOrderUpdates<T extends DraggableItem>(oldItems: T[], newItems: T[]): OrderUpdate[] {\r\n const affected = newItems.filter((item, i) => item.id !== oldItems[i]?.id);\r\n const orderList = affected.slice().sort((a, b) => a.position - b.position).map(i => i.position);\r\n return affected.map((item, i) => ({ id: item.id, newPosition: orderList[i] }));\r\n}\r\n","import React, { useEffect, useRef, useState, useCallback } from \"react\";\r\nimport { combine } from \"@atlaskit/pragmatic-drag-and-drop/combine\";\r\nimport { dropTargetForElements } from \"@atlaskit/pragmatic-drag-and-drop/element/adapter\";\r\nimport { DraggableItemWrapper } from \"./DraggableItemWrapper\";\r\nimport type { DragDropListProps, DraggableItem } from \"../types\";\r\nimport { useDragDropMonitor } from \"../hooks/useDragDropMonitor\";\r\nimport { defaultStyles } from \"../styles/defaultStyles\";\r\n\r\nexport function DragDropList<T extends DraggableItem>({\r\n items,\r\n onReorder,\r\n renderItem,\r\n containerClassName = \"\",\r\n containerStyle = {},\r\n itemClassName = \"\",\r\n itemStyle = {},\r\n dragPreviewClassName = \"\",\r\n dragPreviewStyle = {},\r\n onDragStart,\r\n onDragEnd,\r\n disabled = false,\r\n gap,\r\n direction = \"vertical\",\r\n showDropIndicator = false,\r\n dropIndicatorClassName = \"\",\r\n dropIndicatorStyle = {},\r\n dropIndicatorPosition = \"bottom\",\r\n}: DragDropListProps<T>) {\r\n const containerRef = useRef<HTMLDivElement>(null);\r\n const monitor = useDragDropMonitor({ items, onReorder, disabled });\r\n const [isDraggingOver, setIsDraggingOver] = useState(false);\r\n\r\n const getContainerStyles = (): React.CSSProperties => {\r\n const baseStyle = { ...defaultStyles.container.default };\r\n\r\n if (direction === \"horizontal\") {\r\n Object.assign(baseStyle, defaultStyles.container.horizontal);\r\n }\r\n\r\n if (isDraggingOver) {\r\n Object.assign(baseStyle, defaultStyles.container.dragging);\r\n }\r\n\r\n if (gap !== undefined) {\r\n baseStyle.gap = typeof gap === \"number\" ? `${gap}px` : gap;\r\n }\r\n\r\n return { ...baseStyle, ...containerStyle };\r\n };\r\n\r\n const createDropTarget = useCallback(\r\n (element: HTMLElement) => {\r\n if (disabled) return () => {};\r\n\r\n return dropTargetForElements({\r\n element,\r\n getData: () => ({ type: \"container\" }),\r\n onDragEnter: () => setIsDraggingOver(true),\r\n onDragLeave: () => setIsDraggingOver(false),\r\n onDrop: () => setIsDraggingOver(false),\r\n });\r\n },\r\n [disabled]\r\n );\r\n\r\n useEffect(() => {\r\n const element = containerRef.current;\r\n if (!element || disabled) return;\r\n\r\n return combine(createDropTarget(element), monitor);\r\n }, [createDropTarget, monitor, disabled]);\r\n\r\n return (\r\n <div\r\n ref={containerRef}\r\n className={containerClassName}\r\n style={getContainerStyles()}\r\n >\r\n {items.map((item, index) => (\r\n <DraggableItemWrapper\r\n key={item.id}\r\n item={item}\r\n index={index}\r\n className={itemClassName}\r\n style={itemStyle}\r\n dragPreviewClassName={dragPreviewClassName}\r\n dragPreviewStyle={dragPreviewStyle}\r\n onDragStart={onDragStart}\r\n onDragEnd={onDragEnd}\r\n disabled={disabled}\r\n showDropIndicator={showDropIndicator}\r\n dropIndicatorClassName={dropIndicatorClassName}\r\n dropIndicatorStyle={dropIndicatorStyle}\r\n dropIndicatorPosition={dropIndicatorPosition}\r\n >\r\n {renderItem(item, index)}\r\n </DraggableItemWrapper>\r\n ))}\r\n </div>\r\n );\r\n}\r\n"],"names":["defaultStyles","container","default","minHeight","transition","borderRadius","border","backgroundColor","display","flexDirection","gap","padding","dragging","borderColor","horizontal","flexWrap","item","cursor","userSelect","position","opacity","hover","transform","boxShadow","disabled","preview","pointerEvents","zIndex","dropIndicator","height","left","right","DRAGGABLE_ITEM","DraggableItemWrapper","index","children","className","style","dragPreviewClassName","dragPreviewStyle","onDragStart","onDragEnd","showDropIndicator","dropIndicatorClassName","dropIndicatorStyle","dropIndicatorPosition","elementRef","useRef","isDragging","setIsDragging","useState","isHovered","setIsHovered","dropPosition","setDropPosition","createDraggable","useCallback","element","draggable","getInitialData","type","id","onGenerateDragPreview","nativeSetDragImage","previewElement","cloneNode","previewStyles","Object","assign","width","offsetWidth","offsetHeight","document","body","appendChild","requestAnimationFrame","remove","onDrop","createDropTarget","dropTargetForElements","getData","canDrop","args","_a","source","data","getIsSticky","onDragEnter","self","_b","onDragLeave","useEffect","current","setAttribute","toString","combine","React","createElement","ref","baseStyle","getItemStyles","top","bottom","useDragDropMonitor","items","onReorder","monitorForElements","location","sourceIndex","undefined","dropTargets","destinationTarget","find","target","_c","edge","extractClosestEdge","targetIndex","Number","getAttribute","destinationIndex","oldItems","newItems","list","startIndex","endIndex","result","Array","from","removed","splice","reorder","orderUpdates","affected","filter","i","orderList","slice","sort","a","b","map","newPosition","calculateOrderUpdates","DragDropList","renderItem","containerClassName","containerStyle","itemClassName","itemStyle","direction","containerRef","monitor","isDraggingOver","setIsDraggingOver","getContainerStyles","key"],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var e=require("react"),t=require("@atlaskit/pragmatic-drag-and-drop/combine"),
|
|
1
|
+
"use strict";var e=require("react"),t=require("@atlaskit/pragmatic-drag-and-drop/combine"),r=require("@atlaskit/pragmatic-drag-and-drop/element/adapter"),a=require("@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge");const o={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"}},i="draggable-item";function n({item:a,index:n,children:s,className:d="",style:l={},dragPreviewClassName:c="",dragPreviewStyle:g={},onDragStart:p,onDragEnd:u,disabled:m=!1,showDropIndicator:b=!1,dropIndicatorClassName:f="",dropIndicatorStyle:v={},dropIndicatorPosition:x="bottom"}){const D=e.useRef(null),[y,S]=e.useState(!1),[h,I]=e.useState(!1),[j,O]=e.useState(null),w=e.useCallback(e=>m?()=>{}:r.draggable({element:e,getInitialData:()=>({type:i,id:a.id,index:n}),onGenerateDragPreview:({nativeSetDragImage:t})=>{const r=e.cloneNode(!0),a=Object.assign(Object.assign({},o.preview),g);c&&(r.className=c),Object.assign(r.style,a,{width:`${(null==e?void 0:e.offsetWidth)||100}px`,height:`${(null==e?void 0:e.offsetHeight)||50}px`}),document.body.appendChild(r),t&&t(r,20,20),requestAnimationFrame(()=>r.remove())},onDragStart:()=>{S(!0),null==p||p(a,n)},onDrop:()=>{S(!1),null==u||u(a,n)}}),[a,n,c,g,p,u,m]),C=e.useCallback(e=>m?()=>{}:r.dropTargetForElements({element:e,getData:()=>({type:i,id:a.id,index:n}),canDrop:e=>{var t;return(null===(t=e.source.data)||void 0===t?void 0:t.type)===i},getIsSticky:()=>!0,onDragEnter:({source:e,self:t})=>{var r,a;(null===(r=e.data)||void 0===r?void 0:r.id)!==(null===(a=t.data)||void 0===a?void 0:a.id)&&(I(!0),b&&O(x))},onDragLeave:()=>{I(!1),O(null)},onDrop:()=>{I(!1),O(null)}}),[a.id,n,m,b,x]);return e.useEffect(()=>{const e=D.current;if(e)return e.setAttribute("data-index",n.toString()),m?()=>{}:t.combine(w(e),C(e))},[n,w,C,m]),e.createElement("div",{ref:D,className:d,style:(()=>{const e=Object.assign({},o.item.default);return m?Object.assign(e,o.item.disabled):y?Object.assign(e,o.item.dragging):h&&Object.assign(e,o.item.hover),Object.assign(Object.assign({},e),l)})()},b&&"top"===j&&e.createElement("div",{className:f,style:Object.assign(Object.assign(Object.assign({},o.dropIndicator),v),{top:-1})}),s,b&&"bottom"===j&&e.createElement("div",{className:f,style:Object.assign(Object.assign(Object.assign({},o.dropIndicator),v),{bottom:-1})}))}function s({items:e,onReorder:t,disabled:o=!1}){if(o)return()=>{};return r.monitorForElements({onDrop:({location:r,source:o})=>{var i;const n=null===(i=o.data)||void 0===i?void 0:i.index;if(void 0===n)return;const{dropTargets:s}=r.current,d=s.find(e=>{var t,r,a;return"draggable-item"===(null===(t=e.data)||void 0===t?void 0:t.type)&&(null===(r=e.data)||void 0===r?void 0:r.id)!==(null===(a=o.data)||void 0===a?void 0:a.id)});if(!d)return;const l=a.extractClosestEdge(d),c=Number(d.element.getAttribute("data-index")),g="bottom"===l?c+1:c;if(n!==g){const r=[...e],a=function(e,t,r){const a=Array.from(e),[o]=a.splice(t,1);return a.splice(r,0,o),a}(e,n,g),o=function(e,t){const r=t.filter((t,r)=>{var a;return t.id!==(null===(a=e[r])||void 0===a?void 0:a.id)}),a=r.slice().sort((e,t)=>e.position-t.position).map(e=>e.position);return r.map((e,t)=>({id:e.id,newPosition:a[t]}))}(r,a);t(a,o)}}})}exports.DragDropList=function({items:a,onReorder:i,renderItem:d,containerClassName:l="",containerStyle:c={},itemClassName:g="",itemStyle:p={},dragPreviewClassName:u="",dragPreviewStyle:m={},onDragStart:b,onDragEnd:f,disabled:v=!1,gap:x,direction:D="vertical",showDropIndicator:y=!1,dropIndicatorClassName:S="",dropIndicatorStyle:h={},dropIndicatorPosition:I="bottom"}){const j=e.useRef(null),O=s({items:a,onReorder:i,disabled:v}),[w,C]=e.useState(!1),E=e.useCallback(e=>v?()=>{}:r.dropTargetForElements({element:e,getData:()=>({type:"container"}),onDragEnter:()=>C(!0),onDragLeave:()=>C(!1),onDrop:()=>C(!1)}),[v]);return e.useEffect(()=>{const e=j.current;if(e&&!v)return t.combine(E(e),O)},[E,O,v]),e.createElement("div",{ref:j,className:l,style:(()=>{const e=Object.assign({},o.container.default);return"horizontal"===D&&Object.assign(e,o.container.horizontal),w&&Object.assign(e,o.container.dragging),void 0!==x&&(e.gap="number"==typeof x?`${x}px`:x),Object.assign(Object.assign({},e),c)})()},a.map((t,r)=>e.createElement(n,{key:t.id,item:t,index:r,className:g,style:p,dragPreviewClassName:u,dragPreviewStyle:m,onDragStart:b,onDragEnd:f,disabled:v,showDropIndicator:y,dropIndicatorClassName:S,dropIndicatorStyle:h,dropIndicatorPosition:I},d(t,r))))},exports.DraggableItemWrapper=n,exports.defaultStyles=o,exports.useDragDropMonitor=s;
|
|
2
2
|
//# sourceMappingURL=index.js.map
|