@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
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Sveltier contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,83 @@
1
- # Temporary Holding Version
1
+ # Sveltier
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ The UI framework for AI coding agents, on Svelte 5.
4
+
5
+ Coding agents do not remember your library, cannot see the screen, and learn by running and
6
+ fixing. Sveltier is designed around all three, and the same choices help every developer.
7
+
8
+ - **Finds the right information.** Props tables, `llms.txt` and `llms-full.txt` are generated
9
+ from the TypeScript types, and the typed sources ship in this package. An agent reads the API
10
+ of the version it installed, not a guess from its training data.
11
+ - **Gets it right the first time.** `variant`, `size`, `density`, `color` and `rounded` mean the
12
+ same thing on every component, as literal types: a value that does not exist is a type error
13
+ that lists the ones that do.
14
+ - **Fixes itself when wrong.** Every error has a stable code, says what happened and what to do,
15
+ and links to its entry in the docs. Development builds also warn about mistakes that types
16
+ cannot catch.
17
+ - **Accessible without being asked.** Roles, focus and keys follow the WAI-ARIA Authoring
18
+ Practices, tested in Chromium, Firefox and WebKit.
19
+
20
+ > **Alpha.** The API may still change between releases.
21
+
22
+ ## Install
23
+
24
+ ```sh
25
+ npm install @sveltier/ui
26
+ ```
27
+
28
+ Svelte 5.40 or later is required.
29
+
30
+ ## Set up
31
+
32
+ Wrap the app in `UIProvider` with a theme pack, then use the components anywhere inside it.
33
+
34
+ ```svelte
35
+ <!-- src/routes/+layout.svelte -->
36
+ <script>
37
+ import { UIProvider } from '@sveltier/ui';
38
+ import { monolith } from '@sveltier/ui/themes/monolith';
39
+ let { children } = $props();
40
+ </script>
41
+
42
+ <!-- Monolith, light or dark following the OS -->
43
+ <UIProvider themes={monolith}>
44
+ {@render children()}
45
+ </UIProvider>
46
+ ```
47
+
48
+ ```svelte
49
+ <script>
50
+ import { Button, TextField } from '@sveltier/ui';
51
+ let email = $state('');
52
+ </script>
53
+
54
+ <TextField label="Email" type="email" required bind:value={email} />
55
+ <Button variant="tonal">Save</Button>
56
+ ```
57
+
58
+ Fonts are not bundled: each theme names its families and falls back to system fonts. See
59
+ [Fonts](https://sveltier.com/getting-started/fonts).
60
+
61
+ ## What is inside
62
+
63
+ - **Components:** Alert, Avatar, Badge, Button, ButtonGroup, Card, Chip, Divider, Icon, List,
64
+ ProgressCircular, ProgressLinear, SegmentedControl, Skeleton, Tabs.
65
+ - **Forms:** Form, Field, TextField, Textarea, NumberField and NativeSelect, validated by the
66
+ HTML constraints first, then your rules.
67
+ - **Primitives** for your own components: focus trap, roving focus, dismissable layers, portal,
68
+ inert background and scroll lock, anchored positioning, keyboard maps and typeahead, motion,
69
+ virtual lists.
70
+ - **Theme engine:** five built-in theme packs (Monolith, Heritage, Aurora, Maison and Milano),
71
+ each in light and dark, with flash-free server rendering. Define your own with `defineTheme`.
72
+ - **Zero runtime dependencies,** and a gzip size budget on every entry.
73
+
74
+ ## Docs
75
+
76
+ - [sveltier.com](https://sveltier.com)
77
+ - For agents: [llms.txt](https://sveltier.com/llms.txt) and
78
+ [llms-full.txt](https://sveltier.com/llms-full.txt)
79
+ - [Error codes](https://sveltier.com/errors)
80
+
81
+ ## License
82
+
83
+ [MIT](./LICENSE)
@@ -0,0 +1,88 @@
1
+ <script lang="ts">
2
+ // A message with a type, a title, actions and a close button. See AlertProps for the props.
3
+ import { useDefaults } from '../../core/defaults/context.js';
4
+ import { useLocale } from '../../core/locale/locale.js';
5
+ import { sharedClasses } from '../../core/props/classes.js';
6
+ import './alert.css';
7
+ import type { AlertDefaults, AlertProps } from './types.js';
8
+
9
+ let {
10
+ variant,
11
+ color,
12
+ density,
13
+ rounded,
14
+ type,
15
+ title,
16
+ icon = true,
17
+ open = $bindable(true),
18
+ closable = false,
19
+ closeLabel,
20
+ onclose,
21
+ prepend,
22
+ actions,
23
+ children,
24
+ class: className,
25
+ ref = $bindable(null),
26
+ ...rest
27
+ }: AlertProps = $props();
28
+
29
+ const resolve = useDefaults<AlertDefaults>('Alert', {
30
+ variant: 'tonal',
31
+ color: 'info',
32
+ density: 'default',
33
+ rounded: true
34
+ });
35
+ // A colour passed in wins over the type's.
36
+ const p = $derived(resolve({ variant, color: color ?? type, density, rounded }));
37
+ const locale = useLocale();
38
+
39
+ // Circles, a triangle and their marks on a 24-unit grid, cut out with evenodd.
40
+ const RING = 'M12 3a9 9 0 1 0 0 18 9 9 0 1 0 0-18zm0 2a7 7 0 1 1 0 14 7 7 0 1 1 0-14z';
41
+ const ICONS = {
42
+ info: `${RING}M11 7h2v2h-2zm0 3h2v7h-2z`,
43
+ success: `${RING}M7.6 12.3 9 10.9l2 2 4-4 1.4 1.4-5.4 5.4z`,
44
+ warning: 'M12 2.5 1.8 20.5h20.4zm0 4.1 6.7 11.9H5.3zM11 10h2v4h-2zm0 5h2v2h-2z',
45
+ error: `${RING}M11 7h2v6h-2zm0 8h2v2h-2z`
46
+ };
47
+ const CLOSE =
48
+ 'M6.4 5 12 10.6 17.6 5 19 6.4 13.4 12l5.6 5.6-1.4 1.4-5.6-5.6L6.4 19 5 17.6l5.6-5.6L5 6.4z';
49
+
50
+ function close() {
51
+ open = false;
52
+ onclose?.();
53
+ }
54
+ </script>
55
+
56
+ {#if open}
57
+ <div
58
+ bind:this={ref}
59
+ {...rest}
60
+ role={type === 'warning' || type === 'error' ? 'alert' : 'status'}
61
+ class={['sv-alert', sharedClasses(p, 'Alert'), className]}
62
+ >
63
+ {#if prepend}
64
+ <span class="sv-alert__icon">{@render prepend()}</span>
65
+ {:else if icon && type}
66
+ <span class="sv-alert__icon">
67
+ <svg viewBox="0 0 24 24" fill="currentColor" fill-rule="evenodd" aria-hidden="true">
68
+ <path d={ICONS[type]} />
69
+ </svg>
70
+ </span>
71
+ {/if}
72
+ <div class="sv-alert__content">
73
+ {#if title}<div class="sv-alert__title">{title}</div>{/if}
74
+ {#if children}<div>{@render children()}</div>{/if}
75
+ {#if actions}<div class="sv-alert__actions">{@render actions()}</div>{/if}
76
+ </div>
77
+ {#if closable}
78
+ <button
79
+ type="button"
80
+ class="sv-alert__close"
81
+ aria-label={closeLabel ?? locale.t('close')}
82
+ onclick={close}
83
+ >
84
+ <svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d={CLOSE} /></svg>
85
+ </button>
86
+ {/if}
87
+ </div>
88
+ {/if}
@@ -0,0 +1,4 @@
1
+ import type { AlertProps } from './types.js';
2
+ declare const Alert: import("svelte").Component<AlertProps, {}, "ref" | "open">;
3
+ type Alert = ReturnType<typeof Alert>;
4
+ export default Alert;
@@ -0,0 +1,78 @@
1
+ @layer sv.tokens, sv.base, sv.components, sv.utilities;
2
+
3
+ @layer sv.components {
4
+ /* Icon, message, close, each only when present; padding on the Fibonacci scale. */
5
+ .sv-alert {
6
+ display: flex;
7
+ gap: var(--sv-space-13);
8
+ align-items: flex-start;
9
+ box-sizing: border-box;
10
+ padding: calc(var(--sv-space-13) * var(--sv-density))
11
+ calc(var(--sv-space-21) * var(--sv-density));
12
+ border: var(--sv-hairline) solid var(--sv-variant-border);
13
+ /* The control radius, never rounder than a card, even where controls are pills. */
14
+ border-radius: var(--sv-rounded, min(var(--sv-radius-md), var(--sv-radius-lg)));
15
+ background-color: var(--sv-variant-bg);
16
+ box-shadow: var(--sv-variant-shadow);
17
+ color: var(--sv-variant-fg);
18
+ font-size: var(--sv-text-sm);
19
+ line-height: var(--sv-leading-snug);
20
+ }
21
+
22
+ /* Icons are φ^½ of the text, centred on the first line. */
23
+ .sv-alert__icon {
24
+ display: inline-flex;
25
+ flex: none;
26
+ block-size: calc(1em * var(--sv-leading-snug));
27
+ align-items: center;
28
+ }
29
+
30
+ :where(.sv-alert__icon) svg {
31
+ inline-size: 1.272em;
32
+ block-size: 1.272em;
33
+ }
34
+
35
+ .sv-alert__content {
36
+ display: grid;
37
+ flex: 1;
38
+ gap: var(--sv-space-5);
39
+ min-inline-size: 0;
40
+ }
41
+
42
+ .sv-alert__title {
43
+ font-weight: var(--sv-weight-semibold);
44
+ }
45
+
46
+ .sv-alert__actions {
47
+ display: flex;
48
+ flex-wrap: wrap;
49
+ gap: var(--sv-space-8);
50
+ margin-block-start: var(--sv-space-5);
51
+ }
52
+
53
+ .sv-alert__close {
54
+ display: inline-grid;
55
+ flex: none;
56
+ place-items: center;
57
+ inline-size: 1.618em;
58
+ block-size: 1.618em;
59
+ margin-block: -0.191em;
60
+ padding: 0;
61
+ border: 0;
62
+ border-radius: 50%;
63
+ background: transparent;
64
+ color: inherit;
65
+ cursor: pointer;
66
+ }
67
+
68
+ @media (hover: hover) {
69
+ .sv-alert__close:hover {
70
+ background-color: color-mix(in oklch, currentColor var(--sv-state-hover), transparent);
71
+ }
72
+ }
73
+
74
+ .sv-alert__close svg {
75
+ inline-size: 1em;
76
+ block-size: 1em;
77
+ }
78
+ }
@@ -0,0 +1,2 @@
1
+ export { default as Alert } from './Alert.svelte';
2
+ export type { AlertDefaults, AlertProps } from './types.js';
@@ -0,0 +1 @@
1
+ export { default as Alert } from './Alert.svelte';
@@ -0,0 +1,67 @@
1
+ import type { Snippet } from 'svelte';
2
+ import type { HTMLAttributes } from 'svelte/elements';
3
+ import type { ElementProps } from '../../core/props/element.js';
4
+ import type { Color, Density, Rounded, Variant } from '../../core/props/types.js';
5
+ /** The Alert props that `DefaultsProvider` and `UIProvider` can set for a subtree. */
6
+ export interface AlertDefaults {
7
+ /**
8
+ * Visual weight.
9
+ * @default 'tonal'
10
+ */
11
+ variant: Variant;
12
+ /**
13
+ * The colour, when there is no `type` to take it from.
14
+ * @default 'info'
15
+ */
16
+ color: Color;
17
+ /**
18
+ * Multiplies the padding.
19
+ * @default 'default'
20
+ */
21
+ density: Density;
22
+ /**
23
+ * Corner rounding. `true` keeps the theme's radius.
24
+ * @default true
25
+ */
26
+ rounded: Rounded;
27
+ }
28
+ declare module '../../core/defaults/context.js' {
29
+ interface ComponentDefaults {
30
+ Alert: AlertDefaults;
31
+ }
32
+ }
33
+ /** A message about something that happened or needs attention. */
34
+ export type AlertProps = ElementProps<HTMLDivElement, HTMLAttributes<HTMLDivElement>, Partial<AlertDefaults> & {
35
+ /**
36
+ * What kind of message: sets the colour and the icon. Warnings and errors are announced at
37
+ * once (`role="alert"`), the others politely (`role="status"`).
38
+ */
39
+ type?: 'info' | 'success' | 'warning' | 'error';
40
+ /** A short summary, above the text. */
41
+ title?: string;
42
+ /**
43
+ * Shows the icon of the `type`.
44
+ * @default true
45
+ */
46
+ icon?: boolean;
47
+ /**
48
+ * Shown while true; a closable alert sets it to false. Bindable.
49
+ * @default true
50
+ */
51
+ open?: boolean;
52
+ /**
53
+ * Adds a button that closes the alert and calls `onclose`.
54
+ * @default false
55
+ */
56
+ closable?: boolean;
57
+ /** The name of the close button. Defaults to the locale's `close`. */
58
+ closeLabel?: string;
59
+ /** Called when the close button closes the alert. */
60
+ onclose?: () => void;
61
+ /** Content in place of the type's icon. */
62
+ prepend?: Snippet;
63
+ /** Buttons or links after the text, such as `Retry`. */
64
+ actions?: Snippet;
65
+ /** The message. */
66
+ children?: Snippet;
67
+ }>;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,47 @@
1
+ <script lang="ts">
2
+ // An image with a fallback of initials or an icon. See AvatarProps for the props.
3
+ import { useDefaults } from '../../core/defaults/context.js';
4
+ import { sharedClasses } from '../../core/props/classes.js';
5
+ import './avatar.css';
6
+ import type { AvatarDefaults, AvatarProps } from './types.js';
7
+
8
+ let {
9
+ size,
10
+ variant,
11
+ color,
12
+ rounded,
13
+ src,
14
+ alt,
15
+ children,
16
+ class: className,
17
+ ref = $bindable(null),
18
+ ...rest
19
+ }: AvatarProps = $props();
20
+
21
+ const resolve = useDefaults<AvatarDefaults>('Avatar', {
22
+ size: 'md',
23
+ variant: 'tonal',
24
+ color: 'neutral',
25
+ rounded: 'full'
26
+ });
27
+ const p = $derived(resolve({ size, variant, color, rounded }));
28
+
29
+ // The image that failed, so a new src gets its own chance.
30
+ let failed = $state<string>();
31
+ const image = $derived(src && src !== failed ? src : undefined);
32
+ </script>
33
+
34
+ <span
35
+ bind:this={ref}
36
+ {...rest}
37
+ role={alt ? 'img' : undefined}
38
+ aria-label={alt || undefined}
39
+ aria-hidden={alt ? undefined : 'true'}
40
+ class={['sv-avatar', sharedClasses(p, 'Avatar'), className]}
41
+ >
42
+ {#if image}
43
+ <img class="sv-avatar__image" src={image} alt="" onerror={() => (failed = image)} />
44
+ {:else}
45
+ {@render children?.()}
46
+ {/if}
47
+ </span>
@@ -0,0 +1,4 @@
1
+ import type { AvatarProps } from './types.js';
2
+ declare const Avatar: import("svelte").Component<AvatarProps, {}, "ref">;
3
+ type Avatar = ReturnType<typeof Avatar>;
4
+ export default Avatar;
@@ -0,0 +1,34 @@
1
+ @layer sv.tokens, sv.base, sv.components, sv.utilities;
2
+
3
+ @layer sv.components {
4
+ /* As tall as a control of its size; initials are φ⁻² of that. */
5
+ .sv-avatar {
6
+ position: relative;
7
+ display: inline-flex;
8
+ flex: none;
9
+ align-items: center;
10
+ justify-content: center;
11
+ box-sizing: border-box;
12
+ inline-size: var(--sv-size-height);
13
+ block-size: var(--sv-size-height);
14
+ overflow: hidden;
15
+ border: var(--sv-hairline) solid var(--sv-variant-border);
16
+ border-radius: var(--sv-rounded, var(--sv-radius-full));
17
+ background-color: var(--sv-variant-bg);
18
+ box-shadow: var(--sv-variant-shadow);
19
+ color: var(--sv-variant-fg);
20
+ font: var(--sv-weight-medium) calc(var(--sv-size-height) * 0.382) / 1 var(--sv-font-ui);
21
+ letter-spacing: 0.02em;
22
+ text-transform: uppercase;
23
+ vertical-align: middle;
24
+ user-select: none;
25
+ }
26
+
27
+ .sv-avatar__image {
28
+ position: absolute;
29
+ inset: 0;
30
+ inline-size: 100%;
31
+ block-size: 100%;
32
+ object-fit: cover;
33
+ }
34
+ }
@@ -0,0 +1,2 @@
1
+ export { default as Avatar } from './Avatar.svelte';
2
+ export type { AvatarDefaults, AvatarProps } from './types.js';
@@ -0,0 +1 @@
1
+ export { default as Avatar } from './Avatar.svelte';
@@ -0,0 +1,47 @@
1
+ import type { Snippet } from 'svelte';
2
+ import type { HTMLAttributes } from 'svelte/elements';
3
+ import type { ElementProps } from '../../core/props/element.js';
4
+ import type { Color, Rounded, Size, Variant } from '../../core/props/types.js';
5
+ /** The Avatar props that `DefaultsProvider` and `UIProvider` can set for a subtree. */
6
+ export interface AvatarDefaults {
7
+ /**
8
+ * Width and height: the control height of the size.
9
+ * @default 'md'
10
+ */
11
+ size: Size;
12
+ /**
13
+ * How the fallback is painted.
14
+ * @default 'tonal'
15
+ */
16
+ variant: Variant;
17
+ /**
18
+ * The colour of the fallback.
19
+ * @default 'neutral'
20
+ */
21
+ color: Color;
22
+ /**
23
+ * Corner rounding.
24
+ * @default 'full'
25
+ */
26
+ rounded: Rounded;
27
+ }
28
+ declare module '../../core/defaults/context.js' {
29
+ interface ComponentDefaults {
30
+ Avatar: AvatarDefaults;
31
+ }
32
+ }
33
+ /**
34
+ * A picture of a person or an account: an image, or initials or an icon when there is none
35
+ * or it fails to load.
36
+ */
37
+ export type AvatarProps = ElementProps<HTMLSpanElement, HTMLAttributes<HTMLSpanElement>, Partial<AvatarDefaults> & {
38
+ /** The image. */
39
+ src?: string;
40
+ /**
41
+ * Who or what the avatar shows, for screen readers. Leave it out when a name is shown next
42
+ * to the avatar: it is then decorative and hidden from them.
43
+ */
44
+ alt?: string;
45
+ /** Initials or an icon, shown while there is no image or it failed to load. */
46
+ children?: Snippet;
47
+ }>;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,53 @@
1
+ <script lang="ts">
2
+ // A count or a dot on its content, or alone in a line. See BadgeProps for the props.
3
+ import { useDefaults } from '../../core/defaults/context.js';
4
+ import { sharedClasses } from '../../core/props/classes.js';
5
+ import '../../styles/visually-hidden.css';
6
+ import './badge.css';
7
+ import type { BadgeDefaults, BadgeProps } from './types.js';
8
+
9
+ let {
10
+ color,
11
+ max,
12
+ content,
13
+ dot = false,
14
+ label,
15
+ children,
16
+ id,
17
+ class: className,
18
+ ref = $bindable(null),
19
+ ...rest
20
+ }: BadgeProps = $props();
21
+
22
+ const resolve = useDefaults<BadgeDefaults>('Badge', { color: 'primary', max: 99 });
23
+ const p = $derived(resolve({ color, max }));
24
+
25
+ const visible = $derived(dot || (content != null && content !== 0 && content !== ''));
26
+ const shown = $derived(
27
+ typeof content === 'number' && content > p.max ? `${p.max}+` : String(content ?? '')
28
+ );
29
+ // Screen readers hear the real count, with what it counts.
30
+ const spoken = $derived(dot ? label : [content, label].filter((part) => part != null).join(' '));
31
+ </script>
32
+
33
+ <span
34
+ bind:this={ref}
35
+ {...rest}
36
+ {id}
37
+ class={['sv-badge', !children && 'sv-badge--inline', className]}
38
+ >
39
+ {@render children?.()}
40
+ {#if visible}
41
+ <span class="sv-badge__anchor" aria-hidden="true">
42
+ <span
43
+ class={[
44
+ 'sv-badge__badge',
45
+ sharedClasses({ variant: 'flat', color: p.color }, 'Badge'),
46
+ dot && 'sv-badge__badge--dot'
47
+ ]}>{dot ? '' : shown}</span
48
+ >
49
+ </span>
50
+ <!-- With an id, the content can point at this text: aria-describedby="{id}-label". -->
51
+ {#if spoken}<span class="sv-visually-hidden" id={id && `${id}-label`}>{spoken}</span>{/if}
52
+ {/if}
53
+ </span>
@@ -0,0 +1,4 @@
1
+ import type { BadgeProps } from './types.js';
2
+ declare const Badge: import("svelte").Component<BadgeProps, {}, "ref">;
3
+ type Badge = ReturnType<typeof Badge>;
4
+ export default Badge;
@@ -0,0 +1,57 @@
1
+ @layer sv.tokens, sv.base, sv.components, sv.utilities;
2
+
3
+ @layer sv.components {
4
+ .sv-badge {
5
+ position: relative;
6
+ display: inline-flex;
7
+ flex: none;
8
+ vertical-align: middle;
9
+ }
10
+
11
+ /*
12
+ * A point at the top end corner of the content. The badge is centred on it by flex
13
+ * alignment, overflowing evenly, so it follows the writing direction with no direction
14
+ * selector (minifiers rewrite :dir() into language guesses for older browsers).
15
+ */
16
+ .sv-badge__anchor {
17
+ position: absolute;
18
+ inset-block-start: 0;
19
+ inset-inline-end: 0;
20
+ display: flex;
21
+ align-items: center;
22
+ justify-content: center;
23
+ inline-size: 0;
24
+ block-size: 0;
25
+ pointer-events: none;
26
+ }
27
+
28
+ .sv-badge--inline .sv-badge__anchor {
29
+ position: static;
30
+ display: contents;
31
+ }
32
+
33
+ /* A pill φ times its text. */
34
+ .sv-badge__badge {
35
+ display: inline-flex;
36
+ flex: none;
37
+ align-items: center;
38
+ justify-content: center;
39
+ box-sizing: border-box;
40
+ min-inline-size: 1.618em;
41
+ block-size: 1.618em;
42
+ padding-inline: 0.382em;
43
+ border-radius: var(--sv-radius-full);
44
+ background-color: var(--sv-variant-bg);
45
+ color: var(--sv-variant-fg);
46
+ font: var(--sv-weight-medium) var(--sv-text-label) / 1 var(--sv-font-ui);
47
+ font-variant-numeric: tabular-nums;
48
+ white-space: nowrap;
49
+ }
50
+
51
+ .sv-badge__badge--dot {
52
+ min-inline-size: 0.618em;
53
+ inline-size: 0.618em;
54
+ block-size: 0.618em;
55
+ padding: 0;
56
+ }
57
+ }
@@ -0,0 +1,2 @@
1
+ export { default as Badge } from './Badge.svelte';
2
+ export type { BadgeDefaults, BadgeProps } from './types.js';
@@ -0,0 +1 @@
1
+ export { default as Badge } from './Badge.svelte';
@@ -0,0 +1,43 @@
1
+ import type { Snippet } from 'svelte';
2
+ import type { HTMLAttributes } from 'svelte/elements';
3
+ import type { ElementProps } from '../../core/props/element.js';
4
+ import type { Color } from '../../core/props/types.js';
5
+ /** The Badge props that `DefaultsProvider` and `UIProvider` can set for a subtree. */
6
+ export interface BadgeDefaults {
7
+ /**
8
+ * The badge's fill.
9
+ * @default 'primary'
10
+ */
11
+ color: Color;
12
+ /**
13
+ * Counts above it show as `max+`.
14
+ * @default 99
15
+ */
16
+ max: number;
17
+ }
18
+ declare module '../../core/defaults/context.js' {
19
+ interface ComponentDefaults {
20
+ Badge: BadgeDefaults;
21
+ }
22
+ }
23
+ /**
24
+ * A count or a dot pinned to the top end corner of its content, or standing alone in a line
25
+ * when it has none. A count of 0 hides it.
26
+ */
27
+ export type BadgeProps = ElementProps<HTMLSpanElement, HTMLAttributes<HTMLSpanElement>, Partial<BadgeDefaults> & {
28
+ /** What the badge says: usually a count. */
29
+ content?: number | string;
30
+ /**
31
+ * A dot instead of the content.
32
+ * @default false
33
+ */
34
+ dot?: boolean;
35
+ /**
36
+ * What the content counts, read after it by screen readers: `unread messages` reads
37
+ * "3 unread messages". With `dot`, the whole announcement. With an `id`, this text has
38
+ * the id `{id}-label`, for the `aria-describedby` of a button the badge is pinned to.
39
+ */
40
+ label?: string;
41
+ /** The content the badge is pinned to. */
42
+ children?: Snippet;
43
+ }>;
@@ -0,0 +1 @@
1
+ export {};