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