@vaadin/combo-box 25.3.2 → 25.4.0-alpha2
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/custom-elements.json +39 -1
- package/package.json +14 -14
- package/src/vaadin-combo-box-base-mixin.d.ts +2 -0
- package/src/vaadin-combo-box-base-mixin.js +24 -44
- package/src/vaadin-combo-box-focus-index-mixin.js +2 -2
- package/src/vaadin-combo-box-highlight-mixin.d.ts +18 -0
- package/src/vaadin-combo-box-highlight-mixin.js +109 -0
- package/src/vaadin-combo-box-items-mixin.js +24 -37
- package/src/vaadin-combo-box-mixin.js +4 -4
- package/src/vaadin-combo-box-scroller-mixin.js +5 -0
- package/src/vaadin-combo-box.d.ts +4 -0
- package/src/vaadin-combo-box.js +4 -0
- package/web-types.json +2 -2
- package/web-types.lit.json +2 -2
package/custom-elements.json
CHANGED
|
@@ -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-height` |\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
|
+
"version": "25.4.0-alpha2",
|
|
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": "
|
|
40
|
-
"@vaadin/component-base": "
|
|
41
|
-
"@vaadin/field-base": "
|
|
42
|
-
"@vaadin/input-container": "
|
|
43
|
-
"@vaadin/item": "
|
|
44
|
-
"@vaadin/lit-renderer": "
|
|
45
|
-
"@vaadin/overlay": "
|
|
46
|
-
"@vaadin/vaadin-themable-mixin": "
|
|
39
|
+
"@vaadin/a11y-base": "25.4.0-alpha2",
|
|
40
|
+
"@vaadin/component-base": "25.4.0-alpha2",
|
|
41
|
+
"@vaadin/field-base": "25.4.0-alpha2",
|
|
42
|
+
"@vaadin/input-container": "25.4.0-alpha2",
|
|
43
|
+
"@vaadin/item": "25.4.0-alpha2",
|
|
44
|
+
"@vaadin/lit-renderer": "25.4.0-alpha2",
|
|
45
|
+
"@vaadin/overlay": "25.4.0-alpha2",
|
|
46
|
+
"@vaadin/vaadin-themable-mixin": "25.4.0-alpha2",
|
|
47
47
|
"lit": "^3.0.0"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
|
-
"@vaadin/aura": "
|
|
51
|
-
"@vaadin/chai-plugins": "
|
|
52
|
-
"@vaadin/test-runner-commands": "
|
|
50
|
+
"@vaadin/aura": "25.4.0-alpha2",
|
|
51
|
+
"@vaadin/chai-plugins": "25.4.0-alpha2",
|
|
52
|
+
"@vaadin/test-runner-commands": "25.4.0-alpha2",
|
|
53
53
|
"@vaadin/testing-helpers": "^2.0.0",
|
|
54
|
-
"@vaadin/vaadin-lumo-styles": "
|
|
54
|
+
"@vaadin/vaadin-lumo-styles": "25.4.0-alpha2",
|
|
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": "
|
|
62
|
+
"gitHead": "213f8b55112558d2f976d8730fe44370ca868333"
|
|
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
|
|
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,15 @@ 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', '
|
|
179
|
+
if (['_overlayOpened', '_dropdownItems', '_highlightState', '_theme'].some((prop) => props.has(prop))) {
|
|
187
180
|
this._updateScroller();
|
|
188
181
|
}
|
|
182
|
+
|
|
183
|
+
// An item can be highlighted while the overlay is closed, e.g. when filtering
|
|
184
|
+
// on input. Reference it once the overlay is opened.
|
|
185
|
+
if (props.has('_highlightState') || (props.has('_overlayOpened') && this._overlayOpened)) {
|
|
186
|
+
this._updateActiveDescendant();
|
|
187
|
+
}
|
|
189
188
|
}
|
|
190
189
|
|
|
191
190
|
/** @protected */
|
|
@@ -284,7 +283,7 @@ export const ComboBoxBaseMixin = (superClass) =>
|
|
|
284
283
|
this._scroller.setProperties({
|
|
285
284
|
items: opened || isClosing ? this._dropdownItems : [],
|
|
286
285
|
opened,
|
|
287
|
-
focusedIndex: this.
|
|
286
|
+
focusedIndex: this._highlightedItemIndex,
|
|
288
287
|
theme: this._theme,
|
|
289
288
|
});
|
|
290
289
|
}
|
|
@@ -306,26 +305,19 @@ export const ComboBoxBaseMixin = (superClass) =>
|
|
|
306
305
|
}
|
|
307
306
|
}
|
|
308
307
|
|
|
309
|
-
/** @private */
|
|
310
|
-
_focusedIndexChanged(index, oldIndex) {
|
|
311
|
-
if (oldIndex === undefined) {
|
|
312
|
-
return;
|
|
313
|
-
}
|
|
314
|
-
this._updateActiveDescendant(index);
|
|
315
|
-
}
|
|
316
|
-
|
|
317
308
|
/** @protected */
|
|
318
309
|
_isInputFocused() {
|
|
319
310
|
return this.inputElement && isElementFocused(this.inputElement);
|
|
320
311
|
}
|
|
321
312
|
|
|
322
|
-
/** @
|
|
323
|
-
_updateActiveDescendant(
|
|
313
|
+
/** @protected */
|
|
314
|
+
_updateActiveDescendant() {
|
|
324
315
|
const input = this.inputElement;
|
|
325
316
|
if (!input) {
|
|
326
317
|
return;
|
|
327
318
|
}
|
|
328
319
|
|
|
320
|
+
const index = this._highlightedItemIndex;
|
|
329
321
|
const item = this._getItemElements().find((el) => el.index === index);
|
|
330
322
|
setOrRemoveAttribute(input, 'aria-activedescendant', item?.id);
|
|
331
323
|
}
|
|
@@ -502,11 +494,8 @@ export const ComboBoxBaseMixin = (superClass) =>
|
|
|
502
494
|
/** @private */
|
|
503
495
|
_onArrowDown() {
|
|
504
496
|
if (this.opened) {
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
this._focusedIndex = Math.min(items.length - 1, this._focusedIndex + 1);
|
|
508
|
-
this._prefillFocusedItemLabel();
|
|
509
|
-
}
|
|
497
|
+
this._highlightNextItem();
|
|
498
|
+
this._prefillFocusedItemLabel();
|
|
510
499
|
} else {
|
|
511
500
|
this.open();
|
|
512
501
|
}
|
|
@@ -515,15 +504,7 @@ export const ComboBoxBaseMixin = (superClass) =>
|
|
|
515
504
|
/** @private */
|
|
516
505
|
_onArrowUp() {
|
|
517
506
|
if (this.opened) {
|
|
518
|
-
|
|
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
|
-
|
|
507
|
+
this._highlightPrevItem();
|
|
527
508
|
this._prefillFocusedItemLabel();
|
|
528
509
|
} else {
|
|
529
510
|
this.open();
|
|
@@ -532,9 +513,8 @@ export const ComboBoxBaseMixin = (superClass) =>
|
|
|
532
513
|
|
|
533
514
|
/** @private */
|
|
534
515
|
_prefillFocusedItemLabel() {
|
|
535
|
-
if (this.
|
|
536
|
-
|
|
537
|
-
this._inputElementValue = this._getItemLabel(focusedItem);
|
|
516
|
+
if (this._hasHighlightedItem) {
|
|
517
|
+
this._inputElementValue = this._getItemLabel(this._highlightedItem);
|
|
538
518
|
this._markAllSelectionRange();
|
|
539
519
|
}
|
|
540
520
|
}
|
|
@@ -633,16 +613,16 @@ export const ComboBoxBaseMixin = (superClass) =>
|
|
|
633
613
|
// The overlay is open or
|
|
634
614
|
// The input value has changed but the change hasn't been committed, so cancel it.
|
|
635
615
|
e.stopPropagation();
|
|
636
|
-
this.
|
|
616
|
+
this._clearItemHighlight();
|
|
637
617
|
this._onEscapeCancel();
|
|
638
618
|
} else if (this.opened) {
|
|
639
619
|
// Auto-open is enabled
|
|
640
620
|
// The overlay is open
|
|
641
621
|
e.stopPropagation();
|
|
642
622
|
|
|
643
|
-
if (this.
|
|
623
|
+
if (this._hasHighlightedItem) {
|
|
644
624
|
// An item is focused, revert the input to the filtered value
|
|
645
|
-
this.
|
|
625
|
+
this._clearItemHighlight();
|
|
646
626
|
this._revertInputValue();
|
|
647
627
|
} else {
|
|
648
628
|
// No item is focused, cancel the change and close the overlay
|
|
@@ -766,7 +746,7 @@ export const ComboBoxBaseMixin = (superClass) =>
|
|
|
766
746
|
}
|
|
767
747
|
|
|
768
748
|
if (this.opened) {
|
|
769
|
-
this.
|
|
749
|
+
this._highlightItem(e.detail.item);
|
|
770
750
|
this.close();
|
|
771
751
|
}
|
|
772
752
|
}
|
|
@@ -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.
|
|
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(
|
|
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);
|
|
@@ -205,8 +205,8 @@ export const ComboBoxItemsMixin = (superClass) =>
|
|
|
205
205
|
}
|
|
206
206
|
|
|
207
207
|
/**
|
|
208
|
-
* Override an event listener from `ComboBoxBaseMixin` to
|
|
209
|
-
*
|
|
208
|
+
* Override an event listener from `ComboBoxBaseMixin` to update
|
|
209
|
+
* the filter and open the dropdown on user input.
|
|
210
210
|
* @param {!Event} event
|
|
211
211
|
* @protected
|
|
212
212
|
* @override
|
|
@@ -214,25 +214,18 @@ export const ComboBoxItemsMixin = (superClass) =>
|
|
|
214
214
|
_onInput(event) {
|
|
215
215
|
const filter = this._inputElementValue;
|
|
216
216
|
|
|
217
|
-
// When opening dropdown on user input, both `opened` and `filter` properties are set.
|
|
218
|
-
// Perform a batched property update instead of relying on sync property observers.
|
|
219
|
-
// This is necessary to avoid an extra data-provider request for loading first page.
|
|
220
|
-
const props = {};
|
|
221
|
-
|
|
222
217
|
if (this.filter === filter) {
|
|
223
218
|
// Filter and input value might get out of sync, while keyboard navigating for example.
|
|
224
219
|
// Afterwards, input value might be changed to the same value as used in filtering.
|
|
225
220
|
// In situation like these, we need to make sure all the filter changes handlers are run.
|
|
226
221
|
this._filterChanged(this.filter);
|
|
227
222
|
} else {
|
|
228
|
-
|
|
223
|
+
this.filter = filter;
|
|
229
224
|
}
|
|
230
225
|
|
|
231
226
|
if (!this.opened && !this._isClearButton(event) && !this.autoOpenDisabled) {
|
|
232
|
-
|
|
227
|
+
this.opened = true;
|
|
233
228
|
}
|
|
234
|
-
|
|
235
|
-
this.setProperties(props);
|
|
236
229
|
}
|
|
237
230
|
|
|
238
231
|
/**
|
|
@@ -246,8 +239,8 @@ export const ComboBoxItemsMixin = (superClass) =>
|
|
|
246
239
|
_onOpened() {
|
|
247
240
|
super._onOpened();
|
|
248
241
|
|
|
249
|
-
if (this.filter && this.
|
|
250
|
-
this.
|
|
242
|
+
if (this.filter && !this._hasHighlightedItem) {
|
|
243
|
+
this._highlightItemAt(this.__getItemIndexByFilter(this._dropdownItems));
|
|
251
244
|
}
|
|
252
245
|
}
|
|
253
246
|
|
|
@@ -309,7 +302,7 @@ export const ComboBoxItemsMixin = (superClass) =>
|
|
|
309
302
|
// Scroll to the top of the list whenever the filter changes.
|
|
310
303
|
this._scrollIntoView(0);
|
|
311
304
|
|
|
312
|
-
this.
|
|
305
|
+
this._clearItemHighlight();
|
|
313
306
|
|
|
314
307
|
if (this.items) {
|
|
315
308
|
this.filteredItems = this._filterItems(this.items, filter);
|
|
@@ -348,37 +341,31 @@ export const ComboBoxItemsMixin = (superClass) =>
|
|
|
348
341
|
* @protected
|
|
349
342
|
*/
|
|
350
343
|
_setDropdownItems(newItems) {
|
|
351
|
-
const
|
|
344
|
+
const highlightedItem = this._highlightedItem;
|
|
352
345
|
this._dropdownItems = newItems;
|
|
353
346
|
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
347
|
+
this.__restoreItemHighlight(highlightedItem);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* Highlights the given item again if it is still among the dropdown
|
|
352
|
+
* items, which keeps the highlight in place when more items are
|
|
353
|
+
* loading. Otherwise the item matching the filter is highlighted, or none.
|
|
354
|
+
* @private
|
|
355
|
+
*/
|
|
356
|
+
__restoreItemHighlight(item) {
|
|
357
|
+
const items = this._dropdownItems;
|
|
358
358
|
|
|
359
|
-
// When both the previously
|
|
359
|
+
// When both the previously highlighted entry and the new entry at the
|
|
360
360
|
// same index are placeholders (e.g. the Flow connector mid-scroll
|
|
361
|
-
// re-pushing `_setDropdownItems`), preserve
|
|
361
|
+
// re-pushing `_setDropdownItems`), preserve the highlight until
|
|
362
362
|
// 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
|
-
) {
|
|
363
|
+
if (item instanceof ComboBoxPlaceholder && items[this._highlightedItemIndex] instanceof ComboBoxPlaceholder) {
|
|
368
364
|
return;
|
|
369
365
|
}
|
|
370
366
|
|
|
371
|
-
|
|
372
|
-
|
|
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
|
-
}
|
|
367
|
+
const index = this.__getItemIndexByValue(items, this._getItemValue(item));
|
|
368
|
+
this._highlightItemAt(index > -1 ? index : this.__getItemIndexByFilter(items));
|
|
382
369
|
}
|
|
383
370
|
|
|
384
371
|
/** @private */
|
|
@@ -146,7 +146,7 @@ export const ComboBoxMixin = (superClass) =>
|
|
|
146
146
|
*/
|
|
147
147
|
_hasValidInputValue() {
|
|
148
148
|
const hasInvalidOption =
|
|
149
|
-
this.
|
|
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.
|
|
240
|
-
const focusedItem = this.
|
|
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.
|
|
246
|
+
this._clearItemHighlight();
|
|
247
247
|
} else if (this._inputElementValue === '' || this._inputElementValue === undefined) {
|
|
248
248
|
this.selectedItem = null;
|
|
249
249
|
|
|
@@ -284,6 +284,11 @@ export const ComboBoxScrollerMixin = (superClass) =>
|
|
|
284
284
|
}
|
|
285
285
|
|
|
286
286
|
this.requestContentUpdate();
|
|
287
|
+
|
|
288
|
+
// The focused index can change while closed, when scrolling to it is skipped
|
|
289
|
+
if (this.focusedIndex >= 0 && !this.loading) {
|
|
290
|
+
this.scrollIntoView(this.focusedIndex);
|
|
291
|
+
}
|
|
287
292
|
return;
|
|
288
293
|
}
|
|
289
294
|
|
|
@@ -223,10 +223,14 @@ export interface ComboBoxEventMap<TItem> extends HTMLElementEventMap {
|
|
|
223
223
|
* | `--vaadin-input-field-error-font-weight` |
|
|
224
224
|
* | `--vaadin-input-field-error-line-height` |
|
|
225
225
|
* | `--vaadin-input-field-gap` |
|
|
226
|
+
* | `--vaadin-input-field-height` |
|
|
226
227
|
* | `--vaadin-input-field-helper-color` |
|
|
227
228
|
* | `--vaadin-input-field-helper-font-size` |
|
|
228
229
|
* | `--vaadin-input-field-helper-font-weight` |
|
|
229
230
|
* | `--vaadin-input-field-helper-line-height` |
|
|
231
|
+
* | `--vaadin-input-field-label-aside-gap` |
|
|
232
|
+
* | `--vaadin-input-field-label-aside-text-align` |
|
|
233
|
+
* | `--vaadin-input-field-label-aside-width` |
|
|
230
234
|
* | `--vaadin-input-field-label-color` |
|
|
231
235
|
* | `--vaadin-input-field-label-font-size` |
|
|
232
236
|
* | `--vaadin-input-field-label-font-weight` |
|
package/src/vaadin-combo-box.js
CHANGED
|
@@ -155,10 +155,14 @@ import { ComboBoxMixin } from './vaadin-combo-box-mixin.js';
|
|
|
155
155
|
* | `--vaadin-input-field-error-font-weight` |
|
|
156
156
|
* | `--vaadin-input-field-error-line-height` |
|
|
157
157
|
* | `--vaadin-input-field-gap` |
|
|
158
|
+
* | `--vaadin-input-field-height` |
|
|
158
159
|
* | `--vaadin-input-field-helper-color` |
|
|
159
160
|
* | `--vaadin-input-field-helper-font-size` |
|
|
160
161
|
* | `--vaadin-input-field-helper-font-weight` |
|
|
161
162
|
* | `--vaadin-input-field-helper-line-height` |
|
|
163
|
+
* | `--vaadin-input-field-label-aside-gap` |
|
|
164
|
+
* | `--vaadin-input-field-label-aside-text-align` |
|
|
165
|
+
* | `--vaadin-input-field-label-aside-width` |
|
|
162
166
|
* | `--vaadin-input-field-label-color` |
|
|
163
167
|
* | `--vaadin-input-field-label-font-size` |
|
|
164
168
|
* | `--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.
|
|
4
|
+
"version": "25.4.0-alpha2",
|
|
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.
|
|
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-alpha2/#/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-alpha2/#/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-alpha2/#/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-height` |\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-alpha2/#/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",
|
package/web-types.lit.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/web-types",
|
|
3
3
|
"name": "@vaadin/combo-box",
|
|
4
|
-
"version": "25.
|
|
4
|
+
"version": "25.4.0-alpha2",
|
|
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.
|
|
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-alpha2/#/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-alpha2/#/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-alpha2/#/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-height` |\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-alpha2/#/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
|
{
|