rnwind 0.0.1 → 0.0.3

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 (330) hide show
  1. package/lib/cjs/core/parser/animation.cjs +427 -0
  2. package/lib/cjs/core/parser/animation.cjs.map +1 -0
  3. package/lib/cjs/core/parser/animation.d.ts +126 -0
  4. package/lib/cjs/core/parser/border-dispatcher.cjs +180 -0
  5. package/lib/cjs/core/parser/border-dispatcher.cjs.map +1 -0
  6. package/lib/cjs/core/parser/border-dispatcher.d.ts +15 -0
  7. package/lib/cjs/core/parser/case-convert.cjs +15 -0
  8. package/lib/cjs/core/parser/case-convert.cjs.map +1 -0
  9. package/lib/cjs/core/parser/case-convert.d.ts +6 -0
  10. package/lib/cjs/core/parser/color-properties-dispatcher.cjs +84 -0
  11. package/lib/cjs/core/parser/color-properties-dispatcher.cjs.map +1 -0
  12. package/lib/cjs/core/parser/color-properties-dispatcher.d.ts +19 -0
  13. package/lib/cjs/core/parser/color.cjs +193 -0
  14. package/lib/cjs/core/parser/color.cjs.map +1 -0
  15. package/lib/cjs/core/parser/color.d.ts +12 -0
  16. package/lib/cjs/core/parser/constants.cjs +21 -0
  17. package/lib/cjs/core/parser/constants.cjs.map +1 -0
  18. package/lib/cjs/core/parser/constants.d.ts +8 -0
  19. package/lib/cjs/core/parser/declaration.cjs +347 -0
  20. package/lib/cjs/core/parser/declaration.cjs.map +1 -0
  21. package/lib/cjs/core/parser/declaration.d.ts +15 -0
  22. package/lib/cjs/core/parser/gradient.cjs +132 -0
  23. package/lib/cjs/core/parser/gradient.cjs.map +1 -0
  24. package/lib/cjs/core/parser/gradient.d.ts +59 -0
  25. package/lib/cjs/core/parser/haptics.cjs +73 -0
  26. package/lib/cjs/core/parser/haptics.cjs.map +1 -0
  27. package/lib/cjs/core/parser/haptics.d.ts +47 -0
  28. package/lib/cjs/core/parser/index.d.ts +8 -0
  29. package/lib/cjs/core/parser/keyframes.cjs +95 -0
  30. package/lib/cjs/core/parser/keyframes.cjs.map +1 -0
  31. package/lib/cjs/core/parser/keyframes.d.ts +26 -0
  32. package/lib/cjs/core/parser/layout-dispatcher.cjs +120 -0
  33. package/lib/cjs/core/parser/layout-dispatcher.cjs.map +1 -0
  34. package/lib/cjs/core/parser/layout-dispatcher.d.ts +14 -0
  35. package/lib/cjs/core/parser/length.cjs +110 -0
  36. package/lib/cjs/core/parser/length.cjs.map +1 -0
  37. package/lib/cjs/core/parser/length.d.ts +51 -0
  38. package/lib/cjs/core/parser/motion-dispatcher.cjs +77 -0
  39. package/lib/cjs/core/parser/motion-dispatcher.cjs.map +1 -0
  40. package/lib/cjs/core/parser/motion-dispatcher.d.ts +11 -0
  41. package/lib/cjs/core/parser/property.cjs +22 -0
  42. package/lib/cjs/core/parser/property.cjs.map +1 -0
  43. package/lib/cjs/core/parser/property.d.ts +8 -0
  44. package/lib/cjs/core/parser/safe-area.cjs +404 -0
  45. package/lib/cjs/core/parser/safe-area.cjs.map +1 -0
  46. package/lib/cjs/core/parser/safe-area.d.ts +39 -0
  47. package/lib/cjs/core/parser/selector.cjs +22 -0
  48. package/lib/cjs/core/parser/selector.cjs.map +1 -0
  49. package/lib/cjs/core/parser/selector.d.ts +11 -0
  50. package/lib/cjs/core/parser/shorthand.cjs +188 -0
  51. package/lib/cjs/core/parser/shorthand.cjs.map +1 -0
  52. package/lib/cjs/core/parser/shorthand.d.ts +67 -0
  53. package/lib/cjs/core/parser/text-truncate.cjs +78 -0
  54. package/lib/cjs/core/parser/text-truncate.cjs.map +1 -0
  55. package/lib/cjs/core/parser/text-truncate.d.ts +44 -0
  56. package/lib/cjs/core/parser/theme-vars.cjs +467 -0
  57. package/lib/cjs/core/parser/theme-vars.cjs.map +1 -0
  58. package/lib/cjs/core/parser/theme-vars.d.ts +82 -0
  59. package/lib/cjs/core/parser/tokens.cjs +486 -0
  60. package/lib/cjs/core/parser/tokens.cjs.map +1 -0
  61. package/lib/cjs/core/parser/tokens.d.ts +45 -0
  62. package/lib/cjs/core/parser/transform.cjs +198 -0
  63. package/lib/cjs/core/parser/transform.cjs.map +1 -0
  64. package/lib/cjs/core/parser/transform.d.ts +36 -0
  65. package/lib/cjs/core/parser/tw-parser.cjs +1680 -0
  66. package/lib/cjs/core/parser/tw-parser.cjs.map +1 -0
  67. package/lib/cjs/core/parser/tw-parser.d.ts +210 -0
  68. package/lib/cjs/core/parser/types.d.ts +37 -0
  69. package/lib/cjs/core/parser/typography-dispatcher.cjs +108 -0
  70. package/lib/cjs/core/parser/typography-dispatcher.cjs.map +1 -0
  71. package/lib/cjs/core/parser/typography-dispatcher.d.ts +11 -0
  72. package/lib/cjs/core/parser/typography.cjs +97 -0
  73. package/lib/cjs/core/parser/typography.cjs.map +1 -0
  74. package/lib/cjs/core/parser/typography.d.ts +43 -0
  75. package/lib/cjs/core/style-builder/build-style.cjs +444 -0
  76. package/lib/cjs/core/style-builder/build-style.cjs.map +1 -0
  77. package/lib/cjs/core/style-builder/build-style.d.ts +54 -0
  78. package/lib/cjs/core/style-builder/index.d.ts +3 -0
  79. package/lib/cjs/core/style-builder/union-builder.cjs +326 -0
  80. package/lib/cjs/core/style-builder/union-builder.cjs.map +1 -0
  81. package/lib/cjs/core/style-builder/union-builder.d.ts +128 -0
  82. package/lib/cjs/core/types.d.ts +14 -0
  83. package/lib/cjs/metro/dts.cjs +127 -0
  84. package/lib/cjs/metro/dts.cjs.map +1 -0
  85. package/lib/cjs/metro/dts.d.ts +16 -0
  86. package/lib/cjs/metro/index.cjs +19 -0
  87. package/lib/cjs/metro/index.cjs.map +1 -0
  88. package/lib/cjs/metro/index.d.ts +9 -0
  89. package/lib/cjs/metro/resolver.cjs +47 -0
  90. package/lib/cjs/metro/resolver.cjs.map +1 -0
  91. package/lib/cjs/metro/resolver.d.ts +22 -0
  92. package/lib/cjs/metro/state.cjs +301 -0
  93. package/lib/cjs/metro/state.cjs.map +1 -0
  94. package/lib/cjs/metro/state.d.ts +88 -0
  95. package/lib/cjs/metro/transform-ast.cjs +1472 -0
  96. package/lib/cjs/metro/transform-ast.cjs.map +1 -0
  97. package/lib/cjs/metro/transform-ast.d.ts +88 -0
  98. package/lib/cjs/metro/transformer.cjs +372 -0
  99. package/lib/cjs/metro/transformer.cjs.map +1 -0
  100. package/lib/cjs/metro/transformer.d.ts +47 -0
  101. package/lib/cjs/metro/warn-unknown-classes.cjs +86 -0
  102. package/lib/cjs/metro/warn-unknown-classes.cjs.map +1 -0
  103. package/lib/cjs/metro/warn-unknown-classes.d.ts +21 -0
  104. package/lib/cjs/metro/with-config.cjs +196 -0
  105. package/lib/cjs/metro/with-config.cjs.map +1 -0
  106. package/lib/cjs/metro/with-config.d.ts +79 -0
  107. package/lib/cjs/runtime/chain-handlers.cjs +37 -0
  108. package/lib/cjs/runtime/chain-handlers.cjs.map +1 -0
  109. package/lib/cjs/runtime/chain-handlers.d.ts +33 -0
  110. package/lib/cjs/runtime/components/rnwind-provider.cjs +98 -0
  111. package/lib/cjs/runtime/components/rnwind-provider.cjs.map +1 -0
  112. package/lib/cjs/runtime/components/rnwind-provider.d.ts +84 -0
  113. package/lib/cjs/runtime/gradient-types.d.ts +58 -0
  114. package/lib/cjs/runtime/haptics.cjs +113 -0
  115. package/lib/cjs/runtime/haptics.cjs.map +1 -0
  116. package/lib/cjs/runtime/haptics.d.ts +48 -0
  117. package/lib/cjs/runtime/hooks/use-css.cjs +21 -0
  118. package/lib/cjs/runtime/hooks/use-css.cjs.map +1 -0
  119. package/lib/cjs/runtime/hooks/use-css.d.ts +11 -0
  120. package/lib/cjs/runtime/hooks/use-interact.cjs +46 -0
  121. package/lib/cjs/runtime/hooks/use-interact.cjs.map +1 -0
  122. package/lib/cjs/runtime/hooks/use-interact.d.ts +42 -0
  123. package/lib/cjs/runtime/hooks/use-scheme.cjs +68 -0
  124. package/lib/cjs/runtime/hooks/use-scheme.cjs.map +1 -0
  125. package/lib/cjs/runtime/hooks/use-scheme.d.ts +34 -0
  126. package/lib/cjs/runtime/index.cjs +45 -0
  127. package/lib/cjs/runtime/index.cjs.map +1 -0
  128. package/lib/cjs/runtime/index.d.ts +27 -0
  129. package/lib/cjs/runtime/interactive-box.cjs +35 -0
  130. package/lib/cjs/runtime/interactive-box.cjs.map +1 -0
  131. package/lib/cjs/runtime/interactive-box.d.ts +40 -0
  132. package/lib/cjs/runtime/lookup-css.cjs +542 -0
  133. package/lib/cjs/runtime/lookup-css.cjs.map +1 -0
  134. package/lib/cjs/runtime/lookup-css.d.ts +164 -0
  135. package/lib/cjs/runtime/types.d.ts +29 -0
  136. package/lib/cjs/testing/index.cjs +367 -0
  137. package/lib/cjs/testing/index.cjs.map +1 -0
  138. package/lib/cjs/testing/index.d.ts +145 -0
  139. package/lib/esm/core/parser/animation.d.ts +126 -0
  140. package/lib/esm/core/parser/animation.mjs +408 -0
  141. package/lib/esm/core/parser/animation.mjs.map +1 -0
  142. package/lib/esm/core/parser/border-dispatcher.d.ts +15 -0
  143. package/lib/esm/core/parser/border-dispatcher.mjs +178 -0
  144. package/lib/esm/core/parser/border-dispatcher.mjs.map +1 -0
  145. package/lib/esm/core/parser/case-convert.d.ts +6 -0
  146. package/lib/esm/core/parser/case-convert.mjs +13 -0
  147. package/lib/esm/core/parser/case-convert.mjs.map +1 -0
  148. package/lib/esm/core/parser/color-properties-dispatcher.d.ts +19 -0
  149. package/lib/esm/core/parser/color-properties-dispatcher.mjs +82 -0
  150. package/lib/esm/core/parser/color-properties-dispatcher.mjs.map +1 -0
  151. package/lib/esm/core/parser/color.d.ts +12 -0
  152. package/lib/esm/core/parser/color.mjs +191 -0
  153. package/lib/esm/core/parser/color.mjs.map +1 -0
  154. package/lib/esm/core/parser/constants.d.ts +8 -0
  155. package/lib/esm/core/parser/constants.mjs +13 -0
  156. package/lib/esm/core/parser/constants.mjs.map +1 -0
  157. package/lib/esm/core/parser/declaration.d.ts +15 -0
  158. package/lib/esm/core/parser/declaration.mjs +345 -0
  159. package/lib/esm/core/parser/declaration.mjs.map +1 -0
  160. package/lib/esm/core/parser/gradient.d.ts +59 -0
  161. package/lib/esm/core/parser/gradient.mjs +130 -0
  162. package/lib/esm/core/parser/gradient.mjs.map +1 -0
  163. package/lib/esm/core/parser/haptics.d.ts +47 -0
  164. package/lib/esm/core/parser/haptics.mjs +71 -0
  165. package/lib/esm/core/parser/haptics.mjs.map +1 -0
  166. package/lib/esm/core/parser/index.d.ts +8 -0
  167. package/lib/esm/core/parser/keyframes.d.ts +26 -0
  168. package/lib/esm/core/parser/keyframes.mjs +91 -0
  169. package/lib/esm/core/parser/keyframes.mjs.map +1 -0
  170. package/lib/esm/core/parser/layout-dispatcher.d.ts +14 -0
  171. package/lib/esm/core/parser/layout-dispatcher.mjs +118 -0
  172. package/lib/esm/core/parser/layout-dispatcher.mjs.map +1 -0
  173. package/lib/esm/core/parser/length.d.ts +51 -0
  174. package/lib/esm/core/parser/length.mjs +104 -0
  175. package/lib/esm/core/parser/length.mjs.map +1 -0
  176. package/lib/esm/core/parser/motion-dispatcher.d.ts +11 -0
  177. package/lib/esm/core/parser/motion-dispatcher.mjs +75 -0
  178. package/lib/esm/core/parser/motion-dispatcher.mjs.map +1 -0
  179. package/lib/esm/core/parser/property.d.ts +8 -0
  180. package/lib/esm/core/parser/property.mjs +20 -0
  181. package/lib/esm/core/parser/property.mjs.map +1 -0
  182. package/lib/esm/core/parser/safe-area.d.ts +39 -0
  183. package/lib/esm/core/parser/safe-area.mjs +402 -0
  184. package/lib/esm/core/parser/safe-area.mjs.map +1 -0
  185. package/lib/esm/core/parser/selector.d.ts +11 -0
  186. package/lib/esm/core/parser/selector.mjs +20 -0
  187. package/lib/esm/core/parser/selector.mjs.map +1 -0
  188. package/lib/esm/core/parser/shorthand.d.ts +67 -0
  189. package/lib/esm/core/parser/shorthand.mjs +180 -0
  190. package/lib/esm/core/parser/shorthand.mjs.map +1 -0
  191. package/lib/esm/core/parser/text-truncate.d.ts +44 -0
  192. package/lib/esm/core/parser/text-truncate.mjs +75 -0
  193. package/lib/esm/core/parser/text-truncate.mjs.map +1 -0
  194. package/lib/esm/core/parser/theme-vars.d.ts +82 -0
  195. package/lib/esm/core/parser/theme-vars.mjs +461 -0
  196. package/lib/esm/core/parser/theme-vars.mjs.map +1 -0
  197. package/lib/esm/core/parser/tokens.d.ts +45 -0
  198. package/lib/esm/core/parser/tokens.mjs +480 -0
  199. package/lib/esm/core/parser/tokens.mjs.map +1 -0
  200. package/lib/esm/core/parser/transform.d.ts +36 -0
  201. package/lib/esm/core/parser/transform.mjs +193 -0
  202. package/lib/esm/core/parser/transform.mjs.map +1 -0
  203. package/lib/esm/core/parser/tw-parser.d.ts +210 -0
  204. package/lib/esm/core/parser/tw-parser.mjs +1678 -0
  205. package/lib/esm/core/parser/tw-parser.mjs.map +1 -0
  206. package/lib/esm/core/parser/types.d.ts +37 -0
  207. package/lib/esm/core/parser/typography-dispatcher.d.ts +11 -0
  208. package/lib/esm/core/parser/typography-dispatcher.mjs +106 -0
  209. package/lib/esm/core/parser/typography-dispatcher.mjs.map +1 -0
  210. package/lib/esm/core/parser/typography.d.ts +43 -0
  211. package/lib/esm/core/parser/typography.mjs +91 -0
  212. package/lib/esm/core/parser/typography.mjs.map +1 -0
  213. package/lib/esm/core/style-builder/build-style.d.ts +54 -0
  214. package/lib/esm/core/style-builder/build-style.mjs +442 -0
  215. package/lib/esm/core/style-builder/build-style.mjs.map +1 -0
  216. package/lib/esm/core/style-builder/index.d.ts +3 -0
  217. package/lib/esm/core/style-builder/union-builder.d.ts +128 -0
  218. package/lib/esm/core/style-builder/union-builder.mjs +324 -0
  219. package/lib/esm/core/style-builder/union-builder.mjs.map +1 -0
  220. package/lib/esm/core/types.d.ts +14 -0
  221. package/lib/esm/metro/dts.d.ts +16 -0
  222. package/lib/esm/metro/dts.mjs +125 -0
  223. package/lib/esm/metro/dts.mjs.map +1 -0
  224. package/lib/esm/metro/index.d.ts +9 -0
  225. package/lib/esm/metro/index.mjs +6 -0
  226. package/lib/esm/metro/index.mjs.map +1 -0
  227. package/lib/esm/metro/resolver.d.ts +22 -0
  228. package/lib/esm/metro/resolver.mjs +43 -0
  229. package/lib/esm/metro/resolver.mjs.map +1 -0
  230. package/lib/esm/metro/state.d.ts +88 -0
  231. package/lib/esm/metro/state.mjs +291 -0
  232. package/lib/esm/metro/state.mjs.map +1 -0
  233. package/lib/esm/metro/transform-ast.d.ts +88 -0
  234. package/lib/esm/metro/transform-ast.mjs +1451 -0
  235. package/lib/esm/metro/transform-ast.mjs.map +1 -0
  236. package/lib/esm/metro/transformer.d.ts +47 -0
  237. package/lib/esm/metro/transformer.mjs +349 -0
  238. package/lib/esm/metro/transformer.mjs.map +1 -0
  239. package/lib/esm/metro/warn-unknown-classes.d.ts +21 -0
  240. package/lib/esm/metro/warn-unknown-classes.mjs +84 -0
  241. package/lib/esm/metro/warn-unknown-classes.mjs.map +1 -0
  242. package/lib/esm/metro/with-config.d.ts +79 -0
  243. package/lib/esm/metro/with-config.mjs +194 -0
  244. package/lib/esm/metro/with-config.mjs.map +1 -0
  245. package/lib/esm/runtime/chain-handlers.d.ts +33 -0
  246. package/lib/esm/runtime/chain-handlers.mjs +34 -0
  247. package/lib/esm/runtime/chain-handlers.mjs.map +1 -0
  248. package/lib/esm/runtime/components/rnwind-provider.d.ts +84 -0
  249. package/lib/esm/runtime/components/rnwind-provider.mjs +94 -0
  250. package/lib/esm/runtime/components/rnwind-provider.mjs.map +1 -0
  251. package/lib/esm/runtime/gradient-types.d.ts +58 -0
  252. package/lib/esm/runtime/haptics.d.ts +48 -0
  253. package/lib/esm/runtime/haptics.mjs +110 -0
  254. package/lib/esm/runtime/haptics.mjs.map +1 -0
  255. package/lib/esm/runtime/hooks/use-css.d.ts +11 -0
  256. package/lib/esm/runtime/hooks/use-css.mjs +19 -0
  257. package/lib/esm/runtime/hooks/use-css.mjs.map +1 -0
  258. package/lib/esm/runtime/hooks/use-interact.d.ts +42 -0
  259. package/lib/esm/runtime/hooks/use-interact.mjs +44 -0
  260. package/lib/esm/runtime/hooks/use-interact.mjs.map +1 -0
  261. package/lib/esm/runtime/hooks/use-scheme.d.ts +34 -0
  262. package/lib/esm/runtime/hooks/use-scheme.mjs +63 -0
  263. package/lib/esm/runtime/hooks/use-scheme.mjs.map +1 -0
  264. package/lib/esm/runtime/index.d.ts +27 -0
  265. package/lib/esm/runtime/index.mjs +18 -0
  266. package/lib/esm/runtime/index.mjs.map +1 -0
  267. package/lib/esm/runtime/interactive-box.d.ts +40 -0
  268. package/lib/esm/runtime/interactive-box.mjs +33 -0
  269. package/lib/esm/runtime/interactive-box.mjs.map +1 -0
  270. package/lib/esm/runtime/lookup-css.d.ts +164 -0
  271. package/lib/esm/runtime/lookup-css.mjs +531 -0
  272. package/lib/esm/runtime/lookup-css.mjs.map +1 -0
  273. package/lib/esm/runtime/types.d.ts +29 -0
  274. package/lib/esm/testing/index.d.ts +145 -0
  275. package/lib/esm/testing/index.mjs +344 -0
  276. package/lib/esm/testing/index.mjs.map +1 -0
  277. package/package.json +80 -13
  278. package/preset.css +1171 -0
  279. package/src/core/parser/animation.ts +404 -0
  280. package/src/core/parser/border-dispatcher.ts +176 -0
  281. package/src/core/parser/case-convert.ts +10 -0
  282. package/src/core/parser/color-properties-dispatcher.ts +78 -0
  283. package/src/core/parser/color.ts +191 -0
  284. package/src/core/parser/constants.ts +11 -0
  285. package/src/core/parser/declaration.ts +340 -0
  286. package/src/core/parser/gradient.ts +148 -0
  287. package/src/core/parser/haptics.ts +88 -0
  288. package/src/core/parser/index.ts +8 -0
  289. package/src/core/parser/keyframes.ts +84 -0
  290. package/src/core/parser/layout-dispatcher.ts +111 -0
  291. package/src/core/parser/length.ts +114 -0
  292. package/src/core/parser/motion-dispatcher.ts +89 -0
  293. package/src/core/parser/property.ts +15 -0
  294. package/src/core/parser/safe-area.ts +404 -0
  295. package/src/core/parser/selector.ts +17 -0
  296. package/src/core/parser/shorthand.ts +182 -0
  297. package/src/core/parser/text-truncate.ts +79 -0
  298. package/src/core/parser/theme-vars.ts +465 -0
  299. package/src/core/parser/tokens.ts +456 -0
  300. package/src/core/parser/transform.ts +195 -0
  301. package/src/core/parser/tw-parser.ts +1828 -0
  302. package/src/core/parser/types.ts +45 -0
  303. package/src/core/parser/typography-dispatcher.ts +97 -0
  304. package/src/core/parser/typography.ts +83 -0
  305. package/src/core/style-builder/build-style.ts +500 -0
  306. package/src/core/style-builder/index.ts +3 -0
  307. package/src/core/style-builder/union-builder.ts +328 -0
  308. package/src/core/types.ts +15 -0
  309. package/src/metro/dts.ts +128 -0
  310. package/src/metro/index.ts +9 -0
  311. package/src/metro/resolver.ts +42 -0
  312. package/src/metro/state.ts +305 -0
  313. package/src/metro/transform-ast.ts +1729 -0
  314. package/src/metro/transformer.ts +372 -0
  315. package/src/metro/warn-unknown-classes.ts +79 -0
  316. package/src/metro/with-config.ts +251 -0
  317. package/src/runtime/chain-handlers.ts +47 -0
  318. package/src/runtime/components/rnwind-provider.tsx +144 -0
  319. package/src/runtime/gradient-types.ts +60 -0
  320. package/src/runtime/haptics.ts +120 -0
  321. package/src/runtime/hooks/use-css.ts +16 -0
  322. package/src/runtime/hooks/use-interact.ts +65 -0
  323. package/src/runtime/hooks/use-scheme.ts +63 -0
  324. package/src/runtime/index.ts +54 -0
  325. package/src/runtime/interactive-box.tsx +57 -0
  326. package/src/runtime/lookup-css.ts +628 -0
  327. package/src/runtime/types.ts +32 -0
  328. package/src/testing/index.ts +507 -0
  329. package/src/types/tailwindcss-node.d.ts +33 -0
  330. package/src/index.ts +0 -1
@@ -0,0 +1,372 @@
1
+ import type { File } from '@babel/types'
2
+ import * as t from '@babel/types'
3
+ import { parse } from '@babel/parser'
4
+ import generate from '@babel/generator'
5
+ import { createHash } from 'node:crypto'
6
+ import { realpathSync } from 'node:fs'
7
+ import { transformAst } from './transform-ast'
8
+ import { getClassNamePrefixes, getHostComponents, getHostSources, getRnwindCacheKey, getRnwindState, onThemeChange } from './state'
9
+ import { STYLE_SPECIFIERS, THEME_SIGNATURE_MODULE } from './resolver'
10
+ import { filterUnknownClassCandidates } from './warn-unknown-classes'
11
+
12
+ /** The shape of the upstream module we delegate parsing/babel work to. */
13
+ interface UpstreamTransformer {
14
+ transform: (args: BabelTransformerArgs) => Promise<BabelTransformerResult> | BabelTransformerResult
15
+ }
16
+
17
+ /** Env var that points at the upstream `babelTransformerPath` we override. */
18
+ const UPSTREAM_ENV = 'RNWIND_UPSTREAM_TRANSFORMER'
19
+
20
+ /** Cached upstream module — required once, reused across every transform call. */
21
+ let cachedUpstream: UpstreamTransformer | null = null
22
+
23
+ const generateModule = (generate as unknown as { default?: typeof generate }).default ?? generate
24
+
25
+ /**
26
+ * Parse user source with the broad plugin set (Flow + JSX + TypeScript
27
+ * + class properties). Permissive on purpose so we don't reject any
28
+ * file the upstream could have handled. Returns `null` when parse
29
+ * fails — caller falls back to the raw source string.
30
+ * @param source Source text.
31
+ * @returns Parsed AST, or null on parse failure.
32
+ */
33
+ function parseUserSource(source: string): File | null {
34
+ try {
35
+ return parse(source, {
36
+ sourceType: 'unambiguous',
37
+ allowReturnOutsideFunction: true,
38
+ allowImportExportEverywhere: true,
39
+ plugins: ['typescript', 'jsx'],
40
+ }) as unknown as File
41
+ } catch {
42
+ try {
43
+ return parse(source, {
44
+ sourceType: 'unambiguous',
45
+ allowReturnOutsideFunction: true,
46
+ allowImportExportEverywhere: true,
47
+ plugins: ['flow', 'jsx'],
48
+ }) as unknown as File
49
+ } catch {
50
+ return null
51
+ }
52
+ }
53
+ }
54
+
55
+ /**
56
+ * Print Tailwind-shaped candidates oxide picked up but the parser
57
+ * could NOT compile — typo, missing custom utility, or class not in
58
+ * the user's theme. Filtering by candidates that ALSO appear inside a
59
+ * `className="…"` literal eliminates false positives from imports,
60
+ * comments, and JSX prop values.
61
+ * @param source Original source text — searched for className literals.
62
+ * @param candidates Every candidate oxide surfaced from the source.
63
+ * @param atoms Successfully resolved atoms (keys are class names).
64
+ * @param filename Source path, prefixed onto the warning.
65
+ */
66
+ function warnUnknownClasses(
67
+ source: string,
68
+ candidates: readonly string[],
69
+ atoms: ReadonlyMap<string, unknown>,
70
+ filename: string,
71
+ ): void {
72
+ const atomNames = new Set(atoms.keys())
73
+ const unknown = filterUnknownClassCandidates(source, candidates, atomNames)
74
+ if (unknown.length === 0) return
75
+ // eslint-disable-next-line no-console
76
+ console.warn(`rnwind: unknown class${unknown.length > 1 ? 'es' : ''} in ${filename}: ${unknown.join(', ')}`)
77
+ }
78
+
79
+ /**
80
+ * Extract the bare extension for oxide / internal switches.
81
+ * @param filename Absolute path.
82
+ * @returns Extension without the leading dot (`tsx` / `ts` / `js` / `jsx`).
83
+ */
84
+ function extensionOf(filename: string): string {
85
+ const index = filename.lastIndexOf('.')
86
+ if (index === -1) return 'tsx'
87
+ return filename.slice(index + 1)
88
+ }
89
+
90
+ /**
91
+ * Read the project root Metro hands us per-transform. Falls back to
92
+ * `process.cwd()` only when the upstream harness doesn't set it (unit
93
+ * tests, standalone). Metro's production pipeline always sets it.
94
+ * @param args Metro transformer args.
95
+ * @returns Absolute project root.
96
+ */
97
+ function projectRootOf(args: BabelTransformerArgs): string {
98
+ const fromOptions = args.options?.projectRoot
99
+ if (typeof fromOptions === 'string' && fromOptions.length > 0) return fromOptions
100
+ return process.cwd()
101
+ }
102
+
103
+ /**
104
+ * Whether a `.css` filename is the user's theme entry (the file
105
+ * `withRnwindConfig` pointed us at via `RNWIND_CSS_ENTRY_FILE`).
106
+ * Only the theme CSS should trigger a scheme rebuild — unrelated CSS
107
+ * files in the project stay invisible to rnwind.
108
+ * @param filename Absolute CSS path.
109
+ * @returns Whether the file is the configured theme entry.
110
+ */
111
+ function isThemeCssEntry(filename: string): boolean {
112
+ const cssEntry = process.env.RNWIND_CSS_ENTRY_FILE
113
+ return typeof cssEntry === 'string' && cssEntry.length > 0 && cssEntry === filename
114
+ }
115
+
116
+ /**
117
+ * Parse + run rnwind's JSX rewrite + regenerate source code. When
118
+ * parsing or transformation fails, fall back to the original source —
119
+ * we don't want a transient parse error to crash Metro for a file the
120
+ * upstream might handle fine.
121
+ * @param args Metro args; `src` is the original source text.
122
+ * @returns Rewritten source text (with `className=` rewrites applied).
123
+ */
124
+ async function rewriteSource(args: BabelTransformerArgs): Promise<string> {
125
+ const ast = parseUserSource(args.src)
126
+ if (!ast) return args.src
127
+
128
+ const state = getRnwindState(projectRootOf(args))
129
+ const extension = extensionOf(args.filename)
130
+ const parsed = await state.parser.parseAtoms({ content: args.src, extension })
131
+
132
+ warnUnknownClasses(args.src, parsed.candidates, parsed.atoms, args.filename)
133
+
134
+ const classNamePrefixes = getClassNamePrefixes()
135
+ const hostSources = getHostSources()
136
+ const hostComponents = getHostComponents()
137
+ if (parsed.atoms.size === 0) {
138
+ state.builder.dropFile(args.filename)
139
+ await state.builder.writeSchemes()
140
+ transformAst(ast, {
141
+ styleSpecifiers: [],
142
+ gradientAtoms: parsed.gradientAtoms,
143
+ hapticAtoms: parsed.hapticAtoms,
144
+ classNamePrefixes,
145
+ hostSources,
146
+ hostComponents,
147
+ })
148
+ injectThemeSignatureImport(ast)
149
+ return generateModule(ast).code
150
+ }
151
+
152
+ const { changed } = await state.builder.recordFile(args.filename, parsed.atoms, parsed.keyframes)
153
+ if (changed) await state.builder.writeSchemes()
154
+
155
+ transformAst(ast, {
156
+ styleSpecifiers: STYLE_SPECIFIERS as unknown as readonly string[],
157
+ gradientAtoms: parsed.gradientAtoms,
158
+ hapticAtoms: parsed.hapticAtoms,
159
+ classNamePrefixes,
160
+ hostSources,
161
+ hostComponents,
162
+ })
163
+ injectThemeSignatureImport(ast)
164
+ return generateModule(ast).code
165
+ }
166
+
167
+ /**
168
+ * Prepend `import 'rnwind/__generated/theme-signature'` to every
169
+ * rnwind-transformed file. The resolver maps that specifier to the
170
+ * user's theme CSS so Metro's dependency graph carries a real edge
171
+ * from this JS file to the CSS. When the user edits `global.css`,
172
+ * the CSS module's SHA1 changes, and Metro invalidates every JS file
173
+ * holding this import — forcing them to re-transform with the new
174
+ * theme. The `.css` branch in {@link transform} returns an empty
175
+ * `export {}` module so the runtime cost is one extra `require()`.
176
+ * @param ast Babel File AST to mutate in place.
177
+ */
178
+ function injectThemeSignatureImport(ast: File): void {
179
+ const declaration = t.importDeclaration([], t.stringLiteral(THEME_SIGNATURE_MODULE))
180
+ ast.program.body.unshift(declaration)
181
+ }
182
+
183
+ /**
184
+ * Read the upstream transformer's `getCacheKey()` so our cache-key
185
+ * contribution composes with — rather than replaces — whatever the
186
+ * host framework wants to mix in.
187
+ * @returns Upstream cache key, or `null` when no upstream exposes one.
188
+ */
189
+ function loadUpstreamCacheKey(): string | null {
190
+ const upstream = loadUpstream() as (UpstreamTransformer & { getCacheKey?: () => string }) | null
191
+ if (!upstream) return null
192
+ try {
193
+ return typeof upstream.getCacheKey === 'function' ? upstream.getCacheKey() : null
194
+ } catch {
195
+ return null
196
+ }
197
+ }
198
+
199
+ /**
200
+ * Invoke the upstream `babelTransformerPath` Metro originally had
201
+ * configured. The path is read from `RNWIND_UPSTREAM_TRANSFORMER`,
202
+ * which `withRnwindConfig` sets at Metro startup. When the env var is
203
+ * unset (unit tests, standalone use), fall back to a typescript+jsx
204
+ * parse.
205
+ * @param args Metro's per-file args.
206
+ * @returns Upstream transform result containing the post-babel AST.
207
+ */
208
+ async function runUpstream(args: BabelTransformerArgs): Promise<BabelTransformerResult> {
209
+ if (args.ast && !process.env[UPSTREAM_ENV]) return { ast: args.ast }
210
+ const upstream = loadUpstream()
211
+ if (upstream) return await Promise.resolve(upstream.transform(args))
212
+ if (args.ast) return { ast: args.ast }
213
+ return { ast: parseSource(args.src) }
214
+ }
215
+
216
+ /**
217
+ * Lazily require the upstream transformer module. Cached after first
218
+ * load so per-file overhead is one cache lookup.
219
+ * @returns Upstream module, or null when env is unset.
220
+ */
221
+ function loadUpstream(): UpstreamTransformer | null {
222
+ if (cachedUpstream) return cachedUpstream
223
+ const upstreamPath = process.env[UPSTREAM_ENV]
224
+ if (!upstreamPath || upstreamPath.length === 0) return null
225
+ try {
226
+ // eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires
227
+ const required = require(upstreamPath) as UpstreamTransformer | { default?: UpstreamTransformer }
228
+ const upstream = (required as { default?: UpstreamTransformer }).default ?? (required as UpstreamTransformer)
229
+ if (typeof upstream.transform !== 'function') return null
230
+ cachedUpstream = upstream
231
+ return upstream
232
+ } catch (error) {
233
+ // eslint-disable-next-line no-console
234
+ if (process.env.RNWIND_DEBUG) console.error('rnwind: failed to load upstream transformer:', error)
235
+ return null
236
+ }
237
+ }
238
+
239
+ /**
240
+ * Cheap guard — the file has to look JS/TS, live outside `node_modules`,
241
+ * and mention `className=` before we spend AST cycles on it.
242
+ *
243
+ * Symlink awareness: monorepo workspaces (yarn / pnpm / bun workspaces)
244
+ * symlink each package into the consumer's `node_modules/<name>`, so a
245
+ * file from `packages/ui/src/Foo.tsx` ends up reaching the transformer
246
+ * as `<root>/node_modules/ui/src/Foo.tsx`. The naïve `/node_modules/`
247
+ * check would skip every workspace UI file. We `realpath` the filename
248
+ * once and only bail when the resolved real path is ALSO under
249
+ * node_modules — true third-party installs.
250
+ * @param args Metro args.
251
+ * @returns Whether the file might need the rnwind pass.
252
+ */
253
+ function isRewriteCandidate(args: BabelTransformerArgs): boolean {
254
+ if (!/\.(?:tsx|ts|jsx|js)$/i.test(args.filename)) return false
255
+ // Case-insensitive so `<prefix>ClassName=` (e.g. `contentContainerClassName=`)
256
+ // — which has a capital `C` and so doesn't contain the lowercase
257
+ // `className=` — still routes the file through the rewrite pass.
258
+ if (!/classname=/i.test(args.src)) return false
259
+ if (!args.filename.includes('/node_modules/')) return true
260
+ // node_modules in path → could be a workspace symlink; resolve it.
261
+ try {
262
+ return !realpathSync(args.filename).includes('/node_modules/')
263
+ } catch {
264
+ // realpath failed (broken symlink, missing file). Fall back to skipping.
265
+ return false
266
+ }
267
+ }
268
+
269
+ /**
270
+ * Fallback parse when no upstream is configured AND Metro didn't hand
271
+ * us an AST. Used by unit tests and standalone setups.
272
+ * @param source Source text.
273
+ * @returns Parsed Babel File.
274
+ */
275
+ function parseSource(source: string): File {
276
+ return parse(source, { sourceType: 'module', plugins: ['typescript', 'jsx'] }) as unknown as File
277
+ }
278
+
279
+ /** Metro's babel transformer signature. */
280
+ export interface BabelTransformerArgs {
281
+ filename: string
282
+ src: string
283
+ options: { projectRoot?: string; [key: string]: unknown }
284
+ ast?: File
285
+ plugins?: readonly unknown[]
286
+ }
287
+
288
+ /** Return shape Metro expects from a babel transformer. */
289
+ export interface BabelTransformerResult {
290
+ ast: File
291
+ metadata?: unknown
292
+ }
293
+
294
+ /**
295
+ * rnwind's Metro babel transformer. Two phases per source file:
296
+ *
297
+ * 1. **Pre-process the source string before handing it to the upstream
298
+ * babel pipeline.** babel-preset-expo / React's JSX transform run
299
+ * inside the upstream and convert `<View className="..."/>` into
300
+ * `React.createElement(View, {className})`. If we walked the AST
301
+ * AFTER the upstream, there'd be no JSX attributes left to
302
+ * rewrite. So we parse, run our pass, regenerate code, and feed
303
+ * THAT to the upstream as `src`.
304
+ * 2. **Delegate to the upstream `babelTransformerPath`** (Expo's
305
+ * default handles Flow stripping, expo-router macros, etc.).
306
+ *
307
+ * Skip both phases when the file isn't a JS/TS source under user
308
+ * code, or doesn't mention `className=` — hand straight to upstream.
309
+ * @param args Metro's per-file args.
310
+ * @returns Mutated AST + metadata.
311
+ */
312
+ export async function transform(args: BabelTransformerArgs): Promise<BabelTransformerResult> {
313
+ // Short-circuit `.css` inputs: the theme CSS is pulled into the dep
314
+ // graph as a sentinel (see `THEME_SIGNATURE_MODULE` in resolver.ts)
315
+ // so Metro watches it and invalidates importers on edit, but the
316
+ // file's CSS syntax can't go through a JS babel transformer.
317
+ //
318
+ // When the CSS being transformed IS the user's theme entry, we
319
+ // piggyback on Metro's own file-watcher: Metro calls us here on
320
+ // every CSS save; we trigger `onThemeChange` to rebuild parser +
321
+ // rewrite scheme files with the new values. Metro's dep graph then
322
+ // HMRs the regenerated `common.style.js` to the running app.
323
+ //
324
+ // Emitting the CSS content hash in the fake JS output is what makes
325
+ // Metro propagate invalidation to downstream importers — constant
326
+ // `export {}` bytes would never look changed and Metro would skip
327
+ // the chain.
328
+ if (args.filename.endsWith('.css')) {
329
+ if (isThemeCssEntry(args.filename)) {
330
+ try {
331
+ await onThemeChange(projectRootOf(args))
332
+ } catch {
333
+ // CSS edit happened outside a configured project (e.g. tests).
334
+ }
335
+ }
336
+ const themeHash = createHash('sha256').update(args.src).digest('hex').slice(0, 16)
337
+ const stub = `export const __rnwindThemeHash = ${JSON.stringify(themeHash)};\n`
338
+ return { ast: parse(stub, { sourceType: 'module' }) as unknown as File }
339
+ }
340
+ if (!isRewriteCandidate(args)) {
341
+ if (/\.(?:tsx|ts|jsx|js)$/i.test(args.filename) && !args.filename.includes('/node_modules/')) {
342
+ try {
343
+ getRnwindState(projectRootOf(args)).builder.dropFile(args.filename)
344
+ } catch {
345
+ // State not configured (e.g. test). Nothing to drop.
346
+ }
347
+ }
348
+ return runUpstream(args)
349
+ }
350
+
351
+ const rewrittenSource = await rewriteSource(args)
352
+ return runUpstream({ ...args, src: rewrittenSource, ast: undefined })
353
+ }
354
+
355
+ /**
356
+ * Metro's babel-transformer contract: a `getCacheKey()` export is
357
+ * sampled per-file and mixed into the transform cache key. Returning
358
+ * a string that includes the theme CSS content hash invalidates every
359
+ * cached transform on every CSS edit — so the bundle rebuilds with
360
+ * the new theme automatically on the next request.
361
+ * @returns Cache-key segment that includes rnwind's current theme hash.
362
+ */
363
+ export function getCacheKey(): string {
364
+ const upstreamKey = loadUpstreamCacheKey()
365
+ const ownKey = getRnwindCacheKey()
366
+ return upstreamKey ? `${upstreamKey}|${ownKey}` : ownKey
367
+ }
368
+
369
+ /** Test-only — drop the cached upstream so a new env var picks up next call. */
370
+ export function __resetUpstreamCache(): void {
371
+ cachedUpstream = null
372
+ }
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Yield every literal-text segment found at a `className=` site.
3
+ * @param source Raw source text.
4
+ * @yields Each literal's inner text.
5
+ */
6
+ function* iterateClassNameLiterals(source: string): Iterable<string> {
7
+ // className="..." / className='...'
8
+ for (const match of source.matchAll(/className\s*=\s*"([^"]*)"/g)) yield match[1] ?? ''
9
+ for (const match of source.matchAll(/className\s*=\s*'([^']*)'/g)) yield match[1] ?? ''
10
+ // className={"..."} / className={'...'}
11
+ for (const match of source.matchAll(/className\s*=\s*\{\s*"([^"]*)"\s*\}/g)) yield match[1] ?? ''
12
+ for (const match of source.matchAll(/className\s*=\s*\{\s*'([^']*)'\s*\}/g)) yield match[1] ?? ''
13
+ // className={`...`} — yield each static quasi between `${...}` substitutions.
14
+ for (const match of source.matchAll(/className\s*=\s*\{\s*`([^`]*)`\s*\}/g)) {
15
+ const body = match[1] ?? ''
16
+ for (const part of body.split(/\$\{[^}]*\}/)) yield part
17
+ }
18
+ }
19
+
20
+ /**
21
+ * Pull every `className="…"`, `className={'…'}`, `className={"…"}`, and
22
+ * `className={\`…\`}` literal out of the source and union their
23
+ * whitespace-separated tokens. A regex-based scan is enough — the
24
+ * warning is best-effort, not load-bearing, and a regex sidesteps
25
+ * having to re-parse the file.
26
+ *
27
+ * Skipped on purpose:
28
+ * - `className={someExpression}` with no inline literal (we can't
29
+ * introspect the runtime value at build time).
30
+ * - Template literals with substitutions (`` `text-${size}` ``) — we
31
+ * only union the static-quasi parts, which is fine because the
32
+ * warning fires only on candidates that ARE in the static parts.
33
+ * @param source Raw source text.
34
+ * @returns Set of whitespace-separated tokens drawn from every literal.
35
+ */
36
+ function collectClassNameTokens(source: string): Set<string> {
37
+ const out = new Set<string>()
38
+ for (const literal of iterateClassNameLiterals(source)) {
39
+ for (const token of literal.split(/\s+/)) {
40
+ if (token.length > 0) out.add(token)
41
+ }
42
+ }
43
+ return out
44
+ }
45
+
46
+ /**
47
+ * Filter Tailwind candidate strings down to ones that actually appear
48
+ * as a token inside a `className="…"` literal in the source. Oxide
49
+ * scans the entire file and surfaces anything Tailwind-shaped — that
50
+ * includes import specifiers (`'expo-router'`), comment markers
51
+ * (`/* @rnwind-theme=… *\/`), JSX prop values (`keyboardType="email-
52
+ * address"`), and bare suffixes Tailwind splits out from compound
53
+ * utilities (`bg-sky-500` also produces `sky-500`). None of those are
54
+ * "unknown classes" worth nagging the user about; the genuine signal
55
+ * is a typo in a real `className`, e.g. `bg-srface` for `bg-surface`.
56
+ *
57
+ * The filter walks every `className="…" / {'…'} / {`…`}` literal in the
58
+ * source, splits each on whitespace, and unions the tokens. Only
59
+ * candidates in that token set survive. Then known-good atoms are
60
+ * subtracted, leaving genuine typos.
61
+ * @param source Raw source text the transformer received from Metro.
62
+ * @param candidates Every candidate oxide picked up.
63
+ * @param atoms Set of atom names the parser successfully resolved.
64
+ * @returns Candidates that look like real "unknown classes" the user typed.
65
+ */
66
+ export function filterUnknownClassCandidates(
67
+ source: string,
68
+ candidates: readonly string[],
69
+ atoms: ReadonlySet<string>,
70
+ ): string[] {
71
+ const literalTokens = collectClassNameTokens(source)
72
+ const out: string[] = []
73
+ for (const candidate of candidates) {
74
+ if (atoms.has(candidate)) continue
75
+ if (!literalTokens.has(candidate)) continue
76
+ out.push(candidate)
77
+ }
78
+ return out
79
+ }