@marsio/vue-draggable 1.0.9 → 1.0.11
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 +143 -3
- package/build/cjs/Draggable.js +328 -70
- package/build/cjs/DraggableCore.js +884 -74
- package/build/cjs/utils/domFns.js +60 -18
- package/build/cjs/utils/noop.js +9 -0
- package/build/cjs/utils/positionFns.js +78 -40
- package/build/cjs/utils/shims.js +2 -2
- package/build/web/vue-draggable.min.179e4c366756eb300fbf.hot-update.js +30 -0
- package/build/web/vue-draggable.min.19bbf2e057882622f2f8.hot-update.js +30 -0
- package/build/web/vue-draggable.min.6cc5294fa16ef72f1dc6.hot-update.js +30 -0
- package/build/web/vue-draggable.min.870ce0c3b8d1e5af7abb.hot-update.js +30 -0
- package/build/web/vue-draggable.min.8a0eb1cdda0c757918ec.hot-update.js +30 -0
- package/build/web/vue-draggable.min.8c4367bbfb0323ed907d.hot-update.js +30 -0
- package/build/web/vue-draggable.min.900bc4aa354497b18d12.hot-update.js +30 -0
- package/build/web/vue-draggable.min.a529009727f3ce56b642.hot-update.js +30 -0
- package/build/web/vue-draggable.min.js +241 -282
- package/build/web/vue-draggable_min.179e4c366756eb300fbf.hot-update.json +1 -0
- package/build/web/vue-draggable_min.19bbf2e057882622f2f8.hot-update.json +1 -0
- package/build/web/vue-draggable_min.6cc5294fa16ef72f1dc6.hot-update.json +1 -0
- package/build/web/vue-draggable_min.870ce0c3b8d1e5af7abb.hot-update.json +1 -0
- package/build/web/vue-draggable_min.8a0eb1cdda0c757918ec.hot-update.json +1 -0
- package/build/web/vue-draggable_min.8c4367bbfb0323ed907d.hot-update.json +1 -0
- package/build/web/vue-draggable_min.900bc4aa354497b18d12.hot-update.json +1 -0
- package/build/web/vue-draggable_min.a529009727f3ce56b642.hot-update.json +1 -0
- package/package.json +4 -3
- package/typings/index.d.ts +80 -47
package/build/cjs/Draggable.js
CHANGED
|
@@ -11,15 +11,14 @@ Object.defineProperty(exports, "DraggableCore", {
|
|
|
11
11
|
});
|
|
12
12
|
exports.draggableProps = exports.default = void 0;
|
|
13
13
|
var _vue = require("vue");
|
|
14
|
-
var _get = _interopRequireDefault(require("lodash/get"));
|
|
15
14
|
var _clsx = _interopRequireDefault(require("clsx"));
|
|
16
15
|
var _domFns = require("./utils/domFns");
|
|
17
16
|
var _positionFns = require("./utils/positionFns");
|
|
18
17
|
var _shims = require("./utils/shims");
|
|
19
18
|
var _DraggableCore = _interopRequireWildcard(require("./DraggableCore"));
|
|
20
19
|
var _log = _interopRequireDefault(require("./utils/log"));
|
|
21
|
-
|
|
22
|
-
function _interopRequireWildcard(e, r) { if (!
|
|
20
|
+
var _noop = _interopRequireDefault(require("./utils/noop"));
|
|
21
|
+
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
|
|
23
22
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
24
23
|
/**
|
|
25
24
|
* Draggable is a Vue component that allows elements to be dragged and dropped.
|
|
@@ -56,15 +55,21 @@ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e
|
|
|
56
55
|
* Note:
|
|
57
56
|
* This component requires Vue 3 and is designed to work within a Vue 3 application.
|
|
58
57
|
*/
|
|
59
|
-
|
|
60
|
-
return typeof s === 'function' || Object.prototype.toString.call(s) === '[object Object]' && !(0, _vue.isVNode)(s);
|
|
61
|
-
}
|
|
58
|
+
|
|
62
59
|
const draggableProps = exports.draggableProps = {
|
|
63
60
|
..._DraggableCore.draggableCoreProps,
|
|
64
61
|
axis: {
|
|
65
62
|
type: String,
|
|
66
63
|
default: 'both'
|
|
67
64
|
},
|
|
65
|
+
directionLock: {
|
|
66
|
+
type: Boolean,
|
|
67
|
+
default: false
|
|
68
|
+
},
|
|
69
|
+
directionLockThreshold: {
|
|
70
|
+
type: Number,
|
|
71
|
+
default: 4
|
|
72
|
+
},
|
|
68
73
|
bounds: {
|
|
69
74
|
type: [Object, String, Boolean],
|
|
70
75
|
default: false
|
|
@@ -113,31 +118,89 @@ const Draggable = exports.default = (0, _vue.defineComponent)({
|
|
|
113
118
|
let {
|
|
114
119
|
slots
|
|
115
120
|
} = _ref;
|
|
116
|
-
|
|
117
|
-
const rootElement = (0, _vue.ref)(null);
|
|
118
|
-
if (props.position && !(props.dragFn || props.stopFn)) {
|
|
119
|
-
// eslint-disable-next-line no-console
|
|
120
|
-
console.warn('A `position` was applied to this <Draggable>, without drag handlers. This will make this ' + 'component effectively undraggable. Please attach `dragFn` or `stopFn` handlers so you can adjust the ' + '`position` of this element.');
|
|
121
|
-
}
|
|
121
|
+
const localNodeRef = (0, _vue.ref)(null);
|
|
122
122
|
const state = (0, _vue.reactive)({
|
|
123
123
|
// Whether or not we are currently dragging.
|
|
124
124
|
dragging: false,
|
|
125
125
|
// Whether or not we have been dragged before.
|
|
126
126
|
dragged: false,
|
|
127
127
|
// Current transform x and y.
|
|
128
|
-
x: props.position
|
|
129
|
-
y: props.position
|
|
130
|
-
prevPropsPosition: {
|
|
131
|
-
...props.position
|
|
132
|
-
},
|
|
128
|
+
x: props.position?.x ?? props.defaultPosition.x ?? 0,
|
|
129
|
+
y: props.position?.y ?? props.defaultPosition.y ?? 0,
|
|
133
130
|
// Used for compensating for out-of-bounds drags
|
|
134
131
|
slackX: 0,
|
|
135
132
|
slackY: 0,
|
|
136
133
|
// Can only determine if SVG after mounting
|
|
137
134
|
isElementSVG: false
|
|
138
135
|
});
|
|
136
|
+
const internalState = {
|
|
137
|
+
isUnmounted: false
|
|
138
|
+
};
|
|
139
|
+
const isElementNode = v => {
|
|
140
|
+
return !!v && typeof v === 'object' && 'nodeType' in v && v.nodeType === 1;
|
|
141
|
+
};
|
|
142
|
+
const isRefLike = v => {
|
|
143
|
+
return !!v && typeof v === 'object' && 'value' in v;
|
|
144
|
+
};
|
|
139
145
|
const findDOMNode = () => {
|
|
140
|
-
|
|
146
|
+
const nodeRef = props.nodeRef;
|
|
147
|
+
if (isRefLike(nodeRef)) {
|
|
148
|
+
const v = nodeRef.value;
|
|
149
|
+
if (isElementNode(v)) return v;
|
|
150
|
+
} else if (isElementNode(nodeRef)) {
|
|
151
|
+
return nodeRef;
|
|
152
|
+
}
|
|
153
|
+
return localNodeRef.value;
|
|
154
|
+
};
|
|
155
|
+
const boundsContext = {
|
|
156
|
+
props,
|
|
157
|
+
findDOMNode,
|
|
158
|
+
__boundsCache: {
|
|
159
|
+
key: '',
|
|
160
|
+
node: null,
|
|
161
|
+
boundEl: null,
|
|
162
|
+
boundClientWidth: 0,
|
|
163
|
+
boundClientHeight: 0,
|
|
164
|
+
nodeClientWidth: 0,
|
|
165
|
+
nodeClientHeight: 0,
|
|
166
|
+
bounds: null
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
let rafId = null;
|
|
170
|
+
let internalX = state.x;
|
|
171
|
+
let internalY = state.y;
|
|
172
|
+
let internalSlackX = state.slackX;
|
|
173
|
+
let internalSlackY = state.slackY;
|
|
174
|
+
let directionLockAxis = null;
|
|
175
|
+
let directionLockFixedX = NaN;
|
|
176
|
+
let directionLockFixedY = NaN;
|
|
177
|
+
let directionLockTotalX = 0;
|
|
178
|
+
let directionLockTotalY = 0;
|
|
179
|
+
const resetDirectionLock = () => {
|
|
180
|
+
directionLockAxis = null;
|
|
181
|
+
directionLockFixedX = NaN;
|
|
182
|
+
directionLockFixedY = NaN;
|
|
183
|
+
directionLockTotalX = 0;
|
|
184
|
+
directionLockTotalY = 0;
|
|
185
|
+
};
|
|
186
|
+
const getDirectionLockThreshold = () => {
|
|
187
|
+
const threshold = typeof props.directionLockThreshold === 'number' ? props.directionLockThreshold : 0;
|
|
188
|
+
if (threshold <= 0) return 0;
|
|
189
|
+
const scale = typeof props.scale === 'number' ? props.scale : 1;
|
|
190
|
+
if (!scale) return threshold;
|
|
191
|
+
return threshold / scale;
|
|
192
|
+
};
|
|
193
|
+
const flushToReactiveState = () => {
|
|
194
|
+
rafId = null;
|
|
195
|
+
if (internalX === state.x && internalY === state.y && internalSlackX === state.slackX && internalSlackY === state.slackY) return;
|
|
196
|
+
state.x = internalX;
|
|
197
|
+
state.y = internalY;
|
|
198
|
+
state.slackX = internalSlackX;
|
|
199
|
+
state.slackY = internalSlackY;
|
|
200
|
+
};
|
|
201
|
+
const scheduleFlush = () => {
|
|
202
|
+
if (rafId != null) return;
|
|
203
|
+
rafId = window.requestAnimationFrame(flushToReactiveState);
|
|
141
204
|
};
|
|
142
205
|
(0, _vue.onMounted)(() => {
|
|
143
206
|
if (typeof window.SVGElement !== 'undefined' && findDOMNode() instanceof window.SVGElement) {
|
|
@@ -146,83 +209,229 @@ const Draggable = exports.default = (0, _vue.defineComponent)({
|
|
|
146
209
|
});
|
|
147
210
|
(0, _vue.onUnmounted)(() => {
|
|
148
211
|
state.dragging = false;
|
|
212
|
+
internalState.isUnmounted = true;
|
|
213
|
+
if (rafId != null) {
|
|
214
|
+
window.cancelAnimationFrame(rafId);
|
|
215
|
+
rafId = null;
|
|
216
|
+
}
|
|
149
217
|
});
|
|
150
218
|
const onDragStart = (e, coreData) => {
|
|
151
219
|
(0, _log.default)('Draggable: onDragStart: %j', coreData);
|
|
152
220
|
|
|
153
221
|
// Short-circuit if user's callback killed it.
|
|
154
|
-
const
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
222
|
+
const isControlled = Boolean(props.position);
|
|
223
|
+
if (isControlled) {
|
|
224
|
+
internalX = props.position.x;
|
|
225
|
+
internalY = props.position.y;
|
|
226
|
+
} else {
|
|
227
|
+
internalX = state.x;
|
|
228
|
+
internalY = state.y;
|
|
229
|
+
}
|
|
230
|
+
internalSlackX = state.slackX;
|
|
231
|
+
internalSlackY = state.slackY;
|
|
232
|
+
boundsContext.__boundsCache.key = '';
|
|
233
|
+
boundsContext.__boundsCache.node = null;
|
|
234
|
+
boundsContext.__boundsCache.boundEl = null;
|
|
235
|
+
boundsContext.__boundsCache.boundClientWidth = 0;
|
|
236
|
+
boundsContext.__boundsCache.boundClientHeight = 0;
|
|
237
|
+
boundsContext.__boundsCache.nodeClientWidth = 0;
|
|
238
|
+
boundsContext.__boundsCache.nodeClientHeight = 0;
|
|
239
|
+
boundsContext.__boundsCache.bounds = null;
|
|
240
|
+
resetDirectionLock();
|
|
241
|
+
flushToReactiveState();
|
|
242
|
+
if (props.startFn !== _noop.default) {
|
|
243
|
+
const scale = typeof props.scale === 'number' ? props.scale : 1;
|
|
244
|
+
const uiStart = {
|
|
245
|
+
node: coreData.node,
|
|
246
|
+
x: internalX + coreData.deltaX / scale,
|
|
247
|
+
y: internalY + coreData.deltaY / scale,
|
|
248
|
+
deltaX: coreData.deltaX / scale,
|
|
249
|
+
deltaY: coreData.deltaY / scale,
|
|
250
|
+
lastX: internalX,
|
|
251
|
+
lastY: internalY
|
|
252
|
+
};
|
|
253
|
+
const shouldStart = props.startFn?.(e, uiStart);
|
|
254
|
+
// Kills start event on core as well, so move handlers are never bound.
|
|
255
|
+
if (shouldStart === false) return false;
|
|
256
|
+
}
|
|
160
257
|
state.dragging = true;
|
|
161
258
|
state.dragged = true;
|
|
162
259
|
};
|
|
163
260
|
const onDrag = (e, coreData) => {
|
|
164
261
|
if (!state.dragging) return false;
|
|
165
262
|
(0, _log.default)('Draggable: dragFn: %j', coreData);
|
|
166
|
-
const
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
263
|
+
const scale = typeof props.scale === 'number' ? props.scale : 1;
|
|
264
|
+
const rawDeltaX = coreData.deltaX / scale;
|
|
265
|
+
const rawDeltaY = coreData.deltaY / scale;
|
|
266
|
+
let newX = internalX + rawDeltaX;
|
|
267
|
+
let newY = internalY + rawDeltaY;
|
|
268
|
+
let newSlackX = 0;
|
|
269
|
+
let newSlackY = 0;
|
|
270
|
+
let uiDeltaX = rawDeltaX;
|
|
271
|
+
let uiDeltaY = rawDeltaY;
|
|
272
|
+
const allowAxisX = (0, _positionFns.canDragX)({
|
|
273
|
+
props
|
|
274
|
+
});
|
|
275
|
+
const allowAxisY = (0, _positionFns.canDragY)({
|
|
276
|
+
props
|
|
277
|
+
});
|
|
278
|
+
let effectiveAxisX = allowAxisX;
|
|
279
|
+
let effectiveAxisY = allowAxisY;
|
|
280
|
+
if (props.directionLock && allowAxisX && allowAxisY) {
|
|
281
|
+
if (directionLockAxis == null) {
|
|
282
|
+
directionLockTotalX += rawDeltaX;
|
|
283
|
+
directionLockTotalY += rawDeltaY;
|
|
284
|
+
const threshold = getDirectionLockThreshold();
|
|
285
|
+
if (!threshold || Math.hypot(directionLockTotalX, directionLockTotalY) >= threshold) {
|
|
286
|
+
directionLockAxis = Math.abs(directionLockTotalX) >= Math.abs(directionLockTotalY) ? 'x' : 'y';
|
|
287
|
+
directionLockFixedX = internalX;
|
|
288
|
+
directionLockFixedY = internalY;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
if (directionLockAxis === 'x' && Number.isFinite(directionLockFixedY)) {
|
|
292
|
+
newY = directionLockFixedY;
|
|
293
|
+
uiDeltaY = newY - internalY;
|
|
294
|
+
} else if (directionLockAxis === 'y' && Number.isFinite(directionLockFixedX)) {
|
|
295
|
+
newX = directionLockFixedX;
|
|
296
|
+
uiDeltaX = newX - internalX;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
if (directionLockAxis === 'x') effectiveAxisY = false;
|
|
300
|
+
if (directionLockAxis === 'y') effectiveAxisX = false;
|
|
301
|
+
if (!effectiveAxisX) {
|
|
302
|
+
newX = internalX;
|
|
303
|
+
uiDeltaX = 0;
|
|
304
|
+
}
|
|
305
|
+
if (!effectiveAxisY) {
|
|
306
|
+
newY = internalY;
|
|
307
|
+
uiDeltaY = 0;
|
|
308
|
+
}
|
|
176
309
|
|
|
177
310
|
// Keep within bounds.
|
|
178
311
|
if (props.bounds) {
|
|
179
312
|
// Save original x and y.
|
|
180
|
-
const
|
|
181
|
-
|
|
182
|
-
y
|
|
183
|
-
} = newState;
|
|
313
|
+
const x = newX;
|
|
314
|
+
const y = newY;
|
|
184
315
|
|
|
185
316
|
// Add slack to the values used to calculate bound position. This will ensure that if
|
|
186
317
|
// completely removed.
|
|
187
|
-
|
|
188
|
-
|
|
318
|
+
const slackX = effectiveAxisX ? internalSlackX : 0;
|
|
319
|
+
const slackY = effectiveAxisY ? internalSlackY : 0;
|
|
320
|
+
newX += slackX;
|
|
321
|
+
newY += slackY;
|
|
189
322
|
|
|
190
323
|
// Get bound position. This will ceil/floor the x and y within the boundaries.
|
|
191
|
-
const [
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
}, newState.x, newState.y);
|
|
195
|
-
newState.x = newStateX;
|
|
196
|
-
newState.y = newStateY;
|
|
324
|
+
const [boundX, boundY] = (0, _positionFns.getBoundPosition)(boundsContext, newX, newY);
|
|
325
|
+
newX = boundX;
|
|
326
|
+
newY = boundY;
|
|
197
327
|
|
|
198
328
|
// Recalculate slack by noting how much was shaved by the boundPosition handler.
|
|
199
|
-
|
|
200
|
-
|
|
329
|
+
newSlackX = slackX + (x - newX);
|
|
330
|
+
newSlackY = slackY + (y - newY);
|
|
201
331
|
|
|
202
332
|
// Update the event we fire to reflect what really happened after bounds took effect.
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
uiData.deltaX = newState.x - (state.x ?? 0);
|
|
206
|
-
uiData.deltaY = newState.y - (state.y ?? 0);
|
|
333
|
+
uiDeltaX = newX - internalX;
|
|
334
|
+
uiDeltaY = newY - internalY;
|
|
207
335
|
}
|
|
336
|
+
if (!effectiveAxisX) newSlackX = 0;
|
|
337
|
+
if (!effectiveAxisY) newSlackY = 0;
|
|
208
338
|
|
|
209
339
|
// Short-circuit if user's callback killed it.
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
340
|
+
if (props.dragFn !== _noop.default) {
|
|
341
|
+
const uiData = {
|
|
342
|
+
node: coreData.node,
|
|
343
|
+
x: newX,
|
|
344
|
+
y: newY,
|
|
345
|
+
deltaX: uiDeltaX,
|
|
346
|
+
deltaY: uiDeltaY,
|
|
347
|
+
lastX: internalX,
|
|
348
|
+
lastY: internalY
|
|
349
|
+
};
|
|
350
|
+
const shouldUpdate = props.dragFn?.(e, uiData);
|
|
351
|
+
if (shouldUpdate === false) return false;
|
|
352
|
+
}
|
|
353
|
+
internalX = newX;
|
|
354
|
+
internalY = newY;
|
|
355
|
+
internalSlackX = newSlackX;
|
|
356
|
+
internalSlackY = newSlackY;
|
|
357
|
+
|
|
358
|
+
// PERF: If we are not controlled, we can just move the element directly.
|
|
359
|
+
// This allows us to run at 60fps without the overhead of Vue's reactivity system.
|
|
360
|
+
if (!props.position) {
|
|
361
|
+
const transformOpts = {
|
|
362
|
+
x: (0, _positionFns.canDragX)({
|
|
363
|
+
props
|
|
364
|
+
}) ? internalX : props.defaultPosition.x,
|
|
365
|
+
y: (0, _positionFns.canDragY)({
|
|
366
|
+
props
|
|
367
|
+
}) ? internalY : props.defaultPosition.y
|
|
368
|
+
};
|
|
369
|
+
const positionOffset = props.positionOffset;
|
|
370
|
+
const unit = 'px';
|
|
371
|
+
const isSVG = state.isElementSVG;
|
|
372
|
+
const translation = (0, _domFns.getTranslation)(transformOpts, positionOffset, unit);
|
|
373
|
+
const domNode = findDOMNode();
|
|
374
|
+
if (domNode) {
|
|
375
|
+
if (isSVG) {
|
|
376
|
+
// SVG logic usually requires attribute setting, but for performance we might try CSS if possible,
|
|
377
|
+
// or just fallback to reactivity.
|
|
378
|
+
// However, the original code used `createSVGTransform` which returns a string for `transform` attribute?
|
|
379
|
+
// Wait, existing code uses `transform` prop on VNode for SVG.
|
|
380
|
+
// Direct DOM manipulation on SVG attributes is also possible.
|
|
381
|
+
// For now, let's keep SVG on the react path or try direct setAttribute if simple.
|
|
382
|
+
// But let's stick to HTMLElement for the 'style' path for now to be safe.
|
|
383
|
+
if (!isSVG) (0, _domFns.setTransform)(domNode, translation);
|
|
384
|
+
} else {
|
|
385
|
+
(0, _domFns.setTransform)(domNode, translation);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
// If controlled, or if using RafDrag, or if SVG (for safety), we flush.
|
|
391
|
+
// Actually, if controlled, we MUST flush to let parent update.
|
|
392
|
+
// If uncontrolled and HTML, we skip flush until stop!
|
|
393
|
+
if (props.position || props.useRafDrag || state.isElementSVG) {
|
|
394
|
+
if (props.useRafDrag) {
|
|
395
|
+
if (rafId != null) {
|
|
396
|
+
window.cancelAnimationFrame(rafId);
|
|
397
|
+
rafId = null;
|
|
398
|
+
}
|
|
399
|
+
flushToReactiveState();
|
|
400
|
+
} else {
|
|
401
|
+
scheduleFlush();
|
|
402
|
+
}
|
|
403
|
+
}
|
|
215
404
|
};
|
|
216
405
|
const onDragStop = (e, coreData) => {
|
|
217
406
|
if (!state.dragging) return false;
|
|
218
407
|
|
|
219
408
|
// Short-circuit if user's callback killed it.
|
|
220
|
-
|
|
221
|
-
props
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
409
|
+
if (props.stopFn !== _noop.default) {
|
|
410
|
+
const scale = typeof props.scale === 'number' ? props.scale : 1;
|
|
411
|
+
const allowAxisX = (0, _positionFns.canDragX)({
|
|
412
|
+
props
|
|
413
|
+
});
|
|
414
|
+
const allowAxisY = (0, _positionFns.canDragY)({
|
|
415
|
+
props
|
|
416
|
+
});
|
|
417
|
+
const effectiveAxisX = allowAxisX && directionLockAxis !== 'y';
|
|
418
|
+
const effectiveAxisY = allowAxisY && directionLockAxis !== 'x';
|
|
419
|
+
const deltaX = effectiveAxisX ? coreData.deltaX / scale : 0;
|
|
420
|
+
const deltaY = effectiveAxisY ? coreData.deltaY / scale : 0;
|
|
421
|
+
const uiStop = {
|
|
422
|
+
node: coreData.node,
|
|
423
|
+
x: internalX + deltaX,
|
|
424
|
+
y: internalY + deltaY,
|
|
425
|
+
deltaX,
|
|
426
|
+
deltaY,
|
|
427
|
+
lastX: internalX,
|
|
428
|
+
lastY: internalY
|
|
429
|
+
};
|
|
430
|
+
const shouldContinue = props.stopFn?.(e, uiStop);
|
|
431
|
+
if (shouldContinue === false) return false;
|
|
432
|
+
}
|
|
225
433
|
(0, _log.default)('Draggable: onDragStop: %j', coreData);
|
|
434
|
+
resetDirectionLock();
|
|
226
435
|
const newState = {
|
|
227
436
|
dragging: false,
|
|
228
437
|
slackX: 0,
|
|
@@ -240,14 +449,57 @@ const Draggable = exports.default = (0, _vue.defineComponent)({
|
|
|
240
449
|
newState.x = x;
|
|
241
450
|
newState.y = y;
|
|
242
451
|
}
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
452
|
+
state.dragging = newState.dragging;
|
|
453
|
+
internalSlackX = newState.slackX;
|
|
454
|
+
internalSlackY = newState.slackY;
|
|
455
|
+
if (typeof newState.x === 'number') internalX = newState.x;
|
|
456
|
+
if (typeof newState.y === 'number') internalY = newState.y;
|
|
457
|
+
if (rafId != null) {
|
|
458
|
+
window.cancelAnimationFrame(rafId);
|
|
459
|
+
rafId = null;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
// Always flush at the end to ensure state sync
|
|
463
|
+
flushToReactiveState();
|
|
464
|
+
};
|
|
465
|
+
const getFirstUsableChild = () => {
|
|
466
|
+
const raw = slots.default ? slots.default() : [];
|
|
467
|
+
const stack = Array.isArray(raw) ? [...raw] : [raw];
|
|
468
|
+
while (stack.length) {
|
|
469
|
+
const item = stack.shift();
|
|
470
|
+
if (Array.isArray(item)) {
|
|
471
|
+
for (let i = item.length - 1; i >= 0; i -= 1) stack.unshift(item[i]);
|
|
472
|
+
continue;
|
|
473
|
+
}
|
|
474
|
+
if (!(0, _vue.isVNode)(item)) continue;
|
|
475
|
+
|
|
476
|
+
// Skip comment nodes and whitespace-only text nodes.
|
|
477
|
+
if (item.type === _vue.Comment) continue;
|
|
478
|
+
if (item.type === _vue.Text) {
|
|
479
|
+
const txt = typeof item.children === 'string' ? item.children : '';
|
|
480
|
+
if (!txt || !txt.trim()) continue;
|
|
481
|
+
// Draggable requires an element/component vnode, not bare text.
|
|
482
|
+
continue;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
// Unwrap fragments to find the first real node.
|
|
486
|
+
if (item.type === _vue.Fragment) {
|
|
487
|
+
const fragChildren = item.children;
|
|
488
|
+
if (Array.isArray(fragChildren)) {
|
|
489
|
+
for (let i = fragChildren.length - 1; i >= 0; i -= 1) stack.unshift(fragChildren[i]);
|
|
490
|
+
}
|
|
491
|
+
continue;
|
|
492
|
+
}
|
|
493
|
+
return item;
|
|
494
|
+
}
|
|
495
|
+
return null;
|
|
246
496
|
};
|
|
247
497
|
return () => {
|
|
248
498
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
249
499
|
const {
|
|
250
500
|
axis,
|
|
501
|
+
directionLock,
|
|
502
|
+
directionLockThreshold,
|
|
251
503
|
bounds,
|
|
252
504
|
defaultPosition,
|
|
253
505
|
defaultClassName,
|
|
@@ -287,12 +539,18 @@ const Draggable = exports.default = (0, _vue.defineComponent)({
|
|
|
287
539
|
style = (0, _domFns.createCSSTransform)(transformOpts, positionOffset);
|
|
288
540
|
}
|
|
289
541
|
|
|
542
|
+
// Performance adjustment:
|
|
543
|
+
if (state.dragging && !state.isElementSVG) {
|
|
544
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
545
|
+
style.willChange = 'transform';
|
|
546
|
+
}
|
|
547
|
+
|
|
290
548
|
// Mark with class while dragging
|
|
291
549
|
const className = (0, _clsx.default)(defaultClassName, {
|
|
292
550
|
[defaultClassNameDragging]: state.dragging,
|
|
293
551
|
[defaultClassNameDragged]: state.dragged
|
|
294
552
|
});
|
|
295
|
-
const child =
|
|
553
|
+
const child = getFirstUsableChild();
|
|
296
554
|
if (!child) return null;
|
|
297
555
|
const clonedChildren = (0, _vue.cloneVNode)(child, {
|
|
298
556
|
class: className,
|
|
@@ -305,10 +563,10 @@ const Draggable = exports.default = (0, _vue.defineComponent)({
|
|
|
305
563
|
dragFn: onDrag,
|
|
306
564
|
stopFn: onDragStop
|
|
307
565
|
};
|
|
308
|
-
return (0, _vue.createVNode)(_DraggableCore.default, (0, _vue.mergeProps)({
|
|
309
|
-
"
|
|
310
|
-
}
|
|
311
|
-
default: () =>
|
|
566
|
+
return (0, _vue.createVNode)(_DraggableCore.default, (0, _vue.mergeProps)(coreProps, {
|
|
567
|
+
"nodeRef": props.nodeRef || localNodeRef
|
|
568
|
+
}), {
|
|
569
|
+
default: () => clonedChildren
|
|
312
570
|
});
|
|
313
571
|
};
|
|
314
572
|
}
|