@vaadin/multi-select-combo-box 23.1.0-alpha3 → 23.1.0-beta2

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": "23.1.0-alpha3",
3
+ "version": "23.1.0-beta2",
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-alpha3",
37
- "@vaadin/component-base": "23.1.0-alpha3",
38
- "@vaadin/field-base": "23.1.0-alpha3",
39
- "@vaadin/input-container": "23.1.0-alpha3",
40
- "@vaadin/vaadin-lumo-styles": "23.1.0-alpha3",
41
- "@vaadin/vaadin-material-styles": "23.1.0-alpha3",
42
- "@vaadin/vaadin-themable-mixin": "23.1.0-alpha3"
36
+ "@vaadin/combo-box": "23.1.0-beta2",
37
+ "@vaadin/component-base": "23.1.0-beta2",
38
+ "@vaadin/field-base": "23.1.0-beta2",
39
+ "@vaadin/input-container": "23.1.0-beta2",
40
+ "@vaadin/vaadin-lumo-styles": "23.1.0-beta2",
41
+ "@vaadin/vaadin-material-styles": "23.1.0-beta2",
42
+ "@vaadin/vaadin-themable-mixin": "23.1.0-beta2"
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": "8c9e64e8dfa158dd52a9bf6da351ff038c88ca85"
49
+ "gitHead": "f11f9245a0b5e6bf912725a501c27c24b74e7c8d"
50
50
  }
@@ -30,13 +30,23 @@ 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
- type: String
44
+ type: String,
35
45
  },
36
46
 
37
47
  item: {
38
- type: Object
39
- }
48
+ type: Object,
49
+ },
40
50
  };
41
51
  }
42
52
 
@@ -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>
@@ -73,11 +82,11 @@ class MultiSelectComboBoxChip extends ThemableMixin(PolymerElement) {
73
82
  this.dispatchEvent(
74
83
  new CustomEvent('item-removed', {
75
84
  detail: {
76
- item: this.item
85
+ item: this.item,
77
86
  },
78
87
  bubbles: true,
79
- composed: true
80
- })
88
+ composed: true,
89
+ }),
81
90
  );
82
91
  }
83
92
  }
@@ -9,15 +9,14 @@ 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
- .wrapper {
12
+ #wrapper {
13
13
  display: flex;
14
14
  width: 100%;
15
- min-width: 0;
16
15
  }
17
16
  `,
18
17
  {
19
- moduleId: 'vaadin-multi-select-combo-box-container-styles'
20
- }
18
+ moduleId: 'vaadin-multi-select-combo-box-container-styles',
19
+ },
21
20
  );
22
21
 
23
22
  let memoizedTemplate;
@@ -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('class', 'wrapper');
42
+ wrapper.setAttribute('id', 'wrapper');
44
43
  content.insertBefore(wrapper, slots[2]);
45
44
 
46
45
  wrapper.appendChild(slots[0]);
@@ -51,8 +51,8 @@ class MultiSelectComboBoxInternal extends ComboBoxDataProviderMixin(ComboBoxMixi
51
51
  static get properties() {
52
52
  return {
53
53
  _target: {
54
- type: Object
55
- }
54
+ type: Object,
55
+ },
56
56
  };
57
57
  }
58
58
 
@@ -65,6 +65,17 @@ class MultiSelectComboBoxInternal extends ComboBoxDataProviderMixin(ComboBoxMixi
65
65
  return this.querySelector('[part="clear-button"]');
66
66
  }
67
67
 
68
+ /**
69
+ * Override method inherited from the combo-box
70
+ * to allow opening dropdown when readonly.
71
+ * @override
72
+ */
73
+ open() {
74
+ if (!this.disabled && !(this.readonly && this._getOverlayItems().length === 0)) {
75
+ this.opened = true;
76
+ }
77
+ }
78
+
68
79
  /**
69
80
  * @protected
70
81
  * @override
@@ -113,6 +124,11 @@ class MultiSelectComboBoxInternal extends ComboBoxDataProviderMixin(ComboBoxMixi
113
124
  * @override
114
125
  */
115
126
  _closeOrCommit() {
127
+ if (this.readonly) {
128
+ this.close();
129
+ return;
130
+ }
131
+
116
132
  if (this.__enterPressed) {
117
133
  this.__enterPressed = null;
118
134
 
@@ -127,6 +143,73 @@ class MultiSelectComboBoxInternal extends ComboBoxDataProviderMixin(ComboBoxMixi
127
143
  super._closeOrCommit();
128
144
  }
129
145
 
146
+ /**
147
+ * Override method inherited from the combo-box
148
+ * to not update focused item when readonly.
149
+ * @protected
150
+ * @override
151
+ */
152
+ _onArrowDown() {
153
+ if (!this.readonly) {
154
+ super._onArrowDown();
155
+ } else if (!this.opened) {
156
+ this.open();
157
+ }
158
+ }
159
+
160
+ /**
161
+ * Override method inherited from the combo-box
162
+ * to not update focused item when readonly.
163
+ * @protected
164
+ * @override
165
+ */
166
+ _onArrowUp() {
167
+ if (!this.readonly) {
168
+ super._onArrowUp();
169
+ } else if (!this.opened) {
170
+ this.open();
171
+ }
172
+ }
173
+
174
+ /**
175
+ * Override method inherited from the combo-box
176
+ * to close dropdown on blur when readonly.
177
+ * @param {FocusEvent} event
178
+ * @protected
179
+ * @override
180
+ */
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
+
186
+ super._onFocusout(event);
187
+
188
+ if (this.readonly && !this._closeOnBlurIsPrevented) {
189
+ this.close();
190
+ }
191
+ }
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
+
130
213
  /**
131
214
  * @param {CustomEvent} event
132
215
  * @protected
@@ -135,6 +218,11 @@ class MultiSelectComboBoxInternal extends ComboBoxDataProviderMixin(ComboBoxMixi
135
218
  _overlaySelectedItemChanged(event) {
136
219
  event.stopPropagation();
137
220
 
221
+ // Do not un-select on click when readonly
222
+ if (this.readonly) {
223
+ return;
224
+ }
225
+
138
226
  if (event.detail.item instanceof ComboBoxPlaceholder) {
139
227
  return;
140
228
  }
@@ -143,9 +231,9 @@ class MultiSelectComboBoxInternal extends ComboBoxDataProviderMixin(ComboBoxMixi
143
231
  this.dispatchEvent(
144
232
  new CustomEvent('combo-box-item-selected', {
145
233
  detail: {
146
- item: event.detail.item
147
- }
148
- })
234
+ item: event.detail.item,
235
+ },
236
+ }),
149
237
  );
150
238
  }
151
239
  }
@@ -16,7 +16,7 @@ registerStyles(
16
16
  );
17
17
  }
18
18
  `,
19
- { moduleId: 'vaadin-multi-select-combo-box-overlay-styles' }
19
+ { moduleId: 'vaadin-multi-select-combo-box-overlay-styles' },
20
20
  );
21
21
 
22
22
  /**
@@ -17,15 +17,39 @@ 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) {
23
36
  return false;
24
37
  }
25
38
 
39
+ if (this.comboBox.readonly) {
40
+ return false;
41
+ }
42
+
26
43
  const host = this.comboBox.getRootNode().host;
27
44
  return host._findIndex(item, host.selectedItems, itemIdPath) > -1;
28
45
  }
46
+
47
+ /** @private */
48
+ __updateElement(el, index) {
49
+ super.__updateElement(el, index);
50
+
51
+ el.toggleAttribute('readonly', this.comboBox.readonly);
52
+ }
29
53
  }
30
54
 
31
55
  customElements.define(MultiSelectComboBoxScroller.is, MultiSelectComboBoxScroller);
@@ -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 MultiSelectComboBoxCustomValuesSetEvent = CustomEvent<string>;
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-values-set': MultiSelectComboBoxCustomValuesSetEvent;
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-values-set - Fired when the user sets a custom value.
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-values
149
+ * @attr {boolean} allow-custom-value
142
150
  */
143
- allowCustomValues: boolean;
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:
@@ -232,13 +271,13 @@ declare class MultiSelectComboBox<TItem = ComboBoxDefaultItem> extends HTMLEleme
232
271
  addEventListener<K extends keyof MultiSelectComboBoxEventMap<TItem>>(
233
272
  type: K,
234
273
  listener: (this: MultiSelectComboBox<TItem>, ev: MultiSelectComboBoxEventMap<TItem>[K]) => void,
235
- options?: boolean | AddEventListenerOptions
274
+ options?: boolean | AddEventListenerOptions,
236
275
  ): void;
237
276
 
238
277
  removeEventListener<K extends keyof MultiSelectComboBoxEventMap<TItem>>(
239
278
  type: K,
240
279
  listener: (this: MultiSelectComboBox<TItem>, ev: MultiSelectComboBoxEventMap<TItem>[K]) => void,
241
- options?: boolean | EventListenerOptions
280
+ options?: boolean | EventListenerOptions,
242
281
  ): void;
243
282
  }
244
283