@maas/vue-equipment 1.0.1 → 1.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.
Files changed (41) hide show
  1. package/dist/nuxt/module.json +1 -1
  2. package/dist/nuxt/module.mjs +2 -2
  3. package/dist/plugins/MagicCarousel/src/utils/defaultOptions.mjs +1 -1
  4. package/dist/plugins/MagicDraggable/src/utils/defaultOptions.mjs +1 -1
  5. package/dist/plugins/MagicDrawer/index.d.ts +2 -2
  6. package/dist/plugins/MagicDrawer/src/components/MagicDrawerContent.vue +4 -0
  7. package/dist/plugins/MagicDrawer/src/composables/private/useDrawerDrag.mjs +128 -170
  8. package/dist/plugins/MagicDrawer/src/composables/private/useDrawerProgress.mjs +57 -77
  9. package/dist/plugins/MagicDrawer/src/composables/private/useDrawerSnap.d.ts +16 -11
  10. package/dist/plugins/MagicDrawer/src/composables/private/useDrawerSnap.mjs +175 -175
  11. package/dist/plugins/MagicDrawer/src/composables/private/useDrawerState.mjs +2 -1
  12. package/dist/plugins/MagicDrawer/src/composables/private/useDrawerUtils.d.ts +3 -0
  13. package/dist/plugins/MagicDrawer/src/composables/private/useDrawerUtils.mjs +11 -1
  14. package/dist/plugins/MagicDrawer/src/composables/useMagicDrawer.d.ts +1 -0
  15. package/dist/plugins/MagicDrawer/src/composables/useMagicDrawer.mjs +2 -1
  16. package/dist/plugins/MagicDrawer/src/types/index.d.ts +8 -1
  17. package/dist/plugins/MagicDrawer/src/utils/defaultOptions.mjs +1 -1
  18. package/dist/plugins/MagicTray/index.d.ts +4 -3
  19. package/dist/plugins/MagicTray/index.mjs +3 -0
  20. package/dist/plugins/MagicTray/src/components/MagicTrayContent.d.vue.ts +2 -2
  21. package/dist/plugins/MagicTray/src/components/MagicTrayContent.vue +17 -16
  22. package/dist/plugins/MagicTray/src/components/MagicTrayContent.vue.d.ts +2 -2
  23. package/dist/plugins/MagicTray/src/components/MagicTrayTrigger.d.vue.ts +25 -0
  24. package/dist/plugins/MagicTray/src/components/MagicTrayTrigger.vue +90 -0
  25. package/dist/plugins/MagicTray/src/components/MagicTrayTrigger.vue.d.ts +25 -0
  26. package/dist/plugins/MagicTray/src/composables/private/useTrayDrag.d.ts +0 -4
  27. package/dist/plugins/MagicTray/src/composables/private/useTrayDrag.mjs +27 -385
  28. package/dist/plugins/MagicTray/src/composables/private/useTrayGesture.d.ts +16 -0
  29. package/dist/plugins/MagicTray/src/composables/private/useTrayGesture.mjs +426 -0
  30. package/dist/plugins/MagicTray/src/composables/private/useTrayMagnetism.mjs +11 -37
  31. package/dist/plugins/MagicTray/src/composables/private/useTrayProgress.mjs +1 -1
  32. package/dist/plugins/MagicTray/src/composables/private/useTraySnap.d.ts +12 -7
  33. package/dist/plugins/MagicTray/src/composables/private/useTraySnap.mjs +88 -40
  34. package/dist/plugins/MagicTray/src/composables/private/useTrayUtils.d.ts +10 -1
  35. package/dist/plugins/MagicTray/src/composables/private/useTrayUtils.mjs +17 -1
  36. package/dist/plugins/MagicTray/src/types/index.d.ts +7 -1
  37. package/dist/plugins/MagicTray/src/utils/defaultOptions.mjs +1 -1
  38. package/dist/utils/index.d.ts +46 -1
  39. package/dist/utils/index.js +75 -0
  40. package/dist/utils/index.js.map +1 -1
  41. package/package.json +2 -2
@@ -7,28 +7,13 @@ import {
7
7
  toValue,
8
8
  watch
9
9
  } from "vue";
10
- import {
11
- unrefElement,
12
- useEventListener,
13
- useResizeObserver,
14
- useThrottleFn
15
- } from "@vueuse/core";
16
- import {
17
- cancelEdgeNavigation,
18
- convertToPixels,
19
- guardedReleasePointerCapture,
20
- guardedSetPointerCapture,
21
- isAndroid,
22
- isIOS,
23
- isWithinRange,
24
- lockSelection
25
- } from "@maas/vue-equipment/utils";
10
+ import { unrefElement, useResizeObserver, useThrottleFn } from "@vueuse/core";
11
+ import { convertToPixels } from "@maas/vue-equipment/utils";
26
12
  import { useMagicEmitter } from "@maas/vue-equipment/plugins/MagicEmitter";
27
13
  import { useMagicError } from "@maas/vue-equipment/plugins/MagicError";
28
14
  import { useTraySnap } from "./useTraySnap.mjs";
29
- import { useTrayUtils } from "./useTrayUtils.mjs";
15
+ import { SIDES, useTrayUtils } from "./useTrayUtils.mjs";
30
16
  import { useTrayState } from "./useTrayState.mjs";
31
- const SIDES = ["top", "right", "bottom", "left"];
32
17
  export function useTrayDrag(args) {
33
18
  const { id, elRef } = args;
34
19
  const { logWarning } = useMagicError({
@@ -37,72 +22,27 @@ export function useTrayDrag(args) {
37
22
  });
38
23
  const { initializeState } = useTrayState(toValue(id));
39
24
  const state = initializeState();
40
- const { clampWithOvershoot, isVertical } = useTrayUtils();
25
+ const { flattenSnapPoints, isDraggableSide } = useTrayUtils();
41
26
  const emitter = useMagicEmitter();
42
27
  const {
43
28
  dimension,
44
29
  contentExtent,
45
- maxInset,
46
30
  mapSnapPoint,
47
31
  mappedSnapPoints,
48
- snapPointsMap,
49
- findClosestSnapPoint,
50
- interpolateDragged,
32
+ snapPointAt,
33
+ isSnapTarget,
51
34
  snapTo
52
35
  } = useTraySnap({ id, state });
53
- function dragBounds(side) {
54
- const points = mappedSnapPoints(side);
55
- const geometricMax = maxInset(side);
56
- if (!points.length) {
57
- return { min: 0, max: geometricMax };
58
- }
59
- return {
60
- min: Math.max(0, points[0]),
61
- max: Math.min(points[points.length - 1], geometricMax)
62
- };
63
- }
64
36
  function openSnapPoint(side) {
65
37
  const points = mappedSnapPoints(side);
66
- return points.length ? snapPointsMap(side)[points[0]] : void 0;
38
+ return points.length ? snapPointAt(side, points[0]) : void 0;
67
39
  }
68
- let lastPendingTarget = void 0;
69
- let suppressClick = false;
70
- let cancelPointerup = void 0;
71
- let cancelPointermove = void 0;
72
- let cancelPointercancel = void 0;
73
- let cancelTouchmove = void 0;
74
- let cancelTouchend = void 0;
75
- let cancelTouchcancel = void 0;
76
40
  let resizeObserverEl = null;
77
- let pointerdownTarget = void 0;
78
- let releaseSelection = void 0;
79
41
  const draggableSides = computed(
80
- () => SIDES.filter((side) => (state.options.snapPoints[side]?.length ?? 0) > 0)
81
- );
82
- const threshold = computed(() => state.options.threshold);
83
- const disabled = computed(() => state.options.disabled);
84
- const snapMode = computed(() => state.options.snap.mode);
85
- const dragMode = computed(() => state.options.drag.mode);
86
- const preventEdgeNavigation = computed(
87
- () => state.options.preventEdgeNavigation
42
+ () => SIDES.filter(
43
+ (side) => isDraggableSide({ snapPoints: state.options.snapPoints, side })
44
+ )
88
45
  );
89
- function snapReference(side) {
90
- return snapMode.value === "step" ? state.lastDragged[side] : state.dragged[side];
91
- }
92
- function isSnapDrag(side) {
93
- return typeof dragMode.value === "string" ? dragMode.value === "snap" : (dragMode.value?.[side] ?? "free") === "snap";
94
- }
95
- const hasDragged = computed(() => {
96
- const side = state.draggingSide;
97
- if (!side) {
98
- return false;
99
- }
100
- return !isWithinRange({
101
- input: state.dragged[side],
102
- base: state.lastDragged[side],
103
- threshold: toValue(threshold).lock
104
- });
105
- });
106
46
  const clipPath = computed(() => {
107
47
  const top = Math.max(0, state.dragged.top + state.magnetic.top);
108
48
  const right = Math.max(0, state.dragged.right + state.magnetic.right);
@@ -175,304 +115,6 @@ export function useTrayDrag(args) {
175
115
  state.overshoot.inner = innerPixels ?? 0;
176
116
  await nextTick();
177
117
  }
178
- function computeInset(side, coord) {
179
- let newInset = 0;
180
- switch (side) {
181
- case "top":
182
- newInset = coord - state.origin;
183
- break;
184
- case "bottom":
185
- newInset = state.origin - coord;
186
- break;
187
- case "left":
188
- newInset = coord - state.origin;
189
- break;
190
- case "right":
191
- newInset = state.origin - coord;
192
- break;
193
- }
194
- const { min, max } = dragBounds(side);
195
- return clampWithOvershoot(
196
- newInset,
197
- min,
198
- max,
199
- state.overshoot.outer[side],
200
- state.overshoot.inner
201
- );
202
- }
203
- function setDragged(side, coord) {
204
- const newInset = computeInset(side, coord);
205
- if (newInset === state.dragged[side]) {
206
- return;
207
- }
208
- const prev = state.dragged[side];
209
- state.relDirection[side] = newInset < prev ? "below" : "above";
210
- state.dragged[side] = newInset;
211
- }
212
- function snapDragged(side, coord) {
213
- const inset = computeInset(side, coord);
214
- const target = findClosestSnapPoint({ side, value: inset });
215
- if (target === void 0 || target === state.snapped[side]) {
216
- return;
217
- }
218
- const snapPoint = snapPointsMap(side)[target];
219
- state.dragged[side] = target;
220
- state.snapped[side] = target;
221
- state.activeSnapPoint[side] = snapPoint;
222
- if (snapPoint || snapPoint === 0) {
223
- emitter.emit("beforeSnap", {
224
- id: toValue(id),
225
- snapPoint: { side, point: snapPoint }
226
- });
227
- emitter.emit("afterSnap", {
228
- id: toValue(id),
229
- snapPoint: { side, point: snapPoint }
230
- });
231
- }
232
- }
233
- function checkPosition(side) {
234
- const delta = state.dragged[side] - state.lastDragged[side];
235
- if (Math.abs(delta) > toValue(threshold).distance) {
236
- state.interpolateTo = findClosestSnapPoint({
237
- side,
238
- value: snapReference(side),
239
- direction: delta < 0 ? "below" : "above"
240
- });
241
- } else {
242
- state.interpolateTo = void 0;
243
- }
244
- }
245
- function emitWillSnapTo(side) {
246
- const target = state.interpolateTo ?? state.snapped[side];
247
- if (target === lastPendingTarget) {
248
- return;
249
- }
250
- lastPendingTarget = target;
251
- const snapPoint = snapPointsMap(side)[target];
252
- if (!snapPoint && snapPoint !== 0) {
253
- return;
254
- }
255
- emitter.emit("willSnapTo", {
256
- id: toValue(id),
257
- side,
258
- snapPoint
259
- });
260
- }
261
- function checkMomentum(side) {
262
- const elapsed = Date.now() - state.dragStart.getTime();
263
- const distance = Math.abs(state.dragged[side] - state.lastDragged[side]);
264
- const velocity = elapsed && distance ? distance / elapsed : 0;
265
- if (velocity > toValue(threshold).momentum) {
266
- state.interpolateTo = findClosestSnapPoint({
267
- side,
268
- value: snapReference(side),
269
- direction: state.relDirection[side]
270
- });
271
- }
272
- }
273
- function resetListeners() {
274
- cancelTouchmove?.();
275
- cancelTouchend?.();
276
- cancelTouchcancel?.();
277
- cancelPointerup?.();
278
- cancelPointermove?.();
279
- cancelPointercancel?.();
280
- }
281
- function resetDragState() {
282
- releaseSelection?.();
283
- releaseSelection = void 0;
284
- state.dragging = false;
285
- state.draggingSide = void 0;
286
- state.interpolateTo = void 0;
287
- }
288
- function settle(side) {
289
- if (state.interpolateTo || state.interpolateTo === 0) {
290
- interpolateDragged({ side, to: state.interpolateTo });
291
- state.snapped[side] = state.interpolateTo;
292
- state.activeSnapPoint[side] = snapPointsMap(side)[state.interpolateTo];
293
- } else {
294
- interpolateDragged({ side, to: state.snapped[side] });
295
- }
296
- }
297
- function onPointermove(e) {
298
- if (e.isTrusted && !e.isPrimary) {
299
- return;
300
- }
301
- const side = state.draggingSide;
302
- if (!side) {
303
- return;
304
- }
305
- e.stopImmediatePropagation();
306
- e.stopPropagation();
307
- const coord = isVertical(side) ? e.clientY : e.clientX;
308
- if (isSnapDrag(side)) {
309
- snapDragged(side, coord);
310
- } else {
311
- setDragged(side, coord);
312
- checkMomentum(side);
313
- checkPosition(side);
314
- emitWillSnapTo(side);
315
- }
316
- emitter.emit("drag", {
317
- id: toValue(id),
318
- side,
319
- value: state.dragged[side]
320
- });
321
- }
322
- function onPointerup(e) {
323
- const side = state.draggingSide;
324
- if (side) {
325
- suppressClick = hasDragged.value;
326
- if (!isSnapDrag(side)) {
327
- settle(side);
328
- }
329
- emitter.emit("afterDrag", {
330
- id: toValue(id),
331
- side,
332
- value: state.dragged[side]
333
- });
334
- }
335
- resetDragState();
336
- resetListeners();
337
- guardedReleasePointerCapture({ event: e, element: pointerdownTarget });
338
- }
339
- function onTouchmove(e) {
340
- const side = state.draggingSide;
341
- if (!side) {
342
- return;
343
- }
344
- const firstTouch = e.touches[0];
345
- if (!firstTouch) {
346
- return;
347
- }
348
- e.stopImmediatePropagation();
349
- e.stopPropagation();
350
- if (hasDragged.value) {
351
- e.preventDefault();
352
- }
353
- const coord = isVertical(side) ? firstTouch.clientY : firstTouch.clientX;
354
- if (isSnapDrag(side)) {
355
- snapDragged(side, coord);
356
- } else {
357
- setDragged(side, coord);
358
- checkMomentum(side);
359
- checkPosition(side);
360
- emitWillSnapTo(side);
361
- }
362
- emitter.emit("drag", {
363
- id: toValue(id),
364
- side,
365
- value: state.dragged[side]
366
- });
367
- }
368
- function onTouchend() {
369
- const side = state.draggingSide;
370
- if (side) {
371
- suppressClick = hasDragged.value;
372
- if (!isSnapDrag(side)) {
373
- settle(side);
374
- }
375
- emitter.emit("afterDrag", {
376
- id: toValue(id),
377
- side,
378
- value: state.dragged[side]
379
- });
380
- }
381
- resetDragState();
382
- resetListeners();
383
- }
384
- function beginDrag(side, coord, target) {
385
- state.dragging = true;
386
- state.draggingSide = side;
387
- state.interpolateTo = void 0;
388
- state.dragged[side] += state.magnetic[side];
389
- state.magnetic[side] = 0;
390
- state.lastDragged[side] = state.dragged[side];
391
- lastPendingTarget = void 0;
392
- suppressClick = false;
393
- pointerdownTarget = target;
394
- releaseSelection = lockSelection();
395
- switch (side) {
396
- case "top":
397
- case "left":
398
- state.origin = coord - state.dragged[side];
399
- break;
400
- case "bottom":
401
- case "right":
402
- state.origin = coord + state.dragged[side];
403
- break;
404
- }
405
- state.dragStart = /* @__PURE__ */ new Date();
406
- emitter.emit("beforeDrag", {
407
- id: toValue(id),
408
- side,
409
- value: state.dragged[side]
410
- });
411
- }
412
- function onHandlePointerdown(side, e) {
413
- if (state.dragging || toValue(disabled)) {
414
- return;
415
- }
416
- const coord = isVertical(side) ? e.clientY : e.clientX;
417
- const target = e.target;
418
- beginDrag(side, coord, target);
419
- guardedSetPointerCapture({ event: e, element: target });
420
- resetListeners();
421
- cancelPointerup = useEventListener(document, "pointerup", onPointerup);
422
- cancelPointercancel = useEventListener(
423
- document,
424
- "pointercancel",
425
- onPointerup
426
- );
427
- cancelPointermove = useEventListener(
428
- document,
429
- "pointermove",
430
- onPointermove,
431
- {
432
- passive: false
433
- }
434
- );
435
- cancelTouchend = isIOS() || isAndroid() ? useEventListener(document, "touchend", onTouchend) : void 0;
436
- cancelTouchcancel = isIOS() || isAndroid() ? useEventListener(document, "touchcancel", onTouchend) : void 0;
437
- onPointermove(e);
438
- }
439
- function onHandleTouchstart(side, e) {
440
- if (toValue(disabled)) {
441
- return;
442
- }
443
- if (preventEdgeNavigation.value) {
444
- cancelEdgeNavigation({ event: e });
445
- }
446
- if (!isAndroid() || state.dragging) {
447
- return;
448
- }
449
- const firstTouch = e.touches[0];
450
- if (!firstTouch) {
451
- return;
452
- }
453
- e.stopImmediatePropagation();
454
- e.stopPropagation();
455
- const coord = isVertical(side) ? firstTouch.clientY : firstTouch.clientX;
456
- beginDrag(side, coord, e.target);
457
- cancelTouchmove?.();
458
- cancelTouchmove = useEventListener(document, "touchmove", onTouchmove, {
459
- passive: false
460
- });
461
- cancelTouchend?.();
462
- cancelTouchend = useEventListener(document, "touchend", onTouchend, {
463
- passive: false
464
- });
465
- cancelTouchcancel?.();
466
- cancelTouchcancel = useEventListener(document, "touchcancel", onTouchend);
467
- onTouchmove(e);
468
- }
469
- function onHandleClick(e) {
470
- if (suppressClick) {
471
- e.stopPropagation();
472
- e.preventDefault();
473
- }
474
- suppressClick = false;
475
- }
476
118
  async function snapToCallback(payload) {
477
119
  const { snapPoint } = payload;
478
120
  if (payload.id !== toValue(id) || typeof snapPoint !== "object" || Array.isArray(snapPoint)) {
@@ -484,6 +126,12 @@ export function useTrayDrag(args) {
484
126
  return;
485
127
  }
486
128
  await getSizes();
129
+ if (contentExtent(side) && !isSnapTarget(side, point)) {
130
+ logWarning(
131
+ `Cannot snap side "${side}" to ${point}, which is neither a snap point nor inside a range`
132
+ );
133
+ return;
134
+ }
487
135
  snapTo({
488
136
  side,
489
137
  snapPoint: point,
@@ -501,7 +149,14 @@ export function useTrayDrag(args) {
501
149
  pendingInitialSides.add(side);
502
150
  continue;
503
151
  }
504
- const initial = state.options.initial.snapPoints?.[side] ?? openSnapPoint(side);
152
+ const configured = state.options.initial.snapPoints?.[side];
153
+ const isValid = configured === void 0 || isSnapTarget(side, configured);
154
+ if (!isValid) {
155
+ logWarning(
156
+ `initial.snapPoints.${side} (${configured}) is neither a snap point nor inside a range and is ignored`
157
+ );
158
+ }
159
+ const initial = (isValid ? configured : void 0) ?? openSnapPoint(side);
505
160
  if (initial === void 0) {
506
161
  continue;
507
162
  }
@@ -518,7 +173,7 @@ export function useTrayDrag(args) {
518
173
  }
519
174
  function validateSnapPoints() {
520
175
  for (const side of draggableSides.value) {
521
- const points = state.options.snapPoints[side] ?? [];
176
+ const points = flattenSnapPoints(state.options.snapPoints[side] ?? []);
522
177
  const canOpen = points.some((point) => parseFloat(String(point)) === 0);
523
178
  const hasInitial = state.options.initial.snapPoints?.[side] !== void 0;
524
179
  if (!canOpen && !hasInitial) {
@@ -536,8 +191,7 @@ export function useTrayDrag(args) {
536
191
  function destroy() {
537
192
  emitter.off("snapTo", snapToCallback);
538
193
  resizeObserverEl?.stop();
539
- resetDragState();
540
- resetListeners();
194
+ state.elRect = void 0;
541
195
  }
542
196
  onMounted(async () => {
543
197
  await initialize();
@@ -553,14 +207,6 @@ export function useTrayDrag(args) {
553
207
  await applyInitial();
554
208
  }
555
209
  );
556
- watch(disabled, (value) => {
557
- if (value && state.draggingSide) {
558
- const side = state.draggingSide;
559
- interpolateDragged({ side, to: state.snapped[side] });
560
- resetDragState();
561
- resetListeners();
562
- }
563
- });
564
210
  resizeObserverEl = useResizeObserver(elRef, () => {
565
211
  useThrottleFn(async () => {
566
212
  await getSizes();
@@ -582,10 +228,6 @@ export function useTrayDrag(args) {
582
228
  draggableSides,
583
229
  clipPath,
584
230
  handleStyle,
585
- hasDragged,
586
- dimension,
587
- onHandlePointerdown,
588
- onHandleTouchstart,
589
- onHandleClick
231
+ dimension
590
232
  };
591
233
  }
@@ -0,0 +1,16 @@
1
+ import type { MaybeRef, MaybeRefOrGetter } from 'vue';
2
+ import type { MagicTraySide, TrayState } from '../../types/index.js';
3
+ type UseTrayGestureArgs = {
4
+ id: MaybeRef<string>;
5
+ state: TrayState;
6
+ selectionLock?: 'press' | 'drag';
7
+ preventEdgeNavigation: MaybeRefOrGetter<boolean>;
8
+ };
9
+ export declare function useTrayGesture(args: UseTrayGestureArgs): {
10
+ active: Readonly<import("vue").Ref<boolean, boolean>>;
11
+ hasDragged: import("vue").ComputedRef<boolean>;
12
+ onPointerdown: (side: MagicTraySide, e: PointerEvent) => void;
13
+ onTouchstart: (side: MagicTraySide, e: TouchEvent) => void;
14
+ };
15
+ export type UseTrayGestureReturn = ReturnType<typeof useTrayGesture>;
16
+ export {};