@happyvertical/smrt-ui 0.38.26 → 0.39.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (205) hide show
  1. package/AGENTS.md +23 -7
  2. package/README.md +132 -0
  3. package/dist/components/data/CollectionList.svelte +106 -0
  4. package/dist/components/data/CollectionList.svelte.d.ts +49 -0
  5. package/dist/components/data/CollectionList.svelte.d.ts.map +1 -0
  6. package/dist/components/data/CollectionToolbar.svelte +72 -0
  7. package/dist/components/data/CollectionToolbar.svelte.d.ts +20 -0
  8. package/dist/components/data/CollectionToolbar.svelte.d.ts.map +1 -0
  9. package/dist/components/data/DataTable.svelte +107 -17
  10. package/dist/components/data/DataTable.svelte.d.ts +2 -2
  11. package/dist/components/data/DataTable.svelte.d.ts.map +1 -1
  12. package/dist/components/data/__tests__/DataTable.test.js +61 -1
  13. package/dist/components/data/index.d.ts +2 -0
  14. package/dist/components/data/index.d.ts.map +1 -1
  15. package/dist/components/data/index.js +2 -0
  16. package/dist/components/data/types.d.ts +33 -0
  17. package/dist/components/data/types.d.ts.map +1 -1
  18. package/dist/components/feedback/Alert.svelte +53 -0
  19. package/dist/components/feedback/Alert.svelte.d.ts +14 -0
  20. package/dist/components/feedback/Alert.svelte.d.ts.map +1 -0
  21. package/dist/components/feedback/Drawer.svelte +34 -0
  22. package/dist/components/feedback/Drawer.svelte.d.ts +18 -0
  23. package/dist/components/feedback/Drawer.svelte.d.ts.map +1 -0
  24. package/dist/components/feedback/Meter.svelte +33 -0
  25. package/dist/components/feedback/Meter.svelte.d.ts +16 -0
  26. package/dist/components/feedback/Meter.svelte.d.ts.map +1 -0
  27. package/dist/components/feedback/Modal.svelte +9 -5
  28. package/dist/components/feedback/Modal.svelte.d.ts +2 -2
  29. package/dist/components/feedback/Modal.svelte.d.ts.map +1 -1
  30. package/dist/components/feedback/Progress.svelte +61 -0
  31. package/dist/components/feedback/Progress.svelte.d.ts +14 -0
  32. package/dist/components/feedback/Progress.svelte.d.ts.map +1 -0
  33. package/dist/components/feedback/Spinner.svelte +17 -0
  34. package/dist/components/feedback/Spinner.svelte.d.ts +9 -0
  35. package/dist/components/feedback/Spinner.svelte.d.ts.map +1 -0
  36. package/dist/components/feedback/ToastViewport.svelte +48 -0
  37. package/dist/components/feedback/ToastViewport.svelte.d.ts +10 -0
  38. package/dist/components/feedback/ToastViewport.svelte.d.ts.map +1 -0
  39. package/dist/components/feedback/__tests__/toast.test.js +49 -0
  40. package/dist/components/feedback/index.d.ts +8 -0
  41. package/dist/components/feedback/index.d.ts.map +1 -1
  42. package/dist/components/feedback/index.js +10 -3
  43. package/dist/components/feedback/toast.d.ts +28 -0
  44. package/dist/components/feedback/toast.d.ts.map +1 -0
  45. package/dist/components/feedback/toast.js +58 -0
  46. package/dist/components/forms/Checkbox.svelte +149 -0
  47. package/dist/components/forms/Checkbox.svelte.d.ts +13 -0
  48. package/dist/components/forms/Checkbox.svelte.d.ts.map +1 -0
  49. package/dist/components/forms/Combobox.svelte +172 -0
  50. package/dist/components/forms/Combobox.svelte.d.ts +18 -0
  51. package/dist/components/forms/Combobox.svelte.d.ts.map +1 -0
  52. package/dist/components/forms/DatePicker.svelte +25 -0
  53. package/dist/components/forms/DatePicker.svelte.d.ts +12 -0
  54. package/dist/components/forms/DatePicker.svelte.d.ts.map +1 -0
  55. package/dist/components/forms/ErrorSummary.svelte +32 -0
  56. package/dist/components/forms/ErrorSummary.svelte.d.ts +11 -0
  57. package/dist/components/forms/ErrorSummary.svelte.d.ts.map +1 -0
  58. package/dist/components/forms/Fieldset.svelte +32 -0
  59. package/dist/components/forms/Fieldset.svelte.d.ts +13 -0
  60. package/dist/components/forms/Fieldset.svelte.d.ts.map +1 -0
  61. package/dist/components/forms/FilePicker.svelte +116 -0
  62. package/dist/components/forms/FilePicker.svelte.d.ts +19 -0
  63. package/dist/components/forms/FilePicker.svelte.d.ts.map +1 -0
  64. package/dist/components/forms/Form.svelte +55 -2
  65. package/dist/components/forms/Form.svelte.d.ts +11 -1
  66. package/dist/components/forms/Form.svelte.d.ts.map +1 -1
  67. package/dist/components/forms/FormGroup.svelte +19 -2
  68. package/dist/components/forms/FormGroup.svelte.d.ts +3 -0
  69. package/dist/components/forms/FormGroup.svelte.d.ts.map +1 -1
  70. package/dist/components/forms/Input.svelte +127 -0
  71. package/dist/components/forms/Input.svelte.d.ts +9 -1
  72. package/dist/components/forms/Input.svelte.d.ts.map +1 -1
  73. package/dist/components/forms/InputGroup.svelte +17 -0
  74. package/dist/components/forms/InputGroup.svelte.d.ts +11 -0
  75. package/dist/components/forms/InputGroup.svelte.d.ts.map +1 -0
  76. package/dist/components/forms/Listbox.svelte +97 -0
  77. package/dist/components/forms/Listbox.svelte.d.ts +15 -0
  78. package/dist/components/forms/Listbox.svelte.d.ts.map +1 -0
  79. package/dist/components/forms/MultiSelect.svelte +159 -0
  80. package/dist/components/forms/MultiSelect.svelte.d.ts +16 -0
  81. package/dist/components/forms/MultiSelect.svelte.d.ts.map +1 -0
  82. package/dist/components/forms/Radio.svelte +34 -0
  83. package/dist/components/forms/Radio.svelte.d.ts +10 -0
  84. package/dist/components/forms/Radio.svelte.d.ts.map +1 -0
  85. package/dist/components/forms/RadioGroup.svelte +130 -0
  86. package/dist/components/forms/RadioGroup.svelte.d.ts +19 -0
  87. package/dist/components/forms/RadioGroup.svelte.d.ts.map +1 -0
  88. package/dist/components/forms/RangeSlider.svelte +137 -0
  89. package/dist/components/forms/RangeSlider.svelte.d.ts +21 -0
  90. package/dist/components/forms/RangeSlider.svelte.d.ts.map +1 -0
  91. package/dist/components/forms/SegmentedControl.svelte +87 -0
  92. package/dist/components/forms/SegmentedControl.svelte.d.ts +17 -0
  93. package/dist/components/forms/SegmentedControl.svelte.d.ts.map +1 -0
  94. package/dist/components/forms/Select.svelte +84 -3
  95. package/dist/components/forms/Select.svelte.d.ts +6 -1
  96. package/dist/components/forms/Select.svelte.d.ts.map +1 -1
  97. package/dist/components/forms/Slider.svelte +131 -0
  98. package/dist/components/forms/Slider.svelte.d.ts +18 -0
  99. package/dist/components/forms/Slider.svelte.d.ts.map +1 -0
  100. package/dist/components/forms/Switch.svelte +128 -0
  101. package/dist/components/forms/Switch.svelte.d.ts +14 -0
  102. package/dist/components/forms/Switch.svelte.d.ts.map +1 -0
  103. package/dist/components/forms/TagsInput.svelte +106 -0
  104. package/dist/components/forms/TagsInput.svelte.d.ts +17 -0
  105. package/dist/components/forms/TagsInput.svelte.d.ts.map +1 -0
  106. package/dist/components/forms/Textarea.svelte +84 -3
  107. package/dist/components/forms/Textarea.svelte.d.ts +6 -1
  108. package/dist/components/forms/Textarea.svelte.d.ts.map +1 -1
  109. package/dist/components/forms/TimePicker.svelte +25 -0
  110. package/dist/components/forms/TimePicker.svelte.d.ts +12 -0
  111. package/dist/components/forms/TimePicker.svelte.d.ts.map +1 -0
  112. package/dist/components/forms/ToggleButton.svelte +79 -0
  113. package/dist/components/forms/ToggleButton.svelte.d.ts +13 -0
  114. package/dist/components/forms/ToggleButton.svelte.d.ts.map +1 -0
  115. package/dist/components/forms/__tests__/composite-controls.fixture.svelte +29 -0
  116. package/dist/components/forms/__tests__/composite-controls.fixture.svelte.d.ts +8 -0
  117. package/dist/components/forms/__tests__/composite-controls.fixture.svelte.d.ts.map +1 -0
  118. package/dist/components/forms/__tests__/composite-controls.test.js +33 -0
  119. package/dist/components/forms/__tests__/control-interaction.test.js +95 -0
  120. package/dist/components/forms/__tests__/core-controls.fixture.svelte +39 -0
  121. package/dist/components/forms/__tests__/core-controls.fixture.svelte.d.ts +8 -0
  122. package/dist/components/forms/__tests__/core-controls.fixture.svelte.d.ts.map +1 -0
  123. package/dist/components/forms/__tests__/core-controls.test.js +90 -0
  124. package/dist/components/forms/control-dom.d.ts +6 -0
  125. package/dist/components/forms/control-dom.d.ts.map +1 -0
  126. package/dist/components/forms/control-dom.js +38 -0
  127. package/dist/components/forms/control-interaction-context.d.ts +9 -0
  128. package/dist/components/forms/control-interaction-context.d.ts.map +1 -0
  129. package/dist/components/forms/control-interaction-context.js +15 -0
  130. package/dist/components/forms/control-interaction.d.ts +147 -0
  131. package/dist/components/forms/control-interaction.d.ts.map +1 -0
  132. package/dist/components/forms/control-interaction.js +265 -0
  133. package/dist/components/forms/form-group-context.d.ts +7 -0
  134. package/dist/components/forms/form-group-context.d.ts.map +1 -1
  135. package/dist/components/forms/index.d.ts +22 -1
  136. package/dist/components/forms/index.d.ts.map +1 -1
  137. package/dist/components/forms/index.js +21 -1
  138. package/dist/components/forms/radio-group-context.d.ts +12 -0
  139. package/dist/components/forms/radio-group-context.d.ts.map +1 -0
  140. package/dist/components/forms/radio-group-context.js +11 -0
  141. package/dist/components/forms/types.d.ts +14 -0
  142. package/dist/components/forms/types.d.ts.map +1 -0
  143. package/dist/components/forms/types.js +1 -0
  144. package/dist/components/forms/use-control-registration.svelte.d.ts +8 -0
  145. package/dist/components/forms/use-control-registration.svelte.d.ts.map +1 -0
  146. package/dist/components/forms/use-control-registration.svelte.js +15 -0
  147. package/dist/components/ui/Accordion.svelte +44 -0
  148. package/dist/components/ui/Accordion.svelte.d.ts +12 -0
  149. package/dist/components/ui/Accordion.svelte.d.ts.map +1 -0
  150. package/dist/components/ui/AccordionItem.svelte +42 -0
  151. package/dist/components/ui/AccordionItem.svelte.d.ts +11 -0
  152. package/dist/components/ui/AccordionItem.svelte.d.ts.map +1 -0
  153. package/dist/components/ui/Disclosure.svelte +50 -0
  154. package/dist/components/ui/Disclosure.svelte.d.ts +13 -0
  155. package/dist/components/ui/Disclosure.svelte.d.ts.map +1 -0
  156. package/dist/components/ui/Dropdown.svelte +5 -7
  157. package/dist/components/ui/Dropdown.svelte.d.ts +9 -0
  158. package/dist/components/ui/Dropdown.svelte.d.ts.map +1 -1
  159. package/dist/components/ui/Popover.svelte +102 -0
  160. package/dist/components/ui/Popover.svelte.d.ts +16 -0
  161. package/dist/components/ui/Popover.svelte.d.ts.map +1 -0
  162. package/dist/components/ui/__tests__/interaction-primitives.fixture.svelte +13 -0
  163. package/dist/components/ui/__tests__/interaction-primitives.fixture.svelte.d.ts +19 -0
  164. package/dist/components/ui/__tests__/interaction-primitives.fixture.svelte.d.ts.map +1 -0
  165. package/dist/components/ui/__tests__/interaction-primitives.test.js +31 -0
  166. package/dist/components/ui/accordion-context.d.ts +7 -0
  167. package/dist/components/ui/accordion-context.d.ts.map +1 -0
  168. package/dist/components/ui/accordion-context.js +11 -0
  169. package/dist/components/ui/index.d.ts +5 -1
  170. package/dist/components/ui/index.d.ts.map +1 -1
  171. package/dist/components/ui/index.js +5 -1
  172. package/dist/index.d.ts +1 -1
  173. package/dist/index.d.ts.map +1 -1
  174. package/dist/playground.d.ts +2 -0
  175. package/dist/playground.d.ts.map +1 -0
  176. package/dist/playground.js +1 -0
  177. package/dist/svelte/__tests__/playground.test.js +18 -0
  178. package/dist/svelte/playground/BaseControlsPreview.svelte +233 -0
  179. package/dist/svelte/playground/BaseControlsPreview.svelte.d.ts +4 -0
  180. package/dist/svelte/playground/BaseControlsPreview.svelte.d.ts.map +1 -0
  181. package/dist/svelte/playground/CollectionsPreview.svelte +59 -0
  182. package/dist/svelte/playground/CollectionsPreview.svelte.d.ts +4 -0
  183. package/dist/svelte/playground/CollectionsPreview.svelte.d.ts.map +1 -0
  184. package/dist/svelte/playground/DataTablePreview.svelte +247 -0
  185. package/dist/svelte/playground/DataTablePreview.svelte.d.ts +4 -0
  186. package/dist/svelte/playground/DataTablePreview.svelte.d.ts.map +1 -0
  187. package/dist/svelte/playground/FeedbackPreview.svelte +51 -0
  188. package/dist/svelte/playground/FeedbackPreview.svelte.d.ts +4 -0
  189. package/dist/svelte/playground/FeedbackPreview.svelte.d.ts.map +1 -0
  190. package/dist/svelte/playground/InteractiveControlsPreview.svelte +109 -0
  191. package/dist/svelte/playground/InteractiveControlsPreview.svelte.d.ts +4 -0
  192. package/dist/svelte/playground/InteractiveControlsPreview.svelte.d.ts.map +1 -0
  193. package/dist/svelte/playground.d.ts +20 -0
  194. package/dist/svelte/playground.d.ts.map +1 -0
  195. package/dist/svelte/playground.js +65 -0
  196. package/dist/theme/index.d.ts +6 -4
  197. package/dist/theme/index.d.ts.map +1 -1
  198. package/dist/theme/index.js +6 -7
  199. package/dist/themes/context.svelte.js +1 -1
  200. package/dist/themes/index.d.ts +1 -1
  201. package/dist/themes/index.js +1 -1
  202. package/dist/themes/smrt/index.js +1 -1
  203. package/dist/types-generic.d.ts +7 -1
  204. package/dist/types-generic.d.ts.map +1 -1
  205. package/package.json +23 -12
@@ -1 +1 @@
1
- {"version":3,"file":"FormGroup.svelte.d.ts","sourceRoot":"","sources":["../../../src/components/forms/FormGroup.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAQtC,MAAM,WAAW,KAAK;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAiDD,QAAA,MAAM,SAAS,2CAAwC,CAAC;AACxD,KAAK,SAAS,GAAG,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC;AAC9C,eAAe,SAAS,CAAC"}
1
+ {"version":3,"file":"FormGroup.svelte.d.ts","sourceRoot":"","sources":["../../../src/components/forms/FormGroup.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AAQ1E,MAAM,WAAW,KAAK;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,4EAA4E;IAC5E,WAAW,CAAC,EAAE,yBAAyB,GAAG,KAAK,CAAC;IAChD,QAAQ,EAAE,OAAO,CAAC;CACnB;AAgED,QAAA,MAAM,SAAS,2CAAwC,CAAC;AACxD,KAAK,SAAS,GAAG,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC;AAC9C,eAAe,SAAS,CAAC"}
@@ -1,10 +1,22 @@
1
1
  <script lang="ts">
2
2
  import type { HTMLInputAttributes } from 'svelte/elements';
3
+ import {
4
+ emitControlChange,
5
+ highlightControl,
6
+ revealControl,
7
+ } from './control-dom.js';
8
+ import type {
9
+ ControlInteractionOptions,
10
+ ControlKind,
11
+ } from './control-interaction.js';
12
+ import { tryGetControlInteractionContext } from './control-interaction-context.js';
3
13
  import { tryGetFormGroupContext } from './form-group-context.js';
4
14
 
5
15
  export interface Props extends Omit<HTMLInputAttributes, 'class' | 'value'> {
6
16
  value?: string | number;
7
17
  class?: string;
18
+ /** Stable identity and sensitivity metadata for interaction adapters. */
19
+ interaction?: ControlInteractionOptions | false;
8
20
  }
9
21
 
10
22
  let {
@@ -17,6 +29,8 @@ let {
17
29
  required = false,
18
30
  name,
19
31
  class: className = '',
32
+ interaction,
33
+ 'aria-label': ariaLabel,
20
34
  'aria-describedby': ariaDescribedby,
21
35
  'aria-invalid': ariaInvalid,
22
36
  ...rest
@@ -25,6 +39,8 @@ let {
25
39
  // When wrapped in a <FormGroup>, inherit the id (so its <label for> resolves),
26
40
  // the hint/error association, and the error state — unless set explicitly.
27
41
  const formGroup = tryGetFormGroupContext();
42
+ const controlInteraction = tryGetControlInteractionContext();
43
+ let inputEl = $state<HTMLInputElement | null>(null);
28
44
  const resolvedId = $derived(id ?? formGroup?.().inputId);
29
45
  const resolvedDescribedBy = $derived(
30
46
  ariaDescribedby ?? formGroup?.().describedBy,
@@ -32,9 +48,111 @@ const resolvedDescribedBy = $derived(
32
48
  const resolvedInvalid = $derived(
33
49
  ariaInvalid ?? (formGroup?.().invalid ? 'true' : undefined),
34
50
  );
51
+
52
+ const resolvedInteraction = $derived.by(() => {
53
+ const inherited = formGroup?.().interaction;
54
+ if (interaction === false || inherited === false) return false;
55
+ return { ...(inherited ?? {}), ...(interaction ?? {}) };
56
+ });
57
+ const resolvedControlId = $derived(
58
+ resolvedInteraction === false
59
+ ? undefined
60
+ : (resolvedInteraction.id ?? name ?? resolvedId),
61
+ );
62
+
63
+ function kindFromType(): ControlKind {
64
+ switch (type) {
65
+ case 'email':
66
+ return 'email';
67
+ case 'password':
68
+ return 'password';
69
+ case 'number':
70
+ return 'number';
71
+ case 'date':
72
+ return 'date';
73
+ case 'time':
74
+ return 'time';
75
+ case 'datetime-local':
76
+ return 'datetime';
77
+ case 'range':
78
+ return 'slider';
79
+ default:
80
+ return 'text';
81
+ }
82
+ }
83
+
84
+ function setControlValue(next: unknown) {
85
+ value =
86
+ type === 'number' || type === 'range' ? Number(next) : String(next ?? '');
87
+ if (inputEl) emitControlChange(inputEl);
88
+ }
89
+
90
+ $effect(() => {
91
+ const context = controlInteraction;
92
+ const element = inputEl;
93
+ const controlId = resolvedControlId;
94
+ const options = resolvedInteraction;
95
+ if (!context || !element || !controlId || options === false) return;
96
+
97
+ return context.registry.register({
98
+ identity: {
99
+ formId: context.formId,
100
+ controlId,
101
+ subject: options.subject,
102
+ },
103
+ metadata: {
104
+ kind: kindFromType(),
105
+ label: formGroup?.().label ?? ariaLabel ?? undefined,
106
+ description: options.description ?? formGroup?.().description,
107
+ sensitivity:
108
+ options.sensitivity ?? (type === 'password' ? 'secret' : 'public'),
109
+ readable: options.readable,
110
+ writable: options.writable,
111
+ constraints: {
112
+ required: required === true,
113
+ min: element.min || undefined,
114
+ max: element.max || undefined,
115
+ step: element.step || undefined,
116
+ minLength: element.minLength >= 0 ? element.minLength : undefined,
117
+ maxLength: element.maxLength >= 0 ? element.maxLength : undefined,
118
+ pattern: element.pattern || undefined,
119
+ },
120
+ },
121
+ getValue: () => value,
122
+ setValue: setControlValue,
123
+ clear: () => setControlValue(''),
124
+ focus: () => element.focus(),
125
+ reveal: () => revealControl(element),
126
+ highlight: (durationMs) => highlightControl(element, durationMs),
127
+ validate: () => element.reportValidity(),
128
+ getState: () => ({
129
+ disabled: element.disabled,
130
+ readonly: element.readOnly,
131
+ valid: element.validity.valid,
132
+ validationMessage: element.validationMessage || undefined,
133
+ }),
134
+ });
135
+ });
136
+
137
+ export function focus(): void {
138
+ inputEl?.focus();
139
+ }
140
+
141
+ export function reveal(): void {
142
+ if (inputEl) revealControl(inputEl);
143
+ }
144
+
145
+ export function highlight(durationMs?: number): void {
146
+ if (inputEl) highlightControl(inputEl, durationMs);
147
+ }
148
+
149
+ export function getElement(): HTMLInputElement | null {
150
+ return inputEl;
151
+ }
35
152
  </script>
36
153
 
37
154
  <input
155
+ bind:this={inputEl}
38
156
  id={resolvedId}
39
157
  {type}
40
158
  bind:value
@@ -43,9 +161,12 @@ const resolvedInvalid = $derived(
43
161
  {readonly}
44
162
  {required}
45
163
  {name}
164
+ aria-label={ariaLabel}
46
165
  aria-describedby={resolvedDescribedBy}
47
166
  aria-invalid={resolvedInvalid}
48
167
  class="input {className}"
168
+ data-smrt-control={resolvedControlId}
169
+ data-smrt-form={controlInteraction?.formId}
49
170
  {...rest}
50
171
  />
51
172
 
@@ -71,6 +192,12 @@ const resolvedInvalid = $derived(
71
192
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--smrt-color-primary, #005ac1) 10%, transparent);
72
193
  }
73
194
 
195
+ .input[data-smrt-highlighted='true'] {
196
+ outline: 3px solid var(--smrt-color-tertiary, #7d5260);
197
+ outline-offset: 3px;
198
+ box-shadow: 0 0 0 6px color-mix(in srgb, var(--smrt-color-tertiary, #7d5260) 20%, transparent);
199
+ }
200
+
74
201
  .input:disabled {
75
202
  background-color: var(--smrt-color-surface-container-high, #f3f4f6);
76
203
  cursor: not-allowed;
@@ -1,9 +1,17 @@
1
1
  import type { HTMLInputAttributes } from 'svelte/elements';
2
+ import type { ControlInteractionOptions } from './control-interaction.js';
2
3
  export interface Props extends Omit<HTMLInputAttributes, 'class' | 'value'> {
3
4
  value?: string | number;
4
5
  class?: string;
6
+ /** Stable identity and sensitivity metadata for interaction adapters. */
7
+ interaction?: ControlInteractionOptions | false;
5
8
  }
6
- declare const Input: import("svelte").Component<Props, {}, "value">;
9
+ declare const Input: import("svelte").Component<Props, {
10
+ focus: () => void;
11
+ reveal: () => void;
12
+ highlight: (durationMs?: number) => void;
13
+ getElement: () => HTMLInputElement | null;
14
+ }, "value">;
7
15
  type Input = ReturnType<typeof Input>;
8
16
  export default Input;
9
17
  //# sourceMappingURL=Input.svelte.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Input.svelte.d.ts","sourceRoot":"","sources":["../../../src/components/forms/Input.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAI3D,MAAM,WAAW,KAAM,SAAQ,IAAI,CAAC,mBAAmB,EAAE,OAAO,GAAG,OAAO,CAAC;IACzE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAuCD,QAAA,MAAM,KAAK,gDAAwC,CAAC;AACpD,KAAK,KAAK,GAAG,UAAU,CAAC,OAAO,KAAK,CAAC,CAAC;AACtC,eAAe,KAAK,CAAC"}
1
+ {"version":3,"file":"Input.svelte.d.ts","sourceRoot":"","sources":["../../../src/components/forms/Input.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAM3D,OAAO,KAAK,EACV,yBAAyB,EAE1B,MAAM,0BAA0B,CAAC;AAKlC,MAAM,WAAW,KAAM,SAAQ,IAAI,CAAC,mBAAmB,EAAE,OAAO,GAAG,OAAO,CAAC;IACzE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yEAAyE;IACzE,WAAW,CAAC,EAAE,yBAAyB,GAAG,KAAK,CAAC;CACjD;AAmJD,QAAA,MAAM,KAAK;iBAvBQ,IAAI;kBAIH,IAAI;6BAIS,MAAM,KAAG,IAAI;sBAItB,gBAAgB,GAAG,IAAI;WAWI,CAAC;AACpD,KAAK,KAAK,GAAG,UAAU,CAAC,OAAO,KAAK,CAAC,CAAC;AACtC,eAAe,KAAK,CAAC"}
@@ -0,0 +1,17 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+ export interface Props {
4
+ prefix?: Snippet;
5
+ suffix?: Snippet;
6
+ children: Snippet;
7
+ class?: string;
8
+ }
9
+ let { prefix, suffix, children, class: className = '' }: Props = $props();
10
+ </script>
11
+ <div class="input-group {className}">{#if prefix}<span class="adornment">{@render prefix()}</span>{/if}<div class="control">{@render children()}</div>{#if suffix}<span class="adornment">{@render suffix()}</span>{/if}</div>
12
+ <style>
13
+ .input-group { display: flex; align-items: stretch; width: 100%; border: 1px solid var(--smrt-color-outline-variant); border-radius: var(--smrt-radius-small); background: var(--smrt-color-surface); overflow: hidden; }
14
+ .adornment { display: inline-flex; align-items: center; padding: 0 var(--smrt-spacing-3); background: var(--smrt-color-surface-container-low); color: var(--smrt-color-on-surface-variant); }
15
+ .control { flex: 1; min-width: 0; } .control :global(input), .control :global(select), .control :global(textarea) { border: 0 !important; border-radius: 0 !important; box-shadow: none !important; }
16
+ .input-group:focus-within { outline: 2px solid var(--smrt-color-primary); outline-offset: 1px; }
17
+ </style>
@@ -0,0 +1,11 @@
1
+ import type { Snippet } from 'svelte';
2
+ export interface Props {
3
+ prefix?: Snippet;
4
+ suffix?: Snippet;
5
+ children: Snippet;
6
+ class?: string;
7
+ }
8
+ declare const InputGroup: import("svelte").Component<Props, {}, "">;
9
+ type InputGroup = ReturnType<typeof InputGroup>;
10
+ export default InputGroup;
11
+ //# sourceMappingURL=InputGroup.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InputGroup.svelte.d.ts","sourceRoot":"","sources":["../../../src/components/forms/InputGroup.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAEtC,MAAM,WAAW,KAAK;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAWD,QAAA,MAAM,UAAU,2CAAwC,CAAC;AACzD,KAAK,UAAU,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;AAChD,eAAe,UAAU,CAAC"}
@@ -0,0 +1,97 @@
1
+ <script lang="ts">
2
+ import { highlightControl, revealControl } from './control-dom.js';
3
+ import type {
4
+ ControlInteractionOptions,
5
+ ControlOption,
6
+ } from './control-interaction.js';
7
+ import { tryGetControlInteractionContext } from './control-interaction-context.js';
8
+ import { useControlRegistration } from './use-control-registration.svelte.js';
9
+ export interface Props {
10
+ options: ControlOption[];
11
+ value?: string | number;
12
+ label: string;
13
+ name?: string;
14
+ disabled?: boolean;
15
+ interaction?: ControlInteractionOptions | false;
16
+ onvaluechange?: (value: string | number) => void;
17
+ class?: string;
18
+ }
19
+ let {
20
+ options,
21
+ value = $bindable(),
22
+ label,
23
+ name,
24
+ disabled = false,
25
+ interaction,
26
+ onvaluechange,
27
+ class: className = '',
28
+ }: Props = $props();
29
+ const instanceId = $props.id();
30
+ const interactionContext = tryGetControlInteractionContext();
31
+ let rootEl = $state<HTMLDivElement | null>(null);
32
+ let optionEls = $state<Array<HTMLButtonElement | null>>([]);
33
+ const controlId = $derived(
34
+ interaction === false
35
+ ? undefined
36
+ : (interaction?.id ?? name ?? `listbox-${instanceId}`),
37
+ );
38
+ function select(next: unknown) {
39
+ const option = options.find((item) => String(item.value) === String(next));
40
+ if (!option || option.disabled || disabled) return;
41
+ value = option.value;
42
+ onvaluechange?.(option.value);
43
+ }
44
+ function move(event: KeyboardEvent, index: number) {
45
+ let next = index;
46
+ if (event.key === 'ArrowDown') next = (index + 1) % options.length;
47
+ else if (event.key === 'ArrowUp')
48
+ next = (index - 1 + options.length) % options.length;
49
+ else if (event.key === 'Home') next = 0;
50
+ else if (event.key === 'End') next = options.length - 1;
51
+ else return;
52
+ event.preventDefault();
53
+ while (options[next]?.disabled && next !== index)
54
+ next =
55
+ event.key === 'ArrowUp'
56
+ ? (next - 1 + options.length) % options.length
57
+ : (next + 1) % options.length;
58
+ optionEls[next]?.focus();
59
+ }
60
+ useControlRegistration(() => {
61
+ const root = rootEl;
62
+ if (!root || interaction === false) return false;
63
+ return {
64
+ controlId,
65
+ subject: interaction?.subject,
66
+ metadata: {
67
+ kind: 'listbox',
68
+ label,
69
+ description: interaction?.description,
70
+ sensitivity: interaction?.sensitivity ?? 'public',
71
+ readable: interaction?.readable,
72
+ writable: interaction?.writable,
73
+ options,
74
+ },
75
+ getValue: () => value,
76
+ setValue: select,
77
+ clear: () => {
78
+ value = undefined;
79
+ },
80
+ focus: () => optionEls.find((item) => item && !item.disabled)?.focus(),
81
+ reveal: () => revealControl(root),
82
+ highlight: (durationMs) => highlightControl(root, durationMs),
83
+ getState: () => ({ disabled }),
84
+ };
85
+ });
86
+ </script>
87
+ <div bind:this={rootEl} class="listbox {className}" role="listbox" aria-label={label} aria-disabled={disabled} data-smrt-control={controlId} data-smrt-form={interactionContext?.formId}>
88
+ {#each options as option, index (option.value)}<button bind:this={optionEls[index]} type="button" role="option" aria-selected={value === option.value}
89
+ disabled={disabled || option.disabled} tabindex={value === option.value || (value === undefined && index === 0) ? 0 : -1}
90
+ onkeydown={(event) => move(event, index)} onclick={() => select(option.value)}>{option.label}</button>{/each}
91
+ </div>
92
+ <style>
93
+ .listbox { display: grid; padding: var(--smrt-spacing-1); border: 1px solid var(--smrt-color-outline-variant); border-radius: var(--smrt-radius-small); background: var(--smrt-color-surface); }
94
+ button { padding: var(--smrt-spacing-2) var(--smrt-spacing-3); border: 0; border-radius: var(--smrt-radius-extra-small); background: transparent; color: var(--smrt-color-on-surface); text-align: left; cursor: pointer; }
95
+ button[aria-selected='true'] { background: var(--smrt-color-secondary-container); color: var(--smrt-color-on-secondary-container); } button:focus-visible { outline: 2px solid var(--smrt-color-primary); }
96
+ button:disabled { opacity: .5; cursor: not-allowed; } :global(.listbox[data-smrt-highlighted='true']) { outline: 3px solid var(--smrt-color-tertiary); outline-offset: 4px; }
97
+ </style>
@@ -0,0 +1,15 @@
1
+ import type { ControlInteractionOptions, ControlOption } from './control-interaction.js';
2
+ export interface Props {
3
+ options: ControlOption[];
4
+ value?: string | number;
5
+ label: string;
6
+ name?: string;
7
+ disabled?: boolean;
8
+ interaction?: ControlInteractionOptions | false;
9
+ onvaluechange?: (value: string | number) => void;
10
+ class?: string;
11
+ }
12
+ declare const Listbox: import("svelte").Component<Props, {}, "value">;
13
+ type Listbox = ReturnType<typeof Listbox>;
14
+ export default Listbox;
15
+ //# sourceMappingURL=Listbox.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Listbox.svelte.d.ts","sourceRoot":"","sources":["../../../src/components/forms/Listbox.svelte.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,yBAAyB,EACzB,aAAa,EACd,MAAM,0BAA0B,CAAC;AAIlC,MAAM,WAAW,KAAK;IACpB,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,yBAAyB,GAAG,KAAK,CAAC;IAChD,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,KAAK,IAAI,CAAC;IACjD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAkFD,QAAA,MAAM,OAAO,gDAAwC,CAAC;AACtD,KAAK,OAAO,GAAG,UAAU,CAAC,OAAO,OAAO,CAAC,CAAC;AAC1C,eAAe,OAAO,CAAC"}
@@ -0,0 +1,159 @@
1
+ <script lang="ts">
2
+ import { tick } from 'svelte';
3
+ import { highlightControl, revealControl } from './control-dom.js';
4
+ import type {
5
+ ControlInteractionOptions,
6
+ ControlOption,
7
+ } from './control-interaction.js';
8
+ import { tryGetControlInteractionContext } from './control-interaction-context.js';
9
+ import { useControlRegistration } from './use-control-registration.svelte.js';
10
+ export interface Props {
11
+ options: ControlOption[];
12
+ values?: Array<string | number>;
13
+ label: string;
14
+ name?: string;
15
+ placeholder?: string;
16
+ disabled?: boolean;
17
+ interaction?: ControlInteractionOptions | false;
18
+ onvalueschange?: (values: Array<string | number>) => void;
19
+ class?: string;
20
+ }
21
+ let {
22
+ options,
23
+ values = $bindable([]),
24
+ label,
25
+ name,
26
+ placeholder = 'Select options',
27
+ disabled = false,
28
+ interaction,
29
+ onvalueschange,
30
+ class: className = '',
31
+ }: Props = $props();
32
+ const instanceId = $props.id();
33
+ const listId = `smrt-multiselect-${instanceId}`;
34
+ const triggerId = `${listId}-trigger`;
35
+ const interactionContext = tryGetControlInteractionContext();
36
+ let rootEl = $state<HTMLDivElement | null>(null);
37
+ let triggerEl = $state<HTMLButtonElement | null>(null);
38
+ let optionEls = $state<Array<HTMLButtonElement | null>>([]);
39
+ let open = $state(false);
40
+ const controlId = $derived(
41
+ interaction === false ? undefined : (interaction?.id ?? name ?? listId),
42
+ );
43
+ const selectedLabels = $derived(
44
+ options
45
+ .filter((option) =>
46
+ values.some((value) => String(value) === String(option.value)),
47
+ )
48
+ .map((option) => option.label),
49
+ );
50
+ function toggle(option: ControlOption) {
51
+ if (option.disabled || disabled) return;
52
+ const has = values.some((value) => String(value) === String(option.value));
53
+ values = has
54
+ ? values.filter((value) => String(value) !== String(option.value))
55
+ : [...values, option.value];
56
+ onvalueschange?.(values);
57
+ }
58
+ function setValues(next: unknown) {
59
+ if (!Array.isArray(next)) return;
60
+ values = options
61
+ .filter(
62
+ (option) =>
63
+ next.some((value) => String(value) === String(option.value)) &&
64
+ !option.disabled,
65
+ )
66
+ .map((option) => option.value);
67
+ onvalueschange?.(values);
68
+ }
69
+ async function openOptions(focusFirst = false) {
70
+ if (disabled) return;
71
+ open = true;
72
+ if (focusFirst) {
73
+ await tick();
74
+ optionEls.find((element) => element && !element.disabled)?.focus();
75
+ }
76
+ }
77
+ function closeOptions(refocus = false) {
78
+ open = false;
79
+ if (refocus) triggerEl?.focus();
80
+ }
81
+ function handleTriggerKeydown(event: KeyboardEvent) {
82
+ if (event.key === 'ArrowDown') {
83
+ event.preventDefault();
84
+ openOptions(true);
85
+ } else if (event.key === 'Escape') {
86
+ closeOptions();
87
+ }
88
+ }
89
+ function handleOptionsKeydown(event: KeyboardEvent) {
90
+ if (event.key === 'Escape') {
91
+ event.preventDefault();
92
+ closeOptions(true);
93
+ return;
94
+ }
95
+ if (event.key === 'Tab') {
96
+ closeOptions();
97
+ return;
98
+ }
99
+ if (!['ArrowDown', 'ArrowUp', 'Home', 'End'].includes(event.key)) return;
100
+ event.preventDefault();
101
+ const enabled = optionEls.filter(
102
+ (element): element is HTMLButtonElement => !!element && !element.disabled,
103
+ );
104
+ if (enabled.length === 0) return;
105
+ const current = enabled.indexOf(document.activeElement as HTMLButtonElement);
106
+ const next =
107
+ event.key === 'Home'
108
+ ? 0
109
+ : event.key === 'End'
110
+ ? enabled.length - 1
111
+ : (current + (event.key === 'ArrowUp' ? -1 : 1) + enabled.length) %
112
+ enabled.length;
113
+ enabled[next]?.focus();
114
+ }
115
+ $effect(() => {
116
+ if (!open) return;
117
+ const dismiss = (event: PointerEvent) => {
118
+ if (rootEl && !rootEl.contains(event.target as Node)) closeOptions();
119
+ };
120
+ document.addEventListener('pointerdown', dismiss, true);
121
+ return () => document.removeEventListener('pointerdown', dismiss, true);
122
+ });
123
+ useControlRegistration(() => {
124
+ const root = rootEl;
125
+ const trigger = triggerEl;
126
+ if (!root || !trigger || interaction === false) return false;
127
+ return {
128
+ controlId,
129
+ subject: interaction?.subject,
130
+ metadata: {
131
+ kind: 'multi-select',
132
+ label,
133
+ description: interaction?.description,
134
+ sensitivity: interaction?.sensitivity ?? 'public',
135
+ readable: interaction?.readable,
136
+ writable: interaction?.writable,
137
+ options,
138
+ },
139
+ getValue: () => [...values],
140
+ setValue: setValues,
141
+ clear: () => setValues([]),
142
+ focus: () => trigger.focus(),
143
+ reveal: () => revealControl(root),
144
+ highlight: (durationMs) => highlightControl(root, durationMs),
145
+ getState: () => ({ disabled }),
146
+ };
147
+ });
148
+ </script>
149
+ <div bind:this={rootEl} class="multi-select {className}" data-smrt-control={controlId} data-smrt-form={interactionContext?.formId}>
150
+ <span class="label" id={`${listId}-label`}>{label}</span><button bind:this={triggerEl} id={triggerId} type="button" class="trigger" {disabled} aria-haspopup="listbox" aria-expanded={open} aria-controls={listId} aria-labelledby={`${listId}-label ${triggerId}`} onclick={() => open ? closeOptions() : openOptions()} onkeydown={handleTriggerKeydown}>{selectedLabels.length ? selectedLabels.join(', ') : placeholder}</button>
151
+ {#if open}<div id={listId} class="options" role="listbox" tabindex="-1" aria-multiselectable="true" aria-labelledby={`${listId}-label`} onkeydown={handleOptionsKeydown}>{#each options as option, index (option.value)}<button bind:this={optionEls[index]} type="button" role="option" tabindex="-1" aria-selected={values.some((value) => String(value) === String(option.value))} disabled={option.disabled} onclick={() => toggle(option)}><span aria-hidden="true">{values.some((value) => String(value) === String(option.value)) ? '✓' : ''}</span>{option.label}</button>{/each}</div>{/if}
152
+ </div>
153
+ <style>
154
+ .multi-select { position: relative; display: grid; gap: var(--smrt-spacing-1); color: var(--smrt-color-on-surface); } .label { font: var(--smrt-typography-label-large-font); }
155
+ .trigger { width: 100%; min-height: 2.5rem; padding: var(--smrt-spacing-2) var(--smrt-spacing-3); border: 1px solid var(--smrt-color-outline-variant); border-radius: var(--smrt-radius-small); background: var(--smrt-color-surface); color: inherit; text-align: left; }
156
+ .options { position: absolute; z-index: var(--smrt-z-index-dropdown); top: 100%; left: 0; right: 0; display: grid; padding: var(--smrt-spacing-1); border: 1px solid var(--smrt-color-outline-variant); background: var(--smrt-color-surface-container); box-shadow: var(--smrt-elevation-2); }
157
+ .options button { display: grid; grid-template-columns: 1.25rem 1fr; gap: var(--smrt-spacing-2); padding: var(--smrt-spacing-2); border: 0; background: transparent; color: inherit; text-align: left; } .options button[aria-selected='true'] { background: var(--smrt-color-secondary-container); }
158
+ :global(.multi-select[data-smrt-highlighted='true']) { outline: 3px solid var(--smrt-color-tertiary); outline-offset: 4px; }
159
+ </style>
@@ -0,0 +1,16 @@
1
+ import type { ControlInteractionOptions, ControlOption } from './control-interaction.js';
2
+ export interface Props {
3
+ options: ControlOption[];
4
+ values?: Array<string | number>;
5
+ label: string;
6
+ name?: string;
7
+ placeholder?: string;
8
+ disabled?: boolean;
9
+ interaction?: ControlInteractionOptions | false;
10
+ onvalueschange?: (values: Array<string | number>) => void;
11
+ class?: string;
12
+ }
13
+ declare const MultiSelect: import("svelte").Component<Props, {}, "values">;
14
+ type MultiSelect = ReturnType<typeof MultiSelect>;
15
+ export default MultiSelect;
16
+ //# sourceMappingURL=MultiSelect.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MultiSelect.svelte.d.ts","sourceRoot":"","sources":["../../../src/components/forms/MultiSelect.svelte.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,yBAAyB,EACzB,aAAa,EACd,MAAM,0BAA0B,CAAC;AAIlC,MAAM,WAAW,KAAK;IACpB,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB,MAAM,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,yBAAyB,GAAG,KAAK,CAAC;IAChD,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,KAAK,IAAI,CAAC;IAC1D,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAgJD,QAAA,MAAM,WAAW,iDAAwC,CAAC;AAC1D,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;AAClD,eAAe,WAAW,CAAC"}
@@ -0,0 +1,34 @@
1
+ <script lang="ts">
2
+ import type { HTMLInputAttributes } from 'svelte/elements';
3
+ import { getRadioGroupContext } from './radio-group-context.js';
4
+ export interface Props
5
+ extends Omit<HTMLInputAttributes, 'type' | 'name' | 'checked' | 'value'> {
6
+ value: string;
7
+ label: string;
8
+ disabled?: boolean;
9
+ }
10
+ let { value, label, disabled = false, id, onchange, ...rest }: Props = $props();
11
+ const instanceId = $props.id();
12
+ const group = getRadioGroupContext();
13
+ const resolvedId = $derived(id ?? `smrt-radio-${instanceId}`);
14
+ $effect(() => group.registerOption({ value, label, disabled }));
15
+ function handleChange(event: Event & { currentTarget: HTMLInputElement }) {
16
+ if (event.currentTarget.checked) group.setValue(value);
17
+ onchange?.(event);
18
+ }
19
+ </script>
20
+ <label class="radio" class:disabled={disabled || group.disabled}>
21
+ <input id={resolvedId} type="radio" name={group.name} {value} disabled={disabled || group.disabled} required={group.required}
22
+ checked={group.value === value} onchange={handleChange} {...rest} />
23
+ <span class="radio__mark" aria-hidden="true"></span><span>{label}</span>
24
+ </label>
25
+ <style>
26
+ .radio { display: inline-flex; align-items: center; gap: var(--smrt-spacing-2); cursor: pointer; }
27
+ .radio.disabled { opacity: .5; cursor: not-allowed; }
28
+ input { position: absolute; opacity: 0; width: 1px; height: 1px; }
29
+ .radio__mark { width: 1.15rem; height: 1.15rem; border: 2px solid var(--smrt-color-outline); border-radius: 50%; display: grid; place-items: center; }
30
+ .radio__mark::after { content: ''; width: .55rem; height: .55rem; border-radius: 50%; background: var(--smrt-color-primary); transform: scale(0); transition: transform var(--smrt-duration-short2); }
31
+ input:checked + .radio__mark { border-color: var(--smrt-color-primary); }
32
+ input:checked + .radio__mark::after { transform: scale(1); }
33
+ input:focus-visible + .radio__mark { outline: 2px solid var(--smrt-color-primary); outline-offset: 3px; }
34
+ </style>
@@ -0,0 +1,10 @@
1
+ import type { HTMLInputAttributes } from 'svelte/elements';
2
+ export interface Props extends Omit<HTMLInputAttributes, 'type' | 'name' | 'checked' | 'value'> {
3
+ value: string;
4
+ label: string;
5
+ disabled?: boolean;
6
+ }
7
+ declare const Radio: import("svelte").Component<Props, {}, "">;
8
+ type Radio = ReturnType<typeof Radio>;
9
+ export default Radio;
10
+ //# sourceMappingURL=Radio.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Radio.svelte.d.ts","sourceRoot":"","sources":["../../../src/components/forms/Radio.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAG3D,MAAM,WAAW,KACf,SAAQ,IAAI,CAAC,mBAAmB,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC;IACxE,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAuBD,QAAA,MAAM,KAAK,2CAAwC,CAAC;AACpD,KAAK,KAAK,GAAG,UAAU,CAAC,OAAO,KAAK,CAAC,CAAC;AACtC,eAAe,KAAK,CAAC"}