@vaadin/combo-box 25.0.0-alpha8 → 25.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.
Files changed (34) hide show
  1. package/package.json +14 -17
  2. package/src/styles/vaadin-combo-box-base-styles.js +2 -2
  3. package/src/styles/vaadin-combo-box-overlay-base-styles.js +2 -2
  4. package/src/vaadin-combo-box-base-mixin.d.ts +0 -2
  5. package/src/vaadin-combo-box-base-mixin.js +9 -30
  6. package/src/vaadin-combo-box-data-provider-mixin.js +1 -21
  7. package/src/vaadin-combo-box-item-mixin.js +1 -1
  8. package/src/vaadin-combo-box-item.js +1 -1
  9. package/src/vaadin-combo-box-items-mixin.d.ts +60 -0
  10. package/src/vaadin-combo-box-items-mixin.js +292 -0
  11. package/src/vaadin-combo-box-mixin.d.ts +0 -42
  12. package/src/vaadin-combo-box-mixin.js +4 -236
  13. package/src/vaadin-combo-box-overlay-mixin.js +1 -25
  14. package/src/vaadin-combo-box-overlay.js +2 -2
  15. package/src/vaadin-combo-box-scroller-mixin.d.ts +1 -2
  16. package/src/vaadin-combo-box-scroller-mixin.js +5 -0
  17. package/src/vaadin-combo-box-scroller.js +1 -1
  18. package/src/vaadin-combo-box.d.ts +31 -19
  19. package/src/vaadin-combo-box.js +62 -21
  20. package/vaadin-combo-box.js +1 -1
  21. package/web-types.json +59 -70
  22. package/web-types.lit.json +20 -20
  23. package/src/styles/vaadin-combo-box-core-styles.d.ts +0 -8
  24. package/src/styles/vaadin-combo-box-core-styles.js +0 -12
  25. package/src/styles/vaadin-combo-box-overlay-core-styles.js +0 -18
  26. package/src/styles/vaadin-combo-box-scroller-core-styles.js +0 -27
  27. package/theme/lumo/vaadin-combo-box-item-styles.d.ts +0 -5
  28. package/theme/lumo/vaadin-combo-box-item-styles.js +0 -25
  29. package/theme/lumo/vaadin-combo-box-overlay-styles.d.ts +0 -6
  30. package/theme/lumo/vaadin-combo-box-overlay-styles.js +0 -60
  31. package/theme/lumo/vaadin-combo-box-styles.d.ts +0 -2
  32. package/theme/lumo/vaadin-combo-box-styles.js +0 -12
  33. package/theme/lumo/vaadin-combo-box.d.ts +0 -4
  34. package/theme/lumo/vaadin-combo-box.js +0 -4
@@ -3,10 +3,8 @@
3
3
  * Copyright (c) 2015 - 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 { get } from '@vaadin/component-base/src/path-utils.js';
7
6
  import { ValidateMixin } from '@vaadin/field-base/src/validate-mixin.js';
8
- import { ComboBoxBaseMixin } from './vaadin-combo-box-base-mixin.js';
9
- import { ComboBoxPlaceholder } from './vaadin-combo-box-placeholder.js';
7
+ import { ComboBoxItemsMixin } from './vaadin-combo-box-items-mixin.js';
10
8
 
11
9
  /**
12
10
  * Checks if the value is supported as an item value in this control.
@@ -18,32 +16,14 @@ function isValidValue(value) {
18
16
  return value !== undefined && value !== null;
19
17
  }
20
18
 
21
- /**
22
- * Returns the index of the first item that satisfies the provided testing function
23
- * ignoring placeholder items.
24
- *
25
- * @param {Array<ComboBoxItem | string>} items
26
- * @param {Function} callback
27
- * @return {number}
28
- */
29
- function findItemIndex(items, callback) {
30
- return items.findIndex((item) => {
31
- if (item instanceof ComboBoxPlaceholder) {
32
- return false;
33
- }
34
-
35
- return callback(item);
36
- });
37
- }
38
-
39
19
  /**
40
20
  * @polymerMixin
41
- * @mixes ComboBoxBaseMixin
21
+ * @mixes ComboBoxItemsMixin
42
22
  * @mixes ValidateMixin
43
23
  * @param {function(new:HTMLElement)} superClass
44
24
  */
45
25
  export const ComboBoxMixin = (superClass) =>
46
- class ComboBoxMixinClass extends ValidateMixin(ComboBoxBaseMixin(superClass)) {
26
+ class ComboBoxMixinClass extends ValidateMixin(ComboBoxItemsMixin(superClass)) {
47
27
  static get properties() {
48
28
  return {
49
29
  /**
@@ -63,17 +43,6 @@ export const ComboBoxMixin = (superClass) =>
63
43
  sync: true,
64
44
  },
65
45
 
66
- /**
67
- * A full set of items to filter the visible options from.
68
- * The items can be of either `String` or `Object` type.
69
- * @type {!Array<!ComboBoxItem | string> | undefined}
70
- */
71
- items: {
72
- type: Array,
73
- sync: true,
74
- observer: '_itemsChanged',
75
- },
76
-
77
46
  /**
78
47
  * If `true`, the user can input a value that is not present in the items list.
79
48
  * `value` property will be set to the input value in this case.
@@ -87,18 +56,6 @@ export const ComboBoxMixin = (superClass) =>
87
56
  value: false,
88
57
  },
89
58
 
90
- /**
91
- * A subset of items, filtered based on the user input. Filtered items
92
- * can be assigned directly to omit the internal filtering functionality.
93
- * The items can be of either `String` or `Object` type.
94
- * @type {!Array<!ComboBoxItem | string> | undefined}
95
- */
96
- filteredItems: {
97
- type: Array,
98
- observer: '_filteredItemsChanged',
99
- sync: true,
100
- },
101
-
102
59
  /**
103
60
  * When set to `true`, "loading" attribute is added to host and the overlay element.
104
61
  * @type {boolean}
@@ -110,17 +67,6 @@ export const ComboBoxMixin = (superClass) =>
110
67
  sync: true,
111
68
  },
112
69
 
113
- /**
114
- * Filtering string the user has typed into the input field.
115
- * @type {string}
116
- */
117
- filter: {
118
- type: String,
119
- value: '',
120
- notify: true,
121
- sync: true,
122
- },
123
-
124
70
  /**
125
71
  * The selected item from the `items` array.
126
72
  * @type {ComboBoxItem | string | undefined}
@@ -141,39 +87,6 @@ export const ComboBoxMixin = (superClass) =>
141
87
  type: Object,
142
88
  },
143
89
 
144
- /**
145
- * Path for label of the item. If `items` is an array of objects, the
146
- * `itemLabelPath` is used to fetch the displayed string label for each
147
- * item.
148
- *
149
- * The item label is also used for matching items when processing user
150
- * input, i.e., for filtering and selecting items.
151
- * @attr {string} item-label-path
152
- * @type {string}
153
- */
154
- itemLabelPath: {
155
- type: String,
156
- value: 'label',
157
- observer: '_itemLabelPathChanged',
158
- sync: true,
159
- },
160
-
161
- /**
162
- * Path for the value of the item. If `items` is an array of objects, the
163
- * `itemValuePath:` is used to fetch the string value for the selected
164
- * item.
165
- *
166
- * The item value is used in the `value` property of the combo box,
167
- * to provide the form value.
168
- * @attr {string} item-value-path
169
- * @type {string}
170
- */
171
- itemValuePath: {
172
- type: String,
173
- value: 'value',
174
- sync: true,
175
- },
176
-
177
90
  /**
178
91
  * Path for the id of the item. If `items` is an array of objects,
179
92
  * the `itemIdPath` is used to compare and identify the same item
@@ -245,10 +158,6 @@ export const ComboBoxMixin = (superClass) =>
245
158
  this._scroller[prop] = this[prop];
246
159
  }
247
160
  });
248
-
249
- if (props.has('filter')) {
250
- this._filterChanged(this.filter);
251
- }
252
161
  }
253
162
 
254
163
  /** @private */
@@ -301,28 +210,6 @@ export const ComboBoxMixin = (superClass) =>
301
210
  }
302
211
  }
303
212
 
304
- /**
305
- * Override method from `ComboBoxBaseMixin` to handle item label path.
306
- * @protected
307
- * @override
308
- */
309
- _getItemLabel(item) {
310
- let label = item && this.itemLabelPath ? get(this.itemLabelPath, item) : undefined;
311
- if (label === undefined || label === null) {
312
- label = item ? item.toString() : '';
313
- }
314
- return label;
315
- }
316
-
317
- /** @private */
318
- _getItemValue(item) {
319
- let value = item && this.itemValuePath ? get(this.itemValuePath, item) : undefined;
320
- if (value === undefined) {
321
- value = item ? item.toString() : '';
322
- }
323
- return value;
324
- }
325
-
326
213
  /**
327
214
  * Override method from `ComboBoxBaseMixin` to handle loading.
328
215
  * @protected
@@ -488,37 +375,6 @@ export const ComboBoxMixin = (superClass) =>
488
375
  this._clearFilter();
489
376
  }
490
377
 
491
- /**
492
- * Override an event listener from `ComboBoxBaseMixin` to handle
493
- * batched setting of both `opened` and `filter` properties.
494
- * @param {!Event} event
495
- * @protected
496
- * @override
497
- */
498
- _onInput(event) {
499
- const filter = this._inputElementValue;
500
-
501
- // When opening dropdown on user input, both `opened` and `filter` properties are set.
502
- // Perform a batched property update instead of relying on sync property observers.
503
- // This is necessary to avoid an extra data-provider request for loading first page.
504
- const props = {};
505
-
506
- if (this.filter === filter) {
507
- // Filter and input value might get out of sync, while keyboard navigating for example.
508
- // Afterwards, input value might be changed to the same value as used in filtering.
509
- // In situation like these, we need to make sure all the filter changes handlers are run.
510
- this._filterChanged(this.filter);
511
- } else {
512
- props.filter = filter;
513
- }
514
-
515
- if (!this.opened && !this._isClearButton(event) && !this.autoOpenDisabled) {
516
- props.opened = true;
517
- }
518
-
519
- this.setProperties(props);
520
- }
521
-
522
378
  /**
523
379
  * Override an event listener from `InputMixin`.
524
380
  * @param {!Event} event
@@ -531,30 +387,6 @@ export const ComboBoxMixin = (superClass) =>
531
387
  event.stopPropagation();
532
388
  }
533
389
 
534
- /** @private */
535
- _itemLabelPathChanged(itemLabelPath) {
536
- if (typeof itemLabelPath !== 'string') {
537
- console.error('You should set itemLabelPath to a valid string');
538
- }
539
- }
540
-
541
- /** @private */
542
- _filterChanged(filter) {
543
- // Scroll to the top of the list whenever the filter changes.
544
- this._scrollIntoView(0);
545
-
546
- this._focusedIndex = -1;
547
-
548
- if (this.items) {
549
- this.filteredItems = this._filterItems(this.items, filter);
550
- } else {
551
- // With certain use cases (e. g., external filtering), `items` are
552
- // undefined. Filtering is unnecessary per se, but the filteredItems
553
- // observer should still be invoked to update focused item.
554
- this._filteredItemsChanged(this.filteredItems);
555
- }
556
- }
557
-
558
390
  /**
559
391
  * Override method from `ComboBoxBaseMixin` to handle reverting value.
560
392
  * @protected
@@ -651,40 +483,6 @@ export const ComboBoxMixin = (superClass) =>
651
483
  }
652
484
  }
653
485
 
654
- /** @private */
655
- _itemsChanged(items, oldItems) {
656
- this._ensureItemsOrDataProvider(() => {
657
- this.items = oldItems;
658
- });
659
-
660
- if (items) {
661
- this.filteredItems = items.slice(0);
662
- } else if (oldItems) {
663
- // Only clear filteredItems if the component had items previously but got cleared
664
- this.filteredItems = null;
665
- }
666
- }
667
-
668
- /** @private */
669
- _filteredItemsChanged(filteredItems) {
670
- this._setDropdownItems(filteredItems);
671
- }
672
-
673
- /** @private */
674
- _filterItems(arr, filter) {
675
- if (!arr) {
676
- return arr;
677
- }
678
-
679
- const filteredItems = arr.filter((item) => {
680
- filter = filter ? filter.toString().toLowerCase() : '';
681
- // Check if item contains input value.
682
- return this._getItemLabel(item).toString().toLowerCase().indexOf(filter) > -1;
683
- });
684
-
685
- return filteredItems;
686
- }
687
-
688
486
  /** @private */
689
487
  _selectItemForValue(value) {
690
488
  const valueIndex = this.__getItemIndexByValue(this.filteredItems, value);
@@ -708,6 +506,7 @@ export const ComboBoxMixin = (superClass) =>
708
506
  * Override this method to show custom items.
709
507
  *
710
508
  * @protected
509
+ * @override
711
510
  */
712
511
  _setDropdownItems(newItems) {
713
512
  const oldItems = this._dropdownItems;
@@ -740,37 +539,6 @@ export const ComboBoxMixin = (superClass) =>
740
539
  }
741
540
  }
742
541
 
743
- /**
744
- * Returns the first item that matches the provided value.
745
- *
746
- * @private
747
- */
748
- __getItemIndexByValue(items, value) {
749
- if (!items || !isValidValue(value)) {
750
- return -1;
751
- }
752
-
753
- return findItemIndex(items, (item) => {
754
- return this._getItemValue(item) === value;
755
- });
756
- }
757
-
758
- /**
759
- * Returns the first item that matches the provided label.
760
- * Labels are matched against each other case insensitively.
761
- *
762
- * @private
763
- */
764
- __getItemIndexByLabel(items, label) {
765
- if (!items || !label) {
766
- return -1;
767
- }
768
-
769
- return findItemIndex(items, (item) => {
770
- return this._getItemLabel(item).toString().toLowerCase() === label.toString().toLowerCase();
771
- });
772
- }
773
-
774
542
  /**
775
543
  * Override method from `ComboBoxBaseMixin`.
776
544
  * @protected
@@ -22,21 +22,6 @@ export const ComboBoxOverlayMixin = (superClass) =>
22
22
  this.requiredVerticalSpace = 200;
23
23
  }
24
24
 
25
- /** @protected */
26
- connectedCallback() {
27
- super.connectedCallback();
28
-
29
- const hostDir = this._getHostDir();
30
- if (hostDir) {
31
- this.setAttribute('dir', hostDir);
32
- }
33
- }
34
-
35
- /** @protected */
36
- _getHostDir() {
37
- return this.owner && this.owner.getAttribute('dir');
38
- }
39
-
40
25
  /**
41
26
  * Override method inherited from `Overlay`
42
27
  * to not close on position target click.
@@ -66,16 +51,7 @@ export const ComboBoxOverlayMixin = (superClass) =>
66
51
 
67
52
  /** @protected */
68
53
  _updateOverlayWidth() {
69
- const propPrefix = this.localName;
70
- this.style.setProperty(`--_${propPrefix}-default-width`, `${this.positionTarget.offsetWidth}px`);
71
-
72
- const customWidth = getComputedStyle(this.owner).getPropertyValue(`--${propPrefix}-width`);
73
-
74
- if (customWidth === '') {
75
- this.style.removeProperty(`--${propPrefix}-width`);
76
- } else {
77
- this.style.setProperty(`--${propPrefix}-width`, customWidth);
78
- }
54
+ this.style.setProperty(`--_${this.localName}-default-width`, `${this.positionTarget.offsetWidth}px`);
79
55
  }
80
56
 
81
57
  /** @private */
@@ -7,11 +7,11 @@ 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
- import { overlayStyles } from '@vaadin/overlay/src/styles/vaadin-overlay-core-styles.js';
10
+ import { overlayStyles } from '@vaadin/overlay/src/styles/vaadin-overlay-base-styles.js';
11
11
  import { OverlayMixin } from '@vaadin/overlay/src/vaadin-overlay-mixin.js';
12
12
  import { LumoInjectionMixin } from '@vaadin/vaadin-themable-mixin/lumo-injection-mixin.js';
13
13
  import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
14
- import { comboBoxOverlayStyles } from './styles/vaadin-combo-box-overlay-core-styles.js';
14
+ import { comboBoxOverlayStyles } from './styles/vaadin-combo-box-overlay-base-styles.js';
15
15
  import { ComboBoxOverlayMixin } from './vaadin-combo-box-overlay-mixin.js';
16
16
 
17
17
  /**
@@ -45,8 +45,7 @@ export declare class ComboBoxScrollerMixinClass<TItem, TOwner> {
45
45
  owner: TOwner;
46
46
 
47
47
  /**
48
- * Set true to prevent the overlay from opening automatically.
49
- * @attr {boolean} auto-open-disabled
48
+ * Function used to render the content of every combo-box item.
50
49
  */
51
50
  renderer: ComboBoxItemRenderer<TItem, TOwner> | null | undefined;
52
51
 
@@ -234,6 +234,11 @@ export const ComboBoxScrollerMixin = (superClass) =>
234
234
  scrollTarget: this,
235
235
  scrollContainer: this.$.selector,
236
236
  reorderElements: true,
237
+ // Combo-box items have a CSS-defined minimum height, so the virtualizer's
238
+ // height placeholder logic can be disabled. This helps save reflows which
239
+ // might otherwise be triggered by this logic because it reads the row height
240
+ // right after updating the rows' content.
241
+ __disableHeightPlaceholder: true,
237
242
  });
238
243
  }
239
244
 
@@ -6,7 +6,7 @@
6
6
  import { html, LitElement } from 'lit';
7
7
  import { defineCustomElement } from '@vaadin/component-base/src/define.js';
8
8
  import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
9
- import { comboBoxScrollerStyles } from './styles/vaadin-combo-box-scroller-core-styles.js';
9
+ import { comboBoxScrollerStyles } from './styles/vaadin-combo-box-scroller-base-styles.js';
10
10
  import { ComboBoxScrollerMixin } from './vaadin-combo-box-scroller-mixin.js';
11
11
 
12
12
  /**
@@ -9,7 +9,6 @@ import type { FocusMixinClass } from '@vaadin/a11y-base/src/focus-mixin.js';
9
9
  import type { KeyboardMixinClass } from '@vaadin/a11y-base/src/keyboard-mixin.js';
10
10
  import type { DelegateStateMixinClass } from '@vaadin/component-base/src/delegate-state-mixin.js';
11
11
  import type { ElementMixinClass } from '@vaadin/component-base/src/element-mixin.js';
12
- import type { OverlayClassMixinClass } from '@vaadin/component-base/src/overlay-class-mixin.js';
13
12
  import type { ClearButtonMixinClass } from '@vaadin/field-base/src/clear-button-mixin.js';
14
13
  import type { FieldMixinClass } from '@vaadin/field-base/src/field-mixin.js';
15
14
  import type { InputConstraintsMixinClass } from '@vaadin/field-base/src/input-constraints-mixin.js';
@@ -22,6 +21,7 @@ import type { ThemableMixinClass } from '@vaadin/vaadin-themable-mixin/vaadin-th
22
21
  import type { ThemePropertyMixinClass } from '@vaadin/vaadin-themable-mixin/vaadin-theme-property-mixin.js';
23
22
  import type { ComboBoxBaseMixinClass } from './vaadin-combo-box-base-mixin.js';
24
23
  import type { ComboBoxDataProviderMixinClass } from './vaadin-combo-box-data-provider-mixin.js';
24
+ import type { ComboBoxItemsMixinClass } from './vaadin-combo-box-items-mixin.js';
25
25
  import type { ComboBoxMixinClass } from './vaadin-combo-box-mixin.js';
26
26
  import type { ComboBoxDefaultItem } from './vaadin-combo-box-mixin.js';
27
27
 
@@ -175,33 +175,45 @@ export interface ComboBoxEventMap<TItem> extends HTMLElementEventMap {
175
175
  * `--vaadin-combo-box-overlay-width` | Width of the overlay | `auto`
176
176
  * `--vaadin-combo-box-overlay-max-height` | Max height of the overlay | `65vh`
177
177
  *
178
- * `<vaadin-combo-box>` provides the same set of shadow DOM parts and state attributes as `<vaadin-text-field>`.
179
- * See [`<vaadin-text-field>`](#/elements/vaadin-text-field) for the styling documentation.
178
+ * The following shadow DOM parts are available for styling:
180
179
  *
181
- * In addition to `<vaadin-text-field>` parts, the following parts are available for theming:
180
+ * Part name | Description
181
+ * ---------------------|----------------
182
+ * `label` | The label element
183
+ * `input-field` | The element that wraps prefix, value and buttons
184
+ * `field-button` | Set on both clear and toggle buttons
185
+ * `clear-button` | The clear button
186
+ * `error-message` | The error message element
187
+ * `helper-text` | The helper text element wrapper
188
+ * `required-indicator` | The `required` state indicator element
189
+ * `toggle-button` | The toggle button
190
+ * `overlay` | The overlay container
191
+ * `content` | The overlay content
192
+ * `loader` | The loading indicator shown while loading items
182
193
  *
183
- * Part name | Description
184
- * ----------------|----------------
185
- * `toggle-button` | The toggle button
194
+ * The following state attributes are available for styling:
186
195
  *
187
- * In addition to `<vaadin-text-field>` state attributes, the following state attributes are available for theming:
188
- *
189
- * Attribute | Description | Part name
190
- * ----------|-------------|------------
191
- * `opened` | Set when the combo box dropdown is open | :host
192
- * `loading` | Set when new items are expected | :host
196
+ * Attribute | Description
197
+ * ---------------------|---------------------------------
198
+ * `disabled` | Set when the element is disabled
199
+ * `has-value` | Set when the element has a value
200
+ * `has-label` | Set when the element has a label
201
+ * `has-helper` | Set when the element has helper text or slot
202
+ * `has-error-message` | Set when the element has an error message
203
+ * `has-tooltip` | Set when the element has a slotted tooltip
204
+ * `invalid` | Set when the element is invalid
205
+ * `focused` | Set when the element is focused
206
+ * `focus-ring` | Set when the element is keyboard focused
207
+ * `readonly` | Set when the element is readonly
208
+ * `opened` | Set when the overlay is opened
209
+ * `loading` | Set when loading items from the data provider
193
210
  *
194
211
  * ### Internal components
195
212
  *
196
213
  * In addition to `<vaadin-combo-box>` itself, the following internal
197
214
  * components are themable:
198
215
  *
199
- * - `<vaadin-combo-box-overlay>` - has the same API as [`<vaadin-overlay>`](#/elements/vaadin-overlay).
200
216
  * - `<vaadin-combo-box-item>` - has the same API as [`<vaadin-item>`](#/elements/vaadin-item).
201
- * - [`<vaadin-input-container>`](#/elements/vaadin-input-container) - an internal element wrapping the input.
202
- *
203
- * Note: the `theme` attribute value set on `<vaadin-combo-box>` is
204
- * propagated to the internal components listed above.
205
217
  *
206
218
  * See [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.
207
219
  *
@@ -230,13 +242,13 @@ declare class ComboBox<TItem = ComboBoxDefaultItem> extends HTMLElement {
230
242
 
231
243
  interface ComboBox<TItem = ComboBoxDefaultItem>
232
244
  extends ComboBoxDataProviderMixinClass<TItem>,
245
+ ComboBoxItemsMixinClass<TItem>,
233
246
  ComboBoxMixinClass<TItem>,
234
247
  ComboBoxBaseMixinClass,
235
248
  ValidateMixinClass,
236
249
  PatternMixinClass,
237
250
  LabelMixinClass,
238
251
  KeyboardMixinClass,
239
- OverlayClassMixinClass,
240
252
  InputMixinClass,
241
253
  ClearButtonMixinClass,
242
254
  InputControlMixinClass,
@@ -20,7 +20,7 @@ import { PatternMixin } from '@vaadin/field-base/src/pattern-mixin.js';
20
20
  import { inputFieldShared } from '@vaadin/field-base/src/styles/input-field-shared-styles.js';
21
21
  import { LumoInjectionMixin } from '@vaadin/vaadin-themable-mixin/lumo-injection-mixin.js';
22
22
  import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
23
- import { comboBoxStyles } from './styles/vaadin-combo-box-core-styles.js';
23
+ import { comboBoxStyles } from './styles/vaadin-combo-box-base-styles.js';
24
24
  import { ComboBoxDataProviderMixin } from './vaadin-combo-box-data-provider-mixin.js';
25
25
  import { ComboBoxMixin } from './vaadin-combo-box-mixin.js';
26
26
 
@@ -107,33 +107,45 @@ import { ComboBoxMixin } from './vaadin-combo-box-mixin.js';
107
107
  * `--vaadin-combo-box-overlay-width` | Width of the overlay | `auto`
108
108
  * `--vaadin-combo-box-overlay-max-height` | Max height of the overlay | `65vh`
109
109
  *
110
- * `<vaadin-combo-box>` provides the same set of shadow DOM parts and state attributes as `<vaadin-text-field>`.
111
- * See [`<vaadin-text-field>`](#/elements/vaadin-text-field) for the styling documentation.
110
+ * The following shadow DOM parts are available for styling:
112
111
  *
113
- * In addition to `<vaadin-text-field>` parts, the following parts are available for theming:
112
+ * Part name | Description
113
+ * ---------------------|----------------
114
+ * `label` | The label element
115
+ * `input-field` | The element that wraps prefix, value and buttons
116
+ * `field-button` | Set on both clear and toggle buttons
117
+ * `clear-button` | The clear button
118
+ * `error-message` | The error message element
119
+ * `helper-text` | The helper text element wrapper
120
+ * `required-indicator` | The `required` state indicator element
121
+ * `toggle-button` | The toggle button
122
+ * `overlay` | The overlay container
123
+ * `content` | The overlay content
124
+ * `loader` | The loading indicator shown while loading items
114
125
  *
115
- * Part name | Description
116
- * ----------------|----------------
117
- * `toggle-button` | The toggle button
126
+ * The following state attributes are available for styling:
118
127
  *
119
- * In addition to `<vaadin-text-field>` state attributes, the following state attributes are available for theming:
120
- *
121
- * Attribute | Description | Part name
122
- * ----------|-------------|------------
123
- * `opened` | Set when the combo box dropdown is open | :host
124
- * `loading` | Set when new items are expected | :host
128
+ * Attribute | Description
129
+ * ---------------------|---------------------------------
130
+ * `disabled` | Set when the element is disabled
131
+ * `has-value` | Set when the element has a value
132
+ * `has-label` | Set when the element has a label
133
+ * `has-helper` | Set when the element has helper text or slot
134
+ * `has-error-message` | Set when the element has an error message
135
+ * `has-tooltip` | Set when the element has a slotted tooltip
136
+ * `invalid` | Set when the element is invalid
137
+ * `focused` | Set when the element is focused
138
+ * `focus-ring` | Set when the element is keyboard focused
139
+ * `readonly` | Set when the element is readonly
140
+ * `opened` | Set when the overlay is opened
141
+ * `loading` | Set when loading items from the data provider
125
142
  *
126
143
  * ### Internal components
127
144
  *
128
145
  * In addition to `<vaadin-combo-box>` itself, the following internal
129
146
  * components are themable:
130
147
  *
131
- * - `<vaadin-combo-box-overlay>` - has the same API as [`<vaadin-overlay>`](#/elements/vaadin-overlay).
132
148
  * - `<vaadin-combo-box-item>` - has the same API as [`<vaadin-item>`](#/elements/vaadin-item).
133
- * - [`<vaadin-input-container>`](#/elements/vaadin-input-container) - an internal element wrapping the input.
134
- *
135
- * Note: the `theme` attribute value set on `<vaadin-combo-box>` is
136
- * propagated to the internal components listed above.
137
149
  *
138
150
  * See [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.
139
151
  *
@@ -206,8 +218,8 @@ class ComboBox extends ComboBoxDataProviderMixin(
206
218
  >
207
219
  <slot name="prefix" slot="prefix"></slot>
208
220
  <slot name="input"></slot>
209
- <div id="clearButton" part="clear-button" slot="suffix" aria-hidden="true"></div>
210
- <div id="toggleButton" part="toggle-button" slot="suffix" aria-hidden="true"></div>
221
+ <div id="clearButton" part="field-button clear-button" slot="suffix" aria-hidden="true"></div>
222
+ <div id="toggleButton" part="field-button toggle-button" slot="suffix" aria-hidden="true"></div>
211
223
  </vaadin-input-container>
212
224
 
213
225
  <div part="helper-text">
@@ -221,13 +233,17 @@ class ComboBox extends ComboBoxDataProviderMixin(
221
233
 
222
234
  <vaadin-combo-box-overlay
223
235
  id="overlay"
236
+ exportparts="overlay, content, loader"
224
237
  .owner="${this}"
238
+ .dir="${this.dir}"
225
239
  .opened="${this._overlayOpened}"
226
240
  ?loading="${this.loading}"
227
241
  theme="${ifDefined(this._theme)}"
228
242
  .positionTarget="${this._positionTarget}"
229
243
  no-vertical-overlap
230
- ></vaadin-combo-box-overlay>
244
+ >
245
+ <slot name="overlay"></slot>
246
+ </vaadin-combo-box-overlay>
231
247
 
232
248
  <slot name="tooltip"></slot>
233
249
  `;
@@ -257,6 +273,15 @@ class ComboBox extends ComboBoxDataProviderMixin(
257
273
  this._toggleElement = this.$.toggleButton;
258
274
  }
259
275
 
276
+ /** @protected */
277
+ updated(props) {
278
+ super.updated(props);
279
+
280
+ if (props.has('dataProvider') || props.has('value')) {
281
+ this._warnDataProviderValue(this.dataProvider, this.value);
282
+ }
283
+ }
284
+
260
285
  /**
261
286
  * Override the method from `InputControlMixin`
262
287
  * to stop event propagation to prevent `ComboBoxMixin`
@@ -283,6 +308,22 @@ class ComboBox extends ComboBoxDataProviderMixin(
283
308
  super._onHostClick(event);
284
309
  }
285
310
  }
311
+
312
+ /** @private */
313
+ _warnDataProviderValue(dataProvider, value) {
314
+ if (dataProvider && value !== '' && (this.selectedItem === undefined || this.selectedItem === null)) {
315
+ const valueIndex = this.__getItemIndexByValue(this.filteredItems, value);
316
+ if (valueIndex < 0 || !this._getItemLabel(this.filteredItems[valueIndex])) {
317
+ console.warn(
318
+ 'Warning: unable to determine the label for the provided `value`. ' +
319
+ 'Nothing to display in the text field. This usually happens when ' +
320
+ 'setting an initial `value` before any items are returned from ' +
321
+ 'the `dataProvider` callback. Consider setting `selectedItem` ' +
322
+ 'instead of `value`',
323
+ );
324
+ }
325
+ }
326
+ }
286
327
  }
287
328
 
288
329
  defineCustomElement(ComboBox);
@@ -1,2 +1,2 @@
1
- import './theme/lumo/vaadin-combo-box.js';
1
+ import './src/vaadin-combo-box.js';
2
2
  export * from './src/vaadin-combo-box.js';