@vaadin/combo-box 23.2.0-alpha2 → 23.2.0-dev.48e5e3967
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +13 -13
- package/src/vaadin-combo-box-data-provider-mixin.js +24 -29
- package/src/vaadin-combo-box-light.d.ts +3 -1
- package/src/vaadin-combo-box-light.js +3 -1
- package/src/vaadin-combo-box-mixin.d.ts +0 -5
- package/src/vaadin-combo-box-mixin.js +40 -43
- package/src/vaadin-combo-box.d.ts +1 -0
- package/src/vaadin-combo-box.js +1 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vaadin/combo-box",
|
|
3
|
-
"version": "23.2.0-
|
|
3
|
+
"version": "23.2.0-dev.48e5e3967",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -36,23 +36,23 @@
|
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"@open-wc/dedupe-mixin": "^1.3.0",
|
|
38
38
|
"@polymer/polymer": "^3.0.0",
|
|
39
|
-
"@vaadin/component-base": "23.2.0-
|
|
40
|
-
"@vaadin/field-base": "23.2.0-
|
|
41
|
-
"@vaadin/input-container": "23.2.0-
|
|
42
|
-
"@vaadin/item": "23.2.0-
|
|
43
|
-
"@vaadin/lit-renderer": "23.2.0-
|
|
44
|
-
"@vaadin/vaadin-lumo-styles": "23.2.0-
|
|
45
|
-
"@vaadin/vaadin-material-styles": "23.2.0-
|
|
46
|
-
"@vaadin/vaadin-overlay": "23.2.0-
|
|
47
|
-
"@vaadin/vaadin-themable-mixin": "23.2.0-
|
|
39
|
+
"@vaadin/component-base": "23.2.0-dev.48e5e3967",
|
|
40
|
+
"@vaadin/field-base": "23.2.0-dev.48e5e3967",
|
|
41
|
+
"@vaadin/input-container": "23.2.0-dev.48e5e3967",
|
|
42
|
+
"@vaadin/item": "23.2.0-dev.48e5e3967",
|
|
43
|
+
"@vaadin/lit-renderer": "23.2.0-dev.48e5e3967",
|
|
44
|
+
"@vaadin/vaadin-lumo-styles": "23.2.0-dev.48e5e3967",
|
|
45
|
+
"@vaadin/vaadin-material-styles": "23.2.0-dev.48e5e3967",
|
|
46
|
+
"@vaadin/vaadin-overlay": "23.2.0-dev.48e5e3967",
|
|
47
|
+
"@vaadin/vaadin-themable-mixin": "23.2.0-dev.48e5e3967"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@esm-bundle/chai": "^4.3.4",
|
|
51
|
-
"@vaadin/polymer-legacy-adapter": "23.2.0-
|
|
51
|
+
"@vaadin/polymer-legacy-adapter": "23.2.0-dev.48e5e3967",
|
|
52
52
|
"@vaadin/testing-helpers": "^0.3.2",
|
|
53
|
-
"@vaadin/text-field": "23.2.0-
|
|
53
|
+
"@vaadin/text-field": "23.2.0-dev.48e5e3967",
|
|
54
54
|
"lit": "^2.0.0",
|
|
55
55
|
"sinon": "^13.0.2"
|
|
56
56
|
},
|
|
57
|
-
"gitHead": "
|
|
57
|
+
"gitHead": "961bc4ae5b707c3c02f12b99819b3c12c9b478aa"
|
|
58
58
|
}
|
|
@@ -62,13 +62,17 @@ export const ComboBoxDataProviderMixin = (superClass) =>
|
|
|
62
62
|
__placeHolder: {
|
|
63
63
|
value: new ComboBoxPlaceholder(),
|
|
64
64
|
},
|
|
65
|
+
|
|
66
|
+
/** @private */
|
|
67
|
+
__previousDataProviderFilter: {
|
|
68
|
+
type: String,
|
|
69
|
+
},
|
|
65
70
|
};
|
|
66
71
|
}
|
|
67
72
|
|
|
68
73
|
static get observers() {
|
|
69
74
|
return [
|
|
70
|
-
'_dataProviderFilterChanged(filter
|
|
71
|
-
'_dataProviderClearFilter(dataProvider, opened, value)',
|
|
75
|
+
'_dataProviderFilterChanged(filter)',
|
|
72
76
|
'_warnDataProviderValue(dataProvider, value)',
|
|
73
77
|
'_ensureFirstPage(opened)',
|
|
74
78
|
];
|
|
@@ -77,7 +81,6 @@ export const ComboBoxDataProviderMixin = (superClass) =>
|
|
|
77
81
|
/** @protected */
|
|
78
82
|
ready() {
|
|
79
83
|
super.ready();
|
|
80
|
-
this.clearCache();
|
|
81
84
|
this._scroller.addEventListener('index-requested', (e) => {
|
|
82
85
|
const index = e.detail.index;
|
|
83
86
|
const currentScrollerPos = e.detail.currentScrollerPos;
|
|
@@ -101,38 +104,25 @@ export const ComboBoxDataProviderMixin = (superClass) =>
|
|
|
101
104
|
}
|
|
102
105
|
|
|
103
106
|
/** @private */
|
|
104
|
-
_dataProviderFilterChanged() {
|
|
105
|
-
if (
|
|
107
|
+
_dataProviderFilterChanged(filter) {
|
|
108
|
+
if (this.__previousDataProviderFilter === undefined && filter === '') {
|
|
109
|
+
this.__previousDataProviderFilter = filter;
|
|
106
110
|
return;
|
|
107
111
|
}
|
|
108
112
|
|
|
109
|
-
this.
|
|
110
|
-
|
|
113
|
+
if (this.__previousDataProviderFilter !== filter) {
|
|
114
|
+
this.__previousDataProviderFilter = filter;
|
|
111
115
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
}
|
|
116
|
+
this._pendingRequests = {};
|
|
117
|
+
// Immediately mark as loading if this refresh leads to re-fetching pages
|
|
118
|
+
// This prevents some issues with the properties below triggering
|
|
119
|
+
// observers that also rely on the loading state
|
|
120
|
+
this.loading = this._shouldFetchData();
|
|
121
|
+
// Reset size and internal loading state
|
|
122
|
+
this.size = undefined;
|
|
120
123
|
|
|
121
|
-
|
|
122
|
-
_refreshData(clearFilter) {
|
|
123
|
-
// Immediately mark as loading if this refresh leads to re-fetching pages
|
|
124
|
-
// This prevents some issues with the properties below triggering
|
|
125
|
-
// observers that also rely on the loading state
|
|
126
|
-
this.loading = this._shouldFetchData();
|
|
127
|
-
// Reset size and internal loading state
|
|
128
|
-
this.size = undefined;
|
|
129
|
-
this._pendingRequests = {};
|
|
130
|
-
// Clear filter if requested
|
|
131
|
-
if (clearFilter) {
|
|
132
|
-
this.filter = '';
|
|
124
|
+
this.clearCache();
|
|
133
125
|
}
|
|
134
|
-
// Clear cached pages, and reload current page if we need the data
|
|
135
|
-
this.clearCache();
|
|
136
126
|
}
|
|
137
127
|
|
|
138
128
|
/** @private */
|
|
@@ -229,13 +219,16 @@ export const ComboBoxDataProviderMixin = (superClass) =>
|
|
|
229
219
|
if (!this.dataProvider) {
|
|
230
220
|
return;
|
|
231
221
|
}
|
|
222
|
+
|
|
232
223
|
this._pendingRequests = {};
|
|
233
224
|
const filteredItems = [];
|
|
234
225
|
for (let i = 0; i < (this.size || 0); i++) {
|
|
235
226
|
filteredItems.push(this.__placeHolder);
|
|
236
227
|
}
|
|
237
228
|
this.filteredItems = filteredItems;
|
|
229
|
+
|
|
238
230
|
if (this._shouldFetchData()) {
|
|
231
|
+
this._forceNextRequest = false;
|
|
239
232
|
this._loadPage(0);
|
|
240
233
|
} else {
|
|
241
234
|
this._forceNextRequest = true;
|
|
@@ -269,6 +262,8 @@ export const ComboBoxDataProviderMixin = (superClass) =>
|
|
|
269
262
|
this._ensureItemsOrDataProvider(() => {
|
|
270
263
|
this.dataProvider = oldDataProvider;
|
|
271
264
|
});
|
|
265
|
+
|
|
266
|
+
this.clearCache();
|
|
272
267
|
}
|
|
273
268
|
|
|
274
269
|
/** @private */
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
import { DisabledMixinClass } from '@vaadin/component-base/src/disabled-mixin.js';
|
|
7
7
|
import { KeyboardMixinClass } from '@vaadin/component-base/src/keyboard-mixin.js';
|
|
8
8
|
import { InputMixinClass } from '@vaadin/field-base/src/input-mixin.js';
|
|
9
|
+
import { ValidateMixinClass } from '@vaadin/field-base/src/validate-mixin.js';
|
|
9
10
|
import { ThemableMixinClass } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
10
11
|
import { ComboBoxDataProviderMixinClass } from './vaadin-combo-box-data-provider-mixin.js';
|
|
11
12
|
import { ComboBoxMixinClass } from './vaadin-combo-box-mixin.js';
|
|
@@ -142,7 +143,8 @@ interface ComboBoxLight<TItem = ComboBoxDefaultItem>
|
|
|
142
143
|
KeyboardMixinClass,
|
|
143
144
|
InputMixinClass,
|
|
144
145
|
DisabledMixinClass,
|
|
145
|
-
ThemableMixinClass
|
|
146
|
+
ThemableMixinClass,
|
|
147
|
+
ValidateMixinClass {}
|
|
146
148
|
|
|
147
149
|
declare global {
|
|
148
150
|
interface HTMLElementTagNameMap {
|
|
@@ -8,6 +8,7 @@ import './vaadin-combo-box-overlay.js';
|
|
|
8
8
|
import './vaadin-combo-box-scroller.js';
|
|
9
9
|
import { dashToCamelCase } from '@polymer/polymer/lib/utils/case-map.js';
|
|
10
10
|
import { html, PolymerElement } from '@polymer/polymer/polymer-element.js';
|
|
11
|
+
import { ValidateMixin } from '@vaadin/field-base/src/validate-mixin.js';
|
|
11
12
|
import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
12
13
|
import { ComboBoxDataProviderMixin } from './vaadin-combo-box-data-provider-mixin.js';
|
|
13
14
|
import { ComboBoxMixin } from './vaadin-combo-box-mixin.js';
|
|
@@ -61,8 +62,9 @@ import { ComboBoxMixin } from './vaadin-combo-box-mixin.js';
|
|
|
61
62
|
* @mixes ComboBoxDataProviderMixin
|
|
62
63
|
* @mixes ComboBoxMixin
|
|
63
64
|
* @mixes ThemableMixin
|
|
65
|
+
* @mixes ValidateMixin
|
|
64
66
|
*/
|
|
65
|
-
class ComboBoxLight extends ComboBoxDataProviderMixin(ComboBoxMixin(ThemableMixin(PolymerElement))) {
|
|
67
|
+
class ComboBoxLight extends ComboBoxDataProviderMixin(ComboBoxMixin(ValidateMixin(ThemableMixin(PolymerElement)))) {
|
|
66
68
|
static get is() {
|
|
67
69
|
return 'vaadin-combo-box-light';
|
|
68
70
|
}
|
|
@@ -138,11 +138,6 @@ export declare class ComboBoxMixinClass<TItem> {
|
|
|
138
138
|
*/
|
|
139
139
|
itemIdPath: string | null | undefined;
|
|
140
140
|
|
|
141
|
-
/**
|
|
142
|
-
* Set to true if the value is invalid.
|
|
143
|
-
*/
|
|
144
|
-
invalid: boolean;
|
|
145
|
-
|
|
146
141
|
protected readonly _propertyForValue: string;
|
|
147
142
|
|
|
148
143
|
protected _inputElementValue: string | undefined;
|
|
@@ -236,7 +236,6 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
236
236
|
|
|
237
237
|
static get observers() {
|
|
238
238
|
return [
|
|
239
|
-
'_filterChanged(filter, itemValuePath, itemLabelPath)',
|
|
240
239
|
'_selectedItemChanged(selectedItem, itemValuePath, itemLabelPath)',
|
|
241
240
|
'_openedOrItemsChanged(opened, filteredItems, loading)',
|
|
242
241
|
'_updateScroller(_scroller, filteredItems, opened, loading, selectedItem, itemIdPath, _focusedIndex, renderer, theme)',
|
|
@@ -382,6 +381,25 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
382
381
|
this.opened = false;
|
|
383
382
|
}
|
|
384
383
|
|
|
384
|
+
/**
|
|
385
|
+
* Override Polymer lifecycle callback to handle `filter` property change after
|
|
386
|
+
* the observer for `opened` property is triggered. This is needed when opening
|
|
387
|
+
* combo-box on user input to ensure the focused index is set correctly.
|
|
388
|
+
*
|
|
389
|
+
* @param {!Object} currentProps Current accessor values
|
|
390
|
+
* @param {?Object} changedProps Properties changed since the last call
|
|
391
|
+
* @param {?Object} oldProps Previous values for each changed property
|
|
392
|
+
* @protected
|
|
393
|
+
* @override
|
|
394
|
+
*/
|
|
395
|
+
_propertiesChanged(currentProps, changedProps, oldProps) {
|
|
396
|
+
super._propertiesChanged(currentProps, changedProps, oldProps);
|
|
397
|
+
|
|
398
|
+
if (changedProps.filter !== undefined) {
|
|
399
|
+
this._filterChanged(changedProps.filter);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
|
|
385
403
|
/** @private */
|
|
386
404
|
_initOverlay() {
|
|
387
405
|
const overlay = this.$.overlay;
|
|
@@ -926,9 +944,7 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
926
944
|
|
|
927
945
|
this._clearSelectionRange();
|
|
928
946
|
|
|
929
|
-
|
|
930
|
-
this.filter = '';
|
|
931
|
-
}
|
|
947
|
+
this.filter = '';
|
|
932
948
|
}
|
|
933
949
|
|
|
934
950
|
/**
|
|
@@ -946,19 +962,27 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
946
962
|
* @override
|
|
947
963
|
*/
|
|
948
964
|
_onInput(event) {
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
965
|
+
const filter = this._inputElementValue;
|
|
966
|
+
|
|
967
|
+
// When opening dropdown on user input, both `opened` and `filter` properties are set.
|
|
968
|
+
// Perform a batched property update instead of relying on sync property observers.
|
|
969
|
+
// This is necessary to avoid an extra data-provider request for loading first page.
|
|
970
|
+
const props = {};
|
|
952
971
|
|
|
953
|
-
|
|
954
|
-
if (this.filter === value) {
|
|
972
|
+
if (this.filter === filter) {
|
|
955
973
|
// Filter and input value might get out of sync, while keyboard navigating for example.
|
|
956
974
|
// Afterwards, input value might be changed to the same value as used in filtering.
|
|
957
975
|
// In situation like these, we need to make sure all the filter changes handlers are run.
|
|
958
|
-
this._filterChanged(this.filter
|
|
976
|
+
this._filterChanged(this.filter);
|
|
959
977
|
} else {
|
|
960
|
-
|
|
978
|
+
props.filter = filter;
|
|
961
979
|
}
|
|
980
|
+
|
|
981
|
+
if (!this.opened && !this._isClearButton(event) && !this.autoOpenDisabled) {
|
|
982
|
+
props.opened = true;
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
this.setProperties(props);
|
|
962
986
|
}
|
|
963
987
|
|
|
964
988
|
/**
|
|
@@ -981,11 +1005,7 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
981
1005
|
}
|
|
982
1006
|
|
|
983
1007
|
/** @private */
|
|
984
|
-
_filterChanged(filter
|
|
985
|
-
if (filter === undefined) {
|
|
986
|
-
return;
|
|
987
|
-
}
|
|
988
|
-
|
|
1008
|
+
_filterChanged(filter) {
|
|
989
1009
|
// Scroll to the top of the list whenever the filter changes.
|
|
990
1010
|
this._scrollIntoView(0);
|
|
991
1011
|
|
|
@@ -1064,14 +1084,11 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
1064
1084
|
}
|
|
1065
1085
|
|
|
1066
1086
|
if (isValidValue(value)) {
|
|
1067
|
-
let item;
|
|
1068
1087
|
if (this._getItemValue(this.selectedItem) !== value) {
|
|
1069
1088
|
this._selectItemForValue(value);
|
|
1070
|
-
} else {
|
|
1071
|
-
item = this.selectedItem;
|
|
1072
1089
|
}
|
|
1073
1090
|
|
|
1074
|
-
if (!
|
|
1091
|
+
if (!this.selectedItem && this.allowCustomValue) {
|
|
1075
1092
|
this._inputElementValue = value;
|
|
1076
1093
|
}
|
|
1077
1094
|
|
|
@@ -1079,6 +1096,9 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
1079
1096
|
} else {
|
|
1080
1097
|
this.selectedItem = null;
|
|
1081
1098
|
}
|
|
1099
|
+
|
|
1100
|
+
this.filter = '';
|
|
1101
|
+
|
|
1082
1102
|
// In the next _detectAndDispatchChange() call, the change detection should pass
|
|
1083
1103
|
this._lastCommittedValue = undefined;
|
|
1084
1104
|
}
|
|
@@ -1277,29 +1297,6 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
1277
1297
|
this._clear();
|
|
1278
1298
|
}
|
|
1279
1299
|
|
|
1280
|
-
/**
|
|
1281
|
-
* Returns true if `value` is valid, and sets the `invalid` flag appropriately.
|
|
1282
|
-
*
|
|
1283
|
-
* @return {boolean} True if the value is valid and sets the `invalid` flag appropriately
|
|
1284
|
-
*/
|
|
1285
|
-
validate() {
|
|
1286
|
-
return !(this.invalid = !this.checkValidity());
|
|
1287
|
-
}
|
|
1288
|
-
|
|
1289
|
-
/**
|
|
1290
|
-
* Returns true if the current input value satisfies all constraints (if any).
|
|
1291
|
-
* You can override this method for custom validations.
|
|
1292
|
-
*
|
|
1293
|
-
* @return {boolean}
|
|
1294
|
-
*/
|
|
1295
|
-
checkValidity() {
|
|
1296
|
-
if (super.checkValidity) {
|
|
1297
|
-
return super.checkValidity();
|
|
1298
|
-
}
|
|
1299
|
-
|
|
1300
|
-
return !this.required || !!this.value;
|
|
1301
|
-
}
|
|
1302
|
-
|
|
1303
1300
|
/**
|
|
1304
1301
|
* Fired when the value changes.
|
|
1305
1302
|
*
|
|
@@ -165,6 +165,7 @@ export interface ComboBoxEventMap<TItem> extends HTMLElementEventMap {
|
|
|
165
165
|
* Custom property | Description | Default
|
|
166
166
|
* ----------------------------------------|----------------------------|---------
|
|
167
167
|
* `--vaadin-field-default-width` | Default width of the field | `12em`
|
|
168
|
+
* `--vaadin-combo-box-overlay-width` | Width of the overlay | `auto`
|
|
168
169
|
* `--vaadin-combo-box-overlay-max-height` | Max height of the overlay | `65vh`
|
|
169
170
|
*
|
|
170
171
|
* `<vaadin-combo-box>` provides the same set of shadow DOM parts and state attributes as `<vaadin-text-field>`.
|
package/src/vaadin-combo-box.js
CHANGED
|
@@ -104,6 +104,7 @@ registerStyles('vaadin-combo-box', inputFieldShared, { moduleId: 'vaadin-combo-b
|
|
|
104
104
|
* Custom property | Description | Default
|
|
105
105
|
* ----------------------------------------|----------------------------|---------
|
|
106
106
|
* `--vaadin-field-default-width` | Default width of the field | `12em`
|
|
107
|
+
* `--vaadin-combo-box-overlay-width` | Width of the overlay | `auto`
|
|
107
108
|
* `--vaadin-combo-box-overlay-max-height` | Max height of the overlay | `65vh`
|
|
108
109
|
*
|
|
109
110
|
* `<vaadin-combo-box>` provides the same set of shadow DOM parts and state attributes as `<vaadin-text-field>`.
|