@ciderpress/ui 1.0.0-rc.12 → 1.0.0-rc.14
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/themes/honeycrisp.css +1 -1
- package/dist/node.mjs +17 -13
- package/dist/plugins/mermaid/MermaidRenderer.tsx +2 -2
- package/dist/theme/components/home/hero-banner.tsx +225 -0
- package/dist/theme/components/home/hero-demo.css +492 -61
- package/dist/theme/components/home/hero-demo.test.tsx +159 -0
- package/dist/theme/components/home/hero-demo.tsx +335 -32
- package/dist/theme/components/home/hero.css +142 -9
- package/dist/theme/components/home/hero.test.tsx +105 -0
- package/dist/theme/components/home/hero.tsx +201 -4
- package/dist/theme/components/home/home-visual.css +98 -0
- package/dist/theme/components/home/home-visual.test.tsx +27 -0
- package/dist/theme/components/home/home-visual.tsx +20 -13
- package/dist/theme/components/home/layout.tsx +125 -1
- package/dist/theme/components/home/split.css +2 -2
- package/dist/theme/components/home/tabs.css +1 -1
- package/dist/theme/components/home/trust-strip.css +12 -0
- package/dist/theme/components/home/trust-strip.test.tsx +33 -0
- package/dist/theme/components/home/trust-strip.tsx +76 -15
- package/dist/theme/components/nav/layout.tsx +10 -14
- package/dist/theme/components/nav/nav-logo.tsx +2 -3
- package/dist/theme/components/sidebar/sidebar-filter.test.ts +49 -9
- package/dist/theme/components/sidebar/sidebar-filter.ts +24 -4
- package/dist/theme/index.tsx +8 -1
- package/dist/theme/lib/rich-text-parse.ts +0 -2
- package/dist/theme/lib/theme-favicon.ts +0 -3
- package/dist/theme/styles/themes/honeycrisp.css +20 -20
- package/package.json +20 -19
- package/src/theme/components/home/hero-banner.tsx +225 -0
- package/src/theme/components/home/hero-demo.css +492 -61
- package/src/theme/components/home/hero-demo.test.tsx +159 -0
- package/src/theme/components/home/hero-demo.tsx +335 -32
- package/src/theme/components/home/hero.css +142 -9
- package/src/theme/components/home/hero.test.tsx +105 -0
- package/src/theme/components/home/hero.tsx +201 -4
- package/src/theme/components/home/home-visual.css +98 -0
- package/src/theme/components/home/home-visual.test.tsx +27 -0
- package/src/theme/components/home/home-visual.tsx +20 -13
- package/src/theme/components/home/layout.tsx +125 -1
- package/src/theme/components/home/split.css +2 -2
- package/src/theme/components/home/tabs.css +1 -1
- package/src/theme/components/home/trust-strip.css +12 -0
- package/src/theme/components/home/trust-strip.test.tsx +33 -0
- package/src/theme/components/home/trust-strip.tsx +76 -15
- package/src/theme/components/nav/layout.tsx +10 -14
- package/src/theme/components/nav/nav-logo.tsx +2 -3
- package/src/theme/components/sidebar/sidebar-filter.test.ts +49 -9
- package/src/theme/components/sidebar/sidebar-filter.ts +24 -4
- package/src/theme/index.tsx +8 -1
- package/src/theme/lib/rich-text-parse.ts +0 -2
- package/src/theme/lib/theme-favicon.ts +0 -3
- package/src/theme/styles/themes/honeycrisp.css +20 -20
|
@@ -23,9 +23,7 @@ export function syncThemeFavicon(html: HTMLElement): void {
|
|
|
23
23
|
const surface = resolveSurfaceColor(html)
|
|
24
24
|
const dataUri = buildIconDataUri(brand, shadow, surface)
|
|
25
25
|
const link = ensureFaviconLink()
|
|
26
|
-
// oxlint-disable-next-line functional/immutable-data -- boundary mutation: updating link element href
|
|
27
26
|
link.type = 'image/svg+xml'
|
|
28
|
-
// oxlint-disable-next-line functional/immutable-data -- boundary mutation: updating link element href
|
|
29
27
|
link.href = dataUri
|
|
30
28
|
}
|
|
31
29
|
|
|
@@ -118,7 +116,6 @@ function ensureFaviconLink(): HTMLLinkElement {
|
|
|
118
116
|
return existing
|
|
119
117
|
}
|
|
120
118
|
const link = globalThis.document.createElement('link')
|
|
121
|
-
// oxlint-disable-next-line functional/immutable-data -- boundary mutation: initialising newly created link element
|
|
122
119
|
link.rel = 'icon'
|
|
123
120
|
globalThis.document.head.append(link)
|
|
124
121
|
return link
|
|
@@ -288,7 +288,7 @@ html[data-cp-theme='honeycrisp'][data-cp-variant='dark'] {
|
|
|
288
288
|
}
|
|
289
289
|
|
|
290
290
|
html[data-cp-theme='honeycrisp'][data-cp-variant='light'] {
|
|
291
|
-
--cp-c-brand-1: #
|
|
291
|
+
--cp-c-brand-1: #d02020;
|
|
292
292
|
--cp-c-brand-2: #b91c1c;
|
|
293
293
|
--cp-c-brand-3: #7f1d1d;
|
|
294
294
|
--cp-c-brand-fg: #ffffff;
|
|
@@ -301,15 +301,15 @@ html[data-cp-theme='honeycrisp'][data-cp-variant='light'] {
|
|
|
301
301
|
--cp-c-warn: #d97706;
|
|
302
302
|
--cp-c-info: #2563eb;
|
|
303
303
|
--cp-c-muted: #888888;
|
|
304
|
-
--cp-c-bg: #
|
|
305
|
-
--cp-c-bg-alt: #
|
|
306
|
-
--cp-c-bg-elv: #
|
|
307
|
-
--cp-c-bg-soft: #
|
|
308
|
-
--cp-c-bg-icon: #
|
|
309
|
-
--cp-c-home-bg: #
|
|
304
|
+
--cp-c-bg: #f7f5f0;
|
|
305
|
+
--cp-c-bg-alt: #f1eee7;
|
|
306
|
+
--cp-c-bg-elv: #fffdf8;
|
|
307
|
+
--cp-c-bg-soft: #ebe7dc;
|
|
308
|
+
--cp-c-bg-icon: #d5cebe;
|
|
309
|
+
--cp-c-home-bg: #f7f5f0;
|
|
310
310
|
--cp-c-overlay-faint: rgba(0, 0, 0, 0.1);
|
|
311
|
-
--cp-c-gutter: #
|
|
312
|
-
--cp-code-block-bg: #
|
|
311
|
+
--cp-c-gutter: #f1eee7;
|
|
312
|
+
--cp-code-block-bg: #f1eee7;
|
|
313
313
|
--cp-c-text-1: #1a1a1a;
|
|
314
314
|
--cp-c-text-2: rgba(26, 26, 26, 0.72);
|
|
315
315
|
--cp-c-text-3: rgba(26, 26, 26, 0.48);
|
|
@@ -384,7 +384,7 @@ html[data-cp-theme='honeycrisp'][data-cp-variant='light'] {
|
|
|
384
384
|
--cp-oas-deprecated: var(--cp-c-text-3);
|
|
385
385
|
--cp-oas-required: #dc2626;
|
|
386
386
|
--cp-button-brand-bg: #b91c1c;
|
|
387
|
-
--cp-button-brand-hover-bg: #
|
|
387
|
+
--cp-button-brand-hover-bg: #d02020;
|
|
388
388
|
--cp-button-brand-active-bg: #7f1d1d;
|
|
389
389
|
--cp-button-brand-text: #ffffff;
|
|
390
390
|
--cp-s-1: 1px;
|
|
@@ -535,12 +535,12 @@ html[data-cp-theme='honeycrisp'][data-cp-variant='light'] {
|
|
|
535
535
|
--cp-blur-base: 8px;
|
|
536
536
|
--cp-gradient-brand: linear-gradient(135deg, var(--cp-c-brand-1), var(--cp-c-brand-3));
|
|
537
537
|
--cp-gradient-hero-title: linear-gradient(135deg, var(--cp-c-brand-1), var(--cp-c-brand-light));
|
|
538
|
-
--rp-c-bg: #
|
|
539
|
-
--rp-c-bg-alt: #
|
|
540
|
-
--rp-c-bg-dark: #
|
|
541
|
-
--rp-c-bg-mute: #
|
|
542
|
-
--rp-c-bg-soft: #
|
|
543
|
-
--rp-c-brand: #
|
|
538
|
+
--rp-c-bg: #f7f5f0;
|
|
539
|
+
--rp-c-bg-alt: #f1eee7;
|
|
540
|
+
--rp-c-bg-dark: #f1eee7;
|
|
541
|
+
--rp-c-bg-mute: #f7f5f0;
|
|
542
|
+
--rp-c-bg-soft: #ebe7dc;
|
|
543
|
+
--rp-c-brand: #d02020;
|
|
544
544
|
--rp-c-brand-light: #ef4444;
|
|
545
545
|
--rp-c-brand-lighter: #fca5a5;
|
|
546
546
|
--rp-c-brand-dark: #b91c1c;
|
|
@@ -549,15 +549,15 @@ html[data-cp-theme='honeycrisp'][data-cp-variant='light'] {
|
|
|
549
549
|
--rp-c-divider: #e2e2e2;
|
|
550
550
|
--rp-c-divider-dark: #d0d0d0;
|
|
551
551
|
--rp-c-divider-light: #e2e2e2;
|
|
552
|
-
--rp-c-link: #
|
|
552
|
+
--rp-c-link: #d02020;
|
|
553
553
|
--rp-c-text-1: #1a1a1a;
|
|
554
554
|
--rp-c-text-2: rgba(26, 26, 26, 0.72);
|
|
555
555
|
--rp-c-text-3: rgba(26, 26, 26, 0.48);
|
|
556
556
|
--rp-c-text-4: rgba(26, 26, 26, 0.48);
|
|
557
557
|
--rp-c-text-code: #1a1a1a;
|
|
558
|
-
--rp-code-block-bg: #
|
|
559
|
-
--rp-home-background-bg: #
|
|
560
|
-
--rp-home-feature-bg: #
|
|
558
|
+
--rp-code-block-bg: #f1eee7;
|
|
559
|
+
--rp-home-background-bg: #f7f5f0;
|
|
560
|
+
--rp-home-feature-bg: #ebe7dc;
|
|
561
561
|
--rp-home-hero-secondary-color: rgba(26, 26, 26, 0.72);
|
|
562
562
|
--rp-home-hero-title-color: #1a1a1a;
|
|
563
563
|
--rp-font-family-base:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ciderpress/ui",
|
|
3
|
-
"version": "1.0.0-rc.
|
|
3
|
+
"version": "1.0.0-rc.14",
|
|
4
4
|
"description": "Rspress plugin, theme components, and styles for ciderpress",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ciderpress",
|
|
@@ -47,43 +47,44 @@
|
|
|
47
47
|
"dependencies": {
|
|
48
48
|
"@iconify-json/catppuccin": "^1.2.17",
|
|
49
49
|
"@iconify-json/devicon": "^1.2.62",
|
|
50
|
-
"@iconify-json/logos": "^1.2.
|
|
51
|
-
"@iconify-json/material-icon-theme": "^1.2.
|
|
50
|
+
"@iconify-json/logos": "^1.2.13",
|
|
51
|
+
"@iconify-json/material-icon-theme": "^1.2.70",
|
|
52
52
|
"@iconify-json/mdi": "^1.2.3",
|
|
53
53
|
"@iconify-json/pixel": "^1.2.2",
|
|
54
|
-
"@iconify-json/pixelarticons": "^1.2.
|
|
55
|
-
"@iconify-json/simple-icons": "^1.2.
|
|
54
|
+
"@iconify-json/pixelarticons": "^1.2.8",
|
|
55
|
+
"@iconify-json/simple-icons": "^1.2.93",
|
|
56
56
|
"@iconify-json/skill-icons": "^1.2.4",
|
|
57
|
-
"@iconify-json/vscode-icons": "^1.2.
|
|
57
|
+
"@iconify-json/vscode-icons": "^1.2.73",
|
|
58
58
|
"@iconify/react": "^6.0.2",
|
|
59
59
|
"@mermaid-js/layout-elk": "^0.2.2",
|
|
60
60
|
"@rspress/plugin-sitemap": "^2.0.19",
|
|
61
61
|
"clsx": "^2.1.1",
|
|
62
|
-
"katex": "^0.
|
|
63
|
-
"massaman": "^0.
|
|
64
|
-
"mermaid": "^11.16.
|
|
62
|
+
"katex": "^0.18.4",
|
|
63
|
+
"massaman": "^0.5.0",
|
|
64
|
+
"mermaid": "^11.16.1",
|
|
65
65
|
"openapi-sampler": "^1.7.4",
|
|
66
|
-
"react-aria-components": "^1.
|
|
66
|
+
"react-aria-components": "^1.20.0",
|
|
67
67
|
"ts-morph": "^28.0.0",
|
|
68
68
|
"unist-util-visit": "^5.1.0",
|
|
69
|
-
"@ciderpress/config": "1.0.0-rc.
|
|
70
|
-
"@ciderpress/theme": "1.0.0-rc.
|
|
69
|
+
"@ciderpress/config": "1.0.0-rc.11",
|
|
70
|
+
"@ciderpress/theme": "1.0.0-rc.6"
|
|
71
71
|
},
|
|
72
72
|
"devDependencies": {
|
|
73
73
|
"@ladle/react": "^5.1.1",
|
|
74
|
-
"@rslib/core": "0.23.
|
|
74
|
+
"@rslib/core": "^0.23.2",
|
|
75
75
|
"@rspress/core": "^2.0.19",
|
|
76
|
-
"@types/react": "^19.2.
|
|
77
|
-
"@types/react-dom": "^19.2.
|
|
78
|
-
"esbuild": "^0.28.
|
|
76
|
+
"@types/react": "^19.2.18",
|
|
77
|
+
"@types/react-dom": "^19.2.4",
|
|
78
|
+
"esbuild": "^0.28.2",
|
|
79
79
|
"geist": "^1.7.2",
|
|
80
|
-
"
|
|
81
|
-
"react
|
|
80
|
+
"happy-dom": "^20.12.0",
|
|
81
|
+
"react": "^19.2.8",
|
|
82
|
+
"react-dom": "^19.2.8",
|
|
82
83
|
"rspress-plugin-devkit": "^1.0.0",
|
|
83
84
|
"rspress-plugin-file-tree": "^1.0.5",
|
|
84
85
|
"rspress-plugin-katex": "^1.0.1",
|
|
85
86
|
"rspress-plugin-supersub": "^1.0.0",
|
|
86
|
-
"typescript": "^
|
|
87
|
+
"typescript": "^7.0.2",
|
|
87
88
|
"vitest": "^4.1.10"
|
|
88
89
|
},
|
|
89
90
|
"peerDependencies": {
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import type { BannerFn, CiderpressConfig, ImageSource, LogoContext } from '@ciderpress/config'
|
|
2
|
+
// oxlint-disable-next-line import/no-unresolved -- alias provided by createRspressConfig's resolve.alias
|
|
3
|
+
import userConfigModule from '@ciderpress/internal/user-config'
|
|
4
|
+
import { BRAND_COLORS, DEFAULT_THEME_NAME } from '@ciderpress/theme'
|
|
5
|
+
import React, { useEffect, useState } from 'react'
|
|
6
|
+
|
|
7
|
+
import { withMountBase } from '../../lib/with-mount-base.ts'
|
|
8
|
+
|
|
9
|
+
const COLOR_VARS = Object.freeze({
|
|
10
|
+
brand: '--rp-c-brand',
|
|
11
|
+
brandHover: '--rp-c-brand-dark',
|
|
12
|
+
brandSoft: '--rp-c-brand-tint',
|
|
13
|
+
bg: '--rp-c-bg',
|
|
14
|
+
text: '--rp-c-text-1',
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
const DEFAULT_BRAND = BRAND_COLORS[DEFAULT_THEME_NAME]
|
|
18
|
+
const FALLBACK_COLORS = Object.freeze({
|
|
19
|
+
brand: DEFAULT_BRAND.primary,
|
|
20
|
+
brandHover: DEFAULT_BRAND.hover,
|
|
21
|
+
brandSoft: DEFAULT_BRAND.soft,
|
|
22
|
+
bg: '#ffffff',
|
|
23
|
+
text: '#1f2937',
|
|
24
|
+
})
|
|
25
|
+
const FALLBACK_THEME: LogoContext = Object.freeze({
|
|
26
|
+
name: DEFAULT_THEME_NAME,
|
|
27
|
+
variant: 'dark',
|
|
28
|
+
isDark: true,
|
|
29
|
+
colors: FALLBACK_COLORS,
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Resolve and render a function-valued `brand.banner` with the live theme context.
|
|
34
|
+
*
|
|
35
|
+
* @returns Theme-aware banner content, an image, or null.
|
|
36
|
+
*/
|
|
37
|
+
export function HeroBanner(): React.ReactElement | null {
|
|
38
|
+
const banner = readBannerConfig(userConfigModule)
|
|
39
|
+
const theme = useThemeContext(typeof banner === 'function')
|
|
40
|
+
|
|
41
|
+
if (typeof banner !== 'function') {
|
|
42
|
+
return null
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return <>{renderBanner({ banner, theme })}</>
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
interface RenderBannerParams {
|
|
49
|
+
readonly banner: BannerFn
|
|
50
|
+
readonly theme: LogoContext
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Invoke a banner function and normalize image returns into elements.
|
|
55
|
+
*
|
|
56
|
+
* @private
|
|
57
|
+
* @param params - Banner function and active theme context.
|
|
58
|
+
* @returns Renderable banner content.
|
|
59
|
+
*/
|
|
60
|
+
function renderBanner(params: RenderBannerParams): React.ReactNode {
|
|
61
|
+
const result = params.banner({ theme: params.theme })
|
|
62
|
+
if (typeof result === 'string') {
|
|
63
|
+
return <img src={withMountBase(result)} alt="" />
|
|
64
|
+
}
|
|
65
|
+
if (isImageSource(result)) {
|
|
66
|
+
return (
|
|
67
|
+
<img
|
|
68
|
+
src={withMountBase(result.src)}
|
|
69
|
+
alt={result.alt ?? ''}
|
|
70
|
+
width={result.width}
|
|
71
|
+
height={result.height}
|
|
72
|
+
/>
|
|
73
|
+
)
|
|
74
|
+
}
|
|
75
|
+
return result as React.ReactNode
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Read a function-valued banner from the bundled user config.
|
|
80
|
+
*
|
|
81
|
+
* @private
|
|
82
|
+
* @param mod - User config module or its default export.
|
|
83
|
+
* @returns Banner function when configured.
|
|
84
|
+
*/
|
|
85
|
+
function readBannerConfig(mod: unknown): BannerFn | undefined {
|
|
86
|
+
if (mod === null || mod === undefined) {
|
|
87
|
+
return undefined
|
|
88
|
+
}
|
|
89
|
+
const record = mod as Record<string, unknown>
|
|
90
|
+
const candidate = readConfigExport({ mod, record })
|
|
91
|
+
const brand = candidate.brand
|
|
92
|
+
if (brand === undefined || typeof brand.banner !== 'function') {
|
|
93
|
+
return undefined
|
|
94
|
+
}
|
|
95
|
+
return brand.banner
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
interface ReadConfigExportParams {
|
|
99
|
+
readonly mod: unknown
|
|
100
|
+
readonly record: Record<string, unknown>
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Normalize default and direct user-config module exports.
|
|
105
|
+
*
|
|
106
|
+
* @private
|
|
107
|
+
* @param params - Raw module and record view.
|
|
108
|
+
* @returns Partial Ciderpress config.
|
|
109
|
+
*/
|
|
110
|
+
function readConfigExport(params: ReadConfigExportParams): Partial<CiderpressConfig> {
|
|
111
|
+
if (params.record.default !== null && params.record.default !== undefined) {
|
|
112
|
+
return params.record.default as Partial<CiderpressConfig>
|
|
113
|
+
}
|
|
114
|
+
return params.mod as Partial<CiderpressConfig>
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Subscribe to theme changes only when a runtime banner needs them.
|
|
119
|
+
*
|
|
120
|
+
* @private
|
|
121
|
+
* @param enabled - Whether the banner is function-valued.
|
|
122
|
+
* @returns Server-safe default context followed by the live browser context.
|
|
123
|
+
*/
|
|
124
|
+
function useThemeContext(enabled: boolean): LogoContext {
|
|
125
|
+
const [theme, setTheme] = useState<LogoContext>(FALLBACK_THEME)
|
|
126
|
+
|
|
127
|
+
useEffect(() => {
|
|
128
|
+
if (!enabled) {
|
|
129
|
+
return
|
|
130
|
+
}
|
|
131
|
+
const html = globalThis.document.documentElement
|
|
132
|
+
function update(): void {
|
|
133
|
+
return setTheme(readThemeContext(html))
|
|
134
|
+
}
|
|
135
|
+
update()
|
|
136
|
+
|
|
137
|
+
const observer = new MutationObserver(update)
|
|
138
|
+
observer.observe(html, {
|
|
139
|
+
attributes: true,
|
|
140
|
+
attributeFilter: ['data-cp-theme', 'data-cp-variant', 'class', 'style'],
|
|
141
|
+
})
|
|
142
|
+
return () => observer.disconnect()
|
|
143
|
+
}, [enabled])
|
|
144
|
+
|
|
145
|
+
return theme
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Distinguish a structured image source from a React element.
|
|
150
|
+
*
|
|
151
|
+
* @private
|
|
152
|
+
* @param value - Banner return value.
|
|
153
|
+
* @returns Whether the value is an image source object.
|
|
154
|
+
*/
|
|
155
|
+
function isImageSource(value: unknown): value is Exclude<ImageSource, string> {
|
|
156
|
+
if (value === null || typeof value !== 'object') {
|
|
157
|
+
return false
|
|
158
|
+
}
|
|
159
|
+
const record = value as Record<string, unknown>
|
|
160
|
+
if ('$$typeof' in record) {
|
|
161
|
+
return false
|
|
162
|
+
}
|
|
163
|
+
return typeof record.src === 'string'
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Build the live theme context passed to `brand.banner`.
|
|
168
|
+
*
|
|
169
|
+
* @private
|
|
170
|
+
* @param html - Document root element.
|
|
171
|
+
* @returns Current theme snapshot.
|
|
172
|
+
*/
|
|
173
|
+
function readThemeContext(html: HTMLElement): LogoContext {
|
|
174
|
+
const variant = readVariant(html)
|
|
175
|
+
const name = readThemeName(html)
|
|
176
|
+
const styles = globalThis.window.getComputedStyle(html)
|
|
177
|
+
function read(cssVar: string, fallback: string): string {
|
|
178
|
+
const raw = styles.getPropertyValue(cssVar).trim()
|
|
179
|
+
if (raw.length === 0) {
|
|
180
|
+
return fallback
|
|
181
|
+
}
|
|
182
|
+
return raw
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
return {
|
|
186
|
+
name,
|
|
187
|
+
variant,
|
|
188
|
+
isDark: variant === 'dark',
|
|
189
|
+
colors: {
|
|
190
|
+
brand: read(COLOR_VARS.brand, FALLBACK_COLORS.brand),
|
|
191
|
+
brandHover: read(COLOR_VARS.brandHover, FALLBACK_COLORS.brandHover),
|
|
192
|
+
brandSoft: read(COLOR_VARS.brandSoft, FALLBACK_COLORS.brandSoft),
|
|
193
|
+
bg: read(COLOR_VARS.bg, FALLBACK_COLORS.bg),
|
|
194
|
+
text: read(COLOR_VARS.text, FALLBACK_COLORS.text),
|
|
195
|
+
},
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Read the active color variant from the document root.
|
|
201
|
+
*
|
|
202
|
+
* @private
|
|
203
|
+
* @param html - Document root element.
|
|
204
|
+
* @returns Active variant.
|
|
205
|
+
*/
|
|
206
|
+
function readVariant(html: HTMLElement): 'light' | 'dark' {
|
|
207
|
+
if (html.dataset.cpVariant === 'light') {
|
|
208
|
+
return 'light'
|
|
209
|
+
}
|
|
210
|
+
return 'dark'
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Read the active theme name from the document root.
|
|
215
|
+
*
|
|
216
|
+
* @private
|
|
217
|
+
* @param html - Document root element.
|
|
218
|
+
* @returns Active theme name.
|
|
219
|
+
*/
|
|
220
|
+
function readThemeName(html: HTMLElement): string {
|
|
221
|
+
if (typeof html.dataset.cpTheme === 'string') {
|
|
222
|
+
return html.dataset.cpTheme
|
|
223
|
+
}
|
|
224
|
+
return DEFAULT_THEME_NAME
|
|
225
|
+
}
|