@tamagui/static 1.0.1-beta.19 → 1.0.1-beta.190

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