@vaadin/multi-select-combo-box 24.3.0-alpha1 → 24.3.0-alpha10

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vaadin/multi-select-combo-box",
3
- "version": "24.3.0-alpha1",
3
+ "version": "24.3.0-alpha10",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -37,27 +37,27 @@
37
37
  ],
38
38
  "dependencies": {
39
39
  "@polymer/polymer": "^3.0.0",
40
- "@vaadin/a11y-base": "24.3.0-alpha1",
41
- "@vaadin/combo-box": "24.3.0-alpha1",
42
- "@vaadin/component-base": "24.3.0-alpha1",
43
- "@vaadin/field-base": "24.3.0-alpha1",
44
- "@vaadin/input-container": "24.3.0-alpha1",
45
- "@vaadin/item": "24.3.0-alpha1",
46
- "@vaadin/lit-renderer": "24.3.0-alpha1",
47
- "@vaadin/overlay": "24.3.0-alpha1",
48
- "@vaadin/vaadin-lumo-styles": "24.3.0-alpha1",
49
- "@vaadin/vaadin-material-styles": "24.3.0-alpha1",
50
- "@vaadin/vaadin-themable-mixin": "24.3.0-alpha1"
40
+ "@vaadin/a11y-base": "24.3.0-alpha10",
41
+ "@vaadin/combo-box": "24.3.0-alpha10",
42
+ "@vaadin/component-base": "24.3.0-alpha10",
43
+ "@vaadin/field-base": "24.3.0-alpha10",
44
+ "@vaadin/input-container": "24.3.0-alpha10",
45
+ "@vaadin/item": "24.3.0-alpha10",
46
+ "@vaadin/lit-renderer": "24.3.0-alpha10",
47
+ "@vaadin/overlay": "24.3.0-alpha10",
48
+ "@vaadin/vaadin-lumo-styles": "24.3.0-alpha10",
49
+ "@vaadin/vaadin-material-styles": "24.3.0-alpha10",
50
+ "@vaadin/vaadin-themable-mixin": "24.3.0-alpha10"
51
51
  },
52
52
  "devDependencies": {
53
53
  "@esm-bundle/chai": "^4.3.4",
54
- "@vaadin/testing-helpers": "^0.5.0",
55
- "lit": "^2.0.0",
54
+ "@vaadin/testing-helpers": "^0.6.0",
55
+ "lit": "^3.0.0",
56
56
  "sinon": "^13.0.2"
57
57
  },
58
58
  "web-types": [
59
59
  "web-types.json",
60
60
  "web-types.lit.json"
61
61
  ],
62
- "gitHead": "9ca6f3ca220a777e8eea181a1f5717e39a732240"
62
+ "gitHead": "0271523d93fe5df0425ff64206886614f3c6f401"
63
63
  }
@@ -14,6 +14,10 @@ registerStyles(
14
14
  display: flex;
15
15
  width: 100%;
16
16
  }
17
+
18
+ :host([auto-expand-vertically]) #wrapper {
19
+ flex-wrap: wrap;
20
+ }
17
21
  `,
18
22
  {
19
23
  moduleId: 'vaadin-multi-select-combo-box-container-styles',
@@ -49,6 +53,21 @@ class MultiSelectComboBoxContainer extends InputContainer {
49
53
  }
50
54
  return memoizedTemplate;
51
55
  }
56
+
57
+ static get properties() {
58
+ return {
59
+ /**
60
+ * Set to true to not collapse selected items chips into the overflow
61
+ * chip and instead always expand vertically, causing input field to
62
+ * wrap into multiple lines when width is limited.
63
+ * @attr {boolean} auto-expand-vertically
64
+ */
65
+ autoExpandVertically: {
66
+ type: Boolean,
67
+ reflectToAttribute: true,
68
+ },
69
+ };
70
+ }
52
71
  }
53
72
 
54
73
  defineCustomElement(MultiSelectComboBoxContainer);
@@ -88,6 +88,15 @@ class MultiSelectComboBoxInternal extends ComboBoxDataProviderMixin(ComboBoxMixi
88
88
  value: () => [],
89
89
  },
90
90
 
91
+ /**
92
+ * Set to true to group selected items at the top of the overlay.
93
+ * @attr {boolean} selected-items-on-top
94
+ */
95
+ selectedItemsOnTop: {
96
+ type: Boolean,
97
+ value: false,
98
+ },
99
+
91
100
  /**
92
101
  * Last input value entered by the user before value is updated.
93
102
  * Used to store `filter` property value before clearing it.
@@ -97,6 +106,14 @@ class MultiSelectComboBoxInternal extends ComboBoxDataProviderMixin(ComboBoxMixi
97
106
  notify: true,
98
107
  },
99
108
 
109
+ /**
110
+ * A subset of items to be shown at the top of the overlay.
111
+ */
112
+ topGroup: {
113
+ type: Array,
114
+ observer: '_topGroupChanged',
115
+ },
116
+
100
117
  _target: {
101
118
  type: Object,
102
119
  },
@@ -140,6 +157,39 @@ class MultiSelectComboBoxInternal extends ComboBoxDataProviderMixin(ComboBoxMixi
140
157
  this._toggleElement = this.querySelector('.toggle-button');
141
158
  }
142
159
 
160
+ /**
161
+ * Override combo-box method to group selected
162
+ * items at the top of the overlay.
163
+ *
164
+ * @protected
165
+ * @override
166
+ */
167
+ _setDropdownItems(items) {
168
+ if (this.filter || this.readonly || !this.selectedItemsOnTop) {
169
+ this._dropdownItems = items;
170
+ return;
171
+ }
172
+
173
+ if (items && items.length && this.topGroup && this.topGroup.length) {
174
+ // Filter out items included to the top group.
175
+ const filteredItems = items.filter(
176
+ (item) => !this.topGroup.some((selectedItem) => this._getItemValue(item) === this._getItemValue(selectedItem)),
177
+ );
178
+
179
+ this._dropdownItems = this.topGroup.concat(filteredItems);
180
+ return;
181
+ }
182
+
183
+ this._dropdownItems = items;
184
+ }
185
+
186
+ /** @private */
187
+ _topGroupChanged(topGroup) {
188
+ if (topGroup) {
189
+ this._setDropdownItems(this.filteredItems);
190
+ }
191
+ }
192
+
143
193
  /**
144
194
  * Override combo-box method to set correct owner for using by item renderers.
145
195
  * This needs to be done before the scroller gets added to the DOM to ensure
@@ -172,9 +222,9 @@ class MultiSelectComboBoxInternal extends ComboBoxDataProviderMixin(ComboBoxMixi
172
222
  this.close();
173
223
  } else {
174
224
  // Keep selected item focused after committing on Enter.
175
- const focusedItem = this.filteredItems[this._focusedIndex];
225
+ const focusedItem = this._dropdownItems[this._focusedIndex];
176
226
  this._commitValue();
177
- this._focusedIndex = this.filteredItems.indexOf(focusedItem);
227
+ this._focusedIndex = this._dropdownItems.indexOf(focusedItem);
178
228
  }
179
229
 
180
230
  return;
@@ -53,11 +53,6 @@ export type MultiSelectComboBoxChangeEvent<TItem> = Event & {
53
53
  */
54
54
  export type MultiSelectComboBoxCustomValueSetEvent = CustomEvent<string>;
55
55
 
56
- /**
57
- * Fired when the `dirty` property changes.
58
- */
59
- export type MultiSelectComboBoxDirtyChangedEvent = CustomEvent<{ value: boolean }>;
60
-
61
56
  /**
62
57
  * Fired when the `filter` property changes.
63
58
  */
@@ -88,8 +83,6 @@ export interface MultiSelectComboBoxEventMap<TItem> extends HTMLElementEventMap
88
83
 
89
84
  'custom-value-set': MultiSelectComboBoxCustomValueSetEvent;
90
85
 
91
- 'dirty-changed': MultiSelectComboBoxDirtyChangedEvent;
92
-
93
86
  'filter-changed': MultiSelectComboBoxFilterChangedEvent;
94
87
 
95
88
  'invalid-changed': MultiSelectComboBoxInvalidChangedEvent;
@@ -153,6 +146,7 @@ export interface MultiSelectComboBoxEventMap<TItem> extends HTMLElementEventMap
153
146
  * `--vaadin-field-default-width` | Default width of the field | `12em`
154
147
  * `--vaadin-multi-select-combo-box-overlay-width` | Width of the overlay | `auto`
155
148
  * `--vaadin-multi-select-combo-box-overlay-max-height` | Max height of the overlay | `65vh`
149
+ * `--vaadin-multi-select-combo-box-chip-min-width` | Min width of the chip | `50px`
156
150
  * `--vaadin-multi-select-combo-box-input-min-width` | Min width of the input | `4em`
157
151
  *
158
152
  * ### Internal components
@@ -171,7 +165,6 @@ export interface MultiSelectComboBoxEventMap<TItem> extends HTMLElementEventMap
171
165
  *
172
166
  * @fires {Event} change - Fired when the user commits a value change.
173
167
  * @fires {CustomEvent} custom-value-set - Fired when the user sets a custom value.
174
- * @fires {CustomEvent} dirty-changed - Fired when the `dirty` property changes.
175
168
  * @fires {CustomEvent} filter-changed - Fired when the `filter` property changes.
176
169
  * @fires {CustomEvent} invalid-changed - Fired when the `invalid` property changes.
177
170
  * @fires {CustomEvent} opened-changed - Fired when the `opened` property changes.
@@ -179,6 +172,21 @@ export interface MultiSelectComboBoxEventMap<TItem> extends HTMLElementEventMap
179
172
  * @fires {CustomEvent} validated - Fired whenever the field is validated.
180
173
  */
181
174
  declare class MultiSelectComboBox<TItem = ComboBoxDefaultItem> extends HTMLElement {
175
+ /**
176
+ * Set to true to auto expand horizontally, causing input field to
177
+ * grow until max width is reached.
178
+ * @attr {boolean} auto-expand-horizontally
179
+ */
180
+ autoExpandHorizontally: boolean;
181
+
182
+ /**
183
+ * Set to true to not collapse selected items chips into the overflow
184
+ * chip and instead always expand vertically, causing input field to
185
+ * wrap into multiple lines when width is limited.
186
+ * @attr {boolean} auto-expand-vertically
187
+ */
188
+ autoExpandVertically: boolean;
189
+
182
190
  /**
183
191
  * When true, the user can input a value that is not present in the items list.
184
192
  * @attr {boolean} allow-custom-value
@@ -315,6 +323,12 @@ declare class MultiSelectComboBox<TItem = ComboBoxDefaultItem> extends HTMLEleme
315
323
  */
316
324
  selectedItems: TItem[];
317
325
 
326
+ /**
327
+ * Set to true to group selected items at the top of the overlay.
328
+ * @attr {boolean} selected-items-on-top
329
+ */
330
+ selectedItemsOnTop: boolean;
331
+
318
332
  /**
319
333
  * Total number of items.
320
334
  */
@@ -23,6 +23,7 @@ import { css, registerStyles, ThemableMixin } from '@vaadin/vaadin-themable-mixi
23
23
  const multiSelectComboBox = css`
24
24
  :host {
25
25
  --input-min-width: var(--vaadin-multi-select-combo-box-input-min-width, 4em);
26
+ --_chip-min-width: var(--vaadin-multi-select-combo-box-chip-min-width, 50px);
26
27
  }
27
28
 
28
29
  #chips {
@@ -45,6 +46,14 @@ const multiSelectComboBox = css`
45
46
  flex-basis: 0;
46
47
  padding: 0;
47
48
  }
49
+
50
+ :host([auto-expand-vertically]) #chips {
51
+ display: contents;
52
+ }
53
+
54
+ :host([auto-expand-horizontally]) [class$='container'] {
55
+ width: auto;
56
+ }
48
57
  `;
49
58
 
50
59
  registerStyles('vaadin-multi-select-combo-box', [inputFieldShared, multiSelectComboBox], {
@@ -103,6 +112,7 @@ registerStyles('vaadin-multi-select-combo-box', [inputFieldShared, multiSelectCo
103
112
  * `--vaadin-field-default-width` | Default width of the field | `12em`
104
113
  * `--vaadin-multi-select-combo-box-overlay-width` | Width of the overlay | `auto`
105
114
  * `--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 | `50px`
106
116
  * `--vaadin-multi-select-combo-box-input-min-width` | Min width of the input | `4em`
107
117
  *
108
118
  * ### Internal components
@@ -121,7 +131,6 @@ registerStyles('vaadin-multi-select-combo-box', [inputFieldShared, multiSelectCo
121
131
  *
122
132
  * @fires {Event} change - Fired when the user commits a value change.
123
133
  * @fires {CustomEvent} custom-value-set - Fired when the user sets a custom value.
124
- * @fires {CustomEvent} dirty-changed - Fired when the `dirty` property changes.
125
134
  * @fires {CustomEvent} filter-changed - Fired when the `filter` property changes.
126
135
  * @fires {CustomEvent} invalid-changed - Fired when the `invalid` property changes.
127
136
  * @fires {CustomEvent} opened-changed - Fired when the `opened` property changes.
@@ -166,6 +175,8 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
166
175
  size="{{size}}"
167
176
  filtered-items="[[__effectiveFilteredItems]]"
168
177
  selected-items="[[selectedItems]]"
178
+ selected-items-on-top="[[selectedItemsOnTop]]"
179
+ top-group="[[_topGroup]]"
169
180
  opened="{{opened}}"
170
181
  renderer="[[renderer]]"
171
182
  theme$="[[_theme]]"
@@ -176,6 +187,7 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
176
187
  >
177
188
  <vaadin-multi-select-combo-box-container
178
189
  part="input-field"
190
+ auto-expand-vertically="[[autoExpandVertically]]"
179
191
  readonly="[[readonly]]"
180
192
  disabled="[[disabled]]"
181
193
  invalid="[[invalid]]"
@@ -212,6 +224,31 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
212
224
 
213
225
  static get properties() {
214
226
  return {
227
+ /**
228
+ * Set to true to auto expand horizontally, causing input field to
229
+ * grow until max width is reached.
230
+ * @attr {boolean} auto-expand-horizontally
231
+ */
232
+ autoExpandHorizontally: {
233
+ type: Boolean,
234
+ value: false,
235
+ reflectToAttribute: true,
236
+ observer: '_autoExpandHorizontallyChanged',
237
+ },
238
+
239
+ /**
240
+ * Set to true to not collapse selected items chips into the overflow
241
+ * chip and instead always expand vertically, causing input field to
242
+ * wrap into multiple lines when width is limited.
243
+ * @attr {boolean} auto-expand-vertically
244
+ */
245
+ autoExpandVertically: {
246
+ type: Boolean,
247
+ value: false,
248
+ reflectToAttribute: true,
249
+ observer: '_autoExpandVerticallyChanged',
250
+ },
251
+
215
252
  /**
216
253
  * Set true to prevent the overlay from opening automatically.
217
254
  * @attr {boolean} auto-open-disabled
@@ -431,6 +468,15 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
431
468
  */
432
469
  filteredItems: Array,
433
470
 
471
+ /**
472
+ * Set to true to group selected items at the top of the overlay.
473
+ * @attr {boolean} selected-items-on-top
474
+ */
475
+ selectedItemsOnTop: {
476
+ type: Boolean,
477
+ value: false,
478
+ },
479
+
434
480
  /** @private */
435
481
  value: {
436
482
  type: String,
@@ -465,6 +511,11 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
465
511
  _lastFilter: {
466
512
  type: String,
467
513
  },
514
+
515
+ /** @private */
516
+ _topGroup: {
517
+ type: Array,
518
+ },
468
519
  };
469
520
  }
470
521
 
@@ -472,6 +523,7 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
472
523
  return [
473
524
  '_selectedItemsChanged(selectedItems, selectedItems.*)',
474
525
  '__updateOverflowChip(_overflow, _overflowItems, disabled, readonly)',
526
+ '__updateTopGroup(selectedItemsOnTop, selectedItems, opened)',
475
527
  ];
476
528
  }
477
529
 
@@ -658,6 +710,20 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
658
710
  super._delegateAttribute(name, value);
659
711
  }
660
712
 
713
+ /** @private */
714
+ _autoExpandHorizontallyChanged(autoExpand, oldAutoExpand) {
715
+ if (autoExpand || oldAutoExpand) {
716
+ this.__updateChips();
717
+ }
718
+ }
719
+
720
+ /** @private */
721
+ _autoExpandVerticallyChanged(autoExpand, oldAutoExpand) {
722
+ if (autoExpand || oldAutoExpand) {
723
+ this.__updateChips();
724
+ }
725
+ }
726
+
661
727
  /**
662
728
  * Setting clear button visible reduces total space available
663
729
  * for rendering chips, and making it hidden increases it.
@@ -736,6 +802,10 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
736
802
 
737
803
  // Update selected for dropdown items
738
804
  this.requestContentUpdate();
805
+
806
+ if (this.opened) {
807
+ this.$.comboBox.$.overlay._updateOverlayWidth();
808
+ }
739
809
  }
740
810
 
741
811
  /** @private */
@@ -817,7 +887,6 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
817
887
 
818
888
  /** @private */
819
889
  __updateSelection(selectedItems) {
820
- this.dirty = true;
821
890
  this.selectedItems = selectedItems;
822
891
 
823
892
  this.validate();
@@ -825,6 +894,15 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
825
894
  this.dispatchEvent(new CustomEvent('change', { bubbles: true }));
826
895
  }
827
896
 
897
+ /** @private */
898
+ __updateTopGroup(selectedItemsOnTop, selectedItems, opened) {
899
+ if (!selectedItemsOnTop) {
900
+ this._topGroup = [];
901
+ } else if (!opened) {
902
+ this._topGroup = [...selectedItems];
903
+ }
904
+ }
905
+
828
906
  /** @private */
829
907
  __createChip(item) {
830
908
  const chip = document.createElement('vaadin-multi-select-combo-box-chip');
@@ -889,14 +967,60 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
889
967
  remainingWidth -= this.__getOverflowWidth();
890
968
  }
891
969
 
970
+ const chipMinWidth = parseInt(getComputedStyle(this).getPropertyValue('--_chip-min-width'));
971
+
972
+ if (this.autoExpandHorizontally) {
973
+ const chips = [];
974
+
975
+ // First, add all chips to make the field fully expand
976
+ for (let i = items.length - 1, refNode = null; i >= 0; i--) {
977
+ const chip = this.__createChip(items[i]);
978
+ this.insertBefore(chip, refNode);
979
+ refNode = chip;
980
+ chips.unshift(chip);
981
+ }
982
+
983
+ const overflowItems = [];
984
+ const availableWidth = this._inputField.$.wrapper.clientWidth - this.$.chips.clientWidth;
985
+
986
+ // When auto expanding vertically, no need to measure width
987
+ if (!this.autoExpandVertically && availableWidth < inputWidth) {
988
+ // Always show at least last item as a chip
989
+ while (chips.length > 1) {
990
+ const lastChip = chips.pop();
991
+ lastChip.remove();
992
+ overflowItems.unshift(items.pop());
993
+
994
+ // Remove chips until there is enough width for the input element to fit
995
+ const neededWidth = overflowItems.length > 0 ? inputWidth + this.__getOverflowWidth() : inputWidth;
996
+ if (this._inputField.$.wrapper.clientWidth - this.$.chips.clientWidth >= neededWidth) {
997
+ break;
998
+ }
999
+ }
1000
+
1001
+ if (chips.length === 1) {
1002
+ chips[0].style.maxWidth = `${Math.max(chipMinWidth, remainingWidth)}px`;
1003
+ }
1004
+ }
1005
+
1006
+ this._overflowItems = overflowItems;
1007
+ return;
1008
+ }
1009
+
892
1010
  // Add chips until remaining width is exceeded
893
1011
  for (let i = items.length - 1, refNode = null; i >= 0; i--) {
894
1012
  const chip = this.__createChip(items[i]);
895
1013
  this.insertBefore(chip, refNode);
896
1014
 
897
- if (this.$.chips.clientWidth > remainingWidth) {
898
- chip.remove();
899
- break;
1015
+ // When auto expanding vertically, no need to measure remaining width
1016
+ if (!this.autoExpandVertically && this.$.chips.clientWidth > remainingWidth) {
1017
+ // Always show at least last selected item as a chip
1018
+ if (refNode === null) {
1019
+ chip.style.maxWidth = `${Math.max(chipMinWidth, remainingWidth)}px`;
1020
+ } else {
1021
+ chip.remove();
1022
+ break;
1023
+ }
900
1024
  }
901
1025
 
902
1026
  items.pop();
@@ -3,6 +3,7 @@
3
3
  * Copyright (c) 2021 - 2023 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
+ import '@vaadin/input-container/theme/lumo/vaadin-input-container-styles.js';
6
7
  import '@vaadin/vaadin-lumo-styles/color.js';
7
8
  import '@vaadin/vaadin-lumo-styles/font-icons.js';
8
9
  import '@vaadin/vaadin-lumo-styles/style.js';
@@ -47,6 +48,16 @@ registerStyles(
47
48
  { moduleId: 'lumo-multi-select-combo-box-overlay' },
48
49
  );
49
50
 
51
+ registerStyles(
52
+ 'vaadin-multi-select-combo-box-container',
53
+ css`
54
+ :host([auto-expand-vertically]) {
55
+ padding-block: var(--lumo-space-xs);
56
+ }
57
+ `,
58
+ { moduleId: 'lumo-multi-select-combo-box-container' },
59
+ );
60
+
50
61
  const multiSelectComboBox = css`
51
62
  :host([has-value]) {
52
63
  padding-inline-start: 0;
@@ -56,6 +67,10 @@ const multiSelectComboBox = css`
56
67
  caret-color: var(--lumo-body-text-color) !important;
57
68
  }
58
69
 
70
+ [part='label'] {
71
+ flex-shrink: 0;
72
+ }
73
+
59
74
  /* Override input-container styles */
60
75
  ::slotted([slot='chip']),
61
76
  ::slotted([slot='overflow']) {
@@ -66,17 +81,25 @@ const multiSelectComboBox = css`
66
81
  mask-image: none;
67
82
  }
68
83
 
84
+ :host([auto-expand-vertically]) ::slotted([slot='chip']) {
85
+ margin-block: calc(var(--lumo-space-xs) / 2);
86
+ }
87
+
69
88
  ::slotted([slot='chip']:not([readonly]):not([disabled])) {
70
89
  padding-inline-end: 0;
71
90
  }
72
91
 
92
+ :host([auto-expand-vertically]) ::slotted([slot='input']) {
93
+ min-height: calc(var(--lumo-text-field-size, var(--lumo-size-m)) - 2 * var(--lumo-space-xs));
94
+ }
95
+
73
96
  ::slotted([slot='chip']:not(:last-of-type)),
74
97
  ::slotted([slot='overflow']:not(:last-of-type)) {
75
98
  margin-inline-end: var(--lumo-space-xs);
76
99
  }
77
100
 
78
101
  ::slotted([slot='chip'][focused]) {
79
- background-color: var(--lumo-primary-color);
102
+ background-color: var(--vaadin-selection-color, var(--lumo-primary-color));
80
103
  color: var(--lumo-primary-contrast-color);
81
104
  }
82
105
 
@@ -3,7 +3,6 @@
3
3
  * Copyright (c) 2021 - 2023 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
- import '@vaadin/input-container/theme/lumo/vaadin-input-container.js';
7
6
  import '@vaadin/overlay/theme/lumo/vaadin-overlay.js';
8
7
  import './vaadin-multi-select-combo-box-chip-styles.js';
9
8
  import './vaadin-multi-select-combo-box-styles.js';
@@ -3,6 +3,7 @@
3
3
  * Copyright (c) 2021 - 2023 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
+ import '@vaadin/input-container/theme/material/vaadin-input-container-styles.js';
6
7
  import '@vaadin/vaadin-material-styles/color.js';
7
8
  import '@vaadin/vaadin-material-styles/font-icons.js';
8
9
  import '@vaadin/vaadin-material-styles/typography.js';
@@ -55,6 +56,11 @@ const multiSelectComboBox = css`
55
56
  padding: 0 0.5rem;
56
57
  }
57
58
 
59
+ :host([auto-expand-vertically]) ::slotted([slot='chip']) {
60
+ margin-top: 0.25rem;
61
+ align-self: flex-start;
62
+ }
63
+
58
64
  ::slotted([slot='chip']:not([readonly]):not([disabled])) {
59
65
  padding-inline-end: 0;
60
66
  }
@@ -3,7 +3,6 @@
3
3
  * Copyright (c) 2021 - 2023 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
- import '@vaadin/input-container/theme/material/vaadin-input-container.js';
7
6
  import '@vaadin/overlay/theme/material/vaadin-overlay.js';
8
7
  import './vaadin-multi-select-combo-box-chip-styles.js';
9
8
  import './vaadin-multi-select-combo-box-styles.js';
package/web-types.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/web-types",
3
3
  "name": "@vaadin/multi-select-combo-box",
4
- "version": "24.3.0-alpha1",
4
+ "version": "24.3.0-alpha10",
5
5
  "description-markup": "markdown",
6
6
  "contributions": {
7
7
  "html": {
8
8
  "elements": [
9
9
  {
10
10
  "name": "vaadin-multi-select-combo-box",
11
- "description": "`<vaadin-multi-select-combo-box>` is a web component that wraps `<vaadin-combo-box>` and extends\nits functionality to allow selecting multiple items, in addition to basic features.\n\n```html\n<vaadin-multi-select-combo-box id=\"comboBox\"></vaadin-multi-select-combo-box>\n```\n```js\nconst comboBox = document.querySelector('#comboBox');\ncomboBox.items = ['apple', 'banana', 'lemon', 'orange'];\ncomboBox.selectedItems = ['lemon', 'orange'];\n```\n\n### Styling\n\nThe following shadow DOM parts are available for styling:\n\nPart name | Description\n-----------------------|----------------\n`chips` | The element that wraps slotted chips for selected items\n`label` | The label element\n`input-field` | The element that wraps prefix, value and suffix\n`clear-button` | The clear button\n`error-message` | The error message element\n`helper-text` | The helper text element wrapper\n`required-indicator` | The `required` state indicator element\n`toggle-button` | The toggle button\n\nThe following state attributes are available for styling:\n\nAttribute | Description\n-----------------------|-----------------\n`disabled` | Set to a disabled element\n`has-value` | Set when the element has a value\n`has-label` | Set when the element has a label\n`has-helper` | Set when the element has helper text or slot\n`has-error-message` | Set when the element has an error message\n`invalid` | Set when the element is invalid\n`focused` | Set when the element is focused\n`focus-ring` | Set when the element is keyboard focused\n`loading` | Set when loading items from the data provider\n`opened` | Set when the dropdown is open\n`readonly` | Set to a readonly element\n\nThe following custom CSS properties are available for styling:\n\nCustom property | Description | Default\n-----------------------------------------------------|----------------------------|--------\n`--vaadin-field-default-width` | Default width of the field | `12em`\n`--vaadin-multi-select-combo-box-overlay-width` | Width of the overlay | `auto`\n`--vaadin-multi-select-combo-box-overlay-max-height` | Max height of the overlay | `65vh`\n`--vaadin-multi-select-combo-box-input-min-width` | Min width of the input | `4em`\n\n### Internal components\n\nIn addition to `<vaadin-multi-select-combo-box>` itself, the following internal\ncomponents are themable:\n\n- `<vaadin-multi-select-combo-box-overlay>` - has the same API as `<vaadin-overlay>`.\n- `<vaadin-multi-select-combo-box-item>` - has the same API as `<vaadin-item>`.\n- `<vaadin-multi-select-combo-box-container>` - has the same API as `<vaadin-input-container>`.\n\nNote: the `theme` attribute value set on `<vaadin-multi-select-combo-box>` is\npropagated to these components.\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.",
11
+ "description": "`<vaadin-multi-select-combo-box>` is a web component that wraps `<vaadin-combo-box>` and extends\nits functionality to allow selecting multiple items, in addition to basic features.\n\n```html\n<vaadin-multi-select-combo-box id=\"comboBox\"></vaadin-multi-select-combo-box>\n```\n```js\nconst comboBox = document.querySelector('#comboBox');\ncomboBox.items = ['apple', 'banana', 'lemon', 'orange'];\ncomboBox.selectedItems = ['lemon', 'orange'];\n```\n\n### Styling\n\nThe following shadow DOM parts are available for styling:\n\nPart name | Description\n-----------------------|----------------\n`chips` | The element that wraps slotted chips for selected items\n`label` | The label element\n`input-field` | The element that wraps prefix, value and suffix\n`clear-button` | The clear button\n`error-message` | The error message element\n`helper-text` | The helper text element wrapper\n`required-indicator` | The `required` state indicator element\n`toggle-button` | The toggle button\n\nThe following state attributes are available for styling:\n\nAttribute | Description\n-----------------------|-----------------\n`disabled` | Set to a disabled element\n`has-value` | Set when the element has a value\n`has-label` | Set when the element has a label\n`has-helper` | Set when the element has helper text or slot\n`has-error-message` | Set when the element has an error message\n`invalid` | Set when the element is invalid\n`focused` | Set when the element is focused\n`focus-ring` | Set when the element is keyboard focused\n`loading` | Set when loading items from the data provider\n`opened` | Set when the dropdown is open\n`readonly` | Set to a readonly element\n\nThe following custom CSS properties are available for styling:\n\nCustom property | Description | Default\n-----------------------------------------------------|----------------------------|--------\n`--vaadin-field-default-width` | Default width of the field | `12em`\n`--vaadin-multi-select-combo-box-overlay-width` | Width of the overlay | `auto`\n`--vaadin-multi-select-combo-box-overlay-max-height` | Max height of the overlay | `65vh`\n`--vaadin-multi-select-combo-box-chip-min-width` | Min width of the chip | `50px`\n`--vaadin-multi-select-combo-box-input-min-width` | Min width of the input | `4em`\n\n### Internal components\n\nIn addition to `<vaadin-multi-select-combo-box>` itself, the following internal\ncomponents are themable:\n\n- `<vaadin-multi-select-combo-box-overlay>` - has the same API as `<vaadin-overlay>`.\n- `<vaadin-multi-select-combo-box-item>` - has the same API as `<vaadin-item>`.\n- `<vaadin-multi-select-combo-box-container>` - has the same API as `<vaadin-input-container>`.\n\nNote: the `theme` attribute value set on `<vaadin-multi-select-combo-box>` is\npropagated to these components.\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.",
12
12
  "attributes": [
13
13
  {
14
14
  "name": "disabled",
@@ -120,17 +120,6 @@
120
120
  ]
121
121
  }
122
122
  },
123
- {
124
- "name": "dirty",
125
- "description": "Whether the field is dirty.\n\nThe field is automatically marked as dirty once the user triggers\nan `input` or `change` event. Additionally, the field can be manually\nmarked as dirty by setting the property to `true`.",
126
- "value": {
127
- "type": [
128
- "boolean",
129
- "null",
130
- "undefined"
131
- ]
132
- }
133
- },
134
123
  {
135
124
  "name": "clear-button-visible",
136
125
  "description": "Set to true to display the clear icon which clears the input.",
@@ -208,6 +197,28 @@
208
197
  ]
209
198
  }
210
199
  },
200
+ {
201
+ "name": "auto-expand-horizontally",
202
+ "description": "Set to true to auto expand horizontally, causing input field to\ngrow until max width is reached.",
203
+ "value": {
204
+ "type": [
205
+ "boolean",
206
+ "null",
207
+ "undefined"
208
+ ]
209
+ }
210
+ },
211
+ {
212
+ "name": "auto-expand-vertically",
213
+ "description": "Set to true to not collapse selected items chips into the overflow\nchip and instead always expand vertically, causing input field to\nwrap into multiple lines when width is limited.",
214
+ "value": {
215
+ "type": [
216
+ "boolean",
217
+ "null",
218
+ "undefined"
219
+ ]
220
+ }
221
+ },
211
222
  {
212
223
  "name": "auto-open-disabled",
213
224
  "description": "Set true to prevent the overlay from opening automatically.",
@@ -329,6 +340,17 @@
329
340
  ]
330
341
  }
331
342
  },
343
+ {
344
+ "name": "selected-items-on-top",
345
+ "description": "Set to true to group selected items at the top of the overlay.",
346
+ "value": {
347
+ "type": [
348
+ "boolean",
349
+ "null",
350
+ "undefined"
351
+ ]
352
+ }
353
+ },
332
354
  {
333
355
  "name": "theme",
334
356
  "description": "The theme variants to apply to the component.",
@@ -442,17 +464,6 @@
442
464
  ]
443
465
  }
444
466
  },
445
- {
446
- "name": "dirty",
447
- "description": "Whether the field is dirty.\n\nThe field is automatically marked as dirty once the user triggers\nan `input` or `change` event. Additionally, the field can be manually\nmarked as dirty by setting the property to `true`.",
448
- "value": {
449
- "type": [
450
- "boolean",
451
- "null",
452
- "undefined"
453
- ]
454
- }
455
- },
456
467
  {
457
468
  "name": "clearButtonVisible",
458
469
  "description": "Set to true to display the clear icon which clears the input.",
@@ -530,6 +541,28 @@
530
541
  ]
531
542
  }
532
543
  },
544
+ {
545
+ "name": "autoExpandHorizontally",
546
+ "description": "Set to true to auto expand horizontally, causing input field to\ngrow until max width is reached.",
547
+ "value": {
548
+ "type": [
549
+ "boolean",
550
+ "null",
551
+ "undefined"
552
+ ]
553
+ }
554
+ },
555
+ {
556
+ "name": "autoExpandVertically",
557
+ "description": "Set to true to not collapse selected items chips into the overflow\nchip and instead always expand vertically, causing input field to\nwrap into multiple lines when width is limited.",
558
+ "value": {
559
+ "type": [
560
+ "boolean",
561
+ "null",
562
+ "undefined"
563
+ ]
564
+ }
565
+ },
533
566
  {
534
567
  "name": "autoOpenDisabled",
535
568
  "description": "Set true to prevent the overlay from opening automatically.",
@@ -714,6 +747,17 @@
714
747
  "undefined"
715
748
  ]
716
749
  }
750
+ },
751
+ {
752
+ "name": "selectedItemsOnTop",
753
+ "description": "Set to true to group selected items at the top of the overlay.",
754
+ "value": {
755
+ "type": [
756
+ "boolean",
757
+ "null",
758
+ "undefined"
759
+ ]
760
+ }
717
761
  }
718
762
  ],
719
763
  "events": [
@@ -744,10 +788,6 @@
744
788
  {
745
789
  "name": "invalid-changed",
746
790
  "description": "Fired when the `invalid` property changes."
747
- },
748
- {
749
- "name": "dirty-changed",
750
- "description": "Fired when the `dirty` property changes."
751
791
  }
752
792
  ]
753
793
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/web-types",
3
3
  "name": "@vaadin/multi-select-combo-box",
4
- "version": "24.3.0-alpha1",
4
+ "version": "24.3.0-alpha10",
5
5
  "description-markup": "markdown",
6
6
  "framework": "lit",
7
7
  "framework-config": {
@@ -16,7 +16,7 @@
16
16
  "elements": [
17
17
  {
18
18
  "name": "vaadin-multi-select-combo-box",
19
- "description": "`<vaadin-multi-select-combo-box>` is a web component that wraps `<vaadin-combo-box>` and extends\nits functionality to allow selecting multiple items, in addition to basic features.\n\n```html\n<vaadin-multi-select-combo-box id=\"comboBox\"></vaadin-multi-select-combo-box>\n```\n```js\nconst comboBox = document.querySelector('#comboBox');\ncomboBox.items = ['apple', 'banana', 'lemon', 'orange'];\ncomboBox.selectedItems = ['lemon', 'orange'];\n```\n\n### Styling\n\nThe following shadow DOM parts are available for styling:\n\nPart name | Description\n-----------------------|----------------\n`chips` | The element that wraps slotted chips for selected items\n`label` | The label element\n`input-field` | The element that wraps prefix, value and suffix\n`clear-button` | The clear button\n`error-message` | The error message element\n`helper-text` | The helper text element wrapper\n`required-indicator` | The `required` state indicator element\n`toggle-button` | The toggle button\n\nThe following state attributes are available for styling:\n\nAttribute | Description\n-----------------------|-----------------\n`disabled` | Set to a disabled element\n`has-value` | Set when the element has a value\n`has-label` | Set when the element has a label\n`has-helper` | Set when the element has helper text or slot\n`has-error-message` | Set when the element has an error message\n`invalid` | Set when the element is invalid\n`focused` | Set when the element is focused\n`focus-ring` | Set when the element is keyboard focused\n`loading` | Set when loading items from the data provider\n`opened` | Set when the dropdown is open\n`readonly` | Set to a readonly element\n\nThe following custom CSS properties are available for styling:\n\nCustom property | Description | Default\n-----------------------------------------------------|----------------------------|--------\n`--vaadin-field-default-width` | Default width of the field | `12em`\n`--vaadin-multi-select-combo-box-overlay-width` | Width of the overlay | `auto`\n`--vaadin-multi-select-combo-box-overlay-max-height` | Max height of the overlay | `65vh`\n`--vaadin-multi-select-combo-box-input-min-width` | Min width of the input | `4em`\n\n### Internal components\n\nIn addition to `<vaadin-multi-select-combo-box>` itself, the following internal\ncomponents are themable:\n\n- `<vaadin-multi-select-combo-box-overlay>` - has the same API as `<vaadin-overlay>`.\n- `<vaadin-multi-select-combo-box-item>` - has the same API as `<vaadin-item>`.\n- `<vaadin-multi-select-combo-box-container>` - has the same API as `<vaadin-input-container>`.\n\nNote: the `theme` attribute value set on `<vaadin-multi-select-combo-box>` is\npropagated to these components.\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.",
19
+ "description": "`<vaadin-multi-select-combo-box>` is a web component that wraps `<vaadin-combo-box>` and extends\nits functionality to allow selecting multiple items, in addition to basic features.\n\n```html\n<vaadin-multi-select-combo-box id=\"comboBox\"></vaadin-multi-select-combo-box>\n```\n```js\nconst comboBox = document.querySelector('#comboBox');\ncomboBox.items = ['apple', 'banana', 'lemon', 'orange'];\ncomboBox.selectedItems = ['lemon', 'orange'];\n```\n\n### Styling\n\nThe following shadow DOM parts are available for styling:\n\nPart name | Description\n-----------------------|----------------\n`chips` | The element that wraps slotted chips for selected items\n`label` | The label element\n`input-field` | The element that wraps prefix, value and suffix\n`clear-button` | The clear button\n`error-message` | The error message element\n`helper-text` | The helper text element wrapper\n`required-indicator` | The `required` state indicator element\n`toggle-button` | The toggle button\n\nThe following state attributes are available for styling:\n\nAttribute | Description\n-----------------------|-----------------\n`disabled` | Set to a disabled element\n`has-value` | Set when the element has a value\n`has-label` | Set when the element has a label\n`has-helper` | Set when the element has helper text or slot\n`has-error-message` | Set when the element has an error message\n`invalid` | Set when the element is invalid\n`focused` | Set when the element is focused\n`focus-ring` | Set when the element is keyboard focused\n`loading` | Set when loading items from the data provider\n`opened` | Set when the dropdown is open\n`readonly` | Set to a readonly element\n\nThe following custom CSS properties are available for styling:\n\nCustom property | Description | Default\n-----------------------------------------------------|----------------------------|--------\n`--vaadin-field-default-width` | Default width of the field | `12em`\n`--vaadin-multi-select-combo-box-overlay-width` | Width of the overlay | `auto`\n`--vaadin-multi-select-combo-box-overlay-max-height` | Max height of the overlay | `65vh`\n`--vaadin-multi-select-combo-box-chip-min-width` | Min width of the chip | `50px`\n`--vaadin-multi-select-combo-box-input-min-width` | Min width of the input | `4em`\n\n### Internal components\n\nIn addition to `<vaadin-multi-select-combo-box>` itself, the following internal\ncomponents are themable:\n\n- `<vaadin-multi-select-combo-box-overlay>` - has the same API as `<vaadin-overlay>`.\n- `<vaadin-multi-select-combo-box-item>` - has the same API as `<vaadin-item>`.\n- `<vaadin-multi-select-combo-box-container>` - has the same API as `<vaadin-input-container>`.\n\nNote: the `theme` attribute value set on `<vaadin-multi-select-combo-box>` is\npropagated to these components.\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.",
20
20
  "extension": true,
21
21
  "attributes": [
22
22
  {
@@ -47,13 +47,6 @@
47
47
  "kind": "expression"
48
48
  }
49
49
  },
50
- {
51
- "name": "?dirty",
52
- "description": "Whether the field is dirty.\n\nThe field is automatically marked as dirty once the user triggers\nan `input` or `change` event. Additionally, the field can be manually\nmarked as dirty by setting the property to `true`.",
53
- "value": {
54
- "kind": "expression"
55
- }
56
- },
57
50
  {
58
51
  "name": "?clearButtonVisible",
59
52
  "description": "Set to true to display the clear icon which clears the input.",
@@ -75,6 +68,20 @@
75
68
  "kind": "expression"
76
69
  }
77
70
  },
71
+ {
72
+ "name": "?autoExpandHorizontally",
73
+ "description": "Set to true to auto expand horizontally, causing input field to\ngrow until max width is reached.",
74
+ "value": {
75
+ "kind": "expression"
76
+ }
77
+ },
78
+ {
79
+ "name": "?autoExpandVertically",
80
+ "description": "Set to true to not collapse selected items chips into the overflow\nchip and instead always expand vertically, causing input field to\nwrap into multiple lines when width is limited.",
81
+ "value": {
82
+ "kind": "expression"
83
+ }
84
+ },
78
85
  {
79
86
  "name": "?autoOpenDisabled",
80
87
  "description": "Set true to prevent the overlay from opening automatically.",
@@ -103,6 +110,13 @@
103
110
  "kind": "expression"
104
111
  }
105
112
  },
113
+ {
114
+ "name": "?selectedItemsOnTop",
115
+ "description": "Set to true to group selected items at the top of the overlay.",
116
+ "value": {
117
+ "kind": "expression"
118
+ }
119
+ },
106
120
  {
107
121
  "name": ".label",
108
122
  "description": "The label text for the input node.\nWhen no light dom defined via [slot=label], this value will be used.",
@@ -305,13 +319,6 @@
305
319
  "value": {
306
320
  "kind": "expression"
307
321
  }
308
- },
309
- {
310
- "name": "@dirty-changed",
311
- "description": "Fired when the `dirty` property changes.",
312
- "value": {
313
- "kind": "expression"
314
- }
315
322
  }
316
323
  ]
317
324
  }