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,15 +1,77 @@
1
1
  <script lang="ts">
2
- import type { Snippet } from "svelte";
3
- import type { HTMLButtonAttributes } from "svelte/elements";
2
+ import { tick, untrack, type Snippet } from "svelte";
3
+ import type { HTMLAnchorAttributes, HTMLButtonAttributes } from "svelte/elements";
4
4
  import type { ButtonVariant, SizeVariant } from "../types/variants.js";
5
5
  import { cn } from "../util/cn.js";
6
+ import { isDevBuild } from "../util/app-shell.js";
7
+ import { badgeText, defaultBadgeLabel } from "../util/bottom-tab-bar.js";
8
+ import Badge from "./Badge.svelte";
6
9
 
10
+ /** The shared scale plus `xs`, which only the icon button has. */
11
+ type IconButtonSize = SizeVariant | "xs";
12
+
13
+ /**
14
+ * One type for the button and the link, not a union of the two elements'
15
+ * attributes: that union is too large for TypeScript to carry through a
16
+ * wrapper such as a Storybook `Meta`. Event handlers are typed for the
17
+ * button; on a link they are called with the same event.
18
+ */
7
19
  type Props = Omit<HTMLButtonAttributes, "class"> & {
20
+ /**
21
+ * Where the link goes. Makes this an `<a>` that looks the same;
22
+ * without it, it is a `<button>`. A link cannot be disabled: while
23
+ * `disabled` or `loading` it has no `href`, is `aria-disabled` and
24
+ * does nothing when pressed. A link is not
25
+ * a toggle: `pressed` is ignored.
26
+ */
27
+ href?: string;
28
+ /** With `href`: where the link opens. */
29
+ target?: HTMLAnchorAttributes["target"];
30
+ /** With `href`: the link's relationship, such as `noopener`. */
31
+ rel?: HTMLAnchorAttributes["rel"];
32
+ /** With `href`: download the address instead of opening it. */
33
+ download?: HTMLAnchorAttributes["download"];
34
+ hreflang?: HTMLAnchorAttributes["hreflang"];
35
+ referrerpolicy?: HTMLAnchorAttributes["referrerpolicy"];
36
+ ping?: HTMLAnchorAttributes["ping"];
8
37
  variant?: ButtonVariant;
9
- size?: SizeVariant;
38
+ /**
39
+ * `xs` is a 24px box for dense, pointer-first layouts (card headers,
40
+ * table rows). That is the WCAG 2.2 minimum target size and no more:
41
+ * where the primary input is touch, use `sm` or larger.
42
+ */
43
+ size?: IconButtonSize;
44
+ /**
45
+ * Colour intent for the `ghost` and `outline` variants: `danger` is
46
+ * the quiet destructive button (inline delete). Other variants ignore it.
47
+ */
48
+ tone?: "default" | "danger";
49
+ /**
50
+ * Makes this a toggle button. When defined (true or false) it renders
51
+ * `aria-pressed` and a click flips it; bind it, or pass it one-way and
52
+ * update your own state in `onclick`. Call `event.preventDefault()` in
53
+ * `onclick` to keep the current state: do that whenever the parent
54
+ * updates later (after a request, say) or may refuse the change, or the
55
+ * button shows a state the parent does not have. Leave undefined for a
56
+ * plain button.
57
+ */
58
+ pressed?: boolean;
10
59
  loading?: boolean;
11
60
  /** Required for icon-only usage (no visible text). */
12
61
  label?: string;
62
+ /**
63
+ * A count drawn on the button, in the attention colour, inside the
64
+ * button's own box (so a bar or an `overflow` ancestor cannot cut it).
65
+ * Nothing is drawn for 0, a negative number or when it is left out;
66
+ * while `loading` it is hidden. At `xs` and `sm` there is no room for
67
+ * a number: a dot is drawn instead. Needs `label`: the accessible name
68
+ * becomes the label, a comma and `countLabel(count)`.
69
+ */
70
+ count?: number;
71
+ /** What the count adds to the accessible name, after the label. Default: "3 new". */
72
+ countLabel?: (count: number) => string;
73
+ /** Above this the badge reads `99+`. The accessible name keeps the real count. */
74
+ countMax?: number;
13
75
  class?: string;
14
76
  children?: Snippet;
15
77
  };
@@ -17,72 +79,278 @@
17
79
  let {
18
80
  variant = "primary",
19
81
  size = "md",
82
+ tone = "default",
83
+ pressed = $bindable(),
20
84
  disabled = false,
21
85
  loading = false,
22
- type = "button",
86
+ type,
87
+ href,
23
88
  label = "",
89
+ count,
90
+ countLabel = defaultBadgeLabel,
91
+ countMax = 99,
24
92
  class: className = "",
25
93
  onclick,
26
94
  children,
27
95
  ...restProps
28
96
  }: Props = $props();
29
97
 
30
- const isDisabled = $derived(disabled || loading);
98
+ const isDisabled = $derived(!!disabled || loading);
99
+
100
+ /** A count is drawn only for a positive number, and not while loading. */
101
+ const hasCount = $derived(typeof count === "number" && count > 0);
102
+ const showCount = $derived(hasCount && !loading);
103
+ /** `xs` and `sm` have no room for a number beside the icon: a dot. */
104
+ const countAsDot = $derived(size === "xs" || size === "sm");
105
+ const accessibleName = $derived(
106
+ showCount && label ? `${label}, ${countLabel(count as number)}` : label || undefined,
107
+ );
108
+
109
+ $effect(() => {
110
+ if (!isDevBuild() || !hasCount || label) return;
111
+ console.warn(
112
+ "[zabi-components] IconButton: `count` needs a `label`; without it the count has no accessible name.",
113
+ );
114
+ });
115
+ /**
116
+ * Loading without `disabled`: unavailable, and still where focus is.
117
+ *
118
+ * `disabled` on a button, or no `href` on a link, makes the element
119
+ * unfocusable, and the browser then drops focus on `<body>`: whoever
120
+ * pressed Save with the keyboard was at the top of the page when the
121
+ * save came back. So a loading control says it the ARIA way
122
+ * (`aria-disabled`, `aria-busy`), stays a Tab stop, and swallows the
123
+ * press. `disabled` is the platform's: out of the Tab order.
124
+ */
125
+ const isBusy = $derived(loading && !disabled);
126
+ const isLink = $derived(href !== undefined && href !== null);
127
+ const isToggle = $derived(pressed !== undefined && !isLink);
128
+
129
+ /**
130
+ * A loading link has no `href`, so it is a Tab stop only by `tabindex`.
131
+ * The browser takes focus from an element the moment it stops being
132
+ * focusable, so the two attributes must never both be missing: the
133
+ * `tabindex` goes on before the `href` comes off (their order in the
134
+ * markup), and when loading ends it stays until the `href` is back, one
135
+ * update longer.
136
+ */
137
+ let keepsTabStop = $state(false);
138
+ $effect.pre(() => {
139
+ if (isBusy) {
140
+ keepsTabStop = true;
141
+ } else if (untrack(() => keepsTabStop)) {
142
+ void tick().then(() => (keepsTabStop = false));
143
+ }
144
+ });
145
+
146
+ /** A disabled link has no `href`, but a pointer can still press it. */
147
+ function handleLinkClick(event: MouseEvent) {
148
+ if (isDisabled) {
149
+ event.preventDefault();
150
+ event.stopPropagation();
151
+ return;
152
+ }
153
+ (onclick as ((event: MouseEvent) => void) | null | undefined)?.(event);
154
+ }
155
+
156
+ function handleClick(
157
+ event: MouseEvent & { currentTarget: EventTarget & HTMLButtonElement },
158
+ ) {
159
+ // A loading button is not `disabled`, so the press reaches it: it
160
+ // ends here, toggles nothing and submits nothing.
161
+ if (isBusy) {
162
+ event.preventDefault();
163
+ event.stopPropagation();
164
+ return;
165
+ }
166
+ // Read before the handler runs: a parent that flips its own state in
167
+ // `onclick` has already moved `pressed` by the time it returns.
168
+ const next = !pressed;
169
+ onclick?.(event);
170
+ if (isToggle && !event.defaultPrevented) pressed = next;
171
+ }
31
172
 
32
173
  /**
33
174
  * Square, on the same height scale as Button / Input / Select, so an icon
34
175
  * button sits flush in a toolbar beside a text button of the same size.
35
176
  * Previously these were 8–16px shorter than their own Button.
177
+ *
178
+ * On a coarse pointer `sm` and `md` are 44 by 44px, as Button, Input and
179
+ * Select are 44px tall there, so the toolbar still lines up and the box
180
+ * itself is the touch target. `lg` is 48px already.
181
+ *
182
+ * `xs` sits below that scale on purpose: no text control is 24px. Its
183
+ * target is the box itself on every pointer type. An invisible larger hit
184
+ * area was tried and removed: on touch it covered the visible edge of the
185
+ * neighbouring button, so a tap there fired the wrong one.
36
186
  */
37
187
  const sizeClass = $derived.by(() => {
38
- if (size === "sm") return { box: "size-8", spinner: "size-3.5" };
188
+ if (size === "xs") return { box: "size-6", spinner: "size-3" };
189
+ if (size === "sm") return { box: "size-8 pointer-coarse:min-h-11 pointer-coarse:min-w-11", spinner: "size-3.5" };
39
190
  if (size === "lg") return { box: "size-12", spinner: "size-5" };
40
- return { box: "size-10", spinner: "size-4" };
191
+ return { box: "size-10 pointer-coarse:min-h-11 pointer-coarse:min-w-11", spinner: "size-4" };
41
192
  });
42
193
 
43
194
  const disabledClass =
44
- "disabled:bg-action-disabled disabled:text-action-disabled-text disabled:border-transparent disabled:shadow-none disabled:cursor-not-allowed disabled:active:scale-100";
195
+ "disabled:bg-action-disabled disabled:text-action-disabled-text disabled:border-transparent disabled:bg-none disabled:inset-shadow-none disabled:shadow-none disabled:cursor-not-allowed disabled:active:scale-100";
196
+
197
+ const isDangerTone = $derived(
198
+ tone === "danger" && (variant === "ghost" || variant === "outline"),
199
+ );
45
200
 
46
201
  const variantClass = $derived.by(() => {
202
+ // The veil of the solid fills, as on Button. Not when disabled, and
203
+ // not on a toggled-on button (`pressedClass`): that holds the pressed
204
+ // fill flat, with its outline as the shape.
205
+ const veil = disabled || (isToggle && pressed) ? "" : "bg-control-gradient ";
206
+ const veilAccent = disabled || (isToggle && pressed) ? "" : "bg-control-gradient-accent ";
207
+ if (isDangerTone) {
208
+ const fill =
209
+ "text-error hover:bg-action-danger-subtle active:bg-action-danger-subtle-hover active:scale-[0.98] motion-reduce:active:scale-100 focus-ring--danger";
210
+ return variant === "outline"
211
+ ? `bg-transparent border border-error-border hover:border-error ${fill}`
212
+ : `bg-transparent ${fill}`;
213
+ }
47
214
  switch (variant) {
48
215
  case "secondary":
49
- return "bg-action-secondary text-headline hover:bg-action-secondary-hover active:bg-action-secondary-active active:scale-[0.98]";
216
+ return "bg-action-secondary text-headline hover:bg-action-secondary-hover active:bg-action-secondary-active active:scale-[0.98] motion-reduce:active:scale-100";
217
+ case "tonal":
218
+ return "bg-action-tonal text-action-tonal active:scale-[0.98] motion-reduce:active:scale-100";
50
219
  case "danger":
51
- return "bg-action-danger text-action-danger-text hover:bg-action-danger-hover active:bg-action-danger-active active:scale-[0.98] focus-ring--danger";
220
+ return `${veil}bg-action-danger text-action-danger-text hover:bg-action-danger-hover active:bg-action-danger-active active:scale-[0.98] motion-reduce:active:scale-100 focus-ring--danger`;
52
221
  case "ghost":
53
- return "bg-transparent text-headline hover:bg-surface-hover active:bg-surface-active active:scale-[0.98] focus-ring--muted";
222
+ return "bg-transparent text-headline hover:bg-surface-hover active:bg-surface-active active:scale-[0.98] motion-reduce:active:scale-100 focus-ring--muted";
54
223
  case "outline":
55
- return "bg-transparent border border-border text-headline hover:bg-surface-hover hover:border-border-medium active:bg-surface-active active:scale-[0.98]";
224
+ return "bg-transparent border border-action-outline text-headline hover:bg-surface-hover hover:border-action-outline-hover active:bg-surface-active active:scale-[0.98] motion-reduce:active:scale-100";
56
225
  case "link":
226
+ case "text":
57
227
  return "bg-transparent text-link hover:text-link-hover focus-ring--muted";
228
+ case "accent":
229
+ return `${veilAccent}bg-accent text-on-accent hover:bg-accent-hover active:bg-accent-active active:scale-[0.98] motion-reduce:active:scale-100`;
58
230
  case "primary":
59
231
  default:
60
- return "bg-action-primary text-action-primary hover:bg-action-primary-hover active:bg-action-primary-active active:scale-[0.98]";
232
+ return `${veil}bg-action-primary text-action-primary hover:bg-action-primary-hover active:bg-action-primary-active active:scale-[0.98] motion-reduce:active:scale-100`;
233
+ }
234
+ });
235
+
236
+ /**
237
+ * Held down, a toggled-on ghost or danger-tone button goes one step past its
238
+ * hover fill (the `-subtle-active` roles): with a mouse the hover fill is
239
+ * already showing, so the same fill would not show the press. The solid
240
+ * variants have no further step and keep their fill.
241
+ *
242
+ * Pressed holds a fill that hover cannot reach and adds an inset outline in
243
+ * the text colour, so the state is a shape as well as a colour. It is an
244
+ * outline, not a ring: `.focus-ring` owns `box-shadow`, and an outline also
245
+ * survives forced-colors mode.
246
+ */
247
+ const pressedClass = $derived.by(() => {
248
+ if (!pressed) return "";
249
+ const outline = "outline-2 -outline-offset-2 outline-current";
250
+ if (isDangerTone) {
251
+ return `bg-action-danger-subtle hover:bg-action-danger-subtle-hover active:bg-action-danger-subtle-active ${outline}`;
252
+ }
253
+ switch (variant) {
254
+ case "secondary":
255
+ return `bg-action-secondary-active hover:bg-action-secondary-active ${outline}`;
256
+ case "danger":
257
+ return `bg-action-danger-active hover:bg-action-danger-active ${outline}`;
258
+ case "ghost":
259
+ case "outline":
260
+ case "link":
261
+ case "text":
262
+ return `bg-action-primary-subtle text-link hover:bg-action-primary-subtle-hover active:bg-action-primary-subtle-active ${outline}`;
263
+ case "tonal":
264
+ // The tonal fill keeps its own hover and pressed steps; the
265
+ // outline is what shows it is on.
266
+ return outline;
267
+ case "accent":
268
+ return `bg-accent-active hover:bg-accent-active ${outline}`;
269
+ case "primary":
270
+ default:
271
+ return `bg-action-primary-active hover:bg-action-primary-active ${outline}`;
61
272
  }
62
273
  });
63
274
 
64
275
  const buttonClasses = $derived.by(() => {
65
276
  const base =
66
- "inline-flex focus-ring items-center justify-center rounded-control shrink-0 transition-colors duration-150 cursor-pointer select-none";
67
- return cn(`${base} ${sizeClass.box} ${variantClass} ${disabledClass} ${className}`);
277
+ "inline-flex focus-ring items-center justify-center rounded-control shrink-0 transition-colors duration-(--duration-base) cursor-pointer select-none";
278
+ // `disabled:` does not match an `<a>`: a disabled link wears the
279
+ // disabled pair itself, in place of its variant. So does a loading
280
+ // button, which is not `:disabled` (it keeps focus): with the
281
+ // variant's classes left out, none of its hover or pressed fills can
282
+ // show. The box is a fixed square, so the border changes no size.
283
+ const state =
284
+ isDisabled && (isLink || isBusy)
285
+ ? "bg-(--color-action-disabled) text-action-disabled-text border border-transparent cursor-not-allowed"
286
+ : `${variantClass} ${isLink ? "" : pressedClass} ${disabledClass}`;
287
+ // Relative only for the badge: it is placed against the button's own box.
288
+ return cn(`${base} ${showCount ? "relative " : ""}${sizeClass.box} ${state} ${className}`);
68
289
  });
69
290
  </script>
70
291
 
71
- <button
72
- {type}
73
- class={buttonClasses}
74
- disabled={isDisabled}
75
- aria-busy={loading ? "true" : undefined}
76
- {onclick}
77
- aria-label={label || undefined}
78
- {...restProps}
79
- >
292
+ {#snippet content()}
80
293
  {#if loading}
81
294
  <span
82
- class="inline-block {sizeClass.spinner} shrink-0 animate-spin rounded-full border-2 border-current border-t-transparent opacity-80"
295
+ class="inline-block {sizeClass.spinner} shrink-0 animate-spin rounded-full border-2 border-current border-t-transparent opacity-80 motion-reduce:animate-pulse"
83
296
  aria-hidden="true"
84
297
  ></span>
85
298
  {:else if children}
86
299
  {@render children()}
87
300
  {/if}
88
- </button>
301
+ {#if showCount}
302
+ <!-- Inside the box, in its upper end corner, whatever the size: the box
303
+ edge is the outer edge, so nothing outside it can cut it. Decorative; the
304
+ name carries the count. -->
305
+ {#if countAsDot}
306
+ <span
307
+ class="pointer-events-none absolute end-0.5 top-0.5 size-2 rounded-full bg-error"
308
+ aria-hidden="true"
309
+ data-icon-button-count="dot"
310
+ ></span>
311
+ {:else}
312
+ <Badge
313
+ size="sm"
314
+ emphasis="solid"
315
+ variant="error"
316
+ aria-hidden="true"
317
+ data-icon-button-count="badge"
318
+ class="pointer-events-none absolute end-0.5 top-0.5 h-[18px] min-h-[18px] min-w-[18px] px-[5px] py-0 text-[11px] leading-[18px] whitespace-nowrap"
319
+ >
320
+ {badgeText(count as number, countMax)}
321
+ </Badge>
322
+ {/if}
323
+ {/if}
324
+ {/snippet}
325
+
326
+ {#if isLink}
327
+ <!-- A loading link is given its Tab stop back, so focus stays on it:
328
+ `tabindex` is written before `href` is taken away, in that order. -->
329
+ <a
330
+ tabindex={isBusy || keepsTabStop ? 0 : undefined}
331
+ href={isDisabled ? undefined : href}
332
+ class={buttonClasses}
333
+ role={isDisabled ? "link" : undefined}
334
+ aria-disabled={isDisabled ? "true" : undefined}
335
+ aria-busy={loading ? "true" : undefined}
336
+ aria-label={accessibleName}
337
+ {...(restProps as unknown as HTMLAnchorAttributes)}
338
+ onclick={handleLinkClick}
339
+ >
340
+ {@render content()}
341
+ </a>
342
+ {:else}
343
+ <button
344
+ type={type ?? "button"}
345
+ class={buttonClasses}
346
+ disabled={!!disabled}
347
+ aria-disabled={isBusy ? "true" : undefined}
348
+ aria-busy={loading ? "true" : undefined}
349
+ aria-pressed={pressed}
350
+ onclick={handleClick}
351
+ aria-label={accessibleName}
352
+ {...restProps}
353
+ >
354
+ {@render content()}
355
+ </button>
356
+ {/if}
@@ -1,15 +1,73 @@
1
- import type { Snippet } from "svelte";
2
- import type { HTMLButtonAttributes } from "svelte/elements";
1
+ import { type Snippet } from "svelte";
2
+ import type { HTMLAnchorAttributes, HTMLButtonAttributes } from "svelte/elements";
3
3
  import type { ButtonVariant, SizeVariant } from "../types/variants.js";
4
+ /** The shared scale plus `xs`, which only the icon button has. */
5
+ type IconButtonSize = SizeVariant | "xs";
6
+ /**
7
+ * One type for the button and the link, not a union of the two elements'
8
+ * attributes: that union is too large for TypeScript to carry through a
9
+ * wrapper such as a Storybook `Meta`. Event handlers are typed for the
10
+ * button; on a link they are called with the same event.
11
+ */
4
12
  type Props = Omit<HTMLButtonAttributes, "class"> & {
13
+ /**
14
+ * Where the link goes. Makes this an `<a>` that looks the same;
15
+ * without it, it is a `<button>`. A link cannot be disabled: while
16
+ * `disabled` or `loading` it has no `href`, is `aria-disabled` and
17
+ * does nothing when pressed. A link is not
18
+ * a toggle: `pressed` is ignored.
19
+ */
20
+ href?: string;
21
+ /** With `href`: where the link opens. */
22
+ target?: HTMLAnchorAttributes["target"];
23
+ /** With `href`: the link's relationship, such as `noopener`. */
24
+ rel?: HTMLAnchorAttributes["rel"];
25
+ /** With `href`: download the address instead of opening it. */
26
+ download?: HTMLAnchorAttributes["download"];
27
+ hreflang?: HTMLAnchorAttributes["hreflang"];
28
+ referrerpolicy?: HTMLAnchorAttributes["referrerpolicy"];
29
+ ping?: HTMLAnchorAttributes["ping"];
5
30
  variant?: ButtonVariant;
6
- size?: SizeVariant;
31
+ /**
32
+ * `xs` is a 24px box for dense, pointer-first layouts (card headers,
33
+ * table rows). That is the WCAG 2.2 minimum target size and no more:
34
+ * where the primary input is touch, use `sm` or larger.
35
+ */
36
+ size?: IconButtonSize;
37
+ /**
38
+ * Colour intent for the `ghost` and `outline` variants: `danger` is
39
+ * the quiet destructive button (inline delete). Other variants ignore it.
40
+ */
41
+ tone?: "default" | "danger";
42
+ /**
43
+ * Makes this a toggle button. When defined (true or false) it renders
44
+ * `aria-pressed` and a click flips it; bind it, or pass it one-way and
45
+ * update your own state in `onclick`. Call `event.preventDefault()` in
46
+ * `onclick` to keep the current state: do that whenever the parent
47
+ * updates later (after a request, say) or may refuse the change, or the
48
+ * button shows a state the parent does not have. Leave undefined for a
49
+ * plain button.
50
+ */
51
+ pressed?: boolean;
7
52
  loading?: boolean;
8
53
  /** Required for icon-only usage (no visible text). */
9
54
  label?: string;
55
+ /**
56
+ * A count drawn on the button, in the attention colour, inside the
57
+ * button's own box (so a bar or an `overflow` ancestor cannot cut it).
58
+ * Nothing is drawn for 0, a negative number or when it is left out;
59
+ * while `loading` it is hidden. At `xs` and `sm` there is no room for
60
+ * a number: a dot is drawn instead. Needs `label`: the accessible name
61
+ * becomes the label, a comma and `countLabel(count)`.
62
+ */
63
+ count?: number;
64
+ /** What the count adds to the accessible name, after the label. Default: "3 new". */
65
+ countLabel?: (count: number) => string;
66
+ /** Above this the badge reads `99+`. The accessible name keeps the real count. */
67
+ countMax?: number;
10
68
  class?: string;
11
69
  children?: Snippet;
12
70
  };
13
- declare const IconButton: import("svelte").Component<Props, {}, "">;
71
+ declare const IconButton: import("svelte").Component<Props, {}, "pressed">;
14
72
  type IconButton = ReturnType<typeof IconButton>;
15
73
  export default IconButton;