@ciderpress/ui 1.0.0-rc.1 → 1.0.0-rc.11

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 (162) hide show
  1. package/dist/head/css/loader-apple.css +1 -1
  2. package/dist/head/css/loader-dots.css +1 -1
  3. package/dist/head/css/themes/amber.css +1 -1
  4. package/dist/head/css/themes/arcade.css +1 -1
  5. package/dist/head/css/themes/grannysmith.css +1 -1
  6. package/dist/head/css/themes/honeycrisp.css +1 -1
  7. package/dist/head/css/themes/midnight.css +1 -1
  8. package/dist/head/css/themes/mulled.css +1 -1
  9. package/dist/index.d.ts +1 -1
  10. package/dist/index.mjs +4 -3
  11. package/dist/node.d.ts +1 -1
  12. package/dist/node.mjs +732 -55
  13. package/dist/plugins/mermaid/MermaidRenderer.tsx +49 -6
  14. package/dist/theme/components/footer/site-footer.tsx +68 -9
  15. package/dist/theme/components/home/cta.css +15 -0
  16. package/dist/theme/components/home/cta.tsx +10 -2
  17. package/dist/theme/components/home/feature-card.css +1 -1
  18. package/dist/theme/components/home/feature-card.tsx +8 -10
  19. package/dist/theme/components/home/feature.tsx +54 -31
  20. package/dist/theme/components/home/hero-demo.css +38 -0
  21. package/dist/theme/components/home/home-visual.tsx +226 -0
  22. package/dist/theme/components/home/layout.tsx +410 -108
  23. package/dist/theme/components/home/split.css +46 -19
  24. package/dist/theme/components/home/split.tsx +28 -8
  25. package/dist/theme/components/home/tabs.css +299 -0
  26. package/dist/theme/components/home/tabs.tsx +351 -0
  27. package/dist/theme/components/home/trust-strip.css +41 -0
  28. package/dist/theme/components/home/trust-strip.tsx +168 -11
  29. package/dist/theme/components/home/workspaces.tsx +176 -38
  30. package/dist/theme/components/nav/branch-tag.tsx +7 -7
  31. package/dist/theme/components/nav/ciderpress-docs-bar.css +13 -1
  32. package/dist/theme/components/nav/ciderpress-docs-bar.tsx +33 -2
  33. package/dist/theme/components/nav/ciderpress-header.css +2 -1
  34. package/dist/theme/components/nav/ciderpress-header.tsx +26 -3
  35. package/dist/theme/components/nav/ciderpress-nav-hamburger.css +50 -0
  36. package/dist/theme/components/nav/ciderpress-nav-hamburger.tsx +95 -9
  37. package/dist/theme/components/nav/ciderpress-nav-menu.css +88 -0
  38. package/dist/theme/components/nav/ciderpress-nav-menu.tsx +397 -38
  39. package/dist/theme/components/nav/ciderpress-nav-social-links.tsx +27 -22
  40. package/dist/theme/components/nav/floating-branch-indicator.tsx +7 -7
  41. package/dist/theme/components/nav/header-icon.css +24 -0
  42. package/dist/theme/components/nav/header-icon.tsx +119 -0
  43. package/dist/theme/components/nav/header-logo.css +16 -0
  44. package/dist/theme/components/nav/header-logo.tsx +200 -0
  45. package/dist/theme/components/nav/layout.tsx +117 -16
  46. package/dist/theme/components/nav/nav-logo.tsx +16 -19
  47. package/dist/theme/components/openapi/index.ts +0 -2
  48. package/dist/theme/components/openapi/openapi.css +0 -14
  49. package/dist/theme/components/shared/card-icon.tsx +37 -0
  50. package/dist/theme/components/shared/ciderpress-logo.tsx +5 -1
  51. package/dist/theme/components/shared/icon.tsx +120 -35
  52. package/dist/theme/components/shared/resolve-card-icon.ts +53 -12
  53. package/dist/theme/components/shared/section-card.tsx +37 -6
  54. package/dist/theme/components/sidebar/sidebar-badge.css +50 -0
  55. package/dist/theme/components/sidebar/sidebar-badge.tsx +153 -0
  56. package/dist/theme/components/sidebar/sidebar-links.tsx +6 -2
  57. package/dist/theme/components/sidebar/sidebar-scope.tsx +24 -1
  58. package/dist/theme/components/theme-provider.tsx +27 -11
  59. package/dist/theme/components/workspaces/card.css +4 -0
  60. package/dist/theme/components/workspaces/card.tsx +10 -12
  61. package/dist/theme/components/workspaces/grid.tsx +18 -6
  62. package/dist/theme/hooks/use-ciderpress.ts +65 -5
  63. package/dist/theme/hooks/use-nav-items.ts +82 -11
  64. package/dist/theme/index.tsx +10 -3
  65. package/dist/theme/lib/read-social-links.ts +4 -3
  66. package/dist/theme/lib/rich-text-parse.ts +740 -0
  67. package/dist/theme/lib/rich-text.test.tsx +342 -0
  68. package/dist/theme/lib/rich-text.tsx +86 -0
  69. package/dist/theme/lib/theme-favicon.ts +1 -1
  70. package/dist/theme/lib/with-mount-base.ts +31 -0
  71. package/dist/theme/styles/overrides/fonts.css +7 -4
  72. package/dist/theme/styles/overrides/footnotes.css +54 -0
  73. package/dist/theme/styles/overrides/home.css +11 -2
  74. package/dist/theme/styles/overrides/lists.css +83 -0
  75. package/dist/theme/styles/overrides/rail.css +27 -10
  76. package/dist/theme/styles/overrides/rspress.css +10 -5
  77. package/dist/theme/styles/overrides/section-card.css +9 -0
  78. package/dist/theme/styles/overrides/sidebar.css +22 -0
  79. package/dist/theme/styles/overrides/tokens.css +41 -23
  80. package/dist/theme/styles/rich-text.css +106 -0
  81. package/dist/theme/styles/themes/amber.css +32 -2
  82. package/dist/theme/styles/themes/arcade.css +16 -1
  83. package/dist/theme/styles/themes/grannysmith.css +32 -2
  84. package/dist/theme/styles/themes/honeycrisp.css +37 -7
  85. package/dist/theme/styles/themes/midnight.css +16 -1
  86. package/dist/theme/styles/themes/mulled.css +54 -9
  87. package/package.json +18 -16
  88. package/src/theme/components/footer/site-footer.tsx +68 -9
  89. package/src/theme/components/home/cta.css +15 -0
  90. package/src/theme/components/home/cta.tsx +10 -2
  91. package/src/theme/components/home/feature-card.css +1 -1
  92. package/src/theme/components/home/feature-card.tsx +8 -10
  93. package/src/theme/components/home/feature.tsx +54 -31
  94. package/src/theme/components/home/hero-demo.css +38 -0
  95. package/src/theme/components/home/home-visual.tsx +226 -0
  96. package/src/theme/components/home/layout.tsx +410 -108
  97. package/src/theme/components/home/split.css +46 -19
  98. package/src/theme/components/home/split.tsx +28 -8
  99. package/src/theme/components/home/tabs.css +299 -0
  100. package/src/theme/components/home/tabs.tsx +351 -0
  101. package/src/theme/components/home/trust-strip.css +41 -0
  102. package/src/theme/components/home/trust-strip.tsx +168 -11
  103. package/src/theme/components/home/workspaces.tsx +176 -38
  104. package/src/theme/components/nav/branch-tag.tsx +7 -7
  105. package/src/theme/components/nav/ciderpress-docs-bar.css +13 -1
  106. package/src/theme/components/nav/ciderpress-docs-bar.tsx +33 -2
  107. package/src/theme/components/nav/ciderpress-header.css +2 -1
  108. package/src/theme/components/nav/ciderpress-header.tsx +26 -3
  109. package/src/theme/components/nav/ciderpress-nav-hamburger.css +50 -0
  110. package/src/theme/components/nav/ciderpress-nav-hamburger.tsx +95 -9
  111. package/src/theme/components/nav/ciderpress-nav-menu.css +88 -0
  112. package/src/theme/components/nav/ciderpress-nav-menu.tsx +397 -38
  113. package/src/theme/components/nav/ciderpress-nav-social-links.tsx +27 -22
  114. package/src/theme/components/nav/floating-branch-indicator.tsx +7 -7
  115. package/src/theme/components/nav/header-icon.css +24 -0
  116. package/src/theme/components/nav/header-icon.tsx +119 -0
  117. package/src/theme/components/nav/header-logo.css +16 -0
  118. package/src/theme/components/nav/header-logo.tsx +200 -0
  119. package/src/theme/components/nav/layout.tsx +117 -16
  120. package/src/theme/components/nav/nav-logo.tsx +16 -19
  121. package/src/theme/components/openapi/index.ts +0 -2
  122. package/src/theme/components/openapi/openapi.css +0 -14
  123. package/src/theme/components/shared/card-icon.tsx +37 -0
  124. package/src/theme/components/shared/ciderpress-logo.tsx +5 -1
  125. package/src/theme/components/shared/icon.tsx +120 -35
  126. package/src/theme/components/shared/resolve-card-icon.ts +53 -12
  127. package/src/theme/components/shared/section-card.tsx +37 -6
  128. package/src/theme/components/sidebar/sidebar-badge.css +50 -0
  129. package/src/theme/components/sidebar/sidebar-badge.tsx +153 -0
  130. package/src/theme/components/sidebar/sidebar-links.tsx +6 -2
  131. package/src/theme/components/sidebar/sidebar-scope.tsx +24 -1
  132. package/src/theme/components/theme-provider.tsx +27 -11
  133. package/src/theme/components/workspaces/card.css +4 -0
  134. package/src/theme/components/workspaces/card.tsx +10 -12
  135. package/src/theme/components/workspaces/grid.tsx +18 -6
  136. package/src/theme/hooks/use-ciderpress.ts +65 -5
  137. package/src/theme/hooks/use-nav-items.ts +82 -11
  138. package/src/theme/index.tsx +10 -3
  139. package/src/theme/lib/read-social-links.ts +4 -3
  140. package/src/theme/lib/rich-text-parse.ts +740 -0
  141. package/src/theme/lib/rich-text.test.tsx +342 -0
  142. package/src/theme/lib/rich-text.tsx +86 -0
  143. package/src/theme/lib/theme-favicon.ts +1 -1
  144. package/src/theme/lib/with-mount-base.ts +31 -0
  145. package/src/theme/styles/overrides/fonts.css +7 -4
  146. package/src/theme/styles/overrides/footnotes.css +54 -0
  147. package/src/theme/styles/overrides/home.css +11 -2
  148. package/src/theme/styles/overrides/lists.css +83 -0
  149. package/src/theme/styles/overrides/rail.css +27 -10
  150. package/src/theme/styles/overrides/rspress.css +10 -5
  151. package/src/theme/styles/overrides/section-card.css +9 -0
  152. package/src/theme/styles/overrides/sidebar.css +22 -0
  153. package/src/theme/styles/overrides/tokens.css +41 -23
  154. package/src/theme/styles/rich-text.css +106 -0
  155. package/src/theme/styles/themes/amber.css +32 -2
  156. package/src/theme/styles/themes/arcade.css +16 -1
  157. package/src/theme/styles/themes/grannysmith.css +32 -2
  158. package/src/theme/styles/themes/honeycrisp.css +37 -7
  159. package/src/theme/styles/themes/midnight.css +16 -1
  160. package/src/theme/styles/themes/mulled.css +54 -9
  161. package/dist/theme/components/openapi/copy-markdown-button.tsx +0 -41
  162. package/src/theme/components/openapi/copy-markdown-button.tsx +0 -41
@@ -7,7 +7,7 @@
7
7
  --cp-c-brand-fg: #ffffff;
8
8
  --cp-c-brand-soft: rgba(153, 27, 27, 0.14);
9
9
  --cp-c-on-brand: #ffffff;
10
- --cp-c-brand-light: #dc2626;
10
+ --cp-c-brand-light: #ef4444;
11
11
  --cp-c-brand-lighter: #f87171;
12
12
  --cp-c-success: #16a34a;
13
13
  --cp-c-error: #dc2626;
@@ -130,8 +130,11 @@
130
130
  --cp-radius-lg: 10px;
131
131
  --cp-radius-md-lg: 12px;
132
132
  --cp-radius-pill: 9999px;
133
- --cp-ff-sans: 'Geist', ui-sans-serif, system-ui, sans-serif;
133
+ --cp-ff-sans:
134
+ 'Inter var experimental', 'Inter var', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
135
+ Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
134
136
  --cp-ff-mono: 'Geist Mono', ui-monospace, 'SFMono-Regular', monospace;
137
+ --cp-ff-display: 'Geist Pixel Square', ui-sans-serif, system-ui, sans-serif;
135
138
  --cp-fw-regular: 400;
136
139
  --cp-fw-medium: 500;
137
140
  --cp-fw-semibold: 600;
@@ -251,7 +254,7 @@
251
254
  --rp-c-bg-mute: #0a0a0a;
252
255
  --rp-c-bg-soft: #1c1c1c;
253
256
  --rp-c-brand: #991b1b;
254
- --rp-c-brand-light: #dc2626;
257
+ --rp-c-brand-light: #ef4444;
255
258
  --rp-c-brand-lighter: #f87171;
256
259
  --rp-c-brand-dark: #7f1d1d;
257
260
  --rp-c-brand-darker: #450a0a;
@@ -270,6 +273,18 @@
270
273
  --rp-home-feature-bg: #1c1c1c;
271
274
  --rp-home-hero-secondary-color: rgba(245, 245, 245, 0.72);
272
275
  --rp-home-hero-title-color: #f5f5f5;
276
+ --rp-font-family-base:
277
+ 'Inter var experimental', 'Inter var', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
278
+ Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
279
+ --rp-font-family-mono: 'Geist Mono', ui-monospace, 'SFMono-Regular', monospace;
280
+ --cp-font-family-base:
281
+ 'Inter var experimental', 'Inter var', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
282
+ Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
283
+ --cp-font-family-sans:
284
+ 'Inter var experimental', 'Inter var', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
285
+ Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
286
+ --cp-font-family-mono: 'Geist Mono', ui-monospace, 'SFMono-Regular', monospace;
287
+ --cp-font-family-pixel: 'Geist Pixel Square', ui-sans-serif, system-ui, sans-serif;
273
288
  }
274
289
 
275
290
  html[data-cp-theme='mulled'][data-cp-variant='dark'] {
@@ -279,7 +294,7 @@ html[data-cp-theme='mulled'][data-cp-variant='dark'] {
279
294
  --cp-c-brand-fg: #ffffff;
280
295
  --cp-c-brand-soft: rgba(153, 27, 27, 0.14);
281
296
  --cp-c-on-brand: #ffffff;
282
- --cp-c-brand-light: #dc2626;
297
+ --cp-c-brand-light: #ef4444;
283
298
  --cp-c-brand-lighter: #f87171;
284
299
  --cp-c-success: #16a34a;
285
300
  --cp-c-error: #dc2626;
@@ -402,8 +417,11 @@ html[data-cp-theme='mulled'][data-cp-variant='dark'] {
402
417
  --cp-radius-lg: 10px;
403
418
  --cp-radius-md-lg: 12px;
404
419
  --cp-radius-pill: 9999px;
405
- --cp-ff-sans: 'Geist', ui-sans-serif, system-ui, sans-serif;
420
+ --cp-ff-sans:
421
+ 'Inter var experimental', 'Inter var', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
422
+ Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
406
423
  --cp-ff-mono: 'Geist Mono', ui-monospace, 'SFMono-Regular', monospace;
424
+ --cp-ff-display: 'Geist Pixel Square', ui-sans-serif, system-ui, sans-serif;
407
425
  --cp-fw-regular: 400;
408
426
  --cp-fw-medium: 500;
409
427
  --cp-fw-semibold: 600;
@@ -523,7 +541,7 @@ html[data-cp-theme='mulled'][data-cp-variant='dark'] {
523
541
  --rp-c-bg-mute: #0a0a0a;
524
542
  --rp-c-bg-soft: #1c1c1c;
525
543
  --rp-c-brand: #991b1b;
526
- --rp-c-brand-light: #dc2626;
544
+ --rp-c-brand-light: #ef4444;
527
545
  --rp-c-brand-lighter: #f87171;
528
546
  --rp-c-brand-dark: #7f1d1d;
529
547
  --rp-c-brand-darker: #450a0a;
@@ -542,6 +560,18 @@ html[data-cp-theme='mulled'][data-cp-variant='dark'] {
542
560
  --rp-home-feature-bg: #1c1c1c;
543
561
  --rp-home-hero-secondary-color: rgba(245, 245, 245, 0.72);
544
562
  --rp-home-hero-title-color: #f5f5f5;
563
+ --rp-font-family-base:
564
+ 'Inter var experimental', 'Inter var', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
565
+ Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
566
+ --rp-font-family-mono: 'Geist Mono', ui-monospace, 'SFMono-Regular', monospace;
567
+ --cp-font-family-base:
568
+ 'Inter var experimental', 'Inter var', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
569
+ Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
570
+ --cp-font-family-sans:
571
+ 'Inter var experimental', 'Inter var', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
572
+ Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
573
+ --cp-font-family-mono: 'Geist Mono', ui-monospace, 'SFMono-Regular', monospace;
574
+ --cp-font-family-pixel: 'Geist Pixel Square', ui-sans-serif, system-ui, sans-serif;
545
575
  }
546
576
 
547
577
  html[data-cp-theme='mulled'][data-cp-variant='light'] {
@@ -551,7 +581,7 @@ html[data-cp-theme='mulled'][data-cp-variant='light'] {
551
581
  --cp-c-brand-fg: #ffffff;
552
582
  --cp-c-brand-soft: rgba(153, 27, 27, 0.14);
553
583
  --cp-c-on-brand: #ffffff;
554
- --cp-c-brand-light: #dc2626;
584
+ --cp-c-brand-light: #ef4444;
555
585
  --cp-c-brand-lighter: #f87171;
556
586
  --cp-c-success: #16a34a;
557
587
  --cp-c-error: #dc2626;
@@ -674,8 +704,11 @@ html[data-cp-theme='mulled'][data-cp-variant='light'] {
674
704
  --cp-radius-lg: 10px;
675
705
  --cp-radius-md-lg: 12px;
676
706
  --cp-radius-pill: 9999px;
677
- --cp-ff-sans: 'Geist', ui-sans-serif, system-ui, sans-serif;
707
+ --cp-ff-sans:
708
+ 'Inter var experimental', 'Inter var', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
709
+ Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
678
710
  --cp-ff-mono: 'Geist Mono', ui-monospace, 'SFMono-Regular', monospace;
711
+ --cp-ff-display: 'Geist Pixel Square', ui-sans-serif, system-ui, sans-serif;
679
712
  --cp-fw-regular: 400;
680
713
  --cp-fw-medium: 500;
681
714
  --cp-fw-semibold: 600;
@@ -795,7 +828,7 @@ html[data-cp-theme='mulled'][data-cp-variant='light'] {
795
828
  --rp-c-bg-mute: #fbf6f4;
796
829
  --rp-c-bg-soft: #ead9d4;
797
830
  --rp-c-brand: #991b1b;
798
- --rp-c-brand-light: #dc2626;
831
+ --rp-c-brand-light: #ef4444;
799
832
  --rp-c-brand-lighter: #f87171;
800
833
  --rp-c-brand-dark: #7f1d1d;
801
834
  --rp-c-brand-darker: #450a0a;
@@ -814,4 +847,16 @@ html[data-cp-theme='mulled'][data-cp-variant='light'] {
814
847
  --rp-home-feature-bg: #ead9d4;
815
848
  --rp-home-hero-secondary-color: rgba(42, 6, 6, 0.72);
816
849
  --rp-home-hero-title-color: #2a0606;
850
+ --rp-font-family-base:
851
+ 'Inter var experimental', 'Inter var', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
852
+ Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
853
+ --rp-font-family-mono: 'Geist Mono', ui-monospace, 'SFMono-Regular', monospace;
854
+ --cp-font-family-base:
855
+ 'Inter var experimental', 'Inter var', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
856
+ Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
857
+ --cp-font-family-sans:
858
+ 'Inter var experimental', 'Inter var', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
859
+ Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
860
+ --cp-font-family-mono: 'Geist Mono', ui-monospace, 'SFMono-Regular', monospace;
861
+ --cp-font-family-pixel: 'Geist Pixel Square', ui-sans-serif, system-ui, sans-serif;
817
862
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ciderpress/ui",
3
- "version": "1.0.0-rc.1",
3
+ "version": "1.0.0-rc.11",
4
4
  "description": "Rspress plugin, theme components, and styles for ciderpress",
5
5
  "keywords": [
6
6
  "ciderpress",
@@ -42,37 +42,39 @@
42
42
  },
43
43
  "publishConfig": {
44
44
  "access": "public",
45
- "provenance": false
45
+ "provenance": true
46
46
  },
47
47
  "dependencies": {
48
48
  "@iconify-json/catppuccin": "^1.2.17",
49
49
  "@iconify-json/devicon": "^1.2.62",
50
50
  "@iconify-json/logos": "^1.2.11",
51
- "@iconify-json/material-icon-theme": "^1.2.67",
51
+ "@iconify-json/material-icon-theme": "^1.2.69",
52
52
  "@iconify-json/mdi": "^1.2.3",
53
- "@iconify-json/pixelarticons": "^1.2.6",
54
- "@iconify-json/simple-icons": "^1.2.86",
53
+ "@iconify-json/pixel": "^1.2.2",
54
+ "@iconify-json/pixelarticons": "^1.2.7",
55
+ "@iconify-json/simple-icons": "^1.2.89",
55
56
  "@iconify-json/skill-icons": "^1.2.4",
56
- "@iconify-json/vscode-icons": "^1.2.55",
57
+ "@iconify-json/vscode-icons": "^1.2.65",
57
58
  "@iconify/react": "^6.0.2",
59
+ "@mermaid-js/layout-elk": "^0.2.2",
58
60
  "clsx": "^2.1.1",
59
61
  "katex": "^0.17.0",
60
- "massaman": "^0.2.0",
61
- "mermaid": "^10.9.6",
62
+ "massaman": "^0.3.0",
63
+ "mermaid": "^11.16.0",
62
64
  "openapi-sampler": "^1.7.4",
63
- "react-aria-components": "^1.18.0",
65
+ "react-aria-components": "^1.19.0",
64
66
  "ts-morph": "^28.0.0",
65
67
  "unist-util-visit": "^5.1.0",
66
- "@ciderpress/theme": "1.0.0-rc.1",
67
- "@ciderpress/config": "1.0.0-rc.1"
68
+ "@ciderpress/config": "1.0.0-rc.8",
69
+ "@ciderpress/theme": "1.0.0-rc.5"
68
70
  },
69
71
  "devDependencies": {
70
72
  "@ladle/react": "^5.1.1",
71
- "@rslib/core": "^0.22.0",
72
- "@rspress/core": "^2.0.14",
73
+ "@rslib/core": "0.23.1",
74
+ "@rspress/core": "^2.0.16",
73
75
  "@types/react": "^19.2.17",
74
76
  "@types/react-dom": "^19.2.3",
75
- "esbuild": "^0.28.0",
77
+ "esbuild": "^0.28.1",
76
78
  "geist": "^1.7.2",
77
79
  "react": "^19.2.7",
78
80
  "react-dom": "^19.2.7",
@@ -81,10 +83,10 @@
81
83
  "rspress-plugin-katex": "^1.0.1",
82
84
  "rspress-plugin-supersub": "^1.0.0",
83
85
  "typescript": "^6.0.3",
84
- "vitest": "^4.1.8"
86
+ "vitest": "^4.1.10"
85
87
  },
86
88
  "peerDependencies": {
87
- "@rspress/core": "^2.0.14",
89
+ "@rspress/core": "^2.0.16",
88
90
  "react": "^19.2.5",
89
91
  "react-dom": "^19.2.5"
90
92
  },
@@ -1,14 +1,15 @@
1
+ import type { CopyrightConfig, FooterConfig } from '@ciderpress/config'
1
2
  import { useSite } from '@rspress/core/runtime'
2
- import { match } from 'massaman/match'
3
+ import { match, P } from 'massaman/match'
3
4
  import type React from 'react'
4
5
 
5
6
  import { useCiderpress } from '../../hooks/use-ciderpress'
6
7
  import { readSocialLinks } from '../../lib/read-social-links'
7
8
  import { RouteLink } from '../../lib/route-link.tsx'
8
9
  import { safeUrl } from '../../lib/safe-url.ts'
10
+ import { withMountBase } from '../../lib/with-mount-base.ts'
9
11
  import { CiderpressNavSocialLinks } from '../nav/ciderpress-nav-social-links'
10
12
  import { ThemeSwitcher } from '../nav/theme-switcher'
11
- import { CiderpressMark } from '../shared/ciderpress-mark'
12
13
 
13
14
  import './site-footer.css'
14
15
 
@@ -35,14 +36,17 @@ export function SiteFooter(): React.ReactElement | null {
35
36
  const { message, copyright, socials } = ciderpressFooter ?? {}
36
37
  const { columns, tagline, brandMark } = siteFooter ?? {}
37
38
 
38
- const hasRspressContent = message !== undefined || copyright !== undefined || socials === true
39
+ const copyrightText = resolveCopyright(copyright, rspressSite.title)
40
+ const shouldRenderSocials = socials === true && socialLinks.length > 0
41
+
42
+ const hasFooterContent = message !== undefined || copyrightText !== null || shouldRenderSocials
39
43
  const hasSiteContent = columns !== undefined || tagline !== undefined
40
44
  // The footer also hosts the theme switcher when it's enabled — so a
41
- // config with `theme.switcher: true` but no other footer content
45
+ // config with `theme.themeSwitcher: true` but no other footer content
42
46
  // still needs the footer shell rendered.
43
47
  const hasSwitcher = __CIDERPRESS_THEME_SWITCHER__
44
48
 
45
- if (!hasRspressContent && !hasSiteContent && !hasSwitcher) {
49
+ if (!hasFooterContent && !hasSiteContent && !hasSwitcher) {
46
50
  return null
47
51
  }
48
52
 
@@ -56,7 +60,16 @@ export function SiteFooter(): React.ReactElement | null {
56
60
  <div className="cp-site-footer__brand-mark">
57
61
  {match(brandMark)
58
62
  .with(undefined, () => (
59
- <CiderpressMark className="cp-site-footer__brand-icon" title="" />
63
+ // Default to the project's `/icon.svg` (auto-generated
64
+ // from `config.title` at sync time, or overridden by
65
+ // shipping a `public/icon.svg`). This was previously
66
+ // the hardcoded `<CiderpressMark />` apple, which
67
+ // leaked ciderpress branding into every footer.
68
+ <img
69
+ src={withMountBase('/icon.svg')}
70
+ alt=""
71
+ className="cp-site-footer__brand-icon"
72
+ />
60
73
  ))
61
74
  .otherwise((mark) => mark)}
62
75
  </div>
@@ -65,7 +78,7 @@ export function SiteFooter(): React.ReactElement | null {
65
78
  .otherwise((msg) => (
66
79
  <p className="cp-site-footer__message">{msg}</p>
67
80
  ))}
68
- {match(socials === true && socialLinks.length > 0)
81
+ {match(shouldRenderSocials)
69
82
  .with(true, () => (
70
83
  <div className="cp-site-footer__socials">
71
84
  <CiderpressNavSocialLinks links={socialLinks} />
@@ -95,8 +108,8 @@ export function SiteFooter(): React.ReactElement | null {
95
108
  </div>
96
109
  <div className="cp-site-footer__bottom">
97
110
  <div className="cp-site-footer__bottom-inner">
98
- {match(copyright)
99
- .with(undefined, () => null)
111
+ {match(copyrightText)
112
+ .with(null, () => null)
100
113
  .otherwise((cr) => (
101
114
  <span className="cp-site-footer__copyright">{cr}</span>
102
115
  ))}
@@ -113,3 +126,49 @@ export function SiteFooter(): React.ReactElement | null {
113
126
  </footer>
114
127
  )
115
128
  }
129
+
130
+ /**
131
+ * Resolve the `footer.copyright` config union into a string for rendering.
132
+ *
133
+ * Accepts the new public shape: `true` for auto-generation from the site
134
+ * title + current year, a verbatim string, or a `CopyrightConfig` object
135
+ * with `company` / `dba` / `year`. `undefined` returns `null` so the
136
+ * caller can skip the render.
137
+ *
138
+ * @private
139
+ * @param copyright - The footer copyright config value
140
+ * @param siteTitle - The Rspress site title to use as fallback owner name
141
+ * @returns The formatted copyright string, or `null` when nothing should render
142
+ */
143
+ function resolveCopyright(
144
+ copyright: FooterConfig['copyright'],
145
+ siteTitle: string | undefined
146
+ ): string | null {
147
+ return match(copyright)
148
+ .with(undefined, () => null)
149
+ .with(true, () => formatCopyright({}, siteTitle))
150
+ .with(P.string, (s) => s)
151
+ .otherwise((cfg) => formatCopyright(cfg, siteTitle))
152
+ }
153
+
154
+ /**
155
+ * Build a copyright string from a partial `CopyrightConfig`. Falls back to
156
+ * the site title for the owner name and the current year for the date.
157
+ *
158
+ * @private
159
+ * @param cfg - Copyright config object (may be empty)
160
+ * @param siteTitle - Fallback owner name
161
+ * @returns Formatted copyright string
162
+ */
163
+ function formatCopyright(cfg: CopyrightConfig, siteTitle: string | undefined): string {
164
+ const currentYear = new Date().getFullYear()
165
+ const yearPart = match(cfg.year)
166
+ .with(undefined, () => String(currentYear))
167
+ .with(P.number, (n) => String(n))
168
+ .otherwise(({ from }) => `${from}–${currentYear}`)
169
+ const owner = cfg.dba ?? cfg.company ?? siteTitle ?? ''
170
+ const ownerPart = match(owner.length === 0)
171
+ .with(true, () => '')
172
+ .otherwise(() => ` ${owner}`)
173
+ return `© ${yearPart}${ownerPart}`
174
+ }
@@ -9,6 +9,21 @@
9
9
  padding: 0 32px;
10
10
  }
11
11
 
12
+ .cp-cta__eyebrow {
13
+ font-family: var(--cp-font-family-mono);
14
+ font-size: var(--cp-fs-eyebrow);
15
+ text-transform: uppercase;
16
+ letter-spacing: var(--cp-letter-eyebrow);
17
+ /* Same shade pair as `.cp-accent` — `--cp-c-brand-1` is a fill colour and
18
+ misses 4.5:1 at this size on several themes. See styles/rich-text.css. */
19
+ color: var(--cp-c-brand-2, var(--cp-c-brand-1));
20
+ margin-bottom: var(--cp-s-12);
21
+ }
22
+
23
+ html[data-cp-variant='dark'] .cp-cta__eyebrow {
24
+ color: var(--cp-c-brand-light, var(--cp-c-brand-1));
25
+ }
26
+
12
27
  .cp-cta__title {
13
28
  font-size: clamp(32px, 5vw, 56px);
14
29
  font-weight: 600;
@@ -1,6 +1,7 @@
1
- import { match } from 'massaman/match'
1
+ import { match, P } from 'massaman/match'
2
2
  import type React from 'react'
3
3
 
4
+ import { renderRichText } from '../../lib/rich-text.tsx'
4
5
  import { RouteLink } from '../../lib/route-link.tsx'
5
6
  import { safeUrl } from '../../lib/safe-url.ts'
6
7
  import type { HeroAction } from './hero'
@@ -8,6 +9,10 @@ import type { HeroAction } from './hero'
8
9
  import './cta.css'
9
10
 
10
11
  export interface CTAProps {
12
+ /**
13
+ * Small uppercase kicker rendered above the headline.
14
+ */
15
+ readonly eyebrow?: string
11
16
  /**
12
17
  * Headline.
13
18
  */
@@ -30,12 +35,15 @@ export interface CTAProps {
30
35
  * @returns React element.
31
36
  */
32
37
  export function CTA(props: CTAProps): React.ReactElement {
33
- const { title, subtitle, actions } = props
38
+ const { eyebrow, title, subtitle, actions } = props
34
39
  const list = actions ?? []
35
40
 
36
41
  return (
37
42
  <section className="cp-cta">
38
43
  <div className="cp-cta__inner">
44
+ {match(eyebrow)
45
+ .with(P.string, (e) => <div className="cp-cta__eyebrow">{renderRichText(e)}</div>)
46
+ .otherwise(() => null)}
39
47
  <h2 className="cp-cta__title">{title}</h2>
40
48
  {match(subtitle)
41
49
  .with(undefined, () => null)
@@ -18,7 +18,7 @@
18
18
  }
19
19
 
20
20
  .cp-feature-card__title {
21
- font-family: 'Geist Pixel Square', var(--rp-font-family-base, sans-serif);
21
+ font-family: var(--cp-ff-display);
22
22
  font-size: var(--cp-fs-feature-title);
23
23
  font-weight: var(--cp-fw-bold);
24
24
  color: var(--rp-c-text-1, var(--cp-c-text-1));
@@ -2,15 +2,17 @@ import { match, P } from 'massaman/match'
2
2
  import type React from 'react'
3
3
 
4
4
  import './feature-card.css'
5
+ import { renderRichText } from '../../lib/rich-text.tsx'
5
6
  import { Card } from '../shared/card'
6
- import { Icon } from '../shared/icon'
7
+ import { CardIcon } from '../shared/card-icon'
8
+ import type { CardIconInput } from '../shared/resolve-card-icon'
7
9
  import { resolveCardIcon } from '../shared/resolve-card-icon'
8
10
 
9
11
  export interface FeatureCardProps {
10
12
  readonly title: string
11
13
  readonly description: string
12
14
  readonly href?: string
13
- readonly icon?: string | { readonly id: string; readonly color: string }
15
+ readonly icon?: CardIconInput
14
16
  readonly span?: 2 | 3 | 4 | 6
15
17
  readonly titleLines?: number
16
18
  readonly descriptionLines?: number
@@ -23,7 +25,7 @@ export interface FeatureItem {
23
25
  readonly title: string
24
26
  readonly details: string
25
27
  readonly link?: string
26
- readonly icon?: string | { readonly id: string; readonly color: string }
28
+ readonly icon?: CardIconInput
27
29
  readonly span?: 2 | 3 | 4 | 6
28
30
  }
29
31
 
@@ -46,11 +48,7 @@ export function FeatureCard({
46
48
  const resolved = resolveCardIcon(icon)
47
49
 
48
50
  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
- ))
51
+ .with(P.nonNullable, (r) => <CardIcon resolved={r} className="cp-card__icon" />)
54
52
  .otherwise(() => null)
55
53
 
56
54
  const linkTail = match(href)
@@ -67,14 +65,14 @@ export function FeatureCard({
67
65
  className={clampClass('cp-feature-card__title', titleLines)}
68
66
  style={clampStyle(titleLines)}
69
67
  >
70
- {title}
68
+ {renderRichText(title)}
71
69
  </span>
72
70
  </div>
73
71
  <span
74
72
  className={clampClass('cp-feature-card__desc', descriptionLines)}
75
73
  style={clampStyle(descriptionLines)}
76
74
  >
77
- {description}
75
+ {renderRichText(description)}
78
76
  </span>
79
77
  {linkTail}
80
78
  </Card>
@@ -1,45 +1,68 @@
1
- import type { HomeGridConfig } from '@ciderpress/config'
2
- import { useFrontmatter } from '@rspress/core/runtime'
1
+ import type { TruncateConfig } from '@ciderpress/config'
3
2
  import { match, P } from 'massaman/match'
4
3
  import type React from 'react'
5
4
 
6
- import { useCiderpress } from '../../hooks/use-ciderpress'
5
+ import { renderRichText } from '../../lib/rich-text.tsx'
7
6
  import { FeatureCard } from './feature-card'
8
7
  import type { FeatureItem } from './feature-card'
9
8
 
9
+ interface FrontmatterFeaturesHeading {
10
+ readonly label?: string
11
+ readonly title?: string
12
+ readonly body?: string
13
+ }
14
+
15
+ interface HomeFeatureProps {
16
+ readonly items?: readonly FeatureItem[]
17
+ readonly heading?: FrontmatterFeaturesHeading
18
+ readonly columns?: 1 | 2 | 3 | 4
19
+ readonly truncate?: TruncateConfig
20
+ }
21
+
22
+ const DEFAULT_HEADING_EYEBROW = 'Features'
23
+ const DEFAULT_HEADING_TITLE = 'Built for the way you ship.'
24
+ const DEFAULT_HEADING_SUBTITLE =
25
+ "Everything you need, nothing you don't. Configured in TypeScript, validated at boot."
26
+
10
27
  /**
11
- * Custom HomeFeature override for ciderpress.
12
- * Uses useFrontmatter() hook to read features and renders with FeatureCard/FeatureGrid styling.
28
+ * Features grid block. Renders the supplied feature cards under a heading,
29
+ * or nothing when no cards are present.
13
30
  *
14
- * @returns React element with feature grid or null
31
+ * @param props - Resolved feature cards, optional heading, and truncation limits.
32
+ * @returns React element with the feature grid, or null.
15
33
  */
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
34
+ export function HomeFeature(props: HomeFeatureProps): React.ReactElement | null {
35
+ const { items, heading, columns, truncate } = props
36
+ // Frontmatter is unvalidated user content — a `heading.title: {}`
37
+ // would otherwise render as `[object Object]` in the H2. Treat any
38
+ // non-string value as missing and fall through to the framework default.
39
+ const headingEyebrow = match(heading && heading.label)
40
+ .with(P.string, (s) => s)
41
+ .otherwise(() => DEFAULT_HEADING_EYEBROW)
42
+ const headingTitle = match(heading && heading.title)
43
+ .with(P.string, (s) => s)
44
+ .otherwise(() => DEFAULT_HEADING_TITLE)
45
+ const headingSubtitle = match(heading && heading.body)
46
+ .with(P.string, (s) => s)
47
+ .otherwise(() => DEFAULT_HEADING_SUBTITLE)
48
+ // Column count rides on a custom property so the grid keeps its CSS
49
+ // media queries — a narrow viewport still collapses to one column.
50
+ const gridStyle = match(columns)
51
+ .with(P.number, (c) => ({ '--cp-feature-cols': String(c) }) as React.CSSProperties)
52
+ .otherwise(() => undefined)
27
53
 
28
- return match(features)
54
+ return match(items)
29
55
  .with(
30
56
  P.when((f): f is readonly FeatureItem[] => Array.isArray(f) && f.length > 0),
31
- (items) => (
57
+ (list) => (
32
58
  <div className="cp-feature-section">
33
59
  <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>
60
+ <div className="cp-feature-section-head__eyebrow">{renderRichText(headingEyebrow)}</div>
61
+ <h2 className="cp-feature-section-head__title">{renderRichText(headingTitle)}</h2>
62
+ <p className="cp-feature-section-head__sub">{renderRichText(headingSubtitle)}</p>
40
63
  </div>
41
- <div className="cp-feature-grid">
42
- {items.map((f, i) => renderFeature(f, i, gridConfig))}
64
+ <div className="cp-feature-grid" style={gridStyle}>
65
+ {list.map((f, i) => renderFeature(f, i, truncate))}
43
66
  </div>
44
67
  </div>
45
68
  )
@@ -54,16 +77,16 @@ export function HomeFeature(): React.ReactElement | null {
54
77
  * @private
55
78
  * @param feature - Feature item data
56
79
  * @param index - Array index for key generation
57
- * @param gridConfig - Optional grid config for truncation
80
+ * @param truncate - Optional line-clamp limits for card text
58
81
  * @returns Feature card element
59
82
  */
60
83
  function renderFeature(
61
84
  feature: FeatureItem,
62
85
  index: number,
63
- gridConfig: HomeGridConfig | undefined
86
+ truncate: TruncateConfig | undefined
64
87
  ): React.ReactElement {
65
- const titleLines = gridConfig && gridConfig.truncate && gridConfig.truncate.title
66
- const descLines = gridConfig && gridConfig.truncate && gridConfig.truncate.description
88
+ const titleLines = truncate && truncate.title
89
+ const descLines = truncate && truncate.description
67
90
 
68
91
  return (
69
92
  <FeatureCard
@@ -64,3 +64,41 @@
64
64
  .cp-hero-demo__file {
65
65
  color: var(--cp-c-tint-amber-bright-fg);
66
66
  }
67
+
68
+ /* Image-form hero demo — the frame chrome (rounded corners + brand-soft
69
+ glow shadow) stays; the `<img>` simply fills the surface. The hero
70
+ slot already constrains aspect ratio. */
71
+ .cp-hero-demo--image {
72
+ padding: 0;
73
+ }
74
+
75
+ /* Code-form hero demo — the frame owns the chrome, so strip the native
76
+ Rspress code block's own margin and rounded corners. */
77
+ .cp-hero-demo--code .rp-codeblock {
78
+ margin: 0;
79
+ border-radius: 0;
80
+ }
81
+
82
+ .cp-hero-demo--code .rp-codeblock pre {
83
+ overflow-x: auto;
84
+ }
85
+
86
+ .cp-hero-demo__img {
87
+ display: block;
88
+ width: 100%;
89
+ height: auto;
90
+ border-radius: inherit;
91
+ }
92
+
93
+ /* Custom Split visual `<pre>` shares the `.cp-split__code` surface with
94
+ the default `ConfigPreview` block — same padding, font, scrolling. */
95
+ .cp-split__code {
96
+ margin: 0;
97
+ padding: var(--cp-s-20) var(--cp-s-24);
98
+ font-family: var(--cp-font-family-mono);
99
+ font-size: var(--cp-fs-code);
100
+ line-height: var(--cp-lh-code);
101
+ white-space: pre;
102
+ overflow-x: auto;
103
+ color: var(--cp-c-text-1);
104
+ }