Skip to content

Commit f3eb01a

Browse files
committed
Add menu Transition support
1 parent a86b003 commit f3eb01a

8 files changed

+591
-563
lines changed

examples/views/BasicComponent.vue

+4-1
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,10 @@ export default defineComponent({
102102
zIndex: 3,
103103
minWidth: 230,
104104
x: 500,
105-
y: 200
105+
y: 200,
106+
//menuTransitionProps: {
107+
// name: 'fade',
108+
//}
106109
} as MenuOptions,
107110
}
108111
},

examples/views/BasicUseage.vue

+20-8
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ const menuData = reactive<MenuOptions>({
240240
label: 'Test item dynamic show and hide',
241241
clickClose: false,
242242
onClick: () => {
243-
menuData.items[4].hidden = !menuData.items[4].hidden;
243+
menuData.items![4].hidden = !menuData.items![4].hidden;
244244
},
245245
},
246246
{
@@ -251,10 +251,10 @@ const menuData = reactive<MenuOptions>({
251251
label: 'Test item dynamic change the label',
252252
clickClose: false,
253253
onClick: () => {
254-
if (menuData.items[5].label === 'Test item dynamic change the label')
255-
menuData.items[5].label = 'My label CHANGED!';
254+
if (menuData.items![5].label === 'Test item dynamic change the label')
255+
menuData.items![5].label = 'My label CHANGED!';
256256
else
257-
menuData.items[5].label = 'Test item dynamic change the label';
257+
menuData.items![5].label = 'Test item dynamic change the label';
258258
},
259259
},
260260
{
@@ -272,7 +272,7 @@ const menuData = reactive<MenuOptions>({
272272
children: [
273273
{
274274
label: "Left Top",
275-
direction: 'lt',
275+
direction: 'tl',
276276
children: [
277277
{ label: "Item1" },
278278
{ label: "Item2" },
@@ -290,7 +290,7 @@ const menuData = reactive<MenuOptions>({
290290
},
291291
{
292292
label: "Left Bottom",
293-
direction: 'lb',
293+
direction: 'bl',
294294
children: [
295295
{ label: "Item1" },
296296
{ label: "Item2" },
@@ -299,7 +299,7 @@ const menuData = reactive<MenuOptions>({
299299
},
300300
{
301301
label: "Right Top",
302-
direction: 'rt',
302+
direction: 'tr',
303303
children: [
304304
{ label: "Item1" },
305305
{ label: "Item2" },
@@ -395,6 +395,9 @@ const menuData = reactive<MenuOptions>({
395395
iconFontClass: 'iconfont',
396396
customClass: "class-a",
397397
keyboardControl: true,
398+
//menuTransitionProps: {
399+
// name: 'fade'
400+
//},
398401
zIndex: 3,
399402
minWidth: 230,
400403
x: 0,
@@ -410,7 +413,7 @@ function onContextMenu(e : MouseEvent) {
410413
menuData.x = e.x;
411414
menuData.y = e.y;
412415
//show our menu
413-
ContextMenu.showContextMenu(menuData);
416+
ContextMenu.showContextMenu(menuData as MenuOptions);
414417
}
415418
416419
function onContextMenu1(e : MouseEvent) {
@@ -489,4 +492,13 @@ function onContextMenu3(e : MouseEvent, direction: string) {
489492
.class-a {
490493
font-family: 'Times New Roman', Times, serif;
491494
}
495+
.fade-enter-active,
496+
.fade-leave-active {
497+
transition: opacity 0.25s ease;
498+
}
499+
500+
.fade-enter-from,
501+
.fade-leave-to {
502+
opacity: 0;
503+
}
492504
</style>

library/ContextMenu.vue

+13-13
Original file line numberDiff line numberDiff line change
@@ -44,24 +44,24 @@ export default defineComponent({
4444
4545
return () => {
4646
const { isNew, container, eleId } = genContainer(options.value);
47-
const vnode = show.value ? [ h(ContextSubMenuWrapperConstructor as unknown as string, {
48-
options: options,
49-
show: true,
50-
container: container,
51-
isFullScreenContainer: !isNew,
52-
'onUpdate:show': (v: boolean) => ctx.emit('update:show', v),
53-
onClose: (fromItem: undefined) => {
54-
ctx.emit('update:show', false);
55-
ctx.emit('close');
56-
options.value.onClose?.(fromItem);
57-
},
58-
}, ctx.slots) ] : [];
5947
6048
return [
6149
h(
6250
Teleport,
6351
{ to: `#${eleId}` },
64-
vnode
52+
[
53+
h(ContextSubMenuWrapperConstructor as unknown as string, {
54+
options: options,
55+
show: show,
56+
container: container,
57+
isFullScreenContainer: !isNew,
58+
onClose: (fromItem: undefined) => {
59+
ctx.emit('update:show', false);
60+
ctx.emit('close');
61+
options.value.onClose?.(fromItem);
62+
},
63+
}, ctx.slots)
64+
]
6565
)
6666
];
6767
}

library/ContextMenuDefine.ts

+9-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { SVGAttributes, VNode } from "vue";
1+
import type { SVGAttributes, TransitionProps, VNode } from "vue";
22

33
/**
44
* Default config
@@ -31,6 +31,8 @@ export interface ContextMenuInstance {
3131
}
3232

3333
export type MenuPopDirection = 'br'|'b'|'bl'|'tr'|'t'|'tl'|'l'|'r';
34+
export type MenuChildren = MenuItem[];
35+
3436

3537
export interface MenuOptions {
3638
/**
@@ -144,6 +146,11 @@ export interface MenuOptions {
144146
* Only for css font icon, If you use the svg icon, you do not need to use this.
145147
*/
146148
iconFontClass ?: string;
149+
/**
150+
* The Vue Transition props used when menu show or hide.
151+
* @default ''
152+
*/
153+
menuTransitionProps ?: TransitionProps;
147154
/**
148155
* Should a fixed-width icon area be reserved for menu items without icon. (global)
149156
*
@@ -362,7 +369,7 @@ export interface MenuItem {
362369
/**
363370
* Child menu items (Valid in function mode).
364371
*/
365-
children ?: MenuItem[],
372+
children ?: MenuChildren,
366373
}
367374

368375
export interface ContextMenuPositionData {

library/ContextMenuInstance.ts

+9-5
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import { h, render } from "vue";
1+
import { h, ref, render } from "vue";
22
import type { App, Slot } from "vue";
33
import type { ContextMenuInstance } from "./ContextMenuDefine";
44
import type { MenuOptions } from "./ContextMenuDefine";
5-
import { closeContextMenu } from "./ContextMenuMutex";
5+
import { checkOpenedContextMenu, closeContextMenu } from "./ContextMenuMutex";
66
import { genContainer, transformMenuPosition } from "./ContextMenuUtils";
77
import ContextMenuConstructor from './ContextMenu.vue'
88
import ContextSubMenuWrapperConstructor from './ContextSubMenuWrapper.vue'
@@ -17,14 +17,18 @@ function initInstance(
1717
isNew: boolean,
1818
customSlots?: Record<string, Slot>,
1919
) {
20+
const show = ref(true);
2021
const vnode = h(ContextSubMenuWrapperConstructor, {
2122
options: options,
22-
show: true,
23+
show: show,
2324
container: container,
2425
isFullScreenContainer: !isNew,
25-
onClose: (item: undefined) => {
26+
onCloseAnimFinished: () => {
2627
render(null, container);
28+
},
29+
onClose: (item: undefined) => {
2730
options.onClose?.(item);
31+
show.value = false;
2832
},
2933
}, customSlots);
3034
render(vnode, container);
@@ -117,7 +121,7 @@ export default {
117121
* Get if there is a menu open now.
118122
*/
119123
isAnyContextMenuOpen() {
120-
124+
return checkOpenedContextMenu();
121125
},
122126
/**
123127
* Close the currently open menu

0 commit comments

Comments
 (0)