@takazudo/zudo-doc 5.28.2 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (456) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +49 -16
  3. package/bin/gen-z-index.mjs +18 -18
  4. package/dist/agent-docs/identity.d.ts +4 -0
  5. package/dist/agent-docs/identity.js +24 -0
  6. package/dist/agent-docs/index.d.ts +5 -0
  7. package/dist/agent-docs/index.js +5 -0
  8. package/dist/agent-docs/limits.d.ts +11 -0
  9. package/dist/agent-docs/limits.js +24 -0
  10. package/dist/agent-docs/search.d.ts +14 -0
  11. package/dist/agent-docs/search.js +82 -0
  12. package/dist/agent-docs/tokenize.d.ts +2 -0
  13. package/dist/agent-docs/tokenize.js +22 -0
  14. package/dist/agent-docs/types.d.ts +68 -0
  15. package/dist/agent-docs/types.js +0 -0
  16. package/dist/ai-chat-modal/index.d.ts +1 -4
  17. package/dist/ai-chat-modal/index.js +183 -123
  18. package/dist/asset-components/asset-card.d.ts +1 -2
  19. package/dist/asset-components/asset-card.js +12 -12
  20. package/dist/asset-components/asset-code.d.ts +1 -2
  21. package/dist/asset-components/asset-code.js +10 -10
  22. package/dist/asset-components/shared.d.ts +3 -4
  23. package/dist/asset-components/shared.js +4 -4
  24. package/dist/asset-index-page/body.d.ts +5 -6
  25. package/dist/asset-index-page/body.js +6 -6
  26. package/dist/asset-index-page/index.d.ts +1 -2
  27. package/dist/asset-index-page/index.js +1 -1
  28. package/dist/asset-page/body.d.ts +5 -9
  29. package/dist/asset-page/body.js +3 -3
  30. package/dist/asset-page/components.d.ts +16 -17
  31. package/dist/asset-page/components.js +10 -9
  32. package/dist/asset-page/index.d.ts +1 -2
  33. package/dist/asset-page/index.js +1 -1
  34. package/dist/auto-logo/index.d.ts +1 -2
  35. package/dist/auto-logo/index.js +2 -2
  36. package/dist/body-foot-util/body-foot-util-area.d.ts +3 -4
  37. package/dist/body-foot-util/body-foot-util-area.js +1 -2
  38. package/dist/body-foot-util/edit-link.d.ts +2 -3
  39. package/dist/body-foot-util/edit-link.js +1 -2
  40. package/dist/breadcrumb/breadcrumb.d.ts +6 -6
  41. package/dist/breadcrumb/breadcrumb.js +3 -4
  42. package/dist/category-nav/index.d.ts +1 -2
  43. package/dist/category-nav/index.js +11 -5
  44. package/dist/category-tree-nav/index.d.ts +1 -2
  45. package/dist/category-tree-nav/index.js +3 -3
  46. package/dist/chrome/derive.d.ts +18 -27
  47. package/dist/chrome/derive.js +47 -29
  48. package/dist/chrome/index.d.ts +5 -5
  49. package/dist/chrome/index.js +1 -1
  50. package/dist/chrome/island-data.d.ts +4 -0
  51. package/dist/chrome/island-data.js +52 -0
  52. package/dist/chrome/primary-slots.d.ts +2 -3
  53. package/dist/chrome-bindings.d.ts +28 -22
  54. package/dist/code-group/index.d.ts +3 -4
  55. package/dist/code-group/index.js +3 -7
  56. package/dist/code-syntax/code-block-enhancer.d.ts +1 -2
  57. package/dist/code-syntax/code-block-enhancer.js +2 -2
  58. package/dist/code-syntax/mermaid-init.d.ts +1 -2
  59. package/dist/code-syntax/mermaid-init.js +5 -2
  60. package/dist/code-syntax/tabs-init-script.js +1 -1
  61. package/dist/code-syntax/tabs-init.d.ts +1 -2
  62. package/dist/code-syntax/tabs-init.js +2 -2
  63. package/dist/code-syntax/tabs.d.ts +6 -6
  64. package/dist/code-syntax/tabs.js +8 -8
  65. package/dist/compiled.css +2933 -2943
  66. package/dist/config-assertions/index.d.ts +13 -0
  67. package/dist/config-assertions/index.js +14 -0
  68. package/dist/config.d.ts +36 -17
  69. package/dist/config.js +23 -95
  70. package/dist/content/content-blockquote.d.ts +2 -3
  71. package/dist/content/content-blockquote.js +3 -3
  72. package/dist/content/content-code.d.ts +3 -4
  73. package/dist/content/content-code.js +5 -5
  74. package/dist/content/content-link.d.ts +3 -4
  75. package/dist/content/content-link.js +10 -10
  76. package/dist/content/content-ol.d.ts +2 -3
  77. package/dist/content/content-ol.js +5 -4
  78. package/dist/content/content-paragraph.d.ts +2 -3
  79. package/dist/content/content-paragraph.js +1 -1
  80. package/dist/content/content-strong.d.ts +2 -3
  81. package/dist/content/content-strong.js +3 -3
  82. package/dist/content/content-table.d.ts +2 -3
  83. package/dist/content/content-table.js +4 -4
  84. package/dist/content/content-ul.d.ts +2 -3
  85. package/dist/content/content-ul.js +4 -4
  86. package/dist/content/heading-h2.d.ts +2 -3
  87. package/dist/content/heading-h2.js +4 -4
  88. package/dist/content/heading-h3.d.ts +2 -3
  89. package/dist/content/heading-h3.js +4 -4
  90. package/dist/content/heading-h4.d.ts +2 -3
  91. package/dist/content/heading-h4.js +4 -4
  92. package/dist/content-admonition/index.d.ts +3 -4
  93. package/dist/content-admonition/index.js +2 -2
  94. package/dist/content.css +35 -33
  95. package/dist/design-token-panel-bootstrap-controller.d.ts +178 -0
  96. package/dist/design-token-panel-bootstrap-controller.js +359 -0
  97. package/dist/design-token-panel-bootstrap-island.d.ts +5 -0
  98. package/dist/design-token-panel-bootstrap-island.js +19 -0
  99. package/dist/design-token-panel-bootstrap.d.ts +5 -195
  100. package/dist/design-token-panel-bootstrap.js +3 -288
  101. package/dist/desktop-sidebar-toggle-island/index.d.ts +2 -7
  102. package/dist/desktop-sidebar-toggle-island/index.js +2 -58
  103. package/dist/desktop-sidebar-toggle-island/island.d.ts +4 -0
  104. package/dist/desktop-sidebar-toggle-island/island.js +43 -0
  105. package/dist/desktop-sidebar-toggle-island/storage.d.ts +4 -0
  106. package/dist/desktop-sidebar-toggle-island/storage.js +29 -0
  107. package/dist/desktop-toc-toggle-island/index.d.ts +2 -7
  108. package/dist/desktop-toc-toggle-island/index.js +2 -58
  109. package/dist/desktop-toc-toggle-island/island.d.ts +4 -0
  110. package/dist/desktop-toc-toggle-island/island.js +43 -0
  111. package/dist/desktop-toc-toggle-island/storage.d.ts +4 -0
  112. package/dist/desktop-toc-toggle-island/storage.js +29 -0
  113. package/dist/details/details.d.ts +3 -4
  114. package/dist/details/details.js +1 -1
  115. package/dist/doc-body-end/index.d.ts +1 -2
  116. package/dist/doc-body-end/index.js +1 -1
  117. package/dist/doc-body-end-islands/design-token-panel-island.d.ts +2 -2
  118. package/dist/doc-body-end-islands/design-token-panel-island.js +3 -7
  119. package/dist/doc-body-end-islands/index.d.ts +4 -21
  120. package/dist/doc-body-end-islands/index.js +5 -3
  121. package/dist/doc-body-end-islands/theme-pack-switcher-island.d.ts +3 -13
  122. package/dist/doc-body-end-islands/theme-pack-switcher-island.js +11 -13
  123. package/dist/doc-content-header/index.d.ts +1 -2
  124. package/dist/doc-content-header/index.js +1 -1
  125. package/dist/doc-history/index.d.ts +1 -1
  126. package/dist/doc-history/index.js +166 -141
  127. package/dist/doc-history-area/index.d.ts +6 -4
  128. package/dist/doc-history-area/index.js +17 -16
  129. package/dist/doc-metainfo-area/index.d.ts +2 -3
  130. package/dist/doc-metainfo-area/index.js +1 -1
  131. package/dist/doc-page-renderer/index.d.ts +13 -7
  132. package/dist/doc-page-renderer/index.js +10 -1
  133. package/dist/doc-page-shell/index.d.ts +20 -7
  134. package/dist/doc-page-shell/index.js +17 -6
  135. package/dist/doc-pager/index.d.ts +1 -2
  136. package/dist/doc-pager/index.js +3 -3
  137. package/dist/doc-tags-area/index.d.ts +2 -3
  138. package/dist/doc-tags-area/index.js +1 -1
  139. package/dist/doclayout/doc-layout-with-defaults.d.ts +9 -9
  140. package/dist/doclayout/doc-layout-with-defaults.js +5 -15
  141. package/dist/doclayout/doc-layout.d.ts +26 -27
  142. package/dist/doclayout/doc-layout.js +23 -14
  143. package/dist/docs-schema/index.d.ts +4 -0
  144. package/dist/docs-schema/index.js +1 -0
  145. package/dist/extract-headings/index.js +43 -12
  146. package/dist/factory-context/index.d.ts +22 -19
  147. package/dist/features.css +70 -8
  148. package/dist/find-in-page/find-bar.d.ts +4 -2
  149. package/dist/find-in-page/find-bar.js +58 -69
  150. package/dist/find-in-page/index.d.ts +2 -8
  151. package/dist/find-in-page/index.js +33 -30
  152. package/dist/footer/footer.d.ts +3 -4
  153. package/dist/footer/footer.js +3 -3
  154. package/dist/footer-with-defaults/index.d.ts +2 -3
  155. package/dist/footer-with-defaults/index.js +1 -1
  156. package/dist/frontmatter-preview-defaults/index.js +1 -0
  157. package/dist/head/doc-head.d.ts +1 -1
  158. package/dist/head/doc-head.js +24 -32
  159. package/dist/head/og-tags.d.ts +1 -1
  160. package/dist/head/og-tags.js +8 -7
  161. package/dist/head/twitter-card.d.ts +1 -1
  162. package/dist/head/twitter-card.js +1 -1
  163. package/dist/head-with-defaults/index.d.ts +7 -2
  164. package/dist/head-with-defaults/index.js +46 -32
  165. package/dist/header/header.d.ts +8 -8
  166. package/dist/header/header.js +9 -11
  167. package/dist/header/types.d.ts +7 -7
  168. package/dist/header-with-defaults/index.d.ts +1 -2
  169. package/dist/header-with-defaults/index.js +18 -8
  170. package/dist/home-intro/index.d.ts +2 -5
  171. package/dist/home-intro/index.js +7 -5
  172. package/dist/home-intro/prepare.js +4 -3
  173. package/dist/home-page/index.d.ts +3 -3
  174. package/dist/home-page/index.js +19 -17
  175. package/dist/html-preview-wrapper/highlighted-code.d.ts +3 -4
  176. package/dist/html-preview-wrapper/highlighted-code.js +19 -17
  177. package/dist/html-preview-wrapper/html-preview-wrapper.d.ts +4 -25
  178. package/dist/html-preview-wrapper/html-preview-wrapper.js +2 -87
  179. package/dist/html-preview-wrapper/html-preview.d.ts +3 -10
  180. package/dist/html-preview-wrapper/html-preview.js +13 -37
  181. package/dist/html-preview-wrapper/index.d.ts +2 -1
  182. package/dist/html-preview-wrapper/index.js +1 -1
  183. package/dist/html-preview-wrapper/preview-base.d.ts +3 -5
  184. package/dist/html-preview-wrapper/preview-base.js +56 -59
  185. package/dist/html-preview-wrapper/wrapper.d.ts +20 -0
  186. package/dist/html-preview-wrapper/wrapper.js +37 -0
  187. package/dist/hydration-pending.d.ts +3 -5
  188. package/dist/hydration-pending.js +7 -5
  189. package/dist/i18n-version/language-switcher.d.ts +5 -32
  190. package/dist/i18n-version/language-switcher.js +5 -106
  191. package/dist/i18n-version/switcher-generated-scripts.d.ts +2 -0
  192. package/dist/i18n-version/switcher-generated-scripts.js +107 -0
  193. package/dist/i18n-version/switcher-url-state.d.ts +76 -0
  194. package/dist/i18n-version/switcher-url-state.js +103 -0
  195. package/dist/i18n-version/version-banner.d.ts +2 -3
  196. package/dist/i18n-version/version-banner.js +1 -1
  197. package/dist/i18n-version/version-switcher.d.ts +5 -50
  198. package/dist/i18n-version/version-switcher.js +5 -157
  199. package/dist/icons/index.d.ts +18 -19
  200. package/dist/icons/index.js +17 -33
  201. package/dist/image-enlarge/index.d.ts +1 -10
  202. package/dist/image-enlarge/index.js +80 -55
  203. package/dist/image-enlarge/public.d.ts +2 -0
  204. package/dist/image-enlarge/public.js +6 -0
  205. package/dist/image-enlarge/ssr-fallback.d.ts +2 -0
  206. package/dist/image-enlarge/ssr-fallback.js +8 -0
  207. package/dist/index.d.ts +11 -4
  208. package/dist/inline-version-switcher/index.d.ts +1 -2
  209. package/dist/inline-version-switcher/index.js +1 -1
  210. package/dist/island-types/index.d.ts +2 -2
  211. package/dist/island-types/index.js +1 -5
  212. package/dist/math-block/index.d.ts +4 -7
  213. package/dist/math-block/index.js +5 -5
  214. package/dist/mcp/handler.d.ts +8 -0
  215. package/dist/mcp/handler.js +129 -0
  216. package/dist/mcp/index.d.ts +4 -0
  217. package/dist/mcp/index.js +7 -0
  218. package/dist/mcp/loader.d.ts +19 -0
  219. package/dist/mcp/loader.js +202 -0
  220. package/dist/mdx-components/index.js +40 -108
  221. package/dist/mermaid-enlarge/index.d.ts +1 -8
  222. package/dist/mermaid-enlarge/index.js +174 -158
  223. package/dist/mermaid-enlarge/public.d.ts +2 -0
  224. package/dist/mermaid-enlarge/public.js +6 -0
  225. package/dist/mermaid-enlarge/ssr-fallback.d.ts +2 -0
  226. package/dist/mermaid-enlarge/ssr-fallback.js +8 -0
  227. package/dist/metainfo/doc-metainfo.d.ts +2 -3
  228. package/dist/metainfo/doc-metainfo.js +1 -4
  229. package/dist/metainfo/doc-tags.d.ts +2 -3
  230. package/dist/metainfo/doc-tags.js +1 -1
  231. package/dist/metainfo/frontmatter-preview.d.ts +3 -4
  232. package/dist/metainfo/frontmatter-preview.js +1 -1
  233. package/dist/nav-data-prep/index.js +6 -4
  234. package/dist/nav-indexing/category-nav.d.ts +2 -3
  235. package/dist/nav-indexing/category-nav.js +1 -2
  236. package/dist/nav-indexing/category-tree-nav.d.ts +2 -3
  237. package/dist/nav-indexing/category-tree-nav.js +1 -1
  238. package/dist/nav-indexing/doc-card-grid.d.ts +2 -3
  239. package/dist/nav-indexing/doc-card-grid.js +1 -2
  240. package/dist/nav-indexing/docs-sitemap.d.ts +2 -3
  241. package/dist/nav-indexing/docs-sitemap.js +2 -2
  242. package/dist/nav-indexing/index.d.ts +1 -1
  243. package/dist/nav-indexing/nav-card-grid.d.ts +2 -3
  244. package/dist/nav-indexing/nav-card-grid.js +1 -2
  245. package/dist/nav-indexing/note-tray-index-parts/card-list.d.ts +1 -2
  246. package/dist/nav-indexing/note-tray-index-parts/card-list.js +4 -4
  247. package/dist/nav-indexing/note-tray-index-parts/date-line.d.ts +2 -3
  248. package/dist/nav-indexing/note-tray-index-parts/date-line.js +1 -1
  249. package/dist/nav-indexing/note-tray-index-parts/index-list.d.ts +1 -2
  250. package/dist/nav-indexing/note-tray-index-parts/index-list.js +2 -2
  251. package/dist/nav-indexing/note-tray-index-parts/timeline.d.ts +1 -2
  252. package/dist/nav-indexing/note-tray-index-parts/timeline.js +2 -2
  253. package/dist/nav-indexing/note-tray-index.d.ts +1 -2
  254. package/dist/nav-indexing/note-tray-index.js +1 -1
  255. package/dist/nav-indexing/site-tree-nav-demo.d.ts +2 -3
  256. package/dist/nav-indexing/site-tree-nav-demo.js +2 -2
  257. package/dist/nav-indexing/tag-nav.d.ts +1 -2
  258. package/dist/nav-indexing/tag-nav.js +1 -1
  259. package/dist/nav-indexing/types.d.ts +2 -2
  260. package/dist/nav-indexing/versions-page-content.d.ts +2 -3
  261. package/dist/nav-indexing/versions-page-content.js +8 -8
  262. package/dist/note-tray-index/index.d.ts +1 -2
  263. package/dist/note-tray-index/index.js +1 -1
  264. package/dist/page-loading/page-loading-overlay.d.ts +1 -2
  265. package/dist/page-loading/page-loading-overlay.js +3 -5
  266. package/dist/plugins/agent-export.d.ts +3 -0
  267. package/dist/plugins/agent-export.js +34 -0
  268. package/dist/plugins/internal/agent-export/chunk.d.ts +5 -0
  269. package/dist/plugins/internal/agent-export/chunk.js +90 -0
  270. package/dist/plugins/internal/agent-export/index.d.ts +24 -0
  271. package/dist/plugins/internal/agent-export/index.js +123 -0
  272. package/dist/plugins/internal/agent-export/normalize.d.ts +5 -0
  273. package/dist/plugins/internal/agent-export/normalize.js +73 -0
  274. package/dist/plugins/internal/llms-txt/dev-middleware.d.ts +6 -0
  275. package/dist/plugins/internal/llms-txt/dev-middleware.js +8 -3
  276. package/dist/plugins/internal/llms-txt/emit.js +23 -6
  277. package/dist/plugins/internal/llms-txt/generate.d.ts +7 -1
  278. package/dist/plugins/internal/llms-txt/generate.js +9 -2
  279. package/dist/plugins/internal/llms-txt/load.d.ts +2 -0
  280. package/dist/plugins/internal/llms-txt/load.js +20 -4
  281. package/dist/plugins/internal/llms-txt/types.d.ts +10 -0
  282. package/dist/plugins/routes.js +4 -0
  283. package/dist/preset.d.ts +19 -9
  284. package/dist/preset.js +20 -1
  285. package/dist/route-context-payload/index.js +1 -1
  286. package/dist/routes/404.d.ts +2 -3
  287. package/dist/routes/404.js +1 -1
  288. package/dist/routes/_chrome.d.ts +5 -5
  289. package/dist/routes/_chrome.js +7 -2
  290. package/dist/routes/_context.d.ts +4 -4
  291. package/dist/routes/_design-token-panel-bootstrap.d.ts +1 -4
  292. package/dist/routes/_design-token-panel-bootstrap.js +9 -1
  293. package/dist/routes/docs-slug.d.ts +2 -3
  294. package/dist/routes/docs-tags-index.d.ts +2 -3
  295. package/dist/routes/docs-tags-index.js +1 -1
  296. package/dist/routes/docs-tags-tag.d.ts +2 -3
  297. package/dist/routes/docs-tags-tag.js +1 -1
  298. package/dist/routes/docs-versions.d.ts +2 -3
  299. package/dist/routes/docs-versions.js +1 -1
  300. package/dist/routes/files-path.d.ts +2 -3
  301. package/dist/routes/files-path.js +1 -1
  302. package/dist/routes/index.d.ts +2 -3
  303. package/dist/routes/index.js +1 -1
  304. package/dist/routes/locale-docs-slug.d.ts +2 -3
  305. package/dist/routes/locale-docs-tags-index.d.ts +2 -3
  306. package/dist/routes/locale-docs-tags-index.js +1 -1
  307. package/dist/routes/locale-docs-tags-tag.d.ts +2 -3
  308. package/dist/routes/locale-docs-tags-tag.js +1 -1
  309. package/dist/routes/locale-docs-versions.d.ts +2 -3
  310. package/dist/routes/locale-docs-versions.js +1 -1
  311. package/dist/routes/locale-files-path.d.ts +2 -3
  312. package/dist/routes/locale-files-path.js +1 -1
  313. package/dist/routes/locale-index.d.ts +2 -3
  314. package/dist/routes/locale-index.js +1 -1
  315. package/dist/routes/mcp.d.ts +5 -0
  316. package/dist/routes/mcp.js +25 -0
  317. package/dist/routes/v-docs-slug.d.ts +2 -3
  318. package/dist/routes/v-locale-docs-slug.d.ts +2 -3
  319. package/dist/search-widget/index.d.ts +1 -2
  320. package/dist/search-widget/index.js +4 -7
  321. package/dist/search-widget-script/generated-script.js +12 -5
  322. package/dist/settings-defaults.d.ts +2 -0
  323. package/dist/settings-defaults.js +93 -0
  324. package/dist/settings.d.ts +8 -2
  325. package/dist/sidebar/index.d.ts +1 -1
  326. package/dist/sidebar/sidebar.d.ts +12 -44
  327. package/dist/sidebar/sidebar.js +4 -3
  328. package/dist/sidebar/types.d.ts +14 -0
  329. package/dist/sidebar-prepaint/index.d.ts +1 -2
  330. package/dist/sidebar-prepaint/index.js +4 -6
  331. package/dist/sidebar-resizer/sidebar-resizer-init.d.ts +2 -3
  332. package/dist/sidebar-resizer/sidebar-resizer-init.js +3 -3
  333. package/dist/sidebar-toggle-island/index.d.ts +8 -11
  334. package/dist/sidebar-toggle-island/index.js +75 -62
  335. package/dist/sidebar-tree/build-tree.js +5 -6
  336. package/dist/sidebar-tree/types.d.ts +2 -0
  337. package/dist/sidebar-tree-island/index.d.ts +4 -19
  338. package/dist/sidebar-tree-island/index.js +782 -436
  339. package/dist/sidebar-tree-island/scope-state.d.ts +38 -0
  340. package/dist/sidebar-tree-island/scope-state.js +151 -0
  341. package/dist/sidebar-tree-island/sidebar-scroll-preserve.js +6 -2
  342. package/dist/sidebar-utils/index.d.ts +17 -19
  343. package/dist/sidebar-utils/index.js +100 -3
  344. package/dist/sidebar-utils/scope.d.ts +11 -0
  345. package/dist/sidebar-utils/scope.js +67 -0
  346. package/dist/sidebar-with-defaults/index.d.ts +1 -2
  347. package/dist/sidebar-with-defaults/index.js +19 -18
  348. package/dist/site-schema/nav-tree.js +15 -15
  349. package/dist/site-schema/types.d.ts +1 -0
  350. package/dist/site-tree-nav/index.d.ts +2 -3
  351. package/dist/site-tree-nav/index.js +11 -12
  352. package/dist/site-tree-nav/normalize-island-props.d.ts +16 -0
  353. package/dist/site-tree-nav/normalize-island-props.js +122 -0
  354. package/dist/site-tree-nav-island/index.d.ts +3 -3
  355. package/dist/site-tree-nav-island/index.js +243 -144
  356. package/dist/smart-break/index.d.ts +3 -4
  357. package/dist/smart-break/index.js +1 -1
  358. package/dist/tab-item/tab-item.d.ts +3 -4
  359. package/dist/tab-item/tab-item.js +1 -1
  360. package/dist/tag-pages/index.d.ts +3 -3
  361. package/dist/tag-pages/index.js +10 -10
  362. package/dist/theme/color-scheme-provider.d.ts +3 -3
  363. package/dist/theme/color-scheme-provider.js +3 -3
  364. package/dist/theme/theme-pack-provider.d.ts +1 -1
  365. package/dist/theme/theme-pack-provider.js +3 -3
  366. package/dist/theme/theme-toggle.d.ts +2 -3
  367. package/dist/theme/theme-toggle.js +1 -1
  368. package/dist/theme-pack-dialog/index.d.ts +1 -1
  369. package/dist/theme-pack-dialog/index.js +69 -75
  370. package/dist/theme-pack-dialog/theme-pack-card.d.ts +3 -4
  371. package/dist/theme-pack-dialog/theme-pack-card.js +19 -17
  372. package/dist/theme-pack-switcher/index.d.ts +4 -5
  373. package/dist/theme-pack-switcher/index.js +52 -49
  374. package/dist/theme-toggle/index.d.ts +1 -1
  375. package/dist/theme-toggle/index.js +154 -167
  376. package/dist/theme.css +47 -121
  377. package/dist/toc/mobile-toc.d.ts +3 -5
  378. package/dist/toc/mobile-toc.js +29 -27
  379. package/dist/toc/toc.d.ts +3 -4
  380. package/dist/toc/toc.js +18 -18
  381. package/dist/toc/use-active-heading.d.ts +5 -4
  382. package/dist/toc/use-active-heading.js +36 -30
  383. package/dist/toc-prepaint/index.d.ts +1 -2
  384. package/dist/toc-prepaint/index.js +4 -6
  385. package/dist/transitions/nested-island-props-refresh.d.ts +3 -16
  386. package/dist/transitions/nested-island-props-refresh.js +133 -151
  387. package/dist/transitions/page-events.d.ts +8 -13
  388. package/dist/tree-nav-shared/index.d.ts +4 -5
  389. package/dist/tree-nav-shared/index.js +6 -7
  390. package/dist/use-modal-dialog/index.d.ts +9 -63
  391. package/dist/use-modal-dialog/index.js +41 -59
  392. package/dist/versions-page/index.d.ts +3 -3
  393. package/dist/versions-page/index.js +5 -5
  394. package/dist/wind/index.d.ts +5 -0
  395. package/dist/wind/index.js +169 -0
  396. package/dist/wind.json +498 -0
  397. package/dist/z-index-defaults/index.d.ts +4 -4
  398. package/dist/zdtp-loader.d.ts +7 -0
  399. package/dist/zdtp-loader.js +8 -0
  400. package/eject/asset-components/asset-card.tsx +14 -16
  401. package/eject/asset-components/asset-code.tsx +10 -12
  402. package/eject/asset-components/shared.tsx +5 -7
  403. package/eject/breadcrumb/breadcrumb.tsx +15 -16
  404. package/eject/code-group/index.tsx +4 -10
  405. package/eject/content-admonition/index.tsx +5 -6
  406. package/eject/desktop-sidebar-toggle-island/index.ts +4 -0
  407. package/eject/desktop-sidebar-toggle-island/island.tsx +50 -0
  408. package/eject/desktop-sidebar-toggle-island/storage.ts +27 -0
  409. package/eject/details/details.tsx +3 -5
  410. package/eject/doc-history/index.tsx +193 -179
  411. package/eject/doc-pager/index.tsx +3 -4
  412. package/eject/footer/footer.tsx +7 -9
  413. package/eject/header/header.tsx +42 -54
  414. package/eject/header/nav-overflow-script.ts +1 -1
  415. package/eject/header/types.ts +12 -13
  416. package/eject/image-enlarge/index.tsx +84 -69
  417. package/eject/image-enlarge/public.ts +2 -0
  418. package/eject/image-enlarge/ssr-fallback.tsx +7 -0
  419. package/eject/page-loading/page-loading-overlay.tsx +8 -15
  420. package/eject/sidebar/index.ts +1 -0
  421. package/eject/sidebar/sidebar.tsx +16 -97
  422. package/eject/sidebar/types.ts +15 -0
  423. package/eject/sidebar-toggle-island/index.tsx +103 -102
  424. package/eject/sidebar-tree-island/index.tsx +827 -615
  425. package/eject/sidebar-tree-island/scope-state.ts +154 -0
  426. package/eject/sidebar-tree-island/sidebar-scroll-preserve.ts +8 -2
  427. package/eject/site-tree-nav-island/index.tsx +349 -222
  428. package/eject/tab-item/tab-item.tsx +2 -4
  429. package/eject/theme-toggle/hydration-pending.ts +6 -10
  430. package/eject/theme-toggle/index.tsx +133 -173
  431. package/eject/toc/mobile-toc.tsx +27 -31
  432. package/eject/toc/toc.tsx +21 -24
  433. package/eject/toc/use-active-heading.ts +43 -38
  434. package/package.json +40 -22
  435. package/routes-src/404.tsx +2 -3
  436. package/routes-src/_chrome.tsx +7 -2
  437. package/routes-src/_design-token-panel-bootstrap.tsx +1 -63
  438. package/routes-src/docs-slug.tsx +2 -3
  439. package/routes-src/docs-tags-index.tsx +2 -3
  440. package/routes-src/docs-tags-tag.tsx +2 -3
  441. package/routes-src/docs-versions.tsx +2 -3
  442. package/routes-src/files-path.tsx +2 -4
  443. package/routes-src/index.tsx +2 -3
  444. package/routes-src/locale-docs-slug.tsx +2 -3
  445. package/routes-src/locale-docs-tags-index.tsx +2 -3
  446. package/routes-src/locale-docs-tags-tag.tsx +2 -3
  447. package/routes-src/locale-docs-versions.tsx +2 -3
  448. package/routes-src/locale-files-path.tsx +2 -4
  449. package/routes-src/locale-index.tsx +2 -3
  450. package/routes-src/mcp.tsx +25 -0
  451. package/routes-src/v-docs-slug.tsx +2 -3
  452. package/routes-src/v-locale-docs-slug.tsx +2 -3
  453. package/tsconfig.base.json +1 -1
  454. package/dist/safelist.css +0 -2
  455. package/dist/theme-no-reset.css +0 -379
  456. package/eject/desktop-sidebar-toggle-island/index.tsx +0 -110
@@ -1,8 +1,8 @@
1
1
  "use client";
2
- import { jsx, jsxs } from "preact/jsx-runtime";
3
- import { useEffect, useRef, useState } from "preact/hooks";
2
+ import { jsx, jsxs } from "@takazudo/zfb/zudo-react/jsx-runtime";
3
+ import { computed, getScope, signal, Show } from "@takazudo/zfb/zudo-react";
4
4
  import { ChevronLeft, ChevronRight, Close } from "../icons/index.js";
5
- import { useHydrationPending } from "../hydration-pending.js";
5
+ import { hydrationPending } from "../hydration-pending.js";
6
6
  import { ThemePackDialog } from "../theme-pack-dialog/index.js";
7
7
  import { applyThemePack } from "./theme-pack-sync.js";
8
8
  import {
@@ -17,7 +17,6 @@ function GridIcon({ className }) {
17
17
  return /* @__PURE__ */ jsxs(
18
18
  "svg",
19
19
  {
20
- xmlns: "http://www.w3.org/2000/svg",
21
20
  class: className || void 0,
22
21
  fill: "none",
23
22
  viewBox: "0 0 24 24",
@@ -37,7 +36,6 @@ function PaletteIcon({ className }) {
37
36
  return /* @__PURE__ */ jsxs(
38
37
  "svg",
39
38
  {
40
- xmlns: "http://www.w3.org/2000/svg",
41
39
  class: className || void 0,
42
40
  fill: "none",
43
41
  viewBox: "0 0 24 24",
@@ -60,43 +58,46 @@ function PaletteIcon({ className }) {
60
58
  }
61
59
  );
62
60
  }
63
- const CONTROL_BUTTON_CLASS = "flex items-center gap-hsp-xs rounded border border-muted bg-bg px-hsp-md py-hsp-2xs text-caption text-fg transition-colors hover:border-accent focus-visible:outline-2 focus-visible:outline-accent focus-visible:outline-offset-2 disabled:opacity-50 disabled:pointer-events-none";
64
- const ICON_BUTTON_CLASS = "flex items-center justify-center rounded p-hsp-2xs text-muted transition-colors hover:text-fg focus-visible:outline-2 focus-visible:outline-accent focus-visible:outline-offset-2 disabled:opacity-50 disabled:pointer-events-none";
61
+ const CONTROL_BUTTON_CLASS = "flex items-center gap-hsp-xs rounded border border-muted bg-bg px-hsp-md py-hsp-2xs text-caption text-fg transition-colors duration-0 hover:border-accent focus-visible:outline-2 focus-visible:outline-accent focus-visible:outline-offset-2 disabled:opacity-50 disabled:pointer-events-none";
62
+ const ICON_BUTTON_CLASS = "flex items-center justify-center rounded p-hsp-2xs text-muted transition-colors duration-0 hover:text-fg focus-visible:outline-2 focus-visible:outline-accent focus-visible:outline-offset-2 disabled:opacity-50 disabled:pointer-events-none";
65
63
  function ThemePackSwitcher({
66
64
  active,
67
65
  order,
68
66
  base,
69
67
  pendingUntilHydrated = true
70
68
  }) {
71
- const pending = useHydrationPending(pendingUntilHydrated);
72
- const [open, setOpen] = useState(false);
73
- const [dialogOpen, setDialogOpen] = useState(false);
74
- const [activeSlug, setActiveSlug] = useState(active);
75
- const launcherRef = useRef(null);
76
- const cardRef = useRef(null);
77
- useEffect(() => connectActivePackSync(setActiveSlug), []);
78
- useEffect(() => {
79
- if (!open || dialogOpen) return void 0;
69
+ const scope = getScope();
70
+ const pending = hydrationPending(scope, pendingUntilHydrated);
71
+ const open = signal(false);
72
+ const dialogOpen = signal(false);
73
+ const activeSlug = signal(active);
74
+ const launcherRef = { current: null };
75
+ const cardRef = { current: null };
76
+ scope.onActivate(() => connectActivePackSync((slug) => {
77
+ activeSlug.value = slug;
78
+ }));
79
+ scope.effect(() => {
80
+ if (!open.value || dialogOpen.value) return;
80
81
  return connectEscapeToClose(() => {
81
- setOpen(false);
82
+ open.value = false;
82
83
  launcherRef.current?.focus();
83
84
  });
84
- }, [open, dialogOpen]);
85
- useEffect(() => {
86
- if (open) cardRef.current?.focus();
87
- }, [open]);
88
- const entry = resolveActiveEntry(order, activeSlug);
85
+ });
86
+ scope.effect(() => {
87
+ if (open.value) cardRef.current?.focus();
88
+ });
89
+ const entry = computed(() => resolveActiveEntry(order, activeSlug.value));
89
90
  function cycle(step) {
90
- const target = step === 1 ? nextPackSlug(order, activeSlug) : prevPackSlug(order, activeSlug);
91
- if (target !== null && target !== activeSlug) void applyThemePack(target);
91
+ const target = step === 1 ? nextPackSlug(order, activeSlug.value) : prevPackSlug(order, activeSlug.value);
92
+ if (target !== null && target !== activeSlug.value) void applyThemePack(target);
92
93
  }
93
94
  function closeCard() {
94
- setOpen(false);
95
+ open.value = false;
95
96
  launcherRef.current?.focus();
96
97
  }
97
98
  function openDialog() {
98
- setOpen(false);
99
- setDialogOpen(true);
99
+ open.value = false;
100
+ dialogOpen.value = true;
100
101
  }
101
102
  return /* @__PURE__ */ jsxs(
102
103
  "div",
@@ -104,18 +105,18 @@ function ThemePackSwitcher({
104
105
  class: "fixed right-hsp-lg bottom-hsp-lg z-popover flex flex-col items-end gap-vsp-2xs",
105
106
  "data-theme-pack-switcher": true,
106
107
  children: [
107
- open ? /* @__PURE__ */ jsxs(
108
+ /* @__PURE__ */ jsx(Show, { when: open, children: () => /* @__PURE__ */ jsxs(
108
109
  "div",
109
110
  {
110
111
  ref: cardRef,
111
- tabIndex: -1,
112
+ tabindex: -1,
112
113
  role: "dialog",
113
114
  "aria-label": "Theme pack switcher",
114
115
  "data-switcher-card": true,
115
- class: "flex w-[360px] max-w-[calc(100vw-2rem)] flex-col gap-vsp-2xs rounded-lg border border-muted bg-surface p-hsp-lg shadow-lg focus-visible:outline-2 focus-visible:outline-accent",
116
+ class: "flex w-[360px] max-w-[calc(100vw_-_2rem)] flex-col gap-vsp-2xs rounded-lg border border-muted bg-surface p-hsp-lg shadow-lg focus-visible:outline-2 focus-visible:outline-accent",
116
117
  children: [
117
118
  /* @__PURE__ */ jsxs("div", { class: "flex items-start justify-between gap-hsp-sm", children: [
118
- /* @__PURE__ */ jsx("p", { class: "min-w-0 break-words text-body font-bold text-fg", "aria-live": "polite", children: entry?.name ?? activeSlug }),
119
+ /* @__PURE__ */ jsx("p", { class: "min-w-0 break-words text-body font-bold text-fg", "aria-live": "polite", children: computed(() => entry.value?.name ?? activeSlug.value) }),
119
120
  /* @__PURE__ */ jsxs("div", { class: "flex shrink-0 items-center gap-hsp-2xs", children: [
120
121
  /* @__PURE__ */ jsx(
121
122
  "button",
@@ -124,7 +125,7 @@ function ThemePackSwitcher({
124
125
  "aria-label": "Browse all theme packs",
125
126
  title: "Browse all theme packs",
126
127
  disabled: ThemePackDialogSlot === null,
127
- onClick: openDialog,
128
+ "on:click": openDialog,
128
129
  class: ICON_BUTTON_CLASS,
129
130
  children: /* @__PURE__ */ jsx(GridIcon, { className: "h-icon-sm w-icon-sm" })
130
131
  }
@@ -135,15 +136,15 @@ function ThemePackSwitcher({
135
136
  type: "button",
136
137
  "aria-label": "Close theme pack switcher",
137
138
  title: "Close",
138
- onClick: closeCard,
139
+ "on:click": closeCard,
139
140
  class: ICON_BUTTON_CLASS,
140
- children: /* @__PURE__ */ jsx(Close, { className: "h-icon-sm w-icon-sm" })
141
+ children: /* @__PURE__ */ jsx(Close, { class: "h-icon-sm w-icon-sm" })
141
142
  }
142
143
  )
143
144
  ] })
144
145
  ] }),
145
- entry !== null && /* @__PURE__ */ jsx("span", { class: "self-start rounded-full border border-muted px-hsp-sm text-micro tracking-wide text-muted uppercase", children: entry.mode === "dark" ? "Dark" : "Light" }),
146
- entry !== null && entry.description !== "" && /* @__PURE__ */ jsx("p", { class: "break-words text-caption text-muted", children: entry.description }),
146
+ /* @__PURE__ */ jsx(Show, { when: computed(() => entry.value !== null), children: () => /* @__PURE__ */ jsx("span", { class: "self-start rounded-full border border-muted px-hsp-sm text-micro tracking-wide text-muted uppercase", children: computed(() => entry.value?.mode === "dark" ? "Dark" : "Light") }) }),
147
+ /* @__PURE__ */ jsx(Show, { when: computed(() => entry.value !== null && entry.value.description !== ""), children: () => /* @__PURE__ */ jsx("p", { class: "break-words text-caption text-muted", children: computed(() => entry.value?.description) }) }),
147
148
  /* @__PURE__ */ jsxs("div", { class: "flex items-center justify-between gap-hsp-sm", children: [
148
149
  /* @__PURE__ */ jsxs(
149
150
  "button",
@@ -151,10 +152,10 @@ function ThemePackSwitcher({
151
152
  type: "button",
152
153
  "aria-label": "Previous theme pack",
153
154
  disabled: order.length < 2,
154
- onClick: () => cycle(-1),
155
+ "on:click": () => cycle(-1),
155
156
  class: CONTROL_BUTTON_CLASS,
156
157
  children: [
157
- /* @__PURE__ */ jsx(ChevronLeft, { className: "h-icon-xs w-icon-xs" }),
158
+ /* @__PURE__ */ jsx(ChevronLeft, { class: "h-icon-xs w-icon-xs" }),
158
159
  "Prev"
159
160
  ]
160
161
  }
@@ -165,18 +166,18 @@ function ThemePackSwitcher({
165
166
  type: "button",
166
167
  "aria-label": "Next theme pack",
167
168
  disabled: order.length < 2,
168
- onClick: () => cycle(1),
169
+ "on:click": () => cycle(1),
169
170
  class: CONTROL_BUTTON_CLASS,
170
171
  children: [
171
172
  "Next",
172
- /* @__PURE__ */ jsx(ChevronRight, { className: "h-icon-xs w-icon-xs" })
173
+ /* @__PURE__ */ jsx(ChevronRight, { class: "h-icon-xs w-icon-xs" })
173
174
  ]
174
175
  }
175
176
  )
176
177
  ] })
177
178
  ]
178
179
  }
179
- ) : null,
180
+ ) }),
180
181
  /* @__PURE__ */ jsx(
181
182
  "button",
182
183
  {
@@ -185,15 +186,15 @@ function ThemePackSwitcher({
185
186
  "aria-haspopup": "dialog",
186
187
  "aria-expanded": open,
187
188
  "aria-label": "Theme pack switcher",
188
- "aria-disabled": pending ? "true" : void 0,
189
+ "aria-disabled": computed(() => pending.value ? "true" : void 0),
189
190
  title: "Theme packs",
190
191
  "data-switcher-launcher": true,
191
- "data-zd-pending": pending ? "" : void 0,
192
- onClick: () => {
193
- if (pending) return;
194
- setOpen(!open);
192
+ "data-zd-pending": computed(() => pending.value ? "" : void 0),
193
+ "on:click": () => {
194
+ if (pending.value) return;
195
+ open.value = !open.value;
195
196
  },
196
- class: "flex h-[2.5rem] w-[2.5rem] items-center justify-center rounded-full border border-muted bg-surface text-fg shadow-lg transition-colors hover:text-accent focus-visible:outline-2 focus-visible:outline-accent focus-visible:outline-offset-2",
197
+ class: "flex h-[2.5rem] w-[2.5rem] items-center justify-center rounded-full border border-muted bg-surface text-fg shadow-lg transition-colors duration-0 hover:text-accent focus-visible:outline-2 focus-visible:outline-accent focus-visible:outline-offset-2",
197
198
  children: /* @__PURE__ */ jsx(PaletteIcon, { className: "h-icon-md w-icon-md" })
198
199
  }
199
200
  ),
@@ -201,9 +202,11 @@ function ThemePackSwitcher({
201
202
  ThemePackDialogSlot,
202
203
  {
203
204
  open: dialogOpen,
204
- onClose: () => setDialogOpen(false),
205
+ onClose: () => {
206
+ dialogOpen.value = false;
207
+ },
205
208
  order,
206
- active: activeSlug,
209
+ active: activeSlug.value,
207
210
  base
208
211
  }
209
212
  ) : null
@@ -13,7 +13,7 @@ export interface ThemeToggleProps {
13
13
  /** Keep activation pending until the first successful mount. @default true */
14
14
  pendingUntilHydrated?: boolean;
15
15
  }
16
- export declare function ThemeToggle({ defaultMode, respectPrefersColorScheme, labels, pendingUntilHydrated, }: ThemeToggleProps): import("preact").JSX.Element;
16
+ export declare function ThemeToggle({ defaultMode, respectPrefersColorScheme, labels, pendingUntilHydrated }: ThemeToggleProps): import("@takazudo/zfb").Description;
17
17
  export declare namespace ThemeToggle {
18
18
  var displayName: string;
19
19
  }
@@ -1,8 +1,7 @@
1
1
  "use client";
2
- import { Fragment, jsx, jsxs } from "preact/jsx-runtime";
3
- import { useState, useEffect, useRef } from "preact/hooks";
4
- import { createPortal } from "preact/compat";
5
- import { useHydrationPending } from "../hydration-pending.js";
2
+ import { Fragment, jsx, jsxs } from "@takazudo/zfb/zudo-react/jsx-runtime";
3
+ import { computed, getScope, Show, signal } from "@takazudo/zfb/zudo-react";
4
+ import { hydrationPending } from "../hydration-pending.js";
6
5
  import { AFTER_NAVIGATE_EVENT } from "../transitions/index.js";
7
6
  import {
8
7
  applyThemePreference,
@@ -14,23 +13,26 @@ import {
14
13
  const preferences = ["light", "dark", "system"];
15
14
  let menuSequence = 0;
16
15
  function PreferenceIcon({ preference }) {
17
- return /* @__PURE__ */ jsx(
16
+ return /* @__PURE__ */ jsxs(
18
17
  "svg",
19
18
  {
20
19
  "aria-hidden": "true",
21
- xmlns: "http://www.w3.org/2000/svg",
22
20
  width: "20",
23
21
  height: "20",
24
22
  viewBox: "0 0 24 24",
25
23
  fill: "none",
26
24
  stroke: "currentColor",
27
- strokeWidth: "1.2",
28
- strokeLinecap: "square",
29
- strokeLinejoin: "miter",
30
- children: preference === "light" ? /* @__PURE__ */ jsxs(Fragment, { children: [
31
- /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "3.6" }),
32
- /* @__PURE__ */ jsx("path", { d: "M12 2.5V6M12 18V21.5M2.5 12H6M18 12H21.5M5.3 5.3L7.8 7.8M16.2 16.2L18.7 18.7M5.3 18.7L7.8 16.2M16.2 7.8L18.7 5.3" })
33
- ] }) : preference === "dark" ? /* @__PURE__ */ jsx("path", { d: "M10.2 2.9C5.7 3.9 2.6 7.9 3 12.6C3.4 17.7 7.9 21.5 13 21.1C16.9 20.7 20.1 17.9 21 14.1C18.6 15.7 15.6 15.8 13.2 14.3C9.3 12 8 6.8 10.2 2.9Z" }) : /* @__PURE__ */ jsx("path", { d: "M2.5 3.5H21.5V16.5H2.5ZM12 16.5V20.5M7.5 20.5H16.5" })
25
+ "stroke-width": "1.2",
26
+ "stroke-linecap": "square",
27
+ "stroke-linejoin": "miter",
28
+ children: [
29
+ /* @__PURE__ */ jsx(Show, { when: computed(() => preference === "light"), children: () => /* @__PURE__ */ jsxs(Fragment, { children: [
30
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "3.6" }),
31
+ /* @__PURE__ */ jsx("path", { d: "M12 2.5V6M12 18V21.5M2.5 12H6M18 12H21.5M5.3 5.3L7.8 7.8M16.2 16.2L18.7 18.7M5.3 18.7L7.8 16.2M16.2 7.8L18.7 5.3" })
32
+ ] }) }),
33
+ /* @__PURE__ */ jsx(Show, { when: computed(() => preference === "dark"), children: () => /* @__PURE__ */ jsx("path", { d: "M10.2 2.9C5.7 3.9 2.6 7.9 3 12.6C3.4 17.7 7.9 21.5 13 21.1C16.9 20.7 20.1 17.9 21 14.1C18.6 15.7 15.6 15.8 13.2 14.3C9.3 12 8 6.8 10.2 2.9Z" }) }),
34
+ /* @__PURE__ */ jsx(Show, { when: computed(() => preference === "system"), children: () => /* @__PURE__ */ jsx("path", { d: "M2.5 3.5H21.5V16.5H2.5ZM12 16.5V20.5M7.5 20.5H16.5" }) })
35
+ ]
34
36
  }
35
37
  );
36
38
  }
@@ -41,207 +43,192 @@ const englishLabels = {
41
43
  system: "System",
42
44
  systemHelper: "Follows device \xB7 currently {mode}"
43
45
  };
44
- function ThemeToggle({
45
- defaultMode = "dark",
46
- respectPrefersColorScheme = true,
47
- labels = englishLabels,
48
- pendingUntilHydrated = true
49
- }) {
50
- const pending = useHydrationPending(pendingUntilHydrated);
51
- const menuId = useRef("");
52
- const ensureMenuId = () => {
53
- if (!menuId.current) menuId.current = `zd-appearance-${++menuSequence}`;
54
- };
55
- const rootRef = useRef(null);
56
- const menuRef = useRef(null);
57
- const triggerRef = useRef(null);
58
- const itemRefs = useRef([]);
59
- const restoreFocusRef = useRef(false);
60
- const [preference, setPreference] = useState(
61
- respectPrefersColorScheme ? "system" : defaultMode
62
- );
63
- const [resolved, setResolved] = useState(defaultMode);
64
- const [open, setOpen] = useState(false);
65
- const [activeIndex, setActiveIndex] = useState(0);
66
- const [placement, setPlacement] = useState(null);
67
- useEffect(() => {
68
- const sync = () => {
69
- setPreference(readThemePreference(defaultMode, respectPrefersColorScheme));
70
- setResolved(readColorSchemeFromDom(defaultMode));
71
- };
72
- sync();
73
- const unsubscribePreference = subscribeThemePreferenceChanged(() => {
74
- sync();
75
- setOpen(false);
76
- });
77
- const unsubscribeScheme = subscribeColorSchemeChanged(sync);
78
- return () => {
79
- unsubscribePreference();
80
- unsubscribeScheme();
81
- };
82
- }, [defaultMode, respectPrefersColorScheme]);
83
- useEffect(() => {
84
- if (!open) return;
46
+ function AppearanceMenu({ id, labels, preference, resolved, activeIndex, triggerRef, rootRef, close, select, move }) {
47
+ const scope = getScope();
48
+ const menuRef = { current: null };
49
+ const itemRefs = preferences.map(() => ({ current: null }));
50
+ const placement = signal({ visibility: "hidden", left: "0px", top: "0px", right: "auto", bottom: "auto", margin: "0", width: "260px", "max-height": "none" });
51
+ scope.onActivate(() => {
85
52
  const menu = menuRef.current;
86
- menu?.showPopover?.();
53
+ if (!menu) return;
54
+ menu.showPopover?.();
87
55
  const position = () => {
88
56
  const rect = triggerRef.current?.getBoundingClientRect();
89
57
  if (!rect) return;
90
58
  const gap = 8;
91
- const width = Math.min(260, window.innerWidth - gap * 2);
92
- const desiredHeight = menu?.scrollHeight ?? 280;
59
+ const width = Math.max(0, Math.min(260, window.innerWidth - gap * 2));
60
+ const desiredHeight = menu.scrollHeight || 280;
93
61
  const roomBelow = window.innerHeight - rect.bottom - gap * 2;
94
62
  const roomAbove = rect.top - gap * 2;
95
63
  const above = roomBelow < desiredHeight && roomAbove > roomBelow;
96
64
  const maxHeight = Math.max(80, Math.min(desiredHeight, above ? roomAbove : roomBelow));
97
- setPlacement({
98
- left: Math.max(gap, Math.min(rect.right - width, window.innerWidth - width - gap)),
99
- top: above ? Math.max(gap, rect.top - gap - maxHeight) : rect.bottom + gap,
100
- width,
101
- maxHeight
102
- });
65
+ const left = Math.max(gap, Math.min(rect.right - width, window.innerWidth - width - gap));
66
+ const top = above ? Math.max(gap, rect.top - gap - maxHeight) : rect.bottom + gap;
67
+ placement.value = { visibility: "visible", left: `${left}px`, top: `${top}px`, right: "auto", bottom: "auto", margin: "0", width: `${width}px`, "max-height": `${maxHeight}px` };
103
68
  };
104
69
  const onPointerDown = (event) => {
105
- if (!rootRef.current?.contains(event.target) && !menuRef.current?.contains(event.target)) setOpen(false);
70
+ if (!rootRef.current?.contains(event.target) && !menu.contains(event.target)) close();
106
71
  };
107
- const onNavigate = () => setOpen(false);
72
+ const onNavigate = () => close();
108
73
  position();
74
+ const focusFrame = requestAnimationFrame(() => {
75
+ if (!scope.abortSignal.aborted) itemRefs[activeIndex.value]?.current?.focus();
76
+ });
109
77
  document.addEventListener("pointerdown", onPointerDown);
110
78
  window.addEventListener("resize", position);
111
79
  window.addEventListener("scroll", position, true);
112
80
  document.addEventListener(AFTER_NAVIGATE_EVENT, onNavigate);
113
81
  return () => {
114
- if (menu?.hidePopover && menu.matches(":popover-open")) menu.hidePopover();
82
+ cancelAnimationFrame(focusFrame);
83
+ if (menu.hidePopover && menu.matches(":popover-open")) menu.hidePopover();
115
84
  document.removeEventListener("pointerdown", onPointerDown);
116
85
  window.removeEventListener("resize", position);
117
86
  window.removeEventListener("scroll", position, true);
118
87
  document.removeEventListener(AFTER_NAVIGATE_EVENT, onNavigate);
119
88
  };
120
- }, [open]);
121
- useEffect(() => {
122
- if (open && placement) itemRefs.current[activeIndex]?.focus();
123
- }, [open, placement]);
124
- useEffect(() => {
125
- if (open || !restoreFocusRef.current) return;
126
- restoreFocusRef.current = false;
127
- requestAnimationFrame(() => triggerRef.current?.focus());
128
- }, [open]);
89
+ });
90
+ const onMenuKeyDown = (event) => {
91
+ const keyboard = event;
92
+ if (keyboard.isComposing) return;
93
+ if (keyboard.key === "Escape") {
94
+ keyboard.preventDefault();
95
+ keyboard.stopPropagation();
96
+ close(true);
97
+ } else if (keyboard.key === "Tab") {
98
+ window.setTimeout(() => close(), 0);
99
+ } else if (keyboard.key === "ArrowDown" || keyboard.key === "ArrowUp" || keyboard.key === "Home" || keyboard.key === "End") {
100
+ keyboard.preventDefault();
101
+ const next = keyboard.key === "Home" ? 0 : keyboard.key === "End" ? 2 : activeIndex.value + (keyboard.key === "ArrowDown" ? 1 : -1);
102
+ move(next);
103
+ itemRefs[(next + preferences.length) % preferences.length]?.current?.focus();
104
+ }
105
+ };
106
+ return /* @__PURE__ */ jsxs(
107
+ "div",
108
+ {
109
+ ref: menuRef,
110
+ id,
111
+ role: "menu",
112
+ "aria-label": labels.appearance,
113
+ "on:keydown": onMenuKeyDown,
114
+ class: "fixed z-tooltip overflow-y-auto rounded-lg border border-muted bg-surface p-hsp-xs text-fg shadow-lg",
115
+ style: placement,
116
+ popover: "manual",
117
+ children: [
118
+ /* @__PURE__ */ jsx("div", { class: "px-hsp-sm py-vsp-xs text-small font-semibold", "aria-hidden": "true", children: labels.appearance }),
119
+ preferences.map((option, index) => /* @__PURE__ */ jsxs(
120
+ "button",
121
+ {
122
+ ref: itemRefs[index],
123
+ type: "button",
124
+ role: "menuitemradio",
125
+ "aria-checked": computed(() => preference.value === option),
126
+ "on:focus": () => move(index),
127
+ "on:click": () => select(option),
128
+ class: computed(() => `flex min-h-[44px] w-full items-center gap-hsp-sm rounded px-hsp-sm text-left text-small ${preference.value === option ? "bg-accent/10" : ""} hover:bg-accent/10 focus-visible:bg-accent/10 focus-visible:outline-2 focus-visible:outline-accent`),
129
+ children: [
130
+ /* @__PURE__ */ jsx(PreferenceIcon, { preference: option }),
131
+ /* @__PURE__ */ jsx("span", { class: "flex-1", children: labels[option] }),
132
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", class: "text-accent", children: computed(() => preference.value === option ? "\u2713" : "") })
133
+ ]
134
+ }
135
+ )),
136
+ /* @__PURE__ */ jsx("div", { class: "px-hsp-sm py-vsp-xs text-small text-muted", children: computed(() => labels.systemHelper.replace("{mode}", labels[resolved.value])) })
137
+ ]
138
+ }
139
+ );
140
+ }
141
+ function ThemeToggle({ defaultMode = "dark", respectPrefersColorScheme = true, labels = englishLabels, pendingUntilHydrated = true }) {
142
+ const scope = getScope();
143
+ const pending = hydrationPending(scope, pendingUntilHydrated);
144
+ const rootRef = { current: null };
145
+ const triggerRef = { current: null };
146
+ const preference = signal(respectPrefersColorScheme ? "system" : defaultMode);
147
+ const resolved = signal(defaultMode);
148
+ const open = signal(false);
149
+ const activeIndex = signal(0);
150
+ let menuId = "";
151
+ const ensureMenuId = () => {
152
+ if (!menuId) menuId = `zd-appearance-${++menuSequence}`;
153
+ };
154
+ scope.onActivate(() => {
155
+ const sync = () => {
156
+ preference.value = readThemePreference(defaultMode, respectPrefersColorScheme);
157
+ resolved.value = readColorSchemeFromDom(defaultMode);
158
+ };
159
+ sync();
160
+ const unsubscribePreference = subscribeThemePreferenceChanged(() => {
161
+ sync();
162
+ open.value = false;
163
+ });
164
+ const unsubscribeScheme = subscribeColorSchemeChanged(sync);
165
+ return () => {
166
+ unsubscribePreference();
167
+ unsubscribeScheme();
168
+ };
169
+ });
129
170
  const close = (restoreFocus = false) => {
130
- restoreFocusRef.current = restoreFocus;
131
- setOpen(false);
171
+ open.value = false;
172
+ if (restoreFocus) requestAnimationFrame(() => {
173
+ if (!scope.abortSignal.aborted && !open.value) triggerRef.current?.focus();
174
+ });
132
175
  };
133
176
  const select = (next) => {
134
177
  close(true);
135
178
  applyThemePreference(next);
136
- setPreference(next);
137
- setResolved(readColorSchemeFromDom(defaultMode));
179
+ preference.value = next;
180
+ resolved.value = readColorSchemeFromDom(defaultMode);
138
181
  };
139
182
  const move = (index) => {
140
- const next = (index + preferences.length) % preferences.length;
141
- setActiveIndex(next);
142
- itemRefs.current[next]?.focus();
183
+ activeIndex.value = (index + preferences.length) % preferences.length;
143
184
  };
144
- const onMenuKeyDown = (event) => {
145
- if (event.key === "Escape") {
146
- event.preventDefault();
147
- event.stopPropagation();
148
- close(true);
149
- } else if (event.key === "Tab") {
150
- window.setTimeout(() => close(), 0);
151
- } else if (event.key === "ArrowDown") {
152
- event.preventDefault();
153
- move(activeIndex + 1);
154
- } else if (event.key === "ArrowUp") {
155
- event.preventDefault();
156
- move(activeIndex - 1);
157
- } else if (event.key === "Home") {
158
- event.preventDefault();
159
- move(0);
160
- } else if (event.key === "End") {
161
- event.preventDefault();
162
- move(2);
163
- }
185
+ const show = (index) => {
186
+ ensureMenuId();
187
+ move(index);
188
+ open.value = true;
164
189
  };
165
- return /* @__PURE__ */ jsxs("div", { ref: rootRef, className: "relative inline-flex", "data-zd-theme-menu": "", children: [
166
- /* @__PURE__ */ jsx(
190
+ return /* @__PURE__ */ jsxs("div", { ref: rootRef, class: "relative inline-flex", "data-zd-theme-menu": "", children: [
191
+ /* @__PURE__ */ jsxs(
167
192
  "button",
168
193
  {
169
194
  ref: triggerRef,
170
195
  type: "button",
171
196
  "aria-haspopup": "menu",
172
197
  "aria-expanded": open,
173
- "aria-controls": open ? menuId.current : void 0,
174
- "aria-label": `${labels.appearance}: ${labels[preference]}`,
175
- "aria-disabled": pending ? "true" : void 0,
176
- "data-zd-pending": pending ? "" : void 0,
177
- onClick: () => {
178
- if (pending) return;
179
- if (open) close(true);
180
- else {
181
- setPlacement(null);
182
- ensureMenuId();
183
- setActiveIndex(preferences.indexOf(preference));
184
- setOpen(true);
185
- }
198
+ "aria-controls": computed(() => open.value ? menuId : void 0),
199
+ "aria-label": computed(() => `${labels.appearance}: ${labels[preference.value]}`),
200
+ "aria-disabled": computed(() => pending.value ? "true" : void 0),
201
+ "data-zd-pending": computed(() => pending.value ? "" : void 0),
202
+ "on:click": () => {
203
+ if (pending.value) return;
204
+ if (open.value) close(true);
205
+ else show(preferences.indexOf(preference.value));
186
206
  },
187
- onKeyDown: (event) => {
188
- if (pending) {
189
- if (event.key === "Enter" || event.key === " ") event.preventDefault();
207
+ "on:keydown": (event) => {
208
+ const keyboard = event;
209
+ if (keyboard.isComposing) return;
210
+ if (pending.value) {
211
+ if (keyboard.key === "Enter" || keyboard.key === " ") keyboard.preventDefault();
190
212
  return;
191
213
  }
192
- if (event.key === "ArrowDown" || event.key === "ArrowUp") {
193
- event.preventDefault();
194
- setPlacement(null);
195
- ensureMenuId();
196
- setActiveIndex(event.key === "ArrowDown" ? 0 : 2);
197
- setOpen(true);
198
- } else if (event.key === "Escape" && open) {
199
- event.preventDefault();
200
- event.stopPropagation();
214
+ if (keyboard.key === "ArrowDown" || keyboard.key === "ArrowUp") {
215
+ keyboard.preventDefault();
216
+ show(keyboard.key === "ArrowDown" ? 0 : 2);
217
+ } else if (keyboard.key === "Escape" && open.value) {
218
+ keyboard.preventDefault();
219
+ keyboard.stopPropagation();
201
220
  close(true);
202
221
  }
203
222
  },
204
- className: "inline-flex h-[40px] w-[40px] shrink-0 items-center justify-center text-muted hover:text-fg focus-visible:outline-2 focus-visible:outline-accent focus-visible:outline-offset-2",
205
- children: /* @__PURE__ */ jsx(PreferenceIcon, { preference })
206
- }
207
- ),
208
- open && createPortal(/* @__PURE__ */ jsxs(
209
- "div",
210
- {
211
- ref: menuRef,
212
- id: menuId.current,
213
- role: "menu",
214
- "aria-label": labels.appearance,
215
- popover: typeof HTMLElement !== "undefined" && "showPopover" in HTMLElement.prototype ? "manual" : void 0,
216
- onKeyDown: onMenuKeyDown,
217
- className: "fixed z-tooltip overflow-y-auto rounded-lg border border-muted bg-surface p-hsp-xs text-fg shadow-lg",
218
- style: placement ? { left: placement.left, top: placement.top, right: "auto", bottom: "auto", margin: 0, width: placement.width, maxHeight: placement.maxHeight } : { visibility: "hidden", left: 0, top: 0, right: "auto", bottom: "auto", margin: 0, width: Math.min(260, window.innerWidth - 16) },
223
+ class: "inline-flex h-[40px] w-[40px] shrink-0 items-center justify-center text-muted hover:text-fg focus-visible:outline-2 focus-visible:outline-accent focus-visible:outline-offset-2",
219
224
  children: [
220
- /* @__PURE__ */ jsx("div", { className: "px-hsp-sm py-vsp-xs text-small font-semibold", "aria-hidden": "true", children: labels.appearance }),
221
- preferences.map((option, index) => /* @__PURE__ */ jsxs(
222
- "button",
223
- {
224
- ref: (node) => {
225
- itemRefs.current[index] = node;
226
- },
227
- type: "button",
228
- role: "menuitemradio",
229
- "aria-checked": preference === option,
230
- onFocus: () => setActiveIndex(index),
231
- onClick: () => select(option),
232
- className: `flex min-h-[44px] w-full items-center gap-hsp-sm rounded px-hsp-sm text-left text-small ${preference === option ? "bg-accent/10" : ""} hover:bg-accent/10 focus-visible:bg-accent/10 focus-visible:outline-2 focus-visible:outline-accent`,
233
- children: [
234
- /* @__PURE__ */ jsx(PreferenceIcon, { preference: option }),
235
- /* @__PURE__ */ jsx("span", { className: "flex-1", children: labels[option] }),
236
- /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "text-accent", children: preference === option ? "\u2713" : "" })
237
- ]
238
- },
239
- option
240
- )),
241
- /* @__PURE__ */ jsx("div", { className: "px-hsp-sm py-vsp-xs text-small text-muted", children: labels.systemHelper.replace("{mode}", labels[resolved]) })
225
+ /* @__PURE__ */ jsx(Show, { when: computed(() => preference.value === "light"), children: () => /* @__PURE__ */ jsx(PreferenceIcon, { preference: "light" }) }),
226
+ /* @__PURE__ */ jsx(Show, { when: computed(() => preference.value === "dark"), children: () => /* @__PURE__ */ jsx(PreferenceIcon, { preference: "dark" }) }),
227
+ /* @__PURE__ */ jsx(Show, { when: computed(() => preference.value === "system"), children: () => /* @__PURE__ */ jsx(PreferenceIcon, { preference: "system" }) })
242
228
  ]
243
229
  }
244
- ), document.body)
230
+ ),
231
+ /* @__PURE__ */ jsx(Show, { when: open, children: () => /* @__PURE__ */ jsx(AppearanceMenu, { id: menuId, labels, preference, resolved, activeIndex, triggerRef, rootRef, close, select, move }) })
245
232
  ] });
246
233
  }
247
234
  ThemeToggle.displayName = "ThemeToggle";