@tamagui/web 1.46.2 → 1.47.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.
Files changed (173) hide show
  1. package/dist/cjs/constants/constants.js +15 -15
  2. package/dist/cjs/constants/constants.js.map +1 -1
  3. package/dist/cjs/createComponent.js +83 -106
  4. package/dist/cjs/createComponent.js.map +1 -1
  5. package/dist/cjs/createTamagui.js +0 -1
  6. package/dist/cjs/createTamagui.js.map +1 -1
  7. package/dist/cjs/helpers/ThemeManager.js +6 -5
  8. package/dist/cjs/helpers/ThemeManager.js.map +1 -1
  9. package/dist/cjs/helpers/getSplitStyles.js +75 -98
  10. package/dist/cjs/helpers/getSplitStyles.js.map +2 -2
  11. package/dist/cjs/helpers/getStylesAtomic.js +7 -7
  12. package/dist/cjs/helpers/getStylesAtomic.js.map +1 -1
  13. package/dist/cjs/helpers/getVariantExtras.js +2 -10
  14. package/dist/cjs/helpers/getVariantExtras.js.map +1 -1
  15. package/dist/cjs/helpers/isTamaguiComponent.js +1 -1
  16. package/dist/cjs/helpers/isTamaguiComponent.js.map +1 -1
  17. package/dist/cjs/helpers/mergeProps.js +6 -14
  18. package/dist/cjs/helpers/mergeProps.js.map +1 -1
  19. package/dist/cjs/helpers/normalizeColor.js +2 -1
  20. package/dist/cjs/helpers/normalizeColor.js.map +1 -1
  21. package/dist/cjs/helpers/normalizeValueWithProperty.js +5 -56
  22. package/dist/cjs/helpers/normalizeValueWithProperty.js.map +1 -1
  23. package/dist/cjs/helpers/{createPropMapper.js → propMapper.js} +63 -139
  24. package/dist/cjs/helpers/propMapper.js.map +6 -0
  25. package/dist/cjs/helpers/pseudoDescriptors.js +0 -1
  26. package/dist/cjs/helpers/pseudoDescriptors.js.map +1 -1
  27. package/dist/cjs/helpers/useShallowSetState.js +9 -17
  28. package/dist/cjs/helpers/useShallowSetState.js.map +1 -1
  29. package/dist/cjs/helpers/withStaticProperties.js +9 -0
  30. package/dist/cjs/helpers/withStaticProperties.js.map +1 -1
  31. package/dist/cjs/hooks/useMedia.js +7 -9
  32. package/dist/cjs/hooks/useMedia.js.map +1 -1
  33. package/dist/cjs/hooks/useStyle.js +5 -2
  34. package/dist/cjs/hooks/useStyle.js.map +1 -1
  35. package/dist/cjs/hooks/useTheme.js +28 -32
  36. package/dist/cjs/hooks/useTheme.js.map +1 -1
  37. package/dist/cjs/index.js +2 -2
  38. package/dist/cjs/index.js.map +1 -1
  39. package/dist/cjs/views/Stack.js +1 -4
  40. package/dist/cjs/views/Stack.js.map +1 -1
  41. package/dist/cjs/views/Theme.js +2 -2
  42. package/dist/cjs/views/Theme.js.map +1 -1
  43. package/dist/cjs/views/ThemeDebug.js +2 -2
  44. package/dist/cjs/views/ThemeDebug.js.map +1 -1
  45. package/dist/esm/constants/constants.js +14 -13
  46. package/dist/esm/constants/constants.js.map +1 -1
  47. package/dist/esm/createComponent.js +83 -106
  48. package/dist/esm/createComponent.js.map +1 -1
  49. package/dist/esm/createTamagui.js +0 -1
  50. package/dist/esm/createTamagui.js.map +1 -1
  51. package/dist/esm/helpers/ThemeManager.js +6 -5
  52. package/dist/esm/helpers/ThemeManager.js.map +1 -1
  53. package/dist/esm/helpers/getSplitStyles.js +74 -97
  54. package/dist/esm/helpers/getSplitStyles.js.map +2 -2
  55. package/dist/esm/helpers/getStylesAtomic.js +7 -7
  56. package/dist/esm/helpers/getStylesAtomic.js.map +1 -1
  57. package/dist/esm/helpers/getVariantExtras.js +2 -10
  58. package/dist/esm/helpers/getVariantExtras.js.map +1 -1
  59. package/dist/esm/helpers/isTamaguiComponent.js +1 -1
  60. package/dist/esm/helpers/isTamaguiComponent.js.map +1 -1
  61. package/dist/esm/helpers/mergeProps.js +6 -14
  62. package/dist/esm/helpers/mergeProps.js.map +1 -1
  63. package/dist/esm/helpers/normalizeColor.js +2 -1
  64. package/dist/esm/helpers/normalizeColor.js.map +1 -1
  65. package/dist/esm/helpers/normalizeValueWithProperty.js +5 -56
  66. package/dist/esm/helpers/normalizeValueWithProperty.js.map +1 -1
  67. package/dist/esm/helpers/{createPropMapper.js → propMapper.js} +56 -132
  68. package/dist/esm/helpers/propMapper.js.map +6 -0
  69. package/dist/esm/helpers/pseudoDescriptors.js +0 -1
  70. package/dist/esm/helpers/pseudoDescriptors.js.map +1 -1
  71. package/dist/esm/helpers/useShallowSetState.js +9 -17
  72. package/dist/esm/helpers/useShallowSetState.js.map +1 -1
  73. package/dist/esm/helpers/withStaticProperties.js +9 -0
  74. package/dist/esm/helpers/withStaticProperties.js.map +1 -1
  75. package/dist/esm/hooks/useMedia.js +8 -10
  76. package/dist/esm/hooks/useMedia.js.map +1 -1
  77. package/dist/esm/hooks/useStyle.js +5 -2
  78. package/dist/esm/hooks/useStyle.js.map +1 -1
  79. package/dist/esm/hooks/useTheme.js +28 -32
  80. package/dist/esm/hooks/useTheme.js.map +1 -1
  81. package/dist/esm/index.js +1 -1
  82. package/dist/esm/index.js.map +1 -1
  83. package/dist/esm/views/Stack.js +1 -4
  84. package/dist/esm/views/Stack.js.map +1 -1
  85. package/dist/esm/views/Theme.js +2 -2
  86. package/dist/esm/views/Theme.js.map +1 -1
  87. package/dist/esm/views/ThemeDebug.js +2 -2
  88. package/dist/esm/views/ThemeDebug.js.map +1 -1
  89. package/package.json +9 -9
  90. package/src/constants/constants.ts +15 -11
  91. package/src/createComponent.tsx +143 -140
  92. package/src/createTamagui.ts +0 -1
  93. package/src/helpers/ThemeManager.tsx +10 -6
  94. package/src/helpers/getSplitStyles.tsx +139 -172
  95. package/src/helpers/getStylesAtomic.ts +7 -7
  96. package/src/helpers/getVariantExtras.tsx +15 -31
  97. package/src/helpers/isTamaguiComponent.tsx +3 -3
  98. package/src/helpers/mergeProps.ts +5 -20
  99. package/src/helpers/normalizeColor.ts +2 -1
  100. package/src/helpers/normalizeValueWithProperty.ts +8 -64
  101. package/src/helpers/{createPropMapper.ts → propMapper.ts} +71 -165
  102. package/src/helpers/pseudoDescriptors.ts +0 -1
  103. package/src/helpers/useShallowSetState.tsx +10 -16
  104. package/src/helpers/withStaticProperties.tsx +13 -0
  105. package/src/hooks/useMedia.tsx +15 -10
  106. package/src/hooks/useStyle.tsx +7 -4
  107. package/src/hooks/useTheme.tsx +36 -47
  108. package/src/index.ts +1 -1
  109. package/src/types.tsx +20 -33
  110. package/src/views/Stack.tsx +1 -4
  111. package/src/views/Theme.tsx +3 -3
  112. package/src/views/ThemeDebug.tsx +2 -2
  113. package/types/constants/constants.d.ts +0 -15
  114. package/types/constants/constants.d.ts.map +1 -1
  115. package/types/createComponent.d.ts +5 -8
  116. package/types/createComponent.d.ts.map +1 -1
  117. package/types/createTamagui.d.ts.map +1 -1
  118. package/types/helpers/ThemeManager.d.ts +1 -1
  119. package/types/helpers/ThemeManager.d.ts.map +1 -1
  120. package/types/helpers/getSplitStyles.d.ts +3 -7
  121. package/types/helpers/getSplitStyles.d.ts.map +1 -1
  122. package/types/helpers/getVariantExtras.d.ts +1 -1
  123. package/types/helpers/getVariantExtras.d.ts.map +1 -1
  124. package/types/helpers/isTamaguiComponent.d.ts.map +1 -1
  125. package/types/helpers/mergeProps.d.ts +1 -1
  126. package/types/helpers/mergeProps.d.ts.map +1 -1
  127. package/types/helpers/normalizeColor.d.ts.map +1 -1
  128. package/types/helpers/normalizeValueWithProperty.d.ts.map +1 -1
  129. package/types/helpers/{createPropMapper.d.ts → propMapper.d.ts} +3 -3
  130. package/types/helpers/propMapper.d.ts.map +1 -0
  131. package/types/helpers/pseudoDescriptors.d.ts.map +1 -1
  132. package/types/helpers/useShallowSetState.d.ts.map +1 -1
  133. package/types/helpers/withStaticProperties.d.ts.map +1 -1
  134. package/types/hooks/useMedia.d.ts.map +1 -1
  135. package/types/hooks/useStyle.d.ts +2 -2
  136. package/types/hooks/useStyle.d.ts.map +1 -1
  137. package/types/hooks/useTheme.d.ts +7 -13
  138. package/types/hooks/useTheme.d.ts.map +1 -1
  139. package/types/index.d.ts +1 -1
  140. package/types/index.d.ts.map +1 -1
  141. package/types/styled.d.ts +1 -1
  142. package/types/types.d.ts +17 -25
  143. package/types/types.d.ts.map +1 -1
  144. package/types/views/Stack.d.ts.map +1 -1
  145. package/dist/cjs/helpers/createPropMapper.js.map +0 -6
  146. package/dist/cjs/helpers/parseStaticConfig.js +0 -40
  147. package/dist/cjs/helpers/parseStaticConfig.js.map +0 -6
  148. package/dist/cjs/helpers/swapFontFaceOnWeight.js +0 -63
  149. package/dist/cjs/helpers/swapFontFaceOnWeight.js.map +0 -6
  150. package/dist/cjs/hooks/useSafeRef.js +0 -59
  151. package/dist/cjs/hooks/useSafeRef.js.map +0 -6
  152. package/dist/cjs/hooks/useServerHooks.js +0 -36
  153. package/dist/cjs/hooks/useServerHooks.js.map +0 -6
  154. package/dist/esm/helpers/createPropMapper.js.map +0 -6
  155. package/dist/esm/helpers/parseStaticConfig.js +0 -16
  156. package/dist/esm/helpers/parseStaticConfig.js.map +0 -6
  157. package/dist/esm/helpers/swapFontFaceOnWeight.js +0 -39
  158. package/dist/esm/helpers/swapFontFaceOnWeight.js.map +0 -6
  159. package/dist/esm/hooks/useSafeRef.js +0 -35
  160. package/dist/esm/hooks/useSafeRef.js.map +0 -6
  161. package/dist/esm/hooks/useServerHooks.js +0 -11
  162. package/dist/esm/hooks/useServerHooks.js.map +0 -6
  163. package/src/helpers/parseStaticConfig.ts +0 -14
  164. package/src/hooks/useSafeRef.ts +0 -45
  165. package/types/helpers/createPropMapper.d.ts.map +0 -1
  166. package/types/helpers/parseStaticConfig.d.ts +0 -3
  167. package/types/helpers/parseStaticConfig.d.ts.map +0 -1
  168. package/types/helpers/swapFontFaceOnWeight.d.ts +0 -4
  169. package/types/helpers/swapFontFaceOnWeight.d.ts.map +0 -1
  170. package/types/hooks/useSafeRef.d.ts +0 -4
  171. package/types/hooks/useSafeRef.d.ts.map +0 -1
  172. package/types/hooks/useServerHooks.d.ts +0 -4
  173. package/types/hooks/useServerHooks.d.ts.map +0 -1
@@ -41,9 +41,10 @@ import type {
41
41
  PseudoStyles,
42
42
  RulesToInsert,
43
43
  SpaceTokens,
44
- SplitStyleState,
45
- StaticConfigParsed,
44
+ SplitStyleProps,
45
+ StaticConfig,
46
46
  StyleObject,
47
+ TamaguiComponentState,
47
48
  TamaguiInternalConfig,
48
49
  TextStyleProps,
49
50
  ThemeParsed,
@@ -51,7 +52,6 @@ import type {
51
52
  } from '../types'
52
53
  import type { LanguageContextType } from '../views/FontLanguage.types'
53
54
  import { createMediaStyle } from './createMediaStyle'
54
- import { getPropMappedFontFamily } from './createPropMapper'
55
55
  import { fixStyles } from './expandStyles'
56
56
  import { generateAtomicStyles, getStylesAtomic, styleToCSS } from './getStylesAtomic'
57
57
  import {
@@ -65,6 +65,7 @@ import {
65
65
  normalizeValueWithProperty,
66
66
  reverseMapClassNameToValue,
67
67
  } from './normalizeValueWithProperty'
68
+ import { getPropMappedFontFamily, propMapper } from './propMapper'
68
69
  import { pseudoDescriptors } from './pseudoDescriptors'
69
70
 
70
71
  const fontFamilyKey = 'fontFamily'
@@ -82,12 +83,11 @@ let conf: TamaguiInternalConfig
82
83
 
83
84
  type StyleSplitter = (
84
85
  props: { [key: string]: any },
85
- staticConfig: StaticConfigParsed,
86
- themeState: {
87
- theme: ThemeParsed
88
- name: string
89
- },
90
- state: SplitStyleState,
86
+ staticConfig: StaticConfig,
87
+ theme: ThemeParsed,
88
+ themeName: string,
89
+ componentState: TamaguiComponentState,
90
+ styleProps: SplitStyleProps,
91
91
  parentSplitStyles?: GetStyleResult | null,
92
92
  languageContext?: LanguageContextType,
93
93
  // web-only
@@ -97,18 +97,34 @@ type StyleSplitter = (
97
97
 
98
98
  export const PROP_SPLIT = '-'
99
99
 
100
- // loop props backwards
101
- // track used keys:
102
- // const keys = new Set<string>()
103
- // keep classnames and styles separate:
104
- // const styles = {}
105
- // const classNames = {}
100
+ // if you need and easier way to test performance, you can do something like this
101
+ // add this early return somewhere in this file and you can see roughly where it slows down:
102
+
103
+ // return {
104
+ // space,
105
+ // hasMedia,
106
+ // fontFamily: styleState.fontFamily,
107
+ // viewProps: {
108
+ // children: props.children,
109
+ // },
110
+ // style: {
111
+ // borderColor: props.borderColor,
112
+ // borderWidth: props.borderWidth,
113
+ // padding: props.padding,
114
+ // },
115
+ // pseudos,
116
+ // classNames,
117
+ // rulesToInsert,
118
+ // dynamicThemeAccess,
119
+ // }
106
120
 
107
121
  export const getSplitStyles: StyleSplitter = (
108
122
  props,
109
123
  staticConfig,
110
- themeState,
111
- state,
124
+ theme,
125
+ themeName,
126
+ componentState,
127
+ styleProps,
112
128
  parentSplitStyles,
113
129
  languageContext,
114
130
  elementType,
@@ -116,31 +132,27 @@ export const getSplitStyles: StyleSplitter = (
116
132
  ) => {
117
133
  conf = conf || getConfig()
118
134
  const { shorthands } = conf
119
- const { theme, name: themeName } = themeState
120
135
  const {
121
136
  isHOC,
137
+ isText,
122
138
  variants,
123
- propMapper,
124
139
  isReactNative,
125
140
  inlineProps,
126
141
  inlineWhenUnflattened,
142
+ parentStaticConfig,
143
+ acceptsClassName,
127
144
  } = staticConfig
128
- const validStyleProps = staticConfig.isText ? stylePropsText : validStyles
145
+ const validStyleProps = isText ? stylePropsText : validStyles
129
146
  const viewProps: GetStyleResult['viewProps'] = {}
130
147
  let pseudos: PseudoStyles | null = null
131
- const mediaState = state.mediaState || globalMediaState
148
+ const mediaState = styleProps.mediaState || globalMediaState
132
149
  const usedKeys: Record<string, number> = {}
133
- const propKeys = Object.keys(props)
134
- const numProps = propKeys.length
135
150
  let space: SpaceTokens | null = props.space
136
151
  let hasMedia: boolean | string[] = false
137
152
  let dynamicThemeAccess: boolean | undefined
138
-
139
- const shouldDoClasses =
140
- staticConfig.acceptsClassName && (isWeb || IS_STATIC) && !state.noClassNames
153
+ const shouldDoClasses = acceptsClassName && isWeb && !styleProps.noClassNames
141
154
 
142
155
  let style: ViewStyleWithPseudos = {}
143
- const flatTransforms: FlatTransforms = {}
144
156
  const rulesToInsert: RulesToInsert = []
145
157
  const classNames: ClassNamesObject = {}
146
158
  let className = '' // existing classNames
@@ -154,11 +166,12 @@ export const getSplitStyles: StyleSplitter = (
154
166
  * Not the biggest fan of creating this object but it is a nice API
155
167
  */
156
168
  const styleState: GetStyleState = {
157
- curProps: props,
169
+ curProps: { ...props },
158
170
  classNames,
159
171
  conf,
160
172
  props,
161
- state,
173
+ styleProps,
174
+ componentState,
162
175
  staticConfig,
163
176
  style,
164
177
  theme,
@@ -172,7 +185,7 @@ export const getSplitStyles: StyleSplitter = (
172
185
  console.groupCollapsed('getSplitStyles (collapsed)')
173
186
  // prettier-ignore
174
187
  // rome-ignore lint/nursery/noConsoleLog: ok
175
- console.log({ props, staticConfig, shouldDoClasses, state, propKeys, styleState, theme: { ...theme } })
188
+ console.log({ props, staticConfig, shouldDoClasses, styleProps, componentState, styleState, theme: { ...theme } })
176
189
  console.groupEnd()
177
190
  }
178
191
 
@@ -180,7 +193,7 @@ export const getSplitStyles: StyleSplitter = (
180
193
  // since the compiler will optimize to className we just treat className as the more powerful
181
194
  // TODO the compiler should probably just leave things inline if its not flattening
182
195
  // that way it keeps merging order
183
- if (typeof props.className === 'string') {
196
+ if (process.env.TAMAGUI_TARGET === 'web' && typeof props.className === 'string') {
184
197
  for (const cn of props.className.split(' ')) {
185
198
  if (cn[0] === '_') {
186
199
  // tamagui, merge it expanded on key, eventually this will go away with better compiler
@@ -207,10 +220,9 @@ export const getSplitStyles: StyleSplitter = (
207
220
  }
208
221
  }
209
222
 
210
- for (let i = 0; i < numProps; i++) {
211
- const keyOg = propKeys[i]
223
+ for (const keyOg in props) {
212
224
  let keyInit = keyOg
213
- let valInit = props[keyInit]
225
+ let valInit = props[keyOg]
214
226
 
215
227
  // normalize shorthands up front
216
228
  if (keyInit in shorthands) {
@@ -306,7 +318,7 @@ export const getSplitStyles: StyleSplitter = (
306
318
  }
307
319
 
308
320
  const isMainStyle = keyInit === 'style'
309
- if (isMainStyle || keyInit.startsWith('_style')) {
321
+ if (isMainStyle || (keyInit[0] === '_' && keyInit.startsWith('_style'))) {
310
322
  if (!valInit) continue
311
323
  const styles = [].concat(valInit).flat()
312
324
  const styleLen = styles.length
@@ -472,13 +484,18 @@ export const getSplitStyles: StyleSplitter = (
472
484
  * for if there's a pseudo/media returned from it.
473
485
  */
474
486
 
475
- let isMedia = isMediaKey(keyInit)
487
+ const isValidStyleKeyInit = keyInit in validStyleProps
488
+ const isShorthand = keyInit in shorthands
489
+
490
+ let isVariant = !isValidStyleKeyInit && variants && keyInit in variants
491
+
492
+ const isStyleLikeKey = isShorthand || isValidStyleKeyInit || isVariant
493
+
476
494
  let isPseudo = keyInit in validPseudoKeys
495
+ let isMedia = !isStyleLikeKey && !isPseudo && isMediaKey(keyInit)
477
496
  let isMediaOrPseudo = isMedia || isPseudo
478
497
 
479
- let isVariant = variants && keyInit in variants
480
- const isStyleProp =
481
- isMediaOrPseudo || isVariant || keyInit in validStyleProps || keyInit in shorthands
498
+ const isStyleProp = isMediaOrPseudo || isVariant || isValidStyleKeyInit || isShorthand
482
499
 
483
500
  if (isStyleProp && props.asChild === 'except-style') {
484
501
  continue
@@ -487,14 +504,14 @@ export const getSplitStyles: StyleSplitter = (
487
504
  const shouldPassProp =
488
505
  !isStyleProp ||
489
506
  // is in parent variants
490
- (isHOC &&
491
- staticConfig.parentStaticConfig?.variants &&
492
- keyInit in staticConfig.parentStaticConfig.variants)
507
+ (isHOC && parentStaticConfig?.variants && keyInit in parentStaticConfig.variants)
493
508
 
494
509
  const isHOCShouldPassThrough = Boolean(
495
510
  isHOC &&
496
- (isMediaOrPseudo ||
497
- staticConfig.parentStaticConfig?.variants?.[keyInit] ||
511
+ (isShorthand ||
512
+ isValidStyleKeyInit ||
513
+ isMediaOrPseudo ||
514
+ parentStaticConfig?.variants?.[keyInit] ||
498
515
  keyInit in skipProps)
499
516
  )
500
517
 
@@ -508,7 +525,7 @@ export const getSplitStyles: StyleSplitter = (
508
525
  )
509
526
  // prettier-ignore
510
527
  // rome-ignore lint/nursery/noConsoleLog: <explanation>
511
- console.log({ valInit, variants, variant: variants?.[keyInit], isVariant, shouldPassProp, isHOCShouldPassThrough, curProps: { ...styleState.curProps } })
528
+ console.log({ valInit, variants, variant: variants?.[keyInit], isVariant, shouldPassProp, isHOCShouldPassThrough, curProps: { ...styleState.curProps }, parentStaticConfig })
512
529
  console.groupEnd()
513
530
  }
514
531
 
@@ -546,18 +563,25 @@ export const getSplitStyles: StyleSplitter = (
546
563
  if (keyInit in skipProps) continue
547
564
 
548
565
  // we sort of have to update fontFamily all the time: before variants run, after each variant
549
- if (
550
- valInit &&
551
- (keyInit === fontFamilyKey || keyInit === shorthands[fontFamilyKey]) &&
552
- valInit in conf.fontsParsed
553
- ) {
554
- styleState.fontFamily = valInit
566
+ if (isText) {
567
+ if (
568
+ valInit &&
569
+ (keyInit === fontFamilyKey || keyInit === shorthands[fontFamilyKey]) &&
570
+ valInit in conf.fontsParsed
571
+ ) {
572
+ styleState.fontFamily = valInit
573
+ }
555
574
  }
556
575
 
557
- const expanded =
558
- isMediaOrPseudo || (!(keyInit in validStyleProps) && !isVariant)
559
- ? [[keyInit, valInit]]
560
- : propMapper(keyInit, valInit, styleState)
576
+ const avoidPropMap =
577
+ isMediaOrPseudo ||
578
+ // micro-bench optimize - if theres no variants at all, no need to do expansions
579
+ (isValidStyleKeyInit && !variants) ||
580
+ (!isVariant && !isValidStyleKeyInit)
581
+
582
+ const expanded = avoidPropMap
583
+ ? [[keyInit, valInit]]
584
+ : propMapper(keyInit, valInit, styleState)
561
585
 
562
586
  const next = getPropMappedFontFamily(expanded)
563
587
  if (next) {
@@ -569,7 +593,7 @@ export const getSplitStyles: StyleSplitter = (
569
593
  if (!isServer && isDevTools) {
570
594
  // prettier-ignore
571
595
  // rome-ignore lint/nursery/noConsoleLog: <explanation>
572
- console.log({ expanded, state: { ...state }, isVariant, variant: variants?.[keyInit], shouldPassProp, isHOCShouldPassThrough, theme, usedKeys: { ...usedKeys }, curProps: { ...styleState.curProps } })
596
+ console.log({ expanded, styleProps, componentState, isVariant, variant: variants?.[keyInit], shouldPassProp, isHOCShouldPassThrough, theme, usedKeys: { ...usedKeys }, curProps: { ...styleState.curProps } })
573
597
  // rome-ignore lint/nursery/noConsoleLog: ok
574
598
  console.log('expanded', expanded, '\nusedKeys', { ...usedKeys }, '\ncurrent', {
575
599
  ...style,
@@ -584,27 +608,21 @@ export const getSplitStyles: StyleSplitter = (
584
608
  if (val == null) continue
585
609
  if (key in usedKeys) continue
586
610
 
587
- if (key === fontFamilyKey && valInit && val) {
588
- const fam = valInit[0] === '$' ? valInit : val
589
- if (fam in conf.fontsParsed) {
590
- styleState.fontFamily = fam
591
- }
592
- }
593
-
594
- isMedia = isMediaKey(key)
595
611
  isPseudo = key in validPseudoKeys
612
+ isMedia = !isPseudo && !isValidStyleKeyInit && isMediaKey(key)
596
613
  isMediaOrPseudo = isMedia || isPseudo
614
+ isVariant = variants && key in variants
597
615
 
598
616
  if (inlineProps?.has(key) || (IS_STATIC && inlineWhenUnflattened?.has(key))) {
599
617
  viewProps[key] = props[key] ?? val
600
618
  }
601
619
 
602
- // have to run this logic again here
620
+ // have to run this logic again here because expansions may need to be passed down
621
+ // see StyledButtonVariantPseudoMerge test
603
622
  const isHOCShouldPassThrough =
604
- isHOC && (isMediaOrPseudo || staticConfig.parentStaticConfig?.variants?.[keyInit])
623
+ isHOC && (isMediaOrPseudo || parentStaticConfig?.variants?.[keyInit])
605
624
 
606
625
  if (isHOCShouldPassThrough) {
607
- isVariant = variants && key in variants
608
626
  passDownProp(viewProps, key, val, isMediaOrPseudo)
609
627
  if (process.env.NODE_ENV === 'development' && debug === 'verbose') {
610
628
  console.groupCollapsed(` - passing down prop ${key}`)
@@ -612,10 +630,7 @@ export const getSplitStyles: StyleSplitter = (
612
630
  console.log({ val, after: { ...viewProps[key] } })
613
631
  console.groupEnd()
614
632
  }
615
- // if its also a variant here, pass down but also keep it
616
- if (!isVariant) {
617
- continue
618
- }
633
+ continue
619
634
  }
620
635
 
621
636
  // pseudo
@@ -627,8 +642,7 @@ export const getSplitStyles: StyleSplitter = (
627
642
  styleState,
628
643
  key,
629
644
  val,
630
- true,
631
- state.noClassNames
645
+ styleProps.noClassNames
632
646
  )
633
647
 
634
648
  const descriptor = pseudoDescriptors[key as keyof typeof pseudoDescriptors]
@@ -638,8 +652,8 @@ export const getSplitStyles: StyleSplitter = (
638
652
  // dev-time warning that helps clear confusion around need for animation when using enter/exit style
639
653
  if (
640
654
  process.env.NODE_ENV === 'development' &&
641
- !state.isAnimated &&
642
- !state.unmounted &&
655
+ !styleProps.isAnimated &&
656
+ !componentState.unmounted &&
643
657
  (isEnter || isExit)
644
658
  ) {
645
659
  console.warn(
@@ -650,13 +664,7 @@ export const getSplitStyles: StyleSplitter = (
650
664
  }
651
665
 
652
666
  // don't continue here on isEnter && !state.unmounted because we need to merge defaults
653
- if (!descriptor || (isExit && !state.isExiting)) {
654
- if (process.env.NODE_ENV === 'development' && debug === 'verbose') {
655
- // prettier-ignore
656
- // rome-ignore lint/nursery/noConsoleLog: <explanation>
657
- console.log('skip exit')
658
- }
659
-
667
+ if (!descriptor || (isExit && !styleProps.isExiting)) {
660
668
  continue
661
669
  }
662
670
 
@@ -701,8 +709,8 @@ export const getSplitStyles: StyleSplitter = (
701
709
  // see the if (isDisabled) block below which loops through animatableDefaults
702
710
 
703
711
  const descriptorKey = descriptor.stateKey || descriptor.name
704
- const pseudoState = state[descriptorKey]
705
- let isDisabled = !pseudoState
712
+ const pseudoState = componentState[descriptorKey]
713
+ let isDisabled = isExit ? !styleProps.isExiting : !pseudoState
706
714
 
707
715
  // we never animate in on server side just show the full thing
708
716
  // on client side we use CSS to hide the fully in SSR items, then
@@ -713,23 +721,15 @@ export const getSplitStyles: StyleSplitter = (
713
721
 
714
722
  if (process.env.NODE_ENV === 'development' && debug === 'verbose') {
715
723
  // prettier-ignore
716
- console.groupCollapsed('pseudo', key, !isDisabled)
724
+ console.groupCollapsed('pseudo', key, { isDisabled })
717
725
  // prettier-ignore
718
726
  // rome-ignore lint/nursery/noConsoleLog: <explanation>
719
- console.log(pseudoStyleObject, { isDisabled, descriptorKey, descriptor, pseudoState, state: { ...state } })
727
+ console.log(pseudoStyleObject, { isDisabled, descriptorKey, descriptor, pseudoState, state: { ...componentState } })
720
728
  console.groupEnd()
721
729
  }
722
730
 
723
731
  const importance = descriptor.priority
724
732
 
725
- if (!isDisabled) {
726
- // mark usedKeys based not on pseudoStyleObject
727
- for (const key in val) {
728
- const k = shorthands[key] || key
729
- usedKeys[k] = Math.max(importance, usedKeys[k] || 0)
730
- }
731
- }
732
-
733
733
  for (const pkey in pseudoStyleObject) {
734
734
  const val = pseudoStyleObject[pkey]
735
735
  // when disabled ensure the default value is set for future animations to align
@@ -737,7 +737,7 @@ export const getSplitStyles: StyleSplitter = (
737
737
  if (isDisabled) {
738
738
  if (pkey in animatableDefaults && !(pkey in usedKeys)) {
739
739
  const defaultVal = animatableDefaults[pkey]
740
- mergeStyle(styleState, flatTransforms, pkey, defaultVal)
740
+ mergeStyle(styleState, pkey, defaultVal)
741
741
  }
742
742
  } else {
743
743
  const curImportance = usedKeys[importance] || 0
@@ -747,7 +747,7 @@ export const getSplitStyles: StyleSplitter = (
747
747
  pseudos ||= {}
748
748
  pseudos[key] ||= {}
749
749
  pseudos[key][pkey] = val
750
- mergeStyle(styleState, flatTransforms, pkey, val)
750
+ mergeStyle(styleState, pkey, val)
751
751
  usedKeys[pkey] ||= 1
752
752
  }
753
753
  if (process.env.NODE_ENV === 'development' && debug === 'verbose') {
@@ -757,13 +757,21 @@ export const getSplitStyles: StyleSplitter = (
757
757
  }
758
758
  }
759
759
  }
760
+
761
+ // set this after the loop over pseudoStyleObject so it applies before setting usedKeys
762
+ if (!isDisabled) {
763
+ // mark usedKeys based on pseudoStyleObject
764
+ for (const key in val) {
765
+ const k = shorthands[key] || key
766
+ usedKeys[k] = Math.max(importance, usedKeys[k] || 0)
767
+ }
768
+ }
760
769
  }
761
770
 
762
771
  continue
763
772
  }
764
-
765
773
  // media
766
- if (isMedia) {
774
+ else if (isMedia) {
767
775
  if (!val) continue
768
776
 
769
777
  const isPlatformMedia = key.startsWith('$platform-')
@@ -795,7 +803,9 @@ export const getSplitStyles: StyleSplitter = (
795
803
  console.log(` 📺 ${key}`, { key, mediaStyle, props, shouldDoClasses })
796
804
  }
797
805
 
798
- const hasSpace = 'space' in val
806
+ // for some reason 'space' in val upsetting next ssr during prod build
807
+ // technically i guess this also will not apply if 0 space which makes sense?
808
+ const hasSpace = val['space']
799
809
  if (hasSpace || !shouldDoClasses) {
800
810
  if (!Array.isArray(hasMedia)) {
801
811
  hasMedia = []
@@ -902,7 +912,7 @@ export const getSplitStyles: StyleSplitter = (
902
912
  key in validStyleProps ||
903
913
  (process.env.TAMAGUI_TARGET === 'native' && isAndroid && key === 'elevation')
904
914
  ) {
905
- mergeStyle(styleState, flatTransforms, key, val)
915
+ mergeStyle(styleState, key, val)
906
916
  continue
907
917
  }
908
918
 
@@ -927,10 +937,24 @@ export const getSplitStyles: StyleSplitter = (
927
937
  styleToCSS(style)
928
938
  }
929
939
 
940
+ // these are only the flat transforms
930
941
  // always do this at the very end to preserve the order strictly (animations, origin)
931
942
  // and allow proper merging of all pseudos before applying
932
- if (flatTransforms) {
933
- mergeFlatTransforms(style, flatTransforms, true)
943
+ if (styleState.transforms) {
944
+ // we need to match the order for animations to work because it needs consistent order
945
+ // was thinking of having something like `state.prevTransformsOrder = ['y', 'x', ...]
946
+ // but if we just handle it here its not a big cost and avoids having stateful things
947
+ // so the strategy is: always sort by a consistent order, until you run into a "duplicate"
948
+ // because you can have something like:
949
+ // [{ translateX: 0 }, { scale: 1 }, { translateX: 10 }]
950
+ // so basically we sort until we get to a duplicate... we could sort even smarter but
951
+ // this should work for most (all?) of our cases since the order preservation really only needs to apply
952
+ // to the "flat" transform props
953
+ Object.entries(styleState.transforms)
954
+ .sort(([a], [b]) => a.localeCompare(b))
955
+ .forEach(([key, val]) => {
956
+ mergeTransform(style, key, val, true)
957
+ })
934
958
  }
935
959
 
936
960
  // add in defaults if not set:
@@ -962,14 +986,17 @@ export const getSplitStyles: StyleSplitter = (
962
986
 
963
987
  for (const atomicStyle of atomic) {
964
988
  const key = atomicStyle.property
965
- if (state.isAnimated && props.animateOnly && props.animateOnly.includes(key)) {
989
+ if (
990
+ styleProps.isAnimated &&
991
+ (!props.animateOnly || props.animateOnly.includes(key))
992
+ ) {
966
993
  retainedStyles[key] = style[key]
967
994
  } else {
968
995
  addStyleToInsertRules(rulesToInsert, atomicStyle)
969
996
  mergeClassName(transforms, classNames, key, atomicStyle.identifier)
970
997
  }
971
998
  }
972
- if (!IS_STATIC && !state.keepStyleSSR) {
999
+ if (!IS_STATIC && !styleProps.keepStyleSSR) {
973
1000
  style = retainedStyles
974
1001
  }
975
1002
  }
@@ -1081,7 +1108,7 @@ export const getSplitStyles: StyleSplitter = (
1081
1108
  if (isDevTools) {
1082
1109
  console.groupCollapsed(' 🔹 ===>')
1083
1110
  // prettier-ignore
1084
- const logs = { ...result, state, transforms, viewProps, viewPropsOrder: Object.keys(viewProps), rulesToInsert, parentSplitStyles, flatTransforms }
1111
+ const logs = { ...result, componentState, transforms, viewProps, viewPropsOrder: Object.keys(viewProps), rulesToInsert, parentSplitStyles }
1085
1112
  for (const key in logs) {
1086
1113
  // rome-ignore lint/nursery/noConsoleLog: ok
1087
1114
  console.log(key, logs[key])
@@ -1125,46 +1152,16 @@ function mergeClassName(
1125
1152
  }
1126
1153
  }
1127
1154
 
1128
- /**
1129
- * getSubStyle calls propMapper with props
1130
- * those should be specific to the substyle, but fallback to the base props
1131
- * so given props:
1132
- *
1133
- * { fontSize: 12, color: 'red', $sm: { color: 'blue' } }
1134
- *
1135
- * getSubStyle props should be a proxy that ends up like:
1136
- *
1137
- * { fontSize: 12, color: 'blue' }
1138
- *
1139
- * and to avoid re-creating it over and over, use a WeakMap
1140
- */
1141
-
1142
- function getSubStyleProps(
1143
- defaultProps: Object,
1144
- baseProps: Object,
1145
- specificProps: Object
1146
- ) {
1147
- return {
1148
- ...defaultProps,
1149
- ...baseProps,
1150
- ...specificProps,
1151
- }
1152
- }
1153
-
1154
- function mergeStyle(
1155
- { classNames, viewProps, style, usedKeys }: GetStyleState,
1156
- flatTransforms: FlatTransforms,
1157
- key: string,
1158
- val: any
1159
- ) {
1160
- if (val?.[0] === '_') {
1155
+ function mergeStyle(styleState: GetStyleState, key: string, val: any) {
1156
+ const { classNames, viewProps, style, usedKeys } = styleState
1157
+ if (isWeb && val?.[0] === '_') {
1161
1158
  classNames[key] = val
1162
1159
  usedKeys[key] ||= 1
1163
1160
  } else if (key in stylePropsTransform) {
1164
- flatTransforms ||= {}
1165
- flatTransforms[key] = val
1161
+ styleState.transforms ||= {}
1162
+ styleState.transforms[key] = val
1166
1163
  } else {
1167
- const out = normalizeValueWithProperty(val, key)
1164
+ const out = isWeb ? normalizeValueWithProperty(val, key) : val
1168
1165
  if (key in validStylesOnBaseProps) {
1169
1166
  viewProps[key] = out
1170
1167
  } else {
@@ -1177,7 +1174,6 @@ export const getSubStyle = (
1177
1174
  styleState: GetStyleState,
1178
1175
  subKey: string,
1179
1176
  styleIn: Object,
1180
- avoidDefaultProps?: boolean,
1181
1177
  avoidMergeTransform?: boolean
1182
1178
  ): TextStyleProps => {
1183
1179
  const { staticConfig, props, conf } = styleState
@@ -1186,13 +1182,7 @@ export const getSubStyle = (
1186
1182
  for (let key in styleIn) {
1187
1183
  const val = styleIn[key]
1188
1184
  key = conf.shorthands[key] || key
1189
- const expanded = staticConfig.propMapper(
1190
- key,
1191
- val,
1192
- styleState,
1193
- getSubStyleProps(staticConfig.defaultProps, props, props[subKey]),
1194
- avoidDefaultProps
1195
- )
1185
+ const expanded = propMapper(key, val, styleState, { ...props, ...props[subKey] })
1196
1186
  if (!expanded || (!staticConfig.isHOC && key in skipProps)) {
1197
1187
  continue
1198
1188
  }
@@ -1252,8 +1242,6 @@ const animatableDefaults = {
1252
1242
  const lowercaseHyphenate = (match: string) => `-${match.toLowerCase()}`
1253
1243
  const hyphenate = (str: string) => str.replace(/[A-Z]/g, lowercaseHyphenate)
1254
1244
 
1255
- export type FlatTransforms = Record<string, any>
1256
-
1257
1245
  const mergeTransform = (
1258
1246
  obj: TextStyleProps,
1259
1247
  key: string,
@@ -1269,27 +1257,6 @@ const mergeTransform = (
1269
1257
  } as any)
1270
1258
  }
1271
1259
 
1272
- // we need to match the order for animations to work because it needs consistent order
1273
- // was thinking of having something like `state.prevTransformsOrder = ['y', 'x', ...]
1274
- // but if we just handle it here its not a big cost and avoids having stateful things
1275
- // so the strategy is: always sort by a consistent order, until you run into a "duplicate"
1276
- // because you can have something like:
1277
- // [{ translateX: 0 }, { scale: 1 }, { translateX: 10 }]
1278
- // so basically we sort until we get to a duplicate... we could sort even smarter but
1279
- // this should work for most (all?) of our cases since the order preservation really only needs to apply
1280
- // to the "flat" transform props
1281
- const mergeFlatTransforms = (
1282
- obj: TextStyleProps,
1283
- flatTransforms: FlatTransforms,
1284
- backwards = false
1285
- ) => {
1286
- Object.entries(flatTransforms)
1287
- .sort(([a], [b]) => a.localeCompare(b))
1288
- .forEach(([key, val]) => {
1289
- mergeTransform(obj, key, val, backwards)
1290
- })
1291
- }
1292
-
1293
1260
  const mapTransformKeys = {
1294
1261
  x: 'translateX',
1295
1262
  y: 'translateY',
@@ -107,10 +107,10 @@ export function styleToCSS(style: Record<string, any>) {
107
107
  const radius = normalizeValueWithProperty(shadowRadius)
108
108
  const shadow = `${width} ${height} ${radius} ${shadowColor}`
109
109
  style.boxShadow = style.boxShadow ? `${style.boxShadow}, ${shadow}` : shadow
110
- style.shadowOffset = undefined
111
- style.shadowRadius = undefined
112
- style.shadowColor = undefined
113
- style.shadowOpacity = undefined
110
+ delete style.shadowOffset
111
+ delete style.shadowRadius
112
+ delete style.shadowColor
113
+ delete style.shadowOpacity
114
114
  }
115
115
 
116
116
  // text-shadow
@@ -125,9 +125,9 @@ export function styleToCSS(style: Record<string, any>) {
125
125
  const offsetY = normalizeValueWithProperty(height)
126
126
  style.textShadow = `${offsetX} ${offsetY} ${blurRadius} ${color}`
127
127
  }
128
- style.textShadowColor = undefined
129
- style.textShadowOffset = undefined
130
- style.textShadowRadius = undefined
128
+ delete style.textShadowColor
129
+ delete style.textShadowOffset
130
+ delete style.textShadowRadius
131
131
  }
132
132
  }
133
133