@tamagui/static 1.0.0-alpha.5 → 1.0.0-alpha.9

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.
@@ -4,8 +4,24 @@ import * as fs from "fs";
4
4
  import path from "path";
5
5
  function patchReactNativeWeb() {
6
6
  const rootDir = require.resolve("react-native-web").replace(/\/dist.*/, "");
7
- fs.writeFileSync(path.join(rootDir, "dist", "tamagui-exports.js"), moduleExports);
8
- fs.writeFileSync(path.join(rootDir, "dist", "cjs", "tamagui-exports.js"), cjsExports);
7
+ const modulePath = path.join(rootDir, "dist", "tamagui-exports.js");
8
+ const cjsPath = path.join(rootDir, "dist", "cjs", "tamagui-exports.js");
9
+ const isEqual = (() => {
10
+ let res = false;
11
+ try {
12
+ res = fs.readFileSync(modulePath, "utf-8") === moduleExports && fs.readFileSync(cjsPath, "utf-8") == cjsExports;
13
+ } catch {
14
+ res = false;
15
+ }
16
+ return res;
17
+ })();
18
+ if (!isEqual) {
19
+ console.log("\u{1F95A} Tamagui patching react-native-web to share atomic styling primitives");
20
+ console.log(" > adding", modulePath);
21
+ console.log(" > adding", cjsPath);
22
+ fs.writeFileSync(modulePath, moduleExports);
23
+ fs.writeFileSync(cjsPath, cjsExports);
24
+ }
9
25
  const moduleEntry = path.join(rootDir, "dist", "index.js");
10
26
  const moduleEntrySrc = fs.readFileSync(moduleEntry, "utf-8");
11
27
  if (!moduleEntrySrc.includes("// tamagui-patch-v4")) {
@@ -26,7 +42,6 @@ export const TamaguiExports = TExports
26
42
  exports.TamaguiExports = _interopRequireDefault(require("./tamagui-exports"));
27
43
  // tamagui-patch-end
28
44
  `);
29
- console.log(`Tamagui patched react-native-web`);
30
45
  }
31
46
  }
32
47
  __name(patchReactNativeWeb, "patchReactNativeWeb");
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/patchReactNativeWeb.ts"],
4
- "sourcesContent": ["import * as fs from 'fs'\nimport path from 'path'\n\n// were patching react-native-web so we can use some internal methods\n// we do it this way because we need to rely on webpack or bundler config to determine cjs vs esm\n// so we can't just require it all directly\n// would be nice in the future to be able to eject from react-native-web entirely optionally\n\n// keep it sync\nexport function patchReactNativeWeb() {\n const rootDir = require.resolve('react-native-web').replace(/\\/dist.*/, '')\n\n // write our export files\n fs.writeFileSync(path.join(rootDir, 'dist', 'tamagui-exports.js'), moduleExports)\n fs.writeFileSync(path.join(rootDir, 'dist', 'cjs', 'tamagui-exports.js'), cjsExports)\n\n // if entry files not patched, patch them:\n const moduleEntry = path.join(rootDir, 'dist', 'index.js')\n const moduleEntrySrc = fs.readFileSync(moduleEntry, 'utf-8')\n if (!moduleEntrySrc.includes('// tamagui-patch-v4')) {\n fs.writeFileSync(\n moduleEntry,\n `${removePatch(moduleEntrySrc)}\n\n// tamagui-patch-v4\nimport * as TExports from './tamagui-exports'\nexport const TamaguiExports = TExports\n// tamagui-patch-end\n`\n )\n }\n const cjsEntry = path.join(rootDir, 'dist', 'cjs', 'index.js')\n const cjsEntrySrc = fs.readFileSync(cjsEntry, 'utf-8')\n if (!cjsEntrySrc.includes('// tamagui-patch-v4')) {\n fs.writeFileSync(\n cjsEntry,\n `${removePatch(cjsEntrySrc)}\n\n// tamagui-patch-v4\nexports.TamaguiExports = _interopRequireDefault(require(\"./tamagui-exports\"));\n// tamagui-patch-end\n`\n )\n\n console.log(`Tamagui patched react-native-web`)\n }\n}\n\nfunction removePatch(source: string) {\n return source.replace(/\\/\\/ tamagui-patch([.\\s\\S]*)/g, '')\n}\n\n// view exports/View.ts\nconst forwardedPropsObj = `{\n ...fwdProps.defaultProps,\n ...fwdProps.accessibilityProps,\n ...fwdProps.clickProps,\n ...fwdProps.focusProps,\n ...fwdProps.keyboardProps,\n ...fwdProps.mouseProps,\n ...fwdProps.touchProps,\n ...fwdProps.styleProps,\n href: true,\n lang: true,\n onScroll: true,\n onWheel: true,\n pointerEvents: true\n}\n`\n\nconst moduleExports = `\nexport { atomic } from './exports/StyleSheet/compile'\nexport { default as createCompileableStyle } from './exports/StyleSheet/createCompileableStyle'\nexport { default as createReactDOMStyle } from './exports/StyleSheet/createReactDOMStyle'\nexport { default as i18Style } from './exports/StyleSheet/i18nStyle'\nexport { default as createDOMProps } from './modules/createDOMProps'\nexport { default as AccessibilityUtil } from './modules/AccessibilityUtil'\nexport { default as createElement } from './exports/createElement'\nexport { default as css } from './exports/StyleSheet/css'\nexport { default as TextAncestorContext } from './exports/Text/TextAncestorContext'\nexport { default as pick } from './modules/pick'\nexport { default as useElementLayout } from './modules/useElementLayout'\nexport { default as useMergeRefs } from './modules/useMergeRefs'\nexport { default as usePlatformMethods } from './modules/usePlatformMethods'\nexport { default as useResponderEvents } from './modules/useResponderEvents'\nimport * as fwdProps from './modules/forwardedProps'\nexport const forwardedProps = ${forwardedPropsObj}\n`\n\nconst cjsExports = `\nexports.atomic = require('./exports/StyleSheet/compile').atomic\nexports.createCompileableStyle = require('./exports/StyleSheet/createCompileableStyle')\nexports.createReactDOMStyle = require('./exports/StyleSheet/createReactDOMStyle')\nexports.i18Style = require('./exports/StyleSheet/i18nStyle')\nexports.createDOMProps = require('./modules/createDOMProps')\nexports.AccessibilityUtil = require('./modules/AccessibilityUtil')\nexports.createElement = require('./exports/createElement')\nexports.css = require('./exports/StyleSheet/css')\nexports.TextAncestorContext = require('./exports/Text/TextAncestorContext')\nexports.pick = require('./modules/pick')\nexports.useElementLayout = require('./modules/useElementLayout')\nexports.useMergeRefs = require('./modules/useMergeRefs')\nexports.usePlatformMethods = require('./modules/usePlatformMethods')\nexports.useResponderEvents = require('./modules/useResponderEvents')\nconst fwdProps = require('./modules/forwardedProps')\nexports.forwardedProps = ${forwardedPropsObj}\n`\n"],
5
- "mappings": ";;AAAA;AACA;AAQO,+BAA+B;AACpC,QAAM,UAAU,AAAgB,oCAAoB,QAAQ,YAAY;AAGxE,KAAG,cAAc,KAAK,KAAK,SAAS,QAAQ,uBAAuB;AACnE,KAAG,cAAc,KAAK,KAAK,SAAS,QAAQ,OAAO,uBAAuB;AAG1E,QAAM,cAAc,KAAK,KAAK,SAAS,QAAQ;AAC/C,QAAM,iBAAiB,GAAG,aAAa,aAAa;AACpD,MAAI,CAAC,eAAe,SAAS,wBAAwB;AACnD,OAAG,cACD,aACA,GAAG,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AASnB,QAAM,WAAW,KAAK,KAAK,SAAS,QAAQ,OAAO;AACnD,QAAM,cAAc,GAAG,aAAa,UAAU;AAC9C,MAAI,CAAC,YAAY,SAAS,wBAAwB;AAChD,OAAG,cACD,UACA,GAAG,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAQjB,YAAQ,IAAI;AAAA;AAAA;AAnCA;AAuChB,qBAAqB,QAAgB;AACnC,SAAO,OAAO,QAAQ,iCAAiC;AAAA;AADhD;AAKT,MAAM,oBAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAiB1B,MAAM,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,gCAgBU;AAAA;AAGhC,MAAM,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,2BAgBQ;AAAA;",
4
+ "sourcesContent": ["import * as fs from 'fs'\nimport path from 'path'\n\n// were patching react-native-web so we can use some internal methods\n// we do it this way because we need to rely on webpack or bundler config to determine cjs vs esm\n// so we can't just require it all directly\n// would be nice in the future to be able to eject from react-native-web entirely optionally\n\n// keep it sync\nexport function patchReactNativeWeb() {\n const rootDir = require.resolve('react-native-web').replace(/\\/dist.*/, '')\n const modulePath = path.join(rootDir, 'dist', 'tamagui-exports.js')\n const cjsPath = path.join(rootDir, 'dist', 'cjs', 'tamagui-exports.js')\n\n const isEqual = (() => {\n let res = false\n try {\n res =\n fs.readFileSync(modulePath, 'utf-8') === moduleExports &&\n fs.readFileSync(cjsPath, 'utf-8') == cjsExports\n } catch {\n res = false\n }\n return res\n })()\n\n if (!isEqual) {\n console.log('\uD83E\uDD5A Tamagui patching react-native-web to share atomic styling primitives')\n console.log(' > adding', modulePath)\n console.log(' > adding', cjsPath)\n fs.writeFileSync(modulePath, moduleExports)\n fs.writeFileSync(cjsPath, cjsExports)\n }\n\n // if entry files not patched, patch them:\n const moduleEntry = path.join(rootDir, 'dist', 'index.js')\n const moduleEntrySrc = fs.readFileSync(moduleEntry, 'utf-8')\n if (!moduleEntrySrc.includes('// tamagui-patch-v4')) {\n fs.writeFileSync(\n moduleEntry,\n `${removePatch(moduleEntrySrc)}\n\n// tamagui-patch-v4\nimport * as TExports from './tamagui-exports'\nexport const TamaguiExports = TExports\n// tamagui-patch-end\n`\n )\n }\n const cjsEntry = path.join(rootDir, 'dist', 'cjs', 'index.js')\n const cjsEntrySrc = fs.readFileSync(cjsEntry, 'utf-8')\n if (!cjsEntrySrc.includes('// tamagui-patch-v4')) {\n fs.writeFileSync(\n cjsEntry,\n `${removePatch(cjsEntrySrc)}\n\n// tamagui-patch-v4\nexports.TamaguiExports = _interopRequireDefault(require(\"./tamagui-exports\"));\n// tamagui-patch-end\n`\n )\n }\n}\n\nfunction removePatch(source: string) {\n return source.replace(/\\/\\/ tamagui-patch([.\\s\\S]*)/g, '')\n}\n\n// view exports/View.ts\nconst forwardedPropsObj = `{\n ...fwdProps.defaultProps,\n ...fwdProps.accessibilityProps,\n ...fwdProps.clickProps,\n ...fwdProps.focusProps,\n ...fwdProps.keyboardProps,\n ...fwdProps.mouseProps,\n ...fwdProps.touchProps,\n ...fwdProps.styleProps,\n href: true,\n lang: true,\n onScroll: true,\n onWheel: true,\n pointerEvents: true\n}\n`\n\nconst moduleExports = `\nexport { atomic } from './exports/StyleSheet/compile'\nexport { default as createCompileableStyle } from './exports/StyleSheet/createCompileableStyle'\nexport { default as createReactDOMStyle } from './exports/StyleSheet/createReactDOMStyle'\nexport { default as i18Style } from './exports/StyleSheet/i18nStyle'\nexport { default as createDOMProps } from './modules/createDOMProps'\nexport { default as AccessibilityUtil } from './modules/AccessibilityUtil'\nexport { default as createElement } from './exports/createElement'\nexport { default as css } from './exports/StyleSheet/css'\nexport { default as TextAncestorContext } from './exports/Text/TextAncestorContext'\nexport { default as pick } from './modules/pick'\nexport { default as useElementLayout } from './modules/useElementLayout'\nexport { default as useMergeRefs } from './modules/useMergeRefs'\nexport { default as usePlatformMethods } from './modules/usePlatformMethods'\nexport { default as useResponderEvents } from './modules/useResponderEvents'\nimport * as fwdProps from './modules/forwardedProps'\nexport const forwardedProps = ${forwardedPropsObj}\n`\n\nconst cjsExports = `\nexports.atomic = require('./exports/StyleSheet/compile').atomic\nexports.createCompileableStyle = require('./exports/StyleSheet/createCompileableStyle')\nexports.createReactDOMStyle = require('./exports/StyleSheet/createReactDOMStyle')\nexports.i18Style = require('./exports/StyleSheet/i18nStyle')\nexports.createDOMProps = require('./modules/createDOMProps')\nexports.AccessibilityUtil = require('./modules/AccessibilityUtil')\nexports.createElement = require('./exports/createElement')\nexports.css = require('./exports/StyleSheet/css')\nexports.TextAncestorContext = require('./exports/Text/TextAncestorContext')\nexports.pick = require('./modules/pick')\nexports.useElementLayout = require('./modules/useElementLayout')\nexports.useMergeRefs = require('./modules/useMergeRefs')\nexports.usePlatformMethods = require('./modules/usePlatformMethods')\nexports.useResponderEvents = require('./modules/useResponderEvents')\nconst fwdProps = require('./modules/forwardedProps')\nexports.forwardedProps = ${forwardedPropsObj}\n`\n"],
5
+ "mappings": ";;AAAA;AACA;AAQO,+BAA+B;AACpC,QAAM,UAAU,AAAgB,oCAAoB,QAAQ,YAAY;AACxE,QAAM,aAAa,KAAK,KAAK,SAAS,QAAQ;AAC9C,QAAM,UAAU,KAAK,KAAK,SAAS,QAAQ,OAAO;AAElD,QAAM,UAAW,OAAM;AACrB,QAAI,MAAM;AACV,QAAI;AACF,YACE,GAAG,aAAa,YAAY,aAAa,iBACzC,GAAG,aAAa,SAAS,YAAY;AAAA,YACvC;AACA,YAAM;AAAA;AAER,WAAO;AAAA;AAGT,MAAI,CAAC,SAAS;AACZ,YAAQ,IAAI;AACZ,YAAQ,IAAI,eAAe;AAC3B,YAAQ,IAAI,eAAe;AAC3B,OAAG,cAAc,YAAY;AAC7B,OAAG,cAAc,SAAS;AAAA;AAI5B,QAAM,cAAc,KAAK,KAAK,SAAS,QAAQ;AAC/C,QAAM,iBAAiB,GAAG,aAAa,aAAa;AACpD,MAAI,CAAC,eAAe,SAAS,wBAAwB;AACnD,OAAG,cACD,aACA,GAAG,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AASnB,QAAM,WAAW,KAAK,KAAK,SAAS,QAAQ,OAAO;AACnD,QAAM,cAAc,GAAG,aAAa,UAAU;AAC9C,MAAI,CAAC,YAAY,SAAS,wBAAwB;AAChD,OAAG,cACD,UACA,GAAG,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA7CL;AAuDhB,qBAAqB,QAAgB;AACnC,SAAO,OAAO,QAAQ,iCAAiC;AAAA;AADhD;AAKT,MAAM,oBAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAiB1B,MAAM,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,gCAgBU;AAAA;AAGhC,MAAM,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,2BAgBQ;AAAA;",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tamagui/static",
3
- "version": "1.0.0-alpha.5",
3
+ "version": "1.0.0-alpha.9",
4
4
  "source": "src/index.ts",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.js",
@@ -35,6 +35,7 @@
35
35
  "@types/webpack": "^4.41.26",
36
36
  "babel-loader": "^8.2.2",
37
37
  "css-loader": "^5.2.4",
38
+ "esbuild-loader": "^2.16.0",
38
39
  "jest": "^27.3.1",
39
40
  "loader-utils": "^2.0.0",
40
41
  "react": "*",
@@ -52,11 +53,11 @@
52
53
  "@babel/traverse": "^7.15.4",
53
54
  "@dish/babel-preset": "^0.0.6",
54
55
  "@expo/match-media": "^0.1.0",
55
- "@tamagui/build": "^1.0.0-alpha.2",
56
- "@tamagui/core": "^1.0.0-alpha.5",
57
- "@tamagui/core-node": "^1.0.0-alpha.5",
56
+ "@tamagui/build": "^1.0.0-alpha.8",
57
+ "@tamagui/core": "^1.0.0-alpha.9",
58
+ "@tamagui/core-node": "^1.0.0-alpha.8",
58
59
  "@tamagui/fake-react-native": "^1.0.0-alpha.2",
59
- "@tamagui/helpers": "^1.0.0-alpha.5",
60
+ "@tamagui/helpers": "^1.0.0-alpha.8",
60
61
  "babel-literal-to-ast": "^2.1.0",
61
62
  "esbuild": "^0.13.12",
62
63
  "esbuild-register": "^3.1.2",
@@ -64,10 +65,10 @@
64
65
  "fs-extra": "^9.0.0",
65
66
  "invariant": "^2.2.4",
66
67
  "lodash": "^4.17.20",
67
- "tamagui": "^1.0.0-alpha.5"
68
+ "tamagui": "^1.0.0-alpha.9"
68
69
  },
69
70
  "peerDependencies": {
70
71
  "react-native-web": "*"
71
72
  },
72
- "gitHead": "e12f14aa087c41ea5ba3933a05f33fada0be03c0"
73
+ "gitHead": "48ab0be0ca0b8d7e9a1470ee18d46348bc316cdd"
73
74
  }
@@ -13,6 +13,7 @@ import { findTopmostFunction } from './findTopmostFunction'
13
13
  import { getStaticBindingsForScope } from './getStaticBindingsForScope'
14
14
  import { literalToAst } from './literalToAst'
15
15
  import { loadTamagui } from './loadTamagui'
16
+ import { logLines } from './logLines'
16
17
  import { normalizeTernaries } from './normalizeTernaries'
17
18
  import { removeUnusedHooks } from './removeUnusedHooks'
18
19
 
@@ -51,9 +52,10 @@ export function createExtractor() {
51
52
  })
52
53
 
53
54
  let loadedTamaguiConfig: TamaguiInternalConfig
55
+ let hasLogged = false
54
56
 
55
57
  return {
56
- getTamaguiConfig() {
58
+ getTamagui() {
57
59
  return loadedTamaguiConfig
58
60
  },
59
61
  parse: (
@@ -66,7 +68,9 @@ export function createExtractor() {
66
68
  sourcePath = '',
67
69
  onExtractTag,
68
70
  getFlattenedNode,
69
- onDidFlatten,
71
+ disableExtraction,
72
+ disableExtractInlineMedia,
73
+ disableDebugAttr,
70
74
  ...props
71
75
  }: ExtractorParseProps
72
76
  ) => {
@@ -87,27 +91,25 @@ export function createExtractor() {
87
91
  loadedTamaguiConfig = tamaguiConfig
88
92
 
89
93
  const defaultTheme = tamaguiConfig.themes[Object.keys(tamaguiConfig.themes)[0]]
90
-
91
- // TODO this can be passed in / set based on if source changed
92
- // const shouldReCheckTheme = false //Date.now() - hasParsedFileLast > 600
93
- // hasParsedFileLast = Date.now()
94
-
95
- let doesUseValidImport = false
96
94
  const body = fileOrPath.type === 'Program' ? fileOrPath.get('body') : fileOrPath.program.body
97
95
 
98
96
  /**
99
97
  * Step 1: Determine if importing any statically extractable components
100
98
  */
101
- const isInternalImport = (importStr: string) =>
102
- isInsideTamagui(sourcePath) && importStr[0] === '.'
99
+ const isInternalImport = (importStr: string) => {
100
+ return isInsideTamagui(sourcePath) && importStr[0] === '.'
101
+ }
103
102
 
104
103
  const validComponents: { [key: string]: any } = Object.keys(components)
105
- .filter((key) => !!components[key]?.staticConfig)
104
+ // check if uppercase to avoid hitting media query proxy before init
105
+ .filter((key) => key[0].toUpperCase() === key[0] && !!components[key]?.staticConfig)
106
106
  .reduce((obj, name) => {
107
107
  obj[name] = components[name]
108
108
  return obj
109
109
  }, {})
110
110
 
111
+ let doesUseValidImport = false
112
+
111
113
  for (const bodyPath of body) {
112
114
  if (bodyPath.type !== 'ImportDeclaration') continue
113
115
  const node = ('node' in bodyPath ? bodyPath.node : bodyPath) as any
@@ -148,6 +150,12 @@ export function createExtractor() {
148
150
  */
149
151
  let programPath: NodePath<t.Program>
150
152
 
153
+ const res = {
154
+ flattened: 0,
155
+ optimized: 0,
156
+ modified: 0,
157
+ }
158
+
151
159
  callTraverse({
152
160
  Program: {
153
161
  enter(path) {
@@ -186,8 +194,41 @@ export function createExtractor() {
186
194
  return
187
195
  }
188
196
 
189
- const { staticConfig } = component
190
197
  const originalNodeName = node.name.name
198
+
199
+ if (shouldPrintDebug) {
200
+ console.log(`\n<${originalNodeName} />`)
201
+ }
202
+
203
+ const filePath = sourcePath.replace(process.cwd(), '.')
204
+ const lineNumbers = node.loc
205
+ ? node.loc.start.line +
206
+ (node.loc.start.line !== node.loc.end.line ? `-${node.loc.end.line}` : '')
207
+ : ''
208
+
209
+ // add data-is
210
+ if (shouldAddDebugProp && !disableDebugAttr) {
211
+ const preName = componentName ? `${componentName}:` : ''
212
+ res.modified++
213
+ node.attributes.unshift(
214
+ t.jsxAttribute(
215
+ t.jsxIdentifier('data-is'),
216
+ t.stringLiteral(
217
+ ` ${preName}${node.name.name} ${filePath.replace('./', '')}:${lineNumbers} `
218
+ )
219
+ )
220
+ )
221
+ }
222
+
223
+ if (disableExtraction) {
224
+ if (!hasLogged) {
225
+ console.log('🥚 Tamagui disableExtraction set: no CSS or optimizations will be run')
226
+ hasLogged = true
227
+ }
228
+ return
229
+ }
230
+
231
+ const { staticConfig } = component
191
232
  const isTextView = staticConfig.isText || false
192
233
  const validStyles = staticConfig?.validStyles ?? {}
193
234
 
@@ -224,10 +265,6 @@ export function createExtractor() {
224
265
  return res
225
266
  }
226
267
 
227
- if (shouldPrintDebug) {
228
- console.log(`\n<${originalNodeName} />`)
229
- }
230
-
231
268
  // Generate scope object at this level
232
269
  const staticNamespace = getStaticBindingsForScope(
233
270
  traversePath.scope,
@@ -542,6 +579,11 @@ export function createExtractor() {
542
579
 
543
580
  // shorthand media queries
544
581
  if (name[0] === '$' && t.isJSXExpressionContainer(attribute?.value)) {
582
+ // allow disabling this extraction
583
+ if (disableExtractInlineMedia) {
584
+ return attr
585
+ }
586
+
545
587
  const shortname = name.slice(1)
546
588
  if (mediaQueryConfig[shortname]) {
547
589
  const expression = attribute.value.expression
@@ -593,8 +635,8 @@ export function createExtractor() {
593
635
  // if value can be evaluated, extract it and filter it out
594
636
  const styleValue = attemptEvalSafe(value)
595
637
 
596
- // we never flatten if a prop isn't a valid static attribute
597
- // but we need to make sure its post-prop mapping
638
+ // never flatten if a prop isn't a valid static attribute
639
+ // only post prop-mapping
598
640
  if (!isStaticAttributeName(name)) {
599
641
  let keys = [name]
600
642
  if (staticConfig.propMapper) {
@@ -624,6 +666,8 @@ export function createExtractor() {
624
666
  return {
625
667
  type: 'style',
626
668
  value: { [name]: styleValue },
669
+ name,
670
+ attr: path.node,
627
671
  }
628
672
  }
629
673
 
@@ -755,7 +799,7 @@ export function createExtractor() {
755
799
 
756
800
  // see if we can filter them
757
801
  if (shouldPrintDebug) {
758
- console.log(' - attrs (before): ', attrs.map(attrStr).join(', '))
802
+ console.log(' - attrs (before):\n', logLines(attrs.map(attrStr).join(', ')))
759
803
  }
760
804
 
761
805
  // now update to new values
@@ -775,12 +819,6 @@ export function createExtractor() {
775
819
  modifiedComponents.add(parentFn)
776
820
  }
777
821
 
778
- const filePath = sourcePath.replace(process.cwd(), '.')
779
- const lineNumbers = node.loc
780
- ? node.loc.start.line +
781
- (node.loc.start.line !== node.loc.end.line ? `-${node.loc.end.line}` : '')
782
- : ''
783
-
784
822
  // combine ternaries
785
823
  let ternaries: Ternary[] = []
786
824
  attrs = attrs
@@ -870,29 +908,27 @@ export function createExtractor() {
870
908
  if (cur.type === 'style') {
871
909
  // TODO need to loop over initial props not just style props
872
910
  for (const key in cur.value) {
873
- const shouldInsertNull =
874
- !!(
875
- staticConfig.ensureOverriddenProp?.[key] // || staticConfig.defaultProps?.[key]
876
- )
911
+ const shouldEnsureOverridden = !!staticConfig.ensureOverriddenProp?.[key]
877
912
  const isSetInAttrsAlready = attrs.some(
878
913
  (x) =>
879
914
  x.type === 'attr' &&
880
915
  x.value.type === 'JSXAttribute' &&
881
916
  x.value.name.name === key
882
917
  )
883
- const shouldInsertNullOverride = shouldInsertNull && !isSetInAttrsAlready
884
- // if (shouldPrintDebug) {
885
- // // prettier-ignore
886
- // console.log('what is', key, { shouldInsertNullOverride, shouldInsertNull, isSetInAttrsAlready })
887
- // }
888
- if (shouldInsertNullOverride) {
889
- acc.push({
890
- type: 'attr',
891
- value: t.jsxAttribute(
892
- t.jsxIdentifier(key),
893
- t.jsxExpressionContainer(t.nullLiteral())
894
- ),
895
- })
918
+
919
+ if (!isSetInAttrsAlready) {
920
+ const isVariant = !!staticConfig.variants?.[cur.name || '']
921
+ if (isVariant || shouldEnsureOverridden) {
922
+ acc.push({
923
+ type: 'attr',
924
+ value:
925
+ cur.attr ||
926
+ t.jsxAttribute(
927
+ t.jsxIdentifier(key),
928
+ t.jsxExpressionContainer(t.nullLiteral())
929
+ ),
930
+ })
931
+ }
896
932
  }
897
933
  }
898
934
  }
@@ -902,7 +938,7 @@ export function createExtractor() {
902
938
  }
903
939
 
904
940
  if (shouldPrintDebug) {
905
- console.log(' - attrs (flattened): ', attrs.map(attrStr).join(', '))
941
+ console.log(' - attrs (flattened): \n', logLines(attrs.map(attrStr).join(', ')))
906
942
  }
907
943
 
908
944
  // evaluate away purely style props
@@ -928,7 +964,7 @@ export function createExtractor() {
928
964
  }, [])
929
965
 
930
966
  if (shouldPrintDebug) {
931
- console.log(' - attrs (evaluated styles): ', attrs.map(attrStr).join(', '))
967
+ console.log(' - attrs (evaluated styles): \n', logLines(attrs.map(attrStr).join(', ')))
932
968
  }
933
969
 
934
970
  // combine styles, leave undefined values
@@ -946,7 +982,7 @@ export function createExtractor() {
946
982
  }, [])
947
983
 
948
984
  if (shouldPrintDebug) {
949
- console.log(' - attrs (combined 🔀): ', attrs.map(attrStr).join(', '))
985
+ console.log(' - attrs (combined 🔀): \n', logLines(attrs.map(attrStr).join(', ')))
950
986
  }
951
987
 
952
988
  // post process
@@ -961,9 +997,10 @@ export function createExtractor() {
961
997
  const out = postProcessStyles(props, staticConfig, defaultTheme)
962
998
  const next = out?.style ?? props
963
999
  if (shouldPrintDebug) {
964
- console.log(' >> getStyles: ', objToStr(props), '==>>', objToStr(next))
965
- console.log(' >> style: ', objToStr(out.style))
966
- console.log(' >> viewp: ', objToStr(out.viewProps))
1000
+ console.log(' getStyles props >>\n', logLines(objToStr(props)))
1001
+ console.log(' getStyles next >>\n', logLines(objToStr(next)))
1002
+ console.log(' getStyles style >>\n', logLines(objToStr(out.style)))
1003
+ console.log(' getStyles viewp >>\n', logLines(objToStr(out.viewProps)))
967
1004
  }
968
1005
  if (staticConfig.validStyles) {
969
1006
  for (const key in next) {
@@ -975,10 +1012,6 @@ export function createExtractor() {
975
1012
  return next
976
1013
  }
977
1014
 
978
- if (shouldPrintDebug) {
979
- console.log(' staticConfig.defaultProps', staticConfig.defaultProps)
980
- }
981
-
982
1015
  // used to ensure we pass the entire prop bundle to getStyles
983
1016
  const completeStylesProcessed = getStyles({
984
1017
  ...staticConfig.defaultProps,
@@ -1007,9 +1040,9 @@ export function createExtractor() {
1007
1040
 
1008
1041
  if (shouldPrintDebug) {
1009
1042
  // prettier-ignore
1010
- console.log(' completeStaticProps', objToStr(completeStaticProps))
1043
+ console.log(' completeStaticProps\n', logLines(objToStr(completeStaticProps)))
1011
1044
  // prettier-ignore
1012
- console.log(' completeStylesProcessed', objToStr(completeStylesProcessed))
1045
+ console.log(' completeStylesProcessed\n', logLines(objToStr(completeStylesProcessed)))
1013
1046
  }
1014
1047
 
1015
1048
  for (const attr of attrs) {
@@ -1048,22 +1081,7 @@ export function createExtractor() {
1048
1081
  }
1049
1082
 
1050
1083
  if (shouldPrintDebug) {
1051
- console.log(' - attrs (after): ', attrs.map(attrStr).join(', '))
1052
- }
1053
-
1054
- // add data-is
1055
- if (shouldAddDebugProp) {
1056
- const preName = componentName ? `${componentName}:` : ''
1057
- // unshift so spreads/nesting overwrite
1058
- attrs.unshift({
1059
- type: 'attr',
1060
- value: t.jsxAttribute(
1061
- t.jsxIdentifier('data-is'),
1062
- t.stringLiteral(
1063
- ` ${preName}${node.name.name} ${filePath.replace('./', '')}:${lineNumbers} `
1064
- )
1065
- ),
1066
- })
1084
+ console.log(' - attrs (after):\n', logLines(attrs.map(attrStr).join(', ')))
1067
1085
  }
1068
1086
 
1069
1087
  if (shouldFlatten) {
@@ -1073,7 +1091,7 @@ export function createExtractor() {
1073
1091
  }
1074
1092
  isFlattened = true
1075
1093
  node.name.name = flatNode
1076
- onDidFlatten?.()
1094
+ res.flattened++
1077
1095
  if (closingElement) {
1078
1096
  closingElement.name.name = flatNode
1079
1097
  }
@@ -1082,9 +1100,11 @@ export function createExtractor() {
1082
1100
  if (shouldPrintDebug) {
1083
1101
  // prettier-ignore
1084
1102
  console.log(' [❊] inline props ', inlinePropCount, shouldDeopt ? ' deopted' : '', hasSpread ? ' spread' : '', '!flatten', staticConfig.neverFlatten)
1085
- console.log(' - attrs (end): ', attrs.map(attrStr).join(', '))
1103
+ console.log(' - attrs (end):\n', logLines(attrs.map(attrStr).join(', ')))
1086
1104
  }
1087
1105
 
1106
+ res.optimized++
1107
+
1088
1108
  onExtractTag({
1089
1109
  attrs,
1090
1110
  node,
@@ -1111,6 +1131,8 @@ export function createExtractor() {
1111
1131
  removeUnusedHooks(comp, shouldPrintDebug)
1112
1132
  }
1113
1133
  }
1134
+
1135
+ return res
1114
1136
  },
1115
1137
  }
1116
1138
  }
@@ -18,6 +18,7 @@ import { ensureImportingConcat } from './ensureImportingConcat'
18
18
  import { isSimpleSpread } from './extractHelpers'
19
19
  import { extractMediaStyle } from './extractMediaStyle'
20
20
  import { hoistClassNames } from './hoistClassNames'
21
+ import { logLines } from './logLines'
21
22
 
22
23
  export const CONCAT_CLASSNAME_IMPORT = 'concatClassName'
23
24
 
@@ -79,17 +80,11 @@ export function extractToClassNames({
79
80
  const cssMap = new Map<string, { css: string; commentTexts: string[] }>()
80
81
  const existingHoists: { [key: string]: t.Identifier } = {}
81
82
 
82
- let flattened = 0
83
- let optimized = 0
84
-
85
- extractor.parse(ast, {
83
+ const res = extractor.parse(ast, {
86
84
  sourcePath,
87
85
  shouldPrintDebug,
88
86
  ...options,
89
87
  getFlattenedNode: ({ tag }) => tag,
90
- onDidFlatten() {
91
- flattened++
92
- },
93
88
  onExtractTag: ({
94
89
  attrs,
95
90
  node,
@@ -100,8 +95,6 @@ export function extractToClassNames({
100
95
  lineNumbers,
101
96
  programPath,
102
97
  }) => {
103
- optimized++
104
-
105
98
  let finalClassNames: ClassNameObject[] = []
106
99
  let finalAttrs: (t.JSXAttribute | t.JSXSpreadAttribute)[] = []
107
100
  let finalStyles: StyleObject[] = []
@@ -144,10 +137,6 @@ export function extractToClassNames({
144
137
  case 'style':
145
138
  const styles = addStyles(attr.value)
146
139
  const newClassNames = concatClassName(styles.map((x) => x.identifier).join(' '))
147
- if (shouldPrintDebug) {
148
- // console.log(' style', attr.value)
149
- console.log(' classnames', newClassNames, finalClassNames)
150
- }
151
140
  // prettier-ignore
152
141
  const existing = finalClassNames.find((x) => x.type == 'StringLiteral') as t.StringLiteral | null
153
142
  if (existing) {
@@ -157,7 +146,7 @@ export function extractToClassNames({
157
146
  }
158
147
  if (shouldPrintDebug) {
159
148
  // prettier-ignore
160
- console.log(' classnames (after)', finalClassNames.map(x => x['value']).join(' '))
149
+ console.log(' classnames (after)\n', logLines(finalClassNames.map(x => x['value']).join(' ')))
161
150
  }
162
151
  break
163
152
  case 'attr':
@@ -190,7 +179,7 @@ export function extractToClassNames({
190
179
  const mediaExtraction = extractMediaStyle(
191
180
  attr.value,
192
181
  jsxPath,
193
- extractor.getTamaguiConfig(),
182
+ extractor.getTamagui(),
194
183
  sourcePath,
195
184
  lastMediaImportance,
196
185
  shouldPrintDebug
@@ -276,15 +265,12 @@ export function extractToClassNames({
276
265
  },
277
266
  })
278
267
 
279
- if (!optimized) {
268
+ if (!res || !res.modified) {
280
269
  return null
281
270
  }
282
271
 
283
272
  const styles = Array.from(cssMap.values())
284
- .map((x) => {
285
- // remove comments
286
- return x.css //shouldInternalDedupe ? x.css : `${x.commentTexts.join('\n')}\n${x.css}`
287
- })
273
+ .map((x) => x.css)
288
274
  .join('\n')
289
275
  .trim()
290
276
 
@@ -325,7 +311,7 @@ export function extractToClassNames({
325
311
  const memUsed =
326
312
  Math.round(((process.memoryUsage().heapUsed - mem.heapUsed) / 1024 / 1204) * 10) / 10
327
313
  // prettier-ignore
328
- console.log(` 🥚 ${basename(sourcePath).padStart(40)} ${`${Date.now() - start}`.padStart(3)}ms ׁ· ${`${optimized}`.padStart(4)} optimized · ${flattened} flattened ${memUsed > 10 ? `used ${memUsed}MB` : ''}`)
314
+ console.log(` 🥚 ${basename(sourcePath).padStart(40)} ${`${Date.now() - start}`.padStart(3)}ms ׁ· ${`${res.optimized}`.padStart(4)} optimized · ${res.flattened} flattened ${memUsed > 10 ? `used ${memUsed}MB` : ''}`)
329
315
  }
330
316
 
331
317
  return {
@@ -0,0 +1,11 @@
1
+ export const logLines = (str: string) => {
2
+ let lines: string[] = ['']
3
+ const items = str.split(' ')
4
+ for (const item of items) {
5
+ if (item.length + lines[lines.length - 1].length > 100) {
6
+ lines.push('')
7
+ }
8
+ lines[lines.length - 1] += item + ' '
9
+ }
10
+ return lines.map((line, i) => ' ' + (i == 0 ? '' : ' ') + line.trim()).join('\n')
11
+ }
@@ -9,10 +9,28 @@ import path from 'path'
9
9
  // keep it sync
10
10
  export function patchReactNativeWeb() {
11
11
  const rootDir = require.resolve('react-native-web').replace(/\/dist.*/, '')
12
+ const modulePath = path.join(rootDir, 'dist', 'tamagui-exports.js')
13
+ const cjsPath = path.join(rootDir, 'dist', 'cjs', 'tamagui-exports.js')
12
14
 
13
- // write our export files
14
- fs.writeFileSync(path.join(rootDir, 'dist', 'tamagui-exports.js'), moduleExports)
15
- fs.writeFileSync(path.join(rootDir, 'dist', 'cjs', 'tamagui-exports.js'), cjsExports)
15
+ const isEqual = (() => {
16
+ let res = false
17
+ try {
18
+ res =
19
+ fs.readFileSync(modulePath, 'utf-8') === moduleExports &&
20
+ fs.readFileSync(cjsPath, 'utf-8') == cjsExports
21
+ } catch {
22
+ res = false
23
+ }
24
+ return res
25
+ })()
26
+
27
+ if (!isEqual) {
28
+ console.log('🥚 Tamagui patching react-native-web to share atomic styling primitives')
29
+ console.log(' > adding', modulePath)
30
+ console.log(' > adding', cjsPath)
31
+ fs.writeFileSync(modulePath, moduleExports)
32
+ fs.writeFileSync(cjsPath, cjsExports)
33
+ }
16
34
 
17
35
  // if entry files not patched, patch them:
18
36
  const moduleEntry = path.join(rootDir, 'dist', 'index.js')
@@ -41,8 +59,6 @@ exports.TamaguiExports = _interopRequireDefault(require("./tamagui-exports"));
41
59
  // tamagui-patch-end
42
60
  `
43
61
  )
44
-
45
- console.log(`Tamagui patched react-native-web`)
46
62
  }
47
63
  }
48
64
 
package/src/types.ts CHANGED
@@ -15,6 +15,8 @@ export interface TamaguiOptions {
15
15
  evaluateVars?: boolean
16
16
  importsWhitelist?: string[]
17
17
  disableExtraction?: boolean
18
+ disableDebugAttr?: boolean
19
+ disableExtractInlineMedia?: boolean
18
20
  exclude?: RegExp
19
21
  logTimings?: boolean
20
22
 
@@ -30,9 +32,17 @@ export type ExtractedAttrAttr = {
30
32
  value: t.JSXAttribute | t.JSXSpreadAttribute
31
33
  }
32
34
 
33
- export type ExtractedAttrStyle = { type: 'style'; value: Object }
35
+ export type ExtractedAttrStyle = {
36
+ type: 'style'
37
+ value: Object
38
+ attr?: t.JSXAttribute | t.JSXSpreadAttribute
39
+ name?: string
40
+ }
34
41
 
35
- export type ExtractedAttr = ExtractedAttrAttr | { type: 'ternary'; value: Ternary } | ExtractedAttrStyle
42
+ export type ExtractedAttr =
43
+ | ExtractedAttrAttr
44
+ | { type: 'ternary'; value: Ternary }
45
+ | ExtractedAttrStyle
36
46
 
37
47
  export type ExtractTagProps = {
38
48
  attrs: ExtractedAttr[]
@@ -51,7 +61,6 @@ export type ExtractorParseProps = TamaguiOptions & {
51
61
  shouldPrintDebug?: boolean
52
62
  onExtractTag: (props: ExtractTagProps) => void
53
63
  getFlattenedNode: (props: { isTextView: boolean; tag: string }) => string
54
- onDidFlatten?: () => void
55
64
  }
56
65
 
57
66
  export interface Ternary {