@maas/vue-equipment 0.30.0 → 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.
- package/dist/nuxt/module.json +1 -1
- package/dist/nuxt/module.mjs +2 -2
- package/dist/plugins/MagicAutoSize/src/components/MagicAutoSize.vue +13 -8
- package/dist/plugins/MagicMenu/index.mjs +4 -0
- package/dist/plugins/MagicMenu/src/components/MagicMenuChannel.vue +69 -0
- package/dist/plugins/MagicMenu/src/components/MagicMenuChannel.vue.d.ts +21 -0
- package/dist/plugins/MagicMenu/src/components/MagicMenuContent.vue +1 -3
- package/dist/plugins/MagicMenu/src/components/MagicMenuContent.vue.d.ts +0 -2
- package/dist/plugins/MagicMenu/src/components/MagicMenuRemote.vue +75 -0
- package/dist/plugins/MagicMenu/src/components/MagicMenuRemote.vue.d.ts +29 -0
- package/dist/plugins/MagicMenu/src/components/MagicMenuTrigger.vue +5 -1
- package/dist/plugins/MagicMenu/src/components/MagicMenuView.vue +26 -0
- package/dist/plugins/MagicMenu/src/components/MagicMenuView.vue.d.ts +2 -0
- package/dist/plugins/MagicMenu/src/composables/private/useMenuCallback.mjs +4 -0
- package/dist/plugins/MagicMenu/src/composables/private/useMenuChannel.d.ts +15 -0
- package/dist/plugins/MagicMenu/src/composables/private/useMenuChannel.mjs +73 -0
- package/dist/plugins/MagicMenu/src/composables/private/useMenuRemote.d.ts +13 -0
- package/dist/plugins/MagicMenu/src/composables/private/useMenuRemote.mjs +23 -0
- package/dist/plugins/MagicMenu/src/composables/private/useMenuView.d.ts +2 -2
- package/dist/plugins/MagicMenu/src/composables/private/useMenuView.mjs +4 -2
- package/dist/plugins/MagicMenu/src/composables/useMagicMenu.d.ts +8 -1
- package/dist/plugins/MagicMenu/src/composables/useMagicMenu.mjs +10 -2
- package/dist/plugins/MagicMenu/src/symbols/index.d.ts +3 -1
- package/dist/plugins/MagicMenu/src/symbols/index.mjs +5 -1
- package/dist/plugins/MagicMenu/src/types/index.d.ts +8 -1
- package/package.json +1 -1
package/dist/nuxt/module.json
CHANGED
package/dist/nuxt/module.mjs
CHANGED
|
@@ -4,7 +4,7 @@ const functions$1 = [
|
|
|
4
4
|
{
|
|
5
5
|
name: "MagicAutoSize",
|
|
6
6
|
"package": "plugins",
|
|
7
|
-
lastUpdated:
|
|
7
|
+
lastUpdated: 1719323171000,
|
|
8
8
|
docs: "https://maas.egineering/vue-equipment/plugins/MagicAutoSize/",
|
|
9
9
|
description: "auto Size"
|
|
10
10
|
},
|
|
@@ -53,7 +53,7 @@ const functions$1 = [
|
|
|
53
53
|
{
|
|
54
54
|
name: "MagicMenu",
|
|
55
55
|
"package": "plugins",
|
|
56
|
-
lastUpdated:
|
|
56
|
+
lastUpdated: 1719385203000,
|
|
57
57
|
docs: "https://maas.egineering/vue-equipment/plugins/MagicMenu/",
|
|
58
58
|
description: "menu"
|
|
59
59
|
},
|
|
@@ -55,12 +55,13 @@ const mappedSize = computed(() => {
|
|
|
55
55
|
useMutationObserver(
|
|
56
56
|
elRef,
|
|
57
57
|
(mutations) => {
|
|
58
|
-
const
|
|
58
|
+
const filtered = mutations
|
|
59
59
|
.flatMap((m) => [...m.addedNodes])
|
|
60
|
-
.
|
|
61
|
-
.map((n) => n as HTMLElement)
|
|
60
|
+
.find((n) => n instanceof HTMLElement)
|
|
62
61
|
|
|
63
|
-
|
|
62
|
+
if (!!filtered && filtered instanceof HTMLElement) {
|
|
63
|
+
content.value = filtered
|
|
64
|
+
}
|
|
64
65
|
},
|
|
65
66
|
{
|
|
66
67
|
childList: true,
|
|
@@ -78,11 +79,15 @@ useResizeObserver(content, () => {
|
|
|
78
79
|
|
|
79
80
|
onMounted(() => {
|
|
80
81
|
if (elRef.value) {
|
|
81
|
-
const content = elRef.value.
|
|
82
|
-
|
|
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) {
|
|
83
88
|
size.value = {
|
|
84
|
-
width:
|
|
85
|
-
height:
|
|
89
|
+
width: filtered.offsetWidth,
|
|
90
|
+
height: filtered.offsetHeight,
|
|
86
91
|
}
|
|
87
92
|
}
|
|
88
93
|
}
|
|
@@ -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
|
-
:
|
|
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
|
|
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:
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 {
|
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.30.
|
|
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",
|