@maas/vue-equipment 1.1.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.
Files changed (94) hide show
  1. package/dist/nuxt/module.json +1 -1
  2. package/dist/nuxt/module.mjs +4 -3
  3. package/dist/plugins/MagicCarousel/src/utils/defaultOptions.mjs +1 -1
  4. package/dist/plugins/MagicDotMatrix/index.d.ts +14 -0
  5. package/dist/plugins/MagicDotMatrix/index.mjs +20 -0
  6. package/dist/plugins/MagicDotMatrix/nuxt.d.ts +0 -0
  7. package/dist/plugins/MagicDotMatrix/nuxt.mjs +29 -0
  8. package/dist/plugins/MagicDotMatrix/src/components/MagicDotMatrix.d.vue.ts +10 -0
  9. package/dist/plugins/MagicDotMatrix/src/components/MagicDotMatrix.vue +103 -0
  10. package/dist/plugins/MagicDotMatrix/src/components/MagicDotMatrix.vue.d.ts +10 -0
  11. package/dist/plugins/MagicDotMatrix/src/composables/private/useDotMatrixApi.d.ts +10 -0
  12. package/dist/plugins/MagicDotMatrix/src/composables/private/useDotMatrixApi.mjs +82 -0
  13. package/dist/plugins/MagicDotMatrix/src/composables/private/useDotMatrixState.d.ts +6 -0
  14. package/dist/plugins/MagicDotMatrix/src/composables/private/useDotMatrixState.mjs +71 -0
  15. package/dist/plugins/MagicDotMatrix/src/composables/useMagicDotMatrix.d.ts +10 -0
  16. package/dist/plugins/MagicDotMatrix/src/composables/useMagicDotMatrix.mjs +27 -0
  17. package/dist/plugins/MagicDotMatrix/src/composables/useMagicDotMatrixEmoji.d.ts +19 -0
  18. package/dist/plugins/MagicDotMatrix/src/composables/useMagicDotMatrixEmoji.mjs +50 -0
  19. package/dist/plugins/MagicDotMatrix/src/types/index.d.ts +40 -0
  20. package/dist/plugins/MagicDotMatrix/src/types/index.mjs +0 -0
  21. package/dist/plugins/MagicDotMatrix/src/utils/defaultOptions.d.ts +4 -0
  22. package/dist/plugins/MagicDotMatrix/src/utils/defaultOptions.mjs +14 -0
  23. package/dist/plugins/MagicDotMatrix/src/utils/emoji/animateEmoji.d.ts +5 -0
  24. package/dist/plugins/MagicDotMatrix/src/utils/emoji/animateEmoji.mjs +296 -0
  25. package/dist/plugins/MagicDotMatrix/src/utils/emoji/motions.d.ts +382 -0
  26. package/dist/plugins/MagicDotMatrix/src/utils/emoji/motions.mjs +420 -0
  27. package/dist/plugins/MagicDotMatrix/src/utils/emoji/pickMotion.d.ts +7 -0
  28. package/dist/plugins/MagicDotMatrix/src/utils/emoji/pickMotion.mjs +153 -0
  29. package/dist/plugins/MagicDotMatrix/src/utils/presets/bounce.d.ts +2 -0
  30. package/dist/plugins/MagicDotMatrix/src/utils/presets/bounce.mjs +8 -0
  31. package/dist/plugins/MagicDotMatrix/src/utils/presets/checkerboard.d.ts +2 -0
  32. package/dist/plugins/MagicDotMatrix/src/utils/presets/checkerboard.mjs +18 -0
  33. package/dist/plugins/MagicDotMatrix/src/utils/presets/comet.d.ts +2 -0
  34. package/dist/plugins/MagicDotMatrix/src/utils/presets/comet.mjs +5 -0
  35. package/dist/plugins/MagicDotMatrix/src/utils/presets/drift.d.ts +2 -0
  36. package/dist/plugins/MagicDotMatrix/src/utils/presets/drift.mjs +38 -0
  37. package/dist/plugins/MagicDotMatrix/src/utils/presets/equalizer.d.ts +2 -0
  38. package/dist/plugins/MagicDotMatrix/src/utils/presets/equalizer.mjs +14 -0
  39. package/dist/plugins/MagicDotMatrix/src/utils/presets/fill.d.ts +2 -0
  40. package/dist/plugins/MagicDotMatrix/src/utils/presets/fill.mjs +10 -0
  41. package/dist/plugins/MagicDotMatrix/src/utils/presets/focus.d.ts +2 -0
  42. package/dist/plugins/MagicDotMatrix/src/utils/presets/focus.mjs +5 -0
  43. package/dist/plugins/MagicDotMatrix/src/utils/presets/index.d.ts +12 -0
  44. package/dist/plugins/MagicDotMatrix/src/utils/presets/index.mjs +12 -0
  45. package/dist/plugins/MagicDotMatrix/src/utils/presets/orbit.d.ts +2 -0
  46. package/dist/plugins/MagicDotMatrix/src/utils/presets/orbit.mjs +8 -0
  47. package/dist/plugins/MagicDotMatrix/src/utils/presets/pulse.d.ts +2 -0
  48. package/dist/plugins/MagicDotMatrix/src/utils/presets/pulse.mjs +7 -0
  49. package/dist/plugins/MagicDotMatrix/src/utils/presets/ripple.d.ts +2 -0
  50. package/dist/plugins/MagicDotMatrix/src/utils/presets/ripple.mjs +5 -0
  51. package/dist/plugins/MagicDotMatrix/src/utils/presets/scan.d.ts +2 -0
  52. package/dist/plugins/MagicDotMatrix/src/utils/presets/scan.mjs +6 -0
  53. package/dist/plugins/MagicDotMatrix/src/utils/presets/spiral.d.ts +2 -0
  54. package/dist/plugins/MagicDotMatrix/src/utils/presets/spiral.mjs +34 -0
  55. package/dist/plugins/MagicDotMatrix/src/utils/sequence/equalizerFrame.d.ts +7 -0
  56. package/dist/plugins/MagicDotMatrix/src/utils/sequence/equalizerFrame.mjs +12 -0
  57. package/dist/plugins/MagicDotMatrix/src/utils/sequence/getRings.d.ts +2 -0
  58. package/dist/plugins/MagicDotMatrix/src/utils/sequence/getRings.mjs +24 -0
  59. package/dist/plugins/MagicDotMatrix/src/utils/sequence/ringPath.d.ts +7 -0
  60. package/dist/plugins/MagicDotMatrix/src/utils/sequence/ringPath.mjs +35 -0
  61. package/dist/plugins/MagicDotMatrix/src/utils/sequence/toIndex.d.ts +6 -0
  62. package/dist/plugins/MagicDotMatrix/src/utils/sequence/toIndex.mjs +3 -0
  63. package/dist/plugins/MagicDotMatrix/src/utils/sequence/withTrail.d.ts +6 -0
  64. package/dist/plugins/MagicDotMatrix/src/utils/sequence/withTrail.mjs +17 -0
  65. package/dist/plugins/MagicDraggable/src/utils/defaultOptions.mjs +1 -1
  66. package/dist/plugins/MagicDrawer/src/components/MagicDrawerContent.vue +4 -0
  67. package/dist/plugins/MagicDrawer/src/components/MagicDrawerTrigger.d.vue.ts +1 -1
  68. package/dist/plugins/MagicDrawer/src/components/MagicDrawerTrigger.vue +5 -1
  69. package/dist/plugins/MagicDrawer/src/components/MagicDrawerTrigger.vue.d.ts +1 -1
  70. package/dist/plugins/MagicDrawer/src/composables/private/useDrawerDrag.mjs +1 -2
  71. package/dist/plugins/MagicDrawer/src/composables/private/useDrawerProgress.mjs +57 -77
  72. package/dist/plugins/MagicDrawer/src/composables/private/useDrawerSnap.mjs +2 -5
  73. package/dist/plugins/MagicDrawer/src/utils/defaultOptions.mjs +1 -1
  74. package/dist/plugins/MagicEmitter/src/types/index.d.ts +2 -0
  75. package/dist/plugins/MagicMenu/src/components/MagicMenuTrigger.vue +13 -3
  76. package/dist/plugins/MagicTray/index.d.ts +2 -1
  77. package/dist/plugins/MagicTray/index.mjs +3 -0
  78. package/dist/plugins/MagicTray/src/components/MagicTrayContent.d.vue.ts +2 -2
  79. package/dist/plugins/MagicTray/src/components/MagicTrayContent.vue +17 -16
  80. package/dist/plugins/MagicTray/src/components/MagicTrayContent.vue.d.ts +2 -2
  81. package/dist/plugins/MagicTray/src/components/MagicTrayTrigger.d.vue.ts +25 -0
  82. package/dist/plugins/MagicTray/src/components/MagicTrayTrigger.vue +96 -0
  83. package/dist/plugins/MagicTray/src/components/MagicTrayTrigger.vue.d.ts +25 -0
  84. package/dist/plugins/MagicTray/src/composables/private/useTrayDrag.d.ts +0 -4
  85. package/dist/plugins/MagicTray/src/composables/private/useTrayDrag.mjs +9 -415
  86. package/dist/plugins/MagicTray/src/composables/private/useTrayGesture.d.ts +16 -0
  87. package/dist/plugins/MagicTray/src/composables/private/useTrayGesture.mjs +426 -0
  88. package/dist/plugins/MagicTray/src/composables/private/useTrayMagnetism.mjs +9 -37
  89. package/dist/plugins/MagicTray/src/composables/private/useTrayProgress.mjs +1 -1
  90. package/dist/plugins/MagicTray/src/composables/private/useTraySnap.mjs +2 -4
  91. package/dist/plugins/MagicTray/src/composables/private/useTrayUtils.d.ts +8 -1
  92. package/dist/plugins/MagicTray/src/composables/private/useTrayUtils.mjs +7 -1
  93. package/dist/plugins/MagicTray/src/utils/defaultOptions.mjs +1 -1
  94. package/package.json +3 -4
@@ -0,0 +1,426 @@
1
+ import { computed, onScopeDispose, readonly, ref, toValue, watch } from "vue";
2
+ import { useEventListener } from "@vueuse/core";
3
+ import {
4
+ cancelEdgeNavigation,
5
+ guardedReleasePointerCapture,
6
+ guardedSetPointerCapture,
7
+ isAndroid,
8
+ isIOS,
9
+ isWithinRange,
10
+ lockSelection,
11
+ snapCommit,
12
+ snapRelease
13
+ } from "@maas/vue-equipment/utils";
14
+ import { useMagicEmitter } from "@maas/vue-equipment/plugins/MagicEmitter";
15
+ import { useTraySnap } from "./useTraySnap.mjs";
16
+ import { SIDES, useTrayUtils } from "./useTrayUtils.mjs";
17
+ export function useTrayGesture(args) {
18
+ const { id, state, selectionLock = "press", preventEdgeNavigation } = args;
19
+ const { clampWithOvershoot, isVertical, isDraggableSide } = useTrayUtils();
20
+ const emitter = useMagicEmitter();
21
+ const {
22
+ maxInset,
23
+ mappedSnapPoints,
24
+ mappedRanges,
25
+ rangeAt,
26
+ snapPointAt,
27
+ restingInset,
28
+ findSnapTarget,
29
+ interpolateDragged
30
+ } = useTraySnap({ id, state });
31
+ let lastPendingTarget = void 0;
32
+ let heldRangeSnap = false;
33
+ let flicked = false;
34
+ let cancelPointerup = void 0;
35
+ let cancelPointermove = void 0;
36
+ let cancelPointercancel = void 0;
37
+ let cancelTouchmove = void 0;
38
+ let cancelTouchend = void 0;
39
+ let cancelTouchcancel = void 0;
40
+ let pointerdownTarget = null;
41
+ let releaseSelection = void 0;
42
+ const threshold = computed(() => state.options.threshold);
43
+ const disabled = computed(() => state.options.disabled);
44
+ const snapMode = computed(() => state.options.snap.mode);
45
+ const dragMode = computed(() => state.options.drag.mode);
46
+ const active = ref(false);
47
+ const hasDragged = computed(() => {
48
+ const sides = state.draggingSide ? [state.draggingSide] : SIDES;
49
+ return sides.some(
50
+ (side) => !isWithinRange({
51
+ input: state.dragged[side],
52
+ base: state.lastDragged[side],
53
+ threshold: toValue(threshold).lock
54
+ })
55
+ );
56
+ });
57
+ function lockSelectionOnce() {
58
+ releaseSelection ??= lockSelection();
59
+ }
60
+ function canBegin(side) {
61
+ return !state.dragging && !toValue(disabled) && state.elRect !== void 0 && isDraggableSide({ snapPoints: state.options.snapPoints, side });
62
+ }
63
+ function dragBounds(side) {
64
+ const points = mappedSnapPoints(side);
65
+ const geometricMax = maxInset(side);
66
+ if (!points.length) {
67
+ return { min: 0, max: geometricMax };
68
+ }
69
+ return {
70
+ min: Math.max(0, points[0]),
71
+ max: Math.min(points[points.length - 1], geometricMax)
72
+ };
73
+ }
74
+ function snapDrag(side) {
75
+ return {
76
+ points: mappedSnapPoints(side),
77
+ ranges: mappedRanges(side),
78
+ mode: snapMode.value,
79
+ rest: state.snapped[side],
80
+ start: state.lastDragged[side],
81
+ position: state.dragged[side]
82
+ };
83
+ }
84
+ function settleTarget(side) {
85
+ const target = snapRelease({
86
+ ...snapDrag(side),
87
+ committed: state.interpolateTo,
88
+ flicked,
89
+ tapped: !hasDragged.value
90
+ });
91
+ return restingInset(side, target);
92
+ }
93
+ function isSnapDrag(side) {
94
+ return typeof dragMode.value === "string" ? dragMode.value === "snap" : (dragMode.value?.[side] ?? "free") === "snap";
95
+ }
96
+ function computeInset(side, coord) {
97
+ let newInset = 0;
98
+ switch (side) {
99
+ case "top":
100
+ newInset = coord - state.origin;
101
+ break;
102
+ case "bottom":
103
+ newInset = state.origin - coord;
104
+ break;
105
+ case "left":
106
+ newInset = coord - state.origin;
107
+ break;
108
+ case "right":
109
+ newInset = state.origin - coord;
110
+ break;
111
+ }
112
+ const { min, max } = dragBounds(side);
113
+ return clampWithOvershoot(
114
+ newInset,
115
+ min,
116
+ max,
117
+ state.overshoot.outer[side],
118
+ state.overshoot.inner
119
+ );
120
+ }
121
+ function setDragged(side, coord) {
122
+ const newInset = computeInset(side, coord);
123
+ if (newInset === state.dragged[side]) {
124
+ return;
125
+ }
126
+ const prev = state.dragged[side];
127
+ state.relDirection[side] = newInset < prev ? "below" : "above";
128
+ state.dragged[side] = newInset;
129
+ }
130
+ function snapDragged(side, coord) {
131
+ const inset = computeInset(side, coord);
132
+ const target = findSnapTarget(side, inset);
133
+ if (target === void 0 || target === state.snapped[side]) {
134
+ return;
135
+ }
136
+ state.dragged[side] = target;
137
+ state.snapped[side] = target;
138
+ state.activeSnapPoint[side] = snapPointAt(side, target);
139
+ heldRangeSnap = !mappedSnapPoints(side).includes(target);
140
+ if (!heldRangeSnap) {
141
+ emitSnap(side);
142
+ }
143
+ }
144
+ function releaseSnapDrag(side) {
145
+ if (heldRangeSnap) {
146
+ emitSnap(side);
147
+ }
148
+ heldRangeSnap = false;
149
+ }
150
+ function emitSnap(side) {
151
+ const point = state.activeSnapPoint[side];
152
+ if (point === void 0) {
153
+ return;
154
+ }
155
+ emitter.emit("beforeSnap", {
156
+ id: toValue(id),
157
+ snapPoint: { side, point }
158
+ });
159
+ emitter.emit("afterSnap", {
160
+ id: toValue(id),
161
+ snapPoint: { side, point }
162
+ });
163
+ }
164
+ function checkPosition(side) {
165
+ const direction = state.relDirection[side];
166
+ state.interpolateTo = snapCommit({
167
+ ...snapDrag(side),
168
+ distance: toValue(threshold).distance,
169
+ flicked,
170
+ flickDirection: direction === "absolute" ? void 0 : direction
171
+ });
172
+ }
173
+ function emitWillSnapTo(side) {
174
+ const target = settleTarget(side);
175
+ const isPoint = mappedSnapPoints(side).includes(target);
176
+ const pending = !isPoint && rangeAt(side, target)?.range || target;
177
+ if (pending === lastPendingTarget) {
178
+ return;
179
+ }
180
+ lastPendingTarget = pending;
181
+ const snapPoint = snapPointAt(side, target);
182
+ if (snapPoint === void 0) {
183
+ return;
184
+ }
185
+ emitter.emit("willSnapTo", {
186
+ id: toValue(id),
187
+ side,
188
+ snapPoint
189
+ });
190
+ }
191
+ function checkMomentum(side) {
192
+ const elapsed = Date.now() - state.dragStart.getTime();
193
+ const distance = Math.abs(state.dragged[side] - state.lastDragged[side]);
194
+ const velocity = elapsed && distance ? distance / elapsed : 0;
195
+ flicked = velocity > toValue(threshold).momentum;
196
+ }
197
+ function resetListeners() {
198
+ cancelTouchmove?.();
199
+ cancelTouchend?.();
200
+ cancelTouchcancel?.();
201
+ cancelPointerup?.();
202
+ cancelPointermove?.();
203
+ cancelPointercancel?.();
204
+ }
205
+ function resetDragState() {
206
+ const side = state.draggingSide;
207
+ if (side) {
208
+ state.lastDragged[side] = state.snapped[side];
209
+ }
210
+ releaseSelection?.();
211
+ releaseSelection = void 0;
212
+ active.value = false;
213
+ state.dragging = false;
214
+ state.draggingSide = void 0;
215
+ state.interpolateTo = void 0;
216
+ }
217
+ function settle(side) {
218
+ const target = settleTarget(side);
219
+ if (target !== state.snapped[side] || state.interpolateTo !== void 0) {
220
+ state.snapped[side] = target;
221
+ state.activeSnapPoint[side] = snapPointAt(side, target);
222
+ }
223
+ interpolateDragged({ side, to: target });
224
+ }
225
+ function onPointermove(e) {
226
+ if (e.isTrusted && !e.isPrimary) {
227
+ return;
228
+ }
229
+ const side = state.draggingSide;
230
+ if (!side) {
231
+ return;
232
+ }
233
+ e.stopImmediatePropagation();
234
+ e.stopPropagation();
235
+ const coord = isVertical(side) ? e.clientY : e.clientX;
236
+ if (isSnapDrag(side)) {
237
+ snapDragged(side, coord);
238
+ } else {
239
+ setDragged(side, coord);
240
+ checkMomentum(side);
241
+ checkPosition(side);
242
+ emitWillSnapTo(side);
243
+ }
244
+ if (hasDragged.value) {
245
+ lockSelectionOnce();
246
+ }
247
+ emitter.emit("drag", {
248
+ id: toValue(id),
249
+ side,
250
+ value: state.dragged[side]
251
+ });
252
+ }
253
+ function onPointerup(e) {
254
+ const side = state.draggingSide;
255
+ if (side) {
256
+ if (isSnapDrag(side)) {
257
+ releaseSnapDrag(side);
258
+ } else {
259
+ settle(side);
260
+ }
261
+ emitter.emit("afterDrag", {
262
+ id: toValue(id),
263
+ side,
264
+ value: state.dragged[side]
265
+ });
266
+ }
267
+ resetDragState();
268
+ resetListeners();
269
+ guardedReleasePointerCapture({ event: e, element: pointerdownTarget });
270
+ }
271
+ function onTouchmove(e) {
272
+ const side = state.draggingSide;
273
+ if (!side) {
274
+ return;
275
+ }
276
+ const firstTouch = e.touches[0];
277
+ if (!firstTouch) {
278
+ return;
279
+ }
280
+ e.stopImmediatePropagation();
281
+ e.stopPropagation();
282
+ if (hasDragged.value) {
283
+ e.preventDefault();
284
+ }
285
+ const coord = isVertical(side) ? firstTouch.clientY : firstTouch.clientX;
286
+ if (isSnapDrag(side)) {
287
+ snapDragged(side, coord);
288
+ } else {
289
+ setDragged(side, coord);
290
+ checkMomentum(side);
291
+ checkPosition(side);
292
+ emitWillSnapTo(side);
293
+ }
294
+ if (hasDragged.value) {
295
+ lockSelectionOnce();
296
+ }
297
+ emitter.emit("drag", {
298
+ id: toValue(id),
299
+ side,
300
+ value: state.dragged[side]
301
+ });
302
+ }
303
+ function onTouchend() {
304
+ const side = state.draggingSide;
305
+ if (side) {
306
+ if (isSnapDrag(side)) {
307
+ releaseSnapDrag(side);
308
+ } else {
309
+ settle(side);
310
+ }
311
+ emitter.emit("afterDrag", {
312
+ id: toValue(id),
313
+ side,
314
+ value: state.dragged[side]
315
+ });
316
+ }
317
+ resetDragState();
318
+ resetListeners();
319
+ }
320
+ function beginDrag(side, coord, target) {
321
+ active.value = true;
322
+ state.dragging = true;
323
+ state.draggingSide = side;
324
+ state.interpolateTo = void 0;
325
+ state.dragged[side] += state.magnetic[side];
326
+ state.magnetic[side] = 0;
327
+ state.lastDragged[side] = state.dragged[side];
328
+ lastPendingTarget = void 0;
329
+ heldRangeSnap = false;
330
+ flicked = false;
331
+ pointerdownTarget = target;
332
+ if (selectionLock === "press") {
333
+ lockSelectionOnce();
334
+ }
335
+ switch (side) {
336
+ case "top":
337
+ case "left":
338
+ state.origin = coord - state.dragged[side];
339
+ break;
340
+ case "bottom":
341
+ case "right":
342
+ state.origin = coord + state.dragged[side];
343
+ break;
344
+ }
345
+ state.dragStart = /* @__PURE__ */ new Date();
346
+ emitter.emit("beforeDrag", {
347
+ id: toValue(id),
348
+ side,
349
+ value: state.dragged[side]
350
+ });
351
+ }
352
+ function onCancel() {
353
+ const side = state.draggingSide;
354
+ if (active.value && side) {
355
+ interpolateDragged({ side, to: state.snapped[side] });
356
+ resetDragState();
357
+ }
358
+ resetListeners();
359
+ }
360
+ function onPointerdown(side, e) {
361
+ if (!canBegin(side)) {
362
+ return;
363
+ }
364
+ const coord = isVertical(side) ? e.clientY : e.clientX;
365
+ const target = e.target instanceof Element ? e.target : null;
366
+ beginDrag(side, coord, target);
367
+ guardedSetPointerCapture({ event: e, element: target });
368
+ resetListeners();
369
+ cancelPointerup = useEventListener(document, "pointerup", onPointerup);
370
+ cancelPointercancel = useEventListener(
371
+ document,
372
+ "pointercancel",
373
+ onPointerup
374
+ );
375
+ cancelPointermove = useEventListener(
376
+ document,
377
+ "pointermove",
378
+ onPointermove,
379
+ {
380
+ passive: false
381
+ }
382
+ );
383
+ cancelTouchend = isIOS() || isAndroid() ? useEventListener(document, "touchend", onTouchend) : void 0;
384
+ cancelTouchcancel = isIOS() || isAndroid() ? useEventListener(document, "touchcancel", onTouchend) : void 0;
385
+ onPointermove(e);
386
+ }
387
+ function onTouchstart(side, e) {
388
+ if (toValue(preventEdgeNavigation)) {
389
+ cancelEdgeNavigation({ event: e });
390
+ }
391
+ if (!isAndroid() || !canBegin(side)) {
392
+ return;
393
+ }
394
+ const firstTouch = e.touches[0];
395
+ if (!firstTouch) {
396
+ return;
397
+ }
398
+ e.stopImmediatePropagation();
399
+ e.stopPropagation();
400
+ const coord = isVertical(side) ? firstTouch.clientY : firstTouch.clientX;
401
+ beginDrag(side, coord, e.target instanceof Element ? e.target : null);
402
+ cancelTouchmove?.();
403
+ cancelTouchmove = useEventListener(document, "touchmove", onTouchmove, {
404
+ passive: false
405
+ });
406
+ cancelTouchend?.();
407
+ cancelTouchend = useEventListener(document, "touchend", onTouchend, {
408
+ passive: false
409
+ });
410
+ cancelTouchcancel?.();
411
+ cancelTouchcancel = useEventListener(document, "touchcancel", onTouchend);
412
+ onTouchmove(e);
413
+ }
414
+ watch(disabled, (value) => {
415
+ if (value) {
416
+ onCancel();
417
+ }
418
+ });
419
+ onScopeDispose(onCancel, true);
420
+ return {
421
+ active: readonly(active),
422
+ hasDragged,
423
+ onPointerdown,
424
+ onTouchstart
425
+ };
426
+ }
@@ -5,19 +5,14 @@ import { useMagicEmitter } from "@maas/vue-equipment/plugins/MagicEmitter";
5
5
  import { useMagicError } from "@maas/vue-equipment/plugins/MagicError";
6
6
  import { useEasings } from "@maas/vue-equipment/composables/useEasings";
7
7
  import { useTraySnap } from "./useTraySnap.mjs";
8
- import { useTrayUtils } from "./useTrayUtils.mjs";
9
- const SIDES = ["top", "right", "bottom", "left"];
10
- const EPSILON = 0.5;
8
+ import { SIDES, useTrayUtils } from "./useTrayUtils.mjs";
11
9
  export function useTrayMagnetism(args) {
12
10
  const { id, elRef, handleRefs, state } = args;
13
11
  const { throwError } = useMagicError({
14
12
  prefix: "MagicTray",
15
13
  source: "useTrayMagnetism"
16
14
  });
17
- const { mapSnapPoint, mappedSnapPoints, maxInset } = useTraySnap({
18
- id,
19
- state
20
- });
15
+ const { maxInset } = useTraySnap({ id, state });
21
16
  const { flattenSnapPoints } = useTrayUtils();
22
17
  const emitter = useMagicEmitter();
23
18
  const easings = useEasings();
@@ -42,29 +37,6 @@ export function useTrayMagnetism(args) {
42
37
  const enabled = computed(
43
38
  () => magneticSides.value.length > 0 && !disabled.value
44
39
  );
45
- const magneticPoints = computed(
46
- () => {
47
- const result = {
48
- top: [],
49
- right: [],
50
- bottom: [],
51
- left: []
52
- };
53
- for (const side of magneticSides.value) {
54
- const config = sideConfig(side);
55
- if (!config || !mappedSnapPoints(side).length) {
56
- continue;
57
- }
58
- result[side] = Object.entries(config).map(([key, direction]) => ({
59
- inset: mapSnapPoint(side, coercePoint(key)),
60
- direction
61
- })).filter(
62
- (point) => point.inset === 0 || !!point.inset && !Number.isNaN(point.inset)
63
- );
64
- }
65
- return result;
66
- }
67
- );
68
40
  const progress = {
69
41
  top: 0,
70
42
  right: 0,
@@ -136,11 +108,11 @@ export function useTrayMagnetism(args) {
136
108
  }
137
109
  }
138
110
  function restDirection(side) {
139
- const rest = state.snapped[side];
140
- const match = magneticPoints.value[side].find(
141
- (point) => Math.abs(point.inset - rest) < EPSILON
142
- );
143
- return match ? match.direction : null;
111
+ const point = state.activeSnapPoint[side];
112
+ if (point === void 0) {
113
+ return null;
114
+ }
115
+ return sideConfig(side)?.[point] ?? null;
144
116
  }
145
117
  function handleRect(side) {
146
118
  const handle = unrefElement(handleRefs[side].value?.[0]);
@@ -169,7 +141,7 @@ export function useTrayMagnetism(args) {
169
141
  if (settling[side]) {
170
142
  return;
171
143
  }
172
- if (Math.abs(magneticOffset[side]) <= EPSILON) {
144
+ if (Math.round(magneticOffset[side]) === 0) {
173
145
  resetSide(side);
174
146
  return;
175
147
  }
@@ -346,7 +318,7 @@ export function useTrayMagnetism(args) {
346
318
  -state.dragged[side],
347
319
  maxInset(side) - state.dragged[side]
348
320
  );
349
- if (Math.abs(target) > EPSILON) {
321
+ if (Math.round(target) !== 0) {
350
322
  cancelSettle(side);
351
323
  magneticOffset[side] = target;
352
324
  if (!isVirtual.value) {
@@ -2,7 +2,7 @@ import { toValue, watch } from "vue";
2
2
  import { useMagicEmitter } from "@maas/vue-equipment/plugins/MagicEmitter";
3
3
  import { clampValue } from "@maas/vue-equipment/utils";
4
4
  import { useTraySnap } from "./useTraySnap.mjs";
5
- const SIDES = ["top", "right", "bottom", "left"];
5
+ import { SIDES } from "./useTrayUtils.mjs";
6
6
  export function useTrayProgress(args) {
7
7
  const { id, state } = args;
8
8
  const emitter = useMagicEmitter();
@@ -7,7 +7,6 @@ import {
7
7
  } from "@maas/vue-equipment/utils";
8
8
  import { useMagicEmitter } from "@maas/vue-equipment/plugins/MagicEmitter";
9
9
  import { useTrayUtils } from "./useTrayUtils.mjs";
10
- const SNAP_TOLERANCE = 0.01;
11
10
  function isMapped(value) {
12
11
  return value !== void 0 && !Number.isNaN(value);
13
12
  }
@@ -118,9 +117,7 @@ export function useTraySnap(args) {
118
117
  if (mapped === void 0) {
119
118
  return false;
120
119
  }
121
- return !!rangeAt(side, mapped) || mappedSnapPoints(side).some(
122
- (point) => Math.abs(point - mapped) < SNAP_TOLERANCE
123
- );
120
+ return !!rangeAt(side, mapped) || mappedSnapPoints(side).includes(mapped);
124
121
  }
125
122
  function findSnapTarget(side, inset) {
126
123
  const target = snapTargetAt({
@@ -186,6 +183,7 @@ export function useTraySnap(args) {
186
183
  }
187
184
  const closest = findSnapTarget(side, mapped) ?? mapped;
188
185
  state.snapped[side] = closest;
186
+ state.lastDragged[side] = closest;
189
187
  state.activeSnapPoint[side] = snapPointAt(side, closest) ?? snapPoint;
190
188
  if (shouldInterpolate) {
191
189
  interpolateDragged({ side, to: closest, duration });
@@ -1,8 +1,15 @@
1
- import type { MagicTraySide, MagicTraySnapEntry, MagicTraySnapRange } from '../../types/index.js';
1
+ import type { MagicTraySide, MagicTraySnapEntry, MagicTraySnapRange, TraySnapPoints } from '../../types/index.js';
2
+ export declare const SIDES: Array<MagicTraySide>;
3
+ type IsDraggableSideArgs = {
4
+ snapPoints: TraySnapPoints;
5
+ side: MagicTraySide;
6
+ };
2
7
  export declare function useTrayUtils(): {
3
8
  clampWithOvershoot: (value: number, min: number, max: number, outer: number, inner: number) => any;
4
9
  isVertical: (side: MagicTraySide) => side is "top" | "bottom";
5
10
  oppositeSide: (side: MagicTraySide) => MagicTraySide;
6
11
  isSnapRange: (entry: MagicTraySnapEntry) => entry is MagicTraySnapRange;
7
12
  flattenSnapPoints: (entries: Array<MagicTraySnapEntry>) => import("../../types/index.js").MagicTraySnapPoint[];
13
+ isDraggableSide: (args: IsDraggableSideArgs) => boolean;
8
14
  };
15
+ export {};
@@ -1,4 +1,5 @@
1
1
  import { rubberband } from "@maas/vue-equipment/utils";
2
+ export const SIDES = ["top", "right", "bottom", "left"];
2
3
  export function useTrayUtils() {
3
4
  function clampWithOvershoot(value, min, max, outer, inner) {
4
5
  if (value < min) {
@@ -32,11 +33,16 @@ export function useTrayUtils() {
32
33
  (entry) => isSnapRange(entry) ? [entry.min, entry.max] : [entry]
33
34
  );
34
35
  }
36
+ function isDraggableSide(args) {
37
+ const { snapPoints, side } = args;
38
+ return (snapPoints[side]?.length ?? 0) > 0;
39
+ }
35
40
  return {
36
41
  clampWithOvershoot,
37
42
  isVertical,
38
43
  oppositeSide,
39
44
  isSnapRange,
40
- flattenSnapPoints
45
+ flattenSnapPoints,
46
+ isDraggableSide
41
47
  };
42
48
  }
@@ -19,7 +19,7 @@ const defaultOptions = {
19
19
  virtual: false
20
20
  },
21
21
  threshold: {
22
- lock: 0,
22
+ lock: 8,
23
23
  distance: 128,
24
24
  momentum: 1
25
25
  },
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@maas/vue-equipment",
3
3
  "description": "Our Frontend Toolkit, Free and Open Source",
4
- "version": "1.1.0",
4
+ "version": "1.3.0",
5
5
  "contributors": [
6
6
  {
7
7
  "name": "Robin Scholz",
@@ -78,7 +78,7 @@
78
78
  "@floating-ui/vue": "^1 || ^2",
79
79
  "@maas/magic-timer": "^1",
80
80
  "@maas/vue-autosize": "^1",
81
- "@maas/vue-primitive": "^1.4",
81
+ "@maas/vue-primitive": "^1.5",
82
82
  "@nuxt/kit": ">=3",
83
83
  "@vueuse/core": ">=12",
84
84
  "@vueuse/integrations": ">=12",
@@ -134,8 +134,7 @@
134
134
  "scripts": {
135
135
  "dev": "turbo run dev --parallel",
136
136
  "dev:docs": "turbo run dev --filter=docs",
137
- "dev:nuxt": "turbo run dev --filter=nuxt",
138
- "build": "turbo run build --filter=!playground",
137
+ "build": "turbo run build",
139
138
  "build:types": "turbo run build:types",
140
139
  "build:docs": "pnpm exec playwright install chromium --with-deps && turbo run build --filter=docs",
141
140
  "tokens": "mirror tokens && mirror css",