@tamagui/core 1.0.1-beta.166 → 1.0.1-beta.168
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.map +1 -1
- package/dist/cjs/config.js.map +1 -1
- package/dist/cjs/constants/platform.js +4 -4
- package/dist/cjs/constants/platform.js.map +2 -2
- package/dist/cjs/constants/platform.native.js +3 -3
- package/dist/cjs/constants/platform.native.js.map +2 -2
- package/dist/cjs/createComponent.js +4 -2
- package/dist/cjs/createComponent.js.map +2 -2
- package/dist/cjs/createTamagui.js +1 -4
- package/dist/cjs/createTamagui.js.map +2 -2
- package/dist/cjs/createVariable.js +9 -0
- package/dist/cjs/createVariable.js.map +2 -2
- package/dist/cjs/helpers/ThemeManager.js.map +1 -1
- package/dist/cjs/helpers/getSplitStyles.js +16 -9
- package/dist/cjs/helpers/getSplitStyles.js.map +2 -2
- package/dist/cjs/helpers/getThemeCSSRules.js.map +1 -1
- package/dist/cjs/helpers/isTamaguiElement.js.map +2 -2
- package/dist/cjs/hooks/useIsSSR.js +8 -4
- package/dist/cjs/hooks/useIsSSR.js.map +2 -2
- package/dist/cjs/hooks/useIsTouchDevice.js +1 -1
- package/dist/cjs/hooks/useIsTouchDevice.js.map +2 -2
- package/dist/cjs/hooks/useMedia.js +48 -29
- package/dist/cjs/hooks/useMedia.js.map +2 -2
- package/dist/cjs/hooks/useTheme.js +1 -1
- package/dist/cjs/hooks/useTheme.js.map +2 -2
- package/dist/cjs/styled.js +11 -8
- package/dist/cjs/styled.js.map +2 -2
- package/dist/cjs/types.js.map +1 -1
- package/dist/cjs/updateTheme.js.map +2 -2
- package/dist/cjs/views/TamaguiProvider.js +2 -2
- package/dist/cjs/views/TamaguiProvider.js.map +2 -2
- package/dist/esm/addTheme.js.map +1 -1
- package/dist/esm/config.js.map +1 -1
- package/dist/esm/constants/platform.js +3 -3
- package/dist/esm/constants/platform.js.map +2 -2
- package/dist/esm/constants/platform.native.js +2 -2
- package/dist/esm/constants/platform.native.js.map +2 -2
- package/dist/esm/createComponent.js +4 -2
- package/dist/esm/createComponent.js.map +2 -2
- package/dist/esm/createTamagui.js +1 -4
- package/dist/esm/createTamagui.js.map +2 -2
- package/dist/esm/createVariable.js +8 -0
- package/dist/esm/createVariable.js.map +2 -2
- package/dist/esm/helpers/ThemeManager.js.map +1 -1
- package/dist/esm/helpers/getSplitStyles.js +16 -9
- package/dist/esm/helpers/getSplitStyles.js.map +2 -2
- package/dist/esm/helpers/getThemeCSSRules.js.map +1 -1
- package/dist/esm/helpers/isTamaguiElement.js.map +2 -2
- package/dist/esm/hooks/useIsSSR.js +9 -5
- package/dist/esm/hooks/useIsSSR.js.map +2 -2
- package/dist/esm/hooks/useIsTouchDevice.js +2 -2
- package/dist/esm/hooks/useIsTouchDevice.js.map +2 -2
- package/dist/esm/hooks/useMedia.js +49 -30
- package/dist/esm/hooks/useMedia.js.map +2 -2
- package/dist/esm/hooks/useTheme.js +2 -2
- package/dist/esm/hooks/useTheme.js.map +2 -2
- package/dist/esm/styled.js +11 -8
- package/dist/esm/styled.js.map +2 -2
- package/dist/esm/updateTheme.js.map +2 -2
- package/dist/esm/views/TamaguiProvider.js +3 -3
- package/dist/esm/views/TamaguiProvider.js.map +2 -2
- package/package.json +10 -10
- package/src/addTheme.ts +3 -3
- package/src/config.ts +1 -1
- package/src/constants/platform.native.ts +1 -1
- package/src/constants/platform.ts +2 -2
- package/src/createComponent.tsx +10 -2
- package/src/createTamagui.ts +7 -10
- package/src/createVariable.ts +8 -1
- package/src/helpers/ThemeManager.tsx +4 -4
- package/src/helpers/getSplitStyles.tsx +25 -12
- package/src/helpers/getThemeCSSRules.ts +2 -2
- package/src/helpers/isTamaguiElement.tsx +3 -5
- package/src/hooks/useIsSSR.tsx +10 -5
- package/src/hooks/useIsTouchDevice.tsx +2 -2
- package/src/hooks/useMedia.tsx +65 -36
- package/src/hooks/useTheme.tsx +6 -6
- package/src/styled.tsx +40 -12
- package/src/types.tsx +45 -12
- package/src/updateTheme.ts +2 -2
- package/src/views/TamaguiProvider.tsx +3 -4
- package/types/addTheme.d.ts +2 -2
- package/types/config.d.ts +18 -2
- package/types/constants/platform.d.ts +1 -1
- package/types/constants/platform.native.d.ts +1 -1
- package/types/createVariable.d.ts +5 -0
- package/types/helpers/ThemeManager.d.ts +5 -5
- package/types/helpers/calc.d.ts +5 -0
- package/types/helpers/expandStyle.d.ts +4 -0
- package/types/helpers/expandStyles.d.ts +7 -0
- package/types/helpers/getSplitStyles.d.ts +3 -3
- package/types/helpers/getStylesAtomic.d.ts +4 -0
- package/types/helpers/getThemeCSSRules.d.ts +2 -2
- package/types/helpers/isTamaguiElement.d.ts +4 -6
- package/types/helpers/mergeProps.d.ts +13 -0
- package/types/helpers/normalizeValueWithProperty.d.ts +4 -0
- package/types/hooks/useIsSSR.d.ts +3 -1
- package/types/hooks/useMedia.d.ts +3 -3
- package/types/hooks/useTheme.d.ts +4 -4
- package/types/insertFont.d.ts +3 -0
- package/types/styled.d.ts +5 -1
- package/types/types.d.ts +112 -12
- package/types/updateTheme.d.ts +2 -2
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import React, { isValidElement } from 'react'
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { TamaguiComponent } from '../types'
|
|
4
4
|
import { isTamaguiComponent } from './isTamaguiComponent'
|
|
5
5
|
|
|
6
|
-
export type TamaguiReactElement = React.ReactElement & {
|
|
7
|
-
type:
|
|
8
|
-
staticConfig: StaticConfig
|
|
9
|
-
}
|
|
6
|
+
export type TamaguiReactElement<P = any> = React.ReactElement<P> & {
|
|
7
|
+
type: TamaguiComponent
|
|
10
8
|
}
|
|
11
9
|
|
|
12
10
|
export const isTamaguiElement = (child: any, name?: string): child is TamaguiReactElement => {
|
package/src/hooks/useIsSSR.tsx
CHANGED
|
@@ -1,18 +1,23 @@
|
|
|
1
1
|
import { useState } from 'react'
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { isServer, isWeb, useIsomorphicLayoutEffect } from '../constants/platform'
|
|
4
4
|
import { startTransition } from '../helpers/startTransition'
|
|
5
5
|
|
|
6
6
|
// because any change before first useEffect causes hydration / mismatch issues
|
|
7
7
|
|
|
8
|
-
export const useIsSSR = () => {
|
|
8
|
+
export const useIsSSR = (props?: { immediate?: boolean }) => {
|
|
9
9
|
const [val, setVal] = useState(true)
|
|
10
10
|
|
|
11
11
|
useIsomorphicLayoutEffect(() => {
|
|
12
|
-
if (isWeb && !
|
|
13
|
-
|
|
12
|
+
if (isWeb && !isServer) {
|
|
13
|
+
// could also have a global tamagui `config.immediateSSRTransition`
|
|
14
|
+
if (props?.immediate) {
|
|
14
15
|
setVal(false)
|
|
15
|
-
}
|
|
16
|
+
} else {
|
|
17
|
+
startTransition(() => {
|
|
18
|
+
setVal(false)
|
|
19
|
+
})
|
|
20
|
+
}
|
|
16
21
|
}
|
|
17
22
|
}, [])
|
|
18
23
|
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { useState } from 'react'
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { isServer, isTouchable, isWeb, useIsomorphicLayoutEffect } from '../constants/platform'
|
|
4
4
|
|
|
5
5
|
// ssr friendly
|
|
6
6
|
|
|
7
7
|
export const useIsTouchDevice = () => {
|
|
8
8
|
const [touchOnly, setTouchOnly] = useState(false)
|
|
9
9
|
|
|
10
|
-
if (isWeb && !
|
|
10
|
+
if (isWeb && !isServer) {
|
|
11
11
|
// only ever false on web SSR (env), so run effect conditionally
|
|
12
12
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
13
13
|
useIsomorphicLayoutEffect(() => {
|
package/src/hooks/useMedia.tsx
CHANGED
|
@@ -1,20 +1,39 @@
|
|
|
1
|
-
import { useMemo, useState } from 'react'
|
|
1
|
+
import { useEffect, useMemo, useState } from 'react'
|
|
2
2
|
|
|
3
3
|
import { useIsomorphicLayoutEffect } from '../constants/platform'
|
|
4
4
|
import { matchMedia } from '../helpers/matchMedia'
|
|
5
5
|
import {
|
|
6
|
-
ConfigureMediaQueryOptions,
|
|
7
6
|
MediaQueries,
|
|
8
7
|
MediaQueryKey,
|
|
9
8
|
MediaQueryObject,
|
|
10
9
|
MediaQueryState,
|
|
10
|
+
TamaguiInternalConfig,
|
|
11
11
|
} from '../types'
|
|
12
12
|
import { useSafeRef } from './useSafeRef'
|
|
13
13
|
|
|
14
|
-
export const mediaState: MediaQueryState =
|
|
14
|
+
export const mediaState: MediaQueryState =
|
|
15
|
+
// development time safeguard
|
|
16
|
+
process.env.NODE_ENV === 'development'
|
|
17
|
+
? new Proxy(
|
|
18
|
+
{},
|
|
19
|
+
{
|
|
20
|
+
get(target, key) {
|
|
21
|
+
if (typeof key === 'string' && key[0] === '$') {
|
|
22
|
+
throw new Error(`Access of mediaState should never include $`)
|
|
23
|
+
}
|
|
24
|
+
return Reflect.get(target, key)
|
|
25
|
+
},
|
|
26
|
+
}
|
|
27
|
+
)
|
|
28
|
+
: ({} as any)
|
|
29
|
+
|
|
15
30
|
const mediaQueryListeners: { [key: string]: Set<Function> } = {}
|
|
16
31
|
|
|
17
32
|
export function addMediaQueryListener(key: MediaQueryKey, cb: any) {
|
|
33
|
+
if (process.env.NODE_ENV === 'development' && key[0] === '$') {
|
|
34
|
+
// eslint-disable-next-line no-console
|
|
35
|
+
console.warn(`Warning, listening to media queries shouldn't use the "$" prefix`)
|
|
36
|
+
}
|
|
18
37
|
mediaQueryListeners[key] = mediaQueryListeners[key] || new Set()
|
|
19
38
|
mediaQueryListeners[key].add(cb)
|
|
20
39
|
return () => removeMediaQueryListener(key, cb)
|
|
@@ -35,29 +54,17 @@ const dispose = new Set<Function>()
|
|
|
35
54
|
// for SSR capture it at time of startup
|
|
36
55
|
let initialMediaState: MediaQueryState | null
|
|
37
56
|
|
|
38
|
-
export const configureMedia = ({
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
// support hot reload
|
|
45
|
-
if (initialMediaState) {
|
|
46
|
-
if (process.env.NODE_ENV === 'development') {
|
|
47
|
-
if (JSON.stringify(queries) === JSON.stringify(mediaQueryConfig)) {
|
|
48
|
-
// hmr avoid update
|
|
49
|
-
return
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
setupMediaListeners()
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
Object.assign(mediaQueryConfig, queries)
|
|
56
|
-
// start in the initial state
|
|
57
|
-
for (const key in queries) {
|
|
58
|
-
mediaState[key] = defaultActive[key] || false
|
|
57
|
+
export const configureMedia = (config: TamaguiInternalConfig) => {
|
|
58
|
+
const { media, mediaQueryDefaultActive } = config
|
|
59
|
+
if (!media) return
|
|
60
|
+
for (const key in media) {
|
|
61
|
+
mediaState[key] = mediaQueryDefaultActive?.[key] || false
|
|
59
62
|
}
|
|
63
|
+
Object.assign(mediaQueryConfig, media)
|
|
60
64
|
initialMediaState = { ...mediaState }
|
|
65
|
+
if (config.disableSSR) {
|
|
66
|
+
setupMediaListeners()
|
|
67
|
+
}
|
|
61
68
|
}
|
|
62
69
|
|
|
63
70
|
function unlisten() {
|
|
@@ -65,7 +72,20 @@ function unlisten() {
|
|
|
65
72
|
dispose.clear()
|
|
66
73
|
}
|
|
67
74
|
|
|
75
|
+
/**
|
|
76
|
+
* Note: This should *not* set the state on the first render!
|
|
77
|
+
* Because to avoid hydration issues SSR must match the server
|
|
78
|
+
* *and then* re-render with the actual media query state.
|
|
79
|
+
*/
|
|
80
|
+
let configuredKey = ''
|
|
68
81
|
function setupMediaListeners() {
|
|
82
|
+
// avoid setting up more than once per config
|
|
83
|
+
const nextKey = JSON.stringify(mediaQueryConfig)
|
|
84
|
+
if (nextKey === configuredKey) {
|
|
85
|
+
return
|
|
86
|
+
}
|
|
87
|
+
configuredKey = nextKey
|
|
88
|
+
|
|
69
89
|
// hmr, undo existing before re-binding
|
|
70
90
|
unlisten()
|
|
71
91
|
|
|
@@ -79,6 +99,7 @@ function setupMediaListeners() {
|
|
|
79
99
|
// react native needs these deprecated apis for now
|
|
80
100
|
match.addListener(update)
|
|
81
101
|
dispose.add(() => match.removeListener(update))
|
|
102
|
+
|
|
82
103
|
update()
|
|
83
104
|
|
|
84
105
|
function update() {
|
|
@@ -87,16 +108,18 @@ function setupMediaListeners() {
|
|
|
87
108
|
mediaState[key] = next
|
|
88
109
|
const listeners = mediaQueryListeners[key]
|
|
89
110
|
if (listeners?.size) {
|
|
90
|
-
|
|
91
|
-
cb()
|
|
92
|
-
}
|
|
111
|
+
listeners.forEach((cb) => cb())
|
|
93
112
|
}
|
|
94
113
|
}
|
|
95
114
|
}
|
|
96
115
|
}
|
|
97
116
|
|
|
98
|
-
export function useMediaQueryListeners() {
|
|
99
|
-
|
|
117
|
+
export function useMediaQueryListeners(config: TamaguiInternalConfig) {
|
|
118
|
+
if (config.disableSSR) {
|
|
119
|
+
return
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
useEffect(() => {
|
|
100
123
|
setupMediaListeners()
|
|
101
124
|
return unlisten
|
|
102
125
|
}, [])
|
|
@@ -105,7 +128,7 @@ export function useMediaQueryListeners() {
|
|
|
105
128
|
export function useMedia(): {
|
|
106
129
|
[key in MediaQueryKey]: boolean
|
|
107
130
|
} {
|
|
108
|
-
const [state, setState] = useState(initialMediaState
|
|
131
|
+
const [state, setState] = useState(initialMediaState || {})
|
|
109
132
|
const keys = useSafeRef({} as Record<string, boolean>)
|
|
110
133
|
|
|
111
134
|
function updateState() {
|
|
@@ -120,13 +143,12 @@ export function useMedia(): {
|
|
|
120
143
|
}
|
|
121
144
|
|
|
122
145
|
useIsomorphicLayoutEffect(() => {
|
|
123
|
-
const
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
}
|
|
146
|
+
const disposes: Function[] = Object.keys(keys.current).map((key) =>
|
|
147
|
+
addMediaQueryListener(key, updateState)
|
|
148
|
+
)
|
|
127
149
|
updateState()
|
|
128
150
|
return () => {
|
|
129
|
-
|
|
151
|
+
disposes.forEach((cb) => cb())
|
|
130
152
|
}
|
|
131
153
|
})
|
|
132
154
|
|
|
@@ -134,8 +156,15 @@ export function useMedia(): {
|
|
|
134
156
|
() =>
|
|
135
157
|
new Proxy(state, {
|
|
136
158
|
get(_, key: string) {
|
|
159
|
+
if (process.env.NODE_ENV === 'development') {
|
|
160
|
+
if (!initialMediaState) {
|
|
161
|
+
throw new Error(
|
|
162
|
+
`To use useMedia() you must pass in media configuration to createTamagui, none was found.`
|
|
163
|
+
)
|
|
164
|
+
}
|
|
165
|
+
}
|
|
137
166
|
if (!keys.current[key]) {
|
|
138
|
-
keys.current
|
|
167
|
+
keys.current[key] = true
|
|
139
168
|
}
|
|
140
169
|
return Reflect.get(state, key)
|
|
141
170
|
},
|
package/src/hooks/useTheme.tsx
CHANGED
|
@@ -3,7 +3,7 @@ import React, { useContext, useLayoutEffect, useMemo, useRef, useState } from 'r
|
|
|
3
3
|
|
|
4
4
|
import { getConfig } from '../config'
|
|
5
5
|
import { isDevTools } from '../constants/isDevTools'
|
|
6
|
-
import { isRSC,
|
|
6
|
+
import { isRSC, isServer, useIsomorphicLayoutEffect } from '../constants/platform'
|
|
7
7
|
import { ThemeContext } from '../contexts/ThemeContext'
|
|
8
8
|
import { areEqualSets } from '../helpers/areEqualSets'
|
|
9
9
|
import {
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
ThemeManagerContext,
|
|
13
13
|
emptyManager,
|
|
14
14
|
} from '../helpers/ThemeManager'
|
|
15
|
-
import { ThemeName,
|
|
15
|
+
import { ThemeName, ThemeParsed } from '../types'
|
|
16
16
|
import { GetThemeUnwrapped } from './getThemeUnwrapped'
|
|
17
17
|
import { useConstant } from './useConstant'
|
|
18
18
|
import { useServerRef } from './useServerHooks'
|
|
@@ -38,7 +38,7 @@ export const useTheme = (
|
|
|
38
38
|
componentName?: string,
|
|
39
39
|
props?: ThemeProps,
|
|
40
40
|
forceUpdate?: any
|
|
41
|
-
):
|
|
41
|
+
): ThemeParsed => {
|
|
42
42
|
// TODO this can use useChangeThemeEffect almost ready
|
|
43
43
|
if (isRSC) {
|
|
44
44
|
const config = getConfig()
|
|
@@ -195,10 +195,10 @@ export const useChangeThemeEffect = (
|
|
|
195
195
|
forceUpdateProp?: any,
|
|
196
196
|
uuid?: Object
|
|
197
197
|
): {
|
|
198
|
-
themes: Record<string,
|
|
198
|
+
themes: Record<string, ThemeParsed>
|
|
199
199
|
themeManager: ThemeManager | null
|
|
200
200
|
name: string
|
|
201
|
-
theme:
|
|
201
|
+
theme: ThemeParsed | null
|
|
202
202
|
className?: string
|
|
203
203
|
} => {
|
|
204
204
|
const { themes } = getConfig()
|
|
@@ -236,7 +236,7 @@ export const useChangeThemeEffect = (
|
|
|
236
236
|
return new ThemeManager(next.name, next.className, next.theme, parentManager, reset)
|
|
237
237
|
})
|
|
238
238
|
|
|
239
|
-
if (!
|
|
239
|
+
if (!isServer) {
|
|
240
240
|
useLayoutEffect(() => {
|
|
241
241
|
themeManager.update(next)
|
|
242
242
|
|
package/src/styled.tsx
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Image, Text, TextInput } from 'react-native'
|
|
2
2
|
|
|
3
3
|
import { createComponent } from './createComponent'
|
|
4
|
+
import { TamaguiReactElement, isTamaguiElement } from './helpers/isTamaguiElement'
|
|
4
5
|
import { RNComponents } from './helpers/RNComponents'
|
|
5
6
|
import {
|
|
6
7
|
GetProps,
|
|
@@ -22,6 +23,20 @@ export type StyledOptions<ParentComponent extends StylableComponent> = GetProps<
|
|
|
22
23
|
defaultVariants?: { [key: string]: any }
|
|
23
24
|
}
|
|
24
25
|
|
|
26
|
+
// can't infer from styled(<YStack />) which would be nice
|
|
27
|
+
// * excessively deep type instantiation
|
|
28
|
+
|
|
29
|
+
type GetBaseProps<A extends StylableComponent> =
|
|
30
|
+
// A extends TamaguiReactElement
|
|
31
|
+
// ? GetBaseProps<A['type']> :
|
|
32
|
+
A extends TamaguiComponent<any, any, infer P> ? P : GetProps<A>
|
|
33
|
+
|
|
34
|
+
type GetVariantProps<A extends StylableComponent> =
|
|
35
|
+
// A extends TamaguiReactElement
|
|
36
|
+
// ? GetVariantProps<A['type']>
|
|
37
|
+
// :
|
|
38
|
+
A extends TamaguiComponent<any, any, any, infer V> ? V : {}
|
|
39
|
+
|
|
25
40
|
export function styled<
|
|
26
41
|
ParentComponent extends StylableComponent,
|
|
27
42
|
Variants extends VariantDefinitions<ParentComponent> | void = VariantDefinitions<ParentComponent> | void
|
|
@@ -33,9 +48,18 @@ export function styled<
|
|
|
33
48
|
variants?: Variants | undefined
|
|
34
49
|
// thought i had this typed, but can't get it linked
|
|
35
50
|
defaultVariants?: { [key: string]: any }
|
|
51
|
+
acceptsClassName?: boolean
|
|
36
52
|
},
|
|
37
53
|
staticExtractionOptions?: Partial<StaticConfig>
|
|
38
54
|
) {
|
|
55
|
+
// * excessively deep type instantiation
|
|
56
|
+
// if (isTamaguiElement(Component)) {
|
|
57
|
+
// const props = Component.props
|
|
58
|
+
// // @ts-ignore
|
|
59
|
+
// Component = Component.type
|
|
60
|
+
// options = options ? { ...props, ...options } : props
|
|
61
|
+
// }
|
|
62
|
+
|
|
39
63
|
const staticConfigProps = (() => {
|
|
40
64
|
const parentStaticConfig =
|
|
41
65
|
'staticConfig' in Component ? (Component.staticConfig as StaticConfig) : null
|
|
@@ -50,7 +74,13 @@ export function styled<
|
|
|
50
74
|
}
|
|
51
75
|
|
|
52
76
|
if (options) {
|
|
53
|
-
const {
|
|
77
|
+
const {
|
|
78
|
+
variants,
|
|
79
|
+
name,
|
|
80
|
+
defaultVariants,
|
|
81
|
+
acceptsClassName: acceptsClassNameProp,
|
|
82
|
+
...defaultProps
|
|
83
|
+
} = options
|
|
54
84
|
if (defaultVariants) {
|
|
55
85
|
Object.assign(defaultProps, defaultVariants)
|
|
56
86
|
}
|
|
@@ -61,12 +91,7 @@ export function styled<
|
|
|
61
91
|
RNComponents.add(Component)
|
|
62
92
|
isReactNativeWeb = true
|
|
63
93
|
} else {
|
|
64
|
-
|
|
65
|
-
// eslint-disable-next-line no-console
|
|
66
|
-
console.warn(
|
|
67
|
-
`Invalid styled() component: Tamagui only accepts react-native Text, View, Image, TextInput, or another styled Tamagui view`
|
|
68
|
-
)
|
|
69
|
-
}
|
|
94
|
+
// assuming some sort of non-tamagui non-rn view, will always use style={}
|
|
70
95
|
}
|
|
71
96
|
}
|
|
72
97
|
const reactNativeWebComponent = isReactNativeWeb
|
|
@@ -84,6 +109,8 @@ export function styled<
|
|
|
84
109
|
isInput || staticExtractionOptions?.isText || parentStaticConfig?.isText || Comp === Text
|
|
85
110
|
)
|
|
86
111
|
|
|
112
|
+
const acceptsClassName = acceptsClassNameProp ?? (isTamagui || isReactNativeWeb)
|
|
113
|
+
|
|
87
114
|
const conf: Partial<StaticConfig> = {
|
|
88
115
|
...staticExtractionOptions,
|
|
89
116
|
...(!isTamagui && {
|
|
@@ -102,10 +129,12 @@ export function styled<
|
|
|
102
129
|
isInput,
|
|
103
130
|
isText,
|
|
104
131
|
isImage,
|
|
132
|
+
acceptsClassName,
|
|
105
133
|
}
|
|
106
134
|
|
|
107
135
|
// TODO compiler doesn't have logic to include children, de-opt (see EnsureFlexed for test usage)
|
|
108
|
-
|
|
136
|
+
// bail on non className views as well
|
|
137
|
+
if (defaultProps.children || !acceptsClassName) {
|
|
109
138
|
conf.neverFlatten = true
|
|
110
139
|
}
|
|
111
140
|
|
|
@@ -117,10 +146,9 @@ export function styled<
|
|
|
117
146
|
const component = createComponent(staticConfigProps, Component)
|
|
118
147
|
|
|
119
148
|
// get parent props without pseudos and medias so we can rebuild both with new variants
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
type ParentVariants = ParentComponent extends TamaguiComponent<any, any, any, infer V> ? V : {}
|
|
149
|
+
// get parent props without pseudos and medias so we can rebuild both with new variants
|
|
150
|
+
type ParentPropsBase = GetBaseProps<ParentComponent>
|
|
151
|
+
type ParentVariants = GetVariantProps<ParentComponent>
|
|
124
152
|
|
|
125
153
|
type OurVariants = Variants extends void
|
|
126
154
|
? {}
|
package/src/types.tsx
CHANGED
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
|
|
18
18
|
import { Variable } from './createVariable'
|
|
19
19
|
import { ResolveVariableTypes } from './helpers/createPropMapper'
|
|
20
|
+
import { TamaguiReactElement } from './static'
|
|
20
21
|
import { RNWTextProps, RNWViewProps } from './types-rnw'
|
|
21
22
|
import { FontLanguageProps } from './views/FontLanguage.types'
|
|
22
23
|
import { ThemeProviderProps } from './views/ThemeProvider'
|
|
@@ -161,7 +162,12 @@ export type CreateTamaguiConfig<
|
|
|
161
162
|
fonts: RemoveLanguagePostfixes<F>
|
|
162
163
|
fontLanguages: GetLanguagePostfixes<F> extends never ? string[] : GetLanguagePostfixes<F>[]
|
|
163
164
|
tokens: A
|
|
164
|
-
|
|
165
|
+
// parsed
|
|
166
|
+
themes: {
|
|
167
|
+
[Name in keyof B]: {
|
|
168
|
+
[Key in keyof B[Name]]: Variable
|
|
169
|
+
}
|
|
170
|
+
}
|
|
165
171
|
shorthands: C
|
|
166
172
|
media: D
|
|
167
173
|
animations: AnimationDriver<E>
|
|
@@ -229,13 +235,16 @@ export type GenericTamaguiConfig = CreateTamaguiConfig<
|
|
|
229
235
|
>
|
|
230
236
|
|
|
231
237
|
// since TamaguiConfig will be re-declared, these will all be typed globally
|
|
232
|
-
export type
|
|
238
|
+
export type ThemeDefinition = TamaguiConfig['themes'][keyof TamaguiConfig['themes']]
|
|
239
|
+
export type ThemeKeys = keyof ThemeDefinition
|
|
240
|
+
export type ThemeParsed = {
|
|
241
|
+
[key in ThemeKeys]: Variable
|
|
242
|
+
}
|
|
233
243
|
export type Tokens = TamaguiConfig['tokens']
|
|
234
244
|
export type Shorthands = TamaguiConfig['shorthands']
|
|
235
245
|
export type Media = TamaguiConfig['media']
|
|
236
246
|
export type Themes = TamaguiConfig['themes']
|
|
237
247
|
export type ThemeName = GetAltThemeNames<keyof Themes>
|
|
238
|
-
export type ThemeKeys = keyof ThemeObject
|
|
239
248
|
export type ThemeTokens = `$${ThemeKeys}`
|
|
240
249
|
export type AnimationKeys = Omit<GetAnimationKeys<TamaguiConfig>, number>
|
|
241
250
|
export type FontLanguages = ArrayIntersection<TamaguiConfig['fontLanguages']>
|
|
@@ -263,6 +272,26 @@ export type CreateTamaguiProps = {
|
|
|
263
272
|
}
|
|
264
273
|
|
|
265
274
|
defaultTheme?: string
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* *Advanced use case* For all CSS extracted views, this has no effect.
|
|
278
|
+
*
|
|
279
|
+
* For SSR compatibility on the web, Tamagui will render once with the settings
|
|
280
|
+
* from `mediaQueryDefaultActive` set for all media queries. Then, it will render
|
|
281
|
+
* again after the initial render using the proper media query values. This is so that
|
|
282
|
+
* hydration will match perfectly with the server.
|
|
283
|
+
*
|
|
284
|
+
* Setting disableSSR will avoid this second render by setting the media query state
|
|
285
|
+
* to the actual browser dimensions on initial load. This is only useful for client-only
|
|
286
|
+
* apps.
|
|
287
|
+
*
|
|
288
|
+
*/
|
|
289
|
+
disableSSR?: boolean
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Disable inserting a theme class in the DOM or context, allowing you to manually place it higher.
|
|
293
|
+
* For custom use cases like integration with next-theme.
|
|
294
|
+
*/
|
|
266
295
|
disableRootThemeClass?: boolean
|
|
267
296
|
|
|
268
297
|
defaultProps?: Record<string, any> & {
|
|
@@ -313,9 +342,6 @@ export type TamaguiInternalConfig<
|
|
|
313
342
|
getCSS: () => string
|
|
314
343
|
parsed: boolean
|
|
315
344
|
inverseShorthands: Record<string, string>
|
|
316
|
-
|
|
317
|
-
// just passed in from CreateTamaguiProps
|
|
318
|
-
themeClassNameOnRoot?: boolean
|
|
319
345
|
}
|
|
320
346
|
|
|
321
347
|
export type GetAnimationKeys<A extends GenericTamaguiConfig> = keyof A['animations']['animations']
|
|
@@ -351,10 +377,6 @@ export type MediaProps<A> = {
|
|
|
351
377
|
export type MediaQueries = {
|
|
352
378
|
[key in MediaQueryKey]: MediaQueryObject
|
|
353
379
|
}
|
|
354
|
-
export type ConfigureMediaQueryOptions = {
|
|
355
|
-
queries?: MediaQueries
|
|
356
|
-
defaultActive?: Record<MediaQueryKey, boolean>
|
|
357
|
-
}
|
|
358
380
|
|
|
359
381
|
export type TransformStyleProps = {
|
|
360
382
|
x?: number
|
|
@@ -422,7 +444,7 @@ export type SizeTokens = GetTokenString<keyof Tokens['size']> | number
|
|
|
422
444
|
export type SpaceTokens = GetTokenString<keyof Tokens['space']> | number | boolean
|
|
423
445
|
export type ColorTokens =
|
|
424
446
|
| GetTokenString<keyof Tokens['color']>
|
|
425
|
-
| GetTokenString<keyof
|
|
447
|
+
| GetTokenString<keyof ThemeParsed>
|
|
426
448
|
| CSSColorNames
|
|
427
449
|
export type ZIndexTokens = GetTokenString<keyof Tokens['zIndex']> | number
|
|
428
450
|
export type RadiusTokens = GetTokenString<keyof Tokens['radius']> | number
|
|
@@ -639,7 +661,7 @@ export type TamaguiProviderProps = Partial<Omit<ThemeProviderProps, 'children'>>
|
|
|
639
661
|
export type PropMapper = (
|
|
640
662
|
key: string,
|
|
641
663
|
value: any,
|
|
642
|
-
theme:
|
|
664
|
+
theme: ThemeParsed,
|
|
643
665
|
props: Record<string, any>,
|
|
644
666
|
state: Partial<SplitStyleState>,
|
|
645
667
|
languageContext?: FontLanguageProps,
|
|
@@ -772,6 +794,13 @@ export type StaticConfig = {
|
|
|
772
794
|
* Used insternally to attach default props to names
|
|
773
795
|
*/
|
|
774
796
|
parentNames?: string[]
|
|
797
|
+
|
|
798
|
+
/**
|
|
799
|
+
* By default if styled() doesn't recognize a parent Tamagui compoent or specific react-native views,
|
|
800
|
+
* it will assume the passed in component only accepts style={} for react-native compatibility.
|
|
801
|
+
* Setting `acceptsClassName: true` indicates Tamagui can pass in className props.
|
|
802
|
+
*/
|
|
803
|
+
acceptsClassName?: boolean
|
|
775
804
|
}
|
|
776
805
|
|
|
777
806
|
/**
|
|
@@ -782,6 +811,8 @@ export type StaticConfig = {
|
|
|
782
811
|
|
|
783
812
|
export type StylableComponent =
|
|
784
813
|
| TamaguiComponent
|
|
814
|
+
// * excessively deep type instantiation
|
|
815
|
+
// | TamaguiReactElement
|
|
785
816
|
| React.Component
|
|
786
817
|
| React.ForwardRefExoticComponent<any>
|
|
787
818
|
| ReactComponentWithRef<any, any>
|
|
@@ -809,6 +840,8 @@ export type GetBaseProps<A extends StylableComponent> = A extends TamaguiCompone
|
|
|
809
840
|
: never
|
|
810
841
|
|
|
811
842
|
export type GetProps<A extends StylableComponent> = A extends TamaguiComponent<infer Props>
|
|
843
|
+
? Props
|
|
844
|
+
: A extends TamaguiReactElement<infer Props>
|
|
812
845
|
? Props
|
|
813
846
|
: A extends React.Component<infer Props>
|
|
814
847
|
? GetGenericComponentTamaguiProps<Props>
|
package/src/updateTheme.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { addTheme } from './addTheme'
|
|
2
2
|
import { activeThemeManagers } from './hooks/useTheme'
|
|
3
|
-
import {
|
|
3
|
+
import { ThemeDefinition } from './types'
|
|
4
4
|
|
|
5
|
-
export function updateTheme({ name, theme }: { name: string; theme:
|
|
5
|
+
export function updateTheme({ name, theme }: { name: string; theme: ThemeDefinition }) {
|
|
6
6
|
const next = addTheme({ name, theme, insertCSS: true, update: true })
|
|
7
7
|
|
|
8
8
|
if (process.env.TAMAGUI_TARGET === 'native') {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { useForceUpdate } from '@tamagui/use-force-update'
|
|
2
1
|
import * as React from 'react'
|
|
3
2
|
|
|
4
|
-
import { isClient, isRSC,
|
|
3
|
+
import { isClient, isRSC, isServer } from '../constants/platform'
|
|
5
4
|
import { ButtonInsideButtonContext } from '../contexts/ButtonInsideButtonContext'
|
|
6
5
|
import { TextAncestorProvider } from '../contexts/TextAncestorContext'
|
|
7
6
|
import { useMediaQueryListeners } from '../hooks/useMedia'
|
|
@@ -22,8 +21,8 @@ export function TamaguiProvider({
|
|
|
22
21
|
)
|
|
23
22
|
}
|
|
24
23
|
|
|
25
|
-
if (!
|
|
26
|
-
useMediaQueryListeners()
|
|
24
|
+
if (!isServer) {
|
|
25
|
+
useMediaQueryListeners(config)
|
|
27
26
|
}
|
|
28
27
|
|
|
29
28
|
if (isClient) {
|
package/types/addTheme.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ThemeDefinition } from './types';
|
|
2
2
|
export declare function addTheme({ name: themeName, theme: themeIn, insertCSS, update, }: {
|
|
3
3
|
name: string;
|
|
4
|
-
theme:
|
|
4
|
+
theme: ThemeDefinition;
|
|
5
5
|
insertCSS?: boolean;
|
|
6
6
|
update?: boolean;
|
|
7
7
|
}): {
|
package/types/config.d.ts
CHANGED
|
@@ -17,8 +17,24 @@ export declare const getConfig: () => TamaguiInternalConfig<import("./types").Cr
|
|
|
17
17
|
}, import("./types").GenericFonts>;
|
|
18
18
|
export declare const getTokens: () => import("./types").CreateTokens<import("./createVariable").Variable<import("./createVariable").VariableValue>>;
|
|
19
19
|
export declare const getThemes: () => {
|
|
20
|
-
[
|
|
21
|
-
[
|
|
20
|
+
[x: string]: {
|
|
21
|
+
[x: string]: import("./createVariable").Variable<import("./createVariable").VariableValue>;
|
|
22
|
+
background?: import("./createVariable").Variable<import("./createVariable").VariableValue> | undefined;
|
|
23
|
+
backgroundHover?: import("./createVariable").Variable<import("./createVariable").VariableValue> | undefined;
|
|
24
|
+
backgroundPress?: import("./createVariable").Variable<import("./createVariable").VariableValue> | undefined;
|
|
25
|
+
backgroundFocus?: import("./createVariable").Variable<import("./createVariable").VariableValue> | undefined;
|
|
26
|
+
color?: import("./createVariable").Variable<import("./createVariable").VariableValue> | undefined;
|
|
27
|
+
colorHover?: import("./createVariable").Variable<import("./createVariable").VariableValue> | undefined;
|
|
28
|
+
colorPress?: import("./createVariable").Variable<import("./createVariable").VariableValue> | undefined;
|
|
29
|
+
colorFocus?: import("./createVariable").Variable<import("./createVariable").VariableValue> | undefined;
|
|
30
|
+
borderColor?: import("./createVariable").Variable<import("./createVariable").VariableValue> | undefined;
|
|
31
|
+
borderColorHover?: import("./createVariable").Variable<import("./createVariable").VariableValue> | undefined;
|
|
32
|
+
borderColorPress?: import("./createVariable").Variable<import("./createVariable").VariableValue> | undefined;
|
|
33
|
+
borderColorFocus?: import("./createVariable").Variable<import("./createVariable").VariableValue> | undefined;
|
|
34
|
+
shadowColor?: import("./createVariable").Variable<import("./createVariable").VariableValue> | undefined;
|
|
35
|
+
shadowColorHover?: import("./createVariable").Variable<import("./createVariable").VariableValue> | undefined;
|
|
36
|
+
shadowColorPress?: import("./createVariable").Variable<import("./createVariable").VariableValue> | undefined;
|
|
37
|
+
shadowColorFocus?: import("./createVariable").Variable<import("./createVariable").VariableValue> | undefined;
|
|
22
38
|
};
|
|
23
39
|
};
|
|
24
40
|
export declare const configListeners: Set<ConfigListener>;
|
|
@@ -3,7 +3,7 @@ export declare const isAndroid: boolean;
|
|
|
3
3
|
export declare const isIOS: boolean;
|
|
4
4
|
export declare const isWeb: boolean;
|
|
5
5
|
export declare const isWindowDefined: boolean;
|
|
6
|
-
export declare const
|
|
6
|
+
export declare const isServer: boolean;
|
|
7
7
|
export declare const isClient: boolean;
|
|
8
8
|
export declare const isRSC: any;
|
|
9
9
|
export declare const useIsomorphicLayoutEffect: typeof useEffect;
|
|
@@ -3,7 +3,7 @@ export declare const isAndroid: boolean;
|
|
|
3
3
|
export declare const isIOS: boolean;
|
|
4
4
|
export declare const isWeb = false;
|
|
5
5
|
export declare const isWindowDefined = false;
|
|
6
|
-
export declare const
|
|
6
|
+
export declare const isServer = false;
|
|
7
7
|
export declare const isClient = false;
|
|
8
8
|
export declare const isRSC = false;
|
|
9
9
|
export declare const useIsomorphicLayoutEffect: typeof useLayoutEffect;
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Should rename this to Token
|
|
3
|
+
* Moving to objects for React Server Components support
|
|
4
|
+
*/
|
|
1
5
|
declare const IS_VAR = "__isVar__";
|
|
2
6
|
export declare type VariableValue = string | number;
|
|
3
7
|
declare type VariableIn<A extends VariableValue = VariableValue> = {
|
|
@@ -20,6 +24,7 @@ export declare const createVariable: <A extends string | number = any>(props: Va
|
|
|
20
24
|
};
|
|
21
25
|
export declare function variableToString(vrble?: any, getValue?: boolean): string;
|
|
22
26
|
export declare function isVariable(v: Variable | any): v is Variable;
|
|
27
|
+
export declare function getVariable(nameOrVariable: Variable | string): string;
|
|
23
28
|
export declare function getVariableValue(v: Variable | any): any;
|
|
24
29
|
export declare function getVariableName(v: Variable | any): any;
|
|
25
30
|
export declare function getVariableVariable(v: Variable | any): any;
|