@solid-design-system/components 3.22.18 → 3.23.1

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 (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';