@six-group/ui-library 0.0.0-insider.7c3e3d8 → 0.0.0-insider.a358260

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 (81) hide show
  1. package/dist/cjs/six-checkbox.cjs.entry.js +57 -46
  2. package/dist/cjs/six-checkbox.cjs.entry.js.map +1 -1
  3. package/dist/cjs/six-input.cjs.entry.js +8 -10
  4. package/dist/cjs/six-input.cjs.entry.js.map +1 -1
  5. package/dist/cjs/six-radio.cjs.entry.js +56 -51
  6. package/dist/cjs/six-radio.cjs.entry.js.map +1 -1
  7. package/dist/cjs/six-range.cjs.entry.js +114 -75
  8. package/dist/cjs/six-range.cjs.entry.js.map +1 -1
  9. package/dist/cjs/six-select.cjs.entry.js +298 -239
  10. package/dist/cjs/six-select.cjs.entry.js.map +1 -1
  11. package/dist/cjs/six-textarea.cjs.entry.js +97 -74
  12. package/dist/cjs/six-textarea.cjs.entry.js.map +1 -1
  13. package/dist/collection/components/six-checkbox/six-checkbox.js +62 -49
  14. package/dist/collection/components/six-checkbox/six-checkbox.js.map +1 -1
  15. package/dist/collection/components/six-input/six-input.js +8 -10
  16. package/dist/collection/components/six-input/six-input.js.map +1 -1
  17. package/dist/collection/components/six-radio/six-radio.js +60 -53
  18. package/dist/collection/components/six-radio/six-radio.js.map +1 -1
  19. package/dist/collection/components/six-range/six-range.js +121 -76
  20. package/dist/collection/components/six-range/six-range.js.map +1 -1
  21. package/dist/collection/components/six-select/six-select.js +248 -240
  22. package/dist/collection/components/six-select/six-select.js.map +1 -1
  23. package/dist/collection/components/six-select/util.js +52 -0
  24. package/dist/collection/components/six-select/util.js.map +1 -0
  25. package/dist/collection/components/six-textarea/six-textarea.js +115 -105
  26. package/dist/collection/components/six-textarea/six-textarea.js.map +1 -1
  27. package/dist/components/six-checkbox.js +57 -46
  28. package/dist/components/six-checkbox.js.map +1 -1
  29. package/dist/components/six-input2.js +8 -10
  30. package/dist/components/six-input2.js.map +1 -1
  31. package/dist/components/six-radio.js +56 -51
  32. package/dist/components/six-radio.js.map +1 -1
  33. package/dist/components/six-range.js +114 -75
  34. package/dist/components/six-range.js.map +1 -1
  35. package/dist/components/six-select.js +299 -240
  36. package/dist/components/six-select.js.map +1 -1
  37. package/dist/components/six-textarea.js +97 -74
  38. package/dist/components/six-textarea.js.map +1 -1
  39. package/dist/components.json +30 -22
  40. package/dist/esm/six-checkbox.entry.js +57 -46
  41. package/dist/esm/six-checkbox.entry.js.map +1 -1
  42. package/dist/esm/six-input.entry.js +8 -10
  43. package/dist/esm/six-input.entry.js.map +1 -1
  44. package/dist/esm/six-radio.entry.js +56 -51
  45. package/dist/esm/six-radio.entry.js.map +1 -1
  46. package/dist/esm/six-range.entry.js +114 -75
  47. package/dist/esm/six-range.entry.js.map +1 -1
  48. package/dist/esm/six-select.entry.js +299 -240
  49. package/dist/esm/six-select.entry.js.map +1 -1
  50. package/dist/esm/six-textarea.entry.js +97 -74
  51. package/dist/esm/six-textarea.entry.js.map +1 -1
  52. package/dist/types/components/six-checkbox/six-checkbox.d.ts +21 -17
  53. package/dist/types/components/six-input/six-input.d.ts +1 -1
  54. package/dist/types/components/six-radio/six-radio.d.ts +10 -11
  55. package/dist/types/components/six-range/six-range.d.ts +24 -20
  56. package/dist/types/components/six-select/six-select.d.ts +35 -40
  57. package/dist/types/components/six-select/util.d.ts +7 -0
  58. package/dist/types/components/six-textarea/six-textarea.d.ts +22 -31
  59. package/dist/types/components.d.ts +9 -13
  60. package/dist/ui-library/p-163f2bb0.entry.js +2 -0
  61. package/dist/ui-library/p-163f2bb0.entry.js.map +1 -0
  62. package/dist/ui-library/{p-e9e930d2.entry.js → p-394a2a12.entry.js} +2 -2
  63. package/dist/ui-library/{p-e9e930d2.entry.js.map → p-394a2a12.entry.js.map} +1 -1
  64. package/dist/ui-library/{p-7e0cc4ae.entry.js → p-3c635d0a.entry.js} +2 -2
  65. package/dist/ui-library/p-3c635d0a.entry.js.map +1 -0
  66. package/dist/ui-library/p-5a25d6fb.entry.js +2 -0
  67. package/dist/ui-library/p-5a25d6fb.entry.js.map +1 -0
  68. package/dist/ui-library/{p-90dc6af4.entry.js → p-97cc839c.entry.js} +2 -2
  69. package/dist/ui-library/p-97cc839c.entry.js.map +1 -0
  70. package/dist/ui-library/p-f604e067.entry.js +2 -0
  71. package/dist/ui-library/p-f604e067.entry.js.map +1 -0
  72. package/dist/ui-library/ui-library.esm.js +1 -1
  73. package/package.json +1 -1
  74. package/dist/ui-library/p-0d79b0c6.entry.js +0 -2
  75. package/dist/ui-library/p-0d79b0c6.entry.js.map +0 -1
  76. package/dist/ui-library/p-7e0cc4ae.entry.js.map +0 -1
  77. package/dist/ui-library/p-835c3ff7.entry.js +0 -2
  78. package/dist/ui-library/p-835c3ff7.entry.js.map +0 -1
  79. package/dist/ui-library/p-90dc6af4.entry.js.map +0 -1
  80. package/dist/ui-library/p-edc96efc.entry.js +0 -2
  81. package/dist/ui-library/p-edc96efc.entry.js.map +0 -1
@@ -3,6 +3,7 @@ import { getTextContent, hasSlot } from '../../utils/slot';
3
3
  import FormControl from '../../functional-components/form-control/form-control';
4
4
  import { EventListeners } from '../../utils/event-listeners';
5
5
  import { debounce, DEFAULT_DEBOUNCE_FAST } from '../../utils/execution-control';
6
+ import { getValue, isValidValue, isValueEmpty, valueEquals } from './util';
6
7
  let id = 0;
7
8
  /**
8
9
  * @since 1.0
@@ -31,9 +32,120 @@ export class SixSelect {
31
32
  this.labelId = `select-label-${id}`;
32
33
  this.helpTextId = `select-help-text-${id}`;
33
34
  this.errorTextId = `select-error-text-${id}`;
35
+ this.touched = false;
34
36
  this.customErrorText = '';
35
37
  this.customValidation = false;
36
38
  this.eventListeners = new EventListeners();
39
+ this.handleBlur = () => {
40
+ this.hasFocus = false;
41
+ this.sixBlur.emit();
42
+ };
43
+ this.handleFocus = () => {
44
+ this.hasFocus = true;
45
+ this.sixFocus.emit();
46
+ };
47
+ this.handleInvalid = () => {
48
+ this.invalid = true;
49
+ };
50
+ this.handleClearClick = (event) => {
51
+ event.stopPropagation();
52
+ this.clearValues();
53
+ };
54
+ this.handleSelectAll = (event) => {
55
+ const nonFilteredItems = this.getItems().filter((item) => item.style.display !== 'none');
56
+ const keyName = event.key;
57
+ const keyCode = event.code;
58
+ if (keyName === 'Control') {
59
+ return;
60
+ }
61
+ if (this.isOpen && this.multiple && keyCode === 'KeyA' && event.ctrlKey) {
62
+ event.preventDefault();
63
+ const hasDeselectedOptions = nonFilteredItems.some((opt) => !opt.disabled && !opt.checked);
64
+ nonFilteredItems
65
+ .filter((option) => !option.disabled)
66
+ .forEach((option) => (option.checked = hasDeselectedOptions));
67
+ const checkedItems = nonFilteredItems.filter((option) => option.checked).map((option) => option.value);
68
+ this.value = hasDeselectedOptions ? checkedItems : [];
69
+ }
70
+ };
71
+ this.handleKeyDown = async (event) => {
72
+ var _a;
73
+ const target = event.target;
74
+ const items = this.getItems();
75
+ const firstItem = items[0];
76
+ const lastItem = items[items.length - 1];
77
+ // Ignore key presses on tags
78
+ if (target.tagName.toLowerCase() === 'six-tag') {
79
+ return;
80
+ }
81
+ // Tabbing out of the control closes it
82
+ if (event.key === 'Tab') {
83
+ if (this.isOpen && this.dropdown != null) {
84
+ await this.dropdown.hide();
85
+ }
86
+ return;
87
+ }
88
+ // Up/down opens the menu
89
+ if (['ArrowDown', 'ArrowUp'].includes(event.key)) {
90
+ event.preventDefault();
91
+ // Show the menu if it's not already open
92
+ if (!this.isOpen && this.dropdown != null) {
93
+ await this.dropdown.show();
94
+ }
95
+ // Focus on a menu item
96
+ if (event.key === 'ArrowDown' && firstItem) {
97
+ firstItem.setFocus();
98
+ }
99
+ else if (event.key === 'ArrowUp' && lastItem) {
100
+ lastItem.setFocus();
101
+ }
102
+ }
103
+ // All other keys open the menu and initiate type to select
104
+ if (!this.isOpen && this.dropdown != null) {
105
+ event.stopPropagation();
106
+ event.preventDefault();
107
+ await this.dropdown.show();
108
+ await ((_a = this.menu) === null || _a === void 0 ? void 0 : _a.typeToSelect(event.key));
109
+ }
110
+ };
111
+ this.handleLabelClick = () => {
112
+ var _a;
113
+ (_a = this.box) === null || _a === void 0 ? void 0 : _a.focus();
114
+ };
115
+ this.handleMenuShow = (event) => {
116
+ var _a;
117
+ if (this.disabled) {
118
+ event.preventDefault();
119
+ return;
120
+ }
121
+ this.resizeMenu();
122
+ (_a = this.resizeObserver) === null || _a === void 0 ? void 0 : _a.observe(this.host);
123
+ this.isOpen = true;
124
+ };
125
+ this.handleMenuHide = () => {
126
+ var _a;
127
+ (_a = this.resizeObserver) === null || _a === void 0 ? void 0 : _a.unobserve(this.host);
128
+ this.isOpen = false;
129
+ };
130
+ this.handleSlotChange = () => {
131
+ this.hasHelpTextSlot = hasSlot(this.host, 'help-text');
132
+ this.hasErrorTextSlot = hasSlot(this.host, 'error-text');
133
+ this.hasLabelSlot = hasSlot(this.host, 'label');
134
+ this.update();
135
+ };
136
+ this.handleTagInteraction = (event) => {
137
+ // Don't toggle the menu when a tag's clear button is activated
138
+ const path = event.composedPath();
139
+ const clearButton = path.find((el) => {
140
+ if (el instanceof HTMLElement) {
141
+ const element = el;
142
+ return element.classList.contains('tag__clear');
143
+ }
144
+ });
145
+ if (clearButton) {
146
+ event.stopPropagation();
147
+ }
148
+ };
37
149
  this.hasFocus = false;
38
150
  this.hasHelpTextSlot = false;
39
151
  this.hasErrorTextSlot = false;
@@ -69,7 +181,7 @@ export class SixSelect {
69
181
  this.defaultValue = undefined;
70
182
  }
71
183
  handleDisabledChange() {
72
- if (this.disabled && this.isOpen) {
184
+ if (this.disabled && this.isOpen && this.dropdown != null) {
73
185
  this.dropdown.hide();
74
186
  }
75
187
  }
@@ -77,94 +189,159 @@ export class SixSelect {
77
189
  this.handleSlotChange();
78
190
  }
79
191
  handleMultipleChange() {
80
- // Cast to array | string based on `this.multiple`
81
- const value = this.getValueAsArray();
82
- this.value = this.multiple ? value : value[0] || '';
83
- this.syncItemsFromValue();
192
+ this.update();
84
193
  }
85
- handleValueChange() {
86
- this.syncItemsFromValue();
87
- if (this.input) {
88
- this.sixChange.emit({ value: this.value, isSelected: true });
194
+ handleValueChange(newValue, oldValue) {
195
+ var _a;
196
+ let items = (_a = this.options) !== null && _a !== void 0 ? _a : this.getItems();
197
+ // normalize invalid values. This will re-trigger this watch handler
198
+ if (!isValidValue(newValue, this.multiple, items)) {
199
+ this.value = getValue(newValue, this.multiple, items);
200
+ return;
201
+ }
202
+ // avoid re-triggering if old and new values are equal. Needed because
203
+ // watch does a shallow comparison only.
204
+ if (valueEquals(getValue(oldValue, this.multiple, items), getValue(newValue, this.multiple, items))) {
205
+ return;
206
+ }
207
+ this.update();
208
+ this.sixChange.emit({ value: this.value, isSelected: true });
209
+ }
210
+ update() {
211
+ var _a;
212
+ const items = this.getItems();
213
+ this.value = getValue(this.value, this.multiple, (_a = this.options) !== null && _a !== void 0 ? _a : items);
214
+ if (!Array.isArray(this.value)) {
215
+ // Sync checked states
216
+ items.forEach((item) => (item.checked = false));
217
+ const item = items.find((item) => this.value.includes(item.value));
218
+ if (item != null) {
219
+ item.checked = true;
220
+ }
221
+ // Sync input element content
222
+ this.displayLabel = this.extractLabelForSelectedItem([this.value], items);
223
+ this.displayTags = [];
224
+ const hasSelection = !isValueEmpty(this.value);
225
+ if (hasSelection) {
226
+ this.touched = true;
227
+ }
228
+ if (this.inputElement && this.touched) {
229
+ if (!this.autocomplete) {
230
+ this.inputElement.value = hasSelection ? this.displayLabel : '';
231
+ }
232
+ else if (hasSelection) {
233
+ this.inputElement.value = this.value;
234
+ }
235
+ this.inputElement.checkValidity().then((valid) => (this.invalid = !valid));
236
+ }
237
+ }
238
+ else {
239
+ // Sync checked states
240
+ items.forEach((item) => (item.checked = this.value.includes(item.value)));
241
+ // Sync display label
242
+ const checkedItems = [];
243
+ this.value.forEach((val) => items.map((item) => (item.value === val ? checkedItems.push(item) : null)));
244
+ this.displayTags = checkedItems.map((item) => {
245
+ return (h("six-tag", { exportparts: "base:tag", type: "primary", size: this.size, pill: this.pill, clearable: true, onClick: this.handleTagInteraction, onKeyDown: this.handleTagInteraction, "onSix-tag-clear": (event) => {
246
+ event.stopPropagation();
247
+ if (!this.disabled) {
248
+ this.toggleItem(item);
249
+ }
250
+ } }, this.getItemLabel(item)));
251
+ });
252
+ if (this.maxTagsVisible > 0 && this.displayTags.length > this.maxTagsVisible) {
253
+ const total = this.displayTags.length;
254
+ this.displayLabel = '';
255
+ this.displayTags = this.displayTags.slice(0, this.maxTagsVisible);
256
+ this.displayTags.push(h("six-tag", { exportparts: "base:tag", type: "info", size: this.size }, "+", total - this.maxTagsVisible));
257
+ }
258
+ // Sync input element content
259
+ const hasSelection = !isValueEmpty(this.value);
260
+ if (hasSelection) {
261
+ this.touched = true;
262
+ }
263
+ if (this.inputElement && this.touched) {
264
+ if (!this.autocomplete) {
265
+ this.inputElement.value = hasSelection ? this.displayLabel : '';
266
+ }
267
+ else if (hasSelection) {
268
+ this.inputElement.value = this.value.join(',');
269
+ }
270
+ this.inputElement.checkValidity().then((valid) => (this.invalid = !valid));
271
+ }
89
272
  }
90
273
  }
91
274
  connectedCallback() {
275
+ var _a;
92
276
  if (this.virtualScroll && this.options === null) {
93
277
  console.error('Options must be defined when using virtual scrolling');
94
278
  }
95
- this.handleBlur = this.handleBlur.bind(this);
96
- this.handleFocus = this.handleFocus.bind(this);
97
- this.handleClearClick = this.handleClearClick.bind(this);
98
- this.handleKeyDown = this.handleKeyDown.bind(this);
99
- this.handleSelectAll = this.handleSelectAll.bind(this);
100
- this.handleLabelClick = this.handleLabelClick.bind(this);
101
- this.handleMenuHide = this.handleMenuHide.bind(this);
102
- this.handleMenuShow = this.handleMenuShow.bind(this);
103
- this.handleMenuSelect = this.handleMenuSelect.bind(this);
104
- this.handleSlotChange = this.handleSlotChange.bind(this);
105
- this.handleInvalid = this.handleInvalid.bind(this);
106
- this.handleTagInteraction = this.handleTagInteraction.bind(this);
107
- this.host.shadowRoot.addEventListener('slotchange', this.handleSlotChange);
279
+ (_a = this.host.shadowRoot) === null || _a === void 0 ? void 0 : _a.addEventListener('slotchange', this.handleSlotChange);
108
280
  }
109
281
  componentWillLoad() {
110
282
  this.handleSlotChange();
111
- if (this.multiple && this.value) {
112
- this.value = this.getValueAsArray();
113
- }
114
283
  }
115
284
  componentDidLoad() {
285
+ const inputElement = this.inputElement;
286
+ if (inputElement == null) {
287
+ return;
288
+ }
116
289
  this.resizeObserver = new ResizeObserver(() => this.resizeMenu());
117
- // We need to do an initial sync after the component has rendered, so this will suppress the re-render warning
118
- requestAnimationFrame(() => this.syncItemsFromValue());
119
- this.eventListeners.add(this.input, 'invalid', async (event) => {
120
- if (this.customValidation || (!this.hasErrorTextSlot && !this.errorText && !this.customErrorText)) {
121
- this.customErrorText = await this.input.getValidationMessage();
290
+ this.eventListeners.add(inputElement, 'invalid', async (event) => {
291
+ if (this.customValidation || (!this.hasErrorTextSlot && this.errorText === '' && this.customErrorText === '')) {
292
+ this.customErrorText = await inputElement.getValidationMessage();
122
293
  }
123
294
  event.preventDefault();
124
295
  });
125
- this.eventListeners.add(this.input, 'six-input-input', debounce((event) => {
126
- const enteredValue = this.input.value;
296
+ this.eventListeners.add(inputElement, 'six-input-input', debounce((event) => {
297
+ const enteredValue = inputElement.value;
127
298
  this.clearValues();
128
299
  this.sixChange.emit({ value: enteredValue, isSelected: false });
129
300
  event.stopPropagation();
130
301
  }, this.inputDebounce));
131
- this.input.value = this.hasSelection() ? this.displayLabel : '';
132
302
  }
133
303
  disconnectedCallback() {
134
- this.host.shadowRoot.removeEventListener('slotchange', this.handleSlotChange);
304
+ var _a;
305
+ (_a = this.host.shadowRoot) === null || _a === void 0 ? void 0 : _a.removeEventListener('slotchange', this.handleSlotChange);
135
306
  this.eventListeners.removeAll();
136
307
  }
137
308
  /** Checks for validity and shows the browser's validation message if the control is invalid. */
138
309
  async reportValidity() {
139
- return this.input.reportValidity();
310
+ var _a;
311
+ return (_a = this.inputElement) === null || _a === void 0 ? void 0 : _a.reportValidity();
140
312
  }
141
313
  /** Checks for validity. */
142
314
  async checkValidity() {
143
- return this.input.isValid();
315
+ var _a;
316
+ return (_a = this.inputElement) === null || _a === void 0 ? void 0 : _a.isValid();
144
317
  }
145
318
  /** Sets a custom validation message. If `message` is not empty, the field will be considered invalid. */
146
319
  async setCustomValidity(message) {
147
320
  this.customErrorText = '';
148
321
  this.customValidation = message !== '';
149
- this.input.setCustomValidity(message);
150
- this.invalid = !this.input.checkValidity();
322
+ if (this.inputElement != null) {
323
+ await this.inputElement.setCustomValidity(message);
324
+ this.invalid = !(await this.inputElement.checkValidity());
325
+ }
151
326
  }
152
327
  /** Resets the formcontrol */
153
328
  async reset() {
329
+ var _a;
154
330
  this.clearValues();
155
331
  this.customErrorText = '';
156
332
  this.customValidation = false;
157
- this.input.setCustomValidity('');
333
+ await ((_a = this.inputElement) === null || _a === void 0 ? void 0 : _a.setCustomValidity(''));
158
334
  this.invalid = false;
159
335
  }
160
336
  getItemLabel(item) {
161
- const slot = item.shadowRoot.querySelector('slot:not([name])');
162
- if (slot) {
337
+ var _a, _b;
338
+ const slot = (_a = item.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('slot:not([name])');
339
+ if (slot != null) {
163
340
  return getTextContent(slot);
164
341
  }
165
342
  else {
166
343
  // bugfix/COMSLI-203-six-select-value-is-not-updated-if-the-slot-is-changed
167
- return item.textContent;
344
+ return (_b = item.textContent) !== null && _b !== void 0 ? _b : '';
168
345
  }
169
346
  }
170
347
  getItems() {
@@ -176,192 +353,18 @@ export class SixSelect {
176
353
  hasMenuItems() {
177
354
  return this.getItems().length > 0;
178
355
  }
179
- getValueAsStringArray() {
180
- const values = this.getValueAsArray();
181
- // enforce that the values are converted to 'string' before the value is compared
182
- return values.map(String);
183
- }
184
- getValueAsArray() {
185
- return Array.isArray(this.value) ? this.value : [this.value];
186
- }
187
- handleBlur() {
188
- this.hasFocus = false;
189
- this.sixBlur.emit();
190
- }
191
- handleFocus() {
192
- this.hasFocus = true;
193
- this.sixFocus.emit();
194
- }
195
- handleInvalid() {
196
- this.invalid = true;
197
- }
198
- handleClearClick(event) {
199
- event.stopPropagation();
200
- this.clearValues();
201
- }
202
356
  clearValues() {
203
357
  var _a;
204
358
  this.value = (_a = this.defaultValue) !== null && _a !== void 0 ? _a : (this.multiple ? [] : '');
205
- this.syncItemsFromValue();
206
- }
207
- handleSelectAll(event) {
208
- const nonFilteredItems = this.getItems().filter((item) => item.style.display !== 'none');
209
- const keyName = event.key;
210
- const keyCode = event.code;
211
- if (keyName === 'Control') {
212
- return;
213
- }
214
- if (this.isOpen && this.multiple && keyCode === 'KeyA' && event.ctrlKey) {
215
- event.preventDefault();
216
- const hasDeselectedOptions = nonFilteredItems.some((opt) => !opt.disabled && !opt.checked);
217
- nonFilteredItems
218
- .filter((option) => !option.disabled)
219
- .forEach((option) => (option.checked = hasDeselectedOptions));
220
- const checkedItems = nonFilteredItems.filter((option) => option.checked).map((option) => option.value);
221
- this.value = hasDeselectedOptions ? checkedItems : [];
222
- }
359
+ this.update();
223
360
  }
224
- handleKeyDown(event) {
225
- const target = event.target;
226
- const items = this.getItems();
227
- const firstItem = items[0];
228
- const lastItem = items[items.length - 1];
229
- // Ignore key presses on tags
230
- if (target.tagName.toLowerCase() === 'six-tag') {
231
- return;
232
- }
233
- // Tabbing out of the control closes it
234
- if (event.key === 'Tab') {
235
- if (this.isOpen) {
236
- this.dropdown.hide();
237
- }
361
+ async resizeMenu() {
362
+ if (this.menu == null || this.box == null) {
238
363
  return;
239
364
  }
240
- // Up/down opens the menu
241
- if (['ArrowDown', 'ArrowUp'].includes(event.key)) {
242
- event.preventDefault();
243
- // Show the menu if it's not already open
244
- if (!this.isOpen) {
245
- this.dropdown.show();
246
- }
247
- // Focus on a menu item
248
- if (event.key === 'ArrowDown' && firstItem) {
249
- firstItem.setFocus();
250
- return;
251
- }
252
- if (event.key === 'ArrowUp' && lastItem) {
253
- lastItem.setFocus();
254
- return;
255
- }
256
- }
257
- // All other keys open the menu and initiate type to select
258
- if (!this.isOpen) {
259
- event.stopPropagation();
260
- event.preventDefault();
261
- this.dropdown.show();
262
- this.menu.typeToSelect(event.key);
263
- }
264
- }
265
- handleLabelClick() {
266
- this.box.focus();
267
- }
268
- handleMenuSelect(event) {
269
- const item = event.detail.item;
270
- if (this.multiple) {
271
- if (this.value == null || this.value === '') {
272
- this.value = [];
273
- }
274
- else if (!Array.isArray(this.value)) {
275
- this.value = [this.value];
276
- }
277
- this.value = this.value.includes(item.value)
278
- ? this.value.filter((v) => v !== item.value)
279
- : [...this.value, item.value];
280
- }
281
- else {
282
- this.value = item.value;
283
- }
284
- this.syncItemsFromValue();
285
- }
286
- handleMenuShow(event) {
287
- if (this.disabled) {
288
- event.preventDefault();
289
- return;
290
- }
291
- this.resizeMenu();
292
- this.resizeObserver.observe(this.host);
293
- this.isOpen = true;
294
- }
295
- handleMenuHide() {
296
- this.resizeObserver.unobserve(this.host);
297
- this.isOpen = false;
298
- }
299
- handleSlotChange() {
300
- this.hasHelpTextSlot = hasSlot(this.host, 'help-text');
301
- this.hasErrorTextSlot = hasSlot(this.host, 'error-text');
302
- this.hasLabelSlot = hasSlot(this.host, 'label');
303
- this.syncItemsFromValue();
304
- }
305
- handleTagInteraction(event) {
306
- // Don't toggle the menu when a tag's clear button is activated
307
- const path = event.composedPath();
308
- const clearButton = path.find((el) => {
309
- if (el instanceof HTMLElement) {
310
- const element = el;
311
- return element.classList.contains('tag__clear');
312
- }
313
- });
314
- if (clearButton) {
315
- event.stopPropagation();
316
- }
317
- }
318
- resizeMenu() {
319
365
  this.menu.style.minWidth = `${this.box.clientWidth}px`;
320
366
  if (this.dropdown) {
321
- this.dropdown.reposition();
322
- }
323
- }
324
- syncItemsFromValue() {
325
- const items = this.getItems();
326
- const value = this.getValueAsStringArray();
327
- // Sync checked states
328
- items.forEach((item) => (item.checked = value.includes(item.value)));
329
- // Sync display label
330
- if (this.multiple) {
331
- const checkedItems = [];
332
- value.forEach((val) => items.map((item) => (item.value === val ? checkedItems.push(item) : null)));
333
- this.displayTags = checkedItems.map((item) => {
334
- return (h("six-tag", { exportparts: "base:tag", type: "primary", size: this.size, pill: this.pill, clearable: true, onClick: this.handleTagInteraction, onKeyDown: this.handleTagInteraction, "onSix-tag-clear": (event) => {
335
- event.stopPropagation();
336
- if (!this.disabled) {
337
- item.checked = false;
338
- this.syncValueFromItems();
339
- }
340
- } }, this.getItemLabel(item)));
341
- });
342
- if (this.maxTagsVisible > 0 && this.displayTags.length > this.maxTagsVisible) {
343
- const total = this.displayTags.length;
344
- this.displayLabel = '';
345
- this.displayTags = this.displayTags.slice(0, this.maxTagsVisible);
346
- this.displayTags.push(h("six-tag", { exportparts: "base:tag", type: "info", size: this.size }, "+", total - this.maxTagsVisible));
347
- }
348
- }
349
- else {
350
- this.displayLabel = this.extractLabelForSelectedItem(value, items);
351
- this.displayTags = [];
352
- }
353
- const hasSelection = this.hasSelection();
354
- if (hasSelection) {
355
- this.touched = true;
356
- }
357
- if (this.input && this.touched) {
358
- if (!this.autocomplete) {
359
- this.input.value = hasSelection ? this.displayLabel : '';
360
- }
361
- else if (hasSelection) {
362
- this.input.value = Array.isArray(this.value) ? this.value.join(',') : this.value;
363
- }
364
- this.invalid = !this.input.checkValidity();
367
+ await this.dropdown.reposition();
365
368
  }
366
369
  }
367
370
  extractLabelForSelectedItem(value, items) {
@@ -375,23 +378,34 @@ export class SixSelect {
375
378
  const checkedItem = items.find((item) => item.value === value[0]);
376
379
  return checkedItem ? this.getItemLabel(checkedItem) : '';
377
380
  }
378
- syncValueFromItems() {
379
- const items = this.getItems();
380
- const checkedItems = items.filter((item) => item.checked);
381
- const checkedValues = checkedItems.map((item) => item.value);
382
- this.value = this.multiple
383
- ? this.getValueAsStringArray().filter((val) => checkedValues.includes(val))
384
- : checkedValues.length > 0
385
- ? checkedValues[0]
386
- : '';
381
+ toggleItem(item) {
382
+ var _a;
383
+ const value = getValue(this.value, this.multiple, (_a = this.options) !== null && _a !== void 0 ? _a : this.getItems());
384
+ if (Array.isArray(value)) {
385
+ const itemFound = value.find((v) => v === item.value);
386
+ if (itemFound == null) {
387
+ this.value = [...this.value, item.value];
388
+ }
389
+ else {
390
+ this.value = value.filter((v) => v !== item.value);
391
+ }
392
+ }
393
+ else {
394
+ if (item.value === value) {
395
+ this.value = '';
396
+ }
397
+ else {
398
+ this.value = item.value;
399
+ }
400
+ }
387
401
  }
388
402
  displayError() {
389
403
  return this.invalid && (!this.errorOnBlur || (!this.hasFocus && !this.isOpen));
390
404
  }
391
405
  render() {
392
406
  var _a;
393
- const hasSelection = this.hasSelection();
394
- return (h(FormControl, { inputId: this.inputId, label: this.label, labelId: this.labelId, hasLabelSlot: this.hasLabelSlot, helpTextId: this.helpTextId, helpText: this.helpText, hasHelpTextSlot: this.hasHelpTextSlot, errorTextId: this.errorTextId, errorText: this.customErrorText ? this.customErrorText : this.errorText, hasErrorTextSlot: this.hasErrorTextSlot, size: this.size, onLabelClick: this.handleLabelClick, disabled: this.disabled, required: this.required, displayError: this.displayError() }, h("six-dropdown", { part: "base", ref: (el) => (this.dropdown = el), hoist: this.hoist, closeOnSelect: !this.multiple, containingElement: this.host, disableHideOnEnterAndSpace: this.autocomplete, class: {
407
+ const hasSelection = !isValueEmpty(this.value);
408
+ return (h(FormControl, { inputId: this.inputId, label: this.label, labelId: this.labelId, hasLabelSlot: this.hasLabelSlot, helpTextId: this.helpTextId, helpText: this.helpText, hasHelpTextSlot: this.hasHelpTextSlot, errorTextId: this.errorTextId, errorText: this.customErrorText != null ? this.customErrorText : this.errorText, hasErrorTextSlot: this.hasErrorTextSlot, size: this.size, onLabelClick: this.handleLabelClick, disabled: this.disabled, required: this.required, displayError: this.displayError() }, h("six-dropdown", { part: "base", ref: (el) => (this.dropdown = el), hoist: this.hoist, closeOnSelect: !this.multiple, containingElement: this.host, disableHideOnEnterAndSpace: this.autocomplete, class: {
395
409
  select: true,
396
410
  'select--open': this.isOpen,
397
411
  'select--empty': ((_a = this.value) === null || _a === void 0 ? void 0 : _a.length) === 0,
@@ -410,20 +424,14 @@ export class SixSelect {
410
424
  select__box: true,
411
425
  'select__box--line': this.line,
412
426
  'select__box--autocomplete': this.autocomplete,
413
- }, role: "combobox", "aria-labelledby": this.labelId, "aria-describedby": this.helpTextId, "aria-haspopup": "true", "aria-expanded": this.isOpen ? 'true' : 'false', tabIndex: this.disabled ? -1 : 0, onBlur: this.handleBlur, onFocus: this.handleFocus, onKeyDown: this.handleKeyDown }, h("span", { class: "select__label" }, this.displayTags.length ? (h("span", { part: "tags", class: "select__tags" }, this.displayTags)) : (this.displayLabel || this.placeholder)), this.clearable && hasSelection && (h("six-icon-button", { exportparts: "base:clear-button", class: "select__clear", name: "clear", size: "small", onClick: this.handleClearClick, tabindex: "-1" })), this.hasMenuItems() && (h("span", { part: "icon", class: "select__icon" }, h("six-icon", { size: "medium" }, "expand_more"))), h("six-input", { ref: (el) => (this.input = el), class: {
427
+ }, role: "combobox", "aria-labelledby": this.labelId, "aria-describedby": this.helpTextId, "aria-haspopup": "true", "aria-expanded": this.isOpen ? 'true' : 'false', tabIndex: this.disabled ? -1 : 0, onBlur: this.handleBlur, onFocus: this.handleFocus, onKeyDown: this.handleKeyDown }, h("span", { class: "select__label" }, this.displayTags.length ? (h("span", { part: "tags", class: "select__tags" }, this.displayTags)) : (this.displayLabel || this.placeholder)), this.clearable && hasSelection && (h("six-icon-button", { exportparts: "base:clear-button", class: "select__clear", name: "clear", size: "small", onClick: this.handleClearClick, tabindex: "-1" })), this.hasMenuItems() && (h("span", { part: "icon", class: "select__icon" }, h("six-icon", { size: "medium" }, "expand_more"))), h("six-input", { ref: (el) => (this.inputElement = el), class: {
414
428
  select__input: true,
415
429
  'select__hidden-select': !this.autocomplete,
416
430
  }, "aria-hidden": "true", required: this.required, onInvalid: this.handleInvalid, onFocus: this.handleFocus, clearable: this.clearable, placeholder: this.placeholder, pill: this.pill, disabled: this.disabled, size: this.size, tabIndex: -1 })), h("six-menu", { ref: (el) => (this.menu = el), part: "menu", class: {
417
431
  select__menu: true,
418
432
  'select__menu--filtered': this.filter || this.asyncFilter,
419
433
  'select__menu--hidden': !this.hasMenuItems(),
420
- }, "onSix-menu-item-selected": this.handleMenuSelect, items: this.options, virtualScroll: this.virtualScroll, "remove-box-shadow": true }, h("slot", { onSlotchange: this.handleSlotChange })))));
421
- }
422
- hasSelection() {
423
- if (this.multiple) {
424
- return Array.isArray(this.value) ? this.value.length > 0 : false;
425
- }
426
- return this.value !== '';
434
+ }, "onSix-menu-item-selected": (event) => this.toggleItem(event.detail.item), items: this.options, virtualScroll: this.virtualScroll, "remove-box-shadow": true }, h("slot", { onSlotchange: this.handleSlotChange })))));
427
435
  }
428
436
  static get is() { return "six-select"; }
429
437
  static get encapsulation() { return "shadow"; }
@@ -538,7 +546,7 @@ export class SixSelect {
538
546
  "references": {}
539
547
  },
540
548
  "required": false,
541
- "optional": false,
549
+ "optional": true,
542
550
  "docs": {
543
551
  "tags": [],
544
552
  "text": "The filter's placeholder text."