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,239 @@
1
+ <script lang="ts">
2
+ import ChevronDown from "@lucide/svelte/icons/chevron-down";
3
+ import type { Snippet } from "svelte";
4
+ import type { HTMLAnchorAttributes, HTMLButtonAttributes } from "svelte/elements";
5
+ import { cn } from "../util/cn.js";
6
+ import { fieldDescribedBy, fieldMessageState } from "../util/field.js";
7
+ import { FIELD_CONTROL_TRIGGER, fieldControlEdge, fieldControlSize } from "../util/field-control.js";
8
+ import { generateId } from "../util/ssr-safe.js";
9
+ import FieldMessages from "./FieldMessages.svelte";
10
+
11
+ /**
12
+ * A field-shaped trigger that opens whatever the app gives it, usually its
13
+ * own BottomSheet: the app owns the list, the search and the value. It
14
+ * looks like a Select of the same `size` and is one control: a `<button>`
15
+ * (a link with `href`) named by its label and its current value.
16
+ *
17
+ * Other attributes (`data-*`, `aria-*`, `onfocus`, ...) land on that
18
+ * element. The component does not open anything: `onclick` does, and the
19
+ * app sets `expanded` while its sheet is open.
20
+ */
21
+ type Props = Omit<
22
+ HTMLButtonAttributes,
23
+ | "class"
24
+ | "value"
25
+ | "name"
26
+ | "disabled"
27
+ | "type"
28
+ | "onclick"
29
+ | "aria-describedby"
30
+ | "aria-haspopup"
31
+ | "aria-expanded"
32
+ | "aria-controls"
33
+ | "children"
34
+ > & {
35
+ /** Extra classes for the host element. */
36
+ class?: string;
37
+ /** Id of the control. Omit to auto-generate. */
38
+ id?: string;
39
+ /** The label above the field. It is part of the control's name. */
40
+ label?: string;
41
+ /** The text of what is chosen. It is display text; `formValue` is what a form sends. */
42
+ value?: string;
43
+ /** Shown in the placeholder colour while there is no `value`. */
44
+ placeholder?: string;
45
+ /** An icon or an avatar before the text. */
46
+ leading?: Snippet;
47
+ /** Replaces the chevron at the end: a calendar or a clock, say. It is decoration, so it should be `aria-hidden`. */
48
+ trailing?: Snippet;
49
+ /** Replaces the value text, for rich content. The control is still named by `value`, so give that too. */
50
+ children?: Snippet;
51
+ size?: "sm" | "md" | "lg";
52
+ disabled?: boolean;
53
+ /** Status text under the field. Shown with a `success`, `warning` or `error` variant; for neutral help, use `hint`. */
54
+ message?: string;
55
+ variant?: "default" | "success" | "warning" | "error";
56
+ /** Help text under the field, read out with it. */
57
+ hint?: string;
58
+ /**
59
+ * An error under the field, announced. A button cannot take
60
+ * `aria-invalid`, so the error is the error edge colour and the
61
+ * described-by message; it wins over `variant` and `message`.
62
+ */
63
+ error?: string;
64
+ /** What the control opens: `aria-haspopup`. Default `"dialog"`. Not put on a link. */
65
+ haspopup?: "dialog" | "listbox" | "menu" | "true";
66
+ /** Whether what it opens is open now: `aria-expanded`, and the chevron turns. Leave it out and neither is set. Not put on a link. */
67
+ expanded?: boolean;
68
+ /** Id of what it opens: `aria-controls`. */
69
+ controls?: string;
70
+ /** Makes the control a link to this address, which works without scripts: a page that does the picking. With scripts, `onclick` may call `preventDefault()` and open a sheet instead. */
71
+ href?: string;
72
+ /** With `href`: where the link opens. */
73
+ target?: HTMLAnchorAttributes["target"];
74
+ /** With `href`: the link's relationship, such as `noopener`. */
75
+ rel?: HTMLAnchorAttributes["rel"];
76
+ /** The name a hidden input submits `formValue` under. Without it there is no hidden input. */
77
+ name?: string;
78
+ /** What the form submits for the choice, such as an id. */
79
+ formValue?: string;
80
+ /** The inner `<button>` (or `<a>`). Bindable: the app focuses it when its sheet closes, so a keyboard user is back where they were. */
81
+ element?: HTMLButtonElement | HTMLAnchorElement | null;
82
+ /** Ids of other elements that describe the field. The hint and the message are added after them. */
83
+ "aria-describedby"?: string | null;
84
+ onclick?: (event: MouseEvent) => void;
85
+ };
86
+
87
+ let {
88
+ class: className = "",
89
+ id: idProp,
90
+ label = "",
91
+ value = "",
92
+ placeholder = "",
93
+ leading,
94
+ trailing,
95
+ children,
96
+ size = "md",
97
+ disabled = false,
98
+ variant = "default",
99
+ message = "",
100
+ hint = "",
101
+ error = "",
102
+ haspopup = "dialog",
103
+ expanded,
104
+ controls,
105
+ href,
106
+ target,
107
+ rel,
108
+ name = "",
109
+ formValue = "",
110
+ element = $bindable(),
111
+ "aria-describedby": describedBy,
112
+ onclick,
113
+ ...restProps
114
+ }: Props = $props();
115
+
116
+ const fallbackId = generateId("picker-field");
117
+ const fieldId = $derived(idProp ?? fallbackId);
118
+ const labelId = $derived(`${fieldId}-label`);
119
+ const valueId = $derived(`${fieldId}-value`);
120
+
121
+ const isLink = $derived(href !== undefined && href !== null);
122
+ const status = $derived(fieldMessageState({ variant, message, hint, error }));
123
+ const isEmpty = $derived(value === "");
124
+ const sizeClass = $derived(fieldControlSize(size));
125
+
126
+ const controlClasses = $derived(
127
+ cn(
128
+ FIELD_CONTROL_TRIGGER,
129
+ sizeClass.box,
130
+ sizeClass.text,
131
+ fieldControlEdge(status.variant),
132
+ // `disabled:` does not match an `<a>`: a disabled link wears the pair itself.
133
+ isLink && disabled && "cursor-not-allowed border-input-border bg-input-disabled text-action-disabled-text hover:bg-input-disabled active:bg-input-disabled",
134
+ ),
135
+ );
136
+
137
+ /**
138
+ * The name is the label and the value (the placeholder while there is
139
+ * none), as a Select's is. Without a label the content names it. A
140
+ * caller's own `aria-label` or `aria-labelledby` wins.
141
+ */
142
+ const labelledBy = $derived(label ? `${labelId} ${valueId}` : undefined);
143
+
144
+ /** A disabled link has no `href`, but a pointer can still press it. */
145
+ function handleLinkClick(event: MouseEvent) {
146
+ if (disabled) {
147
+ event.preventDefault();
148
+ event.stopPropagation();
149
+ return;
150
+ }
151
+ onclick?.(event);
152
+ }
153
+ </script>
154
+
155
+ {#snippet content()}
156
+ {#if leading}
157
+ <span class="flex shrink-0 items-center" data-picker-field-leading>{@render leading()}</span>
158
+ {/if}
159
+ <!-- A value has no colour class of its own, and a disabled control none
160
+ at all: the control's `text-body` and its disabled colour are inherited
161
+ (a colour class here beat the disabled one in Select). -->
162
+ <span
163
+ id={valueId}
164
+ class={cn("min-w-0 flex-1 truncate text-start", isEmpty && !disabled && !children && "text-input-placeholder")}
165
+ >
166
+ {#if children}
167
+ {@render children()}
168
+ {:else}
169
+ {isEmpty ? placeholder : value}
170
+ {/if}
171
+ </span>
172
+ {#if trailing}
173
+ <span class="flex shrink-0 items-center text-description" data-picker-field-trailing>{@render trailing()}</span>
174
+ {:else}
175
+ <ChevronDown
176
+ size={20}
177
+ class={cn(
178
+ "shrink-0 text-description transition-transform duration-(--duration-moderate) motion-reduce:transition-none",
179
+ expanded && "rotate-180",
180
+ )}
181
+ aria-hidden="true"
182
+ />
183
+ {/if}
184
+ {/snippet}
185
+
186
+ <div class={cn("w-full min-w-0", className)}>
187
+ {#if label}
188
+ {#if isLink}
189
+ <!-- A link cannot be a label's control. -->
190
+ <span id={labelId} class="mb-2 block text-sm font-medium text-label">{label}</span>
191
+ {:else}
192
+ <label id={labelId} for={fieldId} class="mb-2 block text-sm font-medium text-label">{label}</label>
193
+ {/if}
194
+ {/if}
195
+
196
+ {#if isLink}
197
+ <!-- With `href` the control is a link with its role left native, and
198
+ no `aria-haspopup` or `aria-expanded`: it goes to a page. Disabled, it
199
+ has no `href` and says it is unavailable, as a disabled Button link. -->
200
+ <a
201
+ bind:this={element}
202
+ id={fieldId}
203
+ href={disabled ? undefined : href}
204
+ {target}
205
+ {rel}
206
+ class={controlClasses}
207
+ role={disabled ? "link" : undefined}
208
+ aria-disabled={disabled ? "true" : undefined}
209
+ aria-labelledby={labelledBy}
210
+ aria-describedby={fieldDescribedBy(fieldId, status, describedBy)}
211
+ {...(restProps as unknown as HTMLAnchorAttributes)}
212
+ onclick={handleLinkClick}
213
+ >
214
+ {@render content()}
215
+ </a>
216
+ {:else}
217
+ <button
218
+ bind:this={element}
219
+ type="button"
220
+ id={fieldId}
221
+ {disabled}
222
+ class={controlClasses}
223
+ aria-haspopup={haspopup}
224
+ aria-expanded={expanded}
225
+ aria-controls={controls}
226
+ aria-labelledby={labelledBy}
227
+ aria-describedby={fieldDescribedBy(fieldId, status, describedBy)}
228
+ {...restProps}
229
+ {onclick}
230
+ >
231
+ {@render content()}
232
+ </button>
233
+ {/if}
234
+
235
+ {#if name}
236
+ <input type="hidden" {name} value={formValue} {disabled} />
237
+ {/if}
238
+ <FieldMessages {fieldId} {status} {hint} gap="mt-1" messageClass="w-full" />
239
+ </div>
@@ -0,0 +1,67 @@
1
+ import type { Snippet } from "svelte";
2
+ import type { HTMLAnchorAttributes, HTMLButtonAttributes } from "svelte/elements";
3
+ /**
4
+ * A field-shaped trigger that opens whatever the app gives it, usually its
5
+ * own BottomSheet: the app owns the list, the search and the value. It
6
+ * looks like a Select of the same `size` and is one control: a `<button>`
7
+ * (a link with `href`) named by its label and its current value.
8
+ *
9
+ * Other attributes (`data-*`, `aria-*`, `onfocus`, ...) land on that
10
+ * element. The component does not open anything: `onclick` does, and the
11
+ * app sets `expanded` while its sheet is open.
12
+ */
13
+ type Props = Omit<HTMLButtonAttributes, "class" | "value" | "name" | "disabled" | "type" | "onclick" | "aria-describedby" | "aria-haspopup" | "aria-expanded" | "aria-controls" | "children"> & {
14
+ /** Extra classes for the host element. */
15
+ class?: string;
16
+ /** Id of the control. Omit to auto-generate. */
17
+ id?: string;
18
+ /** The label above the field. It is part of the control's name. */
19
+ label?: string;
20
+ /** The text of what is chosen. It is display text; `formValue` is what a form sends. */
21
+ value?: string;
22
+ /** Shown in the placeholder colour while there is no `value`. */
23
+ placeholder?: string;
24
+ /** An icon or an avatar before the text. */
25
+ leading?: Snippet;
26
+ /** Replaces the chevron at the end: a calendar or a clock, say. It is decoration, so it should be `aria-hidden`. */
27
+ trailing?: Snippet;
28
+ /** Replaces the value text, for rich content. The control is still named by `value`, so give that too. */
29
+ children?: Snippet;
30
+ size?: "sm" | "md" | "lg";
31
+ disabled?: boolean;
32
+ /** Status text under the field. Shown with a `success`, `warning` or `error` variant; for neutral help, use `hint`. */
33
+ message?: string;
34
+ variant?: "default" | "success" | "warning" | "error";
35
+ /** Help text under the field, read out with it. */
36
+ hint?: string;
37
+ /**
38
+ * An error under the field, announced. A button cannot take
39
+ * `aria-invalid`, so the error is the error edge colour and the
40
+ * described-by message; it wins over `variant` and `message`.
41
+ */
42
+ error?: string;
43
+ /** What the control opens: `aria-haspopup`. Default `"dialog"`. Not put on a link. */
44
+ haspopup?: "dialog" | "listbox" | "menu" | "true";
45
+ /** Whether what it opens is open now: `aria-expanded`, and the chevron turns. Leave it out and neither is set. Not put on a link. */
46
+ expanded?: boolean;
47
+ /** Id of what it opens: `aria-controls`. */
48
+ controls?: string;
49
+ /** Makes the control a link to this address, which works without scripts: a page that does the picking. With scripts, `onclick` may call `preventDefault()` and open a sheet instead. */
50
+ href?: string;
51
+ /** With `href`: where the link opens. */
52
+ target?: HTMLAnchorAttributes["target"];
53
+ /** With `href`: the link's relationship, such as `noopener`. */
54
+ rel?: HTMLAnchorAttributes["rel"];
55
+ /** The name a hidden input submits `formValue` under. Without it there is no hidden input. */
56
+ name?: string;
57
+ /** What the form submits for the choice, such as an id. */
58
+ formValue?: string;
59
+ /** The inner `<button>` (or `<a>`). Bindable: the app focuses it when its sheet closes, so a keyboard user is back where they were. */
60
+ element?: HTMLButtonElement | HTMLAnchorElement | null;
61
+ /** Ids of other elements that describe the field. The hint and the message are added after them. */
62
+ "aria-describedby"?: string | null;
63
+ onclick?: (event: MouseEvent) => void;
64
+ };
65
+ declare const PickerField: import("svelte").Component<Props, {}, "element">;
66
+ type PickerField = ReturnType<typeof PickerField>;
67
+ export default PickerField;
@@ -1,13 +1,35 @@
1
1
  <script lang="ts">
2
+ import { isDevBuild } from "../util/app-shell.js";
3
+ import {
4
+ PROGRESS_STRINGS,
5
+ canSegment,
6
+ filledSegments,
7
+ type ProgressStrings,
8
+ } from "../util/progress.js";
9
+ import { mergeStrings } from "../util/ready-made-strings.js";
2
10
  import { generateId } from "../util/ssr-safe.js";
11
+ import { zabiStringsFor } from "../util/zabi-strings.js";
3
12
 
4
13
  interface Props {
5
14
  /** Extra classes for the host element. */
6
15
  class?: string;
7
16
  value?: number;
8
17
  max?: number;
9
- size?: "sm" | "md" | "lg";
18
+ /** Height of the bar: 4, 8, 12 and 16px. */
19
+ size?: "sm" | "md" | "lg" | "xl";
20
+ /**
21
+ * Draws `max` separate segments, `value` of them filled, for a count
22
+ * such as 4 of 19. `max` must be a whole number from 2 to 24; any
23
+ * other `max` draws the continuous bar.
24
+ */
25
+ segmented?: boolean;
26
+ /** Overrides for the built-in strings. */
27
+ strings?: Partial<ProgressStrings>;
10
28
  label?: string;
29
+ /** Names the progressbar when there is no visible `label`. Reaches the element with role="progressbar". */
30
+ "aria-label"?: string;
31
+ /** Points the progressbar at another element's id for its name. Reaches the element with role="progressbar". */
32
+ "aria-labelledby"?: string;
11
33
  }
12
34
 
13
35
  let {
@@ -15,43 +37,101 @@
15
37
  value = 0,
16
38
  max = 100,
17
39
  size = "md",
40
+ segmented = false,
41
+ strings,
18
42
  label = "",
43
+ "aria-label": ariaLabel,
44
+ "aria-labelledby": ariaLabelledby,
19
45
  ...restProps
20
46
  }: Props = $props();
21
47
 
22
48
  const progressId = generateId("progress");
49
+ const labelId = `${progressId}-label`;
23
50
 
24
- let percentage = $derived(Math.min(Math.max((value / max) * 100, 0), 100));
51
+ // A max that is not a positive, finite number would give an empty or full
52
+ // bar with aria-valuemax=0: fall back to the default.
53
+ let safeMax = $derived(Number.isFinite(max) && max > 0 ? max : 100);
54
+ let safeValue = $derived(
55
+ Number.isFinite(value) ? Math.min(Math.max(value, 0), safeMax) : 0,
56
+ );
57
+ let percentage = $derived((safeValue / safeMax) * 100);
58
+ let labelledby = $derived(
59
+ ariaLabelledby ?? (ariaLabel || !label ? undefined : labelId),
60
+ );
25
61
 
26
- let sizeClasses = $derived({
62
+ const sizeClasses = {
27
63
  sm: "h-1",
28
64
  md: "h-2",
29
65
  lg: "h-3",
66
+ xl: "h-4",
67
+ };
68
+
69
+ /** The app-wide words for this component, from a `ZabiStringsProvider` above it, if there is one. */
70
+ const provided = zabiStringsFor("progress");
71
+ const text = $derived(mergeStrings(PROGRESS_STRINGS, provided(), strings));
72
+
73
+ /** Segmented only where `max` can be drawn as segments; otherwise the continuous bar. */
74
+ let asSegments = $derived(segmented && canSegment(max));
75
+ let filled = $derived(filledSegments(value, safeMax));
76
+ let valueText = $derived(asSegments ? text.valueText(filled, safeMax) : undefined);
77
+
78
+ $effect(() => {
79
+ if (!isDevBuild() || !segmented || canSegment(max)) return;
80
+ console.warn(
81
+ "[zabi-components] Progress: `segmented` needs a whole-number `max` from 2 to 24; drawing the continuous bar instead.",
82
+ );
30
83
  });
31
84
  </script>
32
85
 
33
86
  <div class={className} {...restProps}>
34
87
  {#if label}
35
88
  <div class="flex justify-between items-center mb-2">
36
- <label for={progressId} class="text-sm font-medium text-label"
37
- >{label}</label
89
+ <!-- A span named through aria-labelledby, not a label: `for` only
90
+ names form controls, so it left the progressbar without a name. -->
91
+ <span id={labelId} class="text-sm font-medium text-label"
92
+ >{label}</span
38
93
  >
39
- <span class="text-sm text-caption">{Math.round(percentage)}%</span>
94
+ <span class="text-sm text-caption">{asSegments ? valueText : `${Math.round(percentage)}%`}</span>
40
95
  </div>
41
96
  {/if}
42
97
 
43
- <div
44
- id={progressId}
45
- class="w-full border border-input-border bg-input rounded-full overflow-hidden {sizeClasses[size]}"
46
- role="progressbar"
47
- aria-valuenow={value}
48
- aria-valuemin="0"
49
- aria-valuemax={max}
50
- {...restProps}
51
- >
98
+ {#if asSegments}
52
99
  <div
53
- class="h-full bg-brand-600 rounded-full"
54
- style="width: {percentage}%"
55
- ></div>
56
- </div>
100
+ id={progressId}
101
+ class="flex w-full {safeMax > 12 ? 'gap-[2px]' : 'gap-1'} {sizeClasses[size]}"
102
+ role="progressbar"
103
+ aria-label={ariaLabel}
104
+ aria-labelledby={labelledby}
105
+ aria-valuenow={filled}
106
+ aria-valuemin="0"
107
+ aria-valuemax={safeMax}
108
+ aria-valuetext={valueText}
109
+ >
110
+ {#each { length: safeMax } as _, index (index)}
111
+ <!-- Presentational: the count is said once, by the progressbar. -->
112
+ <span
113
+ class="h-full flex-1 min-w-0 rounded-full {index < filled
114
+ ? 'bg-progress-fill forced-colors:bg-[Highlight]'
115
+ : 'bg-progress-track border border-progress-track-border forced-colors:border-[CanvasText]'}"
116
+ aria-hidden="true"
117
+ ></span>
118
+ {/each}
119
+ </div>
120
+ {:else}
121
+ <div
122
+ id={progressId}
123
+ class="w-full border border-progress-track-border bg-progress-track rounded-full overflow-hidden {sizeClasses[size]}"
124
+ role="progressbar"
125
+ aria-label={ariaLabel}
126
+ aria-labelledby={labelledby}
127
+ aria-valuenow={safeValue}
128
+ aria-valuemin="0"
129
+ aria-valuemax={safeMax}
130
+ >
131
+ <div
132
+ class="h-full bg-progress-fill rounded-full"
133
+ style="width: {percentage}%"
134
+ ></div>
135
+ </div>
136
+ {/if}
57
137
  </div>
@@ -1,10 +1,24 @@
1
+ import { type ProgressStrings } from "../util/progress.js";
1
2
  interface Props {
2
3
  /** Extra classes for the host element. */
3
4
  class?: string;
4
5
  value?: number;
5
6
  max?: number;
6
- size?: "sm" | "md" | "lg";
7
+ /** Height of the bar: 4, 8, 12 and 16px. */
8
+ size?: "sm" | "md" | "lg" | "xl";
9
+ /**
10
+ * Draws `max` separate segments, `value` of them filled, for a count
11
+ * such as 4 of 19. `max` must be a whole number from 2 to 24; any
12
+ * other `max` draws the continuous bar.
13
+ */
14
+ segmented?: boolean;
15
+ /** Overrides for the built-in strings. */
16
+ strings?: Partial<ProgressStrings>;
7
17
  label?: string;
18
+ /** Names the progressbar when there is no visible `label`. Reaches the element with role="progressbar". */
19
+ "aria-label"?: string;
20
+ /** Points the progressbar at another element's id for its name. Reaches the element with role="progressbar". */
21
+ "aria-labelledby"?: string;
8
22
  }
9
23
  declare const Progress: import("svelte").Component<Props, {}, "">;
10
24
  type Progress = ReturnType<typeof Progress>;
@@ -1,9 +1,16 @@
1
1
  <script lang="ts">
2
+ import type { Snippet } from "svelte";
3
+ import type { HTMLInputAttributes } from "svelte/elements";
4
+ import type { SemanticVariant } from "../types/variants.js";
2
5
  import SelectionControl from "./SelectionControl.svelte";
3
6
  import type { SelectionControlMarkProps } from "./SelectionControl.svelte";
4
7
  import { RADIO_CHECKED_DOT_CLASSES } from "./selection-control.styles";
5
8
 
6
- interface Props {
9
+ /** Other attributes (`required`, `data-*`, `aria-*`, ...) land on the `<input>`. */
10
+ type Props = Omit<
11
+ HTMLInputAttributes,
12
+ "class" | "id" | "name" | "value" | "disabled" | "checked" | "type" | "onchange"
13
+ > & {
7
14
  /** Extra classes for the host element. */
8
15
  class?: string;
9
16
  id?: string;
@@ -15,7 +22,31 @@
15
22
  checked?: boolean;
16
23
  onChange?: (event: Event) => void;
17
24
  onchange?: (event: Event) => void;
18
- }
25
+ /**
26
+ * Drawn inside the one label, between the box and the label text, as
27
+ * decoration for the name `label` already gives. A leading image
28
+ * should have an empty alt: the label names the row.
29
+ */
30
+ leading?: Snippet;
31
+ /**
32
+ * A line under the label, tied to the radio with `aria-describedby`.
33
+ * The label names the radio; the description does not join the name.
34
+ */
35
+ description?: string;
36
+ /**
37
+ * Where the radio sits in the row. `end` puts it after the leading,
38
+ * the label and the description, at the far edge; the row is still
39
+ * one label and fills the width it is given.
40
+ */
41
+ controlPosition?: "start" | "end";
42
+ variant?: SemanticVariant;
43
+ /** Status text under the control. Shown with a `success`, `warning` or `error` variant; for neutral help, use `hint`. */
44
+ message?: string;
45
+ /** Help text under the control, read out with it. */
46
+ hint?: string;
47
+ /** An error under the control. It marks the input invalid and is announced; it wins over `variant` and `message`. */
48
+ error?: string;
49
+ };
19
50
 
20
51
  let {
21
52
  class: className = "",
@@ -25,11 +56,25 @@
25
56
  label = "",
26
57
  disabled = false,
27
58
  defaultChecked = false,
28
- checked = $bindable(defaultChecked),
59
+ checked = $bindable<Exclude<Props["checked"], undefined>>(),
29
60
  onChange,
30
61
  onchange,
62
+ leading,
63
+ description,
64
+ controlPosition = "start",
31
65
  ...restProps
32
66
  }: Props = $props();
67
+
68
+ // No fallback on a bindable prop: Svelte refuses `bind:…={undefined}` on
69
+ // one that has a fallback (`props_invalid_value`), and a page that throws
70
+ // while it hydrates never becomes interactive. The default is applied
71
+ // here instead: at once, for the server and the first render, and again
72
+ // whenever a parent hands back `undefined`.
73
+ const applyDefaults = () => {
74
+ if (checked === undefined) checked = defaultChecked;
75
+ };
76
+ applyDefaults();
77
+ $effect.pre(applyDefaults);
33
78
  </script>
34
79
 
35
80
  {#snippet mark(_props: SelectionControlMarkProps)}
@@ -49,6 +94,9 @@
49
94
  {onChange}
50
95
  {onchange}
51
96
  {mark}
97
+ {leading}
98
+ {description}
99
+ {controlPosition}
52
100
  class={className}
53
101
  {...restProps}
54
102
  />
@@ -1,4 +1,8 @@
1
- interface Props {
1
+ import type { Snippet } from "svelte";
2
+ import type { HTMLInputAttributes } from "svelte/elements";
3
+ import type { SemanticVariant } from "../types/variants.js";
4
+ /** Other attributes (`required`, `data-*`, `aria-*`, ...) land on the `<input>`. */
5
+ type Props = Omit<HTMLInputAttributes, "class" | "id" | "name" | "value" | "disabled" | "checked" | "type" | "onchange"> & {
2
6
  /** Extra classes for the host element. */
3
7
  class?: string;
4
8
  id?: string;
@@ -10,7 +14,31 @@ interface Props {
10
14
  checked?: boolean;
11
15
  onChange?: (event: Event) => void;
12
16
  onchange?: (event: Event) => void;
13
- }
17
+ /**
18
+ * Drawn inside the one label, between the box and the label text, as
19
+ * decoration for the name `label` already gives. A leading image
20
+ * should have an empty alt: the label names the row.
21
+ */
22
+ leading?: Snippet;
23
+ /**
24
+ * A line under the label, tied to the radio with `aria-describedby`.
25
+ * The label names the radio; the description does not join the name.
26
+ */
27
+ description?: string;
28
+ /**
29
+ * Where the radio sits in the row. `end` puts it after the leading,
30
+ * the label and the description, at the far edge; the row is still
31
+ * one label and fills the width it is given.
32
+ */
33
+ controlPosition?: "start" | "end";
34
+ variant?: SemanticVariant;
35
+ /** Status text under the control. Shown with a `success`, `warning` or `error` variant; for neutral help, use `hint`. */
36
+ message?: string;
37
+ /** Help text under the control, read out with it. */
38
+ hint?: string;
39
+ /** An error under the control. It marks the input invalid and is announced; it wins over `variant` and `message`. */
40
+ error?: string;
41
+ };
14
42
  declare const Radio: import("svelte").Component<Props, {}, "checked">;
15
43
  type Radio = ReturnType<typeof Radio>;
16
44
  export default Radio;