@vaadin/select 24.8.4 → 25.0.0-alpha10

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.
Files changed (35) hide show
  1. package/README.md +0 -29
  2. package/package.json +19 -20
  3. package/src/styles/vaadin-select-base-styles.js +38 -0
  4. package/{theme/material/vaadin-lit-select.d.ts → src/styles/vaadin-select-core-styles.d.ts} +3 -2
  5. package/src/{vaadin-select-core-styles.js → styles/vaadin-select-core-styles.js} +4 -0
  6. package/src/styles/vaadin-select-overlay-base-styles.js +21 -0
  7. package/src/{vaadin-select-overlay-core-styles.js → styles/vaadin-select-overlay-core-styles.js} +1 -1
  8. package/src/styles/vaadin-select-value-button-base-styles.js +30 -0
  9. package/src/vaadin-select-base-mixin.js +31 -29
  10. package/src/vaadin-select-item.js +30 -14
  11. package/src/vaadin-select-list-box.d.ts +1 -2
  12. package/src/vaadin-select-list-box.js +17 -14
  13. package/src/vaadin-select-overlay-mixin.js +31 -12
  14. package/src/vaadin-select-overlay.js +24 -12
  15. package/src/vaadin-select-value-button.js +12 -7
  16. package/src/vaadin-select.d.ts +14 -11
  17. package/src/vaadin-select.js +52 -73
  18. package/web-types.json +2 -2
  19. package/web-types.lit.json +2 -2
  20. package/src/vaadin-lit-select-item.js +0 -63
  21. package/src/vaadin-lit-select-list-box.js +0 -71
  22. package/src/vaadin-lit-select-overlay.js +0 -53
  23. package/src/vaadin-lit-select-value-button.js +0 -42
  24. package/src/vaadin-lit-select.js +0 -109
  25. package/theme/lumo/vaadin-lit-select.d.ts +0 -7
  26. package/theme/lumo/vaadin-lit-select.js +0 -7
  27. package/theme/material/vaadin-lit-select.js +0 -7
  28. package/theme/material/vaadin-select-styles.d.ts +0 -7
  29. package/theme/material/vaadin-select-styles.js +0 -77
  30. package/theme/material/vaadin-select.d.ts +0 -7
  31. package/theme/material/vaadin-select.js +0 -7
  32. package/vaadin-lit-select.d.ts +0 -1
  33. package/vaadin-lit-select.js +0 -2
  34. /package/src/{vaadin-select-core-styles.d.ts → styles/vaadin-select-base-styles.d.ts} +0 -0
  35. /package/src/{vaadin-select-value-button-core-styles.js → styles/vaadin-select-value-button-core-styles.js} +0 -0
package/README.md CHANGED
@@ -39,35 +39,6 @@ Install the component:
39
39
  npm i @vaadin/select
40
40
  ```
41
41
 
42
- Once installed, import the component in your application:
43
-
44
- ```js
45
- import '@vaadin/select';
46
- ```
47
-
48
- ## Themes
49
-
50
- Vaadin components come with two built-in [themes](https://vaadin.com/docs/latest/styling), Lumo and Material.
51
- The [main entrypoint](https://github.com/vaadin/web-components/blob/main/packages/select/vaadin-select.js) of the package uses the Lumo theme.
52
-
53
- To use the Material theme, import the component from the `theme/material` folder:
54
-
55
- ```js
56
- import '@vaadin/select/theme/material/vaadin-select.js';
57
- ```
58
-
59
- You can also import the Lumo version of the component explicitly:
60
-
61
- ```js
62
- import '@vaadin/select/theme/lumo/vaadin-select.js';
63
- ```
64
-
65
- Finally, you can import the un-themed component from the `src` folder to get a minimal starting point:
66
-
67
- ```js
68
- import '@vaadin/select/src/vaadin-select.js';
69
- ```
70
-
71
42
  ## Contributing
72
43
 
73
44
  Read the [contributing guide](https://vaadin.com/docs/latest/contributing) to learn about our development process, how to propose bugfixes and improvements, and how to test your changes to Vaadin components.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vaadin/select",
3
- "version": "24.8.4",
3
+ "version": "25.0.0-alpha10",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -23,6 +23,8 @@
23
23
  "lit.d.ts",
24
24
  "lit.js",
25
25
  "src",
26
+ "!src/styles/*-base-styles.d.ts",
27
+ "!src/styles/*-base-styles.js",
26
28
  "theme",
27
29
  "vaadin-*.d.ts",
28
30
  "vaadin-*.js",
@@ -33,35 +35,32 @@
33
35
  "Vaadin",
34
36
  "vaadin-select",
35
37
  "web-components",
36
- "web-component",
37
- "polymer"
38
+ "web-component"
38
39
  ],
39
40
  "dependencies": {
40
41
  "@open-wc/dedupe-mixin": "^1.3.0",
41
- "@polymer/polymer": "^3.2.0",
42
- "@vaadin/a11y-base": "~24.8.4",
43
- "@vaadin/button": "~24.8.4",
44
- "@vaadin/component-base": "~24.8.4",
45
- "@vaadin/field-base": "~24.8.4",
46
- "@vaadin/input-container": "~24.8.4",
47
- "@vaadin/item": "~24.8.4",
48
- "@vaadin/list-box": "~24.8.4",
49
- "@vaadin/lit-renderer": "~24.8.4",
50
- "@vaadin/overlay": "~24.8.4",
51
- "@vaadin/vaadin-lumo-styles": "~24.8.4",
52
- "@vaadin/vaadin-material-styles": "~24.8.4",
53
- "@vaadin/vaadin-themable-mixin": "~24.8.4",
42
+ "@vaadin/a11y-base": "25.0.0-alpha10",
43
+ "@vaadin/button": "25.0.0-alpha10",
44
+ "@vaadin/component-base": "25.0.0-alpha10",
45
+ "@vaadin/field-base": "25.0.0-alpha10",
46
+ "@vaadin/input-container": "25.0.0-alpha10",
47
+ "@vaadin/item": "25.0.0-alpha10",
48
+ "@vaadin/list-box": "25.0.0-alpha10",
49
+ "@vaadin/lit-renderer": "25.0.0-alpha10",
50
+ "@vaadin/overlay": "25.0.0-alpha10",
51
+ "@vaadin/vaadin-lumo-styles": "25.0.0-alpha10",
52
+ "@vaadin/vaadin-themable-mixin": "25.0.0-alpha10",
54
53
  "lit": "^3.0.0"
55
54
  },
56
55
  "devDependencies": {
57
- "@vaadin/chai-plugins": "~24.8.4",
58
- "@vaadin/test-runner-commands": "~24.8.4",
59
- "@vaadin/testing-helpers": "^1.1.0",
56
+ "@vaadin/chai-plugins": "25.0.0-alpha10",
57
+ "@vaadin/test-runner-commands": "25.0.0-alpha10",
58
+ "@vaadin/testing-helpers": "^2.0.0",
60
59
  "sinon": "^18.0.0"
61
60
  },
62
61
  "web-types": [
63
62
  "web-types.json",
64
63
  "web-types.lit.json"
65
64
  ],
66
- "gitHead": "849e54e967563080a685965e2dced02060b3ab23"
65
+ "gitHead": "6cc6c94079e805fa5b2f0af4dbf3b2a7485e57d0"
67
66
  }
@@ -0,0 +1,38 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2017 - 2025 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+ import '@vaadin/component-base/src/style-props.js';
7
+ import { css } from 'lit';
8
+
9
+ export const selectStyles = css`
10
+ :host {
11
+ position: relative;
12
+ }
13
+
14
+ ::slotted([slot='value']) {
15
+ flex: 1;
16
+ }
17
+
18
+ ::slotted(div[slot='overlay']) {
19
+ display: contents;
20
+ }
21
+
22
+ :host(:not([focus-ring])) [part='input-field'] {
23
+ outline: none;
24
+ }
25
+
26
+ :host([readonly]:not([focus-ring])) [part='input-field'] {
27
+ --vaadin-input-field-border-color: inherit;
28
+ }
29
+
30
+ [part='input-field'],
31
+ :host(:not([readonly])) ::slotted([slot='value']) {
32
+ cursor: var(--vaadin-clickable-cursor);
33
+ }
34
+
35
+ [part='toggle-button']::before {
36
+ mask-image: var(--_vaadin-icon-chevron-down);
37
+ }
38
+ `;
@@ -3,5 +3,6 @@
3
3
  * Copyright (c) 2017 - 2025 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
- import './vaadin-select-styles.js';
7
- import '../../src/vaadin-lit-select.js';
6
+ import type { CSSResult } from 'lit';
7
+
8
+ export const selectStyles: CSSResult;
@@ -13,4 +13,8 @@ export const selectStyles = css`
13
13
  ::slotted([slot='value']) {
14
14
  flex-grow: 1;
15
15
  }
16
+
17
+ ::slotted(div[slot='overlay']) {
18
+ display: contents;
19
+ }
16
20
  `;
@@ -0,0 +1,21 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2017 - 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 selectOverlayStyles = css`
9
+ :host {
10
+ align-items: flex-start;
11
+ justify-content: flex-start;
12
+ }
13
+
14
+ :host(:not([phone])) [part='overlay'] {
15
+ min-width: var(--vaadin-select-overlay-width, var(--_vaadin-select-overlay-default-width));
16
+ }
17
+
18
+ [part='content'] {
19
+ padding: var(--vaadin-item-overlay-padding, 4px);
20
+ }
21
+ `;
@@ -12,7 +12,7 @@ export const selectOverlayStyles = css`
12
12
  }
13
13
 
14
14
  :host(:not([phone])) [part='overlay'] {
15
- min-width: var(--vaadin-select-overlay-width, var(--vaadin-select-text-field-width));
15
+ min-width: var(--vaadin-select-overlay-width, var(--_vaadin-select-overlay-default-width));
16
16
  }
17
17
 
18
18
  @media (forced-colors: active) {
@@ -0,0 +1,30 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2017 - 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 valueButton = css`
9
+ :host {
10
+ min-height: 1lh;
11
+ outline: none;
12
+ overflow: hidden;
13
+ white-space: nowrap;
14
+ width: 100%;
15
+ }
16
+
17
+ ::slotted(*) {
18
+ padding: 0;
19
+ cursor: inherit;
20
+ }
21
+
22
+ .vaadin-button-container,
23
+ [part='label'] {
24
+ display: contents;
25
+ }
26
+
27
+ :host([disabled]) {
28
+ pointer-events: none;
29
+ }
30
+ `;
@@ -63,6 +63,7 @@ export const SelectBaseMixin = (superClass) =>
63
63
  type: Boolean,
64
64
  value: false,
65
65
  notify: true,
66
+ observer: '_openedChanged',
66
67
  reflectToAttribute: true,
67
68
  sync: true,
68
69
  },
@@ -160,11 +161,7 @@ export const SelectBaseMixin = (superClass) =>
160
161
  }
161
162
 
162
163
  static get observers() {
163
- return [
164
- '_updateAriaExpanded(opened, focusElement)',
165
- '_updateSelectedItem(value, _items, placeholder)',
166
- '_openedChanged(opened, _overlayElement)',
167
- ];
164
+ return ['_updateAriaExpanded(opened, focusElement)', '_updateSelectedItem(value, _items, placeholder)'];
168
165
  }
169
166
 
170
167
  constructor() {
@@ -207,6 +204,15 @@ export const SelectBaseMixin = (superClass) =>
207
204
  this.addController(this._tooltipController);
208
205
  }
209
206
 
207
+ /** @protected */
208
+ updated(props) {
209
+ super.updated(props);
210
+
211
+ if (props.has('_phone')) {
212
+ this.toggleAttribute('phone', this._phone);
213
+ }
214
+ }
215
+
210
216
  /**
211
217
  * Requests an update for the content of the select.
212
218
  * While performing the update, it invokes the renderer passed in the `renderer` property.
@@ -219,10 +225,6 @@ export const SelectBaseMixin = (superClass) =>
219
225
  }
220
226
 
221
227
  this._overlayElement.requestContentUpdate();
222
-
223
- if (this._menuElement && this._menuElement.items) {
224
- this._updateSelectedItem(this.value, this._menuElement.items);
225
- }
226
228
  }
227
229
 
228
230
  /**
@@ -283,6 +285,12 @@ export const SelectBaseMixin = (superClass) =>
283
285
  // Store the menu element reference
284
286
  this.__lastMenuElement = menuElement;
285
287
  }
288
+
289
+ // When the renderer was re-assigned so that menu element is preserved
290
+ // but its items have changed, make sure selected property is updated.
291
+ if (this._menuElement && this._menuElement.items) {
292
+ this._updateSelectedItem(this.value, this._menuElement.items);
293
+ }
286
294
  }
287
295
 
288
296
  /** @private */
@@ -364,17 +372,21 @@ export const SelectBaseMixin = (superClass) =>
364
372
  * @protected
365
373
  */
366
374
  _onKeyDownInside(e) {
367
- if (/^(Tab)$/u.test(e.key)) {
375
+ if (e.key === 'Tab') {
376
+ // Temporarily set tabindex to prevent moving focus
377
+ // to the value button element on item Shift + Tab
378
+ this.focusElement.setAttribute('tabindex', '-1');
379
+ this._overlayElement.restoreFocusOnClose = false;
368
380
  this.opened = false;
381
+ setTimeout(() => {
382
+ this.focusElement.setAttribute('tabindex', '0');
383
+ this._overlayElement.restoreFocusOnClose = true;
384
+ });
369
385
  }
370
386
  }
371
387
 
372
388
  /** @private */
373
- _openedChanged(opened, overlayElement) {
374
- if (!overlayElement) {
375
- return;
376
- }
377
-
389
+ _openedChanged(opened, oldOpened) {
378
390
  if (opened) {
379
391
  if (this.disabled || this.readonly) {
380
392
  // Disallow programmatic opening when disabled or readonly
@@ -385,8 +397,6 @@ export const SelectBaseMixin = (superClass) =>
385
397
  // Avoid multiple announcements when a value gets selected from the dropdown
386
398
  this._updateAriaLive(false);
387
399
 
388
- overlayElement.style.setProperty('--vaadin-select-text-field-width', `${this._inputContainer.offsetWidth}px`);
389
-
390
400
  // Preserve focus-ring to restore it later
391
401
  const hasFocusRing = this.hasAttribute('focus-ring');
392
402
  this._openedWithFocusRing = hasFocusRing;
@@ -395,7 +405,7 @@ export const SelectBaseMixin = (superClass) =>
395
405
  if (hasFocusRing) {
396
406
  this.removeAttribute('focus-ring');
397
407
  }
398
- } else if (this.__oldOpened) {
408
+ } else if (oldOpened) {
399
409
  if (this._openedWithFocusRing) {
400
410
  this.setAttribute('focus-ring', '');
401
411
  }
@@ -407,8 +417,6 @@ export const SelectBaseMixin = (superClass) =>
407
417
  this._requestValidation();
408
418
  }
409
419
  }
410
-
411
- this.__oldOpened = opened;
412
420
  }
413
421
 
414
422
  /** @private */
@@ -596,8 +604,8 @@ export const SelectBaseMixin = (superClass) =>
596
604
  * @protected
597
605
  * @override
598
606
  */
599
- _shouldRemoveFocus() {
600
- return !this.opened;
607
+ _shouldRemoveFocus(event) {
608
+ return !this.contains(event.relatedTarget);
601
609
  }
602
610
 
603
611
  /**
@@ -650,13 +658,7 @@ export const SelectBaseMixin = (superClass) =>
650
658
  }
651
659
 
652
660
  /** @private */
653
- async __dispatchChange() {
654
- // Wait for the update complete to guarantee that value-changed is fired
655
- // before validated and change events when using the Lit version of the component.
656
- if (this.updateComplete) {
657
- await this.updateComplete;
658
- }
659
-
661
+ __dispatchChange() {
660
662
  this._requestValidation();
661
663
  this.dispatchEvent(new CustomEvent('change', { bubbles: true }));
662
664
  this.__dispatchChangePending = false;
@@ -3,14 +3,14 @@
3
3
  * Copyright (c) 2017 - 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 { html, PolymerElement } from '@polymer/polymer/polymer-element.js';
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
- import { itemStyles } from '@vaadin/item/src/vaadin-item-core-styles.js';
9
+ import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
10
+ import { itemStyles } from '@vaadin/item/src/styles/vaadin-item-core-styles.js';
10
11
  import { ItemMixin } from '@vaadin/item/src/vaadin-item-mixin.js';
11
- import { registerStyles, ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
12
-
13
- registerStyles('vaadin-select-item', itemStyles, { moduleId: 'vaadin-select-item-styles' });
12
+ import { LumoInjectionMixin } from '@vaadin/vaadin-themable-mixin/lumo-injection-mixin.js';
13
+ import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
14
14
 
15
15
  /**
16
16
  * An element used internally by `<vaadin-select>`. Not intended to be used separately.
@@ -22,12 +22,35 @@ registerStyles('vaadin-select-item', itemStyles, { moduleId: 'vaadin-select-item
22
22
  * @mixes ThemableMixin
23
23
  * @protected
24
24
  */
25
- class SelectItem extends ItemMixin(ThemableMixin(DirMixin(PolymerElement))) {
25
+ class SelectItem extends ItemMixin(ThemableMixin(DirMixin(PolylitMixin(LumoInjectionMixin(LitElement))))) {
26
26
  static get is() {
27
27
  return 'vaadin-select-item';
28
28
  }
29
29
 
30
- static get template() {
30
+ static get styles() {
31
+ return itemStyles;
32
+ }
33
+
34
+ static get properties() {
35
+ return {
36
+ /**
37
+ * Use property instead of setting an attribute in `ready()`
38
+ * for cloning the selected item attached to the value button:
39
+ * in this case, `role` attribute is removed synchronously, and
40
+ * using `ready()` would incorrectly restore the attribute.
41
+ *
42
+ * @protected
43
+ */
44
+ role: {
45
+ type: String,
46
+ value: 'option',
47
+ reflectToAttribute: true,
48
+ },
49
+ };
50
+ }
51
+
52
+ /** @protected */
53
+ render() {
31
54
  return html`
32
55
  <span part="checkmark" aria-hidden="true"></span>
33
56
  <div part="content">
@@ -35,13 +58,6 @@ class SelectItem extends ItemMixin(ThemableMixin(DirMixin(PolymerElement))) {
35
58
  </div>
36
59
  `;
37
60
  }
38
-
39
- /** @protected */
40
- ready() {
41
- super.ready();
42
-
43
- this.setAttribute('role', 'option');
44
- }
45
61
  }
46
62
 
47
63
  defineCustomElement(SelectItem);
@@ -4,14 +4,13 @@
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
  import { ListMixin } from '@vaadin/a11y-base/src/list-mixin.js';
7
- import { ControllerMixin } from '@vaadin/component-base/src/controller-mixin.js';
8
7
  import { DirMixin } from '@vaadin/component-base/src/dir-mixin.js';
9
8
  import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
10
9
 
11
10
  /**
12
11
  * An element used internally by `<vaadin-select>`. Not intended to be used separately.
13
12
  */
14
- declare class SelectListBox extends ListMixin(DirMixin(ThemableMixin(ControllerMixin(HTMLElement)))) {}
13
+ declare class SelectListBox extends ListMixin(DirMixin(ThemableMixin(HTMLElement))) {}
15
14
 
16
15
  declare global {
17
16
  interface HTMLElementTagNameMap {
@@ -3,38 +3,32 @@
3
3
  * Copyright (c) 2017 - 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 { html, PolymerElement } from '@polymer/polymer/polymer-element.js';
6
+ import { html, LitElement } from 'lit';
7
7
  import { ListMixin } from '@vaadin/a11y-base/src/list-mixin.js';
8
- import { ControllerMixin } from '@vaadin/component-base/src/controller-mixin.js';
9
8
  import { defineCustomElement } from '@vaadin/component-base/src/define.js';
10
9
  import { DirMixin } from '@vaadin/component-base/src/dir-mixin.js';
11
- import { listBoxStyles } from '@vaadin/list-box/src/vaadin-list-box-core-styles.js';
12
- import { registerStyles, ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
13
-
14
- registerStyles('vaadin-select-list-box', listBoxStyles, { moduleId: 'vaadin-select-list-box-styles' });
10
+ import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
11
+ import { listBoxStyles } from '@vaadin/list-box/src/styles/vaadin-list-box-core-styles.js';
12
+ import { LumoInjectionMixin } from '@vaadin/vaadin-themable-mixin/lumo-injection-mixin.js';
13
+ import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
15
14
 
16
15
  /**
17
16
  * An element used internally by `<vaadin-select>`. Not intended to be used separately.
18
17
  *
19
18
  * @customElement
20
19
  * @extends HTMLElement
21
- * @mixes ControllerMixin
22
20
  * @mixes DirMixin
23
21
  * @mixes ListMixin
24
22
  * @mixes ThemableMixin
25
23
  * @protected
26
24
  */
27
- class SelectListBox extends ListMixin(ThemableMixin(DirMixin(ControllerMixin(PolymerElement)))) {
25
+ class SelectListBox extends ListMixin(ThemableMixin(DirMixin(PolylitMixin(LumoInjectionMixin(LitElement))))) {
28
26
  static get is() {
29
27
  return 'vaadin-select-list-box';
30
28
  }
31
29
 
32
- static get template() {
33
- return html`
34
- <div part="items">
35
- <slot></slot>
36
- </div>
37
- `;
30
+ static get styles() {
31
+ return listBoxStyles;
38
32
  }
39
33
 
40
34
  static get properties() {
@@ -57,6 +51,15 @@ class SelectListBox extends ListMixin(ThemableMixin(DirMixin(ControllerMixin(Pol
57
51
  return this.shadowRoot.querySelector('[part="items"]');
58
52
  }
59
53
 
54
+ /** @protected */
55
+ render() {
56
+ return html`
57
+ <div part="items">
58
+ <slot></slot>
59
+ </div>
60
+ `;
61
+ }
62
+
60
63
  /** @protected */
61
64
  ready() {
62
65
  super.ready();
@@ -16,7 +16,7 @@ import { PositionMixin } from '@vaadin/overlay/src/vaadin-overlay-position-mixin
16
16
  export const SelectOverlayMixin = (superClass) =>
17
17
  class SelectOverlayMixin extends PositionMixin(OverlayMixin(DirMixin(superClass))) {
18
18
  static get observers() {
19
- return ['_updateOverlayWidth(opened, owner)'];
19
+ return ['_updateOverlayWidth(opened, positionTarget)'];
20
20
  }
21
21
 
22
22
  /** @protected */
@@ -26,6 +26,21 @@ export const SelectOverlayMixin = (superClass) =>
26
26
  this.restoreFocusOnClose = true;
27
27
  }
28
28
 
29
+ /**
30
+ * @override
31
+ * @protected
32
+ */
33
+ get _contentRoot() {
34
+ if (!this.__savedRoot) {
35
+ const root = document.createElement('div');
36
+ root.setAttribute('slot', 'overlay');
37
+ this.owner.appendChild(root);
38
+ this.__savedRoot = root;
39
+ }
40
+
41
+ return this.__savedRoot;
42
+ }
43
+
29
44
  /**
30
45
  * Override method inherited from `Overlay` to always close on outside click,
31
46
  * in order to avoid problem when using inside of the modeless dialog.
@@ -38,22 +53,26 @@ export const SelectOverlayMixin = (superClass) =>
38
53
  return true;
39
54
  }
40
55
 
56
+ /**
57
+ * @protected
58
+ * @override
59
+ */
60
+ _mouseDownListener(event) {
61
+ super._mouseDownListener(event);
62
+
63
+ // Prevent global mousedown event to avoid losing focus on outside click
64
+ event.preventDefault();
65
+ }
66
+
41
67
  /** @protected */
42
68
  _getMenuElement() {
43
- return Array.from(this.children).find((el) => el.localName !== 'style');
69
+ return Array.from(this._contentRoot.children).find((el) => el.localName !== 'style');
44
70
  }
45
71
 
46
72
  /** @private */
47
- _updateOverlayWidth(opened, owner) {
48
- if (opened && owner) {
49
- const widthProperty = '--vaadin-select-overlay-width';
50
- const customWidth = getComputedStyle(owner).getPropertyValue(widthProperty);
51
-
52
- if (customWidth === '') {
53
- this.style.removeProperty(widthProperty);
54
- } else {
55
- this.style.setProperty(widthProperty, customWidth);
56
- }
73
+ _updateOverlayWidth(opened, positionTarget) {
74
+ if (opened && positionTarget) {
75
+ this.style.setProperty('--_vaadin-select-overlay-default-width', `${positionTarget.offsetWidth}px`);
57
76
  }
58
77
  }
59
78
 
@@ -3,17 +3,15 @@
3
3
  * Copyright (c) 2017 - 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 { html, PolymerElement } from '@polymer/polymer/polymer-element.js';
6
+ import { html, LitElement } from 'lit';
7
7
  import { defineCustomElement } from '@vaadin/component-base/src/define.js';
8
- import { overlayStyles } from '@vaadin/overlay/src/vaadin-overlay-styles.js';
9
- import { registerStyles, ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
10
- import { selectOverlayStyles } from './vaadin-select-overlay-core-styles.js';
8
+ import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
9
+ import { overlayStyles } from '@vaadin/overlay/src/styles/vaadin-overlay-core-styles.js';
10
+ import { LumoInjectionMixin } from '@vaadin/vaadin-themable-mixin/lumo-injection-mixin.js';
11
+ import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
12
+ import { selectOverlayStyles } from './styles/vaadin-select-overlay-core-styles.js';
11
13
  import { SelectOverlayMixin } from './vaadin-select-overlay-mixin.js';
12
14
 
13
- registerStyles('vaadin-select-overlay', [overlayStyles, selectOverlayStyles], {
14
- moduleId: 'vaadin-select-overlay-styles',
15
- });
16
-
17
15
  /**
18
16
  * An element used internally by `<vaadin-select>`. Not intended to be used separately.
19
17
  *
@@ -23,21 +21,35 @@ registerStyles('vaadin-select-overlay', [overlayStyles, selectOverlayStyles], {
23
21
  * @mixes ThemableMixin
24
22
  * @private
25
23
  */
26
- export class SelectOverlay extends SelectOverlayMixin(ThemableMixin(PolymerElement)) {
24
+ export class SelectOverlay extends SelectOverlayMixin(ThemableMixin(PolylitMixin(LumoInjectionMixin(LitElement)))) {
27
25
  static get is() {
28
26
  return 'vaadin-select-overlay';
29
27
  }
30
28
 
31
- static get template() {
29
+ static get styles() {
30
+ return [overlayStyles, selectOverlayStyles];
31
+ }
32
+
33
+ /** @protected */
34
+ render() {
32
35
  return html`
33
- <div id="backdrop" part="backdrop" hidden$="[[!withBackdrop]]"></div>
34
- <div part="overlay" id="overlay" tabindex="0">
36
+ <div id="backdrop" part="backdrop" ?hidden="${!this.withBackdrop}"></div>
37
+ <div part="overlay" id="overlay">
35
38
  <div part="content" id="content">
36
39
  <slot></slot>
37
40
  </div>
38
41
  </div>
39
42
  `;
40
43
  }
44
+
45
+ /** @protected */
46
+ updated(props) {
47
+ super.updated(props);
48
+
49
+ if (props.has('renderer')) {
50
+ this.requestContentUpdate();
51
+ }
52
+ }
41
53
  }
42
54
 
43
55
  defineCustomElement(SelectOverlay);