@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
@@ -0,0 +1,226 @@
1
+ import type { HomeVisual, HomeVisualLine, HomeVisualTerminal } from '@ciderpress/config'
2
+ import { CodeBlockRuntime } from '@rspress/core/theme'
3
+ import { match, P } from 'massaman/match'
4
+ import type React from 'react'
5
+
6
+ import { withMountBase } from '../../lib/with-mount-base.ts'
7
+
8
+ import './hero-demo.css'
9
+
10
+ /**
11
+ * Surface a {@link HomeVisual} is rendered into.
12
+ *
13
+ * - `'hero'` — supplies its own framed `cp-hero-demo` container
14
+ * - `'split'` — the parent `cp-split__visual` frame owns the chrome
15
+ * - `'tabs'` — the parent `cp-tabs__visual` frame owns the chrome
16
+ */
17
+ export type HomeVisualContext = 'hero' | 'split' | 'tabs'
18
+
19
+ interface HomeVisualViewProps {
20
+ readonly visual: HomeVisual
21
+ readonly context: HomeVisualContext
22
+ }
23
+
24
+ /**
25
+ * Render a user-supplied {@link HomeVisual}. One union, three variants,
26
+ * shared by `home.hero.demo` and `home.blocks[].visual`:
27
+ *
28
+ * - **code** — rendered through Rspress's native `CodeBlockRuntime`, the
29
+ * same Shiki pipeline that highlights markdown code fences, so it
30
+ * themes identically to the rest of the site.
31
+ * - **image** — a screenshot or graphic, base-prefixed via
32
+ * {@link withMountBase} to survive a mounted `base`.
33
+ * - **terminal** — the framework's fake-macOS chrome painted with the
34
+ * supplied command and output lines.
35
+ *
36
+ * Terminates in `.otherwise`, not `.exhaustive`: on a hand-authored home
37
+ * page this receives raw frontmatter, where a blank `visual:` parses to
38
+ * null and `type:` may name a variant that does not exist. Throwing
39
+ * `NonExhaustiveError` from here failed the entire site build, so an
40
+ * unrenderable visual yields nothing instead.
41
+ *
42
+ * @param props - Validated visual config and the surface it renders into
43
+ * @returns The visual's React element, or null when it cannot be rendered
44
+ */
45
+ export function HomeVisualView(props: HomeVisualViewProps): React.ReactElement | null {
46
+ const { visual, context } = props
47
+ return match(visual)
48
+ .with({ type: 'code' }, (v) => renderCode(v.code, v.language, context))
49
+ .with({ type: 'image' }, (v) => renderImage(v, context))
50
+ .with({ type: 'terminal' }, (v) => <VisualTerminal config={v} />)
51
+ .otherwise(() => null)
52
+ }
53
+
54
+ /**
55
+ * Render the code variant, framing it only in the hero context.
56
+ *
57
+ * @private
58
+ * @param code - Snippet source
59
+ * @param language - Shiki language identifier, defaulting to `ts`
60
+ * @param context - Surface being rendered into
61
+ * @returns Highlighted code block
62
+ */
63
+ function renderCode(
64
+ code: string,
65
+ language: string | undefined,
66
+ context: HomeVisualContext
67
+ ): React.ReactElement {
68
+ const block = <CodeBlockRuntime lang={language ?? 'ts'} code={code} />
69
+ return match(context)
70
+ .with('hero', () => <div className="cp-hero-demo cp-hero-demo--code">{block}</div>)
71
+ .otherwise(() => block)
72
+ }
73
+
74
+ /**
75
+ * Image variant fields shared by both surfaces.
76
+ *
77
+ * @private
78
+ */
79
+ interface VisualImageFields {
80
+ readonly src: string
81
+ readonly alt?: string
82
+ readonly width?: number | string
83
+ readonly height?: number | string
84
+ }
85
+
86
+ /**
87
+ * Render the image variant with the class names its surface expects.
88
+ *
89
+ * @private
90
+ * @param image - Validated image visual
91
+ * @param context - Surface being rendered into
92
+ * @returns Image element, framed in the hero context
93
+ */
94
+ function renderImage(image: VisualImageFields, context: HomeVisualContext): React.ReactElement {
95
+ const { src, alt, width, height } = image
96
+ const framedClass = match(context)
97
+ .with('tabs', () => 'cp-tabs__img')
98
+ .otherwise(() => 'cp-split__img')
99
+ return match(context)
100
+ .with(P.union('split', 'tabs'), () => (
101
+ <img
102
+ src={withMountBase(src)}
103
+ alt={alt ?? ''}
104
+ width={width}
105
+ height={height}
106
+ className={framedClass}
107
+ />
108
+ ))
109
+ .with('hero', () => (
110
+ <div className="cp-hero-demo cp-hero-demo--image">
111
+ <img
112
+ src={withMountBase(src)}
113
+ alt={alt ?? ''}
114
+ width={width}
115
+ height={height}
116
+ className="cp-hero-demo__img"
117
+ />
118
+ </div>
119
+ ))
120
+ .exhaustive()
121
+ }
122
+
123
+ interface VisualTerminalProps {
124
+ readonly config: HomeVisualTerminal
125
+ }
126
+
127
+ /**
128
+ * Render the terminal variant with the user-supplied command and lines.
129
+ * In the split context the parent frame flattens the chrome via CSS, so
130
+ * the markup is identical on both surfaces.
131
+ *
132
+ * @private
133
+ * @param props - Validated terminal config
134
+ * @returns Terminal-shell element
135
+ */
136
+ function VisualTerminal(props: VisualTerminalProps): React.ReactElement {
137
+ const { windowTitle, command, lines } = props.config
138
+ // Hand-authored frontmatter bypasses the schema; a non-string here
139
+ // reaches React as a child and throws mid-render.
140
+ const commandText = match(command)
141
+ .with(P.string, (c) => c)
142
+ .otherwise(() => '')
143
+ const title = match(windowTitle)
144
+ .with(P.string, (w) => w)
145
+ .otherwise(() => undefined)
146
+ // `lines` is required by the type but frontmatter is unvalidated on
147
+ // hand-authored home pages — a missing key would otherwise throw here
148
+ // and blank the whole page.
149
+ const output = match(lines)
150
+ .with(
151
+ P.when((l): l is readonly HomeVisualLine[] => Array.isArray(l)),
152
+ (l) => l.filter(isTerminalLine)
153
+ )
154
+ .otherwise(() => [])
155
+ return (
156
+ <div className="cp-hero-demo">
157
+ <div className="cp-hero-demo__bar">
158
+ <span className="cp-hero-demo__dot" />
159
+ <span className="cp-hero-demo__dot" />
160
+ <span className="cp-hero-demo__dot" />
161
+ {match(title)
162
+ .with(P.string, (w) => <span className="cp-hero-demo__title">{w}</span>)
163
+ .otherwise(() => null)}
164
+ </div>
165
+ <pre className="cp-hero-demo__body">
166
+ <span className="cp-hero-demo__prompt">$ </span>
167
+ {commandText}
168
+ {'\n\n'}
169
+ {output.map((line, i) => (
170
+ <TerminalLine key={`${line.kind}-${i}`} line={line} />
171
+ ))}
172
+ </pre>
173
+ </div>
174
+ )
175
+ }
176
+
177
+ /**
178
+ * Whether a frontmatter value is a renderable terminal line. A YAML
179
+ * sequence with a blank entry yields `null`, which would throw on the
180
+ * first property read.
181
+ *
182
+ * @private
183
+ * @param value - Unvalidated line from frontmatter
184
+ * @returns True when the line can be rendered
185
+ */
186
+ function isTerminalLine(value: unknown): value is HomeVisualLine {
187
+ if (typeof value !== 'object' || value === null) {
188
+ return false
189
+ }
190
+ const line = value as { text?: unknown }
191
+ return typeof line.text === 'string'
192
+ }
193
+
194
+ interface TerminalLineProps {
195
+ readonly line: HomeVisualLine
196
+ }
197
+
198
+ /**
199
+ * Render a single terminal output line. Each kind gets a coloured prefix
200
+ * glyph mirroring the framework default.
201
+ *
202
+ * @private
203
+ * @param props - Single line entry
204
+ * @returns Glyph-prefixed line followed by a newline
205
+ */
206
+ function TerminalLine(props: TerminalLineProps): React.ReactElement {
207
+ // `kind` is a union in the type but arrives unvalidated from
208
+ // hand-authored frontmatter — fall back to the neutral marker rather
209
+ // than throwing on an unknown value.
210
+ const className = match(props.line.kind)
211
+ .with('ok', () => 'cp-hero-demo__ok')
212
+ .with('cmt', () => 'cp-hero-demo__cmt')
213
+ .with('err', () => 'cp-hero-demo__err')
214
+ .otherwise(() => 'cp-hero-demo__info')
215
+ const glyph = match(props.line.kind)
216
+ .with('ok', () => ' ✓')
217
+ .with('cmt', () => ' ↻')
218
+ .with('err', () => ' ✗')
219
+ .otherwise(() => ' ▸')
220
+ return (
221
+ <>
222
+ <span className={className}>{glyph}</span> {props.line.text}
223
+ {'\n'}
224
+ </>
225
+ )
226
+ }