@vaadin/combo-box 23.1.0 → 23.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vaadin/combo-box",
3
- "version": "23.1.0",
3
+ "version": "23.1.3",
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.1.0",
40
- "@vaadin/field-base": "^23.1.0",
41
- "@vaadin/input-container": "^23.1.0",
42
- "@vaadin/item": "^23.1.0",
43
- "@vaadin/lit-renderer": "^23.1.0",
44
- "@vaadin/vaadin-lumo-styles": "^23.1.0",
45
- "@vaadin/vaadin-material-styles": "^23.1.0",
46
- "@vaadin/vaadin-overlay": "^23.1.0",
47
- "@vaadin/vaadin-themable-mixin": "^23.1.0"
39
+ "@vaadin/component-base": "^23.1.3",
40
+ "@vaadin/field-base": "^23.1.3",
41
+ "@vaadin/input-container": "^23.1.3",
42
+ "@vaadin/item": "^23.1.3",
43
+ "@vaadin/lit-renderer": "^23.1.3",
44
+ "@vaadin/vaadin-lumo-styles": "^23.1.3",
45
+ "@vaadin/vaadin-material-styles": "^23.1.3",
46
+ "@vaadin/vaadin-overlay": "^23.1.3",
47
+ "@vaadin/vaadin-themable-mixin": "^23.1.3"
48
48
  },
49
49
  "devDependencies": {
50
50
  "@esm-bundle/chai": "^4.3.4",
51
- "@vaadin/polymer-legacy-adapter": "^23.1.0",
51
+ "@vaadin/polymer-legacy-adapter": "^23.1.3",
52
52
  "@vaadin/testing-helpers": "^0.3.2",
53
- "@vaadin/text-field": "^23.1.0",
53
+ "@vaadin/text-field": "^23.1.3",
54
54
  "lit": "^2.0.0",
55
55
  "sinon": "^13.0.2"
56
56
  },
57
- "gitHead": "322bba42b83f908a78cd972b06acadc5da95a69d"
57
+ "gitHead": "3066c296ad0ef652bc49417005523398199f1bf2"
58
58
  }
@@ -20,7 +20,7 @@ export type ComboBoxDataProvider<TItem> = (
20
20
 
21
21
  export declare function ComboBoxDataProviderMixin<TItem, T extends Constructor<HTMLElement>>(
22
22
  base: T,
23
- ): T & Constructor<ComboBoxDataProviderMixinClass<TItem>>;
23
+ ): Constructor<ComboBoxDataProviderMixinClass<TItem>> & T;
24
24
 
25
25
  export declare class ComboBoxDataProviderMixinClass<TItem> {
26
26
  /**
@@ -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, dataProvider)',
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.$.dropdown.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 (!this._shouldFetchData()) {
107
+ _dataProviderFilterChanged(filter) {
108
+ if (this.__previousDataProviderFilter === undefined && filter === '') {
109
+ this.__previousDataProviderFilter = filter;
106
110
  return;
107
111
  }
108
112
 
109
- this._refreshData();
110
- }
113
+ if (this.__previousDataProviderFilter !== filter) {
114
+ this.__previousDataProviderFilter = filter;
111
115
 
112
- /** @private */
113
- _dataProviderClearFilter(dataProvider, opened, value) {
114
- // Can't depend on filter in this observer as we don't want
115
- // to clear the filter whenever it's set
116
- if (dataProvider && !this.loading && this.filter && !(opened && this.autoOpenDisabled && value === this.filter)) {
117
- this._refreshData(true);
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
- /** @private */
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 */
@@ -188,13 +178,10 @@ export const ComboBoxDataProviderMixin = (superClass) =>
188
178
 
189
179
  const callback = (items, size) => {
190
180
  if (this._pendingRequests[page] === callback) {
191
- if (!this.filteredItems) {
192
- const filteredItems = [];
193
- filteredItems.splice(params.page * params.pageSize, items.length, ...items);
194
- this.filteredItems = filteredItems;
195
- } else {
196
- this.splice('filteredItems', params.page * params.pageSize, items.length, ...items);
197
- }
181
+ const filteredItems = this.filteredItems ? [...this.filteredItems] : [];
182
+ filteredItems.splice(params.page * params.pageSize, items.length, ...items);
183
+ this.filteredItems = filteredItems;
184
+
198
185
  // Update selectedItem from filteredItems if value is set
199
186
  if (this._isValidValue(this.value) && this._getItemValue(this.selectedItem) !== this.value) {
200
187
  this._selectItemForValue(this.value);
@@ -232,13 +219,16 @@ export const ComboBoxDataProviderMixin = (superClass) =>
232
219
  if (!this.dataProvider) {
233
220
  return;
234
221
  }
222
+
235
223
  this._pendingRequests = {};
236
224
  const filteredItems = [];
237
225
  for (let i = 0; i < (this.size || 0); i++) {
238
226
  filteredItems.push(this.__placeHolder);
239
227
  }
240
228
  this.filteredItems = filteredItems;
229
+
241
230
  if (this._shouldFetchData()) {
231
+ this._forceNextRequest = false;
242
232
  this._loadPage(0);
243
233
  } else {
244
234
  this._forceNextRequest = true;
@@ -272,6 +262,8 @@ export const ComboBoxDataProviderMixin = (superClass) =>
272
262
  this._ensureItemsOrDataProvider(() => {
273
263
  this.dataProvider = oldDataProvider;
274
264
  });
265
+
266
+ this.clearCache();
275
267
  }
276
268
 
277
269
  /** @private */
@@ -126,13 +126,13 @@ declare class ComboBoxLight<TItem = ComboBoxDefaultItem> extends HTMLElement {
126
126
  addEventListener<K extends keyof ComboBoxLightEventMap<TItem>>(
127
127
  type: K,
128
128
  listener: (this: ComboBoxLight<TItem>, ev: ComboBoxLightEventMap<TItem>[K]) => void,
129
- options?: boolean | AddEventListenerOptions,
129
+ options?: AddEventListenerOptions | boolean,
130
130
  ): void;
131
131
 
132
132
  removeEventListener<K extends keyof ComboBoxLightEventMap<TItem>>(
133
133
  type: K,
134
134
  listener: (this: ComboBoxLight<TItem>, ev: ComboBoxLightEventMap<TItem>[K]) => void,
135
- options?: boolean | EventListenerOptions,
135
+ options?: EventListenerOptions | boolean,
136
136
  ): void;
137
137
  }
138
138
 
@@ -24,11 +24,11 @@ export type ComboBoxRenderer<TItem> = (
24
24
 
25
25
  export declare function ComboBoxMixin<TItem, T extends Constructor<HTMLElement>>(
26
26
  base: T,
27
- ): T &
28
- Constructor<ComboBoxMixinClass<TItem>> &
27
+ ): Constructor<ComboBoxMixinClass<TItem>> &
29
28
  Constructor<DisabledMixinClass> &
30
29
  Constructor<InputMixinClass> &
31
- Constructor<KeyboardMixinClass>;
30
+ Constructor<KeyboardMixinClass> &
31
+ T;
32
32
 
33
33
  export declare class ComboBoxMixinClass<TItem> {
34
34
  /**
@@ -203,8 +203,7 @@ export const ComboBoxMixin = (subclass) =>
203
203
  static get observers() {
204
204
  return [
205
205
  '_filterChanged(filter, itemValuePath, itemLabelPath)',
206
- '_itemsOrPathsChanged(items.*, itemValuePath, itemLabelPath)',
207
- '_filteredItemsChanged(filteredItems.*, itemValuePath, itemLabelPath)',
206
+ '_filteredItemsChanged(filteredItems)',
208
207
  '_selectedItemChanged(selectedItem, itemValuePath, itemLabelPath)',
209
208
  ];
210
209
  }
@@ -779,9 +778,7 @@ export const ComboBoxMixin = (subclass) =>
779
778
 
780
779
  this._clearSelectionRange();
781
780
 
782
- if (!this.dataProvider) {
783
- this.filter = '';
784
- }
781
+ this.filter = '';
785
782
  }
786
783
 
787
784
  /**
@@ -834,7 +831,7 @@ export const ComboBoxMixin = (subclass) =>
834
831
  }
835
832
 
836
833
  /** @private */
837
- _filterChanged(filter, itemValuePath, itemLabelPath) {
834
+ _filterChanged(filter, _itemValuePath, _itemLabelPath) {
838
835
  if (filter === undefined) {
839
836
  return;
840
837
  }
@@ -848,7 +845,7 @@ export const ComboBoxMixin = (subclass) =>
848
845
  // With certain use cases (e. g., external filtering), `items` are
849
846
  // undefined. Filtering is unnecessary per se, but the filteredItems
850
847
  // observer should still be invoked to update focused item.
851
- this._filteredItemsChanged({ path: 'filteredItems', value: this.filteredItems }, itemValuePath, itemLabelPath);
848
+ this._filteredItemsChanged(this.filteredItems);
852
849
  }
853
850
  }
854
851
 
@@ -924,14 +921,11 @@ export const ComboBoxMixin = (subclass) =>
924
921
  }
925
922
 
926
923
  if (this._isValidValue(value)) {
927
- let item;
928
924
  if (this._getItemValue(this.selectedItem) !== value) {
929
925
  this._selectItemForValue(value);
930
- } else {
931
- item = this.selectedItem;
932
926
  }
933
927
 
934
- if (!item && this.allowCustomValue) {
928
+ if (!this.selectedItem && this.allowCustomValue) {
935
929
  this._inputElementValue = value;
936
930
  }
937
931
 
@@ -939,6 +933,9 @@ export const ComboBoxMixin = (subclass) =>
939
933
  } else {
940
934
  this.selectedItem = null;
941
935
  }
936
+
937
+ this.filter = '';
938
+
942
939
  // In the next _detectAndDispatchChange() call, the change detection should pass
943
940
  this._lastCommittedValue = undefined;
944
941
  }
@@ -956,53 +953,46 @@ export const ComboBoxMixin = (subclass) =>
956
953
  this._ensureItemsOrDataProvider(() => {
957
954
  this.items = oldItems;
958
955
  });
959
- }
960
956
 
961
- /** @private */
962
- _itemsOrPathsChanged(e) {
963
- if (e.path === 'items' || e.path === 'items.splices') {
964
- if (this.items) {
965
- this.filteredItems = this.items.slice(0);
966
- } else if (this.__previousItems) {
967
- // Only clear filteredItems if the component had items previously but got cleared
968
- this.filteredItems = null;
969
- }
957
+ if (items) {
958
+ this.filteredItems = items.slice(0);
959
+ } else if (this.__previousItems) {
960
+ // Only clear filteredItems if the component had items previously but got cleared
961
+ this.filteredItems = null;
962
+ }
970
963
 
971
- const valueIndex = this._indexOfValue(this.value, this.items);
972
- this._focusedIndex = valueIndex;
964
+ const valueIndex = this._indexOfValue(this.value, items);
965
+ this._focusedIndex = valueIndex;
973
966
 
974
- const item = valueIndex > -1 && this.items[valueIndex];
975
- if (item) {
976
- this.selectedItem = item;
977
- }
967
+ const item = valueIndex > -1 && items[valueIndex];
968
+ if (item) {
969
+ this.selectedItem = item;
978
970
  }
979
- this.__previousItems = e.value;
971
+ this.__previousItems = items;
980
972
  }
981
973
 
982
974
  /** @private */
983
- _filteredItemsChanged(e) {
984
- if (e.path === 'filteredItems' || e.path === 'filteredItems.splices') {
985
- this._setOverlayItems(this.filteredItems);
986
-
987
- // When the external filtering is used and `value` was provided before `filteredItems`,
988
- // initialize the selected item with the current value here. This will also cause
989
- // the input element value to sync. In other cases, the selected item is already initialized
990
- // in other observers such as `valueChanged`, `_itemsOrPathsChanged`.
991
- const valueIndex = this._indexOfValue(this.value, this.filteredItems);
992
- if (this.selectedItem === null && valueIndex >= 0) {
993
- this._selectItemForValue(this.value);
994
- }
975
+ _filteredItemsChanged(filteredItems, _itemValuePath, _itemLabelPath) {
976
+ this._setOverlayItems(filteredItems);
977
+
978
+ // When the external filtering is used and `value` was provided before `filteredItems`,
979
+ // initialize the selected item with the current value here. This will also cause
980
+ // the input element value to sync. In other cases, the selected item is already initialized
981
+ // in other observers such as `valueChanged`, `_itemsChanged`.
982
+ const valueIndex = this._indexOfValue(this.value, filteredItems);
983
+ if (this.selectedItem === null && valueIndex >= 0) {
984
+ this._selectItemForValue(this.value);
985
+ }
995
986
 
996
- const inputValue = this._inputElementValue;
997
- if (inputValue === undefined || inputValue === this._getItemLabel(this.selectedItem)) {
998
- // When the input element value is the same as the current value or not defined,
999
- // set the focused index to the item that matches the value.
1000
- this._focusedIndex = this.$.dropdown.indexOfLabel(this._getItemLabel(this.selectedItem));
1001
- } else {
1002
- // When the user filled in something that is different from the current value = filtering is enabled,
1003
- // set the focused index to the item that matches the filter query.
1004
- this._focusedIndex = this.$.dropdown.indexOfLabel(this.filter);
1005
- }
987
+ const inputValue = this._inputElementValue;
988
+ if (inputValue === undefined || inputValue === this._getItemLabel(this.selectedItem)) {
989
+ // When the input element value is the same as the current value or not defined,
990
+ // set the focused index to the item that matches the value.
991
+ this._focusedIndex = this.$.dropdown.indexOfLabel(this._getItemLabel(this.selectedItem));
992
+ } else {
993
+ // When the user filled in something that is different from the current value = filtering is enabled,
994
+ // set the focused index to the item that matches the filter query.
995
+ this._focusedIndex = this.$.dropdown.indexOfLabel(this.filter);
1006
996
  }
1007
997
  }
1008
998
 
@@ -212,13 +212,13 @@ declare class ComboBox<TItem = ComboBoxDefaultItem> extends HTMLElement {
212
212
  addEventListener<K extends keyof ComboBoxEventMap<TItem>>(
213
213
  type: K,
214
214
  listener: (this: ComboBox<TItem>, ev: ComboBoxEventMap<TItem>[K]) => void,
215
- options?: boolean | AddEventListenerOptions,
215
+ options?: AddEventListenerOptions | boolean,
216
216
  ): void;
217
217
 
218
218
  removeEventListener<K extends keyof ComboBoxEventMap<TItem>>(
219
219
  type: K,
220
220
  listener: (this: ComboBox<TItem>, ev: ComboBoxEventMap<TItem>[K]) => void,
221
- options?: boolean | EventListenerOptions,
221
+ options?: EventListenerOptions | boolean,
222
222
  ): void;
223
223
  }
224
224