@tamagui/core 1.0.1-beta.220 → 1.0.1-beta.222
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/addTheme.js +7 -10
- package/dist/cjs/addTheme.js.map +3 -3
- package/dist/cjs/config.js +8 -4
- package/dist/cjs/config.js.map +2 -2
- package/dist/cjs/{hooks/useUnmountEffect.js → contexts/ButtonNestingContext.js} +7 -9
- package/dist/cjs/contexts/ButtonNestingContext.js.map +7 -0
- package/dist/cjs/createComponent.js +63 -67
- package/dist/cjs/createComponent.js.map +3 -3
- package/dist/cjs/createTamagui.js +13 -12
- package/dist/cjs/createTamagui.js.map +2 -2
- package/dist/cjs/createTokens.js.map +2 -2
- package/dist/cjs/createTokens.test.js +27 -0
- package/dist/cjs/createTokens.test.js.map +7 -0
- package/dist/cjs/createVariable.js +4 -9
- package/dist/cjs/createVariable.js.map +2 -2
- package/dist/cjs/createVariable.test.js +7 -0
- package/dist/cjs/createVariable.test.js.map +7 -0
- package/dist/cjs/createVariables.js +6 -7
- package/dist/cjs/createVariables.js.map +2 -2
- package/dist/cjs/helpers/ThemeManager.js +161 -147
- package/dist/cjs/helpers/ThemeManager.js.map +3 -3
- package/dist/cjs/helpers/ThemeManager.test.js +421 -34
- package/dist/cjs/helpers/ThemeManager.test.js.map +2 -2
- package/dist/cjs/helpers/{getTokens.js → ThemeManagerContext.js} +8 -8
- package/dist/cjs/helpers/ThemeManagerContext.js.map +7 -0
- package/dist/cjs/helpers/createPropMapper.js +4 -4
- package/dist/cjs/helpers/createPropMapper.js.map +2 -2
- package/dist/cjs/helpers/extendStaticConfig.js +2 -4
- package/dist/cjs/helpers/extendStaticConfig.js.map +2 -2
- package/dist/cjs/helpers/{assignNativePropsToWeb.native.js → getBoundingClientRect.js} +15 -8
- package/dist/cjs/helpers/getBoundingClientRect.js.map +7 -0
- package/dist/cjs/{hooks/useConstant.js → helpers/getRect.js} +14 -17
- package/dist/cjs/helpers/getRect.js.map +7 -0
- package/dist/cjs/helpers/getSplitStyles.js +82 -85
- package/dist/cjs/helpers/getSplitStyles.js.map +3 -3
- package/dist/cjs/helpers/getThemeCSSRules.js +6 -2
- package/dist/cjs/helpers/getThemeCSSRules.js.map +2 -2
- package/dist/cjs/helpers/insertStyleRule.js +1 -1
- package/dist/cjs/helpers/insertStyleRule.js.map +2 -2
- package/dist/cjs/helpers/mergeTransform.js +11 -8
- package/dist/cjs/helpers/mergeTransform.js.map +2 -2
- package/dist/cjs/helpers/pseudoDescriptors.js +1 -0
- package/dist/cjs/helpers/pseudoDescriptors.js.map +2 -2
- package/dist/cjs/helpers/themeable.js +9 -9
- package/dist/cjs/helpers/themeable.js.map +2 -2
- package/dist/cjs/hooks/useElementLayout.js +4 -12
- package/dist/cjs/hooks/useElementLayout.js.map +2 -2
- package/dist/cjs/hooks/useMedia.js +2 -1
- package/dist/cjs/hooks/useMedia.js.map +2 -2
- package/dist/cjs/hooks/useTheme.js +114 -156
- package/dist/cjs/hooks/useTheme.js.map +3 -3
- package/dist/cjs/hooks/useThemeName.js +52 -0
- package/dist/cjs/hooks/useThemeName.js.map +7 -0
- package/dist/cjs/index.js +2 -5
- package/dist/cjs/index.js.map +2 -2
- package/dist/cjs/setupReactNative.js +20 -7
- package/dist/cjs/setupReactNative.js.map +2 -2
- package/dist/cjs/styled.js +2 -19
- package/dist/cjs/styled.js.map +2 -2
- package/dist/cjs/types.js.map +1 -1
- package/dist/cjs/updateTheme.js +9 -9
- package/dist/cjs/updateTheme.js.map +2 -2
- package/dist/cjs/views/TamaguiProvider.js +3 -3
- package/dist/cjs/views/TamaguiProvider.js.map +2 -2
- package/dist/cjs/views/Theme.js +39 -28
- package/dist/cjs/views/Theme.js.map +3 -3
- package/dist/cjs/views/ThemeProvider.js +8 -33
- package/dist/cjs/views/ThemeProvider.js.map +3 -3
- package/dist/esm/addTheme.js +7 -10
- package/dist/esm/addTheme.js.map +3 -3
- package/dist/esm/config.js +8 -3
- package/dist/esm/config.js.map +2 -2
- package/dist/esm/contexts/ButtonNestingContext.js +6 -0
- package/dist/esm/contexts/ButtonNestingContext.js.map +7 -0
- package/dist/esm/createComponent.js +65 -70
- package/dist/esm/createComponent.js.map +3 -3
- package/dist/esm/createTamagui.js +13 -12
- package/dist/esm/createTamagui.js.map +2 -2
- package/dist/esm/createTokens.js.map +2 -2
- package/dist/esm/createTokens.test.js +26 -0
- package/dist/esm/createTokens.test.js.map +7 -0
- package/dist/esm/createVariable.js +4 -9
- package/dist/esm/createVariable.js.map +2 -2
- package/dist/esm/createVariable.test.js +6 -0
- package/dist/esm/createVariable.test.js.map +7 -0
- package/dist/esm/createVariables.js +6 -7
- package/dist/esm/createVariables.js.map +2 -2
- package/dist/esm/helpers/ThemeManager.js +140 -144
- package/dist/esm/helpers/ThemeManager.js.map +3 -3
- package/dist/esm/helpers/ThemeManager.test.js +421 -34
- package/dist/esm/helpers/ThemeManager.test.js.map +2 -2
- package/dist/esm/helpers/ThemeManagerContext.js +6 -0
- package/dist/esm/helpers/ThemeManagerContext.js.map +7 -0
- package/dist/esm/helpers/createPropMapper.js +4 -4
- package/dist/esm/helpers/createPropMapper.js.map +2 -2
- package/dist/esm/helpers/extendStaticConfig.js +2 -4
- package/dist/esm/helpers/extendStaticConfig.js.map +2 -2
- package/dist/esm/helpers/getBoundingClientRect.js +13 -0
- package/dist/esm/helpers/getBoundingClientRect.js.map +7 -0
- package/dist/esm/helpers/getRect.js +12 -0
- package/dist/esm/helpers/getRect.js.map +7 -0
- package/dist/esm/helpers/getSplitStyles.js +90 -87
- package/dist/esm/helpers/getSplitStyles.js.map +3 -3
- package/dist/esm/helpers/getThemeCSSRules.js +6 -2
- package/dist/esm/helpers/getThemeCSSRules.js.map +2 -2
- package/dist/esm/helpers/insertStyleRule.js +1 -1
- package/dist/esm/helpers/insertStyleRule.js.map +2 -2
- package/dist/esm/helpers/mergeTransform.js +8 -6
- package/dist/esm/helpers/mergeTransform.js.map +2 -2
- package/dist/esm/helpers/pseudoDescriptors.js +1 -0
- package/dist/esm/helpers/pseudoDescriptors.js.map +2 -2
- package/dist/esm/helpers/themeable.js +9 -9
- package/dist/esm/helpers/themeable.js.map +2 -2
- package/dist/esm/hooks/useElementLayout.js +2 -9
- package/dist/esm/hooks/useElementLayout.js.map +2 -2
- package/dist/esm/hooks/useMedia.js +3 -2
- package/dist/esm/hooks/useMedia.js.map +2 -2
- package/dist/esm/hooks/useTheme.js +114 -159
- package/dist/esm/hooks/useTheme.js.map +3 -3
- package/dist/esm/hooks/useThemeName.js +28 -0
- package/dist/esm/hooks/useThemeName.js.map +7 -0
- package/dist/esm/index.js +3 -5
- package/dist/esm/index.js.map +2 -2
- package/dist/esm/setupReactNative.js +18 -6
- package/dist/esm/setupReactNative.js.map +2 -2
- package/dist/esm/styled.js +3 -20
- package/dist/esm/styled.js.map +2 -2
- package/dist/esm/updateTheme.js +9 -9
- package/dist/esm/updateTheme.js.map +2 -2
- package/dist/esm/views/TamaguiProvider.js +4 -4
- package/dist/esm/views/TamaguiProvider.js.map +2 -2
- package/dist/esm/views/Theme.js +40 -29
- package/dist/esm/views/Theme.js.map +3 -3
- package/dist/esm/views/ThemeProvider.js +8 -27
- package/dist/esm/views/ThemeProvider.js.map +2 -2
- package/package.json +12 -12
- package/src/__snapshots__/createTokens.test.ts.snap +877 -0
- package/src/addTheme.ts +9 -12
- package/src/config.ts +10 -2
- package/src/contexts/ButtonNestingContext.tsx +3 -0
- package/src/createComponent.tsx +117 -108
- package/src/createTamagui.ts +16 -14
- package/src/createTokens.test.ts +29 -0
- package/src/createTokens.ts +1 -1
- package/src/createVariable.test.ts +7 -0
- package/src/createVariable.ts +4 -10
- package/src/createVariables.ts +7 -7
- package/src/helpers/ThemeManager.test.tsx +480 -0
- package/src/helpers/ThemeManager.tsx +171 -166
- package/src/helpers/ThemeManagerContext.tsx +5 -0
- package/src/helpers/createPropMapper.ts +4 -4
- package/src/helpers/extendStaticConfig.ts +4 -4
- package/src/helpers/getBoundingClientRect.tsx +7 -0
- package/src/helpers/getRect.tsx +8 -0
- package/src/helpers/getSplitStyles.tsx +98 -93
- package/src/helpers/getThemeCSSRules.ts +9 -2
- package/src/helpers/insertStyleRule.tsx +2 -2
- package/src/helpers/mergeTransform.ts +13 -6
- package/src/helpers/pseudoDescriptors.ts +1 -0
- package/src/helpers/themeable.tsx +17 -9
- package/src/hooks/useElementLayout.tsx +3 -8
- package/src/hooks/useMedia.tsx +3 -3
- package/src/hooks/useTheme.tsx +138 -211
- package/src/hooks/useThemeName.tsx +27 -0
- package/src/index.ts +3 -4
- package/src/setupReactNative.ts +16 -5
- package/src/styled.tsx +4 -23
- package/src/types.tsx +53 -26
- package/src/updateTheme.ts +12 -9
- package/src/views/TamaguiProvider.tsx +5 -5
- package/src/views/Theme.tsx +48 -39
- package/src/views/ThemeProvider.tsx +11 -33
- package/types/Tamagui.d.ts +1 -1
- package/types/addTheme.d.ts +23 -2
- package/types/config.d.ts +0 -1
- package/types/contexts/ButtonNestingContext.d.ts +3 -0
- package/types/createTokens.test.d.ts +2 -0
- package/types/createVariable.d.ts +2 -2
- package/types/createVariable.test.d.ts +2 -0
- package/types/helpers/ThemeManager.d.ts +20 -30
- package/types/helpers/ThemeManager.test.d.ts +2 -0
- package/types/helpers/ThemeManagerContext.d.ts +4 -0
- package/types/helpers/getBoundingClientRect.d.ts +2 -0
- package/types/helpers/getRect.d.ts +9 -0
- package/types/helpers/insertStyleRule.d.ts +1 -1
- package/types/helpers/mergeTransform.d.ts +5 -3
- package/types/helpers/themeable.d.ts +3 -0
- package/types/hooks/useElementLayout.d.ts +0 -8
- package/types/hooks/useTheme.d.ts +10 -20
- package/types/hooks/useThemeName.d.ts +5 -0
- package/types/index.d.ts +3 -4
- package/types/setupReactNative.d.ts +4 -2
- package/types/types.d.ts +46 -20
- package/types/updateTheme.d.ts +23 -2
- package/types/views/Theme.d.ts +3 -4
- package/dist/cjs/constants/platform.js +0 -74
- package/dist/cjs/constants/platform.js.map +0 -7
- package/dist/cjs/constants/platform.native.js +0 -62
- package/dist/cjs/constants/platform.native.js.map +0 -7
- package/dist/cjs/helpers/assignNativePropsToWeb.js +0 -188
- package/dist/cjs/helpers/assignNativePropsToWeb.js.map +0 -7
- package/dist/cjs/helpers/assignNativePropsToWeb.native.js.map +0 -7
- package/dist/cjs/helpers/calc.js +0 -71
- package/dist/cjs/helpers/calc.js.map +0 -7
- package/dist/cjs/helpers/getFont.js +0 -66
- package/dist/cjs/helpers/getFont.js.map +0 -7
- package/dist/cjs/helpers/getStackSize.js +0 -46
- package/dist/cjs/helpers/getStackSize.js.map +0 -7
- package/dist/cjs/helpers/getTokens.js.map +0 -7
- package/dist/cjs/helpers/startTransition.js +0 -36
- package/dist/cjs/helpers/startTransition.js.map +0 -7
- package/dist/cjs/helpers/validate.js +0 -2
- package/dist/cjs/helpers/validate.js.map +0 -7
- package/dist/cjs/hooks/useConstant.js.map +0 -7
- package/dist/cjs/hooks/useIsMounted.js +0 -40
- package/dist/cjs/hooks/useIsMounted.js.map +0 -7
- package/dist/cjs/hooks/usePressable.js +0 -36
- package/dist/cjs/hooks/usePressable.js.map +0 -7
- package/dist/cjs/hooks/useUnmountEffect.js.map +0 -7
- package/dist/cjs/injectStyles.js +0 -40
- package/dist/cjs/injectStyles.js.map +0 -7
- package/dist/cjs/react-native.js +0 -22
- package/dist/cjs/react-native.js.map +0 -7
- package/dist/esm/constants/platform.js +0 -39
- package/dist/esm/constants/platform.js.map +0 -7
- package/dist/esm/constants/platform.native.js +0 -28
- package/dist/esm/constants/platform.native.js.map +0 -7
- package/dist/esm/helpers/assignNativePropsToWeb.js +0 -164
- package/dist/esm/helpers/assignNativePropsToWeb.js.map +0 -7
- package/dist/esm/helpers/assignNativePropsToWeb.native.js +0 -6
- package/dist/esm/helpers/assignNativePropsToWeb.native.js.map +0 -7
- package/dist/esm/helpers/calc.js +0 -47
- package/dist/esm/helpers/calc.js.map +0 -7
- package/dist/esm/helpers/getFont.js +0 -42
- package/dist/esm/helpers/getFont.js.map +0 -7
- package/dist/esm/helpers/getStackSize.js +0 -22
- package/dist/esm/helpers/getStackSize.js.map +0 -7
- package/dist/esm/helpers/getTokens.js +0 -6
- package/dist/esm/helpers/getTokens.js.map +0 -7
- package/dist/esm/helpers/startTransition.js +0 -6
- package/dist/esm/helpers/startTransition.js.map +0 -7
- package/dist/esm/helpers/validate.js +0 -1
- package/dist/esm/helpers/validate.js.map +0 -7
- package/dist/esm/hooks/useConstant.js +0 -15
- package/dist/esm/hooks/useConstant.js.map +0 -7
- package/dist/esm/hooks/useIsMounted.js +0 -16
- package/dist/esm/hooks/useIsMounted.js.map +0 -7
- package/dist/esm/hooks/usePressable.js +0 -12
- package/dist/esm/hooks/usePressable.js.map +0 -7
- package/dist/esm/hooks/useUnmountEffect.js +0 -8
- package/dist/esm/hooks/useUnmountEffect.js.map +0 -7
- package/dist/esm/injectStyles.js +0 -16
- package/dist/esm/injectStyles.js.map +0 -7
- package/dist/esm/react-native.js +0 -3
- package/dist/esm/react-native.js.map +0 -7
- package/src/contexts/ButtonInsideButtonContext.tsx +0 -3
- package/src/contexts/ThemeContext.tsx +0 -5
- package/src/helpers/areEqualSets.tsx +0 -9
- package/src/views/ThemeInverse.tsx +0 -43
- package/src/views/ThemeReset.tsx +0 -43
- package/types/constants/platform.d.ts +0 -13
- package/types/constants/platform.native.d.ts +0 -13
- package/types/contexts/ButtonInsideButtonContext.d.ts +0 -3
- package/types/contexts/ThemeContext.d.ts +0 -7
- package/types/helpers/areEqualSets.d.ts +0 -2
- package/types/helpers/assignNativePropsToWeb.d.ts +0 -2
- package/types/helpers/assignNativePropsToWeb.native.d.ts +0 -2
- package/types/helpers/calc.d.ts +0 -1
- package/types/helpers/getFont.d.ts +0 -3
- package/types/helpers/getStackSize.d.ts +0 -8
- package/types/helpers/getTokens.d.ts +0 -2
- package/types/helpers/startTransition.d.ts +0 -3
- package/types/helpers/validate.d.ts +0 -1
- package/types/hooks/useConstant.d.ts +0 -2
- package/types/hooks/useIsMounted.d.ts +0 -3
- package/types/hooks/useMedia.test.d.ts +0 -1
- package/types/hooks/usePressable.d.ts +0 -3
- package/types/hooks/usePressablePressResponder.d.ts +0 -84
- package/types/hooks/useUnmountEffect.d.ts +0 -2
- package/types/injectStyles.d.ts +0 -7
- package/types/react-native.d.ts +0 -8
- package/types/views/AbsoluteFill.d.ts +0 -5
- package/types/views/AbsoluteFill.native.d.ts +0 -3
- package/types/views/ThemeInverse.d.ts +0 -9
- package/types/views/ThemeReset.d.ts +0 -4
package/src/hooks/useTheme.tsx
CHANGED
|
@@ -1,124 +1,70 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
1
|
+
/* eslint-disable no-console */
|
|
2
|
+
import { isClient, isRSC, isServer, isWeb } from '@tamagui/constants'
|
|
3
|
+
import { useContext, useLayoutEffect, useMemo, useState } from 'react'
|
|
4
4
|
|
|
5
5
|
import { getConfig } from '../config'
|
|
6
6
|
import { isDevTools } from '../constants/isDevTools'
|
|
7
|
-
import { ThemeContext } from '../contexts/ThemeContext'
|
|
8
|
-
import { areEqualSets } from '../helpers/areEqualSets'
|
|
9
7
|
import { createProxy } from '../helpers/createProxy'
|
|
10
|
-
import {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
ThemeManagerContext,
|
|
14
|
-
emptyManager,
|
|
15
|
-
} from '../helpers/ThemeManager'
|
|
16
|
-
import { ThemeName, ThemeParsed } from '../types'
|
|
8
|
+
import { ThemeManager, ThemeManagerState, hasNoThemeUpdatingProps } from '../helpers/ThemeManager'
|
|
9
|
+
import { ThemeManagerContext } from '../helpers/ThemeManagerContext'
|
|
10
|
+
import { ThemeParsed, ThemeProps } from '../types'
|
|
17
11
|
import { GetThemeUnwrapped } from './getThemeUnwrapped'
|
|
18
|
-
import { useServerRef } from './useServerHooks'
|
|
19
12
|
|
|
20
|
-
export
|
|
13
|
+
export type ChangedThemeResponse = {
|
|
14
|
+
themes: Record<string, ThemeParsed>
|
|
15
|
+
themeManager: ThemeManager | null
|
|
16
|
+
name: string
|
|
17
|
+
isNewTheme?: boolean
|
|
18
|
+
theme?: ThemeParsed | null
|
|
21
19
|
className?: string
|
|
22
|
-
disableThemeClass?: boolean
|
|
23
|
-
name: Exclude<ThemeName, number> | null
|
|
24
|
-
componentName?: string
|
|
25
|
-
children?: any
|
|
26
|
-
reset?: boolean
|
|
27
|
-
debug?: boolean | 'verbose'
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
interface UseThemeState {
|
|
31
|
-
uuid: Object
|
|
32
|
-
keys: Set<string>
|
|
33
|
-
isRendering: boolean
|
|
34
20
|
}
|
|
35
21
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
componentName?: string,
|
|
39
|
-
props?: ThemeProps,
|
|
40
|
-
forceUpdate?: any,
|
|
41
|
-
disableTracking?: boolean
|
|
42
|
-
): ThemeParsed => {
|
|
43
|
-
// TODO this can use useChangeThemeEffect almost ready
|
|
22
|
+
const emptyProps = { name: null }
|
|
23
|
+
export const useTheme = (props: ThemeProps = emptyProps): ThemeParsed => {
|
|
44
24
|
if (isRSC) {
|
|
45
25
|
const config = getConfig()
|
|
46
|
-
|
|
47
|
-
return getThemeProxied(
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
if (!state.current) {
|
|
52
|
-
state.current = {
|
|
53
|
-
uuid: {},
|
|
54
|
-
keys: new Set(),
|
|
55
|
-
isRendering: true,
|
|
56
|
-
}
|
|
26
|
+
const name = Object.keys(config.themes)[0]
|
|
27
|
+
return getThemeProxied({
|
|
28
|
+
theme: config.themes[name],
|
|
29
|
+
name,
|
|
30
|
+
})
|
|
57
31
|
}
|
|
58
32
|
|
|
59
|
-
const { name, theme, themes, themeManager, className } = useChangeThemeEffect(
|
|
60
|
-
themeName,
|
|
61
|
-
componentName,
|
|
62
|
-
props,
|
|
63
|
-
forceUpdate,
|
|
64
|
-
state.current.uuid
|
|
65
|
-
)
|
|
33
|
+
const { name, theme, themes, themeManager, className, isNewTheme } = useChangeThemeEffect(props)
|
|
66
34
|
|
|
67
35
|
if (process.env.NODE_ENV === 'development') {
|
|
68
|
-
|
|
69
|
-
|
|
36
|
+
// ensure we aren't creating too many ThemeManagers
|
|
37
|
+
if (isWeb && isNewTheme && className === themeManager?.parentManager?.state.className) {
|
|
38
|
+
console.error(`Should always change, duplicating ThemeMananger bug`, themeManager)
|
|
39
|
+
// eslint-disable-next-line no-debugger
|
|
40
|
+
debugger
|
|
41
|
+
}
|
|
42
|
+
if (props.debug === 'verbose') {
|
|
70
43
|
console.groupCollapsed(' 🔹 useTheme =>', name)
|
|
71
|
-
const logs = {
|
|
44
|
+
const logs = { ...props, name, className, ...(isDevTools && { theme }) }
|
|
72
45
|
for (const key in logs) {
|
|
73
|
-
// eslint-disable-next-line no-console
|
|
74
46
|
console.log(' ', key, logs[key])
|
|
75
47
|
}
|
|
76
|
-
// eslint-disable-next-line no-console
|
|
77
48
|
console.groupEnd()
|
|
78
49
|
}
|
|
79
50
|
}
|
|
80
51
|
|
|
81
|
-
// track usage
|
|
82
|
-
state.current.isRendering = true
|
|
83
|
-
useIsomorphicLayoutEffect(() => {
|
|
84
|
-
const st = state.current
|
|
85
|
-
st.isRendering = false
|
|
86
|
-
const cur = themeManager?.keys.get(st.uuid)
|
|
87
|
-
if (!cur || !areEqualSets(st.keys, cur)) {
|
|
88
|
-
themeManager?.track(st.uuid, st.keys)
|
|
89
|
-
}
|
|
90
|
-
})
|
|
91
|
-
|
|
92
|
-
const debugProp = props && props['debug']
|
|
93
|
-
|
|
94
52
|
if (!theme) {
|
|
95
53
|
if (process.env.NODE_ENV === 'development') {
|
|
96
|
-
|
|
97
|
-
console.warn('No theme with name', themeName)
|
|
54
|
+
console.warn('No theme found', name, props, themeManager)
|
|
98
55
|
}
|
|
99
56
|
return themes[Object.keys(themes)[0]]
|
|
100
57
|
}
|
|
101
58
|
|
|
102
59
|
return useMemo(() => {
|
|
103
60
|
return getThemeProxied({
|
|
61
|
+
isNewTheme,
|
|
104
62
|
theme,
|
|
105
63
|
name,
|
|
106
64
|
className,
|
|
107
65
|
themeManager,
|
|
108
|
-
onStringKeyAccess(key) {
|
|
109
|
-
if (disableTracking) return
|
|
110
|
-
if (state) {
|
|
111
|
-
if (state.current.isRendering && !state.current.keys.has(key)) {
|
|
112
|
-
state.current.keys.add(key)
|
|
113
|
-
if (process.env.NODE_ENV === 'development' && debugProp === 'verbose') {
|
|
114
|
-
// eslint-disable-next-line no-console
|
|
115
|
-
console.log(' 🔸 tracking theme', key)
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
},
|
|
120
66
|
})
|
|
121
|
-
}, [theme, name, className, themeManager
|
|
67
|
+
}, [theme, isNewTheme, name, className, themeManager])
|
|
122
68
|
}
|
|
123
69
|
|
|
124
70
|
function getThemeProxied({
|
|
@@ -126,190 +72,171 @@ function getThemeProxied({
|
|
|
126
72
|
name,
|
|
127
73
|
className,
|
|
128
74
|
themeManager,
|
|
129
|
-
|
|
75
|
+
isNewTheme,
|
|
130
76
|
}: {
|
|
131
77
|
theme: any
|
|
132
78
|
name: string
|
|
133
|
-
onStringKeyAccess?: (cb: string) => void
|
|
134
79
|
className?: string
|
|
135
80
|
themeManager?: ThemeManager | null
|
|
81
|
+
isNewTheme?: boolean
|
|
136
82
|
}) {
|
|
137
83
|
return createProxy(theme, {
|
|
138
84
|
has(_, key) {
|
|
139
|
-
if (typeof key === 'string'
|
|
140
|
-
key = key.slice(1)
|
|
85
|
+
if (typeof key === 'string') {
|
|
86
|
+
if (key[0] === '$') key = key.slice(1)
|
|
87
|
+
return themeManager?.allKeys.has(key)
|
|
141
88
|
}
|
|
142
89
|
return Reflect.has(theme, key)
|
|
143
90
|
},
|
|
144
91
|
get(_, key) {
|
|
145
92
|
if (key === GetThemeUnwrapped) {
|
|
146
93
|
return theme
|
|
147
|
-
}
|
|
148
|
-
if (key === GetThemeManager) {
|
|
94
|
+
} else if (key === GetThemeManager) {
|
|
149
95
|
return themeManager
|
|
150
|
-
}
|
|
151
|
-
|
|
96
|
+
} else if (key === GetIsNewTheme) {
|
|
97
|
+
return isNewTheme
|
|
98
|
+
} else if (key === 'name') {
|
|
152
99
|
return name
|
|
153
|
-
}
|
|
154
|
-
if (key === 'className') {
|
|
100
|
+
} else if (key === 'className') {
|
|
155
101
|
return className
|
|
156
|
-
}
|
|
157
|
-
if (!name || key === '__proto__' || typeof key === 'symbol' || key === '$typeof') {
|
|
102
|
+
} else if (!name || key === '__proto__' || typeof key === 'symbol' || key === '$typeof') {
|
|
158
103
|
return Reflect.get(_, key)
|
|
159
104
|
}
|
|
160
105
|
// auto convert variables to plain
|
|
161
|
-
if (key[0] === '$')
|
|
162
|
-
key = key.slice(1)
|
|
163
|
-
}
|
|
106
|
+
if (key[0] === '$') key = key.slice(1)
|
|
164
107
|
if (!themeManager) {
|
|
165
108
|
return theme[key]
|
|
166
109
|
}
|
|
167
|
-
onStringKeyAccess?.(key)
|
|
168
110
|
return themeManager.getValue(key)
|
|
169
111
|
},
|
|
170
112
|
})
|
|
171
113
|
}
|
|
172
114
|
|
|
173
115
|
const GetThemeManager = Symbol()
|
|
116
|
+
const GetIsNewTheme = Symbol()
|
|
174
117
|
|
|
175
|
-
export const getThemeManager = (theme: any): ThemeManager | undefined =>
|
|
176
|
-
|
|
177
|
-
return theme[GetThemeManager]
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
export function useThemeName(opts?: { parent?: true }): ThemeName {
|
|
181
|
-
if (isRSC) {
|
|
182
|
-
const config = getConfig()
|
|
183
|
-
return config.themes[Object.keys(config.themes)[0]] as any
|
|
184
|
-
}
|
|
185
|
-
const parent = useContext(ThemeManagerContext)
|
|
186
|
-
const [name, setName] = useState(parent?.name || '')
|
|
187
|
-
|
|
188
|
-
useIsomorphicLayoutEffect(() => {
|
|
189
|
-
if (!parent) return
|
|
190
|
-
return parent.onChangeTheme((next, manager) => {
|
|
191
|
-
const name = opts?.parent ? manager.parentName || next : next
|
|
192
|
-
if (!name) return
|
|
193
|
-
setName(name)
|
|
194
|
-
})
|
|
195
|
-
}, [parent])
|
|
196
|
-
|
|
197
|
-
return name
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
export const useDefaultThemeName = () => {
|
|
201
|
-
return useContext(ThemeContext)?.defaultTheme
|
|
202
|
-
}
|
|
118
|
+
export const getThemeManager = (theme: any): ThemeManager | undefined => theme?.[GetThemeManager]
|
|
119
|
+
export const getThemeIsNewTheme = (theme: any): ThemeManager | undefined => theme?.[GetIsNewTheme]
|
|
203
120
|
|
|
204
121
|
export const activeThemeManagers = new Set<ThemeManager>()
|
|
205
122
|
|
|
206
|
-
export const useChangeThemeEffect = (
|
|
207
|
-
|
|
208
|
-
componentName?: string,
|
|
209
|
-
props?: ThemeProps,
|
|
210
|
-
forceUpdateProp?: any,
|
|
211
|
-
uuid?: Object
|
|
212
|
-
): {
|
|
213
|
-
themes: Record<string, ThemeParsed>
|
|
214
|
-
themeManager: ThemeManager | null
|
|
215
|
-
name: string
|
|
216
|
-
theme: ThemeParsed | null
|
|
217
|
-
className?: string
|
|
218
|
-
} => {
|
|
123
|
+
export const useChangeThemeEffect = (props: ThemeProps, root = false): ChangedThemeResponse => {
|
|
124
|
+
const parentManager = useContext(ThemeManagerContext)
|
|
219
125
|
const config = getConfig()
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
throw new Error(
|
|
224
|
-
`Missing tamagui config, you either have a duplicate config, or haven't set it up. Be sure createTamagui is called before rendering.`
|
|
225
|
-
)
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
|
|
126
|
+
const { debug } = props
|
|
127
|
+
// @ts-expect-error internal use only
|
|
128
|
+
const disable = props.disable
|
|
229
129
|
const { themes } = config
|
|
230
|
-
|
|
231
130
|
if (isRSC) {
|
|
232
131
|
// we need context working for this to work well
|
|
233
|
-
const parentManager = new ThemeManager('light', 'light', themes.light)
|
|
234
|
-
const next = parentManager.getNextTheme({
|
|
235
|
-
name,
|
|
236
|
-
componentName,
|
|
237
|
-
themes,
|
|
238
|
-
reset: props?.reset,
|
|
239
|
-
})
|
|
240
132
|
return {
|
|
241
|
-
...
|
|
133
|
+
...createState().state,
|
|
242
134
|
themes,
|
|
243
135
|
themeManager: null,
|
|
244
136
|
}
|
|
245
137
|
}
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
reset,
|
|
138
|
+
if (disable) {
|
|
139
|
+
if (!parentManager) throw new Error(`Disable topmost`)
|
|
140
|
+
return {
|
|
141
|
+
...parentManager.state,
|
|
142
|
+
isNewTheme: false,
|
|
143
|
+
themes,
|
|
144
|
+
themeManager: parentManager,
|
|
145
|
+
}
|
|
255
146
|
}
|
|
256
|
-
const next = parentManager.getNextTheme(getThemeProps, debug)
|
|
257
|
-
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
258
|
-
const forceUpdate = forceUpdateProp || useForceUpdate()
|
|
259
147
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
// not concurrent safe but fixes native (but breaks SSR and not needed on web (i think) so leave only on native)
|
|
266
|
-
let didChange = false
|
|
267
|
-
if (process.env.TAMAGUI_TARGET === 'native') {
|
|
268
|
-
didChange = Boolean(
|
|
269
|
-
next?.name !== themeManager.name || next?.className !== themeManager.className
|
|
270
|
-
)
|
|
271
|
-
if (didChange) {
|
|
272
|
-
themeManager.update(next, false, false)
|
|
273
|
-
}
|
|
148
|
+
type State = {
|
|
149
|
+
isNewTheme: boolean
|
|
150
|
+
state: ThemeManagerState
|
|
151
|
+
themeManager: ThemeManager
|
|
152
|
+
mounted?: boolean
|
|
274
153
|
}
|
|
275
154
|
|
|
155
|
+
const [themeState, setThemeState] = useState<State>(createState)
|
|
156
|
+
const { isNewTheme, state, themeManager, mounted } = themeState
|
|
157
|
+
|
|
276
158
|
if (!isServer) {
|
|
277
159
|
useLayoutEffect(() => {
|
|
278
|
-
|
|
160
|
+
if (disable) return
|
|
161
|
+
// SSR safe inverse (because server can't know prefers scheme)
|
|
162
|
+
// could be done through fancy selectors like how we do prefers-media
|
|
163
|
+
// but may be a bit of explosion of selectors
|
|
164
|
+
if (props.inverse && !mounted) {
|
|
165
|
+
setThemeState({ ...themeState, mounted: true })
|
|
166
|
+
return
|
|
167
|
+
}
|
|
279
168
|
activeThemeManagers.add(themeManager)
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
if (process.env.NODE_ENV === 'development' && debug) {
|
|
290
|
-
// eslint-disable-next-line no-console
|
|
291
|
-
console.log('Changed theme', componentName, next, { props })
|
|
292
|
-
}
|
|
293
|
-
forceUpdate()
|
|
169
|
+
const disposeChangeListener = parentManager?.onChangeTheme(() => {
|
|
170
|
+
if (!isNewTheme && !isWeb) {
|
|
171
|
+
setThemeState({
|
|
172
|
+
...themeState,
|
|
173
|
+
state: { ...themeManager.state },
|
|
174
|
+
isNewTheme: false,
|
|
175
|
+
})
|
|
176
|
+
} else {
|
|
177
|
+
updateState()
|
|
294
178
|
}
|
|
295
179
|
})
|
|
296
|
-
|
|
297
180
|
return () => {
|
|
298
181
|
activeThemeManagers.delete(themeManager)
|
|
299
|
-
|
|
182
|
+
disposeChangeListener?.()
|
|
300
183
|
}
|
|
301
|
-
|
|
302
|
-
|
|
184
|
+
}, [disable, state, isNewTheme, debug])
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// prettier-ignore
|
|
188
|
+
if (process.env.NODE_ENV === 'development' && debug) console.log('useTheme.render isNewTheme', isNewTheme, props, themeManager.state.name, parentManager?.state.name)
|
|
189
|
+
|
|
190
|
+
// this seems unnecessary
|
|
191
|
+
if (hasNoThemeUpdatingProps(props)) {
|
|
192
|
+
if (!parentManager) throw new Error(`Nada`)
|
|
193
|
+
return {
|
|
194
|
+
...parentManager.state,
|
|
195
|
+
themes,
|
|
196
|
+
themeManager: parentManager,
|
|
197
|
+
isNewTheme: false,
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// run inline in render
|
|
202
|
+
updateState()
|
|
203
|
+
|
|
204
|
+
if (!mounted && !parentManager) {
|
|
205
|
+
throw new Error(`Impossible`)
|
|
303
206
|
}
|
|
304
207
|
|
|
305
208
|
return {
|
|
306
|
-
...
|
|
307
|
-
|
|
308
|
-
theme: parentManager.theme,
|
|
309
|
-
}),
|
|
310
|
-
...next,
|
|
311
|
-
className: next.className === parentManager.className ? undefined : next.className,
|
|
209
|
+
...state,
|
|
210
|
+
isNewTheme,
|
|
312
211
|
themes,
|
|
313
212
|
themeManager,
|
|
213
|
+
...(!mounted &&
|
|
214
|
+
parentManager && {
|
|
215
|
+
...parentManager.state,
|
|
216
|
+
isNewTheme: false,
|
|
217
|
+
themeManager: parentManager,
|
|
218
|
+
}),
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
function createState(prev?: State) {
|
|
222
|
+
const _ = new ThemeManager(props, root ? 'root' : parentManager)
|
|
223
|
+
const isNewTheme = _ !== parentManager
|
|
224
|
+
// prettier-ignore
|
|
225
|
+
if (process.env.NODE_ENV === 'development' && debug) [console.groupCollapsed('useTheme create() isNewTheme', isNewTheme), console.log('parent.state.name', parentManager?.state.name, '\n', 'props', props, '\n', isClient ? parentManager : '', 'getState', isNewTheme && isClient ? _.getState(props) : '', '\n', 'state', isClient ? { ..._.state } : ''), console.groupEnd()]
|
|
226
|
+
// only inverse relies on this for ssr
|
|
227
|
+
const mounted = !props.inverse ? true : root || prev?.mounted || false
|
|
228
|
+
return {
|
|
229
|
+
// ThemeManager returns parentManager if no change
|
|
230
|
+
isNewTheme,
|
|
231
|
+
state: { ..._.state },
|
|
232
|
+
themeManager: _,
|
|
233
|
+
mounted,
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
function updateState() {
|
|
238
|
+
if (themeManager.getStateIfChanged(props, state, parentManager)) {
|
|
239
|
+
setThemeState(createState)
|
|
240
|
+
}
|
|
314
241
|
}
|
|
315
242
|
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { isRSC, useIsomorphicLayoutEffect } from '@tamagui/constants'
|
|
2
|
+
import { useContext, useState } from 'react'
|
|
3
|
+
|
|
4
|
+
import { getConfig } from '../config'
|
|
5
|
+
import { ThemeManagerContext } from '../helpers/ThemeManagerContext'
|
|
6
|
+
import { ThemeName } from '../types'
|
|
7
|
+
|
|
8
|
+
export function useThemeName(opts?: { parent?: true }): ThemeName {
|
|
9
|
+
if (isRSC) {
|
|
10
|
+
const config = getConfig()
|
|
11
|
+
return config.themes[Object.keys(config.themes)[0]] as any
|
|
12
|
+
}
|
|
13
|
+
const manager = useContext(ThemeManagerContext)
|
|
14
|
+
const [name, setName] = useState(manager?.state.name || '')
|
|
15
|
+
|
|
16
|
+
useIsomorphicLayoutEffect(() => {
|
|
17
|
+
if (!manager) return
|
|
18
|
+
setName(manager.state.name)
|
|
19
|
+
return manager.onChangeTheme((next, manager) => {
|
|
20
|
+
const name = opts?.parent ? manager.state.parentName || next : next
|
|
21
|
+
if (!name) return
|
|
22
|
+
setName(name)
|
|
23
|
+
})
|
|
24
|
+
}, [manager?.state.name])
|
|
25
|
+
|
|
26
|
+
return name
|
|
27
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -16,7 +16,7 @@ export * from './setupReactNative'
|
|
|
16
16
|
|
|
17
17
|
// for type portability
|
|
18
18
|
export type { RNWTextProps, RNWViewProps } from './types-rnw'
|
|
19
|
-
export {
|
|
19
|
+
export { getConfig, getThemes, getTokens, onConfiguredOnce } from './config'
|
|
20
20
|
|
|
21
21
|
export * from './constants/constants'
|
|
22
22
|
|
|
@@ -36,7 +36,7 @@ export * from './helpers/matchMedia'
|
|
|
36
36
|
export * from './helpers/themeable'
|
|
37
37
|
export * from './helpers/withStaticProperties'
|
|
38
38
|
|
|
39
|
-
export * from './contexts/
|
|
39
|
+
export * from './contexts/ButtonNestingContext'
|
|
40
40
|
|
|
41
41
|
export * from './hooks/useId'
|
|
42
42
|
export * from './hooks/useIsTouchDevice'
|
|
@@ -53,6 +53,7 @@ export {
|
|
|
53
53
|
mediaQueryConfig,
|
|
54
54
|
} from './hooks/useMedia'
|
|
55
55
|
export * from './hooks/useTheme'
|
|
56
|
+
export * from './hooks/useThemeName'
|
|
56
57
|
export * from './hooks/useSafeRef'
|
|
57
58
|
|
|
58
59
|
export * from './views/Slot'
|
|
@@ -60,9 +61,7 @@ export * from './views/Stack'
|
|
|
60
61
|
export * from './views/Text'
|
|
61
62
|
export * from './contexts/TextAncestorContext'
|
|
62
63
|
export * from './views/Theme'
|
|
63
|
-
export * from './views/ThemeInverse'
|
|
64
64
|
export * from './views/ThemeProvider'
|
|
65
|
-
export * from './views/ThemeReset'
|
|
66
65
|
export * from './views/FontLanguage'
|
|
67
66
|
export * from './views/TamaguiProvider'
|
|
68
67
|
|
package/src/setupReactNative.ts
CHANGED
|
@@ -1,9 +1,20 @@
|
|
|
1
|
-
|
|
1
|
+
import { StaticConfig } from './types'
|
|
2
2
|
|
|
3
|
-
export
|
|
4
|
-
|
|
3
|
+
export const ReactNativeStaticConfigs = new WeakMap<any, Partial<StaticConfig> | null>()
|
|
4
|
+
|
|
5
|
+
export function getReactNativeConfig(Component: any) {
|
|
6
|
+
return ReactNativeStaticConfigs.get(Component)
|
|
5
7
|
}
|
|
6
8
|
|
|
7
|
-
export function setupReactNative(
|
|
8
|
-
|
|
9
|
+
export function setupReactNative(rnExports: Record<string, any>) {
|
|
10
|
+
for (const key in rnExports) {
|
|
11
|
+
if (key[0].toLowerCase() === key[0]) continue
|
|
12
|
+
if (!rnExports[key]) continue
|
|
13
|
+
ReactNativeStaticConfigs.set(rnExports[key], {
|
|
14
|
+
isReactNative: true,
|
|
15
|
+
isText: key === 'Text' || key === 'TextInput',
|
|
16
|
+
isInput: key === 'TextInput',
|
|
17
|
+
inlineProps: key === 'Image' ? new Set(['src', 'width', 'height']) : undefined,
|
|
18
|
+
})
|
|
19
|
+
}
|
|
9
20
|
}
|
package/src/styled.tsx
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { getConfig } from './config'
|
|
2
1
|
import { createComponent } from './createComponent'
|
|
3
|
-
import {
|
|
2
|
+
import { ReactNativeStaticConfigs } from './setupReactNative'
|
|
4
3
|
import {
|
|
5
4
|
GetProps,
|
|
6
5
|
GetVariantValues,
|
|
@@ -35,8 +34,6 @@ type GetVariantProps<A extends StylableComponent> =
|
|
|
35
34
|
// :
|
|
36
35
|
A extends TamaguiComponent<any, any, any, infer V> ? V : {}
|
|
37
36
|
|
|
38
|
-
let RNComponentConfigs: WeakMap<any, Partial<StaticConfig>> | null = null
|
|
39
|
-
|
|
40
37
|
export function styled<
|
|
41
38
|
ParentComponent extends StylableComponent,
|
|
42
39
|
Variants extends VariantDefinitions<ParentComponent> | void = VariantDefinitions<ParentComponent> | void
|
|
@@ -62,21 +59,6 @@ export function styled<
|
|
|
62
59
|
// }
|
|
63
60
|
// }
|
|
64
61
|
|
|
65
|
-
const RN = getReactNative()
|
|
66
|
-
if (RN && typeof RN === 'object' && !RNComponentConfigs) {
|
|
67
|
-
RNComponentConfigs = new WeakMap()
|
|
68
|
-
for (const key in RN) {
|
|
69
|
-
const val = RN[key]
|
|
70
|
-
if (!val) continue
|
|
71
|
-
if (key[0].toLowerCase() === key[0]) continue
|
|
72
|
-
RNComponentConfigs.set(val, {
|
|
73
|
-
isReactNative: true,
|
|
74
|
-
isText: key === 'Text' || key === 'TextInput',
|
|
75
|
-
inlineProps: key === 'Image' ? new Set(['src', 'width', 'height']) : undefined,
|
|
76
|
-
})
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
62
|
const staticConfigProps = (() => {
|
|
81
63
|
const parentStaticConfig =
|
|
82
64
|
'staticConfig' in Component ? (Component.staticConfig as StaticConfig) : null
|
|
@@ -105,16 +87,15 @@ export function styled<
|
|
|
105
87
|
Object.assign(defaultProps, defaultVariants)
|
|
106
88
|
}
|
|
107
89
|
const isReactNative = Boolean(
|
|
108
|
-
(
|
|
109
|
-
|
|
110
|
-
RNComponentConfigs.has(parentStaticConfig?.Component))) ||
|
|
90
|
+
ReactNativeStaticConfigs.has(Component) ||
|
|
91
|
+
ReactNativeStaticConfigs.has(parentStaticConfig?.Component) ||
|
|
111
92
|
parentStaticConfig?.isReactNative ||
|
|
112
93
|
staticExtractionOptions?.isReactNative
|
|
113
94
|
)
|
|
114
95
|
const isTamagui = !isReactNative && !!parentStaticConfig
|
|
115
96
|
|
|
116
97
|
const Comp = isReactNative ? parentStaticConfig?.Component || Component : (Component as any)
|
|
117
|
-
const nativeConf = (isReactNative &&
|
|
98
|
+
const nativeConf = (isReactNative && ReactNativeStaticConfigs.get(Comp)) || null
|
|
118
99
|
|
|
119
100
|
const isText = Boolean(staticExtractionOptions?.isText || parentStaticConfig?.isText)
|
|
120
101
|
const acceptsClassName = acceptsClassNameProp ?? (isTamagui || isReactNative)
|