@tamagui/next-theme 1.0.9 → 1.0.11

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,6 +25,7 @@ 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,
28
29
  useRootTheme: () => useRootTheme,
29
30
  useTheme: () => useTheme,
30
31
  useThemeSetting: () => useThemeSetting
@@ -32,19 +33,12 @@ __export(NextTheme_exports, {
32
33
  module.exports = __toCommonJS(NextTheme_exports);
33
34
  var import_jsx_runtime = require("react/jsx-runtime");
34
35
  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 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);
39
+ const ThemeContext = (0, import_react.createContext)(null);
40
+ const useTheme = () => (0, import_react.useContext)(ThemeContext);
41
+ const useThemeSetting = () => (0, import_react.useContext)(ThemeContext);
48
42
  const colorSchemes = ["light", "dark"];
49
43
  const MEDIA = "(prefers-color-scheme: dark)";
50
44
  const useRootTheme = () => {
@@ -60,7 +54,19 @@ const useRootTheme = () => {
60
54
  }
61
55
  return [val, setVal];
62
56
  };
63
- const NextThemeProvider = ({
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,
64
70
  forcedTheme,
65
71
  disableTransitionOnChange = true,
66
72
  enableSystem = true,
@@ -90,31 +96,29 @@ const NextThemeProvider = ({
90
96
  });
91
97
  const mediaListener = (0, import_react.useRef)(handleMediaQuery);
92
98
  mediaListener.current = handleMediaQuery;
93
- const handleChangeTheme = (0, import_use_event.useEvent)(
94
- (theme2, updateStorage = true, updateDOM = true) => {
95
- let name = (value == null ? void 0 : value[theme2]) || theme2;
96
- if (updateStorage) {
97
- try {
98
- localStorage.setItem(storageKey, theme2);
99
- } catch (e) {
100
- }
101
- }
102
- if (theme2 === "system" && enableSystem) {
103
- const resolved = getSystemTheme();
104
- name = (value == null ? void 0 : value[resolved]) || resolved;
99
+ const handleChangeTheme = (0, import_use_event.useEvent)((theme2, updateStorage = true, updateDOM = true) => {
100
+ let name = (value == null ? void 0 : value[theme2]) || theme2;
101
+ if (updateStorage) {
102
+ try {
103
+ localStorage.setItem(storageKey, theme2);
104
+ } catch (e) {
105
105
  }
106
- onChangeTheme == null ? void 0 : onChangeTheme(name.replace("t_", ""));
107
- if (updateDOM) {
108
- const d = document.documentElement;
109
- if (attribute === "class") {
110
- d.classList.remove(...attrs);
111
- d.classList.add(name);
112
- } else {
113
- d.setAttribute(attribute, name);
114
- }
106
+ }
107
+ if (theme2 === "system" && enableSystem) {
108
+ const resolved = getSystemTheme();
109
+ name = (value == null ? void 0 : value[resolved]) || resolved;
110
+ }
111
+ onChangeTheme == null ? void 0 : onChangeTheme(name.replace("t_", ""));
112
+ if (updateDOM) {
113
+ const d = document.documentElement;
114
+ if (attribute === "class") {
115
+ d.classList.remove(...attrs);
116
+ d.classList.add(name);
117
+ } else {
118
+ d.setAttribute(attribute, name);
115
119
  }
116
120
  }
117
- );
121
+ });
118
122
  useIsomorphicLayoutEffect(() => {
119
123
  const handler = (...args) => mediaListener.current(...args);
120
124
  const media = window.matchMedia(MEDIA);
@@ -184,19 +188,23 @@ const NextThemeProvider = ({
184
188
  themes,
185
189
  systemTheme
186
190
  ]);
187
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(ThemeSettingContext.Provider, {
191
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(ThemeContext.Provider, {
188
192
  value: contextValue,
189
193
  children: [
190
194
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ThemeScript, {
191
195
  ...{
192
196
  forcedTheme,
197
+ disableTransitionOnChange,
193
198
  storageKey,
194
199
  systemTheme: resolvedTheme,
195
200
  attribute,
201
+ enableColorScheme,
196
202
  value,
203
+ themes,
197
204
  enableSystem,
198
205
  defaultTheme,
199
- attrs
206
+ attrs,
207
+ nonce
200
208
  }
201
209
  }),
202
210
  (0, import_react.useMemo)(() => children, [children])
@@ -209,52 +217,73 @@ const ThemeScript = (0, import_react.memo)(
209
217
  storageKey,
210
218
  attribute,
211
219
  enableSystem,
220
+ enableColorScheme,
212
221
  defaultTheme,
213
222
  value,
214
- attrs
223
+ attrs,
224
+ nonce
215
225
  }) => {
226
+ const defaultSystem = defaultTheme === "system";
216
227
  const optimization = (() => {
217
228
  if (attribute === "class") {
218
- const removeClasses = attrs.map((t) => `d.remove('${t}')`).join(";");
219
- return `var d=document.documentElement.classList;${removeClasses};`;
229
+ const removeClasses = `c.remove(${attrs.map((t) => `'${t}'`).join(",")})`;
230
+ return `var d=document.documentElement,c=d.classList;${removeClasses};`;
220
231
  } else {
221
- return `var d=document.documentElement;`;
232
+ return `var d=document.documentElement,n='${attribute}',s='setAttribute';`;
222
233
  }
223
234
  })();
224
- const updateDOM = (name, literal) => {
225
- name = (value == null ? void 0 : value[name]) || name;
226
- const val = literal ? name : `'${name}'`;
227
- if (attribute === "class") {
228
- return `d.add(${val})`;
235
+ const fallbackColorScheme = (() => {
236
+ if (!enableColorScheme) {
237
+ return "";
229
238
  }
230
- return `d.setAttribute('${attribute}', ${val})`;
231
- };
232
- const defaultSystem = defaultTheme === "system";
233
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_head.default, {
234
- children: forcedTheme ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("script", {
235
- dangerouslySetInnerHTML: {
236
- __html: `!function(){${optimization}${updateDOM(forcedTheme)}}()`
237
- }
238
- }, "next-themes-script") : enableSystem ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("script", {
239
- dangerouslySetInnerHTML: {
240
- __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(
241
- "dark"
242
- )}:${updateDOM("light")}}else if(e) ${value ? `var x=${JSON.stringify(value)};` : ""}${updateDOM(value ? "x[e]" : "e", true)}}catch(e){}}()`
239
+ const fallback = colorSchemes.includes(defaultTheme) ? defaultTheme : null;
240
+ if (fallback) {
241
+ return `if(e==='light'||e==='dark'||!e)d.style.colorScheme=e||'${defaultTheme}'`;
242
+ } else {
243
+ return `if(e==='light'||e==='dark')d.style.colorScheme=e`;
244
+ }
245
+ })();
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
+ }
253
+ if (attribute === "class") {
254
+ if (literal || resolvedName) {
255
+ text += `c.add(${val})`;
256
+ } else {
257
+ text += `null`;
243
258
  }
244
- }, "next-themes-script") : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("script", {
245
- dangerouslySetInnerHTML: {
246
- __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(
247
- defaultTheme
248
- )};}}catch(t){}}();`
259
+ } else {
260
+ if (resolvedName) {
261
+ text += `d[s](n,${val})`;
249
262
  }
250
- }, "next-themes-script")
263
+ }
264
+ return text;
265
+ };
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 }
251
284
  });
252
285
  },
253
- (prevProps, nextProps) => {
254
- if (prevProps.forcedTheme !== nextProps.forcedTheme)
255
- return false;
256
- return true;
257
- }
286
+ () => true
258
287
  );
259
288
  const getTheme = (key, fallback) => {
260
289
  if (typeof window === "undefined")
@@ -277,6 +306,7 @@ const getSystemTheme = (e) => {
277
306
  // Annotate the CommonJS export names for ESM import in node:
278
307
  0 && (module.exports = {
279
308
  NextThemeProvider,
309
+ Theme,
280
310
  useRootTheme,
281
311
  useTheme,
282
312
  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 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\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 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(\n (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\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'\n ? ['system', 'light', 'dark']\n : ['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 }}\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 }: {\n forcedTheme?: string\n storageKey: string\n attribute?: string\n enableSystem?: boolean\n defaultTheme: string\n value?: ValueObject\n attrs: any\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 return (\n <NextHead>\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 </NextHead>\n )\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"]
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"]
7
7
  }
@@ -1,6 +1,5 @@
1
- import { jsx, jsxs } from "react/jsx-runtime";
1
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
2
  import { useEvent } from "@tamagui/use-event";
3
- import NextHead from "next/head";
4
3
  import * as React from "react";
5
4
  import {
6
5
  createContext,
@@ -13,15 +12,9 @@ import {
13
12
  useState
14
13
  } from "react";
15
14
  const useIsomorphicLayoutEffect = typeof window !== "undefined" ? useLayoutEffect : useEffect;
16
- const ThemeSettingContext = createContext({
17
- toggle: () => {
18
- },
19
- set: (_) => {
20
- },
21
- themes: []
22
- });
23
- const useTheme = () => useContext(ThemeSettingContext);
24
- const useThemeSetting = () => useContext(ThemeSettingContext);
15
+ const ThemeContext = createContext(null);
16
+ const useTheme = () => useContext(ThemeContext);
17
+ const useThemeSetting = () => useContext(ThemeContext);
25
18
  const colorSchemes = ["light", "dark"];
26
19
  const MEDIA = "(prefers-color-scheme: dark)";
27
20
  const useRootTheme = () => {
@@ -37,7 +30,19 @@ const useRootTheme = () => {
37
30
  }
38
31
  return [val, setVal];
39
32
  };
40
- const NextThemeProvider = ({
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,
41
46
  forcedTheme,
42
47
  disableTransitionOnChange = true,
43
48
  enableSystem = true,
@@ -67,31 +72,29 @@ const NextThemeProvider = ({
67
72
  });
68
73
  const mediaListener = useRef(handleMediaQuery);
69
74
  mediaListener.current = handleMediaQuery;
70
- const handleChangeTheme = useEvent(
71
- (theme2, updateStorage = true, updateDOM = true) => {
72
- let name = (value == null ? void 0 : value[theme2]) || theme2;
73
- if (updateStorage) {
74
- try {
75
- localStorage.setItem(storageKey, theme2);
76
- } catch (e) {
77
- }
75
+ const handleChangeTheme = useEvent((theme2, updateStorage = true, updateDOM = true) => {
76
+ let name = (value == null ? void 0 : value[theme2]) || theme2;
77
+ if (updateStorage) {
78
+ try {
79
+ localStorage.setItem(storageKey, theme2);
80
+ } catch (e) {
78
81
  }
79
- if (theme2 === "system" && enableSystem) {
80
- const resolved = getSystemTheme();
81
- name = (value == null ? void 0 : value[resolved]) || resolved;
82
- }
83
- onChangeTheme == null ? void 0 : onChangeTheme(name.replace("t_", ""));
84
- if (updateDOM) {
85
- const d = document.documentElement;
86
- if (attribute === "class") {
87
- d.classList.remove(...attrs);
88
- d.classList.add(name);
89
- } else {
90
- d.setAttribute(attribute, name);
91
- }
82
+ }
83
+ if (theme2 === "system" && enableSystem) {
84
+ const resolved = getSystemTheme();
85
+ name = (value == null ? void 0 : value[resolved]) || resolved;
86
+ }
87
+ onChangeTheme == null ? void 0 : onChangeTheme(name.replace("t_", ""));
88
+ if (updateDOM) {
89
+ const d = document.documentElement;
90
+ if (attribute === "class") {
91
+ d.classList.remove(...attrs);
92
+ d.classList.add(name);
93
+ } else {
94
+ d.setAttribute(attribute, name);
92
95
  }
93
96
  }
94
- );
97
+ });
95
98
  useIsomorphicLayoutEffect(() => {
96
99
  const handler = (...args) => mediaListener.current(...args);
97
100
  const media = window.matchMedia(MEDIA);
@@ -161,19 +164,23 @@ const NextThemeProvider = ({
161
164
  themes,
162
165
  systemTheme
163
166
  ]);
164
- return /* @__PURE__ */ jsxs(ThemeSettingContext.Provider, {
167
+ return /* @__PURE__ */ jsxs(ThemeContext.Provider, {
165
168
  value: contextValue,
166
169
  children: [
167
170
  /* @__PURE__ */ jsx(ThemeScript, {
168
171
  ...{
169
172
  forcedTheme,
173
+ disableTransitionOnChange,
170
174
  storageKey,
171
175
  systemTheme: resolvedTheme,
172
176
  attribute,
177
+ enableColorScheme,
173
178
  value,
179
+ themes,
174
180
  enableSystem,
175
181
  defaultTheme,
176
- attrs
182
+ attrs,
183
+ nonce
177
184
  }
178
185
  }),
179
186
  useMemo(() => children, [children])
@@ -186,52 +193,73 @@ const ThemeScript = memo(
186
193
  storageKey,
187
194
  attribute,
188
195
  enableSystem,
196
+ enableColorScheme,
189
197
  defaultTheme,
190
198
  value,
191
- attrs
199
+ attrs,
200
+ nonce
192
201
  }) => {
202
+ const defaultSystem = defaultTheme === "system";
193
203
  const optimization = (() => {
194
204
  if (attribute === "class") {
195
- const removeClasses = attrs.map((t) => `d.remove('${t}')`).join(";");
196
- return `var d=document.documentElement.classList;${removeClasses};`;
205
+ const removeClasses = `c.remove(${attrs.map((t) => `'${t}'`).join(",")})`;
206
+ return `var d=document.documentElement,c=d.classList;${removeClasses};`;
197
207
  } else {
198
- return `var d=document.documentElement;`;
208
+ return `var d=document.documentElement,n='${attribute}',s='setAttribute';`;
199
209
  }
200
210
  })();
201
- const updateDOM = (name, literal) => {
202
- name = (value == null ? void 0 : value[name]) || name;
203
- const val = literal ? name : `'${name}'`;
204
- if (attribute === "class") {
205
- return `d.add(${val})`;
211
+ const fallbackColorScheme = (() => {
212
+ if (!enableColorScheme) {
213
+ return "";
206
214
  }
207
- return `d.setAttribute('${attribute}', ${val})`;
208
- };
209
- const defaultSystem = defaultTheme === "system";
210
- return /* @__PURE__ */ jsx(NextHead, {
211
- children: forcedTheme ? /* @__PURE__ */ jsx("script", {
212
- dangerouslySetInnerHTML: {
213
- __html: `!function(){${optimization}${updateDOM(forcedTheme)}}()`
214
- }
215
- }, "next-themes-script") : enableSystem ? /* @__PURE__ */ jsx("script", {
216
- dangerouslySetInnerHTML: {
217
- __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(
218
- "dark"
219
- )}:${updateDOM("light")}}else if(e) ${value ? `var x=${JSON.stringify(value)};` : ""}${updateDOM(value ? "x[e]" : "e", true)}}catch(e){}}()`
215
+ const fallback = colorSchemes.includes(defaultTheme) ? defaultTheme : null;
216
+ if (fallback) {
217
+ return `if(e==='light'||e==='dark'||!e)d.style.colorScheme=e||'${defaultTheme}'`;
218
+ } else {
219
+ return `if(e==='light'||e==='dark')d.style.colorScheme=e`;
220
+ }
221
+ })();
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
+ }
229
+ if (attribute === "class") {
230
+ if (literal || resolvedName) {
231
+ text += `c.add(${val})`;
232
+ } else {
233
+ text += `null`;
220
234
  }
221
- }, "next-themes-script") : /* @__PURE__ */ jsx("script", {
222
- dangerouslySetInnerHTML: {
223
- __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(
224
- defaultTheme
225
- )};}}catch(t){}}();`
235
+ } else {
236
+ if (resolvedName) {
237
+ text += `d[s](n,${val})`;
226
238
  }
227
- }, "next-themes-script")
239
+ }
240
+ return text;
241
+ };
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 }
228
260
  });
229
261
  },
230
- (prevProps, nextProps) => {
231
- if (prevProps.forcedTheme !== nextProps.forcedTheme)
232
- return false;
233
- return true;
234
- }
262
+ () => true
235
263
  );
236
264
  const getTheme = (key, fallback) => {
237
265
  if (typeof window === "undefined")
@@ -253,6 +281,7 @@ const getSystemTheme = (e) => {
253
281
  };
254
282
  export {
255
283
  NextThemeProvider,
284
+ Theme,
256
285
  useRootTheme,
257
286
  useTheme,
258
287
  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 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\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 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(\n (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\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'\n ? ['system', 'light', 'dark']\n : ['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 }}\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 }: {\n forcedTheme?: string\n storageKey: string\n attribute?: string\n enableSystem?: boolean\n defaultTheme: string\n value?: ValueObject\n attrs: any\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 return (\n <NextHead>\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 </NextHead>\n )\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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",
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
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.9",
3
+ "version": "1.0.11",
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.9"
19
+ "@tamagui/use-event": "^1.0.11"
20
20
  },
21
21
  "peerDependencies": {
22
22
  "react": "*"
23
23
  },
24
24
  "devDependencies": {
25
- "@tamagui/build": "^1.0.9",
25
+ "@tamagui/build": "^1.0.11",
26
26
  "react": "^18.2.0"
27
27
  },
28
28
  "publishConfig": {
package/src/NextTheme.tsx CHANGED
@@ -2,7 +2,6 @@
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'
6
5
  import * as React from 'react'
7
6
  import {
8
7
  createContext,
@@ -58,20 +57,17 @@ export interface ThemeProviderProps {
58
57
  /** Mapping of theme name to HTML attribute value. Object where key is the theme name and value is the attribute value */
59
58
  value?: ValueObject
60
59
  onChangeTheme?: (name: string) => void
60
+ nonce?: string
61
61
  }
62
62
 
63
- const ThemeSettingContext = createContext<UseThemeProps>({
64
- toggle: () => {},
65
- set: (_) => {},
66
- themes: [],
67
- })
63
+ const ThemeContext = createContext<UseThemeProps | null>(null)
68
64
 
69
65
  /**
70
66
  * @deprecated renamed to `useThemeSetting` to avoid confusion with core `useTheme` hook
71
67
  */
72
- export const useTheme = () => useContext(ThemeSettingContext)
68
+ export const useTheme = () => useContext(ThemeContext)
73
69
 
74
- export const useThemeSetting = () => useContext(ThemeSettingContext)
70
+ export const useThemeSetting = () => useContext(ThemeContext)
75
71
 
76
72
  const colorSchemes = ['light', 'dark']
77
73
  const MEDIA = '(prefers-color-scheme: dark)'
@@ -98,7 +94,17 @@ export const useRootTheme = () => {
98
94
  return [val, setVal] as const
99
95
  }
100
96
 
101
- export const NextThemeProvider: React.FC<ThemeProviderProps> = ({
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,
102
108
  forcedTheme,
103
109
  disableTransitionOnChange = true,
104
110
  enableSystem = true,
@@ -133,36 +139,34 @@ export const NextThemeProvider: React.FC<ThemeProviderProps> = ({
133
139
  const mediaListener = useRef(handleMediaQuery)
134
140
  mediaListener.current = handleMediaQuery
135
141
 
136
- const handleChangeTheme = useEvent(
137
- (theme, updateStorage = true, updateDOM = true) => {
138
- let name = value?.[theme] || theme
142
+ const handleChangeTheme = useEvent((theme, updateStorage = true, updateDOM = true) => {
143
+ let name = value?.[theme] || theme
139
144
 
140
- if (updateStorage) {
141
- try {
142
- localStorage.setItem(storageKey, theme)
143
- } catch (e) {
144
- // Unsupported
145
- }
145
+ if (updateStorage) {
146
+ try {
147
+ localStorage.setItem(storageKey, theme)
148
+ } catch (e) {
149
+ // Unsupported
146
150
  }
151
+ }
147
152
 
148
- if (theme === 'system' && enableSystem) {
149
- const resolved = getSystemTheme()
150
- name = value?.[resolved] || resolved
151
- }
153
+ if (theme === 'system' && enableSystem) {
154
+ const resolved = getSystemTheme()
155
+ name = value?.[resolved] || resolved
156
+ }
152
157
 
153
- onChangeTheme?.(name.replace('t_', ''))
158
+ onChangeTheme?.(name.replace('t_', ''))
154
159
 
155
- if (updateDOM) {
156
- const d = document.documentElement
157
- if (attribute === 'class') {
158
- d.classList.remove(...attrs)
159
- d.classList.add(name)
160
- } else {
161
- d.setAttribute(attribute, name)
162
- }
160
+ if (updateDOM) {
161
+ const d = document.documentElement
162
+ if (attribute === 'class') {
163
+ d.classList.remove(...attrs)
164
+ d.classList.add(name)
165
+ } else {
166
+ d.setAttribute(attribute, name)
163
167
  }
164
- },
165
- )
168
+ }
169
+ })
166
170
 
167
171
  useIsomorphicLayoutEffect(() => {
168
172
  const handler = (...args: any) => mediaListener.current(...args)
@@ -236,9 +240,7 @@ export const NextThemeProvider: React.FC<ThemeProviderProps> = ({
236
240
 
237
241
  const toggle = useEvent(() => {
238
242
  const order =
239
- resolvedTheme === 'dark'
240
- ? ['system', 'light', 'dark']
241
- : ['system', 'dark', 'light']
243
+ resolvedTheme === 'dark' ? ['system', 'light', 'dark'] : ['system', 'dark', 'light']
242
244
  const next = order[(order.indexOf(theme) + 1) % order.length]
243
245
  set(next)
244
246
  })
@@ -272,22 +274,26 @@ export const NextThemeProvider: React.FC<ThemeProviderProps> = ({
272
274
  ])
273
275
 
274
276
  return (
275
- <ThemeSettingContext.Provider value={contextValue}>
277
+ <ThemeContext.Provider value={contextValue}>
276
278
  <ThemeScript
277
279
  {...{
278
280
  forcedTheme,
281
+ disableTransitionOnChange,
279
282
  storageKey,
280
283
  systemTheme: resolvedTheme,
281
284
  attribute,
285
+ enableColorScheme,
282
286
  value,
287
+ themes,
283
288
  enableSystem,
284
289
  defaultTheme,
285
290
  attrs,
291
+ nonce,
286
292
  }}
287
293
  />
288
294
  {/* because on SSR we re-run and can avoid whole tree re-render */}
289
295
  {useMemo(() => children, [children])}
290
- </ThemeSettingContext.Provider>
296
+ </ThemeContext.Provider>
291
297
  )
292
298
  }
293
299
 
@@ -297,85 +303,99 @@ const ThemeScript = memo(
297
303
  storageKey,
298
304
  attribute,
299
305
  enableSystem,
306
+ enableColorScheme,
300
307
  defaultTheme,
301
308
  value,
302
309
  attrs,
303
- }: {
304
- forcedTheme?: string
305
- storageKey: string
306
- attribute?: string
307
- enableSystem?: boolean
308
- defaultTheme: string
309
- value?: ValueObject
310
- attrs: any
311
- }) => {
310
+ nonce,
311
+ }: ThemeProviderProps & { attrs: string[]; defaultTheme: string }) => {
312
+ const defaultSystem = defaultTheme === 'system'
313
+
312
314
  // Code-golfing the amount of characters in the script
313
315
  const optimization = (() => {
314
316
  if (attribute === 'class') {
315
- const removeClasses = attrs.map((t: string) => `d.remove('${t}')`).join(';')
316
- return `var d=document.documentElement.classList;${removeClasses};`
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}'`
317
334
  } else {
318
- return `var d=document.documentElement;`
335
+ return `if(e==='light'||e==='dark')d.style.colorScheme=e`
319
336
  }
320
337
  })()
321
338
 
322
- const updateDOM = (name: string, literal?: boolean) => {
323
- name = value?.[name] || name
324
- const val = literal ? name : `'${name}'`
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
+ }
325
355
 
326
356
  if (attribute === 'class') {
327
- return `d.add(${val})`
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
+ }
328
366
  }
329
367
 
330
- return `d.setAttribute('${attribute}', ${val})`
368
+ return text
331
369
  }
332
370
 
333
- const defaultSystem = defaultTheme === 'system'
371
+ const scriptSrc = (() => {
372
+ if (forcedTheme) {
373
+ return `!function(){${optimization}${updateDOM(forcedTheme)}}()`
374
+ }
334
375
 
335
- return (
336
- <NextHead>
337
- {forcedTheme ? (
338
- <script
339
- key="next-themes-script"
340
- dangerouslySetInnerHTML={{
341
- // These are minified via Terser and then updated by hand, don't recommend
342
- __html: `!function(){${optimization}${updateDOM(forcedTheme)}}()`,
343
- }}
344
- />
345
- ) : enableSystem ? (
346
- <script
347
- key="next-themes-script"
348
- dangerouslySetInnerHTML={{
349
- __html: `!function(){try {${optimization}var e=localStorage.getItem('${storageKey}');${
350
- !defaultSystem ? updateDOM(defaultTheme) + ';' : ''
351
- }if("system"===e||(!e&&${defaultSystem})){var t="${MEDIA}",m=window.matchMedia(t);m.media!==t||m.matches?${updateDOM(
352
- 'dark',
353
- )}:${updateDOM('light')}}else if(e) ${
354
- value ? `var x=${JSON.stringify(value)};` : ''
355
- }${updateDOM(value ? 'x[e]' : 'e', true)}}catch(e){}}()`,
356
- }}
357
- />
358
- ) : (
359
- <script
360
- key="next-themes-script"
361
- dangerouslySetInnerHTML={{
362
- __html: `!function(){try{${optimization}var e=localStorage.getItem("${storageKey}");if(e){${
363
- value ? `var x=${JSON.stringify(value)};` : ''
364
- }${updateDOM(value ? 'x[e]' : 'e', true)}}else{${updateDOM(
365
- defaultTheme,
366
- )};}}catch(t){}}();`,
367
- }}
368
- />
369
- )}
370
- </NextHead>
371
- )
372
- },
373
- (prevProps, nextProps) => {
374
- // Only re-render when forcedTheme changes
375
- // the rest of the props should be completely stable
376
- if (prevProps.forcedTheme !== nextProps.forcedTheme) return false
377
- return true
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
+ })()
394
+
395
+ return <script nonce={nonce} dangerouslySetInnerHTML={{ __html: scriptSrc }} />
378
396
  },
397
+ // Never re-render this component
398
+ () => true
379
399
  )
380
400
 
381
401
  // Helpers
@@ -38,16 +38,18 @@ 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
42
  }
42
43
  /**
43
44
  * @deprecated renamed to `useThemeSetting` to avoid confusion with core `useTheme` hook
44
45
  */
45
- export declare const useTheme: () => UseThemeProps;
46
- export declare const useThemeSetting: () => UseThemeProps;
46
+ export declare const useTheme: () => UseThemeProps | null;
47
+ export declare const useThemeSetting: () => UseThemeProps | null;
47
48
  interface ValueObject {
48
49
  [themeName: string]: string;
49
50
  }
50
51
  export declare const useRootTheme: () => readonly [string, React.Dispatch<React.SetStateAction<string>>];
51
52
  export declare const NextThemeProvider: React.FC<ThemeProviderProps>;
53
+ export declare const Theme: React.FC<ThemeProviderProps>;
52
54
  export {};
53
55
  //# sourceMappingURL=NextTheme.d.ts.map