@nanisoft/prism-ui 0.10.2 → 0.13.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 (334) hide show
  1. package/LICENSE +21 -21
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/blocks/app-shell-01/app-shell.js +4 -4
  4. package/dist/blocks/app-shell-01/index.d.ts +2 -2
  5. package/dist/blocks/app-shell-01/index.js +1 -1
  6. package/dist/blocks/auth-form-01/auth-form.d.ts +11 -1
  7. package/dist/blocks/auth-form-01/auth-form.d.ts.map +1 -1
  8. package/dist/blocks/auth-form-01/auth-form.js +11 -8
  9. package/dist/blocks/auth-form-01/index.d.ts +2 -2
  10. package/dist/blocks/auth-form-01/index.js +1 -1
  11. package/dist/blocks/cta-01/cta.d.ts +26 -21
  12. package/dist/blocks/cta-01/cta.d.ts.map +1 -1
  13. package/dist/blocks/cta-01/cta.js +2 -2
  14. package/dist/blocks/cta-01/index.d.ts +2 -2
  15. package/dist/blocks/cta-01/index.js +1 -1
  16. package/dist/blocks/data-table-01/data-table.js +7 -7
  17. package/dist/blocks/data-table-01/index.d.ts +2 -2
  18. package/dist/blocks/data-table-01/index.js +1 -1
  19. package/dist/blocks/empty-state-01/empty-state.d.ts +143 -0
  20. package/dist/blocks/empty-state-01/empty-state.d.ts.map +1 -0
  21. package/dist/blocks/empty-state-01/empty-state.js +104 -0
  22. package/dist/blocks/empty-state-01/index.d.ts +3 -0
  23. package/dist/blocks/empty-state-01/index.d.ts.map +1 -0
  24. package/dist/blocks/empty-state-01/index.js +1 -0
  25. package/dist/blocks/feature-grid-01/feature-grid.d.ts +28 -1
  26. package/dist/blocks/feature-grid-01/feature-grid.d.ts.map +1 -1
  27. package/dist/blocks/feature-grid-01/feature-grid.js +34 -3
  28. package/dist/blocks/feature-grid-01/index.d.ts +2 -2
  29. package/dist/blocks/feature-grid-01/index.js +1 -1
  30. package/dist/blocks/hero-01/hero.d.ts +35 -15
  31. package/dist/blocks/hero-01/hero.d.ts.map +1 -1
  32. package/dist/blocks/hero-01/hero.js +14 -9
  33. package/dist/blocks/hero-01/index.d.ts +2 -1
  34. package/dist/blocks/hero-01/index.d.ts.map +1 -1
  35. package/dist/blocks/hero-01/index.js +1 -1
  36. package/dist/blocks/index.d.ts +20 -20
  37. package/dist/blocks/index.js +19 -19
  38. package/dist/blocks/instrument-panel-01/index.d.ts +2 -2
  39. package/dist/blocks/instrument-panel-01/index.js +1 -1
  40. package/dist/blocks/instrument-panel-01/instrument-panel.js +1 -1
  41. package/dist/blocks/logo-strip-01/index.d.ts +2 -2
  42. package/dist/blocks/logo-strip-01/index.js +1 -1
  43. package/dist/blocks/logo-strip-01/logo-strip.d.ts +1 -1
  44. package/dist/blocks/logo-strip-01/logo-strip.js +2 -2
  45. package/dist/blocks/note-grid-01/index.d.ts +2 -2
  46. package/dist/blocks/note-grid-01/index.js +1 -1
  47. package/dist/blocks/note-grid-01/note-grid.d.ts +1 -1
  48. package/dist/blocks/note-grid-01/note-grid.js +1 -1
  49. package/dist/blocks/page-header-01/index.d.ts +2 -2
  50. package/dist/blocks/page-header-01/index.js +1 -1
  51. package/dist/blocks/page-header-01/page-header.d.ts +1 -1
  52. package/dist/blocks/page-header-01/page-header.js +4 -4
  53. package/dist/blocks/pricing-01/index.d.ts +1 -1
  54. package/dist/blocks/pricing-01/index.js +1 -1
  55. package/dist/blocks/pricing-01/pricing.d.ts +8 -1
  56. package/dist/blocks/pricing-01/pricing.d.ts.map +1 -1
  57. package/dist/blocks/pricing-01/pricing.js +15 -5
  58. package/dist/blocks/process-flow-01/index.d.ts +3 -0
  59. package/dist/blocks/process-flow-01/index.d.ts.map +1 -0
  60. package/dist/blocks/process-flow-01/index.js +1 -0
  61. package/dist/blocks/process-flow-01/process-flow.d.ts +118 -0
  62. package/dist/blocks/process-flow-01/process-flow.d.ts.map +1 -0
  63. package/dist/blocks/process-flow-01/process-flow.js +71 -0
  64. package/dist/blocks/process-rail-01/index.d.ts +2 -2
  65. package/dist/blocks/process-rail-01/index.js +1 -1
  66. package/dist/blocks/process-rail-01/process-rail.d.ts +1 -1
  67. package/dist/blocks/process-rail-01/process-rail.js +2 -2
  68. package/dist/blocks/product-grid-01/index.d.ts +2 -2
  69. package/dist/blocks/product-grid-01/index.js +1 -1
  70. package/dist/blocks/product-grid-01/product-grid.d.ts +37 -5
  71. package/dist/blocks/product-grid-01/product-grid.d.ts.map +1 -1
  72. package/dist/blocks/product-grid-01/product-grid.js +20 -6
  73. package/dist/blocks/run-console-01/index.d.ts +3 -0
  74. package/dist/blocks/run-console-01/index.d.ts.map +1 -0
  75. package/dist/blocks/run-console-01/index.js +1 -0
  76. package/dist/blocks/run-console-01/run-console.d.ts +111 -0
  77. package/dist/blocks/run-console-01/run-console.d.ts.map +1 -0
  78. package/dist/blocks/run-console-01/run-console.js +48 -0
  79. package/dist/blocks/settings-panel-01/index.d.ts +2 -2
  80. package/dist/blocks/settings-panel-01/index.js +1 -1
  81. package/dist/blocks/settings-panel-01/settings-panel.d.ts +11 -1
  82. package/dist/blocks/settings-panel-01/settings-panel.d.ts.map +1 -1
  83. package/dist/blocks/settings-panel-01/settings-panel.js +15 -10
  84. package/dist/blocks/site-footer/index.d.ts +2 -2
  85. package/dist/blocks/site-footer/index.js +1 -1
  86. package/dist/blocks/site-footer/site-footer.d.ts +1 -1
  87. package/dist/blocks/site-footer/site-footer.js +2 -2
  88. package/dist/blocks/site-header/index.d.ts +2 -2
  89. package/dist/blocks/site-header/index.js +1 -1
  90. package/dist/blocks/site-header/site-header.d.ts +2 -2
  91. package/dist/blocks/site-header/site-header.js +3 -3
  92. package/dist/blocks/site-navbar/index.d.ts +3 -0
  93. package/dist/blocks/site-navbar/index.d.ts.map +1 -0
  94. package/dist/blocks/site-navbar/index.js +1 -0
  95. package/dist/blocks/site-navbar/mobile-nav.d.ts +48 -0
  96. package/dist/blocks/site-navbar/mobile-nav.d.ts.map +1 -0
  97. package/dist/blocks/site-navbar/mobile-nav.js +35 -0
  98. package/dist/blocks/site-navbar/mode-toggle.d.ts +39 -0
  99. package/dist/blocks/site-navbar/mode-toggle.d.ts.map +1 -0
  100. package/dist/blocks/site-navbar/mode-toggle.js +39 -0
  101. package/dist/blocks/site-navbar/navbar-controls.d.ts +79 -0
  102. package/dist/blocks/site-navbar/navbar-controls.d.ts.map +1 -0
  103. package/dist/blocks/site-navbar/navbar-controls.js +40 -0
  104. package/dist/blocks/site-navbar/search-entry.d.ts +29 -0
  105. package/dist/blocks/site-navbar/search-entry.d.ts.map +1 -0
  106. package/dist/blocks/site-navbar/search-entry.js +52 -0
  107. package/dist/blocks/site-navbar/site-navbar.d.ts +212 -0
  108. package/dist/blocks/site-navbar/site-navbar.d.ts.map +1 -0
  109. package/dist/blocks/site-navbar/site-navbar.js +61 -0
  110. package/dist/blocks/site-navbar/sites-menu.d.ts +40 -0
  111. package/dist/blocks/site-navbar/sites-menu.d.ts.map +1 -0
  112. package/dist/blocks/site-navbar/sites-menu.js +48 -0
  113. package/dist/blocks/site-navbar/theme-menu.d.ts +47 -0
  114. package/dist/blocks/site-navbar/theme-menu.d.ts.map +1 -0
  115. package/dist/blocks/site-navbar/theme-menu.js +55 -0
  116. package/dist/blocks/stack-grid-01/index.d.ts +2 -2
  117. package/dist/blocks/stack-grid-01/index.js +1 -1
  118. package/dist/blocks/stack-grid-01/stack-grid.d.ts +42 -11
  119. package/dist/blocks/stack-grid-01/stack-grid.d.ts.map +1 -1
  120. package/dist/blocks/stack-grid-01/stack-grid.js +15 -7
  121. package/dist/blocks/stats-01/index.d.ts +9 -1
  122. package/dist/blocks/stats-01/index.d.ts.map +1 -1
  123. package/dist/blocks/stats-01/index.js +8 -1
  124. package/dist/blocks/stats-01/stats.d.ts +1 -1
  125. package/dist/blocks/stats-01/stats.js +2 -2
  126. package/dist/blocks/status-ledger-01/index.d.ts +2 -2
  127. package/dist/blocks/status-ledger-01/index.js +1 -1
  128. package/dist/blocks/status-ledger-01/status-ledger.d.ts +1 -1
  129. package/dist/blocks/status-ledger-01/status-ledger.js +2 -2
  130. package/dist/catalog.d.ts +1 -1
  131. package/dist/catalog.d.ts.map +1 -1
  132. package/dist/catalog.js +473 -1
  133. package/dist/components/index.d.ts +104 -66
  134. package/dist/components/index.d.ts.map +1 -1
  135. package/dist/components/index.js +74 -40
  136. package/dist/components/ui/accordion.js +1 -1
  137. package/dist/components/ui/alert-dialog.d.ts +119 -0
  138. package/dist/components/ui/alert-dialog.d.ts.map +1 -0
  139. package/dist/components/ui/alert-dialog.js +82 -0
  140. package/dist/components/ui/alert.js +1 -1
  141. package/dist/components/ui/aspect-ratio.d.ts +60 -0
  142. package/dist/components/ui/aspect-ratio.d.ts.map +1 -0
  143. package/dist/components/ui/aspect-ratio.js +61 -0
  144. package/dist/components/ui/avatar.js +1 -1
  145. package/dist/components/ui/badge.js +1 -1
  146. package/dist/components/ui/breadcrumb.js +1 -1
  147. package/dist/components/ui/button-group.d.ts +68 -0
  148. package/dist/components/ui/button-group.d.ts.map +1 -0
  149. package/dist/components/ui/button-group.js +54 -0
  150. package/dist/components/ui/button.js +1 -1
  151. package/dist/components/ui/calendar.d.ts +158 -0
  152. package/dist/components/ui/calendar.d.ts.map +1 -0
  153. package/dist/components/ui/calendar.js +216 -0
  154. package/dist/components/ui/card.d.ts +18 -6
  155. package/dist/components/ui/card.d.ts.map +1 -1
  156. package/dist/components/ui/card.js +23 -8
  157. package/dist/components/ui/carousel.d.ts +118 -0
  158. package/dist/components/ui/carousel.d.ts.map +1 -0
  159. package/dist/components/ui/carousel.js +152 -0
  160. package/dist/components/ui/chart-frame.d.ts +216 -0
  161. package/dist/components/ui/chart-frame.d.ts.map +1 -0
  162. package/dist/components/ui/chart-frame.js +286 -0
  163. package/dist/components/ui/checkbox.js +1 -1
  164. package/dist/components/ui/collapsible.d.ts +97 -0
  165. package/dist/components/ui/collapsible.d.ts.map +1 -0
  166. package/dist/components/ui/collapsible.js +54 -0
  167. package/dist/components/ui/combobox.d.ts +141 -0
  168. package/dist/components/ui/combobox.d.ts.map +1 -0
  169. package/dist/components/ui/combobox.js +243 -0
  170. package/dist/components/ui/command-palette.d.ts +106 -0
  171. package/dist/components/ui/command-palette.d.ts.map +1 -0
  172. package/dist/components/ui/command-palette.js +176 -0
  173. package/dist/components/ui/command.d.ts +82 -0
  174. package/dist/components/ui/command.d.ts.map +1 -0
  175. package/dist/components/ui/command.js +37 -0
  176. package/dist/components/ui/context-menu.d.ts +151 -0
  177. package/dist/components/ui/context-menu.d.ts.map +1 -0
  178. package/dist/components/ui/context-menu.js +97 -0
  179. package/dist/components/ui/cta-link.js +1 -1
  180. package/dist/components/ui/date-picker.d.ts +111 -0
  181. package/dist/components/ui/date-picker.d.ts.map +1 -0
  182. package/dist/components/ui/date-picker.js +74 -0
  183. package/dist/components/ui/diagram.d.ts +84 -15
  184. package/dist/components/ui/diagram.d.ts.map +1 -1
  185. package/dist/components/ui/diagram.js +77 -7
  186. package/dist/components/ui/dialog.js +1 -1
  187. package/dist/components/ui/diff.d.ts +105 -0
  188. package/dist/components/ui/diff.d.ts.map +1 -0
  189. package/dist/components/ui/diff.js +113 -0
  190. package/dist/components/ui/dropdown-menu.d.ts +18 -0
  191. package/dist/components/ui/dropdown-menu.d.ts.map +1 -1
  192. package/dist/components/ui/dropdown-menu.js +1 -1
  193. package/dist/components/ui/fact-list.js +1 -1
  194. package/dist/components/ui/field.js +1 -1
  195. package/dist/components/ui/form.d.ts +151 -0
  196. package/dist/components/ui/form.d.ts.map +1 -0
  197. package/dist/components/ui/form.js +73 -0
  198. package/dist/components/ui/hover-card.d.ts +105 -0
  199. package/dist/components/ui/hover-card.d.ts.map +1 -0
  200. package/dist/components/ui/hover-card.js +49 -0
  201. package/dist/components/ui/input-group.d.ts +99 -0
  202. package/dist/components/ui/input-group.d.ts.map +1 -0
  203. package/dist/components/ui/input-group.js +83 -0
  204. package/dist/components/ui/input.js +1 -1
  205. package/dist/components/ui/item.d.ts +113 -0
  206. package/dist/components/ui/item.d.ts.map +1 -0
  207. package/dist/components/ui/item.js +61 -0
  208. package/dist/components/ui/kbd.js +1 -1
  209. package/dist/components/ui/label.d.ts +58 -0
  210. package/dist/components/ui/label.d.ts.map +1 -0
  211. package/dist/components/ui/label.js +29 -0
  212. package/dist/components/ui/live-region.d.ts +9 -0
  213. package/dist/components/ui/live-region.d.ts.map +1 -1
  214. package/dist/components/ui/live-region.js +10 -2
  215. package/dist/components/ui/mark.js +1 -1
  216. package/dist/components/ui/menubar.d.ts +197 -0
  217. package/dist/components/ui/menubar.d.ts.map +1 -0
  218. package/dist/components/ui/menubar.js +109 -0
  219. package/dist/components/ui/meter.d.ts +121 -0
  220. package/dist/components/ui/meter.d.ts.map +1 -0
  221. package/dist/components/ui/meter.js +82 -0
  222. package/dist/components/ui/native-select.d.ts +72 -0
  223. package/dist/components/ui/native-select.d.ts.map +1 -0
  224. package/dist/components/ui/native-select.js +55 -0
  225. package/dist/components/ui/navigation-menu.d.ts +186 -0
  226. package/dist/components/ui/navigation-menu.d.ts.map +1 -0
  227. package/dist/components/ui/navigation-menu.js +94 -0
  228. package/dist/components/ui/number-field.d.ts +111 -0
  229. package/dist/components/ui/number-field.d.ts.map +1 -0
  230. package/dist/components/ui/number-field.js +84 -0
  231. package/dist/components/ui/one-time-code.d.ts +127 -0
  232. package/dist/components/ui/one-time-code.d.ts.map +1 -0
  233. package/dist/components/ui/one-time-code.js +57 -0
  234. package/dist/components/ui/pagination.js +1 -1
  235. package/dist/components/ui/popover.js +1 -1
  236. package/dist/components/ui/product-mark.d.ts +1 -1
  237. package/dist/components/ui/product-mark.js +1 -1
  238. package/dist/components/ui/product-switcher.d.ts +1 -1
  239. package/dist/components/ui/product-switcher.js +2 -2
  240. package/dist/components/ui/progress.js +1 -1
  241. package/dist/components/ui/prose.js +1 -1
  242. package/dist/components/ui/pulse-graph.js +1 -1
  243. package/dist/components/ui/pulse-series.js +1 -1
  244. package/dist/components/ui/radio-group.js +1 -1
  245. package/dist/components/ui/resizable.d.ts +129 -0
  246. package/dist/components/ui/resizable.d.ts.map +1 -0
  247. package/dist/components/ui/resizable.js +205 -0
  248. package/dist/components/ui/scroll-area.d.ts +97 -0
  249. package/dist/components/ui/scroll-area.d.ts.map +1 -0
  250. package/dist/components/ui/scroll-area.js +68 -0
  251. package/dist/components/ui/search-dialog.d.ts +139 -0
  252. package/dist/components/ui/search-dialog.d.ts.map +1 -0
  253. package/dist/components/ui/search-dialog.js +178 -0
  254. package/dist/components/ui/section.d.ts +26 -0
  255. package/dist/components/ui/section.d.ts.map +1 -1
  256. package/dist/components/ui/section.js +32 -1
  257. package/dist/components/ui/select.js +1 -1
  258. package/dist/components/ui/separator.js +1 -1
  259. package/dist/components/ui/sheet.d.ts +103 -0
  260. package/dist/components/ui/sheet.d.ts.map +1 -0
  261. package/dist/components/ui/sheet.js +58 -0
  262. package/dist/components/ui/sidebar.d.ts +228 -0
  263. package/dist/components/ui/sidebar.d.ts.map +1 -0
  264. package/dist/components/ui/sidebar.js +172 -0
  265. package/dist/components/ui/signal-field.js +1 -1
  266. package/dist/components/ui/skeleton.js +1 -1
  267. package/dist/components/ui/slider.js +1 -1
  268. package/dist/components/ui/spinner.d.ts +79 -0
  269. package/dist/components/ui/spinner.d.ts.map +1 -0
  270. package/dist/components/ui/spinner.js +79 -0
  271. package/dist/components/ui/switch.js +1 -1
  272. package/dist/components/ui/table-sort.d.ts +97 -0
  273. package/dist/components/ui/table-sort.d.ts.map +1 -0
  274. package/dist/components/ui/table-sort.js +102 -0
  275. package/dist/components/ui/table.js +1 -1
  276. package/dist/components/ui/tabs.js +1 -1
  277. package/dist/components/ui/textarea.js +1 -1
  278. package/dist/components/ui/timeline.d.ts +106 -0
  279. package/dist/components/ui/timeline.d.ts.map +1 -0
  280. package/dist/components/ui/timeline.js +111 -0
  281. package/dist/components/ui/toast.d.ts +219 -0
  282. package/dist/components/ui/toast.d.ts.map +1 -0
  283. package/dist/components/ui/toast.js +270 -0
  284. package/dist/components/ui/toggle-group.d.ts +118 -0
  285. package/dist/components/ui/toggle-group.d.ts.map +1 -0
  286. package/dist/components/ui/toggle-group.js +194 -0
  287. package/dist/components/ui/toggle.d.ts +73 -0
  288. package/dist/components/ui/toggle.d.ts.map +1 -0
  289. package/dist/components/ui/toggle.js +44 -0
  290. package/dist/components/ui/tooltip.js +1 -1
  291. package/dist/components/ui/tree.js +1 -1
  292. package/dist/components/ui/typography.js +1 -1
  293. package/dist/fonts/Inter-OFL.txt +93 -93
  294. package/dist/index.d.ts +72 -70
  295. package/dist/index.d.ts.map +1 -1
  296. package/dist/index.js +61 -60
  297. package/dist/lib/rank.d.ts +69 -0
  298. package/dist/lib/rank.d.ts.map +1 -0
  299. package/dist/lib/rank.js +77 -0
  300. package/dist/live/index.d.ts +22 -0
  301. package/dist/live/index.d.ts.map +1 -0
  302. package/dist/live/index.js +20 -0
  303. package/dist/live/run-stream-01/index.d.ts +3 -0
  304. package/dist/live/run-stream-01/index.d.ts.map +1 -0
  305. package/dist/live/run-stream-01/index.js +1 -0
  306. package/dist/live/run-stream-01/run-stream.d.ts +125 -0
  307. package/dist/live/run-stream-01/run-stream.d.ts.map +1 -0
  308. package/dist/live/run-stream-01/run-stream.js +111 -0
  309. package/dist/pages/auth-page/index.d.ts +15 -2
  310. package/dist/pages/auth-page/index.d.ts.map +1 -1
  311. package/dist/pages/auth-page/index.js +8 -4
  312. package/dist/pages/blog-post-page/index.js +5 -5
  313. package/dist/pages/dashboard-page/index.d.ts +4 -4
  314. package/dist/pages/dashboard-page/index.js +4 -4
  315. package/dist/pages/docs-shell/docs-shell.d.ts +37 -4
  316. package/dist/pages/docs-shell/docs-shell.d.ts.map +1 -1
  317. package/dist/pages/docs-shell/docs-shell.js +107 -16
  318. package/dist/pages/docs-shell/index.d.ts +2 -2
  319. package/dist/pages/docs-shell/index.js +1 -1
  320. package/dist/pages/index.d.ts +14 -14
  321. package/dist/pages/index.js +7 -7
  322. package/dist/pages/marketing-page/index.d.ts +6 -6
  323. package/dist/pages/marketing-page/index.js +5 -5
  324. package/dist/pages/not-found-page/index.js +4 -4
  325. package/dist/pages/settings-page/index.d.ts +3 -3
  326. package/dist/pages/settings-page/index.js +4 -4
  327. package/dist/provider/index.d.ts +4 -4
  328. package/dist/provider/index.js +2 -2
  329. package/dist/provider/provider.d.ts +1 -1
  330. package/dist/provider/provider.js +1 -1
  331. package/dist/provider/theme-script.d.ts +1 -1
  332. package/dist/provider/theme-script.js +1 -1
  333. package/dist/styles.css +689 -0
  334. package/package.json +9 -1
@@ -0,0 +1,48 @@
1
+ import type { ProductMarkProps } from '../../components/ui/product-mark.js';
2
+ /** One destination in the mobile panel, which is the site's own navigation. */
3
+ export type MobileNavLink = {
4
+ /** The text of the link. */
5
+ label: string;
6
+ /** Where the link goes. */
7
+ href: string;
8
+ /** Marks this link as the page the reader is on. */
9
+ current?: boolean;
10
+ };
11
+ /** The props the mobile navigation takes. */
12
+ export type MobileNavProps = {
13
+ /** The product this navigation belongs to, drawn as the mark above the list. */
14
+ product: Pick<ProductMarkProps, 'id' | 'name' | 'pack'>;
15
+ /** Every destination, in the order a reader should meet them. */
16
+ links: readonly MobileNavLink[];
17
+ /** The accessible name of the panel, which is also the trigger's name. */
18
+ label: string;
19
+ /** The word on the trigger while the panel is closed. */
20
+ openLabel: string;
21
+ /** The word on the trigger while the panel is open. */
22
+ closeLabel: string;
23
+ };
24
+ /**
25
+ * The navigation for viewports below the row's own threshold.
26
+ *
27
+ * **It carries every destination, not a subset.** From the narrowest phone up to
28
+ * the width the horizontal row is authored for, this panel is the only way to reach
29
+ * a section of the site, so a link the row shows at `lg` and the panel omits at
30
+ * 640 is a route a reader on a small laptop cannot find at all. Both render the one
31
+ * array, so a destination added to one is in the other by construction rather than
32
+ * by remembering twice.
33
+ *
34
+ * **It is a Sheet rather than a disclosure panel of the navbar's own, and the
35
+ * difference is the overlay.** A panel that is a child of the bar sits over the
36
+ * page with the bar still visible and nothing above the rest of the document, so
37
+ * scrolling the page behind it moves content the reader thought was dismissed. A
38
+ * sheet owns a modal surface: the rest of the page is not reachable, Escape closes
39
+ * it, and focus is held inside it and handed back to the trigger on the way out.
40
+ * That is the behaviour a full-width menu over a long page needs, and it is the
41
+ * behaviour Prism's own navigation had to hand-write.
42
+ *
43
+ * The links are full width with a 44 pixel minimum height, because below the row's
44
+ * threshold this is a touch target and not a line of text, and the coarse-pointer
45
+ * floor in the design system asks for exactly that.
46
+ */
47
+ export declare function MobileNav({ product, links, label, openLabel, closeLabel, }: MobileNavProps): import("react").JSX.Element;
48
+ //# sourceMappingURL=mobile-nav.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mobile-nav.d.ts","sourceRoot":"","sources":["../../../src/blocks/site-navbar/mobile-nav.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAA;AAExE,+EAA+E;AAC/E,MAAM,MAAM,aAAa,GAAG;IAC1B,4BAA4B;IAC5B,KAAK,EAAE,MAAM,CAAA;IACb,2BAA2B;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,oDAAoD;IACpD,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB,CAAA;AAED,6CAA6C;AAC7C,MAAM,MAAM,cAAc,GAAG;IAC3B,gFAAgF;IAChF,OAAO,EAAE,IAAI,CAAC,gBAAgB,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC,CAAA;IACvD,iEAAiE;IACjE,KAAK,EAAE,SAAS,aAAa,EAAE,CAAA;IAC/B,0EAA0E;IAC1E,KAAK,EAAE,MAAM,CAAA;IACb,yDAAyD;IACzD,SAAS,EAAE,MAAM,CAAA;IACjB,uDAAuD;IACvD,UAAU,EAAE,MAAM,CAAA;CACnB,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,SAAS,CAAC,EACxB,OAAO,EACP,KAAK,EACL,KAAK,EACL,SAAS,EACT,UAAU,GACX,EAAE,cAAc,+BAsChB"}
@@ -0,0 +1,35 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useState } from 'react';
4
+ import { Menu, X } from 'lucide-react';
5
+ import { Sheet, SheetContent, SheetTitle, SheetTrigger } from '../../components/ui/sheet.js';
6
+ import { ProductMark } from '../../components/ui/product-mark.js';
7
+ /**
8
+ * The navigation for viewports below the row's own threshold.
9
+ *
10
+ * **It carries every destination, not a subset.** From the narrowest phone up to
11
+ * the width the horizontal row is authored for, this panel is the only way to reach
12
+ * a section of the site, so a link the row shows at `lg` and the panel omits at
13
+ * 640 is a route a reader on a small laptop cannot find at all. Both render the one
14
+ * array, so a destination added to one is in the other by construction rather than
15
+ * by remembering twice.
16
+ *
17
+ * **It is a Sheet rather than a disclosure panel of the navbar's own, and the
18
+ * difference is the overlay.** A panel that is a child of the bar sits over the
19
+ * page with the bar still visible and nothing above the rest of the document, so
20
+ * scrolling the page behind it moves content the reader thought was dismissed. A
21
+ * sheet owns a modal surface: the rest of the page is not reachable, Escape closes
22
+ * it, and focus is held inside it and handed back to the trigger on the way out.
23
+ * That is the behaviour a full-width menu over a long page needs, and it is the
24
+ * behaviour Prism's own navigation had to hand-write.
25
+ *
26
+ * The links are full width with a 44 pixel minimum height, because below the row's
27
+ * threshold this is a touch target and not a line of text, and the coarse-pointer
28
+ * floor in the design system asks for exactly that.
29
+ */
30
+ export function MobileNav({ product, links, label, openLabel, closeLabel, }) {
31
+ const [open, setOpen] = useState(false);
32
+ return (_jsxs(Sheet, { open: open, onOpenChange: setOpen, children: [_jsx(SheetTrigger, { "data-slot": "site-navbar-mobile-trigger", "aria-label": open ? closeLabel : openLabel, className: "border-border bg-card text-foreground hover:bg-accent hover:text-accent-foreground focus-visible:border-ring focus-visible:ring-ring flex size-11 shrink-0 items-center justify-center rounded-full border transition-colors focus-visible:ring-[3px] focus-visible:outline-none lg:hidden", children: open ? _jsx(X, { "aria-hidden": true, className: "size-5" }) : _jsx(Menu, { "aria-hidden": true, className: "size-5" }) }), _jsxs(SheetContent, { side: "right", className: "w-80", children: [_jsx(SheetTitle, { className: "sr-only", children: label }), _jsxs("nav", { "aria-label": label, className: "flex flex-col gap-1", children: [_jsx("div", { className: "mb-4 flex items-center", children: _jsx(ProductMark, { id: product.id, name: product.name, pack: product.pack, size: "md" }) }), links.map((link) => (_jsx("a", { href: link.href, "aria-current": link.current ? 'page' : undefined, onClick: () => setOpen(false), className: link.current
33
+ ? 'bg-accent text-accent-foreground focus-visible:border-ring focus-visible:ring-ring flex min-h-11 items-center rounded-lg px-3 text-sm font-medium transition-colors focus-visible:ring-[3px] focus-visible:outline-none'
34
+ : 'text-muted-foreground hover:bg-accent hover:text-accent-foreground focus-visible:border-ring focus-visible:ring-ring flex min-h-11 items-center rounded-lg px-3 text-sm font-medium transition-colors focus-visible:ring-[3px] focus-visible:outline-none', children: link.label }, link.href)))] })] })] }));
35
+ }
@@ -0,0 +1,39 @@
1
+ /** The props the mode toggle takes. */
2
+ export type ModeToggleProps = {
3
+ /** The accessible name of the control while the page is in light mode. */
4
+ lightLabel: string;
5
+ /** The accessible name of the control while the page is in dark mode. */
6
+ darkLabel: string;
7
+ };
8
+ /**
9
+ * The light and dark control.
10
+ *
11
+ * One button rather than a menu, because the choice has two members and a menu is
12
+ * the shape a set of six belongs in. The icon states the mode the page is in and
13
+ * the name states the mode the button will move it to, which is the pairing that
14
+ * makes the control readable at a glance and unambiguous to a screen reader: a
15
+ * button labelled "dark mode" that is currently showing a sun is a control whose
16
+ * label and its state have to be reconciled before it can be used.
17
+ *
18
+ * **It reads the mode from the provider rather than from the document.** The class
19
+ * on `<html>` is the mode, so this could read `document.documentElement.classList`
20
+ * and would then hold a value the theme itself owns in two places. The provider is
21
+ * the single writer of that class, and a control that wrote it directly would be a
22
+ * second writer of a state every other part of the page reads.
23
+ *
24
+ * `aria-pressed` is on the control, and it is worth stating why a toggle rather than
25
+ * a pair of buttons: the button's accessible name changes with the mode, and a
26
+ * changing name on a pressed control is the combination that leaves a screen reader
27
+ * announcing "dark mode, pressed" for a page that is in light mode. The name
28
+ * describes the destination and the pressed state describes the current mode, so the
29
+ * two never contradict each other because neither claims to be the other.
30
+ *
31
+ * **The two labels are keyed to the mode they are shown in, not to the mode they
32
+ * name.** `lightLabel` is what the control is called while the page is in light
33
+ * mode, which is the word that sends a reader to dark mode. Reading them the other
34
+ * way round is the mistake this control shipped with and the test that found it:
35
+ * a page in light mode announced "Switch to light mode", which is a control that
36
+ * claims to do the thing the page is already doing.
37
+ */
38
+ export declare function ModeToggle({ lightLabel, darkLabel }: ModeToggleProps): import("react").JSX.Element;
39
+ //# sourceMappingURL=mode-toggle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mode-toggle.d.ts","sourceRoot":"","sources":["../../../src/blocks/site-navbar/mode-toggle.tsx"],"names":[],"mappings":"AAMA,uCAAuC;AACvC,MAAM,MAAM,eAAe,GAAG;IAC5B,0EAA0E;IAC1E,UAAU,EAAE,MAAM,CAAA;IAClB,yEAAyE;IACzE,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,UAAU,CAAC,EAAE,UAAU,EAAE,SAAS,EAAE,EAAE,eAAe,+BAgBpE"}
@@ -0,0 +1,39 @@
1
+ 'use client';
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { Moon, Sun } from 'lucide-react';
4
+ import { usePrismTheme } from '../../provider/provider.js';
5
+ /**
6
+ * The light and dark control.
7
+ *
8
+ * One button rather than a menu, because the choice has two members and a menu is
9
+ * the shape a set of six belongs in. The icon states the mode the page is in and
10
+ * the name states the mode the button will move it to, which is the pairing that
11
+ * makes the control readable at a glance and unambiguous to a screen reader: a
12
+ * button labelled "dark mode" that is currently showing a sun is a control whose
13
+ * label and its state have to be reconciled before it can be used.
14
+ *
15
+ * **It reads the mode from the provider rather than from the document.** The class
16
+ * on `<html>` is the mode, so this could read `document.documentElement.classList`
17
+ * and would then hold a value the theme itself owns in two places. The provider is
18
+ * the single writer of that class, and a control that wrote it directly would be a
19
+ * second writer of a state every other part of the page reads.
20
+ *
21
+ * `aria-pressed` is on the control, and it is worth stating why a toggle rather than
22
+ * a pair of buttons: the button's accessible name changes with the mode, and a
23
+ * changing name on a pressed control is the combination that leaves a screen reader
24
+ * announcing "dark mode, pressed" for a page that is in light mode. The name
25
+ * describes the destination and the pressed state describes the current mode, so the
26
+ * two never contradict each other because neither claims to be the other.
27
+ *
28
+ * **The two labels are keyed to the mode they are shown in, not to the mode they
29
+ * name.** `lightLabel` is what the control is called while the page is in light
30
+ * mode, which is the word that sends a reader to dark mode. Reading them the other
31
+ * way round is the mistake this control shipped with and the test that found it:
32
+ * a page in light mode announced "Switch to light mode", which is a control that
33
+ * claims to do the thing the page is already doing.
34
+ */
35
+ export function ModeToggle({ lightLabel, darkLabel }) {
36
+ const { mode, toggleMode } = usePrismTheme();
37
+ const dark = mode === 'dark';
38
+ return (_jsx("button", { type: "button", "data-slot": "site-navbar-mode-toggle", onClick: toggleMode, "aria-label": dark ? darkLabel : lightLabel, "aria-pressed": dark, className: "border-border bg-card text-muted-foreground hover:bg-accent hover:text-accent-foreground focus-visible:border-ring focus-visible:ring-ring flex size-11 shrink-0 items-center justify-center rounded-full border transition-colors focus-visible:ring-[3px] focus-visible:outline-none", children: dark ? _jsx(Sun, { "aria-hidden": true, className: "size-4" }) : _jsx(Moon, { "aria-hidden": true, className: "size-4" }) }));
39
+ }
@@ -0,0 +1,79 @@
1
+ import type { Mode, PackId } from '../../theming/index.js';
2
+ import type { SearchDialogMessages } from '../../components/ui/search-dialog.js';
3
+ import { type ThemePack } from './theme-menu.js';
4
+ import type { SwitcherProduct } from '../../components/ui/product-switcher.js';
5
+ import type { MobileNavLink } from './mobile-nav.js';
6
+ /** What the control cluster was told to render. Every field is optional. */
7
+ export type NavbarControlsProps = {
8
+ /** The product whose mark heads the mobile panel. */
9
+ product: {
10
+ id: string;
11
+ name: string;
12
+ pack?: PackId | null;
13
+ };
14
+ /** The site's own destinations, for the panel below the row's threshold. */
15
+ nav: readonly MobileNavLink[];
16
+ /** The accessible name of the panel and of its trigger. */
17
+ navLabel: string;
18
+ /** The set of sites, or nothing for a site that is the only one. */
19
+ sites?: readonly SwitcherProduct[];
20
+ /** The `id` of the site the reader is on. */
21
+ currentSiteId?: string;
22
+ /** The accessible name of the sites menu. */
23
+ sitesLabel?: string;
24
+ /** Where the search index is served from, or nothing for no search. */
25
+ search?: {
26
+ indexUrl: string;
27
+ label: string;
28
+ hint?: string;
29
+ messages: SearchDialogMessages;
30
+ };
31
+ /** The packs the chooser offers, or nothing for no chooser. */
32
+ theme?: {
33
+ label: string;
34
+ packs?: readonly ThemePack[];
35
+ };
36
+ /** The two names of the light and dark control, or nothing for no toggle. */
37
+ mode?: {
38
+ lightLabel: string;
39
+ darkLabel: string;
40
+ };
41
+ /** The two names of the mobile trigger. */
42
+ mobileLabels: {
43
+ open: string;
44
+ close: string;
45
+ };
46
+ /** The pack a reader with no stored choice gets. */
47
+ defaultPack: PackId;
48
+ /** The mode a reader with no stored choice gets. */
49
+ defaultMode: Mode;
50
+ /** A slot for controls the consumer owns, after the ones above. */
51
+ actions?: React.ReactNode;
52
+ };
53
+ /**
54
+ * The bar's controls, and the only client boundary in the navbar.
55
+ *
56
+ * Everything interactive in a site header is application state: what a reader has
57
+ * chosen, what is open, what a search found. None of it is a fact the bar can be
58
+ * told, so none of it can live in a server Component, and the boundary is drawn
59
+ * here rather than around the whole bar so that the brand lockup and the
60
+ * navigation stay server rendered. That is the arrangement that lets a site keep
61
+ * the rest of its page free of client JavaScript, which is the property three of
62
+ * the five NaniSoft sites are built around.
63
+ *
64
+ * **The provider is mounted here and not in the site's root layout, and that is
65
+ * deliberate.** A provider in the layout would wrap every page and every provider
66
+ * is context, so a page that never renders a control would still ship it. Mounted
67
+ * around five buttons, it ships with the buttons and stops there. It is also the
68
+ * only writer of the two attributes the boot script reads, so a choice made here
69
+ * is a choice the next page load resolves to the same theme.
70
+ *
71
+ * **The order is fixed and it is a reading order, not a preference.** Search first
72
+ * because it is the only control that answers a question the reader arrived with;
73
+ * then the two menus, which are choices about where to be rather than about what to
74
+ * do; then the mode, which is the choice that persists across every site in the
75
+ * family; then the mobile trigger, which is last because it is the only one that
76
+ * appears at the narrow end of the range and appears alone there.
77
+ */
78
+ export declare function NavbarControls(props: NavbarControlsProps): import("react").JSX.Element | null;
79
+ //# sourceMappingURL=navbar-controls.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"navbar-controls.d.ts","sourceRoot":"","sources":["../../../src/blocks/site-navbar/navbar-controls.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AACjD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAA;AAI7E,OAAO,EAAa,KAAK,SAAS,EAAE,MAAM,cAAc,CAAA;AACxD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAA;AAC3E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAIjD,4EAA4E;AAC5E,MAAM,MAAM,mBAAmB,GAAG;IAChC,qDAAqD;IACrD,OAAO,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAA;IAC3D,4EAA4E;IAC5E,GAAG,EAAE,SAAS,aAAa,EAAE,CAAA;IAC7B,2DAA2D;IAC3D,QAAQ,EAAE,MAAM,CAAA;IAChB,oEAAoE;IACpE,KAAK,CAAC,EAAE,SAAS,eAAe,EAAE,CAAA;IAClC,6CAA6C;IAC7C,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,6CAA6C;IAC7C,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,uEAAuE;IACvE,MAAM,CAAC,EAAE;QACP,QAAQ,EAAE,MAAM,CAAA;QAChB,KAAK,EAAE,MAAM,CAAA;QACb,IAAI,CAAC,EAAE,MAAM,CAAA;QACb,QAAQ,EAAE,oBAAoB,CAAA;KAC/B,CAAA;IACD,+DAA+D;IAC/D,KAAK,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,SAAS,SAAS,EAAE,CAAA;KAAE,CAAA;IACvD,6EAA6E;IAC7E,IAAI,CAAC,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAA;IAChD,2CAA2C;IAC3C,YAAY,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;IAC7C,oDAAoD;IACpD,WAAW,EAAE,MAAM,CAAA;IACnB,oDAAoD;IACpD,WAAW,EAAE,IAAI,CAAA;IACjB,mEAAmE;IACnE,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CAC1B,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,mBAAmB,sCAsDxD"}
@@ -0,0 +1,40 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { ModeToggle } from './mode-toggle.js';
4
+ import { SearchEntry } from './search-entry.js';
5
+ import { SitesMenu } from './sites-menu.js';
6
+ import { ThemeMenu } from './theme-menu.js';
7
+ import { MobileNav } from './mobile-nav.js';
8
+ import { PrismProvider } from '../../provider/provider.js';
9
+ /**
10
+ * The bar's controls, and the only client boundary in the navbar.
11
+ *
12
+ * Everything interactive in a site header is application state: what a reader has
13
+ * chosen, what is open, what a search found. None of it is a fact the bar can be
14
+ * told, so none of it can live in a server Component, and the boundary is drawn
15
+ * here rather than around the whole bar so that the brand lockup and the
16
+ * navigation stay server rendered. That is the arrangement that lets a site keep
17
+ * the rest of its page free of client JavaScript, which is the property three of
18
+ * the five NaniSoft sites are built around.
19
+ *
20
+ * **The provider is mounted here and not in the site's root layout, and that is
21
+ * deliberate.** A provider in the layout would wrap every page and every provider
22
+ * is context, so a page that never renders a control would still ship it. Mounted
23
+ * around five buttons, it ships with the buttons and stops there. It is also the
24
+ * only writer of the two attributes the boot script reads, so a choice made here
25
+ * is a choice the next page load resolves to the same theme.
26
+ *
27
+ * **The order is fixed and it is a reading order, not a preference.** Search first
28
+ * because it is the only control that answers a question the reader arrived with;
29
+ * then the two menus, which are choices about where to be rather than about what to
30
+ * do; then the mode, which is the choice that persists across every site in the
31
+ * family; then the mobile trigger, which is last because it is the only one that
32
+ * appears at the narrow end of the range and appears alone there.
33
+ */
34
+ export function NavbarControls(props) {
35
+ const { product, nav, navLabel, sites, currentSiteId, sitesLabel, search, theme, mode, mobileLabels, defaultPack, defaultMode, actions, } = props;
36
+ const hasThemeControls = Boolean(theme) || Boolean(mode);
37
+ if (!search && !sites && !hasThemeControls && !actions && nav.length === 0)
38
+ return null;
39
+ return (_jsx(PrismProvider, { defaultPack: defaultPack, defaultMode: defaultMode, children: _jsxs("div", { className: "ms-auto flex items-center gap-2", children: [search ? (_jsx(SearchEntry, { indexUrl: search.indexUrl, label: search.label, hint: search.hint, messages: search.messages })) : null, sites && sites.length > 0 && sitesLabel ? (_jsx(SitesMenu, { sites: sites, currentId: currentSiteId, label: sitesLabel })) : null, theme ? _jsx(ThemeMenu, { label: theme.label, packs: theme.packs }) : null, mode ? _jsx(ModeToggle, { lightLabel: mode.lightLabel, darkLabel: mode.darkLabel }) : null, actions, nav.length > 0 ? (_jsx(MobileNav, { product: product, links: nav, label: navLabel, openLabel: mobileLabels.open, closeLabel: mobileLabels.close })) : null] }) }));
40
+ }
@@ -0,0 +1,29 @@
1
+ import type { SearchDialogProps } from '../../components/ui/search-dialog.js';
2
+ /** The props the search entry takes. It is the dialog's props without its close. */
3
+ export type SearchEntryProps = Omit<SearchDialogProps, 'onClose'>;
4
+ /**
5
+ * The search trigger, and the dialog it opens.
6
+ *
7
+ * **The dialog is loaded on the first activation, so neither the dialog nor the
8
+ * index is part of any page's first paint.** The index is the largest single asset
9
+ * on a documentation site, and a statically imported dialog is in the module graph
10
+ * of every page whether or not the reader ever searches. The trigger is a plain
11
+ * button and the cost of reaching it is one click.
12
+ *
13
+ * **The shortcut is Command-K on Apple platforms and Control-K everywhere else,
14
+ * and it matches rather than replaces.** The listener calls `preventDefault` so the
15
+ * browser's own find behaviour does not also fire, and it toggles so pressing it
16
+ * twice leaves the reader where they started. It is registered on the document
17
+ * rather than on the button, because a shortcut scoped to a control only works once
18
+ * that control has focus, and the point of a shortcut is to save the reader from
19
+ * having to find the control first.
20
+ *
21
+ * **It is icon-only at every width.** The control is not a destination, so its word
22
+ * is the first thing that goes when the bar runs out of room, and the row it sits in
23
+ * is measured rather than assumed: a labelled search control is 55 pixels wider than
24
+ * an icon in the same slot, and on a site whose navigation is nine Sections that is
25
+ * the difference between fitting at the authored breakpoint and folding the brand
26
+ * onto two lines. The accessible name is what replaces the word.
27
+ */
28
+ export declare function SearchEntry(props: SearchEntryProps): import("react").JSX.Element;
29
+ //# sourceMappingURL=search-entry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-entry.d.ts","sourceRoot":"","sources":["../../../src/blocks/site-navbar/search-entry.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAA;AAe1E,oFAAoF;AACpF,MAAM,MAAM,gBAAgB,GAAG,IAAI,CAAC,iBAAiB,EAAE,SAAS,CAAC,CAAA;AAEjE;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,+BAwClD"}
@@ -0,0 +1,52 @@
1
+ 'use client';
2
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { lazy, Suspense, useEffect, useState } from 'react';
4
+ import { Search } from 'lucide-react';
5
+ /**
6
+ * The dialog, loaded on the first activation.
7
+ *
8
+ * Declared at module scope so the import is shared by every search entry on a page
9
+ * rather than re-issued per call, which is what makes a second search on the same
10
+ * page instant. `lazy` is React's own rather than a framework's, because this
11
+ * package imports no framework and has to stay installable in a bundler that is
12
+ * not the one its own site uses.
13
+ */
14
+ const SearchDialog = lazy(() => import('../../components/ui/search-dialog.js').then((module) => ({ default: module.SearchDialog })));
15
+ /**
16
+ * The search trigger, and the dialog it opens.
17
+ *
18
+ * **The dialog is loaded on the first activation, so neither the dialog nor the
19
+ * index is part of any page's first paint.** The index is the largest single asset
20
+ * on a documentation site, and a statically imported dialog is in the module graph
21
+ * of every page whether or not the reader ever searches. The trigger is a plain
22
+ * button and the cost of reaching it is one click.
23
+ *
24
+ * **The shortcut is Command-K on Apple platforms and Control-K everywhere else,
25
+ * and it matches rather than replaces.** The listener calls `preventDefault` so the
26
+ * browser's own find behaviour does not also fire, and it toggles so pressing it
27
+ * twice leaves the reader where they started. It is registered on the document
28
+ * rather than on the button, because a shortcut scoped to a control only works once
29
+ * that control has focus, and the point of a shortcut is to save the reader from
30
+ * having to find the control first.
31
+ *
32
+ * **It is icon-only at every width.** The control is not a destination, so its word
33
+ * is the first thing that goes when the bar runs out of room, and the row it sits in
34
+ * is measured rather than assumed: a labelled search control is 55 pixels wider than
35
+ * an icon in the same slot, and on a site whose navigation is nine Sections that is
36
+ * the difference between fitting at the authored breakpoint and folding the brand
37
+ * onto two lines. The accessible name is what replaces the word.
38
+ */
39
+ export function SearchEntry(props) {
40
+ const [open, setOpen] = useState(false);
41
+ useEffect(() => {
42
+ const onKeyDown = (event) => {
43
+ if ((event.metaKey || event.ctrlKey) && event.key.toLowerCase() === 'k') {
44
+ event.preventDefault();
45
+ setOpen((value) => !value);
46
+ }
47
+ };
48
+ document.addEventListener('keydown', onKeyDown);
49
+ return () => document.removeEventListener('keydown', onKeyDown);
50
+ }, []);
51
+ return (_jsxs(_Fragment, { children: [_jsx("button", { type: "button", "data-slot": "site-navbar-search-trigger", onClick: () => setOpen(true), "aria-label": props.label, "aria-haspopup": "dialog", "aria-expanded": open, className: "border-border bg-card text-muted-foreground hover:bg-accent hover:text-accent-foreground focus-visible:border-ring focus-visible:ring-ring flex size-11 shrink-0 items-center justify-center rounded-full border transition-colors focus-visible:ring-[3px] focus-visible:outline-none", children: _jsx(Search, { "aria-hidden": true, className: "size-4" }) }), open ? (_jsx(Suspense, { fallback: null, children: _jsx(SearchDialog, { ...props, onClose: () => setOpen(false) }) })) : null] }));
52
+ }
@@ -0,0 +1,212 @@
1
+ import type { ReactNode } from 'react';
2
+ import { type ProductMarkProps } from '../../components/ui/product-mark.js';
3
+ import type { SwitcherProduct } from '../../components/ui/product-switcher.js';
4
+ import type { SearchDialogMessages } from '../../components/ui/search-dialog.js';
5
+ import type { Mode, PackId } from '../../theming/index.js';
6
+ import type { ThemePack } from './theme-menu.js';
7
+ /**
8
+ * One destination in the bar's own navigation.
9
+ *
10
+ * `href` is required and `current` is opt-in. The bar marks the current page with
11
+ * `aria-current="page"` rather than with a colour, so a reader who cannot see the
12
+ * colour still knows where they are.
13
+ */
14
+ export type SiteNavLink = {
15
+ /** The text of the link. */
16
+ label: string;
17
+ /** Where the link goes. */
18
+ href: string;
19
+ /**
20
+ * Marks this link as the page the reader is on. Set it on the one link whose
21
+ * destination is the current route.
22
+ *
23
+ * A site that renders the bar once in a root layout cannot know its own route,
24
+ * because a layout is handed no pathname. Such a site passes `currentPath`
25
+ * instead and the bar resolves the mark in the browser; see that prop.
26
+ */
27
+ current?: boolean;
28
+ /**
29
+ * Opens the destination in a new browsing context, which defaults the link
30
+ * relationship to `noopener noreferrer`. Prism does not decide what counts as
31
+ * external: a cross-origin destination is not by itself a reason to open a tab.
32
+ */
33
+ newTab?: boolean;
34
+ };
35
+ /** The search the bar offers, which is a URL rather than an index. */
36
+ export type SiteNavSearch = {
37
+ /**
38
+ * Where this site's JSON index is served from, fetched on the first search and
39
+ * not before. A URL rather than the index itself, because the index is the
40
+ * largest asset on a documentation site and a value passed as a prop is
41
+ * serialized into the document of every route that renders the bar.
42
+ */
43
+ indexUrl: string;
44
+ /** The accessible name of the trigger, of the dialog and of its field. */
45
+ label: string;
46
+ /** Every sentence the dialog can say, which a Component does not ship. */
47
+ messages: SearchDialogMessages;
48
+ /** The text shown before the reader has typed anything. */
49
+ hint?: string;
50
+ };
51
+ /** The colour chooser the bar offers, and whether it offers one at all. */
52
+ export type SiteNavTheme = {
53
+ /** The accessible name of the menu, and of the word on its trigger. */
54
+ label: string;
55
+ /**
56
+ * The packs to choose between, each with the word a reader reads for it. Omit it
57
+ * to offer every published pack under its own capitalised name.
58
+ *
59
+ * A product site passes nothing at all rather than passing this, because a site's
60
+ * ground is a property of the site and a reader who repaints it is a reader on a
61
+ * page that is no longer the one the site describes.
62
+ */
63
+ packs?: readonly ThemePack[];
64
+ };
65
+ /** The light and dark control the bar offers. */
66
+ export type SiteNavMode = {
67
+ /** The control's accessible name while the page is in dark mode. */
68
+ lightLabel: string;
69
+ /** The control's accessible name while the page is in light mode. */
70
+ darkLabel: string;
71
+ };
72
+ /** The two names of the control that opens the navigation below the row. */
73
+ export type SiteNavMobileLabels = {
74
+ /** The word on the trigger while the panel is closed. */
75
+ open: string;
76
+ /** The word on the trigger while the panel is open. */
77
+ close: string;
78
+ };
79
+ /** The props a SiteNavbar takes. */
80
+ export type SiteNavbarProps = {
81
+ /**
82
+ * The product this bar belongs to: the id, name and pack its `ProductMark` is
83
+ * drawn from, and the mark that heads the mobile panel. The bar renders the mark
84
+ * itself rather than a slot, because a bar whose brand lockup is a slot is a bar
85
+ * every consumer has to reimplement.
86
+ */
87
+ product: Pick<ProductMarkProps, 'id' | 'name' | 'pack'>;
88
+ /** Where the brand lockup goes. @defaultValue '/' */
89
+ homeHref?: string;
90
+ /**
91
+ * The pack a reader who has never chosen a pack gets. It is passed to the theme
92
+ * runtime rather than read from the document, so a site states its own default in
93
+ * one place and the control and the page cannot disagree about it.
94
+ */
95
+ defaultPack: PackId;
96
+ /**
97
+ * The mode a reader who has never chosen gets. Required for the same reason
98
+ * `defaultPack` is, and because a toggle with no stated starting mode is a
99
+ * control whose icon is a guess until it is pressed once.
100
+ */
101
+ defaultMode: Mode;
102
+ /** This site's own destinations. Omit for a bar that carries only the lockup. */
103
+ nav?: readonly SiteNavLink[];
104
+ /**
105
+ * The accessible name of the site's navigation. Required, and required rather
106
+ * than defaulted because it is a word a reader hears: a Block that ships no copy
107
+ * ships no reader-facing copy either.
108
+ */
109
+ navLabel: string;
110
+ /**
111
+ * The route the reader is on, for a site that renders the bar once in a root
112
+ * layout and therefore cannot mark the current link itself.
113
+ *
114
+ * A site that composes the bar per page, which is the arrangement that keeps the
115
+ * current link server rendered, sets `current` on the one link instead and leaves
116
+ * this off. The two are alternatives rather than layers, and a site that set both
117
+ * would have two answers to which link is current.
118
+ */
119
+ currentPath?: string;
120
+ /**
121
+ * The set of sites to move between, rendered as a menu. Omit it on a site that is
122
+ * the only one; a set of one is a menu with a single item and no reason to exist.
123
+ */
124
+ sites?: readonly SwitcherProduct[];
125
+ /** The `id` of the site the reader is on, marked in the menu. */
126
+ currentSiteId?: string;
127
+ /**
128
+ * The accessible name of the sites menu. Required whenever `sites` is passed, for
129
+ * the same reason `navLabel` is.
130
+ */
131
+ sitesLabel?: string;
132
+ /** The search the bar offers, or nothing for no search. */
133
+ search?: SiteNavSearch;
134
+ /** The colour chooser the bar offers, or nothing for no chooser. */
135
+ theme?: SiteNavTheme;
136
+ /** The light and dark control the bar offers, or nothing for no toggle. */
137
+ mode?: SiteNavMode;
138
+ /**
139
+ * The two names of the mobile trigger, which is a round icon with no visible
140
+ * word. Required rather than defaulted, because a default would be a sentence
141
+ * this Block ships about a product that is not the caller's, and because a bar
142
+ * that renders an unlabelled round control below its own threshold has a
143
+ * keyboard reader reaching for something it cannot name.
144
+ */
145
+ mobileLabels: SiteNavMobileLabels;
146
+ /**
147
+ * A slot for controls the product owns, after the ones this bar composes. A slot
148
+ * rather than a prop, because an account menu and a sign-in link are application
149
+ * state and neither is a fact a bar can be told.
150
+ */
151
+ actions?: ReactNode;
152
+ /**
153
+ * Keeps the bar at the top of the viewport as the page scrolls. On by default,
154
+ * because the bar is how a reader leaves the page they are on, and a bar that
155
+ * scrolls away takes that with it on exactly the long pages a reader needs it.
156
+ */
157
+ sticky?: boolean;
158
+ /** Layout only. Changing a Prism-owned visual property from here is prohibited. */
159
+ className?: string;
160
+ };
161
+ /**
162
+ * The bar at the top of a product site, with the controls a reader needs on every
163
+ * page of it.
164
+ *
165
+ * It is `SiteHeader` plus the four controls that were missing from it, and it
166
+ * exists because all five NaniSoft sites had the same bar and every one of them had
167
+ * written the missing four separately: Prism's own site had search and a colour
168
+ * chooser and no way to reach its four siblings, and each of the four had a row of
169
+ * product marks where a menu belongs and no search, no mode control and no
170
+ * navigation at all below the width its own row stopped fitting. Five bars, one
171
+ * design language, and no two of them the same bar.
172
+ *
173
+ * Every string is a prop and the Block ships none. There is no site name, no
174
+ * default navigation, no "Search", no list of packs and no list of sites: a bar
175
+ * that hardcoded any of them would hand every consumer a claim about a product that
176
+ * is not theirs, which is the defect this Block exists to remove. The one piece of
177
+ * copy it derives is a pack's own name from its own identifier, and only when the
178
+ * caller names none.
179
+ *
180
+ * **The bar is one flex row that wraps, and it fits by measurement.** The brand
181
+ * lockup and the controls hold their ends, the navigation sits in the middle, and
182
+ * the navigation row is hidden below `lg` where the panel takes over. The brand
183
+ * lockup is the one element that never wraps: a wordmark broken across two lines is
184
+ * not a wordmark, and it is also the one element that yields rather than pushing a
185
+ * control off the right edge of the viewport, which is the harm a header-fit test
186
+ * exists to catch.
187
+ *
188
+ * **The navigation is a `nav` and the sites menu is a second landmark of its own.**
189
+ * A reader who navigates by landmark needs two regions rather than one region with
190
+ * two lists in it, and the two sets are different places: one is where this site
191
+ * goes and the other is where the family goes. The controls are not a region at
192
+ * all, because they are whatever this bar composed plus whatever the consumer put
193
+ * in `actions`, and wrapping them in a landmark would be a claim about content the
194
+ * Block does not own.
195
+ *
196
+ * The bottom hairline is `border-border`, so the bar separates from the page by a
197
+ * line rather than by a fill change, which is how every surface in this system is
198
+ * separated: in the base pack `background` and `card` resolve to the same value, so
199
+ * a fill is not available as a separator. The bar is translucent and blurred, so the
200
+ * content scrolling under it is legible through it rather than hidden by it, which
201
+ * is the reason a sticky bar can be translucent at all.
202
+ *
203
+ * **It is a server Component with one client island inside it.** The lockup and the
204
+ * navigation are rendered on the server and ship no JavaScript; the controls are a
205
+ * single boundary, because a control's state is a reader's state. A site that
206
+ * passes no `search`, `sites`, `theme`, `mode` or `nav` renders the whole bar on the
207
+ * server and ships none, which is the arrangement a static site wants and the reason
208
+ * those props are optional rather than required.
209
+ */
210
+ export declare function SiteNavbar({ product, homeHref, defaultPack, defaultMode, nav, navLabel, currentPath, sites, currentSiteId, sitesLabel, search, theme, mode, mobileLabels, actions, sticky, className, }: SiteNavbarProps): import("react").JSX.Element;
211
+ export default SiteNavbar;
212
+ //# sourceMappingURL=site-navbar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"site-navbar.d.ts","sourceRoot":"","sources":["../../../src/blocks/site-navbar/site-navbar.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAEtC,OAAO,EAAe,KAAK,gBAAgB,EAAE,MAAM,kCAAkC,CAAA;AACrF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAA;AAC3E,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAA;AAE7E,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AAEjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAE7C;;;;;;GAMG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB,4BAA4B;IAC5B,KAAK,EAAE,MAAM,CAAA;IACb,2BAA2B;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ;;;;;;;OAOG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB,CAAA;AAED,sEAAsE;AACtE,MAAM,MAAM,aAAa,GAAG;IAC1B;;;;;OAKG;IACH,QAAQ,EAAE,MAAM,CAAA;IAChB,0EAA0E;IAC1E,KAAK,EAAE,MAAM,CAAA;IACb,0EAA0E;IAC1E,QAAQ,EAAE,oBAAoB,CAAA;IAC9B,2DAA2D;IAC3D,IAAI,CAAC,EAAE,MAAM,CAAA;CACd,CAAA;AAED,2EAA2E;AAC3E,MAAM,MAAM,YAAY,GAAG;IACzB,uEAAuE;IACvE,KAAK,EAAE,MAAM,CAAA;IACb;;;;;;;OAOG;IACH,KAAK,CAAC,EAAE,SAAS,SAAS,EAAE,CAAA;CAC7B,CAAA;AAED,iDAAiD;AACjD,MAAM,MAAM,WAAW,GAAG;IACxB,oEAAoE;IACpE,UAAU,EAAE,MAAM,CAAA;IAClB,qEAAqE;IACrE,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,4EAA4E;AAC5E,MAAM,MAAM,mBAAmB,GAAG;IAChC,yDAAyD;IACzD,IAAI,EAAE,MAAM,CAAA;IACZ,uDAAuD;IACvD,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AAED,oCAAoC;AACpC,MAAM,MAAM,eAAe,GAAG;IAC5B;;;;;OAKG;IACH,OAAO,EAAE,IAAI,CAAC,gBAAgB,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC,CAAA;IACvD,qDAAqD;IACrD,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;OAIG;IACH,WAAW,EAAE,MAAM,CAAA;IACnB;;;;OAIG;IACH,WAAW,EAAE,IAAI,CAAA;IACjB,iFAAiF;IACjF,GAAG,CAAC,EAAE,SAAS,WAAW,EAAE,CAAA;IAC5B;;;;OAIG;IACH,QAAQ,EAAE,MAAM,CAAA;IAChB;;;;;;;;OAQG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;;;OAGG;IACH,KAAK,CAAC,EAAE,SAAS,eAAe,EAAE,CAAA;IAClC,iEAAiE;IACjE,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,2DAA2D;IAC3D,MAAM,CAAC,EAAE,aAAa,CAAA;IACtB,oEAAoE;IACpE,KAAK,CAAC,EAAE,YAAY,CAAA;IACpB,2EAA2E;IAC3E,IAAI,CAAC,EAAE,WAAW,CAAA;IAClB;;;;;;OAMG;IACH,YAAY,EAAE,mBAAmB,CAAA;IACjC;;;;OAIG;IACH,OAAO,CAAC,EAAE,SAAS,CAAA;IACnB;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,mFAAmF;IACnF,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AACH,wBAAgB,UAAU,CAAC,EACzB,OAAO,EACP,QAAc,EACd,WAAW,EACX,WAAW,EACX,GAAG,EACH,QAAQ,EACR,WAAW,EACX,KAAK,EACL,aAAa,EACb,UAAU,EACV,MAAM,EACN,KAAK,EACL,IAAI,EACJ,YAAY,EACZ,OAAO,EACP,MAAa,EACb,SAAS,GACV,EAAE,eAAe,+BAkEjB;AAED,eAAe,UAAU,CAAA"}