@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,112 @@
|
|
|
1
|
+
import { match, P } from 'massaman/match'
|
|
2
|
+
import type React from 'react'
|
|
3
|
+
import { Button, Disclosure, DisclosurePanel } from 'react-aria-components'
|
|
4
|
+
|
|
5
|
+
import { ChevronIcon } from './icons'
|
|
6
|
+
import { SchemaViewer } from './schema-viewer'
|
|
7
|
+
|
|
8
|
+
export interface ResponseListProps {
|
|
9
|
+
/**
|
|
10
|
+
* OpenAPI responses object keyed by status code.
|
|
11
|
+
*/
|
|
12
|
+
readonly responses: Record<string, unknown>
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Renders the list of response status codes for an OpenAPI operation.
|
|
17
|
+
*
|
|
18
|
+
* Each response is collapsible via react-aria-components Disclosure,
|
|
19
|
+
* showing the response schema when expanded.
|
|
20
|
+
*
|
|
21
|
+
* @param props - Response list props
|
|
22
|
+
* @returns React element with collapsible response entries
|
|
23
|
+
*/
|
|
24
|
+
export function ResponseList({ responses }: ResponseListProps): React.ReactElement {
|
|
25
|
+
const entries = Object.entries(responses)
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<div className="cp-oas-responses">
|
|
29
|
+
<div className="cp-oas-responses__title">Responses</div>
|
|
30
|
+
{entries.map(renderResponseItem)}
|
|
31
|
+
</div>
|
|
32
|
+
)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Determine the CSS class for a status code badge.
|
|
37
|
+
*
|
|
38
|
+
* @private
|
|
39
|
+
* @param code - HTTP status code string
|
|
40
|
+
* @returns CSS class name for the status code range
|
|
41
|
+
*/
|
|
42
|
+
function statusClass(code: string): string {
|
|
43
|
+
return match(code.charAt(0))
|
|
44
|
+
.with('2', () => 'cp-oas-response__status--2xx')
|
|
45
|
+
.with('3', () => 'cp-oas-response__status--3xx')
|
|
46
|
+
.with('4', () => 'cp-oas-response__status--4xx')
|
|
47
|
+
.with('5', () => 'cp-oas-response__status--5xx')
|
|
48
|
+
.otherwise(() => '')
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Extract the schema from a response's first content type entry.
|
|
53
|
+
*
|
|
54
|
+
* @private
|
|
55
|
+
* @param response - OpenAPI response object
|
|
56
|
+
* @returns Schema object or null
|
|
57
|
+
*/
|
|
58
|
+
function extractSchema(response: Record<string, unknown>): Record<string, unknown> | null {
|
|
59
|
+
const content = response['content'] as Record<string, Record<string, unknown>> | undefined
|
|
60
|
+
const contentSchema = match(content)
|
|
61
|
+
.with(P.nonNullable, (c) => {
|
|
62
|
+
const entries = Object.entries(c)
|
|
63
|
+
return match(entries)
|
|
64
|
+
.with(
|
|
65
|
+
P.when((e): e is [string, Record<string, unknown>][] => e.length > 0),
|
|
66
|
+
(e) => {
|
|
67
|
+
const [[, mediaType]] = e
|
|
68
|
+
return (mediaType['schema'] ?? null) as Record<string, unknown> | null
|
|
69
|
+
}
|
|
70
|
+
)
|
|
71
|
+
.otherwise(() => null)
|
|
72
|
+
})
|
|
73
|
+
.otherwise(() => null)
|
|
74
|
+
|
|
75
|
+
if (contentSchema !== null) {
|
|
76
|
+
return contentSchema
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return match(response['schema'] as Record<string, unknown> | undefined)
|
|
80
|
+
.with(P.nonNullable, (s) => s)
|
|
81
|
+
.otherwise(() => null)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Render a single response item as a collapsible disclosure.
|
|
86
|
+
*
|
|
87
|
+
* @private
|
|
88
|
+
* @param entry - Tuple of [status code, response value]
|
|
89
|
+
* @returns Collapsible response element
|
|
90
|
+
*/
|
|
91
|
+
function renderResponseItem([code, value]: readonly [string, unknown]): React.ReactElement {
|
|
92
|
+
const response = (value ?? {}) as Record<string, unknown>
|
|
93
|
+
const description = String(response['description'] ?? '')
|
|
94
|
+
const schema = extractSchema(response)
|
|
95
|
+
|
|
96
|
+
const schemaEl = match(schema)
|
|
97
|
+
.with(P.nonNullable, (s) => <SchemaViewer schema={s} />)
|
|
98
|
+
.otherwise(() => <div className="cp-oas-response__description">No response body</div>)
|
|
99
|
+
|
|
100
|
+
return (
|
|
101
|
+
<Disclosure key={code} className="cp-oas-response">
|
|
102
|
+
<Button className="cp-oas-response__trigger" slot="trigger">
|
|
103
|
+
<span className={`cp-oas-response__status ${statusClass(code)}`}>{code}</span>
|
|
104
|
+
<span className="cp-oas-response__description">{description}</span>
|
|
105
|
+
<ChevronIcon className="cp-oas-response__chevron" />
|
|
106
|
+
</Button>
|
|
107
|
+
<DisclosurePanel>
|
|
108
|
+
<div className="cp-oas-response__content">{schemaEl}</div>
|
|
109
|
+
</DisclosurePanel>
|
|
110
|
+
</Disclosure>
|
|
111
|
+
)
|
|
112
|
+
}
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
import { match, P } from 'massaman/match'
|
|
2
|
+
import type React from 'react'
|
|
3
|
+
import { useState } from 'react'
|
|
4
|
+
|
|
5
|
+
import { ChevronIcon } from './icons'
|
|
6
|
+
|
|
7
|
+
export interface SchemaViewerProps {
|
|
8
|
+
/**
|
|
9
|
+
* JSON Schema object to render.
|
|
10
|
+
*/
|
|
11
|
+
readonly schema: Record<string, unknown>
|
|
12
|
+
/**
|
|
13
|
+
* Current nesting depth (max 6).
|
|
14
|
+
*/
|
|
15
|
+
readonly depth?: number
|
|
16
|
+
/**
|
|
17
|
+
* Property name displayed alongside the type.
|
|
18
|
+
*/
|
|
19
|
+
readonly name?: string
|
|
20
|
+
/**
|
|
21
|
+
* Whether this property is required by its parent.
|
|
22
|
+
*/
|
|
23
|
+
readonly isRequired?: boolean
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const MAX_DEPTH = 6
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Recursive JSON Schema renderer.
|
|
30
|
+
*
|
|
31
|
+
* Renders primitive types as inline badges, objects as expandable
|
|
32
|
+
* property lists, arrays with item schemas, and oneOf/anyOf as
|
|
33
|
+
* variant lists. Stops at depth 6.
|
|
34
|
+
*
|
|
35
|
+
* @param props - Schema viewer props
|
|
36
|
+
* @returns React element representing the schema
|
|
37
|
+
*/
|
|
38
|
+
export function SchemaViewer({
|
|
39
|
+
schema,
|
|
40
|
+
depth = 0,
|
|
41
|
+
name,
|
|
42
|
+
isRequired = false,
|
|
43
|
+
}: SchemaViewerProps): React.ReactElement {
|
|
44
|
+
const schemaType = String(schema['type'] ?? '')
|
|
45
|
+
const description = schema['description'] as string | undefined
|
|
46
|
+
const enumValues = schema['enum'] as readonly unknown[] | undefined
|
|
47
|
+
const oneOf = schema['oneOf'] as readonly Record<string, unknown>[] | undefined
|
|
48
|
+
const anyOf = schema['anyOf'] as readonly Record<string, unknown>[] | undefined
|
|
49
|
+
const depthExceeded = depth >= MAX_DEPTH
|
|
50
|
+
|
|
51
|
+
const nameEl = match(name)
|
|
52
|
+
.with(P.nonNullable, (n) => <span className="cp-oas-schema__name">{n}</span>)
|
|
53
|
+
.otherwise(() => null)
|
|
54
|
+
|
|
55
|
+
const enumEl = match(enumValues)
|
|
56
|
+
.with(
|
|
57
|
+
P.when((e): e is readonly unknown[] => e !== undefined && e.length > 0),
|
|
58
|
+
(e) => <EnumValues values={e} />
|
|
59
|
+
)
|
|
60
|
+
.otherwise(() => null)
|
|
61
|
+
|
|
62
|
+
return match({ schemaType, oneOf, anyOf, depthExceeded })
|
|
63
|
+
.with({ depthExceeded: true }, () => (
|
|
64
|
+
<div className="cp-oas-schema__row">
|
|
65
|
+
{nameEl}
|
|
66
|
+
<span className="cp-oas-schema__type">{'...'}</span>
|
|
67
|
+
</div>
|
|
68
|
+
))
|
|
69
|
+
.with({ oneOf: P.nonNullable }, ({ oneOf: variants }) => (
|
|
70
|
+
<>
|
|
71
|
+
<div className="cp-oas-schema__row">
|
|
72
|
+
{nameEl}
|
|
73
|
+
<RequiredBadge show={isRequired} />
|
|
74
|
+
<DescriptionText text={description} />
|
|
75
|
+
</div>
|
|
76
|
+
<VariantSchemas variants={variants} label="one of" depth={depth} />
|
|
77
|
+
</>
|
|
78
|
+
))
|
|
79
|
+
.with({ anyOf: P.nonNullable }, ({ anyOf: variants }) => (
|
|
80
|
+
<>
|
|
81
|
+
<div className="cp-oas-schema__row">
|
|
82
|
+
{nameEl}
|
|
83
|
+
<RequiredBadge show={isRequired} />
|
|
84
|
+
<DescriptionText text={description} />
|
|
85
|
+
</div>
|
|
86
|
+
<VariantSchemas variants={variants} label="any of" depth={depth} />
|
|
87
|
+
</>
|
|
88
|
+
))
|
|
89
|
+
.with({ schemaType: 'object' }, () => (
|
|
90
|
+
<>
|
|
91
|
+
<div className="cp-oas-schema__row">
|
|
92
|
+
{nameEl}
|
|
93
|
+
<RequiredBadge show={isRequired} />
|
|
94
|
+
<DescriptionText text={description} />
|
|
95
|
+
</div>
|
|
96
|
+
<ObjectProperties schema={schema} depth={depth} />
|
|
97
|
+
</>
|
|
98
|
+
))
|
|
99
|
+
.with({ schemaType: 'array' }, () => (
|
|
100
|
+
<>
|
|
101
|
+
<div className="cp-oas-schema__row">
|
|
102
|
+
{nameEl}
|
|
103
|
+
<RequiredBadge show={isRequired} />
|
|
104
|
+
<DescriptionText text={description} />
|
|
105
|
+
</div>
|
|
106
|
+
<ArrayItems schema={schema} depth={depth} />
|
|
107
|
+
</>
|
|
108
|
+
))
|
|
109
|
+
.otherwise(() => (
|
|
110
|
+
<div className="cp-oas-schema__row">
|
|
111
|
+
{nameEl}
|
|
112
|
+
<span className="cp-oas-schema__type">{schemaType}</span>
|
|
113
|
+
<RequiredBadge show={isRequired} />
|
|
114
|
+
{enumEl}
|
|
115
|
+
<DescriptionText text={description} />
|
|
116
|
+
</div>
|
|
117
|
+
))
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Render a required badge when the property is required.
|
|
122
|
+
*
|
|
123
|
+
* @private
|
|
124
|
+
* @param props - Props with show flag
|
|
125
|
+
* @returns Required badge element or null
|
|
126
|
+
*/
|
|
127
|
+
function RequiredBadge({ show }: { readonly show: boolean }): React.ReactElement | null {
|
|
128
|
+
return match(show)
|
|
129
|
+
.with(true, () => <span className="cp-oas-schema__required">required</span>)
|
|
130
|
+
.otherwise(() => null)
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Render a comma-separated list of enum values.
|
|
135
|
+
*
|
|
136
|
+
* @private
|
|
137
|
+
* @param props - Props with values array
|
|
138
|
+
* @returns Enum values element
|
|
139
|
+
*/
|
|
140
|
+
function EnumValues({ values }: { readonly values: readonly unknown[] }): React.ReactElement {
|
|
141
|
+
return (
|
|
142
|
+
<span className="cp-oas-schema__enum">
|
|
143
|
+
{'enum: '}
|
|
144
|
+
{values.map(String).join(', ')}
|
|
145
|
+
</span>
|
|
146
|
+
)
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Render a description text span if text is provided.
|
|
151
|
+
*
|
|
152
|
+
* @private
|
|
153
|
+
* @param props - Props with optional text
|
|
154
|
+
* @returns Description element or null
|
|
155
|
+
*/
|
|
156
|
+
function DescriptionText({
|
|
157
|
+
text,
|
|
158
|
+
}: {
|
|
159
|
+
readonly text: string | undefined
|
|
160
|
+
}): React.ReactElement | null {
|
|
161
|
+
return match(text)
|
|
162
|
+
.with(P.nonNullable, (t) => <span className="cp-oas-schema__description">{t}</span>)
|
|
163
|
+
.otherwise(() => null)
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Render an expandable object properties viewer.
|
|
168
|
+
*
|
|
169
|
+
* @private
|
|
170
|
+
* @param props - Props with schema and depth
|
|
171
|
+
* @returns Expandable object properties element
|
|
172
|
+
*/
|
|
173
|
+
function ObjectProperties({
|
|
174
|
+
schema,
|
|
175
|
+
depth,
|
|
176
|
+
}: {
|
|
177
|
+
readonly schema: Record<string, unknown>
|
|
178
|
+
readonly depth: number
|
|
179
|
+
}): React.ReactElement {
|
|
180
|
+
const [expanded, setExpanded] = useState(depth < 2)
|
|
181
|
+
const properties = (schema['properties'] ?? {}) as Record<string, Record<string, unknown>>
|
|
182
|
+
const requiredList = (schema['required'] ?? []) as readonly string[]
|
|
183
|
+
const propEntries = Object.entries(properties)
|
|
184
|
+
|
|
185
|
+
function handleToggle() {
|
|
186
|
+
setExpanded((prev) => !prev)
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
return (
|
|
190
|
+
<div
|
|
191
|
+
className="cp-oas-schema"
|
|
192
|
+
data-expanded={match(expanded)
|
|
193
|
+
.with(true, () => '' as string | null)
|
|
194
|
+
.otherwise(() => null)}
|
|
195
|
+
>
|
|
196
|
+
<button type="button" className="cp-oas-schema__trigger" onClick={handleToggle}>
|
|
197
|
+
<ChevronIcon className="cp-oas-schema__trigger-chevron" />
|
|
198
|
+
<span className="cp-oas-schema__type">{'object'}</span>
|
|
199
|
+
<span className="cp-oas-schema__description">
|
|
200
|
+
{`{${String(propEntries.length)} properties}`}
|
|
201
|
+
</span>
|
|
202
|
+
</button>
|
|
203
|
+
{match(expanded)
|
|
204
|
+
.with(true, () => (
|
|
205
|
+
<div className="cp-oas-schema__indent">
|
|
206
|
+
{propEntries.map(([propName, propSchema]) => (
|
|
207
|
+
<SchemaViewer
|
|
208
|
+
key={propName}
|
|
209
|
+
schema={propSchema}
|
|
210
|
+
name={propName}
|
|
211
|
+
depth={depth + 1}
|
|
212
|
+
isRequired={requiredList.includes(propName)}
|
|
213
|
+
/>
|
|
214
|
+
))}
|
|
215
|
+
</div>
|
|
216
|
+
))
|
|
217
|
+
.otherwise(() => null)}
|
|
218
|
+
</div>
|
|
219
|
+
)
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Render an array items schema viewer.
|
|
224
|
+
*
|
|
225
|
+
* @private
|
|
226
|
+
* @param props - Props with schema and depth
|
|
227
|
+
* @returns Array items element
|
|
228
|
+
*/
|
|
229
|
+
function ArrayItems({
|
|
230
|
+
schema,
|
|
231
|
+
depth,
|
|
232
|
+
}: {
|
|
233
|
+
readonly schema: Record<string, unknown>
|
|
234
|
+
readonly depth: number
|
|
235
|
+
}): React.ReactElement {
|
|
236
|
+
const items = (schema['items'] ?? {}) as Record<string, unknown>
|
|
237
|
+
return (
|
|
238
|
+
<div className="cp-oas-schema">
|
|
239
|
+
<div className="cp-oas-schema__row">
|
|
240
|
+
<span className="cp-oas-schema__type">{'array of'}</span>
|
|
241
|
+
</div>
|
|
242
|
+
<div className="cp-oas-schema__indent">
|
|
243
|
+
<SchemaViewer schema={items} depth={depth + 1} />
|
|
244
|
+
</div>
|
|
245
|
+
</div>
|
|
246
|
+
)
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Render variant schemas for oneOf/anyOf unions.
|
|
251
|
+
*
|
|
252
|
+
* @private
|
|
253
|
+
* @param props - Props with variants array, label, and depth
|
|
254
|
+
* @returns Variant schemas element
|
|
255
|
+
*/
|
|
256
|
+
function VariantSchemas({
|
|
257
|
+
variants,
|
|
258
|
+
label,
|
|
259
|
+
depth,
|
|
260
|
+
}: {
|
|
261
|
+
readonly variants: readonly Record<string, unknown>[]
|
|
262
|
+
readonly label: string
|
|
263
|
+
readonly depth: number
|
|
264
|
+
}): React.ReactElement {
|
|
265
|
+
return (
|
|
266
|
+
<div className="cp-oas-schema">
|
|
267
|
+
<div className="cp-oas-schema__row">
|
|
268
|
+
<span className="cp-oas-schema__type">{label}</span>
|
|
269
|
+
</div>
|
|
270
|
+
<div className="cp-oas-schema__indent">
|
|
271
|
+
{variants.map((variant, idx) => (
|
|
272
|
+
<SchemaViewer key={String(idx)} schema={variant} depth={depth + 1} />
|
|
273
|
+
))}
|
|
274
|
+
</div>
|
|
275
|
+
</div>
|
|
276
|
+
)
|
|
277
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { match, P } from 'massaman/match'
|
|
2
|
+
import type React from 'react'
|
|
3
|
+
|
|
4
|
+
import { LockIcon } from './icons'
|
|
5
|
+
|
|
6
|
+
export interface SecurityBadgesProps {
|
|
7
|
+
/**
|
|
8
|
+
* Security requirement objects from the OpenAPI operation.
|
|
9
|
+
* Each entry is an alternative (OR); schemes within an entry are combined (AND).
|
|
10
|
+
*/
|
|
11
|
+
readonly securities: readonly Record<string, unknown>[]
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Renders badges for each security requirement of an operation.
|
|
16
|
+
*
|
|
17
|
+
* Each requirement is an alternative (OR). Schemes within a single
|
|
18
|
+
* requirement are combined (AND). OAuth scopes are shown in parentheses.
|
|
19
|
+
*
|
|
20
|
+
* @param props - Security badges props
|
|
21
|
+
* @returns React element or null if no securities
|
|
22
|
+
*/
|
|
23
|
+
export function SecurityBadges({ securities }: SecurityBadgesProps): React.ReactElement | null {
|
|
24
|
+
return match(securities)
|
|
25
|
+
.with(
|
|
26
|
+
P.when((s): s is readonly Record<string, unknown>[] => s.length > 0),
|
|
27
|
+
(s) => (
|
|
28
|
+
<div className="cp-oas-security">
|
|
29
|
+
<div className="cp-oas-security__title">Authentication</div>
|
|
30
|
+
<div className="cp-oas-security__list">
|
|
31
|
+
{s.map((requirement, idx) => (
|
|
32
|
+
<span key={String(idx)} className="cp-oas-security__badge">
|
|
33
|
+
<LockIcon />
|
|
34
|
+
{formatSchemes(requirement)}
|
|
35
|
+
</span>
|
|
36
|
+
))}
|
|
37
|
+
</div>
|
|
38
|
+
</div>
|
|
39
|
+
)
|
|
40
|
+
)
|
|
41
|
+
.otherwise(() => null)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Format security scheme names with optional OAuth scopes.
|
|
46
|
+
*
|
|
47
|
+
* @private
|
|
48
|
+
* @param requirement - Security requirement object
|
|
49
|
+
* @returns Formatted scheme string with AND-combined names
|
|
50
|
+
*/
|
|
51
|
+
function formatSchemes(requirement: Record<string, unknown>): string {
|
|
52
|
+
return Object.entries(requirement)
|
|
53
|
+
.map(([name, scopes]) => {
|
|
54
|
+
const scopeSuffix = match(scopes)
|
|
55
|
+
.with(
|
|
56
|
+
P.when((s): s is readonly string[] => Array.isArray(s) && s.length > 0),
|
|
57
|
+
(s) => ` (${s.join(', ')})`
|
|
58
|
+
)
|
|
59
|
+
.otherwise(() => '')
|
|
60
|
+
return `${name}${scopeSuffix}`
|
|
61
|
+
})
|
|
62
|
+
.join(' + ')
|
|
63
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { match, P } from 'massaman/match'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* All HTTP methods recognised by the OpenAPI specification.
|
|
5
|
+
*/
|
|
6
|
+
export const HTTP_METHODS: readonly string[] = [
|
|
7
|
+
'get',
|
|
8
|
+
'post',
|
|
9
|
+
'put',
|
|
10
|
+
'patch',
|
|
11
|
+
'delete',
|
|
12
|
+
'options',
|
|
13
|
+
'head',
|
|
14
|
+
'trace',
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Resolve an operation object from the spec by path and method.
|
|
19
|
+
*
|
|
20
|
+
* @param input - Spec object, URL path, and HTTP method
|
|
21
|
+
* @returns The matched operation object or null if not found
|
|
22
|
+
*/
|
|
23
|
+
export function resolveOperation(input: {
|
|
24
|
+
readonly spec: Record<string, unknown>
|
|
25
|
+
readonly path: string
|
|
26
|
+
readonly method: string
|
|
27
|
+
}): Record<string, unknown> | null {
|
|
28
|
+
const paths = input.spec['paths'] as Record<string, Record<string, unknown>> | undefined
|
|
29
|
+
return match(paths)
|
|
30
|
+
.with(P.nonNullable, (p) => {
|
|
31
|
+
const pathItem = p[input.path]
|
|
32
|
+
return match(pathItem)
|
|
33
|
+
.with(P.nonNullable, (pi) => {
|
|
34
|
+
const op = pi[input.method.toLowerCase()]
|
|
35
|
+
return match(op)
|
|
36
|
+
.with(P.nonNullable, (o) => o as Record<string, unknown>)
|
|
37
|
+
.otherwise(() => null)
|
|
38
|
+
})
|
|
39
|
+
.otherwise(() => null)
|
|
40
|
+
})
|
|
41
|
+
.otherwise(() => null)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Extract the first server URL from the spec, falling back to a placeholder.
|
|
46
|
+
*
|
|
47
|
+
* @param spec - Parsed OpenAPI spec object
|
|
48
|
+
* @returns First server URL string or `'https://api.example.com'`
|
|
49
|
+
*/
|
|
50
|
+
export function resolveBaseUrl(spec: Record<string, unknown>): string {
|
|
51
|
+
const servers = spec['servers'] as readonly Record<string, unknown>[] | undefined
|
|
52
|
+
return match(servers)
|
|
53
|
+
.with(
|
|
54
|
+
P.when((s): s is readonly Record<string, unknown>[] => s !== undefined && s.length > 0),
|
|
55
|
+
(s) => String(s[0]['url'] ?? 'https://api.example.com')
|
|
56
|
+
)
|
|
57
|
+
.otherwise(() => 'https://api.example.com')
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Resolve security requirements from the operation or global spec.
|
|
62
|
+
*
|
|
63
|
+
* @param input - Operation object and full spec object
|
|
64
|
+
* @returns Array of security requirement objects (operation-level takes precedence)
|
|
65
|
+
*/
|
|
66
|
+
export function resolveSecurities(input: {
|
|
67
|
+
readonly operation: Record<string, unknown>
|
|
68
|
+
readonly spec: Record<string, unknown>
|
|
69
|
+
}): readonly Record<string, unknown>[] {
|
|
70
|
+
const opSecurity = input.operation['security'] as readonly Record<string, unknown>[] | undefined
|
|
71
|
+
const globalSecurity = input.spec['security'] as readonly Record<string, unknown>[] | undefined
|
|
72
|
+
return match(opSecurity)
|
|
73
|
+
.with(P.nonNullable, (s) => s)
|
|
74
|
+
.otherwise(() =>
|
|
75
|
+
match(globalSecurity)
|
|
76
|
+
.with(P.nonNullable, (s) => s)
|
|
77
|
+
.otherwise(() => [] as readonly Record<string, unknown>[])
|
|
78
|
+
)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Extract the first example value from a request body's content map.
|
|
83
|
+
*
|
|
84
|
+
* @param requestBody - OpenAPI request body object, or undefined
|
|
85
|
+
* @returns The first example value found, or null
|
|
86
|
+
*/
|
|
87
|
+
export function extractBodyExample(
|
|
88
|
+
requestBody: Record<string, unknown> | undefined
|
|
89
|
+
): unknown | null {
|
|
90
|
+
return match(requestBody)
|
|
91
|
+
.with(P.nonNullable, (rb) => {
|
|
92
|
+
const content = rb['content'] as Record<string, Record<string, unknown>> | undefined
|
|
93
|
+
return match(content)
|
|
94
|
+
.with(P.nonNullable, (c) => {
|
|
95
|
+
const entries = Object.entries(c)
|
|
96
|
+
return match(entries)
|
|
97
|
+
.with(
|
|
98
|
+
P.when((e): e is [string, Record<string, unknown>][] => e.length > 0),
|
|
99
|
+
(e) => {
|
|
100
|
+
const [[, mediaType]] = e
|
|
101
|
+
const { example } = mediaType as { readonly example?: unknown }
|
|
102
|
+
return match(example)
|
|
103
|
+
.with(P.nonNullable, (ex) => ex)
|
|
104
|
+
.otherwise(() => null)
|
|
105
|
+
}
|
|
106
|
+
)
|
|
107
|
+
.otherwise(() => null)
|
|
108
|
+
})
|
|
109
|
+
.otherwise(() => null)
|
|
110
|
+
})
|
|
111
|
+
.otherwise(() => null)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Check if an HTTP method typically carries a request body.
|
|
116
|
+
*
|
|
117
|
+
* @param method - Lowercase HTTP method string
|
|
118
|
+
* @returns True if the method is POST, PUT, or PATCH
|
|
119
|
+
*/
|
|
120
|
+
export function isBodyMethod(method: string): boolean {
|
|
121
|
+
return method === 'post' || method === 'put' || method === 'patch'
|
|
122
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Accordion — expandable disclosure sections.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
.cp-accordion-group {
|
|
6
|
+
display: flex;
|
|
7
|
+
flex-direction: column;
|
|
8
|
+
gap: 8px;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.cp-accordion {
|
|
12
|
+
border: 1px solid var(--cp-c-border);
|
|
13
|
+
border-radius: var(--rp-radius);
|
|
14
|
+
background: var(--cp-c-bg-soft);
|
|
15
|
+
overflow: hidden;
|
|
16
|
+
transition: border-color 0.2s;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.cp-accordion:hover {
|
|
20
|
+
border-color: var(--cp-c-brand-1);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.cp-accordion__trigger {
|
|
24
|
+
display: flex;
|
|
25
|
+
align-items: center;
|
|
26
|
+
gap: 10px;
|
|
27
|
+
width: 100%;
|
|
28
|
+
min-height: 40px;
|
|
29
|
+
margin: 0;
|
|
30
|
+
padding: 10px 14px;
|
|
31
|
+
border: none;
|
|
32
|
+
background: none;
|
|
33
|
+
cursor: pointer;
|
|
34
|
+
color: var(--cp-c-text-1);
|
|
35
|
+
font-size: 14px;
|
|
36
|
+
font-weight: 600;
|
|
37
|
+
font-family: var(--cp-font-family-base);
|
|
38
|
+
text-align: left;
|
|
39
|
+
line-height: 1.4;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.cp-accordion__trigger:focus-visible {
|
|
43
|
+
outline: 2px solid var(--cp-c-brand-1);
|
|
44
|
+
outline-offset: 2px;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.cp-accordion__icon {
|
|
48
|
+
display: flex;
|
|
49
|
+
align-items: center;
|
|
50
|
+
justify-content: center;
|
|
51
|
+
flex-shrink: 0;
|
|
52
|
+
width: 16px;
|
|
53
|
+
height: 16px;
|
|
54
|
+
color: var(--cp-c-brand-1);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.cp-accordion__icon svg {
|
|
58
|
+
display: block;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.cp-accordion__header {
|
|
62
|
+
display: flex;
|
|
63
|
+
flex-direction: column;
|
|
64
|
+
gap: 2px;
|
|
65
|
+
flex: 1;
|
|
66
|
+
min-width: 0;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.cp-accordion__title {
|
|
70
|
+
line-height: 1.4;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.cp-accordion__description {
|
|
74
|
+
font-size: 12px;
|
|
75
|
+
font-weight: 400;
|
|
76
|
+
color: var(--cp-c-text-2);
|
|
77
|
+
line-height: 1.4;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.cp-accordion__chevron {
|
|
81
|
+
display: flex;
|
|
82
|
+
align-items: center;
|
|
83
|
+
justify-content: center;
|
|
84
|
+
flex-shrink: 0;
|
|
85
|
+
min-height: 40px;
|
|
86
|
+
width: 16px;
|
|
87
|
+
transition: transform 0.2s;
|
|
88
|
+
color: var(--cp-c-text-3);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.cp-accordion__chevron svg {
|
|
92
|
+
display: block;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.cp-accordion[data-expanded] .cp-accordion__chevron {
|
|
96
|
+
transform: rotate(90deg);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.cp-accordion__panel {
|
|
100
|
+
display: none;
|
|
101
|
+
padding: 0 14px 10px;
|
|
102
|
+
font-size: 14px;
|
|
103
|
+
line-height: 1.7;
|
|
104
|
+
color: var(--cp-c-text-2);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.cp-accordion[data-expanded] .cp-accordion__panel {
|
|
108
|
+
display: block;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.cp-accordion__panel > * {
|
|
112
|
+
margin-top: 0;
|
|
113
|
+
margin-bottom: 0;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.cp-accordion__panel > * + * {
|
|
117
|
+
margin-top: 8px;
|
|
118
|
+
}
|