@solid-design-system/components 1.36.0 → 1.37.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 (147) hide show
  1. package/dist/components/es/checkbox-group.js +1 -1
  2. package/dist/components/es/checkbox.js +1 -1
  3. package/dist/components/es/form.js +1 -1
  4. package/dist/components/es/input.js +1 -1
  5. package/dist/components/es/option.js +1 -1
  6. package/dist/components/es/radio-group.js +1 -1
  7. package/dist/components/es/radio.js +1 -1
  8. package/dist/components/es/select.js +2 -2
  9. package/dist/components/es/solid-element.js +1 -1
  10. package/dist/components/es/switch.js +1 -1
  11. package/dist/components/es/teaser.js +1 -1
  12. package/dist/components/es/textarea.js +1 -1
  13. package/dist/components/umd/solid-components.js +18 -18
  14. package/dist/custom-elements.json +1 -1
  15. package/dist/package/components/checkbox/checkbox.d.ts +2 -0
  16. package/dist/package/components/checkbox/checkbox.js +23 -6
  17. package/dist/package/components/checkbox-group/checkbox-group.js +1 -1
  18. package/dist/package/components/input/input.d.ts +3 -0
  19. package/dist/package/components/input/input.js +20 -19
  20. package/dist/package/components/option/option.js +0 -2
  21. package/dist/package/components/radio/radio.js +3 -3
  22. package/dist/package/components/radio-group/radio-group.d.ts +4 -3
  23. package/dist/package/components/radio-group/radio-group.js +25 -27
  24. package/dist/package/components/select/select.d.ts +3 -3
  25. package/dist/package/components/select/select.js +18 -23
  26. package/dist/package/components/switch/switch.d.ts +2 -0
  27. package/dist/package/components/switch/switch.js +15 -7
  28. package/dist/package/components/teaser/teaser.js +5 -1
  29. package/dist/package/components/textarea/textarea.d.ts +3 -0
  30. package/dist/package/components/textarea/textarea.js +30 -24
  31. package/dist/package/internal/form.d.ts +3 -1
  32. package/dist/package/internal/form.js +38 -10
  33. package/dist/package/internal/solid-element.d.ts +2 -0
  34. package/dist/package/styles/tailwind.css.js +1 -1
  35. package/dist/versioned-components/es/accordion-group.js +1 -1
  36. package/dist/versioned-components/es/accordion.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/divider.js +1 -1
  45. package/dist/versioned-components/es/drawer.js +1 -1
  46. package/dist/versioned-components/es/dropdown.js +1 -1
  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 +1 -1
  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/navigation-item.js +1 -1
  54. package/dist/versioned-components/es/notification.js +1 -1
  55. package/dist/versioned-components/es/option.js +1 -1
  56. package/dist/versioned-components/es/popup.js +1 -1
  57. package/dist/versioned-components/es/radio-button.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/select.js +2 -2
  61. package/dist/versioned-components/es/solid-element.js +1 -1
  62. package/dist/versioned-components/es/spinner.js +1 -1
  63. package/dist/versioned-components/es/switch.js +1 -1
  64. package/dist/versioned-components/es/tag.js +1 -1
  65. package/dist/versioned-components/es/teaser.js +1 -1
  66. package/dist/versioned-components/es/textarea.js +1 -1
  67. package/dist/versioned-components/es/tooltip.js +2 -2
  68. package/dist/versioned-components/es/video.js +1 -1
  69. package/dist/versioned-package/_components/button-group/button-group.d.ts +1 -1
  70. package/dist/versioned-package/_components/button-group/button-group.js +11 -11
  71. package/dist/versioned-package/components/accordion/accordion.d.ts +1 -1
  72. package/dist/versioned-package/components/accordion/accordion.js +2 -2
  73. package/dist/versioned-package/components/accordion-group/accordion-group.d.ts +1 -1
  74. package/dist/versioned-package/components/accordion-group/accordion-group.js +3 -3
  75. package/dist/versioned-package/components/badge/badge.d.ts +1 -1
  76. package/dist/versioned-package/components/badge/badge.js +1 -1
  77. package/dist/versioned-package/components/brandshape/brandshape.d.ts +1 -1
  78. package/dist/versioned-package/components/brandshape/brandshape.js +1 -1
  79. package/dist/versioned-package/components/button/button.d.ts +1 -1
  80. package/dist/versioned-package/components/button/button.js +4 -4
  81. package/dist/versioned-package/components/carousel/carousel.d.ts +1 -1
  82. package/dist/versioned-package/components/carousel/carousel.js +6 -6
  83. package/dist/versioned-package/components/carousel-item/carousel-item.d.ts +1 -1
  84. package/dist/versioned-package/components/carousel-item/carousel-item.js +1 -1
  85. package/dist/versioned-package/components/checkbox/checkbox.d.ts +3 -1
  86. package/dist/versioned-package/components/checkbox/checkbox.js +27 -10
  87. package/dist/versioned-package/components/checkbox-group/checkbox-group.d.ts +1 -1
  88. package/dist/versioned-package/components/checkbox-group/checkbox-group.js +6 -6
  89. package/dist/versioned-package/components/divider/divider.d.ts +1 -1
  90. package/dist/versioned-package/components/divider/divider.js +2 -2
  91. package/dist/versioned-package/components/drawer/drawer.d.ts +1 -1
  92. package/dist/versioned-package/components/drawer/drawer.js +2 -2
  93. package/dist/versioned-package/components/dropdown/dropdown.d.ts +1 -1
  94. package/dist/versioned-package/components/dropdown/dropdown.js +8 -8
  95. package/dist/versioned-package/components/header/header.d.ts +1 -1
  96. package/dist/versioned-package/components/header/header.js +4 -4
  97. package/dist/versioned-package/components/icon/icon.d.ts +1 -1
  98. package/dist/versioned-package/components/icon/icon.js +1 -1
  99. package/dist/versioned-package/components/include/include.d.ts +1 -1
  100. package/dist/versioned-package/components/include/include.js +1 -1
  101. package/dist/versioned-package/components/input/input.d.ts +4 -1
  102. package/dist/versioned-package/components/input/input.js +23 -22
  103. package/dist/versioned-package/components/link/link.d.ts +1 -1
  104. package/dist/versioned-package/components/link/link.js +2 -2
  105. package/dist/versioned-package/components/navigation-item/navigation-item.d.ts +1 -1
  106. package/dist/versioned-package/components/navigation-item/navigation-item.js +3 -3
  107. package/dist/versioned-package/components/notification/notification.d.ts +1 -1
  108. package/dist/versioned-package/components/notification/notification.js +5 -5
  109. package/dist/versioned-package/components/option/option.d.ts +1 -1
  110. package/dist/versioned-package/components/option/option.js +2 -4
  111. package/dist/versioned-package/components/popup/popup.d.ts +1 -1
  112. package/dist/versioned-package/components/popup/popup.js +1 -1
  113. package/dist/versioned-package/components/radio/radio.d.ts +1 -1
  114. package/dist/versioned-package/components/radio/radio.js +5 -5
  115. package/dist/versioned-package/components/radio-button/radio-button.d.ts +1 -1
  116. package/dist/versioned-package/components/radio-button/radio-button.js +2 -2
  117. package/dist/versioned-package/components/radio-group/radio-group.d.ts +6 -5
  118. package/dist/versioned-package/components/radio-group/radio-group.js +38 -40
  119. package/dist/versioned-package/components/select/select.d.ts +7 -7
  120. package/dist/versioned-package/components/select/select.js +44 -49
  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 +3 -1
  124. package/dist/versioned-package/components/switch/switch.js +17 -9
  125. package/dist/versioned-package/components/tag/tag.d.ts +1 -1
  126. package/dist/versioned-package/components/tag/tag.js +2 -2
  127. package/dist/versioned-package/components/teaser/teaser.js +6 -2
  128. package/dist/versioned-package/components/textarea/textarea.d.ts +4 -1
  129. package/dist/versioned-package/components/textarea/textarea.js +32 -26
  130. package/dist/versioned-package/components/tooltip/tooltip.d.ts +1 -1
  131. package/dist/versioned-package/components/tooltip/tooltip.js +5 -5
  132. package/dist/versioned-package/components/video/video.d.ts +1 -1
  133. package/dist/versioned-package/components/video/video.js +2 -2
  134. package/dist/versioned-package/internal/form.d.ts +3 -1
  135. package/dist/versioned-package/internal/form.js +40 -12
  136. package/dist/versioned-package/internal/solid-element.d.ts +2 -0
  137. package/dist/versioned-package/styles/tailwind.css.js +1 -1
  138. package/dist/versioned-styles/solid-styles.css +1 -1
  139. package/dist/vscode.html-custom-data.json +44 -34
  140. package/dist/web-types.json +78 -18
  141. package/package.json +1 -1
  142. package/dist/components/es/form-control.styles.js +0 -1
  143. package/dist/package/styles/form-control.styles.d.ts +0 -2
  144. package/dist/package/styles/form-control.styles.js +0 -5
  145. package/dist/versioned-components/es/form-control.styles.js +0 -1
  146. package/dist/versioned-package/styles/form-control.styles.d.ts +0 -2
  147. package/dist/versioned-package/styles/form-control.styles.js +0 -5
@@ -4,6 +4,7 @@ import type { SolidFormControl } from '../../internal/solid-element';
4
4
  export default class SdCheckbox extends SolidElement implements SolidFormControl {
5
5
  private readonly formControlController;
6
6
  input: HTMLInputElement;
7
+ invalidMessage: HTMLDivElement;
7
8
  title: string;
8
9
  name: string;
9
10
  value: string;
@@ -14,6 +15,7 @@ export default class SdCheckbox extends SolidElement implements SolidFormControl
14
15
  defaultChecked: boolean;
15
16
  form: string;
16
17
  required: boolean;
18
+ showInvalidStyle: boolean;
17
19
  get validity(): ValidityState;
18
20
  firstUpdated(): void;
19
21
  private handleClick;
@@ -5,7 +5,7 @@ import { defaultValue } from "../../internal/default-value.js";
5
5
  import { FormControlController } from "../../internal/form.js";
6
6
  import { ifDefined } from "lit/directives/if-defined.js";
7
7
  import { live } from "lit/directives/live.js";
8
- import { query, property } from "lit/decorators.js";
8
+ import { query, property, state } from "lit/decorators.js";
9
9
  import { watch } from "../../internal/watch.js";
10
10
  import cx from "classix";
11
11
  import SolidElement from "../../internal/solid-element.js";
@@ -37,6 +37,7 @@ let SdCheckbox = class extends SolidElement {
37
37
  this.defaultChecked = false;
38
38
  this.form = "";
39
39
  this.required = false;
40
+ this.showInvalidStyle = false;
40
41
  }
41
42
  /** Gets the validity state object */
42
43
  get validity() {
@@ -59,6 +60,7 @@ let SdCheckbox = class extends SolidElement {
59
60
  handleInvalid(event) {
60
61
  this.formControlController.setValidity(false);
61
62
  this.formControlController.emitInvalidEvent(event);
63
+ this.invalidMessage.textContent = event.target.validationMessage;
62
64
  }
63
65
  handleFocus() {
64
66
  this.emit("sd-focus");
@@ -105,6 +107,7 @@ let SdCheckbox = class extends SolidElement {
105
107
  this.formControlController.updateValidity();
106
108
  }
107
109
  render() {
110
+ const checkboxState = this.disabled && this.indeterminate ? "disabledIndeterminate" : this.disabled && this.checked ? "disabledChecked" : this.disabled ? "disabled" : this.showInvalidStyle && this.indeterminate ? "invalidIndeterminate" : this.showInvalidStyle ? "invalid" : this.checked || this.indeterminate ? "filled" : "default";
108
111
  return html`<label part="base" class="${cx(
109
112
  "sd-checkbox group flex items-start text-base leading-normal text-black cursor-pointer",
110
113
  this.disabled && "hover:cursor-not-allowed",
@@ -121,20 +124,31 @@ let SdCheckbox = class extends SolidElement {
121
124
  sm: "mt-[2px]",
122
125
  lg: "mt-[3px]"
123
126
  }[this.size],
124
- this.disabled && this.indeterminate && "border-neutral-500 bg-neutral-500" || this.disabled && this.checked && "border-neutral-500 bg-neutral-500" || this.disabled && "border-neutral-500" || (this.checked || this.indeterminate) && "border-accent hover:border-accent-550 group-hover:border-accent-550 bg-accent group-hover:bg-accent-550" || "border-neutral-800 hover:bg-neutral-200 group-hover:bg-neutral-200 bg-white"
127
+ {
128
+ disabledIndeterminate: "border-neutral-500 bg-neutral-500",
129
+ disabledChecked: "border-neutral-500 bg-neutral-500",
130
+ disabled: "border-neutral-500",
131
+ invalidIndeterminate: "border-error bg-error group-hover:bg-error-400",
132
+ invalid: "border-error group-hover:bg-neutral-200",
133
+ filled: "border-accent hover:border-accent-550 group-hover:border-accent-550 bg-accent group-hover:bg-accent-550",
134
+ default: "border-neutral-800 hover:bg-neutral-200 group-hover:bg-neutral-200 bg-white"
135
+ }[checkboxState]
125
136
  )}">${this.checked ? html`<sd-icon part="checked-icon" class="text-white w-3 h-3" library="system" name="status-hook"></sd-icon>` : ""} ${!this.checked && this.indeterminate ? html`<sd-icon part="indeterminate-icon" class="text-white w-3 h-3" library="system" name="status-minus"></sd-icon>` : ""} </span><span part="label" id="label" class="${cx(
126
- "select-none inline-block ml-2 text-black",
127
- this.disabled && "text-neutral-500" || "text-neutral-800"
128
- )}"><slot></slot></span></label>`;
137
+ "select-none inline-block ml-2",
138
+ this.disabled ? "text-neutral-500" : this.showInvalidStyle ? "text-error" : "text-black"
139
+ )}"><slot></slot></span></label> ${this.formControlController.renderInvalidMessage()}`;
129
140
  }
130
141
  };
131
142
  SdCheckbox.styles = [
132
143
  SolidElement.styles,
133
- css`:host{display:block}:host(:focus-visible){outline-width:0}:host([required]) #label::after{content:' *'}:host([data-user-invalid]) #label{color:rgb(var(--sd-color-error,204 25 55))}:host([data-user-invalid]) #control{border-color:rgb(var(--sd-color-error,204 25 55))}:host([data-user-invalid]):host([indeterminate]) #control{background-color:rgb(var(--sd-color-error,204 25 55))}`
144
+ css`:host{display:block}:host(:focus-visible){outline-width:0}:host([required]) #label::after{content:' *'}`
134
145
  ];
135
146
  __decorateClass([
136
147
  query('input[type="checkbox"]')
137
148
  ], SdCheckbox.prototype, "input", 2);
149
+ __decorateClass([
150
+ query("#invalid-message")
151
+ ], SdCheckbox.prototype, "invalidMessage", 2);
138
152
  __decorateClass([
139
153
  property()
140
154
  ], SdCheckbox.prototype, "title", 2);
@@ -165,6 +179,9 @@ __decorateClass([
165
179
  __decorateClass([
166
180
  property({ type: Boolean, reflect: true })
167
181
  ], SdCheckbox.prototype, "required", 2);
182
+ __decorateClass([
183
+ state()
184
+ ], SdCheckbox.prototype, "showInvalidStyle", 2);
168
185
  __decorateClass([
169
186
  watch("disabled", { waitUntilFirstUpdate: true })
170
187
  ], SdCheckbox.prototype, "handleDisabledChange", 1);
@@ -66,7 +66,7 @@ let SdCheckboxGroup = class extends SolidElement {
66
66
  sm: "text-sm",
67
67
  lg: "text-base"
68
68
  }[this.size]
69
- )}" role="group" aria-labelledby="label"><label part="form-control-label" id="label" class="${cx("mb-2 p-0 font-bold leading-normal text-black", hasLabel ? "flex" : "hidden")}" aria-hidden="${!hasLabel}"><slot name="label">${this.label}</slot></label><div part="form-control-input" class="${cx(
69
+ )}" role="group" aria-labelledby="label"><label part="form-control-label" id="label" class="${cx("mb-2 p-0 font-bold leading-normal text-black", hasLabel ? "flex" : "hidden")}" aria-hidden="${hasLabel ? "false" : "true"}"><slot name="label">${this.label}</slot></label><div part="form-control-input" class="${cx(
70
70
  {
71
71
  vertical: "flex flex-col",
72
72
  horizontal: "flex flex-row"
@@ -7,7 +7,10 @@ export default class SdInput extends SolidElement implements SolidFormControl {
7
7
  private readonly hasSlotController;
8
8
  private readonly localize;
9
9
  input: HTMLInputElement;
10
+ invalidMessage: HTMLDivElement;
10
11
  private hasFocus;
12
+ showValidStyle: boolean;
13
+ showInvalidStyle: boolean;
11
14
  type: 'date' | 'datetime-local' | 'email' | 'number' | 'password' | 'search' | 'tel' | 'text' | 'time' | 'url';
12
15
  size: 'lg' | 'md' | 'sm';
13
16
  inputmode: 'none' | 'text' | 'decimal' | 'numeric' | 'tel' | 'search' | 'email' | 'url';
@@ -12,7 +12,6 @@ import { query, state, property } from "lit/decorators.js";
12
12
  import { watch } from "../../internal/watch.js";
13
13
  import componentStyles from "../../styles/component.styles.js";
14
14
  import cx from "classix";
15
- import formControlStyles from "../../styles/form-control.styles.js";
16
15
  import SolidElement from "../../internal/solid-element.js";
17
16
  var __defProp = Object.defineProperty;
18
17
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -42,6 +41,8 @@ let SdInput = class extends SolidElement {
42
41
  );
43
42
  this.localize = new LocalizeController(this);
44
43
  this.hasFocus = false;
44
+ this.showValidStyle = false;
45
+ this.showInvalidStyle = false;
45
46
  this.type = "text";
46
47
  this.size = "lg";
47
48
  this.value = "";
@@ -115,8 +116,10 @@ let SdInput = class extends SolidElement {
115
116
  this.formControlController.updateValidity();
116
117
  this.emit("sd-input");
117
118
  }
118
- handleInvalid() {
119
+ handleInvalid(event) {
119
120
  this.formControlController.setValidity(false);
121
+ this.formControlController.emitInvalidEvent(event);
122
+ this.invalidMessage.textContent = event.target.validationMessage;
120
123
  }
121
124
  handleKeyDown(event) {
122
125
  const hasModifier = event.metaKey || event.ctrlKey || event.shiftKey || event.altKey;
@@ -210,10 +213,7 @@ let SdInput = class extends SolidElement {
210
213
  const hasLabel = this.label ? true : !!slots["label"];
211
214
  const hasHelpText = this.helpText ? true : !!slots["helpText"];
212
215
  const hasClearIcon = this.clearable && !this.readonly && (typeof this.value === "number" || this.value.length > 0);
213
- const hasValidationAttr = this.required || !!this.pattern || !!this.minlength || !!this.maxlength;
214
- const isInvalid = hasValidationAttr && !this.checkValidity();
215
- const isValid = hasValidationAttr && this.checkValidity();
216
- const inputState = this.disabled ? "disabled" : this.readonly ? "readonly" : this.hasFocus && isInvalid ? "activeInvalid" : this.hasFocus && isValid ? "activeValid" : this.hasFocus ? "active" : isInvalid ? "invalid" : isValid ? "valid" : "default";
216
+ const inputState = this.disabled ? "disabled" : this.readonly ? "readonly" : this.hasFocus && this.showInvalidStyle ? "activeInvalid" : this.hasFocus && this.showValidStyle ? "activeValid" : this.hasFocus ? "active" : this.showInvalidStyle ? "invalid" : this.showValidStyle ? "valid" : "default";
217
217
  const textSize = this.size === "sm" ? "text-sm" : "text-base";
218
218
  const textColor = {
219
219
  disabled: "text-neutral-500",
@@ -242,40 +242,41 @@ let SdInput = class extends SolidElement {
242
242
  md: "text-lg",
243
243
  lg: "text-xl"
244
244
  }[this.size];
245
- return html`<div part="form-control" class="${cx("form-control", hasLabel && "form-control--has-label", this.disabled && "pointer-events-none")}"><label part="form-control-label" id="label" class="${cx("form-control-label mb-2", hasLabel ? "has-label inline-block" : "hidden", textSize)}" for="input" aria-hidden="${hasLabel ? "false" : "true"}"><slot name="label">${this.label}</slot></label><div part="form-control-input" class="form-control-input relative w-full"><div part="border" class="${cx(
246
- "absolute w-full h-full pointer-events-none border rounded-default transition-all",
247
- borderColor
248
- )}"></div><div part="base" class="${cx(
249
- "px-4 flex flex-row items-center rounded-default transition-all",
245
+ return html`<div part="form-control" class="${cx(this.disabled && "pointer-events-none")}"><label part="form-control-label" id="label" class="${cx("mb-2", hasLabel ? "inline-block" : "hidden", textSize)}" for="input" aria-hidden="${hasLabel ? "false" : "true"}"><slot name="label">${this.label}</slot></label><div part="form-control-input" class="relative w-full"><div part="border" class="${cx("absolute w-full h-full pointer-events-none border rounded-default", borderColor)}"></div><div part="base" class="${cx(
246
+ "px-4 flex flex-row items-center rounded-default transition-all bg-white",
250
247
  // Vertical Padding
251
248
  this.size === "lg" ? "py-2" : "py-1",
252
249
  // States
253
250
  !this.disabled && !this.readonly ? "hover:bg-neutral-200" : "",
254
251
  this.readonly && "bg-neutral-100",
255
- isInvalid && "form-control-input--invalid",
256
- textColor,
257
- !this.value && "input--empty",
258
- this.noSpinButtons && "input--no-spin-buttons",
259
- isFirefox && "input--is-firefox"
252
+ textColor
260
253
  )}">${slots["left"] ? html`<slot name="left" part="left" class="${cx("inline-flex", this.size === "sm" ? "mr-1" : "mr-2", iconColor, iconSize)}"></slot>` : ""} <input part="input" id="input" class="${cx(
261
254
  "min-w-0 flex-grow focus:outline-none bg-transparent placeholder-neutral-700",
262
255
  this.size === "sm" ? "h-6" : "h-8",
263
256
  textSize
264
- )}" type="${this.type === "password" && this.passwordVisible ? "text" : this.type}" title="${this.title}" name="${ifDefined(this.name)}" ?disabled="${this.disabled}" ?readonly="${this.readonly}" ?required="${this.required}" placeholder="${ifDefined(this.placeholder)}" minlength="${ifDefined(this.minlength)}" maxlength="${ifDefined(this.maxlength)}" min="${ifDefined(this.min)}" max="${ifDefined(this.max)}" step="${ifDefined(this.step)}" .value="${live(this.value)}" autocapitalize="${ifDefined(this.type === "password" ? "off" : this.autocapitalize)}" autocomplete="${ifDefined(this.type === "password" ? "off" : this.autocomplete)}" autocorrect="${ifDefined(this.type === "password" ? "off" : this.autocorrect)}" ?autofocus="${this.autofocus}" spellcheck="${this.spellcheck}" pattern="${ifDefined(this.pattern)}" enterkeyhint="${ifDefined(this.enterkeyhint)}" inputmode="${ifDefined(this.inputmode)}" aria-describedby="help-text" @change="${this.handleChange}" @input="${this.handleInput}" @invalid="${this.handleInvalid}" @keydown="${this.handleKeyDown}" @focus="${this.handleFocus}" @blur="${this.handleBlur}"> ${hasClearIcon ? html`<button part="clear-button" class="${cx("flex justify-center ", iconMarginLeft)}" type="button" aria-label="${this.localize.term("clearEntry")}" @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.passwordToggle && this.type === "password" ? html`<button aria-label="${this.localize.term(this.passwordVisible ? "hidePassword" : "showPassword")}" part="password-toggle-button" class="flex items-center" type="button" @click="${this.handlePasswordToggle}" tabindex="-1">${this.passwordVisible ? html`<slot name="show-password-icon"><sd-icon class="${cx(iconColor, iconMarginLeft, iconSize)}" library="system" name="eye"></sd-icon></slot>` : html`<slot name="hide-password-icon"><sd-icon class="${cx(iconColor, iconMarginLeft, iconSize)}" library="system" name="eye-crossed-out"></sd-icon></slot>`}</button>` : ""} ${(this.type === "date" || this.type === "datetime-local") && !isFirefox ? html`<sd-icon class="${cx(iconColor, iconMarginLeft, iconSize)}" library="system" name="calendar"></sd-icon>` : ""} ${this.type === "time" ? html`<sd-icon class="${cx(iconColor, iconMarginLeft, iconSize)}" library="system" name="clock"></sd-icon>` : ""} ${isInvalid ? html`<sd-icon class="${cx("text-error", iconMarginLeft, iconSize)}" library="system" name="risk"></sd-icon>` : ""} ${isValid ? html`<sd-icon class="${cx("text-success", iconMarginLeft, iconSize)}" library="system" name="confirm"></sd-icon>` : ""} ${slots["right"] ? html`<slot name="right" part="right" class="${cx("inline-flex", iconColor, iconMarginLeft, iconSize)}"></slot>` : ""}</div></div><slot name="help-text" part="form-control-help-text" id="help-text" class="${cx("text-sm text-neutral-700", hasHelpText ? "block" : "hidden")}" aria-hidden="${hasHelpText ? "false" : "true"}">${this.helpText}</slot></div>`;
257
+ )}" type="${this.type === "password" && this.passwordVisible ? "text" : this.type}" title="${this.title}" name="${ifDefined(this.name)}" ?disabled="${this.disabled}" ?readonly="${this.readonly}" ?required="${this.required}" placeholder="${ifDefined(this.placeholder)}" minlength="${ifDefined(this.minlength)}" maxlength="${ifDefined(this.maxlength)}" min="${ifDefined(this.min)}" max="${ifDefined(this.max)}" step="${ifDefined(this.step)}" .value="${live(this.value)}" autocapitalize="${ifDefined(this.type === "password" ? "off" : this.autocapitalize)}" autocomplete="${ifDefined(this.type === "password" ? "off" : this.autocomplete)}" autocorrect="${ifDefined(this.type === "password" ? "off" : this.autocorrect)}" ?autofocus="${this.autofocus}" spellcheck="${this.spellcheck}" pattern="${ifDefined(this.pattern)}" enterkeyhint="${ifDefined(this.enterkeyhint)}" inputmode="${ifDefined(this.inputmode)}" aria-describedby="help-text" @change="${this.handleChange}" @input="${this.handleInput}" @invalid="${this.handleInvalid}" @keydown="${this.handleKeyDown}" @focus="${this.handleFocus}" @blur="${this.handleBlur}"> ${hasClearIcon ? html`<button part="clear-button" class="${cx("flex justify-center ", iconMarginLeft)}" type="button" aria-label="${this.localize.term("clearEntry")}" @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.passwordToggle && this.type === "password" ? html`<button aria-label="${this.localize.term(this.passwordVisible ? "hidePassword" : "showPassword")}" part="password-toggle-button" class="flex items-center" type="button" @click="${this.handlePasswordToggle}" tabindex="-1">${this.passwordVisible ? html`<slot name="show-password-icon"><sd-icon class="${cx(iconColor, iconMarginLeft, iconSize)}" library="system" name="eye"></sd-icon></slot>` : html`<slot name="hide-password-icon"><sd-icon class="${cx(iconColor, iconMarginLeft, iconSize)}" library="system" name="eye-crossed-out"></sd-icon></slot>`}</button>` : ""} ${(this.type === "date" || this.type === "datetime-local") && !isFirefox ? html`<sd-icon class="${cx(iconColor, iconMarginLeft, iconSize)}" library="system" name="calendar"></sd-icon>` : ""} ${this.type === "time" ? html`<sd-icon class="${cx(iconColor, iconMarginLeft, iconSize)}" library="system" name="clock"></sd-icon>` : ""} ${this.showInvalidStyle ? html`<sd-icon class="${cx("text-error", iconMarginLeft, iconSize)}" library="system" name="risk"></sd-icon>` : ""} ${this.showValidStyle ? html`<sd-icon class="${cx("text-success", iconMarginLeft, iconSize)}" library="system" name="confirm"></sd-icon>` : ""} ${slots["right"] ? html`<slot name="right" part="right" class="${cx("inline-flex", iconColor, iconMarginLeft, iconSize)}"></slot>` : ""}</div></div><slot name="help-text" part="form-control-help-text" id="help-text" class="${cx("text-sm text-neutral-700", hasHelpText ? "block" : "hidden")}" aria-hidden="${!hasHelpText}">${this.helpText}</slot></div>${this.formControlController.renderInvalidMessage()}`;
265
258
  }
266
259
  };
267
260
  SdInput.styles = [
268
261
  componentStyles,
269
- formControlStyles,
270
262
  SolidElement.styles,
271
- css`:host{position:relative;box-sizing:border-box;display:inline-block;width:100%;text-align:left}:host([vertical]){display:block}:host([required]) #label.has-label::after{content:'*';margin-left:var(--sd-spacing-0-5,.125rem)}input::-webkit-inner-spin-button,input::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}input[type=number]{-moz-appearance:textfield}input[type=time]::-webkit-calendar-picker-indicator{background:0 0}details summary::-webkit-details-marker,input[type=date]::-webkit-calendar-picker-indicator,input[type=datetime-local]::-webkit-calendar-picker-indicator,input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration,input[type=search]::-webkit-search-results-button,input[type=search]::-webkit-search-results-decoration{display:none}`
263
+ css`:host{position:relative;box-sizing:border-box;display:inline-block;width:100%;text-align:left}:host([vertical]){display:block}:host([required]) #label::after{content:' *'}details summary::-webkit-details-marker{display:none}input::-webkit-inner-spin-button,input::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}input[type=number]{-moz-appearance:textfield}input[type=time]::-webkit-calendar-picker-indicator{background:0 0}details summary::-webkit-details-marker,input[type=date]::-webkit-calendar-picker-indicator,input[type=datetime-local]::-webkit-calendar-picker-indicator,input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration,input[type=search]::-webkit-search-results-button,input[type=search]::-webkit-search-results-decoration{display:none}`
272
264
  ];
273
265
  __decorateClass([
274
266
  query("#input")
275
267
  ], SdInput.prototype, "input", 2);
268
+ __decorateClass([
269
+ query("#invalid-message")
270
+ ], SdInput.prototype, "invalidMessage", 2);
276
271
  __decorateClass([
277
272
  state()
278
273
  ], SdInput.prototype, "hasFocus", 2);
274
+ __decorateClass([
275
+ state()
276
+ ], SdInput.prototype, "showValidStyle", 2);
277
+ __decorateClass([
278
+ state()
279
+ ], SdInput.prototype, "showInvalidStyle", 2);
279
280
  __decorateClass([
280
281
  property({ reflect: true })
281
282
  ], SdInput.prototype, "type", 2);
@@ -7,7 +7,6 @@ import { query, state, property } from "lit/decorators.js";
7
7
  import { watch } from "../../internal/watch.js";
8
8
  import componentStyles from "../../styles/component.styles.js";
9
9
  import cx from "classix";
10
- import formControlStyles from "../../styles/form-control.styles.js";
11
10
  import SolidElement from "../../internal/solid-element.js";
12
11
  var __defProp = Object.defineProperty;
13
12
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -100,7 +99,6 @@ let SdOption = class extends SolidElement {
100
99
  };
101
100
  SdOption.styles = [
102
101
  componentStyles,
103
- formControlStyles,
104
102
  SolidElement.styles,
105
103
  css`:host{position:relative;display:block;width:100%;outline:2px solid transparent!important;outline-offset:2px!important}`
106
104
  ];
@@ -82,13 +82,13 @@ let SdRadio = class extends SolidElement {
82
82
  }[this.size]
83
83
  )}"><span part="${`${this.checked ? "control--checked" : "control--unchecked"}`}" class="${cx(
84
84
  "flex-initial shrink-0 relative inline-flex items-center justify-center border rounded-full bg-white h-4 w-4",
85
- this.disabled && "border-neutral-500" || this.invalid && "border-error hover:border-error-400 group-hover:border-error-400" || this.checked && "border-accent hover:border-accent-550 group-hover:border-accent-550" || "border-neutral-800 hover:bg-neutral-200 group-hover:bg-neutral-200"
85
+ this.disabled ? "border-neutral-500" : this.invalid ? "border-error hover:border-error-400 group-hover:border-error-400" : this.checked ? "border-accent hover:border-accent-550 group-hover:border-accent-550" : "border-neutral-800 hover:bg-neutral-200 group-hover:bg-neutral-200"
86
86
  )}">${this.checked ? html`<span part="checked" class="${cx(
87
87
  "rounded-full inline-flex text-white border bg-accent h-2.5 w-2.5",
88
- this.disabled && "bg-neutral-500" || this.invalid && "bg-error hover:bg-error-400 group-hover:bg-error-400" || this.checked && "bg-accent hover:bg-accent-550 group-hover:bg-accent-550" || "bg-neutral-800"
88
+ this.disabled ? "bg-neutral-500" : this.invalid ? "bg-error hover:bg-error-400 group-hover:bg-error-400" : this.checked ? "bg-accent hover:bg-accent-550 group-hover:bg-accent-550" : "bg-neutral-800"
89
89
  )}"></span>` : ""}</span><slot part="label" class="${cx(
90
90
  "ml-2 select-none inline-block",
91
- this.disabled && "text-neutral-500" || this.invalid && "text-error" || "text-black"
91
+ this.disabled ? "text-neutral-500" : this.invalid ? "text-error" : "text-black"
92
92
  )}"></slot></span>`;
93
93
  }
94
94
  };
@@ -12,11 +12,12 @@ export default class SdRadioGroup extends SolidElement implements SolidFormContr
12
12
  private validationTimeout;
13
13
  defaultSlot: HTMLSlotElement;
14
14
  validationInput: HTMLInputElement;
15
+ invalidMessage: HTMLDivElement;
15
16
  private hasButtonGroup;
16
17
  defaultValue: string;
17
- private invalid;
18
- private errorText;
18
+ showInvalidStyle: boolean;
19
19
  label: string;
20
+ boldLabel: boolean;
20
21
  name: string;
21
22
  value: string;
22
23
  size: 'lg' | 'sm';
@@ -30,7 +31,7 @@ export default class SdRadioGroup extends SolidElement implements SolidFormContr
30
31
  private getAllRadios;
31
32
  private handleRadioClick;
32
33
  private handleKeyDown;
33
- private handleLabelClick;
34
+ focus(): void;
34
35
  private handleInvalid;
35
36
  private syncRadioElements;
36
37
  private syncRadios;
@@ -7,6 +7,7 @@ import { watch } from "../../internal/watch.js";
7
7
  import componentStyles from "../../styles/component.styles.js";
8
8
  import cx from "classix";
9
9
  import SdButtonGroup from "../../_components/button-group/button-group.js";
10
+ import SdRadio from "../radio/radio.js";
10
11
  import SolidElement from "../../internal/solid-element.js";
11
12
  var __defProp = Object.defineProperty;
12
13
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -27,9 +28,9 @@ let SdRadioGroup = class extends SolidElement {
27
28
  this.customValidityMessage = "";
28
29
  this.hasButtonGroup = false;
29
30
  this.defaultValue = "";
30
- this.invalid = false;
31
- this.errorText = "";
31
+ this.showInvalidStyle = false;
32
32
  this.label = "";
33
+ this.boldLabel = false;
33
34
  this.name = "option";
34
35
  this.value = "";
35
36
  this.size = "lg";
@@ -42,13 +43,10 @@ let SdRadioGroup = class extends SolidElement {
42
43
  const isRequiredAndEmpty = this.required && !this.value;
43
44
  const hasCustomValidityMessage = this.customValidityMessage !== "";
44
45
  if (hasCustomValidityMessage) {
45
- this.invalid = true;
46
46
  return customErrorValidityState;
47
47
  } else if (isRequiredAndEmpty) {
48
- this.invalid = true;
49
48
  return valueMissingValidityState;
50
49
  }
51
- this.invalid = false;
52
50
  return validValidityState;
53
51
  }
54
52
  /** Gets the validation message */
@@ -56,10 +54,8 @@ let SdRadioGroup = class extends SolidElement {
56
54
  const isRequiredAndEmpty = this.required && !this.value;
57
55
  const hasCustomValidityMessage = this.customValidityMessage !== "";
58
56
  if (hasCustomValidityMessage) {
59
- console.log("this.customValidityMessage", this.customValidityMessage);
60
57
  return this.customValidityMessage;
61
58
  } else if (isRequiredAndEmpty) {
62
- console.log("this.validationInput.validationMessage", this.validationInput);
63
59
  return this.validationInput.validationMessage;
64
60
  }
65
61
  return "";
@@ -123,7 +119,8 @@ let SdRadioGroup = class extends SolidElement {
123
119
  }
124
120
  event.preventDefault();
125
121
  }
126
- handleLabelClick() {
122
+ /** Move focus to the checked radio (or the first one if none are checked) */
123
+ focus() {
127
124
  const radios = this.getAllRadios();
128
125
  const checked = radios.find((radio) => radio.checked);
129
126
  const radioToFocus = checked || radios[0];
@@ -134,6 +131,7 @@ let SdRadioGroup = class extends SolidElement {
134
131
  handleInvalid(event) {
135
132
  this.formControlController.setValidity(false);
136
133
  this.formControlController.emitInvalidEvent(event);
134
+ this.invalidMessage.textContent = event.target.validationMessage;
137
135
  }
138
136
  async syncRadioElements() {
139
137
  var _a, _b;
@@ -144,8 +142,8 @@ let SdRadioGroup = class extends SolidElement {
144
142
  await radio.updateComplete;
145
143
  radio.checked = radio.value === this.value;
146
144
  radio.size = this.size;
147
- if ("invalid" in radio) {
148
- radio.invalid = this.invalid;
145
+ if (radio instanceof SdRadio) {
146
+ radio.invalid = this.showInvalidStyle;
149
147
  }
150
148
  })
151
149
  );
@@ -215,10 +213,8 @@ let SdRadioGroup = class extends SolidElement {
215
213
  return this.formControlController.getForm();
216
214
  }
217
215
  /** Checks for validity and shows the browser's validation message if the control is invalid. */
218
- // TODO: https://github.com/solid-design-system/solid/issues/501
219
216
  reportValidity() {
220
217
  const isValid = this.validity.valid;
221
- this.errorText = this.customValidityMessage || isValid ? "" : this.validationInput.validationMessage;
222
218
  this.formControlController.setValidity(isValid);
223
219
  this.validationInput.hidden = true;
224
220
  clearTimeout(this.validationTimeout);
@@ -232,39 +228,38 @@ let SdRadioGroup = class extends SolidElement {
232
228
  /** Sets a custom validation message. Pass an empty string to restore validity. */
233
229
  setCustomValidity(message = "") {
234
230
  this.customValidityMessage = message;
235
- this.errorText = message;
236
231
  this.validationInput.setCustomValidity(message);
237
232
  this.formControlController.updateValidity();
238
233
  }
239
234
  render() {
240
235
  const hasLabelSlot = this.hasSlotController.test("label");
241
- const hasErrorTextSlot = this.hasSlotController.test("error-text");
242
236
  const hasLabel = this.label ? true : !!hasLabelSlot;
243
- const hasErrorText = this.errorText ? true : !!hasErrorTextSlot;
244
237
  const defaultSlot = html`<slot @slotchange="${this.syncRadios}" @click="${this.handleRadioClick}" @keydown="${this.handleKeyDown}"></slot>`;
245
238
  return html`<fieldset part="form-control" class="${cx(
246
- "border-0 p-0 m-0",
247
- hasErrorText && "text-error",
239
+ "border-0 p-0 m-0 flex flex-col",
248
240
  {
249
241
  /* sizes, fonts */
250
242
  sm: "text-sm",
251
243
  lg: "text-base"
252
244
  }[this.size]
253
- )}" role="radiogroup" aria-labelledby="label" aria-errormessage="error-text"><label part="form-control-label" id="label" class="${cx("mb-2 p-0 font-bold leading-normal text-black", hasLabel ? "has-label flex" : "hidden")}" aria-hidden="${!hasLabel}" @click="${this.handleLabelClick}"><slot name="label">${this.label}</slot></label><div part="form-control-input" class="${cx(
254
- "form-control-input flex",
255
- this.invalid && "form-control-input--invalid text-error",
245
+ )}" role="radiogroup" aria-labelledby="label" aria-errormessage="error-text"><label part="form-control-label" id="label" class="${cx(
246
+ "mb-2 p-0 leading-normal text-black text-left",
247
+ !hasLabel && "hidden",
248
+ this.boldLabel && "font-bold"
249
+ )}" @click="${this.focus}" aria-hidden="${hasLabel ? "false" : "true"}"><slot name="label">${this.label}</slot></label><div part="form-control-input" class="${cx(
250
+ "flex",
256
251
  {
257
252
  vertical: "flex-col",
258
253
  horizontal: "flex-row"
259
254
  }[this.orientation]
260
- )}"><div class="sr-only"><div id="error-message" aria-live="assertive">${this.errorText}</div><label><input id="validation-input" type="text" ?required="${this.required}" tabindex="-1" hidden @invalid="${this.handleInvalid}"></label></div>${this.hasButtonGroup ? html`<sd-button-group part="button-group" exportparts="base:button-group__base" role="presentation">${defaultSlot}</sd-button-group>` : defaultSlot}</div></fieldset>`;
255
+ )}"><div class="sr-only"><label><input id="validation-input" type="text" ?required="${this.required}" tabindex="-1" hidden @invalid="${this.handleInvalid}"></label></div>${this.hasButtonGroup ? html`<sd-button-group part="button-group" exportparts="base:button-group__base" role="presentation">${defaultSlot}</sd-button-group>` : defaultSlot}</div></fieldset>${this.formControlController.renderInvalidMessage()}`;
261
256
  }
262
257
  };
263
258
  SdRadioGroup.dependencies = { "sd-button-group": SdButtonGroup };
264
259
  SdRadioGroup.styles = [
265
260
  componentStyles,
266
261
  SolidElement.styles,
267
- css`:host{display:block}:host([orientation=vertical]) ::slotted(sd-radio){margin-bottom:var(--sd-spacing-2,.5rem);display:flex}:host([orientation=vertical]) ::slotted(sd-radio:last-of-type){margin-bottom:var(--sd-spacing-0,0)}:host([orientation=horizontal]) ::slotted(sd-radio){margin-right:var(--sd-spacing-6,1.5rem)}:host([orientation=horizontal]) ::slotted(sd-radio:last-of-type){margin-right:var(--sd-spacing-0,0)}:host([orientation=horizontal]):host([size=sm]) ::slotted(sd-radio){margin-right:var(--sd-spacing-4,1rem)}:host([orientation=horizontal]):host([size=sm]) ::slotted(sd-radio:last-of-type){margin-right:var(--sd-spacing-0,0)}:host([required]) #label.has-label::after{content:'*';margin-left:var(--sd-spacing-0-5,.125rem)}`
262
+ css`:host{display:block}:host([orientation=vertical]) ::slotted(sd-radio){margin-bottom:var(--sd-spacing-2,.5rem);display:flex}:host([orientation=vertical]) ::slotted(sd-radio:last-of-type){margin-bottom:var(--sd-spacing-0,0)}:host([orientation=horizontal]) ::slotted(sd-radio){margin-right:var(--sd-spacing-6,1.5rem)}:host([orientation=horizontal]) ::slotted(sd-radio:last-of-type){margin-right:var(--sd-spacing-0,0)}:host([orientation=horizontal]):host([size=sm]) ::slotted(sd-radio){margin-right:var(--sd-spacing-4,1rem)}:host([orientation=horizontal]):host([size=sm]) ::slotted(sd-radio:last-of-type){margin-right:var(--sd-spacing-0,0)}:host([required]) #label::after{content:' *'}`
268
263
  ];
269
264
  __decorateClass([
270
265
  query("slot:not([name])")
@@ -272,6 +267,9 @@ __decorateClass([
272
267
  __decorateClass([
273
268
  query("#validation-input")
274
269
  ], SdRadioGroup.prototype, "validationInput", 2);
270
+ __decorateClass([
271
+ query("#invalid-message")
272
+ ], SdRadioGroup.prototype, "invalidMessage", 2);
275
273
  __decorateClass([
276
274
  state()
277
275
  ], SdRadioGroup.prototype, "hasButtonGroup", 2);
@@ -280,13 +278,13 @@ __decorateClass([
280
278
  ], SdRadioGroup.prototype, "defaultValue", 2);
281
279
  __decorateClass([
282
280
  state()
283
- ], SdRadioGroup.prototype, "invalid", 2);
284
- __decorateClass([
285
- state()
286
- ], SdRadioGroup.prototype, "errorText", 2);
281
+ ], SdRadioGroup.prototype, "showInvalidStyle", 2);
287
282
  __decorateClass([
288
283
  property()
289
284
  ], SdRadioGroup.prototype, "label", 2);
285
+ __decorateClass([
286
+ property({ type: Boolean, reflect: true })
287
+ ], SdRadioGroup.prototype, "boldLabel", 2);
290
288
  __decorateClass([
291
289
  property()
292
290
  ], SdRadioGroup.prototype, "name", 2);
@@ -309,7 +307,7 @@ __decorateClass([
309
307
  watch("size", { waitUntilFirstUpdate: true })
310
308
  ], SdRadioGroup.prototype, "handleSizeChange", 1);
311
309
  __decorateClass([
312
- watch("invalid", { waitUntilFirstUpdate: true })
310
+ watch("showInvalidStyle", { waitUntilFirstUpdate: true })
313
311
  ], SdRadioGroup.prototype, "handleInvalidChange", 1);
314
312
  __decorateClass([
315
313
  watch("value")
@@ -22,13 +22,14 @@ export default class SdSelect extends SolidElement implements SolidFormControl {
22
22
  displayInput: HTMLInputElement;
23
23
  valueInput: HTMLInputElement;
24
24
  listbox: HTMLSlotElement;
25
+ invalidMessage: HTMLDivElement;
25
26
  private hasFocus;
26
27
  hasHover: boolean;
27
28
  private displayLabel;
28
29
  private currentOption;
29
30
  private selectedOptions;
30
- private isValid;
31
- private isInvalid;
31
+ showValidStyle: boolean;
32
+ showInvalidStyle: boolean;
32
33
  defaultValue: string | string[];
33
34
  open: boolean;
34
35
  size: 'lg' | 'md' | 'sm';
@@ -51,7 +52,6 @@ export default class SdSelect extends SolidElement implements SolidFormControl {
51
52
  get validity(): ValidityState;
52
53
  get validationMessage(): string;
53
54
  connectedCallback(): void;
54
- updated(): void;
55
55
  private addOpenListeners;
56
56
  private removeOpenListeners;
57
57
  private handleFocus;
@@ -13,7 +13,6 @@ import { waitForEvent } from "../../internal/event.js";
13
13
  import { watch } from "../../internal/watch.js";
14
14
  import componentStyles from "../../styles/component.styles.js";
15
15
  import cx from "classix";
16
- import formControlStyles from "../../styles/form-control.styles.js";
17
16
  import SdIcon from "../icon/icon.js";
18
17
  import SdPopup from "../popup/popup.js";
19
18
  import SdTag from "../tag/tag.js";
@@ -42,12 +41,12 @@ let SdSelect = class extends SolidElement {
42
41
  this.hasHover = false;
43
42
  this.displayLabel = "";
44
43
  this.selectedOptions = [];
45
- this.isValid = false;
46
- this.isInvalid = false;
44
+ this.showValidStyle = false;
45
+ this.showInvalidStyle = false;
47
46
  this.defaultValue = "";
48
47
  this.open = false;
49
48
  this.size = "lg";
50
- this.label = "Label";
49
+ this.label = "";
51
50
  this.placeholder = this.localize.term("selectDefaultPlaceholder");
52
51
  this.helpText = "";
53
52
  this.placement = "bottom";
@@ -187,15 +186,6 @@ let SdSelect = class extends SolidElement {
187
186
  this.applySizeToOptions();
188
187
  this.open = false;
189
188
  }
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
189
  addOpenListeners() {
200
190
  document.addEventListener("focusin", this.handleDocumentFocusIn);
201
191
  document.addEventListener("keydown", this.handleDocumentKeyDown);
@@ -373,6 +363,7 @@ let SdSelect = class extends SolidElement {
373
363
  handleInvalid(event) {
374
364
  this.formControlController.setValidity(false);
375
365
  this.formControlController.emitInvalidEvent(event);
366
+ this.invalidMessage.textContent = event.target.validationMessage;
376
367
  }
377
368
  handleMouseEnter() {
378
369
  this.hasHover = true;
@@ -494,7 +485,7 @@ let SdSelect = class extends SolidElement {
494
485
  const hasLabel = this.label ? true : !!slots["label"];
495
486
  const hasHelpText = this.helpText ? true : !!slots["helpText"];
496
487
  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";
488
+ const selectState = this.disabled ? "disabled" : this.hasFocus && this.showInvalidStyle ? "activeInvalid" : this.hasFocus && this.showValidStyle ? "activeValid" : this.hasFocus || this.open ? "active" : this.showInvalidStyle ? "invalid" : this.showValidStyle ? "valid" : "default";
498
489
  const cursorStyles = this.disabled ? "cursor-not-allowed" : "cursor-pointer";
499
490
  const iconMarginLeft = { sm: "ml-1", md: "ml-2", lg: "ml-2" }[this.size];
500
491
  const iconSize = {
@@ -503,9 +494,12 @@ let SdSelect = class extends SolidElement {
503
494
  lg: "text-xl"
504
495
  }[this.size];
505
496
  return html`<div part="form-control" class="${cx(
506
- "form-control relative text-left",
497
+ "relative text-left",
507
498
  cursorStyles,
508
499
  this.size === "sm" ? "text-sm" : "text-base",
500
+ this.open && "z-50"
501
+ )}"><label id="label" part="form-control-label" class="${hasLabel && "inline-block mb-2"}" aria-hidden="${hasLabel ? "false" : "true"}" @click="${this.handleLabelClick}"><slot name="label">${this.label}</slot></label><div part="form-control-input" class="${cx(
502
+ "relative w-full bg-white",
509
503
  {
510
504
  disabled: "text-neutral-500",
511
505
  readonly: "text-black",
@@ -515,9 +509,8 @@ let SdSelect = class extends SolidElement {
515
509
  invalid: "text-error",
516
510
  valid: "text-success",
517
511
  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(
512
+ }[selectState]
513
+ )}"><div part="border" class="${cx(
521
514
  "absolute top-0 w-full h-full pointer-events-none border rounded-default",
522
515
  this.hasHover && "bg-neutral-200",
523
516
  {
@@ -545,10 +538,10 @@ let SdSelect = class extends SolidElement {
545
538
  "appearance-none outline-none flex-grow bg-transparent",
546
539
  cursorStyles,
547
540
  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(
541
+ )}" 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.showInvalidStyle ? html`<sd-icon class="${cx("text-error", iconMarginLeft, iconSize)}" library="system" name="risk"></sd-icon>` : ""} ${this.showValidStyle ? 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
542
  "bg-white px-2 py-3 relative",
550
543
  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>`;
544
+ )}" 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()}`;
552
545
  }
553
546
  };
554
547
  SdSelect.dependencies = {
@@ -558,7 +551,6 @@ SdSelect.dependencies = {
558
551
  };
559
552
  SdSelect.styles = [
560
553
  componentStyles,
561
- formControlStyles,
562
554
  SolidElement.styles,
563
555
  css`:host{position:relative;display:block;width:100%}:host([required]) #label::after{content:' *'}sd-popup::part(popup){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))}`
564
556
  ];
@@ -580,6 +572,9 @@ __decorateClass([
580
572
  __decorateClass([
581
573
  query('[part="listbox"]')
582
574
  ], SdSelect.prototype, "listbox", 2);
575
+ __decorateClass([
576
+ query("#invalid-message")
577
+ ], SdSelect.prototype, "invalidMessage", 2);
583
578
  __decorateClass([
584
579
  state()
585
580
  ], SdSelect.prototype, "hasFocus", 2);
@@ -597,10 +592,10 @@ __decorateClass([
597
592
  ], SdSelect.prototype, "selectedOptions", 2);
598
593
  __decorateClass([
599
594
  state()
600
- ], SdSelect.prototype, "isValid", 2);
595
+ ], SdSelect.prototype, "showValidStyle", 2);
601
596
  __decorateClass([
602
597
  state()
603
- ], SdSelect.prototype, "isInvalid", 2);
598
+ ], SdSelect.prototype, "showInvalidStyle", 2);
604
599
  __decorateClass([
605
600
  defaultValue()
606
601
  ], SdSelect.prototype, "defaultValue", 2);