@tamagui/core 1.0.1-beta.225 → 1.0.1-beta.227
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/createComponent.js +5 -14
- package/dist/cjs/createComponent.js.map +2 -2
- package/dist/cjs/helpers/ThemeManager.js +18 -11
- package/dist/cjs/helpers/ThemeManager.js.map +3 -3
- package/dist/cjs/helpers/getSplitStyles.js +61 -43
- package/dist/cjs/helpers/getSplitStyles.js.map +3 -3
- package/dist/cjs/helpers/normalizeColor.js +2 -2
- package/dist/cjs/helpers/normalizeColor.js.map +2 -2
- package/dist/cjs/hooks/useTheme.js +24 -20
- package/dist/cjs/hooks/useTheme.js.map +3 -3
- package/dist/cjs/styled.js +0 -10
- package/dist/cjs/styled.js.map +2 -2
- package/dist/cjs/types.js.map +1 -1
- package/dist/cjs/views/Theme.js +5 -9
- package/dist/cjs/views/Theme.js.map +2 -2
- package/dist/esm/createComponent.js +5 -14
- package/dist/esm/createComponent.js.map +2 -2
- package/dist/esm/helpers/ThemeManager.js +13 -6
- package/dist/esm/helpers/ThemeManager.js.map +2 -2
- package/dist/esm/helpers/getSplitStyles.js +61 -43
- package/dist/esm/helpers/getSplitStyles.js.map +3 -3
- package/dist/esm/helpers/normalizeColor.js +1 -1
- package/dist/esm/helpers/normalizeColor.js.map +1 -1
- package/dist/esm/hooks/useTheme.js +24 -20
- package/dist/esm/hooks/useTheme.js.map +3 -3
- package/dist/esm/styled.js +0 -10
- package/dist/esm/styled.js.map +2 -2
- package/dist/esm/views/Theme.js +5 -9
- package/dist/esm/views/Theme.js.map +2 -2
- package/package.json +13 -13
- package/src/createComponent.tsx +7 -46
- package/src/helpers/ThemeManager.tsx +25 -11
- package/src/helpers/getSplitStyles.tsx +104 -62
- package/src/helpers/normalizeColor.ts +1 -1
- package/src/hooks/useTheme.tsx +29 -22
- package/src/styled.tsx +0 -12
- package/src/types.tsx +5 -8
- package/src/views/Theme.tsx +5 -9
- package/types/helpers/ThemeManager.d.ts +2 -2
- package/types/helpers/getSplitStyles.d.ts +22 -6
- package/types/hooks/useTheme.d.ts +0 -1
- package/types/types.d.ts +4 -8
package/src/createComponent.tsx
CHANGED
|
@@ -200,8 +200,12 @@ export function createComponent<
|
|
|
200
200
|
if (isAnimated && presence) {
|
|
201
201
|
const presenceState = presence[2]
|
|
202
202
|
if (presenceState) {
|
|
203
|
-
if (
|
|
204
|
-
|
|
203
|
+
if (state.unmounted && presenceState.enterVariant) {
|
|
204
|
+
props[presenceState.enterVariant] = true
|
|
205
|
+
}
|
|
206
|
+
if (!presenceState.isPresent && presenceState.exitVariant) {
|
|
207
|
+
props[presenceState.exitVariant] = true
|
|
208
|
+
}
|
|
205
209
|
}
|
|
206
210
|
}
|
|
207
211
|
|
|
@@ -550,7 +554,7 @@ export function createComponent<
|
|
|
550
554
|
|
|
551
555
|
viewProps.ref = useComposedRefs(hostRef as any, forwardedRef, setMounted)
|
|
552
556
|
|
|
553
|
-
if (process.env.NODE_ENV === 'development' && !isText && isWeb
|
|
557
|
+
if (process.env.NODE_ENV === 'development' && !isText && isWeb) {
|
|
554
558
|
Children.toArray(props.children).forEach((item) => {
|
|
555
559
|
if (typeof item === 'string') {
|
|
556
560
|
// eslint-disable-next-line no-console
|
|
@@ -1037,7 +1041,6 @@ export function createComponent<
|
|
|
1037
1041
|
Component,
|
|
1038
1042
|
...conf,
|
|
1039
1043
|
neverFlatten: true,
|
|
1040
|
-
isHOC: true,
|
|
1041
1044
|
defaultProps: {
|
|
1042
1045
|
...Component.defaultProps,
|
|
1043
1046
|
...conf?.defaultProps,
|
|
@@ -1295,45 +1298,3 @@ const dontComposePressabilityKeys = {
|
|
|
1295
1298
|
function getMediaStateObject(obj: Object) {
|
|
1296
1299
|
return Object.fromEntries(Object.entries(obj).flatMap(([k, v]) => (v ? [[`$${k}`, v]] : [])))
|
|
1297
1300
|
}
|
|
1298
|
-
|
|
1299
|
-
// function ensureBaseHasDefaults(
|
|
1300
|
-
// base: ViewStyle,
|
|
1301
|
-
// pseudos: Record<string, ViewStyle | null | undefined>
|
|
1302
|
-
// ) {
|
|
1303
|
-
// const mergeIfNotExists = (key: string) => {
|
|
1304
|
-
// if (!base.transform?.some((x) => key in x)) {
|
|
1305
|
-
// mergeTransform(base, key, transformDefaults[key] || 0)
|
|
1306
|
-
// }
|
|
1307
|
-
// }
|
|
1308
|
-
|
|
1309
|
-
// for (const name in pseudos) {
|
|
1310
|
-
// const pseudo = pseudos[name]
|
|
1311
|
-
// for (const key in pseudo) {
|
|
1312
|
-
// const val = pseudo[key]
|
|
1313
|
-
// if (key in stylePropsTransform) {
|
|
1314
|
-
// mergeIfNotExists(key)
|
|
1315
|
-
// } else if (key === 'transform') {
|
|
1316
|
-
// if (typeof val === 'string') continue
|
|
1317
|
-
// for (const t of val) {
|
|
1318
|
-
// mergeIfNotExists(Object.keys(t)[0])
|
|
1319
|
-
// }
|
|
1320
|
-
// } else {
|
|
1321
|
-
// if (key in baseDefaults && !(key in base)) {
|
|
1322
|
-
// base[key] = baseDefaults[key]
|
|
1323
|
-
// }
|
|
1324
|
-
// }
|
|
1325
|
-
// }
|
|
1326
|
-
// }
|
|
1327
|
-
// }
|
|
1328
|
-
|
|
1329
|
-
const baseDefaults = {
|
|
1330
|
-
opacity: 1,
|
|
1331
|
-
}
|
|
1332
|
-
|
|
1333
|
-
const transformDefaults = {
|
|
1334
|
-
opacity: 1,
|
|
1335
|
-
scale: 1,
|
|
1336
|
-
rotate: '0deg',
|
|
1337
|
-
rotateY: '0deg',
|
|
1338
|
-
rotateX: '0deg',
|
|
1339
|
-
}
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { isWeb } from '@tamagui/constants'
|
|
2
|
-
|
|
3
1
|
import { getThemes } from '../config'
|
|
4
2
|
import { THEME_CLASSNAME_PREFIX, THEME_NAME_SEPARATOR } from '../constants/constants'
|
|
5
3
|
import { getThemeUnwrapped } from '../hooks/getThemeUnwrapped'
|
|
@@ -80,18 +78,32 @@ export class ThemeManager {
|
|
|
80
78
|
}
|
|
81
79
|
}
|
|
82
80
|
|
|
83
|
-
getStateIfChanged(
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
81
|
+
getStateIfChanged(
|
|
82
|
+
props = this.props,
|
|
83
|
+
state: ThemeManagerState | null = this.state,
|
|
84
|
+
parentManager = this.parentManager
|
|
85
|
+
) {
|
|
86
|
+
const _ = this.getState(props, parentManager)
|
|
87
|
+
|
|
88
|
+
// is removing
|
|
89
|
+
if (state && state !== emptyState && !_) {
|
|
90
|
+
return parentManager?.state
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (!_ || !_.theme || _.theme === state?.theme) {
|
|
94
|
+
// prettier-ignore
|
|
95
|
+
// eslint-disable-next-line no-console
|
|
96
|
+
if (process.env.NODE_ENV === 'development' && props.debug === 'verbose') console.log(`getStateIfChanged not changed`, _?.theme === state?.theme, _, state)
|
|
88
97
|
return null
|
|
89
98
|
}
|
|
90
99
|
return _
|
|
91
100
|
}
|
|
92
101
|
|
|
93
|
-
getState(props = this.props) {
|
|
94
|
-
return
|
|
102
|
+
getState(props = this.props, parentManager = this.parentManager) {
|
|
103
|
+
return (
|
|
104
|
+
getState(props, parentManager) ||
|
|
105
|
+
(process.env.TAMAGUI_TARGET === 'native' ? parentManager?.state : undefined)
|
|
106
|
+
)
|
|
95
107
|
}
|
|
96
108
|
|
|
97
109
|
#allKeys: Set<string> | null = null
|
|
@@ -170,7 +182,7 @@ function getState(
|
|
|
170
182
|
|
|
171
183
|
// prettier-ignore
|
|
172
184
|
// eslint-disable-next-line no-console
|
|
173
|
-
if (process.env.NODE_ENV === 'development' && props.debug === 'verbose') console.
|
|
185
|
+
if (process.env.NODE_ENV === 'development' && props.debug === 'verbose') [console.groupCollapsed('getState', props, { parentName, parentBaseTheme, base, min, max, isParentAComponentTheme }), console.trace(), console.groupEnd()]
|
|
174
186
|
|
|
175
187
|
for (let i = max; i >= min; i--) {
|
|
176
188
|
let prefix = base.slice(0, i).join(THEME_NAME_SEPARATOR)
|
|
@@ -193,7 +205,9 @@ function getState(
|
|
|
193
205
|
if (componentName) {
|
|
194
206
|
// components only look for component themes
|
|
195
207
|
if (nextName) {
|
|
196
|
-
potentials.push(
|
|
208
|
+
potentials.push(
|
|
209
|
+
`${prefix.slice(0, prefix.indexOf(THEME_NAME_SEPARATOR))}_${nextName}_${componentName}`
|
|
210
|
+
)
|
|
197
211
|
}
|
|
198
212
|
potentials.push(`${prefix}_${componentName}`)
|
|
199
213
|
if (nextName) {
|
|
@@ -48,6 +48,33 @@ import {
|
|
|
48
48
|
} from './normalizeValueWithProperty.js'
|
|
49
49
|
import { pseudoDescriptors } from './pseudoDescriptors'
|
|
50
50
|
|
|
51
|
+
type GetStyleResult = {
|
|
52
|
+
pseudos: PseudoStyles
|
|
53
|
+
medias: Record<MediaQueryKey, ViewStyle>
|
|
54
|
+
style: ViewStyle
|
|
55
|
+
classNames: ClassNamesObject
|
|
56
|
+
rulesToInsert: RulesToInsert
|
|
57
|
+
viewProps: StackProps & Record<string, any>
|
|
58
|
+
fontFamily: string | undefined
|
|
59
|
+
mediaKeys: string[]
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
type GetStyleState = {
|
|
63
|
+
style: ViewStyle
|
|
64
|
+
usedKeys: Record<string, number>
|
|
65
|
+
classNames: ClassNamesObject
|
|
66
|
+
flatTransforms: FlatTransforms
|
|
67
|
+
staticConfig: StaticConfigParsed
|
|
68
|
+
theme: ThemeParsed
|
|
69
|
+
props: Record<string, any>
|
|
70
|
+
viewProps: Record<string, any>
|
|
71
|
+
state: SplitStyleState
|
|
72
|
+
conf: TamaguiInternalConfig
|
|
73
|
+
languageContext?: FontLanguageProps
|
|
74
|
+
avoidDefaultProps?: boolean
|
|
75
|
+
avoidMergeTransform?: boolean
|
|
76
|
+
}
|
|
77
|
+
|
|
51
78
|
export type SplitStyles = ReturnType<typeof getSplitStyles>
|
|
52
79
|
export type ClassNamesObject = Record<string, string>
|
|
53
80
|
export type SplitStyleResult = ReturnType<typeof getSplitStyles>
|
|
@@ -134,28 +161,17 @@ type TransformNamespaceKey = 'transform' | PseudoPropKeys | MediaQueryKey
|
|
|
134
161
|
|
|
135
162
|
let conf: TamaguiInternalConfig
|
|
136
163
|
|
|
137
|
-
type SplitStylesAndProps = {
|
|
138
|
-
pseudos: PseudoStyles
|
|
139
|
-
medias: Record<MediaQueryKey, ViewStyle>
|
|
140
|
-
style: ViewStyle
|
|
141
|
-
classNames: ClassNamesObject
|
|
142
|
-
rulesToInsert: RulesToInsert
|
|
143
|
-
viewProps: StackProps & Record<string, any>
|
|
144
|
-
fontFamily: string | undefined
|
|
145
|
-
mediaKeys: string[]
|
|
146
|
-
}
|
|
147
|
-
|
|
148
164
|
type StyleSplitter = (
|
|
149
165
|
props: { [key: string]: any },
|
|
150
166
|
staticConfig: StaticConfigParsed,
|
|
151
167
|
theme: ThemeParsed,
|
|
152
168
|
state: SplitStyleState,
|
|
153
|
-
parentSplitStyles?:
|
|
169
|
+
parentSplitStyles?: GetStyleResult | null,
|
|
154
170
|
languageContext?: LanguageContextType,
|
|
155
171
|
// web-only
|
|
156
172
|
elementType?: string,
|
|
157
173
|
debug?: DebugProp
|
|
158
|
-
) =>
|
|
174
|
+
) => GetStyleResult
|
|
159
175
|
|
|
160
176
|
export const PROP_SPLIT = '-'
|
|
161
177
|
|
|
@@ -190,7 +206,7 @@ export const getSplitStyles: StyleSplitter = (
|
|
|
190
206
|
conf = conf || getConfig()
|
|
191
207
|
const validStyleProps = staticConfig.isText ? stylePropsText : validStyles
|
|
192
208
|
const mediaKeys: string[] = []
|
|
193
|
-
const viewProps:
|
|
209
|
+
const viewProps: GetStyleResult['viewProps'] = {}
|
|
194
210
|
const pseudos: PseudoStyles = {}
|
|
195
211
|
let psuedosUsed: Record<string, number> | null = null
|
|
196
212
|
const medias: Record<MediaQueryKey, ViewStyle> = {}
|
|
@@ -202,7 +218,7 @@ export const getSplitStyles: StyleSplitter = (
|
|
|
202
218
|
staticConfig.acceptsClassName && (isWeb || IS_STATIC) && !state.noClassNames
|
|
203
219
|
|
|
204
220
|
let style: ViewStyle = {}
|
|
205
|
-
|
|
221
|
+
const flatTransforms: FlatTransforms = {}
|
|
206
222
|
|
|
207
223
|
const len = propKeys.length
|
|
208
224
|
const rulesToInsert: RulesToInsert = []
|
|
@@ -214,6 +230,20 @@ export const getSplitStyles: StyleSplitter = (
|
|
|
214
230
|
// fontFamily is our special baby, ensure we grab the latest set one always
|
|
215
231
|
let fontFamily: string | undefined
|
|
216
232
|
|
|
233
|
+
const styleState: GetStyleState = {
|
|
234
|
+
classNames,
|
|
235
|
+
conf,
|
|
236
|
+
flatTransforms,
|
|
237
|
+
props,
|
|
238
|
+
state,
|
|
239
|
+
staticConfig,
|
|
240
|
+
style,
|
|
241
|
+
theme,
|
|
242
|
+
usedKeys,
|
|
243
|
+
viewProps,
|
|
244
|
+
languageContext,
|
|
245
|
+
}
|
|
246
|
+
|
|
217
247
|
if (props.className) {
|
|
218
248
|
for (const cn of props.className.split(' ')) {
|
|
219
249
|
if (cn[0] === '_') {
|
|
@@ -293,23 +323,6 @@ export const getSplitStyles: StyleSplitter = (
|
|
|
293
323
|
continue
|
|
294
324
|
}
|
|
295
325
|
|
|
296
|
-
function mergeStyle(key: string, val: any) {
|
|
297
|
-
usedKeys[key] = usedKeys[key] || 1
|
|
298
|
-
if (val && val[0] === '_') {
|
|
299
|
-
classNames[key] = val
|
|
300
|
-
} else if (key in stylePropsTransform) {
|
|
301
|
-
flatTransforms ||= {}
|
|
302
|
-
flatTransforms[key] = val
|
|
303
|
-
} else {
|
|
304
|
-
const out = normalizeValueWithProperty(val, key)
|
|
305
|
-
if (key in validStylesOnBaseProps) {
|
|
306
|
-
viewProps[key] = out
|
|
307
|
-
} else {
|
|
308
|
-
style[key] = out
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
|
|
313
326
|
if (process.env.TAMAGUI_TARGET === 'web') {
|
|
314
327
|
/**
|
|
315
328
|
* Copying in the accessibility/prop handling from react-native-web here
|
|
@@ -548,18 +561,7 @@ export const getSplitStyles: StyleSplitter = (
|
|
|
548
561
|
if (!val) continue
|
|
549
562
|
|
|
550
563
|
// TODO can avoid processing this if !shouldDoClasses + state is off
|
|
551
|
-
const pseudoStyleObject = getSubStyle(
|
|
552
|
-
key,
|
|
553
|
-
val,
|
|
554
|
-
staticConfig,
|
|
555
|
-
theme,
|
|
556
|
-
props,
|
|
557
|
-
state,
|
|
558
|
-
conf,
|
|
559
|
-
languageContext,
|
|
560
|
-
true,
|
|
561
|
-
true
|
|
562
|
-
)
|
|
564
|
+
const pseudoStyleObject = getSubStyle(styleState, key, val, true, state.noClassNames)
|
|
563
565
|
|
|
564
566
|
const descriptor = pseudoDescriptors[key as keyof typeof pseudoDescriptors]
|
|
565
567
|
const isEnter = descriptor.name === 'enter'
|
|
@@ -590,20 +592,32 @@ export const getSplitStyles: StyleSplitter = (
|
|
|
590
592
|
}
|
|
591
593
|
}
|
|
592
594
|
} else {
|
|
593
|
-
|
|
594
|
-
|
|
595
|
+
const isDisabled = !state[descriptor.stateKey || descriptor.name]
|
|
596
|
+
if (!isDisabled) {
|
|
597
|
+
usedKeys[key] ||= 1
|
|
595
598
|
}
|
|
596
599
|
psuedosUsed ||= {}
|
|
597
|
-
|
|
600
|
+
|
|
598
601
|
const importance = descriptor.priority
|
|
599
602
|
for (const pkey in pseudoStyleObject) {
|
|
600
|
-
const curImportance = psuedosUsed[importance] || 0
|
|
601
603
|
const val = pseudoStyleObject[pkey]
|
|
604
|
+
// when disabled ensure the default value is set for future animations to align
|
|
605
|
+
if (isDisabled) {
|
|
606
|
+
if (!(pkey in usedKeys) && pkey in animatableDefaults) {
|
|
607
|
+
const defaultVal = animatableDefaults[pkey]
|
|
608
|
+
mergeStyle(styleState, pkey, defaultVal, true)
|
|
609
|
+
}
|
|
610
|
+
continue
|
|
611
|
+
}
|
|
612
|
+
const curImportance = psuedosUsed[importance] || 0
|
|
602
613
|
if (importance >= curImportance) {
|
|
603
614
|
psuedosUsed[pkey] = importance
|
|
604
615
|
pseudos[key] ||= {}
|
|
605
616
|
pseudos[key][pkey] = val
|
|
606
|
-
|
|
617
|
+
// prettier-ignore
|
|
618
|
+
// eslint-disable-next-line no-console
|
|
619
|
+
if (process.env.NODE_ENV === 'development' && debug === 'verbose') console.log('merging', pkey, val)
|
|
620
|
+
mergeStyle(styleState, pkey, val)
|
|
607
621
|
}
|
|
608
622
|
}
|
|
609
623
|
}
|
|
@@ -622,14 +636,9 @@ export const getSplitStyles: StyleSplitter = (
|
|
|
622
636
|
// we avoid passing in default props for media queries because that would confuse things like SizableText.size:
|
|
623
637
|
|
|
624
638
|
const mediaStyle = getSubStyle(
|
|
639
|
+
styleState,
|
|
625
640
|
key,
|
|
626
641
|
val,
|
|
627
|
-
staticConfig,
|
|
628
|
-
theme,
|
|
629
|
-
props,
|
|
630
|
-
state,
|
|
631
|
-
conf,
|
|
632
|
-
languageContext,
|
|
633
642
|
// TODO try true like pseudo
|
|
634
643
|
false
|
|
635
644
|
)
|
|
@@ -675,7 +684,7 @@ export const getSplitStyles: StyleSplitter = (
|
|
|
675
684
|
}
|
|
676
685
|
|
|
677
686
|
if (validStyleProps[key]) {
|
|
678
|
-
mergeStyle(key, val)
|
|
687
|
+
mergeStyle(styleState, key, val)
|
|
679
688
|
continue
|
|
680
689
|
}
|
|
681
690
|
|
|
@@ -697,6 +706,11 @@ export const getSplitStyles: StyleSplitter = (
|
|
|
697
706
|
// always do this at the very end to preserve the order strictly (animations, origin)
|
|
698
707
|
// and allow proper merging of all pseudos before applying
|
|
699
708
|
if (flatTransforms) {
|
|
709
|
+
if (process.env.NODE_ENV === 'development' && debug) {
|
|
710
|
+
// prettier-ignore
|
|
711
|
+
// eslint-disable-next-line no-console
|
|
712
|
+
console.log(`Merging flat transforms, transform before`, [...style.transform || []], flatTransforms)
|
|
713
|
+
}
|
|
700
714
|
mergeTransforms(style, flatTransforms, true)
|
|
701
715
|
}
|
|
702
716
|
|
|
@@ -864,18 +878,38 @@ function getSubStyleProps(defaultProps: Object, baseProps: Object, specificProps
|
|
|
864
878
|
return cache.get(key)!
|
|
865
879
|
}
|
|
866
880
|
|
|
881
|
+
function mergeStyle(
|
|
882
|
+
{ usedKeys, classNames, flatTransforms, viewProps, style }: GetStyleState,
|
|
883
|
+
key: string,
|
|
884
|
+
val: any,
|
|
885
|
+
dontSetUsed = false
|
|
886
|
+
) {
|
|
887
|
+
if (!dontSetUsed) {
|
|
888
|
+
usedKeys[key] = usedKeys[key] || 1
|
|
889
|
+
}
|
|
890
|
+
if (val && val[0] === '_') {
|
|
891
|
+
classNames[key] = val
|
|
892
|
+
} else if (key in stylePropsTransform) {
|
|
893
|
+
flatTransforms ||= {}
|
|
894
|
+
flatTransforms[key] = val
|
|
895
|
+
} else {
|
|
896
|
+
const out = normalizeValueWithProperty(val, key)
|
|
897
|
+
if (key in validStylesOnBaseProps) {
|
|
898
|
+
viewProps[key] = out
|
|
899
|
+
} else {
|
|
900
|
+
style[key] = out
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
|
|
867
905
|
export const getSubStyle = (
|
|
906
|
+
styleState: GetStyleState,
|
|
868
907
|
subKey: string,
|
|
869
908
|
styleIn: Object,
|
|
870
|
-
staticConfig: StaticConfigParsed,
|
|
871
|
-
theme: ThemeParsed,
|
|
872
|
-
props: any,
|
|
873
|
-
state: SplitStyleState,
|
|
874
|
-
conf: TamaguiInternalConfig,
|
|
875
|
-
languageContext?: FontLanguageProps,
|
|
876
909
|
avoidDefaultProps?: boolean,
|
|
877
910
|
avoidMergeTransform?: boolean
|
|
878
911
|
): ViewStyle => {
|
|
912
|
+
const { staticConfig, theme, props, state, conf, languageContext } = styleState
|
|
879
913
|
const styleOut: ViewStyle = {}
|
|
880
914
|
|
|
881
915
|
for (let key in styleIn) {
|
|
@@ -939,3 +973,11 @@ function addStyleToInsertRules(rulesToInsert: RulesToInsert, styleObject: Partia
|
|
|
939
973
|
function processIDRefList(idRefList: string | Array<string>): string {
|
|
940
974
|
return Array.isArray(idRefList) ? idRefList.join(' ') : idRefList
|
|
941
975
|
}
|
|
976
|
+
|
|
977
|
+
const animatableDefaults = {
|
|
978
|
+
opacity: 1,
|
|
979
|
+
scale: 1,
|
|
980
|
+
rotate: '0deg',
|
|
981
|
+
rotateY: '0deg',
|
|
982
|
+
rotateX: '0deg',
|
|
983
|
+
}
|
package/src/hooks/useTheme.tsx
CHANGED
|
@@ -11,7 +11,6 @@ import { ThemeParsed, ThemeProps } from '../types'
|
|
|
11
11
|
import { GetThemeUnwrapped } from './getThemeUnwrapped'
|
|
12
12
|
|
|
13
13
|
export type ChangedThemeResponse = {
|
|
14
|
-
themes: Record<string, ThemeParsed>
|
|
15
14
|
themeManager: ThemeManager | null
|
|
16
15
|
name: string
|
|
17
16
|
isNewTheme?: boolean
|
|
@@ -20,17 +19,22 @@ export type ChangedThemeResponse = {
|
|
|
20
19
|
}
|
|
21
20
|
|
|
22
21
|
const emptyProps = { name: null }
|
|
22
|
+
|
|
23
|
+
function getDefaultThemeProxied() {
|
|
24
|
+
const config = getConfig()
|
|
25
|
+
const name = Object.keys(config.themes)[0]
|
|
26
|
+
return getThemeProxied({
|
|
27
|
+
theme: config.themes[name],
|
|
28
|
+
name,
|
|
29
|
+
})
|
|
30
|
+
}
|
|
31
|
+
|
|
23
32
|
export const useTheme = (props: ThemeProps = emptyProps): ThemeParsed => {
|
|
24
33
|
if (isRSC) {
|
|
25
|
-
|
|
26
|
-
const name = Object.keys(config.themes)[0]
|
|
27
|
-
return getThemeProxied({
|
|
28
|
-
theme: config.themes[name],
|
|
29
|
-
name,
|
|
30
|
-
})
|
|
34
|
+
return getDefaultThemeProxied()
|
|
31
35
|
}
|
|
32
36
|
|
|
33
|
-
const { name, theme,
|
|
37
|
+
const { name, theme, themeManager, className, isNewTheme } = useChangeThemeEffect(props)
|
|
34
38
|
|
|
35
39
|
if (process.env.NODE_ENV === 'development') {
|
|
36
40
|
// ensure we aren't creating too many ThemeManagers
|
|
@@ -53,7 +57,7 @@ export const useTheme = (props: ThemeProps = emptyProps): ThemeParsed => {
|
|
|
53
57
|
if (process.env.NODE_ENV === 'development') {
|
|
54
58
|
console.warn('No theme found', name, props, themeManager)
|
|
55
59
|
}
|
|
56
|
-
return
|
|
60
|
+
return getDefaultThemeProxied()
|
|
57
61
|
}
|
|
58
62
|
|
|
59
63
|
return useMemo(() => {
|
|
@@ -121,26 +125,26 @@ export const getThemeIsNewTheme = (theme: any): ThemeManager | undefined => them
|
|
|
121
125
|
export const activeThemeManagers = new Set<ThemeManager>()
|
|
122
126
|
|
|
123
127
|
export const useChangeThemeEffect = (props: ThemeProps, root = false): ChangedThemeResponse => {
|
|
124
|
-
const parentManager = useContext(ThemeManagerContext)
|
|
125
|
-
const config = getConfig()
|
|
126
|
-
const { debug } = props
|
|
127
|
-
// @ts-expect-error internal use only
|
|
128
|
-
const disable = props.disable
|
|
129
|
-
const { themes } = config
|
|
130
128
|
if (isRSC) {
|
|
131
129
|
// we need context working for this to work well
|
|
132
130
|
return {
|
|
133
131
|
...createState().state,
|
|
134
|
-
themes,
|
|
135
132
|
themeManager: null,
|
|
136
133
|
}
|
|
137
134
|
}
|
|
135
|
+
const parentManager = useContext(ThemeManagerContext)
|
|
136
|
+
|
|
137
|
+
const {
|
|
138
|
+
debug,
|
|
139
|
+
// @ts-expect-error internal use only
|
|
140
|
+
disable,
|
|
141
|
+
} = props
|
|
142
|
+
|
|
138
143
|
if (disable) {
|
|
139
144
|
if (!parentManager) throw new Error(`Disable topmost`)
|
|
140
145
|
return {
|
|
141
146
|
...parentManager.state,
|
|
142
147
|
isNewTheme: false,
|
|
143
|
-
themes,
|
|
144
148
|
themeManager: parentManager,
|
|
145
149
|
}
|
|
146
150
|
}
|
|
@@ -189,10 +193,11 @@ export const useChangeThemeEffect = (props: ThemeProps, root = false): ChangedTh
|
|
|
189
193
|
|
|
190
194
|
// this seems unnecessary
|
|
191
195
|
if (hasNoThemeUpdatingProps(props)) {
|
|
192
|
-
if (!parentManager) throw
|
|
196
|
+
if (!parentManager) throw `impossible`
|
|
197
|
+
// prettier-ignore
|
|
198
|
+
if (process.env.NODE_ENV === 'development' && props.debug === 'verbose') console.log('useTheme no updating props', parentManager.state)
|
|
193
199
|
return {
|
|
194
200
|
...parentManager.state,
|
|
195
|
-
themes,
|
|
196
201
|
themeManager: parentManager,
|
|
197
202
|
isNewTheme: false,
|
|
198
203
|
}
|
|
@@ -202,13 +207,12 @@ export const useChangeThemeEffect = (props: ThemeProps, root = false): ChangedTh
|
|
|
202
207
|
updateState()
|
|
203
208
|
|
|
204
209
|
if (!mounted && !parentManager) {
|
|
205
|
-
throw
|
|
210
|
+
throw `impossible`
|
|
206
211
|
}
|
|
207
212
|
|
|
208
213
|
return {
|
|
209
214
|
...state,
|
|
210
215
|
isNewTheme,
|
|
211
|
-
themes,
|
|
212
216
|
themeManager,
|
|
213
217
|
...(!mounted &&
|
|
214
218
|
parentManager && {
|
|
@@ -235,8 +239,11 @@ export const useChangeThemeEffect = (props: ThemeProps, root = false): ChangedTh
|
|
|
235
239
|
}
|
|
236
240
|
|
|
237
241
|
function updateState() {
|
|
238
|
-
if (themeManager.getStateIfChanged(props, state, parentManager)) {
|
|
242
|
+
if (themeManager.getStateIfChanged(props, isNewTheme ? state : null, parentManager)) {
|
|
239
243
|
setThemeState(createState)
|
|
244
|
+
} else {
|
|
245
|
+
// prettier-ignore
|
|
246
|
+
if (process.env.NODE_ENV === 'development' && props.debug === 'verbose') console.log(`useTheme updateState didn't change`)
|
|
240
247
|
}
|
|
241
248
|
}
|
|
242
249
|
}
|
package/src/styled.tsx
CHANGED
|
@@ -63,18 +63,6 @@ export function styled<
|
|
|
63
63
|
const parentStaticConfig =
|
|
64
64
|
'staticConfig' in Component ? (Component.staticConfig as StaticConfig) : null
|
|
65
65
|
|
|
66
|
-
if (process.env.NODE_ENV === 'development') {
|
|
67
|
-
if (parentStaticConfig?.isHOC) {
|
|
68
|
-
// eslint-disable-next-line no-console
|
|
69
|
-
console.warn(
|
|
70
|
-
`Warning: Parent component is a functional component, not a Tamagui styled() component. Extending with styled() will break and lead to incorrect styles.`,
|
|
71
|
-
`Given options:`,
|
|
72
|
-
options,
|
|
73
|
-
new Error().stack
|
|
74
|
-
)
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
66
|
if (options) {
|
|
79
67
|
const {
|
|
80
68
|
variants,
|
package/src/types.tsx
CHANGED
|
@@ -13,7 +13,7 @@ import type {
|
|
|
13
13
|
} from '@tamagui/types-react-native'
|
|
14
14
|
import type { Properties } from 'csstype'
|
|
15
15
|
import type {
|
|
16
|
-
|
|
16
|
+
ComponentType,
|
|
17
17
|
ForwardRefExoticComponent,
|
|
18
18
|
FunctionComponent,
|
|
19
19
|
HTMLAttributes,
|
|
@@ -538,6 +538,8 @@ export type ThemeValueGet<K extends string | number | symbol> = K extends 'theme
|
|
|
538
538
|
? FontTokens
|
|
539
539
|
: K extends FontSizeKeys
|
|
540
540
|
? FontSizeTokens
|
|
541
|
+
: K extends `${`border${string | ''}Radius`}`
|
|
542
|
+
? RadiusTokens
|
|
541
543
|
: K extends SpaceKeys
|
|
542
544
|
? K extends 'shadowOffset'
|
|
543
545
|
? { width: SpaceTokens; height: SpaceTokens }
|
|
@@ -810,11 +812,6 @@ export type StaticConfig = StaticConfigPublic & {
|
|
|
810
812
|
*/
|
|
811
813
|
memo?: boolean
|
|
812
814
|
|
|
813
|
-
/**
|
|
814
|
-
* Used internally to handle extractable HoC separate
|
|
815
|
-
*/
|
|
816
|
-
isHOC?: boolean
|
|
817
|
-
|
|
818
815
|
/**
|
|
819
816
|
* Used insternally to attach default props to names
|
|
820
817
|
*/
|
|
@@ -843,7 +840,7 @@ export type StylableComponent =
|
|
|
843
840
|
| TamaguiComponent
|
|
844
841
|
// * excessively deep type instantiation
|
|
845
842
|
// | TamaguiReactElement
|
|
846
|
-
|
|
|
843
|
+
| ComponentType<any>
|
|
847
844
|
| ForwardRefExoticComponent<any>
|
|
848
845
|
| ReactComponentWithRef<any, any>
|
|
849
846
|
| (new (props: any) => any)
|
|
@@ -873,7 +870,7 @@ export type GetProps<A extends StylableComponent> = A extends TamaguiComponent<i
|
|
|
873
870
|
? Props
|
|
874
871
|
: A extends TamaguiReactElement<infer Props>
|
|
875
872
|
? Props
|
|
876
|
-
: A extends
|
|
873
|
+
: A extends ComponentType<infer Props>
|
|
877
874
|
? GetGenericComponentTamaguiProps<Props>
|
|
878
875
|
: A extends new (props: infer Props) => any
|
|
879
876
|
? GetGenericComponentTamaguiProps<Props>
|
package/src/views/Theme.tsx
CHANGED
|
@@ -14,14 +14,10 @@ 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
|
-
)
|
|
17
|
+
const { name, theme, themeManager, isNewTheme, className } = useChangeThemeEffect(props, isRoot)
|
|
21
18
|
|
|
22
19
|
const disableThemeClass = props.disableThemeClass
|
|
23
|
-
const missingTheme = !
|
|
24
|
-
const disablePassingTheme = missingTheme || !isNewTheme
|
|
20
|
+
const missingTheme = !name || !theme
|
|
25
21
|
|
|
26
22
|
// memo here, changing theme without re-rendering all children is a critical optimization
|
|
27
23
|
// may require some effort of end user to memoize but without this memo they'd have no option
|
|
@@ -30,8 +26,8 @@ export function Theme(props: ThemeProps) {
|
|
|
30
26
|
? React.cloneElement(props.children, { ['data-themeable']: true })
|
|
31
27
|
: props.children
|
|
32
28
|
|
|
33
|
-
return
|
|
34
|
-
}, [
|
|
29
|
+
return missingTheme ? next : wrapThemeManagerContext(next, themeManager)
|
|
30
|
+
}, [missingTheme, props.children, themeManager])
|
|
35
31
|
|
|
36
32
|
if (process.env.NODE_ENV === 'development' && missingTheme) {
|
|
37
33
|
// eslint-disable-next-line no-console
|
|
@@ -39,7 +35,7 @@ export function Theme(props: ThemeProps) {
|
|
|
39
35
|
return props.children
|
|
40
36
|
}
|
|
41
37
|
|
|
42
|
-
if (disableThemeClass ||
|
|
38
|
+
if (disableThemeClass || missingTheme) {
|
|
43
39
|
return contents
|
|
44
40
|
}
|
|
45
41
|
|
|
@@ -24,8 +24,8 @@ export declare class ThemeManager {
|
|
|
24
24
|
updateState(props?: ThemeProps & {
|
|
25
25
|
forceTheme?: ThemeParsed;
|
|
26
26
|
}, notify?: boolean): ThemeManagerState | undefined;
|
|
27
|
-
getStateIfChanged(props?: ThemeProps, state?: ThemeManagerState, parentManager?: ThemeManager | null): ThemeManagerState | null;
|
|
28
|
-
getState(props?: ThemeProps): ThemeManagerState |
|
|
27
|
+
getStateIfChanged(props?: ThemeProps, state?: ThemeManagerState | null, parentManager?: ThemeManager | null): ThemeManagerState | null | undefined;
|
|
28
|
+
getState(props?: ThemeProps, parentManager?: ThemeManager | null): ThemeManagerState | undefined;
|
|
29
29
|
get allKeys(): Set<string>;
|
|
30
30
|
getValue(key: string, state?: ThemeManagerState): import("..").Variable<any> | undefined;
|
|
31
31
|
notify(): void;
|