@tamagui/web 3.0.0-beta.807.1 → 3.0.0-beta.831.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 (266) hide show
  1. package/dist/cjs/config.cjs +1 -1
  2. package/dist/cjs/config.native.cjs +1 -1
  3. package/dist/cjs/config.native.js +1 -1
  4. package/dist/cjs/config.native.js.map +1 -1
  5. package/dist/cjs/createComponent.cjs +28 -18
  6. package/dist/cjs/createComponent.native.cjs +30 -20
  7. package/dist/cjs/createComponent.native.js +30 -20
  8. package/dist/cjs/createComponent.native.js.map +1 -1
  9. package/dist/cjs/createStyledHOC.cjs +54 -4
  10. package/dist/cjs/createStyledHOC.native.cjs +55 -4
  11. package/dist/cjs/createStyledHOC.native.js +55 -4
  12. package/dist/cjs/createStyledHOC.native.js.map +1 -1
  13. package/dist/cjs/createTokens.cjs +1 -1
  14. package/dist/cjs/createTokens.native.cjs +1 -1
  15. package/dist/cjs/createTokens.native.js +1 -1
  16. package/dist/cjs/createTokens.native.js.map +1 -1
  17. package/dist/cjs/dom/html.cjs +147 -99
  18. package/dist/cjs/dom/htmlRuntime.native.cjs +6 -2
  19. package/dist/cjs/dom/htmlRuntime.native.js +6 -2
  20. package/dist/cjs/dom/htmlRuntime.native.js.map +1 -1
  21. package/dist/cjs/dom/primitives.native.cjs +16 -13
  22. package/dist/cjs/dom/primitives.native.js +16 -13
  23. package/dist/cjs/dom/primitives.native.js.map +1 -1
  24. package/dist/cjs/helpers/componentDisplayName.cjs +1 -11
  25. package/dist/cjs/helpers/componentDisplayName.native.cjs +1 -11
  26. package/dist/cjs/helpers/componentDisplayName.native.js +1 -11
  27. package/dist/cjs/helpers/componentDisplayName.native.js.map +1 -1
  28. package/dist/cjs/helpers/directStyleCSS.cjs +101 -104
  29. package/dist/cjs/helpers/formatDiagnostic.cjs +2 -4
  30. package/dist/cjs/helpers/formatDiagnostic.native.cjs +2 -4
  31. package/dist/cjs/helpers/formatDiagnostic.native.js +2 -4
  32. package/dist/cjs/helpers/formatDiagnostic.native.js.map +1 -1
  33. package/dist/cjs/helpers/getCSSStylesAtomic.cjs +10 -10
  34. package/dist/cjs/helpers/getSplitStyles.cjs +168 -600
  35. package/dist/cjs/helpers/getSplitStyles.native.cjs +168 -762
  36. package/dist/cjs/helpers/getSplitStyles.native.js +168 -762
  37. package/dist/cjs/helpers/getSplitStyles.native.js.map +1 -1
  38. package/dist/cjs/helpers/splitStyleProps.cjs +46 -0
  39. package/dist/cjs/helpers/splitStyleProps.native.cjs +49 -0
  40. package/dist/cjs/helpers/splitStyleProps.native.js +51 -0
  41. package/dist/cjs/helpers/splitStyleProps.native.js.map +1 -0
  42. package/dist/cjs/helpers/styleStaticConfig.cjs +76 -0
  43. package/dist/cjs/helpers/styleStaticConfig.native.cjs +79 -0
  44. package/dist/cjs/helpers/styleStaticConfig.native.js +81 -0
  45. package/dist/cjs/helpers/styleStaticConfig.native.js.map +1 -0
  46. package/dist/cjs/helpers/tokenCategories.cjs +32 -71
  47. package/dist/cjs/helpers/tokenCategories.native.cjs +34 -73
  48. package/dist/cjs/helpers/tokenCategories.native.js +34 -73
  49. package/dist/cjs/helpers/tokenCategories.native.js.map +1 -1
  50. package/dist/cjs/helpers/variantResolvers.cjs +87 -0
  51. package/dist/cjs/helpers/variantResolvers.native.cjs +140 -0
  52. package/dist/cjs/helpers/variantResolvers.native.js +142 -0
  53. package/dist/cjs/helpers/variantResolvers.native.js.map +1 -0
  54. package/dist/cjs/hooks/useSplitStyles.cjs +2 -2
  55. package/dist/cjs/hooks/useSplitStyles.native.cjs +2 -2
  56. package/dist/cjs/hooks/useSplitStyles.native.js +2 -2
  57. package/dist/cjs/hooks/useSplitStyles.native.js.map +1 -1
  58. package/dist/cjs/index.cjs +3 -9
  59. package/dist/cjs/index.native.cjs +3 -9
  60. package/dist/cjs/index.native.js +3 -9
  61. package/dist/cjs/index.native.js.map +1 -1
  62. package/dist/cjs/internal-runtime.cjs +8 -7
  63. package/dist/cjs/internal-runtime.native.cjs +8 -7
  64. package/dist/cjs/internal-runtime.native.js +8 -7
  65. package/dist/cjs/internal-runtime.native.js.map +1 -1
  66. package/dist/cjs/static-resolve.cjs +6 -5
  67. package/dist/cjs/static-resolve.native.cjs +6 -5
  68. package/dist/cjs/static-resolve.native.js +6 -5
  69. package/dist/cjs/static-resolve.native.js.map +1 -1
  70. package/dist/cjs/styled.cjs +4 -56
  71. package/dist/cjs/styled.native.cjs +4 -58
  72. package/dist/cjs/styled.native.js +4 -58
  73. package/dist/cjs/styled.native.js.map +1 -1
  74. package/dist/cjs/types.cjs +1 -21
  75. package/dist/cjs/types.native.cjs +1 -21
  76. package/dist/cjs/types.native.js +1 -21
  77. package/dist/cjs/types.native.js.map +1 -1
  78. package/dist/cjs/views/Text.cjs +4 -2
  79. package/dist/cjs/views/Text.native.cjs +4 -2
  80. package/dist/cjs/views/Text.native.js +4 -2
  81. package/dist/cjs/views/Text.native.js.map +1 -1
  82. package/dist/cjs/views/View.cjs +4 -2
  83. package/dist/cjs/views/View.native.cjs +4 -2
  84. package/dist/cjs/views/View.native.js +4 -2
  85. package/dist/cjs/views/View.native.js.map +1 -1
  86. package/dist/esm/config.mjs +1 -1
  87. package/dist/esm/config.mjs.map +1 -1
  88. package/dist/esm/config.native.js +1 -1
  89. package/dist/esm/config.native.js.map +1 -1
  90. package/dist/esm/createComponent.mjs +29 -19
  91. package/dist/esm/createComponent.mjs.map +1 -1
  92. package/dist/esm/createComponent.native.js +31 -21
  93. package/dist/esm/createComponent.native.js.map +1 -1
  94. package/dist/esm/createStyledHOC.mjs +55 -5
  95. package/dist/esm/createStyledHOC.mjs.map +1 -1
  96. package/dist/esm/createStyledHOC.native.js +56 -5
  97. package/dist/esm/createStyledHOC.native.js.map +1 -1
  98. package/dist/esm/createTokens.mjs +1 -1
  99. package/dist/esm/createTokens.mjs.map +1 -1
  100. package/dist/esm/createTokens.native.js +1 -1
  101. package/dist/esm/createTokens.native.js.map +1 -1
  102. package/dist/esm/dom/html.mjs +147 -99
  103. package/dist/esm/dom/html.mjs.map +1 -1
  104. package/dist/esm/dom/htmlRuntime.native.js +7 -3
  105. package/dist/esm/dom/htmlRuntime.native.js.map +1 -1
  106. package/dist/esm/dom/primitives.native.js +16 -13
  107. package/dist/esm/dom/primitives.native.js.map +1 -1
  108. package/dist/esm/helpers/componentDisplayName.mjs +1 -8
  109. package/dist/esm/helpers/componentDisplayName.mjs.map +1 -1
  110. package/dist/esm/helpers/componentDisplayName.native.js +1 -8
  111. package/dist/esm/helpers/componentDisplayName.native.js.map +1 -1
  112. package/dist/esm/helpers/directStyleCSS.mjs +101 -104
  113. package/dist/esm/helpers/directStyleCSS.mjs.map +1 -1
  114. package/dist/esm/helpers/formatDiagnostic.mjs +2 -4
  115. package/dist/esm/helpers/formatDiagnostic.mjs.map +1 -1
  116. package/dist/esm/helpers/formatDiagnostic.native.js +2 -4
  117. package/dist/esm/helpers/formatDiagnostic.native.js.map +1 -1
  118. package/dist/esm/helpers/getCSSStylesAtomic.mjs +10 -10
  119. package/dist/esm/helpers/getCSSStylesAtomic.mjs.map +1 -1
  120. package/dist/esm/helpers/getSplitStyles.mjs +166 -594
  121. package/dist/esm/helpers/getSplitStyles.mjs.map +1 -1
  122. package/dist/esm/helpers/getSplitStyles.native.js +166 -757
  123. package/dist/esm/helpers/getSplitStyles.native.js.map +1 -1
  124. package/dist/esm/helpers/splitStyleProps.mjs +27 -0
  125. package/dist/esm/helpers/splitStyleProps.mjs.map +1 -0
  126. package/dist/esm/helpers/splitStyleProps.native.js +28 -0
  127. package/dist/esm/helpers/splitStyleProps.native.js.map +1 -0
  128. package/dist/esm/helpers/styleStaticConfig.mjs +57 -0
  129. package/dist/esm/helpers/styleStaticConfig.mjs.map +1 -0
  130. package/dist/esm/helpers/styleStaticConfig.native.js +58 -0
  131. package/dist/esm/helpers/styleStaticConfig.native.js.map +1 -0
  132. package/dist/esm/helpers/tokenCategories.mjs +33 -72
  133. package/dist/esm/helpers/tokenCategories.mjs.map +1 -1
  134. package/dist/esm/helpers/tokenCategories.native.js +35 -74
  135. package/dist/esm/helpers/tokenCategories.native.js.map +1 -1
  136. package/dist/esm/helpers/variantResolvers.mjs +65 -0
  137. package/dist/esm/helpers/variantResolvers.mjs.map +1 -0
  138. package/dist/esm/helpers/variantResolvers.native.js +116 -0
  139. package/dist/esm/helpers/variantResolvers.native.js.map +1 -0
  140. package/dist/esm/hooks/useSplitStyles.mjs +2 -2
  141. package/dist/esm/hooks/useSplitStyles.mjs.map +1 -1
  142. package/dist/esm/hooks/useSplitStyles.native.js +2 -2
  143. package/dist/esm/hooks/useSplitStyles.native.js.map +1 -1
  144. package/dist/esm/index.js +3 -5
  145. package/dist/esm/index.mjs +3 -5
  146. package/dist/esm/index.native.js +3 -5
  147. package/dist/esm/internal-runtime.mjs +8 -7
  148. package/dist/esm/internal-runtime.mjs.map +1 -1
  149. package/dist/esm/internal-runtime.native.js +8 -7
  150. package/dist/esm/internal-runtime.native.js.map +1 -1
  151. package/dist/esm/static-resolve.mjs +8 -6
  152. package/dist/esm/static-resolve.mjs.map +1 -1
  153. package/dist/esm/static-resolve.native.js +8 -6
  154. package/dist/esm/static-resolve.native.js.map +1 -1
  155. package/dist/esm/styled.mjs +6 -57
  156. package/dist/esm/styled.mjs.map +1 -1
  157. package/dist/esm/styled.native.js +6 -59
  158. package/dist/esm/styled.native.js.map +1 -1
  159. package/dist/esm/types.mjs +1 -18
  160. package/dist/esm/types.mjs.map +1 -1
  161. package/dist/esm/types.native.js +1 -18
  162. package/dist/esm/types.native.js.map +1 -1
  163. package/dist/esm/views/Text.mjs +4 -2
  164. package/dist/esm/views/Text.mjs.map +1 -1
  165. package/dist/esm/views/Text.native.js +4 -2
  166. package/dist/esm/views/Text.native.js.map +1 -1
  167. package/dist/esm/views/View.mjs +4 -2
  168. package/dist/esm/views/View.mjs.map +1 -1
  169. package/dist/esm/views/View.native.js +4 -2
  170. package/dist/esm/views/View.native.js.map +1 -1
  171. package/package.json +15 -15
  172. package/src/config.ts +1 -1
  173. package/src/createComponent.tsx +41 -30
  174. package/src/createStyledHOC.tsx +56 -9
  175. package/src/createTokens.ts +1 -1
  176. package/src/dom/html.tsx +778 -877
  177. package/src/dom/htmlRuntime.native.tsx +7 -3
  178. package/src/dom/primitives.native.tsx +30 -39
  179. package/src/helpers/componentDisplayName.ts +0 -11
  180. package/src/helpers/directStyleCSS.ts +91 -112
  181. package/src/helpers/formatDiagnostic.ts +2 -4
  182. package/src/helpers/getCSSStylesAtomic.ts +32 -26
  183. package/src/helpers/getSplitStyles.tsx +315 -1119
  184. package/src/helpers/getVariantExtras.tsx +3 -3
  185. package/src/helpers/splitStyleProps.ts +166 -0
  186. package/src/helpers/styleFrontend.ts +8 -4
  187. package/src/helpers/styleStaticConfig.ts +88 -0
  188. package/src/helpers/tokenCategories.ts +62 -93
  189. package/src/helpers/variantResolvers.ts +121 -0
  190. package/src/hooks/useSplitStyles.tsx +17 -2
  191. package/src/hooks/useTheme.tsx +1 -1
  192. package/src/index.ts +8 -4
  193. package/src/internal-runtime.ts +10 -9
  194. package/src/static-resolve.ts +18 -14
  195. package/src/styled.tsx +7 -264
  196. package/src/types.tsx +19 -40
  197. package/src/views/Text.tsx +6 -7
  198. package/src/views/View.tsx +6 -7
  199. package/types/createComponent.d.ts.map +1 -1
  200. package/types/createStyledHOC.d.ts.map +1 -1
  201. package/types/dom/html.d.ts.map +1 -1
  202. package/types/dom/htmlRuntime.native.d.ts.map +1 -1
  203. package/types/dom/primitives.native.d.ts.map +1 -1
  204. package/types/helpers/componentDisplayName.d.ts +0 -3
  205. package/types/helpers/componentDisplayName.d.ts.map +1 -1
  206. package/types/helpers/directStyleCSS.d.ts.map +1 -1
  207. package/types/helpers/formatDiagnostic.d.ts.map +1 -1
  208. package/types/helpers/getCSSStylesAtomic.d.ts +17 -15
  209. package/types/helpers/getCSSStylesAtomic.d.ts.map +1 -1
  210. package/types/helpers/getSplitStyles.d.ts +6 -6
  211. package/types/helpers/getSplitStyles.d.ts.map +1 -1
  212. package/types/helpers/splitStyleProps.d.ts +44 -0
  213. package/types/helpers/splitStyleProps.d.ts.map +1 -0
  214. package/types/helpers/styleFrontend.d.ts +4 -4
  215. package/types/helpers/styleFrontend.d.ts.map +1 -1
  216. package/types/helpers/styleStaticConfig.d.ts +19 -0
  217. package/types/helpers/styleStaticConfig.d.ts.map +1 -0
  218. package/types/helpers/tokenCategories.d.ts +1 -1
  219. package/types/helpers/tokenCategories.d.ts.map +1 -1
  220. package/types/helpers/variantResolvers.d.ts +9 -0
  221. package/types/helpers/variantResolvers.d.ts.map +1 -0
  222. package/types/hooks/useSplitStyles.d.ts.map +1 -1
  223. package/types/index.d.ts +2 -4
  224. package/types/index.d.ts.map +1 -1
  225. package/types/internal-runtime.d.ts.map +1 -1
  226. package/types/static-resolve.d.ts +2 -2
  227. package/types/static-resolve.d.ts.map +1 -1
  228. package/types/styled.d.ts +3 -39
  229. package/types/styled.d.ts.map +1 -1
  230. package/types/types.d.ts +2 -12
  231. package/types/types.d.ts.map +1 -1
  232. package/types/views/Text.d.ts.map +1 -1
  233. package/types/views/View.d.ts.map +1 -1
  234. package/dist/cjs/helpers/getDefaultProps.cjs +0 -24
  235. package/dist/cjs/helpers/getDefaultProps.native.cjs +0 -28
  236. package/dist/cjs/helpers/getDefaultProps.native.js +0 -30
  237. package/dist/cjs/helpers/getDefaultProps.native.js.map +0 -1
  238. package/dist/cjs/helpers/themeable.cjs +0 -92
  239. package/dist/cjs/helpers/themeable.native.cjs +0 -95
  240. package/dist/cjs/helpers/themeable.native.js +0 -97
  241. package/dist/cjs/helpers/themeable.native.js.map +0 -1
  242. package/dist/cjs/hooks/useProps.cjs +0 -129
  243. package/dist/cjs/hooks/useProps.native.cjs +0 -135
  244. package/dist/cjs/hooks/useProps.native.js +0 -137
  245. package/dist/cjs/hooks/useProps.native.js.map +0 -1
  246. package/dist/esm/helpers/getDefaultProps.mjs +0 -4
  247. package/dist/esm/helpers/getDefaultProps.mjs.map +0 -1
  248. package/dist/esm/helpers/getDefaultProps.native.js +0 -6
  249. package/dist/esm/helpers/getDefaultProps.native.js.map +0 -1
  250. package/dist/esm/helpers/themeable.mjs +0 -67
  251. package/dist/esm/helpers/themeable.mjs.map +0 -1
  252. package/dist/esm/helpers/themeable.native.js +0 -68
  253. package/dist/esm/helpers/themeable.native.js.map +0 -1
  254. package/dist/esm/hooks/useProps.mjs +0 -100
  255. package/dist/esm/hooks/useProps.mjs.map +0 -1
  256. package/dist/esm/hooks/useProps.native.js +0 -104
  257. package/dist/esm/hooks/useProps.native.js.map +0 -1
  258. package/src/helpers/getDefaultProps.ts +0 -3
  259. package/src/helpers/themeable.tsx +0 -96
  260. package/src/hooks/useProps.tsx +0 -186
  261. package/types/helpers/getDefaultProps.d.ts +0 -3
  262. package/types/helpers/getDefaultProps.d.ts.map +0 -1
  263. package/types/helpers/themeable.d.ts +0 -3
  264. package/types/helpers/themeable.d.ts.map +0 -1
  265. package/types/hooks/useProps.d.ts +0 -39
  266. package/types/hooks/useProps.d.ts.map +0 -1
@@ -8,16 +8,33 @@ import {
8
8
  StyleObjectIdentifier,
9
9
  StyleObjectRules,
10
10
  nonAnimatableStyleProps,
11
+ propToTokenCategoryCode,
11
12
  stylePropsAll,
12
13
  stylePropsText,
13
14
  stylePropsTransform,
15
+ tokenCategoryColor,
14
16
  validStyles as validStylesView,
15
- tokenCategories,
16
17
  } from '@tamagui/helpers'
18
+ import {
19
+ addTransformValue,
20
+ canonicalStateModifierNames,
21
+ createTransformAccumulator,
22
+ finalizeTransformAccumulator,
23
+ getTransformPartKeys,
24
+ isContainerSizeQueryText,
25
+ isModifierName,
26
+ modifierKindMedia,
27
+ modifierKindPlatform,
28
+ modifierKindState,
29
+ modifierKindTheme,
30
+ removeTransformValue,
31
+ scanFlatValue,
32
+ stateModifierSelectors,
33
+ type FlatValueHandler,
34
+ } from '@tamagui/style-grammar/runtime'
17
35
  import { getConfig, getFont } from '../config'
18
- import { isVariable } from '../createVariable'
19
36
  import { isDevTools } from '../constants/isDevTools'
20
- import { mediaState as globalMediaState } from './mediaState'
37
+ import { isVariable } from '../createVariable'
21
38
  import type {
22
39
  AllGroupContexts,
23
40
  AnimationDriver,
@@ -27,43 +44,19 @@ import type {
27
44
  DebugProp,
28
45
  GetStyleResult,
29
46
  GetStyleState,
47
+ PropMapper,
30
48
  RulesToInsert,
31
49
  SplitStyleProps,
32
50
  StaticConfig,
33
- PropMapper,
34
- Variable,
35
- VariantSpreadFunction,
36
51
  StyleObject,
37
52
  TamaguiComponentState,
38
53
  TamaguiInternalConfig,
39
54
  TextStyle,
40
55
  ThemeParsed,
41
56
  TransitionProp,
57
+ Variable,
58
+ VariantSpreadFunction,
42
59
  } from '../types'
43
- import { variantResolverNames } from '../types'
44
- import {
45
- addTransformValue,
46
- canonicalStateModifierNames,
47
- createTransformAccumulator,
48
- finalizeTransformAccumulator,
49
- getTransformPartKeys,
50
- isContainerSizeQueryText,
51
- isModifierName,
52
- modifierKindMedia,
53
- modifierKindPlatform,
54
- modifierKindState,
55
- modifierKindTheme,
56
- removeTransformValue,
57
- scanFlatValue,
58
- stateModifierSelectors,
59
- type FlatValueHandler,
60
- type TransformAccumulator,
61
- } from '@tamagui/style-grammar/runtime'
62
- import { mediaKeyMatch } from './mediaState'
63
- import { warnOnce, warnRefusedValue } from './warnOnce'
64
- import { expandStyle } from './expandStyle'
65
- import { fixStyles } from './expandStyles'
66
- import { styleToCSS } from './styleToCSS'
67
60
  import {
68
61
  addComposition,
69
62
  canGenerateCSS,
@@ -73,45 +66,53 @@ import {
73
66
  requestBorderStyleDefault,
74
67
  streamAtomic,
75
68
  } from './directStyleCSS'
69
+ import { expandStyle } from './expandStyle'
70
+ import { fixStyles } from './expandStyles'
76
71
  import type { AtomicSlotEntry } from './getCSSStylesAtomic'
72
+ import { getConfigRevisionState } from './grammarConfig'
73
+ import { mediaState as globalMediaState, mediaKeyMatch } from './mediaState'
74
+ import { getStyleStaticConfig, type StyleStaticConfig } from './styleStaticConfig'
75
+ import { styleToCSS } from './styleToCSS'
76
+ import { getVariantDefinition } from './variantResolvers'
77
+ import { warnOnce, warnRefusedValue } from './warnOnce'
77
78
 
78
79
  export { directStyleSignature, flushDirectStyles } from './directStyleCSS'
79
- import { getConfigRevisionState } from './grammarConfig'
80
+
81
+ export { getStyleStaticConfig }
82
+
80
83
  import { isColorStyleKey } from './getDynamicVal'
81
- import { getDefaultProps } from './getDefaultProps'
84
+ import { getVariantExtras } from './getVariantExtras'
82
85
  import { shouldInsertStyleRules, updateRules } from './insertStyleRule'
83
- import { isPlainObject } from './isObj'
84
86
  import { isObj } from './isObj'
85
87
  import { log } from './log'
86
- import { normalizeStyle } from './normalizeStyle'
87
88
  import { normalizeColor } from './normalizeColor'
89
+ import { normalizeStyle } from './normalizeStyle'
88
90
  import { normalizeValueWithProperty } from './normalizeValueWithProperty'
89
91
  import { parseNativeStyle } from './parseNativeStyle.native'
90
92
  import { parseNativeTransform } from './parseNativeTransform.native'
91
- import { getVariantExtras } from './getVariantExtras'
92
93
  import { isRemValue, resolveRem } from './resolveRem'
93
94
  import { expandSafeAreaValue, isSafeAreaKey } from './resolveSafeArea'
94
95
  import { resolveSafeAreaVariable } from './resolveSafeAreaVariable'
95
96
  import { resolveVariableValue } from './resolveVariableValue'
96
- import { THEME_REF_PREFIX } from './themeRef'
97
- import { getTokenCategoryForProperty, tokenCategoryByProperty } from './tokenCategories'
98
97
  import { HOC_CLASSNAME_MARKER, skipProps } from './skipProps'
99
98
  import { styleOriginalValues } from './styleOriginalValues'
100
99
  import {
100
+ setStyleTokenProvenance,
101
101
  type StyleDebugReceipt,
102
102
  type StyleTokenProvenance,
103
- setStyleTokenProvenance,
104
103
  } from './styleProvenance'
104
+ import { THEME_REF_PREFIX } from './themeRef'
105
+ import { getTokenCategoryForProperty } from './tokenCategories'
105
106
  import { transformsToString } from './transformsToString'
106
107
 
107
- export { styleOriginalValues }
108
- export { getStyleTokenProvenance, STYLE_TOKEN_PROVENANCE_KEY } from './styleProvenance'
108
+ export { STYLE_TOKEN_PROVENANCE_KEY, getStyleTokenProvenance } from './styleProvenance'
109
109
  export type {
110
110
  StyleDebugReceipt,
111
111
  StyleDebugTier,
112
112
  StyleTokenBinding,
113
113
  StyleTokenProvenance,
114
114
  } from './styleProvenance'
115
+ export { styleOriginalValues }
115
116
 
116
117
  export type SplitStyles = ReturnType<typeof getSplitStyles>
117
118
 
@@ -143,89 +144,10 @@ export type StyleSplitter = (
143
144
  startedUnhydrated?: boolean,
144
145
  debug?: DebugProp,
145
146
  // resolved animation driver (respects animatedBy prop)
146
- animationDriver?: AnimationDriverLike | null
147
+ animationDriver?: AnimationDriverLike | null,
148
+ styleStaticConfig?: StyleStaticConfig
147
149
  ) => null | GetStyleResult
148
150
 
149
- function compoundMatcherMatches(expected: any, actual: any) {
150
- if (Array.isArray(expected)) {
151
- for (let index = 0; index < expected.length; index++) {
152
- if (expected[index] === actual) return true
153
- }
154
- return false
155
- }
156
- return expected === actual
157
- }
158
-
159
- // clause-string payloads arrive as slices, so booleans and numbers in the
160
- // matcher compare by their string spelling
161
- function compoundMatcherMatchesPayload(
162
- expected: any,
163
- source: string,
164
- start: number,
165
- end: number
166
- ) {
167
- if (Array.isArray(expected)) {
168
- for (let index = 0; index < expected.length; index++) {
169
- if (compoundMatcherMatchesPayload(expected[index], source, start, end)) return true
170
- }
171
- return false
172
- }
173
- const expectedValue = typeof expected === 'string' ? expected : String(expected)
174
- if (expectedValue.length !== end - start) return false
175
- for (let index = 0; index < expectedValue.length; index++) {
176
- if (expectedValue.charCodeAt(index) !== source.charCodeAt(start + index)) return false
177
- }
178
- return true
179
- }
180
-
181
- const preparedCompoundsKey = Symbol()
182
-
183
- type PreparedCompounds = Record<string, number[]> & {
184
- [preparedCompoundsKey]: number[]
185
- }
186
-
187
- type StaticConfigWithPreparedCompounds = StaticConfig & {
188
- [preparedCompoundsKey]?: PreparedCompounds | null
189
- }
190
-
191
- function prepareStaticConfigCompounds(staticConfig: StaticConfig) {
192
- const compoundVariants = staticConfig.compoundVariants
193
- const preparedConfig = staticConfig as StaticConfigWithPreparedCompounds
194
- if (!compoundVariants?.length) {
195
- preparedConfig[preparedCompoundsKey] = null
196
- return
197
- }
198
-
199
- const selectorCounts: number[] = []
200
- const indexesByKey = Object.create(null) as PreparedCompounds
201
- indexesByKey[preparedCompoundsKey] = selectorCounts
202
- for (let index = 0; index < compoundVariants.length; index++) {
203
- const compoundVariant = compoundVariants[index]
204
- let selectorCount = 0
205
- for (const key in compoundVariant) {
206
- if (key === 'style') continue
207
- selectorCount++
208
- ;(indexesByKey[key] ||= []).push(index)
209
- }
210
- selectorCounts[index] = selectorCount
211
- }
212
- preparedConfig[preparedCompoundsKey] = indexesByKey
213
- }
214
-
215
- // compound matching state lives in small per-pass records (components with
216
- // compoundVariants only), garbage-collected with the pass; condition
217
- // composition uses canonical keys (owner ruling 2026-08-28)
218
- type CompoundState = {
219
- seen: number
220
- failed: boolean
221
- matchedBase: boolean
222
- scanned: boolean
223
- /** condition keys matched for the current prop */
224
- pending: string[] | null
225
- /** Cartesian product of condition keys across selecting props */
226
- combinations: string[] | null
227
- }
228
-
229
151
  // ── condition cursors ────────────────────────────────────────────────────────
230
152
 
231
153
  // Cursor handles are indexes into one numeric arena. Strings and the two
@@ -277,18 +199,6 @@ function reserveConditionCursor(cursor: number) {
277
199
  conditionNumbers.set(previous)
278
200
  }
279
201
 
280
- function conditionWrapperCopy(cursor: ConditionCursor) {
281
- const wrapper = conditionNumbers[cursor + conditionWrapperOffset]
282
- const count = wrapper & 7
283
- if (!count) return undefined
284
- const start = wrapper >> 3
285
- const wrappers = new Array<string>(count)
286
- for (let index = 0; index < count; index++) {
287
- wrappers[index] = conditionWrappers[start + index]
288
- }
289
- return wrappers
290
- }
291
-
292
202
  function setConditionUnresolved(cursor: ConditionCursor, name = '') {
293
203
  conditionNumbers[cursor + conditionFlagsOffset] &= ~conditionResolvedFlag
294
204
  if (name) {
@@ -700,256 +610,6 @@ function combineConditionKeys(state: GetStyleState, first: string, second: strin
700
610
  return key
701
611
  }
702
612
 
703
- function freshCompoundState(): CompoundState {
704
- return {
705
- seen: 0,
706
- failed: false,
707
- matchedBase: false,
708
- scanned: false,
709
- pending: null,
710
- combinations: null,
711
- }
712
- }
713
-
714
- function beginCompoundEdges(
715
- indexes: number[] | undefined,
716
- states: (CompoundState | undefined)[]
717
- ) {
718
- if (!indexes) return
719
- for (let index = 0; index < indexes.length; index++) {
720
- const state = (states[indexes[index]] ||= freshCompoundState())
721
- state.pending = null
722
- state.matchedBase = false
723
- state.scanned = false
724
- }
725
- }
726
-
727
- function feedCompoundSegment(
728
- state: DirectState,
729
- source: string,
730
- start: number,
731
- end: number,
732
- isBase: boolean,
733
- valid: boolean,
734
- conditionKey: string
735
- ) {
736
- if (state.flatCompoundOutputDepth) return
737
- const pass = state.flatPass!
738
- const indexes = pass[passCompoundIndexes] as number[] | undefined
739
- const states = pass[passCompoundStates] as (CompoundState | undefined)[] | undefined
740
- const key = pass[passCompoundKey] as string | undefined
741
- if (!indexes || !states || !key) return
742
- const compoundVariants = state.staticConfig.compoundVariants!
743
- for (let index = 0; index < indexes.length; index++) {
744
- const compoundIndex = indexes[index]
745
- const compoundState = (states[compoundIndex] ||= freshCompoundState())
746
- compoundState.scanned = true
747
- if (
748
- !valid ||
749
- start === end ||
750
- !compoundMatcherMatchesPayload(
751
- compoundVariants[compoundIndex][key],
752
- source,
753
- start,
754
- end
755
- )
756
- ) {
757
- continue
758
- }
759
- if (isBase) {
760
- compoundState.matchedBase = true
761
- } else if (!compoundState.matchedBase) {
762
- ;(compoundState.pending ||= []).push(conditionKey)
763
- }
764
- }
765
- }
766
-
767
- const compoundOnlyHandler: FlatValueHandler<DirectState> = {
768
- segment(state, start, end, isBase, valid, source, chainStart, chainEnd, chainValid) {
769
- if (isBase) {
770
- feedCompoundSegment(state, source, start, end, true, valid, '')
771
- return
772
- }
773
- const cursor = state.flatScanCursor
774
- if (
775
- !chainValid ||
776
- !cursor ||
777
- !(conditionNumbers[cursor + conditionFlagsOffset] & conditionResolvedFlag) ||
778
- !conditionNumbers[cursor + conditionValueOffset]
779
- ) {
780
- feedCompoundSegment(state, source, start, end, false, false, '')
781
- return
782
- }
783
- feedCompoundSegment(
784
- state,
785
- source,
786
- start,
787
- end,
788
- false,
789
- valid,
790
- conditionTexts[cursor + conditionKeyOffset] || ''
791
- )
792
- },
793
- modifier(state, start, end, valid, first, source) {
794
- let cursor = state.flatScanCursor
795
- if (!cursor) {
796
- cursor = state.flatScanCursor = acquireConditionCursor()
797
- } else if (first) {
798
- resetConditionCursor(cursor, 0)
799
- }
800
- if (!valid) {
801
- setConditionUnresolved(cursor)
802
- return
803
- }
804
- if (conditionNumbers[cursor + conditionFlagsOffset] & conditionResolvedFlag) {
805
- resolveConditionModifier(state, cursor, source.slice(start, end))
806
- }
807
- },
808
- chain(state, _start, _end, valid) {
809
- const cursor = state.flatScanCursor
810
- if (cursor) {
811
- if (!valid) setConditionUnresolved(cursor)
812
- if (conditionNumbers[cursor + conditionFlagsOffset] & conditionResolvedFlag) {
813
- commitConditionCursor(state, cursor)
814
- }
815
- }
816
- return true
817
- },
818
- }
819
-
820
- function finishCompoundEdges(
821
- pass: StylePass,
822
- key: string,
823
- value: any,
824
- indexes: number[] | undefined,
825
- states: (CompoundState | undefined)[]
826
- ) {
827
- if (!indexes) return
828
- const state = pass[passStyleState] as DirectState
829
- pass[passCompoundIndexes] = indexes
830
- pass[passCompoundKey] = key
831
- pass[passCompoundStates] = states
832
- let needsScan = false
833
- for (let index = 0; index < indexes.length; index++) {
834
- const compoundState = (states[indexes[index]] ||= freshCompoundState())
835
- if (!compoundState.scanned) {
836
- needsScan = true
837
- break
838
- }
839
- }
840
- if (needsScan) {
841
- if (typeof value === 'string') {
842
- const watermark = conditionCursorTop
843
- const previousCursor = state.flatScanCursor
844
- state.flatScanCursor = null
845
- try {
846
- scanFlatValue(value, compoundOnlyHandler, state)
847
- } finally {
848
- state.flatScanCursor = previousCursor
849
- releaseConditionCursors(watermark)
850
- }
851
- } else if (
852
- value &&
853
- typeof value === 'object' &&
854
- !Array.isArray(value) &&
855
- !isVariable(value) &&
856
- Object.prototype.hasOwnProperty.call(value, 'default')
857
- ) {
858
- for (const conditionKey in value) {
859
- const payload = value[conditionKey]
860
- if (conditionKey === 'default') {
861
- const payloadString = String(payload)
862
- feedCompoundSegment(
863
- state,
864
- payloadString,
865
- 0,
866
- payloadString.length,
867
- true,
868
- true,
869
- ''
870
- )
871
- } else {
872
- const watermark = conditionCursorTop
873
- const cursor = acquireConditionCursor()
874
- resolveConditionText(state, cursor, conditionKey)
875
- const condition = commitConditionCursor(state, cursor)
876
- const payloadString = String(payload)
877
- feedCompoundSegment(
878
- state,
879
- payloadString,
880
- 0,
881
- payloadString.length,
882
- false,
883
- Boolean(condition),
884
- condition ? conditionTexts[cursor + conditionKeyOffset] || '' : ''
885
- )
886
- releaseConditionCursors(watermark)
887
- }
888
- }
889
- } else {
890
- const variants = state.staticConfig.compoundVariants!
891
- for (let index = 0; index < indexes.length; index++) {
892
- const compoundIndex = indexes[index]
893
- const compoundState = (states[compoundIndex] ||= freshCompoundState())
894
- compoundState.scanned = true
895
- if (compoundMatcherMatches(variants[compoundIndex][key], value)) {
896
- compoundState.matchedBase = true
897
- }
898
- }
899
- }
900
- }
901
-
902
- const variants = state.staticConfig.compoundVariants!
903
- const selectorCounts = (state.staticConfig as StaticConfigWithPreparedCompounds)[
904
- preparedCompoundsKey
905
- ]![preparedCompoundsKey]
906
- for (let index = 0; index < indexes.length; index++) {
907
- const compoundIndex = indexes[index]
908
- const compoundState = states[compoundIndex]!
909
- if (compoundState.failed) continue
910
- const branches = compoundState.matchedBase ? [''] : compoundState.pending
911
- if (!branches || !branches.length) {
912
- compoundState.failed = true
913
- continue
914
- }
915
-
916
- if (!compoundState.seen) {
917
- compoundState.combinations = branches
918
- } else {
919
- const previous = compoundState.combinations!
920
- const next: string[] = []
921
- for (let left = 0; left < previous.length; left++) {
922
- for (let right = 0; right < branches.length; right++) {
923
- const conditionKey = combineConditionKeys(
924
- state,
925
- previous[left],
926
- branches[right]
927
- )
928
- if (!next.includes(conditionKey)) next.push(conditionKey)
929
- }
930
- }
931
- compoundState.combinations = next
932
- }
933
- compoundState.seen++
934
- if (compoundState.seen !== selectorCounts[compoundIndex]) continue
935
- const style = variants[compoundIndex].style
936
- if (!isPlainObject(style)) continue
937
- const combinations = compoundState.combinations!
938
- for (let combination = 0; combination < combinations.length; combination++) {
939
- for (const styleKey in style) {
940
- contributeProp(
941
- pass,
942
- styleKey,
943
- style[styleKey],
944
- undefined,
945
- states,
946
- combinations[combination]
947
- )
948
- }
949
- }
950
- }
951
- }
952
-
953
613
  // the runtime discrimination rule, phrased over an isChain callback: a
954
614
  // conditional object names a `default` or opens with a resolvable chain
955
615
  // probe: does this object's first key open a resolvable modifier chain (or
@@ -961,7 +621,7 @@ function classifyConditionalObject(
961
621
  isChain?: (chain: string) => boolean,
962
622
  firstCursor?: ConditionCursor
963
623
  ): number {
964
- if (Object.prototype.hasOwnProperty.call(value, 'default')) return -1
624
+ if ('default' in value) return -1
965
625
  for (const key in value) {
966
626
  if (!key.length) return 0
967
627
  if (!state) return isChain?.(key) ? 1 : 0
@@ -990,9 +650,6 @@ const passFrontendContainer = 27
990
650
  const passFrontendContainerType = 28
991
651
  const passHocMappedProperties = 29
992
652
  const passHocMappedClasses = 30
993
- const passCompoundIndexes = 31
994
- const passCompoundKey = 32
995
- const passCompoundStates = 33
996
653
  const passParentCursor = 35
997
654
  const passMapSourceKey = 36
998
655
  const passMapFlags = 37
@@ -1006,171 +663,50 @@ const passTextFlag = 32
1006
663
  const passInputFlag = 64
1007
664
  const passAsChildStyleFlag = 128
1008
665
 
1009
- type PreparedStyledDefaults = unknown[]
1010
-
1011
- // Styled defaults computed once per static config. mergeComponentProps replaces
1012
- // defaults at the prop level, but flat programs merge per clause slot: either a
1013
- // conditioned default or a conditioned prop therefore needs the displaced
1014
- // styled value re-injected at the styled-base position. This is what preserves
1015
- // `styled(View, { flexDirection: 'row' })` under `sm:column`.
1016
- const styledDefaultsCache = new WeakMap<object, PreparedStyledDefaults | null>()
1017
-
1018
- function getStyledDefaults(
1019
- staticConfig: StaticConfig,
1020
- shorthands: Record<string, string>
1021
- ): PreparedStyledDefaults | null {
1022
- let prepared = styledDefaultsCache.get(staticConfig)
1023
- if (prepared === undefined) {
1024
- let entries: unknown[] | null = null
1025
- const defaults = staticConfig.defaultProps
1026
- if (defaults) {
1027
- for (const key in defaults) {
1028
- if (!(key in stylePropsAll || key in shorthands)) continue
1029
- const value = defaults[key]
1030
- if (maybeStyleProgram(value)) (entries ||= []).push(key, value)
1031
- }
1032
- }
1033
- prepared = entries
1034
- styledDefaultsCache.set(staticConfig, prepared)
1035
- }
1036
- return prepared
1037
- }
1038
-
1039
- // definition-time only: render never rescans a value to ask this
1040
- const maybeStyleProgram = (value: any): boolean =>
1041
- typeof value === 'string'
1042
- ? value.indexOf(':') !== -1
1043
- : !!value && typeof value === 'object' && !Array.isArray(value) && !isVariable(value)
1044
-
1045
- function contributeDisplacedStyledDefaults(
1046
- styledDefaults: PreparedStyledDefaults | null,
1047
- processedProps: Record<string, any>,
1048
- pass: StylePass
1049
- ) {
1050
- if (!styledDefaults) return
1051
- for (let offset = 0; offset < styledDefaults.length; offset += 2) {
1052
- const key = styledDefaults[offset] as string
1053
- const value = styledDefaults[offset + 1]
1054
- const propValue = processedProps[key]
1055
- // equal means the default flowed through the merge untouched and will be
1056
- // processed as an ordinary prop entry; different means a call-site value
1057
- // displaced it, and a displaced PROGRAM default re-injects at the styled
1058
- // position so its clause slots survive the caller's base. A displaced
1059
- // plain default matters only when the displacing prop itself carries
1060
- // clauses, which the prop's own scan discovers — see the weak injection
1061
- // in forEachPropInForwardOrder.
1062
- if (propValue !== undefined && propValue !== value) {
1063
- contributeProp(pass, key, value)
1064
- }
1065
- }
1066
- }
1067
-
1068
- function injectDisplacedStyledDefault(pass: StylePass, key: string, value: any) {
1069
- const defaultValue = pass[4].defaultProps?.[key]
1070
- if (
1071
- defaultValue === undefined ||
1072
- value === undefined ||
1073
- value === defaultValue ||
1074
- maybeStyleProgram(defaultValue)
1075
- ) {
1076
- return
1077
- }
1078
- const state = pass[passStyleState] as DirectState
1079
- state.flatWeakContribution = true
1080
- try {
1081
- contributeProp(pass, key, defaultValue)
1082
- } finally {
1083
- state.flatWeakContribution = false
1084
- }
1085
- }
1086
-
1087
666
  /**
1088
667
  * Walks every style contribution in authored forward order and hands each one
1089
668
  * to `contribute`, without building an intermediate list.
1090
669
  *
1091
- * Order is base style, then any styled default a call-site value displaced,
1092
- * then the props. That is the cascade: last writer wins, so the props must come
1093
- * last.
1094
- *
1095
- * The common case touches each source object exactly once and allocates
1096
- * nothing. Only compound variants need a materialised list, because a matching
1097
- * compound has to run immediately after the LAST prop that selected it, and
1098
- * that anchor is not known until the props have been indexed.
670
+ * Order is the base style, then the props. That is the cascade: last writer
671
+ * wins, so the props must come last — a call-site value and a variant always
672
+ * land on top of a styled() base style.
1099
673
  */
1100
674
  function forEachPropInForwardOrder(pass: StylePass) {
1101
675
  const styleState = pass[passStyleState] as GetStyleState
1102
- const staticConfig = styleState.staticConfig
1103
676
  const processedProps = styleState.props
1104
- const shorthands = styleState.conf.shorthands
1105
- const processedBaseStyle = staticConfig.baseStyle
1106
- const styledDefaults = getStyledDefaults(staticConfig, shorthands)
1107
- const directState = styleState as DirectState
1108
- const preparedCompounds = (staticConfig as StaticConfigWithPreparedCompounds)[
1109
- preparedCompoundsKey
1110
- ]
1111
-
1112
- if (preparedCompounds === undefined && staticConfig.compoundVariants?.length) {
1113
- throw new Error(
1114
- 'A component with compoundVariants reached style resolution before its static config was prepared.'
1115
- )
1116
- }
677
+ const styleStaticConfig = (styleState as DirectState).flatStyleStaticConfig!
678
+ const baseStyle = styleStaticConfig.baseStyle
679
+ const baseVariantProps = styleStaticConfig.baseVariantProps
1117
680
 
1118
681
  const conditionWrapperBase = conditionWrapperTop
1119
- if (!preparedCompounds) {
1120
- try {
1121
- if (processedBaseStyle) {
1122
- for (const key in processedBaseStyle) {
1123
- contributeProp(pass, key, processedBaseStyle[key])
1124
- }
1125
- }
1126
- contributeDisplacedStyledDefaults(styledDefaults, processedProps, pass)
1127
- for (const key in processedProps) {
1128
- const value = processedProps[key]
1129
- directState.flatPropSawCondition = false
1130
- contributeProp(pass, key, value)
1131
- if (directState.flatPropSawCondition) {
1132
- injectDisplacedStyledDefault(pass, key, value)
1133
- }
1134
- }
1135
- } finally {
1136
- releaseConditionPayloads(conditionWrapperBase)
1137
- }
1138
- return
1139
- }
1140
-
1141
- const compoundVariants = staticConfig.compoundVariants!
1142
- const compoundStates: (CompoundState | undefined)[] = new Array(compoundVariants.length)
1143
682
  try {
1144
- if (processedBaseStyle) {
1145
- for (const key in processedBaseStyle) {
1146
- contributeProp(pass, key, processedBaseStyle[key])
683
+ // asChild renders the child instead of this element, so this component's own
684
+ // base styles are not its to apply; anything the call site passed still is
685
+ const appliesBaseStyle = baseStyle && !processedProps.asChild
686
+ if (appliesBaseStyle) {
687
+ for (const key in baseStyle) {
688
+ // a current value replaces its default variant in the default's authored
689
+ // slot. changing the value must not move it after later child defaults.
690
+ contributeProp(
691
+ pass,
692
+ key,
693
+ baseVariantProps &&
694
+ Object.hasOwn(baseVariantProps, key) &&
695
+ Object.hasOwn(processedProps, key)
696
+ ? processedProps[key]
697
+ : baseStyle[key]
698
+ )
1147
699
  }
1148
700
  }
1149
- contributeDisplacedStyledDefaults(styledDefaults, processedProps, pass)
1150
- const selectorCounts = preparedCompounds[preparedCompoundsKey]
1151
- for (
1152
- let compoundIndex = 0;
1153
- compoundIndex < compoundVariants.length;
1154
- compoundIndex++
1155
- ) {
1156
- if (selectorCounts[compoundIndex]) continue
1157
- const style = compoundVariants[compoundIndex].style
1158
- if (!isPlainObject(style)) continue
1159
- for (const key in style) contributeProp(pass, key, style[key])
1160
- }
1161
701
  for (const key in processedProps) {
1162
- const compoundIndexes = preparedCompounds[key]
1163
- const value = processedProps[key]
1164
- beginCompoundEdges(compoundIndexes, compoundStates)
1165
- directState.flatPropSawCondition = false
1166
- contributeProp(pass, key, value, compoundIndexes, compoundStates)
1167
- if (directState.flatPropSawCondition) {
1168
- injectDisplacedStyledDefault(pass, key, value)
702
+ if (appliesBaseStyle && baseVariantProps && Object.hasOwn(baseVariantProps, key)) {
703
+ continue
1169
704
  }
1170
- finishCompoundEdges(pass, key, value, compoundIndexes, compoundStates)
705
+ contributeProp(pass, key, processedProps[key])
1171
706
  }
1172
- } finally {
707
+ } catch (error) {
1173
708
  releaseConditionPayloads(conditionWrapperBase)
709
+ throw error
1174
710
  }
1175
711
  }
1176
712
 
@@ -1369,18 +905,9 @@ function contributeProp(
1369
905
  pass: StylePass,
1370
906
  keyOg: string,
1371
907
  valOg: any,
1372
- compoundIndexes?: number[],
1373
- compoundStates?: (CompoundState | undefined)[],
1374
908
  parentConditionKey?: string
1375
909
  ) {
1376
910
  const parentWatermark = conditionCursorTop
1377
- if (compoundIndexes) {
1378
- pass[passCompoundIndexes] = compoundIndexes
1379
- pass[passCompoundKey] = keyOg
1380
- pass[passCompoundStates] = compoundStates
1381
- } else if (pass[passCompoundIndexes]) {
1382
- pass[passCompoundIndexes] = undefined
1383
- }
1384
911
  if (parentConditionKey) {
1385
912
  pass[passParentCursor] = acquireConditionKeyCursor(
1386
913
  pass[passStyleState] as GetStyleState,
@@ -1627,18 +1154,9 @@ function contributeProp(
1627
1154
  clearDirectStyle(styleState, key)
1628
1155
  }
1629
1156
  if (process.env.TAMAGUI_TARGET === 'web') {
1630
- if (
1631
- key === 'containerName' &&
1632
- typeof normalized[key] === 'string' &&
1633
- normalized[key].indexOf(':') === -1
1634
- ) {
1157
+ if (key === 'containerName') {
1635
1158
  pass[passContainerName] = normalized[key]
1636
- }
1637
- if (
1638
- key === 'containerType' &&
1639
- typeof normalized[key] === 'string' &&
1640
- normalized[key].indexOf(':') === -1
1641
- ) {
1159
+ } else if (key === 'containerType') {
1642
1160
  pass[passContainerType] = normalized[key]
1643
1161
  }
1644
1162
  }
@@ -1762,6 +1280,19 @@ function contributeProp(
1762
1280
  }
1763
1281
  }
1764
1282
 
1283
+ if (
1284
+ process.env.TAMAGUI_TARGET === 'web' &&
1285
+ isValidStyleKeyInit &&
1286
+ valInit == null &&
1287
+ keyOg in props
1288
+ ) {
1289
+ clearDirectStyle(styleState, keyInit)
1290
+ if (styledContextKeys?.has(keyInit)) {
1291
+ ;(styleState.overriddenContextProps ||= {})[keyInit] = valInit
1292
+ }
1293
+ return
1294
+ }
1295
+
1765
1296
  let isVariant = !isValidStyleKeyInit && variants && keyInit in variants
1766
1297
  const isStyleLikeKey = isValidStyleKeyInit || isVariant
1767
1298
  const isStyleProp = isValidStyleKeyInit || (isVariant && !noExpand)
@@ -1893,18 +1424,11 @@ export const getSplitStyles: StyleSplitter = (
1893
1424
  elementType,
1894
1425
  startedUnhydrated,
1895
1426
  debug,
1896
- animationDriver
1427
+ animationDriver,
1428
+ styleStaticConfig
1897
1429
  ) => {
1898
1430
  const conf = getConfig()
1899
- // a frontend-bound component resolves its static style input (class-string
1900
- // base, string variants) through its own descriptor; implementations memoize
1901
- // per (staticConfig, config). components without a descriptor pay one read.
1902
- if (staticConfig.styleFrontend?.normalizeStaticConfig) {
1903
- staticConfig = staticConfig.styleFrontend.normalizeStaticConfig(
1904
- staticConfig as any,
1905
- conf
1906
- ) as StaticConfig
1907
- }
1431
+ styleStaticConfig ||= getStyleStaticConfig(staticConfig, conf)
1908
1432
  // use passed animationDriver or fall back to context/config
1909
1433
  const driver =
1910
1434
  animationDriver ||
@@ -1920,15 +1444,9 @@ export const getSplitStyles: StyleSplitter = (
1920
1444
  }
1921
1445
 
1922
1446
  const { shorthands } = conf
1923
- const {
1924
- isHOC,
1925
- isText,
1926
- isInput,
1927
- variants,
1928
- inlineProps,
1929
- parentStaticConfig,
1930
- acceptsClassName,
1931
- } = staticConfig
1447
+ const { isHOC, isText, isInput, inlineProps, parentStaticConfig, acceptsClassName } =
1448
+ staticConfig
1449
+ const variants = styleStaticConfig.variants
1932
1450
 
1933
1451
  const viewProps: GetStyleResult['viewProps'] = {}
1934
1452
  const mediaState = styleProps.mediaState || globalMediaState
@@ -1946,14 +1464,16 @@ export const getSplitStyles: StyleSplitter = (
1946
1464
  let hasMedia: boolean | Set<string> = false
1947
1465
  let pseudoGroups: Set<string> | undefined
1948
1466
  let mediaGroups: Set<string> | undefined
1949
- // the frontend's normalizeStaticConfig partitions unclaimed styled-base
1467
+ // the frontend normalization partitions unclaimed styled-base
1950
1468
  // classes into passthroughClassName (baseStyle holds styles only). they are
1951
1469
  // the base's raw-interop className at the earliest forward position:
1952
1470
  // prepend them and flip the cascade-preserving switch so every later
1953
1471
  // Tamagui contribution keeps its last-wins position inline, exactly as a
1954
1472
  // className prop does mid-loop
1955
1473
  const staticPassthroughClassName =
1956
- process.env.TAMAGUI_TARGET === 'web' ? staticConfig.passthroughClassName || '' : ''
1474
+ process.env.TAMAGUI_TARGET === 'web'
1475
+ ? styleStaticConfig.passthroughClassName || ''
1476
+ : ''
1957
1477
  let className = staticPassthroughClassName
1958
1478
  if (staticPassthroughClassName) {
1959
1479
  shouldDoClasses = false
@@ -1993,6 +1513,7 @@ export const getSplitStyles: StyleSplitter = (
1993
1513
  // resolved animation driver (respects animatedBy prop)
1994
1514
  animationDriver: resolvedDriver,
1995
1515
  }
1516
+ ;(styleState as DirectState).flatStyleStaticConfig = styleStaticConfig
1996
1517
  if (canGenerateCSS && shouldDoClasses && styleProps.canPlatformPseudo) {
1997
1518
  // a platform driver with native pseudo states may flip this whole pass
1998
1519
  // inline once a platform-pseudo clause is discovered: defer CSS into
@@ -2035,34 +1556,26 @@ export const getSplitStyles: StyleSplitter = (
2035
1556
  noNormalize,
2036
1557
  isAnimated,
2037
1558
  styledContext,
2038
- styledContextKeys,
2039
1559
  } = styleProps
1560
+ const styledContextKeys = styleStaticConfig.styledContextKeys
2040
1561
 
2041
1562
  const styleFrontend = staticConfig.styleFrontend
2042
1563
  let frontendGroup: boolean | string | undefined
2043
1564
  let frontendContainer: boolean | string | undefined
2044
1565
  let frontendContainerType: string | undefined
2045
1566
  const processedProps = props
2046
- const parentVariants = parentStaticConfig?.variants
2047
- const defaultProps = asChild ? getDefaultProps(staticConfig) : undefined
1567
+ const parentVariants = parentStaticConfig
1568
+ ? getStyleStaticConfig(parentStaticConfig as StaticConfig, conf).variants
1569
+ : undefined
1570
+ const defaultProps = asChild ? styleStaticConfig.defaultProps : undefined
2048
1571
  const asChildExceptStyleLike =
2049
1572
  asChild === 'except-style' || asChild === 'except-style-web'
2050
1573
  let containerValue: boolean | string | undefined
2051
1574
  let containerName: string | undefined
2052
1575
  let containerType: string | undefined
2053
1576
  if (process.env.TAMAGUI_TARGET === 'web') {
2054
- const authoredContainerName = processedProps.containerName
2055
- const authoredContainerType = processedProps.containerType
2056
- containerName =
2057
- typeof authoredContainerName === 'string' &&
2058
- authoredContainerName.indexOf(':') === -1
2059
- ? authoredContainerName
2060
- : undefined
2061
- containerType =
2062
- typeof authoredContainerType === 'string' &&
2063
- authoredContainerType.indexOf(':') === -1
2064
- ? authoredContainerType
2065
- : undefined
1577
+ containerName = processedProps.containerName
1578
+ containerType = processedProps.containerType
2066
1579
  }
2067
1580
 
2068
1581
  // properties whose class landed through the HOC class transport at an
@@ -2118,99 +1631,94 @@ export const getSplitStyles: StyleSplitter = (
2118
1631
  ]
2119
1632
  ;(styleState as DirectState).flatPass = pass
2120
1633
 
2121
- forEachPropInForwardOrder(pass)
2122
-
2123
- ;[
2124
- ,
2125
- ,
2126
- ,
2127
- ,
2128
- ,
2129
- ,
2130
- ,
2131
- ,
2132
- ,
2133
- ,
2134
- ,
2135
- ,
2136
- ,
2137
- ,
2138
- ,
2139
- ,
2140
- ,
2141
- ,
2142
- ,
2143
- ,
2144
- ,
2145
- className,
2146
- shouldDoClasses,
2147
- containerValue,
2148
- containerName,
2149
- containerType,
2150
- frontendGroup,
2151
- frontendContainer,
2152
- frontendContainerType,
2153
- hocMappedClassProperties,
2154
- hocMappedClasses,
2155
- ] = pass
2156
-
2157
- if (process.env.TAMAGUI_TARGET === 'web' && containerValue) {
2158
- containerName ??= typeof containerValue === 'string' ? containerValue : undefined
2159
- containerType ??= 'inline-size'
2160
- contributeValue(
2161
- styleState,
2162
- containerName ? 'container' : 'containerType',
2163
- containerName ? `${containerName} / ${containerType}` : containerType,
2164
- mergeStyle
2165
- )
2166
- }
2167
-
2168
- if (
2169
- process.env.NODE_ENV === 'development' &&
2170
- (debug === 'profile' || (globalThis as any).time)
2171
- ) {
2172
- // @ts-expect-error
2173
- time`split-styles-propsend`
2174
- }
2175
-
2176
- const conditionalStates = styleState.flatStateKeys || null
2177
- const usesSafeArea = !!styleState.flatUsesSafeArea
2178
- if (styleState.flatMediaKeys?.size) {
2179
- if (!hasMedia) hasMedia = new Set()
2180
- if (typeof hasMedia !== 'boolean') {
2181
- for (const key of styleState.flatMediaKeys) hasMedia.add(key)
2182
- }
2183
- }
2184
- if (styleState.flatGroupKeys?.size) {
2185
- pseudoGroups ||= new Set()
2186
- for (const key of styleState.flatGroupKeys) pseudoGroups.add(key)
2187
- }
2188
- if (styleState.flatGroupMedia?.size) {
2189
- mediaGroups ||= new Set()
2190
- for (const key of styleState.flatGroupMedia) mediaGroups.add(key)
2191
- }
1634
+ let conditionalStates: Set<string> | null = null
1635
+ let usesSafeArea = false
1636
+ const conditionWrapperBase = conditionWrapperTop
1637
+ try {
1638
+ forEachPropInForwardOrder(pass)
1639
+
1640
+ ;[
1641
+ ,
1642
+ ,
1643
+ ,
1644
+ ,
1645
+ ,
1646
+ ,
1647
+ ,
1648
+ ,
1649
+ ,
1650
+ ,
1651
+ ,
1652
+ ,
1653
+ ,
1654
+ ,
1655
+ ,
1656
+ ,
1657
+ ,
1658
+ ,
1659
+ ,
1660
+ ,
1661
+ ,
1662
+ className,
1663
+ shouldDoClasses,
1664
+ containerValue,
1665
+ containerName,
1666
+ containerType,
1667
+ frontendGroup,
1668
+ frontendContainer,
1669
+ frontendContainerType,
1670
+ hocMappedClassProperties,
1671
+ hocMappedClasses,
1672
+ ] = pass
2192
1673
 
2193
- // a platform driver with native pseudo states rides the emitter path: the
2194
- // whole frame completes inline instead of as classes. The frame is neutral,
2195
- // so choosing the policy after the pass costs nothing to undo.
2196
- if (styleProps.canPlatformPseudo && styleState.flatHasPlatformPseudo) {
2197
- shouldDoClasses = false
2198
- styleState.flatShouldDoClasses = false
2199
- if (styleState.transformAccumulator) {
2200
- mergeStyle(
1674
+ if (process.env.TAMAGUI_TARGET === 'web' && containerValue) {
1675
+ containerName ??= typeof containerValue === 'string' ? containerValue : undefined
1676
+ containerType ??= 'inline-size'
1677
+ contributeValue(
2201
1678
  styleState,
2202
- 'transform',
2203
- finalizeTransformAccumulator(styleState.transformAccumulator),
2204
- 1,
2205
- true
1679
+ containerName ? 'container' : 'containerType',
1680
+ containerName ? `${containerName} / ${containerType}` : containerType,
1681
+ mergeStyle
2206
1682
  )
2207
- styleState.transformAccumulator = undefined
2208
1683
  }
2209
- convertDeferredInline(styleState, mergeStyle)
2210
- }
2211
1684
 
2212
- // streaming already applied every winner; only the residue completes here
2213
- completeStreaming(styleState, mergeStyle)
1685
+ if (
1686
+ process.env.NODE_ENV === 'development' &&
1687
+ (debug === 'profile' || (globalThis as any).time)
1688
+ ) {
1689
+ // @ts-expect-error
1690
+ time`split-styles-propsend`
1691
+ }
1692
+
1693
+ conditionalStates = styleState.flatStateKeys || null
1694
+ usesSafeArea = !!styleState.flatUsesSafeArea
1695
+ hasMedia = styleState.flatMediaKeys?.size ? styleState.flatMediaKeys : false
1696
+ pseudoGroups = styleState.flatGroupKeys?.size ? styleState.flatGroupKeys : undefined
1697
+ mediaGroups = styleState.flatGroupMedia?.size ? styleState.flatGroupMedia : undefined
1698
+
1699
+ // a platform driver with native pseudo states rides the emitter path: the
1700
+ // whole frame completes inline instead of as classes. The frame is neutral,
1701
+ // so choosing the policy after the pass costs nothing to undo.
1702
+ if (styleProps.canPlatformPseudo && styleState.flatHasPlatformPseudo) {
1703
+ shouldDoClasses = false
1704
+ styleState.flatShouldDoClasses = false
1705
+ if (styleState.transformAccumulator) {
1706
+ mergeStyle(
1707
+ styleState,
1708
+ 'transform',
1709
+ finalizeTransformAccumulator(styleState.transformAccumulator),
1710
+ true
1711
+ )
1712
+ styleState.transformAccumulator = undefined
1713
+ }
1714
+ convertDeferredInline(styleState, mergeStyle)
1715
+ }
1716
+
1717
+ // streaming already applied every winner; only the residue completes here
1718
+ completeStreaming(styleState, mergeStyle)
1719
+ } finally {
1720
+ releaseConditionPayloads(conditionWrapperBase)
1721
+ }
2214
1722
 
2215
1723
  // hand the selected transition to animation drivers and keep it out of native
2216
1724
  // destination styles, where `transition` is not a React Native style key.
@@ -2480,7 +1988,6 @@ function mergeStyle(
2480
1988
  styleState: GetStyleState,
2481
1989
  key: string,
2482
1990
  val: any,
2483
- _importance: number,
2484
1991
  disableNormalize = false,
2485
1992
  originalVal?: any
2486
1993
  ) {
@@ -2491,7 +1998,8 @@ function mergeStyle(
2491
1998
  // overriddenContextProps using the original token value (like '8') rather
2492
1999
  // than the resolved CSS variable, so children's functional variants can look
2493
2000
  // up token values. membership is a per-staticConfig cached Set.
2494
- const contextPropSet = getContextPropSet(staticConfig)
2001
+ const contextPropSet = (styleState as DirectState).flatStyleStaticConfig!
2002
+ .styledContextKeys
2495
2003
  if (contextPropSet?.has(key)) {
2496
2004
  styleState.overriddenContextProps ||= {}
2497
2005
  // priority: originalVal from propMapper, tracked original from variant
@@ -2544,13 +2052,10 @@ function recordStyleTokenProvenance(
2544
2052
  }
2545
2053
  const isConfiguredToken =
2546
2054
  tokenName !== '' &&
2547
- (Object.prototype.hasOwnProperty.call(styleState.theme, tokenName) ||
2548
- Object.prototype.hasOwnProperty.call(
2549
- styleState.conf.themes?.[styleState.flatThemeName || ''] || {},
2550
- tokenName
2551
- ) ||
2552
- Object.values(styleState.conf.tokensParsed).some((category) =>
2553
- Object.prototype.hasOwnProperty.call(category, tokenName)
2055
+ (tokenName in styleState.theme ||
2056
+ tokenName in (styleState.conf.themes?.[styleState.flatThemeName || ''] || {}) ||
2057
+ Object.values(styleState.conf.tokensParsed).some(
2058
+ (category) => tokenName in category
2554
2059
  ))
2555
2060
  if (isConfiguredToken) {
2556
2061
  ;(styleState.tokenProvenance ||= {})[key] = originalVal
@@ -2585,7 +2090,6 @@ const resolveAcceptedStyle = (
2585
2090
  _state,
2586
2091
  key,
2587
2092
  value,
2588
- _importance,
2589
2093
  disableNormalize,
2590
2094
  originalValue
2591
2095
  ) => {
@@ -2637,13 +2141,13 @@ export type MergeStyle = (
2637
2141
  state: GetStyleState,
2638
2142
  key: string,
2639
2143
  value: any,
2640
- importance: number,
2641
2144
  disableNormalize?: boolean,
2642
2145
  originalValue?: any
2643
2146
  ) => void
2644
2147
 
2645
2148
  type DirectState = GetStyleState & {
2646
2149
  flatPass?: StylePass
2150
+ flatStyleStaticConfig?: StyleStaticConfig
2647
2151
  /** streaming winner per property: packed precedence + 1, base 0 */
2648
2152
  flatUsed?: Record<string, number>
2649
2153
  flatTransitions?: AtomicSlotEntry[]
@@ -2658,9 +2162,6 @@ type DirectState = GetStyleState & {
2658
2162
  flatTextShadow?: Record<string, any>
2659
2163
  flatWebShadow?: any[]
2660
2164
  flatScanCursor?: ConditionCursor | null
2661
- flatCompoundOutputDepth?: number
2662
- flatPropSawCondition?: boolean
2663
- flatWeakContribution?: boolean
2664
2165
  /** the value being contributed is known to carry clauses: its property
2665
2166
  * will see 2+ contributions, so CSS emission opens the combined slot
2666
2167
  * directly instead of building a single class it would discard */
@@ -2695,23 +2196,22 @@ function streamWriteCSS(
2695
2196
  if (property.charCodeAt(0) === 116 && property.startsWith('transition')) {
2696
2197
  const transitions = (direct.flatTransitions ||= [])
2697
2198
  for (let index = 0; index < transitions.length; index++) {
2698
- if (
2699
- transitions[index].property === property &&
2700
- transitions[index].identity === identity
2701
- ) {
2702
- transitions[index].value = value
2703
- transitions[index].condition = condition
2199
+ if (transitions[index][0] === property && transitions[index][3] === identity) {
2200
+ transitions[index][1] = value
2201
+ transitions[index][2] = condition
2704
2202
  return
2705
2203
  }
2706
2204
  }
2707
- transitions.push({
2205
+ transitions.push([
2708
2206
  property,
2709
2207
  value,
2710
2208
  condition,
2711
2209
  identity,
2712
- selector: cursor ? conditionTexts[cursor + conditionSelectorOffset] || '' : '',
2713
- wrappers: cursor ? conditionWrapperCopy(cursor) : undefined,
2714
- })
2210
+ cursor ? conditionTexts[cursor + conditionSelectorOffset] || '' : '',
2211
+ cursor ? conditionWrappers : undefined,
2212
+ cursor ? conditionNumbers[cursor + conditionWrapperOffset] >> 3 : 0,
2213
+ cursor ? conditionNumbers[cursor + conditionWrapperOffset] & 7 : 0,
2214
+ ])
2715
2215
  return
2716
2216
  }
2717
2217
  streamAtomic(
@@ -2724,7 +2224,7 @@ function streamWriteCSS(
2724
2224
  cursor ? conditionWrappers : undefined,
2725
2225
  cursor ? conditionNumbers[cursor + conditionWrapperOffset] >> 3 : 0,
2726
2226
  cursor ? conditionNumbers[cursor + conditionWrapperOffset] & 7 : 0,
2727
- direct.flatWeakContribution === true,
2227
+ false,
2728
2228
  original
2729
2229
  )
2730
2230
  }
@@ -2754,14 +2254,9 @@ function streamWriteInline(
2754
2254
  const importance = condition ? Math.floor(condition / 256) + 1 : 0
2755
2255
  const used = (direct.flatUsed ||= {})
2756
2256
  const previous = used[property]
2757
- if (previous !== undefined) {
2758
- if (previous > importance) return
2759
- // a weak write restores a styled default: any earlier write owns the
2760
- // property
2761
- if (direct.flatWeakContribution === true) return
2762
- }
2257
+ if (previous !== undefined && previous > importance) return
2763
2258
  used[property] = importance
2764
- merge(state, property, value, 1, !normalize, original)
2259
+ merge(state, property, value, !normalize, original)
2765
2260
  }
2766
2261
 
2767
2262
  /**
@@ -2791,23 +2286,20 @@ function streamRetractInline(
2791
2286
  */
2792
2287
  function convertDeferredInline(state: GetStyleState, merge: MergeStyle) {
2793
2288
  const direct = state as DirectState
2794
- const used = (direct.flatUsed ||= {})
2795
2289
  const consume = (entries: AtomicSlotEntry[]) => {
2796
2290
  for (let index = 0; index < entries.length; index++) {
2797
2291
  const entry = entries[index]
2798
- const condition = entry.condition
2292
+ const condition = entry[2]
2799
2293
  if (condition && !(condition & 1)) continue
2800
- const importance = condition ? Math.floor(condition / 256) + 1 : 0
2801
- const previous = used[entry.property]
2802
- if (previous !== undefined && previous > importance) continue
2803
- used[entry.property] = importance
2804
- merge(
2294
+ streamWriteInline(
2805
2295
  state,
2806
- entry.property,
2807
- entry.value,
2808
- 1,
2809
- true,
2810
- entry.original !== undefined ? entry.original : entry.value
2296
+ entry[0],
2297
+ entry[1],
2298
+ null,
2299
+ merge,
2300
+ entry[8] !== undefined ? entry[8] : entry[1],
2301
+ false,
2302
+ condition
2811
2303
  )
2812
2304
  }
2813
2305
  }
@@ -2890,11 +2382,6 @@ function emitUnderCondition(
2890
2382
  warnSource: any
2891
2383
  ): number {
2892
2384
  const condition = conditionNumbers[cursor + conditionValueOffset]
2893
- // a real conditional clause reached emission intent (active or not): the
2894
- // prop loop uses this to restore a displaced plain styled default
2895
- if (merge && property && condition) {
2896
- ;(state as DirectState).flatPropSawCondition = true
2897
- }
2898
2385
  if (!(conditionNumbers[cursor + conditionFlagsOffset] & conditionResolvedFlag)) {
2899
2386
  if (warnMode && process.env.NODE_ENV === 'development') {
2900
2387
  warnRefusedValue(
@@ -2970,15 +2457,6 @@ const directStyleHandler: FlatValueHandler<GetStyleState> = {
2970
2457
  ) {
2971
2458
  if (isBase) {
2972
2459
  if (start === end) return
2973
- feedCompoundSegment(
2974
- state as DirectState,
2975
- source,
2976
- start,
2977
- end,
2978
- true,
2979
- valid || failure === 'invalid-character' || failure === 'stray-comment-close',
2980
- ''
2981
- )
2982
2460
  if (!valid) {
2983
2461
  if (failure === 'invalid-character' || failure === 'stray-comment-close') {
2984
2462
  // refusal belongs to the clause grammar. Keep only the decision until
@@ -3056,17 +2534,6 @@ const directStyleHandler: FlatValueHandler<GetStyleState> = {
3056
2534
  : conditionNumbers[cursor + conditionFlagsOffset] & conditionResolvedFlag
3057
2535
  ? conditionNumbers[cursor + conditionValueOffset]
3058
2536
  : 0
3059
- feedCompoundSegment(
3060
- directState,
3061
- source,
3062
- start,
3063
- end,
3064
- false,
3065
- valid && Boolean(condition),
3066
- condition && directState.flatPass?.[passCompoundIndexes]
3067
- ? conditionTexts[cursor + conditionKeyOffset] || ''
3068
- : ''
3069
- )
3070
2537
  if (!condition) return
3071
2538
  if (!valid) {
3072
2539
  if (process.env.NODE_ENV === 'development') {
@@ -3175,7 +2642,7 @@ const directStyleHandler: FlatValueHandler<GetStyleState> = {
3175
2642
  process.env.NODE_ENV === 'development' &&
3176
2643
  !hasBase &&
3177
2644
  result & 4 &&
3178
- (property in tokenCategories.color || property in tokenCategoryByProperty) &&
2645
+ property in propToTokenCategoryCode &&
3179
2646
  splitComponents(source.slice(lastPayloadStart)).length > 1
3180
2647
  ) {
3181
2648
  warnOnce(
@@ -3350,9 +2817,6 @@ function tokenVariable(
3350
2817
  if (category) {
3351
2818
  const own = state.conf.tokensParsed[category]?.[lookupName]
3352
2819
  if (own) return fillTokenLookup(own, false, lookupName)
3353
- for (const sibling of ['color', 'space', 'size', 'radius', 'zIndex'] as const) {
3354
- if (sibling !== category && state.conf.tokensParsed[sibling]?.[lookupName]) return
3355
- }
3356
2820
  } else {
3357
2821
  const first = lookupName.charCodeAt(0)
3358
2822
  if ((first >= 48 && first <= 57) || first === 43 || first === 45 || first === 46) {
@@ -3371,7 +2835,7 @@ function tokenVariable(
3371
2835
  }
3372
2836
 
3373
2837
  // literal strings dominate authored values, and each pays tokenVariable's
3374
- // full miss path (category probe, sibling scans, theme lookups). Remember the
2838
+ // full miss path (category probe and theme lookups). Remember the
3375
2839
  // misses per (config revision, theme record, theme name); a supported registry
3376
2840
  // mutation bumps the revision and swaps the whole cache. Font-keyed
3377
2841
  // properties resolve through mutable per-pass fontFamily state and stay
@@ -3435,16 +2899,15 @@ function configuredValue(state: GetStyleState, property: string, raw: string): a
3435
2899
  if (misses.has(missKey)) return raw
3436
2900
  }
3437
2901
 
2902
+ if (process.env.NODE_ENV === 'development') {
2903
+ const category = getTokenCategoryForProperty(property)
2904
+ if (category && category !== 'color' && state.conf.tokensParsed.color?.[name]) {
2905
+ warnOnce(`"${name}" contributes to "color", not "${property}"`)
2906
+ }
2907
+ }
3438
2908
  const lookup = tokenVariable(state, property, name)
3439
2909
  if (!lookup || !isVariable(lookup.value)) {
3440
2910
  if (misses) misses.add(missKey)
3441
- if (
3442
- process.env.NODE_ENV === 'development' &&
3443
- tokenCategoryByProperty[property] &&
3444
- state.conf.tokensParsed.color?.[name]
3445
- ) {
3446
- warnOnce(`"${name}" contributes to "color", not "${property}"; keeping it literal`)
3447
- }
3448
2911
  return raw
3449
2912
  }
3450
2913
  const resolveValues =
@@ -3636,6 +3099,13 @@ function emitProperty(
3636
3099
  ) {
3637
3100
  const direct = state as DirectState
3638
3101
  const condition = cursor ? conditionNumbers[cursor + conditionValueOffset] : 0
3102
+ if (process.env.TAMAGUI_TARGET === 'web' && value === false && !condition) {
3103
+ clearDirectStyle(state, property)
3104
+ if (direct.flatStyleStaticConfig?.styledContextKeys?.has(property)) {
3105
+ ;(state.overriddenContextProps ||= {})[property] = false
3106
+ }
3107
+ return
3108
+ }
3639
3109
  if (condition & 4) (state.flatEnterKeys ||= new Set()).add(property)
3640
3110
  if (condition & 8) (state.flatExitKeys ||= new Set()).add(property)
3641
3111
 
@@ -3703,12 +3173,7 @@ function emitProperty(
3703
3173
  // a base CSS write displaces an earlier inline base for the property, but
3704
3174
  // never an inline conditional winner and never on a weak styled-default
3705
3175
  // restore: the style object is live during the streaming pass
3706
- if (
3707
- !condition &&
3708
- state.style &&
3709
- direct.flatWeakContribution !== true &&
3710
- !(direct.flatUsed && direct.flatUsed[property])
3711
- ) {
3176
+ if (!condition && state.style && !(direct.flatUsed && direct.flatUsed[property])) {
3712
3177
  delete state.style[property]
3713
3178
  }
3714
3179
  streamWriteCSS(state, property, value, cursor, originalValue)
@@ -4410,12 +3875,10 @@ function contributeStyleObjectInner(
4410
3875
  ) {
4411
3876
  const directState = state as DirectState
4412
3877
  const parent = (directState.flatPass?.[passParentCursor] as ConditionCursor) || null
4413
- const hasDefault = Object.prototype.hasOwnProperty.call(value, 'default')
3878
+ const hasDefault = 'default' in value
4414
3879
  let hasBase = false
4415
3880
  const base = hasDefault ? value.default : undefined
4416
3881
  if (base != null) {
4417
- const baseString = String(base)
4418
- feedCompoundSegment(directState, baseString, 0, baseString.length, true, true, '')
4419
3882
  emitAtParentCondition(state, property, base, merge, base, contextOnly)
4420
3883
  hasBase = true
4421
3884
  }
@@ -4449,18 +3912,6 @@ function contributeStyleObjectInner(
4449
3912
  1,
4450
3913
  payload
4451
3914
  )
4452
- const payloadString = String(payload)
4453
- feedCompoundSegment(
4454
- directState,
4455
- payloadString,
4456
- 0,
4457
- payloadString.length,
4458
- false,
4459
- Boolean(condition),
4460
- condition && directState.flatPass?.[passCompoundIndexes]
4461
- ? conditionTexts[cursor + conditionKeyOffset] || ''
4462
- : ''
4463
- )
4464
3915
  }
4465
3916
  releaseConditionCursors(watermark)
4466
3917
  }
@@ -4486,16 +3937,17 @@ function contributeValue(
4486
3937
  if (isConditionTransport(value)) {
4487
3938
  // a wrapping component's conditional contributions arrive as resolved
4488
3939
  // atoms: replay each into a cursor at this position, no text reparsed
4489
- if (value.hasBase) {
4490
- contributeValue(state, property, value.base, merge, value.base, contextOnly)
3940
+ if (value[transportHasBase]) {
3941
+ const base = value[transportBase]
3942
+ contributeValue(state, property, base, merge, base, contextOnly)
4491
3943
  }
4492
- for (let offset = 0; offset < value.entries.length; ) {
4493
- const entryValue = value.entries[offset]
3944
+ for (let offset = transportEntries; offset < value.length; ) {
3945
+ const entryValue = value[offset]
4494
3946
  const watermark = conditionCursorTop
4495
3947
  try {
4496
3948
  const cursor = acquireTransportCursor(
4497
3949
  state,
4498
- value.entries,
3950
+ value,
4499
3951
  offset,
4500
3952
  ((state as DirectState).flatPass?.[passParentCursor] as ConditionCursor) || null
4501
3953
  )
@@ -4544,8 +3996,7 @@ function contributeValue(
4544
3996
  }
4545
3997
  const isObjectValue =
4546
3998
  value && typeof value === 'object' && !Array.isArray(value) && !isVariable(value)
4547
- const objectHasDefault =
4548
- isObjectValue && Object.prototype.hasOwnProperty.call(value, 'default')
3999
+ const objectHasDefault = isObjectValue && 'default' in value
4549
4000
  const firstChild =
4550
4001
  isObjectValue && !objectHasDefault ? acquireConditionCursor(effective) : null
4551
4002
  if (
@@ -4696,40 +4147,37 @@ export function clearDirectStyle(state: GetStyleState, property: string) {
4696
4147
  // ── HOC clause transport ─────────────────────────────────────────────────────
4697
4148
  // A conditional contribution whose key the host cannot style hands the wrapped
4698
4149
  // component its RESOLVED atoms, never serialized condition text: the inner
4699
- // pass replays them straight into a cursor. Values are recognized only through
4700
- // a module-private WeakSet, so the transport cannot become publicly authorable.
4701
-
4702
- interface ConditionTransport {
4703
- hasBase: boolean
4704
- base: any
4705
- entries: unknown[]
4706
- }
4150
+ // pass replays them straight into a cursor. the private symbol makes the tuple
4151
+ // impossible to author through public style values.
4707
4152
 
4708
- const conditionTransports = new WeakSet<ConditionTransport>()
4153
+ const conditionTransportTag = Symbol()
4154
+ const transportHasBase = 1
4155
+ const transportBase = 2
4156
+ const transportEntries = 3
4157
+ const transportEntryWidth = 2
4158
+ type ConditionTransport = [typeof conditionTransportTag, boolean, any, ...unknown[]]
4709
4159
 
4710
4160
  function isConditionTransport(value: unknown): value is ConditionTransport {
4711
- return (
4712
- typeof value === 'object' &&
4713
- value !== null &&
4714
- conditionTransports.has(value as ConditionTransport)
4715
- )
4161
+ return Array.isArray(value) && value[0] === conditionTransportTag
4716
4162
  }
4717
4163
 
4718
- const transportEntryWidth = 2
4719
-
4720
- function appendConditionEntry(entries: unknown[], cursor: ConditionCursor, value: any) {
4721
- entries.push(value, conditionTexts[cursor + conditionKeyOffset] || '')
4164
+ function appendConditionEntry(
4165
+ transport: ConditionTransport,
4166
+ cursor: ConditionCursor,
4167
+ value: any
4168
+ ) {
4169
+ transport.push(value, conditionTexts[cursor + conditionKeyOffset] || '')
4722
4170
  }
4723
4171
 
4724
4172
  /** rebuild a transported clause's cursor by re-parsing its canonical key */
4725
4173
  function acquireTransportCursor(
4726
4174
  state: GetStyleState,
4727
- entries: unknown[],
4175
+ transport: ConditionTransport,
4728
4176
  offset: number,
4729
4177
  parent: ConditionCursor | null
4730
4178
  ): ConditionCursor {
4731
4179
  const cursor = acquireConditionCursor(parent)
4732
- const key = entries[offset + 1] as string
4180
+ const key = transport[offset + 1] as string
4733
4181
  if (key) resolveConditionText(state, cursor, key)
4734
4182
  commitConditionCursor(state, cursor)
4735
4183
  return cursor
@@ -4745,13 +4193,11 @@ function mergeConditionTransport(
4745
4193
  if (isConditionTransport(prev)) {
4746
4194
  transport = prev
4747
4195
  } else {
4748
- transport = { hasBase: false, base: undefined, entries: [] }
4749
- conditionTransports.add(transport)
4196
+ transport = [conditionTransportTag, false, undefined]
4750
4197
  if (prev != null) {
4751
4198
  const isObjectValue =
4752
4199
  typeof prev === 'object' && !Array.isArray(prev) && !isVariable(prev)
4753
- const objectHasDefault =
4754
- isObjectValue && Object.prototype.hasOwnProperty.call(prev, 'default')
4200
+ const objectHasDefault = isObjectValue && 'default' in prev
4755
4201
  const authoredWatermark = conditionCursorTop
4756
4202
  try {
4757
4203
  const firstCursor =
@@ -4772,8 +4218,8 @@ function mergeConditionTransport(
4772
4218
  const payload = (prev as Record<string, any>)[key]
4773
4219
  if (payload == null) continue
4774
4220
  if (key === 'default') {
4775
- transport.hasBase = true
4776
- transport.base = payload
4221
+ transport[transportHasBase] = true
4222
+ transport[transportBase] = payload
4777
4223
  continue
4778
4224
  }
4779
4225
  const watermark = conditionCursorTop
@@ -4784,12 +4230,12 @@ function mergeConditionTransport(
4784
4230
  resolveConditionText(state, keyCursor, key)
4785
4231
  commitConditionCursor(state, keyCursor)
4786
4232
  }
4787
- appendConditionEntry(transport.entries, keyCursor, payload)
4233
+ appendConditionEntry(transport, keyCursor, payload)
4788
4234
  if (keyCursor !== firstCursor) releaseConditionCursors(watermark)
4789
4235
  }
4790
4236
  } else {
4791
- transport.hasBase = true
4792
- transport.base = prev
4237
+ transport[transportHasBase] = true
4238
+ transport[transportBase] = prev
4793
4239
  }
4794
4240
  } finally {
4795
4241
  releaseConditionCursors(authoredWatermark)
@@ -4799,13 +4245,17 @@ function mergeConditionTransport(
4799
4245
  // a repeat contribution under the same condition set replaces its entry and
4800
4246
  // moves to the end: the wrapped pass sees last-wins in authored order
4801
4247
  const cursorKey = conditionTexts[cursor + conditionKeyOffset] || ''
4802
- for (let offset = 0; offset < transport.entries.length; offset += transportEntryWidth) {
4803
- if (transport.entries[offset + 1] === cursorKey) {
4804
- transport.entries.splice(offset, transportEntryWidth)
4248
+ for (
4249
+ let offset = transportEntries;
4250
+ offset < transport.length;
4251
+ offset += transportEntryWidth
4252
+ ) {
4253
+ if (transport[offset + 1] === cursorKey) {
4254
+ transport.splice(offset, transportEntryWidth)
4805
4255
  break
4806
4256
  }
4807
4257
  }
4808
- appendConditionEntry(transport.entries, cursor, value)
4258
+ appendConditionEntry(transport, cursor, value)
4809
4259
  return transport
4810
4260
  }
4811
4261
 
@@ -4814,10 +4264,8 @@ type VariantScanContext = [GetStyleState, string, string]
4814
4264
  const variantValueHandler: FlatValueHandler<VariantScanContext> = {
4815
4265
  segment(ctx, start, end, isBase, valid, source, chainStart, chainEnd, chainValid) {
4816
4266
  const state = ctx[0]
4817
- const directState = state as DirectState
4818
4267
  if (start === end) return
4819
4268
  if (isBase) {
4820
- feedCompoundSegment(directState, source, start, end, true, valid, '')
4821
4269
  if (!valid) return
4822
4270
  emitResolvedVariant(ctx[1], source.slice(start, end), state, ctx[2], null)
4823
4271
  return
@@ -4825,22 +4273,11 @@ const variantValueHandler: FlatValueHandler<VariantScanContext> = {
4825
4273
  if (!valid || !chainValid) return
4826
4274
  // the clause's own condition: parent composition happens downstream where
4827
4275
  // the resolved output emits, exactly like every other conditional value
4828
- const cursor = directState.flatScanCursor
4276
+ const cursor = (state as DirectState).flatScanCursor
4829
4277
  const condition =
4830
4278
  cursor && conditionNumbers[cursor + conditionFlagsOffset] & conditionResolvedFlag
4831
4279
  ? conditionNumbers[cursor + conditionValueOffset]
4832
4280
  : 0
4833
- feedCompoundSegment(
4834
- directState,
4835
- source,
4836
- start,
4837
- end,
4838
- false,
4839
- Boolean(condition),
4840
- condition && directState.flatPass?.[passCompoundIndexes]
4841
- ? conditionTexts[cursor! + conditionKeyOffset] || ''
4842
- : ''
4843
- )
4844
4281
  if (!condition) return
4845
4282
  emitResolvedVariant(ctx[1], source.slice(start, end), state, ctx[2], cursor!)
4846
4283
  },
@@ -4872,42 +4309,6 @@ const variantValueHandler: FlatValueHandler<VariantScanContext> = {
4872
4309
  },
4873
4310
  }
4874
4311
 
4875
- // per-staticConfig union of every key the styled context declares, cached so
4876
- // context-membership checks on the style write path are one Set lookup instead
4877
- // of re-deriving config each time (issues #3670, #3676)
4878
- const contextPropSets = new WeakMap<StaticConfig, Set<string> | null>()
4879
- export function getContextPropSet(staticConfig: StaticConfig): Set<string> | null {
4880
- const cached = contextPropSets.get(staticConfig)
4881
- if (cached !== undefined) return cached
4882
- const contextConfig = staticConfig.context || staticConfig.parentStaticConfig?.context
4883
- const inheritedContextPropKeys =
4884
- !staticConfig.context ||
4885
- staticConfig.context === staticConfig.parentStaticConfig?.context
4886
- ? staticConfig.parentStaticConfig?.contextProps
4887
- : undefined
4888
- const contextPropKeys = staticConfig.contextProps || inheritedContextPropKeys
4889
- let set: Set<string> | null = null
4890
- if (contextConfig?.props) {
4891
- set ||= new Set()
4892
- for (const key in contextConfig.props) set.add(key)
4893
- }
4894
- if (contextPropKeys) {
4895
- set ||= new Set()
4896
- for (const key of contextPropKeys) set.add(key)
4897
- }
4898
- if (contextConfig?.propKeys) {
4899
- set ||= new Set()
4900
- for (const key of contextConfig.propKeys) set.add(key)
4901
- }
4902
- const parentPropKeys = staticConfig.parentStaticConfig?.context?.propKeys
4903
- if (parentPropKeys) {
4904
- set ||= new Set()
4905
- for (const key of parentPropKeys) set.add(key)
4906
- }
4907
- contextPropSets.set(staticConfig, set)
4908
- return set
4909
- }
4910
-
4911
4312
  function emitMappedValue(
4912
4313
  styleState: GetStyleState,
4913
4314
  key: string,
@@ -4965,8 +4366,8 @@ const contributeMappedValue: PropMapper = (
4965
4366
  )
4966
4367
  }
4967
4368
 
4968
- const { conf, styleProps, staticConfig } = styleState
4969
- const { variants } = staticConfig
4369
+ const { conf, styleProps } = styleState
4370
+ const variants = (styleState as DirectState).flatStyleStaticConfig!.variants
4970
4371
  const { disableExpandShorthands, noExpand, resolveValues } = styleProps
4971
4372
  const shorthands = conf.shorthands
4972
4373
 
@@ -5093,18 +4494,20 @@ function resolveVariants(
5093
4494
  styleState: GetStyleState,
5094
4495
  parentVariantKey: string
5095
4496
  ) {
5096
- const variantDefinition = styleState.staticConfig.variants?.[key]
4497
+ const variantDefinition = (styleState as DirectState).flatStyleStaticConfig!.variants?.[
4498
+ key
4499
+ ]
5097
4500
  if (isConditionTransport(value)) {
5098
4501
  // conditional variant selections transported through an HOC: resolve each
5099
4502
  // branch under its replayed condition
5100
- if (value.hasBase) {
5101
- emitResolvedVariant(key, value.base, styleState, parentVariantKey, null)
4503
+ if (value[transportHasBase]) {
4504
+ emitResolvedVariant(key, value[transportBase], styleState, parentVariantKey, null)
5102
4505
  }
5103
- for (let offset = 0; offset < value.entries.length; ) {
5104
- const entryValue = value.entries[offset]
4506
+ for (let offset = transportEntries; offset < value.length; ) {
4507
+ const entryValue = value[offset]
5105
4508
  const watermark = conditionCursorTop
5106
4509
  try {
5107
- const cursor = acquireTransportCursor(styleState, value.entries, offset, null)
4510
+ const cursor = acquireTransportCursor(styleState, value, offset, null)
5108
4511
  emitResolvedVariant(key, entryValue, styleState, parentVariantKey, cursor)
5109
4512
  } finally {
5110
4513
  releaseConditionCursors(watermark)
@@ -5142,8 +4545,7 @@ function resolveVariants(
5142
4545
  // argument shape) falls through whole
5143
4546
  const isObjectValue =
5144
4547
  value && typeof value === 'object' && !Array.isArray(value) && !isVariable(value)
5145
- const objectHasDefault =
5146
- isObjectValue && Object.prototype.hasOwnProperty.call(value, 'default')
4548
+ const objectHasDefault = isObjectValue && 'default' in value
5147
4549
  const objectWatermark = conditionCursorTop
5148
4550
  try {
5149
4551
  const firstCursor =
@@ -5156,18 +4558,7 @@ function resolveVariants(
5156
4558
  for (const objKey in value) {
5157
4559
  const payload = value[objKey]
5158
4560
  if (payload == null) continue
5159
- const directState = styleState as DirectState
5160
- const payloadString = String(payload)
5161
4561
  if (objKey === 'default') {
5162
- feedCompoundSegment(
5163
- directState,
5164
- payloadString,
5165
- 0,
5166
- payloadString.length,
5167
- true,
5168
- true,
5169
- ''
5170
- )
5171
4562
  emitResolvedVariant(key, payload, styleState, parentVariantKey, null)
5172
4563
  continue
5173
4564
  }
@@ -5180,17 +4571,6 @@ function resolveVariants(
5180
4571
  resolveConditionText(styleState, cursor, objKey)
5181
4572
  condition = commitConditionCursor(styleState, cursor)
5182
4573
  }
5183
- if (directState.flatPass?.[passCompoundIndexes]) {
5184
- feedCompoundSegment(
5185
- directState,
5186
- payloadString,
5187
- 0,
5188
- payloadString.length,
5189
- false,
5190
- Boolean(condition),
5191
- condition ? conditionTexts[cursor + conditionKeyOffset] || '' : ''
5192
- )
5193
- }
5194
4574
  // an unresolvable key still flows down as its (unresolved) cursor so the
5195
4575
  // downstream contribution warns and drops it, never emits unconditioned
5196
4576
  emitResolvedVariant(key, payload, styleState, parentVariantKey, cursor)
@@ -5212,37 +4592,15 @@ function emitResolvedVariant(
5212
4592
  parentVariantKey: string,
5213
4593
  conditionCursor: ConditionCursor | null
5214
4594
  ) {
5215
- const { staticConfig, conf, debug } = styleState
4595
+ const { conf, debug } = styleState
5216
4596
  const styleProps = styleState.styleProps
5217
- const { variants } = staticConfig
4597
+ const variants = (styleState as DirectState).flatStyleStaticConfig!.variants
5218
4598
  if (!variants) return
5219
4599
 
5220
4600
  const variant = variants[key]
5221
4601
  let variantValue = getVariantDefinition(variant, value, conf, styleState)
5222
4602
 
5223
- if (process.env.NODE_ENV === 'development' && debug === 'verbose') {
5224
- console.groupCollapsed(`♦️♦️♦️ resolve variant ${key}`)
5225
- console.info({
5226
- key,
5227
- value,
5228
- variantValue,
5229
- variants,
5230
- })
5231
- console.groupEnd()
5232
- }
5233
-
5234
4603
  if (!variantValue) {
5235
- // variant at key exists, but no matching variant
5236
- // disabling warnings, its fine to pass through, could re-enable later somehoiw
5237
- if (process.env.TAMAGUI_WARN_ON_MISSING_VARIANT === '1') {
5238
- // don't warn on missing booleans
5239
- if (typeof value !== 'boolean') {
5240
- const name = styleState.styleProps.displayName || '[UnnamedComponent]'
5241
- console.warn(
5242
- `No variant found: ${name} has variant "${key}", but no matching value "${value}"`
5243
- )
5244
- }
5245
- }
5246
4604
  return
5247
4605
  }
5248
4606
 
@@ -5269,43 +4627,38 @@ function emitResolvedVariant(
5269
4627
  }
5270
4628
  const { noSkip } = styleProps
5271
4629
  const originals = styleOriginalValues.get(variantValue)
5272
- const directState = styleState as DirectState
5273
- directState.flatCompoundOutputDepth = (directState.flatCompoundOutputDepth || 0) + 1
5274
- try {
5275
- for (const outputKey in variantValue) {
5276
- if (!noSkip && outputKey in skipProps) continue
5277
- // normalize per value at the variant boundary (numbers gain units on
5278
- // web, px-strings become numbers on native), the same normalization the
5279
- // materialized variant object received before streaming replaced it —
5280
- // atomic identity depends on it
5281
- const rawOutputValue = variantValue[outputKey]
5282
- const outputValue = styleProps.noNormalize
5283
- ? rawOutputValue
5284
- : normalizeValueWithProperty(
5285
- rawOutputValue,
5286
- conf.shorthands[outputKey] || outputKey
5287
- )
5288
- const originalValue = originals?.[outputKey] ?? rawOutputValue
5289
-
5290
- const contextPropSet = getContextPropSet(staticConfig)
5291
- if (contextPropSet?.has(outputKey)) {
5292
- styleState.overriddenContextProps ||= {}
5293
- styleState.overriddenContextProps[outputKey] = originalValue
5294
- styleState.originalContextPropValues ||= {}
5295
- styleState.originalContextPropValues[outputKey] = originalValue
5296
- }
4630
+ for (const outputKey in variantValue) {
4631
+ if (!noSkip && outputKey in skipProps) continue
4632
+ // normalize per value at the variant boundary (numbers gain units on
4633
+ // web, px-strings become numbers on native), the same normalization the
4634
+ // materialized variant object received before streaming replaced it —
4635
+ // atomic identity depends on it
4636
+ const rawOutputValue = variantValue[outputKey]
4637
+ const outputValue = styleProps.noNormalize
4638
+ ? rawOutputValue
4639
+ : normalizeValueWithProperty(
4640
+ rawOutputValue,
4641
+ conf.shorthands[outputKey] || outputKey
4642
+ )
4643
+ const originalValue = originals?.[outputKey] ?? rawOutputValue
5297
4644
 
5298
- contributeMappedValue(
5299
- outputKey,
5300
- outputValue,
5301
- styleState,
5302
- parentVariantKey === key && outputKey === key,
5303
- conditionCursor || undefined,
5304
- originalValue
5305
- )
4645
+ const contextPropSet = (styleState as DirectState).flatStyleStaticConfig!
4646
+ .styledContextKeys
4647
+ if (contextPropSet?.has(outputKey)) {
4648
+ styleState.overriddenContextProps ||= {}
4649
+ styleState.overriddenContextProps[outputKey] = originalValue
4650
+ styleState.originalContextPropValues ||= {}
4651
+ styleState.originalContextPropValues[outputKey] = originalValue
5306
4652
  }
5307
- } finally {
5308
- directState.flatCompoundOutputDepth!--
4653
+
4654
+ contributeMappedValue(
4655
+ outputKey,
4656
+ outputValue,
4657
+ styleState,
4658
+ parentVariantKey === key && outputKey === key,
4659
+ conditionCursor || undefined,
4660
+ originalValue
4661
+ )
5309
4662
  }
5310
4663
  }
5311
4664
 
@@ -5334,160 +4687,3 @@ const variableToFontNameCache = new WeakMap<Variable, string>()
5334
4687
  // the prop -> token-category tables live in their own module; re-exported
5335
4688
  // here because they have always been part of this module's public surface
5336
4689
  export * from './tokenCategories'
5337
-
5338
- // goes through specificity finding best matching variant function
5339
- function getVariantDefinition(
5340
- variant: any,
5341
- value: any,
5342
- conf: TamaguiInternalConfig,
5343
- { theme }: Partial<GetStyleState>
5344
- ): any {
5345
- if (!variant) return
5346
- if (value === undefined) return
5347
- if (typeof variant === 'function') {
5348
- return variant
5349
- }
5350
- if (Object.prototype.hasOwnProperty.call(variant, value)) {
5351
- return variant[value]
5352
- }
5353
- for (const { key, parts } of getCompiledVariantResolvers(variant)) {
5354
- for (const part of parts) {
5355
- if (matchesVariantResolver(part, value, conf, theme)) {
5356
- return variant[key]
5357
- }
5358
- }
5359
- }
5360
-
5361
- return
5362
- }
5363
-
5364
- type VariantResolverName = (typeof variantResolverNames)[number]
5365
-
5366
- const variantResolverNameSet = new Set<string>(variantResolverNames)
5367
-
5368
- type CompiledVariantResolver = {
5369
- key: string
5370
- parts: VariantResolverName[]
5371
- }
5372
-
5373
- const variantResolverCache = new WeakMap<object, readonly CompiledVariantResolver[]>()
5374
-
5375
- const preparedStyleStaticConfigs = new WeakSet<StaticConfig>()
5376
-
5377
- export function prepareStyleStaticConfig(staticConfig: StaticConfig): StaticConfig {
5378
- if (preparedStyleStaticConfigs.has(staticConfig)) return staticConfig
5379
- preparedStyleStaticConfigs.add(staticConfig)
5380
- getContextPropSet(staticConfig)
5381
- prepareStaticConfigCompounds(staticConfig)
5382
- const variants = staticConfig.variants
5383
- if (variants) {
5384
- for (const key in variants) {
5385
- const variant = variants[key]
5386
- if (variant && typeof variant === 'object') getCompiledVariantResolvers(variant)
5387
- }
5388
- }
5389
- return staticConfig
5390
- }
5391
-
5392
- function getCompiledVariantResolvers(variant: object) {
5393
- let cached = variantResolverCache.get(variant)
5394
- if (cached) {
5395
- return cached
5396
- }
5397
- const compiled: CompiledVariantResolver[] = []
5398
- for (const key in variant) {
5399
- const parts = parseVariantResolverKey(key)
5400
- if (parts) {
5401
- compiled.push({ key, parts })
5402
- }
5403
- }
5404
- variantResolverCache.set(variant, compiled)
5405
- return compiled
5406
- }
5407
-
5408
- function parseVariantResolverKey(key: string): VariantResolverName[] | null {
5409
- if (!key) return null
5410
- const parts: VariantResolverName[] = []
5411
- let start = 0
5412
- for (let index = 0; index <= key.length; index++) {
5413
- if (index !== key.length && key.charCodeAt(index) !== 124) continue
5414
- let partStart = start
5415
- let partEnd = index
5416
- while (partStart < partEnd && key.charCodeAt(partStart) <= 32) partStart++
5417
- while (partEnd > partStart && key.charCodeAt(partEnd - 1) <= 32) partEnd--
5418
- if (partStart === partEnd) return null
5419
- const part = key.slice(partStart, partEnd)
5420
- if (!variantResolverNameSet.has(part)) return null
5421
- parts.push(part as VariantResolverName)
5422
- start = index + 1
5423
- }
5424
- return parts
5425
- }
5426
-
5427
- function hasNumericPrefix(value: string, suffixLength: number): boolean {
5428
- if (value.length <= suffixLength) return false
5429
- return Number.isFinite(Number(value.slice(0, value.length - suffixLength)))
5430
- }
5431
-
5432
- function matchesVariantResolver(
5433
- resolverName: VariantResolverName,
5434
- value: any,
5435
- conf: TamaguiInternalConfig,
5436
- theme: Partial<GetStyleState>['theme']
5437
- ) {
5438
- const string = typeof value === 'string'
5439
- const number = typeof value === 'number'
5440
- const rem = string && value.endsWith('rem') && hasNumericPrefix(value, 3)
5441
-
5442
- switch (resolverName) {
5443
- case 'Size':
5444
- case 'Space':
5445
- case 'Radius':
5446
- case 'ZIndex':
5447
- // styles are authored by devs and never validated at runtime: any number
5448
- // or string routes to the token variant, which passes unknown values
5449
- // through. Size keeps its historical variable exclusion so variables
5450
- // route to the Space/Radius/ZIndex fallbacks.
5451
- return (
5452
- value === true ||
5453
- number ||
5454
- string ||
5455
- (resolverName !== 'Size' && isVariable(value))
5456
- )
5457
- // a token or theme color, otherwise any string is taken to be a raw CSS
5458
- // color and left for the browser to resolve. checking that against a CSS
5459
- // color-name table costs 2.3KB gzip to reject values that were never valid
5460
- // anyway. `red/50` opacity modifiers stay limited to token and theme
5461
- // colors, which the branches above already covered.
5462
- case 'Color':
5463
- return (value != null && value in conf.tokensParsed.color) || string
5464
- case 'Theme':
5465
- return string && !!theme && value in theme
5466
- case 'FontSize':
5467
- return value === true || !!conf.fontsParsed.body?.size?.[value] || number || rem
5468
- case 'FontStyle':
5469
- return (
5470
- !!conf.fontsParsed.body?.style?.[value] ||
5471
- value === 'normal' ||
5472
- value === 'italic'
5473
- )
5474
- case 'FontTransform':
5475
- return (
5476
- !!conf.fontsParsed.body?.transform?.[value] ||
5477
- value === 'none' ||
5478
- value === 'capitalize' ||
5479
- value === 'uppercase' ||
5480
- value === 'lowercase'
5481
- )
5482
- case 'FontLineHeight':
5483
- return !!conf.fontsParsed.body?.lineHeight?.[value] || number || rem
5484
- case 'FontLetterSpacing':
5485
- return !!conf.fontsParsed.body?.letterSpacing?.[value] || number || rem
5486
- case 'number':
5487
- case 'string':
5488
- case 'boolean':
5489
- return typeof value === resolverName
5490
- case 'any':
5491
- return true
5492
- }
5493
- }