@vaadin/vaadin-combo-box 5.4.8 → 5.4.12

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
@@ -10,7 +10,7 @@
10
10
  "repository": "vaadin/vaadin-combo-box",
11
11
  "homepage": "https://vaadin.com/components",
12
12
  "name": "@vaadin/vaadin-combo-box",
13
- "version": "5.4.8",
13
+ "version": "5.4.12",
14
14
  "main": "vaadin-combo-box.js",
15
15
  "author": "Vaadin Ltd",
16
16
  "license": "Apache-2.0",
@@ -25,8 +25,6 @@
25
25
  "theme"
26
26
  ],
27
27
  "resolutions": {
28
- "es-abstract": "1.17.6",
29
- "@types/doctrine": "0.0.3",
30
28
  "inherits": "2.0.3",
31
29
  "samsam": "1.1.3",
32
30
  "supports-color": "3.1.2",
@@ -48,9 +46,12 @@
48
46
  "@vaadin/vaadin-element-mixin": "^2.4.1"
49
47
  },
50
48
  "scripts": {
51
- "generate-typings": "gen-typescript-declarations --outDir . --verify"
49
+ "generate-typings": "gen-typescript-declarations --outDir . --verify",
50
+ "test": "wct --npm"
52
51
  },
53
52
  "devDependencies": {
53
+ "@web-padawan/gen-typescript-declarations": "^1.6.2",
54
+ "web-component-tester": "6.9.2",
54
55
  "@polymer/iron-form": "^3.0.0",
55
56
  "@polymer/iron-component-page": "^4.0.0",
56
57
  "@polymer/iron-test-helpers": "^3.0.0",
@@ -23,6 +23,9 @@ $_documentContainer.innerHTML = `<dom-module id="vaadin-combo-box-overlay-styles
23
23
  </dom-module>`;
24
24
 
25
25
  document.head.appendChild($_documentContainer.content);
26
+ let memoizedTemplate;
27
+
28
+
26
29
  /**
27
30
  * The overlay element.
28
31
  *
@@ -41,6 +44,26 @@ class ComboBoxOverlayElement extends OverlayElement {
41
44
  return 'vaadin-combo-box-overlay';
42
45
  }
43
46
 
47
+ static get properties() {
48
+ return {
49
+ /**
50
+ * The element to position/align the dropdown by.
51
+ */
52
+ positionTarget: {
53
+ type: Object
54
+ }
55
+ };
56
+ }
57
+
58
+ static get template() {
59
+ if (!memoizedTemplate) {
60
+ memoizedTemplate = super.template.cloneNode(true);
61
+ memoizedTemplate.content.querySelector('[part~="overlay"]').removeAttribute('tabindex');
62
+ }
63
+
64
+ return memoizedTemplate;
65
+ }
66
+
44
67
  connectedCallback() {
45
68
  super.connectedCallback();
46
69
 
@@ -60,6 +83,19 @@ class ComboBoxOverlayElement extends OverlayElement {
60
83
  const content = this.shadowRoot.querySelector('[part~="content"]');
61
84
  content.parentNode.insertBefore(loader, content);
62
85
  }
86
+
87
+ /**
88
+ * Override OverlayElement._outsideClickListener to prevent closing the
89
+ * overlay when clicking into the combo box input element
90
+ * @param event
91
+ * @private
92
+ */
93
+ _outsideClickListener(event) {
94
+ const eventPath = event.composedPath();
95
+ if (eventPath.indexOf(this.positionTarget) < 0 && eventPath.indexOf(this) < 0) {
96
+ this.close();
97
+ }
98
+ }
63
99
  }
64
100
 
65
101
  customElements.define(ComboBoxOverlayElement.is, ComboBoxOverlayElement);
@@ -83,7 +119,7 @@ class ComboBoxDropdownElement extends DisableUpgradeMixin(
83
119
  display: none;
84
120
  }
85
121
  </style>
86
- <vaadin-combo-box-overlay id="overlay" hidden\$="[[hidden]]" opened="[[opened]]" template="{{template}}" style="align-items: stretch; margin: 0;" theme\$="[[theme]]">
122
+ <vaadin-combo-box-overlay id="overlay" hidden\$="[[hidden]]" position-target="[[positionTarget]]" opened="{{opened}}" template="{{template}}" style="align-items: stretch; margin: 0;" theme\$="[[theme]]">
87
123
  <slot></slot>
88
124
  </vaadin-combo-box-overlay>
89
125
  `;
@@ -130,7 +166,6 @@ class ComboBoxDropdownElement extends DisableUpgradeMixin(
130
166
  constructor() {
131
167
  super();
132
168
  this._boundSetPosition = this._setPosition.bind(this);
133
- this._boundOutsideClickListener = this._outsideClickListener.bind(this);
134
169
  }
135
170
 
136
171
  connectedCallback() {
@@ -186,26 +221,13 @@ class ComboBoxDropdownElement extends DisableUpgradeMixin(
186
221
  this._setPosition();
187
222
 
188
223
  window.addEventListener('scroll', this._boundSetPosition, true);
189
- document.addEventListener('click', this._boundOutsideClickListener, true);
190
224
  this.dispatchEvent(new CustomEvent('vaadin-combo-box-dropdown-opened', {bubbles: true, composed: true}));
191
225
  } else if (!this.__emptyItems) {
192
226
  window.removeEventListener('scroll', this._boundSetPosition, true);
193
- document.removeEventListener('click', this._boundOutsideClickListener, true);
194
227
  this.dispatchEvent(new CustomEvent('vaadin-combo-box-dropdown-closed', {bubbles: true, composed: true}));
195
228
  }
196
229
  }
197
230
 
198
-
199
- // We need to listen on 'click' event and capture it and close the overlay before
200
- // propagating the event to the listener in the button. Otherwise, if the clicked button would call
201
- // open(), this would happen: https://www.youtube.com/watch?v=Z86V_ICUCD4
202
- _outsideClickListener(event) {
203
- const eventPath = event.composedPath();
204
- if (eventPath.indexOf(this.positionTarget) < 0 && eventPath.indexOf(this.$.overlay) < 0) {
205
- this.opened = false;
206
- }
207
- }
208
-
209
231
  _isPositionFixed(element) {
210
232
  const offsetParent = this._getOffsetParent(element);
211
233
 
@@ -576,16 +576,36 @@ export const ComboBoxMixin = subclass => class VaadinComboBoxMixinElement extend
576
576
  */
577
577
  _onEscape(e) {
578
578
  if (this.autoOpenDisabled) {
579
- this._focusedIndex = -1;
580
- this.cancel();
581
- } else if (this.opened) {
582
- this._stopPropagation(e);
583
-
584
- if (this._focusedIndex > -1) {
579
+ // Auto-open is disabled
580
+ if (this.opened || (this.value !== this._inputElementValue && this._inputElementValue.length > 0)) {
581
+ // The overlay is open or
582
+ // the input value has changed but the change hasn't been committed, so cancel it.
583
+ this._stopPropagation(e);
585
584
  this._focusedIndex = -1;
586
- this._revertInputValue();
587
- } else {
588
585
  this.cancel();
586
+ } else if (this.clearButtonVisible && !this.opened && !!this.value) {
587
+ this._stopPropagation(e);
588
+ // The clear button is visible and the overlay is closed, so clear the value.
589
+ this._clear();
590
+ }
591
+ } else {
592
+ // Auto-open is enabled
593
+ if (this.opened) {
594
+ // The overlay is open
595
+ this._stopPropagation(e);
596
+
597
+ if (this._focusedIndex > -1) {
598
+ // An item is focused, revert the input to the filtered value
599
+ this._focusedIndex = -1;
600
+ this._revertInputValue();
601
+ } else {
602
+ // No item is focused, cancel the change and close the overlay
603
+ this.cancel();
604
+ }
605
+ } else if (this.clearButtonVisible && !!this.value) {
606
+ this._stopPropagation(e);
607
+ // The clear button is visible and the overlay is closed, so clear the value.
608
+ this._clear();
589
609
  }
590
610
  }
591
611
  }
@@ -684,13 +704,19 @@ export const ComboBoxMixin = subclass => class VaadinComboBoxMixinElement extend
684
704
  }
685
705
  } else {
686
706
  const toLowerCase = (item) => item && item.toLowerCase && item.toLowerCase();
687
- const itemsMatchedByLabel = this.filteredItems
688
- && this.filteredItems.filter(item => toLowerCase(this._getItemLabel(item)) === toLowerCase(this._inputElementValue))
689
- || [];
707
+
708
+ // Try to find an item whose label matches the input value. A matching item is searched from
709
+ // the filteredItems array (if available) and the selectedItem (if available).
710
+ const itemMatchingByLabel = [...(this.filteredItems || []), this.selectedItem].filter((item) => {
711
+ return toLowerCase(this._getItemLabel(item)) === toLowerCase(this._inputElementValue);
712
+ })[0];
713
+
690
714
  if (this.allowCustomValue
691
715
  // to prevent a repetitive input value being saved after pressing ESC and Tab.
692
- && !itemsMatchedByLabel.length) {
716
+ && !itemMatchingByLabel) {
693
717
 
718
+ // An item matching by label was not found, but custom values are allowed.
719
+ // Dispatch a custom-value-set event with the input value.
694
720
  const e = new CustomEvent('custom-value-set', {detail: this._inputElementValue, composed: true, cancelable: true, bubbles: true});
695
721
  this.dispatchEvent(e);
696
722
  if (!e.defaultPrevented) {
@@ -698,9 +724,11 @@ export const ComboBoxMixin = subclass => class VaadinComboBoxMixinElement extend
698
724
  this._selectItemForValue(customValue);
699
725
  this.value = customValue;
700
726
  }
701
- } else if (!this.allowCustomValue && !this.opened && itemsMatchedByLabel.length > 0) {
702
- this.value = this._getItemValue(itemsMatchedByLabel[0]);
727
+ } else if (!this.allowCustomValue && !this.opened && itemMatchingByLabel) {
728
+ // An item matching by label was found, select it.
729
+ this.value = this._getItemValue(itemMatchingByLabel);
703
730
  } else {
731
+ // Revert the input value
704
732
  this._inputElementValue = this.selectedItem ? this._getItemLabel(this.selectedItem) : (this.value || '');
705
733
  }
706
734
  }
@@ -229,7 +229,7 @@ class ComboBoxElement extends
229
229
  }
230
230
 
231
231
  static get version() {
232
- return '5.4.8';
232
+ return '5.4.12';
233
233
  }
234
234
 
235
235
  static get properties() {
@@ -358,12 +358,8 @@ class ComboBoxElement extends
358
358
  // Stop propagation of Esc in capturing phase so that
359
359
  // vaadin-text-field will not handle Esc as a shortcut
360
360
  // to clear the value.
361
- // We need to set this listener for "this.inputElement"
362
- // instead of just "this", otherwise keyboard navigation behaviour
363
- // breaks a bit on Safari and some related tests fail.
364
- this.inputElement.addEventListener('keydown', e => {
361
+ this.addEventListener('keydown', e => {
365
362
  if (this._isEventKey(e, 'esc')) {
366
- this._stopPropagation(e);
367
363
  // Trigger _onEscape method of vaadin-combo-box-mixin because
368
364
  // bubbling phase is not reached.
369
365
  this._onEscape(e);