@vaadin/context-menu 24.0.0-alpha9 → 24.0.0-beta2

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vaadin/context-menu",
3
- "version": "24.0.0-alpha9",
3
+ "version": "24.0.0-beta2",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -39,18 +39,18 @@
39
39
  "dependencies": {
40
40
  "@open-wc/dedupe-mixin": "^1.3.0",
41
41
  "@polymer/polymer": "^3.0.0",
42
- "@vaadin/component-base": "24.0.0-alpha9",
43
- "@vaadin/item": "24.0.0-alpha9",
44
- "@vaadin/list-box": "24.0.0-alpha9",
45
- "@vaadin/lit-renderer": "24.0.0-alpha9",
46
- "@vaadin/overlay": "24.0.0-alpha9",
47
- "@vaadin/vaadin-lumo-styles": "24.0.0-alpha9",
48
- "@vaadin/vaadin-material-styles": "24.0.0-alpha9",
49
- "@vaadin/vaadin-themable-mixin": "24.0.0-alpha9"
42
+ "@vaadin/component-base": "24.0.0-beta2",
43
+ "@vaadin/item": "24.0.0-beta2",
44
+ "@vaadin/list-box": "24.0.0-beta2",
45
+ "@vaadin/lit-renderer": "24.0.0-beta2",
46
+ "@vaadin/overlay": "24.0.0-beta2",
47
+ "@vaadin/vaadin-lumo-styles": "24.0.0-beta2",
48
+ "@vaadin/vaadin-material-styles": "24.0.0-beta2",
49
+ "@vaadin/vaadin-themable-mixin": "24.0.0-beta2"
50
50
  },
51
51
  "devDependencies": {
52
52
  "@esm-bundle/chai": "^4.3.4",
53
- "@vaadin/testing-helpers": "^0.3.2",
53
+ "@vaadin/testing-helpers": "^0.4.0",
54
54
  "lit": "^2.0.0",
55
55
  "sinon": "^13.0.2"
56
56
  },
@@ -58,5 +58,5 @@
58
58
  "web-types.json",
59
59
  "web-types.lit.json"
60
60
  ],
61
- "gitHead": "cc3f747164041566b300bde4b105d2475649e93f"
61
+ "gitHead": "00086f1f6d487f042f189c9b9ecd7ba736960888"
62
62
  }
@@ -0,0 +1,21 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2016 - 2023 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+ import { DirMixin } from '@vaadin/component-base/src/dir-mixin.js';
7
+ import { ItemMixin } from '@vaadin/item/src/vaadin-item-mixin.js';
8
+ import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
9
+
10
+ /**
11
+ * An element used internally by `<vaadin-context-menu>`. Not intended to be used separately.
12
+ */
13
+ declare class ContextMenuItem extends ItemMixin(DirMixin(ThemableMixin(HTMLElement))) {}
14
+
15
+ declare global {
16
+ interface HTMLElementTagNameMap {
17
+ 'vaadin-context-menu-item': ContextMenuItem;
18
+ }
19
+ }
20
+
21
+ export { ContextMenuItem };
@@ -0,0 +1,53 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2016 - 2023 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+ import { html, PolymerElement } from '@polymer/polymer/polymer-element.js';
7
+ import { DirMixin } from '@vaadin/component-base/src/dir-mixin.js';
8
+ import { ItemMixin } from '@vaadin/item/src/vaadin-item-mixin.js';
9
+ import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
10
+
11
+ /**
12
+ * An element used internally by `<vaadin-context-menu>`. Not intended to be used separately.
13
+ *
14
+ * @extends HTMLElement
15
+ * @mixes DirMixin
16
+ * @mixes ItemMixin
17
+ * @mixes ThemableMixin
18
+ * @protected
19
+ */
20
+ class ContextMenuItem extends ItemMixin(ThemableMixin(DirMixin(PolymerElement))) {
21
+ static get is() {
22
+ return 'vaadin-context-menu-item';
23
+ }
24
+
25
+ static get template() {
26
+ return html`
27
+ <style>
28
+ :host {
29
+ display: inline-block;
30
+ }
31
+
32
+ :host([hidden]) {
33
+ display: none !important;
34
+ }
35
+ </style>
36
+ <span part="checkmark" aria-hidden="true"></span>
37
+ <div part="content">
38
+ <slot></slot>
39
+ </div>
40
+ `;
41
+ }
42
+
43
+ /** @protected */
44
+ ready() {
45
+ super.ready();
46
+
47
+ this.setAttribute('role', 'menuitem');
48
+ }
49
+ }
50
+
51
+ customElements.define(ContextMenuItem.is, ContextMenuItem);
52
+
53
+ export { ContextMenuItem };
@@ -0,0 +1,22 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2016 - 2023 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+ import { ControllerMixin } from '@vaadin/component-base/src/controller-mixin.js';
7
+ import { DirMixin } from '@vaadin/component-base/src/dir-mixin.js';
8
+ import { ListMixin } from '@vaadin/component-base/src/list-mixin.js';
9
+ import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
10
+
11
+ /**
12
+ * An element used internally by `<vaadin-context-menu>`. Not intended to be used separately.
13
+ */
14
+ declare class ContextMenuListBox extends ListMixin(DirMixin(ThemableMixin(ControllerMixin(HTMLElement)))) {}
15
+
16
+ declare global {
17
+ interface HTMLElementTagNameMap {
18
+ 'vaadin-context-menu-list-box': ContextMenuListBox;
19
+ }
20
+ }
21
+
22
+ export { ContextMenuListBox };
@@ -0,0 +1,81 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2016 - 2023 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+ import { html, PolymerElement } from '@polymer/polymer/polymer-element.js';
7
+ import { ControllerMixin } from '@vaadin/component-base/src/controller-mixin.js';
8
+ import { DirMixin } from '@vaadin/component-base/src/dir-mixin.js';
9
+ import { ListMixin } from '@vaadin/component-base/src/list-mixin.js';
10
+ import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
11
+
12
+ /**
13
+ * An element used internally by `<vaadin-context-menu>`. Not intended to be used separately.
14
+ *
15
+ * @extends HTMLElement
16
+ * @mixes ControllerMixin
17
+ * @mixes DirMixin
18
+ * @mixes ListMixin
19
+ * @mixes ThemableMixin
20
+ * @protected
21
+ */
22
+ class ContextMenuListBox extends ListMixin(ThemableMixin(DirMixin(ControllerMixin(PolymerElement)))) {
23
+ static get is() {
24
+ return 'vaadin-context-menu-list-box';
25
+ }
26
+
27
+ static get template() {
28
+ return html`
29
+ <style>
30
+ :host {
31
+ display: flex;
32
+ }
33
+
34
+ :host([hidden]) {
35
+ display: none !important;
36
+ }
37
+
38
+ [part='items'] {
39
+ height: 100%;
40
+ width: 100%;
41
+ overflow-y: auto;
42
+ -webkit-overflow-scrolling: touch;
43
+ }
44
+ </style>
45
+ <div part="items">
46
+ <slot></slot>
47
+ </div>
48
+ `;
49
+ }
50
+
51
+ static get properties() {
52
+ return {
53
+ // We don't need to define this property since super default is vertical,
54
+ // but we don't want it to be modified, or be shown in the API docs.
55
+ /** @private */
56
+ orientation: {
57
+ readOnly: true,
58
+ },
59
+ };
60
+ }
61
+
62
+ /**
63
+ * @return {!HTMLElement}
64
+ * @protected
65
+ * @override
66
+ */
67
+ get _scrollerElement() {
68
+ return this.shadowRoot.querySelector('[part="items"]');
69
+ }
70
+
71
+ /** @protected */
72
+ ready() {
73
+ super.ready();
74
+
75
+ this.setAttribute('role', 'menu');
76
+ }
77
+ }
78
+
79
+ customElements.define(ContextMenuListBox.is, ContextMenuListBox);
80
+
81
+ export { ContextMenuListBox };
@@ -0,0 +1,20 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2016 - 2023 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+ import { Overlay } from '@vaadin/overlay/src/vaadin-overlay.js';
7
+ import { MenuOverlayMixin } from './vaadin-menu-overlay-mixin.js';
8
+
9
+ /**
10
+ * An element used internally by `<vaadin-context-menu>`. Not intended to be used separately.
11
+ */
12
+ declare class ContextMenuOverlay extends MenuOverlayMixin(Overlay) {}
13
+
14
+ declare global {
15
+ interface HTMLElementTagNameMap {
16
+ 'vaadin-context-menu-overlay': ContextMenuOverlay;
17
+ }
18
+ }
19
+
20
+ export { ContextMenuOverlay };
@@ -4,134 +4,23 @@
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
  import { Overlay } from '@vaadin/overlay/src/vaadin-overlay.js';
7
- import { PositionMixin } from '@vaadin/overlay/src/vaadin-overlay-position-mixin.js';
8
- import { css, registerStyles } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
7
+ import { registerStyles } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
8
+ import { MenuOverlayMixin } from './vaadin-menu-overlay-mixin.js';
9
+ import { styles } from './vaadin-menu-overlay-styles.js';
9
10
 
10
- registerStyles(
11
- 'vaadin-context-menu-overlay',
12
- css`
13
- :host {
14
- align-items: flex-start;
15
- justify-content: flex-start;
16
- }
17
-
18
- :host([right-aligned]),
19
- :host([end-aligned]) {
20
- align-items: flex-end;
21
- }
22
-
23
- :host([bottom-aligned]) {
24
- justify-content: flex-end;
25
- }
26
-
27
- [part='overlay'] {
28
- background-color: #fff;
29
- }
30
- `,
31
- { moduleId: 'vaadin-context-menu-overlay-styles' },
32
- );
11
+ registerStyles('vaadin-context-menu-overlay', styles, { moduleId: 'vaadin-context-menu-overlay-styles' });
33
12
 
34
13
  /**
35
14
  * An element used internally by `<vaadin-context-menu>`. Not intended to be used separately.
36
15
  *
37
16
  * @extends Overlay
17
+ * @mixes MenuOverlayMixin
38
18
  * @protected
39
19
  */
40
- class ContextMenuOverlay extends PositionMixin(Overlay) {
20
+ export class ContextMenuOverlay extends MenuOverlayMixin(Overlay) {
41
21
  static get is() {
42
22
  return 'vaadin-context-menu-overlay';
43
23
  }
44
-
45
- static get properties() {
46
- return {
47
- /**
48
- * @protected
49
- */
50
- parentOverlay: {
51
- type: Object,
52
- readOnly: true,
53
- },
54
- };
55
- }
56
-
57
- static get observers() {
58
- return ['_themeChanged(_theme)'];
59
- }
60
-
61
- ready() {
62
- super.ready();
63
-
64
- this.addEventListener('keydown', (e) => {
65
- if (!e.defaultPrevented && e.composedPath()[0] === this.$.overlay && [38, 40].indexOf(e.keyCode) > -1) {
66
- const child = this.getFirstChild();
67
- if (child && Array.isArray(child.items) && child.items.length) {
68
- e.preventDefault();
69
- if (e.keyCode === 38) {
70
- child.items[child.items.length - 1].focus();
71
- } else {
72
- child.focus();
73
- }
74
- }
75
- }
76
- });
77
- }
78
-
79
- getFirstChild() {
80
- return this.querySelector(':not(style):not(slot)');
81
- }
82
-
83
- _themeChanged() {
84
- this.close();
85
- }
86
-
87
- getBoundaries() {
88
- // Measure actual overlay and content sizes
89
- const overlayRect = this.getBoundingClientRect();
90
- const contentRect = this.$.overlay.getBoundingClientRect();
91
-
92
- // Maximum x and y values are imposed by content size and overlay limits.
93
- let yMax = overlayRect.bottom - contentRect.height;
94
-
95
- // Adjust constraints to ensure bottom-aligned applies to sub-menu.
96
- const parent = this.parentOverlay;
97
- if (parent && parent.hasAttribute('bottom-aligned')) {
98
- const parentStyle = getComputedStyle(parent);
99
- yMax = yMax - parseFloat(parentStyle.bottom) - parseFloat(parentStyle.height);
100
- }
101
-
102
- return {
103
- xMax: overlayRect.right - contentRect.width,
104
- xMin: overlayRect.left + contentRect.width,
105
- yMax,
106
- };
107
- }
108
-
109
- _updatePosition() {
110
- super._updatePosition();
111
-
112
- if (this.positionTarget && this.parentOverlay) {
113
- // This overlay is positioned by a parent menu item,
114
- // adjust the position by the overlay content paddings
115
- const content = this.$.content;
116
- const style = getComputedStyle(content);
117
-
118
- // Horizontal adjustment
119
- const isLeftAligned = !!this.style.left;
120
- if (isLeftAligned) {
121
- this.style.left = `${parseFloat(this.style.left) + parseFloat(style.paddingLeft)}px`;
122
- } else {
123
- this.style.right = `${parseFloat(this.style.right) + parseFloat(style.paddingRight)}px`;
124
- }
125
-
126
- // Vertical adjustment
127
- const isBottomAligned = !!this.style.bottom;
128
- if (isBottomAligned) {
129
- this.style.bottom = `${parseFloat(this.style.bottom) - parseFloat(style.paddingBottom)}px`;
130
- } else {
131
- this.style.top = `${parseFloat(this.style.top) - parseFloat(style.paddingTop)}px`;
132
- }
133
- }
134
- }
135
24
  }
136
25
 
137
26
  customElements.define(ContextMenuOverlay.is, ContextMenuOverlay);
@@ -57,20 +57,20 @@ export interface ContextMenuEventMap extends HTMLElementEventMap, ContextMenuCus
57
57
  *
58
58
  * ```javascript
59
59
  * contextMenu.items = [
60
- * {text: 'Menu Item 1', theme: 'primary', children:
60
+ * { text: 'Menu Item 1', theme: 'primary', children:
61
61
  * [
62
- * {text: 'Menu Item 1-1', checked: true},
63
- * {text: 'Menu Item 1-2'}
62
+ * { text: 'Menu Item 1-1', checked: true },
63
+ * { text: 'Menu Item 1-2' }
64
64
  * ]
65
65
  * },
66
- * {component: 'hr'},
67
- * {text: 'Menu Item 2', children:
66
+ * { component: 'hr' },
67
+ * { text: 'Menu Item 2', children:
68
68
  * [
69
- * {text: 'Menu Item 2-1'},
70
- * {text: 'Menu Item 2-2', disabled: true}
69
+ * { text: 'Menu Item 2-1' },
70
+ * { text: 'Menu Item 2-2', disabled: true }
71
71
  * ]
72
72
  * },
73
- * {text: 'Menu Item 3', disabled: true}
73
+ * { text: 'Menu Item 3', disabled: true }
74
74
  * ];
75
75
  *
76
76
  * contextMenu.addEventListener('item-selected', e => {
@@ -121,7 +121,7 @@ export interface ContextMenuEventMap extends HTMLElementEventMap, ContextMenuCus
121
121
  * in the next renderer call and will be provided with the `root` argument.
122
122
  * On first call it will be empty.
123
123
  *
124
- * ### vaadin-contextmenu Gesture Event
124
+ * ### `vaadin-contextmenu` Gesture Event
125
125
  *
126
126
  * `vaadin-contextmenu` is a gesture event (a custom event),
127
127
  * which is dispatched after either `contextmenu` or long touch events.
@@ -267,6 +267,11 @@ declare class ContextMenu extends OverlayClassMixin(ElementMixin(ThemePropertyMi
267
267
  */
268
268
  renderer: ContextMenuRenderer | null | undefined;
269
269
 
270
+ /**
271
+ * When true, the menu overlay is modeless.
272
+ */
273
+ protected _modeless: boolean;
274
+
270
275
  /**
271
276
  * Requests an update for the content of the menu overlay.
272
277
  * While performing the update, it invokes the renderer passed in the `renderer` property.
@@ -30,20 +30,20 @@ import { ItemsMixin } from './vaadin-contextmenu-items-mixin.js';
30
30
  *
31
31
  * ```javascript
32
32
  * contextMenu.items = [
33
- * {text: 'Menu Item 1', theme: 'primary', children:
33
+ * { text: 'Menu Item 1', theme: 'primary', children:
34
34
  * [
35
- * {text: 'Menu Item 1-1', checked: true},
36
- * {text: 'Menu Item 1-2'}
35
+ * { text: 'Menu Item 1-1', checked: true },
36
+ * { text: 'Menu Item 1-2' }
37
37
  * ]
38
38
  * },
39
- * {component: 'hr'},
40
- * {text: 'Menu Item 2', children:
39
+ * { component: 'hr' },
40
+ * { text: 'Menu Item 2', children:
41
41
  * [
42
- * {text: 'Menu Item 2-1'},
43
- * {text: 'Menu Item 2-2', disabled: true}
42
+ * { text: 'Menu Item 2-1' },
43
+ * { text: 'Menu Item 2-2', disabled: true }
44
44
  * ]
45
45
  * },
46
- * {text: 'Menu Item 3', disabled: true}
46
+ * { text: 'Menu Item 3', disabled: true }
47
47
  * ];
48
48
  *
49
49
  * contextMenu.addEventListener('item-selected', e => {
@@ -94,7 +94,7 @@ import { ItemsMixin } from './vaadin-contextmenu-items-mixin.js';
94
94
  * in the next renderer call and will be provided with the `root` argument.
95
95
  * On first call it will be empty.
96
96
  *
97
- * ### vaadin-contextmenu Gesture Event
97
+ * ### `vaadin-contextmenu` Gesture Event
98
98
  *
99
99
  * `vaadin-contextmenu` is a gesture event (a custom event),
100
100
  * which is dispatched after either `contextmenu` or long touch events.
@@ -225,12 +225,12 @@ class ContextMenu extends OverlayClassMixin(
225
225
  id="overlay"
226
226
  on-opened-changed="_onOverlayOpened"
227
227
  on-vaadin-overlay-open="_onVaadinOverlayOpen"
228
+ modeless="[[_modeless]]"
228
229
  with-backdrop="[[_phone]]"
229
230
  phone$="[[_phone]]"
230
231
  model="[[_context]]"
231
232
  theme$="[[_theme]]"
232
- >
233
- </vaadin-context-menu-overlay>
233
+ ></vaadin-context-menu-overlay>
234
234
  `;
235
235
  }
236
236
 
@@ -309,6 +309,14 @@ class ContextMenu extends OverlayClassMixin(
309
309
  type: Function,
310
310
  },
311
311
 
312
+ /**
313
+ * When true, the menu overlay is modeless.
314
+ * @protected
315
+ */
316
+ _modeless: {
317
+ type: Boolean,
318
+ },
319
+
312
320
  /** @private */
313
321
  _context: Object,
314
322
 
@@ -3,9 +3,9 @@
3
3
  * Copyright (c) 2016 - 2023 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-context-menu-item.js';
7
+ import './vaadin-context-menu-list-box.js';
6
8
  import type { Constructor } from '@open-wc/dedupe-mixin';
7
- import { Item } from '@vaadin/item/src/vaadin-item.js';
8
- import { ListBox } from '@vaadin/list-box/src/vaadin-list-box.js';
9
9
 
10
10
  export interface ContextMenuItem {
11
11
  text?: string;
@@ -16,27 +16,6 @@ export interface ContextMenuItem {
16
16
  children?: ContextMenuItem[];
17
17
  }
18
18
 
19
- /**
20
- * An element used internally by `<vaadin-context-menu>`. Not intended to be used separately.
21
- *
22
- * @protected
23
- */
24
- declare class ContextMenuItemElement extends Item {}
25
-
26
- declare global {
27
- interface HTMLElementTagNameMap {
28
- 'vaadin-context-menu-item': ContextMenuItemElement;
29
- 'vaadin-context-menu-list-box': ContextMenuListBox;
30
- }
31
- }
32
-
33
- /**
34
- * An element used internally by `<vaadin-context-menu>`. Not intended to be used separately.
35
- *
36
- * @protected
37
- */
38
- declare class ContextMenuListBox extends ListBox {}
39
-
40
19
  export declare function ItemsMixin<T extends Constructor<HTMLElement>>(base: T): Constructor<ItemsMixinClass> & T;
41
20
 
42
21
  export declare class ItemsMixinClass {
@@ -51,22 +30,27 @@ export declare class ItemsMixinClass {
51
30
  *
52
31
  * ```javascript
53
32
  * contextMenu.items = [
54
- * {text: 'Menu Item 1', theme: 'primary', children:
33
+ * { text: 'Menu Item 1', theme: 'primary', children:
55
34
  * [
56
- * {text: 'Menu Item 1-1', checked: true},
57
- * {text: 'Menu Item 1-2'}
35
+ * { text: 'Menu Item 1-1', checked: true },
36
+ * { text: 'Menu Item 1-2' }
58
37
  * ]
59
38
  * },
60
- * {component: 'hr'},
61
- * {text: 'Menu Item 2', children:
39
+ * { component: 'hr' },
40
+ * { text: 'Menu Item 2', children:
62
41
  * [
63
- * {text: 'Menu Item 2-1'},
64
- * {text: 'Menu Item 2-2', disabled: true}
42
+ * { text: 'Menu Item 2-1' },
43
+ * { text: 'Menu Item 2-2', disabled: true }
65
44
  * ]
66
45
  * },
67
- * {text: 'Menu Item 3', disabled: true}
46
+ * { text: 'Menu Item 3', disabled: true }
68
47
  * ];
69
48
  * ```
70
49
  */
71
50
  items: ContextMenuItem[] | undefined;
51
+
52
+ /**
53
+ * Tag name prefix used by overlay, list-box and items.
54
+ */
55
+ protected readonly _tagNamePrefix: string;
72
56
  }