0
# Functional API
1
2
The functional API provides programmatic control over context menus through global methods. This approach is ideal for dynamic menus, event-driven scenarios, and situations where you need full control over menu display and configuration.
3
4
## Capabilities
5
6
### Show Context Menu
7
8
Display a context menu at specified coordinates with configurable options and menu items.
9
10
```typescript { .api }
11
/**
12
* Show a context menu programmatically
13
* @param options - Menu configuration including position, items, and display options
14
* @param customSlots - Optional custom rendering slots for menu components
15
* @returns ContextMenuInstance for controlling the displayed menu
16
*/
17
function showContextMenu(
18
options: MenuOptions,
19
customSlots?: Record<string, Slot>
20
): ContextMenuInstance;
21
```
22
23
**Usage Examples:**
24
25
```typescript
26
import ContextMenu from '@imengyu/vue3-context-menu';
27
28
// Basic context menu
29
function showBasicMenu(e: MouseEvent) {
30
e.preventDefault();
31
32
ContextMenu.showContextMenu({
33
x: e.x,
34
y: e.y,
35
items: [
36
{ label: "Open", onClick: () => console.log("Open clicked") },
37
{ label: "Save", onClick: () => console.log("Save clicked") },
38
{ divided: true, label: "Exit", onClick: () => console.log("Exit clicked") }
39
]
40
});
41
}
42
43
// Advanced menu with theming and configuration
44
function showAdvancedMenu(e: MouseEvent) {
45
e.preventDefault();
46
47
const menuInstance = ContextMenu.showContextMenu({
48
x: e.x,
49
y: e.y,
50
theme: 'win10 dark',
51
minWidth: 200,
52
maxHeight: 400,
53
keyboardControl: true,
54
adjustPosition: true,
55
items: [
56
{
57
label: "File Operations",
58
icon: "folder-icon",
59
children: [
60
{ label: "New File", shortcut: "Ctrl+N", onClick: createFile },
61
{ label: "Open File", shortcut: "Ctrl+O", onClick: openFile },
62
{ divided: true, label: "Recent Files", children: getRecentFiles() }
63
]
64
},
65
{ label: "Edit", disabled: !canEdit, onClick: editHandler }
66
],
67
onClose: (lastItem) => {
68
if (lastItem) {
69
console.log(`Menu closed after clicking: ${lastItem.label}`);
70
}
71
}
72
});
73
74
// You can control the menu instance
75
setTimeout(() => {
76
if (!menuInstance.isClosed()) {
77
menuInstance.closeMenu();
78
}
79
}, 5000);
80
}
81
82
// Menu with custom rendering slots
83
function showCustomMenu(e: MouseEvent) {
84
ContextMenu.showContextMenu({
85
x: e.x,
86
y: e.y,
87
items: [{ label: "Custom Item", icon: "star" }]
88
}, {
89
// Custom item renderer
90
itemRender: ({ label, icon, onClick, onMouseEnter, disabled }) => [
91
h('div', {
92
class: `my-custom-item ${disabled ? 'disabled' : ''}`,
93
onClick: onClick,
94
onMouseenter: onMouseEnter
95
}, [
96
icon ? h('img', { src: icon, class: 'custom-icon' }) : null,
97
h('span', { class: 'custom-label' }, label)
98
])
99
]
100
});
101
}
102
```
103
104
### Close Context Menu
105
106
Close the currently open context menu programmatically.
107
108
```typescript { .api }
109
/**
110
* Close the currently open context menu
111
*/
112
function closeContextMenu(): void;
113
```
114
115
**Usage:**
116
117
```typescript
118
import ContextMenu from '@imengyu/vue3-context-menu';
119
120
// Close menu after some action
121
function handleAction() {
122
performAction();
123
ContextMenu.closeContextMenu();
124
}
125
126
// Close menu on escape key
127
document.addEventListener('keydown', (e) => {
128
if (e.key === 'Escape' && ContextMenu.isAnyContextMenuOpen()) {
129
ContextMenu.closeContextMenu();
130
}
131
});
132
```
133
134
### Check Menu Status
135
136
Check if any context menu is currently open.
137
138
```typescript { .api }
139
/**
140
* Check if any context menu is currently open
141
* @returns true if a context menu is open, false otherwise
142
*/
143
function isAnyContextMenuOpen(): boolean;
144
```
145
146
**Usage:**
147
148
```typescript
149
import ContextMenu from '@imengyu/vue3-context-menu';
150
151
// Conditional logic based on menu state
152
function handleGlobalClick() {
153
if (ContextMenu.isAnyContextMenuOpen()) {
154
// Don't perform action if menu is open
155
return;
156
}
157
158
performGlobalAction();
159
}
160
161
// Prevent multiple menus
162
function showMenuIfNoneOpen(e: MouseEvent) {
163
if (!ContextMenu.isAnyContextMenuOpen()) {
164
ContextMenu.showContextMenu({
165
x: e.x,
166
y: e.y,
167
items: getMenuItems()
168
});
169
}
170
}
171
```
172
173
### Transform Menu Position
174
175
Transform menu display position for scaled containers or special positioning needs.
176
177
```typescript { .api }
178
/**
179
* Transform menu position for scaled containers
180
* @param element - Target element for position calculation
181
* @param x - X coordinate relative to element
182
* @param y - Y coordinate relative to element
183
* @param container - Optional container element for position calculation
184
* @returns Transformed coordinates for menu display
185
*/
186
function transformMenuPosition(
187
element: HTMLElement,
188
x: number,
189
y: number,
190
container?: HTMLElement
191
): { x: number, y: number };
192
```
193
194
**Usage:**
195
196
```typescript
197
import ContextMenu from '@imengyu/vue3-context-menu';
198
199
// Handle scaled containers
200
function onContextMenuInScaledContainer(e: MouseEvent) {
201
e.preventDefault();
202
203
const target = e.target as HTMLElement;
204
const scaledContainer = document.getElementById('scaled-container');
205
206
// Transform position to account for scaling
207
const position = ContextMenu.transformMenuPosition(
208
target,
209
e.offsetX,
210
e.offsetY,
211
scaledContainer
212
);
213
214
ContextMenu.showContextMenu({
215
x: position.x,
216
y: position.y,
217
items: getMenuItems(),
218
getContainer: () => scaledContainer
219
});
220
}
221
```
222
223
## Configuration Options
224
225
### MenuOptions Interface
226
227
Complete configuration interface for context menu display and behavior.
228
229
```typescript { .api }
230
interface MenuOptions {
231
/** Array of menu items to display */
232
items?: MenuItem[];
233
/** X coordinate for menu display */
234
x: number;
235
/** Y coordinate for menu display */
236
y: number;
237
/** X-coordinate offset between submenu and parent */
238
xOffset?: number;
239
/** Y-coordinate offset between submenu and parent */
240
yOffset?: number;
241
/** Menu popup direction relative to coordinates */
242
direction?: MenuPopDirection;
243
/** Z-index for menu display */
244
zIndex?: number;
245
/** Zoom level for menu display */
246
zoom?: number;
247
/** Custom CSS class for menu styling */
248
customClass?: string;
249
/** Enable mouse scroll in menu area */
250
mouseScroll?: boolean;
251
/** Reserve space for up/down scroll buttons */
252
updownButtonSpaceholder?: boolean;
253
/** Theme name for menu styling */
254
theme?: string;
255
/** Class name to ignore click events */
256
ignoreClickClassName?: string;
257
/** Close menu when clicking outside */
258
clickCloseOnOutside?: boolean;
259
/** Class name that closes menu when clicked */
260
clickCloseClassName?: string;
261
/** Custom icon font class name */
262
iconFontClass?: string;
263
/** Vue transition properties for menu animations */
264
menuTransitionProps?: TransitionProps;
265
/** Reserve icon width for items without icons */
266
preserveIconWidth?: boolean;
267
/** Enable keyboard navigation control */
268
keyboardControl?: boolean;
269
/** Maximum menu width in pixels */
270
maxWidth?: number;
271
/** Maximum menu height in pixels */
272
maxHeight?: number;
273
/** Minimum menu width in pixels */
274
minWidth?: number;
275
/** Close menu when user scrolls */
276
closeWhenScroll?: boolean;
277
/** Padding for submenu position adjustment */
278
adjustPadding?: { x: number, y: number } | number;
279
/** Automatically adjust menu position to prevent overflow */
280
adjustPosition?: boolean;
281
/** Custom container element for menu mounting */
282
getContainer?: HTMLElement | (() => HTMLElement);
283
/** Callback when menu is closing */
284
onClose?: (lastClickItem: MenuItem | undefined) => void;
285
/** Callback when user clicks outside (when clickCloseOnOutside is false) */
286
onClickOnOutside?: (e: MouseEvent) => void;
287
/** Callback for left keyboard focus movement (MenuBar use) */
288
onKeyFocusMoveLeft?: () => void;
289
/** Callback for right keyboard focus movement (MenuBar use) */
290
onKeyFocusMoveRight?: () => void;
291
}
292
```
293
294
### MenuItem Interface
295
296
Configuration for individual menu items including appearance, behavior, and submenu support.
297
298
```typescript { .api }
299
interface MenuItem {
300
/** Menu item label text or custom render function */
301
label?: string | VNode | ((label: string) => VNode);
302
/** Menu item icon (CSS class, image path, or VNode) */
303
icon?: string | VNode | ((icon: string) => VNode);
304
/** Custom icon font class name */
305
iconFontClass?: string;
306
/** Reserve icon width for this item */
307
preserveIconWidth?: boolean;
308
/** SVG symbol icon reference */
309
svgIcon?: string;
310
/** SVG element properties */
311
svgProps?: SVGAttributes;
312
/** Disable menu item */
313
disabled?: boolean | ComputedRef<boolean>;
314
/** Hide menu item */
315
hidden?: boolean | ComputedRef<boolean>;
316
/** Show check mark on menu item */
317
checked?: boolean | ComputedRef<boolean>;
318
/** Shortcut key text display */
319
shortcut?: string;
320
/** Submenu popup direction */
321
direction?: MenuPopDirection;
322
/** Auto-adjust submenu position */
323
adjustSubMenuPosition?: boolean;
324
/** Allow click event when item has children */
325
clickableWhenHasChildren?: boolean;
326
/** Close menu when this item is clicked */
327
clickClose?: boolean;
328
/** Separator configuration */
329
divided?: boolean | 'up' | 'down' | 'self';
330
/** Custom CSS class for item */
331
customClass?: string;
332
/** Maximum height for submenu */
333
maxHeight?: number;
334
/** Maximum width for submenu */
335
maxWidth?: number | string;
336
/** Minimum width for submenu */
337
minWidth?: number | string;
338
/** Click event handler */
339
onClick?: (e?: MouseEvent | KeyboardEvent) => void;
340
/** Submenu close event handler */
341
onSubMenuClose?: (itemInstance?: MenuItemContext) => void;
342
/** Submenu open event handler */
343
onSubMenuOpen?: (itemInstance?: MenuItemContext) => void;
344
/** Custom render function for item */
345
customRender?: VNode | ((item: MenuItem) => VNode);
346
/** Child menu items for submenu */
347
children?: MenuItem[];
348
}
349
```
350
351
## Context Menu Instance
352
353
The returned instance from `showContextMenu` provides methods to control the displayed menu.
354
355
```typescript { .api }
356
interface ContextMenuInstance {
357
/** Close the menu programmatically */
358
closeMenu(fromItem?: MenuItem | undefined): void;
359
/** Check if the menu is currently closed */
360
isClosed(): boolean;
361
/** Get the root menu instance for advanced control */
362
getMenuRef(): ContextSubMenuInstance | undefined;
363
/** Get menu dimensions in pixels */
364
getMenuDimensions(): { width: number, height: number };
365
}
366
367
interface ContextSubMenuInstance {
368
/** Get root element of submenu */
369
getSubmenuRoot(): HTMLElement | undefined;
370
/** Get inner container element */
371
getMenu(): HTMLElement | undefined;
372
/** Get child menu item by index */
373
getChildItem(index: number): MenuItemContext | undefined;
374
/** Get submenu dimensions */
375
getMenuDimensions(): { width: number, height: number };
376
/** Get/set scroll position */
377
getScrollValue(): number;
378
setScrollValue(v: number): void;
379
/** Get maximum scroll height */
380
getScrollHeight(): number;
381
/** Force position adjustment */
382
adjustPosition(): void;
383
/** Get maximum submenu height */
384
getMaxHeight(): number;
385
/** Get/set submenu position */
386
getPosition(): { x: number, y: number };
387
setPosition(x: number, y: number): void;
388
}
389
```