@vaadin/menu-bar 25.0.0-alpha1 → 25.0.0-alpha11
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 +15 -16
- package/src/styles/vaadin-menu-bar-base-styles.d.ts +8 -0
- package/src/styles/vaadin-menu-bar-base-styles.js +55 -0
- package/src/styles/vaadin-menu-bar-button-base-styles.d.ts +8 -0
- package/src/styles/vaadin-menu-bar-button-base-styles.js +47 -0
- package/src/styles/vaadin-menu-bar-item-base-styles.d.ts +8 -0
- package/src/styles/vaadin-menu-bar-item-base-styles.js +8 -0
- package/src/styles/vaadin-menu-bar-overlay-base-styles.d.ts +8 -0
- package/src/styles/vaadin-menu-bar-overlay-base-styles.js +9 -0
- package/src/vaadin-menu-bar-button.js +2 -13
- package/src/vaadin-menu-bar-item.js +5 -11
- package/src/vaadin-menu-bar-list-box.js +5 -18
- package/src/vaadin-menu-bar-mixin.js +145 -130
- package/src/vaadin-menu-bar-overlay.js +7 -4
- package/src/vaadin-menu-bar-submenu-mixin.js +3 -3
- package/src/vaadin-menu-bar-submenu.js +20 -11
- package/src/vaadin-menu-bar.d.ts +3 -6
- package/src/vaadin-menu-bar.js +11 -27
- package/vaadin-menu-bar.js +1 -1
- package/web-types.json +2 -2
- package/web-types.lit.json +2 -2
- package/theme/lumo/vaadin-menu-bar-button-styles.d.ts +0 -1
- package/theme/lumo/vaadin-menu-bar-button-styles.js +0 -128
- package/theme/lumo/vaadin-menu-bar-button.d.ts +0 -2
- package/theme/lumo/vaadin-menu-bar-button.js +0 -2
- package/theme/lumo/vaadin-menu-bar-item-styles.d.ts +0 -2
- package/theme/lumo/vaadin-menu-bar-item-styles.js +0 -27
- package/theme/lumo/vaadin-menu-bar-list-box-styles.d.ts +0 -1
- package/theme/lumo/vaadin-menu-bar-list-box-styles.js +0 -5
- package/theme/lumo/vaadin-menu-bar-overlay-styles.d.ts +0 -1
- package/theme/lumo/vaadin-menu-bar-overlay-styles.js +0 -13
- package/theme/lumo/vaadin-menu-bar-styles.d.ts +0 -1
- package/theme/lumo/vaadin-menu-bar-styles.js +0 -17
- package/theme/lumo/vaadin-menu-bar.d.ts +0 -6
- package/theme/lumo/vaadin-menu-bar.js +0 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vaadin/menu-bar",
|
|
3
|
-
"version": "25.0.0-
|
|
3
|
+
"version": "25.0.0-alpha11",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -21,7 +21,6 @@
|
|
|
21
21
|
"type": "module",
|
|
22
22
|
"files": [
|
|
23
23
|
"src",
|
|
24
|
-
"theme",
|
|
25
24
|
"vaadin-*.d.ts",
|
|
26
25
|
"vaadin-*.js",
|
|
27
26
|
"web-types.json",
|
|
@@ -35,27 +34,27 @@
|
|
|
35
34
|
],
|
|
36
35
|
"dependencies": {
|
|
37
36
|
"@open-wc/dedupe-mixin": "^1.3.0",
|
|
38
|
-
"@vaadin/a11y-base": "25.0.0-
|
|
39
|
-
"@vaadin/button": "25.0.0-
|
|
40
|
-
"@vaadin/component-base": "25.0.0-
|
|
41
|
-
"@vaadin/context-menu": "25.0.0-
|
|
42
|
-
"@vaadin/item": "25.0.0-
|
|
43
|
-
"@vaadin/list-box": "25.0.0-
|
|
44
|
-
"@vaadin/overlay": "25.0.0-
|
|
45
|
-
"@vaadin/vaadin-
|
|
46
|
-
"@vaadin/vaadin-themable-mixin": "25.0.0-alpha1",
|
|
37
|
+
"@vaadin/a11y-base": "25.0.0-alpha11",
|
|
38
|
+
"@vaadin/button": "25.0.0-alpha11",
|
|
39
|
+
"@vaadin/component-base": "25.0.0-alpha11",
|
|
40
|
+
"@vaadin/context-menu": "25.0.0-alpha11",
|
|
41
|
+
"@vaadin/item": "25.0.0-alpha11",
|
|
42
|
+
"@vaadin/list-box": "25.0.0-alpha11",
|
|
43
|
+
"@vaadin/overlay": "25.0.0-alpha11",
|
|
44
|
+
"@vaadin/vaadin-themable-mixin": "25.0.0-alpha11",
|
|
47
45
|
"lit": "^3.0.0"
|
|
48
46
|
},
|
|
49
47
|
"devDependencies": {
|
|
50
|
-
"@vaadin/chai-plugins": "25.0.0-
|
|
51
|
-
"@vaadin/icon": "25.0.0-
|
|
52
|
-
"@vaadin/test-runner-commands": "25.0.0-
|
|
53
|
-
"@vaadin/testing-helpers": "^
|
|
48
|
+
"@vaadin/chai-plugins": "25.0.0-alpha11",
|
|
49
|
+
"@vaadin/icon": "25.0.0-alpha11",
|
|
50
|
+
"@vaadin/test-runner-commands": "25.0.0-alpha11",
|
|
51
|
+
"@vaadin/testing-helpers": "^2.0.0",
|
|
52
|
+
"@vaadin/vaadin-lumo-styles": "25.0.0-alpha11",
|
|
54
53
|
"sinon": "^18.0.0"
|
|
55
54
|
},
|
|
56
55
|
"web-types": [
|
|
57
56
|
"web-types.json",
|
|
58
57
|
"web-types.lit.json"
|
|
59
58
|
],
|
|
60
|
-
"gitHead": "
|
|
59
|
+
"gitHead": "abfd315ba5a7484a613e0768635a4e8fe945a44b"
|
|
61
60
|
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (c) 2019 - 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 'lit';
|
|
7
|
+
|
|
8
|
+
export const menuBarStyles = css`
|
|
9
|
+
:host {
|
|
10
|
+
display: block;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
:host([hidden]) {
|
|
14
|
+
display: none !important;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
[part='container'] {
|
|
18
|
+
display: flex;
|
|
19
|
+
flex-wrap: nowrap;
|
|
20
|
+
margin: calc((var(--vaadin-focus-ring-width) + 1px) * -1);
|
|
21
|
+
overflow: hidden;
|
|
22
|
+
padding: calc(var(--vaadin-focus-ring-width) + 1px);
|
|
23
|
+
position: relative;
|
|
24
|
+
width: 100%;
|
|
25
|
+
--_gap: var(--vaadin-menu-bar-gap, 0px);
|
|
26
|
+
--_bw: var(--vaadin-button-border-width, 1px);
|
|
27
|
+
gap: var(--_gap);
|
|
28
|
+
--_rad-button: var(--vaadin-button-border-radius, var(--vaadin-radius-m));
|
|
29
|
+
--_rad: min(var(--_gap) * 1000, var(--_rad-button));
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
::slotted(vaadin-menu-bar-button:not(:first-of-type)) {
|
|
33
|
+
margin-inline-start: min(var(--_bw) * -1 + var(--_gap) * 1000, 0px);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
::slotted(vaadin-menu-bar-button) {
|
|
37
|
+
border-radius: var(--_rad);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
::slotted([first-visible]),
|
|
41
|
+
:host([has-single-button]) ::slotted([slot='overflow']) {
|
|
42
|
+
border-start-start-radius: var(--_rad-button);
|
|
43
|
+
border-end-start-radius: var(--_rad-button);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
::slotted(:is([last-visible], [slot='overflow'])) {
|
|
47
|
+
border-start-end-radius: var(--_rad-button);
|
|
48
|
+
border-end-end-radius: var(--_rad-button);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
:host([theme~='end-aligned']) ::slotted(vaadin-menu-bar-button[first-visible]),
|
|
52
|
+
:host([theme~='end-aligned'][has-single-button]) ::slotted(vaadin-menu-bar-button) {
|
|
53
|
+
margin-inline-start: auto;
|
|
54
|
+
}
|
|
55
|
+
`;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (c) 2019 - 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 'lit';
|
|
7
|
+
|
|
8
|
+
export const menuBarButtonStyles = css`
|
|
9
|
+
:host {
|
|
10
|
+
flex-shrink: 0;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
:host([focus-ring]) {
|
|
14
|
+
z-index: 1;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
:host([slot='overflow']) {
|
|
18
|
+
margin-inline-end: 0;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.vaadin-button-container {
|
|
22
|
+
gap: inherit;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
:host(:not([slot='overflow']):not([theme~='icon'])[aria-haspopup]) [part='suffix'] {
|
|
26
|
+
display: flex;
|
|
27
|
+
align-items: center;
|
|
28
|
+
gap: inherit;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
:host(:not([slot='overflow']):not([theme~='icon'])[aria-haspopup]) [part='suffix']::after {
|
|
32
|
+
background: currentColor;
|
|
33
|
+
content: '';
|
|
34
|
+
height: var(--vaadin-icon-size, 1lh);
|
|
35
|
+
mask-image: var(--_vaadin-icon-chevron-down);
|
|
36
|
+
width: var(--vaadin-icon-size, 1lh);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
::slotted(vaadin-menu-bar-item) {
|
|
40
|
+
padding: 0;
|
|
41
|
+
gap: 0;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
::slotted(vaadin-menu-bar-item)::after {
|
|
45
|
+
display: none;
|
|
46
|
+
}
|
|
47
|
+
`;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (c) 2019 - 2025 Vaadin Ltd.
|
|
4
|
+
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
+
*/
|
|
6
|
+
import { contextMenuItemStyles } from '@vaadin/context-menu/src/styles/vaadin-context-menu-item-base-styles.js';
|
|
7
|
+
|
|
8
|
+
export const menuBarItemStyles = contextMenuItemStyles;
|
|
@@ -0,0 +1,9 @@
|
|
|
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 { menuOverlayStyles } from '@vaadin/context-menu/src/styles/vaadin-menu-overlay-base-styles.js';
|
|
7
|
+
import { overlayStyles } from '@vaadin/overlay/src/styles/vaadin-overlay-base-styles.js';
|
|
8
|
+
|
|
9
|
+
export const menuBarOverlayStyles = [overlayStyles, menuOverlayStyles];
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { Button } from '@vaadin/button/src/vaadin-button.js';
|
|
7
7
|
import { defineCustomElement } from '@vaadin/component-base/src/define.js';
|
|
8
|
-
import {
|
|
8
|
+
import { menuBarButtonStyles } from './styles/vaadin-menu-bar-button-base-styles.js';
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* An element used internally by `<vaadin-menu-bar>`. Not intended to be used separately.
|
|
@@ -20,18 +20,7 @@ class MenuBarButton extends Button {
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
static get styles() {
|
|
23
|
-
return [
|
|
24
|
-
super.styles,
|
|
25
|
-
css`
|
|
26
|
-
:host {
|
|
27
|
-
flex-shrink: 0;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
:host([slot='overflow']) {
|
|
31
|
-
margin-inline-end: 0;
|
|
32
|
-
}
|
|
33
|
-
`,
|
|
34
|
-
];
|
|
23
|
+
return [super.styles, menuBarButtonStyles];
|
|
35
24
|
}
|
|
36
25
|
|
|
37
26
|
/**
|
|
@@ -3,12 +3,14 @@
|
|
|
3
3
|
* Copyright (c) 2019 - 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 {
|
|
6
|
+
import { html, LitElement } from 'lit';
|
|
7
7
|
import { defineCustomElement } from '@vaadin/component-base/src/define.js';
|
|
8
8
|
import { DirMixin } from '@vaadin/component-base/src/dir-mixin.js';
|
|
9
9
|
import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
|
|
10
10
|
import { ItemMixin } from '@vaadin/item/src/vaadin-item-mixin.js';
|
|
11
|
+
import { LumoInjectionMixin } from '@vaadin/vaadin-themable-mixin/lumo-injection-mixin.js';
|
|
11
12
|
import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
13
|
+
import { menuBarItemStyles } from './styles/vaadin-menu-bar-item-base-styles.js';
|
|
12
14
|
|
|
13
15
|
/**
|
|
14
16
|
* An element used internally by `<vaadin-menu-bar>`. Not intended to be used separately.
|
|
@@ -20,21 +22,13 @@ import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mix
|
|
|
20
22
|
* @mixes ThemableMixin
|
|
21
23
|
* @protected
|
|
22
24
|
*/
|
|
23
|
-
class MenuBarItem extends ItemMixin(ThemableMixin(DirMixin(PolylitMixin(LitElement)))) {
|
|
25
|
+
class MenuBarItem extends ItemMixin(ThemableMixin(DirMixin(PolylitMixin(LumoInjectionMixin(LitElement))))) {
|
|
24
26
|
static get is() {
|
|
25
27
|
return 'vaadin-menu-bar-item';
|
|
26
28
|
}
|
|
27
29
|
|
|
28
30
|
static get styles() {
|
|
29
|
-
return
|
|
30
|
-
:host {
|
|
31
|
-
display: inline-block;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
:host([hidden]) {
|
|
35
|
-
display: none !important;
|
|
36
|
-
}
|
|
37
|
-
`;
|
|
31
|
+
return menuBarItemStyles;
|
|
38
32
|
}
|
|
39
33
|
|
|
40
34
|
/** @protected */
|
|
@@ -3,11 +3,13 @@
|
|
|
3
3
|
* Copyright (c) 2019 - 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 {
|
|
6
|
+
import { html, LitElement } from 'lit';
|
|
7
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-base-styles.js';
|
|
12
|
+
import { LumoInjectionMixin } from '@vaadin/vaadin-themable-mixin/lumo-injection-mixin.js';
|
|
11
13
|
import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
12
14
|
|
|
13
15
|
/**
|
|
@@ -20,28 +22,13 @@ import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mix
|
|
|
20
22
|
* @mixes ThemableMixin
|
|
21
23
|
* @protected
|
|
22
24
|
*/
|
|
23
|
-
class MenuBarListBox extends ListMixin(ThemableMixin(DirMixin(PolylitMixin(LitElement)))) {
|
|
25
|
+
class MenuBarListBox extends ListMixin(ThemableMixin(DirMixin(PolylitMixin(LumoInjectionMixin(LitElement))))) {
|
|
24
26
|
static get is() {
|
|
25
27
|
return 'vaadin-menu-bar-list-box';
|
|
26
28
|
}
|
|
27
29
|
|
|
28
30
|
static get styles() {
|
|
29
|
-
return
|
|
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
|
-
`;
|
|
31
|
+
return listBoxStyles;
|
|
45
32
|
}
|
|
46
33
|
|
|
47
34
|
static get properties() {
|
|
@@ -10,6 +10,8 @@ import { DisabledMixin } from '@vaadin/a11y-base/src/disabled-mixin.js';
|
|
|
10
10
|
import { FocusMixin } from '@vaadin/a11y-base/src/focus-mixin.js';
|
|
11
11
|
import { isElementFocused, isKeyboardActive } from '@vaadin/a11y-base/src/focus-utils.js';
|
|
12
12
|
import { KeyboardDirectionMixin } from '@vaadin/a11y-base/src/keyboard-direction-mixin.js';
|
|
13
|
+
import { microTask } from '@vaadin/component-base/src/async.js';
|
|
14
|
+
import { Debouncer } from '@vaadin/component-base/src/debounce.js';
|
|
13
15
|
import { I18nMixin } from '@vaadin/component-base/src/i18n-mixin.js';
|
|
14
16
|
import { ResizeMixin } from '@vaadin/component-base/src/resize-mixin.js';
|
|
15
17
|
import { SlotController } from '@vaadin/component-base/src/slot-controller.js';
|
|
@@ -189,41 +191,9 @@ export const MenuBarMixin = (superClass) =>
|
|
|
189
191
|
type: Boolean,
|
|
190
192
|
sync: true,
|
|
191
193
|
},
|
|
192
|
-
|
|
193
|
-
/**
|
|
194
|
-
* @type {boolean}
|
|
195
|
-
* @protected
|
|
196
|
-
*/
|
|
197
|
-
_hasOverflow: {
|
|
198
|
-
type: Boolean,
|
|
199
|
-
value: false,
|
|
200
|
-
sync: true,
|
|
201
|
-
},
|
|
202
|
-
|
|
203
|
-
/** @protected */
|
|
204
|
-
_overflow: {
|
|
205
|
-
type: Object,
|
|
206
|
-
},
|
|
207
|
-
|
|
208
|
-
/** @protected */
|
|
209
|
-
_container: {
|
|
210
|
-
type: Object,
|
|
211
|
-
sync: true,
|
|
212
|
-
},
|
|
213
194
|
};
|
|
214
195
|
}
|
|
215
196
|
|
|
216
|
-
static get observers() {
|
|
217
|
-
return [
|
|
218
|
-
'_themeChanged(_theme, _overflow, _container)',
|
|
219
|
-
'__hasOverflowChanged(_hasOverflow, _overflow)',
|
|
220
|
-
'__i18nChanged(__effectiveI18n, _overflow)',
|
|
221
|
-
'__updateButtons(items, disabled, _overflow, _container)',
|
|
222
|
-
'_reverseCollapseChanged(reverseCollapse, _overflow, _container)',
|
|
223
|
-
'_tabNavigationChanged(tabNavigation, _overflow, _container)',
|
|
224
|
-
];
|
|
225
|
-
}
|
|
226
|
-
|
|
227
197
|
/**
|
|
228
198
|
* The object used to localize this component. To change the default
|
|
229
199
|
* localization, replace this with an object that provides all properties, or
|
|
@@ -305,8 +275,15 @@ export const MenuBarMixin = (superClass) =>
|
|
|
305
275
|
}
|
|
306
276
|
|
|
307
277
|
/** @private */
|
|
308
|
-
get
|
|
309
|
-
return this.
|
|
278
|
+
get _hasOverflow() {
|
|
279
|
+
return this._overflow && !this._overflow.hasAttribute('hidden');
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/** @private */
|
|
283
|
+
set _hasOverflow(hasOverflow) {
|
|
284
|
+
if (this._overflow) {
|
|
285
|
+
this._overflow.toggleAttribute('hidden', !hasOverflow);
|
|
286
|
+
}
|
|
310
287
|
}
|
|
311
288
|
|
|
312
289
|
/** @protected */
|
|
@@ -315,6 +292,20 @@ export const MenuBarMixin = (superClass) =>
|
|
|
315
292
|
|
|
316
293
|
this.setAttribute('role', 'menubar');
|
|
317
294
|
|
|
295
|
+
this._subMenuController = new SlotController(this, 'submenu', 'vaadin-menu-bar-submenu', {
|
|
296
|
+
initializer: (menu) => {
|
|
297
|
+
menu.setAttribute('is-root', '');
|
|
298
|
+
|
|
299
|
+
menu.addEventListener('item-selected', this.__onItemSelected.bind(this));
|
|
300
|
+
menu.addEventListener('close-all-menus', this.__onEscapeClose.bind(this));
|
|
301
|
+
|
|
302
|
+
const overlay = menu._overlayElement;
|
|
303
|
+
overlay._contentRoot.addEventListener('keydown', this.__boundOnContextMenuKeydown);
|
|
304
|
+
|
|
305
|
+
this._subMenu = menu;
|
|
306
|
+
},
|
|
307
|
+
});
|
|
308
|
+
|
|
318
309
|
this._overflowController = new SlotController(this, 'overflow', 'vaadin-menu-bar-button', {
|
|
319
310
|
initializer: (btn) => {
|
|
320
311
|
btn.setAttribute('hidden', '');
|
|
@@ -331,27 +322,51 @@ export const MenuBarMixin = (superClass) =>
|
|
|
331
322
|
this._overflow = btn;
|
|
332
323
|
},
|
|
333
324
|
});
|
|
325
|
+
|
|
326
|
+
this.addController(this._subMenuController);
|
|
334
327
|
this.addController(this._overflowController);
|
|
335
328
|
|
|
336
329
|
this.addEventListener('mousedown', () => this._hideTooltip(true));
|
|
337
330
|
this.addEventListener('mouseleave', () => this._hideTooltip());
|
|
338
331
|
|
|
339
|
-
this.
|
|
340
|
-
|
|
332
|
+
this._container = this.shadowRoot.querySelector('[part="container"]');
|
|
333
|
+
}
|
|
341
334
|
|
|
342
|
-
|
|
343
|
-
|
|
335
|
+
/** @protected */
|
|
336
|
+
updated(props) {
|
|
337
|
+
super.updated(props);
|
|
344
338
|
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
339
|
+
if (props.has('items') || props.has('_theme') || props.has('disabled')) {
|
|
340
|
+
this.__renderButtons(this.items);
|
|
341
|
+
}
|
|
348
342
|
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
343
|
+
if (props.has('items') || props.has('_theme') || props.has('reverseCollapse')) {
|
|
344
|
+
this.__scheduleOverflow();
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
if (props.has('items')) {
|
|
348
|
+
this.__updateSubMenu();
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
if (props.has('overlayClass')) {
|
|
352
|
+
this._subMenu.overlayClass = this.overlayClass;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
if (props.has('_theme')) {
|
|
356
|
+
this._themeChanged(this._theme);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
if (props.has('disabled')) {
|
|
360
|
+
this._overflow.toggleAttribute('disabled', this.disabled);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
if (props.has('tabNavigation')) {
|
|
364
|
+
this._tabNavigationChanged(this.tabNavigation);
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
if (props.has('__effectiveI18n')) {
|
|
368
|
+
this.__i18nChanged(this.__effectiveI18n);
|
|
369
|
+
}
|
|
355
370
|
}
|
|
356
371
|
|
|
357
372
|
/**
|
|
@@ -380,84 +395,37 @@ export const MenuBarMixin = (superClass) =>
|
|
|
380
395
|
* @override
|
|
381
396
|
*/
|
|
382
397
|
_onResize() {
|
|
383
|
-
this.
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
/**
|
|
387
|
-
* A callback for the `_theme` property observer.
|
|
388
|
-
* It propagates the host theme to the buttons and the sub menu.
|
|
389
|
-
*
|
|
390
|
-
* @param {string | null} theme
|
|
391
|
-
* @private
|
|
392
|
-
*/
|
|
393
|
-
_themeChanged(theme, overflow, container) {
|
|
394
|
-
if (overflow && container) {
|
|
395
|
-
this.__renderButtons(this.items);
|
|
396
|
-
this.__detectOverflow();
|
|
397
|
-
|
|
398
|
-
if (theme) {
|
|
399
|
-
overflow.setAttribute('theme', theme);
|
|
400
|
-
this._subMenu.setAttribute('theme', theme);
|
|
401
|
-
} else {
|
|
402
|
-
overflow.removeAttribute('theme');
|
|
403
|
-
this._subMenu.removeAttribute('theme');
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
/**
|
|
409
|
-
* A callback for the 'reverseCollapse' property observer.
|
|
410
|
-
*
|
|
411
|
-
* @param {boolean | null} _reverseCollapse
|
|
412
|
-
* @private
|
|
413
|
-
*/
|
|
414
|
-
_reverseCollapseChanged(_reverseCollapse, overflow, container) {
|
|
415
|
-
if (overflow && container) {
|
|
416
|
-
this.__detectOverflow();
|
|
417
|
-
}
|
|
398
|
+
this.__scheduleOverflow();
|
|
418
399
|
}
|
|
419
400
|
|
|
420
401
|
/** @private */
|
|
421
|
-
|
|
422
|
-
if (
|
|
423
|
-
|
|
424
|
-
this.
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
this._setTabindex(btn, false);
|
|
429
|
-
}
|
|
430
|
-
btn.setAttribute('role', tabNavigation ? 'button' : 'menuitem');
|
|
431
|
-
});
|
|
402
|
+
_themeChanged(theme) {
|
|
403
|
+
if (theme) {
|
|
404
|
+
this._overflow.setAttribute('theme', theme);
|
|
405
|
+
this._subMenu.setAttribute('theme', theme);
|
|
406
|
+
} else {
|
|
407
|
+
this._overflow.removeAttribute('theme');
|
|
408
|
+
this._subMenu.removeAttribute('theme');
|
|
432
409
|
}
|
|
433
|
-
this.setAttribute('role', tabNavigation ? 'group' : 'menubar');
|
|
434
410
|
}
|
|
435
411
|
|
|
436
412
|
/** @private */
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
413
|
+
_tabNavigationChanged(tabNavigation) {
|
|
414
|
+
const target = this.querySelector('[tabindex="0"]');
|
|
415
|
+
this._buttons.forEach((btn) => {
|
|
416
|
+
if (target) {
|
|
417
|
+
this._setTabindex(btn, btn === target);
|
|
418
|
+
} else {
|
|
419
|
+
this._setTabindex(btn, false);
|
|
420
|
+
}
|
|
421
|
+
btn.setAttribute('role', tabNavigation ? 'button' : 'menuitem');
|
|
422
|
+
});
|
|
423
|
+
|
|
424
|
+
this.setAttribute('role', tabNavigation ? 'group' : 'menubar');
|
|
441
425
|
}
|
|
442
426
|
|
|
443
427
|
/** @private */
|
|
444
|
-
|
|
445
|
-
if (!overflow || !container) {
|
|
446
|
-
return;
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
if (items !== this._oldItems) {
|
|
450
|
-
this._oldItems = items;
|
|
451
|
-
this.__renderButtons(items);
|
|
452
|
-
this.__detectOverflow();
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
if (disabled !== this._oldDisabled) {
|
|
456
|
-
this._oldDisabled = disabled;
|
|
457
|
-
this.__renderButtons(items);
|
|
458
|
-
overflow.toggleAttribute('disabled', disabled);
|
|
459
|
-
}
|
|
460
|
-
|
|
428
|
+
__updateSubMenu() {
|
|
461
429
|
const subMenu = this._subMenu;
|
|
462
430
|
if (subMenu && subMenu.opened) {
|
|
463
431
|
const button = subMenu._overlayElement.positionTarget;
|
|
@@ -471,12 +439,12 @@ export const MenuBarMixin = (superClass) =>
|
|
|
471
439
|
}
|
|
472
440
|
|
|
473
441
|
/** @private */
|
|
474
|
-
__i18nChanged(effectiveI18n
|
|
475
|
-
if (
|
|
442
|
+
__i18nChanged(effectiveI18n) {
|
|
443
|
+
if (effectiveI18n && effectiveI18n.moreOptions !== undefined) {
|
|
476
444
|
if (effectiveI18n.moreOptions) {
|
|
477
|
-
|
|
445
|
+
this._overflow.setAttribute('aria-label', effectiveI18n.moreOptions);
|
|
478
446
|
} else {
|
|
479
|
-
|
|
447
|
+
this._overflow.removeAttribute('aria-label');
|
|
480
448
|
}
|
|
481
449
|
}
|
|
482
450
|
}
|
|
@@ -561,11 +529,14 @@ export const MenuBarMixin = (superClass) =>
|
|
|
561
529
|
}
|
|
562
530
|
|
|
563
531
|
/** @private */
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
}
|
|
532
|
+
__scheduleOverflow() {
|
|
533
|
+
this._overflowDebouncer = Debouncer.debounce(this._overflowDebouncer, microTask, () => {
|
|
534
|
+
this.__detectOverflow();
|
|
535
|
+
});
|
|
536
|
+
}
|
|
568
537
|
|
|
538
|
+
/** @private */
|
|
539
|
+
__detectOverflow() {
|
|
569
540
|
const overflow = this._overflow;
|
|
570
541
|
const buttons = this._buttons.filter((btn) => btn !== overflow);
|
|
571
542
|
const oldOverflowCount = this.__getOverflowCount(overflow);
|
|
@@ -707,6 +678,7 @@ export const MenuBarMixin = (superClass) =>
|
|
|
707
678
|
_hideTooltip(immediate) {
|
|
708
679
|
const tooltip = this._tooltipController && this._tooltipController.node;
|
|
709
680
|
if (tooltip) {
|
|
681
|
+
this._tooltipController.setContext({ item: null });
|
|
710
682
|
tooltip._stateController.close(immediate);
|
|
711
683
|
}
|
|
712
684
|
}
|
|
@@ -770,6 +742,34 @@ export const MenuBarMixin = (superClass) =>
|
|
|
770
742
|
return Array.from(e.composedPath()).find((el) => el.localName === 'vaadin-menu-bar-button');
|
|
771
743
|
}
|
|
772
744
|
|
|
745
|
+
/**
|
|
746
|
+
* Override method inherited from `FocusMixin`
|
|
747
|
+
*
|
|
748
|
+
* @override
|
|
749
|
+
* @protected
|
|
750
|
+
*/
|
|
751
|
+
_shouldSetFocus(event) {
|
|
752
|
+
// Ignore events from the submenu
|
|
753
|
+
if (event.composedPath().includes(this._subMenu)) {
|
|
754
|
+
return false;
|
|
755
|
+
}
|
|
756
|
+
return super._shouldSetFocus(event);
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
/**
|
|
760
|
+
* Override method inherited from `FocusMixin`
|
|
761
|
+
*
|
|
762
|
+
* @override
|
|
763
|
+
* @protected
|
|
764
|
+
*/
|
|
765
|
+
_shouldRemoveFocus(event) {
|
|
766
|
+
// Ignore events from the submenu
|
|
767
|
+
if (event.composedPath().includes(this._subMenu)) {
|
|
768
|
+
return false;
|
|
769
|
+
}
|
|
770
|
+
return super._shouldRemoveFocus(event);
|
|
771
|
+
}
|
|
772
|
+
|
|
773
773
|
/**
|
|
774
774
|
* Override method inherited from `FocusMixin`
|
|
775
775
|
*
|
|
@@ -852,6 +852,16 @@ export const MenuBarMixin = (superClass) =>
|
|
|
852
852
|
* @override
|
|
853
853
|
*/
|
|
854
854
|
_onKeyDown(event) {
|
|
855
|
+
// Ignore events from the submenu
|
|
856
|
+
if (event.composedPath().includes(this._subMenu)) {
|
|
857
|
+
return;
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
this._handleKeyDown(event);
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
/** @private */
|
|
864
|
+
_handleKeyDown(event) {
|
|
855
865
|
switch (event.key) {
|
|
856
866
|
case 'ArrowDown':
|
|
857
867
|
this._onArrowDown(event);
|
|
@@ -866,11 +876,16 @@ export const MenuBarMixin = (superClass) =>
|
|
|
866
876
|
}
|
|
867
877
|
|
|
868
878
|
/**
|
|
869
|
-
* @param {!MouseEvent}
|
|
879
|
+
* @param {!MouseEvent} event
|
|
870
880
|
* @protected
|
|
871
881
|
*/
|
|
872
|
-
_onMouseOver(
|
|
873
|
-
|
|
882
|
+
_onMouseOver(event) {
|
|
883
|
+
// Ignore events from the submenu
|
|
884
|
+
if (event.composedPath().includes(this._subMenu)) {
|
|
885
|
+
return;
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
const button = this._getButtonFromEvent(event);
|
|
874
889
|
if (!button) {
|
|
875
890
|
// Hide tooltip on mouseover to disabled button
|
|
876
891
|
this._hideTooltip();
|
|
@@ -902,11 +917,11 @@ export const MenuBarMixin = (superClass) =>
|
|
|
902
917
|
if (e.keyCode === 37 || (e.keyCode === 39 && !item._item.children)) {
|
|
903
918
|
// Prevent ArrowLeft from being handled in context-menu
|
|
904
919
|
e.stopImmediatePropagation();
|
|
905
|
-
this.
|
|
920
|
+
this._handleKeyDown(e);
|
|
906
921
|
}
|
|
907
922
|
|
|
908
923
|
if (e.key === 'Tab' && this.tabNavigation) {
|
|
909
|
-
this.
|
|
924
|
+
this._handleKeyDown(e);
|
|
910
925
|
}
|
|
911
926
|
}
|
|
912
927
|
}
|
|
@@ -989,13 +1004,13 @@ export const MenuBarMixin = (superClass) =>
|
|
|
989
1004
|
|
|
990
1005
|
/** @private */
|
|
991
1006
|
_focusFirstItem() {
|
|
992
|
-
const list = this._subMenu._overlayElement.firstElementChild;
|
|
1007
|
+
const list = this._subMenu._overlayElement._contentRoot.firstElementChild;
|
|
993
1008
|
list.focus();
|
|
994
1009
|
}
|
|
995
1010
|
|
|
996
1011
|
/** @private */
|
|
997
1012
|
_focusLastItem() {
|
|
998
|
-
const list = this._subMenu._overlayElement.firstElementChild;
|
|
1013
|
+
const list = this._subMenu._overlayElement._contentRoot.firstElementChild;
|
|
999
1014
|
const item = list.items[list.items.length - 1];
|
|
1000
1015
|
if (item) {
|
|
1001
1016
|
item.focus();
|
|
@@ -8,10 +8,10 @@ import { defineCustomElement } from '@vaadin/component-base/src/define.js';
|
|
|
8
8
|
import { DirMixin } from '@vaadin/component-base/src/dir-mixin.js';
|
|
9
9
|
import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
|
|
10
10
|
import { MenuOverlayMixin } from '@vaadin/context-menu/src/vaadin-menu-overlay-mixin.js';
|
|
11
|
-
import { styles } from '@vaadin/context-menu/src/vaadin-menu-overlay-styles.js';
|
|
12
11
|
import { OverlayMixin } from '@vaadin/overlay/src/vaadin-overlay-mixin.js';
|
|
13
|
-
import {
|
|
12
|
+
import { LumoInjectionMixin } from '@vaadin/vaadin-themable-mixin/lumo-injection-mixin.js';
|
|
14
13
|
import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
14
|
+
import { menuBarOverlayStyles } from './styles/vaadin-menu-bar-overlay-base-styles.js';
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* An element used internally by `<vaadin-menu-bar>`. Not intended to be used separately.
|
|
@@ -24,13 +24,15 @@ import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mix
|
|
|
24
24
|
* @mixes ThemableMixin
|
|
25
25
|
* @protected
|
|
26
26
|
*/
|
|
27
|
-
export class MenuBarOverlay extends MenuOverlayMixin(
|
|
27
|
+
export class MenuBarOverlay extends MenuOverlayMixin(
|
|
28
|
+
OverlayMixin(DirMixin(ThemableMixin(PolylitMixin(LumoInjectionMixin(LitElement))))),
|
|
29
|
+
) {
|
|
28
30
|
static get is() {
|
|
29
31
|
return 'vaadin-menu-bar-overlay';
|
|
30
32
|
}
|
|
31
33
|
|
|
32
34
|
static get styles() {
|
|
33
|
-
return
|
|
35
|
+
return menuBarOverlayStyles;
|
|
34
36
|
}
|
|
35
37
|
|
|
36
38
|
/** @protected */
|
|
@@ -40,6 +42,7 @@ export class MenuBarOverlay extends MenuOverlayMixin(OverlayMixin(DirMixin(Thema
|
|
|
40
42
|
<div part="overlay" id="overlay" tabindex="0">
|
|
41
43
|
<div part="content" id="content">
|
|
42
44
|
<slot></slot>
|
|
45
|
+
<slot name="submenu"></slot>
|
|
43
46
|
</div>
|
|
44
47
|
</div>
|
|
45
48
|
`;
|
|
@@ -31,8 +31,8 @@ export const SubMenuMixin = (superClass) =>
|
|
|
31
31
|
/**
|
|
32
32
|
* Overriding the observer to not add global "contextmenu" listener.
|
|
33
33
|
*/
|
|
34
|
-
_openedChanged(
|
|
35
|
-
|
|
34
|
+
_openedChanged() {
|
|
35
|
+
// Do nothing
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
/**
|
|
@@ -43,7 +43,7 @@ export const SubMenuMixin = (superClass) =>
|
|
|
43
43
|
|
|
44
44
|
// Only handle 1st level submenu
|
|
45
45
|
if (this.hasAttribute('is-root')) {
|
|
46
|
-
this.
|
|
46
|
+
this.parentElement._close();
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
|
|
@@ -7,6 +7,7 @@ import './vaadin-menu-bar-item.js';
|
|
|
7
7
|
import './vaadin-menu-bar-list-box.js';
|
|
8
8
|
import './vaadin-menu-bar-overlay.js';
|
|
9
9
|
import { css, html, LitElement } from 'lit';
|
|
10
|
+
import { ifDefined } from 'lit/directives/if-defined.js';
|
|
10
11
|
import { defineCustomElement } from '@vaadin/component-base/src/define.js';
|
|
11
12
|
import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
|
|
12
13
|
import { ThemePropertyMixin } from '@vaadin/vaadin-themable-mixin/vaadin-theme-property-mixin.js';
|
|
@@ -40,17 +41,25 @@ class MenuBarSubmenu extends SubMenuMixin(ThemePropertyMixin(PolylitMixin(LitEle
|
|
|
40
41
|
|
|
41
42
|
/** @protected */
|
|
42
43
|
render() {
|
|
43
|
-
return html
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
44
|
+
return html`
|
|
45
|
+
<vaadin-menu-bar-overlay
|
|
46
|
+
id="overlay"
|
|
47
|
+
.owner="${this}"
|
|
48
|
+
.opened="${this.opened}"
|
|
49
|
+
.model="${this._context}"
|
|
50
|
+
.modeless="${this._modeless}"
|
|
51
|
+
.renderer="${this.__itemsRenderer}"
|
|
52
|
+
.withBackdrop="${this._phone}"
|
|
53
|
+
?phone="${this._phone}"
|
|
54
|
+
theme="${ifDefined(this._theme)}"
|
|
55
|
+
exportparts="backdrop, overlay, content"
|
|
56
|
+
@opened-changed="${this._onOverlayOpened}"
|
|
57
|
+
@vaadin-overlay-open="${this._onVaadinOverlayOpen}"
|
|
58
|
+
>
|
|
59
|
+
<slot name="overlay"></slot>
|
|
60
|
+
<slot name="submenu" slot="submenu"></slot>
|
|
61
|
+
</vaadin-menu-bar-overlay>
|
|
62
|
+
`;
|
|
54
63
|
}
|
|
55
64
|
}
|
|
56
65
|
|
package/src/vaadin-menu-bar.d.ts
CHANGED
|
@@ -30,13 +30,13 @@ export interface MenuBarEventMap<TItem extends MenuBarItem = MenuBarItem>
|
|
|
30
30
|
*
|
|
31
31
|
* To create the menu bar, first add the component to the page:
|
|
32
32
|
*
|
|
33
|
-
* ```
|
|
33
|
+
* ```html
|
|
34
34
|
* <vaadin-menu-bar></vaadin-menu-bar>
|
|
35
35
|
* ```
|
|
36
36
|
*
|
|
37
37
|
* And then use [`items`](#/elements/vaadin-menu-bar#property-items) property to initialize the structure:
|
|
38
38
|
*
|
|
39
|
-
* ```
|
|
39
|
+
* ```js
|
|
40
40
|
* document.querySelector('vaadin-menu-bar').items = [{text: 'File'}, {text: 'Edit'}];
|
|
41
41
|
* ```
|
|
42
42
|
*
|
|
@@ -65,7 +65,7 @@ export interface MenuBarEventMap<TItem extends MenuBarItem = MenuBarItem>
|
|
|
65
65
|
* - `<vaadin-menu-bar-button>` - has the same API as [`<vaadin-button>`](#/elements/vaadin-button).
|
|
66
66
|
* - `<vaadin-menu-bar-item>` - has the same API as [`<vaadin-item>`](#/elements/vaadin-item).
|
|
67
67
|
* - `<vaadin-menu-bar-list-box>` - has the same API as [`<vaadin-list-box>`](#/elements/vaadin-list-box).
|
|
68
|
-
* - `<vaadin-menu-bar-
|
|
68
|
+
* - `<vaadin-menu-bar-submenu>` - has the same API as [`<vaadin-context-menu>`](#/elements/vaadin-context-menu).
|
|
69
69
|
*
|
|
70
70
|
* The `<vaadin-menu-bar-item>` sub-menu elements have the following additional state attributes
|
|
71
71
|
* on top of the built-in `<vaadin-item>` state attributes:
|
|
@@ -74,9 +74,6 @@ export interface MenuBarEventMap<TItem extends MenuBarItem = MenuBarItem>
|
|
|
74
74
|
* ---------- |-------------
|
|
75
75
|
* `expanded` | Expanded parent item.
|
|
76
76
|
*
|
|
77
|
-
* Note: the `theme` attribute value set on `<vaadin-menu-bar>` is
|
|
78
|
-
* propagated to the internal components listed above.
|
|
79
|
-
*
|
|
80
77
|
* @fires {CustomEvent} item-selected - Fired when a submenu item or menu bar button without children is clicked.
|
|
81
78
|
*/
|
|
82
79
|
declare class MenuBar<TItem extends MenuBarItem = MenuBarItem> extends HTMLElement {
|
package/src/vaadin-menu-bar.js
CHANGED
|
@@ -5,12 +5,14 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import './vaadin-menu-bar-submenu.js';
|
|
7
7
|
import './vaadin-menu-bar-button.js';
|
|
8
|
-
import {
|
|
8
|
+
import { html, LitElement } from 'lit';
|
|
9
9
|
import { defineCustomElement } from '@vaadin/component-base/src/define.js';
|
|
10
10
|
import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
|
|
11
11
|
import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
|
|
12
12
|
import { TooltipController } from '@vaadin/component-base/src/tooltip-controller.js';
|
|
13
|
+
import { LumoInjectionMixin } from '@vaadin/vaadin-themable-mixin/lumo-injection-mixin.js';
|
|
13
14
|
import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
15
|
+
import { menuBarStyles } from './styles/vaadin-menu-bar-base-styles.js';
|
|
14
16
|
import { MenuBarMixin } from './vaadin-menu-bar-mixin.js';
|
|
15
17
|
|
|
16
18
|
/**
|
|
@@ -20,13 +22,13 @@ import { MenuBarMixin } from './vaadin-menu-bar-mixin.js';
|
|
|
20
22
|
*
|
|
21
23
|
* To create the menu bar, first add the component to the page:
|
|
22
24
|
*
|
|
23
|
-
* ```
|
|
25
|
+
* ```html
|
|
24
26
|
* <vaadin-menu-bar></vaadin-menu-bar>
|
|
25
27
|
* ```
|
|
26
28
|
*
|
|
27
29
|
* And then use [`items`](#/elements/vaadin-menu-bar#property-items) property to initialize the structure:
|
|
28
30
|
*
|
|
29
|
-
* ```
|
|
31
|
+
* ```js
|
|
30
32
|
* document.querySelector('vaadin-menu-bar').items = [{text: 'File'}, {text: 'Edit'}];
|
|
31
33
|
* ```
|
|
32
34
|
*
|
|
@@ -55,7 +57,7 @@ import { MenuBarMixin } from './vaadin-menu-bar-mixin.js';
|
|
|
55
57
|
* - `<vaadin-menu-bar-button>` - has the same API as [`<vaadin-button>`](#/elements/vaadin-button).
|
|
56
58
|
* - `<vaadin-menu-bar-item>` - has the same API as [`<vaadin-item>`](#/elements/vaadin-item).
|
|
57
59
|
* - `<vaadin-menu-bar-list-box>` - has the same API as [`<vaadin-list-box>`](#/elements/vaadin-list-box).
|
|
58
|
-
* - `<vaadin-menu-bar-
|
|
60
|
+
* - `<vaadin-menu-bar-submenu>` - has the same API as [`<vaadin-context-menu>`](#/elements/vaadin-context-menu).
|
|
59
61
|
*
|
|
60
62
|
* The `<vaadin-menu-bar-item>` sub-menu elements have the following additional state attributes
|
|
61
63
|
* on top of the built-in `<vaadin-item>` state attributes:
|
|
@@ -64,9 +66,6 @@ import { MenuBarMixin } from './vaadin-menu-bar-mixin.js';
|
|
|
64
66
|
* ---------- |-------------
|
|
65
67
|
* `expanded` | Expanded parent item.
|
|
66
68
|
*
|
|
67
|
-
* Note: the `theme` attribute value set on `<vaadin-menu-bar>` is
|
|
68
|
-
* propagated to the internal components listed above.
|
|
69
|
-
*
|
|
70
69
|
* @fires {CustomEvent<boolean>} item-selected - Fired when a submenu item or menu bar button without children is clicked.
|
|
71
70
|
*
|
|
72
71
|
* @customElement
|
|
@@ -75,39 +74,24 @@ import { MenuBarMixin } from './vaadin-menu-bar-mixin.js';
|
|
|
75
74
|
* @mixes MenuBarMixin
|
|
76
75
|
* @mixes ThemableMixin
|
|
77
76
|
*/
|
|
78
|
-
class MenuBar extends MenuBarMixin(ElementMixin(ThemableMixin(PolylitMixin(LitElement)))) {
|
|
77
|
+
class MenuBar extends MenuBarMixin(ElementMixin(ThemableMixin(PolylitMixin(LumoInjectionMixin(LitElement))))) {
|
|
79
78
|
static get is() {
|
|
80
79
|
return 'vaadin-menu-bar';
|
|
81
80
|
}
|
|
82
81
|
|
|
83
82
|
static get styles() {
|
|
84
|
-
return
|
|
85
|
-
:host {
|
|
86
|
-
display: block;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
:host([hidden]) {
|
|
90
|
-
display: none !important;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
[part='container'] {
|
|
94
|
-
position: relative;
|
|
95
|
-
display: flex;
|
|
96
|
-
width: 100%;
|
|
97
|
-
flex-wrap: nowrap;
|
|
98
|
-
overflow: hidden;
|
|
99
|
-
}
|
|
100
|
-
`;
|
|
83
|
+
return menuBarStyles;
|
|
101
84
|
}
|
|
102
85
|
|
|
103
86
|
/** @protected */
|
|
104
87
|
render() {
|
|
105
88
|
return html`
|
|
106
|
-
<div part="container">
|
|
89
|
+
<div part="container" @click="${this.__onButtonClick}" @mouseover="${this._onMouseOver}">
|
|
107
90
|
<slot></slot>
|
|
108
91
|
<slot name="overflow"></slot>
|
|
109
92
|
</div>
|
|
110
|
-
|
|
93
|
+
|
|
94
|
+
<slot name="submenu"></slot>
|
|
111
95
|
|
|
112
96
|
<slot name="tooltip"></slot>
|
|
113
97
|
`;
|
package/vaadin-menu-bar.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import './
|
|
1
|
+
import './src/vaadin-menu-bar.js';
|
|
2
2
|
export * from './src/vaadin-menu-bar.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/menu-bar",
|
|
4
|
-
"version": "25.0.0-
|
|
4
|
+
"version": "25.0.0-alpha11",
|
|
5
5
|
"description-markup": "markdown",
|
|
6
6
|
"contributions": {
|
|
7
7
|
"html": {
|
|
8
8
|
"elements": [
|
|
9
9
|
{
|
|
10
10
|
"name": "vaadin-menu-bar",
|
|
11
|
-
"description": "`<vaadin-menu-bar>` is a Web Component providing a set of horizontally stacked buttons offering\nthe user quick access to a consistent set of commands. Each button can toggle a submenu with\nsupport for additional levels of nested menus.\n\nTo create the menu bar, first add the component to the page:\n\n
|
|
11
|
+
"description": "`<vaadin-menu-bar>` is a Web Component providing a set of horizontally stacked buttons offering\nthe user quick access to a consistent set of commands. Each button can toggle a submenu with\nsupport for additional levels of nested menus.\n\nTo create the menu bar, first add the component to the page:\n\n```html\n<vaadin-menu-bar></vaadin-menu-bar>\n```\n\nAnd then use [`items`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-alpha11/#/elements/vaadin-menu-bar#property-items) property to initialize the structure:\n\n```js\ndocument.querySelector('vaadin-menu-bar').items = [{text: 'File'}, {text: 'Edit'}];\n```\n\n### Styling\n\nThe following shadow DOM parts are exposed for styling:\n\nPart name | Description\n------------------|----------------\n`container` | The container wrapping menu bar buttons.\n\nThe following state attributes are available for styling:\n\nAttribute | Description\n--------------------|----------------------------------\n`disabled` | Set when the menu bar is disabled\n`has-single-button` | Set when there is only one button visible\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.\n\n### Internal components\n\nIn addition to `<vaadin-menu-bar>` itself, the following internal\ncomponents are themable:\n\n- `<vaadin-menu-bar-button>` - has the same API as [`<vaadin-button>`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-alpha11/#/elements/vaadin-button).\n- `<vaadin-menu-bar-item>` - has the same API as [`<vaadin-item>`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-alpha11/#/elements/vaadin-item).\n- `<vaadin-menu-bar-list-box>` - has the same API as [`<vaadin-list-box>`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-alpha11/#/elements/vaadin-list-box).\n- `<vaadin-menu-bar-submenu>` - has the same API as [`<vaadin-context-menu>`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-alpha11/#/elements/vaadin-context-menu).\n\nThe `<vaadin-menu-bar-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": "disabled",
|
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/menu-bar",
|
|
4
|
-
"version": "25.0.0-
|
|
4
|
+
"version": "25.0.0-alpha11",
|
|
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-menu-bar",
|
|
19
|
-
"description": "`<vaadin-menu-bar>` is a Web Component providing a set of horizontally stacked buttons offering\nthe user quick access to a consistent set of commands. Each button can toggle a submenu with\nsupport for additional levels of nested menus.\n\nTo create the menu bar, first add the component to the page:\n\n
|
|
19
|
+
"description": "`<vaadin-menu-bar>` is a Web Component providing a set of horizontally stacked buttons offering\nthe user quick access to a consistent set of commands. Each button can toggle a submenu with\nsupport for additional levels of nested menus.\n\nTo create the menu bar, first add the component to the page:\n\n```html\n<vaadin-menu-bar></vaadin-menu-bar>\n```\n\nAnd then use [`items`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-alpha11/#/elements/vaadin-menu-bar#property-items) property to initialize the structure:\n\n```js\ndocument.querySelector('vaadin-menu-bar').items = [{text: 'File'}, {text: 'Edit'}];\n```\n\n### Styling\n\nThe following shadow DOM parts are exposed for styling:\n\nPart name | Description\n------------------|----------------\n`container` | The container wrapping menu bar buttons.\n\nThe following state attributes are available for styling:\n\nAttribute | Description\n--------------------|----------------------------------\n`disabled` | Set when the menu bar is disabled\n`has-single-button` | Set when there is only one button visible\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.\n\n### Internal components\n\nIn addition to `<vaadin-menu-bar>` itself, the following internal\ncomponents are themable:\n\n- `<vaadin-menu-bar-button>` - has the same API as [`<vaadin-button>`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-alpha11/#/elements/vaadin-button).\n- `<vaadin-menu-bar-item>` - has the same API as [`<vaadin-item>`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-alpha11/#/elements/vaadin-item).\n- `<vaadin-menu-bar-list-box>` - has the same API as [`<vaadin-list-box>`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-alpha11/#/elements/vaadin-list-box).\n- `<vaadin-menu-bar-submenu>` - has the same API as [`<vaadin-context-menu>`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-alpha11/#/elements/vaadin-context-menu).\n\nThe `<vaadin-menu-bar-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
|
{
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
import { button } from '@vaadin/button/theme/lumo/vaadin-button-styles.js';
|
|
2
|
-
import { css, registerStyles } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
3
|
-
|
|
4
|
-
const menuBarButton = css`
|
|
5
|
-
:host {
|
|
6
|
-
margin: calc(var(--lumo-space-xs) / 2);
|
|
7
|
-
margin-left: 0;
|
|
8
|
-
border-radius: 0;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
[part='label'] {
|
|
12
|
-
width: 100%;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/* NOTE(web-padawan): avoid using shorthand padding property for IE11 */
|
|
16
|
-
[part='label'] ::slotted(vaadin-menu-bar-item) {
|
|
17
|
-
justify-content: center;
|
|
18
|
-
background-color: transparent;
|
|
19
|
-
height: var(--lumo-button-size);
|
|
20
|
-
margin: 0 calc((var(--lumo-size-m) / 3 + var(--lumo-border-radius-m) / 2) * -1);
|
|
21
|
-
padding-left: calc(var(--lumo-size-m) / 3 + var(--lumo-border-radius-m) / 2);
|
|
22
|
-
padding-right: calc(var(--lumo-size-m) / 3 + var(--lumo-border-radius-m) / 2);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
:host([theme~='small']) [part='label'] ::slotted(vaadin-menu-bar-item) {
|
|
26
|
-
min-height: var(--lumo-size-s);
|
|
27
|
-
margin: 0 calc((var(--lumo-size-s) / 3 + var(--lumo-border-radius-m) / 2) * -1);
|
|
28
|
-
padding-left: calc(var(--lumo-size-s) / 3 + var(--lumo-border-radius-m) / 2);
|
|
29
|
-
padding-right: calc(var(--lumo-size-s) / 3 + var(--lumo-border-radius-m) / 2);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
:host([theme~='tertiary']) [part='label'] ::slotted(vaadin-menu-bar-item) {
|
|
33
|
-
margin: 0 calc((var(--lumo-button-size) / 6) * -1);
|
|
34
|
-
padding-left: calc(var(--lumo-button-size) / 6);
|
|
35
|
-
padding-right: calc(var(--lumo-button-size) / 6);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
:host([theme~='tertiary-inline']) {
|
|
39
|
-
margin-top: calc(var(--lumo-space-xs) / 2);
|
|
40
|
-
margin-bottom: calc(var(--lumo-space-xs) / 2);
|
|
41
|
-
margin-right: calc(var(--lumo-space-xs) / 2);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
:host([theme~='tertiary-inline']) [part='label'] ::slotted(vaadin-menu-bar-item) {
|
|
45
|
-
margin: 0;
|
|
46
|
-
padding: 0;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
:host([first-visible]) {
|
|
50
|
-
border-radius: var(--lumo-border-radius-m) 0 0 var(--lumo-border-radius-m);
|
|
51
|
-
|
|
52
|
-
/* Needed to retain the focus-ring with border-radius */
|
|
53
|
-
margin-left: calc(var(--lumo-space-xs) / 2);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
:host([last-visible]),
|
|
57
|
-
:host([slot='overflow']) {
|
|
58
|
-
border-radius: 0 var(--lumo-border-radius-m) var(--lumo-border-radius-m) 0;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
:host([theme~='tertiary']),
|
|
62
|
-
:host([theme~='tertiary-inline']) {
|
|
63
|
-
border-radius: var(--lumo-border-radius-m);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
:host([slot='overflow']) {
|
|
67
|
-
min-width: var(--lumo-button-size);
|
|
68
|
-
padding-left: calc(var(--lumo-button-size) / 4);
|
|
69
|
-
padding-right: calc(var(--lumo-button-size) / 4);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
:host([slot='overflow']) ::slotted(*) {
|
|
73
|
-
font-size: var(--lumo-font-size-xl);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
:host([slot='overflow']) [part='prefix'],
|
|
77
|
-
:host([slot='overflow']) [part='suffix'] {
|
|
78
|
-
margin-left: 0;
|
|
79
|
-
margin-right: 0;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
:host([theme~='dropdown-indicators']:not([slot='overflow']):not([theme~='icon'])[aria-haspopup]) [part='suffix'] {
|
|
83
|
-
margin-inline-start: 0;
|
|
84
|
-
width: 1em;
|
|
85
|
-
height: 1em;
|
|
86
|
-
line-height: 1;
|
|
87
|
-
font-size: var(--lumo-icon-size-s);
|
|
88
|
-
position: relative;
|
|
89
|
-
inset-inline-start: 0.15em;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/* prettier-ignore */
|
|
93
|
-
:host([theme~='dropdown-indicators']:not([slot='overflow']):not([theme~='icon'])[aria-haspopup]) [part='suffix']::after {
|
|
94
|
-
font-family: lumo-icons;
|
|
95
|
-
content: var(--lumo-icons-dropdown);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/* prettier-ignore */
|
|
99
|
-
:host([theme~='dropdown-indicators']:not([slot='overflow']):not([theme~='icon'])[theme~='tertiary'][aria-haspopup]) [part='suffix'] {
|
|
100
|
-
inset-inline-start: 0.05em;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/* prettier-ignore */
|
|
104
|
-
:host([theme~='dropdown-indicators']:not([slot='overflow']):not([theme~='icon'])[theme~='tertiary-inline'][aria-haspopup]) [part='suffix'] {
|
|
105
|
-
inset-inline-start: 0;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/* RTL styles */
|
|
109
|
-
:host([dir='rtl']) {
|
|
110
|
-
margin-left: calc(var(--lumo-space-xs) / 2);
|
|
111
|
-
margin-right: 0;
|
|
112
|
-
border-radius: 0;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
:host([dir='rtl'][first-visible]) {
|
|
116
|
-
border-radius: 0 var(--lumo-border-radius-m) var(--lumo-border-radius-m) 0;
|
|
117
|
-
margin-right: calc(var(--lumo-space-xs) / 2);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
:host([dir='rtl'][last-visible]),
|
|
121
|
-
:host([dir='rtl'][slot='overflow']) {
|
|
122
|
-
border-radius: var(--lumo-border-radius-m) 0 0 var(--lumo-border-radius-m);
|
|
123
|
-
}
|
|
124
|
-
`;
|
|
125
|
-
|
|
126
|
-
registerStyles('vaadin-menu-bar-button', [button, menuBarButton], {
|
|
127
|
-
moduleId: 'lumo-menu-bar-button',
|
|
128
|
-
});
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import '@vaadin/vaadin-lumo-styles/sizing.js';
|
|
2
|
-
import '@vaadin/vaadin-lumo-styles/spacing.js';
|
|
3
|
-
import { contextMenuItem } from '@vaadin/context-menu/theme/lumo/vaadin-context-menu-item-styles.js';
|
|
4
|
-
import { item } from '@vaadin/item/theme/lumo/vaadin-item-styles.js';
|
|
5
|
-
import { css, registerStyles } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
6
|
-
|
|
7
|
-
const menuBarItem = css`
|
|
8
|
-
[part='content'] {
|
|
9
|
-
display: flex;
|
|
10
|
-
/* tweak to inherit centering from menu bar button */
|
|
11
|
-
align-items: inherit;
|
|
12
|
-
justify-content: inherit;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
[part='content'] ::slotted(vaadin-icon) {
|
|
16
|
-
display: inline-block;
|
|
17
|
-
width: var(--lumo-icon-size-m);
|
|
18
|
-
height: var(--lumo-icon-size-m);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
[part='content'] ::slotted(vaadin-icon[icon^='vaadin:']) {
|
|
22
|
-
padding: var(--lumo-space-xs);
|
|
23
|
-
box-sizing: border-box !important;
|
|
24
|
-
}
|
|
25
|
-
`;
|
|
26
|
-
|
|
27
|
-
registerStyles('vaadin-menu-bar-item', [item, contextMenuItem, menuBarItem], { moduleId: 'lumo-menu-bar-item' });
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import { contextMenuListBox } from '@vaadin/context-menu/theme/lumo/vaadin-context-menu-list-box-styles.js';
|
|
2
|
-
import { listBox } from '@vaadin/list-box/theme/lumo/vaadin-list-box-styles.js';
|
|
3
|
-
import { registerStyles } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
4
|
-
|
|
5
|
-
registerStyles('vaadin-menu-bar-list-box', [listBox, contextMenuListBox], { moduleId: 'lumo-menu-bar-list-box' });
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { contextMenuOverlay } from '@vaadin/context-menu/theme/lumo/vaadin-context-menu-overlay-styles.js';
|
|
2
|
-
import { menuOverlay } from '@vaadin/vaadin-lumo-styles/mixins/menu-overlay.js';
|
|
3
|
-
import { css, registerStyles } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
4
|
-
|
|
5
|
-
const menuBarOverlay = css`
|
|
6
|
-
:host(:first-of-type) {
|
|
7
|
-
padding-top: var(--lumo-space-xs);
|
|
8
|
-
}
|
|
9
|
-
`;
|
|
10
|
-
|
|
11
|
-
registerStyles('vaadin-menu-bar-overlay', [menuOverlay, contextMenuOverlay, menuBarOverlay], {
|
|
12
|
-
moduleId: 'lumo-menu-bar-overlay',
|
|
13
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import '@vaadin/vaadin-lumo-styles/style.js';
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import '@vaadin/vaadin-lumo-styles/style.js';
|
|
2
|
-
import { css, registerStyles } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
3
|
-
|
|
4
|
-
registerStyles(
|
|
5
|
-
'vaadin-menu-bar',
|
|
6
|
-
css`
|
|
7
|
-
:host([has-single-button]) ::slotted(vaadin-menu-bar-button) {
|
|
8
|
-
border-radius: var(--lumo-border-radius-m);
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
:host([theme~='end-aligned']) ::slotted(vaadin-menu-bar-button[first-visible]),
|
|
12
|
-
:host([theme~='end-aligned'][has-single-button]) ::slotted(vaadin-menu-bar-button) {
|
|
13
|
-
margin-inline-start: auto;
|
|
14
|
-
}
|
|
15
|
-
`,
|
|
16
|
-
{ moduleId: 'lumo-menu-bar' },
|
|
17
|
-
);
|