@tamagui/static 2.7.7 → 3.0.0-beta.643.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 (329) hide show
  1. package/dist/cjs/check-dep-versions.cjs +355 -0
  2. package/dist/cjs/checkDeps.cjs +302 -0
  3. package/dist/cjs/compiler.cjs +286 -0
  4. package/dist/cjs/compilerHost.cjs +1695 -0
  5. package/dist/cjs/constants.cjs +33 -0
  6. package/dist/cjs/domStructuralPass.cjs +112 -0
  7. package/dist/cjs/exports.cjs +42 -0
  8. package/dist/cjs/extractor/addLocalExports.cjs +64 -0
  9. package/dist/cjs/extractor/bundle.cjs +203 -0
  10. package/dist/cjs/extractor/bundleConfig.cjs +747 -0
  11. package/dist/cjs/extractor/concatClassName.cjs +117 -0
  12. package/dist/cjs/extractor/detectModuleFormat.cjs +54 -0
  13. package/dist/cjs/extractor/esbuildAliasPlugin.cjs +47 -0
  14. package/dist/cjs/extractor/esbuildTsconfigPaths.cjs +92 -0
  15. package/dist/cjs/extractor/getTamaguiConfigPathFromOptionsConfig.cjs +38 -0
  16. package/dist/cjs/extractor/loadTamagui.cjs +344 -0
  17. package/dist/cjs/extractor/regenerateConfig.cjs +161 -0
  18. package/dist/cjs/extractor/watchTamaguiConfig.cjs +64 -0
  19. package/dist/cjs/getPragmaOptions.cjs +67 -0
  20. package/dist/cjs/helpers/memoize.cjs +42 -0
  21. package/dist/cjs/helpers/requireTamaguiCore.cjs +40 -0
  22. package/dist/cjs/index.cjs +34 -0
  23. package/dist/cjs/registerRequire.cjs +220 -0
  24. package/dist/cjs/server.cjs +66 -0
  25. package/dist/cjs/staticEvaluationIgnoredModules.cjs +86 -0
  26. package/dist/cjs/types.cjs +17 -0
  27. package/dist/cjs/zero/artifact.cjs +145 -0
  28. package/dist/cjs/zero/graph.cjs +209 -0
  29. package/dist/cjs/zero/identity.cjs +61 -0
  30. package/dist/cjs/zero/index.cjs +26 -0
  31. package/dist/cjs/zero/islands.cjs +232 -0
  32. package/dist/cjs/zero/options.cjs +163 -0
  33. package/dist/cjs/zero/ownership.cjs +79 -0
  34. package/dist/cjs/zero/theme.cjs +328 -0
  35. package/dist/cjs/zero/transform.cjs +203 -0
  36. package/dist/esm/check-dep-versions.mjs +329 -0
  37. package/dist/esm/check-dep-versions.mjs.map +1 -0
  38. package/dist/esm/checkDeps.mjs +279 -0
  39. package/dist/esm/checkDeps.mjs.map +1 -0
  40. package/dist/esm/compiler.mjs +255 -0
  41. package/dist/esm/compiler.mjs.map +1 -0
  42. package/dist/esm/compilerHost.mjs +1675 -0
  43. package/dist/esm/compilerHost.mjs.map +1 -0
  44. package/dist/esm/constants.mjs +7 -0
  45. package/dist/esm/constants.mjs.map +1 -0
  46. package/dist/esm/domStructuralPass.mjs +92 -0
  47. package/dist/esm/domStructuralPass.mjs.map +1 -0
  48. package/dist/esm/exports.mjs +26 -0
  49. package/dist/esm/extractor/addLocalExports.mjs +44 -0
  50. package/dist/esm/extractor/addLocalExports.mjs.map +1 -0
  51. package/dist/esm/extractor/bundle.mjs +173 -0
  52. package/dist/esm/extractor/bundle.mjs.map +1 -0
  53. package/dist/esm/extractor/bundleConfig.mjs +706 -0
  54. package/dist/esm/extractor/bundleConfig.mjs.map +1 -0
  55. package/dist/esm/extractor/concatClassName.mjs +96 -0
  56. package/dist/esm/extractor/concatClassName.mjs.map +1 -0
  57. package/dist/esm/extractor/detectModuleFormat.mjs +31 -0
  58. package/dist/esm/extractor/detectModuleFormat.mjs.map +1 -0
  59. package/dist/esm/extractor/esbuildAliasPlugin.mjs +26 -0
  60. package/dist/esm/extractor/esbuildAliasPlugin.mjs.map +1 -0
  61. package/dist/esm/extractor/esbuildTsconfigPaths.mjs +63 -0
  62. package/dist/esm/extractor/esbuildTsconfigPaths.mjs.map +1 -0
  63. package/dist/esm/extractor/getTamaguiConfigPathFromOptionsConfig.mjs +18 -0
  64. package/dist/esm/extractor/getTamaguiConfigPathFromOptionsConfig.mjs.map +1 -0
  65. package/dist/esm/extractor/loadTamagui.mjs +306 -0
  66. package/dist/esm/extractor/loadTamagui.mjs.map +1 -0
  67. package/dist/esm/extractor/regenerateConfig.mjs +131 -0
  68. package/dist/esm/extractor/regenerateConfig.mjs.map +1 -0
  69. package/dist/esm/extractor/watchTamaguiConfig.mjs +43 -0
  70. package/dist/esm/extractor/watchTamaguiConfig.mjs.map +1 -0
  71. package/dist/esm/getPragmaOptions.mjs +46 -0
  72. package/dist/esm/getPragmaOptions.mjs.map +1 -0
  73. package/dist/esm/helpers/memoize.mjs +21 -0
  74. package/dist/esm/helpers/memoize.mjs.map +1 -0
  75. package/dist/esm/helpers/requireTamaguiCore.mjs +19 -0
  76. package/dist/esm/helpers/requireTamaguiCore.mjs.map +1 -0
  77. package/dist/esm/index.mjs +8 -0
  78. package/dist/esm/index.mjs.map +1 -0
  79. package/dist/esm/registerRequire.mjs +195 -0
  80. package/dist/esm/registerRequire.mjs.map +1 -0
  81. package/dist/esm/server.mjs +40 -0
  82. package/dist/esm/server.mjs.map +1 -0
  83. package/dist/esm/setup.mjs +0 -0
  84. package/dist/esm/staticEvaluationIgnoredModules.mjs +61 -0
  85. package/dist/esm/staticEvaluationIgnoredModules.mjs.map +1 -0
  86. package/dist/esm/types.mjs +0 -0
  87. package/dist/esm/zero/artifact.mjs +119 -0
  88. package/dist/esm/zero/artifact.mjs.map +1 -0
  89. package/dist/esm/zero/graph.mjs +170 -0
  90. package/dist/esm/zero/graph.mjs.map +1 -0
  91. package/dist/esm/zero/identity.mjs +36 -0
  92. package/dist/esm/zero/identity.mjs.map +1 -0
  93. package/dist/esm/zero/index.mjs +15 -0
  94. package/dist/esm/zero/islands.mjs +197 -0
  95. package/dist/esm/zero/islands.mjs.map +1 -0
  96. package/dist/esm/zero/options.mjs +129 -0
  97. package/dist/esm/zero/options.mjs.map +1 -0
  98. package/dist/esm/zero/ownership.mjs +48 -0
  99. package/dist/esm/zero/ownership.mjs.map +1 -0
  100. package/dist/esm/zero/theme.mjs +303 -0
  101. package/dist/esm/zero/theme.mjs.map +1 -0
  102. package/dist/esm/zero/transform.mjs +177 -0
  103. package/dist/esm/zero/transform.mjs.map +1 -0
  104. package/package.json +33 -43
  105. package/src/check-dep-versions.ts +2 -2
  106. package/src/checkDeps.ts +3 -2
  107. package/src/compiler.ts +425 -0
  108. package/src/compilerHost.ts +3125 -0
  109. package/src/constants.ts +0 -5
  110. package/src/domStructuralPass.ts +170 -0
  111. package/src/exports.ts +3 -6
  112. package/src/extractor/addLocalExports.ts +49 -0
  113. package/src/extractor/bundle.ts +20 -35
  114. package/src/extractor/bundleConfig.ts +334 -187
  115. package/src/extractor/concatClassName.ts +13 -20
  116. package/src/extractor/getTamaguiConfigPathFromOptionsConfig.ts +5 -4
  117. package/src/extractor/loadTamagui.ts +196 -143
  118. package/src/extractor/regenerateConfig.ts +65 -13
  119. package/src/extractor/watchTamaguiConfig.ts +6 -1
  120. package/src/helpers/requireTamaguiCore.ts +6 -1
  121. package/src/registerRequire.ts +94 -132
  122. package/src/staticEvaluationIgnoredModules.ts +74 -0
  123. package/src/types.ts +2 -107
  124. package/src/zero/artifact.ts +142 -0
  125. package/src/zero/graph.ts +359 -0
  126. package/src/zero/identity.ts +73 -0
  127. package/src/zero/index.ts +8 -0
  128. package/src/zero/islands.ts +262 -0
  129. package/src/zero/options.ts +239 -0
  130. package/src/zero/ownership.ts +113 -0
  131. package/src/zero/theme.ts +478 -0
  132. package/src/zero/transform.ts +320 -0
  133. package/types/check-dep-versions.d.ts.map +1 -1
  134. package/types/checkDeps.d.ts.map +1 -1
  135. package/types/compiler.d.ts +117 -0
  136. package/types/compiler.d.ts.map +1 -0
  137. package/types/compilerHost.d.ts +25 -0
  138. package/types/compilerHost.d.ts.map +1 -0
  139. package/types/constants.d.ts +0 -1
  140. package/types/constants.d.ts.map +1 -1
  141. package/types/domStructuralPass.d.ts +3 -0
  142. package/types/domStructuralPass.d.ts.map +1 -0
  143. package/types/exports.d.ts +3 -6
  144. package/types/exports.d.ts.map +1 -1
  145. package/types/extractor/addLocalExports.d.ts +3 -0
  146. package/types/extractor/addLocalExports.d.ts.map +1 -0
  147. package/types/extractor/bundle.d.ts +66 -65
  148. package/types/extractor/bundle.d.ts.map +1 -1
  149. package/types/extractor/bundleConfig.d.ts +19 -4
  150. package/types/extractor/bundleConfig.d.ts.map +1 -1
  151. package/types/extractor/esbuildAliasPlugin.d.ts.map +1 -1
  152. package/types/extractor/getTamaguiConfigPathFromOptionsConfig.d.ts +1 -1
  153. package/types/extractor/getTamaguiConfigPathFromOptionsConfig.d.ts.map +1 -1
  154. package/types/extractor/loadTamagui.d.ts +26 -3
  155. package/types/extractor/loadTamagui.d.ts.map +1 -1
  156. package/types/extractor/regenerateConfig.d.ts +1 -1
  157. package/types/extractor/regenerateConfig.d.ts.map +1 -1
  158. package/types/extractor/watchTamaguiConfig.d.ts.map +1 -1
  159. package/types/getPragmaOptions.d.ts +1 -1
  160. package/types/helpers/memoize.d.ts +1 -1
  161. package/types/helpers/memoize.d.ts.map +1 -1
  162. package/types/helpers/requireTamaguiCore.d.ts.map +1 -1
  163. package/types/index.d.ts.map +1 -1
  164. package/types/registerRequire.d.ts +2 -2
  165. package/types/registerRequire.d.ts.map +1 -1
  166. package/types/staticEvaluationIgnoredModules.d.ts +9 -0
  167. package/types/staticEvaluationIgnoredModules.d.ts.map +1 -0
  168. package/types/types.d.ts +2 -90
  169. package/types/types.d.ts.map +1 -1
  170. package/types/zero/artifact.d.ts +44 -0
  171. package/types/zero/artifact.d.ts.map +1 -0
  172. package/types/zero/graph.d.ts +139 -0
  173. package/types/zero/graph.d.ts.map +1 -0
  174. package/types/zero/identity.d.ts +33 -0
  175. package/types/zero/identity.d.ts.map +1 -0
  176. package/types/zero/index.d.ts +9 -0
  177. package/types/zero/index.d.ts.map +1 -0
  178. package/types/zero/islands.d.ts +56 -0
  179. package/types/zero/islands.d.ts.map +1 -0
  180. package/types/zero/options.d.ts +58 -0
  181. package/types/zero/options.d.ts.map +1 -0
  182. package/types/zero/ownership.d.ts +51 -0
  183. package/types/zero/ownership.d.ts.map +1 -0
  184. package/types/zero/theme.d.ts +83 -0
  185. package/types/zero/theme.d.ts.map +1 -0
  186. package/types/zero/transform.d.ts +53 -0
  187. package/types/zero/transform.d.ts.map +1 -0
  188. package/dist/check-dep-versions.cjs +0 -372
  189. package/dist/checkDeps.cjs +0 -271
  190. package/dist/constants.cjs +0 -51
  191. package/dist/exports.cjs +0 -48
  192. package/dist/extractor/accessSafe.cjs +0 -48
  193. package/dist/extractor/babelParse.cjs +0 -56
  194. package/dist/extractor/buildClassName.cjs +0 -86
  195. package/dist/extractor/bundle.cjs +0 -234
  196. package/dist/extractor/bundleConfig.cjs +0 -729
  197. package/dist/extractor/concatClassName.cjs +0 -129
  198. package/dist/extractor/createEvaluator.cjs +0 -88
  199. package/dist/extractor/createExtractor.cjs +0 -1968
  200. package/dist/extractor/createLogger.cjs +0 -50
  201. package/dist/extractor/detectModuleFormat.cjs +0 -55
  202. package/dist/extractor/ensureImportingConcat.cjs +0 -54
  203. package/dist/extractor/errors.cjs +0 -28
  204. package/dist/extractor/esbuildAliasPlugin.cjs +0 -56
  205. package/dist/extractor/esbuildTsconfigPaths.cjs +0 -108
  206. package/dist/extractor/evaluateAstNode.cjs +0 -128
  207. package/dist/extractor/extractHelpers.cjs +0 -182
  208. package/dist/extractor/extractMediaStyle.cjs +0 -169
  209. package/dist/extractor/extractToClassNames.cjs +0 -475
  210. package/dist/extractor/extractToNative.cjs +0 -369
  211. package/dist/extractor/findTopmostFunction.cjs +0 -43
  212. package/dist/extractor/generatedUid.cjs +0 -58
  213. package/dist/extractor/getPrefixLogs.cjs +0 -31
  214. package/dist/extractor/getPropValueFromAttributes.cjs +0 -85
  215. package/dist/extractor/getSourceModule.cjs +0 -100
  216. package/dist/extractor/getStaticBindingsForScope.cjs +0 -213
  217. package/dist/extractor/getTamaguiConfigPathFromOptionsConfig.cjs +0 -41
  218. package/dist/extractor/hasTopLevelAwait.cjs +0 -62
  219. package/dist/extractor/hoistClassNames.cjs +0 -76
  220. package/dist/extractor/literalToAst.cjs +0 -109
  221. package/dist/extractor/loadFile.cjs +0 -17
  222. package/dist/extractor/loadTamagui.cjs +0 -373
  223. package/dist/extractor/logLines.cjs +0 -43
  224. package/dist/extractor/normalizeTernaries.cjs +0 -100
  225. package/dist/extractor/propsToFontFamilyCache.cjs +0 -42
  226. package/dist/extractor/regenerateConfig.cjs +0 -178
  227. package/dist/extractor/removeUnusedHooks.cjs +0 -108
  228. package/dist/extractor/timer.cjs +0 -52
  229. package/dist/extractor/validHTMLAttributes.cjs +0 -79
  230. package/dist/extractor/watchTamaguiConfig.cjs +0 -70
  231. package/dist/getPragmaOptions.cjs +0 -73
  232. package/dist/helpers/memoize.cjs +0 -45
  233. package/dist/helpers/requireTamaguiCore.cjs +0 -40
  234. package/dist/index.cjs +0 -42
  235. package/dist/registerRequire.cjs +0 -209
  236. package/dist/server.cjs +0 -82
  237. package/dist/types.cjs +0 -18
  238. package/dist/worker.cjs +0 -111
  239. package/src/extractor/accessSafe.ts +0 -22
  240. package/src/extractor/babelParse.ts +0 -38
  241. package/src/extractor/buildClassName.ts +0 -76
  242. package/src/extractor/createEvaluator.ts +0 -82
  243. package/src/extractor/createExtractor.ts +0 -2970
  244. package/src/extractor/createLogger.ts +0 -41
  245. package/src/extractor/ensureImportingConcat.ts +0 -36
  246. package/src/extractor/errors.ts +0 -1
  247. package/src/extractor/evaluateAstNode.ts +0 -136
  248. package/src/extractor/extractHelpers.ts +0 -211
  249. package/src/extractor/extractMediaStyle.ts +0 -194
  250. package/src/extractor/extractToClassNames.ts +0 -733
  251. package/src/extractor/extractToNative.ts +0 -506
  252. package/src/extractor/findTopmostFunction.ts +0 -24
  253. package/src/extractor/generatedUid.ts +0 -41
  254. package/src/extractor/getPrefixLogs.ts +0 -9
  255. package/src/extractor/getPropValueFromAttributes.ts +0 -95
  256. package/src/extractor/getSourceModule.ts +0 -96
  257. package/src/extractor/getStaticBindingsForScope.ts +0 -237
  258. package/src/extractor/hasTopLevelAwait.ts +0 -28
  259. package/src/extractor/hoistClassNames.ts +0 -52
  260. package/src/extractor/literalToAst.ts +0 -85
  261. package/src/extractor/loadFile.ts +0 -17
  262. package/src/extractor/logLines.ts +0 -16
  263. package/src/extractor/normalizeTernaries.ts +0 -89
  264. package/src/extractor/propsToFontFamilyCache.ts +0 -18
  265. package/src/extractor/removeUnusedHooks.ts +0 -83
  266. package/src/extractor/timer.ts +0 -25
  267. package/src/extractor/validHTMLAttributes.ts +0 -52
  268. package/src/worker.ts +0 -142
  269. package/types/extractor/accessSafe.d.ts +0 -3
  270. package/types/extractor/accessSafe.d.ts.map +0 -1
  271. package/types/extractor/babelParse.d.ts +0 -5
  272. package/types/extractor/babelParse.d.ts.map +0 -1
  273. package/types/extractor/buildClassName.d.ts +0 -7
  274. package/types/extractor/buildClassName.d.ts.map +0 -1
  275. package/types/extractor/createEvaluator.d.ts +0 -12
  276. package/types/extractor/createEvaluator.d.ts.map +0 -1
  277. package/types/extractor/createExtractor.d.ts +0 -32
  278. package/types/extractor/createExtractor.d.ts.map +0 -1
  279. package/types/extractor/createLogger.d.ts +0 -3
  280. package/types/extractor/createLogger.d.ts.map +0 -1
  281. package/types/extractor/ensureImportingConcat.d.ts +0 -4
  282. package/types/extractor/ensureImportingConcat.d.ts.map +0 -1
  283. package/types/extractor/errors.d.ts +0 -3
  284. package/types/extractor/errors.d.ts.map +0 -1
  285. package/types/extractor/evaluateAstNode.d.ts +0 -3
  286. package/types/extractor/evaluateAstNode.d.ts.map +0 -1
  287. package/types/extractor/extractHelpers.d.ts +0 -28
  288. package/types/extractor/extractHelpers.d.ts.map +0 -1
  289. package/types/extractor/extractMediaStyle.d.ts +0 -11
  290. package/types/extractor/extractMediaStyle.d.ts.map +0 -1
  291. package/types/extractor/extractToClassNames.d.ts +0 -25
  292. package/types/extractor/extractToClassNames.d.ts.map +0 -1
  293. package/types/extractor/extractToNative.d.ts +0 -13
  294. package/types/extractor/extractToNative.d.ts.map +0 -1
  295. package/types/extractor/findTopmostFunction.d.ts +0 -4
  296. package/types/extractor/findTopmostFunction.d.ts.map +0 -1
  297. package/types/extractor/generatedUid.d.ts +0 -5
  298. package/types/extractor/generatedUid.d.ts.map +0 -1
  299. package/types/extractor/getPrefixLogs.d.ts +0 -3
  300. package/types/extractor/getPrefixLogs.d.ts.map +0 -1
  301. package/types/extractor/getPropValueFromAttributes.d.ts +0 -19
  302. package/types/extractor/getPropValueFromAttributes.d.ts.map +0 -1
  303. package/types/extractor/getSourceModule.d.ts +0 -16
  304. package/types/extractor/getSourceModule.d.ts.map +0 -1
  305. package/types/extractor/getStaticBindingsForScope.d.ts +0 -5
  306. package/types/extractor/getStaticBindingsForScope.d.ts.map +0 -1
  307. package/types/extractor/hasTopLevelAwait.d.ts +0 -2
  308. package/types/extractor/hasTopLevelAwait.d.ts.map +0 -1
  309. package/types/extractor/hoistClassNames.d.ts +0 -6
  310. package/types/extractor/hoistClassNames.d.ts.map +0 -1
  311. package/types/extractor/literalToAst.d.ts +0 -4
  312. package/types/extractor/literalToAst.d.ts.map +0 -1
  313. package/types/extractor/loadFile.d.ts +0 -1
  314. package/types/extractor/loadFile.d.ts.map +0 -1
  315. package/types/extractor/logLines.d.ts +0 -2
  316. package/types/extractor/logLines.d.ts.map +0 -1
  317. package/types/extractor/normalizeTernaries.d.ts +0 -5
  318. package/types/extractor/normalizeTernaries.d.ts.map +0 -1
  319. package/types/extractor/propsToFontFamilyCache.d.ts +0 -4
  320. package/types/extractor/propsToFontFamilyCache.d.ts.map +0 -1
  321. package/types/extractor/removeUnusedHooks.d.ts +0 -3
  322. package/types/extractor/removeUnusedHooks.d.ts.map +0 -1
  323. package/types/extractor/timer.d.ts +0 -5
  324. package/types/extractor/timer.d.ts.map +0 -1
  325. package/types/extractor/validHTMLAttributes.d.ts +0 -52
  326. package/types/extractor/validHTMLAttributes.d.ts.map +0 -1
  327. package/types/worker.d.ts +0 -46
  328. package/types/worker.d.ts.map +0 -1
  329. /package/dist/{setup.cjs → cjs/setup.cjs} +0 -0
@@ -0,0 +1,478 @@
1
+ import {
2
+ childNode,
3
+ childNodes,
4
+ resolvedModuleId,
5
+ walkAst,
6
+ zeroRuleMessage,
7
+ type AstNode,
8
+ type SourceEdit,
9
+ type ZeroViolation,
10
+ } from '@tamagui/compiler-core'
11
+ import { getThemeClassNames, reservedThemeProps } from '@tamagui/helpers'
12
+ import {
13
+ getInlineValuesFromProps,
14
+ getVariablesCSSRules,
15
+ resolveThemeName,
16
+ variableToString,
17
+ type InlineValueIssue,
18
+ type TamaguiInternalConfig,
19
+ } from '@tamagui/web'
20
+
21
+ import type { IslandThemeBridgeLayer } from './islands'
22
+
23
+ /**
24
+ * Static `<Theme>` lowering.
25
+ *
26
+ * A `<Theme>` node is markup plus classes and nothing else once its name and its
27
+ * direct theme-key values are known at build time. This resolves the name the
28
+ * way the runtime resolves it, emits the same span the runtime emits, and turns
29
+ * every value the parser cannot use into a violation rather than the warn-and-
30
+ * drop the render path does.
31
+ */
32
+
33
+ /**
34
+ * One branch of a `<Theme name>`. `test` is the source text of the condition
35
+ * that selects it, or null for the unconditional branch. A literal name is one
36
+ * option with a null test.
37
+ */
38
+ export interface ThemeNameOption {
39
+ test: string | null
40
+ name: string | undefined
41
+ }
42
+
43
+ export interface StaticThemeNode {
44
+ element: AstNode
45
+ opening: AstNode
46
+ closing: AstNode | null
47
+ options: ThemeNameOption[]
48
+ reset: boolean
49
+ contain: boolean
50
+ /** The compiled inline-value layer, when the node carries theme-key props. */
51
+ layer: IslandThemeBridgeLayer | null
52
+ }
53
+
54
+ /**
55
+ * The most branches one element's chain may enumerate.
56
+ *
57
+ * Rule 4 says a theme name must be statically enumerable, not that it must be
58
+ * literal. A chain of conditionals is still enumerable, but the emitted
59
+ * expression is one branch per combination, so it has to stop somewhere: past
60
+ * this the authored tree is asking for runtime theme state with extra steps.
61
+ */
62
+ const MAX_THEME_BRANCHES = 8
63
+
64
+ /**
65
+ * Reserved `<Theme>` props zero mode lowers. Everything else on the table is
66
+ * runtime behavior with no compiled form, including a `children` prop: the
67
+ * lowered span carries the element's body, not an attribute.
68
+ */
69
+ const LOWERABLE_RESERVED_PROPS = new Set(['name', 'reset', 'contain'])
70
+
71
+ function jsxAttributeName(attribute: AstNode): string | null {
72
+ const name = childNode(attribute, 'name')
73
+ return name && typeof name.name === 'string' ? name.name : null
74
+ }
75
+
76
+ function literalOf(node: AstNode | null): string | number | boolean | null | undefined {
77
+ if (!node) return undefined
78
+ if (node.type === 'Literal' && typeof node.value !== 'object') {
79
+ return node.value as string | number | boolean | null
80
+ }
81
+ return undefined
82
+ }
83
+
84
+ /**
85
+ * True when evaluating this expression twice could do something. The lowered
86
+ * className and style attributes each repeat the condition, so a condition that
87
+ * calls, assigns, or awaits would run more times than the author wrote it.
88
+ */
89
+ function hasSideEffects(node: AstNode): boolean {
90
+ let found = false
91
+ walkAst(node, (child) => {
92
+ if (
93
+ child.type === 'CallExpression' ||
94
+ child.type === 'OptionalCallExpression' ||
95
+ child.type === 'NewExpression' ||
96
+ child.type === 'AwaitExpression' ||
97
+ child.type === 'YieldExpression' ||
98
+ child.type === 'AssignmentExpression' ||
99
+ child.type === 'UpdateExpression' ||
100
+ child.type === 'TaggedTemplateExpression'
101
+ ) {
102
+ found = true
103
+ }
104
+ })
105
+ return found
106
+ }
107
+
108
+ /**
109
+ * Reads a `name` value into its branches. A literal is one branch; a conditional
110
+ * over literal names is one branch per arm, nested conditionals included.
111
+ */
112
+ function readNameOptions(
113
+ value: AstNode,
114
+ source: string,
115
+ guards: string[]
116
+ ): ThemeNameOption[] | null {
117
+ const literal = literalOf(value)
118
+ if (typeof literal === 'string') {
119
+ return [{ test: guards.length ? guards.join(' && ') : null, name: literal }]
120
+ }
121
+ if (value.type === 'ConditionalExpression') {
122
+ const test = childNode(value, 'test')
123
+ const consequent = childNode(value, 'consequent')
124
+ const alternate = childNode(value, 'alternate')
125
+ if (!test || !consequent || !alternate) return null
126
+ if (hasSideEffects(test)) return null
127
+ const testText = source.slice(test.start, test.end).replace(/\s+/g, ' ').trim()
128
+ const left = readNameOptions(consequent, source, [...guards, `(${testText})`])
129
+ const right = readNameOptions(alternate, source, [...guards, `!(${testText})`])
130
+ if (!left || !right) return null
131
+ return [...left, ...right]
132
+ }
133
+ return null
134
+ }
135
+
136
+ /**
137
+ * Folds one value per branch into a single expression. The branches are the
138
+ * product in authored order and the last one is exhaustive, so it is the
139
+ * ternary's else. Branches that agree collapse to a literal, which is what makes
140
+ * an ordinary literal `<Theme name="dark">` emit a plain string.
141
+ */
142
+ export function foldBranches(branches: { test: string | null; value: string }[]): string {
143
+ const last = branches[branches.length - 1]!
144
+ if (new Set(branches.map((branch) => branch.value)).size === 1) return last.value
145
+ let expression = last.value
146
+ for (let index = branches.length - 2; index >= 0; index--) {
147
+ const branch = branches[index]!
148
+ expression =
149
+ branch.test === null
150
+ ? branch.value
151
+ : `${branch.test} ? ${branch.value} : ${expression}`
152
+ }
153
+ return expression
154
+ }
155
+
156
+ /** One resolved theme name, with the guard that selects it. */
157
+ export interface ThemeBranch {
158
+ test: string | null
159
+ name: string
160
+ isNew: boolean
161
+ }
162
+
163
+ /**
164
+ * Every theme name an element's `<Theme>` ancestry can resolve to.
165
+ *
166
+ * The chain is root-most first and includes the element's own node when it has
167
+ * one. Each node contributes its branches; the result is their product, walked
168
+ * in authored order so a nested `<Theme name="blue">` resolves against whatever
169
+ * its parent resolved to, exactly as `resolveThemeName` does at runtime.
170
+ */
171
+ export function resolveThemeChain(
172
+ chain: readonly StaticThemeNode[],
173
+ rootThemeName: string,
174
+ config: TamaguiInternalConfig
175
+ ): ThemeBranch[] {
176
+ let branches: ThemeBranch[] = [{ test: null, name: rootThemeName, isNew: false }]
177
+ for (const node of chain) {
178
+ const next: typeof branches = []
179
+ for (const parent of branches) {
180
+ for (const option of node.options) {
181
+ const resolved = resolveThemeName(
182
+ parent.name,
183
+ option.name,
184
+ node.reset,
185
+ config.themes as Record<string, any>
186
+ )
187
+ const tests = [parent.test, option.test].filter(Boolean)
188
+ next.push({
189
+ test: tests.length ? tests.join(' && ') : null,
190
+ name: resolved ?? parent.name,
191
+ isNew: resolved !== null,
192
+ })
193
+ }
194
+ }
195
+ branches = next
196
+ }
197
+ return branches
198
+ }
199
+
200
+ export interface StaticThemeReadResult {
201
+ node: StaticThemeNode | null
202
+ violations: ZeroViolation[]
203
+ /** The CSS rules the node's inline values need, keyed by their class name. */
204
+ css: Map<string, string>
205
+ }
206
+
207
+ /**
208
+ * Reads one `<Theme>` element into its static description.
209
+ *
210
+ * Prop classification is `reservedThemeProps`, the same table the runtime reads,
211
+ * so a name that becomes reserved later cannot mean a theme key here and a
212
+ * reserved prop there.
213
+ */
214
+ export function readStaticTheme(
215
+ element: AstNode,
216
+ id: string,
217
+ source: string,
218
+ config: TamaguiInternalConfig
219
+ ): StaticThemeReadResult {
220
+ const moduleId = resolvedModuleId(id)
221
+ const violations: ZeroViolation[] = []
222
+ const css = new Map<string, string>()
223
+ const opening = childNode(element, 'openingElement')!
224
+ const closing = childNode(element, 'closingElement')
225
+
226
+ const span = (node: AstNode) => ({ id: moduleId, start: node.start, end: node.end })
227
+
228
+ let options: ThemeNameOption[] = [{ test: null, name: undefined }]
229
+ let reset = false
230
+ let contain = false
231
+ const themeKeyProps: Record<string, string | number> = {}
232
+
233
+ for (const attribute of childNodes(opening, 'attributes')) {
234
+ if (attribute.type !== 'JSXAttribute') {
235
+ violations.push({
236
+ rule: 1,
237
+ code: 'local/unsafe-style-spread',
238
+ span: span(attribute),
239
+ component: 'Theme',
240
+ message: zeroRuleMessage(1, { component: 'Theme' }),
241
+ })
242
+ continue
243
+ }
244
+ const key = jsxAttributeName(attribute)
245
+ if (!key) continue
246
+ const rawValue = childNode(attribute, 'value')
247
+ const value =
248
+ rawValue && rawValue.type === 'JSXExpressionContainer'
249
+ ? childNode(rawValue, 'expression')
250
+ : rawValue
251
+
252
+ if (key === 'name') {
253
+ const read = value ? readNameOptions(value, source, []) : null
254
+ if (!read) {
255
+ violations.push({
256
+ rule: 4,
257
+ code: 'local/unsupported-target',
258
+ span: span(attribute),
259
+ component: 'Theme',
260
+ message: zeroRuleMessage(4, {
261
+ detail: `the <Theme name> value ${source
262
+ .slice(attribute.start, attribute.end)
263
+ .replace(/\s+/g, ' ')
264
+ .trim()}, which is not a literal theme name or a conditional over literal theme names,`,
265
+ }),
266
+ })
267
+ continue
268
+ }
269
+ options = read
270
+ continue
271
+ }
272
+
273
+ if (reservedThemeProps[key]) {
274
+ if (!LOWERABLE_RESERVED_PROPS.has(key)) {
275
+ violations.push({
276
+ rule: 4,
277
+ code: 'local/unsupported-target',
278
+ span: span(attribute),
279
+ component: 'Theme',
280
+ message: zeroRuleMessage(4, {
281
+ detail: `the <Theme ${key}> prop, which has no compiled form,`,
282
+ }),
283
+ })
284
+ continue
285
+ }
286
+ // presence is the value for a bare boolean attribute
287
+ const literal = value ? literalOf(value) : true
288
+ if (typeof literal !== 'boolean') {
289
+ violations.push({
290
+ rule: 4,
291
+ code: 'local/unsupported-target',
292
+ span: span(attribute),
293
+ component: 'Theme',
294
+ message: zeroRuleMessage(4, {
295
+ detail: `a non-literal <Theme ${key}> value,`,
296
+ }),
297
+ })
298
+ continue
299
+ }
300
+ if (key === 'reset') reset = literal
301
+ if (key === 'contain') contain = literal
302
+ continue
303
+ }
304
+
305
+ // everything else is a theme key, and its value has to be build-time data
306
+ const literal = value ? literalOf(value) : undefined
307
+ if (typeof literal !== 'string' && typeof literal !== 'number') {
308
+ violations.push({
309
+ rule: 3,
310
+ code: 'local/dynamic-style-value',
311
+ span: span(attribute),
312
+ component: 'Theme',
313
+ message: zeroRuleMessage(3, {
314
+ prop: key,
315
+ component: 'Theme',
316
+ detail: value
317
+ ? 'a theme value must be a string or number literal at build time'
318
+ : 'a theme key needs a value',
319
+ }),
320
+ })
321
+ continue
322
+ }
323
+ themeKeyProps[key] = literal
324
+ }
325
+
326
+ // the runtime throws on this pair rather than picking one
327
+ if (reset && options.some((option) => option.name !== undefined)) {
328
+ violations.push({
329
+ rule: 4,
330
+ code: 'local/unsupported-target',
331
+ span: span(opening),
332
+ component: 'Theme',
333
+ message: zeroRuleMessage(4, {
334
+ detail: 'a <Theme> with both name and reset, which cannot mean one theme,',
335
+ }),
336
+ })
337
+ }
338
+
339
+ if (!closing) {
340
+ violations.push({
341
+ rule: 4,
342
+ code: 'local/unsupported-target',
343
+ span: span(element),
344
+ component: 'Theme',
345
+ message: zeroRuleMessage(4, {
346
+ detail: 'a self-closing <Theme>, which has no subtree to theme,',
347
+ }),
348
+ })
349
+ }
350
+
351
+ // One parse per unique authored value, and every clause the parser could not
352
+ // use is a violation here instead of the warn-and-drop the render path does.
353
+ const issues: InlineValueIssue[] = []
354
+ const inlineValues = Object.keys(themeKeyProps).length
355
+ ? getInlineValuesFromProps(themeKeyProps, config, (issue) => issues.push(issue))
356
+ : null
357
+ for (const issue of issues) {
358
+ violations.push({
359
+ rule: 3,
360
+ code: 'local/dynamic-style-value',
361
+ span: span(opening),
362
+ component: 'Theme',
363
+ message: zeroRuleMessage(3, {
364
+ prop: issue.key,
365
+ component: 'Theme',
366
+ detail: issue.message,
367
+ }),
368
+ })
369
+ }
370
+
371
+ const inlineCSS = inlineValues ? getVariablesCSSRules(inlineValues, config) : null
372
+ if (inlineCSS) css.set(inlineCSS.identifier, inlineCSS.rules.join(''))
373
+
374
+ if (violations.length) return { node: null, violations, css }
375
+
376
+ return {
377
+ node: {
378
+ element,
379
+ opening,
380
+ closing,
381
+ options,
382
+ reset,
383
+ contain,
384
+ layer:
385
+ inlineValues && inlineCSS
386
+ ? {
387
+ inlineValues: inlineValues as IslandThemeBridgeLayer['inlineValues'],
388
+ inlineClassName: inlineCSS.identifier,
389
+ }
390
+ : null,
391
+ },
392
+ violations,
393
+ css,
394
+ }
395
+ }
396
+
397
+ /**
398
+ * The span a static `<Theme>` lowers to.
399
+ *
400
+ * Same classes and same inline style the runtime span carries, because both are
401
+ * read by the same CSS: the theme classes select the named theme's variables,
402
+ * the inline-value class carries the direct props at the anchored specificity
403
+ * that lets it beat them, and `display: contents` keeps the span out of layout.
404
+ */
405
+ export function lowerStaticTheme(
406
+ node: StaticThemeNode,
407
+ chain: readonly StaticThemeNode[],
408
+ rootThemeName: string,
409
+ config: TamaguiInternalConfig,
410
+ id: string
411
+ ): { edits: SourceEdit[]; violations: ZeroViolation[] } {
412
+ const moduleId = resolvedModuleId(id)
413
+ const branches = resolveThemeChain(chain, rootThemeName, config)
414
+ if (branches.length > MAX_THEME_BRANCHES) {
415
+ return {
416
+ edits: [],
417
+ violations: [
418
+ {
419
+ rule: 4,
420
+ code: 'local/unsupported-target',
421
+ span: { id: moduleId, start: node.element.start, end: node.element.end },
422
+ component: 'Theme',
423
+ message: zeroRuleMessage(4, {
424
+ detail: `a <Theme> chain that enumerates ${branches.length} theme names, past the ${MAX_THEME_BRANCHES} this lowers,`,
425
+ }),
426
+ },
427
+ ],
428
+ }
429
+ }
430
+
431
+ const inlineClass = node.layer?.inlineClassName ?? ''
432
+ const classBranches = branches.map((branch) => ({
433
+ test: branch.test,
434
+ value: JSON.stringify(
435
+ [branch.isNew ? getThemeClassNames(branch.name) : '', 'is_Theme', inlineClass]
436
+ .filter(Boolean)
437
+ .join(' ')
438
+ .replace(/\s+/g, ' ')
439
+ .trim()
440
+ ),
441
+ }))
442
+
443
+ const baseStyle = node.contain
444
+ ? `display:"contents",contain:"strict"`
445
+ : `display:"contents"`
446
+ const styleBranches = branches.map((branch) => {
447
+ const theme = (config.themes as Record<string, any>)[branch.name]
448
+ const color = branch.isNew && theme ? variableToString(theme.color) : ''
449
+ return {
450
+ test: branch.test,
451
+ value: color ? `{color:${JSON.stringify(color)},${baseStyle}}` : `{${baseStyle}}`,
452
+ }
453
+ })
454
+
455
+ const className = foldBranches(classBranches)
456
+ const style = foldBranches(styleBranches)
457
+ const classAttribute = className.startsWith('"')
458
+ ? `className=${className}`
459
+ : `className={${className}}`
460
+
461
+ const edits: SourceEdit[] = [
462
+ {
463
+ start: node.opening.start,
464
+ end: node.opening.end,
465
+ content: `<span ${classAttribute} style={${style}}>`,
466
+ origin: { id: moduleId, start: node.opening.start, end: node.opening.end },
467
+ },
468
+ ]
469
+ if (node.closing) {
470
+ edits.push({
471
+ start: node.closing.start,
472
+ end: node.closing.end,
473
+ content: `</span>`,
474
+ origin: { id: moduleId, start: node.closing.start, end: node.closing.end },
475
+ })
476
+ }
477
+ return { edits, violations: [] }
478
+ }