@vaadin/combo-box 23.0.3 → 23.0.6

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.0.3",
3
+ "version": "23.0.6",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -34,23 +34,23 @@
34
34
  "dependencies": {
35
35
  "@open-wc/dedupe-mixin": "^1.3.0",
36
36
  "@polymer/polymer": "^3.0.0",
37
- "@vaadin/component-base": "^23.0.3",
38
- "@vaadin/field-base": "^23.0.3",
39
- "@vaadin/input-container": "^23.0.3",
40
- "@vaadin/item": "^23.0.3",
41
- "@vaadin/vaadin-lumo-styles": "^23.0.3",
42
- "@vaadin/vaadin-material-styles": "^23.0.3",
43
- "@vaadin/vaadin-overlay": "^23.0.3",
44
- "@vaadin/vaadin-themable-mixin": "^23.0.3"
37
+ "@vaadin/component-base": "^23.0.6",
38
+ "@vaadin/field-base": "^23.0.6",
39
+ "@vaadin/input-container": "^23.0.6",
40
+ "@vaadin/item": "^23.0.6",
41
+ "@vaadin/vaadin-lumo-styles": "^23.0.6",
42
+ "@vaadin/vaadin-material-styles": "^23.0.6",
43
+ "@vaadin/vaadin-overlay": "^23.0.6",
44
+ "@vaadin/vaadin-themable-mixin": "^23.0.6"
45
45
  },
46
46
  "devDependencies": {
47
47
  "@esm-bundle/chai": "^4.3.4",
48
- "@vaadin/dialog": "^23.0.3",
49
- "@vaadin/polymer-legacy-adapter": "^23.0.3",
48
+ "@vaadin/dialog": "^23.0.6",
49
+ "@vaadin/polymer-legacy-adapter": "^23.0.6",
50
50
  "@vaadin/testing-helpers": "^0.3.2",
51
- "@vaadin/text-field": "^23.0.3",
51
+ "@vaadin/text-field": "^23.0.6",
52
52
  "lit": "^2.0.0",
53
53
  "sinon": "^9.2.0"
54
54
  },
55
- "gitHead": "3f010a4167c9e04405c9dfab098da0821e02a601"
55
+ "gitHead": "82ca8522e24a63343fb28bcb4c686e55d25c8858"
56
56
  }
@@ -576,20 +576,27 @@ export const ComboBoxMixin = (subclass) =>
576
576
 
577
577
  /** @private */
578
578
  _onEnter(e) {
579
- // should close on enter when custom values are allowed, input field is cleared, or when an existing
580
- // item is focused with keyboard. If auto open is disabled, under the same conditions, commit value.
581
- if (
582
- (this.opened || this.autoOpenDisabled) &&
583
- (this.allowCustomValue || this._inputElementValue === '' || this._focusedIndex > -1)
584
- ) {
585
- this._closeOrCommit();
586
-
579
+ // do not commit value when custom values are disallowed and input value is not a valid option
580
+ // also stop propagation of the event, otherwise the user could submit a form while the input
581
+ // still contains an invalid value
582
+ if (!this.allowCustomValue && this._inputElementValue !== '' && this._focusedIndex < 0) {
587
583
  // Do not submit the surrounding form.
588
584
  e.preventDefault();
585
+ // Do not trigger global listeners
586
+ e.stopPropagation();
587
+ return;
588
+ }
589
589
 
590
+ // stop propagation of the enter event only if the dropdown is opened, this
591
+ // "consumes" the enter event for the action of closing the dropdown
592
+ if (this.opened) {
593
+ // Do not submit the surrounding form.
594
+ e.preventDefault();
590
595
  // Do not trigger global listeners
591
596
  e.stopPropagation();
592
597
  }
598
+
599
+ this._closeOrCommit();
593
600
  }
594
601
 
595
602
  /**
@@ -960,21 +967,23 @@ export const ComboBoxMixin = (subclass) =>
960
967
  if (e.path === 'filteredItems' || e.path === 'filteredItems.splices') {
961
968
  this._setOverlayItems(this.filteredItems);
962
969
 
963
- const filterIndex = this.$.dropdown.indexOfLabel(this.filter);
964
- if (this.opened) {
965
- this._focusedIndex = filterIndex;
966
- } else {
967
- // Pre-select item matching the filter to focus it later when overlay opens
968
- const valueIndex = this._indexOfValue(this.value, this.filteredItems);
969
- this._focusedIndex = filterIndex === -1 ? valueIndex : filterIndex;
970
+ // When the external filtering is used and `value` was provided before `filteredItems`,
971
+ // initialize the selected item with the current value here. This will also cause
972
+ // the input element value to sync. In other cases, the selected item is already initialized
973
+ // in other observers such as `valueChanged`, `_itemsOrPathsChanged`.
974
+ const valueIndex = this._indexOfValue(this.value, this.filteredItems);
975
+ if (this.selectedItem === null && valueIndex >= 0) {
976
+ this._selectItemForValue(this.value);
970
977
  }
971
978
 
972
- // see https://github.com/vaadin/web-components/issues/2615
973
- if (this.selectedItem === null && this._focusedIndex >= 0) {
974
- const filteredItem = this.filteredItems[this._focusedIndex];
975
- if (this._getItemValue(filteredItem) === this.value) {
976
- this._selectItemForValue(this.value);
977
- }
979
+ if (this._inputElementValue === undefined || this._inputElementValue === this.value) {
980
+ // When the input element value is the same as the current value or not defined,
981
+ // set the focused index to the item that matches the value.
982
+ this._focusedIndex = this._indexOfValue(this.value, this.filteredItems);
983
+ } else {
984
+ // When the user filled in something that is different from the current value = filtering is enabled,
985
+ // set the focused index to the item that matches the filter query.
986
+ this._focusedIndex = this.$.dropdown.indexOfLabel(this.filter);
978
987
  }
979
988
  }
980
989
  }
@@ -999,12 +1008,13 @@ export const ComboBoxMixin = (subclass) =>
999
1008
  const valueIndex = this._indexOfValue(value, this.filteredItems);
1000
1009
  const previouslySelectedItem = this.selectedItem;
1001
1010
 
1002
- this.selectedItem =
1003
- valueIndex >= 0
1004
- ? this.filteredItems[valueIndex]
1005
- : this.dataProvider && this.selectedItem === undefined
1006
- ? undefined
1007
- : null;
1011
+ if (valueIndex >= 0) {
1012
+ this.selectedItem = this.filteredItems[valueIndex];
1013
+ } else if (this.dataProvider && this.selectedItem === undefined) {
1014
+ this.selectedItem = undefined;
1015
+ } else {
1016
+ this.selectedItem = null;
1017
+ }
1008
1018
 
1009
1019
  if (this.selectedItem === null && previouslySelectedItem === null) {
1010
1020
  this._selectedItemChanged(this.selectedItem);
@@ -1028,15 +1038,17 @@ export const ComboBoxMixin = (subclass) =>
1028
1038
 
1029
1039
  /** @private */
1030
1040
  _indexOfValue(value, items) {
1031
- if (items && this._isValidValue(value)) {
1032
- for (let i = 0; i < items.length; i++) {
1033
- if (items[i] !== this.__placeHolder && this._getItemValue(items[i]) === value) {
1034
- return i;
1035
- }
1036
- }
1041
+ if (!items || !this._isValidValue(value)) {
1042
+ return -1;
1037
1043
  }
1038
1044
 
1039
- return -1;
1045
+ return items.findIndex((item) => {
1046
+ if (item instanceof ComboBoxPlaceholder) {
1047
+ return false;
1048
+ }
1049
+
1050
+ return this._getItemValue(item) === value;
1051
+ });
1040
1052
  }
1041
1053
 
1042
1054
  /**
@@ -250,9 +250,16 @@ export class ComboBoxScroller extends PolymerElement {
250
250
  }
251
251
 
252
252
  /** @private */
253
- __focusedIndexChanged(index) {
254
- if (this.__virtualizer && index >= 0) {
253
+ __focusedIndexChanged(index, oldIndex) {
254
+ if (!this.__virtualizer) {
255
+ return;
256
+ }
257
+
258
+ if (index !== oldIndex) {
255
259
  this.requestContentUpdate();
260
+ }
261
+
262
+ if (index >= 0) {
256
263
  this.scrollIntoView(index);
257
264
  }
258
265
  }