snap-dnd 0.1.2 → 0.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 +105 -0
- package/dist/behaviors/AutoScroll.d.ts +20 -0
- package/dist/behaviors/ConstraintAxis.d.ts +37 -0
- package/dist/behaviors/SnapGrid.d.ts +38 -0
- package/dist/behaviors/index.d.ts +3 -0
- package/dist/core/DragEngine.d.ts +60 -0
- package/dist/core/DragState.d.ts +67 -0
- package/dist/core/DropZone.d.ts +97 -0
- package/dist/core/Snap.d.ts +85 -0
- package/dist/core/index.d.ts +4 -0
- package/dist/index.d.ts +62 -0
- package/dist/plugins/FileDrop.d.ts +33 -0
- package/dist/plugins/Kanban.d.ts +40 -0
- package/dist/plugins/Sortable.d.ts +33 -0
- package/dist/plugins/index.d.ts +3 -0
- package/dist/sensors/FileSensor.d.ts +51 -0
- package/dist/sensors/PointerSensor.d.ts +79 -0
- package/dist/sensors/index.d.ts +2 -0
- package/dist/snap.core.js +2 -2
- package/dist/snap.core.js.map +4 -4
- package/dist/snap.esm.js +11 -11
- package/dist/snap.esm.js.map +4 -4
- package/dist/snap.umd.js +11 -11
- package/dist/snap.umd.js.map +4 -4
- package/dist/types/index.d.ts +161 -0
- package/dist/utils/BoundsCache.d.ts +54 -0
- package/dist/utils/DataTransfer.d.ts +32 -0
- package/dist/utils/EventEmitter.d.ts +37 -0
- package/dist/utils/ObjectPool.d.ts +38 -0
- package/dist/utils/RAFThrottle.d.ts +39 -0
- package/dist/utils/index.d.ts +5 -0
- package/package.json +1 -1
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core types for Snap drag and drop library
|
|
3
|
+
*/
|
|
4
|
+
export interface Point {
|
|
5
|
+
x: number;
|
|
6
|
+
y: number;
|
|
7
|
+
}
|
|
8
|
+
export interface Rect {
|
|
9
|
+
x: number;
|
|
10
|
+
y: number;
|
|
11
|
+
width: number;
|
|
12
|
+
height: number;
|
|
13
|
+
}
|
|
14
|
+
export type Unsubscribe = () => void;
|
|
15
|
+
export type Axis = 'x' | 'y' | 'both';
|
|
16
|
+
export interface DragSession {
|
|
17
|
+
readonly id: string;
|
|
18
|
+
readonly element: HTMLElement;
|
|
19
|
+
readonly origin: Point;
|
|
20
|
+
readonly data: DataTransfer;
|
|
21
|
+
current: Point;
|
|
22
|
+
delta: Point;
|
|
23
|
+
dropZone: HTMLElement | null;
|
|
24
|
+
phase: DragPhase;
|
|
25
|
+
}
|
|
26
|
+
export type DragPhase = 'pending' | 'dragging' | 'dropping' | 'cancelled';
|
|
27
|
+
export interface DataTransfer {
|
|
28
|
+
setData(type: string, value: unknown): void;
|
|
29
|
+
getData<T = unknown>(type: string): T | undefined;
|
|
30
|
+
hasType(type: string): boolean;
|
|
31
|
+
readonly types: string[];
|
|
32
|
+
clear(): void;
|
|
33
|
+
}
|
|
34
|
+
export interface DragStartEvent {
|
|
35
|
+
readonly element: HTMLElement;
|
|
36
|
+
readonly position: Point;
|
|
37
|
+
readonly data: DataTransfer;
|
|
38
|
+
cancel(): void;
|
|
39
|
+
}
|
|
40
|
+
export interface DragMoveEvent {
|
|
41
|
+
readonly element: HTMLElement;
|
|
42
|
+
readonly position: Point;
|
|
43
|
+
readonly delta: Point;
|
|
44
|
+
readonly dropZone: HTMLElement | null;
|
|
45
|
+
}
|
|
46
|
+
export interface DragEndEvent {
|
|
47
|
+
readonly element: HTMLElement;
|
|
48
|
+
readonly position: Point;
|
|
49
|
+
readonly delta: Point;
|
|
50
|
+
readonly cancelled: boolean;
|
|
51
|
+
}
|
|
52
|
+
export interface DropEvent {
|
|
53
|
+
readonly element: HTMLElement;
|
|
54
|
+
readonly dropZone: HTMLElement;
|
|
55
|
+
readonly position: Point;
|
|
56
|
+
readonly data: DataTransfer;
|
|
57
|
+
readonly insertionIndex?: number;
|
|
58
|
+
readonly sourceContainer?: HTMLElement;
|
|
59
|
+
}
|
|
60
|
+
export interface DropZoneEnterEvent {
|
|
61
|
+
readonly element: HTMLElement;
|
|
62
|
+
readonly dropZone: HTMLElement;
|
|
63
|
+
readonly position: Point;
|
|
64
|
+
}
|
|
65
|
+
export interface DropZoneLeaveEvent {
|
|
66
|
+
readonly element: HTMLElement;
|
|
67
|
+
readonly dropZone: HTMLElement;
|
|
68
|
+
}
|
|
69
|
+
export interface FileDropEvent {
|
|
70
|
+
readonly files: File[];
|
|
71
|
+
readonly position: Point;
|
|
72
|
+
readonly dropZone: HTMLElement;
|
|
73
|
+
}
|
|
74
|
+
export interface AutoScrollOptions {
|
|
75
|
+
threshold?: number;
|
|
76
|
+
maxSpeed?: number;
|
|
77
|
+
acceleration?: number;
|
|
78
|
+
}
|
|
79
|
+
export interface GridOptions {
|
|
80
|
+
x: number;
|
|
81
|
+
y: number;
|
|
82
|
+
}
|
|
83
|
+
export interface SortableOptions {
|
|
84
|
+
animation?: number;
|
|
85
|
+
ghostClass?: string;
|
|
86
|
+
placeholderClass?: string;
|
|
87
|
+
}
|
|
88
|
+
export interface KanbanOptions {
|
|
89
|
+
containers?: string;
|
|
90
|
+
items?: string;
|
|
91
|
+
animation?: number;
|
|
92
|
+
}
|
|
93
|
+
export interface FileDropOptions {
|
|
94
|
+
accept?: string[];
|
|
95
|
+
multiple?: boolean;
|
|
96
|
+
maxSize?: number;
|
|
97
|
+
}
|
|
98
|
+
export interface ItemOptions {
|
|
99
|
+
data?: Record<string, unknown>;
|
|
100
|
+
axis?: Axis;
|
|
101
|
+
handle?: string;
|
|
102
|
+
disabled?: boolean;
|
|
103
|
+
}
|
|
104
|
+
export interface DropZoneOptions {
|
|
105
|
+
accepts?: string[] | ((data: DataTransfer) => boolean);
|
|
106
|
+
onEnter?: (event: DropZoneEnterEvent) => void;
|
|
107
|
+
onLeave?: (event: DropZoneLeaveEvent) => void;
|
|
108
|
+
}
|
|
109
|
+
export interface SnapOptions {
|
|
110
|
+
draggableSelector?: string;
|
|
111
|
+
dropZoneSelector?: string;
|
|
112
|
+
handleSelector?: string;
|
|
113
|
+
axis?: Axis;
|
|
114
|
+
grid?: GridOptions;
|
|
115
|
+
delay?: number;
|
|
116
|
+
distance?: number;
|
|
117
|
+
autoScroll?: boolean | AutoScrollOptions;
|
|
118
|
+
onDragStart?: (event: DragStartEvent) => void | false;
|
|
119
|
+
onDragMove?: (event: DragMoveEvent) => void;
|
|
120
|
+
onDragEnd?: (event: DragEndEvent) => void;
|
|
121
|
+
onDrop?: (event: DropEvent) => void;
|
|
122
|
+
onDropZoneEnter?: (event: DropZoneEnterEvent) => void;
|
|
123
|
+
onDropZoneLeave?: (event: DropZoneLeaveEvent) => void;
|
|
124
|
+
sortable?: boolean | SortableOptions;
|
|
125
|
+
kanban?: boolean | KanbanOptions;
|
|
126
|
+
fileDrop?: boolean | FileDropOptions;
|
|
127
|
+
autoRefresh?: boolean;
|
|
128
|
+
ghostClass?: string;
|
|
129
|
+
placeholderClass?: string;
|
|
130
|
+
}
|
|
131
|
+
export type StateEvent = 'dragstart' | 'dragmove' | 'dragend' | 'dropzoneenter' | 'dropzoneleave' | 'drop';
|
|
132
|
+
export interface Sensor {
|
|
133
|
+
attach(): void;
|
|
134
|
+
detach(): void;
|
|
135
|
+
}
|
|
136
|
+
export interface Plugin {
|
|
137
|
+
name: string;
|
|
138
|
+
init(snap: SnapInstance): void;
|
|
139
|
+
destroy(): void;
|
|
140
|
+
}
|
|
141
|
+
export interface Behavior {
|
|
142
|
+
name: string;
|
|
143
|
+
onDragStart?(session: DragSession): void;
|
|
144
|
+
onDragMove?(session: DragSession): void;
|
|
145
|
+
onDragEnd?(session: DragSession): void;
|
|
146
|
+
destroy(): void;
|
|
147
|
+
}
|
|
148
|
+
export interface SnapInstance {
|
|
149
|
+
readonly options: SnapOptions;
|
|
150
|
+
enable(): void;
|
|
151
|
+
disable(): void;
|
|
152
|
+
destroy(): void;
|
|
153
|
+
refresh(): void;
|
|
154
|
+
setOptions(options: Partial<SnapOptions>): void;
|
|
155
|
+
addDraggable(element: HTMLElement, options?: ItemOptions): void;
|
|
156
|
+
removeDraggable(element: HTMLElement): void;
|
|
157
|
+
addDropZone(element: HTMLElement, options?: DropZoneOptions): void;
|
|
158
|
+
removeDropZone(element: HTMLElement): void;
|
|
159
|
+
isDragging(): boolean;
|
|
160
|
+
getActiveElement(): HTMLElement | null;
|
|
161
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cached bounding rect manager using WeakMap
|
|
3
|
+
* Automatically cleans up when elements are removed from DOM
|
|
4
|
+
*/
|
|
5
|
+
export declare class BoundsCache {
|
|
6
|
+
private _cache;
|
|
7
|
+
private _dirty;
|
|
8
|
+
private _invalidateAll;
|
|
9
|
+
/**
|
|
10
|
+
* Get cached bounds for an element, or compute and cache
|
|
11
|
+
*/
|
|
12
|
+
get(element: Element): DOMRect;
|
|
13
|
+
/**
|
|
14
|
+
* Mark a specific element's bounds as dirty
|
|
15
|
+
*/
|
|
16
|
+
invalidate(element: Element): void;
|
|
17
|
+
/**
|
|
18
|
+
* Mark all cached bounds as dirty (e.g., on scroll/resize)
|
|
19
|
+
*/
|
|
20
|
+
invalidateAll(): void;
|
|
21
|
+
/**
|
|
22
|
+
* Force update bounds for an element
|
|
23
|
+
*/
|
|
24
|
+
update(element: Element): DOMRect;
|
|
25
|
+
/**
|
|
26
|
+
* Remove element from cache
|
|
27
|
+
*/
|
|
28
|
+
remove(element: Element): void;
|
|
29
|
+
/**
|
|
30
|
+
* Clear the dirty flag after a frame
|
|
31
|
+
*/
|
|
32
|
+
clearDirty(): void;
|
|
33
|
+
private _update;
|
|
34
|
+
}
|
|
35
|
+
export declare const boundsCache: BoundsCache;
|
|
36
|
+
/**
|
|
37
|
+
* Check if a point is inside a rect
|
|
38
|
+
*/
|
|
39
|
+
export declare function pointInRect(x: number, y: number, rect: DOMRect): boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Check if two rects intersect
|
|
42
|
+
*/
|
|
43
|
+
export declare function rectsIntersect(a: DOMRect, b: DOMRect): boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Get the center point of a rect
|
|
46
|
+
*/
|
|
47
|
+
export declare function rectCenter(rect: DOMRect): {
|
|
48
|
+
x: number;
|
|
49
|
+
y: number;
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Calculate distance between two points
|
|
53
|
+
*/
|
|
54
|
+
export declare function distance(x1: number, y1: number, x2: number, y2: number): number;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom DataTransfer implementation for passing data during drag operations
|
|
3
|
+
* Not the browser's native DataTransfer
|
|
4
|
+
*/
|
|
5
|
+
import type { DataTransfer as IDataTransfer } from '../types/index.js';
|
|
6
|
+
export declare class SnapDataTransfer implements IDataTransfer {
|
|
7
|
+
private _data;
|
|
8
|
+
/**
|
|
9
|
+
* Set data for a given type
|
|
10
|
+
*/
|
|
11
|
+
setData(type: string, value: unknown): void;
|
|
12
|
+
/**
|
|
13
|
+
* Get data for a given type
|
|
14
|
+
*/
|
|
15
|
+
getData<T = unknown>(type: string): T | undefined;
|
|
16
|
+
/**
|
|
17
|
+
* Check if a type exists
|
|
18
|
+
*/
|
|
19
|
+
hasType(type: string): boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Get all registered types
|
|
22
|
+
*/
|
|
23
|
+
get types(): string[];
|
|
24
|
+
/**
|
|
25
|
+
* Clear all data
|
|
26
|
+
*/
|
|
27
|
+
clear(): void;
|
|
28
|
+
/**
|
|
29
|
+
* Create a copy of this transfer
|
|
30
|
+
*/
|
|
31
|
+
clone(): SnapDataTransfer;
|
|
32
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lightweight pub/sub event emitter
|
|
3
|
+
* Optimized for minimal allocations
|
|
4
|
+
*/
|
|
5
|
+
import type { Unsubscribe } from '../types/index.js';
|
|
6
|
+
export type EventCallback<T = unknown> = (data: T) => void;
|
|
7
|
+
export declare class EventEmitter<Events extends Record<string, unknown>> {
|
|
8
|
+
private _listeners;
|
|
9
|
+
/**
|
|
10
|
+
* Subscribe to an event
|
|
11
|
+
*/
|
|
12
|
+
on<K extends keyof Events>(event: K, callback: EventCallback<Events[K]>): Unsubscribe;
|
|
13
|
+
/**
|
|
14
|
+
* Subscribe to an event once
|
|
15
|
+
*/
|
|
16
|
+
once<K extends keyof Events>(event: K, callback: EventCallback<Events[K]>): Unsubscribe;
|
|
17
|
+
/**
|
|
18
|
+
* Emit an event to all subscribers
|
|
19
|
+
*/
|
|
20
|
+
emit<K extends keyof Events>(event: K, data: Events[K]): void;
|
|
21
|
+
/**
|
|
22
|
+
* Remove all listeners for an event, or all listeners
|
|
23
|
+
*/
|
|
24
|
+
off<K extends keyof Events>(event?: K): void;
|
|
25
|
+
/**
|
|
26
|
+
* Check if there are any listeners for an event
|
|
27
|
+
*/
|
|
28
|
+
hasListeners<K extends keyof Events>(event: K): boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Get the number of listeners for an event
|
|
31
|
+
*/
|
|
32
|
+
listenerCount<K extends keyof Events>(event: K): number;
|
|
33
|
+
/**
|
|
34
|
+
* Clear all listeners
|
|
35
|
+
*/
|
|
36
|
+
destroy(): void;
|
|
37
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generic object pool for reusing frequently allocated objects
|
|
3
|
+
* Reduces GC pressure during drag operations
|
|
4
|
+
*/
|
|
5
|
+
export declare class ObjectPool<T> {
|
|
6
|
+
private _pool;
|
|
7
|
+
private _factory;
|
|
8
|
+
private _reset;
|
|
9
|
+
private _maxSize;
|
|
10
|
+
constructor(factory: () => T, reset: (obj: T) => void, initialSize?: number, maxSize?: number);
|
|
11
|
+
/**
|
|
12
|
+
* Get an object from the pool or create a new one
|
|
13
|
+
*/
|
|
14
|
+
acquire(): T;
|
|
15
|
+
/**
|
|
16
|
+
* Return an object to the pool for reuse
|
|
17
|
+
*/
|
|
18
|
+
release(obj: T): void;
|
|
19
|
+
/**
|
|
20
|
+
* Clear all pooled objects
|
|
21
|
+
*/
|
|
22
|
+
clear(): void;
|
|
23
|
+
/**
|
|
24
|
+
* Current pool size
|
|
25
|
+
*/
|
|
26
|
+
get size(): number;
|
|
27
|
+
}
|
|
28
|
+
import type { Point, Rect } from '../types/index.js';
|
|
29
|
+
export declare const pointPool: ObjectPool<Point>;
|
|
30
|
+
export declare const rectPool: ObjectPool<Rect>;
|
|
31
|
+
/**
|
|
32
|
+
* Helper to get a point from pool with initial values
|
|
33
|
+
*/
|
|
34
|
+
export declare function acquirePoint(x: number, y: number): Point;
|
|
35
|
+
/**
|
|
36
|
+
* Helper to get a rect from pool with initial values
|
|
37
|
+
*/
|
|
38
|
+
export declare function acquireRect(x: number, y: number, width: number, height: number): Rect;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RAF-based throttling for high-frequency events
|
|
3
|
+
* Ensures only one callback per animation frame
|
|
4
|
+
*/
|
|
5
|
+
export declare class RAFThrottle<T> {
|
|
6
|
+
private _rafId;
|
|
7
|
+
private _pending;
|
|
8
|
+
private _callback;
|
|
9
|
+
constructor(callback: (data: T) => void);
|
|
10
|
+
/**
|
|
11
|
+
* Queue data to be processed on next animation frame
|
|
12
|
+
* Only the most recent data will be processed
|
|
13
|
+
*/
|
|
14
|
+
queue(data: T): void;
|
|
15
|
+
/**
|
|
16
|
+
* Cancel any pending frame
|
|
17
|
+
*/
|
|
18
|
+
cancel(): void;
|
|
19
|
+
/**
|
|
20
|
+
* Process immediately if there's pending data
|
|
21
|
+
*/
|
|
22
|
+
flush(): void;
|
|
23
|
+
/**
|
|
24
|
+
* Check if there's a pending frame
|
|
25
|
+
*/
|
|
26
|
+
get isPending(): boolean;
|
|
27
|
+
private _process;
|
|
28
|
+
/**
|
|
29
|
+
* Cleanup
|
|
30
|
+
*/
|
|
31
|
+
destroy(): void;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Create a throttled function using RAF
|
|
35
|
+
*/
|
|
36
|
+
export declare function rafThrottle<T extends (...args: unknown[]) => void>(fn: T): T & {
|
|
37
|
+
cancel: () => void;
|
|
38
|
+
flush: () => void;
|
|
39
|
+
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { ObjectPool, pointPool, rectPool, acquirePoint, acquireRect } from './ObjectPool.js';
|
|
2
|
+
export { EventEmitter, type EventCallback } from './EventEmitter.js';
|
|
3
|
+
export { BoundsCache, boundsCache, pointInRect, rectsIntersect, rectCenter, distance } from './BoundsCache.js';
|
|
4
|
+
export { RAFThrottle, rafThrottle } from './RAFThrottle.js';
|
|
5
|
+
export { SnapDataTransfer } from './DataTransfer.js';
|