@tamagui/web 1.72.2 → 1.73.0
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/contexts/ComponentContext.js +1 -0
- package/dist/cjs/contexts/ComponentContext.js.map +1 -1
- package/dist/cjs/contexts/ComponentContext.native.js +1 -0
- package/dist/cjs/contexts/ComponentContext.native.js.map +1 -1
- package/dist/cjs/createComponent.js +21 -25
- package/dist/cjs/createComponent.js.map +1 -1
- package/dist/cjs/createComponent.native.js +20 -24
- package/dist/cjs/createComponent.native.js.map +1 -1
- package/dist/cjs/createTamagui.js +35 -32
- package/dist/cjs/createTamagui.js.map +1 -1
- package/dist/cjs/createTamagui.native.js +35 -32
- package/dist/cjs/createTamagui.native.js.map +1 -1
- package/dist/cjs/helpers/getThemeCSSRules.js +1 -1
- package/dist/cjs/helpers/getThemeCSSRules.js.map +1 -1
- package/dist/cjs/helpers/propMapper.js +15 -10
- package/dist/cjs/helpers/propMapper.js.map +1 -1
- package/dist/cjs/helpers/propMapper.native.js +15 -10
- package/dist/cjs/helpers/propMapper.native.js.map +1 -1
- package/dist/cjs/hooks/useConfiguration.js +33 -0
- package/dist/cjs/hooks/useConfiguration.js.map +6 -0
- package/dist/cjs/hooks/useConfiguration.native.js +34 -0
- package/dist/cjs/hooks/useConfiguration.native.js.map +6 -0
- package/dist/cjs/hooks/useDisableSSR.js +34 -0
- package/dist/cjs/hooks/useDisableSSR.js.map +6 -0
- package/dist/cjs/hooks/useDisableSSR.native.js +35 -0
- package/dist/cjs/hooks/useDisableSSR.native.js.map +6 -0
- package/dist/cjs/hooks/useMedia.js +7 -9
- package/dist/cjs/hooks/useMedia.js.map +1 -1
- package/dist/cjs/hooks/useMedia.native.js +7 -9
- package/dist/cjs/hooks/useMedia.native.js.map +1 -1
- package/dist/cjs/hooks/useProps.js +2 -2
- package/dist/cjs/hooks/useProps.js.map +1 -1
- package/dist/cjs/hooks/useProps.native.js +2 -2
- package/dist/cjs/hooks/useProps.native.js.map +1 -1
- package/dist/cjs/hooks/useTheme.js +26 -27
- package/dist/cjs/hooks/useTheme.js.map +2 -2
- package/dist/cjs/hooks/useTheme.native.js +26 -27
- package/dist/cjs/hooks/useTheme.native.js.map +2 -2
- package/dist/cjs/index.js +6 -6
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/index.native.js +6 -6
- package/dist/cjs/index.native.js.map +1 -1
- package/dist/cjs/views/Configuration.js +26 -0
- package/dist/cjs/views/Configuration.js.map +6 -0
- package/dist/cjs/views/Configuration.native.js +27 -0
- package/dist/cjs/views/Configuration.native.js.map +6 -0
- package/dist/cjs/views/Theme.js +16 -11
- package/dist/cjs/views/Theme.js.map +1 -1
- package/dist/cjs/views/Theme.native.js +16 -11
- package/dist/cjs/views/Theme.native.js.map +1 -1
- package/dist/cjs/views/ThemeDebug.js +8 -8
- package/dist/cjs/views/ThemeDebug.js.map +1 -1
- package/dist/esm/contexts/ComponentContext.js +1 -0
- package/dist/esm/contexts/ComponentContext.js.map +1 -1
- package/dist/esm/createComponent.js +14 -18
- package/dist/esm/createComponent.js.map +1 -1
- package/dist/esm/createTamagui.js +35 -32
- package/dist/esm/createTamagui.js.map +1 -1
- package/dist/esm/helpers/getThemeCSSRules.js +1 -1
- package/dist/esm/helpers/getThemeCSSRules.js.map +1 -1
- package/dist/esm/helpers/propMapper.js +15 -10
- package/dist/esm/helpers/propMapper.js.map +1 -1
- package/dist/esm/hooks/useConfiguration.js +15 -0
- package/dist/esm/hooks/useConfiguration.js.map +6 -0
- package/dist/esm/hooks/useDisableSSR.js +15 -0
- package/dist/esm/hooks/useDisableSSR.js.map +6 -0
- package/dist/esm/hooks/useMedia.js +7 -7
- package/dist/esm/hooks/useMedia.js.map +1 -1
- package/dist/esm/hooks/useProps.js +1 -1
- package/dist/esm/hooks/useProps.js.map +1 -1
- package/dist/esm/hooks/useTheme.js +23 -25
- package/dist/esm/hooks/useTheme.js.map +2 -2
- package/dist/esm/index.js +3 -3
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/views/Configuration.js +7 -0
- package/dist/esm/views/Configuration.js.map +6 -0
- package/dist/esm/views/Theme.js +15 -11
- package/dist/esm/views/Theme.js.map +1 -1
- package/dist/esm/views/ThemeDebug.js +2 -2
- package/dist/esm/views/ThemeDebug.js.map +1 -1
- package/package.json +9 -9
- package/src/contexts/ComponentContext.tsx +1 -0
- package/src/createComponent.tsx +16 -17
- package/src/createTamagui.ts +54 -51
- package/src/helpers/getThemeCSSRules.ts +2 -1
- package/src/helpers/propMapper.ts +16 -18
- package/src/hooks/useConfiguration.tsx +14 -0
- package/src/hooks/useDisableSSR.tsx +14 -0
- package/src/hooks/useMedia.tsx +12 -8
- package/src/hooks/useProps.tsx +1 -1
- package/src/hooks/useTheme.tsx +26 -25
- package/src/index.ts +3 -3
- package/src/types.tsx +7 -6
- package/src/views/Configuration.tsx +11 -0
- package/src/views/Theme.tsx +8 -9
- package/src/views/ThemeDebug.tsx +3 -3
- package/types/contexts/ComponentContext.d.ts.map +1 -1
- package/types/createComponent.d.ts.map +1 -1
- package/types/createTamagui.d.ts.map +1 -1
- package/types/helpers/getThemeCSSRules.d.ts.map +1 -1
- package/types/helpers/propMapper.d.ts.map +1 -1
- package/types/hooks/useConfiguration.d.ts +151 -0
- package/types/hooks/useConfiguration.d.ts.map +1 -0
- package/types/hooks/useDisableSSR.d.ts +4 -0
- package/types/hooks/useDisableSSR.d.ts.map +1 -0
- package/types/hooks/useMedia.d.ts +2 -3
- package/types/hooks/useMedia.d.ts.map +1 -1
- package/types/hooks/useTheme.d.ts +3 -3
- package/types/hooks/useTheme.d.ts.map +1 -1
- package/types/index.d.ts +3 -3
- package/types/index.d.ts.map +1 -1
- package/types/types.d.ts +7 -6
- package/types/types.d.ts.map +1 -1
- package/types/views/Configuration.d.ts +9 -0
- package/types/views/Configuration.d.ts.map +1 -0
- package/types/views/Theme.d.ts.map +1 -1
- package/src/helpers/getAnimationDriver.tsx +0 -8
- package/src/hooks/useAnimationDriver.tsx +0 -8
- package/src/views/AnimationDriverProvider.tsx +0 -16
- package/types/helpers/getAnimationDriver.d.ts +0 -9
- package/types/hooks/useAnimationDriver.d.ts +0 -4
- package/types/hooks/useStyle.d.ts +0 -8
package/src/createComponent.tsx
CHANGED
|
@@ -43,6 +43,7 @@ import {
|
|
|
43
43
|
DisposeFn,
|
|
44
44
|
GroupState,
|
|
45
45
|
LayoutEvent,
|
|
46
|
+
SizeTokens,
|
|
46
47
|
SpaceDirection,
|
|
47
48
|
SpaceValue,
|
|
48
49
|
SpacerProps,
|
|
@@ -570,11 +571,7 @@ export function createComponent<
|
|
|
570
571
|
|
|
571
572
|
if (process.env.NODE_ENV === 'development' && time) time`theme`
|
|
572
573
|
|
|
573
|
-
const mediaState = useMedia(
|
|
574
|
-
// @ts-ignore, we just pass a stable object so we can get it later with
|
|
575
|
-
// should match to the one used in `setMediaShouldUpdate` below
|
|
576
|
-
stateRef
|
|
577
|
-
)
|
|
574
|
+
const mediaState = useMedia(stateRef, componentContext)
|
|
578
575
|
|
|
579
576
|
if (process.env.NODE_ENV === 'development' && time) time`media`
|
|
580
577
|
|
|
@@ -603,7 +600,7 @@ export function createComponent<
|
|
|
603
600
|
props,
|
|
604
601
|
staticConfig,
|
|
605
602
|
theme,
|
|
606
|
-
themeState
|
|
603
|
+
themeState?.state?.name || '',
|
|
607
604
|
state,
|
|
608
605
|
styleProps,
|
|
609
606
|
null,
|
|
@@ -697,7 +694,7 @@ export function createComponent<
|
|
|
697
694
|
presence,
|
|
698
695
|
componentState: state,
|
|
699
696
|
styleProps,
|
|
700
|
-
theme: themeState.state
|
|
697
|
+
theme: themeState.state?.theme!,
|
|
701
698
|
pseudos: pseudos || null,
|
|
702
699
|
hostRef,
|
|
703
700
|
staticConfig,
|
|
@@ -1349,6 +1346,17 @@ export function Unspaced(props: { children?: any }) {
|
|
|
1349
1346
|
}
|
|
1350
1347
|
Unspaced['isUnspaced'] = true
|
|
1351
1348
|
|
|
1349
|
+
const getSpacerSize = (size: SizeTokens | number | boolean, { tokens }) => {
|
|
1350
|
+
size = size === true ? '$true' : size
|
|
1351
|
+
const sizePx = tokens.space[size as any] ?? size
|
|
1352
|
+
return {
|
|
1353
|
+
width: sizePx,
|
|
1354
|
+
height: sizePx,
|
|
1355
|
+
minWidth: sizePx,
|
|
1356
|
+
minHeight: sizePx,
|
|
1357
|
+
}
|
|
1358
|
+
}
|
|
1359
|
+
|
|
1352
1360
|
// dont used styled() here to avoid circular deps
|
|
1353
1361
|
// keep inline to avoid circular deps
|
|
1354
1362
|
// @ts-expect-error we override
|
|
@@ -1368,16 +1376,7 @@ export const Spacer = createComponent<SpacerProps>({
|
|
|
1368
1376
|
|
|
1369
1377
|
variants: {
|
|
1370
1378
|
size: {
|
|
1371
|
-
'...
|
|
1372
|
-
size = size === true ? '$true' : size
|
|
1373
|
-
const sizePx = tokens.space[size] ?? size
|
|
1374
|
-
return {
|
|
1375
|
-
width: sizePx,
|
|
1376
|
-
height: sizePx,
|
|
1377
|
-
minWidth: sizePx,
|
|
1378
|
-
minHeight: sizePx,
|
|
1379
|
-
}
|
|
1380
|
-
},
|
|
1379
|
+
'...': getSpacerSize,
|
|
1381
1380
|
},
|
|
1382
1381
|
|
|
1383
1382
|
flex: {
|
package/src/createTamagui.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { isWeb } from '@tamagui/constants'
|
|
|
2
2
|
|
|
3
3
|
import { configListeners, setConfig, setTokens } from './config'
|
|
4
4
|
import { Variable } from './createVariable'
|
|
5
|
-
import { createVariables } from './createVariables'
|
|
5
|
+
import { DeepVariableObject, createVariables } from './createVariables'
|
|
6
6
|
import { getThemeCSSRules } from './helpers/getThemeCSSRules'
|
|
7
7
|
import {
|
|
8
8
|
getAllRules,
|
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
CreateTamaguiProps,
|
|
20
20
|
DedupedTheme,
|
|
21
21
|
DedupedThemes,
|
|
22
|
+
GenericFont,
|
|
22
23
|
GetCSS,
|
|
23
24
|
InferTamaguiConfig,
|
|
24
25
|
TamaguiInternalConfig,
|
|
@@ -38,62 +39,63 @@ export function createTamagui<Conf extends CreateTamaguiProps>(
|
|
|
38
39
|
return configIn as any
|
|
39
40
|
}
|
|
40
41
|
|
|
41
|
-
if (process.env.NODE_ENV === 'development') {
|
|
42
|
-
if (!configIn.tokens) {
|
|
43
|
-
throw new Error('Must define tokens')
|
|
44
|
-
}
|
|
45
|
-
if (!configIn.themes) {
|
|
46
|
-
throw new Error('Must define themes')
|
|
47
|
-
}
|
|
48
|
-
if (!configIn.fonts) {
|
|
49
|
-
throw new Error('Must define fonts')
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
42
|
// ensure variables
|
|
54
|
-
const tokens = createVariables(configIn.tokens)
|
|
55
|
-
|
|
56
|
-
// faster lookups
|
|
57
43
|
const tokensParsed: TokensParsed = {} as any
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
const
|
|
63
|
-
for (const
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
44
|
+
const tokens = createVariables(configIn.tokens || {})
|
|
45
|
+
|
|
46
|
+
if (configIn.tokens) {
|
|
47
|
+
// faster lookups
|
|
48
|
+
const tokensMerged: TokensMerged = {} as any
|
|
49
|
+
for (const cat in tokens) {
|
|
50
|
+
tokensParsed[cat] = {}
|
|
51
|
+
tokensMerged[cat] = {}
|
|
52
|
+
const tokenCat = tokens[cat]
|
|
53
|
+
for (const key in tokenCat) {
|
|
54
|
+
const val = tokenCat[key]
|
|
55
|
+
const prefixedKey = `$${key}`
|
|
56
|
+
tokensParsed[cat][prefixedKey] = val as any
|
|
57
|
+
tokensMerged[cat][prefixedKey] = val as any
|
|
58
|
+
tokensMerged[cat][key] = val as any
|
|
59
|
+
}
|
|
69
60
|
}
|
|
61
|
+
setTokens(tokensMerged)
|
|
70
62
|
}
|
|
71
|
-
setTokens(tokensMerged)
|
|
72
63
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
64
|
+
let foundThemes: DedupedThemes | undefined
|
|
65
|
+
if (configIn.themes) {
|
|
66
|
+
const noThemes = Object.keys(configIn.themes).length === 0
|
|
67
|
+
foundThemes = scanAllSheets(noThemes, tokensParsed)
|
|
68
|
+
}
|
|
76
69
|
|
|
77
|
-
|
|
78
|
-
Object.entries(configIn.fonts!).map(([k, v]) => {
|
|
79
|
-
return [k, createVariables(v, 'f', true)]
|
|
80
|
-
})
|
|
81
|
-
)
|
|
70
|
+
listenForSheetChanges()
|
|
82
71
|
|
|
83
72
|
let fontSizeTokens: Set<string> | null = null
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
for (const familyName in fontTokens) {
|
|
88
|
-
const font = fontTokens[familyName]
|
|
89
|
-
const fontParsed = parseFont(font)
|
|
90
|
-
res[`$${familyName}`] = fontParsed
|
|
91
|
-
if (!fontSizeTokens && fontParsed.size) {
|
|
92
|
-
fontSizeTokens = new Set(Object.keys(fontParsed.size))
|
|
73
|
+
let fontsParsed:
|
|
74
|
+
| {
|
|
75
|
+
[k: string]: DeepVariableObject<GenericFont<string>>
|
|
93
76
|
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
77
|
+
| undefined
|
|
78
|
+
|
|
79
|
+
if (configIn.fonts) {
|
|
80
|
+
const fontTokens = Object.fromEntries(
|
|
81
|
+
Object.entries(configIn.fonts).map(([k, v]) => {
|
|
82
|
+
return [k, createVariables(v, 'f', true)]
|
|
83
|
+
})
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
fontsParsed = (() => {
|
|
87
|
+
const res = {} as typeof fontTokens
|
|
88
|
+
for (const familyName in fontTokens) {
|
|
89
|
+
const font = fontTokens[familyName]
|
|
90
|
+
const fontParsed = parseFont(font)
|
|
91
|
+
res[`$${familyName}`] = fontParsed
|
|
92
|
+
if (!fontSizeTokens && fontParsed.size) {
|
|
93
|
+
fontSizeTokens = new Set(Object.keys(fontParsed.size))
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return res!
|
|
97
|
+
})()
|
|
98
|
+
}
|
|
97
99
|
|
|
98
100
|
const specificTokens = {}
|
|
99
101
|
|
|
@@ -238,14 +240,14 @@ ${runtimeStyles}`
|
|
|
238
240
|
let defaultFontName =
|
|
239
241
|
configIn.defaultFont ||
|
|
240
242
|
// uses font named "body" if present for compat
|
|
241
|
-
('body' in configIn.fonts ? 'body' : '')
|
|
243
|
+
(configIn.fonts && ('body' in configIn.fonts ? 'body' : ''))
|
|
242
244
|
|
|
243
245
|
if (!defaultFontName && configIn.fonts) {
|
|
244
246
|
// defaults to the first font to make life easier
|
|
245
247
|
defaultFontName = Object.keys(configIn.fonts)[0]
|
|
246
248
|
}
|
|
247
249
|
|
|
248
|
-
if (defaultFontName[0] === '$') {
|
|
250
|
+
if (defaultFontName?.[0] === '$') {
|
|
249
251
|
defaultFontName = defaultFontName.slice(1)
|
|
250
252
|
}
|
|
251
253
|
|
|
@@ -253,6 +255,7 @@ ${runtimeStyles}`
|
|
|
253
255
|
const defaultFont = `$${defaultFontName}`
|
|
254
256
|
|
|
255
257
|
const config: TamaguiInternalConfig = {
|
|
258
|
+
fonts: {},
|
|
256
259
|
groupNames: [],
|
|
257
260
|
settings: {},
|
|
258
261
|
onlyAllowShorthands: false,
|
|
@@ -267,7 +270,7 @@ ${runtimeStyles}`
|
|
|
267
270
|
? Object.fromEntries(Object.entries(shorthands).map(([k, v]) => [v, k]))
|
|
268
271
|
: {},
|
|
269
272
|
themes: themeConfig.themes as any,
|
|
270
|
-
fontsParsed,
|
|
273
|
+
fontsParsed: fontsParsed || {},
|
|
271
274
|
themeConfig,
|
|
272
275
|
tokensParsed: tokensParsed as any,
|
|
273
276
|
parsed: true,
|
|
@@ -23,7 +23,8 @@ export function getThemeCSSRules(props: {
|
|
|
23
23
|
const { config, themeName, theme, names } = props
|
|
24
24
|
|
|
25
25
|
// special case for SSR
|
|
26
|
-
const hasDarkLight =
|
|
26
|
+
const hasDarkLight =
|
|
27
|
+
config.themes && ('light' in config.themes || 'dark' in config.themes)
|
|
27
28
|
const CNP = `.${THEME_CLASSNAME_PREFIX}`
|
|
28
29
|
let vars = ''
|
|
29
30
|
|
|
@@ -101,7 +101,7 @@ const resolveVariants: StyleResolver = (
|
|
|
101
101
|
const { variants } = staticConfig
|
|
102
102
|
if (!variants) return
|
|
103
103
|
|
|
104
|
-
let variantValue = getVariantDefinition(variants[key],
|
|
104
|
+
let variantValue = getVariantDefinition(variants[key], value, conf)
|
|
105
105
|
|
|
106
106
|
if (process.env.NODE_ENV === 'development' && debug === 'verbose') {
|
|
107
107
|
console.groupCollapsed(`♦️♦️♦️ resolve variant ${key}`)
|
|
@@ -316,30 +316,28 @@ const tokenCats = ['size', 'color', 'radius', 'space', 'zIndex'].map((name) => (
|
|
|
316
316
|
}))
|
|
317
317
|
|
|
318
318
|
// goes through specificity finding best matching variant function
|
|
319
|
-
function getVariantDefinition(
|
|
320
|
-
variant: any,
|
|
321
|
-
key: string,
|
|
322
|
-
value: any,
|
|
323
|
-
conf: TamaguiInternalConfig
|
|
324
|
-
) {
|
|
319
|
+
function getVariantDefinition(variant: any, value: any, conf: TamaguiInternalConfig) {
|
|
325
320
|
if (typeof variant === 'function') {
|
|
326
321
|
return variant
|
|
327
322
|
}
|
|
328
|
-
|
|
329
|
-
|
|
323
|
+
const exact = variant[value]
|
|
324
|
+
if (exact) {
|
|
325
|
+
return exact
|
|
330
326
|
}
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
327
|
+
if (value != null) {
|
|
328
|
+
const { tokensParsed } = conf
|
|
329
|
+
for (const { name, spreadName } of tokenCats) {
|
|
330
|
+
if (spreadName in variant && value in tokensParsed[name]) {
|
|
331
|
+
return variant[spreadName]
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
const fontSizeVariant = variant['...fontSize']
|
|
335
|
+
if (fontSizeVariant && conf.fontSizeTokens.has(value)) {
|
|
336
|
+
return fontSizeVariant
|
|
335
337
|
}
|
|
336
|
-
}
|
|
337
|
-
const fontSizeVariant = variant['...fontSize']
|
|
338
|
-
if (fontSizeVariant && conf.fontSizeTokens.has(value)) {
|
|
339
|
-
return fontSizeVariant
|
|
340
338
|
}
|
|
341
339
|
// fallback to catch all | size
|
|
342
|
-
return variant[`:${typeof value}`] || variant['...']
|
|
340
|
+
return variant[`:${typeof value}`] || variant['...']
|
|
343
341
|
}
|
|
344
342
|
|
|
345
343
|
const fontShorthand = {
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { useContext } from 'react'
|
|
2
|
+
|
|
3
|
+
import { getConfig } from '../config'
|
|
4
|
+
import { ComponentContext } from '../contexts/ComponentContext'
|
|
5
|
+
|
|
6
|
+
export const useConfiguration = () => {
|
|
7
|
+
const { groups, animationDriver, ...restComponentConfig } = useContext(ComponentContext)
|
|
8
|
+
const { animations, ...restConfig } = getConfig()
|
|
9
|
+
return {
|
|
10
|
+
...restConfig,
|
|
11
|
+
...restComponentConfig,
|
|
12
|
+
animationDriver: animationDriver ?? getConfig().animations,
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { useContext } from 'react'
|
|
2
|
+
|
|
3
|
+
import { getConfig } from '../config'
|
|
4
|
+
import { ComponentContext } from '../contexts/ComponentContext'
|
|
5
|
+
import { ComponentContextI } from '../types'
|
|
6
|
+
|
|
7
|
+
export function useDisableSSR() {
|
|
8
|
+
const componentContext = useContext(ComponentContext)
|
|
9
|
+
return getDisableSSR(componentContext)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function getDisableSSR(componentContext: ComponentContextI) {
|
|
13
|
+
return componentContext.disableSSR ?? getConfig().disableSSR
|
|
14
|
+
}
|
package/src/hooks/useMedia.tsx
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { useIsomorphicLayoutEffect } from '@tamagui/constants'
|
|
2
|
-
import { useRef, useSyncExternalStore } from 'react'
|
|
2
|
+
import { useContext, useRef, useSyncExternalStore } from 'react'
|
|
3
3
|
|
|
4
4
|
import { getConfig } from '../config'
|
|
5
|
+
import { ComponentContext } from '../contexts/ComponentContext'
|
|
5
6
|
import { createProxy } from '../helpers/createProxy'
|
|
6
7
|
import { matchMedia } from '../helpers/matchMedia'
|
|
7
8
|
import { pseudoDescriptors } from '../helpers/pseudoDescriptors'
|
|
8
9
|
import type {
|
|
10
|
+
ComponentContextI,
|
|
9
11
|
MediaQueries,
|
|
10
12
|
MediaQueryKey,
|
|
11
13
|
MediaQueryObject,
|
|
@@ -13,6 +15,8 @@ import type {
|
|
|
13
15
|
TamaguiInternalConfig,
|
|
14
16
|
UseMediaState,
|
|
15
17
|
} from '../types'
|
|
18
|
+
import { useConfiguration } from './useConfiguration'
|
|
19
|
+
import { getDisableSSR, useDisableSSR } from './useDisableSSR'
|
|
16
20
|
|
|
17
21
|
export let mediaState: MediaQueryState =
|
|
18
22
|
// development only safeguard
|
|
@@ -50,9 +54,6 @@ export const isMediaKey = (key: string) =>
|
|
|
50
54
|
|
|
51
55
|
// for SSR capture it at time of startup
|
|
52
56
|
let initState: MediaQueryState
|
|
53
|
-
export const getInitialMediaState = () => {
|
|
54
|
-
return (getConfig().disableSSR ? mediaState : initState) || {}
|
|
55
|
-
}
|
|
56
57
|
|
|
57
58
|
// media always above pseudos
|
|
58
59
|
const defaultMediaImportance = Object.keys(pseudoDescriptors).length
|
|
@@ -191,14 +192,17 @@ function subscribe(subscriber: any) {
|
|
|
191
192
|
return () => listeners.delete(subscriber)
|
|
192
193
|
}
|
|
193
194
|
|
|
194
|
-
export function useMedia(uid?: any): UseMediaState {
|
|
195
|
+
export function useMedia(uid?: any, componentContext?: ComponentContextI): UseMediaState {
|
|
195
196
|
const internal = useRef<UseMediaInternalState | undefined>()
|
|
197
|
+
// performance boost to avoid using context twice
|
|
198
|
+
const disableSSR = componentContext ? getDisableSSR(componentContext) : useDisableSSR()
|
|
199
|
+
const initialState = (disableSSR ? mediaState : initState) || {}
|
|
196
200
|
|
|
197
201
|
const state = useSyncExternalStore<MediaQueryState>(
|
|
198
202
|
subscribe,
|
|
199
203
|
() => {
|
|
200
204
|
if (!internal.current) {
|
|
201
|
-
return
|
|
205
|
+
return initialState
|
|
202
206
|
}
|
|
203
207
|
|
|
204
208
|
const { touched, prev } = internal.current
|
|
@@ -223,13 +227,13 @@ export function useMedia(uid?: any): UseMediaState {
|
|
|
223
227
|
|
|
224
228
|
return mediaState
|
|
225
229
|
},
|
|
226
|
-
() =>
|
|
230
|
+
() => initialState
|
|
227
231
|
)
|
|
228
232
|
|
|
229
233
|
return new Proxy(state, {
|
|
230
234
|
get(_, key) {
|
|
231
235
|
if (typeof key === 'string') {
|
|
232
|
-
internal.current ||= { prev:
|
|
236
|
+
internal.current ||= { prev: initialState }
|
|
233
237
|
internal.current.touched ||= new Set()
|
|
234
238
|
internal.current.touched.add(key)
|
|
235
239
|
}
|
package/src/hooks/useProps.tsx
CHANGED
package/src/hooks/useTheme.tsx
CHANGED
|
@@ -21,8 +21,8 @@ import type {
|
|
|
21
21
|
import { GetThemeUnwrapped } from './getThemeUnwrapped'
|
|
22
22
|
|
|
23
23
|
export type ChangedThemeResponse = {
|
|
24
|
-
state
|
|
25
|
-
themeManager
|
|
24
|
+
state?: ThemeManagerState
|
|
25
|
+
themeManager?: ThemeManager | null
|
|
26
26
|
isNewTheme: boolean
|
|
27
27
|
mounted?: boolean
|
|
28
28
|
}
|
|
@@ -90,22 +90,23 @@ export const useThemeWithState = (
|
|
|
90
90
|
)
|
|
91
91
|
|
|
92
92
|
const { themeManager, state } = changedThemeState
|
|
93
|
-
const { theme, name, className } = state
|
|
94
93
|
|
|
95
|
-
if (!theme) {
|
|
94
|
+
if (!state?.theme) {
|
|
96
95
|
if (process.env.NODE_ENV === 'development') {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
props
|
|
100
|
-
|
|
101
|
-
|
|
96
|
+
if (process.env.TAMAGUI_DISABLE_NO_THEME_WARNING !== '1') {
|
|
97
|
+
console.warn(
|
|
98
|
+
`[tamagui] No theme found, this could be due to an invalid theme name (given theme props ${JSON.stringify(
|
|
99
|
+
props
|
|
100
|
+
)}).\n\nIf this is intended and you are using Tamagui without any themes, you can disable this warning by setting the environment variable TAMAGUI_DISABLE_NO_THEME_WARNING=1`
|
|
101
|
+
)
|
|
102
|
+
}
|
|
102
103
|
}
|
|
103
|
-
throw `❌ 1`
|
|
104
104
|
}
|
|
105
105
|
|
|
106
106
|
const themeProxied = useMemo(() => {
|
|
107
|
-
|
|
108
|
-
|
|
107
|
+
if (!themeManager || !state?.theme) return {}
|
|
108
|
+
return getThemeProxied(state.theme, themeManager, keys.current, props.debug)
|
|
109
|
+
}, [state, themeManager])
|
|
109
110
|
|
|
110
111
|
if (process.env.NODE_ENV === 'development' && props.debug === 'verbose') {
|
|
111
112
|
console.groupCollapsed(' 🔹 useTheme =>', name)
|
|
@@ -184,7 +185,7 @@ export const activeThemeManagers = new Set<ThemeManager>()
|
|
|
184
185
|
|
|
185
186
|
export const useChangeThemeEffect = (
|
|
186
187
|
props: ThemeProps,
|
|
187
|
-
|
|
188
|
+
isRoot = false,
|
|
188
189
|
keys?: string[],
|
|
189
190
|
shouldUpdate?: () => boolean | undefined
|
|
190
191
|
): ChangedThemeResponse => {
|
|
@@ -195,11 +196,10 @@ export const useChangeThemeEffect = (
|
|
|
195
196
|
|
|
196
197
|
const parentManager = useContext(ThemeManagerContext)
|
|
197
198
|
|
|
198
|
-
if (disable) {
|
|
199
|
-
if (!parentManager) throw `❌ 2`
|
|
199
|
+
if ((!isRoot && !parentManager) || disable) {
|
|
200
200
|
return {
|
|
201
201
|
isNewTheme: false,
|
|
202
|
-
state: parentManager
|
|
202
|
+
state: parentManager?.state,
|
|
203
203
|
themeManager: parentManager,
|
|
204
204
|
}
|
|
205
205
|
}
|
|
@@ -224,11 +224,11 @@ export const useChangeThemeEffect = (
|
|
|
224
224
|
function getShouldUpdateTheme(
|
|
225
225
|
manager = themeManager,
|
|
226
226
|
nextState?: ThemeManagerState | null,
|
|
227
|
-
prevState: ThemeManagerState = state,
|
|
227
|
+
prevState: ThemeManagerState | undefined = state,
|
|
228
228
|
forceShouldChange = false
|
|
229
229
|
) {
|
|
230
230
|
const forceUpdate = shouldUpdate?.()
|
|
231
|
-
if (!forceShouldChange && forceUpdate === false) return
|
|
231
|
+
if (!manager || (!forceShouldChange && forceUpdate === false)) return
|
|
232
232
|
const next = nextState || manager.getState(props, parentManager)
|
|
233
233
|
if (forceShouldChange) return next
|
|
234
234
|
if (!next) return
|
|
@@ -241,6 +241,8 @@ export const useChangeThemeEffect = (
|
|
|
241
241
|
if (!isServer) {
|
|
242
242
|
// listen for parent change + notify children change
|
|
243
243
|
useLayoutEffect(() => {
|
|
244
|
+
if (!themeManager) return
|
|
245
|
+
|
|
244
246
|
// SSR safe inverse (because server can't know prefers scheme)
|
|
245
247
|
// could be done through fancy selectors like how we do prefers-media
|
|
246
248
|
// but may be a bit of explosion of selectors
|
|
@@ -269,7 +271,6 @@ export const useChangeThemeEffect = (
|
|
|
269
271
|
const doUpdate = force ?? Boolean(keys?.length || isNewTheme)
|
|
270
272
|
|
|
271
273
|
if (process.env.NODE_ENV === 'development' && props.debug) {
|
|
272
|
-
|
|
273
274
|
// biome-ignore lint/suspicious/noConsoleLog: <explanation>
|
|
274
275
|
console.log(` 🔸 onChange`, themeManager.id, {
|
|
275
276
|
force,
|
|
@@ -278,7 +279,7 @@ export const useChangeThemeEffect = (
|
|
|
278
279
|
name,
|
|
279
280
|
manager,
|
|
280
281
|
keys,
|
|
281
|
-
})
|
|
282
|
+
})
|
|
282
283
|
}
|
|
283
284
|
if (doUpdate) {
|
|
284
285
|
setThemeState(createState)
|
|
@@ -313,12 +314,12 @@ export const useChangeThemeEffect = (
|
|
|
313
314
|
}
|
|
314
315
|
|
|
315
316
|
if (isInversingOnMount) {
|
|
316
|
-
if (!parentManager) throw '❌ 3'
|
|
317
317
|
return {
|
|
318
318
|
isNewTheme: false,
|
|
319
319
|
themeManager: parentManager,
|
|
320
320
|
state: {
|
|
321
|
-
|
|
321
|
+
name: '',
|
|
322
|
+
...parentManager?.state,
|
|
322
323
|
className: '',
|
|
323
324
|
},
|
|
324
325
|
}
|
|
@@ -342,7 +343,7 @@ export const useChangeThemeEffect = (
|
|
|
342
343
|
|
|
343
344
|
if (hasThemeUpdatingProps) {
|
|
344
345
|
const getNewThemeManager = () => {
|
|
345
|
-
return new ThemeManager(props,
|
|
346
|
+
return new ThemeManager(props, isRoot ? 'root' : parentManager)
|
|
346
347
|
}
|
|
347
348
|
|
|
348
349
|
if (prev?.themeManager) {
|
|
@@ -388,7 +389,7 @@ export const useChangeThemeEffect = (
|
|
|
388
389
|
const isNewTheme = Boolean(themeManager !== parentManager || props.inverse)
|
|
389
390
|
|
|
390
391
|
// only inverse relies on this for ssr
|
|
391
|
-
const mounted = !props.inverse ? true :
|
|
392
|
+
const mounted = !props.inverse ? true : isRoot || prev?.mounted
|
|
392
393
|
|
|
393
394
|
if (!state) {
|
|
394
395
|
if (isNewTheme) {
|
|
@@ -399,7 +400,7 @@ export const useChangeThemeEffect = (
|
|
|
399
400
|
}
|
|
400
401
|
}
|
|
401
402
|
|
|
402
|
-
if (!force && state.name === prev?.state
|
|
403
|
+
if (!force && state.name === prev?.state?.name) {
|
|
403
404
|
return prev
|
|
404
405
|
}
|
|
405
406
|
|
package/src/index.ts
CHANGED
|
@@ -31,7 +31,6 @@ export * from './contexts/ComponentContext'
|
|
|
31
31
|
export * from './helpers/createStyledContext'
|
|
32
32
|
export * from './helpers/expandStyles'
|
|
33
33
|
export * from './helpers/propMapper'
|
|
34
|
-
export * from './helpers/getAnimationDriver'
|
|
35
34
|
export * from './helpers/getExpandedShorthands'
|
|
36
35
|
export * from './helpers/getSplitStyles'
|
|
37
36
|
export * from './helpers/getStylesAtomic'
|
|
@@ -60,9 +59,10 @@ export {
|
|
|
60
59
|
} from './hooks/useMedia'
|
|
61
60
|
export * from './hooks/useTheme'
|
|
62
61
|
export * from './hooks/useThemeName'
|
|
63
|
-
export * from './hooks/
|
|
62
|
+
export * from './hooks/useConfiguration'
|
|
64
63
|
export * from './hooks/useIsTouchDevice'
|
|
65
64
|
export * from './hooks/useProps'
|
|
65
|
+
export * from './hooks/useConfiguration'
|
|
66
66
|
|
|
67
67
|
export * from './views/Slot'
|
|
68
68
|
export * from './views/Stack'
|
|
@@ -72,7 +72,7 @@ export * from './views/Theme'
|
|
|
72
72
|
export * from './views/ThemeProvider'
|
|
73
73
|
export * from './views/FontLanguage'
|
|
74
74
|
export * from './views/TamaguiProvider'
|
|
75
|
-
export * from './views/
|
|
75
|
+
export * from './views/Configuration'
|
|
76
76
|
|
|
77
77
|
export * from '@tamagui/use-did-finish-ssr'
|
|
78
78
|
export * from '@tamagui/use-event'
|
package/src/types.tsx
CHANGED
|
@@ -180,6 +180,7 @@ export type ReactComponentWithRef<Props, Ref> = ForwardRefExoticComponent<
|
|
|
180
180
|
>
|
|
181
181
|
|
|
182
182
|
export type ComponentContextI = {
|
|
183
|
+
disableSSR?: boolean
|
|
183
184
|
inText: boolean
|
|
184
185
|
language: LanguageContextType | null
|
|
185
186
|
animationDriver: AnimationDriver | null
|
|
@@ -413,12 +414,12 @@ type ConfProps<
|
|
|
413
414
|
H extends DefaultFontSetting = DefaultFontSetting,
|
|
414
415
|
I extends GenericTamaguiSettings = GenericTamaguiSettings
|
|
415
416
|
> = {
|
|
416
|
-
tokens
|
|
417
|
-
themes
|
|
417
|
+
tokens?: A
|
|
418
|
+
themes?: B
|
|
418
419
|
shorthands?: C
|
|
419
420
|
media?: D
|
|
420
421
|
animations?: AnimationDriver<E>
|
|
421
|
-
fonts
|
|
422
|
+
fonts?: F
|
|
422
423
|
onlyAllowShorthands?: G
|
|
423
424
|
defaultFont?: H
|
|
424
425
|
settings?: I
|
|
@@ -605,9 +606,9 @@ export type CreateTamaguiProps = {
|
|
|
605
606
|
shorthands?: CreateShorthands
|
|
606
607
|
media?: GenericTamaguiConfig['media']
|
|
607
608
|
animations?: AnimationDriver<any>
|
|
608
|
-
fonts
|
|
609
|
-
tokens
|
|
610
|
-
themes
|
|
609
|
+
fonts?: GenericTamaguiConfig['fonts']
|
|
610
|
+
tokens?: GenericTamaguiConfig['tokens']
|
|
611
|
+
themes?: {
|
|
611
612
|
[key: string]: {
|
|
612
613
|
[key: string]: string | number | Variable
|
|
613
614
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ComponentContext } from '../contexts/ComponentContext'
|
|
2
|
+
import type { AnimationDriver } from '../types'
|
|
3
|
+
|
|
4
|
+
interface ConfigurationProps {
|
|
5
|
+
animationDriver?: AnimationDriver | null
|
|
6
|
+
children: React.ReactNode
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const Configuration = (props: ConfigurationProps) => {
|
|
10
|
+
return <ComponentContext.Provider {...props} />
|
|
11
|
+
}
|