@vaadin/multi-select-combo-box 23.2.0-dev.8a7678b70 → 23.3.0-alpha1
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 +9 -7
- package/package.json +18 -12
- package/src/lit/renderer-directives.d.ts +4 -4
- package/src/vaadin-multi-select-combo-box-chip.js +1 -1
- package/src/vaadin-multi-select-combo-box-internal.js +21 -1
- package/src/vaadin-multi-select-combo-box-item.js +1 -1
- package/src/vaadin-multi-select-combo-box.d.ts +38 -20
- package/src/vaadin-multi-select-combo-box.js +75 -35
- package/web-types.json +670 -0
- package/web-types.lit.json +293 -0
package/README.md
CHANGED
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
# @vaadin/multi-select-combo-box
|
|
2
2
|
|
|
3
|
-
> ⚠️ Work in progress, please do not use this component yet.
|
|
4
|
-
|
|
5
3
|
A web component that wraps `<vaadin-combo-box>` and allows selecting multiple items.
|
|
6
4
|
|
|
5
|
+
[Documentation + Live Demo ↗](https://vaadin.com/docs/latest/components/multi-select-combo-box)
|
|
6
|
+
|
|
7
7
|
```html
|
|
8
|
-
<vaadin-multi-select-combo-box
|
|
8
|
+
<vaadin-multi-select-combo-box style="width: 300px"></vaadin-multi-select-combo-box>
|
|
9
9
|
<script>
|
|
10
|
-
const comboBox = document.querySelector('
|
|
10
|
+
const comboBox = document.querySelector('vaadin-multi-select-combo-box');
|
|
11
11
|
comboBox.items = ['apple', 'banana', 'lemon', 'orange'];
|
|
12
|
-
comboBox.selectedItems = ['
|
|
12
|
+
comboBox.selectedItems = ['apple', 'banana'];
|
|
13
13
|
</script>
|
|
14
14
|
```
|
|
15
15
|
|
|
16
|
+
[<img src="https://raw.githubusercontent.com/vaadin/web-components/master/packages/multi-select-combo-box/screenshot.png" width="300" alt="Screenshot of vaadin-multi-select-combo-box">](https://vaadin.com/docs/latest/components/multi-select-combo-box)
|
|
17
|
+
|
|
16
18
|
## Installation
|
|
17
19
|
|
|
18
20
|
Install the component:
|
|
@@ -29,7 +31,7 @@ import '@vaadin/multi-select-combo-box';
|
|
|
29
31
|
|
|
30
32
|
## Themes
|
|
31
33
|
|
|
32
|
-
Vaadin components come with two built-in [themes](https://vaadin.com/docs/latest/
|
|
34
|
+
Vaadin components come with two built-in [themes](https://vaadin.com/docs/latest/styling), Lumo and Material.
|
|
33
35
|
The [main entrypoint](https://github.com/vaadin/web-components/blob/master/packages/multi-select-combo-box/vaadin-multi-select-combo-box.js) of the package uses the Lumo theme.
|
|
34
36
|
|
|
35
37
|
To use the Material theme, import the component from the `theme/material` folder:
|
|
@@ -52,7 +54,7 @@ import '@vaadin/multi-select-combo-box/src/vaadin-multi-select-combo-box.js';
|
|
|
52
54
|
|
|
53
55
|
## Contributing
|
|
54
56
|
|
|
55
|
-
Read the [contributing guide](https://vaadin.com/docs/latest/
|
|
57
|
+
Read the [contributing guide](https://vaadin.com/docs/latest/contributing/overview) to learn about our development process, how to propose bugfixes and improvements, and how to test your changes to Vaadin components.
|
|
56
58
|
|
|
57
59
|
## License
|
|
58
60
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vaadin/multi-select-combo-box",
|
|
3
|
-
"version": "23.
|
|
3
|
+
"version": "23.3.0-alpha1",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -19,12 +19,14 @@
|
|
|
19
19
|
"main": "vaadin-multi-select-combo-box.js",
|
|
20
20
|
"module": "vaadin-multi-select-combo-box.js",
|
|
21
21
|
"files": [
|
|
22
|
-
"lit.js",
|
|
23
22
|
"lit.d.ts",
|
|
23
|
+
"lit.js",
|
|
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",
|
|
@@ -35,19 +37,23 @@
|
|
|
35
37
|
],
|
|
36
38
|
"dependencies": {
|
|
37
39
|
"@polymer/polymer": "^3.0.0",
|
|
38
|
-
"@vaadin/combo-box": "23.
|
|
39
|
-
"@vaadin/component-base": "23.
|
|
40
|
-
"@vaadin/field-base": "23.
|
|
41
|
-
"@vaadin/input-container": "23.
|
|
42
|
-
"@vaadin/lit-renderer": "23.
|
|
43
|
-
"@vaadin/vaadin-lumo-styles": "23.
|
|
44
|
-
"@vaadin/vaadin-material-styles": "23.
|
|
45
|
-
"@vaadin/vaadin-themable-mixin": "23.
|
|
40
|
+
"@vaadin/combo-box": "23.3.0-alpha1",
|
|
41
|
+
"@vaadin/component-base": "23.3.0-alpha1",
|
|
42
|
+
"@vaadin/field-base": "23.3.0-alpha1",
|
|
43
|
+
"@vaadin/input-container": "23.3.0-alpha1",
|
|
44
|
+
"@vaadin/lit-renderer": "23.3.0-alpha1",
|
|
45
|
+
"@vaadin/vaadin-lumo-styles": "23.3.0-alpha1",
|
|
46
|
+
"@vaadin/vaadin-material-styles": "23.3.0-alpha1",
|
|
47
|
+
"@vaadin/vaadin-themable-mixin": "23.3.0-alpha1"
|
|
46
48
|
},
|
|
47
49
|
"devDependencies": {
|
|
48
50
|
"@esm-bundle/chai": "^4.3.4",
|
|
49
51
|
"@vaadin/testing-helpers": "^0.3.2",
|
|
50
52
|
"sinon": "^13.0.2"
|
|
51
53
|
},
|
|
52
|
-
"
|
|
54
|
+
"web-types": [
|
|
55
|
+
"web-types.json",
|
|
56
|
+
"web-types.lit.json"
|
|
57
|
+
],
|
|
58
|
+
"gitHead": "beabc527d4b1274eb798ff701d406fed45cfe638"
|
|
53
59
|
}
|
|
@@ -3,11 +3,11 @@
|
|
|
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';
|
|
8
|
-
import { ComboBoxItemModel } from '@vaadin/combo-box/src/vaadin-combo-box.js';
|
|
6
|
+
import type { TemplateResult } from 'lit';
|
|
7
|
+
import type { DirectiveResult } from 'lit/directive.js';
|
|
8
|
+
import type { ComboBoxItemModel } from '@vaadin/combo-box/src/vaadin-combo-box.js';
|
|
9
9
|
import { LitRendererDirective } from '@vaadin/lit-renderer';
|
|
10
|
-
import { MultiSelectComboBox } from '../vaadin-multi-select-combo-box.js';
|
|
10
|
+
import type { MultiSelectComboBox } from '../vaadin-multi-select-combo-box.js';
|
|
11
11
|
|
|
12
12
|
export type MultiSelectComboBoxLitRenderer<TItem> = (
|
|
13
13
|
item: TItem,
|
|
@@ -18,7 +18,7 @@ import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mix
|
|
|
18
18
|
* `label` | Element containing the label
|
|
19
19
|
* `remove-button` | Remove button
|
|
20
20
|
*
|
|
21
|
-
* See [Styling Components](https://vaadin.com/docs/latest/
|
|
21
|
+
* See [Styling Components](https://vaadin.com/docs/latest/styling/custom-theme/styling-components) documentation.
|
|
22
22
|
*
|
|
23
23
|
* @extends HTMLElement
|
|
24
24
|
* @private
|
|
@@ -38,7 +38,6 @@ class MultiSelectComboBoxInternal extends ComboBoxDataProviderMixin(ComboBoxMixi
|
|
|
38
38
|
|
|
39
39
|
<vaadin-multi-select-combo-box-overlay
|
|
40
40
|
id="overlay"
|
|
41
|
-
hidden$="[[_isOverlayHidden(filteredItems, loading)]]"
|
|
42
41
|
opened="[[_overlayOpened]]"
|
|
43
42
|
loading$="[[loading]]"
|
|
44
43
|
theme$="[[_theme]]"
|
|
@@ -87,6 +86,15 @@ class MultiSelectComboBoxInternal extends ComboBoxDataProviderMixin(ComboBoxMixi
|
|
|
87
86
|
value: () => [],
|
|
88
87
|
},
|
|
89
88
|
|
|
89
|
+
/**
|
|
90
|
+
* Last input value entered by the user before value is updated.
|
|
91
|
+
* Used to store `filter` property value before clearing it.
|
|
92
|
+
*/
|
|
93
|
+
lastFilter: {
|
|
94
|
+
type: String,
|
|
95
|
+
notify: true,
|
|
96
|
+
},
|
|
97
|
+
|
|
90
98
|
_target: {
|
|
91
99
|
type: Object,
|
|
92
100
|
},
|
|
@@ -195,6 +203,18 @@ class MultiSelectComboBoxInternal extends ComboBoxDataProviderMixin(ComboBoxMixi
|
|
|
195
203
|
super._closeOrCommit();
|
|
196
204
|
}
|
|
197
205
|
|
|
206
|
+
/**
|
|
207
|
+
* @protected
|
|
208
|
+
* @override
|
|
209
|
+
*/
|
|
210
|
+
_commitValue() {
|
|
211
|
+
// Store filter value for checking if user input is matching
|
|
212
|
+
// an item which is already selected, to not un-select it.
|
|
213
|
+
this.lastFilter = this.filter;
|
|
214
|
+
|
|
215
|
+
super._commitValue();
|
|
216
|
+
}
|
|
217
|
+
|
|
198
218
|
/**
|
|
199
219
|
* Override method inherited from the combo-box
|
|
200
220
|
* to not update focused item when readonly.
|
|
@@ -23,7 +23,7 @@ import { ComboBoxItem } from '@vaadin/combo-box/src/vaadin-combo-box-item.js';
|
|
|
23
23
|
* `selected` | Set when the item is selected | :host
|
|
24
24
|
* `focused` | Set when the item is focused | :host
|
|
25
25
|
*
|
|
26
|
-
* See [Styling Components](https://vaadin.com/docs/latest/
|
|
26
|
+
* See [Styling Components](https://vaadin.com/docs/latest/styling/custom-theme/styling-components) documentation.
|
|
27
27
|
*
|
|
28
28
|
* @extends ComboBoxItem
|
|
29
29
|
* @private
|
|
@@ -3,26 +3,28 @@
|
|
|
3
3
|
* Copyright (c) 2021 - 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 {
|
|
6
|
+
import type {
|
|
7
7
|
ComboBoxDataProvider,
|
|
8
8
|
ComboBoxDefaultItem,
|
|
9
9
|
ComboBoxItemModel,
|
|
10
10
|
} from '@vaadin/combo-box/src/vaadin-combo-box.js';
|
|
11
|
-
import { ControllerMixinClass } from '@vaadin/component-base/src/controller-mixin.js';
|
|
12
|
-
import { DisabledMixinClass } from '@vaadin/component-base/src/disabled-mixin.js';
|
|
13
|
-
import { ElementMixinClass } from '@vaadin/component-base/src/element-mixin.js';
|
|
14
|
-
import { FocusMixinClass } from '@vaadin/component-base/src/focus-mixin.js';
|
|
15
|
-
import { KeyboardMixinClass } from '@vaadin/component-base/src/keyboard-mixin.js';
|
|
16
|
-
import { ResizeMixinClass } from '@vaadin/component-base/src/resize-mixin.js';
|
|
17
|
-
import { DelegateFocusMixinClass } from '@vaadin/field-base/src/delegate-focus-mixin.js';
|
|
18
|
-
import { DelegateStateMixinClass } from '@vaadin/field-base/src/delegate-state-mixin.js';
|
|
19
|
-
import { FieldMixinClass } from '@vaadin/field-base/src/field-mixin.js';
|
|
20
|
-
import { InputConstraintsMixinClass } from '@vaadin/field-base/src/input-constraints-mixin.js';
|
|
21
|
-
import { InputControlMixinClass } from '@vaadin/field-base/src/input-control-mixin.js';
|
|
22
|
-
import { InputMixinClass } from '@vaadin/field-base/src/input-mixin.js';
|
|
23
|
-
import { LabelMixinClass } from '@vaadin/field-base/src/label-mixin.js';
|
|
24
|
-
import {
|
|
25
|
-
import {
|
|
11
|
+
import type { ControllerMixinClass } from '@vaadin/component-base/src/controller-mixin.js';
|
|
12
|
+
import type { DisabledMixinClass } from '@vaadin/component-base/src/disabled-mixin.js';
|
|
13
|
+
import type { ElementMixinClass } from '@vaadin/component-base/src/element-mixin.js';
|
|
14
|
+
import type { FocusMixinClass } from '@vaadin/component-base/src/focus-mixin.js';
|
|
15
|
+
import type { KeyboardMixinClass } from '@vaadin/component-base/src/keyboard-mixin.js';
|
|
16
|
+
import type { ResizeMixinClass } from '@vaadin/component-base/src/resize-mixin.js';
|
|
17
|
+
import type { DelegateFocusMixinClass } from '@vaadin/field-base/src/delegate-focus-mixin.js';
|
|
18
|
+
import type { DelegateStateMixinClass } from '@vaadin/field-base/src/delegate-state-mixin.js';
|
|
19
|
+
import type { FieldMixinClass } from '@vaadin/field-base/src/field-mixin.js';
|
|
20
|
+
import type { InputConstraintsMixinClass } from '@vaadin/field-base/src/input-constraints-mixin.js';
|
|
21
|
+
import type { InputControlMixinClass } from '@vaadin/field-base/src/input-control-mixin.js';
|
|
22
|
+
import type { InputMixinClass } from '@vaadin/field-base/src/input-mixin.js';
|
|
23
|
+
import type { LabelMixinClass } from '@vaadin/field-base/src/label-mixin.js';
|
|
24
|
+
import type { SlotStylesMixinClass } from '@vaadin/field-base/src/slot-styles-mixin.js';
|
|
25
|
+
import type { ValidateMixinClass } from '@vaadin/field-base/src/validate-mixin.js';
|
|
26
|
+
import type { ThemableMixinClass } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
27
|
+
import type { ThemePropertyMixinClass } from '@vaadin/vaadin-themable-mixin/vaadin-theme-property-mixin.js';
|
|
26
28
|
|
|
27
29
|
export type MultiSelectComboBoxRenderer<TItem> = (
|
|
28
30
|
root: HTMLElement,
|
|
@@ -65,6 +67,11 @@ export type MultiSelectComboBoxInvalidChangedEvent = CustomEvent<{ value: boolea
|
|
|
65
67
|
*/
|
|
66
68
|
export type MultiSelectComboBoxSelectedItemsChangedEvent<TItem> = CustomEvent<{ value: TItem[] }>;
|
|
67
69
|
|
|
70
|
+
/**
|
|
71
|
+
* Fired whenever the field is validated.
|
|
72
|
+
*/
|
|
73
|
+
export type MultiSelectComboBoxValidatedEvent = CustomEvent<{ valid: boolean }>;
|
|
74
|
+
|
|
68
75
|
export interface MultiSelectComboBoxEventMap<TItem> extends HTMLElementEventMap {
|
|
69
76
|
change: MultiSelectComboBoxChangeEvent<TItem>;
|
|
70
77
|
|
|
@@ -75,6 +82,8 @@ export interface MultiSelectComboBoxEventMap<TItem> extends HTMLElementEventMap
|
|
|
75
82
|
'invalid-changed': MultiSelectComboBoxInvalidChangedEvent;
|
|
76
83
|
|
|
77
84
|
'selected-items-changed': MultiSelectComboBoxSelectedItemsChangedEvent<TItem>;
|
|
85
|
+
|
|
86
|
+
validated: MultiSelectComboBoxValidatedEvent;
|
|
78
87
|
}
|
|
79
88
|
|
|
80
89
|
/**
|
|
@@ -131,6 +140,7 @@ export interface MultiSelectComboBoxEventMap<TItem> extends HTMLElementEventMap
|
|
|
131
140
|
* Custom property | Description | Default
|
|
132
141
|
* -----------------------------------------------------|----------------------------|--------
|
|
133
142
|
* `--vaadin-field-default-width` | Default width of the field | `12em`
|
|
143
|
+
* `--vaadin-multi-select-combo-box-overlay-width` | Width of the overlay | `auto`
|
|
134
144
|
* `--vaadin-multi-select-combo-box-overlay-max-height` | Max height of the overlay | `65vh`
|
|
135
145
|
* `--vaadin-multi-select-combo-box-input-min-width` | Min width of the input | `4em`
|
|
136
146
|
*
|
|
@@ -146,13 +156,14 @@ export interface MultiSelectComboBoxEventMap<TItem> extends HTMLElementEventMap
|
|
|
146
156
|
* Note: the `theme` attribute value set on `<vaadin-multi-select-combo-box>` is
|
|
147
157
|
* propagated to these components.
|
|
148
158
|
*
|
|
149
|
-
* See [Styling Components](https://vaadin.com/docs/latest/
|
|
159
|
+
* See [Styling Components](https://vaadin.com/docs/latest/styling/custom-theme/styling-components) documentation.
|
|
150
160
|
*
|
|
151
161
|
* @fires {Event} change - Fired when the user commits a value change.
|
|
152
162
|
* @fires {CustomEvent} custom-value-set - Fired when the user sets a custom value.
|
|
153
163
|
* @fires {CustomEvent} filter-changed - Fired when the `filter` property changes.
|
|
154
164
|
* @fires {CustomEvent} invalid-changed - Fired when the `invalid` property changes.
|
|
155
165
|
* @fires {CustomEvent} selected-items-changed - Fired when the `selectedItems` property changes.
|
|
166
|
+
* @fires {CustomEvent} validated - Fired whenever the field is validated.
|
|
156
167
|
*/
|
|
157
168
|
declare class MultiSelectComboBox<TItem = ComboBoxDefaultItem> extends HTMLElement {
|
|
158
169
|
/**
|
|
@@ -294,6 +305,11 @@ declare class MultiSelectComboBox<TItem = ComboBoxDefaultItem> extends HTMLEleme
|
|
|
294
305
|
*/
|
|
295
306
|
clearCache(): void;
|
|
296
307
|
|
|
308
|
+
/**
|
|
309
|
+
* Clears the selected items.
|
|
310
|
+
*/
|
|
311
|
+
clear(): void;
|
|
312
|
+
|
|
297
313
|
/**
|
|
298
314
|
* Requests an update for the content of items.
|
|
299
315
|
* While performing the update, it invokes the renderer (passed in the `renderer` property) once an item.
|
|
@@ -305,21 +321,22 @@ declare class MultiSelectComboBox<TItem = ComboBoxDefaultItem> extends HTMLEleme
|
|
|
305
321
|
addEventListener<K extends keyof MultiSelectComboBoxEventMap<TItem>>(
|
|
306
322
|
type: K,
|
|
307
323
|
listener: (this: MultiSelectComboBox<TItem>, ev: MultiSelectComboBoxEventMap<TItem>[K]) => void,
|
|
308
|
-
options?:
|
|
324
|
+
options?: AddEventListenerOptions | boolean,
|
|
309
325
|
): void;
|
|
310
326
|
|
|
311
327
|
removeEventListener<K extends keyof MultiSelectComboBoxEventMap<TItem>>(
|
|
312
328
|
type: K,
|
|
313
329
|
listener: (this: MultiSelectComboBox<TItem>, ev: MultiSelectComboBoxEventMap<TItem>[K]) => void,
|
|
314
|
-
options?:
|
|
330
|
+
options?: EventListenerOptions | boolean,
|
|
315
331
|
): void;
|
|
316
332
|
}
|
|
317
333
|
|
|
318
334
|
interface MultiSelectComboBox
|
|
319
335
|
extends ValidateMixinClass,
|
|
336
|
+
SlotStylesMixinClass,
|
|
320
337
|
LabelMixinClass,
|
|
321
338
|
KeyboardMixinClass,
|
|
322
|
-
InputMixinClass,
|
|
339
|
+
Omit<InputMixinClass, 'value'>,
|
|
323
340
|
InputControlMixinClass,
|
|
324
341
|
InputConstraintsMixinClass,
|
|
325
342
|
FocusMixinClass,
|
|
@@ -329,6 +346,7 @@ interface MultiSelectComboBox
|
|
|
329
346
|
DelegateFocusMixinClass,
|
|
330
347
|
ResizeMixinClass,
|
|
331
348
|
ThemableMixinClass,
|
|
349
|
+
ThemePropertyMixinClass,
|
|
332
350
|
ElementMixinClass,
|
|
333
351
|
ControllerMixinClass {}
|
|
334
352
|
|
|
@@ -11,6 +11,7 @@ import { announce } from '@vaadin/component-base/src/a11y-announcer.js';
|
|
|
11
11
|
import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
|
|
12
12
|
import { ResizeMixin } from '@vaadin/component-base/src/resize-mixin.js';
|
|
13
13
|
import { processTemplates } from '@vaadin/component-base/src/templates.js';
|
|
14
|
+
import { TooltipController } from '@vaadin/component-base/src/tooltip-controller.js';
|
|
14
15
|
import { InputControlMixin } from '@vaadin/field-base/src/input-control-mixin.js';
|
|
15
16
|
import { InputController } from '@vaadin/field-base/src/input-controller.js';
|
|
16
17
|
import { LabelledInputController } from '@vaadin/field-base/src/labelled-input-controller.js';
|
|
@@ -31,10 +32,6 @@ const multiSelectComboBox = css`
|
|
|
31
32
|
align-items: center;
|
|
32
33
|
}
|
|
33
34
|
|
|
34
|
-
:host([has-value]) ::slotted(input:placeholder-shown) {
|
|
35
|
-
color: transparent !important;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
35
|
::slotted(input) {
|
|
39
36
|
box-sizing: border-box;
|
|
40
37
|
flex: 1 0 var(--input-min-width);
|
|
@@ -109,6 +106,7 @@ registerStyles('vaadin-multi-select-combo-box', [inputFieldShared, multiSelectCo
|
|
|
109
106
|
* Custom property | Description | Default
|
|
110
107
|
* -----------------------------------------------------|----------------------------|--------
|
|
111
108
|
* `--vaadin-field-default-width` | Default width of the field | `12em`
|
|
109
|
+
* `--vaadin-multi-select-combo-box-overlay-width` | Width of the overlay | `auto`
|
|
112
110
|
* `--vaadin-multi-select-combo-box-overlay-max-height` | Max height of the overlay | `65vh`
|
|
113
111
|
* `--vaadin-multi-select-combo-box-input-min-width` | Min width of the input | `4em`
|
|
114
112
|
*
|
|
@@ -124,13 +122,14 @@ registerStyles('vaadin-multi-select-combo-box', [inputFieldShared, multiSelectCo
|
|
|
124
122
|
* Note: the `theme` attribute value set on `<vaadin-multi-select-combo-box>` is
|
|
125
123
|
* propagated to these components.
|
|
126
124
|
*
|
|
127
|
-
* See [Styling Components](https://vaadin.com/docs/latest/
|
|
125
|
+
* See [Styling Components](https://vaadin.com/docs/latest/styling/custom-theme/styling-components) documentation.
|
|
128
126
|
*
|
|
129
127
|
* @fires {Event} change - Fired when the user commits a value change.
|
|
130
128
|
* @fires {CustomEvent} custom-value-set - Fired when the user sets a custom value.
|
|
131
129
|
* @fires {CustomEvent} filter-changed - Fired when the `filter` property changes.
|
|
132
130
|
* @fires {CustomEvent} invalid-changed - Fired when the `invalid` property changes.
|
|
133
131
|
* @fires {CustomEvent} selected-items-changed - Fired when the `selectedItems` property changes.
|
|
132
|
+
* @fires {CustomEvent} validated - Fired whenever the field is validated.
|
|
134
133
|
*
|
|
135
134
|
* @extends HTMLElement
|
|
136
135
|
* @mixes ElementMixin
|
|
@@ -163,6 +162,7 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
|
|
|
163
162
|
allow-custom-value="[[allowCustomValue]]"
|
|
164
163
|
data-provider="[[dataProvider]]"
|
|
165
164
|
filter="{{filter}}"
|
|
165
|
+
last-filter="{{_lastFilter}}"
|
|
166
166
|
loading="{{loading}}"
|
|
167
167
|
size="{{size}}"
|
|
168
168
|
filtered-items="[[__effectiveFilteredItems]]"
|
|
@@ -195,7 +195,13 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
|
|
|
195
195
|
></vaadin-multi-select-combo-box-chip>
|
|
196
196
|
<div id="chips" part="chips" slot="prefix"></div>
|
|
197
197
|
<slot name="input"></slot>
|
|
198
|
-
<div
|
|
198
|
+
<div
|
|
199
|
+
id="clearButton"
|
|
200
|
+
part="clear-button"
|
|
201
|
+
slot="suffix"
|
|
202
|
+
on-touchend="_onClearButtonTouchend"
|
|
203
|
+
aria-hidden="true"
|
|
204
|
+
></div>
|
|
199
205
|
<div id="toggleButton" class="toggle-button" part="toggle-button" slot="suffix" aria-hidden="true"></div>
|
|
200
206
|
</vaadin-multi-select-combo-box-container>
|
|
201
207
|
</vaadin-multi-select-combo-box-internal>
|
|
@@ -208,6 +214,8 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
|
|
|
208
214
|
<slot name="error-message"></slot>
|
|
209
215
|
</div>
|
|
210
216
|
</div>
|
|
217
|
+
|
|
218
|
+
<slot name="tooltip"></slot>
|
|
211
219
|
`;
|
|
212
220
|
}
|
|
213
221
|
|
|
@@ -423,6 +431,11 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
|
|
|
423
431
|
*/
|
|
424
432
|
filteredItems: Array,
|
|
425
433
|
|
|
434
|
+
/** @private */
|
|
435
|
+
value: {
|
|
436
|
+
type: String,
|
|
437
|
+
},
|
|
438
|
+
|
|
426
439
|
/** @private */
|
|
427
440
|
__effectiveItems: {
|
|
428
441
|
type: Array,
|
|
@@ -435,12 +448,6 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
|
|
|
435
448
|
computed: '__computeEffectiveFilteredItems(items, filteredItems, selectedItems, readonly)',
|
|
436
449
|
},
|
|
437
450
|
|
|
438
|
-
/** @protected */
|
|
439
|
-
_hasValue: {
|
|
440
|
-
type: Boolean,
|
|
441
|
-
value: false,
|
|
442
|
-
},
|
|
443
|
-
|
|
444
451
|
/** @private */
|
|
445
452
|
_overflowItems: {
|
|
446
453
|
type: Array,
|
|
@@ -453,6 +460,11 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
|
|
|
453
460
|
value: -1,
|
|
454
461
|
observer: '_focusedChipIndexChanged',
|
|
455
462
|
},
|
|
463
|
+
|
|
464
|
+
/** @private */
|
|
465
|
+
_lastFilter: {
|
|
466
|
+
type: String,
|
|
467
|
+
},
|
|
456
468
|
};
|
|
457
469
|
}
|
|
458
470
|
|
|
@@ -460,6 +472,19 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
|
|
|
460
472
|
return ['_selectedItemsChanged(selectedItems, selectedItems.*)'];
|
|
461
473
|
}
|
|
462
474
|
|
|
475
|
+
/** @protected */
|
|
476
|
+
get slotStyles() {
|
|
477
|
+
const tag = this.localName;
|
|
478
|
+
return [
|
|
479
|
+
...super.slotStyles,
|
|
480
|
+
`
|
|
481
|
+
${tag}[has-value] input::placeholder {
|
|
482
|
+
color: transparent !important;
|
|
483
|
+
}
|
|
484
|
+
`,
|
|
485
|
+
];
|
|
486
|
+
}
|
|
487
|
+
|
|
463
488
|
/**
|
|
464
489
|
* Used by `InputControlMixin` as a reference to the clear button element.
|
|
465
490
|
* @protected
|
|
@@ -488,6 +513,10 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
|
|
|
488
513
|
);
|
|
489
514
|
this.addController(new LabelledInputController(this.inputElement, this._labelController));
|
|
490
515
|
|
|
516
|
+
this._tooltipController = new TooltipController(this);
|
|
517
|
+
this.addController(this._tooltipController);
|
|
518
|
+
this._tooltipController.setShouldShow((target) => !target.opened);
|
|
519
|
+
|
|
491
520
|
this._inputField = this.shadowRoot.querySelector('[part="input-field"]');
|
|
492
521
|
this.__updateChips();
|
|
493
522
|
|
|
@@ -502,6 +531,15 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
|
|
|
502
531
|
return this.required && !this.readonly ? this._hasValue : true;
|
|
503
532
|
}
|
|
504
533
|
|
|
534
|
+
/**
|
|
535
|
+
* Clears the selected items.
|
|
536
|
+
*/
|
|
537
|
+
clear() {
|
|
538
|
+
this.__updateSelection([]);
|
|
539
|
+
|
|
540
|
+
announce(this.i18n.cleared);
|
|
541
|
+
}
|
|
542
|
+
|
|
505
543
|
/**
|
|
506
544
|
* Clears the cached pages and reloads data from data provider when needed.
|
|
507
545
|
*/
|
|
@@ -561,21 +599,6 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
|
|
|
561
599
|
this._focusedChipIndex = -1;
|
|
562
600
|
this.validate();
|
|
563
601
|
}
|
|
564
|
-
|
|
565
|
-
// Propagate focused attribute to internal combo box
|
|
566
|
-
if (this.$ && this.$.comboBox) {
|
|
567
|
-
this.$.comboBox.toggleAttribute('focused', focused);
|
|
568
|
-
}
|
|
569
|
-
}
|
|
570
|
-
|
|
571
|
-
/**
|
|
572
|
-
* Override method inherited from `InputMixin`
|
|
573
|
-
* to keep attribute after clearing the input.
|
|
574
|
-
* @protected
|
|
575
|
-
* @override
|
|
576
|
-
*/
|
|
577
|
-
_toggleHasValue() {
|
|
578
|
-
super._toggleHasValue(this._hasValue);
|
|
579
602
|
}
|
|
580
603
|
|
|
581
604
|
/**
|
|
@@ -664,9 +687,7 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
|
|
|
664
687
|
|
|
665
688
|
/** @private */
|
|
666
689
|
_selectedItemsChanged(selectedItems) {
|
|
667
|
-
this.
|
|
668
|
-
|
|
669
|
-
this._toggleHasValue();
|
|
690
|
+
this._toggleHasValue(this._hasValue);
|
|
670
691
|
|
|
671
692
|
// Use placeholder for announcing items
|
|
672
693
|
if (this._hasValue) {
|
|
@@ -755,7 +776,8 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
|
|
|
755
776
|
const itemsCopy = [...this.selectedItems];
|
|
756
777
|
itemsCopy.splice(itemsCopy.indexOf(item), 1);
|
|
757
778
|
this.__updateSelection(itemsCopy);
|
|
758
|
-
this.
|
|
779
|
+
const itemLabel = this._getItemLabel(item);
|
|
780
|
+
this.__announceItem(itemLabel, false, itemsCopy.length);
|
|
759
781
|
}
|
|
760
782
|
|
|
761
783
|
/** @private */
|
|
@@ -768,8 +790,9 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
|
|
|
768
790
|
let isSelected = false;
|
|
769
791
|
|
|
770
792
|
if (index !== -1) {
|
|
793
|
+
const lastFilter = this._lastFilter;
|
|
771
794
|
// Do not unselect when manually typing and committing an already selected item.
|
|
772
|
-
if (
|
|
795
|
+
if (lastFilter && lastFilter.toLowerCase() === itemLabel.toLowerCase()) {
|
|
773
796
|
this.__clearFilter();
|
|
774
797
|
return;
|
|
775
798
|
}
|
|
@@ -877,6 +900,14 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
|
|
|
877
900
|
this._overflowItems = items;
|
|
878
901
|
}
|
|
879
902
|
|
|
903
|
+
/** @private */
|
|
904
|
+
_onClearButtonTouchend(event) {
|
|
905
|
+
// Cancel the following click and focus events
|
|
906
|
+
event.preventDefault();
|
|
907
|
+
|
|
908
|
+
this.clear();
|
|
909
|
+
}
|
|
910
|
+
|
|
880
911
|
/**
|
|
881
912
|
* Override method inherited from `InputControlMixin` and clear items.
|
|
882
913
|
* @protected
|
|
@@ -885,9 +916,7 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
|
|
|
885
916
|
_onClearButtonClick(event) {
|
|
886
917
|
event.stopPropagation();
|
|
887
918
|
|
|
888
|
-
this.
|
|
889
|
-
|
|
890
|
-
announce(this.i18n.cleared);
|
|
919
|
+
this.clear();
|
|
891
920
|
}
|
|
892
921
|
|
|
893
922
|
/**
|
|
@@ -1092,6 +1121,17 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
|
|
|
1092
1121
|
__computeEffectiveFilteredItems(items, filteredItems, selectedItems, readonly) {
|
|
1093
1122
|
return !items && readonly ? selectedItems : filteredItems;
|
|
1094
1123
|
}
|
|
1124
|
+
|
|
1125
|
+
/**
|
|
1126
|
+
* Override a method from `InputMixin` to
|
|
1127
|
+
* compute the presence of value based on `selectedItems`.
|
|
1128
|
+
*
|
|
1129
|
+
* @protected
|
|
1130
|
+
* @override
|
|
1131
|
+
*/
|
|
1132
|
+
get _hasValue() {
|
|
1133
|
+
return this.selectedItems && this.selectedItems.length > 0;
|
|
1134
|
+
}
|
|
1095
1135
|
}
|
|
1096
1136
|
|
|
1097
1137
|
customElements.define(MultiSelectComboBox.is, MultiSelectComboBox);
|