@maas/vue-equipment 1.3.0 → 1.4.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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@maas/vue-equipment/nuxt",
3
3
  "configKey": "vueEquipment",
4
- "version": "1.2.0",
4
+ "version": "1.3.0",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.3",
7
7
  "unbuild": "unknown"
@@ -2,7 +2,7 @@ import type { MaybeRef } from 'vue';
2
2
  import type { MagicTraySide } from '../types/index.js';
3
3
  interface MagicTrayTriggerProps {
4
4
  id?: MaybeRef<string>;
5
- side: MagicTraySide;
5
+ side: MagicTraySide | Array<MagicTraySide>;
6
6
  disabled?: boolean;
7
7
  preventEdgeNavigation?: boolean;
8
8
  asChild?: boolean;
@@ -3,7 +3,8 @@
3
3
  class="magic-tray-trigger"
4
4
  :as-child="asChild"
5
5
  :data-id="`${mappedId}-trigger`"
6
- :data-side="side"
6
+ :data-side="mappedSide"
7
+ :data-axis="axis"
7
8
  :data-dragging="active"
8
9
  :data-dragged="hasDragged"
9
10
  :data-disabled="mappedDisabled"
@@ -29,7 +30,7 @@ const {
29
30
  asChild
30
31
  } = defineProps({
31
32
  id: { type: null, required: false },
32
- side: { type: String, required: true },
33
+ side: { type: [String, Array], required: true },
33
34
  disabled: { type: Boolean, required: false },
34
35
  preventEdgeNavigation: { type: Boolean, required: false },
35
36
  asChild: { type: Boolean, required: false }
@@ -54,6 +55,17 @@ const { active, hasDragged, onPointerdown, onTouchstart } = useTrayGesture({
54
55
  preventEdgeNavigation: () => preventEdgeNavigation ?? state.options.preventEdgeNavigation
55
56
  });
56
57
  const mappedDisabled = computed(() => disabled || state.options.disabled);
58
+ const sides = computed(() => Array.isArray(side) ? side : [side]);
59
+ const mappedSide = computed(() => sides.value.join(" "));
60
+ const axis = computed(() => {
61
+ const horizontal = sides.value.some(
62
+ (side2) => side2 === "left" || side2 === "right"
63
+ );
64
+ const vertical = sides.value.some(
65
+ (side2) => side2 === "top" || side2 === "bottom"
66
+ );
67
+ return horizontal && vertical ? "both" : vertical ? "y" : "x";
68
+ });
57
69
  function isEditable(target) {
58
70
  if (!(target instanceof Element)) {
59
71
  return false;
@@ -76,16 +88,18 @@ function guardedTouchstart(event) {
76
88
  </script>
77
89
 
78
90
  <style>
79
- .magic-tray-trigger[data-disabled='false'][data-side='left'],
80
- .magic-tray-trigger[data-disabled='false'][data-side='right'] {
91
+ .magic-tray-trigger[data-disabled='false'][data-axis='x'] {
81
92
  touch-action: var(--magic-tray-trigger-touch-action, pan-y);
82
93
  }
83
94
 
84
- .magic-tray-trigger[data-disabled='false'][data-side='top'],
85
- .magic-tray-trigger[data-disabled='false'][data-side='bottom'] {
95
+ .magic-tray-trigger[data-disabled='false'][data-axis='y'] {
86
96
  touch-action: var(--magic-tray-trigger-touch-action, pan-x);
87
97
  }
88
98
 
99
+ .magic-tray-trigger[data-disabled='false'][data-axis='both'] {
100
+ touch-action: var(--magic-tray-trigger-touch-action, none);
101
+ }
102
+
89
103
  .magic-tray-trigger[data-dragging='true'] * {
90
104
  -webkit-user-drag: none;
91
105
  }
@@ -2,7 +2,7 @@ import type { MaybeRef } from 'vue';
2
2
  import type { MagicTraySide } from '../types/index.js';
3
3
  interface MagicTrayTriggerProps {
4
4
  id?: MaybeRef<string>;
5
- side: MagicTraySide;
5
+ side: MagicTraySide | Array<MagicTraySide>;
6
6
  disabled?: boolean;
7
7
  preventEdgeNavigation?: boolean;
8
8
  asChild?: boolean;
@@ -9,8 +9,8 @@ type UseTrayGestureArgs = {
9
9
  export declare function useTrayGesture(args: UseTrayGestureArgs): {
10
10
  active: Readonly<import("vue").Ref<boolean, boolean>>;
11
11
  hasDragged: import("vue").ComputedRef<boolean>;
12
- onPointerdown: (side: MagicTraySide, e: PointerEvent) => void;
13
- onTouchstart: (side: MagicTraySide, e: TouchEvent) => void;
12
+ onPointerdown: (side: MagicTraySide | Array<MagicTraySide>, e: PointerEvent) => void;
13
+ onTouchstart: (side: MagicTraySide | Array<MagicTraySide>, e: TouchEvent) => void;
14
14
  };
15
15
  export type UseTrayGestureReturn = ReturnType<typeof useTrayGesture>;
16
16
  export {};
@@ -39,6 +39,7 @@ export function useTrayGesture(args) {
39
39
  let cancelTouchcancel = void 0;
40
40
  let pointerdownTarget = null;
41
41
  let releaseSelection = void 0;
42
+ let pending = void 0;
42
43
  const threshold = computed(() => state.options.threshold);
43
44
  const disabled = computed(() => state.options.disabled);
44
45
  const snapMode = computed(() => state.options.snap.mode);
@@ -57,8 +58,45 @@ export function useTrayGesture(args) {
57
58
  function lockSelectionOnce() {
58
59
  releaseSelection ??= lockSelection();
59
60
  }
60
- function canBegin(side) {
61
- return !state.dragging && !toValue(disabled) && state.elRect !== void 0 && isDraggableSide({ snapPoints: state.options.snapPoints, side });
61
+ function canStart() {
62
+ return !state.dragging && !toValue(disabled) && state.elRect !== void 0;
63
+ }
64
+ function draggableSides(side) {
65
+ const sides = Array.isArray(side) ? side : [side];
66
+ return sides.filter(
67
+ (side2) => isDraggableSide({ snapPoints: state.options.snapPoints, side: side2 })
68
+ );
69
+ }
70
+ function resolveSide(sides, dx, dy) {
71
+ const horizontal = sides.filter((side) => !isVertical(side));
72
+ const vertical = sides.filter(isVertical);
73
+ const alongX = horizontal.length > 0 && (!vertical.length || Math.abs(dx) >= Math.abs(dy));
74
+ const delta = alongX ? dx : dy;
75
+ if (Math.abs(delta) <= toValue(threshold).lock) {
76
+ return void 0;
77
+ }
78
+ const candidates = alongX ? horizontal : vertical;
79
+ const preferred = alongX ? delta > 0 ? "left" : "right" : delta > 0 ? "top" : "bottom";
80
+ return candidates.includes(preferred) ? preferred : candidates[0];
81
+ }
82
+ function resolvePending(x, y) {
83
+ if (!pending) {
84
+ return void 0;
85
+ }
86
+ if (!canStart()) {
87
+ pending = void 0;
88
+ resetListeners();
89
+ return void 0;
90
+ }
91
+ const side = resolveSide(pending.sides, x - pending.x, y - pending.y);
92
+ if (!side) {
93
+ return void 0;
94
+ }
95
+ const { x: pressX, y: pressY, target, pressedAt } = pending;
96
+ pending = void 0;
97
+ beginDrag(side, isVertical(side) ? pressY : pressX, target);
98
+ state.dragStart = pressedAt;
99
+ return side;
62
100
  }
63
101
  function dragBounds(side) {
64
102
  const points = mappedSnapPoints(side);
@@ -173,11 +211,11 @@ export function useTrayGesture(args) {
173
211
  function emitWillSnapTo(side) {
174
212
  const target = settleTarget(side);
175
213
  const isPoint = mappedSnapPoints(side).includes(target);
176
- const pending = !isPoint && rangeAt(side, target)?.range || target;
177
- if (pending === lastPendingTarget) {
214
+ const pending2 = !isPoint && rangeAt(side, target)?.range || target;
215
+ if (pending2 === lastPendingTarget) {
178
216
  return;
179
217
  }
180
- lastPendingTarget = pending;
218
+ lastPendingTarget = pending2;
181
219
  const snapPoint = snapPointAt(side, target);
182
220
  if (snapPoint === void 0) {
183
221
  return;
@@ -204,6 +242,7 @@ export function useTrayGesture(args) {
204
242
  }
205
243
  function resetDragState() {
206
244
  const side = state.draggingSide;
245
+ pending = void 0;
207
246
  if (side) {
208
247
  state.lastDragged[side] = state.snapped[side];
209
248
  }
@@ -226,7 +265,7 @@ export function useTrayGesture(args) {
226
265
  if (e.isTrusted && !e.isPrimary) {
227
266
  return;
228
267
  }
229
- const side = state.draggingSide;
268
+ const side = state.draggingSide ?? resolvePending(e.clientX, e.clientY);
230
269
  if (!side) {
231
270
  return;
232
271
  }
@@ -269,14 +308,14 @@ export function useTrayGesture(args) {
269
308
  guardedReleasePointerCapture({ event: e, element: pointerdownTarget });
270
309
  }
271
310
  function onTouchmove(e) {
272
- const side = state.draggingSide;
273
- if (!side) {
274
- return;
275
- }
276
311
  const firstTouch = e.touches[0];
277
312
  if (!firstTouch) {
278
313
  return;
279
314
  }
315
+ const side = state.draggingSide ?? resolvePending(firstTouch.clientX, firstTouch.clientY);
316
+ if (!side) {
317
+ return;
318
+ }
280
319
  e.stopImmediatePropagation();
281
320
  e.stopPropagation();
282
321
  if (hasDragged.value) {
@@ -355,15 +394,28 @@ export function useTrayGesture(args) {
355
394
  interpolateDragged({ side, to: state.snapped[side] });
356
395
  resetDragState();
357
396
  }
397
+ pending = void 0;
358
398
  resetListeners();
359
399
  }
360
400
  function onPointerdown(side, e) {
361
- if (!canBegin(side)) {
401
+ const sides = draggableSides(side);
402
+ if (!canStart() || !sides.length) {
362
403
  return;
363
404
  }
364
- const coord = isVertical(side) ? e.clientY : e.clientX;
365
405
  const target = e.target instanceof Element ? e.target : null;
366
- beginDrag(side, coord, target);
406
+ const only = sides.length === 1 ? sides[0] : void 0;
407
+ if (only) {
408
+ beginDrag(only, isVertical(only) ? e.clientY : e.clientX, target);
409
+ } else {
410
+ pending = {
411
+ sides,
412
+ x: e.clientX,
413
+ y: e.clientY,
414
+ target,
415
+ pressedAt: /* @__PURE__ */ new Date()
416
+ };
417
+ pointerdownTarget = target;
418
+ }
367
419
  guardedSetPointerCapture({ event: e, element: target });
368
420
  resetListeners();
369
421
  cancelPointerup = useEventListener(document, "pointerup", onPointerup);
@@ -382,23 +434,42 @@ export function useTrayGesture(args) {
382
434
  );
383
435
  cancelTouchend = isIOS() || isAndroid() ? useEventListener(document, "touchend", onTouchend) : void 0;
384
436
  cancelTouchcancel = isIOS() || isAndroid() ? useEventListener(document, "touchcancel", onTouchend) : void 0;
385
- onPointermove(e);
437
+ if (!pending) {
438
+ onPointermove(e);
439
+ }
386
440
  }
387
441
  function onTouchstart(side, e) {
388
442
  if (toValue(preventEdgeNavigation)) {
389
443
  cancelEdgeNavigation({ event: e });
390
444
  }
391
- if (!isAndroid() || !canBegin(side)) {
445
+ const sides = draggableSides(side);
446
+ if (!isAndroid() || !canStart() || !sides.length) {
392
447
  return;
393
448
  }
394
449
  const firstTouch = e.touches[0];
395
450
  if (!firstTouch) {
396
451
  return;
397
452
  }
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);
453
+ const target = e.target instanceof Element ? e.target : null;
454
+ const only = sides.length === 1 ? sides[0] : void 0;
455
+ if (only) {
456
+ e.stopImmediatePropagation();
457
+ e.stopPropagation();
458
+ beginDrag(
459
+ only,
460
+ isVertical(only) ? firstTouch.clientY : firstTouch.clientX,
461
+ target
462
+ );
463
+ } else {
464
+ pending = {
465
+ sides,
466
+ x: firstTouch.clientX,
467
+ y: firstTouch.clientY,
468
+ target,
469
+ pressedAt: /* @__PURE__ */ new Date()
470
+ };
471
+ pointerdownTarget = target;
472
+ }
402
473
  cancelTouchmove?.();
403
474
  cancelTouchmove = useEventListener(document, "touchmove", onTouchmove, {
404
475
  passive: false
@@ -409,7 +480,9 @@ export function useTrayGesture(args) {
409
480
  });
410
481
  cancelTouchcancel?.();
411
482
  cancelTouchcancel = useEventListener(document, "touchcancel", onTouchend);
412
- onTouchmove(e);
483
+ if (!pending) {
484
+ onTouchmove(e);
485
+ }
413
486
  }
414
487
  watch(disabled, (value) => {
415
488
  if (value) {
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.3.0",
4
+ "version": "1.4.0",
5
5
  "contributors": [
6
6
  {
7
7
  "name": "Robin Scholz",