@tamagui/next-theme 1.0.1-beta.98 → 1.0.1-rc.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/cjs/NextTheme.js +111 -113
- package/dist/cjs/NextTheme.js.map +3 -3
- package/dist/cjs/index.js +1 -0
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/NextTheme.js +104 -114
- package/dist/esm/NextTheme.js.map +3 -3
- package/dist/esm/index.js +0 -0
- package/dist/esm/index.js.map +1 -1
- package/package.json +5 -5
- package/src/NextTheme.tsx +71 -74
- package/types/NextTheme.d.ts +23 -2
- package/types/index.d.ts +0 -0
- package/dist/jsx/NextTheme.js +0 -219
- package/dist/jsx/index.js +0 -1
- package/types/NextTheme.d.ts.map +0 -1
- package/types/index.d.ts.map +0 -1
package/src/NextTheme.tsx
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
// https://raw.githubusercontent.com/pacocoursey/next-themes/master/index.tsx
|
|
2
2
|
// forked temporarily due to buggy theme change
|
|
3
3
|
|
|
4
|
+
import { useEvent } from '@tamagui/use-event'
|
|
4
5
|
import NextHead from 'next/head'
|
|
5
6
|
import * as React from 'react'
|
|
6
7
|
import {
|
|
7
8
|
createContext,
|
|
8
9
|
memo,
|
|
9
|
-
useCallback,
|
|
10
10
|
useContext,
|
|
11
11
|
useEffect,
|
|
12
12
|
useLayoutEffect,
|
|
@@ -23,9 +23,11 @@ export interface UseThemeProps {
|
|
|
23
23
|
/** Forced theme name for the current page */
|
|
24
24
|
forcedTheme?: string
|
|
25
25
|
/** Update the theme */
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
/** Active theme name */
|
|
26
|
+
set: (theme: string) => void
|
|
27
|
+
toggle: () => void
|
|
28
|
+
/** Active theme name - will return "system" if not overriden, see "resolvedTheme" for getting resolved system value */
|
|
29
|
+
current?: string
|
|
30
|
+
/** @deprecated Use `current` instead (deprecating avoid confusion with useTheme) */
|
|
29
31
|
theme?: string
|
|
30
32
|
/** If `enableSystem` is true and the active theme is "system", this returns whether the system preference resolved to "dark" or "light". Otherwise, identical to `theme` */
|
|
31
33
|
resolvedTheme?: string
|
|
@@ -57,12 +59,18 @@ export interface ThemeProviderProps {
|
|
|
57
59
|
onChangeTheme?: (name: string) => void
|
|
58
60
|
}
|
|
59
61
|
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
62
|
+
const ThemeSettingContext = createContext<UseThemeProps>({
|
|
63
|
+
toggle: () => {},
|
|
64
|
+
set: (_) => {},
|
|
63
65
|
themes: [],
|
|
64
66
|
})
|
|
65
|
-
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* @deprecated renamed to `useThemeSetting` to avoid confusion with core `useTheme` hook
|
|
70
|
+
*/
|
|
71
|
+
export const useTheme = () => useContext(ThemeSettingContext)
|
|
72
|
+
|
|
73
|
+
export const useThemeSetting = () => useContext(ThemeSettingContext)
|
|
66
74
|
|
|
67
75
|
const colorSchemes = ['light', 'dark']
|
|
68
76
|
const MEDIA = '(prefers-color-scheme: dark)'
|
|
@@ -85,7 +93,7 @@ export const NextThemeProvider: React.FC<ThemeProviderProps> = ({
|
|
|
85
93
|
enableSystem = true,
|
|
86
94
|
enableColorScheme = true,
|
|
87
95
|
storageKey = 'theme',
|
|
88
|
-
themes =
|
|
96
|
+
themes = colorSchemes,
|
|
89
97
|
defaultTheme = enableSystem ? 'system' : 'light',
|
|
90
98
|
attribute = 'class',
|
|
91
99
|
onChangeTheme,
|
|
@@ -100,26 +108,21 @@ export const NextThemeProvider: React.FC<ThemeProviderProps> = ({
|
|
|
100
108
|
// const resolvedTheme = React.useDeferredValue(resolvedThemeFast)
|
|
101
109
|
const attrs = !value ? themes : Object.values(value)
|
|
102
110
|
|
|
103
|
-
const handleMediaQuery =
|
|
104
|
-
(e
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
},
|
|
111
|
-
[theme, forcedTheme]
|
|
112
|
-
)
|
|
111
|
+
const handleMediaQuery = useEvent((e?) => {
|
|
112
|
+
const systemTheme = getSystemTheme(e)
|
|
113
|
+
React.startTransition(() => {
|
|
114
|
+
setResolvedTheme(systemTheme)
|
|
115
|
+
})
|
|
116
|
+
if (theme === 'system' && !forcedTheme) handleChangeTheme(systemTheme, false)
|
|
117
|
+
})
|
|
113
118
|
|
|
114
119
|
// Ref hack to avoid adding handleMediaQuery as a dep
|
|
115
120
|
const mediaListener = useRef(handleMediaQuery)
|
|
116
121
|
mediaListener.current = handleMediaQuery
|
|
117
122
|
|
|
118
|
-
const handleChangeTheme =
|
|
123
|
+
const handleChangeTheme = useEvent((theme, updateStorage = true, updateDOM = true) => {
|
|
119
124
|
let name = value?.[theme] || theme
|
|
120
125
|
|
|
121
|
-
const enable = disableTransitionOnChange && updateDOM ? disableAnimation() : null
|
|
122
|
-
|
|
123
126
|
if (updateStorage) {
|
|
124
127
|
try {
|
|
125
128
|
localStorage.setItem(storageKey, theme)
|
|
@@ -137,16 +140,14 @@ export const NextThemeProvider: React.FC<ThemeProviderProps> = ({
|
|
|
137
140
|
|
|
138
141
|
if (updateDOM) {
|
|
139
142
|
const d = document.documentElement
|
|
140
|
-
|
|
141
143
|
if (attribute === 'class') {
|
|
142
144
|
d.classList.remove(...attrs)
|
|
143
145
|
d.classList.add(name)
|
|
144
146
|
} else {
|
|
145
147
|
d.setAttribute(attribute, name)
|
|
146
148
|
}
|
|
147
|
-
enable?.()
|
|
148
149
|
}
|
|
149
|
-
}
|
|
150
|
+
})
|
|
150
151
|
|
|
151
152
|
useIsomorphicLayoutEffect(() => {
|
|
152
153
|
const handler = (...args: any) => mediaListener.current(...args)
|
|
@@ -160,17 +161,14 @@ export const NextThemeProvider: React.FC<ThemeProviderProps> = ({
|
|
|
160
161
|
}
|
|
161
162
|
}, [])
|
|
162
163
|
|
|
163
|
-
const
|
|
164
|
-
(
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
},
|
|
172
|
-
[forcedTheme]
|
|
173
|
-
)
|
|
164
|
+
const set = useEvent((newTheme) => {
|
|
165
|
+
if (forcedTheme) {
|
|
166
|
+
handleChangeTheme(newTheme, true, false)
|
|
167
|
+
} else {
|
|
168
|
+
handleChangeTheme(newTheme)
|
|
169
|
+
}
|
|
170
|
+
setThemeState(newTheme)
|
|
171
|
+
})
|
|
174
172
|
|
|
175
173
|
// localStorage event handling
|
|
176
174
|
useEffect(() => {
|
|
@@ -180,19 +178,19 @@ export const NextThemeProvider: React.FC<ThemeProviderProps> = ({
|
|
|
180
178
|
}
|
|
181
179
|
// If default theme set, use it if localstorage === null (happens on local storage manual deletion)
|
|
182
180
|
const theme = e.newValue || defaultTheme
|
|
183
|
-
|
|
181
|
+
set(theme)
|
|
184
182
|
}
|
|
185
183
|
window.addEventListener('storage', handleStorage)
|
|
186
184
|
return () => {
|
|
187
185
|
window.removeEventListener('storage', handleStorage)
|
|
188
186
|
}
|
|
189
|
-
}, [])
|
|
187
|
+
}, [defaultTheme, set, storageKey])
|
|
190
188
|
|
|
191
189
|
// color-scheme handling
|
|
192
190
|
useIsomorphicLayoutEffect(() => {
|
|
193
191
|
if (!enableColorScheme) return
|
|
194
192
|
|
|
195
|
-
|
|
193
|
+
const colorScheme =
|
|
196
194
|
// If theme is forced to light or dark, use that
|
|
197
195
|
forcedTheme && colorSchemes.includes(forcedTheme)
|
|
198
196
|
? forcedTheme
|
|
@@ -206,28 +204,46 @@ export const NextThemeProvider: React.FC<ThemeProviderProps> = ({
|
|
|
206
204
|
|
|
207
205
|
// color-scheme tells browser how to render built-in elements like forms, scrollbars, etc.
|
|
208
206
|
// if color-scheme is null, this will remove the property
|
|
209
|
-
|
|
207
|
+
const userPrefers =
|
|
208
|
+
typeof window !== 'undefined' &&
|
|
209
|
+
window.matchMedia &&
|
|
210
|
+
window.matchMedia('(prefers-color-scheme: dark)').matches
|
|
211
|
+
? 'dark'
|
|
212
|
+
: 'light'
|
|
213
|
+
|
|
214
|
+
const wePrefer = colorScheme || 'light'
|
|
215
|
+
|
|
216
|
+
// avoid running this because it causes full page reflow
|
|
217
|
+
if (userPrefers !== wePrefer) {
|
|
218
|
+
document.documentElement.style.setProperty('color-scheme', colorScheme)
|
|
219
|
+
}
|
|
210
220
|
}, [enableColorScheme, theme, resolvedTheme, forcedTheme])
|
|
211
221
|
|
|
222
|
+
const toggle = useEvent(() => {
|
|
223
|
+
const order =
|
|
224
|
+
resolvedTheme === 'dark' ? ['system', 'light', 'dark'] : ['system', 'dark', 'light']
|
|
225
|
+
const next = order[(order.indexOf(theme) + 1) % order.length]
|
|
226
|
+
set(next)
|
|
227
|
+
})
|
|
228
|
+
|
|
229
|
+
const contextResolvedTheme = theme === 'system' ? resolvedTheme : theme
|
|
230
|
+
const systemTheme = (enableSystem ? resolvedTheme : undefined) as 'light' | 'dark' | undefined
|
|
212
231
|
const contextValue = useMemo(() => {
|
|
213
|
-
|
|
232
|
+
const value: UseThemeProps = {
|
|
214
233
|
theme,
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
resolvedTheme === 'dark' ? ['system', 'light', 'dark'] : ['system', 'dark', 'light']
|
|
219
|
-
const next = order[(order.indexOf(theme) + 1) % order.length]
|
|
220
|
-
setTheme(next)
|
|
221
|
-
},
|
|
234
|
+
current: theme,
|
|
235
|
+
set,
|
|
236
|
+
toggle,
|
|
222
237
|
forcedTheme,
|
|
223
|
-
resolvedTheme:
|
|
238
|
+
resolvedTheme: contextResolvedTheme,
|
|
224
239
|
themes: enableSystem ? [...themes, 'system'] : themes,
|
|
225
|
-
systemTheme
|
|
240
|
+
systemTheme,
|
|
226
241
|
} as const
|
|
227
|
-
|
|
242
|
+
return value
|
|
243
|
+
}, [theme, set, toggle, forcedTheme, contextResolvedTheme, enableSystem, themes, systemTheme])
|
|
228
244
|
|
|
229
245
|
return (
|
|
230
|
-
<
|
|
246
|
+
<ThemeSettingContext.Provider value={contextValue}>
|
|
231
247
|
<ThemeScript
|
|
232
248
|
{...{
|
|
233
249
|
forcedTheme,
|
|
@@ -240,8 +256,9 @@ export const NextThemeProvider: React.FC<ThemeProviderProps> = ({
|
|
|
240
256
|
attrs,
|
|
241
257
|
}}
|
|
242
258
|
/>
|
|
243
|
-
{
|
|
244
|
-
|
|
259
|
+
{/* because on SSR we re-run and can avoid whole tree re-render */}
|
|
260
|
+
{useMemo(() => children, [children])}
|
|
261
|
+
</ThemeSettingContext.Provider>
|
|
245
262
|
)
|
|
246
263
|
}
|
|
247
264
|
|
|
@@ -337,26 +354,6 @@ const getTheme = (key: string, fallback?: string) => {
|
|
|
337
354
|
return theme || fallback
|
|
338
355
|
}
|
|
339
356
|
|
|
340
|
-
const disableAnimation = () => {
|
|
341
|
-
const css = document.createElement('style')
|
|
342
|
-
css.appendChild(
|
|
343
|
-
document.createTextNode(
|
|
344
|
-
`*{-webkit-transition:none!important;-moz-transition:none!important;-o-transition:none!important;-ms-transition:none!important;transition:none!important}`
|
|
345
|
-
)
|
|
346
|
-
)
|
|
347
|
-
document.head.appendChild(css)
|
|
348
|
-
|
|
349
|
-
return () => {
|
|
350
|
-
// Force restyle
|
|
351
|
-
;(() => window.getComputedStyle(document.body))()
|
|
352
|
-
|
|
353
|
-
// Wait for next tick before removing
|
|
354
|
-
setTimeout(() => {
|
|
355
|
-
document.head.removeChild(css)
|
|
356
|
-
}, 1)
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
|
|
360
357
|
const getSystemTheme = (e?: MediaQueryList) => {
|
|
361
358
|
if (!e) {
|
|
362
359
|
e = window.matchMedia(MEDIA)
|
package/types/NextTheme.d.ts
CHANGED
|
@@ -1,28 +1,49 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
export interface UseThemeProps {
|
|
3
|
+
/** List of all available theme names */
|
|
3
4
|
themes: string[];
|
|
5
|
+
/** Forced theme name for the current page */
|
|
4
6
|
forcedTheme?: string;
|
|
5
|
-
|
|
6
|
-
|
|
7
|
+
/** Update the theme */
|
|
8
|
+
set: (theme: string) => void;
|
|
9
|
+
toggle: () => void;
|
|
10
|
+
/** Active theme name - will return "system" if not overriden, see "resolvedTheme" for getting resolved system value */
|
|
11
|
+
current?: string;
|
|
12
|
+
/** @deprecated Use `current` instead (deprecating avoid confusion with useTheme) */
|
|
7
13
|
theme?: string;
|
|
14
|
+
/** If `enableSystem` is true and the active theme is "system", this returns whether the system preference resolved to "dark" or "light". Otherwise, identical to `theme` */
|
|
8
15
|
resolvedTheme?: string;
|
|
16
|
+
/** If enableSystem is true, returns the System theme preference ("dark" or "light"), regardless what the active theme is */
|
|
9
17
|
systemTheme?: 'dark' | 'light';
|
|
10
18
|
}
|
|
11
19
|
export interface ThemeProviderProps {
|
|
12
20
|
children?: any;
|
|
21
|
+
/** List of all available theme names */
|
|
13
22
|
themes?: string[];
|
|
23
|
+
/** Forced theme name for the current page */
|
|
14
24
|
forcedTheme?: string;
|
|
25
|
+
/** Whether to switch between dark and light themes based on prefers-color-scheme */
|
|
15
26
|
enableSystem?: boolean;
|
|
16
27
|
systemTheme?: string;
|
|
28
|
+
/** Disable all CSS transitions when switching themes */
|
|
17
29
|
disableTransitionOnChange?: boolean;
|
|
30
|
+
/** Whether to indicate to browsers which color scheme is used (dark or light) for built-in UI like inputs and buttons */
|
|
18
31
|
enableColorScheme?: boolean;
|
|
32
|
+
/** Key used to store theme setting in localStorage */
|
|
19
33
|
storageKey?: string;
|
|
34
|
+
/** Default theme name (for v0.0.12 and lower the default was light). If `enableSystem` is false, the default theme is light */
|
|
20
35
|
defaultTheme?: string;
|
|
36
|
+
/** HTML attribute modified based on the active theme. Accepts `class` and `data-*` (meaning any data attribute, `data-mode`, `data-color`, etc.) */
|
|
21
37
|
attribute?: string | 'class';
|
|
38
|
+
/** Mapping of theme name to HTML attribute value. Object where key is the theme name and value is the attribute value */
|
|
22
39
|
value?: ValueObject;
|
|
23
40
|
onChangeTheme?: (name: string) => void;
|
|
24
41
|
}
|
|
42
|
+
/**
|
|
43
|
+
* @deprecated renamed to `useThemeSetting` to avoid confusion with core `useTheme` hook
|
|
44
|
+
*/
|
|
25
45
|
export declare const useTheme: () => UseThemeProps;
|
|
46
|
+
export declare const useThemeSetting: () => UseThemeProps;
|
|
26
47
|
interface ValueObject {
|
|
27
48
|
[themeName: string]: string;
|
|
28
49
|
}
|
package/types/index.d.ts
CHANGED
|
File without changes
|
package/dist/jsx/NextTheme.js
DELETED
|
@@ -1,219 +0,0 @@
|
|
|
1
|
-
import NextHead from "next/head";
|
|
2
|
-
import {
|
|
3
|
-
createContext,
|
|
4
|
-
memo,
|
|
5
|
-
useCallback,
|
|
6
|
-
useContext,
|
|
7
|
-
useEffect,
|
|
8
|
-
useLayoutEffect,
|
|
9
|
-
useMemo,
|
|
10
|
-
useRef,
|
|
11
|
-
useState
|
|
12
|
-
} from "react";
|
|
13
|
-
const useIsomorphicLayoutEffect = typeof window !== "undefined" ? useLayoutEffect : useEffect;
|
|
14
|
-
const ThemeContext = createContext({
|
|
15
|
-
toggleTheme: () => {
|
|
16
|
-
},
|
|
17
|
-
setTheme: (_) => {
|
|
18
|
-
},
|
|
19
|
-
themes: []
|
|
20
|
-
});
|
|
21
|
-
const useTheme = () => useContext(ThemeContext);
|
|
22
|
-
const colorSchemes = ["light", "dark"];
|
|
23
|
-
const MEDIA = "(prefers-color-scheme: dark)";
|
|
24
|
-
const useRootTheme = () => {
|
|
25
|
-
const isClient = typeof document !== "undefined";
|
|
26
|
-
const classes = isClient ? [...document.documentElement.classList] : [];
|
|
27
|
-
const isDark = classes.includes("t_dark");
|
|
28
|
-
return useState(isDark ? "dark" : "light");
|
|
29
|
-
};
|
|
30
|
-
const NextThemeProvider = ({
|
|
31
|
-
forcedTheme,
|
|
32
|
-
disableTransitionOnChange = true,
|
|
33
|
-
enableSystem = true,
|
|
34
|
-
enableColorScheme = true,
|
|
35
|
-
storageKey = "theme",
|
|
36
|
-
themes = ["light", "dark"],
|
|
37
|
-
defaultTheme = enableSystem ? "system" : "light",
|
|
38
|
-
attribute = "class",
|
|
39
|
-
onChangeTheme,
|
|
40
|
-
value = {
|
|
41
|
-
dark: "t_dark",
|
|
42
|
-
light: "t_light"
|
|
43
|
-
},
|
|
44
|
-
children
|
|
45
|
-
}) => {
|
|
46
|
-
const [theme, setThemeState] = useState(() => getTheme(storageKey, defaultTheme));
|
|
47
|
-
const [resolvedTheme, setResolvedTheme] = useState(() => getTheme(storageKey));
|
|
48
|
-
const attrs = !value ? themes : Object.values(value);
|
|
49
|
-
const handleMediaQuery = useCallback((e) => {
|
|
50
|
-
const systemTheme = getSystemTheme(e);
|
|
51
|
-
setResolvedTheme(systemTheme);
|
|
52
|
-
if (theme === "system" && !forcedTheme)
|
|
53
|
-
handleChangeTheme(systemTheme, false);
|
|
54
|
-
}, [theme, forcedTheme]);
|
|
55
|
-
const mediaListener = useRef(handleMediaQuery);
|
|
56
|
-
mediaListener.current = handleMediaQuery;
|
|
57
|
-
const handleChangeTheme = useCallback((theme2, updateStorage = true, updateDOM = true) => {
|
|
58
|
-
let name = (value == null ? void 0 : value[theme2]) || theme2;
|
|
59
|
-
const enable = disableTransitionOnChange && updateDOM ? disableAnimation() : null;
|
|
60
|
-
if (updateStorage) {
|
|
61
|
-
try {
|
|
62
|
-
localStorage.setItem(storageKey, theme2);
|
|
63
|
-
} catch (e) {
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
if (theme2 === "system" && enableSystem) {
|
|
67
|
-
const resolved = getSystemTheme();
|
|
68
|
-
name = (value == null ? void 0 : value[resolved]) || resolved;
|
|
69
|
-
}
|
|
70
|
-
onChangeTheme == null ? void 0 : onChangeTheme(name.replace("t_", ""));
|
|
71
|
-
if (updateDOM) {
|
|
72
|
-
const d = document.documentElement;
|
|
73
|
-
if (attribute === "class") {
|
|
74
|
-
d.classList.remove(...attrs);
|
|
75
|
-
d.classList.add(name);
|
|
76
|
-
} else {
|
|
77
|
-
d.setAttribute(attribute, name);
|
|
78
|
-
}
|
|
79
|
-
enable == null ? void 0 : enable();
|
|
80
|
-
}
|
|
81
|
-
}, []);
|
|
82
|
-
useIsomorphicLayoutEffect(() => {
|
|
83
|
-
const handler = (...args) => mediaListener.current(...args);
|
|
84
|
-
const media = window.matchMedia(MEDIA);
|
|
85
|
-
media.addListener(handler);
|
|
86
|
-
handler(media);
|
|
87
|
-
return () => {
|
|
88
|
-
media.removeListener(handler);
|
|
89
|
-
};
|
|
90
|
-
}, []);
|
|
91
|
-
const setTheme = useCallback((newTheme) => {
|
|
92
|
-
if (forcedTheme) {
|
|
93
|
-
handleChangeTheme(newTheme, true, false);
|
|
94
|
-
} else {
|
|
95
|
-
handleChangeTheme(newTheme);
|
|
96
|
-
}
|
|
97
|
-
setThemeState(newTheme);
|
|
98
|
-
}, [forcedTheme]);
|
|
99
|
-
useEffect(() => {
|
|
100
|
-
const handleStorage = (e) => {
|
|
101
|
-
if (e.key !== storageKey) {
|
|
102
|
-
return;
|
|
103
|
-
}
|
|
104
|
-
const theme2 = e.newValue || defaultTheme;
|
|
105
|
-
setTheme(theme2);
|
|
106
|
-
};
|
|
107
|
-
window.addEventListener("storage", handleStorage);
|
|
108
|
-
return () => {
|
|
109
|
-
window.removeEventListener("storage", handleStorage);
|
|
110
|
-
};
|
|
111
|
-
}, []);
|
|
112
|
-
useIsomorphicLayoutEffect(() => {
|
|
113
|
-
if (!enableColorScheme)
|
|
114
|
-
return;
|
|
115
|
-
let colorScheme = forcedTheme && colorSchemes.includes(forcedTheme) ? forcedTheme : theme && colorSchemes.includes(theme) ? theme : theme === "system" ? resolvedTheme || null : null;
|
|
116
|
-
document.documentElement.style.setProperty("color-scheme", colorScheme);
|
|
117
|
-
}, [enableColorScheme, theme, resolvedTheme, forcedTheme]);
|
|
118
|
-
const contextValue = useMemo(() => {
|
|
119
|
-
return {
|
|
120
|
-
theme,
|
|
121
|
-
setTheme,
|
|
122
|
-
toggleTheme() {
|
|
123
|
-
const order = resolvedTheme === "dark" ? ["system", "light", "dark"] : ["system", "dark", "light"];
|
|
124
|
-
const next = order[(order.indexOf(theme) + 1) % order.length];
|
|
125
|
-
setTheme(next);
|
|
126
|
-
},
|
|
127
|
-
forcedTheme,
|
|
128
|
-
resolvedTheme: theme === "system" ? resolvedTheme : theme,
|
|
129
|
-
themes: enableSystem ? [...themes, "system"] : themes,
|
|
130
|
-
systemTheme: enableSystem ? resolvedTheme : void 0
|
|
131
|
-
};
|
|
132
|
-
}, [theme, forcedTheme, resolvedTheme, enableSystem]);
|
|
133
|
-
return <ThemeContext.Provider value={contextValue}>
|
|
134
|
-
<ThemeScript {...{
|
|
135
|
-
forcedTheme,
|
|
136
|
-
storageKey,
|
|
137
|
-
systemTheme: resolvedTheme,
|
|
138
|
-
attribute,
|
|
139
|
-
value,
|
|
140
|
-
enableSystem,
|
|
141
|
-
defaultTheme,
|
|
142
|
-
attrs
|
|
143
|
-
}} />
|
|
144
|
-
{children}
|
|
145
|
-
</ThemeContext.Provider>;
|
|
146
|
-
};
|
|
147
|
-
const ThemeScript = memo(({
|
|
148
|
-
forcedTheme,
|
|
149
|
-
storageKey,
|
|
150
|
-
attribute,
|
|
151
|
-
enableSystem,
|
|
152
|
-
defaultTheme,
|
|
153
|
-
value,
|
|
154
|
-
attrs
|
|
155
|
-
}) => {
|
|
156
|
-
const optimization = (() => {
|
|
157
|
-
if (attribute === "class") {
|
|
158
|
-
const removeClasses = attrs.map((t) => `d.remove('${t}')`).join(";");
|
|
159
|
-
return `var d=document.documentElement.classList;${removeClasses};`;
|
|
160
|
-
} else {
|
|
161
|
-
return `var d=document.documentElement;`;
|
|
162
|
-
}
|
|
163
|
-
})();
|
|
164
|
-
const updateDOM = (name, literal) => {
|
|
165
|
-
name = (value == null ? void 0 : value[name]) || name;
|
|
166
|
-
const val = literal ? name : `'${name}'`;
|
|
167
|
-
if (attribute === "class") {
|
|
168
|
-
return `d.add(${val})`;
|
|
169
|
-
}
|
|
170
|
-
return `d.setAttribute('${attribute}', ${val})`;
|
|
171
|
-
};
|
|
172
|
-
const defaultSystem = defaultTheme === "system";
|
|
173
|
-
return <NextHead>{forcedTheme ? <script key="next-themes-script" dangerouslySetInnerHTML={{
|
|
174
|
-
__html: `!function(){${optimization}${updateDOM(forcedTheme)}}()`
|
|
175
|
-
}} /> : enableSystem ? <script key="next-themes-script" dangerouslySetInnerHTML={{
|
|
176
|
-
__html: `!function(){try {${optimization}var e=localStorage.getItem('${storageKey}');${!defaultSystem ? updateDOM(defaultTheme) + ";" : ""}if("system"===e||(!e&&${defaultSystem})){var t="${MEDIA}",m=window.matchMedia(t);m.media!==t||m.matches?${updateDOM("dark")}:${updateDOM("light")}}else if(e) ${value ? `var x=${JSON.stringify(value)};` : ""}${updateDOM(value ? "x[e]" : "e", true)}}catch(e){}}()`
|
|
177
|
-
}} /> : <script key="next-themes-script" dangerouslySetInnerHTML={{
|
|
178
|
-
__html: `!function(){try{${optimization}var e=localStorage.getItem("${storageKey}");if(e){${value ? `var x=${JSON.stringify(value)};` : ""}${updateDOM(value ? "x[e]" : "e", true)}}else{${updateDOM(defaultTheme)};}}catch(t){}}();`
|
|
179
|
-
}} />}</NextHead>;
|
|
180
|
-
}, (prevProps, nextProps) => {
|
|
181
|
-
if (prevProps.forcedTheme !== nextProps.forcedTheme)
|
|
182
|
-
return false;
|
|
183
|
-
return true;
|
|
184
|
-
});
|
|
185
|
-
const getTheme = (key, fallback) => {
|
|
186
|
-
if (typeof window === "undefined")
|
|
187
|
-
return void 0;
|
|
188
|
-
let theme;
|
|
189
|
-
try {
|
|
190
|
-
theme = localStorage.getItem(key) || void 0;
|
|
191
|
-
} catch (e) {
|
|
192
|
-
}
|
|
193
|
-
return theme || fallback;
|
|
194
|
-
};
|
|
195
|
-
const disableAnimation = () => {
|
|
196
|
-
const css = document.createElement("style");
|
|
197
|
-
css.appendChild(document.createTextNode(`*{-webkit-transition:none!important;-moz-transition:none!important;-o-transition:none!important;-ms-transition:none!important;transition:none!important}`));
|
|
198
|
-
document.head.appendChild(css);
|
|
199
|
-
return () => {
|
|
200
|
-
;
|
|
201
|
-
(() => window.getComputedStyle(document.body))();
|
|
202
|
-
setTimeout(() => {
|
|
203
|
-
document.head.removeChild(css);
|
|
204
|
-
}, 1);
|
|
205
|
-
};
|
|
206
|
-
};
|
|
207
|
-
const getSystemTheme = (e) => {
|
|
208
|
-
if (!e) {
|
|
209
|
-
e = window.matchMedia(MEDIA);
|
|
210
|
-
}
|
|
211
|
-
const isDark = e.matches;
|
|
212
|
-
const systemTheme = isDark ? "dark" : "light";
|
|
213
|
-
return systemTheme;
|
|
214
|
-
};
|
|
215
|
-
export {
|
|
216
|
-
NextThemeProvider,
|
|
217
|
-
useRootTheme,
|
|
218
|
-
useTheme
|
|
219
|
-
};
|
package/dist/jsx/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "./NextTheme";
|
package/types/NextTheme.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"NextTheme.d.ts","sourceRoot":"","sources":["../src/NextTheme.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAe9B,MAAM,WAAW,aAAa;IAE5B,MAAM,EAAE,MAAM,EAAE,CAAA;IAEhB,WAAW,CAAC,EAAE,MAAM,CAAA;IAEpB,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACjC,WAAW,EAAE,MAAM,IAAI,CAAA;IAEvB,KAAK,CAAC,EAAE,MAAM,CAAA;IAEd,aAAa,CAAC,EAAE,MAAM,CAAA;IAEtB,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;CAC/B;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,EAAE,GAAG,CAAA;IAEd,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;IAEjB,WAAW,CAAC,EAAE,MAAM,CAAA;IAEpB,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,WAAW,CAAC,EAAE,MAAM,CAAA;IAEpB,yBAAyB,CAAC,EAAE,OAAO,CAAA;IAEnC,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAE3B,UAAU,CAAC,EAAE,MAAM,CAAA;IAEnB,YAAY,CAAC,EAAE,MAAM,CAAA;IAErB,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;IAE5B,KAAK,CAAC,EAAE,WAAW,CAAA;IACnB,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;CACvC;AAOD,eAAO,MAAM,QAAQ,qBAAiC,CAAA;AAKtD,UAAU,WAAW;IACnB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAAA;CAC5B;AAED,eAAO,MAAM,YAAY,8DAMxB,CAAA;AAED,eAAO,MAAM,iBAAiB,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAoK1D,CAAA"}
|
package/types/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAA"}
|