@tamagui/web 1.46.2 → 1.47.1

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 +82 -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 +78 -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} +64 -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 +82 -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 +77 -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} +57 -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 +142 -140
  92. package/src/createTamagui.ts +0 -1
  93. package/src/helpers/ThemeManager.tsx +10 -6
  94. package/src/helpers/getSplitStyles.tsx +144 -173
  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} +72 -164
  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
 
@@ -506,9 +523,13 @@ export const getSplitStyles: StyleSplitter = (
506
523
  shouldPassThrough ? '(pass)' : ''
507
524
  } 🔹🔹🔹🔹`
508
525
  )
509
- // prettier-ignore
510
526
  // rome-ignore lint/nursery/noConsoleLog: <explanation>
511
- console.log({ valInit, variants, variant: variants?.[keyInit], isVariant, shouldPassProp, isHOCShouldPassThrough, curProps: { ...styleState.curProps } })
527
+ console.log({ isVariant, valInit, shouldPassProp })
528
+ if (isClient) {
529
+ // prettier-ignore
530
+ // rome-ignore lint/nursery/noConsoleLog: <explanation>
531
+ console.log({ variants, variant: variants?.[keyInit], isVariant, isHOCShouldPassThrough, curProps: { ...styleState.curProps }, parentStaticConfig })
532
+ }
512
533
  console.groupEnd()
513
534
  }
514
535
 
@@ -546,18 +567,25 @@ export const getSplitStyles: StyleSplitter = (
546
567
  if (keyInit in skipProps) continue
547
568
 
548
569
  // 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
570
+ if (isText) {
571
+ if (
572
+ valInit &&
573
+ (keyInit === fontFamilyKey || keyInit === shorthands[fontFamilyKey]) &&
574
+ valInit in conf.fontsParsed
575
+ ) {
576
+ styleState.fontFamily = valInit
577
+ }
555
578
  }
556
579
 
557
- const expanded =
558
- isMediaOrPseudo || (!(keyInit in validStyleProps) && !isVariant)
559
- ? [[keyInit, valInit]]
560
- : propMapper(keyInit, valInit, styleState)
580
+ const avoidPropMap =
581
+ isMediaOrPseudo ||
582
+ // micro-bench optimize - if theres no variants at all, no need to do expansions
583
+ (isValidStyleKeyInit && !variants) ||
584
+ (!isVariant && !isValidStyleKeyInit)
585
+
586
+ const expanded = avoidPropMap
587
+ ? [[keyInit, valInit]]
588
+ : propMapper(keyInit, valInit, styleState)
561
589
 
562
590
  const next = getPropMappedFontFamily(expanded)
563
591
  if (next) {
@@ -569,7 +597,7 @@ export const getSplitStyles: StyleSplitter = (
569
597
  if (!isServer && isDevTools) {
570
598
  // prettier-ignore
571
599
  // rome-ignore lint/nursery/noConsoleLog: <explanation>
572
- console.log({ expanded, state: { ...state }, isVariant, variant: variants?.[keyInit], shouldPassProp, isHOCShouldPassThrough, theme, usedKeys: { ...usedKeys }, curProps: { ...styleState.curProps } })
600
+ console.log({ expanded, styleProps, componentState, isVariant, variant: variants?.[keyInit], shouldPassProp, isHOCShouldPassThrough, theme, usedKeys: { ...usedKeys }, curProps: { ...styleState.curProps } })
573
601
  // rome-ignore lint/nursery/noConsoleLog: ok
574
602
  console.log('expanded', expanded, '\nusedKeys', { ...usedKeys }, '\ncurrent', {
575
603
  ...style,
@@ -584,27 +612,21 @@ export const getSplitStyles: StyleSplitter = (
584
612
  if (val == null) continue
585
613
  if (key in usedKeys) continue
586
614
 
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
615
  isPseudo = key in validPseudoKeys
616
+ isMedia = !isPseudo && !isValidStyleKeyInit && isMediaKey(key)
596
617
  isMediaOrPseudo = isMedia || isPseudo
618
+ isVariant = variants && key in variants
597
619
 
598
620
  if (inlineProps?.has(key) || (IS_STATIC && inlineWhenUnflattened?.has(key))) {
599
621
  viewProps[key] = props[key] ?? val
600
622
  }
601
623
 
602
- // have to run this logic again here
624
+ // have to run this logic again here because expansions may need to be passed down
625
+ // see StyledButtonVariantPseudoMerge test
603
626
  const isHOCShouldPassThrough =
604
- isHOC && (isMediaOrPseudo || staticConfig.parentStaticConfig?.variants?.[keyInit])
627
+ isHOC && (isMediaOrPseudo || parentStaticConfig?.variants?.[keyInit])
605
628
 
606
629
  if (isHOCShouldPassThrough) {
607
- isVariant = variants && key in variants
608
630
  passDownProp(viewProps, key, val, isMediaOrPseudo)
609
631
  if (process.env.NODE_ENV === 'development' && debug === 'verbose') {
610
632
  console.groupCollapsed(` - passing down prop ${key}`)
@@ -612,10 +634,7 @@ export const getSplitStyles: StyleSplitter = (
612
634
  console.log({ val, after: { ...viewProps[key] } })
613
635
  console.groupEnd()
614
636
  }
615
- // if its also a variant here, pass down but also keep it
616
- if (!isVariant) {
617
- continue
618
- }
637
+ continue
619
638
  }
620
639
 
621
640
  // pseudo
@@ -627,8 +646,7 @@ export const getSplitStyles: StyleSplitter = (
627
646
  styleState,
628
647
  key,
629
648
  val,
630
- true,
631
- state.noClassNames
649
+ styleProps.noClassNames
632
650
  )
633
651
 
634
652
  const descriptor = pseudoDescriptors[key as keyof typeof pseudoDescriptors]
@@ -638,8 +656,8 @@ export const getSplitStyles: StyleSplitter = (
638
656
  // dev-time warning that helps clear confusion around need for animation when using enter/exit style
639
657
  if (
640
658
  process.env.NODE_ENV === 'development' &&
641
- !state.isAnimated &&
642
- !state.unmounted &&
659
+ !styleProps.isAnimated &&
660
+ !componentState.unmounted &&
643
661
  (isEnter || isExit)
644
662
  ) {
645
663
  console.warn(
@@ -650,13 +668,7 @@ export const getSplitStyles: StyleSplitter = (
650
668
  }
651
669
 
652
670
  // 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
-
671
+ if (!descriptor || (isExit && !styleProps.isExiting)) {
660
672
  continue
661
673
  }
662
674
 
@@ -701,8 +713,8 @@ export const getSplitStyles: StyleSplitter = (
701
713
  // see the if (isDisabled) block below which loops through animatableDefaults
702
714
 
703
715
  const descriptorKey = descriptor.stateKey || descriptor.name
704
- const pseudoState = state[descriptorKey]
705
- let isDisabled = !pseudoState
716
+ const pseudoState = componentState[descriptorKey]
717
+ let isDisabled = isExit ? !styleProps.isExiting : !pseudoState
706
718
 
707
719
  // we never animate in on server side just show the full thing
708
720
  // on client side we use CSS to hide the fully in SSR items, then
@@ -713,23 +725,15 @@ export const getSplitStyles: StyleSplitter = (
713
725
 
714
726
  if (process.env.NODE_ENV === 'development' && debug === 'verbose') {
715
727
  // prettier-ignore
716
- console.groupCollapsed('pseudo', key, !isDisabled)
728
+ console.groupCollapsed('pseudo', key, { isDisabled })
717
729
  // prettier-ignore
718
730
  // rome-ignore lint/nursery/noConsoleLog: <explanation>
719
- console.log(pseudoStyleObject, { isDisabled, descriptorKey, descriptor, pseudoState, state: { ...state } })
731
+ console.log(pseudoStyleObject, { isDisabled, descriptorKey, descriptor, pseudoState, state: { ...componentState } })
720
732
  console.groupEnd()
721
733
  }
722
734
 
723
735
  const importance = descriptor.priority
724
736
 
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
737
  for (const pkey in pseudoStyleObject) {
734
738
  const val = pseudoStyleObject[pkey]
735
739
  // when disabled ensure the default value is set for future animations to align
@@ -737,7 +741,7 @@ export const getSplitStyles: StyleSplitter = (
737
741
  if (isDisabled) {
738
742
  if (pkey in animatableDefaults && !(pkey in usedKeys)) {
739
743
  const defaultVal = animatableDefaults[pkey]
740
- mergeStyle(styleState, flatTransforms, pkey, defaultVal)
744
+ mergeStyle(styleState, pkey, defaultVal)
741
745
  }
742
746
  } else {
743
747
  const curImportance = usedKeys[importance] || 0
@@ -747,7 +751,7 @@ export const getSplitStyles: StyleSplitter = (
747
751
  pseudos ||= {}
748
752
  pseudos[key] ||= {}
749
753
  pseudos[key][pkey] = val
750
- mergeStyle(styleState, flatTransforms, pkey, val)
754
+ mergeStyle(styleState, pkey, val)
751
755
  usedKeys[pkey] ||= 1
752
756
  }
753
757
  if (process.env.NODE_ENV === 'development' && debug === 'verbose') {
@@ -757,13 +761,21 @@ export const getSplitStyles: StyleSplitter = (
757
761
  }
758
762
  }
759
763
  }
764
+
765
+ // set this after the loop over pseudoStyleObject so it applies before setting usedKeys
766
+ if (!isDisabled) {
767
+ // mark usedKeys based on pseudoStyleObject
768
+ for (const key in val) {
769
+ const k = shorthands[key] || key
770
+ usedKeys[k] = Math.max(importance, usedKeys[k] || 0)
771
+ }
772
+ }
760
773
  }
761
774
 
762
775
  continue
763
776
  }
764
-
765
777
  // media
766
- if (isMedia) {
778
+ else if (isMedia) {
767
779
  if (!val) continue
768
780
 
769
781
  const isPlatformMedia = key.startsWith('$platform-')
@@ -795,7 +807,9 @@ export const getSplitStyles: StyleSplitter = (
795
807
  console.log(` 📺 ${key}`, { key, mediaStyle, props, shouldDoClasses })
796
808
  }
797
809
 
798
- const hasSpace = 'space' in val
810
+ // for some reason 'space' in val upsetting next ssr during prod build
811
+ // technically i guess this also will not apply if 0 space which makes sense?
812
+ const hasSpace = val['space']
799
813
  if (hasSpace || !shouldDoClasses) {
800
814
  if (!Array.isArray(hasMedia)) {
801
815
  hasMedia = []
@@ -902,7 +916,7 @@ export const getSplitStyles: StyleSplitter = (
902
916
  key in validStyleProps ||
903
917
  (process.env.TAMAGUI_TARGET === 'native' && isAndroid && key === 'elevation')
904
918
  ) {
905
- mergeStyle(styleState, flatTransforms, key, val)
919
+ mergeStyle(styleState, key, val)
906
920
  continue
907
921
  }
908
922
 
@@ -927,10 +941,24 @@ export const getSplitStyles: StyleSplitter = (
927
941
  styleToCSS(style)
928
942
  }
929
943
 
944
+ // these are only the flat transforms
930
945
  // always do this at the very end to preserve the order strictly (animations, origin)
931
946
  // and allow proper merging of all pseudos before applying
932
- if (flatTransforms) {
933
- mergeFlatTransforms(style, flatTransforms, true)
947
+ if (styleState.transforms) {
948
+ // we need to match the order for animations to work because it needs consistent order
949
+ // was thinking of having something like `state.prevTransformsOrder = ['y', 'x', ...]
950
+ // but if we just handle it here its not a big cost and avoids having stateful things
951
+ // so the strategy is: always sort by a consistent order, until you run into a "duplicate"
952
+ // because you can have something like:
953
+ // [{ translateX: 0 }, { scale: 1 }, { translateX: 10 }]
954
+ // so basically we sort until we get to a duplicate... we could sort even smarter but
955
+ // this should work for most (all?) of our cases since the order preservation really only needs to apply
956
+ // to the "flat" transform props
957
+ Object.entries(styleState.transforms)
958
+ .sort(([a], [b]) => a.localeCompare(b))
959
+ .forEach(([key, val]) => {
960
+ mergeTransform(style, key, val, true)
961
+ })
934
962
  }
935
963
 
936
964
  // add in defaults if not set:
@@ -962,14 +990,17 @@ export const getSplitStyles: StyleSplitter = (
962
990
 
963
991
  for (const atomicStyle of atomic) {
964
992
  const key = atomicStyle.property
965
- if (state.isAnimated && props.animateOnly && props.animateOnly.includes(key)) {
993
+ if (
994
+ styleProps.isAnimated &&
995
+ (!props.animateOnly || props.animateOnly.includes(key))
996
+ ) {
966
997
  retainedStyles[key] = style[key]
967
998
  } else {
968
999
  addStyleToInsertRules(rulesToInsert, atomicStyle)
969
1000
  mergeClassName(transforms, classNames, key, atomicStyle.identifier)
970
1001
  }
971
1002
  }
972
- if (!IS_STATIC && !state.keepStyleSSR) {
1003
+ if (!IS_STATIC && !styleProps.keepStyleSSR) {
973
1004
  style = retainedStyles
974
1005
  }
975
1006
  }
@@ -1081,7 +1112,7 @@ export const getSplitStyles: StyleSplitter = (
1081
1112
  if (isDevTools) {
1082
1113
  console.groupCollapsed(' 🔹 ===>')
1083
1114
  // prettier-ignore
1084
- const logs = { ...result, state, transforms, viewProps, viewPropsOrder: Object.keys(viewProps), rulesToInsert, parentSplitStyles, flatTransforms }
1115
+ const logs = { ...result, componentState, transforms, viewProps, viewPropsOrder: Object.keys(viewProps), rulesToInsert, parentSplitStyles }
1085
1116
  for (const key in logs) {
1086
1117
  // rome-ignore lint/nursery/noConsoleLog: ok
1087
1118
  console.log(key, logs[key])
@@ -1125,46 +1156,16 @@ function mergeClassName(
1125
1156
  }
1126
1157
  }
1127
1158
 
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] === '_') {
1159
+ function mergeStyle(styleState: GetStyleState, key: string, val: any) {
1160
+ const { classNames, viewProps, style, usedKeys } = styleState
1161
+ if (isWeb && val?.[0] === '_') {
1161
1162
  classNames[key] = val
1162
1163
  usedKeys[key] ||= 1
1163
1164
  } else if (key in stylePropsTransform) {
1164
- flatTransforms ||= {}
1165
- flatTransforms[key] = val
1165
+ styleState.transforms ||= {}
1166
+ styleState.transforms[key] = val
1166
1167
  } else {
1167
- const out = normalizeValueWithProperty(val, key)
1168
+ const out = isWeb ? normalizeValueWithProperty(val, key) : val
1168
1169
  if (key in validStylesOnBaseProps) {
1169
1170
  viewProps[key] = out
1170
1171
  } else {
@@ -1177,7 +1178,6 @@ export const getSubStyle = (
1177
1178
  styleState: GetStyleState,
1178
1179
  subKey: string,
1179
1180
  styleIn: Object,
1180
- avoidDefaultProps?: boolean,
1181
1181
  avoidMergeTransform?: boolean
1182
1182
  ): TextStyleProps => {
1183
1183
  const { staticConfig, props, conf } = styleState
@@ -1186,13 +1186,7 @@ export const getSubStyle = (
1186
1186
  for (let key in styleIn) {
1187
1187
  const val = styleIn[key]
1188
1188
  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
- )
1189
+ const expanded = propMapper(key, val, styleState, { ...props, ...props[subKey] })
1196
1190
  if (!expanded || (!staticConfig.isHOC && key in skipProps)) {
1197
1191
  continue
1198
1192
  }
@@ -1252,8 +1246,6 @@ const animatableDefaults = {
1252
1246
  const lowercaseHyphenate = (match: string) => `-${match.toLowerCase()}`
1253
1247
  const hyphenate = (str: string) => str.replace(/[A-Z]/g, lowercaseHyphenate)
1254
1248
 
1255
- export type FlatTransforms = Record<string, any>
1256
-
1257
1249
  const mergeTransform = (
1258
1250
  obj: TextStyleProps,
1259
1251
  key: string,
@@ -1269,27 +1261,6 @@ const mergeTransform = (
1269
1261
  } as any)
1270
1262
  }
1271
1263
 
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
1264
  const mapTransformKeys = {
1294
1265
  x: 'translateX',
1295
1266
  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