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

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-alpha4",
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-alpha4",
37
+ "@vaadin/component-base": "23.1.0-alpha4",
38
+ "@vaadin/field-base": "23.1.0-alpha4",
39
+ "@vaadin/input-container": "23.1.0-alpha4",
40
+ "@vaadin/vaadin-lumo-styles": "23.1.0-alpha4",
41
+ "@vaadin/vaadin-material-styles": "23.1.0-alpha4",
42
+ "@vaadin/vaadin-themable-mixin": "23.1.0-alpha4"
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": "aacdb7fe09811894751f0378ff7fb66071892c71"
50
50
  }
@@ -31,12 +31,12 @@ class MultiSelectComboBoxChip extends ThemableMixin(PolymerElement) {
31
31
  static get properties() {
32
32
  return {
33
33
  label: {
34
- type: String
34
+ type: String,
35
35
  },
36
36
 
37
37
  item: {
38
- type: Object
39
- }
38
+ type: Object,
39
+ },
40
40
  };
41
41
  }
42
42
 
@@ -73,11 +73,11 @@ class MultiSelectComboBoxChip extends ThemableMixin(PolymerElement) {
73
73
  this.dispatchEvent(
74
74
  new CustomEvent('item-removed', {
75
75
  detail: {
76
- item: this.item
76
+ item: this.item,
77
77
  },
78
78
  bubbles: true,
79
- composed: true
80
- })
79
+ composed: true,
80
+ }),
81
81
  );
82
82
  }
83
83
  }
@@ -16,8 +16,8 @@ registerStyles(
16
16
  }
17
17
  `,
18
18
  {
19
- moduleId: 'vaadin-multi-select-combo-box-container-styles'
20
- }
19
+ moduleId: 'vaadin-multi-select-combo-box-container-styles',
20
+ },
21
21
  );
22
22
 
23
23
  let memoizedTemplate;
@@ -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,49 @@ 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
+ super._onFocusout(event);
183
+
184
+ if (this.readonly && !this._closeOnBlurIsPrevented) {
185
+ this.close();
186
+ }
187
+ }
188
+
130
189
  /**
131
190
  * @param {CustomEvent} event
132
191
  * @protected
@@ -135,6 +194,11 @@ class MultiSelectComboBoxInternal extends ComboBoxDataProviderMixin(ComboBoxMixi
135
194
  _overlaySelectedItemChanged(event) {
136
195
  event.stopPropagation();
137
196
 
197
+ // Do not un-select on click when readonly
198
+ if (this.readonly) {
199
+ return;
200
+ }
201
+
138
202
  if (event.detail.item instanceof ComboBoxPlaceholder) {
139
203
  return;
140
204
  }
@@ -143,9 +207,9 @@ class MultiSelectComboBoxInternal extends ComboBoxDataProviderMixin(ComboBoxMixi
143
207
  this.dispatchEvent(
144
208
  new CustomEvent('combo-box-item-selected', {
145
209
  detail: {
146
- item: event.detail.item
147
- }
148
- })
210
+ item: event.detail.item,
211
+ },
212
+ }),
149
213
  );
150
214
  }
151
215
  }
@@ -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
  /**
@@ -23,9 +23,20 @@ class MultiSelectComboBoxScroller extends ComboBoxScroller {
23
23
  return false;
24
24
  }
25
25
 
26
+ if (this.comboBox.readonly) {
27
+ return false;
28
+ }
29
+
26
30
  const host = this.comboBox.getRootNode().host;
27
31
  return host._findIndex(item, host.selectedItems, itemIdPath) > -1;
28
32
  }
33
+
34
+ /** @private */
35
+ __updateElement(el, index) {
36
+ super.__updateElement(el, index);
37
+
38
+ el.toggleAttribute('readonly', this.comboBox.readonly);
39
+ }
29
40
  }
30
41
 
31
42
  customElements.define(MultiSelectComboBoxScroller.is, MultiSelectComboBoxScroller);
@@ -232,13 +232,13 @@ declare class MultiSelectComboBox<TItem = ComboBoxDefaultItem> extends HTMLEleme
232
232
  addEventListener<K extends keyof MultiSelectComboBoxEventMap<TItem>>(
233
233
  type: K,
234
234
  listener: (this: MultiSelectComboBox<TItem>, ev: MultiSelectComboBoxEventMap<TItem>[K]) => void,
235
- options?: boolean | AddEventListenerOptions
235
+ options?: boolean | AddEventListenerOptions,
236
236
  ): void;
237
237
 
238
238
  removeEventListener<K extends keyof MultiSelectComboBoxEventMap<TItem>>(
239
239
  type: K,
240
240
  listener: (this: MultiSelectComboBox<TItem>, ev: MultiSelectComboBoxEventMap<TItem>[K]) => void,
241
- options?: boolean | EventListenerOptions
241
+ options?: boolean | EventListenerOptions,
242
242
  ): void;
243
243
  }
244
244
 
@@ -46,7 +46,7 @@ const multiSelectComboBox = css`
46
46
  `;
47
47
 
48
48
  registerStyles('vaadin-multi-select-combo-box', [inputFieldShared, multiSelectComboBox], {
49
- moduleId: 'vaadin-multi-select-combo-box-styles'
49
+ moduleId: 'vaadin-multi-select-combo-box-styles',
50
50
  });
51
51
 
52
52
  /**
@@ -213,7 +213,7 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
213
213
  type: Boolean,
214
214
  reflectToAttribute: true,
215
215
  observer: '_clearButtonVisibleChanged',
216
- value: false
216
+ value: false,
217
217
  },
218
218
 
219
219
  /**
@@ -221,7 +221,7 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
221
221
  * The items can be of either `String` or `Object` type.
222
222
  */
223
223
  items: {
224
- type: Array
224
+ type: Array,
225
225
  },
226
226
 
227
227
  /**
@@ -229,7 +229,7 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
229
229
  * @attr {string} item-label-path
230
230
  */
231
231
  itemLabelPath: {
232
- type: String
232
+ type: String,
233
233
  },
234
234
 
235
235
  /**
@@ -238,7 +238,7 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
238
238
  * @attr {string} item-value-path
239
239
  */
240
240
  itemValuePath: {
241
- type: String
241
+ type: String,
242
242
  },
243
243
 
244
244
  /**
@@ -246,7 +246,17 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
246
246
  * @attr {string} item-id-path
247
247
  */
248
248
  itemIdPath: {
249
- type: String
249
+ type: String,
250
+ },
251
+
252
+ /**
253
+ * When present, it specifies that the field is read-only.
254
+ */
255
+ readonly: {
256
+ type: Boolean,
257
+ value: false,
258
+ observer: '_readonlyChanged',
259
+ reflectToAttribute: true,
250
260
  },
251
261
 
252
262
  /**
@@ -256,7 +266,7 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
256
266
  selectedItems: {
257
267
  type: Array,
258
268
  value: () => [],
259
- notify: true
269
+ notify: true,
260
270
  },
261
271
 
262
272
  /**
@@ -266,7 +276,7 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
266
276
  type: Boolean,
267
277
  notify: true,
268
278
  value: false,
269
- reflectToAttribute: true
279
+ reflectToAttribute: true,
270
280
  },
271
281
 
272
282
  /**
@@ -276,7 +286,7 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
276
286
  pageSize: {
277
287
  type: Number,
278
288
  value: 50,
279
- observer: '_pageSizeChanged'
289
+ observer: '_pageSizeChanged',
280
290
  },
281
291
 
282
292
  /**
@@ -293,7 +303,7 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
293
303
  */
294
304
  dataProvider: {
295
305
  type: Object,
296
- observer: '_dataProviderChanged'
306
+ observer: '_dataProviderChanged',
297
307
  },
298
308
 
299
309
  /**
@@ -302,7 +312,7 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
302
312
  */
303
313
  allowCustomValues: {
304
314
  type: Boolean,
305
- value: false
315
+ value: false,
306
316
  },
307
317
 
308
318
  /**
@@ -324,7 +334,7 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
324
334
  filter: {
325
335
  type: String,
326
336
  value: '',
327
- notify: true
337
+ notify: true,
328
338
  },
329
339
 
330
340
  /**
@@ -337,14 +347,14 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
337
347
  /** @protected */
338
348
  _hasValue: {
339
349
  type: Boolean,
340
- value: false
350
+ value: false,
341
351
  },
342
352
 
343
353
  /** @private */
344
354
  _overflowItems: {
345
355
  type: Array,
346
- value: () => []
347
- }
356
+ value: () => [],
357
+ },
348
358
  };
349
359
  }
350
360
 
@@ -376,7 +386,7 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
376
386
  this._setFocusElement(input);
377
387
  this.stateTarget = input;
378
388
  this.ariaTarget = input;
379
- })
389
+ }),
380
390
  );
381
391
  this.addController(new LabelledInputController(this.inputElement, this._labelController));
382
392
 
@@ -465,6 +475,26 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
465
475
  }
466
476
  }
467
477
 
478
+ /** @private */
479
+ _readonlyChanged(readonly, oldReadonly) {
480
+ if (readonly) {
481
+ this.__savedItems = this.$.comboBox._getOverlayItems();
482
+ 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
+ });
488
+ } else if (oldReadonly) {
489
+ this.$.comboBox._setOverlayItems(this.__savedItems);
490
+ this.__savedItems = null;
491
+
492
+ this._chips.forEach((chip) => {
493
+ chip.removeAttribute('readonly');
494
+ });
495
+ }
496
+ }
497
+
468
498
  /** @private */
469
499
  _pageSizeChanged(pageSize, oldPageSize) {
470
500
  if (Math.floor(pageSize) !== pageSize || pageSize <= 0) {
@@ -484,6 +514,10 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
484
514
  // Re-render chips
485
515
  this.__updateChips();
486
516
 
517
+ if (this.readonly) {
518
+ this.$.comboBox._setOverlayItems(selectedItems);
519
+ }
520
+
487
521
  // Re-render scroller
488
522
  this.$.comboBox.$.dropdown._scroller.requestContentUpdate();
489
523
 
@@ -593,6 +627,7 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
593
627
 
594
628
  chip.item = item;
595
629
  chip.toggleAttribute('disabled', this.disabled);
630
+ chip.toggleAttribute('readonly', this.readonly);
596
631
 
597
632
  const label = this._getItemLabel(item, this.itemLabelPath);
598
633
  chip.label = label;
@@ -719,8 +754,8 @@ class MultiSelectComboBox extends ResizeMixin(InputControlMixin(ThemableMixin(El
719
754
  new CustomEvent('custom-values-set', {
720
755
  detail: event.detail,
721
756
  composed: true,
722
- bubbles: true
723
- })
757
+ bubbles: true,
758
+ }),
724
759
  );
725
760
  }
726
761
 
@@ -22,7 +22,7 @@ const chip = css`
22
22
  cursor: var(--lumo-clickable-cursor);
23
23
  }
24
24
 
25
- :host(:not([part~='overflow'])) {
25
+ :host(:not([part~='overflow']):not([readonly]):not([disabled])) {
26
26
  padding-inline-end: 0;
27
27
  }
28
28
 
@@ -88,13 +88,18 @@ const chip = css`
88
88
  content: var(--lumo-icons-cross);
89
89
  }
90
90
 
91
- :host([disabled]) [part] {
91
+ :host([disabled]) [part='label'] {
92
92
  color: var(--lumo-disabled-text-color);
93
93
  -webkit-text-fill-color: var(--lumo-disabled-text-color);
94
94
  pointer-events: none;
95
95
  }
96
+
97
+ :host([readonly]) [part='remove-button'],
98
+ :host([disabled]) [part='remove-button'] {
99
+ display: none;
100
+ }
96
101
  `;
97
102
 
98
103
  registerStyles('vaadin-multi-select-combo-box-chip', [fieldButton, chip], {
99
- moduleId: 'lumo-multi-select-combo-box-chip'
104
+ moduleId: 'lumo-multi-select-combo-box-chip',
100
105
  });
@@ -10,6 +10,21 @@ import '@vaadin/vaadin-lumo-styles/typography.js';
10
10
  import { inputFieldShared } from '@vaadin/vaadin-lumo-styles/mixins/input-field-shared.js';
11
11
  import { css, registerStyles } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
12
12
 
13
+ registerStyles(
14
+ 'vaadin-multi-select-combo-box-item',
15
+ css`
16
+ @media (any-hover: hover) {
17
+ :host(:hover[readonly]) {
18
+ background-color: transparent;
19
+ cursor: default;
20
+ }
21
+ }
22
+ `,
23
+ {
24
+ moduleId: 'lumo-multi-select-combo-box-item',
25
+ },
26
+ );
27
+
13
28
  const multiSelectComboBox = css`
14
29
  :host([has-value]) {
15
30
  padding-inline-start: 0;
@@ -26,8 +41,13 @@ const multiSelectComboBox = css`
26
41
  [part='toggle-button']::before {
27
42
  content: var(--lumo-icons-dropdown);
28
43
  }
44
+
45
+ :host([readonly][has-value]) [part='toggle-button'] {
46
+ color: var(--lumo-contrast-60pct);
47
+ cursor: var(--lumo-clickable-cursor);
48
+ }
29
49
  `;
30
50
 
31
51
  registerStyles('vaadin-multi-select-combo-box', [inputFieldShared, multiSelectComboBox], {
32
- moduleId: 'lumo-multi-select-combo-box'
52
+ moduleId: 'lumo-multi-select-combo-box',
33
53
  });
@@ -13,17 +13,20 @@ const chip = css`
13
13
  :host {
14
14
  height: 1.25rem;
15
15
  margin-inline-end: 0.25rem;
16
- padding-inline-start: 0.5rem;
16
+ padding: 0 0.5rem;
17
17
  border-radius: 4px;
18
18
  background-color: hsla(214, 53%, 23%, 0.1);
19
19
  cursor: default;
20
20
  font-family: var(--material-font-family);
21
21
  }
22
22
 
23
+ :host(:not([part~='overflow']):not([readonly]):not([disabled])) {
24
+ padding-inline-end: 0;
25
+ }
26
+
23
27
  :host([part~='overflow']) {
24
28
  position: relative;
25
29
  margin-inline-start: 0.5rem;
26
- padding-inline-end: 0.5rem;
27
30
  }
28
31
 
29
32
  :host([part~='overflow'])::before,
@@ -85,22 +88,18 @@ const chip = css`
85
88
  content: var(--material-icons-clear);
86
89
  }
87
90
 
88
- /* Disabled */
89
- :host([disabled]) [part] {
90
- pointer-events: none;
91
- }
92
-
93
91
  :host([disabled]) [part='label'] {
94
92
  color: var(--material-disabled-text-color);
95
93
  -webkit-text-fill-color: var(--material-disabled-text-color);
94
+ pointer-events: none;
96
95
  }
97
96
 
97
+ :host([readonly]) [part='remove-button'],
98
98
  :host([disabled]) [part='remove-button'] {
99
- color: hsla(0, 0%, 100%, 0.75);
100
- -webkit-text-fill-color: hsla(0, 0%, 100%, 0.75);
99
+ display: none;
101
100
  }
102
101
  `;
103
102
 
104
103
  registerStyles('vaadin-multi-select-combo-box-chip', [fieldButton, chip], {
105
- moduleId: 'material-multi-select-combo-box-chip'
104
+ moduleId: 'material-multi-select-combo-box-chip',
106
105
  });
@@ -9,6 +9,21 @@ import '@vaadin/vaadin-material-styles/typography.js';
9
9
  import { inputFieldShared } from '@vaadin/vaadin-material-styles/mixins/input-field-shared.js';
10
10
  import { css, registerStyles } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
11
11
 
12
+ registerStyles(
13
+ 'vaadin-multi-select-combo-box-item',
14
+ css`
15
+ @media (any-hover: hover) {
16
+ :host(:hover[readonly]) {
17
+ background-color: transparent;
18
+ cursor: default;
19
+ }
20
+ }
21
+ `,
22
+ {
23
+ moduleId: 'material-multi-select-combo-box-item',
24
+ },
25
+ );
26
+
12
27
  const multiSelectComboBox = css`
13
28
  :host([readonly]) [part~='chip'] {
14
29
  opacity: 0.5;
@@ -30,8 +45,12 @@ const multiSelectComboBox = css`
30
45
  :host([opened]) [part='toggle-button'] {
31
46
  transform: rotate(180deg);
32
47
  }
48
+
49
+ :host([readonly][has-value]) [part='toggle-button'] {
50
+ color: var(--material-secondary-text-color);
51
+ }
33
52
  `;
34
53
 
35
54
  registerStyles('vaadin-multi-select-combo-box', [inputFieldShared, multiSelectComboBox], {
36
- moduleId: 'material-multi-select-combo-box'
55
+ moduleId: 'material-multi-select-combo-box',
37
56
  });