@maas/vue-equipment 1.3.0 → 1.4.1

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.4.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,51 @@ 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 isOpen(side) {
71
+ return state.dragged[side] > dragBounds(side).min;
72
+ }
73
+ function resolveSide(sides, dx, dy) {
74
+ const horizontal = sides.filter((side) => !isVertical(side));
75
+ const vertical = sides.filter(isVertical);
76
+ const alongX = horizontal.length > 0 && (!vertical.length || Math.abs(dx) >= Math.abs(dy));
77
+ const delta = alongX ? dx : dy;
78
+ if (delta === 0) {
79
+ return void 0;
80
+ }
81
+ const candidates = alongX ? horizontal : vertical;
82
+ const [opens, closes] = alongX ? delta > 0 ? ["left", "right"] : ["right", "left"] : delta > 0 ? ["top", "bottom"] : ["bottom", "top"];
83
+ if (candidates.includes(closes) && isOpen(closes)) {
84
+ return closes;
85
+ }
86
+ return candidates.includes(opens) ? opens : candidates[0];
87
+ }
88
+ function resolvePending(x, y) {
89
+ if (!pending) {
90
+ return void 0;
91
+ }
92
+ if (!canStart()) {
93
+ pending = void 0;
94
+ resetListeners();
95
+ return void 0;
96
+ }
97
+ const side = resolveSide(pending.sides, x - pending.x, y - pending.y);
98
+ if (!side) {
99
+ return void 0;
100
+ }
101
+ const { x: pressX, y: pressY, target, pressedAt } = pending;
102
+ pending = void 0;
103
+ beginDrag(side, isVertical(side) ? pressY : pressX, target);
104
+ state.dragStart = pressedAt;
105
+ return side;
62
106
  }
63
107
  function dragBounds(side) {
64
108
  const points = mappedSnapPoints(side);
@@ -173,11 +217,11 @@ export function useTrayGesture(args) {
173
217
  function emitWillSnapTo(side) {
174
218
  const target = settleTarget(side);
175
219
  const isPoint = mappedSnapPoints(side).includes(target);
176
- const pending = !isPoint && rangeAt(side, target)?.range || target;
177
- if (pending === lastPendingTarget) {
220
+ const pending2 = !isPoint && rangeAt(side, target)?.range || target;
221
+ if (pending2 === lastPendingTarget) {
178
222
  return;
179
223
  }
180
- lastPendingTarget = pending;
224
+ lastPendingTarget = pending2;
181
225
  const snapPoint = snapPointAt(side, target);
182
226
  if (snapPoint === void 0) {
183
227
  return;
@@ -204,6 +248,7 @@ export function useTrayGesture(args) {
204
248
  }
205
249
  function resetDragState() {
206
250
  const side = state.draggingSide;
251
+ pending = void 0;
207
252
  if (side) {
208
253
  state.lastDragged[side] = state.snapped[side];
209
254
  }
@@ -226,7 +271,7 @@ export function useTrayGesture(args) {
226
271
  if (e.isTrusted && !e.isPrimary) {
227
272
  return;
228
273
  }
229
- const side = state.draggingSide;
274
+ const side = state.draggingSide ?? resolvePending(e.clientX, e.clientY);
230
275
  if (!side) {
231
276
  return;
232
277
  }
@@ -269,14 +314,14 @@ export function useTrayGesture(args) {
269
314
  guardedReleasePointerCapture({ event: e, element: pointerdownTarget });
270
315
  }
271
316
  function onTouchmove(e) {
272
- const side = state.draggingSide;
273
- if (!side) {
274
- return;
275
- }
276
317
  const firstTouch = e.touches[0];
277
318
  if (!firstTouch) {
278
319
  return;
279
320
  }
321
+ const side = state.draggingSide ?? resolvePending(firstTouch.clientX, firstTouch.clientY);
322
+ if (!side) {
323
+ return;
324
+ }
280
325
  e.stopImmediatePropagation();
281
326
  e.stopPropagation();
282
327
  if (hasDragged.value) {
@@ -355,15 +400,28 @@ export function useTrayGesture(args) {
355
400
  interpolateDragged({ side, to: state.snapped[side] });
356
401
  resetDragState();
357
402
  }
403
+ pending = void 0;
358
404
  resetListeners();
359
405
  }
360
406
  function onPointerdown(side, e) {
361
- if (!canBegin(side)) {
407
+ const sides = draggableSides(side);
408
+ if (!canStart() || !sides.length) {
362
409
  return;
363
410
  }
364
- const coord = isVertical(side) ? e.clientY : e.clientX;
365
411
  const target = e.target instanceof Element ? e.target : null;
366
- beginDrag(side, coord, target);
412
+ const only = sides.length === 1 ? sides[0] : void 0;
413
+ if (only) {
414
+ beginDrag(only, isVertical(only) ? e.clientY : e.clientX, target);
415
+ } else {
416
+ pending = {
417
+ sides,
418
+ x: e.clientX,
419
+ y: e.clientY,
420
+ target,
421
+ pressedAt: /* @__PURE__ */ new Date()
422
+ };
423
+ pointerdownTarget = target;
424
+ }
367
425
  guardedSetPointerCapture({ event: e, element: target });
368
426
  resetListeners();
369
427
  cancelPointerup = useEventListener(document, "pointerup", onPointerup);
@@ -382,23 +440,42 @@ export function useTrayGesture(args) {
382
440
  );
383
441
  cancelTouchend = isIOS() || isAndroid() ? useEventListener(document, "touchend", onTouchend) : void 0;
384
442
  cancelTouchcancel = isIOS() || isAndroid() ? useEventListener(document, "touchcancel", onTouchend) : void 0;
385
- onPointermove(e);
443
+ if (!pending) {
444
+ onPointermove(e);
445
+ }
386
446
  }
387
447
  function onTouchstart(side, e) {
388
448
  if (toValue(preventEdgeNavigation)) {
389
449
  cancelEdgeNavigation({ event: e });
390
450
  }
391
- if (!isAndroid() || !canBegin(side)) {
451
+ const sides = draggableSides(side);
452
+ if (!isAndroid() || !canStart() || !sides.length) {
392
453
  return;
393
454
  }
394
455
  const firstTouch = e.touches[0];
395
456
  if (!firstTouch) {
396
457
  return;
397
458
  }
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);
459
+ const target = e.target instanceof Element ? e.target : null;
460
+ const only = sides.length === 1 ? sides[0] : void 0;
461
+ if (only) {
462
+ e.stopImmediatePropagation();
463
+ e.stopPropagation();
464
+ beginDrag(
465
+ only,
466
+ isVertical(only) ? firstTouch.clientY : firstTouch.clientX,
467
+ target
468
+ );
469
+ } else {
470
+ pending = {
471
+ sides,
472
+ x: firstTouch.clientX,
473
+ y: firstTouch.clientY,
474
+ target,
475
+ pressedAt: /* @__PURE__ */ new Date()
476
+ };
477
+ pointerdownTarget = target;
478
+ }
402
479
  cancelTouchmove?.();
403
480
  cancelTouchmove = useEventListener(document, "touchmove", onTouchmove, {
404
481
  passive: false
@@ -409,7 +486,9 @@ export function useTrayGesture(args) {
409
486
  });
410
487
  cancelTouchcancel?.();
411
488
  cancelTouchcancel = useEventListener(document, "touchcancel", onTouchend);
412
- onTouchmove(e);
489
+ if (!pending) {
490
+ onTouchmove(e);
491
+ }
413
492
  }
414
493
  watch(disabled, (value) => {
415
494
  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.1",
5
5
  "contributors": [
6
6
  {
7
7
  "name": "Robin Scholz",