@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,178 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prompt — AI prompt block with action buttons and dropdown.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
.cp-prompt {
|
|
6
|
+
display: flex;
|
|
7
|
+
flex-direction: column;
|
|
8
|
+
margin: var(--cp-s-16) 0;
|
|
9
|
+
border: 1px solid var(--cp-c-border);
|
|
10
|
+
border-radius: var(--rp-radius);
|
|
11
|
+
overflow: visible;
|
|
12
|
+
position: relative;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.cp-prompt__header {
|
|
16
|
+
display: flex;
|
|
17
|
+
align-items: center;
|
|
18
|
+
gap: var(--cp-s-10);
|
|
19
|
+
padding: var(--cp-s-10) var(--cp-s-14);
|
|
20
|
+
background: var(--cp-c-bg-elv);
|
|
21
|
+
border-radius: var(--rp-radius);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.cp-prompt__header:has(+ .cp-prompt__code) {
|
|
25
|
+
border-radius: var(--rp-radius) var(--rp-radius) 0 0;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.cp-prompt__icon {
|
|
29
|
+
display: flex;
|
|
30
|
+
align-items: center;
|
|
31
|
+
justify-content: center;
|
|
32
|
+
flex-shrink: 0;
|
|
33
|
+
width: var(--cp-size-prompt-icon);
|
|
34
|
+
height: var(--cp-size-prompt-icon);
|
|
35
|
+
color: var(--cp-c-brand-1);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.cp-prompt__description {
|
|
39
|
+
flex: 1;
|
|
40
|
+
min-width: 0;
|
|
41
|
+
font-size: var(--cp-fs-prompt-desc);
|
|
42
|
+
line-height: var(--cp-lh-base);
|
|
43
|
+
color: var(--cp-c-text-1);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.cp-prompt__feedback {
|
|
47
|
+
font-size: var(--cp-fs-prompt-feedback);
|
|
48
|
+
font-weight: 500;
|
|
49
|
+
color: var(--cp-c-brand-1);
|
|
50
|
+
white-space: nowrap;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.cp-prompt__actions {
|
|
54
|
+
display: inline-flex;
|
|
55
|
+
align-items: center;
|
|
56
|
+
gap: var(--cp-s-4);
|
|
57
|
+
flex-shrink: 0;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/* ── Buttons ──────────────────────────────────────────────── */
|
|
61
|
+
|
|
62
|
+
.cp-prompt__btn {
|
|
63
|
+
display: inline-flex;
|
|
64
|
+
align-items: center;
|
|
65
|
+
justify-content: center;
|
|
66
|
+
gap: var(--cp-s-6);
|
|
67
|
+
padding: 0;
|
|
68
|
+
border: 1px solid var(--cp-c-border);
|
|
69
|
+
border-radius: var(--rp-radius);
|
|
70
|
+
background: var(--cp-c-bg);
|
|
71
|
+
color: var(--cp-c-text-2);
|
|
72
|
+
font-family: var(--cp-font-family-base);
|
|
73
|
+
font-size: var(--cp-fs-prompt-btn);
|
|
74
|
+
font-weight: 500;
|
|
75
|
+
cursor: pointer;
|
|
76
|
+
transition:
|
|
77
|
+
color var(--cp-duration-fast),
|
|
78
|
+
border-color var(--cp-duration-fast),
|
|
79
|
+
background var(--cp-duration-fast);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.cp-prompt__btn:hover {
|
|
83
|
+
color: var(--cp-c-brand-1);
|
|
84
|
+
border-color: var(--cp-c-brand-1);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.cp-prompt__btn--primary {
|
|
88
|
+
padding: var(--cp-s-4) var(--cp-s-12);
|
|
89
|
+
height: var(--cp-size-prompt-btn);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.cp-prompt__btn--icon {
|
|
93
|
+
width: var(--cp-size-prompt-btn);
|
|
94
|
+
height: var(--cp-size-prompt-btn);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/* ── Dropdown ─────────────────────────────────────────────── */
|
|
98
|
+
|
|
99
|
+
.cp-prompt__dropdown {
|
|
100
|
+
position: relative;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.cp-prompt__menu {
|
|
104
|
+
position: absolute;
|
|
105
|
+
top: calc(100% + var(--cp-s-6));
|
|
106
|
+
right: 0;
|
|
107
|
+
z-index: var(--cp-z-dropdown);
|
|
108
|
+
min-width: var(--cp-size-menu-min);
|
|
109
|
+
padding: var(--cp-s-4);
|
|
110
|
+
background: var(--cp-c-bg);
|
|
111
|
+
border: 1px solid var(--cp-c-border);
|
|
112
|
+
border-radius: var(--rp-radius);
|
|
113
|
+
box-shadow: var(--cp-shadow-menu);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.cp-prompt__menu-item {
|
|
117
|
+
display: flex;
|
|
118
|
+
align-items: center;
|
|
119
|
+
gap: var(--cp-s-10);
|
|
120
|
+
width: 100%;
|
|
121
|
+
padding: var(--cp-s-8) var(--cp-s-10);
|
|
122
|
+
border: none;
|
|
123
|
+
border-radius: var(--rp-radius-small);
|
|
124
|
+
background: none;
|
|
125
|
+
color: var(--cp-c-text-1);
|
|
126
|
+
font-family: var(--cp-font-family-base);
|
|
127
|
+
font-size: var(--cp-fs-prompt-menu-item);
|
|
128
|
+
text-align: left;
|
|
129
|
+
cursor: pointer;
|
|
130
|
+
transition: background var(--cp-duration-fast);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
.cp-prompt__menu-item:hover {
|
|
134
|
+
background: var(--cp-c-bg-soft);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.cp-prompt__menu-icon {
|
|
138
|
+
display: flex;
|
|
139
|
+
align-items: center;
|
|
140
|
+
justify-content: center;
|
|
141
|
+
flex-shrink: 0;
|
|
142
|
+
width: var(--cp-size-prompt-menu-icon);
|
|
143
|
+
height: var(--cp-size-prompt-menu-icon);
|
|
144
|
+
color: var(--cp-c-text-2);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.cp-prompt__menu-text {
|
|
148
|
+
display: flex;
|
|
149
|
+
flex-direction: column;
|
|
150
|
+
gap: 1px;
|
|
151
|
+
min-width: 0;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
.cp-prompt__menu-label {
|
|
155
|
+
font-weight: 500;
|
|
156
|
+
line-height: var(--cp-lh-tighter);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
.cp-prompt__menu-desc {
|
|
160
|
+
font-size: var(--cp-fs-prompt-menu-desc);
|
|
161
|
+
color: var(--cp-c-text-3);
|
|
162
|
+
line-height: var(--cp-lh-tighter);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/* ── Hidden raw & Code block ──────────────────────────────── */
|
|
166
|
+
|
|
167
|
+
.cp-prompt__raw {
|
|
168
|
+
display: none;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
.cp-prompt__code {
|
|
172
|
+
border-top: 1px solid var(--cp-c-border);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.cp-prompt__code div[class*='language-'] {
|
|
176
|
+
margin: 0 !important;
|
|
177
|
+
border-radius: 0 0 var(--rp-radius) var(--rp-radius) !important;
|
|
178
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { Story } from '@ladle/react'
|
|
2
|
+
|
|
3
|
+
import { Prompt } from './prompt.tsx'
|
|
4
|
+
|
|
5
|
+
const meta = {
|
|
6
|
+
title: 'Data Display / Prompt',
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export default meta
|
|
10
|
+
|
|
11
|
+
const SAMPLE_PROMPT = `You are a senior TypeScript engineer. Review the diff below and flag
|
|
12
|
+
correctness issues, edge cases, and missing tests. Be terse and prescriptive
|
|
13
|
+
— no praise, no recap.`
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Default — description, copy action, and an expandable code view of
|
|
17
|
+
* the raw prompt text.
|
|
18
|
+
*
|
|
19
|
+
* @returns Prompt with single Copy action
|
|
20
|
+
*/
|
|
21
|
+
// oxlint-disable-next-line func-style -- Ladle stories use `export const`
|
|
22
|
+
export const Default: Story = () => (
|
|
23
|
+
<Prompt description="Senior TypeScript code review prompt">{SAMPLE_PROMPT}</Prompt>
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Prompt with multiple actions — Copy is primary, the rest live in a
|
|
28
|
+
* dropdown next to it.
|
|
29
|
+
*
|
|
30
|
+
* @returns Prompt with full action set
|
|
31
|
+
*/
|
|
32
|
+
// oxlint-disable-next-line func-style -- Ladle stories use `export const`
|
|
33
|
+
export const MultipleActions: Story = () => (
|
|
34
|
+
<Prompt
|
|
35
|
+
description="Open this prompt in your tool of choice"
|
|
36
|
+
actions={['copy', 'cursor', 'vscode', 'chatgpt', 'claude']}
|
|
37
|
+
>
|
|
38
|
+
{SAMPLE_PROMPT}
|
|
39
|
+
</Prompt>
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Custom icon — overrides the default `pixelarticons:sparkles`.
|
|
44
|
+
*
|
|
45
|
+
* @returns Prompt with custom icon
|
|
46
|
+
*/
|
|
47
|
+
// oxlint-disable-next-line func-style -- Ladle stories use `export const`
|
|
48
|
+
export const CustomIcon: Story = () => (
|
|
49
|
+
<Prompt
|
|
50
|
+
icon="pixelarticons:bug"
|
|
51
|
+
description="Reproduce and isolate a flaky test"
|
|
52
|
+
actions={['copy', 'claude']}
|
|
53
|
+
>
|
|
54
|
+
Identify which test is flaky in the attached file, reduce it to a minimal repro, and propose a
|
|
55
|
+
fix that doesn't trade speed for stability.
|
|
56
|
+
</Prompt>
|
|
57
|
+
)
|
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
import { CodeBlockRuntime } from '@rspress/core/theme'
|
|
2
|
+
import { match, P } from 'massaman/match'
|
|
3
|
+
import type React from 'react'
|
|
4
|
+
import { useCallback, useEffect, useRef, useState } from 'react'
|
|
5
|
+
|
|
6
|
+
import { Icon } from './icon'
|
|
7
|
+
|
|
8
|
+
export type PromptAction = 'copy' | 'cursor' | 'vscode' | 'chatgpt' | 'claude'
|
|
9
|
+
|
|
10
|
+
export interface PromptProps {
|
|
11
|
+
/**
|
|
12
|
+
* Short description of what the prompt does.
|
|
13
|
+
* Displayed as the visible summary.
|
|
14
|
+
*/
|
|
15
|
+
readonly description?: string
|
|
16
|
+
/**
|
|
17
|
+
* Iconify icon ID rendered before the description.
|
|
18
|
+
* Defaults to `pixelarticons:sparkles`.
|
|
19
|
+
*/
|
|
20
|
+
readonly icon?: string
|
|
21
|
+
/**
|
|
22
|
+
* Action buttons to display. Defaults to `['copy']`.
|
|
23
|
+
* - `copy` — copy prompt text to clipboard
|
|
24
|
+
* - `cursor` — copy to clipboard and launch Cursor IDE
|
|
25
|
+
* - `vscode` — copy to clipboard and launch VS Code
|
|
26
|
+
* - `chatgpt` — open ChatGPT in a new tab with prompt pre-filled
|
|
27
|
+
* - `claude` — open Claude in a new tab with prompt pre-filled
|
|
28
|
+
*/
|
|
29
|
+
readonly actions?: readonly PromptAction[]
|
|
30
|
+
/**
|
|
31
|
+
* The raw prompt text. Rendered inside an expandable code block.
|
|
32
|
+
*/
|
|
33
|
+
readonly children: React.ReactNode
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* AI prompt block with description, action buttons, and an expandable
|
|
38
|
+
* code view for the full prompt text.
|
|
39
|
+
*
|
|
40
|
+
* @param props - Prompt configuration with description, icon, and actions
|
|
41
|
+
* @returns React element with prompt card
|
|
42
|
+
*/
|
|
43
|
+
export function Prompt({
|
|
44
|
+
description,
|
|
45
|
+
icon = 'pixelarticons:sparkles',
|
|
46
|
+
actions = ['copy'],
|
|
47
|
+
children,
|
|
48
|
+
}: PromptProps): React.ReactElement {
|
|
49
|
+
const [expanded, setExpanded] = useState(false)
|
|
50
|
+
const [feedback, setFeedback] = useState<string | null>(null)
|
|
51
|
+
const contentRef = useRef<HTMLDivElement>(null)
|
|
52
|
+
|
|
53
|
+
const getRawText = useCallback(
|
|
54
|
+
(): string =>
|
|
55
|
+
match(contentRef.current)
|
|
56
|
+
.with(null, () => '')
|
|
57
|
+
.otherwise((el) => el.textContent ?? ''),
|
|
58
|
+
[]
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
const feedbackTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)
|
|
62
|
+
|
|
63
|
+
useEffect(
|
|
64
|
+
() => () => {
|
|
65
|
+
if (feedbackTimerRef.current !== null) {
|
|
66
|
+
clearTimeout(feedbackTimerRef.current)
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
[]
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
const showFeedback = useCallback((msg: string) => {
|
|
73
|
+
if (feedbackTimerRef.current !== null) {
|
|
74
|
+
clearTimeout(feedbackTimerRef.current)
|
|
75
|
+
}
|
|
76
|
+
setFeedback(msg)
|
|
77
|
+
feedbackTimerRef.current = setTimeout(() => setFeedback(null), 2000)
|
|
78
|
+
}, [])
|
|
79
|
+
|
|
80
|
+
const handleAction = useCallback(
|
|
81
|
+
(action: PromptAction) => {
|
|
82
|
+
const text = getRawText()
|
|
83
|
+
|
|
84
|
+
match(action)
|
|
85
|
+
.with('copy', () => {
|
|
86
|
+
navigator.clipboard
|
|
87
|
+
.writeText(text)
|
|
88
|
+
.then(() => {
|
|
89
|
+
showFeedback('Copied!')
|
|
90
|
+
return null
|
|
91
|
+
})
|
|
92
|
+
.catch(() => {
|
|
93
|
+
showFeedback('Copy failed')
|
|
94
|
+
})
|
|
95
|
+
})
|
|
96
|
+
.with('cursor', () => {
|
|
97
|
+
// Copy prompt to clipboard then open Cursor so the user can paste into composer
|
|
98
|
+
navigator.clipboard
|
|
99
|
+
.writeText(text)
|
|
100
|
+
.then(() => {
|
|
101
|
+
showFeedback('Copied — opening Cursor…')
|
|
102
|
+
globalThis.open('cursor://', '_self')
|
|
103
|
+
return null
|
|
104
|
+
})
|
|
105
|
+
.catch(() => {
|
|
106
|
+
showFeedback('Copy failed')
|
|
107
|
+
})
|
|
108
|
+
})
|
|
109
|
+
.with('vscode', () => {
|
|
110
|
+
navigator.clipboard
|
|
111
|
+
.writeText(text)
|
|
112
|
+
.then(() => {
|
|
113
|
+
showFeedback('Copied — opening VS Code…')
|
|
114
|
+
globalThis.open('vscode://', '_self')
|
|
115
|
+
return null
|
|
116
|
+
})
|
|
117
|
+
.catch(() => {
|
|
118
|
+
showFeedback('Copy failed')
|
|
119
|
+
})
|
|
120
|
+
})
|
|
121
|
+
.with('chatgpt', () => {
|
|
122
|
+
const encoded = encodeURIComponent(text)
|
|
123
|
+
globalThis.open(`https://chatgpt.com/?hints=search&prompt=${encoded}`, '_blank')
|
|
124
|
+
showFeedback('Opened ChatGPT')
|
|
125
|
+
})
|
|
126
|
+
.with('claude', () => {
|
|
127
|
+
const encoded = encodeURIComponent(text)
|
|
128
|
+
globalThis.open(`https://claude.ai/new?q=${encoded}`, '_blank')
|
|
129
|
+
showFeedback('Opened Claude')
|
|
130
|
+
})
|
|
131
|
+
.exhaustive()
|
|
132
|
+
},
|
|
133
|
+
[getRawText, showFeedback]
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
const toggleExpanded = useCallback(() => {
|
|
137
|
+
setExpanded((prev) => !prev)
|
|
138
|
+
}, [])
|
|
139
|
+
|
|
140
|
+
const descEl = match(description)
|
|
141
|
+
.with(P.nonNullable, (d) => <span className="cp-prompt__description">{d}</span>)
|
|
142
|
+
.otherwise(() => null)
|
|
143
|
+
|
|
144
|
+
const feedbackEl = match(feedback)
|
|
145
|
+
.with(P.nonNullable, (msg) => <span className="cp-prompt__feedback">{msg}</span>)
|
|
146
|
+
.otherwise(() => null)
|
|
147
|
+
|
|
148
|
+
const primaryAction = actions[0] ?? 'copy'
|
|
149
|
+
const dropdownActions = actions.slice(1)
|
|
150
|
+
|
|
151
|
+
return (
|
|
152
|
+
<div className="cp-prompt">
|
|
153
|
+
<div className="cp-prompt__header">
|
|
154
|
+
<span className="cp-prompt__icon">
|
|
155
|
+
<Icon icon={icon} />
|
|
156
|
+
</span>
|
|
157
|
+
{descEl}
|
|
158
|
+
{feedbackEl}
|
|
159
|
+
<span className="cp-prompt__actions">
|
|
160
|
+
<PrimaryButton action={primaryAction} onPress={handleAction} />
|
|
161
|
+
{match(dropdownActions.length > 0)
|
|
162
|
+
.with(true, () => <ActionDropdown actions={dropdownActions} onPress={handleAction} />)
|
|
163
|
+
.otherwise(() => null)}
|
|
164
|
+
<button
|
|
165
|
+
type="button"
|
|
166
|
+
className="cp-prompt__btn cp-prompt__btn--icon"
|
|
167
|
+
onClick={toggleExpanded}
|
|
168
|
+
title={match(expanded)
|
|
169
|
+
.with(true, () => 'Hide prompt')
|
|
170
|
+
.otherwise(() => 'Show prompt')}
|
|
171
|
+
>
|
|
172
|
+
<Icon
|
|
173
|
+
icon={match(expanded)
|
|
174
|
+
.with(true, () => 'pixelarticons:collapse')
|
|
175
|
+
.otherwise(() => 'pixelarticons:expand')}
|
|
176
|
+
/>
|
|
177
|
+
</button>
|
|
178
|
+
</span>
|
|
179
|
+
</div>
|
|
180
|
+
<div ref={contentRef} className="cp-prompt__raw" hidden>
|
|
181
|
+
{children}
|
|
182
|
+
</div>
|
|
183
|
+
{match(expanded)
|
|
184
|
+
.with(true, () => (
|
|
185
|
+
<div className="cp-prompt__code">
|
|
186
|
+
<CodeBlockRuntime lang="markdown" code={getRawText()} />
|
|
187
|
+
</div>
|
|
188
|
+
))
|
|
189
|
+
.otherwise(() => null)}
|
|
190
|
+
</div>
|
|
191
|
+
)
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Action metadata for display.
|
|
196
|
+
*
|
|
197
|
+
* @private
|
|
198
|
+
*/
|
|
199
|
+
interface ActionMeta {
|
|
200
|
+
readonly label: string
|
|
201
|
+
readonly icon: React.ReactNode
|
|
202
|
+
readonly description: string
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Resolve display metadata for a prompt action.
|
|
207
|
+
*
|
|
208
|
+
* @private
|
|
209
|
+
* @param action - The prompt action type
|
|
210
|
+
* @returns Label, icon, and description for the action
|
|
211
|
+
*/
|
|
212
|
+
function actionMeta(action: PromptAction): ActionMeta {
|
|
213
|
+
return match(action)
|
|
214
|
+
.with('copy', () => ({
|
|
215
|
+
label: 'Copy',
|
|
216
|
+
icon: <Icon icon="pixelarticons:clipboard" />,
|
|
217
|
+
description: 'Copy to clipboard',
|
|
218
|
+
}))
|
|
219
|
+
.with('cursor', () => ({
|
|
220
|
+
label: 'Cursor',
|
|
221
|
+
icon: <Icon icon="simple-icons:cursor" />,
|
|
222
|
+
description: 'Copy and open Cursor IDE',
|
|
223
|
+
}))
|
|
224
|
+
.with('vscode', () => ({
|
|
225
|
+
label: 'VS Code',
|
|
226
|
+
icon: <Icon icon="mdi:microsoft-visual-studio-code" />,
|
|
227
|
+
description: 'Copy and open VS Code',
|
|
228
|
+
}))
|
|
229
|
+
.with('chatgpt', () => ({
|
|
230
|
+
label: 'ChatGPT',
|
|
231
|
+
icon: <Icon icon="simple-icons:openai" />,
|
|
232
|
+
description: 'Open in ChatGPT with prompt',
|
|
233
|
+
}))
|
|
234
|
+
.with('claude', () => ({
|
|
235
|
+
label: 'Claude',
|
|
236
|
+
icon: <Icon icon="simple-icons:claude" />,
|
|
237
|
+
description: 'Open in Claude with prompt',
|
|
238
|
+
}))
|
|
239
|
+
.exhaustive()
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
interface PrimaryButtonProps {
|
|
243
|
+
readonly action: PromptAction
|
|
244
|
+
readonly onPress: (action: PromptAction) => void
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Full-width primary action button.
|
|
249
|
+
*
|
|
250
|
+
* @private
|
|
251
|
+
* @param props - Action and press handler
|
|
252
|
+
* @returns Button element
|
|
253
|
+
*/
|
|
254
|
+
function PrimaryButton({ action, onPress }: PrimaryButtonProps): React.ReactElement {
|
|
255
|
+
const meta = actionMeta(action)
|
|
256
|
+
const handleClick = useCallback(() => {
|
|
257
|
+
onPress(action)
|
|
258
|
+
}, [action, onPress])
|
|
259
|
+
|
|
260
|
+
return (
|
|
261
|
+
<button type="button" className="cp-prompt__btn cp-prompt__btn--primary" onClick={handleClick}>
|
|
262
|
+
{meta.icon}
|
|
263
|
+
<span>{meta.label}</span>
|
|
264
|
+
</button>
|
|
265
|
+
)
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
interface ActionDropdownProps {
|
|
269
|
+
readonly actions: readonly PromptAction[]
|
|
270
|
+
readonly onPress: (action: PromptAction) => void
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Dropdown menu for additional prompt actions.
|
|
275
|
+
*
|
|
276
|
+
* @private
|
|
277
|
+
* @param props - Actions list and press handler
|
|
278
|
+
* @returns Dropdown element with toggle and menu
|
|
279
|
+
*/
|
|
280
|
+
function ActionDropdown({ actions, onPress }: ActionDropdownProps): React.ReactElement {
|
|
281
|
+
const [open, setOpen] = useState(false)
|
|
282
|
+
const ref = useRef<HTMLDivElement>(null)
|
|
283
|
+
|
|
284
|
+
useEffect(() => {
|
|
285
|
+
if (!open) {
|
|
286
|
+
return
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
function handler(e: MouseEvent): void {
|
|
290
|
+
if (ref.current && !ref.current.contains(e.target as Node)) {
|
|
291
|
+
setOpen(false)
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
document.addEventListener('mousedown', handler)
|
|
296
|
+
return () => document.removeEventListener('mousedown', handler)
|
|
297
|
+
}, [open])
|
|
298
|
+
|
|
299
|
+
const handleToggle = useCallback(() => {
|
|
300
|
+
setOpen((prev) => !prev)
|
|
301
|
+
}, [])
|
|
302
|
+
|
|
303
|
+
return (
|
|
304
|
+
<div ref={ref} className="cp-prompt__dropdown">
|
|
305
|
+
<button
|
|
306
|
+
type="button"
|
|
307
|
+
className="cp-prompt__btn cp-prompt__btn--icon"
|
|
308
|
+
onClick={handleToggle}
|
|
309
|
+
aria-expanded={open}
|
|
310
|
+
aria-haspopup="menu"
|
|
311
|
+
>
|
|
312
|
+
<Icon
|
|
313
|
+
icon={match(open)
|
|
314
|
+
.with(true, () => 'pixelarticons:chevron-up')
|
|
315
|
+
.otherwise(() => 'pixelarticons:chevron-down')}
|
|
316
|
+
/>
|
|
317
|
+
</button>
|
|
318
|
+
{match(open)
|
|
319
|
+
.with(true, () => (
|
|
320
|
+
<div className="cp-prompt__menu" role="menu">
|
|
321
|
+
{actions.map((action) => {
|
|
322
|
+
const meta = actionMeta(action)
|
|
323
|
+
return (
|
|
324
|
+
<DropdownItem
|
|
325
|
+
key={action}
|
|
326
|
+
action={action}
|
|
327
|
+
meta={meta}
|
|
328
|
+
onPress={(a) => {
|
|
329
|
+
onPress(a)
|
|
330
|
+
setOpen(false)
|
|
331
|
+
}}
|
|
332
|
+
/>
|
|
333
|
+
)
|
|
334
|
+
})}
|
|
335
|
+
</div>
|
|
336
|
+
))
|
|
337
|
+
.otherwise(() => null)}
|
|
338
|
+
</div>
|
|
339
|
+
)
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
interface DropdownItemProps {
|
|
343
|
+
readonly action: PromptAction
|
|
344
|
+
readonly meta: ActionMeta
|
|
345
|
+
readonly onPress: (action: PromptAction) => void
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* A single item in the action dropdown menu.
|
|
350
|
+
*
|
|
351
|
+
* @private
|
|
352
|
+
* @param props - Action, display metadata, and press handler
|
|
353
|
+
* @returns Menu item button
|
|
354
|
+
*/
|
|
355
|
+
function DropdownItem({ action, meta, onPress }: DropdownItemProps): React.ReactElement {
|
|
356
|
+
const handleClick = useCallback(() => {
|
|
357
|
+
onPress(action)
|
|
358
|
+
}, [action, onPress])
|
|
359
|
+
|
|
360
|
+
return (
|
|
361
|
+
<button type="button" className="cp-prompt__menu-item" role="menuitem" onClick={handleClick}>
|
|
362
|
+
<span className="cp-prompt__menu-icon">{meta.icon}</span>
|
|
363
|
+
<span className="cp-prompt__menu-text">
|
|
364
|
+
<span className="cp-prompt__menu-label">{meta.label}</span>
|
|
365
|
+
<span className="cp-prompt__menu-desc">{meta.description}</span>
|
|
366
|
+
</span>
|
|
367
|
+
</button>
|
|
368
|
+
)
|
|
369
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolved icon with id and color.
|
|
3
|
+
*/
|
|
4
|
+
export interface ResolvedCardIcon {
|
|
5
|
+
readonly id: string
|
|
6
|
+
readonly color: string
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Resolve a unified icon config into id + color.
|
|
11
|
+
*
|
|
12
|
+
* String icons get the default `'purple'` color. Object icons pass through.
|
|
13
|
+
* Returns `undefined` for undefined input.
|
|
14
|
+
*
|
|
15
|
+
* @param icon - Icon config (string, object, or undefined)
|
|
16
|
+
* @returns Resolved icon or undefined
|
|
17
|
+
*/
|
|
18
|
+
export function resolveCardIcon(
|
|
19
|
+
icon: string | { readonly id: string; readonly color: string } | undefined
|
|
20
|
+
): ResolvedCardIcon | undefined {
|
|
21
|
+
if (icon === undefined) {
|
|
22
|
+
return undefined
|
|
23
|
+
}
|
|
24
|
+
if (typeof icon === 'string') {
|
|
25
|
+
return { id: icon, color: 'purple' }
|
|
26
|
+
}
|
|
27
|
+
return icon
|
|
28
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { Story } from '@ladle/react'
|
|
2
|
+
|
|
3
|
+
import { SectionCard } from './section-card.tsx'
|
|
4
|
+
|
|
5
|
+
const meta = {
|
|
6
|
+
title: 'Surface / Section Card',
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export default meta
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Default — icon, title, description. Renders as a clickable `<a>`
|
|
13
|
+
* routed through the stubbed Rspress `<Link>`.
|
|
14
|
+
*
|
|
15
|
+
* @returns Linked section card
|
|
16
|
+
*/
|
|
17
|
+
// oxlint-disable-next-line func-style -- Ladle stories use `export const`
|
|
18
|
+
export const Default: Story = () => (
|
|
19
|
+
<SectionCard
|
|
20
|
+
href="/guides/getting-started"
|
|
21
|
+
title="Getting started"
|
|
22
|
+
description="Spin up a Ciderpress site against your existing markdown in under five minutes."
|
|
23
|
+
icon="pixelarticons:flag"
|
|
24
|
+
/>
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* No description — minimum content.
|
|
29
|
+
*
|
|
30
|
+
* @returns Section card with title only
|
|
31
|
+
*/
|
|
32
|
+
// oxlint-disable-next-line func-style -- Ladle stories use `export const`
|
|
33
|
+
export const TitleOnly: Story = () => (
|
|
34
|
+
<SectionCard href="/concepts" title="Concepts" icon="pixelarticons:bulb" />
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Custom icon + colour — pass `{ id, color }` to override the auto
|
|
39
|
+
* resolution from `resolveCardIcon`.
|
|
40
|
+
*
|
|
41
|
+
* @returns Card with explicit blue icon
|
|
42
|
+
*/
|
|
43
|
+
// oxlint-disable-next-line func-style -- Ladle stories use `export const`
|
|
44
|
+
export const CustomIcon: Story = () => (
|
|
45
|
+
<SectionCard
|
|
46
|
+
href="/references/api"
|
|
47
|
+
title="API reference"
|
|
48
|
+
description="Every public export with full prop tables and example snippets."
|
|
49
|
+
icon={{ id: 'pixelarticons:code', color: 'blue' }}
|
|
50
|
+
/>
|
|
51
|
+
)
|