@vaadin/multi-select-combo-box 23.1.0-alpha4 → 23.1.0-beta3
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 +9 -9
- package/src/vaadin-multi-select-combo-box-chip.js +11 -2
- package/src/vaadin-multi-select-combo-box-container.js +2 -3
- package/src/vaadin-multi-select-combo-box-internal.js +24 -0
- package/src/vaadin-multi-select-combo-box-scroller.js +13 -0
- package/src/vaadin-multi-select-combo-box.d.ts +45 -6
- package/src/vaadin-multi-select-combo-box.js +288 -63
- package/theme/lumo/vaadin-multi-select-combo-box-chip-styles.js +17 -11
- package/theme/lumo/vaadin-multi-select-combo-box-styles.js +6 -2
- package/theme/material/vaadin-multi-select-combo-box-chip-styles.js +13 -13
- package/theme/material/vaadin-multi-select-combo-box-styles.js +2 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vaadin/multi-select-combo-box",
|
|
3
|
-
"version": "23.1.0-
|
|
3
|
+
"version": "23.1.0-beta3",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -33,18 +33,18 @@
|
|
|
33
33
|
],
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"@polymer/polymer": "^3.0.0",
|
|
36
|
-
"@vaadin/combo-box": "23.1.0-
|
|
37
|
-
"@vaadin/component-base": "23.1.0-
|
|
38
|
-
"@vaadin/field-base": "23.1.0-
|
|
39
|
-
"@vaadin/input-container": "23.1.0-
|
|
40
|
-
"@vaadin/vaadin-lumo-styles": "23.1.0-
|
|
41
|
-
"@vaadin/vaadin-material-styles": "23.1.0-
|
|
42
|
-
"@vaadin/vaadin-themable-mixin": "23.1.0-
|
|
36
|
+
"@vaadin/combo-box": "23.1.0-beta3",
|
|
37
|
+
"@vaadin/component-base": "23.1.0-beta3",
|
|
38
|
+
"@vaadin/field-base": "23.1.0-beta3",
|
|
39
|
+
"@vaadin/input-container": "23.1.0-beta3",
|
|
40
|
+
"@vaadin/vaadin-lumo-styles": "23.1.0-beta3",
|
|
41
|
+
"@vaadin/vaadin-material-styles": "23.1.0-beta3",
|
|
42
|
+
"@vaadin/vaadin-themable-mixin": "23.1.0-beta3"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"@esm-bundle/chai": "^4.3.4",
|
|
46
46
|
"@vaadin/testing-helpers": "^0.3.2",
|
|
47
47
|
"sinon": "^13.0.2"
|
|
48
48
|
},
|
|
49
|
-
"gitHead": "
|
|
49
|
+
"gitHead": "c787ceb8a312f88631c6d429ff320d5f89b1b838"
|
|
50
50
|
}
|
|
@@ -30,6 +30,16 @@ class MultiSelectComboBoxChip extends ThemableMixin(PolymerElement) {
|
|
|
30
30
|
|
|
31
31
|
static get properties() {
|
|
32
32
|
return {
|
|
33
|
+
disabled: {
|
|
34
|
+
type: Boolean,
|
|
35
|
+
reflectToAttribute: true,
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
readonly: {
|
|
39
|
+
type: Boolean,
|
|
40
|
+
reflectToAttribute: true,
|
|
41
|
+
},
|
|
42
|
+
|
|
33
43
|
label: {
|
|
34
44
|
type: String,
|
|
35
45
|
},
|
|
@@ -49,7 +59,6 @@ class MultiSelectComboBoxChip extends ThemableMixin(PolymerElement) {
|
|
|
49
59
|
align-self: center;
|
|
50
60
|
white-space: nowrap;
|
|
51
61
|
box-sizing: border-box;
|
|
52
|
-
min-width: 0;
|
|
53
62
|
}
|
|
54
63
|
|
|
55
64
|
[part='label'] {
|
|
@@ -57,7 +66,7 @@ class MultiSelectComboBoxChip extends ThemableMixin(PolymerElement) {
|
|
|
57
66
|
text-overflow: ellipsis;
|
|
58
67
|
}
|
|
59
68
|
|
|
60
|
-
:host([part~='overflow']) [part='remove-button'] {
|
|
69
|
+
:host(:is([readonly], [disabled], [part~='overflow'])) [part='remove-button'] {
|
|
61
70
|
display: none !important;
|
|
62
71
|
}
|
|
63
72
|
</style>
|
|
@@ -9,10 +9,9 @@ import { css, registerStyles } from '@vaadin/vaadin-themable-mixin/vaadin-themab
|
|
|
9
9
|
registerStyles(
|
|
10
10
|
'vaadin-multi-select-combo-box-container',
|
|
11
11
|
css`
|
|
12
|
-
|
|
12
|
+
#wrapper {
|
|
13
13
|
display: flex;
|
|
14
14
|
width: 100%;
|
|
15
|
-
min-width: 0;
|
|
16
15
|
}
|
|
17
16
|
`,
|
|
18
17
|
{
|
|
@@ -40,7 +39,7 @@ class MultiSelectComboBoxContainer extends InputContainer {
|
|
|
40
39
|
const slots = content.querySelectorAll('slot');
|
|
41
40
|
|
|
42
41
|
const wrapper = document.createElement('div');
|
|
43
|
-
wrapper.setAttribute('
|
|
42
|
+
wrapper.setAttribute('id', 'wrapper');
|
|
44
43
|
content.insertBefore(wrapper, slots[2]);
|
|
45
44
|
|
|
46
45
|
wrapper.appendChild(slots[0]);
|
|
@@ -179,6 +179,10 @@ class MultiSelectComboBoxInternal extends ComboBoxDataProviderMixin(ComboBoxMixi
|
|
|
179
179
|
* @override
|
|
180
180
|
*/
|
|
181
181
|
_onFocusout(event) {
|
|
182
|
+
// Disable combo-box logic that updates selectedItem
|
|
183
|
+
// based on the overlay focused index on input blur
|
|
184
|
+
this._ignoreCommitValue = true;
|
|
185
|
+
|
|
182
186
|
super._onFocusout(event);
|
|
183
187
|
|
|
184
188
|
if (this.readonly && !this._closeOnBlurIsPrevented) {
|
|
@@ -186,6 +190,26 @@ class MultiSelectComboBoxInternal extends ComboBoxDataProviderMixin(ComboBoxMixi
|
|
|
186
190
|
}
|
|
187
191
|
}
|
|
188
192
|
|
|
193
|
+
/**
|
|
194
|
+
* Override method inherited from the combo-box
|
|
195
|
+
* to not commit an already selected item again
|
|
196
|
+
* on blur, which would result in un-selecting.
|
|
197
|
+
* @protected
|
|
198
|
+
* @override
|
|
199
|
+
*/
|
|
200
|
+
_detectAndDispatchChange() {
|
|
201
|
+
if (this._ignoreCommitValue) {
|
|
202
|
+
this._ignoreCommitValue = false;
|
|
203
|
+
|
|
204
|
+
// Reset internal combo-box state
|
|
205
|
+
this.selectedItem = null;
|
|
206
|
+
this._inputElementValue = '';
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
super._detectAndDispatchChange();
|
|
211
|
+
}
|
|
212
|
+
|
|
189
213
|
/**
|
|
190
214
|
* @param {CustomEvent} event
|
|
191
215
|
* @protected
|
|
@@ -17,6 +17,19 @@ class MultiSelectComboBoxScroller extends ComboBoxScroller {
|
|
|
17
17
|
return 'vaadin-multi-select-combo-box-scroller';
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
/** @protected */
|
|
21
|
+
ready() {
|
|
22
|
+
super.ready();
|
|
23
|
+
|
|
24
|
+
this.setAttribute('aria-multiselectable', 'true');
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** @private */
|
|
28
|
+
__getAriaSelected(_focusedIndex, itemIndex) {
|
|
29
|
+
const item = this.items[itemIndex];
|
|
30
|
+
return this.__isItemSelected(item, null, this.itemIdPath).toString();
|
|
31
|
+
}
|
|
32
|
+
|
|
20
33
|
/** @private */
|
|
21
34
|
__isItemSelected(item, _selectedItem, itemIdPath) {
|
|
22
35
|
if (item instanceof ComboBoxPlaceholder) {
|
|
@@ -20,6 +20,14 @@ import { LabelMixinClass } from '@vaadin/field-base/src/label-mixin.js';
|
|
|
20
20
|
import { ValidateMixinClass } from '@vaadin/field-base/src/validate-mixin.js';
|
|
21
21
|
import { ThemableMixinClass } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
22
22
|
|
|
23
|
+
export interface MultiSelectComboBoxI18n {
|
|
24
|
+
cleared: string;
|
|
25
|
+
focused: string;
|
|
26
|
+
selected: string;
|
|
27
|
+
deselected: string;
|
|
28
|
+
total: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
23
31
|
/**
|
|
24
32
|
* Fired when the user commits a value change.
|
|
25
33
|
*/
|
|
@@ -30,7 +38,7 @@ export type MultiSelectComboBoxChangeEvent<TItem> = Event & {
|
|
|
30
38
|
/**
|
|
31
39
|
* Fired when the user sets a custom value.
|
|
32
40
|
*/
|
|
33
|
-
export type
|
|
41
|
+
export type MultiSelectComboBoxCustomValueSetEvent = CustomEvent<string>;
|
|
34
42
|
|
|
35
43
|
/**
|
|
36
44
|
* Fired when the `filter` property changes.
|
|
@@ -50,7 +58,7 @@ export type MultiSelectComboBoxSelectedItemsChangedEvent<TItem> = CustomEvent<{
|
|
|
50
58
|
export interface MultiSelectComboBoxEventMap<TItem> extends HTMLElementEventMap {
|
|
51
59
|
change: MultiSelectComboBoxChangeEvent<TItem>;
|
|
52
60
|
|
|
53
|
-
'custom-
|
|
61
|
+
'custom-value-set': MultiSelectComboBoxCustomValueSetEvent;
|
|
54
62
|
|
|
55
63
|
'filter-changed': MultiSelectComboBoxFilterChangedEvent;
|
|
56
64
|
|
|
@@ -79,6 +87,7 @@ export interface MultiSelectComboBoxEventMap<TItem> extends HTMLElementEventMap
|
|
|
79
87
|
*
|
|
80
88
|
* Part name | Description
|
|
81
89
|
* -----------------------|----------------
|
|
90
|
+
* `chips` | The element that wraps chips for selected items
|
|
82
91
|
* `chip` | Chip shown for every selected item
|
|
83
92
|
* `label` | The label element
|
|
84
93
|
* `input-field` | The element that wraps prefix, value and suffix
|
|
@@ -112,7 +121,6 @@ export interface MultiSelectComboBoxEventMap<TItem> extends HTMLElementEventMap
|
|
|
112
121
|
* -----------------------------------------------------|----------------------------|--------
|
|
113
122
|
* `--vaadin-field-default-width` | Default width of the field | `12em`
|
|
114
123
|
* `--vaadin-multi-select-combo-box-overlay-max-height` | Max height of the overlay | `65vh`
|
|
115
|
-
* `--vaadin-multi-select-combo-box-chip-min-width` | Min width of the chip | `60px`
|
|
116
124
|
* `--vaadin-multi-select-combo-box-input-min-width` | Min width of the input | `4em`
|
|
117
125
|
*
|
|
118
126
|
* ### Internal components
|
|
@@ -130,7 +138,7 @@ export interface MultiSelectComboBoxEventMap<TItem> extends HTMLElementEventMap
|
|
|
130
138
|
* See [Styling Components](https://vaadin.com/docs/latest/ds/customization/styling-components) documentation.
|
|
131
139
|
*
|
|
132
140
|
* @fires {Event} change - Fired when the user commits a value change.
|
|
133
|
-
* @fires {CustomEvent} custom-
|
|
141
|
+
* @fires {CustomEvent} custom-value-set - Fired when the user sets a custom value.
|
|
134
142
|
* @fires {CustomEvent} filter-changed - Fired when the `filter` property changes.
|
|
135
143
|
* @fires {CustomEvent} invalid-changed - Fired when the `invalid` property changes.
|
|
136
144
|
* @fires {CustomEvent} selected-items-changed - Fired when the `selectedItems` property changes.
|
|
@@ -138,9 +146,9 @@ export interface MultiSelectComboBoxEventMap<TItem> extends HTMLElementEventMap
|
|
|
138
146
|
declare class MultiSelectComboBox<TItem = ComboBoxDefaultItem> extends HTMLElement {
|
|
139
147
|
/**
|
|
140
148
|
* When true, the user can input a value that is not present in the items list.
|
|
141
|
-
* @attr {boolean} allow-custom-
|
|
149
|
+
* @attr {boolean} allow-custom-value
|
|
142
150
|
*/
|
|
143
|
-
|
|
151
|
+
allowCustomValue: boolean;
|
|
144
152
|
|
|
145
153
|
/**
|
|
146
154
|
* Set true to prevent the overlay from opening automatically.
|
|
@@ -199,6 +207,30 @@ declare class MultiSelectComboBox<TItem = ComboBoxDefaultItem> extends HTMLEleme
|
|
|
199
207
|
*/
|
|
200
208
|
itemValuePath: string;
|
|
201
209
|
|
|
210
|
+
/**
|
|
211
|
+
* The object used to localize this component.
|
|
212
|
+
* To change the default localization, replace the entire
|
|
213
|
+
* _i18n_ object or just the property you want to modify.
|
|
214
|
+
*
|
|
215
|
+
* The object has the following JSON structure and default values:
|
|
216
|
+
* ```
|
|
217
|
+
* {
|
|
218
|
+
* // Screen reader announcement on clear button click.
|
|
219
|
+
* cleared: 'Selection cleared',
|
|
220
|
+
* // Screen reader announcement when a chip is focused.
|
|
221
|
+
* focused: ' focused. Press Backspace to remove',
|
|
222
|
+
* // Screen reader announcement when item is selected.
|
|
223
|
+
* selected: 'added to selection',
|
|
224
|
+
* // Screen reader announcement when item is deselected.
|
|
225
|
+
* deselected: 'removed from selection',
|
|
226
|
+
* // Screen reader announcement of the selected items count.
|
|
227
|
+
* // {count} is replaced with the actual count of items.
|
|
228
|
+
* total: '{count} items selected',
|
|
229
|
+
* }
|
|
230
|
+
* ```
|
|
231
|
+
*/
|
|
232
|
+
i18n: MultiSelectComboBoxI18n;
|
|
233
|
+
|
|
202
234
|
/**
|
|
203
235
|
* True if the dropdown is open, false otherwise.
|
|
204
236
|
*/
|
|
@@ -210,6 +242,13 @@ declare class MultiSelectComboBox<TItem = ComboBoxDefaultItem> extends HTMLEleme
|
|
|
210
242
|
*/
|
|
211
243
|
pageSize: number;
|
|
212
244
|
|
|
245
|
+
/**
|
|
246
|
+
* A hint to the user of what can be entered in the control.
|
|
247
|
+
* The placeholder will be only displayed in the case when
|
|
248
|
+
* there is no item selected.
|
|
249
|
+
*/
|
|
250
|
+
placeholder: string;
|
|
251
|
+
|
|
213
252
|
/**
|
|
214
253
|
* Custom function for rendering the content of every item.
|
|
215
254
|
* Receives three arguments:
|
|
@@ -7,6 +7,7 @@ import './vaadin-multi-select-combo-box-chip.js';
|
|
|
7
7
|
import './vaadin-multi-select-combo-box-container.js';
|
|
8
8
|
import './vaadin-multi-select-combo-box-internal.js';
|
|
9
9
|
import { html, PolymerElement } from '@polymer/polymer/polymer-element.js';
|
|
10
|
+
import { announce } from '@vaadin/component-base/src/a11y-announcer.js';
|
|
10
11
|
import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
|
|
11
12
|
import { ResizeMixin } from '@vaadin/component-base/src/resize-mixin.js';
|
|
12
13
|
import { processTemplates } from '@vaadin/component-base/src/templates.js';
|
|
@@ -18,7 +19,6 @@ import { css, registerStyles, ThemableMixin } from '@vaadin/vaadin-themable-mixi
|
|
|
18
19
|
|
|
19
20
|
const multiSelectComboBox = css`
|
|
20
21
|
:host {
|
|
21
|
-
--chip-min-width: var(--vaadin-multi-select-combo-box-chip-min-width, 4em);
|
|
22
22
|
--input-min-width: var(--vaadin-multi-select-combo-box-input-min-width, 4em);
|
|
23
23
|
}
|
|
24
24
|
|
|
@@ -26,6 +26,11 @@ const multiSelectComboBox = css`
|
|
|
26
26
|
display: none !important;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
#chips {
|
|
30
|
+
display: flex;
|
|
31
|
+
align-items: center;
|
|
32
|
+
}
|
|
33
|
+
|
|
29
34
|
:host([has-value]) ::slotted(input:placeholder-shown) {
|
|
30
35
|
color: transparent !important;
|
|
31
36
|
}
|
|
@@ -37,11 +42,12 @@ const multiSelectComboBox = css`
|
|
|
37
42
|
|
|
38
43
|
[part='chip'] {
|
|
39
44
|
flex: 0 1 auto;
|
|
40
|
-
min-width: var(--chip-min-width);
|
|
41
45
|
}
|
|
42
46
|
|
|
43
|
-
:host([readonly]
|
|
44
|
-
|
|
47
|
+
:host(:is([readonly], [disabled])) ::slotted(input) {
|
|
48
|
+
flex-grow: 0;
|
|
49
|
+
flex-basis: 0;
|
|
50
|
+
padding: 0;
|
|
45
51
|
}
|
|
46
52
|
`;
|
|
47
53
|
|
|
@@ -69,6 +75,7 @@ registerStyles('vaadin-multi-select-combo-box', [inputFieldShared, multiSelectCo
|
|
|
69
75
|
*
|
|
70
76
|
* Part name | Description
|
|
71
77
|
* -----------------------|----------------
|
|
78
|
+
* `chips` | The element that wraps chips for selected items
|
|
72
79
|
* `chip` | Chip shown for every selected item
|
|
73
80
|
* `label` | The label element
|
|
74
81
|
* `input-field` | The element that wraps prefix, value and suffix
|
|
@@ -102,7 +109,6 @@ registerStyles('vaadin-multi-select-combo-box', [inputFieldShared, multiSelectCo
|
|
|
102
109
|
* -----------------------------------------------------|----------------------------|--------
|
|
103
110
|
* `--vaadin-field-default-width` | Default width of the field | `12em`
|
|
104
111
|
* `--vaadin-multi-select-combo-box-overlay-max-height` | Max height of the overlay | `65vh`
|
|
105
|
-
* `--vaadin-multi-select-combo-box-chip-min-width` | Min width of the chip | `60px`
|
|
106
112
|
* `--vaadin-multi-select-combo-box-input-min-width` | Min width of the input | `4em`
|
|
107
113
|
*
|
|
108
114
|
* ### Internal components
|
|
@@ -120,7 +126,7 @@ registerStyles('vaadin-multi-select-combo-box', [inputFieldShared, multiSelectCo
|
|
|
120
126
|
* See [Styling Components](https://vaadin.com/docs/latest/ds/customization/styling-components) documentation.
|
|
121
127
|
*
|
|
122
128
|
* @fires {Event} change - Fired when the user commits a value change.
|
|
123
|
-
* @fires {CustomEvent} custom-
|
|
129
|
+
* @fires {CustomEvent} custom-value-set - Fired when the user sets a custom value.
|
|
124
130
|
* @fires {CustomEvent} filter-changed - Fired when the `filter` property changes.
|
|
125
131
|
* @fires {CustomEvent} invalid-changed - Fired when the `invalid` property changes.
|
|
126
132
|
* @fires {CustomEvent} selected-items-changed - Fired when the `selectedItems` property changes.
|
|
@@ -153,7 +159,7 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
|
|
|
153
159
|
disabled="[[disabled]]"
|
|
154
160
|
readonly="[[readonly]]"
|
|
155
161
|
auto-open-disabled="[[autoOpenDisabled]]"
|
|
156
|
-
allow-custom-value="[[
|
|
162
|
+
allow-custom-value="[[allowCustomValue]]"
|
|
157
163
|
data-provider="[[dataProvider]]"
|
|
158
164
|
filter="{{filter}}"
|
|
159
165
|
filtered-items="[[filteredItems]]"
|
|
@@ -172,14 +178,17 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
|
|
|
172
178
|
theme$="[[theme]]"
|
|
173
179
|
>
|
|
174
180
|
<vaadin-multi-select-combo-box-chip
|
|
181
|
+
id="overflow"
|
|
175
182
|
slot="prefix"
|
|
176
183
|
part$="[[_getOverflowPart(_overflowItems.length)]]"
|
|
177
184
|
disabled="[[disabled]]"
|
|
185
|
+
readonly="[[readonly]]"
|
|
178
186
|
label="[[_getOverflowLabel(_overflowItems.length)]]"
|
|
179
187
|
title$="[[_getOverflowTitle(_overflowItems)]]"
|
|
180
188
|
hidden$="[[_isOverflowHidden(_overflowItems.length)]]"
|
|
181
189
|
on-mousedown="_preventBlur"
|
|
182
190
|
></vaadin-multi-select-combo-box-chip>
|
|
191
|
+
<div id="chips" part="chips" slot="prefix"></div>
|
|
183
192
|
<slot name="input"></slot>
|
|
184
193
|
<div id="clearButton" part="clear-button" slot="suffix"></div>
|
|
185
194
|
<div id="toggleButton" class="toggle-button" part="toggle-button" slot="suffix"></div>
|
|
@@ -249,6 +258,43 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
|
|
|
249
258
|
type: String,
|
|
250
259
|
},
|
|
251
260
|
|
|
261
|
+
/**
|
|
262
|
+
* The object used to localize this component.
|
|
263
|
+
* To change the default localization, replace the entire
|
|
264
|
+
* _i18n_ object or just the property you want to modify.
|
|
265
|
+
*
|
|
266
|
+
* The object has the following JSON structure and default values:
|
|
267
|
+
* ```
|
|
268
|
+
* {
|
|
269
|
+
* // Screen reader announcement on clear button click.
|
|
270
|
+
* cleared: 'Selection cleared',
|
|
271
|
+
* // Screen reader announcement when a chip is focused.
|
|
272
|
+
* focused: ' focused. Press Backspace to remove',
|
|
273
|
+
* // Screen reader announcement when item is selected.
|
|
274
|
+
* selected: 'added to selection',
|
|
275
|
+
* // Screen reader announcement when item is deselected.
|
|
276
|
+
* deselected: 'removed from selection',
|
|
277
|
+
* // Screen reader announcement of the selected items count.
|
|
278
|
+
* // {count} is replaced with the actual count of items.
|
|
279
|
+
* total: '{count} items selected',
|
|
280
|
+
* }
|
|
281
|
+
* ```
|
|
282
|
+
* @type {!MultiSelectComboBoxI18n}
|
|
283
|
+
* @default {English/US}
|
|
284
|
+
*/
|
|
285
|
+
i18n: {
|
|
286
|
+
type: Object,
|
|
287
|
+
value: () => {
|
|
288
|
+
return {
|
|
289
|
+
cleared: 'Selection cleared',
|
|
290
|
+
focused: 'focused. Press Backspace to remove',
|
|
291
|
+
selected: 'added to selection',
|
|
292
|
+
deselected: 'removed from selection',
|
|
293
|
+
total: '{count} items selected',
|
|
294
|
+
};
|
|
295
|
+
},
|
|
296
|
+
},
|
|
297
|
+
|
|
252
298
|
/**
|
|
253
299
|
* When present, it specifies that the field is read-only.
|
|
254
300
|
*/
|
|
@@ -308,13 +354,24 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
|
|
|
308
354
|
|
|
309
355
|
/**
|
|
310
356
|
* When true, the user can input a value that is not present in the items list.
|
|
311
|
-
* @attr {boolean} allow-custom-
|
|
357
|
+
* @attr {boolean} allow-custom-value
|
|
312
358
|
*/
|
|
313
|
-
|
|
359
|
+
allowCustomValue: {
|
|
314
360
|
type: Boolean,
|
|
315
361
|
value: false,
|
|
316
362
|
},
|
|
317
363
|
|
|
364
|
+
/**
|
|
365
|
+
* A hint to the user of what can be entered in the control.
|
|
366
|
+
* The placeholder will be only displayed in the case when
|
|
367
|
+
* there is no item selected.
|
|
368
|
+
*/
|
|
369
|
+
placeholder: {
|
|
370
|
+
type: String,
|
|
371
|
+
value: '',
|
|
372
|
+
observer: '_placeholderChanged',
|
|
373
|
+
},
|
|
374
|
+
|
|
318
375
|
/**
|
|
319
376
|
* Custom function for rendering the content of every item.
|
|
320
377
|
* Receives three arguments:
|
|
@@ -355,6 +412,13 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
|
|
|
355
412
|
type: Array,
|
|
356
413
|
value: () => [],
|
|
357
414
|
},
|
|
415
|
+
|
|
416
|
+
/** @private */
|
|
417
|
+
_focusedChipIndex: {
|
|
418
|
+
type: Number,
|
|
419
|
+
value: -1,
|
|
420
|
+
observer: '_focusedChipIndexChanged',
|
|
421
|
+
},
|
|
358
422
|
};
|
|
359
423
|
}
|
|
360
424
|
|
|
@@ -401,7 +465,7 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
|
|
|
401
465
|
* @return {boolean}
|
|
402
466
|
*/
|
|
403
467
|
checkValidity() {
|
|
404
|
-
return this.required ? this._hasValue : true;
|
|
468
|
+
return this.required && !this.readonly ? this._hasValue : true;
|
|
405
469
|
}
|
|
406
470
|
|
|
407
471
|
/**
|
|
@@ -413,9 +477,7 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
|
|
|
413
477
|
super._disabledChanged(disabled, oldDisabled);
|
|
414
478
|
|
|
415
479
|
if (disabled || oldDisabled) {
|
|
416
|
-
this.
|
|
417
|
-
chip.toggleAttribute('disabled', disabled);
|
|
418
|
-
});
|
|
480
|
+
this.__updateChips();
|
|
419
481
|
}
|
|
420
482
|
}
|
|
421
483
|
|
|
@@ -441,6 +503,7 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
|
|
|
441
503
|
super._setFocused(focused);
|
|
442
504
|
|
|
443
505
|
if (!focused) {
|
|
506
|
+
this._focusedChipIndex = -1;
|
|
444
507
|
this.validate();
|
|
445
508
|
}
|
|
446
509
|
}
|
|
@@ -464,6 +527,26 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
|
|
|
464
527
|
this.__updateChips();
|
|
465
528
|
}
|
|
466
529
|
|
|
530
|
+
/**
|
|
531
|
+
* Override method from `DelegateStateMixin` to set required state
|
|
532
|
+
* using `aria-required` attribute instead of `required`, in order
|
|
533
|
+
* to prevent screen readers from announcing "invalid entry".
|
|
534
|
+
* @protected
|
|
535
|
+
* @override
|
|
536
|
+
*/
|
|
537
|
+
_delegateAttribute(name, value) {
|
|
538
|
+
if (!this.stateTarget) {
|
|
539
|
+
return;
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
if (name === 'required') {
|
|
543
|
+
this._delegateAttribute('aria-required', value ? 'true' : false);
|
|
544
|
+
return;
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
super._delegateAttribute(name, value);
|
|
548
|
+
}
|
|
549
|
+
|
|
467
550
|
/**
|
|
468
551
|
* Setting clear button visible reduces total space available
|
|
469
552
|
* for rendering chips, and making it hidden increases it.
|
|
@@ -480,18 +563,11 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
|
|
|
480
563
|
if (readonly) {
|
|
481
564
|
this.__savedItems = this.$.comboBox._getOverlayItems();
|
|
482
565
|
this.$.comboBox._setOverlayItems(Array.from(this.selectedItems));
|
|
483
|
-
|
|
484
|
-
// Update chips to hide remove button
|
|
485
|
-
this._chips.forEach((chip) => {
|
|
486
|
-
chip.setAttribute('readonly', '');
|
|
487
|
-
});
|
|
566
|
+
this.__updateChips();
|
|
488
567
|
} else if (oldReadonly) {
|
|
489
568
|
this.$.comboBox._setOverlayItems(this.__savedItems);
|
|
490
569
|
this.__savedItems = null;
|
|
491
|
-
|
|
492
|
-
this._chips.forEach((chip) => {
|
|
493
|
-
chip.removeAttribute('readonly');
|
|
494
|
-
});
|
|
570
|
+
this.__updateChips();
|
|
495
571
|
}
|
|
496
572
|
}
|
|
497
573
|
|
|
@@ -505,12 +581,35 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
|
|
|
505
581
|
this.$.comboBox.pageSize = this.pageSize;
|
|
506
582
|
}
|
|
507
583
|
|
|
584
|
+
/** @private */
|
|
585
|
+
_placeholderChanged(placeholder) {
|
|
586
|
+
const tmpPlaceholder = this.__tmpA11yPlaceholder;
|
|
587
|
+
// Do not store temporary placeholder
|
|
588
|
+
if (tmpPlaceholder !== placeholder) {
|
|
589
|
+
this.__savedPlaceholder = placeholder;
|
|
590
|
+
|
|
591
|
+
if (tmpPlaceholder) {
|
|
592
|
+
this.placeholder = tmpPlaceholder;
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
|
|
508
597
|
/** @private */
|
|
509
598
|
_selectedItemsChanged(selectedItems) {
|
|
510
599
|
this._hasValue = Boolean(selectedItems && selectedItems.length);
|
|
511
600
|
|
|
512
601
|
this._toggleHasValue();
|
|
513
602
|
|
|
603
|
+
// Use placeholder for announcing items
|
|
604
|
+
if (this._hasValue) {
|
|
605
|
+
const tmpPlaceholder = selectedItems.map((item) => this._getItemLabel(item, this.itemLabelPath)).join(', ');
|
|
606
|
+
this.__tmpA11yPlaceholder = tmpPlaceholder;
|
|
607
|
+
this.placeholder = tmpPlaceholder;
|
|
608
|
+
} else {
|
|
609
|
+
delete this.__tmpA11yPlaceholder;
|
|
610
|
+
this.placeholder = this.__savedPlaceholder;
|
|
611
|
+
}
|
|
612
|
+
|
|
514
613
|
// Re-render chips
|
|
515
614
|
this.__updateChips();
|
|
516
615
|
|
|
@@ -580,11 +679,19 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
|
|
|
580
679
|
this.$.comboBox.clear();
|
|
581
680
|
}
|
|
582
681
|
|
|
682
|
+
/** @private */
|
|
683
|
+
__announceItem(itemLabel, isSelected, itemCount) {
|
|
684
|
+
const state = isSelected ? 'selected' : 'deselected';
|
|
685
|
+
const total = this.i18n.total.replace('{count}', itemCount || 0);
|
|
686
|
+
announce(`${itemLabel} ${this.i18n[state]} ${total}`);
|
|
687
|
+
}
|
|
688
|
+
|
|
583
689
|
/** @private */
|
|
584
690
|
__removeItem(item) {
|
|
585
691
|
const itemsCopy = [...this.selectedItems];
|
|
586
692
|
itemsCopy.splice(itemsCopy.indexOf(item), 1);
|
|
587
693
|
this.__updateSelection(itemsCopy);
|
|
694
|
+
this.__announceItem(item, false, itemsCopy.length);
|
|
588
695
|
}
|
|
589
696
|
|
|
590
697
|
/** @private */
|
|
@@ -592,9 +699,13 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
|
|
|
592
699
|
const itemsCopy = [...this.selectedItems];
|
|
593
700
|
|
|
594
701
|
const index = this._findIndex(item, itemsCopy, this.itemIdPath);
|
|
702
|
+
const itemLabel = this._getItemLabel(item, this.itemLabelPath);
|
|
703
|
+
|
|
704
|
+
let isSelected = false;
|
|
705
|
+
|
|
595
706
|
if (index !== -1) {
|
|
596
707
|
// Do not unselect when manually typing and committing an already selected item.
|
|
597
|
-
if (this.filter.toLowerCase() ===
|
|
708
|
+
if (this.filter.toLowerCase() === itemLabel.toLowerCase()) {
|
|
598
709
|
this.__clearFilter();
|
|
599
710
|
return;
|
|
600
711
|
}
|
|
@@ -602,12 +713,15 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
|
|
|
602
713
|
itemsCopy.splice(index, 1);
|
|
603
714
|
} else {
|
|
604
715
|
itemsCopy.push(item);
|
|
716
|
+
isSelected = true;
|
|
605
717
|
}
|
|
606
718
|
|
|
607
719
|
this.__updateSelection(itemsCopy);
|
|
608
720
|
|
|
609
721
|
// Suppress `value-changed` event.
|
|
610
722
|
this.__clearFilter();
|
|
723
|
+
|
|
724
|
+
this.__announceItem(itemLabel, isSelected, itemsCopy.length);
|
|
611
725
|
}
|
|
612
726
|
|
|
613
727
|
/** @private */
|
|
@@ -626,8 +740,8 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
|
|
|
626
740
|
chip.setAttribute('slot', 'prefix');
|
|
627
741
|
|
|
628
742
|
chip.item = item;
|
|
629
|
-
chip.
|
|
630
|
-
chip.
|
|
743
|
+
chip.disabled = this.disabled;
|
|
744
|
+
chip.readonly = this.readonly;
|
|
631
745
|
|
|
632
746
|
const label = this._getItemLabel(item, this.itemLabelPath);
|
|
633
747
|
chip.label = label;
|
|
@@ -640,18 +754,21 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
|
|
|
640
754
|
}
|
|
641
755
|
|
|
642
756
|
/** @private */
|
|
643
|
-
|
|
757
|
+
__getOverflowWidth() {
|
|
758
|
+
const chip = this.$.overflow;
|
|
759
|
+
|
|
644
760
|
chip.style.visibility = 'hidden';
|
|
645
|
-
chip.
|
|
646
|
-
chip.style.minWidth = 'var(--chip-min-width)';
|
|
761
|
+
chip.removeAttribute('hidden');
|
|
647
762
|
|
|
648
|
-
|
|
763
|
+
// Detect max possible width of the overflow chip
|
|
764
|
+
chip.setAttribute('part', 'chip overflow');
|
|
765
|
+
const overflowStyle = getComputedStyle(chip);
|
|
766
|
+
const overflowWidth = chip.clientWidth + parseInt(overflowStyle.marginInlineStart);
|
|
649
767
|
|
|
650
|
-
chip.
|
|
651
|
-
chip.style.display = '';
|
|
768
|
+
chip.setAttribute('hidden', '');
|
|
652
769
|
chip.style.visibility = '';
|
|
653
770
|
|
|
654
|
-
return
|
|
771
|
+
return overflowWidth;
|
|
655
772
|
}
|
|
656
773
|
|
|
657
774
|
/** @private */
|
|
@@ -661,46 +778,36 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
|
|
|
661
778
|
}
|
|
662
779
|
|
|
663
780
|
// Clear all chips except the overflow
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
chip.remove();
|
|
781
|
+
Array.from(this._chips).forEach((chip) => {
|
|
782
|
+
if (chip !== this.$.overflow) {
|
|
783
|
+
chip.remove();
|
|
784
|
+
}
|
|
669
785
|
});
|
|
670
786
|
|
|
671
787
|
const items = [...this.selectedItems];
|
|
672
788
|
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
const chipMinWidth = this.__getMinWidth(overflow);
|
|
677
|
-
const inputMinWidth = parseInt(getComputedStyle(this.inputElement).flexBasis);
|
|
678
|
-
const containerStyle = getComputedStyle(this._inputField);
|
|
789
|
+
// Detect available remaining width for chips
|
|
790
|
+
const totalWidth = this._inputField.$.wrapper.clientWidth;
|
|
791
|
+
const inputWidth = parseInt(getComputedStyle(this.inputElement).flexBasis);
|
|
679
792
|
|
|
680
|
-
|
|
681
|
-
let totalWidth =
|
|
682
|
-
parseInt(containerStyle.width) -
|
|
683
|
-
parseInt(containerStyle.paddingLeft) -
|
|
684
|
-
parseInt(containerStyle.paddingRight) -
|
|
685
|
-
this.$.toggleButton.clientWidth -
|
|
686
|
-
inputMinWidth;
|
|
793
|
+
let remainingWidth = totalWidth - inputWidth;
|
|
687
794
|
|
|
688
|
-
if (
|
|
689
|
-
|
|
795
|
+
if (items.length > 1) {
|
|
796
|
+
remainingWidth -= this.__getOverflowWidth();
|
|
690
797
|
}
|
|
691
798
|
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
799
|
+
// Add chips until remaining width is exceeded
|
|
800
|
+
for (let i = items.length - 1, refNode = null; i >= 0; i--) {
|
|
801
|
+
const chip = this.__createChip(items[i]);
|
|
802
|
+
this.$.chips.insertBefore(chip, refNode);
|
|
803
|
+
|
|
804
|
+
if (this.$.chips.clientWidth > remainingWidth) {
|
|
805
|
+
chip.remove();
|
|
695
806
|
break;
|
|
696
807
|
}
|
|
697
808
|
|
|
698
|
-
|
|
699
|
-
const chip = this.__createChip(item);
|
|
700
|
-
this._inputField.insertBefore(chip, refNode);
|
|
701
|
-
|
|
809
|
+
items.pop();
|
|
702
810
|
refNode = chip;
|
|
703
|
-
totalWidth -= chipMinWidth;
|
|
704
811
|
}
|
|
705
812
|
|
|
706
813
|
this._overflowItems = items;
|
|
@@ -715,6 +822,8 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
|
|
|
715
822
|
event.stopPropagation();
|
|
716
823
|
|
|
717
824
|
this.__updateSelection([]);
|
|
825
|
+
|
|
826
|
+
announce(this.i18n.cleared);
|
|
718
827
|
}
|
|
719
828
|
|
|
720
829
|
/**
|
|
@@ -725,8 +834,121 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
|
|
|
725
834
|
*/
|
|
726
835
|
_onKeyDown(event) {
|
|
727
836
|
const items = this.selectedItems || [];
|
|
728
|
-
|
|
729
|
-
|
|
837
|
+
|
|
838
|
+
if (event.key === 'Escape' && this.clearButtonVisible && items.length) {
|
|
839
|
+
this.selectedItems = [];
|
|
840
|
+
return;
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
const chips = Array.from(this._chips).slice(1);
|
|
844
|
+
|
|
845
|
+
if (!this.readonly && chips.length > 0) {
|
|
846
|
+
switch (event.key) {
|
|
847
|
+
case 'Backspace':
|
|
848
|
+
this._onBackSpace(chips);
|
|
849
|
+
break;
|
|
850
|
+
case 'ArrowLeft':
|
|
851
|
+
this._onArrowLeft(chips);
|
|
852
|
+
break;
|
|
853
|
+
case 'ArrowRight':
|
|
854
|
+
this._onArrowRight(chips);
|
|
855
|
+
break;
|
|
856
|
+
default:
|
|
857
|
+
this._focusedChipIndex = -1;
|
|
858
|
+
break;
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
/** @private */
|
|
864
|
+
_onArrowLeft(chips) {
|
|
865
|
+
if (this.inputElement.value !== '' || this.opened) {
|
|
866
|
+
return;
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
const idx = this._focusedChipIndex;
|
|
870
|
+
let newIdx;
|
|
871
|
+
|
|
872
|
+
if (this.getAttribute('dir') !== 'rtl') {
|
|
873
|
+
if (idx === -1) {
|
|
874
|
+
// Focus last chip
|
|
875
|
+
newIdx = chips.length - 1;
|
|
876
|
+
} else if (idx > 0) {
|
|
877
|
+
// Focus prev chip
|
|
878
|
+
newIdx = idx - 1;
|
|
879
|
+
}
|
|
880
|
+
} else if (idx === chips.length - 1) {
|
|
881
|
+
// Blur last chip
|
|
882
|
+
newIdx = -1;
|
|
883
|
+
} else if (idx > -1) {
|
|
884
|
+
// Focus next chip
|
|
885
|
+
newIdx = idx + 1;
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
if (newIdx !== undefined) {
|
|
889
|
+
this._focusedChipIndex = newIdx;
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
/** @private */
|
|
894
|
+
_onArrowRight(chips) {
|
|
895
|
+
if (this.inputElement.value !== '' || this.opened) {
|
|
896
|
+
return;
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
const idx = this._focusedChipIndex;
|
|
900
|
+
let newIdx;
|
|
901
|
+
|
|
902
|
+
if (this.getAttribute('dir') === 'rtl') {
|
|
903
|
+
if (idx === -1) {
|
|
904
|
+
// Focus last chip
|
|
905
|
+
newIdx = chips.length - 1;
|
|
906
|
+
} else if (idx > 0) {
|
|
907
|
+
// Focus prev chip
|
|
908
|
+
newIdx = idx - 1;
|
|
909
|
+
}
|
|
910
|
+
} else if (idx === chips.length - 1) {
|
|
911
|
+
// Blur last chip
|
|
912
|
+
newIdx = -1;
|
|
913
|
+
} else if (idx > -1) {
|
|
914
|
+
// Focus next chip
|
|
915
|
+
newIdx = idx + 1;
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
if (newIdx !== undefined) {
|
|
919
|
+
this._focusedChipIndex = newIdx;
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
/** @private */
|
|
924
|
+
_onBackSpace(chips) {
|
|
925
|
+
if (this.inputElement.value !== '' || this.opened) {
|
|
926
|
+
return;
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
const idx = this._focusedChipIndex;
|
|
930
|
+
if (idx === -1) {
|
|
931
|
+
this._focusedChipIndex = chips.length - 1;
|
|
932
|
+
} else {
|
|
933
|
+
this.__removeItem(chips[idx].item);
|
|
934
|
+
this._focusedChipIndex = -1;
|
|
935
|
+
}
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
/** @private */
|
|
939
|
+
_focusedChipIndexChanged(focusedIndex, oldFocusedIndex) {
|
|
940
|
+
if (focusedIndex > -1 || oldFocusedIndex > -1) {
|
|
941
|
+
const chips = Array.from(this._chips).slice(1);
|
|
942
|
+
chips.forEach((chip, index) => {
|
|
943
|
+
chip.toggleAttribute('focused', index === focusedIndex);
|
|
944
|
+
});
|
|
945
|
+
|
|
946
|
+
// Announce focused chip
|
|
947
|
+
if (focusedIndex > -1) {
|
|
948
|
+
const item = chips[focusedIndex].item;
|
|
949
|
+
const itemLabel = this._getItemLabel(item, this.itemLabelPath);
|
|
950
|
+
announce(`${itemLabel} ${this.i18n.focused}`);
|
|
951
|
+
}
|
|
730
952
|
}
|
|
731
953
|
}
|
|
732
954
|
|
|
@@ -748,10 +970,13 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
|
|
|
748
970
|
// Do not set combo-box value
|
|
749
971
|
event.preventDefault();
|
|
750
972
|
|
|
973
|
+
// Stop the original event
|
|
974
|
+
event.stopPropagation();
|
|
975
|
+
|
|
751
976
|
this.__clearFilter();
|
|
752
977
|
|
|
753
978
|
this.dispatchEvent(
|
|
754
|
-
new CustomEvent('custom-
|
|
979
|
+
new CustomEvent('custom-value-set', {
|
|
755
980
|
detail: event.detail,
|
|
756
981
|
composed: true,
|
|
757
982
|
bubbles: true,
|
|
@@ -22,6 +22,15 @@ const chip = css`
|
|
|
22
22
|
cursor: var(--lumo-clickable-cursor);
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
:host([focused]) {
|
|
26
|
+
background-color: var(--lumo-primary-color);
|
|
27
|
+
color: var(--lumo-primary-contrast-color);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
:host([focused]) [part='remove-button'] {
|
|
31
|
+
color: inherit;
|
|
32
|
+
}
|
|
33
|
+
|
|
25
34
|
:host(:not([part~='overflow']):not([readonly]):not([disabled])) {
|
|
26
35
|
padding-inline-end: 0;
|
|
27
36
|
}
|
|
@@ -36,19 +45,19 @@ const chip = css`
|
|
|
36
45
|
:host([part~='overflow'])::after {
|
|
37
46
|
position: absolute;
|
|
38
47
|
content: '';
|
|
39
|
-
width:
|
|
40
|
-
height:
|
|
41
|
-
border-left:
|
|
42
|
-
border-radius:
|
|
48
|
+
width: 100%;
|
|
49
|
+
height: 100%;
|
|
50
|
+
border-left: calc(var(--lumo-space-s) / 4) solid;
|
|
51
|
+
border-radius: var(--lumo-border-radius-s);
|
|
43
52
|
border-color: var(--lumo-contrast-30pct);
|
|
44
53
|
}
|
|
45
54
|
|
|
46
55
|
:host([part~='overflow'])::before {
|
|
47
|
-
left: -
|
|
56
|
+
left: calc(-1 * var(--lumo-space-s) / 2);
|
|
48
57
|
}
|
|
49
58
|
|
|
50
59
|
:host([part~='overflow'])::after {
|
|
51
|
-
left: -
|
|
60
|
+
left: calc(-1 * var(--lumo-space-s));
|
|
52
61
|
}
|
|
53
62
|
|
|
54
63
|
:host([part~='overflow-two']) {
|
|
@@ -79,9 +88,11 @@ const chip = css`
|
|
|
79
88
|
justify-content: center;
|
|
80
89
|
margin-top: -0.3125em;
|
|
81
90
|
margin-bottom: -0.3125em;
|
|
91
|
+
margin-inline-start: auto;
|
|
82
92
|
width: 1.25em;
|
|
83
93
|
height: 1.25em;
|
|
84
94
|
font-size: 1.5em;
|
|
95
|
+
transition: none;
|
|
85
96
|
}
|
|
86
97
|
|
|
87
98
|
[part='remove-button']::before {
|
|
@@ -93,11 +104,6 @@ const chip = css`
|
|
|
93
104
|
-webkit-text-fill-color: var(--lumo-disabled-text-color);
|
|
94
105
|
pointer-events: none;
|
|
95
106
|
}
|
|
96
|
-
|
|
97
|
-
:host([readonly]) [part='remove-button'],
|
|
98
|
-
:host([disabled]) [part='remove-button'] {
|
|
99
|
-
display: none;
|
|
100
|
-
}
|
|
101
107
|
`;
|
|
102
108
|
|
|
103
109
|
registerStyles('vaadin-multi-select-combo-box-chip', [fieldButton, chip], {
|
|
@@ -30,14 +30,18 @@ const multiSelectComboBox = css`
|
|
|
30
30
|
padding-inline-start: 0;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
:host([
|
|
34
|
-
|
|
33
|
+
:host([has-value]) ::slotted(input:placeholder-shown) {
|
|
34
|
+
caret-color: var(--lumo-body-text-color) !important;
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
[part~='chip']:not(:last-of-type) {
|
|
38
38
|
margin-inline-end: var(--lumo-space-xs);
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
[part~='overflow']:not([hidden]) + :not(:empty) {
|
|
42
|
+
margin-inline-start: var(--lumo-space-xs);
|
|
43
|
+
}
|
|
44
|
+
|
|
41
45
|
[part='toggle-button']::before {
|
|
42
46
|
content: var(--lumo-icons-dropdown);
|
|
43
47
|
}
|
|
@@ -15,11 +15,15 @@ const chip = css`
|
|
|
15
15
|
margin-inline-end: 0.25rem;
|
|
16
16
|
padding: 0 0.5rem;
|
|
17
17
|
border-radius: 4px;
|
|
18
|
-
background-color:
|
|
18
|
+
background-color: rgba(0, 0, 0, 0.08);
|
|
19
19
|
cursor: default;
|
|
20
20
|
font-family: var(--material-font-family);
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
+
:host([focused]) {
|
|
24
|
+
background-color: rgba(0, 0, 0, 0.16);
|
|
25
|
+
}
|
|
26
|
+
|
|
23
27
|
:host(:not([part~='overflow']):not([readonly]):not([disabled])) {
|
|
24
28
|
padding-inline-end: 0;
|
|
25
29
|
}
|
|
@@ -33,19 +37,19 @@ const chip = css`
|
|
|
33
37
|
:host([part~='overflow'])::after {
|
|
34
38
|
position: absolute;
|
|
35
39
|
content: '';
|
|
36
|
-
width:
|
|
37
|
-
height:
|
|
38
|
-
border-left:
|
|
39
|
-
border-radius:
|
|
40
|
-
border-color:
|
|
40
|
+
width: 100%;
|
|
41
|
+
height: 100%;
|
|
42
|
+
border-left: 0.125rem solid;
|
|
43
|
+
border-radius: 0.25rem;
|
|
44
|
+
border-color: rgba(0, 0, 0, 0.08);
|
|
41
45
|
}
|
|
42
46
|
|
|
43
47
|
:host([part~='overflow'])::before {
|
|
44
|
-
left: -
|
|
48
|
+
left: -0.25rem;
|
|
45
49
|
}
|
|
46
50
|
|
|
47
51
|
:host([part~='overflow'])::after {
|
|
48
|
-
left: -
|
|
52
|
+
left: -0.5rem;
|
|
49
53
|
}
|
|
50
54
|
|
|
51
55
|
:host([part~='overflow-two']) {
|
|
@@ -79,6 +83,7 @@ const chip = css`
|
|
|
79
83
|
box-sizing: border-box;
|
|
80
84
|
width: 20px;
|
|
81
85
|
height: 20px;
|
|
86
|
+
margin-inline-start: auto;
|
|
82
87
|
line-height: 20px;
|
|
83
88
|
padding: 0;
|
|
84
89
|
font-size: 0.75em;
|
|
@@ -93,11 +98,6 @@ const chip = css`
|
|
|
93
98
|
-webkit-text-fill-color: var(--material-disabled-text-color);
|
|
94
99
|
pointer-events: none;
|
|
95
100
|
}
|
|
96
|
-
|
|
97
|
-
:host([readonly]) [part='remove-button'],
|
|
98
|
-
:host([disabled]) [part='remove-button'] {
|
|
99
|
-
display: none;
|
|
100
|
-
}
|
|
101
101
|
`;
|
|
102
102
|
|
|
103
103
|
registerStyles('vaadin-multi-select-combo-box-chip', [fieldButton, chip], {
|
|
@@ -25,8 +25,8 @@ registerStyles(
|
|
|
25
25
|
);
|
|
26
26
|
|
|
27
27
|
const multiSelectComboBox = css`
|
|
28
|
-
:host([
|
|
29
|
-
|
|
28
|
+
:host([has-value]) ::slotted(input:placeholder-shown) {
|
|
29
|
+
caret-color: var(--material-body-text-color) !important;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
[part='input-field'] {
|