zabi-components 8.0.0 → 8.1.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 (364) hide show
  1. package/CHANGELOG.md +1924 -0
  2. package/README.md +243 -10
  3. package/THEME.md +149 -332
  4. package/THEMING.md +1192 -266
  5. package/dist/atoms/ActionPanel.svelte +15 -5
  6. package/dist/atoms/Avatar.svelte +104 -0
  7. package/dist/atoms/Avatar.svelte.d.ts +34 -0
  8. package/dist/atoms/Badge.svelte +36 -7
  9. package/dist/atoms/Badge.svelte.d.ts +2 -2
  10. package/dist/atoms/Button.svelte +177 -27
  11. package/dist/atoms/Button.svelte.d.ts +30 -2
  12. package/dist/atoms/Card.svelte +4 -4
  13. package/dist/atoms/CardHeader.svelte +16 -4
  14. package/dist/atoms/Checkbox.svelte +48 -21
  15. package/dist/atoms/Checkbox.svelte.d.ts +4 -2
  16. package/dist/atoms/CodeBlock.svelte +20 -2
  17. package/dist/atoms/CodeBlock.svelte.d.ts +4 -0
  18. package/dist/atoms/ColorPicker.svelte +259 -49
  19. package/dist/atoms/ColorPicker.svelte.d.ts +3 -0
  20. package/dist/atoms/Container.svelte +16 -8
  21. package/dist/atoms/DateField.svelte +107 -0
  22. package/dist/atoms/DateField.svelte.d.ts +53 -0
  23. package/dist/atoms/FieldMessages.svelte +69 -0
  24. package/dist/atoms/FieldMessages.svelte.d.ts +23 -0
  25. package/dist/atoms/FloatingActionButton.svelte +174 -0
  26. package/dist/atoms/FloatingActionButton.svelte.d.ts +51 -0
  27. package/dist/atoms/Heading.svelte +37 -5
  28. package/dist/atoms/Heading.svelte.d.ts +7 -0
  29. package/dist/atoms/IconButton.svelte +220 -24
  30. package/dist/atoms/IconButton.svelte.d.ts +49 -4
  31. package/dist/atoms/Input.svelte +253 -52
  32. package/dist/atoms/Input.svelte.d.ts +32 -2
  33. package/dist/atoms/List.svelte +4 -1
  34. package/dist/atoms/ListItem.svelte +44 -11
  35. package/dist/atoms/ListItem.svelte.d.ts +5 -0
  36. package/dist/atoms/Progress.svelte +27 -8
  37. package/dist/atoms/Progress.svelte.d.ts +4 -0
  38. package/dist/atoms/Radio.svelte +19 -3
  39. package/dist/atoms/Radio.svelte.d.ts +4 -2
  40. package/dist/atoms/Rating.svelte +494 -0
  41. package/dist/atoms/Rating.svelte.d.ts +56 -0
  42. package/dist/atoms/Select.svelte +433 -91
  43. package/dist/atoms/Select.svelte.d.ts +49 -3
  44. package/dist/atoms/SelectionControl.svelte +94 -17
  45. package/dist/atoms/SelectionControl.svelte.d.ts +4 -3
  46. package/dist/atoms/Skeleton.svelte +1 -1
  47. package/dist/atoms/Slider.svelte +309 -0
  48. package/dist/atoms/Slider.svelte.d.ts +40 -0
  49. package/dist/atoms/Spinner.svelte +57 -0
  50. package/dist/atoms/Spinner.svelte.d.ts +19 -0
  51. package/dist/atoms/Table.svelte +151 -6
  52. package/dist/atoms/Table.svelte.d.ts +15 -3
  53. package/dist/atoms/TemporalField.svelte +140 -0
  54. package/dist/atoms/TemporalField.svelte.d.ts +32 -0
  55. package/dist/atoms/Text.svelte +23 -11
  56. package/dist/atoms/Text.svelte.d.ts +6 -3
  57. package/dist/atoms/Textarea.svelte +55 -44
  58. package/dist/atoms/Textarea.svelte.d.ts +14 -2
  59. package/dist/atoms/ThemeToggle.svelte +223 -44
  60. package/dist/atoms/ThemeToggle.svelte.d.ts +26 -3
  61. package/dist/atoms/TimeField.svelte +108 -0
  62. package/dist/atoms/TimeField.svelte.d.ts +54 -0
  63. package/dist/atoms/Toast.svelte +17 -4
  64. package/dist/atoms/Toast.svelte.d.ts +2 -0
  65. package/dist/atoms/Toggle.svelte +41 -8
  66. package/dist/atoms/Toggle.svelte.d.ts +11 -2
  67. package/dist/atoms/Tooltip.svelte +508 -23
  68. package/dist/atoms/Tooltip.svelte.d.ts +11 -0
  69. package/dist/atoms/ZabiStringsProvider.svelte +45 -0
  70. package/dist/atoms/ZabiStringsProvider.svelte.d.ts +27 -0
  71. package/dist/atoms/index.d.ts +17 -0
  72. package/dist/atoms/index.js +12 -0
  73. package/dist/atoms/selection-control.styles.d.ts +36 -5
  74. package/dist/atoms/selection-control.styles.js +40 -9
  75. package/dist/components/atoms/index.d.ts +17 -0
  76. package/dist/components/atoms/index.d.ts.map +1 -1
  77. package/dist/components/atoms/selection-control.styles.d.ts +36 -5
  78. package/dist/components/atoms/selection-control.styles.d.ts.map +1 -1
  79. package/dist/components/index.d.ts +80 -2
  80. package/dist/components/index.d.ts.map +1 -1
  81. package/dist/components/molecules/index.d.ts +46 -0
  82. package/dist/components/molecules/index.d.ts.map +1 -1
  83. package/dist/components/molecules/toast-store.d.ts +53 -7
  84. package/dist/components/molecules/toast-store.d.ts.map +1 -1
  85. package/dist/components/organisms/index.d.ts +5 -0
  86. package/dist/components/organisms/index.d.ts.map +1 -1
  87. package/dist/components/types/variants.d.ts +15 -1
  88. package/dist/components/types/variants.d.ts.map +1 -1
  89. package/dist/components/util/app-shell.d.ts +28 -0
  90. package/dist/components/util/app-shell.d.ts.map +1 -0
  91. package/dist/components/util/avatar.d.ts +36 -0
  92. package/dist/components/util/avatar.d.ts.map +1 -0
  93. package/dist/components/util/bottom-sheet.d.ts +30 -0
  94. package/dist/components/util/bottom-sheet.d.ts.map +1 -0
  95. package/dist/components/util/bottom-tab-bar.d.ts +35 -0
  96. package/dist/components/util/bottom-tab-bar.d.ts.map +1 -0
  97. package/dist/components/util/calendar.d.ts +56 -0
  98. package/dist/components/util/calendar.d.ts.map +1 -0
  99. package/dist/components/util/collapsible.d.ts +58 -0
  100. package/dist/components/util/collapsible.d.ts.map +1 -0
  101. package/dist/components/util/confirm-dialog.d.ts +12 -0
  102. package/dist/components/util/confirm-dialog.d.ts.map +1 -0
  103. package/dist/components/util/date.d.ts +96 -0
  104. package/dist/components/util/date.d.ts.map +1 -0
  105. package/dist/components/util/drawer.d.ts +13 -0
  106. package/dist/components/util/drawer.d.ts.map +1 -0
  107. package/dist/components/util/dropdown.d.ts +47 -0
  108. package/dist/components/util/dropdown.d.ts.map +1 -0
  109. package/dist/components/util/field.d.ts +39 -0
  110. package/dist/components/util/field.d.ts.map +1 -0
  111. package/dist/components/util/fit-in-viewport.d.ts +201 -0
  112. package/dist/components/util/fit-in-viewport.d.ts.map +1 -0
  113. package/dist/components/util/focus-utils.d.ts +75 -2
  114. package/dist/components/util/focus-utils.d.ts.map +1 -1
  115. package/dist/components/util/hydration.d.ts +45 -0
  116. package/dist/components/util/hydration.d.ts.map +1 -0
  117. package/dist/components/util/keyboard-inset.d.ts +18 -0
  118. package/dist/components/util/keyboard-inset.d.ts.map +1 -0
  119. package/dist/components/util/media-grid.d.ts +51 -0
  120. package/dist/components/util/media-grid.d.ts.map +1 -0
  121. package/dist/components/util/media.d.ts +6 -0
  122. package/dist/components/util/media.d.ts.map +1 -0
  123. package/dist/components/util/overlay-chrome.d.ts +53 -0
  124. package/dist/components/util/overlay-chrome.d.ts.map +1 -0
  125. package/dist/components/util/overlay.d.ts +72 -0
  126. package/dist/components/util/overlay.d.ts.map +1 -0
  127. package/dist/components/util/photo.d.ts +215 -0
  128. package/dist/components/util/photo.d.ts.map +1 -0
  129. package/dist/components/util/portal.d.ts +23 -0
  130. package/dist/components/util/portal.d.ts.map +1 -0
  131. package/dist/components/util/pull-to-refresh.d.ts +27 -0
  132. package/dist/components/util/pull-to-refresh.d.ts.map +1 -0
  133. package/dist/components/util/radio-keys.d.ts +25 -0
  134. package/dist/components/util/radio-keys.d.ts.map +1 -0
  135. package/dist/components/util/rating.d.ts +23 -0
  136. package/dist/components/util/rating.d.ts.map +1 -0
  137. package/dist/components/util/ready-made-strings.d.ts +77 -0
  138. package/dist/components/util/ready-made-strings.d.ts.map +1 -0
  139. package/dist/components/util/scroll-padding.d.ts +20 -0
  140. package/dist/components/util/scroll-padding.d.ts.map +1 -0
  141. package/dist/components/util/segmented-control.d.ts +16 -0
  142. package/dist/components/util/segmented-control.d.ts.map +1 -0
  143. package/dist/components/util/select.d.ts +41 -0
  144. package/dist/components/util/select.d.ts.map +1 -0
  145. package/dist/components/util/sheet-drag.d.ts +60 -0
  146. package/dist/components/util/sheet-drag.d.ts.map +1 -0
  147. package/dist/components/util/sidebar.d.ts +63 -0
  148. package/dist/components/util/sidebar.d.ts.map +1 -0
  149. package/dist/components/util/sortable-list.d.ts +65 -0
  150. package/dist/components/util/sortable-list.d.ts.map +1 -0
  151. package/dist/components/util/stepper.d.ts +40 -0
  152. package/dist/components/util/stepper.d.ts.map +1 -0
  153. package/dist/components/util/swipeable-list-item.d.ts +36 -0
  154. package/dist/components/util/swipeable-list-item.d.ts.map +1 -0
  155. package/dist/components/util/theme-mode.d.ts +80 -0
  156. package/dist/components/util/theme-mode.d.ts.map +1 -0
  157. package/dist/components/util/toaster.d.ts +93 -0
  158. package/dist/components/util/toaster.d.ts.map +1 -0
  159. package/dist/components/util/tooltip.d.ts +10 -0
  160. package/dist/components/util/tooltip.d.ts.map +1 -0
  161. package/dist/components/util/top-navbar.d.ts +11 -0
  162. package/dist/components/util/top-navbar.d.ts.map +1 -0
  163. package/dist/components/util/touch-target.d.ts +31 -0
  164. package/dist/components/util/touch-target.d.ts.map +1 -0
  165. package/dist/components/util/zabi-strings.d.ts +133 -0
  166. package/dist/components/util/zabi-strings.d.ts.map +1 -0
  167. package/dist/create-theme/cli.js +169 -0
  168. package/dist/create-theme/index.d.ts +176 -0
  169. package/dist/create-theme/index.js +817 -0
  170. package/dist/create-theme/lib/ramp-math.js +128 -0
  171. package/dist/create-theme/lib/resolve.js +141 -0
  172. package/dist/create-theme/theme-data.js +1116 -0
  173. package/dist/index.d.ts +80 -2
  174. package/dist/index.js +57 -2
  175. package/dist/molecules/Alert.svelte +33 -5
  176. package/dist/molecules/Alert.svelte.d.ts +2 -0
  177. package/dist/molecules/AppBar.svelte +415 -0
  178. package/dist/molecules/AppBar.svelte.d.ts +69 -0
  179. package/dist/molecules/AvatarGroup.svelte +116 -0
  180. package/dist/molecules/AvatarGroup.svelte.d.ts +40 -0
  181. package/dist/molecules/BottomSheet.svelte +540 -0
  182. package/dist/molecules/BottomSheet.svelte.d.ts +93 -0
  183. package/dist/molecules/BottomTabBar.svelte +297 -0
  184. package/dist/molecules/BottomTabBar.svelte.d.ts +64 -0
  185. package/dist/molecules/Calendar.svelte +597 -0
  186. package/dist/molecules/Calendar.svelte.d.ts +72 -0
  187. package/dist/molecules/Collapsible.svelte +243 -0
  188. package/dist/molecules/Collapsible.svelte.d.ts +44 -0
  189. package/dist/molecules/CollapsibleGroup.svelte +126 -0
  190. package/dist/molecules/CollapsibleGroup.svelte.d.ts +14 -0
  191. package/dist/molecules/ComponentDemo.svelte +16 -4
  192. package/dist/molecules/ComponentDemo.svelte.d.ts +3 -0
  193. package/dist/molecules/ConfirmDialog.svelte +253 -0
  194. package/dist/molecules/ConfirmDialog.svelte.d.ts +55 -0
  195. package/dist/molecules/ContactForm.svelte +34 -17
  196. package/dist/molecules/ContactForm.svelte.d.ts +8 -0
  197. package/dist/molecules/Drawer.svelte +394 -0
  198. package/dist/molecules/Drawer.svelte.d.ts +55 -0
  199. package/dist/molecules/Dropdown.svelte +509 -48
  200. package/dist/molecules/Dropdown.svelte.d.ts +45 -6
  201. package/dist/molecules/DropdownItem.svelte +122 -0
  202. package/dist/molecules/DropdownItem.svelte.d.ts +28 -0
  203. package/dist/molecules/EmptyState.svelte +55 -10
  204. package/dist/molecules/EmptyState.svelte.d.ts +8 -0
  205. package/dist/molecules/FormField.svelte +9 -1
  206. package/dist/molecules/FormField.svelte.d.ts +2 -0
  207. package/dist/molecules/Header.svelte +1 -1
  208. package/dist/molecules/ImageUpload.svelte +383 -70
  209. package/dist/molecules/ImageUpload.svelte.d.ts +47 -2
  210. package/dist/molecules/MediaGrid.svelte +527 -0
  211. package/dist/molecules/MediaGrid.svelte.d.ts +77 -0
  212. package/dist/molecules/Modal.svelte +288 -72
  213. package/dist/molecules/Modal.svelte.d.ts +51 -2
  214. package/dist/molecules/NavigationMenuContent.svelte +58 -1
  215. package/dist/molecules/NavigationMenuItem.svelte +0 -1
  216. package/dist/molecules/NavigationMenuLink.svelte +1 -1
  217. package/dist/molecules/NavigationMenuList.svelte +10 -3
  218. package/dist/molecules/NavigationMenuTrigger.svelte +2 -2
  219. package/dist/molecules/Page.svelte +32 -2
  220. package/dist/molecules/Page.svelte.d.ts +11 -0
  221. package/dist/molecules/PhotoGrid.svelte +433 -0
  222. package/dist/molecules/PhotoGrid.svelte.d.ts +62 -0
  223. package/dist/molecules/PhotoViewer.svelte +1116 -0
  224. package/dist/molecules/PhotoViewer.svelte.d.ts +56 -0
  225. package/dist/molecules/PropsTable.svelte +22 -10
  226. package/dist/molecules/PropsTable.svelte.d.ts +3 -0
  227. package/dist/molecules/PullToRefresh.svelte +263 -0
  228. package/dist/molecules/PullToRefresh.svelte.d.ts +52 -0
  229. package/dist/molecules/RadioGroup.svelte +52 -14
  230. package/dist/molecules/RadioGroup.svelte.d.ts +14 -3
  231. package/dist/molecules/Section.svelte +1 -1
  232. package/dist/molecules/SegmentedControl.svelte +323 -0
  233. package/dist/molecules/SegmentedControl.svelte.d.ts +34 -0
  234. package/dist/molecules/SidebarBrandHeader.svelte +11 -1
  235. package/dist/molecules/SidebarBrandHeader.svelte.d.ts +3 -0
  236. package/dist/molecules/SidebarFooter.svelte +29 -6
  237. package/dist/molecules/SidebarFooter.svelte.d.ts +3 -0
  238. package/dist/molecules/SlideUp.svelte +220 -61
  239. package/dist/molecules/SlideUp.svelte.d.ts +26 -0
  240. package/dist/molecules/SortableList.svelte +632 -0
  241. package/dist/molecules/SortableList.svelte.d.ts +69 -0
  242. package/dist/molecules/Stepper.svelte +548 -0
  243. package/dist/molecules/Stepper.svelte.d.ts +39 -0
  244. package/dist/molecules/StickyActionBar.svelte +191 -0
  245. package/dist/molecules/StickyActionBar.svelte.d.ts +65 -0
  246. package/dist/molecules/SwipeableListItem.svelte +334 -0
  247. package/dist/molecules/SwipeableListItem.svelte.d.ts +54 -0
  248. package/dist/molecules/Tabs.svelte +233 -9
  249. package/dist/molecules/Tabs.svelte.d.ts +7 -0
  250. package/dist/molecules/Toaster.svelte +350 -5
  251. package/dist/molecules/Toaster.svelte.d.ts +95 -2
  252. package/dist/molecules/ToasterToast.svelte +253 -67
  253. package/dist/molecules/ToasterToast.svelte.d.ts +9 -0
  254. package/dist/molecules/UnsavedChangesBar.svelte +212 -0
  255. package/dist/molecules/UnsavedChangesBar.svelte.d.ts +43 -0
  256. package/dist/molecules/index.d.ts +46 -0
  257. package/dist/molecules/index.js +27 -0
  258. package/dist/molecules/toast-store.d.ts +53 -7
  259. package/dist/molecules/toast-store.js +21 -0
  260. package/dist/organisms/AppShell.svelte +196 -0
  261. package/dist/organisms/AppShell.svelte.d.ts +61 -0
  262. package/dist/organisms/SidebarAccountPanel.svelte +107 -12
  263. package/dist/organisms/SidebarAccountPanel.svelte.d.ts +19 -0
  264. package/dist/organisms/SidebarNavigation.svelte +96 -15
  265. package/dist/organisms/SidebarNavigation.svelte.d.ts +29 -1
  266. package/dist/organisms/SidebarPanel.svelte +31 -10
  267. package/dist/organisms/SidebarShell.svelte +162 -11
  268. package/dist/organisms/SidebarShell.svelte.d.ts +56 -2
  269. package/dist/organisms/TopNavbar.svelte +256 -31
  270. package/dist/organisms/TopNavbar.svelte.d.ts +26 -0
  271. package/dist/organisms/index.d.ts +5 -0
  272. package/dist/organisms/index.js +3 -0
  273. package/dist/types/components.d.ts +4 -0
  274. package/dist/types/components.d.ts.map +1 -1
  275. package/dist/types/index.d.ts +605 -25
  276. package/dist/types/index.d.ts.map +1 -1
  277. package/dist/types/variants.ts +17 -1
  278. package/dist/util/app-shell.d.ts +27 -0
  279. package/dist/util/app-shell.js +72 -0
  280. package/dist/util/avatar.d.ts +35 -0
  281. package/dist/util/avatar.js +52 -0
  282. package/dist/util/bottom-sheet.d.ts +29 -0
  283. package/dist/util/bottom-sheet.js +43 -0
  284. package/dist/util/bottom-tab-bar.d.ts +34 -0
  285. package/dist/util/bottom-tab-bar.js +54 -0
  286. package/dist/util/calendar.d.ts +55 -0
  287. package/dist/util/calendar.js +74 -0
  288. package/dist/util/collapsible.d.ts +57 -0
  289. package/dist/util/collapsible.js +23 -0
  290. package/dist/util/confirm-dialog.d.ts +11 -0
  291. package/dist/util/confirm-dialog.js +2 -0
  292. package/dist/util/date.d.ts +95 -0
  293. package/dist/util/date.js +237 -0
  294. package/dist/util/drawer.d.ts +12 -0
  295. package/dist/util/drawer.js +7 -0
  296. package/dist/util/dropdown.d.ts +46 -0
  297. package/dist/util/dropdown.js +21 -0
  298. package/dist/util/field.d.ts +38 -0
  299. package/dist/util/field.js +38 -0
  300. package/dist/util/fit-in-viewport.d.ts +200 -0
  301. package/dist/util/fit-in-viewport.js +399 -0
  302. package/dist/util/focus-utils.d.ts +75 -2
  303. package/dist/util/focus-utils.js +182 -9
  304. package/dist/util/hydration.d.ts +44 -0
  305. package/dist/util/hydration.js +58 -0
  306. package/dist/util/keyboard-inset.d.ts +17 -0
  307. package/dist/util/keyboard-inset.js +53 -0
  308. package/dist/util/media-grid.d.ts +50 -0
  309. package/dist/util/media-grid.js +81 -0
  310. package/dist/util/media.d.ts +5 -0
  311. package/dist/util/media.js +10 -0
  312. package/dist/util/overlay-chrome.d.ts +52 -0
  313. package/dist/util/overlay-chrome.js +56 -0
  314. package/dist/util/overlay.d.ts +71 -0
  315. package/dist/util/overlay.js +240 -0
  316. package/dist/util/photo.d.ts +214 -0
  317. package/dist/util/photo.js +206 -0
  318. package/dist/util/portal.d.ts +22 -0
  319. package/dist/util/portal.js +50 -0
  320. package/dist/util/pull-to-refresh.d.ts +26 -0
  321. package/dist/util/pull-to-refresh.js +30 -0
  322. package/dist/util/radio-keys.d.ts +24 -0
  323. package/dist/util/radio-keys.js +49 -0
  324. package/dist/util/rating.d.ts +22 -0
  325. package/dist/util/rating.js +26 -0
  326. package/dist/util/ready-made-strings.d.ts +76 -0
  327. package/dist/util/ready-made-strings.js +67 -0
  328. package/dist/util/scroll-padding.d.ts +19 -0
  329. package/dist/util/scroll-padding.js +44 -0
  330. package/dist/util/segmented-control.d.ts +15 -0
  331. package/dist/util/segmented-control.js +1 -0
  332. package/dist/util/select.d.ts +40 -0
  333. package/dist/util/select.js +63 -0
  334. package/dist/util/sheet-drag.d.ts +59 -0
  335. package/dist/util/sheet-drag.js +241 -0
  336. package/dist/util/sidebar.d.ts +62 -0
  337. package/dist/util/sidebar.js +38 -0
  338. package/dist/util/sortable-list.d.ts +64 -0
  339. package/dist/util/sortable-list.js +53 -0
  340. package/dist/util/stepper.d.ts +39 -0
  341. package/dist/util/stepper.js +38 -0
  342. package/dist/util/swipeable-list-item.d.ts +35 -0
  343. package/dist/util/swipeable-list-item.js +32 -0
  344. package/dist/util/theme-mode.d.ts +79 -0
  345. package/dist/util/theme-mode.js +121 -0
  346. package/dist/util/toaster.d.ts +92 -0
  347. package/dist/util/toaster.js +75 -0
  348. package/dist/util/tooltip.d.ts +9 -0
  349. package/dist/util/tooltip.js +18 -0
  350. package/dist/util/top-navbar.d.ts +10 -0
  351. package/dist/util/top-navbar.js +5 -0
  352. package/dist/util/touch-target.d.ts +30 -0
  353. package/dist/util/touch-target.js +30 -0
  354. package/dist/util/zabi-strings.d.ts +132 -0
  355. package/dist/util/zabi-strings.js +105 -0
  356. package/dist/zabi-components-colors.css +5 -2
  357. package/dist/zabi-components-theme-dark-only.css +543 -241
  358. package/dist/zabi-components-theme-dark.css +543 -241
  359. package/dist/zabi-components-theme-only.css +1584 -367
  360. package/dist/zabi-components-theme.css +1584 -367
  361. package/dist/zabi-components.css +3885 -518
  362. package/docs/lucide-icons.md +40 -17
  363. package/docs/theme-imports.md +81 -11
  364. package/package.json +35 -8
@@ -1,24 +1,50 @@
1
1
  <script lang="ts">
2
+ import { mergeStrings } from "../util/ready-made-strings.js";
3
+ import { zabiStringsFor } from "../util/zabi-strings.js";
2
4
  import ThemeToggle from "../atoms/ThemeToggle.svelte";
3
5
  import IconButton from "../atoms/IconButton.svelte";
4
- import { ExternalLink, Menu, X } from "@lucide/svelte";
6
+ import ExternalLink from "@lucide/svelte/icons/external-link";
7
+ import Menu from "@lucide/svelte/icons/menu";
8
+ import X from "@lucide/svelte/icons/x";
5
9
  import type { Component, Snippet } from "svelte";
6
10
  import { generateId } from "../util/ssr-safe.js";
7
11
  import { cn } from "../util/cn.js";
12
+ import type { ThemeToggleLabels } from "../util/theme-mode.js";
13
+ import { DEFAULT_TOP_NAVBAR_STRINGS, type TopNavbarStrings } from "../util/top-navbar.js";
14
+ import { isInsideToastRegion } from "../util/focus-utils.js";
8
15
 
9
16
  export interface TopNavbarNavItem {
10
17
  label: string;
11
18
  href: string;
12
19
  icon?: Component<{ size?: number; class?: string }>;
13
20
  iconFilled?: Component<{ size?: number; class?: string }>;
21
+ /** Marks the link and opens it in a new tab. Defaults to true for absolute URLs. */
22
+ external?: boolean;
14
23
  }
15
24
 
25
+ export type TopNavbarCollapseAt = "sm" | "md" | "lg" | "xl";
26
+
16
27
  interface Props {
17
28
  brand?: string;
18
29
  brandHref?: string;
19
30
  /** `aria-label` on `<nav>` when multiple nav landmarks exist. */
20
31
  ariaLabel?: string;
21
32
  showThemeToggle?: boolean;
33
+ /**
34
+ * How the theme toggle steps: `"two"` flips light and dark, `"three"`
35
+ * goes through system, light and dark. As `modes` of ThemeToggle.
36
+ */
37
+ themeModes?: "two" | "three";
38
+ /**
39
+ * The `localStorage` key the theme choice is kept under; `null` keeps
40
+ * nothing. As `storageKey` of ThemeToggle, whose default applies when
41
+ * this is left out.
42
+ */
43
+ themeStorageKey?: string | null;
44
+ /** The texts of the theme toggle's name, for another language. As `labels` of ThemeToggle. */
45
+ themeLabels?: Partial<ThemeToggleLabels>;
46
+ /** The words the bar says by itself: the menu button's two names and the note on a link that opens a new tab. */
47
+ strings?: Partial<TopNavbarStrings>;
22
48
  class?: string;
23
49
  /** @deprecated use `class`. */
24
50
  className?: string;
@@ -27,6 +53,12 @@
27
53
  items?: TopNavbarNavItem[];
28
54
  navVariant?: "header" | "sidebar";
29
55
  currentPath?: string;
56
+ /**
57
+ * Where the links move from the phone menu into the bar: at this
58
+ * breakpoint and wider they sit in the row. Raise it when the row has
59
+ * more items than fit at 768px.
60
+ */
61
+ collapseAt?: TopNavbarCollapseAt;
30
62
  preventNavigation?: boolean;
31
63
  onclick?: (event: Event) => void;
32
64
  }
@@ -36,12 +68,17 @@
36
68
  brandHref,
37
69
  ariaLabel,
38
70
  showThemeToggle = true,
71
+ themeModes = "two",
72
+ themeStorageKey,
73
+ themeLabels,
74
+ strings,
39
75
  class: classAttr = "",
40
76
  className: legacyClass = "",
41
77
  embedded = false,
42
78
  items = [],
43
79
  navVariant = "header",
44
80
  currentPath = "",
81
+ collapseAt = "md",
45
82
  preventNavigation = false,
46
83
  onclick,
47
84
  nav,
@@ -55,18 +92,135 @@
55
92
 
56
93
  const mobileMenuId = generateId("topnavbar-menu");
57
94
 
95
+ /** The app-wide words for this component, from a `ZabiStringsProvider` above it, if there is one. */
96
+ const provided = zabiStringsFor("topNavbar");
97
+ const text = $derived(mergeStrings(DEFAULT_TOP_NAVBAR_STRINGS, provided(), strings));
98
+
58
99
  let isMenuOpen = $state(false);
100
+ let navElement = $state<HTMLElement | null>(null);
101
+ let panelElement = $state<HTMLElement | null>(null);
102
+ let menuButtonHolder = $state<HTMLElement | null>(null);
103
+
104
+ /**
105
+ * The classes that move the links between the row and the menu, written
106
+ * out for each breakpoint: Tailwind only generates a class it can read in
107
+ * the source, so `${collapseAt}:hidden` would produce nothing. `query` is
108
+ * the same breakpoint for the script (Tailwind's defaults).
109
+ */
110
+ const COLLAPSE: Record<
111
+ TopNavbarCollapseAt,
112
+ { row: string; menu: string; brand: string; query: string }
113
+ > = {
114
+ sm: { row: "hidden sm:block", menu: "sm:hidden", brand: "sm:shrink-0", query: "(min-width: 40rem)" },
115
+ md: { row: "hidden md:block", menu: "md:hidden", brand: "md:shrink-0", query: "(min-width: 48rem)" },
116
+ lg: { row: "hidden lg:block", menu: "lg:hidden", brand: "lg:shrink-0", query: "(min-width: 64rem)" },
117
+ xl: { row: "hidden xl:block", menu: "xl:hidden", brand: "xl:shrink-0", query: "(min-width: 80rem)" },
118
+ };
119
+ const collapse = $derived(COLLAPSE[collapseAt] ?? COLLAPSE.md);
59
120
 
60
121
  function toggleMenu() {
61
122
  isMenuOpen = !isMenuOpen;
62
123
  }
63
124
 
125
+ function focusMenuButton() {
126
+ menuButtonHolder?.querySelector("button")?.focus();
127
+ }
128
+
129
+ /**
130
+ * The menu is a disclosure, not a dialog: nothing is trapped or locked, so
131
+ * it has to get out of the way by itself whenever the user has moved on.
132
+ */
64
133
  function handleWindowKeydown(event: KeyboardEvent) {
65
- if (event.key === "Escape" && isMenuOpen) {
134
+ // A menu inside the panel (a Dropdown, say) closes on Escape first.
135
+ if (event.key !== "Escape" || !isMenuOpen || event.defaultPrevented) return;
136
+ const focusInside = !!panelElement?.contains(document.activeElement);
137
+ isMenuOpen = false;
138
+ // The link that had focus is gone; without this, focus falls to <body>.
139
+ if (focusInside) focusMenuButton();
140
+ }
141
+
142
+ /** A toast lies over the menu; a press on it, or focus in it, is not leaving the bar. */
143
+ function isOutside(event: Event): boolean {
144
+ if (isInsideToastRegion(event.target)) return false;
145
+ return !!navElement && !(event.target instanceof Node && navElement.contains(event.target));
146
+ }
147
+
148
+ /**
149
+ * A press outside the bar closes the menu once it is complete (the click),
150
+ * not when it starts. The open menu pushes the page down, so closing it
151
+ * on the way down moved the page back up under the pointer and the
152
+ * control that was pressed never got its click.
153
+ */
154
+ let pressing = false;
155
+
156
+ function handleOutsideClick(event: MouseEvent) {
157
+ if (isMenuOpen && isOutside(event)) isMenuOpen = false;
158
+ }
159
+
160
+ /**
161
+ * Focus that leaves the bar by the keyboard or from a script. A press
162
+ * moves focus too, between its `mousedown` and its click (after the
163
+ * finger has lifted, on a touch screen); that one is left to the click.
164
+ */
165
+ function handleOutsideFocus(event: FocusEvent) {
166
+ if (isMenuOpen && !pressing && isOutside(event)) isMenuOpen = false;
167
+ }
168
+
169
+ /** Following a link in the menu: the page under it is about to change. */
170
+ function handlePanelClick(event: MouseEvent) {
171
+ if (event.target instanceof Element && event.target.closest("a[href]")) {
66
172
  isMenuOpen = false;
67
173
  }
68
174
  }
69
175
 
176
+ // The route changed some other way (history, a link elsewhere on the page).
177
+ let lastPath: string | undefined;
178
+ $effect(() => {
179
+ if (lastPath !== undefined && currentPath !== lastPath) isMenuOpen = false;
180
+ lastPath = currentPath;
181
+ });
182
+
183
+ // Past the breakpoint the menu button is gone, so a menu left open could
184
+ // not be closed, and it would still be open on the way back down.
185
+ $effect(() => {
186
+ if (typeof window === "undefined" || !window.matchMedia) return;
187
+ const wide = window.matchMedia(collapse.query);
188
+ const close = () => {
189
+ if (wide.matches) isMenuOpen = false;
190
+ };
191
+ wide.addEventListener("change", close);
192
+ return () => wide.removeEventListener("change", close);
193
+ });
194
+
195
+ /**
196
+ * The menu scrolls on its own only when it is taller than the room under
197
+ * the bar. A scrolling box clips whatever reaches outside it, and a
198
+ * Dropdown among the `actions` opens past the end of the menu: when the
199
+ * menu fits, that has to stay visible, as it was before the menu could
200
+ * scroll.
201
+ */
202
+ let panelScrolls = $state(false);
203
+ $effect(() => {
204
+ const panel = panelElement;
205
+ const content = panel?.firstElementChild;
206
+ if (!panel || !content) {
207
+ panelScrolls = false;
208
+ return;
209
+ }
210
+ const measure = () => {
211
+ const room = parseFloat(getComputedStyle(panel).maxHeight);
212
+ panelScrolls = Number.isFinite(room) && content.getBoundingClientRect().height > room;
213
+ };
214
+ measure();
215
+ window.addEventListener("resize", measure);
216
+ const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(measure);
217
+ observer?.observe(content);
218
+ return () => {
219
+ window.removeEventListener("resize", measure);
220
+ observer?.disconnect();
221
+ };
222
+ });
223
+
70
224
  function handleNavLinkClick(event: MouseEvent) {
71
225
  if (preventNavigation) {
72
226
  event.preventDefault();
@@ -76,9 +230,10 @@
76
230
  }
77
231
  }
78
232
 
79
- /** Absolute URLs leave the site, so they are marked and open in a new tab. */
80
- function isExternal(href: string): boolean {
81
- return href.startsWith("http://") || href.startsWith("https://");
233
+ /** Absolute URLs leave the site, so they are marked and open in a new tab.
234
+ * `external` overrides that for same-origin links that leave the app. */
235
+ function isExternal(item: TopNavbarNavItem): boolean {
236
+ return item.external ?? (item.href.startsWith("http://") || item.href.startsWith("https://"));
82
237
  }
83
238
 
84
239
  /** App routes: prefix match except `/` and absolute URLs (exact match). */
@@ -98,8 +253,24 @@
98
253
  : "flex flex-col gap-1 md:flex-row md:items-center md:justify-between";
99
254
  });
100
255
 
101
- function getNavItemClasses(): string {
102
- return "flex flex-col gap-1 grow h-full items-center justify-center min-h-0 min-w-0 relative shrink-0 cursor-pointer w-full md:w-auto";
256
+ /** Where a list of links is drawn: in the bar, in the phone menu, or alone (`embedded`). */
257
+ type NavListPlace = "row" | "menu" | "embedded";
258
+
259
+ function getListClasses(place: NavListPlace): string {
260
+ if (place === "embedded" || navVariant === "sidebar") return ulClasses;
261
+ // The row only shows at the breakpoint and wider, and the menu only
262
+ // below it, so neither needs a breakpoint of its own.
263
+ return place === "row"
264
+ ? "flex flex-row items-center justify-between gap-1"
265
+ : "flex flex-col gap-1";
266
+ }
267
+
268
+ function getNavItemClasses(place: NavListPlace = "embedded"): string {
269
+ const base =
270
+ "flex flex-col gap-1 grow h-full items-center justify-center min-h-0 min-w-0 relative shrink-0 cursor-pointer";
271
+ if (place === "row") return `${base} w-auto`;
272
+ if (place === "menu") return `${base} w-full`;
273
+ return `${base} w-full md:w-auto`;
103
274
  }
104
275
 
105
276
  /**
@@ -121,15 +292,20 @@
121
292
  const base =
122
293
  "focus-ring focus-ring--nav group/nav-item flex flex-col items-center justify-center overflow-clip relative rounded-pill shrink-0 transition-colors duration-200 outline-none";
123
294
  return isActive
124
- ? cn(base, "bg-nav-menu-active text-nav-menu-item-active")
295
+ ? // Forced colours drop the fill and recolour the label: the
296
+ // current item keeps an inset outline there, which is drawn.
297
+ cn(
298
+ base,
299
+ "bg-nav-menu-active text-nav-menu-item-active forced-colors:outline-solid forced-colors:outline-2 forced-colors:-outline-offset-2",
300
+ )
125
301
  : cn(
126
302
  base,
127
- "text-nav-menu-item hover:bg-nav-menu-hover hover:text-nav-menu-item-hover",
303
+ "text-nav-menu-item hover:bg-nav-menu-hover hover:text-nav-menu-item-hover active:bg-nav-menu-active",
128
304
  );
129
305
  }
130
306
 
131
307
  function getStateLayerClasses(): string {
132
- return "box-border flex gap-1 h-10 items-center px-4 py-2 relative shrink-0";
308
+ return "box-border flex gap-1 h-10 pointer-coarse:h-11 items-center px-4 py-2 relative shrink-0";
133
309
  }
134
310
 
135
311
  function getLabelClasses(): string {
@@ -143,15 +319,16 @@
143
319
  }
144
320
  </script>
145
321
 
146
- {#snippet defaultNavList()}
147
- <ul class="{ulClasses} list-none m-0 p-0">
322
+ {#snippet defaultNavList(place: NavListPlace)}
323
+ <ul class="{getListClasses(place)} list-none m-0 p-0">
148
324
  {#each items as item (item.href)}
149
325
  {@const isActive = isNavItemActive(item.href)}
150
- {@const external = isExternal(item.href)}
151
- <li class={getNavItemClasses()}>
326
+ {@const external = isExternal(item)}
327
+ <li class={getNavItemClasses(place)}>
328
+ <!-- In the menu the link is the whole row, not a pill as wide as its label. -->
152
329
  <a
153
330
  href={item.href}
154
- class={getIconContainerClasses(isActive)}
331
+ class={cn(getIconContainerClasses(isActive), place === "menu" && "w-full")}
155
332
  onclick={handleNavLinkClick}
156
333
  aria-current={isActive ? "page" : undefined}
157
334
  target={external ? "_blank" : undefined}
@@ -178,7 +355,7 @@
178
355
  class="shrink-0 text-current opacity-70"
179
356
  aria-hidden="true"
180
357
  />
181
- <span class="sr-only">(opens in a new tab)</span>
358
+ <span class="sr-only">{text.opensInNewTab}</span>
182
359
  {/if}
183
360
  </div>
184
361
  </a>
@@ -187,57 +364,68 @@
187
364
  </ul>
188
365
  {/snippet}
189
366
 
190
- <svelte:window onkeydown={handleWindowKeydown} />
367
+ <svelte:window
368
+ onkeydown={handleWindowKeydown}
369
+ onmousedowncapture={() => (pressing = true)}
370
+ onmouseupcapture={() => (pressing = false)}
371
+ onpointercancelcapture={() => (pressing = false)}
372
+ onclickcapture={handleOutsideClick}
373
+ onfocusin={handleOutsideFocus}
374
+ />
191
375
 
192
376
  {#if embedded}
193
377
  <nav class={className} aria-label={ariaLabel} {...restProps}>
194
378
  {#if nav}
195
379
  {@render nav()}
196
380
  {:else}
197
- {@render defaultNavList()}
381
+ {@render defaultNavList("embedded")}
198
382
  {/if}
199
383
  </nav>
200
384
  {:else}
201
385
  <nav
386
+ bind:this={navElement}
202
387
  class={cn("border-b border-border bg-background sticky top-0 z-sticky", className)}
203
388
  aria-label={ariaLabel}
204
389
  {...restProps}
205
390
  >
206
391
  <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
207
392
  <div class="flex justify-between items-center h-16">
208
- <div class="shrink-0">
393
+ <!-- Beside the menu button the brand gives way and is cut short,
394
+ so the button stays on screen however long the name or large the
395
+ text. In the row it keeps its full width, as before. -->
396
+ <div class={cn("flex min-w-0", collapse.brand)}>
209
397
  {#if brandHref}
210
398
  <a
211
399
  href={brandHref}
212
- class="focus-ring text-xl font-bold text-headline transition-colors hover:text-link"
400
+ class="focus-ring block min-w-0 truncate text-xl font-bold text-headline transition-colors hover:text-link active:text-link pointer-coarse:min-h-11 pointer-coarse:leading-[2.75rem]"
213
401
  >
214
402
  {brand}
215
403
  </a>
216
404
  {:else}
217
- <span class="text-xl font-bold text-headline">{brand}</span>
405
+ <span class="block min-w-0 truncate text-xl font-bold text-headline">{brand}</span>
218
406
  {/if}
219
407
  </div>
220
408
 
221
- <div class="hidden md:block">
409
+ <div class={collapse.row}>
222
410
  <div class="ml-10 flex items-center space-x-4">
223
411
  {#if nav}
224
412
  {@render nav()}
225
413
  {:else if items.length > 0}
226
- {@render defaultNavList()}
414
+ {@render defaultNavList("row")}
227
415
  {/if}
228
416
  </div>
229
417
  </div>
230
418
 
231
- <div class="hidden md:block">
419
+ <div class={collapse.row}>
232
420
  <div class="ml-4 flex items-center space-x-4">
233
421
  {@render actions?.()}
234
422
  {#if showThemeToggle}
235
- <ThemeToggle />
423
+ <ThemeToggle modes={themeModes} storageKey={themeStorageKey} labels={themeLabels} />
236
424
  {/if}
237
425
  </div>
238
426
  </div>
239
427
 
240
- <div class="md:hidden">
428
+ <div bind:this={menuButtonHolder} class={cn("ms-2 shrink-0", collapse.menu)}>
241
429
  <!--
242
430
  Was a bare ☰ glyph in a text-2xl span: font-dependent,
243
431
  off the icon scale, and with no disclosure semantics, so
@@ -245,10 +433,10 @@
245
433
  -->
246
434
  <IconButton
247
435
  variant="ghost"
248
- label={isMenuOpen ? "Close menu" : "Open menu"}
436
+ label={isMenuOpen ? text.closeMenu : text.openMenu}
249
437
  onclick={toggleMenu}
250
438
  aria-expanded={isMenuOpen}
251
- aria-controls={mobileMenuId}
439
+ aria-controls={isMenuOpen ? mobileMenuId : undefined}
252
440
  >
253
441
  {#if isMenuOpen}
254
442
  <X size={20} />
@@ -259,21 +447,32 @@
259
447
  </div>
260
448
  </div>
261
449
 
450
+ <!-- `aria-controls` above names this panel only while it exists.
451
+ Keeping it in the DOM, hidden, would render `nav` and `actions` a
452
+ second time on every page for every desktop visitor: duplicate ids
453
+ from the caller's snippets, and a second ThemeToggle mounted. -->
262
454
  {#if isMenuOpen}
263
- <div class="md:hidden" id={mobileMenuId}>
455
+ <!-- svelte-ignore a11y_click_events_have_key_events, a11y_no_static_element_interactions -->
456
+ <div
457
+ bind:this={panelElement}
458
+ class={cn("topnavbar-menu", collapse.menu)}
459
+ id={mobileMenuId}
460
+ data-scrolls={panelScrolls ? "" : undefined}
461
+ onclick={handlePanelClick}
462
+ >
264
463
  <div
265
464
  class="px-2 pt-2 pb-3 space-y-1 sm:px-3 border-t border-border"
266
465
  >
267
466
  {#if nav}
268
467
  {@render nav()}
269
468
  {:else if items.length > 0}
270
- {@render defaultNavList()}
469
+ {@render defaultNavList("menu")}
271
470
  {/if}
272
471
  <div class="pt-4">
273
472
  {@render actions?.()}
274
473
  {#if showThemeToggle}
275
474
  <div class="mt-2">
276
- <ThemeToggle />
475
+ <ThemeToggle modes={themeModes} storageKey={themeStorageKey} labels={themeLabels} />
277
476
  </div>
278
477
  {/if}
279
478
  </div>
@@ -283,3 +482,29 @@
283
482
  </div>
284
483
  </nav>
285
484
  {/if}
485
+
486
+ <style>
487
+ /*
488
+ * The bar is sticky, so an open menu taller than the screen could never be
489
+ * scrolled into view: the page moved under it and its last control stayed
490
+ * below the fold. It takes what is left of the screen under the 4rem bar
491
+ * (and its 1px border) and scrolls on its own, without handing the scroll
492
+ * on to the page when it reaches an end. `dvh` follows a phone's
493
+ * collapsing address bar; `vh` is for browsers without it. In a web app
494
+ * installed to the home screen the bar starts below the status bar, so
495
+ * that inset comes off as well, or the menu's end would be under the
496
+ * bottom of the screen by as much.
497
+ *
498
+ * Only a menu that does not fit scrolls (`data-scrolls`, set by the
499
+ * script): a scrolling box would clip a Dropdown that opens out of it.
500
+ */
501
+ .topnavbar-menu {
502
+ max-height: calc(100vh - 4rem - 1px - env(safe-area-inset-top, 0px));
503
+ max-height: calc(100dvh - 4rem - 1px - env(safe-area-inset-top, 0px));
504
+ }
505
+
506
+ .topnavbar-menu[data-scrolls] {
507
+ overflow-y: auto;
508
+ overscroll-behavior: contain;
509
+ }
510
+ </style>
@@ -1,4 +1,6 @@
1
1
  import type { Component, Snippet } from "svelte";
2
+ import type { ThemeToggleLabels } from "../util/theme-mode.js";
3
+ import { type TopNavbarStrings } from "../util/top-navbar.js";
2
4
  export interface TopNavbarNavItem {
3
5
  label: string;
4
6
  href: string;
@@ -10,13 +12,31 @@ export interface TopNavbarNavItem {
10
12
  size?: number;
11
13
  class?: string;
12
14
  }>;
15
+ /** Marks the link and opens it in a new tab. Defaults to true for absolute URLs. */
16
+ external?: boolean;
13
17
  }
18
+ export type TopNavbarCollapseAt = "sm" | "md" | "lg" | "xl";
14
19
  interface Props {
15
20
  brand?: string;
16
21
  brandHref?: string;
17
22
  /** `aria-label` on `<nav>` when multiple nav landmarks exist. */
18
23
  ariaLabel?: string;
19
24
  showThemeToggle?: boolean;
25
+ /**
26
+ * How the theme toggle steps: `"two"` flips light and dark, `"three"`
27
+ * goes through system, light and dark. As `modes` of ThemeToggle.
28
+ */
29
+ themeModes?: "two" | "three";
30
+ /**
31
+ * The `localStorage` key the theme choice is kept under; `null` keeps
32
+ * nothing. As `storageKey` of ThemeToggle, whose default applies when
33
+ * this is left out.
34
+ */
35
+ themeStorageKey?: string | null;
36
+ /** The texts of the theme toggle's name, for another language. As `labels` of ThemeToggle. */
37
+ themeLabels?: Partial<ThemeToggleLabels>;
38
+ /** The words the bar says by itself: the menu button's two names and the note on a link that opens a new tab. */
39
+ strings?: Partial<TopNavbarStrings>;
20
40
  class?: string;
21
41
  /** @deprecated use `class`. */
22
42
  className?: string;
@@ -25,6 +45,12 @@ interface Props {
25
45
  items?: TopNavbarNavItem[];
26
46
  navVariant?: "header" | "sidebar";
27
47
  currentPath?: string;
48
+ /**
49
+ * Where the links move from the phone menu into the bar: at this
50
+ * breakpoint and wider they sit in the row. Raise it when the row has
51
+ * more items than fit at 768px.
52
+ */
53
+ collapseAt?: TopNavbarCollapseAt;
28
54
  preventNavigation?: boolean;
29
55
  onclick?: (event: Event) => void;
30
56
  }
@@ -3,3 +3,8 @@ export { default as SidebarNavigation } from './SidebarNavigation.svelte';
3
3
  export { default as SidebarShell } from './SidebarShell.svelte';
4
4
  export { default as SidebarAccountPanel } from './SidebarAccountPanel.svelte';
5
5
  export { default as SidebarPanel } from './SidebarPanel.svelte';
6
+ export { default as AppShell } from './AppShell.svelte';
7
+ export { DEFAULT_TOP_NAVBAR_STRINGS } from '../util/top-navbar.js';
8
+ export type { TopNavbarStrings } from '../util/top-navbar.js';
9
+ export { DEFAULT_SIDEBAR_ACCOUNT_PANEL_STRINGS, DEFAULT_SIDEBAR_NAVIGATION_STRINGS, } from '../util/sidebar.js';
10
+ export type { SidebarAccountPanelStrings, SidebarNavigationStrings } from '../util/sidebar.js';
@@ -3,3 +3,6 @@ export { default as SidebarNavigation } from './SidebarNavigation.svelte';
3
3
  export { default as SidebarShell } from './SidebarShell.svelte';
4
4
  export { default as SidebarAccountPanel } from './SidebarAccountPanel.svelte';
5
5
  export { default as SidebarPanel } from './SidebarPanel.svelte';
6
+ export { default as AppShell } from './AppShell.svelte';
7
+ export { DEFAULT_TOP_NAVBAR_STRINGS } from '../util/top-navbar.js';
8
+ export { DEFAULT_SIDEBAR_ACCOUNT_PANEL_STRINGS, DEFAULT_SIDEBAR_NAVIGATION_STRINGS, } from '../util/sidebar.js';
@@ -79,6 +79,10 @@ export interface SelectProps {
79
79
  searchPlaceholder?: string;
80
80
  maxMenuHeight?: string;
81
81
  menuWidth?: string;
82
+ /** `auto` (the default): a BottomSheet on a phone, under the field elsewhere. */
83
+ presentation?: "auto" | "popover" | "sheet" | "native";
84
+ /** The component's own texts; see `SelectStrings`. The single-text props win over it. */
85
+ strings?: Partial<import("../components/util/select.js").SelectStrings>;
82
86
  noResultsText?: string;
83
87
  disabled?: boolean;
84
88
  className?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"components.d.ts","sourceRoot":"","sources":["../../src/types/components.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"components.d.ts","sourceRoot":"","sources":["../../src/types/components.ts"],"names":[],"mappings":"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"}