@maas/vue-equipment 0.29.8 → 0.30.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.
Files changed (35) hide show
  1. package/dist/nuxt/module.json +1 -1
  2. package/dist/nuxt/module.mjs +8 -1
  3. package/dist/plugins/MagicAutoSize/index.d.ts +4 -0
  4. package/dist/plugins/MagicAutoSize/index.mjs +7 -0
  5. package/dist/plugins/MagicAutoSize/nuxt.d.ts +2 -0
  6. package/dist/plugins/MagicAutoSize/nuxt.mjs +14 -0
  7. package/dist/plugins/MagicAutoSize/src/components/MagicAutoSize.vue +99 -0
  8. package/dist/plugins/MagicAutoSize/src/components/MagicAutoSize.vue.d.ts +40 -0
  9. package/dist/plugins/MagicCommand/src/components/MagicCommandBody.vue.d.ts +0 -1
  10. package/dist/plugins/MagicMenu/index.mjs +4 -0
  11. package/dist/plugins/MagicMenu/src/components/MagicMenuChannel.vue +69 -0
  12. package/dist/plugins/MagicMenu/src/components/MagicMenuChannel.vue.d.ts +21 -0
  13. package/dist/plugins/MagicMenu/src/components/MagicMenuContent.vue +1 -3
  14. package/dist/plugins/MagicMenu/src/components/MagicMenuContent.vue.d.ts +0 -2
  15. package/dist/plugins/MagicMenu/src/components/MagicMenuRemote.vue +75 -0
  16. package/dist/plugins/MagicMenu/src/components/MagicMenuRemote.vue.d.ts +29 -0
  17. package/dist/plugins/MagicMenu/src/components/MagicMenuTrigger.vue +5 -1
  18. package/dist/plugins/MagicMenu/src/components/MagicMenuView.vue +26 -0
  19. package/dist/plugins/MagicMenu/src/components/MagicMenuView.vue.d.ts +2 -0
  20. package/dist/plugins/MagicMenu/src/composables/private/useMenuCallback.mjs +4 -0
  21. package/dist/plugins/MagicMenu/src/composables/private/useMenuChannel.d.ts +15 -0
  22. package/dist/plugins/MagicMenu/src/composables/private/useMenuChannel.mjs +73 -0
  23. package/dist/plugins/MagicMenu/src/composables/private/useMenuRemote.d.ts +13 -0
  24. package/dist/plugins/MagicMenu/src/composables/private/useMenuRemote.mjs +23 -0
  25. package/dist/plugins/MagicMenu/src/composables/private/useMenuView.d.ts +2 -2
  26. package/dist/plugins/MagicMenu/src/composables/private/useMenuView.mjs +4 -2
  27. package/dist/plugins/MagicMenu/src/composables/useMagicMenu.d.ts +8 -1
  28. package/dist/plugins/MagicMenu/src/composables/useMagicMenu.mjs +10 -2
  29. package/dist/plugins/MagicMenu/src/symbols/index.d.ts +3 -1
  30. package/dist/plugins/MagicMenu/src/symbols/index.mjs +5 -1
  31. package/dist/plugins/MagicMenu/src/types/index.d.ts +8 -1
  32. package/dist/plugins/MagicPlayer/src/components/MagicPlayerControls.vue +1 -1
  33. package/dist/plugins/index.d.ts +1 -0
  34. package/dist/plugins/index.mjs +1 -0
  35. package/package.json +1 -1
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@maas/vue-equipment/nuxt",
3
3
  "configKey": "vueEquipment",
4
- "version": "0.29.7",
4
+ "version": "0.30.0",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "0.8.0",
7
7
  "unbuild": "unknown"
@@ -1,6 +1,13 @@
1
1
  import { defineNuxtModule, createResolver, extendViteConfig, installModule, addImportsSources } from '@nuxt/kit';
2
2
 
3
3
  const functions$1 = [
4
+ {
5
+ name: "MagicAutoSize",
6
+ "package": "plugins",
7
+ lastUpdated: 1719323171000,
8
+ docs: "https://maas.egineering/vue-equipment/plugins/MagicAutoSize/",
9
+ description: "auto Size"
10
+ },
4
11
  {
5
12
  name: "MagicCommand",
6
13
  "package": "plugins",
@@ -46,7 +53,7 @@ const functions$1 = [
46
53
  {
47
54
  name: "MagicMenu",
48
55
  "package": "plugins",
49
- lastUpdated: 1719315337000,
56
+ lastUpdated: 1719385203000,
50
57
  docs: "https://maas.egineering/vue-equipment/plugins/MagicMenu/",
51
58
  description: "menu"
52
59
  },
@@ -0,0 +1,4 @@
1
+ import type { Plugin } from 'vue';
2
+ import MagicAutoSize from './src/components/MagicAutoSize.vue.js';
3
+ declare const MagicAutoSizePlugin: Plugin;
4
+ export { MagicAutoSizePlugin, MagicAutoSize };
@@ -0,0 +1,7 @@
1
+ import MagicAutoSize from "./src/components/MagicAutoSize.vue";
2
+ const MagicAutoSizePlugin = {
3
+ install: (app) => {
4
+ app.component("MagicAutoSize", MagicAutoSize);
5
+ }
6
+ };
7
+ export { MagicAutoSizePlugin, MagicAutoSize };
@@ -0,0 +1,2 @@
1
+ declare const _default: import("@nuxt/schema").NuxtModule<import("@nuxt/schema").ModuleOptions>;
2
+ export default _default;
@@ -0,0 +1,14 @@
1
+ import { defineNuxtModule, createResolver, addComponent } from "@nuxt/kit";
2
+ export default defineNuxtModule({
3
+ meta: {
4
+ name: "@maas/vue-equipment/nuxt/MagicAutoSize"
5
+ },
6
+ setup() {
7
+ const resolver = createResolver(import.meta.url);
8
+ addComponent({
9
+ filePath: resolver.resolve("src/components/MagicAutoSize.vue"),
10
+ name: "MagicAutoSize",
11
+ global: true
12
+ });
13
+ }
14
+ });
@@ -0,0 +1,99 @@
1
+ <template>
2
+ <div
3
+ class="magic-auto-size"
4
+ ref="elRef"
5
+ :style="{
6
+ '--magic-auto-size-width': mappedSize?.width,
7
+ '--magic-auto-size-height': mappedSize?.height,
8
+ }"
9
+ >
10
+ <slot />
11
+ </div>
12
+ </template>
13
+
14
+ <script lang="ts" setup>
15
+ import { ref, computed, onMounted } from 'vue'
16
+ import { useResizeObserver, useMutationObserver } from '@vueuse/core'
17
+
18
+ interface MagicAutoSizeProps {
19
+ width?: boolean
20
+ height?: boolean
21
+ }
22
+
23
+ const props = withDefaults(defineProps<MagicAutoSizeProps>(), {
24
+ width: true,
25
+ height: true,
26
+ })
27
+
28
+ const elRef = ref<HTMLElement | undefined>(undefined)
29
+
30
+ const size = ref<{ width: number; height: number }>()
31
+ const content = ref<HTMLElement | undefined>(undefined)
32
+
33
+ const mappedSize = computed(() => {
34
+ if (size.value) {
35
+ switch (true) {
36
+ case props.width && props.height:
37
+ return {
38
+ width: `${size.value.width}px`,
39
+ height: `${size.value.height}px`,
40
+ }
41
+ case props.width:
42
+ return {
43
+ width: `${size.value.width}px`,
44
+ }
45
+ case props.height:
46
+ return {
47
+ height: `${size.value.height}px`,
48
+ }
49
+ }
50
+ } else {
51
+ return undefined
52
+ }
53
+ })
54
+
55
+ useMutationObserver(
56
+ elRef,
57
+ (mutations) => {
58
+ const filtered = mutations
59
+ .flatMap((m) => [...m.addedNodes])
60
+ .find((n) => n instanceof HTMLElement)
61
+
62
+ if (!!filtered && filtered instanceof HTMLElement) {
63
+ content.value = filtered
64
+ }
65
+ },
66
+ {
67
+ childList: true,
68
+ }
69
+ )
70
+
71
+ useResizeObserver(content, () => {
72
+ if (content.value) {
73
+ size.value = {
74
+ width: content.value.offsetWidth,
75
+ height: content.value.offsetHeight,
76
+ }
77
+ }
78
+ })
79
+
80
+ onMounted(() => {
81
+ if (elRef.value) {
82
+ const content = elRef.value.querySelectorAll('*')
83
+ const filtered = Array.from(content).find(
84
+ (node) => node instanceof HTMLElement
85
+ )
86
+
87
+ if (!!filtered && filtered instanceof HTMLElement) {
88
+ size.value = {
89
+ width: filtered.offsetWidth,
90
+ height: filtered.offsetHeight,
91
+ }
92
+ }
93
+ }
94
+ })
95
+ </script>
96
+
97
+ <style>
98
+ .magic-auto-size{--magic-auto-size-transition-function:ease;--magic-auto-size-transition-duration:100ms;height:var(--magic-auto-size-height);transition:all var(--magic-auto-size-transition-duration) var(--magic-auto-size-transition-function);width:var(--magic-auto-size-width)}
99
+ </style>
@@ -0,0 +1,40 @@
1
+ interface MagicAutoSizeProps {
2
+ width?: boolean;
3
+ height?: boolean;
4
+ }
5
+ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__VLS_WithDefaults<__VLS_TypePropsToOption<MagicAutoSizeProps>, {
6
+ width: boolean;
7
+ height: boolean;
8
+ }>, {}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<__VLS_WithDefaults<__VLS_TypePropsToOption<MagicAutoSizeProps>, {
9
+ width: boolean;
10
+ height: boolean;
11
+ }>>>, {
12
+ width: boolean;
13
+ height: boolean;
14
+ }, {}>, {
15
+ default?(_: {}): any;
16
+ }>;
17
+ export default _default;
18
+
19
+ type __VLS_WithDefaults<P, D> = {
20
+ [K in keyof Pick<P, keyof P>]: K extends keyof D ? __VLS_Prettify<P[K] & {
21
+ default: D[K];
22
+ }> : P[K];
23
+ };
24
+ type __VLS_Prettify<T> = {
25
+ [K in keyof T]: T[K];
26
+ } & {};
27
+ type __VLS_WithTemplateSlots<T, S> = T & {
28
+ new (): {
29
+ $slots: S;
30
+ };
31
+ };
32
+ type __VLS_NonUndefinedable<T> = T extends undefined ? never : T;
33
+ type __VLS_TypePropsToOption<T> = {
34
+ [K in keyof T]-?: {} extends Pick<T, K> ? {
35
+ type: import('vue').PropType<__VLS_NonUndefinedable<T[K]>>;
36
+ } : {
37
+ type: import('vue').PropType<T[K]>;
38
+ required: true;
39
+ };
40
+ };
@@ -2,7 +2,6 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<{}
2
2
  default?(_: {}): any;
3
3
  }>;
4
4
  export default _default;
5
-
6
5
  type __VLS_WithTemplateSlots<T, S> = T & {
7
6
  new (): {
8
7
  $slots: S;
@@ -1,7 +1,9 @@
1
1
  import MagicMenuFloat from "./src/components/MagicMenuFloat.vue";
2
2
  import MagicMenuContent from "./src/components/MagicMenuContent.vue";
3
+ import MagicMenuChannel from "./src/components/MagicMenuChannel.vue";
3
4
  import MagicMenuItem from "./src/components/MagicMenuItem.vue";
4
5
  import MagicMenuProvider from "./src/components/MagicMenuProvider.vue";
6
+ import MagicMenuRemote from "./src/components/MagicMenuRemote.vue";
5
7
  import MagicMenuTrigger from "./src/components/MagicMenuTrigger.vue";
6
8
  import MagicMenuView from "./src/components/MagicMenuView.vue";
7
9
  import { useMagicMenu } from "./src/composables/useMagicMenu.mjs";
@@ -14,8 +16,10 @@ const MagicMenuPlugin = {
14
16
  install: (app) => {
15
17
  app.component("MagicMenuFloat", MagicMenuFloat);
16
18
  app.component("MagicMenuContent", MagicMenuContent);
19
+ app.component("MagicMenuChannel", MagicMenuChannel);
17
20
  app.component("MagicMenuItem", MagicMenuItem);
18
21
  app.component("MagicMenuProvider", MagicMenuProvider);
22
+ app.component("MagicMenuRemote", MagicMenuRemote);
19
23
  app.component("MagicMenuTrigger", MagicMenuTrigger);
20
24
  app.component("MagicMenuView", MagicMenuView);
21
25
  }
@@ -0,0 +1,69 @@
1
+ <template>
2
+ <div
3
+ class="magic-menu-channel"
4
+ v-if="channel.active"
5
+ :data-id="mappedId"
6
+ :id="id"
7
+ >
8
+ <slot />
9
+ </div>
10
+ </template>
11
+
12
+ <script lang="ts" setup>
13
+ import { computed, inject, provide, onBeforeUnmount } from 'vue'
14
+ import { useMenuChannel } from '../composables/private/useMenuChannel'
15
+ import {
16
+ MagicMenuInstanceId,
17
+ MagicMenuViewId,
18
+ MagicMenuContentId,
19
+ MagicMenuChannelId,
20
+ MagicMenuChannelActive,
21
+ } from '../symbols'
22
+
23
+ interface MagicMenuChannelProps {
24
+ id: string
25
+ }
26
+
27
+ const props = defineProps<MagicMenuChannelProps>()
28
+
29
+ const instanceId = inject(MagicMenuInstanceId, undefined)
30
+ const viewId = inject(MagicMenuViewId, undefined)
31
+ const contentId = inject(MagicMenuContentId, undefined)
32
+
33
+ if (!instanceId) {
34
+ throw new Error('MagicMenuChannel must be nested inside MagicMenuProvider')
35
+ }
36
+
37
+ if (!viewId) {
38
+ throw new Error('MagicMenuChannel must be nested inside MagicMenuView')
39
+ }
40
+
41
+ if (!contentId) {
42
+ throw new Error('MagicMenuChannel must be nested inside MagicMenuContent')
43
+ }
44
+
45
+ if (!props.id) {
46
+ throw new Error('MagicMenuChannel requires an id')
47
+ }
48
+
49
+ const mappedId = computed(() => `magic-menu-channel-${props.id}`)
50
+
51
+ // Register channel
52
+ const { initializeChannel, deleteChannel } = useMenuChannel({
53
+ instanceId,
54
+ viewId,
55
+ })
56
+
57
+ const channel = initializeChannel({
58
+ id: mappedId.value,
59
+ })
60
+
61
+ // Pass id and active state to children
62
+ provide(MagicMenuChannelId, mappedId.value)
63
+ provide(MagicMenuChannelActive, channel.active)
64
+
65
+ // Lifecycle
66
+ onBeforeUnmount(() => {
67
+ deleteChannel(mappedId.value)
68
+ })
69
+ </script>
@@ -0,0 +1,21 @@
1
+ interface MagicMenuChannelProps {
2
+ id: string;
3
+ }
4
+ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__VLS_TypePropsToOption<MagicMenuChannelProps>, {}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<__VLS_TypePropsToOption<MagicMenuChannelProps>>>, {}, {}>, {
5
+ default?(_: {}): any;
6
+ }>;
7
+ export default _default;
8
+ type __VLS_WithTemplateSlots<T, S> = T & {
9
+ new (): {
10
+ $slots: S;
11
+ };
12
+ };
13
+ type __VLS_NonUndefinedable<T> = T extends undefined ? never : T;
14
+ type __VLS_TypePropsToOption<T> = {
15
+ [K in keyof T]-?: {} extends Pick<T, K> ? {
16
+ type: import('vue').PropType<__VLS_NonUndefinedable<T[K]>>;
17
+ } : {
18
+ type: import('vue').PropType<T[K]>;
19
+ required: true;
20
+ };
21
+ };
@@ -16,7 +16,7 @@
16
16
  v-if="innerActive"
17
17
  >
18
18
  <magic-menu-float
19
- :placement="placement"
19
+ :placement="view?.placement"
20
20
  :arrow="arrow"
21
21
  :reference-el="referenceEl"
22
22
  >
@@ -45,7 +45,6 @@ import {
45
45
  type MaybeRef,
46
46
  type ComponentPublicInstance,
47
47
  } from 'vue'
48
- import type { Placement } from '@floating-ui/vue'
49
48
  import { useMenuView } from '../composables/private/useMenuView'
50
49
  import {
51
50
  MagicMenuInstanceId,
@@ -64,7 +63,6 @@ defineOptions({
64
63
  })
65
64
 
66
65
  interface MagicMenuContentProps {
67
- placement?: Placement
68
66
  arrow?: boolean | undefined
69
67
  referenceEl?: MaybeRef<HTMLElement | ComponentPublicInstance>
70
68
  }
@@ -1,9 +1,7 @@
1
1
  import { type MaybeRef, type ComponentPublicInstance } from 'vue';
2
- import type { Placement } from '@floating-ui/vue';
3
2
  import '@maas/vue-equipment/utils/css/animations/fade-in.css';
4
3
  import '@maas/vue-equipment/utils/css/animations/fade-out.css';
5
4
  interface MagicMenuContentProps {
6
- placement?: Placement;
7
5
  arrow?: boolean | undefined;
8
6
  referenceEl?: MaybeRef<HTMLElement | ComponentPublicInstance>;
9
7
  }
@@ -0,0 +1,75 @@
1
+ <template>
2
+ <div
3
+ class="magic-menu-remote"
4
+ :class="{ '-active': channel?.active, '-disabled': disabled }"
5
+ :data-id="`${channelId}-remote`"
6
+ @click="onClick"
7
+ @mouseenter="onMouseenter"
8
+ >
9
+ <slot :is-active="view?.active" :is-disabled="disabled" />
10
+ </div>
11
+ </template>
12
+
13
+ <script lang="ts" setup>
14
+ import { computed, inject } from 'vue'
15
+ import { useMenuView } from '../composables/private/useMenuView'
16
+ import { useMenuChannel } from '../composables/private/useMenuChannel'
17
+ import { MagicMenuInstanceId, MagicMenuViewId } from '../symbols'
18
+
19
+ import type { Interaction } from '../types'
20
+ import { useMenuRemote } from '../composables/private/useMenuRemote'
21
+
22
+ interface MagicMenuRemoteProps {
23
+ channelId: string
24
+ viewId?: string
25
+ instanceId?: string
26
+ disabled?: boolean
27
+ trigger?: Interaction[]
28
+ }
29
+
30
+ const props = defineProps<MagicMenuRemoteProps>()
31
+
32
+ const instanceId = inject(MagicMenuInstanceId, props.instanceId)
33
+ const viewId = inject(MagicMenuViewId, props.viewId)
34
+
35
+ if (!instanceId) {
36
+ throw new Error(
37
+ 'MagicMenuRemote must be nested inside MagicMenuProvider or an instanceId must be provided'
38
+ )
39
+ }
40
+
41
+ if (!viewId) {
42
+ throw new Error(
43
+ 'MagicMenuTrigger must be nested inside MagicMenuView or a viewId must be provided'
44
+ )
45
+ }
46
+
47
+ if (!props.channelId) {
48
+ throw new Error('MagicMenuRemote requires a channelId')
49
+ }
50
+
51
+ const mappedChannelId = computed(() => `magic-menu-channel-${props.channelId}`)
52
+ const mappedTrigger = computed<Interaction[]>(
53
+ () => props.trigger ?? ['mouseenter']
54
+ )
55
+
56
+ const { getView } = useMenuView(instanceId)
57
+ const view = getView(viewId)
58
+
59
+ const { getChannel } = useMenuChannel({
60
+ instanceId,
61
+ viewId,
62
+ })
63
+ const channel = getChannel(mappedChannelId.value)
64
+
65
+ const { onClick, onMouseenter } = useMenuRemote({
66
+ viewId,
67
+ instanceId,
68
+ mappedChannelId,
69
+ mappedTrigger,
70
+ })
71
+ </script>
72
+
73
+ <style>
74
+ .magic-menu-remote{cursor:var(--magic-menu-remote-cursor,pointer)}
75
+ </style>
@@ -0,0 +1,29 @@
1
+ import type { Interaction } from '../types';
2
+ interface MagicMenuRemoteProps {
3
+ channelId: string;
4
+ viewId?: string;
5
+ instanceId?: string;
6
+ disabled?: boolean;
7
+ trigger?: Interaction[];
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>>>, {}, {}>, {
10
+ default?(_: {
11
+ isActive: boolean | undefined;
12
+ isDisabled: boolean | undefined;
13
+ }): any;
14
+ }>;
15
+ export default _default;
16
+ type __VLS_WithTemplateSlots<T, S> = T & {
17
+ new (): {
18
+ $slots: S;
19
+ };
20
+ };
21
+ type __VLS_NonUndefinedable<T> = T extends undefined ? never : T;
22
+ type __VLS_TypePropsToOption<T> = {
23
+ [K in keyof T]-?: {} extends Pick<T, K> ? {
24
+ type: import('vue').PropType<__VLS_NonUndefinedable<T[K]>>;
25
+ } : {
26
+ type: import('vue').PropType<T[K]>;
27
+ required: true;
28
+ };
29
+ };
@@ -69,7 +69,9 @@ const mappedTrigger = computed<Interaction[]>(() => {
69
69
  case 'menubar':
70
70
  return view?.parent.item
71
71
  ? ['mouseenter', 'mouseleave', 'click']
72
- : ['mouseenter', 'click']
72
+ : state.active
73
+ ? ['mouseenter', 'click']
74
+ : ['click']
73
75
  case 'dropdown':
74
76
  return view?.parent.item
75
77
  ? ['mouseenter', 'mouseleave', 'click']
@@ -78,6 +80,8 @@ const mappedTrigger = computed<Interaction[]>(() => {
78
80
  return view?.parent.item
79
81
  ? ['mouseenter', 'mouseleave', 'click']
80
82
  : ['right-click']
83
+ case 'navigation':
84
+ return ['mouseenter', 'mouseleave']
81
85
  }
82
86
  })
83
87
 
@@ -16,9 +16,12 @@ import {
16
16
  MagicMenuItemId,
17
17
  MagicMenuViewActive,
18
18
  } from '../symbols'
19
+ import type { Placement } from '@floating-ui/vue'
20
+ import { useMenuState } from '../composables/private/useMenuState'
19
21
 
20
22
  interface MagicMenuViewProps {
21
23
  id?: string
24
+ placement?: Placement
22
25
  }
23
26
 
24
27
  const props = defineProps<MagicMenuViewProps>()
@@ -36,9 +39,32 @@ const mappedParentTree = computed(() => [...parentTree, mappedId.value])
36
39
 
37
40
  // Register view
38
41
  const { initializeView, deleteView } = useMenuView(instanceId)
42
+ const { initializeState } = useMenuState(instanceId)
43
+ const state = initializeState()
44
+
45
+ const mappedPlacement = computed(() => {
46
+ if (props.placement) {
47
+ return props.placement
48
+ }
49
+
50
+ switch (state.options.mode) {
51
+ case 'navigation':
52
+ return 'bottom'
53
+ case 'menubar':
54
+ return !itemId ? 'bottom-start' : 'right-start'
55
+ case 'dropdown':
56
+ return !itemId ? 'bottom' : 'right-start'
57
+ case 'context':
58
+ return 'right-start'
59
+ default:
60
+ return 'bottom'
61
+ }
62
+ })
63
+
39
64
  const view = initializeView({
40
65
  id: mappedId.value,
41
66
  parent: { views: parentTree, item: itemId ?? '' },
67
+ placement: mappedPlacement.value,
42
68
  })
43
69
 
44
70
  // Pass id, active state and parent tree to children
@@ -1,5 +1,7 @@
1
+ import type { Placement } from '@floating-ui/vue';
1
2
  interface MagicMenuViewProps {
2
3
  id?: string;
4
+ placement?: Placement;
3
5
  }
4
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>>>, {}, {}>, {
5
7
  default?(_: {}): any;
@@ -17,6 +17,8 @@ export function useMenuCallback(args) {
17
17
  break;
18
18
  case "menubar":
19
19
  break;
20
+ case "navigation":
21
+ break;
20
22
  case "context":
21
23
  lockScroll();
22
24
  break;
@@ -36,6 +38,8 @@ export function useMenuCallback(args) {
36
38
  break;
37
39
  case "menubar":
38
40
  break;
41
+ case "navigation":
42
+ break;
39
43
  case "context":
40
44
  unlockScroll();
41
45
  break;
@@ -0,0 +1,15 @@
1
+ import { type MaybeRef } from 'vue';
2
+ import type { MenuChannel } from '../../types.js';
3
+ type UseMenuChannelArgs = {
4
+ instanceId: MaybeRef<string>;
5
+ viewId: string;
6
+ };
7
+ type InitializeChannelArgs = Pick<MenuChannel, 'id'>;
8
+ export declare function useMenuChannel(args: UseMenuChannelArgs): {
9
+ initializeChannel: (args: InitializeChannelArgs) => MenuChannel;
10
+ deleteChannel: (id: string) => void;
11
+ getChannel: (id: string) => MenuChannel | undefined;
12
+ selectChannel: (id: string) => void;
13
+ unselectChannel: (id: string) => void;
14
+ };
15
+ export {};
@@ -0,0 +1,73 @@
1
+ import { reactive } from "vue";
2
+ import { useMenuView } from "./useMenuView.mjs";
3
+ import { useMenuState } from "./useMenuState.mjs";
4
+ export function useMenuChannel(args) {
5
+ const { instanceId, viewId } = args;
6
+ const { initializeState } = useMenuState(instanceId);
7
+ const state = initializeState();
8
+ const { getView } = useMenuView(instanceId);
9
+ const view = getView(viewId);
10
+ if (!view) {
11
+ throw new Error(`View ${viewId} not found`);
12
+ }
13
+ function createChannel(args2) {
14
+ const { id } = args2;
15
+ const channel = {
16
+ id,
17
+ active: false
18
+ };
19
+ return reactive(channel);
20
+ }
21
+ function addChannel(args2) {
22
+ const channel = createChannel(args2);
23
+ if (view?.channels) {
24
+ view.channels = [...view?.channels, channel];
25
+ }
26
+ return channel;
27
+ }
28
+ function unselectSiblings(id) {
29
+ return view?.channels.filter((channel) => channel.id !== id).forEach((channel) => channel.active = false);
30
+ }
31
+ function initializeChannel(args2) {
32
+ const { id } = args2;
33
+ const instance = getChannel(id);
34
+ if (!instance) {
35
+ const channel = addChannel(args2);
36
+ return channel;
37
+ }
38
+ return instance;
39
+ }
40
+ function deleteChannel(id) {
41
+ if (!view?.channels)
42
+ return;
43
+ view.channels = view.channels.filter((x) => x.id !== id);
44
+ }
45
+ function getChannel(id) {
46
+ return view?.channels.find((channel) => {
47
+ return channel.id === id;
48
+ });
49
+ }
50
+ function selectChannel(id) {
51
+ const instance = getChannel(id);
52
+ if (instance) {
53
+ instance.active = true;
54
+ unselectSiblings(id);
55
+ if (view) {
56
+ state.input.view = view.id;
57
+ }
58
+ }
59
+ }
60
+ function unselectChannel(id) {
61
+ const instance = getChannel(id);
62
+ if (instance) {
63
+ instance.active = false;
64
+ }
65
+ }
66
+ return {
67
+ initializeChannel,
68
+ deleteChannel,
69
+ getChannel,
70
+ selectChannel,
71
+ unselectChannel
72
+ };
73
+ }
@@ -0,0 +1,13 @@
1
+ import { type MaybeRef, type ComputedRef } from 'vue';
2
+ import type { Interaction } from '../../types.js';
3
+ interface UseMenuRemoteArgs {
4
+ viewId: string;
5
+ instanceId: MaybeRef<string>;
6
+ mappedChannelId: MaybeRef<string>;
7
+ mappedTrigger: ComputedRef<Interaction[]>;
8
+ }
9
+ export declare function useMenuRemote(args: UseMenuRemoteArgs): {
10
+ onClick: () => void;
11
+ onMouseenter: () => void;
12
+ };
13
+ export {};
@@ -0,0 +1,23 @@
1
+ import { toValue } from "vue";
2
+ import { useMenuChannel } from "./useMenuChannel.mjs";
3
+ export function useMenuRemote(args) {
4
+ const { viewId, instanceId, mappedChannelId, mappedTrigger } = args;
5
+ const { selectChannel } = useMenuChannel({
6
+ instanceId,
7
+ viewId
8
+ });
9
+ function onClick() {
10
+ if (mappedTrigger.value.includes("click")) {
11
+ selectChannel(toValue(mappedChannelId));
12
+ }
13
+ }
14
+ function onMouseenter() {
15
+ if (mappedTrigger.value.includes("mouseenter")) {
16
+ selectChannel(toValue(mappedChannelId));
17
+ }
18
+ }
19
+ return {
20
+ onClick,
21
+ onMouseenter
22
+ };
23
+ }
@@ -1,9 +1,9 @@
1
1
  import { type MaybeRef } from 'vue';
2
2
  import type { MenuView } from '../../types/index.js';
3
- type FindViewArgs = Pick<MenuView, 'id' | 'parent'>;
3
+ type InitializeViewArgs = Pick<MenuView, 'id' | 'parent' | 'placement'>;
4
4
  export declare function useMenuView(instanceId: MaybeRef<string>): {
5
5
  currentView: import("vue").ComputedRef<MenuView>;
6
- initializeView: (args: FindViewArgs) => MenuView;
6
+ initializeView: (args: InitializeViewArgs) => MenuView;
7
7
  deleteView: (id: string) => void;
8
8
  getView: (id: string) => MenuView | undefined;
9
9
  getRelativeViewIndex: (id: string) => number;
@@ -9,7 +9,7 @@ export function useMenuView(instanceId) {
9
9
  )
10
10
  );
11
11
  function createView(args) {
12
- const { id, parent } = args;
12
+ const { id, parent, placement } = args;
13
13
  if (parent.views.length === 0) {
14
14
  parent.views.push(toValue(instanceId));
15
15
  }
@@ -21,7 +21,9 @@ export function useMenuView(instanceId) {
21
21
  content: void 0
22
22
  },
23
23
  active: false,
24
- items: []
24
+ items: [],
25
+ channels: [],
26
+ placement
25
27
  };
26
28
  return reactive(view);
27
29
  }
@@ -1,6 +1,13 @@
1
1
  import { type MaybeRef } from 'vue';
2
- export declare function useMagicMenu(instanceId: MaybeRef<string>): {
2
+ interface UseMagicMenuArgs {
3
+ instanceId: MaybeRef<string>;
4
+ viewId?: string;
5
+ }
6
+ export declare function useMagicMenu(args: UseMagicMenuArgs): {
3
7
  selectView: (id: string) => void;
4
8
  unselectView: (id: string) => void;
9
+ selectChannel: (id: string) => void;
10
+ unselectChannel: (id: string) => void;
5
11
  };
6
12
  export type UseMagicMenuReturn = ReturnType<typeof useMagicMenu>;
13
+ export {};
@@ -1,8 +1,16 @@
1
1
  import { useMenuView } from "./private/useMenuView.mjs";
2
- export function useMagicMenu(instanceId) {
2
+ import { useMenuChannel } from "./private/useMenuChannel.mjs";
3
+ export function useMagicMenu(args) {
4
+ const { instanceId, viewId } = args;
3
5
  const { selectView, unselectView } = useMenuView(instanceId);
6
+ const { selectChannel, unselectChannel } = useMenuChannel({
7
+ instanceId,
8
+ viewId: viewId ?? ""
9
+ });
4
10
  return {
5
11
  selectView,
6
- unselectView
12
+ unselectView,
13
+ selectChannel,
14
+ unselectChannel
7
15
  };
8
16
  }
@@ -6,4 +6,6 @@ declare const MagicMenuViewActive: InjectionKey<boolean>;
6
6
  declare const MagicMenuContentId: InjectionKey<string>;
7
7
  declare const MagicMenuItemId: InjectionKey<string>;
8
8
  declare const MagicMenuItemActive: InjectionKey<boolean>;
9
- export { MagicMenuInstanceId, MagicMenuParentTree, MagicMenuViewId, MagicMenuViewActive, MagicMenuContentId, MagicMenuItemId, MagicMenuItemActive, };
9
+ declare const MagicMenuChannelId: InjectionKey<string>;
10
+ declare const MagicMenuChannelActive: InjectionKey<boolean>;
11
+ export { MagicMenuInstanceId, MagicMenuParentTree, MagicMenuViewId, MagicMenuViewActive, MagicMenuContentId, MagicMenuItemId, MagicMenuItemActive, MagicMenuChannelId, MagicMenuChannelActive, };
@@ -5,6 +5,8 @@ const MagicMenuViewActive = Symbol();
5
5
  const MagicMenuContentId = Symbol();
6
6
  const MagicMenuItemId = Symbol();
7
7
  const MagicMenuItemActive = Symbol();
8
+ const MagicMenuChannelId = Symbol();
9
+ const MagicMenuChannelActive = Symbol();
8
10
  export {
9
11
  MagicMenuInstanceId,
10
12
  MagicMenuParentTree,
@@ -12,5 +14,7 @@ export {
12
14
  MagicMenuViewActive,
13
15
  MagicMenuContentId,
14
16
  MagicMenuItemId,
15
- MagicMenuItemActive
17
+ MagicMenuItemActive,
18
+ MagicMenuChannelId,
19
+ MagicMenuChannelActive
16
20
  };
@@ -1,5 +1,6 @@
1
+ import type { Placement } from '@floating-ui/vue';
1
2
  import type { RequireAllNested } from '@maas/vue-equipment/utils';
2
- type MenuMode = 'dropdown' | 'menubar' | 'context';
3
+ type MenuMode = 'dropdown' | 'menubar' | 'context' | 'navigation';
3
4
  export interface MagicMenuOptions {
4
5
  mode?: MenuMode;
5
6
  transition?: {
@@ -18,10 +19,15 @@ export interface MenuItem {
18
19
  active: boolean;
19
20
  disabled: boolean;
20
21
  }
22
+ export interface MenuChannel {
23
+ id: string;
24
+ active: boolean;
25
+ }
21
26
  export interface MenuView {
22
27
  id: string;
23
28
  active: boolean;
24
29
  items: MenuItem[];
30
+ channels: MenuChannel[];
25
31
  parent: {
26
32
  item: string;
27
33
  views: string[];
@@ -30,6 +36,7 @@ export interface MenuView {
30
36
  trigger?: HTMLElement;
31
37
  content?: HTMLElement;
32
38
  };
39
+ placement: Placement;
33
40
  click?: Coordinates;
34
41
  }
35
42
  export interface MenuState {
@@ -146,5 +146,5 @@ const hidden = computed(() => {
146
146
  </script>
147
147
 
148
148
  <style>
149
- :root{--magic-player-controls-height:3rem;--magic-player-controls-padding:0.75rem;--magic-player-controls-bottom:1.5rem;--magic-player-controls-left:1.5rem;--magic-player-controls-width:calc(100% - var(--magic-player-controls-left)*2);--magic-player-controls-gap:1rem;--magic-player-controls-border-radius:50rem;--magic-player-controls-background:rgba(32,32,32,.8);--magic-player-controls-backdrop-filter:blur(80px);--magic-player-controls-color:#fff;--magic-player-controls-button-width:3rem;--magic-player-controls-icon-width:1.25rem}@media (max-width:640px){:root{--magic-player-controls-height:2.5rem;--magic-player-controls-bottom:0.75rem;--magic-player-controls-padding:0.5rem}}.magic-player-controls{inset:0;pointer-events:none;position:absolute;width:100%}.magic-player-controls-enter-active{animation:fade-up-in .15s ease}.magic-player-controls-leave-active{animation:fade-up-out .15s ease}.magic-player-controls__bar{align-items:flex-start;bottom:var(--magic-player-controls-bottom);display:flex;flex-direction:column;gap:var(--magic-player-controls-gap);left:var(--magic-player-controls-left);margin:0 auto;pointer-events:auto;position:absolute;width:var(--magic-player-controls-width)}.magic-player-controls__bar--inner{align-items:center;-webkit-backdrop-filter:var(--magic-player-controls-backdrop-filter);backdrop-filter:var(--magic-player-controls-backdrop-filter);background-color:var(--magic-player-controls-background);border-radius:var(--magic-player-controls-border-radius);box-sizing:border-box;color:var(--magic-player-controls-color);display:flex;height:var(--magic-player-controls-height);padding:0 var(--magic-player-controls-padding);width:100%}.magic-player-controls__item{align-items:center;display:inline-flex;-webkit-user-select:none;-moz-user-select:none;user-select:none}.magic-player-controls__item.-shrink-0{flex-shrink:0}.magic-player-controls__item.-grow{flex-grow:1}.magic-player-controls__item button{align-items:center;-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:transparent;border:0;border-radius:0;color:inherit;cursor:pointer;display:flex;height:var(--magic-player-controls-height);justify-content:center;outline:none;padding:0;width:var(--magic-player-controls-button-width)}.magic-player-controls__item button svg{display:block;height:auto;width:var(--magic-player-controls-icon-width)}.magic-player-controls__timeline{width:100%}.magic-player-controls.-standalone{inset:unset;position:relative;--magic-player-controls-width:100%;--magic-player-controls-bottom:0;--magic-player-controls-left:0;--magic-player-controls-padding:0;--magic-player-controls-background:unset;--magic-player-controls-border-radius:unset;--magic-player-controls-background:transparent;--magic-player-controls-backdrop-filter:none;--magic-player-controls-transition-duration:unset;--magic-player-controls-transition-timing-function:unset}.magic-player-controls.-standalone .magic-player-controls__bar{position:relative}
149
+ :root{--magic-player-controls-height:3rem;--magic-player-controls-padding:0.75rem;--magic-player-controls-bottom:1.5rem;--magic-player-controls-left:1.5rem;--magic-player-controls-width:calc(100% - var(--magic-player-controls-left)*2);--magic-player-controls-gap:1rem;--magic-player-controls-border-radius:50rem;--magic-player-controls-background:rgba(32,32,32,.8);--magic-player-controls-backdrop-filter:blur(80px);--magic-player-controls-color:#fff;--magic-player-controls-button-width:3rem;--magic-player-controls-icon-width:1.25rem}@media (max-width:640px){:root{--magic-player-controls-height:2.5rem;--magic-player-controls-bottom:0.75rem;--magic-player-controls-padding:0.5rem}}.magic-player-controls{inset:0;pointer-events:none;position:absolute;width:100%}.magic-player-controls-enter-active{animation:fade-up-in .15s ease}.magic-player-controls-leave-active{animation:fade-up-out .15s ease}.magic-player-controls__bar{align-items:flex-start;bottom:var(--magic-player-controls-bottom);display:flex;flex-direction:column;gap:var(--magic-player-controls-gap);left:var(--magic-player-controls-left);margin:0 auto;pointer-events:auto;position:absolute;width:var(--magic-player-controls-width)}.magic-player-controls__bar--inner{align-items:center;-webkit-backdrop-filter:var(--magic-player-controls-backdrop-filter);backdrop-filter:var(--magic-player-controls-backdrop-filter);background-color:var(--magic-player-controls-background);border-radius:var(--magic-player-controls-border-radius);box-sizing:border-box;color:var(--magic-player-controls-color);display:flex;height:var(--magic-player-controls-height);padding:0 var(--magic-player-controls-padding);width:100%}.magic-player-controls__item{align-items:center;display:inline-flex;-webkit-user-select:none;-moz-user-select:none;user-select:none}.magic-player-controls__item.-shrink-0{flex-shrink:0}.magic-player-controls__item.-grow{flex-grow:1}.magic-player-controls__item button{align-items:center;-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:transparent;border:0;border-radius:0;color:inherit;cursor:pointer;display:flex;height:var(--magic-player-controls-height);justify-content:center;outline:none;padding:0;width:var(--magic-player-controls-button-width)}.magic-player-controls__item button svg{display:block;height:auto;width:var(--magic-player-controls-icon-width)}.magic-player-controls__timeline{width:100%}.magic-player-controls.-standalone{inset:unset;position:relative;--magic-player-controls-width:100%;--magic-player-controls-bottom:0;--magic-player-controls-left:0;--magic-player-controls-padding:0;--magic-player-controls-background:unset;--magic-player-controls-border-radius:unset;--magic-player-controls-background:transparent;--magic-player-controls-backdrop-filter:none}.magic-player-controls.-standalone .magic-player-controls__bar{position:relative}
150
150
  </style>
@@ -1,3 +1,4 @@
1
+ export * from './MagicAutoSize/index.js';
1
2
  export * from './MagicCommand/index.js';
2
3
  export * from './MagicCookie/index.js';
3
4
  export * from './MagicDraggable/index.js';
@@ -1,3 +1,4 @@
1
+ export * from "./MagicAutoSize/index.mjs";
1
2
  export * from "./MagicCommand/index.mjs";
2
3
  export * from "./MagicCookie/index.mjs";
3
4
  export * from "./MagicDraggable/index.mjs";
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@maas/vue-equipment",
3
3
  "description": "A magic collection of Vue composables, plugins, components and directives",
4
- "version": "0.29.8",
4
+ "version": "0.30.1",
5
5
  "author": "Robin Scholz <https://github.com/robinscholz>, Christoph Jeworutzki <https://github.com/ChristophJeworutzki>",
6
6
  "devDependencies": {
7
7
  "@antfu/ni": "^0.21.12",