@vaadin/combo-box 23.2.0-alpha2 → 23.2.0-alpha5
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 +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-light.d.ts +21 -10
- package/src/vaadin-combo-box-light.js +4 -2
- package/src/vaadin-combo-box-mixin.d.ts +8 -24
- package/src/vaadin-combo-box-mixin.js +53 -69
- package/src/vaadin-combo-box.d.ts +31 -20
- package/src/vaadin-combo-box.js +2 -1
- package/web-types.json +1054 -0
- package/web-types.lit.json +496 -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-alpha5",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -24,7 +24,9 @@
|
|
|
24
24
|
"src",
|
|
25
25
|
"theme",
|
|
26
26
|
"vaadin-*.d.ts",
|
|
27
|
-
"vaadin-*.js"
|
|
27
|
+
"vaadin-*.js",
|
|
28
|
+
"web-types.json",
|
|
29
|
+
"web-types.lit.json"
|
|
28
30
|
],
|
|
29
31
|
"keywords": [
|
|
30
32
|
"Vaadin",
|
|
@@ -36,23 +38,27 @@
|
|
|
36
38
|
"dependencies": {
|
|
37
39
|
"@open-wc/dedupe-mixin": "^1.3.0",
|
|
38
40
|
"@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-
|
|
41
|
+
"@vaadin/component-base": "23.2.0-alpha5",
|
|
42
|
+
"@vaadin/field-base": "23.2.0-alpha5",
|
|
43
|
+
"@vaadin/input-container": "23.2.0-alpha5",
|
|
44
|
+
"@vaadin/item": "23.2.0-alpha5",
|
|
45
|
+
"@vaadin/lit-renderer": "23.2.0-alpha5",
|
|
46
|
+
"@vaadin/vaadin-lumo-styles": "23.2.0-alpha5",
|
|
47
|
+
"@vaadin/vaadin-material-styles": "23.2.0-alpha5",
|
|
48
|
+
"@vaadin/vaadin-overlay": "23.2.0-alpha5",
|
|
49
|
+
"@vaadin/vaadin-themable-mixin": "23.2.0-alpha5"
|
|
48
50
|
},
|
|
49
51
|
"devDependencies": {
|
|
50
52
|
"@esm-bundle/chai": "^4.3.4",
|
|
51
|
-
"@vaadin/polymer-legacy-adapter": "23.2.0-
|
|
53
|
+
"@vaadin/polymer-legacy-adapter": "23.2.0-alpha5",
|
|
52
54
|
"@vaadin/testing-helpers": "^0.3.2",
|
|
53
|
-
"@vaadin/text-field": "23.2.0-
|
|
55
|
+
"@vaadin/text-field": "23.2.0-alpha5",
|
|
54
56
|
"lit": "^2.0.0",
|
|
55
57
|
"sinon": "^13.0.2"
|
|
56
58
|
},
|
|
57
|
-
"
|
|
59
|
+
"web-types": [
|
|
60
|
+
"web-types.json",
|
|
61
|
+
"web-types.lit.json"
|
|
62
|
+
],
|
|
63
|
+
"gitHead": "c6247fd741d61096d75a71feda4a1faf88b6f0ce"
|
|
58
64
|
}
|
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
* Copyright (c) 2017 - 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 { TemplateResult } from 'lit';
|
|
7
|
-
import { DirectiveResult } from 'lit/directive.js';
|
|
6
|
+
import type { TemplateResult } from 'lit';
|
|
7
|
+
import type { DirectiveResult } from 'lit/directive.js';
|
|
8
8
|
import { LitRendererDirective } from '@vaadin/lit-renderer';
|
|
9
|
-
import { ComboBox, ComboBoxItemModel } from '../vaadin-combo-box.js';
|
|
9
|
+
import type { ComboBox, ComboBoxItemModel } from '../vaadin-combo-box.js';
|
|
10
10
|
|
|
11
11
|
export type ComboBoxLitRenderer<TItem> = (
|
|
12
12
|
item: TItem,
|
|
@@ -3,9 +3,9 @@
|
|
|
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 { Constructor } from '@open-wc/dedupe-mixin';
|
|
6
|
+
import type { Constructor } from '@open-wc/dedupe-mixin';
|
|
7
7
|
|
|
8
|
-
export type ComboBoxDataProviderCallback<TItem> = (items: TItem[], size
|
|
8
|
+
export type ComboBoxDataProviderCallback<TItem> = (items: TItem[], size?: number) => void;
|
|
9
9
|
|
|
10
10
|
export interface ComboBoxDataProviderParams {
|
|
11
11
|
page: number;
|
|
@@ -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
|
-
):
|
|
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
|
|
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 */
|
|
@@ -196,10 +186,13 @@ export const ComboBoxDataProviderMixin = (superClass) =>
|
|
|
196
186
|
filteredItems.splice(params.page * params.pageSize, items.length, ...items);
|
|
197
187
|
this.filteredItems = filteredItems;
|
|
198
188
|
|
|
199
|
-
if (!this.opened && !this.
|
|
189
|
+
if (!this.opened && !this._isInputFocused()) {
|
|
200
190
|
this._commitValue();
|
|
201
191
|
}
|
|
202
|
-
|
|
192
|
+
|
|
193
|
+
if (size !== undefined) {
|
|
194
|
+
this.size = size;
|
|
195
|
+
}
|
|
203
196
|
|
|
204
197
|
delete this._pendingRequests[page];
|
|
205
198
|
|
|
@@ -229,13 +222,16 @@ export const ComboBoxDataProviderMixin = (superClass) =>
|
|
|
229
222
|
if (!this.dataProvider) {
|
|
230
223
|
return;
|
|
231
224
|
}
|
|
225
|
+
|
|
232
226
|
this._pendingRequests = {};
|
|
233
227
|
const filteredItems = [];
|
|
234
228
|
for (let i = 0; i < (this.size || 0); i++) {
|
|
235
229
|
filteredItems.push(this.__placeHolder);
|
|
236
230
|
}
|
|
237
231
|
this.filteredItems = filteredItems;
|
|
232
|
+
|
|
238
233
|
if (this._shouldFetchData()) {
|
|
234
|
+
this._forceNextRequest = false;
|
|
239
235
|
this._loadPage(0);
|
|
240
236
|
} else {
|
|
241
237
|
this._forceNextRequest = true;
|
|
@@ -269,6 +265,8 @@ export const ComboBoxDataProviderMixin = (superClass) =>
|
|
|
269
265
|
this._ensureItemsOrDataProvider(() => {
|
|
270
266
|
this.dataProvider = oldDataProvider;
|
|
271
267
|
});
|
|
268
|
+
|
|
269
|
+
this.clearCache();
|
|
272
270
|
}
|
|
273
271
|
|
|
274
272
|
/** @private */
|
|
@@ -3,13 +3,14 @@
|
|
|
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 { DisabledMixinClass } from '@vaadin/component-base/src/disabled-mixin.js';
|
|
7
|
-
import { KeyboardMixinClass } from '@vaadin/component-base/src/keyboard-mixin.js';
|
|
8
|
-
import { InputMixinClass } from '@vaadin/field-base/src/input-mixin.js';
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
6
|
+
import type { DisabledMixinClass } from '@vaadin/component-base/src/disabled-mixin.js';
|
|
7
|
+
import type { KeyboardMixinClass } from '@vaadin/component-base/src/keyboard-mixin.js';
|
|
8
|
+
import type { InputMixinClass } from '@vaadin/field-base/src/input-mixin.js';
|
|
9
|
+
import type { ValidateMixinClass } from '@vaadin/field-base/src/validate-mixin.js';
|
|
10
|
+
import type { ThemableMixinClass } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
11
|
+
import type { ThemePropertyMixinClass } from '@vaadin/vaadin-themable-mixin/vaadin-theme-property-mixin.js';
|
|
12
|
+
import type { ComboBoxDataProviderMixinClass } from './vaadin-combo-box-data-provider-mixin.js';
|
|
13
|
+
import type { ComboBoxDefaultItem, ComboBoxMixinClass } from './vaadin-combo-box-mixin.js';
|
|
13
14
|
export {
|
|
14
15
|
ComboBoxDataProvider,
|
|
15
16
|
ComboBoxDataProviderCallback,
|
|
@@ -54,6 +55,11 @@ export type ComboBoxLightFilterChangedEvent = CustomEvent<{ value: string }>;
|
|
|
54
55
|
*/
|
|
55
56
|
export type ComboBoxLightSelectedItemChangedEvent<TItem> = CustomEvent<{ value: TItem | null | undefined }>;
|
|
56
57
|
|
|
58
|
+
/**
|
|
59
|
+
* Fired whenever the field is validated.
|
|
60
|
+
*/
|
|
61
|
+
export type ComboBoxLightValidatedEvent = CustomEvent<{ valid: boolean }>;
|
|
62
|
+
|
|
57
63
|
export interface ComboBoxLightEventMap<TItem> extends HTMLElementEventMap {
|
|
58
64
|
change: ComboBoxLightChangeEvent<TItem>;
|
|
59
65
|
|
|
@@ -68,6 +74,8 @@ export interface ComboBoxLightEventMap<TItem> extends HTMLElementEventMap {
|
|
|
68
74
|
'value-changed': ComboBoxLightValueChangedEvent;
|
|
69
75
|
|
|
70
76
|
'selected-item-changed': ComboBoxLightSelectedItemChangedEvent<TItem>;
|
|
77
|
+
|
|
78
|
+
validated: ComboBoxLightValidatedEvent;
|
|
71
79
|
}
|
|
72
80
|
|
|
73
81
|
/**
|
|
@@ -114,6 +122,7 @@ export interface ComboBoxLightEventMap<TItem> extends HTMLElementEventMap {
|
|
|
114
122
|
* @fires {CustomEvent} opened-changed - Fired when the `opened` property changes.
|
|
115
123
|
* @fires {CustomEvent} selected-item-changed - Fired when the `selectedItem` property changes.
|
|
116
124
|
* @fires {CustomEvent} value-changed - Fired when the `value` property changes.
|
|
125
|
+
* @fires {CustomEvent} validated - Fired whenever the field is validated.
|
|
117
126
|
*/
|
|
118
127
|
declare class ComboBoxLight<TItem = ComboBoxDefaultItem> extends HTMLElement {
|
|
119
128
|
/**
|
|
@@ -126,13 +135,13 @@ declare class ComboBoxLight<TItem = ComboBoxDefaultItem> extends HTMLElement {
|
|
|
126
135
|
addEventListener<K extends keyof ComboBoxLightEventMap<TItem>>(
|
|
127
136
|
type: K,
|
|
128
137
|
listener: (this: ComboBoxLight<TItem>, ev: ComboBoxLightEventMap<TItem>[K]) => void,
|
|
129
|
-
options?:
|
|
138
|
+
options?: AddEventListenerOptions | boolean,
|
|
130
139
|
): void;
|
|
131
140
|
|
|
132
141
|
removeEventListener<K extends keyof ComboBoxLightEventMap<TItem>>(
|
|
133
142
|
type: K,
|
|
134
143
|
listener: (this: ComboBoxLight<TItem>, ev: ComboBoxLightEventMap<TItem>[K]) => void,
|
|
135
|
-
options?:
|
|
144
|
+
options?: EventListenerOptions | boolean,
|
|
136
145
|
): void;
|
|
137
146
|
}
|
|
138
147
|
|
|
@@ -142,7 +151,9 @@ interface ComboBoxLight<TItem = ComboBoxDefaultItem>
|
|
|
142
151
|
KeyboardMixinClass,
|
|
143
152
|
InputMixinClass,
|
|
144
153
|
DisabledMixinClass,
|
|
145
|
-
ThemableMixinClass
|
|
154
|
+
ThemableMixinClass,
|
|
155
|
+
ThemePropertyMixinClass,
|
|
156
|
+
ValidateMixinClass {}
|
|
146
157
|
|
|
147
158
|
declare global {
|
|
148
159
|
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';
|
|
@@ -56,13 +57,15 @@ import { ComboBoxMixin } from './vaadin-combo-box-mixin.js';
|
|
|
56
57
|
* @fires {CustomEvent} opened-changed - Fired when the `opened` property changes.
|
|
57
58
|
* @fires {CustomEvent} selected-item-changed - Fired when the `selectedItem` property changes.
|
|
58
59
|
* @fires {CustomEvent} value-changed - Fired when the `value` property changes.
|
|
60
|
+
* @fires {CustomEvent} validated - Fired whenever the field is validated.
|
|
59
61
|
*
|
|
60
62
|
* @extends HTMLElement
|
|
61
63
|
* @mixes ComboBoxDataProviderMixin
|
|
62
64
|
* @mixes ComboBoxMixin
|
|
63
65
|
* @mixes ThemableMixin
|
|
66
|
+
* @mixes ValidateMixin
|
|
64
67
|
*/
|
|
65
|
-
class ComboBoxLight extends ComboBoxDataProviderMixin(ComboBoxMixin(ThemableMixin(PolymerElement))) {
|
|
68
|
+
class ComboBoxLight extends ComboBoxDataProviderMixin(ComboBoxMixin(ValidateMixin(ThemableMixin(PolymerElement)))) {
|
|
66
69
|
static get is() {
|
|
67
70
|
return 'vaadin-combo-box-light';
|
|
68
71
|
}
|
|
@@ -79,7 +82,6 @@ class ComboBoxLight extends ComboBoxDataProviderMixin(ComboBoxMixin(ThemableMixi
|
|
|
79
82
|
|
|
80
83
|
<vaadin-combo-box-overlay
|
|
81
84
|
id="overlay"
|
|
82
|
-
hidden$="[[_isOverlayHidden(filteredItems, loading)]]"
|
|
83
85
|
opened="[[_overlayOpened]]"
|
|
84
86
|
loading$="[[loading]]"
|
|
85
87
|
theme$="[[_theme]]"
|
|
@@ -3,11 +3,11 @@
|
|
|
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 { Constructor } from '@open-wc/dedupe-mixin';
|
|
7
|
-
import { DisabledMixinClass } from '@vaadin/component-base/src/disabled-mixin.js';
|
|
8
|
-
import { KeyboardMixinClass } from '@vaadin/component-base/src/keyboard-mixin.js';
|
|
9
|
-
import { InputMixinClass } from '@vaadin/field-base/src/input-mixin.js';
|
|
10
|
-
import { ComboBox } from './vaadin-combo-box.js';
|
|
6
|
+
import type { Constructor } from '@open-wc/dedupe-mixin';
|
|
7
|
+
import type { DisabledMixinClass } from '@vaadin/component-base/src/disabled-mixin.js';
|
|
8
|
+
import type { KeyboardMixinClass } from '@vaadin/component-base/src/keyboard-mixin.js';
|
|
9
|
+
import type { InputMixinClass } from '@vaadin/field-base/src/input-mixin.js';
|
|
10
|
+
import type { ComboBox } from './vaadin-combo-box.js';
|
|
11
11
|
|
|
12
12
|
export type ComboBoxDefaultItem = any;
|
|
13
13
|
|
|
@@ -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
|
-
):
|
|
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
|
/**
|
|
@@ -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;
|
|
@@ -170,16 +165,5 @@ export declare class ComboBoxMixinClass<TItem> {
|
|
|
170
165
|
*/
|
|
171
166
|
close(): void;
|
|
172
167
|
|
|
173
|
-
/**
|
|
174
|
-
* Returns true if `value` is valid, and sets the `invalid` flag appropriately.
|
|
175
|
-
*/
|
|
176
|
-
validate(): boolean;
|
|
177
|
-
|
|
178
|
-
/**
|
|
179
|
-
* Returns true if the current input value satisfies all constraints (if any).
|
|
180
|
-
* You can override this method for custom validations.
|
|
181
|
-
*/
|
|
182
|
-
checkValidity(): boolean;
|
|
183
|
-
|
|
184
168
|
protected _revertInputValue(): void;
|
|
185
169
|
}
|
|
@@ -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)',
|
|
@@ -382,6 +382,25 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
382
382
|
this.opened = false;
|
|
383
383
|
}
|
|
384
384
|
|
|
385
|
+
/**
|
|
386
|
+
* Override Polymer lifecycle callback to handle `filter` property change after
|
|
387
|
+
* the observer for `opened` property is triggered. This is needed when opening
|
|
388
|
+
* combo-box on user input to ensure the focused index is set correctly.
|
|
389
|
+
*
|
|
390
|
+
* @param {!Object} currentProps Current accessor values
|
|
391
|
+
* @param {?Object} changedProps Properties changed since the last call
|
|
392
|
+
* @param {?Object} oldProps Previous values for each changed property
|
|
393
|
+
* @protected
|
|
394
|
+
* @override
|
|
395
|
+
*/
|
|
396
|
+
_propertiesChanged(currentProps, changedProps, oldProps) {
|
|
397
|
+
super._propertiesChanged(currentProps, changedProps, oldProps);
|
|
398
|
+
|
|
399
|
+
if (changedProps.filter !== undefined) {
|
|
400
|
+
this._filterChanged(changedProps.filter);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
385
404
|
/** @private */
|
|
386
405
|
_initOverlay() {
|
|
387
406
|
const overlay = this.$.overlay;
|
|
@@ -395,11 +414,6 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
395
414
|
// Prevent blurring the input when clicking inside the overlay
|
|
396
415
|
overlay.addEventListener('mousedown', (e) => e.preventDefault());
|
|
397
416
|
|
|
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
417
|
// Manual two-way binding for the overlay "opened" property
|
|
404
418
|
overlay.addEventListener('opened-changed', (e) => {
|
|
405
419
|
this._overlayOpened = e.detail.value;
|
|
@@ -424,9 +438,7 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
424
438
|
};
|
|
425
439
|
|
|
426
440
|
// Ensure the scroller is rendered
|
|
427
|
-
|
|
428
|
-
overlay.requestContentUpdate();
|
|
429
|
-
}
|
|
441
|
+
overlay.requestContentUpdate();
|
|
430
442
|
|
|
431
443
|
const scroller = overlay.querySelector(scrollerTag);
|
|
432
444
|
|
|
@@ -493,6 +505,11 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
493
505
|
this._updateActiveDescendant(index);
|
|
494
506
|
}
|
|
495
507
|
|
|
508
|
+
/** @protected */
|
|
509
|
+
_isInputFocused() {
|
|
510
|
+
return this.inputElement && isElementFocused(this.inputElement);
|
|
511
|
+
}
|
|
512
|
+
|
|
496
513
|
/** @private */
|
|
497
514
|
_updateActiveDescendant(index) {
|
|
498
515
|
const input = this.inputElement;
|
|
@@ -519,14 +536,14 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
519
536
|
this._openedWithFocusRing = this.hasAttribute('focus-ring');
|
|
520
537
|
// For touch devices, we don't want to popup virtual keyboard
|
|
521
538
|
// unless input element is explicitly focused by the user.
|
|
522
|
-
if (!this.
|
|
539
|
+
if (!this._isInputFocused() && !isTouch) {
|
|
523
540
|
this.focus();
|
|
524
541
|
}
|
|
525
542
|
|
|
526
543
|
this.$.overlay.restoreFocusOnClose = true;
|
|
527
544
|
} else {
|
|
528
545
|
this._onClosed();
|
|
529
|
-
if (this._openedWithFocusRing && this.
|
|
546
|
+
if (this._openedWithFocusRing && this._isInputFocused()) {
|
|
530
547
|
this.setAttribute('focus-ring', '');
|
|
531
548
|
}
|
|
532
549
|
}
|
|
@@ -600,8 +617,6 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
600
617
|
|
|
601
618
|
/** @private */
|
|
602
619
|
_onClick(e) {
|
|
603
|
-
this._closeOnBlurIsPrevented = true;
|
|
604
|
-
|
|
605
620
|
const path = e.composedPath();
|
|
606
621
|
|
|
607
622
|
if (this._isClearButton(e)) {
|
|
@@ -611,8 +626,6 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
611
626
|
} else {
|
|
612
627
|
this._onHostClick(e);
|
|
613
628
|
}
|
|
614
|
-
|
|
615
|
-
this._closeOnBlurIsPrevented = false;
|
|
616
629
|
}
|
|
617
630
|
|
|
618
631
|
/**
|
|
@@ -628,16 +641,12 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
628
641
|
if (e.key === 'Tab') {
|
|
629
642
|
this.$.overlay.restoreFocusOnClose = false;
|
|
630
643
|
} else if (e.key === 'ArrowDown') {
|
|
631
|
-
this._closeOnBlurIsPrevented = true;
|
|
632
644
|
this._onArrowDown();
|
|
633
|
-
this._closeOnBlurIsPrevented = false;
|
|
634
645
|
|
|
635
646
|
// Prevent caret from moving
|
|
636
647
|
e.preventDefault();
|
|
637
648
|
} else if (e.key === 'ArrowUp') {
|
|
638
|
-
this._closeOnBlurIsPrevented = true;
|
|
639
649
|
this._onArrowUp();
|
|
640
|
-
this._closeOnBlurIsPrevented = false;
|
|
641
650
|
|
|
642
651
|
// Prevent caret from moving
|
|
643
652
|
e.preventDefault();
|
|
@@ -708,8 +717,7 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
708
717
|
// and there's no need to modify the selection range if the input isn't focused anyway.
|
|
709
718
|
// This affects Safari. When the overlay is open, and then hitting tab, browser should focus
|
|
710
719
|
// the next focusable element instead of the combo-box itself.
|
|
711
|
-
|
|
712
|
-
if (this.hasAttribute('focused')) {
|
|
720
|
+
if (this._isInputFocused() && this.inputElement.setSelectionRange) {
|
|
713
721
|
this.inputElement.setSelectionRange(start, end);
|
|
714
722
|
}
|
|
715
723
|
}
|
|
@@ -819,7 +827,7 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
819
827
|
toggleElement.addEventListener('mousedown', (e) => e.preventDefault());
|
|
820
828
|
// Unfocus previously focused element if focus is not inside combo box (on touch devices)
|
|
821
829
|
toggleElement.addEventListener('click', () => {
|
|
822
|
-
if (isTouch && !this.
|
|
830
|
+
if (isTouch && !this._isInputFocused()) {
|
|
823
831
|
document.activeElement.blur();
|
|
824
832
|
}
|
|
825
833
|
});
|
|
@@ -926,9 +934,7 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
926
934
|
|
|
927
935
|
this._clearSelectionRange();
|
|
928
936
|
|
|
929
|
-
|
|
930
|
-
this.filter = '';
|
|
931
|
-
}
|
|
937
|
+
this.filter = '';
|
|
932
938
|
}
|
|
933
939
|
|
|
934
940
|
/**
|
|
@@ -946,19 +952,27 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
946
952
|
* @override
|
|
947
953
|
*/
|
|
948
954
|
_onInput(event) {
|
|
949
|
-
|
|
950
|
-
this.open();
|
|
951
|
-
}
|
|
955
|
+
const filter = this._inputElementValue;
|
|
952
956
|
|
|
953
|
-
|
|
954
|
-
|
|
957
|
+
// When opening dropdown on user input, both `opened` and `filter` properties are set.
|
|
958
|
+
// Perform a batched property update instead of relying on sync property observers.
|
|
959
|
+
// This is necessary to avoid an extra data-provider request for loading first page.
|
|
960
|
+
const props = {};
|
|
961
|
+
|
|
962
|
+
if (this.filter === filter) {
|
|
955
963
|
// Filter and input value might get out of sync, while keyboard navigating for example.
|
|
956
964
|
// Afterwards, input value might be changed to the same value as used in filtering.
|
|
957
965
|
// In situation like these, we need to make sure all the filter changes handlers are run.
|
|
958
|
-
this._filterChanged(this.filter
|
|
966
|
+
this._filterChanged(this.filter);
|
|
959
967
|
} else {
|
|
960
|
-
|
|
968
|
+
props.filter = filter;
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
if (!this.opened && !this._isClearButton(event) && !this.autoOpenDisabled) {
|
|
972
|
+
props.opened = true;
|
|
961
973
|
}
|
|
974
|
+
|
|
975
|
+
this.setProperties(props);
|
|
962
976
|
}
|
|
963
977
|
|
|
964
978
|
/**
|
|
@@ -981,11 +995,7 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
981
995
|
}
|
|
982
996
|
|
|
983
997
|
/** @private */
|
|
984
|
-
_filterChanged(filter
|
|
985
|
-
if (filter === undefined) {
|
|
986
|
-
return;
|
|
987
|
-
}
|
|
988
|
-
|
|
998
|
+
_filterChanged(filter) {
|
|
989
999
|
// Scroll to the top of the list whenever the filter changes.
|
|
990
1000
|
this._scrollIntoView(0);
|
|
991
1001
|
|
|
@@ -1064,14 +1074,11 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
1064
1074
|
}
|
|
1065
1075
|
|
|
1066
1076
|
if (isValidValue(value)) {
|
|
1067
|
-
let item;
|
|
1068
1077
|
if (this._getItemValue(this.selectedItem) !== value) {
|
|
1069
1078
|
this._selectItemForValue(value);
|
|
1070
|
-
} else {
|
|
1071
|
-
item = this.selectedItem;
|
|
1072
1079
|
}
|
|
1073
1080
|
|
|
1074
|
-
if (!
|
|
1081
|
+
if (!this.selectedItem && this.allowCustomValue) {
|
|
1075
1082
|
this._inputElementValue = value;
|
|
1076
1083
|
}
|
|
1077
1084
|
|
|
@@ -1079,6 +1086,9 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
1079
1086
|
} else {
|
|
1080
1087
|
this.selectedItem = null;
|
|
1081
1088
|
}
|
|
1089
|
+
|
|
1090
|
+
this.filter = '';
|
|
1091
|
+
|
|
1082
1092
|
// In the next _detectAndDispatchChange() call, the change detection should pass
|
|
1083
1093
|
this._lastCommittedValue = undefined;
|
|
1084
1094
|
}
|
|
@@ -1236,9 +1246,6 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
1236
1246
|
if (this.opened) {
|
|
1237
1247
|
this._focusedIndex = this.filteredItems.indexOf(e.detail.item);
|
|
1238
1248
|
this.close();
|
|
1239
|
-
} else if (this.selectedItem !== e.detail.item) {
|
|
1240
|
-
this.selectedItem = e.detail.item;
|
|
1241
|
-
this._detectAndDispatchChange();
|
|
1242
1249
|
}
|
|
1243
1250
|
}
|
|
1244
1251
|
|
|
@@ -1277,35 +1284,12 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
1277
1284
|
this._clear();
|
|
1278
1285
|
}
|
|
1279
1286
|
|
|
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
1287
|
/**
|
|
1304
1288
|
* Fired when the value changes.
|
|
1305
1289
|
*
|
|
1306
1290
|
* @event value-changed
|
|
1307
1291
|
* @param {Object} detail
|
|
1308
|
-
*
|
|
1292
|
+
* @param {String} detail.value the combobox value
|
|
1309
1293
|
*/
|
|
1310
1294
|
|
|
1311
1295
|
/**
|
|
@@ -1313,7 +1297,7 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
1313
1297
|
*
|
|
1314
1298
|
* @event selected-item-changed
|
|
1315
1299
|
* @param {Object} detail
|
|
1316
|
-
*
|
|
1300
|
+
* @param {Object|String} detail.value the selected item. Type is the same as the type of `items`.
|
|
1317
1301
|
*/
|
|
1318
1302
|
|
|
1319
1303
|
/**
|