@takazudo/zudo-doc 0.2.21 → 1.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.
- package/bin/gen-z-index.mjs +164 -0
- package/bin/tags-audit-runner.ts +126 -0
- package/bin/tags-audit.mjs +64 -0
- package/bin/zudo-doc.mjs +83 -0
- package/dist/ai-chat-modal/index.d.ts +8 -0
- package/dist/ai-chat-modal/index.js +243 -0
- package/dist/body-foot-util/body-foot-util-area.d.ts +4 -8
- package/dist/body-foot-util/edit-link.d.ts +4 -8
- package/dist/body-foot-util/index.d.ts +4 -3
- package/dist/breadcrumb/breadcrumb.d.ts +5 -9
- package/dist/breadcrumb/find-path.d.ts +2 -5
- package/dist/breadcrumb/index.d.ts +4 -4
- package/dist/breadcrumb/types.d.ts +3 -5
- package/dist/category-nav/index.d.ts +86 -0
- package/dist/category-nav/index.js +44 -0
- package/dist/category-tree-nav/index.d.ts +65 -0
- package/dist/category-tree-nav/index.js +24 -0
- package/dist/code-group/index.d.ts +10 -0
- package/dist/code-group/index.js +37 -0
- package/dist/code-syntax/code-block-enhancer-script.d.ts +1 -3
- package/dist/code-syntax/code-block-enhancer.d.ts +3 -6
- package/dist/code-syntax/index.d.ts +9 -8
- package/dist/code-syntax/mermaid-init-script.d.ts +3 -5
- package/dist/code-syntax/mermaid-init.d.ts +4 -7
- package/dist/code-syntax/tabs-init-script.d.ts +1 -3
- package/dist/code-syntax/tabs-init.d.ts +3 -6
- package/dist/code-syntax/tabs.d.ts +4 -7
- package/dist/color-scheme-utils.d.ts +125 -0
- package/dist/color-scheme-utils.js +151 -0
- package/dist/compose-meta-title/index.d.ts +7 -0
- package/dist/compose-meta-title/index.js +10 -0
- package/dist/content/component-map.d.ts +13 -17
- package/dist/content/content-blockquote.d.ts +3 -6
- package/dist/content/content-code.d.ts +3 -6
- package/dist/content/content-code.js +1 -1
- package/dist/content/content-link.d.ts +3 -6
- package/dist/content/content-link.js +1 -1
- package/dist/content/content-ol.d.ts +3 -6
- package/dist/content/content-paragraph.d.ts +3 -6
- package/dist/content/content-strong.d.ts +3 -6
- package/dist/content/content-table.d.ts +3 -6
- package/dist/content/content-ul.d.ts +3 -6
- package/dist/content/heading-h2.d.ts +3 -6
- package/dist/content/heading-h3.d.ts +3 -6
- package/dist/content/heading-h4.d.ts +3 -6
- package/dist/content/index.d.ts +29 -13
- package/dist/content-admonition/index.d.ts +15 -0
- package/dist/content-admonition/index.js +14 -0
- package/dist/design-token-panel-bootstrap.d.ts +38 -0
- package/dist/design-token-panel-bootstrap.js +29 -0
- package/dist/desktop-sidebar-toggle-island/index.d.ts +5 -0
- package/dist/desktop-sidebar-toggle-island/index.js +62 -0
- package/dist/details/details.d.ts +3 -7
- package/dist/details/index.d.ts +2 -2
- package/dist/doc-body-end/index.d.ts +21 -0
- package/dist/doc-body-end/index.js +15 -0
- package/dist/doc-content-header/index.d.ts +69 -0
- package/dist/doc-content-header/index.js +49 -0
- package/dist/doc-history/index.d.ts +10 -0
- package/dist/doc-history/index.js +407 -0
- package/dist/doc-history-area/index.d.ts +84 -0
- package/dist/doc-history-area/index.js +76 -0
- package/dist/doc-metainfo-area/index.d.ts +46 -0
- package/dist/doc-metainfo-area/index.js +41 -0
- package/dist/doc-page-props/index.d.ts +93 -0
- package/dist/doc-page-props/index.js +0 -0
- package/dist/doc-page-renderer/index.d.ts +128 -0
- package/dist/doc-page-renderer/index.js +103 -0
- package/dist/doc-page-shell/index.d.ts +136 -0
- package/dist/doc-page-shell/index.js +127 -0
- package/dist/doc-pager/index.d.ts +25 -0
- package/dist/doc-pager/index.js +41 -0
- package/dist/doc-route-entries/index.d.ts +125 -0
- package/dist/doc-route-entries/index.js +76 -0
- package/dist/doc-route-paths/index.d.ts +54 -0
- package/dist/doc-route-paths/index.js +61 -0
- package/dist/doc-tags-area/index.d.ts +38 -0
- package/dist/doc-tags-area/index.js +30 -0
- package/dist/doclayout/anchors.d.ts +7 -9
- package/dist/doclayout/doc-layout-with-defaults.d.ts +16 -12
- package/dist/doclayout/doc-layout.d.ts +5 -9
- package/dist/doclayout/index.d.ts +6 -6
- package/dist/eject/index.d.ts +33 -0
- package/dist/eject/index.js +229 -0
- package/dist/extract-headings/index.d.ts +43 -0
- package/dist/extract-headings/index.js +111 -0
- package/dist/factory-context/index.d.ts +80 -0
- package/dist/factory-context/index.js +0 -0
- package/dist/features.css +882 -0
- package/dist/footer/footer.d.ts +4 -8
- package/dist/footer/index.d.ts +13 -3
- package/dist/footer/types.d.ts +4 -6
- package/dist/footer-with-defaults/index.d.ts +63 -0
- package/dist/footer-with-defaults/index.js +128 -0
- package/dist/frontmatter-preview-data/index.d.ts +26 -0
- package/dist/frontmatter-preview-data/index.js +23 -0
- package/dist/github-helpers/index.d.ts +17 -0
- package/dist/github-helpers/index.js +16 -0
- package/dist/head/doc-head.d.ts +3 -6
- package/dist/head/index.d.ts +9 -5
- package/dist/head/og-tags.d.ts +4 -7
- package/dist/head/twitter-card.d.ts +3 -6
- package/dist/head/types.d.ts +1 -3
- package/dist/head-with-defaults/index.d.ts +49 -0
- package/dist/head-with-defaults/index.js +62 -0
- package/dist/header/header.d.ts +6 -10
- package/dist/header/index.d.ts +16 -6
- package/dist/header/nav-active.d.ts +5 -7
- package/dist/header/nav-overflow-script.d.ts +1 -3
- package/dist/header/right-items.d.ts +3 -6
- package/dist/header/types.d.ts +10 -12
- package/dist/header-with-defaults/index.d.ts +77 -0
- package/dist/header-with-defaults/index.js +163 -0
- package/dist/html-preview-wrapper/dedent.d.ts +1 -3
- package/dist/html-preview-wrapper/highlighted-code.d.ts +3 -7
- package/dist/html-preview-wrapper/html-preview-wrapper.d.ts +6 -10
- package/dist/html-preview-wrapper/html-preview.d.ts +5 -9
- package/dist/html-preview-wrapper/index.d.ts +8 -5
- package/dist/html-preview-wrapper/preflight.d.ts +1 -3
- package/dist/html-preview-wrapper/preview-base.d.ts +4 -8
- package/dist/i18n-version/index.d.ts +7 -5
- package/dist/i18n-version/language-switcher.d.ts +5 -8
- package/dist/i18n-version/types.d.ts +3 -5
- package/dist/i18n-version/version-banner.d.ts +4 -8
- package/dist/i18n-version/version-switcher.d.ts +7 -10
- package/dist/icons/index.d.ts +9 -13
- package/dist/image-enlarge/index.d.ts +13 -0
- package/dist/image-enlarge/index.js +176 -0
- package/dist/index.d.ts +26 -2
- package/dist/inline-version-switcher/index.d.ts +31 -0
- package/dist/inline-version-switcher/index.js +44 -0
- package/dist/integrations/claude-resources/escape-for-mdx.d.ts +1 -3
- package/dist/integrations/claude-resources/generate.d.ts +2 -4
- package/dist/integrations/claude-resources/index.d.ts +7 -10
- package/dist/integrations/doc-history/index.d.ts +21 -24
- package/dist/integrations/doc-history/pre-build.d.ts +7 -9
- package/dist/integrations/llms-txt/dev-middleware.d.ts +7 -11
- package/dist/integrations/llms-txt/emit.d.ts +2 -7
- package/dist/integrations/llms-txt/generate.d.ts +3 -8
- package/dist/integrations/llms-txt/index.d.ts +33 -8
- package/dist/integrations/llms-txt/load.d.ts +3 -7
- package/dist/integrations/llms-txt/strip.d.ts +2 -6
- package/dist/integrations/llms-txt/types.d.ts +9 -13
- package/dist/integrations/search-index/build-emitter.d.ts +4 -7
- package/dist/integrations/search-index/collect.d.ts +2 -5
- package/dist/integrations/search-index/dev-middleware.d.ts +5 -8
- package/dist/integrations/search-index/index.d.ts +7 -5
- package/dist/integrations/search-index/types.d.ts +5 -7
- package/dist/island-types/index.d.ts +44 -0
- package/dist/island-types/index.js +12 -0
- package/dist/locale-merge/index.d.ts +114 -0
- package/dist/locale-merge/index.js +27 -0
- package/dist/math-block/index.d.ts +18 -0
- package/dist/math-block/index.js +29 -0
- package/dist/md-utils/index.d.ts +6 -8
- package/dist/md-utils/index.js +2 -1
- package/dist/mdx-components/index.d.ts +46 -0
- package/dist/mdx-components/index.js +161 -0
- package/dist/mermaid-enlarge/index.d.ts +11 -0
- package/dist/mermaid-enlarge/index.js +290 -0
- package/dist/metainfo/doc-metainfo.d.ts +5 -9
- package/dist/metainfo/doc-tags.d.ts +7 -11
- package/dist/metainfo/frontmatter-preview.d.ts +8 -12
- package/dist/metainfo/index.d.ts +6 -4
- package/dist/nav-data-prep/index.d.ts +72 -0
- package/dist/nav-data-prep/index.js +34 -0
- package/dist/nav-indexing/category-nav.d.ts +4 -8
- package/dist/nav-indexing/category-tree-nav.d.ts +4 -8
- package/dist/nav-indexing/doc-card-grid.d.ts +4 -8
- package/dist/nav-indexing/docs-sitemap.d.ts +4 -8
- package/dist/nav-indexing/index.d.ts +37 -10
- package/dist/nav-indexing/nav-card-grid.d.ts +4 -8
- package/dist/nav-indexing/site-tree-nav-demo.d.ts +4 -8
- package/dist/nav-indexing/tag-nav.d.ts +6 -10
- package/dist/nav-indexing/types.d.ts +6 -8
- package/dist/nav-indexing/versions-page-content.d.ts +4 -8
- package/dist/nav-scope/index.d.ts +41 -0
- package/dist/nav-scope/index.js +41 -0
- package/dist/nav-source-cache/index.d.ts +13 -0
- package/dist/nav-source-cache/index.js +28 -0
- package/dist/nav-source-docs/index.d.ts +169 -0
- package/dist/nav-source-docs/index.js +123 -0
- package/dist/page-loading/index.d.ts +1 -2
- package/dist/page-loading/page-loading-overlay.d.ts +4 -8
- package/dist/plugins/claude-resources.d.ts +3 -0
- package/dist/plugins/claude-resources.js +27 -0
- package/dist/plugins/connect-adapter.d.ts +31 -0
- package/dist/plugins/connect-adapter.js +78 -0
- package/dist/plugins/doc-history.d.ts +3 -0
- package/dist/plugins/doc-history.js +54 -0
- package/dist/plugins/llms-txt.d.ts +3 -0
- package/dist/plugins/llms-txt.js +48 -0
- package/dist/plugins/plugin-utils.d.ts +17 -0
- package/dist/plugins/plugin-utils.js +11 -0
- package/dist/plugins/routes.d.ts +2 -0
- package/dist/plugins/routes.js +100 -0
- package/dist/plugins/search-index.d.ts +3 -0
- package/dist/plugins/search-index.js +24 -0
- package/dist/preset.d.ts +198 -0
- package/dist/preset.js +185 -0
- package/dist/render-markdown/index.d.ts +5 -0
- package/dist/render-markdown/index.js +115 -0
- package/dist/robots.d.ts +36 -0
- package/dist/robots.js +17 -0
- package/dist/route-enumerators/index.d.ts +204 -0
- package/dist/route-enumerators/index.js +156 -0
- package/dist/routes/404.d.ts +7 -0
- package/dist/routes/404.js +47 -0
- package/dist/routes/_chrome.d.ts +32 -0
- package/dist/routes/_chrome.js +365 -0
- package/dist/routes/_context.d.ts +56 -0
- package/dist/routes/_context.js +222 -0
- package/dist/routes/_docs-helpers.d.ts +43 -0
- package/dist/routes/_docs-helpers.js +173 -0
- package/dist/routes/_virtual.d.js +0 -0
- package/dist/routes/api-ai-chat.d.ts +5 -0
- package/dist/routes/api-ai-chat.js +24 -0
- package/dist/routes/docs-slug.d.ts +21 -0
- package/dist/routes/docs-slug.js +26 -0
- package/dist/routes/docs-tags-index.d.ts +7 -0
- package/dist/routes/docs-tags-index.js +11 -0
- package/dist/routes/docs-tags-tag.d.ts +23 -0
- package/dist/routes/docs-tags-tag.js +19 -0
- package/dist/routes/docs-versions.d.ts +7 -0
- package/dist/routes/docs-versions.js +11 -0
- package/dist/routes/index.d.ts +7 -0
- package/dist/routes/index.js +117 -0
- package/dist/routes/locale-docs-slug.d.ts +27 -0
- package/dist/routes/locale-docs-slug.js +40 -0
- package/dist/routes/locale-docs-tags-index.d.ts +18 -0
- package/dist/routes/locale-docs-tags-index.js +15 -0
- package/dist/routes/locale-docs-tags-tag.d.ts +25 -0
- package/dist/routes/locale-docs-tags-tag.js +22 -0
- package/dist/routes/locale-docs-versions.d.ts +18 -0
- package/dist/routes/locale-docs-versions.js +15 -0
- package/dist/routes/locale-index.d.ts +24 -0
- package/dist/routes/locale-index.js +132 -0
- package/dist/routes/robots.txt.d.ts +3 -0
- package/dist/routes/robots.txt.js +8 -0
- package/dist/routes/sitemap.xml.d.ts +5 -0
- package/dist/routes/sitemap.xml.js +31 -0
- package/dist/routes/v-docs-slug.d.ts +27 -0
- package/dist/routes/v-docs-slug.js +34 -0
- package/dist/routes/v-locale-docs-slug.d.ts +31 -0
- package/dist/routes/v-locale-docs-slug.js +50 -0
- package/dist/safelist.css +1 -1
- package/dist/search-widget/index.d.ts +38 -0
- package/dist/search-widget/index.js +169 -0
- package/dist/search-widget-script/index.d.ts +18 -0
- package/dist/search-widget-script/index.js +465 -0
- package/dist/settings.d.ts +270 -0
- package/dist/settings.js +0 -0
- package/dist/sidebar/index.d.ts +21 -3
- package/dist/sidebar/sidebar.d.ts +5 -9
- package/dist/sidebar/types.d.ts +4 -6
- package/dist/sidebar-prepaint/index.d.ts +21 -0
- package/dist/sidebar-prepaint/index.js +23 -0
- package/dist/sidebar-resizer/index.d.ts +2 -6
- package/dist/sidebar-resizer/sidebar-resizer-init.d.ts +6 -10
- package/dist/sidebar-toggle-island/index.d.ts +13 -0
- package/dist/sidebar-toggle-island/index.js +122 -0
- package/dist/sidebar-tree/build-tree.d.ts +4 -8
- package/dist/sidebar-tree/category-meta.d.ts +3 -6
- package/dist/sidebar-tree/index.d.ts +18 -3
- package/dist/sidebar-tree/types.d.ts +6 -8
- package/dist/sidebar-tree-island/index.d.ts +13 -0
- package/dist/sidebar-tree-island/index.js +454 -0
- package/dist/sidebar-utils/index.d.ts +64 -0
- package/dist/sidebar-utils/index.js +88 -0
- package/dist/sidebar-with-defaults/index.d.ts +38 -0
- package/dist/sidebar-with-defaults/index.js +45 -0
- package/dist/site-tree-nav/index.d.ts +71 -0
- package/dist/site-tree-nav/index.js +36 -0
- package/dist/site-tree-nav-island/index.d.ts +11 -0
- package/dist/site-tree-nav-island/index.js +176 -0
- package/dist/slug/index.d.ts +4 -0
- package/dist/slug/index.js +19 -0
- package/dist/smart-break/index.d.ts +55 -0
- package/dist/{toc/smart-break.js → smart-break/index.js} +30 -3
- package/dist/tab-item/index.d.ts +2 -2
- package/dist/tab-item/tab-item.d.ts +6 -7
- package/dist/tag-helpers/index.d.ts +40 -0
- package/dist/tag-helpers/index.js +54 -0
- package/dist/tag-pages/index.d.ts +114 -0
- package/dist/tag-pages/index.js +146 -0
- package/dist/tags-audit.d.ts +107 -0
- package/dist/tags-audit.js +321 -0
- package/dist/theme/color-scheme-provider.d.ts +4 -8
- package/dist/theme/color-tweak-export-modal.d.ts +4 -7
- package/dist/theme/design-token-serde.d.ts +14 -17
- package/dist/theme/design-token-types.d.ts +4 -6
- package/dist/theme/iframe-bridge.d.ts +12 -14
- package/dist/theme/index.d.ts +7 -9
- package/dist/theme/theme-toggle.d.ts +3 -8
- package/dist/theme-toggle/color-scheme-sync.d.ts +5 -7
- package/dist/theme-toggle/index.d.ts +4 -8
- package/dist/toc/cx.d.ts +2 -3
- package/dist/toc/index.d.ts +8 -6
- package/dist/toc/mobile-toc.d.ts +5 -9
- package/dist/toc/mobile-toc.js +1 -1
- package/dist/toc/toc-title.d.ts +1 -3
- package/dist/toc/toc.d.ts +5 -9
- package/dist/toc/toc.js +1 -1
- package/dist/toc/types.d.ts +1 -3
- package/dist/toc/use-active-heading.d.ts +4 -7
- package/dist/transitions/index.d.ts +1 -1
- package/dist/transitions/page-events.d.ts +4 -6
- package/dist/tree-nav-shared/index.d.ts +22 -0
- package/dist/tree-nav-shared/index.js +66 -0
- package/dist/url-helpers/index.d.ts +37 -0
- package/dist/url-helpers/index.js +106 -0
- package/dist/url-normalizer/index.d.ts +39 -1
- package/dist/url-normalizer/normalize.d.ts +3 -5
- package/dist/use-modal-dialog/index.d.ts +70 -0
- package/dist/use-modal-dialog/index.js +73 -0
- package/dist/versions-page/index.d.ts +55 -0
- package/dist/versions-page/index.js +73 -0
- package/eject/breadcrumb/breadcrumb.tsx +194 -0
- package/eject/breadcrumb/find-path.ts +26 -0
- package/eject/breadcrumb/index.ts +4 -0
- package/eject/breadcrumb/types.ts +32 -0
- package/eject/code-group/index.tsx +78 -0
- package/eject/content-admonition/index.tsx +50 -0
- package/eject/details/details.tsx +34 -0
- package/eject/details/index.ts +4 -0
- package/eject/doc-pager/index.tsx +91 -0
- package/eject/footer/footer.tsx +167 -0
- package/eject/footer/index.ts +19 -0
- package/eject/footer/types.ts +60 -0
- package/eject/header/header.tsx +725 -0
- package/eject/header/index.ts +36 -0
- package/eject/header/nav-active.ts +122 -0
- package/eject/header/nav-overflow-script.ts +302 -0
- package/eject/header/right-items.ts +78 -0
- package/eject/header/types.ts +69 -0
- package/eject/page-loading/index.ts +10 -0
- package/eject/page-loading/page-loading-overlay.tsx +103 -0
- package/eject/sidebar/index.ts +27 -0
- package/eject/sidebar/sidebar.tsx +137 -0
- package/eject/sidebar/types.ts +73 -0
- package/eject/tab-item/index.ts +7 -0
- package/eject/tab-item/tab-item.tsx +70 -0
- package/eject/theme-toggle/color-scheme-sync.ts +73 -0
- package/eject/theme-toggle/index.tsx +120 -0
- package/eject/toc/cx.ts +38 -0
- package/eject/toc/index.ts +11 -0
- package/eject/toc/mobile-toc.tsx +133 -0
- package/eject/toc/toc-title.ts +33 -0
- package/eject/toc/toc.tsx +119 -0
- package/eject/toc/types.ts +14 -0
- package/eject/toc/use-active-heading.ts +162 -0
- package/package.json +371 -11
- package/routes-src/404.tsx +49 -0
- package/routes-src/_chrome.tsx +470 -0
- package/routes-src/_context.ts +314 -0
- package/routes-src/_docs-helpers.ts +284 -0
- package/routes-src/_virtual.d.ts +15 -0
- package/routes-src/api-ai-chat.tsx +46 -0
- package/routes-src/docs-slug.tsx +43 -0
- package/routes-src/docs-tags-index.tsx +14 -0
- package/routes-src/docs-tags-tag.tsx +29 -0
- package/routes-src/docs-versions.tsx +15 -0
- package/routes-src/index.tsx +134 -0
- package/routes-src/locale-docs-slug.tsx +69 -0
- package/routes-src/locale-docs-tags-index.tsx +23 -0
- package/routes-src/locale-docs-tags-tag.tsx +39 -0
- package/routes-src/locale-docs-versions.tsx +23 -0
- package/routes-src/locale-index.tsx +150 -0
- package/routes-src/robots.txt.tsx +13 -0
- package/routes-src/sitemap.xml.tsx +48 -0
- package/routes-src/v-docs-slug.tsx +64 -0
- package/routes-src/v-locale-docs-slug.tsx +85 -0
- package/dist/toc/smart-break.d.ts +0 -27
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/** @jsxRuntime automatic */
|
|
2
|
+
/** @jsxImportSource preact */
|
|
3
|
+
|
|
4
|
+
// Server-rendered, zero-hydration full-page loading overlay.
|
|
5
|
+
//
|
|
6
|
+
// Renders three things into the document:
|
|
7
|
+
//
|
|
8
|
+
// 1. A fixed-position overlay `<div>` with a centered spinner. Hidden
|
|
9
|
+
// by default (`opacity: 0; pointer-events: none;`) and made
|
|
10
|
+
// visible by adding `data-visible` to it.
|
|
11
|
+
// 2. A `<style>` block that owns the overlay + spinner CSS plus the
|
|
12
|
+
// `prefers-reduced-motion` fallback. Inlined via
|
|
13
|
+
// `dangerouslySetInnerHTML` (matching the ColorSchemeProvider
|
|
14
|
+
// pattern) so no separate stylesheet has to be wired up.
|
|
15
|
+
// 3. A small `<script>` that toggles the `data-visible` attribute on
|
|
16
|
+
// navigation lifecycle events. The event names come from the
|
|
17
|
+
// `@takazudo/zudo-doc/transitions` module — this component does
|
|
18
|
+
// not reach for the underlying browser event names directly. Under
|
|
19
|
+
// zfb's Strategy B SPA navigation, the v2 vocabulary resolves to
|
|
20
|
+
// `zfb:before-preparation` (BEFORE_NAVIGATE_EVENT) and
|
|
21
|
+
// `zfb:after-swap` (AFTER_NAVIGATE_EVENT); see
|
|
22
|
+
// `transitions/page-events.ts` for rationale.
|
|
23
|
+
//
|
|
24
|
+
// The component is intentionally not hydrated. Hydrating Preact just to
|
|
25
|
+
// attach two listeners would be wasteful given the original Astro file
|
|
26
|
+
// shipped a tiny imperative script — this port keeps that profile.
|
|
27
|
+
|
|
28
|
+
import {
|
|
29
|
+
AFTER_NAVIGATE_EVENT,
|
|
30
|
+
BEFORE_NAVIGATE_EVENT,
|
|
31
|
+
} from "../transitions/page-events.js";
|
|
32
|
+
|
|
33
|
+
/** Default `id` for the overlay element. Stable so test rigs can target it. */
|
|
34
|
+
export const PAGE_LOADING_OVERLAY_ID = "page-loading-overlay";
|
|
35
|
+
|
|
36
|
+
export interface PageLoadingOverlayProps {
|
|
37
|
+
/**
|
|
38
|
+
* Override the DOM `id` used by both the overlay element and the
|
|
39
|
+
* bootstrap script. Useful when multiple overlays could co-exist on
|
|
40
|
+
* the page (e.g. tests). Defaults to `PAGE_LOADING_OVERLAY_ID`.
|
|
41
|
+
*/
|
|
42
|
+
id?: string;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Build the inline bootstrap script body. Exported so test rigs can
|
|
47
|
+
* inspect / snapshot it without rendering the component.
|
|
48
|
+
*/
|
|
49
|
+
export function buildPageLoadingOverlayBootstrap(overlayId: string): string {
|
|
50
|
+
// Values are inlined as JSON literals so the script is fully
|
|
51
|
+
// self-contained and matches the `define:vars` shape used elsewhere
|
|
52
|
+
// (see ColorSchemeProvider). Event names come from the transitions
|
|
53
|
+
// module's exported constants — no raw `astro:*` strings live in
|
|
54
|
+
// this file.
|
|
55
|
+
const id = JSON.stringify(overlayId);
|
|
56
|
+
const before = JSON.stringify(BEFORE_NAVIGATE_EVENT);
|
|
57
|
+
const after = JSON.stringify(AFTER_NAVIGATE_EVENT);
|
|
58
|
+
return `(function(){
|
|
59
|
+
var id=${id};
|
|
60
|
+
function show(){var el=document.getElementById(id);if(!el)return;el.setAttribute("data-visible","");el.setAttribute("aria-hidden","false");}
|
|
61
|
+
function hide(){var el=document.getElementById(id);if(!el)return;el.removeAttribute("data-visible");el.setAttribute("aria-hidden","true");}
|
|
62
|
+
function setPending(ev){document.querySelectorAll("[data-zd-nav-pending]").forEach(function(el){el.removeAttribute("data-zd-nav-pending");});var src=ev&&ev.sourceElement;if(src&&src instanceof Element)src.setAttribute("data-zd-nav-pending","");}
|
|
63
|
+
function clearPending(){document.querySelectorAll("[data-zd-nav-pending]").forEach(function(el){el.removeAttribute("data-zd-nav-pending");});}
|
|
64
|
+
document.addEventListener(${before},show);
|
|
65
|
+
document.addEventListener(${after},hide);
|
|
66
|
+
document.addEventListener(${before},setPending);
|
|
67
|
+
document.addEventListener(${after},clearPending);
|
|
68
|
+
})();`;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Full-page loading overlay shown during view-transition navigations.
|
|
73
|
+
*
|
|
74
|
+
* Mount this once per layout (typically inside `DocLayoutWithDefaults`'s
|
|
75
|
+
* `bodyEnd` slot, alongside the existing body-end providers). It is
|
|
76
|
+
* server-rendered and self-wires its visibility — no hydration needed.
|
|
77
|
+
*
|
|
78
|
+
* CSS lives in the host project's `src/styles/global.css` (`.page-loading-overlay`,
|
|
79
|
+
* `.page-loading-spinner`, `[data-zd-nav-pending]` rules) rather than in an
|
|
80
|
+
* inline `<style>` block here — a `<style>` inside `<body>` violates HTML5
|
|
81
|
+
* element-permitted-content and fails html-validate (same fix applied to the
|
|
82
|
+
* version-switcher in zudolab/zudo-doc#1505; regression caught in W2A #1543).
|
|
83
|
+
*/
|
|
84
|
+
export default function PageLoadingOverlay({
|
|
85
|
+
id = PAGE_LOADING_OVERLAY_ID,
|
|
86
|
+
}: PageLoadingOverlayProps = {}) {
|
|
87
|
+
return (
|
|
88
|
+
<>
|
|
89
|
+
<div
|
|
90
|
+
id={id}
|
|
91
|
+
class="page-loading-overlay"
|
|
92
|
+
aria-hidden="true"
|
|
93
|
+
>
|
|
94
|
+
<span class="page-loading-spinner" />
|
|
95
|
+
</div>
|
|
96
|
+
<script
|
|
97
|
+
dangerouslySetInnerHTML={{
|
|
98
|
+
__html: buildPageLoadingOverlayBootstrap(id),
|
|
99
|
+
}}
|
|
100
|
+
/>
|
|
101
|
+
</>
|
|
102
|
+
);
|
|
103
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public entry for the framework-agnostic sidebar shell.
|
|
3
|
+
*
|
|
4
|
+
* Consumers import from `@takazudo/zudo-doc/sidebar`:
|
|
5
|
+
*
|
|
6
|
+
* import {
|
|
7
|
+
* Sidebar,
|
|
8
|
+
* type SidebarProps,
|
|
9
|
+
* type SidebarNavNode,
|
|
10
|
+
* type SidebarRootMenuItem,
|
|
11
|
+
* type SidebarLocaleLink,
|
|
12
|
+
* type SidebarTreeIslandProps,
|
|
13
|
+
* } from "@takazudo/zudo-doc/sidebar";
|
|
14
|
+
*
|
|
15
|
+
* The shell does NOT include the SidebarTree island itself — the host
|
|
16
|
+
* project's existing Preact island is plugged in via the
|
|
17
|
+
* `treeComponent` prop (or rendered as `children`).
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
export { Sidebar } from "./sidebar.js";
|
|
21
|
+
export type { SidebarProps } from "./sidebar.js";
|
|
22
|
+
export type {
|
|
23
|
+
SidebarLocaleLink,
|
|
24
|
+
SidebarNavNode,
|
|
25
|
+
SidebarRootMenuItem,
|
|
26
|
+
SidebarTreeIslandProps,
|
|
27
|
+
} from "./types.js";
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
/** @jsxRuntime automatic */
|
|
4
|
+
/** @jsxImportSource preact */
|
|
5
|
+
|
|
6
|
+
// JSX port of src/components/sidebar.
|
|
7
|
+
//
|
|
8
|
+
// The original Astro template was almost entirely data assembly —
|
|
9
|
+
// build root-menu items from `settings.headerNav`, load the locale's
|
|
10
|
+
// docs collection, build the nav tree for the active section, optionally
|
|
11
|
+
// remap hrefs for versioned routes, and finally render the project's
|
|
12
|
+
// `<SidebarTree client:load .../>` Preact island.
|
|
13
|
+
//
|
|
14
|
+
// All of that data-prep depends on host-only helpers (`@/config/i18n`,
|
|
15
|
+
// `@/utils/sidebar`, `@/utils/locale-docs`, `@/utils/base`,
|
|
16
|
+
// `@/config/settings`) that v2 must not import. This shell therefore
|
|
17
|
+
// keeps the data-prep on the host side and only provides:
|
|
18
|
+
//
|
|
19
|
+
// - typed props that match the SidebarTree island's prop shape, so
|
|
20
|
+
// the host's prep code can be typed against v2's interface;
|
|
21
|
+
// - a `treeComponent` prop the host supplies (their existing Preact
|
|
22
|
+
// island) — the shell instantiates it with the typed props and
|
|
23
|
+
// forwards everything;
|
|
24
|
+
// - a `children` fallback for callers that want to render the tree
|
|
25
|
+
// themselves (useful for tests, fixtures, and downstream projects
|
|
26
|
+
// that swap the tree out wholesale).
|
|
27
|
+
//
|
|
28
|
+
// Wave 13 ("smoke-toc duplicate-nav regression follow-on", zudolab/zudo-doc#1355):
|
|
29
|
+
// before this refactor, this module exported a `Sidebar` wrapper that
|
|
30
|
+
// itself called `Island({when:"load", children:<SidebarInner/>})` and
|
|
31
|
+
// returned the wrapped div. The zfb island scanner picked the exported
|
|
32
|
+
// `Sidebar` (the wrapper) as the bundle's hydration target, so on the
|
|
33
|
+
// client `mountIslands` ran `hydrate(<Sidebar/>, dataIslandDiv)` where
|
|
34
|
+
// the rendered vnode itself emitted *another* `<div data-zfb-island=
|
|
35
|
+
// "Sidebar"><SidebarInner/></div>` inside the existing one. Unlike the
|
|
36
|
+
// `Toc` / `MobileToc` case (where the inner re-rendered identical
|
|
37
|
+
// content alongside the SSR'd content, producing a visible duplicate),
|
|
38
|
+
// the duplicate here was silent: the host passes `treeComponent` (a
|
|
39
|
+
// Preact component function) as a prop, and `island.ts`'s
|
|
40
|
+
// `captureSerializableProps` does `JSON.stringify` on the props bag,
|
|
41
|
+
// which silently drops function values. At hydrate time the
|
|
42
|
+
// deserialized props had no `treeComponent`, `SidebarInner` returned
|
|
43
|
+
// `null`, and the appended wrapper-div was empty. Net result: an extra
|
|
44
|
+
// dead-mount data-zfb-island Sidebar div alongside the SSR'd tree, with
|
|
45
|
+
// no observable content — but a wasted hydration slot, and the actual
|
|
46
|
+
// user-facing event-handler / state work was being done entirely by
|
|
47
|
+
// the host's `SidebarTree` island registration.
|
|
48
|
+
//
|
|
49
|
+
// Fix: same shape as Toc / MobileToc — drop the `Island`-wrapping
|
|
50
|
+
// outer, export the bare component (was `SidebarInner`) as `Sidebar`,
|
|
51
|
+
// pin `displayName` explicitly. The `<Island when="load">` wrapper is
|
|
52
|
+
// applied at the call site (`<DocLayoutWithDefaults>`).
|
|
53
|
+
|
|
54
|
+
import type { ComponentChildren, FunctionComponent, VNode } from "preact";
|
|
55
|
+
|
|
56
|
+
import type { SidebarTreeIslandProps } from "./types.js";
|
|
57
|
+
|
|
58
|
+
export interface SidebarProps extends SidebarTreeIslandProps {
|
|
59
|
+
/**
|
|
60
|
+
* The host's SidebarTree component. When present, the shell renders
|
|
61
|
+
* `<TreeComponent {...islandProps} />` with the typed props below.
|
|
62
|
+
* Mutually exclusive with `children`: prefer this form so v2 owns the
|
|
63
|
+
* prop forwarding contract.
|
|
64
|
+
*/
|
|
65
|
+
treeComponent?: FunctionComponent<SidebarTreeIslandProps>;
|
|
66
|
+
/**
|
|
67
|
+
* Pre-rendered tree content — falls back to this when
|
|
68
|
+
* `treeComponent` is omitted. Useful for tests and for layouts that
|
|
69
|
+
* compose the tree separately (e.g. inside a host wrapper
|
|
70
|
+
* that needs `client:load` on the actual island element).
|
|
71
|
+
*/
|
|
72
|
+
children?: ComponentChildren;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Sidebar shell — typed wrapper around the SidebarTree island.
|
|
77
|
+
*
|
|
78
|
+
* Two usage shapes (matching the breadcrumb shell's pattern):
|
|
79
|
+
*
|
|
80
|
+
* 1. Pass `treeComponent` plus the data props (`nodes`,
|
|
81
|
+
* `rootMenuItems`, `localeLinks`, …). The shell forwards them all
|
|
82
|
+
* to the supplied component.
|
|
83
|
+
*
|
|
84
|
+
* 2. Pass `children` (e.g. a pre-instantiated `<SidebarTree
|
|
85
|
+
* client:load … />` from an Astro wrapper). The shell renders
|
|
86
|
+
* them as-is — the typed island props are then unused but kept on
|
|
87
|
+
* the type signature so call-sites stay self-documenting.
|
|
88
|
+
*
|
|
89
|
+
* **The caller is responsible for wrapping this in `<Island when="load">`**
|
|
90
|
+
* so the SSG output emits the `data-zfb-island="Sidebar"` hydration
|
|
91
|
+
* marker around the rendered tree. `<DocLayoutWithDefaults>` does this
|
|
92
|
+
* for you; consumers who render `<Sidebar>` outside the default layout
|
|
93
|
+
* (e.g. via the `sidebarOverride` prop or in a custom layout) must
|
|
94
|
+
* apply the wrapper themselves — otherwise no hydration marker is
|
|
95
|
+
* emitted, and the runtime walks past the SSR'd tree without claiming
|
|
96
|
+
* it as an island. Either way the actual user-facing interactivity
|
|
97
|
+
* comes from the `treeComponent`'s own island registration; the
|
|
98
|
+
* `<Island>` wrapper here exists so the shell can host data-only
|
|
99
|
+
* variants in the future without losing the marker contract.
|
|
100
|
+
*/
|
|
101
|
+
export function Sidebar(props: SidebarProps): VNode | null {
|
|
102
|
+
const {
|
|
103
|
+
treeComponent: TreeComponent,
|
|
104
|
+
children,
|
|
105
|
+
nodes,
|
|
106
|
+
currentSlug,
|
|
107
|
+
rootMenuItems,
|
|
108
|
+
backToMenuLabel,
|
|
109
|
+
localeLinks,
|
|
110
|
+
themeDefaultMode,
|
|
111
|
+
} = props;
|
|
112
|
+
|
|
113
|
+
if (TreeComponent) {
|
|
114
|
+
return (
|
|
115
|
+
<TreeComponent
|
|
116
|
+
nodes={nodes}
|
|
117
|
+
currentSlug={currentSlug}
|
|
118
|
+
rootMenuItems={rootMenuItems}
|
|
119
|
+
backToMenuLabel={backToMenuLabel}
|
|
120
|
+
localeLinks={localeLinks}
|
|
121
|
+
themeDefaultMode={themeDefaultMode}
|
|
122
|
+
/>
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (children !== undefined && children !== null) {
|
|
127
|
+
return <>{children}</>;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
// Pin the marker name to "Sidebar" regardless of how Preact's compat
|
|
133
|
+
// layer or esbuild minification renames the function. Island's SSR
|
|
134
|
+
// pass reads `displayName ?? name` to derive the marker string;
|
|
135
|
+
// pinning both means the SSG marker stays `data-zfb-island="Sidebar"`
|
|
136
|
+
// independent of the bundle's symbol-renaming.
|
|
137
|
+
Sidebar.displayName = "Sidebar";
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public types for the framework-agnostic sidebar shell.
|
|
3
|
+
*
|
|
4
|
+
* The original `sidebar` mixed three concerns:
|
|
5
|
+
* 1. Building `rootMenuItems` from `settings.headerNav` (with i18n
|
|
6
|
+
* label resolution and version-aware hrefs).
|
|
7
|
+
* 2. Building the doc tree via `loadLocaleDocs` +
|
|
8
|
+
* `buildSidebarForSection`, then optionally remapping hrefs to
|
|
9
|
+
* versioned paths.
|
|
10
|
+
* 3. Rendering a `<SidebarTree client:load .../>` Preact island.
|
|
11
|
+
*
|
|
12
|
+
* Concerns (1) and (2) depend on host-only helpers that v2 must not
|
|
13
|
+
* reach into. The v2 shell exists to:
|
|
14
|
+
* - publish the prop shape so the host's data prep code can be
|
|
15
|
+
* typed against a v2-owned interface, and
|
|
16
|
+
* - render whatever the host hands in (typically the project's
|
|
17
|
+
* `<SidebarTree client:load .../>` island) inside a typed wrapper.
|
|
18
|
+
*
|
|
19
|
+
* The structural types here mirror `src/utils/docs.ts` (`NavNode`) and
|
|
20
|
+
* `src/types/locale.ts` (`LocaleLink`) so the host can keep using its
|
|
21
|
+
* existing data-prep pipeline without re-mapping fields.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* One node in the navigation tree the SidebarTree island renders.
|
|
26
|
+
* Matches `NavNode` in the host project's `src/utils/docs.ts`.
|
|
27
|
+
*/
|
|
28
|
+
export interface SidebarNavNode {
|
|
29
|
+
slug: string;
|
|
30
|
+
label: string;
|
|
31
|
+
description?: string;
|
|
32
|
+
position: number;
|
|
33
|
+
href?: string;
|
|
34
|
+
hasPage: boolean;
|
|
35
|
+
children: SidebarNavNode[];
|
|
36
|
+
sortOrder?: "asc" | "desc";
|
|
37
|
+
collapsed?: boolean;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Item in the root-level "Docusaurus-style" menu shown above the
|
|
42
|
+
* doc tree on mobile / inside the back-to-menu view.
|
|
43
|
+
*/
|
|
44
|
+
export interface SidebarRootMenuItem {
|
|
45
|
+
label: string;
|
|
46
|
+
href: string;
|
|
47
|
+
children?: SidebarRootMenuItem[];
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Locale switcher link rendered inside the mobile sidebar footer.
|
|
52
|
+
* Matches `LocaleLink` in the host project's `src/types/locale.ts`.
|
|
53
|
+
*/
|
|
54
|
+
export interface SidebarLocaleLink {
|
|
55
|
+
code: string;
|
|
56
|
+
label: string;
|
|
57
|
+
href: string;
|
|
58
|
+
active: boolean;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Props the SidebarTree island consumes. The shell forwards these
|
|
63
|
+
* to whichever component the host plugs in via {@link SidebarProps.treeComponent}
|
|
64
|
+
* (or to nothing, when the host renders its own tree as `children`).
|
|
65
|
+
*/
|
|
66
|
+
export interface SidebarTreeIslandProps {
|
|
67
|
+
nodes: SidebarNavNode[];
|
|
68
|
+
currentSlug?: string;
|
|
69
|
+
rootMenuItems?: SidebarRootMenuItem[];
|
|
70
|
+
backToMenuLabel?: string;
|
|
71
|
+
localeLinks?: SidebarLocaleLink[];
|
|
72
|
+
themeDefaultMode?: "light" | "dark";
|
|
73
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// E5 framework primitives — tab-item visual wrapper.
|
|
2
|
+
//
|
|
3
|
+
// Subpath: `@takazudo/zudo-doc/tab-item`. JSX port of
|
|
4
|
+
// the legacy `tab-item` component from the host project.
|
|
5
|
+
|
|
6
|
+
export { TabItem, default } from "./tab-item.js";
|
|
7
|
+
export type { TabItemProps } from "./tab-item.js";
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/** @jsxRuntime automatic */
|
|
2
|
+
/** @jsxImportSource preact */
|
|
3
|
+
|
|
4
|
+
// JSX port of the legacy `tab-item` component.
|
|
5
|
+
//
|
|
6
|
+
// Visual wrapper for one tab panel inside a Tabs group. Server-rendered,
|
|
7
|
+
// no hydration. The companion Tabs island reads `data-tab-value` /
|
|
8
|
+
// `data-tab-label` / `data-tab-default` to wire interactivity, so the
|
|
9
|
+
// attribute shape here must mirror the Astro original byte-for-byte.
|
|
10
|
+
|
|
11
|
+
import type { ComponentChildren } from "preact";
|
|
12
|
+
|
|
13
|
+
export interface TabItemProps {
|
|
14
|
+
/** Human-readable label rendered by the parent Tabs trigger row. */
|
|
15
|
+
label: string;
|
|
16
|
+
/**
|
|
17
|
+
* Optional stable value for the tab. Falls back to `label` when
|
|
18
|
+
* omitted, matching the Astro original's `value ?? label`.
|
|
19
|
+
*/
|
|
20
|
+
value?: string;
|
|
21
|
+
/**
|
|
22
|
+
* When true, this panel is the initially-active one. Encoded as the
|
|
23
|
+
* empty-string `data-tab-default` attribute so plain attribute
|
|
24
|
+
* selectors (`[data-tab-default]`) still match.
|
|
25
|
+
*/
|
|
26
|
+
default?: boolean;
|
|
27
|
+
/** Panel body. */
|
|
28
|
+
children?: ComponentChildren;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* One tab panel.
|
|
33
|
+
*
|
|
34
|
+
* Wave 11 (zudolab/zudo-doc#1355): the default panel is rendered
|
|
35
|
+
* **without** the `hidden` attribute so the SSR HTML already shows the
|
|
36
|
+
* correct active panel before any JS runs. Non-default panels keep
|
|
37
|
+
* `hidden`. This avoids the post-Wave-10 regression where the tabs
|
|
38
|
+
* init script could land after first paint and flash an empty tab
|
|
39
|
+
* group; it also gives the no-JS path a usable default tab.
|
|
40
|
+
*
|
|
41
|
+
* The companion `TabsInit` script remains the source of truth at
|
|
42
|
+
* runtime — it re-derives the active tab from `localStorage` and
|
|
43
|
+
* `[data-tab-default]` and reapplies `hidden` / `aria-selected` so
|
|
44
|
+
* the SSR-rendered defaults survive group sync and View Transitions.
|
|
45
|
+
*/
|
|
46
|
+
export function TabItem({
|
|
47
|
+
label,
|
|
48
|
+
value,
|
|
49
|
+
default: isDefault,
|
|
50
|
+
children,
|
|
51
|
+
}: TabItemProps) {
|
|
52
|
+
return (
|
|
53
|
+
<div
|
|
54
|
+
class="tab-panel"
|
|
55
|
+
role="tabpanel"
|
|
56
|
+
data-tab-value={value ?? label}
|
|
57
|
+
data-tab-label={label}
|
|
58
|
+
// `data-tab-default={undefined}` omits the attribute entirely,
|
|
59
|
+
// matching the Astro template's conditional spread.
|
|
60
|
+
data-tab-default={isDefault ? "" : undefined}
|
|
61
|
+
// Render `hidden` only on non-default panels so the SSR markup
|
|
62
|
+
// shows the active panel immediately (no JS-required flash).
|
|
63
|
+
hidden={isDefault ? undefined : true}
|
|
64
|
+
>
|
|
65
|
+
{children}
|
|
66
|
+
</div>
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export default TabItem;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// Shared color-scheme state helpers for ThemeToggle (#2012 E3).
|
|
2
|
+
//
|
|
3
|
+
// Two ThemeToggle instances can be mounted at once (header + mobile
|
|
4
|
+
// sidebar footer). Each instance holds its own `mode` state, so a
|
|
5
|
+
// toggle in one used to leave the other's icon stale — the instances
|
|
6
|
+
// only read the DOM at mount. These helpers centralise the write path
|
|
7
|
+
// (`applyColorScheme`) and give every instance a subscription point
|
|
8
|
+
// (`subscribeColorSchemeChanged`) keyed on the `color-scheme-changed`
|
|
9
|
+
// window event, which `applyColorScheme` dispatches after mutating the
|
|
10
|
+
// DOM. The same event is already consumed by the zdtp design-token
|
|
11
|
+
// panel, so the event name is a cross-package contract — do not rename.
|
|
12
|
+
//
|
|
13
|
+
// This module is intentionally NOT marked "use client": zfb's island
|
|
14
|
+
// scanner registers every exported binding of a "use client" file as an
|
|
15
|
+
// island, and these helpers are plain functions, not components. They
|
|
16
|
+
// run in the browser only (called from the ThemeToggle island and
|
|
17
|
+
// unit tests).
|
|
18
|
+
|
|
19
|
+
export type ColorSchemeMode = "light" | "dark";
|
|
20
|
+
|
|
21
|
+
export const COLOR_SCHEME_CHANGED_EVENT = "color-scheme-changed";
|
|
22
|
+
|
|
23
|
+
const STORAGE_KEY = "zudo-doc-theme";
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Read the active color scheme from `<html data-theme>`. Falls back to
|
|
27
|
+
* `defaultMode` when the attribute is missing or holds an unexpected
|
|
28
|
+
* value (e.g. before the ColorSchemeProvider bootstrap script ran).
|
|
29
|
+
*/
|
|
30
|
+
export function readColorSchemeFromDom(
|
|
31
|
+
defaultMode: ColorSchemeMode,
|
|
32
|
+
): ColorSchemeMode {
|
|
33
|
+
const actual = document.documentElement.getAttribute("data-theme");
|
|
34
|
+
return actual === "light" || actual === "dark" ? actual : defaultMode;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Apply `next` as the active color scheme: mutate the DOM, persist the
|
|
39
|
+
* preference, and notify every subscriber (including other mounted
|
|
40
|
+
* ThemeToggle instances and the zdtp design-token panel) via the
|
|
41
|
+
* `color-scheme-changed` window event.
|
|
42
|
+
*
|
|
43
|
+
* Tweak-state reconciliation is intentionally NOT done here (#2037). The zdtp
|
|
44
|
+
* panel owns its own storage lifecycle: it persists the unified tweak envelope
|
|
45
|
+
* under `zudo-doc-tweak-state-v3` (auto-migrating the legacy
|
|
46
|
+
* `zudo-doc-tweak-state-v2` / `zudo-doc-tweak-state` keys into it), and its own
|
|
47
|
+
* `color-scheme-changed` listener clears applied inline styles and re-seeds the
|
|
48
|
+
* color slice from the newly active scheme. An earlier version of this function
|
|
49
|
+
* deleted `zudo-doc-tweak-state` + `-v2` on every toggle, which (a) targeted
|
|
50
|
+
* stale keys after zdtp moved to v3 — so it no longer did anything — and
|
|
51
|
+
* (b) when it did fire, wiped the whole envelope including scheme-independent
|
|
52
|
+
* spacing/typography/size tweaks, contradicting the documented carry-over
|
|
53
|
+
* guarantee. So the host no longer touches zdtp's private storage keys.
|
|
54
|
+
*
|
|
55
|
+
* Whether palette tweaks should instead persist per-scheme (so a light/dark
|
|
56
|
+
* round-trip keeps them) is a zdtp design question tracked upstream at
|
|
57
|
+
* Takazudo/zudo-design-token-panel#343. See zudo-doc#2037.
|
|
58
|
+
*/
|
|
59
|
+
export function applyColorScheme(next: ColorSchemeMode): void {
|
|
60
|
+
document.documentElement.setAttribute("data-theme", next);
|
|
61
|
+
document.documentElement.style.colorScheme = next;
|
|
62
|
+
localStorage.setItem(STORAGE_KEY, next);
|
|
63
|
+
window.dispatchEvent(new CustomEvent(COLOR_SCHEME_CHANGED_EVENT));
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Subscribe to color-scheme changes. Returns an unsubscribe function
|
|
68
|
+
* (suitable as a `useEffect` cleanup).
|
|
69
|
+
*/
|
|
70
|
+
export function subscribeColorSchemeChanged(listener: () => void): () => void {
|
|
71
|
+
window.addEventListener(COLOR_SCHEME_CHANGED_EVENT, listener);
|
|
72
|
+
return () => window.removeEventListener(COLOR_SCHEME_CHANGED_EVENT, listener);
|
|
73
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
/** @jsxRuntime automatic */
|
|
4
|
+
/** @jsxImportSource preact */
|
|
5
|
+
// BARE (non-island-wrapped) theme toggle — the single ThemeToggle
|
|
6
|
+
// implementation (#2012 E2). Published as the dedicated
|
|
7
|
+
// `@takazudo/zudo-doc/theme-toggle` subpath so hosts can compose it
|
|
8
|
+
// into their own `<Island>` wrappers (or nest it inside another island,
|
|
9
|
+
// e.g. the mobile sidebar footer) without inheriting an extra island
|
|
10
|
+
// layer. The island-wrapped variant for the `./theme` barrel lives in
|
|
11
|
+
// `../theme/theme-toggle.tsx`, which wraps this component.
|
|
12
|
+
//
|
|
13
|
+
// Use the preact hook entrypoints directly — zfb's esbuild step does
|
|
14
|
+
// not alias "react" to "preact/compat", so importing from "react" here
|
|
15
|
+
// would fail to resolve.
|
|
16
|
+
import { useState, useEffect } from "preact/hooks";
|
|
17
|
+
import {
|
|
18
|
+
applyColorScheme,
|
|
19
|
+
readColorSchemeFromDom,
|
|
20
|
+
subscribeColorSchemeChanged,
|
|
21
|
+
type ColorSchemeMode,
|
|
22
|
+
} from "./color-scheme-sync.js";
|
|
23
|
+
|
|
24
|
+
function SunIcon() {
|
|
25
|
+
return (
|
|
26
|
+
<svg
|
|
27
|
+
aria-hidden="true"
|
|
28
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
29
|
+
width="20"
|
|
30
|
+
height="20"
|
|
31
|
+
viewBox="0 0 24 24"
|
|
32
|
+
fill="none"
|
|
33
|
+
stroke="currentColor"
|
|
34
|
+
strokeWidth="2"
|
|
35
|
+
strokeLinecap="round"
|
|
36
|
+
strokeLinejoin="round"
|
|
37
|
+
>
|
|
38
|
+
<circle cx="12" cy="12" r="5" />
|
|
39
|
+
<line x1="12" y1="1" x2="12" y2="3" />
|
|
40
|
+
<line x1="12" y1="21" x2="12" y2="23" />
|
|
41
|
+
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64" />
|
|
42
|
+
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78" />
|
|
43
|
+
<line x1="1" y1="12" x2="3" y2="12" />
|
|
44
|
+
<line x1="21" y1="12" x2="23" y2="12" />
|
|
45
|
+
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36" />
|
|
46
|
+
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22" />
|
|
47
|
+
</svg>
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function MoonIcon() {
|
|
52
|
+
return (
|
|
53
|
+
<svg
|
|
54
|
+
aria-hidden="true"
|
|
55
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
56
|
+
width="20"
|
|
57
|
+
height="20"
|
|
58
|
+
viewBox="0 0 24 24"
|
|
59
|
+
fill="none"
|
|
60
|
+
stroke="currentColor"
|
|
61
|
+
strokeWidth="2"
|
|
62
|
+
strokeLinecap="round"
|
|
63
|
+
strokeLinejoin="round"
|
|
64
|
+
>
|
|
65
|
+
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z" />
|
|
66
|
+
</svg>
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export interface ThemeToggleProps {
|
|
71
|
+
defaultMode?: ColorSchemeMode;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// NAMED export (not default) on purpose: tsup compiles a default export
|
|
75
|
+
// to `export { ThemeToggle as default }`, an alias shape zfb's island
|
|
76
|
+
// scanner does not recognize — the island then never registers and the
|
|
77
|
+
// header toggle ships dead (zero hydration). Named exports compile to
|
|
78
|
+
// `export { ThemeToggle }`, which the scanner handles (same pattern as
|
|
79
|
+
// the package's MobileToc island).
|
|
80
|
+
export function ThemeToggle({
|
|
81
|
+
defaultMode = "dark",
|
|
82
|
+
}: ThemeToggleProps) {
|
|
83
|
+
// Initial state must match server render to avoid hydration mismatch.
|
|
84
|
+
// Actual theme is synced from DOM in useEffect below.
|
|
85
|
+
const [mode, setMode] = useState<ColorSchemeMode>(defaultMode);
|
|
86
|
+
|
|
87
|
+
useEffect(() => {
|
|
88
|
+
const sync = () => setMode(readColorSchemeFromDom(defaultMode));
|
|
89
|
+
sync();
|
|
90
|
+
// Cross-instance sync (#2012 E3): every mounted toggle re-reads the
|
|
91
|
+
// DOM whenever any instance (or the zdtp panel) applies a scheme,
|
|
92
|
+
// so the header toggle and the sidebar-footer toggle never disagree.
|
|
93
|
+
return subscribeColorSchemeChanged(sync);
|
|
94
|
+
}, []); // eslint-disable-line react-hooks/exhaustive-deps
|
|
95
|
+
|
|
96
|
+
function toggle() {
|
|
97
|
+
const next = mode === "dark" ? "light" : "dark";
|
|
98
|
+
setMode(next);
|
|
99
|
+
applyColorScheme(next);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const nextMode = mode === "dark" ? "light" : "dark";
|
|
103
|
+
|
|
104
|
+
return (
|
|
105
|
+
<button
|
|
106
|
+
onClick={toggle}
|
|
107
|
+
aria-label={`Switch to ${nextMode} mode`}
|
|
108
|
+
className="text-muted hover:text-fg transition-colors p-hsp-sm focus-visible:outline-2 focus-visible:outline-accent focus-visible:outline-offset-2"
|
|
109
|
+
>
|
|
110
|
+
{mode === "dark" ? <SunIcon /> : <MoonIcon />}
|
|
111
|
+
</button>
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
// Pin the island marker name to "ThemeToggle" regardless of bundler
|
|
115
|
+
// identifier mangling: zfb's Island() derives the SSR marker via
|
|
116
|
+
// `displayName ?? name`, and esbuild may rename the function when
|
|
117
|
+
// another binding shares the name in the same bundle. Setting
|
|
118
|
+
// displayName explicitly keeps the emitted marker aligned with the
|
|
119
|
+
// island-manifest entry. zudolab/zudo-doc#1446.
|
|
120
|
+
ThemeToggle.displayName = "ThemeToggle";
|
package/eject/toc/cx.ts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tiny `clsx`-style class name joiner. Accepts strings, falsy values,
|
|
3
|
+
* and arrays/objects of the same — only truthy strings survive.
|
|
4
|
+
*
|
|
5
|
+
* Framework primitives keep their dependency surface minimal so that a
|
|
6
|
+
* downstream consumer of `@takazudo/zudo-doc/toc` does not need an extra
|
|
7
|
+
* runtime dep just for class name composition. The behavior here is the
|
|
8
|
+
* subset the TOC primitives use; see `clsx` for the full feature set.
|
|
9
|
+
*/
|
|
10
|
+
type ClassValue =
|
|
11
|
+
| string
|
|
12
|
+
| number
|
|
13
|
+
| bigint
|
|
14
|
+
| boolean
|
|
15
|
+
| null
|
|
16
|
+
| undefined
|
|
17
|
+
| ClassValue[]
|
|
18
|
+
| { [key: string]: unknown };
|
|
19
|
+
|
|
20
|
+
export function cx(...args: ClassValue[]): string {
|
|
21
|
+
const out: string[] = [];
|
|
22
|
+
for (const arg of args) {
|
|
23
|
+
if (!arg) continue;
|
|
24
|
+
if (typeof arg === "string") {
|
|
25
|
+
out.push(arg);
|
|
26
|
+
} else if (typeof arg === "number" || typeof arg === "bigint") {
|
|
27
|
+
out.push(String(arg));
|
|
28
|
+
} else if (Array.isArray(arg)) {
|
|
29
|
+
const inner = cx(...arg);
|
|
30
|
+
if (inner) out.push(inner);
|
|
31
|
+
} else if (typeof arg === "object") {
|
|
32
|
+
for (const key of Object.keys(arg)) {
|
|
33
|
+
if ((arg as Record<string, unknown>)[key]) out.push(key);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return out.join(" ");
|
|
38
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export { Toc } from "./toc.js";
|
|
2
|
+
export type { TocProps } from "./toc.js";
|
|
3
|
+
export { MobileToc } from "./mobile-toc.js";
|
|
4
|
+
export type { MobileTocProps } from "./mobile-toc.js";
|
|
5
|
+
export { useActiveHeading, getActiveHeadingId } from "./use-active-heading.js";
|
|
6
|
+
export type { UseActiveHeadingResult } from "./use-active-heading.js";
|
|
7
|
+
export type { HeadingItem } from "./types.js";
|
|
8
|
+
// Exposed so consumers wiring their own scanner-visible Toc/MobileToc shims
|
|
9
|
+
// (the override pattern from zudolab/zudo-doc#2057) can derive the locale TOC
|
|
10
|
+
// label from the page `lang` without hand-mirroring the lang→title map.
|
|
11
|
+
export { getTocTitle } from "./toc-title.js";
|