@vaadin/combo-box 25.3.0-rc1 → 25.4.0-alpha1

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.
@@ -155,6 +155,10 @@
155
155
  }
156
156
  ],
157
157
  "mixins": [
158
+ {
159
+ "name": "ComboBoxHighlightMixin",
160
+ "module": "src/vaadin-combo-box-highlight-mixin.js"
161
+ },
158
162
  {
159
163
  "name": "KeyboardMixin",
160
164
  "package": "@vaadin/a11y-base/src/keyboard-mixin.js"
@@ -306,6 +310,40 @@
306
310
  }
307
311
  ]
308
312
  },
313
+ {
314
+ "kind": "javascript-module",
315
+ "path": "src/vaadin-combo-box-highlight-mixin.js",
316
+ "declarations": [
317
+ {
318
+ "kind": "mixin",
319
+ "description": "A mixin that tracks which element of a combo box has the keyboard highlight\nwhile the DOM focus stays in the input. Only one element is highlighted at\na time.\n\nThe state is one of:\n\n- `{ type: 'none' }`: nothing is highlighted.\n- `{ type: 'item', index }`: the dropdown item at `index`.\n\nMixins applied on top can add more types by calling `_setHighlightState()`.",
320
+ "name": "ComboBoxHighlightMixin",
321
+ "members": [],
322
+ "attributes": [],
323
+ "parameters": [
324
+ {
325
+ "name": "superClass"
326
+ }
327
+ ],
328
+ "mixins": [
329
+ {
330
+ "name": "dedupeMixin",
331
+ "package": "@open-wc/dedupe-mixin"
332
+ }
333
+ ]
334
+ }
335
+ ],
336
+ "exports": [
337
+ {
338
+ "kind": "js",
339
+ "name": "ComboBoxHighlightMixin",
340
+ "declaration": {
341
+ "name": "ComboBoxHighlightMixin",
342
+ "module": "src/vaadin-combo-box-highlight-mixin.js"
343
+ }
344
+ }
345
+ ]
346
+ },
309
347
  {
310
348
  "kind": "javascript-module",
311
349
  "path": "src/vaadin-combo-box-item-mixin.js",
@@ -1781,7 +1819,7 @@
1781
1819
  "declarations": [
1782
1820
  {
1783
1821
  "kind": "class",
1784
- "description": "`<vaadin-combo-box>` is a web component for choosing a value from a filterable list of options\npresented in a dropdown overlay. The options can be provided as a list of strings or objects\nby setting [`items`](#/elements/vaadin-combo-box#property-items) property on the element.\n\n```html\n<vaadin-combo-box id=\"combo-box\"></vaadin-combo-box>\n```\n\n```js\ndocument.querySelector('#combo-box').items = ['apple', 'orange', 'banana'];\n```\n\nWhen the selected `value` is changed, a `value-changed` event is triggered.\n\n### Item rendering\n\nTo customize the content of the `<vaadin-combo-box-item>` elements placed in the dropdown, use\n[`renderer`](#/elements/vaadin-combo-box#property-renderer) property which accepts a function.\nThe renderer function is called with `root`, `comboBox`, and `model` as arguments.\n\nGenerate DOM content by using `model` object properties if needed, and append it to the `root`\nelement. The `comboBox` reference is provided to access the combo-box element state. Do not\nset combo-box properties in a `renderer` function.\n\n```js\nconst comboBox = document.querySelector('#combo-box');\ncomboBox.items = [{'label': 'Hydrogen', 'value': 'H'}];\ncomboBox.renderer = (root, comboBox, model) => {\n const item = model.item;\n root.innerHTML = `${model.index}: ${item.label} <b>${item.value}</b>`;\n};\n```\n\nRenderer is called on the opening of the combo-box and each time the related model is updated.\nBefore creating new content, it is recommended to check if there is already an existing DOM\nelement in `root` from a previous renderer call for reusing it. Even though combo-box uses\ninfinite scrolling, reducing DOM operations might improve performance.\n\nThe following properties are available in the `model` argument:\n\nProperty | Type | Description\n-----------|------------------|-------------\n`index` | Number | Index of the item in the `items` array\n`item` | String or Object | The item reference\n`selected` | Boolean | True when item is selected\n`focused` | Boolean | True when item is focused\n\n### Lazy Loading with Function Data Provider\n\nIn addition to assigning an array to the items property, you can alternatively use the\n[`dataProvider`](#/elements/vaadin-combo-box#property-dataProvider) function property.\nThe `<vaadin-combo-box>` calls this function lazily, only when it needs more data\nto be displayed.\n\n__Note that when using function data providers, the total number of items\nneeds to be set manually. The total number of items can be returned\nin the second argument of the data provider callback:__\n\n```js\ncomboBox.dataProvider = async (params, callback) => {\n const API = 'https://demo.vaadin.com/demo-data/1.0/filtered-countries';\n const { filter, page, pageSize } = params;\n const index = page * pageSize;\n\n const res = await fetch(`${API}?index=${index}&count=${pageSize}&filter=${filter}`);\n if (res.ok) {\n const { result, size } = await res.json();\n callback(result, size);\n }\n};\n```\n\n### Styling\n\nThe following shadow DOM parts are available for styling:\n\nPart name | Description\n---------------------|----------------\n`label` | The label element\n`input-field` | The element that wraps prefix, value and buttons\n`field-button` | Set on both clear and toggle buttons\n`clear-button` | The clear button\n`error-message` | The error message element\n`helper-text` | The helper text element wrapper\n`required-indicator` | The `required` state indicator element\n`toggle-button` | The toggle button\n`overlay` | The overlay container\n`content` | The overlay content\n`loader` | The loading indicator shown while loading items\n\nThe following state attributes are available for styling:\n\nAttribute | Description\n---------------------|---------------------------------\n`disabled` | Set when the element is disabled\n`has-value` | Set when the element has a value\n`has-label` | Set when the element has a label\n`has-helper` | Set when the element has helper text or slot\n`has-error-message` | Set when the element has an error message\n`has-tooltip` | Set when the element has a slotted tooltip\n`invalid` | Set when the element is invalid\n`focused` | Set when the element is focused\n`focus-ring` | Set when the element is keyboard focused\n`readonly` | Set when the element is readonly\n`opened` | Set when the overlay is opened\n`loading` | Set when loading items from the data provider\n\nThe following custom CSS properties are available for styling:\n\nCustom CSS property |\n:--------------------------------------------------|\n| `--vaadin-combo-box-overlay-max-height` |\n| `--vaadin-combo-box-overlay-width` |\n| `--vaadin-field-default-width` |\n| `--vaadin-input-field-background` |\n| `--vaadin-input-field-border-color` |\n| `--vaadin-input-field-border-radius` |\n| `--vaadin-input-field-border-width` |\n| `--vaadin-input-field-bottom-end-radius` |\n| `--vaadin-input-field-bottom-start-radius` |\n| `--vaadin-input-field-button-text-color` |\n| `--vaadin-input-field-container-gap` |\n| `--vaadin-input-field-disabled-background` |\n| `--vaadin-input-field-disabled-text-color` |\n| `--vaadin-input-field-error-color` |\n| `--vaadin-input-field-error-font-size` |\n| `--vaadin-input-field-error-font-weight` |\n| `--vaadin-input-field-error-line-height` |\n| `--vaadin-input-field-gap` |\n| `--vaadin-input-field-helper-color` |\n| `--vaadin-input-field-helper-font-size` |\n| `--vaadin-input-field-helper-font-weight` |\n| `--vaadin-input-field-helper-line-height` |\n| `--vaadin-input-field-label-color` |\n| `--vaadin-input-field-label-font-size` |\n| `--vaadin-input-field-label-font-weight` |\n| `--vaadin-input-field-label-line-height` |\n| `--vaadin-input-field-padding` |\n| `--vaadin-input-field-placeholder-color` |\n| `--vaadin-input-field-required-indicator` |\n| `--vaadin-input-field-required-indicator-color` |\n| `--vaadin-input-field-top-end-radius` |\n| `--vaadin-input-field-top-start-radius` |\n| `--vaadin-input-field-value-color` |\n| `--vaadin-input-field-value-font-size` |\n| `--vaadin-input-field-value-font-weight` |\n| `--vaadin-input-field-value-line-height` |\n| `--vaadin-item-overlay-padding` |\n\n### Internal components\n\nIn addition to `<vaadin-combo-box>` itself, the following internal\ncomponents are themable:\n\n- `<vaadin-combo-box-item>` - has the same API as [`<vaadin-item>`](#/elements/vaadin-item).\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.",
1822
+ "description": "`<vaadin-combo-box>` is a web component for choosing a value from a filterable list of options\npresented in a dropdown overlay. The options can be provided as a list of strings or objects\nby setting [`items`](#/elements/vaadin-combo-box#property-items) property on the element.\n\n```html\n<vaadin-combo-box id=\"combo-box\"></vaadin-combo-box>\n```\n\n```js\ndocument.querySelector('#combo-box').items = ['apple', 'orange', 'banana'];\n```\n\nWhen the selected `value` is changed, a `value-changed` event is triggered.\n\n### Item rendering\n\nTo customize the content of the `<vaadin-combo-box-item>` elements placed in the dropdown, use\n[`renderer`](#/elements/vaadin-combo-box#property-renderer) property which accepts a function.\nThe renderer function is called with `root`, `comboBox`, and `model` as arguments.\n\nGenerate DOM content by using `model` object properties if needed, and append it to the `root`\nelement. The `comboBox` reference is provided to access the combo-box element state. Do not\nset combo-box properties in a `renderer` function.\n\n```js\nconst comboBox = document.querySelector('#combo-box');\ncomboBox.items = [{'label': 'Hydrogen', 'value': 'H'}];\ncomboBox.renderer = (root, comboBox, model) => {\n const item = model.item;\n root.innerHTML = `${model.index}: ${item.label} <b>${item.value}</b>`;\n};\n```\n\nRenderer is called on the opening of the combo-box and each time the related model is updated.\nBefore creating new content, it is recommended to check if there is already an existing DOM\nelement in `root` from a previous renderer call for reusing it. Even though combo-box uses\ninfinite scrolling, reducing DOM operations might improve performance.\n\nThe following properties are available in the `model` argument:\n\nProperty | Type | Description\n-----------|------------------|-------------\n`index` | Number | Index of the item in the `items` array\n`item` | String or Object | The item reference\n`selected` | Boolean | True when item is selected\n`focused` | Boolean | True when item is focused\n\n### Lazy Loading with Function Data Provider\n\nIn addition to assigning an array to the items property, you can alternatively use the\n[`dataProvider`](#/elements/vaadin-combo-box#property-dataProvider) function property.\nThe `<vaadin-combo-box>` calls this function lazily, only when it needs more data\nto be displayed.\n\n__Note that when using function data providers, the total number of items\nneeds to be set manually. The total number of items can be returned\nin the second argument of the data provider callback:__\n\n```js\ncomboBox.dataProvider = async (params, callback) => {\n const API = 'https://demo.vaadin.com/demo-data/1.0/filtered-countries';\n const { filter, page, pageSize } = params;\n const index = page * pageSize;\n\n const res = await fetch(`${API}?index=${index}&count=${pageSize}&filter=${filter}`);\n if (res.ok) {\n const { result, size } = await res.json();\n callback(result, size);\n }\n};\n```\n\n### Styling\n\nThe following shadow DOM parts are available for styling:\n\nPart name | Description\n---------------------|----------------\n`label` | The label element\n`input-field` | The element that wraps prefix, value and buttons\n`field-button` | Set on both clear and toggle buttons\n`clear-button` | The clear button\n`error-message` | The error message element\n`helper-text` | The helper text element wrapper\n`required-indicator` | The `required` state indicator element\n`toggle-button` | The toggle button\n`overlay` | The overlay container\n`content` | The overlay content\n`loader` | The loading indicator shown while loading items\n\nThe following state attributes are available for styling:\n\nAttribute | Description\n---------------------|---------------------------------\n`disabled` | Set when the element is disabled\n`has-value` | Set when the element has a value\n`has-label` | Set when the element has a label\n`has-helper` | Set when the element has helper text or slot\n`has-error-message` | Set when the element has an error message\n`has-tooltip` | Set when the element has a slotted tooltip\n`invalid` | Set when the element is invalid\n`focused` | Set when the element is focused\n`focus-ring` | Set when the element is keyboard focused\n`readonly` | Set when the element is readonly\n`opened` | Set when the overlay is opened\n`loading` | Set when loading items from the data provider\n\nThe following custom CSS properties are available for styling:\n\nCustom CSS property |\n:--------------------------------------------------|\n| `--vaadin-combo-box-overlay-max-height` |\n| `--vaadin-combo-box-overlay-width` |\n| `--vaadin-field-default-width` |\n| `--vaadin-input-field-background` |\n| `--vaadin-input-field-border-color` |\n| `--vaadin-input-field-border-radius` |\n| `--vaadin-input-field-border-width` |\n| `--vaadin-input-field-bottom-end-radius` |\n| `--vaadin-input-field-bottom-start-radius` |\n| `--vaadin-input-field-button-text-color` |\n| `--vaadin-input-field-container-gap` |\n| `--vaadin-input-field-disabled-background` |\n| `--vaadin-input-field-disabled-text-color` |\n| `--vaadin-input-field-error-color` |\n| `--vaadin-input-field-error-font-size` |\n| `--vaadin-input-field-error-font-weight` |\n| `--vaadin-input-field-error-line-height` |\n| `--vaadin-input-field-gap` |\n| `--vaadin-input-field-helper-color` |\n| `--vaadin-input-field-helper-font-size` |\n| `--vaadin-input-field-helper-font-weight` |\n| `--vaadin-input-field-helper-line-height` |\n| `--vaadin-input-field-label-aside-gap` |\n| `--vaadin-input-field-label-aside-text-align` |\n| `--vaadin-input-field-label-aside-width` |\n| `--vaadin-input-field-label-color` |\n| `--vaadin-input-field-label-font-size` |\n| `--vaadin-input-field-label-font-weight` |\n| `--vaadin-input-field-label-line-height` |\n| `--vaadin-input-field-padding` |\n| `--vaadin-input-field-placeholder-color` |\n| `--vaadin-input-field-required-indicator` |\n| `--vaadin-input-field-required-indicator-color` |\n| `--vaadin-input-field-top-end-radius` |\n| `--vaadin-input-field-top-start-radius` |\n| `--vaadin-input-field-value-color` |\n| `--vaadin-input-field-value-font-size` |\n| `--vaadin-input-field-value-font-weight` |\n| `--vaadin-input-field-value-line-height` |\n| `--vaadin-item-overlay-padding` |\n\n### Internal components\n\nIn addition to `<vaadin-combo-box>` itself, the following internal\ncomponents are themable:\n\n- `<vaadin-combo-box-item>` - has the same API as [`<vaadin-item>`](#/elements/vaadin-item).\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.",
1785
1823
  "name": "ComboBox",
1786
1824
  "members": [
1787
1825
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vaadin/combo-box",
3
- "version": "25.3.0-rc1",
3
+ "version": "25.4.0-alpha1",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -36,22 +36,22 @@
36
36
  ],
37
37
  "dependencies": {
38
38
  "@open-wc/dedupe-mixin": "^1.3.0",
39
- "@vaadin/a11y-base": "25.3.0-rc1",
40
- "@vaadin/component-base": "25.3.0-rc1",
41
- "@vaadin/field-base": "25.3.0-rc1",
42
- "@vaadin/input-container": "25.3.0-rc1",
43
- "@vaadin/item": "25.3.0-rc1",
44
- "@vaadin/lit-renderer": "25.3.0-rc1",
45
- "@vaadin/overlay": "25.3.0-rc1",
46
- "@vaadin/vaadin-themable-mixin": "25.3.0-rc1",
39
+ "@vaadin/a11y-base": "25.4.0-alpha1",
40
+ "@vaadin/component-base": "25.4.0-alpha1",
41
+ "@vaadin/field-base": "25.4.0-alpha1",
42
+ "@vaadin/input-container": "25.4.0-alpha1",
43
+ "@vaadin/item": "25.4.0-alpha1",
44
+ "@vaadin/lit-renderer": "25.4.0-alpha1",
45
+ "@vaadin/overlay": "25.4.0-alpha1",
46
+ "@vaadin/vaadin-themable-mixin": "25.4.0-alpha1",
47
47
  "lit": "^3.0.0"
48
48
  },
49
49
  "devDependencies": {
50
- "@vaadin/aura": "25.3.0-rc1",
51
- "@vaadin/chai-plugins": "25.3.0-rc1",
52
- "@vaadin/test-runner-commands": "25.3.0-rc1",
50
+ "@vaadin/aura": "25.4.0-alpha1",
51
+ "@vaadin/chai-plugins": "25.4.0-alpha1",
52
+ "@vaadin/test-runner-commands": "25.4.0-alpha1",
53
53
  "@vaadin/testing-helpers": "^2.0.0",
54
- "@vaadin/vaadin-lumo-styles": "25.3.0-rc1",
54
+ "@vaadin/vaadin-lumo-styles": "25.4.0-alpha1",
55
55
  "sinon": "^22.0.0"
56
56
  },
57
57
  "customElements": "custom-elements.json",
@@ -59,5 +59,5 @@
59
59
  "web-types.json",
60
60
  "web-types.lit.json"
61
61
  ],
62
- "gitHead": "d4809590b2f61bd607e376ab3dec84f4bfb059a7"
62
+ "gitHead": "be38ec1866e96508f3f4591f95c949ef55903a34"
63
63
  }
@@ -9,10 +9,12 @@ 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 { InputMixinClass } from '@vaadin/field-base/src/input-mixin.js';
11
11
  import type { ValidateMixinClass } from '@vaadin/field-base/src/validate-mixin.js';
12
+ import type { ComboBoxHighlightMixinClass } from './vaadin-combo-box-highlight-mixin.js';
12
13
 
13
14
  export declare function ComboBoxBaseMixin<T extends Constructor<HTMLElement>>(
14
15
  base: T,
15
16
  ): Constructor<ComboBoxBaseMixinClass> &
17
+ Constructor<ComboBoxHighlightMixinClass> &
16
18
  Constructor<DisabledMixinClass> &
17
19
  Constructor<FocusMixinClass> &
18
20
  Constructor<InputMixinClass> &
@@ -10,10 +10,13 @@ import { KeyboardMixin } from '@vaadin/a11y-base/src/keyboard-mixin.js';
10
10
  import { isTouch } from '@vaadin/component-base/src/browser-utils.js';
11
11
  import { setOrRemoveAttribute } from '@vaadin/component-base/src/dom-utils.js';
12
12
  import { InputMixin } from '@vaadin/field-base/src/input-mixin.js';
13
+ import { ComboBoxHighlightMixin } from './vaadin-combo-box-highlight-mixin.js';
13
14
  import { ComboBoxPlaceholder } from './vaadin-combo-box-placeholder.js';
14
15
 
15
16
  export const ComboBoxBaseMixin = (superClass) =>
16
- class ComboBoxMixinBaseClass extends KeyboardMixin(InputMixin(DisabledMixin(FocusMixin(superClass)))) {
17
+ class ComboBoxMixinBaseClass extends ComboBoxHighlightMixin(
18
+ KeyboardMixin(InputMixin(DisabledMixin(FocusMixin(superClass)))),
19
+ ) {
17
20
  static get properties() {
18
21
  return {
19
22
  /**
@@ -46,16 +49,6 @@ export const ComboBoxBaseMixin = (superClass) =>
46
49
  reflectToAttribute: true,
47
50
  },
48
51
 
49
- /**
50
- * @protected
51
- */
52
- _focusedIndex: {
53
- type: Number,
54
- observer: '_focusedIndexChanged',
55
- value: -1,
56
- sync: true,
57
- },
58
-
59
52
  /**
60
53
  * @type {!HTMLElement | undefined}
61
54
  * @protected
@@ -183,9 +176,13 @@ export const ComboBoxBaseMixin = (superClass) =>
183
176
 
184
177
  // Update the scroller only once the overlay is actually opened, so that the
185
178
  // virtualizer does not measure and render items while the overlay is hidden.
186
- if (['_overlayOpened', '_dropdownItems', '_focusedIndex', '_theme'].some((prop) => props.has(prop))) {
179
+ if (['_overlayOpened', '_dropdownItems', '_highlightState', '_theme'].some((prop) => props.has(prop))) {
187
180
  this._updateScroller();
188
181
  }
182
+
183
+ if (props.has('_highlightState')) {
184
+ this._updateActiveDescendant();
185
+ }
189
186
  }
190
187
 
191
188
  /** @protected */
@@ -284,7 +281,7 @@ export const ComboBoxBaseMixin = (superClass) =>
284
281
  this._scroller.setProperties({
285
282
  items: opened || isClosing ? this._dropdownItems : [],
286
283
  opened,
287
- focusedIndex: this._focusedIndex,
284
+ focusedIndex: this._highlightedItemIndex,
288
285
  theme: this._theme,
289
286
  });
290
287
  }
@@ -306,26 +303,19 @@ export const ComboBoxBaseMixin = (superClass) =>
306
303
  }
307
304
  }
308
305
 
309
- /** @private */
310
- _focusedIndexChanged(index, oldIndex) {
311
- if (oldIndex === undefined) {
312
- return;
313
- }
314
- this._updateActiveDescendant(index);
315
- }
316
-
317
306
  /** @protected */
318
307
  _isInputFocused() {
319
308
  return this.inputElement && isElementFocused(this.inputElement);
320
309
  }
321
310
 
322
- /** @private */
323
- _updateActiveDescendant(index) {
311
+ /** @protected */
312
+ _updateActiveDescendant() {
324
313
  const input = this.inputElement;
325
314
  if (!input) {
326
315
  return;
327
316
  }
328
317
 
318
+ const index = this._highlightedItemIndex;
329
319
  const item = this._getItemElements().find((el) => el.index === index);
330
320
  setOrRemoveAttribute(input, 'aria-activedescendant', item?.id);
331
321
  }
@@ -502,11 +492,8 @@ export const ComboBoxBaseMixin = (superClass) =>
502
492
  /** @private */
503
493
  _onArrowDown() {
504
494
  if (this.opened) {
505
- const items = this._dropdownItems;
506
- if (items) {
507
- this._focusedIndex = Math.min(items.length - 1, this._focusedIndex + 1);
508
- this._prefillFocusedItemLabel();
509
- }
495
+ this._highlightNextItem();
496
+ this._prefillFocusedItemLabel();
510
497
  } else {
511
498
  this.open();
512
499
  }
@@ -515,15 +502,7 @@ export const ComboBoxBaseMixin = (superClass) =>
515
502
  /** @private */
516
503
  _onArrowUp() {
517
504
  if (this.opened) {
518
- if (this._focusedIndex > -1) {
519
- this._focusedIndex = Math.max(0, this._focusedIndex - 1);
520
- } else {
521
- const items = this._dropdownItems;
522
- if (items) {
523
- this._focusedIndex = items.length - 1;
524
- }
525
- }
526
-
505
+ this._highlightPrevItem();
527
506
  this._prefillFocusedItemLabel();
528
507
  } else {
529
508
  this.open();
@@ -532,9 +511,8 @@ export const ComboBoxBaseMixin = (superClass) =>
532
511
 
533
512
  /** @private */
534
513
  _prefillFocusedItemLabel() {
535
- if (this._focusedIndex > -1) {
536
- const focusedItem = this._dropdownItems[this._focusedIndex];
537
- this._inputElementValue = this._getItemLabel(focusedItem);
514
+ if (this._hasHighlightedItem) {
515
+ this._inputElementValue = this._getItemLabel(this._highlightedItem);
538
516
  this._markAllSelectionRange();
539
517
  }
540
518
  }
@@ -633,16 +611,16 @@ export const ComboBoxBaseMixin = (superClass) =>
633
611
  // The overlay is open or
634
612
  // The input value has changed but the change hasn't been committed, so cancel it.
635
613
  e.stopPropagation();
636
- this._focusedIndex = -1;
614
+ this._clearItemHighlight();
637
615
  this._onEscapeCancel();
638
616
  } else if (this.opened) {
639
617
  // Auto-open is enabled
640
618
  // The overlay is open
641
619
  e.stopPropagation();
642
620
 
643
- if (this._focusedIndex > -1) {
621
+ if (this._hasHighlightedItem) {
644
622
  // An item is focused, revert the input to the filtered value
645
- this._focusedIndex = -1;
623
+ this._clearItemHighlight();
646
624
  this._revertInputValue();
647
625
  } else {
648
626
  // No item is focused, cancel the change and close the overlay
@@ -766,7 +744,7 @@ export const ComboBoxBaseMixin = (superClass) =>
766
744
  }
767
745
 
768
746
  if (this.opened) {
769
- this._focusedIndex = this._dropdownItems.indexOf(e.detail.item);
747
+ this._highlightItem(e.detail.item);
770
748
  this.close();
771
749
  }
772
750
  }
@@ -47,7 +47,7 @@ export const ComboBoxFocusIndexMixin = (superClass) =>
47
47
  // wins. Rendering rows around `index` also lets placeholder rows fire
48
48
  // `index-requested`, loading any missing pages via the data-provider
49
49
  // chain.
50
- this._focusedIndex = index;
50
+ this._highlightItemAt(index);
51
51
  this._scrollIntoView(index, true);
52
52
 
53
53
  // A page-load may have kicked in during the scroll (placeholder
@@ -61,7 +61,7 @@ export const ComboBoxFocusIndexMixin = (superClass) =>
61
61
  delete this.__pendingFocusIndex;
62
62
  requestAnimationFrame(() => {
63
63
  if (this.isConnected) {
64
- this._updateActiveDescendant(index);
64
+ this._updateActiveDescendant();
65
65
  }
66
66
  });
67
67
  }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2015 - 2026 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+ import type { Constructor } from '@open-wc/dedupe-mixin';
7
+
8
+ /**
9
+ * A mixin that tracks which element of a combo box has the keyboard highlight
10
+ * while the DOM focus stays in the input. Only one element is highlighted at
11
+ * a time.
12
+ */
13
+ export declare function ComboBoxHighlightMixin<T extends Constructor<HTMLElement>>(
14
+ base: T,
15
+ ): Constructor<ComboBoxHighlightMixinClass> & T;
16
+
17
+ // Nothing to declare, all state and methods are considered internal
18
+ export declare class ComboBoxHighlightMixinClass {}
@@ -0,0 +1,109 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2015 - 2026 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+ import { dedupeMixin } from '@open-wc/dedupe-mixin';
7
+
8
+ /**
9
+ * A mixin that tracks which element of a combo box has the keyboard highlight
10
+ * while the DOM focus stays in the input. Only one element is highlighted at
11
+ * a time.
12
+ *
13
+ * The state is one of:
14
+ *
15
+ * - `{ type: 'none' }`: nothing is highlighted.
16
+ * - `{ type: 'item', index }`: the dropdown item at `index`.
17
+ *
18
+ * Mixins applied on top can add more types by calling `_setHighlightState()`.
19
+ */
20
+ const ComboBoxHighlightMixinImplementation = (superClass) =>
21
+ class ComboBoxHighlightMixinClass extends superClass {
22
+ static get properties() {
23
+ return {
24
+ /**
25
+ * The element that currently has the keyboard highlight.
26
+ * @protected
27
+ */
28
+ _highlightState: {
29
+ type: Object,
30
+ value: () => ({ type: 'none' }),
31
+ sync: true,
32
+ },
33
+ };
34
+ }
35
+
36
+ /** @protected */
37
+ get _hasHighlightedItem() {
38
+ return this._highlightState.type === 'item';
39
+ }
40
+
41
+ /** @protected */
42
+ get _highlightedItemIndex() {
43
+ return this._hasHighlightedItem ? this._highlightState.index : -1;
44
+ }
45
+
46
+ /** @protected */
47
+ get _highlightedItem() {
48
+ return this._hasHighlightedItem ? this._dropdownItems?.[this._highlightState.index] : undefined;
49
+ }
50
+
51
+ /** @protected */
52
+ _highlightNextItem() {
53
+ const items = this._dropdownItems;
54
+ if (items) {
55
+ this._highlightItemAt(Math.min(items.length - 1, this._highlightedItemIndex + 1));
56
+ }
57
+ }
58
+
59
+ /** @protected */
60
+ _highlightPrevItem() {
61
+ const items = this._dropdownItems;
62
+ if (items) {
63
+ this._highlightItemAt(
64
+ this._hasHighlightedItem ? Math.max(0, this._highlightState.index - 1) : items.length - 1,
65
+ );
66
+ }
67
+ }
68
+
69
+ /** @protected */
70
+ _highlightItem(item) {
71
+ const items = this._dropdownItems;
72
+ this._highlightItemAt(items ? items.indexOf(item) : -1);
73
+ }
74
+
75
+ /** @protected */
76
+ _highlightItemAt(index) {
77
+ if (index > -1) {
78
+ this._setHighlightState({ type: 'item', index });
79
+ } else {
80
+ this._clearItemHighlight();
81
+ }
82
+ }
83
+
84
+ /**
85
+ * @protected
86
+ */
87
+ _clearItemHighlight() {
88
+ if (this._hasHighlightedItem) {
89
+ this._clearHighlight();
90
+ }
91
+ }
92
+
93
+ /** @protected */
94
+ _clearHighlight() {
95
+ this._setHighlightState({ type: 'none' });
96
+ }
97
+
98
+ /**
99
+ * @protected
100
+ */
101
+ _setHighlightState(state) {
102
+ const oldState = this._highlightState;
103
+ if (state.type !== oldState.type || state.index !== oldState.index) {
104
+ this._highlightState = state;
105
+ }
106
+ }
107
+ };
108
+
109
+ export const ComboBoxHighlightMixin = dedupeMixin(ComboBoxHighlightMixinImplementation);
@@ -246,8 +246,8 @@ export const ComboBoxItemsMixin = (superClass) =>
246
246
  _onOpened() {
247
247
  super._onOpened();
248
248
 
249
- if (this.filter && this._focusedIndex === -1) {
250
- this._focusedIndex = this.__getItemIndexByFilter(this._dropdownItems);
249
+ if (this.filter && !this._hasHighlightedItem) {
250
+ this._highlightItemAt(this.__getItemIndexByFilter(this._dropdownItems));
251
251
  }
252
252
  }
253
253
 
@@ -309,7 +309,7 @@ export const ComboBoxItemsMixin = (superClass) =>
309
309
  // Scroll to the top of the list whenever the filter changes.
310
310
  this._scrollIntoView(0);
311
311
 
312
- this._focusedIndex = -1;
312
+ this._clearItemHighlight();
313
313
 
314
314
  if (this.items) {
315
315
  this.filteredItems = this._filterItems(this.items, filter);
@@ -348,37 +348,31 @@ export const ComboBoxItemsMixin = (superClass) =>
348
348
  * @protected
349
349
  */
350
350
  _setDropdownItems(newItems) {
351
- const oldItems = this._dropdownItems;
351
+ const highlightedItem = this._highlightedItem;
352
352
  this._dropdownItems = newItems;
353
353
 
354
- // Store the currently focused item if any. The focused index preserves
355
- // in the case when more filtered items are loading but it is reset
356
- // when the user types in a filter query.
357
- const focusedItem = oldItems ? oldItems[this._focusedIndex] : null;
354
+ this.__restoreItemHighlight(highlightedItem);
355
+ }
356
+
357
+ /**
358
+ * Highlights the given item again if it is still among the dropdown
359
+ * items, which keeps the highlight in place when more items are
360
+ * loading. Otherwise the item matching the filter is highlighted, or none.
361
+ * @private
362
+ */
363
+ __restoreItemHighlight(item) {
364
+ const items = this._dropdownItems;
358
365
 
359
- // When both the previously-focused entry and the new entry at the
366
+ // When both the previously highlighted entry and the new entry at the
360
367
  // same index are placeholders (e.g. the Flow connector mid-scroll
361
- // re-pushing `_setDropdownItems`), preserve `_focusedIndex` until
368
+ // re-pushing `_setDropdownItems`), preserve the highlight until
362
369
  // a follow-up call lands a real item at that position.
363
- if (
364
- oldItems &&
365
- oldItems[this._focusedIndex] instanceof ComboBoxPlaceholder &&
366
- newItems[this._focusedIndex] instanceof ComboBoxPlaceholder
367
- ) {
370
+ if (item instanceof ComboBoxPlaceholder && items[this._highlightedItemIndex] instanceof ComboBoxPlaceholder) {
368
371
  return;
369
372
  }
370
373
 
371
- // Try to first set focus on the item that had been focused before `newItems` were updated
372
- // if it is still present in the `newItems` array. Otherwise, set the focused index
373
- // depending on the selected item or the filter query.
374
- const focusedItemIndex = this.__getItemIndexByValue(newItems, this._getItemValue(focusedItem));
375
- if (focusedItemIndex > -1) {
376
- this._focusedIndex = focusedItemIndex;
377
- } else {
378
- // When the user filled in something that is different from the current value = filtering is enabled,
379
- // set the focused index to the item that matches the filter query.
380
- this._focusedIndex = this.__getItemIndexByFilter(newItems);
381
- }
374
+ const index = this.__getItemIndexByValue(items, this._getItemValue(item));
375
+ this._highlightItemAt(index > -1 ? index : this.__getItemIndexByFilter(items));
382
376
  }
383
377
 
384
378
  /** @private */
@@ -146,7 +146,7 @@ export const ComboBoxMixin = (superClass) =>
146
146
  */
147
147
  _hasValidInputValue() {
148
148
  const hasInvalidOption =
149
- this._focusedIndex < 0 &&
149
+ !this._hasHighlightedItem &&
150
150
  this._inputElementValue !== '' &&
151
151
  this._getItemLabel(this.selectedItem) !== this._inputElementValue;
152
152
 
@@ -236,14 +236,14 @@ export const ComboBoxMixin = (superClass) =>
236
236
  * @override
237
237
  */
238
238
  _commitValue() {
239
- if (this._focusedIndex > -1) {
240
- const focusedItem = this._dropdownItems[this._focusedIndex];
239
+ if (this._hasHighlightedItem) {
240
+ const focusedItem = this._highlightedItem;
241
241
  if (this.selectedItem !== focusedItem) {
242
242
  this.selectedItem = focusedItem;
243
243
  }
244
244
  // Make sure input field is updated in case value doesn't change (i.e. FOO -> foo)
245
245
  this._inputElementValue = this._getItemLabel(this.selectedItem);
246
- this._focusedIndex = -1;
246
+ this._clearItemHighlight();
247
247
  } else if (this._inputElementValue === '' || this._inputElementValue === undefined) {
248
248
  this.selectedItem = null;
249
249
 
@@ -227,6 +227,9 @@ export interface ComboBoxEventMap<TItem> extends HTMLElementEventMap {
227
227
  * | `--vaadin-input-field-helper-font-size` |
228
228
  * | `--vaadin-input-field-helper-font-weight` |
229
229
  * | `--vaadin-input-field-helper-line-height` |
230
+ * | `--vaadin-input-field-label-aside-gap` |
231
+ * | `--vaadin-input-field-label-aside-text-align` |
232
+ * | `--vaadin-input-field-label-aside-width` |
230
233
  * | `--vaadin-input-field-label-color` |
231
234
  * | `--vaadin-input-field-label-font-size` |
232
235
  * | `--vaadin-input-field-label-font-weight` |
@@ -159,6 +159,9 @@ import { ComboBoxMixin } from './vaadin-combo-box-mixin.js';
159
159
  * | `--vaadin-input-field-helper-font-size` |
160
160
  * | `--vaadin-input-field-helper-font-weight` |
161
161
  * | `--vaadin-input-field-helper-line-height` |
162
+ * | `--vaadin-input-field-label-aside-gap` |
163
+ * | `--vaadin-input-field-label-aside-text-align` |
164
+ * | `--vaadin-input-field-label-aside-width` |
162
165
  * | `--vaadin-input-field-label-color` |
163
166
  * | `--vaadin-input-field-label-font-size` |
164
167
  * | `--vaadin-input-field-label-font-weight` |
package/web-types.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/web-types",
3
3
  "name": "@vaadin/combo-box",
4
- "version": "25.3.0-rc1",
4
+ "version": "25.4.0-alpha1",
5
5
  "description-markup": "markdown",
6
6
  "contributions": {
7
7
  "html": {
8
8
  "elements": [
9
9
  {
10
10
  "name": "vaadin-combo-box",
11
- "description": "`<vaadin-combo-box>` is a web component for choosing a value from a filterable list of options\npresented in a dropdown overlay. The options can be provided as a list of strings or objects\nby setting [`items`](https://cdn.vaadin.com/vaadin-web-components/25.3.0-rc1/#/elements/vaadin-combo-box#property-items) property on the element.\n\n```html\n<vaadin-combo-box id=\"combo-box\"></vaadin-combo-box>\n```\n```js\ndocument.querySelector('#combo-box').items = ['apple', 'orange', 'banana'];\n```\n\nWhen the selected `value` is changed, a `value-changed` event is triggered.\n\n### Item rendering\n\nTo customize the content of the `<vaadin-combo-box-item>` elements placed in the dropdown, use\n[`renderer`](https://cdn.vaadin.com/vaadin-web-components/25.3.0-rc1/#/elements/vaadin-combo-box#property-renderer) property which accepts a function.\nThe renderer function is called with `root`, `comboBox`, and `model` as arguments.\n\nGenerate DOM content by using `model` object properties if needed, and append it to the `root`\nelement. The `comboBox` reference is provided to access the combo-box element state. Do not\nset combo-box properties in a `renderer` function.\n\n```js\nconst comboBox = document.querySelector('#combo-box');\ncomboBox.items = [{'label': 'Hydrogen', 'value': 'H'}];\ncomboBox.renderer = (root, comboBox, model) => {\n const item = model.item;\n root.innerHTML = `${model.index}: ${item.label} <b>${item.value}</b>`;\n};\n```\n\nRenderer is called on the opening of the combo-box and each time the related model is updated.\nBefore creating new content, it is recommended to check if there is already an existing DOM\nelement in `root` from a previous renderer call for reusing it. Even though combo-box uses\ninfinite scrolling, reducing DOM operations might improve performance.\n\nThe following properties are available in the `model` argument:\n\nProperty | Type | Description\n-----------|------------------|-------------\n`index` | Number | Index of the item in the `items` array\n`item` | String or Object | The item reference\n`selected` | Boolean | True when item is selected\n`focused` | Boolean | True when item is focused\n\n### Lazy Loading with Function Data Provider\n\nIn addition to assigning an array to the items property, you can alternatively use the\n[`dataProvider`](https://cdn.vaadin.com/vaadin-web-components/25.3.0-rc1/#/elements/vaadin-combo-box#property-dataProvider) function property.\nThe `<vaadin-combo-box>` calls this function lazily, only when it needs more data\nto be displayed.\n\n__Note that when using function data providers, the total number of items\nneeds to be set manually. The total number of items can be returned\nin the second argument of the data provider callback:__\n\n```js\ncomboBox.dataProvider = async (params, callback) => {\n const API = 'https://demo.vaadin.com/demo-data/1.0/filtered-countries';\n const { filter, page, pageSize } = params;\n const index = page * pageSize;\n\n const res = await fetch(`${API}?index=${index}&count=${pageSize}&filter=${filter}`);\n if (res.ok) {\n const { result, size } = await res.json();\n callback(result, size);\n }\n};\n```\n\n### Styling\n\nThe following shadow DOM parts are available for styling:\n\nPart name | Description\n---------------------|----------------\n`label` | The label element\n`input-field` | The element that wraps prefix, value and buttons\n`field-button` | Set on both clear and toggle buttons\n`clear-button` | The clear button\n`error-message` | The error message element\n`helper-text` | The helper text element wrapper\n`required-indicator` | The `required` state indicator element\n`toggle-button` | The toggle button\n`overlay` | The overlay container\n`content` | The overlay content\n`loader` | The loading indicator shown while loading items\n\nThe following state attributes are available for styling:\n\nAttribute | Description\n---------------------|---------------------------------\n`disabled` | Set when the element is disabled\n`has-value` | Set when the element has a value\n`has-label` | Set when the element has a label\n`has-helper` | Set when the element has helper text or slot\n`has-error-message` | Set when the element has an error message\n`has-tooltip` | Set when the element has a slotted tooltip\n`invalid` | Set when the element is invalid\n`focused` | Set when the element is focused\n`focus-ring` | Set when the element is keyboard focused\n`readonly` | Set when the element is readonly\n`opened` | Set when the overlay is opened\n`loading` | Set when loading items from the data provider\n\nThe following custom CSS properties are available for styling:\n\nCustom CSS property |\n:--------------------------------------------------|\n| `--vaadin-combo-box-overlay-max-height` |\n| `--vaadin-combo-box-overlay-width` |\n| `--vaadin-field-default-width` |\n| `--vaadin-input-field-background` |\n| `--vaadin-input-field-border-color` |\n| `--vaadin-input-field-border-radius` |\n| `--vaadin-input-field-border-width` |\n| `--vaadin-input-field-bottom-end-radius` |\n| `--vaadin-input-field-bottom-start-radius` |\n| `--vaadin-input-field-button-text-color` |\n| `--vaadin-input-field-container-gap` |\n| `--vaadin-input-field-disabled-background` |\n| `--vaadin-input-field-disabled-text-color` |\n| `--vaadin-input-field-error-color` |\n| `--vaadin-input-field-error-font-size` |\n| `--vaadin-input-field-error-font-weight` |\n| `--vaadin-input-field-error-line-height` |\n| `--vaadin-input-field-gap` |\n| `--vaadin-input-field-helper-color` |\n| `--vaadin-input-field-helper-font-size` |\n| `--vaadin-input-field-helper-font-weight` |\n| `--vaadin-input-field-helper-line-height` |\n| `--vaadin-input-field-label-color` |\n| `--vaadin-input-field-label-font-size` |\n| `--vaadin-input-field-label-font-weight` |\n| `--vaadin-input-field-label-line-height` |\n| `--vaadin-input-field-padding` |\n| `--vaadin-input-field-placeholder-color` |\n| `--vaadin-input-field-required-indicator` |\n| `--vaadin-input-field-required-indicator-color` |\n| `--vaadin-input-field-top-end-radius` |\n| `--vaadin-input-field-top-start-radius` |\n| `--vaadin-input-field-value-color` |\n| `--vaadin-input-field-value-font-size` |\n| `--vaadin-input-field-value-font-weight` |\n| `--vaadin-input-field-value-line-height` |\n| `--vaadin-item-overlay-padding` |\n\n### Internal components\n\nIn addition to `<vaadin-combo-box>` itself, the following internal\ncomponents are themable:\n\n- `<vaadin-combo-box-item>` - has the same API as [`<vaadin-item>`](https://cdn.vaadin.com/vaadin-web-components/25.3.0-rc1/#/elements/vaadin-item).\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.",
11
+ "description": "`<vaadin-combo-box>` is a web component for choosing a value from a filterable list of options\npresented in a dropdown overlay. The options can be provided as a list of strings or objects\nby setting [`items`](https://cdn.vaadin.com/vaadin-web-components/25.4.0-alpha1/#/elements/vaadin-combo-box#property-items) property on the element.\n\n```html\n<vaadin-combo-box id=\"combo-box\"></vaadin-combo-box>\n```\n```js\ndocument.querySelector('#combo-box').items = ['apple', 'orange', 'banana'];\n```\n\nWhen the selected `value` is changed, a `value-changed` event is triggered.\n\n### Item rendering\n\nTo customize the content of the `<vaadin-combo-box-item>` elements placed in the dropdown, use\n[`renderer`](https://cdn.vaadin.com/vaadin-web-components/25.4.0-alpha1/#/elements/vaadin-combo-box#property-renderer) property which accepts a function.\nThe renderer function is called with `root`, `comboBox`, and `model` as arguments.\n\nGenerate DOM content by using `model` object properties if needed, and append it to the `root`\nelement. The `comboBox` reference is provided to access the combo-box element state. Do not\nset combo-box properties in a `renderer` function.\n\n```js\nconst comboBox = document.querySelector('#combo-box');\ncomboBox.items = [{'label': 'Hydrogen', 'value': 'H'}];\ncomboBox.renderer = (root, comboBox, model) => {\n const item = model.item;\n root.innerHTML = `${model.index}: ${item.label} <b>${item.value}</b>`;\n};\n```\n\nRenderer is called on the opening of the combo-box and each time the related model is updated.\nBefore creating new content, it is recommended to check if there is already an existing DOM\nelement in `root` from a previous renderer call for reusing it. Even though combo-box uses\ninfinite scrolling, reducing DOM operations might improve performance.\n\nThe following properties are available in the `model` argument:\n\nProperty | Type | Description\n-----------|------------------|-------------\n`index` | Number | Index of the item in the `items` array\n`item` | String or Object | The item reference\n`selected` | Boolean | True when item is selected\n`focused` | Boolean | True when item is focused\n\n### Lazy Loading with Function Data Provider\n\nIn addition to assigning an array to the items property, you can alternatively use the\n[`dataProvider`](https://cdn.vaadin.com/vaadin-web-components/25.4.0-alpha1/#/elements/vaadin-combo-box#property-dataProvider) function property.\nThe `<vaadin-combo-box>` calls this function lazily, only when it needs more data\nto be displayed.\n\n__Note that when using function data providers, the total number of items\nneeds to be set manually. The total number of items can be returned\nin the second argument of the data provider callback:__\n\n```js\ncomboBox.dataProvider = async (params, callback) => {\n const API = 'https://demo.vaadin.com/demo-data/1.0/filtered-countries';\n const { filter, page, pageSize } = params;\n const index = page * pageSize;\n\n const res = await fetch(`${API}?index=${index}&count=${pageSize}&filter=${filter}`);\n if (res.ok) {\n const { result, size } = await res.json();\n callback(result, size);\n }\n};\n```\n\n### Styling\n\nThe following shadow DOM parts are available for styling:\n\nPart name | Description\n---------------------|----------------\n`label` | The label element\n`input-field` | The element that wraps prefix, value and buttons\n`field-button` | Set on both clear and toggle buttons\n`clear-button` | The clear button\n`error-message` | The error message element\n`helper-text` | The helper text element wrapper\n`required-indicator` | The `required` state indicator element\n`toggle-button` | The toggle button\n`overlay` | The overlay container\n`content` | The overlay content\n`loader` | The loading indicator shown while loading items\n\nThe following state attributes are available for styling:\n\nAttribute | Description\n---------------------|---------------------------------\n`disabled` | Set when the element is disabled\n`has-value` | Set when the element has a value\n`has-label` | Set when the element has a label\n`has-helper` | Set when the element has helper text or slot\n`has-error-message` | Set when the element has an error message\n`has-tooltip` | Set when the element has a slotted tooltip\n`invalid` | Set when the element is invalid\n`focused` | Set when the element is focused\n`focus-ring` | Set when the element is keyboard focused\n`readonly` | Set when the element is readonly\n`opened` | Set when the overlay is opened\n`loading` | Set when loading items from the data provider\n\nThe following custom CSS properties are available for styling:\n\nCustom CSS property |\n:--------------------------------------------------|\n| `--vaadin-combo-box-overlay-max-height` |\n| `--vaadin-combo-box-overlay-width` |\n| `--vaadin-field-default-width` |\n| `--vaadin-input-field-background` |\n| `--vaadin-input-field-border-color` |\n| `--vaadin-input-field-border-radius` |\n| `--vaadin-input-field-border-width` |\n| `--vaadin-input-field-bottom-end-radius` |\n| `--vaadin-input-field-bottom-start-radius` |\n| `--vaadin-input-field-button-text-color` |\n| `--vaadin-input-field-container-gap` |\n| `--vaadin-input-field-disabled-background` |\n| `--vaadin-input-field-disabled-text-color` |\n| `--vaadin-input-field-error-color` |\n| `--vaadin-input-field-error-font-size` |\n| `--vaadin-input-field-error-font-weight` |\n| `--vaadin-input-field-error-line-height` |\n| `--vaadin-input-field-gap` |\n| `--vaadin-input-field-helper-color` |\n| `--vaadin-input-field-helper-font-size` |\n| `--vaadin-input-field-helper-font-weight` |\n| `--vaadin-input-field-helper-line-height` |\n| `--vaadin-input-field-label-aside-gap` |\n| `--vaadin-input-field-label-aside-text-align` |\n| `--vaadin-input-field-label-aside-width` |\n| `--vaadin-input-field-label-color` |\n| `--vaadin-input-field-label-font-size` |\n| `--vaadin-input-field-label-font-weight` |\n| `--vaadin-input-field-label-line-height` |\n| `--vaadin-input-field-padding` |\n| `--vaadin-input-field-placeholder-color` |\n| `--vaadin-input-field-required-indicator` |\n| `--vaadin-input-field-required-indicator-color` |\n| `--vaadin-input-field-top-end-radius` |\n| `--vaadin-input-field-top-start-radius` |\n| `--vaadin-input-field-value-color` |\n| `--vaadin-input-field-value-font-size` |\n| `--vaadin-input-field-value-font-weight` |\n| `--vaadin-input-field-value-line-height` |\n| `--vaadin-item-overlay-padding` |\n\n### Internal components\n\nIn addition to `<vaadin-combo-box>` itself, the following internal\ncomponents are themable:\n\n- `<vaadin-combo-box-item>` - has the same API as [`<vaadin-item>`](https://cdn.vaadin.com/vaadin-web-components/25.4.0-alpha1/#/elements/vaadin-item).\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.",
12
12
  "attributes": [
13
13
  {
14
14
  "name": "accessible-description-ref",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/web-types",
3
3
  "name": "@vaadin/combo-box",
4
- "version": "25.3.0-rc1",
4
+ "version": "25.4.0-alpha1",
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-combo-box",
19
- "description": "`<vaadin-combo-box>` is a web component for choosing a value from a filterable list of options\npresented in a dropdown overlay. The options can be provided as a list of strings or objects\nby setting [`items`](https://cdn.vaadin.com/vaadin-web-components/25.3.0-rc1/#/elements/vaadin-combo-box#property-items) property on the element.\n\n```html\n<vaadin-combo-box id=\"combo-box\"></vaadin-combo-box>\n```\n```js\ndocument.querySelector('#combo-box').items = ['apple', 'orange', 'banana'];\n```\n\nWhen the selected `value` is changed, a `value-changed` event is triggered.\n\n### Item rendering\n\nTo customize the content of the `<vaadin-combo-box-item>` elements placed in the dropdown, use\n[`renderer`](https://cdn.vaadin.com/vaadin-web-components/25.3.0-rc1/#/elements/vaadin-combo-box#property-renderer) property which accepts a function.\nThe renderer function is called with `root`, `comboBox`, and `model` as arguments.\n\nGenerate DOM content by using `model` object properties if needed, and append it to the `root`\nelement. The `comboBox` reference is provided to access the combo-box element state. Do not\nset combo-box properties in a `renderer` function.\n\n```js\nconst comboBox = document.querySelector('#combo-box');\ncomboBox.items = [{'label': 'Hydrogen', 'value': 'H'}];\ncomboBox.renderer = (root, comboBox, model) => {\n const item = model.item;\n root.innerHTML = `${model.index}: ${item.label} <b>${item.value}</b>`;\n};\n```\n\nRenderer is called on the opening of the combo-box and each time the related model is updated.\nBefore creating new content, it is recommended to check if there is already an existing DOM\nelement in `root` from a previous renderer call for reusing it. Even though combo-box uses\ninfinite scrolling, reducing DOM operations might improve performance.\n\nThe following properties are available in the `model` argument:\n\nProperty | Type | Description\n-----------|------------------|-------------\n`index` | Number | Index of the item in the `items` array\n`item` | String or Object | The item reference\n`selected` | Boolean | True when item is selected\n`focused` | Boolean | True when item is focused\n\n### Lazy Loading with Function Data Provider\n\nIn addition to assigning an array to the items property, you can alternatively use the\n[`dataProvider`](https://cdn.vaadin.com/vaadin-web-components/25.3.0-rc1/#/elements/vaadin-combo-box#property-dataProvider) function property.\nThe `<vaadin-combo-box>` calls this function lazily, only when it needs more data\nto be displayed.\n\n__Note that when using function data providers, the total number of items\nneeds to be set manually. The total number of items can be returned\nin the second argument of the data provider callback:__\n\n```js\ncomboBox.dataProvider = async (params, callback) => {\n const API = 'https://demo.vaadin.com/demo-data/1.0/filtered-countries';\n const { filter, page, pageSize } = params;\n const index = page * pageSize;\n\n const res = await fetch(`${API}?index=${index}&count=${pageSize}&filter=${filter}`);\n if (res.ok) {\n const { result, size } = await res.json();\n callback(result, size);\n }\n};\n```\n\n### Styling\n\nThe following shadow DOM parts are available for styling:\n\nPart name | Description\n---------------------|----------------\n`label` | The label element\n`input-field` | The element that wraps prefix, value and buttons\n`field-button` | Set on both clear and toggle buttons\n`clear-button` | The clear button\n`error-message` | The error message element\n`helper-text` | The helper text element wrapper\n`required-indicator` | The `required` state indicator element\n`toggle-button` | The toggle button\n`overlay` | The overlay container\n`content` | The overlay content\n`loader` | The loading indicator shown while loading items\n\nThe following state attributes are available for styling:\n\nAttribute | Description\n---------------------|---------------------------------\n`disabled` | Set when the element is disabled\n`has-value` | Set when the element has a value\n`has-label` | Set when the element has a label\n`has-helper` | Set when the element has helper text or slot\n`has-error-message` | Set when the element has an error message\n`has-tooltip` | Set when the element has a slotted tooltip\n`invalid` | Set when the element is invalid\n`focused` | Set when the element is focused\n`focus-ring` | Set when the element is keyboard focused\n`readonly` | Set when the element is readonly\n`opened` | Set when the overlay is opened\n`loading` | Set when loading items from the data provider\n\nThe following custom CSS properties are available for styling:\n\nCustom CSS property |\n:--------------------------------------------------|\n| `--vaadin-combo-box-overlay-max-height` |\n| `--vaadin-combo-box-overlay-width` |\n| `--vaadin-field-default-width` |\n| `--vaadin-input-field-background` |\n| `--vaadin-input-field-border-color` |\n| `--vaadin-input-field-border-radius` |\n| `--vaadin-input-field-border-width` |\n| `--vaadin-input-field-bottom-end-radius` |\n| `--vaadin-input-field-bottom-start-radius` |\n| `--vaadin-input-field-button-text-color` |\n| `--vaadin-input-field-container-gap` |\n| `--vaadin-input-field-disabled-background` |\n| `--vaadin-input-field-disabled-text-color` |\n| `--vaadin-input-field-error-color` |\n| `--vaadin-input-field-error-font-size` |\n| `--vaadin-input-field-error-font-weight` |\n| `--vaadin-input-field-error-line-height` |\n| `--vaadin-input-field-gap` |\n| `--vaadin-input-field-helper-color` |\n| `--vaadin-input-field-helper-font-size` |\n| `--vaadin-input-field-helper-font-weight` |\n| `--vaadin-input-field-helper-line-height` |\n| `--vaadin-input-field-label-color` |\n| `--vaadin-input-field-label-font-size` |\n| `--vaadin-input-field-label-font-weight` |\n| `--vaadin-input-field-label-line-height` |\n| `--vaadin-input-field-padding` |\n| `--vaadin-input-field-placeholder-color` |\n| `--vaadin-input-field-required-indicator` |\n| `--vaadin-input-field-required-indicator-color` |\n| `--vaadin-input-field-top-end-radius` |\n| `--vaadin-input-field-top-start-radius` |\n| `--vaadin-input-field-value-color` |\n| `--vaadin-input-field-value-font-size` |\n| `--vaadin-input-field-value-font-weight` |\n| `--vaadin-input-field-value-line-height` |\n| `--vaadin-item-overlay-padding` |\n\n### Internal components\n\nIn addition to `<vaadin-combo-box>` itself, the following internal\ncomponents are themable:\n\n- `<vaadin-combo-box-item>` - has the same API as [`<vaadin-item>`](https://cdn.vaadin.com/vaadin-web-components/25.3.0-rc1/#/elements/vaadin-item).\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.",
19
+ "description": "`<vaadin-combo-box>` is a web component for choosing a value from a filterable list of options\npresented in a dropdown overlay. The options can be provided as a list of strings or objects\nby setting [`items`](https://cdn.vaadin.com/vaadin-web-components/25.4.0-alpha1/#/elements/vaadin-combo-box#property-items) property on the element.\n\n```html\n<vaadin-combo-box id=\"combo-box\"></vaadin-combo-box>\n```\n```js\ndocument.querySelector('#combo-box').items = ['apple', 'orange', 'banana'];\n```\n\nWhen the selected `value` is changed, a `value-changed` event is triggered.\n\n### Item rendering\n\nTo customize the content of the `<vaadin-combo-box-item>` elements placed in the dropdown, use\n[`renderer`](https://cdn.vaadin.com/vaadin-web-components/25.4.0-alpha1/#/elements/vaadin-combo-box#property-renderer) property which accepts a function.\nThe renderer function is called with `root`, `comboBox`, and `model` as arguments.\n\nGenerate DOM content by using `model` object properties if needed, and append it to the `root`\nelement. The `comboBox` reference is provided to access the combo-box element state. Do not\nset combo-box properties in a `renderer` function.\n\n```js\nconst comboBox = document.querySelector('#combo-box');\ncomboBox.items = [{'label': 'Hydrogen', 'value': 'H'}];\ncomboBox.renderer = (root, comboBox, model) => {\n const item = model.item;\n root.innerHTML = `${model.index}: ${item.label} <b>${item.value}</b>`;\n};\n```\n\nRenderer is called on the opening of the combo-box and each time the related model is updated.\nBefore creating new content, it is recommended to check if there is already an existing DOM\nelement in `root` from a previous renderer call for reusing it. Even though combo-box uses\ninfinite scrolling, reducing DOM operations might improve performance.\n\nThe following properties are available in the `model` argument:\n\nProperty | Type | Description\n-----------|------------------|-------------\n`index` | Number | Index of the item in the `items` array\n`item` | String or Object | The item reference\n`selected` | Boolean | True when item is selected\n`focused` | Boolean | True when item is focused\n\n### Lazy Loading with Function Data Provider\n\nIn addition to assigning an array to the items property, you can alternatively use the\n[`dataProvider`](https://cdn.vaadin.com/vaadin-web-components/25.4.0-alpha1/#/elements/vaadin-combo-box#property-dataProvider) function property.\nThe `<vaadin-combo-box>` calls this function lazily, only when it needs more data\nto be displayed.\n\n__Note that when using function data providers, the total number of items\nneeds to be set manually. The total number of items can be returned\nin the second argument of the data provider callback:__\n\n```js\ncomboBox.dataProvider = async (params, callback) => {\n const API = 'https://demo.vaadin.com/demo-data/1.0/filtered-countries';\n const { filter, page, pageSize } = params;\n const index = page * pageSize;\n\n const res = await fetch(`${API}?index=${index}&count=${pageSize}&filter=${filter}`);\n if (res.ok) {\n const { result, size } = await res.json();\n callback(result, size);\n }\n};\n```\n\n### Styling\n\nThe following shadow DOM parts are available for styling:\n\nPart name | Description\n---------------------|----------------\n`label` | The label element\n`input-field` | The element that wraps prefix, value and buttons\n`field-button` | Set on both clear and toggle buttons\n`clear-button` | The clear button\n`error-message` | The error message element\n`helper-text` | The helper text element wrapper\n`required-indicator` | The `required` state indicator element\n`toggle-button` | The toggle button\n`overlay` | The overlay container\n`content` | The overlay content\n`loader` | The loading indicator shown while loading items\n\nThe following state attributes are available for styling:\n\nAttribute | Description\n---------------------|---------------------------------\n`disabled` | Set when the element is disabled\n`has-value` | Set when the element has a value\n`has-label` | Set when the element has a label\n`has-helper` | Set when the element has helper text or slot\n`has-error-message` | Set when the element has an error message\n`has-tooltip` | Set when the element has a slotted tooltip\n`invalid` | Set when the element is invalid\n`focused` | Set when the element is focused\n`focus-ring` | Set when the element is keyboard focused\n`readonly` | Set when the element is readonly\n`opened` | Set when the overlay is opened\n`loading` | Set when loading items from the data provider\n\nThe following custom CSS properties are available for styling:\n\nCustom CSS property |\n:--------------------------------------------------|\n| `--vaadin-combo-box-overlay-max-height` |\n| `--vaadin-combo-box-overlay-width` |\n| `--vaadin-field-default-width` |\n| `--vaadin-input-field-background` |\n| `--vaadin-input-field-border-color` |\n| `--vaadin-input-field-border-radius` |\n| `--vaadin-input-field-border-width` |\n| `--vaadin-input-field-bottom-end-radius` |\n| `--vaadin-input-field-bottom-start-radius` |\n| `--vaadin-input-field-button-text-color` |\n| `--vaadin-input-field-container-gap` |\n| `--vaadin-input-field-disabled-background` |\n| `--vaadin-input-field-disabled-text-color` |\n| `--vaadin-input-field-error-color` |\n| `--vaadin-input-field-error-font-size` |\n| `--vaadin-input-field-error-font-weight` |\n| `--vaadin-input-field-error-line-height` |\n| `--vaadin-input-field-gap` |\n| `--vaadin-input-field-helper-color` |\n| `--vaadin-input-field-helper-font-size` |\n| `--vaadin-input-field-helper-font-weight` |\n| `--vaadin-input-field-helper-line-height` |\n| `--vaadin-input-field-label-aside-gap` |\n| `--vaadin-input-field-label-aside-text-align` |\n| `--vaadin-input-field-label-aside-width` |\n| `--vaadin-input-field-label-color` |\n| `--vaadin-input-field-label-font-size` |\n| `--vaadin-input-field-label-font-weight` |\n| `--vaadin-input-field-label-line-height` |\n| `--vaadin-input-field-padding` |\n| `--vaadin-input-field-placeholder-color` |\n| `--vaadin-input-field-required-indicator` |\n| `--vaadin-input-field-required-indicator-color` |\n| `--vaadin-input-field-top-end-radius` |\n| `--vaadin-input-field-top-start-radius` |\n| `--vaadin-input-field-value-color` |\n| `--vaadin-input-field-value-font-size` |\n| `--vaadin-input-field-value-font-weight` |\n| `--vaadin-input-field-value-line-height` |\n| `--vaadin-item-overlay-padding` |\n\n### Internal components\n\nIn addition to `<vaadin-combo-box>` itself, the following internal\ncomponents are themable:\n\n- `<vaadin-combo-box-item>` - has the same API as [`<vaadin-item>`](https://cdn.vaadin.com/vaadin-web-components/25.4.0-alpha1/#/elements/vaadin-item).\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.",
20
20
  "extension": true,
21
21
  "attributes": [
22
22
  {