@zpress/ui 0.5.1 → 0.6.0
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/theme/components/nav/theme-switcher.tsx +18 -3
- package/dist/theme/components/theme-provider.tsx +23 -5
- package/dist/theme/styles/overrides/rspress.css +6 -0
- package/package.json +5 -4
- package/src/theme/components/nav/theme-switcher.tsx +18 -3
- package/src/theme/components/theme-provider.tsx +23 -5
- package/src/theme/styles/overrides/rspress.css +6 -0
|
@@ -11,12 +11,25 @@ interface ThemeOption {
|
|
|
11
11
|
readonly label: string
|
|
12
12
|
readonly swatch: string
|
|
13
13
|
readonly defaultColorMode: 'dark' | 'light' | 'toggle'
|
|
14
|
+
readonly modes: readonly ('dark' | 'light')[]
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
const THEME_OPTIONS: readonly ThemeOption[] = [
|
|
17
|
-
{
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
{
|
|
19
|
+
name: 'base',
|
|
20
|
+
label: 'Base',
|
|
21
|
+
swatch: '#a78bfa',
|
|
22
|
+
defaultColorMode: 'toggle',
|
|
23
|
+
modes: ['dark', 'light'],
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
name: 'midnight',
|
|
27
|
+
label: 'Midnight',
|
|
28
|
+
swatch: '#60a5fa',
|
|
29
|
+
defaultColorMode: 'dark',
|
|
30
|
+
modes: ['dark'],
|
|
31
|
+
},
|
|
32
|
+
{ name: 'arcade', label: 'Arcade', swatch: '#00ff88', defaultColorMode: 'dark', modes: ['dark'] },
|
|
20
33
|
]
|
|
21
34
|
|
|
22
35
|
const VALID_THEME_NAMES = new Set(THEME_OPTIONS.map((t) => t.name))
|
|
@@ -52,6 +65,8 @@ function applyTheme(theme: ThemeOption): void {
|
|
|
52
65
|
html.dataset.zpTheme = theme.name
|
|
53
66
|
localStorage.setItem('zpress-theme', theme.name)
|
|
54
67
|
|
|
68
|
+
html.dataset.zpModes = theme.modes.join(' ')
|
|
69
|
+
|
|
55
70
|
if (theme.defaultColorMode === 'dark') {
|
|
56
71
|
// 'rp-dark' is Rspress's dark mode class; 'dark' is added for Tailwind compatibility
|
|
57
72
|
html.classList.add('rp-dark', 'dark')
|
|
@@ -6,6 +6,16 @@ declare const __ZPRESS_COLOR_MODE__: string
|
|
|
6
6
|
declare const __ZPRESS_THEME_COLORS__: string
|
|
7
7
|
declare const __ZPRESS_THEME_DARK_COLORS__: string
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Supported color modes per built-in theme — used to set `data-zp-modes`
|
|
11
|
+
* so the appearance toggle is hidden for single-mode themes.
|
|
12
|
+
*/
|
|
13
|
+
const THEME_MODES: Readonly<Record<string, string>> = {
|
|
14
|
+
base: 'dark light',
|
|
15
|
+
midnight: 'dark',
|
|
16
|
+
arcade: 'dark',
|
|
17
|
+
}
|
|
18
|
+
|
|
9
19
|
const COLOR_VAR_MAP: Record<string, readonly string[]> = {
|
|
10
20
|
brand: ['--zp-c-brand-1', '--rp-c-brand'],
|
|
11
21
|
brandLight: ['--rp-c-brand-light'],
|
|
@@ -167,7 +177,15 @@ export function ThemeProvider(): React.ReactElement | null {
|
|
|
167
177
|
// 1. Set theme attribute
|
|
168
178
|
html.dataset.zpTheme = themeName
|
|
169
179
|
|
|
170
|
-
// 2.
|
|
180
|
+
// 2. Set supported modes — hides the appearance toggle for single-mode themes
|
|
181
|
+
const modes = THEME_MODES[themeName]
|
|
182
|
+
if (modes) {
|
|
183
|
+
html.dataset.zpModes = modes
|
|
184
|
+
} else {
|
|
185
|
+
html.dataset.zpModes = 'dark light'
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// 3. Force color mode if not toggle
|
|
171
189
|
if (colorMode === 'dark') {
|
|
172
190
|
html.classList.add('rp-dark', 'dark')
|
|
173
191
|
html.dataset.dark = 'true'
|
|
@@ -186,12 +204,12 @@ export function ThemeProvider(): React.ReactElement | null {
|
|
|
186
204
|
}
|
|
187
205
|
}
|
|
188
206
|
|
|
189
|
-
//
|
|
207
|
+
// 4. Apply base color overrides
|
|
190
208
|
if (hasColors) {
|
|
191
209
|
applyColorOverrides(html, colors)
|
|
192
210
|
}
|
|
193
211
|
|
|
194
|
-
//
|
|
212
|
+
// 5. Observe dark mode changes for dark-specific overrides
|
|
195
213
|
if (hasDarkColors) {
|
|
196
214
|
const isDark = html.classList.contains('rp-dark')
|
|
197
215
|
if (isDark) {
|
|
@@ -214,7 +232,7 @@ export function ThemeProvider(): React.ReactElement | null {
|
|
|
214
232
|
|
|
215
233
|
observer.observe(html, { attributes: true, attributeFilter: ['class'] })
|
|
216
234
|
|
|
217
|
-
//
|
|
235
|
+
// 6. Dismiss loading overlay
|
|
218
236
|
const cancelLoader = dismissLoader(html)
|
|
219
237
|
|
|
220
238
|
return () => {
|
|
@@ -223,7 +241,7 @@ export function ThemeProvider(): React.ReactElement | null {
|
|
|
223
241
|
}
|
|
224
242
|
}
|
|
225
243
|
|
|
226
|
-
//
|
|
244
|
+
// 6. Dismiss loading overlay (no dark-color observer needed)
|
|
227
245
|
return dismissLoader(html)
|
|
228
246
|
}, [])
|
|
229
247
|
|
|
@@ -32,6 +32,12 @@ html .rp-button--big {
|
|
|
32
32
|
border-radius: 9999px;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
+
/* ── Single-mode themes — hide the appearance toggle when only one mode is supported ── */
|
|
36
|
+
html[data-zp-modes='dark'] .rp-appearance,
|
|
37
|
+
html[data-zp-modes='light'] .rp-appearance {
|
|
38
|
+
display: none;
|
|
39
|
+
}
|
|
40
|
+
|
|
35
41
|
/* ── Tables ──────────────────────────────────────────────── */
|
|
36
42
|
html table {
|
|
37
43
|
border-radius: var(--rp-radius);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zpress/ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Rspress plugin, theme components, and styles for zpress",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -52,9 +52,9 @@
|
|
|
52
52
|
"@iconify-json/vscode-icons": "^1.2.45",
|
|
53
53
|
"@iconify/react": "^6.0.2",
|
|
54
54
|
"ts-pattern": "^5.9.0",
|
|
55
|
-
"@zpress/config": "0.2.
|
|
56
|
-
"@zpress/core": "0.6.
|
|
57
|
-
"@zpress/theme": "0.
|
|
55
|
+
"@zpress/config": "0.2.2",
|
|
56
|
+
"@zpress/core": "0.6.2",
|
|
57
|
+
"@zpress/theme": "0.3.0"
|
|
58
58
|
},
|
|
59
59
|
"devDependencies": {
|
|
60
60
|
"@rslib/core": "^0.20.0",
|
|
@@ -79,6 +79,7 @@
|
|
|
79
79
|
"build": "rslib build",
|
|
80
80
|
"postbuild": "node scripts/minify-head.mjs",
|
|
81
81
|
"dev": "rslib build --watch --no-clean",
|
|
82
|
+
"test": "vitest run",
|
|
82
83
|
"typecheck": "tsc --noEmit"
|
|
83
84
|
}
|
|
84
85
|
}
|
|
@@ -11,12 +11,25 @@ interface ThemeOption {
|
|
|
11
11
|
readonly label: string
|
|
12
12
|
readonly swatch: string
|
|
13
13
|
readonly defaultColorMode: 'dark' | 'light' | 'toggle'
|
|
14
|
+
readonly modes: readonly ('dark' | 'light')[]
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
const THEME_OPTIONS: readonly ThemeOption[] = [
|
|
17
|
-
{
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
{
|
|
19
|
+
name: 'base',
|
|
20
|
+
label: 'Base',
|
|
21
|
+
swatch: '#a78bfa',
|
|
22
|
+
defaultColorMode: 'toggle',
|
|
23
|
+
modes: ['dark', 'light'],
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
name: 'midnight',
|
|
27
|
+
label: 'Midnight',
|
|
28
|
+
swatch: '#60a5fa',
|
|
29
|
+
defaultColorMode: 'dark',
|
|
30
|
+
modes: ['dark'],
|
|
31
|
+
},
|
|
32
|
+
{ name: 'arcade', label: 'Arcade', swatch: '#00ff88', defaultColorMode: 'dark', modes: ['dark'] },
|
|
20
33
|
]
|
|
21
34
|
|
|
22
35
|
const VALID_THEME_NAMES = new Set(THEME_OPTIONS.map((t) => t.name))
|
|
@@ -52,6 +65,8 @@ function applyTheme(theme: ThemeOption): void {
|
|
|
52
65
|
html.dataset.zpTheme = theme.name
|
|
53
66
|
localStorage.setItem('zpress-theme', theme.name)
|
|
54
67
|
|
|
68
|
+
html.dataset.zpModes = theme.modes.join(' ')
|
|
69
|
+
|
|
55
70
|
if (theme.defaultColorMode === 'dark') {
|
|
56
71
|
// 'rp-dark' is Rspress's dark mode class; 'dark' is added for Tailwind compatibility
|
|
57
72
|
html.classList.add('rp-dark', 'dark')
|
|
@@ -6,6 +6,16 @@ declare const __ZPRESS_COLOR_MODE__: string
|
|
|
6
6
|
declare const __ZPRESS_THEME_COLORS__: string
|
|
7
7
|
declare const __ZPRESS_THEME_DARK_COLORS__: string
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Supported color modes per built-in theme — used to set `data-zp-modes`
|
|
11
|
+
* so the appearance toggle is hidden for single-mode themes.
|
|
12
|
+
*/
|
|
13
|
+
const THEME_MODES: Readonly<Record<string, string>> = {
|
|
14
|
+
base: 'dark light',
|
|
15
|
+
midnight: 'dark',
|
|
16
|
+
arcade: 'dark',
|
|
17
|
+
}
|
|
18
|
+
|
|
9
19
|
const COLOR_VAR_MAP: Record<string, readonly string[]> = {
|
|
10
20
|
brand: ['--zp-c-brand-1', '--rp-c-brand'],
|
|
11
21
|
brandLight: ['--rp-c-brand-light'],
|
|
@@ -167,7 +177,15 @@ export function ThemeProvider(): React.ReactElement | null {
|
|
|
167
177
|
// 1. Set theme attribute
|
|
168
178
|
html.dataset.zpTheme = themeName
|
|
169
179
|
|
|
170
|
-
// 2.
|
|
180
|
+
// 2. Set supported modes — hides the appearance toggle for single-mode themes
|
|
181
|
+
const modes = THEME_MODES[themeName]
|
|
182
|
+
if (modes) {
|
|
183
|
+
html.dataset.zpModes = modes
|
|
184
|
+
} else {
|
|
185
|
+
html.dataset.zpModes = 'dark light'
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// 3. Force color mode if not toggle
|
|
171
189
|
if (colorMode === 'dark') {
|
|
172
190
|
html.classList.add('rp-dark', 'dark')
|
|
173
191
|
html.dataset.dark = 'true'
|
|
@@ -186,12 +204,12 @@ export function ThemeProvider(): React.ReactElement | null {
|
|
|
186
204
|
}
|
|
187
205
|
}
|
|
188
206
|
|
|
189
|
-
//
|
|
207
|
+
// 4. Apply base color overrides
|
|
190
208
|
if (hasColors) {
|
|
191
209
|
applyColorOverrides(html, colors)
|
|
192
210
|
}
|
|
193
211
|
|
|
194
|
-
//
|
|
212
|
+
// 5. Observe dark mode changes for dark-specific overrides
|
|
195
213
|
if (hasDarkColors) {
|
|
196
214
|
const isDark = html.classList.contains('rp-dark')
|
|
197
215
|
if (isDark) {
|
|
@@ -214,7 +232,7 @@ export function ThemeProvider(): React.ReactElement | null {
|
|
|
214
232
|
|
|
215
233
|
observer.observe(html, { attributes: true, attributeFilter: ['class'] })
|
|
216
234
|
|
|
217
|
-
//
|
|
235
|
+
// 6. Dismiss loading overlay
|
|
218
236
|
const cancelLoader = dismissLoader(html)
|
|
219
237
|
|
|
220
238
|
return () => {
|
|
@@ -223,7 +241,7 @@ export function ThemeProvider(): React.ReactElement | null {
|
|
|
223
241
|
}
|
|
224
242
|
}
|
|
225
243
|
|
|
226
|
-
//
|
|
244
|
+
// 6. Dismiss loading overlay (no dark-color observer needed)
|
|
227
245
|
return dismissLoader(html)
|
|
228
246
|
}, [])
|
|
229
247
|
|
|
@@ -32,6 +32,12 @@ html .rp-button--big {
|
|
|
32
32
|
border-radius: 9999px;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
+
/* ── Single-mode themes — hide the appearance toggle when only one mode is supported ── */
|
|
36
|
+
html[data-zp-modes='dark'] .rp-appearance,
|
|
37
|
+
html[data-zp-modes='light'] .rp-appearance {
|
|
38
|
+
display: none;
|
|
39
|
+
}
|
|
40
|
+
|
|
35
41
|
/* ── Tables ──────────────────────────────────────────────── */
|
|
36
42
|
html table {
|
|
37
43
|
border-radius: var(--rp-radius);
|