@thomasfosterau/components 0.0.0 → 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 (484) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +241 -56
  3. package/dist/canvas/VectorCanvas.svelte +320 -0
  4. package/dist/canvas/VectorCanvas.svelte.d.ts +105 -0
  5. package/dist/canvas/history.d.ts +105 -0
  6. package/dist/canvas/history.js +147 -0
  7. package/dist/canvas/index.d.ts +15 -0
  8. package/dist/canvas/index.js +14 -0
  9. package/dist/canvas/types.d.ts +91 -0
  10. package/dist/canvas/types.js +13 -0
  11. package/dist/canvas/utils.d.ts +66 -0
  12. package/dist/canvas/utils.js +114 -0
  13. package/dist/charts/Chart.svelte +300 -0
  14. package/dist/charts/Chart.svelte.d.ts +50 -0
  15. package/dist/charts/index.d.ts +11 -0
  16. package/dist/charts/index.js +10 -0
  17. package/dist/charts/types.d.ts +28 -0
  18. package/dist/charts/types.js +6 -0
  19. package/dist/citations/BookCitation.svelte +53 -0
  20. package/dist/citations/BookCitation.svelte.d.ts +41 -0
  21. package/dist/citations/ChapterCitation.svelte +38 -0
  22. package/dist/citations/ChapterCitation.svelte.d.ts +50 -0
  23. package/dist/citations/Citation.svelte +47 -0
  24. package/dist/citations/Citation.svelte.d.ts +24 -0
  25. package/dist/citations/CreditList.svelte +69 -0
  26. package/dist/citations/CreditList.svelte.d.ts +47 -0
  27. package/dist/citations/DOILink.svelte +28 -0
  28. package/dist/citations/DOILink.svelte.d.ts +19 -0
  29. package/dist/citations/Footnote.svelte +39 -0
  30. package/dist/citations/Footnote.svelte.d.ts +17 -0
  31. package/dist/citations/FootnoteList.svelte +36 -0
  32. package/dist/citations/FootnoteList.svelte.d.ts +21 -0
  33. package/dist/citations/ISBNLink.svelte +29 -0
  34. package/dist/citations/ISBNLink.svelte.d.ts +19 -0
  35. package/dist/citations/ISSNLink.svelte +29 -0
  36. package/dist/citations/ISSNLink.svelte.d.ts +19 -0
  37. package/dist/citations/Publisher.svelte +34 -0
  38. package/dist/citations/Publisher.svelte.d.ts +14 -0
  39. package/dist/citations/ReferenceList.svelte +53 -0
  40. package/dist/citations/ReferenceList.svelte.d.ts +21 -0
  41. package/dist/citations/ReportCitation.svelte +41 -0
  42. package/dist/citations/ReportCitation.svelte.d.ts +36 -0
  43. package/dist/citations/ScholarlyArticleCitation.svelte +64 -0
  44. package/dist/citations/ScholarlyArticleCitation.svelte.d.ts +41 -0
  45. package/dist/citations/ThesisCitation.svelte +35 -0
  46. package/dist/citations/ThesisCitation.svelte.d.ts +29 -0
  47. package/dist/citations/bibliography.svelte.d.ts +55 -0
  48. package/dist/citations/bibliography.svelte.js +78 -0
  49. package/dist/citations/citation.d.ts +71 -0
  50. package/dist/citations/citation.js +121 -0
  51. package/dist/citations/csl.d.ts +102 -0
  52. package/dist/citations/csl.js +20 -0
  53. package/dist/citations/index.d.ts +31 -0
  54. package/dist/citations/index.js +36 -0
  55. package/dist/citations/list-format.d.ts +34 -0
  56. package/dist/citations/list-format.js +40 -0
  57. package/dist/context.svelte.d.ts +46 -0
  58. package/dist/context.svelte.js +51 -0
  59. package/dist/data/ChatBubble.svelte +48 -0
  60. package/dist/data/ChatBubble.svelte.d.ts +33 -0
  61. package/dist/data/DataGrid.svelte +150 -0
  62. package/dist/data/DataGrid.svelte.d.ts +118 -0
  63. package/dist/data/DescriptionList.svelte +53 -0
  64. package/dist/data/DescriptionList.svelte.d.ts +26 -0
  65. package/dist/data/DescriptionRow.svelte +56 -0
  66. package/dist/data/DescriptionRow.svelte.d.ts +21 -0
  67. package/dist/data/DiffText.svelte +29 -0
  68. package/dist/data/DiffText.svelte.d.ts +19 -0
  69. package/dist/data/ItemList.svelte +80 -0
  70. package/dist/data/ItemList.svelte.d.ts +52 -0
  71. package/dist/data/LinkListItem.svelte +46 -0
  72. package/dist/data/LinkListItem.svelte.d.ts +21 -0
  73. package/dist/data/MessageThread.svelte +29 -0
  74. package/dist/data/MessageThread.svelte.d.ts +17 -0
  75. package/dist/data/Pagination.svelte +136 -0
  76. package/dist/data/Pagination.svelte.d.ts +79 -0
  77. package/dist/data/PaginationFooter.svelte +42 -0
  78. package/dist/data/PaginationFooter.svelte.d.ts +61 -0
  79. package/dist/data/ResultCount.svelte +27 -0
  80. package/dist/data/ResultCount.svelte.d.ts +18 -0
  81. package/dist/data/Table.svelte +151 -0
  82. package/dist/data/Table.svelte.d.ts +75 -0
  83. package/dist/data/TreeList.svelte +41 -0
  84. package/dist/data/TreeList.svelte.d.ts +17 -0
  85. package/dist/data/TreeListItem.svelte +29 -0
  86. package/dist/data/TreeListItem.svelte.d.ts +10 -0
  87. package/dist/data/description-context.d.ts +39 -0
  88. package/dist/data/description-context.js +36 -0
  89. package/dist/data/diff.d.ts +14 -0
  90. package/dist/data/diff.js +10 -0
  91. package/dist/data/index.d.ts +37 -0
  92. package/dist/data/index.js +37 -0
  93. package/dist/data/list-item.d.ts +30 -0
  94. package/dist/data/list-item.js +19 -0
  95. package/dist/data/pagination.d.ts +81 -0
  96. package/dist/data/pagination.js +79 -0
  97. package/dist/data/table-types.d.ts +71 -0
  98. package/dist/data/table-types.js +35 -0
  99. package/dist/feedback/ConfirmDialog.svelte +79 -0
  100. package/dist/feedback/ConfirmDialog.svelte.d.ts +82 -0
  101. package/dist/feedback/Dialog.svelte +47 -0
  102. package/dist/feedback/Dialog.svelte.d.ts +36 -0
  103. package/dist/feedback/DialogFrame.svelte +64 -0
  104. package/dist/feedback/DialogFrame.svelte.d.ts +23 -0
  105. package/dist/feedback/Drawer.svelte +43 -0
  106. package/dist/feedback/Drawer.svelte.d.ts +43 -0
  107. package/dist/feedback/LoadingBoundary.svelte +61 -0
  108. package/dist/feedback/LoadingBoundary.svelte.d.ts +34 -0
  109. package/dist/feedback/ProgressBar.svelte +46 -0
  110. package/dist/feedback/ProgressBar.svelte.d.ts +28 -0
  111. package/dist/feedback/SegmentBar.svelte +83 -0
  112. package/dist/feedback/SegmentBar.svelte.d.ts +37 -0
  113. package/dist/feedback/StatTile.svelte +77 -0
  114. package/dist/feedback/StatTile.svelte.d.ts +50 -0
  115. package/dist/feedback/Stats.svelte +18 -0
  116. package/dist/feedback/Stats.svelte.d.ts +16 -0
  117. package/dist/feedback/Steps.svelte +72 -0
  118. package/dist/feedback/Steps.svelte.d.ts +61 -0
  119. package/dist/feedback/Timeline.svelte +86 -0
  120. package/dist/feedback/Timeline.svelte.d.ts +55 -0
  121. package/dist/feedback/Toaster.svelte +78 -0
  122. package/dist/feedback/Toaster.svelte.d.ts +32 -0
  123. package/dist/feedback/index.d.ts +34 -0
  124. package/dist/feedback/index.js +29 -0
  125. package/dist/feedback/sizes.d.ts +41 -0
  126. package/dist/feedback/sizes.js +69 -0
  127. package/dist/feedback/toaster.d.ts +48 -0
  128. package/dist/feedback/toaster.js +29 -0
  129. package/dist/fields/Calendar.svelte +60 -0
  130. package/dist/fields/Calendar.svelte.d.ts +11 -0
  131. package/dist/fields/CalendarMonths.svelte +86 -0
  132. package/dist/fields/CalendarMonths.svelte.d.ts +30 -0
  133. package/dist/fields/Checkbox.svelte +33 -0
  134. package/dist/fields/Checkbox.svelte.d.ts +30 -0
  135. package/dist/fields/CheckboxGroup.svelte +41 -0
  136. package/dist/fields/CheckboxGroup.svelte.d.ts +40 -0
  137. package/dist/fields/Combobox.svelte +229 -0
  138. package/dist/fields/Combobox.svelte.d.ts +133 -0
  139. package/dist/fields/DateField.svelte +37 -0
  140. package/dist/fields/DateField.svelte.d.ts +20 -0
  141. package/dist/fields/DateInput.svelte +31 -0
  142. package/dist/fields/DateInput.svelte.d.ts +35 -0
  143. package/dist/fields/DatePicker.svelte +47 -0
  144. package/dist/fields/DatePicker.svelte.d.ts +25 -0
  145. package/dist/fields/DateRangePicker.svelte +70 -0
  146. package/dist/fields/DateRangePicker.svelte.d.ts +43 -0
  147. package/dist/fields/Dropzone.svelte +232 -0
  148. package/dist/fields/Dropzone.svelte.d.ts +103 -0
  149. package/dist/fields/FieldErrors.svelte +30 -0
  150. package/dist/fields/FieldErrors.svelte.d.ts +11 -0
  151. package/dist/fields/Fieldset.svelte +53 -0
  152. package/dist/fields/Fieldset.svelte.d.ts +27 -0
  153. package/dist/fields/FileInput.svelte +68 -0
  154. package/dist/fields/FileInput.svelte.d.ts +39 -0
  155. package/dist/fields/FormField.svelte +78 -0
  156. package/dist/fields/FormField.svelte.d.ts +29 -0
  157. package/dist/fields/ImageInput.svelte +87 -0
  158. package/dist/fields/ImageInput.svelte.d.ts +45 -0
  159. package/dist/fields/MultiSelect.svelte +112 -0
  160. package/dist/fields/MultiSelect.svelte.d.ts +75 -0
  161. package/dist/fields/NumberField.svelte +190 -0
  162. package/dist/fields/NumberField.svelte.d.ts +76 -0
  163. package/dist/fields/PasswordInput.svelte +95 -0
  164. package/dist/fields/PasswordInput.svelte.d.ts +58 -0
  165. package/dist/fields/PickerPopover.svelte +47 -0
  166. package/dist/fields/PickerPopover.svelte.d.ts +16 -0
  167. package/dist/fields/PinInput.svelte +83 -0
  168. package/dist/fields/PinInput.svelte.d.ts +66 -0
  169. package/dist/fields/PushToggle.svelte +93 -0
  170. package/dist/fields/PushToggle.svelte.d.ts +55 -0
  171. package/dist/fields/RadioGroup.svelte +88 -0
  172. package/dist/fields/RadioGroup.svelte.d.ts +41 -0
  173. package/dist/fields/RangeCalendar.svelte +51 -0
  174. package/dist/fields/RangeCalendar.svelte.d.ts +23 -0
  175. package/dist/fields/Rating.svelte +127 -0
  176. package/dist/fields/Rating.svelte.d.ts +86 -0
  177. package/dist/fields/SearchInput.svelte +58 -0
  178. package/dist/fields/SearchInput.svelte.d.ts +33 -0
  179. package/dist/fields/SegmentGroup.svelte +91 -0
  180. package/dist/fields/SegmentGroup.svelte.d.ts +20 -0
  181. package/dist/fields/Select.svelte +36 -0
  182. package/dist/fields/Select.svelte.d.ts +35 -0
  183. package/dist/fields/Slider.svelte +194 -0
  184. package/dist/fields/Slider.svelte.d.ts +100 -0
  185. package/dist/fields/TagsInput.svelte +256 -0
  186. package/dist/fields/TagsInput.svelte.d.ts +102 -0
  187. package/dist/fields/TextInput.svelte +26 -0
  188. package/dist/fields/TextInput.svelte.d.ts +36 -0
  189. package/dist/fields/Textarea.svelte +22 -0
  190. package/dist/fields/Textarea.svelte.d.ts +31 -0
  191. package/dist/fields/TimeField.svelte +30 -0
  192. package/dist/fields/TimeField.svelte.d.ts +19 -0
  193. package/dist/fields/Toggle.svelte +72 -0
  194. package/dist/fields/Toggle.svelte.d.ts +38 -0
  195. package/dist/fields/VideoInput.svelte +35 -0
  196. package/dist/fields/VideoInput.svelte.d.ts +46 -0
  197. package/dist/fields/calendar-props.d.ts +119 -0
  198. package/dist/fields/calendar-props.js +51 -0
  199. package/dist/fields/dates.d.ts +28 -0
  200. package/dist/fields/dates.js +26 -0
  201. package/dist/fields/field-types.d.ts +80 -0
  202. package/dist/fields/field-types.js +92 -0
  203. package/dist/fields/file-validation.d.ts +30 -0
  204. package/dist/fields/file-validation.js +51 -0
  205. package/dist/fields/index.d.ts +43 -0
  206. package/dist/fields/index.js +42 -0
  207. package/dist/fields/latest-search.svelte.d.ts +38 -0
  208. package/dist/fields/latest-search.svelte.js +85 -0
  209. package/dist/fields/number-format.d.ts +52 -0
  210. package/dist/fields/number-format.js +89 -0
  211. package/dist/fields/segmented-field.d.ts +128 -0
  212. package/dist/fields/segmented-field.js +52 -0
  213. package/dist/fields/slider-keys.d.ts +21 -0
  214. package/dist/fields/slider-keys.js +37 -0
  215. package/dist/formatting/Countdown.svelte +110 -0
  216. package/dist/formatting/Countdown.svelte.d.ts +35 -0
  217. package/dist/formatting/DateTime.svelte +35 -0
  218. package/dist/formatting/DateTime.svelte.d.ts +26 -0
  219. package/dist/formatting/Duration.svelte +18 -0
  220. package/dist/formatting/Duration.svelte.d.ts +20 -0
  221. package/dist/formatting/FormatList.svelte +31 -0
  222. package/dist/formatting/FormatList.svelte.d.ts +46 -0
  223. package/dist/formatting/Highlight.svelte +51 -0
  224. package/dist/formatting/Highlight.svelte.d.ts +19 -0
  225. package/dist/formatting/Number.svelte +35 -0
  226. package/dist/formatting/Number.svelte.d.ts +43 -0
  227. package/dist/formatting/RelativeTime.svelte +69 -0
  228. package/dist/formatting/RelativeTime.svelte.d.ts +26 -0
  229. package/dist/formatting/Year.svelte +39 -0
  230. package/dist/formatting/Year.svelte.d.ts +21 -0
  231. package/dist/formatting/duration.d.ts +44 -0
  232. package/dist/formatting/duration.js +125 -0
  233. package/dist/formatting/index.d.ts +15 -0
  234. package/dist/formatting/index.js +17 -0
  235. package/dist/forms/EntityForm.svelte +185 -0
  236. package/dist/forms/EntityForm.svelte.d.ts +66 -0
  237. package/dist/forms/FormActions.svelte +29 -0
  238. package/dist/forms/FormActions.svelte.d.ts +37 -0
  239. package/dist/forms/FormErrors.svelte +21 -0
  240. package/dist/forms/FormErrors.svelte.d.ts +16 -0
  241. package/dist/forms/HiddenField.svelte +22 -0
  242. package/dist/forms/HiddenField.svelte.d.ts +11 -0
  243. package/dist/forms/SearchForm.svelte +43 -0
  244. package/dist/forms/SearchForm.svelte.d.ts +36 -0
  245. package/dist/forms/entity-form.d.ts +12 -0
  246. package/dist/forms/entity-form.js +12 -0
  247. package/dist/forms/index.d.ts +14 -0
  248. package/dist/forms/index.js +14 -0
  249. package/dist/hotkeys/HotkeyBadge.svelte +39 -0
  250. package/dist/hotkeys/HotkeyBadge.svelte.d.ts +25 -0
  251. package/dist/hotkeys/HotkeyHelpDialog.svelte +68 -0
  252. package/dist/hotkeys/HotkeyHelpDialog.svelte.d.ts +35 -0
  253. package/dist/hotkeys/HotkeyProvider.svelte +92 -0
  254. package/dist/hotkeys/HotkeyProvider.svelte.d.ts +4 -0
  255. package/dist/hotkeys/context.svelte.d.ts +47 -0
  256. package/dist/hotkeys/context.svelte.js +72 -0
  257. package/dist/hotkeys/index.d.ts +28 -0
  258. package/dist/hotkeys/index.js +27 -0
  259. package/dist/hotkeys/match.d.ts +65 -0
  260. package/dist/hotkeys/match.js +135 -0
  261. package/dist/hotkeys/registry.svelte.d.ts +55 -0
  262. package/dist/hotkeys/registry.svelte.js +110 -0
  263. package/dist/hotkeys/types.d.ts +74 -0
  264. package/dist/hotkeys/types.js +18 -0
  265. package/dist/index.d.ts +37 -0
  266. package/dist/index.js +37 -0
  267. package/dist/infobox/Infobox.svelte +79 -0
  268. package/dist/infobox/Infobox.svelte.d.ts +33 -0
  269. package/dist/infobox/InfoboxHeader.svelte +35 -0
  270. package/dist/infobox/InfoboxHeader.svelte.d.ts +18 -0
  271. package/dist/infobox/InfoboxImage.svelte +38 -0
  272. package/dist/infobox/InfoboxImage.svelte.d.ts +21 -0
  273. package/dist/infobox/InfoboxRow.svelte +50 -0
  274. package/dist/infobox/InfoboxRow.svelte.d.ts +25 -0
  275. package/dist/infobox/InfoboxSection.svelte +24 -0
  276. package/dist/infobox/InfoboxSection.svelte.d.ts +12 -0
  277. package/dist/infobox/index.d.ts +21 -0
  278. package/dist/infobox/index.js +20 -0
  279. package/dist/infobox/types.d.ts +86 -0
  280. package/dist/infobox/types.js +27 -0
  281. package/dist/layout/AppShell.svelte +50 -0
  282. package/dist/layout/AppShell.svelte.d.ts +28 -0
  283. package/dist/layout/Breadcrumbs.svelte +52 -0
  284. package/dist/layout/Breadcrumbs.svelte.d.ts +18 -0
  285. package/dist/layout/Cluster.svelte +28 -0
  286. package/dist/layout/Cluster.svelte.d.ts +27 -0
  287. package/dist/layout/DetailLayout.svelte +50 -0
  288. package/dist/layout/DetailLayout.svelte.d.ts +19 -0
  289. package/dist/layout/FilterBar.svelte +40 -0
  290. package/dist/layout/FilterBar.svelte.d.ts +12 -0
  291. package/dist/layout/Fits.svelte +27 -0
  292. package/dist/layout/Fits.svelte.d.ts +13 -0
  293. package/dist/layout/Flow.svelte +46 -0
  294. package/dist/layout/Flow.svelte.d.ts +16 -0
  295. package/dist/layout/Footer.svelte +32 -0
  296. package/dist/layout/Footer.svelte.d.ts +12 -0
  297. package/dist/layout/Grid.svelte +23 -0
  298. package/dist/layout/Grid.svelte.d.ts +26 -0
  299. package/dist/layout/HStack.svelte +12 -0
  300. package/dist/layout/HStack.svelte.d.ts +34 -0
  301. package/dist/layout/Hero.svelte +76 -0
  302. package/dist/layout/Hero.svelte.d.ts +36 -0
  303. package/dist/layout/Main.svelte +30 -0
  304. package/dist/layout/Main.svelte.d.ts +15 -0
  305. package/dist/layout/Navbar.svelte +68 -0
  306. package/dist/layout/Navbar.svelte.d.ts +31 -0
  307. package/dist/layout/PageHeader.svelte +77 -0
  308. package/dist/layout/PageHeader.svelte.d.ts +33 -0
  309. package/dist/layout/Section.svelte +72 -0
  310. package/dist/layout/Section.svelte.d.ts +40 -0
  311. package/dist/layout/Sidebar.svelte +54 -0
  312. package/dist/layout/Sidebar.svelte.d.ts +27 -0
  313. package/dist/layout/Spacer.svelte +12 -0
  314. package/dist/layout/Spacer.svelte.d.ts +6 -0
  315. package/dist/layout/Tabs.svelte +85 -0
  316. package/dist/layout/Tabs.svelte.d.ts +42 -0
  317. package/dist/layout/VStack.svelte +12 -0
  318. package/dist/layout/VStack.svelte.d.ts +29 -0
  319. package/dist/layout/index.d.ts +38 -0
  320. package/dist/layout/index.js +38 -0
  321. package/dist/layout/space.d.ts +44 -0
  322. package/dist/layout/space.js +76 -0
  323. package/dist/layout/types.d.ts +52 -0
  324. package/dist/layout/types.js +27 -0
  325. package/dist/links/ContextLinks.svelte +28 -0
  326. package/dist/links/ContextLinks.svelte.d.ts +20 -0
  327. package/dist/links/EmailLink.svelte +26 -0
  328. package/dist/links/EmailLink.svelte.d.ts +20 -0
  329. package/dist/links/index.d.ts +7 -0
  330. package/dist/links/index.js +7 -0
  331. package/dist/media/Figure.svelte +26 -0
  332. package/dist/media/Figure.svelte.d.ts +12 -0
  333. package/dist/media/Image.svelte +76 -0
  334. package/dist/media/Image.svelte.d.ts +41 -0
  335. package/dist/media/Video.svelte +65 -0
  336. package/dist/media/Video.svelte.d.ts +29 -0
  337. package/dist/media/image-dimensions.d.ts +28 -0
  338. package/dist/media/image-dimensions.js +34 -0
  339. package/dist/media/index.d.ts +10 -0
  340. package/dist/media/index.js +10 -0
  341. package/dist/search/CommandPalette.svelte +257 -0
  342. package/dist/search/CommandPalette.svelte.d.ts +59 -0
  343. package/dist/search/index.d.ts +13 -0
  344. package/dist/search/index.js +13 -0
  345. package/dist/search/types.d.ts +40 -0
  346. package/dist/search/types.js +20 -0
  347. package/dist/seo/Head.svelte +190 -0
  348. package/dist/seo/Head.svelte.d.ts +86 -0
  349. package/dist/seo/JsonLd.svelte +30 -0
  350. package/dist/seo/JsonLd.svelte.d.ts +20 -0
  351. package/dist/seo/index.d.ts +18 -0
  352. package/dist/seo/index.js +17 -0
  353. package/dist/seo/json-ld.d.ts +33 -0
  354. package/dist/seo/json-ld.js +29 -0
  355. package/dist/seo/og-image.d.ts +72 -0
  356. package/dist/seo/og-image.js +82 -0
  357. package/dist/seo/types.d.ts +43 -0
  358. package/dist/seo/types.js +6 -0
  359. package/dist/theme.css +161 -0
  360. package/dist/tips/PopoverTip.svelte +80 -0
  361. package/dist/tips/PopoverTip.svelte.d.ts +33 -0
  362. package/dist/tips/Tip.svelte +91 -0
  363. package/dist/tips/Tip.svelte.d.ts +25 -0
  364. package/dist/tips/index.d.ts +15 -0
  365. package/dist/tips/index.js +14 -0
  366. package/dist/tips/tip-stack.d.ts +26 -0
  367. package/dist/tips/tip-stack.js +37 -0
  368. package/dist/tips/tip-store.svelte.d.ts +75 -0
  369. package/dist/tips/tip-store.svelte.js +158 -0
  370. package/dist/tips/types.d.ts +46 -0
  371. package/dist/tips/types.js +6 -0
  372. package/dist/ui/Accordion.svelte +75 -0
  373. package/dist/ui/Accordion.svelte.d.ts +50 -0
  374. package/dist/ui/AccordionItem.svelte +73 -0
  375. package/dist/ui/AccordionItem.svelte.d.ts +18 -0
  376. package/dist/ui/Alert.svelte +61 -0
  377. package/dist/ui/Alert.svelte.d.ts +37 -0
  378. package/dist/ui/Badge.svelte +39 -0
  379. package/dist/ui/Badge.svelte.d.ts +32 -0
  380. package/dist/ui/Button.svelte +44 -0
  381. package/dist/ui/Button.svelte.d.ts +29 -0
  382. package/dist/ui/ButtonGroup.svelte +24 -0
  383. package/dist/ui/ButtonGroup.svelte.d.ts +17 -0
  384. package/dist/ui/Card.svelte +49 -0
  385. package/dist/ui/Card.svelte.d.ts +44 -0
  386. package/dist/ui/Chip.svelte +58 -0
  387. package/dist/ui/Chip.svelte.d.ts +21 -0
  388. package/dist/ui/ConfirmButton.svelte +75 -0
  389. package/dist/ui/ConfirmButton.svelte.d.ts +48 -0
  390. package/dist/ui/ContextMenu.svelte +75 -0
  391. package/dist/ui/ContextMenu.svelte.d.ts +25 -0
  392. package/dist/ui/Disclosure.svelte +46 -0
  393. package/dist/ui/Disclosure.svelte.d.ts +22 -0
  394. package/dist/ui/Divider.svelte +47 -0
  395. package/dist/ui/Divider.svelte.d.ts +28 -0
  396. package/dist/ui/DropdownMenu.svelte +44 -0
  397. package/dist/ui/DropdownMenu.svelte.d.ts +30 -0
  398. package/dist/ui/EmptyState.svelte +37 -0
  399. package/dist/ui/EmptyState.svelte.d.ts +22 -0
  400. package/dist/ui/ExternalLink.svelte +38 -0
  401. package/dist/ui/ExternalLink.svelte.d.ts +34 -0
  402. package/dist/ui/Heading.svelte +58 -0
  403. package/dist/ui/Heading.svelte.d.ts +22 -0
  404. package/dist/ui/Link.svelte +34 -0
  405. package/dist/ui/Link.svelte.d.ts +20 -0
  406. package/dist/ui/LinkButton.svelte +51 -0
  407. package/dist/ui/LinkButton.svelte.d.ts +33 -0
  408. package/dist/ui/Menu.svelte +24 -0
  409. package/dist/ui/Menu.svelte.d.ts +13 -0
  410. package/dist/ui/MenuCheckboxItem.svelte +33 -0
  411. package/dist/ui/MenuCheckboxItem.svelte.d.ts +20 -0
  412. package/dist/ui/MenuItem.svelte +73 -0
  413. package/dist/ui/MenuItem.svelte.d.ts +21 -0
  414. package/dist/ui/MenuRadioGroup.svelte +25 -0
  415. package/dist/ui/MenuRadioGroup.svelte.d.ts +20 -0
  416. package/dist/ui/MenuRadioItem.svelte +20 -0
  417. package/dist/ui/MenuRadioItem.svelte.d.ts +15 -0
  418. package/dist/ui/MenuSeparator.svelte +27 -0
  419. package/dist/ui/MenuSeparator.svelte.d.ts +8 -0
  420. package/dist/ui/MenuSub.svelte +24 -0
  421. package/dist/ui/MenuSub.svelte.d.ts +15 -0
  422. package/dist/ui/Popover.svelte +63 -0
  423. package/dist/ui/Popover.svelte.d.ts +40 -0
  424. package/dist/ui/ShareButton.svelte +64 -0
  425. package/dist/ui/ShareButton.svelte.d.ts +39 -0
  426. package/dist/ui/Skeleton.svelte +43 -0
  427. package/dist/ui/Skeleton.svelte.d.ts +22 -0
  428. package/dist/ui/Spinner.svelte +41 -0
  429. package/dist/ui/Spinner.svelte.d.ts +35 -0
  430. package/dist/ui/Stack.svelte +36 -0
  431. package/dist/ui/Stack.svelte.d.ts +48 -0
  432. package/dist/ui/ThemeToggle.svelte +65 -0
  433. package/dist/ui/ThemeToggle.svelte.d.ts +24 -0
  434. package/dist/ui/ToggleButton.svelte +58 -0
  435. package/dist/ui/ToggleButton.svelte.d.ts +45 -0
  436. package/dist/ui/ToggleGroup.svelte +142 -0
  437. package/dist/ui/ToggleGroup.svelte.d.ts +86 -0
  438. package/dist/ui/Toolbar.svelte +40 -0
  439. package/dist/ui/Toolbar.svelte.d.ts +20 -0
  440. package/dist/ui/ToolbarButton.svelte +29 -0
  441. package/dist/ui/ToolbarButton.svelte.d.ts +21 -0
  442. package/dist/ui/ToolbarLink.svelte +21 -0
  443. package/dist/ui/ToolbarLink.svelte.d.ts +12 -0
  444. package/dist/ui/ToolbarSeparator.svelte +22 -0
  445. package/dist/ui/ToolbarSeparator.svelte.d.ts +12 -0
  446. package/dist/ui/ToolbarToggleGroup.svelte +66 -0
  447. package/dist/ui/ToolbarToggleGroup.svelte.d.ts +52 -0
  448. package/dist/ui/Tooltip.svelte +54 -0
  449. package/dist/ui/Tooltip.svelte.d.ts +35 -0
  450. package/dist/ui/VisuallyHidden.svelte +23 -0
  451. package/dist/ui/VisuallyHidden.svelte.d.ts +10 -0
  452. package/dist/ui/accordion-context.d.ts +26 -0
  453. package/dist/ui/accordion-context.js +23 -0
  454. package/dist/ui/colour-token.d.ts +41 -0
  455. package/dist/ui/colour-token.js +49 -0
  456. package/dist/ui/context-menu.d.ts +13 -0
  457. package/dist/ui/context-menu.js +13 -0
  458. package/dist/ui/index.d.ts +63 -0
  459. package/dist/ui/index.js +62 -0
  460. package/dist/ui/menu-context.d.ts +20 -0
  461. package/dist/ui/menu-context.js +22 -0
  462. package/dist/ui/menu-parts/CheckboxItemPart.svelte +26 -0
  463. package/dist/ui/menu-parts/CheckboxItemPart.svelte.d.ts +5 -0
  464. package/dist/ui/menu-parts/ItemPart.svelte +29 -0
  465. package/dist/ui/menu-parts/ItemPart.svelte.d.ts +5 -0
  466. package/dist/ui/menu-parts/RadioGroupPart.svelte +24 -0
  467. package/dist/ui/menu-parts/RadioGroupPart.svelte.d.ts +5 -0
  468. package/dist/ui/menu-parts/RadioItemPart.svelte +22 -0
  469. package/dist/ui/menu-parts/RadioItemPart.svelte.d.ts +5 -0
  470. package/dist/ui/menu-parts/SeparatorPart.svelte +16 -0
  471. package/dist/ui/menu-parts/SeparatorPart.svelte.d.ts +5 -0
  472. package/dist/ui/menu-parts/SubPart.svelte +28 -0
  473. package/dist/ui/menu-parts/SubPart.svelte.d.ts +5 -0
  474. package/dist/ui/menu-parts/menu-parts.d.ts +104 -0
  475. package/dist/ui/menu-parts/menu-parts.js +31 -0
  476. package/dist/ui/menu-parts/parts.d.ts +12 -0
  477. package/dist/ui/menu-parts/parts.js +27 -0
  478. package/dist/ui/slug.d.ts +19 -0
  479. package/dist/ui/slug.js +25 -0
  480. package/dist/ui/toggle-classes.d.ts +39 -0
  481. package/dist/ui/toggle-classes.js +36 -0
  482. package/dist/ui/tones.d.ts +103 -0
  483. package/dist/ui/tones.js +240 -0
  484. package/package.json +41 -25
@@ -0,0 +1,35 @@
1
+ <!-- @component
2
+ A `<data>` element whose text is the `Intl.NumberFormat` rendering and whose `value` attribute keeps the raw number.
3
+ -->
4
+ <!--
5
+ NumberFormat — a `<data>` element whose text is `Intl.NumberFormat`'s
6
+ rendering and whose `value` attribute is the raw number/bigint, so the
7
+ machine-readable figure survives locale formatting.
8
+
9
+ Exported as `NumberFormat` (not `Number`) to avoid shadowing the global.
10
+
11
+ ARIA contract: none beyond native `<data>` semantics — `value` carries the
12
+ machine-readable figure, the rendered text carries the locale-formatted one.
13
+ -->
14
+ <script lang="ts">import { getComponentsContext } from "../context.svelte.js";
15
+ let { value, locales = getComponentsContext().locale(), style = "decimal", unit, unitDisplay = "short", currency, currencyDisplay = "symbol", maximumFractionDigits, minimumFractionDigits, signDisplay, notation, options, ...rest } = $props();
16
+ // The formatter and the formatted string are separate `$derived` values so
17
+ // constructing the (relatively expensive) `Intl.NumberFormat` is skipped
18
+ // when only `value` changes. See PERF-CPU-003 in
19
+ // docs/specs/performance-invariants.md.
20
+ const format = $derived(new Intl.NumberFormat(locales, options ?? {
21
+ style,
22
+ unit,
23
+ unitDisplay,
24
+ currency,
25
+ currencyDisplay,
26
+ maximumFractionDigits,
27
+ minimumFractionDigits,
28
+ signDisplay,
29
+ notation
30
+ }));
31
+ const formatted = $derived(format.format(value));
32
+ const raw = $derived(String(value));
33
+ </script>
34
+
35
+ <data {...rest} value={raw}>{formatted}</data>
@@ -0,0 +1,43 @@
1
+ import type { HTMLDataAttributes } from 'svelte/elements';
2
+ interface Props extends Omit<HTMLDataAttributes, 'value'> {
3
+ /** The number to format; the raw value also goes in the `value` attribute. */
4
+ value: number | bigint;
5
+ /**
6
+ * Locale(s) for `Intl` formatting.
7
+ * @defaultValue the components context's `locale()`
8
+ */
9
+ locales?: string | readonly string[] | undefined;
10
+ /**
11
+ * `Intl.NumberFormat` `style`.
12
+ * @defaultValue `'decimal'`
13
+ */
14
+ style?: Intl.NumberFormatOptions['style'] | undefined;
15
+ /** The unit when `style` is `unit` (`kilometer`, `percent`). */
16
+ unit?: string | undefined;
17
+ /**
18
+ * `Intl.NumberFormat` `unitDisplay`.
19
+ * @defaultValue `'short'`
20
+ */
21
+ unitDisplay?: Intl.NumberFormatOptions['unitDisplay'] | undefined;
22
+ /** ISO 4217 code when `style` is `currency`. */
23
+ currency?: string | undefined;
24
+ /**
25
+ * `Intl.NumberFormat` `currencyDisplay`.
26
+ * @defaultValue `'symbol'`
27
+ */
28
+ currencyDisplay?: Intl.NumberFormatOptions['currencyDisplay'] | undefined;
29
+ /** `Intl.NumberFormat` `maximumFractionDigits`. */
30
+ maximumFractionDigits?: number | undefined;
31
+ /** `Intl.NumberFormat` `minimumFractionDigits`. */
32
+ minimumFractionDigits?: number | undefined;
33
+ /** `Intl.NumberFormat` `signDisplay`. */
34
+ signDisplay?: Intl.NumberFormatOptions['signDisplay'] | undefined;
35
+ /** `Intl.NumberFormat` `notation`. */
36
+ notation?: Intl.NumberFormatOptions['notation'] | undefined;
37
+ /** Raw `Intl.NumberFormatOptions`; wins over the individual style props when given. */
38
+ options?: Intl.NumberFormatOptions | undefined;
39
+ }
40
+ /** A `<data>` element whose text is the `Intl.NumberFormat` rendering and whose `value` attribute keeps the raw number. */
41
+ declare const Number: import("svelte").Component<Props, {}, "">;
42
+ type Number = ReturnType<typeof Number>;
43
+ export default Number;
@@ -0,0 +1,69 @@
1
+ <!-- @component
2
+ "3 days ago" / "in 2 hours" via `Intl.RelativeTimeFormat`, in the largest unit whose magnitude is at least one.
3
+ -->
4
+ <!--
5
+ RelativeTime — "3 days ago" / "in 2 hours" via `Intl.RelativeTimeFormat`,
6
+ picking the largest unit (seconds → years) whose magnitude is at least one.
7
+
8
+ ARIA contract: none beyond native `<time>` semantics. The absolute instant
9
+ is never hidden — it is both the machine-readable `datetime` and the
10
+ human-readable `title`, so a reader who hovers (or a tool that reads
11
+ `title`) gets the precise moment the relative text is glossing over.
12
+ -->
13
+ <script lang="ts">import { getComponentsContext } from "../context.svelte.js";
14
+ let { value, now, locales = getComponentsContext().locale(), numeric = "auto", style = "long", ...rest } = $props();
15
+ const UNITS = [
16
+ {
17
+ unit: "year",
18
+ ms: 365.25 * 24 * 60 * 60 * 1e3
19
+ },
20
+ {
21
+ unit: "month",
22
+ ms: 30.44 * 24 * 60 * 60 * 1e3
23
+ },
24
+ {
25
+ unit: "week",
26
+ ms: 7 * 24 * 60 * 60 * 1e3
27
+ },
28
+ {
29
+ unit: "day",
30
+ ms: 24 * 60 * 60 * 1e3
31
+ },
32
+ {
33
+ unit: "hour",
34
+ ms: 60 * 60 * 1e3
35
+ },
36
+ {
37
+ unit: "minute",
38
+ ms: 60 * 1e3
39
+ },
40
+ {
41
+ unit: "second",
42
+ ms: 1e3
43
+ }
44
+ ];
45
+ const instant = $derived(new Date(value));
46
+ const reference = $derived(new Date(now ?? Date.now()));
47
+ const diffMs = $derived(instant.getTime() - reference.getTime());
48
+ // Largest unit whose magnitude rounds to at least one; falls back to
49
+ // seconds for anything smaller (e.g. "0 seconds ago" / "in 0 seconds").
50
+ const picked = $derived(UNITS.find((candidate) => Math.abs(diffMs) >= candidate.ms) ?? UNITS[UNITS.length - 1]);
51
+ const roundedValue = $derived(Math.round(diffMs / picked.ms));
52
+ // The formatter and the formatted string are separate `$derived` values so
53
+ // constructing the (relatively expensive) `Intl.RelativeTimeFormat` is
54
+ // skipped when only `value`/`now` change. See PERF-CPU-003 in
55
+ // docs/specs/performance-invariants.md.
56
+ const format = $derived(new Intl.RelativeTimeFormat(locales, {
57
+ numeric,
58
+ style
59
+ }));
60
+ const formatted = $derived(format.format(roundedValue, picked.unit));
61
+ const iso = $derived(instant.toISOString());
62
+ const absoluteFormat = $derived(new Intl.DateTimeFormat(locales, {
63
+ dateStyle: "full",
64
+ timeStyle: "short"
65
+ }));
66
+ const absolute = $derived(absoluteFormat.format(instant));
67
+ </script>
68
+
69
+ <time {...rest} datetime={iso} title={absolute}>{formatted}</time>
@@ -0,0 +1,26 @@
1
+ import type { HTMLTimeAttributes } from 'svelte/elements';
2
+ interface Props extends HTMLTimeAttributes {
3
+ /** The instant: a `Date`, epoch milliseconds or an ISO string. */
4
+ value: Date | number | string;
5
+ /** The instant "now" is measured from; defaults to the current wall clock at render. */
6
+ now?: Date | number | undefined;
7
+ /**
8
+ * Locale(s) for `Intl` formatting.
9
+ * @defaultValue the components context's `locale()`
10
+ */
11
+ locales?: string | readonly string[] | undefined;
12
+ /**
13
+ * `Intl.RelativeTimeFormat` `numeric`; `auto` allows "yesterday".
14
+ * @defaultValue `'auto'`
15
+ */
16
+ numeric?: Intl.RelativeTimeFormatOptions['numeric'] | undefined;
17
+ /**
18
+ * `Intl.RelativeTimeFormat` `style`.
19
+ * @defaultValue `'long'`
20
+ */
21
+ style?: Intl.RelativeTimeFormatOptions['style'] | undefined;
22
+ }
23
+ /** "3 days ago" / "in 2 hours" via `Intl.RelativeTimeFormat`, in the largest unit whose magnitude is at least one. */
24
+ declare const RelativeTime: import("svelte").Component<Props, {}, "">;
25
+ type RelativeTime = ReturnType<typeof RelativeTime>;
26
+ export default RelativeTime;
@@ -0,0 +1,39 @@
1
+ <!-- @component
2
+ A `<time>` element carrying just a year, for dates whose precision really is a year.
3
+ -->
4
+ <!--
5
+ Year — a `<time>` element carrying just a year: `datetime="1925"`, and
6
+ `Intl.DateTimeFormat`'s locale rendering of the year (with its era, when
7
+ asked) as the text. For publication dates, lifespans and anything else whose
8
+ precision really is a year.
9
+
10
+ ARIA contract: none beyond the native `<time>` semantics. `datetime` is a
11
+ valid HTML year string (four or more digits), so the value stays
12
+ machine-readable at the precision it actually has rather than claiming a
13
+ midnight-on-1-January instant.
14
+
15
+ A `number` is a CALENDAR YEAR (`1925`), not an epoch timestamp — that is
16
+ what a caller holding "the year" has. A `Date` or string is read as an
17
+ instant and its UTC year is taken, so a date at midnight UTC never renders
18
+ as the previous year in a timezone west of Greenwich. Years before 1 CE have
19
+ no HTML year string, so for those `datetime` falls back to the ISO instant.
20
+ -->
21
+ <script lang="ts">import { getComponentsContext } from "../context.svelte.js";
22
+ let { value, locales = getComponentsContext().locale(), era, representation = "numeric", ...rest } = $props();
23
+ const instant = $derived.by(() => {
24
+ if (typeof value !== "number") return new Date(value);
25
+ const date = new Date(Date.UTC(2e3, 0, 1));
26
+ date.setUTCFullYear(value);
27
+ return date;
28
+ });
29
+ const format = $derived(new Intl.DateTimeFormat(locales, {
30
+ year: representation,
31
+ era,
32
+ timeZone: "UTC"
33
+ }));
34
+ const formatted = $derived(format.format(instant));
35
+ const year = $derived(instant.getUTCFullYear());
36
+ const datetime = $derived(year >= 1 ? String(year).padStart(4, "0") : instant.toISOString());
37
+ </script>
38
+
39
+ <time {...rest} {datetime}>{formatted}</time>
@@ -0,0 +1,21 @@
1
+ import type { HTMLTimeAttributes } from 'svelte/elements';
2
+ interface Props extends HTMLTimeAttributes {
3
+ /** A calendar year, or an instant (its UTC year is used). */
4
+ value: Date | number | string;
5
+ /**
6
+ * Locale(s) for `Intl` formatting.
7
+ * @defaultValue the components context's `locale()`
8
+ */
9
+ locales?: string | readonly string[] | undefined;
10
+ /** Append the era: `1925 AD`. */
11
+ era?: Intl.DateTimeFormatOptions['era'] | undefined;
12
+ /**
13
+ * Four digits or two.
14
+ * @defaultValue `'numeric'`
15
+ */
16
+ representation?: 'numeric' | '2-digit' | undefined;
17
+ }
18
+ /** A `<time>` element carrying just a year, for dates whose precision really is a year. */
19
+ declare const Year: import("svelte").Component<Props, {}, "">;
20
+ type Year = ReturnType<typeof Year>;
21
+ export default Year;
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Lengths of time: the value type, its ISO 8601 form for `<time datetime>`,
3
+ * and a locale-aware formatter that `Duration` and `Countdown` share and an
4
+ * app can call in plain TypeScript.
5
+ *
6
+ * `formatDuration` uses `Intl.DurationFormat` where the runtime has it
7
+ * (Baseline 2025) and otherwise composes per-unit `Intl.NumberFormat` unit
8
+ * strings with an `Intl.ListFormat` of `type: 'unit'`, so the fallback is
9
+ * still localised, just less idiomatic.
10
+ *
11
+ * @module
12
+ */
13
+ /** A length of time; any subset of fields. Mirrors `Intl.DurationFormat`'s input. */
14
+ export interface DurationValue {
15
+ readonly years?: number | undefined;
16
+ readonly months?: number | undefined;
17
+ readonly weeks?: number | undefined;
18
+ readonly days?: number | undefined;
19
+ readonly hours?: number | undefined;
20
+ readonly minutes?: number | undefined;
21
+ readonly seconds?: number | undefined;
22
+ readonly milliseconds?: number | undefined;
23
+ }
24
+ /** How a duration is spelled: `'2 hours, 30 minutes'`, `'2 hr, 30 min'`, `'2h 30m'` or `'2:30:00'`. */
25
+ export type DurationStyle = 'long' | 'short' | 'narrow' | 'digital';
26
+ /**
27
+ * Split milliseconds into days, hours, minutes, seconds and milliseconds,
28
+ * leaving out the zero fields (`9_309_000` → `{ hours: 2, minutes: 35,
29
+ * seconds: 9 }`). Days are the largest unit: months and years have no fixed
30
+ * length. Negative input is treated as zero.
31
+ */
32
+ export declare function durationFromMilliseconds(ms: number): DurationValue;
33
+ /**
34
+ * The ISO 8601 duration string for `<time datetime>`: `{ hours: 2,
35
+ * minutes: 30 }` → `'PT2H30M'`. Milliseconds join the seconds as a
36
+ * fraction; an empty duration is `'PT0S'`.
37
+ */
38
+ export declare function toIsoDuration(value: DurationValue): string;
39
+ /**
40
+ * Format a duration for `locales` in `style`, through `Intl.DurationFormat`
41
+ * where available and a localised `NumberFormat` + `ListFormat` composition
42
+ * otherwise.
43
+ */
44
+ export declare function formatDuration(value: DurationValue, locales?: string | readonly string[], style?: DurationStyle): string;
@@ -0,0 +1,125 @@
1
+ /**
2
+ * Lengths of time: the value type, its ISO 8601 form for `<time datetime>`,
3
+ * and a locale-aware formatter that `Duration` and `Countdown` share and an
4
+ * app can call in plain TypeScript.
5
+ *
6
+ * `formatDuration` uses `Intl.DurationFormat` where the runtime has it
7
+ * (Baseline 2025) and otherwise composes per-unit `Intl.NumberFormat` unit
8
+ * strings with an `Intl.ListFormat` of `type: 'unit'`, so the fallback is
9
+ * still localised, just less idiomatic.
10
+ *
11
+ * @module
12
+ */
13
+ /** The fields, largest first, with the `Intl` unit each formats as. */
14
+ const FIELDS = [
15
+ { field: 'years', unit: 'year' },
16
+ { field: 'months', unit: 'month' },
17
+ { field: 'weeks', unit: 'week' },
18
+ { field: 'days', unit: 'day' },
19
+ { field: 'hours', unit: 'hour' },
20
+ { field: 'minutes', unit: 'minute' },
21
+ { field: 'seconds', unit: 'second' },
22
+ { field: 'milliseconds', unit: 'millisecond' },
23
+ ];
24
+ const SECOND = 1000;
25
+ const MINUTE = 60 * SECOND;
26
+ const HOUR = 60 * MINUTE;
27
+ const DAY = 24 * HOUR;
28
+ /**
29
+ * Split milliseconds into days, hours, minutes, seconds and milliseconds,
30
+ * leaving out the zero fields (`9_309_000` → `{ hours: 2, minutes: 35,
31
+ * seconds: 9 }`). Days are the largest unit: months and years have no fixed
32
+ * length. Negative input is treated as zero.
33
+ */
34
+ export function durationFromMilliseconds(ms) {
35
+ let rest = Math.max(0, Math.round(ms));
36
+ const parts = {};
37
+ for (const [field, size] of [
38
+ ['days', DAY],
39
+ ['hours', HOUR],
40
+ ['minutes', MINUTE],
41
+ ['seconds', SECOND],
42
+ ['milliseconds', 1],
43
+ ]) {
44
+ const count = Math.floor(rest / size);
45
+ rest -= count * size;
46
+ if (count > 0)
47
+ parts[field] = count;
48
+ }
49
+ return parts;
50
+ }
51
+ /**
52
+ * The ISO 8601 duration string for `<time datetime>`: `{ hours: 2,
53
+ * minutes: 30 }` → `'PT2H30M'`. Milliseconds join the seconds as a
54
+ * fraction; an empty duration is `'PT0S'`.
55
+ */
56
+ export function toIsoDuration(value) {
57
+ const amount = (field) => value[field] ?? 0;
58
+ const date = [
59
+ amount('years') > 0 ? `${amount('years')}Y` : '',
60
+ amount('months') > 0 ? `${amount('months')}M` : '',
61
+ amount('weeks') > 0 ? `${amount('weeks')}W` : '',
62
+ amount('days') > 0 ? `${amount('days')}D` : '',
63
+ ].join('');
64
+ const seconds = amount('seconds') + amount('milliseconds') / 1000;
65
+ const time = [
66
+ amount('hours') > 0 ? `${amount('hours')}H` : '',
67
+ amount('minutes') > 0 ? `${amount('minutes')}M` : '',
68
+ seconds > 0 ? `${Number(seconds.toFixed(3))}S` : '',
69
+ ].join('');
70
+ if (date === '' && time === '')
71
+ return 'PT0S';
72
+ return `P${date}${time === '' ? '' : `T${time}`}`;
73
+ }
74
+ /** `Intl.DurationFormat` when the runtime has it. */
75
+ function nativeDurationFormat() {
76
+ const intl = Intl;
77
+ return intl.DurationFormat;
78
+ }
79
+ /** `value` with the `undefined` and zero fields dropped, as `Intl.DurationFormat` wants. */
80
+ function presentFields(value) {
81
+ return Object.fromEntries(FIELDS.filter(({ field }) => (value[field] ?? 0) !== 0).map(({ field }) => [
82
+ field,
83
+ value[field],
84
+ ]));
85
+ }
86
+ /** `H:MM:SS` from the hours, minutes and seconds, the larger units folded into hours. */
87
+ function digital(value) {
88
+ const hours = (value.days ?? 0) * 24 + (value.hours ?? 0);
89
+ const pad = (n) => String(n).padStart(2, '0');
90
+ return `${hours}:${pad(value.minutes ?? 0)}:${pad(value.seconds ?? 0)}`;
91
+ }
92
+ /**
93
+ * Format a duration for `locales` in `style`, through `Intl.DurationFormat`
94
+ * where available and a localised `NumberFormat` + `ListFormat` composition
95
+ * otherwise.
96
+ */
97
+ export function formatDuration(value, locales, style = 'short') {
98
+ const present = presentFields(value);
99
+ const Native = nativeDurationFormat();
100
+ if (Native !== undefined) {
101
+ return new Native(locales, { style }).format(present);
102
+ }
103
+ if (style === 'digital')
104
+ return digital(value);
105
+ const unitDisplay = style;
106
+ // A mutable copy: TS6's `Intl.ListFormat` (svelte-check) takes no readonly array.
107
+ const tags = typeof locales === 'object' ? [...locales] : locales;
108
+ const pieces = FIELDS.filter(({ field }) => present[field] !== undefined).map(({ field, unit }) => new Intl.NumberFormat(tags, {
109
+ style: 'unit',
110
+ unit,
111
+ unitDisplay,
112
+ }).format(present[field] ?? 0));
113
+ return new Intl.ListFormat(tags, {
114
+ type: 'unit',
115
+ style: style === 'long' ? 'long' : style === 'short' ? 'short' : 'narrow',
116
+ }).format(pieces.length === 0
117
+ ? [
118
+ new Intl.NumberFormat(tags, {
119
+ style: 'unit',
120
+ unit: 'second',
121
+ unitDisplay,
122
+ }).format(0),
123
+ ]
124
+ : pieces);
125
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * formatting — locale-aware rendering of dates, numbers, lists and search
3
+ * highlights. See the package README for the family reference.
4
+ *
5
+ * @module
6
+ */
7
+ export { default as Countdown } from './Countdown.svelte';
8
+ export { default as DateTime } from './DateTime.svelte';
9
+ export { default as Duration } from './Duration.svelte';
10
+ export * from './duration.ts';
11
+ export { default as NumberFormat } from './Number.svelte';
12
+ export { default as FormatList } from './FormatList.svelte';
13
+ export { default as RelativeTime } from './RelativeTime.svelte';
14
+ export { default as Year } from './Year.svelte';
15
+ export { default as Highlight, tokenise } from './Highlight.svelte';
@@ -0,0 +1,17 @@
1
+ /**
2
+ * formatting — locale-aware rendering of dates, numbers, lists and search
3
+ * highlights. See the package README for the family reference.
4
+ *
5
+ * @module
6
+ */
7
+ export { default as Countdown } from './Countdown.svelte';
8
+ export { default as DateTime } from './DateTime.svelte';
9
+ export { default as Duration } from './Duration.svelte';
10
+ export * from "./duration.js";
11
+ // `NumberFormat`, not `Number`: a named export called `Number` would shadow
12
+ // the global constructor for anyone importing it by that name.
13
+ export { default as NumberFormat } from './Number.svelte';
14
+ export { default as FormatList } from './FormatList.svelte';
15
+ export { default as RelativeTime } from './RelativeTime.svelte';
16
+ export { default as Year } from './Year.svelte';
17
+ export { default as Highlight, tokenise } from './Highlight.svelte';
@@ -0,0 +1,185 @@
1
+ <!-- @component
2
+ Renders an `@thomasfosterau/effect-forms-svelte` `defineEntityForm` definition through this library’s field primitives.
3
+ -->
4
+ <!--
5
+ EntityForm — the generic renderer for an `@thomasfosterau/effect-forms-svelte`
6
+ `defineEntityForm` definition: it walks `definition.entriesFor(mode)` and
7
+ renders each entry through this library's field primitives —
8
+ `FormField` + `TextInput` / `DateInput` / `Textarea` / `Select` for scalars
9
+ and selects, and the entry's own component for a bespoke widget (a picker,
10
+ a contributor list), bridged through the widget contract below.
11
+
12
+ The one component of this package that touches Effect, which is why it is a
13
+ separate entry point (`@thomasfosterau/components/entity-form`) with
14
+ `@thomasfosterau/effect-forms-svelte` an OPTIONAL peer: a consumer that
15
+ never imports this entry never installs the form library or `effect`. The
16
+ renderer itself imports only the store (`createForm`) and types.
17
+
18
+ **Seeding.** `definition`, `mode`, `initial` and `initialRows` configure the
19
+ store ONCE, at mount: a form never changes entity or mode mid-flight, and an
20
+ edit page's values must land in the SSR HTML. There is no `$effect`
21
+ re-seeding, so a value typed before hydration is never wiped by a late seed.
22
+ A create form whose command carries a client id gets one minted here, once
23
+ per mount, so a retried submission stays idempotent.
24
+
25
+ **The widget contract.** A widget entry receives, in this order: its
26
+ definition's `props()`, then the caller's `fieldProps[key]`, then the bridge
27
+ — `name`, `value`, `onChange`, `errors`. The bridge is spread LAST, so
28
+ neither of the first two can sever the store binding. A `value` widget
29
+ bridges a string field of the store; a `rows` widget bridges a row list held
30
+ here and serialises it itself (its own hidden input).
31
+
32
+ **Submission.** `enhance(form)` supplies the spreadable `<form>` attributes.
33
+ It defaults to the store's own `form.props` (POST + its progressive
34
+ enhancement); a SvelteKit app passes its `$app/forms`-backed `enhanceForm`,
35
+ which this package cannot import.
36
+
37
+ **Form-level messages.** The store's root errors and the caller's
38
+ `messages` (a failure the store never saw, such as a server action's
39
+ `fail(500, { message })`) share one `FormErrors` block, store errors first.
40
+
41
+ Every string that is not the definition's own (labels, submit labels and
42
+ option labels are its message thunks) is a prop with an English default.
43
+ -->
44
+ <script lang="ts">import { createForm } from "@thomasfosterau/effect-forms-svelte";
45
+ import DateInput from "../fields/DateInput.svelte";
46
+ import FormField from "../fields/FormField.svelte";
47
+ import Select from "../fields/Select.svelte";
48
+ import TextInput from "../fields/TextInput.svelte";
49
+ import Textarea from "../fields/Textarea.svelte";
50
+ import FormActions from "./FormActions.svelte";
51
+ import FormErrors from "./FormErrors.svelte";
52
+ let { definition, mode, cancelHref, action, initial = {}, initialRows = {}, fieldProps = {}, enhance = (form) => form.props, cancelLabel = "Cancel", pendingLabel = "Saving…", selectPlaceholder = "Choose…", requiredLabel, messages, class: className, ...rest } = $props();
53
+ // Configure-once, at mount (see the header): these reads are deliberately
54
+ // not reactive.
55
+ // svelte-ignore state_referenced_locally
56
+ const configured = {
57
+ definition,
58
+ mode,
59
+ initial,
60
+ initialRows
61
+ };
62
+ const baseDefaults = configured.mode === "create" ? configured.definition.createDefaults : configured.definition.updateDefaults;
63
+ const mintedId = configured.mode === "create" && configured.definition.clientId ? { id: crypto.randomUUID() } : undefined;
64
+ const defaults = {
65
+ ...baseDefaults,
66
+ ...configured.initial,
67
+ ...mintedId
68
+ };
69
+ const form = createForm({
70
+ schema: configured.mode === "create" ? configured.definition.createInput : configured.definition.updateInput,
71
+ defaults
72
+ });
73
+ const entries = configured.definition.entriesFor(configured.mode);
74
+ // SAFETY: `defineEntityForm` validated every entry key against the derived
75
+ // all-string input schema. The definition types that schema `Schema.Top`,
76
+ // whose path-typed accessor admits no key (`never`), so the key is asserted
77
+ // into it and the handle typed by this function's own return type.
78
+ const handle = (key) => form.field(key);
79
+ const getField = (key) => handle(key).value ?? "";
80
+ const setField = (key, next) => {
81
+ handle(key).value = next;
82
+ };
83
+ let rows = $state(Object.fromEntries(entries.filter((entry) => entry._tag === "widget" && entry.bridge === "rows").map((entry) => [entry.key, [...configured.initialRows[entry.key] ?? []]])));
84
+ const bridge = (entry) => entry.bridge === "rows" ? {
85
+ name: entry.key,
86
+ value: rows[entry.key] ?? [],
87
+ onChange: (next) => {
88
+ rows[entry.key] = next;
89
+ },
90
+ errors: handle(entry.key).visibleErrors
91
+ } : {
92
+ name: entry.key,
93
+ value: getField(entry.key),
94
+ onChange: (next) => setField(entry.key, next),
95
+ errors: handle(entry.key).visibleErrors
96
+ };
97
+ const selectOptions = (entry) => (configured.definition.fieldFor(entry.key).options ?? []).map((value) => ({
98
+ value,
99
+ label: entry.options.optionLabels[value]?.() ?? value
100
+ }));
101
+ const inputMode = (entry) => entry.options.inputmode ?? (configured.definition.fieldFor(entry.key).kind === "number" ? "numeric" : undefined);
102
+ const showHiddenId = configured.mode === "update" || configured.definition.clientId;
103
+ const submitLabel = $derived(mode === "create" ? definition.submit.create() : definition.submit.update());
104
+ const gated = $derived(entries.some((entry) => entry._tag === "widget" && entry.options.gate === true && getField(entry.key) === ""));
105
+ // The empty path is the form's own (non-field) messages.
106
+ // The caller's `messages` (a server fault with no form state) follow them.
107
+ const rootErrors = $derived([...form.errorsAt([]), ...messages ?? []]);
108
+ const fieldId = (key) => `entity-form-${key}`;
109
+ // The `FormField` wrapper is the same for a select and a scalar entry.
110
+ const fieldAttrs = (entry) => ({
111
+ id: fieldId(entry.key),
112
+ label: entry.options.label(),
113
+ required: entry.options.required === true,
114
+ errors: handle(entry.key).visibleErrors,
115
+ requiredLabel
116
+ });
117
+ </script>
118
+
119
+ <!-- A scalar entry's control: a textarea, a date input or a text input. -->
120
+ {#snippet scalarInput(entry: ScalarEntry, control: FieldControl)}
121
+ {#if entry.multiline}
122
+ <Textarea
123
+ {...control}
124
+ name={entry.key}
125
+ placeholder={entry.options.placeholder?.()}
126
+ bind:value={() => getField(entry.key), (next: string) => setField(entry.key, next)}
127
+ />
128
+ {:else if entry.options.type === 'date'}
129
+ <DateInput
130
+ {...control}
131
+ name={entry.key}
132
+ bind:value={() => getField(entry.key), (next: string) => setField(entry.key, next)}
133
+ />
134
+ {:else}
135
+ <TextInput
136
+ {...control}
137
+ name={entry.key}
138
+ type={entry.options.type === 'url' ? 'url' : 'text'}
139
+ inputmode={inputMode(entry)}
140
+ placeholder={entry.options.placeholder?.()}
141
+ bind:value={() => getField(entry.key), (next: string) => setField(entry.key, next)}
142
+ />
143
+ {/if}
144
+ {/snippet}
145
+
146
+ <form {...rest} {...enhance(form)} {action} class={['space-y-4', className]}>
147
+ {#if showHiddenId}
148
+ <input type="hidden" name="id" value={getField('id')} />
149
+ {/if}
150
+
151
+ <FormErrors messages={rootErrors} />
152
+
153
+ {#each entries as entry (entry.key)}
154
+ {#if entry._tag === 'widget'}
155
+ <entry.component {...entry.props()} {...fieldProps[entry.key] ?? {}} {...bridge(entry)} />
156
+ {:else if entry._tag === 'select'}
157
+ <FormField {...fieldAttrs(entry)}>
158
+ {#snippet children(control)}
159
+ <Select
160
+ {...control}
161
+ name={entry.key}
162
+ options={selectOptions(entry)}
163
+ placeholder={selectPlaceholder}
164
+ bind:value={() => getField(entry.key), (next: string) => setField(entry.key, next)}
165
+ />
166
+ {/snippet}
167
+ </FormField>
168
+ {:else}
169
+ <FormField {...fieldAttrs(entry)}>
170
+ {#snippet children(control)}
171
+ {@render scalarInput(entry, control)}
172
+ {/snippet}
173
+ </FormField>
174
+ {/if}
175
+ {/each}
176
+
177
+ <FormActions
178
+ {submitLabel}
179
+ {pendingLabel}
180
+ pending={form.submitting}
181
+ disabled={gated}
182
+ {cancelHref}
183
+ {cancelLabel}
184
+ />
185
+ </form>