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
@@ -1,25 +1,105 @@
1
+ import { type Snippet } from "svelte";
1
2
  import type { HTMLAttributes } from "svelte/elements";
3
+ import type { ButtonSize, ButtonVariant } from "../types/variants.js";
2
4
  export type ImageUploadFileDetail = {
3
5
  /** Selected file, or `null` when the image is removed. */
4
6
  file: File | null;
5
7
  /** Object URL used for the preview, or `null`. */
6
8
  url: string | null;
7
9
  };
8
- type Props = Omit<HTMLAttributes<HTMLDivElement>, "onchange" | "onclick"> & {
10
+ export type ImageUploadPreviewType = "image" | "video";
11
+ export type ImageUploadActionsPlacement = "overlay" | "strip";
12
+ export type ImageUploadVariant = "dropzone" | "button";
13
+ /**
14
+ * Why a file was turned away: `accept` does not allow it, it is over
15
+ * `maxSize`, or (only with `multiple` and `maxFiles`) it is one too many.
16
+ */
17
+ export type ImageUploadRejectReason = "type" | "size" | "count";
18
+ export type ImageUploadPreviewDetail = {
19
+ /** The current `value`. */
20
+ url: string;
21
+ /** What the built-in preview would have rendered. */
22
+ type: ImageUploadPreviewType;
23
+ alt: string;
24
+ };
25
+ type Props = Omit<HTMLAttributes<HTMLDivElement>, "onchange" | "onclick" | "id"> & {
9
26
  /** Extra classes for the host element. */
10
27
  class?: string;
28
+ /**
29
+ * `dropzone` (default): the drop area, and the preview with Change and
30
+ * Remove once there is a value. `button`: only a button that opens the
31
+ * file chooser, for a row of choices; no drop area, no preview and no
32
+ * Remove. The picked file comes through `onfileselect` and `bind:value`,
33
+ * and the app shows it where it wants.
34
+ */
35
+ variant?: ImageUploadVariant;
36
+ /** `variant="button"`: the trigger's `Button` variant. */
37
+ buttonVariant?: ButtonVariant;
38
+ /** `variant="button"`: the trigger's `Button` size. */
39
+ buttonSize?: ButtonSize;
40
+ /** The largest file taken, in bytes. A larger one goes to `onfilereject` with `"size"`. */
41
+ maxSize?: number;
42
+ /**
43
+ * The chooser and a drop take several files, handed over together
44
+ * through `onfiles`, in the order they were chosen. The component
45
+ * then keeps none of them: no preview, `value` is not set and
46
+ * `onfileselect` is not called. The page shows them where it wants
47
+ * (a `PhotoGrid`, say).
48
+ */
49
+ multiple?: boolean;
50
+ /** With `multiple`: the most files taken in one go. The rest go to `onfilereject` with `"count"`. */
51
+ maxFiles?: number;
52
+ /** `variant="button"`: the trigger's content, in place of `label`. */
53
+ children?: Snippet;
54
+ /** Id of the control the label points at; generated when omitted. */
55
+ id?: string;
56
+ /** Visible label, associated with the dropzone. With `variant="button"` it is the button's text. */
57
+ label?: string;
11
58
  /** Preview URL; `bind:value` to read it. */
12
59
  value?: string | null;
13
60
  disabled?: boolean;
14
61
  accept?: string;
15
62
  placeholder?: string;
63
+ /** Second line of the dropzone. */
64
+ browseText?: string;
65
+ changeText?: string;
66
+ removeText?: string;
67
+ /** Accessible name of the Change action; defaults to `changeText` plus `label`. */
68
+ changeLabel?: string;
69
+ /** Accessible name of the Remove action; defaults to `removeText` plus `label`. */
70
+ removeLabel?: string;
71
+ /** Text alternative for the preview. */
72
+ alt?: string;
73
+ /** Forces the preview kind when the URL has no extension to go by. */
74
+ previewType?: ImageUploadPreviewType;
75
+ /** Replaces the built-in `<img>` / `<video>` preview. */
76
+ preview?: Snippet<[ImageUploadPreviewDetail]>;
77
+ /**
78
+ * Where Change and Remove sit: over the whole preview, or in a strip
79
+ * along its top edge. Defaults to the strip for a video, whose controls
80
+ * an overlay would cover, and to the overlay otherwise.
81
+ */
82
+ actionsPlacement?: ImageUploadActionsPlacement;
83
+ /** Announced to screen readers when a file or URL is set. */
84
+ selectedText?: string;
85
+ /** Announced to screen readers when the value is cleared. */
86
+ removedText?: string;
16
87
  errorMessage?: string;
88
+ errorTitle?: string;
89
+ /** Closing line of the error block; `false` or `""` leaves it out. */
90
+ errorRecovery?: string | false;
17
91
  /** Native `change` event from the hidden file input. */
18
92
  onchange?: (event: Event) => void;
19
- /** Fires when the file chooser is opened. */
93
+ /** Fires before the file chooser opens; `event.preventDefault()` keeps it closed. */
20
94
  onclick?: (event: Event) => void;
95
+ /** Replaces the native file chooser, for a media library or another source. */
96
+ onbrowse?: (event: Event) => void;
21
97
  /** Selected file and preview URL; `{ file: null, url: null }` on remove. */
22
98
  onfileselect?: (detail: ImageUploadFileDetail) => void;
99
+ /** A dropped file that `accept` does not allow, or a dropped or chosen file over `maxSize`. */
100
+ onfilereject?: (file: File, reason: ImageUploadRejectReason) => void;
101
+ /** With `multiple`: every file that was taken, in order. Not called with none. */
102
+ onfiles?: (files: File[]) => void;
23
103
  };
24
104
  declare const ImageUpload: import("svelte").Component<Props, {}, "value">;
25
105
  type ImageUpload = ReturnType<typeof ImageUpload>;
@@ -0,0 +1,459 @@
1
+ <script lang="ts">
2
+ import type { HTMLAttributes } from "svelte/elements";
3
+ import Table from "../atoms/Table.svelte";
4
+ import { cn } from "../util/cn.js";
5
+ import {
6
+ CHART_GLASS,
7
+ chartColors,
8
+ chartFormatter,
9
+ chartMarker,
10
+ chartScale,
11
+ chartTextScale,
12
+ labelEvery,
13
+ measureWidth,
14
+ widestText,
15
+ linePath,
16
+ markerPath,
17
+ type ChartFormat,
18
+ type ChartSeries,
19
+ } from "../util/chart.js";
20
+
21
+ /**
22
+ * A line chart for one or a few series over shared x labels, drawn as
23
+ * plain SVG.
24
+ *
25
+ * It is a `figure`: the `label` is its caption, the drawing is hidden
26
+ * from assistive technology, and the same numbers are in a real table
27
+ * (off screen unless `showTable`). Each series has its own marker shape
28
+ * as well as its own colour. Pointing at or tapping the plot shows the
29
+ * values at that x label in a small pane of the library's thick material
30
+ * that floats over the plot beside the guide, as a Tooltip does.
31
+ *
32
+ * The six series colours are `--zabi-chart-1` to `--zabi-chart-6`, set on
33
+ * the chart or on anything around it; they default to colours made from
34
+ * theme tokens that follow light and dark. Each marker has a ring cut out
35
+ * of the lines around it, so it shows whatever the chart stands on;
36
+ * `--zabi-chart-surface` paints that ring a colour of your own.
37
+ */
38
+ type Props = Omit<HTMLAttributes<HTMLElement>, "class"> & {
39
+ /** The lines: a `name` and one value per x label (`null` leaves a gap). Up to six keep a colour of their own. */
40
+ series: ChartSeries[];
41
+ /** The labels along the x axis, one per point. */
42
+ xLabels?: string[];
43
+ /** The bottom of the y axis. Without it, the lowest value rounded down to a tick. */
44
+ yMin?: number;
45
+ /** The top of the y axis. Without it, the highest value rounded up to a tick. */
46
+ yMax?: number;
47
+ /** How a value is written: `number` (default), `percent` (72 is "72 %"), or a function. */
48
+ yFormat?: ChartFormat;
49
+ /** Height of the drawing in px. The width is the container's. */
50
+ height?: number;
51
+ /** The caption, and what the chart is called. */
52
+ label: string;
53
+ /** Keeps the caption for assistive technology and takes it off the screen. */
54
+ labelHidden?: boolean;
55
+ /** The key under the plot. Without it, shown when there is more than one series. */
56
+ legend?: boolean;
57
+ /** A marker on every point, a different shape per series. */
58
+ markers?: boolean;
59
+ /** Shows the data table under the chart; otherwise it is there for assistive technology only. */
60
+ showTable?: boolean;
61
+ /** The heading of the table's first column (what the x labels are: "Week"). */
62
+ xTitle?: string;
63
+ /** The language of the built-in number formats. Without it, the runtime's. */
64
+ locale?: string;
65
+ /** Stands the chart on a panel of the thick material (frosted glass), for a chart that floats over a wash, a tint or a picture. On a plain card it shows nothing: leave it off there. */
66
+ glass?: boolean;
67
+ class?: string;
68
+ };
69
+
70
+ let {
71
+ series,
72
+ xLabels = [],
73
+ yMin,
74
+ yMax,
75
+ yFormat = "number",
76
+ height = 240,
77
+ label,
78
+ labelHidden = false,
79
+ legend,
80
+ markers = true,
81
+ showTable = false,
82
+ xTitle = "",
83
+ locale,
84
+ glass = false,
85
+ class: className = "",
86
+ ...restProps
87
+ }: Props = $props();
88
+
89
+ const uid = $props.id();
90
+ const maskId = `${uid}-rings`;
91
+
92
+ /** Before it is measured (on the server) the drawing is laid out this wide and scaled to fit. */
93
+ const FALLBACK_WIDTH = 600;
94
+ const TOP = 8;
95
+ /** Room at each end of the plot, so the first and last markers stand inside it. */
96
+ const INSET = 8;
97
+ const MARKER = 4;
98
+
99
+ let measured = $state(0);
100
+ let tickWidth = $state(0);
101
+ let active = $state<number | null>(null);
102
+
103
+ const width = $derived(measured > 0 ? measured : FALLBACK_WIDTH);
104
+ /** Chart text is set in rem; the room for it grows with the reader's text size. */
105
+ const rem = $derived(measured > 0 ? chartTextScale() : 1);
106
+ const plotHeight = $derived(Math.max(height, 80));
107
+ const bottom = $derived(Math.round(28 * rem));
108
+ const format = $derived(chartFormatter(yFormat, locale));
109
+ const count = $derived(Math.max(xLabels.length, ...series.map((line) => line.points.length), 0));
110
+ const scale = $derived(chartScale(series.flatMap((line) => line.points), { min: yMin, max: yMax }));
111
+ const tickLabels = $derived(scale.ticks.map((tick) => format(tick)));
112
+ /** The value axis takes the width of its widest label as drawn; until that is known, an estimate. */
113
+ const left = $derived((tickWidth || Math.max(...tickLabels.map((label) => label.length), 1) * 7 * rem) + 12);
114
+ const innerWidth = $derived(Math.max(width - left, 10));
115
+ const innerHeight = $derived(Math.max(plotHeight - TOP - bottom, 10));
116
+ const span = $derived(Math.max(innerWidth - INSET * 2, 1));
117
+ const every = $derived(labelEvery(xLabels, span, 7 * rem));
118
+ const showLegend = $derived(legend ?? series.length > 1);
119
+ /** A marker on every point only while the points stand apart; closer than that they would run into a band. */
120
+ const roomForMarkers = $derived(count <= 1 || span / (count - 1) >= MARKER * 3);
121
+
122
+ const x = (index: number) => (count <= 1 ? left + innerWidth / 2 : left + INSET + (index * span) / (count - 1));
123
+ const y = (value: number) => TOP + innerHeight - ((value - scale.min) / (scale.max - scale.min)) * innerHeight;
124
+ const isValue = (value: unknown): value is number => typeof value === "number" && Number.isFinite(value);
125
+
126
+ const colors = $derived(chartColors(series.map((line) => line.color)));
127
+ const lines = $derived(
128
+ series.map((line, index) => {
129
+ const points = Array.from({ length: count }, (_, at) => {
130
+ const value = line.points[at];
131
+ return isValue(value) ? { x: x(at), y: y(value) } : null;
132
+ });
133
+ return {
134
+ name: line.name,
135
+ color: colors[index],
136
+ marker: chartMarker(index),
137
+ points,
138
+ path: linePath(points),
139
+ };
140
+ }),
141
+ );
142
+
143
+ function nearest(event: PointerEvent) {
144
+ if (count === 0) return;
145
+ const box = (event.currentTarget as SVGSVGElement).getBoundingClientRect();
146
+ if (!(box.width > 0)) return;
147
+ const at = ((event.clientX - box.left) / box.width) * width;
148
+ const index = count <= 1 ? 0 : Math.round(((at - left - INSET) / span) * (count - 1));
149
+ active = Math.min(count - 1, Math.max(0, index));
150
+ }
151
+
152
+ /** A finger lifting leaves the values up; a mouse leaving takes them away. */
153
+ function leave(event: PointerEvent) {
154
+ if (event.pointerType === "mouse") active = null;
155
+ }
156
+ </script>
157
+
158
+ <figure
159
+ class={cn("zabi-chart relative m-0 flex flex-col gap-3", glass && CHART_GLASS, className)}
160
+ {...restProps}
161
+ >
162
+ <figcaption class={cn("text-label text-sm font-medium", labelHidden && "sr-only")}>{label}</figcaption>
163
+
164
+ <div class="relative w-full" use:measureWidth={(value) => (measured = value)}>
165
+ <svg
166
+ class="plot block w-full"
167
+ viewBox="0 0 {width} {plotHeight}"
168
+ height={plotHeight}
169
+ aria-hidden="true"
170
+ focusable="false"
171
+ onpointermove={nearest}
172
+ onpointerdown={nearest}
173
+ onpointerleave={leave}
174
+ >
175
+ <g use:widestText={{ onwidth: (value) => (tickWidth = value), key: [tickLabels, measured] }}>
176
+ {#each scale.ticks as tick, index (tick)}
177
+ <line class="grid" class:axis={index === 0} x1={left} x2={left + innerWidth} y1={y(tick)} y2={y(tick)} />
178
+ <text class="tick" x={left - 12} y={y(tick)} text-anchor="end" dominant-baseline="central">
179
+ {tickLabels[index]}
180
+ </text>
181
+ {/each}
182
+ </g>
183
+
184
+ {#each xLabels as text, index (index)}
185
+ {#if index % every === 0 && index < count}
186
+ <text
187
+ class="tick"
188
+ class:on={index === active}
189
+ x={count > 1 && index === 0 ? left : count > 1 && index === count - 1 ? left + innerWidth : x(index)}
190
+ y={plotHeight - bottom + 20 * rem}
191
+ text-anchor={count > 1 && index === 0 ? "start" : count > 1 && index === count - 1 ? "end" : "middle"}
192
+ >
193
+ {text}
194
+ </text>
195
+ {/if}
196
+ {/each}
197
+
198
+ {#if active !== null}
199
+ <line class="guide" x1={x(active)} x2={x(active)} y1={TOP} y2={TOP + innerHeight} />
200
+ {/if}
201
+
202
+ <!-- A ring is cut out of the lines around every marker, so what shows in it is
203
+ whatever the chart stands on: a card, a tint, a pane of glass. -->
204
+ <mask id={maskId} maskUnits="userSpaceOnUse" x="0" y="0" {width} height={plotHeight}>
205
+ <rect {width} height={plotHeight} fill="white" />
206
+ {#each lines as line, lineIndex (lineIndex)}
207
+ {#each line.points as point, index (index)}
208
+ {#if point && ((markers && roomForMarkers) || index === active)}
209
+ <path
210
+ class="ring"
211
+ d={markerPath(line.marker, point.x, point.y, index === active ? MARKER + 1.5 : MARKER)}
212
+ />
213
+ {/if}
214
+ {/each}
215
+ {/each}
216
+ </mask>
217
+ <g mask="url(#{maskId})">
218
+ {#each lines as line, lineIndex (lineIndex)}
219
+ <g class="series" style:--_c={line.color}>
220
+ <path class="line" d={line.path} />
221
+ </g>
222
+ {/each}
223
+ </g>
224
+ {#each lines as line, lineIndex (lineIndex)}
225
+ <g class="marks" style:--_c={line.color}>
226
+ {#each line.points as point, index (index)}
227
+ {#if point && ((markers && roomForMarkers) || index === active)}
228
+ <path
229
+ class="marker"
230
+ d={markerPath(line.marker, point.x, point.y, index === active ? MARKER + 1.5 : MARKER)}
231
+ />
232
+ {/if}
233
+ {/each}
234
+ </g>
235
+ {/each}
236
+ </svg>
237
+
238
+ <!-- The values at the x label pointed at: a pane of the same material as a Tooltip, over the
239
+ plot and beside the guide, on the side with more room. The table says the same to
240
+ assistive technology. -->
241
+ {#if active !== null}
242
+ {@const before = x(active) > left + innerWidth / 2}
243
+ <div
244
+ class="readout material-thick text-body rounded-control px-3 py-2 text-sm leading-5"
245
+ style:top="{TOP}px"
246
+ style:left={before ? undefined : `${((x(active) + 12) / width) * 100}%`}
247
+ style:right={before ? `${((width - x(active) + 12) / width) * 100}%` : undefined}
248
+ aria-hidden="true"
249
+ >
250
+ {#if xLabels[active] !== undefined}
251
+ <div class="text-label font-medium">{xLabels[active]}</div>
252
+ {/if}
253
+ {#each lines as line, index (index)}
254
+ {@const value = series[index].points[active]}
255
+ {#if isValue(value)}
256
+ <div class="row">
257
+ <svg class="swatch" viewBox="0 0 12 12" width="12" height="12" style:--_c={line.color}>
258
+ <path class="marker" d={markerPath(line.marker, 6, 6, 4)} />
259
+ </svg>
260
+ <span class="name text-description">{line.name}</span>
261
+ <span class="text-headline font-medium tabular-nums">{format(value)}</span>
262
+ </div>
263
+ {/if}
264
+ {/each}
265
+ </div>
266
+ {/if}
267
+ </div>
268
+
269
+ <!-- The key. The table below says the same to assistive technology. -->
270
+ <div class="key text-description text-sm" aria-hidden="true">
271
+ {#if showLegend}
272
+ {#each lines as line, index (index)}
273
+ <span class="entry">
274
+ <svg class="swatch" viewBox="0 0 20 12" width="20" height="12" style:--_c={line.color}>
275
+ <path class="line" d="M1 6H19" />
276
+ <path class="marker" d={markerPath(line.marker, 10, 6, 3.5)} />
277
+ </svg>
278
+ <span>{line.name}</span>
279
+ </span>
280
+ {/each}
281
+ {/if}
282
+ </div>
283
+
284
+ <!-- The library's own Table, so the numbers look like every other table in the app. -->
285
+ <Table class={showTable ? "" : "sr-only"}>
286
+ <thead class="border-border bg-surface-elevated border-b">
287
+ <tr>
288
+ {#if xTitle}<th class="text-headline px-4 py-3 text-start font-medium" scope="col">{xTitle}</th>{:else}<td></td>{/if}
289
+ {#each series as line, column (column)}
290
+ <th class="text-headline px-4 py-3 text-end font-medium" scope="col">{line.name}</th>
291
+ {/each}
292
+ </tr>
293
+ </thead>
294
+ <tbody class="divide-border divide-y">
295
+ {#each { length: count } as _, index (index)}
296
+ <tr>
297
+ <th class="text-body px-4 py-3 text-start font-normal" scope="row">{xLabels[index] ?? index + 1}</th>
298
+ {#each series as line, column (column)}
299
+ {@const value = line.points[index]}
300
+ <td class="text-body px-4 py-3 text-end tabular-nums">{isValue(value) ? format(value) : ""}</td>
301
+ {/each}
302
+ </tr>
303
+ {/each}
304
+ </tbody>
305
+ </Table>
306
+ </figure>
307
+
308
+ <style>
309
+ /*
310
+ * What an app may set, on the chart or on anything around it; read with
311
+ * a fallback and never declared here:
312
+ * --zabi-chart-1 … --zabi-chart-6 the series colours (util/chart.ts)
313
+ * --zabi-chart-surface what the chart stands on; rings the markers
314
+ */
315
+ .plot {
316
+ overflow: visible;
317
+ /* A sideways drag reads along the line; an up or down one still scrolls the page. */
318
+ touch-action: pan-y;
319
+ }
320
+
321
+ /* The library's hairline, as between the rows of a list; the line the plot
322
+ stands on is the edge a Progress track has. */
323
+ .grid {
324
+ stroke: var(--color-border);
325
+ stroke-width: 1;
326
+ shape-rendering: crispEdges;
327
+ }
328
+
329
+ .grid.axis {
330
+ stroke: var(--color-border-strong);
331
+ }
332
+
333
+ .guide {
334
+ stroke: var(--color-border-medium);
335
+ }
336
+
337
+ .guide {
338
+ stroke-width: 1;
339
+ shape-rendering: crispEdges;
340
+ }
341
+
342
+ .tick {
343
+ fill: var(--color-caption);
344
+ font-size: 0.75rem;
345
+ font-variant-numeric: tabular-nums;
346
+ }
347
+
348
+ .tick.on {
349
+ fill: var(--color-headline);
350
+ font-weight: 500;
351
+ }
352
+
353
+ .line {
354
+ fill: none;
355
+ stroke: var(--_c);
356
+ stroke-width: 2;
357
+ stroke-linecap: round;
358
+ stroke-linejoin: round;
359
+ }
360
+
361
+ /* A marker stands in a ring cut out of the lines (the mask above), so the ring is whatever
362
+ is behind the chart. An app that sets --zabi-chart-surface gets the ring painted instead. */
363
+ .marker {
364
+ fill: var(--_c);
365
+ stroke: var(--zabi-chart-surface, transparent);
366
+ stroke-width: 2;
367
+ stroke-linejoin: round;
368
+ paint-order: stroke;
369
+ }
370
+
371
+ .ring {
372
+ fill: black;
373
+ stroke: black;
374
+ stroke-width: 4;
375
+ stroke-linejoin: round;
376
+ }
377
+
378
+ .zabi-chart {
379
+ container-type: inline-size;
380
+ }
381
+
382
+ .key {
383
+ display: flex;
384
+ flex-wrap: wrap;
385
+ align-items: center;
386
+ gap: 0.25rem 1.25rem;
387
+ }
388
+
389
+ .key:empty {
390
+ display: none;
391
+ }
392
+
393
+ .entry {
394
+ display: inline-flex;
395
+ align-items: center;
396
+ gap: 0.5rem;
397
+ }
398
+
399
+ /* The pane of values: it floats, so it is glass (the fill, blur, edge and every fallback
400
+ come with .material-thick), and it never takes the pointer from the plot under it. */
401
+ .readout {
402
+ position: absolute;
403
+ z-index: 1;
404
+ display: grid;
405
+ grid-template-columns: auto minmax(0, 1fr) auto;
406
+ gap: 0.125rem 0.5rem;
407
+ max-inline-size: min(16rem, 70%);
408
+ pointer-events: none;
409
+ }
410
+
411
+ .readout > :first-child:not(.row) {
412
+ grid-column: 1 / -1;
413
+ }
414
+
415
+ .row {
416
+ display: grid;
417
+ grid-column: 1 / -1;
418
+ grid-template-columns: subgrid;
419
+ align-items: center;
420
+ }
421
+
422
+ .row .name {
423
+ padding-inline-end: 0.5rem;
424
+ overflow-wrap: anywhere;
425
+ }
426
+
427
+ .swatch {
428
+ flex: none;
429
+ overflow: visible;
430
+ }
431
+
432
+ /* In the key a marker sits on its own line: there the ring is the line knocked back. */
433
+ .swatch .marker {
434
+ stroke: none;
435
+ }
436
+
437
+ /* Forced colours: the drawing is in the system's text colour, and the
438
+ marker shapes and the key tell the series apart. */
439
+ @media (forced-colors: active) {
440
+ .line {
441
+ stroke: CanvasText;
442
+ }
443
+
444
+ .marker {
445
+ fill: CanvasText;
446
+ stroke: Canvas;
447
+ }
448
+
449
+ .tick {
450
+ fill: CanvasText;
451
+ }
452
+
453
+ .grid,
454
+ .grid.axis,
455
+ .guide {
456
+ stroke: GrayText;
457
+ }
458
+ }
459
+ </style>
@@ -0,0 +1,53 @@
1
+ import type { HTMLAttributes } from "svelte/elements";
2
+ import { type ChartFormat, type ChartSeries } from "../util/chart.js";
3
+ /**
4
+ * A line chart for one or a few series over shared x labels, drawn as
5
+ * plain SVG.
6
+ *
7
+ * It is a `figure`: the `label` is its caption, the drawing is hidden
8
+ * from assistive technology, and the same numbers are in a real table
9
+ * (off screen unless `showTable`). Each series has its own marker shape
10
+ * as well as its own colour. Pointing at or tapping the plot shows the
11
+ * values at that x label in a small pane of the library's thick material
12
+ * that floats over the plot beside the guide, as a Tooltip does.
13
+ *
14
+ * The six series colours are `--zabi-chart-1` to `--zabi-chart-6`, set on
15
+ * the chart or on anything around it; they default to colours made from
16
+ * theme tokens that follow light and dark. Each marker has a ring cut out
17
+ * of the lines around it, so it shows whatever the chart stands on;
18
+ * `--zabi-chart-surface` paints that ring a colour of your own.
19
+ */
20
+ type Props = Omit<HTMLAttributes<HTMLElement>, "class"> & {
21
+ /** The lines: a `name` and one value per x label (`null` leaves a gap). Up to six keep a colour of their own. */
22
+ series: ChartSeries[];
23
+ /** The labels along the x axis, one per point. */
24
+ xLabels?: string[];
25
+ /** The bottom of the y axis. Without it, the lowest value rounded down to a tick. */
26
+ yMin?: number;
27
+ /** The top of the y axis. Without it, the highest value rounded up to a tick. */
28
+ yMax?: number;
29
+ /** How a value is written: `number` (default), `percent` (72 is "72 %"), or a function. */
30
+ yFormat?: ChartFormat;
31
+ /** Height of the drawing in px. The width is the container's. */
32
+ height?: number;
33
+ /** The caption, and what the chart is called. */
34
+ label: string;
35
+ /** Keeps the caption for assistive technology and takes it off the screen. */
36
+ labelHidden?: boolean;
37
+ /** The key under the plot. Without it, shown when there is more than one series. */
38
+ legend?: boolean;
39
+ /** A marker on every point, a different shape per series. */
40
+ markers?: boolean;
41
+ /** Shows the data table under the chart; otherwise it is there for assistive technology only. */
42
+ showTable?: boolean;
43
+ /** The heading of the table's first column (what the x labels are: "Week"). */
44
+ xTitle?: string;
45
+ /** The language of the built-in number formats. Without it, the runtime's. */
46
+ locale?: string;
47
+ /** Stands the chart on a panel of the thick material (frosted glass), for a chart that floats over a wash, a tint or a picture. On a plain card it shows nothing: leave it off there. */
48
+ glass?: boolean;
49
+ class?: string;
50
+ };
51
+ declare const LineChart: import("svelte").Component<Props, {}, "">;
52
+ type LineChart = ReturnType<typeof LineChart>;
53
+ export default LineChart;