@takazudo/zudo-doc 3.2.0 → 4.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/CHANGELOG.md +61 -0
- package/README.md +2 -2
- package/bin/tag-cli-config.ts +126 -0
- package/bin/tags-audit-runner.ts +60 -76
- package/bin/tags-audit.mjs +17 -36
- package/bin/tags-suggest-runner.ts +429 -0
- package/bin/tags-suggest.mjs +30 -0
- package/bin/zudo-doc.mjs +78 -25
- package/dist/breadcrumb/breadcrumb.d.ts +4 -4
- package/dist/breadcrumb/find-path.d.ts +2 -2
- package/dist/breadcrumb/index.d.ts +1 -1
- package/dist/breadcrumb/types.d.ts +0 -5
- package/dist/chrome/derive.d.ts +16 -4
- package/dist/chrome/derive.js +64 -4
- package/dist/chrome/index.d.ts +13 -10
- package/dist/chrome/index.js +12 -6
- package/dist/chrome/primary-slots.d.ts +21 -0
- package/dist/chrome/primary-slots.js +59 -0
- package/dist/chrome-bindings.d.ts +227 -0
- package/dist/chrome-bindings.js +6 -0
- package/dist/code-syntax/code-block-enhancer-script.d.ts +4 -0
- package/dist/code-syntax/code-block-enhancer-script.js +7 -4
- package/dist/code-syntax/code-block-enhancer.d.ts +2 -2
- package/dist/code-syntax/code-block-enhancer.js +1 -3
- package/dist/code-syntax/index.d.ts +5 -5
- package/dist/code-syntax/index.js +4 -13
- package/dist/code-syntax/mermaid-init-script.d.ts +1 -22
- package/dist/code-syntax/mermaid-init-script.js +0 -2
- package/dist/code-syntax/mermaid-init.d.ts +0 -1
- package/dist/code-syntax/mermaid-init.js +3 -4
- package/dist/code-syntax/tabs-init.d.ts +0 -1
- package/dist/code-syntax/tabs-init.js +1 -3
- package/dist/code-syntax/tabs.d.ts +0 -1
- package/dist/code-syntax/tabs.js +1 -3
- package/dist/color-scheme-utils.d.ts +72 -4
- package/dist/color-scheme-utils.js +137 -0
- package/dist/color-schemes-defaults/index.d.ts +23 -0
- package/dist/color-schemes-defaults/index.js +134 -0
- package/dist/config.d.ts +459 -0
- package/dist/config.js +125 -0
- package/dist/content/component-map.d.ts +0 -16
- package/dist/content/component-map.js +2 -4
- package/dist/content/index.d.ts +1 -1
- package/dist/content/index.js +2 -3
- package/dist/content.css +1 -1
- package/dist/design-token-panel-bootstrap.d.ts +82 -27
- package/dist/design-token-panel-bootstrap.js +110 -21
- package/dist/design-token-panel-config/index.d.ts +49 -0
- package/dist/design-token-panel-config/index.js +211 -0
- package/dist/design-token-panel-config/manifest.d.ts +46 -0
- package/dist/design-token-panel-config/manifest.js +105 -0
- package/dist/directive-vocabulary-defaults/index.d.ts +16 -0
- package/dist/directive-vocabulary-defaults/index.js +12 -0
- package/dist/doc-body-end-islands/design-token-panel-island.d.ts +15 -0
- package/dist/doc-body-end-islands/design-token-panel-island.js +31 -0
- package/dist/doc-body-end-islands/index.d.ts +52 -7
- package/dist/doc-body-end-islands/index.js +19 -0
- package/dist/doc-body-end-islands/theme-pack-switcher-island.d.ts +37 -0
- package/dist/doc-body-end-islands/theme-pack-switcher-island.js +18 -0
- package/dist/doc-content-header/index.js +1 -1
- package/dist/doc-history-area/index.d.ts +10 -4
- package/dist/doc-history-area/index.js +3 -2
- package/dist/doc-metainfo-area/index.d.ts +1 -0
- package/dist/doc-page-props/index.d.ts +7 -23
- package/dist/doc-page-renderer/index.d.ts +1 -0
- package/dist/doc-page-renderer/index.js +1 -0
- package/dist/doc-page-shell/index.js +19 -12
- package/dist/doc-pager/index.js +1 -1
- package/dist/doc-route-entries/index.d.ts +2 -2
- package/dist/doclayout/doc-layout-with-defaults.js +4 -4
- package/dist/doclayout/doc-layout.d.ts +8 -0
- package/dist/doclayout/doc-layout.js +10 -1
- package/dist/docs-schema/index.d.ts +67 -0
- package/dist/docs-schema/index.js +43 -0
- package/dist/eject/index.d.ts +16 -0
- package/dist/eject/index.js +122 -28
- package/dist/extract-headings/index.d.ts +5 -8
- package/dist/extract-headings/index.js +2 -9
- package/dist/factory-context/index.d.ts +56 -4
- package/dist/features.css +65 -43
- package/dist/find-in-page/find-bar.d.ts +9 -0
- package/dist/find-in-page/find-bar.js +114 -0
- package/dist/find-in-page/find-in-page.d.ts +17 -0
- package/dist/find-in-page/find-in-page.js +131 -0
- package/dist/find-in-page/index.d.ts +11 -0
- package/dist/find-in-page/index.js +49 -0
- package/dist/footer/footer.js +1 -0
- package/dist/frontmatter-preview-defaults/index.d.ts +16 -0
- package/dist/frontmatter-preview-defaults/index.js +25 -0
- package/dist/head-with-defaults/index.d.ts +2 -0
- package/dist/head-with-defaults/index.js +16 -0
- package/dist/header/header.d.ts +10 -5
- package/dist/header/header.js +45 -5
- package/dist/header/index.d.ts +1 -1
- package/dist/header/types.d.ts +30 -1
- package/dist/header-with-defaults/index.js +1 -0
- package/dist/home-page/index.d.ts +2 -0
- package/dist/home-page/index.js +11 -5
- package/dist/home-page/prepare-home-data.js +1 -1
- package/dist/i18n-defaults/index.d.ts +22 -0
- package/dist/i18n-defaults/index.js +167 -0
- package/dist/locale-merge/index.d.ts +9 -14
- package/dist/locale-merge/index.js +6 -4
- package/dist/mdx-components/index.js +4 -4
- package/dist/plugins/claude-resources.d.ts +1 -0
- package/dist/plugins/claude-resources.js +4 -2
- package/dist/plugins/doc-history.js +1 -1
- package/dist/{integrations → plugins/internal}/claude-resources/index.d.ts +1 -16
- package/dist/{integrations → plugins/internal}/claude-resources/index.js +0 -9
- package/dist/{integrations → plugins/internal}/doc-history/index.d.ts +0 -17
- package/dist/{integrations → plugins/internal}/doc-history/index.js +0 -4
- package/dist/{integrations → plugins/internal}/doc-history/pre-build.d.ts +2 -4
- package/dist/plugins/internal/llms-txt/index.d.ts +7 -0
- package/dist/{integrations → plugins/internal}/llms-txt/load.d.ts +1 -1
- package/dist/{integrations → plugins/internal}/llms-txt/load.js +2 -2
- package/dist/{integrations → plugins/internal}/llms-txt/strip.d.ts +2 -3
- package/dist/{integrations → plugins/internal}/llms-txt/strip.js +1 -1
- package/dist/{integrations → plugins/internal}/llms-txt/types.d.ts +13 -22
- package/dist/{integrations → plugins/internal}/search-index/collect.js +1 -1
- package/dist/plugins/internal/theme-packs/copy.d.ts +32 -0
- package/dist/plugins/internal/theme-packs/copy.js +45 -0
- package/dist/plugins/internal/theme-packs/dev-middleware.d.ts +22 -0
- package/dist/plugins/internal/theme-packs/dev-middleware.js +80 -0
- package/dist/plugins/internal/theme-packs/index.d.ts +6 -0
- package/dist/plugins/internal/theme-packs/index.js +9 -0
- package/dist/plugins/internal/theme-packs/resolve.d.ts +17 -0
- package/dist/plugins/internal/theme-packs/resolve.js +17 -0
- package/dist/plugins/internal/theme-packs/types.d.ts +22 -0
- package/dist/plugins/internal/theme-packs/types.js +0 -0
- package/dist/plugins/llms-txt.js +1 -1
- package/dist/plugins/routes.js +55 -21
- package/dist/plugins/search-index.js +1 -1
- package/dist/plugins/theme-packs.d.ts +3 -0
- package/dist/plugins/theme-packs.js +40 -0
- package/dist/preset.d.ts +28 -14
- package/dist/preset.js +24 -9
- package/dist/route-context/index.js +4 -6
- package/dist/route-enumerators/index.d.ts +6 -18
- package/dist/route-enumerators/index.js +8 -6
- package/dist/routes/404.js +3 -1
- package/dist/routes/_chrome.js +3 -2
- package/dist/routes/_context.d.ts +7 -3
- package/dist/routes/_context.js +2 -0
- package/dist/routes/_docs-helpers.js +9 -21
- package/dist/safelist.css +1 -1
- package/dist/settings.d.ts +64 -12
- package/dist/sidebar-tree/build-tree.d.ts +3 -4
- package/dist/sidebar-tree/build-tree.js +4 -3
- package/dist/sidebar-tree/index.d.ts +2 -2
- package/dist/sidebar-tree/types.d.ts +6 -17
- package/dist/site-tree-nav-island/index.d.ts +3 -1
- package/dist/site-tree-nav-island/index.js +17 -5
- package/dist/site-tree-nav-island/state.d.ts +4 -0
- package/dist/site-tree-nav-island/state.js +10 -0
- package/dist/tag-helpers/index.d.ts +6 -13
- package/dist/tag-helpers/index.js +5 -23
- package/dist/tag-pages/index.d.ts +8 -21
- package/dist/tag-pages/index.js +14 -10
- package/dist/tags-audit.d.ts +16 -44
- package/dist/tags-audit.js +9 -172
- package/dist/theme/color-scheme-provider.d.ts +2 -3
- package/dist/theme/color-scheme-provider.js +2 -10
- package/dist/theme/index.d.ts +1 -4
- package/dist/theme/index.js +2 -30
- package/dist/theme/theme-pack-provider.d.ts +42 -0
- package/dist/theme/theme-pack-provider.js +75 -0
- package/dist/theme-cli/apply.d.ts +16 -0
- package/dist/theme-cli/apply.js +61 -0
- package/dist/theme-cli/config-io.d.ts +15 -0
- package/dist/theme-cli/config-io.js +51 -0
- package/dist/theme-cli/config-rewriter.d.ts +21 -0
- package/dist/theme-cli/config-rewriter.js +141 -0
- package/dist/theme-cli/config-scanner.d.ts +63 -0
- package/dist/theme-cli/config-scanner.js +288 -0
- package/dist/theme-cli/index.d.ts +7 -0
- package/dist/theme-cli/index.js +38 -0
- package/dist/theme-cli/list.d.ts +27 -0
- package/dist/theme-cli/list.js +64 -0
- package/dist/theme-cli/provenance.d.ts +17 -0
- package/dist/theme-cli/provenance.js +35 -0
- package/dist/theme-cli/registry.d.ts +14 -0
- package/dist/theme-cli/registry.js +13 -0
- package/dist/theme-pack-dialog/dialog-state.d.ts +25 -0
- package/dist/theme-pack-dialog/dialog-state.js +40 -0
- package/dist/theme-pack-dialog/index.d.ts +5 -0
- package/dist/theme-pack-dialog/index.js +152 -0
- package/dist/theme-pack-dialog/theme-pack-card.d.ts +25 -0
- package/dist/theme-pack-dialog/theme-pack-card.js +72 -0
- package/dist/theme-pack-switcher/index.d.ts +49 -0
- package/dist/theme-pack-switcher/index.js +205 -0
- package/dist/theme-pack-switcher/switcher-state.d.ts +56 -0
- package/dist/theme-pack-switcher/switcher-state.js +43 -0
- package/dist/theme-pack-switcher/theme-pack-sync.d.ts +85 -0
- package/dist/theme-pack-switcher/theme-pack-sync.js +121 -0
- package/dist/theme-packs/beacon/fonts/AtkinsonHyperlegible-400-latin.woff2 +0 -0
- package/dist/theme-packs/beacon/fonts/AtkinsonHyperlegible-700-latin.woff2 +0 -0
- package/dist/theme-packs/beacon/fonts/AtkinsonHyperlegible-italic-400-latin.woff2 +0 -0
- package/dist/theme-packs/beacon/fonts/AtkinsonHyperlegible-italic-700-latin.woff2 +0 -0
- package/dist/theme-packs/beacon/fonts/AtkinsonHyperlegibleMono-italic-latin.woff2 +0 -0
- package/dist/theme-packs/beacon/fonts/AtkinsonHyperlegibleMono-latin.woff2 +0 -0
- package/dist/theme-packs/beacon/fonts/OFL.txt +94 -0
- package/dist/theme-packs/beacon/meta.json +37 -0
- package/dist/theme-packs/beacon/pack.css +442 -0
- package/dist/theme-packs/broadsheet/fonts/CourierPrime-400-latin.woff2 +0 -0
- package/dist/theme-packs/broadsheet/fonts/CourierPrime-700-latin.woff2 +0 -0
- package/dist/theme-packs/broadsheet/fonts/OFL.txt +95 -0
- package/dist/theme-packs/broadsheet/fonts/PlayfairDisplay-italic-latin.woff2 +0 -0
- package/dist/theme-packs/broadsheet/fonts/PlayfairDisplay-latin.woff2 +0 -0
- package/dist/theme-packs/broadsheet/fonts/SourceSerif4-italic-latin.woff2 +0 -0
- package/dist/theme-packs/broadsheet/fonts/SourceSerif4-latin.woff2 +0 -0
- package/dist/theme-packs/broadsheet/meta.json +38 -0
- package/dist/theme-packs/broadsheet/pack.css +448 -0
- package/dist/theme-packs/brutalist/fonts/ArchivoBlack-latin.woff2 +0 -0
- package/dist/theme-packs/brutalist/fonts/IBMPlexMono-400-latin.woff2 +0 -0
- package/dist/theme-packs/brutalist/fonts/IBMPlexMono-500-latin.woff2 +0 -0
- package/dist/theme-packs/brutalist/fonts/IBMPlexMono-700-latin.woff2 +0 -0
- package/dist/theme-packs/brutalist/fonts/OFL.txt +95 -0
- package/dist/theme-packs/brutalist/fonts/SpaceGrotesk-latin.woff2 +0 -0
- package/dist/theme-packs/brutalist/meta.json +38 -0
- package/dist/theme-packs/brutalist/pack.css +546 -0
- package/dist/theme-packs/default/meta.json +37 -0
- package/dist/theme-packs/drift/fonts/IBMPlexMono-400-latin-ext.woff2 +0 -0
- package/dist/theme-packs/drift/fonts/IBMPlexMono-400-latin.woff2 +0 -0
- package/dist/theme-packs/drift/fonts/IBMPlexMono-500-latin-ext.woff2 +0 -0
- package/dist/theme-packs/drift/fonts/IBMPlexMono-500-latin.woff2 +0 -0
- package/dist/theme-packs/drift/fonts/IBMPlexSans-italic-latin.woff2 +0 -0
- package/dist/theme-packs/drift/fonts/IBMPlexSans-latin-ext.woff2 +0 -0
- package/dist/theme-packs/drift/fonts/IBMPlexSans-latin.woff2 +0 -0
- package/dist/theme-packs/drift/fonts/OFL.txt +93 -0
- package/dist/theme-packs/drift/meta.json +37 -0
- package/dist/theme-packs/drift/pack.css +478 -0
- package/dist/theme-packs/fjord/fonts/Inter-latin-ext.woff2 +0 -0
- package/dist/theme-packs/fjord/fonts/Inter-latin.woff2 +0 -0
- package/dist/theme-packs/fjord/fonts/JetBrainsMono-latin-ext.woff2 +0 -0
- package/dist/theme-packs/fjord/fonts/JetBrainsMono-latin.woff2 +0 -0
- package/dist/theme-packs/fjord/fonts/OFL.txt +94 -0
- package/dist/theme-packs/fjord/meta.json +37 -0
- package/dist/theme-packs/fjord/pack.css +375 -0
- package/dist/theme-packs/foundry/fonts/Inter-latin-ext.woff2 +0 -0
- package/dist/theme-packs/foundry/fonts/Inter-latin.woff2 +0 -0
- package/dist/theme-packs/foundry/fonts/OFL.txt +93 -0
- package/dist/theme-packs/foundry/meta.json +37 -0
- package/dist/theme-packs/foundry/pack.css +202 -0
- package/dist/theme-packs/futura-editorial/fonts/Jost-latin.woff2 +0 -0
- package/dist/theme-packs/futura-editorial/fonts/NotoSans-italic-latin.woff2 +0 -0
- package/dist/theme-packs/futura-editorial/fonts/NotoSans-latin.woff2 +0 -0
- package/dist/theme-packs/futura-editorial/fonts/OFL.txt +95 -0
- package/dist/theme-packs/futura-editorial/fonts/SpaceMono-400-latin.woff2 +0 -0
- package/dist/theme-packs/futura-editorial/fonts/SpaceMono-700-latin.woff2 +0 -0
- package/dist/theme-packs/futura-editorial/meta.json +38 -0
- package/dist/theme-packs/futura-editorial/pack.css +313 -0
- package/dist/theme-packs/hearth/fonts/Fraunces-italic-latin.woff2 +0 -0
- package/dist/theme-packs/hearth/fonts/Fraunces-latin.woff2 +0 -0
- package/dist/theme-packs/hearth/fonts/Nunito-latin.woff2 +0 -0
- package/dist/theme-packs/hearth/fonts/OFL.txt +95 -0
- package/dist/theme-packs/hearth/fonts/SplineSansMono-latin.woff2 +0 -0
- package/dist/theme-packs/hearth/meta.json +38 -0
- package/dist/theme-packs/hearth/pack.css +385 -0
- package/dist/theme-packs/hollow/fonts/OFL.txt +94 -0
- package/dist/theme-packs/hollow/fonts/SpaceGrotesk-latin.woff2 +0 -0
- package/dist/theme-packs/hollow/fonts/SpaceMono-400-italic-latin.woff2 +0 -0
- package/dist/theme-packs/hollow/fonts/SpaceMono-400-latin.woff2 +0 -0
- package/dist/theme-packs/hollow/fonts/SpaceMono-700-latin.woff2 +0 -0
- package/dist/theme-packs/hollow/meta.json +37 -0
- package/dist/theme-packs/hollow/pack.css +428 -0
- package/dist/theme-packs/ledger/fonts/CrimsonPro-latin-ext-italic.woff2 +0 -0
- package/dist/theme-packs/ledger/fonts/CrimsonPro-latin-ext.woff2 +0 -0
- package/dist/theme-packs/ledger/fonts/CrimsonPro-latin-italic.woff2 +0 -0
- package/dist/theme-packs/ledger/fonts/CrimsonPro-latin.woff2 +0 -0
- package/dist/theme-packs/ledger/fonts/IBMPlexMono-400-latin-ext.woff2 +0 -0
- package/dist/theme-packs/ledger/fonts/IBMPlexMono-400-latin.woff2 +0 -0
- package/dist/theme-packs/ledger/fonts/IBMPlexMono-500-latin-ext.woff2 +0 -0
- package/dist/theme-packs/ledger/fonts/IBMPlexMono-500-latin.woff2 +0 -0
- package/dist/theme-packs/ledger/fonts/OFL.txt +94 -0
- package/dist/theme-packs/ledger/meta.json +37 -0
- package/dist/theme-packs/ledger/pack.css +463 -0
- package/dist/theme-packs/manuscript/fonts/CourierPrime-400-latin-ext.woff2 +0 -0
- package/dist/theme-packs/manuscript/fonts/CourierPrime-400-latin.woff2 +0 -0
- package/dist/theme-packs/manuscript/fonts/CourierPrime-700-latin-ext.woff2 +0 -0
- package/dist/theme-packs/manuscript/fonts/CourierPrime-700-latin.woff2 +0 -0
- package/dist/theme-packs/manuscript/fonts/EBGaramond-latin-italic.woff2 +0 -0
- package/dist/theme-packs/manuscript/fonts/EBGaramond-latin.woff2 +0 -0
- package/dist/theme-packs/manuscript/fonts/OFL.txt +94 -0
- package/dist/theme-packs/manuscript/meta.json +37 -0
- package/dist/theme-packs/manuscript/pack.css +376 -0
- package/dist/theme-packs/matcha/fonts/MPLUS1Code-latin.woff2 +0 -0
- package/dist/theme-packs/matcha/fonts/OFL.txt +95 -0
- package/dist/theme-packs/matcha/fonts/ShipporiMincho-500-latin.woff2 +0 -0
- package/dist/theme-packs/matcha/fonts/ShipporiMincho-700-latin.woff2 +0 -0
- package/dist/theme-packs/matcha/fonts/ZenKakuGothicNew-400-latin.woff2 +0 -0
- package/dist/theme-packs/matcha/fonts/ZenKakuGothicNew-500-latin.woff2 +0 -0
- package/dist/theme-packs/matcha/meta.json +38 -0
- package/dist/theme-packs/matcha/pack.css +409 -0
- package/dist/theme-packs/nocturne/fonts/CormorantGaramond-italic-latin.woff2 +0 -0
- package/dist/theme-packs/nocturne/fonts/CormorantGaramond-latin.woff2 +0 -0
- package/dist/theme-packs/nocturne/fonts/IBMPlexMono-400-latin.woff2 +0 -0
- package/dist/theme-packs/nocturne/fonts/IBMPlexMono-500-latin.woff2 +0 -0
- package/dist/theme-packs/nocturne/fonts/IBMPlexMono-italic-latin.woff2 +0 -0
- package/dist/theme-packs/nocturne/fonts/Manrope-latin.woff2 +0 -0
- package/dist/theme-packs/nocturne/fonts/OFL.txt +95 -0
- package/dist/theme-packs/nocturne/meta.json +38 -0
- package/dist/theme-packs/nocturne/pack.css +502 -0
- package/dist/theme-packs/observatory/fonts/JosefinSans-latin.woff2 +0 -0
- package/dist/theme-packs/observatory/fonts/Jost-italic-latin.woff2 +0 -0
- package/dist/theme-packs/observatory/fonts/Jost-latin.woff2 +0 -0
- package/dist/theme-packs/observatory/fonts/OFL.txt +95 -0
- package/dist/theme-packs/observatory/fonts/SpaceMono-400-latin.woff2 +0 -0
- package/dist/theme-packs/observatory/fonts/SpaceMono-700-latin.woff2 +0 -0
- package/dist/theme-packs/observatory/fonts/SpaceMono-italic-latin.woff2 +0 -0
- package/dist/theme-packs/observatory/meta.json +38 -0
- package/dist/theme-packs/observatory/pack.css +728 -0
- package/dist/theme-packs/onyx/fonts/CormorantGaramond-italic-latin.woff2 +0 -0
- package/dist/theme-packs/onyx/fonts/CormorantGaramond-latin.woff2 +0 -0
- package/dist/theme-packs/onyx/fonts/IBMPlexMono-400-latin-ext.woff2 +0 -0
- package/dist/theme-packs/onyx/fonts/IBMPlexMono-400-latin.woff2 +0 -0
- package/dist/theme-packs/onyx/fonts/IBMPlexMono-500-latin-ext.woff2 +0 -0
- package/dist/theme-packs/onyx/fonts/IBMPlexMono-500-latin.woff2 +0 -0
- package/dist/theme-packs/onyx/fonts/Jost-latin.woff2 +0 -0
- package/dist/theme-packs/onyx/fonts/OFL.txt +95 -0
- package/dist/theme-packs/onyx/meta.json +38 -0
- package/dist/theme-packs/onyx/pack.css +497 -0
- package/dist/theme-packs/phosphor/fonts/JetBrainsMono-latin-ext.woff2 +0 -0
- package/dist/theme-packs/phosphor/fonts/JetBrainsMono-latin.woff2 +0 -0
- package/dist/theme-packs/phosphor/fonts/OFL.txt +94 -0
- package/dist/theme-packs/phosphor/fonts/VT323-latin-ext.woff2 +0 -0
- package/dist/theme-packs/phosphor/fonts/VT323-latin.woff2 +0 -0
- package/dist/theme-packs/phosphor/meta.json +38 -0
- package/dist/theme-packs/phosphor/pack.css +493 -0
- package/dist/theme-packs/solar/fonts/OFL.txt +94 -0
- package/dist/theme-packs/solar/fonts/SourceCodePro-italic-latin.woff2 +0 -0
- package/dist/theme-packs/solar/fonts/SourceCodePro-latin.woff2 +0 -0
- package/dist/theme-packs/solar/fonts/SourceSans3-italic-latin.woff2 +0 -0
- package/dist/theme-packs/solar/fonts/SourceSans3-latin.woff2 +0 -0
- package/dist/theme-packs/solar/meta.json +37 -0
- package/dist/theme-packs/solar/pack.css +380 -0
- package/dist/theme-packs/sumi/fonts/IBMPlexMono-400-latin-ext.woff2 +0 -0
- package/dist/theme-packs/sumi/fonts/IBMPlexMono-400-latin.woff2 +0 -0
- package/dist/theme-packs/sumi/fonts/IBMPlexMono-500-latin-ext.woff2 +0 -0
- package/dist/theme-packs/sumi/fonts/IBMPlexMono-500-latin.woff2 +0 -0
- package/dist/theme-packs/sumi/fonts/OFL.txt +95 -0
- package/dist/theme-packs/sumi/fonts/ShipporiMinchoB1-600-latin.woff2 +0 -0
- package/dist/theme-packs/sumi/fonts/ShipporiMinchoB1-700-latin.woff2 +0 -0
- package/dist/theme-packs/sumi/fonts/ShipporiMinchoB1-800-latin.woff2 +0 -0
- package/dist/theme-packs/sumi/fonts/ZenKakuGothicNew-400-latin.woff2 +0 -0
- package/dist/theme-packs/sumi/fonts/ZenKakuGothicNew-500-latin.woff2 +0 -0
- package/dist/theme-packs/sumi/meta.json +38 -0
- package/dist/theme-packs/sumi/pack.css +502 -0
- package/dist/theme-packs/swissgrid/fonts/IBMPlexMono-400-latin-ext.woff2 +0 -0
- package/dist/theme-packs/swissgrid/fonts/IBMPlexMono-400-latin.woff2 +0 -0
- package/dist/theme-packs/swissgrid/fonts/IBMPlexMono-600-latin.woff2 +0 -0
- package/dist/theme-packs/swissgrid/fonts/Inter-latin-ext.woff2 +0 -0
- package/dist/theme-packs/swissgrid/fonts/Inter-latin.woff2 +0 -0
- package/dist/theme-packs/swissgrid/fonts/InterTight-latin.woff2 +0 -0
- package/dist/theme-packs/swissgrid/fonts/OFL.txt +95 -0
- package/dist/theme-packs/swissgrid/meta.json +38 -0
- package/dist/theme-packs/swissgrid/pack.css +518 -0
- package/dist/theme-packs/washi/fonts/MPlus1Code-400-latin.woff2 +0 -0
- package/dist/theme-packs/washi/fonts/MPlus1Code-500-latin.woff2 +0 -0
- package/dist/theme-packs/washi/fonts/OFL.txt +95 -0
- package/dist/theme-packs/washi/fonts/ShipporiMincho-500-latin.woff2 +0 -0
- package/dist/theme-packs/washi/fonts/ShipporiMincho-600-latin.woff2 +0 -0
- package/dist/theme-packs/washi/fonts/ShipporiMincho-700-latin.woff2 +0 -0
- package/dist/theme-packs/washi/fonts/ZenKakuGothicNew-400-latin.woff2 +0 -0
- package/dist/theme-packs/washi/fonts/ZenKakuGothicNew-500-latin.woff2 +0 -0
- package/dist/theme-packs/washi/fonts/ZenKakuGothicNew-700-latin.woff2 +0 -0
- package/dist/theme-packs/washi/meta.json +38 -0
- package/dist/theme-packs/washi/pack.css +479 -0
- package/dist/theme-packs-registry/index.d.ts +5 -0
- package/dist/theme-packs-registry/index.js +30 -0
- package/dist/theme-packs-registry/load-registry.d.ts +23 -0
- package/dist/theme-packs-registry/load-registry.js +64 -0
- package/dist/theme-packs-registry/meta-schema.d.ts +70 -0
- package/dist/theme-packs-registry/meta-schema.js +38 -0
- package/dist/theme-packs-registry/resolve-enabled-packs.d.ts +25 -0
- package/dist/theme-packs-registry/resolve-enabled-packs.js +43 -0
- package/dist/theme-packs-registry/token-manifest.d.ts +19 -0
- package/dist/theme-packs-registry/token-manifest.js +57 -0
- package/dist/theme-packs-registry/validator.d.ts +35 -0
- package/dist/theme-packs-registry/validator.js +284 -0
- package/dist/theme-toggle/color-scheme-sync.d.ts +2 -4
- package/dist/theme.css +319 -0
- package/dist/versions-page/index.d.ts +2 -2
- package/dist/versions-page/index.js +8 -8
- package/dist/z-index-defaults/index.d.ts +45 -0
- package/dist/z-index-defaults/index.js +34 -0
- package/eject/breadcrumb/breadcrumb.tsx +4 -4
- package/eject/breadcrumb/find-path.ts +2 -2
- package/eject/breadcrumb/index.ts +1 -1
- package/eject/breadcrumb/types.ts +0 -6
- package/eject/code-group/index.tsx +2 -2
- package/eject/doc-history/index.tsx +1 -1
- package/eject/doc-pager/index.tsx +1 -1
- package/eject/footer/footer.tsx +1 -0
- package/eject/header/header.tsx +86 -21
- package/eject/header/index.ts +3 -0
- package/eject/header/types.ts +39 -1
- package/eject/site-tree-nav-island/index.tsx +15 -3
- package/eject/site-tree-nav-island/state.ts +9 -0
- package/eject/theme-toggle/color-scheme-sync.ts +2 -4
- package/package.json +82 -29
- package/routes-src/404.tsx +4 -1
- package/routes-src/_chrome.tsx +31 -8
- package/routes-src/_context.ts +4 -0
- package/routes-src/_docs-helpers.ts +9 -29
- package/routes-src/_virtual.d.ts +38 -2
- package/tsconfig.base.json +29 -0
- package/virtual-modules.d.ts +83 -0
- package/zfb-config-shim.d.ts +210 -0
- package/dist/integrations/llms-txt/index.d.ts +0 -33
- package/dist/theme/color-tweak-export-modal.d.ts +0 -16
- package/dist/theme/color-tweak-export-modal.js +0 -138
- package/dist/theme/design-token-serde.d.ts +0 -183
- package/dist/theme/design-token-serde.js +0 -346
- package/dist/theme/design-token-types.d.ts +0 -13
- package/dist/theme/design-token-types.js +0 -6
- package/dist/theme/iframe-bridge.d.ts +0 -42
- package/dist/theme/iframe-bridge.js +0 -72
- /package/dist/{integrations → plugins/internal}/claude-resources/escape-for-mdx.d.ts +0 -0
- /package/dist/{integrations → plugins/internal}/claude-resources/escape-for-mdx.js +0 -0
- /package/dist/{integrations → plugins/internal}/claude-resources/generate.d.ts +0 -0
- /package/dist/{integrations → plugins/internal}/claude-resources/generate.js +0 -0
- /package/dist/{integrations → plugins/internal}/doc-history/pre-build.js +0 -0
- /package/dist/{integrations → plugins/internal}/llms-txt/dev-middleware.d.ts +0 -0
- /package/dist/{integrations → plugins/internal}/llms-txt/dev-middleware.js +0 -0
- /package/dist/{integrations → plugins/internal}/llms-txt/emit.d.ts +0 -0
- /package/dist/{integrations → plugins/internal}/llms-txt/emit.js +0 -0
- /package/dist/{integrations → plugins/internal}/llms-txt/generate.d.ts +0 -0
- /package/dist/{integrations → plugins/internal}/llms-txt/generate.js +0 -0
- /package/dist/{integrations → plugins/internal}/llms-txt/index.js +0 -0
- /package/dist/{integrations → plugins/internal}/llms-txt/types.js +0 -0
- /package/dist/{integrations → plugins/internal}/search-index/build-emitter.d.ts +0 -0
- /package/dist/{integrations → plugins/internal}/search-index/build-emitter.js +0 -0
- /package/dist/{integrations → plugins/internal}/search-index/collect.d.ts +0 -0
- /package/dist/{integrations → plugins/internal}/search-index/dev-middleware.d.ts +0 -0
- /package/dist/{integrations → plugins/internal}/search-index/dev-middleware.js +0 -0
- /package/dist/{integrations → plugins/internal}/search-index/index.d.ts +0 -0
- /package/dist/{integrations → plugins/internal}/search-index/index.js +0 -0
- /package/dist/{integrations → plugins/internal}/search-index/types.d.ts +0 -0
- /package/dist/{integrations → plugins/internal}/search-index/types.js +0 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type ThemePackRegistry, type ThemePackRegistryEntry } from "../theme-packs-registry/index.js";
|
|
2
|
+
export type { ThemePackRegistry, ThemePackRegistryEntry };
|
|
3
|
+
export interface LoadInstalledThemePackCatalogOptions {
|
|
4
|
+
/** Override for tests — points at a fixture `theme-packs/` directory
|
|
5
|
+
* instead of this module's own shipped one. */
|
|
6
|
+
themePacksDir?: string | URL;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Load the full installed catalog (every pack the running
|
|
10
|
+
* `@takazudo/zudo-doc` ships), validated the same way the package's own
|
|
11
|
+
* build validates it (`loadThemePackRegistry` — throws loudly naming the
|
|
12
|
+
* offending pack on a corrupted install rather than silently degrading).
|
|
13
|
+
*/
|
|
14
|
+
export declare function loadInstalledThemePackCatalog(options?: LoadInstalledThemePackCatalogOptions): ThemePackRegistry;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import {
|
|
2
|
+
loadThemePackRegistry
|
|
3
|
+
} from "../theme-packs-registry/index.js";
|
|
4
|
+
function defaultThemePacksDir() {
|
|
5
|
+
return new URL("../theme-packs/", import.meta.url);
|
|
6
|
+
}
|
|
7
|
+
function loadInstalledThemePackCatalog(options = {}) {
|
|
8
|
+
const dir = options.themePacksDir ?? defaultThemePacksDir();
|
|
9
|
+
return loadThemePackRegistry(dir);
|
|
10
|
+
}
|
|
11
|
+
export {
|
|
12
|
+
loadInstalledThemePackCatalog
|
|
13
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { ThemePackMeta } from "../theme-packs-registry/index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Structurally parse the `{base}theme-packs/index.json` registry payload
|
|
4
|
+
* (ADR Decision 2: `{ schemaVersion: 1, packs: ThemePackMeta[] }`). This is a
|
|
5
|
+
* defensive shape check against a truncated/malformed fetch response — NOT a
|
|
6
|
+
* re-run of the build-time zod validator (`theme-packs-registry/validator.ts`),
|
|
7
|
+
* which already gated every pack before the manifest was ever written.
|
|
8
|
+
* Re-validating each field client-side would pull `zod` into this dialog's
|
|
9
|
+
* browser bundle for no real benefit (the ADR's "Registry types... come from
|
|
10
|
+
* theme-packs-registry/" note means TYPES only). Returns `null` on any shape
|
|
11
|
+
* mismatch so the caller can show its inline error note instead of crashing
|
|
12
|
+
* on a bad field access later (`isValidThemePackMeta` covers every field
|
|
13
|
+
* `ThemePackCard` reads).
|
|
14
|
+
*/
|
|
15
|
+
export declare function parseThemePackRegistryPayload(data: unknown): ThemePackMeta[] | null;
|
|
16
|
+
/**
|
|
17
|
+
* Resolve which `meta.preview` swatch set paints the dialog's cards, matching
|
|
18
|
+
* the CURRENT light/dark UI mode (ADR Decision 7: "Card previews must pick
|
|
19
|
+
* the swatch set matching the CURRENT light/dark mode" — NOT `meta.mode`,
|
|
20
|
+
* which is only the designed-primary badge). Takes the raw `data-theme`
|
|
21
|
+
* attribute value rather than reading `document` itself so it stays
|
|
22
|
+
* plain-Node testable — mirrors `theme-toggle/color-scheme-sync.ts`'s
|
|
23
|
+
* `readColorSchemeFromDom` fallback shape (unknown/missing → "light").
|
|
24
|
+
*/
|
|
25
|
+
export declare function resolveDialogMode(dataThemeAttr: string | null): "light" | "dark";
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
function isValidSwatches(value) {
|
|
2
|
+
if (typeof value !== "object" || value === null) return false;
|
|
3
|
+
const v = value;
|
|
4
|
+
if (typeof v["bg"] !== "string" || typeof v["fg"] !== "string" || typeof v["accent"] !== "string") {
|
|
5
|
+
return false;
|
|
6
|
+
}
|
|
7
|
+
const syntax = v["syntax"];
|
|
8
|
+
if (typeof syntax !== "object" || syntax === null) return false;
|
|
9
|
+
const s = syntax;
|
|
10
|
+
return typeof s["keyword"] === "string" && typeof s["string"] === "string" && typeof s["comment"] === "string" && typeof s["callable"] === "string";
|
|
11
|
+
}
|
|
12
|
+
function isValidThemePackMeta(entry) {
|
|
13
|
+
if (typeof entry !== "object" || entry === null) return false;
|
|
14
|
+
const p = entry;
|
|
15
|
+
if (typeof p["slug"] !== "string" || typeof p["name"] !== "string" || typeof p["description"] !== "string") {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
if (p["mode"] !== "light" && p["mode"] !== "dark") return false;
|
|
19
|
+
const fonts = p["fonts"];
|
|
20
|
+
if (typeof fonts !== "object" || fonts === null) return false;
|
|
21
|
+
if (typeof fonts["sans"] !== "string") return false;
|
|
22
|
+
const preview = p["preview"];
|
|
23
|
+
if (typeof preview !== "object" || preview === null) return false;
|
|
24
|
+
const pv = preview;
|
|
25
|
+
return isValidSwatches(pv["light"]) && isValidSwatches(pv["dark"]);
|
|
26
|
+
}
|
|
27
|
+
function parseThemePackRegistryPayload(data) {
|
|
28
|
+
if (typeof data !== "object" || data === null) return null;
|
|
29
|
+
const record = data;
|
|
30
|
+
if (record["schemaVersion"] !== 1 || !Array.isArray(record["packs"])) return null;
|
|
31
|
+
const packs = record["packs"];
|
|
32
|
+
return packs.every(isValidThemePackMeta) ? packs : null;
|
|
33
|
+
}
|
|
34
|
+
function resolveDialogMode(dataThemeAttr) {
|
|
35
|
+
return dataThemeAttr === "dark" ? "dark" : "light";
|
|
36
|
+
}
|
|
37
|
+
export {
|
|
38
|
+
parseThemePackRegistryPayload,
|
|
39
|
+
resolveDialogMode
|
|
40
|
+
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { ThemePackDialogProps } from "../theme-pack-switcher/index.js";
|
|
2
|
+
export declare function ThemePackDialog({ open, onClose, order, active, base }: ThemePackDialogProps): import("preact").JSX.Element;
|
|
3
|
+
export declare namespace ThemePackDialog {
|
|
4
|
+
var displayName: string;
|
|
5
|
+
}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { Fragment, jsx, jsxs } from "preact/jsx-runtime";
|
|
3
|
+
import { useCallback, useEffect, useRef, useState } from "preact/compat";
|
|
4
|
+
import { Close } from "../icons/index.js";
|
|
5
|
+
import { AFTER_NAVIGATE_EVENT } from "../transitions/index.js";
|
|
6
|
+
import { applyThemePack, DEFAULT_THEME_PACK_SLUG } from "../theme-pack-switcher/theme-pack-sync.js";
|
|
7
|
+
import { connectActivePackSync } from "../theme-pack-switcher/switcher-state.js";
|
|
8
|
+
import { useModalDialog } from "../use-modal-dialog/index.js";
|
|
9
|
+
import { parseThemePackRegistryPayload, resolveDialogMode } from "./dialog-state.js";
|
|
10
|
+
import { ThemePackCard } from "./theme-pack-card.js";
|
|
11
|
+
const COLOR_SCHEME_CHANGED_EVENT = "color-scheme-changed";
|
|
12
|
+
const LAUNCHER_SELECTOR = "[data-switcher-launcher]";
|
|
13
|
+
function ThemePackDialog({ open, onClose, order, active, base }) {
|
|
14
|
+
const [registryState, setRegistryState] = useState("idle");
|
|
15
|
+
const [packs, setPacks] = useState(null);
|
|
16
|
+
const [mode, setMode] = useState(
|
|
17
|
+
() => typeof document === "undefined" ? "light" : resolveDialogMode(document.documentElement.getAttribute("data-theme"))
|
|
18
|
+
);
|
|
19
|
+
const [activeSlug, setActiveSlug] = useState(active);
|
|
20
|
+
const launcherFocusRef = useRef(null);
|
|
21
|
+
const hasBrowsablePacks = order.some((entry) => entry.slug !== DEFAULT_THEME_PACK_SLUG);
|
|
22
|
+
useEffect(() => connectActivePackSync(setActiveSlug), []);
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
function sync() {
|
|
25
|
+
setMode(resolveDialogMode(document.documentElement.getAttribute("data-theme")));
|
|
26
|
+
}
|
|
27
|
+
window.addEventListener(COLOR_SCHEME_CHANGED_EVENT, sync);
|
|
28
|
+
return () => window.removeEventListener(COLOR_SCHEME_CHANGED_EVENT, sync);
|
|
29
|
+
}, []);
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
if (!open) return;
|
|
32
|
+
launcherFocusRef.current = document.querySelector(LAUNCHER_SELECTOR);
|
|
33
|
+
}, [open]);
|
|
34
|
+
const hasOpenedRef = useRef(false);
|
|
35
|
+
const [fetchToken, setFetchToken] = useState(0);
|
|
36
|
+
useEffect(() => {
|
|
37
|
+
if (open && !hasOpenedRef.current) {
|
|
38
|
+
hasOpenedRef.current = true;
|
|
39
|
+
if (hasBrowsablePacks) setFetchToken((t) => t + 1);
|
|
40
|
+
}
|
|
41
|
+
}, [open, hasBrowsablePacks]);
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
if (fetchToken === 0) return;
|
|
44
|
+
let cancelled = false;
|
|
45
|
+
setRegistryState("loading");
|
|
46
|
+
fetch(`${base}theme-packs/index.json`).then((res) => {
|
|
47
|
+
if (!res.ok) throw new Error(`theme-packs/index.json responded ${res.status}`);
|
|
48
|
+
return res.json();
|
|
49
|
+
}).then((data) => {
|
|
50
|
+
if (cancelled) return;
|
|
51
|
+
const parsed = parseThemePackRegistryPayload(data);
|
|
52
|
+
if (parsed === null) {
|
|
53
|
+
setRegistryState("error");
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
setPacks(parsed);
|
|
57
|
+
setRegistryState("loaded");
|
|
58
|
+
}).catch(() => {
|
|
59
|
+
if (!cancelled) setRegistryState("error");
|
|
60
|
+
});
|
|
61
|
+
return () => {
|
|
62
|
+
cancelled = true;
|
|
63
|
+
};
|
|
64
|
+
}, [fetchToken, base]);
|
|
65
|
+
const retry = useCallback(() => setFetchToken((t) => t + 1), []);
|
|
66
|
+
const { dialogRef, handleBackdropClick } = useModalDialog({
|
|
67
|
+
isOpen: open,
|
|
68
|
+
onClose,
|
|
69
|
+
navigateEvent: AFTER_NAVIGATE_EVENT,
|
|
70
|
+
backdropClickClose: true,
|
|
71
|
+
manageFocus: true,
|
|
72
|
+
returnFocusRef: launcherFocusRef
|
|
73
|
+
});
|
|
74
|
+
return /* @__PURE__ */ jsx(
|
|
75
|
+
"dialog",
|
|
76
|
+
{
|
|
77
|
+
ref: dialogRef,
|
|
78
|
+
onClick: handleBackdropClick,
|
|
79
|
+
"aria-labelledby": "zd-theme-pack-dialog-title",
|
|
80
|
+
className: "z-modal m-auto max-h-[85vh] w-[calc(100vw-2rem)] max-w-[64rem] rounded-lg border border-muted bg-surface p-0 text-fg backdrop:z-modal-backdrop backdrop:bg-bg/80",
|
|
81
|
+
children: /* @__PURE__ */ jsxs("div", { className: "flex max-h-[85vh] flex-col", children: [
|
|
82
|
+
/* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center justify-between gap-hsp-sm border-b border-muted px-hsp-lg py-vsp-sm", children: [
|
|
83
|
+
/* @__PURE__ */ jsx("h2", { id: "zd-theme-pack-dialog-title", className: "text-title font-bold text-fg", children: "Preview theme" }),
|
|
84
|
+
/* @__PURE__ */ jsx(
|
|
85
|
+
"button",
|
|
86
|
+
{
|
|
87
|
+
type: "button",
|
|
88
|
+
onClick: () => dialogRef.current?.close(),
|
|
89
|
+
"aria-label": "Close",
|
|
90
|
+
className: "flex items-center justify-center text-muted transition-colors hover:text-fg",
|
|
91
|
+
children: /* @__PURE__ */ jsx(Close, { className: "h-icon-sm w-icon-sm" })
|
|
92
|
+
}
|
|
93
|
+
)
|
|
94
|
+
] }),
|
|
95
|
+
/* @__PURE__ */ jsx("div", { className: "min-h-0 flex-1 overflow-y-auto overscroll-contain px-hsp-lg py-vsp-lg", children: !hasBrowsablePacks ? /* @__PURE__ */ jsx("p", { className: "py-vsp-xl text-center text-small text-muted", children: "No other theme packs are configured \u2014 only the default look is available." }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
96
|
+
registryState === "error" && /* @__PURE__ */ jsxs(
|
|
97
|
+
"div",
|
|
98
|
+
{
|
|
99
|
+
role: "alert",
|
|
100
|
+
className: "mx-auto flex max-w-sm flex-col items-center gap-vsp-xs rounded-[0.75rem] border border-danger bg-bg px-hsp-lg py-vsp-lg text-center text-small text-danger",
|
|
101
|
+
children: [
|
|
102
|
+
/* @__PURE__ */ jsx("p", { children: "Could not load theme previews." }),
|
|
103
|
+
/* @__PURE__ */ jsx(
|
|
104
|
+
"button",
|
|
105
|
+
{
|
|
106
|
+
type: "button",
|
|
107
|
+
onClick: retry,
|
|
108
|
+
className: "rounded border border-danger px-hsp-md py-hsp-2xs text-caption text-danger transition-colors hover:bg-danger/10",
|
|
109
|
+
children: "Retry"
|
|
110
|
+
}
|
|
111
|
+
)
|
|
112
|
+
]
|
|
113
|
+
}
|
|
114
|
+
),
|
|
115
|
+
(registryState === "idle" || registryState === "loading") && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
116
|
+
/* @__PURE__ */ jsx("p", { role: "status", className: "sr-only", children: "Loading theme previews\u2026" }),
|
|
117
|
+
/* @__PURE__ */ jsx(
|
|
118
|
+
"div",
|
|
119
|
+
{
|
|
120
|
+
"aria-hidden": "true",
|
|
121
|
+
className: "grid grid-cols-1 gap-hsp-lg sm:grid-cols-2 lg:grid-cols-3",
|
|
122
|
+
children: order.map((entry) => /* @__PURE__ */ jsx(
|
|
123
|
+
"div",
|
|
124
|
+
{
|
|
125
|
+
className: "h-40 animate-pulse rounded-lg border border-muted bg-surface/50"
|
|
126
|
+
},
|
|
127
|
+
entry.slug
|
|
128
|
+
))
|
|
129
|
+
}
|
|
130
|
+
)
|
|
131
|
+
] }),
|
|
132
|
+
packs !== null && /* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 gap-hsp-lg sm:grid-cols-2 lg:grid-cols-3", children: packs.map((meta) => /* @__PURE__ */ jsx(
|
|
133
|
+
ThemePackCard,
|
|
134
|
+
{
|
|
135
|
+
meta,
|
|
136
|
+
mode,
|
|
137
|
+
isActive: meta.slug === activeSlug,
|
|
138
|
+
onSelect: () => {
|
|
139
|
+
void applyThemePack(meta.slug);
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
meta.slug
|
|
143
|
+
)) })
|
|
144
|
+
] }) })
|
|
145
|
+
] })
|
|
146
|
+
}
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
ThemePackDialog.displayName = "ThemePackDialog";
|
|
150
|
+
export {
|
|
151
|
+
ThemePackDialog
|
|
152
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/** @jsxRuntime automatic */
|
|
2
|
+
/** @jsxImportSource preact */
|
|
3
|
+
import type { VNode } from "preact";
|
|
4
|
+
import type { ThemePackMeta } from "../theme-packs-registry/index.js";
|
|
5
|
+
export interface ThemePackCardProps {
|
|
6
|
+
/** Full pack meta (incl. resolved preview swatches) for one registry entry. */
|
|
7
|
+
meta: ThemePackMeta;
|
|
8
|
+
/** Current light/dark UI mode — selects which `meta.preview` swatch set
|
|
9
|
+
* paints the card (NOT `meta.mode`, which is only the designed-primary
|
|
10
|
+
* badge shown alongside the name). */
|
|
11
|
+
mode: "light" | "dark";
|
|
12
|
+
/** Whether this card's pack is the currently active one (selected ring). */
|
|
13
|
+
isActive: boolean;
|
|
14
|
+
/** Apply this pack — the caller wires this to `applyThemePack(meta.slug)`;
|
|
15
|
+
* this component stays a plain presentational click forwarder. */
|
|
16
|
+
onSelect: () => void;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* One theme-pack preview card: a mini "Aa Heading" / prose+link / code-line
|
|
20
|
+
* sample painted from `meta.preview[mode]`, plus name, Light/Dark badge, and
|
|
21
|
+
* description. Clicking applies the pack immediately (the dialog stays open
|
|
22
|
+
* — ADR Decision 7 — so the selected ring is driven by `isActive`, not by
|
|
23
|
+
* the click itself).
|
|
24
|
+
*/
|
|
25
|
+
export declare function ThemePackCard({ meta, mode, isActive, onSelect }: ThemePackCardProps): VNode;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { jsx, jsxs } from "preact/jsx-runtime";
|
|
2
|
+
function ThemePackCard({ meta, mode, isActive, onSelect }) {
|
|
3
|
+
const swatches = meta.preview[mode];
|
|
4
|
+
const fontCaption = meta.fonts.display ?? meta.fonts.sans;
|
|
5
|
+
return /* @__PURE__ */ jsxs(
|
|
6
|
+
"button",
|
|
7
|
+
{
|
|
8
|
+
type: "button",
|
|
9
|
+
onClick: onSelect,
|
|
10
|
+
"aria-pressed": isActive,
|
|
11
|
+
"aria-label": `Apply ${meta.name} theme pack \u2014 ${meta.mode === "dark" ? "Dark" : "Light"}. ${meta.description}`,
|
|
12
|
+
className: `flex flex-col gap-vsp-2xs rounded-lg border p-hsp-sm text-left transition-colors focus-visible:outline-2 focus-visible:outline-accent focus-visible:outline-offset-2 ${isActive ? "border-accent ring-2 ring-accent" : "border-muted hover:border-accent"}`,
|
|
13
|
+
children: [
|
|
14
|
+
/* @__PURE__ */ jsxs(
|
|
15
|
+
"div",
|
|
16
|
+
{
|
|
17
|
+
"aria-hidden": "true",
|
|
18
|
+
className: "flex flex-col gap-vsp-3xs rounded-md border p-hsp-sm",
|
|
19
|
+
style: {
|
|
20
|
+
backgroundColor: swatches.bg,
|
|
21
|
+
color: swatches.fg,
|
|
22
|
+
borderColor: `color-mix(in oklch, ${swatches.fg} 15%, transparent)`
|
|
23
|
+
},
|
|
24
|
+
children: [
|
|
25
|
+
/* @__PURE__ */ jsx("p", { className: "text-title font-bold", children: "Aa Heading" }),
|
|
26
|
+
/* @__PURE__ */ jsxs("p", { className: "text-small", children: [
|
|
27
|
+
"The quick brown fox jumps over",
|
|
28
|
+
" ",
|
|
29
|
+
/* @__PURE__ */ jsx("span", { className: "underline", style: { color: swatches.accent }, children: "the lazy dog" }),
|
|
30
|
+
"."
|
|
31
|
+
] }),
|
|
32
|
+
/* @__PURE__ */ jsxs(
|
|
33
|
+
"p",
|
|
34
|
+
{
|
|
35
|
+
className: "rounded px-hsp-2xs py-hsp-3xs font-mono text-caption",
|
|
36
|
+
style: { backgroundColor: `color-mix(in oklch, ${swatches.fg} 8%, transparent)` },
|
|
37
|
+
children: [
|
|
38
|
+
/* @__PURE__ */ jsx("span", { style: { color: swatches.syntax.keyword }, children: "const" }),
|
|
39
|
+
" ",
|
|
40
|
+
/* @__PURE__ */ jsx("span", { style: { color: swatches.syntax.callable }, children: "theme" }),
|
|
41
|
+
" =",
|
|
42
|
+
" ",
|
|
43
|
+
/* @__PURE__ */ jsxs("span", { style: { color: swatches.syntax.string }, children: [
|
|
44
|
+
'"',
|
|
45
|
+
meta.slug,
|
|
46
|
+
'"'
|
|
47
|
+
] }),
|
|
48
|
+
";",
|
|
49
|
+
" ",
|
|
50
|
+
/* @__PURE__ */ jsxs("span", { style: { color: swatches.syntax.comment }, children: [
|
|
51
|
+
"// ",
|
|
52
|
+
meta.mode
|
|
53
|
+
] })
|
|
54
|
+
]
|
|
55
|
+
}
|
|
56
|
+
)
|
|
57
|
+
]
|
|
58
|
+
}
|
|
59
|
+
),
|
|
60
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-hsp-sm", children: [
|
|
61
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 truncate text-body font-bold text-fg", children: meta.name }),
|
|
62
|
+
/* @__PURE__ */ jsx("span", { className: "shrink-0 rounded-full border border-muted px-hsp-sm text-micro tracking-wide text-muted uppercase", children: meta.mode === "dark" ? "Dark" : "Light" })
|
|
63
|
+
] }),
|
|
64
|
+
/* @__PURE__ */ jsx("p", { className: "text-caption text-muted", children: meta.description }),
|
|
65
|
+
/* @__PURE__ */ jsx("p", { className: "text-micro text-muted", children: fontCaption })
|
|
66
|
+
]
|
|
67
|
+
}
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
export {
|
|
71
|
+
ThemePackCard
|
|
72
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/** @jsxRuntime automatic */
|
|
2
|
+
/** @jsxImportSource preact */
|
|
3
|
+
import type { JSX } from "preact";
|
|
4
|
+
import { type ThemePackOrderEntry } from "./switcher-state.js";
|
|
5
|
+
export type { ThemePackOrderEntry } from "./switcher-state.js";
|
|
6
|
+
/**
|
|
7
|
+
* Island props (ADR Decision 7 "Switcher data flow") — serializable ONLY:
|
|
8
|
+
* they ride the island marker's `data-props` JSON across the SSR → hydrate
|
|
9
|
+
* boundary, so no functions/components may ever be added here.
|
|
10
|
+
*/
|
|
11
|
+
export interface ThemePackSwitcherProps {
|
|
12
|
+
/** The SSR-known active pack slug (`settings.themePack`); the user's
|
|
13
|
+
* stored choice is synced from the DOM after hydration. */
|
|
14
|
+
active: string;
|
|
15
|
+
/** The resolved, enabled packs IN SWITCHER ORDER — the Prev/Next cycle
|
|
16
|
+
* order and the dialog grid order. */
|
|
17
|
+
order: ThemePackOrderEntry[];
|
|
18
|
+
/** Base prefix WITH trailing slash (`ctx.withBase("/")`) — forwarded to
|
|
19
|
+
* the browse-all dialog for its `{base}theme-packs/index.json` fetch. */
|
|
20
|
+
base: string;
|
|
21
|
+
}
|
|
22
|
+
/** Props of the browse-all dialog mounted through {@link ThemePackDialogSlot}
|
|
23
|
+
* — the #2825 contract. The dialog fetches `{base}theme-packs/index.json`
|
|
24
|
+
* lazily on first open for the full meta (preview swatches); cards apply
|
|
25
|
+
* via `applyThemePack(slug)` and the dialog stays open (ADR Decision 7). */
|
|
26
|
+
export interface ThemePackDialogProps {
|
|
27
|
+
/** Whether the dialog is currently open. */
|
|
28
|
+
open: boolean;
|
|
29
|
+
/** Close callback (Esc / ✕ / backdrop — the dialog's own close paths). */
|
|
30
|
+
onClose: () => void;
|
|
31
|
+
/** The switcher order — also the dialog grid order. */
|
|
32
|
+
order: ThemePackOrderEntry[];
|
|
33
|
+
/** Currently active pack slug (live — follows `theme-pack-changed`). */
|
|
34
|
+
active: string;
|
|
35
|
+
/** Base prefix WITH trailing slash for the `index.json` fetch. */
|
|
36
|
+
base: string;
|
|
37
|
+
}
|
|
38
|
+
/** The browse-all dialog component contract (#2825). */
|
|
39
|
+
export type ThemePackDialogComponent = (props: ThemePackDialogProps) => JSX.Element | null;
|
|
40
|
+
/**
|
|
41
|
+
* The bottom-right theme-pack switcher flyout. Mounted (settings-gated on
|
|
42
|
+
* `themePackSwitcher`) by the package body-end islands via
|
|
43
|
+
* `Island({ when: "load" })` — see
|
|
44
|
+
* `../doc-body-end-islands/theme-pack-switcher-island.tsx`.
|
|
45
|
+
*/
|
|
46
|
+
export declare function ThemePackSwitcher({ active, order, base }: ThemePackSwitcherProps): JSX.Element;
|
|
47
|
+
export declare namespace ThemePackSwitcher {
|
|
48
|
+
var displayName: string;
|
|
49
|
+
}
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "preact/jsx-runtime";
|
|
3
|
+
import { useEffect, useRef, useState } from "preact/hooks";
|
|
4
|
+
import { ChevronLeft, ChevronRight, Close } from "../icons/index.js";
|
|
5
|
+
import { ThemePackDialog } from "../theme-pack-dialog/index.js";
|
|
6
|
+
import { applyThemePack } from "./theme-pack-sync.js";
|
|
7
|
+
import {
|
|
8
|
+
connectActivePackSync,
|
|
9
|
+
connectEscapeToClose,
|
|
10
|
+
nextPackSlug,
|
|
11
|
+
prevPackSlug,
|
|
12
|
+
resolveActiveEntry
|
|
13
|
+
} from "./switcher-state.js";
|
|
14
|
+
const ThemePackDialogSlot = ThemePackDialog;
|
|
15
|
+
function GridIcon({ className }) {
|
|
16
|
+
return /* @__PURE__ */ jsxs(
|
|
17
|
+
"svg",
|
|
18
|
+
{
|
|
19
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
20
|
+
class: className || void 0,
|
|
21
|
+
fill: "none",
|
|
22
|
+
viewBox: "0 0 24 24",
|
|
23
|
+
stroke: "currentColor",
|
|
24
|
+
"stroke-width": "2",
|
|
25
|
+
"aria-hidden": "true",
|
|
26
|
+
children: [
|
|
27
|
+
/* @__PURE__ */ jsx("rect", { x: "4", y: "4", width: "7", height: "7", rx: "1" }),
|
|
28
|
+
/* @__PURE__ */ jsx("rect", { x: "13", y: "4", width: "7", height: "7", rx: "1" }),
|
|
29
|
+
/* @__PURE__ */ jsx("rect", { x: "4", y: "13", width: "7", height: "7", rx: "1" }),
|
|
30
|
+
/* @__PURE__ */ jsx("rect", { x: "13", y: "13", width: "7", height: "7", rx: "1" })
|
|
31
|
+
]
|
|
32
|
+
}
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
function PaletteIcon({ className }) {
|
|
36
|
+
return /* @__PURE__ */ jsxs(
|
|
37
|
+
"svg",
|
|
38
|
+
{
|
|
39
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
40
|
+
class: className || void 0,
|
|
41
|
+
fill: "none",
|
|
42
|
+
viewBox: "0 0 24 24",
|
|
43
|
+
stroke: "currentColor",
|
|
44
|
+
"stroke-width": "2",
|
|
45
|
+
"aria-hidden": "true",
|
|
46
|
+
children: [
|
|
47
|
+
/* @__PURE__ */ jsx(
|
|
48
|
+
"path",
|
|
49
|
+
{
|
|
50
|
+
"stroke-linecap": "round",
|
|
51
|
+
"stroke-linejoin": "round",
|
|
52
|
+
d: "M12 21a9 9 0 1 1 9-9c0 2-1.5 3-3 3h-2a2 2 0 0 0-1.5 3.3c.5.6.2 1.7-.7 1.7H12z"
|
|
53
|
+
}
|
|
54
|
+
),
|
|
55
|
+
/* @__PURE__ */ jsx("circle", { cx: "7.5", cy: "11.5", r: "1", fill: "currentColor", stroke: "none" }),
|
|
56
|
+
/* @__PURE__ */ jsx("circle", { cx: "10.5", cy: "7.5", r: "1", fill: "currentColor", stroke: "none" }),
|
|
57
|
+
/* @__PURE__ */ jsx("circle", { cx: "15", cy: "7.5", r: "1", fill: "currentColor", stroke: "none" })
|
|
58
|
+
]
|
|
59
|
+
}
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
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";
|
|
63
|
+
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";
|
|
64
|
+
function ThemePackSwitcher({ active, order, base }) {
|
|
65
|
+
const [open, setOpen] = useState(false);
|
|
66
|
+
const [dialogOpen, setDialogOpen] = useState(false);
|
|
67
|
+
const [activeSlug, setActiveSlug] = useState(active);
|
|
68
|
+
const launcherRef = useRef(null);
|
|
69
|
+
const cardRef = useRef(null);
|
|
70
|
+
useEffect(() => connectActivePackSync(setActiveSlug), []);
|
|
71
|
+
useEffect(() => {
|
|
72
|
+
if (!open || dialogOpen) return void 0;
|
|
73
|
+
return connectEscapeToClose(() => {
|
|
74
|
+
setOpen(false);
|
|
75
|
+
launcherRef.current?.focus();
|
|
76
|
+
});
|
|
77
|
+
}, [open, dialogOpen]);
|
|
78
|
+
useEffect(() => {
|
|
79
|
+
if (open) cardRef.current?.focus();
|
|
80
|
+
}, [open]);
|
|
81
|
+
const entry = resolveActiveEntry(order, activeSlug);
|
|
82
|
+
function cycle(step) {
|
|
83
|
+
const target = step === 1 ? nextPackSlug(order, activeSlug) : prevPackSlug(order, activeSlug);
|
|
84
|
+
if (target !== null && target !== activeSlug) void applyThemePack(target);
|
|
85
|
+
}
|
|
86
|
+
function closeCard() {
|
|
87
|
+
setOpen(false);
|
|
88
|
+
launcherRef.current?.focus();
|
|
89
|
+
}
|
|
90
|
+
function openDialog() {
|
|
91
|
+
setOpen(false);
|
|
92
|
+
setDialogOpen(true);
|
|
93
|
+
}
|
|
94
|
+
return /* @__PURE__ */ jsxs(
|
|
95
|
+
"div",
|
|
96
|
+
{
|
|
97
|
+
class: "fixed right-hsp-lg bottom-hsp-lg z-popover flex flex-col items-end gap-vsp-2xs",
|
|
98
|
+
"data-theme-pack-switcher": true,
|
|
99
|
+
children: [
|
|
100
|
+
open ? /* @__PURE__ */ jsxs(
|
|
101
|
+
"div",
|
|
102
|
+
{
|
|
103
|
+
ref: cardRef,
|
|
104
|
+
tabIndex: -1,
|
|
105
|
+
role: "dialog",
|
|
106
|
+
"aria-label": "Theme pack switcher",
|
|
107
|
+
"data-switcher-card": true,
|
|
108
|
+
class: "flex w-72 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",
|
|
109
|
+
children: [
|
|
110
|
+
/* @__PURE__ */ jsxs("div", { class: "flex items-start justify-between gap-hsp-sm", children: [
|
|
111
|
+
/* @__PURE__ */ jsx("p", { class: "min-w-0 break-words text-body font-bold text-fg", "aria-live": "polite", children: entry?.name ?? activeSlug }),
|
|
112
|
+
/* @__PURE__ */ jsxs("div", { class: "flex shrink-0 items-center gap-hsp-2xs", children: [
|
|
113
|
+
/* @__PURE__ */ jsx(
|
|
114
|
+
"button",
|
|
115
|
+
{
|
|
116
|
+
type: "button",
|
|
117
|
+
"aria-label": "Browse all theme packs",
|
|
118
|
+
title: "Browse all theme packs",
|
|
119
|
+
disabled: ThemePackDialogSlot === null,
|
|
120
|
+
onClick: openDialog,
|
|
121
|
+
class: ICON_BUTTON_CLASS,
|
|
122
|
+
children: /* @__PURE__ */ jsx(GridIcon, { className: "h-icon-sm w-icon-sm" })
|
|
123
|
+
}
|
|
124
|
+
),
|
|
125
|
+
/* @__PURE__ */ jsx(
|
|
126
|
+
"button",
|
|
127
|
+
{
|
|
128
|
+
type: "button",
|
|
129
|
+
"aria-label": "Close theme pack switcher",
|
|
130
|
+
title: "Close",
|
|
131
|
+
onClick: closeCard,
|
|
132
|
+
class: ICON_BUTTON_CLASS,
|
|
133
|
+
children: /* @__PURE__ */ jsx(Close, { className: "h-icon-sm w-icon-sm" })
|
|
134
|
+
}
|
|
135
|
+
)
|
|
136
|
+
] })
|
|
137
|
+
] }),
|
|
138
|
+
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" }),
|
|
139
|
+
entry !== null && entry.description !== "" && /* @__PURE__ */ jsx("p", { class: "text-caption text-muted", children: entry.description }),
|
|
140
|
+
/* @__PURE__ */ jsxs("div", { class: "flex items-center justify-between gap-hsp-sm", children: [
|
|
141
|
+
/* @__PURE__ */ jsxs(
|
|
142
|
+
"button",
|
|
143
|
+
{
|
|
144
|
+
type: "button",
|
|
145
|
+
"aria-label": "Previous theme pack",
|
|
146
|
+
disabled: order.length < 2,
|
|
147
|
+
onClick: () => cycle(-1),
|
|
148
|
+
class: CONTROL_BUTTON_CLASS,
|
|
149
|
+
children: [
|
|
150
|
+
/* @__PURE__ */ jsx(ChevronLeft, { className: "h-icon-xs w-icon-xs" }),
|
|
151
|
+
"Prev"
|
|
152
|
+
]
|
|
153
|
+
}
|
|
154
|
+
),
|
|
155
|
+
/* @__PURE__ */ jsxs(
|
|
156
|
+
"button",
|
|
157
|
+
{
|
|
158
|
+
type: "button",
|
|
159
|
+
"aria-label": "Next theme pack",
|
|
160
|
+
disabled: order.length < 2,
|
|
161
|
+
onClick: () => cycle(1),
|
|
162
|
+
class: CONTROL_BUTTON_CLASS,
|
|
163
|
+
children: [
|
|
164
|
+
"Next",
|
|
165
|
+
/* @__PURE__ */ jsx(ChevronRight, { className: "h-icon-xs w-icon-xs" })
|
|
166
|
+
]
|
|
167
|
+
}
|
|
168
|
+
)
|
|
169
|
+
] })
|
|
170
|
+
]
|
|
171
|
+
}
|
|
172
|
+
) : null,
|
|
173
|
+
/* @__PURE__ */ jsx(
|
|
174
|
+
"button",
|
|
175
|
+
{
|
|
176
|
+
ref: launcherRef,
|
|
177
|
+
type: "button",
|
|
178
|
+
"aria-haspopup": "dialog",
|
|
179
|
+
"aria-expanded": open,
|
|
180
|
+
"aria-label": "Theme pack switcher",
|
|
181
|
+
title: "Theme packs",
|
|
182
|
+
"data-switcher-launcher": true,
|
|
183
|
+
onClick: () => setOpen(!open),
|
|
184
|
+
class: "flex h-10 w-10 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",
|
|
185
|
+
children: /* @__PURE__ */ jsx(PaletteIcon, { className: "h-icon-md w-icon-md" })
|
|
186
|
+
}
|
|
187
|
+
),
|
|
188
|
+
ThemePackDialogSlot !== null ? /* @__PURE__ */ jsx(
|
|
189
|
+
ThemePackDialogSlot,
|
|
190
|
+
{
|
|
191
|
+
open: dialogOpen,
|
|
192
|
+
onClose: () => setDialogOpen(false),
|
|
193
|
+
order,
|
|
194
|
+
active: activeSlug,
|
|
195
|
+
base
|
|
196
|
+
}
|
|
197
|
+
) : null
|
|
198
|
+
]
|
|
199
|
+
}
|
|
200
|
+
);
|
|
201
|
+
}
|
|
202
|
+
ThemePackSwitcher.displayName = "ThemePackSwitcher";
|
|
203
|
+
export {
|
|
204
|
+
ThemePackSwitcher
|
|
205
|
+
};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One entry of the flyout's SSR-provided `order` prop — the lightweight
|
|
3
|
+
* projection of a registry entry's meta (ADR Decision 7 "Switcher data
|
|
4
|
+
* flow": `{ slug, name, mode, description }`). The array order IS the
|
|
5
|
+
* Prev/Next cycle order (and the dialog grid order).
|
|
6
|
+
*/
|
|
7
|
+
export interface ThemePackOrderEntry {
|
|
8
|
+
/** Pack slug (`meta.slug` — equals the pack's directory name). */
|
|
9
|
+
slug: string;
|
|
10
|
+
/** Display name shown as the flyout card title. */
|
|
11
|
+
name: string;
|
|
12
|
+
/** Designed-primary mode badge — a badge, not a capability flag. */
|
|
13
|
+
mode: "light" | "dark";
|
|
14
|
+
/** 1–2 sentence note shown under the title. */
|
|
15
|
+
description: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Resolve the cycle target `step` away from `active` in `order`, wrapping
|
|
19
|
+
* around at both ends (ADR Decision 7: "Ordering IS the switcher order",
|
|
20
|
+
* Prev/Next cycle with wraparound).
|
|
21
|
+
*
|
|
22
|
+
* - Empty `order` → `null` (nothing to cycle to).
|
|
23
|
+
* - `active` not present in `order` (e.g. the html attribute carries a slug
|
|
24
|
+
* the switcher was not configured with) → the first entry for `+1`, the
|
|
25
|
+
* last for `-1`, so the UI recovers onto the cycle instead of dead-ending.
|
|
26
|
+
*/
|
|
27
|
+
export declare function cyclePackSlug(order: readonly ThemePackOrderEntry[], active: string, step: 1 | -1): string | null;
|
|
28
|
+
/** The Prev/Next cycle target after `active` (wraparound). */
|
|
29
|
+
export declare function nextPackSlug(order: readonly ThemePackOrderEntry[], active: string): string | null;
|
|
30
|
+
/** The Prev/Next cycle target before `active` (wraparound). */
|
|
31
|
+
export declare function prevPackSlug(order: readonly ThemePackOrderEntry[], active: string): string | null;
|
|
32
|
+
/**
|
|
33
|
+
* The `order` entry matching `active`, or `null` when the active slug is not
|
|
34
|
+
* part of the switcher order (the card then falls back to showing the bare
|
|
35
|
+
* slug with no badge/description).
|
|
36
|
+
*/
|
|
37
|
+
export declare function resolveActiveEntry(order: readonly ThemePackOrderEntry[], active: string): ThemePackOrderEntry | null;
|
|
38
|
+
/**
|
|
39
|
+
* Connect a state setter to the live active-pack source of truth: push the
|
|
40
|
+
* CURRENT DOM value once immediately, then re-push on every
|
|
41
|
+
* `theme-pack-changed` event so multiple mounted surfaces (flyout, dialog, a
|
|
42
|
+
* future header trigger) never disagree — the ThemeToggle cross-instance
|
|
43
|
+
* sync pattern (#2012 E3). Returns an unsubscribe function suitable as a
|
|
44
|
+
* `useEffect` cleanup.
|
|
45
|
+
*
|
|
46
|
+
* Note the display state only ever advances FROM this event: a failed or
|
|
47
|
+
* aborted `applyThemePack` never fires it, so the UI never shows a pack that
|
|
48
|
+
* did not commit (ADR Decision 3 failure semantics).
|
|
49
|
+
*/
|
|
50
|
+
export declare function connectActivePackSync(onActive: (slug: string) => void): () => void;
|
|
51
|
+
/**
|
|
52
|
+
* Register a document-level Escape handler (used while the flyout card is
|
|
53
|
+
* open — close on Escape, acceptance criterion of #2821). Returns the
|
|
54
|
+
* matching teardown, suitable as a `useEffect` cleanup.
|
|
55
|
+
*/
|
|
56
|
+
export declare function connectEscapeToClose(onEscape: () => void): () => void;
|