@vaadin/context-menu 25.2.0-alpha8 → 25.2.0-beta1
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/custom-elements.json +94 -7
- package/package.json +13 -13
- package/src/vaadin-context-menu-item.js +5 -3
- package/src/vaadin-context-menu-list-box.js +0 -3
- package/src/vaadin-context-menu-mixin.js +28 -21
- package/src/vaadin-context-menu-overlay.js +0 -4
- package/src/vaadin-context-menu-tooltip-controller.js +81 -0
- package/src/vaadin-context-menu.d.ts +28 -0
- package/src/vaadin-context-menu.js +31 -12
- package/src/vaadin-contextmenu-event.js +1 -1
- package/src/vaadin-contextmenu-items-mixin.d.ts +25 -0
- package/src/vaadin-contextmenu-items-mixin.js +68 -11
- package/src/vaadin-menu-overlay-mixin.js +1 -4
- package/web-types.json +20 -28
- package/web-types.lit.json +17 -3
package/custom-elements.json
CHANGED
|
@@ -29,7 +29,11 @@
|
|
|
29
29
|
{
|
|
30
30
|
"kind": "method",
|
|
31
31
|
"name": "close",
|
|
32
|
-
"description": "Closes the overlay."
|
|
32
|
+
"description": "Closes the overlay.",
|
|
33
|
+
"inheritedFrom": {
|
|
34
|
+
"name": "ItemsMixin",
|
|
35
|
+
"module": "src/vaadin-contextmenu-items-mixin.js"
|
|
36
|
+
}
|
|
33
37
|
},
|
|
34
38
|
{
|
|
35
39
|
"kind": "field",
|
|
@@ -48,7 +52,7 @@
|
|
|
48
52
|
"type": {
|
|
49
53
|
"text": "!Array<!ContextMenuItem> | undefined"
|
|
50
54
|
},
|
|
51
|
-
"description": "Defines a (hierarchical) menu structure for the component.\nIf a menu item has a non-empty `children` set, a sub-menu with the child items is opened\nnext to the parent menu on mouseover, tap or a right arrow keypress.\n\nThe items API can't be used together with a renderer!\n\n#### Example\n\n```javascript\ncontextMenu.items = [\n { text: 'Menu Item 1', theme: 'primary', className: 'first', children:\n [\n { text: 'Menu Item 1-1', checked: true, keepOpen: true },\n { text: 'Menu Item 1-2' }\n ]\n },\n { component: 'hr' },\n { text: 'Menu Item 2', children:\n [\n { text: 'Menu Item 2-1' },\n { text: 'Menu Item 2-2', disabled: true }\n ]\n },\n { text: 'Menu Item 3', disabled: true, className: 'last' }\n];\n```",
|
|
55
|
+
"description": "Defines a (hierarchical) menu structure for the component.\nIf a menu item has a non-empty `children` set, a sub-menu with the child items is opened\nnext to the parent menu on mouseover, tap or a right arrow keypress.\n\nThe items API can't be used together with a renderer!\n\n#### Example\n\n```javascript\ncontextMenu.items = [\n { text: 'Menu Item 1', theme: 'primary', className: 'first', children:\n [\n { text: 'Menu Item 1-1', checked: true, keepOpen: true },\n { text: 'Menu Item 1-2' }\n ]\n },\n { component: 'hr' },\n { text: 'Menu Item 2', children:\n [\n { text: 'Menu Item 2-1' },\n { text: 'Menu Item 2-2', disabled: true }\n ]\n },\n { text: 'Menu Item 3', disabled: true, className: 'last' }\n];\n```\n\n#### Item tooltips\n\nMenu items can have tooltips that are shown on hover and keyboard\nfocus. To enable them, add a slotted `<vaadin-tooltip>` element\nand set the `tooltip` property on each item that should have one:\n\n```html\n<vaadin-context-menu>\n <vaadin-tooltip slot=\"tooltip\"></vaadin-tooltip>\n</vaadin-context-menu>\n```",
|
|
52
56
|
"attribute": "items",
|
|
53
57
|
"inheritedFrom": {
|
|
54
58
|
"name": "ItemsMixin",
|
|
@@ -230,13 +234,92 @@
|
|
|
230
234
|
}
|
|
231
235
|
]
|
|
232
236
|
},
|
|
237
|
+
{
|
|
238
|
+
"kind": "javascript-module",
|
|
239
|
+
"path": "src/vaadin-context-menu-tooltip-controller.js",
|
|
240
|
+
"declarations": [
|
|
241
|
+
{
|
|
242
|
+
"kind": "class",
|
|
243
|
+
"description": "Controller for the tooltip slotted into `<vaadin-context-menu>`. Configures\nthe tooltip in manual mode and drives its target, context, and position\nbased on the currently hovered or focused item.",
|
|
244
|
+
"name": "ContextMenuTooltipController",
|
|
245
|
+
"members": [
|
|
246
|
+
{
|
|
247
|
+
"kind": "method",
|
|
248
|
+
"name": "bringToFront"
|
|
249
|
+
},
|
|
250
|
+
{
|
|
251
|
+
"kind": "method",
|
|
252
|
+
"name": "close",
|
|
253
|
+
"parameters": [
|
|
254
|
+
{
|
|
255
|
+
"name": "immediate",
|
|
256
|
+
"type": {
|
|
257
|
+
"text": "boolean"
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
]
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
"kind": "method",
|
|
264
|
+
"name": "initCustomNode",
|
|
265
|
+
"parameters": [
|
|
266
|
+
{
|
|
267
|
+
"name": "tooltipNode"
|
|
268
|
+
}
|
|
269
|
+
]
|
|
270
|
+
},
|
|
271
|
+
{
|
|
272
|
+
"kind": "method",
|
|
273
|
+
"name": "open",
|
|
274
|
+
"parameters": [
|
|
275
|
+
{
|
|
276
|
+
"name": "{ trigger }"
|
|
277
|
+
},
|
|
278
|
+
{
|
|
279
|
+
"name": "options",
|
|
280
|
+
"type": {
|
|
281
|
+
"text": "{ trigger: 'hover' | 'focus' }"
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
]
|
|
285
|
+
},
|
|
286
|
+
{
|
|
287
|
+
"kind": "method",
|
|
288
|
+
"name": "setTarget",
|
|
289
|
+
"parameters": [
|
|
290
|
+
{
|
|
291
|
+
"name": "target",
|
|
292
|
+
"type": {
|
|
293
|
+
"text": "HTMLElement | null"
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
]
|
|
297
|
+
}
|
|
298
|
+
],
|
|
299
|
+
"superclass": {
|
|
300
|
+
"name": "SlotController",
|
|
301
|
+
"package": "@vaadin/component-base/src/slot-controller.js"
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
],
|
|
305
|
+
"exports": [
|
|
306
|
+
{
|
|
307
|
+
"kind": "js",
|
|
308
|
+
"name": "ContextMenuTooltipController",
|
|
309
|
+
"declaration": {
|
|
310
|
+
"name": "ContextMenuTooltipController",
|
|
311
|
+
"module": "src/vaadin-context-menu-tooltip-controller.js"
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
]
|
|
315
|
+
},
|
|
233
316
|
{
|
|
234
317
|
"kind": "javascript-module",
|
|
235
318
|
"path": "src/vaadin-context-menu.js",
|
|
236
319
|
"declarations": [
|
|
237
320
|
{
|
|
238
321
|
"kind": "class",
|
|
239
|
-
"description": "`<vaadin-context-menu>` is a Web Component for creating context menus.\n\n### Items\n\nItems is a higher level convenience API for defining a (hierarchical) menu structure for the component.\nIf a menu item has a non-empty `children` set, a sub-menu with the child items is opened\nnext to the parent menu on mouseover, tap or a right arrow keypress.\n\nWhen an item is selected, `<vaadin-context-menu>` dispatches an \"item-selected\" event\nwith the selected item as `event.detail.value` property.\nIf item does not have `keepOpen` property the menu will be closed.\n\n```javascript\ncontextMenu.items = [\n { text: 'Menu Item 1', theme: 'primary', className: 'first', children:\n [\n { text: 'Menu Item 1-1', checked: true, keepOpen: true },\n { text: 'Menu Item 1-2' }\n ]\n },\n { component: 'hr' },\n { text: 'Menu Item 2', children:\n [\n { text: 'Menu Item 2-1' },\n { text: 'Menu Item 2-2', disabled: true }\n ]\n },\n { text: 'Menu Item 3', disabled: true, className: 'last' }\n];\n\ncontextMenu.addEventListener('item-selected', e => {\n const item = e.detail.value;\n console.log(`${item.text} selected`);\n});\n```\n\n**NOTE:** when the `items` array is defined, the renderer cannot be used.\n\n### Rendering\n\nThe content of the menu can be populated by using the renderer callback function.\n\nThe renderer function provides `root`, `contextMenu`, `model` arguments when applicable.\nGenerate DOM content by using `model` object properties if needed, append it to the `root`\nelement and control the state of the host element by accessing `contextMenu`. Before generating\nnew content, the renderer function should check if there is already content in `root` for reusing it.\n\n```html\n<vaadin-context-menu id=\"contextMenu\">\n <p>This paragraph has a context menu.</p>\n</vaadin-context-menu>\n```\n```js\nconst contextMenu = document.querySelector('#contextMenu');\ncontextMenu.renderer = (root, contextMenu, context) => {\n let listBox = root.firstElementChild;\n if (!listBox) {\n listBox = document.createElement('vaadin-list-box');\n root.appendChild(listBox);\n }\n\n let item = listBox.querySelector('vaadin-item');\n if (!item) {\n item = document.createElement('vaadin-item');\n listBox.appendChild(item);\n }\n item.textContent = 'Content of the selector: ' + context.target.textContent;\n};\n```\n\nYou can access the menu context inside the renderer using\n`context.target` and `context.detail`.\n\nRenderer is called on the opening of the context-menu and each time the related context is updated.\nDOM generated during the renderer call can be reused\nin the next renderer call and will be provided with the `root` argument.\nOn first call it will be empty.\n\n### `vaadin-contextmenu` Gesture Event\n\n`vaadin-contextmenu` is a gesture event (a custom event),\nwhich is dispatched after either `contextmenu` or long touch events.\nThis enables support for both mouse and touch environments in a uniform way.\n\n`<vaadin-context-menu>` opens the menu overlay on the `vaadin-contextmenu`\nevent by default.\n\n### Menu Listener\n\nBy default, the `<vaadin-context-menu>` element listens for the menu opening\nevent on itself. In case if you do not want to wrap the target, you can listen for\nevents on an element outside the `<vaadin-context-menu>` by setting the\n`listenOn` property:\n\n```html\n<vaadin-context-menu id=\"contextMenu\"></vaadin-context-menu>\n\n<div id=\"menuListener\">The element that listens for the contextmenu event.</div>\n```\n```javascript\nconst contextMenu = document.querySelector('#contextMenu');\ncontextMenu.listenOn = document.querySelector('#menuListener');\n```\n\n### Filtering Menu Targets\n\nBy default, the listener element and all its descendants open the context\nmenu. You can filter the menu targets to a smaller set of elements inside\nthe listener element by setting the `selector` property.\n\nIn the following example, only the elements matching `.has-menu` will open the context menu:\n\n```html\n<vaadin-context-menu selector=\".has-menu\">\n <p class=\"has-menu\">This paragraph opens the context menu</p>\n <p>This paragraph does not open the context menu</p>\n</vaadin-context-menu>\n```\n\n### Menu Context\n\nThe following properties are available in the `context` argument:\n\n- `target` is the menu opening event target, which is the element that\nthe user has called the context menu for\n- `detail` is the menu opening event detail\n\nIn the following example, the menu item text is composed with the contents\nof the element that opened the menu:\n\n```html\n<vaadin-context-menu selector=\"li\" id=\"contextMenu\">\n <ul>\n <li>Foo</li>\n <li>Bar</li>\n <li>Baz</li>\n </ul>\n</vaadin-context-menu>\n```\n```js\nconst contextMenu = document.querySelector('#contextMenu');\ncontextMenu.renderer = (root, contextMenu, context) => {\n let listBox = root.firstElementChild;\n if (!listBox) {\n listBox = document.createElement('vaadin-list-box');\n root.appendChild(listBox);\n }\n\n let item = listBox.querySelector('vaadin-item');\n if (!item) {\n item = document.createElement('vaadin-item');\n listBox.appendChild(item);\n }\n item.textContent = 'The menu target: ' + context.target.textContent;\n};\n```\n\n### Styling\n\nThe following shadow DOM parts are available for styling:\n\nPart name | Description\n-----------------|-------------------------------------------\n`backdrop` | Backdrop of the overlay\n`overlay` | The overlay container\n`content` | The overlay content\n\n### Custom CSS Properties\n\nThe following custom CSS properties are available for styling:\n\nCustom CSS property | Description\n--------------------------------------|-------------\n`--vaadin-context-menu-offset-top` | Used as an offset when using `position` and the context menu is aligned vertically below the target\n`--vaadin-context-menu-offset-bottom` | Used as an offset when using `position` and the context menu is aligned vertically above the target\n`--vaadin-context-menu-offset-start` | Used as an offset when using `position` and the context menu is aligned horizontally after the target\n`--vaadin-context-menu-offset-end` | Used as an offset when using `position` and the context menu is aligned horizontally before the target\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.\n\n### Internal components\n\nWhen using `items` API the following internal components are themable:\n\n- `<vaadin-context-menu-item>` - has the same API as [`<vaadin-item>`](#/elements/vaadin-item).\n- `<vaadin-context-menu-list-box>` - has the same API as [`<vaadin-list-box>`](#/elements/vaadin-list-box).\n\nThe `<vaadin-context-menu-item>` sub-menu elements have the following additional state attributes\non top of the built-in `<vaadin-item>` state attributes:\n\nAttribute | Description\n---------- |-------------\n`expanded` | Expanded parent item.",
|
|
322
|
+
"description": "`<vaadin-context-menu>` is a Web Component for creating context menus.\n\n### Items\n\nItems is a higher level convenience API for defining a (hierarchical) menu structure for the component.\nIf a menu item has a non-empty `children` set, a sub-menu with the child items is opened\nnext to the parent menu on mouseover, tap or a right arrow keypress.\n\nWhen an item is selected, `<vaadin-context-menu>` dispatches an \"item-selected\" event\nwith the selected item as `event.detail.value` property.\nIf item does not have `keepOpen` property the menu will be closed.\n\n```javascript\ncontextMenu.items = [\n { text: 'Menu Item 1', theme: 'primary', className: 'first', children:\n [\n { text: 'Menu Item 1-1', checked: true, keepOpen: true },\n { text: 'Menu Item 1-2' }\n ]\n },\n { component: 'hr' },\n { text: 'Menu Item 2', children:\n [\n { text: 'Menu Item 2-1' },\n { text: 'Menu Item 2-2', disabled: true }\n ]\n },\n { text: 'Menu Item 3', disabled: true, className: 'last' }\n];\n\ncontextMenu.addEventListener('item-selected', e => {\n const item = e.detail.value;\n console.log(`${item.text} selected`);\n});\n```\n\n**NOTE:** when the `items` array is defined, the renderer cannot be used.\n\n#### Disabled menu items\n\nWhen disabled, menu items are rendered as \"dimmed\".\n\nBy default, disabled items are not focusable and don't react to hover.\nAs a result, they are hidden from assistive technologies, and it's not\npossible to show a tooltip to explain why they are disabled. This can\nbe addressed by enabling the feature flag `accessibleDisabledMenuItems`,\nwhich makes disabled items focusable and hoverable, while still\npreventing them from being activated:\n\n```js\n// Set before any context menu is attached to the DOM.\nwindow.Vaadin.featureFlags.accessibleDisabledMenuItems = true;\n```\n\n#### Item tooltips\n\nMenu items can have tooltips that are shown on hover and keyboard\nfocus. To enable them, add a slotted `<vaadin-tooltip>` element\nand set the `tooltip` property on each item that should have one:\n\n```html\n<vaadin-context-menu>\n <vaadin-tooltip slot=\"tooltip\"></vaadin-tooltip>\n</vaadin-context-menu>\n```\n\n### Rendering\n\nThe content of the menu can be populated by using the renderer callback function.\n\nThe renderer function provides `root`, `contextMenu`, `model` arguments when applicable.\nGenerate DOM content by using `model` object properties if needed, append it to the `root`\nelement and control the state of the host element by accessing `contextMenu`. Before generating\nnew content, the renderer function should check if there is already content in `root` for reusing it.\n\n```html\n<vaadin-context-menu id=\"contextMenu\">\n <p>This paragraph has a context menu.</p>\n</vaadin-context-menu>\n```\n```js\nconst contextMenu = document.querySelector('#contextMenu');\ncontextMenu.renderer = (root, contextMenu, context) => {\n let listBox = root.firstElementChild;\n if (!listBox) {\n listBox = document.createElement('vaadin-list-box');\n root.appendChild(listBox);\n }\n\n let item = listBox.querySelector('vaadin-item');\n if (!item) {\n item = document.createElement('vaadin-item');\n listBox.appendChild(item);\n }\n item.textContent = 'Content of the selector: ' + context.target.textContent;\n};\n```\n\nYou can access the menu context inside the renderer using\n`context.target` and `context.detail`.\n\nRenderer is called on the opening of the context-menu and each time the related context is updated.\nDOM generated during the renderer call can be reused\nin the next renderer call and will be provided with the `root` argument.\nOn first call it will be empty.\n\n### `vaadin-contextmenu` Gesture Event\n\n`vaadin-contextmenu` is a gesture event (a custom event),\nwhich is dispatched after either `contextmenu` or long touch events.\nThis enables support for both mouse and touch environments in a uniform way.\n\n`<vaadin-context-menu>` opens the menu overlay on the `vaadin-contextmenu`\nevent by default.\n\n### Menu Listener\n\nBy default, the `<vaadin-context-menu>` element listens for the menu opening\nevent on itself. In case if you do not want to wrap the target, you can listen for\nevents on an element outside the `<vaadin-context-menu>` by setting the\n`listenOn` property:\n\n```html\n<vaadin-context-menu id=\"contextMenu\"></vaadin-context-menu>\n\n<div id=\"menuListener\">The element that listens for the contextmenu event.</div>\n```\n```javascript\nconst contextMenu = document.querySelector('#contextMenu');\ncontextMenu.listenOn = document.querySelector('#menuListener');\n```\n\n### Filtering Menu Targets\n\nBy default, the listener element and all its descendants open the context\nmenu. You can filter the menu targets to a smaller set of elements inside\nthe listener element by setting the `selector` property.\n\nIn the following example, only the elements matching `.has-menu` will open the context menu:\n\n```html\n<vaadin-context-menu selector=\".has-menu\">\n <p class=\"has-menu\">This paragraph opens the context menu</p>\n <p>This paragraph does not open the context menu</p>\n</vaadin-context-menu>\n```\n\n### Menu Context\n\nThe following properties are available in the `context` argument:\n\n- `target` is the menu opening event target, which is the element that\nthe user has called the context menu for\n- `detail` is the menu opening event detail\n\nIn the following example, the menu item text is composed with the contents\nof the element that opened the menu:\n\n```html\n<vaadin-context-menu selector=\"li\" id=\"contextMenu\">\n <ul>\n <li>Foo</li>\n <li>Bar</li>\n <li>Baz</li>\n </ul>\n</vaadin-context-menu>\n```\n```js\nconst contextMenu = document.querySelector('#contextMenu');\ncontextMenu.renderer = (root, contextMenu, context) => {\n let listBox = root.firstElementChild;\n if (!listBox) {\n listBox = document.createElement('vaadin-list-box');\n root.appendChild(listBox);\n }\n\n let item = listBox.querySelector('vaadin-item');\n if (!item) {\n item = document.createElement('vaadin-item');\n listBox.appendChild(item);\n }\n item.textContent = 'The menu target: ' + context.target.textContent;\n};\n```\n\n### Styling\n\nThe following shadow DOM parts are available for styling:\n\nPart name | Description\n-----------------|-------------------------------------------\n`backdrop` | Backdrop of the overlay\n`overlay` | The overlay container\n`content` | The overlay content\n\n### Custom CSS Properties\n\nThe following custom CSS properties are available for styling:\n\nCustom CSS property | Description\n--------------------------------------|-------------\n`--vaadin-context-menu-offset-top` | Used as an offset when using `position` and the context menu is aligned vertically below the target\n`--vaadin-context-menu-offset-bottom` | Used as an offset when using `position` and the context menu is aligned vertically above the target\n`--vaadin-context-menu-offset-start` | Used as an offset when using `position` and the context menu is aligned horizontally after the target\n`--vaadin-context-menu-offset-end` | Used as an offset when using `position` and the context menu is aligned horizontally before the target\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.\n\n### Internal components\n\nWhen using `items` API the following internal components are themable:\n\n- `<vaadin-context-menu-item>` - has the same API as [`<vaadin-item>`](#/elements/vaadin-item).\n- `<vaadin-context-menu-list-box>` - has the same API as [`<vaadin-list-box>`](#/elements/vaadin-list-box).\n\nThe `<vaadin-context-menu-item>` sub-menu elements have the following additional state attributes\non top of the built-in `<vaadin-item>` state attributes:\n\nAttribute | Description\n---------- |-------------\n`expanded` | Expanded parent item.",
|
|
240
323
|
"name": "ContextMenu",
|
|
241
324
|
"members": [
|
|
242
325
|
{
|
|
@@ -244,8 +327,8 @@
|
|
|
244
327
|
"name": "close",
|
|
245
328
|
"description": "Closes the overlay.",
|
|
246
329
|
"inheritedFrom": {
|
|
247
|
-
"name": "
|
|
248
|
-
"module": "src/vaadin-
|
|
330
|
+
"name": "ItemsMixin",
|
|
331
|
+
"module": "src/vaadin-contextmenu-items-mixin.js"
|
|
249
332
|
}
|
|
250
333
|
},
|
|
251
334
|
{
|
|
@@ -269,7 +352,7 @@
|
|
|
269
352
|
"type": {
|
|
270
353
|
"text": "!Array<!ContextMenuItem> | undefined"
|
|
271
354
|
},
|
|
272
|
-
"description": "Defines a (hierarchical) menu structure for the component.\nIf a menu item has a non-empty `children` set, a sub-menu with the child items is opened\nnext to the parent menu on mouseover, tap or a right arrow keypress.\n\nThe items API can't be used together with a renderer!\n\n#### Example\n\n```javascript\ncontextMenu.items = [\n { text: 'Menu Item 1', theme: 'primary', className: 'first', children:\n [\n { text: 'Menu Item 1-1', checked: true, keepOpen: true },\n { text: 'Menu Item 1-2' }\n ]\n },\n { component: 'hr' },\n { text: 'Menu Item 2', children:\n [\n { text: 'Menu Item 2-1' },\n { text: 'Menu Item 2-2', disabled: true }\n ]\n },\n { text: 'Menu Item 3', disabled: true, className: 'last' }\n];\n```",
|
|
355
|
+
"description": "Defines a (hierarchical) menu structure for the component.\nIf a menu item has a non-empty `children` set, a sub-menu with the child items is opened\nnext to the parent menu on mouseover, tap or a right arrow keypress.\n\nThe items API can't be used together with a renderer!\n\n#### Example\n\n```javascript\ncontextMenu.items = [\n { text: 'Menu Item 1', theme: 'primary', className: 'first', children:\n [\n { text: 'Menu Item 1-1', checked: true, keepOpen: true },\n { text: 'Menu Item 1-2' }\n ]\n },\n { component: 'hr' },\n { text: 'Menu Item 2', children:\n [\n { text: 'Menu Item 2-1' },\n { text: 'Menu Item 2-2', disabled: true }\n ]\n },\n { text: 'Menu Item 3', disabled: true, className: 'last' }\n];\n```\n\n#### Item tooltips\n\nMenu items can have tooltips that are shown on hover and keyboard\nfocus. To enable them, add a slotted `<vaadin-tooltip>` element\nand set the `tooltip` property on each item that should have one:\n\n```html\n<vaadin-context-menu>\n <vaadin-tooltip slot=\"tooltip\"></vaadin-tooltip>\n</vaadin-context-menu>\n```",
|
|
273
356
|
"attribute": "items",
|
|
274
357
|
"inheritedFrom": {
|
|
275
358
|
"name": "ItemsMixin",
|
|
@@ -564,6 +647,10 @@
|
|
|
564
647
|
"description": "",
|
|
565
648
|
"name": "ItemsMixin",
|
|
566
649
|
"members": [
|
|
650
|
+
{
|
|
651
|
+
"kind": "method",
|
|
652
|
+
"name": "close"
|
|
653
|
+
},
|
|
567
654
|
{
|
|
568
655
|
"kind": "field",
|
|
569
656
|
"name": "items",
|
|
@@ -571,7 +658,7 @@
|
|
|
571
658
|
"type": {
|
|
572
659
|
"text": "!Array<!ContextMenuItem> | undefined"
|
|
573
660
|
},
|
|
574
|
-
"description": "Defines a (hierarchical) menu structure for the component.\nIf a menu item has a non-empty `children` set, a sub-menu with the child items is opened\nnext to the parent menu on mouseover, tap or a right arrow keypress.\n\nThe items API can't be used together with a renderer!\n\n#### Example\n\n```javascript\ncontextMenu.items = [\n { text: 'Menu Item 1', theme: 'primary', className: 'first', children:\n [\n { text: 'Menu Item 1-1', checked: true, keepOpen: true },\n { text: 'Menu Item 1-2' }\n ]\n },\n { component: 'hr' },\n { text: 'Menu Item 2', children:\n [\n { text: 'Menu Item 2-1' },\n { text: 'Menu Item 2-2', disabled: true }\n ]\n },\n { text: 'Menu Item 3', disabled: true, className: 'last' }\n];\n```",
|
|
661
|
+
"description": "Defines a (hierarchical) menu structure for the component.\nIf a menu item has a non-empty `children` set, a sub-menu with the child items is opened\nnext to the parent menu on mouseover, tap or a right arrow keypress.\n\nThe items API can't be used together with a renderer!\n\n#### Example\n\n```javascript\ncontextMenu.items = [\n { text: 'Menu Item 1', theme: 'primary', className: 'first', children:\n [\n { text: 'Menu Item 1-1', checked: true, keepOpen: true },\n { text: 'Menu Item 1-2' }\n ]\n },\n { component: 'hr' },\n { text: 'Menu Item 2', children:\n [\n { text: 'Menu Item 2-1' },\n { text: 'Menu Item 2-2', disabled: true }\n ]\n },\n { text: 'Menu Item 3', disabled: true, className: 'last' }\n];\n```\n\n#### Item tooltips\n\nMenu items can have tooltips that are shown on hover and keyboard\nfocus. To enable them, add a slotted `<vaadin-tooltip>` element\nand set the `tooltip` property on each item that should have one:\n\n```html\n<vaadin-context-menu>\n <vaadin-tooltip slot=\"tooltip\"></vaadin-tooltip>\n</vaadin-context-menu>\n```",
|
|
575
662
|
"attribute": "items"
|
|
576
663
|
}
|
|
577
664
|
],
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vaadin/context-menu",
|
|
3
|
-
"version": "25.2.0-
|
|
3
|
+
"version": "25.2.0-beta1",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -37,21 +37,21 @@
|
|
|
37
37
|
],
|
|
38
38
|
"dependencies": {
|
|
39
39
|
"@open-wc/dedupe-mixin": "^1.3.0",
|
|
40
|
-
"@vaadin/a11y-base": "25.2.0-
|
|
41
|
-
"@vaadin/component-base": "25.2.0-
|
|
42
|
-
"@vaadin/item": "25.2.0-
|
|
43
|
-
"@vaadin/list-box": "25.2.0-
|
|
44
|
-
"@vaadin/lit-renderer": "25.2.0-
|
|
45
|
-
"@vaadin/overlay": "25.2.0-
|
|
46
|
-
"@vaadin/vaadin-themable-mixin": "25.2.0-
|
|
40
|
+
"@vaadin/a11y-base": "25.2.0-beta1",
|
|
41
|
+
"@vaadin/component-base": "25.2.0-beta1",
|
|
42
|
+
"@vaadin/item": "25.2.0-beta1",
|
|
43
|
+
"@vaadin/list-box": "25.2.0-beta1",
|
|
44
|
+
"@vaadin/lit-renderer": "25.2.0-beta1",
|
|
45
|
+
"@vaadin/overlay": "25.2.0-beta1",
|
|
46
|
+
"@vaadin/vaadin-themable-mixin": "25.2.0-beta1",
|
|
47
47
|
"lit": "^3.0.0"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
|
-
"@vaadin/aura": "25.2.0-
|
|
51
|
-
"@vaadin/chai-plugins": "25.2.0-
|
|
52
|
-
"@vaadin/test-runner-commands": "25.2.0-
|
|
50
|
+
"@vaadin/aura": "25.2.0-beta1",
|
|
51
|
+
"@vaadin/chai-plugins": "25.2.0-beta1",
|
|
52
|
+
"@vaadin/test-runner-commands": "25.2.0-beta1",
|
|
53
53
|
"@vaadin/testing-helpers": "^2.0.0",
|
|
54
|
-
"@vaadin/vaadin-lumo-styles": "25.2.0-
|
|
54
|
+
"@vaadin/vaadin-lumo-styles": "25.2.0-beta1",
|
|
55
55
|
"sinon": "^21.0.2"
|
|
56
56
|
},
|
|
57
57
|
"customElements": "custom-elements.json",
|
|
@@ -59,5 +59,5 @@
|
|
|
59
59
|
"web-types.json",
|
|
60
60
|
"web-types.lit.json"
|
|
61
61
|
],
|
|
62
|
-
"gitHead": "
|
|
62
|
+
"gitHead": "471a23f60d1eb725f98a33f62cb9664d9c0a4163"
|
|
63
63
|
}
|
|
@@ -17,9 +17,6 @@ import { contextMenuItemStyles } from './styles/vaadin-context-menu-item-base-st
|
|
|
17
17
|
*
|
|
18
18
|
* @customElement vaadin-context-menu-item
|
|
19
19
|
* @extends HTMLElement
|
|
20
|
-
* @mixes DirMixin
|
|
21
|
-
* @mixes ItemMixin
|
|
22
|
-
* @mixes ThemableMixin
|
|
23
20
|
* @protected
|
|
24
21
|
*/
|
|
25
22
|
class ContextMenuItem extends ItemMixin(ThemableMixin(DirMixin(PolylitMixin(LumoInjectionMixin(LitElement))))) {
|
|
@@ -47,6 +44,11 @@ class ContextMenuItem extends ItemMixin(ThemableMixin(DirMixin(PolylitMixin(Lumo
|
|
|
47
44
|
|
|
48
45
|
this.setAttribute('role', 'menuitem');
|
|
49
46
|
}
|
|
47
|
+
|
|
48
|
+
/** @override */
|
|
49
|
+
__shouldAllowFocusWhenDisabled() {
|
|
50
|
+
return window.Vaadin.featureFlags.accessibleDisabledMenuItems;
|
|
51
|
+
}
|
|
50
52
|
}
|
|
51
53
|
|
|
52
54
|
defineCustomElement(ContextMenuItem);
|
|
@@ -17,9 +17,6 @@ import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mix
|
|
|
17
17
|
*
|
|
18
18
|
* @customElement vaadin-context-menu-list-box
|
|
19
19
|
* @extends HTMLElement
|
|
20
|
-
* @mixes DirMixin
|
|
21
|
-
* @mixes ListMixin
|
|
22
|
-
* @mixes ThemableMixin
|
|
23
20
|
* @protected
|
|
24
21
|
*/
|
|
25
22
|
class ContextMenuListBox extends ListMixin(ThemableMixin(DirMixin(PolylitMixin(LumoInjectionMixin(LitElement))))) {
|
|
@@ -7,12 +7,9 @@ import { isElementFocusable, isKeyboardActive } from '@vaadin/a11y-base/src/focu
|
|
|
7
7
|
import { isAndroid, isIOS } from '@vaadin/component-base/src/browser-utils.js';
|
|
8
8
|
import { addListener, deepTargetFind, gestures, removeListener } from '@vaadin/component-base/src/gestures.js';
|
|
9
9
|
import { MediaQueryController } from '@vaadin/component-base/src/media-query-controller.js';
|
|
10
|
+
import { ContextMenuTooltipController } from './vaadin-context-menu-tooltip-controller.js';
|
|
10
11
|
import { ItemsMixin } from './vaadin-contextmenu-items-mixin.js';
|
|
11
12
|
|
|
12
|
-
/**
|
|
13
|
-
* @polymerMixin
|
|
14
|
-
* @mixes ItemsMixin
|
|
15
|
-
*/
|
|
16
13
|
export const ContextMenuMixin = (superClass) =>
|
|
17
14
|
class ContextMenuMixinClass extends ItemsMixin(superClass) {
|
|
18
15
|
static get properties() {
|
|
@@ -35,6 +32,7 @@ export const ContextMenuMixin = (superClass) =>
|
|
|
35
32
|
value: false,
|
|
36
33
|
notify: true,
|
|
37
34
|
readOnly: true,
|
|
35
|
+
sync: true,
|
|
38
36
|
},
|
|
39
37
|
|
|
40
38
|
/**
|
|
@@ -134,7 +132,7 @@ export const ContextMenuMixin = (superClass) =>
|
|
|
134
132
|
this._boundOpen = this.open.bind(this);
|
|
135
133
|
this._boundClose = this.close.bind(this);
|
|
136
134
|
this._boundPreventDefault = this._preventDefault.bind(this);
|
|
137
|
-
this.
|
|
135
|
+
this.__onGlobalContextMenu = this.__onGlobalContextMenu.bind(this);
|
|
138
136
|
}
|
|
139
137
|
|
|
140
138
|
/** @protected */
|
|
@@ -143,6 +141,7 @@ export const ContextMenuMixin = (superClass) =>
|
|
|
143
141
|
|
|
144
142
|
this.__boundOnScroll = this.__onScroll.bind(this);
|
|
145
143
|
window.addEventListener('scroll', this.__boundOnScroll, true);
|
|
144
|
+
document.documentElement.addEventListener('contextmenu', this.__onGlobalContextMenu, true);
|
|
146
145
|
|
|
147
146
|
// Restore opened state if overlay was opened when disconnecting
|
|
148
147
|
if (this.__restoreOpened) {
|
|
@@ -155,10 +154,16 @@ export const ContextMenuMixin = (superClass) =>
|
|
|
155
154
|
super.disconnectedCallback();
|
|
156
155
|
|
|
157
156
|
window.removeEventListener('scroll', this.__boundOnScroll, true);
|
|
157
|
+
document.documentElement.removeEventListener('contextmenu', this.__onGlobalContextMenu, true);
|
|
158
158
|
|
|
159
|
-
//
|
|
159
|
+
// Memorize opened state and defer close so that DOM moves (disconnect
|
|
160
|
+
// followed by reconnect within the same task) do not close the overlay.
|
|
160
161
|
this.__restoreOpened = this.opened;
|
|
161
|
-
|
|
162
|
+
setTimeout(() => {
|
|
163
|
+
if (!this.isConnected) {
|
|
164
|
+
this.close();
|
|
165
|
+
}
|
|
166
|
+
});
|
|
162
167
|
}
|
|
163
168
|
|
|
164
169
|
/** @protected */
|
|
@@ -172,6 +177,15 @@ export const ContextMenuMixin = (superClass) =>
|
|
|
172
177
|
this._fullscreen = matches;
|
|
173
178
|
}),
|
|
174
179
|
);
|
|
180
|
+
|
|
181
|
+
// Sub-menus inherit the tooltip controller from their parent menu
|
|
182
|
+
// (assigned before `firstUpdated` runs) to reuse the same slotted
|
|
183
|
+
// `<vaadin-tooltip>` across nesting levels. Only create a new one
|
|
184
|
+
// when none was inherited, i.e. on the outer host.
|
|
185
|
+
if (!this._tooltipController) {
|
|
186
|
+
this._tooltipController = new ContextMenuTooltipController(this);
|
|
187
|
+
this.addController(this._tooltipController);
|
|
188
|
+
}
|
|
175
189
|
}
|
|
176
190
|
|
|
177
191
|
/**
|
|
@@ -280,13 +294,7 @@ export const ContextMenuMixin = (superClass) =>
|
|
|
280
294
|
}
|
|
281
295
|
|
|
282
296
|
/** @private */
|
|
283
|
-
_openedChanged(opened
|
|
284
|
-
if (opened) {
|
|
285
|
-
document.documentElement.addEventListener('contextmenu', this._boundOnGlobalContextMenu, true);
|
|
286
|
-
} else if (oldOpened) {
|
|
287
|
-
document.documentElement.removeEventListener('contextmenu', this._boundOnGlobalContextMenu, true);
|
|
288
|
-
}
|
|
289
|
-
|
|
297
|
+
_openedChanged(opened) {
|
|
290
298
|
this.__setListenOnUserSelect(opened);
|
|
291
299
|
}
|
|
292
300
|
|
|
@@ -328,6 +336,8 @@ export const ContextMenuMixin = (superClass) =>
|
|
|
328
336
|
* Closes the overlay.
|
|
329
337
|
*/
|
|
330
338
|
close() {
|
|
339
|
+
super.close();
|
|
340
|
+
|
|
331
341
|
this._setOpened(false);
|
|
332
342
|
}
|
|
333
343
|
|
|
@@ -620,7 +630,10 @@ export const ContextMenuMixin = (superClass) =>
|
|
|
620
630
|
}
|
|
621
631
|
|
|
622
632
|
/** @private */
|
|
623
|
-
|
|
633
|
+
__onGlobalContextMenu(e) {
|
|
634
|
+
if (!this.opened) {
|
|
635
|
+
return;
|
|
636
|
+
}
|
|
624
637
|
if (!e.shiftKey) {
|
|
625
638
|
const isTouchDevice = isAndroid || isIOS;
|
|
626
639
|
if (!isTouchDevice) {
|
|
@@ -645,10 +658,4 @@ export const ContextMenuMixin = (superClass) =>
|
|
|
645
658
|
this.close();
|
|
646
659
|
}
|
|
647
660
|
}
|
|
648
|
-
|
|
649
|
-
/**
|
|
650
|
-
* Fired when the context menu is closed.
|
|
651
|
-
*
|
|
652
|
-
* @event closed
|
|
653
|
-
*/
|
|
654
661
|
};
|
|
@@ -18,10 +18,6 @@ import { MenuOverlayMixin } from './vaadin-menu-overlay-mixin.js';
|
|
|
18
18
|
*
|
|
19
19
|
* @customElement vaadin-context-menu-overlay
|
|
20
20
|
* @extends HTMLElement
|
|
21
|
-
* @mixes DirMixin
|
|
22
|
-
* @mixes MenuOverlayMixin
|
|
23
|
-
* @mixes OverlayMixin
|
|
24
|
-
* @mixes ThemableMixin
|
|
25
21
|
* @protected
|
|
26
22
|
*/
|
|
27
23
|
export class ContextMenuOverlay extends MenuOverlayMixin(
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (c) 2016 - 2026 Vaadin Ltd.
|
|
4
|
+
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
+
*/
|
|
6
|
+
import { SlotController } from '@vaadin/component-base/src/slot-controller.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Controller for the tooltip slotted into `<vaadin-context-menu>`. Configures
|
|
10
|
+
* the tooltip in manual mode and drives its target, context, and position
|
|
11
|
+
* based on the currently hovered or focused item.
|
|
12
|
+
*/
|
|
13
|
+
export class ContextMenuTooltipController extends SlotController {
|
|
14
|
+
constructor(host) {
|
|
15
|
+
super(host, 'tooltip');
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** @override */
|
|
19
|
+
initCustomNode(tooltipNode) {
|
|
20
|
+
tooltipNode.manual = true;
|
|
21
|
+
tooltipNode.generator ||= ({ item }) => item?.tooltip;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** @protected */
|
|
25
|
+
_getItem(target) {
|
|
26
|
+
return target._item;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** @protected */
|
|
30
|
+
_getDefaultPosition(target) {
|
|
31
|
+
const item = this._getItem(target);
|
|
32
|
+
return item.children?.length > 0 && !item.disabled ? 'start' : 'end';
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* @param {HTMLElement | null} target
|
|
37
|
+
*/
|
|
38
|
+
setTarget(target) {
|
|
39
|
+
const tooltipNode = this.node;
|
|
40
|
+
if (!tooltipNode) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const item = target ? this._getItem(target) : null;
|
|
45
|
+
if (item?.tooltip) {
|
|
46
|
+
tooltipNode.target = target;
|
|
47
|
+
tooltipNode.context = { item };
|
|
48
|
+
tooltipNode._position = item.tooltipPosition || this._getDefaultPosition(target);
|
|
49
|
+
} else {
|
|
50
|
+
tooltipNode.target = null;
|
|
51
|
+
tooltipNode.context = { item: null };
|
|
52
|
+
this.close(true);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* @param {{ trigger: 'hover' | 'focus' }} options
|
|
58
|
+
*/
|
|
59
|
+
open({ trigger }) {
|
|
60
|
+
const tooltipNode = this.node;
|
|
61
|
+
if (tooltipNode?.isConnected && tooltipNode.target) {
|
|
62
|
+
tooltipNode._stateController.open({
|
|
63
|
+
hover: trigger === 'hover',
|
|
64
|
+
focus: trigger === 'focus',
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
bringToFront() {
|
|
70
|
+
const tooltipNode = this.node;
|
|
71
|
+
tooltipNode?._overlayElement?.bringToFront();
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* @param {boolean} immediate
|
|
76
|
+
*/
|
|
77
|
+
close(immediate) {
|
|
78
|
+
const tooltipNode = this.node;
|
|
79
|
+
tooltipNode?._stateController.close(immediate);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
@@ -106,6 +106,34 @@ export interface ContextMenuEventMap<TItem extends ContextMenuItem = ContextMenu
|
|
|
106
106
|
*
|
|
107
107
|
* **NOTE:** when the `items` array is defined, the renderer cannot be used.
|
|
108
108
|
*
|
|
109
|
+
* #### Disabled menu items
|
|
110
|
+
*
|
|
111
|
+
* When disabled, menu items are rendered as "dimmed".
|
|
112
|
+
*
|
|
113
|
+
* By default, disabled items are not focusable and don't react to hover.
|
|
114
|
+
* As a result, they are hidden from assistive technologies, and it's not
|
|
115
|
+
* possible to show a tooltip to explain why they are disabled. This can
|
|
116
|
+
* be addressed by enabling the feature flag `accessibleDisabledMenuItems`,
|
|
117
|
+
* which makes disabled items focusable and hoverable, while still
|
|
118
|
+
* preventing them from being activated:
|
|
119
|
+
*
|
|
120
|
+
* ```js
|
|
121
|
+
* // Set before any context menu is attached to the DOM.
|
|
122
|
+
* window.Vaadin.featureFlags.accessibleDisabledMenuItems = true;
|
|
123
|
+
* ```
|
|
124
|
+
*
|
|
125
|
+
* #### Item tooltips
|
|
126
|
+
*
|
|
127
|
+
* Menu items can have tooltips that are shown on hover and keyboard
|
|
128
|
+
* focus. To enable them, add a slotted `<vaadin-tooltip>` element
|
|
129
|
+
* and set the `tooltip` property on each item that should have one:
|
|
130
|
+
*
|
|
131
|
+
* ```html
|
|
132
|
+
* <vaadin-context-menu>
|
|
133
|
+
* <vaadin-tooltip slot="tooltip"></vaadin-tooltip>
|
|
134
|
+
* </vaadin-context-menu>
|
|
135
|
+
* ```
|
|
136
|
+
*
|
|
109
137
|
* ### Rendering
|
|
110
138
|
*
|
|
111
139
|
* The content of the menu can be populated by using the renderer callback function.
|
|
@@ -54,6 +54,34 @@ import { ContextMenuMixin } from './vaadin-context-menu-mixin.js';
|
|
|
54
54
|
*
|
|
55
55
|
* **NOTE:** when the `items` array is defined, the renderer cannot be used.
|
|
56
56
|
*
|
|
57
|
+
* #### Disabled menu items
|
|
58
|
+
*
|
|
59
|
+
* When disabled, menu items are rendered as "dimmed".
|
|
60
|
+
*
|
|
61
|
+
* By default, disabled items are not focusable and don't react to hover.
|
|
62
|
+
* As a result, they are hidden from assistive technologies, and it's not
|
|
63
|
+
* possible to show a tooltip to explain why they are disabled. This can
|
|
64
|
+
* be addressed by enabling the feature flag `accessibleDisabledMenuItems`,
|
|
65
|
+
* which makes disabled items focusable and hoverable, while still
|
|
66
|
+
* preventing them from being activated:
|
|
67
|
+
*
|
|
68
|
+
* ```js
|
|
69
|
+
* // Set before any context menu is attached to the DOM.
|
|
70
|
+
* window.Vaadin.featureFlags.accessibleDisabledMenuItems = true;
|
|
71
|
+
* ```
|
|
72
|
+
*
|
|
73
|
+
* #### Item tooltips
|
|
74
|
+
*
|
|
75
|
+
* Menu items can have tooltips that are shown on hover and keyboard
|
|
76
|
+
* focus. To enable them, add a slotted `<vaadin-tooltip>` element
|
|
77
|
+
* and set the `tooltip` property on each item that should have one:
|
|
78
|
+
*
|
|
79
|
+
* ```html
|
|
80
|
+
* <vaadin-context-menu>
|
|
81
|
+
* <vaadin-tooltip slot="tooltip"></vaadin-tooltip>
|
|
82
|
+
* </vaadin-context-menu>
|
|
83
|
+
* ```
|
|
84
|
+
*
|
|
57
85
|
* ### Rendering
|
|
58
86
|
*
|
|
59
87
|
* The content of the menu can be populated by using the renderer callback function.
|
|
@@ -218,9 +246,6 @@ import { ContextMenuMixin } from './vaadin-context-menu-mixin.js';
|
|
|
218
246
|
*
|
|
219
247
|
* @customElement vaadin-context-menu
|
|
220
248
|
* @extends HTMLElement
|
|
221
|
-
* @mixes ElementMixin
|
|
222
|
-
* @mixes ContextMenuMixin
|
|
223
|
-
* @mixes ThemePropertyMixin
|
|
224
249
|
*/
|
|
225
250
|
class ContextMenu extends ContextMenuMixin(ElementMixin(ThemePropertyMixin(PolylitMixin(LitElement)))) {
|
|
226
251
|
static get is() {
|
|
@@ -267,7 +292,7 @@ class ContextMenu extends ContextMenuMixin(ElementMixin(ThemePropertyMixin(Polyl
|
|
|
267
292
|
.modeless="${this._modeless}"
|
|
268
293
|
.renderer="${this.items ? this.__itemsRenderer : this.renderer}"
|
|
269
294
|
.position="${position}"
|
|
270
|
-
.positionTarget="${position ? context
|
|
295
|
+
.positionTarget="${position ? context?.target : this._positionTarget}"
|
|
271
296
|
.horizontalAlign="${this.__computeHorizontalAlign(position)}"
|
|
272
297
|
.verticalAlign="${this.__computeVerticalAlign(position)}"
|
|
273
298
|
?no-horizontal-overlap="${this.__computeNoHorizontalOverlap(position)}"
|
|
@@ -283,6 +308,8 @@ class ContextMenu extends ContextMenuMixin(ElementMixin(ThemePropertyMixin(Polyl
|
|
|
283
308
|
<slot name="overlay"></slot>
|
|
284
309
|
<slot name="submenu" slot="submenu"></slot>
|
|
285
310
|
</vaadin-context-menu-overlay>
|
|
311
|
+
|
|
312
|
+
<slot name="tooltip"></slot>
|
|
286
313
|
`;
|
|
287
314
|
}
|
|
288
315
|
|
|
@@ -321,14 +348,6 @@ class ContextMenu extends ContextMenuMixin(ElementMixin(ThemePropertyMixin(Polyl
|
|
|
321
348
|
|
|
322
349
|
return ['top-start', 'top-end', 'top', 'start-bottom', 'end-bottom'].includes(position) ? 'bottom' : 'top';
|
|
323
350
|
}
|
|
324
|
-
|
|
325
|
-
/**
|
|
326
|
-
* Fired when an item is selected when the context menu is populated using the `items` API.
|
|
327
|
-
*
|
|
328
|
-
* @event item-selected
|
|
329
|
-
* @param {Object} detail
|
|
330
|
-
* @param {Object} detail.value the selected menu item
|
|
331
|
-
*/
|
|
332
351
|
}
|
|
333
352
|
|
|
334
353
|
defineCustomElement(ContextMenu);
|
|
@@ -120,7 +120,7 @@ register({
|
|
|
120
120
|
ev.detail = { x, y, sourceEvent };
|
|
121
121
|
target.dispatchEvent(ev);
|
|
122
122
|
// Forward `preventDefault` in a clean way
|
|
123
|
-
if (ev.defaultPrevented && sourceEvent
|
|
123
|
+
if (ev.defaultPrevented && sourceEvent?.preventDefault) {
|
|
124
124
|
sourceEvent.preventDefault();
|
|
125
125
|
}
|
|
126
126
|
},
|
|
@@ -9,6 +9,19 @@ import type { Constructor } from '@open-wc/dedupe-mixin';
|
|
|
9
9
|
|
|
10
10
|
export type ContextMenuItem<TItemData extends object = object> = {
|
|
11
11
|
text?: string;
|
|
12
|
+
/**
|
|
13
|
+
* Text to be set as the menu item's tooltip.
|
|
14
|
+
* Requires a `<vaadin-tooltip slot="tooltip">` element to be added inside the `<vaadin-context-menu>`.
|
|
15
|
+
*/
|
|
16
|
+
tooltip?: string;
|
|
17
|
+
/**
|
|
18
|
+
* Position of the item's tooltip relative to the item
|
|
19
|
+
* (e.g. `end`, `top`, `bottom-start`). Items with a sub-menu default to `start` to
|
|
20
|
+
* avoid overlap with the opening sub-menu; all other items, including disabled ones
|
|
21
|
+
* (whose sub-menus cannot be opened), default to `end`. If the slotted
|
|
22
|
+
* `<vaadin-tooltip>` has its `position` property set, that value is used instead.
|
|
23
|
+
*/
|
|
24
|
+
tooltipPosition?: string;
|
|
12
25
|
component?: HTMLElement | string;
|
|
13
26
|
disabled?: boolean;
|
|
14
27
|
checked?: boolean;
|
|
@@ -48,6 +61,18 @@ export declare class ItemsMixinClass<TItem extends ContextMenuItem = ContextMenu
|
|
|
48
61
|
* { text: 'Menu Item 3', disabled: true, className: 'last' }
|
|
49
62
|
* ];
|
|
50
63
|
* ```
|
|
64
|
+
*
|
|
65
|
+
* #### Item tooltips
|
|
66
|
+
*
|
|
67
|
+
* Menu items can have tooltips that are shown on hover and keyboard
|
|
68
|
+
* focus. To enable them, add a slotted `<vaadin-tooltip>` element
|
|
69
|
+
* and set the `tooltip` property on each item that should have one:
|
|
70
|
+
*
|
|
71
|
+
* ```html
|
|
72
|
+
* <vaadin-context-menu>
|
|
73
|
+
* <vaadin-tooltip slot="tooltip"></vaadin-tooltip>
|
|
74
|
+
* </vaadin-context-menu>
|
|
75
|
+
* ```
|
|
51
76
|
*/
|
|
52
77
|
items: TItem[] | undefined;
|
|
53
78
|
|
|
@@ -3,11 +3,9 @@
|
|
|
3
3
|
* Copyright (c) 2016 - 2026 Vaadin Ltd.
|
|
4
4
|
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
5
|
*/
|
|
6
|
+
import { isKeyboardActive } from '@vaadin/a11y-base/src/focus-utils.js';
|
|
6
7
|
import { isTouch } from '@vaadin/component-base/src/browser-utils.js';
|
|
7
8
|
|
|
8
|
-
/**
|
|
9
|
-
* @polymerMixin
|
|
10
|
-
*/
|
|
11
9
|
export const ItemsMixin = (superClass) =>
|
|
12
10
|
class ItemsMixin extends superClass {
|
|
13
11
|
static get properties() {
|
|
@@ -16,6 +14,13 @@ export const ItemsMixin = (superClass) =>
|
|
|
16
14
|
* @typedef ContextMenuItem
|
|
17
15
|
* @type {object}
|
|
18
16
|
* @property {string} text - Text to be set as the menu item component's textContent
|
|
17
|
+
* @property {string} tooltip - Text to be set as the menu item's tooltip.
|
|
18
|
+
* Requires a `<vaadin-tooltip slot="tooltip">` element to be added inside the `<vaadin-context-menu>`.
|
|
19
|
+
* @property {string} tooltipPosition - Position of the item's tooltip relative to the
|
|
20
|
+
* item (e.g. `end`, `top`, `bottom-start`). Items with a sub-menu default to `start`
|
|
21
|
+
* to avoid overlap with the opening sub-menu; all other items, including disabled
|
|
22
|
+
* ones (whose sub-menus cannot be opened), default to `end`. If the slotted
|
|
23
|
+
* `<vaadin-tooltip>` has its `position` property set, that value is used instead.
|
|
19
24
|
* @property {string | HTMLElement} component - The component to represent the item.
|
|
20
25
|
* Either a tagName or an element instance. Defaults to "vaadin-context-menu-item".
|
|
21
26
|
* @property {boolean} disabled - If true, the item is disabled and cannot be selected
|
|
@@ -54,6 +59,18 @@ export const ItemsMixin = (superClass) =>
|
|
|
54
59
|
* ];
|
|
55
60
|
* ```
|
|
56
61
|
*
|
|
62
|
+
* #### Item tooltips
|
|
63
|
+
*
|
|
64
|
+
* Menu items can have tooltips that are shown on hover and keyboard
|
|
65
|
+
* focus. To enable them, add a slotted `<vaadin-tooltip>` element
|
|
66
|
+
* and set the `tooltip` property on each item that should have one:
|
|
67
|
+
*
|
|
68
|
+
* ```html
|
|
69
|
+
* <vaadin-context-menu>
|
|
70
|
+
* <vaadin-tooltip slot="tooltip"></vaadin-tooltip>
|
|
71
|
+
* </vaadin-context-menu>
|
|
72
|
+
* ```
|
|
73
|
+
*
|
|
57
74
|
* @type {!Array<!ContextMenuItem> | undefined}
|
|
58
75
|
*/
|
|
59
76
|
items: {
|
|
@@ -105,6 +122,7 @@ export const ItemsMixin = (superClass) =>
|
|
|
105
122
|
disconnectedCallback() {
|
|
106
123
|
super.disconnectedCallback();
|
|
107
124
|
document.documentElement.removeEventListener('click', this.__itemsOutsideClickListener);
|
|
125
|
+
this._tooltipController.setTarget(null);
|
|
108
126
|
}
|
|
109
127
|
|
|
110
128
|
/**
|
|
@@ -126,7 +144,7 @@ export const ItemsMixin = (superClass) =>
|
|
|
126
144
|
// If parent item is not focused, do not focus submenu
|
|
127
145
|
if (overlay.parentOverlay) {
|
|
128
146
|
const parent = overlay.parentOverlay._contentRoot.querySelector('[expanded]');
|
|
129
|
-
if (parent
|
|
147
|
+
if (parent?.hasAttribute('focused') && child) {
|
|
130
148
|
child.focus();
|
|
131
149
|
} else {
|
|
132
150
|
overlay.$.overlay.focus();
|
|
@@ -231,6 +249,26 @@ export const ItemsMixin = (superClass) =>
|
|
|
231
249
|
listBox.setAttribute('theme', this._theme);
|
|
232
250
|
}
|
|
233
251
|
|
|
252
|
+
listBox.addEventListener('mouseover', (event) => {
|
|
253
|
+
const itemElement = event.target.closest(`${this._tagNamePrefix}-item`);
|
|
254
|
+
this._tooltipController.setTarget(itemElement);
|
|
255
|
+
this._tooltipController.open({ trigger: 'hover' });
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
listBox.addEventListener('mouseleave', () => {
|
|
259
|
+
this._tooltipController.close(true);
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
listBox.addEventListener('focusin', (event) => {
|
|
263
|
+
if (!isKeyboardActive()) {
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
const itemElement = event.target.closest(`${this._tagNamePrefix}-item`);
|
|
268
|
+
this._tooltipController.setTarget(itemElement);
|
|
269
|
+
this._tooltipController.open({ trigger: 'focus' });
|
|
270
|
+
});
|
|
271
|
+
|
|
234
272
|
listBox.addEventListener('selected-changed', (event) => {
|
|
235
273
|
const { value } = event.detail;
|
|
236
274
|
if (typeof value === 'number') {
|
|
@@ -300,6 +338,12 @@ export const ItemsMixin = (superClass) =>
|
|
|
300
338
|
__initSubMenu() {
|
|
301
339
|
const subMenu = document.createElement(this.constructor.is);
|
|
302
340
|
|
|
341
|
+
// The slotted `<vaadin-tooltip>` lives on the outer `<vaadin-context-menu>`
|
|
342
|
+
// host. Its tooltip controller instance is shared across sub-menus to
|
|
343
|
+
// reuse the same tooltip element for items at every nesting level.
|
|
344
|
+
subMenu._tooltipController = this._tooltipController;
|
|
345
|
+
subMenu.__parentMenu = this;
|
|
346
|
+
|
|
303
347
|
subMenu._modeless = true;
|
|
304
348
|
subMenu.openOn = 'opensubmenu';
|
|
305
349
|
|
|
@@ -323,9 +367,7 @@ export const ItemsMixin = (superClass) =>
|
|
|
323
367
|
|
|
324
368
|
// Listen to the forwarded event from sub-menu.
|
|
325
369
|
this.addEventListener('close-all-menus', () => {
|
|
326
|
-
|
|
327
|
-
// as we can't have `sync: true` on `opened` property.
|
|
328
|
-
this._overlayElement.close();
|
|
370
|
+
this.close();
|
|
329
371
|
});
|
|
330
372
|
|
|
331
373
|
// Listen to the forwarded event from sub-menu.
|
|
@@ -344,7 +386,10 @@ export const ItemsMixin = (superClass) =>
|
|
|
344
386
|
|
|
345
387
|
// Mark parent item as collapsed when closing.
|
|
346
388
|
subMenu.addEventListener('opened-changed', (event) => {
|
|
347
|
-
|
|
389
|
+
const opened = event.detail.value;
|
|
390
|
+
if (opened) {
|
|
391
|
+
this._tooltipController.bringToFront();
|
|
392
|
+
} else {
|
|
348
393
|
const expandedItem = this._listBox.querySelector('[expanded]');
|
|
349
394
|
if (expandedItem) {
|
|
350
395
|
this.__updateExpanded(expandedItem, false);
|
|
@@ -374,12 +419,12 @@ export const ItemsMixin = (superClass) =>
|
|
|
374
419
|
const subMenu = this._subMenu;
|
|
375
420
|
const expandedItem = this._listBox.querySelector('[expanded]');
|
|
376
421
|
|
|
377
|
-
if (item && item !== expandedItem) {
|
|
422
|
+
if (item && item !== expandedItem && !item.disabled) {
|
|
378
423
|
const { children } = item._item;
|
|
379
424
|
|
|
380
425
|
// Check if the sub-menu was focused before closing it.
|
|
381
426
|
const child = subMenu._overlayElement._contentRoot.firstElementChild;
|
|
382
|
-
const isSubmenuFocused = child
|
|
427
|
+
const isSubmenuFocused = child?.focused;
|
|
383
428
|
|
|
384
429
|
// Mark previously expanded item as collapsed
|
|
385
430
|
if (expandedItem) {
|
|
@@ -395,7 +440,7 @@ export const ItemsMixin = (superClass) =>
|
|
|
395
440
|
return;
|
|
396
441
|
}
|
|
397
442
|
|
|
398
|
-
if (children
|
|
443
|
+
if (children?.length) {
|
|
399
444
|
// Open or update the submenu if the new item has children
|
|
400
445
|
this.__updateExpanded(item, true);
|
|
401
446
|
this.__openSubMenu(subMenu, item);
|
|
@@ -407,6 +452,12 @@ export const ItemsMixin = (superClass) =>
|
|
|
407
452
|
this._overlayElement.$.overlay.focus();
|
|
408
453
|
}
|
|
409
454
|
}
|
|
455
|
+
|
|
456
|
+
// Only reachable with `accessibleDisabledMenuItems` enabled (disabled
|
|
457
|
+
// items otherwise have `pointer-events: none` and never receive mouseover).
|
|
458
|
+
if (item?.disabled) {
|
|
459
|
+
subMenu.close();
|
|
460
|
+
}
|
|
410
461
|
}
|
|
411
462
|
|
|
412
463
|
/** @protected */
|
|
@@ -494,4 +545,10 @@ export const ItemsMixin = (superClass) =>
|
|
|
494
545
|
component.removeAttribute('theme');
|
|
495
546
|
}
|
|
496
547
|
}
|
|
548
|
+
|
|
549
|
+
close() {
|
|
550
|
+
if (!this.__parentMenu) {
|
|
551
|
+
this._tooltipController.close(true);
|
|
552
|
+
}
|
|
553
|
+
}
|
|
497
554
|
};
|
|
@@ -6,9 +6,6 @@
|
|
|
6
6
|
import { OverlayFocusMixin } from '@vaadin/overlay/src/vaadin-overlay-focus-mixin.js';
|
|
7
7
|
import { PositionMixin } from '@vaadin/overlay/src/vaadin-overlay-position-mixin.js';
|
|
8
8
|
|
|
9
|
-
/**
|
|
10
|
-
* @polymerMixin
|
|
11
|
-
*/
|
|
12
9
|
export const MenuOverlayMixin = (superClass) =>
|
|
13
10
|
class MenuOverlayMixin extends OverlayFocusMixin(PositionMixin(superClass)) {
|
|
14
11
|
static get properties() {
|
|
@@ -103,7 +100,7 @@ export const MenuOverlayMixin = (superClass) =>
|
|
|
103
100
|
|
|
104
101
|
// Adjust constraints to ensure bottom-aligned applies to sub-menu.
|
|
105
102
|
const parent = this.parentOverlay;
|
|
106
|
-
if (parent
|
|
103
|
+
if (parent?.hasAttribute('bottom-aligned')) {
|
|
107
104
|
const parentStyle = getComputedStyle(parent);
|
|
108
105
|
yMax = yMax - parseFloat(parentStyle.bottom) - parseFloat(parentStyle.height);
|
|
109
106
|
}
|
package/web-types.json
CHANGED
|
@@ -1,23 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/web-types",
|
|
3
3
|
"name": "@vaadin/context-menu",
|
|
4
|
-
"version": "25.2.0-
|
|
4
|
+
"version": "25.2.0-beta1",
|
|
5
5
|
"description-markup": "markdown",
|
|
6
6
|
"contributions": {
|
|
7
7
|
"html": {
|
|
8
8
|
"elements": [
|
|
9
9
|
{
|
|
10
10
|
"name": "vaadin-context-menu",
|
|
11
|
-
"description": "`<vaadin-context-menu>` is a Web Component for creating context menus.\n\n### Items\n\nItems is a higher level convenience API for defining a (hierarchical) menu structure for the component.\nIf a menu item has a non-empty `children` set, a sub-menu with the child items is opened\nnext to the parent menu on mouseover, tap or a right arrow keypress.\n\nWhen an item is selected, `<vaadin-context-menu>` dispatches an \"item-selected\" event\nwith the selected item as `event.detail.value` property.\nIf item does not have `keepOpen` property the menu will be closed.\n\n```javascript\ncontextMenu.items = [\n { text: 'Menu Item 1', theme: 'primary', className: 'first', children:\n [\n { text: 'Menu Item 1-1', checked: true, keepOpen: true },\n { text: 'Menu Item 1-2' }\n ]\n },\n { component: 'hr' },\n { text: 'Menu Item 2', children:\n [\n { text: 'Menu Item 2-1' },\n { text: 'Menu Item 2-2', disabled: true }\n ]\n },\n { text: 'Menu Item 3', disabled: true, className: 'last' }\n];\n\ncontextMenu.addEventListener('item-selected', e => {\n const item = e.detail.value;\n console.log(`${item.text} selected`);\n});\n```\n\n**NOTE:** when the `items` array is defined, the renderer cannot be used.\n\n### Rendering\n\nThe content of the menu can be populated by using the renderer callback function.\n\nThe renderer function provides `root`, `contextMenu`, `model` arguments when applicable.\nGenerate DOM content by using `model` object properties if needed, append it to the `root`\nelement and control the state of the host element by accessing `contextMenu`. Before generating\nnew content, the renderer function should check if there is already content in `root` for reusing it.\n\n```html\n<vaadin-context-menu id=\"contextMenu\">\n <p>This paragraph has a context menu.</p>\n</vaadin-context-menu>\n```\n```js\nconst contextMenu = document.querySelector('#contextMenu');\ncontextMenu.renderer = (root, contextMenu, context) => {\n let listBox = root.firstElementChild;\n if (!listBox) {\n listBox = document.createElement('vaadin-list-box');\n root.appendChild(listBox);\n }\n\n let item = listBox.querySelector('vaadin-item');\n if (!item) {\n item = document.createElement('vaadin-item');\n listBox.appendChild(item);\n }\n item.textContent = 'Content of the selector: ' + context.target.textContent;\n};\n```\n\nYou can access the menu context inside the renderer using\n`context.target` and `context.detail`.\n\nRenderer is called on the opening of the context-menu and each time the related context is updated.\nDOM generated during the renderer call can be reused\nin the next renderer call and will be provided with the `root` argument.\nOn first call it will be empty.\n\n### `vaadin-contextmenu` Gesture Event\n\n`vaadin-contextmenu` is a gesture event (a custom event),\nwhich is dispatched after either `contextmenu` or long touch events.\nThis enables support for both mouse and touch environments in a uniform way.\n\n`<vaadin-context-menu>` opens the menu overlay on the `vaadin-contextmenu`\nevent by default.\n\n### Menu Listener\n\nBy default, the `<vaadin-context-menu>` element listens for the menu opening\nevent on itself. In case if you do not want to wrap the target, you can listen for\nevents on an element outside the `<vaadin-context-menu>` by setting the\n`listenOn` property:\n\n```html\n<vaadin-context-menu id=\"contextMenu\"></vaadin-context-menu>\n\n<div id=\"menuListener\">The element that listens for the contextmenu event.</div>\n```\n```javascript\nconst contextMenu = document.querySelector('#contextMenu');\ncontextMenu.listenOn = document.querySelector('#menuListener');\n```\n\n### Filtering Menu Targets\n\nBy default, the listener element and all its descendants open the context\nmenu. You can filter the menu targets to a smaller set of elements inside\nthe listener element by setting the `selector` property.\n\nIn the following example, only the elements matching `.has-menu` will open the context menu:\n\n```html\n<vaadin-context-menu selector=\".has-menu\">\n <p class=\"has-menu\">This paragraph opens the context menu</p>\n <p>This paragraph does not open the context menu</p>\n</vaadin-context-menu>\n```\n\n### Menu Context\n\nThe following properties are available in the `context` argument:\n\n- `target` is the menu opening event target, which is the element that\nthe user has called the context menu for\n- `detail` is the menu opening event detail\n\nIn the following example, the menu item text is composed with the contents\nof the element that opened the menu:\n\n```html\n<vaadin-context-menu selector=\"li\" id=\"contextMenu\">\n <ul>\n <li>Foo</li>\n <li>Bar</li>\n <li>Baz</li>\n </ul>\n</vaadin-context-menu>\n```\n```js\nconst contextMenu = document.querySelector('#contextMenu');\ncontextMenu.renderer = (root, contextMenu, context) => {\n let listBox = root.firstElementChild;\n if (!listBox) {\n listBox = document.createElement('vaadin-list-box');\n root.appendChild(listBox);\n }\n\n let item = listBox.querySelector('vaadin-item');\n if (!item) {\n item = document.createElement('vaadin-item');\n listBox.appendChild(item);\n }\n item.textContent = 'The menu target: ' + context.target.textContent;\n};\n```\n\n### Styling\n\nThe following shadow DOM parts are available for styling:\n\nPart name | Description\n-----------------|-------------------------------------------\n`backdrop` | Backdrop of the overlay\n`overlay` | The overlay container\n`content` | The overlay content\n\n### Custom CSS Properties\n\nThe following custom CSS properties are available for styling:\n\nCustom CSS property | Description\n--------------------------------------|-------------\n`--vaadin-context-menu-offset-top` | Used as an offset when using `position` and the context menu is aligned vertically below the target\n`--vaadin-context-menu-offset-bottom` | Used as an offset when using `position` and the context menu is aligned vertically above the target\n`--vaadin-context-menu-offset-start` | Used as an offset when using `position` and the context menu is aligned horizontally after the target\n`--vaadin-context-menu-offset-end` | Used as an offset when using `position` and the context menu is aligned horizontally before the target\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.\n\n### Internal components\n\nWhen using `items` API the following internal components are themable:\n\n- `<vaadin-context-menu-item>` - has the same API as [`<vaadin-item>`](https://cdn.vaadin.com/vaadin-web-components/25.2.0-
|
|
11
|
+
"description": "`<vaadin-context-menu>` is a Web Component for creating context menus.\n\n### Items\n\nItems is a higher level convenience API for defining a (hierarchical) menu structure for the component.\nIf a menu item has a non-empty `children` set, a sub-menu with the child items is opened\nnext to the parent menu on mouseover, tap or a right arrow keypress.\n\nWhen an item is selected, `<vaadin-context-menu>` dispatches an \"item-selected\" event\nwith the selected item as `event.detail.value` property.\nIf item does not have `keepOpen` property the menu will be closed.\n\n```javascript\ncontextMenu.items = [\n { text: 'Menu Item 1', theme: 'primary', className: 'first', children:\n [\n { text: 'Menu Item 1-1', checked: true, keepOpen: true },\n { text: 'Menu Item 1-2' }\n ]\n },\n { component: 'hr' },\n { text: 'Menu Item 2', children:\n [\n { text: 'Menu Item 2-1' },\n { text: 'Menu Item 2-2', disabled: true }\n ]\n },\n { text: 'Menu Item 3', disabled: true, className: 'last' }\n];\n\ncontextMenu.addEventListener('item-selected', e => {\n const item = e.detail.value;\n console.log(`${item.text} selected`);\n});\n```\n\n**NOTE:** when the `items` array is defined, the renderer cannot be used.\n\n#### Disabled menu items\n\nWhen disabled, menu items are rendered as \"dimmed\".\n\nBy default, disabled items are not focusable and don't react to hover.\nAs a result, they are hidden from assistive technologies, and it's not\npossible to show a tooltip to explain why they are disabled. This can\nbe addressed by enabling the feature flag `accessibleDisabledMenuItems`,\nwhich makes disabled items focusable and hoverable, while still\npreventing them from being activated:\n\n```js\n// Set before any context menu is attached to the DOM.\nwindow.Vaadin.featureFlags.accessibleDisabledMenuItems = true;\n```\n\n#### Item tooltips\n\nMenu items can have tooltips that are shown on hover and keyboard\nfocus. To enable them, add a slotted `<vaadin-tooltip>` element\nand set the `tooltip` property on each item that should have one:\n\n```html\n<vaadin-context-menu>\n <vaadin-tooltip slot=\"tooltip\"></vaadin-tooltip>\n</vaadin-context-menu>\n```\n\n### Rendering\n\nThe content of the menu can be populated by using the renderer callback function.\n\nThe renderer function provides `root`, `contextMenu`, `model` arguments when applicable.\nGenerate DOM content by using `model` object properties if needed, append it to the `root`\nelement and control the state of the host element by accessing `contextMenu`. Before generating\nnew content, the renderer function should check if there is already content in `root` for reusing it.\n\n```html\n<vaadin-context-menu id=\"contextMenu\">\n <p>This paragraph has a context menu.</p>\n</vaadin-context-menu>\n```\n```js\nconst contextMenu = document.querySelector('#contextMenu');\ncontextMenu.renderer = (root, contextMenu, context) => {\n let listBox = root.firstElementChild;\n if (!listBox) {\n listBox = document.createElement('vaadin-list-box');\n root.appendChild(listBox);\n }\n\n let item = listBox.querySelector('vaadin-item');\n if (!item) {\n item = document.createElement('vaadin-item');\n listBox.appendChild(item);\n }\n item.textContent = 'Content of the selector: ' + context.target.textContent;\n};\n```\n\nYou can access the menu context inside the renderer using\n`context.target` and `context.detail`.\n\nRenderer is called on the opening of the context-menu and each time the related context is updated.\nDOM generated during the renderer call can be reused\nin the next renderer call and will be provided with the `root` argument.\nOn first call it will be empty.\n\n### `vaadin-contextmenu` Gesture Event\n\n`vaadin-contextmenu` is a gesture event (a custom event),\nwhich is dispatched after either `contextmenu` or long touch events.\nThis enables support for both mouse and touch environments in a uniform way.\n\n`<vaadin-context-menu>` opens the menu overlay on the `vaadin-contextmenu`\nevent by default.\n\n### Menu Listener\n\nBy default, the `<vaadin-context-menu>` element listens for the menu opening\nevent on itself. In case if you do not want to wrap the target, you can listen for\nevents on an element outside the `<vaadin-context-menu>` by setting the\n`listenOn` property:\n\n```html\n<vaadin-context-menu id=\"contextMenu\"></vaadin-context-menu>\n\n<div id=\"menuListener\">The element that listens for the contextmenu event.</div>\n```\n```javascript\nconst contextMenu = document.querySelector('#contextMenu');\ncontextMenu.listenOn = document.querySelector('#menuListener');\n```\n\n### Filtering Menu Targets\n\nBy default, the listener element and all its descendants open the context\nmenu. You can filter the menu targets to a smaller set of elements inside\nthe listener element by setting the `selector` property.\n\nIn the following example, only the elements matching `.has-menu` will open the context menu:\n\n```html\n<vaadin-context-menu selector=\".has-menu\">\n <p class=\"has-menu\">This paragraph opens the context menu</p>\n <p>This paragraph does not open the context menu</p>\n</vaadin-context-menu>\n```\n\n### Menu Context\n\nThe following properties are available in the `context` argument:\n\n- `target` is the menu opening event target, which is the element that\nthe user has called the context menu for\n- `detail` is the menu opening event detail\n\nIn the following example, the menu item text is composed with the contents\nof the element that opened the menu:\n\n```html\n<vaadin-context-menu selector=\"li\" id=\"contextMenu\">\n <ul>\n <li>Foo</li>\n <li>Bar</li>\n <li>Baz</li>\n </ul>\n</vaadin-context-menu>\n```\n```js\nconst contextMenu = document.querySelector('#contextMenu');\ncontextMenu.renderer = (root, contextMenu, context) => {\n let listBox = root.firstElementChild;\n if (!listBox) {\n listBox = document.createElement('vaadin-list-box');\n root.appendChild(listBox);\n }\n\n let item = listBox.querySelector('vaadin-item');\n if (!item) {\n item = document.createElement('vaadin-item');\n listBox.appendChild(item);\n }\n item.textContent = 'The menu target: ' + context.target.textContent;\n};\n```\n\n### Styling\n\nThe following shadow DOM parts are available for styling:\n\nPart name | Description\n-----------------|-------------------------------------------\n`backdrop` | Backdrop of the overlay\n`overlay` | The overlay container\n`content` | The overlay content\n\n### Custom CSS Properties\n\nThe following custom CSS properties are available for styling:\n\nCustom CSS property | Description\n--------------------------------------|-------------\n`--vaadin-context-menu-offset-top` | Used as an offset when using `position` and the context menu is aligned vertically below the target\n`--vaadin-context-menu-offset-bottom` | Used as an offset when using `position` and the context menu is aligned vertically above the target\n`--vaadin-context-menu-offset-start` | Used as an offset when using `position` and the context menu is aligned horizontally after the target\n`--vaadin-context-menu-offset-end` | Used as an offset when using `position` and the context menu is aligned horizontally before the target\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.\n\n### Internal components\n\nWhen using `items` API the following internal components are themable:\n\n- `<vaadin-context-menu-item>` - has the same API as [`<vaadin-item>`](https://cdn.vaadin.com/vaadin-web-components/25.2.0-beta1/#/elements/vaadin-item).\n- `<vaadin-context-menu-list-box>` - has the same API as [`<vaadin-list-box>`](https://cdn.vaadin.com/vaadin-web-components/25.2.0-beta1/#/elements/vaadin-list-box).\n\nThe `<vaadin-context-menu-item>` sub-menu elements have the following additional state attributes\non top of the built-in `<vaadin-item>` state attributes:\n\nAttribute | Description\n---------- |-------------\n`expanded` | Expanded parent item.",
|
|
12
12
|
"attributes": [
|
|
13
13
|
{
|
|
14
14
|
"name": "close-on",
|
|
15
15
|
"description": "Event name to listen for closing the context menu.",
|
|
16
16
|
"value": {
|
|
17
17
|
"type": [
|
|
18
|
-
"string"
|
|
19
|
-
"null",
|
|
20
|
-
"undefined"
|
|
18
|
+
"string"
|
|
21
19
|
]
|
|
22
20
|
}
|
|
23
21
|
},
|
|
@@ -26,9 +24,7 @@
|
|
|
26
24
|
"description": "Event name to listen for opening the context menu.",
|
|
27
25
|
"value": {
|
|
28
26
|
"type": [
|
|
29
|
-
"string"
|
|
30
|
-
"null",
|
|
31
|
-
"undefined"
|
|
27
|
+
"string"
|
|
32
28
|
]
|
|
33
29
|
}
|
|
34
30
|
},
|
|
@@ -37,9 +33,7 @@
|
|
|
37
33
|
"description": "Position of the overlay with respect to the target.\nSupported values: null, `top-start`, `top`, `top-end`,\n`bottom-start`, `bottom`, `bottom-end`, `start-top`,\n`start`, `start-bottom`, `end-top`, `end`, `end-bottom`.",
|
|
38
34
|
"value": {
|
|
39
35
|
"type": [
|
|
40
|
-
"string"
|
|
41
|
-
"null",
|
|
42
|
-
"undefined"
|
|
36
|
+
"string"
|
|
43
37
|
]
|
|
44
38
|
}
|
|
45
39
|
},
|
|
@@ -48,9 +42,7 @@
|
|
|
48
42
|
"description": "CSS selector that can be used to target any child element\nof the context menu to listen for `openOn` events.",
|
|
49
43
|
"value": {
|
|
50
44
|
"type": [
|
|
51
|
-
"string"
|
|
52
|
-
"null",
|
|
53
|
-
"undefined"
|
|
45
|
+
"string"
|
|
54
46
|
]
|
|
55
47
|
}
|
|
56
48
|
},
|
|
@@ -73,18 +65,16 @@
|
|
|
73
65
|
"description": "Event name to listen for closing the context menu.",
|
|
74
66
|
"value": {
|
|
75
67
|
"type": [
|
|
76
|
-
"string"
|
|
77
|
-
"null",
|
|
78
|
-
"undefined"
|
|
68
|
+
"string"
|
|
79
69
|
]
|
|
80
70
|
}
|
|
81
71
|
},
|
|
82
72
|
{
|
|
83
73
|
"name": "items",
|
|
84
|
-
"description": "Defines a (hierarchical) menu structure for the component.\nIf a menu item has a non-empty `children` set, a sub-menu with the child items is opened\nnext to the parent menu on mouseover, tap or a right arrow keypress.\n\nThe items API can't be used together with a renderer!\n\n#### Example\n\n```javascript\ncontextMenu.items = [\n { text: 'Menu Item 1', theme: 'primary', className: 'first', children:\n [\n { text: 'Menu Item 1-1', checked: true, keepOpen: true },\n { text: 'Menu Item 1-2' }\n ]\n },\n { component: 'hr' },\n { text: 'Menu Item 2', children:\n [\n { text: 'Menu Item 2-1' },\n { text: 'Menu Item 2-2', disabled: true }\n ]\n },\n { text: 'Menu Item 3', disabled: true, className: 'last' }\n];\n```",
|
|
74
|
+
"description": "Defines a (hierarchical) menu structure for the component.\nIf a menu item has a non-empty `children` set, a sub-menu with the child items is opened\nnext to the parent menu on mouseover, tap or a right arrow keypress.\n\nThe items API can't be used together with a renderer!\n\n#### Example\n\n```javascript\ncontextMenu.items = [\n { text: 'Menu Item 1', theme: 'primary', className: 'first', children:\n [\n { text: 'Menu Item 1-1', checked: true, keepOpen: true },\n { text: 'Menu Item 1-2' }\n ]\n },\n { component: 'hr' },\n { text: 'Menu Item 2', children:\n [\n { text: 'Menu Item 2-1' },\n { text: 'Menu Item 2-2', disabled: true }\n ]\n },\n { text: 'Menu Item 3', disabled: true, className: 'last' }\n];\n```\n\n#### Item tooltips\n\nMenu items can have tooltips that are shown on hover and keyboard\nfocus. To enable them, add a slotted `<vaadin-tooltip>` element\nand set the `tooltip` property on each item that should have one:\n\n```html\n<vaadin-context-menu>\n <vaadin-tooltip slot=\"tooltip\"></vaadin-tooltip>\n</vaadin-context-menu>\n```",
|
|
85
75
|
"value": {
|
|
86
76
|
"type": [
|
|
87
|
-
"Array
|
|
77
|
+
"Array<ContextMenuItem>",
|
|
88
78
|
"undefined"
|
|
89
79
|
]
|
|
90
80
|
}
|
|
@@ -103,9 +93,7 @@
|
|
|
103
93
|
"description": "Event name to listen for opening the context menu.",
|
|
104
94
|
"value": {
|
|
105
95
|
"type": [
|
|
106
|
-
"string"
|
|
107
|
-
"null",
|
|
108
|
-
"undefined"
|
|
96
|
+
"string"
|
|
109
97
|
]
|
|
110
98
|
}
|
|
111
99
|
},
|
|
@@ -114,9 +102,7 @@
|
|
|
114
102
|
"description": "Position of the overlay with respect to the target.\nSupported values: null, `top-start`, `top`, `top-end`,\n`bottom-start`, `bottom`, `bottom-end`, `start-top`,\n`start`, `start-bottom`, `end-top`, `end`, `end-bottom`.",
|
|
115
103
|
"value": {
|
|
116
104
|
"type": [
|
|
117
|
-
"string"
|
|
118
|
-
"null",
|
|
119
|
-
"undefined"
|
|
105
|
+
"string"
|
|
120
106
|
]
|
|
121
107
|
}
|
|
122
108
|
},
|
|
@@ -135,14 +121,16 @@
|
|
|
135
121
|
"description": "CSS selector that can be used to target any child element\nof the context menu to listen for `openOn` events.",
|
|
136
122
|
"value": {
|
|
137
123
|
"type": [
|
|
138
|
-
"string"
|
|
139
|
-
"null",
|
|
140
|
-
"undefined"
|
|
124
|
+
"string"
|
|
141
125
|
]
|
|
142
126
|
}
|
|
143
127
|
}
|
|
144
128
|
],
|
|
145
129
|
"events": [
|
|
130
|
+
{
|
|
131
|
+
"name": "close-all-menus",
|
|
132
|
+
"description": "Fired when all menus should close, e.g., after pressing Tab or on submenu close."
|
|
133
|
+
},
|
|
146
134
|
{
|
|
147
135
|
"name": "closed",
|
|
148
136
|
"description": "Fired when the context menu is closed."
|
|
@@ -151,6 +139,10 @@
|
|
|
151
139
|
"name": "item-selected",
|
|
152
140
|
"description": "Fired when an item is selected when the context menu is populated using the `items` API."
|
|
153
141
|
},
|
|
142
|
+
{
|
|
143
|
+
"name": "items-outside-click",
|
|
144
|
+
"description": "Fired when a click happens outside any open sub-menus."
|
|
145
|
+
},
|
|
154
146
|
{
|
|
155
147
|
"name": "opened-changed",
|
|
156
148
|
"description": "Fired when the `opened` property changes."
|
package/web-types.lit.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/web-types",
|
|
3
3
|
"name": "@vaadin/context-menu",
|
|
4
|
-
"version": "25.2.0-
|
|
4
|
+
"version": "25.2.0-beta1",
|
|
5
5
|
"description-markup": "markdown",
|
|
6
6
|
"framework": "lit",
|
|
7
7
|
"framework-config": {
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"elements": [
|
|
17
17
|
{
|
|
18
18
|
"name": "vaadin-context-menu",
|
|
19
|
-
"description": "`<vaadin-context-menu>` is a Web Component for creating context menus.\n\n### Items\n\nItems is a higher level convenience API for defining a (hierarchical) menu structure for the component.\nIf a menu item has a non-empty `children` set, a sub-menu with the child items is opened\nnext to the parent menu on mouseover, tap or a right arrow keypress.\n\nWhen an item is selected, `<vaadin-context-menu>` dispatches an \"item-selected\" event\nwith the selected item as `event.detail.value` property.\nIf item does not have `keepOpen` property the menu will be closed.\n\n```javascript\ncontextMenu.items = [\n { text: 'Menu Item 1', theme: 'primary', className: 'first', children:\n [\n { text: 'Menu Item 1-1', checked: true, keepOpen: true },\n { text: 'Menu Item 1-2' }\n ]\n },\n { component: 'hr' },\n { text: 'Menu Item 2', children:\n [\n { text: 'Menu Item 2-1' },\n { text: 'Menu Item 2-2', disabled: true }\n ]\n },\n { text: 'Menu Item 3', disabled: true, className: 'last' }\n];\n\ncontextMenu.addEventListener('item-selected', e => {\n const item = e.detail.value;\n console.log(`${item.text} selected`);\n});\n```\n\n**NOTE:** when the `items` array is defined, the renderer cannot be used.\n\n### Rendering\n\nThe content of the menu can be populated by using the renderer callback function.\n\nThe renderer function provides `root`, `contextMenu`, `model` arguments when applicable.\nGenerate DOM content by using `model` object properties if needed, append it to the `root`\nelement and control the state of the host element by accessing `contextMenu`. Before generating\nnew content, the renderer function should check if there is already content in `root` for reusing it.\n\n```html\n<vaadin-context-menu id=\"contextMenu\">\n <p>This paragraph has a context menu.</p>\n</vaadin-context-menu>\n```\n```js\nconst contextMenu = document.querySelector('#contextMenu');\ncontextMenu.renderer = (root, contextMenu, context) => {\n let listBox = root.firstElementChild;\n if (!listBox) {\n listBox = document.createElement('vaadin-list-box');\n root.appendChild(listBox);\n }\n\n let item = listBox.querySelector('vaadin-item');\n if (!item) {\n item = document.createElement('vaadin-item');\n listBox.appendChild(item);\n }\n item.textContent = 'Content of the selector: ' + context.target.textContent;\n};\n```\n\nYou can access the menu context inside the renderer using\n`context.target` and `context.detail`.\n\nRenderer is called on the opening of the context-menu and each time the related context is updated.\nDOM generated during the renderer call can be reused\nin the next renderer call and will be provided with the `root` argument.\nOn first call it will be empty.\n\n### `vaadin-contextmenu` Gesture Event\n\n`vaadin-contextmenu` is a gesture event (a custom event),\nwhich is dispatched after either `contextmenu` or long touch events.\nThis enables support for both mouse and touch environments in a uniform way.\n\n`<vaadin-context-menu>` opens the menu overlay on the `vaadin-contextmenu`\nevent by default.\n\n### Menu Listener\n\nBy default, the `<vaadin-context-menu>` element listens for the menu opening\nevent on itself. In case if you do not want to wrap the target, you can listen for\nevents on an element outside the `<vaadin-context-menu>` by setting the\n`listenOn` property:\n\n```html\n<vaadin-context-menu id=\"contextMenu\"></vaadin-context-menu>\n\n<div id=\"menuListener\">The element that listens for the contextmenu event.</div>\n```\n```javascript\nconst contextMenu = document.querySelector('#contextMenu');\ncontextMenu.listenOn = document.querySelector('#menuListener');\n```\n\n### Filtering Menu Targets\n\nBy default, the listener element and all its descendants open the context\nmenu. You can filter the menu targets to a smaller set of elements inside\nthe listener element by setting the `selector` property.\n\nIn the following example, only the elements matching `.has-menu` will open the context menu:\n\n```html\n<vaadin-context-menu selector=\".has-menu\">\n <p class=\"has-menu\">This paragraph opens the context menu</p>\n <p>This paragraph does not open the context menu</p>\n</vaadin-context-menu>\n```\n\n### Menu Context\n\nThe following properties are available in the `context` argument:\n\n- `target` is the menu opening event target, which is the element that\nthe user has called the context menu for\n- `detail` is the menu opening event detail\n\nIn the following example, the menu item text is composed with the contents\nof the element that opened the menu:\n\n```html\n<vaadin-context-menu selector=\"li\" id=\"contextMenu\">\n <ul>\n <li>Foo</li>\n <li>Bar</li>\n <li>Baz</li>\n </ul>\n</vaadin-context-menu>\n```\n```js\nconst contextMenu = document.querySelector('#contextMenu');\ncontextMenu.renderer = (root, contextMenu, context) => {\n let listBox = root.firstElementChild;\n if (!listBox) {\n listBox = document.createElement('vaadin-list-box');\n root.appendChild(listBox);\n }\n\n let item = listBox.querySelector('vaadin-item');\n if (!item) {\n item = document.createElement('vaadin-item');\n listBox.appendChild(item);\n }\n item.textContent = 'The menu target: ' + context.target.textContent;\n};\n```\n\n### Styling\n\nThe following shadow DOM parts are available for styling:\n\nPart name | Description\n-----------------|-------------------------------------------\n`backdrop` | Backdrop of the overlay\n`overlay` | The overlay container\n`content` | The overlay content\n\n### Custom CSS Properties\n\nThe following custom CSS properties are available for styling:\n\nCustom CSS property | Description\n--------------------------------------|-------------\n`--vaadin-context-menu-offset-top` | Used as an offset when using `position` and the context menu is aligned vertically below the target\n`--vaadin-context-menu-offset-bottom` | Used as an offset when using `position` and the context menu is aligned vertically above the target\n`--vaadin-context-menu-offset-start` | Used as an offset when using `position` and the context menu is aligned horizontally after the target\n`--vaadin-context-menu-offset-end` | Used as an offset when using `position` and the context menu is aligned horizontally before the target\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.\n\n### Internal components\n\nWhen using `items` API the following internal components are themable:\n\n- `<vaadin-context-menu-item>` - has the same API as [`<vaadin-item>`](https://cdn.vaadin.com/vaadin-web-components/25.2.0-
|
|
19
|
+
"description": "`<vaadin-context-menu>` is a Web Component for creating context menus.\n\n### Items\n\nItems is a higher level convenience API for defining a (hierarchical) menu structure for the component.\nIf a menu item has a non-empty `children` set, a sub-menu with the child items is opened\nnext to the parent menu on mouseover, tap or a right arrow keypress.\n\nWhen an item is selected, `<vaadin-context-menu>` dispatches an \"item-selected\" event\nwith the selected item as `event.detail.value` property.\nIf item does not have `keepOpen` property the menu will be closed.\n\n```javascript\ncontextMenu.items = [\n { text: 'Menu Item 1', theme: 'primary', className: 'first', children:\n [\n { text: 'Menu Item 1-1', checked: true, keepOpen: true },\n { text: 'Menu Item 1-2' }\n ]\n },\n { component: 'hr' },\n { text: 'Menu Item 2', children:\n [\n { text: 'Menu Item 2-1' },\n { text: 'Menu Item 2-2', disabled: true }\n ]\n },\n { text: 'Menu Item 3', disabled: true, className: 'last' }\n];\n\ncontextMenu.addEventListener('item-selected', e => {\n const item = e.detail.value;\n console.log(`${item.text} selected`);\n});\n```\n\n**NOTE:** when the `items` array is defined, the renderer cannot be used.\n\n#### Disabled menu items\n\nWhen disabled, menu items are rendered as \"dimmed\".\n\nBy default, disabled items are not focusable and don't react to hover.\nAs a result, they are hidden from assistive technologies, and it's not\npossible to show a tooltip to explain why they are disabled. This can\nbe addressed by enabling the feature flag `accessibleDisabledMenuItems`,\nwhich makes disabled items focusable and hoverable, while still\npreventing them from being activated:\n\n```js\n// Set before any context menu is attached to the DOM.\nwindow.Vaadin.featureFlags.accessibleDisabledMenuItems = true;\n```\n\n#### Item tooltips\n\nMenu items can have tooltips that are shown on hover and keyboard\nfocus. To enable them, add a slotted `<vaadin-tooltip>` element\nand set the `tooltip` property on each item that should have one:\n\n```html\n<vaadin-context-menu>\n <vaadin-tooltip slot=\"tooltip\"></vaadin-tooltip>\n</vaadin-context-menu>\n```\n\n### Rendering\n\nThe content of the menu can be populated by using the renderer callback function.\n\nThe renderer function provides `root`, `contextMenu`, `model` arguments when applicable.\nGenerate DOM content by using `model` object properties if needed, append it to the `root`\nelement and control the state of the host element by accessing `contextMenu`. Before generating\nnew content, the renderer function should check if there is already content in `root` for reusing it.\n\n```html\n<vaadin-context-menu id=\"contextMenu\">\n <p>This paragraph has a context menu.</p>\n</vaadin-context-menu>\n```\n```js\nconst contextMenu = document.querySelector('#contextMenu');\ncontextMenu.renderer = (root, contextMenu, context) => {\n let listBox = root.firstElementChild;\n if (!listBox) {\n listBox = document.createElement('vaadin-list-box');\n root.appendChild(listBox);\n }\n\n let item = listBox.querySelector('vaadin-item');\n if (!item) {\n item = document.createElement('vaadin-item');\n listBox.appendChild(item);\n }\n item.textContent = 'Content of the selector: ' + context.target.textContent;\n};\n```\n\nYou can access the menu context inside the renderer using\n`context.target` and `context.detail`.\n\nRenderer is called on the opening of the context-menu and each time the related context is updated.\nDOM generated during the renderer call can be reused\nin the next renderer call and will be provided with the `root` argument.\nOn first call it will be empty.\n\n### `vaadin-contextmenu` Gesture Event\n\n`vaadin-contextmenu` is a gesture event (a custom event),\nwhich is dispatched after either `contextmenu` or long touch events.\nThis enables support for both mouse and touch environments in a uniform way.\n\n`<vaadin-context-menu>` opens the menu overlay on the `vaadin-contextmenu`\nevent by default.\n\n### Menu Listener\n\nBy default, the `<vaadin-context-menu>` element listens for the menu opening\nevent on itself. In case if you do not want to wrap the target, you can listen for\nevents on an element outside the `<vaadin-context-menu>` by setting the\n`listenOn` property:\n\n```html\n<vaadin-context-menu id=\"contextMenu\"></vaadin-context-menu>\n\n<div id=\"menuListener\">The element that listens for the contextmenu event.</div>\n```\n```javascript\nconst contextMenu = document.querySelector('#contextMenu');\ncontextMenu.listenOn = document.querySelector('#menuListener');\n```\n\n### Filtering Menu Targets\n\nBy default, the listener element and all its descendants open the context\nmenu. You can filter the menu targets to a smaller set of elements inside\nthe listener element by setting the `selector` property.\n\nIn the following example, only the elements matching `.has-menu` will open the context menu:\n\n```html\n<vaadin-context-menu selector=\".has-menu\">\n <p class=\"has-menu\">This paragraph opens the context menu</p>\n <p>This paragraph does not open the context menu</p>\n</vaadin-context-menu>\n```\n\n### Menu Context\n\nThe following properties are available in the `context` argument:\n\n- `target` is the menu opening event target, which is the element that\nthe user has called the context menu for\n- `detail` is the menu opening event detail\n\nIn the following example, the menu item text is composed with the contents\nof the element that opened the menu:\n\n```html\n<vaadin-context-menu selector=\"li\" id=\"contextMenu\">\n <ul>\n <li>Foo</li>\n <li>Bar</li>\n <li>Baz</li>\n </ul>\n</vaadin-context-menu>\n```\n```js\nconst contextMenu = document.querySelector('#contextMenu');\ncontextMenu.renderer = (root, contextMenu, context) => {\n let listBox = root.firstElementChild;\n if (!listBox) {\n listBox = document.createElement('vaadin-list-box');\n root.appendChild(listBox);\n }\n\n let item = listBox.querySelector('vaadin-item');\n if (!item) {\n item = document.createElement('vaadin-item');\n listBox.appendChild(item);\n }\n item.textContent = 'The menu target: ' + context.target.textContent;\n};\n```\n\n### Styling\n\nThe following shadow DOM parts are available for styling:\n\nPart name | Description\n-----------------|-------------------------------------------\n`backdrop` | Backdrop of the overlay\n`overlay` | The overlay container\n`content` | The overlay content\n\n### Custom CSS Properties\n\nThe following custom CSS properties are available for styling:\n\nCustom CSS property | Description\n--------------------------------------|-------------\n`--vaadin-context-menu-offset-top` | Used as an offset when using `position` and the context menu is aligned vertically below the target\n`--vaadin-context-menu-offset-bottom` | Used as an offset when using `position` and the context menu is aligned vertically above the target\n`--vaadin-context-menu-offset-start` | Used as an offset when using `position` and the context menu is aligned horizontally after the target\n`--vaadin-context-menu-offset-end` | Used as an offset when using `position` and the context menu is aligned horizontally before the target\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.\n\n### Internal components\n\nWhen using `items` API the following internal components are themable:\n\n- `<vaadin-context-menu-item>` - has the same API as [`<vaadin-item>`](https://cdn.vaadin.com/vaadin-web-components/25.2.0-beta1/#/elements/vaadin-item).\n- `<vaadin-context-menu-list-box>` - has the same API as [`<vaadin-list-box>`](https://cdn.vaadin.com/vaadin-web-components/25.2.0-beta1/#/elements/vaadin-list-box).\n\nThe `<vaadin-context-menu-item>` sub-menu elements have the following additional state attributes\non top of the built-in `<vaadin-item>` state attributes:\n\nAttribute | Description\n---------- |-------------\n`expanded` | Expanded parent item.",
|
|
20
20
|
"extension": true,
|
|
21
21
|
"attributes": [
|
|
22
22
|
{
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
},
|
|
29
29
|
{
|
|
30
30
|
"name": ".items",
|
|
31
|
-
"description": "Defines a (hierarchical) menu structure for the component.\nIf a menu item has a non-empty `children` set, a sub-menu with the child items is opened\nnext to the parent menu on mouseover, tap or a right arrow keypress.\n\nThe items API can't be used together with a renderer!\n\n#### Example\n\n```javascript\ncontextMenu.items = [\n { text: 'Menu Item 1', theme: 'primary', className: 'first', children:\n [\n { text: 'Menu Item 1-1', checked: true, keepOpen: true },\n { text: 'Menu Item 1-2' }\n ]\n },\n { component: 'hr' },\n { text: 'Menu Item 2', children:\n [\n { text: 'Menu Item 2-1' },\n { text: 'Menu Item 2-2', disabled: true }\n ]\n },\n { text: 'Menu Item 3', disabled: true, className: 'last' }\n];\n```",
|
|
31
|
+
"description": "Defines a (hierarchical) menu structure for the component.\nIf a menu item has a non-empty `children` set, a sub-menu with the child items is opened\nnext to the parent menu on mouseover, tap or a right arrow keypress.\n\nThe items API can't be used together with a renderer!\n\n#### Example\n\n```javascript\ncontextMenu.items = [\n { text: 'Menu Item 1', theme: 'primary', className: 'first', children:\n [\n { text: 'Menu Item 1-1', checked: true, keepOpen: true },\n { text: 'Menu Item 1-2' }\n ]\n },\n { component: 'hr' },\n { text: 'Menu Item 2', children:\n [\n { text: 'Menu Item 2-1' },\n { text: 'Menu Item 2-2', disabled: true }\n ]\n },\n { text: 'Menu Item 3', disabled: true, className: 'last' }\n];\n```\n\n#### Item tooltips\n\nMenu items can have tooltips that are shown on hover and keyboard\nfocus. To enable them, add a slotted `<vaadin-tooltip>` element\nand set the `tooltip` property on each item that should have one:\n\n```html\n<vaadin-context-menu>\n <vaadin-tooltip slot=\"tooltip\"></vaadin-tooltip>\n</vaadin-context-menu>\n```",
|
|
32
32
|
"value": {
|
|
33
33
|
"kind": "expression"
|
|
34
34
|
}
|
|
@@ -68,6 +68,13 @@
|
|
|
68
68
|
"kind": "expression"
|
|
69
69
|
}
|
|
70
70
|
},
|
|
71
|
+
{
|
|
72
|
+
"name": "@close-all-menus",
|
|
73
|
+
"description": "Fired when all menus should close, e.g., after pressing Tab or on submenu close.",
|
|
74
|
+
"value": {
|
|
75
|
+
"kind": "expression"
|
|
76
|
+
}
|
|
77
|
+
},
|
|
71
78
|
{
|
|
72
79
|
"name": "@closed",
|
|
73
80
|
"description": "Fired when the context menu is closed.",
|
|
@@ -82,6 +89,13 @@
|
|
|
82
89
|
"kind": "expression"
|
|
83
90
|
}
|
|
84
91
|
},
|
|
92
|
+
{
|
|
93
|
+
"name": "@items-outside-click",
|
|
94
|
+
"description": "Fired when a click happens outside any open sub-menus.",
|
|
95
|
+
"value": {
|
|
96
|
+
"kind": "expression"
|
|
97
|
+
}
|
|
98
|
+
},
|
|
85
99
|
{
|
|
86
100
|
"name": "@opened-changed",
|
|
87
101
|
"description": "Fired when the `opened` property changes.",
|