@ciderpress/ui 1.0.0-rc.1
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/LICENSE +21 -0
- package/README.md +23 -0
- package/dist/0~142.js +2 -0
- package/dist/0~164.js +2 -0
- package/dist/0~2.js +2 -0
- package/dist/0~225.js +2 -0
- package/dist/0~288.js +2 -0
- package/dist/0~299.js +2 -0
- package/dist/0~3.js +2 -0
- package/dist/0~301.js +2 -0
- package/dist/0~311.js +2 -0
- package/dist/0~326.js +2 -0
- package/dist/0~40.js +2 -0
- package/dist/0~43.js +2 -0
- package/dist/0~433.js +2 -0
- package/dist/0~453.js +2 -0
- package/dist/0~457.js +2 -0
- package/dist/0~497.js +2 -0
- package/dist/0~511.js +2 -0
- package/dist/0~603.js +2 -0
- package/dist/0~616.js +2 -0
- package/dist/0~659.js +2 -0
- package/dist/0~670.js +2 -0
- package/dist/0~687.js +2 -0
- package/dist/0~706.js +2 -0
- package/dist/0~729.js +2 -0
- package/dist/0~768.js +2 -0
- package/dist/0~819.js +2 -0
- package/dist/0~830.js +2 -0
- package/dist/0~854.js +2 -0
- package/dist/0~863.js +2 -0
- package/dist/0~879.js +2 -0
- package/dist/0~96.js +2 -0
- package/dist/0~97.js +2 -0
- package/dist/components/FileTree/FileTree.css +90 -0
- package/dist/components/FileTree/FileTree.d.ts +7 -0
- package/dist/components/FileTree/FileTree.js +531 -0
- package/dist/components/FileTree/FileTreeItem.d.ts +8 -0
- package/dist/components/FileTree/RemoteSvgIcon.d.ts +11 -0
- package/dist/components/FileTree/index.d.ts +4 -0
- package/dist/components/folder-icons.d.ts +32 -0
- package/dist/components/languages.d.ts +7 -0
- package/dist/components/tree-parser/tree-parser.d.ts +12 -0
- package/dist/components/tree-parser/types.d.ts +11 -0
- package/dist/head/css/loader-apple.css +1 -0
- package/dist/head/css/loader-backdrop.css +1 -0
- package/dist/head/css/loader-dots.css +1 -0
- package/dist/head/css/themes/amber.css +1 -0
- package/dist/head/css/themes/arcade.css +1 -0
- package/dist/head/css/themes/grannysmith.css +1 -0
- package/dist/head/css/themes/honeycrisp.css +1 -0
- package/dist/head/css/themes/midnight.css +1 -0
- package/dist/head/css/themes/mulled.css +1 -0
- package/dist/head/js/loader-dots.js +1 -0
- package/dist/head/js/vscode-nav.js +1 -0
- package/dist/index.d.ts +43 -0
- package/dist/index.mjs +40 -0
- package/dist/node.d.ts +81 -0
- package/dist/node.mjs +17762 -0
- package/dist/plugins/mermaid/MermaidRenderer.tsx +480 -0
- package/dist/plugins/mermaid/mermaid.css +199 -0
- package/dist/theme/components/announcement/announcement-bar.css +103 -0
- package/dist/theme/components/announcement/announcement-bar.tsx +173 -0
- package/dist/theme/components/ask-ai/ask-ai-button.css +52 -0
- package/dist/theme/components/ask-ai/ask-ai-button.tsx +56 -0
- package/dist/theme/components/content-footer/content-footer-portal.tsx +70 -0
- package/dist/theme/components/content-footer/feedback.css +47 -0
- package/dist/theme/components/content-footer/feedback.tsx +96 -0
- package/dist/theme/components/content-footer/meta-actions.css +25 -0
- package/dist/theme/components/content-footer/meta-actions.tsx +57 -0
- package/dist/theme/components/content-footer/page-pager.css +61 -0
- package/dist/theme/components/content-footer/page-pager.tsx +110 -0
- package/dist/theme/components/edit-source-button.tsx +97 -0
- package/dist/theme/components/footer/site-footer.css +179 -0
- package/dist/theme/components/footer/site-footer.tsx +115 -0
- package/dist/theme/components/home/cta.css +67 -0
- package/dist/theme/components/home/cta.tsx +77 -0
- package/dist/theme/components/home/feature-card.css +52 -0
- package/dist/theme/components/home/feature-card.tsx +131 -0
- package/dist/theme/components/home/feature.tsx +79 -0
- package/dist/theme/components/home/hero-demo.css +66 -0
- package/dist/theme/components/home/hero-demo.tsx +46 -0
- package/dist/theme/components/home/hero.css +96 -0
- package/dist/theme/components/home/hero.tsx +111 -0
- package/dist/theme/components/home/layout.tsx +183 -0
- package/dist/theme/components/home/page-rail.css +21 -0
- package/dist/theme/components/home/page-rail.tsx +19 -0
- package/dist/theme/components/home/split.css +148 -0
- package/dist/theme/components/home/split.tsx +120 -0
- package/dist/theme/components/home/trust-strip.css +33 -0
- package/dist/theme/components/home/trust-strip.tsx +43 -0
- package/dist/theme/components/home/workspaces.tsx +71 -0
- package/dist/theme/components/nav/branch-tag.css +54 -0
- package/dist/theme/components/nav/branch-tag.tsx +101 -0
- package/dist/theme/components/nav/ciderpress-doc-layout.tsx +247 -0
- package/dist/theme/components/nav/ciderpress-docs-bar.css +505 -0
- package/dist/theme/components/nav/ciderpress-docs-bar.tsx +426 -0
- package/dist/theme/components/nav/ciderpress-header.css +172 -0
- package/dist/theme/components/nav/ciderpress-header.tsx +113 -0
- package/dist/theme/components/nav/ciderpress-layout-context.tsx +49 -0
- package/dist/theme/components/nav/ciderpress-nav-hamburger.css +193 -0
- package/dist/theme/components/nav/ciderpress-nav-hamburger.tsx +112 -0
- package/dist/theme/components/nav/ciderpress-nav-menu.css +130 -0
- package/dist/theme/components/nav/ciderpress-nav-menu.tsx +372 -0
- package/dist/theme/components/nav/ciderpress-nav-search.css +73 -0
- package/dist/theme/components/nav/ciderpress-nav-search.tsx +55 -0
- package/dist/theme/components/nav/ciderpress-nav-social-links.css +35 -0
- package/dist/theme/components/nav/ciderpress-nav-social-links.tsx +87 -0
- package/dist/theme/components/nav/floating-branch-indicator.css +106 -0
- package/dist/theme/components/nav/floating-branch-indicator.tsx +109 -0
- package/dist/theme/components/nav/layout.tsx +268 -0
- package/dist/theme/components/nav/mobile-nav-cta.tsx +79 -0
- package/dist/theme/components/nav/nav-divider.css +15 -0
- package/dist/theme/components/nav/nav-divider.tsx +19 -0
- package/dist/theme/components/nav/nav-logo.css +42 -0
- package/dist/theme/components/nav/nav-logo.tsx +262 -0
- package/dist/theme/components/nav/theme-switcher.css +92 -0
- package/dist/theme/components/nav/theme-switcher.tsx +298 -0
- package/dist/theme/components/nav/topbar-cta.css +45 -0
- package/dist/theme/components/nav/topbar-cta.tsx +39 -0
- package/dist/theme/components/nav/variant-toggle.css +70 -0
- package/dist/theme/components/nav/variant-toggle.tsx +83 -0
- package/dist/theme/components/nav/version-chip.css +31 -0
- package/dist/theme/components/nav/version-chip.tsx +45 -0
- package/dist/theme/components/nav/vscode-tag.css +32 -0
- package/dist/theme/components/nav/vscode-tag.tsx +20 -0
- package/dist/theme/components/openapi/code-sample.tsx +341 -0
- package/dist/theme/components/openapi/copy-markdown-button.tsx +41 -0
- package/dist/theme/components/openapi/icons.tsx +45 -0
- package/dist/theme/components/openapi/index.ts +6 -0
- package/dist/theme/components/openapi/method-badge.tsx +24 -0
- package/dist/theme/components/openapi/openapi.css +665 -0
- package/dist/theme/components/openapi/operation.tsx +200 -0
- package/dist/theme/components/openapi/overview.tsx +207 -0
- package/dist/theme/components/openapi/parameters-table.tsx +149 -0
- package/dist/theme/components/openapi/request-body.tsx +90 -0
- package/dist/theme/components/openapi/response-list.tsx +112 -0
- package/dist/theme/components/openapi/schema-viewer.tsx +277 -0
- package/dist/theme/components/openapi/security-badges.tsx +63 -0
- package/dist/theme/components/openapi/spec-utils.ts +122 -0
- package/dist/theme/components/shared/accordion.css +118 -0
- package/dist/theme/components/shared/accordion.stories.tsx +96 -0
- package/dist/theme/components/shared/accordion.tsx +191 -0
- package/dist/theme/components/shared/brand-logo.stories.tsx +49 -0
- package/dist/theme/components/shared/brand-mark.stories.tsx +53 -0
- package/dist/theme/components/shared/browser-window.css +1 -0
- package/dist/theme/components/shared/browser-window.stories.tsx +100 -0
- package/dist/theme/components/shared/browser-window.tsx +2 -0
- package/dist/theme/components/shared/card.stories.tsx +50 -0
- package/dist/theme/components/shared/card.tsx +35 -0
- package/dist/theme/components/shared/ciderpress-logo.tsx +93 -0
- package/dist/theme/components/shared/ciderpress-mark.tsx +77 -0
- package/dist/theme/components/shared/color.css +56 -0
- package/dist/theme/components/shared/color.stories.tsx +47 -0
- package/dist/theme/components/shared/color.tsx +69 -0
- package/dist/theme/components/shared/columns.css +37 -0
- package/dist/theme/components/shared/columns.stories.tsx +91 -0
- package/dist/theme/components/shared/columns.tsx +50 -0
- package/dist/theme/components/shared/desktop-window.css +339 -0
- package/dist/theme/components/shared/desktop-window.tsx +535 -0
- package/dist/theme/components/shared/field.css +158 -0
- package/dist/theme/components/shared/field.stories.tsx +100 -0
- package/dist/theme/components/shared/field.tsx +186 -0
- package/dist/theme/components/shared/frame.css +39 -0
- package/dist/theme/components/shared/frame.stories.tsx +49 -0
- package/dist/theme/components/shared/frame.tsx +76 -0
- package/dist/theme/components/shared/icon.stories.tsx +90 -0
- package/dist/theme/components/shared/icon.tsx +41 -0
- package/dist/theme/components/shared/prompt.css +178 -0
- package/dist/theme/components/shared/prompt.stories.tsx +57 -0
- package/dist/theme/components/shared/prompt.tsx +369 -0
- package/dist/theme/components/shared/resolve-card-icon.ts +28 -0
- package/dist/theme/components/shared/section-card.stories.tsx +51 -0
- package/dist/theme/components/shared/section-card.tsx +44 -0
- package/dist/theme/components/shared/section-grid.stories.tsx +46 -0
- package/dist/theme/components/shared/section-grid.tsx +15 -0
- package/dist/theme/components/shared/status-badge.css +37 -0
- package/dist/theme/components/shared/status-badge.stories.tsx +61 -0
- package/dist/theme/components/shared/status-badge.tsx +74 -0
- package/dist/theme/components/shared/steps.css +88 -0
- package/dist/theme/components/shared/steps.stories.tsx +68 -0
- package/dist/theme/components/shared/steps.tsx +100 -0
- package/dist/theme/components/shared/tech-icon-table.stories.tsx +29 -0
- package/dist/theme/components/shared/tech-icon-table.tsx +71 -0
- package/dist/theme/components/shared/tech-tag.stories.tsx +40 -0
- package/dist/theme/components/shared/tech-tag.tsx +31 -0
- package/dist/theme/components/shared/theme-color-palette.css +80 -0
- package/dist/theme/components/shared/theme-color-palette.stories.tsx +52 -0
- package/dist/theme/components/shared/theme-color-palette.tsx +275 -0
- package/dist/theme/components/shared/tooltip.css +69 -0
- package/dist/theme/components/shared/tooltip.stories.tsx +72 -0
- package/dist/theme/components/shared/tooltip.tsx +77 -0
- package/dist/theme/components/sidebar/framework-picker.css +77 -0
- package/dist/theme/components/sidebar/framework-picker.tsx +78 -0
- package/dist/theme/components/sidebar/sidebar-filter.test.ts +140 -0
- package/dist/theme/components/sidebar/sidebar-filter.ts +79 -0
- package/dist/theme/components/sidebar/sidebar-links.css +102 -0
- package/dist/theme/components/sidebar/sidebar-links.tsx +122 -0
- package/dist/theme/components/sidebar/sidebar-promo.css +42 -0
- package/dist/theme/components/sidebar/sidebar-promo.tsx +52 -0
- package/dist/theme/components/sidebar/sidebar-scope.tsx +151 -0
- package/dist/theme/components/sidebar/sidebar-toggle.css +181 -0
- package/dist/theme/components/sidebar/sidebar-toggle.tsx +127 -0
- package/dist/theme/components/theme-provider.tsx +637 -0
- package/dist/theme/components/workspaces/card.css +151 -0
- package/dist/theme/components/workspaces/card.tsx +166 -0
- package/dist/theme/components/workspaces/grid.tsx +62 -0
- package/dist/theme/css.d.ts +1 -0
- package/dist/theme/env.d.ts +12 -0
- package/dist/theme/fonts/GeistMono-Variable.woff2 +0 -0
- package/dist/theme/fonts/GeistPixel-Square.woff2 +0 -0
- package/dist/theme/fonts/GeistSans-Variable.woff2 +0 -0
- package/dist/theme/hooks/use-ciderpress.ts +61 -0
- package/dist/theme/hooks/use-nav-items.ts +76 -0
- package/dist/theme/icons/index.ts +2 -0
- package/dist/theme/icons/tech-map.ts +228 -0
- package/dist/theme/index.tsx +180 -0
- package/dist/theme/lib/read-social-links.ts +27 -0
- package/dist/theme/lib/route-link.tsx +126 -0
- package/dist/theme/lib/safe-url.test.ts +0 -0
- package/dist/theme/lib/safe-url.ts +68 -0
- package/dist/theme/lib/theme-favicon.ts +125 -0
- package/dist/theme/lib/user-config-stub.ts +12 -0
- package/dist/theme/styles/layers.css +32 -0
- package/dist/theme/styles/overrides/badge.css +26 -0
- package/dist/theme/styles/overrides/content-footer.css +80 -0
- package/dist/theme/styles/overrides/details.css +61 -0
- package/dist/theme/styles/overrides/fonts.css +32 -0
- package/dist/theme/styles/overrides/home-card.css +133 -0
- package/dist/theme/styles/overrides/home.css +243 -0
- package/dist/theme/styles/overrides/rail.css +337 -0
- package/dist/theme/styles/overrides/rspress.css +62 -0
- package/dist/theme/styles/overrides/scrollbar.css +25 -0
- package/dist/theme/styles/overrides/section-card.css +114 -0
- package/dist/theme/styles/overrides/sidebar.css +144 -0
- package/dist/theme/styles/overrides/tokens.css +288 -0
- package/dist/theme/styles/overrides/vscode.css +88 -0
- package/dist/theme/styles/themes/amber.css +545 -0
- package/dist/theme/styles/themes/arcade-fx.css +366 -0
- package/dist/theme/styles/themes/arcade.css +273 -0
- package/dist/theme/styles/themes/grannysmith.css +545 -0
- package/dist/theme/styles/themes/honeycrisp.css +545 -0
- package/dist/theme/styles/themes/midnight.css +273 -0
- package/dist/theme/styles/themes/mulled.css +817 -0
- package/package.json +103 -0
- package/src/theme/components/announcement/announcement-bar.css +103 -0
- package/src/theme/components/announcement/announcement-bar.tsx +173 -0
- package/src/theme/components/ask-ai/ask-ai-button.css +52 -0
- package/src/theme/components/ask-ai/ask-ai-button.tsx +56 -0
- package/src/theme/components/content-footer/content-footer-portal.tsx +70 -0
- package/src/theme/components/content-footer/feedback.css +47 -0
- package/src/theme/components/content-footer/feedback.tsx +96 -0
- package/src/theme/components/content-footer/meta-actions.css +25 -0
- package/src/theme/components/content-footer/meta-actions.tsx +57 -0
- package/src/theme/components/content-footer/page-pager.css +61 -0
- package/src/theme/components/content-footer/page-pager.tsx +110 -0
- package/src/theme/components/edit-source-button.tsx +97 -0
- package/src/theme/components/footer/site-footer.css +179 -0
- package/src/theme/components/footer/site-footer.tsx +115 -0
- package/src/theme/components/home/cta.css +67 -0
- package/src/theme/components/home/cta.tsx +77 -0
- package/src/theme/components/home/feature-card.css +52 -0
- package/src/theme/components/home/feature-card.tsx +131 -0
- package/src/theme/components/home/feature.tsx +79 -0
- package/src/theme/components/home/hero-demo.css +66 -0
- package/src/theme/components/home/hero-demo.tsx +46 -0
- package/src/theme/components/home/hero.css +96 -0
- package/src/theme/components/home/hero.tsx +111 -0
- package/src/theme/components/home/layout.tsx +183 -0
- package/src/theme/components/home/page-rail.css +21 -0
- package/src/theme/components/home/page-rail.tsx +19 -0
- package/src/theme/components/home/split.css +148 -0
- package/src/theme/components/home/split.tsx +120 -0
- package/src/theme/components/home/trust-strip.css +33 -0
- package/src/theme/components/home/trust-strip.tsx +43 -0
- package/src/theme/components/home/workspaces.tsx +71 -0
- package/src/theme/components/nav/branch-tag.css +54 -0
- package/src/theme/components/nav/branch-tag.tsx +101 -0
- package/src/theme/components/nav/ciderpress-doc-layout.tsx +247 -0
- package/src/theme/components/nav/ciderpress-docs-bar.css +505 -0
- package/src/theme/components/nav/ciderpress-docs-bar.tsx +426 -0
- package/src/theme/components/nav/ciderpress-header.css +172 -0
- package/src/theme/components/nav/ciderpress-header.tsx +113 -0
- package/src/theme/components/nav/ciderpress-layout-context.tsx +49 -0
- package/src/theme/components/nav/ciderpress-nav-hamburger.css +193 -0
- package/src/theme/components/nav/ciderpress-nav-hamburger.tsx +112 -0
- package/src/theme/components/nav/ciderpress-nav-menu.css +130 -0
- package/src/theme/components/nav/ciderpress-nav-menu.tsx +372 -0
- package/src/theme/components/nav/ciderpress-nav-search.css +73 -0
- package/src/theme/components/nav/ciderpress-nav-search.tsx +55 -0
- package/src/theme/components/nav/ciderpress-nav-social-links.css +35 -0
- package/src/theme/components/nav/ciderpress-nav-social-links.tsx +87 -0
- package/src/theme/components/nav/floating-branch-indicator.css +106 -0
- package/src/theme/components/nav/floating-branch-indicator.tsx +109 -0
- package/src/theme/components/nav/layout.tsx +268 -0
- package/src/theme/components/nav/mobile-nav-cta.tsx +79 -0
- package/src/theme/components/nav/nav-divider.css +15 -0
- package/src/theme/components/nav/nav-divider.tsx +19 -0
- package/src/theme/components/nav/nav-logo.css +42 -0
- package/src/theme/components/nav/nav-logo.tsx +262 -0
- package/src/theme/components/nav/theme-switcher.css +92 -0
- package/src/theme/components/nav/theme-switcher.tsx +298 -0
- package/src/theme/components/nav/topbar-cta.css +45 -0
- package/src/theme/components/nav/topbar-cta.tsx +39 -0
- package/src/theme/components/nav/variant-toggle.css +70 -0
- package/src/theme/components/nav/variant-toggle.tsx +83 -0
- package/src/theme/components/nav/version-chip.css +31 -0
- package/src/theme/components/nav/version-chip.tsx +45 -0
- package/src/theme/components/nav/vscode-tag.css +32 -0
- package/src/theme/components/nav/vscode-tag.tsx +20 -0
- package/src/theme/components/openapi/code-sample.tsx +341 -0
- package/src/theme/components/openapi/copy-markdown-button.tsx +41 -0
- package/src/theme/components/openapi/icons.tsx +45 -0
- package/src/theme/components/openapi/index.ts +6 -0
- package/src/theme/components/openapi/method-badge.tsx +24 -0
- package/src/theme/components/openapi/openapi.css +665 -0
- package/src/theme/components/openapi/operation.tsx +200 -0
- package/src/theme/components/openapi/overview.tsx +207 -0
- package/src/theme/components/openapi/parameters-table.tsx +149 -0
- package/src/theme/components/openapi/request-body.tsx +90 -0
- package/src/theme/components/openapi/response-list.tsx +112 -0
- package/src/theme/components/openapi/schema-viewer.tsx +277 -0
- package/src/theme/components/openapi/security-badges.tsx +63 -0
- package/src/theme/components/openapi/spec-utils.ts +122 -0
- package/src/theme/components/shared/accordion.css +118 -0
- package/src/theme/components/shared/accordion.stories.tsx +96 -0
- package/src/theme/components/shared/accordion.tsx +191 -0
- package/src/theme/components/shared/brand-logo.stories.tsx +49 -0
- package/src/theme/components/shared/brand-mark.stories.tsx +53 -0
- package/src/theme/components/shared/browser-window.css +1 -0
- package/src/theme/components/shared/browser-window.stories.tsx +100 -0
- package/src/theme/components/shared/browser-window.tsx +2 -0
- package/src/theme/components/shared/card.stories.tsx +50 -0
- package/src/theme/components/shared/card.tsx +35 -0
- package/src/theme/components/shared/ciderpress-logo.tsx +93 -0
- package/src/theme/components/shared/ciderpress-mark.tsx +77 -0
- package/src/theme/components/shared/color.css +56 -0
- package/src/theme/components/shared/color.stories.tsx +47 -0
- package/src/theme/components/shared/color.tsx +69 -0
- package/src/theme/components/shared/columns.css +37 -0
- package/src/theme/components/shared/columns.stories.tsx +91 -0
- package/src/theme/components/shared/columns.tsx +50 -0
- package/src/theme/components/shared/desktop-window.css +339 -0
- package/src/theme/components/shared/desktop-window.tsx +535 -0
- package/src/theme/components/shared/field.css +158 -0
- package/src/theme/components/shared/field.stories.tsx +100 -0
- package/src/theme/components/shared/field.tsx +186 -0
- package/src/theme/components/shared/frame.css +39 -0
- package/src/theme/components/shared/frame.stories.tsx +49 -0
- package/src/theme/components/shared/frame.tsx +76 -0
- package/src/theme/components/shared/icon.stories.tsx +90 -0
- package/src/theme/components/shared/icon.tsx +41 -0
- package/src/theme/components/shared/prompt.css +178 -0
- package/src/theme/components/shared/prompt.stories.tsx +57 -0
- package/src/theme/components/shared/prompt.tsx +369 -0
- package/src/theme/components/shared/resolve-card-icon.ts +28 -0
- package/src/theme/components/shared/section-card.stories.tsx +51 -0
- package/src/theme/components/shared/section-card.tsx +44 -0
- package/src/theme/components/shared/section-grid.stories.tsx +46 -0
- package/src/theme/components/shared/section-grid.tsx +15 -0
- package/src/theme/components/shared/status-badge.css +37 -0
- package/src/theme/components/shared/status-badge.stories.tsx +61 -0
- package/src/theme/components/shared/status-badge.tsx +74 -0
- package/src/theme/components/shared/steps.css +88 -0
- package/src/theme/components/shared/steps.stories.tsx +68 -0
- package/src/theme/components/shared/steps.tsx +100 -0
- package/src/theme/components/shared/tech-icon-table.stories.tsx +29 -0
- package/src/theme/components/shared/tech-icon-table.tsx +71 -0
- package/src/theme/components/shared/tech-tag.stories.tsx +40 -0
- package/src/theme/components/shared/tech-tag.tsx +31 -0
- package/src/theme/components/shared/theme-color-palette.css +80 -0
- package/src/theme/components/shared/theme-color-palette.stories.tsx +52 -0
- package/src/theme/components/shared/theme-color-palette.tsx +275 -0
- package/src/theme/components/shared/tooltip.css +69 -0
- package/src/theme/components/shared/tooltip.stories.tsx +72 -0
- package/src/theme/components/shared/tooltip.tsx +77 -0
- package/src/theme/components/sidebar/framework-picker.css +77 -0
- package/src/theme/components/sidebar/framework-picker.tsx +78 -0
- package/src/theme/components/sidebar/sidebar-filter.test.ts +140 -0
- package/src/theme/components/sidebar/sidebar-filter.ts +79 -0
- package/src/theme/components/sidebar/sidebar-links.css +102 -0
- package/src/theme/components/sidebar/sidebar-links.tsx +122 -0
- package/src/theme/components/sidebar/sidebar-promo.css +42 -0
- package/src/theme/components/sidebar/sidebar-promo.tsx +52 -0
- package/src/theme/components/sidebar/sidebar-scope.tsx +151 -0
- package/src/theme/components/sidebar/sidebar-toggle.css +181 -0
- package/src/theme/components/sidebar/sidebar-toggle.tsx +127 -0
- package/src/theme/components/theme-provider.tsx +637 -0
- package/src/theme/components/workspaces/card.css +151 -0
- package/src/theme/components/workspaces/card.tsx +166 -0
- package/src/theme/components/workspaces/grid.tsx +62 -0
- package/src/theme/css.d.ts +1 -0
- package/src/theme/env.d.ts +12 -0
- package/src/theme/fonts/GeistMono-Variable.woff2 +0 -0
- package/src/theme/fonts/GeistPixel-Square.woff2 +0 -0
- package/src/theme/fonts/GeistSans-Variable.woff2 +0 -0
- package/src/theme/hooks/use-ciderpress.ts +61 -0
- package/src/theme/hooks/use-nav-items.ts +76 -0
- package/src/theme/icons/index.ts +2 -0
- package/src/theme/icons/tech-map.ts +228 -0
- package/src/theme/index.tsx +180 -0
- package/src/theme/lib/read-social-links.ts +27 -0
- package/src/theme/lib/route-link.tsx +126 -0
- package/src/theme/lib/safe-url.test.ts +0 -0
- package/src/theme/lib/safe-url.ts +68 -0
- package/src/theme/lib/theme-favicon.ts +125 -0
- package/src/theme/lib/user-config-stub.ts +12 -0
- package/src/theme/styles/layers.css +32 -0
- package/src/theme/styles/overrides/badge.css +26 -0
- package/src/theme/styles/overrides/content-footer.css +80 -0
- package/src/theme/styles/overrides/details.css +61 -0
- package/src/theme/styles/overrides/fonts.css +32 -0
- package/src/theme/styles/overrides/home-card.css +133 -0
- package/src/theme/styles/overrides/home.css +243 -0
- package/src/theme/styles/overrides/rail.css +337 -0
- package/src/theme/styles/overrides/rspress.css +62 -0
- package/src/theme/styles/overrides/scrollbar.css +25 -0
- package/src/theme/styles/overrides/section-card.css +114 -0
- package/src/theme/styles/overrides/sidebar.css +144 -0
- package/src/theme/styles/overrides/tokens.css +288 -0
- package/src/theme/styles/overrides/vscode.css +88 -0
- package/src/theme/styles/themes/amber.css +545 -0
- package/src/theme/styles/themes/arcade-fx.css +366 -0
- package/src/theme/styles/themes/arcade.css +273 -0
- package/src/theme/styles/themes/grannysmith.css +545 -0
- package/src/theme/styles/themes/honeycrisp.css +545 -0
- package/src/theme/styles/themes/midnight.css +273 -0
- package/src/theme/styles/themes/mulled.css +817 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Floating git-branch indicator — pinned to the bottom-right viewport
|
|
3
|
+
* corner. Collapsed shows only the git-branch icon (36px circle); on
|
|
4
|
+
* hover/focus the pill expands rightward to reveal the branch name.
|
|
5
|
+
*
|
|
6
|
+
* `right`-anchored so the expansion grows leftward and never clips off the
|
|
7
|
+
* right edge regardless of branch-name length.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
.cp-floating-branch {
|
|
11
|
+
position: fixed;
|
|
12
|
+
bottom: 16px;
|
|
13
|
+
right: 16px;
|
|
14
|
+
z-index: 50;
|
|
15
|
+
|
|
16
|
+
display: inline-flex;
|
|
17
|
+
align-items: center;
|
|
18
|
+
gap: 0;
|
|
19
|
+
|
|
20
|
+
height: 36px;
|
|
21
|
+
width: 36px;
|
|
22
|
+
padding: 0;
|
|
23
|
+
border-radius: 18px;
|
|
24
|
+
|
|
25
|
+
background: var(--cp-c-bg-soft);
|
|
26
|
+
border: 1px solid var(--cp-c-divider);
|
|
27
|
+
color: var(--cp-c-text-3);
|
|
28
|
+
|
|
29
|
+
font-family: var(--cp-font-family-mono);
|
|
30
|
+
font-size: 12px;
|
|
31
|
+
font-weight: 600;
|
|
32
|
+
line-height: 1;
|
|
33
|
+
white-space: nowrap;
|
|
34
|
+
overflow: hidden;
|
|
35
|
+
text-decoration: none !important;
|
|
36
|
+
|
|
37
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.18);
|
|
38
|
+
backdrop-filter: blur(8px);
|
|
39
|
+
|
|
40
|
+
transition:
|
|
41
|
+
width 0.2s ease,
|
|
42
|
+
padding 0.2s ease,
|
|
43
|
+
gap 0.2s ease,
|
|
44
|
+
border-color 0.2s,
|
|
45
|
+
color 0.2s,
|
|
46
|
+
background 0.2s;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.cp-floating-branch:hover,
|
|
50
|
+
.cp-floating-branch:focus-visible {
|
|
51
|
+
width: auto;
|
|
52
|
+
max-width: 240px;
|
|
53
|
+
padding: 0 12px 0 10px;
|
|
54
|
+
gap: 6px;
|
|
55
|
+
|
|
56
|
+
border-color: var(--cp-c-brand-1);
|
|
57
|
+
color: var(--cp-c-brand-1);
|
|
58
|
+
background: var(--cp-c-bg);
|
|
59
|
+
text-decoration: none !important;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.cp-floating-branch:focus-visible {
|
|
63
|
+
outline: 2px solid var(--rp-c-brand);
|
|
64
|
+
outline-offset: 2px;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.cp-floating-branch__icon {
|
|
68
|
+
flex-shrink: 0;
|
|
69
|
+
width: 16px;
|
|
70
|
+
height: 16px;
|
|
71
|
+
margin: 0 auto;
|
|
72
|
+
transition: margin 0.2s ease;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.cp-floating-branch:hover .cp-floating-branch__icon,
|
|
76
|
+
.cp-floating-branch:focus-visible .cp-floating-branch__icon {
|
|
77
|
+
margin: 0;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.cp-floating-branch__text {
|
|
81
|
+
display: inline-block;
|
|
82
|
+
max-width: 0;
|
|
83
|
+
opacity: 0;
|
|
84
|
+
overflow: hidden;
|
|
85
|
+
text-overflow: ellipsis;
|
|
86
|
+
|
|
87
|
+
transition:
|
|
88
|
+
max-width 0.2s ease,
|
|
89
|
+
opacity 0.15s ease;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.cp-floating-branch:hover .cp-floating-branch__text,
|
|
93
|
+
.cp-floating-branch:focus-visible .cp-floating-branch__text {
|
|
94
|
+
max-width: 200px;
|
|
95
|
+
opacity: 1;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/* ── Responsive ──────────────────────────────────────────── */
|
|
99
|
+
/* Mobile: hide the floating branch indicator entirely. The hamburger
|
|
100
|
+
drawer surfaces the same chrome, and a corner-anchored chip
|
|
101
|
+
competes with the on-screen keyboard / browser UI on small viewports. */
|
|
102
|
+
@media (max-width: 768px) {
|
|
103
|
+
.cp-floating-branch {
|
|
104
|
+
display: none;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import type { SiteConfig } from '@ciderpress/config'
|
|
2
|
+
import { match, P } from 'massaman/match'
|
|
3
|
+
import type React from 'react'
|
|
4
|
+
|
|
5
|
+
import { useCiderpress } from '../../hooks/use-ciderpress'
|
|
6
|
+
|
|
7
|
+
import './floating-branch-indicator.css'
|
|
8
|
+
import { Icon } from '../shared/icon.tsx'
|
|
9
|
+
|
|
10
|
+
declare const __CIDERPRESS_GIT_BRANCH__: string | undefined
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Floating git-branch indicator pinned to the bottom-right corner of the
|
|
14
|
+
* viewport. Collapsed: a small circular icon. On hover: expands to reveal
|
|
15
|
+
* the branch name. Click anywhere on the pill opens the branch on GitHub.
|
|
16
|
+
*
|
|
17
|
+
* Hidden when on default branches (`main` / `master`), when the
|
|
18
|
+
* build-time branch global is undefined, or when `site.edit.repo` is
|
|
19
|
+
* not configured.
|
|
20
|
+
*
|
|
21
|
+
* @returns React element or null when hidden
|
|
22
|
+
*/
|
|
23
|
+
export function FloatingBranchIndicator(): React.ReactElement | null {
|
|
24
|
+
const { site } = useCiderpress()
|
|
25
|
+
const branch = resolveBranch()
|
|
26
|
+
|
|
27
|
+
if (!branch || branch === 'main' || branch === 'master') {
|
|
28
|
+
return null
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const href = buildBranchHref({ repo: resolveRepo(site), branch })
|
|
32
|
+
if (href === null) {
|
|
33
|
+
return null
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return (
|
|
37
|
+
<a
|
|
38
|
+
className="cp-floating-branch"
|
|
39
|
+
href={href}
|
|
40
|
+
target="_blank"
|
|
41
|
+
rel="noopener noreferrer"
|
|
42
|
+
title={`Branch: ${branch}`}
|
|
43
|
+
>
|
|
44
|
+
<Icon
|
|
45
|
+
icon="pixelarticons:git-branch"
|
|
46
|
+
width={16}
|
|
47
|
+
height={16}
|
|
48
|
+
className="cp-floating-branch__icon"
|
|
49
|
+
/>
|
|
50
|
+
<span className="cp-floating-branch__text">{branch}</span>
|
|
51
|
+
</a>
|
|
52
|
+
)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export { FloatingBranchIndicator as default }
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Resolves the current git branch name from the build-time global,
|
|
59
|
+
* returning an empty string when undefined.
|
|
60
|
+
*
|
|
61
|
+
* @private
|
|
62
|
+
* @returns Current git branch name or empty string
|
|
63
|
+
*/
|
|
64
|
+
function resolveBranch(): string {
|
|
65
|
+
if (__CIDERPRESS_GIT_BRANCH__ !== undefined) {
|
|
66
|
+
return __CIDERPRESS_GIT_BRANCH__
|
|
67
|
+
}
|
|
68
|
+
return ''
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Build a GitHub `/tree/<branch>` URL from the configured `site.edit.repo`.
|
|
73
|
+
*
|
|
74
|
+
* Accepts either a full URL (used as-is) or an `org/repo` slug
|
|
75
|
+
* (prefixed with `https://github.com/`). Returns `null` when `repo` is
|
|
76
|
+
* missing so the caller can omit the component entirely.
|
|
77
|
+
*
|
|
78
|
+
* @private
|
|
79
|
+
* @param params - The configured repo and the current branch.
|
|
80
|
+
* @returns Fully-qualified URL string, or `null` when unconfigured.
|
|
81
|
+
*/
|
|
82
|
+
function buildBranchHref(params: {
|
|
83
|
+
readonly repo: string | undefined
|
|
84
|
+
readonly branch: string
|
|
85
|
+
}): string | null {
|
|
86
|
+
return match(params.repo)
|
|
87
|
+
.with(undefined, () => null)
|
|
88
|
+
.with('', () => null)
|
|
89
|
+
.with(P.string.startsWith('http'), (full) => `${full}/tree/${params.branch}`)
|
|
90
|
+
.otherwise((slug) => `https://github.com/${slug}/tree/${params.branch}`)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Pull the configured edit-repo slug off the site config, expressed
|
|
95
|
+
* with explicit null checks rather than optional chaining.
|
|
96
|
+
*
|
|
97
|
+
* @private
|
|
98
|
+
* @param site - The ciderpress site config (may be undefined).
|
|
99
|
+
* @returns The configured `edit.repo` value or `undefined`.
|
|
100
|
+
*/
|
|
101
|
+
function resolveRepo(site: SiteConfig | undefined): string | undefined {
|
|
102
|
+
if (site === undefined) {
|
|
103
|
+
return undefined
|
|
104
|
+
}
|
|
105
|
+
if (site.edit === undefined) {
|
|
106
|
+
return undefined
|
|
107
|
+
}
|
|
108
|
+
return site.edit.repo
|
|
109
|
+
}
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
import type { SiteEditConfig, SiteReportConfig } from '@ciderpress/config'
|
|
2
|
+
import { useFrontmatter, useSite } from '@rspress/core/runtime'
|
|
3
|
+
import { Layout as OriginalLayout } from '@rspress/core/theme-original'
|
|
4
|
+
import { match, P } from 'massaman/match'
|
|
5
|
+
import type React from 'react'
|
|
6
|
+
import { useEffect } from 'react'
|
|
7
|
+
|
|
8
|
+
import { useCiderpress } from '../../hooks/use-ciderpress'
|
|
9
|
+
import { useNavItems } from '../../hooks/use-nav-items'
|
|
10
|
+
import { readSocialLinks } from '../../lib/read-social-links'
|
|
11
|
+
import { AnnouncementBar } from '../announcement/announcement-bar'
|
|
12
|
+
import { ContentFooterPortal } from '../content-footer/content-footer-portal'
|
|
13
|
+
import { Feedback } from '../content-footer/feedback'
|
|
14
|
+
import type { MetaAction } from '../content-footer/meta-actions'
|
|
15
|
+
import { MetaActions } from '../content-footer/meta-actions'
|
|
16
|
+
import { SiteFooter } from '../footer/site-footer'
|
|
17
|
+
import { SidebarLinks } from '../sidebar/sidebar-links'
|
|
18
|
+
import { SidebarPromo } from '../sidebar/sidebar-promo'
|
|
19
|
+
import { CiderpressDocsBar } from './ciderpress-docs-bar'
|
|
20
|
+
import { CiderpressHeader } from './ciderpress-header'
|
|
21
|
+
import type { CiderpressNavMenuItem } from './ciderpress-nav-menu'
|
|
22
|
+
import { FloatingBranchIndicator } from './floating-branch-indicator'
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Custom Layout override for ciderpress.
|
|
26
|
+
*
|
|
27
|
+
* Renders `<CiderpressHeader />` as the entire site header chrome
|
|
28
|
+
* (Rspress's `.rp-nav` is hidden via CSS in `ciderpress-header.css`).
|
|
29
|
+
* `<OriginalLayout />` is kept around purely to render Rspress's
|
|
30
|
+
* sidebar + article body + footer; every nav-related slot is fed
|
|
31
|
+
* `null` so Rspress doesn't render its own chrome.
|
|
32
|
+
*
|
|
33
|
+
* Slots still in use:
|
|
34
|
+
* - `beforeSidebar`: SidebarLinks (above) and the `.cp-sidebar-top` band
|
|
35
|
+
* - `afterSidebar`: SidebarLinks (below) plus SidebarPromo
|
|
36
|
+
* - `afterDoc`: Feedback + MetaActions portalled into the doc footer
|
|
37
|
+
* - `bottom`: SiteFooter on doc pages
|
|
38
|
+
*
|
|
39
|
+
* @returns React element with the custom layout
|
|
40
|
+
*/
|
|
41
|
+
export function Layout(): React.ReactElement {
|
|
42
|
+
// Rspress's `.rp-nav` is visually hidden via `ciderpress-header.css`
|
|
43
|
+
// but stays in the a11y tree, producing duplicate `banner` landmarks
|
|
44
|
+
// alongside our `<CiderpressHeader>`. Mark it aria-hidden after mount
|
|
45
|
+
// so screen readers ignore it. The element lives for the layout's
|
|
46
|
+
// lifetime, so no cleanup is required.
|
|
47
|
+
useEffect(() => {
|
|
48
|
+
const rpNav = document.querySelector('.rp-nav')
|
|
49
|
+
if (rpNav !== null) {
|
|
50
|
+
rpNav.setAttribute('aria-hidden', 'true')
|
|
51
|
+
}
|
|
52
|
+
}, [])
|
|
53
|
+
|
|
54
|
+
const { sidebarAbove, sidebarBelow, site } = useCiderpress()
|
|
55
|
+
const { site: rspressSite } = useSite()
|
|
56
|
+
const configNavItems = readNavItems(rspressSite)
|
|
57
|
+
const scrapedNavItems = useNavItems()
|
|
58
|
+
const navItems = match(configNavItems.length > 0)
|
|
59
|
+
.with(true, () => configNavItems)
|
|
60
|
+
.otherwise(() => scrapedNavItems)
|
|
61
|
+
const socialLinks = readSocialLinks(rspressSite)
|
|
62
|
+
const { announcement, topbarCta, sidebarPromo: sidebarPromoConfig, edit, report } = site ?? {}
|
|
63
|
+
const { frontmatter } = useFrontmatter()
|
|
64
|
+
const fmRecord = frontmatter as Record<string, unknown>
|
|
65
|
+
const isHome = fmRecord.pageType === 'home'
|
|
66
|
+
const isBlank = fmRecord.pageType === 'blank'
|
|
67
|
+
const filepathValue = fmRecord.__filepath
|
|
68
|
+
const pagePath = match(filepathValue)
|
|
69
|
+
.with(P.string, (v) => v)
|
|
70
|
+
.otherwise(() => '')
|
|
71
|
+
|
|
72
|
+
const announcementSlot = match(announcement)
|
|
73
|
+
.with(undefined, () => null)
|
|
74
|
+
.otherwise((a) => (
|
|
75
|
+
<AnnouncementBar id={a.id} lead={a.lead} cta={a.cta} persistent={a.persistent}>
|
|
76
|
+
{a.message}
|
|
77
|
+
</AnnouncementBar>
|
|
78
|
+
))
|
|
79
|
+
|
|
80
|
+
const aboveItems = sidebarAbove ?? []
|
|
81
|
+
const belowItems = sidebarBelow ?? []
|
|
82
|
+
|
|
83
|
+
const beforeSidebar = match(aboveItems.length > 0)
|
|
84
|
+
.with(true, () => (
|
|
85
|
+
<div className="cp-sidebar-top">
|
|
86
|
+
<SidebarLinks items={aboveItems} position="above" />
|
|
87
|
+
</div>
|
|
88
|
+
))
|
|
89
|
+
.otherwise(() => null)
|
|
90
|
+
|
|
91
|
+
const sidebarPromo = match(sidebarPromoConfig)
|
|
92
|
+
.with(undefined, () => null)
|
|
93
|
+
.otherwise((p) => (
|
|
94
|
+
<SidebarPromo title={p.title} body={p.body} ctaText={p.cta.text} ctaHref={p.cta.href} />
|
|
95
|
+
))
|
|
96
|
+
|
|
97
|
+
const belowLinks = match(belowItems.length > 0)
|
|
98
|
+
.with(true, () => <SidebarLinks items={belowItems} position="below" />)
|
|
99
|
+
.otherwise(() => null)
|
|
100
|
+
|
|
101
|
+
const afterSidebar = match(belowLinks === null && sidebarPromo === null)
|
|
102
|
+
.with(true, () => null)
|
|
103
|
+
.otherwise(() => (
|
|
104
|
+
<div className="cp-sidebar-bottom">
|
|
105
|
+
{belowLinks}
|
|
106
|
+
{sidebarPromo}
|
|
107
|
+
</div>
|
|
108
|
+
))
|
|
109
|
+
|
|
110
|
+
const bottomSlot = match(isHome || isBlank)
|
|
111
|
+
.with(true, () => null)
|
|
112
|
+
.otherwise(() => <SiteFooter />)
|
|
113
|
+
|
|
114
|
+
const metaActions = collectMetaActions({ edit, report, pagePath })
|
|
115
|
+
|
|
116
|
+
const afterDocSlot = (
|
|
117
|
+
<ContentFooterPortal>
|
|
118
|
+
<Feedback />
|
|
119
|
+
<MetaActions actions={metaActions} />
|
|
120
|
+
</ContentFooterPortal>
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
return (
|
|
124
|
+
<>
|
|
125
|
+
<CiderpressHeader
|
|
126
|
+
announcement={announcementSlot}
|
|
127
|
+
navItems={navItems}
|
|
128
|
+
socialLinks={socialLinks}
|
|
129
|
+
topbarCta={topbarCta}
|
|
130
|
+
isHome={isHome}
|
|
131
|
+
/>
|
|
132
|
+
<OriginalLayout
|
|
133
|
+
top={null}
|
|
134
|
+
beforeNavMenu={null}
|
|
135
|
+
afterNavMenu={null}
|
|
136
|
+
beforeSidebar={beforeSidebar}
|
|
137
|
+
afterSidebar={afterSidebar}
|
|
138
|
+
beforeDoc={<CiderpressDocsBar />}
|
|
139
|
+
afterDoc={afterDocSlot}
|
|
140
|
+
bottom={bottomSlot}
|
|
141
|
+
/>
|
|
142
|
+
<FloatingBranchIndicator />
|
|
143
|
+
</>
|
|
144
|
+
)
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Pull the primary nav menu items off Rspress's `site` shape. The
|
|
149
|
+
* Rspress `SiteData` type doesn't expose `nav` at compile time, so we
|
|
150
|
+
* read through an indexed access and validate the shape at runtime.
|
|
151
|
+
*
|
|
152
|
+
* @private
|
|
153
|
+
* @param site - Rspress site data
|
|
154
|
+
* @returns Array of nav items (empty array when not configured)
|
|
155
|
+
*/
|
|
156
|
+
function readNavItems(site: unknown): readonly CiderpressNavMenuItem[] {
|
|
157
|
+
const candidate = (site as { readonly nav?: unknown }).nav
|
|
158
|
+
if (!Array.isArray(candidate)) {
|
|
159
|
+
return []
|
|
160
|
+
}
|
|
161
|
+
return candidate.filter(
|
|
162
|
+
(item): item is CiderpressNavMenuItem =>
|
|
163
|
+
typeof item === 'object' &&
|
|
164
|
+
item !== null &&
|
|
165
|
+
typeof (item as { text?: unknown }).text === 'string' &&
|
|
166
|
+
typeof (item as { link?: unknown }).link === 'string'
|
|
167
|
+
)
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Build the list of `MetaAction`s to render under each doc page,
|
|
172
|
+
* derived from `site.edit` and `site.report`. Returns an empty array
|
|
173
|
+
* when neither is configured.
|
|
174
|
+
*
|
|
175
|
+
* @private
|
|
176
|
+
* @param params - Site edit/report config plus current page path
|
|
177
|
+
* @returns Ordered list of meta actions
|
|
178
|
+
*/
|
|
179
|
+
function collectMetaActions(params: {
|
|
180
|
+
readonly edit: SiteEditConfig | undefined
|
|
181
|
+
readonly report: SiteReportConfig | undefined
|
|
182
|
+
readonly pagePath: string
|
|
183
|
+
}): readonly MetaAction[] {
|
|
184
|
+
const { edit, report, pagePath } = params
|
|
185
|
+
const editAction = match(edit)
|
|
186
|
+
.with(undefined, () => null)
|
|
187
|
+
.otherwise(
|
|
188
|
+
(e): MetaAction => ({
|
|
189
|
+
label: e.label ?? 'Edit this page on GitHub',
|
|
190
|
+
href: buildEditUrl(e, pagePath),
|
|
191
|
+
icon: <EditIcon />,
|
|
192
|
+
})
|
|
193
|
+
)
|
|
194
|
+
const reportAction = match(report)
|
|
195
|
+
.with(undefined, () => null)
|
|
196
|
+
.otherwise(
|
|
197
|
+
(r): MetaAction => ({
|
|
198
|
+
label: r.label ?? 'Report an issue',
|
|
199
|
+
href: buildReportUrl(r),
|
|
200
|
+
icon: <AlertIcon />,
|
|
201
|
+
})
|
|
202
|
+
)
|
|
203
|
+
return [editAction, reportAction].filter((a): a is MetaAction => a !== null)
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* @private
|
|
208
|
+
*/
|
|
209
|
+
function buildEditUrl(edit: SiteEditConfig, pagePath: string): string {
|
|
210
|
+
if (edit.repo.startsWith('http')) {
|
|
211
|
+
return edit.repo
|
|
212
|
+
}
|
|
213
|
+
const branch = edit.branch ?? 'main'
|
|
214
|
+
const directory = match(edit.directory)
|
|
215
|
+
.with(undefined, () => '')
|
|
216
|
+
.otherwise((d) => `${d.replaceAll(/^\/+|\/+$/g, '')}/`)
|
|
217
|
+
const path = pagePath.replace(/^\/+/, '')
|
|
218
|
+
return `https://github.com/${edit.repo}/edit/${branch}/${directory}${path}`
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* @private
|
|
223
|
+
*/
|
|
224
|
+
function buildReportUrl(report: SiteReportConfig): string {
|
|
225
|
+
if (report.repo.startsWith('http')) {
|
|
226
|
+
return report.repo
|
|
227
|
+
}
|
|
228
|
+
return `https://github.com/${report.repo}/issues/new`
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* @private
|
|
233
|
+
*/
|
|
234
|
+
function EditIcon(): React.ReactElement {
|
|
235
|
+
return (
|
|
236
|
+
<svg
|
|
237
|
+
width="11"
|
|
238
|
+
height="11"
|
|
239
|
+
viewBox="0 0 24 24"
|
|
240
|
+
fill="none"
|
|
241
|
+
stroke="currentColor"
|
|
242
|
+
strokeWidth="2"
|
|
243
|
+
>
|
|
244
|
+
<path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" />
|
|
245
|
+
<path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z" />
|
|
246
|
+
</svg>
|
|
247
|
+
)
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* @private
|
|
252
|
+
*/
|
|
253
|
+
function AlertIcon(): React.ReactElement {
|
|
254
|
+
return (
|
|
255
|
+
<svg
|
|
256
|
+
width="11"
|
|
257
|
+
height="11"
|
|
258
|
+
viewBox="0 0 24 24"
|
|
259
|
+
fill="none"
|
|
260
|
+
stroke="currentColor"
|
|
261
|
+
strokeWidth="2"
|
|
262
|
+
>
|
|
263
|
+
<circle cx="12" cy="12" r="10" />
|
|
264
|
+
<line x1="12" y1="8" x2="12" y2="12" />
|
|
265
|
+
<line x1="12" y1="16" x2="12.01" y2="16" />
|
|
266
|
+
</svg>
|
|
267
|
+
)
|
|
268
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import React, { useEffect, useState } from 'react'
|
|
2
|
+
import { createPortal } from 'react-dom'
|
|
3
|
+
|
|
4
|
+
import { TopbarCTA } from './topbar-cta'
|
|
5
|
+
|
|
6
|
+
export interface MobileNavCTAProps {
|
|
7
|
+
/**
|
|
8
|
+
* CTA button text.
|
|
9
|
+
*/
|
|
10
|
+
readonly text: string
|
|
11
|
+
/**
|
|
12
|
+
* CTA destination href.
|
|
13
|
+
*/
|
|
14
|
+
readonly href: string
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const HOST_ATTR = 'data-cp-mobile-nav-cta-host'
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* MobileNavCTA — portals a primary CTA button into Rspress's mobile
|
|
21
|
+
* nav-screen (`.rp-nav-screen__container`) so users can still reach
|
|
22
|
+
* the get-started action when the topbar CTA is hidden on narrow
|
|
23
|
+
* viewports. Inserts the CTA right before the trailing social-links
|
|
24
|
+
* block so the existing dividers wrap it naturally.
|
|
25
|
+
*
|
|
26
|
+
* Watches DOM mutations because Rspress mounts the nav-screen
|
|
27
|
+
* lazily on first hamburger click and re-mounts on route changes.
|
|
28
|
+
*
|
|
29
|
+
* @param props - CTA configuration.
|
|
30
|
+
* @returns React element.
|
|
31
|
+
*/
|
|
32
|
+
export function MobileNavCTA(props: MobileNavCTAProps): React.ReactElement | null {
|
|
33
|
+
const [host, setHost] = useState<HTMLElement | null>(null)
|
|
34
|
+
|
|
35
|
+
useEffect(() => {
|
|
36
|
+
function ensureHost(): HTMLElement | null {
|
|
37
|
+
const container = globalThis.document.querySelector(
|
|
38
|
+
'.rp-nav-screen__container'
|
|
39
|
+
) as HTMLElement | null
|
|
40
|
+
if (container === null) {
|
|
41
|
+
return null
|
|
42
|
+
}
|
|
43
|
+
const existing = container.querySelector(`[${HOST_ATTR}]`) as HTMLElement | null
|
|
44
|
+
if (existing !== null) {
|
|
45
|
+
return existing
|
|
46
|
+
}
|
|
47
|
+
const node = globalThis.document.createElement('div')
|
|
48
|
+
node.setAttribute(HOST_ATTR, '')
|
|
49
|
+
node.className = 'cp-mobile-nav-cta'
|
|
50
|
+
const socials = container.querySelector('.rp-social-links')
|
|
51
|
+
if (socials === null) {
|
|
52
|
+
container.append(node)
|
|
53
|
+
} else {
|
|
54
|
+
socials.before(node)
|
|
55
|
+
}
|
|
56
|
+
return node
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
setHost(ensureHost())
|
|
60
|
+
|
|
61
|
+
const observer = new globalThis.MutationObserver(() => {
|
|
62
|
+
const next = ensureHost()
|
|
63
|
+
setHost((prev) => {
|
|
64
|
+
if (prev !== null && prev.isConnected) {
|
|
65
|
+
return prev
|
|
66
|
+
}
|
|
67
|
+
return next
|
|
68
|
+
})
|
|
69
|
+
})
|
|
70
|
+
observer.observe(globalThis.document.body, { childList: true, subtree: true })
|
|
71
|
+
|
|
72
|
+
return () => observer.disconnect()
|
|
73
|
+
}, [])
|
|
74
|
+
|
|
75
|
+
if (host === null) {
|
|
76
|
+
return null
|
|
77
|
+
}
|
|
78
|
+
return createPortal(<TopbarCTA text={props.text} href={props.href} />, host)
|
|
79
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vertical nav divider — used inline between groups of topbar elements.
|
|
3
|
+
*
|
|
4
|
+
* Theme-customisable via:
|
|
5
|
+
* --cp-c-divider colour (defaults via the active theme's --cp-c-divider)
|
|
6
|
+
* --cp-nav-divider-height height of the line (default 18px)
|
|
7
|
+
* --cp-nav-divider-width width of the line (default 1px)
|
|
8
|
+
*/
|
|
9
|
+
.cp-nav-divider {
|
|
10
|
+
display: inline-block;
|
|
11
|
+
flex-shrink: 0;
|
|
12
|
+
width: var(--cp-nav-divider-width, 1px);
|
|
13
|
+
height: var(--cp-nav-divider-height, 18px);
|
|
14
|
+
background: var(--cp-c-divider);
|
|
15
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type React from 'react'
|
|
2
|
+
|
|
3
|
+
import './nav-divider.css'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Thin vertical divider used to separate adjacent groups of nav items
|
|
7
|
+
* in the topbar (logo / search / menu / icons / CTA).
|
|
8
|
+
*
|
|
9
|
+
* Themable via the `--cp-c-divider` CSS custom property and the
|
|
10
|
+
* `.cp-nav-divider` class. The divider is `aria-hidden` so it does not
|
|
11
|
+
* pollute the accessibility tree.
|
|
12
|
+
*
|
|
13
|
+
* @returns Inline-flex divider element
|
|
14
|
+
*/
|
|
15
|
+
export function NavDivider(): React.ReactElement {
|
|
16
|
+
return <span className="cp-nav-divider" aria-hidden="true" />
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export { NavDivider as default }
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NavLogo slot — portaled into `.rp-nav__title__link` to render ciderpress's
|
|
3
|
+
* theme-aware `<CiderpressLogo />` SVG or the user's function-form logo.
|
|
4
|
+
*
|
|
5
|
+
* Render pipeline:
|
|
6
|
+
* 1. Initial paint: Rspress emits its native `<img src="/logo.svg">`
|
|
7
|
+
* (the auto-generated static SVG with hardcoded brand color).
|
|
8
|
+
* 2. After hydration: NavLogo's portal mounts a `<span class="cp-nav-logo">`
|
|
9
|
+
* child with an inline SVG that reads `var(--rp-c-brand)` via
|
|
10
|
+
* `currentColor`, giving us theme-aware color switching.
|
|
11
|
+
* 3. CSS below hides the native img + fallback span when our portal mounts
|
|
12
|
+
* so only the theme-aware version shows.
|
|
13
|
+
*
|
|
14
|
+
* The `:has(.cp-nav-logo)` guard means CSS only hides Rspress's native logo
|
|
15
|
+
* when our slot actually mounted — if NavLogo fails for any reason, the
|
|
16
|
+
* static `/logo.svg` stays visible as a graceful fallback.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
.cp-nav-logo {
|
|
20
|
+
display: inline-flex;
|
|
21
|
+
align-items: center;
|
|
22
|
+
line-height: 0;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.cp-nav-logo > svg {
|
|
26
|
+
display: block;
|
|
27
|
+
height: 1.75rem;
|
|
28
|
+
width: auto;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/* When our theme-aware portal mounts, hide Rspress's stock title elements
|
|
32
|
+
so we don't double-render. Covers both:
|
|
33
|
+
- the fallback `<span>title</span>` (rendered when no logo string)
|
|
34
|
+
- the native `<img class="rspress-logo">` (rendered for string logos
|
|
35
|
+
including our `/logo.svg` default).
|
|
36
|
+
The `:not(.cp-nav-logo)` guard is critical — our portal IS a span, so
|
|
37
|
+
a bare `> span` selector would hide it too. */
|
|
38
|
+
.rp-nav__title__link:has(.cp-nav-logo) > span:not(.cp-nav-logo),
|
|
39
|
+
.rp-nav__title__link:has(.cp-nav-logo) > .rp-nav__title__logo,
|
|
40
|
+
.rp-nav__title__link:has(.cp-nav-logo) > img.rspress-logo {
|
|
41
|
+
display: none;
|
|
42
|
+
}
|