@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.
Files changed (42) hide show
  1. package/dist/cjs/createComponent.js +5 -14
  2. package/dist/cjs/createComponent.js.map +2 -2
  3. package/dist/cjs/helpers/ThemeManager.js +18 -11
  4. package/dist/cjs/helpers/ThemeManager.js.map +3 -3
  5. package/dist/cjs/helpers/getSplitStyles.js +61 -43
  6. package/dist/cjs/helpers/getSplitStyles.js.map +3 -3
  7. package/dist/cjs/helpers/normalizeColor.js +2 -2
  8. package/dist/cjs/helpers/normalizeColor.js.map +2 -2
  9. package/dist/cjs/hooks/useTheme.js +24 -20
  10. package/dist/cjs/hooks/useTheme.js.map +3 -3
  11. package/dist/cjs/styled.js +0 -10
  12. package/dist/cjs/styled.js.map +2 -2
  13. package/dist/cjs/types.js.map +1 -1
  14. package/dist/cjs/views/Theme.js +5 -9
  15. package/dist/cjs/views/Theme.js.map +2 -2
  16. package/dist/esm/createComponent.js +5 -14
  17. package/dist/esm/createComponent.js.map +2 -2
  18. package/dist/esm/helpers/ThemeManager.js +13 -6
  19. package/dist/esm/helpers/ThemeManager.js.map +2 -2
  20. package/dist/esm/helpers/getSplitStyles.js +61 -43
  21. package/dist/esm/helpers/getSplitStyles.js.map +3 -3
  22. package/dist/esm/helpers/normalizeColor.js +1 -1
  23. package/dist/esm/helpers/normalizeColor.js.map +1 -1
  24. package/dist/esm/hooks/useTheme.js +24 -20
  25. package/dist/esm/hooks/useTheme.js.map +3 -3
  26. package/dist/esm/styled.js +0 -10
  27. package/dist/esm/styled.js.map +2 -2
  28. package/dist/esm/views/Theme.js +5 -9
  29. package/dist/esm/views/Theme.js.map +2 -2
  30. package/package.json +13 -13
  31. package/src/createComponent.tsx +7 -46
  32. package/src/helpers/ThemeManager.tsx +25 -11
  33. package/src/helpers/getSplitStyles.tsx +104 -62
  34. package/src/helpers/normalizeColor.ts +1 -1
  35. package/src/hooks/useTheme.tsx +29 -22
  36. package/src/styled.tsx +0 -12
  37. package/src/types.tsx +5 -8
  38. package/src/views/Theme.tsx +5 -9
  39. package/types/helpers/ThemeManager.d.ts +2 -2
  40. package/types/helpers/getSplitStyles.d.ts +22 -6
  41. package/types/hooks/useTheme.d.ts +0 -1
  42. package/types/types.d.ts +4 -8
@@ -200,8 +200,12 @@ export function createComponent<
200
200
  if (isAnimated && presence) {
201
201
  const presenceState = presence[2]
202
202
  if (presenceState) {
203
- if (presenceState.enterVariant) props[presenceState.enterVariant] = true
204
- if (presenceState.exitVariant) props[presenceState.exitVariant] = true
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 && !staticConfig.isHOC) {
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(props = this.props, state = this.state, parentManager = this.parentManager) {
84
- const _ =
85
- getState(props, parentManager) ||
86
- (process.env.TAMAGUI_TARGET === 'native' ? parentManager?.state : undefined)
87
- if (!_ || !_.theme || _.theme === state.theme) {
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 getState(props, this.parentManager)
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.log('getState', props, { parentName, parentBaseTheme, base, min, max, isParentAComponentTheme, parentManager })
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(`${prefix.replace(/_.*$/, '')}_${nextName}_${componentName}`)
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?: SplitStylesAndProps | null,
169
+ parentSplitStyles?: GetStyleResult | null,
154
170
  languageContext?: LanguageContextType,
155
171
  // web-only
156
172
  elementType?: string,
157
173
  debug?: DebugProp
158
- ) => SplitStylesAndProps
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: SplitStylesAndProps['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
- let flatTransforms: FlatTransforms | undefined
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
- if (!state[descriptor.stateKey || descriptor.name]) {
594
- continue
595
+ const isDisabled = !state[descriptor.stateKey || descriptor.name]
596
+ if (!isDisabled) {
597
+ usedKeys[key] ||= 1
595
598
  }
596
599
  psuedosUsed ||= {}
597
- usedKeys[key] ||= 1
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
- mergeStyle(pkey, val)
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
+ }
@@ -1,4 +1,4 @@
1
- import normalizeCSSColor from '@tamagui/normalize-css-color-lite'
1
+ import normalizeCSSColor from 'normalize-css-color'
2
2
 
3
3
  export const normalizeColor = (color?: number | string | null, opacity?: number) => {
4
4
  if (color == null || color == undefined) {
@@ -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
- const config = getConfig()
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, themes, themeManager, className, isNewTheme } = useChangeThemeEffect(props)
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 themes[Object.keys(themes)[0]]
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 new Error(`Nada`)
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 new Error(`Impossible`)
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
- Component,
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
- | Component
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 Component<infer Props>
873
+ : A extends ComponentType<infer Props>
877
874
  ? GetGenericComponentTamaguiProps<Props>
878
875
  : A extends new (props: infer Props) => any
879
876
  ? GetGenericComponentTamaguiProps<Props>
@@ -14,14 +14,10 @@ export function Theme(props: ThemeProps) {
14
14
  }
15
15
 
16
16
  const isRoot = !!props['_isRoot']
17
- const { name, theme, themeManager, themes, isNewTheme, className } = useChangeThemeEffect(
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 = !themes || !name || !theme
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 disablePassingTheme ? next : wrapThemeManagerContext(next, themeManager)
34
- }, [disablePassingTheme, props.children, themeManager])
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 || disablePassingTheme) {
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 | null;
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;