dnd-manager 1.2.0 → 1.3.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/CHANGELOG.md +25 -0
- package/LICENSE +0 -0
- package/README.md +290 -768
- package/dist/index.d.mts +146 -12
- package/dist/index.mjs +468 -77
- package/dist/index.mjs.map +1 -1
- package/package.json +16 -13
package/dist/index.d.mts
CHANGED
|
@@ -18,6 +18,24 @@ type DragDropConfig = {
|
|
|
18
18
|
* dragThreshold: 15 // Harder to start drag (better for mobile scroll)
|
|
19
19
|
*/
|
|
20
20
|
dragThreshold?: number;
|
|
21
|
+
/**
|
|
22
|
+
* Milliseconds a press must be held, moving at most `dragDelayTolerance`, before it becomes a
|
|
23
|
+
* drag: a long press, so a touch list still scrolls under a swiping finger. A number applies to
|
|
24
|
+
* every pointer type; an object sets it per type (`{ touch: 250 }`: a mouse still drags at once).
|
|
25
|
+
* Moving further during the delay releases the press and leaves the gesture to the browser. Once
|
|
26
|
+
* the delay passes the drag starts at once, without waiting for a move.
|
|
27
|
+
* @default 0
|
|
28
|
+
*/
|
|
29
|
+
dragDelay?: number | {
|
|
30
|
+
mouse?: number;
|
|
31
|
+
pen?: number;
|
|
32
|
+
touch?: number;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Pixels a press may move during `dragDelay` before it is released.
|
|
36
|
+
* @default 5
|
|
37
|
+
*/
|
|
38
|
+
dragDelayTolerance?: number;
|
|
21
39
|
/**
|
|
22
40
|
* Maximum distance in pixels between pointerdown and pointerup to treat as a click/tap.
|
|
23
41
|
* Used to distinguish intentional clicks from cancelled drag attempts.
|
|
@@ -29,8 +47,11 @@ type DragDropConfig = {
|
|
|
29
47
|
*/
|
|
30
48
|
clickThreshold?: number;
|
|
31
49
|
/**
|
|
32
|
-
* Distance in pixels from
|
|
33
|
-
*
|
|
50
|
+
* Distance in pixels from an edge that triggers auto-scrolling during drag.
|
|
51
|
+
* Near an edge of the closest scroll container under the pointer that can still scroll that way
|
|
52
|
+
* (an `overflow: auto | scroll` element), that container scrolls; its zone is at most a quarter
|
|
53
|
+
* of its size. Otherwise the window scrolls near the viewport's edges. Scrolling continues while
|
|
54
|
+
* the pointer rests in the zone.
|
|
34
55
|
* @default 100
|
|
35
56
|
* @example
|
|
36
57
|
* scrollThreshold: 50 // Start scrolling closer to edges
|
|
@@ -38,8 +59,8 @@ type DragDropConfig = {
|
|
|
38
59
|
*/
|
|
39
60
|
scrollThreshold?: number;
|
|
40
61
|
/**
|
|
41
|
-
* Scroll speed in pixels per animation frame during auto-scroll.
|
|
42
|
-
* Higher values = faster scrolling when dragging near
|
|
62
|
+
* Scroll speed in pixels per animation frame during auto-scroll (`0` disables it).
|
|
63
|
+
* Higher values = faster scrolling when dragging near edges.
|
|
43
64
|
* @default 10
|
|
44
65
|
* @example
|
|
45
66
|
* scrollSpeed: 5 // Slower, smoother scroll
|
|
@@ -81,17 +102,57 @@ type DragDropConfig = {
|
|
|
81
102
|
* droppableKind: 'zone' // Can drop on zones
|
|
82
103
|
*/
|
|
83
104
|
droppableKind: string | string[];
|
|
105
|
+
/**
|
|
106
|
+
* Where droppables are looked for under the pointer.
|
|
107
|
+
* - `'document'`: anywhere in the page, so items can move to another manager's container (a box
|
|
108
|
+
* and a party panel each with its own manager).
|
|
109
|
+
* - `'container'`: only inside this manager's container, for independent widgets on one page
|
|
110
|
+
* that share kinds.
|
|
111
|
+
* @default 'document'
|
|
112
|
+
*/
|
|
113
|
+
dropScope?: 'document' | 'container';
|
|
114
|
+
/**
|
|
115
|
+
* Keyboard pick-and-place. Space or Enter on a focused draggable (make it focusable: a
|
|
116
|
+
* `<button>`, or `tabindex="0"`) picks it up; the arrow keys move the target to the nearest
|
|
117
|
+
* droppable in that direction (scrolled into view); Space or Enter drops there (ignored on a
|
|
118
|
+
* target `canDrop` rejects); Escape cancels (whatever `cancelOnEscape` says), and so do Tab and
|
|
119
|
+
* focus leaving the source. The callbacks fire as for a pointer drag, `onDragMove` with the
|
|
120
|
+
* target's center. Announce the moves from them in an `aria-live` region.
|
|
121
|
+
* @default false
|
|
122
|
+
*/
|
|
123
|
+
keyboard?: boolean;
|
|
124
|
+
/**
|
|
125
|
+
* Let a press focus the draggable, as a click would. By default the manager cancels the
|
|
126
|
+
* `pointerdown`, which keeps the browser from selecting text or dragging an image natively, but
|
|
127
|
+
* also from moving focus. With `true` it cancels `selectstart` and `dragstart` during the press
|
|
128
|
+
* instead: the source is focused (no focus ring for a mouse, per `:focus-visible`), so focus
|
|
129
|
+
* styles, keyboard follow-ups and a virtual list that keeps its focused row rendered all work.
|
|
130
|
+
* @default false
|
|
131
|
+
*/
|
|
132
|
+
focusOnPress?: boolean;
|
|
84
133
|
};
|
|
85
134
|
type PointerPosition = {
|
|
86
135
|
x: number;
|
|
87
136
|
y: number;
|
|
88
137
|
};
|
|
138
|
+
/** Result passed to onDragEnd when the item was dropped on a valid target; null when drag was cancelled or dropped on invalid target. */
|
|
139
|
+
type DragEndResult<TItem, TPosition> = {
|
|
140
|
+
sourcePosition: TPosition;
|
|
141
|
+
targetPosition: TPosition;
|
|
142
|
+
sourceItem: TItem;
|
|
143
|
+
};
|
|
89
144
|
type DragDropCallbacks<TItem, TPosition> = {
|
|
90
|
-
/** Called when determining if an element can be dragged */canDrag?: (element: HTMLElement, position: TPosition) => boolean;
|
|
91
|
-
|
|
145
|
+
/** Called when determining if an element can be dragged */canDrag?: (element: HTMLElement, position: TPosition) => boolean;
|
|
146
|
+
/**
|
|
147
|
+
* Called for the droppable under the pointer on every drag frame, and again at the drop: return
|
|
148
|
+
* `false` to reject it. A rejected droppable gets `data-drop-invalid` instead of `data-hovered`,
|
|
149
|
+
* and a drop on it ends the drag with `onDragEnd(null)`. Keep it cheap.
|
|
150
|
+
*/
|
|
151
|
+
canDrop?: (sourcePosition: TPosition, targetPosition: TPosition, sourceItem: TItem) => boolean; /** Called when drag starts (after threshold is met) */
|
|
152
|
+
onDragStart?: (element: HTMLElement, position: TPosition, item: TItem) => void; /** Called continuously during drag, with the droppable that would receive a drop (or null) */
|
|
92
153
|
onDragMove?: (pos: PointerPosition, hoveredElement: HTMLElement | null) => void; /** Called when item is dropped on a valid target */
|
|
93
|
-
onDrop?: (sourcePosition: TPosition, targetPosition: TPosition, sourceItem: TItem) => void; /** Called when drag ends (
|
|
94
|
-
onDragEnd?: () => void; /** Called on simple click/tap (no drag) */
|
|
154
|
+
onDrop?: (sourcePosition: TPosition, targetPosition: TPosition, sourceItem: TItem) => void; /** Called when drag ends (success or cancel). Receives drop result when dropped on valid target, null otherwise. Use for reordering DOM/state and cleanup. */
|
|
155
|
+
onDragEnd?: (result: DragEndResult<TItem, TPosition> | null) => void; /** Called on simple click/tap (no drag) */
|
|
95
156
|
onClick?: (element: HTMLElement, position: TPosition) => void; /** Called to extract item data from an element */
|
|
96
157
|
getItemData?: (element: HTMLElement, position: TPosition) => TItem | null; /** Called to get the custom position/coordinates of an element */
|
|
97
158
|
getItemPosition: (element: HTMLElement, kind: string) => TPosition | null;
|
|
@@ -101,9 +162,12 @@ type DragState<TItem, TPosition> = {
|
|
|
101
162
|
sourceElement: HTMLElement | null;
|
|
102
163
|
sourcePosition: TPosition | null;
|
|
103
164
|
sourceItem: TItem | null;
|
|
104
|
-
activePointerId: number | null;
|
|
165
|
+
activePointerId: number | null; /** What drives the current press or drag. */
|
|
166
|
+
input: 'pointer' | 'keyboard' | null;
|
|
105
167
|
isDragging: boolean;
|
|
106
|
-
lastHoveredElement: HTMLElement | null;
|
|
168
|
+
lastHoveredElement: HTMLElement | null; /** The droppable under the pointer that `canDrop` rejected (marked `data-drop-invalid`). */
|
|
169
|
+
lastInvalidElement: HTMLElement | null; /** Set when drop on valid target; passed to onDragEnd in cleanup */
|
|
170
|
+
lastDropResult: DragEndResult<TItem, TPosition> | null;
|
|
107
171
|
};
|
|
108
172
|
declare class DragDropManager<TItem = unknown, TPosition = unknown> {
|
|
109
173
|
private container;
|
|
@@ -114,22 +178,92 @@ declare class DragDropManager<TItem = unknown, TPosition = unknown> {
|
|
|
114
178
|
private state;
|
|
115
179
|
private rafId;
|
|
116
180
|
private lastPointerPos;
|
|
181
|
+
/**
|
|
182
|
+
* Set while a drag holds the pointer down: the browser follows the release with a native
|
|
183
|
+
* `click` (on the source element under pointer capture), which must not activate it.
|
|
184
|
+
*/
|
|
185
|
+
private suppressClickOnRelease;
|
|
186
|
+
private releaseClickBlocker;
|
|
187
|
+
/** The pending `dragDelay` of the current press. */
|
|
188
|
+
private delayTimer;
|
|
189
|
+
private activePointerType;
|
|
190
|
+
/** The droppable a keyboard drag points at. */
|
|
191
|
+
private keyboardTarget;
|
|
192
|
+
/**
|
|
193
|
+
* The key that picked up or dropped: its `keyup` would activate a focused button (Space clicks
|
|
194
|
+
* on keyup), so it is swallowed.
|
|
195
|
+
*/
|
|
196
|
+
private swallowKeyUp;
|
|
117
197
|
private boundHandlers;
|
|
118
198
|
constructor(containerRef: {
|
|
119
199
|
current: HTMLElement | null;
|
|
120
200
|
} | string | HTMLElement, config: DragDropConfig, callbacks: DragDropCallbacks<TItem, TPosition>);
|
|
121
201
|
private attachListeners;
|
|
202
|
+
/**
|
|
203
|
+
* The source position and item of the draggable `match`, if it may be dragged: it has a
|
|
204
|
+
* position, is not `data-empty`, `canDrag` allows it and it has item data.
|
|
205
|
+
*/
|
|
206
|
+
private resolveSource;
|
|
122
207
|
private handlePointerDown;
|
|
123
208
|
private handlePointerMove;
|
|
209
|
+
private startDrag;
|
|
210
|
+
/** The `dragDelay` for a pointer type (`''` from a constructed event counts as a mouse). */
|
|
211
|
+
private delayFor;
|
|
212
|
+
/**
|
|
213
|
+
* Once a touch press is a drag, the finger moves the item, not the page: a browser that starts
|
|
214
|
+
* panning would cancel the pointer. Before that, touches stay the browser's.
|
|
215
|
+
*/
|
|
216
|
+
private handleTouchMove;
|
|
217
|
+
/**
|
|
218
|
+
* The press's pointer events, heard on the source itself. While it is in the DOM they also reach
|
|
219
|
+
* the window's listeners, which handle them; once it is detached only these hear them.
|
|
220
|
+
*/
|
|
221
|
+
private handleDetachedSourcePointer;
|
|
222
|
+
/** A long press opens no context menu (Android, iOS) while it is a drag or about to be one. */
|
|
223
|
+
private handleContextMenu;
|
|
224
|
+
private scheduleFrame;
|
|
225
|
+
/** One drag frame: hover feedback, auto-scroll and `onDragMove` at the latest pointer position. */
|
|
226
|
+
private runFrame;
|
|
124
227
|
private handlePointerUp;
|
|
125
228
|
private handlePointerCancel;
|
|
126
229
|
private handleKeyDown;
|
|
127
230
|
private handleMouseOut;
|
|
128
|
-
|
|
231
|
+
/** Space or Enter on a focused draggable picks it up (`keyboard: true`). */
|
|
232
|
+
private handlePickUpKey;
|
|
233
|
+
/** The keys of a keyboard drag, ahead of anything else on the page. */
|
|
234
|
+
private handleKeyboardDragKey;
|
|
235
|
+
private handleKeyUp;
|
|
236
|
+
/** Focus leaving the source (Tab, a click elsewhere) cancels a keyboard drag. */
|
|
237
|
+
private handleFocusOut;
|
|
238
|
+
/** Makes `match` the keyboard drag's target: marked, scrolled into view, sent to `onDragMove`. */
|
|
239
|
+
private pointKeyboardAt;
|
|
240
|
+
/**
|
|
241
|
+
* The droppable nearest the current target (or the source) in a direction: its center lies that
|
|
242
|
+
* way, and it is closest along the axis, with distance across the axis counting double, so the
|
|
243
|
+
* next cell in the same row or column wins over a diagonal one.
|
|
244
|
+
*/
|
|
245
|
+
private nearestDroppable;
|
|
246
|
+
/** Drops a keyboard drag on its target, unless there is none or `canDrop` rejects it. */
|
|
247
|
+
private dropWithKeyboard;
|
|
248
|
+
/**
|
|
249
|
+
* Swallows the `click` the browser dispatches right after the release that ended a drag, in the
|
|
250
|
+
* same task; a timeout lets the blocker go when no click comes.
|
|
251
|
+
*/
|
|
252
|
+
private blockNextClick;
|
|
129
253
|
private cleanup;
|
|
130
254
|
private getPointerId;
|
|
131
255
|
private isActivePointer;
|
|
132
256
|
private normalizeKindList;
|
|
257
|
+
/** The target position of the droppable `match` if the current source may drop there. */
|
|
258
|
+
private acceptedPosition;
|
|
259
|
+
/**
|
|
260
|
+
* Marks the droppable under the pointer: `data-hovered` when it would receive a drop (also the
|
|
261
|
+
* source itself, for "drag over itself" styling), `data-drop-invalid` when `canDrop` rejects it.
|
|
262
|
+
* Without `canDrop` every droppable is marked hovered.
|
|
263
|
+
*/
|
|
264
|
+
private markTarget;
|
|
265
|
+
/** The droppable around `element` (the one under the pointer), within `dropScope`. */
|
|
266
|
+
private findDroppable;
|
|
133
267
|
/**
|
|
134
268
|
* Find closest ancestor element with a `data-kind` matching any expected kind.
|
|
135
269
|
*/
|
|
@@ -171,5 +305,5 @@ declare class DragPreviewController {
|
|
|
171
305
|
destroy(): void;
|
|
172
306
|
}
|
|
173
307
|
//#endregion
|
|
174
|
-
export { type DragDropCallbacks, type DragDropConfig, DragDropManager, DragPreviewController, type DragPreviewControllerOptions, type PointerPosition };
|
|
308
|
+
export { type DragDropCallbacks, type DragDropConfig, DragDropManager, type DragEndResult, DragPreviewController, type DragPreviewControllerOptions, type PointerPosition };
|
|
175
309
|
//# sourceMappingURL=index.d.mts.map
|