livemark 0.25.0 → 0.27.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 (427) hide show
  1. package/README.md +3 -2
  2. package/build/actions/config/define.d.ts +12 -0
  3. package/build/actions/config/define.unit.js +8 -1
  4. package/build/actions/escape/copy.d.ts +11 -0
  5. package/build/actions/escape/copy.js +29 -0
  6. package/build/actions/escape/copy.unit.d.ts +1 -0
  7. package/build/actions/escape/copy.unit.js +37 -0
  8. package/build/actions/escape/list.d.ts +12 -0
  9. package/build/actions/escape/list.js +27 -0
  10. package/build/actions/escape/list.unit.d.ts +1 -0
  11. package/build/actions/escape/list.unit.js +36 -0
  12. package/build/actions/target/build.d.ts +9 -26
  13. package/build/actions/target/build.js +50 -71
  14. package/build/actions/target/build.unit.d.ts +1 -0
  15. package/build/actions/target/build.unit.js +76 -0
  16. package/build/actions/target/clear.d.ts +4 -0
  17. package/build/actions/target/clear.js +14 -0
  18. package/build/actions/target/clear.unit.d.ts +1 -0
  19. package/build/actions/target/clear.unit.js +23 -0
  20. package/build/commands/build.js +1 -2
  21. package/build/commands/clear.d.ts +5 -0
  22. package/build/commands/clear.js +15 -0
  23. package/build/commands/escape.d.ts +4 -3
  24. package/build/commands/escape.js +45 -48
  25. package/build/commands/preview.js +1 -2
  26. package/build/commands/start.js +1 -2
  27. package/build/components/Abbr.d.ts +1 -1
  28. package/build/components/Abbr.js +2 -4
  29. package/build/components/AnsiCode.d.ts +1 -1
  30. package/build/components/AnsiCode.js +2 -2
  31. package/build/components/Article.d.ts +2 -1
  32. package/build/components/Article.js +7 -14
  33. package/build/components/BackToTop.d.ts +1 -1
  34. package/build/components/Banner.d.ts +2 -2
  35. package/build/components/Banner.js +7 -3
  36. package/build/components/BlogIndex.d.ts +1 -1
  37. package/build/components/BlogIndex.js +2 -11
  38. package/build/components/Breadcrumbs.d.ts +1 -1
  39. package/build/components/Breadcrumbs.js +2 -3
  40. package/build/components/Callout.d.ts +1 -1
  41. package/build/components/Callout.js +5 -9
  42. package/build/components/Card.d.ts +1 -1
  43. package/build/components/Card.js +2 -3
  44. package/build/components/Cards.d.ts +1 -1
  45. package/build/components/ChangelogIndex.d.ts +1 -1
  46. package/build/components/ChangelogIndex.js +2 -11
  47. package/build/components/ChoiceList.d.ts +15 -0
  48. package/build/components/ChoiceList.js +13 -0
  49. package/build/components/CodeBlock.d.ts +1 -1
  50. package/build/components/CodeBlock.js +3 -16
  51. package/build/components/CodeTabs.d.ts +1 -1
  52. package/build/components/CodeTabs.js +2 -3
  53. package/build/components/Column.d.ts +1 -1
  54. package/build/components/Columns.d.ts +1 -1
  55. package/build/components/Content.d.ts +1 -1
  56. package/build/components/ContentTab.d.ts +1 -1
  57. package/build/components/ContentTabs.d.ts +1 -1
  58. package/build/components/ContentTabs.js +2 -3
  59. package/build/components/DefaultCatchBoundary.d.ts +1 -1
  60. package/build/components/DefaultCatchBoundary.js +5 -7
  61. package/build/components/DefinitionList.d.ts +3 -3
  62. package/build/components/Details.d.ts +1 -1
  63. package/build/components/Details.js +2 -5
  64. package/build/components/FileTree.d.ts +1 -1
  65. package/build/components/FileTree.js +3 -5
  66. package/build/components/Footer.d.ts +1 -1
  67. package/build/components/Footer.js +2 -5
  68. package/build/components/FootnoteRef.d.ts +1 -1
  69. package/build/components/FootnoteRef.js +2 -4
  70. package/build/components/Header.d.ts +6 -0
  71. package/build/components/Header.js +26 -0
  72. package/build/components/HeaderMenu.d.ts +2 -0
  73. package/build/components/HeaderMenu.js +27 -0
  74. package/build/components/HeaderNav.d.ts +6 -0
  75. package/build/components/HeaderNav.js +74 -0
  76. package/build/components/HeaderSearch.d.ts +4 -0
  77. package/build/components/HeaderSearch.js +33 -0
  78. package/build/components/Heading.d.ts +6 -6
  79. package/build/components/InlineBadge.d.ts +2 -2
  80. package/build/components/InlineBadge.js +1 -1
  81. package/build/components/InlineIcon.d.ts +1 -1
  82. package/build/components/InlineToc.d.ts +1 -1
  83. package/build/components/InlineToc.js +2 -4
  84. package/build/components/Layout.d.ts +2 -1
  85. package/build/components/Layout.js +5 -58
  86. package/build/components/LinkButton.d.ts +2 -2
  87. package/build/components/LinkButton.js +1 -1
  88. package/build/components/MenuSheet.d.ts +22 -0
  89. package/build/components/MenuSheet.js +27 -0
  90. package/build/components/Mermaid.d.ts +1 -1
  91. package/build/components/MermaidRenderer.d.ts +1 -1
  92. package/build/components/MermaidRenderer.js +20 -8
  93. package/build/components/NotFound.d.ts +1 -1
  94. package/build/components/NotFound.js +3 -6
  95. package/build/components/PackageTabs.d.ts +1 -1
  96. package/build/components/PackageTabs.js +3 -7
  97. package/build/components/PageToolbar.d.ts +1 -1
  98. package/build/components/PageToolbar.js +2 -10
  99. package/build/components/PrevNext.d.ts +1 -1
  100. package/build/components/PrevNext.js +2 -10
  101. package/build/components/Root.d.ts +4 -0
  102. package/build/components/Root.js +8 -0
  103. package/build/components/Search.d.ts +5 -2
  104. package/build/components/Search.js +11 -9
  105. package/build/components/SearchDialog.d.ts +1 -1
  106. package/build/components/SearchDialog.js +10 -133
  107. package/build/components/Section.d.ts +1 -1
  108. package/build/components/SectionHeader.d.ts +1 -1
  109. package/build/components/SheetPanel.d.ts +12 -0
  110. package/build/components/SheetPanel.js +19 -0
  111. package/build/components/Sidebar.d.ts +1 -1
  112. package/build/components/Sidebar.js +12 -14
  113. package/build/components/SidebarArticles.d.ts +4 -1
  114. package/build/components/SidebarArticles.js +5 -9
  115. package/build/components/SidebarLinks.d.ts +4 -1
  116. package/build/components/SidebarLinks.js +6 -9
  117. package/build/components/SidebarPosts.d.ts +4 -1
  118. package/build/components/SidebarPosts.js +7 -23
  119. package/build/components/SidebarReleases.d.ts +4 -1
  120. package/build/components/SidebarReleases.js +5 -15
  121. package/build/components/SidebarSectionPicker.d.ts +8 -0
  122. package/build/components/SidebarSectionPicker.js +31 -0
  123. package/build/components/SidebarSections.d.ts +1 -1
  124. package/build/components/SidebarSections.js +5 -9
  125. package/build/components/SiteLink.d.ts +1 -1
  126. package/build/components/SiteTitle.d.ts +1 -1
  127. package/build/components/SiteTitle.js +2 -6
  128. package/build/components/SortableTable.d.ts +1 -1
  129. package/build/components/SoundCloud.d.ts +1 -1
  130. package/build/components/SoundCloud.js +2 -2
  131. package/build/components/TagIndex.d.ts +1 -1
  132. package/build/components/TagIndex.js +2 -11
  133. package/build/components/Theme.d.ts +2 -1
  134. package/build/components/Theme.js +35 -15
  135. package/build/components/Toc.d.ts +5 -4
  136. package/build/components/Toc.js +35 -35
  137. package/build/components/YouTube.d.ts +1 -1
  138. package/build/components/YouTube.js +2 -2
  139. package/build/components/ZoomImage.d.ts +1 -1
  140. package/build/content/article.js +4 -11
  141. package/build/content-collections.js +6 -4
  142. package/build/elements/accordion.d.ts +4 -4
  143. package/build/elements/accordion.js +2 -3
  144. package/build/elements/alert-dialog.d.ts +12 -12
  145. package/build/elements/alert-dialog.js +2 -4
  146. package/build/elements/alert.d.ts +4 -4
  147. package/build/elements/alert.js +2 -2
  148. package/build/elements/aspect-ratio.d.ts +1 -1
  149. package/build/elements/avatar.d.ts +6 -6
  150. package/build/elements/badge.d.ts +1 -1
  151. package/build/elements/badge.js +3 -1
  152. package/build/elements/breadcrumb.d.ts +6 -6
  153. package/build/elements/breadcrumb.js +2 -4
  154. package/build/elements/button-group.d.ts +2 -2
  155. package/build/elements/button-group.js +5 -5
  156. package/build/elements/button.d.ts +2 -2
  157. package/build/elements/button.js +9 -7
  158. package/build/elements/calendar.d.ts +2 -2
  159. package/build/elements/calendar.js +2 -2
  160. package/build/elements/card.d.ts +7 -7
  161. package/build/elements/card.js +4 -4
  162. package/build/elements/carousel.d.ts +5 -5
  163. package/build/elements/carousel.js +3 -7
  164. package/build/elements/chart.d.ts +6 -6
  165. package/build/elements/chart.js +5 -11
  166. package/build/elements/checkbox.d.ts +1 -1
  167. package/build/elements/collapsible.d.ts +3 -3
  168. package/build/elements/command.d.ts +9 -9
  169. package/build/elements/command.js +5 -11
  170. package/build/elements/context-menu.d.ts +15 -15
  171. package/build/elements/context-menu.js +6 -9
  172. package/build/elements/dialog.d.ts +10 -10
  173. package/build/elements/dialog.js +2 -6
  174. package/build/elements/drawer.d.ts +14 -12
  175. package/build/elements/drawer.js +14 -15
  176. package/build/elements/dropdown-menu.d.ts +15 -15
  177. package/build/elements/dropdown-menu.js +7 -10
  178. package/build/elements/empty.d.ts +6 -6
  179. package/build/elements/empty.js +2 -2
  180. package/build/elements/field.d.ts +10 -10
  181. package/build/elements/field.js +3 -4
  182. package/build/elements/hover-card.d.ts +3 -3
  183. package/build/elements/hover-card.js +2 -2
  184. package/build/elements/input-group.d.ts +7 -7
  185. package/build/elements/input-group.js +5 -5
  186. package/build/elements/input-otp.d.ts +4 -4
  187. package/build/elements/input.d.ts +1 -1
  188. package/build/elements/input.js +2 -2
  189. package/build/elements/item.d.ts +9 -9
  190. package/build/elements/item.js +2 -2
  191. package/build/elements/kbd.d.ts +2 -2
  192. package/build/elements/label.d.ts +1 -1
  193. package/build/elements/menubar.d.ts +16 -16
  194. package/build/elements/menubar.js +9 -11
  195. package/build/elements/native-select.d.ts +3 -3
  196. package/build/elements/native-select.js +2 -4
  197. package/build/elements/navigation-menu.d.ts +8 -8
  198. package/build/elements/navigation-menu.js +3 -5
  199. package/build/elements/pagination.d.ts +7 -7
  200. package/build/elements/pagination.js +4 -10
  201. package/build/elements/popover.d.ts +6 -6
  202. package/build/elements/popover.js +2 -2
  203. package/build/elements/progress.d.ts +5 -5
  204. package/build/elements/progress.js +2 -3
  205. package/build/elements/radio-group.d.ts +2 -2
  206. package/build/elements/resizable.d.ts +3 -3
  207. package/build/elements/scroll-area.d.ts +2 -2
  208. package/build/elements/scroll-area.js +2 -4
  209. package/build/elements/select.d.ts +9 -9
  210. package/build/elements/select.js +4 -9
  211. package/build/elements/separator.d.ts +1 -1
  212. package/build/elements/sheet.d.ts +8 -8
  213. package/build/elements/sheet.js +2 -6
  214. package/build/elements/sidebar.d.ts +19 -19
  215. package/build/elements/sidebar.js +15 -37
  216. package/build/elements/skeleton.d.ts +1 -1
  217. package/build/elements/slider.d.ts +2 -1
  218. package/build/elements/slider.js +2 -3
  219. package/build/elements/sonner.d.ts +1 -1
  220. package/build/elements/spinner.d.ts +1 -1
  221. package/build/elements/switch.d.ts +1 -1
  222. package/build/elements/table.d.ts +8 -8
  223. package/build/elements/tabs.d.ts +4 -4
  224. package/build/elements/tabs.js +3 -3
  225. package/build/elements/textarea.d.ts +1 -1
  226. package/build/elements/textarea.js +2 -2
  227. package/build/elements/toggle-group.d.ts +3 -2
  228. package/build/elements/toggle-group.js +3 -3
  229. package/build/elements/toggle.d.ts +1 -1
  230. package/build/elements/toggle.js +2 -2
  231. package/build/elements/tooltip.d.ts +4 -4
  232. package/build/elements/tooltip.js +2 -3
  233. package/build/head.d.ts +4 -0
  234. package/build/head.js +6 -0
  235. package/build/helpers/agent-skills.d.ts +22 -0
  236. package/build/helpers/agent-skills.js +46 -0
  237. package/build/helpers/agent-skills.unit.d.ts +1 -0
  238. package/build/helpers/agent-skills.unit.js +49 -0
  239. package/build/helpers/article-search.d.ts +19 -0
  240. package/build/helpers/article-search.js +134 -0
  241. package/build/helpers/article.d.ts +13 -0
  242. package/build/helpers/article.js +17 -1
  243. package/build/helpers/dependency-dir.d.ts +5 -0
  244. package/build/helpers/dependency-dir.js +20 -0
  245. package/build/helpers/dependency-dir.unit.d.ts +1 -0
  246. package/build/helpers/dependency-dir.unit.js +25 -0
  247. package/build/helpers/dynamic-icon-resolver.d.ts +1 -1
  248. package/build/helpers/dynamic-icon.d.ts +1 -1
  249. package/build/helpers/head.d.ts +58 -0
  250. package/build/helpers/head.js +80 -0
  251. package/build/helpers/head.unit.d.ts +1 -0
  252. package/build/helpers/head.unit.js +110 -0
  253. package/build/helpers/llms.d.ts +33 -0
  254. package/build/helpers/llms.js +72 -0
  255. package/build/helpers/llms.unit.d.ts +1 -0
  256. package/build/helpers/llms.unit.js +98 -0
  257. package/build/helpers/nav-items.d.ts +11 -0
  258. package/build/helpers/nav-items.js +65 -0
  259. package/build/helpers/render-inline-markdown.d.ts +1 -0
  260. package/build/helpers/render-inline-markdown.js +34 -0
  261. package/build/helpers/render-inline-markdown.unit.d.ts +1 -0
  262. package/build/helpers/render-inline-markdown.unit.js +20 -0
  263. package/build/helpers/search-highlight.d.ts +8 -0
  264. package/build/helpers/search-highlight.js +59 -0
  265. package/build/helpers/search-highlight.unit.d.ts +1 -0
  266. package/build/helpers/search-highlight.unit.js +36 -0
  267. package/build/helpers/target-export.d.ts +9 -0
  268. package/build/helpers/target-export.js +24 -0
  269. package/build/helpers/target-export.unit.d.ts +1 -0
  270. package/build/helpers/target-export.unit.js +25 -0
  271. package/build/helpers/theme.d.ts +6 -2
  272. package/build/helpers/theme.js +40 -7
  273. package/build/helpers/theme.unit.d.ts +1 -0
  274. package/build/helpers/theme.unit.js +30 -0
  275. package/build/hooks/hydrated.d.ts +2 -0
  276. package/build/hooks/hydrated.js +15 -0
  277. package/build/index.d.ts +1 -0
  278. package/build/index.js +1 -1
  279. package/build/models/config.d.ts +52 -6
  280. package/build/models/config.js +17 -1
  281. package/build/models/section.d.ts +4 -2
  282. package/build/models/section.js +1 -1
  283. package/build/plugins/vite-agents.d.ts +17 -0
  284. package/build/plugins/vite-agents.js +109 -0
  285. package/build/plugins/vite-agents.unit.d.ts +1 -0
  286. package/build/plugins/vite-agents.unit.js +20 -0
  287. package/build/plugins/vite-livemark.d.ts +4 -5
  288. package/build/plugins/vite-livemark.js +56 -90
  289. package/build/plugins/vite-robots.d.ts +4 -2
  290. package/build/plugins/vite-robots.js +15 -2
  291. package/build/plugins/vite-robots.unit.js +5 -1
  292. package/build/program.js +4 -2
  293. package/build/routes/$.d.ts +4 -1
  294. package/build/routes/$.js +20 -9
  295. package/build/routes/__root.js +29 -63
  296. package/build/settings.js +2 -1
  297. package/build/vite.config.js +3 -1
  298. package/package.json +69 -66
  299. package/{.agents/skills → skills}/livemark-authoring/SKILL.md +2 -2
  300. package/{.agents/skills → skills}/livemark-configuration/SKILL.md +16 -5
  301. package/skills/livemark-customization/SKILL.md +146 -0
  302. package/source/actions/config/define.unit.ts +9 -0
  303. package/source/actions/escape/copy.ts +35 -0
  304. package/source/actions/escape/copy.unit.ts +51 -0
  305. package/source/actions/escape/list.ts +30 -0
  306. package/source/actions/escape/list.unit.ts +42 -0
  307. package/source/actions/target/build.ts +49 -69
  308. package/source/actions/target/build.unit.ts +95 -0
  309. package/source/actions/target/clear.ts +14 -0
  310. package/source/actions/target/clear.unit.ts +25 -0
  311. package/source/commands/build.ts +0 -1
  312. package/source/commands/clear.ts +15 -0
  313. package/source/commands/escape.ts +42 -59
  314. package/source/commands/preview.ts +0 -1
  315. package/source/commands/start.ts +0 -1
  316. package/source/components/AnsiCode.tsx +1 -1
  317. package/source/components/Article.tsx +8 -4
  318. package/source/components/Banner.tsx +12 -2
  319. package/source/components/BlogIndex.tsx +1 -1
  320. package/source/components/Callout.tsx +4 -6
  321. package/source/components/ChangelogIndex.tsx +1 -1
  322. package/source/components/ChoiceList.tsx +69 -0
  323. package/source/components/CodeBlock.tsx +6 -6
  324. package/source/components/CodeTabs.tsx +1 -1
  325. package/source/components/ContentTabs.tsx +1 -1
  326. package/source/components/DefaultCatchBoundary.tsx +4 -6
  327. package/source/components/Details.tsx +1 -1
  328. package/source/components/FileTree.tsx +1 -1
  329. package/source/components/Header.tsx +52 -0
  330. package/source/components/HeaderMenu.tsx +41 -0
  331. package/source/components/HeaderNav.tsx +145 -0
  332. package/source/components/HeaderSearch.tsx +77 -0
  333. package/source/components/InlineBadge.tsx +1 -1
  334. package/source/components/InlineToc.tsx +1 -1
  335. package/source/components/Layout.tsx +16 -160
  336. package/source/components/LinkButton.tsx +9 -1
  337. package/source/components/MenuSheet.tsx +92 -0
  338. package/source/components/MermaidRenderer.tsx +19 -8
  339. package/source/components/NotFound.tsx +3 -5
  340. package/source/components/PackageTabs.tsx +2 -2
  341. package/source/components/PageToolbar.tsx +11 -3
  342. package/source/components/PrevNext.tsx +2 -2
  343. package/source/components/Root.tsx +13 -0
  344. package/source/components/Search.tsx +28 -8
  345. package/source/components/SearchDialog.tsx +15 -189
  346. package/source/components/SheetPanel.tsx +69 -0
  347. package/source/components/Sidebar.tsx +27 -14
  348. package/source/components/SidebarArticles.tsx +4 -3
  349. package/source/components/SidebarLinks.tsx +3 -2
  350. package/source/components/SidebarPosts.tsx +3 -2
  351. package/source/components/SidebarReleases.tsx +3 -2
  352. package/source/components/SidebarSectionPicker.tsx +70 -0
  353. package/source/components/SiteTitle.tsx +5 -5
  354. package/source/components/SoundCloud.tsx +1 -1
  355. package/source/components/TagIndex.tsx +1 -1
  356. package/source/components/Theme.tsx +55 -29
  357. package/source/components/Toc.tsx +76 -55
  358. package/source/components/YouTube.tsx +1 -1
  359. package/source/content/article.ts +8 -13
  360. package/source/content-collections.ts +5 -4
  361. package/source/elements/alert-dialog.tsx +1 -1
  362. package/source/elements/alert.tsx +1 -1
  363. package/source/elements/badge.tsx +4 -0
  364. package/source/elements/button-group.tsx +4 -4
  365. package/source/elements/button.tsx +10 -6
  366. package/source/elements/calendar.tsx +1 -1
  367. package/source/elements/card.tsx +3 -3
  368. package/source/elements/command.tsx +7 -4
  369. package/source/elements/context-menu.tsx +5 -5
  370. package/source/elements/dialog.tsx +1 -1
  371. package/source/elements/drawer.tsx +59 -43
  372. package/source/elements/dropdown-menu.tsx +6 -6
  373. package/source/elements/empty.tsx +1 -1
  374. package/source/elements/field.tsx +1 -1
  375. package/source/elements/hover-card.tsx +1 -1
  376. package/source/elements/input-group.tsx +4 -4
  377. package/source/elements/input.tsx +1 -1
  378. package/source/elements/item.tsx +1 -1
  379. package/source/elements/menubar.tsx +8 -8
  380. package/source/elements/native-select.tsx +1 -1
  381. package/source/elements/popover.tsx +1 -1
  382. package/source/elements/select.tsx +3 -3
  383. package/source/elements/sidebar.tsx +8 -21
  384. package/source/elements/tabs.tsx +2 -2
  385. package/source/elements/textarea.tsx +1 -1
  386. package/source/elements/toggle-group.tsx +2 -2
  387. package/source/elements/toggle.tsx +1 -1
  388. package/source/env.d.ts +1 -0
  389. package/source/head.ts +7 -0
  390. package/source/helpers/agent-skills.ts +59 -0
  391. package/source/helpers/agent-skills.unit.ts +56 -0
  392. package/source/helpers/article-search.tsx +192 -0
  393. package/source/helpers/article.ts +17 -0
  394. package/source/helpers/dependency-dir.ts +20 -0
  395. package/source/helpers/dependency-dir.unit.ts +39 -0
  396. package/source/helpers/head.ts +105 -0
  397. package/source/helpers/head.unit.ts +118 -0
  398. package/source/helpers/llms.ts +109 -0
  399. package/source/helpers/llms.unit.ts +115 -0
  400. package/source/helpers/nav-items.tsx +102 -0
  401. package/source/helpers/render-inline-markdown.ts +44 -0
  402. package/source/helpers/render-inline-markdown.unit.ts +30 -0
  403. package/source/helpers/search-highlight.ts +73 -0
  404. package/source/helpers/search-highlight.unit.ts +42 -0
  405. package/source/helpers/target-export.ts +28 -0
  406. package/source/helpers/target-export.unit.ts +37 -0
  407. package/source/helpers/theme.ts +40 -6
  408. package/source/helpers/theme.unit.ts +32 -0
  409. package/source/hooks/hydrated.ts +18 -0
  410. package/source/index.ts +1 -0
  411. package/source/models/config.ts +24 -0
  412. package/source/models/section.ts +3 -0
  413. package/source/plugins/vite-agents.ts +135 -0
  414. package/source/plugins/vite-agents.unit.ts +26 -0
  415. package/source/plugins/vite-livemark.ts +54 -95
  416. package/source/plugins/vite-robots.ts +18 -3
  417. package/source/plugins/vite-robots.unit.ts +7 -0
  418. package/source/program.ts +2 -0
  419. package/source/routes/$.tsx +27 -9
  420. package/source/routes/__root.tsx +51 -71
  421. package/source/settings.ts +1 -0
  422. package/source/styles/general.css +59 -11
  423. package/source/styles/markdown.css +13 -7
  424. package/source/styles/shape.css +14 -0
  425. package/source/vite.config.ts +2 -0
  426. package/.agents/skills/change-review/SKILL.md +0 -47
  427. package/.agents/skills/livemark-customization/SKILL.md +0 -118
@@ -1,15 +1,3 @@
1
- import { config } from "livemark:virtual"
2
- import { Link, useLocation, useMatch } from "@tanstack/react-router"
3
- import { useHotkey } from "@tanstack/react-hotkeys"
4
- import {
5
- currentSection,
6
- sectionFirstArticle,
7
- sectionFlatArticles,
8
- sortedArticles,
9
- } from "../content/article.ts"
10
- import { DynamicIcon } from "../helpers/dynamic-icon.tsx"
11
- import { prefixUrl } from "../helpers/prefix-url.ts"
12
- import { activeSiteLink, customSectionActive } from "../helpers/section.ts"
13
1
  import {
14
2
  SidebarInset,
15
3
  SidebarProvider,
@@ -18,160 +6,25 @@ import {
18
6
  } from "../elements/sidebar.tsx"
19
7
  import { BackToTop } from "./BackToTop.tsx"
20
8
  import { Banner } from "./Banner.tsx"
9
+ import { Header } from "./Header.tsx"
21
10
  import { Sidebar } from "./Sidebar.tsx"
22
- import { SiteLink } from "./SiteLink.tsx"
23
- import { SiteTitle } from "./SiteTitle.tsx"
24
-
25
- function splatFor(pathname: string) {
26
- return { _splat: pathname.replace(/^\/|\/$/g, "") }
27
- }
28
11
 
12
+ /** Site chrome around a page: banner, header, sidebar and back-to-top */
29
13
  export function Layout(props: { withSidebar?: boolean; children?: React.ReactNode }) {
30
- const pathname = useLocation({ select: l => l.pathname })
31
- const articleRoute = useMatch({ from: "/$", shouldThrow: false })
32
- const activeSection = articleRoute
33
- ? currentSection(`/${pathname.replace(/^\/|\/$/g, "")}/`)
34
- : undefined
35
- const siteLinkTarget = activeSiteLink(pathname, config.sections ?? [])
36
-
37
- useHotkey("J", () =>
38
- window.scrollBy({ top: window.innerHeight * 0.8, behavior: "smooth" }),
39
- )
40
- useHotkey("K", () =>
41
- window.scrollBy({ top: -window.innerHeight * 0.8, behavior: "smooth" }),
42
- )
43
-
44
- const sections = config.sections
45
-
46
- const header = (
47
- <header className="sticky top-0 z-20 flex h-16 shrink-0 items-center border-b bg-background">
48
- <div
49
- className={`flex items-center self-stretch pl-4 ${props.withSidebar ? "pr-4" : "lg:pr-20"}`}
50
- >
51
- {props.withSidebar ? (
52
- <>
53
- <div className="hidden lg:flex">
54
- <SidebarTrigger />
55
- </div>
56
- <SiteLink to={siteLinkTarget} className="lg:hidden flex items-center gap-2">
57
- <SiteTitle />
58
- </SiteLink>
59
- </>
60
- ) : (
61
- <SiteLink to={siteLinkTarget} className="flex items-center gap-2">
62
- <SiteTitle />
63
- </SiteLink>
64
- )}
65
- </div>
66
- <div className="hidden lg:flex flex-1 items-center gap-8 self-stretch px-6 text-sm">
67
- {sections?.length ? (
68
- sections
69
- .filter(section => section.position === "header")
70
- .map(section => {
71
- const icon = section.icon
72
- if (section.type === "custom") {
73
- const isActive = customSectionActive(section.url, pathname)
74
- return (
75
- <a
76
- key={section.url}
77
- href={prefixUrl(section.url, config.base)}
78
- className={`inline-flex items-center gap-1.5 text-foreground ${
79
- isActive
80
- ? "font-medium border-b-2 border-foreground pb-0.5 -mb-0.5"
81
- : "opacity-80 hover:opacity-100 transition-opacity"
82
- }`}
83
- >
84
- {icon && <DynamicIcon name={icon} className="size-3.5" />}
85
- <span>{section.title}</span>
86
- </a>
87
- )
88
- }
89
- const isActive = activeSection?.prefix === section.prefix
90
- const target =
91
- section.type === "blog" || section.type === "changelog"
92
- ? section.prefix
93
- : sectionFirstArticle.get(section.prefix)
94
- const latestVersion =
95
- section.type === "changelog" && section.version
96
- ? sortedArticles.find(
97
- a => a.path === sectionFlatArticles.get(section.prefix)?.[0],
98
- )?.title
99
- : undefined
100
- return (
101
- <Link
102
- key={section.prefix}
103
- to={target === "/" ? "/" : "/$"}
104
- params={target && target !== "/" ? splatFor(target) : {}}
105
- className={`inline-flex items-center gap-1.5 text-foreground ${
106
- isActive
107
- ? "font-medium border-b-2 border-foreground pb-0.5 -mb-0.5"
108
- : "opacity-80 hover:opacity-100 transition-opacity"
109
- }`}
110
- >
111
- {icon && <DynamicIcon name={icon} className="size-3.5" />}
112
- <span>
113
- {section.title}
114
- {latestVersion && (
115
- <span className="opacity-80"> ({latestVersion})</span>
116
- )}
117
- </span>
118
- </Link>
119
- )
120
- })
121
- ) : (
122
- <Link
123
- to="/"
124
- className="text-foreground font-medium underline underline-offset-4"
125
- >
126
- Docs
127
- </Link>
128
- )}
129
- {config.links
130
- ?.filter(
131
- link =>
132
- link.position === "header" &&
133
- (!link.prefix || link.prefix === activeSection?.prefix),
134
- )
135
- .map(link => (
136
- <a
137
- key={link.url}
138
- href={prefixUrl(link.url, config.base)}
139
- className="text-foreground opacity-80 hover:opacity-100 transition-opacity"
140
- >
141
- {link.icon && (
142
- <DynamicIcon
143
- name={link.icon}
144
- className="inline size-3.5 align-[-0.125em]"
145
- />
146
- )}{" "}
147
- {link.title}
148
- </a>
149
- ))}
150
- <Banner />
151
- </div>
152
- <div className="lg:hidden ml-auto pr-2">
153
- <SidebarTrigger />
154
- </div>
155
- </header>
156
- )
157
-
158
14
  return (
159
- <SidebarProvider
160
- key={props.withSidebar ? "sidebar" : "mini"}
161
- defaultOpen={!!props.withSidebar}
162
- >
163
- <SidebarShell withSidebar={props.withSidebar} header={header}>
164
- {props.children}
165
- </SidebarShell>
166
- </SidebarProvider>
15
+ <>
16
+ <Banner />
17
+ <SidebarProvider
18
+ key={props.withSidebar ? "sidebar" : "mini"}
19
+ defaultOpen={!!props.withSidebar}
20
+ >
21
+ <SidebarShell withSidebar={props.withSidebar}>{props.children}</SidebarShell>
22
+ </SidebarProvider>
23
+ </>
167
24
  )
168
25
  }
169
26
 
170
- function SidebarShell(props: {
171
- withSidebar?: boolean
172
- header: React.ReactNode
173
- children?: React.ReactNode
174
- }) {
27
+ function SidebarShell(props: { withSidebar?: boolean; children?: React.ReactNode }) {
175
28
  const { isMobile, setOpenMobile } = useSidebar()
176
29
  const onClick = (event: React.MouseEvent<HTMLDivElement>) => {
177
30
  if (!isMobile) return
@@ -181,7 +34,10 @@ function SidebarShell(props: {
181
34
  <div style={{ display: "contents" }} onClick={onClick}>
182
35
  <Sidebar withSidebar={props.withSidebar} />
183
36
  <SidebarInset>
184
- {props.header}
37
+ <Header
38
+ toggle={props.withSidebar && <SidebarTrigger />}
39
+ menu={<SidebarTrigger />}
40
+ />
185
41
  <main className="flex-1">{props.children}</main>
186
42
  <BackToTop />
187
43
  </SidebarInset>
@@ -5,7 +5,15 @@ import { cn } from "cn"
5
5
  export function LinkButton(props: {
6
6
  href: string
7
7
  label: string
8
- variant?: "default" | "outline" | "secondary" | "ghost" | "destructive" | "link"
8
+ variant?:
9
+ | "default"
10
+ | "outline"
11
+ | "secondary"
12
+ | "ghost"
13
+ | "positive"
14
+ | "warning"
15
+ | "destructive"
16
+ | "link"
9
17
  size?: "default" | "sm" | "lg"
10
18
  }) {
11
19
  return (
@@ -0,0 +1,92 @@
1
+ import { CheckIcon } from "lucide-react"
2
+ import { cloneElement, useState, type ReactElement, type ReactNode } from "react"
3
+ import { cn } from "cn"
4
+ import {
5
+ DropdownMenu,
6
+ DropdownMenuContent,
7
+ DropdownMenuItem,
8
+ DropdownMenuTrigger,
9
+ } from "../elements/dropdown-menu.tsx"
10
+ import { useIsMobile } from "../hooks/media.ts"
11
+ import { SheetPanel } from "./SheetPanel.tsx"
12
+
13
+ /** One row of a `MenuSheet` */
14
+ export type MenuSheetItem = {
15
+ id: string
16
+ label: ReactNode
17
+ icon?: ReactNode
18
+ active?: boolean
19
+ onSelect?: () => void
20
+ }
21
+
22
+ /** A menu that is an anchored dropdown from a laptop up and a bottom sheet on a
23
+ * phone */
24
+ export function MenuSheet(props: {
25
+ trigger: ReactElement<{ onClick?: () => void; children?: ReactNode }>
26
+ children?: ReactNode
27
+ title: ReactNode
28
+ items: MenuSheetItem[]
29
+ align?: "start" | "end"
30
+ onOpenChange?: (open: boolean) => void
31
+ }) {
32
+ const isMobile = useIsMobile()
33
+ const [open, setOpen] = useState(false)
34
+ const changeOpen = (next: boolean) => {
35
+ setOpen(next)
36
+ props.onOpenChange?.(next)
37
+ }
38
+
39
+ if (isMobile) {
40
+ return (
41
+ <>
42
+ {cloneElement(props.trigger, { onClick: () => changeOpen(true) }, props.children)}
43
+ <SheetPanel open={open} onOpenChange={changeOpen} title={props.title}>
44
+ <ul className="flex w-full min-w-0 flex-col gap-1">
45
+ {props.items.map(item => (
46
+ <li key={item.id}>
47
+ <button
48
+ type="button"
49
+ className={cn(ROW, item.active && ROW_ACTIVE)}
50
+ onClick={() => {
51
+ item.onSelect?.()
52
+ changeOpen(false)
53
+ }}
54
+ >
55
+ {item.icon}
56
+ <span className="flex-1 truncate">{item.label}</span>
57
+ {item.active && <CheckIcon className="size-4 shrink-0" />}
58
+ </button>
59
+ </li>
60
+ ))}
61
+ </ul>
62
+ </SheetPanel>
63
+ </>
64
+ )
65
+ }
66
+
67
+ return (
68
+ <DropdownMenu onOpenChange={props.onOpenChange}>
69
+ {/* Without a `render`, Base UI's trigger falls back to a bare <button> — which
70
+ SSR paints on a phone until `useIsMobile` flips, flashing a stray icon. */}
71
+ <DropdownMenuTrigger render={props.trigger}>{props.children}</DropdownMenuTrigger>
72
+ <DropdownMenuContent align={props.align ?? "end"}>
73
+ {props.items.map(item => (
74
+ <DropdownMenuItem
75
+ key={item.id}
76
+ onClick={item.onSelect}
77
+ className="cursor-pointer gap-2"
78
+ >
79
+ {item.icon}
80
+ <span className={item.active ? "font-medium" : undefined}>{item.label}</span>
81
+ </DropdownMenuItem>
82
+ ))}
83
+ </DropdownMenuContent>
84
+ </DropdownMenu>
85
+ )
86
+ }
87
+
88
+ const ROW =
89
+ "hover:bg-muted active:bg-muted flex h-10 w-full items-center gap-2.5 overflow-hidden rounded-md p-2 text-left text-base outline-hidden [&_svg]:size-[18px] [&_svg]:shrink-0"
90
+
91
+ const ROW_ACTIVE =
92
+ "bg-sidebar-accent text-sidebar-accent-foreground font-semibold [&_svg]:stroke-[2.5]"
@@ -3,6 +3,10 @@ import mermaid from "mermaid"
3
3
 
4
4
  mermaid.initialize({ startOnLoad: false })
5
5
 
6
+ // Module-wide so runs never overlap, even across effect re-runs: overlapping runs on
7
+ // one node reject with "reading 'firstChild'".
8
+ let renderQueue = Promise.resolve()
9
+
6
10
  /** Renders a Mermaid diagram from a chart definition string */
7
11
  export default function MermaidRenderer(props: { children: string }) {
8
12
  const ref = useRef<HTMLDivElement>(null)
@@ -12,14 +16,21 @@ export default function MermaidRenderer(props: { children: string }) {
12
16
  if (!el) return
13
17
 
14
18
  const render = () => {
15
- const isDark = document.documentElement.classList.contains("dark")
16
- mermaid.initialize({
17
- startOnLoad: false,
18
- theme: isDark ? "dark" : "default",
19
- })
20
- el.textContent = props.children
21
- el.removeAttribute("data-processed")
22
- mermaid.run({ nodes: [el] })
19
+ renderQueue = renderQueue
20
+ .then(() => {
21
+ if (!el.isConnected) return
22
+ const isDark = document.documentElement.classList.contains("dark")
23
+ mermaid.initialize({
24
+ startOnLoad: false,
25
+ theme: isDark ? "dark" : "default",
26
+ })
27
+ el.textContent = props.children
28
+ el.removeAttribute("data-processed")
29
+ return mermaid.run({ nodes: [el] })
30
+ })
31
+ .catch(error => {
32
+ if (el.isConnected) console.error(error)
33
+ })
23
34
  }
24
35
 
25
36
  render()
@@ -1,4 +1,5 @@
1
1
  import { Link } from "@tanstack/react-router"
2
+ import { buttonVariants } from "../elements/button.tsx"
2
3
 
3
4
  export function NotFound({ children }: { children?: any }) {
4
5
  return (
@@ -11,14 +12,11 @@ export function NotFound({ children }: { children?: any }) {
11
12
  <button
12
13
  type="button"
13
14
  onClick={() => window.history.back()}
14
- className="bg-primary text-primary-foreground px-4 py-2 text-sm font-medium hover:bg-primary/80 transition-colors"
15
+ className={buttonVariants({ size: "lg" })}
15
16
  >
16
17
  Go Back
17
18
  </button>
18
- <Link
19
- to="/"
20
- className="border border-border px-4 py-2 text-sm font-medium hover:bg-card transition-colors"
21
- >
19
+ <Link to="/" className={buttonVariants({ variant: "outline", size: "lg" })}>
22
20
  Home
23
21
  </Link>
24
22
  </div>
@@ -31,7 +31,7 @@ export function PackageTabs(props: PackageTabsProps) {
31
31
  }
32
32
 
33
33
  return (
34
- <figure className="not-prose my-4 relative rounded-xl border shadow-sm overflow-hidden text-sm bg-sidebar dark:bg-sidebar">
34
+ <figure className="not-prose my-4 relative rounded-card border shadow-sm overflow-hidden text-sm bg-sidebar dark:bg-sidebar">
35
35
  <div className="flex items-center border-b">
36
36
  <div className="flex flex-1 items-center">
37
37
  {managers.map(pm => (
@@ -52,7 +52,7 @@ export function PackageTabs(props: PackageTabsProps) {
52
52
  <button
53
53
  type="button"
54
54
  onClick={handleCopy}
55
- className="me-2 p-1 rounded-md text-muted-foreground hover:text-foreground transition-colors"
55
+ className="me-2 p-1 rounded-control text-muted-foreground hover:text-foreground transition-colors"
56
56
  aria-label="Copy code"
57
57
  >
58
58
  {copied ? <Check className="size-3.5" /> : <Clipboard className="size-3.5" />}
@@ -37,13 +37,13 @@ export function PageToolbar(props: {
37
37
 
38
38
  return (
39
39
  <>
40
- <div className="mb-6 flex flex-col gap-2 text-sm">
41
- <p className="text-sm font-medium mb-1">Actions</p>
40
+ <div data-slot="page-toolbar" className="flex flex-col gap-2 text-sm">
42
41
  {sourceHref ? (
43
42
  <a
44
43
  href={sourceHref}
45
44
  target="_blank"
46
45
  rel="noopener noreferrer"
46
+ data-slot="page-action"
47
47
  className={buttonClass}
48
48
  >
49
49
  <SourceIcon className="size-3.5" />
@@ -51,6 +51,7 @@ export function PageToolbar(props: {
51
51
  </a>
52
52
  ) : (
53
53
  <span
54
+ data-slot="page-action"
54
55
  className={`${buttonClass} opacity-50 cursor-not-allowed hover:text-muted-foreground`}
55
56
  aria-disabled="true"
56
57
  >
@@ -58,13 +59,19 @@ export function PageToolbar(props: {
58
59
  {sourceLabel}
59
60
  </span>
60
61
  )}
61
- <button type="button" onClick={handleCopy} className={buttonClass}>
62
+ <button
63
+ type="button"
64
+ onClick={handleCopy}
65
+ data-slot="page-action"
66
+ className={buttonClass}
67
+ >
62
68
  {copied ? <Check className="size-3.5" /> : <Copy className="size-3.5" />}
63
69
  Copy Markdown
64
70
  </button>
65
71
  <button
66
72
  type="button"
67
73
  onClick={() => openIn("https://chatgpt.com/", { hints: "search" })}
74
+ data-slot="page-action"
68
75
  className={buttonClass}
69
76
  >
70
77
  <ExternalLink className="size-3.5" />
@@ -73,6 +80,7 @@ export function PageToolbar(props: {
73
80
  <button
74
81
  type="button"
75
82
  onClick={() => openIn("https://claude.ai/new")}
83
+ data-slot="page-action"
76
84
  className={buttonClass}
77
85
  >
78
86
  <ExternalLink className="size-3.5" />
@@ -29,7 +29,7 @@ export function PrevNext(props: { path: string }) {
29
29
  <Link
30
30
  to="/$"
31
31
  params={{ _splat: prev.path.replace(/^\/|\/$/g, "") }}
32
- className="flex-1 rounded-xl border shadow-sm p-4 hover:bg-muted/50 transition-colors"
32
+ className="flex-1 rounded-card border shadow-sm p-4 hover:bg-muted/50 transition-colors"
33
33
  >
34
34
  <span className="flex items-center gap-1 text-sm text-muted-foreground">
35
35
  <ChevronLeft className="size-4" />
@@ -42,7 +42,7 @@ export function PrevNext(props: { path: string }) {
42
42
  <Link
43
43
  to="/$"
44
44
  params={{ _splat: next.path.replace(/^\/|\/$/g, "") }}
45
- className="flex-1 rounded-xl border shadow-sm p-4 hover:bg-muted/50 transition-colors text-right"
45
+ className="flex-1 rounded-card border shadow-sm p-4 hover:bg-muted/50 transition-colors text-right"
46
46
  >
47
47
  <span className="flex items-center justify-end gap-1 text-sm text-muted-foreground">
48
48
  Next
@@ -0,0 +1,13 @@
1
+ import { useHotkey } from "@tanstack/react-hotkeys"
2
+
3
+ /** Headless wrapper around every route; pages add their own chrome with `Layout` */
4
+ export function Root(props: { children?: React.ReactNode }) {
5
+ useHotkey("J", () =>
6
+ window.scrollBy({ top: window.innerHeight * 0.8, behavior: "smooth" }),
7
+ )
8
+ useHotkey("K", () =>
9
+ window.scrollBy({ top: -window.innerHeight * 0.8, behavior: "smooth" }),
10
+ )
11
+
12
+ return props.children
13
+ }
@@ -1,27 +1,47 @@
1
1
  import { useState } from "react"
2
2
  import { useHotkey } from "@tanstack/react-hotkeys"
3
3
  import { Search as SearchIcon } from "lucide-react"
4
+ import { cn } from "cn"
5
+ import { isMobileNow } from "../hooks/media.ts"
6
+ import { HeaderSearch } from "./HeaderSearch.tsx"
4
7
  import { SearchDialog } from "./SearchDialog.tsx"
5
8
 
6
- /** Search button with "/" keyboard shortcut and command palette dialog */
7
- export function Search() {
9
+ /** Search button with "S" keyboard shortcut: a command palette from `lg`, an in-header field below.
10
+ * `compact` keeps it an icon from `lg` too, when header sections need the room */
11
+ export function Search(props: { compact?: boolean }) {
8
12
  const [open, setOpen] = useState(false)
13
+ const [headerOpen, setHeaderOpen] = useState(false)
14
+ const openSearch = () => (isMobileNow() ? setHeaderOpen(true) : setOpen(true))
9
15
 
10
- useHotkey("/", () => setOpen(true))
16
+ useHotkey("S", openSearch)
11
17
 
12
18
  return (
13
19
  <>
14
20
  <button
15
21
  type="button"
16
- onClick={() => setOpen(true)}
17
- className="flex w-full items-center gap-2 rounded-xl border border-border bg-sidebar-accent/70 px-3 py-2 text-sm text-muted-foreground shadow-xs hover:bg-background transition-colors cursor-pointer"
22
+ onClick={openSearch}
23
+ aria-label="Search"
24
+ aria-keyshortcuts="S"
25
+ title="Search"
26
+ className={cn(
27
+ "flex h-9 items-center gap-2 rounded-control border border-border bg-muted/50 px-2.5 text-sm text-muted-foreground shadow-xs hover:bg-muted transition-colors cursor-pointer",
28
+ !props.compact && "lg:w-56",
29
+ )}
18
30
  >
19
31
  <SearchIcon className="size-4" />
20
- <span className="flex-1 text-left">Search...</span>
21
- <kbd className="rounded border border-border bg-muted px-1.5 py-0.5 text-[10px] font-mono">
22
- /
32
+ <span className={cn("hidden flex-1 text-left", !props.compact && "lg:inline")}>
33
+ Search...
34
+ </span>
35
+ <kbd
36
+ className={cn(
37
+ "hidden rounded border border-border bg-background px-1.5 py-0.5 text-[10px] font-mono",
38
+ !props.compact && "lg:inline",
39
+ )}
40
+ >
41
+ S
23
42
  </kbd>
24
43
  </button>
44
+ {headerOpen && <HeaderSearch onClose={() => setHeaderOpen(false)} />}
25
45
  <SearchDialog open={open} onOpenChange={setOpen} />
26
46
  </>
27
47
  )