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,39 @@
1
+ /** Types and pure helpers for `Stepper`. Kept out of the component so they can be tested without a DOM. */
2
+ /** One step: a label, and optionally a line under it. A plain string is a step with only a label. */
3
+ export interface StepperStep {
4
+ label: string;
5
+ /** A short line under the label in the full layout, and under the current step's name in the compact one. */
6
+ description?: string;
7
+ }
8
+ /** A step as the `steps` prop takes it. */
9
+ export type StepperItem = string | StepperStep;
10
+ /** Where a step is in the flow. */
11
+ export type StepperStepState = "completed" | "current" | "upcoming";
12
+ export type StepperLayout = "auto" | "full" | "compact";
13
+ /**
14
+ * Every built-in string. Pass a partial object to `strings` to translate.
15
+ * `step` is counted from 1 in all of them.
16
+ */
17
+ export interface StepperStrings {
18
+ /** The visible start of the compact line: "Step 2 of 3". */
19
+ position: (step: number, total: number) => string;
20
+ /**
21
+ * What a screen reader reads for a step, and the name of its button when
22
+ * the step is one: "Step 1 of 3: Details, completed".
23
+ */
24
+ stepLabel: (step: number, total: number, label: string, state: StepperStepState) => string;
25
+ /** Read out, politely, when the current step changes: "Step 2 of 3: Ratings". */
26
+ announcement: (step: number, total: number, label: string) => string;
27
+ }
28
+ export declare const STEPPER_STRINGS: StepperStrings;
29
+ /** Strings and objects alike, as objects. */
30
+ export declare function normalizeSteps(steps: readonly StepperItem[] | null | undefined): StepperStep[];
31
+ /**
32
+ * The index of the step that is shown as current: `current` as a whole number
33
+ * held within the steps. Below the first step it is the first, past the last
34
+ * it is the last, and something that is not a number is the first. `-1` when
35
+ * there are no steps.
36
+ */
37
+ export declare function clampStep(current: number | null | undefined, total: number): number;
38
+ /** The state of the step at `index` when the step at `current` is the current one. */
39
+ export declare function stepState(index: number, current: number): StepperStepState;
@@ -0,0 +1,38 @@
1
+ /** Types and pure helpers for `Stepper`. Kept out of the component so they can be tested without a DOM. */
2
+ const STATE_WORDS = {
3
+ completed: "completed",
4
+ current: "current",
5
+ upcoming: "upcoming",
6
+ };
7
+ export const STEPPER_STRINGS = {
8
+ position: (step, total) => `Step ${step} of ${total}`,
9
+ stepLabel: (step, total, label, state) => `Step ${step} of ${total}: ${label}, ${STATE_WORDS[state]}`,
10
+ announcement: (step, total, label) => `Step ${step} of ${total}: ${label}`,
11
+ };
12
+ /** Strings and objects alike, as objects. */
13
+ export function normalizeSteps(steps) {
14
+ return (steps ?? []).map((step) => (typeof step === "string" ? { label: step } : step));
15
+ }
16
+ /**
17
+ * The index of the step that is shown as current: `current` as a whole number
18
+ * held within the steps. Below the first step it is the first, past the last
19
+ * it is the last, and something that is not a number is the first. `-1` when
20
+ * there are no steps.
21
+ */
22
+ export function clampStep(current, total) {
23
+ if (total <= 0)
24
+ return -1;
25
+ if (current === null || current === undefined || Number.isNaN(current))
26
+ return 0;
27
+ if (current === Infinity)
28
+ return total - 1;
29
+ if (current === -Infinity)
30
+ return 0;
31
+ return Math.max(0, Math.min(total - 1, Math.trunc(current)));
32
+ }
33
+ /** The state of the step at `index` when the step at `current` is the current one. */
34
+ export function stepState(index, current) {
35
+ if (index < current)
36
+ return "completed";
37
+ return index === current ? "current" : "upcoming";
38
+ }
@@ -0,0 +1,35 @@
1
+ import type { Component } from "svelte";
2
+ /** Public types and shared state for `SwipeableListItem`. */
3
+ /** One action behind a row, such as Delete. */
4
+ export interface SwipeableListItemAction {
5
+ id: string;
6
+ /** The button's text, and its accessible name. */
7
+ label: string;
8
+ /** Drawn above the label. */
9
+ icon?: Component<{
10
+ size?: number;
11
+ class?: string;
12
+ }>;
13
+ /** `danger` for an action that destroys something. */
14
+ tone?: "default" | "danger";
15
+ /** Runs when the button is pressed. The row closes afterwards. */
16
+ onselect: () => void;
17
+ }
18
+ /** The words a `SwipeableListItem` says by itself. */
19
+ export interface SwipeableListItemStrings {
20
+ /** Accessible name of the button that opens the row's actions, and of the group they are in. */
21
+ actions: string;
22
+ }
23
+ export declare const DEFAULT_SWIPEABLE_LIST_ITEM_STRINGS: SwipeableListItemStrings;
24
+ /**
25
+ * Says that a row has opened: every other open row in the same list closes.
26
+ * Returns what to call when this row closes or goes away.
27
+ */
28
+ export declare function registerOpenRow(root: HTMLElement, close: () => void): () => void;
29
+ /**
30
+ * Where a swipe ends: open or closed. A flick decides by its direction,
31
+ * whatever the distance; otherwise the row goes to whichever is nearer.
32
+ * `revealed` and `width` are px of the actions; `velocity` is px per ms,
33
+ * positive towards revealing.
34
+ */
35
+ export declare function settleSwipe(revealed: number, width: number, velocity: number, flick: number): boolean;
@@ -0,0 +1,32 @@
1
+ export const DEFAULT_SWIPEABLE_LIST_ITEM_STRINGS = {
2
+ actions: "Actions",
3
+ };
4
+ /** What groups rows: the nearest list around a row. Rows with none are each on their own. */
5
+ const LIST = 'ul, ol, [role="list"], [role="listbox"]';
6
+ /** The rows that are open now. */
7
+ const openRows = new Set();
8
+ /**
9
+ * Says that a row has opened: every other open row in the same list closes.
10
+ * Returns what to call when this row closes or goes away.
11
+ */
12
+ export function registerOpenRow(root, close) {
13
+ const list = root.closest(LIST);
14
+ for (const other of [...openRows]) {
15
+ if (other.root !== root && list && other.root.closest(LIST) === list)
16
+ other.close();
17
+ }
18
+ const entry = { root, close };
19
+ openRows.add(entry);
20
+ return () => openRows.delete(entry);
21
+ }
22
+ /**
23
+ * Where a swipe ends: open or closed. A flick decides by its direction,
24
+ * whatever the distance; otherwise the row goes to whichever is nearer.
25
+ * `revealed` and `width` are px of the actions; `velocity` is px per ms,
26
+ * positive towards revealing.
27
+ */
28
+ export function settleSwipe(revealed, width, velocity, flick) {
29
+ if (Math.abs(velocity) > flick)
30
+ return velocity > 0;
31
+ return revealed > width / 2;
32
+ }
@@ -0,0 +1,88 @@
1
+ /**
2
+ * What DateField and TimeField share once they are given a `locale`: the
3
+ * words, and the pure parts of the time picker (which hours and minutes
4
+ * there are, which are outside `min` and `max`).
5
+ */
6
+ /** The words DateField says when it has a `locale`. Replace any of them to translate. */
7
+ export interface DateFieldStrings {
8
+ /** The sheet's action that empties the field. Shown while the field has a value and is not `required`. */
9
+ clear: string;
10
+ /** The sheet's name when the field has no label. */
11
+ chooseDate: string;
12
+ }
13
+ export declare const DATE_FIELD_STRINGS: DateFieldStrings;
14
+ /** The words TimeField says when it has a `locale`. Replace any of them to translate. */
15
+ export interface TimeFieldStrings {
16
+ /** The sheet's action that empties the field. Shown while the field has a value and is not `required`. */
17
+ clear: string;
18
+ /** The sheet's action that sets the chosen time and closes it. */
19
+ done: string;
20
+ /** Accessible name of the column of hours. */
21
+ hours: string;
22
+ /** Accessible name of the column of minutes. */
23
+ minutes: string;
24
+ /** The sheet's words beside Done for the time Done will set: "Chosen time 18:00". */
25
+ chosenTime: string;
26
+ /** The sheet's name when the field has no label. */
27
+ chooseTime: string;
28
+ }
29
+ export declare const TIME_FIELD_STRINGS: TimeFieldStrings;
30
+ /** Whether a `locale` was given: a tag, or a list with at least one. */
31
+ export declare function hasLocale(locale: string | string[] | undefined | null): boolean;
32
+ /** The minutes between choices when the app says nothing: five. */
33
+ export declare const DEFAULT_MINUTE_STEP = 5;
34
+ /**
35
+ * Whether the library's time picker can serve this `step`. It has hours and
36
+ * minutes only, so a step in seconds (under 60) or `"any"` is left to the
37
+ * platform's own picker.
38
+ */
39
+ export declare function stepFitsLibraryPicker(step: number | "any" | undefined): boolean;
40
+ /** `step` (in seconds) as whole minutes between choices; five without one. */
41
+ export declare function minuteStep(step: number | "any" | undefined): number;
42
+ /** `"19:30"` (or `"19:30:15"`) as [19, 30]; null for anything else. */
43
+ export declare function parseHourMinute(value: string | null | undefined): [number, number] | null;
44
+ /**
45
+ * The time an empty field's columns stand at: `openAt`, else `now` (an
46
+ * hour and a minute), kept within `min` and `max` and on the minute step.
47
+ * Only a place to scroll to; nothing is chosen. Two-digit strings, as the
48
+ * columns' option values.
49
+ */
50
+ export declare function openingTime(options: {
51
+ openAt?: string;
52
+ now: [number, number];
53
+ stepMinutes: number;
54
+ min?: string;
55
+ max?: string;
56
+ }): [string, string];
57
+ /**
58
+ * Whether a time is within `min` and `max`, either of which may be missing.
59
+ * Like the native input, a `min` later than `max` is a range over midnight:
60
+ * 22:00 to 06:00 allows 23:30 and 05:00.
61
+ */
62
+ export declare function timeInRange(hour: number, minute: number, min?: string, max?: string): boolean;
63
+ export interface TimeChoice {
64
+ /** Two digits: `"07"`. */
65
+ value: string;
66
+ label: string;
67
+ disabled: boolean;
68
+ }
69
+ /** The hour as the locale writes it: "19" in Swedish, "7 PM" in American English. */
70
+ export declare function hourLabel(hour: number, locale: string | string[] | undefined): string;
71
+ /** The minute as two digits, in the locale's own numerals. */
72
+ export declare function minuteLabel(minute: number, locale: string | string[] | undefined): string;
73
+ /** The 24 hours. An hour is disabled when no time in it is within `min` and `max`. */
74
+ export declare function hourChoices(locale: string | string[] | undefined, min?: string, max?: string): TimeChoice[];
75
+ /**
76
+ * The minutes of one hour: every `stepMinutes`, plus the minute of `current`
77
+ * when it is not on the step, so a value such as 19:07 can be kept. A minute
78
+ * is disabled when the time is outside `min` and `max`; with no hour chosen
79
+ * none is.
80
+ */
81
+ export declare function minuteChoices(options: {
82
+ locale: string | string[] | undefined;
83
+ stepMinutes: number;
84
+ hour: string;
85
+ current?: string;
86
+ min?: string;
87
+ max?: string;
88
+ }): TimeChoice[];
@@ -0,0 +1,136 @@
1
+ /**
2
+ * What DateField and TimeField share once they are given a `locale`: the
3
+ * words, and the pure parts of the time picker (which hours and minutes
4
+ * there are, which are outside `min` and `max`).
5
+ */
6
+ import { formatTime } from "./date.js";
7
+ export const DATE_FIELD_STRINGS = {
8
+ clear: "Clear",
9
+ chooseDate: "Choose date",
10
+ };
11
+ export const TIME_FIELD_STRINGS = {
12
+ clear: "Clear",
13
+ done: "Done",
14
+ hours: "Hours",
15
+ minutes: "Minutes",
16
+ chosenTime: "Chosen time",
17
+ chooseTime: "Choose time",
18
+ };
19
+ /** Whether a `locale` was given: a tag, or a list with at least one. */
20
+ export function hasLocale(locale) {
21
+ return Array.isArray(locale) ? locale.length > 0 : !!locale;
22
+ }
23
+ /** The minutes between choices when the app says nothing: five. */
24
+ export const DEFAULT_MINUTE_STEP = 5;
25
+ /**
26
+ * Whether the library's time picker can serve this `step`. It has hours and
27
+ * minutes only, so a step in seconds (under 60) or `"any"` is left to the
28
+ * platform's own picker.
29
+ */
30
+ export function stepFitsLibraryPicker(step) {
31
+ if (step === undefined)
32
+ return true;
33
+ return typeof step === "number" && Number.isFinite(step) && step >= 60;
34
+ }
35
+ /** `step` (in seconds) as whole minutes between choices; five without one. */
36
+ export function minuteStep(step) {
37
+ if (typeof step === "number" && Number.isFinite(step) && step >= 60)
38
+ return Math.round(step / 60);
39
+ return DEFAULT_MINUTE_STEP;
40
+ }
41
+ const pad2 = (value) => String(value).padStart(2, "0");
42
+ /** `"19:30"` (or `"19:30:15"`) as [19, 30]; null for anything else. */
43
+ export function parseHourMinute(value) {
44
+ const match = /^(\d{2}):(\d{2})(?::\d{2}(?:\.\d+)?)?$/.exec(value ?? "");
45
+ if (!match)
46
+ return null;
47
+ const hour = Number(match[1]);
48
+ const minute = Number(match[2]);
49
+ return hour > 23 || minute > 59 ? null : [hour, minute];
50
+ }
51
+ /**
52
+ * The time an empty field's columns stand at: `openAt`, else `now` (an
53
+ * hour and a minute), kept within `min` and `max` and on the minute step.
54
+ * Only a place to scroll to; nothing is chosen. Two-digit strings, as the
55
+ * columns' option values.
56
+ */
57
+ export function openingTime(options) {
58
+ const { openAt, now, stepMinutes, min, max } = options;
59
+ const [hour, minute] = parseHourMinute(openAt) ?? now;
60
+ let at = hour * 60 + minute;
61
+ const lower = parseHourMinute(min);
62
+ const upper = parseHourMinute(max);
63
+ const from = lower ? lower[0] * 60 + lower[1] : null;
64
+ const to = upper ? upper[0] * 60 + upper[1] : null;
65
+ const inRange = (value) => timeInRange(Math.floor(value / 60) % 24, value % 60, min, max);
66
+ if (!inRange(at)) {
67
+ const overMidnight = from !== null && to !== null && from > to;
68
+ at = from !== null && (overMidnight || at < from) ? from : (to ?? at);
69
+ }
70
+ const floored = Math.floor(at / stepMinutes) * stepMinutes;
71
+ const stepped = inRange(floored) ? floored : Math.min(Math.ceil(at / stepMinutes) * stepMinutes, 23 * 60 + 59);
72
+ return [pad2(Math.floor(stepped / 60)), pad2(stepped % 60)];
73
+ }
74
+ /**
75
+ * Whether a time is within `min` and `max`, either of which may be missing.
76
+ * Like the native input, a `min` later than `max` is a range over midnight:
77
+ * 22:00 to 06:00 allows 23:30 and 05:00.
78
+ */
79
+ export function timeInRange(hour, minute, min, max) {
80
+ const at = hour * 60 + minute;
81
+ const lower = parseHourMinute(min);
82
+ const upper = parseHourMinute(max);
83
+ const from = lower ? lower[0] * 60 + lower[1] : null;
84
+ const to = upper ? upper[0] * 60 + upper[1] : null;
85
+ if (from !== null && to !== null && from > to)
86
+ return at >= from || at <= to;
87
+ if (from !== null && at < from)
88
+ return false;
89
+ if (to !== null && at > to)
90
+ return false;
91
+ return true;
92
+ }
93
+ /** The hour as the locale writes it: "19" in Swedish, "7 PM" in American English. */
94
+ export function hourLabel(hour, locale) {
95
+ return formatTime(`${pad2(hour)}:00`, locale, { hour: "numeric" }) || pad2(hour);
96
+ }
97
+ /** The minute as two digits, in the locale's own numerals. */
98
+ export function minuteLabel(minute, locale) {
99
+ try {
100
+ return new Intl.NumberFormat(locale || undefined, { minimumIntegerDigits: 2, useGrouping: false }).format(minute);
101
+ }
102
+ catch {
103
+ return pad2(minute);
104
+ }
105
+ }
106
+ /** The 24 hours. An hour is disabled when no time in it is within `min` and `max`. */
107
+ export function hourChoices(locale, min, max) {
108
+ return Array.from({ length: 24 }, (_, hour) => ({
109
+ value: pad2(hour),
110
+ label: hourLabel(hour, locale),
111
+ disabled: !Array.from({ length: 60 }, (_, minute) => minute).some((minute) => timeInRange(hour, minute, min, max)),
112
+ }));
113
+ }
114
+ /**
115
+ * The minutes of one hour: every `stepMinutes`, plus the minute of `current`
116
+ * when it is not on the step, so a value such as 19:07 can be kept. A minute
117
+ * is disabled when the time is outside `min` and `max`; with no hour chosen
118
+ * none is.
119
+ */
120
+ export function minuteChoices(options) {
121
+ const { locale, stepMinutes, hour, current, min, max } = options;
122
+ const minutes = new Set();
123
+ for (let minute = 0; minute < 60; minute += stepMinutes)
124
+ minutes.add(minute);
125
+ const now = parseHourMinute(current);
126
+ if (now)
127
+ minutes.add(now[1]);
128
+ const chosenHour = hour === "" ? null : Number(hour);
129
+ return [...minutes]
130
+ .sort((a, b) => a - b)
131
+ .map((minute) => ({
132
+ value: pad2(minute),
133
+ label: minuteLabel(minute, locale),
134
+ disabled: chosenHour !== null && !timeInRange(chosenHour, minute, min, max),
135
+ }));
136
+ }
@@ -0,0 +1,79 @@
1
+ /**
2
+ * The page's theme mode, read and written in one place.
3
+ *
4
+ * The theme is switched on `<html>`: `data-theme="auto" | "light" | "dark"`,
5
+ * or the older `dark` class (THEMING.md, "Light, dark and auto"). ThemeToggle
6
+ * uses these helpers, and so can an app that renders a control of its own, a
7
+ * SegmentedControl with three options for instance: both then read and write
8
+ * the same attribute, and ThemeToggle follows whatever the other one sets.
9
+ *
10
+ * Everything here is safe to call on the server: without a document the
11
+ * readers return the default and the writers do nothing.
12
+ */
13
+ /** `"auto"` follows the system; the other two are a choice. */
14
+ export type ThemeMode = "auto" | "light" | "dark";
15
+ /** The modes in the order a three-way ThemeToggle steps through them. */
16
+ export declare const THEME_MODES: readonly ThemeMode[];
17
+ /** Where the choice is kept in `localStorage` unless a key is given. The key ThemeToggle has always used. */
18
+ export declare const DEFAULT_THEME_STORAGE_KEY = "theme";
19
+ /** The texts ThemeToggle builds its accessible name from. Pass any of them as `labels`. */
20
+ export interface ThemeToggleLabels {
21
+ /** What `"auto"` is called, with three modes. Default `"system"`. */
22
+ auto: string;
23
+ /** Default `"light"`. */
24
+ light: string;
25
+ /** Default `"dark"`. */
26
+ dark: string;
27
+ /**
28
+ * The name with three modes, from the current mode's word and the next
29
+ * one's. Default: "Theme: system. Switch to light".
30
+ */
31
+ describe: (current: string, next: string) => string;
32
+ /**
33
+ * The name with two modes. It does not change: the button is a switch, and
34
+ * `aria-pressed` says whether dark is on. Default "Dark mode".
35
+ */
36
+ darkMode: string;
37
+ /** The name before the button mounts, when the mode is not known yet. Default "Theme toggle". */
38
+ beforeMount: string;
39
+ }
40
+ export declare function isThemeMode(value: unknown): value is ThemeMode;
41
+ /**
42
+ * The mode the page is in. `data-theme` says it outright; a page without the
43
+ * attribute is dark with the `dark` class and light without it (such a page
44
+ * does not follow the system, so it is never `"auto"`).
45
+ */
46
+ export declare function getThemeMode(): ThemeMode;
47
+ /** Whether the page is dark right now: by the class, by `data-theme="dark"`, or by `auto` on a dark system. */
48
+ export declare function isThemeDark(): boolean;
49
+ export interface SetThemeModeOptions {
50
+ /**
51
+ * Where to keep the choice in `localStorage`. Default `"theme"`; `null`
52
+ * keeps nothing (an app that stores the choice in its own backend).
53
+ */
54
+ storageKey?: string | null;
55
+ }
56
+ /**
57
+ * Puts the page in `mode` by writing `data-theme` on `<html>`, and remembers
58
+ * it. A leftover `dark` class and an inline `color-scheme` are removed: either
59
+ * would hold the page dark, or its native controls, under another mode. The
60
+ * theme sets `color-scheme` for each value of the attribute.
61
+ */
62
+ export declare function setThemeMode(mode: ThemeMode, options?: SetThemeModeOptions): void;
63
+ /** The stored choice, or `null` when there is none, it is not a mode, or `storageKey` is `null`. */
64
+ export declare function getStoredThemeMode(storageKey?: string | null): ThemeMode | null;
65
+ /** Remembers `mode` under `storageKey` (default `"theme"`); `null` keeps nothing. */
66
+ export declare function storeThemeMode(mode: ThemeMode, storageKey?: string | null): void;
67
+ /**
68
+ * A script for `<head>` that applies the stored mode before the first paint,
69
+ * so a returning visitor does not see the other theme flash by. Returns the
70
+ * source as a string; it has no dependencies and can be inlined as it is.
71
+ *
72
+ * It writes to whichever mechanism the page uses, as ThemeToggle does:
73
+ * `data-theme` when `<html>` already has the attribute or the stored mode is
74
+ * `"auto"`, and the `dark` class otherwise. With nothing stored it does
75
+ * nothing, and the markup's own `data-theme` (or its absence) stands.
76
+ *
77
+ * The key is written into the script as a JSON string, so any key is safe.
78
+ */
79
+ export declare function themeInitScript(storageKey?: string): string;
@@ -0,0 +1,121 @@
1
+ /**
2
+ * The page's theme mode, read and written in one place.
3
+ *
4
+ * The theme is switched on `<html>`: `data-theme="auto" | "light" | "dark"`,
5
+ * or the older `dark` class (THEMING.md, "Light, dark and auto"). ThemeToggle
6
+ * uses these helpers, and so can an app that renders a control of its own, a
7
+ * SegmentedControl with three options for instance: both then read and write
8
+ * the same attribute, and ThemeToggle follows whatever the other one sets.
9
+ *
10
+ * Everything here is safe to call on the server: without a document the
11
+ * readers return the default and the writers do nothing.
12
+ */
13
+ /** The modes in the order a three-way ThemeToggle steps through them. */
14
+ export const THEME_MODES = ["auto", "light", "dark"];
15
+ /** Where the choice is kept in `localStorage` unless a key is given. The key ThemeToggle has always used. */
16
+ export const DEFAULT_THEME_STORAGE_KEY = "theme";
17
+ export function isThemeMode(value) {
18
+ return value === "auto" || value === "light" || value === "dark";
19
+ }
20
+ function root() {
21
+ return typeof document === "undefined" ? undefined : document.documentElement;
22
+ }
23
+ function storage() {
24
+ try {
25
+ return typeof localStorage === "undefined" ? undefined : localStorage;
26
+ }
27
+ catch {
28
+ // Reading `localStorage` throws where storage is blocked.
29
+ return undefined;
30
+ }
31
+ }
32
+ /**
33
+ * The mode the page is in. `data-theme` says it outright; a page without the
34
+ * attribute is dark with the `dark` class and light without it (such a page
35
+ * does not follow the system, so it is never `"auto"`).
36
+ */
37
+ export function getThemeMode() {
38
+ const html = root();
39
+ if (!html)
40
+ return "light";
41
+ const attribute = html.getAttribute("data-theme");
42
+ if (isThemeMode(attribute))
43
+ return attribute;
44
+ return html.classList.contains("dark") ? "dark" : "light";
45
+ }
46
+ /** Whether the page is dark right now: by the class, by `data-theme="dark"`, or by `auto` on a dark system. */
47
+ export function isThemeDark() {
48
+ const html = root();
49
+ if (!html)
50
+ return false;
51
+ // The class brings the dark tokens whatever the attribute says.
52
+ if (html.classList.contains("dark"))
53
+ return true;
54
+ const mode = getThemeMode();
55
+ if (mode === "auto") {
56
+ return typeof window !== "undefined" && !!window.matchMedia?.("(prefers-color-scheme: dark)").matches;
57
+ }
58
+ return mode === "dark";
59
+ }
60
+ /**
61
+ * Puts the page in `mode` by writing `data-theme` on `<html>`, and remembers
62
+ * it. A leftover `dark` class and an inline `color-scheme` are removed: either
63
+ * would hold the page dark, or its native controls, under another mode. The
64
+ * theme sets `color-scheme` for each value of the attribute.
65
+ */
66
+ export function setThemeMode(mode, options = {}) {
67
+ if (!isThemeMode(mode))
68
+ return;
69
+ const html = root();
70
+ if (!html)
71
+ return;
72
+ html.setAttribute("data-theme", mode);
73
+ html.classList.remove("dark");
74
+ html.style.removeProperty("color-scheme");
75
+ storeThemeMode(mode, options.storageKey);
76
+ }
77
+ /** The stored choice, or `null` when there is none, it is not a mode, or `storageKey` is `null`. */
78
+ export function getStoredThemeMode(storageKey = DEFAULT_THEME_STORAGE_KEY) {
79
+ if (storageKey === null)
80
+ return null;
81
+ try {
82
+ const stored = storage()?.getItem(storageKey);
83
+ return isThemeMode(stored) ? stored : null;
84
+ }
85
+ catch {
86
+ return null;
87
+ }
88
+ }
89
+ /** Remembers `mode` under `storageKey` (default `"theme"`); `null` keeps nothing. */
90
+ export function storeThemeMode(mode, storageKey = DEFAULT_THEME_STORAGE_KEY) {
91
+ if (storageKey === null)
92
+ return;
93
+ try {
94
+ storage()?.setItem(storageKey, mode);
95
+ }
96
+ catch {
97
+ // Storage full or blocked: the page is still switched.
98
+ }
99
+ }
100
+ /**
101
+ * A script for `<head>` that applies the stored mode before the first paint,
102
+ * so a returning visitor does not see the other theme flash by. Returns the
103
+ * source as a string; it has no dependencies and can be inlined as it is.
104
+ *
105
+ * It writes to whichever mechanism the page uses, as ThemeToggle does:
106
+ * `data-theme` when `<html>` already has the attribute or the stored mode is
107
+ * `"auto"`, and the `dark` class otherwise. With nothing stored it does
108
+ * nothing, and the markup's own `data-theme` (or its absence) stands.
109
+ *
110
+ * The key is written into the script as a JSON string, so any key is safe.
111
+ */
112
+ export function themeInitScript(storageKey = DEFAULT_THEME_STORAGE_KEY) {
113
+ const key = JSON.stringify(String(storageKey)).replace(/</g, "\\u003c");
114
+ return ("(function(){try{" +
115
+ `var m=localStorage.getItem(${key});` +
116
+ 'if(m!=="auto"&&m!=="light"&&m!=="dark")return;' +
117
+ "var r=document.documentElement;" +
118
+ 'if(r.hasAttribute("data-theme")||m==="auto"){r.setAttribute("data-theme",m);r.classList.remove("dark")}' +
119
+ 'else{r.classList.toggle("dark",m==="dark")}' +
120
+ "}catch(e){}})();");
121
+ }