@sveltier/ui 0.0.0-stage → 0.1.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (331) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +82 -2
  3. package/dist/components/Accordion/Accordion.svelte +74 -0
  4. package/dist/components/Accordion/Accordion.svelte.d.ts +25 -0
  5. package/dist/components/Accordion/accordion.css +88 -0
  6. package/dist/components/Accordion/index.d.ts +2 -0
  7. package/dist/components/Accordion/index.js +1 -0
  8. package/dist/components/Accordion/types.d.ts +64 -0
  9. package/dist/components/Accordion/types.js +1 -0
  10. package/dist/components/Alert/Alert.svelte +88 -0
  11. package/dist/components/Alert/Alert.svelte.d.ts +4 -0
  12. package/dist/components/Alert/alert.css +78 -0
  13. package/dist/components/Alert/index.d.ts +2 -0
  14. package/dist/components/Alert/index.js +1 -0
  15. package/dist/components/Alert/types.d.ts +67 -0
  16. package/dist/components/Alert/types.js +1 -0
  17. package/dist/components/Avatar/Avatar.svelte +47 -0
  18. package/dist/components/Avatar/Avatar.svelte.d.ts +4 -0
  19. package/dist/components/Avatar/avatar.css +34 -0
  20. package/dist/components/Avatar/index.d.ts +2 -0
  21. package/dist/components/Avatar/index.js +1 -0
  22. package/dist/components/Avatar/types.d.ts +47 -0
  23. package/dist/components/Avatar/types.js +1 -0
  24. package/dist/components/Badge/Badge.svelte +53 -0
  25. package/dist/components/Badge/Badge.svelte.d.ts +4 -0
  26. package/dist/components/Badge/badge.css +57 -0
  27. package/dist/components/Badge/index.d.ts +2 -0
  28. package/dist/components/Badge/index.js +1 -0
  29. package/dist/components/Badge/types.d.ts +43 -0
  30. package/dist/components/Badge/types.js +1 -0
  31. package/dist/components/Button/Button.svelte +85 -0
  32. package/dist/components/Button/Button.svelte.d.ts +4 -0
  33. package/dist/components/Button/button.css +132 -0
  34. package/dist/components/Button/index.d.ts +2 -0
  35. package/dist/components/Button/index.js +1 -0
  36. package/dist/components/Button/types.d.ts +76 -0
  37. package/dist/components/Button/types.js +1 -0
  38. package/dist/components/ButtonGroup/ButtonGroup.svelte +61 -0
  39. package/dist/components/ButtonGroup/ButtonGroup.svelte.d.ts +4 -0
  40. package/dist/components/ButtonGroup/button-group.css +39 -0
  41. package/dist/components/ButtonGroup/index.d.ts +2 -0
  42. package/dist/components/ButtonGroup/index.js +1 -0
  43. package/dist/components/ButtonGroup/types.d.ts +48 -0
  44. package/dist/components/ButtonGroup/types.js +1 -0
  45. package/dist/components/Card/Card.svelte +53 -0
  46. package/dist/components/Card/Card.svelte.d.ts +4 -0
  47. package/dist/components/Card/card.css +62 -0
  48. package/dist/components/Card/index.d.ts +2 -0
  49. package/dist/components/Card/index.js +1 -0
  50. package/dist/components/Card/types.d.ts +56 -0
  51. package/dist/components/Card/types.js +1 -0
  52. package/dist/components/Checkbox/Checkbox.svelte +105 -0
  53. package/dist/components/Checkbox/Checkbox.svelte.d.ts +4 -0
  54. package/dist/components/Checkbox/checkbox.css +138 -0
  55. package/dist/components/Checkbox/index.d.ts +2 -0
  56. package/dist/components/Checkbox/index.js +1 -0
  57. package/dist/components/Checkbox/types.d.ts +76 -0
  58. package/dist/components/Checkbox/types.js +1 -0
  59. package/dist/components/Chip/Chip.svelte +109 -0
  60. package/dist/components/Chip/Chip.svelte.d.ts +4 -0
  61. package/dist/components/Chip/chip.css +101 -0
  62. package/dist/components/Chip/index.d.ts +2 -0
  63. package/dist/components/Chip/index.js +1 -0
  64. package/dist/components/Chip/types.d.ts +69 -0
  65. package/dist/components/Chip/types.js +1 -0
  66. package/dist/components/Choice/Choice.svelte +60 -0
  67. package/dist/components/Choice/Choice.svelte.d.ts +4 -0
  68. package/dist/components/Choice/choice.css +75 -0
  69. package/dist/components/Choice/types.d.ts +43 -0
  70. package/dist/components/Choice/types.js +1 -0
  71. package/dist/components/Dialog/Dialog.svelte +36 -0
  72. package/dist/components/Dialog/Dialog.svelte.d.ts +4 -0
  73. package/dist/components/Dialog/index.d.ts +2 -0
  74. package/dist/components/Dialog/index.js +1 -0
  75. package/dist/components/Dialog/types.d.ts +50 -0
  76. package/dist/components/Dialog/types.js +1 -0
  77. package/dist/components/Divider/Divider.svelte +19 -0
  78. package/dist/components/Divider/Divider.svelte.d.ts +4 -0
  79. package/dist/components/Divider/divider.css +23 -0
  80. package/dist/components/Divider/index.d.ts +2 -0
  81. package/dist/components/Divider/index.js +1 -0
  82. package/dist/components/Divider/types.d.ts +10 -0
  83. package/dist/components/Divider/types.js +1 -0
  84. package/dist/components/Field/Field.svelte +95 -0
  85. package/dist/components/Field/Field.svelte.d.ts +4 -0
  86. package/dist/components/Field/field.css +210 -0
  87. package/dist/components/Field/index.d.ts +3 -0
  88. package/dist/components/Field/index.js +2 -0
  89. package/dist/components/Field/types.d.ts +109 -0
  90. package/dist/components/Field/types.js +2 -0
  91. package/dist/components/Form/Form.svelte +93 -0
  92. package/dist/components/Form/Form.svelte.d.ts +8 -0
  93. package/dist/components/Form/form.css +16 -0
  94. package/dist/components/Form/index.d.ts +2 -0
  95. package/dist/components/Form/index.js +1 -0
  96. package/dist/components/Form/types.d.ts +38 -0
  97. package/dist/components/Form/types.js +1 -0
  98. package/dist/components/Icon/Icon.svelte +38 -0
  99. package/dist/components/Icon/Icon.svelte.d.ts +4 -0
  100. package/dist/components/Icon/icon.css +33 -0
  101. package/dist/components/Icon/index.d.ts +2 -0
  102. package/dist/components/Icon/index.js +1 -0
  103. package/dist/components/Icon/types.d.ts +34 -0
  104. package/dist/components/Icon/types.js +1 -0
  105. package/dist/components/List/List.svelte +39 -0
  106. package/dist/components/List/List.svelte.d.ts +4 -0
  107. package/dist/components/List/ListItem.svelte +57 -0
  108. package/dist/components/List/ListItem.svelte.d.ts +4 -0
  109. package/dist/components/List/index.d.ts +3 -0
  110. package/dist/components/List/index.js +2 -0
  111. package/dist/components/List/list.css +127 -0
  112. package/dist/components/List/types.d.ts +67 -0
  113. package/dist/components/List/types.js +1 -0
  114. package/dist/components/Menu/Menu.svelte +195 -0
  115. package/dist/components/Menu/Menu.svelte.d.ts +4 -0
  116. package/dist/components/Menu/index.d.ts +2 -0
  117. package/dist/components/Menu/index.js +1 -0
  118. package/dist/components/Menu/menu.css +103 -0
  119. package/dist/components/Menu/types.d.ts +90 -0
  120. package/dist/components/Menu/types.js +1 -0
  121. package/dist/components/Modal/Modal.svelte +146 -0
  122. package/dist/components/Modal/Modal.svelte.d.ts +4 -0
  123. package/dist/components/Modal/modal.css +150 -0
  124. package/dist/components/Modal/types.d.ts +54 -0
  125. package/dist/components/Modal/types.js +1 -0
  126. package/dist/components/NativeSelect/NativeSelect.svelte +110 -0
  127. package/dist/components/NativeSelect/NativeSelect.svelte.d.ts +25 -0
  128. package/dist/components/NativeSelect/index.d.ts +2 -0
  129. package/dist/components/NativeSelect/index.js +1 -0
  130. package/dist/components/NativeSelect/native-select.css +45 -0
  131. package/dist/components/NativeSelect/types.d.ts +58 -0
  132. package/dist/components/NativeSelect/types.js +1 -0
  133. package/dist/components/NumberField/NumberField.svelte +246 -0
  134. package/dist/components/NumberField/NumberField.svelte.d.ts +4 -0
  135. package/dist/components/NumberField/index.d.ts +2 -0
  136. package/dist/components/NumberField/index.js +1 -0
  137. package/dist/components/NumberField/number-field.css +74 -0
  138. package/dist/components/NumberField/types.d.ts +73 -0
  139. package/dist/components/NumberField/types.js +1 -0
  140. package/dist/components/Popover/Popover.svelte +115 -0
  141. package/dist/components/Popover/Popover.svelte.d.ts +4 -0
  142. package/dist/components/Popover/index.d.ts +2 -0
  143. package/dist/components/Popover/index.js +1 -0
  144. package/dist/components/Popover/popover.css +67 -0
  145. package/dist/components/Popover/types.d.ts +83 -0
  146. package/dist/components/Popover/types.js +1 -0
  147. package/dist/components/Progress/ProgressCircular.svelte +61 -0
  148. package/dist/components/Progress/ProgressCircular.svelte.d.ts +4 -0
  149. package/dist/components/Progress/ProgressLinear.svelte +44 -0
  150. package/dist/components/Progress/ProgressLinear.svelte.d.ts +4 -0
  151. package/dist/components/Progress/index.d.ts +3 -0
  152. package/dist/components/Progress/index.js +2 -0
  153. package/dist/components/Progress/progress-circular.css +61 -0
  154. package/dist/components/Progress/progress-linear.css +67 -0
  155. package/dist/components/Progress/types.d.ts +53 -0
  156. package/dist/components/Progress/types.js +1 -0
  157. package/dist/components/RadioGroup/RadioGroup.svelte +149 -0
  158. package/dist/components/RadioGroup/RadioGroup.svelte.d.ts +25 -0
  159. package/dist/components/RadioGroup/index.d.ts +2 -0
  160. package/dist/components/RadioGroup/index.js +1 -0
  161. package/dist/components/RadioGroup/radio-group.css +139 -0
  162. package/dist/components/RadioGroup/types.d.ts +93 -0
  163. package/dist/components/RadioGroup/types.js +1 -0
  164. package/dist/components/SegmentedControl/SegmentedControl.svelte +70 -0
  165. package/dist/components/SegmentedControl/SegmentedControl.svelte.d.ts +25 -0
  166. package/dist/components/SegmentedControl/index.d.ts +2 -0
  167. package/dist/components/SegmentedControl/index.js +1 -0
  168. package/dist/components/SegmentedControl/segmented-control.css +68 -0
  169. package/dist/components/SegmentedControl/types.d.ts +60 -0
  170. package/dist/components/SegmentedControl/types.js +1 -0
  171. package/dist/components/Sheet/Sheet.svelte +56 -0
  172. package/dist/components/Sheet/Sheet.svelte.d.ts +4 -0
  173. package/dist/components/Sheet/index.d.ts +2 -0
  174. package/dist/components/Sheet/index.js +2 -0
  175. package/dist/components/Sheet/sheet.css +61 -0
  176. package/dist/components/Sheet/types.d.ts +51 -0
  177. package/dist/components/Sheet/types.js +1 -0
  178. package/dist/components/Skeleton/Skeleton.svelte +33 -0
  179. package/dist/components/Skeleton/Skeleton.svelte.d.ts +4 -0
  180. package/dist/components/Skeleton/index.d.ts +2 -0
  181. package/dist/components/Skeleton/index.js +1 -0
  182. package/dist/components/Skeleton/skeleton.css +70 -0
  183. package/dist/components/Skeleton/types.d.ts +25 -0
  184. package/dist/components/Skeleton/types.js +1 -0
  185. package/dist/components/Slider/Slider.svelte +153 -0
  186. package/dist/components/Slider/Slider.svelte.d.ts +4 -0
  187. package/dist/components/Slider/index.d.ts +2 -0
  188. package/dist/components/Slider/index.js +1 -0
  189. package/dist/components/Slider/slider.css +206 -0
  190. package/dist/components/Slider/types.d.ts +102 -0
  191. package/dist/components/Slider/types.js +1 -0
  192. package/dist/components/Switch/Switch.svelte +94 -0
  193. package/dist/components/Switch/Switch.svelte.d.ts +4 -0
  194. package/dist/components/Switch/index.d.ts +2 -0
  195. package/dist/components/Switch/index.js +1 -0
  196. package/dist/components/Switch/switch.css +118 -0
  197. package/dist/components/Switch/types.d.ts +67 -0
  198. package/dist/components/Switch/types.js +1 -0
  199. package/dist/components/Tabs/Tabs.svelte +93 -0
  200. package/dist/components/Tabs/Tabs.svelte.d.ts +25 -0
  201. package/dist/components/Tabs/index.d.ts +2 -0
  202. package/dist/components/Tabs/index.js +1 -0
  203. package/dist/components/Tabs/tabs.css +73 -0
  204. package/dist/components/Tabs/types.d.ts +59 -0
  205. package/dist/components/Tabs/types.js +1 -0
  206. package/dist/components/TextField/TextField.svelte +115 -0
  207. package/dist/components/TextField/TextField.svelte.d.ts +4 -0
  208. package/dist/components/TextField/index.d.ts +2 -0
  209. package/dist/components/TextField/index.js +1 -0
  210. package/dist/components/TextField/types.d.ts +57 -0
  211. package/dist/components/TextField/types.js +1 -0
  212. package/dist/components/Textarea/Textarea.svelte +116 -0
  213. package/dist/components/Textarea/Textarea.svelte.d.ts +4 -0
  214. package/dist/components/Textarea/index.d.ts +2 -0
  215. package/dist/components/Textarea/index.js +1 -0
  216. package/dist/components/Textarea/textarea.css +35 -0
  217. package/dist/components/Textarea/types.d.ts +60 -0
  218. package/dist/components/Textarea/types.js +1 -0
  219. package/dist/components/Tooltip/Tooltip.svelte +161 -0
  220. package/dist/components/Tooltip/Tooltip.svelte.d.ts +4 -0
  221. package/dist/components/Tooltip/index.d.ts +2 -0
  222. package/dist/components/Tooltip/index.js +1 -0
  223. package/dist/components/Tooltip/tooltip.css +44 -0
  224. package/dist/components/Tooltip/types.d.ts +55 -0
  225. package/dist/components/Tooltip/types.js +1 -0
  226. package/dist/core/defaults/DefaultsProvider.svelte +30 -0
  227. package/dist/core/defaults/DefaultsProvider.svelte.d.ts +13 -0
  228. package/dist/core/defaults/context.d.ts +45 -0
  229. package/dist/core/defaults/context.js +38 -0
  230. package/dist/core/display/display.d.ts +39 -0
  231. package/dist/core/display/display.js +53 -0
  232. package/dist/core/errors/codes.d.ts +124 -0
  233. package/dist/core/errors/codes.js +108 -0
  234. package/dist/core/errors/errors.d.ts +8 -0
  235. package/dist/core/errors/errors.js +7 -0
  236. package/dist/core/form/constraints.d.ts +15 -0
  237. package/dist/core/form/constraints.js +42 -0
  238. package/dist/core/form/context.d.ts +19 -0
  239. package/dist/core/form/context.js +4 -0
  240. package/dist/core/form/field.svelte.d.ts +34 -0
  241. package/dist/core/form/field.svelte.js +66 -0
  242. package/dist/core/form/number.d.ts +24 -0
  243. package/dist/core/form/number.js +71 -0
  244. package/dist/core/form/types.d.ts +22 -0
  245. package/dist/core/form/types.js +1 -0
  246. package/dist/core/locale/locale.d.ts +56 -0
  247. package/dist/core/locale/locale.js +82 -0
  248. package/dist/core/overlay/types.d.ts +33 -0
  249. package/dist/core/overlay/types.js +1 -0
  250. package/dist/core/props/classes.d.ts +21 -0
  251. package/dist/core/props/classes.js +44 -0
  252. package/dist/core/props/element.d.ts +18 -0
  253. package/dist/core/props/element.js +1 -0
  254. package/dist/core/props/types.d.ts +47 -0
  255. package/dist/core/props/types.js +16 -0
  256. package/dist/core/provider/UIProvider.svelte +63 -0
  257. package/dist/core/provider/UIProvider.svelte.d.ts +29 -0
  258. package/dist/core/theme/ThemeProvider.svelte +178 -0
  259. package/dist/core/theme/ThemeProvider.svelte.d.ts +25 -0
  260. package/dist/core/theme/color.d.ts +23 -0
  261. package/dist/core/theme/color.js +54 -0
  262. package/dist/core/theme/context.d.ts +25 -0
  263. package/dist/core/theme/context.js +14 -0
  264. package/dist/core/theme/css.d.ts +25 -0
  265. package/dist/core/theme/css.js +73 -0
  266. package/dist/core/theme/define.d.ts +11 -0
  267. package/dist/core/theme/define.js +21 -0
  268. package/dist/core/theme/resolve.d.ts +6 -0
  269. package/dist/core/theme/resolve.js +18 -0
  270. package/dist/core/theme/theme-provider.css +13 -0
  271. package/dist/core/theme/types.d.ts +35 -0
  272. package/dist/core/theme/types.js +61 -0
  273. package/dist/core/toast/ToastOutlet.svelte +192 -0
  274. package/dist/core/toast/ToastOutlet.svelte.d.ts +11 -0
  275. package/dist/core/toast/ToastProvider.svelte +39 -0
  276. package/dist/core/toast/ToastProvider.svelte.d.ts +19 -0
  277. package/dist/core/toast/toast.css +134 -0
  278. package/dist/core/toast/toast.svelte.d.ts +117 -0
  279. package/dist/core/toast/toast.svelte.js +133 -0
  280. package/dist/dev/off.d.ts +5 -0
  281. package/dist/dev/off.js +4 -0
  282. package/dist/dev/on.d.ts +20 -0
  283. package/dist/dev/on.js +49 -0
  284. package/dist/index.d.ts +67 -0
  285. package/dist/index.js +83 -0
  286. package/dist/primitives/anchored/anchored.d.ts +39 -0
  287. package/dist/primitives/anchored/anchored.js +104 -0
  288. package/dist/primitives/anchored/fallback.d.ts +31 -0
  289. package/dist/primitives/anchored/fallback.js +73 -0
  290. package/dist/primitives/focus/focus-trap.d.ts +25 -0
  291. package/dist/primitives/focus/focus-trap.js +86 -0
  292. package/dist/primitives/focus/roving-focus.d.ts +22 -0
  293. package/dist/primitives/focus/roving-focus.js +86 -0
  294. package/dist/primitives/focus/tabbable.d.ts +9 -0
  295. package/dist/primitives/focus/tabbable.js +75 -0
  296. package/dist/primitives/inert/inert-others.d.ts +12 -0
  297. package/dist/primitives/inert/inert-others.js +44 -0
  298. package/dist/primitives/keyboard/keymap.d.ts +17 -0
  299. package/dist/primitives/keyboard/keymap.js +39 -0
  300. package/dist/primitives/keyboard/typeahead.d.ts +18 -0
  301. package/dist/primitives/keyboard/typeahead.js +50 -0
  302. package/dist/primitives/layer/dismissable.d.ts +32 -0
  303. package/dist/primitives/layer/dismissable.js +91 -0
  304. package/dist/primitives/motion/easing.d.ts +9 -0
  305. package/dist/primitives/motion/easing.js +46 -0
  306. package/dist/primitives/motion/motion.d.ts +59 -0
  307. package/dist/primitives/motion/motion.js +80 -0
  308. package/dist/primitives/portal/Portal.svelte +37 -0
  309. package/dist/primitives/portal/Portal.svelte.d.ts +9 -0
  310. package/dist/primitives/portal/PortalContent.svelte +15 -0
  311. package/dist/primitives/portal/PortalContent.svelte.d.ts +9 -0
  312. package/dist/primitives/portal/portal.css +8 -0
  313. package/dist/primitives/scroll-lock/scroll-lock.d.ts +10 -0
  314. package/dist/primitives/scroll-lock/scroll-lock.js +33 -0
  315. package/dist/primitives/virtual/virtual-list.svelte.d.ts +65 -0
  316. package/dist/primitives/virtual/virtual-list.svelte.js +291 -0
  317. package/dist/styles/base.css +44 -0
  318. package/dist/styles/props.css +140 -0
  319. package/dist/styles/tokens.css +84 -0
  320. package/dist/styles/visually-hidden.css +16 -0
  321. package/dist/themes/aurora.d.ts +13 -0
  322. package/dist/themes/aurora.js +103 -0
  323. package/dist/themes/heritage.d.ts +13 -0
  324. package/dist/themes/heritage.js +102 -0
  325. package/dist/themes/maison.d.ts +13 -0
  326. package/dist/themes/maison.js +99 -0
  327. package/dist/themes/milano.d.ts +13 -0
  328. package/dist/themes/milano.js +101 -0
  329. package/dist/themes/monolith.d.ts +13 -0
  330. package/dist/themes/monolith.js +101 -0
  331. package/package.json +87 -5
@@ -0,0 +1,56 @@
1
+ /** Built-in English messages: the labels and announcements of components. */
2
+ export declare const MESSAGES: {
3
+ close: string;
4
+ loading: string;
5
+ notifications: string;
6
+ progress: string;
7
+ required: string;
8
+ tooShort: string;
9
+ tooLong: string;
10
+ typeEmail: string;
11
+ typeUrl: string;
12
+ patternMismatch: string;
13
+ badInput: string;
14
+ rangeUnderflow: string;
15
+ rangeOverflow: string;
16
+ stepMismatch: string;
17
+ increase: string;
18
+ decrease: string;
19
+ };
20
+ export type MessageKey = keyof typeof MESSAGES;
21
+ export type Messages = Record<MessageKey, string>;
22
+ export interface LocaleOptions {
23
+ /** BCP 47 locale used for formatting, for example "en-GB". Defaults to "en-US". */
24
+ locale?: string;
25
+ /** ISO 4217 currency of formatCurrency(), for example "EUR". Defaults to "USD". */
26
+ currency?: string;
27
+ /** IANA time zone of formatDate(), for example "Europe/London". Defaults to the runtime's. */
28
+ timeZone?: string;
29
+ /** A translation, or single messages merged over the English ones. */
30
+ messages?: Partial<Messages>;
31
+ }
32
+ /** Messages and formatting, as seen by `useLocale()`. Settings are reactive. */
33
+ export interface LocaleInstance {
34
+ readonly locale: string;
35
+ readonly currency: string;
36
+ readonly timeZone: string | undefined;
37
+ /** The message `key`, with `{name}` placeholders replaced from `values`. */
38
+ t(key: MessageKey, values?: Record<string, string | number>): string;
39
+ formatNumber(value: number | bigint, options?: Intl.NumberFormatOptions): string;
40
+ /** Money in `currency` (default: the locale setting). Fraction digits follow the currency. */
41
+ formatCurrency(value: number | bigint, currency?: string, options?: Intl.NumberFormatOptions): string;
42
+ /** A ratio as a percentage: 0.0184 is "2%", or "1.84%" with minimumFractionDigits: 2. */
43
+ formatPercent(value: number, options?: Intl.NumberFormatOptions): string;
44
+ formatDate(value: Date | number, options?: Intl.DateTimeFormatOptions): string;
45
+ /** Time from `now` in the largest unit that fits: "5 minutes ago", "tomorrow". */
46
+ formatRelative(value: Date | number, now?: Date | number): string;
47
+ }
48
+ /** Builds a locale whose settings are read through `options` on every call. */
49
+ export declare function createLocale(options: () => LocaleOptions): LocaleInstance;
50
+ /** Gives a subtree its locale, built from the root's options. */
51
+ export declare const setLocaleContext: (locale: LocaleInstance) => LocaleInstance;
52
+ /**
53
+ * Returns messages and formatters for the current locale. Call it during component
54
+ * initialisation. Without a provider it returns one shared instance with the defaults.
55
+ */
56
+ export declare function useLocale(): LocaleInstance;
@@ -0,0 +1,82 @@
1
+ import { getContext, hasContext, setContext } from 'svelte';
2
+ /** Built-in English messages: the labels and announcements of components. */
3
+ export const MESSAGES = {
4
+ close: 'Close',
5
+ loading: 'Loading',
6
+ // The region of toasts, followed by its key: "Notifications (F8)".
7
+ notifications: 'Notifications',
8
+ progress: 'Progress',
9
+ // Validation: the HTML constraints of form fields.
10
+ required: 'Required',
11
+ tooShort: 'Enter at least {min} characters',
12
+ tooLong: 'Enter no more than {max} characters',
13
+ typeEmail: 'Enter a valid email address',
14
+ typeUrl: 'Enter a valid web address',
15
+ patternMismatch: 'Enter a value in the requested format',
16
+ badInput: 'Enter a number',
17
+ rangeUnderflow: 'Enter {min} or more',
18
+ rangeOverflow: 'Enter {max} or less',
19
+ stepMismatch: 'Enter a value in steps of {step}',
20
+ // The buttons of a number field.
21
+ increase: 'Increase',
22
+ decrease: 'Decrease'
23
+ };
24
+ // Building an Intl formatter is the expensive part, so each one is built once per locale and
25
+ // options. Keys hold no user data, so the cache is safe to share across server requests.
26
+ const cache = new Map();
27
+ function cached(Format, locale, options) {
28
+ const key = `${Format.name}|${locale}|${JSON.stringify(options)}`;
29
+ let formatter = cache.get(key);
30
+ if (!formatter)
31
+ cache.set(key, (formatter = new Format(locale, options)));
32
+ return formatter;
33
+ }
34
+ // Largest unit first, with its length in seconds.
35
+ const UNITS = [
36
+ ['year', 31_536_000],
37
+ ['month', 2_592_000],
38
+ ['week', 604_800],
39
+ ['day', 86_400],
40
+ ['hour', 3_600],
41
+ ['minute', 60],
42
+ ['second', 1]
43
+ ];
44
+ /** Builds a locale whose settings are read through `options` on every call. */
45
+ export function createLocale(options) {
46
+ const locale = () => options().locale ?? 'en-US';
47
+ const currency = () => options().currency ?? 'USD';
48
+ const timeZone = () => options().timeZone;
49
+ const number = (format) => cached(Intl.NumberFormat, locale(), format);
50
+ return {
51
+ get locale() {
52
+ return locale();
53
+ },
54
+ get currency() {
55
+ return currency();
56
+ },
57
+ get timeZone() {
58
+ return timeZone();
59
+ },
60
+ t: (key, values) => (options().messages?.[key] ?? MESSAGES[key]).replace(/\{(\w+)\}/g, (match, name) => String(values?.[name] ?? match)),
61
+ formatNumber: (value, format = {}) => number(format).format(value),
62
+ formatCurrency: (value, code = currency(), format = {}) => number({ ...format, style: 'currency', currency: code }).format(value),
63
+ formatPercent: (value, format = {}) => number({ ...format, style: 'percent' }).format(value),
64
+ formatDate: (value, format = {}) => cached(Intl.DateTimeFormat, locale(), { timeZone: timeZone(), ...format }).format(value),
65
+ formatRelative: (value, now = Date.now()) => {
66
+ const seconds = (+value - +now) / 1000;
67
+ const [unit, length] = UNITS.find(([, size]) => Math.abs(seconds) >= size) ?? ['second', 1];
68
+ return cached(Intl.RelativeTimeFormat, locale(), { numeric: 'auto' }).format(Math.round(seconds / length), unit);
69
+ }
70
+ };
71
+ }
72
+ const KEY = Symbol('sveltier.locale');
73
+ let shared;
74
+ /** Gives a subtree its locale, built from the root's options. */
75
+ export const setLocaleContext = (locale) => setContext(KEY, locale);
76
+ /**
77
+ * Returns messages and formatters for the current locale. Call it during component
78
+ * initialisation. Without a provider it returns one shared instance with the defaults.
79
+ */
80
+ export function useLocale() {
81
+ return hasContext(KEY) ? getContext(KEY) : (shared ??= createLocale(() => ({})));
82
+ }
@@ -0,0 +1,33 @@
1
+ import type { Attachment } from 'svelte/attachments';
2
+ export declare const CLOSE_REASONS: readonly ["escape", "outside", "focus", "action"];
3
+ /**
4
+ * Why an overlay closed itself: `'escape'` (the Escape key), `'outside'` (a press outside it,
5
+ * on the backdrop of a modal), `'focus'` (focus moved out of a menu or a popover) or `'action'`
6
+ * (its close button, `close()` from its snippets, or a choice made in it).
7
+ */
8
+ export type CloseReason = (typeof CLOSE_REASONS)[number];
9
+ /**
10
+ * What an overlay passes to its `trigger` snippet: the ARIA that ties the control to the
11
+ * overlay, the handlers that open it, and an attachment that tells the overlay which element
12
+ * opened it (focus goes back there on close). Spread it onto the control.
13
+ *
14
+ * @example
15
+ * <Dialog title="Rename the account">
16
+ * {#snippet trigger(attributes)}<Button {...attributes}>Rename</Button>{/snippet}
17
+ * …
18
+ * </Dialog>
19
+ */
20
+ export interface TriggerAttributes {
21
+ /** The kind of overlay the control opens. */
22
+ 'aria-haspopup'?: 'dialog' | 'menu' | 'true';
23
+ /** Whether the overlay is open, for overlays that stay beside the control. */
24
+ 'aria-expanded'?: boolean;
25
+ /** The overlay's id while it is open. */
26
+ 'aria-controls'?: string;
27
+ /** The overlay's id, for a tooltip that describes the control. */
28
+ 'aria-describedby'?: string;
29
+ onclick?: (event: MouseEvent) => void;
30
+ onkeydown?: (event: KeyboardEvent) => void;
31
+ /** The attachment that hands the control to the overlay. */
32
+ [attachment: symbol]: Attachment<HTMLElement>;
33
+ }
@@ -0,0 +1 @@
1
+ export const CLOSE_REASONS = ['escape', 'outside', 'focus', 'action'];
@@ -0,0 +1,21 @@
1
+ import { type SharedProps, type Variant } from './types.js';
2
+ /** The shared props that map to classes. */
3
+ export type SharedClassProps = Pick<SharedProps, 'variant' | 'density' | 'size' | 'color' | 'rounded'>;
4
+ /**
5
+ * Classes for a component's shared props, for example
6
+ * `sv-variant-flat sv-density-default sv-size-md sv-color-primary sv-rounded`.
7
+ *
8
+ * The classes set custom properties (`--sv-color`, `--sv-variant-bg`, `--sv-size-height`,
9
+ * `--sv-density`, `--sv-rounded`, …) that the component reads. Custom properties inherit,
10
+ * so pass a value for every shared prop the component has, defaults included (the values
11
+ * `useDefaults()` resolves); an omitted one would follow the parent component.
12
+ *
13
+ * In development, a value outside its list warns with the valid ones, naming `component`.
14
+ * A component that takes only some variants passes them as `variants`.
15
+ *
16
+ * @example
17
+ * // In a component: resolve the defaults, then name the component for the warnings.
18
+ * const p = $derived(resolve({ variant, size, color }));
19
+ * const classes = $derived(['my-pill', sharedClasses(p, 'MyPill')]);
20
+ */
21
+ export declare function sharedClasses({ variant, density, size, color, rounded }: SharedClassProps, component?: string, variants?: readonly Variant[]): string;
@@ -0,0 +1,44 @@
1
+ import { checkValue, DEV } from '#dev';
2
+ import '../../styles/props.css';
3
+ import { INTENT_COLORS } from '../theme/types.js';
4
+ import { DENSITIES, ROUNDED, SIZES, VARIANTS } from './types.js';
5
+ /**
6
+ * Classes for a component's shared props, for example
7
+ * `sv-variant-flat sv-density-default sv-size-md sv-color-primary sv-rounded`.
8
+ *
9
+ * The classes set custom properties (`--sv-color`, `--sv-variant-bg`, `--sv-size-height`,
10
+ * `--sv-density`, `--sv-rounded`, …) that the component reads. Custom properties inherit,
11
+ * so pass a value for every shared prop the component has, defaults included (the values
12
+ * `useDefaults()` resolves); an omitted one would follow the parent component.
13
+ *
14
+ * In development, a value outside its list warns with the valid ones, naming `component`.
15
+ * A component that takes only some variants passes them as `variants`.
16
+ *
17
+ * @example
18
+ * // In a component: resolve the defaults, then name the component for the warnings.
19
+ * const p = $derived(resolve({ variant, size, color }));
20
+ * const classes = $derived(['my-pill', sharedClasses(p, 'MyPill')]);
21
+ */
22
+ export function sharedClasses({ variant, density, size, color, rounded }, component = 'component', variants = VARIANTS) {
23
+ if (DEV) {
24
+ // An intent given as the variant usually meant the colour.
25
+ const intent = INTENT_COLORS.includes(variant);
26
+ checkValue(component, 'variant', variant, variants, intent ? `To colour it, use color="${variant}".` : undefined);
27
+ checkValue(component, 'size', size, SIZES);
28
+ checkValue(component, 'density', density, DENSITIES);
29
+ checkValue(component, 'rounded', rounded, ROUNDED);
30
+ }
31
+ let classes = '';
32
+ if (variant)
33
+ classes += ` sv-variant-${variant}`;
34
+ if (density)
35
+ classes += ` sv-density-${density}`;
36
+ if (size)
37
+ classes += ` sv-size-${size}`;
38
+ if (color)
39
+ classes += ` sv-color-${color}`;
40
+ if (rounded !== undefined) {
41
+ classes += rounded === true ? ' sv-rounded' : ` sv-rounded-${rounded || 'none'}`;
42
+ }
43
+ return classes.slice(1);
44
+ }
@@ -0,0 +1,18 @@
1
+ import type { ClassValue } from 'svelte/elements';
2
+ /**
3
+ * The props of a component rendered as one root element: its own props `Own`, then every
4
+ * attribute of `Attributes` that `Own` does not redefine (spread onto the root), `class`
5
+ * (merged after the component's own classes) and a bindable `ref` to the root element.
6
+ *
7
+ * Own props win over same-named attributes, so a shared `size` or `color` never clashes
8
+ * with the HTML attribute of the same name.
9
+ *
10
+ * @example
11
+ * type PillProps = ElementProps<HTMLSpanElement, HTMLAttributes<HTMLSpanElement>, { size?: Size }>;
12
+ */
13
+ export type ElementProps<Element, Attributes, Own = object> = Own & Omit<Attributes, keyof Own | 'class'> & {
14
+ /** Classes added after the component's own: a string, an array or an object. */
15
+ class?: ClassValue | null;
16
+ /** The root element, bindable with `bind:ref`. */
17
+ ref?: Element | null;
18
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,47 @@
1
+ import type { IntentColor } from '../theme/types.js';
2
+ /** How tightly a component packs its content. `default` is the baseline. */
3
+ export declare const DENSITIES: readonly ["compact", "default", "comfortable"];
4
+ export type Density = (typeof DENSITIES)[number];
5
+ /** Overall scale of a component. `md` is the baseline. */
6
+ export declare const SIZES: readonly ["xs", "sm", "md", "lg", "xl"];
7
+ export type Size = (typeof SIZES)[number];
8
+ /**
9
+ * Visual weight: a raised surface, filled, tinted, outlined, text only, or no decoration at
10
+ * all.
11
+ */
12
+ export declare const VARIANTS: readonly ["elevated", "flat", "tonal", "outlined", "text", "plain"];
13
+ export type Variant = (typeof VARIANTS)[number];
14
+ /**
15
+ * Corner rounding. `true` keeps the theme's radius, `false` / `'none'` removes it,
16
+ * `sm`–`xl` pick a theme radius, `'full'` makes a pill whatever the theme.
17
+ */
18
+ export declare const ROUNDED: readonly [true, false, "none", "sm", "md", "lg", "xl", "full"];
19
+ export type Rounded = (typeof ROUNDED)[number];
20
+ /**
21
+ * Custom colours added with `defineTheme()`. Register them here by declaration merging to
22
+ * use them as a component's `color`:
23
+ *
24
+ * @example
25
+ * declare module '@sveltier/ui' {
26
+ * interface CustomColors {
27
+ * brand: true;
28
+ * }
29
+ * }
30
+ */
31
+ export interface CustomColors {
32
+ }
33
+ /**
34
+ * A component's colour: an intent, `neutral` (the text colour, with the background as its
35
+ * on-colour), or a custom colour registered in `CustomColors`.
36
+ */
37
+ export type Color = IntentColor | 'neutral' | Extract<keyof CustomColors, string> extends infer C ? C : never;
38
+ /** Props shared by every component that supports them. */
39
+ export interface SharedProps {
40
+ variant?: Variant;
41
+ density?: Density;
42
+ size?: Size;
43
+ color?: Color;
44
+ rounded?: Rounded;
45
+ disabled?: boolean;
46
+ loading?: boolean;
47
+ }
@@ -0,0 +1,16 @@
1
+ // The shared prop vocabulary. Every component that has one of these props uses exactly
2
+ // these names and these values.
3
+ /** How tightly a component packs its content. `default` is the baseline. */
4
+ export const DENSITIES = ['compact', 'default', 'comfortable'];
5
+ /** Overall scale of a component. `md` is the baseline. */
6
+ export const SIZES = ['xs', 'sm', 'md', 'lg', 'xl'];
7
+ /**
8
+ * Visual weight: a raised surface, filled, tinted, outlined, text only, or no decoration at
9
+ * all.
10
+ */
11
+ export const VARIANTS = ['elevated', 'flat', 'tonal', 'outlined', 'text', 'plain'];
12
+ /**
13
+ * Corner rounding. `true` keeps the theme's radius, `false` / `'none'` removes it,
14
+ * `sm`–`xl` pick a theme radius, `'full'` makes a pill whatever the theme.
15
+ */
16
+ export const ROUNDED = [true, false, 'none', 'sm', 'md', 'lg', 'xl', 'full'];
@@ -0,0 +1,63 @@
1
+ <script lang="ts" module>
2
+ import type { Snippet } from 'svelte';
3
+ import type { DefaultsConfig } from '../defaults/context.js';
4
+ import type { DisplayOptions } from '../display/display.js';
5
+ import type { LocaleOptions } from '../locale/locale.js';
6
+ import type { ThemeChoice, ThemeDefinition } from '../theme/types.js';
7
+
8
+ export interface UIProviderProps {
9
+ /** The registered themes, for example `monolith` or `{ ...monolith, ...maison }`. */
10
+ themes: Record<string, ThemeDefinition>;
11
+ /** "system" or a theme name. Bindable. */
12
+ theme?: ThemeChoice;
13
+ /** Theme used by "system" when the OS prefers light. Defaults to the first light theme. */
14
+ light?: string;
15
+ /** Theme used by "system" when the OS prefers dark. Defaults to the first dark theme. */
16
+ dark?: string;
17
+ /** Where the user's theme choice is remembered; `false` turns persistence off. */
18
+ storageKey?: string | false;
19
+ /** CSP nonce for the generated `<style>` and `<script>`. */
20
+ nonce?: string;
21
+ /** Default props for every component below. */
22
+ defaults?: DefaultsConfig;
23
+ /** Breakpoint thresholds, mobile breakpoint and server width. Read once. */
24
+ display?: DisplayOptions;
25
+ /** Locale, currency, time zone and messages. Changes apply at once. */
26
+ locale?: LocaleOptions;
27
+ children?: Snippet;
28
+ }
29
+ </script>
30
+
31
+ <script lang="ts">
32
+ // The root of an app: theme, defaults, display, locale and toasts in one component.
33
+ import { untrack } from 'svelte';
34
+ import DefaultsProvider from '../defaults/DefaultsProvider.svelte';
35
+ import { createDisplay, setDisplayContext } from '../display/display.js';
36
+ import { createLocale, setLocaleContext } from '../locale/locale.js';
37
+ import ThemeProvider from '../theme/ThemeProvider.svelte';
38
+ import ToastProvider from '../toast/ToastProvider.svelte';
39
+
40
+ let {
41
+ themes,
42
+ theme = $bindable(),
43
+ light,
44
+ dark,
45
+ storageKey,
46
+ nonce,
47
+ defaults,
48
+ display,
49
+ locale,
50
+ children
51
+ }: UIProviderProps = $props();
52
+
53
+ setDisplayContext(untrack(() => createDisplay(display)));
54
+ setLocaleContext(createLocale(() => locale ?? {}));
55
+ </script>
56
+
57
+ <ThemeProvider {themes} bind:theme {light} {dark} {storageKey} {nonce}>
58
+ <DefaultsProvider defaults={defaults ?? {}}>
59
+ <ToastProvider>
60
+ {@render children?.()}
61
+ </ToastProvider>
62
+ </DefaultsProvider>
63
+ </ThemeProvider>
@@ -0,0 +1,29 @@
1
+ import type { Snippet } from 'svelte';
2
+ import type { DefaultsConfig } from '../defaults/context.js';
3
+ import type { DisplayOptions } from '../display/display.js';
4
+ import type { LocaleOptions } from '../locale/locale.js';
5
+ import type { ThemeChoice, ThemeDefinition } from '../theme/types.js';
6
+ export interface UIProviderProps {
7
+ /** The registered themes, for example `monolith` or `{ ...monolith, ...maison }`. */
8
+ themes: Record<string, ThemeDefinition>;
9
+ /** "system" or a theme name. Bindable. */
10
+ theme?: ThemeChoice;
11
+ /** Theme used by "system" when the OS prefers light. Defaults to the first light theme. */
12
+ light?: string;
13
+ /** Theme used by "system" when the OS prefers dark. Defaults to the first dark theme. */
14
+ dark?: string;
15
+ /** Where the user's theme choice is remembered; `false` turns persistence off. */
16
+ storageKey?: string | false;
17
+ /** CSP nonce for the generated `<style>` and `<script>`. */
18
+ nonce?: string;
19
+ /** Default props for every component below. */
20
+ defaults?: DefaultsConfig;
21
+ /** Breakpoint thresholds, mobile breakpoint and server width. Read once. */
22
+ display?: DisplayOptions;
23
+ /** Locale, currency, time zone and messages. Changes apply at once. */
24
+ locale?: LocaleOptions;
25
+ children?: Snippet;
26
+ }
27
+ declare const UIProvider: import("svelte").Component<UIProviderProps, {}, "theme">;
28
+ type UIProvider = ReturnType<typeof UIProvider>;
29
+ export default UIProvider;
@@ -0,0 +1,178 @@
1
+ <script lang="ts" module>
2
+ import type { Snippet } from 'svelte';
3
+ import type { HTMLAttributes } from 'svelte/elements';
4
+ import type { ThemeChoice, ThemeDefinition } from './types.js';
5
+
6
+ export interface ThemeProviderProps extends HTMLAttributes<HTMLDivElement> {
7
+ /** "system" or a theme name. Nested providers inherit their parent's choice by default. */
8
+ theme?: ThemeChoice;
9
+ /** Root only, and required there. The registered themes, for example `monolith` or `{ ...monolith, ...maison }`. */
10
+ themes?: Record<string, ThemeDefinition>;
11
+ /** Root only. Theme used by "system" when the OS prefers light. Defaults to the first light theme. */
12
+ light?: string;
13
+ /** Root only. Theme used by "system" when the OS prefers dark. Defaults to the first dark theme. */
14
+ dark?: string;
15
+ /** Root only. Where the user's choice is remembered; `false` turns persistence off. */
16
+ storageKey?: string | false;
17
+ /** Root only. CSP nonce for the generated `<style>` and `<script>`. */
18
+ nonce?: string;
19
+ /** Nested only. Paint the scope's background. */
20
+ withBackground?: boolean;
21
+ /** Nested only. The wrapper element. */
22
+ ref?: HTMLDivElement | null;
23
+ children?: Snippet;
24
+ }
25
+ </script>
26
+
27
+ <script lang="ts">
28
+ import { onMount, untrack } from 'svelte';
29
+ import { MediaQuery } from 'svelte/reactivity';
30
+ import '../../styles/tokens.css';
31
+ import '../../styles/base.css';
32
+ import './theme-provider.css';
33
+ import { sveltierError } from '../errors/errors.js';
34
+ import { hasThemeContext, setThemeContext, useTheme, type ThemeInstance } from './context.js';
35
+ import { THEME_ATTRIBUTE, themeCss, themeHead, themeScript } from './css.js';
36
+
37
+ const parent = hasThemeContext() ? useTheme() : undefined;
38
+
39
+ let {
40
+ theme = $bindable(),
41
+ themes,
42
+ light,
43
+ dark,
44
+ storageKey = 'sv-theme',
45
+ nonce,
46
+ withBackground = false,
47
+ ref = $bindable(null),
48
+ class: className,
49
+ children,
50
+ ...rest
51
+ }: ThemeProviderProps = $props();
52
+
53
+ const registry = $derived.by(() => {
54
+ const registered = parent?.themes ?? themes;
55
+ if (!registered) {
56
+ throw sveltierError(
57
+ 'SV1001',
58
+ "The root <ThemeProvider> has no themes. Pass one, for example themes={monolith} from '@sveltier/ui/themes/monolith'."
59
+ );
60
+ }
61
+ return registered;
62
+ });
63
+ const lightName = $derived(parent?.light ?? light ?? first(registry, false));
64
+ const darkName = $derived(parent?.dark ?? dark ?? first(registry, true));
65
+ const choice = $derived<ThemeChoice>(theme ?? parent?.choice ?? 'system');
66
+
67
+ const prefersDark = new MediaQuery('(prefers-color-scheme: dark)', false);
68
+ const name = $derived(
69
+ choice === 'system' ? (prefersDark.current ? darkName : lightName) : choice
70
+ );
71
+ const current = $derived(registry[name] ?? (registry[lightName] as ThemeDefinition));
72
+ const persist = $derived(!parent && storageKey !== false ? storageKey : undefined);
73
+ /** The first registered theme with the given darkness, or the first theme at all. */
74
+ function first(themes: Record<string, ThemeDefinition>, isDark: boolean): string {
75
+ const names = Object.keys(themes);
76
+ return names.find((n) => themes[n]?.dark === isDark) ?? (names[0] as string);
77
+ }
78
+
79
+ const isChoice = (value: unknown): value is ThemeChoice =>
80
+ value === 'system' || (typeof value === 'string' && Object.hasOwn(registry, value));
81
+
82
+ // The server cannot read a stored choice and the first client render must match the server
83
+ // HTML. The inline head script has already painted the stored theme, so <html> is only
84
+ // touched after mount, once the stored choice is known.
85
+ let mounted = $state(false);
86
+ const fallback = untrack(() => theme ?? 'system');
87
+
88
+ onMount(() => {
89
+ if (persist) {
90
+ try {
91
+ const stored = localStorage.getItem(persist);
92
+ if (isChoice(stored)) theme = stored;
93
+ } catch {
94
+ // Storage blocked (privacy mode, sandboxed iframe): keep the default.
95
+ }
96
+ }
97
+ mounted = true;
98
+ if (!parent) return () => document.documentElement.removeAttribute(THEME_ATTRIBUTE);
99
+ });
100
+
101
+ $effect(() => {
102
+ if (mounted && !parent) document.documentElement.setAttribute(THEME_ATTRIBUTE, choice);
103
+ });
104
+
105
+ const head = $derived(
106
+ parent
107
+ ? ''
108
+ : themeHead(
109
+ themeCss({ themes: registry, light: lightName, dark: darkName, fallback }),
110
+ persist ? themeScript(persist, ['system', ...Object.keys(registry)]) : '',
111
+ nonce
112
+ )
113
+ );
114
+
115
+ const instance: ThemeInstance = {
116
+ get choice() {
117
+ return choice;
118
+ },
119
+ get name() {
120
+ return name;
121
+ },
122
+ get current() {
123
+ return current;
124
+ },
125
+ get isDark() {
126
+ return current.dark;
127
+ },
128
+ get themes() {
129
+ return registry;
130
+ },
131
+ get light() {
132
+ return lightName;
133
+ },
134
+ get dark() {
135
+ return darkName;
136
+ },
137
+ set(next) {
138
+ if (!isChoice(next)) {
139
+ const names = Object.keys(registry).join(', ');
140
+ throw sveltierError(
141
+ 'SV1002',
142
+ `Unknown theme "${next}". Registered: ${names}, or "system".`
143
+ );
144
+ }
145
+ theme = next;
146
+ try {
147
+ if (persist) localStorage.setItem(persist, next);
148
+ } catch {
149
+ // Not remembered, but the choice still applies to this page view.
150
+ }
151
+ },
152
+ toggle() {
153
+ instance.set(current.dark ? lightName : darkName);
154
+ }
155
+ };
156
+
157
+ setThemeContext(instance);
158
+ </script>
159
+
160
+ <svelte:head>
161
+ {#if head}
162
+ <!-- eslint-disable-next-line svelte/no-at-html-tags -- generated from validated theme values -->
163
+ {@html head}
164
+ {/if}
165
+ </svelte:head>
166
+
167
+ {#if parent}
168
+ <div
169
+ bind:this={ref}
170
+ {...rest}
171
+ class={['sv-theme-provider', withBackground && 'sv-theme-provider--background', className]}
172
+ data-sv-theme={choice}
173
+ >
174
+ {@render children?.()}
175
+ </div>
176
+ {:else}
177
+ {@render children?.()}
178
+ {/if}
@@ -0,0 +1,25 @@
1
+ import type { Snippet } from 'svelte';
2
+ import type { HTMLAttributes } from 'svelte/elements';
3
+ import type { ThemeChoice, ThemeDefinition } from './types.js';
4
+ export interface ThemeProviderProps extends HTMLAttributes<HTMLDivElement> {
5
+ /** "system" or a theme name. Nested providers inherit their parent's choice by default. */
6
+ theme?: ThemeChoice;
7
+ /** Root only, and required there. The registered themes, for example `monolith` or `{ ...monolith, ...maison }`. */
8
+ themes?: Record<string, ThemeDefinition>;
9
+ /** Root only. Theme used by "system" when the OS prefers light. Defaults to the first light theme. */
10
+ light?: string;
11
+ /** Root only. Theme used by "system" when the OS prefers dark. Defaults to the first dark theme. */
12
+ dark?: string;
13
+ /** Root only. Where the user's choice is remembered; `false` turns persistence off. */
14
+ storageKey?: string | false;
15
+ /** Root only. CSP nonce for the generated `<style>` and `<script>`. */
16
+ nonce?: string;
17
+ /** Nested only. Paint the scope's background. */
18
+ withBackground?: boolean;
19
+ /** Nested only. The wrapper element. */
20
+ ref?: HTMLDivElement | null;
21
+ children?: Snippet;
22
+ }
23
+ declare const ThemeProvider: import("svelte").Component<ThemeProviderProps, {}, "theme" | "ref">;
24
+ type ThemeProvider = ReturnType<typeof ThemeProvider>;
25
+ export default ThemeProvider;
@@ -0,0 +1,23 @@
1
+ export interface Oklch {
2
+ /** Lightness, 0–1. */
3
+ l: number;
4
+ /** Chroma, 0–0.4 in practice. */
5
+ c: number;
6
+ /** Hue in degrees. */
7
+ h: number;
8
+ /** Alpha, 0–1. */
9
+ alpha: number;
10
+ }
11
+ /** Parses `oklch(L C H)` or `oklch(L C H / A)` with numbers or percentages. */
12
+ export declare function parseOklch(value: string): Oklch | undefined;
13
+ /** Linear-light sRGB channels, clamped to the sRGB gamut. */
14
+ export declare function toLinearSrgb({ l, c, h }: Oklch): [number, number, number];
15
+ /** WCAG relative luminance of an opaque colour. */
16
+ export declare function luminance(color: Oklch): number;
17
+ /** WCAG 2 contrast ratio between two opaque oklch colours (1–21). */
18
+ export declare function contrast(a: Oklch, b: Oklch): number;
19
+ /**
20
+ * Picks a readable text colour for a filled background: a deep ink or a near-white, both
21
+ * tinted with the background's hue, whichever contrasts more.
22
+ */
23
+ export declare function onColor(background: string): string | undefined;