@tamagui/next-theme 1.0.16 → 1.0.18

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.
@@ -25,7 +25,6 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
25
25
  var NextTheme_exports = {};
26
26
  __export(NextTheme_exports, {
27
27
  NextThemeProvider: () => NextThemeProvider,
28
- Theme: () => Theme,
29
28
  useRootTheme: () => useRootTheme,
30
29
  useTheme: () => useTheme,
31
30
  useThemeSetting: () => useThemeSetting
@@ -33,12 +32,19 @@ __export(NextTheme_exports, {
33
32
  module.exports = __toCommonJS(NextTheme_exports);
34
33
  var import_jsx_runtime = require("react/jsx-runtime");
35
34
  var import_use_event = require("@tamagui/use-event");
35
+ var import_head = __toESM(require("next/head"));
36
36
  var React = __toESM(require("react"));
37
37
  var import_react = require("react");
38
38
  const useIsomorphicLayoutEffect = typeof window !== "undefined" ? import_react.useLayoutEffect : import_react.useEffect;
39
- const ThemeContext = (0, import_react.createContext)(null);
40
- const useTheme = () => (0, import_react.useContext)(ThemeContext);
41
- const useThemeSetting = () => (0, import_react.useContext)(ThemeContext);
39
+ const ThemeSettingContext = (0, import_react.createContext)({
40
+ toggle: () => {
41
+ },
42
+ set: (_) => {
43
+ },
44
+ themes: []
45
+ });
46
+ const useTheme = () => (0, import_react.useContext)(ThemeSettingContext);
47
+ const useThemeSetting = () => (0, import_react.useContext)(ThemeSettingContext);
42
48
  const colorSchemes = ["light", "dark"];
43
49
  const MEDIA = "(prefers-color-scheme: dark)";
44
50
  const useRootTheme = () => {
@@ -54,19 +60,7 @@ const useRootTheme = () => {
54
60
  }
55
61
  return [val, setVal];
56
62
  };
57
- const NextThemeProvider = (props) => {
58
- const context = (0, import_react.useContext)(ThemeContext);
59
- if (context) {
60
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, {
61
- children: props.children
62
- });
63
- }
64
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Theme, {
65
- ...props
66
- });
67
- };
68
- const Theme = ({
69
- nonce,
63
+ const NextThemeProvider = ({
70
64
  forcedTheme,
71
65
  disableTransitionOnChange = true,
72
66
  enableSystem = true,
@@ -75,6 +69,7 @@ const Theme = ({
75
69
  themes = colorSchemes,
76
70
  defaultTheme = enableSystem ? "system" : "light",
77
71
  attribute = "class",
72
+ skipNextHead,
78
73
  onChangeTheme,
79
74
  value = {
80
75
  dark: "t_dark",
@@ -188,23 +183,20 @@ const Theme = ({
188
183
  themes,
189
184
  systemTheme
190
185
  ]);
191
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(ThemeContext.Provider, {
186
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(ThemeSettingContext.Provider, {
192
187
  value: contextValue,
193
188
  children: [
194
189
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ThemeScript, {
195
190
  ...{
196
191
  forcedTheme,
197
- disableTransitionOnChange,
198
192
  storageKey,
199
193
  systemTheme: resolvedTheme,
200
194
  attribute,
201
- enableColorScheme,
202
195
  value,
203
- themes,
204
196
  enableSystem,
205
197
  defaultTheme,
206
198
  attrs,
207
- nonce
199
+ skipNextHead
208
200
  }
209
201
  }),
210
202
  (0, import_react.useMemo)(() => children, [children])
@@ -217,73 +209,58 @@ const ThemeScript = (0, import_react.memo)(
217
209
  storageKey,
218
210
  attribute,
219
211
  enableSystem,
220
- enableColorScheme,
221
212
  defaultTheme,
222
213
  value,
223
214
  attrs,
224
- nonce
215
+ skipNextHead
225
216
  }) => {
226
- const defaultSystem = defaultTheme === "system";
227
217
  const optimization = (() => {
228
218
  if (attribute === "class") {
229
- const removeClasses = `c.remove(${attrs.map((t) => `'${t}'`).join(",")})`;
230
- return `var d=document.documentElement,c=d.classList;${removeClasses};`;
231
- } else {
232
- return `var d=document.documentElement,n='${attribute}',s='setAttribute';`;
233
- }
234
- })();
235
- const fallbackColorScheme = (() => {
236
- if (!enableColorScheme) {
237
- return "";
238
- }
239
- const fallback = colorSchemes.includes(defaultTheme) ? defaultTheme : null;
240
- if (fallback) {
241
- return `if(e==='light'||e==='dark'||!e)d.style.colorScheme=e||'${defaultTheme}'`;
219
+ const removeClasses = attrs.map((t) => `d.remove('${t}')`).join(";");
220
+ return `var d=document.documentElement.classList;${removeClasses};`;
242
221
  } else {
243
- return `if(e==='light'||e==='dark')d.style.colorScheme=e`;
222
+ return `var d=document.documentElement;`;
244
223
  }
245
224
  })();
246
- const updateDOM = (name, literal = false, setColorScheme = true) => {
247
- const resolvedName = value ? value[name] : name;
248
- const val = literal ? name + `|| ''` : `'${resolvedName}'`;
249
- let text = "";
250
- if (enableColorScheme && setColorScheme && !literal && colorSchemes.includes(name)) {
251
- text += `d.style.colorScheme = '${name}';`;
252
- }
225
+ const updateDOM = (name, literal) => {
226
+ name = (value == null ? void 0 : value[name]) || name;
227
+ const val = literal ? name : `'${name}'`;
253
228
  if (attribute === "class") {
254
- if (literal || resolvedName) {
255
- text += `c.add(${val})`;
256
- } else {
257
- text += `null`;
258
- }
259
- } else {
260
- if (resolvedName) {
261
- text += `d[s](n,${val})`;
262
- }
229
+ return `d.add(${val})`;
263
230
  }
264
- return text;
231
+ return `d.setAttribute('${attribute}', ${val})`;
265
232
  };
266
- const scriptSrc = (() => {
267
- if (forcedTheme) {
268
- return `!function(){${optimization}${updateDOM(forcedTheme)}}()`;
269
- }
270
- if (enableSystem) {
271
- return `!function(){try{${optimization}var e=localStorage.getItem('${storageKey}');if('system'===e||(!e&&${defaultSystem})){var t='${MEDIA}',m=window.matchMedia(t);if(m.media!==t||m.matches){${updateDOM(
272
- "dark"
273
- )}}else{${updateDOM("light")}}}else if(e){${value ? `var x=${JSON.stringify(value)};` : ""}${updateDOM(value ? `x[e]` : "e", true)}}${!defaultSystem ? `else{` + updateDOM(defaultTheme, false, false) + "}" : ""}${fallbackColorScheme}}catch(e){}}()`;
274
- }
275
- return `!function(){try{${optimization}var e=localStorage.getItem('${storageKey}');if(e){${value ? `var x=${JSON.stringify(value)};` : ""}${updateDOM(value ? `x[e]` : "e", true)}}else{${updateDOM(
276
- defaultTheme,
277
- false,
278
- false
279
- )};}${fallbackColorScheme}}catch(t){}}();`;
280
- })();
281
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("script", {
282
- nonce,
283
- dangerouslySetInnerHTML: { __html: scriptSrc }
233
+ const defaultSystem = defaultTheme === "system";
234
+ const contents = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, {
235
+ children: forcedTheme ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("script", {
236
+ dangerouslySetInnerHTML: {
237
+ __html: `!function(){${optimization}${updateDOM(forcedTheme)}}()`
238
+ }
239
+ }, "next-themes-script") : enableSystem ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("script", {
240
+ dangerouslySetInnerHTML: {
241
+ __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(
242
+ "dark"
243
+ )}:${updateDOM("light")}}else if(e) ${value ? `var x=${JSON.stringify(value)};` : ""}${updateDOM(value ? "x[e]" : "e", true)}}catch(e){}}()`
244
+ }
245
+ }, "next-themes-script") : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("script", {
246
+ dangerouslySetInnerHTML: {
247
+ __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(
248
+ defaultTheme
249
+ )};}}catch(t){}}();`
250
+ }
251
+ }, "next-themes-script")
252
+ });
253
+ if (skipNextHead)
254
+ return contents;
255
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_head.default, {
256
+ children: contents
284
257
  });
285
258
  },
286
- () => true
259
+ (prevProps, nextProps) => {
260
+ if (prevProps.forcedTheme !== nextProps.forcedTheme)
261
+ return false;
262
+ return true;
263
+ }
287
264
  );
288
265
  const getTheme = (key, fallback) => {
289
266
  if (typeof window === "undefined")
@@ -306,7 +283,6 @@ const getSystemTheme = (e) => {
306
283
  // Annotate the CommonJS export names for ESM import in node:
307
284
  0 && (module.exports = {
308
285
  NextThemeProvider,
309
- Theme,
310
286
  useRootTheme,
311
287
  useTheme,
312
288
  useThemeSetting
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/NextTheme.tsx"],
4
- "sourcesContent": ["// https://raw.githubusercontent.com/pacocoursey/next-themes/master/index.tsx\n// forked temporarily due to buggy theme change\n\nimport { useEvent } from '@tamagui/use-event'\nimport * as React from 'react'\nimport {\n createContext,\n memo,\n useContext,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from 'react'\n\nconst useIsomorphicLayoutEffect =\n typeof window !== 'undefined' ? useLayoutEffect : useEffect\n\nexport interface UseThemeProps {\n /** List of all available theme names */\n themes: string[]\n /** Forced theme name for the current page */\n forcedTheme?: string\n /** Update the theme */\n set: (theme: string) => void\n toggle: () => void\n /** Active theme name - will return \"system\" if not overriden, see \"resolvedTheme\" for getting resolved system value */\n current?: string\n /** @deprecated Use `current` instead (deprecating avoid confusion with useTheme) */\n theme?: string\n /** 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` */\n resolvedTheme?: string\n /** If enableSystem is true, returns the System theme preference (\"dark\" or \"light\"), regardless what the active theme is */\n systemTheme?: 'dark' | 'light'\n}\n\nexport interface ThemeProviderProps {\n children?: any\n /** List of all available theme names */\n themes?: string[]\n /** Forced theme name for the current page */\n forcedTheme?: string\n /** Whether to switch between dark and light themes based on prefers-color-scheme */\n enableSystem?: boolean\n systemTheme?: string\n /** Disable all CSS transitions when switching themes */\n disableTransitionOnChange?: boolean\n /** Whether to indicate to browsers which color scheme is used (dark or light) for built-in UI like inputs and buttons */\n enableColorScheme?: boolean\n /** Key used to store theme setting in localStorage */\n storageKey?: string\n /** Default theme name (for v0.0.12 and lower the default was light). If `enableSystem` is false, the default theme is light */\n defaultTheme?: string\n /** HTML attribute modified based on the active theme. Accepts `class` and `data-*` (meaning any data attribute, `data-mode`, `data-color`, etc.) */\n attribute?: string | 'class'\n /** Mapping of theme name to HTML attribute value. Object where key is the theme name and value is the attribute value */\n value?: ValueObject\n onChangeTheme?: (name: string) => void\n nonce?: string\n}\n\nconst ThemeContext = createContext<UseThemeProps | null>(null)\n\n/**\n * @deprecated renamed to `useThemeSetting` to avoid confusion with core `useTheme` hook\n */\nexport const useTheme = () => useContext(ThemeContext)\n\nexport const useThemeSetting = () => useContext(ThemeContext)\n\nconst colorSchemes = ['light', 'dark']\nconst MEDIA = '(prefers-color-scheme: dark)'\n\ninterface ValueObject {\n [themeName: string]: string\n}\n\n// note this only works for light being default for now...\nexport const useRootTheme = () => {\n const [val, setVal] = useState('light')\n\n if (typeof document !== 'undefined') {\n useLayoutEffect(() => {\n // @ts-ignore\n const classes = [...document.documentElement.classList]\n const isDark = classes.includes('t_dark')\n React.startTransition(() => {\n setVal(isDark ? 'dark' : 'light')\n })\n }, [])\n }\n\n return [val, setVal] as const\n}\n\nexport const NextThemeProvider: React.FC<ThemeProviderProps> = (props) => {\n const context = useContext(ThemeContext)\n // Ignore nested context providers, just passthrough children\n if (context) {\n return <>{props.children}</>\n }\n return <Theme {...props} />\n}\n\nexport const Theme: React.FC<ThemeProviderProps> = ({\n nonce,\n forcedTheme,\n disableTransitionOnChange = true,\n enableSystem = true,\n enableColorScheme = true,\n storageKey = 'theme',\n themes = colorSchemes,\n defaultTheme = enableSystem ? 'system' : 'light',\n attribute = 'class',\n onChangeTheme,\n value = {\n dark: 't_dark',\n light: 't_light',\n },\n children,\n}) => {\n const [theme, setThemeState] = useState(() => getTheme(storageKey, defaultTheme))\n const [resolvedTheme, setResolvedTheme] = useState(() => getTheme(storageKey))\n // const resolvedTheme = React.useDeferredValue(resolvedThemeFast)\n const attrs = !value ? themes : Object.values(value)\n\n const handleMediaQuery = useEvent((e?) => {\n const systemTheme = getSystemTheme(e)\n React.startTransition(() => {\n setResolvedTheme(systemTheme)\n })\n if (theme === 'system' && !forcedTheme) {\n handleChangeTheme(systemTheme, false)\n }\n })\n\n // Ref hack to avoid adding handleMediaQuery as a dep\n const mediaListener = useRef(handleMediaQuery)\n mediaListener.current = handleMediaQuery\n\n const handleChangeTheme = useEvent((theme, updateStorage = true, updateDOM = true) => {\n let name = value?.[theme] || theme\n\n if (updateStorage) {\n try {\n localStorage.setItem(storageKey, theme)\n } catch (e) {\n // Unsupported\n }\n }\n\n if (theme === 'system' && enableSystem) {\n const resolved = getSystemTheme()\n name = value?.[resolved] || resolved\n }\n\n onChangeTheme?.(name.replace('t_', ''))\n\n if (updateDOM) {\n const d = document.documentElement\n if (attribute === 'class') {\n d.classList.remove(...attrs)\n d.classList.add(name)\n } else {\n d.setAttribute(attribute, name)\n }\n }\n })\n\n useIsomorphicLayoutEffect(() => {\n const handler = (...args: any) => mediaListener.current(...args)\n // Always listen to System preference\n const media = window.matchMedia(MEDIA)\n // Intentionally use deprecated listener methods to support iOS & old browsers\n media.addListener(handler)\n handler(media)\n return () => {\n media.removeListener(handler)\n }\n }, [])\n\n const set = useEvent((newTheme) => {\n if (forcedTheme) {\n handleChangeTheme(newTheme, true, false)\n } else {\n handleChangeTheme(newTheme)\n }\n setThemeState(newTheme)\n })\n\n // localStorage event handling\n useEffect(() => {\n const handleStorage = (e: StorageEvent) => {\n if (e.key !== storageKey) {\n return\n }\n // If default theme set, use it if localstorage === null (happens on local storage manual deletion)\n const theme = e.newValue || defaultTheme\n set(theme)\n }\n window.addEventListener('storage', handleStorage)\n return () => {\n window.removeEventListener('storage', handleStorage)\n }\n }, [defaultTheme, set, storageKey])\n\n // color-scheme handling\n useIsomorphicLayoutEffect(() => {\n if (!enableColorScheme) return\n\n const colorScheme =\n // If theme is forced to light or dark, use that\n forcedTheme && colorSchemes.includes(forcedTheme)\n ? forcedTheme\n : // If regular theme is light or dark\n theme && colorSchemes.includes(theme)\n ? theme\n : // If theme is system, use the resolved version\n theme === 'system'\n ? resolvedTheme || null\n : null\n\n // color-scheme tells browser how to render built-in elements like forms, scrollbars, etc.\n // if color-scheme is null, this will remove the property\n const userPrefers =\n typeof window !== 'undefined' &&\n window.matchMedia &&\n window.matchMedia('(prefers-color-scheme: dark)').matches\n ? 'dark'\n : 'light'\n\n const wePrefer = colorScheme || 'light'\n\n // avoid running this because it causes full page reflow\n if (userPrefers !== wePrefer) {\n document.documentElement.style.setProperty('color-scheme', colorScheme)\n }\n }, [enableColorScheme, theme, resolvedTheme, forcedTheme])\n\n const toggle = useEvent(() => {\n const order =\n resolvedTheme === 'dark' ? ['system', 'light', 'dark'] : ['system', 'dark', 'light']\n const next = order[(order.indexOf(theme) + 1) % order.length]\n set(next)\n })\n\n const contextResolvedTheme = theme === 'system' ? resolvedTheme : theme\n const systemTheme = (enableSystem ? resolvedTheme : undefined) as\n | 'light'\n | 'dark'\n | undefined\n const contextValue = useMemo(() => {\n const value: UseThemeProps = {\n theme,\n current: theme,\n set,\n toggle,\n forcedTheme,\n resolvedTheme: contextResolvedTheme,\n themes: enableSystem ? [...themes, 'system'] : themes,\n systemTheme,\n } as const\n return value\n }, [\n theme,\n set,\n toggle,\n forcedTheme,\n contextResolvedTheme,\n enableSystem,\n themes,\n systemTheme,\n ])\n\n return (\n <ThemeContext.Provider value={contextValue}>\n <ThemeScript\n {...{\n forcedTheme,\n disableTransitionOnChange,\n storageKey,\n systemTheme: resolvedTheme,\n attribute,\n enableColorScheme,\n value,\n themes,\n enableSystem,\n defaultTheme,\n attrs,\n nonce,\n }}\n />\n {/* because on SSR we re-run and can avoid whole tree re-render */}\n {useMemo(() => children, [children])}\n </ThemeContext.Provider>\n )\n}\n\nconst ThemeScript = memo(\n ({\n forcedTheme,\n storageKey,\n attribute,\n enableSystem,\n enableColorScheme,\n defaultTheme,\n value,\n attrs,\n nonce,\n }: ThemeProviderProps & { attrs: string[]; defaultTheme: string }) => {\n const defaultSystem = defaultTheme === 'system'\n\n // Code-golfing the amount of characters in the script\n const optimization = (() => {\n if (attribute === 'class') {\n const removeClasses = `c.remove(${attrs.map((t: string) => `'${t}'`).join(',')})`\n\n return `var d=document.documentElement,c=d.classList;${removeClasses};`\n } else {\n return `var d=document.documentElement,n='${attribute}',s='setAttribute';`\n }\n })()\n\n const fallbackColorScheme = (() => {\n if (!enableColorScheme) {\n return ''\n }\n\n const fallback = colorSchemes.includes(defaultTheme) ? defaultTheme : null\n\n if (fallback) {\n return `if(e==='light'||e==='dark'||!e)d.style.colorScheme=e||'${defaultTheme}'`\n } else {\n return `if(e==='light'||e==='dark')d.style.colorScheme=e`\n }\n })()\n\n const updateDOM = (name: string, literal: boolean = false, setColorScheme = true) => {\n const resolvedName = value ? value[name] : name\n const val = literal ? name + `|| ''` : `'${resolvedName}'`\n let text = ''\n\n // MUCH faster to set colorScheme alongside HTML attribute/class\n // as it only incurs 1 style recalculation rather than 2\n // This can save over 250ms of work for pages with big DOM\n if (\n enableColorScheme &&\n setColorScheme &&\n !literal &&\n colorSchemes.includes(name)\n ) {\n text += `d.style.colorScheme = '${name}';`\n }\n\n if (attribute === 'class') {\n if (literal || resolvedName) {\n text += `c.add(${val})`\n } else {\n text += `null`\n }\n } else {\n if (resolvedName) {\n text += `d[s](n,${val})`\n }\n }\n\n return text\n }\n\n const scriptSrc = (() => {\n if (forcedTheme) {\n return `!function(){${optimization}${updateDOM(forcedTheme)}}()`\n }\n\n if (enableSystem) {\n return `!function(){try{${optimization}var e=localStorage.getItem('${storageKey}');if('system'===e||(!e&&${defaultSystem})){var t='${MEDIA}',m=window.matchMedia(t);if(m.media!==t||m.matches){${updateDOM(\n 'dark'\n )}}else{${updateDOM('light')}}}else if(e){${\n value ? `var x=${JSON.stringify(value)};` : ''\n }${updateDOM(value ? `x[e]` : 'e', true)}}${\n !defaultSystem ? `else{` + updateDOM(defaultTheme, false, false) + '}' : ''\n }${fallbackColorScheme}}catch(e){}}()`\n }\n\n return `!function(){try{${optimization}var e=localStorage.getItem('${storageKey}');if(e){${\n value ? `var x=${JSON.stringify(value)};` : ''\n }${updateDOM(value ? `x[e]` : 'e', true)}}else{${updateDOM(\n defaultTheme,\n false,\n false\n )};}${fallbackColorScheme}}catch(t){}}();`\n })()\n\n return <script nonce={nonce} dangerouslySetInnerHTML={{ __html: scriptSrc }} />\n },\n // Never re-render this component\n () => true\n)\n\n// Helpers\nconst getTheme = (key: string, fallback?: string) => {\n if (typeof window === 'undefined') return undefined\n let theme\n try {\n theme = localStorage.getItem(key) || undefined\n } catch (e) {\n // Unsupported\n }\n return theme || fallback\n}\n\nconst getSystemTheme = (e?: MediaQueryList) => {\n if (!e) {\n e = window.matchMedia(MEDIA)\n }\n\n const isDark = e.matches\n const systemTheme = isDark ? 'dark' : 'light'\n return systemTheme\n}\n"],
5
- "mappings": "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",
6
- "names": ["systemTheme", "theme", "value"]
4
+ "sourcesContent": ["// https://raw.githubusercontent.com/pacocoursey/next-themes/master/index.tsx\n// forked temporarily due to buggy theme change\n\nimport { useEvent } from '@tamagui/use-event'\nimport NextHead from 'next/head'\nimport * as React from 'react'\nimport {\n createContext,\n memo,\n useContext,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from 'react'\n\nconst useIsomorphicLayoutEffect =\n typeof window !== 'undefined' ? useLayoutEffect : useEffect\n\nexport interface UseThemeProps {\n /** List of all available theme names */\n themes: string[]\n /** Forced theme name for the current page */\n forcedTheme?: string\n /** Update the theme */\n set: (theme: string) => void\n toggle: () => void\n /** Active theme name - will return \"system\" if not overriden, see \"resolvedTheme\" for getting resolved system value */\n current?: string\n /** @deprecated Use `current` instead (deprecating avoid confusion with useTheme) */\n theme?: string\n /** 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` */\n resolvedTheme?: string\n /** If enableSystem is true, returns the System theme preference (\"dark\" or \"light\"), regardless what the active theme is */\n systemTheme?: 'dark' | 'light'\n}\n\nexport interface ThemeProviderProps {\n children?: any\n /** List of all available theme names */\n themes?: string[]\n /** Forced theme name for the current page */\n forcedTheme?: string\n /** Whether to switch between dark and light themes based on prefers-color-scheme */\n enableSystem?: boolean\n systemTheme?: string\n /** Disable all CSS transitions when switching themes */\n disableTransitionOnChange?: boolean\n /** Whether to indicate to browsers which color scheme is used (dark or light) for built-in UI like inputs and buttons */\n enableColorScheme?: boolean\n /** Key used to store theme setting in localStorage */\n storageKey?: string\n /** Default theme name (for v0.0.12 and lower the default was light). If `enableSystem` is false, the default theme is light */\n defaultTheme?: string\n /** HTML attribute modified based on the active theme. Accepts `class` and `data-*` (meaning any data attribute, `data-mode`, `data-color`, etc.) */\n attribute?: string | 'class'\n /** Mapping of theme name to HTML attribute value. Object where key is the theme name and value is the attribute value */\n value?: ValueObject\n onChangeTheme?: (name: string) => void\n\n // avoids warning\n\n skipNextHead?: boolean\n}\n\nconst ThemeSettingContext = createContext<UseThemeProps>({\n toggle: () => {},\n set: (_) => {},\n themes: [],\n})\n\n/**\n * @deprecated renamed to `useThemeSetting` to avoid confusion with core `useTheme` hook\n */\nexport const useTheme = () => useContext(ThemeSettingContext)\n\nexport const useThemeSetting = () => useContext(ThemeSettingContext)\n\nconst colorSchemes = ['light', 'dark']\nconst MEDIA = '(prefers-color-scheme: dark)'\n\ninterface ValueObject {\n [themeName: string]: string\n}\n\n// note this only works for light being default for now...\nexport const useRootTheme = () => {\n const [val, setVal] = useState('light')\n\n if (typeof document !== 'undefined') {\n useLayoutEffect(() => {\n // @ts-ignore\n const classes = [...document.documentElement.classList]\n const isDark = classes.includes('t_dark')\n React.startTransition(() => {\n setVal(isDark ? 'dark' : 'light')\n })\n }, [])\n }\n\n return [val, setVal] as const\n}\n\nexport const NextThemeProvider: React.FC<ThemeProviderProps> = ({\n forcedTheme,\n disableTransitionOnChange = true,\n enableSystem = true,\n enableColorScheme = true,\n storageKey = 'theme',\n themes = colorSchemes,\n defaultTheme = enableSystem ? 'system' : 'light',\n attribute = 'class',\n skipNextHead,\n onChangeTheme,\n value = {\n dark: 't_dark',\n light: 't_light',\n },\n children,\n}) => {\n const [theme, setThemeState] = useState(() => getTheme(storageKey, defaultTheme))\n const [resolvedTheme, setResolvedTheme] = useState(() => getTheme(storageKey))\n // const resolvedTheme = React.useDeferredValue(resolvedThemeFast)\n const attrs = !value ? themes : Object.values(value)\n\n const handleMediaQuery = useEvent((e?) => {\n const systemTheme = getSystemTheme(e)\n React.startTransition(() => {\n setResolvedTheme(systemTheme)\n })\n if (theme === 'system' && !forcedTheme) {\n handleChangeTheme(systemTheme, false)\n }\n })\n\n // Ref hack to avoid adding handleMediaQuery as a dep\n const mediaListener = useRef(handleMediaQuery)\n mediaListener.current = handleMediaQuery\n\n const handleChangeTheme = useEvent((theme, updateStorage = true, updateDOM = true) => {\n let name = value?.[theme] || theme\n\n if (updateStorage) {\n try {\n localStorage.setItem(storageKey, theme)\n } catch (e) {\n // Unsupported\n }\n }\n\n if (theme === 'system' && enableSystem) {\n const resolved = getSystemTheme()\n name = value?.[resolved] || resolved\n }\n\n onChangeTheme?.(name.replace('t_', ''))\n\n if (updateDOM) {\n const d = document.documentElement\n if (attribute === 'class') {\n d.classList.remove(...attrs)\n d.classList.add(name)\n } else {\n d.setAttribute(attribute, name)\n }\n }\n })\n\n useIsomorphicLayoutEffect(() => {\n const handler = (...args: any) => mediaListener.current(...args)\n // Always listen to System preference\n const media = window.matchMedia(MEDIA)\n // Intentionally use deprecated listener methods to support iOS & old browsers\n media.addListener(handler)\n handler(media)\n return () => {\n media.removeListener(handler)\n }\n }, [])\n\n const set = useEvent((newTheme) => {\n if (forcedTheme) {\n handleChangeTheme(newTheme, true, false)\n } else {\n handleChangeTheme(newTheme)\n }\n setThemeState(newTheme)\n })\n\n // localStorage event handling\n useEffect(() => {\n const handleStorage = (e: StorageEvent) => {\n if (e.key !== storageKey) {\n return\n }\n // If default theme set, use it if localstorage === null (happens on local storage manual deletion)\n const theme = e.newValue || defaultTheme\n set(theme)\n }\n window.addEventListener('storage', handleStorage)\n return () => {\n window.removeEventListener('storage', handleStorage)\n }\n }, [defaultTheme, set, storageKey])\n\n // color-scheme handling\n useIsomorphicLayoutEffect(() => {\n if (!enableColorScheme) return\n\n const colorScheme =\n // If theme is forced to light or dark, use that\n forcedTheme && colorSchemes.includes(forcedTheme)\n ? forcedTheme\n : // If regular theme is light or dark\n theme && colorSchemes.includes(theme)\n ? theme\n : // If theme is system, use the resolved version\n theme === 'system'\n ? resolvedTheme || null\n : null\n\n // color-scheme tells browser how to render built-in elements like forms, scrollbars, etc.\n // if color-scheme is null, this will remove the property\n const userPrefers =\n typeof window !== 'undefined' &&\n window.matchMedia &&\n window.matchMedia('(prefers-color-scheme: dark)').matches\n ? 'dark'\n : 'light'\n\n const wePrefer = colorScheme || 'light'\n\n // avoid running this because it causes full page reflow\n if (userPrefers !== wePrefer) {\n document.documentElement.style.setProperty('color-scheme', colorScheme)\n }\n }, [enableColorScheme, theme, resolvedTheme, forcedTheme])\n\n const toggle = useEvent(() => {\n const order =\n resolvedTheme === 'dark' ? ['system', 'light', 'dark'] : ['system', 'dark', 'light']\n const next = order[(order.indexOf(theme) + 1) % order.length]\n set(next)\n })\n\n const contextResolvedTheme = theme === 'system' ? resolvedTheme : theme\n const systemTheme = (enableSystem ? resolvedTheme : undefined) as\n | 'light'\n | 'dark'\n | undefined\n const contextValue = useMemo(() => {\n const value: UseThemeProps = {\n theme,\n current: theme,\n set,\n toggle,\n forcedTheme,\n resolvedTheme: contextResolvedTheme,\n themes: enableSystem ? [...themes, 'system'] : themes,\n systemTheme,\n } as const\n return value\n }, [\n theme,\n set,\n toggle,\n forcedTheme,\n contextResolvedTheme,\n enableSystem,\n themes,\n systemTheme,\n ])\n\n return (\n <ThemeSettingContext.Provider value={contextValue}>\n <ThemeScript\n {...{\n forcedTheme,\n storageKey,\n systemTheme: resolvedTheme,\n attribute,\n value,\n enableSystem,\n defaultTheme,\n attrs,\n skipNextHead,\n }}\n />\n {/* because on SSR we re-run and can avoid whole tree re-render */}\n {useMemo(() => children, [children])}\n </ThemeSettingContext.Provider>\n )\n}\n\nconst ThemeScript = memo(\n ({\n forcedTheme,\n storageKey,\n attribute,\n enableSystem,\n defaultTheme,\n value,\n attrs,\n skipNextHead,\n }: {\n forcedTheme?: string\n storageKey: string\n attribute?: string\n enableSystem?: boolean\n defaultTheme: string\n value?: ValueObject\n attrs: any\n skipNextHead\n }) => {\n // Code-golfing the amount of characters in the script\n const optimization = (() => {\n if (attribute === 'class') {\n const removeClasses = attrs.map((t: string) => `d.remove('${t}')`).join(';')\n return `var d=document.documentElement.classList;${removeClasses};`\n } else {\n return `var d=document.documentElement;`\n }\n })()\n\n const updateDOM = (name: string, literal?: boolean) => {\n name = value?.[name] || name\n const val = literal ? name : `'${name}'`\n\n if (attribute === 'class') {\n return `d.add(${val})`\n }\n\n return `d.setAttribute('${attribute}', ${val})`\n }\n\n const defaultSystem = defaultTheme === 'system'\n\n const contents = (\n <>\n {forcedTheme ? (\n <script\n key=\"next-themes-script\"\n dangerouslySetInnerHTML={{\n // These are minified via Terser and then updated by hand, don't recommend\n __html: `!function(){${optimization}${updateDOM(forcedTheme)}}()`,\n }}\n />\n ) : enableSystem ? (\n <script\n key=\"next-themes-script\"\n dangerouslySetInnerHTML={{\n __html: `!function(){try {${optimization}var e=localStorage.getItem('${storageKey}');${\n !defaultSystem ? updateDOM(defaultTheme) + ';' : ''\n }if(\"system\"===e||(!e&&${defaultSystem})){var t=\"${MEDIA}\",m=window.matchMedia(t);m.media!==t||m.matches?${updateDOM(\n 'dark'\n )}:${updateDOM('light')}}else if(e) ${\n value ? `var x=${JSON.stringify(value)};` : ''\n }${updateDOM(value ? 'x[e]' : 'e', true)}}catch(e){}}()`,\n }}\n />\n ) : (\n <script\n key=\"next-themes-script\"\n dangerouslySetInnerHTML={{\n __html: `!function(){try{${optimization}var e=localStorage.getItem(\"${storageKey}\");if(e){${\n value ? `var x=${JSON.stringify(value)};` : ''\n }${updateDOM(value ? 'x[e]' : 'e', true)}}else{${updateDOM(\n defaultTheme\n )};}}catch(t){}}();`,\n }}\n />\n )}\n </>\n )\n\n if (skipNextHead) return contents\n\n return <NextHead>{contents}</NextHead>\n },\n (prevProps, nextProps) => {\n // Only re-render when forcedTheme changes\n // the rest of the props should be completely stable\n if (prevProps.forcedTheme !== nextProps.forcedTheme) return false\n return true\n }\n)\n\n// Helpers\nconst getTheme = (key: string, fallback?: string) => {\n if (typeof window === 'undefined') return undefined\n let theme\n try {\n theme = localStorage.getItem(key) || undefined\n } catch (e) {\n // Unsupported\n }\n return theme || fallback\n}\n\nconst getSystemTheme = (e?: MediaQueryList) => {\n if (!e) {\n e = window.matchMedia(MEDIA)\n }\n\n const isDark = e.matches\n const systemTheme = isDark ? 'dark' : 'light'\n return systemTheme\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["systemTheme", "theme", "value", "NextHead"]
7
7
  }
@@ -1,5 +1,6 @@
1
1
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
2
  import { useEvent } from "@tamagui/use-event";
3
+ import NextHead from "next/head";
3
4
  import * as React from "react";
4
5
  import {
5
6
  createContext,
@@ -12,9 +13,15 @@ import {
12
13
  useState
13
14
  } from "react";
14
15
  const useIsomorphicLayoutEffect = typeof window !== "undefined" ? useLayoutEffect : useEffect;
15
- const ThemeContext = createContext(null);
16
- const useTheme = () => useContext(ThemeContext);
17
- const useThemeSetting = () => useContext(ThemeContext);
16
+ const ThemeSettingContext = createContext({
17
+ toggle: () => {
18
+ },
19
+ set: (_) => {
20
+ },
21
+ themes: []
22
+ });
23
+ const useTheme = () => useContext(ThemeSettingContext);
24
+ const useThemeSetting = () => useContext(ThemeSettingContext);
18
25
  const colorSchemes = ["light", "dark"];
19
26
  const MEDIA = "(prefers-color-scheme: dark)";
20
27
  const useRootTheme = () => {
@@ -30,19 +37,7 @@ const useRootTheme = () => {
30
37
  }
31
38
  return [val, setVal];
32
39
  };
33
- const NextThemeProvider = (props) => {
34
- const context = useContext(ThemeContext);
35
- if (context) {
36
- return /* @__PURE__ */ jsx(Fragment, {
37
- children: props.children
38
- });
39
- }
40
- return /* @__PURE__ */ jsx(Theme, {
41
- ...props
42
- });
43
- };
44
- const Theme = ({
45
- nonce,
40
+ const NextThemeProvider = ({
46
41
  forcedTheme,
47
42
  disableTransitionOnChange = true,
48
43
  enableSystem = true,
@@ -51,6 +46,7 @@ const Theme = ({
51
46
  themes = colorSchemes,
52
47
  defaultTheme = enableSystem ? "system" : "light",
53
48
  attribute = "class",
49
+ skipNextHead,
54
50
  onChangeTheme,
55
51
  value = {
56
52
  dark: "t_dark",
@@ -164,23 +160,20 @@ const Theme = ({
164
160
  themes,
165
161
  systemTheme
166
162
  ]);
167
- return /* @__PURE__ */ jsxs(ThemeContext.Provider, {
163
+ return /* @__PURE__ */ jsxs(ThemeSettingContext.Provider, {
168
164
  value: contextValue,
169
165
  children: [
170
166
  /* @__PURE__ */ jsx(ThemeScript, {
171
167
  ...{
172
168
  forcedTheme,
173
- disableTransitionOnChange,
174
169
  storageKey,
175
170
  systemTheme: resolvedTheme,
176
171
  attribute,
177
- enableColorScheme,
178
172
  value,
179
- themes,
180
173
  enableSystem,
181
174
  defaultTheme,
182
175
  attrs,
183
- nonce
176
+ skipNextHead
184
177
  }
185
178
  }),
186
179
  useMemo(() => children, [children])
@@ -193,73 +186,58 @@ const ThemeScript = memo(
193
186
  storageKey,
194
187
  attribute,
195
188
  enableSystem,
196
- enableColorScheme,
197
189
  defaultTheme,
198
190
  value,
199
191
  attrs,
200
- nonce
192
+ skipNextHead
201
193
  }) => {
202
- const defaultSystem = defaultTheme === "system";
203
194
  const optimization = (() => {
204
195
  if (attribute === "class") {
205
- const removeClasses = `c.remove(${attrs.map((t) => `'${t}'`).join(",")})`;
206
- return `var d=document.documentElement,c=d.classList;${removeClasses};`;
207
- } else {
208
- return `var d=document.documentElement,n='${attribute}',s='setAttribute';`;
209
- }
210
- })();
211
- const fallbackColorScheme = (() => {
212
- if (!enableColorScheme) {
213
- return "";
214
- }
215
- const fallback = colorSchemes.includes(defaultTheme) ? defaultTheme : null;
216
- if (fallback) {
217
- return `if(e==='light'||e==='dark'||!e)d.style.colorScheme=e||'${defaultTheme}'`;
196
+ const removeClasses = attrs.map((t) => `d.remove('${t}')`).join(";");
197
+ return `var d=document.documentElement.classList;${removeClasses};`;
218
198
  } else {
219
- return `if(e==='light'||e==='dark')d.style.colorScheme=e`;
199
+ return `var d=document.documentElement;`;
220
200
  }
221
201
  })();
222
- const updateDOM = (name, literal = false, setColorScheme = true) => {
223
- const resolvedName = value ? value[name] : name;
224
- const val = literal ? name + `|| ''` : `'${resolvedName}'`;
225
- let text = "";
226
- if (enableColorScheme && setColorScheme && !literal && colorSchemes.includes(name)) {
227
- text += `d.style.colorScheme = '${name}';`;
228
- }
202
+ const updateDOM = (name, literal) => {
203
+ name = (value == null ? void 0 : value[name]) || name;
204
+ const val = literal ? name : `'${name}'`;
229
205
  if (attribute === "class") {
230
- if (literal || resolvedName) {
231
- text += `c.add(${val})`;
232
- } else {
233
- text += `null`;
234
- }
235
- } else {
236
- if (resolvedName) {
237
- text += `d[s](n,${val})`;
238
- }
206
+ return `d.add(${val})`;
239
207
  }
240
- return text;
208
+ return `d.setAttribute('${attribute}', ${val})`;
241
209
  };
242
- const scriptSrc = (() => {
243
- if (forcedTheme) {
244
- return `!function(){${optimization}${updateDOM(forcedTheme)}}()`;
245
- }
246
- if (enableSystem) {
247
- return `!function(){try{${optimization}var e=localStorage.getItem('${storageKey}');if('system'===e||(!e&&${defaultSystem})){var t='${MEDIA}',m=window.matchMedia(t);if(m.media!==t||m.matches){${updateDOM(
248
- "dark"
249
- )}}else{${updateDOM("light")}}}else if(e){${value ? `var x=${JSON.stringify(value)};` : ""}${updateDOM(value ? `x[e]` : "e", true)}}${!defaultSystem ? `else{` + updateDOM(defaultTheme, false, false) + "}" : ""}${fallbackColorScheme}}catch(e){}}()`;
250
- }
251
- return `!function(){try{${optimization}var e=localStorage.getItem('${storageKey}');if(e){${value ? `var x=${JSON.stringify(value)};` : ""}${updateDOM(value ? `x[e]` : "e", true)}}else{${updateDOM(
252
- defaultTheme,
253
- false,
254
- false
255
- )};}${fallbackColorScheme}}catch(t){}}();`;
256
- })();
257
- return /* @__PURE__ */ jsx("script", {
258
- nonce,
259
- dangerouslySetInnerHTML: { __html: scriptSrc }
210
+ const defaultSystem = defaultTheme === "system";
211
+ const contents = /* @__PURE__ */ jsx(Fragment, {
212
+ children: forcedTheme ? /* @__PURE__ */ jsx("script", {
213
+ dangerouslySetInnerHTML: {
214
+ __html: `!function(){${optimization}${updateDOM(forcedTheme)}}()`
215
+ }
216
+ }, "next-themes-script") : enableSystem ? /* @__PURE__ */ jsx("script", {
217
+ dangerouslySetInnerHTML: {
218
+ __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(
219
+ "dark"
220
+ )}:${updateDOM("light")}}else if(e) ${value ? `var x=${JSON.stringify(value)};` : ""}${updateDOM(value ? "x[e]" : "e", true)}}catch(e){}}()`
221
+ }
222
+ }, "next-themes-script") : /* @__PURE__ */ jsx("script", {
223
+ dangerouslySetInnerHTML: {
224
+ __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(
225
+ defaultTheme
226
+ )};}}catch(t){}}();`
227
+ }
228
+ }, "next-themes-script")
229
+ });
230
+ if (skipNextHead)
231
+ return contents;
232
+ return /* @__PURE__ */ jsx(NextHead, {
233
+ children: contents
260
234
  });
261
235
  },
262
- () => true
236
+ (prevProps, nextProps) => {
237
+ if (prevProps.forcedTheme !== nextProps.forcedTheme)
238
+ return false;
239
+ return true;
240
+ }
263
241
  );
264
242
  const getTheme = (key, fallback) => {
265
243
  if (typeof window === "undefined")
@@ -281,7 +259,6 @@ const getSystemTheme = (e) => {
281
259
  };
282
260
  export {
283
261
  NextThemeProvider,
284
- Theme,
285
262
  useRootTheme,
286
263
  useTheme,
287
264
  useThemeSetting
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/NextTheme.tsx"],
4
- "sourcesContent": ["// https://raw.githubusercontent.com/pacocoursey/next-themes/master/index.tsx\n// forked temporarily due to buggy theme change\n\nimport { useEvent } from '@tamagui/use-event'\nimport * as React from 'react'\nimport {\n createContext,\n memo,\n useContext,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from 'react'\n\nconst useIsomorphicLayoutEffect =\n typeof window !== 'undefined' ? useLayoutEffect : useEffect\n\nexport interface UseThemeProps {\n /** List of all available theme names */\n themes: string[]\n /** Forced theme name for the current page */\n forcedTheme?: string\n /** Update the theme */\n set: (theme: string) => void\n toggle: () => void\n /** Active theme name - will return \"system\" if not overriden, see \"resolvedTheme\" for getting resolved system value */\n current?: string\n /** @deprecated Use `current` instead (deprecating avoid confusion with useTheme) */\n theme?: string\n /** 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` */\n resolvedTheme?: string\n /** If enableSystem is true, returns the System theme preference (\"dark\" or \"light\"), regardless what the active theme is */\n systemTheme?: 'dark' | 'light'\n}\n\nexport interface ThemeProviderProps {\n children?: any\n /** List of all available theme names */\n themes?: string[]\n /** Forced theme name for the current page */\n forcedTheme?: string\n /** Whether to switch between dark and light themes based on prefers-color-scheme */\n enableSystem?: boolean\n systemTheme?: string\n /** Disable all CSS transitions when switching themes */\n disableTransitionOnChange?: boolean\n /** Whether to indicate to browsers which color scheme is used (dark or light) for built-in UI like inputs and buttons */\n enableColorScheme?: boolean\n /** Key used to store theme setting in localStorage */\n storageKey?: string\n /** Default theme name (for v0.0.12 and lower the default was light). If `enableSystem` is false, the default theme is light */\n defaultTheme?: string\n /** HTML attribute modified based on the active theme. Accepts `class` and `data-*` (meaning any data attribute, `data-mode`, `data-color`, etc.) */\n attribute?: string | 'class'\n /** Mapping of theme name to HTML attribute value. Object where key is the theme name and value is the attribute value */\n value?: ValueObject\n onChangeTheme?: (name: string) => void\n nonce?: string\n}\n\nconst ThemeContext = createContext<UseThemeProps | null>(null)\n\n/**\n * @deprecated renamed to `useThemeSetting` to avoid confusion with core `useTheme` hook\n */\nexport const useTheme = () => useContext(ThemeContext)\n\nexport const useThemeSetting = () => useContext(ThemeContext)\n\nconst colorSchemes = ['light', 'dark']\nconst MEDIA = '(prefers-color-scheme: dark)'\n\ninterface ValueObject {\n [themeName: string]: string\n}\n\n// note this only works for light being default for now...\nexport const useRootTheme = () => {\n const [val, setVal] = useState('light')\n\n if (typeof document !== 'undefined') {\n useLayoutEffect(() => {\n // @ts-ignore\n const classes = [...document.documentElement.classList]\n const isDark = classes.includes('t_dark')\n React.startTransition(() => {\n setVal(isDark ? 'dark' : 'light')\n })\n }, [])\n }\n\n return [val, setVal] as const\n}\n\nexport const NextThemeProvider: React.FC<ThemeProviderProps> = (props) => {\n const context = useContext(ThemeContext)\n // Ignore nested context providers, just passthrough children\n if (context) {\n return <>{props.children}</>\n }\n return <Theme {...props} />\n}\n\nexport const Theme: React.FC<ThemeProviderProps> = ({\n nonce,\n forcedTheme,\n disableTransitionOnChange = true,\n enableSystem = true,\n enableColorScheme = true,\n storageKey = 'theme',\n themes = colorSchemes,\n defaultTheme = enableSystem ? 'system' : 'light',\n attribute = 'class',\n onChangeTheme,\n value = {\n dark: 't_dark',\n light: 't_light',\n },\n children,\n}) => {\n const [theme, setThemeState] = useState(() => getTheme(storageKey, defaultTheme))\n const [resolvedTheme, setResolvedTheme] = useState(() => getTheme(storageKey))\n // const resolvedTheme = React.useDeferredValue(resolvedThemeFast)\n const attrs = !value ? themes : Object.values(value)\n\n const handleMediaQuery = useEvent((e?) => {\n const systemTheme = getSystemTheme(e)\n React.startTransition(() => {\n setResolvedTheme(systemTheme)\n })\n if (theme === 'system' && !forcedTheme) {\n handleChangeTheme(systemTheme, false)\n }\n })\n\n // Ref hack to avoid adding handleMediaQuery as a dep\n const mediaListener = useRef(handleMediaQuery)\n mediaListener.current = handleMediaQuery\n\n const handleChangeTheme = useEvent((theme, updateStorage = true, updateDOM = true) => {\n let name = value?.[theme] || theme\n\n if (updateStorage) {\n try {\n localStorage.setItem(storageKey, theme)\n } catch (e) {\n // Unsupported\n }\n }\n\n if (theme === 'system' && enableSystem) {\n const resolved = getSystemTheme()\n name = value?.[resolved] || resolved\n }\n\n onChangeTheme?.(name.replace('t_', ''))\n\n if (updateDOM) {\n const d = document.documentElement\n if (attribute === 'class') {\n d.classList.remove(...attrs)\n d.classList.add(name)\n } else {\n d.setAttribute(attribute, name)\n }\n }\n })\n\n useIsomorphicLayoutEffect(() => {\n const handler = (...args: any) => mediaListener.current(...args)\n // Always listen to System preference\n const media = window.matchMedia(MEDIA)\n // Intentionally use deprecated listener methods to support iOS & old browsers\n media.addListener(handler)\n handler(media)\n return () => {\n media.removeListener(handler)\n }\n }, [])\n\n const set = useEvent((newTheme) => {\n if (forcedTheme) {\n handleChangeTheme(newTheme, true, false)\n } else {\n handleChangeTheme(newTheme)\n }\n setThemeState(newTheme)\n })\n\n // localStorage event handling\n useEffect(() => {\n const handleStorage = (e: StorageEvent) => {\n if (e.key !== storageKey) {\n return\n }\n // If default theme set, use it if localstorage === null (happens on local storage manual deletion)\n const theme = e.newValue || defaultTheme\n set(theme)\n }\n window.addEventListener('storage', handleStorage)\n return () => {\n window.removeEventListener('storage', handleStorage)\n }\n }, [defaultTheme, set, storageKey])\n\n // color-scheme handling\n useIsomorphicLayoutEffect(() => {\n if (!enableColorScheme) return\n\n const colorScheme =\n // If theme is forced to light or dark, use that\n forcedTheme && colorSchemes.includes(forcedTheme)\n ? forcedTheme\n : // If regular theme is light or dark\n theme && colorSchemes.includes(theme)\n ? theme\n : // If theme is system, use the resolved version\n theme === 'system'\n ? resolvedTheme || null\n : null\n\n // color-scheme tells browser how to render built-in elements like forms, scrollbars, etc.\n // if color-scheme is null, this will remove the property\n const userPrefers =\n typeof window !== 'undefined' &&\n window.matchMedia &&\n window.matchMedia('(prefers-color-scheme: dark)').matches\n ? 'dark'\n : 'light'\n\n const wePrefer = colorScheme || 'light'\n\n // avoid running this because it causes full page reflow\n if (userPrefers !== wePrefer) {\n document.documentElement.style.setProperty('color-scheme', colorScheme)\n }\n }, [enableColorScheme, theme, resolvedTheme, forcedTheme])\n\n const toggle = useEvent(() => {\n const order =\n resolvedTheme === 'dark' ? ['system', 'light', 'dark'] : ['system', 'dark', 'light']\n const next = order[(order.indexOf(theme) + 1) % order.length]\n set(next)\n })\n\n const contextResolvedTheme = theme === 'system' ? resolvedTheme : theme\n const systemTheme = (enableSystem ? resolvedTheme : undefined) as\n | 'light'\n | 'dark'\n | undefined\n const contextValue = useMemo(() => {\n const value: UseThemeProps = {\n theme,\n current: theme,\n set,\n toggle,\n forcedTheme,\n resolvedTheme: contextResolvedTheme,\n themes: enableSystem ? [...themes, 'system'] : themes,\n systemTheme,\n } as const\n return value\n }, [\n theme,\n set,\n toggle,\n forcedTheme,\n contextResolvedTheme,\n enableSystem,\n themes,\n systemTheme,\n ])\n\n return (\n <ThemeContext.Provider value={contextValue}>\n <ThemeScript\n {...{\n forcedTheme,\n disableTransitionOnChange,\n storageKey,\n systemTheme: resolvedTheme,\n attribute,\n enableColorScheme,\n value,\n themes,\n enableSystem,\n defaultTheme,\n attrs,\n nonce,\n }}\n />\n {/* because on SSR we re-run and can avoid whole tree re-render */}\n {useMemo(() => children, [children])}\n </ThemeContext.Provider>\n )\n}\n\nconst ThemeScript = memo(\n ({\n forcedTheme,\n storageKey,\n attribute,\n enableSystem,\n enableColorScheme,\n defaultTheme,\n value,\n attrs,\n nonce,\n }: ThemeProviderProps & { attrs: string[]; defaultTheme: string }) => {\n const defaultSystem = defaultTheme === 'system'\n\n // Code-golfing the amount of characters in the script\n const optimization = (() => {\n if (attribute === 'class') {\n const removeClasses = `c.remove(${attrs.map((t: string) => `'${t}'`).join(',')})`\n\n return `var d=document.documentElement,c=d.classList;${removeClasses};`\n } else {\n return `var d=document.documentElement,n='${attribute}',s='setAttribute';`\n }\n })()\n\n const fallbackColorScheme = (() => {\n if (!enableColorScheme) {\n return ''\n }\n\n const fallback = colorSchemes.includes(defaultTheme) ? defaultTheme : null\n\n if (fallback) {\n return `if(e==='light'||e==='dark'||!e)d.style.colorScheme=e||'${defaultTheme}'`\n } else {\n return `if(e==='light'||e==='dark')d.style.colorScheme=e`\n }\n })()\n\n const updateDOM = (name: string, literal: boolean = false, setColorScheme = true) => {\n const resolvedName = value ? value[name] : name\n const val = literal ? name + `|| ''` : `'${resolvedName}'`\n let text = ''\n\n // MUCH faster to set colorScheme alongside HTML attribute/class\n // as it only incurs 1 style recalculation rather than 2\n // This can save over 250ms of work for pages with big DOM\n if (\n enableColorScheme &&\n setColorScheme &&\n !literal &&\n colorSchemes.includes(name)\n ) {\n text += `d.style.colorScheme = '${name}';`\n }\n\n if (attribute === 'class') {\n if (literal || resolvedName) {\n text += `c.add(${val})`\n } else {\n text += `null`\n }\n } else {\n if (resolvedName) {\n text += `d[s](n,${val})`\n }\n }\n\n return text\n }\n\n const scriptSrc = (() => {\n if (forcedTheme) {\n return `!function(){${optimization}${updateDOM(forcedTheme)}}()`\n }\n\n if (enableSystem) {\n return `!function(){try{${optimization}var e=localStorage.getItem('${storageKey}');if('system'===e||(!e&&${defaultSystem})){var t='${MEDIA}',m=window.matchMedia(t);if(m.media!==t||m.matches){${updateDOM(\n 'dark'\n )}}else{${updateDOM('light')}}}else if(e){${\n value ? `var x=${JSON.stringify(value)};` : ''\n }${updateDOM(value ? `x[e]` : 'e', true)}}${\n !defaultSystem ? `else{` + updateDOM(defaultTheme, false, false) + '}' : ''\n }${fallbackColorScheme}}catch(e){}}()`\n }\n\n return `!function(){try{${optimization}var e=localStorage.getItem('${storageKey}');if(e){${\n value ? `var x=${JSON.stringify(value)};` : ''\n }${updateDOM(value ? `x[e]` : 'e', true)}}else{${updateDOM(\n defaultTheme,\n false,\n false\n )};}${fallbackColorScheme}}catch(t){}}();`\n })()\n\n return <script nonce={nonce} dangerouslySetInnerHTML={{ __html: scriptSrc }} />\n },\n // Never re-render this component\n () => true\n)\n\n// Helpers\nconst getTheme = (key: string, fallback?: string) => {\n if (typeof window === 'undefined') return undefined\n let theme\n try {\n theme = localStorage.getItem(key) || undefined\n } catch (e) {\n // Unsupported\n }\n return theme || fallback\n}\n\nconst getSystemTheme = (e?: MediaQueryList) => {\n if (!e) {\n e = window.matchMedia(MEDIA)\n }\n\n const isDark = e.matches\n const systemTheme = isDark ? 'dark' : 'light'\n return systemTheme\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["// https://raw.githubusercontent.com/pacocoursey/next-themes/master/index.tsx\n// forked temporarily due to buggy theme change\n\nimport { useEvent } from '@tamagui/use-event'\nimport NextHead from 'next/head'\nimport * as React from 'react'\nimport {\n createContext,\n memo,\n useContext,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from 'react'\n\nconst useIsomorphicLayoutEffect =\n typeof window !== 'undefined' ? useLayoutEffect : useEffect\n\nexport interface UseThemeProps {\n /** List of all available theme names */\n themes: string[]\n /** Forced theme name for the current page */\n forcedTheme?: string\n /** Update the theme */\n set: (theme: string) => void\n toggle: () => void\n /** Active theme name - will return \"system\" if not overriden, see \"resolvedTheme\" for getting resolved system value */\n current?: string\n /** @deprecated Use `current` instead (deprecating avoid confusion with useTheme) */\n theme?: string\n /** 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` */\n resolvedTheme?: string\n /** If enableSystem is true, returns the System theme preference (\"dark\" or \"light\"), regardless what the active theme is */\n systemTheme?: 'dark' | 'light'\n}\n\nexport interface ThemeProviderProps {\n children?: any\n /** List of all available theme names */\n themes?: string[]\n /** Forced theme name for the current page */\n forcedTheme?: string\n /** Whether to switch between dark and light themes based on prefers-color-scheme */\n enableSystem?: boolean\n systemTheme?: string\n /** Disable all CSS transitions when switching themes */\n disableTransitionOnChange?: boolean\n /** Whether to indicate to browsers which color scheme is used (dark or light) for built-in UI like inputs and buttons */\n enableColorScheme?: boolean\n /** Key used to store theme setting in localStorage */\n storageKey?: string\n /** Default theme name (for v0.0.12 and lower the default was light). If `enableSystem` is false, the default theme is light */\n defaultTheme?: string\n /** HTML attribute modified based on the active theme. Accepts `class` and `data-*` (meaning any data attribute, `data-mode`, `data-color`, etc.) */\n attribute?: string | 'class'\n /** Mapping of theme name to HTML attribute value. Object where key is the theme name and value is the attribute value */\n value?: ValueObject\n onChangeTheme?: (name: string) => void\n\n // avoids warning\n\n skipNextHead?: boolean\n}\n\nconst ThemeSettingContext = createContext<UseThemeProps>({\n toggle: () => {},\n set: (_) => {},\n themes: [],\n})\n\n/**\n * @deprecated renamed to `useThemeSetting` to avoid confusion with core `useTheme` hook\n */\nexport const useTheme = () => useContext(ThemeSettingContext)\n\nexport const useThemeSetting = () => useContext(ThemeSettingContext)\n\nconst colorSchemes = ['light', 'dark']\nconst MEDIA = '(prefers-color-scheme: dark)'\n\ninterface ValueObject {\n [themeName: string]: string\n}\n\n// note this only works for light being default for now...\nexport const useRootTheme = () => {\n const [val, setVal] = useState('light')\n\n if (typeof document !== 'undefined') {\n useLayoutEffect(() => {\n // @ts-ignore\n const classes = [...document.documentElement.classList]\n const isDark = classes.includes('t_dark')\n React.startTransition(() => {\n setVal(isDark ? 'dark' : 'light')\n })\n }, [])\n }\n\n return [val, setVal] as const\n}\n\nexport const NextThemeProvider: React.FC<ThemeProviderProps> = ({\n forcedTheme,\n disableTransitionOnChange = true,\n enableSystem = true,\n enableColorScheme = true,\n storageKey = 'theme',\n themes = colorSchemes,\n defaultTheme = enableSystem ? 'system' : 'light',\n attribute = 'class',\n skipNextHead,\n onChangeTheme,\n value = {\n dark: 't_dark',\n light: 't_light',\n },\n children,\n}) => {\n const [theme, setThemeState] = useState(() => getTheme(storageKey, defaultTheme))\n const [resolvedTheme, setResolvedTheme] = useState(() => getTheme(storageKey))\n // const resolvedTheme = React.useDeferredValue(resolvedThemeFast)\n const attrs = !value ? themes : Object.values(value)\n\n const handleMediaQuery = useEvent((e?) => {\n const systemTheme = getSystemTheme(e)\n React.startTransition(() => {\n setResolvedTheme(systemTheme)\n })\n if (theme === 'system' && !forcedTheme) {\n handleChangeTheme(systemTheme, false)\n }\n })\n\n // Ref hack to avoid adding handleMediaQuery as a dep\n const mediaListener = useRef(handleMediaQuery)\n mediaListener.current = handleMediaQuery\n\n const handleChangeTheme = useEvent((theme, updateStorage = true, updateDOM = true) => {\n let name = value?.[theme] || theme\n\n if (updateStorage) {\n try {\n localStorage.setItem(storageKey, theme)\n } catch (e) {\n // Unsupported\n }\n }\n\n if (theme === 'system' && enableSystem) {\n const resolved = getSystemTheme()\n name = value?.[resolved] || resolved\n }\n\n onChangeTheme?.(name.replace('t_', ''))\n\n if (updateDOM) {\n const d = document.documentElement\n if (attribute === 'class') {\n d.classList.remove(...attrs)\n d.classList.add(name)\n } else {\n d.setAttribute(attribute, name)\n }\n }\n })\n\n useIsomorphicLayoutEffect(() => {\n const handler = (...args: any) => mediaListener.current(...args)\n // Always listen to System preference\n const media = window.matchMedia(MEDIA)\n // Intentionally use deprecated listener methods to support iOS & old browsers\n media.addListener(handler)\n handler(media)\n return () => {\n media.removeListener(handler)\n }\n }, [])\n\n const set = useEvent((newTheme) => {\n if (forcedTheme) {\n handleChangeTheme(newTheme, true, false)\n } else {\n handleChangeTheme(newTheme)\n }\n setThemeState(newTheme)\n })\n\n // localStorage event handling\n useEffect(() => {\n const handleStorage = (e: StorageEvent) => {\n if (e.key !== storageKey) {\n return\n }\n // If default theme set, use it if localstorage === null (happens on local storage manual deletion)\n const theme = e.newValue || defaultTheme\n set(theme)\n }\n window.addEventListener('storage', handleStorage)\n return () => {\n window.removeEventListener('storage', handleStorage)\n }\n }, [defaultTheme, set, storageKey])\n\n // color-scheme handling\n useIsomorphicLayoutEffect(() => {\n if (!enableColorScheme) return\n\n const colorScheme =\n // If theme is forced to light or dark, use that\n forcedTheme && colorSchemes.includes(forcedTheme)\n ? forcedTheme\n : // If regular theme is light or dark\n theme && colorSchemes.includes(theme)\n ? theme\n : // If theme is system, use the resolved version\n theme === 'system'\n ? resolvedTheme || null\n : null\n\n // color-scheme tells browser how to render built-in elements like forms, scrollbars, etc.\n // if color-scheme is null, this will remove the property\n const userPrefers =\n typeof window !== 'undefined' &&\n window.matchMedia &&\n window.matchMedia('(prefers-color-scheme: dark)').matches\n ? 'dark'\n : 'light'\n\n const wePrefer = colorScheme || 'light'\n\n // avoid running this because it causes full page reflow\n if (userPrefers !== wePrefer) {\n document.documentElement.style.setProperty('color-scheme', colorScheme)\n }\n }, [enableColorScheme, theme, resolvedTheme, forcedTheme])\n\n const toggle = useEvent(() => {\n const order =\n resolvedTheme === 'dark' ? ['system', 'light', 'dark'] : ['system', 'dark', 'light']\n const next = order[(order.indexOf(theme) + 1) % order.length]\n set(next)\n })\n\n const contextResolvedTheme = theme === 'system' ? resolvedTheme : theme\n const systemTheme = (enableSystem ? resolvedTheme : undefined) as\n | 'light'\n | 'dark'\n | undefined\n const contextValue = useMemo(() => {\n const value: UseThemeProps = {\n theme,\n current: theme,\n set,\n toggle,\n forcedTheme,\n resolvedTheme: contextResolvedTheme,\n themes: enableSystem ? [...themes, 'system'] : themes,\n systemTheme,\n } as const\n return value\n }, [\n theme,\n set,\n toggle,\n forcedTheme,\n contextResolvedTheme,\n enableSystem,\n themes,\n systemTheme,\n ])\n\n return (\n <ThemeSettingContext.Provider value={contextValue}>\n <ThemeScript\n {...{\n forcedTheme,\n storageKey,\n systemTheme: resolvedTheme,\n attribute,\n value,\n enableSystem,\n defaultTheme,\n attrs,\n skipNextHead,\n }}\n />\n {/* because on SSR we re-run and can avoid whole tree re-render */}\n {useMemo(() => children, [children])}\n </ThemeSettingContext.Provider>\n )\n}\n\nconst ThemeScript = memo(\n ({\n forcedTheme,\n storageKey,\n attribute,\n enableSystem,\n defaultTheme,\n value,\n attrs,\n skipNextHead,\n }: {\n forcedTheme?: string\n storageKey: string\n attribute?: string\n enableSystem?: boolean\n defaultTheme: string\n value?: ValueObject\n attrs: any\n skipNextHead\n }) => {\n // Code-golfing the amount of characters in the script\n const optimization = (() => {\n if (attribute === 'class') {\n const removeClasses = attrs.map((t: string) => `d.remove('${t}')`).join(';')\n return `var d=document.documentElement.classList;${removeClasses};`\n } else {\n return `var d=document.documentElement;`\n }\n })()\n\n const updateDOM = (name: string, literal?: boolean) => {\n name = value?.[name] || name\n const val = literal ? name : `'${name}'`\n\n if (attribute === 'class') {\n return `d.add(${val})`\n }\n\n return `d.setAttribute('${attribute}', ${val})`\n }\n\n const defaultSystem = defaultTheme === 'system'\n\n const contents = (\n <>\n {forcedTheme ? (\n <script\n key=\"next-themes-script\"\n dangerouslySetInnerHTML={{\n // These are minified via Terser and then updated by hand, don't recommend\n __html: `!function(){${optimization}${updateDOM(forcedTheme)}}()`,\n }}\n />\n ) : enableSystem ? (\n <script\n key=\"next-themes-script\"\n dangerouslySetInnerHTML={{\n __html: `!function(){try {${optimization}var e=localStorage.getItem('${storageKey}');${\n !defaultSystem ? updateDOM(defaultTheme) + ';' : ''\n }if(\"system\"===e||(!e&&${defaultSystem})){var t=\"${MEDIA}\",m=window.matchMedia(t);m.media!==t||m.matches?${updateDOM(\n 'dark'\n )}:${updateDOM('light')}}else if(e) ${\n value ? `var x=${JSON.stringify(value)};` : ''\n }${updateDOM(value ? 'x[e]' : 'e', true)}}catch(e){}}()`,\n }}\n />\n ) : (\n <script\n key=\"next-themes-script\"\n dangerouslySetInnerHTML={{\n __html: `!function(){try{${optimization}var e=localStorage.getItem(\"${storageKey}\");if(e){${\n value ? `var x=${JSON.stringify(value)};` : ''\n }${updateDOM(value ? 'x[e]' : 'e', true)}}else{${updateDOM(\n defaultTheme\n )};}}catch(t){}}();`,\n }}\n />\n )}\n </>\n )\n\n if (skipNextHead) return contents\n\n return <NextHead>{contents}</NextHead>\n },\n (prevProps, nextProps) => {\n // Only re-render when forcedTheme changes\n // the rest of the props should be completely stable\n if (prevProps.forcedTheme !== nextProps.forcedTheme) return false\n return true\n }\n)\n\n// Helpers\nconst getTheme = (key: string, fallback?: string) => {\n if (typeof window === 'undefined') return undefined\n let theme\n try {\n theme = localStorage.getItem(key) || undefined\n } catch (e) {\n // Unsupported\n }\n return theme || fallback\n}\n\nconst getSystemTheme = (e?: MediaQueryList) => {\n if (!e) {\n e = window.matchMedia(MEDIA)\n }\n\n const isDark = e.matches\n const systemTheme = isDark ? 'dark' : 'light'\n return systemTheme\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["systemTheme", "theme", "value"]
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tamagui/next-theme",
3
- "version": "1.0.16",
3
+ "version": "1.0.18",
4
4
  "sideEffects": false,
5
5
  "source": "src/index.ts",
6
6
  "types": "./types/index.d.ts",
@@ -16,13 +16,13 @@
16
16
  "watch": "tamagui-build --watch"
17
17
  },
18
18
  "dependencies": {
19
- "@tamagui/use-event": "^1.0.16"
19
+ "@tamagui/use-event": "^1.0.18"
20
20
  },
21
21
  "peerDependencies": {
22
22
  "react": "*"
23
23
  },
24
24
  "devDependencies": {
25
- "@tamagui/build": "^1.0.16",
25
+ "@tamagui/build": "^1.0.18",
26
26
  "react": "^18.2.0"
27
27
  },
28
28
  "publishConfig": {
package/src/NextTheme.tsx CHANGED
@@ -2,6 +2,7 @@
2
2
  // forked temporarily due to buggy theme change
3
3
 
4
4
  import { useEvent } from '@tamagui/use-event'
5
+ import NextHead from 'next/head'
5
6
  import * as React from 'react'
6
7
  import {
7
8
  createContext,
@@ -57,17 +58,24 @@ export interface ThemeProviderProps {
57
58
  /** Mapping of theme name to HTML attribute value. Object where key is the theme name and value is the attribute value */
58
59
  value?: ValueObject
59
60
  onChangeTheme?: (name: string) => void
60
- nonce?: string
61
+
62
+ // avoids warning
63
+
64
+ skipNextHead?: boolean
61
65
  }
62
66
 
63
- const ThemeContext = createContext<UseThemeProps | null>(null)
67
+ const ThemeSettingContext = createContext<UseThemeProps>({
68
+ toggle: () => {},
69
+ set: (_) => {},
70
+ themes: [],
71
+ })
64
72
 
65
73
  /**
66
74
  * @deprecated renamed to `useThemeSetting` to avoid confusion with core `useTheme` hook
67
75
  */
68
- export const useTheme = () => useContext(ThemeContext)
76
+ export const useTheme = () => useContext(ThemeSettingContext)
69
77
 
70
- export const useThemeSetting = () => useContext(ThemeContext)
78
+ export const useThemeSetting = () => useContext(ThemeSettingContext)
71
79
 
72
80
  const colorSchemes = ['light', 'dark']
73
81
  const MEDIA = '(prefers-color-scheme: dark)'
@@ -94,17 +102,7 @@ export const useRootTheme = () => {
94
102
  return [val, setVal] as const
95
103
  }
96
104
 
97
- export const NextThemeProvider: React.FC<ThemeProviderProps> = (props) => {
98
- const context = useContext(ThemeContext)
99
- // Ignore nested context providers, just passthrough children
100
- if (context) {
101
- return <>{props.children}</>
102
- }
103
- return <Theme {...props} />
104
- }
105
-
106
- export const Theme: React.FC<ThemeProviderProps> = ({
107
- nonce,
105
+ export const NextThemeProvider: React.FC<ThemeProviderProps> = ({
108
106
  forcedTheme,
109
107
  disableTransitionOnChange = true,
110
108
  enableSystem = true,
@@ -113,6 +111,7 @@ export const Theme: React.FC<ThemeProviderProps> = ({
113
111
  themes = colorSchemes,
114
112
  defaultTheme = enableSystem ? 'system' : 'light',
115
113
  attribute = 'class',
114
+ skipNextHead,
116
115
  onChangeTheme,
117
116
  value = {
118
117
  dark: 't_dark',
@@ -274,26 +273,23 @@ export const Theme: React.FC<ThemeProviderProps> = ({
274
273
  ])
275
274
 
276
275
  return (
277
- <ThemeContext.Provider value={contextValue}>
276
+ <ThemeSettingContext.Provider value={contextValue}>
278
277
  <ThemeScript
279
278
  {...{
280
279
  forcedTheme,
281
- disableTransitionOnChange,
282
280
  storageKey,
283
281
  systemTheme: resolvedTheme,
284
282
  attribute,
285
- enableColorScheme,
286
283
  value,
287
- themes,
288
284
  enableSystem,
289
285
  defaultTheme,
290
286
  attrs,
291
- nonce,
287
+ skipNextHead,
292
288
  }}
293
289
  />
294
290
  {/* because on SSR we re-run and can avoid whole tree re-render */}
295
291
  {useMemo(() => children, [children])}
296
- </ThemeContext.Provider>
292
+ </ThemeSettingContext.Provider>
297
293
  )
298
294
  }
299
295
 
@@ -303,99 +299,91 @@ const ThemeScript = memo(
303
299
  storageKey,
304
300
  attribute,
305
301
  enableSystem,
306
- enableColorScheme,
307
302
  defaultTheme,
308
303
  value,
309
304
  attrs,
310
- nonce,
311
- }: ThemeProviderProps & { attrs: string[]; defaultTheme: string }) => {
312
- const defaultSystem = defaultTheme === 'system'
313
-
305
+ skipNextHead,
306
+ }: {
307
+ forcedTheme?: string
308
+ storageKey: string
309
+ attribute?: string
310
+ enableSystem?: boolean
311
+ defaultTheme: string
312
+ value?: ValueObject
313
+ attrs: any
314
+ skipNextHead
315
+ }) => {
314
316
  // Code-golfing the amount of characters in the script
315
317
  const optimization = (() => {
316
318
  if (attribute === 'class') {
317
- const removeClasses = `c.remove(${attrs.map((t: string) => `'${t}'`).join(',')})`
318
-
319
- return `var d=document.documentElement,c=d.classList;${removeClasses};`
320
- } else {
321
- return `var d=document.documentElement,n='${attribute}',s='setAttribute';`
322
- }
323
- })()
324
-
325
- const fallbackColorScheme = (() => {
326
- if (!enableColorScheme) {
327
- return ''
328
- }
329
-
330
- const fallback = colorSchemes.includes(defaultTheme) ? defaultTheme : null
331
-
332
- if (fallback) {
333
- return `if(e==='light'||e==='dark'||!e)d.style.colorScheme=e||'${defaultTheme}'`
319
+ const removeClasses = attrs.map((t: string) => `d.remove('${t}')`).join(';')
320
+ return `var d=document.documentElement.classList;${removeClasses};`
334
321
  } else {
335
- return `if(e==='light'||e==='dark')d.style.colorScheme=e`
322
+ return `var d=document.documentElement;`
336
323
  }
337
324
  })()
338
325
 
339
- const updateDOM = (name: string, literal: boolean = false, setColorScheme = true) => {
340
- const resolvedName = value ? value[name] : name
341
- const val = literal ? name + `|| ''` : `'${resolvedName}'`
342
- let text = ''
343
-
344
- // MUCH faster to set colorScheme alongside HTML attribute/class
345
- // as it only incurs 1 style recalculation rather than 2
346
- // This can save over 250ms of work for pages with big DOM
347
- if (
348
- enableColorScheme &&
349
- setColorScheme &&
350
- !literal &&
351
- colorSchemes.includes(name)
352
- ) {
353
- text += `d.style.colorScheme = '${name}';`
354
- }
326
+ const updateDOM = (name: string, literal?: boolean) => {
327
+ name = value?.[name] || name
328
+ const val = literal ? name : `'${name}'`
355
329
 
356
330
  if (attribute === 'class') {
357
- if (literal || resolvedName) {
358
- text += `c.add(${val})`
359
- } else {
360
- text += `null`
361
- }
362
- } else {
363
- if (resolvedName) {
364
- text += `d[s](n,${val})`
365
- }
331
+ return `d.add(${val})`
366
332
  }
367
333
 
368
- return text
334
+ return `d.setAttribute('${attribute}', ${val})`
369
335
  }
370
336
 
371
- const scriptSrc = (() => {
372
- if (forcedTheme) {
373
- return `!function(){${optimization}${updateDOM(forcedTheme)}}()`
374
- }
375
-
376
- if (enableSystem) {
377
- return `!function(){try{${optimization}var e=localStorage.getItem('${storageKey}');if('system'===e||(!e&&${defaultSystem})){var t='${MEDIA}',m=window.matchMedia(t);if(m.media!==t||m.matches){${updateDOM(
378
- 'dark'
379
- )}}else{${updateDOM('light')}}}else if(e){${
380
- value ? `var x=${JSON.stringify(value)};` : ''
381
- }${updateDOM(value ? `x[e]` : 'e', true)}}${
382
- !defaultSystem ? `else{` + updateDOM(defaultTheme, false, false) + '}' : ''
383
- }${fallbackColorScheme}}catch(e){}}()`
384
- }
385
-
386
- return `!function(){try{${optimization}var e=localStorage.getItem('${storageKey}');if(e){${
387
- value ? `var x=${JSON.stringify(value)};` : ''
388
- }${updateDOM(value ? `x[e]` : 'e', true)}}else{${updateDOM(
389
- defaultTheme,
390
- false,
391
- false
392
- )};}${fallbackColorScheme}}catch(t){}}();`
393
- })()
337
+ const defaultSystem = defaultTheme === 'system'
394
338
 
395
- return <script nonce={nonce} dangerouslySetInnerHTML={{ __html: scriptSrc }} />
339
+ const contents = (
340
+ <>
341
+ {forcedTheme ? (
342
+ <script
343
+ key="next-themes-script"
344
+ dangerouslySetInnerHTML={{
345
+ // These are minified via Terser and then updated by hand, don't recommend
346
+ __html: `!function(){${optimization}${updateDOM(forcedTheme)}}()`,
347
+ }}
348
+ />
349
+ ) : enableSystem ? (
350
+ <script
351
+ key="next-themes-script"
352
+ dangerouslySetInnerHTML={{
353
+ __html: `!function(){try {${optimization}var e=localStorage.getItem('${storageKey}');${
354
+ !defaultSystem ? updateDOM(defaultTheme) + ';' : ''
355
+ }if("system"===e||(!e&&${defaultSystem})){var t="${MEDIA}",m=window.matchMedia(t);m.media!==t||m.matches?${updateDOM(
356
+ 'dark'
357
+ )}:${updateDOM('light')}}else if(e) ${
358
+ value ? `var x=${JSON.stringify(value)};` : ''
359
+ }${updateDOM(value ? 'x[e]' : 'e', true)}}catch(e){}}()`,
360
+ }}
361
+ />
362
+ ) : (
363
+ <script
364
+ key="next-themes-script"
365
+ dangerouslySetInnerHTML={{
366
+ __html: `!function(){try{${optimization}var e=localStorage.getItem("${storageKey}");if(e){${
367
+ value ? `var x=${JSON.stringify(value)};` : ''
368
+ }${updateDOM(value ? 'x[e]' : 'e', true)}}else{${updateDOM(
369
+ defaultTheme
370
+ )};}}catch(t){}}();`,
371
+ }}
372
+ />
373
+ )}
374
+ </>
375
+ )
376
+
377
+ if (skipNextHead) return contents
378
+
379
+ return <NextHead>{contents}</NextHead>
396
380
  },
397
- // Never re-render this component
398
- () => true
381
+ (prevProps, nextProps) => {
382
+ // Only re-render when forcedTheme changes
383
+ // the rest of the props should be completely stable
384
+ if (prevProps.forcedTheme !== nextProps.forcedTheme) return false
385
+ return true
386
+ }
399
387
  )
400
388
 
401
389
  // Helpers
@@ -38,18 +38,17 @@ export interface ThemeProviderProps {
38
38
  /** Mapping of theme name to HTML attribute value. Object where key is the theme name and value is the attribute value */
39
39
  value?: ValueObject;
40
40
  onChangeTheme?: (name: string) => void;
41
- nonce?: string;
41
+ skipNextHead?: boolean;
42
42
  }
43
43
  /**
44
44
  * @deprecated renamed to `useThemeSetting` to avoid confusion with core `useTheme` hook
45
45
  */
46
- export declare const useTheme: () => UseThemeProps | null;
47
- export declare const useThemeSetting: () => UseThemeProps | null;
46
+ export declare const useTheme: () => UseThemeProps;
47
+ export declare const useThemeSetting: () => UseThemeProps;
48
48
  interface ValueObject {
49
49
  [themeName: string]: string;
50
50
  }
51
51
  export declare const useRootTheme: () => readonly [string, React.Dispatch<React.SetStateAction<string>>];
52
52
  export declare const NextThemeProvider: React.FC<ThemeProviderProps>;
53
- export declare const Theme: React.FC<ThemeProviderProps>;
54
53
  export {};
55
54
  //# sourceMappingURL=NextTheme.d.ts.map