@nqmcreative/ui 0.1.1 → 0.2.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 (308) hide show
  1. package/README.md +89 -34
  2. package/cli/index.mjs +67 -30
  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,75 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+ import type { HTMLInputAttributes } from 'svelte/elements';
4
+ import { peerFocusRing, tonePeerChecked, tonePeerFocus, type Tone } from '../../core/tones.js';
5
+
6
+ interface Props extends Omit<HTMLInputAttributes, 'type' | 'size'> {
7
+ checked?: boolean;
8
+ /** Renders the dash state — visual only, `checked` stays false. */
9
+ indeterminate?: boolean;
10
+ label?: string;
11
+ description?: string;
12
+ tone?: Tone;
13
+ children?: Snippet;
14
+ }
15
+
16
+ let {
17
+ checked = $bindable(false),
18
+ indeterminate = false,
19
+ label,
20
+ description,
21
+ tone = 'brand',
22
+ disabled = false,
23
+ class: className = '',
24
+ children,
25
+ ...rest
26
+ }: Props = $props();
27
+
28
+ let el: HTMLInputElement | null = $state(null);
29
+
30
+ $effect(() => {
31
+ if (el) el.indeterminate = indeterminate;
32
+ });
33
+ </script>
34
+
35
+ <label
36
+ class="group inline-flex items-start gap-2.5 font-sans text-sm
37
+ {disabled ? 'pointer-events-none opacity-50' : 'cursor-pointer'} {className}"
38
+ >
39
+ <input bind:this={el} type="checkbox" bind:checked {disabled} class="peer sr-only" {...rest} />
40
+ <span
41
+ class="mt-0.5 flex size-[18px] shrink-0 items-center justify-center rounded border border-hairline-strong bg-bg shadow-xs transition-colors duration-150 ease-brand-out
42
+ {tonePeerChecked[tone]} {peerFocusRing} {tonePeerFocus[tone]}"
43
+ aria-hidden="true"
44
+ >
45
+ {#if indeterminate}
46
+ <span class="h-0.5 w-2.5 rounded-full bg-text-muted"></span>
47
+ {:else}
48
+ <svg
49
+ class="size-3 text-text-inverse opacity-0 transition-opacity duration-150 group-has-[:checked]:opacity-100"
50
+ viewBox="0 0 12 12"
51
+ fill="none"
52
+ >
53
+ <path
54
+ d="m2 6 2.6 2.6L10 3.2"
55
+ stroke="currentColor"
56
+ stroke-width="2"
57
+ stroke-linecap="round"
58
+ stroke-linejoin="round"
59
+ />
60
+ </svg>
61
+ {/if}
62
+ </span>
63
+ {#if label || description || children}
64
+ <span class="flex flex-col gap-0.5">
65
+ {#if children}
66
+ {@render children()}
67
+ {:else if label}
68
+ <span class="leading-snug text-text">{label}</span>
69
+ {/if}
70
+ {#if description}
71
+ <span class="text-[13px] leading-snug text-text-muted">{description}</span>
72
+ {/if}
73
+ </span>
74
+ {/if}
75
+ </label>
@@ -0,0 +1,15 @@
1
+ import type { Snippet } from 'svelte';
2
+ import type { HTMLInputAttributes } from 'svelte/elements';
3
+ import { type Tone } from '../../core/tones.js';
4
+ interface Props extends Omit<HTMLInputAttributes, 'type' | 'size'> {
5
+ checked?: boolean;
6
+ /** Renders the dash state — visual only, `checked` stays false. */
7
+ indeterminate?: boolean;
8
+ label?: string;
9
+ description?: string;
10
+ tone?: Tone;
11
+ children?: Snippet;
12
+ }
13
+ declare const Checkbox: import("svelte").Component<Props, {}, "checked">;
14
+ type Checkbox = ReturnType<typeof Checkbox>;
15
+ export default Checkbox;
@@ -0,0 +1,111 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+ import type { HTMLFieldsetAttributes } from 'svelte/elements';
4
+ import Checkbox from './Checkbox.svelte';
5
+ import { toneBorder, toneSurface, type Tone } from '../../core/tones.js';
6
+
7
+ export interface CheckboxOption {
8
+ value: string;
9
+ label: string;
10
+ description?: string;
11
+ disabled?: boolean;
12
+ }
13
+
14
+ interface Props extends Omit<HTMLFieldsetAttributes, 'onchange'> {
15
+ /** Bindable — the `value` of every checked option. */
16
+ value?: string[];
17
+ options?: CheckboxOption[];
18
+ legend?: string;
19
+ hint?: string;
20
+ error?: string;
21
+ required?: boolean;
22
+ tone?: Tone;
23
+ orientation?: 'vertical' | 'horizontal';
24
+ /** Wraps each option in a bordered, clickable card. */
25
+ boxed?: boolean;
26
+ /** Cap on how many may be checked at once. `0` means no limit. */
27
+ max?: number;
28
+ onchange?: (value: string[]) => void;
29
+ /** Pass your own `Checkbox`es instead of `options`. */
30
+ children?: Snippet;
31
+ }
32
+
33
+ let {
34
+ value = $bindable([]),
35
+ options,
36
+ legend,
37
+ hint,
38
+ error,
39
+ required = false,
40
+ tone = 'brand',
41
+ orientation = 'vertical',
42
+ boxed = false,
43
+ max = 0,
44
+ onchange,
45
+ class: className = '',
46
+ children,
47
+ ...rest
48
+ }: Props = $props();
49
+
50
+ const full = $derived(max > 0 && value.length >= max);
51
+
52
+ function toggle(option: CheckboxOption) {
53
+ value = value.includes(option.value)
54
+ ? value.filter((v) => v !== option.value)
55
+ : [...value, option.value];
56
+ onchange?.(value);
57
+ }
58
+ </script>
59
+
60
+ <fieldset class="flex flex-col gap-3 border-0 p-0 {className}" {...rest}>
61
+ {#if legend}
62
+ <legend class="mb-1 font-sans text-sm font-medium text-text">
63
+ {legend}
64
+ {#if required}<span class="ml-0.5 text-danger" aria-hidden="true">*</span>{/if}
65
+ </legend>
66
+ {/if}
67
+
68
+ <div class="flex gap-2.5 {orientation === 'horizontal' ? 'flex-row flex-wrap' : 'flex-col'}">
69
+ {#if options}
70
+ {#each options as option (option.value)}
71
+ {@const checked = value.includes(option.value)}
72
+ {@const disabled = option.disabled || (full && !checked)}
73
+ {#if boxed}
74
+ <label
75
+ class="flex flex-1 cursor-pointer items-start gap-3 rounded-lg border p-4 shadow-xs transition-colors duration-150 ease-brand-out
76
+ {checked
77
+ ? `${toneBorder[tone]} ${toneSurface[tone]}`
78
+ : 'border-hairline bg-bg hover:border-hairline-strong'}
79
+ {disabled ? 'pointer-events-none opacity-50' : ''}"
80
+ >
81
+ <Checkbox
82
+ {checked}
83
+ {disabled}
84
+ {tone}
85
+ label={option.label}
86
+ description={option.description}
87
+ onchange={() => toggle(option)}
88
+ />
89
+ </label>
90
+ {:else}
91
+ <Checkbox
92
+ {checked}
93
+ {disabled}
94
+ {tone}
95
+ label={option.label}
96
+ description={option.description}
97
+ onchange={() => toggle(option)}
98
+ />
99
+ {/if}
100
+ {/each}
101
+ {:else if children}
102
+ {@render children()}
103
+ {/if}
104
+ </div>
105
+
106
+ {#if error}
107
+ <p class="font-sans text-[13px] text-danger">{error}</p>
108
+ {:else if hint}
109
+ <p class="font-sans text-[13px] text-text-muted">{hint}</p>
110
+ {/if}
111
+ </fieldset>
@@ -0,0 +1,30 @@
1
+ import type { Snippet } from 'svelte';
2
+ import type { HTMLFieldsetAttributes } from 'svelte/elements';
3
+ import { type Tone } from '../../core/tones.js';
4
+ export interface CheckboxOption {
5
+ value: string;
6
+ label: string;
7
+ description?: string;
8
+ disabled?: boolean;
9
+ }
10
+ interface Props extends Omit<HTMLFieldsetAttributes, 'onchange'> {
11
+ /** Bindable — the `value` of every checked option. */
12
+ value?: string[];
13
+ options?: CheckboxOption[];
14
+ legend?: string;
15
+ hint?: string;
16
+ error?: string;
17
+ required?: boolean;
18
+ tone?: Tone;
19
+ orientation?: 'vertical' | 'horizontal';
20
+ /** Wraps each option in a bordered, clickable card. */
21
+ boxed?: boolean;
22
+ /** Cap on how many may be checked at once. `0` means no limit. */
23
+ max?: number;
24
+ onchange?: (value: string[]) => void;
25
+ /** Pass your own `Checkbox`es instead of `options`. */
26
+ children?: Snippet;
27
+ }
28
+ declare const CheckboxGroup: import("svelte").Component<Props, {}, "value">;
29
+ type CheckboxGroup = ReturnType<typeof CheckboxGroup>;
30
+ export default CheckboxGroup;
@@ -0,0 +1,266 @@
1
+ <script lang="ts">
2
+ import { anchored } from '../../core/actions/anchor.js';
3
+ import { clickOutside, portal } from '../../core/actions/dismissable.js';
4
+ import { ListCursor, groupItems, matchQuery, revealIndex } from '../../core/list.svelte.js';
5
+ import { toneFocusWithinBorder, toneSoft, toneText, type Tone } from '../../core/tones.js';
6
+ import { useLocale } from '../../core/locale.svelte.js';
7
+
8
+ export interface ComboboxOption {
9
+ value: string;
10
+ label: string;
11
+ /** Second line under the label. */
12
+ description?: string;
13
+ disabled?: boolean;
14
+ /** Options sharing a group are rendered under one heading. */
15
+ group?: string;
16
+ }
17
+
18
+ interface Props {
19
+ /** Bindable — the selected option's `value`, or `''`. */
20
+ value?: string;
21
+ options: ComboboxOption[];
22
+ placeholder?: string;
23
+ tone?: Tone;
24
+ invalid?: boolean;
25
+ disabled?: boolean;
26
+ /** Shows a clear button once something is selected. */
27
+ clearable?: boolean;
28
+ emptyText?: string;
29
+ id?: string;
30
+ name?: string;
31
+ onchange?: (value: string) => void;
32
+ class?: string;
33
+ }
34
+
35
+ let {
36
+ value = $bindable(''),
37
+ options,
38
+ placeholder,
39
+ tone = 'brand',
40
+ invalid = false,
41
+ disabled = false,
42
+ clearable = true,
43
+ emptyText,
44
+ id,
45
+ name,
46
+ onchange,
47
+ class: className = ''
48
+ }: Props = $props();
49
+
50
+ const t = useLocale();
51
+
52
+ let open = $state(false);
53
+ let query = $state('');
54
+ let wrapper: HTMLElement | null = $state(null);
55
+ let inputEl: HTMLInputElement | null = $state(null);
56
+ let listEl: HTMLElement | null = $state(null);
57
+
58
+ const selected = $derived(options.find((option) => option.value === value));
59
+
60
+ const matches = $derived(
61
+ matchQuery(options, query, (option) => `${option.label} ${option.description ?? ''}`)
62
+ );
63
+
64
+ /** Options in render order, grouped when any option declares a `group`. */
65
+ const groups = $derived(groupItems(matches));
66
+ const flat = $derived(groups.flatMap(([, items]) => items));
67
+
68
+ const cursor = new ListCursor(() => flat);
69
+ const active = $derived(cursor.index);
70
+
71
+ /**
72
+ * Set while we hand focus back to the field after a choice. Focusing fires
73
+ * `focus` synchronously, and this field opens on focus — without the guard,
74
+ * picking an option would immediately reopen the list it just closed.
75
+ */
76
+ let restoring = false;
77
+
78
+ function openList() {
79
+ if (disabled || open || restoring) return;
80
+ open = true;
81
+ query = '';
82
+ cursor.reset((option) => option.value === value);
83
+ }
84
+
85
+ function choose(option: ComboboxOption) {
86
+ if (option.disabled) return;
87
+ value = option.value;
88
+ onchange?.(option.value);
89
+ open = false;
90
+ query = '';
91
+ restoring = true;
92
+ inputEl?.focus();
93
+ restoring = false;
94
+ }
95
+
96
+ function clear(event: MouseEvent) {
97
+ event.stopPropagation();
98
+ value = '';
99
+ query = '';
100
+ onchange?.('');
101
+ restoring = true;
102
+ inputEl?.focus();
103
+ restoring = false;
104
+ }
105
+
106
+ function move(step: number) {
107
+ cursor.move(step);
108
+ revealIndex(listEl, cursor.index);
109
+ }
110
+
111
+ function onKeydown(event: KeyboardEvent) {
112
+ switch (event.key) {
113
+ case 'ArrowDown':
114
+ event.preventDefault();
115
+ if (!open) openList();
116
+ else move(1);
117
+ break;
118
+ case 'ArrowUp':
119
+ event.preventDefault();
120
+ if (open) move(-1);
121
+ break;
122
+ case 'Enter':
123
+ if (open && cursor.current) {
124
+ event.preventDefault();
125
+ choose(cursor.current);
126
+ }
127
+ break;
128
+ case 'Escape':
129
+ if (open) {
130
+ event.preventDefault();
131
+ event.stopPropagation();
132
+ open = false;
133
+ query = '';
134
+ }
135
+ break;
136
+ case 'Tab':
137
+ open = false;
138
+ break;
139
+ }
140
+ }
141
+ </script>
142
+
143
+ <div
144
+ bind:this={wrapper}
145
+ class="relative inline-flex w-full items-center gap-2 rounded-md border bg-bg pr-1.5 pl-3 shadow-xs transition-colors duration-150 ease-brand-out
146
+ {invalid ? 'border-danger' : `border-hairline-strong ${toneFocusWithinBorder[tone]}`}
147
+ {disabled ? 'pointer-events-none opacity-50' : ''} {className}"
148
+ >
149
+ <input
150
+ bind:this={inputEl}
151
+ {id}
152
+ {disabled}
153
+ type="text"
154
+ role="combobox"
155
+ autocomplete="off"
156
+ aria-expanded={open}
157
+ aria-controls="{id ?? 'combobox'}-listbox"
158
+ aria-activedescendant={open && flat[active] ? `${id ?? 'combobox'}-opt-${active}` : undefined}
159
+ aria-invalid={invalid ? 'true' : undefined}
160
+ placeholder={selected ? selected.label : (placeholder ?? t.current.comboboxPlaceholder)}
161
+ value={open ? query : (selected?.label ?? '')}
162
+ oninput={(event) => {
163
+ query = event.currentTarget.value;
164
+ open = true;
165
+ cursor.index = 0;
166
+ }}
167
+ onfocus={openList}
168
+ onkeydown={onKeydown}
169
+ class="h-10 w-full min-w-0 bg-transparent font-sans text-sm text-text placeholder:text-text-muted focus:outline-none"
170
+ />
171
+
172
+ {#if name}<input type="hidden" {name} {value} />{/if}
173
+
174
+ {#if clearable && value && !disabled}
175
+ <button
176
+ type="button"
177
+ onclick={clear}
178
+ aria-label={t.current.clear}
179
+ class="shrink-0 rounded p-1 text-text-muted transition-colors duration-150 hover:bg-bg-inset hover:text-text focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-current"
180
+ >
181
+ <svg class="size-3.5" viewBox="0 0 14 14" fill="none" aria-hidden="true">
182
+ <path
183
+ d="m2 2 10 10M12 2 2 12"
184
+ stroke="currentColor"
185
+ stroke-width="1.6"
186
+ stroke-linecap="round"
187
+ />
188
+ </svg>
189
+ </button>
190
+ {/if}
191
+
192
+ <svg
193
+ class="pointer-events-none mr-1.5 size-4 shrink-0 text-text-muted transition-transform duration-150 {open
194
+ ? 'rotate-180'
195
+ : ''}"
196
+ viewBox="0 0 16 16"
197
+ fill="none"
198
+ aria-hidden="true"
199
+ >
200
+ <path d="m4 6 4 4 4-4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" />
201
+ </svg>
202
+ </div>
203
+
204
+ {#if open}
205
+ <div
206
+ bind:this={listEl}
207
+ use:portal
208
+ use:anchored={{ anchor: wrapper, placement: 'bottom-start', offset: 4, matchWidth: true }}
209
+ use:clickOutside={{ onoutside: () => (open = false), ignore: [wrapper] }}
210
+ id="{id ?? 'combobox'}-listbox"
211
+ role="listbox"
212
+ class="z-50 max-h-64 overflow-y-auto rounded-lg border border-hairline bg-bg py-1 font-sans shadow-lg"
213
+ >
214
+ {#if flat.length === 0}
215
+ <p class="px-3 py-6 text-center text-sm text-text-muted">
216
+ {emptyText ?? t.current.noMatches}
217
+ </p>
218
+ {:else}
219
+ {#each groups as [group, items] (group)}
220
+ {#if group}
221
+ <p class="px-3 pt-2 pb-1 text-[11px] font-semibold text-text-muted">{group}</p>
222
+ {/if}
223
+ {#each items as option (option.value)}
224
+ {@const index = flat.indexOf(option)}
225
+ <!-- svelte-ignore a11y_click_events_have_key_events -->
226
+ <div
227
+ id="{id ?? 'combobox'}-opt-{index}"
228
+ data-index={index}
229
+ role="option"
230
+ tabindex="-1"
231
+ aria-selected={option.value === value}
232
+ aria-disabled={option.disabled}
233
+ onclick={() => choose(option)}
234
+ onpointermove={() => (cursor.index = index)}
235
+ class="mx-1 flex cursor-pointer flex-col gap-0.5 rounded-md px-2.5 py-2 text-sm transition-colors duration-100
236
+ {option.disabled ? 'pointer-events-none opacity-40' : ''}
237
+ {index === active ? toneSoft[tone] : 'text-text-secondary'}"
238
+ >
239
+ <span class="flex items-center gap-2">
240
+ <span class="min-w-0 flex-1 truncate">{option.label}</span>
241
+ {#if option.value === value}
242
+ <svg
243
+ class="size-3.5 shrink-0 {toneText[tone]}"
244
+ viewBox="0 0 14 14"
245
+ fill="none"
246
+ aria-hidden="true"
247
+ >
248
+ <path
249
+ d="m2 7 3.2 3.2L12 3.6"
250
+ stroke="currentColor"
251
+ stroke-width="1.8"
252
+ stroke-linecap="round"
253
+ stroke-linejoin="round"
254
+ />
255
+ </svg>
256
+ {/if}
257
+ </span>
258
+ {#if option.description}
259
+ <span class="truncate text-xs text-text-muted">{option.description}</span>
260
+ {/if}
261
+ </div>
262
+ {/each}
263
+ {/each}
264
+ {/if}
265
+ </div>
266
+ {/if}
@@ -0,0 +1,29 @@
1
+ import { type Tone } from '../../core/tones.js';
2
+ export interface ComboboxOption {
3
+ value: string;
4
+ label: string;
5
+ /** Second line under the label. */
6
+ description?: string;
7
+ disabled?: boolean;
8
+ /** Options sharing a group are rendered under one heading. */
9
+ group?: string;
10
+ }
11
+ interface Props {
12
+ /** Bindable — the selected option's `value`, or `''`. */
13
+ value?: string;
14
+ options: ComboboxOption[];
15
+ placeholder?: string;
16
+ tone?: Tone;
17
+ invalid?: boolean;
18
+ disabled?: boolean;
19
+ /** Shows a clear button once something is selected. */
20
+ clearable?: boolean;
21
+ emptyText?: string;
22
+ id?: string;
23
+ name?: string;
24
+ onchange?: (value: string) => void;
25
+ class?: string;
26
+ }
27
+ declare const Combobox: import("svelte").Component<Props, {}, "value">;
28
+ type Combobox = ReturnType<typeof Combobox>;
29
+ export default Combobox;