@solid-design-system/components 3.22.18 → 3.23.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (196) hide show
  1. package/dist/components/es/combobox.js +11 -0
  2. package/dist/components/es/dropdown.js +1 -1
  3. package/dist/components/es/map-marker.js +1 -1
  4. package/dist/components/es/navigation-item.js +1 -1
  5. package/dist/components/es/optgroup.js +1 -0
  6. package/dist/components/es/option-renderer.js +1 -0
  7. package/dist/components/es/select.js +7 -3
  8. package/dist/components/es/solid-components2.js +7 -7
  9. package/dist/components/es/tabbable.js +1 -1
  10. package/dist/components/es/utils.js +1 -0
  11. package/dist/components/umd/solid-components.js +37 -23
  12. package/dist/custom-elements.json +1 -1
  13. package/dist/package/components/combobox/combobox.d.ts +129 -0
  14. package/dist/package/components/combobox/combobox.js +958 -0
  15. package/dist/package/components/combobox/option-renderer.d.ts +5 -0
  16. package/dist/package/components/combobox/option-renderer.js +4 -0
  17. package/dist/package/components/combobox/utils.d.ts +8 -0
  18. package/dist/package/components/combobox/utils.js +14 -0
  19. package/dist/package/components/dropdown/dropdown.d.ts +2 -1
  20. package/dist/package/components/dropdown/dropdown.js +37 -28
  21. package/dist/package/components/navigation-item/navigation-item.d.ts +1 -0
  22. package/dist/package/components/navigation-item/navigation-item.js +4 -1
  23. package/dist/package/components/optgroup/optgroup.d.ts +20 -0
  24. package/dist/package/components/optgroup/optgroup.js +68 -0
  25. package/dist/package/components/select/select.d.ts +5 -1
  26. package/dist/package/components/select/select.js +94 -29
  27. package/dist/package/internal/tabbable.js +1 -1
  28. package/dist/package/solid-components.d.ts +2 -0
  29. package/dist/package/solid-components.js +74 -70
  30. package/dist/package/styles/tailwind.css.js +1 -1
  31. package/dist/package/translations/de.js +7 -4
  32. package/dist/package/translations/en.js +7 -4
  33. package/dist/package/utilities/localize.d.ts +3 -0
  34. package/dist/versioned-components/es/accordion-group.js +1 -1
  35. package/dist/versioned-components/es/accordion.js +1 -1
  36. package/dist/versioned-components/es/audio.js +1 -1
  37. package/dist/versioned-components/es/badge.js +1 -1
  38. package/dist/versioned-components/es/brandshape.js +1 -1
  39. package/dist/versioned-components/es/button.js +1 -1
  40. package/dist/versioned-components/es/carousel-item.js +1 -1
  41. package/dist/versioned-components/es/carousel.js +3 -3
  42. package/dist/versioned-components/es/checkbox-group.js +1 -1
  43. package/dist/versioned-components/es/checkbox.js +1 -1
  44. package/dist/versioned-components/es/combobox.js +11 -0
  45. package/dist/versioned-components/es/dialog.js +1 -1
  46. package/dist/versioned-components/es/divider.js +1 -1
  47. package/dist/versioned-components/es/drawer.js +1 -1
  48. package/dist/versioned-components/es/dropdown.js +1 -1
  49. package/dist/versioned-components/es/expandable.js +1 -1
  50. package/dist/versioned-components/es/flipcard.js +1 -1
  51. package/dist/versioned-components/es/form.js +1 -1
  52. package/dist/versioned-components/es/header.js +1 -1
  53. package/dist/versioned-components/es/icon.js +1 -1
  54. package/dist/versioned-components/es/include.js +1 -1
  55. package/dist/versioned-components/es/input.js +1 -1
  56. package/dist/versioned-components/es/link.js +1 -1
  57. package/dist/versioned-components/es/map-marker.js +1 -1
  58. package/dist/versioned-components/es/navigation-item.js +1 -1
  59. package/dist/versioned-components/es/notification.js +1 -1
  60. package/dist/versioned-components/es/optgroup.js +1 -0
  61. package/dist/versioned-components/es/option-renderer.js +1 -0
  62. package/dist/versioned-components/es/option.js +1 -1
  63. package/dist/versioned-components/es/quickfact.js +1 -1
  64. package/dist/versioned-components/es/radio-button.js +1 -1
  65. package/dist/versioned-components/es/radio-group.js +1 -1
  66. package/dist/versioned-components/es/radio.js +1 -1
  67. package/dist/versioned-components/es/scrollable.js +1 -1
  68. package/dist/versioned-components/es/select.js +7 -3
  69. package/dist/versioned-components/es/solid-components2.js +7 -7
  70. package/dist/versioned-components/es/spinner.js +1 -1
  71. package/dist/versioned-components/es/step-group.js +1 -1
  72. package/dist/versioned-components/es/step.js +1 -1
  73. package/dist/versioned-components/es/switch.js +1 -1
  74. package/dist/versioned-components/es/tab-group.js +1 -1
  75. package/dist/versioned-components/es/tab-panel.js +1 -1
  76. package/dist/versioned-components/es/tab.js +1 -1
  77. package/dist/versioned-components/es/tabbable.js +1 -1
  78. package/dist/versioned-components/es/tag.js +1 -1
  79. package/dist/versioned-components/es/teaser-media.js +1 -1
  80. package/dist/versioned-components/es/teaser.js +1 -1
  81. package/dist/versioned-components/es/textarea.js +1 -1
  82. package/dist/versioned-components/es/tooltip.js +2 -2
  83. package/dist/versioned-components/es/utils.js +1 -0
  84. package/dist/versioned-components/es/video.js +1 -1
  85. package/dist/versioned-package/_components/button-group/button-group.d.ts +1 -1
  86. package/dist/versioned-package/_components/button-group/button-group.js +11 -11
  87. package/dist/versioned-package/components/accordion/accordion.d.ts +1 -1
  88. package/dist/versioned-package/components/accordion/accordion.js +2 -2
  89. package/dist/versioned-package/components/accordion-group/accordion-group.d.ts +1 -1
  90. package/dist/versioned-package/components/accordion-group/accordion-group.js +3 -3
  91. package/dist/versioned-package/components/audio/audio.d.ts +1 -1
  92. package/dist/versioned-package/components/audio/audio.js +6 -6
  93. package/dist/versioned-package/components/badge/badge.d.ts +1 -1
  94. package/dist/versioned-package/components/badge/badge.js +1 -1
  95. package/dist/versioned-package/components/brandshape/brandshape.d.ts +1 -1
  96. package/dist/versioned-package/components/brandshape/brandshape.js +1 -1
  97. package/dist/versioned-package/components/button/button.d.ts +1 -1
  98. package/dist/versioned-package/components/button/button.js +4 -4
  99. package/dist/versioned-package/components/carousel/carousel.d.ts +1 -1
  100. package/dist/versioned-package/components/carousel/carousel.js +6 -6
  101. package/dist/versioned-package/components/carousel-item/carousel-item.d.ts +1 -1
  102. package/dist/versioned-package/components/carousel-item/carousel-item.js +1 -1
  103. package/dist/versioned-package/components/checkbox/checkbox.d.ts +1 -1
  104. package/dist/versioned-package/components/checkbox/checkbox.js +3 -3
  105. package/dist/versioned-package/components/checkbox-group/checkbox-group.d.ts +1 -1
  106. package/dist/versioned-package/components/checkbox-group/checkbox-group.js +5 -5
  107. package/dist/versioned-package/components/combobox/combobox.d.ts +129 -0
  108. package/dist/versioned-package/components/combobox/combobox.js +958 -0
  109. package/dist/versioned-package/components/combobox/option-renderer.d.ts +5 -0
  110. package/dist/versioned-package/components/combobox/option-renderer.js +4 -0
  111. package/dist/versioned-package/components/combobox/utils.d.ts +8 -0
  112. package/dist/versioned-package/components/combobox/utils.js +14 -0
  113. package/dist/versioned-package/components/dialog/dialog.d.ts +1 -1
  114. package/dist/versioned-package/components/dialog/dialog.js +2 -2
  115. package/dist/versioned-package/components/divider/divider.d.ts +1 -1
  116. package/dist/versioned-package/components/divider/divider.js +2 -2
  117. package/dist/versioned-package/components/drawer/drawer.d.ts +1 -1
  118. package/dist/versioned-package/components/drawer/drawer.js +2 -2
  119. package/dist/versioned-package/components/dropdown/dropdown.d.ts +3 -2
  120. package/dist/versioned-package/components/dropdown/dropdown.js +42 -33
  121. package/dist/versioned-package/components/expandable/expandable.d.ts +1 -1
  122. package/dist/versioned-package/components/expandable/expandable.js +2 -2
  123. package/dist/versioned-package/components/flipcard/flipcard.d.ts +1 -1
  124. package/dist/versioned-package/components/flipcard/flipcard.js +1 -1
  125. package/dist/versioned-package/components/header/header.d.ts +1 -1
  126. package/dist/versioned-package/components/header/header.js +4 -4
  127. package/dist/versioned-package/components/icon/icon.d.ts +1 -1
  128. package/dist/versioned-package/components/icon/icon.js +1 -1
  129. package/dist/versioned-package/components/include/include.d.ts +1 -1
  130. package/dist/versioned-package/components/include/include.js +1 -1
  131. package/dist/versioned-package/components/input/input.d.ts +1 -1
  132. package/dist/versioned-package/components/input/input.js +3 -3
  133. package/dist/versioned-package/components/link/link.d.ts +1 -1
  134. package/dist/versioned-package/components/link/link.js +2 -2
  135. package/dist/versioned-package/components/map-marker/map-marker.d.ts +1 -1
  136. package/dist/versioned-package/components/map-marker/map-marker.js +1 -1
  137. package/dist/versioned-package/components/navigation-item/navigation-item.d.ts +2 -1
  138. package/dist/versioned-package/components/navigation-item/navigation-item.js +9 -6
  139. package/dist/versioned-package/components/notification/notification.d.ts +1 -1
  140. package/dist/versioned-package/components/notification/notification.js +5 -5
  141. package/dist/versioned-package/components/optgroup/optgroup.d.ts +20 -0
  142. package/dist/versioned-package/components/optgroup/optgroup.js +68 -0
  143. package/dist/versioned-package/components/option/option.d.ts +1 -1
  144. package/dist/versioned-package/components/option/option.js +2 -2
  145. package/dist/versioned-package/components/popup/popup.d.ts +1 -1
  146. package/dist/versioned-package/components/popup/popup.js +1 -1
  147. package/dist/versioned-package/components/quickfact/quickfact.d.ts +1 -1
  148. package/dist/versioned-package/components/quickfact/quickfact.js +2 -2
  149. package/dist/versioned-package/components/radio/radio.d.ts +1 -1
  150. package/dist/versioned-package/components/radio/radio.js +2 -2
  151. package/dist/versioned-package/components/radio-button/radio-button.d.ts +1 -1
  152. package/dist/versioned-package/components/radio-button/radio-button.js +2 -2
  153. package/dist/versioned-package/components/radio-group/radio-group.d.ts +2 -2
  154. package/dist/versioned-package/components/radio-group/radio-group.js +13 -13
  155. package/dist/versioned-package/components/scrollable/scrollable.d.ts +1 -1
  156. package/dist/versioned-package/components/scrollable/scrollable.js +3 -3
  157. package/dist/versioned-package/components/select/select.d.ts +9 -5
  158. package/dist/versioned-package/components/select/select.js +115 -50
  159. package/dist/versioned-package/components/spinner/spinner.d.ts +1 -1
  160. package/dist/versioned-package/components/spinner/spinner.js +1 -1
  161. package/dist/versioned-package/components/step/step.d.ts +1 -1
  162. package/dist/versioned-package/components/step/step.js +2 -2
  163. package/dist/versioned-package/components/step-group/step-group.d.ts +1 -1
  164. package/dist/versioned-package/components/step-group/step-group.js +2 -2
  165. package/dist/versioned-package/components/switch/switch.d.ts +1 -1
  166. package/dist/versioned-package/components/switch/switch.js +1 -1
  167. package/dist/versioned-package/components/tab/tab.d.ts +1 -1
  168. package/dist/versioned-package/components/tab/tab.js +2 -2
  169. package/dist/versioned-package/components/tab-group/tab-group.d.ts +1 -1
  170. package/dist/versioned-package/components/tab-group/tab-group.js +13 -13
  171. package/dist/versioned-package/components/tab-panel/tab-panel.d.ts +1 -1
  172. package/dist/versioned-package/components/tab-panel/tab-panel.js +2 -2
  173. package/dist/versioned-package/components/tag/tag.d.ts +1 -1
  174. package/dist/versioned-package/components/tag/tag.js +2 -2
  175. package/dist/versioned-package/components/teaser/teaser.js +1 -1
  176. package/dist/versioned-package/components/teaser-media/teaser-media.js +1 -1
  177. package/dist/versioned-package/components/textarea/textarea.d.ts +1 -1
  178. package/dist/versioned-package/components/textarea/textarea.js +2 -2
  179. package/dist/versioned-package/components/tooltip/tooltip.d.ts +1 -1
  180. package/dist/versioned-package/components/tooltip/tooltip.js +5 -5
  181. package/dist/versioned-package/components/video/video.d.ts +1 -1
  182. package/dist/versioned-package/components/video/video.js +2 -2
  183. package/dist/versioned-package/internal/form.js +3 -3
  184. package/dist/versioned-package/internal/tabbable.js +1 -1
  185. package/dist/versioned-package/solid-components.d.ts +2 -0
  186. package/dist/versioned-package/solid-components.js +74 -70
  187. package/dist/versioned-package/styles/headline/headline.css.js +1 -1
  188. package/dist/versioned-package/styles/tailwind.css.js +1 -1
  189. package/dist/versioned-package/translations/de.js +7 -4
  190. package/dist/versioned-package/translations/en.js +7 -4
  191. package/dist/versioned-package/utilities/autocomplete-config.js +4 -4
  192. package/dist/versioned-package/utilities/localize.d.ts +3 -0
  193. package/dist/versioned-styles/solid-styles.css +1 -1
  194. package/dist/vscode.html-custom-data.json +373 -47
  195. package/dist/web-types.json +3335 -1813
  196. package/package.json +3 -3
@@ -0,0 +1,5 @@
1
+ import type { TemplateResult } from 'lit';
2
+ import type SdOption from '../option/option.js';
3
+ export type OptionRenderer = (option: SdOption, query?: string) => TemplateResult | string | HTMLElement;
4
+ export declare const defaultOptionRenderer: OptionRenderer;
5
+ export declare const highlightOptionRenderer: OptionRenderer;
@@ -0,0 +1,4 @@
1
+ const defaultOptionRenderer = (option) => option;
2
+ export {
3
+ defaultOptionRenderer
4
+ };
@@ -0,0 +1,8 @@
1
+ import type SdOptGroup from '../optgroup/optgroup.js';
2
+ import type SdOption from '../option/option.js';
3
+ export declare const getAssignedElementsForSlot: (slot: HTMLSlotElement) => HTMLElement[];
4
+ export declare const getOptionOrNestedOptions: (item: HTMLElement) => SdOption | SdOption[];
5
+ export declare const isOptgroup: (item: HTMLElement) => item is SdOptGroup;
6
+ export declare const getAllOptions: (items: HTMLElement[]) => (SdOption | SdOption[])[];
7
+ export declare const filterOnlyOptgroups: (items: HTMLElement[]) => SdOptGroup[];
8
+ export declare const normalizeString: (str: string) => string;
@@ -0,0 +1,14 @@
1
+ const getAssignedElementsForSlot = (slot) => Array.from(slot.assignedElements({ flatten: true }));
2
+ const getOptionOrNestedOptions = (item) => item.tagName.toLocaleLowerCase() === "sd-option" ? item : Array.from(item.querySelectorAll(":scope > sd-option"));
3
+ const isOptgroup = (item) => item.tagName.toLocaleLowerCase() === "sd-optgroup";
4
+ const getAllOptions = (items) => items.map(getOptionOrNestedOptions);
5
+ const filterOnlyOptgroups = (items) => items.filter(isOptgroup);
6
+ const normalizeString = (str) => str.normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLowerCase();
7
+ export {
8
+ filterOnlyOptgroups,
9
+ getAllOptions,
10
+ getAssignedElementsForSlot,
11
+ getOptionOrNestedOptions,
12
+ isOptgroup,
13
+ normalizeString
14
+ };
@@ -22,6 +22,8 @@ export default class SdDropdown extends SolidElement {
22
22
  connectedCallback(): void;
23
23
  firstUpdated(): void;
24
24
  disconnectedCallback(): void;
25
+ getAccessibleTrigger(): HTMLElement | null;
26
+ updateAccessibleTrigger(): void;
25
27
  focusOnTrigger(): void;
26
28
  getMenu(): SdMenu | undefined;
27
29
  handleKeyDown(event: KeyboardEvent): void;
@@ -33,7 +35,6 @@ export default class SdDropdown extends SolidElement {
33
35
  handleTriggerKeyDown(event: KeyboardEvent): void;
34
36
  handleTriggerKeyUp(event: KeyboardEvent): void;
35
37
  handleTriggerSlotChange(): void;
36
- updateAccessibleTrigger(): void;
37
38
  show(): Promise<void>;
38
39
  hide(): Promise<void>;
39
40
  reposition(): void;
@@ -60,8 +60,44 @@ let SdDropdown = class extends SolidElement {
60
60
  this.removeOpenListeners();
61
61
  this.hide();
62
62
  }
63
+ /**
64
+ * Slotted triggers can be arbitrary content. The accessible trigger is the tabbable element
65
+ * within the slotted trigger. This could be the slotted element itself, a child of the slotted element,
66
+ * or an element within the slotted elements shadow root.
67
+ *
68
+ * e.g. the accessible trigger of an <sd-button> is a <button> located inside its shadow root.
69
+ *
70
+ * To determine this, we assume the first tabbable element in the trigger slot is the "accessible trigger."
71
+ * */
72
+ getAccessibleTrigger() {
73
+ const assignedElements = this.trigger.assignedElements({ flatten: true });
74
+ const accessibleTrigger = assignedElements.find((el) => getTabbableBoundary(el).start);
75
+ let target = null;
76
+ if (accessibleTrigger) {
77
+ switch (accessibleTrigger.tagName.toLowerCase()) {
78
+ case "sd-button":
79
+ case "sd-icon-button":
80
+ target = accessibleTrigger.button;
81
+ break;
82
+ case "sd-navigation-item":
83
+ target = accessibleTrigger.button;
84
+ break;
85
+ default:
86
+ target = accessibleTrigger;
87
+ }
88
+ }
89
+ return target;
90
+ }
91
+ // Slotted triggers can be arbitrary content, but we need to connect them to the dropdown panel with `aria-haspopup` and
92
+ // `aria-expanded`. These must be applied to the `accessible trigger`.
93
+ updateAccessibleTrigger() {
94
+ const target = this.getAccessibleTrigger();
95
+ if (!target) return;
96
+ target.setAttribute("aria-haspopup", "true");
97
+ target.setAttribute("aria-expanded", this.open ? "true" : "false");
98
+ }
63
99
  focusOnTrigger() {
64
- const trigger = this.trigger.assignedElements({ flatten: true })[0];
100
+ const trigger = this.getAccessibleTrigger();
65
101
  if (typeof (trigger == null ? void 0 : trigger.focus) === "function") {
66
102
  trigger.focus();
67
103
  }
@@ -163,33 +199,6 @@ let SdDropdown = class extends SolidElement {
163
199
  handleTriggerSlotChange() {
164
200
  this.updateAccessibleTrigger();
165
201
  }
166
- //
167
- // Slotted triggers can be arbitrary content, but we need to link them to the dropdown panel with `aria-haspopup` and
168
- // `aria-expanded`. These must be applied to the "accessible trigger" (the tabbable portion of the trigger element
169
- // that gets slotted in) so screen readers will understand them. The accessible trigger could be the slotted element,
170
- // a child of the slotted element, or an element in the slotted element's shadow root.
171
- //
172
- // For example, the accessible trigger of an <sd-button> is a <button> located inside its shadow root.
173
- //
174
- // To determine this, we assume the first tabbable element in the trigger slot is the "accessible trigger."
175
- //
176
- updateAccessibleTrigger() {
177
- const assignedElements = this.trigger.assignedElements({ flatten: true });
178
- const accessibleTrigger = assignedElements.find((el) => getTabbableBoundary(el).start);
179
- let target;
180
- if (accessibleTrigger) {
181
- switch (accessibleTrigger.tagName.toLowerCase()) {
182
- case "sd-button":
183
- case "sd-icon-button":
184
- target = accessibleTrigger.button;
185
- break;
186
- default:
187
- target = accessibleTrigger;
188
- }
189
- target.setAttribute("aria-haspopup", "true");
190
- target.setAttribute("aria-expanded", this.open ? "true" : "false");
191
- }
192
- }
193
202
  /** Shows the dropdown panel. */
194
203
  async show() {
195
204
  if (this.open) {
@@ -1,6 +1,7 @@
1
1
  import SolidElement from '../../internal/solid-element';
2
2
  export default class SdNavigationItem extends SolidElement {
3
3
  private readonly hasSlotController;
4
+ button: HTMLButtonElement | HTMLLinkElement | null;
4
5
  vertical: boolean;
5
6
  size: 'base' | 'lg' | 'sm';
6
7
  href: string;
@@ -3,7 +3,7 @@ import { customElement } from "../../internal/register-custom-element.js";
3
3
  import { HasSlotController } from "../../internal/slot.js";
4
4
  import { literal, html } from "lit/static-html.js";
5
5
  import { ifDefined } from "lit/directives/if-defined.js";
6
- import { property } from "lit/decorators.js";
6
+ import { query, property } from "lit/decorators.js";
7
7
  import componentStyles from "../../styles/component.styles.js";
8
8
  import cx from "classix";
9
9
  import InteractiveStyles from "../../styles/interactive/interactive.css.js";
@@ -145,6 +145,9 @@ SdNavigationItem.styles = [
145
145
  unsafeCSS(InteractiveStyles),
146
146
  css`:host{position:relative;box-sizing:border-box;display:inline-block}:host([vertical]){display:block}details summary::-webkit-details-marker{display:none}`
147
147
  ];
148
+ __decorateClass([
149
+ query('a[part="base"], button[part="base"]')
150
+ ], SdNavigationItem.prototype, "button", 2);
148
151
  __decorateClass([
149
152
  property({ type: Boolean, reflect: true })
150
153
  ], SdNavigationItem.prototype, "vertical", 2);
@@ -0,0 +1,20 @@
1
+ import SdDivider from '../divider/divider';
2
+ import SolidElement from '../../internal/solid-element';
3
+ import type { CSSResultGroup } from 'lit';
4
+ export default class SdOptgroup extends SolidElement {
5
+ static dependencies: {
6
+ 'sd-divider': typeof SdDivider;
7
+ };
8
+ defaultSlot: HTMLSlotElement;
9
+ private handleDisableOptions;
10
+ disabled: boolean;
11
+ label: string;
12
+ handleDisabledChange(): void;
13
+ render(): import("lit").TemplateResult;
14
+ static styles: CSSResultGroup;
15
+ }
16
+ declare global {
17
+ interface HTMLElementTagNameMap {
18
+ 'sd-optgroup': SdOptgroup;
19
+ }
20
+ }
@@ -0,0 +1,68 @@
1
+ import { css } from "lit";
2
+ import { customElement } from "../../internal/register-custom-element.js";
3
+ import { html } from "lit/static-html.js";
4
+ import { query, property } from "lit/decorators.js";
5
+ import { watch } from "../../internal/watch.js";
6
+ import componentStyles from "../../styles/component.styles.js";
7
+ import cx from "classix";
8
+ import SdDivider from "../divider/divider.js";
9
+ import SolidElement from "../../internal/solid-element.js";
10
+ var __defProp = Object.defineProperty;
11
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
12
+ var __decorateClass = (decorators, target, key, kind) => {
13
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
14
+ for (var i = decorators.length - 1, decorator; i >= 0; i--)
15
+ if (decorator = decorators[i])
16
+ result = (kind ? decorator(target, key, result) : decorator(result)) || result;
17
+ if (kind && result) __defProp(target, key, result);
18
+ return result;
19
+ };
20
+ let SdOptgroup = class extends SolidElement {
21
+ constructor() {
22
+ super(...arguments);
23
+ this.disabled = false;
24
+ this.label = "";
25
+ }
26
+ /**
27
+ * Syncs the disabled prop for all slotted sd-options when it is triggered
28
+ */
29
+ handleDisableOptions() {
30
+ const { disabled } = this;
31
+ this.defaultSlot.assignedElements().filter((opt) => opt.tagName.toLowerCase() === "sd-option").forEach((opt) => {
32
+ opt.disabled = disabled;
33
+ });
34
+ }
35
+ handleDisabledChange() {
36
+ this.handleDisableOptions();
37
+ }
38
+ render() {
39
+ const { disabled } = this;
40
+ return html`<div role="${disabled ? "presentation" : "group"}" class="${cx(this.disabled ? "text-neutral-500" : "")}" part="base" aria-labelledby="group-label"><sd-divider id="divider" class="pt-2 pb-4" part="divider"></sd-divider><div part="label-container" class="${cx(this.disabled ? "text-neutral-500" : "text-black")} px-4 font-bold text-left" role="presentation" id="group-label"><slot name="label"><span>${this.label}</span></slot></div><div role="group" part="options"><slot @slotchange="${this.handleDisableOptions}"></slot></div></div>`;
41
+ }
42
+ };
43
+ SdOptgroup.dependencies = {
44
+ "sd-divider": SdDivider
45
+ };
46
+ SdOptgroup.styles = [
47
+ componentStyles,
48
+ SolidElement.styles,
49
+ css`:host{--display-divider:block}#divider{display:var(--display-divider)}`
50
+ ];
51
+ __decorateClass([
52
+ query("slot:not([name])")
53
+ ], SdOptgroup.prototype, "defaultSlot", 2);
54
+ __decorateClass([
55
+ property({ reflect: true, type: Boolean })
56
+ ], SdOptgroup.prototype, "disabled", 2);
57
+ __decorateClass([
58
+ property()
59
+ ], SdOptgroup.prototype, "label", 2);
60
+ __decorateClass([
61
+ watch("disabled", { waitUntilFirstUpdate: true })
62
+ ], SdOptgroup.prototype, "handleDisabledChange", 1);
63
+ SdOptgroup = __decorateClass([
64
+ customElement("sd-optgroup")
65
+ ], SdOptgroup);
66
+ export {
67
+ SdOptgroup as default
68
+ };
@@ -55,6 +55,7 @@ export default class SdSelect extends SolidElement implements SolidFormControl {
55
55
  get validity(): ValidityState;
56
56
  get validationMessage(): string;
57
57
  connectedCallback(): void;
58
+ firstUpdated(): void;
58
59
  private addOpenListeners;
59
60
  private removeOpenListeners;
60
61
  private handleFocus;
@@ -62,10 +63,13 @@ export default class SdSelect extends SolidElement implements SolidFormControl {
62
63
  private handleDocumentFocusIn;
63
64
  private handleDocumentKeyDown;
64
65
  private handleDocumentMouseDown;
66
+ private handleTagKeyDown;
67
+ private handleTagMaxOptionsKeyDown;
65
68
  private handleLabelClick;
66
69
  private handleComboboxMouseDown;
67
70
  private handleComboboxKeyDown;
68
71
  private handleClearClick;
72
+ private clearSelect;
69
73
  private handleClearMouseDown;
70
74
  private handleOptionClick;
71
75
  private handleDefaultSlotChange;
@@ -76,7 +80,7 @@ export default class SdSelect extends SolidElement implements SolidFormControl {
76
80
  private setSelectedOptions;
77
81
  private toggleOptionSelection;
78
82
  private selectionChanged;
79
- protected get tags(): TemplateResult<1>[];
83
+ protected get tags(): (TemplateResult<1> | TemplateResult<1>[])[];
80
84
  private handleInvalid;
81
85
  private handleMouseEnter;
82
86
  private handleMouseLeave;
@@ -67,7 +67,7 @@ let SdSelect = class extends SolidElement {
67
67
  base:tag__base,
68
68
  content:tag__content,
69
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>`;
70
+ " size="${this.size === "sm" ? "sm" : "lg"}" removable @keydown="${(event) => this.handleTagKeyDown(event, option)}" @sd-remove="${(event) => this.handleTagRemove(event, option)}">${option.getTextLabel()}</sd-tag>`;
71
71
  };
72
72
  this.handleDocumentFocusIn = (event) => {
73
73
  const path = event.composedPath();
@@ -182,9 +182,11 @@ let SdSelect = class extends SolidElement {
182
182
  }
183
183
  connectedCallback() {
184
184
  super.connectedCallback();
185
- this.applySizeToOptions();
186
185
  this.open = false;
187
186
  }
187
+ firstUpdated() {
188
+ this.applySizeToOptions();
189
+ }
188
190
  addOpenListeners() {
189
191
  document.addEventListener("focusin", this.handleDocumentFocusIn);
190
192
  document.addEventListener("keydown", this.handleDocumentKeyDown);
@@ -204,6 +206,40 @@ let SdSelect = class extends SolidElement {
204
206
  this.hasFocus = false;
205
207
  this.emit("sd-blur");
206
208
  }
209
+ handleTagKeyDown(event, option) {
210
+ var _a, _b, _c;
211
+ if (event.key === "Backspace" && this.multiple) {
212
+ event.stopPropagation();
213
+ const tagParent = (_a = event.currentTarget) == null ? void 0 : _a.parentElement;
214
+ const previousTag = (_b = tagParent == null ? void 0 : tagParent.previousElementSibling) == null ? void 0 : _b.querySelector("sd-tag");
215
+ const nextTag = (_c = tagParent == null ? void 0 : tagParent.nextElementSibling) == null ? void 0 : _c.querySelector("sd-tag");
216
+ this.handleTagRemove(new CustomEvent("sd-remove"), option);
217
+ this.updateComplete.then(() => {
218
+ if (nextTag) {
219
+ nextTag.focus();
220
+ } else if (previousTag) {
221
+ previousTag.focus();
222
+ } else {
223
+ this.focus({ preventScroll: true });
224
+ }
225
+ });
226
+ }
227
+ }
228
+ handleTagMaxOptionsKeyDown(event) {
229
+ if (event.key === "Backspace" && this.multiple) {
230
+ event.stopPropagation();
231
+ this.handleTagRemove(new CustomEvent("sd-remove"), this.selectedOptions[this.selectedOptions.length - 1]);
232
+ this.updateComplete.then(() => {
233
+ var _a;
234
+ const tags = (_a = this.shadowRoot) == null ? void 0 : _a.querySelectorAll("sd-tag");
235
+ if (tags && tags.length > 0) {
236
+ tags == null ? void 0 : tags[(tags == null ? void 0 : tags.length) - 1].focus();
237
+ } else {
238
+ this.focus({ preventScroll: true });
239
+ }
240
+ });
241
+ }
242
+ }
207
243
  handleLabelClick() {
208
244
  this.displayInput.focus();
209
245
  }
@@ -223,15 +259,16 @@ let SdSelect = class extends SolidElement {
223
259
  }
224
260
  handleClearClick(event) {
225
261
  event.stopPropagation();
226
- if (this.value !== "") {
227
- this.setSelectedOptions([]);
228
- this.displayInput.focus({ preventScroll: true });
229
- this.updateComplete.then(() => {
230
- this.emit("sd-clear");
231
- this.emit("sd-input");
232
- this.emit("sd-change");
233
- });
234
- }
262
+ this.clearSelect();
263
+ }
264
+ clearSelect() {
265
+ this.setSelectedOptions([]);
266
+ this.displayInput.focus({ preventScroll: true });
267
+ this.updateComplete.then(() => {
268
+ this.emit("sd-clear");
269
+ this.emit("sd-input");
270
+ this.emit("sd-change");
271
+ });
235
272
  }
236
273
  handleClearMouseDown(event) {
237
274
  event.stopPropagation();
@@ -278,7 +315,10 @@ let SdSelect = class extends SolidElement {
278
315
  }
279
316
  handleTagRemove(event, option) {
280
317
  event.stopPropagation();
281
- if (!this.disabled) {
318
+ if (!option) {
319
+ this.clearSelect();
320
+ }
321
+ if (option && !this.disabled) {
282
322
  this.toggleOptionSelection(option, false);
283
323
  this.deletedTagLabel = this.localize.term("removed", option.textContent);
284
324
  this.updateComplete.then(() => {
@@ -318,7 +358,11 @@ let SdSelect = class extends SolidElement {
318
358
  if (newSelectedOptions.length) {
319
359
  newSelectedOptions.forEach((el) => el.selected = true);
320
360
  }
321
- this.selectionChanged();
361
+ if (Array.isArray(option)) {
362
+ this.selectionChanged();
363
+ } else {
364
+ this.selectionChanged(option);
365
+ }
322
366
  }
323
367
  // Toggles an option's selected state
324
368
  toggleOptionSelection(option, force) {
@@ -327,13 +371,25 @@ let SdSelect = class extends SolidElement {
327
371
  } else {
328
372
  option.selected = !option.selected;
329
373
  }
330
- this.selectionChanged();
374
+ if (Array.isArray(option)) {
375
+ this.selectionChanged();
376
+ } else {
377
+ this.selectionChanged(option);
378
+ }
331
379
  }
332
380
  // This method must be called whenever the selection changes. It will update the selected options cache, the current
333
381
  // value, and the display value
334
- selectionChanged() {
382
+ selectionChanged(option) {
335
383
  var _a, _b;
336
- this.selectedOptions = this.getAllOptions().filter((el) => el.selected);
384
+ if (option && this.multiple) {
385
+ if (this.selectedOptions.find((el) => el.value === option.value)) {
386
+ this.selectedOptions = this.selectedOptions.filter((el) => el.value !== option.value);
387
+ } else {
388
+ this.selectedOptions = [...this.selectedOptions, option];
389
+ }
390
+ } else {
391
+ this.selectedOptions = this.getAllOptions().filter((el) => el.selected);
392
+ }
337
393
  if (this.multiple) {
338
394
  this.value = this.selectedOptions.map((el) => el.value);
339
395
  if (this.useTags || this.value.length === 0) {
@@ -350,15 +406,23 @@ let SdSelect = class extends SolidElement {
350
406
  });
351
407
  }
352
408
  get tags() {
353
- return this.selectedOptions.map((option, index) => {
354
- if (index < this.maxOptionsVisible || this.maxOptionsVisible <= 0) {
355
- const tag = this.getTag(option, index);
356
- return html`<div @sd-remove="${(e) => this.handleTagRemove(e, option)}">${typeof tag === "string" ? unsafeHTML(tag) : tag}</div>`;
357
- } else if (index === this.maxOptionsVisible) {
358
- return html`<sd-tag size="${this.size === "sm" ? "sm" : "lg"}" ?disabled="${this.disabled}">+${this.selectedOptions.length - index}</sd-tag>`;
359
- }
360
- return html``;
361
- });
409
+ if (this.selectedOptions.length <= this.maxOptionsVisible) {
410
+ return this.selectedOptions.map((option, index) => {
411
+ if (index < this.maxOptionsVisible || this.maxOptionsVisible <= 0) {
412
+ const tag = this.getTag(option, index);
413
+ return html`<div @sd-remove="${(e) => this.handleTagRemove(e, option)}">${typeof tag === "string" ? unsafeHTML(tag) : tag}</div>`;
414
+ }
415
+ return [html``];
416
+ });
417
+ } else {
418
+ return [
419
+ html`<sd-tag ?disabled="${this.disabled}" part="tag" exportparts="
420
+ base:tag__base,
421
+ content:tag__content,
422
+ removable-indicator:tag__removable-indicator,
423
+ " size="${this.size === "sm" ? "sm" : "lg"}" removable @keydown="${(event) => this.handleTagMaxOptionsKeyDown(event)}" @sd-remove="${(event) => this.handleTagRemove(event)}">${this.selectedOptions.length} ${this.localize.term("tagsSelected")}</sd-tag>`
424
+ ];
425
+ }
362
426
  }
363
427
  handleInvalid(event) {
364
428
  this.formControlController.setValidity(false);
@@ -394,7 +458,7 @@ let SdSelect = class extends SolidElement {
394
458
  }
395
459
  async handleOpenChange() {
396
460
  if (this.open && !this.disabled) {
397
- this.setCurrentOption(this.selectedOptions[0] || this.getFirstOption());
461
+ if (!this.multiple) this.setCurrentOption(this.selectedOptions[0] || this.getFirstOption());
398
462
  this.emit("sd-show");
399
463
  this.addOpenListeners();
400
464
  await stopAnimations(this);
@@ -426,6 +490,7 @@ let SdSelect = class extends SolidElement {
426
490
  });
427
491
  }
428
492
  handleValueChange() {
493
+ if (this.selectedOptions.length === (Array.isArray(this.value) ? this.value.length : 1)) return;
429
494
  const allOptions = this.getAllOptions();
430
495
  const value = Array.isArray(this.value) ? this.value : [this.value];
431
496
  this.setSelectedOptions(allOptions.filter((el) => value.includes(el.value)));
@@ -530,13 +595,13 @@ let SdSelect = class extends SolidElement {
530
595
  "appearance-none outline-none flex-grow bg-transparent w-full placeholder-neutral-700",
531
596
  cursorStyles,
532
597
  this.multiple && this.useTags && this.value.length > 0 ? "hidden" : ""
533
- )}" 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-invalid="${this.showInvalidStyle}" aria-describedby="help-text invalid-message" 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-icon-fill-neutral-800", iconSize)}" library="system" name="closing-round"></sd-icon></slot></button>` : ""} ${this.showInvalidStyle ? html`<sd-icon part="invalid-icon" class="${cx(iconMarginLeft, iconSize, "text-error")}" library="system" name="risk"></sd-icon>` : ""} ${this.styleOnValid && this.showValidStyle ? html`<sd-icon part="valid-icon" class="${cx("flex-shrink-0 text-success", iconMarginLeft, iconSize)}" library="system" name="status-check"></sd-icon>` : ""}<slot name="expand-icon" part="expand-icon" class="${cx(
598
+ )}" 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-invalid="${this.showInvalidStyle}" aria-describedby="help-text invalid-message" 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>` : ""}<div aria-live="polite" id="control-value" class="absolute top-0 left-0 opacity-0 -z-10">${this.selectedOptions.map((option) => option == null ? void 0 : option.getTextLabel()).join(", ")}</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-controls="control-value" 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-icon-fill-neutral-800", iconSize)}" library="system" name="closing-round"></sd-icon></slot></button>` : ""} ${this.showInvalidStyle ? html`<sd-icon part="invalid-icon" class="${cx(iconMarginLeft, iconSize, "text-error")}" library="system" name="risk"></sd-icon>` : ""} ${this.styleOnValid && this.showValidStyle ? html`<sd-icon part="valid-icon" class="${cx("flex-shrink-0 text-success", iconMarginLeft, iconSize)}" library="system" name="status-check"></sd-icon>` : ""}<slot name="expand-icon" part="expand-icon" class="${cx(
534
599
  "inline-flex ml-2 transition-all",
535
600
  this.open ? "rotate-180" : "rotate-0",
536
601
  this.disabled ? "text-neutral-500" : "text-primary",
537
602
  iconSize
538
603
  )}"><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(
539
- "bg-white px-2 py-3 relative border-primary overflow-y-auto",
604
+ "bg-white px-2 py-3 relative border-primary overflow-y-scroll",
540
605
  this.open && "shadow",
541
606
  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"
542
607
  )}" 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>${this.formControlController.renderInvalidMessage()}`;
@@ -550,7 +615,7 @@ SdSelect.dependencies = {
550
615
  SdSelect.styles = [
551
616
  componentStyles,
552
617
  SolidElement.styles,
553
- css`:host{position:relative;display:block;width:100%}:host([required]) #label::after{content:' *'}[part=listbox]{max-height:var(--auto-size-available-height,auto)}sd-popup::part(popup){z-index:var(--sd-z-index-dropdown,900);overflow-y:scroll}sd-tag::part(base){border-radius:var(--sd-border-radius-default,.25rem);padding-left:var(--sd-spacing-1,.25rem);padding-right:var(--sd-spacing-1,.25rem)}sd-tag[size=lg]::part(base){padding-left:var(--sd-spacing-2,.5rem);padding-right:var(--sd-spacing-2,.5rem)}sd-tag[disabled=false]::part(base):hover{--tw-bg-opacity:1;background-color:rgb(var(--sd-color-primary-100,236 240 249) / var(--tw-bg-opacity))}`
618
+ css`:host{position:relative;display:block;width:100%}:host([required]) #label::after{content:' *'}[part=listbox]{max-height:var(--auto-size-available-height,auto)}sd-popup::part(popup){z-index:var(--sd-z-index-dropdown,900)}sd-tag::part(base){border-radius:var(--sd-border-radius-default,.25rem);padding-left:var(--sd-spacing-1,.25rem);padding-right:var(--sd-spacing-1,.25rem)}sd-tag[size=lg]::part(base){padding-left:var(--sd-spacing-2,.5rem);padding-right:var(--sd-spacing-2,.5rem)}sd-tag[disabled=false]::part(base):hover{--tw-bg-opacity:1;background-color:rgb(var(--sd-color-primary-100,236 240 249) / var(--tw-bg-opacity))}`
554
619
  ];
555
620
  __decorateClass([
556
621
  queryAssignedElements({ selector: "sd-option" })
@@ -12,7 +12,7 @@ function isTabbable(el) {
12
12
  if (tag === "input" && el.getAttribute("type") === "radio" && !el.hasAttribute("checked")) {
13
13
  return false;
14
14
  }
15
- if (el.offsetParent === null) {
15
+ if (el.offsetParent === null && !(el.getRootNode() instanceof ShadowRoot)) {
16
16
  return false;
17
17
  }
18
18
  if (window.getComputedStyle(el).visibility === "hidden") {
@@ -8,6 +8,7 @@ export { default as SdCarousel } from './components/carousel/carousel';
8
8
  export { default as SdCarouselItem } from './components/carousel-item/carousel-item';
9
9
  export { default as SdCheckbox } from './components/checkbox/checkbox';
10
10
  export { default as SdCheckboxGroup } from './components/checkbox-group/checkbox-group';
11
+ export { default as SdCombobox } from './components/combobox/combobox';
11
12
  export { default as SdDialog } from './components/dialog/dialog';
12
13
  export { default as SdDivider } from './components/divider/divider';
13
14
  export { default as SdDrawer } from './components/drawer/drawer';
@@ -22,6 +23,7 @@ export { default as SdLink } from './components/link/link';
22
23
  export { default as SdMapMarker } from './components/map-marker/map-marker';
23
24
  export { default as SdNavigationItem } from './components/navigation-item/navigation-item';
24
25
  export { default as SdNotification } from './components/notification/notification';
26
+ export { default as SdOptgroup } from './components/optgroup/optgroup';
25
27
  export { default as SdOption } from './components/option/option';
26
28
  export { default as SdPopup } from './components/popup/popup';
27
29
  export { default as SdQuickfact } from './components/quickfact/quickfact';