@maas/vue-equipment 0.30.0 → 0.30.2
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 +61 -16
- package/dist/plugins/MagicMenu/src/components/MagicMenuContent.vue.d.ts +0 -2
- package/dist/plugins/MagicMenu/src/components/MagicMenuFloat.vue +2 -2
- package/dist/plugins/MagicMenu/src/components/MagicMenuItem.vue +1 -1
- package/dist/plugins/MagicMenu/src/components/MagicMenuProvider.vue +1 -5
- package/dist/plugins/MagicMenu/src/components/MagicMenuRemote.vue +84 -0
- package/dist/plugins/MagicMenu/src/components/MagicMenuRemote.vue.d.ts +29 -0
- package/dist/plugins/MagicMenu/src/components/MagicMenuTrigger.vue +25 -31
- 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.d.ts +2 -1
- package/dist/plugins/MagicMenu/src/composables/private/useMenuCallback.mjs +6 -1
- package/dist/plugins/MagicMenu/src/composables/private/useMenuChannel.d.ts +15 -0
- package/dist/plugins/MagicMenu/src/composables/private/useMenuChannel.mjs +70 -0
- package/dist/plugins/MagicMenu/src/composables/private/useMenuCursor.d.ts +21 -0
- package/dist/plugins/MagicMenu/src/composables/private/useMenuCursor.mjs +212 -0
- package/dist/plugins/MagicMenu/src/composables/private/useMenuItem.mjs +2 -2
- package/dist/plugins/MagicMenu/src/composables/private/useMenuKeyListener.mjs +4 -4
- 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/useMenuTrigger.d.ts +1 -3
- package/dist/plugins/MagicMenu/src/composables/private/useMenuTrigger.mjs +2 -180
- package/dist/plugins/MagicMenu/src/composables/private/useMenuView.d.ts +4 -3
- package/dist/plugins/MagicMenu/src/composables/private/useMenuView.mjs +28 -15
- 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 +9 -6
- package/dist/plugins/MagicMenu/src/utils/defaultOptions.mjs +3 -3
- package/dist/plugins/MagicPlayer/src/components/MagicPlayer.vue.d.ts +1 -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
|
>
|
|
@@ -44,9 +44,13 @@ import {
|
|
|
44
44
|
computed,
|
|
45
45
|
type MaybeRef,
|
|
46
46
|
type ComponentPublicInstance,
|
|
47
|
+
onBeforeUnmount,
|
|
47
48
|
} from 'vue'
|
|
48
|
-
import type { Placement } from '@floating-ui/vue'
|
|
49
49
|
import { useMenuView } from '../composables/private/useMenuView'
|
|
50
|
+
import { useMenuState } from '../composables/private/useMenuState'
|
|
51
|
+
import { useMenuCallback } from '../composables/private/useMenuCallback'
|
|
52
|
+
import { useMenuDOM } from '../composables/private/useMenuDOM'
|
|
53
|
+
import { useMenuCursor } from '../composables/private/useMenuCursor'
|
|
50
54
|
import {
|
|
51
55
|
MagicMenuInstanceId,
|
|
52
56
|
MagicMenuViewId,
|
|
@@ -55,16 +59,12 @@ import {
|
|
|
55
59
|
|
|
56
60
|
import '@maas/vue-equipment/utils/css/animations/fade-in.css'
|
|
57
61
|
import '@maas/vue-equipment/utils/css/animations/fade-out.css'
|
|
58
|
-
import { useMenuState } from '../composables/private/useMenuState'
|
|
59
|
-
import { useMenuCallback } from '../composables/private/useMenuCallback'
|
|
60
|
-
import { useMenuDOM } from '../composables/private/useMenuDOM'
|
|
61
62
|
|
|
62
63
|
defineOptions({
|
|
63
64
|
inheritAttrs: false,
|
|
64
65
|
})
|
|
65
66
|
|
|
66
67
|
interface MagicMenuContentProps {
|
|
67
|
-
placement?: Placement
|
|
68
68
|
arrow?: boolean | undefined
|
|
69
69
|
referenceEl?: MaybeRef<HTMLElement | ComponentPublicInstance>
|
|
70
70
|
}
|
|
@@ -103,6 +103,10 @@ const mappedTransition = computed(() => {
|
|
|
103
103
|
}
|
|
104
104
|
})
|
|
105
105
|
|
|
106
|
+
// Split isActive into two values to animate content smoothly
|
|
107
|
+
const innerActive = ref(false)
|
|
108
|
+
const wrapperActive = ref(false)
|
|
109
|
+
|
|
106
110
|
const { lockScroll, unlockScroll } = useMenuDOM()
|
|
107
111
|
const {
|
|
108
112
|
onBeforeEnter,
|
|
@@ -117,11 +121,22 @@ const {
|
|
|
117
121
|
viewId,
|
|
118
122
|
lockScroll,
|
|
119
123
|
unlockScroll,
|
|
124
|
+
wrapperActive,
|
|
120
125
|
})
|
|
121
126
|
|
|
122
|
-
//
|
|
123
|
-
const
|
|
124
|
-
const
|
|
127
|
+
// Handle cursor
|
|
128
|
+
const mappedClick = computed(() => view?.click)
|
|
129
|
+
const mappedPlacement = computed(() => view?.placement ?? 'bottom')
|
|
130
|
+
const mappedTrigger = computed(
|
|
131
|
+
() => document.querySelector(`[data-id="${viewId}-trigger"]`) as HTMLElement
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
const { destroy, initialize, isInsideTriangle, isInsideTo } = useMenuCursor({
|
|
135
|
+
from: mappedTrigger,
|
|
136
|
+
to: contentRef,
|
|
137
|
+
placement: mappedPlacement,
|
|
138
|
+
click: mappedClick,
|
|
139
|
+
})
|
|
125
140
|
|
|
126
141
|
// Handle state
|
|
127
142
|
async function onOpen() {
|
|
@@ -129,15 +144,20 @@ async function onOpen() {
|
|
|
129
144
|
await nextTick()
|
|
130
145
|
innerActive.value = true
|
|
131
146
|
await nextTick()
|
|
132
|
-
|
|
133
|
-
view.children.content = contentRef.value
|
|
134
|
-
}
|
|
147
|
+
initialize()
|
|
135
148
|
}
|
|
136
149
|
|
|
137
|
-
|
|
150
|
+
function onClose() {
|
|
151
|
+
destroy()
|
|
138
152
|
innerActive.value = false
|
|
139
|
-
|
|
140
|
-
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function disableCursor() {
|
|
156
|
+
state.input.disabled = [...state.input.disabled, 'pointer']
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function enableCursor() {
|
|
160
|
+
state.input.disabled = state.input.disabled.filter((x) => x !== 'pointer')
|
|
141
161
|
}
|
|
142
162
|
|
|
143
163
|
watch(
|
|
@@ -151,9 +171,34 @@ watch(
|
|
|
151
171
|
}
|
|
152
172
|
)
|
|
153
173
|
|
|
174
|
+
watch(isInsideTriangle, (value) => {
|
|
175
|
+
if (value) {
|
|
176
|
+
disableCursor()
|
|
177
|
+
} else {
|
|
178
|
+
enableCursor()
|
|
179
|
+
}
|
|
180
|
+
})
|
|
181
|
+
|
|
182
|
+
watch(isInsideTo, (value) => {
|
|
183
|
+
if (value) {
|
|
184
|
+
enableCursor()
|
|
185
|
+
} else {
|
|
186
|
+
switch (state.options.mode) {
|
|
187
|
+
case 'navigation':
|
|
188
|
+
if (!isInsideTriangle.value) {
|
|
189
|
+
view!.active = false
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
})
|
|
194
|
+
|
|
195
|
+
onBeforeUnmount(async () => {
|
|
196
|
+
destroy()
|
|
197
|
+
})
|
|
198
|
+
|
|
154
199
|
provide(MagicMenuContentId, `${viewId}-content`)
|
|
155
200
|
</script>
|
|
156
201
|
|
|
157
202
|
<style>
|
|
158
|
-
.magic-menu-content{-webkit-user-select:none;-moz-user-select:none;user-select:none}.magic-menu-content__inner{border:0;padding:0}.magic-menu-
|
|
203
|
+
.magic-menu-content{-webkit-user-select:none;-moz-user-select:none;user-select:none}.magic-menu-content__inner{border:0;padding:0}.magic-menu-content--initial-enter-active{animation:fade-in 0ms ease}.magic-menu-content--final-leave-active{animation:fade-out .2s ease}.magic-menu-content--nested-enter-active{animation:fade-in .3s ease}
|
|
159
204
|
</style>
|
|
@@ -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
|
}
|
|
@@ -161,7 +161,7 @@ const mappedReferenceEl = computed(() => {
|
|
|
161
161
|
},
|
|
162
162
|
}
|
|
163
163
|
} else {
|
|
164
|
-
return
|
|
164
|
+
return document.querySelector(`[data-id="${viewId}-trigger"]`)
|
|
165
165
|
}
|
|
166
166
|
})
|
|
167
167
|
|
|
@@ -221,5 +221,5 @@ const polygonPoints = computed(() => {
|
|
|
221
221
|
</script>
|
|
222
222
|
|
|
223
223
|
<style>
|
|
224
|
-
.magic-menu-float{display:flex
|
|
224
|
+
.magic-menu-float{display:flex}.magic-menu-float.-top{flex-direction:column-reverse}.magic-menu-float.-bottom{flex-direction:column}.magic-menu-float.-left{flex-direction:row-reverse}.magic-menu-float.-right{flex-direction:row}.magic-menu-float__arrow{color:var(--magic-menu-float-arrow-color,inherit);height:var(--magic-menu-float-arrow-height,.75rem);width:var(--magic-menu-float-arrow-width,.75rem)}.magic-menu-float__arrow svg{height:100%;width:100%}
|
|
225
225
|
</style>
|
|
@@ -0,0 +1,84 @@
|
|
|
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, watch } 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 { initializeChannel, deleteChannel } = useMenuChannel({
|
|
60
|
+
instanceId,
|
|
61
|
+
viewId,
|
|
62
|
+
})
|
|
63
|
+
let channel = initializeChannel({ id: mappedChannelId.value })
|
|
64
|
+
|
|
65
|
+
const { onClick, onMouseenter } = useMenuRemote({
|
|
66
|
+
viewId,
|
|
67
|
+
instanceId,
|
|
68
|
+
mappedChannelId,
|
|
69
|
+
mappedTrigger,
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
watch(
|
|
73
|
+
() => view?.active,
|
|
74
|
+
() => {
|
|
75
|
+
// Reset if parent view changes
|
|
76
|
+
deleteChannel(mappedChannelId.value)
|
|
77
|
+
channel = initializeChannel({ id: mappedChannelId.value })
|
|
78
|
+
}
|
|
79
|
+
)
|
|
80
|
+
</script>
|
|
81
|
+
|
|
82
|
+
<style>
|
|
83
|
+
.magic-menu-remote{cursor:var(--magic-menu-remote-cursor,pointer)}
|
|
84
|
+
</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
|
+
};
|
|
@@ -8,14 +8,13 @@
|
|
|
8
8
|
@click="onClick"
|
|
9
9
|
@contextmenu="onClick"
|
|
10
10
|
@mouseenter="onMouseenter"
|
|
11
|
-
@mouseleave="onMouseleave"
|
|
12
11
|
>
|
|
13
12
|
<slot :is-active="view?.active" :is-disabled="mappedDisabled" />
|
|
14
13
|
</div>
|
|
15
14
|
</template>
|
|
16
15
|
|
|
17
16
|
<script lang="ts" setup>
|
|
18
|
-
import { computed, inject, onBeforeUnmount, ref, watch } from 'vue'
|
|
17
|
+
import { computed, inject, onBeforeUnmount, ref, toValue, watch } from 'vue'
|
|
19
18
|
import { useMenuState } from '../composables/private/useMenuState'
|
|
20
19
|
import { useMenuView } from '../composables/private/useMenuView'
|
|
21
20
|
import { useMenuItem } from '../composables/private/useMenuItem'
|
|
@@ -27,6 +26,7 @@ import {
|
|
|
27
26
|
} from '../symbols'
|
|
28
27
|
|
|
29
28
|
import type { Interaction } from '../types'
|
|
29
|
+
import { onKeyStroke } from '@vueuse/core'
|
|
30
30
|
|
|
31
31
|
interface MagicMenuTriggerProps {
|
|
32
32
|
disabled?: boolean
|
|
@@ -68,16 +68,16 @@ const mappedTrigger = computed<Interaction[]>(() => {
|
|
|
68
68
|
switch (state.options.mode) {
|
|
69
69
|
case 'menubar':
|
|
70
70
|
return view?.parent.item
|
|
71
|
-
? ['mouseenter', '
|
|
72
|
-
:
|
|
73
|
-
|
|
74
|
-
return view?.parent.item
|
|
75
|
-
? ['mouseenter', 'mouseleave', 'click']
|
|
71
|
+
? ['mouseenter', 'click']
|
|
72
|
+
: state.active
|
|
73
|
+
? ['mouseenter', 'click']
|
|
76
74
|
: ['click']
|
|
75
|
+
case 'dropdown':
|
|
76
|
+
return view?.parent.item ? ['mouseenter', 'click'] : ['click']
|
|
77
77
|
case 'context':
|
|
78
|
-
return view?.parent.item
|
|
79
|
-
|
|
80
|
-
|
|
78
|
+
return view?.parent.item ? ['mouseenter', 'click'] : ['right-click']
|
|
79
|
+
case 'navigation':
|
|
80
|
+
return ['mouseenter']
|
|
81
81
|
}
|
|
82
82
|
})
|
|
83
83
|
|
|
@@ -89,32 +89,26 @@ const mappedTabindex = computed(() => {
|
|
|
89
89
|
}
|
|
90
90
|
})
|
|
91
91
|
|
|
92
|
-
const {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
})
|
|
101
|
-
|
|
102
|
-
// Initialize watcher
|
|
103
|
-
initialize()
|
|
92
|
+
const { onMouseenter, onClick, onEnter } = useMenuTrigger({
|
|
93
|
+
instanceId,
|
|
94
|
+
viewId,
|
|
95
|
+
itemId,
|
|
96
|
+
mappedDisabled,
|
|
97
|
+
mappedTrigger,
|
|
98
|
+
elRef,
|
|
99
|
+
})
|
|
104
100
|
|
|
105
101
|
watch(
|
|
106
|
-
|
|
107
|
-
(value) => {
|
|
108
|
-
if (
|
|
109
|
-
|
|
102
|
+
() => view?.active,
|
|
103
|
+
async (value) => {
|
|
104
|
+
if (value) {
|
|
105
|
+
await new Promise((resolve) => requestAnimationFrame(resolve))
|
|
106
|
+
toValue(elRef)?.blur()
|
|
110
107
|
}
|
|
111
|
-
}
|
|
112
|
-
{ immediate: true }
|
|
108
|
+
}
|
|
113
109
|
)
|
|
114
110
|
|
|
115
|
-
|
|
116
|
-
destroy()
|
|
117
|
-
})
|
|
111
|
+
onKeyStroke('Enter', onEnter)
|
|
118
112
|
</script>
|
|
119
113
|
|
|
120
114
|
<style>
|
|
@@ -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;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type MaybeRef } from 'vue';
|
|
1
|
+
import { type MaybeRef, type Ref } from 'vue';
|
|
2
2
|
import type { MenuState } from '../../types.js';
|
|
3
3
|
type UseMenuCallbackArgs = {
|
|
4
4
|
state: MenuState;
|
|
@@ -6,6 +6,7 @@ type UseMenuCallbackArgs = {
|
|
|
6
6
|
viewId: string;
|
|
7
7
|
lockScroll: () => void;
|
|
8
8
|
unlockScroll: () => void;
|
|
9
|
+
wrapperActive: Ref<boolean>;
|
|
9
10
|
};
|
|
10
11
|
export declare function useMenuCallback(args: UseMenuCallbackArgs): {
|
|
11
12
|
onBeforeEnter: (_el: Element) => void;
|