@vaadin/menu-bar 24.0.0-alpha9 → 24.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vaadin/menu-bar",
3
- "version": "24.0.0-alpha9",
3
+ "version": "24.0.0-beta1",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -37,22 +37,22 @@
37
37
  "dependencies": {
38
38
  "@open-wc/dedupe-mixin": "^1.3.0",
39
39
  "@polymer/polymer": "^3.0.0",
40
- "@vaadin/button": "24.0.0-alpha9",
41
- "@vaadin/component-base": "24.0.0-alpha9",
42
- "@vaadin/context-menu": "24.0.0-alpha9",
43
- "@vaadin/vaadin-lumo-styles": "24.0.0-alpha9",
44
- "@vaadin/vaadin-material-styles": "24.0.0-alpha9",
45
- "@vaadin/vaadin-themable-mixin": "24.0.0-alpha9"
40
+ "@vaadin/button": "24.0.0-beta1",
41
+ "@vaadin/component-base": "24.0.0-beta1",
42
+ "@vaadin/context-menu": "24.0.0-beta1",
43
+ "@vaadin/vaadin-lumo-styles": "24.0.0-beta1",
44
+ "@vaadin/vaadin-material-styles": "24.0.0-beta1",
45
+ "@vaadin/vaadin-themable-mixin": "24.0.0-beta1"
46
46
  },
47
47
  "devDependencies": {
48
48
  "@esm-bundle/chai": "^4.3.4",
49
- "@vaadin/icon": "24.0.0-alpha9",
50
- "@vaadin/testing-helpers": "^0.3.2",
49
+ "@vaadin/icon": "24.0.0-beta1",
50
+ "@vaadin/testing-helpers": "^0.4.0",
51
51
  "sinon": "^13.0.2"
52
52
  },
53
53
  "web-types": [
54
54
  "web-types.json",
55
55
  "web-types.lit.json"
56
56
  ],
57
- "gitHead": "cc3f747164041566b300bde4b105d2475649e93f"
57
+ "gitHead": "c5b48921a62482746df8e46994b37e1490fec27e"
58
58
  }
@@ -17,7 +17,7 @@ registerStyles(
17
17
  margin-inline-end: 0;
18
18
  }
19
19
 
20
- [part='label'] ::slotted(vaadin-context-menu-item) {
20
+ [part='label'] ::slotted(vaadin-menu-bar-item) {
21
21
  position: relative;
22
22
  z-index: 1;
23
23
  }
@@ -0,0 +1,21 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2019 - 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-menu-bar>`. Not intended to be used separately.
12
+ */
13
+ declare class MenuBarItem extends ItemMixin(DirMixin(ThemableMixin(HTMLElement))) {}
14
+
15
+ declare global {
16
+ interface HTMLElementTagNameMap {
17
+ 'vaadin-menu-bar-item': MenuBarItem;
18
+ }
19
+ }
20
+
21
+ export { MenuBarItem };
@@ -0,0 +1,55 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2019 - 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-menu-bar>`. Not intended to be used separately.
13
+ *
14
+ * @extends HTMLElement
15
+ * @mixes DirMixin
16
+ * @mixes ItemMixin
17
+ * @mixes ThemableMixin
18
+ * @protected
19
+ */
20
+ class MenuBarItem extends ItemMixin(ThemableMixin(DirMixin(PolymerElement))) {
21
+ static get is() {
22
+ return 'vaadin-menu-bar-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
+ connectedCallback() {
45
+ super.connectedCallback();
46
+
47
+ // Set role in `connectedCallback()` instead of `ready()`
48
+ // because the role is removed when teleporting to button.
49
+ this.setAttribute('role', 'menuitem');
50
+ }
51
+ }
52
+
53
+ customElements.define(MenuBarItem.is, MenuBarItem);
54
+
55
+ export { MenuBarItem };
@@ -0,0 +1,22 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2019 - 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-menu-bar>`. Not intended to be used separately.
13
+ */
14
+ declare class MenuBarListBox extends ListMixin(DirMixin(ThemableMixin(ControllerMixin(HTMLElement)))) {}
15
+
16
+ declare global {
17
+ interface HTMLElementTagNameMap {
18
+ 'vaadin-menu-bar-list-box': MenuBarListBox;
19
+ }
20
+ }
21
+
22
+ export { MenuBarListBox };
@@ -0,0 +1,81 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2019 - 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-menu-bar>`. 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 MenuBarListBox extends ListMixin(ThemableMixin(DirMixin(ControllerMixin(PolymerElement)))) {
23
+ static get is() {
24
+ return 'vaadin-menu-bar-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(MenuBarListBox.is, MenuBarListBox);
80
+
81
+ export { MenuBarListBox };
@@ -4,22 +4,34 @@
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
  import type { Constructor } from '@open-wc/dedupe-mixin';
7
+ import type { ControllerMixinClass } from '@vaadin/component-base/src/controller-mixin.js';
7
8
  import type { FocusMixinClass } from '@vaadin/component-base/src/focus-mixin.js';
8
9
  import type { KeyboardDirectionMixinClass } from '@vaadin/component-base/src/keyboard-direction-mixin.js';
9
10
  import type { KeyboardMixinClass } from '@vaadin/component-base/src/keyboard-mixin.js';
11
+ import type { ResizeMixinClass } from '@vaadin/component-base/src/resize-mixin.js';
10
12
 
11
- export declare function InteractionsMixin<T extends Constructor<HTMLElement>>(
13
+ export declare function MenuBarMixin<T extends Constructor<HTMLElement>>(
12
14
  base: T,
13
- ): Constructor<FocusMixinClass> &
14
- Constructor<InteractionsMixinClass> &
15
+ ): Constructor<ControllerMixinClass> &
16
+ Constructor<FocusMixinClass> &
15
17
  Constructor<KeyboardDirectionMixinClass> &
16
18
  Constructor<KeyboardMixinClass> &
19
+ Constructor<MenuBarMixinClass> &
20
+ Constructor<ResizeMixinClass> &
17
21
  T;
18
22
 
19
- export declare class InteractionsMixinClass {
23
+ export declare class MenuBarMixinClass {
20
24
  /**
21
25
  * If true, the submenu will open on hover (mouseover) instead of click.
22
26
  * @attr {boolean} open-on-hover
23
27
  */
24
28
  openOnHover: boolean | null | undefined;
29
+
30
+ protected readonly _buttons: HTMLElement[];
31
+
32
+ protected readonly _container: HTMLElement;
33
+
34
+ protected readonly _overflow: HTMLElement;
35
+
36
+ protected _hasOverflow: boolean;
25
37
  }
@@ -3,17 +3,22 @@
3
3
  * Copyright (c) 2019 - 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 { ControllerMixin } from '@vaadin/component-base/src/controller-mixin.js';
6
7
  import { FocusMixin } from '@vaadin/component-base/src/focus-mixin.js';
7
8
  import { isElementFocused, isKeyboardActive } from '@vaadin/component-base/src/focus-utils.js';
8
9
  import { KeyboardDirectionMixin } from '@vaadin/component-base/src/keyboard-direction-mixin.js';
10
+ import { ResizeMixin } from '@vaadin/component-base/src/resize-mixin.js';
11
+ import { SlotController } from '@vaadin/component-base/src/slot-controller.js';
9
12
 
10
13
  /**
11
14
  * @polymerMixin
15
+ * @mixes ControllerMixin
12
16
  * @mixes FocusMixin
13
- * @mixes KeyboardDirectionMixinClass
17
+ * @mixes KeyboardDirectionMixin
18
+ * @mixes ResizeMixin
14
19
  */
15
- export const InteractionsMixin = (superClass) =>
16
- class InteractionsMixin extends KeyboardDirectionMixin(FocusMixin(superClass)) {
20
+ export const MenuBarMixin = (superClass) =>
21
+ class MenuBarMixinClass extends KeyboardDirectionMixin(ResizeMixin(FocusMixin(ControllerMixin(superClass)))) {
17
22
  static get properties() {
18
23
  return {
19
24
  /**
@@ -23,34 +28,40 @@ export const InteractionsMixin = (superClass) =>
23
28
  openOnHover: {
24
29
  type: Boolean,
25
30
  },
26
- };
27
- }
28
31
 
29
- constructor() {
30
- super();
31
- this.__boundOnContextMenuKeydown = this.__onContextMenuKeydown.bind(this);
32
+ /**
33
+ * @type {boolean}
34
+ * @protected
35
+ */
36
+ _hasOverflow: {
37
+ type: Boolean,
38
+ value: false,
39
+ },
40
+
41
+ /** @protected */
42
+ _overflow: {
43
+ type: Object,
44
+ },
45
+
46
+ /** @protected */
47
+ _container: {
48
+ type: Object,
49
+ },
50
+ };
32
51
  }
33
52
 
34
53
  static get observers() {
35
- return ['_itemsChanged(items, items.splices)'];
54
+ return [
55
+ '_itemsChanged(items, items.splices)',
56
+ '__hasOverflowChanged(_hasOverflow, _overflow)',
57
+ '__i18nChanged(i18n, _overflow)',
58
+ '_menuItemsChanged(items, _overflow, _container, items.splices)',
59
+ ];
36
60
  }
37
61
 
38
- /** @protected */
39
- ready() {
40
- super.ready();
41
-
42
- this.addEventListener('mousedown', () => this._hideTooltip());
43
- this.addEventListener('mouseleave', () => this._hideTooltip());
44
-
45
- this._subMenu.addEventListener('item-selected', this.__onItemSelected.bind(this));
46
- this._subMenu.addEventListener('close-all-menus', this.__onEscapeClose.bind(this));
47
-
48
- const overlay = this._subMenu.$.overlay;
49
- overlay.addEventListener('keydown', this.__boundOnContextMenuKeydown);
50
-
51
- const container = this._container;
52
- container.addEventListener('click', this.__onButtonClick.bind(this));
53
- container.addEventListener('mouseover', (e) => this._onMouseOver(e));
62
+ constructor() {
63
+ super();
64
+ this.__boundOnContextMenuKeydown = this.__onContextMenuKeydown.bind(this);
54
65
  }
55
66
 
56
67
  /**
@@ -77,6 +88,66 @@ export const InteractionsMixin = (superClass) =>
77
88
  return false;
78
89
  }
79
90
 
91
+ /**
92
+ * Override getter from `ResizeMixin` to observe parent.
93
+ *
94
+ * @protected
95
+ * @override
96
+ */
97
+ get _observeParent() {
98
+ return true;
99
+ }
100
+
101
+ /**
102
+ * @return {!Array<!HTMLElement>}
103
+ * @protected
104
+ */
105
+ get _buttons() {
106
+ return Array.from(this.querySelectorAll('vaadin-menu-bar-button'));
107
+ }
108
+
109
+ /** @private */
110
+ get _subMenu() {
111
+ return this.shadowRoot.querySelector('vaadin-menu-bar-submenu');
112
+ }
113
+
114
+ /** @protected */
115
+ ready() {
116
+ super.ready();
117
+
118
+ this.setAttribute('role', 'menubar');
119
+
120
+ this._overflowController = new SlotController(this, 'overflow', 'vaadin-menu-bar-button', {
121
+ initializer: (btn) => {
122
+ btn.setAttribute('hidden', '');
123
+
124
+ const dots = document.createElement('div');
125
+ dots.setAttribute('aria-hidden', 'true');
126
+ dots.innerHTML = '&centerdot;'.repeat(3);
127
+ btn.appendChild(dots);
128
+
129
+ this._overflow = btn;
130
+ this._initButtonAttrs(btn);
131
+ },
132
+ });
133
+ this.addController(this._overflowController);
134
+
135
+ this.addEventListener('mousedown', () => this._hideTooltip());
136
+ this.addEventListener('mouseleave', () => this._hideTooltip());
137
+
138
+ this._subMenu.addEventListener('item-selected', this.__onItemSelected.bind(this));
139
+ this._subMenu.addEventListener('close-all-menus', this.__onEscapeClose.bind(this));
140
+
141
+ const overlay = this._subMenu.$.overlay;
142
+ overlay.addEventListener('keydown', this.__boundOnContextMenuKeydown);
143
+
144
+ const container = this.shadowRoot.querySelector('[part="container"]');
145
+ container.addEventListener('click', this.__onButtonClick.bind(this));
146
+ container.addEventListener('mouseover', (e) => this._onMouseOver(e));
147
+
148
+ this._container = container;
149
+ }
150
+
80
151
  /**
81
152
  * Override method inherited from `KeyboardDirectionMixin`
82
153
  * to use the list of menu-bar buttons as items.
@@ -95,6 +166,232 @@ export const InteractionsMixin = (superClass) =>
95
166
  this._hideTooltip(true);
96
167
  }
97
168
 
169
+ /**
170
+ * Implement callback from `ResizeMixin` to update buttons
171
+ * and detect whether to show or hide the overflow button.
172
+ *
173
+ * @protected
174
+ * @override
175
+ */
176
+ _onResize() {
177
+ this.__detectOverflow();
178
+ }
179
+
180
+ /** @private */
181
+ __hasOverflowChanged(hasOverflow, overflow) {
182
+ if (overflow) {
183
+ overflow.toggleAttribute('hidden', !hasOverflow);
184
+ }
185
+ }
186
+
187
+ /** @private */
188
+ _menuItemsChanged(items, overflow, container) {
189
+ if (!overflow || !container) {
190
+ return;
191
+ }
192
+
193
+ if (items !== this._oldItems) {
194
+ this._oldItems = items;
195
+ this.__renderButtons(items);
196
+ }
197
+ }
198
+
199
+ /** @private */
200
+ __i18nChanged(i18n, overflow) {
201
+ if (overflow && i18n && i18n.moreOptions !== undefined) {
202
+ if (i18n.moreOptions) {
203
+ overflow.setAttribute('aria-label', i18n.moreOptions);
204
+ } else {
205
+ overflow.removeAttribute('aria-label');
206
+ }
207
+ }
208
+ }
209
+
210
+ /** @private */
211
+ __getOverflowCount(overflow) {
212
+ // We can't use optional chaining due to webpack 4
213
+ return (overflow.item && overflow.item.children && overflow.item.children.length) || 0;
214
+ }
215
+
216
+ /** @private */
217
+ __restoreButtons(buttons) {
218
+ buttons.forEach((button) => {
219
+ button.disabled = (button.item && button.item.disabled) || this.disabled;
220
+ button.style.visibility = '';
221
+ button.style.position = '';
222
+
223
+ // Teleport item component back from "overflow" sub-menu
224
+ const item = button.item && button.item.component;
225
+ if (item instanceof HTMLElement && item.getAttribute('role') === 'menuitem') {
226
+ button.appendChild(item);
227
+ item.removeAttribute('role');
228
+ }
229
+ });
230
+ this.__updateOverflow([]);
231
+ }
232
+
233
+ /** @private */
234
+ __updateOverflow(items) {
235
+ this._overflow.item = { children: items };
236
+ this._hasOverflow = items.length > 0;
237
+ }
238
+
239
+ /** @private */
240
+ __setOverflowItems(buttons, overflow) {
241
+ const container = this._container;
242
+
243
+ if (container.offsetWidth < container.scrollWidth) {
244
+ this._hasOverflow = true;
245
+
246
+ const isRTL = this.__isRTL;
247
+
248
+ let i;
249
+ for (i = buttons.length; i > 0; i--) {
250
+ const btn = buttons[i - 1];
251
+ const btnStyle = getComputedStyle(btn);
252
+
253
+ // If this button isn't overflowing, then the rest aren't either
254
+ if (
255
+ (!isRTL && btn.offsetLeft + btn.offsetWidth < container.offsetWidth - overflow.offsetWidth) ||
256
+ (isRTL && btn.offsetLeft >= overflow.offsetWidth)
257
+ ) {
258
+ break;
259
+ }
260
+
261
+ btn.disabled = true;
262
+ btn.style.visibility = 'hidden';
263
+ btn.style.position = 'absolute';
264
+ // Save width for buttons with component
265
+ btn.style.width = btnStyle.width;
266
+ }
267
+ const items = buttons.filter((_, idx) => idx >= i).map((b) => b.item);
268
+ this.__updateOverflow(items);
269
+ }
270
+ }
271
+
272
+ /** @private */
273
+ __detectOverflow() {
274
+ const overflow = this._overflow;
275
+ const buttons = this._buttons.filter((btn) => btn !== overflow);
276
+ const oldOverflowCount = this.__getOverflowCount(overflow);
277
+
278
+ // Reset all buttons in the menu bar and the overflow button
279
+ this.__restoreButtons(buttons);
280
+
281
+ // Hide any overflowing buttons and put them in the 'overflow' button
282
+ this.__setOverflowItems(buttons, overflow);
283
+
284
+ const newOverflowCount = this.__getOverflowCount(overflow);
285
+ if (oldOverflowCount !== newOverflowCount && this._subMenu.opened) {
286
+ this._subMenu.close();
287
+ }
288
+
289
+ const isSingleButton = newOverflowCount === buttons.length || (newOverflowCount === 0 && buttons.length === 1);
290
+ this.toggleAttribute('has-single-button', isSingleButton);
291
+ }
292
+
293
+ /** @protected */
294
+ _removeButtons() {
295
+ this._buttons.forEach((button) => {
296
+ if (button !== this._overflow) {
297
+ this.removeChild(button);
298
+ }
299
+ });
300
+ }
301
+
302
+ /** @protected */
303
+ _initButton(item) {
304
+ const button = document.createElement('vaadin-menu-bar-button');
305
+
306
+ const itemCopy = { ...item };
307
+ button.item = itemCopy;
308
+
309
+ if (item.component) {
310
+ const component = this.__getComponent(itemCopy);
311
+ itemCopy.component = component;
312
+ // Save item for overflow menu
313
+ component.item = itemCopy;
314
+ button.appendChild(component);
315
+ } else if (item.text) {
316
+ button.textContent = item.text;
317
+ }
318
+
319
+ return button;
320
+ }
321
+
322
+ /** @protected */
323
+ _initButtonAttrs(button) {
324
+ button.setAttribute('role', 'menuitem');
325
+
326
+ if (button === this._overflow || (button.item && button.item.children)) {
327
+ button.setAttribute('aria-haspopup', 'true');
328
+ button.setAttribute('aria-expanded', 'false');
329
+ }
330
+ }
331
+
332
+ /** @protected */
333
+ _setButtonDisabled(button, disabled) {
334
+ button.disabled = disabled;
335
+ button.setAttribute('tabindex', disabled ? '-1' : '0');
336
+ }
337
+
338
+ /** @protected */
339
+ _setButtonTheme(btn, hostTheme) {
340
+ let theme = hostTheme;
341
+
342
+ // Item theme takes precedence over host theme even if it's empty, as long as it's not undefined or null
343
+ const itemTheme = btn.item && btn.item.theme;
344
+ if (itemTheme != null) {
345
+ theme = Array.isArray(itemTheme) ? itemTheme.join(' ') : itemTheme;
346
+ }
347
+
348
+ if (theme) {
349
+ btn.setAttribute('theme', theme);
350
+ } else {
351
+ btn.removeAttribute('theme');
352
+ }
353
+ }
354
+
355
+ /** @private */
356
+ __getComponent(item) {
357
+ const itemComponent = item.component;
358
+ let component;
359
+
360
+ const isElement = itemComponent instanceof HTMLElement;
361
+ // Use existing item component, if any
362
+ if (isElement && itemComponent.localName === 'vaadin-menu-bar-item') {
363
+ component = itemComponent;
364
+ } else {
365
+ component = document.createElement('vaadin-menu-bar-item');
366
+ component.appendChild(isElement ? itemComponent : document.createElement(itemComponent));
367
+ }
368
+ if (item.text) {
369
+ const node = component.firstChild || component;
370
+ node.textContent = item.text;
371
+ }
372
+ return component;
373
+ }
374
+
375
+ /** @private */
376
+ __renderButtons(items = []) {
377
+ this._removeButtons();
378
+
379
+ /* Empty array, do nothing */
380
+ if (items.length === 0) {
381
+ return;
382
+ }
383
+
384
+ items.forEach((item) => {
385
+ const button = this._initButton(item);
386
+ this.insertBefore(button, this._overflow);
387
+ this._setButtonDisabled(button, item.disabled);
388
+ this._initButtonAttrs(button);
389
+ this._setButtonTheme(button, this._theme);
390
+ });
391
+
392
+ this.__detectOverflow();
393
+ }
394
+
98
395
  /**
99
396
  * @param {HTMLElement} button
100
397
  * @protected
@@ -273,11 +570,6 @@ export const InteractionsMixin = (superClass) =>
273
570
  }
274
571
  }
275
572
 
276
- /** @private */
277
- get _subMenu() {
278
- return this.shadowRoot.querySelector('vaadin-menu-bar-submenu');
279
- }
280
-
281
573
  /** @private */
282
574
  _itemsChanged() {
283
575
  const subMenu = this._subMenu;
@@ -0,0 +1,20 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2019 - 2023 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+ import { MenuOverlayMixin } from '@vaadin/context-menu/src/vaadin-menu-overlay-mixin.js';
7
+ import { Overlay } from '@vaadin/overlay/src/vaadin-overlay.js';
8
+
9
+ /**
10
+ * An element used internally by `<vaadin-menu-bar>`. Not intended to be used separately.
11
+ */
12
+ declare class MenuBarOverlay extends MenuOverlayMixin(Overlay) {}
13
+
14
+ declare global {
15
+ interface HTMLElementTagNameMap {
16
+ 'vaadin-menu-bar-overlay': MenuBarOverlay;
17
+ }
18
+ }
19
+
20
+ export { MenuBarOverlay };