@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.
Files changed (428) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +23 -0
  3. package/dist/0~142.js +2 -0
  4. package/dist/0~164.js +2 -0
  5. package/dist/0~2.js +2 -0
  6. package/dist/0~225.js +2 -0
  7. package/dist/0~288.js +2 -0
  8. package/dist/0~299.js +2 -0
  9. package/dist/0~3.js +2 -0
  10. package/dist/0~301.js +2 -0
  11. package/dist/0~311.js +2 -0
  12. package/dist/0~326.js +2 -0
  13. package/dist/0~40.js +2 -0
  14. package/dist/0~43.js +2 -0
  15. package/dist/0~433.js +2 -0
  16. package/dist/0~453.js +2 -0
  17. package/dist/0~457.js +2 -0
  18. package/dist/0~497.js +2 -0
  19. package/dist/0~511.js +2 -0
  20. package/dist/0~603.js +2 -0
  21. package/dist/0~616.js +2 -0
  22. package/dist/0~659.js +2 -0
  23. package/dist/0~670.js +2 -0
  24. package/dist/0~687.js +2 -0
  25. package/dist/0~706.js +2 -0
  26. package/dist/0~729.js +2 -0
  27. package/dist/0~768.js +2 -0
  28. package/dist/0~819.js +2 -0
  29. package/dist/0~830.js +2 -0
  30. package/dist/0~854.js +2 -0
  31. package/dist/0~863.js +2 -0
  32. package/dist/0~879.js +2 -0
  33. package/dist/0~96.js +2 -0
  34. package/dist/0~97.js +2 -0
  35. package/dist/components/FileTree/FileTree.css +90 -0
  36. package/dist/components/FileTree/FileTree.d.ts +7 -0
  37. package/dist/components/FileTree/FileTree.js +531 -0
  38. package/dist/components/FileTree/FileTreeItem.d.ts +8 -0
  39. package/dist/components/FileTree/RemoteSvgIcon.d.ts +11 -0
  40. package/dist/components/FileTree/index.d.ts +4 -0
  41. package/dist/components/folder-icons.d.ts +32 -0
  42. package/dist/components/languages.d.ts +7 -0
  43. package/dist/components/tree-parser/tree-parser.d.ts +12 -0
  44. package/dist/components/tree-parser/types.d.ts +11 -0
  45. package/dist/head/css/loader-apple.css +1 -0
  46. package/dist/head/css/loader-backdrop.css +1 -0
  47. package/dist/head/css/loader-dots.css +1 -0
  48. package/dist/head/css/themes/amber.css +1 -0
  49. package/dist/head/css/themes/arcade.css +1 -0
  50. package/dist/head/css/themes/grannysmith.css +1 -0
  51. package/dist/head/css/themes/honeycrisp.css +1 -0
  52. package/dist/head/css/themes/midnight.css +1 -0
  53. package/dist/head/css/themes/mulled.css +1 -0
  54. package/dist/head/js/loader-dots.js +1 -0
  55. package/dist/head/js/vscode-nav.js +1 -0
  56. package/dist/index.d.ts +43 -0
  57. package/dist/index.mjs +40 -0
  58. package/dist/node.d.ts +81 -0
  59. package/dist/node.mjs +17762 -0
  60. package/dist/plugins/mermaid/MermaidRenderer.tsx +480 -0
  61. package/dist/plugins/mermaid/mermaid.css +199 -0
  62. package/dist/theme/components/announcement/announcement-bar.css +103 -0
  63. package/dist/theme/components/announcement/announcement-bar.tsx +173 -0
  64. package/dist/theme/components/ask-ai/ask-ai-button.css +52 -0
  65. package/dist/theme/components/ask-ai/ask-ai-button.tsx +56 -0
  66. package/dist/theme/components/content-footer/content-footer-portal.tsx +70 -0
  67. package/dist/theme/components/content-footer/feedback.css +47 -0
  68. package/dist/theme/components/content-footer/feedback.tsx +96 -0
  69. package/dist/theme/components/content-footer/meta-actions.css +25 -0
  70. package/dist/theme/components/content-footer/meta-actions.tsx +57 -0
  71. package/dist/theme/components/content-footer/page-pager.css +61 -0
  72. package/dist/theme/components/content-footer/page-pager.tsx +110 -0
  73. package/dist/theme/components/edit-source-button.tsx +97 -0
  74. package/dist/theme/components/footer/site-footer.css +179 -0
  75. package/dist/theme/components/footer/site-footer.tsx +115 -0
  76. package/dist/theme/components/home/cta.css +67 -0
  77. package/dist/theme/components/home/cta.tsx +77 -0
  78. package/dist/theme/components/home/feature-card.css +52 -0
  79. package/dist/theme/components/home/feature-card.tsx +131 -0
  80. package/dist/theme/components/home/feature.tsx +79 -0
  81. package/dist/theme/components/home/hero-demo.css +66 -0
  82. package/dist/theme/components/home/hero-demo.tsx +46 -0
  83. package/dist/theme/components/home/hero.css +96 -0
  84. package/dist/theme/components/home/hero.tsx +111 -0
  85. package/dist/theme/components/home/layout.tsx +183 -0
  86. package/dist/theme/components/home/page-rail.css +21 -0
  87. package/dist/theme/components/home/page-rail.tsx +19 -0
  88. package/dist/theme/components/home/split.css +148 -0
  89. package/dist/theme/components/home/split.tsx +120 -0
  90. package/dist/theme/components/home/trust-strip.css +33 -0
  91. package/dist/theme/components/home/trust-strip.tsx +43 -0
  92. package/dist/theme/components/home/workspaces.tsx +71 -0
  93. package/dist/theme/components/nav/branch-tag.css +54 -0
  94. package/dist/theme/components/nav/branch-tag.tsx +101 -0
  95. package/dist/theme/components/nav/ciderpress-doc-layout.tsx +247 -0
  96. package/dist/theme/components/nav/ciderpress-docs-bar.css +505 -0
  97. package/dist/theme/components/nav/ciderpress-docs-bar.tsx +426 -0
  98. package/dist/theme/components/nav/ciderpress-header.css +172 -0
  99. package/dist/theme/components/nav/ciderpress-header.tsx +113 -0
  100. package/dist/theme/components/nav/ciderpress-layout-context.tsx +49 -0
  101. package/dist/theme/components/nav/ciderpress-nav-hamburger.css +193 -0
  102. package/dist/theme/components/nav/ciderpress-nav-hamburger.tsx +112 -0
  103. package/dist/theme/components/nav/ciderpress-nav-menu.css +130 -0
  104. package/dist/theme/components/nav/ciderpress-nav-menu.tsx +372 -0
  105. package/dist/theme/components/nav/ciderpress-nav-search.css +73 -0
  106. package/dist/theme/components/nav/ciderpress-nav-search.tsx +55 -0
  107. package/dist/theme/components/nav/ciderpress-nav-social-links.css +35 -0
  108. package/dist/theme/components/nav/ciderpress-nav-social-links.tsx +87 -0
  109. package/dist/theme/components/nav/floating-branch-indicator.css +106 -0
  110. package/dist/theme/components/nav/floating-branch-indicator.tsx +109 -0
  111. package/dist/theme/components/nav/layout.tsx +268 -0
  112. package/dist/theme/components/nav/mobile-nav-cta.tsx +79 -0
  113. package/dist/theme/components/nav/nav-divider.css +15 -0
  114. package/dist/theme/components/nav/nav-divider.tsx +19 -0
  115. package/dist/theme/components/nav/nav-logo.css +42 -0
  116. package/dist/theme/components/nav/nav-logo.tsx +262 -0
  117. package/dist/theme/components/nav/theme-switcher.css +92 -0
  118. package/dist/theme/components/nav/theme-switcher.tsx +298 -0
  119. package/dist/theme/components/nav/topbar-cta.css +45 -0
  120. package/dist/theme/components/nav/topbar-cta.tsx +39 -0
  121. package/dist/theme/components/nav/variant-toggle.css +70 -0
  122. package/dist/theme/components/nav/variant-toggle.tsx +83 -0
  123. package/dist/theme/components/nav/version-chip.css +31 -0
  124. package/dist/theme/components/nav/version-chip.tsx +45 -0
  125. package/dist/theme/components/nav/vscode-tag.css +32 -0
  126. package/dist/theme/components/nav/vscode-tag.tsx +20 -0
  127. package/dist/theme/components/openapi/code-sample.tsx +341 -0
  128. package/dist/theme/components/openapi/copy-markdown-button.tsx +41 -0
  129. package/dist/theme/components/openapi/icons.tsx +45 -0
  130. package/dist/theme/components/openapi/index.ts +6 -0
  131. package/dist/theme/components/openapi/method-badge.tsx +24 -0
  132. package/dist/theme/components/openapi/openapi.css +665 -0
  133. package/dist/theme/components/openapi/operation.tsx +200 -0
  134. package/dist/theme/components/openapi/overview.tsx +207 -0
  135. package/dist/theme/components/openapi/parameters-table.tsx +149 -0
  136. package/dist/theme/components/openapi/request-body.tsx +90 -0
  137. package/dist/theme/components/openapi/response-list.tsx +112 -0
  138. package/dist/theme/components/openapi/schema-viewer.tsx +277 -0
  139. package/dist/theme/components/openapi/security-badges.tsx +63 -0
  140. package/dist/theme/components/openapi/spec-utils.ts +122 -0
  141. package/dist/theme/components/shared/accordion.css +118 -0
  142. package/dist/theme/components/shared/accordion.stories.tsx +96 -0
  143. package/dist/theme/components/shared/accordion.tsx +191 -0
  144. package/dist/theme/components/shared/brand-logo.stories.tsx +49 -0
  145. package/dist/theme/components/shared/brand-mark.stories.tsx +53 -0
  146. package/dist/theme/components/shared/browser-window.css +1 -0
  147. package/dist/theme/components/shared/browser-window.stories.tsx +100 -0
  148. package/dist/theme/components/shared/browser-window.tsx +2 -0
  149. package/dist/theme/components/shared/card.stories.tsx +50 -0
  150. package/dist/theme/components/shared/card.tsx +35 -0
  151. package/dist/theme/components/shared/ciderpress-logo.tsx +93 -0
  152. package/dist/theme/components/shared/ciderpress-mark.tsx +77 -0
  153. package/dist/theme/components/shared/color.css +56 -0
  154. package/dist/theme/components/shared/color.stories.tsx +47 -0
  155. package/dist/theme/components/shared/color.tsx +69 -0
  156. package/dist/theme/components/shared/columns.css +37 -0
  157. package/dist/theme/components/shared/columns.stories.tsx +91 -0
  158. package/dist/theme/components/shared/columns.tsx +50 -0
  159. package/dist/theme/components/shared/desktop-window.css +339 -0
  160. package/dist/theme/components/shared/desktop-window.tsx +535 -0
  161. package/dist/theme/components/shared/field.css +158 -0
  162. package/dist/theme/components/shared/field.stories.tsx +100 -0
  163. package/dist/theme/components/shared/field.tsx +186 -0
  164. package/dist/theme/components/shared/frame.css +39 -0
  165. package/dist/theme/components/shared/frame.stories.tsx +49 -0
  166. package/dist/theme/components/shared/frame.tsx +76 -0
  167. package/dist/theme/components/shared/icon.stories.tsx +90 -0
  168. package/dist/theme/components/shared/icon.tsx +41 -0
  169. package/dist/theme/components/shared/prompt.css +178 -0
  170. package/dist/theme/components/shared/prompt.stories.tsx +57 -0
  171. package/dist/theme/components/shared/prompt.tsx +369 -0
  172. package/dist/theme/components/shared/resolve-card-icon.ts +28 -0
  173. package/dist/theme/components/shared/section-card.stories.tsx +51 -0
  174. package/dist/theme/components/shared/section-card.tsx +44 -0
  175. package/dist/theme/components/shared/section-grid.stories.tsx +46 -0
  176. package/dist/theme/components/shared/section-grid.tsx +15 -0
  177. package/dist/theme/components/shared/status-badge.css +37 -0
  178. package/dist/theme/components/shared/status-badge.stories.tsx +61 -0
  179. package/dist/theme/components/shared/status-badge.tsx +74 -0
  180. package/dist/theme/components/shared/steps.css +88 -0
  181. package/dist/theme/components/shared/steps.stories.tsx +68 -0
  182. package/dist/theme/components/shared/steps.tsx +100 -0
  183. package/dist/theme/components/shared/tech-icon-table.stories.tsx +29 -0
  184. package/dist/theme/components/shared/tech-icon-table.tsx +71 -0
  185. package/dist/theme/components/shared/tech-tag.stories.tsx +40 -0
  186. package/dist/theme/components/shared/tech-tag.tsx +31 -0
  187. package/dist/theme/components/shared/theme-color-palette.css +80 -0
  188. package/dist/theme/components/shared/theme-color-palette.stories.tsx +52 -0
  189. package/dist/theme/components/shared/theme-color-palette.tsx +275 -0
  190. package/dist/theme/components/shared/tooltip.css +69 -0
  191. package/dist/theme/components/shared/tooltip.stories.tsx +72 -0
  192. package/dist/theme/components/shared/tooltip.tsx +77 -0
  193. package/dist/theme/components/sidebar/framework-picker.css +77 -0
  194. package/dist/theme/components/sidebar/framework-picker.tsx +78 -0
  195. package/dist/theme/components/sidebar/sidebar-filter.test.ts +140 -0
  196. package/dist/theme/components/sidebar/sidebar-filter.ts +79 -0
  197. package/dist/theme/components/sidebar/sidebar-links.css +102 -0
  198. package/dist/theme/components/sidebar/sidebar-links.tsx +122 -0
  199. package/dist/theme/components/sidebar/sidebar-promo.css +42 -0
  200. package/dist/theme/components/sidebar/sidebar-promo.tsx +52 -0
  201. package/dist/theme/components/sidebar/sidebar-scope.tsx +151 -0
  202. package/dist/theme/components/sidebar/sidebar-toggle.css +181 -0
  203. package/dist/theme/components/sidebar/sidebar-toggle.tsx +127 -0
  204. package/dist/theme/components/theme-provider.tsx +637 -0
  205. package/dist/theme/components/workspaces/card.css +151 -0
  206. package/dist/theme/components/workspaces/card.tsx +166 -0
  207. package/dist/theme/components/workspaces/grid.tsx +62 -0
  208. package/dist/theme/css.d.ts +1 -0
  209. package/dist/theme/env.d.ts +12 -0
  210. package/dist/theme/fonts/GeistMono-Variable.woff2 +0 -0
  211. package/dist/theme/fonts/GeistPixel-Square.woff2 +0 -0
  212. package/dist/theme/fonts/GeistSans-Variable.woff2 +0 -0
  213. package/dist/theme/hooks/use-ciderpress.ts +61 -0
  214. package/dist/theme/hooks/use-nav-items.ts +76 -0
  215. package/dist/theme/icons/index.ts +2 -0
  216. package/dist/theme/icons/tech-map.ts +228 -0
  217. package/dist/theme/index.tsx +180 -0
  218. package/dist/theme/lib/read-social-links.ts +27 -0
  219. package/dist/theme/lib/route-link.tsx +126 -0
  220. package/dist/theme/lib/safe-url.test.ts +0 -0
  221. package/dist/theme/lib/safe-url.ts +68 -0
  222. package/dist/theme/lib/theme-favicon.ts +125 -0
  223. package/dist/theme/lib/user-config-stub.ts +12 -0
  224. package/dist/theme/styles/layers.css +32 -0
  225. package/dist/theme/styles/overrides/badge.css +26 -0
  226. package/dist/theme/styles/overrides/content-footer.css +80 -0
  227. package/dist/theme/styles/overrides/details.css +61 -0
  228. package/dist/theme/styles/overrides/fonts.css +32 -0
  229. package/dist/theme/styles/overrides/home-card.css +133 -0
  230. package/dist/theme/styles/overrides/home.css +243 -0
  231. package/dist/theme/styles/overrides/rail.css +337 -0
  232. package/dist/theme/styles/overrides/rspress.css +62 -0
  233. package/dist/theme/styles/overrides/scrollbar.css +25 -0
  234. package/dist/theme/styles/overrides/section-card.css +114 -0
  235. package/dist/theme/styles/overrides/sidebar.css +144 -0
  236. package/dist/theme/styles/overrides/tokens.css +288 -0
  237. package/dist/theme/styles/overrides/vscode.css +88 -0
  238. package/dist/theme/styles/themes/amber.css +545 -0
  239. package/dist/theme/styles/themes/arcade-fx.css +366 -0
  240. package/dist/theme/styles/themes/arcade.css +273 -0
  241. package/dist/theme/styles/themes/grannysmith.css +545 -0
  242. package/dist/theme/styles/themes/honeycrisp.css +545 -0
  243. package/dist/theme/styles/themes/midnight.css +273 -0
  244. package/dist/theme/styles/themes/mulled.css +817 -0
  245. package/package.json +103 -0
  246. package/src/theme/components/announcement/announcement-bar.css +103 -0
  247. package/src/theme/components/announcement/announcement-bar.tsx +173 -0
  248. package/src/theme/components/ask-ai/ask-ai-button.css +52 -0
  249. package/src/theme/components/ask-ai/ask-ai-button.tsx +56 -0
  250. package/src/theme/components/content-footer/content-footer-portal.tsx +70 -0
  251. package/src/theme/components/content-footer/feedback.css +47 -0
  252. package/src/theme/components/content-footer/feedback.tsx +96 -0
  253. package/src/theme/components/content-footer/meta-actions.css +25 -0
  254. package/src/theme/components/content-footer/meta-actions.tsx +57 -0
  255. package/src/theme/components/content-footer/page-pager.css +61 -0
  256. package/src/theme/components/content-footer/page-pager.tsx +110 -0
  257. package/src/theme/components/edit-source-button.tsx +97 -0
  258. package/src/theme/components/footer/site-footer.css +179 -0
  259. package/src/theme/components/footer/site-footer.tsx +115 -0
  260. package/src/theme/components/home/cta.css +67 -0
  261. package/src/theme/components/home/cta.tsx +77 -0
  262. package/src/theme/components/home/feature-card.css +52 -0
  263. package/src/theme/components/home/feature-card.tsx +131 -0
  264. package/src/theme/components/home/feature.tsx +79 -0
  265. package/src/theme/components/home/hero-demo.css +66 -0
  266. package/src/theme/components/home/hero-demo.tsx +46 -0
  267. package/src/theme/components/home/hero.css +96 -0
  268. package/src/theme/components/home/hero.tsx +111 -0
  269. package/src/theme/components/home/layout.tsx +183 -0
  270. package/src/theme/components/home/page-rail.css +21 -0
  271. package/src/theme/components/home/page-rail.tsx +19 -0
  272. package/src/theme/components/home/split.css +148 -0
  273. package/src/theme/components/home/split.tsx +120 -0
  274. package/src/theme/components/home/trust-strip.css +33 -0
  275. package/src/theme/components/home/trust-strip.tsx +43 -0
  276. package/src/theme/components/home/workspaces.tsx +71 -0
  277. package/src/theme/components/nav/branch-tag.css +54 -0
  278. package/src/theme/components/nav/branch-tag.tsx +101 -0
  279. package/src/theme/components/nav/ciderpress-doc-layout.tsx +247 -0
  280. package/src/theme/components/nav/ciderpress-docs-bar.css +505 -0
  281. package/src/theme/components/nav/ciderpress-docs-bar.tsx +426 -0
  282. package/src/theme/components/nav/ciderpress-header.css +172 -0
  283. package/src/theme/components/nav/ciderpress-header.tsx +113 -0
  284. package/src/theme/components/nav/ciderpress-layout-context.tsx +49 -0
  285. package/src/theme/components/nav/ciderpress-nav-hamburger.css +193 -0
  286. package/src/theme/components/nav/ciderpress-nav-hamburger.tsx +112 -0
  287. package/src/theme/components/nav/ciderpress-nav-menu.css +130 -0
  288. package/src/theme/components/nav/ciderpress-nav-menu.tsx +372 -0
  289. package/src/theme/components/nav/ciderpress-nav-search.css +73 -0
  290. package/src/theme/components/nav/ciderpress-nav-search.tsx +55 -0
  291. package/src/theme/components/nav/ciderpress-nav-social-links.css +35 -0
  292. package/src/theme/components/nav/ciderpress-nav-social-links.tsx +87 -0
  293. package/src/theme/components/nav/floating-branch-indicator.css +106 -0
  294. package/src/theme/components/nav/floating-branch-indicator.tsx +109 -0
  295. package/src/theme/components/nav/layout.tsx +268 -0
  296. package/src/theme/components/nav/mobile-nav-cta.tsx +79 -0
  297. package/src/theme/components/nav/nav-divider.css +15 -0
  298. package/src/theme/components/nav/nav-divider.tsx +19 -0
  299. package/src/theme/components/nav/nav-logo.css +42 -0
  300. package/src/theme/components/nav/nav-logo.tsx +262 -0
  301. package/src/theme/components/nav/theme-switcher.css +92 -0
  302. package/src/theme/components/nav/theme-switcher.tsx +298 -0
  303. package/src/theme/components/nav/topbar-cta.css +45 -0
  304. package/src/theme/components/nav/topbar-cta.tsx +39 -0
  305. package/src/theme/components/nav/variant-toggle.css +70 -0
  306. package/src/theme/components/nav/variant-toggle.tsx +83 -0
  307. package/src/theme/components/nav/version-chip.css +31 -0
  308. package/src/theme/components/nav/version-chip.tsx +45 -0
  309. package/src/theme/components/nav/vscode-tag.css +32 -0
  310. package/src/theme/components/nav/vscode-tag.tsx +20 -0
  311. package/src/theme/components/openapi/code-sample.tsx +341 -0
  312. package/src/theme/components/openapi/copy-markdown-button.tsx +41 -0
  313. package/src/theme/components/openapi/icons.tsx +45 -0
  314. package/src/theme/components/openapi/index.ts +6 -0
  315. package/src/theme/components/openapi/method-badge.tsx +24 -0
  316. package/src/theme/components/openapi/openapi.css +665 -0
  317. package/src/theme/components/openapi/operation.tsx +200 -0
  318. package/src/theme/components/openapi/overview.tsx +207 -0
  319. package/src/theme/components/openapi/parameters-table.tsx +149 -0
  320. package/src/theme/components/openapi/request-body.tsx +90 -0
  321. package/src/theme/components/openapi/response-list.tsx +112 -0
  322. package/src/theme/components/openapi/schema-viewer.tsx +277 -0
  323. package/src/theme/components/openapi/security-badges.tsx +63 -0
  324. package/src/theme/components/openapi/spec-utils.ts +122 -0
  325. package/src/theme/components/shared/accordion.css +118 -0
  326. package/src/theme/components/shared/accordion.stories.tsx +96 -0
  327. package/src/theme/components/shared/accordion.tsx +191 -0
  328. package/src/theme/components/shared/brand-logo.stories.tsx +49 -0
  329. package/src/theme/components/shared/brand-mark.stories.tsx +53 -0
  330. package/src/theme/components/shared/browser-window.css +1 -0
  331. package/src/theme/components/shared/browser-window.stories.tsx +100 -0
  332. package/src/theme/components/shared/browser-window.tsx +2 -0
  333. package/src/theme/components/shared/card.stories.tsx +50 -0
  334. package/src/theme/components/shared/card.tsx +35 -0
  335. package/src/theme/components/shared/ciderpress-logo.tsx +93 -0
  336. package/src/theme/components/shared/ciderpress-mark.tsx +77 -0
  337. package/src/theme/components/shared/color.css +56 -0
  338. package/src/theme/components/shared/color.stories.tsx +47 -0
  339. package/src/theme/components/shared/color.tsx +69 -0
  340. package/src/theme/components/shared/columns.css +37 -0
  341. package/src/theme/components/shared/columns.stories.tsx +91 -0
  342. package/src/theme/components/shared/columns.tsx +50 -0
  343. package/src/theme/components/shared/desktop-window.css +339 -0
  344. package/src/theme/components/shared/desktop-window.tsx +535 -0
  345. package/src/theme/components/shared/field.css +158 -0
  346. package/src/theme/components/shared/field.stories.tsx +100 -0
  347. package/src/theme/components/shared/field.tsx +186 -0
  348. package/src/theme/components/shared/frame.css +39 -0
  349. package/src/theme/components/shared/frame.stories.tsx +49 -0
  350. package/src/theme/components/shared/frame.tsx +76 -0
  351. package/src/theme/components/shared/icon.stories.tsx +90 -0
  352. package/src/theme/components/shared/icon.tsx +41 -0
  353. package/src/theme/components/shared/prompt.css +178 -0
  354. package/src/theme/components/shared/prompt.stories.tsx +57 -0
  355. package/src/theme/components/shared/prompt.tsx +369 -0
  356. package/src/theme/components/shared/resolve-card-icon.ts +28 -0
  357. package/src/theme/components/shared/section-card.stories.tsx +51 -0
  358. package/src/theme/components/shared/section-card.tsx +44 -0
  359. package/src/theme/components/shared/section-grid.stories.tsx +46 -0
  360. package/src/theme/components/shared/section-grid.tsx +15 -0
  361. package/src/theme/components/shared/status-badge.css +37 -0
  362. package/src/theme/components/shared/status-badge.stories.tsx +61 -0
  363. package/src/theme/components/shared/status-badge.tsx +74 -0
  364. package/src/theme/components/shared/steps.css +88 -0
  365. package/src/theme/components/shared/steps.stories.tsx +68 -0
  366. package/src/theme/components/shared/steps.tsx +100 -0
  367. package/src/theme/components/shared/tech-icon-table.stories.tsx +29 -0
  368. package/src/theme/components/shared/tech-icon-table.tsx +71 -0
  369. package/src/theme/components/shared/tech-tag.stories.tsx +40 -0
  370. package/src/theme/components/shared/tech-tag.tsx +31 -0
  371. package/src/theme/components/shared/theme-color-palette.css +80 -0
  372. package/src/theme/components/shared/theme-color-palette.stories.tsx +52 -0
  373. package/src/theme/components/shared/theme-color-palette.tsx +275 -0
  374. package/src/theme/components/shared/tooltip.css +69 -0
  375. package/src/theme/components/shared/tooltip.stories.tsx +72 -0
  376. package/src/theme/components/shared/tooltip.tsx +77 -0
  377. package/src/theme/components/sidebar/framework-picker.css +77 -0
  378. package/src/theme/components/sidebar/framework-picker.tsx +78 -0
  379. package/src/theme/components/sidebar/sidebar-filter.test.ts +140 -0
  380. package/src/theme/components/sidebar/sidebar-filter.ts +79 -0
  381. package/src/theme/components/sidebar/sidebar-links.css +102 -0
  382. package/src/theme/components/sidebar/sidebar-links.tsx +122 -0
  383. package/src/theme/components/sidebar/sidebar-promo.css +42 -0
  384. package/src/theme/components/sidebar/sidebar-promo.tsx +52 -0
  385. package/src/theme/components/sidebar/sidebar-scope.tsx +151 -0
  386. package/src/theme/components/sidebar/sidebar-toggle.css +181 -0
  387. package/src/theme/components/sidebar/sidebar-toggle.tsx +127 -0
  388. package/src/theme/components/theme-provider.tsx +637 -0
  389. package/src/theme/components/workspaces/card.css +151 -0
  390. package/src/theme/components/workspaces/card.tsx +166 -0
  391. package/src/theme/components/workspaces/grid.tsx +62 -0
  392. package/src/theme/css.d.ts +1 -0
  393. package/src/theme/env.d.ts +12 -0
  394. package/src/theme/fonts/GeistMono-Variable.woff2 +0 -0
  395. package/src/theme/fonts/GeistPixel-Square.woff2 +0 -0
  396. package/src/theme/fonts/GeistSans-Variable.woff2 +0 -0
  397. package/src/theme/hooks/use-ciderpress.ts +61 -0
  398. package/src/theme/hooks/use-nav-items.ts +76 -0
  399. package/src/theme/icons/index.ts +2 -0
  400. package/src/theme/icons/tech-map.ts +228 -0
  401. package/src/theme/index.tsx +180 -0
  402. package/src/theme/lib/read-social-links.ts +27 -0
  403. package/src/theme/lib/route-link.tsx +126 -0
  404. package/src/theme/lib/safe-url.test.ts +0 -0
  405. package/src/theme/lib/safe-url.ts +68 -0
  406. package/src/theme/lib/theme-favicon.ts +125 -0
  407. package/src/theme/lib/user-config-stub.ts +12 -0
  408. package/src/theme/styles/layers.css +32 -0
  409. package/src/theme/styles/overrides/badge.css +26 -0
  410. package/src/theme/styles/overrides/content-footer.css +80 -0
  411. package/src/theme/styles/overrides/details.css +61 -0
  412. package/src/theme/styles/overrides/fonts.css +32 -0
  413. package/src/theme/styles/overrides/home-card.css +133 -0
  414. package/src/theme/styles/overrides/home.css +243 -0
  415. package/src/theme/styles/overrides/rail.css +337 -0
  416. package/src/theme/styles/overrides/rspress.css +62 -0
  417. package/src/theme/styles/overrides/scrollbar.css +25 -0
  418. package/src/theme/styles/overrides/section-card.css +114 -0
  419. package/src/theme/styles/overrides/sidebar.css +144 -0
  420. package/src/theme/styles/overrides/tokens.css +288 -0
  421. package/src/theme/styles/overrides/vscode.css +88 -0
  422. package/src/theme/styles/themes/amber.css +545 -0
  423. package/src/theme/styles/themes/arcade-fx.css +366 -0
  424. package/src/theme/styles/themes/arcade.css +273 -0
  425. package/src/theme/styles/themes/grannysmith.css +545 -0
  426. package/src/theme/styles/themes/honeycrisp.css +545 -0
  427. package/src/theme/styles/themes/midnight.css +273 -0
  428. package/src/theme/styles/themes/mulled.css +817 -0
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Feature Card — layout and typography (base card styles from home-card.css).
3
+ */
4
+
5
+ /* ── Feature card layout ───────────────────────────────────── */
6
+ .cp-feature-card {
7
+ display: flex;
8
+ flex-direction: column;
9
+ gap: var(--cp-s-10);
10
+ height: 100%;
11
+ }
12
+
13
+ /* Row 1: icon + title */
14
+ .cp-feature-card__header {
15
+ display: flex;
16
+ align-items: center;
17
+ gap: var(--cp-s-12);
18
+ }
19
+
20
+ .cp-feature-card__title {
21
+ font-family: 'Geist Pixel Square', var(--rp-font-family-base, sans-serif);
22
+ font-size: var(--cp-fs-feature-title);
23
+ font-weight: var(--cp-fw-bold);
24
+ color: var(--rp-c-text-1, var(--cp-c-text-1));
25
+ line-height: var(--cp-lh-tight);
26
+ }
27
+
28
+ /* Row 2: description */
29
+ .cp-feature-card__desc {
30
+ font-size: var(--cp-fs-feature-desc);
31
+ color: var(--rp-c-text-2, var(--cp-c-text-2));
32
+ line-height: var(--cp-lh-base);
33
+ }
34
+
35
+ /* ── Truncation ────────────────────────────────────────────── */
36
+ .cp-feature-card__title.cp-clamp,
37
+ .cp-feature-card__desc.cp-clamp {
38
+ display: -webkit-box;
39
+ -webkit-box-orient: vertical;
40
+ overflow: hidden;
41
+ text-overflow: ellipsis;
42
+ }
43
+
44
+ /* Row 3: link tail (mockup pattern) */
45
+ .cp-feature-card__link {
46
+ margin-top: auto;
47
+ padding-top: var(--cp-s-16);
48
+ font-family: var(--cp-font-family-mono);
49
+ font-size: var(--cp-fs-feature-link);
50
+ color: var(--cp-c-brand-1);
51
+ font-weight: 500;
52
+ }
@@ -0,0 +1,131 @@
1
+ import { match, P } from 'massaman/match'
2
+ import type React from 'react'
3
+
4
+ import './feature-card.css'
5
+ import { Card } from '../shared/card'
6
+ import { Icon } from '../shared/icon'
7
+ import { resolveCardIcon } from '../shared/resolve-card-icon'
8
+
9
+ export interface FeatureCardProps {
10
+ readonly title: string
11
+ readonly description: string
12
+ readonly href?: string
13
+ readonly icon?: string | { readonly id: string; readonly color: string }
14
+ readonly span?: 2 | 3 | 4 | 6
15
+ readonly titleLines?: number
16
+ readonly descriptionLines?: number
17
+ }
18
+
19
+ /**
20
+ * Frontmatter-shaped data for consumers to map from.
21
+ */
22
+ export interface FeatureItem {
23
+ readonly title: string
24
+ readonly details: string
25
+ readonly link?: string
26
+ readonly icon?: string | { readonly id: string; readonly color: string }
27
+ readonly span?: 2 | 3 | 4 | 6
28
+ }
29
+
30
+ /**
31
+ * Feature card for landing pages — matches the workspace/section card design.
32
+ * Renders as `<a>` when `href` is provided, `<div>` otherwise.
33
+ *
34
+ * @param props - Feature card props including title, description, href, icon, span, titleLines, descriptionLines
35
+ * @returns React element with feature card layout
36
+ */
37
+ export function FeatureCard({
38
+ title,
39
+ description,
40
+ href,
41
+ icon,
42
+ span = 4,
43
+ titleLines,
44
+ descriptionLines,
45
+ }: FeatureCardProps): React.ReactElement {
46
+ const resolved = resolveCardIcon(icon)
47
+
48
+ const iconEl = match(resolved)
49
+ .with(P.nonNullable, (r) => (
50
+ <span className={`cp-card__icon cp-card__icon--${r.color}`}>
51
+ <Icon icon={r.id} />
52
+ </span>
53
+ ))
54
+ .otherwise(() => null)
55
+
56
+ const linkTail = match(href)
57
+ .with(P.nonNullable, () => <span className="cp-feature-card__link">Learn more →</span>)
58
+ .otherwise(() => null)
59
+
60
+ return (
61
+ <div className={`cp-feature-grid__item cp-feature-grid__item--span-${span}`}>
62
+ <div className="cp-feature-grid__item-wrap">
63
+ <Card href={href} className="cp-feature-card">
64
+ <div className="cp-feature-card__header">
65
+ {iconEl}
66
+ <span
67
+ className={clampClass('cp-feature-card__title', titleLines)}
68
+ style={clampStyle(titleLines)}
69
+ >
70
+ {title}
71
+ </span>
72
+ </div>
73
+ <span
74
+ className={clampClass('cp-feature-card__desc', descriptionLines)}
75
+ style={clampStyle(descriptionLines)}
76
+ >
77
+ {description}
78
+ </span>
79
+ {linkTail}
80
+ </Card>
81
+ </div>
82
+ </div>
83
+ )
84
+ }
85
+
86
+ interface FeatureGridProps {
87
+ readonly children: React.ReactNode
88
+ }
89
+
90
+ /**
91
+ * Flex-wrap layout container for feature cards.
92
+ *
93
+ * @param props - Props with children to render inside the grid
94
+ * @returns React element wrapping children in a feature grid
95
+ */
96
+ export function FeatureGrid({ children }: FeatureGridProps): React.ReactElement {
97
+ return (
98
+ <div className="cp-feature-section">
99
+ <div className="cp-feature-grid">{children}</div>
100
+ </div>
101
+ )
102
+ }
103
+
104
+ /**
105
+ * Build a className string with optional `cp-clamp` suffix.
106
+ *
107
+ * @private
108
+ * @param base - Base CSS class name
109
+ * @param lines - Optional line clamp value
110
+ * @returns Class string with or without cp-clamp
111
+ */
112
+ function clampClass(base: string, lines: number | undefined): string {
113
+ if (lines) {
114
+ return `${base} cp-clamp`
115
+ }
116
+ return base
117
+ }
118
+
119
+ /**
120
+ * Build an inline style object for line clamping.
121
+ *
122
+ * @private
123
+ * @param lines - Optional line clamp value
124
+ * @returns Style object with WebkitLineClamp or undefined
125
+ */
126
+ function clampStyle(lines: number | undefined): React.CSSProperties | undefined {
127
+ if (lines) {
128
+ return { WebkitLineClamp: lines }
129
+ }
130
+ return undefined
131
+ }
@@ -0,0 +1,79 @@
1
+ import type { HomeGridConfig } from '@ciderpress/config'
2
+ import { useFrontmatter } from '@rspress/core/runtime'
3
+ import { match, P } from 'massaman/match'
4
+ import type React from 'react'
5
+
6
+ import { useCiderpress } from '../../hooks/use-ciderpress'
7
+ import { FeatureCard } from './feature-card'
8
+ import type { FeatureItem } from './feature-card'
9
+
10
+ /**
11
+ * Custom HomeFeature override for ciderpress.
12
+ * Uses useFrontmatter() hook to read features and renders with FeatureCard/FeatureGrid styling.
13
+ *
14
+ * @returns React element with feature grid or null
15
+ */
16
+ export function HomeFeature(): React.ReactElement | null {
17
+ const { frontmatter } = useFrontmatter()
18
+ const { home } = useCiderpress()
19
+ const gridConfig = home && home.features
20
+
21
+ // Rspress types frontmatter as its own FrontMatterMeta shape which does not
22
+ // include ciderpress-specific `features`. The double cast is necessary because
23
+ // no shared Zod schema exists for frontmatter validation at runtime.
24
+ const features = (frontmatter as Record<string, unknown>).features as
25
+ | readonly FeatureItem[]
26
+ | undefined
27
+
28
+ return match(features)
29
+ .with(
30
+ P.when((f): f is readonly FeatureItem[] => Array.isArray(f) && f.length > 0),
31
+ (items) => (
32
+ <div className="cp-feature-section">
33
+ <div className="cp-feature-section-head">
34
+ <div className="cp-feature-section-head__eyebrow">Features</div>
35
+ <h2 className="cp-feature-section-head__title">Built for the way you ship.</h2>
36
+ <p className="cp-feature-section-head__sub">
37
+ Everything you need, nothing you don&apos;t. Configured in TypeScript, validated at
38
+ boot.
39
+ </p>
40
+ </div>
41
+ <div className="cp-feature-grid">
42
+ {items.map((f, i) => renderFeature(f, i, gridConfig))}
43
+ </div>
44
+ </div>
45
+ )
46
+ )
47
+ .otherwise(() => null)
48
+ }
49
+
50
+ /**
51
+ * Render a single feature as a FeatureCard element.
52
+ * Accepts the array index from `.map()` to guarantee unique keys.
53
+ *
54
+ * @private
55
+ * @param feature - Feature item data
56
+ * @param index - Array index for key generation
57
+ * @param gridConfig - Optional grid config for truncation
58
+ * @returns Feature card element
59
+ */
60
+ function renderFeature(
61
+ feature: FeatureItem,
62
+ index: number,
63
+ gridConfig: HomeGridConfig | undefined
64
+ ): React.ReactElement {
65
+ const titleLines = gridConfig && gridConfig.truncate && gridConfig.truncate.title
66
+ const descLines = gridConfig && gridConfig.truncate && gridConfig.truncate.description
67
+
68
+ return (
69
+ <FeatureCard
70
+ key={`${feature.title}-${index}`}
71
+ title={feature.title}
72
+ description={feature.details}
73
+ href={feature.link}
74
+ icon={feature.icon}
75
+ titleLines={titleLines}
76
+ descriptionLines={descLines}
77
+ />
78
+ )
79
+ }
@@ -0,0 +1,66 @@
1
+ .cp-hero-demo {
2
+ max-width: var(--cp-size-demo-max);
3
+ margin: 0 auto;
4
+ border: 1px solid var(--cp-c-border);
5
+ border-radius: var(--cp-radius-lg);
6
+ background: var(--cp-code-block-bg);
7
+ overflow: hidden;
8
+ box-shadow: var(--cp-shadow-hero-demo);
9
+ }
10
+
11
+ .cp-hero-demo__bar {
12
+ display: flex;
13
+ align-items: center;
14
+ gap: var(--cp-s-8);
15
+ padding: var(--cp-s-10) var(--cp-s-14);
16
+ background: var(--cp-c-bg-elv);
17
+ border-bottom: 1px solid var(--cp-c-border);
18
+ }
19
+
20
+ .cp-hero-demo__dot {
21
+ width: var(--cp-size-window-dot);
22
+ height: var(--cp-size-window-dot);
23
+ border-radius: 50%;
24
+ background: var(--cp-c-bg-soft);
25
+ border: 1px solid var(--cp-c-border);
26
+ }
27
+
28
+ .cp-hero-demo__title {
29
+ font-family: var(--cp-font-family-mono);
30
+ font-size: var(--cp-fs-demo-title);
31
+ color: var(--cp-c-text-3);
32
+ margin-left: var(--cp-s-8);
33
+ }
34
+
35
+ .cp-hero-demo__title em {
36
+ color: var(--cp-c-text-2);
37
+ font-style: normal;
38
+ }
39
+
40
+ .cp-hero-demo__body {
41
+ margin: 0;
42
+ padding: var(--cp-s-20) var(--cp-s-24);
43
+ font-family: var(--cp-font-family-mono);
44
+ font-size: var(--cp-fs-demo-body);
45
+ line-height: var(--cp-lh-demo);
46
+ white-space: pre;
47
+ overflow-x: auto;
48
+ color: var(--cp-c-text-1);
49
+ }
50
+
51
+ .cp-hero-demo__prompt,
52
+ .cp-hero-demo__ok {
53
+ color: var(--cp-c-brand-1);
54
+ }
55
+
56
+ .cp-hero-demo__cmt {
57
+ color: var(--cp-c-text-3);
58
+ }
59
+
60
+ .cp-hero-demo__info {
61
+ color: var(--cp-c-tint-blue-fg);
62
+ }
63
+
64
+ .cp-hero-demo__file {
65
+ color: var(--cp-c-tint-amber-bright-fg);
66
+ }
@@ -0,0 +1,46 @@
1
+ import type React from 'react'
2
+
3
+ import './hero-demo.css'
4
+
5
+ /**
6
+ * HeroDemo — default terminal-style demo block used inside Hero.
7
+ *
8
+ * Renders a fake macOS window with `pnpm ciderpress dev` output. Self-contained
9
+ * so consumers can render it directly in MDX or via HomeLayout.
10
+ *
11
+ * @returns React element.
12
+ */
13
+ export function HeroDemo(): React.ReactElement {
14
+ return (
15
+ <div className="cp-hero-demo">
16
+ <div className="cp-hero-demo__bar">
17
+ <span className="cp-hero-demo__dot" />
18
+ <span className="cp-hero-demo__dot" />
19
+ <span className="cp-hero-demo__dot" />
20
+ <span className="cp-hero-demo__title">
21
+ <em>~/code/acme</em> — pnpm ciderpress dev
22
+ </span>
23
+ </div>
24
+ <pre className="cp-hero-demo__body">
25
+ <span className="cp-hero-demo__prompt">$ </span>pnpm ciderpress dev
26
+ {'\n\n'}
27
+ <span className="cp-hero-demo__ok"> ▸</span> ciderpress 0.5 — Rspress 2.0
28
+ {'\n'}
29
+ <span className="cp-hero-demo__ok"> ▸</span> watching{' '}
30
+ <span className="cp-hero-demo__file">./docs</span>,{' '}
31
+ <span className="cp-hero-demo__file">./openapi.yaml</span>
32
+ {'\n'}
33
+ <span className="cp-hero-demo__ok"> ▸</span> sidebar synced from 24 files
34
+ {'\n'}
35
+ <span className="cp-hero-demo__info"> ▸</span> openapi spec parsed — 18 endpoints
36
+ {'\n'}
37
+ <span className="cp-hero-demo__ok"> ✓</span> ready on{' '}
38
+ <span className="cp-hero-demo__file">http://localhost:4321</span> in 412ms
39
+ {'\n\n'}
40
+ <span className="cp-hero-demo__cmt"> ↻ docs/guides/openapi.md changed</span>
41
+ {'\n'}
42
+ <span className="cp-hero-demo__cmt"> ↻ rebuilt sidebar in 8ms</span>
43
+ </pre>
44
+ </div>
45
+ )
46
+ }
@@ -0,0 +1,96 @@
1
+ .cp-hero {
2
+ position: relative;
3
+ padding: 96px 0 72px;
4
+ text-align: center;
5
+ }
6
+
7
+ .cp-hero__inner {
8
+ max-width: 1100px;
9
+ margin: 0 auto;
10
+ padding: 0 32px;
11
+ }
12
+
13
+ .cp-hero__eyebrow {
14
+ display: inline-flex;
15
+ align-items: center;
16
+ gap: 8px;
17
+ padding: 6px 12px;
18
+ border: 1px solid var(--cp-c-border);
19
+ border-radius: var(--cp-radius-pill);
20
+ background: var(--cp-c-bg-elv);
21
+ font-family: var(--cp-font-family-mono);
22
+ font-size: 11px;
23
+ color: var(--cp-c-text-2);
24
+ text-transform: uppercase;
25
+ letter-spacing: 0.06em;
26
+ margin-bottom: 28px;
27
+ }
28
+
29
+ .cp-hero__title {
30
+ font-size: clamp(40px, 6.5vw, 76px);
31
+ font-weight: 600;
32
+ letter-spacing: -0.04em;
33
+ line-height: 1;
34
+ margin: 0 0 24px;
35
+ color: var(--cp-c-text-1);
36
+ }
37
+
38
+ .cp-hero__title .cp-hero__grad {
39
+ color: var(--cp-c-brand-1);
40
+ }
41
+
42
+ .cp-hero__tagline {
43
+ max-width: 640px;
44
+ margin: 0 auto 40px;
45
+ font-size: 18px;
46
+ line-height: 1.6;
47
+ color: var(--cp-c-text-2);
48
+ }
49
+
50
+ .cp-hero__cta {
51
+ display: flex;
52
+ gap: 12px;
53
+ justify-content: center;
54
+ flex-wrap: wrap;
55
+ margin-bottom: 56px;
56
+ }
57
+
58
+ .cp-hero__btn {
59
+ display: inline-flex;
60
+ align-items: center;
61
+ gap: 8px;
62
+ padding: 10px 18px;
63
+ font-size: 14px;
64
+ font-weight: 500;
65
+ border-radius: var(--cp-radius-pill);
66
+ border: 1px solid var(--cp-c-border);
67
+ background: transparent;
68
+ color: var(--cp-c-text-1);
69
+ cursor: pointer;
70
+ transition: all 0.15s ease;
71
+ white-space: nowrap;
72
+ text-decoration: none;
73
+ }
74
+
75
+ .cp-hero__btn:hover {
76
+ background: var(--cp-c-bg-soft);
77
+ border-color: var(--cp-c-border);
78
+ }
79
+
80
+ .cp-hero__btn--primary {
81
+ background: var(--cp-c-brand-1);
82
+ color: var(--cp-c-brand-fg);
83
+ border-color: var(--cp-c-brand-1);
84
+ font-weight: 600;
85
+ }
86
+
87
+ .cp-hero__btn--primary:hover {
88
+ background: var(--cp-c-brand-2);
89
+ border-color: var(--cp-c-brand-2);
90
+ }
91
+
92
+ .cp-hero__demo {
93
+ max-width: 920px;
94
+ margin: 0 auto;
95
+ text-align: left;
96
+ }
@@ -0,0 +1,111 @@
1
+ import { match } from 'massaman/match'
2
+ import type React from 'react'
3
+
4
+ import { RouteLink } from '../../lib/route-link.tsx'
5
+ import { safeUrl } from '../../lib/safe-url.ts'
6
+
7
+ import './hero.css'
8
+
9
+ export interface HeroAction {
10
+ /**
11
+ * Visible label.
12
+ */
13
+ readonly text: string
14
+ /**
15
+ * Destination URL.
16
+ */
17
+ readonly link: string
18
+ /**
19
+ * Visual style — `brand` is the filled primary, `alt` is the outline.
20
+ */
21
+ readonly theme?: 'brand' | 'alt'
22
+ }
23
+
24
+ export interface HeroProps {
25
+ /**
26
+ * Optional eyebrow chip (e.g. "★ 2.1k stars · v0.4.2").
27
+ */
28
+ readonly eyebrow?: React.ReactNode
29
+ /**
30
+ * Main heading. Wrap a fragment in `<span className="cp-hero__grad">…</span>`
31
+ * for the gradient phrase.
32
+ */
33
+ readonly title: React.ReactNode
34
+ /**
35
+ * Sub-text shown below the headline.
36
+ */
37
+ readonly tagline?: React.ReactNode
38
+ /**
39
+ * Two CTAs at most for visual balance.
40
+ */
41
+ readonly actions?: readonly HeroAction[]
42
+ /**
43
+ * Optional visual block beneath the CTAs (terminal demo, screenshot, etc).
44
+ */
45
+ readonly demo?: React.ReactNode
46
+ }
47
+
48
+ /**
49
+ * Hero — landing-page hero with eyebrow chip, gradient-friendly headline,
50
+ * tagline, CTAs, and an optional demo slot. The radial accent glow + dotted
51
+ * grid backdrop are baked in via CSS and adapt to the active theme.
52
+ *
53
+ * @param props - Hero configuration.
54
+ * @returns React element.
55
+ */
56
+ export function Hero(props: HeroProps): React.ReactElement {
57
+ const { eyebrow, title, tagline, actions, demo } = props
58
+ const list = actions ?? []
59
+
60
+ return (
61
+ <section className="cp-hero">
62
+ <div className="cp-hero__inner">
63
+ {match(eyebrow)
64
+ .with(undefined, () => null)
65
+ .otherwise((e) => (
66
+ <div className="cp-hero__eyebrow">{e}</div>
67
+ ))}
68
+ <h1 className="cp-hero__title">{title}</h1>
69
+ {match(tagline)
70
+ .with(undefined, () => null)
71
+ .otherwise((t) => (
72
+ <p className="cp-hero__tagline">{t}</p>
73
+ ))}
74
+ {match(list.length === 0)
75
+ .with(true, () => null)
76
+ .otherwise(() => (
77
+ <div className="cp-hero__cta">{list.map(renderAction)}</div>
78
+ ))}
79
+ {match(demo)
80
+ .with(undefined, () => null)
81
+ .otherwise((d) => (
82
+ <div className="cp-hero__demo">{d}</div>
83
+ ))}
84
+ </div>
85
+ </section>
86
+ )
87
+ }
88
+
89
+ /**
90
+ * Render a single hero CTA action.
91
+ *
92
+ * @private
93
+ * @param action - Hero action.
94
+ * @param index - Array index for key generation.
95
+ * @returns Anchor element.
96
+ */
97
+ function renderAction(action: HeroAction, index: number): React.ReactElement | null {
98
+ const href = safeUrl(action.link)
99
+ if (href === null) {
100
+ return null
101
+ }
102
+ const className = match(action.theme ?? 'brand')
103
+ .with('brand', () => 'cp-hero__btn cp-hero__btn--primary')
104
+ .otherwise(() => 'cp-hero__btn')
105
+
106
+ return (
107
+ <RouteLink key={`${href}:${index}`} href={href} className={className}>
108
+ {action.text}
109
+ </RouteLink>
110
+ )
111
+ }