@vaadin/context-menu 25.0.0-alpha9 → 25.0.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/package.json +13 -16
- package/src/styles/vaadin-context-menu-item-base-styles.js +3 -3
- package/src/styles/vaadin-context-menu-overlay-base-styles.js +28 -1
- package/src/vaadin-context-menu-item.js +1 -1
- package/src/vaadin-context-menu-list-box.js +1 -1
- package/src/vaadin-context-menu-mixin.js +19 -6
- package/src/vaadin-context-menu-overlay.js +55 -1
- package/src/vaadin-context-menu.d.ts +41 -5
- package/src/vaadin-context-menu.js +73 -9
- package/src/vaadin-contextmenu-items-mixin.js +25 -15
- package/src/vaadin-menu-overlay-mixin.js +1 -1
- package/vaadin-context-menu.js +1 -1
- package/web-types.json +10 -6
- package/web-types.lit.json +11 -4
- package/src/styles/vaadin-context-menu-item-core-styles.d.ts +0 -8
- package/src/styles/vaadin-context-menu-item-core-styles.js +0 -8
- package/src/styles/vaadin-context-menu-overlay-core-styles.d.ts +0 -8
- package/src/styles/vaadin-context-menu-overlay-core-styles.js +0 -9
- package/src/styles/vaadin-menu-overlay-core-styles.d.ts +0 -8
- package/src/styles/vaadin-menu-overlay-core-styles.js +0 -32
- package/theme/lumo/vaadin-context-menu-item-styles.d.ts +0 -6
- package/theme/lumo/vaadin-context-menu-item-styles.js +0 -45
- package/theme/lumo/vaadin-context-menu-list-box-styles.d.ts +0 -5
- package/theme/lumo/vaadin-context-menu-list-box-styles.js +0 -47
- package/theme/lumo/vaadin-context-menu-overlay-styles.d.ts +0 -4
- package/theme/lumo/vaadin-context-menu-overlay-styles.js +0 -35
- package/theme/lumo/vaadin-context-menu.d.ts +0 -4
- package/theme/lumo/vaadin-context-menu.js +0 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vaadin/context-menu",
|
|
3
|
-
"version": "25.0.0-
|
|
3
|
+
"version": "25.0.0-beta1",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -23,9 +23,6 @@
|
|
|
23
23
|
"lit.d.ts",
|
|
24
24
|
"lit.js",
|
|
25
25
|
"src",
|
|
26
|
-
"!src/styles/*-base-styles.d.ts",
|
|
27
|
-
"!src/styles/*-base-styles.js",
|
|
28
|
-
"theme",
|
|
29
26
|
"vaadin-*.d.ts",
|
|
30
27
|
"vaadin-*.js",
|
|
31
28
|
"web-types.json",
|
|
@@ -39,25 +36,25 @@
|
|
|
39
36
|
],
|
|
40
37
|
"dependencies": {
|
|
41
38
|
"@open-wc/dedupe-mixin": "^1.3.0",
|
|
42
|
-
"@vaadin/a11y-base": "25.0.0-
|
|
43
|
-
"@vaadin/component-base": "25.0.0-
|
|
44
|
-
"@vaadin/item": "25.0.0-
|
|
45
|
-
"@vaadin/list-box": "25.0.0-
|
|
46
|
-
"@vaadin/lit-renderer": "25.0.0-
|
|
47
|
-
"@vaadin/overlay": "25.0.0-
|
|
48
|
-
"@vaadin/vaadin-
|
|
49
|
-
"@vaadin/vaadin-themable-mixin": "25.0.0-alpha9",
|
|
39
|
+
"@vaadin/a11y-base": "25.0.0-beta1",
|
|
40
|
+
"@vaadin/component-base": "25.0.0-beta1",
|
|
41
|
+
"@vaadin/item": "25.0.0-beta1",
|
|
42
|
+
"@vaadin/list-box": "25.0.0-beta1",
|
|
43
|
+
"@vaadin/lit-renderer": "25.0.0-beta1",
|
|
44
|
+
"@vaadin/overlay": "25.0.0-beta1",
|
|
45
|
+
"@vaadin/vaadin-themable-mixin": "25.0.0-beta1",
|
|
50
46
|
"lit": "^3.0.0"
|
|
51
47
|
},
|
|
52
48
|
"devDependencies": {
|
|
53
|
-
"@vaadin/chai-plugins": "25.0.0-
|
|
54
|
-
"@vaadin/test-runner-commands": "25.0.0-
|
|
49
|
+
"@vaadin/chai-plugins": "25.0.0-beta1",
|
|
50
|
+
"@vaadin/test-runner-commands": "25.0.0-beta1",
|
|
55
51
|
"@vaadin/testing-helpers": "^2.0.0",
|
|
56
|
-
"
|
|
52
|
+
"@vaadin/vaadin-lumo-styles": "25.0.0-beta1",
|
|
53
|
+
"sinon": "^21.0.0"
|
|
57
54
|
},
|
|
58
55
|
"web-types": [
|
|
59
56
|
"web-types.json",
|
|
60
57
|
"web-types.lit.json"
|
|
61
58
|
],
|
|
62
|
-
"gitHead": "
|
|
59
|
+
"gitHead": "1d20cf54e582d1f2e209126d4586f8b4c01c50e0"
|
|
63
60
|
}
|
|
@@ -3,17 +3,17 @@
|
|
|
3
3
|
* Copyright (c) 2016 - 2025 Vaadin Ltd.
|
|
4
4
|
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
5
|
*/
|
|
6
|
-
import '@vaadin/component-base/src/style-props.js';
|
|
6
|
+
import '@vaadin/component-base/src/styles/style-props.js';
|
|
7
7
|
import { css } from 'lit';
|
|
8
8
|
import { itemStyles } from '@vaadin/item/src/styles/vaadin-item-base-styles.js';
|
|
9
9
|
|
|
10
10
|
const menuItemStyles = css`
|
|
11
11
|
:host::after {
|
|
12
|
-
background: var(--vaadin-color-
|
|
12
|
+
background: var(--vaadin-text-color-secondary);
|
|
13
13
|
content: '';
|
|
14
14
|
display: block;
|
|
15
15
|
height: var(--vaadin-icon-size, 1lh);
|
|
16
|
-
mask
|
|
16
|
+
mask: var(--_vaadin-icon-chevron-down) 50% / var(--vaadin-icon-visual-size, 100%) no-repeat;
|
|
17
17
|
rotate: -90deg;
|
|
18
18
|
visibility: hidden;
|
|
19
19
|
width: var(--vaadin-icon-size, 1lh);
|
|
@@ -3,7 +3,34 @@
|
|
|
3
3
|
* Copyright (c) 2016 - 2025 Vaadin Ltd.
|
|
4
4
|
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
5
|
*/
|
|
6
|
+
import { css } from 'lit';
|
|
6
7
|
import { overlayStyles } from '@vaadin/overlay/src/styles/vaadin-overlay-base-styles.js';
|
|
7
8
|
import { menuOverlayStyles } from './vaadin-menu-overlay-base-styles.js';
|
|
8
9
|
|
|
9
|
-
|
|
10
|
+
const contextMenuOverlay = css`
|
|
11
|
+
:host {
|
|
12
|
+
--_default-offset: 4px;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
:host([position^='top'][top-aligned]) [part='overlay'],
|
|
16
|
+
:host([position^='bottom'][top-aligned]) [part='overlay'] {
|
|
17
|
+
margin-top: var(--vaadin-context-menu-offset-top, var(--_default-offset));
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
:host([position^='top'][bottom-aligned]) [part='overlay'],
|
|
21
|
+
:host([position^='bottom'][bottom-aligned]) [part='overlay'] {
|
|
22
|
+
margin-bottom: var(--vaadin-context-menu-offset-bottom, var(--_default-offset));
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
:host([position^='start'][start-aligned]) [part='overlay'],
|
|
26
|
+
:host([position^='end'][start-aligned]) [part='overlay'] {
|
|
27
|
+
margin-inline-start: var(--vaadin-context-menu-offset-start, var(--_default-offset));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
:host([position^='start'][end-aligned]) [part='overlay'],
|
|
31
|
+
:host([position^='end'][end-aligned]) [part='overlay'] {
|
|
32
|
+
margin-inline-end: var(--vaadin-context-menu-offset-end, var(--_default-offset));
|
|
33
|
+
}
|
|
34
|
+
`;
|
|
35
|
+
|
|
36
|
+
export const contextMenuOverlayStyles = [overlayStyles, menuOverlayStyles, contextMenuOverlay];
|
|
@@ -10,7 +10,7 @@ import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
|
|
|
10
10
|
import { ItemMixin } from '@vaadin/item/src/vaadin-item-mixin.js';
|
|
11
11
|
import { LumoInjectionMixin } from '@vaadin/vaadin-themable-mixin/lumo-injection-mixin.js';
|
|
12
12
|
import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
13
|
-
import { contextMenuItemStyles } from './styles/vaadin-context-menu-item-
|
|
13
|
+
import { contextMenuItemStyles } from './styles/vaadin-context-menu-item-base-styles.js';
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* An element used internally by `<vaadin-context-menu>`. Not intended to be used separately.
|
|
@@ -8,7 +8,7 @@ import { ListMixin } from '@vaadin/a11y-base/src/list-mixin.js';
|
|
|
8
8
|
import { defineCustomElement } from '@vaadin/component-base/src/define.js';
|
|
9
9
|
import { DirMixin } from '@vaadin/component-base/src/dir-mixin.js';
|
|
10
10
|
import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
|
|
11
|
-
import { listBoxStyles } from '@vaadin/list-box/src/styles/vaadin-list-box-
|
|
11
|
+
import { listBoxStyles } from '@vaadin/list-box/src/styles/vaadin-list-box-base-styles.js';
|
|
12
12
|
import { LumoInjectionMixin } from '@vaadin/vaadin-themable-mixin/lumo-injection-mixin.js';
|
|
13
13
|
import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
14
14
|
|
|
@@ -209,6 +209,14 @@ export const ContextMenuMixin = (superClass) =>
|
|
|
209
209
|
this.__forwardFocus();
|
|
210
210
|
}
|
|
211
211
|
|
|
212
|
+
/**
|
|
213
|
+
* Runs after overlay's closing animation is finished
|
|
214
|
+
* @private
|
|
215
|
+
*/
|
|
216
|
+
_onVaadinOverlayClosed() {
|
|
217
|
+
this.dispatchEvent(new CustomEvent('closed'));
|
|
218
|
+
}
|
|
219
|
+
|
|
212
220
|
/** @private */
|
|
213
221
|
_targetOrOpenOnChanged(listenOn, openOn) {
|
|
214
222
|
if (this._oldListenOn && this._oldOpenOn) {
|
|
@@ -334,6 +342,9 @@ export const ContextMenuMixin = (superClass) =>
|
|
|
334
342
|
return Array.prototype.filter.call(targets, (el) => {
|
|
335
343
|
return e.composedPath().indexOf(el) > -1;
|
|
336
344
|
})[0];
|
|
345
|
+
} else if (this.listenOn && this.listenOn !== this && this.position) {
|
|
346
|
+
// If listenOn has been set on a different element than the context menu root, then use listenOn as the target.
|
|
347
|
+
return this.listenOn;
|
|
337
348
|
}
|
|
338
349
|
return e.target;
|
|
339
350
|
}
|
|
@@ -427,17 +438,13 @@ export const ContextMenuMixin = (superClass) =>
|
|
|
427
438
|
/** @private */
|
|
428
439
|
__focusItem(item) {
|
|
429
440
|
if (item) {
|
|
430
|
-
item.focus();
|
|
431
|
-
|
|
432
|
-
if (isKeyboardActive()) {
|
|
433
|
-
item.setAttribute('focus-ring', '');
|
|
434
|
-
}
|
|
441
|
+
item.focus({ focusVisible: isKeyboardActive() });
|
|
435
442
|
}
|
|
436
443
|
}
|
|
437
444
|
|
|
438
445
|
/** @private */
|
|
439
446
|
__onScroll() {
|
|
440
|
-
if (!this.opened) {
|
|
447
|
+
if (!this.opened || this.position) {
|
|
441
448
|
return;
|
|
442
449
|
}
|
|
443
450
|
|
|
@@ -641,4 +648,10 @@ export const ContextMenuMixin = (superClass) =>
|
|
|
641
648
|
this.close();
|
|
642
649
|
}
|
|
643
650
|
}
|
|
651
|
+
|
|
652
|
+
/**
|
|
653
|
+
* Fired when the context menu is closed.
|
|
654
|
+
*
|
|
655
|
+
* @event closed
|
|
656
|
+
*/
|
|
644
657
|
};
|
|
@@ -10,7 +10,7 @@ import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
|
|
|
10
10
|
import { OverlayMixin } from '@vaadin/overlay/src/vaadin-overlay-mixin.js';
|
|
11
11
|
import { LumoInjectionMixin } from '@vaadin/vaadin-themable-mixin/lumo-injection-mixin.js';
|
|
12
12
|
import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
13
|
-
import { contextMenuOverlayStyles } from './styles/vaadin-context-menu-overlay-
|
|
13
|
+
import { contextMenuOverlayStyles } from './styles/vaadin-context-menu-overlay-base-styles.js';
|
|
14
14
|
import { MenuOverlayMixin } from './vaadin-menu-overlay-mixin.js';
|
|
15
15
|
|
|
16
16
|
/**
|
|
@@ -31,10 +31,64 @@ export class ContextMenuOverlay extends MenuOverlayMixin(
|
|
|
31
31
|
return 'vaadin-context-menu-overlay';
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
static get properties() {
|
|
35
|
+
return {
|
|
36
|
+
/**
|
|
37
|
+
* Position of the overlay with respect to the target.
|
|
38
|
+
* Supported values: null, `top-start`, `top`, `top-end`,
|
|
39
|
+
* `bottom-start`, `bottom`, `bottom-end`, `start-top`,
|
|
40
|
+
* `start`, `start-bottom`, `end-top`, `end`, `end-bottom`.
|
|
41
|
+
*/
|
|
42
|
+
position: {
|
|
43
|
+
type: String,
|
|
44
|
+
reflectToAttribute: true,
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
|
|
34
49
|
static get styles() {
|
|
35
50
|
return contextMenuOverlayStyles;
|
|
36
51
|
}
|
|
37
52
|
|
|
53
|
+
/**
|
|
54
|
+
* @protected
|
|
55
|
+
* @override
|
|
56
|
+
*/
|
|
57
|
+
_updatePosition() {
|
|
58
|
+
super._updatePosition();
|
|
59
|
+
|
|
60
|
+
if (this.parentOverlay == null && this.positionTarget && this.position && this.opened) {
|
|
61
|
+
if (this.position === 'bottom' || this.position === 'top') {
|
|
62
|
+
const targetRect = this.positionTarget.getBoundingClientRect();
|
|
63
|
+
const overlayRect = this.$.overlay.getBoundingClientRect();
|
|
64
|
+
|
|
65
|
+
const offset = targetRect.width / 2 - overlayRect.width / 2;
|
|
66
|
+
|
|
67
|
+
if (this.style.left) {
|
|
68
|
+
const left = overlayRect.left + offset;
|
|
69
|
+
if (left > 0) {
|
|
70
|
+
this.style.left = `${left}px`;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (this.style.right) {
|
|
75
|
+
const right = parseFloat(this.style.right) + offset;
|
|
76
|
+
if (right > 0) {
|
|
77
|
+
this.style.right = `${right}px`;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (this.position === 'start' || this.position === 'end') {
|
|
83
|
+
const targetRect = this.positionTarget.getBoundingClientRect();
|
|
84
|
+
const overlayRect = this.$.overlay.getBoundingClientRect();
|
|
85
|
+
|
|
86
|
+
const offset = targetRect.height / 2 - overlayRect.height / 2;
|
|
87
|
+
this.style.top = `${overlayRect.top + offset}px`;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
38
92
|
/** @protected */
|
|
39
93
|
render() {
|
|
40
94
|
return html`
|
|
@@ -4,13 +4,26 @@
|
|
|
4
4
|
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
5
|
*/
|
|
6
6
|
import type { ElementMixinClass } from '@vaadin/component-base/src/element-mixin.js';
|
|
7
|
-
import type { OverlayClassMixinClass } from '@vaadin/component-base/src/overlay-class-mixin.js';
|
|
8
7
|
import type { ThemePropertyMixinClass } from '@vaadin/vaadin-themable-mixin/vaadin-theme-property-mixin.js';
|
|
9
8
|
import type { ContextMenuMixinClass } from './vaadin-context-menu-mixin.js';
|
|
10
9
|
import type { ContextMenuItem } from './vaadin-contextmenu-items-mixin.js';
|
|
11
10
|
|
|
12
11
|
export { ContextMenuItem };
|
|
13
12
|
|
|
13
|
+
export type ContextMenuPosition =
|
|
14
|
+
| 'bottom-end'
|
|
15
|
+
| 'bottom-start'
|
|
16
|
+
| 'bottom'
|
|
17
|
+
| 'end-bottom'
|
|
18
|
+
| 'end-top'
|
|
19
|
+
| 'end'
|
|
20
|
+
| 'start-bottom'
|
|
21
|
+
| 'start-top'
|
|
22
|
+
| 'start'
|
|
23
|
+
| 'top-end'
|
|
24
|
+
| 'top-start'
|
|
25
|
+
| 'top';
|
|
26
|
+
|
|
14
27
|
export interface ContextMenuRendererContext {
|
|
15
28
|
target: HTMLElement;
|
|
16
29
|
detail?: { sourceEvent: Event };
|
|
@@ -34,6 +47,11 @@ export type ContextMenuItemSelectedEvent<TItem extends ContextMenuItem = Context
|
|
|
34
47
|
value: TItem;
|
|
35
48
|
}>;
|
|
36
49
|
|
|
50
|
+
/**
|
|
51
|
+
* Fired when the context menu is closed.
|
|
52
|
+
*/
|
|
53
|
+
export type ContextMenuClosedEvent = CustomEvent;
|
|
54
|
+
|
|
37
55
|
export interface ContextMenuCustomEventMap<TItem extends ContextMenuItem = ContextMenuItem> {
|
|
38
56
|
'opened-changed': ContextMenuOpenedChangedEvent;
|
|
39
57
|
|
|
@@ -42,6 +60,8 @@ export interface ContextMenuCustomEventMap<TItem extends ContextMenuItem = Conte
|
|
|
42
60
|
'close-all-menus': Event;
|
|
43
61
|
|
|
44
62
|
'items-outside-click': Event;
|
|
63
|
+
|
|
64
|
+
closed: ContextMenuClosedEvent;
|
|
45
65
|
}
|
|
46
66
|
|
|
47
67
|
export interface ContextMenuEventMap<TItem extends ContextMenuItem = ContextMenuItem>
|
|
@@ -216,6 +236,17 @@ export interface ContextMenuEventMap<TItem extends ContextMenuItem = ContextMenu
|
|
|
216
236
|
* `overlay` | The overlay container
|
|
217
237
|
* `content` | The overlay content
|
|
218
238
|
*
|
|
239
|
+
* ### Custom CSS Properties
|
|
240
|
+
*
|
|
241
|
+
* The following custom CSS properties are available for styling:
|
|
242
|
+
*
|
|
243
|
+
* Custom CSS property | Description
|
|
244
|
+
* --------------------------------------|-------------
|
|
245
|
+
* `--vaadin-context-menu-offset-top` | Used as an offset when using `position` and the context menu is aligned vertically below the target
|
|
246
|
+
* `--vaadin-context-menu-offset-bottom` | Used as an offset when using `position` and the context menu is aligned vertically above the target
|
|
247
|
+
* `--vaadin-context-menu-offset-start` | Used as an offset when using `position` and the context menu is aligned horizontally after the target
|
|
248
|
+
* `--vaadin-context-menu-offset-end` | Used as an offset when using `position` and the context menu is aligned horizontally before the target
|
|
249
|
+
*
|
|
219
250
|
* See [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.
|
|
220
251
|
*
|
|
221
252
|
* ### Internal components
|
|
@@ -232,13 +263,19 @@ export interface ContextMenuEventMap<TItem extends ContextMenuItem = ContextMenu
|
|
|
232
263
|
* ---------- |-------------
|
|
233
264
|
* `expanded` | Expanded parent item.
|
|
234
265
|
*
|
|
235
|
-
* Note: the `theme` attribute value set on `<vaadin-context-menu>` is
|
|
236
|
-
* propagated to the internal components listed above.
|
|
237
|
-
*
|
|
238
266
|
* @fires {CustomEvent} opened-changed - Fired when the `opened` property changes.
|
|
239
267
|
* @fires {CustomEvent} item-selected - Fired when an item is selected when the context menu is populated using the `items` API.
|
|
268
|
+
* @fires {CustomEvent} closed - Fired when the context menu is closed.
|
|
240
269
|
*/
|
|
241
270
|
declare class ContextMenu<TItem extends ContextMenuItem = ContextMenuItem> extends HTMLElement {
|
|
271
|
+
/**
|
|
272
|
+
* Position of the overlay with respect to the target.
|
|
273
|
+
* Supported values: null, `top-start`, `top`, `top-end`,
|
|
274
|
+
* `bottom-start`, `bottom`, `bottom-end`, `start-top`,
|
|
275
|
+
* `start`, `start-bottom`, `end-top`, `end`, `end-bottom`.
|
|
276
|
+
*/
|
|
277
|
+
position: ContextMenuPosition | null | undefined;
|
|
278
|
+
|
|
242
279
|
addEventListener<K extends keyof ContextMenuEventMap>(
|
|
243
280
|
type: K,
|
|
244
281
|
listener: (this: ContextMenu<TItem>, ev: ContextMenuEventMap<TItem>[K]) => void,
|
|
@@ -254,7 +291,6 @@ declare class ContextMenu<TItem extends ContextMenuItem = ContextMenuItem> exten
|
|
|
254
291
|
|
|
255
292
|
interface ContextMenu<TItem extends ContextMenuItem = ContextMenuItem>
|
|
256
293
|
extends ContextMenuMixinClass<TItem>,
|
|
257
|
-
OverlayClassMixinClass,
|
|
258
294
|
ElementMixinClass,
|
|
259
295
|
ThemePropertyMixinClass {}
|
|
260
296
|
|
|
@@ -11,7 +11,6 @@ import { css, html, LitElement } from 'lit';
|
|
|
11
11
|
import { ifDefined } from 'lit/directives/if-defined.js';
|
|
12
12
|
import { defineCustomElement } from '@vaadin/component-base/src/define.js';
|
|
13
13
|
import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
|
|
14
|
-
import { OverlayClassMixin } from '@vaadin/component-base/src/overlay-class-mixin.js';
|
|
15
14
|
import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
|
|
16
15
|
import { ThemePropertyMixin } from '@vaadin/vaadin-themable-mixin/vaadin-theme-property-mixin.js';
|
|
17
16
|
import { ContextMenuMixin } from './vaadin-context-menu-mixin.js';
|
|
@@ -184,6 +183,17 @@ import { ContextMenuMixin } from './vaadin-context-menu-mixin.js';
|
|
|
184
183
|
* `overlay` | The overlay container
|
|
185
184
|
* `content` | The overlay content
|
|
186
185
|
*
|
|
186
|
+
* ### Custom CSS Properties
|
|
187
|
+
*
|
|
188
|
+
* The following custom CSS properties are available for styling:
|
|
189
|
+
*
|
|
190
|
+
* Custom CSS property | Description
|
|
191
|
+
* --------------------------------------|-------------
|
|
192
|
+
* `--vaadin-context-menu-offset-top` | Used as an offset when using `position` and the context menu is aligned vertically below the target
|
|
193
|
+
* `--vaadin-context-menu-offset-bottom` | Used as an offset when using `position` and the context menu is aligned vertically above the target
|
|
194
|
+
* `--vaadin-context-menu-offset-start` | Used as an offset when using `position` and the context menu is aligned horizontally after the target
|
|
195
|
+
* `--vaadin-context-menu-offset-end` | Used as an offset when using `position` and the context menu is aligned horizontally before the target
|
|
196
|
+
*
|
|
187
197
|
* See [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.
|
|
188
198
|
*
|
|
189
199
|
* ### Internal components
|
|
@@ -200,22 +210,17 @@ import { ContextMenuMixin } from './vaadin-context-menu-mixin.js';
|
|
|
200
210
|
* ---------- |-------------
|
|
201
211
|
* `expanded` | Expanded parent item.
|
|
202
212
|
*
|
|
203
|
-
* Note: the `theme` attribute value set on `<vaadin-context-menu>` is
|
|
204
|
-
* propagated to the internal components listed above.
|
|
205
|
-
*
|
|
206
213
|
* @fires {CustomEvent} opened-changed - Fired when the `opened` property changes.
|
|
207
214
|
* @fires {CustomEvent} item-selected - Fired when an item is selected when the context menu is populated using the `items` API.
|
|
215
|
+
* @fires {CustomEvent} closed - Fired when the context menu is closed.
|
|
208
216
|
*
|
|
209
217
|
* @customElement
|
|
210
218
|
* @extends HTMLElement
|
|
211
219
|
* @mixes ElementMixin
|
|
212
220
|
* @mixes ContextMenuMixin
|
|
213
|
-
* @mixes OverlayClassMixin
|
|
214
221
|
* @mixes ThemePropertyMixin
|
|
215
222
|
*/
|
|
216
|
-
class ContextMenu extends ContextMenuMixin(
|
|
217
|
-
OverlayClassMixin(ElementMixin(ThemePropertyMixin(PolylitMixin(LitElement)))),
|
|
218
|
-
) {
|
|
223
|
+
class ContextMenu extends ContextMenuMixin(ElementMixin(ThemePropertyMixin(PolylitMixin(LitElement)))) {
|
|
219
224
|
static get is() {
|
|
220
225
|
return 'vaadin-context-menu';
|
|
221
226
|
}
|
|
@@ -232,23 +237,46 @@ class ContextMenu extends ContextMenuMixin(
|
|
|
232
237
|
`;
|
|
233
238
|
}
|
|
234
239
|
|
|
240
|
+
static get properties() {
|
|
241
|
+
return {
|
|
242
|
+
/**
|
|
243
|
+
* Position of the overlay with respect to the target.
|
|
244
|
+
* Supported values: null, `top-start`, `top`, `top-end`,
|
|
245
|
+
* `bottom-start`, `bottom`, `bottom-end`, `start-top`,
|
|
246
|
+
* `start`, `start-bottom`, `end-top`, `end`, `end-bottom`.
|
|
247
|
+
*/
|
|
248
|
+
position: {
|
|
249
|
+
type: String,
|
|
250
|
+
},
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
|
|
235
254
|
/** @protected */
|
|
236
255
|
render() {
|
|
256
|
+
const { _context: context, position } = this;
|
|
257
|
+
|
|
237
258
|
return html`
|
|
238
259
|
<slot id="slot"></slot>
|
|
239
260
|
<vaadin-context-menu-overlay
|
|
240
261
|
id="overlay"
|
|
241
262
|
.owner="${this}"
|
|
242
263
|
.opened="${this.opened}"
|
|
243
|
-
.model="${
|
|
264
|
+
.model="${context}"
|
|
244
265
|
.modeless="${this._modeless}"
|
|
245
266
|
.renderer="${this.items ? this.__itemsRenderer : this.renderer}"
|
|
267
|
+
.position="${position}"
|
|
268
|
+
.positionTarget="${position ? context && context.target : this._positionTarget}"
|
|
269
|
+
.horizontalAlign="${this.__computeHorizontalAlign(position)}"
|
|
270
|
+
.verticalAlign="${this.__computeVerticalAlign(position)}"
|
|
271
|
+
?no-horizontal-overlap="${this.__computeNoHorizontalOverlap(position)}"
|
|
272
|
+
?no-vertical-overlap="${this.__computeNoVerticalOverlap(position)}"
|
|
246
273
|
.withBackdrop="${this._phone}"
|
|
247
274
|
?phone="${this._phone}"
|
|
248
275
|
theme="${ifDefined(this._theme)}"
|
|
249
276
|
exportparts="backdrop, overlay, content"
|
|
250
277
|
@opened-changed="${this._onOverlayOpened}"
|
|
251
278
|
@vaadin-overlay-open="${this._onVaadinOverlayOpen}"
|
|
279
|
+
@vaadin-overlay-closed="${this._onVaadinOverlayClosed}"
|
|
252
280
|
>
|
|
253
281
|
<slot name="overlay"></slot>
|
|
254
282
|
<slot name="submenu" slot="submenu"></slot>
|
|
@@ -256,6 +284,42 @@ class ContextMenu extends ContextMenuMixin(
|
|
|
256
284
|
`;
|
|
257
285
|
}
|
|
258
286
|
|
|
287
|
+
/** @private */
|
|
288
|
+
__computeHorizontalAlign(position) {
|
|
289
|
+
if (!position) {
|
|
290
|
+
return 'start';
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
return ['top-end', 'bottom-end', 'start-top', 'start', 'start-bottom'].includes(position) ? 'end' : 'start';
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/** @private */
|
|
297
|
+
__computeNoHorizontalOverlap(position) {
|
|
298
|
+
if (!position) {
|
|
299
|
+
return !!this._positionTarget;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
return ['start-top', 'start', 'start-bottom', 'end-top', 'end', 'end-bottom'].includes(position);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/** @private */
|
|
306
|
+
__computeNoVerticalOverlap(position) {
|
|
307
|
+
if (!position) {
|
|
308
|
+
return false;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
return ['top-start', 'top-end', 'top', 'bottom-start', 'bottom', 'bottom-end'].includes(position);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/** @private */
|
|
315
|
+
__computeVerticalAlign(position) {
|
|
316
|
+
if (!position) {
|
|
317
|
+
return 'top';
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
return ['top-start', 'top-end', 'top', 'start-bottom', 'end-bottom'].includes(position) ? 'bottom' : 'top';
|
|
321
|
+
}
|
|
322
|
+
|
|
259
323
|
/**
|
|
260
324
|
* Fired when an item is selected when the context menu is populated using the `items` API.
|
|
261
325
|
*
|
|
@@ -16,14 +16,14 @@ export const ItemsMixin = (superClass) =>
|
|
|
16
16
|
* @typedef ContextMenuItem
|
|
17
17
|
* @type {object}
|
|
18
18
|
* @property {string} text - Text to be set as the menu item component's textContent
|
|
19
|
-
* @property {
|
|
19
|
+
* @property {string | HTMLElement} component - The component to represent the item.
|
|
20
20
|
* Either a tagName or an element instance. Defaults to "vaadin-context-menu-item".
|
|
21
21
|
* @property {boolean} disabled - If true, the item is disabled and cannot be selected
|
|
22
22
|
* @property {boolean} checked - If true, the item shows a checkmark next to it
|
|
23
23
|
* @property {boolean} keepOpen - If true, the menu will not be closed on item selection
|
|
24
24
|
* @property {string} className - A space-delimited list of CSS class names to be set on the menu item component.
|
|
25
|
-
* @property {
|
|
26
|
-
* @property {
|
|
25
|
+
* @property {string | string[]} theme - If set, sets the given theme(s) as an attribute to the menu item component, overriding any theme set on the context menu.
|
|
26
|
+
* @property {ContextMenuItem[]} children - Array of child menu items
|
|
27
27
|
*/
|
|
28
28
|
|
|
29
29
|
/**
|
|
@@ -60,6 +60,12 @@ export const ItemsMixin = (superClass) =>
|
|
|
60
60
|
type: Array,
|
|
61
61
|
sync: true,
|
|
62
62
|
},
|
|
63
|
+
|
|
64
|
+
/** @protected */
|
|
65
|
+
_positionTarget: {
|
|
66
|
+
type: Object,
|
|
67
|
+
sync: true,
|
|
68
|
+
},
|
|
63
69
|
};
|
|
64
70
|
}
|
|
65
71
|
|
|
@@ -131,14 +137,12 @@ export const ItemsMixin = (superClass) =>
|
|
|
131
137
|
}
|
|
132
138
|
|
|
133
139
|
/** @private */
|
|
134
|
-
__openSubMenu(subMenu, itemElement
|
|
140
|
+
__openSubMenu(subMenu, itemElement) {
|
|
141
|
+
// Update sub-menu items and position target
|
|
135
142
|
this.__updateSubMenuForItem(subMenu, itemElement);
|
|
136
|
-
subMenu.overlayClass = overlayClass;
|
|
137
143
|
|
|
138
144
|
const parent = this._overlayElement;
|
|
139
|
-
|
|
140
145
|
const subMenuOverlay = subMenu._overlayElement;
|
|
141
|
-
subMenuOverlay.noHorizontalOverlap = true;
|
|
142
146
|
// Store the reference parent overlay
|
|
143
147
|
subMenuOverlay._setParentOverlay(parent);
|
|
144
148
|
|
|
@@ -165,7 +169,8 @@ export const ItemsMixin = (superClass) =>
|
|
|
165
169
|
__updateSubMenuForItem(subMenu, itemElement) {
|
|
166
170
|
subMenu.items = itemElement._item.children;
|
|
167
171
|
subMenu.listenOn = itemElement;
|
|
168
|
-
subMenu.
|
|
172
|
+
subMenu._positionTarget = itemElement;
|
|
173
|
+
subMenu._overlayElement.requestContentUpdate();
|
|
169
174
|
}
|
|
170
175
|
|
|
171
176
|
/**
|
|
@@ -367,27 +372,33 @@ export const ItemsMixin = (superClass) =>
|
|
|
367
372
|
}
|
|
368
373
|
|
|
369
374
|
const subMenu = this._subMenu;
|
|
375
|
+
const expandedItem = this._listBox.querySelector('[expanded]');
|
|
370
376
|
|
|
371
|
-
if (item) {
|
|
377
|
+
if (item && item !== expandedItem) {
|
|
372
378
|
const { children } = item._item;
|
|
373
379
|
|
|
374
380
|
// Check if the sub-menu was focused before closing it.
|
|
375
381
|
const child = subMenu._overlayElement._contentRoot.firstElementChild;
|
|
376
382
|
const isSubmenuFocused = child && child.focused;
|
|
377
383
|
|
|
378
|
-
|
|
384
|
+
// Mark previously expanded item as collapsed
|
|
385
|
+
if (expandedItem) {
|
|
386
|
+
this.__updateExpanded(expandedItem, false);
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
// Close sub-menu if there are no children for the new item
|
|
390
|
+
if (!children || !children.length) {
|
|
379
391
|
subMenu.close();
|
|
380
392
|
}
|
|
393
|
+
|
|
381
394
|
if (!this.opened) {
|
|
382
395
|
return;
|
|
383
396
|
}
|
|
384
397
|
|
|
385
398
|
if (children && children.length) {
|
|
399
|
+
// Open or update the submenu if the new item has children
|
|
386
400
|
this.__updateExpanded(item, true);
|
|
387
|
-
|
|
388
|
-
// Forward parent overlay class
|
|
389
|
-
const { overlayClass } = this;
|
|
390
|
-
this.__openSubMenu(subMenu, item, overlayClass);
|
|
401
|
+
this.__openSubMenu(subMenu, item);
|
|
391
402
|
} else if (isSubmenuFocused) {
|
|
392
403
|
// If the sub-menu item was focused, focus its parent item.
|
|
393
404
|
subMenu.listenOn.focus();
|
|
@@ -406,7 +417,6 @@ export const ItemsMixin = (superClass) =>
|
|
|
406
417
|
/**
|
|
407
418
|
* @param {!HTMLElement} root
|
|
408
419
|
* @param {!ContextMenu} menu
|
|
409
|
-
* @param {!ContextMenuRendererContext} context
|
|
410
420
|
* @protected
|
|
411
421
|
*/
|
|
412
422
|
__itemsRenderer(root, menu) {
|
|
@@ -113,7 +113,7 @@ export const MenuOverlayMixin = (superClass) =>
|
|
|
113
113
|
_updatePosition() {
|
|
114
114
|
super._updatePosition();
|
|
115
115
|
|
|
116
|
-
if (this.positionTarget && this.parentOverlay) {
|
|
116
|
+
if (this.positionTarget && this.parentOverlay && this.opened) {
|
|
117
117
|
// This overlay is positioned by a parent menu item,
|
|
118
118
|
// adjust the position by the overlay content paddings
|
|
119
119
|
const content = this.$.content;
|
package/vaadin-context-menu.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import './
|
|
1
|
+
import './src/vaadin-context-menu.js';
|
|
2
2
|
export * from './src/vaadin-context-menu.js';
|
package/web-types.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/web-types",
|
|
3
3
|
"name": "@vaadin/context-menu",
|
|
4
|
-
"version": "25.0.0-
|
|
4
|
+
"version": "25.0.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\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.0.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### 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.0.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.0.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": "selector",
|
|
@@ -40,8 +40,8 @@
|
|
|
40
40
|
}
|
|
41
41
|
},
|
|
42
42
|
{
|
|
43
|
-
"name": "
|
|
44
|
-
"description": "
|
|
43
|
+
"name": "position",
|
|
44
|
+
"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`.",
|
|
45
45
|
"value": {
|
|
46
46
|
"type": [
|
|
47
47
|
"string",
|
|
@@ -123,8 +123,8 @@
|
|
|
123
123
|
}
|
|
124
124
|
},
|
|
125
125
|
{
|
|
126
|
-
"name": "
|
|
127
|
-
"description": "
|
|
126
|
+
"name": "position",
|
|
127
|
+
"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`.",
|
|
128
128
|
"value": {
|
|
129
129
|
"type": [
|
|
130
130
|
"string",
|
|
@@ -135,6 +135,10 @@
|
|
|
135
135
|
}
|
|
136
136
|
],
|
|
137
137
|
"events": [
|
|
138
|
+
{
|
|
139
|
+
"name": "closed",
|
|
140
|
+
"description": "Fired when the context menu is closed."
|
|
141
|
+
},
|
|
138
142
|
{
|
|
139
143
|
"name": "item-selected",
|
|
140
144
|
"description": "Fired when an item is selected when the context menu is populated using the `items` API."
|
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.0.0-
|
|
4
|
+
"version": "25.0.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\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.0.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### 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.0.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.0.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
|
{
|
|
@@ -62,8 +62,15 @@
|
|
|
62
62
|
}
|
|
63
63
|
},
|
|
64
64
|
{
|
|
65
|
-
"name": ".
|
|
66
|
-
"description": "
|
|
65
|
+
"name": ".position",
|
|
66
|
+
"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`.",
|
|
67
|
+
"value": {
|
|
68
|
+
"kind": "expression"
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"name": "@closed",
|
|
73
|
+
"description": "Fired when the context menu is closed.",
|
|
67
74
|
"value": {
|
|
68
75
|
"kind": "expression"
|
|
69
76
|
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license
|
|
3
|
-
* Copyright (c) 2016 - 2025 Vaadin Ltd.
|
|
4
|
-
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
-
*/
|
|
6
|
-
import { itemStyles } from '@vaadin/item/src/styles/vaadin-item-core-styles.js';
|
|
7
|
-
|
|
8
|
-
export const contextMenuItemStyles = [itemStyles];
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license
|
|
3
|
-
* Copyright (c) 2016 - 2025 Vaadin Ltd.
|
|
4
|
-
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
-
*/
|
|
6
|
-
import { overlayStyles } from '@vaadin/overlay/src/styles/vaadin-overlay-core-styles.js';
|
|
7
|
-
import { menuOverlayStyles } from './vaadin-menu-overlay-core-styles.js';
|
|
8
|
-
|
|
9
|
-
export const contextMenuOverlayStyles = [overlayStyles, menuOverlayStyles];
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license
|
|
3
|
-
* Copyright (c) 2016 - 2025 Vaadin Ltd.
|
|
4
|
-
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
-
*/
|
|
6
|
-
import { css } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
7
|
-
|
|
8
|
-
export const menuOverlayStyles = css`
|
|
9
|
-
:host {
|
|
10
|
-
align-items: flex-start;
|
|
11
|
-
justify-content: flex-start;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
:host([right-aligned]),
|
|
15
|
-
:host([end-aligned]) {
|
|
16
|
-
align-items: flex-end;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
:host([bottom-aligned]) {
|
|
20
|
-
justify-content: flex-end;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
[part='overlay'] {
|
|
24
|
-
background-color: #fff;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
@media (forced-colors: active) {
|
|
28
|
-
[part='overlay'] {
|
|
29
|
-
outline: 3px solid !important;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
`;
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import '@vaadin/vaadin-lumo-styles/color.js';
|
|
2
|
-
import '@vaadin/vaadin-lumo-styles/font-icons.js';
|
|
3
|
-
import '@vaadin/vaadin-lumo-styles/sizing.js';
|
|
4
|
-
import '@vaadin/vaadin-lumo-styles/spacing.js';
|
|
5
|
-
declare const contextMenuItem: import("lit").CSSResult;
|
|
6
|
-
export { contextMenuItem };
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import '@vaadin/vaadin-lumo-styles/color.js';
|
|
2
|
-
import '@vaadin/vaadin-lumo-styles/font-icons.js';
|
|
3
|
-
import '@vaadin/vaadin-lumo-styles/sizing.js';
|
|
4
|
-
import '@vaadin/vaadin-lumo-styles/spacing.js';
|
|
5
|
-
import { item } from '@vaadin/item/theme/lumo/vaadin-item-styles.js';
|
|
6
|
-
import { css, registerStyles } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
7
|
-
|
|
8
|
-
const contextMenuItem = css`
|
|
9
|
-
/* :hover needed to workaround https://github.com/vaadin/web-components/issues/3133 */
|
|
10
|
-
:host(:hover) {
|
|
11
|
-
user-select: none;
|
|
12
|
-
-webkit-user-select: none;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
:host([role='menuitem'][menu-item-checked]) [part='checkmark']::before {
|
|
16
|
-
opacity: 1;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
:host([aria-haspopup='true'])::after {
|
|
20
|
-
font-family: lumo-icons;
|
|
21
|
-
font-size: var(--lumo-icon-size-xs);
|
|
22
|
-
content: var(--lumo-icons-angle-right);
|
|
23
|
-
color: var(--lumo-tertiary-text-color);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
:host(:not([dir='rtl'])[aria-haspopup='true'])::after {
|
|
27
|
-
margin-right: calc(var(--lumo-space-m) * -1);
|
|
28
|
-
padding-left: var(--lumo-space-m);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
:host([expanded]) {
|
|
32
|
-
background-color: var(--lumo-primary-color-10pct);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/* RTL styles */
|
|
36
|
-
:host([dir='rtl'][aria-haspopup='true'])::after {
|
|
37
|
-
content: var(--lumo-icons-angle-left);
|
|
38
|
-
margin-left: calc(var(--lumo-space-m) * -1);
|
|
39
|
-
padding-right: var(--lumo-space-m);
|
|
40
|
-
}
|
|
41
|
-
`;
|
|
42
|
-
|
|
43
|
-
registerStyles('vaadin-context-menu-item', [item, contextMenuItem], { moduleId: 'lumo-context-menu-item' });
|
|
44
|
-
|
|
45
|
-
export { contextMenuItem };
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import '@vaadin/vaadin-lumo-styles/color.js';
|
|
2
|
-
import '@vaadin/vaadin-lumo-styles/spacing.js';
|
|
3
|
-
import '@vaadin/vaadin-lumo-styles/style.js';
|
|
4
|
-
import { listBox } from '@vaadin/list-box/theme/lumo/vaadin-list-box-styles.js';
|
|
5
|
-
import { css, registerStyles } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
6
|
-
|
|
7
|
-
const contextMenuListBox = css`
|
|
8
|
-
:host {
|
|
9
|
-
--_lumo-list-box-item-selected-icon-display: block;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
/* Normal item */
|
|
13
|
-
[part='items'] ::slotted([role='menuitem']) {
|
|
14
|
-
-webkit-tap-highlight-color: var(--lumo-primary-color-10pct);
|
|
15
|
-
cursor: default;
|
|
16
|
-
outline: none;
|
|
17
|
-
border-radius: var(--lumo-border-radius-m);
|
|
18
|
-
padding-left: calc(var(--lumo-border-radius-m) / 4);
|
|
19
|
-
padding-right: calc(var(--lumo-space-l) + var(--lumo-border-radius-m) / 4);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/* Hovered item */
|
|
23
|
-
/* TODO a workaround until we have "focus-follows-mouse". After that, use the hover style for focus-ring as well */
|
|
24
|
-
[part='items'] ::slotted([role='menuitem']:hover:not([disabled])),
|
|
25
|
-
[part='items'] ::slotted([role='menuitem'][expanded]:not([disabled])) {
|
|
26
|
-
background-color: var(--lumo-primary-color-10pct);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/* RTL styles */
|
|
30
|
-
:host([dir='rtl']) [part='items'] ::slotted([role='menuitem']) {
|
|
31
|
-
padding-left: calc(var(--lumo-space-l) + var(--lumo-border-radius-m) / 4);
|
|
32
|
-
padding-right: calc(var(--lumo-border-radius-m) / 4);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/* Focused item */
|
|
36
|
-
@media (pointer: coarse) {
|
|
37
|
-
[part='items'] ::slotted([role='menuitem']:hover:not([expanded]):not([disabled])) {
|
|
38
|
-
background-color: transparent;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
`;
|
|
42
|
-
|
|
43
|
-
registerStyles('vaadin-context-menu-list-box', [listBox, contextMenuListBox], {
|
|
44
|
-
moduleId: 'lumo-context-menu-list-box',
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
export { contextMenuListBox };
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import '@vaadin/vaadin-lumo-styles/spacing.js';
|
|
2
|
-
import '@vaadin/vaadin-lumo-styles/style.js';
|
|
3
|
-
import { menuOverlay } from '@vaadin/vaadin-lumo-styles/mixins/menu-overlay.js';
|
|
4
|
-
import { css, registerStyles } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
5
|
-
|
|
6
|
-
const contextMenuOverlay = css`
|
|
7
|
-
:host([phone]) {
|
|
8
|
-
/* stylelint-disable declaration-block-no-redundant-longhand-properties */
|
|
9
|
-
top: 0 !important;
|
|
10
|
-
right: 0 !important;
|
|
11
|
-
bottom: var(--vaadin-overlay-viewport-bottom) !important;
|
|
12
|
-
left: 0 !important;
|
|
13
|
-
/* stylelint-enable declaration-block-no-redundant-longhand-properties */
|
|
14
|
-
align-items: stretch;
|
|
15
|
-
justify-content: flex-end;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/* TODO These style overrides should not be needed.
|
|
19
|
-
We should instead offer a way to have non-selectable items inside the context menu. */
|
|
20
|
-
|
|
21
|
-
:host {
|
|
22
|
-
--_lumo-list-box-item-selected-icon-display: none;
|
|
23
|
-
--_lumo-list-box-item-padding-left: calc(var(--lumo-space-m) + var(--lumo-border-radius-m) / 4);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
[part='overlay'] {
|
|
27
|
-
outline: none;
|
|
28
|
-
}
|
|
29
|
-
`;
|
|
30
|
-
|
|
31
|
-
registerStyles('vaadin-context-menu-overlay', [menuOverlay, contextMenuOverlay], {
|
|
32
|
-
moduleId: 'lumo-context-menu-overlay',
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
export { contextMenuOverlay };
|