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 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
  [![npm version](https://img.shields.io/npm/v/react-dragdrop-kit.svg)](https://www.npmjs.com/package/react-dragdrop-kit)
7
7
  [![npm downloads](https://img.shields.io/npm/dm/react-dragdrop-kit.svg)](https://www.npmjs.com/package/react-dragdrop-kit)
8
- [![bundle size](https://img.shields.io/bundlephobia/minzip/react-dragdrop-kit)](https://bundlephobia.com/package/react-dragdrop-kit)
8
+ [![npm unpacked size](https://img.shields.io/npm/unpacked-size/react-dragdrop-kit)](https://www.npmjs.com/package/react-dragdrop-kit)
9
9
  [![license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/Yourstruggle11/react-dragdrop-kit)
10
10
  [![Ask DeepWiki](https://deepwiki.com/badge.svg)](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
- ### Kanban module
34
-
35
- - Card reorder within columns
36
- - Card movement across columns
37
- - Column reordering
38
- - Headless rendering (`renderColumn`, `renderCard`)
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
- ### General
43
-
44
- - TypeScript-first API
45
- - Lightweight runtime and tree-shakeable exports
46
- - Built on `@atlaskit/pragmatic-drag-and-drop`
47
-
48
- ## Installation
49
-
50
- ```bash
51
- npm install react-dragdrop-kit
52
- # or
53
- pnpm add react-dragdrop-kit
54
- # or
55
- yarn add react-dragdrop-kit
56
- ```
57
-
58
- ## Package entry points
59
-
60
- ```ts
61
- import { DragDropList } from "react-dragdrop-kit";
62
- ```
63
-
64
- ```ts
65
- import { KanbanBoard, applyDragResult } from "react-dragdrop-kit/kanban";
66
- ```
67
-
68
- ## Quick start: sortable list
69
-
70
- ```tsx
71
- import { useState } from "react";
72
- import { DragDropList } from "react-dragdrop-kit";
73
-
74
- interface Todo {
75
- id: string;
76
- position: number;
77
- title: string;
78
- }
79
-
80
- export default function TodoList() {
81
- const [items, setItems] = useState<Todo[]>([
82
- { id: "1", position: 0, title: "Design" },
83
- { id: "2", position: 1, title: "Build" },
84
- { id: "3", position: 2, title: "Ship" },
85
- ]);
86
-
87
- return (
88
- <DragDropList
89
- items={items}
90
- onReorder={(next) =>
91
- setItems(next.map((item, index) => ({ ...item, position: index })))
92
- }
93
- renderItem={(item) => (
94
- <div style={{ padding: 12, border: "1px solid #e5e7eb", borderRadius: 8 }}>
95
- {item.title}
96
- </div>
97
- )}
98
- showDropIndicator
99
- gap={8}
100
- />
101
- );
102
- }
103
- ```
104
-
105
- ## Quick start: drag handle and multi-drag
106
-
107
- ```tsx
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
- ## Quick start: Kanban board
125
-
126
- ```tsx
127
- import { useCallback, useState } from "react";
128
- import {
129
- KanbanBoard,
130
- applyDragResult,
131
- type DropResult,
132
- type KanbanBoardState,
133
- } from "react-dragdrop-kit/kanban";
134
-
135
- export default function Board() {
136
- const [state, setState] = useState<KanbanBoardState>({
137
- columns: [
138
- { id: "todo", title: "To Do", cardIds: ["task-1", "task-2"] },
139
- { id: "done", title: "Done", cardIds: [] },
140
- ],
141
- cards: {
142
- "task-1": { id: "task-1", title: "Design landing page" },
143
- "task-2": { id: "task-2", title: "Implement auth" },
144
- },
145
- });
146
-
147
- const handleDragEnd = useCallback(
148
- (result: DropResult, stateBefore: KanbanBoardState) => {
149
- if (!result.destination) return;
150
- setState(applyDragResult(stateBefore, result));
151
- },
152
- []
153
- );
154
-
155
- return (
156
- <KanbanBoard
157
- state={state}
158
- onDragEnd={handleDragEnd}
159
- renderColumn={(column) => <div style={{ padding: 12 }}>{column.title}</div>}
160
- renderCard={(card) => <div style={{ padding: 12 }}>{card.title}</div>}
161
- />
162
- );
163
- }
164
- ```
165
-
166
- ## API reference: list module
167
-
168
- ### Core types
169
-
170
- ```ts
171
- type DraggableItem = {
172
- id: string;
173
- position: number;
174
- [key: string]: any;
175
- };
176
-
177
- type OrderUpdate = {
178
- id: string;
179
- newPosition: number;
180
- moved?: boolean;
181
- };
182
- ```
183
-
184
- ### DragDropList props
185
-
186
- | Prop | Type | Default | Description |
187
- | --- | --- | --- | --- |
188
- | `items` | `T[]` | Required | Controlled items. Each item must include `id` and `position`. |
189
- | `onReorder` | `(newItems: T[], orderUpdates: OrderUpdate[]) => void` | Required | Fired after successful drop/reorder. |
190
- | `renderItem` | `(item: T, index: number) => ReactNode` | Required | Item renderer. |
191
- | `containerClassName` | `string` | `""` | Class name for container. |
192
- | `containerStyle` | `React.CSSProperties` | `{}` | Inline style for container. |
193
- | `itemClassName` | `string` | `""` | Class for each draggable wrapper. |
194
- | `itemStyle` | `React.CSSProperties` | `{}` | Style for each draggable wrapper. |
195
- | `dragPreviewClassName` | `string` | `""` | Class for generated drag preview. |
196
- | `dragPreviewStyle` | `React.CSSProperties` | `{}` | Style for generated drag preview. |
197
- | `onDragStart` | `(item: T, index: number) => void` | `undefined` | Callback on item drag start. |
198
- | `onDragEnd` | `(item: T, index: number) => void` | `undefined` | Callback on item drag end. |
199
- | `disabled` | `boolean` | `false` | Disables list drag/drop. |
200
- | `gap` | `number \| string` | `undefined` | Gap applied to container. |
201
- | `direction` | `"vertical" \| "horizontal"` | `"vertical"` | Layout and closest-edge interpretation. |
202
- | `showDropIndicator` | `boolean` | `false` | Enables drop indicator line. |
203
- | `dropIndicatorClassName` | `string` | `""` | Class for drop indicator. |
204
- | `dropIndicatorStyle` | `React.CSSProperties` | `{}` | Style for drop indicator. |
205
- | `dropIndicatorPosition` | `"top" \| "bottom"` | `"bottom"` | Indicator position for hovered target item. |
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
- ## API reference: Kanban module
211
-
212
- The full Kanban API is documented in [docs/kanban.md](./docs/kanban.md).
213
-
214
- Exports:
215
-
216
- - Components: `KanbanBoard`, `KanbanColumnView`, `KanbanCardView`
217
- - Hooks: `useKanbanDnd`, `useAutoscroll`
218
- - A11y: `AnnouncerProvider`, `useAnnouncer`, `announcements`
219
- - Utils: `applyDragResult`, `reorderArray`
220
- - Types: `KanbanBoardState`, `DropResult`, `KanbanCard`, `KanbanColumn`, and more
221
-
222
- ## Examples
223
-
224
- ### Repository examples
225
-
226
- - `examples/basic-example.tsx`
227
- - `examples/advanced-features.tsx`
228
- - `examples/material-ui-example.tsx`
229
- - `examples/tailwind-example.tsx`
230
- - `examples/kanban/basic-kanban.tsx`
231
- - `examples/kanban/rich-cards-kanban.tsx`
232
- - `examples/kanban/themed-kanban.tsx`
233
- - `examples/kanban/accessible-kanban.tsx`
234
-
235
- ### Demo examples
236
-
237
- - List/grid examples under `apps/demo/src/examples/*`
238
- - Kanban demos:
239
- - `apps/demo/src/examples/BasicKanban/index.tsx`
240
- - `apps/demo/src/examples/RichKanban/index.tsx`
241
- - `apps/demo/src/examples/SwimlanesKanban/index.tsx`
242
- - `apps/demo/src/examples/WipLimitsKanban/index.tsx`
243
-
244
- ## Migration notes
245
-
246
- ### From react-beautiful-dnd
247
-
248
- High-level mapping for Kanban use cases:
249
-
250
- - `DragDropContext` -> `KanbanBoard`
251
- - `Droppable` -> `KanbanColumnView`
252
- - `Draggable` -> `KanbanCardView`
253
-
254
- Important differences:
255
-
256
- 1. State is normalized (`columns` + `cards`) instead of nested.
257
- 2. IDs are explicit and owned by your app.
258
- 3. Rendering is done via render functions (`renderColumn`, `renderCard`).
259
-
260
- ## Development notes
261
-
262
- ### React Strict Mode
263
-
264
- In development, React Strict Mode can mount effects twice.
265
- Ensure listener setup and cleanup are idempotent when integrating custom logic.
266
-
267
- ## Bundle size
268
-
269
- Approximate minified sizes:
270
-
271
- - `react-dragdrop-kit`: about 5KB
272
- - `react-dragdrop-kit/kanban`: about 9KB
273
-
274
- ## Documentation and links
275
-
276
- - [Kanban guide](./docs/kanban.md)
277
- - [Known issues](./KNOWN_ISSUES.md)
278
- - [Changelog](./packages/react-dragdrop-kit/CHANGELOG.md)
279
- - [Examples folder](./examples)
280
- - [Demo app](https://react-dragdrop-kit.netlify.app/)
281
-
282
- ## Support
283
-
284
- - [Report issues](https://github.com/Yourstruggle11/react-dragdrop-kit/issues)
285
- - [Request features](https://github.com/Yourstruggle11/react-dragdrop-kit/issues/new)
286
-
287
- ## License
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