@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,229 @@
1
+ <!-- @component
2
+ A single-select typeahead over a static list or an asynchronous search, on bits-ui’s `Combobox`.
3
+ -->
4
+ <!--
5
+ Combobox — a single-select typeahead over a static list OR an asynchronous
6
+ search, on bits-ui's `Combobox`.
7
+
8
+ The previous generation of this component hand-rolled the APG combobox
9
+ pattern: an `<input role="combobox">`, a `<ul role="listbox">`, an
10
+ `activeIndex`, wrap-around arrow keys, Home/End, and a blur timeout to let a
11
+ pointerdown on an option land before the list closed. All of that is
12
+ bits-ui's here. What is NOT bits-ui's, and is what this file is actually
13
+ about, is the SEARCH LIFECYCLE.
14
+
15
+ The search lifecycle (`latest-search.svelte.ts`, shared with `TagsInput`),
16
+ in the order the problems bite:
17
+
18
+ debounce a keystroke does not start a request; `debounceMs` of
19
+ quiet does.
20
+ latest-wins each request gets an `AbortController`, and starting a
21
+ new one aborts the last. A superseded request is
22
+ cancelled rather than merely ignored, so a slow first
23
+ response cannot overwrite a fast second one.
24
+ stale-while- the previous results stay on screen while the next
25
+ revalidate request is in flight, with `pending` true. Clearing the
26
+ list on every keystroke makes the dropdown strobe and
27
+ costs the reader the thing they were about to pick.
28
+
29
+ ARIA contract: bits-ui gives the input `role="combobox"`,
30
+ `aria-autocomplete="list"`, `aria-expanded` and `aria-activedescendant`
31
+ pointing at the highlighted option; the panel is `role="listbox"` and each
32
+ row `role="option"` with `aria-selected`. The visible `<label>` names the
33
+ input through `for`/`id`; `errorMessage` is a `role="alert"` paragraph the
34
+ input is NOT described by, because a search failure is about the list rather
35
+ than about the value.
36
+
37
+ One behaviour is preserved from the hand-rolled version on purpose:
38
+ **Enter with nothing highlighted must not prevent a wrapping `<form>` from
39
+ submitting.** A search box that sits in a plain GET form has to keep working
40
+ when the list is empty or the reader never opened it. bits-ui's input
41
+ `preventDefault`s Enter whenever the panel is open, so the handler below
42
+ closes the panel first when nothing is highlighted: with the panel closed,
43
+ bits-ui treats Enter as an interaction key and returns without touching the
44
+ event, and the form submits. `highlighted` is tracked through the items'
45
+ own `onHighlight` / `onUnhighlight` callbacks, which is the only place
46
+ bits-ui surfaces it.
47
+
48
+ Note what that means in practice: bits-ui puts the cursor on the first
49
+ candidate as soon as typing produces one, so with matches on screen Enter
50
+ COMMITS. The fall-through happens where it matters — a query that matched
51
+ nothing, or a panel the reader never opened — which is exactly the case a
52
+ no-JS search form depends on.
53
+
54
+ `postedValue="query"` turns the widget into a search box, and changes two
55
+ things. The `name` moves onto the visible `<input>`, so the form posts the
56
+ typed text, and it does so with JavaScript off because the server-rendered
57
+ input is the posted control. And Enter submits the form unless the reader
58
+ MOVED to an option with the keyboard (`navigated`): bits-ui's
59
+ auto-highlight of the first candidate does not count, so typing a query and
60
+ pressing Enter searches for that query instead of opening the first
61
+ suggestion. Clicking an option still commits it.
62
+ -->
63
+ <script lang="ts" generics="T">import { Combobox } from "bits-ui";
64
+ import { inputSize } from "./field-types.js";
65
+ import { LatestSearch } from "./latest-search.svelte.js";
66
+ let { value = $bindable(), items, onSearch, debounceMs = 150, getId, getLabel, getBadge, label, placeholder, name, postedValue = "id", initialQuery, onQueryChange, onSelect, emptyLabel = "No matches", pendingLabel = "Searching…", errorMessage, id: idProp, describedBy = "", labelId: _labelId, invalid = false, required = false, disabled = false, size = "md", class: className, inputClass, hideLabel = false, portal = true, item, footer, empty, ...rest } = $props();
67
+ const uid = $props.id();
68
+ const inputId = $derived(idProp ?? uid);
69
+ // Only the initial value seeds the text; later changes come from typing.
70
+ // svelte-ignore state_referenced_locally
71
+ let query = $state(initialQuery ?? "");
72
+ let open = $state(false);
73
+ const searcher = new LatestSearch(() => onSearch, () => debounceMs);
74
+ const results = $derived(searcher.results);
75
+ const pending = $derived(searcher.pending);
76
+ const searchError = $derived(searcher.error);
77
+ /** The id of the row bits-ui currently has under the cursor, if any. */
78
+ let highlighted = $state();
79
+ /** The reader moved the cursor with the keyboard since they last typed. */
80
+ let navigated = false;
81
+ /** Static mode filters locally; async mode shows whatever last settled. */
82
+ const visible = $derived.by(() => {
83
+ if (onSearch !== undefined) return results;
84
+ const all = items ?? [];
85
+ const needle = query.trim().toLowerCase();
86
+ if (needle === "") return all;
87
+ return all.filter((entry) => getLabel(entry).toLowerCase().includes(needle));
88
+ });
89
+ const selectedLabel = $derived.by(() => {
90
+ if (value === undefined || items === undefined) return undefined;
91
+ const match = items.find((entry) => getId(entry) === value);
92
+ return match === undefined ? undefined : getLabel(match);
93
+ });
94
+ /** Seeds bits-ui's input text once, at mount. */
95
+ const initialText = $derived(selectedLabel ?? initialQuery);
96
+ const postsQuery = $derived(postedValue === "query");
97
+ const visibleError = $derived(errorMessage ?? searchError);
98
+ $effect(() => () => searcher.dispose());
99
+ const typed = (event) => {
100
+ query = event.currentTarget.value;
101
+ navigated = false;
102
+ onQueryChange?.(query);
103
+ if (onSearch === undefined) {
104
+ open = true;
105
+ return;
106
+ }
107
+ if (query.trim() === "") {
108
+ searcher.clear();
109
+ open = false;
110
+ return;
111
+ }
112
+ open = true;
113
+ searcher.schedule(query);
114
+ };
115
+ const navigationKeys = new Set([
116
+ "ArrowDown",
117
+ "ArrowUp",
118
+ "Home",
119
+ "End",
120
+ "PageDown",
121
+ "PageUp"
122
+ ]);
123
+ const keydown = (event) => {
124
+ if (navigationKeys.has(event.key)) {
125
+ navigated = true;
126
+ return;
127
+ }
128
+ if (event.key !== "Enter") return;
129
+ // In query mode a highlight the reader did not move to is bits-ui's
130
+ // auto-highlight, not a choice: treat it as nothing highlighted.
131
+ const committing = highlighted !== undefined && (!postsQuery || navigated);
132
+ if (committing) return;
133
+ // Nothing to commit. Close first so bits-ui's own Enter branch takes the
134
+ // closed path, which returns without `preventDefault` — that is what lets
135
+ // a wrapping form submit.
136
+ open = false;
137
+ };
138
+ </script>
139
+
140
+ <div {...rest} class={['fieldset w-full', className]}>
141
+ <label class={['label', hideLabel && 'sr-only']} for={inputId}>{label}</label>
142
+
143
+ <Combobox.Root
144
+ type="single"
145
+ bind:open
146
+ value={value ?? ''}
147
+ onValueChange={(next) => {
148
+ value = next === '' ? undefined : next;
149
+ if (next === '' || onSelect === undefined) return;
150
+ const chosen = visible.find((entry) => getId(entry) === next);
151
+ if (chosen !== undefined) onSelect(chosen);
152
+ }}
153
+ {disabled}
154
+ {required}
155
+ >
156
+ <Combobox.Input
157
+ id={inputId}
158
+ {...initialText === undefined ? {} : { defaultValue: initialText }}
159
+ {...postsQuery && name !== undefined ? { name } : {}}
160
+ {placeholder}
161
+ autocomplete="off"
162
+ aria-describedby={describedBy === '' ? undefined : describedBy}
163
+ aria-invalid={invalid ? 'true' : undefined}
164
+ oninput={typed}
165
+ onkeydown={keydown}
166
+ class={['input w-full', inputSize[size], invalid && 'input-error', inputClass]}
167
+ />
168
+
169
+ <Combobox.Portal disabled={!portal}>
170
+ <Combobox.Content
171
+ sideOffset={4}
172
+ class="menu bg-base-100 rounded-box border-base-300 z-50 max-h-72 min-w-64 overflow-auto border p-2 shadow-md"
173
+ >
174
+ <Combobox.Viewport>
175
+ {#each visible as entry (getId(entry))}
176
+ {@const entryId = getId(entry)}
177
+ {@const badge = getBadge?.(entry)}
178
+ <Combobox.Item
179
+ value={entryId}
180
+ label={getLabel(entry)}
181
+ onHighlight={() => (highlighted = entryId)}
182
+ onUnhighlight={() => {
183
+ if (highlighted === entryId) highlighted = undefined;
184
+ }}
185
+ class="rounded-field data-highlighted:bg-base-200 data-disabled:opacity-50 flex cursor-pointer items-center justify-between gap-3 px-3 py-2"
186
+ >
187
+ {#if item}
188
+ {@render item(entry)}
189
+ {:else}
190
+ <span>{getLabel(entry)}</span>
191
+ {#if badge !== undefined}
192
+ <span class="badge badge-ghost badge-sm">{badge}</span>
193
+ {/if}
194
+ {/if}
195
+ </Combobox.Item>
196
+ {/each}
197
+
198
+ {#if visible.length === 0}
199
+ {#if pending}
200
+ <p class="fieldset-label px-3 py-2">{pendingLabel}</p>
201
+ {:else if empty}
202
+ {@render empty({ query })}
203
+ {:else}
204
+ <p class="fieldset-label px-3 py-2">{emptyLabel}</p>
205
+ {/if}
206
+ {/if}
207
+
208
+ {#if footer}
209
+ {@render footer({ query, pending })}
210
+ {/if}
211
+ </Combobox.Viewport>
212
+ </Combobox.Content>
213
+ </Combobox.Portal>
214
+ </Combobox.Root>
215
+
216
+ <!--
217
+ In id mode the posted value is the id, not the typed text: bits-ui's own
218
+ hidden input is not used, because `name` here means "post the selection"
219
+ and nothing else about the widget should depend on it. In query mode the
220
+ visible input above carries `name` instead.
221
+ -->
222
+ {#if name !== undefined && !postsQuery}
223
+ <input type="hidden" {name} value={value ?? ''} />
224
+ {/if}
225
+
226
+ {#if visibleError !== undefined}
227
+ <p class="text-error pt-1 text-sm" role="alert">{visibleError}</p>
228
+ {/if}
229
+ </div>
@@ -0,0 +1,133 @@
1
+ import { Combobox } from 'bits-ui';
2
+ import type { Snippet } from 'svelte';
3
+ import type { HTMLAttributes } from 'svelte/elements';
4
+ import { type FieldSize } from './field-types.ts';
5
+ declare function $$render<T>(): {
6
+ props: Omit<HTMLAttributes<HTMLDivElement>, "class" | "id" | "children"> & {
7
+ /** The selected item's id. */
8
+ value?: string | undefined;
9
+ /** A static list, filtered here by label. Ignored when `onSearch` is set. */
10
+ items?: readonly T[] | undefined;
11
+ /**
12
+ * Fetch matches for a query. Debounced by `debounceMs`; `signal` aborts
13
+ * when a newer query supersedes this one, so pass it to `fetch`.
14
+ */
15
+ onSearch?: ((query: string, signal: AbortSignal) => Promise<readonly T[]>) | undefined;
16
+ /**
17
+ * Quiet period before a search starts, in milliseconds.
18
+ * @defaultValue `150`
19
+ */
20
+ debounceMs?: number | undefined;
21
+ /** The item's stable id — what `value` holds and what the hidden input posts. */
22
+ getId: (item: T) => string;
23
+ /** The item's human-readable text. */
24
+ getLabel: (item: T) => string;
25
+ /** Optional short chip on the right of a row. */
26
+ getBadge?: ((item: T) => string | undefined) | undefined;
27
+ /** Visible label; names the input. */
28
+ label: string;
29
+ /** Placeholder in the input. */
30
+ placeholder?: string | undefined;
31
+ /**
32
+ * Posted field name. With `postedValue="id"` it renders a hidden input
33
+ * carrying the selected id; with `postedValue="query"` it goes on the
34
+ * visible input, which posts the typed text.
35
+ */
36
+ name?: string | undefined;
37
+ /**
38
+ * What the field under `name` posts: the selected item's id, or the typed
39
+ * query text. `'query'` makes the input itself the posted control (so a
40
+ * plain GET search form works with JavaScript off) and makes Enter submit
41
+ * the form unless the reader arrowed to an option.
42
+ * @defaultValue `'id'`
43
+ */
44
+ postedValue?: "id" | "query" | undefined;
45
+ /** Text in the input at mount, such as the current search. A selected item's label wins. */
46
+ initialQuery?: string | undefined;
47
+ /** Called with the raw input text on every keystroke. */
48
+ onQueryChange?: ((query: string) => void) | undefined;
49
+ /** Called with the item the reader committed (click, or Enter on a highlighted row). */
50
+ onSelect?: ((item: T) => void) | undefined;
51
+ /**
52
+ * Shown when a settled search returned nothing.
53
+ * @defaultValue `'No matches'`
54
+ */
55
+ emptyLabel?: string | undefined;
56
+ /**
57
+ * Shown while the first search for a query is in flight.
58
+ * @defaultValue `'Searching…'`
59
+ */
60
+ pendingLabel?: string | undefined;
61
+ /** A caller-owned failure, rendered as an alert under the input. */
62
+ errorMessage?: string | undefined;
63
+ /** `FieldControl`: the input's id. */
64
+ id?: string | undefined;
65
+ /**
66
+ * `FieldControl`: ids for `aria-describedby`.
67
+ * @defaultValue `''`
68
+ */
69
+ describedBy?: string | undefined;
70
+ /**
71
+ * `FieldControl`: the visible label's id. Not used — this control is
72
+ * labelable, so the `FormField`'s `<label for>` already names it; taken
73
+ * here so a spread `FieldControl` does not leak it as an attribute.
74
+ */
75
+ labelId?: string | undefined;
76
+ /** `FieldControl`: the field is in error. */
77
+ invalid?: boolean | undefined;
78
+ /** `FieldControl`: the field must be filled. */
79
+ required?: boolean | undefined;
80
+ /** Disables the input. */
81
+ disabled?: boolean | undefined;
82
+ /**
83
+ * daisyUI size step.
84
+ * @defaultValue `'md'`
85
+ */
86
+ size?: FieldSize | undefined;
87
+ /** Extra classes on the root, merged last. */
88
+ class?: string | undefined;
89
+ /** Extra classes on the `<input>`, merged last (e.g. daisyUI `join-item`). */
90
+ inputClass?: string | undefined;
91
+ /** Keep the label as the input's accessible name but hide it visually. */
92
+ hideLabel?: boolean | undefined;
93
+ /**
94
+ * Portal the listbox to `<body>`. `false` renders it inside this
95
+ * component's root instead; it still floats over the layout.
96
+ * @defaultValue `true`
97
+ */
98
+ portal?: boolean | undefined;
99
+ /** Replace a row's contents. */
100
+ item?: Snippet<[T]> | undefined;
101
+ /** Rendered after the rows — a "create this" row, a "see all" link. */
102
+ footer?: Snippet<[{
103
+ query: string;
104
+ pending: boolean;
105
+ }]> | undefined;
106
+ /** Replaces `emptyLabel` when a settled search returned nothing. */
107
+ empty?: Snippet<[{
108
+ query: string;
109
+ }]> | undefined;
110
+ };
111
+ exports: {};
112
+ bindings: "value";
113
+ slots: {};
114
+ events: {};
115
+ };
116
+ declare class __sveltets_Render<T> {
117
+ props(): ReturnType<typeof $$render<T>>['props'];
118
+ events(): ReturnType<typeof $$render<T>>['events'];
119
+ slots(): ReturnType<typeof $$render<T>>['slots'];
120
+ bindings(): "value";
121
+ exports(): {};
122
+ }
123
+ interface $$IsomorphicComponent {
124
+ new <T>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<T>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<T>['props']>, ReturnType<__sveltets_Render<T>['events']>, ReturnType<__sveltets_Render<T>['slots']>> & {
125
+ $$bindings?: ReturnType<__sveltets_Render<T>['bindings']>;
126
+ } & ReturnType<__sveltets_Render<T>['exports']>;
127
+ <T>(internal: unknown, props: ReturnType<__sveltets_Render<T>['props']> & {}): ReturnType<__sveltets_Render<T>['exports']>;
128
+ z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
129
+ }
130
+ /** A single-select typeahead over a static list or an asynchronous search, on bits-ui’s `Combobox`. */
131
+ declare const Combobox: $$IsomorphicComponent;
132
+ type Combobox<T> = InstanceType<typeof Combobox<T>>;
133
+ export default Combobox;
@@ -0,0 +1,37 @@
1
+ <!-- @component
2
+ Segmented day / month / year entry on bits-ui `DateField`, in the locale's order.
3
+ -->
4
+ <!--
5
+ DateField — a date typed into segments (day, month, year; optionally hour
6
+ and minute), each a `role="spinbutton"`: digits to type, ↑ / ↓ to step,
7
+ ← / → and auto-advance between segments, Backspace to clear. The order
8
+ and separators follow the locale (en-AU day/month/year, en-US
9
+ month/day/year).
10
+
11
+ `DateInput` (the native `<input type="date">`) stays the default for a
12
+ single date on a form. Reach for this when a design needs the same
13
+ control on every browser, or a time as well as a date.
14
+
15
+ ARIA contract: see `SegmentGroup` — a `role="group"` named by the
16
+ `FormField` label through `labelId`, `aria-describedby` its hint and
17
+ errors, `aria-invalid` when in error. With `name`, bits-ui posts the ISO
18
+ value (`2026-10-14`) through a hidden input.
19
+ -->
20
+ <script lang="ts">import { DateField } from "bits-ui";
21
+ import { getComponentsContext } from "../context.svelte.js";
22
+ import { definedProps } from "./calendar-props.js";
23
+ import SegmentGroup from "./SegmentGroup.svelte";
24
+ import { segmentedField } from "./segmented-field.js";
25
+ let { value = $bindable(), minValue, maxValue, granularity = "day", ...shared } = $props();
26
+ const context = getComponentsContext();
27
+ const field = $derived(segmentedField(shared, context.locale()));
28
+ </script>
29
+
30
+ <DateField.Root
31
+ bind:value={() => value as DateValue, (next) => (value = next)}
32
+ {...field.root}
33
+ {...definedProps({ minValue, maxValue })}
34
+ {granularity}
35
+ >
36
+ <SegmentGroup parts={DateField} group={field.group} />
37
+ </DateField.Root>
@@ -0,0 +1,20 @@
1
+ import type { DateValue } from '@internationalized/date';
2
+ import { DateField } from 'bits-ui';
3
+ import { type SegmentedFieldProps } from './segmented-field.ts';
4
+ interface Props extends SegmentedFieldProps {
5
+ /** The date; `undefined` while empty or incomplete. Bindable. */
6
+ value?: DateValue | undefined;
7
+ /** Earliest valid date. */
8
+ minValue?: DateValue | undefined;
9
+ /** Latest valid date. */
10
+ maxValue?: DateValue | undefined;
11
+ /**
12
+ * The smallest segment shown.
13
+ * @defaultValue `'day'`
14
+ */
15
+ granularity?: 'day' | 'hour' | 'minute' | 'second' | undefined;
16
+ }
17
+ /** Segmented day / month / year entry on bits-ui `DateField`, in the locale's order. */
18
+ declare const DateField: import("svelte").Component<Props, {}, "value">;
19
+ type DateField = ReturnType<typeof DateField>;
20
+ export default DateField;
@@ -0,0 +1,31 @@
1
+ <!-- @component
2
+ A native `<input type="date">` in daisyUI `input` styling, with `FieldControl` wiring.
3
+ -->
4
+ <!--
5
+ DateInput — the native `<input type="date">` in daisyUI `input` styling.
6
+
7
+ `value` holds the ISO calendar date (`YYYY-MM-DD`) the control speaks
8
+ natively, which is also the shape a JSON API's date fields take, so no
9
+ conversion sits between the two.
10
+
11
+ Native on purpose, and the reason is worth stating: bits-ui's `DateField`
12
+ is a segmented control with its own locale handling and its own keyboard
13
+ contract, which is the right answer when a design needs a calendar popover
14
+ and the wrong one for a single date on a form — the platform control is
15
+ keyboard-complete, localises itself, and on a phone opens the system date
16
+ picker that people already know.
17
+ -->
18
+ <script lang="ts">import { inputSize } from "./field-types.js";
19
+ let { value = $bindable(""), min, max, size = "md", invalid = false, describedBy = "", labelId: _labelId, class: className, ...rest } = $props();
20
+ </script>
21
+
22
+ <input
23
+ {...rest}
24
+ type="date"
25
+ bind:value
26
+ {min}
27
+ {max}
28
+ aria-invalid={invalid ? 'true' : undefined}
29
+ aria-describedby={describedBy === '' ? undefined : describedBy}
30
+ class={['input w-full', inputSize[size], invalid && 'input-error', className]}
31
+ />
@@ -0,0 +1,35 @@
1
+ import type { HTMLInputAttributes } from 'svelte/elements';
2
+ import { type FieldSize } from './field-types.ts';
3
+ interface Props extends Omit<HTMLInputAttributes, 'type' | 'value' | 'size' | 'min' | 'max'> {
4
+ /**
5
+ * ISO calendar date, `YYYY-MM-DD`; empty when unset.
6
+ * @defaultValue `''`
7
+ */
8
+ value?: string | undefined;
9
+ /** Earliest selectable date, ISO. */
10
+ min?: string | undefined;
11
+ /** Latest selectable date, ISO. */
12
+ max?: string | undefined;
13
+ /**
14
+ * daisyUI size step.
15
+ * @defaultValue `'md'`
16
+ */
17
+ size?: FieldSize | undefined;
18
+ /** `FieldControl`: the field is in error — sets `aria-invalid` and the error style. */
19
+ invalid?: boolean | undefined;
20
+ /**
21
+ * `FieldControl`: space-separated ids for `aria-describedby`.
22
+ * @defaultValue `''`
23
+ */
24
+ describedBy?: string | undefined;
25
+ /**
26
+ * `FieldControl`: the visible label's id. Not used — this control is
27
+ * labelable, so the `FormField`'s `<label for>` already names it; taken
28
+ * here so a spread `FieldControl` does not leak it as an attribute.
29
+ */
30
+ labelId?: string | undefined;
31
+ }
32
+ /** A native `<input type="date">` in daisyUI `input` styling, with `FieldControl` wiring. */
33
+ declare const DateInput: import("svelte").Component<Props, {}, "value">;
34
+ type DateInput = ReturnType<typeof DateInput>;
35
+ export default DateInput;
@@ -0,0 +1,47 @@
1
+ <!-- @component
2
+ A segmented date field with a button that opens a calendar popover, on bits-ui `DatePicker`.
3
+ -->
4
+ <!--
5
+ DatePicker — `DateField`'s segments plus a calendar button: type the date,
6
+ or open the month and pick it. Selecting a day closes the popover
7
+ (`closeOnDateSelect`) and returns focus to the button.
8
+
9
+ Reach for it when the reader benefits from seeing the month (which day
10
+ of the week, what is unavailable); for a plain date on a form the
11
+ native `DateInput` remains the default.
12
+
13
+ ARIA contract: the segment group as `DateField` (named by the
14
+ `FormField` label through `labelId`); the trigger and dialog as
15
+ `PickerPopover`; the grid as `Calendar`.
16
+ -->
17
+ <script lang="ts">import { DatePicker } from "bits-ui";
18
+ import { getComponentsContext } from "../context.svelte.js";
19
+ import { definedProps } from "./calendar-props.js";
20
+ import PickerPopover from "./PickerPopover.svelte";
21
+ import SegmentGroup from "./SegmentGroup.svelte";
22
+ import { pickerField } from "./segmented-field.js";
23
+ let { value = $bindable(), open = $bindable(false), minValue, maxValue, granularity = "day", closeOnDateSelect = true, ...shared } = $props();
24
+ const context = getComponentsContext();
25
+ const picker = $derived(pickerField(shared, context.locale()));
26
+ </script>
27
+
28
+ <DatePicker.Root
29
+ bind:value={() => value as DateValue, (next) => (value = next)}
30
+ bind:open
31
+ {...picker.root}
32
+ {...definedProps({ minValue, maxValue })}
33
+ {granularity}
34
+ {closeOnDateSelect}
35
+ >
36
+ <SegmentGroup parts={DatePicker} group={picker.group}>
37
+ {#snippet trailing()}
38
+ <PickerPopover
39
+ parts={DatePicker}
40
+ triggerLabel={picker.triggerLabel}
41
+ calendarLabel={picker.calendarLabel}
42
+ months={picker.months}
43
+ disabled={picker.group.disabled}
44
+ />
45
+ {/snippet}
46
+ </SegmentGroup>
47
+ </DatePicker.Root>
@@ -0,0 +1,25 @@
1
+ import type { DateValue } from '@internationalized/date';
2
+ import { DatePicker } from 'bits-ui';
3
+ import { type PickerProps, type SegmentedFieldProps } from './segmented-field.ts';
4
+ interface Props extends SegmentedFieldProps, PickerProps {
5
+ /** The date; `undefined` while empty or incomplete. Bindable. */
6
+ value?: DateValue | undefined;
7
+ /** Earliest valid date. */
8
+ minValue?: DateValue | undefined;
9
+ /** Latest valid date. */
10
+ maxValue?: DateValue | undefined;
11
+ /**
12
+ * The smallest segment shown.
13
+ * @defaultValue `'day'`
14
+ */
15
+ granularity?: 'day' | 'hour' | 'minute' | 'second' | undefined;
16
+ /**
17
+ * Close the popover when a day is picked.
18
+ * @defaultValue `true`
19
+ */
20
+ closeOnDateSelect?: boolean | undefined;
21
+ }
22
+ /** A segmented date field with a button that opens a calendar popover, on bits-ui `DatePicker`. */
23
+ declare const DatePicker: import("svelte").Component<Props, {}, "value" | "open">;
24
+ type DatePicker = ReturnType<typeof DatePicker>;
25
+ export default DatePicker;
@@ -0,0 +1,70 @@
1
+ <!-- @component
2
+ Two segmented date fields, a start and an end, with a range-calendar popover, on bits-ui `DateRangePicker`.
3
+ -->
4
+ <!--
5
+ DateRangePicker — a start and an end date typed into segments, or picked
6
+ as a span on a `RangeCalendar` in a popover. `minDays` / `maxDays`
7
+ constrain the span while it is chosen.
8
+
9
+ ARIA contract: the whole control is one `role="group"` named by the
10
+ `FormField` label (`labelId`) and described by its hint and errors, so
11
+ the error text reaches it (a written-out `group` does not take
12
+ `aria-invalid`; `invalid` draws the error border). Inside it, the two halves are groups named
13
+ `startLabel` / `endLabel`, so a segment reads "day, <label> Start date".
14
+ The dash between them is `aria-hidden`. The trigger and dialog are
15
+ `PickerPopover`'s.
16
+ -->
17
+ <script lang="ts">import { DateRangePicker } from "bits-ui";
18
+ import { getComponentsContext } from "../context.svelte.js";
19
+ import { definedProps } from "./calendar-props.js";
20
+ import { inputSize } from "./field-types.js";
21
+ import PickerPopover from "./PickerPopover.svelte";
22
+ import SegmentGroup from "./SegmentGroup.svelte";
23
+ import { pickerField } from "./segmented-field.js";
24
+ let { value = $bindable(), open = $bindable(false), minValue, maxValue, minDays, maxDays, closeOnRangeSelect = true, startName, endName, startLabel = "Start date", endLabel = "End date", ...shared } = $props();
25
+ const context = getComponentsContext();
26
+ const picker = $derived(pickerField(shared, context.locale()));
27
+ const group = $derived(picker.group);
28
+ const { class: className, ...attributes } = $derived(group.attributes);
29
+ </script>
30
+
31
+ <DateRangePicker.Root
32
+ bind:value={
33
+ () => value ?? { start: undefined, end: undefined },
34
+ (next) => (value = { start: next.start, end: next.end })
35
+ }
36
+ bind:open
37
+ {...picker.root}
38
+ {...definedProps({ minValue, maxValue, minDays, maxDays })}
39
+ {closeOnRangeSelect}
40
+ >
41
+ {#snippet child({ props })}
42
+ <div
43
+ {...attributes}
44
+ {...props}
45
+ {...group.id === undefined ? {} : { id: group.id }}
46
+ role="group"
47
+ aria-labelledby={group.labelId}
48
+ aria-describedby={group.describedBy === '' ? undefined : group.describedBy}
49
+ class={[
50
+ 'input inline-flex w-auto items-center gap-0 tabular-nums',
51
+ inputSize[group.size],
52
+ group.invalid && 'input-error',
53
+ 'data-invalid:input-error',
54
+ group.disabled && 'opacity-50',
55
+ className,
56
+ ]}
57
+ >
58
+ <SegmentGroup parts={DateRangePicker} {group} range={{ type: 'start', label: startLabel, name: startName }} />
59
+ <span aria-hidden="true" class="text-base-content/60 px-1.5">–</span>
60
+ <SegmentGroup parts={DateRangePicker} {group} range={{ type: 'end', label: endLabel, name: endName }} />
61
+ <PickerPopover
62
+ parts={DateRangePicker}
63
+ triggerLabel={picker.triggerLabel}
64
+ calendarLabel={picker.calendarLabel}
65
+ months={picker.months}
66
+ disabled={group.disabled}
67
+ />
68
+ </div>
69
+ {/snippet}
70
+ </DateRangePicker.Root>