@vaadin/select 24.0.0-alpha8 → 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/select",
3
- "version": "24.0.0-alpha8",
3
+ "version": "24.0.0-beta1",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -38,21 +38,21 @@
38
38
  ],
39
39
  "dependencies": {
40
40
  "@polymer/polymer": "^3.2.0",
41
- "@vaadin/button": "24.0.0-alpha8",
42
- "@vaadin/component-base": "24.0.0-alpha8",
43
- "@vaadin/field-base": "24.0.0-alpha8",
44
- "@vaadin/input-container": "24.0.0-alpha8",
45
- "@vaadin/item": "24.0.0-alpha8",
46
- "@vaadin/list-box": "24.0.0-alpha8",
47
- "@vaadin/lit-renderer": "24.0.0-alpha8",
48
- "@vaadin/overlay": "24.0.0-alpha8",
49
- "@vaadin/vaadin-lumo-styles": "24.0.0-alpha8",
50
- "@vaadin/vaadin-material-styles": "24.0.0-alpha8",
51
- "@vaadin/vaadin-themable-mixin": "24.0.0-alpha8"
41
+ "@vaadin/button": "24.0.0-beta1",
42
+ "@vaadin/component-base": "24.0.0-beta1",
43
+ "@vaadin/field-base": "24.0.0-beta1",
44
+ "@vaadin/input-container": "24.0.0-beta1",
45
+ "@vaadin/item": "24.0.0-beta1",
46
+ "@vaadin/list-box": "24.0.0-beta1",
47
+ "@vaadin/lit-renderer": "24.0.0-beta1",
48
+ "@vaadin/overlay": "24.0.0-beta1",
49
+ "@vaadin/vaadin-lumo-styles": "24.0.0-beta1",
50
+ "@vaadin/vaadin-material-styles": "24.0.0-beta1",
51
+ "@vaadin/vaadin-themable-mixin": "24.0.0-beta1"
52
52
  },
53
53
  "devDependencies": {
54
54
  "@esm-bundle/chai": "^4.3.4",
55
- "@vaadin/testing-helpers": "^0.3.2",
55
+ "@vaadin/testing-helpers": "^0.4.0",
56
56
  "lit": "^2.0.0",
57
57
  "sinon": "^13.0.2"
58
58
  },
@@ -60,5 +60,5 @@
60
60
  "web-types.json",
61
61
  "web-types.lit.json"
62
62
  ],
63
- "gitHead": "476752249bb12295c500980d98a3256ad3b22b73"
63
+ "gitHead": "c5b48921a62482746df8e46994b37e1490fec27e"
64
64
  }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2023 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+ import { SlotController } from '@vaadin/component-base/src/slot-controller.js';
7
+
8
+ /**
9
+ * A controller to manage the value button element.
10
+ */
11
+ export class ButtonController extends SlotController {}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2023 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+ import { SlotController } from '@vaadin/component-base/src/slot-controller.js';
7
+
8
+ /**
9
+ * A controller to manage the value button element.
10
+ */
11
+ export class ButtonController extends SlotController {
12
+ constructor(host) {
13
+ super(host, 'value', 'vaadin-select-value-button', {
14
+ initializer: (button, host) => {
15
+ host._setFocusElement(button);
16
+ host.ariaTarget = button;
17
+ host.stateTarget = button;
18
+
19
+ button.setAttribute('aria-haspopup', 'listbox');
20
+ },
21
+ });
22
+ }
23
+ }
@@ -0,0 +1,21 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2017 - 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-select>`. Not intended to be used separately.
12
+ */
13
+ declare class SelectItem extends ItemMixin(DirMixin(ThemableMixin(HTMLElement))) {}
14
+
15
+ declare global {
16
+ interface HTMLElementTagNameMap {
17
+ 'vaadin-select-item': SelectItem;
18
+ }
19
+ }
20
+
21
+ export { SelectItem };
@@ -3,18 +3,51 @@
3
3
  * Copyright (c) 2017 - 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 { Item } from '@vaadin/item/src/vaadin-item.js';
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';
7
10
 
8
11
  /**
9
12
  * An element used internally by `<vaadin-select>`. Not intended to be used separately.
10
13
  *
11
- * @extends Item
14
+ * @extends HTMLElement
15
+ * @mixes DirMixin
16
+ * @mixes ItemMixin
17
+ * @mixes ThemableMixin
12
18
  * @protected
13
19
  */
14
- class SelectItem extends Item {
20
+ class SelectItem extends ItemMixin(ThemableMixin(DirMixin(PolymerElement))) {
15
21
  static get is() {
16
22
  return 'vaadin-select-item';
17
23
  }
24
+
25
+ static get template() {
26
+ return html`
27
+ <style>
28
+ :host {
29
+ display: inline-block;
30
+ }
31
+
32
+ :host([hidden]) {
33
+ display: none !important;
34
+ }
35
+ </style>
36
+ <span part="checkmark" aria-hidden="true"></span>
37
+ <div part="content">
38
+ <slot></slot>
39
+ </div>
40
+ `;
41
+ }
42
+
43
+ /** @protected */
44
+ ready() {
45
+ super.ready();
46
+
47
+ this.setAttribute('role', 'option');
48
+ }
18
49
  }
19
50
 
20
51
  customElements.define(SelectItem.is, SelectItem);
52
+
53
+ export { SelectItem };
@@ -0,0 +1,22 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2017 - 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-select>`. Not intended to be used separately.
13
+ */
14
+ declare class SelectListBox extends ListMixin(DirMixin(ThemableMixin(ControllerMixin(HTMLElement)))) {}
15
+
16
+ declare global {
17
+ interface HTMLElementTagNameMap {
18
+ 'vaadin-select-list-box': SelectListBox;
19
+ }
20
+ }
21
+
22
+ export { SelectListBox };
@@ -3,18 +3,77 @@
3
3
  * Copyright (c) 2017 - 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 { ListBox } from '@vaadin/list-box/src/vaadin-list-box.js';
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';
7
11
 
8
12
  /**
9
13
  * An element used internally by `<vaadin-select>`. Not intended to be used separately.
10
14
  *
11
- * @extends ListBox
15
+ * @extends HTMLElement
16
+ * @mixes ControllerMixin
17
+ * @mixes DirMixin
18
+ * @mixes ListMixin
19
+ * @mixes ThemableMixin
12
20
  * @protected
13
21
  */
14
- class SelectListBox extends ListBox {
22
+ class SelectListBox extends ListMixin(ThemableMixin(DirMixin(ControllerMixin(PolymerElement)))) {
15
23
  static get is() {
16
24
  return 'vaadin-select-list-box';
17
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', 'listbox');
76
+ }
18
77
  }
19
78
 
20
79
  customElements.define(SelectListBox.is, SelectListBox);
@@ -6,6 +6,8 @@
6
6
  import { DelegateFocusMixin } from '@vaadin/component-base/src/delegate-focus-mixin.js';
7
7
  import { DelegateStateMixin } from '@vaadin/component-base/src/delegate-state-mixin.js';
8
8
  import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
9
+ import { KeyboardMixin } from '@vaadin/component-base/src/keyboard-mixin.js';
10
+ import { OverlayClassMixin } from '@vaadin/component-base/src/overlay-class-mixin.js';
9
11
  import { FieldMixin } from '@vaadin/field-base/src/field-mixin.js';
10
12
  import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
11
13
 
@@ -172,8 +174,8 @@ export interface SelectEventMap extends HTMLElementEventMap, SelectCustomEventMa
172
174
  * @fires {CustomEvent} value-changed - Fired when the `value` property changes.
173
175
  * @fires {CustomEvent} validated - Fired whenever the field is validated.
174
176
  */
175
- declare class Select extends DelegateFocusMixin(
176
- DelegateStateMixin(FieldMixin(ElementMixin(ThemableMixin(HTMLElement)))),
177
+ declare class Select extends OverlayClassMixin(
178
+ DelegateFocusMixin(DelegateStateMixin(KeyboardMixin(FieldMixin(ElementMixin(ThemableMixin(HTMLElement)))))),
177
179
  ) {
178
180
  /**
179
181
  * An array containing items that will be rendered as the options of the select.
@@ -214,10 +216,8 @@ declare class Select extends DelegateFocusMixin(
214
216
  renderer: SelectRenderer | undefined;
215
217
 
216
218
  /**
217
- * It stores the the `value` property of the selected item, providing the
218
- * value for iron-form.
219
- * When there’s an item selected, it's the value of that item, otherwise
220
- * it's an empty string.
219
+ * The `value` property of the selected item, or an empty string
220
+ * if no item is selected.
221
221
  * On change or initialization, the component finds the item which matches the
222
222
  * value and displays it.
223
223
  * If no value is provided to the component, it selects the first item without
@@ -12,8 +12,9 @@ import { html, PolymerElement } from '@polymer/polymer/polymer-element.js';
12
12
  import { DelegateFocusMixin } from '@vaadin/component-base/src/delegate-focus-mixin.js';
13
13
  import { DelegateStateMixin } from '@vaadin/component-base/src/delegate-state-mixin.js';
14
14
  import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
15
+ import { KeyboardMixin } from '@vaadin/component-base/src/keyboard-mixin.js';
15
16
  import { MediaQueryController } from '@vaadin/component-base/src/media-query-controller.js';
16
- import { SlotController } from '@vaadin/component-base/src/slot-controller.js';
17
+ import { OverlayClassMixin } from '@vaadin/component-base/src/overlay-class-mixin.js';
17
18
  import { processTemplates } from '@vaadin/component-base/src/templates.js';
18
19
  import { TooltipController } from '@vaadin/component-base/src/tooltip-controller.js';
19
20
  import { generateUniqueId } from '@vaadin/component-base/src/unique-id-utils.js';
@@ -21,6 +22,7 @@ import { FieldMixin } from '@vaadin/field-base/src/field-mixin.js';
21
22
  import { fieldShared } from '@vaadin/field-base/src/styles/field-shared-styles.js';
22
23
  import { inputFieldContainer } from '@vaadin/field-base/src/styles/input-field-container-styles.js';
23
24
  import { registerStyles, ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
25
+ import { ButtonController } from './button-controller.js';
24
26
 
25
27
  registerStyles('vaadin-select', [fieldShared, inputFieldContainer], { moduleId: 'vaadin-select-styles' });
26
28
 
@@ -135,8 +137,12 @@ registerStyles('vaadin-select', [fieldShared, inputFieldContainer], { moduleId:
135
137
  * @mixes FieldMixin
136
138
  * @mixes DelegateFocusMixin
137
139
  * @mixes DelegateStateMixin
140
+ * @mixes KeyboardMixin
141
+ * @mixes OverlayClassMixin
138
142
  */
139
- class Select extends DelegateFocusMixin(DelegateStateMixin(FieldMixin(ElementMixin(ThemableMixin(PolymerElement))))) {
143
+ class Select extends OverlayClassMixin(
144
+ DelegateFocusMixin(DelegateStateMixin(KeyboardMixin(FieldMixin(ElementMixin(ThemableMixin(PolymerElement)))))),
145
+ ) {
140
146
  static get is() {
141
147
  return 'vaadin-select';
142
148
  }
@@ -241,10 +247,8 @@ class Select extends DelegateFocusMixin(DelegateStateMixin(FieldMixin(ElementMix
241
247
  renderer: Function,
242
248
 
243
249
  /**
244
- * It stores the the `value` property of the selected item, providing the
245
- * value for iron-form.
246
- * When there’s an item selected, it's the value of that item, otherwise
247
- * it's an empty string.
250
+ * The `value` property of the selected item, or an empty string
251
+ * if no item is selected.
248
252
  * On change or initialization, the component finds the item which matches the
249
253
  * value and displays it.
250
254
  * If no value is provided to the component, it selects the first item without
@@ -297,9 +301,6 @@ class Select extends DelegateFocusMixin(DelegateStateMixin(FieldMixin(ElementMix
297
301
  value: '(max-width: 420px), (max-height: 420px)',
298
302
  },
299
303
 
300
- /** @private */
301
- _overlayElement: Object,
302
-
303
304
  /** @private */
304
305
  _inputContainer: Object,
305
306
 
@@ -314,23 +315,16 @@ class Select extends DelegateFocusMixin(DelegateStateMixin(FieldMixin(ElementMix
314
315
 
315
316
  static get observers() {
316
317
  return [
317
- '_updateAriaExpanded(opened)',
318
+ '_updateAriaExpanded(opened, focusElement)',
318
319
  '_updateSelectedItem(value, _items, placeholder)',
319
320
  '_rendererChanged(renderer, _overlayElement)',
320
321
  ];
321
322
  }
322
323
 
323
- /** @protected */
324
- get _valueButton() {
325
- return this._valueButtonController && this._valueButtonController.node;
326
- }
327
-
328
324
  constructor() {
329
325
  super();
330
326
 
331
- this._fieldId = `${this.localName}-${generateUniqueId()}`;
332
-
333
- this._boundOnKeyDown = this._onKeyDown.bind(this);
327
+ this._itemId = `value-${this.localName}-${generateUniqueId()}`;
334
328
  }
335
329
 
336
330
  /** @protected */
@@ -348,20 +342,7 @@ class Select extends DelegateFocusMixin(DelegateStateMixin(FieldMixin(ElementMix
348
342
  this._overlayElement = this.shadowRoot.querySelector('vaadin-select-overlay');
349
343
  this._inputContainer = this.shadowRoot.querySelector('[part~="input-field"]');
350
344
 
351
- this._valueButtonController = new SlotController(this, 'value', 'vaadin-select-value-button', {
352
- initializer: (btn) => {
353
- this._setFocusElement(btn);
354
- this.ariaTarget = btn;
355
- this.stateTarget = btn;
356
-
357
- btn.setAttribute('aria-haspopup', 'listbox');
358
- btn.setAttribute('aria-labelledby', `${this._labelId} ${this._fieldId}`);
359
-
360
- this._updateAriaExpanded(this.opened);
361
-
362
- btn.addEventListener('keydown', this._boundOnKeyDown);
363
- },
364
- });
345
+ this._valueButtonController = new ButtonController(this);
365
346
  this.addController(this._valueButtonController);
366
347
 
367
348
  this.addController(
@@ -464,8 +445,6 @@ class Select extends DelegateFocusMixin(DelegateStateMixin(FieldMixin(ElementMix
464
445
  true,
465
446
  );
466
447
 
467
- menuElement.setAttribute('role', 'listbox');
468
-
469
448
  // Store the menu element reference
470
449
  this.__lastMenuElement = menuElement;
471
450
  }
@@ -475,7 +454,6 @@ class Select extends DelegateFocusMixin(DelegateStateMixin(FieldMixin(ElementMix
475
454
  __initMenuItems(menuElement) {
476
455
  if (menuElement.items) {
477
456
  this._items = menuElement.items;
478
- this._items.forEach((item) => item.setAttribute('role', 'option'));
479
457
  }
480
458
  }
481
459
 
@@ -512,9 +490,10 @@ class Select extends DelegateFocusMixin(DelegateStateMixin(FieldMixin(ElementMix
512
490
  /**
513
491
  * @param {!KeyboardEvent} e
514
492
  * @protected
493
+ * @override
515
494
  */
516
495
  _onKeyDown(e) {
517
- if (!this.readonly && !this.opened) {
496
+ if (e.target === this.focusElement && !this.readonly && !this.opened) {
518
497
  if (/^(Enter|SpaceBar|\s|ArrowDown|Down|ArrowUp|Up)$/u.test(e.key)) {
519
498
  e.preventDefault();
520
499
  this.opened = true;
@@ -579,19 +558,19 @@ class Select extends DelegateFocusMixin(DelegateStateMixin(FieldMixin(ElementMix
579
558
  }
580
559
 
581
560
  /** @private */
582
- _updateAriaExpanded(opened) {
583
- if (this._valueButton) {
584
- this._valueButton.setAttribute('aria-expanded', opened ? 'true' : 'false');
561
+ _updateAriaExpanded(opened, focusElement) {
562
+ if (focusElement) {
563
+ focusElement.setAttribute('aria-expanded', opened ? 'true' : 'false');
585
564
  }
586
565
  }
587
566
 
588
567
  /** @private */
589
568
  _updateAriaLive(ariaLive) {
590
- if (this._valueButton) {
569
+ if (this.focusElement) {
591
570
  if (ariaLive) {
592
- this._valueButton.setAttribute('aria-live', 'polite');
571
+ this.focusElement.setAttribute('aria-live', 'polite');
593
572
  } else {
594
- this._valueButton.removeAttribute('aria-live');
573
+ this.focusElement.removeAttribute('aria-live');
595
574
  }
596
575
  }
597
576
  }
@@ -610,7 +589,7 @@ class Select extends DelegateFocusMixin(DelegateStateMixin(FieldMixin(ElementMix
610
589
  // Store reference to the original item
611
590
  labelItem._sourceItem = selected;
612
591
 
613
- this.__appendValueItemElement(labelItem);
592
+ this.__appendValueItemElement(labelItem, this.focusElement);
614
593
 
615
594
  // Ensure the item gets proper styles
616
595
  labelItem.selected = true;
@@ -636,33 +615,36 @@ class Select extends DelegateFocusMixin(DelegateStateMixin(FieldMixin(ElementMix
636
615
 
637
616
  /**
638
617
  * @param {!HTMLElement} itemElement
618
+ * @param {!HTMLElement} parent
639
619
  * @private
640
620
  */
641
- __appendValueItemElement(itemElement) {
621
+ __appendValueItemElement(itemElement, parent) {
622
+ parent.appendChild(itemElement);
642
623
  itemElement.removeAttribute('tabindex');
624
+ itemElement.removeAttribute('aria-selected');
643
625
  itemElement.removeAttribute('role');
644
- itemElement.setAttribute('id', this._fieldId);
645
-
646
- this._valueButton.appendChild(itemElement);
626
+ itemElement.setAttribute('id', this._itemId);
647
627
  }
648
628
 
649
629
  /** @private */
650
630
  __updateValueButton() {
651
- if (!this._valueButton) {
631
+ const valueButton = this.focusElement;
632
+
633
+ if (!valueButton) {
652
634
  return;
653
635
  }
654
636
 
655
- this._valueButton.innerHTML = '';
637
+ valueButton.innerHTML = '';
656
638
 
657
639
  const selected = this._items[this._menuElement.selected];
658
640
 
659
- this._valueButton.removeAttribute('placeholder');
641
+ valueButton.removeAttribute('placeholder');
660
642
 
661
643
  if (!selected) {
662
644
  if (this.placeholder) {
663
645
  const item = this.__createItemElement({ label: this.placeholder });
664
- this.__appendValueItemElement(item);
665
- this._valueButton.setAttribute('placeholder', '');
646
+ this.__appendValueItemElement(item, valueButton);
647
+ valueButton.setAttribute('placeholder', '');
666
648
  }
667
649
  } else {
668
650
  this.__attachSelectedItem(selected);
@@ -678,6 +660,12 @@ class Select extends DelegateFocusMixin(DelegateStateMixin(FieldMixin(ElementMix
678
660
  delete this._selectedChanging;
679
661
  }
680
662
  }
663
+
664
+ // Use item ID if there is a selected item or placeholder text
665
+ valueButton.setAttribute(
666
+ 'aria-labelledby',
667
+ selected || this.placeholder ? `${this._labelId} ${this._itemId}` : this._labelId,
668
+ );
681
669
  }
682
670
 
683
671
  /** @private */
@@ -6,10 +6,16 @@
6
6
  import '@vaadin/vaadin-lumo-styles/sizing.js';
7
7
  import '@vaadin/vaadin-lumo-styles/style.js';
8
8
  import '@vaadin/vaadin-lumo-styles/font-icons.js';
9
+ import { item } from '@vaadin/item/theme/lumo/vaadin-item-styles.js';
10
+ import { listBox } from '@vaadin/list-box/theme/lumo/vaadin-list-box-styles.js';
9
11
  import { inputFieldShared } from '@vaadin/vaadin-lumo-styles/mixins/input-field-shared.js';
10
12
  import { menuOverlay } from '@vaadin/vaadin-lumo-styles/mixins/menu-overlay.js';
11
13
  import { css, registerStyles } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
12
14
 
15
+ registerStyles('vaadin-select-item', item, { moduleId: 'lumo-select-item' });
16
+
17
+ registerStyles('vaadin-select-list-box', listBox, { moduleId: 'lumo-select-list-box' });
18
+
13
19
  const select = css`
14
20
  :host(:not([theme*='align'])) ::slotted([slot='value']) {
15
21
  text-align: start;
@@ -33,9 +39,11 @@ const select = css`
33
39
 
34
40
  /* placeholder styles */
35
41
  [part='input-field'] ::slotted([slot='value'][placeholder]) {
36
- color: inherit;
37
- transition: opacity 0.175s 0.1s;
38
- opacity: 0.5;
42
+ color: var(--lumo-secondary-text-color);
43
+ }
44
+
45
+ :host(:is([readonly], [disabled])) ::slotted([slot='value'][placeholder]) {
46
+ opacity: 0;
39
47
  }
40
48
 
41
49
  [part='toggle-button']::before {
@@ -4,8 +4,6 @@
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
  import '@vaadin/input-container/theme/lumo/vaadin-input-container.js';
7
- import '@vaadin/item/theme/lumo/vaadin-item.js';
8
- import '@vaadin/list-box/theme/lumo/vaadin-list-box.js';
9
7
  import '@vaadin/overlay/theme/lumo/vaadin-overlay.js';
10
8
  import './vaadin-select-styles.js';
11
9
  import '../../src/vaadin-select.js';
@@ -4,10 +4,16 @@
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
  import '@vaadin/vaadin-material-styles/font-icons.js';
7
+ import { item } from '@vaadin/item/theme/material/vaadin-item-styles.js';
8
+ import { listBox } from '@vaadin/list-box/theme/material/vaadin-list-box-styles.js';
7
9
  import { inputFieldShared } from '@vaadin/vaadin-material-styles/mixins/input-field-shared.js';
8
10
  import { menuOverlay } from '@vaadin/vaadin-material-styles/mixins/menu-overlay.js';
9
11
  import { css, registerStyles } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
10
12
 
13
+ registerStyles('vaadin-select-item', item, { moduleId: 'material-select-item' });
14
+
15
+ registerStyles('vaadin-select-list-box', listBox, { moduleId: 'material-select-list-box' });
16
+
11
17
  const select = css`
12
18
  :host {
13
19
  display: inline-flex;
@@ -4,8 +4,6 @@
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
  import '@vaadin/input-container/theme/material/vaadin-input-container.js';
7
- import '@vaadin/item/theme/material/vaadin-item.js';
8
- import '@vaadin/list-box/theme/material/vaadin-list-box.js';
9
7
  import '@vaadin/overlay/theme/material/vaadin-overlay.js';
10
8
  import './vaadin-select-styles.js';
11
9
  import '../../src/vaadin-select.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/select",
4
- "version": "24.0.0-alpha8",
4
+ "version": "24.0.0-alpha12",
5
5
  "description-markup": "markdown",
6
6
  "contributions": {
7
7
  "html": {
8
8
  "elements": [
9
9
  {
10
10
  "name": "vaadin-select",
11
- "description": "`<vaadin-select>` is a Web Component for selecting values from a list of items.\n\n### Items\n\nUse the `items` property to define possible options for the select:\n\n```html\n<vaadin-select id=\"select\"></vaadin-select>\n```\n```js\nconst select = document.querySelector('#select');\nselect.items = [\n { label: 'Most recent first', value: 'recent' },\n { component: 'hr' },\n { label: 'Rating: low to high', value: 'rating-asc' },\n { label: 'Rating: high to low', value: 'rating-desc' },\n { component: 'hr' },\n { label: 'Price: low to high', value: 'price-asc', disabled: true },\n { label: 'Price: high to low', value: 'price-desc', disabled: true }\n];\n```\n\n### Rendering\n\nAlternatively, the content of the select can be populated by using the renderer callback function.\n\nThe renderer function provides `root`, `select` arguments.\nGenerate DOM content, append it to the `root` element and control the state\nof the host element by accessing `select`.\n\n```js\nconst select = document.querySelector('#select');\nselect.renderer = function(root, select) {\n const listBox = document.createElement('vaadin-list-box');\n // append 3 <vaadin-item> elements\n ['Jose', 'Manolo', 'Pedro'].forEach(function(name) {\n const item = document.createElement('vaadin-item');\n item.textContent = name;\n item.setAttribute('label', name)\n listBox.appendChild(item);\n });\n\n // update the content\n root.appendChild(listBox);\n};\n```\n\nRenderer is called on initialization of new select and on its opening.\nDOM generated during the renderer call can be reused\nin the next renderer call and will be provided with the `root` argument.\nOn first call it will be empty.\n\n* Hint: By setting the `label` property of inner vaadin-items you will\nbe able to change the visual representation of the selected value in the input part.\n\n### Styling\n\nThe following custom properties are available for styling:\n\nCustom property | Description | Target element | Default\n-----------------------------------|------------------------------|----------------------------------\n`--vaadin-field-default-width` | Default width of the field | :host | `12em`\n`--vaadin-select-text-field-width` | Effective width of the field | `vaadin-select-overlay` |\n\n`<vaadin-select>` provides mostly the same set of shadow DOM parts and state attributes as `<vaadin-text-field>`.\nSee [`<vaadin-text-field>`](https://cdn.vaadin.com/vaadin-web-components/24.0.0-alpha8/#/elements/vaadin-text-field) for the styling documentation.\n\n\nIn addition to `<vaadin-text-field>` parts, the following parts are available for theming:\n\nPart name | Description\n----------------|----------------\n`toggle-button` | The toggle button\n\nIn addition to `<vaadin-text-field>` state attributes, the following state attributes are available for theming:\n\nAttribute | Description | Part name\n----------|-----------------------------|-----------\n`opened` | Set when the select is open | :host\n\nThere are two exceptions in terms of styling compared to `<vaadin-text-field>`:\n- the `clear-button` shadow DOM part does not exist in `<vaadin-select>`.\n- the `input-prevented` state attribute is not supported by `<vaadin-select>`.\n\n### Internal components\n\nIn addition to `<vaadin-select>` itself, the following internal\ncomponents are themable:\n\n- `<vaadin-select-overlay>` - has the same API as [`<vaadin-overlay>`](https://cdn.vaadin.com/vaadin-web-components/24.0.0-alpha8/#/elements/vaadin-overlay).\n- `<vaadin-select-value-button>` - has the same API as [`<vaadin-button>`](https://cdn.vaadin.com/vaadin-web-components/24.0.0-alpha8/#/elements/vaadin-button).\n- [`<vaadin-input-container>`](https://cdn.vaadin.com/vaadin-web-components/24.0.0-alpha8/#/elements/vaadin-input-container) - an internal element wrapping the button.\n\nNote: the `theme` attribute value set on `<vaadin-select>` is\npropagated to the internal components listed above.\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/custom-theme/styling-components) documentation.",
11
+ "description": "`<vaadin-select>` is a Web Component for selecting values from a list of items.\n\n### Items\n\nUse the `items` property to define possible options for the select:\n\n```html\n<vaadin-select id=\"select\"></vaadin-select>\n```\n```js\nconst select = document.querySelector('#select');\nselect.items = [\n { label: 'Most recent first', value: 'recent' },\n { component: 'hr' },\n { label: 'Rating: low to high', value: 'rating-asc' },\n { label: 'Rating: high to low', value: 'rating-desc' },\n { component: 'hr' },\n { label: 'Price: low to high', value: 'price-asc', disabled: true },\n { label: 'Price: high to low', value: 'price-desc', disabled: true }\n];\n```\n\n### Rendering\n\nAlternatively, the content of the select can be populated by using the renderer callback function.\n\nThe renderer function provides `root`, `select` arguments.\nGenerate DOM content, append it to the `root` element and control the state\nof the host element by accessing `select`.\n\n```js\nconst select = document.querySelector('#select');\nselect.renderer = function(root, select) {\n const listBox = document.createElement('vaadin-list-box');\n // append 3 <vaadin-item> elements\n ['Jose', 'Manolo', 'Pedro'].forEach(function(name) {\n const item = document.createElement('vaadin-item');\n item.textContent = name;\n item.setAttribute('label', name)\n listBox.appendChild(item);\n });\n\n // update the content\n root.appendChild(listBox);\n};\n```\n\nRenderer is called on initialization of new select and on its opening.\nDOM generated during the renderer call can be reused\nin the next renderer call and will be provided with the `root` argument.\nOn first call it will be empty.\n\n* Hint: By setting the `label` property of inner vaadin-items you will\nbe able to change the visual representation of the selected value in the input part.\n\n### Styling\n\nThe following custom properties are available for styling:\n\nCustom property | Description | Target element | Default\n-----------------------------------|------------------------------|----------------------------------\n`--vaadin-field-default-width` | Default width of the field | :host | `12em`\n`--vaadin-select-text-field-width` | Effective width of the field | `vaadin-select-overlay` |\n\n`<vaadin-select>` provides mostly the same set of shadow DOM parts and state attributes as `<vaadin-text-field>`.\nSee [`<vaadin-text-field>`](https://cdn.vaadin.com/vaadin-web-components/24.0.0-alpha12/#/elements/vaadin-text-field) for the styling documentation.\n\n\nIn addition to `<vaadin-text-field>` parts, the following parts are available for theming:\n\nPart name | Description\n----------------|----------------\n`toggle-button` | The toggle button\n\nIn addition to `<vaadin-text-field>` state attributes, the following state attributes are available for theming:\n\nAttribute | Description | Part name\n----------|-----------------------------|-----------\n`opened` | Set when the select is open | :host\n\nThere are two exceptions in terms of styling compared to `<vaadin-text-field>`:\n- the `clear-button` shadow DOM part does not exist in `<vaadin-select>`.\n- the `input-prevented` state attribute is not supported by `<vaadin-select>`.\n\n### Internal components\n\nIn addition to `<vaadin-select>` itself, the following internal\ncomponents are themable:\n\n- `<vaadin-select-overlay>` - has the same API as [`<vaadin-overlay>`](https://cdn.vaadin.com/vaadin-web-components/24.0.0-alpha12/#/elements/vaadin-overlay).\n- `<vaadin-select-value-button>` - has the same API as [`<vaadin-button>`](https://cdn.vaadin.com/vaadin-web-components/24.0.0-alpha12/#/elements/vaadin-button).\n- [`<vaadin-input-container>`](https://cdn.vaadin.com/vaadin-web-components/24.0.0-alpha12/#/elements/vaadin-input-container) - an internal element wrapping the button.\n\nNote: the `theme` attribute value set on `<vaadin-select>` is\npropagated to the internal components listed above.\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/custom-theme/styling-components) documentation.",
12
12
  "attributes": [
13
13
  {
14
14
  "name": "label",
@@ -87,6 +87,17 @@
87
87
  ]
88
88
  }
89
89
  },
90
+ {
91
+ "name": "overlay-class",
92
+ "description": "A space-delimited list of CSS class names to set on the overlay element.\nThis property does not affect other CSS class names set manually via JS.\n\nNote, if the CSS class name was set with this property, clearing it will\nremove it from the overlay, even if the same class name was also added\nmanually, e.g. by using `classList.add()` in the `renderer` function.",
93
+ "value": {
94
+ "type": [
95
+ "string",
96
+ "null",
97
+ "undefined"
98
+ ]
99
+ }
100
+ },
90
101
  {
91
102
  "name": "opened",
92
103
  "description": "Set when the select is open",
@@ -227,6 +238,17 @@
227
238
  ]
228
239
  }
229
240
  },
241
+ {
242
+ "name": "overlayClass",
243
+ "description": "A space-delimited list of CSS class names to set on the overlay element.\nThis property does not affect other CSS class names set manually via JS.\n\nNote, if the CSS class name was set with this property, clearing it will\nremove it from the overlay, even if the same class name was also added\nmanually, e.g. by using `classList.add()` in the `renderer` function.",
244
+ "value": {
245
+ "type": [
246
+ "string",
247
+ "null",
248
+ "undefined"
249
+ ]
250
+ }
251
+ },
230
252
  {
231
253
  "name": "items",
232
254
  "description": "An array containing items that will be rendered as the options of the select.\n\n#### Example\n```js\nselect.items = [\n { label: 'Most recent first', value: 'recent' },\n { component: 'hr' },\n { label: 'Rating: low to high', value: 'rating-asc' },\n { label: 'Rating: high to low', value: 'rating-desc' },\n { component: 'hr' },\n { label: 'Price: low to high', value: 'price-asc', disabled: true },\n { label: 'Price: high to low', value: 'price-desc', disabled: true }\n];\n```\n\nNote: each item is rendered by default as the internal `<vaadin-select-item>` that is an extension of `<vaadin-item>`.\nTo render the item with a custom component, provide a tag name by the `component` property.",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/web-types",
3
3
  "name": "@vaadin/select",
4
- "version": "24.0.0-alpha8",
4
+ "version": "24.0.0-alpha12",
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-select",
19
- "description": "`<vaadin-select>` is a Web Component for selecting values from a list of items.\n\n### Items\n\nUse the `items` property to define possible options for the select:\n\n```html\n<vaadin-select id=\"select\"></vaadin-select>\n```\n```js\nconst select = document.querySelector('#select');\nselect.items = [\n { label: 'Most recent first', value: 'recent' },\n { component: 'hr' },\n { label: 'Rating: low to high', value: 'rating-asc' },\n { label: 'Rating: high to low', value: 'rating-desc' },\n { component: 'hr' },\n { label: 'Price: low to high', value: 'price-asc', disabled: true },\n { label: 'Price: high to low', value: 'price-desc', disabled: true }\n];\n```\n\n### Rendering\n\nAlternatively, the content of the select can be populated by using the renderer callback function.\n\nThe renderer function provides `root`, `select` arguments.\nGenerate DOM content, append it to the `root` element and control the state\nof the host element by accessing `select`.\n\n```js\nconst select = document.querySelector('#select');\nselect.renderer = function(root, select) {\n const listBox = document.createElement('vaadin-list-box');\n // append 3 <vaadin-item> elements\n ['Jose', 'Manolo', 'Pedro'].forEach(function(name) {\n const item = document.createElement('vaadin-item');\n item.textContent = name;\n item.setAttribute('label', name)\n listBox.appendChild(item);\n });\n\n // update the content\n root.appendChild(listBox);\n};\n```\n\nRenderer is called on initialization of new select and on its opening.\nDOM generated during the renderer call can be reused\nin the next renderer call and will be provided with the `root` argument.\nOn first call it will be empty.\n\n* Hint: By setting the `label` property of inner vaadin-items you will\nbe able to change the visual representation of the selected value in the input part.\n\n### Styling\n\nThe following custom properties are available for styling:\n\nCustom property | Description | Target element | Default\n-----------------------------------|------------------------------|----------------------------------\n`--vaadin-field-default-width` | Default width of the field | :host | `12em`\n`--vaadin-select-text-field-width` | Effective width of the field | `vaadin-select-overlay` |\n\n`<vaadin-select>` provides mostly the same set of shadow DOM parts and state attributes as `<vaadin-text-field>`.\nSee [`<vaadin-text-field>`](https://cdn.vaadin.com/vaadin-web-components/24.0.0-alpha8/#/elements/vaadin-text-field) for the styling documentation.\n\n\nIn addition to `<vaadin-text-field>` parts, the following parts are available for theming:\n\nPart name | Description\n----------------|----------------\n`toggle-button` | The toggle button\n\nIn addition to `<vaadin-text-field>` state attributes, the following state attributes are available for theming:\n\nAttribute | Description | Part name\n----------|-----------------------------|-----------\n`opened` | Set when the select is open | :host\n\nThere are two exceptions in terms of styling compared to `<vaadin-text-field>`:\n- the `clear-button` shadow DOM part does not exist in `<vaadin-select>`.\n- the `input-prevented` state attribute is not supported by `<vaadin-select>`.\n\n### Internal components\n\nIn addition to `<vaadin-select>` itself, the following internal\ncomponents are themable:\n\n- `<vaadin-select-overlay>` - has the same API as [`<vaadin-overlay>`](https://cdn.vaadin.com/vaadin-web-components/24.0.0-alpha8/#/elements/vaadin-overlay).\n- `<vaadin-select-value-button>` - has the same API as [`<vaadin-button>`](https://cdn.vaadin.com/vaadin-web-components/24.0.0-alpha8/#/elements/vaadin-button).\n- [`<vaadin-input-container>`](https://cdn.vaadin.com/vaadin-web-components/24.0.0-alpha8/#/elements/vaadin-input-container) - an internal element wrapping the button.\n\nNote: the `theme` attribute value set on `<vaadin-select>` is\npropagated to the internal components listed above.\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/custom-theme/styling-components) documentation.",
19
+ "description": "`<vaadin-select>` is a Web Component for selecting values from a list of items.\n\n### Items\n\nUse the `items` property to define possible options for the select:\n\n```html\n<vaadin-select id=\"select\"></vaadin-select>\n```\n```js\nconst select = document.querySelector('#select');\nselect.items = [\n { label: 'Most recent first', value: 'recent' },\n { component: 'hr' },\n { label: 'Rating: low to high', value: 'rating-asc' },\n { label: 'Rating: high to low', value: 'rating-desc' },\n { component: 'hr' },\n { label: 'Price: low to high', value: 'price-asc', disabled: true },\n { label: 'Price: high to low', value: 'price-desc', disabled: true }\n];\n```\n\n### Rendering\n\nAlternatively, the content of the select can be populated by using the renderer callback function.\n\nThe renderer function provides `root`, `select` arguments.\nGenerate DOM content, append it to the `root` element and control the state\nof the host element by accessing `select`.\n\n```js\nconst select = document.querySelector('#select');\nselect.renderer = function(root, select) {\n const listBox = document.createElement('vaadin-list-box');\n // append 3 <vaadin-item> elements\n ['Jose', 'Manolo', 'Pedro'].forEach(function(name) {\n const item = document.createElement('vaadin-item');\n item.textContent = name;\n item.setAttribute('label', name)\n listBox.appendChild(item);\n });\n\n // update the content\n root.appendChild(listBox);\n};\n```\n\nRenderer is called on initialization of new select and on its opening.\nDOM generated during the renderer call can be reused\nin the next renderer call and will be provided with the `root` argument.\nOn first call it will be empty.\n\n* Hint: By setting the `label` property of inner vaadin-items you will\nbe able to change the visual representation of the selected value in the input part.\n\n### Styling\n\nThe following custom properties are available for styling:\n\nCustom property | Description | Target element | Default\n-----------------------------------|------------------------------|----------------------------------\n`--vaadin-field-default-width` | Default width of the field | :host | `12em`\n`--vaadin-select-text-field-width` | Effective width of the field | `vaadin-select-overlay` |\n\n`<vaadin-select>` provides mostly the same set of shadow DOM parts and state attributes as `<vaadin-text-field>`.\nSee [`<vaadin-text-field>`](https://cdn.vaadin.com/vaadin-web-components/24.0.0-alpha12/#/elements/vaadin-text-field) for the styling documentation.\n\n\nIn addition to `<vaadin-text-field>` parts, the following parts are available for theming:\n\nPart name | Description\n----------------|----------------\n`toggle-button` | The toggle button\n\nIn addition to `<vaadin-text-field>` state attributes, the following state attributes are available for theming:\n\nAttribute | Description | Part name\n----------|-----------------------------|-----------\n`opened` | Set when the select is open | :host\n\nThere are two exceptions in terms of styling compared to `<vaadin-text-field>`:\n- the `clear-button` shadow DOM part does not exist in `<vaadin-select>`.\n- the `input-prevented` state attribute is not supported by `<vaadin-select>`.\n\n### Internal components\n\nIn addition to `<vaadin-select>` itself, the following internal\ncomponents are themable:\n\n- `<vaadin-select-overlay>` - has the same API as [`<vaadin-overlay>`](https://cdn.vaadin.com/vaadin-web-components/24.0.0-alpha12/#/elements/vaadin-overlay).\n- `<vaadin-select-value-button>` - has the same API as [`<vaadin-button>`](https://cdn.vaadin.com/vaadin-web-components/24.0.0-alpha12/#/elements/vaadin-button).\n- [`<vaadin-input-container>`](https://cdn.vaadin.com/vaadin-web-components/24.0.0-alpha12/#/elements/vaadin-input-container) - an internal element wrapping the button.\n\nNote: the `theme` attribute value set on `<vaadin-select>` is\npropagated to the internal components listed above.\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/custom-theme/styling-components) documentation.",
20
20
  "extension": true,
21
21
  "attributes": [
22
22
  {
@@ -82,6 +82,13 @@
82
82
  "kind": "expression"
83
83
  }
84
84
  },
85
+ {
86
+ "name": ".overlayClass",
87
+ "description": "A space-delimited list of CSS class names to set on the overlay element.\nThis property does not affect other CSS class names set manually via JS.\n\nNote, if the CSS class name was set with this property, clearing it will\nremove it from the overlay, even if the same class name was also added\nmanually, e.g. by using `classList.add()` in the `renderer` function.",
88
+ "value": {
89
+ "kind": "expression"
90
+ }
91
+ },
85
92
  {
86
93
  "name": ".items",
87
94
  "description": "An array containing items that will be rendered as the options of the select.\n\n#### Example\n```js\nselect.items = [\n { label: 'Most recent first', value: 'recent' },\n { component: 'hr' },\n { label: 'Rating: low to high', value: 'rating-asc' },\n { label: 'Rating: high to low', value: 'rating-desc' },\n { component: 'hr' },\n { label: 'Price: low to high', value: 'price-asc', disabled: true },\n { label: 'Price: high to low', value: 'price-desc', disabled: true }\n];\n```\n\nNote: each item is rendered by default as the internal `<vaadin-select-item>` that is an extension of `<vaadin-item>`.\nTo render the item with a custom component, provide a tag name by the `component` property.",