@tamagui/static 1.88.13 → 1.89.0-1706308641099

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. package/LICENSE +21 -0
  2. package/dist/esm/constants.mjs +10 -0
  3. package/dist/esm/extractor/accessSafe.mjs +11 -0
  4. package/dist/esm/extractor/babelParse.mjs +18 -0
  5. package/dist/esm/extractor/buildClassName.mjs +26 -0
  6. package/dist/esm/extractor/bundle.mjs +94 -0
  7. package/dist/esm/extractor/bundleConfig.mjs +263 -0
  8. package/dist/esm/extractor/createEvaluator.mjs +34 -0
  9. package/dist/esm/extractor/createExtractor.mjs +952 -0
  10. package/dist/esm/extractor/ensureImportingConcat.mjs +13 -0
  11. package/dist/esm/extractor/esbuildAliasPlugin.mjs +20 -0
  12. package/dist/esm/extractor/evaluateAstNode.mjs +48 -0
  13. package/dist/esm/extractor/extractHelpers.mjs +72 -0
  14. package/dist/esm/extractor/extractMediaStyle.mjs +93 -0
  15. package/dist/esm/extractor/extractToClassNames.mjs +237 -0
  16. package/dist/esm/extractor/findTopmostFunction.mjs +10 -0
  17. package/dist/esm/extractor/generateTamaguiStudioConfig.mjs +108 -0
  18. package/dist/esm/extractor/generatedUid.mjs +12 -0
  19. package/dist/esm/extractor/getPrefixLogs.mjs +4 -0
  20. package/dist/esm/extractor/getPropValueFromAttributes.mjs +31 -0
  21. package/dist/esm/extractor/getSourceModule.mjs +33 -0
  22. package/dist/esm/extractor/getStaticBindingsForScope.mjs +112 -0
  23. package/dist/esm/extractor/getTamaguiConfigPathFromOptionsConfig.mjs +5 -0
  24. package/dist/esm/extractor/hoistClassNames.mjs +24 -0
  25. package/dist/esm/extractor/literalToAst.mjs +48 -0
  26. package/dist/esm/extractor/loadFile.mjs +11 -0
  27. package/dist/esm/extractor/loadTamagui.mjs +233 -0
  28. package/dist/esm/extractor/logLines.mjs +11 -0
  29. package/dist/esm/extractor/normalizeTernaries.mjs +33 -0
  30. package/dist/esm/extractor/propsToFontFamilyCache.mjs +12 -0
  31. package/dist/esm/extractor/removeUnusedHooks.mjs +41 -0
  32. package/dist/esm/extractor/timer.mjs +19 -0
  33. package/dist/esm/extractor/validHTMLAttributes.mjs +49 -0
  34. package/dist/esm/getPragmaOptions.mjs +19 -0
  35. package/dist/esm/helpers/memoize.mjs +13 -0
  36. package/dist/esm/helpers/requireTamaguiCore.mjs +5 -0
  37. package/dist/esm/index.mjs +3 -0
  38. package/dist/esm/minifyCSS.mjs +12 -0
  39. package/dist/esm/registerRequire.mjs +74 -0
  40. package/dist/esm/server.mjs +40 -0
  41. package/dist/esm/setup.mjs +1 -0
  42. package/dist/esm/static.mjs +10 -0
  43. package/dist/esm/types.mjs +0 -0
  44. package/dist/esm/webpackPlugin.mjs +7 -0
  45. package/package.json +15 -15
@@ -0,0 +1,13 @@
1
+ import * as t from "@babel/types";
2
+ const importConcatPkg = "@tamagui/helpers";
3
+ function ensureImportingConcat(path) {
4
+ const imported = path.get("body").find(x => x.isImportDeclaration() && x.node.source.value === importConcatPkg),
5
+ importSpecifier = t.importSpecifier(t.identifier("concatClassName"), t.identifier("concatClassName"));
6
+ if (!imported) {
7
+ path.node.body.push(t.importDeclaration([importSpecifier], t.stringLiteral(importConcatPkg)));
8
+ return;
9
+ }
10
+ const specifiers = imported.node.specifiers;
11
+ specifiers.some(x => t.isImportSpecifier(x) && t.isIdentifier(x.imported) && x.imported.name === "concatClassName") || specifiers.push(t.importSpecifier(t.identifier("concatClassName"), t.identifier("concatClassName")));
12
+ }
13
+ export { ensureImportingConcat };
@@ -0,0 +1,20 @@
1
+ const esbuildAliasPlugin = config => {
2
+ const alias = config && Object.keys(config);
3
+ return {
4
+ name: "path-alias",
5
+ setup(build) {
6
+ if (!alias || !alias.length) return;
7
+ const main = (k, args) => ({
8
+ path: config[k].replace(/\/$/, "")
9
+ });
10
+ alias.forEach(k => {
11
+ build.onResolve({
12
+ filter: new RegExp(`^.*${k}$`)
13
+ }, args => main(k, args)), build.onResolve({
14
+ filter: new RegExp(`^.*\\/${k}\\/.*$`)
15
+ }, args => main(k, args));
16
+ });
17
+ }
18
+ };
19
+ };
20
+ export { esbuildAliasPlugin };
@@ -0,0 +1,48 @@
1
+ import * as t from "@babel/types";
2
+ function evaluateAstNode(exprNode, evalFn, shouldPrintDebug) {
3
+ if (exprNode !== void 0) {
4
+ if (exprNode === null) return !0;
5
+ if (t.isJSXExpressionContainer(exprNode)) return evaluateAstNode(exprNode.expression);
6
+ if (t.isObjectExpression(exprNode)) {
7
+ const ret = {};
8
+ for (let idx = -1, len = exprNode.properties.length; ++idx < len;) {
9
+ const value = exprNode.properties[idx];
10
+ if (!t.isObjectProperty(value)) throw new Error("evaluateAstNode can only evaluate object properties");
11
+ let key;
12
+ if (value.computed) {
13
+ if (typeof evalFn != "function") throw new Error("evaluateAstNode does not support computed keys unless an eval function is provided");
14
+ key = evaluateAstNode(value.key, evalFn);
15
+ } else if (t.isIdentifier(value.key)) key = value.key.name;else if (t.isStringLiteral(value.key) || t.isNumericLiteral(value.key)) key = value.key.value;else throw new Error("Unsupported key type: " + value.key.type);
16
+ if (typeof key != "string" && typeof key != "number") throw new Error("key must be either a string or a number");
17
+ ret[key] = evaluateAstNode(value.value, evalFn);
18
+ }
19
+ return ret;
20
+ }
21
+ if (t.isArrayExpression(exprNode)) return exprNode.elements.map(x => evaluateAstNode(x, evalFn));
22
+ if (t.isUnaryExpression(exprNode) && exprNode.operator === "-") {
23
+ const ret = evaluateAstNode(exprNode.argument, evalFn);
24
+ return ret == null ? null : -ret;
25
+ }
26
+ if (t.isTemplateLiteral(exprNode)) {
27
+ if (typeof evalFn != "function") throw new Error("evaluateAstNode does not support template literals unless an eval function is provided");
28
+ let ret = "";
29
+ for (let idx = -1, len = exprNode.quasis.length; ++idx < len;) {
30
+ const quasi = exprNode.quasis[idx],
31
+ expr = exprNode.expressions[idx];
32
+ ret += quasi.value.raw, expr && (ret += evaluateAstNode(expr, evalFn));
33
+ }
34
+ return ret;
35
+ }
36
+ if (t.isNullLiteral(exprNode)) return null;
37
+ if (t.isNumericLiteral(exprNode) || t.isStringLiteral(exprNode) || t.isBooleanLiteral(exprNode)) return exprNode.value;
38
+ if (t.isBinaryExpression(exprNode)) {
39
+ if (exprNode.operator === "+") return evaluateAstNode(exprNode.left, evalFn) + evaluateAstNode(exprNode.right, evalFn);
40
+ if (exprNode.operator === "-") return evaluateAstNode(exprNode.left, evalFn) - evaluateAstNode(exprNode.right, evalFn);
41
+ if (exprNode.operator === "*") return evaluateAstNode(exprNode.left, evalFn) * evaluateAstNode(exprNode.right, evalFn);
42
+ if (exprNode.operator === "/") return evaluateAstNode(exprNode.left, evalFn) / evaluateAstNode(exprNode.right, evalFn);
43
+ }
44
+ if (typeof evalFn != "function") throw new Error("evaluateAstNode does not support non-literal values unless an eval function is provided");
45
+ return evalFn(exprNode);
46
+ }
47
+ }
48
+ export { evaluateAstNode };
@@ -0,0 +1,72 @@
1
+ import { basename } from "path";
2
+ import generate from "@babel/generator";
3
+ import * as t from "@babel/types";
4
+ import findRoot from "find-root";
5
+ import { memoize } from "../helpers/memoize.mjs";
6
+ function isPresent(input) {
7
+ return input != null;
8
+ }
9
+ function isSimpleSpread(node) {
10
+ return t.isIdentifier(node.argument) || t.isMemberExpression(node.argument);
11
+ }
12
+ const attrStr = attr => attr ? attr.type === "attr" ? getNameAttr(attr.value) : attr.type === "ternary" ? `...${ternaryStr(attr.value)}` : `${attr.type}(${objToStr(attr.value)})` : "",
13
+ objToStr = (obj, spacer = ", ") => obj ? `{${Object.entries(obj).map(([k, v]) => `${k}:${Array.isArray(v) ? "[...]" : v && typeof v == "object" ? `${objToStr(v, ",")}` : JSON.stringify(v)}`).join(spacer)}}` : `${obj}`,
14
+ getNameAttr = attr => t.isJSXSpreadAttribute(attr) ? `...${attr.argument.name}` : "name" in attr ? attr.name.name : `unknown-${attr.type}`,
15
+ ternaryStr = x => ["ternary(", t.isIdentifier(x.test) ? x.test.name : t.isMemberExpression(x.test) ? [x.test.object.name, x.test.property.name] :
16
+ // @ts-ignore
17
+ generate(x.test).code, isFilledObj(x.consequent) ? ` ? ${objToStr(x.consequent)}` : " ? \u{1F6AB}", isFilledObj(x.alternate) ? ` : ${objToStr(x.alternate)}` : " : \u{1F6AB}", ")"].flat().join(""),
18
+ isFilledObj = obj => obj && Object.keys(obj).length;
19
+ function findComponentName(scope) {
20
+ const componentName = "";
21
+ let cur = scope.path;
22
+ for (; cur.parentPath && !t.isProgram(cur.parentPath.parent);) cur = cur.parentPath;
23
+ let node = cur.parent;
24
+ if (t.isExportNamedDeclaration(node) && (node = node.declaration), t.isVariableDeclaration(node)) {
25
+ const [dec] = node.declarations;
26
+ if (t.isVariableDeclarator(dec) && t.isIdentifier(dec.id)) return dec.id.name;
27
+ }
28
+ return t.isFunctionDeclaration(node) ? node.id?.name : componentName;
29
+ }
30
+ function isValidThemeHook(props, jsxPath, n, sourcePath) {
31
+ if (!t.isIdentifier(n.object) || !t.isIdentifier(n.property)) return !1;
32
+ const binding = jsxPath.scope.getAllBindings()[n.object.name];
33
+ if (!binding?.path || !binding.path.isVariableDeclarator()) return !1;
34
+ const init = binding.path.node.init;
35
+ if (!init || !t.isCallExpression(init) || !t.isIdentifier(init.callee) || init.callee.name !== "useTheme") return !1;
36
+ const importNode = binding.scope.getBinding("useTheme")?.path.parent;
37
+ return !(!t.isImportDeclaration(importNode) || sourcePath && !isValidImport(props, sourcePath));
38
+ }
39
+ const isInsideComponentPackage = (props, moduleName) => getValidComponentsPaths(props).some(path => moduleName.startsWith(path)),
40
+ isComponentPackage = (props, srcName) => getValidComponentsPaths(props).some(path => srcName.startsWith(path));
41
+ function getValidComponent(props, moduleName, componentName) {
42
+ if (componentName[0].toUpperCase() !== componentName[0]) return !1;
43
+ for (const loaded of props.allLoadedComponents) {
44
+ if (!loaded) continue;
45
+ const isInModule = moduleName === "*" || moduleName.startsWith(loaded.moduleName),
46
+ foundComponent = loaded.nameToInfo[componentName];
47
+ if (isInModule && foundComponent) return foundComponent;
48
+ }
49
+ return null;
50
+ }
51
+ const isValidModule = (props, moduleName) => {
52
+ if (typeof moduleName != "string") throw new Error("No module name");
53
+ const isLocal = moduleName.startsWith(".");
54
+ return {
55
+ isLocal,
56
+ isValid: isLocal ? isInsideComponentPackage(props, moduleName) : isComponentPackage(props, moduleName)
57
+ };
58
+ },
59
+ getValidImport = (props, moduleName, componentName) => {
60
+ const {
61
+ isValid,
62
+ isLocal
63
+ } = isValidModule(props, moduleName);
64
+ return !isValid || !componentName ? null : getValidComponent(props, isLocal ? "*" : moduleName, componentName) || null;
65
+ },
66
+ isValidImport = (props, moduleName, componentName) => componentName ? !!getValidImport(props, moduleName, componentName) : isValidModule(props, moduleName).isValid,
67
+ getValidComponentPackages = memoize(props => [... /* @__PURE__ */new Set(["@tamagui/core", "tamagui", ...props.components])]),
68
+ getValidComponentsPaths = memoize(props => getValidComponentPackages(props).flatMap(pkg => {
69
+ const root = findRoot(pkg);
70
+ return [basename(root), pkg].filter(Boolean);
71
+ }));
72
+ export { attrStr, findComponentName, getValidComponent, getValidComponentsPaths, getValidImport, isComponentPackage, isInsideComponentPackage, isPresent, isSimpleSpread, isValidImport, isValidModule, isValidThemeHook, objToStr, ternaryStr };
@@ -0,0 +1,93 @@
1
+ import * as t from "@babel/types";
2
+ import { createMediaStyle } from "@tamagui/core";
3
+ import { requireTamaguiCore } from "../helpers/requireTamaguiCore.mjs";
4
+ import { isPresent, isValidImport } from "./extractHelpers.mjs";
5
+ function extractMediaStyle(props, ternary, jsxPath, tamaguiConfig, sourcePath, importance = 0, shouldPrintDebug = !1) {
6
+ const {
7
+ getStylesAtomic,
8
+ mediaObjectToString
9
+ } = requireTamaguiCore("web"),
10
+ mt = getMediaQueryTernary(props, ternary, jsxPath, sourcePath);
11
+ if (!mt) return null;
12
+ const {
13
+ key
14
+ } = mt;
15
+ if (!tamaguiConfig.media[key]) return console.error(`Media query "${key}" not found: ${Object.keys(tamaguiConfig.media)}`), null;
16
+ const getStyleObj = (styleObj, negate = !1) => styleObj ? {
17
+ styleObj,
18
+ negate
19
+ } : null,
20
+ styleOpts = [getStyleObj(ternary.consequent, !1), getStyleObj(ternary.alternate, !0)].filter(isPresent);
21
+ if (shouldPrintDebug && !styleOpts.length) return console.info(" media query, no styles?"), null;
22
+ const mediaKeyPrecendence = Object.keys(tamaguiConfig.media).reduce((acc, cur, i) => (acc[cur] = new Array(importance + 1).fill(":root").join(""), acc), {});
23
+ let mediaStyles = [];
24
+ for (const {
25
+ styleObj,
26
+ negate
27
+ } of styleOpts) {
28
+ const singleMediaStyles = getStylesAtomic(styleObj).map(style => {
29
+ const mediaStyle = createMediaStyle(style, key, tamaguiConfig.media, !0, negate),
30
+ className = `.${mediaStyle.identifier}`;
31
+ return {
32
+ ...mediaStyle,
33
+ className
34
+ };
35
+ });
36
+ shouldPrintDebug === "verbose" && console.info(" media styles:", importance, styleObj, singleMediaStyles.map(x => x.identifier).join(", ")), mediaStyles = [...mediaStyles, ...singleMediaStyles];
37
+ }
38
+ return ternary.remove(), {
39
+ mediaStyles,
40
+ ternaryWithoutMedia: mt.ternaryWithoutMedia
41
+ };
42
+ }
43
+ function getMediaQueryTernary(props, ternary, jsxPath, sourcePath) {
44
+ if (t.isLogicalExpression(ternary.test) && ternary.test.operator === "&&") {
45
+ const mediaLeft = getMediaInfoFromExpression(props, ternary.test.left, jsxPath, sourcePath, ternary.inlineMediaQuery);
46
+ if (mediaLeft) return {
47
+ ...mediaLeft,
48
+ ternaryWithoutMedia: {
49
+ ...ternary,
50
+ test: ternary.test.right
51
+ }
52
+ };
53
+ }
54
+ const result = getMediaInfoFromExpression(props, ternary.test, jsxPath, sourcePath, ternary.inlineMediaQuery);
55
+ return result ? {
56
+ ...result,
57
+ ternaryWithoutMedia: null
58
+ } : null;
59
+ }
60
+ function getMediaInfoFromExpression(props, test, jsxPath, sourcePath, inlineMediaQuery) {
61
+ if (inlineMediaQuery) return {
62
+ key: inlineMediaQuery,
63
+ bindingName: inlineMediaQuery
64
+ };
65
+ if (t.isMemberExpression(test) && t.isIdentifier(test.object) && t.isIdentifier(test.property)) {
66
+ const name = test.object.name,
67
+ key = test.property.name,
68
+ binding = jsxPath.scope.getAllBindings()[name];
69
+ if (!binding) return !1;
70
+ const bindingNode = binding.path?.node;
71
+ return !t.isVariableDeclarator(bindingNode) || !bindingNode.init || !isValidMediaCall(props, jsxPath, bindingNode.init, sourcePath) ? !1 : {
72
+ key,
73
+ bindingName: name
74
+ };
75
+ }
76
+ if (t.isIdentifier(test)) {
77
+ const key = test.name,
78
+ node = jsxPath.scope.getBinding(test.name)?.path?.node;
79
+ return !t.isVariableDeclarator(node) || !node.init || !isValidMediaCall(props, jsxPath, node.init, sourcePath) ? !1 : {
80
+ key,
81
+ bindingName: key
82
+ };
83
+ }
84
+ return null;
85
+ }
86
+ function isValidMediaCall(props, jsxPath, init, sourcePath) {
87
+ if (!init || !t.isCallExpression(init) || !t.isIdentifier(init.callee) || init.callee.name !== "useMedia") return !1;
88
+ const mediaBinding = jsxPath.scope.getAllBindings().useMedia;
89
+ if (!mediaBinding) return !1;
90
+ const useMediaImport = mediaBinding.path.parent;
91
+ return !(!t.isImportDeclaration(useMediaImport) || !isValidImport(props, sourcePath));
92
+ }
93
+ export { extractMediaStyle, isValidMediaCall };
@@ -0,0 +1,237 @@
1
+ import * as path from "path";
2
+ import { basename } from "path";
3
+ import * as util from "util";
4
+ import generate from "@babel/generator";
5
+ import * as t from "@babel/types";
6
+ import { concatClassName } from "@tamagui/helpers";
7
+ import { requireTamaguiCore } from "../helpers/requireTamaguiCore.mjs";
8
+ import { babelParse } from "./babelParse.mjs";
9
+ import { buildClassName } from "./buildClassName.mjs";
10
+ import { ensureImportingConcat } from "./ensureImportingConcat.mjs";
11
+ import { isSimpleSpread } from "./extractHelpers.mjs";
12
+ import { extractMediaStyle } from "./extractMediaStyle.mjs";
13
+ import { getPrefixLogs } from "./getPrefixLogs.mjs";
14
+ import { hoistClassNames } from "./hoistClassNames.mjs";
15
+ import { logLines } from "./logLines.mjs";
16
+ import { getFontFamilyClassNameFromProps } from "./propsToFontFamilyCache.mjs";
17
+ import { timer } from "./timer.mjs";
18
+ const mergeStyleGroups = {
19
+ shadowOpacity: !0,
20
+ shadowRadius: !0,
21
+ shadowColor: !0,
22
+ shadowOffset: !0
23
+ };
24
+ async function extractToClassNames({
25
+ extractor,
26
+ source,
27
+ sourcePath,
28
+ options,
29
+ shouldPrintDebug
30
+ }) {
31
+ const tm = timer(),
32
+ {
33
+ getStylesAtomic
34
+ } = requireTamaguiCore("web");
35
+ if (sourcePath?.includes("node_modules")) return null;
36
+ if (shouldPrintDebug && console.warn(`--- ${sourcePath} ---
37
+
38
+ `), typeof source != "string") throw new Error("`source` must be a string of javascript");
39
+ if (sourcePath && !path.isAbsolute(sourcePath)) throw new Error("`sourcePath` must be an absolute path to a .js file, got: " + sourcePath);
40
+ /.[tj]sx?$/i.test(sourcePath || "") || console.warn(`${sourcePath?.slice(0, 100)} - bad filename.`), !options.disableExtraction && !options._disableLoadTamagui && (await extractor.loadTamagui(options));
41
+ const shouldLogTiming = options.logTimings ?? !0,
42
+ start = Date.now(),
43
+ mem = process.env.TAMAGUI_SHOW_MEMORY_USAGE && shouldLogTiming ? process.memoryUsage() : null;
44
+ let ast;
45
+ try {
46
+ ast = babelParse(source, sourcePath);
47
+ } catch (err) {
48
+ throw console.error("babel parse error:", sourcePath?.slice(0, 100)), err;
49
+ }
50
+ tm.mark("babel-parse", shouldPrintDebug === "verbose");
51
+ const cssMap = /* @__PURE__ */new Map(),
52
+ existingHoists = {};
53
+ let hasFlattened = !1;
54
+ const res = await extractor.parse(ast, {
55
+ shouldPrintDebug,
56
+ ...options,
57
+ sourcePath,
58
+ extractStyledDefinitions: !0,
59
+ onStyleRule(identifier, rules) {
60
+ const css = rules.join(";");
61
+ shouldPrintDebug && console.info(`adding styled() rule: .${identifier} ${css}`), cssMap.set(`.${identifier}`, {
62
+ css,
63
+ commentTexts: []
64
+ });
65
+ },
66
+ getFlattenedNode: ({
67
+ tag
68
+ }) => (hasFlattened = !0, tag),
69
+ onExtractTag: ({
70
+ parserProps,
71
+ attrs,
72
+ node,
73
+ attemptEval,
74
+ jsxPath,
75
+ originalNodeName,
76
+ filePath,
77
+ lineNumbers,
78
+ programPath,
79
+ isFlattened,
80
+ config,
81
+ completeProps,
82
+ staticConfig
83
+ }) => {
84
+ if (staticConfig.acceptsClassName === !1) {
85
+ shouldPrintDebug && console.info("bail, acceptsClassName is false");
86
+ return;
87
+ }
88
+ const didFlattenThisTag = hasFlattened;
89
+ hasFlattened = !1;
90
+ let finalClassNames = [];
91
+ const finalAttrs = [];
92
+ let finalStyles = [],
93
+ viewStyles = {};
94
+ for (const attr of attrs) attr.type === "style" && (viewStyles = {
95
+ ...viewStyles,
96
+ ...attr.value
97
+ });
98
+ const ensureNeededPrevStyle = style => {
99
+ if (!Object.keys(style).some(key => mergeStyleGroups[key])) return style;
100
+ for (const k in mergeStyleGroups) k in viewStyles && (style[k] = style[k] ?? viewStyles[k]);
101
+ return style;
102
+ },
103
+ addStyles = style => {
104
+ if (!style) return [];
105
+ const styleWithPrev = ensureNeededPrevStyle(style),
106
+ res2 = getStylesAtomic(styleWithPrev);
107
+ return res2.length && (finalStyles = [...finalStyles, ...res2]), res2;
108
+ };
109
+ let lastMediaImportance = 1;
110
+ for (const attr of attrs) switch (attr.type) {
111
+ case "style":
112
+ {
113
+ if (isFlattened) {
114
+ const styles2 = addStyles(attr.value),
115
+ newFontFamily = getFontFamilyClassNameFromProps(attr.value) || "",
116
+ newClassNames = concatClassName(styles2.map(x => x.identifier).join(" ") + newFontFamily),
117
+ existing = finalClassNames.find(x => x.type == "StringLiteral");
118
+ if (existing) {
119
+ let previous = existing.value;
120
+ newFontFamily && (shouldPrintDebug && console.info(` newFontFamily: ${newFontFamily}`), previous = previous.replace(/font_[a-z]+/i, "")), existing.value = `${previous} ${newClassNames}`;
121
+ } else finalClassNames = [...finalClassNames, t.stringLiteral(newClassNames)];
122
+ } else {
123
+ const styles2 = getStylesAtomic(attr.value);
124
+ finalStyles = [...finalStyles, ...styles2];
125
+ for (const style of styles2) {
126
+ const prop = style.pseudo ? `${style.property}-${style.pseudo}` : style.property;
127
+ finalAttrs.push(t.jsxAttribute(t.jsxIdentifier(prop), t.stringLiteral(style.identifier)));
128
+ }
129
+ }
130
+ break;
131
+ }
132
+ case "attr":
133
+ {
134
+ const val = attr.value;
135
+ if (t.isJSXSpreadAttribute(val)) isSimpleSpread(val) && finalClassNames.push(t.logicalExpression("&&", val.argument, t.memberExpression(val.argument, t.identifier("className"))));else if (val.name.name === "className") {
136
+ const value = val.value;
137
+ if (value) try {
138
+ const evaluatedValue = attemptEval(value);
139
+ finalClassNames.push(t.stringLiteral(evaluatedValue));
140
+ } catch {
141
+ finalClassNames.push(value.expression);
142
+ }
143
+ continue;
144
+ }
145
+ finalAttrs.push(val);
146
+ break;
147
+ }
148
+ case "ternary":
149
+ {
150
+ const mediaExtraction = extractMediaStyle(parserProps, attr.value, jsxPath, extractor.getTamagui(), sourcePath || "", lastMediaImportance, shouldPrintDebug);
151
+ if (shouldPrintDebug && mediaExtraction && console.info("ternary (mediaStyles)", mediaExtraction.ternaryWithoutMedia?.inlineMediaQuery ?? "", mediaExtraction.mediaStyles.map(x => x.identifier).join(".")), !mediaExtraction) {
152
+ addTernaryStyle(attr.value, addStyles(attr.value.consequent), addStyles(attr.value.alternate));
153
+ continue;
154
+ }
155
+ lastMediaImportance++, mediaExtraction.mediaStyles && (finalStyles = [...finalStyles, ...mediaExtraction.mediaStyles]), mediaExtraction.ternaryWithoutMedia ? addTernaryStyle(mediaExtraction.ternaryWithoutMedia, mediaExtraction.mediaStyles, []) : finalClassNames = [...finalClassNames, ...mediaExtraction.mediaStyles.map(x => t.stringLiteral(x.identifier))];
156
+ break;
157
+ }
158
+ }
159
+ function addTernaryStyle(ternary, a, b) {
160
+ const cCN = a.map(x => x.identifier).join(" "),
161
+ aCN = b.map(x => x.identifier).join(" ");
162
+ a.length && b.length ? finalClassNames.push(t.conditionalExpression(ternary.test, t.stringLiteral(cCN), t.stringLiteral(aCN))) : finalClassNames.push(t.conditionalExpression(ternary.test, t.stringLiteral(" " + cCN), t.stringLiteral(" " + aCN)));
163
+ }
164
+ if (shouldPrintDebug && console.info(` finalClassNames
165
+ `, logLines(finalClassNames.map(x => x.value).join(" "))), node.attributes = finalAttrs, finalClassNames.length) {
166
+ const extraClassNames = (() => {
167
+ let value = "";
168
+ return isFlattened && (process.env.TAMAGUI_DEBUG_OPTIMIZATIONS && (value += "is_tamagui_flattened"), staticConfig.componentName && (value += ` is_${staticConfig.componentName}`)), value;
169
+ })(),
170
+ names = buildClassName(finalClassNames, extraClassNames),
171
+ nameExpr = names ? hoistClassNames(jsxPath, existingHoists, names) : null;
172
+ let expr = nameExpr;
173
+ if (nameExpr && !t.isIdentifier(nameExpr) && didFlattenThisTag) {
174
+ ensureImportingConcat(programPath);
175
+ const simpleSpreads = attrs.filter(x => x.type === "attr" && t.isJSXSpreadAttribute(x.value) && isSimpleSpread(x.value));
176
+ expr = t.callExpression(t.identifier("concatClassName"), [expr, ...simpleSpreads.map(val => val.value.argument)]);
177
+ }
178
+ node.attributes.push(t.jsxAttribute(t.jsxIdentifier("className"), t.jsxExpressionContainer(expr)));
179
+ }
180
+ const comment = util.format("/* %s:%s (%s) */", filePath, lineNumbers, originalNodeName);
181
+ for (const {
182
+ identifier,
183
+ rules
184
+ } of finalStyles) {
185
+ const className = `.${identifier}`;
186
+ if (cssMap.has(className)) {
187
+ if (comment) {
188
+ const val = cssMap.get(className);
189
+ val.commentTexts.push(comment), cssMap.set(className, val);
190
+ }
191
+ } else rules.length && cssMap.set(className, {
192
+ css: rules.join(`
193
+ `),
194
+ commentTexts: [comment]
195
+ });
196
+ }
197
+ }
198
+ });
199
+ if (!res || !res.modified && !res.optimized && !res.flattened && !res.styled) return shouldPrintDebug && console.info("no res or none modified", res), null;
200
+ const styles = Array.from(cssMap.values()).map(x => x.css).join(`
201
+ `).trim(),
202
+ result = generate(ast, {
203
+ concise: !1,
204
+ filename: sourcePath,
205
+ // this makes the debug output terrible, and i think sourcemap works already
206
+ retainLines: !1,
207
+ sourceFileName: sourcePath,
208
+ sourceMaps: !0
209
+ }, source);
210
+ if (shouldPrintDebug && (console.info(`
211
+ -------- output code -------
212
+
213
+ `, result.code.split(`
214
+ `).filter(x => !x.startsWith("//")).join(`
215
+ `)), console.info(`
216
+ -------- output style --------
217
+
218
+ `, styles)), shouldLogTiming) {
219
+ const memUsed = mem ? Math.round((process.memoryUsage().heapUsed - mem.heapUsed) / 1024 / 1204 * 10) / 10 : 0,
220
+ path2 = basename(sourcePath || "").replace(/\.[jt]sx?$/, "").slice(0, 22).trim().padStart(24),
221
+ numOptimized = `${res.optimized + res.styled}`.padStart(3),
222
+ numFound = `${res.found + res.styled}`.padStart(3),
223
+ numFlattened = `${res.flattened}`.padStart(3),
224
+ memory = memUsed ? ` ${memUsed}MB` : "",
225
+ timingStr = `${Date.now() - start}ms`.padStart(6),
226
+ pre = getPrefixLogs(options),
227
+ memStr = memory ? `(${memory})` : "";
228
+ console.info(`${pre} ${path2} \xB7 ${numFound} found \xB7 ${numOptimized} opt \xB7 ${numFlattened} flat ${timingStr} ${memStr}`);
229
+ }
230
+ return {
231
+ ast,
232
+ styles,
233
+ js: result.code,
234
+ map: result.map
235
+ };
236
+ }
237
+ export { extractToClassNames };
@@ -0,0 +1,10 @@
1
+ function findTopmostFunction(jsxPath) {
2
+ const isFunction = path => path.isArrowFunctionExpression() || path.isFunctionDeclaration() || path.isFunctionExpression();
3
+ let compFn = jsxPath.findParent(isFunction);
4
+ for (; compFn;) {
5
+ const parent = compFn.findParent(isFunction);
6
+ if (parent) compFn = parent;else break;
7
+ }
8
+ return compFn || null;
9
+ }
10
+ export { findTopmostFunction };
@@ -0,0 +1,108 @@
1
+ import { dirname, join } from "path";
2
+ import { generateThemes, writeGeneratedThemes } from "@tamagui/generate-themes";
3
+ import fs, { readFile } from "fs-extra";
4
+ import { requireTamaguiCore } from "../helpers/requireTamaguiCore.mjs";
5
+ import { getBundledConfig } from "./bundleConfig.mjs";
6
+ const tamaguiDir = join(process.cwd(), ".tamagui"),
7
+ confFile = join(tamaguiDir, "tamagui.config.json");
8
+ async function generateTamaguiStudioConfig(tamaguiOptions, configIn, rebuild = !1) {
9
+ try {
10
+ const config = configIn ?? (await getBundledConfig(tamaguiOptions, rebuild));
11
+ if (!config) return;
12
+ const out = transformConfig(config, tamaguiOptions.platform);
13
+ await fs.ensureDir(dirname(confFile)), await fs.writeJSON(confFile, out, {
14
+ spaces: 2
15
+ });
16
+ } catch (err) {
17
+ (process.env.DEBUG?.includes("tamagui") || process.env.IS_TAMAGUI_DEV) && console.warn("generateTamaguiStudioConfig error", err);
18
+ }
19
+ }
20
+ function generateTamaguiStudioConfigSync(_tamaguiOptions, config) {
21
+ try {
22
+ fs.ensureDirSync(dirname(confFile)), fs.writeJSONSync(confFile, transformConfig(config, _tamaguiOptions.platform), {
23
+ spaces: 2
24
+ });
25
+ } catch (err) {
26
+ (process.env.DEBUG?.includes("tamagui") || process.env.IS_TAMAGUI_DEV) && console.warn("generateTamaguiStudioConfig error", err);
27
+ }
28
+ }
29
+ async function generateTamaguiThemes(tamaguiOptions, force = !1) {
30
+ if (!tamaguiOptions.themeBuilder) return;
31
+ const {
32
+ input,
33
+ output
34
+ } = tamaguiOptions.themeBuilder,
35
+ inPath = resolveRelativePath(input),
36
+ outPath = resolveRelativePath(output),
37
+ generatedOutput = await generateThemes(inPath),
38
+ hasChanged = force || (await (async () => {
39
+ try {
40
+ if (!(await fs.pathExists(join(tamaguiDir, "theme-builder.json")))) return !0;
41
+ if (!generatedOutput) return !1;
42
+ const next = generatedOutput.generated,
43
+ current = await readFile(outPath, "utf-8");
44
+ return next !== current;
45
+ } catch {}
46
+ return !0;
47
+ })());
48
+ return hasChanged && (await writeGeneratedThemes(tamaguiDir, outPath, generatedOutput)), hasChanged;
49
+ }
50
+ const resolveRelativePath = inputPath => inputPath.startsWith(".") ? join(process.cwd(), inputPath) : require.resolve(inputPath);
51
+ function cloneDeepSafe(x, excludeKeys = {}) {
52
+ return x && (Array.isArray(x) ? x.map(_ => cloneDeepSafe(_)) : typeof x == "function" ? "Function" : typeof x != "object" ? x : "$$typeof" in x ? "Component" : Object.fromEntries(Object.entries(x).flatMap(([k, v]) => excludeKeys[k] ? [] : [[k, cloneDeepSafe(v)]])));
53
+ }
54
+ function transformConfig(config, platform) {
55
+ if (!config) return null;
56
+ const {
57
+ getVariableValue
58
+ } = requireTamaguiCore(platform),
59
+ next = cloneDeepSafe(config, {
60
+ validStyles: !0
61
+ }),
62
+ {
63
+ components,
64
+ nameToPaths,
65
+ tamaguiConfig
66
+ } = next,
67
+ {
68
+ themes,
69
+ tokens
70
+ } = tamaguiConfig;
71
+ for (const key in themes) {
72
+ const theme = themes[key];
73
+ theme.id = key;
74
+ for (const tkey in theme) theme[tkey] = getVariableValue(theme[tkey]);
75
+ }
76
+ for (const key in tokens) {
77
+ const token = {
78
+ ...tokens[key]
79
+ };
80
+ for (const tkey in token) token[tkey] = getVariableValue(token[tkey]);
81
+ }
82
+ for (const component of components) for (const _ in component.nameToInfo) {
83
+ const compDefinition = {
84
+ ...component.nameToInfo[_]
85
+ };
86
+ component.nameToInfo[_] = compDefinition;
87
+ const {
88
+ parentStaticConfig,
89
+ ...rest
90
+ } = compDefinition.staticConfig;
91
+ compDefinition.staticConfig = rest;
92
+ }
93
+ next.nameToPaths = {};
94
+ for (const key in nameToPaths) next.nameToPaths[key] = [...nameToPaths[key]];
95
+ const {
96
+ fontsParsed,
97
+ getCSS,
98
+ tokensParsed,
99
+ themeConfig,
100
+ ...cleanedConfig
101
+ } = next.tamaguiConfig;
102
+ return {
103
+ components,
104
+ nameToPaths,
105
+ tamaguiConfig: cleanedConfig
106
+ };
107
+ }
108
+ export { generateTamaguiStudioConfig, generateTamaguiStudioConfigSync, generateTamaguiThemes };
@@ -0,0 +1,12 @@
1
+ import * as t from "@babel/types";
2
+ function generateUid(scope, name) {
3
+ if (typeof scope != "object") throw "generateUid expects a scope object as its first parameter";
4
+ if (!(typeof name == "string" && name !== "")) throw "generateUid expects a valid name as its second parameter";
5
+ name = t.toIdentifier(name).replace(/^_+/, "").replace(/[0-9]+$/g, "");
6
+ let uid,
7
+ i = 0;
8
+ do i > 1 ? uid = name + i : uid = name, i++; while (scope.hasLabel(uid) || scope.hasBinding(uid) || scope.hasGlobal(uid) || scope.hasReference(uid));
9
+ const program = scope.getProgramParent();
10
+ return program.references[uid] = !0, program.uids[uid] = !0, uid;
11
+ }
12
+ export { generateUid };
@@ -0,0 +1,4 @@
1
+ function getPrefixLogs(options) {
2
+ return options?.prefixLogs ?? ` ${options?.platform || "web"} | `;
3
+ }
4
+ export { getPrefixLogs };
@@ -0,0 +1,31 @@
1
+ import generate from "@babel/generator";
2
+ import * as t from "@babel/types";
3
+ import { accessSafe } from "./accessSafe.mjs";
4
+ function getPropValueFromAttributes(propName, attrs) {
5
+ let propIndex = -1,
6
+ jsxAttr = null;
7
+ for (let idx = -1, len = attrs.length; ++idx < len;) {
8
+ const attr = attrs[idx];
9
+ if (t.isJSXAttribute(attr) && attr.name && attr.name.name === propName) {
10
+ propIndex = idx, jsxAttr = attr;
11
+ break;
12
+ }
13
+ }
14
+ if (!jsxAttr || jsxAttr.value == null) return null;
15
+ let propValue = jsxAttr.value;
16
+ if (t.isJSXExpressionContainer(propValue) && (propValue = propValue.expression), t.isJSXEmptyExpression(propValue)) return console.error("encountered JSXEmptyExpression"), null;
17
+ const applicableSpreads = attrs.filter(
18
+ // 1. idx is greater than propValue prop index
19
+ // 2. attr is a spread operator
20
+ (attr, idx) => {
21
+ if (t.isJSXSpreadAttribute(attr)) {
22
+ if (t.isIdentifier(attr.argument) || t.isMemberExpression(attr.argument)) return idx > propIndex;
23
+ if (t.isLogicalExpression(attr.argument)) return !1;
24
+ throw new Error(`unsupported spread of type "${attr.argument.type}": ${// @ts-ignore
25
+ generate(attr).code}`);
26
+ }
27
+ return !1;
28
+ }).map(attr => attr.argument);
29
+ return applicableSpreads.length > 0 && (propValue = applicableSpreads.reduce((acc, val) => t.logicalExpression("||", accessSafe(val, propName), acc), propValue)), propValue;
30
+ }
31
+ export { getPropValueFromAttributes };