@vaadin/combo-box 23.2.0-dev.53560527d → 23.2.0
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/README.md +4 -4
- package/package.json +20 -14
- package/src/lit/renderer-directives.d.ts +3 -3
- package/src/vaadin-combo-box-data-provider-mixin.d.ts +3 -3
- package/src/vaadin-combo-box-data-provider-mixin.js +29 -31
- package/src/vaadin-combo-box-item.js +1 -1
- package/src/vaadin-combo-box-light.d.ts +21 -10
- package/src/vaadin-combo-box-light.js +43 -8
- package/src/vaadin-combo-box-mixin.d.ts +8 -24
- package/src/vaadin-combo-box-mixin.js +82 -84
- package/src/vaadin-combo-box.d.ts +32 -21
- package/src/vaadin-combo-box.js +3 -2
- package/theme/lumo/vaadin-combo-box-dropdown-styles.js +4 -33
- package/theme/material/vaadin-combo-box-dropdown-styles.js +3 -89
- package/web-types.json +1054 -0
- package/web-types.lit.json +496 -0
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
import { isTouch } from '@vaadin/component-base/src/browser-utils.js';
|
|
7
7
|
import { ControllerMixin } from '@vaadin/component-base/src/controller-mixin.js';
|
|
8
8
|
import { DisabledMixin } from '@vaadin/component-base/src/disabled-mixin.js';
|
|
9
|
+
import { isElementFocused } from '@vaadin/component-base/src/focus-utils.js';
|
|
9
10
|
import { KeyboardMixin } from '@vaadin/component-base/src/keyboard-mixin.js';
|
|
10
11
|
import { processTemplates } from '@vaadin/component-base/src/templates.js';
|
|
11
12
|
import { InputMixin } from '@vaadin/field-base/src/input-mixin.js';
|
|
@@ -236,7 +237,6 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
236
237
|
|
|
237
238
|
static get observers() {
|
|
238
239
|
return [
|
|
239
|
-
'_filterChanged(filter, itemValuePath, itemLabelPath)',
|
|
240
240
|
'_selectedItemChanged(selectedItem, itemValuePath, itemLabelPath)',
|
|
241
241
|
'_openedOrItemsChanged(opened, filteredItems, loading)',
|
|
242
242
|
'_updateScroller(_scroller, filteredItems, opened, loading, selectedItem, itemIdPath, _focusedIndex, renderer, theme)',
|
|
@@ -280,14 +280,26 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
280
280
|
}
|
|
281
281
|
}
|
|
282
282
|
|
|
283
|
+
/**
|
|
284
|
+
* Get a reference to the native `<input>` element.
|
|
285
|
+
* Override to provide a custom input.
|
|
286
|
+
* @protected
|
|
287
|
+
* @return {HTMLInputElement | undefined}
|
|
288
|
+
*/
|
|
289
|
+
get _nativeInput() {
|
|
290
|
+
return this.inputElement;
|
|
291
|
+
}
|
|
292
|
+
|
|
283
293
|
/**
|
|
284
294
|
* Override method inherited from `InputMixin`
|
|
285
295
|
* to customize the input element.
|
|
286
296
|
* @protected
|
|
287
297
|
* @override
|
|
288
298
|
*/
|
|
289
|
-
_inputElementChanged(
|
|
290
|
-
super._inputElementChanged(
|
|
299
|
+
_inputElementChanged(inputElement) {
|
|
300
|
+
super._inputElementChanged(inputElement);
|
|
301
|
+
|
|
302
|
+
const input = this._nativeInput;
|
|
291
303
|
|
|
292
304
|
if (input) {
|
|
293
305
|
input.autocomplete = 'off';
|
|
@@ -382,6 +394,25 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
382
394
|
this.opened = false;
|
|
383
395
|
}
|
|
384
396
|
|
|
397
|
+
/**
|
|
398
|
+
* Override Polymer lifecycle callback to handle `filter` property change after
|
|
399
|
+
* the observer for `opened` property is triggered. This is needed when opening
|
|
400
|
+
* combo-box on user input to ensure the focused index is set correctly.
|
|
401
|
+
*
|
|
402
|
+
* @param {!Object} currentProps Current accessor values
|
|
403
|
+
* @param {?Object} changedProps Properties changed since the last call
|
|
404
|
+
* @param {?Object} oldProps Previous values for each changed property
|
|
405
|
+
* @protected
|
|
406
|
+
* @override
|
|
407
|
+
*/
|
|
408
|
+
_propertiesChanged(currentProps, changedProps, oldProps) {
|
|
409
|
+
super._propertiesChanged(currentProps, changedProps, oldProps);
|
|
410
|
+
|
|
411
|
+
if (changedProps.filter !== undefined) {
|
|
412
|
+
this._filterChanged(changedProps.filter);
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
|
|
385
416
|
/** @private */
|
|
386
417
|
_initOverlay() {
|
|
387
418
|
const overlay = this.$.overlay;
|
|
@@ -395,11 +426,6 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
395
426
|
// Prevent blurring the input when clicking inside the overlay
|
|
396
427
|
overlay.addEventListener('mousedown', (e) => e.preventDefault());
|
|
397
428
|
|
|
398
|
-
// Preventing the default modal behavior of the overlay on input click
|
|
399
|
-
overlay.addEventListener('vaadin-overlay-outside-click', (e) => {
|
|
400
|
-
e.preventDefault();
|
|
401
|
-
});
|
|
402
|
-
|
|
403
429
|
// Manual two-way binding for the overlay "opened" property
|
|
404
430
|
overlay.addEventListener('opened-changed', (e) => {
|
|
405
431
|
this._overlayOpened = e.detail.value;
|
|
@@ -424,9 +450,7 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
424
450
|
};
|
|
425
451
|
|
|
426
452
|
// Ensure the scroller is rendered
|
|
427
|
-
|
|
428
|
-
overlay.requestContentUpdate();
|
|
429
|
-
}
|
|
453
|
+
overlay.requestContentUpdate();
|
|
430
454
|
|
|
431
455
|
const scroller = overlay.querySelector(scrollerTag);
|
|
432
456
|
|
|
@@ -442,6 +466,11 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
442
466
|
// eslint-disable-next-line max-params
|
|
443
467
|
_updateScroller(scroller, items, opened, loading, selectedItem, itemIdPath, focusedIndex, renderer, theme) {
|
|
444
468
|
if (scroller) {
|
|
469
|
+
if (opened) {
|
|
470
|
+
scroller.style.maxHeight =
|
|
471
|
+
getComputedStyle(this).getPropertyValue(`--${this._tagNamePrefix}-overlay-max-height`) || '65vh';
|
|
472
|
+
}
|
|
473
|
+
|
|
445
474
|
scroller.setProperties({
|
|
446
475
|
items: opened ? items : [],
|
|
447
476
|
opened,
|
|
@@ -455,11 +484,6 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
455
484
|
}
|
|
456
485
|
}
|
|
457
486
|
|
|
458
|
-
/** @protected */
|
|
459
|
-
_isOverlayHidden(items, loading) {
|
|
460
|
-
return !loading && !(items && items.length);
|
|
461
|
-
}
|
|
462
|
-
|
|
463
487
|
/** @private */
|
|
464
488
|
_openedOrItemsChanged(opened, items, loading) {
|
|
465
489
|
// Close the overlay if there are no items to display.
|
|
@@ -488,9 +512,14 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
488
512
|
this._updateActiveDescendant(index);
|
|
489
513
|
}
|
|
490
514
|
|
|
515
|
+
/** @protected */
|
|
516
|
+
_isInputFocused() {
|
|
517
|
+
return this.inputElement && isElementFocused(this.inputElement);
|
|
518
|
+
}
|
|
519
|
+
|
|
491
520
|
/** @private */
|
|
492
521
|
_updateActiveDescendant(index) {
|
|
493
|
-
const input = this.
|
|
522
|
+
const input = this._nativeInput;
|
|
494
523
|
if (!input) {
|
|
495
524
|
return;
|
|
496
525
|
}
|
|
@@ -514,19 +543,19 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
514
543
|
this._openedWithFocusRing = this.hasAttribute('focus-ring');
|
|
515
544
|
// For touch devices, we don't want to popup virtual keyboard
|
|
516
545
|
// unless input element is explicitly focused by the user.
|
|
517
|
-
if (!this.
|
|
546
|
+
if (!this._isInputFocused() && !isTouch) {
|
|
518
547
|
this.focus();
|
|
519
548
|
}
|
|
520
549
|
|
|
521
550
|
this.$.overlay.restoreFocusOnClose = true;
|
|
522
551
|
} else {
|
|
523
552
|
this._onClosed();
|
|
524
|
-
if (this._openedWithFocusRing && this.
|
|
553
|
+
if (this._openedWithFocusRing && this._isInputFocused()) {
|
|
525
554
|
this.setAttribute('focus-ring', '');
|
|
526
555
|
}
|
|
527
556
|
}
|
|
528
557
|
|
|
529
|
-
const input = this.
|
|
558
|
+
const input = this._nativeInput;
|
|
530
559
|
if (input) {
|
|
531
560
|
input.setAttribute('aria-expanded', !!opened);
|
|
532
561
|
|
|
@@ -595,8 +624,6 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
595
624
|
|
|
596
625
|
/** @private */
|
|
597
626
|
_onClick(e) {
|
|
598
|
-
this._closeOnBlurIsPrevented = true;
|
|
599
|
-
|
|
600
627
|
const path = e.composedPath();
|
|
601
628
|
|
|
602
629
|
if (this._isClearButton(e)) {
|
|
@@ -606,8 +633,6 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
606
633
|
} else {
|
|
607
634
|
this._onHostClick(e);
|
|
608
635
|
}
|
|
609
|
-
|
|
610
|
-
this._closeOnBlurIsPrevented = false;
|
|
611
636
|
}
|
|
612
637
|
|
|
613
638
|
/**
|
|
@@ -623,16 +648,12 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
623
648
|
if (e.key === 'Tab') {
|
|
624
649
|
this.$.overlay.restoreFocusOnClose = false;
|
|
625
650
|
} else if (e.key === 'ArrowDown') {
|
|
626
|
-
this._closeOnBlurIsPrevented = true;
|
|
627
651
|
this._onArrowDown();
|
|
628
|
-
this._closeOnBlurIsPrevented = false;
|
|
629
652
|
|
|
630
653
|
// Prevent caret from moving
|
|
631
654
|
e.preventDefault();
|
|
632
655
|
} else if (e.key === 'ArrowUp') {
|
|
633
|
-
this._closeOnBlurIsPrevented = true;
|
|
634
656
|
this._onArrowUp();
|
|
635
|
-
this._closeOnBlurIsPrevented = false;
|
|
636
657
|
|
|
637
658
|
// Prevent caret from moving
|
|
638
659
|
e.preventDefault();
|
|
@@ -703,8 +724,7 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
703
724
|
// and there's no need to modify the selection range if the input isn't focused anyway.
|
|
704
725
|
// This affects Safari. When the overlay is open, and then hitting tab, browser should focus
|
|
705
726
|
// the next focusable element instead of the combo-box itself.
|
|
706
|
-
|
|
707
|
-
if (this.hasAttribute('focused')) {
|
|
727
|
+
if (this._isInputFocused() && this.inputElement.setSelectionRange) {
|
|
708
728
|
this.inputElement.setSelectionRange(start, end);
|
|
709
729
|
}
|
|
710
730
|
}
|
|
@@ -814,7 +834,7 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
814
834
|
toggleElement.addEventListener('mousedown', (e) => e.preventDefault());
|
|
815
835
|
// Unfocus previously focused element if focus is not inside combo box (on touch devices)
|
|
816
836
|
toggleElement.addEventListener('click', () => {
|
|
817
|
-
if (isTouch && !this.
|
|
837
|
+
if (isTouch && !this._isInputFocused()) {
|
|
818
838
|
document.activeElement.blur();
|
|
819
839
|
}
|
|
820
840
|
});
|
|
@@ -849,10 +869,6 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
849
869
|
_onOpened() {
|
|
850
870
|
// Defer scroll position adjustment to improve performance.
|
|
851
871
|
requestAnimationFrame(() => {
|
|
852
|
-
// When opened is set as attribute, this logic needs to be delayed until scroller is created.
|
|
853
|
-
this._scroller.style.maxHeight =
|
|
854
|
-
getComputedStyle(this).getPropertyValue(`--${this._tagNamePrefix}-overlay-max-height`) || '65vh';
|
|
855
|
-
|
|
856
872
|
this._scrollIntoView(this._focusedIndex);
|
|
857
873
|
|
|
858
874
|
// Set attribute after the items are rendered when overlay is opened for the first time.
|
|
@@ -925,9 +941,7 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
925
941
|
|
|
926
942
|
this._clearSelectionRange();
|
|
927
943
|
|
|
928
|
-
|
|
929
|
-
this.filter = '';
|
|
930
|
-
}
|
|
944
|
+
this.filter = '';
|
|
931
945
|
}
|
|
932
946
|
|
|
933
947
|
/**
|
|
@@ -945,19 +959,27 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
945
959
|
* @override
|
|
946
960
|
*/
|
|
947
961
|
_onInput(event) {
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
962
|
+
const filter = this._inputElementValue;
|
|
963
|
+
|
|
964
|
+
// When opening dropdown on user input, both `opened` and `filter` properties are set.
|
|
965
|
+
// Perform a batched property update instead of relying on sync property observers.
|
|
966
|
+
// This is necessary to avoid an extra data-provider request for loading first page.
|
|
967
|
+
const props = {};
|
|
951
968
|
|
|
952
|
-
|
|
953
|
-
if (this.filter === value) {
|
|
969
|
+
if (this.filter === filter) {
|
|
954
970
|
// Filter and input value might get out of sync, while keyboard navigating for example.
|
|
955
971
|
// Afterwards, input value might be changed to the same value as used in filtering.
|
|
956
972
|
// In situation like these, we need to make sure all the filter changes handlers are run.
|
|
957
|
-
this._filterChanged(this.filter
|
|
973
|
+
this._filterChanged(this.filter);
|
|
958
974
|
} else {
|
|
959
|
-
|
|
975
|
+
props.filter = filter;
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
if (!this.opened && !this._isClearButton(event) && !this.autoOpenDisabled) {
|
|
979
|
+
props.opened = true;
|
|
960
980
|
}
|
|
981
|
+
|
|
982
|
+
this.setProperties(props);
|
|
961
983
|
}
|
|
962
984
|
|
|
963
985
|
/**
|
|
@@ -980,11 +1002,7 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
980
1002
|
}
|
|
981
1003
|
|
|
982
1004
|
/** @private */
|
|
983
|
-
_filterChanged(filter
|
|
984
|
-
if (filter === undefined) {
|
|
985
|
-
return;
|
|
986
|
-
}
|
|
987
|
-
|
|
1005
|
+
_filterChanged(filter) {
|
|
988
1006
|
// Scroll to the top of the list whenever the filter changes.
|
|
989
1007
|
this._scrollIntoView(0);
|
|
990
1008
|
|
|
@@ -1027,7 +1045,7 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
1027
1045
|
this.value = '';
|
|
1028
1046
|
}
|
|
1029
1047
|
|
|
1030
|
-
this._toggleHasValue(this.
|
|
1048
|
+
this._toggleHasValue(this._hasValue);
|
|
1031
1049
|
this._inputElementValue = this.value;
|
|
1032
1050
|
}
|
|
1033
1051
|
} else {
|
|
@@ -1063,21 +1081,21 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
1063
1081
|
}
|
|
1064
1082
|
|
|
1065
1083
|
if (isValidValue(value)) {
|
|
1066
|
-
let item;
|
|
1067
1084
|
if (this._getItemValue(this.selectedItem) !== value) {
|
|
1068
1085
|
this._selectItemForValue(value);
|
|
1069
|
-
} else {
|
|
1070
|
-
item = this.selectedItem;
|
|
1071
1086
|
}
|
|
1072
1087
|
|
|
1073
|
-
if (!
|
|
1088
|
+
if (!this.selectedItem && this.allowCustomValue) {
|
|
1074
1089
|
this._inputElementValue = value;
|
|
1075
1090
|
}
|
|
1076
1091
|
|
|
1077
|
-
this._toggleHasValue(this.
|
|
1092
|
+
this._toggleHasValue(this._hasValue);
|
|
1078
1093
|
} else {
|
|
1079
1094
|
this.selectedItem = null;
|
|
1080
1095
|
}
|
|
1096
|
+
|
|
1097
|
+
this.filter = '';
|
|
1098
|
+
|
|
1081
1099
|
// In the next _detectAndDispatchChange() call, the change detection should pass
|
|
1082
1100
|
this._lastCommittedValue = undefined;
|
|
1083
1101
|
}
|
|
@@ -1235,9 +1253,6 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
1235
1253
|
if (this.opened) {
|
|
1236
1254
|
this._focusedIndex = this.filteredItems.indexOf(e.detail.item);
|
|
1237
1255
|
this.close();
|
|
1238
|
-
} else if (this.selectedItem !== e.detail.item) {
|
|
1239
|
-
this.selectedItem = e.detail.item;
|
|
1240
|
-
this._detectAndDispatchChange();
|
|
1241
1256
|
}
|
|
1242
1257
|
}
|
|
1243
1258
|
|
|
@@ -1249,6 +1264,12 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
1249
1264
|
|
|
1250
1265
|
/** @private */
|
|
1251
1266
|
_onFocusout(event) {
|
|
1267
|
+
// VoiceOver on iOS fires `focusout` event when moving focus to the item in the dropdown.
|
|
1268
|
+
// Do not focus the input in this case, because it would break announcement for the item.
|
|
1269
|
+
if (event.relatedTarget && event.relatedTarget.localName === `${this._tagNamePrefix}-item`) {
|
|
1270
|
+
return;
|
|
1271
|
+
}
|
|
1272
|
+
|
|
1252
1273
|
// Fixes the problem with `focusout` happening when clicking on the scroll bar on Edge
|
|
1253
1274
|
if (event.relatedTarget === this.$.overlay) {
|
|
1254
1275
|
event.composedPath()[0].focus();
|
|
@@ -1276,35 +1297,12 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
1276
1297
|
this._clear();
|
|
1277
1298
|
}
|
|
1278
1299
|
|
|
1279
|
-
/**
|
|
1280
|
-
* Returns true if `value` is valid, and sets the `invalid` flag appropriately.
|
|
1281
|
-
*
|
|
1282
|
-
* @return {boolean} True if the value is valid and sets the `invalid` flag appropriately
|
|
1283
|
-
*/
|
|
1284
|
-
validate() {
|
|
1285
|
-
return !(this.invalid = !this.checkValidity());
|
|
1286
|
-
}
|
|
1287
|
-
|
|
1288
|
-
/**
|
|
1289
|
-
* Returns true if the current input value satisfies all constraints (if any).
|
|
1290
|
-
* You can override this method for custom validations.
|
|
1291
|
-
*
|
|
1292
|
-
* @return {boolean}
|
|
1293
|
-
*/
|
|
1294
|
-
checkValidity() {
|
|
1295
|
-
if (super.checkValidity) {
|
|
1296
|
-
return super.checkValidity();
|
|
1297
|
-
}
|
|
1298
|
-
|
|
1299
|
-
return !this.required || !!this.value;
|
|
1300
|
-
}
|
|
1301
|
-
|
|
1302
1300
|
/**
|
|
1303
1301
|
* Fired when the value changes.
|
|
1304
1302
|
*
|
|
1305
1303
|
* @event value-changed
|
|
1306
1304
|
* @param {Object} detail
|
|
1307
|
-
*
|
|
1305
|
+
* @param {String} detail.value the combobox value
|
|
1308
1306
|
*/
|
|
1309
1307
|
|
|
1310
1308
|
/**
|
|
@@ -1312,7 +1310,7 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
1312
1310
|
*
|
|
1313
1311
|
* @event selected-item-changed
|
|
1314
1312
|
* @param {Object} detail
|
|
1315
|
-
*
|
|
1313
|
+
* @param {Object|String} detail.value the selected item. Type is the same as the type of `items`.
|
|
1316
1314
|
*/
|
|
1317
1315
|
|
|
1318
1316
|
/**
|
|
@@ -3,24 +3,25 @@
|
|
|
3
3
|
* Copyright (c) 2015 - 2022 Vaadin Ltd.
|
|
4
4
|
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
5
|
*/
|
|
6
|
-
import { ControllerMixinClass } from '@vaadin/component-base/src/controller-mixin.js';
|
|
7
|
-
import { DisabledMixinClass } from '@vaadin/component-base/src/disabled-mixin.js';
|
|
8
|
-
import { ElementMixinClass } from '@vaadin/component-base/src/element-mixin.js';
|
|
9
|
-
import { FocusMixinClass } from '@vaadin/component-base/src/focus-mixin.js';
|
|
10
|
-
import { KeyboardMixinClass } from '@vaadin/component-base/src/keyboard-mixin.js';
|
|
11
|
-
import { DelegateFocusMixinClass } from '@vaadin/field-base/src/delegate-focus-mixin.js';
|
|
12
|
-
import { DelegateStateMixinClass } from '@vaadin/field-base/src/delegate-state-mixin.js';
|
|
13
|
-
import { FieldMixinClass } from '@vaadin/field-base/src/field-mixin.js';
|
|
14
|
-
import { InputConstraintsMixinClass } from '@vaadin/field-base/src/input-constraints-mixin.js';
|
|
15
|
-
import { InputControlMixinClass } from '@vaadin/field-base/src/input-control-mixin.js';
|
|
16
|
-
import { InputMixinClass } from '@vaadin/field-base/src/input-mixin.js';
|
|
17
|
-
import { LabelMixinClass } from '@vaadin/field-base/src/label-mixin.js';
|
|
18
|
-
import { PatternMixinClass } from '@vaadin/field-base/src/pattern-mixin.js';
|
|
19
|
-
import { ValidateMixinClass } from '@vaadin/field-base/src/validate-mixin.js';
|
|
20
|
-
import { ThemableMixinClass } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
6
|
+
import type { ControllerMixinClass } from '@vaadin/component-base/src/controller-mixin.js';
|
|
7
|
+
import type { DisabledMixinClass } from '@vaadin/component-base/src/disabled-mixin.js';
|
|
8
|
+
import type { ElementMixinClass } from '@vaadin/component-base/src/element-mixin.js';
|
|
9
|
+
import type { FocusMixinClass } from '@vaadin/component-base/src/focus-mixin.js';
|
|
10
|
+
import type { KeyboardMixinClass } from '@vaadin/component-base/src/keyboard-mixin.js';
|
|
11
|
+
import type { DelegateFocusMixinClass } from '@vaadin/field-base/src/delegate-focus-mixin.js';
|
|
12
|
+
import type { DelegateStateMixinClass } from '@vaadin/field-base/src/delegate-state-mixin.js';
|
|
13
|
+
import type { FieldMixinClass } from '@vaadin/field-base/src/field-mixin.js';
|
|
14
|
+
import type { InputConstraintsMixinClass } from '@vaadin/field-base/src/input-constraints-mixin.js';
|
|
15
|
+
import type { InputControlMixinClass } from '@vaadin/field-base/src/input-control-mixin.js';
|
|
16
|
+
import type { InputMixinClass } from '@vaadin/field-base/src/input-mixin.js';
|
|
17
|
+
import type { LabelMixinClass } from '@vaadin/field-base/src/label-mixin.js';
|
|
18
|
+
import type { PatternMixinClass } from '@vaadin/field-base/src/pattern-mixin.js';
|
|
19
|
+
import type { ValidateMixinClass } from '@vaadin/field-base/src/validate-mixin.js';
|
|
20
|
+
import type { ThemableMixinClass } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
21
|
+
import type { ThemePropertyMixinClass } from '@vaadin/vaadin-themable-mixin/vaadin-theme-property-mixin.js';
|
|
22
|
+
import type { ComboBoxDataProviderMixinClass } from './vaadin-combo-box-data-provider-mixin.js';
|
|
23
|
+
import type { ComboBoxMixinClass } from './vaadin-combo-box-mixin.js';
|
|
24
|
+
import type { ComboBoxDefaultItem } from './vaadin-combo-box-mixin.js';
|
|
24
25
|
export {
|
|
25
26
|
ComboBoxDataProvider,
|
|
26
27
|
ComboBoxDataProviderCallback,
|
|
@@ -65,6 +66,11 @@ export type ComboBoxFilterChangedEvent = CustomEvent<{ value: string }>;
|
|
|
65
66
|
*/
|
|
66
67
|
export type ComboBoxSelectedItemChangedEvent<TItem> = CustomEvent<{ value: TItem | null | undefined }>;
|
|
67
68
|
|
|
69
|
+
/**
|
|
70
|
+
* Fired whenever the field is validated.
|
|
71
|
+
*/
|
|
72
|
+
export type ComboBoxValidatedEvent = CustomEvent<{ valid: boolean }>;
|
|
73
|
+
|
|
68
74
|
export interface ComboBoxEventMap<TItem> extends HTMLElementEventMap {
|
|
69
75
|
change: ComboBoxChangeEvent<TItem>;
|
|
70
76
|
|
|
@@ -79,6 +85,8 @@ export interface ComboBoxEventMap<TItem> extends HTMLElementEventMap {
|
|
|
79
85
|
'value-changed': ComboBoxValueChangedEvent;
|
|
80
86
|
|
|
81
87
|
'selected-item-changed': ComboBoxSelectedItemChangedEvent<TItem>;
|
|
88
|
+
|
|
89
|
+
validated: ComboBoxValidatedEvent;
|
|
82
90
|
}
|
|
83
91
|
|
|
84
92
|
/**
|
|
@@ -165,6 +173,7 @@ export interface ComboBoxEventMap<TItem> extends HTMLElementEventMap {
|
|
|
165
173
|
* Custom property | Description | Default
|
|
166
174
|
* ----------------------------------------|----------------------------|---------
|
|
167
175
|
* `--vaadin-field-default-width` | Default width of the field | `12em`
|
|
176
|
+
* `--vaadin-combo-box-overlay-width` | Width of the overlay | `auto`
|
|
168
177
|
* `--vaadin-combo-box-overlay-max-height` | Max height of the overlay | `65vh`
|
|
169
178
|
*
|
|
170
179
|
* `<vaadin-combo-box>` provides the same set of shadow DOM parts and state attributes as `<vaadin-text-field>`.
|
|
@@ -198,7 +207,7 @@ export interface ComboBoxEventMap<TItem> extends HTMLElementEventMap {
|
|
|
198
207
|
* Note: the `theme` attribute value set on `<vaadin-combo-box>` is
|
|
199
208
|
* propagated to the internal components listed above.
|
|
200
209
|
*
|
|
201
|
-
* See [Styling Components](https://vaadin.com/docs/latest/
|
|
210
|
+
* See [Styling Components](https://vaadin.com/docs/latest/styling/custom-theme/styling-components) documentation.
|
|
202
211
|
*
|
|
203
212
|
* @fires {Event} change - Fired when the user commits a value change.
|
|
204
213
|
* @fires {CustomEvent} custom-value-set - Fired when the user sets a custom value.
|
|
@@ -207,18 +216,19 @@ export interface ComboBoxEventMap<TItem> extends HTMLElementEventMap {
|
|
|
207
216
|
* @fires {CustomEvent} opened-changed - Fired when the `opened` property changes.
|
|
208
217
|
* @fires {CustomEvent} selected-item-changed - Fired when the `selectedItem` property changes.
|
|
209
218
|
* @fires {CustomEvent} value-changed - Fired when the `value` property changes.
|
|
219
|
+
* @fires {CustomEvent} validated - Fired whenever the field is validated.
|
|
210
220
|
*/
|
|
211
221
|
declare class ComboBox<TItem = ComboBoxDefaultItem> extends HTMLElement {
|
|
212
222
|
addEventListener<K extends keyof ComboBoxEventMap<TItem>>(
|
|
213
223
|
type: K,
|
|
214
224
|
listener: (this: ComboBox<TItem>, ev: ComboBoxEventMap<TItem>[K]) => void,
|
|
215
|
-
options?:
|
|
225
|
+
options?: AddEventListenerOptions | boolean,
|
|
216
226
|
): void;
|
|
217
227
|
|
|
218
228
|
removeEventListener<K extends keyof ComboBoxEventMap<TItem>>(
|
|
219
229
|
type: K,
|
|
220
230
|
listener: (this: ComboBox<TItem>, ev: ComboBoxEventMap<TItem>[K]) => void,
|
|
221
|
-
options?:
|
|
231
|
+
options?: EventListenerOptions | boolean,
|
|
222
232
|
): void;
|
|
223
233
|
}
|
|
224
234
|
|
|
@@ -238,6 +248,7 @@ interface ComboBox<TItem = ComboBoxDefaultItem>
|
|
|
238
248
|
DelegateStateMixinClass,
|
|
239
249
|
DelegateFocusMixinClass,
|
|
240
250
|
ThemableMixinClass,
|
|
251
|
+
ThemePropertyMixinClass,
|
|
241
252
|
ElementMixinClass,
|
|
242
253
|
ControllerMixinClass {}
|
|
243
254
|
|
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>`.
|
|
@@ -137,7 +138,7 @@ registerStyles('vaadin-combo-box', inputFieldShared, { moduleId: 'vaadin-combo-b
|
|
|
137
138
|
* Note: the `theme` attribute value set on `<vaadin-combo-box>` is
|
|
138
139
|
* propagated to the internal components listed above.
|
|
139
140
|
*
|
|
140
|
-
* See [Styling Components](https://vaadin.com/docs/latest/
|
|
141
|
+
* See [Styling Components](https://vaadin.com/docs/latest/styling/custom-theme/styling-components) documentation.
|
|
141
142
|
*
|
|
142
143
|
* @fires {Event} change - Fired when the user commits a value change.
|
|
143
144
|
* @fires {CustomEvent} custom-value-set - Fired when the user sets a custom value.
|
|
@@ -146,6 +147,7 @@ registerStyles('vaadin-combo-box', inputFieldShared, { moduleId: 'vaadin-combo-b
|
|
|
146
147
|
* @fires {CustomEvent} opened-changed - Fired when the `opened` property changes.
|
|
147
148
|
* @fires {CustomEvent} selected-item-changed - Fired when the `selectedItem` property changes.
|
|
148
149
|
* @fires {CustomEvent} value-changed - Fired when the `value` property changes.
|
|
150
|
+
* @fires {CustomEvent} validated - Fired whenever the field is validated.
|
|
149
151
|
*
|
|
150
152
|
* @extends HTMLElement
|
|
151
153
|
* @mixes ElementMixin
|
|
@@ -200,7 +202,6 @@ class ComboBox extends ComboBoxDataProviderMixin(
|
|
|
200
202
|
|
|
201
203
|
<vaadin-combo-box-overlay
|
|
202
204
|
id="overlay"
|
|
203
|
-
hidden$="[[_isOverlayHidden(filteredItems, loading)]]"
|
|
204
205
|
opened="[[_overlayOpened]]"
|
|
205
206
|
loading$="[[loading]]"
|
|
206
207
|
theme$="[[_theme]]"
|
|
@@ -2,6 +2,7 @@ import '@vaadin/vaadin-lumo-styles/color.js';
|
|
|
2
2
|
import '@vaadin/vaadin-lumo-styles/spacing.js';
|
|
3
3
|
import '@vaadin/vaadin-lumo-styles/style.js';
|
|
4
4
|
import '@vaadin/vaadin-overlay/theme/lumo/vaadin-overlay.js';
|
|
5
|
+
import { loader } from '@vaadin/vaadin-lumo-styles/mixins/loader.js';
|
|
5
6
|
import { menuOverlayCore } from '@vaadin/vaadin-lumo-styles/mixins/menu-overlay.js';
|
|
6
7
|
import { overlay } from '@vaadin/vaadin-lumo-styles/mixins/overlay.js';
|
|
7
8
|
import { css, registerStyles } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
@@ -36,10 +37,7 @@ const comboBoxOverlay = css`
|
|
|
36
37
|
margin-bottom: var(--lumo-space-xs);
|
|
37
38
|
}
|
|
38
39
|
|
|
39
|
-
|
|
40
|
-
box-sizing: border-box;
|
|
41
|
-
width: var(--lumo-icon-size-s);
|
|
42
|
-
height: var(--lumo-icon-size-s);
|
|
40
|
+
[part~='loader'] {
|
|
43
41
|
position: absolute;
|
|
44
42
|
z-index: 1;
|
|
45
43
|
left: var(--lumo-space-s);
|
|
@@ -48,38 +46,11 @@ const comboBoxOverlay = css`
|
|
|
48
46
|
margin-left: auto;
|
|
49
47
|
margin-inline-start: auto;
|
|
50
48
|
margin-inline-end: 0;
|
|
51
|
-
border: 2px solid transparent;
|
|
52
|
-
border-color: var(--lumo-primary-color-50pct) var(--lumo-primary-color-50pct) var(--lumo-primary-color)
|
|
53
|
-
var(--lumo-primary-color);
|
|
54
|
-
border-radius: calc(0.5 * var(--lumo-icon-size-s));
|
|
55
|
-
opacity: 0;
|
|
56
|
-
animation: 1s linear infinite lumo-combo-box-loader-rotate, 0.3s 0.1s lumo-combo-box-loader-fade-in both;
|
|
57
|
-
pointer-events: none;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
@keyframes lumo-combo-box-loader-fade-in {
|
|
61
|
-
0% {
|
|
62
|
-
opacity: 0;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
100% {
|
|
66
|
-
opacity: 1;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
@keyframes lumo-combo-box-loader-rotate {
|
|
71
|
-
0% {
|
|
72
|
-
transform: rotate(0deg);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
100% {
|
|
76
|
-
transform: rotate(360deg);
|
|
77
|
-
}
|
|
78
49
|
}
|
|
79
50
|
|
|
80
51
|
/* RTL specific styles */
|
|
81
52
|
|
|
82
|
-
:host([
|
|
53
|
+
:host([dir='rtl']) [part~='loader'] {
|
|
83
54
|
left: auto;
|
|
84
55
|
margin-left: 0;
|
|
85
56
|
margin-right: auto;
|
|
@@ -88,6 +59,6 @@ const comboBoxOverlay = css`
|
|
|
88
59
|
}
|
|
89
60
|
`;
|
|
90
61
|
|
|
91
|
-
registerStyles('vaadin-combo-box-overlay', [overlay, menuOverlayCore, comboBoxOverlay], {
|
|
62
|
+
registerStyles('vaadin-combo-box-overlay', [overlay, menuOverlayCore, comboBoxOverlay, loader], {
|
|
92
63
|
moduleId: 'lumo-combo-box-overlay',
|
|
93
64
|
});
|