@tamagui/static 1.0.1-beta.21 → 1.0.1-beta.211

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 (260) hide show
  1. package/dist/{cjs/constants.js → constants.js} +9 -4
  2. package/dist/constants.js.map +7 -0
  3. package/dist/{cjs/extractor → extractor}/accessSafe.js +14 -4
  4. package/dist/{esm/extractor → extractor}/accessSafe.js.map +2 -2
  5. package/dist/{cjs/extractor → extractor}/babelParse.js +20 -17
  6. package/dist/extractor/babelParse.js.map +7 -0
  7. package/dist/{cjs/extractor → extractor}/buildClassName.js +40 -11
  8. package/dist/extractor/buildClassName.js.map +7 -0
  9. package/dist/extractor/bundle.js +117 -0
  10. package/dist/extractor/bundle.js.map +7 -0
  11. package/dist/{cjs/extractor → extractor}/createEvaluator.js +19 -14
  12. package/dist/extractor/createEvaluator.js.map +7 -0
  13. package/dist/extractor/createExtractor.js +1645 -0
  14. package/dist/extractor/createExtractor.js.map +7 -0
  15. package/dist/{cjs/extractor → extractor}/ensureImportingConcat.js +18 -8
  16. package/dist/extractor/ensureImportingConcat.js.map +7 -0
  17. package/dist/{cjs/extractor → extractor}/evaluateAstNode.js +14 -6
  18. package/dist/{esm/extractor → extractor}/evaluateAstNode.js.map +2 -2
  19. package/dist/{cjs/extractor → extractor}/extractHelpers.js +91 -27
  20. package/dist/extractor/extractHelpers.js.map +7 -0
  21. package/dist/{cjs/extractor → extractor}/extractMediaStyle.js +49 -50
  22. package/dist/extractor/extractMediaStyle.js.map +7 -0
  23. package/dist/{cjs/extractor → extractor}/extractToClassNames.js +165 -109
  24. package/dist/extractor/extractToClassNames.js.map +7 -0
  25. package/dist/{cjs/extractor → extractor}/findTopmostFunction.js +2 -3
  26. package/dist/{esm/extractor → extractor}/findTopmostFunction.js.map +2 -2
  27. package/dist/{cjs/extractor → extractor}/generatedUid.js +9 -4
  28. package/dist/{cjs/extractor → extractor}/generatedUid.js.map +3 -3
  29. package/dist/{cjs/extractor → extractor}/getPrefixLogs.js +1 -2
  30. package/dist/extractor/getPrefixLogs.js.map +7 -0
  31. package/dist/{cjs/extractor → extractor}/getPropValueFromAttributes.js +24 -15
  32. package/dist/extractor/getPropValueFromAttributes.js.map +7 -0
  33. package/dist/{cjs/extractor → extractor}/getSourceModule.js +5 -3
  34. package/dist/{esm/extractor → extractor}/getSourceModule.js.map +2 -2
  35. package/dist/{cjs/extractor → extractor}/getStaticBindingsForScope.js +88 -38
  36. package/dist/extractor/getStaticBindingsForScope.js.map +7 -0
  37. package/dist/{cjs/extractor → extractor}/hoistClassNames.js +5 -4
  38. package/dist/{esm/extractor → extractor}/hoistClassNames.js.map +3 -3
  39. package/dist/{cjs/extractor → extractor}/literalToAst.js +26 -34
  40. package/dist/{cjs/extractor → extractor}/literalToAst.js.map +2 -2
  41. package/dist/extractor/loadFile.js +21 -0
  42. package/dist/extractor/loadFile.js.map +7 -0
  43. package/dist/extractor/loadTamagui.js +421 -0
  44. package/dist/extractor/loadTamagui.js.map +7 -0
  45. package/dist/{cjs/extractor → extractor}/logLines.js +3 -3
  46. package/dist/{cjs/extractor → extractor}/logLines.js.map +2 -2
  47. package/dist/{cjs/extractor → extractor}/normalizeTernaries.js +13 -36
  48. package/dist/extractor/normalizeTernaries.js.map +7 -0
  49. package/dist/{cjs/extractor → extractor}/removeUnusedHooks.js +7 -5
  50. package/dist/{cjs/extractor → extractor}/removeUnusedHooks.js.map +2 -2
  51. package/dist/{cjs/extractor → extractor}/timer.js +11 -4
  52. package/dist/extractor/timer.js.map +7 -0
  53. package/dist/{cjs/extractor → extractor}/validHTMLAttributes.js +52 -0
  54. package/dist/extractor/validHTMLAttributes.js.map +7 -0
  55. package/dist/getPragmaOptions.js +68 -0
  56. package/dist/getPragmaOptions.js.map +7 -0
  57. package/dist/helpers/memoize.js +46 -0
  58. package/dist/helpers/memoize.js.map +7 -0
  59. package/dist/{cjs/index.js → index.js} +10 -7
  60. package/dist/index.js.map +7 -0
  61. package/dist/require.js +90 -0
  62. package/dist/require.js.map +7 -0
  63. package/dist/tamagui-node/tamagui.config.js +6781 -0
  64. package/dist/{jsx/types.js → tamagui-node/tamaguicore-components.config.js} +0 -0
  65. package/dist/tamagui-node/tamaguitestdesignsystem-components.config.js +31 -0
  66. package/dist/{cjs/types.js → types.js} +1 -0
  67. package/dist/types.js.map +7 -0
  68. package/dist/webpackPlugin.js +35 -0
  69. package/dist/webpackPlugin.js.map +7 -0
  70. package/package.json +47 -35
  71. package/src/constants.ts +14 -0
  72. package/src/extractor/accessSafe.ts +18 -0
  73. package/src/extractor/babelParse.ts +28 -0
  74. package/src/extractor/buildClassName.ts +77 -0
  75. package/src/extractor/bundle.ts +110 -0
  76. package/src/extractor/createEvaluator.ts +73 -0
  77. package/src/extractor/createExtractor.ts +2133 -0
  78. package/src/extractor/ensureImportingConcat.ts +32 -0
  79. package/src/extractor/evaluateAstNode.ts +121 -0
  80. package/src/extractor/extractHelpers.ts +201 -0
  81. package/src/extractor/extractMediaStyle.ts +199 -0
  82. package/src/extractor/extractToClassNames.ts +450 -0
  83. package/src/extractor/findTopmostFunction.ts +22 -0
  84. package/src/extractor/generatedUid.ts +43 -0
  85. package/src/extractor/getPrefixLogs.ts +6 -0
  86. package/src/extractor/getPropValueFromAttributes.ts +92 -0
  87. package/src/extractor/getSourceModule.ts +101 -0
  88. package/src/extractor/getStaticBindingsForScope.ts +227 -0
  89. package/src/extractor/hoistClassNames.ts +45 -0
  90. package/src/extractor/literalToAst.ts +84 -0
  91. package/src/extractor/loadFile.ts +17 -0
  92. package/src/extractor/loadTamagui.ts +480 -0
  93. package/src/extractor/logLines.ts +16 -0
  94. package/src/extractor/normalizeTernaries.ts +63 -0
  95. package/src/extractor/removeUnusedHooks.ts +76 -0
  96. package/src/extractor/timer.ts +29 -0
  97. package/src/extractor/validHTMLAttributes.ts +99 -0
  98. package/src/getPragmaOptions.ts +53 -0
  99. package/src/helpers/memoize.ts +21 -0
  100. package/src/index.ts +11 -0
  101. package/src/require.ts +107 -0
  102. package/src/types.ts +98 -0
  103. package/src/webpackPlugin.ts +9 -0
  104. package/tamagui.tsconfig.json +5 -0
  105. package/types/constants.d.ts +1 -1
  106. package/types/extractor/babelParse.d.ts +2 -1
  107. package/types/extractor/buildClassName.d.ts +5 -2
  108. package/types/extractor/bundle.d.ts +13 -0
  109. package/types/extractor/createEvaluator.d.ts +4 -4
  110. package/types/extractor/createExtractor.d.ts +26 -11
  111. package/types/extractor/extractHelpers.d.ts +16 -4
  112. package/types/extractor/extractMediaStyle.d.ts +3 -3
  113. package/types/extractor/extractToClassNames.d.ts +5 -9
  114. package/types/extractor/getPrefixLogs.d.ts +1 -1
  115. package/types/extractor/getPropValueFromAttributes.d.ts +16 -0
  116. package/types/extractor/getStaticBindingsForScope.d.ts +2 -1
  117. package/types/extractor/loadFile.d.ts +1 -0
  118. package/types/extractor/loadTamagui.d.ts +22 -6
  119. package/types/extractor/normalizeTernaries.d.ts +1 -1
  120. package/types/extractor/validHTMLAttributes.d.ts +49 -0
  121. package/types/getPragmaOptions.d.ts +9 -0
  122. package/types/helpers/memoize.d.ts +8 -0
  123. package/types/index.d.ts +9 -7
  124. package/types/require.d.ts +4 -0
  125. package/types/types.d.ts +32 -32
  126. package/types/webpackPlugin.d.ts +4 -0
  127. package/dist/cjs/constants.js.map +0 -7
  128. package/dist/cjs/extractor/accessSafe.js.map +0 -7
  129. package/dist/cjs/extractor/babelParse.js.map +0 -7
  130. package/dist/cjs/extractor/buildClassName.js.map +0 -7
  131. package/dist/cjs/extractor/createEvaluator.js.map +0 -7
  132. package/dist/cjs/extractor/createExtractor.js +0 -1221
  133. package/dist/cjs/extractor/createExtractor.js.map +0 -7
  134. package/dist/cjs/extractor/ensureImportingConcat.js.map +0 -7
  135. package/dist/cjs/extractor/evaluateAstNode.js.map +0 -7
  136. package/dist/cjs/extractor/extractHelpers.js.map +0 -7
  137. package/dist/cjs/extractor/extractMediaStyle.js.map +0 -7
  138. package/dist/cjs/extractor/extractToClassNames.js.map +0 -7
  139. package/dist/cjs/extractor/findTopmostFunction.js.map +0 -7
  140. package/dist/cjs/extractor/getPrefixLogs.js.map +0 -7
  141. package/dist/cjs/extractor/getPropValueFromAttributes.js.map +0 -7
  142. package/dist/cjs/extractor/getSourceModule.js.map +0 -7
  143. package/dist/cjs/extractor/getStaticBindingsForScope.js.map +0 -7
  144. package/dist/cjs/extractor/hoistClassNames.js.map +0 -7
  145. package/dist/cjs/extractor/loadTamagui.js +0 -106
  146. package/dist/cjs/extractor/loadTamagui.js.map +0 -7
  147. package/dist/cjs/extractor/normalizeTernaries.js.map +0 -7
  148. package/dist/cjs/extractor/timer.js.map +0 -7
  149. package/dist/cjs/extractor/validHTMLAttributes.js.map +0 -7
  150. package/dist/cjs/index.js.map +0 -7
  151. package/dist/cjs/patchReactNativeWeb.js +0 -167
  152. package/dist/cjs/patchReactNativeWeb.js.map +0 -7
  153. package/dist/cjs/types.js.map +0 -7
  154. package/dist/esm/constants.js +0 -14
  155. package/dist/esm/constants.js.map +0 -7
  156. package/dist/esm/extractor/accessSafe.js +0 -11
  157. package/dist/esm/extractor/babelParse.js +0 -30
  158. package/dist/esm/extractor/babelParse.js.map +0 -7
  159. package/dist/esm/extractor/buildClassName.js +0 -40
  160. package/dist/esm/extractor/buildClassName.js.map +0 -7
  161. package/dist/esm/extractor/createEvaluator.js +0 -52
  162. package/dist/esm/extractor/createEvaluator.js.map +0 -7
  163. package/dist/esm/extractor/createExtractor.js +0 -1169
  164. package/dist/esm/extractor/createExtractor.js.map +0 -7
  165. package/dist/esm/extractor/ensureImportingConcat.js +0 -24
  166. package/dist/esm/extractor/ensureImportingConcat.js.map +0 -7
  167. package/dist/esm/extractor/evaluateAstNode.js +0 -94
  168. package/dist/esm/extractor/extractHelpers.js +0 -103
  169. package/dist/esm/extractor/extractHelpers.js.map +0 -7
  170. package/dist/esm/extractor/extractMediaStyle.js +0 -152
  171. package/dist/esm/extractor/extractMediaStyle.js.map +0 -7
  172. package/dist/esm/extractor/extractToClassNames.js +0 -293
  173. package/dist/esm/extractor/extractToClassNames.js.map +0 -7
  174. package/dist/esm/extractor/findTopmostFunction.js +0 -23
  175. package/dist/esm/extractor/generatedUid.js +0 -28
  176. package/dist/esm/extractor/generatedUid.js.map +0 -7
  177. package/dist/esm/extractor/getPrefixLogs.js +0 -12
  178. package/dist/esm/extractor/getPrefixLogs.js.map +0 -7
  179. package/dist/esm/extractor/getPropValueFromAttributes.js +0 -49
  180. package/dist/esm/extractor/getPropValueFromAttributes.js.map +0 -7
  181. package/dist/esm/extractor/getSourceModule.js +0 -69
  182. package/dist/esm/extractor/getStaticBindingsForScope.js +0 -137
  183. package/dist/esm/extractor/getStaticBindingsForScope.js.map +0 -7
  184. package/dist/esm/extractor/hoistClassNames.js +0 -44
  185. package/dist/esm/extractor/literalToAst.js +0 -80
  186. package/dist/esm/extractor/literalToAst.js.map +0 -7
  187. package/dist/esm/extractor/loadTamagui.js +0 -84
  188. package/dist/esm/extractor/loadTamagui.js.map +0 -7
  189. package/dist/esm/extractor/logLines.js +0 -22
  190. package/dist/esm/extractor/logLines.js.map +0 -7
  191. package/dist/esm/extractor/normalizeTernaries.js +0 -53
  192. package/dist/esm/extractor/normalizeTernaries.js.map +0 -7
  193. package/dist/esm/extractor/removeUnusedHooks.js +0 -80
  194. package/dist/esm/extractor/removeUnusedHooks.js.map +0 -7
  195. package/dist/esm/extractor/timer.js +0 -24
  196. package/dist/esm/extractor/timer.js.map +0 -7
  197. package/dist/esm/extractor/validHTMLAttributes.js +0 -52
  198. package/dist/esm/extractor/validHTMLAttributes.js.map +0 -7
  199. package/dist/esm/index.js +0 -14
  200. package/dist/esm/index.js.map +0 -7
  201. package/dist/esm/patchReactNativeWeb.js +0 -142
  202. package/dist/esm/patchReactNativeWeb.js.map +0 -7
  203. package/dist/esm/types.js +0 -1
  204. package/dist/esm/types.js.map +0 -7
  205. package/dist/jsx/constants.js +0 -13
  206. package/dist/jsx/extractor/accessSafe.js +0 -10
  207. package/dist/jsx/extractor/babelParse.js +0 -29
  208. package/dist/jsx/extractor/buildClassName.js +0 -39
  209. package/dist/jsx/extractor/createEvaluator.js +0 -51
  210. package/dist/jsx/extractor/createExtractor.js +0 -1168
  211. package/dist/jsx/extractor/ensureImportingConcat.js +0 -23
  212. package/dist/jsx/extractor/evaluateAstNode.js +0 -93
  213. package/dist/jsx/extractor/extractHelpers.js +0 -102
  214. package/dist/jsx/extractor/extractMediaStyle.js +0 -151
  215. package/dist/jsx/extractor/extractToClassNames.js +0 -292
  216. package/dist/jsx/extractor/findTopmostFunction.js +0 -22
  217. package/dist/jsx/extractor/generatedUid.js +0 -27
  218. package/dist/jsx/extractor/getPrefixLogs.js +0 -11
  219. package/dist/jsx/extractor/getPropValueFromAttributes.js +0 -48
  220. package/dist/jsx/extractor/getSourceModule.js +0 -68
  221. package/dist/jsx/extractor/getStaticBindingsForScope.js +0 -136
  222. package/dist/jsx/extractor/hoistClassNames.js +0 -43
  223. package/dist/jsx/extractor/literalToAst.js +0 -79
  224. package/dist/jsx/extractor/loadTamagui.js +0 -83
  225. package/dist/jsx/extractor/logLines.js +0 -21
  226. package/dist/jsx/extractor/normalizeTernaries.js +0 -52
  227. package/dist/jsx/extractor/removeUnusedHooks.js +0 -79
  228. package/dist/jsx/extractor/timer.js +0 -23
  229. package/dist/jsx/extractor/validHTMLAttributes.js +0 -51
  230. package/dist/jsx/index.js +0 -13
  231. package/dist/jsx/patchReactNativeWeb.js +0 -141
  232. package/types/constants.d.ts.map +0 -1
  233. package/types/extractor/accessSafe.d.ts.map +0 -1
  234. package/types/extractor/babelParse.d.ts.map +0 -1
  235. package/types/extractor/buildClassName.d.ts.map +0 -1
  236. package/types/extractor/createEvaluator.d.ts.map +0 -1
  237. package/types/extractor/createExtractor.d.ts.map +0 -1
  238. package/types/extractor/ensureImportingConcat.d.ts.map +0 -1
  239. package/types/extractor/evaluateAstNode.d.ts.map +0 -1
  240. package/types/extractor/extractHelpers.d.ts.map +0 -1
  241. package/types/extractor/extractMediaStyle.d.ts.map +0 -1
  242. package/types/extractor/extractToClassNames.d.ts.map +0 -1
  243. package/types/extractor/findTopmostFunction.d.ts.map +0 -1
  244. package/types/extractor/generatedUid.d.ts.map +0 -1
  245. package/types/extractor/getPrefixLogs.d.ts.map +0 -1
  246. package/types/extractor/getPropValueFromAttributes.d.ts.map +0 -1
  247. package/types/extractor/getSourceModule.d.ts.map +0 -1
  248. package/types/extractor/getStaticBindingsForScope.d.ts.map +0 -1
  249. package/types/extractor/hoistClassNames.d.ts.map +0 -1
  250. package/types/extractor/literalToAst.d.ts.map +0 -1
  251. package/types/extractor/loadTamagui.d.ts.map +0 -1
  252. package/types/extractor/logLines.d.ts.map +0 -1
  253. package/types/extractor/normalizeTernaries.d.ts.map +0 -1
  254. package/types/extractor/removeUnusedHooks.d.ts.map +0 -1
  255. package/types/extractor/timer.d.ts.map +0 -1
  256. package/types/extractor/validHTMLAttributes.d.ts.map +0 -1
  257. package/types/index.d.ts.map +0 -1
  258. package/types/patchReactNativeWeb.d.ts +0 -2
  259. package/types/patchReactNativeWeb.d.ts.map +0 -1
  260. package/types/types.d.ts.map +0 -1
@@ -0,0 +1,32 @@
1
+ import { NodePath } from '@babel/traverse'
2
+ import * as t from '@babel/types'
3
+
4
+ const importConcatPkg = '@tamagui/helpers'
5
+
6
+ export function ensureImportingConcat(path: NodePath<t.Program>) {
7
+ const bodyPath = path.get('body')
8
+ const imported: NodePath<t.ImportDeclaration> | undefined = bodyPath.find(
9
+ (x) => x.isImportDeclaration() && x.node.source.value === importConcatPkg
10
+ ) as any
11
+ const importSpecifier = t.importSpecifier(
12
+ t.identifier('concatClassName'),
13
+ t.identifier('concatClassName')
14
+ )
15
+
16
+ if (!imported) {
17
+ path.node.body.push(t.importDeclaration([importSpecifier], t.stringLiteral(importConcatPkg)))
18
+ return
19
+ }
20
+
21
+ const specifiers = imported.node.specifiers
22
+ const alreadyImported = specifiers.some(
23
+ (x) =>
24
+ t.isImportSpecifier(x) && t.isIdentifier(x.imported) && x.imported.name === 'concatClassName'
25
+ )
26
+
27
+ if (!alreadyImported) {
28
+ specifiers.push(
29
+ t.importSpecifier(t.identifier('concatClassName'), t.identifier('concatClassName'))
30
+ )
31
+ }
32
+ }
@@ -0,0 +1,121 @@
1
+ import * as t from '@babel/types'
2
+
3
+ export function evaluateAstNode(
4
+ exprNode: t.Node | undefined | null,
5
+ evalFn?: (node: t.Node) => any,
6
+ shouldPrintDebug?: boolean | 'verbose'
7
+ ): any {
8
+ if (exprNode === undefined) {
9
+ return undefined
10
+ }
11
+
12
+ // null === boolean true (at least in our use cases for jsx eval)
13
+ if (exprNode === null) {
14
+ return true
15
+ }
16
+
17
+ if (t.isJSXExpressionContainer(exprNode)) {
18
+ return evaluateAstNode(exprNode.expression)
19
+ }
20
+
21
+ // loop through ObjectExpression keys
22
+ if (t.isObjectExpression(exprNode)) {
23
+ const ret: Record<string, any> = {}
24
+ for (let idx = -1, len = exprNode.properties.length; ++idx < len; ) {
25
+ const value = exprNode.properties[idx]
26
+
27
+ if (!t.isObjectProperty(value)) {
28
+ throw new Error('evaluateAstNode can only evaluate object properties')
29
+ }
30
+
31
+ let key: string | number | null | undefined | boolean
32
+ if (value.computed) {
33
+ if (typeof evalFn !== 'function') {
34
+ throw new Error(
35
+ 'evaluateAstNode does not support computed keys unless an eval function is provided'
36
+ )
37
+ }
38
+ key = evaluateAstNode(value.key, evalFn)
39
+ } else if (t.isIdentifier(value.key)) {
40
+ key = value.key.name
41
+ } else if (t.isStringLiteral(value.key) || t.isNumericLiteral(value.key)) {
42
+ key = value.key.value
43
+ } else {
44
+ throw new Error('Unsupported key type: ' + value.key.type)
45
+ }
46
+
47
+ if (typeof key !== 'string' && typeof key !== 'number') {
48
+ throw new Error('key must be either a string or a number')
49
+ }
50
+
51
+ ret[key] = evaluateAstNode(value.value, evalFn)
52
+ }
53
+ return ret
54
+ }
55
+
56
+ if (t.isArrayExpression(exprNode)) {
57
+ return exprNode.elements.map((x) => {
58
+ return evaluateAstNode(x as any, evalFn)
59
+ })
60
+ }
61
+
62
+ if (t.isUnaryExpression(exprNode) && exprNode.operator === '-') {
63
+ const ret = evaluateAstNode(exprNode.argument, evalFn)
64
+ if (ret == null) {
65
+ return null
66
+ }
67
+ return -ret
68
+ }
69
+
70
+ if (t.isTemplateLiteral(exprNode)) {
71
+ if (typeof evalFn !== 'function') {
72
+ throw new Error(
73
+ 'evaluateAstNode does not support template literals unless an eval function is provided'
74
+ )
75
+ }
76
+
77
+ let ret: string = ''
78
+ for (let idx = -1, len = exprNode.quasis.length; ++idx < len; ) {
79
+ const quasi = exprNode.quasis[idx]
80
+ const expr = exprNode.expressions[idx]
81
+ ret += quasi.value.raw
82
+ if (expr) {
83
+ ret += evaluateAstNode(expr, evalFn)
84
+ }
85
+ }
86
+ return ret
87
+ }
88
+
89
+ // In the interest of representing the "evaluated" prop
90
+ // as the user intended, we support negative null. Why not.
91
+ if (t.isNullLiteral(exprNode)) {
92
+ return null
93
+ }
94
+
95
+ if (t.isNumericLiteral(exprNode) || t.isStringLiteral(exprNode) || t.isBooleanLiteral(exprNode)) {
96
+ // In the interest of representing the "evaluated" prop
97
+ // as the user intended, we support negative null. Why not.
98
+ return exprNode.value
99
+ }
100
+
101
+ if (t.isBinaryExpression(exprNode)) {
102
+ if (exprNode.operator === '+') {
103
+ return evaluateAstNode(exprNode.left, evalFn) + evaluateAstNode(exprNode.right, evalFn)
104
+ } else if (exprNode.operator === '-') {
105
+ return evaluateAstNode(exprNode.left, evalFn) - evaluateAstNode(exprNode.right, evalFn)
106
+ } else if (exprNode.operator === '*') {
107
+ return evaluateAstNode(exprNode.left, evalFn) * evaluateAstNode(exprNode.right, evalFn)
108
+ } else if (exprNode.operator === '/') {
109
+ return evaluateAstNode(exprNode.left, evalFn) / evaluateAstNode(exprNode.right, evalFn)
110
+ }
111
+ }
112
+
113
+ // if we've made it this far, the value has to be evaluated
114
+ if (typeof evalFn !== 'function') {
115
+ throw new Error(
116
+ 'evaluateAstNode does not support non-literal values unless an eval function is provided'
117
+ )
118
+ }
119
+
120
+ return evalFn(exprNode)
121
+ }
@@ -0,0 +1,201 @@
1
+ import { basename, relative } from 'path'
2
+
3
+ import generate from '@babel/generator'
4
+ import type { NodePath } from '@babel/traverse'
5
+ import * as t from '@babel/types'
6
+ import findRoot from 'find-root'
7
+
8
+ import { memoize } from '../helpers/memoize.js'
9
+ import type { ExtractedAttr, TamaguiOptionsWithFileInfo, Ternary } from '../types.js'
10
+
11
+ // import { astToLiteral } from './literalToAst'
12
+
13
+ export function isPresent<T extends Object>(input: null | void | undefined | T): input is T {
14
+ return input != null
15
+ }
16
+
17
+ export function isSimpleSpread(node: t.JSXSpreadAttribute) {
18
+ return t.isIdentifier(node.argument) || t.isMemberExpression(node.argument)
19
+ }
20
+
21
+ export const attrStr = (attr?: ExtractedAttr) => {
22
+ return !attr
23
+ ? ''
24
+ : attr.type === 'attr'
25
+ ? getNameAttr(attr.value)
26
+ : attr.type === 'ternary'
27
+ ? `...${ternaryStr(attr.value)}`
28
+ : `${attr.type}(${objToStr(attr.value)})`
29
+ }
30
+
31
+ export const objToStr = (obj: any, spacer = ', ') => {
32
+ if (!obj) {
33
+ return `${obj}`
34
+ }
35
+ return `{${Object.entries(obj)
36
+ .map(
37
+ ([k, v]) =>
38
+ `${k}:${
39
+ Array.isArray(v)
40
+ ? `[...]`
41
+ : v && typeof v === 'object'
42
+ ? `${objToStr(v, ',')}`
43
+ : JSON.stringify(v)
44
+ }`
45
+ )
46
+ .join(spacer)}}`
47
+ }
48
+
49
+ const getNameAttr = (attr: t.JSXAttribute | t.JSXSpreadAttribute) => {
50
+ if (t.isJSXSpreadAttribute(attr)) {
51
+ return `...${attr.argument['name']}`
52
+ }
53
+ return 'name' in attr ? attr.name.name : `unknown-${attr['type']}`
54
+ }
55
+
56
+ export const ternaryStr = (x: Ternary) => {
57
+ const conditional = t.isIdentifier(x.test)
58
+ ? x.test.name
59
+ : t.isMemberExpression(x.test)
60
+ ? [x.test.object['name'], x.test.property['name']]
61
+ : generate(x.test as any).code
62
+ return [
63
+ 'ternary(',
64
+ conditional,
65
+ isFilledObj(x.consequent) ? ` ? ${objToStr(x.consequent)}` : ' ? 🚫',
66
+ isFilledObj(x.alternate) ? ` : ${objToStr(x.alternate)}` : ' : 🚫',
67
+ ')',
68
+ ]
69
+ .flat()
70
+ .join('')
71
+ }
72
+
73
+ const isFilledObj = (obj: any) => obj && Object.keys(obj).length
74
+
75
+ export function findComponentName(scope) {
76
+ const componentName = ''
77
+ let cur = scope.path
78
+ while (cur.parentPath && !t.isProgram(cur.parentPath.parent)) {
79
+ cur = cur.parentPath
80
+ }
81
+ let node = cur.parent
82
+ if (t.isExportNamedDeclaration(node)) {
83
+ node = node.declaration
84
+ }
85
+ if (t.isVariableDeclaration(node)) {
86
+ const [dec] = node.declarations
87
+ if (t.isVariableDeclarator(dec) && t.isIdentifier(dec.id)) {
88
+ return dec.id.name
89
+ }
90
+ }
91
+ if (t.isFunctionDeclaration(node)) {
92
+ return node.id?.name
93
+ }
94
+ return componentName
95
+ }
96
+
97
+ export function isValidThemeHook(
98
+ props: TamaguiOptionsWithFileInfo,
99
+ jsxPath: NodePath<t.JSXElement>,
100
+ n: t.MemberExpression,
101
+ sourcePath: string
102
+ ) {
103
+ if (!t.isIdentifier(n.object) || !t.isIdentifier(n.property)) return false
104
+ const bindings = jsxPath.scope.getAllBindings()
105
+ const binding = bindings[n.object.name]
106
+ if (!binding?.path) return false
107
+ if (!binding.path.isVariableDeclarator()) return false
108
+ const init = binding.path.node.init
109
+ if (!t.isCallExpression(init)) return false
110
+ if (!t.isIdentifier(init.callee)) return false
111
+ // TODO could support renaming useTheme by looking up import first
112
+ if (init.callee.name !== 'useTheme') return false
113
+ const importNode = binding.scope.getBinding('useTheme')?.path.parent
114
+ if (!t.isImportDeclaration(importNode)) return false
115
+ if (!isValidImport(props, sourcePath)) {
116
+ return false
117
+ }
118
+ return true
119
+ }
120
+
121
+ export const isInsideComponentPackage = (props: TamaguiOptionsWithFileInfo, moduleName: string) => {
122
+ return getValidComponentsPaths(props).some((path) => {
123
+ return moduleName.startsWith(path)
124
+ })
125
+ }
126
+
127
+ export const isComponentPackage = (props: TamaguiOptionsWithFileInfo, srcName: string) => {
128
+ return getValidComponentsPaths(props).some((path) => {
129
+ return srcName.startsWith(path)
130
+ })
131
+ }
132
+
133
+ export function getValidComponent(
134
+ props: TamaguiOptionsWithFileInfo,
135
+ moduleName: string,
136
+ componentName: string
137
+ ) {
138
+ // must be uppercase of course
139
+ if (componentName[0].toUpperCase() !== componentName[0]) {
140
+ return false
141
+ }
142
+
143
+ for (const loaded of props.allLoadedComponents) {
144
+ const isInModule = moduleName === '*' || moduleName.startsWith(loaded.moduleName)
145
+ const foundComponent = loaded.nameToInfo[componentName]
146
+ // eslint-disable-next-line no-console
147
+ if (isInModule && foundComponent) {
148
+ return foundComponent
149
+ }
150
+ }
151
+
152
+ return null
153
+ }
154
+
155
+ export const isValidModule = (props: TamaguiOptionsWithFileInfo, moduleName: string) => {
156
+ if (typeof moduleName !== 'string') {
157
+ throw new Error(`No module name`)
158
+ }
159
+ const isLocal = moduleName.startsWith('.')
160
+ return {
161
+ isLocal,
162
+ isValid: isLocal
163
+ ? isInsideComponentPackage(props, moduleName)
164
+ : isComponentPackage(props, moduleName),
165
+ }
166
+ }
167
+
168
+ export const getValidImport = (
169
+ props: TamaguiOptionsWithFileInfo,
170
+ moduleName: string,
171
+ componentName?: string
172
+ ) => {
173
+ const { isValid, isLocal } = isValidModule(props, moduleName)
174
+ if (!isValid || !componentName) {
175
+ return null
176
+ }
177
+ return getValidComponent(props, isLocal ? '*' : moduleName, componentName) || null
178
+ }
179
+
180
+ export const isValidImport = (
181
+ props: TamaguiOptionsWithFileInfo,
182
+ moduleName: string,
183
+ componentName?: string
184
+ ) => {
185
+ if (!componentName) {
186
+ return isValidModule(props, moduleName).isValid
187
+ }
188
+ return Boolean(getValidImport(props, moduleName, componentName))
189
+ }
190
+
191
+ const getValidComponentPackages = memoize((props: TamaguiOptionsWithFileInfo) => {
192
+ // just always look for `tamagui` and `@tamagui/core`
193
+ return [...new Set(['@tamagui/core', 'tamagui', ...props.components])]
194
+ })
195
+
196
+ const getValidComponentsPaths = memoize((props: TamaguiOptionsWithFileInfo) => {
197
+ return getValidComponentPackages(props).map((pkg) => {
198
+ const root = findRoot(pkg)
199
+ return basename(root)
200
+ })
201
+ })
@@ -0,0 +1,199 @@
1
+ import { NodePath } from '@babel/traverse'
2
+ import * as t from '@babel/types'
3
+ import { TamaguiInternalConfig, getStylesAtomic, mediaObjectToString } from '@tamagui/core-node'
4
+ import type { ViewStyle } from 'react-native'
5
+
6
+ import { MEDIA_SEP } from '../constants.js'
7
+ import type { StyleObject, TamaguiOptionsWithFileInfo, Ternary } from '../types.js'
8
+ import { isPresent, isValidImport } from './extractHelpers.js'
9
+
10
+ export function extractMediaStyle(
11
+ props: TamaguiOptionsWithFileInfo,
12
+ ternary: Ternary,
13
+ jsxPath: NodePath<t.JSXElement>,
14
+ tamaguiConfig: TamaguiInternalConfig,
15
+ sourcePath: string,
16
+ importance = 0,
17
+ shouldPrintDebug: boolean | 'verbose' = false
18
+ ) {
19
+ const mt = getMediaQueryTernary(props, ternary, jsxPath, sourcePath)
20
+ if (!mt) {
21
+ return null
22
+ }
23
+ const { key } = mt
24
+ const mq = tamaguiConfig.media[key]
25
+ if (!mq) {
26
+ // eslint-disable-next-line no-console
27
+ console.error(`Media query "${key}" not found: ${Object.keys(tamaguiConfig.media)}`)
28
+ return null
29
+ }
30
+ const getStyleObj = (styleObj: ViewStyle | null, negate = false) => {
31
+ return styleObj ? { styleObj, negate } : null
32
+ }
33
+ const styleOpts = [
34
+ getStyleObj(ternary.consequent, false),
35
+ getStyleObj(ternary.alternate, true),
36
+ ].filter(isPresent)
37
+ if (shouldPrintDebug && !styleOpts.length) {
38
+ // eslint-disable-next-line no-console
39
+ console.log(' media query, no styles?')
40
+ return null
41
+ }
42
+ // for now order first strongest
43
+ const mediaKeys = Object.keys(tamaguiConfig.media)
44
+ const mediaKeyPrecendence = mediaKeys.reduce((acc, cur, i) => {
45
+ acc[cur] = new Array(importance + 1).fill(':root').join('')
46
+ return acc
47
+ }, {})
48
+ let mediaStyles: StyleObject[] = []
49
+ for (const { styleObj, negate } of styleOpts) {
50
+ const styles = getStylesAtomic(styleObj)
51
+ const singleMediaStyles = styles.map((style) => {
52
+ const negKey = negate ? '0' : ''
53
+ const ogPrefix = style.identifier.slice(0, style.identifier.indexOf('-') + 1)
54
+ // adds an extra separator before and after to detect later in concatClassName
55
+ // so it goes from: "_f-[hash]"
56
+ // to: "_f-_sm0_[hash]" or "_f-_sm_[hash]"
57
+ const identifier = `${style.identifier.replace(
58
+ ogPrefix,
59
+ `${ogPrefix}${MEDIA_SEP}${key}${negKey}${MEDIA_SEP}`
60
+ )}`
61
+ const className = `.${identifier}`
62
+ const mediaSelector = mediaObjectToString(tamaguiConfig.media[key])
63
+ const screenStr = negate ? 'not all' : 'screen'
64
+ const mediaQuery = `${screenStr} and ${mediaSelector}`
65
+ const precendencePrefix = mediaKeyPrecendence[key]
66
+ const styleInner = style.rules
67
+ .map((rule) => rule.replace(style.identifier, identifier))
68
+ .join(';')
69
+ // combines media queries if they already exist
70
+ let styleRule = ''
71
+ if (styleInner.includes('@media')) {
72
+ // combine
73
+ styleRule = styleInner.replace('{', ` and ${mediaQuery} {`)
74
+ } else {
75
+ styleRule = `@media ${mediaQuery} { ${precendencePrefix} ${styleInner} }`
76
+ }
77
+ return {
78
+ ...style,
79
+ identifier,
80
+ className,
81
+ rules: [styleRule],
82
+ }
83
+ })
84
+ if (shouldPrintDebug === 'verbose') {
85
+ // prettier-ignore
86
+ // eslint-disable-next-line no-console
87
+ console.log(' media styles:', importance, styleObj, singleMediaStyles.map(x => x.identifier).join(', '))
88
+ }
89
+ // add to output
90
+ mediaStyles = [...mediaStyles, ...singleMediaStyles]
91
+ }
92
+ // filter out
93
+ ternary.remove()
94
+ return { mediaStyles, ternaryWithoutMedia: mt.ternaryWithoutMedia }
95
+ }
96
+
97
+ function getMediaQueryTernary(
98
+ props: TamaguiOptionsWithFileInfo,
99
+ ternary: Ternary,
100
+ jsxPath: NodePath<t.JSXElement>,
101
+ sourcePath: string
102
+ ): null | {
103
+ key: string
104
+ bindingName: string
105
+ ternaryWithoutMedia: Ternary | null
106
+ } {
107
+ // this handles unwrapping logical && media query ternarys
108
+ // first, unwrap if it has media logicalExpression
109
+ if (t.isLogicalExpression(ternary.test) && ternary.test.operator === '&&') {
110
+ // *should* be normalized to always be on left side
111
+ const mediaLeft = getMediaInfoFromExpression(
112
+ props,
113
+ ternary.test.left,
114
+ jsxPath,
115
+ sourcePath,
116
+ ternary.inlineMediaQuery
117
+ )
118
+ if (mediaLeft) {
119
+ return {
120
+ ...mediaLeft,
121
+ ternaryWithoutMedia: {
122
+ ...ternary,
123
+ test: ternary.test.right,
124
+ },
125
+ }
126
+ }
127
+ }
128
+ // const media = useMedia()
129
+ // ... media.sm
130
+ const result = getMediaInfoFromExpression(
131
+ props,
132
+ ternary.test,
133
+ jsxPath,
134
+ sourcePath,
135
+ ternary.inlineMediaQuery
136
+ )
137
+ if (result) {
138
+ return {
139
+ ...result,
140
+ ternaryWithoutMedia: null,
141
+ }
142
+ }
143
+ return null
144
+ }
145
+
146
+ function getMediaInfoFromExpression(
147
+ props: TamaguiOptionsWithFileInfo,
148
+ test: t.Expression,
149
+ jsxPath: NodePath<t.JSXElement>,
150
+ sourcePath: string,
151
+ inlineMediaQuery?: string
152
+ ) {
153
+ if (inlineMediaQuery) {
154
+ return {
155
+ key: inlineMediaQuery,
156
+ bindingName: inlineMediaQuery,
157
+ }
158
+ }
159
+ if (t.isMemberExpression(test) && t.isIdentifier(test.object) && t.isIdentifier(test.property)) {
160
+ const name = test.object['name']
161
+ const key = test.property['name']
162
+ const bindings = jsxPath.scope.getAllBindings()
163
+ const binding = bindings[name]
164
+ if (!binding) return false
165
+ const bindingNode = binding.path?.node
166
+ if (!t.isVariableDeclarator(bindingNode) || !bindingNode.init) return false
167
+ if (!isValidMediaCall(props, jsxPath, bindingNode.init, sourcePath)) return false
168
+ return { key, bindingName: name }
169
+ }
170
+ if (t.isIdentifier(test)) {
171
+ const key = test.name
172
+ const node = jsxPath.scope.getBinding(test.name)?.path?.node
173
+ if (!t.isVariableDeclarator(node)) return false
174
+ if (!node.init || !isValidMediaCall(props, jsxPath, node.init, sourcePath)) return false
175
+ return { key, bindingName: key }
176
+ }
177
+ return null
178
+ }
179
+
180
+ export function isValidMediaCall(
181
+ props: TamaguiOptionsWithFileInfo,
182
+ jsxPath: NodePath<t.JSXElement>,
183
+ init: t.Expression,
184
+ sourcePath: string
185
+ ) {
186
+ if (!t.isCallExpression(init)) return false
187
+ if (!t.isIdentifier(init.callee)) return false
188
+ // TODO could support renaming useMedia by looking up import first
189
+ if (init.callee.name !== 'useMedia') return false
190
+ const bindings = jsxPath.scope.getAllBindings()
191
+ const mediaBinding = bindings['useMedia']
192
+ if (!mediaBinding) return false
193
+ const useMediaImport = mediaBinding.path.parent
194
+ if (!t.isImportDeclaration(useMediaImport)) return false
195
+ if (!isValidImport(props, sourcePath)) {
196
+ return false
197
+ }
198
+ return true
199
+ }