@tamagui/codemod-flat-values 3.0.0-beta.831.1 → 3.0.0-beta.881.1

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.
package/README.md CHANGED
@@ -82,6 +82,11 @@ helper, a `react-native` component, and an intrinsic tag are all left alone —
82
82
  a condition-only branch: with clause-level merge (decision 21)
83
83
  `exitStyle={{ x: 10 }}` is exactly `x="exit:10px"`, which keeps whatever base the
84
84
  styled component, variant, or call site defined — the same thing the v1 prop did.
85
+ - V2 spread variant keys become typed `styled.dynamic` callbacks for the size,
86
+ space, color, radius, font-size, and z-index token categories. Type keys become
87
+ one `number | string | boolean` dynamic, with `typeof` branches when each body
88
+ is one object-literal return. The report leaves catch-all keys, mixed exact and
89
+ function branches, and sibling-prop reads authored.
85
90
 
86
91
  Every program the report suggests is parsed back with the real value parser and merged
87
92
  with the real clause merge before it is printed. A program that does not read back
@@ -198,6 +203,11 @@ A flag means a human decides. Every code the tool can emit:
198
203
  | `structured-<property>` | a condition needs an object or array with no verified CSS-shaped migration rule |
199
204
  | `condition-order-not-preservable`, `base-order-not-preservable` | merging would move a value past something that can also set it |
200
205
  | `computed-property` | a computed key hides the affected style property |
206
+ | `functional-variant-needs-resolve` | the callback reads `extras.props`; use the generated `.resolve` draft |
207
+ | `functional-variant-mixed` | exact branches and a function key share one variant |
208
+ | `functional-variant-catch-all` | `'...'` needs an explicit value type chosen by the app |
209
+ | `functional-variant-type-bodies` | different type-key bodies cannot be combined into safe `typeof` branches |
210
+ | `functional-variant-unsupported`, `functional-variant-unsupported-extras`, `functional-variant-styled-import` | the callback, env access, or `styled` import does not have a provable automatic rewrite |
201
211
  | `emitted-program-mismatch`, `emitted-value-invalid` | the printer failed its own re-parse; this is a codemod bug |
202
212
  | plus any code from the shared converter | `unsupported-legacy-value`, `legacy-condition-object`, `ambiguous-legacy-group`, `legacy-composite-shorthand` |
203
213
 
@@ -215,5 +225,5 @@ payloads go through the same shared converter, so they always agree on that.
215
225
  ## Remaining manual migration
216
226
 
217
227
  The report counts the files whose sites all converted: those have no legacy condition
218
- object left. V3 has no compatibility setting, so the report names every file that
219
- still needs a hand edit after `--write`.
228
+ object or flagged functional variant left. V3 has no compatibility setting, so the
229
+ report names every file that still needs a hand edit after `--write`.
@@ -0,0 +1,469 @@
1
+ import { Node, SyntaxKind } from "ts-morph";
2
+ import { unwrapExpression } from "./expressions.mjs";
3
+
4
+ const spreadTypes = /* @__PURE__ */ new Map([
5
+ ["...size", "SizeTokens"],
6
+ ["...space", "SpaceTokens"],
7
+ ["...color", "ColorTokens"],
8
+ ["...radius", "RadiusTokens"],
9
+ ["...fontSize", "FontSizeTokens"],
10
+ ["...zIndex", "ZIndexTokens"]
11
+ ]);
12
+ const typeKeys = /* @__PURE__ */ new Map([
13
+ [":number", "number"],
14
+ [":string", "string"],
15
+ [":boolean", "boolean"]
16
+ ]);
17
+ const typeOrder = [
18
+ "number",
19
+ "string",
20
+ "boolean"
21
+ ];
22
+ const envMembers = /* @__PURE__ */ new Set([
23
+ "tokens",
24
+ "theme",
25
+ "fonts",
26
+ "font",
27
+ "fontFamily"
28
+ ]);
29
+ function propertyName(node) {
30
+ if (Node.isIdentifier(node) || Node.isPrivateIdentifier(node)) return node.getText();
31
+ if (Node.isStringLiteral(node) || Node.isNumericLiteral(node)) {
32
+ return node.getLiteralText();
33
+ }
34
+ return null;
35
+ }
36
+ function renderNode(node, replacements) {
37
+ const start = node.getStart();
38
+ const end = node.getEnd();
39
+ const selected = [];
40
+ for (const replacement of [...replacements].sort((left, right) => right.end - right.start - (left.end - left.start))) {
41
+ if (replacement.start < start || replacement.end > end) continue;
42
+ if (selected.some((current) => replacement.start < current.end && replacement.end > current.start)) {
43
+ continue;
44
+ }
45
+ selected.push(replacement);
46
+ }
47
+ let text = node.getText();
48
+ for (const replacement of selected.sort((left, right) => right.start - left.start)) {
49
+ const relativeStart = replacement.start - start;
50
+ const relativeEnd = replacement.end - start;
51
+ text = `${text.slice(0, relativeStart)}${replacement.text}${text.slice(relativeEnd)}`;
52
+ }
53
+ return text;
54
+ }
55
+ function referencesWithin(node, definition) {
56
+ return definition.findReferencesAsNodes().filter((reference) => reference.getStart() >= node.getStart() && reference.getEnd() <= node.getEnd());
57
+ }
58
+ function renderObjectReturn(expression, replacements) {
59
+ let current = expression;
60
+ while (Node.isParenthesizedExpression(current)) current = current.getExpression();
61
+ return renderNode(Node.isAsExpression(current) || Node.isTypeAssertion(current) ? expression : unwrapExpression(expression), replacements);
62
+ }
63
+ function callbackAnalysis(callback) {
64
+ const body = callback.getBody();
65
+ const parameters = callback.getParameters();
66
+ const firstNameNode = parameters[0]?.getNameNode();
67
+ const firstName = Node.isIdentifier(firstNameNode) ? firstNameNode.getText() : null;
68
+ const secondNameNode = parameters[1]?.getNameNode();
69
+ const renderedReplacements = [];
70
+ const normalizedReplacements = [];
71
+ const draftReplacements = [];
72
+ const unsupportedExtras = /* @__PURE__ */ new Set();
73
+ let propsLine = null;
74
+ let usesEnv = false;
75
+ if (firstNameNode && Node.isIdentifier(firstNameNode)) {
76
+ for (const reference of referencesWithin(body, firstNameNode)) {
77
+ normalizedReplacements.push({
78
+ start: reference.getStart(),
79
+ end: reference.getEnd(),
80
+ text: "value"
81
+ });
82
+ }
83
+ }
84
+ if (secondNameNode && Node.isIdentifier(secondNameNode)) {
85
+ const references = referencesWithin(body, secondNameNode);
86
+ usesEnv = references.length > 0;
87
+ const otherSameName = body.getDescendantsOfKind(SyntaxKind.Identifier).some((identifier) => identifier.getText() === secondNameNode.getText() && !references.some((reference) => reference.getStart() === identifier.getStart() && reference.getEnd() === identifier.getEnd()));
88
+ const envNameExists = body.getDescendantsOfKind(SyntaxKind.Identifier).some((identifier) => identifier.getText() === "env");
89
+ if (secondNameNode.getText() !== "env" && !otherSameName && !envNameExists) {
90
+ renderedReplacements.push({
91
+ start: secondNameNode.getStart(),
92
+ end: secondNameNode.getEnd(),
93
+ text: "env"
94
+ });
95
+ for (const reference of references) {
96
+ renderedReplacements.push({
97
+ start: reference.getStart(),
98
+ end: reference.getEnd(),
99
+ text: "env"
100
+ });
101
+ }
102
+ }
103
+ for (const reference of references) {
104
+ normalizedReplacements.push({
105
+ start: reference.getStart(),
106
+ end: reference.getEnd(),
107
+ text: "env"
108
+ });
109
+ draftReplacements.push({
110
+ start: reference.getStart(),
111
+ end: reference.getEnd(),
112
+ text: "env"
113
+ });
114
+ const parent = reference.getParent();
115
+ if (Node.isPropertyAccessExpression(parent) && parent.getExpression().getStart() === reference.getStart()) {
116
+ const member = parent.getName();
117
+ if (member === "props") {
118
+ propsLine ??= callback.getSourceFile().getLineAndColumnAtPos(parent.getStart()).line;
119
+ draftReplacements.push({
120
+ start: parent.getStart(),
121
+ end: parent.getEnd(),
122
+ text: "props"
123
+ });
124
+ } else if (!envMembers.has(member)) {
125
+ unsupportedExtras.add(member);
126
+ }
127
+ }
128
+ if (Node.isElementAccessExpression(parent) && parent.getExpression().getStart() === reference.getStart()) {
129
+ const argument = parent.getArgumentExpression();
130
+ const member = argument && Node.isStringLiteral(argument) ? argument.getLiteralValue() : null;
131
+ if (member === "props") {
132
+ propsLine ??= callback.getSourceFile().getLineAndColumnAtPos(parent.getStart()).line;
133
+ draftReplacements.push({
134
+ start: parent.getStart(),
135
+ end: parent.getEnd(),
136
+ text: "props"
137
+ });
138
+ } else if (member === null || !envMembers.has(member)) {
139
+ unsupportedExtras.add(member ?? parent.getText());
140
+ }
141
+ }
142
+ }
143
+ } else if (secondNameNode && Node.isObjectBindingPattern(secondNameNode)) {
144
+ for (const element of secondNameNode.getElements()) {
145
+ const bindingName = element.getNameNode();
146
+ const sourceName = propertyName(element.getPropertyNameNode() ?? bindingName);
147
+ if (!sourceName || !Node.isIdentifier(bindingName)) {
148
+ unsupportedExtras.add(element.getText());
149
+ continue;
150
+ }
151
+ if (element.getDotDotDotToken()) {
152
+ unsupportedExtras.add(element.getText());
153
+ continue;
154
+ }
155
+ const references = referencesWithin(body, bindingName);
156
+ if (sourceName === "props") {
157
+ propsLine ??= callback.getSourceFile().getLineAndColumnAtPos(element.getStart()).line;
158
+ for (const reference of references) {
159
+ draftReplacements.push({
160
+ start: reference.getStart(),
161
+ end: reference.getEnd(),
162
+ text: "props"
163
+ });
164
+ }
165
+ continue;
166
+ }
167
+ if (!envMembers.has(sourceName)) {
168
+ unsupportedExtras.add(sourceName);
169
+ continue;
170
+ }
171
+ if (references.length) usesEnv = true;
172
+ for (const reference of references) {
173
+ normalizedReplacements.push({
174
+ start: reference.getStart(),
175
+ end: reference.getEnd(),
176
+ text: `env.${sourceName}`
177
+ });
178
+ draftReplacements.push({
179
+ start: reference.getStart(),
180
+ end: reference.getEnd(),
181
+ text: `env.${sourceName}`
182
+ });
183
+ }
184
+ }
185
+ } else if (secondNameNode) {
186
+ unsupportedExtras.add(secondNameNode.getText());
187
+ }
188
+ const normalizedBody = firstNameNode && !Node.isIdentifier(firstNameNode) ? null : renderNode(body, normalizedReplacements);
189
+ const draftBody = firstNameNode && !Node.isIdentifier(firstNameNode) ? null : renderNode(body, draftReplacements);
190
+ let objectReturn = null;
191
+ const unwrappedBody = Node.isExpression(body) ? unwrapExpression(body) : body;
192
+ if (Node.isExpression(body) && Node.isObjectLiteralExpression(unwrappedBody)) {
193
+ objectReturn = renderObjectReturn(body, normalizedReplacements);
194
+ } else if (Node.isBlock(body)) {
195
+ const statements = body.getStatements();
196
+ if (statements.length === 1 && Node.isReturnStatement(statements[0])) {
197
+ const returned = statements[0].getExpression();
198
+ if (returned) {
199
+ const unwrapped = unwrapExpression(returned);
200
+ if (Node.isObjectLiteralExpression(unwrapped)) {
201
+ objectReturn = renderObjectReturn(returned, normalizedReplacements);
202
+ }
203
+ }
204
+ }
205
+ }
206
+ return {
207
+ callback,
208
+ firstName,
209
+ rendered: renderNode(callback, renderedReplacements),
210
+ normalizedBody,
211
+ objectReturn,
212
+ usesEnv,
213
+ propsLine,
214
+ draftBody,
215
+ unsupportedExtras: [...unsupportedExtras].sort()
216
+ };
217
+ }
218
+ function styledImport(sourceFile) {
219
+ for (const declaration of sourceFile.getImportDeclarations()) {
220
+ const module = declaration.getModuleSpecifierValue();
221
+ if (module !== "tamagui" && module !== "@tamagui/core") continue;
222
+ if (declaration.getNamedImports().some((specifier) => {
223
+ const localName = specifier.getAliasNode()?.getText() ?? specifier.getName();
224
+ return specifier.getName() === "styled" && localName === "styled";
225
+ })) {
226
+ return declaration;
227
+ }
228
+ }
229
+ return null;
230
+ }
231
+ function typeReference(sourceFile, declaration, typeName) {
232
+ const module = declaration.getModuleSpecifierValue();
233
+ for (const current of sourceFile.getImportDeclarations()) {
234
+ if (current.getModuleSpecifierValue() !== module) continue;
235
+ const existing = current.getNamedImports().find((specifier) => specifier.getName() === typeName);
236
+ if (existing) {
237
+ return {
238
+ localName: existing.getAliasNode()?.getText() ?? existing.getName(),
239
+ required: null
240
+ };
241
+ }
242
+ }
243
+ let localName = typeName;
244
+ if (sourceFile.getLocal(localName)) {
245
+ localName = `Tamagui${typeName}`;
246
+ let suffix = 2;
247
+ while (sourceFile.getLocal(localName)) localName = `Tamagui${typeName}${suffix++}`;
248
+ }
249
+ return {
250
+ localName,
251
+ required: {
252
+ module,
253
+ name: typeName,
254
+ localName
255
+ }
256
+ };
257
+ }
258
+ function callbackFromProperty(property) {
259
+ if (!Node.isPropertyAssignment(property)) return null;
260
+ const initializer = unwrapExpression(property.getInitializerOrThrow());
261
+ return Node.isArrowFunction(initializer) || Node.isFunctionExpression(initializer) ? initializer : null;
262
+ }
263
+ function commentsBefore(properties) {
264
+ const comments = /* @__PURE__ */ new Map();
265
+ for (const property of properties) {
266
+ for (const range of property.getLeadingCommentRanges()) {
267
+ comments.set(range.getPos(), range.getText());
268
+ }
269
+ }
270
+ return [...comments.entries()].sort((left, right) => left[0] - right[0]).map((entry) => entry[1]).join("\n");
271
+ }
272
+ function convertFunctionalVariants(config, label, write) {
273
+ const sites = [];
274
+ const requiredTypeImports = [];
275
+ const variantsProperty = config.getProperty("variants");
276
+ if (!Node.isPropertyAssignment(variantsProperty)) {
277
+ return {
278
+ sites,
279
+ requiredTypeImports
280
+ };
281
+ }
282
+ const variants = unwrapExpression(variantsProperty.getInitializerOrThrow());
283
+ if (!Node.isObjectLiteralExpression(variants)) return {
284
+ sites,
285
+ requiredTypeImports
286
+ };
287
+ const sourceFile = config.getSourceFile();
288
+ const importDeclaration = styledImport(sourceFile);
289
+ for (const variant of variants.getProperties()) {
290
+ if (!Node.isPropertyAssignment(variant)) continue;
291
+ const variantName = propertyName(variant.getNameNode());
292
+ if (!variantName) continue;
293
+ const initializer = unwrapExpression(variant.getInitializerOrThrow());
294
+ if (!Node.isObjectLiteralExpression(initializer)) continue;
295
+ const functional = initializer.getProperties().flatMap((property) => {
296
+ if (!("getNameNode" in property)) return [];
297
+ const name = propertyName(property.getNameNode());
298
+ return name && (name === "..." || name.startsWith("...") || name.startsWith(":")) ? [{
299
+ name,
300
+ property
301
+ }] : [];
302
+ });
303
+ if (!functional.length) continue;
304
+ const flags = [];
305
+ const notes = [];
306
+ const line = sourceFile.getLineAndColumnAtPos(functional[0].property.getStart()).line;
307
+ const before = variant.getText();
308
+ const exact = initializer.getProperties().filter((property) => !functional.some((entry) => entry.property === property));
309
+ const callbacks = functional.map((entry) => callbackFromProperty(entry.property));
310
+ const analyses = callbacks.map((callback) => callback ? callbackAnalysis(callback) : null);
311
+ let after = before;
312
+ let draft = null;
313
+ let dynamicText = null;
314
+ let requiredImport = null;
315
+ if (exact.length) {
316
+ flags.push({
317
+ code: "functional-variant-mixed",
318
+ detail: `variant "${variantName}" combines exact branches with a function key; v3 has no mixed variant form`
319
+ });
320
+ }
321
+ if (functional.some((entry) => entry.name === "...")) {
322
+ flags.push({
323
+ code: "functional-variant-catch-all",
324
+ detail: `choose the value type and replace this catch-all with styled.dynamic<YourValue>(...); unknown would erase the prop contract`
325
+ });
326
+ }
327
+ if (callbacks.some((callback) => callback === null)) {
328
+ flags.push({
329
+ code: "functional-variant-unsupported",
330
+ detail: `variant "${variantName}" uses a function key whose value is not an inline arrow or function expression`
331
+ });
332
+ }
333
+ if (callbacks.some((callback) => callback && (callback.getParameters().length > 2 || callback.isAsync() || Node.isFunctionExpression(callback) && callback.isGenerator()))) {
334
+ flags.push({
335
+ code: "functional-variant-unsupported",
336
+ detail: `variant "${variantName}" uses an async, generator, or three-parameter callback`
337
+ });
338
+ }
339
+ if (analyses.some((analysis) => analysis?.firstName === null)) {
340
+ flags.push({
341
+ code: "functional-variant-unsupported",
342
+ detail: `variant "${variantName}" destructures its value parameter; migrate that callback by hand`
343
+ });
344
+ }
345
+ const unsupportedExtras = [...new Set(analyses.flatMap((analysis) => analysis?.unsupportedExtras ?? []))];
346
+ if (unsupportedExtras.length) {
347
+ flags.push({
348
+ code: "functional-variant-unsupported-extras",
349
+ detail: `v3 env has no ${unsupportedExtras.map((name) => `"${name}"`).join(", ")} member`
350
+ });
351
+ }
352
+ const propsAnalysis = analyses.find((analysis) => analysis?.propsLine != null);
353
+ if (propsAnalysis) {
354
+ const analysis = propsAnalysis;
355
+ const valueName = analysis.firstName ?? "value";
356
+ const propAccess = /^[A-Za-z_$][\w$]*$/.test(variantName) ? `props.${variantName}` : `props[${JSON.stringify(variantName)}]`;
357
+ const body = analysis.draftBody;
358
+ if (body) {
359
+ const statements = Node.isBlock(analysis.callback.getBody()) ? body.slice(1, -1).trim() : `return ${body}`;
360
+ draft = `${variantName}: styled.dynamic<${spreadTypes.get(functional[0].name) ?? typeKeys.get(functional[0].name) ?? "YourValue"}>()
361
+
362
+ .resolve((props, env) => {
363
+ const ${valueName} = ${propAccess}
364
+ ${statements.split("\n").map((statement) => ` ${statement}`).join("\n")}
365
+ })`;
366
+ }
367
+ flags.push({
368
+ code: "functional-variant-needs-resolve",
369
+ detail: `line ${analysis.propsLine} reads sibling props; declare the consumed prop with styled.dynamic<T>() and adapt the generated .resolve draft`
370
+ });
371
+ }
372
+ const allTypeKeys = functional.every((entry) => typeKeys.has(entry.name));
373
+ const oneSpread = functional.length === 1 && spreadTypes.has(functional[0].name);
374
+ if (new Set(functional.map((entry) => entry.name)).size !== functional.length) {
375
+ flags.push({
376
+ code: "functional-variant-unsupported",
377
+ detail: `variant "${variantName}" repeats a function key`
378
+ });
379
+ }
380
+ if (!functional.some((entry) => entry.name === "...") && !allTypeKeys && !oneSpread) {
381
+ flags.push({
382
+ code: "functional-variant-unsupported",
383
+ detail: `variant "${variantName}" uses unsupported functional keys ${functional.map((entry) => `"${entry.name}"`).join(", ")}`
384
+ });
385
+ }
386
+ if (!flags.length && oneSpread) {
387
+ if (!importDeclaration) {
388
+ flags.push({
389
+ code: "functional-variant-styled-import",
390
+ detail: `the file does not import styled directly from "tamagui" or "@tamagui/core", so the token type source is not provable`
391
+ });
392
+ } else {
393
+ const typeName = spreadTypes.get(functional[0].name);
394
+ const reference = typeReference(sourceFile, importDeclaration, typeName);
395
+ requiredImport = reference.required;
396
+ dynamicText = `styled.dynamic<${reference.localName}>(${analyses[0].rendered})`;
397
+ notes.push(`uses ${reference.localName} from ${importDeclaration.getModuleSpecifierValue()}`);
398
+ }
399
+ } else if (!flags.length && allTypeKeys) {
400
+ const present = new Set(functional.map((entry) => typeKeys.get(entry.name)));
401
+ const union = typeOrder.filter((type) => present.has(type)).join(" | ");
402
+ if (functional.length === 1) {
403
+ dynamicText = `styled.dynamic<${union}>(${analyses[0].rendered})`;
404
+ } else {
405
+ const normalizedBodies = analyses.map((analysis) => analysis.normalizedBody);
406
+ const sameBody = normalizedBodies.every((body) => body === normalizedBodies[0]);
407
+ const envParameter = analyses.some((analysis) => analysis.usesEnv) ? ", env" : "";
408
+ if (sameBody) {
409
+ dynamicText = `styled.dynamic<${union}>((value${envParameter}) => ${normalizedBodies[0]})`;
410
+ } else if (analyses.every((analysis) => analysis.objectReturn !== null)) {
411
+ const byType = new Map(functional.map((entry, index) => [typeKeys.get(entry.name), analyses[index].objectReturn]));
412
+ const ordered = typeOrder.filter((type) => byType.has(type));
413
+ const branches = ordered.map((type, index) => index === ordered.length - 1 ? `return ${byType.get(type)}` : `if (typeof value === '${type}') return ${byType.get(type)}`);
414
+ dynamicText = `styled.dynamic<${union}>((value${envParameter}) => {
415
+ ${branches.map((branch) => ` ${branch}`).join("\n")}
416
+ })`;
417
+ } else {
418
+ flags.push({
419
+ code: "functional-variant-type-bodies",
420
+ detail: `variant "${variantName}" has different type-key bodies; automatic typeof branches require each body to be one object-literal return`
421
+ });
422
+ }
423
+ }
424
+ }
425
+ if (dynamicText && !flags.length) {
426
+ const comments = commentsBefore(functional.map((entry) => entry.property));
427
+ const replacement = comments ? `${comments}
428
+ ${dynamicText}` : dynamicText;
429
+ after = `${variant.getNameNode().getText()}: ${replacement}`;
430
+ if (requiredImport) requiredTypeImports.push(requiredImport);
431
+ if (write) variant.setInitializer(replacement);
432
+ }
433
+ sites.push({
434
+ label: `${label} variants.${variantName}`,
435
+ line,
436
+ before,
437
+ after,
438
+ converted: flags.length === 0,
439
+ flags,
440
+ draft,
441
+ notes
442
+ });
443
+ }
444
+ return {
445
+ sites,
446
+ requiredTypeImports
447
+ };
448
+ }
449
+ function addFunctionalVariantTypeImports(sourceFile, imports) {
450
+ const seen = /* @__PURE__ */ new Set();
451
+ for (const required of imports) {
452
+ const key = `${required.module}:${required.name}:${required.localName}`;
453
+ if (seen.has(key)) continue;
454
+ seen.add(key);
455
+ const declaration = sourceFile.getImportDeclarations().find((current) => current.getModuleSpecifierValue() === required.module);
456
+ if (!declaration) continue;
457
+ if (sourceFile.getImportDeclarations().some((current) => current.getModuleSpecifierValue() === required.module && current.getNamedImports().some((specifier) => specifier.getName() === required.name))) {
458
+ continue;
459
+ }
460
+ declaration.addNamedImport({
461
+ name: required.name,
462
+ alias: required.localName === required.name ? void 0 : required.localName,
463
+ isTypeOnly: !declaration.isTypeOnly()
464
+ });
465
+ }
466
+ }
467
+
468
+ export { addFunctionalVariantTypeImports, convertFunctionalVariants };
469
+ //# sourceMappingURL=functionalVariants.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"functionalVariants.js","names":[],"sources":["functionalVariants.js"],"sourcesContent":["import {\n Node,\n SyntaxKind\n} from \"ts-morph\";\nimport { unwrapExpression } from \"./expressions\";\nconst spreadTypes = /* @__PURE__ */ new Map([\n [\"...size\", \"SizeTokens\"],\n [\"...space\", \"SpaceTokens\"],\n [\"...color\", \"ColorTokens\"],\n [\"...radius\", \"RadiusTokens\"],\n [\"...fontSize\", \"FontSizeTokens\"],\n [\"...zIndex\", \"ZIndexTokens\"]\n]);\nconst typeKeys = /* @__PURE__ */ new Map([\n [\":number\", \"number\"],\n [\":string\", \"string\"],\n [\":boolean\", \"boolean\"]\n]);\nconst typeOrder = [\"number\", \"string\", \"boolean\"];\nconst envMembers = /* @__PURE__ */ new Set([\"tokens\", \"theme\", \"fonts\", \"font\", \"fontFamily\"]);\nfunction propertyName(node) {\n if (Node.isIdentifier(node) || Node.isPrivateIdentifier(node)) return node.getText();\n if (Node.isStringLiteral(node) || Node.isNumericLiteral(node)) {\n return node.getLiteralText();\n }\n return null;\n}\nfunction renderNode(node, replacements) {\n const start = node.getStart();\n const end = node.getEnd();\n const selected = [];\n for (const replacement of [...replacements].sort(\n (left, right) => right.end - right.start - (left.end - left.start)\n )) {\n if (replacement.start < start || replacement.end > end) continue;\n if (selected.some(\n (current) => replacement.start < current.end && replacement.end > current.start\n )) {\n continue;\n }\n selected.push(replacement);\n }\n let text = node.getText();\n for (const replacement of selected.sort((left, right) => right.start - left.start)) {\n const relativeStart = replacement.start - start;\n const relativeEnd = replacement.end - start;\n text = `${text.slice(0, relativeStart)}${replacement.text}${text.slice(relativeEnd)}`;\n }\n return text;\n}\nfunction referencesWithin(node, definition) {\n return definition.findReferencesAsNodes().filter(\n (reference) => reference.getStart() >= node.getStart() && reference.getEnd() <= node.getEnd()\n );\n}\nfunction renderObjectReturn(expression, replacements) {\n let current = expression;\n while (Node.isParenthesizedExpression(current)) current = current.getExpression();\n return renderNode(\n Node.isAsExpression(current) || Node.isTypeAssertion(current) ? expression : unwrapExpression(expression),\n replacements\n );\n}\nfunction callbackAnalysis(callback) {\n const body = callback.getBody();\n const parameters = callback.getParameters();\n const firstNameNode = parameters[0]?.getNameNode();\n const firstName = Node.isIdentifier(firstNameNode) ? firstNameNode.getText() : null;\n const secondNameNode = parameters[1]?.getNameNode();\n const renderedReplacements = [];\n const normalizedReplacements = [];\n const draftReplacements = [];\n const unsupportedExtras = /* @__PURE__ */ new Set();\n let propsLine = null;\n let usesEnv = false;\n if (firstNameNode && Node.isIdentifier(firstNameNode)) {\n for (const reference of referencesWithin(body, firstNameNode)) {\n normalizedReplacements.push({\n start: reference.getStart(),\n end: reference.getEnd(),\n text: \"value\"\n });\n }\n }\n if (secondNameNode && Node.isIdentifier(secondNameNode)) {\n const references = referencesWithin(body, secondNameNode);\n usesEnv = references.length > 0;\n const otherSameName = body.getDescendantsOfKind(SyntaxKind.Identifier).some(\n (identifier) => identifier.getText() === secondNameNode.getText() && !references.some(\n (reference) => reference.getStart() === identifier.getStart() && reference.getEnd() === identifier.getEnd()\n )\n );\n const envNameExists = body.getDescendantsOfKind(SyntaxKind.Identifier).some((identifier) => identifier.getText() === \"env\");\n if (secondNameNode.getText() !== \"env\" && !otherSameName && !envNameExists) {\n renderedReplacements.push({\n start: secondNameNode.getStart(),\n end: secondNameNode.getEnd(),\n text: \"env\"\n });\n for (const reference of references) {\n renderedReplacements.push({\n start: reference.getStart(),\n end: reference.getEnd(),\n text: \"env\"\n });\n }\n }\n for (const reference of references) {\n normalizedReplacements.push({\n start: reference.getStart(),\n end: reference.getEnd(),\n text: \"env\"\n });\n draftReplacements.push({\n start: reference.getStart(),\n end: reference.getEnd(),\n text: \"env\"\n });\n const parent = reference.getParent();\n if (Node.isPropertyAccessExpression(parent) && parent.getExpression().getStart() === reference.getStart()) {\n const member = parent.getName();\n if (member === \"props\") {\n propsLine ??= callback.getSourceFile().getLineAndColumnAtPos(parent.getStart()).line;\n draftReplacements.push({\n start: parent.getStart(),\n end: parent.getEnd(),\n text: \"props\"\n });\n } else if (!envMembers.has(member)) {\n unsupportedExtras.add(member);\n }\n }\n if (Node.isElementAccessExpression(parent) && parent.getExpression().getStart() === reference.getStart()) {\n const argument = parent.getArgumentExpression();\n const member = argument && Node.isStringLiteral(argument) ? argument.getLiteralValue() : null;\n if (member === \"props\") {\n propsLine ??= callback.getSourceFile().getLineAndColumnAtPos(parent.getStart()).line;\n draftReplacements.push({\n start: parent.getStart(),\n end: parent.getEnd(),\n text: \"props\"\n });\n } else if (member === null || !envMembers.has(member)) {\n unsupportedExtras.add(member ?? parent.getText());\n }\n }\n }\n } else if (secondNameNode && Node.isObjectBindingPattern(secondNameNode)) {\n for (const element of secondNameNode.getElements()) {\n const bindingName = element.getNameNode();\n const sourceName = propertyName(element.getPropertyNameNode() ?? bindingName);\n if (!sourceName || !Node.isIdentifier(bindingName)) {\n unsupportedExtras.add(element.getText());\n continue;\n }\n if (element.getDotDotDotToken()) {\n unsupportedExtras.add(element.getText());\n continue;\n }\n const references = referencesWithin(body, bindingName);\n if (sourceName === \"props\") {\n propsLine ??= callback.getSourceFile().getLineAndColumnAtPos(element.getStart()).line;\n for (const reference of references) {\n draftReplacements.push({\n start: reference.getStart(),\n end: reference.getEnd(),\n text: \"props\"\n });\n }\n continue;\n }\n if (!envMembers.has(sourceName)) {\n unsupportedExtras.add(sourceName);\n continue;\n }\n if (references.length) usesEnv = true;\n for (const reference of references) {\n normalizedReplacements.push({\n start: reference.getStart(),\n end: reference.getEnd(),\n text: `env.${sourceName}`\n });\n draftReplacements.push({\n start: reference.getStart(),\n end: reference.getEnd(),\n text: `env.${sourceName}`\n });\n }\n }\n } else if (secondNameNode) {\n unsupportedExtras.add(secondNameNode.getText());\n }\n const normalizedBody = firstNameNode && !Node.isIdentifier(firstNameNode) ? null : renderNode(body, normalizedReplacements);\n const draftBody = firstNameNode && !Node.isIdentifier(firstNameNode) ? null : renderNode(body, draftReplacements);\n let objectReturn = null;\n const unwrappedBody = Node.isExpression(body) ? unwrapExpression(body) : body;\n if (Node.isExpression(body) && Node.isObjectLiteralExpression(unwrappedBody)) {\n objectReturn = renderObjectReturn(body, normalizedReplacements);\n } else if (Node.isBlock(body)) {\n const statements = body.getStatements();\n if (statements.length === 1 && Node.isReturnStatement(statements[0])) {\n const returned = statements[0].getExpression();\n if (returned) {\n const unwrapped = unwrapExpression(returned);\n if (Node.isObjectLiteralExpression(unwrapped)) {\n objectReturn = renderObjectReturn(returned, normalizedReplacements);\n }\n }\n }\n }\n return {\n callback,\n firstName,\n rendered: renderNode(callback, renderedReplacements),\n normalizedBody,\n objectReturn,\n usesEnv,\n propsLine,\n draftBody,\n unsupportedExtras: [...unsupportedExtras].sort()\n };\n}\nfunction styledImport(sourceFile) {\n for (const declaration of sourceFile.getImportDeclarations()) {\n const module = declaration.getModuleSpecifierValue();\n if (module !== \"tamagui\" && module !== \"@tamagui/core\") continue;\n if (declaration.getNamedImports().some((specifier) => {\n const localName = specifier.getAliasNode()?.getText() ?? specifier.getName();\n return specifier.getName() === \"styled\" && localName === \"styled\";\n })) {\n return declaration;\n }\n }\n return null;\n}\nfunction typeReference(sourceFile, declaration, typeName) {\n const module = declaration.getModuleSpecifierValue();\n for (const current of sourceFile.getImportDeclarations()) {\n if (current.getModuleSpecifierValue() !== module) continue;\n const existing = current.getNamedImports().find((specifier) => specifier.getName() === typeName);\n if (existing) {\n return {\n localName: existing.getAliasNode()?.getText() ?? existing.getName(),\n required: null\n };\n }\n }\n let localName = typeName;\n if (sourceFile.getLocal(localName)) {\n localName = `Tamagui${typeName}`;\n let suffix = 2;\n while (sourceFile.getLocal(localName)) localName = `Tamagui${typeName}${suffix++}`;\n }\n return { localName, required: { module, name: typeName, localName } };\n}\nfunction callbackFromProperty(property) {\n if (!Node.isPropertyAssignment(property)) return null;\n const initializer = unwrapExpression(property.getInitializerOrThrow());\n return Node.isArrowFunction(initializer) || Node.isFunctionExpression(initializer) ? initializer : null;\n}\nfunction commentsBefore(properties) {\n const comments = /* @__PURE__ */ new Map();\n for (const property of properties) {\n for (const range of property.getLeadingCommentRanges()) {\n comments.set(range.getPos(), range.getText());\n }\n }\n return [...comments.entries()].sort((left, right) => left[0] - right[0]).map((entry) => entry[1]).join(\"\\n\");\n}\nfunction convertFunctionalVariants(config, label, write) {\n const sites = [];\n const requiredTypeImports = [];\n const variantsProperty = config.getProperty(\"variants\");\n if (!Node.isPropertyAssignment(variantsProperty)) {\n return { sites, requiredTypeImports };\n }\n const variants = unwrapExpression(variantsProperty.getInitializerOrThrow());\n if (!Node.isObjectLiteralExpression(variants)) return { sites, requiredTypeImports };\n const sourceFile = config.getSourceFile();\n const importDeclaration = styledImport(sourceFile);\n for (const variant of variants.getProperties()) {\n if (!Node.isPropertyAssignment(variant)) continue;\n const variantName = propertyName(variant.getNameNode());\n if (!variantName) continue;\n const initializer = unwrapExpression(variant.getInitializerOrThrow());\n if (!Node.isObjectLiteralExpression(initializer)) continue;\n const functional = initializer.getProperties().flatMap((property) => {\n if (!(\"getNameNode\" in property)) return [];\n const name = propertyName(property.getNameNode());\n return name && (name === \"...\" || name.startsWith(\"...\") || name.startsWith(\":\")) ? [{ name, property }] : [];\n });\n if (!functional.length) continue;\n const flags = [];\n const notes = [];\n const line = sourceFile.getLineAndColumnAtPos(functional[0].property.getStart()).line;\n const before = variant.getText();\n const exact = initializer.getProperties().filter((property) => !functional.some((entry) => entry.property === property));\n const callbacks = functional.map((entry) => callbackFromProperty(entry.property));\n const analyses = callbacks.map(\n (callback) => callback ? callbackAnalysis(callback) : null\n );\n let after = before;\n let draft = null;\n let dynamicText = null;\n let requiredImport = null;\n if (exact.length) {\n flags.push({\n code: \"functional-variant-mixed\",\n detail: `variant \"${variantName}\" combines exact branches with a function key; v3 has no mixed variant form`\n });\n }\n if (functional.some((entry) => entry.name === \"...\")) {\n flags.push({\n code: \"functional-variant-catch-all\",\n detail: `choose the value type and replace this catch-all with styled.dynamic<YourValue>(...); unknown would erase the prop contract`\n });\n }\n if (callbacks.some((callback) => callback === null)) {\n flags.push({\n code: \"functional-variant-unsupported\",\n detail: `variant \"${variantName}\" uses a function key whose value is not an inline arrow or function expression`\n });\n }\n if (callbacks.some(\n (callback) => callback && (callback.getParameters().length > 2 || callback.isAsync() || Node.isFunctionExpression(callback) && callback.isGenerator())\n )) {\n flags.push({\n code: \"functional-variant-unsupported\",\n detail: `variant \"${variantName}\" uses an async, generator, or three-parameter callback`\n });\n }\n if (analyses.some((analysis) => analysis?.firstName === null)) {\n flags.push({\n code: \"functional-variant-unsupported\",\n detail: `variant \"${variantName}\" destructures its value parameter; migrate that callback by hand`\n });\n }\n const unsupportedExtras = [\n ...new Set(analyses.flatMap((analysis) => analysis?.unsupportedExtras ?? []))\n ];\n if (unsupportedExtras.length) {\n flags.push({\n code: \"functional-variant-unsupported-extras\",\n detail: `v3 env has no ${unsupportedExtras.map((name) => `\"${name}\"`).join(\", \")} member`\n });\n }\n const propsAnalysis = analyses.find((analysis) => analysis?.propsLine != null);\n if (propsAnalysis) {\n const analysis = propsAnalysis;\n const valueName = analysis.firstName ?? \"value\";\n const propAccess = /^[A-Za-z_$][\\w$]*$/.test(variantName) ? `props.${variantName}` : `props[${JSON.stringify(variantName)}]`;\n const body = analysis.draftBody;\n if (body) {\n const statements = Node.isBlock(analysis.callback.getBody()) ? body.slice(1, -1).trim() : `return ${body}`;\n draft = `${variantName}: styled.dynamic<${spreadTypes.get(functional[0].name) ?? typeKeys.get(functional[0].name) ?? \"YourValue\"}>()\n\n.resolve((props, env) => {\n const ${valueName} = ${propAccess}\n${statements.split(\"\\n\").map((statement) => ` ${statement}`).join(\"\\n\")}\n})`;\n }\n flags.push({\n code: \"functional-variant-needs-resolve\",\n detail: `line ${analysis.propsLine} reads sibling props; declare the consumed prop with styled.dynamic<T>() and adapt the generated .resolve draft`\n });\n }\n const allTypeKeys = functional.every((entry) => typeKeys.has(entry.name));\n const oneSpread = functional.length === 1 && spreadTypes.has(functional[0].name);\n if (new Set(functional.map((entry) => entry.name)).size !== functional.length) {\n flags.push({\n code: \"functional-variant-unsupported\",\n detail: `variant \"${variantName}\" repeats a function key`\n });\n }\n if (!functional.some((entry) => entry.name === \"...\") && !allTypeKeys && !oneSpread) {\n flags.push({\n code: \"functional-variant-unsupported\",\n detail: `variant \"${variantName}\" uses unsupported functional keys ${functional.map((entry) => `\"${entry.name}\"`).join(\", \")}`\n });\n }\n if (!flags.length && oneSpread) {\n if (!importDeclaration) {\n flags.push({\n code: \"functional-variant-styled-import\",\n detail: `the file does not import styled directly from \"tamagui\" or \"@tamagui/core\", so the token type source is not provable`\n });\n } else {\n const typeName = spreadTypes.get(functional[0].name);\n const reference = typeReference(sourceFile, importDeclaration, typeName);\n requiredImport = reference.required;\n dynamicText = `styled.dynamic<${reference.localName}>(${analyses[0].rendered})`;\n notes.push(\n `uses ${reference.localName} from ${importDeclaration.getModuleSpecifierValue()}`\n );\n }\n } else if (!flags.length && allTypeKeys) {\n const present = new Set(functional.map((entry) => typeKeys.get(entry.name)));\n const union = typeOrder.filter((type) => present.has(type)).join(\" | \");\n if (functional.length === 1) {\n dynamicText = `styled.dynamic<${union}>(${analyses[0].rendered})`;\n } else {\n const normalizedBodies = analyses.map((analysis) => analysis.normalizedBody);\n const sameBody = normalizedBodies.every((body) => body === normalizedBodies[0]);\n const envParameter = analyses.some((analysis) => analysis.usesEnv) ? \", env\" : \"\";\n if (sameBody) {\n dynamicText = `styled.dynamic<${union}>((value${envParameter}) => ${normalizedBodies[0]})`;\n } else if (analyses.every((analysis) => analysis.objectReturn !== null)) {\n const byType = new Map(\n functional.map((entry, index) => [\n typeKeys.get(entry.name),\n analyses[index].objectReturn\n ])\n );\n const ordered = typeOrder.filter((type) => byType.has(type));\n const branches = ordered.map(\n (type, index) => index === ordered.length - 1 ? `return ${byType.get(type)}` : `if (typeof value === '${type}') return ${byType.get(type)}`\n );\n dynamicText = `styled.dynamic<${union}>((value${envParameter}) => {\n${branches.map((branch) => ` ${branch}`).join(\"\\n\")}\n})`;\n } else {\n flags.push({\n code: \"functional-variant-type-bodies\",\n detail: `variant \"${variantName}\" has different type-key bodies; automatic typeof branches require each body to be one object-literal return`\n });\n }\n }\n }\n if (dynamicText && !flags.length) {\n const comments = commentsBefore(functional.map((entry) => entry.property));\n const replacement = comments ? `${comments}\n${dynamicText}` : dynamicText;\n after = `${variant.getNameNode().getText()}: ${replacement}`;\n if (requiredImport) requiredTypeImports.push(requiredImport);\n if (write) variant.setInitializer(replacement);\n }\n sites.push({\n label: `${label} variants.${variantName}`,\n line,\n before,\n after,\n converted: flags.length === 0,\n flags,\n draft,\n notes\n });\n }\n return { sites, requiredTypeImports };\n}\nfunction addFunctionalVariantTypeImports(sourceFile, imports) {\n const seen = /* @__PURE__ */ new Set();\n for (const required of imports) {\n const key = `${required.module}:${required.name}:${required.localName}`;\n if (seen.has(key)) continue;\n seen.add(key);\n const declaration = sourceFile.getImportDeclarations().find((current) => current.getModuleSpecifierValue() === required.module);\n if (!declaration) continue;\n if (sourceFile.getImportDeclarations().some(\n (current) => current.getModuleSpecifierValue() === required.module && current.getNamedImports().some((specifier) => specifier.getName() === required.name)\n )) {\n continue;\n }\n declaration.addNamedImport({\n name: required.name,\n alias: required.localName === required.name ? void 0 : required.localName,\n isTypeOnly: !declaration.isTypeOnly()\n });\n }\n}\nexport {\n addFunctionalVariantTypeImports,\n convertFunctionalVariants\n};\n//# sourceMappingURL=functionalVariants.js.map\n"],"mappings":"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"}
package/dist/index.mjs CHANGED
@@ -7,6 +7,7 @@ import { ModuleKind, ModuleResolutionKind, Node, Project, ScriptTarget, SyntaxKi
7
7
  import { planContainers } from "./containers.mjs";
8
8
  import { convertJsxSite, convertStyleObject } from "./convert.mjs";
9
9
  import { compact, unwrapExpression } from "./expressions.mjs";
10
+ import { addFunctionalVariantTypeImports, convertFunctionalVariants } from "./functionalVariants.mjs";
10
11
  import { codemodMediaNames, createModifierRegistry, grammarPlatformNames } from "./grammar.mjs";
11
12
  import { createProvenance } from "./provenance.mjs";
12
13
  import { renderReport } from "./report.mjs";
@@ -151,6 +152,19 @@ function variantSites(config, label, registry, containers, targets, host, write2
151
152
  if (!Node.isPropertyAssignment(variant)) continue;
152
153
  const variantName = compact(variant.getNameNode().getText());
153
154
  const branches = unwrapExpression(variant.getInitializerOrThrow());
155
+ if (Node.isCallExpression(branches)) {
156
+ const callee = branches.getExpression();
157
+ if (Node.isPropertyAccessExpression(callee) && callee.getName() === "dynamic") {
158
+ const body = branches.getArguments()[0];
159
+ if (body && Node.isExpression(body)) {
160
+ for (const style of variantStyleObjects(body)) {
161
+ const site = convertStyleObject(style, "styled", `${label} variants.${variantName}`, registry, containers, targets, host, write2);
162
+ if (site) sites.push(site);
163
+ }
164
+ }
165
+ }
166
+ continue;
167
+ }
154
168
  if (!Node.isObjectLiteralExpression(branches)) continue;
155
169
  for (const branch of branches.getProperties()) {
156
170
  if (!Node.isPropertyAssignment(branch)) continue;
@@ -183,6 +197,8 @@ function inspectFile(sourceFile, registry, provenance2, write2) {
183
197
  const containers = planContainers(sourceFile, registry);
184
198
  const targets = conversionTargets(sourceFile.getFilePath());
185
199
  const sites = [];
200
+ const functionalVariants = [];
201
+ const requiredTypeImports = [];
186
202
  const styledCalls = sourceFile.getDescendantsOfKind(SyntaxKind.CallExpression).filter((call) => provenance2.isTamaguiStyledCall(call)).sort((left, right) => right.getStart() - left.getStart());
187
203
  const jsxOpenings = [...sourceFile.getDescendantsOfKind(SyntaxKind.JsxOpeningElement), ...sourceFile.getDescendantsOfKind(SyntaxKind.JsxSelfClosingElement)].filter((opening) => provenance2.isTamaguiElement(opening)).sort((left, right) => right.getStart() - left.getStart());
188
204
  for (const opening of jsxOpenings) {
@@ -196,13 +212,19 @@ function inspectFile(sourceFile, registry, provenance2, write2) {
196
212
  if (!Node.isObjectLiteralExpression(config)) continue;
197
213
  const label = `styled(${compact(call.getArguments()[0]?.getText() ?? "unknown")}, \u2026)`;
198
214
  sites.push(...variantSites(config, label, registry, containers, targets, host, write2));
215
+ const functional = convertFunctionalVariants(config, label, write2);
216
+ functionalVariants.push(...functional.sites);
217
+ requiredTypeImports.push(...functional.requiredTypeImports);
199
218
  const site = convertStyleObject(config, "styled", label, registry, containers, targets, host, write2);
200
219
  if (site) sites.push(site);
201
220
  }
202
221
  sites.sort((left, right) => left.line - right.line || left.label.localeCompare(right.label));
222
+ functionalVariants.sort((left, right) => left.line - right.line || left.label.localeCompare(right.label));
223
+ if (write2) addFunctionalVariantTypeImports(sourceFile, requiredTypeImports);
203
224
  return {
204
225
  file: relative(projectRoot, sourceFile.getFilePath()),
205
- sites
226
+ sites,
227
+ functionalVariants
206
228
  };
207
229
  }
208
230
  const usage = `Converts Tamagui style syntax to V3 flat property values and reports what it cannot convert.
@@ -321,6 +343,6 @@ if (write) {
321
343
  }
322
344
  console.log(`wrote ${reportPath}`);
323
345
  if (write) console.log(`rewrote ${written} source files`);
324
- console.log(`${summary.sites} sites: ${summary.clean - summary.waiting} clean, ${summary.needsRelocation} need relocation, ${summary.unknownHost} unknown host, ${summary.ineligible} ineligible, ${summary.waiting} waiting on runtime support, ${summary.flagged} syntax-flagged; ${summary.ignoredFiles} source files ignored`);
346
+ console.log(`${summary.sites} style sites: ${summary.clean - summary.waiting} clean, ${summary.needsRelocation} need relocation, ${summary.unknownHost} unknown host, ${summary.ineligible} ineligible, ${summary.waiting} waiting on runtime support, ${summary.flagged} syntax-flagged; ${summary.functionalVariantSites} functional variants: ${summary.functionalVariantConverted} automatic, ${summary.functionalVariantFlagged} flagged; ${summary.ignoredFiles} source files ignored`);
325
347
 
326
348
  //# sourceMappingURL=index.mjs.map