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,74 @@
1
+ /** Public types and pure helpers for `Calendar`. */
2
+ import { addDays, addMonths, endOfWeek, startOfWeek } from "./date.js";
3
+ export const DEFAULT_CALENDAR_STRINGS = {
4
+ previousMonth: "Previous month",
5
+ nextMonth: "Next month",
6
+ today: "today",
7
+ selected: "selected",
8
+ unavailable: "unavailable",
9
+ events: (events) => `${events.length} ${events.length === 1 ? "event" : "events"}: ${events
10
+ .map((event) => event.label)
11
+ .join(", ")}`,
12
+ };
13
+ /** How many dots a day shows at most. The name of the day still counts every event. */
14
+ export const MAX_EVENT_DOTS = 3;
15
+ /**
16
+ * The accessible name of a day: the full date, then what is true of it, then
17
+ * its events. "Tuesday 6 October 2026, today, selected, 2 events: Quiz at The
18
+ * Crown, Music quiz".
19
+ */
20
+ export function calendarDayName(fullDate, state, strings) {
21
+ const parts = [fullDate];
22
+ if (state.today)
23
+ parts.push(strings.today);
24
+ if (state.selected)
25
+ parts.push(strings.selected);
26
+ if (state.disabled)
27
+ parts.push(strings.unavailable);
28
+ if (state.events.length > 0)
29
+ parts.push(strings.events(state.events));
30
+ return parts.join(", ");
31
+ }
32
+ /**
33
+ * Where a key takes focus from `date`, by the date-grid pattern: the arrows by
34
+ * a day and a week, Home and End to the ends of the week, Page Up and Page
35
+ * Down by a month, and by a year with Shift. Left and Right swap in a
36
+ * right-to-left layout, where the next day is on the left.
37
+ *
38
+ * Returns null for a key that does not move, or a move past year 1 or 9999.
39
+ */
40
+ export function calendarKeyTarget(key, date, options = {}) {
41
+ const { shift = false, rtl = false, weekStartsOn = 1 } = options;
42
+ switch (key) {
43
+ case "ArrowLeft":
44
+ return addDays(date, rtl ? 1 : -1);
45
+ case "ArrowRight":
46
+ return addDays(date, rtl ? -1 : 1);
47
+ case "ArrowUp":
48
+ return addDays(date, -7);
49
+ case "ArrowDown":
50
+ return addDays(date, 7);
51
+ case "Home":
52
+ return startOfWeek(date, weekStartsOn);
53
+ case "End":
54
+ return endOfWeek(date, weekStartsOn);
55
+ case "PageUp":
56
+ return addMonths(date, shift ? -12 : -1);
57
+ case "PageDown":
58
+ return addMonths(date, shift ? 12 : 1);
59
+ default:
60
+ return null;
61
+ }
62
+ }
63
+ /** The events of each day, in the order given. */
64
+ export function groupEventsByDate(events) {
65
+ const byDate = new Map();
66
+ for (const event of events) {
67
+ const list = byDate.get(event.date);
68
+ if (list)
69
+ list.push(event);
70
+ else
71
+ byDate.set(event.date, [event]);
72
+ }
73
+ return byDate;
74
+ }
@@ -0,0 +1,139 @@
1
+ /**
2
+ * What the four charts share: the series colours, a number formatter, a
3
+ * linear scale with round ticks, and the few path builders. Plain arithmetic
4
+ * that writes SVG; there is no chart library under it.
5
+ */
6
+ /**
7
+ * `glass` on a chart: the library's thick material (the one a Tooltip and a
8
+ * sheet are made of, the level that carries description and caption text),
9
+ * the container corner and room inside it. `on-surface` gives the text its
10
+ * theme colours back when the chart stands in a brand or accent block. Every
11
+ * fallback of the material (reduced transparency, more contrast, forced
12
+ * colours, no backdrop-filter, data-materials="opaque") comes with the class.
13
+ */
14
+ export declare const CHART_GLASS = "material-thick on-surface rounded-container p-4";
15
+ /** A theme colour by name. */
16
+ export type ChartColorName = "primary" | "accent" | "success" | "warning" | "error" | "info" | "neutral";
17
+ /** A theme colour by name, or any CSS colour (`"#c2410c"`, `"var(--color-brand-800)"`). */
18
+ export type ChartColor = ChartColorName | (string & {});
19
+ /** A number as text: the two built in, or the app's own function. */
20
+ export type ChartFormat = "number" | "percent" | ((value: number) => string);
21
+ /** One value of a `BarChart` or a `PieChart`. */
22
+ export interface ChartDatum {
23
+ label: string;
24
+ value: number;
25
+ /** Without it, the series colour of its place in the list. */
26
+ color?: ChartColor;
27
+ }
28
+ /** One line of a `LineChart`. */
29
+ export interface ChartSeries {
30
+ name: string;
31
+ /** One value per x label; `null` leaves a gap in the line. */
32
+ points: Array<number | null>;
33
+ /** Without it, the series colour of its place in the list. */
34
+ color?: ChartColor;
35
+ }
36
+ /**
37
+ * The six series colours, in order. Each is a custom property an app may set
38
+ * on the chart or on anything around it (read with a fallback, declared
39
+ * nowhere), and falls back to a step of the theme's own ramps, so it follows
40
+ * light and dark and the app's brand.
41
+ *
42
+ * They are the colours the rest of the library is made of: the action blue
43
+ * a `Progress` fills with, the accent, a deep step of each, and the neutral
44
+ * grey. Two hues and a grey, told apart by lightness as much as by hue,
45
+ * which is what a reader who does not see red and green needs. None is a
46
+ * status colour. The sixth is the one colour from outside those ramps (the
47
+ * brand turned toward red), for the rare chart with six series.
48
+ */
49
+ export declare const CHART_SERIES_COLORS: readonly string[];
50
+ /** The CSS colour of a series: its own if it names one, else the one of its place (they repeat after six). */
51
+ export declare function chartColor(color: ChartColor | undefined, index: number): string;
52
+ /**
53
+ * The colours of a whole chart, for when named colours and places mix.
54
+ * A series with a `color` gets it. One without keeps the series colour of
55
+ * its place, unless a named colour in the same chart sits next to that one
56
+ * (`success` beside the deep accent, `neutral` beside the grey): then it moves on
57
+ * to the next series colour that is free.
58
+ */
59
+ export declare function chartColors(colors: Array<ChartColor | undefined>): string[];
60
+ /**
61
+ * `"number"` is the locale's plain number. `"percent"` reads the value as
62
+ * already a percentage (72 is "72 %", not 7,200 %). Without a `locale` the
63
+ * runtime's is used, which on a server may not be the reader's: pass one.
64
+ */
65
+ export declare function chartFormatter(format: ChartFormat | undefined, locale?: string): (value: number) => string;
66
+ /** A share of the whole (0 to 1) as a whole percentage. */
67
+ export declare function shareFormatter(locale?: string): (share: number) => string;
68
+ /** 1, 2 or 5 times a power of ten: the one nearest to `target` intervals. */
69
+ export declare function niceStep(range: number, target?: number): number;
70
+ export interface ChartScale {
71
+ min: number;
72
+ max: number;
73
+ ticks: number[];
74
+ }
75
+ /**
76
+ * The value axis. A `min` or `max` that is given is kept exactly; one that is
77
+ * not is rounded outward to a tick. `zero` keeps zero on the axis (bars).
78
+ */
79
+ export declare function chartScale(values: Array<number | null | undefined>, options?: {
80
+ min?: number;
81
+ max?: number;
82
+ zero?: boolean;
83
+ }): ChartScale;
84
+ /** Every how-manyth x label fits: 1 is all of them. */
85
+ export declare function labelEvery(labels: string[], available: number, charWidth?: number): number;
86
+ /** A line through the points, broken where one is missing. */
87
+ export declare function linePath(points: Array<{
88
+ x: number;
89
+ y: number;
90
+ } | null>): string;
91
+ /** An upright bar from `from` to `to` (y), rounded at the `to` end and square where it stands on the zero line. */
92
+ export declare function barPath(x: number, width: number, from: number, to: number, radius: number): string;
93
+ export declare const CHART_MARKERS: readonly ["circle", "square", "diamond", "triangle"];
94
+ export type ChartMarker = (typeof CHART_MARKERS)[number];
95
+ /** The marker of a series, so two lines differ by more than colour (they repeat after four). */
96
+ export declare function chartMarker(index: number): ChartMarker;
97
+ /** A marker centred on a point, as a path. */
98
+ export declare function markerPath(shape: ChartMarker, x: number, y: number, r: number): string;
99
+ export interface PieSlice {
100
+ index: number;
101
+ label: string;
102
+ value: number;
103
+ /** 0 to 1. */
104
+ share: number;
105
+ /** Radians, clockwise from twelve o'clock. */
106
+ start: number;
107
+ end: number;
108
+ }
109
+ /** The slices in the order given. A value that is not a positive number takes no room. */
110
+ export declare function pieSlices(data: ChartDatum[]): PieSlice[];
111
+ /** A slice of a pie, or of a ring when `inner` is above zero. */
112
+ export declare function slicePath(cx: number, cy: number, outer: number, inner: number, start: number, end: number): string;
113
+ /** How much larger than 16px the reader's text is: chart text is set in rem, and the room for it follows. */
114
+ export declare function chartTextScale(): number;
115
+ /**
116
+ * Reports the width of the widest `text` inside the node, as drawn, now and
117
+ * whenever what it is given changes. The value axis takes its room from
118
+ * this, not from a count of characters. Where text cannot be measured
119
+ * nothing is reported and the estimate stands.
120
+ */
121
+ export declare function widestText(node: SVGElement, options: {
122
+ onwidth: (width: number) => void;
123
+ key?: unknown;
124
+ }): {
125
+ update(next: {
126
+ onwidth: (width: number) => void;
127
+ key?: unknown;
128
+ }): void;
129
+ };
130
+ /**
131
+ * Reports the element's width now and whenever it changes: the charts are
132
+ * drawn at the width of their container, in real pixels, so text is never
133
+ * scaled. Where there is no `ResizeObserver` the width is read once.
134
+ */
135
+ export declare function measureWidth(node: HTMLElement, onwidth: (width: number) => void): {
136
+ destroy?: undefined;
137
+ } | {
138
+ destroy: () => void;
139
+ };
@@ -0,0 +1,305 @@
1
+ /**
2
+ * What the four charts share: the series colours, a number formatter, a
3
+ * linear scale with round ticks, and the few path builders. Plain arithmetic
4
+ * that writes SVG; there is no chart library under it.
5
+ */
6
+ /**
7
+ * `glass` on a chart: the library's thick material (the one a Tooltip and a
8
+ * sheet are made of, the level that carries description and caption text),
9
+ * the container corner and room inside it. `on-surface` gives the text its
10
+ * theme colours back when the chart stands in a brand or accent block. Every
11
+ * fallback of the material (reduced transparency, more contrast, forced
12
+ * colours, no backdrop-filter, data-materials="opaque") comes with the class.
13
+ */
14
+ export const CHART_GLASS = "material-thick on-surface rounded-container p-4";
15
+ const NAMED = {
16
+ primary: "var(--color-action-primary)",
17
+ accent: "var(--color-accent)",
18
+ success: "var(--color-success)",
19
+ warning: "var(--color-warning)",
20
+ error: "var(--color-error)",
21
+ info: "var(--color-info)",
22
+ neutral: "var(--color-neutral)",
23
+ };
24
+ /**
25
+ * The six series colours, in order. Each is a custom property an app may set
26
+ * on the chart or on anything around it (read with a fallback, declared
27
+ * nowhere), and falls back to a step of the theme's own ramps, so it follows
28
+ * light and dark and the app's brand.
29
+ *
30
+ * They are the colours the rest of the library is made of: the action blue
31
+ * a `Progress` fills with, the accent, a deep step of each, and the neutral
32
+ * grey. Two hues and a grey, told apart by lightness as much as by hue,
33
+ * which is what a reader who does not see red and green needs. None is a
34
+ * status colour. The sixth is the one colour from outside those ramps (the
35
+ * brand turned toward red), for the rare chart with six series.
36
+ */
37
+ export const CHART_SERIES_COLORS = [
38
+ "var(--zabi-chart-1, var(--color-action-primary))",
39
+ "var(--zabi-chart-2, var(--color-accent-500))",
40
+ "var(--zabi-chart-3, var(--color-brand-900))",
41
+ "var(--zabi-chart-4, var(--color-accent-700))",
42
+ "var(--zabi-chart-5, var(--color-base-500))",
43
+ "var(--zabi-chart-6, color-mix(in oklch, var(--color-brand-700), var(--color-error-700)))",
44
+ ];
45
+ const slot = (index) => ((index % 6) + 6) % 6;
46
+ /** The CSS colour of a series: its own if it names one, else the one of its place (they repeat after six). */
47
+ export function chartColor(color, index) {
48
+ if (!color)
49
+ return CHART_SERIES_COLORS[slot(index)];
50
+ return Object.prototype.hasOwnProperty.call(NAMED, color) ? NAMED[color] : color;
51
+ }
52
+ /** The series colour a theme colour sits nearest to: one chart does not show both. */
53
+ const NEAREST = new Map([
54
+ ["primary", 0],
55
+ ["info", 0],
56
+ ["accent", 1],
57
+ ["success", 3],
58
+ ["neutral", 4],
59
+ ]);
60
+ /**
61
+ * The colours of a whole chart, for when named colours and places mix.
62
+ * A series with a `color` gets it. One without keeps the series colour of
63
+ * its place, unless a named colour in the same chart sits next to that one
64
+ * (`success` beside the deep accent, `neutral` beside the grey): then it moves on
65
+ * to the next series colour that is free.
66
+ */
67
+ export function chartColors(colors) {
68
+ const taken = new Set();
69
+ for (const color of colors) {
70
+ const near = color ? NEAREST.get(color) : undefined;
71
+ if (near !== undefined)
72
+ taken.add(near);
73
+ }
74
+ colors.forEach((color, index) => {
75
+ if (!color && !taken.has(slot(index)))
76
+ taken.add(slot(index));
77
+ });
78
+ const moved = new Set();
79
+ return colors.map((color, index) => {
80
+ if (color)
81
+ return chartColor(color, index);
82
+ const own = slot(index);
83
+ const clash = colors.some((other) => other && NEAREST.get(other) === own);
84
+ if (!clash)
85
+ return CHART_SERIES_COLORS[own];
86
+ for (let step = 1; step < 6; step++) {
87
+ const next = slot(own + step);
88
+ if (!taken.has(next) && !moved.has(next)) {
89
+ moved.add(next);
90
+ return CHART_SERIES_COLORS[next];
91
+ }
92
+ }
93
+ return CHART_SERIES_COLORS[own];
94
+ });
95
+ }
96
+ /**
97
+ * `"number"` is the locale's plain number. `"percent"` reads the value as
98
+ * already a percentage (72 is "72 %", not 7,200 %). Without a `locale` the
99
+ * runtime's is used, which on a server may not be the reader's: pass one.
100
+ */
101
+ export function chartFormatter(format, locale) {
102
+ if (typeof format === "function")
103
+ return format;
104
+ const options = format === "percent"
105
+ ? { style: "unit", unit: "percent", maximumFractionDigits: 1 }
106
+ : { maximumFractionDigits: 2 };
107
+ let formatter;
108
+ try {
109
+ formatter = new Intl.NumberFormat(locale, options);
110
+ }
111
+ catch {
112
+ formatter = new Intl.NumberFormat(undefined, options);
113
+ }
114
+ return (value) => formatter.format(value);
115
+ }
116
+ /** A share of the whole (0 to 1) as a whole percentage. */
117
+ export function shareFormatter(locale) {
118
+ let formatter;
119
+ try {
120
+ formatter = new Intl.NumberFormat(locale, { style: "percent", maximumFractionDigits: 0 });
121
+ }
122
+ catch {
123
+ formatter = new Intl.NumberFormat(undefined, { style: "percent", maximumFractionDigits: 0 });
124
+ }
125
+ return (share) => formatter.format(share);
126
+ }
127
+ const finite = (value) => typeof value === "number" && Number.isFinite(value);
128
+ /** 1, 2 or 5 times a power of ten: the one nearest to `target` intervals. */
129
+ export function niceStep(range, target = 4) {
130
+ if (!(range > 0))
131
+ return 1;
132
+ const raw = range / target;
133
+ const magnitude = 10 ** Math.floor(Math.log10(raw));
134
+ const unit = raw / magnitude;
135
+ return (unit < 1.5 ? 1 : unit < 3.5 ? 2 : unit < 7.5 ? 5 : 10) * magnitude;
136
+ }
137
+ /**
138
+ * The value axis. A `min` or `max` that is given is kept exactly; one that is
139
+ * not is rounded outward to a tick. `zero` keeps zero on the axis (bars).
140
+ */
141
+ export function chartScale(values, options = {}) {
142
+ const data = values.filter(finite);
143
+ let low = data.length ? Math.min(...data) : 0;
144
+ let high = data.length ? Math.max(...data) : 1;
145
+ if (options.zero) {
146
+ low = Math.min(0, low);
147
+ high = Math.max(0, high);
148
+ }
149
+ const fixedMin = finite(options.min);
150
+ const fixedMax = finite(options.max);
151
+ if (fixedMin)
152
+ low = options.min;
153
+ if (fixedMax)
154
+ high = options.max;
155
+ if (!(high > low)) {
156
+ if (fixedMax && !fixedMin)
157
+ low = high - 1;
158
+ else
159
+ high = low + 1;
160
+ }
161
+ const step = niceStep(high - low);
162
+ if (!fixedMin)
163
+ low = Math.floor(low / step) * step;
164
+ if (!fixedMax)
165
+ high = Math.ceil(high / step) * step;
166
+ const ticks = [];
167
+ for (let tick = Math.ceil(low / step - 1e-9) * step; tick <= high + step * 1e-9; tick += step) {
168
+ ticks.push(Number(tick.toPrecision(12)));
169
+ }
170
+ return { min: Number(low.toPrecision(12)), max: Number(high.toPrecision(12)), ticks };
171
+ }
172
+ /** Every how-manyth x label fits: 1 is all of them. */
173
+ export function labelEvery(labels, available, charWidth = 7) {
174
+ if (!labels.length || !(available > 0))
175
+ return 1;
176
+ const widest = Math.max(...labels.map((label) => label.length)) * charWidth + 12;
177
+ return Math.max(1, Math.ceil((widest * labels.length) / available));
178
+ }
179
+ const round = (value) => Math.round(value * 100) / 100;
180
+ /** A line through the points, broken where one is missing. */
181
+ export function linePath(points) {
182
+ let path = "";
183
+ let pen = false;
184
+ for (const point of points) {
185
+ if (!point) {
186
+ pen = false;
187
+ continue;
188
+ }
189
+ path += `${pen ? "L" : "M"}${round(point.x)} ${round(point.y)}`;
190
+ pen = true;
191
+ }
192
+ return path;
193
+ }
194
+ /** An upright bar from `from` to `to` (y), rounded at the `to` end and square where it stands on the zero line. */
195
+ export function barPath(x, width, from, to, radius) {
196
+ const height = Math.abs(to - from);
197
+ const r = round(Math.max(0, Math.min(radius, width / 2, height)));
198
+ const [left, base, w] = [round(x), round(from), round(width)];
199
+ const up = to < from ? -1 : 1;
200
+ const side = round(height - r);
201
+ if (!(height > 0))
202
+ return "";
203
+ return `M${left} ${base}v${up * side}a${r} ${r} 0 0 ${up < 0 ? 1 : 0} ${r} ${up * r}h${round(w - 2 * r)}a${r} ${r} 0 0 ${up < 0 ? 1 : 0} ${r} ${-up * r}v${-up * side}Z`;
204
+ }
205
+ export const CHART_MARKERS = ["circle", "square", "diamond", "triangle"];
206
+ /** The marker of a series, so two lines differ by more than colour (they repeat after four). */
207
+ export function chartMarker(index) {
208
+ return CHART_MARKERS[((index % 4) + 4) % 4];
209
+ }
210
+ /** A marker centred on a point, as a path. */
211
+ export function markerPath(shape, x, y, r) {
212
+ const [cx, cy] = [round(x), round(y)];
213
+ switch (shape) {
214
+ case "square": {
215
+ const side = round(r * 0.9);
216
+ return `M${cx - side} ${cy - side}h${side * 2}v${side * 2}h${-side * 2}Z`;
217
+ }
218
+ case "diamond": {
219
+ const reach = round(r * 1.25);
220
+ return `M${cx} ${cy - reach}L${cx + reach} ${cy}L${cx} ${cy + reach}L${cx - reach} ${cy}Z`;
221
+ }
222
+ case "triangle": {
223
+ const reach = round(r * 1.2);
224
+ return `M${cx} ${cy - reach}L${cx + reach} ${round(cy + reach * 0.8)}L${cx - reach} ${round(cy + reach * 0.8)}Z`;
225
+ }
226
+ default:
227
+ return `M${cx - r} ${cy}a${r} ${r} 0 1 0 ${r * 2} 0a${r} ${r} 0 1 0 ${-r * 2} 0Z`;
228
+ }
229
+ }
230
+ /** The slices in the order given. A value that is not a positive number takes no room. */
231
+ export function pieSlices(data) {
232
+ const values = data.map((datum) => (finite(datum.value) && datum.value > 0 ? datum.value : 0));
233
+ const total = values.reduce((sum, value) => sum + value, 0);
234
+ let angle = 0;
235
+ return data.map((datum, index) => {
236
+ const share = total > 0 ? values[index] / total : 0;
237
+ const start = angle;
238
+ angle += share * Math.PI * 2;
239
+ return { index, label: datum.label, value: datum.value, share, start, end: angle };
240
+ });
241
+ }
242
+ const onCircle = (cx, cy, r, angle) => `${round(cx + r * Math.sin(angle))} ${round(cy - r * Math.cos(angle))}`;
243
+ /** A slice of a pie, or of a ring when `inner` is above zero. */
244
+ export function slicePath(cx, cy, outer, inner, start, end) {
245
+ const sweep = end - start;
246
+ if (!(sweep > 0))
247
+ return "";
248
+ if (sweep >= Math.PI * 2 - 1e-6) {
249
+ // A whole turn has no arc of its own: two halves.
250
+ const half = start + Math.PI;
251
+ const ring = (r, clockwise) => `M${onCircle(cx, cy, r, start)}A${r} ${r} 0 1 ${clockwise} ${onCircle(cx, cy, r, half)}A${r} ${r} 0 1 ${clockwise} ${onCircle(cx, cy, r, start)}Z`;
252
+ return inner > 0 ? ring(outer, 1) + ring(inner, 0) : ring(outer, 1);
253
+ }
254
+ const large = sweep > Math.PI ? 1 : 0;
255
+ const arc = `M${onCircle(cx, cy, outer, start)}A${outer} ${outer} 0 ${large} 1 ${onCircle(cx, cy, outer, end)}`;
256
+ if (!(inner > 0))
257
+ return `${arc}L${round(cx)} ${round(cy)}Z`;
258
+ return `${arc}L${onCircle(cx, cy, inner, end)}A${inner} ${inner} 0 ${large} 0 ${onCircle(cx, cy, inner, start)}Z`;
259
+ }
260
+ /** How much larger than 16px the reader's text is: chart text is set in rem, and the room for it follows. */
261
+ export function chartTextScale() {
262
+ if (typeof document === "undefined" || typeof getComputedStyle !== "function")
263
+ return 1;
264
+ const size = Number.parseFloat(getComputedStyle(document.documentElement).fontSize);
265
+ return size > 0 ? size / 16 : 1;
266
+ }
267
+ /**
268
+ * Reports the width of the widest `text` inside the node, as drawn, now and
269
+ * whenever what it is given changes. The value axis takes its room from
270
+ * this, not from a count of characters. Where text cannot be measured
271
+ * nothing is reported and the estimate stands.
272
+ */
273
+ export function widestText(node, options) {
274
+ let report = options.onwidth;
275
+ const measure = () => {
276
+ let widest = 0;
277
+ for (const text of node.querySelectorAll("text")) {
278
+ if (typeof text.getComputedTextLength !== "function")
279
+ return;
280
+ widest = Math.max(widest, text.getComputedTextLength());
281
+ }
282
+ if (widest > 0)
283
+ report(Math.ceil(widest));
284
+ };
285
+ measure();
286
+ return {
287
+ update(next) {
288
+ report = next.onwidth;
289
+ measure();
290
+ },
291
+ };
292
+ }
293
+ /**
294
+ * Reports the element's width now and whenever it changes: the charts are
295
+ * drawn at the width of their container, in real pixels, so text is never
296
+ * scaled. Where there is no `ResizeObserver` the width is read once.
297
+ */
298
+ export function measureWidth(node, onwidth) {
299
+ onwidth(node.clientWidth);
300
+ if (typeof ResizeObserver === "undefined")
301
+ return {};
302
+ const observer = new ResizeObserver(() => onwidth(node.clientWidth));
303
+ observer.observe(node);
304
+ return { destroy: () => observer.disconnect() };
305
+ }
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Chip and ChipGroup: what they share, and the arithmetic of the one-row
3
+ * layout.
4
+ *
5
+ * The scroll logic is pure, so it can be tested with made-up metrics: jsdom
6
+ * has no layout. The component reads the real ones and passes them in.
7
+ */
8
+ export type ChipGroupType = "radio" | "checkbox";
9
+ export type ChipGroupLayout = "wrap" | "row";
10
+ export type ChipGroupEdge = "fade" | "none";
11
+ /** What a ChipGroup hands to the chips (and groups) inside it. */
12
+ export interface ChipGroupContext {
13
+ /** Without a type the group is layout only. */
14
+ readonly type: ChipGroupType | undefined;
15
+ readonly name: string | undefined;
16
+ readonly layout: ChipGroupLayout;
17
+ readonly disabled: boolean;
18
+ /** Whether the chip with this value is selected, by the group's `value`. */
19
+ isSelected(value: string): boolean;
20
+ /**
21
+ * The chip with this value was checked or unchecked. `report` is true for
22
+ * a person's change (the group's `onchange` hears it) and false for one
23
+ * taken in by a binding on hydration, which is reported once afterwards.
24
+ */
25
+ change(value: string, checked: boolean, report: boolean): void;
26
+ /** The value a radio group holds, for `bind:group`. */
27
+ readonly radioValue: string | undefined;
28
+ /** A form reset emptied a radio group. */
29
+ restore(): void;
30
+ }
31
+ export declare const CHIP_GROUP_CONTEXT_KEY: unique symbol;
32
+ /** The gap between chips, and the margin that keeps a revealed chip off the edge. */
33
+ export declare const CHIP_GAP = 8;
34
+ /** The next value of a checkbox group when `value` is checked or unchecked. Order is kept. */
35
+ export declare function toggleValue(current: readonly string[] | undefined, value: string, checked: boolean): string[];
36
+ export interface RowMetrics {
37
+ /** `scrollLeft`: 0 at the start, negative towards the end in a right-to-left row. */
38
+ scrollLeft: number;
39
+ scrollWidth: number;
40
+ clientWidth: number;
41
+ rtl: boolean;
42
+ }
43
+ export interface RowOverflow {
44
+ /** More chips are hidden before the first visible one. */
45
+ start: boolean;
46
+ /** More chips are hidden after the last visible one. */
47
+ end: boolean;
48
+ }
49
+ /** Which sides of the row have chips out of view. Start and end follow the direction. */
50
+ export declare function measureRowOverflow(metrics: RowMetrics): RowOverflow;
51
+ export interface Span {
52
+ left: number;
53
+ right: number;
54
+ }
55
+ /**
56
+ * The `scrollLeft` that brings `item` fully into `box` with `margin` to spare,
57
+ * or the current one if it is in view already. Both spans are in the same
58
+ * coordinates (the viewport's). The result stays inside what the row can
59
+ * scroll. An item wider than the box is lined up with its start edge.
60
+ */
61
+ export declare function scrollLeftToReveal(metrics: RowMetrics, box: Span, item: Span, margin?: number): number;
62
+ /** The first chosen chip in a row: a link, a toggle button or a checked input. */
63
+ export declare const SELECTED_CHIP_SELECTOR = "[aria-current]:not([aria-current=\"false\"]), [aria-pressed=\"true\"], input:checked";
64
+ /** The element to bring into view for a selected chip: the label around an input, else the element. */
65
+ export declare function chipBox(selected: Element): Element;
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Chip and ChipGroup: what they share, and the arithmetic of the one-row
3
+ * layout.
4
+ *
5
+ * The scroll logic is pure, so it can be tested with made-up metrics: jsdom
6
+ * has no layout. The component reads the real ones and passes them in.
7
+ */
8
+ export const CHIP_GROUP_CONTEXT_KEY = Symbol("zabi-chip-group");
9
+ /** The gap between chips, and the margin that keeps a revealed chip off the edge. */
10
+ export const CHIP_GAP = 8;
11
+ /** The next value of a checkbox group when `value` is checked or unchecked. Order is kept. */
12
+ export function toggleValue(current, value, checked) {
13
+ const list = current ?? [];
14
+ const has = list.includes(value);
15
+ if (checked)
16
+ return has ? [...list] : [...list, value];
17
+ return has ? list.filter((item) => item !== value) : [...list];
18
+ }
19
+ /** Fractional scroll positions: less than this from an edge counts as at it. */
20
+ const TOLERANCE = 1;
21
+ /** Which sides of the row have chips out of view. Start and end follow the direction. */
22
+ export function measureRowOverflow(metrics) {
23
+ const hidden = metrics.scrollWidth - metrics.clientWidth;
24
+ if (hidden <= TOLERANCE)
25
+ return { start: false, end: false };
26
+ // The distance from the start edge: `scrollLeft` itself, or its negative in a
27
+ // right-to-left row. The wrong sign is rubber-banding, and counts as none.
28
+ const fromStart = Math.min(Math.max(0, metrics.rtl ? -metrics.scrollLeft : metrics.scrollLeft), hidden);
29
+ return { start: fromStart > TOLERANCE, end: fromStart < hidden - TOLERANCE };
30
+ }
31
+ /**
32
+ * The `scrollLeft` that brings `item` fully into `box` with `margin` to spare,
33
+ * or the current one if it is in view already. Both spans are in the same
34
+ * coordinates (the viewport's). The result stays inside what the row can
35
+ * scroll. An item wider than the box is lined up with its start edge.
36
+ */
37
+ export function scrollLeftToReveal(metrics, box, item, margin = CHIP_GAP) {
38
+ const hidden = Math.max(0, metrics.scrollWidth - metrics.clientWidth);
39
+ let delta = 0;
40
+ const tooWide = item.right - item.left > box.right - box.left - margin * 2;
41
+ if (tooWide) {
42
+ delta = metrics.rtl ? item.right - box.right + margin : item.left - box.left - margin;
43
+ }
44
+ else if (item.left < box.left + margin) {
45
+ delta = item.left - box.left - margin;
46
+ }
47
+ else if (item.right > box.right - margin) {
48
+ delta = item.right - box.right + margin;
49
+ }
50
+ const next = metrics.scrollLeft + delta;
51
+ return metrics.rtl ? Math.min(0, Math.max(-hidden, next)) : Math.min(hidden, Math.max(0, next));
52
+ }
53
+ /** The first chosen chip in a row: a link, a toggle button or a checked input. */
54
+ export const SELECTED_CHIP_SELECTOR = '[aria-current]:not([aria-current="false"]), [aria-pressed="true"], input:checked';
55
+ /** The element to bring into view for a selected chip: the label around an input, else the element. */
56
+ export function chipBox(selected) {
57
+ return selected instanceof HTMLInputElement ? (selected.closest("label") ?? selected) : selected;
58
+ }