@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.
- package/dist/head/css/loader-apple.css +1 -1
- package/dist/head/css/loader-dots.css +1 -1
- package/dist/head/css/themes/amber.css +1 -1
- package/dist/head/css/themes/arcade.css +1 -1
- package/dist/head/css/themes/grannysmith.css +1 -1
- package/dist/head/css/themes/honeycrisp.css +1 -1
- package/dist/head/css/themes/midnight.css +1 -1
- package/dist/head/css/themes/mulled.css +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.mjs +4 -3
- package/dist/node.d.ts +1 -1
- package/dist/node.mjs +732 -55
- package/dist/plugins/mermaid/MermaidRenderer.tsx +49 -6
- package/dist/theme/components/footer/site-footer.tsx +68 -9
- package/dist/theme/components/home/cta.css +15 -0
- package/dist/theme/components/home/cta.tsx +10 -2
- package/dist/theme/components/home/feature-card.css +1 -1
- package/dist/theme/components/home/feature-card.tsx +8 -10
- package/dist/theme/components/home/feature.tsx +54 -31
- package/dist/theme/components/home/hero-demo.css +38 -0
- package/dist/theme/components/home/home-visual.tsx +226 -0
- package/dist/theme/components/home/layout.tsx +410 -108
- package/dist/theme/components/home/split.css +46 -19
- package/dist/theme/components/home/split.tsx +28 -8
- package/dist/theme/components/home/tabs.css +299 -0
- package/dist/theme/components/home/tabs.tsx +351 -0
- package/dist/theme/components/home/trust-strip.css +41 -0
- package/dist/theme/components/home/trust-strip.tsx +168 -11
- package/dist/theme/components/home/workspaces.tsx +176 -38
- package/dist/theme/components/nav/branch-tag.tsx +7 -7
- package/dist/theme/components/nav/ciderpress-docs-bar.css +13 -1
- package/dist/theme/components/nav/ciderpress-docs-bar.tsx +33 -2
- package/dist/theme/components/nav/ciderpress-header.css +2 -1
- package/dist/theme/components/nav/ciderpress-header.tsx +26 -3
- package/dist/theme/components/nav/ciderpress-nav-hamburger.css +50 -0
- package/dist/theme/components/nav/ciderpress-nav-hamburger.tsx +95 -9
- package/dist/theme/components/nav/ciderpress-nav-menu.css +88 -0
- package/dist/theme/components/nav/ciderpress-nav-menu.tsx +397 -38
- package/dist/theme/components/nav/ciderpress-nav-social-links.tsx +27 -22
- package/dist/theme/components/nav/floating-branch-indicator.tsx +7 -7
- package/dist/theme/components/nav/header-icon.css +24 -0
- package/dist/theme/components/nav/header-icon.tsx +119 -0
- package/dist/theme/components/nav/header-logo.css +16 -0
- package/dist/theme/components/nav/header-logo.tsx +200 -0
- package/dist/theme/components/nav/layout.tsx +117 -16
- package/dist/theme/components/nav/nav-logo.tsx +16 -19
- package/dist/theme/components/openapi/index.ts +0 -2
- package/dist/theme/components/openapi/openapi.css +0 -14
- package/dist/theme/components/shared/card-icon.tsx +37 -0
- package/dist/theme/components/shared/ciderpress-logo.tsx +5 -1
- package/dist/theme/components/shared/icon.tsx +120 -35
- package/dist/theme/components/shared/resolve-card-icon.ts +53 -12
- package/dist/theme/components/shared/section-card.tsx +37 -6
- package/dist/theme/components/sidebar/sidebar-badge.css +50 -0
- package/dist/theme/components/sidebar/sidebar-badge.tsx +153 -0
- package/dist/theme/components/sidebar/sidebar-links.tsx +6 -2
- package/dist/theme/components/sidebar/sidebar-scope.tsx +24 -1
- package/dist/theme/components/theme-provider.tsx +27 -11
- package/dist/theme/components/workspaces/card.css +4 -0
- package/dist/theme/components/workspaces/card.tsx +10 -12
- package/dist/theme/components/workspaces/grid.tsx +18 -6
- package/dist/theme/hooks/use-ciderpress.ts +65 -5
- package/dist/theme/hooks/use-nav-items.ts +82 -11
- package/dist/theme/index.tsx +10 -3
- package/dist/theme/lib/read-social-links.ts +4 -3
- package/dist/theme/lib/rich-text-parse.ts +740 -0
- package/dist/theme/lib/rich-text.test.tsx +342 -0
- package/dist/theme/lib/rich-text.tsx +86 -0
- package/dist/theme/lib/theme-favicon.ts +1 -1
- package/dist/theme/lib/with-mount-base.ts +31 -0
- package/dist/theme/styles/overrides/fonts.css +7 -4
- package/dist/theme/styles/overrides/footnotes.css +54 -0
- package/dist/theme/styles/overrides/home.css +11 -2
- package/dist/theme/styles/overrides/lists.css +83 -0
- package/dist/theme/styles/overrides/rail.css +27 -10
- package/dist/theme/styles/overrides/rspress.css +10 -5
- package/dist/theme/styles/overrides/section-card.css +9 -0
- package/dist/theme/styles/overrides/sidebar.css +22 -0
- package/dist/theme/styles/overrides/tokens.css +41 -23
- package/dist/theme/styles/rich-text.css +106 -0
- package/dist/theme/styles/themes/amber.css +32 -2
- package/dist/theme/styles/themes/arcade.css +16 -1
- package/dist/theme/styles/themes/grannysmith.css +32 -2
- package/dist/theme/styles/themes/honeycrisp.css +37 -7
- package/dist/theme/styles/themes/midnight.css +16 -1
- package/dist/theme/styles/themes/mulled.css +54 -9
- package/package.json +18 -16
- package/src/theme/components/footer/site-footer.tsx +68 -9
- package/src/theme/components/home/cta.css +15 -0
- package/src/theme/components/home/cta.tsx +10 -2
- package/src/theme/components/home/feature-card.css +1 -1
- package/src/theme/components/home/feature-card.tsx +8 -10
- package/src/theme/components/home/feature.tsx +54 -31
- package/src/theme/components/home/hero-demo.css +38 -0
- package/src/theme/components/home/home-visual.tsx +226 -0
- package/src/theme/components/home/layout.tsx +410 -108
- package/src/theme/components/home/split.css +46 -19
- package/src/theme/components/home/split.tsx +28 -8
- package/src/theme/components/home/tabs.css +299 -0
- package/src/theme/components/home/tabs.tsx +351 -0
- package/src/theme/components/home/trust-strip.css +41 -0
- package/src/theme/components/home/trust-strip.tsx +168 -11
- package/src/theme/components/home/workspaces.tsx +176 -38
- package/src/theme/components/nav/branch-tag.tsx +7 -7
- package/src/theme/components/nav/ciderpress-docs-bar.css +13 -1
- package/src/theme/components/nav/ciderpress-docs-bar.tsx +33 -2
- package/src/theme/components/nav/ciderpress-header.css +2 -1
- package/src/theme/components/nav/ciderpress-header.tsx +26 -3
- package/src/theme/components/nav/ciderpress-nav-hamburger.css +50 -0
- package/src/theme/components/nav/ciderpress-nav-hamburger.tsx +95 -9
- package/src/theme/components/nav/ciderpress-nav-menu.css +88 -0
- package/src/theme/components/nav/ciderpress-nav-menu.tsx +397 -38
- package/src/theme/components/nav/ciderpress-nav-social-links.tsx +27 -22
- package/src/theme/components/nav/floating-branch-indicator.tsx +7 -7
- package/src/theme/components/nav/header-icon.css +24 -0
- package/src/theme/components/nav/header-icon.tsx +119 -0
- package/src/theme/components/nav/header-logo.css +16 -0
- package/src/theme/components/nav/header-logo.tsx +200 -0
- package/src/theme/components/nav/layout.tsx +117 -16
- package/src/theme/components/nav/nav-logo.tsx +16 -19
- package/src/theme/components/openapi/index.ts +0 -2
- package/src/theme/components/openapi/openapi.css +0 -14
- package/src/theme/components/shared/card-icon.tsx +37 -0
- package/src/theme/components/shared/ciderpress-logo.tsx +5 -1
- package/src/theme/components/shared/icon.tsx +120 -35
- package/src/theme/components/shared/resolve-card-icon.ts +53 -12
- package/src/theme/components/shared/section-card.tsx +37 -6
- package/src/theme/components/sidebar/sidebar-badge.css +50 -0
- package/src/theme/components/sidebar/sidebar-badge.tsx +153 -0
- package/src/theme/components/sidebar/sidebar-links.tsx +6 -2
- package/src/theme/components/sidebar/sidebar-scope.tsx +24 -1
- package/src/theme/components/theme-provider.tsx +27 -11
- package/src/theme/components/workspaces/card.css +4 -0
- package/src/theme/components/workspaces/card.tsx +10 -12
- package/src/theme/components/workspaces/grid.tsx +18 -6
- package/src/theme/hooks/use-ciderpress.ts +65 -5
- package/src/theme/hooks/use-nav-items.ts +82 -11
- package/src/theme/index.tsx +10 -3
- package/src/theme/lib/read-social-links.ts +4 -3
- package/src/theme/lib/rich-text-parse.ts +740 -0
- package/src/theme/lib/rich-text.test.tsx +342 -0
- package/src/theme/lib/rich-text.tsx +86 -0
- package/src/theme/lib/theme-favicon.ts +1 -1
- package/src/theme/lib/with-mount-base.ts +31 -0
- package/src/theme/styles/overrides/fonts.css +7 -4
- package/src/theme/styles/overrides/footnotes.css +54 -0
- package/src/theme/styles/overrides/home.css +11 -2
- package/src/theme/styles/overrides/lists.css +83 -0
- package/src/theme/styles/overrides/rail.css +27 -10
- package/src/theme/styles/overrides/rspress.css +10 -5
- package/src/theme/styles/overrides/section-card.css +9 -0
- package/src/theme/styles/overrides/sidebar.css +22 -0
- package/src/theme/styles/overrides/tokens.css +41 -23
- package/src/theme/styles/rich-text.css +106 -0
- package/src/theme/styles/themes/amber.css +32 -2
- package/src/theme/styles/themes/arcade.css +16 -1
- package/src/theme/styles/themes/grannysmith.css +32 -2
- package/src/theme/styles/themes/honeycrisp.css +37 -7
- package/src/theme/styles/themes/midnight.css +16 -1
- package/src/theme/styles/themes/mulled.css +54 -9
- package/dist/theme/components/openapi/copy-markdown-button.tsx +0 -41
- 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
|
+
}
|