@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,262 @@
1
+ import { mkdirSync, readFileSync, writeFileSync } from 'node:fs'
2
+ import path from 'node:path'
3
+
4
+ import type { ZeroIsland } from './options'
5
+
6
+ /**
7
+ * Island generation.
8
+ *
9
+ * An island is a full-runtime entry graph built in a separate bundler
10
+ * invocation. The zero graph never imports it; it imports a generated loader
11
+ * that owns the deterministic server placeholder, the shared React handoff, and
12
+ * the async fetch of the separately built island bundle.
13
+ */
14
+
15
+ export const ISLAND_RUNTIME_KEY = '__tamagui_island_runtime__'
16
+ export const ISLAND_REGISTRY_KEY = '__tamagui_islands__'
17
+
18
+ /** Block 3's normalized internal representation, produced at compile time. */
19
+ export interface IslandThemeBridgeLayer {
20
+ inlineValues: {
21
+ values: Record<string, string | number>
22
+ themes?: Record<string, Record<string, string | number>>
23
+ }
24
+ inlineClassName: string
25
+ }
26
+
27
+ export interface IslandThemeBridge {
28
+ id: string
29
+ name: string
30
+ layers: IslandThemeBridgeLayer[]
31
+ }
32
+
33
+ export interface IslandGenerationInput {
34
+ island: ZeroIsland
35
+ /** Names the integration in the loader's recovery diagnostic. */
36
+ integration: string
37
+ /** Absolute path of the app's tamagui config module. */
38
+ configPath: string
39
+ /** URL the loader fetches the built island bundle from. */
40
+ scriptUrl: string
41
+ /** URL of the one generated CSS artifact both entries load. */
42
+ cssHref: string
43
+ }
44
+
45
+ function writeIfChanged(file: string, content: string) {
46
+ mkdirSync(path.dirname(file), { recursive: true })
47
+ let existing: string | null = null
48
+ try {
49
+ existing = readFileSync(file, 'utf8')
50
+ } catch {
51
+ existing = null
52
+ }
53
+ if (existing !== content) writeFileSync(file, content)
54
+ }
55
+
56
+ function importPath(from: string, to: string) {
57
+ const relative = path.relative(path.dirname(from), to).replace(/\\/g, '/')
58
+ return relative.startsWith('.') ? relative : `./${relative}`
59
+ }
60
+
61
+ export function generateIslandLoaderSource(input: IslandGenerationInput): string {
62
+ return `// generated by @tamagui/static zero-runtime. do not edit.
63
+ import * as React from 'react'
64
+ import * as ReactDOM from 'react-dom'
65
+ import * as JSXRuntime from 'react/jsx-runtime'
66
+
67
+ const ISLAND_ID = ${JSON.stringify(input.island.id)}
68
+ const ISLAND_SRC = ${JSON.stringify(input.scriptUrl)}
69
+ const CSS_HREF = ${JSON.stringify(input.cssHref)}
70
+ const INTEGRATION = ${JSON.stringify(input.integration)}
71
+
72
+ function sharedRuntime() {
73
+ const scope = globalThis
74
+ if (!scope[${JSON.stringify(ISLAND_RUNTIME_KEY)}]) {
75
+ scope[${JSON.stringify(ISLAND_RUNTIME_KEY)}] = {
76
+ react: React,
77
+ reactDom: ReactDOM,
78
+ jsxRuntime: JSXRuntime,
79
+ }
80
+ }
81
+ if (!scope[${JSON.stringify(ISLAND_REGISTRY_KEY)}]) {
82
+ scope[${JSON.stringify(ISLAND_REGISTRY_KEY)}] = {}
83
+ }
84
+ return scope
85
+ }
86
+
87
+ // The one accepted runtime recovery in zero-runtime mode, and it is loud on
88
+ // purpose. "Unimported" is not decidable at build time for a published zero
89
+ // artifact on Next or Metro, so the loader still guarantees the island has its
90
+ // styles; on a correct build this never runs.
91
+ function ensureZeroStylesheet() {
92
+ const links = document.querySelectorAll('link[rel="stylesheet"]')
93
+ for (let index = 0; index < links.length; index++) {
94
+ const href = links[index].getAttribute('href') || ''
95
+ if (href === CSS_HREF || href.split('?')[0].endsWith(CSS_HREF)) return
96
+ }
97
+ console.error(
98
+ '[tamagui zero-runtime] the page did not link the generated CSS artifact ' +
99
+ CSS_HREF +
100
+ ', so island "' +
101
+ ISLAND_ID +
102
+ '" (' +
103
+ INTEGRATION +
104
+ ') is loading it at runtime. On a correct build this never happens: the ' +
105
+ 'artifact is generated by the build and must be linked by the document ' +
106
+ 'that mounts the island. Fix the document, not this recovery.'
107
+ )
108
+ const link = document.createElement('link')
109
+ link.rel = 'stylesheet'
110
+ link.href = CSS_HREF
111
+ link.setAttribute('data-tamagui-zero-css', '1')
112
+ document.head.appendChild(link)
113
+ }
114
+
115
+ let pending = null
116
+
117
+ function loadIsland() {
118
+ const scope = sharedRuntime()
119
+ const registered = scope[${JSON.stringify(ISLAND_REGISTRY_KEY)}][ISLAND_ID]
120
+ if (registered) return Promise.resolve(registered)
121
+ if (!pending) {
122
+ pending = new Promise((resolve, reject) => {
123
+ ensureZeroStylesheet()
124
+ const script = document.createElement('script')
125
+ script.src = ISLAND_SRC
126
+ script.async = true
127
+ script.onload = () => {
128
+ const mod = scope[${JSON.stringify(ISLAND_REGISTRY_KEY)}][ISLAND_ID]
129
+ if (mod) resolve(mod)
130
+ else reject(new Error('tamagui island ' + ISLAND_ID + ' did not register'))
131
+ }
132
+ script.onerror = () => reject(new Error('tamagui island ' + ISLAND_ID + ' failed to load ' + ISLAND_SRC))
133
+ document.head.appendChild(script)
134
+ })
135
+ }
136
+ return pending
137
+ }
138
+
139
+ export default function TamaguiIsland(props) {
140
+ const bridgeId = props['data-tamagui-bridge'] || 'root'
141
+ const [Loaded, setLoaded] = React.useState(null)
142
+
143
+ React.useEffect(() => {
144
+ let cancelled = false
145
+ loadIsland().then((mod) => {
146
+ if (!cancelled) setLoaded(() => mod.Island)
147
+ })
148
+ return () => {
149
+ cancelled = true
150
+ }
151
+ }, [])
152
+
153
+ if (!Loaded) {
154
+ return React.createElement('div', {
155
+ 'data-tamagui-island': ISLAND_ID,
156
+ 'data-tamagui-bridge': bridgeId,
157
+ })
158
+ }
159
+
160
+ const forwarded = {}
161
+ for (const key in props) forwarded[key] = props[key]
162
+ forwarded['data-tamagui-island'] = ISLAND_ID
163
+ return React.createElement(Loaded, forwarded)
164
+ }
165
+ `
166
+ }
167
+
168
+ export function generateIslandEntrySource(input: IslandGenerationInput): string {
169
+ const entry = input.island.entry
170
+ return `// generated by @tamagui/static zero-runtime. do not edit.
171
+ import * as React from 'react'
172
+ import { TamaguiProvider, Theme } from 'tamagui'
173
+ import config from ${JSON.stringify(importPath(entry, input.configPath))}
174
+ import IslandRoot from ${JSON.stringify(importPath(entry, input.island.module))}
175
+
176
+ export function Island(props) {
177
+ const bridge = props.__tamaguiBridge
178
+ const inner = {}
179
+ for (const key in props) {
180
+ if (key !== '__tamaguiBridge') inner[key] = props[key]
181
+ }
182
+ let node = React.createElement(IslandRoot, inner)
183
+ const layers = (bridge && bridge.layers) || []
184
+ for (let index = layers.length - 1; index >= 0; index--) {
185
+ node = React.createElement(
186
+ Theme,
187
+ {
188
+ inlineValues: layers[index].inlineValues,
189
+ inlineClassName: layers[index].inlineClassName,
190
+ forceClassName: true,
191
+ },
192
+ node
193
+ )
194
+ }
195
+ // isSubtreeRoot: the island shares a document with a zero page that already
196
+ // has its own compiled theme spans, so its provider must not write a theme
197
+ // class onto html or body and must carry its own theme on its own node.
198
+ return React.createElement(
199
+ TamaguiProvider,
200
+ {
201
+ config,
202
+ defaultTheme: (bridge && bridge.name) || 'light',
203
+ disableInjectCSS: true,
204
+ isSubtreeRoot: true,
205
+ },
206
+ node
207
+ )
208
+ }
209
+
210
+ const scope = globalThis
211
+ if (!scope[${JSON.stringify(ISLAND_REGISTRY_KEY)}]) scope[${JSON.stringify(ISLAND_REGISTRY_KEY)}] = {}
212
+ scope[${JSON.stringify(ISLAND_REGISTRY_KEY)}][${JSON.stringify(input.island.id)}] = { Island }
213
+ `
214
+ }
215
+
216
+ export function writeIslandModules(input: IslandGenerationInput): void {
217
+ writeIfChanged(input.island.loader, generateIslandLoaderSource(input))
218
+ writeIfChanged(input.island.entry, generateIslandEntrySource(input))
219
+ }
220
+
221
+ /**
222
+ * The island child build externalizes React to the handoff the generated loader
223
+ * publishes, so one React instance serves both graphs.
224
+ *
225
+ * Property paths are the source of truth: webpack needs the segments (a dotted
226
+ * string becomes one literal property name), rollup needs the joined expression.
227
+ */
228
+ export const ISLAND_EXTERNAL_GLOBAL_PATHS: Record<string, string[]> = {
229
+ react: [ISLAND_RUNTIME_KEY, 'react'],
230
+ 'react-dom': [ISLAND_RUNTIME_KEY, 'reactDom'],
231
+ 'react/jsx-runtime': [ISLAND_RUNTIME_KEY, 'jsxRuntime'],
232
+ }
233
+
234
+ export const ISLAND_EXTERNAL_GLOBALS: Record<string, string> = Object.fromEntries(
235
+ Object.entries(ISLAND_EXTERNAL_GLOBAL_PATHS).map(([name, segments]) => [
236
+ name,
237
+ `globalThis.${segments.join('.')}`,
238
+ ])
239
+ )
240
+
241
+ /**
242
+ * Merges one module's bridge descriptors into the build-wide manifest.
243
+ *
244
+ * A module is transformed once per compilation (webpack builds a server and a
245
+ * client pass over the same source), so a bridge id must replace its previous
246
+ * record rather than append a duplicate.
247
+ */
248
+ export function mergeIslandBridges(
249
+ target: Map<string, IslandThemeBridge[]>,
250
+ incoming: Map<string, IslandThemeBridge[]>
251
+ ): void {
252
+ for (const [islandId, bridges] of incoming) {
253
+ const list = target.get(islandId) ?? []
254
+ for (const bridge of bridges) {
255
+ const index = list.findIndex((existing) => existing.id === bridge.id)
256
+ if (index >= 0) list[index] = bridge
257
+ else list.push(bridge)
258
+ }
259
+ list.sort((left, right) => (left.id < right.id ? -1 : left.id > right.id ? 1 : 0))
260
+ target.set(islandId, list)
261
+ }
262
+ }
@@ -0,0 +1,239 @@
1
+ import { zeroConfigDriverMessage } from '@tamagui/compiler-core'
2
+ import type { TamaguiInternalConfig } from '@tamagui/web'
3
+ import glob from 'fast-glob'
4
+ import path from 'node:path'
5
+
6
+ import type { TamaguiOptions } from '../types'
7
+
8
+ /**
9
+ * `TAMAGUI_RUNTIME` has exactly two integration-owned literal values. The public
10
+ * `experimental.zeroRuntime` option is the author input; this literal is
11
+ * generated output, so an ambient shell value never reaches a build.
12
+ */
13
+ export type TamaguiRuntimeLiteral = 'full' | 'zero'
14
+
15
+ export type ZeroRuntimeMode = 'off' | 'report' | 'enforce'
16
+
17
+ export interface ZeroIsland {
18
+ /** Stable, deterministic id derived from the island module's root-relative path. */
19
+ id: string
20
+ /** Absolute path of the island root module. */
21
+ module: string
22
+ /** Absolute path of the generated loader the zero graph imports. */
23
+ loader: string
24
+ /** Absolute path of the generated full-runtime entry. */
25
+ entry: string
26
+ }
27
+
28
+ export interface ZeroRuntimeResolved {
29
+ mode: ZeroRuntimeMode
30
+ /** The project being built. The graph gate excludes its own package. */
31
+ root: string
32
+ islandGlobs: string[]
33
+ islands: ZeroIsland[]
34
+ /** Absolute directory holding generated loaders, entries, and receipts. */
35
+ outDir: string
36
+ /** Absolute path of the single generated CSS artifact. */
37
+ cssPath: string
38
+ }
39
+
40
+ // under the project's existing generated-output directory, which the repository
41
+ // already excludes from git and from the formatter
42
+ export const ZERO_OUT_DIRNAME = '.tamagui/zero'
43
+
44
+ /**
45
+ * Island id is the module's basename, which is also the generated loader's
46
+ * filename. Two declared islands may not share a basename.
47
+ */
48
+ export function islandIdFor(moduleId: string): string {
49
+ return path.basename(moduleId).replace(/\.[jt]sx?$/, '')
50
+ }
51
+
52
+ type ZeroRuntimeInput = Pick<TamaguiOptions, 'experimental' | 'outputCSS' | 'platform'>
53
+
54
+ export async function resolveZeroRuntime(
55
+ options: ZeroRuntimeInput,
56
+ root: string
57
+ ): Promise<ZeroRuntimeResolved> {
58
+ const early = resolveZeroRuntimeEarly(options, root)
59
+ if (early.done) return early.resolved
60
+ return finishZeroRuntime(
61
+ options,
62
+ root,
63
+ early.islandGlobs,
64
+ early.islandGlobs.length
65
+ ? await glob(early.islandGlobs, { cwd: root, absolute: true, dot: false })
66
+ : []
67
+ )
68
+ }
69
+
70
+ /** The webpack adapter configures itself synchronously, before any hook runs. */
71
+ export function resolveZeroRuntimeSync(
72
+ options: ZeroRuntimeInput,
73
+ root: string
74
+ ): ZeroRuntimeResolved {
75
+ const early = resolveZeroRuntimeEarly(options, root)
76
+ if (early.done) return early.resolved
77
+ return finishZeroRuntime(
78
+ options,
79
+ root,
80
+ early.islandGlobs,
81
+ early.islandGlobs.length
82
+ ? glob.sync(early.islandGlobs, { cwd: root, absolute: true, dot: false })
83
+ : []
84
+ )
85
+ }
86
+
87
+ function resolveZeroRuntimeEarly(
88
+ options: ZeroRuntimeInput,
89
+ root: string
90
+ ):
91
+ | { done: true; resolved: ZeroRuntimeResolved }
92
+ | { done: false; islandGlobs: string[] } {
93
+ const requested = options.experimental?.zeroRuntime
94
+ const outDir = path.join(root, ZERO_OUT_DIRNAME)
95
+ const off: ZeroRuntimeResolved = {
96
+ mode: 'off',
97
+ root,
98
+ islandGlobs: [],
99
+ islands: [],
100
+ outDir,
101
+ cssPath: '',
102
+ }
103
+ if (!requested) return { done: true, resolved: off }
104
+
105
+ if (options.platform === 'native' && requested === 'report') {
106
+ return { done: true, resolved: { ...off, mode: 'report' } }
107
+ }
108
+
109
+ if (options.platform === 'native') {
110
+ throw new Error(
111
+ `[tamagui zero-runtime] experimental.zeroRuntime is web only. A native build always receives TAMAGUI_RUNTIME="full".`
112
+ )
113
+ }
114
+
115
+ // `report` keeps the full runtime, so it owns no generated artifact and needs
116
+ // no outputCSS. It still runs every per-module analysis.
117
+ if (requested !== 'report' && !options.outputCSS) {
118
+ throw new Error(
119
+ `[tamagui zero-runtime] experimental.zeroRuntime requires outputCSS. The bundler owns one generated CSS artifact and derives TAMAGUI_DID_OUTPUT_CSS from it.`
120
+ )
121
+ }
122
+
123
+ if (requested !== 'report' && process.env.TAMAGUI_DOES_SSR_CSS === 'mutates-themes') {
124
+ throw new Error(
125
+ `[tamagui zero-runtime] Rule 4: TAMAGUI_DOES_SSR_CSS="mutates-themes" declares runtime theme mutation. Zero-runtime themes are build-time data. Remove runtime mutation or move that surface to a full-runtime island.`
126
+ )
127
+ }
128
+
129
+ return {
130
+ done: false,
131
+ islandGlobs: requested === true || requested === 'report' ? [] : requested.islands,
132
+ }
133
+ }
134
+
135
+ function finishZeroRuntime(
136
+ options: ZeroRuntimeInput,
137
+ root: string,
138
+ islandGlobs: string[],
139
+ matches: string[]
140
+ ): ZeroRuntimeResolved {
141
+ const outDir = path.join(root, ZERO_OUT_DIRNAME)
142
+ // resolveZeroRuntimeEarly already rejected a missing outputCSS in enforce mode
143
+ const outputCSS = (options.outputCSS ?? '') as string
144
+ const islands = [...new Set(matches.map((match) => path.normalize(match)))]
145
+ .sort()
146
+ .map((module): ZeroIsland => {
147
+ const id = islandIdFor(module)
148
+ return {
149
+ id,
150
+ module,
151
+ loader: path.join(outDir, `${id}.loader.js`),
152
+ entry: path.join(outDir, `${id}.entry.js`),
153
+ }
154
+ })
155
+
156
+ const seen = new Set<string>()
157
+ for (const island of islands) {
158
+ if (seen.has(island.id)) {
159
+ throw new Error(
160
+ `[tamagui zero-runtime] two declared islands share the basename "${island.id}". Island ids are their module basename because that is also the generated loader's filename.`
161
+ )
162
+ }
163
+ seen.add(island.id)
164
+ }
165
+
166
+ if (islandGlobs.length && islands.length === 0) {
167
+ throw new Error(
168
+ `[tamagui zero-runtime] experimental.zeroRuntime.islands matched no module for ${JSON.stringify(
169
+ islandGlobs
170
+ )}`
171
+ )
172
+ }
173
+
174
+ return {
175
+ mode: options.experimental?.zeroRuntime === 'report' ? 'report' : 'enforce',
176
+ root,
177
+ islandGlobs,
178
+ islands,
179
+ outDir,
180
+ cssPath: !outputCSS
181
+ ? ''
182
+ : path.isAbsolute(outputCSS)
183
+ ? outputCSS
184
+ : path.resolve(root, outputCSS),
185
+ }
186
+ }
187
+
188
+ /**
189
+ * Rule 5 at config level. A non-CSS driver in the zero entry's own config means
190
+ * every animated component in that graph needs a component animation runtime,
191
+ * which is exactly what the mode removes.
192
+ */
193
+ export function assertZeroConfigDrivers(config: TamaguiInternalConfig): void {
194
+ // `animationDrivers` is set only for a multi-driver config; a single-driver
195
+ // config resolves to `animations`, and reading only the map would make this
196
+ // check silently unable to fail for the ordinary shape
197
+ const drivers: [string, { outputStyle?: unknown } | undefined][] = (
198
+ config.animationDrivers
199
+ ? Object.entries(config.animationDrivers)
200
+ : [['default', config.animations]]
201
+ ) as [string, { outputStyle?: unknown } | undefined][]
202
+ for (const [name, driver] of drivers) {
203
+ if (!driver || driver.outputStyle === 'css') continue
204
+ throw new Error(zeroConfigDriverMessage(name, driver.outputStyle))
205
+ }
206
+ }
207
+
208
+ export type ZeroIntegration = 'vite' | 'next-webpack' | 'metro-web'
209
+
210
+ /**
211
+ * Base and island support are enabled per integration after that integration
212
+ * passes its own receipts. One lagging integration never blocks another.
213
+ */
214
+ export const ZERO_INTEGRATION_SUPPORT: Record<
215
+ ZeroIntegration,
216
+ { base: boolean; islands: boolean }
217
+ > = {
218
+ vite: { base: true, islands: true },
219
+ 'next-webpack': { base: true, islands: true },
220
+ 'metro-web': { base: true, islands: true },
221
+ }
222
+
223
+ export function assertZeroIntegrationSupport(
224
+ integration: ZeroIntegration,
225
+ resolved: ZeroRuntimeResolved
226
+ ): void {
227
+ if (resolved.mode !== 'enforce') return
228
+ const support = ZERO_INTEGRATION_SUPPORT[integration]
229
+ if (!support.base) {
230
+ throw new Error(
231
+ `[tamagui zero-runtime] ${integration} has not qualified for zero-runtime output in this version. Use zeroRuntime: "report" or choose a qualified integration.`
232
+ )
233
+ }
234
+ if (resolved.islands.length && !support.islands) {
235
+ throw new Error(
236
+ `[tamagui zero-runtime] ${integration} does not support experimental.zeroRuntime islands in this version. Use zeroRuntime: true without islands or choose an integration with island support.`
237
+ )
238
+ }
239
+ }
@@ -0,0 +1,113 @@
1
+ import { createHash } from 'node:crypto'
2
+ import { readFileSync } from 'node:fs'
3
+ import path from 'node:path'
4
+
5
+ import type { TamaguiOptions } from '../types'
6
+ import { resolveZeroRuntimeSync } from './options'
7
+
8
+ /**
9
+ * Artifact ownership, shared by every integration and by both CSS tiers.
10
+ *
11
+ * A build may claim `TAMAGUI_DID_OUTPUT_CSS='1'` only after the artifact that
12
+ * replaces the stripped JavaScript rules is proven to exist, to match the CSS
13
+ * this build's config generates, and to be loaded by the entry graph. Those are
14
+ * three separate failures with three separate causes, so they are three
15
+ * separate diagnostics.
16
+ */
17
+
18
+ export type GlobalCSSFailureKind = 'missing' | 'stale' | 'unimported'
19
+
20
+ export interface GlobalCSSFailure {
21
+ kind: GlobalCSSFailureKind
22
+ cssPath: string
23
+ message: string
24
+ }
25
+
26
+ export const hashCSS = (css: string) =>
27
+ createHash('sha256').update(css).digest('hex').slice(0, 16)
28
+
29
+ const normalize = (value: string) => value.split(/[?#]/, 1)[0]!.replace(/\\/g, '/')
30
+
31
+ /**
32
+ * `TAMAGUI_DOES_SSR_CSS='mutates-themes'` declares that themes are mutated at
33
+ * runtime, which is the one declaration that keeps the runtime theme generator
34
+ * alive. It therefore blocks the compiled-global-CSS claim outright.
35
+ */
36
+ export const declaresRuntimeThemeMutation = () =>
37
+ process.env.TAMAGUI_DOES_SSR_CSS === 'mutates-themes'
38
+
39
+ export interface GlobalCSSOwnership {
40
+ /** Absolute path of the artifact this build owns. */
41
+ cssPath: string
42
+ }
43
+
44
+ /**
45
+ * The compiled-global-CSS tier for one web build, or null when the build is not
46
+ * in that tier.
47
+ *
48
+ * Zero mode owns its own combined artifact and derives the flag through
49
+ * `ZeroCSSArtifact`, so it is deliberately excluded here: one tier, one owner.
50
+ */
51
+ export function resolveGlobalCSSOwnership(
52
+ options: Pick<TamaguiOptions, 'experimental' | 'outputCSS' | 'platform' | 'disable'>,
53
+ root: string
54
+ ): GlobalCSSOwnership | null {
55
+ if (options.disable) return null
56
+ if (options.platform === 'native') return null
57
+ if (!options.outputCSS) return null
58
+ if (declaresRuntimeThemeMutation()) return null
59
+ if (resolveZeroRuntimeSync(options, root).mode === 'enforce') return null
60
+ return {
61
+ cssPath: path.isAbsolute(options.outputCSS)
62
+ ? options.outputCSS
63
+ : path.resolve(root, options.outputCSS),
64
+ }
65
+ }
66
+
67
+ /**
68
+ * The three ways the stripping fact and its replacement asset can diverge.
69
+ *
70
+ * `loadedModuleIds` is the set of module ids the entry graph actually shipped.
71
+ * An integration that publishes the artifact as a static file rather than as a
72
+ * graph module passes the published copy's path instead, which is the same
73
+ * question asked of a different transport.
74
+ */
75
+ export function checkGlobalCSSArtifact(input: {
76
+ cssPath: string
77
+ expectedCSS: string
78
+ loadedModuleIds: Iterable<string>
79
+ /** How the entry is expected to reach the artifact, printed on failure. */
80
+ importHint: string
81
+ }): GlobalCSSFailure | null {
82
+ const { cssPath, expectedCSS } = input
83
+ let onDisk: string
84
+ try {
85
+ onDisk = readFileSync(cssPath, 'utf8')
86
+ } catch {
87
+ return {
88
+ kind: 'missing',
89
+ cssPath,
90
+ message: `[tamagui] the generated CSS artifact ${cssPath} does not exist, so this build cannot claim TAMAGUI_DID_OUTPUT_CSS. The design-system, :root, font and theme rules would be stripped from JavaScript and put nowhere.`,
91
+ }
92
+ }
93
+ if (onDisk !== expectedCSS) {
94
+ return {
95
+ kind: 'stale',
96
+ cssPath,
97
+ message: `[tamagui] the generated CSS artifact ${cssPath} is stale: it hashes ${hashCSS(
98
+ onDisk
99
+ )} but this build's config generates ${hashCSS(
100
+ expectedCSS
101
+ )}. Deriving TAMAGUI_DID_OUTPUT_CSS from it would ship rules that do not match the build.`,
102
+ }
103
+ }
104
+ const wanted = normalize(cssPath)
105
+ for (const id of input.loadedModuleIds) {
106
+ if (normalize(id) === wanted) return null
107
+ }
108
+ return {
109
+ kind: 'unimported',
110
+ cssPath,
111
+ message: `[tamagui] the generated CSS artifact ${cssPath} exists but the entry graph never loads it. ${input.importHint}`,
112
+ }
113
+ }