@@ -9,7 +9,13 @@ import {
9
9
watch,
10
10
type Ref
11
11
} from 'vue-demi'
12
- import type { Fn, RefOrElement, RefOrValue } from './types'
12
+ import {
13
+ Fn,
14
+ MoveDataEvent,
15
+ RefOrElement,
16
+ RefOrValue,
17
+ SortableDataEvent
18
+ } from './types'
13
19
14
20
import { error } from './utils/log'
15
21
@@ -51,10 +57,24 @@ function tryOnMounted(fn: Fn) {
51
57
else nextTick(fn)
52
58
}
53
59
54
- const CLONE_ELEMENT_KEY = Symbol('cloneElement')
60
+ const DATA_ELEMENT_KEY = Symbol('dataElement')
61
+
62
+ const sortableEventKeys = [
63
+ "onStart",
64
+ "onEnd",
65
+ "onAdd",
66
+ "onClone",
67
+ "onChoose",
68
+ "onUnchoose",
69
+ "onUpdate",
70
+ "onSort",
71
+ "onRemove",
72
+ "onFilter",
73
+ "onChange"
74
+ ] as const;
55
75
56
76
interface DraggableEvent extends SortableEvent {
57
- item: HTMLElement & { [CLONE_ELEMENT_KEY ]: any }
77
+ item: HTMLElement & { [DATA_ELEMENT_KEY ]: any }
58
78
}
59
79
type SortableMethod = 'closest' | 'save' | 'toArray' | 'destroy' | 'option'
60
80
@@ -69,7 +89,15 @@ export interface UseDraggableReturn extends Pick<Sortable, SortableMethod> {
69
89
resume: () => void
70
90
}
71
91
72
- export interface UseDraggableOptions<T> extends Options {
92
+ type MoveDataFunction = (evt: MoveDataEvent, originalEvent: Event) => boolean | -1 | 1 | void
93
+
94
+ type ExtendedOptions = Options & {
95
+ [key in typeof sortableEventKeys[number]]?: (evt: SortableDataEvent) => void
96
+ } & {
97
+ onMove?: MoveDataFunction;
98
+ }
99
+
100
+ export interface UseDraggableOptions<T> extends ExtendedOptions {
73
101
clone?: (element: T) => T
74
102
immediate?: boolean
75
103
customUpdate?: (event: SortableEvent) => void
@@ -130,16 +158,16 @@ export function useDraggable<T>(...args: any[]): UseDraggableReturn {
130
158
* Element dragging started
131
159
* @param {DraggableEvent} evt - DraggableEvent
132
160
*/
133
- function onStart (evt: DraggableEvent) {
134
- evt.item[CLONE_ELEMENT_KEY ] = clone(unref(unref(list)?.[evt.oldIndex!]))
161
+ function onChoose (evt: DraggableEvent) {
162
+ evt.item[DATA_ELEMENT_KEY ] = clone(unref(unref(list)?.[evt.oldIndex!]))
135
163
}
136
164
137
165
/**
138
166
* Element is dropped into the list from another list
139
167
* @param {DraggableEvent} evt
140
168
*/
141
169
function onAdd(evt: DraggableEvent) {
142
- const element = evt.item[CLONE_ELEMENT_KEY ]
170
+ const element = evt.item[DATA_ELEMENT_KEY ]
143
171
if (isUndefined(element)) return
144
172
removeNode(evt.item)
145
173
if (isRef<any[]>(list)) {
@@ -193,8 +221,8 @@ export function useDraggable<T>(...args: any[]): UseDraggableReturn {
193
221
* preset options
194
222
*/
195
223
const presetOptions: UseDraggableOptions<T> = {
224
+ onChoose,
196
225
onUpdate,
197
- onStart,
198
226
onAdd,
199
227
onRemove
200
228
}
@@ -216,12 +244,30 @@ export function useDraggable<T>(...args: any[]): UseDraggableReturn {
216
244
function mergeOptions() {
217
245
// eslint-disable-next-line
218
246
const { immediate, clone, ...restOptions } = unref(options) ?? {}
247
+ sortableEventKeys.forEach(key => {
248
+ if (restOptions[key]) {
249
+ restOptions[key] = extendSortableEvent(restOptions[key])
250
+ }
251
+ })
252
+ if (restOptions.onMove) {
253
+ restOptions.onMove = extendMoveEvent(restOptions.onMove)
254
+ }
219
255
return mergeOptionsEvents(
220
256
list === null ? {} : presetOptions,
221
257
restOptions
222
258
) as Options
223
259
}
224
260
261
+ function extendSortableEvent(fn: (evt: SortableDataEvent) => void) {
262
+ return (evt: DraggableEvent) =>
263
+ fn({ ...evt, itemData: evt.item[DATA_ELEMENT_KEY] })
264
+ }
265
+
266
+ function extendMoveEvent(fn: MoveDataFunction) {
267
+ return (moveEvent: any, originalEvent: Event) =>
268
+ fn({ ...moveEvent, draggedData: moveEvent.dragged[DATA_ELEMENT_KEY] }, originalEvent)
269
+ }
270
+
225
271
const start = (target?: HTMLElement) => {
226
272
target = getTarget(target)
227
273
if (instance) methods.destroy()
0 commit comments