-
-
Notifications
You must be signed in to change notification settings - Fork 4
/
theme-switcher.tsx
85 lines (82 loc) · 2.71 KB
/
theme-switcher.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
import { ColorSchemeType } from "../../types";
import { noFOUCScript, type ScriptArgs } from "./no-fouc";
import { initialState } from "../../store";
import { DEFAULT_ID } from "../../constants";
import { Switcher } from "../switcher";
export interface ThemeSwitcherProps {
/**
* Forced theme name for the current page
* @see [Force per page theme and color-scheme](https://github.com/react18-tools/nextjs-themes?tab=readme-ov-file#force-per-page-theme-and-color-scheme)
*/
forcedTheme?: string;
/**
* Forced color scheme for the current page
* @see [Force per page theme and color-scheme](https://github.com/react18-tools/nextjs-themes?tab=readme-ov-file#force-per-page-theme-and-color-scheme)
*/
forcedColorScheme?: ColorSchemeType;
/**
* CSS selector for the target element to apply the theme.
* Use this to specify a different target element than the default (html or documentElement).
* This is particularly useful for controlling the theme of different parts of the page independently.
*/
targetSelector?: string;
/**
* The transition property to enforce on all elements, preventing unwanted transitions during theme changes.
* @example 'background .3s'
* @defaultValue 'none'
*/
themeTransition?: string;
/**
* Provide a styles object imported from CSS/SCSS modules if you are using these modules to define theme and color-scheme classes.
* All classes applied to the target are modified using the styles object as follows:
* `if (styles) classes = classes.map(cls => styles[cls] ?? cls);`
*/
styles?: Record<string, string>;
/** The nonce value for your Content Security Policy. */
nonce?: string;
}
/** Script component to inject script before hydration */
const Script = ({
targetSelector,
nonce,
styles,
forcedTheme,
forcedColorScheme,
}: ThemeSwitcherProps) => {
const args = [
targetSelector || "#" + DEFAULT_ID,
initialState,
styles,
forcedTheme,
forcedColorScheme,
] as ScriptArgs;
// handle client side exceptions when script is not run. <- for client side apps like vite or CRA
typeof window !== "undefined" && noFOUCScript(...args);
return (
<script
// skipcq: JS-0440
dangerouslySetInnerHTML={{
__html: `(${noFOUCScript})(${JSON.stringify(args).slice(1, -1)})`,
}}
nonce={nonce}
/>
);
};
/**
* The Core component wich applies classes and transitions. Use this only once on a layout.
*
* For contained themes you may use Switcher from `nextjs-themes/client/switcher`
*
* @example
* ```tsx
* <ThemeSwitcher [...props] />
* ```
*/
export const ThemeSwitcher = (props: ThemeSwitcherProps) => {
return (
<>
<Script {...props} />
<Switcher {...props} />
</>
);
};