@tamagui/core 1.0.1-rc.8 → 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.
- package/dist/cjs/Pressability.js +32 -0
- package/dist/cjs/Pressability.js.map +7 -0
- package/dist/cjs/Pressability.native.js +32 -0
- package/dist/cjs/Pressability.native.js.map +7 -0
- package/dist/cjs/ThemeContext.js +30 -0
- package/dist/cjs/ThemeContext.js.map +7 -0
- package/dist/cjs/ThemeManager.js +211 -0
- package/dist/cjs/ThemeManager.js.map +7 -0
- package/dist/cjs/conf.js +70 -0
- package/dist/cjs/conf.js.map +7 -0
- package/dist/cjs/constants/platform.js +4 -10
- package/dist/cjs/constants/platform.js.map +2 -2
- package/dist/cjs/constants/rnw.native.js +28 -0
- package/dist/cjs/constants/rnw.native.js.map +7 -0
- package/dist/cjs/contexts/ButtonInsideButtonContext.js.map +1 -1
- package/dist/cjs/createComponent.js +25 -27
- package/dist/cjs/createComponent.js.map +2 -2
- package/dist/cjs/createTamagui.js +4 -1
- package/dist/cjs/createTamagui.js.map +2 -2
- package/dist/cjs/defaultComponentState.js +2 -0
- package/dist/cjs/defaultComponentState.js.map +7 -0
- package/dist/cjs/helpers/ThemeManager.js +4 -2
- package/dist/cjs/helpers/ThemeManager.js.map +2 -2
- package/dist/cjs/helpers/Unwrap.js +29 -0
- package/dist/cjs/helpers/Unwrap.js.map +7 -0
- package/dist/cjs/helpers/assignNativePropsToWeb.js.map +1 -1
- package/dist/cjs/helpers/assignNativePropsToWeb.native.js.map +1 -1
- package/dist/cjs/helpers/cache.js +7 -11
- package/dist/cjs/helpers/cache.js.map +2 -2
- package/dist/cjs/helpers/calc.js.map +2 -2
- package/dist/cjs/helpers/createShallowUpdate.js +9 -12
- package/dist/cjs/helpers/createShallowUpdate.js.map +1 -1
- package/dist/cjs/helpers/createTamaguiProvider.js +65 -0
- package/dist/cjs/helpers/createTamaguiProvider.js.map +7 -0
- package/dist/cjs/helpers/cssHash.js +51 -0
- package/dist/cjs/helpers/cssHash.js.map +7 -0
- package/dist/cjs/helpers/expandStyle.js +29 -41
- package/dist/cjs/helpers/expandStyle.js.map +2 -2
- package/dist/cjs/helpers/expandStyle.test.js +10 -0
- package/dist/cjs/helpers/expandStyle.test.js.map +7 -0
- package/dist/cjs/helpers/getFont.js +2 -6
- package/dist/cjs/helpers/getFont.js.map +2 -2
- package/dist/cjs/helpers/getSplitStyles.js +22 -23
- package/dist/cjs/helpers/getSplitStyles.js.map +2 -2
- package/dist/cjs/helpers/getStackSize.js.map +1 -1
- package/dist/cjs/helpers/getStylesAtomic.js +10 -11
- package/dist/cjs/helpers/getStylesAtomic.js.map +2 -2
- package/dist/cjs/helpers/insertStyleRule.js +58 -27
- package/dist/cjs/helpers/insertStyleRule.js.map +3 -3
- package/dist/cjs/helpers/nativeGestureHandler.native.js +19 -0
- package/dist/cjs/helpers/nativeGestureHandler.native.js.map +7 -0
- package/dist/cjs/helpers/normalizeValueWithProperty.js +3 -3
- package/dist/cjs/helpers/normalizeValueWithProperty.js.map +2 -2
- package/dist/cjs/helpers/startTransition.js +1 -4
- package/dist/cjs/helpers/startTransition.js.map +2 -2
- package/dist/cjs/helpers/themeable.js +2 -2
- package/dist/cjs/helpers/themeable.js.map +2 -2
- package/dist/cjs/helpers/wrapThemeManagerContext.js +37 -0
- package/dist/cjs/helpers/wrapThemeManagerContext.js.map +7 -0
- package/dist/cjs/hooks/useConstant.js +0 -3
- package/dist/cjs/hooks/useConstant.js.map +2 -2
- package/dist/cjs/hooks/useElementLayout.js +1 -1
- package/dist/cjs/hooks/useElementLayout.js.map +2 -2
- package/dist/cjs/hooks/useFeatures.js +201 -0
- package/dist/cjs/hooks/useFeatures.js.map +7 -0
- package/dist/cjs/hooks/useIsMounted.js.map +1 -1
- package/dist/cjs/hooks/useIsSSR.js +6 -10
- package/dist/cjs/hooks/useIsSSR.js.map +2 -2
- package/dist/cjs/hooks/useMedia.js +5 -0
- package/dist/cjs/hooks/useMedia.js.map +2 -2
- package/dist/cjs/hooks/usePressable.js.map +1 -1
- package/dist/cjs/hooks/usePrevious.js +1 -0
- package/dist/cjs/hooks/usePrevious.js.map +7 -0
- package/dist/cjs/hooks/useTheme.js +45 -50
- package/dist/cjs/hooks/useTheme.js.map +3 -3
- package/dist/cjs/hooks/useUnmountEffect.js.map +1 -1
- package/dist/cjs/styled.js +12 -0
- package/dist/cjs/styled.js.map +2 -2
- package/dist/cjs/views/TamaguiProvider.js +3 -0
- package/dist/cjs/views/TamaguiProvider.js.map +2 -2
- package/dist/cjs/views/TextAncestorContext.js +44 -0
- package/dist/cjs/views/TextAncestorContext.js.map +7 -0
- package/dist/cjs/views/Theme.js +15 -21
- package/dist/cjs/views/Theme.js.map +3 -3
- package/dist/cjs/views/ThemeInverse.js +20 -21
- package/dist/cjs/views/ThemeInverse.js.map +2 -2
- package/dist/cjs/views/ThemeReset.js +5 -10
- package/dist/cjs/views/ThemeReset.js.map +3 -3
- package/dist/esm/Pressability.js +7 -0
- package/dist/esm/Pressability.js.map +7 -0
- package/dist/esm/Pressability.native.js +7 -0
- package/dist/esm/Pressability.native.js.map +7 -0
- package/dist/esm/ThemeContext.js +6 -0
- package/dist/esm/ThemeContext.js.map +7 -0
- package/dist/esm/ThemeManager.js +185 -0
- package/dist/esm/ThemeManager.js.map +7 -0
- package/dist/esm/conf.js +39 -0
- package/dist/esm/conf.js.map +7 -0
- package/dist/esm/constants/platform.js +3 -7
- package/dist/esm/constants/platform.js.map +2 -2
- package/dist/esm/constants/rnw.native.js +5 -0
- package/dist/esm/constants/rnw.native.js.map +7 -0
- package/dist/esm/contexts/ButtonInsideButtonContext.js.map +1 -1
- package/dist/esm/createComponent.js +26 -28
- package/dist/esm/createComponent.js.map +2 -2
- package/dist/esm/createTamagui.js +9 -2
- package/dist/esm/createTamagui.js.map +2 -2
- package/dist/esm/defaultComponentState.js +1 -0
- package/dist/esm/defaultComponentState.js.map +7 -0
- package/dist/esm/helpers/ThemeManager.js +4 -2
- package/dist/esm/helpers/ThemeManager.js.map +2 -2
- package/dist/esm/helpers/Unwrap.js +5 -0
- package/dist/esm/helpers/Unwrap.js.map +7 -0
- package/dist/esm/helpers/assignNativePropsToWeb.js.map +1 -1
- package/dist/esm/helpers/assignNativePropsToWeb.native.js.map +1 -1
- package/dist/esm/helpers/cache.js +7 -10
- package/dist/esm/helpers/cache.js.map +2 -2
- package/dist/esm/helpers/calc.js.map +2 -2
- package/dist/esm/helpers/createShallowUpdate.js +9 -12
- package/dist/esm/helpers/createShallowUpdate.js.map +1 -1
- package/dist/esm/helpers/createTamaguiProvider.js +38 -0
- package/dist/esm/helpers/createTamaguiProvider.js.map +7 -0
- package/dist/esm/helpers/cssHash.js +27 -0
- package/dist/esm/helpers/cssHash.js.map +7 -0
- package/dist/esm/helpers/expandStyle.js +26 -38
- package/dist/esm/helpers/expandStyle.js.map +2 -2
- package/dist/esm/helpers/expandStyle.test.js +9 -0
- package/dist/esm/helpers/expandStyle.test.js.map +7 -0
- package/dist/esm/helpers/getFont.js +2 -6
- package/dist/esm/helpers/getFont.js.map +2 -2
- package/dist/esm/helpers/getSplitStyles.js +24 -24
- package/dist/esm/helpers/getSplitStyles.js.map +2 -2
- package/dist/esm/helpers/getStackSize.js.map +1 -1
- package/dist/esm/helpers/getStylesAtomic.js +10 -11
- package/dist/esm/helpers/getStylesAtomic.js.map +2 -2
- package/dist/esm/helpers/insertStyleRule.js +56 -26
- package/dist/esm/helpers/insertStyleRule.js.map +3 -3
- package/dist/esm/helpers/nativeGestureHandler.native.js +2 -0
- package/dist/esm/helpers/nativeGestureHandler.native.js.map +7 -0
- package/dist/esm/helpers/normalizeValueWithProperty.js +3 -3
- package/dist/esm/helpers/normalizeValueWithProperty.js.map +2 -2
- package/dist/esm/helpers/startTransition.js.map +1 -1
- package/dist/esm/helpers/themeable.js +2 -2
- package/dist/esm/helpers/themeable.js.map +2 -2
- package/dist/esm/helpers/wrapThemeManagerContext.js +11 -0
- package/dist/esm/helpers/wrapThemeManagerContext.js.map +7 -0
- package/dist/esm/hooks/useConstant.js +1 -4
- package/dist/esm/hooks/useConstant.js.map +2 -2
- package/dist/esm/hooks/useElementLayout.js +1 -1
- package/dist/esm/hooks/useElementLayout.js.map +2 -2
- package/dist/esm/hooks/useFeatures.js +174 -0
- package/dist/esm/hooks/useFeatures.js.map +7 -0
- package/dist/esm/hooks/useIsMounted.js.map +1 -1
- package/dist/esm/hooks/useIsSSR.js +8 -12
- package/dist/esm/hooks/useIsSSR.js.map +2 -2
- package/dist/esm/hooks/useMedia.js +4 -0
- package/dist/esm/hooks/useMedia.js.map +2 -2
- package/dist/esm/hooks/usePressable.js.map +1 -1
- package/dist/esm/hooks/usePrevious.js +1 -0
- package/dist/esm/hooks/usePrevious.js.map +7 -0
- package/dist/esm/hooks/useTheme.js +45 -50
- package/dist/esm/hooks/useTheme.js.map +3 -3
- package/dist/esm/hooks/useUnmountEffect.js.map +1 -1
- package/dist/esm/styled.js +12 -0
- package/dist/esm/styled.js.map +2 -2
- package/dist/esm/views/TamaguiProvider.js +3 -0
- package/dist/esm/views/TamaguiProvider.js.map +2 -2
- package/dist/esm/views/TextAncestorContext.js +15 -0
- package/dist/esm/views/TextAncestorContext.js.map +7 -0
- package/dist/esm/views/Theme.js +14 -14
- package/dist/esm/views/Theme.js.map +2 -2
- package/dist/esm/views/ThemeInverse.js +15 -20
- package/dist/esm/views/ThemeInverse.js.map +2 -2
- package/dist/esm/views/ThemeReset.js +4 -6
- package/dist/esm/views/ThemeReset.js.map +2 -2
- package/package.json +13 -14
- package/src/createComponent.tsx +47 -43
- package/src/createTamagui.ts +10 -2
- package/src/helpers/ThemeManager.tsx +7 -2
- package/src/helpers/cache.ts +7 -9
- package/src/helpers/expandStyle.ts +27 -41
- package/src/helpers/getSplitStyles.tsx +40 -23
- package/src/helpers/getStylesAtomic.ts +15 -15
- package/src/helpers/insertStyleRule.tsx +68 -38
- package/src/helpers/normalizeValueWithProperty.ts +3 -3
- package/src/helpers/themeable.tsx +3 -3
- package/src/hooks/useElementLayout.tsx +1 -1
- package/src/hooks/useMedia.tsx +3 -0
- package/src/hooks/useTheme.tsx +67 -48
- package/src/styled.tsx +15 -0
- package/src/views/TamaguiProvider.tsx +6 -0
- package/src/views/Theme.tsx +15 -22
- package/types/createComponent.d.ts +1 -1
- package/types/helpers/ThemeManager.d.ts +1 -1
- package/types/helpers/cache.d.ts +2 -4
- package/types/helpers/insertStyleRule.d.ts +2 -1
- package/types/helpers/themeable.d.ts +1 -1
- package/types/hooks/useMedia.d.ts +1 -0
- package/types/hooks/useTheme.d.ts +1 -1
- package/types/views/Theme.d.ts +1 -1
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
// this needs to check if its inserted already? 99% of the time it is
|
|
2
|
-
// this should avoid re-inserts, but need to test the perf trade-offs
|
|
3
|
-
// i tested with the site itself and the initial insert was trivial
|
|
4
|
-
|
|
5
1
|
import type { StyleObject } from '@tamagui/helpers'
|
|
6
2
|
|
|
7
3
|
const allSelectors: Record<string, string> = {}
|
|
@@ -17,18 +13,7 @@ function addTransform(identifier: string, css: string, rule?: CSSRule) {
|
|
|
17
13
|
const s = css.indexOf('transform:')
|
|
18
14
|
if (s === -1) {
|
|
19
15
|
if (process.env.NODE_ENV === 'development') {
|
|
20
|
-
|
|
21
|
-
console.groupCollapsed(
|
|
22
|
-
`❌ Invalid transform, likely used deg/% improperly ${identifier}`
|
|
23
|
-
)
|
|
24
|
-
// eslint-disable-next-line no-console
|
|
25
|
-
console.log('rule:', rule)
|
|
26
|
-
// eslint-disable-next-line no-console
|
|
27
|
-
console.trace()
|
|
28
|
-
// eslint-disable-next-line no-console
|
|
29
|
-
console.groupEnd()
|
|
30
|
-
} else {
|
|
31
|
-
// missing transform
|
|
16
|
+
console.error(`❌ Invalid transform, likely used deg/% improperly ${identifier}`)
|
|
32
17
|
}
|
|
33
18
|
return false
|
|
34
19
|
}
|
|
@@ -50,9 +35,31 @@ const isClient = typeof document !== 'undefined'
|
|
|
50
35
|
// 1. debugging at dev time
|
|
51
36
|
// 2. avoid duplicate insert styles at runtime
|
|
52
37
|
// 3. used now for merging transforms atomically
|
|
38
|
+
|
|
39
|
+
// multiple sheets could have the same ids so we have to count
|
|
40
|
+
|
|
53
41
|
const scannedNum = new WeakMap<CSSStyleSheet, number>()
|
|
42
|
+
const totalSheetSelectors = new Map<string, number>()
|
|
43
|
+
|
|
44
|
+
export function listenForSheetChanges() {
|
|
45
|
+
if (!isClient) return
|
|
46
|
+
function handleNode(node: Node, remove = false) {
|
|
47
|
+
if (node instanceof HTMLStyleElement && node.sheet) {
|
|
48
|
+
updateSheetStyles(node.sheet, remove)
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
const mo = new MutationObserver((entries) => {
|
|
52
|
+
for (const entry of entries) {
|
|
53
|
+
entry.addedNodes.forEach((node) => handleNode(node))
|
|
54
|
+
entry.removedNodes.forEach((node) => handleNode(node, true))
|
|
55
|
+
}
|
|
56
|
+
})
|
|
57
|
+
mo.observe(document.head, {
|
|
58
|
+
childList: true,
|
|
59
|
+
})
|
|
60
|
+
}
|
|
54
61
|
|
|
55
|
-
export function
|
|
62
|
+
export function scanAllSheets() {
|
|
56
63
|
if (process.env.NODE_ENV === 'test') return
|
|
57
64
|
if (!isClient) return
|
|
58
65
|
const sheets = document.styleSheets
|
|
@@ -60,28 +67,53 @@ export function updateInserted() {
|
|
|
60
67
|
for (let i = 0; i < sheets.length; i++) {
|
|
61
68
|
const sheet = sheets[i]
|
|
62
69
|
if (!sheet) continue
|
|
70
|
+
updateSheetStyles(sheet)
|
|
71
|
+
}
|
|
72
|
+
}
|
|
63
73
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
} catch {
|
|
70
|
-
continue
|
|
71
|
-
}
|
|
74
|
+
function track(id: string, remove = false) {
|
|
75
|
+
const next = (totalSheetSelectors.get(id) || 0) + (remove ? -1 : 1)
|
|
76
|
+
totalSheetSelectors.set(id, next)
|
|
77
|
+
return next
|
|
78
|
+
}
|
|
72
79
|
|
|
73
|
-
|
|
74
|
-
|
|
80
|
+
function updateSheetStyles(sheet: CSSStyleSheet, remove = false) {
|
|
81
|
+
// avoid errors on cross origin sheets
|
|
82
|
+
// https://stackoverflow.com/questions/49993633/uncaught-domexception-failed-to-read-the-cssrules-property
|
|
83
|
+
let rules: CSSRuleList
|
|
84
|
+
try {
|
|
85
|
+
rules = sheet.cssRules
|
|
86
|
+
} catch {
|
|
87
|
+
return
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const len = rules.length
|
|
91
|
+
const lastScanned = scannedNum.get(sheet) || 0
|
|
92
|
+
|
|
93
|
+
if (!remove) {
|
|
94
|
+
// avoid work dumb but works
|
|
75
95
|
if (lastScanned === len) {
|
|
76
|
-
|
|
96
|
+
return
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
for (let i = lastScanned; i < len; i++) {
|
|
101
|
+
const rule = rules[i]
|
|
102
|
+
const response = getTamaguiSelector(rule)
|
|
103
|
+
if (!response) {
|
|
104
|
+
return
|
|
77
105
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
106
|
+
|
|
107
|
+
const [identifier, cssRule] = response
|
|
108
|
+
|
|
109
|
+
// track references
|
|
110
|
+
const total = track(identifier, remove)
|
|
111
|
+
|
|
112
|
+
if (remove) {
|
|
113
|
+
if (total === 0) {
|
|
114
|
+
delete allSelectors[identifier]
|
|
83
115
|
}
|
|
84
|
-
|
|
116
|
+
} else {
|
|
85
117
|
if (!(identifier in allSelectors)) {
|
|
86
118
|
const isTransform = identifier.startsWith('_transform')
|
|
87
119
|
const shouldInsert = isTransform
|
|
@@ -92,8 +124,9 @@ export function updateInserted() {
|
|
|
92
124
|
}
|
|
93
125
|
}
|
|
94
126
|
}
|
|
95
|
-
scannedNum.set(sheet, i)
|
|
96
127
|
}
|
|
128
|
+
|
|
129
|
+
scannedNum.set(sheet, len)
|
|
97
130
|
}
|
|
98
131
|
|
|
99
132
|
function getTamaguiSelector(
|
|
@@ -122,9 +155,6 @@ const getIdentifierFromTamaguiSelector = (selector: string) =>
|
|
|
122
155
|
.replace(/:[a-z]+$/, '')
|
|
123
156
|
.slice(1)
|
|
124
157
|
|
|
125
|
-
// move this to probably inside createTamagui
|
|
126
|
-
updateInserted()
|
|
127
|
-
|
|
128
158
|
const sheet = isClient
|
|
129
159
|
? document.head.appendChild(document.createElement('style')).sheet
|
|
130
160
|
: null
|
|
@@ -11,13 +11,13 @@ import { normalizeColor } from './normalizeColor'
|
|
|
11
11
|
const cache = {}
|
|
12
12
|
|
|
13
13
|
export function normalizeValueWithProperty(value: any, property?: string): any {
|
|
14
|
-
if (property && unitlessNumbers[property]) {
|
|
15
|
-
return value
|
|
16
|
-
}
|
|
17
14
|
const cached = cache[value]
|
|
18
15
|
if (cached !== undefined) {
|
|
19
16
|
return cached
|
|
20
17
|
}
|
|
18
|
+
if (property && property in unitlessNumbers) {
|
|
19
|
+
return value
|
|
20
|
+
}
|
|
21
21
|
let res = value
|
|
22
22
|
if (
|
|
23
23
|
process.env.TAMAGUI_TARGET === 'web' &&
|
|
@@ -6,9 +6,9 @@ import { Theme } from '../views/Theme'
|
|
|
6
6
|
export interface ThemeableProps {
|
|
7
7
|
theme?: ThemeName | null
|
|
8
8
|
themeInverse?: boolean
|
|
9
|
+
themeReset?: boolean
|
|
9
10
|
componentName?: string
|
|
10
11
|
debug?: boolean | 'verbose'
|
|
11
|
-
reset?: boolean
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
export function themeable<Component extends (props: any) => any>(
|
|
@@ -16,7 +16,7 @@ export function themeable<Component extends (props: any) => any>(
|
|
|
16
16
|
opts?: { componentName?: string }
|
|
17
17
|
) {
|
|
18
18
|
const withThemeComponent = forwardRef(function WithTheme(props: ThemeableProps, ref) {
|
|
19
|
-
const { themeInverse, theme, componentName,
|
|
19
|
+
const { themeInverse, theme, componentName, themeReset, ...rest } = props
|
|
20
20
|
const element = React.createElement(component, { ...rest, ref } as any)
|
|
21
21
|
|
|
22
22
|
return (
|
|
@@ -26,7 +26,7 @@ export function themeable<Component extends (props: any) => any>(
|
|
|
26
26
|
name={(theme as any) || null}
|
|
27
27
|
data-themeable
|
|
28
28
|
debug={props.debug}
|
|
29
|
-
reset={props.
|
|
29
|
+
reset={props.themeReset}
|
|
30
30
|
>
|
|
31
31
|
{element}
|
|
32
32
|
</Theme>
|
|
@@ -73,7 +73,7 @@ export function useElementLayout(
|
|
|
73
73
|
// Observing is done in a separate effect to avoid this effect running
|
|
74
74
|
// when 'onLayout' changes.
|
|
75
75
|
useIsomorphicLayoutEffect(() => {
|
|
76
|
-
if (!
|
|
76
|
+
if (!resizeObserver || !hasLayoutEvent) return
|
|
77
77
|
const node = ref.current
|
|
78
78
|
if (!node) return
|
|
79
79
|
LayoutHandlers.set(node, onLayoutEvent)
|
package/src/hooks/useMedia.tsx
CHANGED
|
@@ -35,6 +35,7 @@ export const mediaState: MediaQueryState =
|
|
|
35
35
|
|
|
36
36
|
export const mediaQueryConfig: MediaQueries = {}
|
|
37
37
|
export const getMedia = () => mediaState
|
|
38
|
+
export const mediaKeysWithAndWithout$ = new Set<string>()
|
|
38
39
|
|
|
39
40
|
// for SSR capture it at time of startup
|
|
40
41
|
let initState: MediaQueryState
|
|
@@ -58,6 +59,8 @@ export const configureMedia = (config: TamaguiInternalConfig) => {
|
|
|
58
59
|
if (!media) return
|
|
59
60
|
for (const key in media) {
|
|
60
61
|
mediaState[key] = mediaQueryDefaultActive?.[key] || false
|
|
62
|
+
mediaKeysWithAndWithout$.add(key)
|
|
63
|
+
mediaKeysWithAndWithout$.add(`$${key}`)
|
|
61
64
|
}
|
|
62
65
|
Object.assign(mediaQueryConfig, media)
|
|
63
66
|
initState = { ...mediaState }
|
package/src/hooks/useTheme.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* eslint-disable no-console */
|
|
2
2
|
import { isClient, isRSC, isServer, isWeb } from '@tamagui/constants'
|
|
3
|
-
import { useContext, useEffect,
|
|
3
|
+
import { useContext, useEffect, useMemo, useState } from 'react'
|
|
4
4
|
|
|
5
5
|
import { getConfig } from '../config'
|
|
6
6
|
import { isDevTools } from '../constants/isDevTools'
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
import { ThemeManagerContext } from '../helpers/ThemeManagerContext'
|
|
14
14
|
import { ThemeParsed, ThemeProps } from '../types'
|
|
15
15
|
import { GetThemeUnwrapped } from './getThemeUnwrapped'
|
|
16
|
+
import { useServerRef } from './useServerHooks'
|
|
16
17
|
|
|
17
18
|
export type ChangedThemeResponse = {
|
|
18
19
|
themeManager: ThemeManager | null
|
|
@@ -33,12 +34,28 @@ function getDefaultThemeProxied() {
|
|
|
33
34
|
})
|
|
34
35
|
}
|
|
35
36
|
|
|
37
|
+
interface UseThemeState {
|
|
38
|
+
keys: Set<string>
|
|
39
|
+
}
|
|
40
|
+
|
|
36
41
|
export const useTheme = (props: ThemeProps = emptyProps): ThemeParsed => {
|
|
37
42
|
if (isRSC) {
|
|
38
43
|
return getDefaultThemeProxied()
|
|
39
44
|
}
|
|
40
45
|
|
|
41
|
-
const
|
|
46
|
+
const state = useServerRef() as React.MutableRefObject<UseThemeState>
|
|
47
|
+
if (isClient && !state.current) {
|
|
48
|
+
state.current = {
|
|
49
|
+
keys: new Set(),
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
state.current?.keys.clear()
|
|
53
|
+
|
|
54
|
+
const { name, theme, themeManager, className, isNewTheme } = useChangeThemeEffect(
|
|
55
|
+
props,
|
|
56
|
+
false,
|
|
57
|
+
isClient ? () => state.current.keys.size === 0 : undefined
|
|
58
|
+
)
|
|
42
59
|
|
|
43
60
|
if (process.env.NODE_ENV === 'development') {
|
|
44
61
|
// ensure we aren't creating too many ThemeManagers
|
|
@@ -73,6 +90,7 @@ export const useTheme = (props: ThemeProps = emptyProps): ThemeParsed => {
|
|
|
73
90
|
name,
|
|
74
91
|
className,
|
|
75
92
|
themeManager,
|
|
93
|
+
state,
|
|
76
94
|
})
|
|
77
95
|
}, [theme, isNewTheme, name, className, themeManager])
|
|
78
96
|
}
|
|
@@ -83,12 +101,14 @@ function getThemeProxied({
|
|
|
83
101
|
className,
|
|
84
102
|
themeManager,
|
|
85
103
|
isNewTheme,
|
|
104
|
+
state,
|
|
86
105
|
}: {
|
|
87
106
|
theme: any
|
|
88
107
|
name: string
|
|
89
108
|
className?: string
|
|
90
109
|
themeManager?: ThemeManager | null
|
|
91
110
|
isNewTheme?: boolean
|
|
111
|
+
state?: React.RefObject<UseThemeState>
|
|
92
112
|
}) {
|
|
93
113
|
return createProxy(theme, {
|
|
94
114
|
has(_, key) {
|
|
@@ -122,7 +142,20 @@ function getThemeProxied({
|
|
|
122
142
|
if (!themeManager) {
|
|
123
143
|
return theme[key]
|
|
124
144
|
}
|
|
125
|
-
|
|
145
|
+
const val = themeManager.getValue(key)
|
|
146
|
+
if (val && state) {
|
|
147
|
+
if (isClient) {
|
|
148
|
+
return new Proxy(val as any, {
|
|
149
|
+
get(_, subkey) {
|
|
150
|
+
if (subkey === 'val') {
|
|
151
|
+
state.current!.keys.add(key as any)
|
|
152
|
+
}
|
|
153
|
+
return Reflect.get(val, subkey)
|
|
154
|
+
},
|
|
155
|
+
})
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return val
|
|
126
159
|
},
|
|
127
160
|
})
|
|
128
161
|
}
|
|
@@ -139,7 +172,8 @@ export const activeThemeManagers = new Set<ThemeManager>()
|
|
|
139
172
|
|
|
140
173
|
export const useChangeThemeEffect = (
|
|
141
174
|
props: ThemeProps,
|
|
142
|
-
root = false
|
|
175
|
+
root = false,
|
|
176
|
+
disableUpdate?: () => boolean
|
|
143
177
|
): ChangedThemeResponse => {
|
|
144
178
|
if (isRSC) {
|
|
145
179
|
// we need context working for this to work well
|
|
@@ -186,20 +220,16 @@ export const useChangeThemeEffect = (
|
|
|
186
220
|
return
|
|
187
221
|
}
|
|
188
222
|
activeThemeManagers.add(themeManager)
|
|
189
|
-
const disposeChangeListener = parentManager?.onChangeTheme(() => {
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
} else {
|
|
197
|
-
updateState()
|
|
198
|
-
}
|
|
199
|
-
})
|
|
223
|
+
// const disposeChangeListener = parentManager?.onChangeTheme((name, manager) => {
|
|
224
|
+
// // console.log('hi', props, state, name, manager)
|
|
225
|
+
// if (state.theme !== manager.state.theme) {
|
|
226
|
+
// console.warn('now update to', manager.state.name)
|
|
227
|
+
// updateState(manager)
|
|
228
|
+
// }
|
|
229
|
+
// })
|
|
200
230
|
return () => {
|
|
201
231
|
activeThemeManagers.delete(themeManager)
|
|
202
|
-
disposeChangeListener?.()
|
|
232
|
+
// disposeChangeListener?.()
|
|
203
233
|
}
|
|
204
234
|
}, [disable, state, isNewTheme, debug])
|
|
205
235
|
}
|
|
@@ -209,13 +239,8 @@ export const useChangeThemeEffect = (
|
|
|
209
239
|
|
|
210
240
|
if (shouldReturnParentState) {
|
|
211
241
|
if (!parentManager) throw 'impossible'
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
'useTheme hasNoThemeUpdatingProps',
|
|
215
|
-
parentManager.state.name,
|
|
216
|
-
'isInversingOnMount',
|
|
217
|
-
isInversingOnMount
|
|
218
|
-
)
|
|
242
|
+
// prettier-ignore
|
|
243
|
+
if (process.env.NODE_ENV === 'development' && props.debug === 'verbose') console.log('useTheme hasNoThemeUpdatingProps', parentManager.state.name, 'isInversingOnMount', isInversingOnMount)
|
|
219
244
|
return {
|
|
220
245
|
...parentManager.state,
|
|
221
246
|
className: isInversingOnMount ? '' : parentManager.state.className,
|
|
@@ -234,27 +259,19 @@ export const useChangeThemeEffect = (
|
|
|
234
259
|
}
|
|
235
260
|
|
|
236
261
|
function createState(prev?: State) {
|
|
262
|
+
if (prev && disableUpdate?.()) {
|
|
263
|
+
return prev
|
|
264
|
+
}
|
|
265
|
+
// returns previous theme manager if no change
|
|
237
266
|
const _ = new ThemeManager(props, root ? 'root' : parentManager)
|
|
238
267
|
const isNewTheme = _ !== parentManager
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
'props',
|
|
247
|
-
props,
|
|
248
|
-
'\n',
|
|
249
|
-
isClient ? parentManager : '',
|
|
250
|
-
'getState',
|
|
251
|
-
isNewTheme && isClient ? _.getState(props) : '',
|
|
252
|
-
'\n',
|
|
253
|
-
'state',
|
|
254
|
-
isClient ? { ..._.state } : ''
|
|
255
|
-
),
|
|
256
|
-
console.groupEnd(),
|
|
257
|
-
]
|
|
268
|
+
// prettier-ignore
|
|
269
|
+
|
|
270
|
+
// if (prev?.isNewTheme && _.state.theme !== parentManager?.state.theme) {
|
|
271
|
+
// console.warn('notify')
|
|
272
|
+
// _.notify()
|
|
273
|
+
// }
|
|
274
|
+
|
|
258
275
|
// only inverse relies on this for ssr
|
|
259
276
|
const mounted = !props.inverse ? true : root || prev?.mounted
|
|
260
277
|
return {
|
|
@@ -266,12 +283,14 @@ export const useChangeThemeEffect = (
|
|
|
266
283
|
}
|
|
267
284
|
}
|
|
268
285
|
|
|
269
|
-
function updateState() {
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
)
|
|
286
|
+
function updateState(updatingManager?: ThemeManager) {
|
|
287
|
+
if (disableUpdate?.()) {
|
|
288
|
+
return
|
|
289
|
+
}
|
|
290
|
+
const manager = updatingManager ?? themeManager
|
|
291
|
+
const next = manager.getState(props, parentManager)
|
|
292
|
+
const shouldChange = manager.getStateShouldChange(next, isNewTheme ? state : null)
|
|
293
|
+
// console.log(`got it`, next, isNewTheme, shouldChange, { ...updatingManager?.state })
|
|
275
294
|
if (shouldChange) {
|
|
276
295
|
setThemeState(createState)
|
|
277
296
|
} else {
|
package/src/styled.tsx
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { stylePropsAll, validStyles } from '@tamagui/helpers'
|
|
2
|
+
|
|
1
3
|
import { createComponent } from './createComponent'
|
|
2
4
|
import { ReactNativeStaticConfigs } from './setupReactNative'
|
|
3
5
|
import {
|
|
@@ -60,6 +62,19 @@ export function styled<
|
|
|
60
62
|
// }
|
|
61
63
|
// }
|
|
62
64
|
|
|
65
|
+
// validate not using a variant over an existing valid style
|
|
66
|
+
if (process.env.NODE_ENV === 'development') {
|
|
67
|
+
if (options?.variants) {
|
|
68
|
+
for (const key in options.variants) {
|
|
69
|
+
if (key in stylePropsAll) {
|
|
70
|
+
console.error(
|
|
71
|
+
`Invalid variant key overlaps with style key: ${key}. Tamagui prevents defining variants that use valid style keys to reduce implementation complexity.`
|
|
72
|
+
)
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
63
78
|
const staticConfigProps = (() => {
|
|
64
79
|
const parentStaticConfig =
|
|
65
80
|
'staticConfig' in Component ? (Component.staticConfig as StaticConfig) : null
|
|
@@ -32,6 +32,12 @@ export function TamaguiProvider({
|
|
|
32
32
|
// inject CSS if asked to (not SSR compliant)
|
|
33
33
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
34
34
|
React.useLayoutEffect(() => {
|
|
35
|
+
// for easier support of hidden-until-js mount animations
|
|
36
|
+
// user must set t_unmounted on documentElement from SSR
|
|
37
|
+
if (document.documentElement.classList.contains('t_unmounted')) {
|
|
38
|
+
document.documentElement.classList.remove('t_unmounted')
|
|
39
|
+
}
|
|
40
|
+
|
|
35
41
|
if (disableInjectCSS) return
|
|
36
42
|
const style = document.createElement('style')
|
|
37
43
|
style.appendChild(document.createTextNode(config.getCSS()))
|
package/src/views/Theme.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isWeb } from '@tamagui/constants'
|
|
2
|
-
import React, { useMemo } from 'react'
|
|
2
|
+
import React, { Children, cloneElement, useMemo } from 'react'
|
|
3
3
|
|
|
4
4
|
import { variableToString } from '../createVariable'
|
|
5
5
|
import { ThemeManager } from '../helpers/ThemeManager'
|
|
@@ -14,23 +14,20 @@ export function Theme(props: ThemeProps) {
|
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
const isRoot = !!props['_isRoot']
|
|
17
|
-
const { name, theme, themeManager,
|
|
18
|
-
props,
|
|
19
|
-
isRoot
|
|
20
|
-
)
|
|
21
|
-
|
|
17
|
+
const { name, theme, themeManager, className } = useChangeThemeEffect(props, isRoot)
|
|
22
18
|
const disableThemeClass = props.disableThemeClass
|
|
23
19
|
const missingTheme = !(name && theme)
|
|
24
20
|
|
|
25
21
|
// memo here, changing theme without re-rendering all children is a critical optimization
|
|
26
22
|
// may require some effort of end user to memoize but without this memo they'd have no option
|
|
27
|
-
let contents =
|
|
28
|
-
|
|
29
|
-
?
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
23
|
+
let contents = useThemeManagerContext(
|
|
24
|
+
props['data-themeable']
|
|
25
|
+
? Children.map(props.children, (child) =>
|
|
26
|
+
cloneElement(child, { ['data-themeable']: true })
|
|
27
|
+
)
|
|
28
|
+
: props.children,
|
|
29
|
+
themeManager
|
|
30
|
+
)
|
|
34
31
|
|
|
35
32
|
if (process.env.NODE_ENV === 'development' && missingTheme) {
|
|
36
33
|
// eslint-disable-next-line no-console
|
|
@@ -60,15 +57,15 @@ export function Theme(props: ThemeProps) {
|
|
|
60
57
|
return contents
|
|
61
58
|
}
|
|
62
59
|
|
|
63
|
-
export function
|
|
60
|
+
export function useThemeManagerContext(
|
|
64
61
|
children: any,
|
|
65
62
|
themeManager?: ThemeManager | null,
|
|
66
63
|
shouldReset?: boolean
|
|
67
64
|
) {
|
|
65
|
+
// disabled super memoize it - listener first strategy
|
|
66
|
+
const value = themeManager // useMemo(() => themeManager, [!!themeManager])
|
|
68
67
|
// be sure to memoize themeManager to avoid reparenting
|
|
69
|
-
if (!
|
|
70
|
-
return children
|
|
71
|
-
}
|
|
68
|
+
if (!value) return children
|
|
72
69
|
// be sure to memoize shouldReset to avoid reparenting
|
|
73
70
|
let next = children
|
|
74
71
|
// TODO likely not necessary if we do reset logic now in useTheme?
|
|
@@ -76,9 +73,5 @@ export function wrapThemeManagerContext(
|
|
|
76
73
|
if (shouldReset && themeManager) {
|
|
77
74
|
next = <Theme name={themeManager.state.parentName}>{next}</Theme>
|
|
78
75
|
}
|
|
79
|
-
return
|
|
80
|
-
<ThemeManagerContext.Provider value={themeManager}>
|
|
81
|
-
{next}
|
|
82
|
-
</ThemeManagerContext.Provider>
|
|
83
|
-
)
|
|
76
|
+
return <ThemeManagerContext.Provider value={value}>{next}</ThemeManagerContext.Provider>
|
|
84
77
|
}
|
|
@@ -17,5 +17,5 @@ export type SpacedChildrenProps = {
|
|
|
17
17
|
direction?: SpaceDirection;
|
|
18
18
|
separator?: React.ReactNode;
|
|
19
19
|
};
|
|
20
|
-
export declare function spacedChildren(
|
|
20
|
+
export declare function spacedChildren(props: SpacedChildrenProps): React.ReactNode;
|
|
21
21
|
//# sourceMappingURL=createComponent.d.ts.map
|
|
@@ -25,7 +25,7 @@ export declare class ThemeManager {
|
|
|
25
25
|
forceTheme?: ThemeParsed;
|
|
26
26
|
}, notify?: boolean): ThemeManagerState | undefined;
|
|
27
27
|
getStateIfChanged(props?: ThemeProps, state?: ThemeManagerState | null, parentManager?: ThemeManager | null): ThemeManagerState | null | undefined;
|
|
28
|
-
getStateShouldChange(nextState: ThemeManagerState | null, state?: ThemeManagerState | null):
|
|
28
|
+
getStateShouldChange(nextState: ThemeManagerState | null, state?: ThemeManagerState | null): boolean;
|
|
29
29
|
getState(props?: ThemeProps, parentManager?: ThemeManager | null): ThemeManagerState | null;
|
|
30
30
|
get allKeys(): Set<string>;
|
|
31
31
|
getValue(key: string, state?: ThemeManagerState): import("..").Variable<any> | undefined;
|
package/types/helpers/cache.d.ts
CHANGED
|
@@ -2,11 +2,9 @@ type Value = Object | Array<any> | string | number;
|
|
|
2
2
|
export type Style = {
|
|
3
3
|
[key: string]: Value;
|
|
4
4
|
};
|
|
5
|
-
declare
|
|
6
|
-
v: Record<string, any>;
|
|
5
|
+
export declare const cache: {
|
|
7
6
|
get(key: string, valStr: string): any;
|
|
8
7
|
set(key: string, valStr: string, object: any): void;
|
|
9
|
-
}
|
|
10
|
-
export declare const cache: Cache;
|
|
8
|
+
};
|
|
11
9
|
export {};
|
|
12
10
|
//# sourceMappingURL=cache.d.ts.map
|
|
@@ -3,7 +3,8 @@ export declare const insertedTransforms: {};
|
|
|
3
3
|
export declare const getAllSelectors: () => Record<string, string>;
|
|
4
4
|
export declare const getAllRules: () => string[];
|
|
5
5
|
export declare const getAllTransforms: () => {};
|
|
6
|
-
export declare function
|
|
6
|
+
export declare function listenForSheetChanges(): void;
|
|
7
|
+
export declare function scanAllSheets(): void;
|
|
7
8
|
export declare function updateRules(identifier: string, rules: string[]): boolean;
|
|
8
9
|
export type PartialStyleObject = Pick<StyleObject, 'identifier' | 'property' | 'rules'>;
|
|
9
10
|
export type RulesToInsert = PartialStyleObject[];
|
|
@@ -2,9 +2,9 @@ import { ThemeName } from '../types';
|
|
|
2
2
|
export interface ThemeableProps {
|
|
3
3
|
theme?: ThemeName | null;
|
|
4
4
|
themeInverse?: boolean;
|
|
5
|
+
themeReset?: boolean;
|
|
5
6
|
componentName?: string;
|
|
6
7
|
debug?: boolean | 'verbose';
|
|
7
|
-
reset?: boolean;
|
|
8
8
|
}
|
|
9
9
|
export declare function themeable<Component extends (props: any) => any>(component: Component, opts?: {
|
|
10
10
|
componentName?: string;
|
|
@@ -2,6 +2,7 @@ import { MediaQueries, MediaQueryKey, MediaQueryObject, MediaQueryState, Tamagui
|
|
|
2
2
|
export declare const mediaState: MediaQueryState;
|
|
3
3
|
export declare const mediaQueryConfig: MediaQueries;
|
|
4
4
|
export declare const getMedia: () => MediaQueryState;
|
|
5
|
+
export declare const mediaKeysWithAndWithout$: Set<string>;
|
|
5
6
|
export declare const getInitialMediaState: () => MediaQueryState;
|
|
6
7
|
export declare const getMediaKeyImportance: (key: string) => number;
|
|
7
8
|
export declare const configureMedia: (config: TamaguiInternalConfig) => void;
|
|
@@ -11,5 +11,5 @@ export declare const useTheme: (props?: ThemeProps) => ThemeParsed;
|
|
|
11
11
|
export declare const getThemeManager: (theme: any) => ThemeManager | undefined;
|
|
12
12
|
export declare const getThemeIsNewTheme: (theme: any) => ThemeManager | undefined;
|
|
13
13
|
export declare const activeThemeManagers: Set<ThemeManager>;
|
|
14
|
-
export declare const useChangeThemeEffect: (props: ThemeProps, root?: boolean) => ChangedThemeResponse;
|
|
14
|
+
export declare const useChangeThemeEffect: (props: ThemeProps, root?: boolean, disableUpdate?: () => boolean) => ChangedThemeResponse;
|
|
15
15
|
//# sourceMappingURL=useTheme.d.ts.map
|
package/types/views/Theme.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ThemeManager } from '../helpers/ThemeManager';
|
|
2
2
|
import { ThemeProps } from '../types';
|
|
3
3
|
export declare function Theme(props: ThemeProps): any;
|
|
4
|
-
export declare function
|
|
4
|
+
export declare function useThemeManagerContext(children: any, themeManager?: ThemeManager | null, shouldReset?: boolean): any;
|
|
5
5
|
//# sourceMappingURL=Theme.d.ts.map
|