@nqmcreative/ui 0.1.1 → 0.2.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 (308) hide show
  1. package/README.md +89 -34
  2. package/cli/index.mjs +83 -33
  3. package/dist/core/calendar.d.ts +3 -0
  4. package/dist/core/calendar.js +36 -0
  5. package/dist/core/dialog.svelte.d.ts +14 -0
  6. package/dist/core/dialog.svelte.js +23 -0
  7. package/dist/core/files.d.ts +35 -0
  8. package/dist/core/files.js +62 -0
  9. package/dist/core/index.d.ts +37 -0
  10. package/dist/core/index.js +35 -0
  11. package/dist/core/list.svelte.d.ts +41 -0
  12. package/dist/core/list.svelte.js +77 -0
  13. package/dist/core/number.d.ts +7 -0
  14. package/dist/core/number.js +17 -0
  15. package/dist/core/pagination.d.ts +6 -0
  16. package/dist/core/pagination.js +21 -0
  17. package/dist/core/password.d.ts +8 -0
  18. package/dist/core/password.js +23 -0
  19. package/dist/core/table.d.ts +22 -0
  20. package/dist/core/table.js +41 -0
  21. package/dist/core/theme.svelte.d.ts +16 -0
  22. package/dist/core/theme.svelte.js +34 -0
  23. package/dist/core/trigger.d.ts +35 -0
  24. package/dist/core/trigger.js +77 -0
  25. package/dist/index.d.ts +11 -103
  26. package/dist/index.js +11 -75
  27. package/dist/{components → styles/matte}/AccordionItem.svelte +1 -1
  28. package/dist/{components → styles/matte}/AccordionItem.svelte.d.ts +1 -1
  29. package/dist/{components → styles/matte}/Alert.svelte +8 -2
  30. package/dist/{components → styles/matte}/Alert.svelte.d.ts +1 -1
  31. package/dist/{components → styles/matte}/Avatar.svelte +1 -1
  32. package/dist/{components → styles/matte}/Avatar.svelte.d.ts +1 -1
  33. package/dist/{components → styles/matte}/Badge.svelte +8 -3
  34. package/dist/{components → styles/matte}/Badge.svelte.d.ts +1 -3
  35. package/dist/{components → styles/matte}/Breadcrumb.svelte +2 -2
  36. package/dist/{components → styles/matte}/Breadcrumb.svelte.d.ts +1 -1
  37. package/dist/{components → styles/matte}/Button.svelte +1 -1
  38. package/dist/{components → styles/matte}/Button.svelte.d.ts +1 -1
  39. package/dist/styles/matte/CTASection.svelte +76 -0
  40. package/dist/styles/matte/CTASection.svelte.d.ts +18 -0
  41. package/dist/{components → styles/matte}/Calendar.svelte +7 -17
  42. package/dist/{components → styles/matte}/Calendar.svelte.d.ts +1 -1
  43. package/dist/{components → styles/matte}/Card.svelte +1 -1
  44. package/dist/{components → styles/matte}/Card.svelte.d.ts +1 -1
  45. package/dist/{components → styles/matte}/Checkbox.svelte +1 -1
  46. package/dist/{components → styles/matte}/Checkbox.svelte.d.ts +1 -1
  47. package/dist/{components → styles/matte}/CheckboxGroup.svelte +1 -1
  48. package/dist/{components → styles/matte}/CheckboxGroup.svelte.d.ts +1 -1
  49. package/dist/{components → styles/matte}/Combobox.svelte +31 -42
  50. package/dist/{components → styles/matte}/Combobox.svelte.d.ts +1 -1
  51. package/dist/{components → styles/matte}/CommandPalette.svelte +26 -41
  52. package/dist/{components → styles/matte}/CommandPalette.svelte.d.ts +1 -1
  53. package/dist/{components → styles/matte}/ConfirmDialog.svelte +2 -2
  54. package/dist/{components → styles/matte}/ConfirmDialog.svelte.d.ts +2 -2
  55. package/dist/{components → styles/matte}/ContextMenu.svelte +5 -7
  56. package/dist/{components → styles/matte}/DatePicker.svelte +7 -11
  57. package/dist/{components → styles/matte}/DatePicker.svelte.d.ts +1 -1
  58. package/dist/{components → styles/matte}/Drawer.svelte +4 -7
  59. package/dist/{components → styles/matte}/Dropdown.svelte +18 -36
  60. package/dist/{components → styles/matte}/Dropdown.svelte.d.ts +1 -1
  61. package/dist/{components → styles/matte}/Dropzone.svelte +11 -43
  62. package/dist/{components → styles/matte}/Dropzone.svelte.d.ts +2 -5
  63. package/dist/{components → styles/matte}/EmptyState.svelte +1 -1
  64. package/dist/{components → styles/matte}/EmptyState.svelte.d.ts +1 -1
  65. package/dist/styles/matte/FeatureCard.svelte +58 -0
  66. package/dist/styles/matte/FeatureCard.svelte.d.ts +16 -0
  67. package/dist/styles/matte/FeatureGrid.svelte +62 -0
  68. package/dist/styles/matte/FeatureGrid.svelte.d.ts +16 -0
  69. package/dist/{components → styles/matte}/Footer.svelte +1 -1
  70. package/dist/{components → styles/matte}/Footer.svelte.d.ts +1 -1
  71. package/dist/styles/matte/HeroSection.svelte +80 -0
  72. package/dist/styles/matte/HeroSection.svelte.d.ts +21 -0
  73. package/dist/{components → styles/matte}/Input.svelte +1 -1
  74. package/dist/{components → styles/matte}/Input.svelte.d.ts +1 -1
  75. package/dist/{components → styles/matte}/Link.svelte +1 -1
  76. package/dist/{components → styles/matte}/Link.svelte.d.ts +1 -1
  77. package/dist/{components → styles/matte}/LocaleProvider.svelte +1 -1
  78. package/dist/{components → styles/matte}/LocaleProvider.svelte.d.ts +1 -1
  79. package/dist/styles/matte/LogoCloud.svelte +61 -0
  80. package/dist/styles/matte/LogoCloud.svelte.d.ts +19 -0
  81. package/dist/{components → styles/matte}/MenuItem.svelte +1 -1
  82. package/dist/{components → styles/matte}/MenuItem.svelte.d.ts +1 -1
  83. package/dist/{components → styles/matte}/Modal.svelte +4 -7
  84. package/dist/{components → styles/matte}/MultiSelect.svelte +18 -37
  85. package/dist/{components → styles/matte}/MultiSelect.svelte.d.ts +1 -1
  86. package/dist/{components → styles/matte}/Navbar.svelte +2 -2
  87. package/dist/{components → styles/matte}/Navbar.svelte.d.ts +1 -1
  88. package/dist/{components → styles/matte}/NumberInput.svelte +4 -8
  89. package/dist/{components → styles/matte}/NumberInput.svelte.d.ts +1 -1
  90. package/dist/{components → styles/matte}/Pagination.svelte +4 -15
  91. package/dist/{components → styles/matte}/Pagination.svelte.d.ts +1 -1
  92. package/dist/{components → styles/matte}/PasswordInput.svelte +4 -13
  93. package/dist/{components → styles/matte}/PasswordInput.svelte.d.ts +1 -1
  94. package/dist/{components → styles/matte}/Popover.svelte +16 -41
  95. package/dist/{components → styles/matte}/Popover.svelte.d.ts +1 -1
  96. package/dist/styles/matte/PricingCard.svelte +107 -0
  97. package/dist/styles/matte/PricingCard.svelte.d.ts +25 -0
  98. package/dist/{components → styles/matte}/Progress.svelte +3 -2
  99. package/dist/{components → styles/matte}/Progress.svelte.d.ts +1 -1
  100. package/dist/{components → styles/matte}/Radio.svelte +1 -1
  101. package/dist/{components → styles/matte}/Radio.svelte.d.ts +1 -1
  102. package/dist/{components → styles/matte}/RadioGroup.svelte +1 -1
  103. package/dist/{components → styles/matte}/RadioGroup.svelte.d.ts +1 -1
  104. package/dist/{components → styles/matte}/SegmentedControl.svelte +1 -1
  105. package/dist/{components → styles/matte}/SegmentedControl.svelte.d.ts +1 -1
  106. package/dist/{components → styles/matte}/Select.svelte +1 -1
  107. package/dist/{components → styles/matte}/Select.svelte.d.ts +1 -1
  108. package/dist/{components → styles/matte}/Sidebar.svelte +2 -2
  109. package/dist/{components → styles/matte}/Sidebar.svelte.d.ts +1 -1
  110. package/dist/{components → styles/matte}/Slider.svelte +3 -2
  111. package/dist/{components → styles/matte}/Slider.svelte.d.ts +1 -1
  112. package/dist/{components → styles/matte}/Spinner.svelte +2 -2
  113. package/dist/{components → styles/matte}/Spinner.svelte.d.ts +1 -1
  114. package/dist/{components → styles/matte}/Stat.svelte +1 -1
  115. package/dist/{components → styles/matte}/Stat.svelte.d.ts +1 -1
  116. package/dist/styles/matte/StatsBand.svelte +57 -0
  117. package/dist/styles/matte/StatsBand.svelte.d.ts +20 -0
  118. package/dist/{components → styles/matte}/Steps.svelte +1 -1
  119. package/dist/{components → styles/matte}/Steps.svelte.d.ts +1 -1
  120. package/dist/{components → styles/matte}/Switch.svelte +1 -1
  121. package/dist/{components → styles/matte}/Switch.svelte.d.ts +1 -1
  122. package/dist/{components → styles/matte}/Table.svelte +6 -28
  123. package/dist/{components → styles/matte}/Table.svelte.d.ts +2 -6
  124. package/dist/{components → styles/matte}/Tabs.svelte +8 -1
  125. package/dist/{components → styles/matte}/Tabs.svelte.d.ts +1 -1
  126. package/dist/styles/matte/Testimonial.svelte +67 -0
  127. package/dist/styles/matte/Testimonial.svelte.d.ts +19 -0
  128. package/dist/{components → styles/matte}/Textarea.svelte +1 -1
  129. package/dist/{components → styles/matte}/Textarea.svelte.d.ts +1 -1
  130. package/dist/{components → styles/matte}/ThemeToggle.svelte +14 -27
  131. package/dist/{components → styles/matte}/ThemeToggle.svelte.d.ts +2 -6
  132. package/dist/{components → styles/matte}/Toaster.svelte +4 -4
  133. package/dist/styles/matte/index.d.ts +109 -0
  134. package/dist/styles/matte/index.js +83 -0
  135. package/dist/styles/paper/Accordion.svelte +17 -0
  136. package/dist/styles/paper/Accordion.svelte.d.ts +8 -0
  137. package/dist/styles/paper/AccordionItem.svelte +46 -0
  138. package/dist/styles/paper/AccordionItem.svelte.d.ts +14 -0
  139. package/dist/styles/paper/Alert.svelte +99 -0
  140. package/dist/styles/paper/Alert.svelte.d.ts +18 -0
  141. package/dist/styles/paper/Avatar.svelte +60 -0
  142. package/dist/styles/paper/Avatar.svelte.d.ts +16 -0
  143. package/dist/styles/paper/AvatarGroup.svelte +17 -0
  144. package/dist/styles/paper/AvatarGroup.svelte.d.ts +8 -0
  145. package/dist/styles/paper/Badge.svelte +58 -0
  146. package/dist/styles/paper/Badge.svelte.d.ts +16 -0
  147. package/dist/styles/paper/Breadcrumb.svelte +49 -0
  148. package/dist/styles/paper/Breadcrumb.svelte.d.ts +14 -0
  149. package/dist/styles/paper/Button.svelte +96 -0
  150. package/dist/styles/paper/Button.svelte.d.ts +21 -0
  151. package/dist/styles/paper/CTASection.svelte +76 -0
  152. package/dist/styles/paper/CTASection.svelte.d.ts +18 -0
  153. package/dist/styles/paper/Calendar.svelte +202 -0
  154. package/dist/styles/paper/Calendar.svelte.d.ts +22 -0
  155. package/dist/styles/paper/Card.svelte +78 -0
  156. package/dist/styles/paper/Card.svelte.d.ts +21 -0
  157. package/dist/styles/paper/Checkbox.svelte +75 -0
  158. package/dist/styles/paper/Checkbox.svelte.d.ts +15 -0
  159. package/dist/styles/paper/CheckboxGroup.svelte +111 -0
  160. package/dist/styles/paper/CheckboxGroup.svelte.d.ts +30 -0
  161. package/dist/styles/paper/Combobox.svelte +266 -0
  162. package/dist/styles/paper/Combobox.svelte.d.ts +29 -0
  163. package/dist/styles/paper/CommandPalette.svelte +209 -0
  164. package/dist/styles/paper/CommandPalette.svelte.d.ts +32 -0
  165. package/dist/styles/paper/ConfirmDialog.svelte +97 -0
  166. package/dist/styles/paper/ConfirmDialog.svelte.d.ts +22 -0
  167. package/dist/styles/paper/ContextMenu.svelte +88 -0
  168. package/dist/styles/paper/ContextMenu.svelte.d.ts +15 -0
  169. package/dist/styles/paper/DatePicker.svelte +192 -0
  170. package/dist/styles/paper/DatePicker.svelte.d.ts +23 -0
  171. package/dist/styles/paper/Divider.svelte +30 -0
  172. package/dist/styles/paper/Divider.svelte.d.ts +10 -0
  173. package/dist/styles/paper/Drawer.svelte +165 -0
  174. package/dist/styles/paper/Drawer.svelte.d.ts +20 -0
  175. package/dist/styles/paper/Dropdown.svelte +94 -0
  176. package/dist/styles/paper/Dropdown.svelte.d.ts +23 -0
  177. package/dist/styles/paper/Dropzone.svelte +210 -0
  178. package/dist/styles/paper/Dropzone.svelte.d.ts +29 -0
  179. package/dist/styles/paper/EmptyState.svelte +71 -0
  180. package/dist/styles/paper/EmptyState.svelte.d.ts +18 -0
  181. package/dist/styles/paper/FeatureCard.svelte +58 -0
  182. package/dist/styles/paper/FeatureCard.svelte.d.ts +16 -0
  183. package/dist/styles/paper/FeatureGrid.svelte +62 -0
  184. package/dist/styles/paper/FeatureGrid.svelte.d.ts +16 -0
  185. package/dist/styles/paper/Field.svelte +42 -0
  186. package/dist/styles/paper/Field.svelte.d.ts +16 -0
  187. package/dist/styles/paper/Footer.svelte +91 -0
  188. package/dist/styles/paper/Footer.svelte.d.ts +25 -0
  189. package/dist/styles/paper/HeroSection.svelte +86 -0
  190. package/dist/styles/paper/HeroSection.svelte.d.ts +21 -0
  191. package/dist/styles/paper/Input.svelte +60 -0
  192. package/dist/styles/paper/Input.svelte.d.ts +18 -0
  193. package/dist/styles/paper/InputGroup.svelte +20 -0
  194. package/dist/styles/paper/InputGroup.svelte.d.ts +11 -0
  195. package/dist/styles/paper/Kbd.svelte +17 -0
  196. package/dist/styles/paper/Kbd.svelte.d.ts +8 -0
  197. package/dist/styles/paper/Label.svelte +16 -0
  198. package/dist/styles/paper/Label.svelte.d.ts +9 -0
  199. package/dist/styles/paper/Link.svelte +44 -0
  200. package/dist/styles/paper/Link.svelte.d.ts +16 -0
  201. package/dist/styles/paper/LocaleProvider.svelte +24 -0
  202. package/dist/styles/paper/LocaleProvider.svelte.d.ts +10 -0
  203. package/dist/styles/paper/LogoCloud.svelte +61 -0
  204. package/dist/styles/paper/LogoCloud.svelte.d.ts +19 -0
  205. package/dist/styles/paper/MenuItem.svelte +64 -0
  206. package/dist/styles/paper/MenuItem.svelte.d.ts +18 -0
  207. package/dist/styles/paper/MenuSeparator.svelte +22 -0
  208. package/dist/styles/paper/MenuSeparator.svelte.d.ts +8 -0
  209. package/dist/styles/paper/Modal.svelte +118 -0
  210. package/dist/styles/paper/Modal.svelte.d.ts +21 -0
  211. package/dist/styles/paper/MultiSelect.svelte +287 -0
  212. package/dist/styles/paper/MultiSelect.svelte.d.ts +31 -0
  213. package/dist/styles/paper/Navbar.svelte +201 -0
  214. package/dist/styles/paper/Navbar.svelte.d.ts +33 -0
  215. package/dist/styles/paper/NumberInput.svelte +96 -0
  216. package/dist/styles/paper/NumberInput.svelte.d.ts +15 -0
  217. package/dist/styles/paper/Pagination.svelte +83 -0
  218. package/dist/styles/paper/Pagination.svelte.d.ts +15 -0
  219. package/dist/styles/paper/PasswordInput.svelte +100 -0
  220. package/dist/styles/paper/PasswordInput.svelte.d.ts +12 -0
  221. package/dist/styles/paper/Popover.svelte +89 -0
  222. package/dist/styles/paper/Popover.svelte.d.ts +19 -0
  223. package/dist/styles/paper/PricingCard.svelte +108 -0
  224. package/dist/styles/paper/PricingCard.svelte.d.ts +25 -0
  225. package/dist/styles/paper/Progress.svelte +59 -0
  226. package/dist/styles/paper/Progress.svelte.d.ts +17 -0
  227. package/dist/styles/paper/Radio.svelte +55 -0
  228. package/dist/styles/paper/Radio.svelte.d.ts +15 -0
  229. package/dist/styles/paper/RadioGroup.svelte +95 -0
  230. package/dist/styles/paper/RadioGroup.svelte.d.ts +27 -0
  231. package/dist/styles/paper/SegmentedControl.svelte +88 -0
  232. package/dist/styles/paper/SegmentedControl.svelte.d.ts +25 -0
  233. package/dist/styles/paper/Select.svelte +61 -0
  234. package/dist/styles/paper/Select.svelte.d.ts +20 -0
  235. package/dist/styles/paper/Sidebar.svelte +206 -0
  236. package/dist/styles/paper/Sidebar.svelte.d.ts +36 -0
  237. package/dist/styles/paper/Skeleton.svelte +46 -0
  238. package/dist/styles/paper/Skeleton.svelte.d.ts +13 -0
  239. package/dist/styles/paper/Slider.svelte +80 -0
  240. package/dist/styles/paper/Slider.svelte.d.ts +19 -0
  241. package/dist/styles/paper/Spinner.svelte +34 -0
  242. package/dist/styles/paper/Spinner.svelte.d.ts +13 -0
  243. package/dist/styles/paper/Stat.svelte +51 -0
  244. package/dist/styles/paper/Stat.svelte.d.ts +16 -0
  245. package/dist/styles/paper/StatsBand.svelte +63 -0
  246. package/dist/styles/paper/StatsBand.svelte.d.ts +20 -0
  247. package/dist/styles/paper/Steps.svelte +141 -0
  248. package/dist/styles/paper/Steps.svelte.d.ts +24 -0
  249. package/dist/styles/paper/Switch.svelte +64 -0
  250. package/dist/styles/paper/Switch.svelte.d.ts +14 -0
  251. package/dist/styles/paper/Table.svelte +217 -0
  252. package/dist/styles/paper/Table.svelte.d.ts +66 -0
  253. package/dist/styles/paper/Tabs.svelte +102 -0
  254. package/dist/styles/paper/Tabs.svelte.d.ts +23 -0
  255. package/dist/styles/paper/Testimonial.svelte +64 -0
  256. package/dist/styles/paper/Testimonial.svelte.d.ts +19 -0
  257. package/dist/styles/paper/Textarea.svelte +54 -0
  258. package/dist/styles/paper/Textarea.svelte.d.ts +12 -0
  259. package/dist/styles/paper/ThemeToggle.svelte +130 -0
  260. package/dist/styles/paper/ThemeToggle.svelte.d.ts +16 -0
  261. package/dist/styles/paper/Toaster.svelte +132 -0
  262. package/dist/styles/paper/Toaster.svelte.d.ts +8 -0
  263. package/dist/styles/paper/Tooltip.svelte +33 -0
  264. package/dist/styles/paper/Tooltip.svelte.d.ts +12 -0
  265. package/dist/styles/paper/fonts.css +46 -0
  266. package/dist/styles/paper/index.d.ts +109 -0
  267. package/dist/styles/paper/index.js +83 -0
  268. package/dist/styles/paper/theme.css +222 -0
  269. package/package.json +531 -201
  270. package/registry.json +658 -339
  271. /package/dist/{actions → core/actions}/anchor.d.ts +0 -0
  272. /package/dist/{actions → core/actions}/anchor.js +0 -0
  273. /package/dist/{actions → core/actions}/dismissable.d.ts +0 -0
  274. /package/dist/{actions → core/actions}/dismissable.js +0 -0
  275. /package/dist/{date.d.ts → core/date.d.ts} +0 -0
  276. /package/dist/{date.js → core/date.js} +0 -0
  277. /package/dist/{locale.svelte.d.ts → core/locale.svelte.d.ts} +0 -0
  278. /package/dist/{locale.svelte.js → core/locale.svelte.js} +0 -0
  279. /package/dist/{toast.svelte.d.ts → core/toast.svelte.d.ts} +0 -0
  280. /package/dist/{toast.svelte.js → core/toast.svelte.js} +0 -0
  281. /package/dist/{tones.d.ts → core/tones.d.ts} +0 -0
  282. /package/dist/{tones.js → core/tones.js} +0 -0
  283. /package/dist/{components → styles/matte}/Accordion.svelte +0 -0
  284. /package/dist/{components → styles/matte}/Accordion.svelte.d.ts +0 -0
  285. /package/dist/{components → styles/matte}/AvatarGroup.svelte +0 -0
  286. /package/dist/{components → styles/matte}/AvatarGroup.svelte.d.ts +0 -0
  287. /package/dist/{components → styles/matte}/ContextMenu.svelte.d.ts +0 -0
  288. /package/dist/{components → styles/matte}/Divider.svelte +0 -0
  289. /package/dist/{components → styles/matte}/Divider.svelte.d.ts +0 -0
  290. /package/dist/{components → styles/matte}/Drawer.svelte.d.ts +0 -0
  291. /package/dist/{components → styles/matte}/Field.svelte +0 -0
  292. /package/dist/{components → styles/matte}/Field.svelte.d.ts +0 -0
  293. /package/dist/{components → styles/matte}/InputGroup.svelte +0 -0
  294. /package/dist/{components → styles/matte}/InputGroup.svelte.d.ts +0 -0
  295. /package/dist/{components → styles/matte}/Kbd.svelte +0 -0
  296. /package/dist/{components → styles/matte}/Kbd.svelte.d.ts +0 -0
  297. /package/dist/{components → styles/matte}/Label.svelte +0 -0
  298. /package/dist/{components → styles/matte}/Label.svelte.d.ts +0 -0
  299. /package/dist/{components → styles/matte}/MenuSeparator.svelte +0 -0
  300. /package/dist/{components → styles/matte}/MenuSeparator.svelte.d.ts +0 -0
  301. /package/dist/{components → styles/matte}/Modal.svelte.d.ts +0 -0
  302. /package/dist/{components → styles/matte}/Skeleton.svelte +0 -0
  303. /package/dist/{components → styles/matte}/Skeleton.svelte.d.ts +0 -0
  304. /package/dist/{components → styles/matte}/Toaster.svelte.d.ts +0 -0
  305. /package/dist/{components → styles/matte}/Tooltip.svelte +0 -0
  306. /package/dist/{components → styles/matte}/Tooltip.svelte.d.ts +0 -0
  307. /package/dist/{fonts.css → styles/matte/fonts.css} +0 -0
  308. /package/dist/{theme.css → styles/matte/theme.css} +0 -0
@@ -0,0 +1,206 @@
1
+ <script module lang="ts">
2
+ export interface SidebarItem {
3
+ /** Stable id used for the active state. Falls back to `href`. */
4
+ id?: string;
5
+ label: string;
6
+ href?: string;
7
+ disabled?: boolean;
8
+ badge?: string | number;
9
+ /** Nested links — the parent becomes a collapsible group. */
10
+ items?: SidebarItem[];
11
+ /** Open the group on first render. */
12
+ open?: boolean;
13
+ }
14
+
15
+ export interface SidebarSection {
16
+ /** Small heading above a run of items. */
17
+ label?: string;
18
+ items: SidebarItem[];
19
+ }
20
+ </script>
21
+
22
+ <script lang="ts">
23
+ import type { Snippet } from 'svelte';
24
+ import { useLocale } from '../../core/locale.svelte.js';
25
+ import { focusRing, toneRing, toneSoft, type Tone } from '../../core/tones.js';
26
+
27
+ interface Props {
28
+ sections: SidebarSection[];
29
+ /** Bindable — the `id` (or `href`) of the current item. */
30
+ value?: string;
31
+ /** Bindable — narrow rail mode. */
32
+ collapsed?: boolean;
33
+ /** Show the collapse button. */
34
+ collapsible?: boolean;
35
+ tone?: Tone;
36
+ header?: Snippet;
37
+ footer?: Snippet;
38
+ onnavigate?: (item: SidebarItem) => void;
39
+ class?: string;
40
+ }
41
+
42
+ let {
43
+ sections,
44
+ value = $bindable(''),
45
+ collapsed = $bindable(false),
46
+ collapsible = true,
47
+ tone = 'brand',
48
+ header,
49
+ footer,
50
+ onnavigate,
51
+ class: className = ''
52
+ }: Props = $props();
53
+
54
+ const t = useLocale();
55
+
56
+ const keyOf = (item: SidebarItem) => item.id ?? item.href ?? item.label;
57
+
58
+ /** Groups start open when asked, or when they contain the active item. */
59
+ let opened = $state<Record<string, boolean>>({});
60
+
61
+ const isOpen = (item: SidebarItem) =>
62
+ opened[keyOf(item)] ?? (item.open || item.items!.some((child) => keyOf(child) === value));
63
+
64
+ function toggle(item: SidebarItem) {
65
+ opened = { ...opened, [keyOf(item)]: !isOpen(item) };
66
+ }
67
+
68
+ function go(item: SidebarItem) {
69
+ if (item.disabled) return;
70
+ value = keyOf(item);
71
+ onnavigate?.(item);
72
+ }
73
+
74
+ const row =
75
+ 'flex w-full items-center gap-3 rounded-md px-2.5 py-2 text-left font-sans text-sm transition-colors duration-150 ease-brand-out disabled:pointer-events-none disabled:opacity-40';
76
+ </script>
77
+
78
+ <aside
79
+ class="flex h-full shrink-0 flex-col border-r border-hairline bg-bg-alt transition-[width] duration-200 ease-brand-out
80
+ {collapsed ? 'w-16' : 'w-60'} {className}"
81
+ >
82
+ {#if header}
83
+ <div class="flex h-16 shrink-0 items-center gap-3 border-b border-hairline px-3">
84
+ {@render header()}
85
+ </div>
86
+ {/if}
87
+
88
+ <nav aria-label={t.current.navigation} class="flex-1 overflow-y-auto p-2">
89
+ {#each sections as section, i (section.label ?? i)}
90
+ <div class="flex flex-col gap-0.5 {i > 0 ? 'mt-4' : ''}">
91
+ {#if section.label && !collapsed}
92
+ <p class="px-2.5 pb-1 font-sans text-[11px] font-semibold text-text-muted">
93
+ {section.label}
94
+ </p>
95
+ {:else if section.label && collapsed && i > 0}
96
+ <div class="mx-2 mb-1 h-px bg-hairline" role="separator"></div>
97
+ {/if}
98
+
99
+ {#each section.items as item (keyOf(item))}
100
+ {#if item.items?.length}
101
+ <button
102
+ type="button"
103
+ onclick={() => toggle(item)}
104
+ aria-expanded={isOpen(item)}
105
+ title={collapsed ? item.label : undefined}
106
+ class="{row} {focusRing} {toneRing[
107
+ tone
108
+ ]} text-text-secondary hover:bg-bg-inset hover:text-text"
109
+ >
110
+ <span class="min-w-0 flex-1 truncate {collapsed ? 'sr-only' : ''}">{item.label}</span>
111
+ {#if !collapsed}
112
+ <svg
113
+ class="size-3.5 shrink-0 transition-transform duration-200 {isOpen(item)
114
+ ? 'rotate-90'
115
+ : ''}"
116
+ viewBox="0 0 16 16"
117
+ fill="none"
118
+ aria-hidden="true"
119
+ >
120
+ <path
121
+ d="m6 4 4 4-4 4"
122
+ stroke="currentColor"
123
+ stroke-width="1.6"
124
+ stroke-linecap="round"
125
+ />
126
+ </svg>
127
+ {/if}
128
+ </button>
129
+
130
+ {#if isOpen(item) && !collapsed}
131
+ <div class="ml-4 flex flex-col gap-0.5 border-l border-hairline pl-2">
132
+ {#each item.items as child (keyOf(child))}
133
+ <a
134
+ href={child.href}
135
+ onclick={() => go(child)}
136
+ aria-current={value === keyOf(child) ? 'page' : undefined}
137
+ class="{row} {focusRing} {toneRing[tone]} {value === keyOf(child)
138
+ ? `${toneSoft[tone]} font-medium`
139
+ : 'text-text-muted hover:bg-bg-inset hover:text-text'} {child.disabled
140
+ ? 'pointer-events-none opacity-40'
141
+ : ''}"
142
+ >
143
+ <span class="min-w-0 flex-1 truncate">{child.label}</span>
144
+ {#if child.badge !== undefined}
145
+ <span class="shrink-0 text-[11px] tabular-nums">{child.badge}</span>
146
+ {/if}
147
+ </a>
148
+ {/each}
149
+ </div>
150
+ {/if}
151
+ {:else}
152
+ <a
153
+ href={item.href}
154
+ onclick={() => go(item)}
155
+ aria-current={value === keyOf(item) ? 'page' : undefined}
156
+ title={collapsed ? item.label : undefined}
157
+ class="{row} {focusRing} {toneRing[tone]} {value === keyOf(item)
158
+ ? `${toneSoft[tone]} font-medium`
159
+ : 'text-text-secondary hover:bg-bg-inset hover:text-text'} {item.disabled
160
+ ? 'pointer-events-none opacity-40'
161
+ : ''}"
162
+ >
163
+ <span class="min-w-0 flex-1 truncate {collapsed ? 'sr-only' : ''}">{item.label}</span>
164
+ {#if item.badge !== undefined && !collapsed}
165
+ <span class="shrink-0 text-[11px] text-text-muted tabular-nums">{item.badge}</span>
166
+ {/if}
167
+ </a>
168
+ {/if}
169
+ {/each}
170
+ </div>
171
+ {/each}
172
+ </nav>
173
+
174
+ {#if footer || collapsible}
175
+ <div class="flex shrink-0 flex-col gap-2 border-t border-hairline p-2">
176
+ {#if footer}
177
+ {@render footer()}
178
+ {/if}
179
+ {#if collapsible}
180
+ <button
181
+ type="button"
182
+ onclick={() => (collapsed = !collapsed)}
183
+ aria-label={collapsed ? t.current.expandSidebar : t.current.collapseSidebar}
184
+ class="inline-flex h-8 items-center justify-center gap-2 rounded-md font-sans text-xs text-text-muted transition-colors duration-150 hover:bg-bg-inset hover:text-text {focusRing} {toneRing[
185
+ tone
186
+ ]}"
187
+ >
188
+ <svg
189
+ class="size-4 transition-transform duration-200 {collapsed ? 'rotate-180' : ''}"
190
+ viewBox="0 0 16 16"
191
+ fill="none"
192
+ aria-hidden="true"
193
+ >
194
+ <path
195
+ d="m10 4-4 4 4 4"
196
+ stroke="currentColor"
197
+ stroke-width="1.6"
198
+ stroke-linecap="round"
199
+ />
200
+ </svg>
201
+ {#if !collapsed}<span>{t.current.collapseSidebar}</span>{/if}
202
+ </button>
203
+ {/if}
204
+ </div>
205
+ {/if}
206
+ </aside>
@@ -0,0 +1,36 @@
1
+ export interface SidebarItem {
2
+ /** Stable id used for the active state. Falls back to `href`. */
3
+ id?: string;
4
+ label: string;
5
+ href?: string;
6
+ disabled?: boolean;
7
+ badge?: string | number;
8
+ /** Nested links — the parent becomes a collapsible group. */
9
+ items?: SidebarItem[];
10
+ /** Open the group on first render. */
11
+ open?: boolean;
12
+ }
13
+ export interface SidebarSection {
14
+ /** Small heading above a run of items. */
15
+ label?: string;
16
+ items: SidebarItem[];
17
+ }
18
+ import type { Snippet } from 'svelte';
19
+ import { type Tone } from '../../core/tones.js';
20
+ interface Props {
21
+ sections: SidebarSection[];
22
+ /** Bindable — the `id` (or `href`) of the current item. */
23
+ value?: string;
24
+ /** Bindable — narrow rail mode. */
25
+ collapsed?: boolean;
26
+ /** Show the collapse button. */
27
+ collapsible?: boolean;
28
+ tone?: Tone;
29
+ header?: Snippet;
30
+ footer?: Snippet;
31
+ onnavigate?: (item: SidebarItem) => void;
32
+ class?: string;
33
+ }
34
+ declare const Sidebar: import("svelte").Component<Props, {}, "value" | "collapsed">;
35
+ type Sidebar = ReturnType<typeof Sidebar>;
36
+ export default Sidebar;
@@ -0,0 +1,46 @@
1
+ <script lang="ts">
2
+ import type { HTMLAttributes } from 'svelte/elements';
3
+
4
+ export type SkeletonVariant = 'text' | 'block' | 'circle';
5
+
6
+ interface Props extends HTMLAttributes<HTMLDivElement> {
7
+ variant?: SkeletonVariant;
8
+ /** `text` only — number of stacked lines, the last one runs short. */
9
+ lines?: number;
10
+ /** Any CSS length, e.g. `'12rem'` or `'60%'`. */
11
+ width?: string;
12
+ height?: string;
13
+ }
14
+
15
+ let {
16
+ variant = 'text',
17
+ lines = 1,
18
+ width,
19
+ height,
20
+ class: className = '',
21
+ ...rest
22
+ }: Props = $props();
23
+
24
+ const variants: Record<SkeletonVariant, string> = {
25
+ text: 'h-4 w-full rounded-md',
26
+ block: 'h-24 w-full rounded-lg',
27
+ circle: 'size-10 rounded-full'
28
+ };
29
+ </script>
30
+
31
+ {#if variant === 'text' && lines > 1}
32
+ <div class="flex w-full flex-col gap-2 {className}" {...rest}>
33
+ {#each { length: lines }, i (i)}
34
+ <div
35
+ class="h-4 animate-pulse rounded-md bg-bg-inset {i === lines - 1 ? 'w-2/3' : 'w-full'}"
36
+ style={width && i !== lines - 1 ? `width:${width}` : undefined}
37
+ ></div>
38
+ {/each}
39
+ </div>
40
+ {:else}
41
+ <div
42
+ class="animate-pulse bg-bg-inset {variants[variant]} {className}"
43
+ style="{width ? `width:${width};` : ''}{height ? `height:${height};` : ''}"
44
+ {...rest}
45
+ ></div>
46
+ {/if}
@@ -0,0 +1,13 @@
1
+ import type { HTMLAttributes } from 'svelte/elements';
2
+ export type SkeletonVariant = 'text' | 'block' | 'circle';
3
+ interface Props extends HTMLAttributes<HTMLDivElement> {
4
+ variant?: SkeletonVariant;
5
+ /** `text` only — number of stacked lines, the last one runs short. */
6
+ lines?: number;
7
+ /** Any CSS length, e.g. `'12rem'` or `'60%'`. */
8
+ width?: string;
9
+ height?: string;
10
+ }
11
+ declare const Skeleton: import("svelte").Component<Props, {}, "">;
12
+ type Skeleton = ReturnType<typeof Skeleton>;
13
+ export default Skeleton;
@@ -0,0 +1,80 @@
1
+ <script lang="ts">
2
+ import type { HTMLInputAttributes } from 'svelte/elements';
3
+ import { toneText, type Tone } from '../../core/tones.js';
4
+ import { percentOf } from '../../core/number.js';
5
+
6
+ interface Props extends Omit<HTMLInputAttributes, 'size' | 'type' | 'value' | 'min' | 'max'> {
7
+ value?: number;
8
+ min?: number;
9
+ max?: number;
10
+ step?: number;
11
+ tone?: Tone;
12
+ label?: string;
13
+ /** Prints the current value on the right of the label row. */
14
+ showValue?: boolean;
15
+ /** Appended to the printed value, e.g. `'%'`. */
16
+ unit?: string;
17
+ /** Tick labels under the track — usually just `[min, max]`. */
18
+ marks?: (number | string)[];
19
+ }
20
+
21
+ let {
22
+ value = $bindable(50),
23
+ min = 0,
24
+ max = 100,
25
+ step = 1,
26
+ tone = 'brand',
27
+ label,
28
+ showValue = false,
29
+ unit = '',
30
+ marks,
31
+ disabled = false,
32
+ class: className = '',
33
+ ...rest
34
+ }: Props = $props();
35
+
36
+ const pct = $derived(percentOf(value, min, max));
37
+
38
+ // The filled part of the track and the thumb both paint with `currentColor`,
39
+ // so a single tone class on the input drives every vendor pseudo-element.
40
+ // The gradient classes below are spelled out twice on purpose: Tailwind only
41
+ // sees literal class strings, so a shared JS constant would produce nothing.
42
+ </script>
43
+
44
+ <div class="flex w-full flex-col gap-2 {disabled ? 'opacity-50' : ''} {className}">
45
+ {#if label || showValue}
46
+ <div class="flex items-baseline justify-between gap-4 font-sans text-sm">
47
+ {#if label}<span class="text-text-secondary">{label}</span>{/if}
48
+ {#if showValue}
49
+ <span class="text-sm font-medium tabular-nums {toneText[tone]}">{value}{unit}</span>
50
+ {/if}
51
+ </div>
52
+ {/if}
53
+
54
+ <input
55
+ type="range"
56
+ bind:value
57
+ {min}
58
+ {max}
59
+ {step}
60
+ {disabled}
61
+ aria-label={label}
62
+ style="--pct:{pct}%"
63
+ class="h-5 w-full cursor-pointer appearance-none bg-transparent focus:outline-none disabled:cursor-not-allowed
64
+ {toneText[tone]}
65
+ focus-visible:outline-2 focus-visible:outline-offset-4
66
+ [&::-moz-range-thumb]:size-4 [&::-moz-range-thumb]:rounded-full
67
+ [&::-moz-range-thumb]:border-2 [&::-moz-range-thumb]:border-bg [&::-moz-range-thumb]:bg-current [&::-moz-range-thumb]:shadow-sm [&::-moz-range-track]:h-1.5 [&::-moz-range-track]:rounded-full [&::-moz-range-track]:bg-[linear-gradient(to_right,currentColor_var(--pct),var(--color-bg-inset)_var(--pct))] [&::-webkit-slider-runnable-track]:h-1.5 [&::-webkit-slider-runnable-track]:rounded-full [&::-webkit-slider-runnable-track]:bg-[linear-gradient(to_right,currentColor_var(--pct),var(--color-bg-inset)_var(--pct))]
68
+ [&::-webkit-slider-thumb]:-mt-[5px] [&::-webkit-slider-thumb]:size-4 [&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:border-2
69
+ [&::-webkit-slider-thumb]:border-bg [&::-webkit-slider-thumb]:bg-current [&::-webkit-slider-thumb]:shadow-sm"
70
+ {...rest}
71
+ />
72
+
73
+ {#if marks?.length}
74
+ <div class="flex justify-between text-[11px] text-text-muted tabular-nums">
75
+ {#each marks as mark (mark)}
76
+ <span>{mark}</span>
77
+ {/each}
78
+ </div>
79
+ {/if}
80
+ </div>
@@ -0,0 +1,19 @@
1
+ import type { HTMLInputAttributes } from 'svelte/elements';
2
+ import { type Tone } from '../../core/tones.js';
3
+ interface Props extends Omit<HTMLInputAttributes, 'size' | 'type' | 'value' | 'min' | 'max'> {
4
+ value?: number;
5
+ min?: number;
6
+ max?: number;
7
+ step?: number;
8
+ tone?: Tone;
9
+ label?: string;
10
+ /** Prints the current value on the right of the label row. */
11
+ showValue?: boolean;
12
+ /** Appended to the printed value, e.g. `'%'`. */
13
+ unit?: string;
14
+ /** Tick labels under the track — usually just `[min, max]`. */
15
+ marks?: (number | string)[];
16
+ }
17
+ declare const Slider: import("svelte").Component<Props, {}, "value">;
18
+ type Slider = ReturnType<typeof Slider>;
19
+ export default Slider;
@@ -0,0 +1,34 @@
1
+ <script lang="ts">
2
+ import type { HTMLAttributes } from 'svelte/elements';
3
+ import { toneText, type Tone } from '../../core/tones.js';
4
+ import { useLocale } from '../../core/locale.svelte.js';
5
+
6
+ export type SpinnerSize = 'xs' | 'sm' | 'md' | 'lg';
7
+
8
+ interface Props extends HTMLAttributes<HTMLSpanElement> {
9
+ size?: SpinnerSize;
10
+ /** Omit to inherit the parent's `currentColor` (e.g. inside a Button). */
11
+ tone?: Tone;
12
+ /** Defaults to the locale's loading string; pass `''` to hide it. */
13
+ label?: string;
14
+ }
15
+
16
+ const t = useLocale();
17
+
18
+ let { size = 'md', tone, label, class: className = '', ...rest }: Props = $props();
19
+
20
+ const sizes: Record<SpinnerSize, string> = {
21
+ xs: 'size-3 border-[1.5px]',
22
+ sm: 'size-4 border-2',
23
+ md: 'size-5 border-2',
24
+ lg: 'size-8 border-[3px]'
25
+ };
26
+ </script>
27
+
28
+ <span
29
+ role="status"
30
+ aria-label={label ?? t.current.loading}
31
+ class="inline-block shrink-0 animate-spin rounded-full border-current/25 border-t-current
32
+ {sizes[size]} {tone ? toneText[tone] : ''} {className}"
33
+ {...rest}
34
+ ></span>
@@ -0,0 +1,13 @@
1
+ import type { HTMLAttributes } from 'svelte/elements';
2
+ import { type Tone } from '../../core/tones.js';
3
+ export type SpinnerSize = 'xs' | 'sm' | 'md' | 'lg';
4
+ interface Props extends HTMLAttributes<HTMLSpanElement> {
5
+ size?: SpinnerSize;
6
+ /** Omit to inherit the parent's `currentColor` (e.g. inside a Button). */
7
+ tone?: Tone;
8
+ /** Defaults to the locale's loading string; pass `''` to hide it. */
9
+ label?: string;
10
+ }
11
+ declare const Spinner: import("svelte").Component<Props, {}, "">;
12
+ type Spinner = ReturnType<typeof Spinner>;
13
+ export default Spinner;
@@ -0,0 +1,51 @@
1
+ <script lang="ts">
2
+ import type { HTMLAttributes } from 'svelte/elements';
3
+ import { toneText, type Tone } from '../../core/tones.js';
4
+
5
+ export type StatTrend = 'up' | 'down' | 'flat';
6
+
7
+ interface Props extends HTMLAttributes<HTMLDivElement> {
8
+ label: string;
9
+ value: string | number;
10
+ /** Secondary figure, e.g. `'+12.4%'`. */
11
+ delta?: string;
12
+ trend?: StatTrend;
13
+ hint?: string;
14
+ /** Colour of the value itself. Leave unset for plain `text`. */
15
+ tone?: Tone;
16
+ }
17
+
18
+ let {
19
+ label,
20
+ value,
21
+ delta,
22
+ trend = 'flat',
23
+ hint,
24
+ tone,
25
+ class: className = '',
26
+ ...rest
27
+ }: Props = $props();
28
+
29
+ const trendTone: Record<StatTrend, Tone> = { up: 'success', down: 'danger', flat: 'neutral' };
30
+ const trendGlyph: Record<StatTrend, string> = { up: '↑', down: '↓', flat: '→' };
31
+ </script>
32
+
33
+ <div class="flex flex-col gap-1 font-sans {className}" {...rest}>
34
+ <span class="text-sm font-medium text-text-muted">{label}</span>
35
+ <div class="flex items-baseline gap-2">
36
+ <span
37
+ class="font-heading text-3xl font-semibold tracking-tight tabular-nums {tone
38
+ ? toneText[tone]
39
+ : 'text-text'}"
40
+ >
41
+ {value}
42
+ </span>
43
+ {#if delta}
44
+ <span class="text-sm font-medium {toneText[trendTone[trend]]}">
45
+ {trendGlyph[trend]}
46
+ {delta}
47
+ </span>
48
+ {/if}
49
+ </div>
50
+ {#if hint}<span class="text-sm text-text-muted">{hint}</span>{/if}
51
+ </div>
@@ -0,0 +1,16 @@
1
+ import type { HTMLAttributes } from 'svelte/elements';
2
+ import { type Tone } from '../../core/tones.js';
3
+ export type StatTrend = 'up' | 'down' | 'flat';
4
+ interface Props extends HTMLAttributes<HTMLDivElement> {
5
+ label: string;
6
+ value: string | number;
7
+ /** Secondary figure, e.g. `'+12.4%'`. */
8
+ delta?: string;
9
+ trend?: StatTrend;
10
+ hint?: string;
11
+ /** Colour of the value itself. Leave unset for plain `text`. */
12
+ tone?: Tone;
13
+ }
14
+ declare const Stat: import("svelte").Component<Props, {}, "">;
15
+ type Stat = ReturnType<typeof Stat>;
16
+ export default Stat;
@@ -0,0 +1,63 @@
1
+ <script lang="ts">
2
+ import type { HTMLAttributes } from 'svelte/elements';
3
+ import Stat from './Stat.svelte';
4
+ import type { StatTrend } from './Stat.svelte';
5
+ import type { Tone } from '../../core/tones.js';
6
+
7
+ export interface BandStat {
8
+ label: string;
9
+ value: string | number;
10
+ delta?: string;
11
+ trend?: StatTrend;
12
+ hint?: string;
13
+ tone?: Tone;
14
+ }
15
+
16
+ interface Props extends HTMLAttributes<HTMLElement> {
17
+ stats: BandStat[];
18
+ title?: string;
19
+ /** Figures in one bordered card rather than free-standing. */
20
+ bordered?: boolean;
21
+ }
22
+
23
+ let { stats, title, bordered = true, class: className = '', ...rest }: Props = $props();
24
+
25
+ const cols = $derived(
26
+ stats.length === 2
27
+ ? 'sm:grid-cols-2'
28
+ : stats.length === 4
29
+ ? 'sm:grid-cols-2 lg:grid-cols-4'
30
+ : 'sm:grid-cols-3'
31
+ );
32
+ </script>
33
+
34
+ <section class="w-full px-6 py-16 {className}" {...rest}>
35
+ <div class="mx-auto flex w-full max-w-6xl flex-col gap-8">
36
+ {#if title}
37
+ <h2
38
+ class="max-w-xl font-heading text-3xl font-semibold tracking-tight text-balance text-text"
39
+ >
40
+ {title}
41
+ </h2>
42
+ {/if}
43
+
44
+ <div
45
+ class="grid {cols} {bordered
46
+ ? 'gap-px overflow-hidden rounded-lg border border-hairline bg-hairline shadow-xs'
47
+ : 'gap-8'}"
48
+ >
49
+ {#each stats as stat (stat.label)}
50
+ <div class={bordered ? 'bg-bg p-6' : ''}>
51
+ <Stat
52
+ label={stat.label}
53
+ value={stat.value}
54
+ delta={stat.delta}
55
+ trend={stat.trend}
56
+ hint={stat.hint}
57
+ tone={stat.tone}
58
+ />
59
+ </div>
60
+ {/each}
61
+ </div>
62
+ </div>
63
+ </section>
@@ -0,0 +1,20 @@
1
+ import type { HTMLAttributes } from 'svelte/elements';
2
+ import type { StatTrend } from './Stat.svelte';
3
+ import type { Tone } from '../../core/tones.js';
4
+ export interface BandStat {
5
+ label: string;
6
+ value: string | number;
7
+ delta?: string;
8
+ trend?: StatTrend;
9
+ hint?: string;
10
+ tone?: Tone;
11
+ }
12
+ interface Props extends HTMLAttributes<HTMLElement> {
13
+ stats: BandStat[];
14
+ title?: string;
15
+ /** Figures in one bordered card rather than free-standing. */
16
+ bordered?: boolean;
17
+ }
18
+ declare const StatsBand: import("svelte").Component<Props, {}, "">;
19
+ type StatsBand = ReturnType<typeof StatsBand>;
20
+ export default StatsBand;