@sveltier/ui 0.0.0-stage → 0.1.0-alpha.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 (276) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +82 -2
  3. package/dist/components/Alert/Alert.svelte +88 -0
  4. package/dist/components/Alert/Alert.svelte.d.ts +4 -0
  5. package/dist/components/Alert/alert.css +78 -0
  6. package/dist/components/Alert/index.d.ts +2 -0
  7. package/dist/components/Alert/index.js +1 -0
  8. package/dist/components/Alert/types.d.ts +67 -0
  9. package/dist/components/Alert/types.js +1 -0
  10. package/dist/components/Avatar/Avatar.svelte +47 -0
  11. package/dist/components/Avatar/Avatar.svelte.d.ts +4 -0
  12. package/dist/components/Avatar/avatar.css +34 -0
  13. package/dist/components/Avatar/index.d.ts +2 -0
  14. package/dist/components/Avatar/index.js +1 -0
  15. package/dist/components/Avatar/types.d.ts +47 -0
  16. package/dist/components/Avatar/types.js +1 -0
  17. package/dist/components/Badge/Badge.svelte +53 -0
  18. package/dist/components/Badge/Badge.svelte.d.ts +4 -0
  19. package/dist/components/Badge/badge.css +57 -0
  20. package/dist/components/Badge/index.d.ts +2 -0
  21. package/dist/components/Badge/index.js +1 -0
  22. package/dist/components/Badge/types.d.ts +43 -0
  23. package/dist/components/Badge/types.js +1 -0
  24. package/dist/components/Button/Button.svelte +85 -0
  25. package/dist/components/Button/Button.svelte.d.ts +4 -0
  26. package/dist/components/Button/button.css +132 -0
  27. package/dist/components/Button/index.d.ts +2 -0
  28. package/dist/components/Button/index.js +1 -0
  29. package/dist/components/Button/types.d.ts +76 -0
  30. package/dist/components/Button/types.js +1 -0
  31. package/dist/components/ButtonGroup/ButtonGroup.svelte +61 -0
  32. package/dist/components/ButtonGroup/ButtonGroup.svelte.d.ts +4 -0
  33. package/dist/components/ButtonGroup/button-group.css +39 -0
  34. package/dist/components/ButtonGroup/index.d.ts +2 -0
  35. package/dist/components/ButtonGroup/index.js +1 -0
  36. package/dist/components/ButtonGroup/types.d.ts +48 -0
  37. package/dist/components/ButtonGroup/types.js +1 -0
  38. package/dist/components/Card/Card.svelte +53 -0
  39. package/dist/components/Card/Card.svelte.d.ts +4 -0
  40. package/dist/components/Card/card.css +62 -0
  41. package/dist/components/Card/index.d.ts +2 -0
  42. package/dist/components/Card/index.js +1 -0
  43. package/dist/components/Card/types.d.ts +56 -0
  44. package/dist/components/Card/types.js +1 -0
  45. package/dist/components/Checkbox/Checkbox.svelte +105 -0
  46. package/dist/components/Checkbox/Checkbox.svelte.d.ts +4 -0
  47. package/dist/components/Checkbox/checkbox.css +138 -0
  48. package/dist/components/Checkbox/index.d.ts +2 -0
  49. package/dist/components/Checkbox/index.js +1 -0
  50. package/dist/components/Checkbox/types.d.ts +76 -0
  51. package/dist/components/Checkbox/types.js +1 -0
  52. package/dist/components/Chip/Chip.svelte +109 -0
  53. package/dist/components/Chip/Chip.svelte.d.ts +4 -0
  54. package/dist/components/Chip/chip.css +101 -0
  55. package/dist/components/Chip/index.d.ts +2 -0
  56. package/dist/components/Chip/index.js +1 -0
  57. package/dist/components/Chip/types.d.ts +69 -0
  58. package/dist/components/Chip/types.js +1 -0
  59. package/dist/components/Choice/Choice.svelte +60 -0
  60. package/dist/components/Choice/Choice.svelte.d.ts +4 -0
  61. package/dist/components/Choice/choice.css +75 -0
  62. package/dist/components/Choice/types.d.ts +43 -0
  63. package/dist/components/Choice/types.js +1 -0
  64. package/dist/components/Divider/Divider.svelte +19 -0
  65. package/dist/components/Divider/Divider.svelte.d.ts +4 -0
  66. package/dist/components/Divider/divider.css +23 -0
  67. package/dist/components/Divider/index.d.ts +2 -0
  68. package/dist/components/Divider/index.js +1 -0
  69. package/dist/components/Divider/types.d.ts +10 -0
  70. package/dist/components/Divider/types.js +1 -0
  71. package/dist/components/Field/Field.svelte +95 -0
  72. package/dist/components/Field/Field.svelte.d.ts +4 -0
  73. package/dist/components/Field/field.css +210 -0
  74. package/dist/components/Field/index.d.ts +3 -0
  75. package/dist/components/Field/index.js +2 -0
  76. package/dist/components/Field/types.d.ts +109 -0
  77. package/dist/components/Field/types.js +2 -0
  78. package/dist/components/Form/Form.svelte +93 -0
  79. package/dist/components/Form/Form.svelte.d.ts +8 -0
  80. package/dist/components/Form/form.css +16 -0
  81. package/dist/components/Form/index.d.ts +2 -0
  82. package/dist/components/Form/index.js +1 -0
  83. package/dist/components/Form/types.d.ts +38 -0
  84. package/dist/components/Form/types.js +1 -0
  85. package/dist/components/Icon/Icon.svelte +38 -0
  86. package/dist/components/Icon/Icon.svelte.d.ts +4 -0
  87. package/dist/components/Icon/icon.css +33 -0
  88. package/dist/components/Icon/index.d.ts +2 -0
  89. package/dist/components/Icon/index.js +1 -0
  90. package/dist/components/Icon/types.d.ts +34 -0
  91. package/dist/components/Icon/types.js +1 -0
  92. package/dist/components/List/List.svelte +39 -0
  93. package/dist/components/List/List.svelte.d.ts +4 -0
  94. package/dist/components/List/ListItem.svelte +57 -0
  95. package/dist/components/List/ListItem.svelte.d.ts +4 -0
  96. package/dist/components/List/index.d.ts +3 -0
  97. package/dist/components/List/index.js +2 -0
  98. package/dist/components/List/list.css +127 -0
  99. package/dist/components/List/types.d.ts +67 -0
  100. package/dist/components/List/types.js +1 -0
  101. package/dist/components/NativeSelect/NativeSelect.svelte +110 -0
  102. package/dist/components/NativeSelect/NativeSelect.svelte.d.ts +25 -0
  103. package/dist/components/NativeSelect/index.d.ts +2 -0
  104. package/dist/components/NativeSelect/index.js +1 -0
  105. package/dist/components/NativeSelect/native-select.css +45 -0
  106. package/dist/components/NativeSelect/types.d.ts +58 -0
  107. package/dist/components/NativeSelect/types.js +1 -0
  108. package/dist/components/NumberField/NumberField.svelte +246 -0
  109. package/dist/components/NumberField/NumberField.svelte.d.ts +4 -0
  110. package/dist/components/NumberField/index.d.ts +2 -0
  111. package/dist/components/NumberField/index.js +1 -0
  112. package/dist/components/NumberField/number-field.css +74 -0
  113. package/dist/components/NumberField/types.d.ts +73 -0
  114. package/dist/components/NumberField/types.js +1 -0
  115. package/dist/components/Progress/ProgressCircular.svelte +61 -0
  116. package/dist/components/Progress/ProgressCircular.svelte.d.ts +4 -0
  117. package/dist/components/Progress/ProgressLinear.svelte +44 -0
  118. package/dist/components/Progress/ProgressLinear.svelte.d.ts +4 -0
  119. package/dist/components/Progress/index.d.ts +3 -0
  120. package/dist/components/Progress/index.js +2 -0
  121. package/dist/components/Progress/progress-circular.css +61 -0
  122. package/dist/components/Progress/progress-linear.css +67 -0
  123. package/dist/components/Progress/types.d.ts +53 -0
  124. package/dist/components/Progress/types.js +1 -0
  125. package/dist/components/RadioGroup/RadioGroup.svelte +149 -0
  126. package/dist/components/RadioGroup/RadioGroup.svelte.d.ts +25 -0
  127. package/dist/components/RadioGroup/index.d.ts +2 -0
  128. package/dist/components/RadioGroup/index.js +1 -0
  129. package/dist/components/RadioGroup/radio-group.css +139 -0
  130. package/dist/components/RadioGroup/types.d.ts +93 -0
  131. package/dist/components/RadioGroup/types.js +1 -0
  132. package/dist/components/SegmentedControl/SegmentedControl.svelte +70 -0
  133. package/dist/components/SegmentedControl/SegmentedControl.svelte.d.ts +25 -0
  134. package/dist/components/SegmentedControl/index.d.ts +2 -0
  135. package/dist/components/SegmentedControl/index.js +1 -0
  136. package/dist/components/SegmentedControl/segmented-control.css +68 -0
  137. package/dist/components/SegmentedControl/types.d.ts +60 -0
  138. package/dist/components/SegmentedControl/types.js +1 -0
  139. package/dist/components/Skeleton/Skeleton.svelte +33 -0
  140. package/dist/components/Skeleton/Skeleton.svelte.d.ts +4 -0
  141. package/dist/components/Skeleton/index.d.ts +2 -0
  142. package/dist/components/Skeleton/index.js +1 -0
  143. package/dist/components/Skeleton/skeleton.css +70 -0
  144. package/dist/components/Skeleton/types.d.ts +25 -0
  145. package/dist/components/Skeleton/types.js +1 -0
  146. package/dist/components/Slider/Slider.svelte +153 -0
  147. package/dist/components/Slider/Slider.svelte.d.ts +4 -0
  148. package/dist/components/Slider/index.d.ts +2 -0
  149. package/dist/components/Slider/index.js +1 -0
  150. package/dist/components/Slider/slider.css +206 -0
  151. package/dist/components/Slider/types.d.ts +102 -0
  152. package/dist/components/Slider/types.js +1 -0
  153. package/dist/components/Switch/Switch.svelte +94 -0
  154. package/dist/components/Switch/Switch.svelte.d.ts +4 -0
  155. package/dist/components/Switch/index.d.ts +2 -0
  156. package/dist/components/Switch/index.js +1 -0
  157. package/dist/components/Switch/switch.css +118 -0
  158. package/dist/components/Switch/types.d.ts +67 -0
  159. package/dist/components/Switch/types.js +1 -0
  160. package/dist/components/Tabs/Tabs.svelte +93 -0
  161. package/dist/components/Tabs/Tabs.svelte.d.ts +25 -0
  162. package/dist/components/Tabs/index.d.ts +2 -0
  163. package/dist/components/Tabs/index.js +1 -0
  164. package/dist/components/Tabs/tabs.css +73 -0
  165. package/dist/components/Tabs/types.d.ts +59 -0
  166. package/dist/components/Tabs/types.js +1 -0
  167. package/dist/components/TextField/TextField.svelte +115 -0
  168. package/dist/components/TextField/TextField.svelte.d.ts +4 -0
  169. package/dist/components/TextField/index.d.ts +2 -0
  170. package/dist/components/TextField/index.js +1 -0
  171. package/dist/components/TextField/types.d.ts +57 -0
  172. package/dist/components/TextField/types.js +1 -0
  173. package/dist/components/Textarea/Textarea.svelte +116 -0
  174. package/dist/components/Textarea/Textarea.svelte.d.ts +4 -0
  175. package/dist/components/Textarea/index.d.ts +2 -0
  176. package/dist/components/Textarea/index.js +1 -0
  177. package/dist/components/Textarea/textarea.css +35 -0
  178. package/dist/components/Textarea/types.d.ts +60 -0
  179. package/dist/components/Textarea/types.js +1 -0
  180. package/dist/core/defaults/DefaultsProvider.svelte +30 -0
  181. package/dist/core/defaults/DefaultsProvider.svelte.d.ts +13 -0
  182. package/dist/core/defaults/context.d.ts +45 -0
  183. package/dist/core/defaults/context.js +38 -0
  184. package/dist/core/display/display.d.ts +39 -0
  185. package/dist/core/display/display.js +53 -0
  186. package/dist/core/errors/codes.d.ts +112 -0
  187. package/dist/core/errors/codes.js +96 -0
  188. package/dist/core/errors/errors.d.ts +8 -0
  189. package/dist/core/errors/errors.js +7 -0
  190. package/dist/core/form/constraints.d.ts +15 -0
  191. package/dist/core/form/constraints.js +42 -0
  192. package/dist/core/form/context.d.ts +19 -0
  193. package/dist/core/form/context.js +4 -0
  194. package/dist/core/form/field.svelte.d.ts +34 -0
  195. package/dist/core/form/field.svelte.js +66 -0
  196. package/dist/core/form/number.d.ts +24 -0
  197. package/dist/core/form/number.js +71 -0
  198. package/dist/core/form/types.d.ts +22 -0
  199. package/dist/core/form/types.js +1 -0
  200. package/dist/core/locale/locale.d.ts +55 -0
  201. package/dist/core/locale/locale.js +80 -0
  202. package/dist/core/props/classes.d.ts +21 -0
  203. package/dist/core/props/classes.js +44 -0
  204. package/dist/core/props/element.d.ts +18 -0
  205. package/dist/core/props/element.js +1 -0
  206. package/dist/core/props/types.d.ts +47 -0
  207. package/dist/core/props/types.js +16 -0
  208. package/dist/core/provider/UIProvider.svelte +60 -0
  209. package/dist/core/provider/UIProvider.svelte.d.ts +29 -0
  210. package/dist/core/theme/ThemeProvider.svelte +178 -0
  211. package/dist/core/theme/ThemeProvider.svelte.d.ts +25 -0
  212. package/dist/core/theme/color.d.ts +23 -0
  213. package/dist/core/theme/color.js +54 -0
  214. package/dist/core/theme/context.d.ts +25 -0
  215. package/dist/core/theme/context.js +14 -0
  216. package/dist/core/theme/css.d.ts +25 -0
  217. package/dist/core/theme/css.js +69 -0
  218. package/dist/core/theme/define.d.ts +11 -0
  219. package/dist/core/theme/define.js +21 -0
  220. package/dist/core/theme/resolve.d.ts +6 -0
  221. package/dist/core/theme/resolve.js +18 -0
  222. package/dist/core/theme/theme-provider.css +13 -0
  223. package/dist/core/theme/types.d.ts +35 -0
  224. package/dist/core/theme/types.js +61 -0
  225. package/dist/dev/off.d.ts +4 -0
  226. package/dist/dev/off.js +3 -0
  227. package/dist/dev/on.d.ts +8 -0
  228. package/dist/dev/on.js +33 -0
  229. package/dist/index.d.ts +58 -0
  230. package/dist/index.js +72 -0
  231. package/dist/primitives/anchored/anchored.d.ts +39 -0
  232. package/dist/primitives/anchored/anchored.js +104 -0
  233. package/dist/primitives/anchored/fallback.d.ts +31 -0
  234. package/dist/primitives/anchored/fallback.js +73 -0
  235. package/dist/primitives/focus/focus-trap.d.ts +25 -0
  236. package/dist/primitives/focus/focus-trap.js +86 -0
  237. package/dist/primitives/focus/roving-focus.d.ts +22 -0
  238. package/dist/primitives/focus/roving-focus.js +86 -0
  239. package/dist/primitives/focus/tabbable.d.ts +9 -0
  240. package/dist/primitives/focus/tabbable.js +75 -0
  241. package/dist/primitives/inert/inert-others.d.ts +12 -0
  242. package/dist/primitives/inert/inert-others.js +44 -0
  243. package/dist/primitives/keyboard/keymap.d.ts +17 -0
  244. package/dist/primitives/keyboard/keymap.js +39 -0
  245. package/dist/primitives/keyboard/typeahead.d.ts +18 -0
  246. package/dist/primitives/keyboard/typeahead.js +50 -0
  247. package/dist/primitives/layer/dismissable.d.ts +26 -0
  248. package/dist/primitives/layer/dismissable.js +84 -0
  249. package/dist/primitives/motion/easing.d.ts +9 -0
  250. package/dist/primitives/motion/easing.js +46 -0
  251. package/dist/primitives/motion/motion.d.ts +59 -0
  252. package/dist/primitives/motion/motion.js +80 -0
  253. package/dist/primitives/portal/Portal.svelte +37 -0
  254. package/dist/primitives/portal/Portal.svelte.d.ts +9 -0
  255. package/dist/primitives/portal/PortalContent.svelte +15 -0
  256. package/dist/primitives/portal/PortalContent.svelte.d.ts +9 -0
  257. package/dist/primitives/portal/portal.css +8 -0
  258. package/dist/primitives/scroll-lock/scroll-lock.d.ts +10 -0
  259. package/dist/primitives/scroll-lock/scroll-lock.js +33 -0
  260. package/dist/primitives/virtual/virtual-list.svelte.d.ts +65 -0
  261. package/dist/primitives/virtual/virtual-list.svelte.js +291 -0
  262. package/dist/styles/base.css +44 -0
  263. package/dist/styles/props.css +137 -0
  264. package/dist/styles/tokens.css +84 -0
  265. package/dist/styles/visually-hidden.css +16 -0
  266. package/dist/themes/aurora.d.ts +13 -0
  267. package/dist/themes/aurora.js +103 -0
  268. package/dist/themes/heritage.d.ts +13 -0
  269. package/dist/themes/heritage.js +102 -0
  270. package/dist/themes/maison.d.ts +13 -0
  271. package/dist/themes/maison.js +99 -0
  272. package/dist/themes/milano.d.ts +13 -0
  273. package/dist/themes/milano.js +101 -0
  274. package/dist/themes/monolith.d.ts +13 -0
  275. package/dist/themes/monolith.js +101 -0
  276. package/package.json +87 -5
@@ -0,0 +1,93 @@
1
+ import type { HTMLFieldsetAttributes } from 'svelte/elements';
2
+ import type { FieldError, Rule, ValidateOn } from '../../core/form/types.js';
3
+ import type { ElementProps } from '../../core/props/element.js';
4
+ import type { Color, Density, Size } from '../../core/props/types.js';
5
+ /** The RadioGroup props that `DefaultsProvider` and `UIProvider` can set for a subtree. */
6
+ export interface RadioGroupDefaults {
7
+ /**
8
+ * The colour of the chosen radio. An invalid group uses `error`.
9
+ * @default 'primary'
10
+ */
11
+ color: Color;
12
+ /**
13
+ * The size of the radios and their labels.
14
+ * @default 'md'
15
+ */
16
+ size: Size;
17
+ /**
18
+ * Multiplies the height of each row, never the text.
19
+ * @default 'default'
20
+ */
21
+ density: Density;
22
+ /**
23
+ * Mutes the group and disables every radio in it.
24
+ * @default false
25
+ */
26
+ disabled: boolean;
27
+ }
28
+ declare module '../../core/defaults/context.js' {
29
+ interface ComponentDefaults {
30
+ RadioGroup: RadioGroupDefaults;
31
+ }
32
+ }
33
+ /** One choice of a RadioGroup. */
34
+ export interface RadioGroupOption<T extends string | number = string> {
35
+ /** The value the group binds to when this radio is chosen. */
36
+ value: T;
37
+ /** What the radio says. */
38
+ label: string;
39
+ /** Help under the label, read out with the radio. */
40
+ hint?: string;
41
+ disabled?: boolean;
42
+ }
43
+ type RadioGroupOwnProps<T extends string | number> = Partial<RadioGroupDefaults> & {
44
+ /** The choices, in order. */
45
+ options: readonly RadioGroupOption<T>[];
46
+ /** The chosen value, or `null` for none. Bindable. */
47
+ value?: T | null;
48
+ /** The question the radios answer, as the group's legend. Without it, use `aria-label`. */
49
+ label?: string;
50
+ /** Help under the radios. An error replaces it. */
51
+ hint?: string;
52
+ /**
53
+ * An error from outside the group, such as the server's answer: a message, a list of which
54
+ * the first is shown, or `true` for an invalid state described elsewhere.
55
+ */
56
+ error?: FieldError;
57
+ /** Checks run in order after `required`, with the chosen value. The first message is shown. */
58
+ rules?: readonly Rule<T>[];
59
+ /** When the message shows. Defaults to the form's setting, else `'blur'`. */
60
+ validateOn?: ValidateOn;
61
+ /**
62
+ * A choice must be made. Adds an asterisk to the legend.
63
+ * @default false
64
+ */
65
+ required?: boolean;
66
+ /**
67
+ * Lays the radios side by side, wrapping when they run out of room.
68
+ * @default false
69
+ */
70
+ inline?: boolean;
71
+ /** The name the radios submit their value under. Generated when not given. */
72
+ name?: string;
73
+ };
74
+ /**
75
+ * One choice among a few options, all shown: native radios sharing a name in a `<fieldset>`,
76
+ * whose `<legend>` is the label. The arrow keys move the choice, as the platform does. `class`,
77
+ * `style`, `ref` and other attributes go to the `<fieldset>`. For many options, use a
78
+ * NativeSelect.
79
+ *
80
+ * @example
81
+ * <RadioGroup
82
+ * label="Pay out"
83
+ * name="payout"
84
+ * required
85
+ * options={[
86
+ * { value: 'daily', label: 'Every day' },
87
+ * { value: 'weekly', label: 'Every Monday', hint: 'Fewer, larger transfers' }
88
+ * ]}
89
+ * bind:value={payout}
90
+ * />
91
+ */
92
+ export type RadioGroupProps<T extends string | number = string> = ElementProps<HTMLFieldSetElement, Omit<HTMLFieldsetAttributes, 'children'>, RadioGroupOwnProps<T>>;
93
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,70 @@
1
+ <script lang="ts" generics="T extends string | number">
2
+ // One choice among a few, as a radio group. See SegmentedControlProps for the props.
3
+ import { useDefaults } from '../../core/defaults/context.js';
4
+ import { sharedClasses } from '../../core/props/classes.js';
5
+ import { rovingFocus } from '../../primitives/focus/roving-focus.js';
6
+ import './segmented-control.css';
7
+ import type {
8
+ SegmentedControlDefaults,
9
+ SegmentedControlOption,
10
+ SegmentedControlProps
11
+ } from './types.js';
12
+
13
+ let {
14
+ variant,
15
+ color,
16
+ size,
17
+ density,
18
+ rounded,
19
+ options,
20
+ value = $bindable(),
21
+ onchange,
22
+ disabled = false,
23
+ class: className,
24
+ ref = $bindable(null),
25
+ ...rest
26
+ }: SegmentedControlProps<T> = $props();
27
+
28
+ const resolve = useDefaults<SegmentedControlDefaults>('SegmentedControl', {
29
+ variant: 'elevated',
30
+ color: 'neutral',
31
+ size: 'md',
32
+ density: 'default',
33
+ rounded: true
34
+ });
35
+ const p = $derived(resolve({ variant, color, size, density, rounded }));
36
+ const index = $derived(options.findIndex((option) => option.value === value));
37
+
38
+ // Selection follows focus, as in a radio group: arrows move and pick.
39
+ function pick(option: SegmentedControlOption<T>) {
40
+ if (disabled || option.disabled || option.value === value) return;
41
+ value = option.value;
42
+ onchange?.(option.value);
43
+ }
44
+ </script>
45
+
46
+ <div
47
+ bind:this={ref}
48
+ {...rest}
49
+ role="radiogroup"
50
+ class={['sv-segmented', sharedClasses(p, 'SegmentedControl'), className]}
51
+ style:--sv-segments={options.length}
52
+ style:--sv-segment={index}
53
+ {@attach rovingFocus({ orientation: 'horizontal' })}
54
+ >
55
+ {#if index >= 0}<span class="sv-segmented__thumb" aria-hidden="true"></span>{/if}
56
+ {#each options as option (option.value)}
57
+ <button
58
+ type="button"
59
+ role="radio"
60
+ class="sv-segmented__option"
61
+ data-sv-item
62
+ aria-checked={option.value === value}
63
+ disabled={disabled || option.disabled}
64
+ onclick={() => pick(option)}
65
+ onfocus={() => pick(option)}
66
+ >
67
+ {option.label}
68
+ </button>
69
+ {/each}
70
+ </div>
@@ -0,0 +1,25 @@
1
+ import type { SegmentedControlProps } from './types.js';
2
+ declare function $$render<T extends string | number>(): {
3
+ props: SegmentedControlProps<T>;
4
+ exports: {};
5
+ bindings: "ref" | "value";
6
+ slots: {};
7
+ events: {};
8
+ };
9
+ declare class __sveltets_Render<T extends string | number> {
10
+ props(): ReturnType<typeof $$render<T>>['props'];
11
+ events(): ReturnType<typeof $$render<T>>['events'];
12
+ slots(): ReturnType<typeof $$render<T>>['slots'];
13
+ bindings(): "ref" | "value";
14
+ exports(): {};
15
+ }
16
+ interface $$IsomorphicComponent {
17
+ new <T extends string | number>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<T>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<T>['props']>, ReturnType<__sveltets_Render<T>['events']>, ReturnType<__sveltets_Render<T>['slots']>> & {
18
+ $$bindings?: ReturnType<__sveltets_Render<T>['bindings']>;
19
+ } & ReturnType<__sveltets_Render<T>['exports']>;
20
+ <T extends string | number>(internal: unknown, props: ReturnType<__sveltets_Render<T>['props']> & {}): ReturnType<__sveltets_Render<T>['exports']>;
21
+ z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
22
+ }
23
+ declare const SegmentedControl: $$IsomorphicComponent;
24
+ type SegmentedControl<T extends string | number> = InstanceType<typeof SegmentedControl<T>>;
25
+ export default SegmentedControl;
@@ -0,0 +1,2 @@
1
+ export { default as SegmentedControl } from './SegmentedControl.svelte';
2
+ export type { SegmentedControlDefaults, SegmentedControlOption, SegmentedControlProps } from './types.js';
@@ -0,0 +1 @@
1
+ export { default as SegmentedControl } from './SegmentedControl.svelte';
@@ -0,0 +1,68 @@
1
+ @layer sv.tokens, sv.base, sv.components, sv.utilities;
2
+
3
+ @layer sv.components {
4
+ /*
5
+ * Segments share the width of the widest, so the thumb moves one segment per step with
6
+ * translate alone. The selected segment is painted by the variant classes.
7
+ */
8
+ .sv-segmented {
9
+ --sv-segmented-pad: var(--sv-space-3);
10
+ position: relative;
11
+ isolation: isolate;
12
+ display: inline-grid;
13
+ grid-auto-columns: 1fr;
14
+ grid-auto-flow: column;
15
+ box-sizing: border-box;
16
+ max-inline-size: 100%;
17
+ block-size: calc(var(--sv-size-height) * var(--sv-density));
18
+ padding: var(--sv-segmented-pad);
19
+ border-radius: var(--sv-rounded, var(--sv-radius-md));
20
+ background-color: var(--sv-color-surface-raised);
21
+ vertical-align: middle;
22
+ }
23
+
24
+ .sv-segmented__thumb {
25
+ position: absolute;
26
+ inset-block: var(--sv-segmented-pad);
27
+ inset-inline-start: var(--sv-segmented-pad);
28
+ z-index: -1;
29
+ inline-size: calc((100% - 2 * var(--sv-segmented-pad)) / var(--sv-segments));
30
+ border: var(--sv-hairline) solid var(--sv-variant-border);
31
+ border-radius: calc(var(--sv-rounded, var(--sv-radius-md)) - var(--sv-segmented-pad));
32
+ box-sizing: border-box;
33
+ background-color: var(--sv-variant-bg);
34
+ box-shadow: var(--sv-variant-shadow);
35
+ translate: calc(var(--sv-segment) * 100%) 0;
36
+ transition: translate var(--sv-duration-normal) var(--sv-ease);
37
+ }
38
+
39
+ /* An attribute selector, as minifiers rewrite :dir() into language guesses. */
40
+ :where([dir='rtl']) .sv-segmented__thumb {
41
+ translate: calc(var(--sv-segment) * -100%) 0;
42
+ }
43
+
44
+ .sv-segmented__option {
45
+ min-inline-size: 0;
46
+ margin: 0;
47
+ padding: 0 calc(var(--sv-size-height) * var(--sv-density) * 0.382);
48
+ overflow: hidden;
49
+ border: 0;
50
+ border-radius: calc(var(--sv-rounded, var(--sv-radius-md)) - var(--sv-segmented-pad));
51
+ background: transparent;
52
+ color: var(--sv-color-text-muted);
53
+ font: var(--sv-weight-medium) var(--sv-size-text) / 1 var(--sv-font-ui);
54
+ text-overflow: ellipsis;
55
+ white-space: nowrap;
56
+ cursor: pointer;
57
+ -webkit-tap-highlight-color: transparent;
58
+ }
59
+
60
+ .sv-segmented__option[aria-checked='true'] {
61
+ color: var(--sv-variant-fg);
62
+ }
63
+
64
+ .sv-segmented__option:disabled {
65
+ opacity: 0.382;
66
+ cursor: not-allowed;
67
+ }
68
+ }
@@ -0,0 +1,60 @@
1
+ import type { HTMLAttributes } from 'svelte/elements';
2
+ import type { ElementProps } from '../../core/props/element.js';
3
+ import type { Color, Density, Rounded, Size, Variant } from '../../core/props/types.js';
4
+ /** The SegmentedControl props that `DefaultsProvider` and `UIProvider` can set for a subtree. */
5
+ export interface SegmentedControlDefaults {
6
+ /**
7
+ * How the selected segment is painted: a raised surface by default.
8
+ * @default 'elevated'
9
+ */
10
+ variant: Variant;
11
+ /**
12
+ * The colour of the selected segment.
13
+ * @default 'neutral'
14
+ */
15
+ color: Color;
16
+ /**
17
+ * Height and text size.
18
+ * @default 'md'
19
+ */
20
+ size: Size;
21
+ /**
22
+ * Multiplies the height and padding, never the text.
23
+ * @default 'default'
24
+ */
25
+ density: Density;
26
+ /**
27
+ * Corner rounding. `true` keeps the theme's radius.
28
+ * @default true
29
+ */
30
+ rounded: Rounded;
31
+ }
32
+ declare module '../../core/defaults/context.js' {
33
+ interface ComponentDefaults {
34
+ SegmentedControl: SegmentedControlDefaults;
35
+ }
36
+ }
37
+ /** One choice of a SegmentedControl. */
38
+ export interface SegmentedControlOption<T extends string | number = string> {
39
+ value: T;
40
+ /** What the segment says. */
41
+ label: string;
42
+ disabled?: boolean;
43
+ }
44
+ /**
45
+ * One choice among a few options, side by side, as a radio group with one tab stop. Name it
46
+ * with `aria-label`.
47
+ */
48
+ export type SegmentedControlProps<T extends string | number = string> = ElementProps<HTMLDivElement, HTMLAttributes<HTMLDivElement>, Partial<SegmentedControlDefaults> & {
49
+ /** The choices, in order. */
50
+ options: readonly SegmentedControlOption<T>[];
51
+ /** The chosen value. Bindable. */
52
+ value?: T;
53
+ /** Called with the value the user picks. */
54
+ onchange?: (value: T) => void;
55
+ /**
56
+ * Disables every option.
57
+ * @default false
58
+ */
59
+ disabled?: boolean;
60
+ }>;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,33 @@
1
+ <script lang="ts">
2
+ // A loading placeholder. See SkeletonProps for the props.
3
+ import { sharedClasses } from '../../core/props/classes.js';
4
+ import './skeleton.css';
5
+ import type { SkeletonProps } from './types.js';
6
+
7
+ let {
8
+ type = 'text',
9
+ lines = 1,
10
+ size = 'md',
11
+ class: className,
12
+ ref = $bindable(null),
13
+ ...rest
14
+ }: SkeletonProps = $props();
15
+
16
+ const count = $derived(Math.max(1, Math.trunc(lines) || 1));
17
+ </script>
18
+
19
+ <span
20
+ bind:this={ref}
21
+ {...rest}
22
+ aria-hidden="true"
23
+ class={[
24
+ 'sv-skeleton',
25
+ `sv-skeleton--${type}`,
26
+ type === 'circle' && sharedClasses({ size }, 'Skeleton'),
27
+ className
28
+ ]}
29
+ >
30
+ {#if type === 'text'}
31
+ {#each { length: count }, line (line)}<span class="sv-skeleton__line"></span>{/each}
32
+ {/if}
33
+ </span>
@@ -0,0 +1,4 @@
1
+ import type { SkeletonProps } from './types.js';
2
+ declare const Skeleton: import("svelte").Component<SkeletonProps, {}, "ref">;
3
+ type Skeleton = ReturnType<typeof Skeleton>;
4
+ export default Skeleton;
@@ -0,0 +1,2 @@
1
+ export { default as Skeleton } from './Skeleton.svelte';
2
+ export type { SkeletonProps } from './types.js';
@@ -0,0 +1 @@
1
+ export { default as Skeleton } from './Skeleton.svelte';
@@ -0,0 +1,70 @@
1
+ @layer sv.tokens, sv.base, sv.components, sv.utilities;
2
+
3
+ @layer sv.components {
4
+ .sv-skeleton,
5
+ .sv-skeleton__line {
6
+ position: relative;
7
+ display: block;
8
+ overflow: hidden;
9
+ border-radius: var(--sv-radius-sm);
10
+ background-color: var(--sv-color-surface-raised);
11
+ }
12
+
13
+ /* Lines as tall as the text around them, a φ⁻¹ gap apart. */
14
+ .sv-skeleton--text {
15
+ display: grid;
16
+ gap: 0.618em;
17
+ overflow: visible;
18
+ background-color: transparent;
19
+ }
20
+
21
+ .sv-skeleton__line {
22
+ block-size: 1em;
23
+ }
24
+
25
+ .sv-skeleton__line:last-child:not(:first-child) {
26
+ inline-size: 61.8%;
27
+ }
28
+
29
+ .sv-skeleton--rect {
30
+ inline-size: 100%;
31
+ aspect-ratio: 1.618;
32
+ /* The control radius, never rounder than a card, even where controls are pills. */
33
+ border-radius: min(var(--sv-radius-md), var(--sv-radius-lg));
34
+ }
35
+
36
+ .sv-skeleton--circle {
37
+ inline-size: var(--sv-size-height);
38
+ block-size: var(--sv-size-height);
39
+ border-radius: 50%;
40
+ }
41
+
42
+ /* A highlight sweeps across: transform only, and none under reduced motion. */
43
+ .sv-skeleton:not(.sv-skeleton--text)::after,
44
+ .sv-skeleton__line::after {
45
+ content: '';
46
+ position: absolute;
47
+ inset: 0;
48
+ background: linear-gradient(
49
+ 90deg,
50
+ transparent,
51
+ color-mix(in oklch, var(--sv-color-surface) 61.8%, transparent),
52
+ transparent
53
+ );
54
+ transform: translateX(-100%);
55
+ animation: sv-skeleton-sweep 1618ms var(--sv-ease) infinite;
56
+ }
57
+
58
+ @media (prefers-reduced-motion: reduce) {
59
+ .sv-skeleton::after,
60
+ .sv-skeleton__line::after {
61
+ display: none;
62
+ }
63
+ }
64
+
65
+ @keyframes sv-skeleton-sweep {
66
+ to {
67
+ transform: translateX(100%);
68
+ }
69
+ }
70
+ }
@@ -0,0 +1,25 @@
1
+ import type { HTMLAttributes } from 'svelte/elements';
2
+ import type { ElementProps } from '../../core/props/element.js';
3
+ import type { Size } from '../../core/props/types.js';
4
+ /**
5
+ * A placeholder in the shape of content that is still loading. Hidden from assistive
6
+ * technology: mark the region that is loading with `aria-busy="true"` instead.
7
+ */
8
+ export type SkeletonProps = ElementProps<HTMLSpanElement, HTMLAttributes<HTMLSpanElement>, {
9
+ /**
10
+ * Lines of text, a golden rectangle that fills the width (an image, a chart), or a circle
11
+ * (an avatar).
12
+ * @default 'text'
13
+ */
14
+ type?: 'text' | 'rect' | 'circle';
15
+ /**
16
+ * Lines of text; the last of several is φ⁻¹ as wide.
17
+ * @default 1
18
+ */
19
+ lines?: number;
20
+ /**
21
+ * The diameter of a circle: the control height of the size.
22
+ * @default 'md'
23
+ */
24
+ size?: Size;
25
+ }>;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,153 @@
1
+ <script lang="ts">
2
+ // A number picked along a track, with its label, its value and validation. See SliderProps.
3
+ import { untrack } from 'svelte';
4
+ import { DEV, warnUnnamed } from '#dev';
5
+ import { useDefaults } from '../../core/defaults/context.js';
6
+ import { createField } from '../../core/form/field.svelte.js';
7
+ import { useLocale } from '../../core/locale/locale.js';
8
+ import { sharedClasses } from '../../core/props/classes.js';
9
+ import './slider.css';
10
+ import type { SliderDefaults, SliderProps } from './types.js';
11
+
12
+ let {
13
+ color,
14
+ size,
15
+ density,
16
+ disabled,
17
+ value = $bindable(),
18
+ min = 0,
19
+ max = 100,
20
+ step = 1,
21
+ ticks,
22
+ format,
23
+ label,
24
+ hint,
25
+ error,
26
+ rules,
27
+ validateOn,
28
+ id: idProp,
29
+ 'aria-describedby': describedBy,
30
+ class: className,
31
+ style,
32
+ ref = $bindable(null),
33
+ ...rest
34
+ }: SliderProps = $props();
35
+
36
+ const uid = $props.id();
37
+ const id = $derived(idProp ?? uid);
38
+ const resolve = useDefaults<SliderDefaults>('Slider', {
39
+ color: 'primary',
40
+ size: 'md',
41
+ density: 'default',
42
+ disabled: false
43
+ });
44
+ const p = $derived(resolve({ color, size, density, disabled }));
45
+ const locale = useLocale();
46
+
47
+ const current = $derived(value ?? min);
48
+ // A form reset goes back to the value the slider started at.
49
+ const initial = untrack(() => value ?? min);
50
+ // Where a value sits along the track, from 0 to 1.
51
+ const along = (at: number) =>
52
+ max > min ? Math.min(1, Math.max(0, (at - min) / (max - min))) : 0;
53
+
54
+ // Steps in decimals add up with float errors (0.1 + 0.2), so tick values are rounded to the
55
+ // decimals of min and step, the same values the input stops at.
56
+ const decimals = (at: number) => `${at}`.split('.')[1]?.length ?? 0;
57
+ const marks = $derived.by((): Array<{ value: number; label?: string }> => {
58
+ if (!ticks) return [];
59
+ if (ticks !== true) {
60
+ return ticks.map((tick) => (typeof tick === 'number' ? { value: tick } : tick));
61
+ }
62
+ if (!(step > 0) || max <= min) return [];
63
+ const places = Math.max(decimals(min), decimals(step));
64
+ const count = Math.floor((max - min) / step + 1e-9);
65
+ return Array.from({ length: count + 1 }, (_, index) => ({
66
+ value: Number((min + index * step).toFixed(places))
67
+ }));
68
+ });
69
+
70
+ const tickLabel = $derived(marks.find((mark) => mark.value === current && mark.label)?.label);
71
+ const text = $derived(format?.(current) ?? tickLabel ?? locale.formatNumber(current));
72
+
73
+ const field = createField<number>({
74
+ value: () => current,
75
+ // A range always holds a value; the browser keeps it between min and max, on a step.
76
+ empty: () => false,
77
+ check: () => undefined,
78
+ rules: () => rules,
79
+ error: () => error,
80
+ validateOn: () => validateOn,
81
+ control: () => ref
82
+ });
83
+
84
+ const message = $derived(typeof field.error === 'string' ? field.error : undefined);
85
+
86
+ if (DEV) $effect(() => warnUnnamed('Slider', ref));
87
+
88
+ // Letting go of the thumb, or a key step, finishes an edit, so it also counts as leaving.
89
+ function committed() {
90
+ field.changed();
91
+ field.left();
92
+ }
93
+ </script>
94
+
95
+ <div
96
+ class={[
97
+ 'sv-slider',
98
+ sharedClasses(p, 'Slider'),
99
+ field.error !== false && 'sv-slider--invalid',
100
+ p.disabled && 'sv-slider--disabled',
101
+ className
102
+ ]}
103
+ {style}
104
+ style:--sv-slider-fraction={along(current)}
105
+ oninput={field.changed}
106
+ onchange={committed}
107
+ >
108
+ {#if label}
109
+ <div class="sv-slider__header">
110
+ <label class="sv-slider__label" for={id}>{label}</label>
111
+ <!-- Shown for sight; screen readers hear the slider's own value. -->
112
+ <span class="sv-slider__value" aria-hidden="true">{text}</span>
113
+ </div>
114
+ {/if}
115
+ <input
116
+ bind:this={ref}
117
+ defaultValue={initial}
118
+ {...rest}
119
+ {id}
120
+ type="range"
121
+ class="sv-slider__input"
122
+ {min}
123
+ {max}
124
+ {step}
125
+ disabled={p.disabled}
126
+ aria-describedby={[describedBy, message ? `${id}-error` : hint ? `${id}-hint` : undefined]
127
+ .filter(Boolean)
128
+ .join(' ') || undefined}
129
+ aria-invalid={field.error !== false || undefined}
130
+ aria-valuetext={format || tickLabel ? text : undefined}
131
+ bind:value={() => current, (next: number) => (value = next)}
132
+ />
133
+ {#if marks.length}
134
+ <div class="sv-slider__ticks" aria-hidden="true">
135
+ {#each marks as mark (mark.value)}
136
+ <span
137
+ class={[
138
+ 'sv-slider__tick',
139
+ mark.value <= min && 'sv-slider__tick--start',
140
+ mark.value >= max && 'sv-slider__tick--end'
141
+ ]}
142
+ style:--sv-slider-at={along(mark.value)}
143
+ >{#if mark.label}<span class="sv-slider__tick-label">{mark.label}</span>{/if}</span
144
+ >
145
+ {/each}
146
+ </div>
147
+ {/if}
148
+ {#if hint && !message}<p class="sv-slider__hint" id="{id}-hint">{hint}</p>{/if}
149
+ <!-- Announces an error that appears after the user has moved on. -->
150
+ <div aria-live="polite">
151
+ {#if message}<p class="sv-slider__error" id="{id}-error">{message}</p>{/if}
152
+ </div>
153
+ </div>
@@ -0,0 +1,4 @@
1
+ import type { SliderProps } from './types.js';
2
+ declare const Slider: import("svelte").Component<SliderProps, {}, "ref" | "value">;
3
+ type Slider = ReturnType<typeof Slider>;
4
+ export default Slider;
@@ -0,0 +1,2 @@
1
+ export { default as Slider } from './Slider.svelte';
2
+ export type { SliderDefaults, SliderProps, SliderTick } from './types.js';
@@ -0,0 +1 @@
1
+ export { default as Slider } from './Slider.svelte';