0
# Events
1
2
Shopify Draggable provides a comprehensive event system with drag events, specialized events for each draggable type, and plugin-specific events. All events extend AbstractEvent and support cancellation.
3
4
## Capabilities
5
6
### Base Event Class
7
8
All events inherit from AbstractEvent providing common functionality.
9
10
```typescript { .api }
11
/**
12
* Base class for all draggable events
13
*/
14
abstract class AbstractEvent<TData = {[key: string]: any}> {
15
readonly type: string;
16
readonly cancelable: boolean;
17
constructor(data: TData);
18
cancel(): void;
19
canceled(): boolean;
20
clone(data?: Partial<TData>): AbstractEvent<TData>;
21
}
22
23
export {AbstractEvent as BaseEvent};
24
```
25
26
**Usage Example:**
27
28
```typescript
29
draggable.on('drag:start', (event) => {
30
console.log('Event type:', event.type);
31
console.log('Can cancel:', event.cancelable);
32
33
// Cancel the event if needed
34
if (shouldCancelDrag()) {
35
event.cancel();
36
}
37
38
// Check if event was canceled
39
if (event.canceled()) {
40
console.log('Event was canceled');
41
}
42
});
43
```
44
45
### Core Drag Events
46
47
Base drag events that fire during drag operations for all draggable types.
48
49
```typescript { .api }
50
class DragEvent extends AbstractEvent {
51
readonly source: HTMLElement;
52
readonly originalSource: HTMLElement;
53
readonly mirror: HTMLElement;
54
readonly sourceContainer: HTMLElement;
55
readonly sensorEvent: SensorEvent;
56
readonly originalEvent: Event;
57
}
58
59
class DragStartEvent extends DragEvent {}
60
class DragMoveEvent extends DragEvent {}
61
class DragStopEvent extends DragEvent {}
62
class DragStoppedEvent extends DragEvent {}
63
64
class DragOverEvent extends DragEvent {
65
readonly overContainer: HTMLElement;
66
readonly over: HTMLElement;
67
}
68
69
class DragOutEvent extends DragEvent {
70
readonly overContainer: HTMLElement;
71
readonly over: HTMLElement;
72
}
73
74
class DragOverContainerEvent extends DragEvent {
75
readonly overContainer: HTMLElement;
76
}
77
78
class DragOutContainerEvent extends DragEvent {
79
readonly overContainer: HTMLElement;
80
}
81
82
class DragPressureEvent extends DragEvent {
83
readonly pressure: number;
84
}
85
```
86
87
**Event Names:**
88
89
```typescript { .api }
90
type DraggableEventNames =
91
| 'draggable:initialize'
92
| 'draggable:destroy'
93
| 'drag:start'
94
| 'drag:move'
95
| 'drag:over'
96
| 'drag:over:container'
97
| 'drag:out'
98
| 'drag:out:container'
99
| 'drag:stop'
100
| 'drag:stopped'
101
| 'drag:pressure'
102
| MirrorEventNames;
103
```
104
105
**Usage Example:**
106
107
```typescript
108
draggable.on('drag:start', (event) => {
109
console.log('Started dragging:', event.source);
110
console.log('Original element:', event.originalSource);
111
console.log('From container:', event.sourceContainer);
112
});
113
114
draggable.on('drag:over', (event) => {
115
console.log('Dragging over:', event.over);
116
console.log('In container:', event.overContainer);
117
});
118
119
draggable.on('drag:pressure', (event) => {
120
console.log('Pressure level:', event.pressure);
121
// Handle force touch or pressure-sensitive input
122
if (event.pressure > 0.8) {
123
showContextMenu(event.source);
124
}
125
});
126
```
127
128
### Draggable Lifecycle Events
129
130
Events specific to Draggable instance lifecycle.
131
132
```typescript { .api }
133
class DraggableEvent extends AbstractEvent {
134
readonly draggable: Draggable;
135
}
136
137
class DraggableInitializedEvent extends DraggableEvent {}
138
class DraggableDestroyEvent extends DraggableEvent {}
139
```
140
141
**Usage Example:**
142
143
```typescript
144
draggable.on('draggable:initialize', (event) => {
145
console.log('Draggable initialized:', event.draggable);
146
setupDragCallbacks(event.draggable);
147
});
148
149
draggable.on('draggable:destroy', (event) => {
150
console.log('Draggable being destroyed');
151
cleanupDragCallbacks();
152
});
153
```
154
155
### Sortable Events
156
157
Events specific to sortable operations.
158
159
```typescript { .api }
160
class SortableEvent extends AbstractEvent {
161
readonly dragEvent: DragEvent;
162
}
163
164
class SortableStartEvent extends SortableEvent {
165
readonly startIndex: number;
166
readonly startContainer: HTMLElement;
167
}
168
169
class SortableSortEvent extends SortableEvent {
170
readonly oldIndex: number;
171
readonly newIndex: number;
172
readonly oldContainer: HTMLElement;
173
readonly newContainer: HTMLElement;
174
}
175
176
class SortableSortedEvent extends SortableEvent {
177
readonly oldIndex: number;
178
readonly newIndex: number;
179
readonly oldContainer: HTMLElement;
180
readonly newContainer: HTMLElement;
181
}
182
183
class SortableStopEvent extends SortableEvent {
184
readonly oldIndex: number;
185
readonly newIndex: number;
186
readonly oldContainer: HTMLElement;
187
readonly newContainer: HTMLElement;
188
}
189
```
190
191
**Event Names:**
192
193
```typescript { .api }
194
type SortableEventNames =
195
| 'sortable:start'
196
| 'sortable:sort'
197
| 'sortable:sorted'
198
| 'sortable:stop'
199
| DraggableEventNames;
200
```
201
202
### Droppable Events
203
204
Events specific to droppable operations.
205
206
```typescript { .api }
207
class DroppableEvent extends AbstractEvent {
208
readonly dragEvent: DragEvent;
209
}
210
211
class DroppableStartEvent extends DroppableEvent {
212
dropzone: HTMLElement;
213
}
214
215
class DroppableDroppedEvent extends DroppableEvent {
216
dropzone: HTMLElement;
217
}
218
219
class DroppableReturnedEvent extends DroppableEvent {
220
dropzone: HTMLElement;
221
}
222
223
class DroppableStopEvent extends DroppableEvent {
224
dropzone: HTMLElement;
225
}
226
```
227
228
**Event Names:**
229
230
```typescript { .api }
231
type DroppableEventNames =
232
| 'droppable:start'
233
| 'droppable:dropped'
234
| 'droppable:returned'
235
| 'droppable:stop'
236
| DraggableEventNames;
237
```
238
239
### Swappable Events
240
241
Events specific to swappable operations.
242
243
```typescript { .api }
244
class SwappableEvent extends AbstractEvent {
245
readonly dragEvent: DragEvent;
246
}
247
248
class SwappableStartEvent extends SwappableEvent {}
249
250
class SwappableSwapEvent extends SwappableEvent {
251
readonly over: HTMLElement;
252
readonly overContainer: HTMLElement;
253
}
254
255
class SwappableSwappedEvent extends SwappableEvent {
256
readonly swappedElement: HTMLElement;
257
}
258
259
class SwappableStopEvent extends SwappableEvent {}
260
```
261
262
**Event Names:**
263
264
```typescript { .api }
265
type SwappableEventNames =
266
| 'swappable:start'
267
| 'swappable:swap'
268
| 'swappable:swapped'
269
| 'swappable:stop'
270
| DraggableEventNames;
271
```
272
273
### Mirror Events
274
275
Events related to the mirror plugin that creates drag representations.
276
277
```typescript { .api }
278
class MirrorEvent extends AbstractEvent {
279
readonly source: HTMLElement;
280
readonly originalSource: HTMLElement;
281
readonly sourceContainer: HTMLElement;
282
readonly sensorEvent: SensorEvent;
283
readonly originalEvent: Event;
284
}
285
286
class MirrorCreateEvent extends MirrorEvent {}
287
288
class MirrorCreatedEvent extends MirrorEvent {
289
readonly mirror: HTMLElement;
290
}
291
292
class MirrorAttachedEvent extends MirrorEvent {
293
readonly mirror: HTMLElement;
294
}
295
296
class MirrorMoveEvent extends MirrorEvent {
297
readonly mirror: HTMLElement;
298
readonly passedThreshX: boolean;
299
readonly passedThreshY: boolean;
300
}
301
302
class MirrorMovedEvent extends MirrorEvent {
303
readonly mirror: HTMLElement;
304
readonly passedThreshX: boolean;
305
readonly passedThreshY: boolean;
306
}
307
308
class MirrorDestroyEvent extends MirrorEvent {
309
readonly mirror: HTMLElement;
310
}
311
```
312
313
**Event Names:**
314
315
```typescript { .api }
316
type MirrorEventNames =
317
| 'mirror:create'
318
| 'mirror:created'
319
| 'mirror:attached'
320
| 'mirror:move'
321
| 'mirror:moved'
322
| 'mirror:destroy';
323
```
324
325
### Plugin Events
326
327
Events from additional plugins.
328
329
```typescript { .api }
330
// Collidable Plugin Events
331
class CollidableEvent extends AbstractEvent {
332
readonly dragEvent: DragEvent;
333
readonly collidingElement: HTMLElement;
334
}
335
336
class CollidableInEvent extends CollidableEvent {}
337
class CollidableOutEvent extends CollidableEvent {}
338
339
type CollidableEventNames = 'collidable:in' | 'collidable:out';
340
341
// Snappable Plugin Events
342
class SnapEvent extends AbstractEvent {
343
readonly dragEvent: DragEvent;
344
readonly snappable: HTMLElement;
345
}
346
347
class SnapInEvent extends SnapEvent {}
348
class SnapOutEvent extends SnapEvent {}
349
350
type SnappableEventNames = 'snap:in' | 'snap:out';
351
```
352
353
## Event Type Helper
354
355
TypeScript utility type for getting specific event types from event names.
356
357
```typescript { .api }
358
type GetEventByEventName<TEventName> =
359
TEventName extends 'draggable:initialize'
360
? DraggableInitializedEvent
361
: TEventName extends 'drag:start'
362
? DragStartEvent
363
: TEventName extends 'sortable:sorted'
364
? SortableSortedEvent
365
: TEventName extends 'droppable:dropped'
366
? DroppableDroppedEvent
367
: TEventName extends 'swappable:swapped'
368
? SwappableSwappedEvent
369
: AbstractEvent;
370
```
371
372
**Usage Example:**
373
374
```typescript
375
// TypeScript will correctly infer the event type
376
draggable.on('drag:start', (event) => {
377
// event is correctly typed as DragStartEvent
378
console.log(event.source, event.originalSource);
379
});
380
381
sortable.on('sortable:sorted', (event) => {
382
// event is correctly typed as SortableSortedEvent
383
console.log(event.oldIndex, event.newIndex);
384
});
385
```
386
387
## Complete Event Example
388
389
```typescript
390
import { Draggable } from "@shopify/draggable";
391
392
const draggable = new Draggable(containers, options);
393
394
// Set up comprehensive event logging
395
const events = [
396
'draggable:initialize',
397
'drag:start',
398
'drag:move',
399
'drag:over',
400
'drag:out',
401
'drag:stop',
402
'drag:stopped',
403
'mirror:create',
404
'mirror:created',
405
'mirror:move',
406
'mirror:destroy'
407
];
408
409
events.forEach(eventName => {
410
draggable.on(eventName, (event) => {
411
console.log(`Event: ${eventName}`, {
412
type: event.type,
413
cancelable: event.cancelable,
414
canceled: event.canceled(),
415
timestamp: Date.now()
416
});
417
});
418
});
419
420
// Handle cancellation scenarios
421
draggable.on('drag:start', (event) => {
422
// Cancel drag if element is disabled
423
if (event.source.hasAttribute('disabled')) {
424
event.cancel();
425
showMessage('This item cannot be moved');
426
}
427
});
428
```