@tamagui/core 1.0.1-rc.9 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/dist/cjs/createComponent.js +25 -27
  2. package/dist/cjs/createComponent.js.map +2 -2
  3. package/dist/cjs/createTamagui.js +2 -1
  4. package/dist/cjs/createTamagui.js.map +2 -2
  5. package/dist/cjs/helpers/ThemeManager.js +4 -2
  6. package/dist/cjs/helpers/ThemeManager.js.map +2 -2
  7. package/dist/cjs/helpers/Unwrap.js +29 -0
  8. package/dist/cjs/helpers/Unwrap.js.map +7 -0
  9. package/dist/cjs/helpers/cache.js +7 -11
  10. package/dist/cjs/helpers/cache.js.map +2 -2
  11. package/dist/cjs/helpers/expandStyle.js +29 -41
  12. package/dist/cjs/helpers/expandStyle.js.map +2 -2
  13. package/dist/cjs/helpers/getSplitStyles.js +8 -14
  14. package/dist/cjs/helpers/getSplitStyles.js.map +2 -2
  15. package/dist/cjs/helpers/getStylesAtomic.js +10 -11
  16. package/dist/cjs/helpers/getStylesAtomic.js.map +2 -2
  17. package/dist/cjs/helpers/insertStyleRule.js +0 -2
  18. package/dist/cjs/helpers/insertStyleRule.js.map +2 -2
  19. package/dist/cjs/hooks/useTheme.js +45 -50
  20. package/dist/cjs/hooks/useTheme.js.map +3 -3
  21. package/dist/cjs/views/TamaguiProvider.js +3 -0
  22. package/dist/cjs/views/TamaguiProvider.js.map +2 -2
  23. package/dist/cjs/views/Theme.js +15 -21
  24. package/dist/cjs/views/Theme.js.map +3 -3
  25. package/dist/esm/createComponent.js +26 -28
  26. package/dist/esm/createComponent.js.map +2 -2
  27. package/dist/esm/createTamagui.js +2 -1
  28. package/dist/esm/createTamagui.js.map +2 -2
  29. package/dist/esm/helpers/ThemeManager.js +4 -2
  30. package/dist/esm/helpers/ThemeManager.js.map +2 -2
  31. package/dist/esm/helpers/Unwrap.js +5 -0
  32. package/dist/esm/helpers/Unwrap.js.map +7 -0
  33. package/dist/esm/helpers/cache.js +7 -10
  34. package/dist/esm/helpers/cache.js.map +2 -2
  35. package/dist/esm/helpers/expandStyle.js +26 -38
  36. package/dist/esm/helpers/expandStyle.js.map +2 -2
  37. package/dist/esm/helpers/getSplitStyles.js +8 -14
  38. package/dist/esm/helpers/getSplitStyles.js.map +2 -2
  39. package/dist/esm/helpers/getStylesAtomic.js +10 -11
  40. package/dist/esm/helpers/getStylesAtomic.js.map +2 -2
  41. package/dist/esm/helpers/insertStyleRule.js +0 -2
  42. package/dist/esm/helpers/insertStyleRule.js.map +2 -2
  43. package/dist/esm/hooks/useTheme.js +45 -50
  44. package/dist/esm/hooks/useTheme.js.map +3 -3
  45. package/dist/esm/views/TamaguiProvider.js +3 -0
  46. package/dist/esm/views/TamaguiProvider.js.map +2 -2
  47. package/dist/esm/views/Theme.js +14 -14
  48. package/dist/esm/views/Theme.js.map +2 -2
  49. package/package.json +13 -13
  50. package/src/createComponent.tsx +47 -43
  51. package/src/createTamagui.ts +2 -1
  52. package/src/helpers/ThemeManager.tsx +7 -2
  53. package/src/helpers/cache.ts +7 -9
  54. package/src/helpers/expandStyle.ts +27 -41
  55. package/src/helpers/getSplitStyles.tsx +23 -14
  56. package/src/helpers/getStylesAtomic.ts +15 -15
  57. package/src/helpers/insertStyleRule.tsx +0 -2
  58. package/src/hooks/useTheme.tsx +67 -48
  59. package/src/views/TamaguiProvider.tsx +6 -0
  60. package/src/views/Theme.tsx +15 -22
  61. package/types/createComponent.d.ts +1 -1
  62. package/types/helpers/ThemeManager.d.ts +1 -1
  63. package/types/helpers/cache.d.ts +2 -4
  64. package/types/hooks/useTheme.d.ts +1 -1
  65. package/types/views/Theme.d.ts +1 -1
@@ -9,6 +9,7 @@ import {
9
9
  } from "../helpers/ThemeManager";
10
10
  import { ThemeManagerContext } from "../helpers/ThemeManagerContext";
11
11
  import { GetThemeUnwrapped } from "./getThemeUnwrapped";
12
+ import { useServerRef } from "./useServerHooks";
12
13
  const emptyProps = { name: null };
13
14
  function getDefaultThemeProxied() {
14
15
  const config = getConfig();
@@ -19,13 +20,24 @@ function getDefaultThemeProxied() {
19
20
  });
20
21
  }
21
22
  const useTheme = (props = emptyProps) => {
22
- var _a;
23
+ var _a, _b;
23
24
  if (isRSC) {
24
25
  return getDefaultThemeProxied();
25
26
  }
26
- const { name, theme, themeManager, className, isNewTheme } = useChangeThemeEffect(props);
27
+ const state = useServerRef();
28
+ if (isClient && !state.current) {
29
+ state.current = {
30
+ keys: /* @__PURE__ */ new Set()
31
+ };
32
+ }
33
+ (_a = state.current) == null ? void 0 : _a.keys.clear();
34
+ const { name, theme, themeManager, className, isNewTheme } = useChangeThemeEffect(
35
+ props,
36
+ false,
37
+ isClient ? () => state.current.keys.size === 0 : void 0
38
+ );
27
39
  if (process.env.NODE_ENV === "development") {
28
- if (isWeb && isNewTheme && className === ((_a = themeManager == null ? void 0 : themeManager.parentManager) == null ? void 0 : _a.state.className)) {
40
+ if (isWeb && isNewTheme && className === ((_b = themeManager == null ? void 0 : themeManager.parentManager) == null ? void 0 : _b.state.className)) {
29
41
  console.error("Should always change, duplicating ThemeMananger bug", themeManager);
30
42
  }
31
43
  if (props.debug === "verbose") {
@@ -49,7 +61,8 @@ const useTheme = (props = emptyProps) => {
49
61
  theme,
50
62
  name,
51
63
  className,
52
- themeManager
64
+ themeManager,
65
+ state
53
66
  });
54
67
  }, [theme, isNewTheme, name, className, themeManager]);
55
68
  };
@@ -58,7 +71,8 @@ function getThemeProxied({
58
71
  name,
59
72
  className,
60
73
  themeManager,
61
- isNewTheme
74
+ isNewTheme,
75
+ state
62
76
  }) {
63
77
  return createProxy(theme, {
64
78
  has(_, key) {
@@ -88,7 +102,20 @@ function getThemeProxied({
88
102
  if (!themeManager) {
89
103
  return theme[key];
90
104
  }
91
- return themeManager.getValue(key);
105
+ const val = themeManager.getValue(key);
106
+ if (val && state) {
107
+ if (isClient) {
108
+ return new Proxy(val, {
109
+ get(_2, subkey) {
110
+ if (subkey === "val") {
111
+ state.current.keys.add(key);
112
+ }
113
+ return Reflect.get(val, subkey);
114
+ }
115
+ });
116
+ }
117
+ }
118
+ return val;
92
119
  }
93
120
  });
94
121
  }
@@ -97,7 +124,7 @@ const GetIsNewTheme = Symbol();
97
124
  const getThemeManager = (theme) => theme == null ? void 0 : theme[GetThemeManager];
98
125
  const getThemeIsNewTheme = (theme) => theme == null ? void 0 : theme[GetIsNewTheme];
99
126
  const activeThemeManagers = /* @__PURE__ */ new Set();
100
- const useChangeThemeEffect = (props, root = false) => {
127
+ const useChangeThemeEffect = (props, root = false, disableUpdate) => {
101
128
  if (isRSC) {
102
129
  return {
103
130
  ...createState().state,
@@ -129,20 +156,8 @@ const useChangeThemeEffect = (props, root = false) => {
129
156
  return;
130
157
  }
131
158
  activeThemeManagers.add(themeManager);
132
- const disposeChangeListener = parentManager == null ? void 0 : parentManager.onChangeTheme(() => {
133
- if (!(isNewTheme || isWeb)) {
134
- setThemeState({
135
- ...themeState,
136
- state: { ...themeManager.state },
137
- isNewTheme: false
138
- });
139
- } else {
140
- updateState();
141
- }
142
- });
143
159
  return () => {
144
160
  activeThemeManagers.delete(themeManager);
145
- disposeChangeListener == null ? void 0 : disposeChangeListener();
146
161
  };
147
162
  }, [disable, state, isNewTheme, debug]);
148
163
  }
@@ -152,12 +167,7 @@ const useChangeThemeEffect = (props, root = false) => {
152
167
  if (!parentManager)
153
168
  throw "impossible";
154
169
  if (process.env.NODE_ENV === "development" && props.debug === "verbose")
155
- console.log(
156
- "useTheme hasNoThemeUpdatingProps",
157
- parentManager.state.name,
158
- "isInversingOnMount",
159
- isInversingOnMount
160
- );
170
+ console.log("useTheme hasNoThemeUpdatingProps", parentManager.state.name, "isInversingOnMount", isInversingOnMount);
161
171
  return {
162
172
  ...parentManager.state,
163
173
  className: isInversingOnMount ? "" : parentManager.state.className,
@@ -172,27 +182,11 @@ const useChangeThemeEffect = (props, root = false) => {
172
182
  themeManager
173
183
  };
174
184
  function createState(prev) {
185
+ if (prev && (disableUpdate == null ? void 0 : disableUpdate())) {
186
+ return prev;
187
+ }
175
188
  const _ = new ThemeManager(props, root ? "root" : parentManager);
176
189
  const isNewTheme2 = _ !== parentManager;
177
- if (process.env.NODE_ENV === "development" && debug)
178
- [
179
- console.groupCollapsed("useTheme create() isNewTheme", isNewTheme2),
180
- console.log(
181
- "parent.state.name",
182
- parentManager == null ? void 0 : parentManager.state.name,
183
- "\n",
184
- "props",
185
- props,
186
- "\n",
187
- isClient ? parentManager : "",
188
- "getState",
189
- isNewTheme2 && isClient ? _.getState(props) : "",
190
- "\n",
191
- "state",
192
- isClient ? { ..._.state } : ""
193
- ),
194
- console.groupEnd()
195
- ];
196
190
  const mounted2 = !props.inverse ? true : root || (prev == null ? void 0 : prev.mounted);
197
191
  return {
198
192
  isNewTheme: isNewTheme2,
@@ -201,12 +195,13 @@ const useChangeThemeEffect = (props, root = false) => {
201
195
  mounted: mounted2
202
196
  };
203
197
  }
204
- function updateState() {
205
- const next = themeManager.getState(props, parentManager);
206
- const shouldChange = themeManager.getStateShouldChange(
207
- next,
208
- isNewTheme ? state : null
209
- );
198
+ function updateState(updatingManager) {
199
+ if (disableUpdate == null ? void 0 : disableUpdate()) {
200
+ return;
201
+ }
202
+ const manager = updatingManager ?? themeManager;
203
+ const next = manager.getState(props, parentManager);
204
+ const shouldChange = manager.getStateShouldChange(next, isNewTheme ? state : null);
210
205
  if (shouldChange) {
211
206
  setThemeState(createState);
212
207
  } else {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/hooks/useTheme.tsx"],
4
- "sourcesContent": ["/* eslint-disable no-console */\nimport { isClient, isRSC, isServer, isWeb } from '@tamagui/constants'\nimport { useContext, useEffect, useLayoutEffect, useMemo, useState } from 'react'\n\nimport { getConfig } from '../config'\nimport { isDevTools } from '../constants/isDevTools'\nimport { createProxy } from '../helpers/createProxy'\nimport {\n ThemeManager,\n ThemeManagerState,\n hasNoThemeUpdatingProps,\n} from '../helpers/ThemeManager'\nimport { ThemeManagerContext } from '../helpers/ThemeManagerContext'\nimport { ThemeParsed, ThemeProps } from '../types'\nimport { GetThemeUnwrapped } from './getThemeUnwrapped'\n\nexport type ChangedThemeResponse = {\n themeManager: ThemeManager | null\n name: string\n isNewTheme?: boolean\n theme?: ThemeParsed | null\n className?: string\n}\n\nconst emptyProps = { name: null }\n\nfunction getDefaultThemeProxied() {\n const config = getConfig()\n const name = Object.keys(config.themes)[0]\n return getThemeProxied({\n theme: config.themes[name],\n name,\n })\n}\n\nexport const useTheme = (props: ThemeProps = emptyProps): ThemeParsed => {\n if (isRSC) {\n return getDefaultThemeProxied()\n }\n\n const { name, theme, themeManager, className, isNewTheme } = useChangeThemeEffect(props)\n\n if (process.env.NODE_ENV === 'development') {\n // ensure we aren't creating too many ThemeManagers\n if (\n isWeb &&\n isNewTheme &&\n className === themeManager?.parentManager?.state.className\n ) {\n console.error('Should always change, duplicating ThemeMananger bug', themeManager)\n }\n if (props.debug === 'verbose') {\n console.groupCollapsed(' \uD83D\uDD39 useTheme =>', name)\n const logs = { ...props, name, className, ...(isDevTools && { theme }) }\n for (const key in logs) {\n console.log(' ', key, logs[key])\n }\n console.groupEnd()\n }\n }\n\n if (!theme) {\n if (process.env.NODE_ENV === 'development') {\n console.warn('No theme found', name, props, themeManager)\n }\n return getDefaultThemeProxied()\n }\n\n return useMemo(() => {\n return getThemeProxied({\n isNewTheme,\n theme,\n name,\n className,\n themeManager,\n })\n }, [theme, isNewTheme, name, className, themeManager])\n}\n\nfunction getThemeProxied({\n theme,\n name,\n className,\n themeManager,\n isNewTheme,\n}: {\n theme: any\n name: string\n className?: string\n themeManager?: ThemeManager | null\n isNewTheme?: boolean\n}) {\n return createProxy(theme, {\n has(_, key) {\n if (typeof key === 'string') {\n if (key[0] === '$') key = key.slice(1)\n return themeManager?.allKeys.has(key)\n }\n return Reflect.has(theme, key)\n },\n get(_, key) {\n if (key === GetThemeUnwrapped) {\n return theme\n } else if (key === GetThemeManager) {\n return themeManager\n } else if (key === GetIsNewTheme) {\n return isNewTheme\n } else if (key === 'name') {\n return name\n } else if (key === 'className') {\n return className\n } else if (\n !name ||\n key === '__proto__' ||\n typeof key === 'symbol' ||\n key === '$typeof'\n ) {\n return Reflect.get(_, key)\n }\n // auto convert variables to plain\n if (key[0] === '$') key = key.slice(1)\n if (!themeManager) {\n return theme[key]\n }\n return themeManager.getValue(key)\n },\n })\n}\n\nconst GetThemeManager = Symbol()\nconst GetIsNewTheme = Symbol()\n\nexport const getThemeManager = (theme: any): ThemeManager | undefined =>\n theme?.[GetThemeManager]\nexport const getThemeIsNewTheme = (theme: any): ThemeManager | undefined =>\n theme?.[GetIsNewTheme]\n\nexport const activeThemeManagers = new Set<ThemeManager>()\n\nexport const useChangeThemeEffect = (\n props: ThemeProps,\n root = false\n): ChangedThemeResponse => {\n if (isRSC) {\n // we need context working for this to work well\n return {\n ...createState().state,\n themeManager: null,\n }\n }\n const parentManager = useContext(ThemeManagerContext)\n\n const {\n debug,\n // @ts-expect-error internal use only\n disable,\n } = props\n\n if (disable) {\n if (!parentManager) throw new Error('Disable topmost')\n return {\n ...parentManager.state,\n isNewTheme: false,\n themeManager: parentManager,\n }\n }\n\n type State = {\n isNewTheme: boolean\n state: ThemeManagerState\n themeManager: ThemeManager\n mounted?: boolean\n }\n\n const [themeState, setThemeState] = useState<State>(createState)\n const { isNewTheme, state, themeManager, mounted } = themeState\n\n if (!isServer) {\n useEffect(() => {\n if (disable) return\n // SSR safe inverse (because server can't know prefers scheme)\n // could be done through fancy selectors like how we do prefers-media\n // but may be a bit of explosion of selectors\n if (props.inverse && !mounted) {\n setThemeState({ ...themeState, mounted: true })\n return\n }\n activeThemeManagers.add(themeManager)\n const disposeChangeListener = parentManager?.onChangeTheme(() => {\n if (!(isNewTheme || isWeb)) {\n setThemeState({\n ...themeState,\n state: { ...themeManager.state },\n isNewTheme: false,\n })\n } else {\n updateState()\n }\n })\n return () => {\n activeThemeManagers.delete(themeManager)\n disposeChangeListener?.()\n }\n }, [disable, state, isNewTheme, debug])\n }\n\n const isInversingOnMount = Boolean(!themeState.mounted && props.inverse)\n const shouldReturnParentState = hasNoThemeUpdatingProps(props) || isInversingOnMount\n\n if (shouldReturnParentState) {\n if (!parentManager) throw 'impossible'\n if (process.env.NODE_ENV === 'development' && props.debug === 'verbose')\n console.log(\n 'useTheme hasNoThemeUpdatingProps',\n parentManager.state.name,\n 'isInversingOnMount',\n isInversingOnMount\n )\n return {\n ...parentManager.state,\n className: isInversingOnMount ? '' : parentManager.state.className,\n themeManager: parentManager,\n isNewTheme: false,\n }\n }\n\n // run inline in render\n updateState()\n\n return {\n ...state,\n isNewTheme,\n themeManager,\n }\n\n function createState(prev?: State) {\n const _ = new ThemeManager(props, root ? 'root' : parentManager)\n const isNewTheme = _ !== parentManager\n if (process.env.NODE_ENV === 'development' && debug)\n [\n console.groupCollapsed('useTheme create() isNewTheme', isNewTheme),\n console.log(\n 'parent.state.name',\n parentManager?.state.name,\n '\\n',\n 'props',\n props,\n '\\n',\n isClient ? parentManager : '',\n 'getState',\n isNewTheme && isClient ? _.getState(props) : '',\n '\\n',\n 'state',\n isClient ? { ..._.state } : ''\n ),\n console.groupEnd(),\n ]\n // only inverse relies on this for ssr\n const mounted = !props.inverse ? true : root || prev?.mounted\n return {\n // ThemeManager returns parentManager if no change\n isNewTheme,\n state: { ..._.state },\n themeManager: _,\n mounted,\n }\n }\n\n function updateState() {\n const next = themeManager.getState(props, parentManager)\n const shouldChange = themeManager.getStateShouldChange(\n next,\n isNewTheme ? state : null\n )\n if (shouldChange) {\n setThemeState(createState)\n } else {\n if (!next && parentManager?.state.name !== state.name) {\n // were changing back to parent state\n setThemeState(createState)\n }\n }\n }\n}\n"],
5
- "mappings": "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",
6
- "names": ["isNewTheme", "mounted"]
4
+ "sourcesContent": ["/* eslint-disable no-console */\nimport { isClient, isRSC, isServer, isWeb } from '@tamagui/constants'\nimport { useContext, useEffect, useMemo, useState } from 'react'\n\nimport { getConfig } from '../config'\nimport { isDevTools } from '../constants/isDevTools'\nimport { createProxy } from '../helpers/createProxy'\nimport {\n ThemeManager,\n ThemeManagerState,\n hasNoThemeUpdatingProps,\n} from '../helpers/ThemeManager'\nimport { ThemeManagerContext } from '../helpers/ThemeManagerContext'\nimport { ThemeParsed, ThemeProps } from '../types'\nimport { GetThemeUnwrapped } from './getThemeUnwrapped'\nimport { useServerRef } from './useServerHooks'\n\nexport type ChangedThemeResponse = {\n themeManager: ThemeManager | null\n name: string\n isNewTheme?: boolean\n theme?: ThemeParsed | null\n className?: string\n}\n\nconst emptyProps = { name: null }\n\nfunction getDefaultThemeProxied() {\n const config = getConfig()\n const name = Object.keys(config.themes)[0]\n return getThemeProxied({\n theme: config.themes[name],\n name,\n })\n}\n\ninterface UseThemeState {\n keys: Set<string>\n}\n\nexport const useTheme = (props: ThemeProps = emptyProps): ThemeParsed => {\n if (isRSC) {\n return getDefaultThemeProxied()\n }\n\n const state = useServerRef() as React.MutableRefObject<UseThemeState>\n if (isClient && !state.current) {\n state.current = {\n keys: new Set(),\n }\n }\n state.current?.keys.clear()\n\n const { name, theme, themeManager, className, isNewTheme } = useChangeThemeEffect(\n props,\n false,\n isClient ? () => state.current.keys.size === 0 : undefined\n )\n\n if (process.env.NODE_ENV === 'development') {\n // ensure we aren't creating too many ThemeManagers\n if (\n isWeb &&\n isNewTheme &&\n className === themeManager?.parentManager?.state.className\n ) {\n console.error('Should always change, duplicating ThemeMananger bug', themeManager)\n }\n if (props.debug === 'verbose') {\n console.groupCollapsed(' \uD83D\uDD39 useTheme =>', name)\n const logs = { ...props, name, className, ...(isDevTools && { theme }) }\n for (const key in logs) {\n console.log(' ', key, logs[key])\n }\n console.groupEnd()\n }\n }\n\n if (!theme) {\n if (process.env.NODE_ENV === 'development') {\n console.warn('No theme found', name, props, themeManager)\n }\n return getDefaultThemeProxied()\n }\n\n return useMemo(() => {\n return getThemeProxied({\n isNewTheme,\n theme,\n name,\n className,\n themeManager,\n state,\n })\n }, [theme, isNewTheme, name, className, themeManager])\n}\n\nfunction getThemeProxied({\n theme,\n name,\n className,\n themeManager,\n isNewTheme,\n state,\n}: {\n theme: any\n name: string\n className?: string\n themeManager?: ThemeManager | null\n isNewTheme?: boolean\n state?: React.RefObject<UseThemeState>\n}) {\n return createProxy(theme, {\n has(_, key) {\n if (typeof key === 'string') {\n if (key[0] === '$') key = key.slice(1)\n return themeManager?.allKeys.has(key)\n }\n return Reflect.has(theme, key)\n },\n get(_, key) {\n if (key === GetThemeUnwrapped) {\n return theme\n } else if (key === GetThemeManager) {\n return themeManager\n } else if (key === GetIsNewTheme) {\n return isNewTheme\n } else if (key === 'name') {\n return name\n } else if (key === 'className') {\n return className\n } else if (\n !name ||\n key === '__proto__' ||\n typeof key === 'symbol' ||\n key === '$typeof'\n ) {\n return Reflect.get(_, key)\n }\n // auto convert variables to plain\n if (key[0] === '$') key = key.slice(1)\n if (!themeManager) {\n return theme[key]\n }\n const val = themeManager.getValue(key)\n if (val && state) {\n if (isClient) {\n return new Proxy(val as any, {\n get(_, subkey) {\n if (subkey === 'val') {\n state.current!.keys.add(key as any)\n }\n return Reflect.get(val, subkey)\n },\n })\n }\n }\n return val\n },\n })\n}\n\nconst GetThemeManager = Symbol()\nconst GetIsNewTheme = Symbol()\n\nexport const getThemeManager = (theme: any): ThemeManager | undefined =>\n theme?.[GetThemeManager]\nexport const getThemeIsNewTheme = (theme: any): ThemeManager | undefined =>\n theme?.[GetIsNewTheme]\n\nexport const activeThemeManagers = new Set<ThemeManager>()\n\nexport const useChangeThemeEffect = (\n props: ThemeProps,\n root = false,\n disableUpdate?: () => boolean\n): ChangedThemeResponse => {\n if (isRSC) {\n // we need context working for this to work well\n return {\n ...createState().state,\n themeManager: null,\n }\n }\n const parentManager = useContext(ThemeManagerContext)\n\n const {\n debug,\n // @ts-expect-error internal use only\n disable,\n } = props\n\n if (disable) {\n if (!parentManager) throw new Error('Disable topmost')\n return {\n ...parentManager.state,\n isNewTheme: false,\n themeManager: parentManager,\n }\n }\n\n type State = {\n isNewTheme: boolean\n state: ThemeManagerState\n themeManager: ThemeManager\n mounted?: boolean\n }\n\n const [themeState, setThemeState] = useState<State>(createState)\n const { isNewTheme, state, themeManager, mounted } = themeState\n\n if (!isServer) {\n useEffect(() => {\n if (disable) return\n // SSR safe inverse (because server can't know prefers scheme)\n // could be done through fancy selectors like how we do prefers-media\n // but may be a bit of explosion of selectors\n if (props.inverse && !mounted) {\n setThemeState({ ...themeState, mounted: true })\n return\n }\n activeThemeManagers.add(themeManager)\n // const disposeChangeListener = parentManager?.onChangeTheme((name, manager) => {\n // // console.log('hi', props, state, name, manager)\n // if (state.theme !== manager.state.theme) {\n // console.warn('now update to', manager.state.name)\n // updateState(manager)\n // }\n // })\n return () => {\n activeThemeManagers.delete(themeManager)\n // disposeChangeListener?.()\n }\n }, [disable, state, isNewTheme, debug])\n }\n\n const isInversingOnMount = Boolean(!themeState.mounted && props.inverse)\n const shouldReturnParentState = hasNoThemeUpdatingProps(props) || isInversingOnMount\n\n if (shouldReturnParentState) {\n if (!parentManager) throw 'impossible'\n // prettier-ignore\n if (process.env.NODE_ENV === 'development' && props.debug === 'verbose') console.log('useTheme hasNoThemeUpdatingProps', parentManager.state.name, 'isInversingOnMount', isInversingOnMount)\n return {\n ...parentManager.state,\n className: isInversingOnMount ? '' : parentManager.state.className,\n themeManager: parentManager,\n isNewTheme: false,\n }\n }\n\n // run inline in render\n updateState()\n\n return {\n ...state,\n isNewTheme,\n themeManager,\n }\n\n function createState(prev?: State) {\n if (prev && disableUpdate?.()) {\n return prev\n }\n // returns previous theme manager if no change\n const _ = new ThemeManager(props, root ? 'root' : parentManager)\n const isNewTheme = _ !== parentManager\n // prettier-ignore\n\n // if (prev?.isNewTheme && _.state.theme !== parentManager?.state.theme) {\n // console.warn('notify')\n // _.notify()\n // }\n\n // only inverse relies on this for ssr\n const mounted = !props.inverse ? true : root || prev?.mounted\n return {\n // ThemeManager returns parentManager if no change\n isNewTheme,\n state: { ..._.state },\n themeManager: _,\n mounted,\n }\n }\n\n function updateState(updatingManager?: ThemeManager) {\n if (disableUpdate?.()) {\n return\n }\n const manager = updatingManager ?? themeManager\n const next = manager.getState(props, parentManager)\n const shouldChange = manager.getStateShouldChange(next, isNewTheme ? state : null)\n // console.log(`got it`, next, isNewTheme, shouldChange, { ...updatingManager?.state })\n if (shouldChange) {\n setThemeState(createState)\n } else {\n if (!next && parentManager?.state.name !== state.name) {\n // were changing back to parent state\n setThemeState(createState)\n }\n }\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["_", "isNewTheme", "mounted"]
7
7
  }
@@ -23,6 +23,9 @@ function TamaguiProvider({
23
23
  }
24
24
  if (isClient) {
25
25
  React.useLayoutEffect(() => {
26
+ if (document.documentElement.classList.contains("t_unmounted")) {
27
+ document.documentElement.classList.remove("t_unmounted");
28
+ }
26
29
  if (disableInjectCSS)
27
30
  return;
28
31
  const style = document.createElement("style");
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/views/TamaguiProvider.tsx"],
4
- "sourcesContent": ["import { isClient, isRSC, isServer, isWeb } from '@tamagui/constants'\nimport * as React from 'react'\n\nimport { ButtonNestingContext } from '../contexts/ButtonNestingContext'\nimport { TextAncestorContext } from '../contexts/TextAncestorContext'\nimport { useMediaListeners } from '../hooks/useMedia'\nimport type { TamaguiProviderProps } from '../types'\nimport { ThemeProvider } from './ThemeProvider'\n\nexport function TamaguiProvider({\n children,\n disableInjectCSS,\n config,\n ...themePropsProvider\n}: TamaguiProviderProps) {\n if (isRSC) {\n return (\n <span\n style={{ display: 'contents' }}\n className={`t_${Object.keys(config.themes)[0] || 'light'}`}\n >\n {children}\n </span>\n )\n }\n\n if (!(isWeb && isServer)) {\n useMediaListeners(config)\n }\n\n if (isClient) {\n // inject CSS if asked to (not SSR compliant)\n // eslint-disable-next-line react-hooks/rules-of-hooks\n React.useLayoutEffect(() => {\n if (disableInjectCSS) return\n const style = document.createElement('style')\n style.appendChild(document.createTextNode(config.getCSS()))\n document.head.appendChild(style)\n return () => {\n document.head.removeChild(style)\n }\n }, [config, disableInjectCSS])\n }\n\n return (\n <ButtonNestingContext.Provider value={false}>\n <TextAncestorContext.Provider value={false}>\n <ThemeProvider\n themeClassNameOnRoot={config.themeClassNameOnRoot}\n disableRootThemeClass={config.disableRootThemeClass}\n {...themePropsProvider}\n defaultTheme={themePropsProvider.defaultTheme ?? Object.keys(config.themes)[0]}\n >\n {children}\n </ThemeProvider>\n </TextAncestorContext.Provider>\n </ButtonNestingContext.Provider>\n )\n}\n"],
5
- "mappings": "AAiBM;AAjBN,SAAS,UAAU,OAAO,UAAU,aAAa;AACjD,YAAY,WAAW;AAEvB,SAAS,4BAA4B;AACrC,SAAS,2BAA2B;AACpC,SAAS,yBAAyB;AAElC,SAAS,qBAAqB;AAEvB,SAAS,gBAAgB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,KACG;AACL,GAAyB;AACvB,MAAI,OAAO;AACT,WACE,oBAAC;AAAA,MACC,OAAO,EAAE,SAAS,WAAW;AAAA,MAC7B,WAAW,KAAK,OAAO,KAAK,OAAO,MAAM,EAAE,MAAM;AAAA,MAEhD;AAAA,KACH;AAAA,EAEJ;AAEA,MAAI,EAAE,SAAS,WAAW;AACxB,sBAAkB,MAAM;AAAA,EAC1B;AAEA,MAAI,UAAU;AAGZ,UAAM,gBAAgB,MAAM;AAC1B,UAAI;AAAkB;AACtB,YAAM,QAAQ,SAAS,cAAc,OAAO;AAC5C,YAAM,YAAY,SAAS,eAAe,OAAO,OAAO,CAAC,CAAC;AAC1D,eAAS,KAAK,YAAY,KAAK;AAC/B,aAAO,MAAM;AACX,iBAAS,KAAK,YAAY,KAAK;AAAA,MACjC;AAAA,IACF,GAAG,CAAC,QAAQ,gBAAgB,CAAC;AAAA,EAC/B;AAEA,SACE,oBAAC,qBAAqB,UAArB;AAAA,IAA8B,OAAO;AAAA,IACpC,8BAAC,oBAAoB,UAApB;AAAA,MAA6B,OAAO;AAAA,MACnC,8BAAC;AAAA,QACC,sBAAsB,OAAO;AAAA,QAC7B,uBAAuB,OAAO;AAAA,QAC7B,GAAG;AAAA,QACJ,cAAc,mBAAmB,gBAAgB,OAAO,KAAK,OAAO,MAAM,EAAE;AAAA,QAE3E;AAAA,OACH;AAAA,KACF;AAAA,GACF;AAEJ;",
4
+ "sourcesContent": ["import { isClient, isRSC, isServer, isWeb } from '@tamagui/constants'\nimport * as React from 'react'\n\nimport { ButtonNestingContext } from '../contexts/ButtonNestingContext'\nimport { TextAncestorContext } from '../contexts/TextAncestorContext'\nimport { useMediaListeners } from '../hooks/useMedia'\nimport type { TamaguiProviderProps } from '../types'\nimport { ThemeProvider } from './ThemeProvider'\n\nexport function TamaguiProvider({\n children,\n disableInjectCSS,\n config,\n ...themePropsProvider\n}: TamaguiProviderProps) {\n if (isRSC) {\n return (\n <span\n style={{ display: 'contents' }}\n className={`t_${Object.keys(config.themes)[0] || 'light'}`}\n >\n {children}\n </span>\n )\n }\n\n if (!(isWeb && isServer)) {\n useMediaListeners(config)\n }\n\n if (isClient) {\n // inject CSS if asked to (not SSR compliant)\n // eslint-disable-next-line react-hooks/rules-of-hooks\n React.useLayoutEffect(() => {\n // for easier support of hidden-until-js mount animations\n // user must set t_unmounted on documentElement from SSR\n if (document.documentElement.classList.contains('t_unmounted')) {\n document.documentElement.classList.remove('t_unmounted')\n }\n\n if (disableInjectCSS) return\n const style = document.createElement('style')\n style.appendChild(document.createTextNode(config.getCSS()))\n document.head.appendChild(style)\n return () => {\n document.head.removeChild(style)\n }\n }, [config, disableInjectCSS])\n }\n\n return (\n <ButtonNestingContext.Provider value={false}>\n <TextAncestorContext.Provider value={false}>\n <ThemeProvider\n themeClassNameOnRoot={config.themeClassNameOnRoot}\n disableRootThemeClass={config.disableRootThemeClass}\n {...themePropsProvider}\n defaultTheme={themePropsProvider.defaultTheme ?? Object.keys(config.themes)[0]}\n >\n {children}\n </ThemeProvider>\n </TextAncestorContext.Provider>\n </ButtonNestingContext.Provider>\n )\n}\n"],
5
+ "mappings": "AAiBM;AAjBN,SAAS,UAAU,OAAO,UAAU,aAAa;AACjD,YAAY,WAAW;AAEvB,SAAS,4BAA4B;AACrC,SAAS,2BAA2B;AACpC,SAAS,yBAAyB;AAElC,SAAS,qBAAqB;AAEvB,SAAS,gBAAgB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,KACG;AACL,GAAyB;AACvB,MAAI,OAAO;AACT,WACE,oBAAC;AAAA,MACC,OAAO,EAAE,SAAS,WAAW;AAAA,MAC7B,WAAW,KAAK,OAAO,KAAK,OAAO,MAAM,EAAE,MAAM;AAAA,MAEhD;AAAA,KACH;AAAA,EAEJ;AAEA,MAAI,EAAE,SAAS,WAAW;AACxB,sBAAkB,MAAM;AAAA,EAC1B;AAEA,MAAI,UAAU;AAGZ,UAAM,gBAAgB,MAAM;AAG1B,UAAI,SAAS,gBAAgB,UAAU,SAAS,aAAa,GAAG;AAC9D,iBAAS,gBAAgB,UAAU,OAAO,aAAa;AAAA,MACzD;AAEA,UAAI;AAAkB;AACtB,YAAM,QAAQ,SAAS,cAAc,OAAO;AAC5C,YAAM,YAAY,SAAS,eAAe,OAAO,OAAO,CAAC,CAAC;AAC1D,eAAS,KAAK,YAAY,KAAK;AAC/B,aAAO,MAAM;AACX,iBAAS,KAAK,YAAY,KAAK;AAAA,MACjC;AAAA,IACF,GAAG,CAAC,QAAQ,gBAAgB,CAAC;AAAA,EAC/B;AAEA,SACE,oBAAC,qBAAqB,UAArB;AAAA,IAA8B,OAAO;AAAA,IACpC,8BAAC,oBAAoB,UAApB;AAAA,MAA6B,OAAO;AAAA,MACnC,8BAAC;AAAA,QACC,sBAAsB,OAAO;AAAA,QAC7B,uBAAuB,OAAO;AAAA,QAC7B,GAAG;AAAA,QACJ,cAAc,mBAAmB,gBAAgB,OAAO,KAAK,OAAO,MAAM,EAAE;AAAA,QAE3E;AAAA,OACH;AAAA,KACF;AAAA,GACF;AAEJ;",
6
6
  "names": []
7
7
  }
@@ -1,6 +1,6 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
2
  import { isWeb } from "@tamagui/constants";
3
- import React, { useMemo } from "react";
3
+ import { Children, cloneElement } from "react";
4
4
  import { variableToString } from "../createVariable";
5
5
  import { ThemeManagerContext } from "../helpers/ThemeManagerContext";
6
6
  import { useChangeThemeEffect } from "../hooks/useTheme";
@@ -9,16 +9,16 @@ function Theme(props) {
9
9
  return props.children;
10
10
  }
11
11
  const isRoot = !!props["_isRoot"];
12
- const { name, theme, themeManager, isNewTheme, className } = useChangeThemeEffect(
13
- props,
14
- isRoot
15
- );
12
+ const { name, theme, themeManager, className } = useChangeThemeEffect(props, isRoot);
16
13
  const disableThemeClass = props.disableThemeClass;
17
14
  const missingTheme = !(name && theme);
18
- let contents = useMemo(() => {
19
- const next = props["data-themeable"] ? React.cloneElement(props.children, { ["data-themeable"]: true }) : props.children;
20
- return missingTheme ? next : wrapThemeManagerContext(next, themeManager);
21
- }, [missingTheme, props.children, themeManager]);
15
+ let contents = useThemeManagerContext(
16
+ props["data-themeable"] ? Children.map(
17
+ props.children,
18
+ (child) => cloneElement(child, { ["data-themeable"]: true })
19
+ ) : props.children,
20
+ themeManager
21
+ );
22
22
  if (process.env.NODE_ENV === "development" && missingTheme) {
23
23
  name && !theme && console.warn(`No theme found by name ${name}`);
24
24
  return props.children;
@@ -38,10 +38,10 @@ function Theme(props) {
38
38
  }
39
39
  return contents;
40
40
  }
41
- function wrapThemeManagerContext(children, themeManager, shouldReset) {
42
- if (!themeManager) {
41
+ function useThemeManagerContext(children, themeManager, shouldReset) {
42
+ const value = themeManager;
43
+ if (!value)
43
44
  return children;
44
- }
45
45
  let next = children;
46
46
  if (shouldReset && themeManager) {
47
47
  next = /* @__PURE__ */ jsx(Theme, {
@@ -50,12 +50,12 @@ function wrapThemeManagerContext(children, themeManager, shouldReset) {
50
50
  });
51
51
  }
52
52
  return /* @__PURE__ */ jsx(ThemeManagerContext.Provider, {
53
- value: themeManager,
53
+ value,
54
54
  children: next
55
55
  });
56
56
  }
57
57
  export {
58
58
  Theme,
59
- wrapThemeManagerContext
59
+ useThemeManagerContext
60
60
  };
61
61
  //# sourceMappingURL=Theme.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/views/Theme.tsx"],
4
- "sourcesContent": ["import { isWeb } from '@tamagui/constants'\nimport React, { useMemo } from 'react'\n\nimport { variableToString } from '../createVariable'\nimport { ThemeManager } from '../helpers/ThemeManager'\nimport { ThemeManagerContext } from '../helpers/ThemeManagerContext'\nimport { useChangeThemeEffect } from '../hooks/useTheme'\nimport { ThemeProps } from '../types'\n\nexport function Theme(props: ThemeProps) {\n // @ts-expect-error only for internal views\n if (props.disable) {\n return props.children\n }\n\n const isRoot = !!props['_isRoot']\n const { name, theme, themeManager, isNewTheme, className } = useChangeThemeEffect(\n props,\n isRoot\n )\n\n const disableThemeClass = props.disableThemeClass\n const missingTheme = !(name && theme)\n\n // memo here, changing theme without re-rendering all children is a critical optimization\n // may require some effort of end user to memoize but without this memo they'd have no option\n let contents = useMemo(() => {\n const next = props['data-themeable']\n ? React.cloneElement(props.children, { ['data-themeable']: true })\n : props.children\n\n return missingTheme ? next : wrapThemeManagerContext(next, themeManager)\n }, [missingTheme, props.children, themeManager])\n\n if (process.env.NODE_ENV === 'development' && missingTheme) {\n // eslint-disable-next-line no-console\n name && !theme && console.warn(`No theme found by name ${name}`)\n return props.children\n }\n\n if (disableThemeClass || missingTheme) {\n return contents\n }\n\n if (isWeb) {\n const cn = [props.className, className, '_dsp_contents'].filter(Boolean).join(' ')\n contents = (\n <span\n className={cn}\n style={{\n // in order to provide currentColor, set color by default\n color: variableToString(theme?.color),\n }}\n >\n {contents}\n </span>\n )\n }\n\n return contents\n}\n\nexport function wrapThemeManagerContext(\n children: any,\n themeManager?: ThemeManager | null,\n shouldReset?: boolean\n) {\n // be sure to memoize themeManager to avoid reparenting\n if (!themeManager) {\n return children\n }\n // be sure to memoize shouldReset to avoid reparenting\n let next = children\n // TODO likely not necessary if we do reset logic now in useTheme?\n // reset to parent theme\n if (shouldReset && themeManager) {\n next = <Theme name={themeManager.state.parentName}>{next}</Theme>\n }\n return (\n <ThemeManagerContext.Provider value={themeManager}>\n {next}\n </ThemeManagerContext.Provider>\n )\n}\n"],
5
- "mappings": "AA+CM;AA/CN,SAAS,aAAa;AACtB,OAAO,SAAS,eAAe;AAE/B,SAAS,wBAAwB;AAEjC,SAAS,2BAA2B;AACpC,SAAS,4BAA4B;AAG9B,SAAS,MAAM,OAAmB;AAEvC,MAAI,MAAM,SAAS;AACjB,WAAO,MAAM;AAAA,EACf;AAEA,QAAM,SAAS,CAAC,CAAC,MAAM;AACvB,QAAM,EAAE,MAAM,OAAO,cAAc,YAAY,UAAU,IAAI;AAAA,IAC3D;AAAA,IACA;AAAA,EACF;AAEA,QAAM,oBAAoB,MAAM;AAChC,QAAM,eAAe,EAAE,QAAQ;AAI/B,MAAI,WAAW,QAAQ,MAAM;AAC3B,UAAM,OAAO,MAAM,oBACf,MAAM,aAAa,MAAM,UAAU,EAAE,CAAC,mBAAmB,KAAK,CAAC,IAC/D,MAAM;AAEV,WAAO,eAAe,OAAO,wBAAwB,MAAM,YAAY;AAAA,EACzE,GAAG,CAAC,cAAc,MAAM,UAAU,YAAY,CAAC;AAE/C,MAAI,QAAQ,IAAI,aAAa,iBAAiB,cAAc;AAE1D,YAAQ,CAAC,SAAS,QAAQ,KAAK,0BAA0B,MAAM;AAC/D,WAAO,MAAM;AAAA,EACf;AAEA,MAAI,qBAAqB,cAAc;AACrC,WAAO;AAAA,EACT;AAEA,MAAI,OAAO;AACT,UAAM,KAAK,CAAC,MAAM,WAAW,WAAW,eAAe,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG;AACjF,eACE,oBAAC;AAAA,MACC,WAAW;AAAA,MACX,OAAO;AAAA,QAEL,OAAO,iBAAiB,+BAAO,KAAK;AAAA,MACtC;AAAA,MAEC;AAAA,KACH;AAAA,EAEJ;AAEA,SAAO;AACT;AAEO,SAAS,wBACd,UACA,cACA,aACA;AAEA,MAAI,CAAC,cAAc;AACjB,WAAO;AAAA,EACT;AAEA,MAAI,OAAO;AAGX,MAAI,eAAe,cAAc;AAC/B,WAAO,oBAAC;AAAA,MAAM,MAAM,aAAa,MAAM;AAAA,MAAa;AAAA,KAAK;AAAA,EAC3D;AACA,SACE,oBAAC,oBAAoB,UAApB;AAAA,IAA6B,OAAO;AAAA,IAClC;AAAA,GACH;AAEJ;",
4
+ "sourcesContent": ["import { isWeb } from '@tamagui/constants'\nimport React, { Children, cloneElement, useMemo } from 'react'\n\nimport { variableToString } from '../createVariable'\nimport { ThemeManager } from '../helpers/ThemeManager'\nimport { ThemeManagerContext } from '../helpers/ThemeManagerContext'\nimport { useChangeThemeEffect } from '../hooks/useTheme'\nimport { ThemeProps } from '../types'\n\nexport function Theme(props: ThemeProps) {\n // @ts-expect-error only for internal views\n if (props.disable) {\n return props.children\n }\n\n const isRoot = !!props['_isRoot']\n const { name, theme, themeManager, className } = useChangeThemeEffect(props, isRoot)\n const disableThemeClass = props.disableThemeClass\n const missingTheme = !(name && theme)\n\n // memo here, changing theme without re-rendering all children is a critical optimization\n // may require some effort of end user to memoize but without this memo they'd have no option\n let contents = useThemeManagerContext(\n props['data-themeable']\n ? Children.map(props.children, (child) =>\n cloneElement(child, { ['data-themeable']: true })\n )\n : props.children,\n themeManager\n )\n\n if (process.env.NODE_ENV === 'development' && missingTheme) {\n // eslint-disable-next-line no-console\n name && !theme && console.warn(`No theme found by name ${name}`)\n return props.children\n }\n\n if (disableThemeClass || missingTheme) {\n return contents\n }\n\n if (isWeb) {\n const cn = [props.className, className, '_dsp_contents'].filter(Boolean).join(' ')\n contents = (\n <span\n className={cn}\n style={{\n // in order to provide currentColor, set color by default\n color: variableToString(theme?.color),\n }}\n >\n {contents}\n </span>\n )\n }\n\n return contents\n}\n\nexport function useThemeManagerContext(\n children: any,\n themeManager?: ThemeManager | null,\n shouldReset?: boolean\n) {\n // disabled super memoize it - listener first strategy\n const value = themeManager // useMemo(() => themeManager, [!!themeManager])\n // be sure to memoize themeManager to avoid reparenting\n if (!value) return children\n // be sure to memoize shouldReset to avoid reparenting\n let next = children\n // TODO likely not necessary if we do reset logic now in useTheme?\n // reset to parent theme\n if (shouldReset && themeManager) {\n next = <Theme name={themeManager.state.parentName}>{next}</Theme>\n }\n return <ThemeManagerContext.Provider value={value}>{next}</ThemeManagerContext.Provider>\n}\n"],
5
+ "mappings": "AA4CM;AA5CN,SAAS,aAAa;AACtB,SAAgB,UAAU,oBAA6B;AAEvD,SAAS,wBAAwB;AAEjC,SAAS,2BAA2B;AACpC,SAAS,4BAA4B;AAG9B,SAAS,MAAM,OAAmB;AAEvC,MAAI,MAAM,SAAS;AACjB,WAAO,MAAM;AAAA,EACf;AAEA,QAAM,SAAS,CAAC,CAAC,MAAM;AACvB,QAAM,EAAE,MAAM,OAAO,cAAc,UAAU,IAAI,qBAAqB,OAAO,MAAM;AACnF,QAAM,oBAAoB,MAAM;AAChC,QAAM,eAAe,EAAE,QAAQ;AAI/B,MAAI,WAAW;AAAA,IACb,MAAM,oBACF,SAAS;AAAA,MAAI,MAAM;AAAA,MAAU,CAAC,UAC5B,aAAa,OAAO,EAAE,CAAC,mBAAmB,KAAK,CAAC;AAAA,IAClD,IACA,MAAM;AAAA,IACV;AAAA,EACF;AAEA,MAAI,QAAQ,IAAI,aAAa,iBAAiB,cAAc;AAE1D,YAAQ,CAAC,SAAS,QAAQ,KAAK,0BAA0B,MAAM;AAC/D,WAAO,MAAM;AAAA,EACf;AAEA,MAAI,qBAAqB,cAAc;AACrC,WAAO;AAAA,EACT;AAEA,MAAI,OAAO;AACT,UAAM,KAAK,CAAC,MAAM,WAAW,WAAW,eAAe,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG;AACjF,eACE,oBAAC;AAAA,MACC,WAAW;AAAA,MACX,OAAO;AAAA,QAEL,OAAO,iBAAiB,+BAAO,KAAK;AAAA,MACtC;AAAA,MAEC;AAAA,KACH;AAAA,EAEJ;AAEA,SAAO;AACT;AAEO,SAAS,uBACd,UACA,cACA,aACA;AAEA,QAAM,QAAQ;AAEd,MAAI,CAAC;AAAO,WAAO;AAEnB,MAAI,OAAO;AAGX,MAAI,eAAe,cAAc;AAC/B,WAAO,oBAAC;AAAA,MAAM,MAAM,aAAa,MAAM;AAAA,MAAa;AAAA,KAAK;AAAA,EAC3D;AACA,SAAO,oBAAC,oBAAoB,UAApB;AAAA,IAA6B;AAAA,IAAe;AAAA,GAAK;AAC3D;",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tamagui/core",
3
- "version": "1.0.1-rc.9",
3
+ "version": "1.0.1",
4
4
  "source": "src/index.ts",
5
5
  "main": "dist/cjs",
6
6
  "module": "dist/esm",
@@ -28,28 +28,28 @@
28
28
  "reset.css"
29
29
  ],
30
30
  "dependencies": {
31
- "@tamagui/compose-refs": "^1.0.1-rc.9",
32
- "@tamagui/constants": "^1.0.1-rc.9",
33
- "@tamagui/helpers": "^1.0.1-rc.9",
34
- "@tamagui/react-native-use-pressable": "^1.0.1-rc.9",
35
- "@tamagui/react-native-use-responder-events": "^1.0.1-rc.9",
36
- "@tamagui/use-did-finish-ssr": "^1.0.1-rc.9",
37
- "@tamagui/use-event": "^1.0.1-rc.9",
38
- "@tamagui/use-force-update": "^1.0.1-rc.9",
31
+ "@tamagui/compose-refs": "^1.0.1",
32
+ "@tamagui/constants": "^1.0.1",
33
+ "@tamagui/helpers": "^1.0.1",
34
+ "@tamagui/react-native-use-pressable": "^1.0.1",
35
+ "@tamagui/react-native-use-responder-events": "^1.0.1",
36
+ "@tamagui/use-did-finish-ssr": "^1.0.1",
37
+ "@tamagui/use-event": "^1.0.1",
38
+ "@tamagui/use-force-update": "^1.0.1",
39
39
  "normalize-css-color": "^1.0.2"
40
40
  },
41
41
  "peerDependencies": {
42
- "react": "^18.2.0",
43
- "react-dom": "^18.2.0"
42
+ "react": "*",
43
+ "react-dom": "*"
44
44
  },
45
45
  "devDependencies": {
46
- "@tamagui/build": "^1.0.1-rc.9",
46
+ "@tamagui/build": "^1.0.1",
47
47
  "@testing-library/react": "^13.4.0",
48
48
  "csstype": "^3.0.10",
49
49
  "react": "^18.2.0",
50
50
  "react-dom": "^18.2.0",
51
51
  "typescript": "^4.7.4",
52
- "vitest": "^0.25.7"
52
+ "vitest": "^0.26.2"
53
53
  },
54
54
  "exports": {
55
55
  "./package.json": "./package.json",
@@ -20,7 +20,6 @@ import React, {
20
20
  createElement,
21
21
  forwardRef,
22
22
  memo,
23
- startTransition,
24
23
  useCallback,
25
24
  useContext,
26
25
  useEffect,
@@ -61,7 +60,7 @@ import {
61
60
  } from './types'
62
61
  import { usePressability } from './vendor/Pressability'
63
62
  import { Slot, mergeEvent } from './views/Slot'
64
- import { wrapThemeManagerContext } from './views/Theme'
63
+ import { useThemeManagerContext } from './views/Theme'
65
64
 
66
65
  // let t
67
66
  // import { timer } from '@tamagui/timer'
@@ -558,7 +557,8 @@ export function createComponent<
558
557
 
559
558
  if (process.env.NODE_ENV === 'development' && !isText && isWeb) {
560
559
  Children.toArray(props.children).forEach((item) => {
561
- if (typeof item === 'string') {
560
+ // allow newlines because why not its annoying with mdx
561
+ if (typeof item === 'string' && item !== '\n') {
562
562
  // eslint-disable-next-line no-console
563
563
  console.error(
564
564
  `Unexpected text node: ${item}. A text node cannot be a child of a <View>.`
@@ -585,10 +585,17 @@ export function createComponent<
585
585
  const shouldSetMounted = needsMount && state.unmounted
586
586
  useEffect(() => {
587
587
  if (!shouldSetMounted) return
588
+ if (state.unmounted === true && needsMount) {
589
+ setStateShallow({
590
+ unmounted: false,
591
+ })
592
+ return
593
+ }
594
+
588
595
  setStateShallow({
589
596
  unmounted: false,
590
597
  })
591
- }, [shouldSetMounted])
598
+ }, [shouldSetMounted, state.unmounted])
592
599
 
593
600
  let styles: Record<string, any>[]
594
601
 
@@ -618,11 +625,15 @@ export function createComponent<
618
625
  const fontFamilyClassName = fontFamily ? `font_${fontFamily}` : ''
619
626
 
620
627
  const classList = [
628
+ hasEnterStyle && ((state.unmounted && needsMount) || !isClient)
629
+ ? 't_will-mount'
630
+ : '',
621
631
  componentName ? componentClassName : '',
622
632
  fontFamilyClassName,
623
633
  themeIsNew ? theme.className : '',
624
634
  classNames ? Object.values(classNames).join(' ') : '',
625
635
  ]
636
+
626
637
  const className = classList.join(' ')
627
638
 
628
639
  if (process.env.TAMAGUI_TARGET === 'web') {
@@ -811,23 +822,20 @@ export function createComponent<
811
822
  stateRef.current.themeShouldReset = true
812
823
  }
813
824
 
814
- const childEls =
815
- !children || asChild
816
- ? children
817
- : wrapThemeManagerContext(
818
- spacedChildren({
819
- separator,
820
- children,
821
- space,
822
- direction: props.spaceDirection || 'both',
823
- isZStack,
824
- }),
825
- // only set context if changed theme
826
- stateRef.current.hasProvidedThemeManager ? themeManager : undefined,
827
- stateRef.current.themeShouldReset
828
- )
825
+ const innerContent = useThemeManagerContext(
826
+ spacedChildren({
827
+ separator,
828
+ children,
829
+ space,
830
+ direction: props.spaceDirection || 'both',
831
+ isZStack,
832
+ }),
833
+ // only set context if changed theme
834
+ stateRef.current.hasProvidedThemeManager ? themeManager : undefined,
835
+ stateRef.current.themeShouldReset
836
+ )
829
837
 
830
- let content: any
838
+ let content = !children || asChild ? children : innerContent
831
839
 
832
840
  if (asChild) {
833
841
  elementType = Slot
@@ -865,7 +873,7 @@ export function createComponent<
865
873
  }
866
874
  }
867
875
 
868
- content = createElement(elementType, viewProps, childEls)
876
+ content = createElement(elementType, viewProps, content)
869
877
 
870
878
  if (process.env.TAMAGUI_TARGET === 'web') {
871
879
  if (events || isAnimatedReactNativeWeb) {
@@ -921,7 +929,6 @@ export function createComponent<
921
929
  styles,
922
930
  pseudos,
923
931
  content,
924
- childEls,
925
932
  shouldAvoidClasses,
926
933
  avoidClasses: avoidClassesWhileAnimating,
927
934
  animation: props.animation,
@@ -1162,41 +1169,38 @@ export type SpacedChildrenProps = {
1162
1169
  separator?: React.ReactNode
1163
1170
  }
1164
1171
 
1165
- export function spacedChildren({
1166
- isZStack,
1167
- children,
1168
- space,
1169
- direction,
1170
- spaceFlex,
1171
- separator,
1172
- }: SpacedChildrenProps) {
1172
+ export function spacedChildren(props: SpacedChildrenProps) {
1173
+ const { isZStack, children, space, direction, spaceFlex, separator } = props
1173
1174
  const hasSpace = !!(space || spaceFlex)
1174
1175
  const hasSeparator = !(separator === undefined || separator === null)
1175
1176
  if (!(hasSpace || hasSeparator || isZStack)) {
1176
1177
  return children
1177
1178
  }
1179
+
1178
1180
  const childrenList = Children.toArray(children)
1181
+
1179
1182
  const len = childrenList.length
1180
- if (len <= 1 && !isZStack) {
1181
- if (len === 1) {
1182
- // forward space! only when one component doesn't make sense to forward space to all children
1183
- const [onlyChild] = childrenList
1184
- if (React.isValidElement(onlyChild) && onlyChild.type?.['shouldForwardSpace']) {
1185
- return React.cloneElement(onlyChild, {
1186
- space,
1187
- spaceFlex,
1188
- separator,
1189
- } as any)
1190
- }
1191
- }
1183
+ if (len <= 1 && !isZStack && !childrenList[0]?.['type']?.['shouldForwardSpace']) {
1192
1184
  return childrenList
1193
1185
  }
1186
+
1194
1187
  const final: React.ReactNode[] = []
1195
- for (const [index, child] of childrenList.entries()) {
1188
+ for (let [index, child] of childrenList.entries()) {
1196
1189
  const isEmpty =
1197
1190
  child === null ||
1198
1191
  child === undefined ||
1199
1192
  (Array.isArray(child) && child.length === 0)
1193
+
1194
+ // forward space
1195
+ if (!isEmpty && React.isValidElement(child) && child.type?.['shouldForwardSpace']) {
1196
+ child = React.cloneElement(child, {
1197
+ space,
1198
+ spaceFlex,
1199
+ separator,
1200
+ key: child.key,
1201
+ } as any)
1202
+ }
1203
+
1200
1204
  // push them all, but wrap some in Fragment
1201
1205
  if (isEmpty || !child || (child['key'] && !isZStack)) {
1202
1206
  final.push(child)
@@ -212,7 +212,8 @@ export function createTamagui<Conf extends CreateTamaguiProps>(
212
212
  tokensParsed,
213
213
  parsed: true,
214
214
  getCSS: (separator = '\n') => {
215
- return `.is_Text .is_Text {display:inline-flex;}
215
+ return `.t_unmounted .t_will-mount {opacity:0;visibility:hidden;}
216
+ .is_Text .is_Text {display:inline-flex;}
216
217
  ._dsp_contents {display:contents;}
217
218
  ${themeConfig.cssRuleSets.join(separator)}
218
219
  ${themeConfig.themeRuleSets.join(separator)}
@@ -42,6 +42,10 @@ export class ThemeManager {
42
42
  if (!parentManager) {
43
43
  throw new Error('Must set up root first')
44
44
  }
45
+
46
+ // copy over listeners
47
+ this.themeListeners = parentManager.themeListeners
48
+
45
49
  // no change no props
46
50
  if (hasNoThemeUpdatingProps(props)) {
47
51
  return parentManager
@@ -101,9 +105,9 @@ export class ThemeManager {
101
105
  state: ThemeManagerState | null = this.state
102
106
  ) {
103
107
  if (!nextState?.theme || nextState.theme === state?.theme) {
104
- return null
108
+ return false
105
109
  }
106
- return nextState
110
+ return true
107
111
  }
108
112
 
109
113
  getState(props = this.props, parentManager = this.parentManager) {
@@ -136,6 +140,7 @@ export class ThemeManager {
136
140
  }
137
141
 
138
142
  notify() {
143
+ console.log('notify', this.themeListeners.size, this.themeListeners)
139
144
  this.themeListeners.forEach((cb) => cb(this.state.name, this))
140
145
  }
141
146