@vaadin/multi-select-combo-box 24.6.0-alpha8 → 24.6.0-beta1

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.
Files changed (26) hide show
  1. package/package.json +16 -15
  2. package/src/vaadin-lit-multi-select-combo-box-chip.js +79 -0
  3. package/src/vaadin-lit-multi-select-combo-box-container.js +66 -0
  4. package/src/vaadin-lit-multi-select-combo-box-internal.js +56 -0
  5. package/src/vaadin-lit-multi-select-combo-box-item.js +50 -0
  6. package/src/vaadin-lit-multi-select-combo-box-overlay.js +64 -0
  7. package/src/vaadin-lit-multi-select-combo-box-scroller.js +96 -0
  8. package/src/vaadin-lit-multi-select-combo-box.d.ts +1 -0
  9. package/src/vaadin-lit-multi-select-combo-box.js +146 -0
  10. package/src/vaadin-multi-select-combo-box-chip.js +6 -27
  11. package/src/vaadin-multi-select-combo-box-internal-mixin.js +425 -0
  12. package/src/vaadin-multi-select-combo-box-internal.js +3 -399
  13. package/src/vaadin-multi-select-combo-box-mixin.d.ts +253 -0
  14. package/src/vaadin-multi-select-combo-box-mixin.js +1150 -0
  15. package/src/vaadin-multi-select-combo-box-styles.d.ts +10 -0
  16. package/src/vaadin-multi-select-combo-box-styles.js +73 -0
  17. package/src/vaadin-multi-select-combo-box.d.ts +5 -213
  18. package/src/vaadin-multi-select-combo-box.js +5 -1139
  19. package/theme/lumo/vaadin-lit-multi-select-combo-box.d.ts +3 -0
  20. package/theme/lumo/vaadin-lit-multi-select-combo-box.js +3 -0
  21. package/theme/material/vaadin-lit-multi-select-combo-box.d.ts +3 -0
  22. package/theme/material/vaadin-lit-multi-select-combo-box.js +3 -0
  23. package/vaadin-lit-multi-select-combo-box.d.ts +1 -0
  24. package/vaadin-lit-multi-select-combo-box.js +2 -0
  25. package/web-types.json +5 -5
  26. package/web-types.lit.json +8 -8
@@ -7,23 +7,20 @@ import './vaadin-multi-select-combo-box-item.js';
7
7
  import './vaadin-multi-select-combo-box-overlay.js';
8
8
  import './vaadin-multi-select-combo-box-scroller.js';
9
9
  import { html, PolymerElement } from '@polymer/polymer/polymer-element.js';
10
- import { ComboBoxDataProviderMixin } from '@vaadin/combo-box/src/vaadin-combo-box-data-provider-mixin.js';
11
- import { ComboBoxMixin } from '@vaadin/combo-box/src/vaadin-combo-box-mixin.js';
12
- import { ComboBoxPlaceholder } from '@vaadin/combo-box/src/vaadin-combo-box-placeholder.js';
13
10
  import { defineCustomElement } from '@vaadin/component-base/src/define.js';
14
11
  import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
12
+ import { MultiSelectComboBoxInternalMixin } from './vaadin-multi-select-combo-box-internal-mixin.js';
15
13
 
16
14
  /**
17
15
  * An element used internally by `<vaadin-multi-select-combo-box>`. Not intended to be used separately.
18
16
  *
19
17
  * @customElement
20
18
  * @extends HTMLElement
21
- * @mixes ComboBoxDataProviderMixin
22
- * @mixes ComboBoxMixin
19
+ * @mixes MultiSelectComboBoxInternalMixin
23
20
  * @mixes ThemableMixin
24
21
  * @private
25
22
  */
26
- class MultiSelectComboBoxInternal extends ComboBoxDataProviderMixin(ComboBoxMixin(ThemableMixin(PolymerElement))) {
23
+ class MultiSelectComboBoxInternal extends MultiSelectComboBoxInternalMixin(ThemableMixin(PolymerElement)) {
27
24
  static get is() {
28
25
  return 'vaadin-multi-select-combo-box-internal';
29
26
  }
@@ -49,399 +46,6 @@ class MultiSelectComboBoxInternal extends ComboBoxDataProviderMixin(ComboBoxMixi
49
46
  ></vaadin-multi-select-combo-box-overlay>
50
47
  `;
51
48
  }
52
-
53
- static get properties() {
54
- return {
55
- /**
56
- * A subset of items, filtered based on the user input.
57
- */
58
- filteredItems: {
59
- type: Array,
60
- notify: true,
61
- },
62
-
63
- /**
64
- * When true, filter string isn't cleared after selecting an item.
65
- */
66
- keepFilter: {
67
- type: Boolean,
68
- value: false,
69
- },
70
-
71
- /**
72
- * When set to `true`, "loading" attribute is set
73
- * on the host and the overlay element.
74
- * @type {boolean}
75
- */
76
- loading: {
77
- type: Boolean,
78
- notify: true,
79
- },
80
-
81
- /**
82
- * Total number of items.
83
- * @type {number | undefined}
84
- */
85
- size: {
86
- type: Number,
87
- notify: true,
88
- },
89
-
90
- /**
91
- * Selected items to render in the dropdown
92
- * when the component is read-only.
93
- */
94
- selectedItems: {
95
- type: Array,
96
- value: () => [],
97
- },
98
-
99
- /**
100
- * Set to true to group selected items at the top of the overlay.
101
- * @attr {boolean} selected-items-on-top
102
- */
103
- selectedItemsOnTop: {
104
- type: Boolean,
105
- value: false,
106
- },
107
-
108
- /**
109
- * Last input value entered by the user before value is updated.
110
- * Used to store `filter` property value before clearing it.
111
- */
112
- lastFilter: {
113
- type: String,
114
- notify: true,
115
- },
116
-
117
- /**
118
- * A subset of items to be shown at the top of the overlay.
119
- */
120
- topGroup: {
121
- type: Array,
122
- observer: '_topGroupChanged',
123
- },
124
-
125
- _target: {
126
- type: Object,
127
- },
128
- };
129
- }
130
-
131
- static get observers() {
132
- return ['_readonlyChanged(readonly)'];
133
- }
134
-
135
- /**
136
- * Reference to the clear button element.
137
- * @protected
138
- * @return {!HTMLElement}
139
- */
140
- get clearElement() {
141
- return this.querySelector('[part="clear-button"]');
142
- }
143
-
144
- /**
145
- * Tag name prefix used by scroller and items.
146
- * @protected
147
- * @return {string}
148
- */
149
- get _tagNamePrefix() {
150
- return 'vaadin-multi-select-combo-box';
151
- }
152
-
153
- /**
154
- * Override method inherited from the combo-box
155
- * to allow opening dropdown when readonly.
156
- * @override
157
- */
158
- open() {
159
- if (!this.disabled && !(this.readonly && this.selectedItems.length === 0)) {
160
- this.opened = true;
161
- }
162
- }
163
-
164
- /** @protected */
165
- ready() {
166
- super.ready();
167
-
168
- this._target = this;
169
- this._toggleElement = this.querySelector('.toggle-button');
170
- }
171
-
172
- /** @private */
173
- _readonlyChanged() {
174
- this._setDropdownItems(this.filteredItems);
175
- }
176
-
177
- /**
178
- * Override combo-box method to group selected
179
- * items at the top of the overlay.
180
- *
181
- * @protected
182
- * @override
183
- */
184
- _setDropdownItems(items) {
185
- if (this.readonly) {
186
- super._setDropdownItems(this.selectedItems);
187
- return;
188
- }
189
-
190
- if (this.filter || !this.selectedItemsOnTop) {
191
- super._setDropdownItems(items);
192
- return;
193
- }
194
-
195
- if (items && items.length && this.topGroup && this.topGroup.length) {
196
- // Filter out items included to the top group.
197
- const filteredItems = items.filter(
198
- (item) => this._comboBox._findIndex(item, this.topGroup, this.itemIdPath) === -1,
199
- );
200
-
201
- super._setDropdownItems(this.topGroup.concat(filteredItems));
202
- return;
203
- }
204
-
205
- super._setDropdownItems(items);
206
- }
207
-
208
- /** @private */
209
- _topGroupChanged(topGroup) {
210
- if (topGroup) {
211
- this._setDropdownItems(this.filteredItems);
212
- }
213
- }
214
-
215
- /**
216
- * Override combo-box method to set correct owner for using by item renderers.
217
- * This needs to be done before the scroller gets added to the DOM to ensure
218
- * Lit directive works in case when combo-box is opened using attribute.
219
- *
220
- * @protected
221
- * @override
222
- */
223
- _initScroller() {
224
- const comboBox = this.getRootNode().host;
225
-
226
- this._comboBox = comboBox;
227
-
228
- super._initScroller(comboBox);
229
- }
230
-
231
- /**
232
- * Override Enter handler to keep overlay open
233
- * when item is selected or unselected.
234
- * @param {!Event} event
235
- * @protected
236
- * @override
237
- */
238
- _onEnter(event) {
239
- if (this.opened) {
240
- // Do not submit the surrounding form.
241
- event.preventDefault();
242
- // Do not trigger global listeners.
243
- event.stopPropagation();
244
-
245
- if (this.readonly) {
246
- this.close();
247
- } else if (this._hasValidInputValue()) {
248
- // Keep selected item focused after committing on Enter.
249
- const focusedItem = this._dropdownItems[this._focusedIndex];
250
- this._commitValue();
251
- this._focusedIndex = this._dropdownItems.indexOf(focusedItem);
252
- }
253
-
254
- return;
255
- }
256
-
257
- super._onEnter(event);
258
- }
259
-
260
- /**
261
- * Override Escape handler to not clear
262
- * selected items when readonly.
263
- * @param {!Event} event
264
- * @protected
265
- * @override
266
- */
267
- _onEscape(event) {
268
- if (this.readonly) {
269
- event.stopPropagation();
270
- if (this.opened) {
271
- this.close();
272
- }
273
- return;
274
- }
275
-
276
- super._onEscape(event);
277
- }
278
-
279
- /**
280
- * Override from combo-box to ignore requests to clear the filter if the
281
- * keepFilter option is enabled. Exceptions are when the dropdown is closed,
282
- * so the filter is still cleared on cancel and focus out.
283
- * @protected
284
- * @override
285
- */
286
- _clearFilter() {
287
- if (!this.keepFilter || !this.opened) {
288
- super._clearFilter();
289
- }
290
- }
291
-
292
- /**
293
- * Override method from combo-box to always clear the filter when reverting
294
- * the input value, regardless of the keepFilter option.
295
- * @override
296
- * @protected
297
- */
298
- _revertInputValueToValue() {
299
- super._revertInputValueToValue();
300
- this.filter = '';
301
- }
302
-
303
- /**
304
- * @protected
305
- * @override
306
- */
307
- _commitValue() {
308
- // Store filter value for checking if user input is matching
309
- // an item which is already selected, to not un-select it.
310
- this.lastFilter = this.filter;
311
-
312
- super._commitValue();
313
- }
314
-
315
- /**
316
- * Override method inherited from the combo-box
317
- * to not update focused item when readonly.
318
- * @protected
319
- * @override
320
- */
321
- _onArrowDown() {
322
- if (!this.readonly) {
323
- super._onArrowDown();
324
- } else if (!this.opened) {
325
- this.open();
326
- }
327
- }
328
-
329
- /**
330
- * Override method inherited from the combo-box
331
- * to not update focused item when readonly.
332
- * @protected
333
- * @override
334
- */
335
- _onArrowUp() {
336
- if (!this.readonly) {
337
- super._onArrowUp();
338
- } else if (!this.opened) {
339
- this.open();
340
- }
341
- }
342
-
343
- /**
344
- * Override method inherited from the combo-box
345
- * to close dropdown on blur when readonly.
346
- * @param {boolean} focused
347
- * @protected
348
- * @override
349
- */
350
- _setFocused(focused) {
351
- // Disable combo-box logic that updates selectedItem
352
- // based on the overlay focused index on input blur
353
- if (!focused) {
354
- this._ignoreCommitValue = true;
355
- }
356
-
357
- super._setFocused(focused);
358
-
359
- if (!focused && this.readonly && !this._closeOnBlurIsPrevented) {
360
- this.close();
361
- }
362
- }
363
-
364
- /**
365
- * Override method inherited from the combo-box
366
- * to not commit an already selected item again
367
- * on blur, which would result in un-selecting.
368
- * @protected
369
- * @override
370
- */
371
- _detectAndDispatchChange() {
372
- if (this._ignoreCommitValue) {
373
- this._ignoreCommitValue = false;
374
-
375
- // Reset internal combo-box state
376
- this.selectedItem = null;
377
- this._inputElementValue = '';
378
- return;
379
- }
380
-
381
- super._detectAndDispatchChange();
382
- }
383
-
384
- /**
385
- * @param {CustomEvent} event
386
- * @protected
387
- * @override
388
- */
389
- _overlaySelectedItemChanged(event) {
390
- event.stopPropagation();
391
-
392
- // Do not un-select on click when readonly
393
- if (this.readonly) {
394
- return;
395
- }
396
-
397
- if (event.detail.item instanceof ComboBoxPlaceholder) {
398
- return;
399
- }
400
-
401
- if (this.opened) {
402
- // Store filter value for checking if user input is matching
403
- // an item which is already selected, to not un-select it.
404
- this.lastFilter = this.filter;
405
-
406
- this.dispatchEvent(
407
- new CustomEvent('combo-box-item-selected', {
408
- detail: {
409
- item: event.detail.item,
410
- },
411
- }),
412
- );
413
- }
414
- }
415
-
416
- /**
417
- * Override method inherited from the combo-box
418
- * to not request data provider when read-only.
419
- *
420
- * @protected
421
- * @override
422
- */
423
- _shouldFetchData() {
424
- if (this.readonly) {
425
- return false;
426
- }
427
-
428
- return super._shouldFetchData();
429
- }
430
-
431
- /**
432
- * Override method inherited from the combo-box
433
- * to not clear the data provider cache when read-only.
434
- *
435
- * @protected
436
- * @override
437
- */
438
- clearCache() {
439
- if (this.readonly) {
440
- return;
441
- }
442
-
443
- super.clearCache();
444
- }
445
49
  }
446
50
 
447
51
  defineCustomElement(MultiSelectComboBoxInternal);
@@ -0,0 +1,253 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2021 - 2024 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+ import type { Constructor } from '@open-wc/dedupe-mixin';
7
+ import type { DelegateFocusMixinClass } from '@vaadin/a11y-base/src/delegate-focus-mixin.js';
8
+ import type { DisabledMixinClass } from '@vaadin/a11y-base/src/disabled-mixin.js';
9
+ import type { FocusMixinClass } from '@vaadin/a11y-base/src/focus-mixin.js';
10
+ import type { KeyboardMixinClass } from '@vaadin/a11y-base/src/keyboard-mixin.js';
11
+ import type { ComboBoxDataProvider, ComboBoxItemModel } from '@vaadin/combo-box/src/vaadin-combo-box.js';
12
+ import type { ControllerMixinClass } from '@vaadin/component-base/src/controller-mixin.js';
13
+ import type { DelegateStateMixinClass } from '@vaadin/component-base/src/delegate-state-mixin.js';
14
+ import type { ResizeMixinClass } from '@vaadin/component-base/src/resize-mixin.js';
15
+ import type { SlotStylesMixinClass } from '@vaadin/component-base/src/slot-styles-mixin.js';
16
+ import type { ClearButtonMixinClass } from '@vaadin/field-base/src/clear-button-mixin.js';
17
+ import type { FieldMixinClass } from '@vaadin/field-base/src/field-mixin.js';
18
+ import type { InputConstraintsMixinClass } from '@vaadin/field-base/src/input-constraints-mixin.js';
19
+ import type { InputControlMixinClass } from '@vaadin/field-base/src/input-control-mixin.js';
20
+ import type { InputMixinClass } from '@vaadin/field-base/src/input-mixin.js';
21
+ import type { LabelMixinClass } from '@vaadin/field-base/src/label-mixin.js';
22
+ import type { ValidateMixinClass } from '@vaadin/field-base/src/validate-mixin.js';
23
+ import type { MultiSelectComboBox } from './vaadin-multi-select-combo-box.js';
24
+
25
+ export type MultiSelectComboBoxRenderer<TItem> = (
26
+ root: HTMLElement,
27
+ comboBox: MultiSelectComboBox<TItem>,
28
+ model: ComboBoxItemModel<TItem>,
29
+ ) => void;
30
+
31
+ export interface MultiSelectComboBoxI18n {
32
+ cleared: string;
33
+ focused: string;
34
+ selected: string;
35
+ deselected: string;
36
+ total: string;
37
+ }
38
+
39
+ export declare function MultiSelectComboBoxMixin<TItem, T extends Constructor<HTMLElement>>(
40
+ base: T,
41
+ ): Constructor<ClearButtonMixinClass> &
42
+ Constructor<ControllerMixinClass> &
43
+ Constructor<DelegateFocusMixinClass> &
44
+ Constructor<DelegateStateMixinClass> &
45
+ Constructor<DisabledMixinClass> &
46
+ Constructor<FieldMixinClass> &
47
+ Constructor<FocusMixinClass> &
48
+ Constructor<InputConstraintsMixinClass> &
49
+ Constructor<InputControlMixinClass> &
50
+ Constructor<InputMixinClass> &
51
+ Constructor<KeyboardMixinClass> &
52
+ Constructor<LabelMixinClass> &
53
+ Constructor<MultiSelectComboBoxMixinClass<TItem>> &
54
+ Constructor<ResizeMixinClass> &
55
+ Constructor<SlotStylesMixinClass> &
56
+ Constructor<ValidateMixinClass> &
57
+ T;
58
+
59
+ export declare class MultiSelectComboBoxMixinClass<TItem> {
60
+ /**
61
+ * Set to true to auto expand horizontally, causing input field to
62
+ * grow until max width is reached.
63
+ * @attr {boolean} auto-expand-horizontally
64
+ */
65
+ autoExpandHorizontally: boolean;
66
+
67
+ /**
68
+ * Set to true to not collapse selected items chips into the overflow
69
+ * chip and instead always expand vertically, causing input field to
70
+ * wrap into multiple lines when width is limited.
71
+ * @attr {boolean} auto-expand-vertically
72
+ */
73
+ autoExpandVertically: boolean;
74
+
75
+ /**
76
+ * When true, the user can input a value that is not present in the items list.
77
+ * @attr {boolean} allow-custom-value
78
+ */
79
+ allowCustomValue: boolean;
80
+
81
+ /**
82
+ * Set true to prevent the overlay from opening automatically.
83
+ * @attr {boolean} auto-open-disabled
84
+ */
85
+ autoOpenDisabled: boolean;
86
+
87
+ /**
88
+ * Function that provides items lazily. Receives two arguments:
89
+ *
90
+ * - `params` - Object with the following properties:
91
+ * - `params.page` Requested page index
92
+ * - `params.pageSize` Current page size
93
+ * - `params.filter` Currently applied filter
94
+ *
95
+ * - `callback(items, size)` - Callback function with arguments:
96
+ * - `items` Current page of items
97
+ * - `size` Total number of items.
98
+ */
99
+ dataProvider: ComboBoxDataProvider<TItem> | null | undefined;
100
+
101
+ /**
102
+ * A subset of items, filtered based on the user input. Filtered items
103
+ * can be assigned directly to omit the internal filtering functionality.
104
+ * The items can be of either `String` or `Object` type.
105
+ */
106
+ filteredItems: TItem[] | undefined;
107
+
108
+ /**
109
+ * Filtering string the user has typed into the input field.
110
+ */
111
+ filter: string;
112
+
113
+ /**
114
+ * A full set of items to filter the visible options from.
115
+ * The items can be of either `String` or `Object` type.
116
+ */
117
+ items: TItem[] | undefined;
118
+
119
+ /**
120
+ * A function used to generate CSS class names for dropdown
121
+ * items and selected chips based on the item. The return
122
+ * value should be the generated class name as a string, or
123
+ * multiple class names separated by whitespace characters.
124
+ */
125
+ itemClassNameGenerator: (item: TItem) => string;
126
+
127
+ /**
128
+ * The item property used for a visual representation of the item.
129
+ * @attr {string} item-label-path
130
+ */
131
+ itemLabelPath: string;
132
+
133
+ /**
134
+ * Path for the id of the item, used to detect whether the item is selected.
135
+ * @attr {string} item-id-path
136
+ */
137
+ itemIdPath: string;
138
+
139
+ /**
140
+ * Path for the value of the item. If `items` is an array of objects,
141
+ * this property is used as a string value for the selected item.
142
+ * @attr {string} item-value-path
143
+ */
144
+ itemValuePath: string;
145
+
146
+ /**
147
+ * The object used to localize this component.
148
+ * To change the default localization, replace the entire
149
+ * _i18n_ object or just the property you want to modify.
150
+ *
151
+ * The object has the following JSON structure and default values:
152
+ * ```
153
+ * {
154
+ * // Screen reader announcement on clear button click.
155
+ * cleared: 'Selection cleared',
156
+ * // Screen reader announcement when a chip is focused.
157
+ * focused: ' focused. Press Backspace to remove',
158
+ * // Screen reader announcement when item is selected.
159
+ * selected: 'added to selection',
160
+ * // Screen reader announcement when item is deselected.
161
+ * deselected: 'removed from selection',
162
+ * // Screen reader announcement of the selected items count.
163
+ * // {count} is replaced with the actual count of items.
164
+ * total: '{count} items selected',
165
+ * }
166
+ * ```
167
+ */
168
+ i18n: MultiSelectComboBoxI18n;
169
+
170
+ /**
171
+ * When true, filter string isn't cleared after selecting an item.
172
+ * @attr {boolean} keep-filter
173
+ */
174
+ keepFilter: boolean;
175
+
176
+ /**
177
+ * True when loading items from the data provider, false otherwise.
178
+ */
179
+ loading: boolean;
180
+
181
+ /**
182
+ * A space-delimited list of CSS class names to set on the overlay element.
183
+ *
184
+ * @attr {string} overlay-class
185
+ */
186
+ overlayClass: string;
187
+
188
+ /**
189
+ * True if the dropdown is open, false otherwise.
190
+ */
191
+ opened: boolean;
192
+
193
+ /**
194
+ * Number of items fetched at a time from the data provider.
195
+ * @attr {number} page-size
196
+ */
197
+ pageSize: number;
198
+
199
+ /**
200
+ * A hint to the user of what can be entered in the control.
201
+ * The placeholder will be only displayed in the case when
202
+ * there is no item selected.
203
+ */
204
+ placeholder: string;
205
+
206
+ /**
207
+ * Custom function for rendering the content of every item.
208
+ * Receives three arguments:
209
+ *
210
+ * - `root` The `<vaadin-multi-select-combo-box-item>` internal container DOM element.
211
+ * - `comboBox` The reference to the `<vaadin-multi-select-combo-box>` element.
212
+ * - `model` The object with the properties related with the rendered
213
+ * item, contains:
214
+ * - `model.index` The index of the rendered item.
215
+ * - `model.item` The item.
216
+ */
217
+ renderer: MultiSelectComboBoxRenderer<TItem> | null | undefined;
218
+
219
+ /**
220
+ * The list of selected items.
221
+ * Note: modifying the selected items creates a new array each time.
222
+ */
223
+ selectedItems: TItem[];
224
+
225
+ /**
226
+ * Set to true to group selected items at the top of the overlay.
227
+ * @attr {boolean} selected-items-on-top
228
+ */
229
+ selectedItemsOnTop: boolean;
230
+
231
+ /**
232
+ * Total number of items.
233
+ */
234
+ size: number | undefined;
235
+
236
+ /**
237
+ * Clears the cached pages and reloads data from data provider when needed.
238
+ */
239
+ clearCache(): void;
240
+
241
+ /**
242
+ * Clears the selected items.
243
+ */
244
+ clear(): void;
245
+
246
+ /**
247
+ * Requests an update for the content of items.
248
+ * While performing the update, it invokes the renderer (passed in the `renderer` property) once an item.
249
+ *
250
+ * It is not guaranteed that the update happens immediately (synchronously) after it is requested.
251
+ */
252
+ requestContentUpdate(): void;
253
+ }