zabi-components 8.0.0 → 9.0.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 (456) hide show
  1. package/CHANGELOG.md +2935 -0
  2. package/README.md +243 -10
  3. package/THEME.md +162 -332
  4. package/THEMING.md +1419 -259
  5. package/dist/atoms/ActionPanel.svelte +15 -5
  6. package/dist/atoms/Avatar.svelte +120 -0
  7. package/dist/atoms/Avatar.svelte.d.ts +46 -0
  8. package/dist/atoms/Badge.svelte +71 -13
  9. package/dist/atoms/Badge.svelte.d.ts +8 -2
  10. package/dist/atoms/Block.svelte +74 -0
  11. package/dist/atoms/Block.svelte.d.ts +29 -0
  12. package/dist/atoms/Button.svelte +217 -30
  13. package/dist/atoms/Button.svelte.d.ts +33 -4
  14. package/dist/atoms/Card.svelte +182 -26
  15. package/dist/atoms/Card.svelte.d.ts +55 -3
  16. package/dist/atoms/CardHeader.svelte +16 -4
  17. package/dist/atoms/Checkbox.svelte +81 -21
  18. package/dist/atoms/Checkbox.svelte.d.ts +31 -2
  19. package/dist/atoms/Chip.svelte +351 -0
  20. package/dist/atoms/Chip.svelte.d.ts +57 -0
  21. package/dist/atoms/CodeBlock.svelte +20 -2
  22. package/dist/atoms/CodeBlock.svelte.d.ts +4 -0
  23. package/dist/atoms/CodeField.svelte +385 -0
  24. package/dist/atoms/CodeField.svelte.d.ts +61 -0
  25. package/dist/atoms/ColorPicker.svelte +260 -49
  26. package/dist/atoms/ColorPicker.svelte.d.ts +3 -0
  27. package/dist/atoms/Container.svelte +16 -8
  28. package/dist/atoms/DateField.svelte +145 -0
  29. package/dist/atoms/DateField.svelte.d.ts +81 -0
  30. package/dist/atoms/FieldMessages.svelte +69 -0
  31. package/dist/atoms/FieldMessages.svelte.d.ts +23 -0
  32. package/dist/atoms/FloatingActionButton.svelte +176 -0
  33. package/dist/atoms/FloatingActionButton.svelte.d.ts +51 -0
  34. package/dist/atoms/Heading.svelte +63 -5
  35. package/dist/atoms/Heading.svelte.d.ts +14 -0
  36. package/dist/atoms/IconButton.svelte +294 -26
  37. package/dist/atoms/IconButton.svelte.d.ts +62 -4
  38. package/dist/atoms/Input.svelte +259 -53
  39. package/dist/atoms/Input.svelte.d.ts +33 -2
  40. package/dist/atoms/List.svelte +5 -1
  41. package/dist/atoms/ListItem.svelte +70 -13
  42. package/dist/atoms/ListItem.svelte.d.ts +11 -0
  43. package/dist/atoms/PickerField.svelte +239 -0
  44. package/dist/atoms/PickerField.svelte.d.ts +67 -0
  45. package/dist/atoms/Progress.svelte +99 -19
  46. package/dist/atoms/Progress.svelte.d.ts +15 -1
  47. package/dist/atoms/Radio.svelte +51 -3
  48. package/dist/atoms/Radio.svelte.d.ts +30 -2
  49. package/dist/atoms/Rating.svelte +620 -0
  50. package/dist/atoms/Rating.svelte.d.ts +77 -0
  51. package/dist/atoms/Select.svelte +438 -98
  52. package/dist/atoms/Select.svelte.d.ts +61 -3
  53. package/dist/atoms/SelectionControl.svelte +193 -23
  54. package/dist/atoms/SelectionControl.svelte.d.ts +29 -3
  55. package/dist/atoms/Skeleton.svelte +114 -18
  56. package/dist/atoms/Skeleton.svelte.d.ts +30 -3
  57. package/dist/atoms/SkeletonGroup.svelte +43 -0
  58. package/dist/atoms/SkeletonGroup.svelte.d.ts +20 -0
  59. package/dist/atoms/Slider.svelte +344 -0
  60. package/dist/atoms/Slider.svelte.d.ts +40 -0
  61. package/dist/atoms/Sparkline.svelte +109 -0
  62. package/dist/atoms/Sparkline.svelte.d.ts +27 -0
  63. package/dist/atoms/SpeechBubble.svelte +187 -0
  64. package/dist/atoms/SpeechBubble.svelte.d.ts +33 -0
  65. package/dist/atoms/Spinner.svelte +57 -0
  66. package/dist/atoms/Spinner.svelte.d.ts +19 -0
  67. package/dist/atoms/Stat.svelte +72 -0
  68. package/dist/atoms/Stat.svelte.d.ts +19 -0
  69. package/dist/atoms/Table.svelte +151 -6
  70. package/dist/atoms/Table.svelte.d.ts +15 -3
  71. package/dist/atoms/TemporalField.svelte +472 -0
  72. package/dist/atoms/TemporalField.svelte.d.ts +48 -0
  73. package/dist/atoms/Text.svelte +23 -11
  74. package/dist/atoms/Text.svelte.d.ts +6 -3
  75. package/dist/atoms/Textarea.svelte +150 -44
  76. package/dist/atoms/Textarea.svelte.d.ts +35 -2
  77. package/dist/atoms/ThemeToggle.svelte +223 -44
  78. package/dist/atoms/ThemeToggle.svelte.d.ts +26 -3
  79. package/dist/atoms/TimeColumn.svelte +150 -0
  80. package/dist/atoms/TimeColumn.svelte.d.ts +25 -0
  81. package/dist/atoms/TimeField.svelte +151 -0
  82. package/dist/atoms/TimeField.svelte.d.ts +85 -0
  83. package/dist/atoms/Toast.svelte +22 -8
  84. package/dist/atoms/Toast.svelte.d.ts +2 -0
  85. package/dist/atoms/Toggle.svelte +98 -14
  86. package/dist/atoms/Toggle.svelte.d.ts +26 -2
  87. package/dist/atoms/Tooltip.svelte +528 -24
  88. package/dist/atoms/Tooltip.svelte.d.ts +18 -0
  89. package/dist/atoms/ZabiStringsProvider.svelte +45 -0
  90. package/dist/atoms/ZabiStringsProvider.svelte.d.ts +27 -0
  91. package/dist/atoms/index.d.ts +38 -0
  92. package/dist/atoms/index.js +29 -0
  93. package/dist/atoms/selection-control.styles.d.ts +47 -5
  94. package/dist/atoms/selection-control.styles.js +52 -10
  95. package/dist/components/atoms/index.d.ts +38 -0
  96. package/dist/components/atoms/index.d.ts.map +1 -1
  97. package/dist/components/atoms/selection-control.styles.d.ts +47 -5
  98. package/dist/components/atoms/selection-control.styles.d.ts.map +1 -1
  99. package/dist/components/index.d.ts +104 -2
  100. package/dist/components/index.d.ts.map +1 -1
  101. package/dist/components/map.d.ts +11 -0
  102. package/dist/components/map.d.ts.map +1 -0
  103. package/dist/components/molecules/index.d.ts +51 -0
  104. package/dist/components/molecules/index.d.ts.map +1 -1
  105. package/dist/components/molecules/toast-store.d.ts +83 -7
  106. package/dist/components/molecules/toast-store.d.ts.map +1 -1
  107. package/dist/components/organisms/index.d.ts +10 -0
  108. package/dist/components/organisms/index.d.ts.map +1 -1
  109. package/dist/components/types/variants.d.ts +24 -1
  110. package/dist/components/types/variants.d.ts.map +1 -1
  111. package/dist/components/util/app-shell.d.ts +79 -0
  112. package/dist/components/util/app-shell.d.ts.map +1 -0
  113. package/dist/components/util/avatar.d.ts +39 -0
  114. package/dist/components/util/avatar.d.ts.map +1 -0
  115. package/dist/components/util/bottom-sheet.d.ts +30 -0
  116. package/dist/components/util/bottom-sheet.d.ts.map +1 -0
  117. package/dist/components/util/bottom-tab-bar.d.ts +41 -0
  118. package/dist/components/util/bottom-tab-bar.d.ts.map +1 -0
  119. package/dist/components/util/calendar.d.ts +56 -0
  120. package/dist/components/util/calendar.d.ts.map +1 -0
  121. package/dist/components/util/chart.d.ts +140 -0
  122. package/dist/components/util/chart.d.ts.map +1 -0
  123. package/dist/components/util/chip.d.ts +66 -0
  124. package/dist/components/util/chip.d.ts.map +1 -0
  125. package/dist/components/util/cn.d.ts.map +1 -1
  126. package/dist/components/util/code-field.d.ts +63 -0
  127. package/dist/components/util/code-field.d.ts.map +1 -0
  128. package/dist/components/util/collapsible.d.ts +64 -0
  129. package/dist/components/util/collapsible.d.ts.map +1 -0
  130. package/dist/components/util/confirm-dialog.d.ts +12 -0
  131. package/dist/components/util/confirm-dialog.d.ts.map +1 -0
  132. package/dist/components/util/date.d.ts +96 -0
  133. package/dist/components/util/date.d.ts.map +1 -0
  134. package/dist/components/util/display-voice.d.ts +10 -0
  135. package/dist/components/util/display-voice.d.ts.map +1 -0
  136. package/dist/components/util/drawer.d.ts +13 -0
  137. package/dist/components/util/drawer.d.ts.map +1 -0
  138. package/dist/components/util/dropdown.d.ts +47 -0
  139. package/dist/components/util/dropdown.d.ts.map +1 -0
  140. package/dist/components/util/field-control.d.ts +30 -0
  141. package/dist/components/util/field-control.d.ts.map +1 -0
  142. package/dist/components/util/field.d.ts +45 -0
  143. package/dist/components/util/field.d.ts.map +1 -0
  144. package/dist/components/util/fit-in-viewport.d.ts +201 -0
  145. package/dist/components/util/fit-in-viewport.d.ts.map +1 -0
  146. package/dist/components/util/focus-utils.d.ts +77 -2
  147. package/dist/components/util/focus-utils.d.ts.map +1 -1
  148. package/dist/components/util/hydration.d.ts +45 -0
  149. package/dist/components/util/hydration.d.ts.map +1 -0
  150. package/dist/components/util/keyboard-inset.d.ts +18 -0
  151. package/dist/components/util/keyboard-inset.d.ts.map +1 -0
  152. package/dist/components/util/map-view.d.ts +144 -0
  153. package/dist/components/util/map-view.d.ts.map +1 -0
  154. package/dist/components/util/media-grid.d.ts +51 -0
  155. package/dist/components/util/media-grid.d.ts.map +1 -0
  156. package/dist/components/util/media.d.ts +6 -0
  157. package/dist/components/util/media.d.ts.map +1 -0
  158. package/dist/components/util/overlay-chrome.d.ts +53 -0
  159. package/dist/components/util/overlay-chrome.d.ts.map +1 -0
  160. package/dist/components/util/overlay.d.ts +72 -0
  161. package/dist/components/util/overlay.d.ts.map +1 -0
  162. package/dist/components/util/photo.d.ts +234 -0
  163. package/dist/components/util/photo.d.ts.map +1 -0
  164. package/dist/components/util/portal.d.ts +23 -0
  165. package/dist/components/util/portal.d.ts.map +1 -0
  166. package/dist/components/util/progress.d.ts +19 -0
  167. package/dist/components/util/progress.d.ts.map +1 -0
  168. package/dist/components/util/pull-to-refresh.d.ts +27 -0
  169. package/dist/components/util/pull-to-refresh.d.ts.map +1 -0
  170. package/dist/components/util/radio-keys.d.ts +25 -0
  171. package/dist/components/util/radio-keys.d.ts.map +1 -0
  172. package/dist/components/util/rating.d.ts +23 -0
  173. package/dist/components/util/rating.d.ts.map +1 -0
  174. package/dist/components/util/ready-made-strings.d.ts +77 -0
  175. package/dist/components/util/ready-made-strings.d.ts.map +1 -0
  176. package/dist/components/util/scroll-edge.d.ts +33 -0
  177. package/dist/components/util/scroll-edge.d.ts.map +1 -0
  178. package/dist/components/util/scroll-padding.d.ts +20 -0
  179. package/dist/components/util/scroll-padding.d.ts.map +1 -0
  180. package/dist/components/util/segmented-control.d.ts +16 -0
  181. package/dist/components/util/segmented-control.d.ts.map +1 -0
  182. package/dist/components/util/select.d.ts +41 -0
  183. package/dist/components/util/select.d.ts.map +1 -0
  184. package/dist/components/util/sheet-drag.d.ts +84 -0
  185. package/dist/components/util/sheet-drag.d.ts.map +1 -0
  186. package/dist/components/util/sidebar.d.ts +63 -0
  187. package/dist/components/util/sidebar.d.ts.map +1 -0
  188. package/dist/components/util/skeleton.d.ts +15 -0
  189. package/dist/components/util/skeleton.d.ts.map +1 -0
  190. package/dist/components/util/sliding-indicator.d.ts +25 -0
  191. package/dist/components/util/sliding-indicator.d.ts.map +1 -0
  192. package/dist/components/util/sortable-list.d.ts +65 -0
  193. package/dist/components/util/sortable-list.d.ts.map +1 -0
  194. package/dist/components/util/stepper.d.ts +40 -0
  195. package/dist/components/util/stepper.d.ts.map +1 -0
  196. package/dist/components/util/swipeable-list-item.d.ts +36 -0
  197. package/dist/components/util/swipeable-list-item.d.ts.map +1 -0
  198. package/dist/components/util/temporal-field.d.ts +89 -0
  199. package/dist/components/util/temporal-field.d.ts.map +1 -0
  200. package/dist/components/util/theme-mode.d.ts +80 -0
  201. package/dist/components/util/theme-mode.d.ts.map +1 -0
  202. package/dist/components/util/toaster.d.ts +133 -0
  203. package/dist/components/util/toaster.d.ts.map +1 -0
  204. package/dist/components/util/tone-surface.d.ts +34 -0
  205. package/dist/components/util/tone-surface.d.ts.map +1 -0
  206. package/dist/components/util/tooltip.d.ts +10 -0
  207. package/dist/components/util/tooltip.d.ts.map +1 -0
  208. package/dist/components/util/top-navbar.d.ts +35 -0
  209. package/dist/components/util/top-navbar.d.ts.map +1 -0
  210. package/dist/components/util/touch-target.d.ts +31 -0
  211. package/dist/components/util/touch-target.d.ts.map +1 -0
  212. package/dist/components/util/zabi-strings.d.ts +142 -0
  213. package/dist/components/util/zabi-strings.d.ts.map +1 -0
  214. package/dist/create-theme/cli.js +173 -0
  215. package/dist/create-theme/index.d.ts +190 -0
  216. package/dist/create-theme/index.js +1034 -0
  217. package/dist/create-theme/lib/ramp-math.js +128 -0
  218. package/dist/create-theme/lib/resolve.js +238 -0
  219. package/dist/create-theme/theme-data.js +2644 -0
  220. package/dist/index.d.ts +104 -2
  221. package/dist/index.js +75 -2
  222. package/dist/map.d.ts +10 -0
  223. package/dist/map.js +9 -0
  224. package/dist/molecules/Alert.svelte +63 -16
  225. package/dist/molecules/Alert.svelte.d.ts +14 -1
  226. package/dist/molecules/AppBar.svelte +674 -0
  227. package/dist/molecules/AppBar.svelte.d.ts +131 -0
  228. package/dist/molecules/AvatarGroup.svelte +116 -0
  229. package/dist/molecules/AvatarGroup.svelte.d.ts +40 -0
  230. package/dist/molecules/BarChart.svelte +381 -0
  231. package/dist/molecules/BarChart.svelte.d.ts +45 -0
  232. package/dist/molecules/BottomSheet.svelte +608 -0
  233. package/dist/molecules/BottomSheet.svelte.d.ts +109 -0
  234. package/dist/molecules/BottomTabBar.svelte +403 -0
  235. package/dist/molecules/BottomTabBar.svelte.d.ts +98 -0
  236. package/dist/molecules/Calendar.svelte +597 -0
  237. package/dist/molecules/Calendar.svelte.d.ts +72 -0
  238. package/dist/molecules/ChipGroup.svelte +325 -0
  239. package/dist/molecules/ChipGroup.svelte.d.ts +41 -0
  240. package/dist/molecules/Collapsible.svelte +347 -0
  241. package/dist/molecules/Collapsible.svelte.d.ts +61 -0
  242. package/dist/molecules/CollapsibleGroup.svelte +136 -0
  243. package/dist/molecules/CollapsibleGroup.svelte.d.ts +14 -0
  244. package/dist/molecules/ComponentDemo.svelte +16 -4
  245. package/dist/molecules/ComponentDemo.svelte.d.ts +3 -0
  246. package/dist/molecules/ConfirmDialog.svelte +257 -0
  247. package/dist/molecules/ConfirmDialog.svelte.d.ts +58 -0
  248. package/dist/molecules/ContactForm.svelte +34 -17
  249. package/dist/molecules/ContactForm.svelte.d.ts +8 -0
  250. package/dist/molecules/Drawer.svelte +415 -0
  251. package/dist/molecules/Drawer.svelte.d.ts +55 -0
  252. package/dist/molecules/Dropdown.svelte +517 -48
  253. package/dist/molecules/Dropdown.svelte.d.ts +47 -6
  254. package/dist/molecules/DropdownItem.svelte +122 -0
  255. package/dist/molecules/DropdownItem.svelte.d.ts +28 -0
  256. package/dist/molecules/EmptyState.svelte +55 -10
  257. package/dist/molecules/EmptyState.svelte.d.ts +8 -0
  258. package/dist/molecules/FormField.svelte +9 -1
  259. package/dist/molecules/FormField.svelte.d.ts +2 -0
  260. package/dist/molecules/Header.svelte +1 -1
  261. package/dist/molecules/ImageUpload.svelte +492 -69
  262. package/dist/molecules/ImageUpload.svelte.d.ts +82 -2
  263. package/dist/molecules/LineChart.svelte +459 -0
  264. package/dist/molecules/LineChart.svelte.d.ts +53 -0
  265. package/dist/molecules/MapView.svelte +565 -0
  266. package/dist/molecules/MapView.svelte.d.ts +88 -0
  267. package/dist/molecules/MediaGrid.svelte +527 -0
  268. package/dist/molecules/MediaGrid.svelte.d.ts +77 -0
  269. package/dist/molecules/Modal.svelte +293 -72
  270. package/dist/molecules/Modal.svelte.d.ts +51 -2
  271. package/dist/molecules/NavigationMenuContent.svelte +58 -1
  272. package/dist/molecules/NavigationMenuItem.svelte +0 -1
  273. package/dist/molecules/NavigationMenuLink.svelte +1 -1
  274. package/dist/molecules/NavigationMenuList.svelte +10 -3
  275. package/dist/molecules/NavigationMenuTrigger.svelte +2 -2
  276. package/dist/molecules/Page.svelte +32 -2
  277. package/dist/molecules/Page.svelte.d.ts +11 -0
  278. package/dist/molecules/PhotoGrid.svelte +523 -0
  279. package/dist/molecules/PhotoGrid.svelte.d.ts +73 -0
  280. package/dist/molecules/PhotoViewer.svelte +1213 -0
  281. package/dist/molecules/PhotoViewer.svelte.d.ts +74 -0
  282. package/dist/molecules/PieChart.svelte +421 -0
  283. package/dist/molecules/PieChart.svelte.d.ts +51 -0
  284. package/dist/molecules/PropsTable.svelte +22 -10
  285. package/dist/molecules/PropsTable.svelte.d.ts +3 -0
  286. package/dist/molecules/PullToRefresh.svelte +263 -0
  287. package/dist/molecules/PullToRefresh.svelte.d.ts +52 -0
  288. package/dist/molecules/RadioGroup.svelte +72 -18
  289. package/dist/molecules/RadioGroup.svelte.d.ts +19 -3
  290. package/dist/molecules/Section.svelte +1 -1
  291. package/dist/molecules/SegmentedControl.svelte +456 -0
  292. package/dist/molecules/SegmentedControl.svelte.d.ts +40 -0
  293. package/dist/molecules/SidebarBrandHeader.svelte +11 -1
  294. package/dist/molecules/SidebarBrandHeader.svelte.d.ts +3 -0
  295. package/dist/molecules/SidebarFooter.svelte +30 -7
  296. package/dist/molecules/SidebarFooter.svelte.d.ts +3 -0
  297. package/dist/molecules/SidebarNavSection.svelte +1 -1
  298. package/dist/molecules/SlideUp.svelte +220 -61
  299. package/dist/molecules/SlideUp.svelte.d.ts +26 -0
  300. package/dist/molecules/SortableList.svelte +633 -0
  301. package/dist/molecules/SortableList.svelte.d.ts +69 -0
  302. package/dist/molecules/Stepper.svelte +562 -0
  303. package/dist/molecules/Stepper.svelte.d.ts +39 -0
  304. package/dist/molecules/StickyActionBar.svelte +250 -0
  305. package/dist/molecules/StickyActionBar.svelte.d.ts +78 -0
  306. package/dist/molecules/SwipeableListItem.svelte +334 -0
  307. package/dist/molecules/SwipeableListItem.svelte.d.ts +54 -0
  308. package/dist/molecules/Tabs.svelte +310 -9
  309. package/dist/molecules/Tabs.svelte.d.ts +7 -0
  310. package/dist/molecules/Toaster.svelte +514 -5
  311. package/dist/molecules/Toaster.svelte.d.ts +153 -2
  312. package/dist/molecules/ToasterToast.svelte +495 -77
  313. package/dist/molecules/ToasterToast.svelte.d.ts +15 -0
  314. package/dist/molecules/UnsavedChangesBar.svelte +223 -0
  315. package/dist/molecules/UnsavedChangesBar.svelte.d.ts +43 -0
  316. package/dist/molecules/index.d.ts +51 -0
  317. package/dist/molecules/index.js +31 -0
  318. package/dist/molecules/toast-store.d.ts +83 -7
  319. package/dist/molecules/toast-store.js +25 -1
  320. package/dist/organisms/AppNavigation.svelte +440 -0
  321. package/dist/organisms/AppNavigation.svelte.d.ts +72 -0
  322. package/dist/organisms/AppShell.svelte +696 -0
  323. package/dist/organisms/AppShell.svelte.d.ts +157 -0
  324. package/dist/organisms/AppShellHeaderPart.svelte +163 -0
  325. package/dist/organisms/AppShellHeaderPart.svelte.d.ts +57 -0
  326. package/dist/organisms/SidebarAccountPanel.svelte +107 -12
  327. package/dist/organisms/SidebarAccountPanel.svelte.d.ts +19 -0
  328. package/dist/organisms/SidebarNavigation.svelte +111 -43
  329. package/dist/organisms/SidebarNavigation.svelte.d.ts +29 -1
  330. package/dist/organisms/SidebarPanel.svelte +34 -17
  331. package/dist/organisms/SidebarPanel.svelte.d.ts +1 -0
  332. package/dist/organisms/SidebarShell.svelte +164 -14
  333. package/dist/organisms/SidebarShell.svelte.d.ts +56 -2
  334. package/dist/organisms/TopNavbar.svelte +353 -39
  335. package/dist/organisms/TopNavbar.svelte.d.ts +47 -0
  336. package/dist/organisms/TopNavbarSheetContent.svelte +145 -0
  337. package/dist/organisms/TopNavbarSheetContent.svelte.d.ts +24 -0
  338. package/dist/organisms/index.d.ts +10 -0
  339. package/dist/organisms/index.js +7 -0
  340. package/dist/types/components.d.ts +21 -1
  341. package/dist/types/components.d.ts.map +1 -1
  342. package/dist/types/index.d.ts +1093 -26
  343. package/dist/types/index.d.ts.map +1 -1
  344. package/dist/types/variants.ts +28 -1
  345. package/dist/util/app-shell.d.ts +78 -0
  346. package/dist/util/app-shell.js +97 -0
  347. package/dist/util/avatar.d.ts +38 -0
  348. package/dist/util/avatar.js +52 -0
  349. package/dist/util/bottom-sheet.d.ts +29 -0
  350. package/dist/util/bottom-sheet.js +43 -0
  351. package/dist/util/bottom-tab-bar.d.ts +40 -0
  352. package/dist/util/bottom-tab-bar.js +54 -0
  353. package/dist/util/calendar.d.ts +55 -0
  354. package/dist/util/calendar.js +74 -0
  355. package/dist/util/chart.d.ts +139 -0
  356. package/dist/util/chart.js +305 -0
  357. package/dist/util/chip.d.ts +65 -0
  358. package/dist/util/chip.js +58 -0
  359. package/dist/util/cn.js +28 -2
  360. package/dist/util/code-field.d.ts +62 -0
  361. package/dist/util/code-field.js +112 -0
  362. package/dist/util/collapsible.d.ts +63 -0
  363. package/dist/util/collapsible.js +23 -0
  364. package/dist/util/confirm-dialog.d.ts +11 -0
  365. package/dist/util/confirm-dialog.js +2 -0
  366. package/dist/util/date.d.ts +95 -0
  367. package/dist/util/date.js +237 -0
  368. package/dist/util/display-voice.d.ts +9 -0
  369. package/dist/util/display-voice.js +9 -0
  370. package/dist/util/drawer.d.ts +12 -0
  371. package/dist/util/drawer.js +7 -0
  372. package/dist/util/dropdown.d.ts +46 -0
  373. package/dist/util/dropdown.js +21 -0
  374. package/dist/util/field-control.d.ts +29 -0
  375. package/dist/util/field-control.js +32 -0
  376. package/dist/util/field.d.ts +44 -0
  377. package/dist/util/field.js +38 -0
  378. package/dist/util/fit-in-viewport.d.ts +200 -0
  379. package/dist/util/fit-in-viewport.js +399 -0
  380. package/dist/util/focus-utils.d.ts +77 -2
  381. package/dist/util/focus-utils.js +186 -9
  382. package/dist/util/hydration.d.ts +44 -0
  383. package/dist/util/hydration.js +58 -0
  384. package/dist/util/keyboard-inset.d.ts +17 -0
  385. package/dist/util/keyboard-inset.js +53 -0
  386. package/dist/util/map-view.d.ts +143 -0
  387. package/dist/util/map-view.js +121 -0
  388. package/dist/util/media-grid.d.ts +50 -0
  389. package/dist/util/media-grid.js +81 -0
  390. package/dist/util/media.d.ts +5 -0
  391. package/dist/util/media.js +10 -0
  392. package/dist/util/overlay-chrome.d.ts +52 -0
  393. package/dist/util/overlay-chrome.js +56 -0
  394. package/dist/util/overlay.d.ts +71 -0
  395. package/dist/util/overlay.js +240 -0
  396. package/dist/util/photo.d.ts +233 -0
  397. package/dist/util/photo.js +209 -0
  398. package/dist/util/portal.d.ts +22 -0
  399. package/dist/util/portal.js +50 -0
  400. package/dist/util/progress.d.ts +18 -0
  401. package/dist/util/progress.js +17 -0
  402. package/dist/util/pull-to-refresh.d.ts +26 -0
  403. package/dist/util/pull-to-refresh.js +30 -0
  404. package/dist/util/radio-keys.d.ts +24 -0
  405. package/dist/util/radio-keys.js +49 -0
  406. package/dist/util/rating.d.ts +22 -0
  407. package/dist/util/rating.js +26 -0
  408. package/dist/util/ready-made-strings.d.ts +76 -0
  409. package/dist/util/ready-made-strings.js +67 -0
  410. package/dist/util/scroll-edge.d.ts +32 -0
  411. package/dist/util/scroll-edge.js +87 -0
  412. package/dist/util/scroll-padding.d.ts +19 -0
  413. package/dist/util/scroll-padding.js +44 -0
  414. package/dist/util/segmented-control.d.ts +15 -0
  415. package/dist/util/segmented-control.js +1 -0
  416. package/dist/util/select.d.ts +40 -0
  417. package/dist/util/select.js +63 -0
  418. package/dist/util/sheet-drag.d.ts +83 -0
  419. package/dist/util/sheet-drag.js +311 -0
  420. package/dist/util/sidebar.d.ts +62 -0
  421. package/dist/util/sidebar.js +38 -0
  422. package/dist/util/skeleton.d.ts +14 -0
  423. package/dist/util/skeleton.js +22 -0
  424. package/dist/util/sliding-indicator.d.ts +24 -0
  425. package/dist/util/sliding-indicator.js +44 -0
  426. package/dist/util/sortable-list.d.ts +64 -0
  427. package/dist/util/sortable-list.js +53 -0
  428. package/dist/util/stepper.d.ts +39 -0
  429. package/dist/util/stepper.js +38 -0
  430. package/dist/util/swipeable-list-item.d.ts +35 -0
  431. package/dist/util/swipeable-list-item.js +32 -0
  432. package/dist/util/temporal-field.d.ts +88 -0
  433. package/dist/util/temporal-field.js +136 -0
  434. package/dist/util/theme-mode.d.ts +79 -0
  435. package/dist/util/theme-mode.js +121 -0
  436. package/dist/util/toaster.d.ts +132 -0
  437. package/dist/util/toaster.js +130 -0
  438. package/dist/util/tone-surface.d.ts +33 -0
  439. package/dist/util/tone-surface.js +35 -0
  440. package/dist/util/tooltip.d.ts +9 -0
  441. package/dist/util/tooltip.js +18 -0
  442. package/dist/util/top-navbar.d.ts +34 -0
  443. package/dist/util/top-navbar.js +28 -0
  444. package/dist/util/touch-target.d.ts +30 -0
  445. package/dist/util/touch-target.js +30 -0
  446. package/dist/util/zabi-strings.d.ts +141 -0
  447. package/dist/util/zabi-strings.js +105 -0
  448. package/dist/zabi-components-colors.css +11 -2
  449. package/dist/zabi-components-theme-dark-only.css +870 -258
  450. package/dist/zabi-components-theme-dark.css +870 -258
  451. package/dist/zabi-components-theme-only.css +2419 -368
  452. package/dist/zabi-components-theme.css +2419 -368
  453. package/dist/zabi-components.css +6032 -711
  454. package/docs/lucide-icons.md +40 -17
  455. package/docs/theme-imports.md +81 -11
  456. package/package.json +45 -8
@@ -0,0 +1,263 @@
1
+ <script lang="ts">
2
+ import { mergeStrings } from "../util/ready-made-strings.js";
3
+ import { zabiStringsFor } from "../util/zabi-strings.js";
4
+ import type { Snippet } from "svelte";
5
+ import type { HTMLAttributes } from "svelte/elements";
6
+ import ArrowDown from "@lucide/svelte/icons/arrow-down";
7
+ import Spinner from "../atoms/Spinner.svelte";
8
+ import { cn } from "../util/cn.js";
9
+ import {
10
+ DEFAULT_PULL_TO_REFRESH_STRINGS,
11
+ pullDistance,
12
+ scrollContainerOf,
13
+ type PullToRefreshStrings,
14
+ } from "../util/pull-to-refresh.js";
15
+ import { DRAG_SLOP, prefersReducedMotion } from "../util/sheet-drag.js";
16
+
17
+ /**
18
+ * A list that reloads when it is pulled down from its top, on a touch
19
+ * screen.
20
+ *
21
+ * The pull is a shortcut. The same refresh is a button at the top of the
22
+ * region, out of sight until keyboard focus reaches it, and named for a
23
+ * screen reader; "Refreshing" and "Updated" are announced, and the
24
+ * region is `aria-busy` meanwhile.
25
+ *
26
+ * It only acts while what scrolls the list (the page, or the nearest
27
+ * scrolling ancestor, such as the content of an `AppShell`) is at its
28
+ * top, and never takes an ordinary scroll. The indicator is in the flow
29
+ * of the region, above the list, so under an app bar it comes out below
30
+ * the bar.
31
+ *
32
+ * ```svelte
33
+ * <PullToRefresh onrefresh={() => loadRounds()}>
34
+ * <List items={rounds} />
35
+ * </PullToRefresh>
36
+ * ```
37
+ */
38
+ type Props = Omit<HTMLAttributes<HTMLDivElement>, "class" | "children" | "aria-busy"> & {
39
+ /**
40
+ * Reloads the list. Return the promise: the indicator stays until it
41
+ * settles. A promise that rejects ends the refresh too, and nothing
42
+ * is announced as updated; say what went wrong yourself.
43
+ */
44
+ onrefresh?: () => Promise<void> | void;
45
+ /** Whether a refresh is running. Bindable: set it to show the indicator for a refresh of your own. */
46
+ refreshing?: boolean;
47
+ /** No pull and no button. */
48
+ disabled?: boolean;
49
+ /** How far the indicator has to come out for letting go to refresh, in px. */
50
+ threshold?: number;
51
+ /**
52
+ * The button that refreshes without the gesture. Without it the pull
53
+ * is the only way this component offers, and the app has to give
54
+ * another (WCAG 2.5.1).
55
+ */
56
+ showButton?: boolean;
57
+ /** The words the component says by itself, for another language. */
58
+ strings?: Partial<PullToRefreshStrings>;
59
+ class?: string;
60
+ /** The list. */
61
+ children?: Snippet;
62
+ };
63
+
64
+ let {
65
+ onrefresh,
66
+ refreshing = $bindable<Exclude<Props["refreshing"], undefined>>(),
67
+ disabled = false,
68
+ threshold = 64,
69
+ showButton = true,
70
+ strings,
71
+ class: className = "",
72
+ children,
73
+ ...restProps
74
+ }: Props = $props();
75
+
76
+ // No fallback on a bindable prop (see Collapsible): the default is applied here.
77
+ const applyDefaults = () => {
78
+ if (refreshing === undefined) refreshing = false;
79
+ };
80
+ applyDefaults();
81
+ $effect.pre(applyDefaults);
82
+
83
+ /** The app-wide words for this component, from a `ZabiStringsProvider` above it, if there is one. */
84
+ const provided = zabiStringsFor("pullToRefresh");
85
+ const text = $derived(mergeStrings(DEFAULT_PULL_TO_REFRESH_STRINGS, provided(), strings));
86
+
87
+ let root = $state<HTMLDivElement>();
88
+ /** How far the indicator is out under a finger, in px; null when no pull is going on. */
89
+ let pulled = $state<number | null>(null);
90
+ /** What the status region says. It is in the page, empty, before anything is said. */
91
+ let status = $state("");
92
+ /** Set when a refresh of this component's own failed: nothing was updated. */
93
+ let failed = false;
94
+
95
+ const armed = $derived(pulled !== null && pulled >= threshold);
96
+
97
+ async function refresh() {
98
+ if (disabled || refreshing) return;
99
+ failed = false;
100
+ refreshing = true;
101
+ try {
102
+ await onrefresh?.();
103
+ } catch {
104
+ // The app's to report (see `onrefresh`). The refresh is over all the same.
105
+ failed = true;
106
+ } finally {
107
+ refreshing = false;
108
+ }
109
+ }
110
+
111
+ // The announcements follow `refreshing`, whoever set it.
112
+ let wasRefreshing = false;
113
+ $effect(() => {
114
+ const now = !!refreshing;
115
+ if (now === wasRefreshing) return;
116
+ wasRefreshing = now;
117
+ status = now ? text.refreshing : failed ? "" : text.done;
118
+ });
119
+
120
+ // The browser's own pull-to-refresh must not fire as well: that is a
121
+ // property of what scrolls, which is not this element.
122
+ $effect(() => {
123
+ const element = root;
124
+ if (!element || disabled) return;
125
+ const scroller = scrollContainerOf(element);
126
+ const before = scroller.style.overscrollBehaviorY;
127
+ scroller.style.overscrollBehaviorY = "contain";
128
+ return () => {
129
+ scroller.style.overscrollBehaviorY = before;
130
+ };
131
+ });
132
+
133
+ // --- The pull. Touch events, because the browser owns the gesture (it
134
+ // scrolls) until it is taken, and only a touch listener that is not
135
+ // passive can take it. A mouse does not pull.
136
+ $effect(() => {
137
+ const element = root;
138
+ if (!element || disabled) return;
139
+ const scroller = scrollContainerOf(element);
140
+ let touchId: number | null = null;
141
+ let startX = 0;
142
+ let startY = 0;
143
+ let pulling = false;
144
+
145
+ const find = (list: TouchList) => Array.from(list).find((touch) => touch.identifier === touchId);
146
+
147
+ function onTouchStart(event: TouchEvent) {
148
+ if (touchId !== null || event.touches.length !== 1 || refreshing) return;
149
+ if (scroller.scrollTop > 0) return;
150
+ const touch = event.touches[0];
151
+ touchId = touch.identifier;
152
+ startX = touch.clientX;
153
+ startY = touch.clientY;
154
+ pulling = false;
155
+ }
156
+
157
+ function onTouchMove(event: TouchEvent) {
158
+ const touch = find(event.touches);
159
+ if (!touch) return;
160
+ const dx = touch.clientX - startX;
161
+ const dy = touch.clientY - startY;
162
+ if (!pulling) {
163
+ // Scrolled since, upwards, or sideways: not a pull.
164
+ if (scroller.scrollTop > 0 || dy < DRAG_SLOP) return;
165
+ if (Math.abs(dx) > Math.abs(dy)) {
166
+ touchId = null;
167
+ return;
168
+ }
169
+ pulling = true;
170
+ // Measured from where the pull was recognised.
171
+ startY = touch.clientY;
172
+ }
173
+ if (event.cancelable) event.preventDefault();
174
+ pulled = pullDistance(touch.clientY - startY, threshold);
175
+ }
176
+
177
+ function finish(event: TouchEvent, cancelled: boolean) {
178
+ if (!find(event.changedTouches)) return;
179
+ touchId = null;
180
+ const far = pulling && !cancelled && pulled !== null && pulled >= threshold;
181
+ pulling = false;
182
+ pulled = null;
183
+ if (far) void refresh();
184
+ }
185
+
186
+ const onTouchEnd = (event: TouchEvent) => finish(event, false);
187
+ const onTouchCancel = (event: TouchEvent) => finish(event, true);
188
+
189
+ element.addEventListener("touchstart", onTouchStart, { passive: true });
190
+ element.addEventListener("touchmove", onTouchMove, { passive: false });
191
+ element.addEventListener("touchend", onTouchEnd);
192
+ element.addEventListener("touchcancel", onTouchCancel);
193
+ return () => {
194
+ element.removeEventListener("touchstart", onTouchStart);
195
+ element.removeEventListener("touchmove", onTouchMove);
196
+ element.removeEventListener("touchend", onTouchEnd);
197
+ element.removeEventListener("touchcancel", onTouchCancel);
198
+ };
199
+ });
200
+
201
+ /**
202
+ * The height of the indicator: under the finger while pulling, at the
203
+ * threshold while the refresh runs. Where motion is unwanted it does not
204
+ * follow the finger: it is there, at full height, or it is not.
205
+ */
206
+ const indicatorHeight = $derived.by(() => {
207
+ if (refreshing) return threshold;
208
+ if (pulled === null) return 0;
209
+ return prefersReducedMotion() ? (pulled > 0 ? threshold : 0) : pulled;
210
+ });
211
+ </script>
212
+
213
+ <div
214
+ {...restProps}
215
+ bind:this={root}
216
+ class={cn("relative", className)}
217
+ aria-busy={refreshing ? "true" : undefined}
218
+ data-pull-to-refresh
219
+ data-refreshing={refreshing ? "true" : "false"}
220
+ >
221
+ <!-- In the page before it says anything, or the first announcement is lost. -->
222
+ <div class="sr-only" role="status" aria-live="polite" data-pull-status>{status}</div>
223
+
224
+ {#if showButton && !disabled}
225
+ <!-- Out of sight until keyboard focus reaches it: the list is what the region is for. -->
226
+ <button
227
+ type="button"
228
+ class="focus-ring sr-only cursor-pointer rounded-control bg-action-secondary text-sm font-medium text-headline hover:bg-action-secondary-hover active:bg-action-secondary-active focus-visible:not-sr-only focus-visible:absolute focus-visible:start-[8px] focus-visible:top-[8px] focus-visible:z-10 focus-visible:min-h-11 focus-visible:px-[16px]"
229
+ aria-disabled={refreshing ? "true" : undefined}
230
+ data-pull-button
231
+ onclick={() => void refresh()}
232
+ >
233
+ {text.refresh}
234
+ </button>
235
+ {/if}
236
+
237
+ <!-- Decorative: the status region and the button carry it for assistive technology. -->
238
+ <div
239
+ class={cn(
240
+ "flex items-end justify-center overflow-hidden text-sm text-description",
241
+ pulled === null && "transition-[height] duration-200 ease-out motion-reduce:transition-none",
242
+ )}
243
+ style:height="{indicatorHeight}px"
244
+ aria-hidden="true"
245
+ data-pull-indicator
246
+ data-armed={armed ? "true" : "false"}
247
+ >
248
+ <div class="flex h-[64px] shrink-0 items-center gap-[8px]">
249
+ {#if refreshing}
250
+ <Spinner size="md" />
251
+ <span>{text.refreshing}</span>
252
+ {:else}
253
+ <ArrowDown
254
+ size={16}
255
+ class={cn("transition-transform duration-150 motion-reduce:transition-none", armed && "rotate-180")}
256
+ />
257
+ <span>{armed ? text.release : text.pull}</span>
258
+ {/if}
259
+ </div>
260
+ </div>
261
+
262
+ {@render children?.()}
263
+ </div>
@@ -0,0 +1,52 @@
1
+ import type { Snippet } from "svelte";
2
+ import type { HTMLAttributes } from "svelte/elements";
3
+ import { type PullToRefreshStrings } from "../util/pull-to-refresh.js";
4
+ /**
5
+ * A list that reloads when it is pulled down from its top, on a touch
6
+ * screen.
7
+ *
8
+ * The pull is a shortcut. The same refresh is a button at the top of the
9
+ * region, out of sight until keyboard focus reaches it, and named for a
10
+ * screen reader; "Refreshing" and "Updated" are announced, and the
11
+ * region is `aria-busy` meanwhile.
12
+ *
13
+ * It only acts while what scrolls the list (the page, or the nearest
14
+ * scrolling ancestor, such as the content of an `AppShell`) is at its
15
+ * top, and never takes an ordinary scroll. The indicator is in the flow
16
+ * of the region, above the list, so under an app bar it comes out below
17
+ * the bar.
18
+ *
19
+ * ```svelte
20
+ * <PullToRefresh onrefresh={() => loadRounds()}>
21
+ * <List items={rounds} />
22
+ * </PullToRefresh>
23
+ * ```
24
+ */
25
+ type Props = Omit<HTMLAttributes<HTMLDivElement>, "class" | "children" | "aria-busy"> & {
26
+ /**
27
+ * Reloads the list. Return the promise: the indicator stays until it
28
+ * settles. A promise that rejects ends the refresh too, and nothing
29
+ * is announced as updated; say what went wrong yourself.
30
+ */
31
+ onrefresh?: () => Promise<void> | void;
32
+ /** Whether a refresh is running. Bindable: set it to show the indicator for a refresh of your own. */
33
+ refreshing?: boolean;
34
+ /** No pull and no button. */
35
+ disabled?: boolean;
36
+ /** How far the indicator has to come out for letting go to refresh, in px. */
37
+ threshold?: number;
38
+ /**
39
+ * The button that refreshes without the gesture. Without it the pull
40
+ * is the only way this component offers, and the app has to give
41
+ * another (WCAG 2.5.1).
42
+ */
43
+ showButton?: boolean;
44
+ /** The words the component says by itself, for another language. */
45
+ strings?: Partial<PullToRefreshStrings>;
46
+ class?: string;
47
+ /** The list. */
48
+ children?: Snippet;
49
+ };
50
+ declare const PullToRefresh: import("svelte").Component<Props, {}, "refreshing">;
51
+ type PullToRefresh = ReturnType<typeof PullToRefresh>;
52
+ export default PullToRefresh;
@@ -4,10 +4,13 @@
4
4
  RADIO_GROUP_CONTROL_SHELL,
5
5
  RADIO_GROUP_OPTION_LABEL_ROW,
6
6
  RADIO_GROUP_RING_OVERLAY,
7
+ SELECTION_CONTROL_INPUT,
7
8
  } from "../atoms/selection-control.styles";
9
+ import type { HTMLFieldsetAttributes } from "svelte/elements";
8
10
  import { generateId } from "../util/ssr-safe.js";
9
11
  import { SvelteMap } from "svelte/reactivity";
10
12
  import { cn } from "../util/cn.js";
13
+ import { resetValueOf, groupBinding } from "../util/hydration.js";
11
14
 
12
15
  export type RadioGroupOption = {
13
16
  value: string;
@@ -16,32 +19,63 @@
16
19
  description?: string;
17
20
  };
18
21
 
19
- interface Props {
22
+ /** Other attributes (`id`, `data-*`, `aria-*`, ...) land on the `<fieldset>`. */
23
+ type Props = Omit<HTMLFieldsetAttributes, "class" | "name" | "disabled"> & {
20
24
  /** Extra classes for the host element. */
21
25
  class?: string;
22
26
  options: RadioGroupOption[];
23
27
  /** Selected value; `bind:value`. Use `undefined` for no selection. */
24
28
  value?: string | undefined;
25
- /** Uncontrolled initial value. */
29
+ /**
30
+ * The selection to start with when `value` is `undefined` as the
31
+ * group is created. Applied once: it does not come back when the
32
+ * value is set to `undefined` later, and it never replaces a choice.
33
+ */
26
34
  defaultValue?: string | undefined;
35
+ /**
36
+ * Name the value is submitted under in a form. Without a name the
37
+ * group is not part of the form around it: it submits nothing and a
38
+ * form reset leaves it alone.
39
+ */
27
40
  name?: string;
28
41
  disabled?: boolean;
29
42
  legend?: string;
30
43
  label?: string;
31
- }
44
+ /**
45
+ * Draw a ring round the chosen row. Off, the filled radio alone shows
46
+ * the choice; keyboard focus keeps its ring either way.
47
+ */
48
+ chosenRing?: boolean;
49
+ };
32
50
 
33
51
  let {
34
52
  class: className = "",
35
53
  options,
36
54
  defaultValue,
37
- value = $bindable(defaultValue),
55
+ value = $bindable(),
38
56
  name: nameProp,
39
57
  disabled = false,
40
58
  legend = "",
41
59
  label = "",
60
+ chosenRing = true,
42
61
  ...restProps
43
62
  }: Props = $props();
44
63
 
64
+ // No fallback on the bindable prop: with one, `bind:value={undefined}`
65
+ // (which the prop's own documentation names as "no selection") throws
66
+ // `props_invalid_value` and the page never hydrates. The default is
67
+ // applied once, here, so the server renders it too. A choice made in the
68
+ // server markup before hydration is taken in after this and wins.
69
+ (() => {
70
+ if (value === undefined && defaultValue !== undefined) value = defaultValue;
71
+ })();
72
+
73
+ /**
74
+ * The radios always share a name, the caller's or one made here: without
75
+ * one they are not a group to the browser. With a name made here they are
76
+ * kept out of any form around them (`form` names a form that does not
77
+ * exist): it used to be submitted as `radiogroup-…`, a field nobody named.
78
+ */
45
79
  const fallbackName = generateId("radiogroup");
46
80
  const groupName = $derived(nameProp || fallbackName);
47
81
  const legendText = $derived(legend || label);
@@ -75,13 +109,24 @@
75
109
  return option.value === fallbackValue ? 0 : -1;
76
110
  }
77
111
 
78
- function handleChange(event: Event) {
79
- if (disabled) return;
80
- const target = event.target as HTMLInputElement;
81
- value = target.value;
82
- }
83
-
84
112
  const elementsByValue = new SvelteMap<string, HTMLInputElement>();
113
+
114
+ /**
115
+ * The radios are bound, so an option picked before the page hydrated is
116
+ * kept: Svelte's binding hands it over here instead of overwriting it
117
+ * (see util/hydration.ts). A form reset empties the selection, as it empties
118
+ * a bound native input.
119
+ */
120
+ const chosen = groupBinding<string>(
121
+ () => value,
122
+ (next) => {
123
+ if (!disabled) value = next;
124
+ },
125
+ () => {
126
+ if (!disabled) value = resetValueOf<string>(elementsByValue.values());
127
+ },
128
+ );
129
+
85
130
  function registerRadio(valueKey: string) {
86
131
  return (node: HTMLInputElement) => {
87
132
  elementsByValue.set(valueKey, node);
@@ -166,20 +211,28 @@
166
211
  {/if}
167
212
 
168
213
  <div class="space-y-3">
169
- {#each options as option (option.value)}
214
+ {#each options as option, index (option.value)}
170
215
  {@const optionDisabled = isOptionDisabled(option)}
171
- {@const isChecked = value === option.value}
172
- <label class={optionLabelWrapperClasses}>
173
- <span class={radioControlShellClasses}>
216
+ {@const descriptionId = option.description ? `${fallbackName}-${index}-description` : undefined}
217
+ <!-- A one-line row is centred in its height; with a description the radio stays at the top, by the label. -->
218
+ <label
219
+ class={cn(
220
+ optionLabelWrapperClasses,
221
+ !option.description && "items-center",
222
+ !chosenRing && "selection-control-option-row-quiet",
223
+ )}
224
+ >
225
+ <span class={cn(radioControlShellClasses, !option.description && "mt-0")}>
174
226
  <input
175
227
  type="radio"
176
228
  name={groupName}
229
+ form={nameProp ? undefined : groupName}
177
230
  value={option.value}
178
- checked={isChecked}
231
+ bind:group={chosen.value}
179
232
  disabled={optionDisabled}
180
233
  tabindex={tabIndexFor(option)}
181
- class="sr-only"
182
- onchange={handleChange}
234
+ aria-describedby={descriptionId}
235
+ class={SELECTION_CONTROL_INPUT}
183
236
  {@attach registerRadio(option.value)}
184
237
  />
185
238
  <span class={radioRingOverlayClasses}></span>
@@ -190,7 +243,8 @@
190
243
  {option.label}
191
244
  </span>
192
245
  {#if option.description}
193
- <span class="text-sm text-description">
246
+ <!-- aria-hidden keeps it out of the name; aria-describedby still reads it. -->
247
+ <span id={descriptionId} class="text-sm text-description" aria-hidden="true">
194
248
  {option.description}
195
249
  </span>
196
250
  {/if}
@@ -1,22 +1,38 @@
1
+ import type { HTMLFieldsetAttributes } from "svelte/elements";
1
2
  export type RadioGroupOption = {
2
3
  value: string;
3
4
  label: string;
4
5
  disabled?: boolean;
5
6
  description?: string;
6
7
  };
7
- interface Props {
8
+ /** Other attributes (`id`, `data-*`, `aria-*`, ...) land on the `<fieldset>`. */
9
+ type Props = Omit<HTMLFieldsetAttributes, "class" | "name" | "disabled"> & {
8
10
  /** Extra classes for the host element. */
9
11
  class?: string;
10
12
  options: RadioGroupOption[];
11
13
  /** Selected value; `bind:value`. Use `undefined` for no selection. */
12
14
  value?: string | undefined;
13
- /** Uncontrolled initial value. */
15
+ /**
16
+ * The selection to start with when `value` is `undefined` as the
17
+ * group is created. Applied once: it does not come back when the
18
+ * value is set to `undefined` later, and it never replaces a choice.
19
+ */
14
20
  defaultValue?: string | undefined;
21
+ /**
22
+ * Name the value is submitted under in a form. Without a name the
23
+ * group is not part of the form around it: it submits nothing and a
24
+ * form reset leaves it alone.
25
+ */
15
26
  name?: string;
16
27
  disabled?: boolean;
17
28
  legend?: string;
18
29
  label?: string;
19
- }
30
+ /**
31
+ * Draw a ring round the chosen row. Off, the filled radio alone shows
32
+ * the choice; keyboard focus keeps its ring either way.
33
+ */
34
+ chosenRing?: boolean;
35
+ };
20
36
  declare const RadioGroup: import("svelte").Component<Props, {}, "value">;
21
37
  type RadioGroup = ReturnType<typeof RadioGroup>;
22
38
  export default RadioGroup;
@@ -76,7 +76,7 @@
76
76
  case "muted":
77
77
  return "bg-base-50";
78
78
  case "accent":
79
- return "bg-brand-50 dark:bg-brand-950";
79
+ return "bg-brand-50";
80
80
  case "transparent":
81
81
  return "bg-transparent";
82
82
  default: