@solid-design-system/components 1.31.0 → 1.32.0

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 (142) hide show
  1. package/dist/components/es/checkbox.js +1 -1
  2. package/dist/components/es/default-value.js +1 -0
  3. package/dist/components/es/drawer.js +1 -1
  4. package/dist/components/es/dropdown.js +1 -1
  5. package/dist/components/es/form-control.styles.js +1 -0
  6. package/dist/components/es/icon.js +3 -4
  7. package/dist/components/es/input.js +1 -1
  8. package/dist/components/es/live.js +3 -3
  9. package/dist/components/es/option.js +1 -0
  10. package/dist/components/es/popup.js +1 -1
  11. package/dist/components/es/scroll.js +1 -0
  12. package/dist/components/es/select.js +5 -0
  13. package/dist/components/es/solid-components2.js +1 -1
  14. package/dist/components/es/solid-element.js +1 -1
  15. package/dist/components/es/switch.js +1 -1
  16. package/dist/components/es/tabbable.js +1 -1
  17. package/dist/components/es/tag.js +1 -1
  18. package/dist/components/umd/solid-components.js +25 -22
  19. package/dist/custom-elements.json +1 -1
  20. package/dist/package/components/option/option.d.ts +30 -0
  21. package/dist/package/components/option/option.js +145 -0
  22. package/dist/package/components/popup/popup.d.ts +3 -0
  23. package/dist/package/components/popup/popup.js +17 -0
  24. package/dist/package/components/select/select.d.ts +101 -0
  25. package/dist/package/components/select/select.js +700 -0
  26. package/dist/package/components/tag/tag.d.ts +1 -0
  27. package/dist/package/components/tag/tag.js +5 -3
  28. package/dist/package/solid-components.d.ts +2 -0
  29. package/dist/package/solid-components.js +22 -18
  30. package/dist/package/styles/tailwind.css.js +1 -1
  31. package/dist/package/translations/en.js +3 -4
  32. package/dist/package/utilities/localize.d.ts +1 -0
  33. package/dist/versioned-components/es/accordion-group.js +1 -1
  34. package/dist/versioned-components/es/accordion.js +1 -1
  35. package/dist/versioned-components/es/badge.js +1 -1
  36. package/dist/versioned-components/es/brandshape.js +1 -1
  37. package/dist/versioned-components/es/button.js +1 -1
  38. package/dist/versioned-components/es/carousel-item.js +1 -1
  39. package/dist/versioned-components/es/carousel.js +3 -3
  40. package/dist/versioned-components/es/checkbox-group.js +1 -1
  41. package/dist/versioned-components/es/checkbox.js +1 -1
  42. package/dist/versioned-components/es/default-value.js +1 -0
  43. package/dist/versioned-components/es/divider.js +1 -1
  44. package/dist/versioned-components/es/drawer.js +1 -1
  45. package/dist/versioned-components/es/dropdown.js +1 -1
  46. package/dist/versioned-components/es/form-control.styles.js +1 -0
  47. package/dist/versioned-components/es/form.js +1 -1
  48. package/dist/versioned-components/es/header.js +1 -1
  49. package/dist/versioned-components/es/icon.js +3 -4
  50. package/dist/versioned-components/es/include.js +1 -1
  51. package/dist/versioned-components/es/input.js +1 -1
  52. package/dist/versioned-components/es/link.js +1 -1
  53. package/dist/versioned-components/es/live.js +3 -3
  54. package/dist/versioned-components/es/navigation-item.js +1 -1
  55. package/dist/versioned-components/es/notification.js +1 -1
  56. package/dist/versioned-components/es/option.js +1 -0
  57. package/dist/versioned-components/es/popup.js +1 -1
  58. package/dist/versioned-components/es/radio-group.js +1 -1
  59. package/dist/versioned-components/es/radio.js +1 -1
  60. package/dist/versioned-components/es/scroll.js +1 -0
  61. package/dist/versioned-components/es/select.js +5 -0
  62. package/dist/versioned-components/es/solid-components2.js +1 -1
  63. package/dist/versioned-components/es/solid-element.js +1 -1
  64. package/dist/versioned-components/es/spinner.js +1 -1
  65. package/dist/versioned-components/es/switch.js +1 -1
  66. package/dist/versioned-components/es/tabbable.js +1 -1
  67. package/dist/versioned-components/es/tag.js +1 -1
  68. package/dist/versioned-components/es/teaser.js +1 -1
  69. package/dist/versioned-components/es/tooltip.js +2 -2
  70. package/dist/versioned-components/es/video.js +1 -1
  71. package/dist/versioned-package/_components/button-group/button-group.d.ts +1 -1
  72. package/dist/versioned-package/_components/button-group/button-group.js +11 -11
  73. package/dist/versioned-package/components/accordion/accordion.d.ts +1 -1
  74. package/dist/versioned-package/components/accordion/accordion.js +2 -2
  75. package/dist/versioned-package/components/accordion-group/accordion-group.d.ts +1 -1
  76. package/dist/versioned-package/components/accordion-group/accordion-group.js +3 -3
  77. package/dist/versioned-package/components/badge/badge.d.ts +1 -1
  78. package/dist/versioned-package/components/badge/badge.js +1 -1
  79. package/dist/versioned-package/components/brandshape/brandshape.d.ts +1 -1
  80. package/dist/versioned-package/components/brandshape/brandshape.js +1 -1
  81. package/dist/versioned-package/components/button/button.d.ts +1 -1
  82. package/dist/versioned-package/components/button/button.js +4 -4
  83. package/dist/versioned-package/components/carousel/carousel.d.ts +1 -1
  84. package/dist/versioned-package/components/carousel/carousel.js +6 -6
  85. package/dist/versioned-package/components/carousel-item/carousel-item.d.ts +1 -1
  86. package/dist/versioned-package/components/carousel-item/carousel-item.js +1 -1
  87. package/dist/versioned-package/components/checkbox/checkbox.d.ts +1 -1
  88. package/dist/versioned-package/components/checkbox/checkbox.js +4 -4
  89. package/dist/versioned-package/components/checkbox-group/checkbox-group.d.ts +1 -1
  90. package/dist/versioned-package/components/checkbox-group/checkbox-group.js +5 -5
  91. package/dist/versioned-package/components/divider/divider.d.ts +1 -1
  92. package/dist/versioned-package/components/divider/divider.js +2 -2
  93. package/dist/versioned-package/components/drawer/drawer.d.ts +1 -1
  94. package/dist/versioned-package/components/drawer/drawer.js +2 -2
  95. package/dist/versioned-package/components/dropdown/dropdown.d.ts +1 -1
  96. package/dist/versioned-package/components/dropdown/dropdown.js +8 -8
  97. package/dist/versioned-package/components/header/header.d.ts +1 -1
  98. package/dist/versioned-package/components/header/header.js +4 -4
  99. package/dist/versioned-package/components/icon/icon.d.ts +1 -1
  100. package/dist/versioned-package/components/icon/icon.js +1 -1
  101. package/dist/versioned-package/components/include/include.d.ts +1 -1
  102. package/dist/versioned-package/components/include/include.js +1 -1
  103. package/dist/versioned-package/components/input/input.d.ts +1 -1
  104. package/dist/versioned-package/components/input/input.js +4 -4
  105. package/dist/versioned-package/components/link/link.d.ts +1 -1
  106. package/dist/versioned-package/components/link/link.js +2 -2
  107. package/dist/versioned-package/components/navigation-item/navigation-item.d.ts +1 -1
  108. package/dist/versioned-package/components/navigation-item/navigation-item.js +3 -3
  109. package/dist/versioned-package/components/notification/notification.d.ts +1 -1
  110. package/dist/versioned-package/components/notification/notification.js +5 -5
  111. package/dist/versioned-package/components/option/option.d.ts +30 -0
  112. package/dist/versioned-package/components/option/option.js +145 -0
  113. package/dist/versioned-package/components/popup/popup.d.ts +4 -1
  114. package/dist/versioned-package/components/popup/popup.js +18 -1
  115. package/dist/versioned-package/components/radio/radio.d.ts +1 -1
  116. package/dist/versioned-package/components/radio/radio.js +2 -2
  117. package/dist/versioned-package/components/radio-group/radio-group.d.ts +2 -2
  118. package/dist/versioned-package/components/radio-group/radio-group.js +14 -14
  119. package/dist/versioned-package/components/select/select.d.ts +101 -0
  120. package/dist/versioned-package/components/select/select.js +700 -0
  121. package/dist/versioned-package/components/spinner/spinner.d.ts +1 -1
  122. package/dist/versioned-package/components/spinner/spinner.js +1 -1
  123. package/dist/versioned-package/components/switch/switch.d.ts +1 -1
  124. package/dist/versioned-package/components/switch/switch.js +2 -2
  125. package/dist/versioned-package/components/tag/tag.d.ts +2 -1
  126. package/dist/versioned-package/components/tag/tag.js +6 -4
  127. package/dist/versioned-package/components/teaser/teaser.js +1 -1
  128. package/dist/versioned-package/components/tooltip/tooltip.d.ts +1 -1
  129. package/dist/versioned-package/components/tooltip/tooltip.js +5 -5
  130. package/dist/versioned-package/components/video/video.d.ts +1 -1
  131. package/dist/versioned-package/components/video/video.js +2 -2
  132. package/dist/versioned-package/internal/form.js +2 -2
  133. package/dist/versioned-package/solid-components.d.ts +2 -0
  134. package/dist/versioned-package/solid-components.js +22 -18
  135. package/dist/versioned-package/styles/form-control.styles.js +1 -1
  136. package/dist/versioned-package/styles/tailwind.css.js +1 -1
  137. package/dist/versioned-package/translations/en.js +3 -4
  138. package/dist/versioned-package/utilities/localize.d.ts +1 -0
  139. package/dist/versioned-styles/solid-styles.css +1 -1
  140. package/dist/vscode.html-custom-data.json +346 -32
  141. package/dist/web-types.json +790 -82
  142. package/package.json +3 -3
@@ -0,0 +1,700 @@
1
+ import { stopAnimations, animateTo } from "../../internal/animate.js";
2
+ import { css, html } from "lit";
3
+ import { customElement } from "../../internal/register-custom-element.js";
4
+ import { defaultValue } from "../../internal/default-value.js";
5
+ import { FormControlController } from "../../internal/form.js";
6
+ import { setDefaultAnimation, getAnimation } from "../../utilities/animation-registry.js";
7
+ import { HasSlotController } from "../../internal/slot.js";
8
+ import { LocalizeController } from "../../utilities/localize.js";
9
+ import { queryAssignedElements, query, state, property } from "lit/decorators.js";
10
+ import { scrollIntoView } from "../../internal/scroll.js";
11
+ import { unsafeHTML } from "lit/directives/unsafe-html.js";
12
+ import { waitForEvent } from "../../internal/event.js";
13
+ import { watch } from "../../internal/watch.js";
14
+ import componentStyles from "../../styles/component.styles.js";
15
+ import cx from "classix";
16
+ import formControlStyles from "../../styles/form-control.styles.js";
17
+ import SdIcon from "../icon/icon.js";
18
+ import SdPopup from "../popup/popup.js";
19
+ import SdTag from "../tag/tag.js";
20
+ import SolidElement from "../../internal/solid-element.js";
21
+ var __defProp = Object.defineProperty;
22
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
23
+ var __decorateClass = (decorators, target, key, kind) => {
24
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
25
+ for (var i = decorators.length - 1, decorator; i >= 0; i--)
26
+ if (decorator = decorators[i])
27
+ result = (kind ? decorator(target, key, result) : decorator(result)) || result;
28
+ if (kind && result)
29
+ __defProp(target, key, result);
30
+ return result;
31
+ };
32
+ let SdSelect = class extends SolidElement {
33
+ constructor() {
34
+ super(...arguments);
35
+ this.formControlController = new FormControlController(this, {
36
+ assumeInteractionOn: ["sd-blur", "sd-input"]
37
+ });
38
+ this.hasSlotController = new HasSlotController(this, "help-text", "label");
39
+ this.localize = new LocalizeController(this);
40
+ this.typeToSelectString = "";
41
+ this.hasFocus = false;
42
+ this.hasHover = false;
43
+ this.displayLabel = "";
44
+ this.selectedOptions = [];
45
+ this.isValid = false;
46
+ this.isInvalid = false;
47
+ this.defaultValue = "";
48
+ this.open = false;
49
+ this.size = "lg";
50
+ this.label = "Label";
51
+ this.placeholder = this.localize.term("selectDefaultPlaceholder");
52
+ this.helpText = "";
53
+ this.placement = "bottom";
54
+ this.currentPlacement = this.placement;
55
+ this.clearable = false;
56
+ this.disabled = false;
57
+ this.multiple = false;
58
+ this.useTags = false;
59
+ this.maxOptionsVisible = 3;
60
+ this.form = "";
61
+ this.name = "";
62
+ this.value = "";
63
+ this.required = false;
64
+ this.hoist = false;
65
+ this.getTag = (option) => {
66
+ return html`<sd-tag ?disabled="${this.disabled}" part="tag" exportparts="
67
+ base:tag__base,
68
+ content:tag__content,
69
+ removable-indicator:tag__removable-indicator,
70
+ " size="${this.size === "sm" ? "sm" : "lg"}" removable @sd-remove="${(event) => this.handleTagRemove(event, option)}">${option.getTextLabel()}</sd-tag>`;
71
+ };
72
+ this.handleDocumentFocusIn = (event) => {
73
+ const path = event.composedPath();
74
+ if (this && !path.includes(this)) {
75
+ this.hide();
76
+ }
77
+ };
78
+ this.handleDocumentKeyDown = (event) => {
79
+ const target = event.target;
80
+ const isClearButton = target.closest(".select__clear") !== null;
81
+ const isIconButton = target.closest("sd-icon-button") !== null;
82
+ if (isClearButton || isIconButton) {
83
+ return;
84
+ }
85
+ if (event.key === "Escape" && this.open) {
86
+ event.preventDefault();
87
+ event.stopPropagation();
88
+ this.hide();
89
+ this.displayInput.focus({ preventScroll: true });
90
+ }
91
+ if (event.key === "Enter" || event.key === " " && this.typeToSelectString === "") {
92
+ event.preventDefault();
93
+ event.stopImmediatePropagation();
94
+ if (!this.open) {
95
+ this.show();
96
+ return;
97
+ }
98
+ if (this.currentOption && !this.currentOption.disabled) {
99
+ if (this.multiple) {
100
+ this.toggleOptionSelection(this.currentOption);
101
+ } else {
102
+ this.setSelectedOptions(this.currentOption);
103
+ }
104
+ this.updateComplete.then(() => {
105
+ this.emit("sd-input");
106
+ this.emit("sd-change");
107
+ });
108
+ if (!this.multiple) {
109
+ this.hide();
110
+ this.displayInput.focus({ preventScroll: true });
111
+ }
112
+ }
113
+ return;
114
+ }
115
+ if (["ArrowUp", "ArrowDown", "Home", "End"].includes(event.key)) {
116
+ const allOptions = this.getAllOptions();
117
+ const currentIndex = allOptions.indexOf(this.currentOption);
118
+ let newIndex = Math.max(0, currentIndex);
119
+ event.preventDefault();
120
+ if (!this.open) {
121
+ this.show();
122
+ if (this.currentOption) {
123
+ return;
124
+ }
125
+ }
126
+ if (event.key === "ArrowDown") {
127
+ newIndex = currentIndex + 1;
128
+ if (newIndex > allOptions.length - 1)
129
+ newIndex = 0;
130
+ } else if (event.key === "ArrowUp") {
131
+ newIndex = currentIndex - 1;
132
+ if (newIndex < 0)
133
+ newIndex = allOptions.length - 1;
134
+ } else if (event.key === "Home") {
135
+ newIndex = 0;
136
+ } else if (event.key === "End") {
137
+ newIndex = allOptions.length - 1;
138
+ }
139
+ this.setCurrentOption(allOptions[newIndex]);
140
+ }
141
+ if (event.key.length === 1 || event.key === "Backspace") {
142
+ const allOptions = this.getAllOptions();
143
+ if (event.metaKey || event.ctrlKey || event.altKey) {
144
+ return;
145
+ }
146
+ if (!this.open) {
147
+ if (event.key === "Backspace") {
148
+ return;
149
+ }
150
+ this.show();
151
+ }
152
+ event.stopPropagation();
153
+ event.preventDefault();
154
+ clearTimeout(this.typeToSelectTimeout);
155
+ this.typeToSelectTimeout = window.setTimeout(() => this.typeToSelectString = "", 1e3);
156
+ if (event.key === "Backspace") {
157
+ this.typeToSelectString = this.typeToSelectString.slice(0, -1);
158
+ } else {
159
+ this.typeToSelectString += event.key.toLowerCase();
160
+ }
161
+ for (const option of allOptions) {
162
+ const label = option.getTextLabel().toLowerCase();
163
+ if (label.startsWith(this.typeToSelectString)) {
164
+ this.setCurrentOption(option);
165
+ break;
166
+ }
167
+ }
168
+ }
169
+ };
170
+ this.handleDocumentMouseDown = (event) => {
171
+ const path = event.composedPath();
172
+ if (this && !path.includes(this)) {
173
+ this.hide();
174
+ }
175
+ };
176
+ }
177
+ /** Gets the validity state object */
178
+ get validity() {
179
+ return this.valueInput.validity;
180
+ }
181
+ /** Gets the validation message */
182
+ get validationMessage() {
183
+ return this.valueInput.validationMessage;
184
+ }
185
+ connectedCallback() {
186
+ super.connectedCallback();
187
+ this.applySizeToOptions();
188
+ this.open = false;
189
+ }
190
+ /** Checks for the presence of the attributes 'data-user-valid' or 'data-user-invalid' and updates the corresponding state for reactive conditional styling. */
191
+ updated() {
192
+ if (this.hasAttribute("data-user-valid") && this.checkValidity()) {
193
+ this.isValid = true;
194
+ }
195
+ if (this.hasAttribute("data-user-invalid") && !this.checkValidity()) {
196
+ this.isInvalid = true;
197
+ }
198
+ }
199
+ addOpenListeners() {
200
+ document.addEventListener("focusin", this.handleDocumentFocusIn);
201
+ document.addEventListener("keydown", this.handleDocumentKeyDown);
202
+ document.addEventListener("mousedown", this.handleDocumentMouseDown);
203
+ }
204
+ removeOpenListeners() {
205
+ document.removeEventListener("focusin", this.handleDocumentFocusIn);
206
+ document.removeEventListener("keydown", this.handleDocumentKeyDown);
207
+ document.removeEventListener("mousedown", this.handleDocumentMouseDown);
208
+ }
209
+ handleFocus() {
210
+ this.hasFocus = true;
211
+ this.displayInput.setSelectionRange(0, 0);
212
+ this.emit("sd-focus");
213
+ }
214
+ handleBlur() {
215
+ this.hasFocus = false;
216
+ this.emit("sd-blur");
217
+ }
218
+ handleLabelClick() {
219
+ this.displayInput.focus();
220
+ }
221
+ handleComboboxMouseDown(event) {
222
+ const path = event.composedPath();
223
+ const isRemovableIndicator = path.some((el) => el instanceof HTMLSlotElement && el.name === "removable-indicator");
224
+ if (this.disabled || isRemovableIndicator) {
225
+ return;
226
+ }
227
+ event.preventDefault();
228
+ this.displayInput.focus({ preventScroll: true });
229
+ this.open = !this.open;
230
+ }
231
+ handleComboboxKeyDown(event) {
232
+ event.stopPropagation();
233
+ this.handleDocumentKeyDown(event);
234
+ }
235
+ handleClearClick(event) {
236
+ event.stopPropagation();
237
+ if (this.value !== "") {
238
+ this.setSelectedOptions([]);
239
+ this.displayInput.focus({ preventScroll: true });
240
+ this.updateComplete.then(() => {
241
+ this.emit("sd-clear");
242
+ this.emit("sd-input");
243
+ this.emit("sd-change");
244
+ });
245
+ }
246
+ }
247
+ handleClearMouseDown(event) {
248
+ event.stopPropagation();
249
+ event.preventDefault();
250
+ }
251
+ handleOptionClick(event) {
252
+ const target = event.target;
253
+ const option = target.closest("sd-option");
254
+ const oldValue = this.value;
255
+ if (option && !option.disabled) {
256
+ if (this.multiple) {
257
+ this.toggleOptionSelection(option);
258
+ } else {
259
+ this.setSelectedOptions(option);
260
+ }
261
+ this.updateComplete.then(() => this.displayInput.focus({ preventScroll: true }));
262
+ if (this.value !== oldValue) {
263
+ this.updateComplete.then(() => {
264
+ this.emit("sd-input");
265
+ this.emit("sd-change");
266
+ });
267
+ }
268
+ if (!this.multiple) {
269
+ this.hide();
270
+ this.displayInput.focus({ preventScroll: true });
271
+ }
272
+ }
273
+ }
274
+ handleDefaultSlotChange() {
275
+ const allOptions = this.getAllOptions();
276
+ const value = Array.isArray(this.value) ? this.value : [this.value];
277
+ const values = [];
278
+ if (customElements.get("sd-option")) {
279
+ allOptions.forEach((option) => {
280
+ if (this.multiple) {
281
+ option.checkbox = true;
282
+ }
283
+ values.push(option.value);
284
+ });
285
+ this.setSelectedOptions(allOptions.filter((el) => value.includes(el.value)));
286
+ } else {
287
+ customElements.whenDefined("sd-option").then(() => this.handleDefaultSlotChange());
288
+ }
289
+ }
290
+ handleTagRemove(event, option) {
291
+ event.stopPropagation();
292
+ if (!this.disabled) {
293
+ this.toggleOptionSelection(option, false);
294
+ this.updateComplete.then(() => {
295
+ this.emit("sd-input");
296
+ this.emit("sd-change");
297
+ });
298
+ }
299
+ }
300
+ // Gets an array of all <sd-option> elements
301
+ getAllOptions() {
302
+ return [...this.querySelectorAll("sd-option")];
303
+ }
304
+ // Gets the first <sd-option> element
305
+ getFirstOption() {
306
+ return this.querySelector("sd-option");
307
+ }
308
+ // Sets the current option, which is the option the user is currently interacting with (e.g. via keyboard). Only one
309
+ // option may be "current" at a time.
310
+ setCurrentOption(option) {
311
+ const allOptions = this.getAllOptions();
312
+ allOptions.forEach((el) => {
313
+ el.current = false;
314
+ el.tabIndex = -1;
315
+ });
316
+ if (option) {
317
+ this.currentOption = option;
318
+ option.current = true;
319
+ option.tabIndex = 0;
320
+ option.focus();
321
+ }
322
+ }
323
+ // Sets the selected option(s)
324
+ setSelectedOptions(option) {
325
+ const allOptions = this.getAllOptions();
326
+ const newSelectedOptions = Array.isArray(option) ? option : [option];
327
+ allOptions.forEach((el) => el.selected = false);
328
+ if (newSelectedOptions.length) {
329
+ newSelectedOptions.forEach((el) => el.selected = true);
330
+ }
331
+ this.selectionChanged();
332
+ }
333
+ // Toggles an option's selected state
334
+ toggleOptionSelection(option, force) {
335
+ if (force === true || force === false) {
336
+ option.selected = force;
337
+ } else {
338
+ option.selected = !option.selected;
339
+ }
340
+ this.selectionChanged();
341
+ }
342
+ // This method must be called whenever the selection changes. It will update the selected options cache, the current
343
+ // value, and the display value
344
+ selectionChanged() {
345
+ var _a, _b;
346
+ this.selectedOptions = this.getAllOptions().filter((el) => el.selected);
347
+ if (this.multiple) {
348
+ this.value = this.selectedOptions.map((el) => el.value);
349
+ if (this.useTags || this.value.length === 0) {
350
+ this.displayLabel = "";
351
+ } else {
352
+ this.displayLabel = this.localize.term("numOptionsSelected", this.selectedOptions.length);
353
+ }
354
+ } else {
355
+ this.value = ((_a = this.selectedOptions[0]) == null ? void 0 : _a.value) ?? "";
356
+ this.displayLabel = ((_b = this.selectedOptions[0]) == null ? void 0 : _b.getTextLabel()) ?? "";
357
+ }
358
+ this.updateComplete.then(() => {
359
+ this.formControlController.updateValidity();
360
+ });
361
+ }
362
+ get tags() {
363
+ return this.selectedOptions.map((option, index) => {
364
+ if (index < this.maxOptionsVisible || this.maxOptionsVisible <= 0) {
365
+ const tag = this.getTag(option, index);
366
+ return html`<div @sd-remove="${(e) => this.handleTagRemove(e, option)}">${typeof tag === "string" ? unsafeHTML(tag) : tag}</div>`;
367
+ } else if (index === this.maxOptionsVisible) {
368
+ return html`<sd-tag size="${this.size === "sm" ? "sm" : "lg"}" ?disabled="${this.disabled}">+${this.selectedOptions.length - index}</sd-tag>`;
369
+ }
370
+ return html``;
371
+ });
372
+ }
373
+ handleInvalid(event) {
374
+ this.formControlController.setValidity(false);
375
+ this.formControlController.emitInvalidEvent(event);
376
+ }
377
+ handleMouseEnter() {
378
+ this.hasHover = true;
379
+ }
380
+ handleMouseLeave() {
381
+ this.hasHover = false;
382
+ }
383
+ /** Receives incoming event detail from sd-popup and updates local state for conditional styling. */
384
+ handleCurrentPlacement(e) {
385
+ const incomingPlacement = e.detail;
386
+ if (incomingPlacement) {
387
+ this.currentPlacement = incomingPlacement;
388
+ }
389
+ }
390
+ handleUseTagsChange() {
391
+ const allOptions = this.getAllOptions();
392
+ if (customElements.get("sd-option")) {
393
+ allOptions.forEach((option) => {
394
+ option.checkbox = this.multiple;
395
+ });
396
+ }
397
+ }
398
+ handleDisabledChange() {
399
+ if (this.disabled) {
400
+ this.open = false;
401
+ this.handleOpenChange();
402
+ }
403
+ }
404
+ async handleOpenChange() {
405
+ if (this.open && !this.disabled) {
406
+ this.setCurrentOption(this.selectedOptions[0] || this.getFirstOption());
407
+ this.emit("sd-show");
408
+ this.addOpenListeners();
409
+ await stopAnimations(this);
410
+ this.listbox.hidden = false;
411
+ this.popup.active = true;
412
+ requestAnimationFrame(() => {
413
+ this.setCurrentOption(this.currentOption);
414
+ });
415
+ const { keyframes, options } = getAnimation(this, "select.show", { dir: this.localize.dir() });
416
+ await animateTo(this.popup.popup, keyframes, options);
417
+ if (this.currentOption) {
418
+ scrollIntoView(this.currentOption, this.listbox, "vertical", "auto");
419
+ }
420
+ this.emit("sd-after-show");
421
+ } else {
422
+ this.emit("sd-hide");
423
+ this.removeOpenListeners();
424
+ await stopAnimations(this);
425
+ const { keyframes, options } = getAnimation(this, "select.hide", { dir: this.localize.dir() });
426
+ await animateTo(this.popup.popup, keyframes, options);
427
+ this.listbox.hidden = true;
428
+ this.popup.active = false;
429
+ this.emit("sd-after-hide");
430
+ }
431
+ }
432
+ applySizeToOptions() {
433
+ this._optionsInDefaultSlot.forEach((option) => {
434
+ option.size = this.size;
435
+ });
436
+ }
437
+ handleValueChange() {
438
+ const allOptions = this.getAllOptions();
439
+ const value = Array.isArray(this.value) ? this.value : [this.value];
440
+ this.setSelectedOptions(allOptions.filter((el) => value.includes(el.value)));
441
+ }
442
+ /** Shows the listbox. */
443
+ async show() {
444
+ if (this.open || this.disabled) {
445
+ this.open = false;
446
+ return void 0;
447
+ }
448
+ this.open = true;
449
+ return waitForEvent(this, "sd-after-show");
450
+ }
451
+ /** Hides the listbox. */
452
+ async hide() {
453
+ if (!this.open || this.disabled) {
454
+ this.open = false;
455
+ return void 0;
456
+ }
457
+ this.open = false;
458
+ return waitForEvent(this, "sd-after-hide");
459
+ }
460
+ /** Checks for validity but does not show a validation message. Returns `true` when valid and `false` when invalid. */
461
+ checkValidity() {
462
+ var _a;
463
+ return (_a = this.valueInput) == null ? void 0 : _a.checkValidity();
464
+ }
465
+ /** Gets the associated form, if one exists. */
466
+ getForm() {
467
+ return this.formControlController.getForm();
468
+ }
469
+ /** Checks for validity and shows the browser's validation message if the control is invalid. */
470
+ reportValidity() {
471
+ return this.valueInput.reportValidity();
472
+ }
473
+ /** Sets a custom validation message. Pass an empty string to restore validity. */
474
+ setCustomValidity(message) {
475
+ this.valueInput.setCustomValidity(message);
476
+ this.formControlController.updateValidity();
477
+ }
478
+ /** Sets focus on the control. */
479
+ focus(options) {
480
+ this.displayInput.focus(options);
481
+ }
482
+ /** Removes focus from the control. */
483
+ blur() {
484
+ this.displayInput.blur();
485
+ }
486
+ render() {
487
+ const slots = {
488
+ default: this.hasSlotController.test("[default]"),
489
+ label: this.hasSlotController.test("label"),
490
+ clearIcon: this.hasSlotController.test("clear-icon"),
491
+ expandIcon: this.hasSlotController.test("expand-icon"),
492
+ helpText: this.hasSlotController.test("help-text")
493
+ };
494
+ const hasLabel = this.label ? true : !!slots["label"];
495
+ const hasHelpText = this.helpText ? true : !!slots["helpText"];
496
+ const hasClearIcon = this.clearable && !this.disabled && this.value.length > 0;
497
+ const selectState = this.disabled ? "disabled" : this.hasFocus && this.isInvalid ? "activeInvalid" : this.hasFocus && this.isValid ? "activeValid" : this.hasFocus || this.open ? "active" : this.isInvalid ? "invalid" : this.isValid ? "valid" : "default";
498
+ const cursorStyles = this.disabled ? "cursor-not-allowed" : "cursor-pointer";
499
+ const iconMarginLeft = { sm: "ml-1", md: "ml-2", lg: "ml-2" }[this.size];
500
+ const iconSize = {
501
+ sm: "text-base",
502
+ md: "text-lg",
503
+ lg: "text-xl"
504
+ }[this.size];
505
+ return html`<div part="form-control" class="${cx(
506
+ "form-control relative text-left",
507
+ cursorStyles,
508
+ this.size === "sm" ? "text-sm" : "text-base",
509
+ {
510
+ disabled: "text-neutral-500",
511
+ readonly: "text-black",
512
+ activeInvalid: "text-error",
513
+ activeValid: "text-success",
514
+ active: "text-black",
515
+ invalid: "text-error",
516
+ valid: "text-success",
517
+ default: "text-black"
518
+ }[selectState],
519
+ this.open && "z-10"
520
+ )}"><label id="label" part="form-control-label" class="${hasLabel && "inline-block mb-2"}" aria-hidden="${hasLabel ? "false" : "true"}" @click="${this.handleLabelClick}"><slot name="label" class="${cx(this.disabled && "text-black")}">${this.label}</slot></label><div part="form-control-input" class="${cx("relative w-full bg-white")}"><div part="border" class="${cx(
521
+ "absolute top-0 w-full h-full pointer-events-none border rounded-default",
522
+ this.hasHover && "bg-neutral-200",
523
+ {
524
+ disabled: "border-neutral-500",
525
+ readonly: "border-neutral-800",
526
+ activeInvalid: "border-error border-2",
527
+ activeValid: "border-success border-2",
528
+ active: "border-primary border-2",
529
+ invalid: "border-error",
530
+ valid: "border-success",
531
+ default: "border-neutral-800"
532
+ }[selectState],
533
+ this.open && (this.currentPlacement === "bottom" ? "rounded-bl-none rounded-br-none" : "rounded-tl-none rounded-tr-none")
534
+ )}"></div><sd-popup @sd-current-placement="${this.handleCurrentPlacement}" class="${cx(
535
+ "inline-flex relative w-full",
536
+ this.currentPlacement === "bottom" ? "origin-top" : "origin-bottom"
537
+ )}" placement="${this.placement}" strategy="${this.hoist ? "fixed" : "absolute"}" flip shift sync="width" auto-size="vertical" auto-size-padding="10"><div part="combobox" class="${cx(
538
+ "relative w-full px-4 flex flex-row items-center rounded-default",
539
+ {
540
+ sm: "py-1 min-h-[32px]",
541
+ md: "py-1 min-h-[40px]",
542
+ lg: "py-2 min-h-[48px]"
543
+ }[this.size]
544
+ )}" slot="anchor" @keydown="${this.handleComboboxKeyDown}" @mousedown="${this.handleComboboxMouseDown}" @mouseenter="${this.handleMouseEnter}" @mouseleave="${this.handleMouseLeave}"><input name="${this.name}" form="${this.form}" part="display-input" class="${cx(
545
+ "appearance-none outline-none flex-grow bg-transparent",
546
+ cursorStyles,
547
+ this.multiple && this.useTags && this.value.length > 0 ? "hidden" : ""
548
+ )}" type="text" placeholder="${this.placeholder}" .disabled="${this.disabled}" .value="${this.displayLabel}" autocomplete="off" spellcheck="false" autocapitalize="off" readonly="readonly" aria-controls="listbox" aria-expanded="${this.open ? "true" : "false"}" aria-haspopup="listbox" aria-labelledby="label" aria-disabled="${this.disabled ? "true" : "false"}" aria-describedby="help-text" role="combobox" tabindex="0" @focus="${this.handleFocus}" @blur="${this.handleBlur}"> ${this.multiple && this.useTags ? html`<div part="tags" class="flex-grow flex flex-wrap items-center gap-1">${this.tags}</div>` : ""} <input class="${cx("value-input absolute top-0 left-0 w-full h-full opacity-0 -z-10", cursorStyles)}" type="text" ?disabled="${this.disabled}" ?required="${this.required}" .value="${Array.isArray(this.value) ? this.value.join(", ") : this.value}" tabindex="-1" aria-hidden="true" @focus="${() => this.focus()}" @invalid="${this.handleInvalid}"> ${hasClearIcon ? html`<button part="clear-button" class="${cx("select__clear flex justify-center", iconMarginLeft)}" type="button" aria-label="${this.localize.term("clearEntry")}" @mousedown="${this.handleClearMouseDown}" @click="${this.handleClearClick}" tabindex="-1"><slot name="clear-icon"><sd-icon class="${cx("text-neutral-500", iconSize)}" library="system" name="closing-round"></sd-icon></slot></button>` : ""} ${this.isInvalid ? html`<sd-icon class="${cx("text-error", iconMarginLeft, iconSize)}" library="system" name="risk"></sd-icon>` : ""} ${this.isValid ? html`<sd-icon class="${cx("text-success", iconMarginLeft, iconSize)}" library="system" name="confirm"></sd-icon>` : ""}<slot name="expand-icon" part="expand-icon" class="${cx("inline-flex ml-2 transition-all", this.open ? "rotate-180" : "rotate-0", iconSize)}"><sd-icon name="chevron-down" part="chevron" library="system" color="currentColor"></sd-icon></slot></div><div id="listbox" role="listbox" aria-expanded="${this.open ? "true" : "false"}" aria-multiselectable="${this.multiple ? "true" : "false"}" aria-labelledby="label" part="listbox" class="${cx(
549
+ "bg-white px-2 py-3 relative",
550
+ this.currentPlacement === "bottom" ? "border-r-2 border-b-2 border-l-2 rounded-br-default rounded-bl-default" : "border-r-2 border-t-2 border-l-2 rounded-tr-default rounded-tl-default"
551
+ )}" tabindex="-1" @mouseup="${this.handleOptionClick}" @slotchange="${this.handleDefaultSlotChange}"><slot></slot></div></sd-popup></div><div class="text-sm text-neutral-700" part="form-control-help-text" id="help-text" aria-hidden="${hasHelpText ? "false" : "true"}"><slot name="help-text">${this.helpText}</slot></div></div>`;
552
+ }
553
+ };
554
+ SdSelect.dependencies = {
555
+ "sd-icon": SdIcon,
556
+ "sd-popup": SdPopup,
557
+ "sd-tag": SdTag
558
+ };
559
+ SdSelect.styles = [
560
+ componentStyles,
561
+ formControlStyles,
562
+ SolidElement.styles,
563
+ css`:host{display:block;position:relative;width:100%}:host([required]) #label::after{content:' *'}sd-popup::part(popup){overflow-y:scroll}sd-tag::part(base){border-radius:4px;padding-left:4px;padding-right:4px}sd-tag[size=lg]::part(base){padding-left:8px;padding-right:8px}sd-tag[disabled=false]::part(base):hover{background-color:rgb(var(--sd-color-primary-100,236 240 249) / 1)}`
564
+ ];
565
+ __decorateClass([
566
+ queryAssignedElements({ selector: "sd-option" })
567
+ ], SdSelect.prototype, "_optionsInDefaultSlot", 2);
568
+ __decorateClass([
569
+ query("sd-popup")
570
+ ], SdSelect.prototype, "popup", 2);
571
+ __decorateClass([
572
+ query('[part="combobox"]')
573
+ ], SdSelect.prototype, "combobox", 2);
574
+ __decorateClass([
575
+ query('[part="display-input"]')
576
+ ], SdSelect.prototype, "displayInput", 2);
577
+ __decorateClass([
578
+ query(".value-input")
579
+ ], SdSelect.prototype, "valueInput", 2);
580
+ __decorateClass([
581
+ query('[part="listbox"]')
582
+ ], SdSelect.prototype, "listbox", 2);
583
+ __decorateClass([
584
+ state()
585
+ ], SdSelect.prototype, "hasFocus", 2);
586
+ __decorateClass([
587
+ state()
588
+ ], SdSelect.prototype, "hasHover", 2);
589
+ __decorateClass([
590
+ state()
591
+ ], SdSelect.prototype, "displayLabel", 2);
592
+ __decorateClass([
593
+ state()
594
+ ], SdSelect.prototype, "currentOption", 2);
595
+ __decorateClass([
596
+ state()
597
+ ], SdSelect.prototype, "selectedOptions", 2);
598
+ __decorateClass([
599
+ state()
600
+ ], SdSelect.prototype, "isValid", 2);
601
+ __decorateClass([
602
+ state()
603
+ ], SdSelect.prototype, "isInvalid", 2);
604
+ __decorateClass([
605
+ defaultValue()
606
+ ], SdSelect.prototype, "defaultValue", 2);
607
+ __decorateClass([
608
+ property({ type: Boolean, reflect: true })
609
+ ], SdSelect.prototype, "open", 2);
610
+ __decorateClass([
611
+ property({ reflect: true })
612
+ ], SdSelect.prototype, "size", 2);
613
+ __decorateClass([
614
+ property()
615
+ ], SdSelect.prototype, "label", 2);
616
+ __decorateClass([
617
+ property()
618
+ ], SdSelect.prototype, "placeholder", 2);
619
+ __decorateClass([
620
+ property({ attribute: "help-text" })
621
+ ], SdSelect.prototype, "helpText", 2);
622
+ __decorateClass([
623
+ property({ reflect: true })
624
+ ], SdSelect.prototype, "placement", 2);
625
+ __decorateClass([
626
+ state()
627
+ ], SdSelect.prototype, "currentPlacement", 2);
628
+ __decorateClass([
629
+ property({ type: Boolean })
630
+ ], SdSelect.prototype, "clearable", 2);
631
+ __decorateClass([
632
+ property({ type: Boolean, reflect: true })
633
+ ], SdSelect.prototype, "disabled", 2);
634
+ __decorateClass([
635
+ property({ type: Boolean, reflect: true })
636
+ ], SdSelect.prototype, "multiple", 2);
637
+ __decorateClass([
638
+ property({ type: Boolean, reflect: true })
639
+ ], SdSelect.prototype, "useTags", 2);
640
+ __decorateClass([
641
+ property({ attribute: "max-options-visible", type: Number })
642
+ ], SdSelect.prototype, "maxOptionsVisible", 2);
643
+ __decorateClass([
644
+ property({ reflect: true })
645
+ ], SdSelect.prototype, "form", 2);
646
+ __decorateClass([
647
+ property()
648
+ ], SdSelect.prototype, "name", 2);
649
+ __decorateClass([
650
+ property({
651
+ converter: {
652
+ fromAttribute: (value) => value.split(" "),
653
+ toAttribute: (value) => value.join(" ")
654
+ }
655
+ })
656
+ ], SdSelect.prototype, "value", 2);
657
+ __decorateClass([
658
+ property({ type: Boolean, reflect: true })
659
+ ], SdSelect.prototype, "required", 2);
660
+ __decorateClass([
661
+ property({ type: Boolean })
662
+ ], SdSelect.prototype, "hoist", 2);
663
+ __decorateClass([
664
+ property()
665
+ ], SdSelect.prototype, "getTag", 2);
666
+ __decorateClass([
667
+ watch("useTags", { waitUntilFirstUpdate: true })
668
+ ], SdSelect.prototype, "handleUseTagsChange", 1);
669
+ __decorateClass([
670
+ watch("disabled", { waitUntilFirstUpdate: true })
671
+ ], SdSelect.prototype, "handleDisabledChange", 1);
672
+ __decorateClass([
673
+ watch("open", { waitUntilFirstUpdate: true })
674
+ ], SdSelect.prototype, "handleOpenChange", 1);
675
+ __decorateClass([
676
+ watch("size", { waitUntilFirstUpdate: true })
677
+ ], SdSelect.prototype, "applySizeToOptions", 1);
678
+ __decorateClass([
679
+ watch("value", { waitUntilFirstUpdate: true })
680
+ ], SdSelect.prototype, "handleValueChange", 1);
681
+ SdSelect = __decorateClass([
682
+ customElement("sd-select")
683
+ ], SdSelect);
684
+ setDefaultAnimation("select.show", {
685
+ keyframes: [
686
+ { opacity: 0, scale: 0.9 },
687
+ { opacity: 1, scale: 1 }
688
+ ],
689
+ options: { duration: 100, easing: "ease" }
690
+ });
691
+ setDefaultAnimation("select.hide", {
692
+ keyframes: [
693
+ { opacity: 1, scale: 1 },
694
+ { opacity: 0, scale: 0.9 }
695
+ ],
696
+ options: { duration: 100, easing: "ease" }
697
+ });
698
+ export {
699
+ SdSelect as default
700
+ };