@wrksz/themes 0.2.0 → 0.2.1
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/README.md +193 -1
- package/dist/index.d.ts +6 -2
- package/dist/index.js +103 -22
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1 +1,193 @@
|
|
|
1
|
-
|
|
1
|
+
<img src=".github/images/banner.png" alt="@wrksz/themes" width="100%" />
|
|
2
|
+
|
|
3
|
+
# @wrksz/themes
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@wrksz/themes)
|
|
6
|
+
|
|
7
|
+
Modern theme management for Next.js 16+ and React 19+. Drop-in replacement for `next-themes` - fixes every known bug and adds missing features.
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
bun add @wrksz/themes
|
|
11
|
+
# or
|
|
12
|
+
npm install @wrksz/themes
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Setup
|
|
16
|
+
|
|
17
|
+
Add the provider to your root layout. Add `suppressHydrationWarning` to `<html>` to prevent hydration warnings caused by the inline theme script running before React hydrates.
|
|
18
|
+
|
|
19
|
+
```tsx
|
|
20
|
+
// app/layout.tsx
|
|
21
|
+
import { ThemeProvider } from "@wrksz/themes";
|
|
22
|
+
|
|
23
|
+
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
|
24
|
+
return (
|
|
25
|
+
<html lang="en" suppressHydrationWarning>
|
|
26
|
+
<body>
|
|
27
|
+
<ThemeProvider>{children}</ThemeProvider>
|
|
28
|
+
</body>
|
|
29
|
+
</html>
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Usage
|
|
35
|
+
|
|
36
|
+
```tsx
|
|
37
|
+
"use client";
|
|
38
|
+
|
|
39
|
+
import { useTheme } from "@wrksz/themes";
|
|
40
|
+
|
|
41
|
+
export function ThemeToggle() {
|
|
42
|
+
const { theme, setTheme } = useTheme();
|
|
43
|
+
|
|
44
|
+
return (
|
|
45
|
+
<button onClick={() => setTheme(theme === "dark" ? "light" : "dark")}>
|
|
46
|
+
Toggle theme
|
|
47
|
+
</button>
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## API
|
|
53
|
+
|
|
54
|
+
### `ThemeProvider`
|
|
55
|
+
|
|
56
|
+
| Prop | Type | Default | Description |
|
|
57
|
+
|------|------|---------|-------------|
|
|
58
|
+
| `themes` | `string[]` | `["light", "dark"]` | Available themes |
|
|
59
|
+
| `defaultTheme` | `string` | `"system"` | Theme used when no preference is stored |
|
|
60
|
+
| `forcedTheme` | `string` | - | Force a specific theme, ignoring user preference |
|
|
61
|
+
| `enableSystem` | `boolean` | `true` | Detect system preference via `prefers-color-scheme` |
|
|
62
|
+
| `enableColorScheme` | `boolean` | `true` | Set native `color-scheme` CSS property |
|
|
63
|
+
| `attribute` | `string \| string[]` | `"class"` | HTML attribute(s) to set on target element (`"class"`, `"data-theme"`, etc.) |
|
|
64
|
+
| `value` | `Record<string, string>` | - | Map theme names to attribute values |
|
|
65
|
+
| `target` | `string` | `"html"` | Element to apply theme to (`"html"`, `"body"`, or a CSS selector) |
|
|
66
|
+
| `storageKey` | `string` | `"theme"` | Key used for storage |
|
|
67
|
+
| `storage` | `"localStorage" \| "sessionStorage" \| "none"` | `"localStorage"` | Where to persist the theme |
|
|
68
|
+
| `disableTransitionOnChange` | `boolean` | `false` | Disable CSS transitions when switching themes |
|
|
69
|
+
| `themeColor` | `string \| Record<string, string>` | - | Update `<meta name="theme-color">` on theme change |
|
|
70
|
+
| `nonce` | `string` | - | CSP nonce for the inline script |
|
|
71
|
+
| `onThemeChange` | `(theme: string) => void` | - | Called whenever the resolved theme changes |
|
|
72
|
+
|
|
73
|
+
### `useTheme`
|
|
74
|
+
|
|
75
|
+
```tsx
|
|
76
|
+
const {
|
|
77
|
+
theme, // Current theme - may be "system"
|
|
78
|
+
resolvedTheme, // Actual theme - never "system"
|
|
79
|
+
systemTheme, // System preference: "light" | "dark" | undefined
|
|
80
|
+
forcedTheme, // Forced theme if set
|
|
81
|
+
themes, // Available themes
|
|
82
|
+
setTheme, // Set theme
|
|
83
|
+
} = useTheme();
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Supports generics for full type safety:
|
|
87
|
+
|
|
88
|
+
```tsx
|
|
89
|
+
type AppTheme = "light" | "dark" | "high-contrast";
|
|
90
|
+
|
|
91
|
+
const { theme, setTheme } = useTheme<AppTheme>();
|
|
92
|
+
// theme: AppTheme | "system" | undefined
|
|
93
|
+
// setTheme: (theme: AppTheme | "system") => void
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Examples
|
|
97
|
+
|
|
98
|
+
### Custom themes with Tailwind
|
|
99
|
+
|
|
100
|
+
```tsx
|
|
101
|
+
<ThemeProvider
|
|
102
|
+
themes={["light", "dark", "high-contrast"]}
|
|
103
|
+
attribute="class"
|
|
104
|
+
>
|
|
105
|
+
{children}
|
|
106
|
+
</ThemeProvider>
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Data attribute instead of class
|
|
110
|
+
|
|
111
|
+
```tsx
|
|
112
|
+
<ThemeProvider attribute="data-theme">
|
|
113
|
+
{children}
|
|
114
|
+
</ThemeProvider>
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
```css
|
|
118
|
+
[data-theme="dark"] { --bg: #000; }
|
|
119
|
+
[data-theme="light"] { --bg: #fff; }
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Custom attribute values
|
|
123
|
+
|
|
124
|
+
```tsx
|
|
125
|
+
<ThemeProvider
|
|
126
|
+
themes={["light", "dark"]}
|
|
127
|
+
attribute="data-mode"
|
|
128
|
+
value={{ light: "light-mode", dark: "dark-mode" }}
|
|
129
|
+
>
|
|
130
|
+
{children}
|
|
131
|
+
</ThemeProvider>
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Meta theme-color (Safari / PWA)
|
|
135
|
+
|
|
136
|
+
```tsx
|
|
137
|
+
<ThemeProvider
|
|
138
|
+
themeColor={{ light: "#ffffff", dark: "#0a0a0a" }}
|
|
139
|
+
>
|
|
140
|
+
{children}
|
|
141
|
+
</ThemeProvider>
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Works with CSS variables too:
|
|
145
|
+
|
|
146
|
+
```tsx
|
|
147
|
+
<ThemeProvider themeColor="var(--color-background)">
|
|
148
|
+
{children}
|
|
149
|
+
</ThemeProvider>
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### Disable storage
|
|
153
|
+
|
|
154
|
+
```tsx
|
|
155
|
+
// No persistence - always uses defaultTheme or system preference
|
|
156
|
+
<ThemeProvider storage="none" defaultTheme="dark">
|
|
157
|
+
{children}
|
|
158
|
+
</ThemeProvider>
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Forced theme per page
|
|
162
|
+
|
|
163
|
+
```tsx
|
|
164
|
+
// app/dashboard/layout.tsx
|
|
165
|
+
<ThemeProvider forcedTheme="dark">
|
|
166
|
+
{children}
|
|
167
|
+
</ThemeProvider>
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Class on body instead of html
|
|
171
|
+
|
|
172
|
+
```tsx
|
|
173
|
+
<ThemeProvider target="body">
|
|
174
|
+
{children}
|
|
175
|
+
</ThemeProvider>
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## Why not `next-themes`?
|
|
179
|
+
|
|
180
|
+
| Issue | next-themes | @wrksz/themes |
|
|
181
|
+
|-------|-------------|---------------|
|
|
182
|
+
| React 19 script warning | Yes | Fixed (RSC split) |
|
|
183
|
+
| `__name` minification bug | Yes | Fixed |
|
|
184
|
+
| React 19 Activity/cacheComponents stale theme | Yes | Fixed (`useSyncExternalStore`) |
|
|
185
|
+
| `sessionStorage` support | No | Yes |
|
|
186
|
+
| Disable storage | No | Yes (`storage: "none"`) |
|
|
187
|
+
| `meta theme-color` support | No | Yes (`themeColor` prop) |
|
|
188
|
+
| Generic types | No | Yes (`useTheme<AppTheme>()`) |
|
|
189
|
+
| Zero runtime dependencies | Yes | Yes |
|
|
190
|
+
|
|
191
|
+
## License
|
|
192
|
+
|
|
193
|
+
MIT
|
package/dist/index.d.ts
CHANGED
|
@@ -3,6 +3,8 @@ type DefaultTheme = "light" | "dark" | "system";
|
|
|
3
3
|
type Attribute = "class" | `data-${string}`;
|
|
4
4
|
type ValueObject = Record<string, string>;
|
|
5
5
|
type StorageType = "localStorage" | "sessionStorage" | "none";
|
|
6
|
+
/** Per-theme colors for meta theme-color, or a single string for all themes */
|
|
7
|
+
type ThemeColor = string | Partial<Record<string, string>>;
|
|
6
8
|
type ThemeProviderProps<Themes extends string = DefaultTheme> = {
|
|
7
9
|
children: ReactNode;
|
|
8
10
|
/** All available themes */
|
|
@@ -31,6 +33,8 @@ type ThemeProviderProps<Themes extends string = DefaultTheme> = {
|
|
|
31
33
|
nonce?: string;
|
|
32
34
|
/** Called when theme changes */
|
|
33
35
|
onThemeChange?: (theme: Themes) => void;
|
|
36
|
+
/** Colors for meta theme-color tag, per theme or a single value */
|
|
37
|
+
themeColor?: ThemeColor;
|
|
34
38
|
};
|
|
35
39
|
type ThemeContextValue<Themes extends string = DefaultTheme> = {
|
|
36
40
|
/** Current theme (may be "system") */
|
|
@@ -48,5 +52,5 @@ type ThemeContextValue<Themes extends string = DefaultTheme> = {
|
|
|
48
52
|
};
|
|
49
53
|
declare function useTheme<Themes extends string = DefaultTheme>(): ThemeContextValue<Themes>;
|
|
50
54
|
import { ReactElement } from "react";
|
|
51
|
-
declare function ThemeProvider<Themes extends string = DefaultTheme>({ children, themes, forcedTheme, enableSystem, defaultTheme, attribute, value: valueMap, target, disableTransitionOnChange, storage, storageKey, enableColorScheme, nonce, onThemeChange }: ThemeProviderProps<Themes>): ReactElement;
|
|
52
|
-
export { useTheme, ValueObject, ThemeProviderProps, ThemeProvider, ThemeContextValue, StorageType, DefaultTheme, Attribute };
|
|
55
|
+
declare function ThemeProvider<Themes extends string = DefaultTheme>({ children, themes, forcedTheme, enableSystem, defaultTheme, attribute, value: valueMap, target, disableTransitionOnChange, storage, storageKey, enableColorScheme, nonce, onThemeChange, themeColor }: ThemeProviderProps<Themes>): ReactElement;
|
|
56
|
+
export { useTheme, ValueObject, ThemeProviderProps, ThemeProvider, ThemeContextValue, ThemeColor, StorageType, DefaultTheme, Attribute };
|
package/dist/index.js
CHANGED
|
@@ -10,10 +10,63 @@ function useTheme() {
|
|
|
10
10
|
return ctx;
|
|
11
11
|
}
|
|
12
12
|
// src/client-provider.tsx
|
|
13
|
-
import { useCallback, useEffect, useRef,
|
|
13
|
+
import { useCallback, useEffect, useRef, useSyncExternalStore } from "react";
|
|
14
|
+
|
|
15
|
+
// src/store.ts
|
|
16
|
+
var state = { theme: undefined, systemTheme: undefined };
|
|
17
|
+
var listeners = new Set;
|
|
18
|
+
function emit() {
|
|
19
|
+
for (const listener of listeners)
|
|
20
|
+
listener();
|
|
21
|
+
}
|
|
22
|
+
var SERVER_SNAPSHOT = { theme: undefined, systemTheme: undefined };
|
|
23
|
+
var themeStore = {
|
|
24
|
+
subscribe(listener) {
|
|
25
|
+
listeners.add(listener);
|
|
26
|
+
return () => {
|
|
27
|
+
listeners.delete(listener);
|
|
28
|
+
};
|
|
29
|
+
},
|
|
30
|
+
getSnapshot() {
|
|
31
|
+
return state;
|
|
32
|
+
},
|
|
33
|
+
getServerSnapshot() {
|
|
34
|
+
return SERVER_SNAPSHOT;
|
|
35
|
+
},
|
|
36
|
+
setTheme(theme) {
|
|
37
|
+
if (state.theme === theme)
|
|
38
|
+
return;
|
|
39
|
+
state = { ...state, theme };
|
|
40
|
+
emit();
|
|
41
|
+
},
|
|
42
|
+
setSystemTheme(systemTheme) {
|
|
43
|
+
if (state.systemTheme === systemTheme)
|
|
44
|
+
return;
|
|
45
|
+
state = { ...state, systemTheme };
|
|
46
|
+
emit();
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
// src/client-provider.tsx
|
|
14
51
|
import { jsxDEV } from "react/jsx-dev-runtime";
|
|
15
52
|
|
|
16
53
|
var DEFAULT_THEMES = ["light", "dark"];
|
|
54
|
+
function resolveThemeColor(themeColor, resolved) {
|
|
55
|
+
if (typeof themeColor === "string")
|
|
56
|
+
return themeColor;
|
|
57
|
+
return themeColor[resolved];
|
|
58
|
+
}
|
|
59
|
+
function updateMetaThemeColor(color) {
|
|
60
|
+
if (!color)
|
|
61
|
+
return;
|
|
62
|
+
let meta = document.querySelector('meta[name="theme-color"]');
|
|
63
|
+
if (!meta) {
|
|
64
|
+
meta = document.createElement("meta");
|
|
65
|
+
meta.name = "theme-color";
|
|
66
|
+
document.head.appendChild(meta);
|
|
67
|
+
}
|
|
68
|
+
meta.content = color;
|
|
69
|
+
}
|
|
17
70
|
function ClientThemeProvider({
|
|
18
71
|
children,
|
|
19
72
|
themes = DEFAULT_THEMES,
|
|
@@ -27,11 +80,11 @@ function ClientThemeProvider({
|
|
|
27
80
|
storage = "localStorage",
|
|
28
81
|
storageKey = "theme",
|
|
29
82
|
enableColorScheme = true,
|
|
83
|
+
themeColor,
|
|
30
84
|
onThemeChange
|
|
31
85
|
}) {
|
|
32
86
|
const resolvedDefault = defaultTheme ?? (enableSystem ? "system" : "light");
|
|
33
|
-
const
|
|
34
|
-
const [systemTheme, setSystemTheme] = useState(undefined);
|
|
87
|
+
const { theme, systemTheme } = useSyncExternalStore(themeStore.subscribe, themeStore.getSnapshot, themeStore.getServerSnapshot);
|
|
35
88
|
const resolvedTheme = forcedTheme ?? (theme === "system" || theme === undefined ? systemTheme : theme);
|
|
36
89
|
const onThemeChangeRef = useRef(onThemeChange);
|
|
37
90
|
useEffect(() => {
|
|
@@ -68,10 +121,21 @@ function ClientThemeProvider({
|
|
|
68
121
|
if (enableColorScheme && (resolved === "light" || resolved === "dark")) {
|
|
69
122
|
el.style.colorScheme = resolved;
|
|
70
123
|
}
|
|
71
|
-
|
|
124
|
+
if (themeColor) {
|
|
125
|
+
updateMetaThemeColor(resolveThemeColor(themeColor, resolved));
|
|
126
|
+
}
|
|
127
|
+
}, [
|
|
128
|
+
attribute,
|
|
129
|
+
disableTransitionOnChange,
|
|
130
|
+
enableColorScheme,
|
|
131
|
+
getTargetEl,
|
|
132
|
+
themes,
|
|
133
|
+
valueMap,
|
|
134
|
+
themeColor
|
|
135
|
+
]);
|
|
72
136
|
useEffect(() => {
|
|
73
137
|
if (forcedTheme) {
|
|
74
|
-
|
|
138
|
+
themeStore.setTheme(forcedTheme);
|
|
75
139
|
return;
|
|
76
140
|
}
|
|
77
141
|
let stored = null;
|
|
@@ -82,25 +146,25 @@ function ClientThemeProvider({
|
|
|
82
146
|
}
|
|
83
147
|
} catch {}
|
|
84
148
|
const initial = stored && themes.includes(stored) ? stored : resolvedDefault;
|
|
85
|
-
|
|
149
|
+
themeStore.setTheme(initial);
|
|
86
150
|
}, [forcedTheme, resolvedDefault, storage, storageKey, themes]);
|
|
87
151
|
useEffect(() => {
|
|
88
152
|
if (!enableSystem)
|
|
89
153
|
return;
|
|
90
154
|
const mq = window.matchMedia("(prefers-color-scheme: dark)");
|
|
91
|
-
|
|
92
|
-
setSystemTheme(sys);
|
|
155
|
+
themeStore.setSystemTheme(mq.matches ? "dark" : "light");
|
|
93
156
|
const handler = (e) => {
|
|
94
157
|
const next = e.matches ? "dark" : "light";
|
|
95
|
-
setSystemTheme(next);
|
|
96
|
-
|
|
158
|
+
themeStore.setSystemTheme(next);
|
|
159
|
+
const current = themeStore.getSnapshot().theme;
|
|
160
|
+
if (current === "system" || current === undefined) {
|
|
97
161
|
applyToDom(next);
|
|
98
162
|
onThemeChangeRef.current?.(next);
|
|
99
163
|
}
|
|
100
164
|
};
|
|
101
165
|
mq.addEventListener("change", handler);
|
|
102
166
|
return () => mq.removeEventListener("change", handler);
|
|
103
|
-
}, [enableSystem,
|
|
167
|
+
}, [enableSystem, applyToDom]);
|
|
104
168
|
useEffect(() => {
|
|
105
169
|
if (storage === "none")
|
|
106
170
|
return;
|
|
@@ -109,20 +173,21 @@ function ClientThemeProvider({
|
|
|
109
173
|
return;
|
|
110
174
|
if (themes.includes(e.newValue)) {
|
|
111
175
|
const newTheme = e.newValue;
|
|
112
|
-
const resolved = newTheme === "system" ? systemTheme ?? "light" : newTheme;
|
|
113
|
-
|
|
176
|
+
const resolved = newTheme === "system" ? themeStore.getSnapshot().systemTheme ?? "light" : newTheme;
|
|
177
|
+
themeStore.setTheme(newTheme);
|
|
114
178
|
applyToDom(resolved);
|
|
115
179
|
}
|
|
116
180
|
};
|
|
117
181
|
window.addEventListener("storage", handler);
|
|
118
182
|
return () => window.removeEventListener("storage", handler);
|
|
119
|
-
}, [storage, storageKey, themes,
|
|
183
|
+
}, [storage, storageKey, themes, applyToDom]);
|
|
120
184
|
const setTheme = useCallback((next) => {
|
|
121
185
|
if (forcedTheme)
|
|
122
186
|
return;
|
|
123
|
-
const
|
|
124
|
-
const
|
|
125
|
-
|
|
187
|
+
const current = themeStore.getSnapshot().theme;
|
|
188
|
+
const newTheme = typeof next === "function" ? next(current) : next;
|
|
189
|
+
const resolved = newTheme === "system" ? themeStore.getSnapshot().systemTheme ?? "light" : newTheme;
|
|
190
|
+
themeStore.setTheme(newTheme);
|
|
126
191
|
applyToDom(resolved);
|
|
127
192
|
onThemeChangeRef.current?.(resolved);
|
|
128
193
|
try {
|
|
@@ -131,7 +196,7 @@ function ClientThemeProvider({
|
|
|
131
196
|
store.setItem(storageKey, newTheme);
|
|
132
197
|
}
|
|
133
198
|
} catch {}
|
|
134
|
-
}, [applyToDom, forcedTheme, storage, storageKey
|
|
199
|
+
}, [applyToDom, forcedTheme, storage, storageKey]);
|
|
135
200
|
const contextValue = {
|
|
136
201
|
theme: forcedTheme ?? theme,
|
|
137
202
|
resolvedTheme,
|
|
@@ -147,7 +212,7 @@ function ClientThemeProvider({
|
|
|
147
212
|
}
|
|
148
213
|
|
|
149
214
|
// src/script.ts
|
|
150
|
-
function themeScript(storageKey, attribute, defaultTheme, enableSystem, enableColorScheme, forcedTheme, themes, value, target, storage) {
|
|
215
|
+
function themeScript(storageKey, attribute, defaultTheme, enableSystem, enableColorScheme, forcedTheme, themes, value, target, storage, themeColors) {
|
|
151
216
|
let theme;
|
|
152
217
|
if (forcedTheme) {
|
|
153
218
|
theme = forcedTheme;
|
|
@@ -181,6 +246,18 @@ function themeScript(storageKey, attribute, defaultTheme, enableSystem, enableCo
|
|
|
181
246
|
if (enableColorScheme && (theme === "light" || theme === "dark")) {
|
|
182
247
|
el.style.colorScheme = theme;
|
|
183
248
|
}
|
|
249
|
+
if (themeColors) {
|
|
250
|
+
const color = typeof themeColors === "string" ? themeColors : themeColors[theme];
|
|
251
|
+
if (color) {
|
|
252
|
+
let meta = document.querySelector('meta[name="theme-color"]');
|
|
253
|
+
if (!meta) {
|
|
254
|
+
meta = document.createElement("meta");
|
|
255
|
+
meta.setAttribute("name", "theme-color");
|
|
256
|
+
document.head.appendChild(meta);
|
|
257
|
+
}
|
|
258
|
+
meta.setAttribute("content", color);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
184
261
|
}
|
|
185
262
|
function getScript(config) {
|
|
186
263
|
const fn = themeScript.toString().replace(/\s*__name\s*\([^)]*\)\s*;?\s*/g, "");
|
|
@@ -194,7 +271,8 @@ function getScript(config) {
|
|
|
194
271
|
JSON.stringify(config.themes),
|
|
195
272
|
JSON.stringify(config.value ?? null),
|
|
196
273
|
JSON.stringify(config.target),
|
|
197
|
-
JSON.stringify(config.storage)
|
|
274
|
+
JSON.stringify(config.storage),
|
|
275
|
+
JSON.stringify(config.themeColors ?? null)
|
|
198
276
|
].join(",");
|
|
199
277
|
return `(${fn})(${args})`;
|
|
200
278
|
}
|
|
@@ -216,7 +294,8 @@ function ThemeProvider({
|
|
|
216
294
|
storageKey = "theme",
|
|
217
295
|
enableColorScheme = true,
|
|
218
296
|
nonce,
|
|
219
|
-
onThemeChange
|
|
297
|
+
onThemeChange,
|
|
298
|
+
themeColor
|
|
220
299
|
}) {
|
|
221
300
|
const resolvedDefault = defaultTheme ?? (enableSystem ? "system" : "light");
|
|
222
301
|
return /* @__PURE__ */ jsxDEV2(Fragment, {
|
|
@@ -233,7 +312,8 @@ function ThemeProvider({
|
|
|
233
312
|
themes,
|
|
234
313
|
value: valueMap,
|
|
235
314
|
target,
|
|
236
|
-
storage
|
|
315
|
+
storage,
|
|
316
|
+
themeColors: themeColor
|
|
237
317
|
})
|
|
238
318
|
},
|
|
239
319
|
nonce
|
|
@@ -250,6 +330,7 @@ function ThemeProvider({
|
|
|
250
330
|
storage,
|
|
251
331
|
storageKey,
|
|
252
332
|
enableColorScheme,
|
|
333
|
+
themeColor,
|
|
253
334
|
onThemeChange,
|
|
254
335
|
children
|
|
255
336
|
}, undefined, false, undefined, this)
|