@maas/vue-equipment 0.30.2 → 0.30.4

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 (91) hide show
  1. package/dist/nuxt/module.json +1 -1
  2. package/dist/plugins/MagicAutoSize/src/components/MagicAutoSize.vue +1 -0
  3. package/dist/plugins/MagicAutoSize/src/components/MagicAutoSize.vue.d.ts +6 -4
  4. package/dist/plugins/MagicCommand/src/components/MagicCommandBody.vue.d.ts +4 -2
  5. package/dist/plugins/MagicCommand/src/components/MagicCommandDrawer.vue.d.ts +4 -2
  6. package/dist/plugins/MagicCommand/src/components/MagicCommandFooter.vue.d.ts +4 -2
  7. package/dist/plugins/MagicCommand/src/components/MagicCommandGroup.vue.d.ts +4 -2
  8. package/dist/plugins/MagicCommand/src/components/MagicCommandHead.vue.d.ts +4 -2
  9. package/dist/plugins/MagicCommand/src/components/MagicCommandItem.vue +2 -2
  10. package/dist/plugins/MagicCommand/src/components/MagicCommandItem.vue.d.ts +8 -6
  11. package/dist/plugins/MagicCommand/src/components/MagicCommandModal.vue.d.ts +4 -2
  12. package/dist/plugins/MagicCommand/src/components/MagicCommandProvider.vue.d.ts +6 -4
  13. package/dist/plugins/MagicCommand/src/components/MagicCommandView.vue +1 -1
  14. package/dist/plugins/MagicCommand/src/components/MagicCommandView.vue.d.ts +6 -4
  15. package/dist/plugins/MagicCommand/src/composables/private/useCommandItem.mjs +1 -2
  16. package/dist/plugins/MagicCommand/src/composables/private/useCommandView.mjs +1 -2
  17. package/dist/plugins/MagicCookie/src/components/MagicCookie.vue.d.ts +9 -7
  18. package/dist/plugins/MagicCookie/src/composables/private/useCookieApi.d.ts +3 -3
  19. package/dist/plugins/MagicDraggable/src/components/MagicDraggable.vue.d.ts +6 -4
  20. package/dist/plugins/MagicDraggable/src/composables/private/useDraggableScrollLock.mjs +1 -2
  21. package/dist/plugins/MagicDraggable/src/composables/private/useDraggableSnap.d.ts +2 -2
  22. package/dist/plugins/MagicDraggable/src/composables/private/useDraggableState.d.ts +1 -1
  23. package/dist/plugins/MagicDraggable/src/composables/private/useDraggableState.mjs +1 -2
  24. package/dist/plugins/MagicDrawer/src/components/MagicDrawer.vue.d.ts +7 -5
  25. package/dist/plugins/MagicDrawer/src/composables/private/useDrawerDOM.mjs +1 -2
  26. package/dist/plugins/MagicDrawer/src/composables/private/useDrawerDrag.mjs +4 -8
  27. package/dist/plugins/MagicDrawer/src/composables/private/useDrawerSnap.mjs +14 -28
  28. package/dist/plugins/MagicDrawer/src/composables/private/useDrawerState.d.ts +1 -64
  29. package/dist/plugins/MagicDrawer/src/composables/private/useDrawerState.mjs +1 -2
  30. package/dist/plugins/MagicDrawer/src/composables/private/useDrawerUtils.mjs +8 -16
  31. package/dist/plugins/MagicEmitter/src/composables/useMagicEmitter.d.ts +30 -30
  32. package/dist/plugins/MagicMarquee/src/components/MagicMarquee.vue.d.ts +7 -5
  33. package/dist/plugins/MagicMenu/src/components/MagicMenuChannel.vue +21 -15
  34. package/dist/plugins/MagicMenu/src/components/MagicMenuChannel.vue.d.ts +4 -2
  35. package/dist/plugins/MagicMenu/src/components/MagicMenuContent.vue +57 -36
  36. package/dist/plugins/MagicMenu/src/components/MagicMenuContent.vue.d.ts +7 -5
  37. package/dist/plugins/MagicMenu/src/components/MagicMenuFloat.vue +7 -7
  38. package/dist/plugins/MagicMenu/src/components/MagicMenuFloat.vue.d.ts +4 -2
  39. package/dist/plugins/MagicMenu/src/components/MagicMenuItem.vue +0 -1
  40. package/dist/plugins/MagicMenu/src/components/MagicMenuItem.vue.d.ts +8 -6
  41. package/dist/plugins/MagicMenu/src/components/MagicMenuProvider.vue +1 -1
  42. package/dist/plugins/MagicMenu/src/components/MagicMenuProvider.vue.d.ts +4 -2
  43. package/dist/plugins/MagicMenu/src/components/MagicMenuRemote.vue +11 -7
  44. package/dist/plugins/MagicMenu/src/components/MagicMenuRemote.vue.d.ts +4 -2
  45. package/dist/plugins/MagicMenu/src/components/MagicMenuTrigger.vue +4 -4
  46. package/dist/plugins/MagicMenu/src/components/MagicMenuTrigger.vue.d.ts +4 -2
  47. package/dist/plugins/MagicMenu/src/components/MagicMenuView.vue +0 -1
  48. package/dist/plugins/MagicMenu/src/components/MagicMenuView.vue.d.ts +4 -2
  49. package/dist/plugins/MagicMenu/src/composables/private/useMenuChannel.mjs +1 -8
  50. package/dist/plugins/MagicMenu/src/composables/private/useMenuCursor.d.ts +2 -11
  51. package/dist/plugins/MagicMenu/src/composables/private/useMenuCursor.mjs +66 -86
  52. package/dist/plugins/MagicMenu/src/composables/private/useMenuDOM.mjs +1 -2
  53. package/dist/plugins/MagicMenu/src/composables/private/useMenuItem.mjs +1 -2
  54. package/dist/plugins/MagicMenu/src/composables/private/useMenuKeyListener.mjs +2 -4
  55. package/dist/plugins/MagicMenu/src/composables/private/useMenuTrigger.mjs +16 -4
  56. package/dist/plugins/MagicMenu/src/composables/private/useMenuView.d.ts +2 -2
  57. package/dist/plugins/MagicMenu/src/composables/private/useMenuView.mjs +53 -13
  58. package/dist/plugins/MagicMenu/src/composables/useMagicMenu.d.ts +2 -2
  59. package/dist/plugins/MagicMenu/src/types/index.d.ts +11 -4
  60. package/dist/plugins/MagicMenu/src/utils/defaultOptions.mjs +6 -3
  61. package/dist/plugins/MagicMenu/src/utils/modeTransitions.d.ts +6 -0
  62. package/dist/plugins/MagicMenu/src/utils/modeTransitions.mjs +7 -0
  63. package/dist/plugins/MagicModal/src/components/MagicModal.vue.d.ts +7 -5
  64. package/dist/plugins/MagicModal/src/composables/private/useModalDOM.mjs +1 -2
  65. package/dist/plugins/MagicNoise/src/composables/private/useNoiseApi.mjs +3 -6
  66. package/dist/plugins/MagicPlayer/src/components/MagicAudioPlayer.vue.d.ts +6 -4
  67. package/dist/plugins/MagicPlayer/src/components/MagicAudioPlayerControls.vue.d.ts +4 -2
  68. package/dist/plugins/MagicPlayer/src/components/MagicPlayer.vue.d.ts +7 -5
  69. package/dist/plugins/MagicPlayer/src/components/MagicPlayerControls.vue.d.ts +10 -8
  70. package/dist/plugins/MagicPlayer/src/components/MagicPlayerDisplayTime.vue.d.ts +1 -1
  71. package/dist/plugins/MagicPlayer/src/components/MagicPlayerOverlay.vue.d.ts +4 -2
  72. package/dist/plugins/MagicPlayer/src/components/MagicPlayerPoster.vue.d.ts +4 -2
  73. package/dist/plugins/MagicPlayer/src/composables/private/usePlayerAudioApi.mjs +1 -2
  74. package/dist/plugins/MagicPlayer/src/composables/private/usePlayerControlsApi.mjs +5 -10
  75. package/dist/plugins/MagicPlayer/src/composables/private/usePlayerMediaApi.mjs +8 -16
  76. package/dist/plugins/MagicPlayer/src/composables/private/usePlayerRuntime.mjs +3 -6
  77. package/dist/plugins/MagicPlayer/src/composables/private/usePlayerStateEmitter.d.ts +3 -3
  78. package/dist/plugins/MagicPlayer/src/composables/private/usePlayerVideoApi.mjs +2 -4
  79. package/dist/plugins/MagicScroll/src/components/MagicScrollCollision.vue.d.ts +4 -2
  80. package/dist/plugins/MagicScroll/src/components/MagicScrollMotion.vue.d.ts +6 -4
  81. package/dist/plugins/MagicScroll/src/components/MagicScrollProvider.vue.d.ts +10 -8
  82. package/dist/plugins/MagicScroll/src/components/MagicScrollScene.vue.d.ts +8 -6
  83. package/dist/plugins/MagicScroll/src/components/MagicScrollTransform.vue.d.ts +6 -4
  84. package/dist/plugins/MagicScroll/src/composables/private/useCollisionDetect.mjs +4 -8
  85. package/dist/plugins/MagicScroll/src/composables/private/useScrollApi.mjs +2 -4
  86. package/dist/plugins/MagicScroll/src/symbols/index.d.ts +2 -18
  87. package/dist/plugins/MagicToast/src/components/MagicToastComponent.vue.d.ts +6 -4
  88. package/dist/plugins/MagicToast/src/composables/private/useToastApi.mjs +1 -2
  89. package/dist/plugins/MagicToast/src/composables/private/useToastStore.d.ts +1 -1
  90. package/dist/plugins/MagicToast/src/composables/useMagicToast.mjs +1 -2
  91. package/package.json +2 -1
@@ -3,7 +3,7 @@
3
3
  class="magic-menu-remote"
4
4
  :class="{ '-active': channel?.active, '-disabled': disabled }"
5
5
  :data-id="`${channelId}-remote`"
6
- @click="onClick"
6
+ @pointerdown="onClick"
7
7
  @mouseenter="onMouseenter"
8
8
  >
9
9
  <slot :is-active="view?.active" :is-disabled="disabled" />
@@ -49,6 +49,7 @@ if (!props.channelId) {
49
49
  }
50
50
 
51
51
  const mappedChannelId = computed(() => `magic-menu-channel-${props.channelId}`)
52
+
52
53
  const mappedTrigger = computed<Interaction[]>(
53
54
  () => props.trigger ?? ['mouseenter']
54
55
  )
@@ -60,7 +61,6 @@ const { initializeChannel, deleteChannel } = useMenuChannel({
60
61
  instanceId,
61
62
  viewId,
62
63
  })
63
- let channel = initializeChannel({ id: mappedChannelId.value })
64
64
 
65
65
  const { onClick, onMouseenter } = useMenuRemote({
66
66
  viewId,
@@ -69,16 +69,20 @@ const { onClick, onMouseenter } = useMenuRemote({
69
69
  mappedTrigger,
70
70
  })
71
71
 
72
+ let channel = initializeChannel({ id: mappedChannelId.value })
73
+
72
74
  watch(
73
75
  () => view?.active,
74
- () => {
75
- // Reset if parent view changes
76
- deleteChannel(mappedChannelId.value)
77
- channel = initializeChannel({ id: mappedChannelId.value })
76
+ (value) => {
77
+ // Reset if parent view is inactive
78
+ if (!value) {
79
+ deleteChannel(mappedChannelId.value)
80
+ channel = initializeChannel({ id: mappedChannelId.value })
81
+ }
78
82
  }
79
83
  )
80
84
  </script>
81
85
 
82
86
  <style>
83
- .magic-menu-remote{cursor:var(--magic-menu-remote-cursor,pointer)}
87
+ .magic-menu-remote{cursor:var(--magic-menu-remote-cursor,pointer)}.magic-menu-remote.-disabled{pointer-events:none}
84
88
  </style>
@@ -6,12 +6,14 @@ interface MagicMenuRemoteProps {
6
6
  disabled?: boolean;
7
7
  trigger?: Interaction[];
8
8
  }
9
- declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__VLS_TypePropsToOption<MagicMenuRemoteProps>, {}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<__VLS_TypePropsToOption<MagicMenuRemoteProps>>>, {}, {}>, {
9
+ declare function __VLS_template(): {
10
10
  default?(_: {
11
11
  isActive: boolean | undefined;
12
12
  isDisabled: boolean | undefined;
13
13
  }): any;
14
- }>;
14
+ };
15
+ declare const __VLS_component: import("vue").DefineComponent<__VLS_TypePropsToOption<MagicMenuRemoteProps>, {}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<__VLS_TypePropsToOption<MagicMenuRemoteProps>>>, {}, {}>;
16
+ declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, ReturnType<typeof __VLS_template>>;
15
17
  export default _default;
16
18
  type __VLS_WithTemplateSlots<T, S> = T & {
17
19
  new (): {
@@ -5,7 +5,7 @@
5
5
  :class="{ '-active': view?.active, '-disabled': mappedDisabled }"
6
6
  :data-id="`${viewId}-trigger`"
7
7
  :tabindex="mappedTabindex"
8
- @click="onClick"
8
+ @pointerdown="onClick"
9
9
  @contextmenu="onClick"
10
10
  @mouseenter="onMouseenter"
11
11
  >
@@ -14,7 +14,7 @@
14
14
  </template>
15
15
 
16
16
  <script lang="ts" setup>
17
- import { computed, inject, onBeforeUnmount, ref, toValue, watch } from 'vue'
17
+ import { computed, inject, ref, toValue, watch } from 'vue'
18
18
  import { useMenuState } from '../composables/private/useMenuState'
19
19
  import { useMenuView } from '../composables/private/useMenuView'
20
20
  import { useMenuItem } from '../composables/private/useMenuItem'
@@ -58,7 +58,7 @@ const state = initializeState()
58
58
  const { getItem } = useMenuItem({ instanceId, viewId })
59
59
  const item = getItem(itemId ?? '')
60
60
 
61
- const mappedDisabled = computed(() => props.disabled ?? item?.disabled)
61
+ const mappedDisabled = computed(() => props.disabled ?? item?.disabled ?? false)
62
62
 
63
63
  const mappedTrigger = computed<Interaction[]>(() => {
64
64
  if (props.trigger?.length) {
@@ -112,5 +112,5 @@ onKeyStroke('Enter', onEnter)
112
112
  </script>
113
113
 
114
114
  <style>
115
- .magic-menu-trigger{cursor:var(--magic-menu-trigger-cursor,pointer)}
115
+ .magic-menu-trigger{cursor:var(--magic-menu-trigger-cursor,pointer)}.magic-menu-trigger.-disabled{pointer-events:none}
116
116
  </style>
@@ -3,12 +3,14 @@ interface MagicMenuTriggerProps {
3
3
  disabled?: boolean;
4
4
  trigger?: Interaction[];
5
5
  }
6
- declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__VLS_TypePropsToOption<MagicMenuTriggerProps>, {}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<__VLS_TypePropsToOption<MagicMenuTriggerProps>>>, {}, {}>, {
6
+ declare function __VLS_template(): {
7
7
  default?(_: {
8
8
  isActive: boolean | undefined;
9
9
  isDisabled: boolean;
10
10
  }): any;
11
- }>;
11
+ };
12
+ declare const __VLS_component: import("vue").DefineComponent<__VLS_TypePropsToOption<MagicMenuTriggerProps>, {}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<__VLS_TypePropsToOption<MagicMenuTriggerProps>>>, {}, {}>;
13
+ declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, ReturnType<typeof __VLS_template>>;
12
14
  export default _default;
13
15
  type __VLS_WithTemplateSlots<T, S> = T & {
14
16
  new (): {
@@ -8,7 +8,6 @@
8
8
  import { computed, inject, onBeforeUnmount, provide } from 'vue'
9
9
  import { uuid } from '@maas/vue-equipment/utils'
10
10
  import { useMenuView } from '../composables/private/useMenuView'
11
-
12
11
  import {
13
12
  MagicMenuInstanceId,
14
13
  MagicMenuViewId,
@@ -3,9 +3,11 @@ interface MagicMenuViewProps {
3
3
  id?: string;
4
4
  placement?: Placement;
5
5
  }
6
- declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__VLS_TypePropsToOption<MagicMenuViewProps>, {}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<__VLS_TypePropsToOption<MagicMenuViewProps>>>, {}, {}>, {
6
+ declare function __VLS_template(): {
7
7
  default?(_: {}): any;
8
- }>;
8
+ };
9
+ declare const __VLS_component: import("vue").DefineComponent<__VLS_TypePropsToOption<MagicMenuViewProps>, {}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<__VLS_TypePropsToOption<MagicMenuViewProps>>>, {}, {}>;
10
+ declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, ReturnType<typeof __VLS_template>>;
9
11
  export default _default;
10
12
  type __VLS_WithTemplateSlots<T, S> = T & {
11
13
  new (): {
@@ -1,10 +1,7 @@
1
1
  import { reactive } from "vue";
2
2
  import { useMenuView } from "./useMenuView.mjs";
3
- import { useMenuState } from "./useMenuState.mjs";
4
3
  export function useMenuChannel(args) {
5
4
  const { instanceId, viewId } = args;
6
- const { initializeState } = useMenuState(instanceId);
7
- const state = initializeState();
8
5
  const { getView } = useMenuView(instanceId);
9
6
  const view = getView(viewId);
10
7
  function createChannel(args2) {
@@ -35,8 +32,7 @@ export function useMenuChannel(args) {
35
32
  return instance;
36
33
  }
37
34
  function deleteChannel(id) {
38
- if (!view?.channels)
39
- return;
35
+ if (!view?.channels) return;
40
36
  view.channels = view.channels.filter((x) => x.id !== id);
41
37
  }
42
38
  function getChannel(id) {
@@ -49,9 +45,6 @@ export function useMenuChannel(args) {
49
45
  if (instance) {
50
46
  instance.active = true;
51
47
  unselectSiblings(id);
52
- if (view) {
53
- state.input.view = view.id;
54
- }
55
48
  }
56
49
  }
57
50
  function unselectChannel(id) {
@@ -1,13 +1,5 @@
1
- import { type MaybeRef } from 'vue';
2
- import type { Coordinates } from '../../types.js';
3
- import type { Placement } from '@floating-ui/vue';
4
- interface UseMenuCursorArgs {
5
- from: MaybeRef<HTMLElement | undefined>;
6
- to: MaybeRef<HTMLElement | undefined>;
7
- placement: MaybeRef<Placement>;
8
- click: MaybeRef<Coordinates | undefined>;
9
- }
10
- export declare function useMenuCursor(args: UseMenuCursorArgs): {
1
+ import type { MenuView } from '../../types.js';
2
+ export declare function useMenuCursor(view: MenuView, debug?: boolean): {
11
3
  coords: import("vue").Ref<{
12
4
  x: number;
13
5
  y: number;
@@ -18,4 +10,3 @@ export declare function useMenuCursor(args: UseMenuCursorArgs): {
18
10
  initialize: () => void;
19
11
  destroy: () => void;
20
12
  };
21
- export {};
@@ -1,14 +1,7 @@
1
- import { ref, toValue } from "vue";
2
- import {
3
- useEventListener,
4
- useElementBounding,
5
- useResizeObserver,
6
- usePointer
7
- } from "@vueuse/core";
8
- export function useMenuCursor(args) {
9
- const cancelListener = ref(new AbortController());
10
- const { x, y } = usePointer();
11
- const { from, to, placement, click } = args;
1
+ import { ref } from "vue";
2
+ import { useEventListener } from "@vueuse/core";
3
+ export function useMenuCursor(view, debug = false) {
4
+ let cancelListener = new AbortController();
12
5
  const coords = ref([
13
6
  { x: 0, y: 0 },
14
7
  { x: 0, y: 0 },
@@ -19,7 +12,7 @@ export function useMenuCursor(args) {
19
12
  const isInsideTriangle = ref(false);
20
13
  function extendTriangle(vertices, pixelAmount) {
21
14
  const [a, b, c] = vertices;
22
- switch (toValue(placement)) {
15
+ switch (view?.placement) {
23
16
  case "bottom":
24
17
  case "bottom-start":
25
18
  case "bottom-end":
@@ -63,11 +56,10 @@ export function useMenuCursor(args) {
63
56
  }
64
57
  break;
65
58
  }
66
- coords.value = [a, b, c];
67
59
  return [a, b, c];
68
60
  }
69
- function isPointInTriangle(args2) {
70
- const { p, a, b, c } = args2;
61
+ function isPointInTriangle(args) {
62
+ const { p, a, b, c } = args;
71
63
  const v0 = { x: c.x - a.x, y: c.y - a.y };
72
64
  const v1 = { x: b.x - a.x, y: b.y - a.y };
73
65
  const v2 = { x: p.x - a.x, y: p.y - a.y };
@@ -81,37 +73,29 @@ export function useMenuCursor(args) {
81
73
  const v = (dot00 * dot12 - dot01 * dot02) * invDenom;
82
74
  return u >= 0 && v >= 0 && u + v <= 1;
83
75
  }
84
- function isPointInRectangle(args2) {
85
- const { p, top, left, bottom, right } = args2;
76
+ function isPointInRectangle(args) {
77
+ const { p, top, left, bottom, right } = args;
86
78
  return p.x >= left && p.x <= right && p.y >= top && p.y <= bottom;
87
79
  }
88
- function triangleOverlap(cursor, from2, to2) {
89
- const fromBounding = useElementBounding(from2, {
90
- windowScroll: false,
91
- windowResize: false
92
- });
93
- const toBounding = useElementBounding(to2, {
94
- windowScroll: false,
95
- windowResize: false
96
- });
80
+ function getTriangle(fromBounding, toBounding) {
97
81
  const { top, left, bottom, right } = toBounding;
98
- const centerPoint = toValue(click) ?? {
99
- x: (fromBounding.left.value + fromBounding.right.value) / 2,
100
- y: (fromBounding.top.value + fromBounding.bottom.value) / 2
82
+ const centerPoint = view.state.clicked ? view.state.clicked : {
83
+ x: (fromBounding.left + fromBounding.right) / 2,
84
+ y: (fromBounding.top + fromBounding.bottom) / 2
101
85
  };
102
86
  const sidePoints = [];
103
- switch (toValue(placement)) {
87
+ switch (view.placement) {
104
88
  case "top":
105
89
  case "top-start":
106
90
  case "top-end":
107
91
  case "bottom":
108
92
  case "bottom-start":
109
93
  case "bottom-end":
110
- const topDist = Math.abs(top.value - centerPoint.y);
111
- const bottomDist = Math.abs(bottom.value - centerPoint.y);
94
+ const topDist = Math.abs(top - centerPoint.y);
95
+ const bottomDist = Math.abs(bottom - centerPoint.y);
112
96
  const mappedY = topDist < bottomDist ? top : bottom;
113
- sidePoints.push({ x: left.value, y: mappedY.value });
114
- sidePoints.push({ x: right.value, y: mappedY.value });
97
+ sidePoints.push({ x: left, y: mappedY });
98
+ sidePoints.push({ x: right, y: mappedY });
115
99
  break;
116
100
  case "right":
117
101
  case "right-start":
@@ -119,17 +103,21 @@ export function useMenuCursor(args) {
119
103
  case "left":
120
104
  case "left-start":
121
105
  case "left-end":
122
- const rightDist = Math.abs(right.value - centerPoint.x);
123
- const leftDist = Math.abs(left.value - centerPoint.x);
106
+ const rightDist = Math.abs(right - centerPoint.x);
107
+ const leftDist = Math.abs(left - centerPoint.x);
124
108
  const mappedX = rightDist < leftDist ? right : left;
125
- sidePoints.push({ x: mappedX.value, y: top.value });
126
- sidePoints.push({ x: mappedX.value, y: bottom.value });
109
+ sidePoints.push({ x: mappedX, y: top });
110
+ sidePoints.push({ x: mappedX, y: bottom });
127
111
  break;
128
112
  }
129
113
  const [a, b, c] = extendTriangle(
130
114
  [centerPoint, sidePoints[0], sidePoints[1]],
131
115
  16
132
116
  );
117
+ return [a, b, c];
118
+ }
119
+ function triangleOverlap(cursor, fromBounding, toBounding) {
120
+ const [a, b, c] = getTriangle(fromBounding, toBounding);
133
121
  return isPointInTriangle({
134
122
  p: cursor,
135
123
  a,
@@ -137,69 +125,61 @@ export function useMenuCursor(args) {
137
125
  c
138
126
  });
139
127
  }
140
- function elementOverlap(cursor, element) {
141
- const { top, left, bottom, right } = useElementBounding(element, {
142
- windowScroll: false,
143
- windowResize: false
144
- });
128
+ function elementOverlap(cursor, bounding) {
129
+ const { top, left, bottom, right } = bounding;
145
130
  return isPointInRectangle({
146
131
  p: cursor,
147
- top: top.value,
148
- left: left.value,
149
- bottom: bottom.value,
150
- right: right.value
132
+ top,
133
+ left,
134
+ bottom,
135
+ right
151
136
  });
152
137
  }
153
138
  function onMousemove(e) {
154
- const cursor = { x: e.clientX, y: e.clientY };
155
- isInsideFrom.value = elementOverlap(cursor, from);
156
- isInsideTo.value = elementOverlap(cursor, to);
157
- isInsideTriangle.value = triangleOverlap(cursor, from, to);
158
- }
159
- function fromMouseenter() {
160
- isInsideFrom.value = true;
161
- }
162
- function fromMouseleave() {
163
- isInsideFrom.value = false;
164
- }
165
- function toMouseenter() {
166
- isInsideTo.value = true;
167
- }
168
- function toMouseleave(e) {
169
- isInsideTo.value = false;
170
- }
171
- function onResize() {
172
- const cursor = { x: x.value, y: y.value };
173
- isInsideFrom.value = elementOverlap(cursor, from);
174
- isInsideTo.value = elementOverlap(cursor, to);
175
- isInsideTriangle.value = triangleOverlap(cursor, from, to);
139
+ const from = Array.from(
140
+ document.querySelectorAll(`[data-id="${view?.id}-trigger"]`)
141
+ );
142
+ const to = document.querySelector(
143
+ `[data-id="${view?.id}-content"] .magic-menu-content__inner`
144
+ );
145
+ if (from.length && to) {
146
+ const cursor = { x: e.clientX, y: e.clientY };
147
+ const toBounding = to.getBoundingClientRect();
148
+ isInsideTo.value = elementOverlap(cursor, toBounding);
149
+ isInsideFrom.value = from.some((trigger) => {
150
+ const fromBounding = trigger.getBoundingClientRect();
151
+ const overlap = elementOverlap(cursor, fromBounding);
152
+ return overlap;
153
+ });
154
+ isInsideTriangle.value = from.some((trigger) => {
155
+ const fromBounding = trigger.getBoundingClientRect();
156
+ const overlap = triangleOverlap(cursor, fromBounding, toBounding);
157
+ return overlap;
158
+ });
159
+ if (debug) {
160
+ const allCoords = [];
161
+ from.forEach((trigger) => {
162
+ const fromBounding = trigger.getBoundingClientRect();
163
+ const [a, b, c] = getTriangle(fromBounding, toBounding);
164
+ allCoords.push(a, b, c);
165
+ });
166
+ coords.value = allCoords;
167
+ }
168
+ }
176
169
  }
177
170
  function initialize() {
178
- cancelListener.value.abort();
179
- cancelListener.value = new AbortController();
180
- useEventListener(from, "mouseenter", fromMouseenter, {
181
- signal: cancelListener.value.signal
182
- });
183
- useEventListener(from, "mouseleave", fromMouseleave, {
184
- signal: cancelListener.value.signal
185
- });
186
- useEventListener(to, "mouseenter", toMouseenter, {
187
- signal: cancelListener.value.signal
188
- });
189
- useEventListener(to, "mouseleave", toMouseleave, {
190
- signal: cancelListener.value.signal
191
- });
171
+ cancelListener.abort();
172
+ cancelListener = new AbortController();
192
173
  useEventListener(document, "mousemove", onMousemove, {
193
- signal: cancelListener.value.signal
174
+ signal: cancelListener.signal
194
175
  });
195
- useResizeObserver(to, onResize);
196
176
  }
197
177
  function destroy() {
198
178
  coords.value = [];
199
179
  isInsideFrom.value = false;
200
180
  isInsideTo.value = false;
201
181
  isInsideTriangle.value = false;
202
- cancelListener.value.abort();
182
+ cancelListener.abort();
203
183
  }
204
184
  return {
205
185
  coords,
@@ -11,8 +11,7 @@ export function useMenuDOM() {
11
11
  scrollLock.value = false;
12
12
  }
13
13
  function addScrollLockPadding() {
14
- if (typeof window === "undefined")
15
- return;
14
+ if (typeof window === "undefined") return;
16
15
  const exclude = new RegExp(/magic-menu?/);
17
16
  const scrollbarWidth = window.innerWidth - document.body.offsetWidth;
18
17
  document.body.style.setProperty("--scrollbar-width", `${scrollbarWidth}px`);
@@ -39,8 +39,7 @@ export function useMenuItem(args) {
39
39
  return instance;
40
40
  }
41
41
  function deleteItem(id) {
42
- if (!view?.items)
43
- return;
42
+ if (!view?.items) return;
44
43
  view.items = view.items.filter((x) => x.id !== id);
45
44
  }
46
45
  function getItem(id) {
@@ -94,8 +94,7 @@ export function useMenuKeyListener(instanceId) {
94
94
  }
95
95
  const viewId = state.input.view;
96
96
  const inputView = getView(viewId);
97
- if (!inputView)
98
- return;
97
+ if (!inputView) return;
99
98
  const enabledItems = getEnabledItems(inputView);
100
99
  const prevIndex = enabledItems.findIndex((item) => item.active) - 1;
101
100
  if (prevIndex >= 0) {
@@ -118,8 +117,7 @@ export function useMenuKeyListener(instanceId) {
118
117
  }
119
118
  const viewId = state.input.view;
120
119
  const inputView = getView(viewId);
121
- if (!inputView)
122
- return;
120
+ if (!inputView) return;
123
121
  const enabledItems = getEnabledItems(inputView);
124
122
  const nextIndex = enabledItems.findIndex((item) => item.active) + 1;
125
123
  if (nextIndex >= 0) {
@@ -15,7 +15,7 @@ export function useMenuTrigger(args) {
15
15
  selectView(viewId);
16
16
  state.active = true;
17
17
  if (view) {
18
- view.click = { x: e.clientX, y: e.clientY };
18
+ view.state.clicked = { x: e.clientX, y: e.clientY };
19
19
  }
20
20
  if (!itemId) {
21
21
  state.input.view = viewId;
@@ -38,11 +38,17 @@ export function useMenuTrigger(args) {
38
38
  }
39
39
  function onMouseenter() {
40
40
  if (mappedTrigger.value.includes("mouseenter") && !mappedDisabled.value && viewId && view) {
41
- if (mappedTrigger.value[0].includes("mouseenter")) {
41
+ if (mappedTrigger.value[0] === "mouseenter") {
42
42
  state.active = true;
43
43
  }
44
+ let delay = 0;
45
+ switch (state.options.mode) {
46
+ case "navigation":
47
+ delay = 200;
48
+ break;
49
+ }
44
50
  if (state.active) {
45
- selectView(viewId);
51
+ selectView(viewId, delay);
46
52
  if (!itemId) {
47
53
  state.input.view = viewId;
48
54
  }
@@ -51,10 +57,16 @@ export function useMenuTrigger(args) {
51
57
  }
52
58
  function onClick(e) {
53
59
  if (mappedTrigger.value.includes("click") && !mappedDisabled.value && e.button === 0 && viewId) {
60
+ let delay = 0;
61
+ switch (state.options.mode) {
62
+ case "navigation":
63
+ delay = 200;
64
+ break;
65
+ }
54
66
  switch (true) {
55
67
  case !state.active:
56
68
  state.active = true;
57
- selectView(viewId);
69
+ selectView(viewId, delay);
58
70
  if (!itemId) {
59
71
  state.input.view = viewId;
60
72
  }
@@ -12,8 +12,8 @@ export declare function useMenuView(instanceId: MaybeRef<string>): {
12
12
  getTopLevelView: () => MenuView | undefined;
13
13
  getNestedView: (itemId: string) => MenuView | undefined;
14
14
  getParentView: (id: string) => MenuView | undefined;
15
- selectView: (id: string) => void;
16
- unselectView: (id: string) => void;
15
+ selectView: (id: string, delayMs?: number) => Promise<void>;
16
+ unselectView: (id: string, delayMs?: number) => Promise<void>;
17
17
  unselectUnrelatedViews: (id: string) => void;
18
18
  unselectDescendingViews: (id: string) => void;
19
19
  unselectAllViews: () => void;
@@ -1,8 +1,4 @@
1
- import {
2
- reactive,
3
- computed,
4
- toValue
5
- } from "vue";
1
+ import { reactive, computed, toValue } from "vue";
6
2
  import { useMenuState } from "./useMenuState.mjs";
7
3
  export function useMenuView(instanceId) {
8
4
  const { initializeState } = useMenuState(instanceId);
@@ -23,7 +19,11 @@ export function useMenuView(instanceId) {
23
19
  active: false,
24
20
  items: [],
25
21
  channels: [],
26
- placement
22
+ placement,
23
+ state: {
24
+ selectAbortController: new AbortController(),
25
+ unselectAbortController: new AbortController()
26
+ }
27
27
  };
28
28
  return reactive(view);
29
29
  }
@@ -32,11 +32,19 @@ export function useMenuView(instanceId) {
32
32
  state.views = [...state.views, view];
33
33
  return view;
34
34
  }
35
+ function delay(ms, signal) {
36
+ return new Promise((resolve, reject) => {
37
+ const timer = setTimeout(resolve, ms);
38
+ signal.addEventListener("abort", () => {
39
+ clearTimeout(timer);
40
+ reject(new DOMException("Aborted", "AbortError"));
41
+ });
42
+ });
43
+ }
35
44
  function initializeView(args) {
36
45
  const { id } = args;
37
46
  let instance = getView(id);
38
- if (!instance)
39
- instance = addView(args);
47
+ if (!instance) instance = addView(args);
40
48
  return instance;
41
49
  }
42
50
  function deleteView(id) {
@@ -81,17 +89,49 @@ export function useMenuView(instanceId) {
81
89
  (view) => view.id !== id && !argView?.parent.views.includes(view.id)
82
90
  );
83
91
  }
84
- function selectView(id) {
92
+ async function selectView(id, delayMs = 0) {
85
93
  const instance = getView(id);
86
94
  if (instance) {
87
- instance.active = true;
88
- unselectUnrelatedViews(id);
95
+ if (instance.state.unselectAbortController) {
96
+ instance.state.unselectAbortController.abort();
97
+ }
98
+ const abortController = new AbortController();
99
+ instance.state.selectAbortController = abortController;
100
+ try {
101
+ await delay(delayMs, abortController.signal);
102
+ instance.active = true;
103
+ unselectUnrelatedViews(id);
104
+ } catch (err) {
105
+ if (err.name === "AbortError") {
106
+ console.log(
107
+ `selectView() was interrupted by a call to unselectView()`
108
+ );
109
+ } else {
110
+ throw err;
111
+ }
112
+ }
89
113
  }
90
114
  }
91
- function unselectView(id) {
115
+ async function unselectView(id, delayMs = 0) {
92
116
  const instance = getView(id);
93
117
  if (instance) {
94
- instance.active = false;
118
+ if (instance.state.selectAbortController) {
119
+ instance.state.selectAbortController.abort();
120
+ }
121
+ const abortController = new AbortController();
122
+ instance.state.unselectAbortController = abortController;
123
+ try {
124
+ await delay(delayMs, abortController.signal);
125
+ instance.active = false;
126
+ } catch (err) {
127
+ if (err.name === "AbortError") {
128
+ console.log(
129
+ `unselectView() was interrupted by a call to selectView()`
130
+ );
131
+ } else {
132
+ throw err;
133
+ }
134
+ }
95
135
  }
96
136
  }
97
137
  function unselectUnrelatedViews(id) {
@@ -4,8 +4,8 @@ interface UseMagicMenuArgs {
4
4
  viewId: string;
5
5
  }
6
6
  export declare function useMagicMenu(args: UseMagicMenuArgs): {
7
- selectView: (id: string) => void;
8
- unselectView: (id: string) => void;
7
+ selectView: (id: string, delayMs?: number) => Promise<void>;
8
+ unselectView: (id: string, delayMs?: number) => Promise<void>;
9
9
  selectChannel: (id: string) => void;
10
10
  unselectChannel: (id: string) => void;
11
11
  };
@@ -3,10 +3,13 @@ import type { RequireAllNested } from '@maas/vue-equipment/utils';
3
3
  type MenuMode = 'dropdown' | 'menubar' | 'context' | 'navigation';
4
4
  export interface MagicMenuOptions {
5
5
  mode?: MenuMode;
6
+ debug?: boolean;
6
7
  transition?: {
7
- initial?: string;
8
- final?: string;
9
- nested?: string;
8
+ content?: {
9
+ default?: string;
10
+ nested?: string;
11
+ };
12
+ channel: string;
10
13
  };
11
14
  }
12
15
  export type Interaction = 'click' | 'mouseenter' | 'right-click';
@@ -33,7 +36,11 @@ export interface MenuView {
33
36
  views: string[];
34
37
  };
35
38
  placement: Placement;
36
- click?: Coordinates;
39
+ state: {
40
+ selectAbortController: AbortController;
41
+ unselectAbortController: AbortController;
42
+ clicked?: Coordinates;
43
+ };
37
44
  }
38
45
  export interface MenuState {
39
46
  id: string;