@yahoo/uds 3.104.0 → 3.105.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/dist/automated-config/dist/generated/autoVariants.cjs +57 -0
  2. package/dist/automated-config/dist/generated/autoVariants.d.cts +57 -57
  3. package/dist/automated-config/dist/generated/autoVariants.d.ts +57 -57
  4. package/dist/automated-config/dist/generated/autoVariants.js +57 -0
  5. package/dist/automated-config/dist/utils/generateDefaultClassName.cjs +18 -0
  6. package/dist/automated-config/dist/utils/generateDefaultClassName.d.cts +14 -0
  7. package/dist/automated-config/dist/utils/generateDefaultClassName.d.ts +14 -0
  8. package/dist/automated-config/dist/utils/generateDefaultClassName.js +17 -0
  9. package/dist/automated-config/dist/utils/index.cjs +3 -6
  10. package/dist/automated-config/dist/utils/index.d.cts +2 -2
  11. package/dist/automated-config/dist/utils/index.d.ts +2 -2
  12. package/dist/automated-config/dist/utils/index.js +3 -5
  13. package/dist/cli/runner.cjs +21 -5
  14. package/dist/cli/runner.js +21 -5
  15. package/dist/components/client/Button.cjs +9 -9
  16. package/dist/components/client/Button.js +2 -2
  17. package/dist/components/client/IconButton.cjs +8 -8
  18. package/dist/components/client/IconButton.js +2 -2
  19. package/dist/components/client/SpringMotionConfig.cjs +4 -4
  20. package/dist/components/client/SpringMotionConfig.js +5 -5
  21. package/dist/components/client/buttonConstants.cjs +10 -0
  22. package/dist/components/client/buttonConstants.d.cts +9 -0
  23. package/dist/components/client/buttonConstants.d.ts +9 -0
  24. package/dist/components/client/buttonConstants.js +8 -0
  25. package/dist/index.cjs +2 -1
  26. package/dist/index.d.cts +2 -1
  27. package/dist/index.d.ts +2 -1
  28. package/dist/index.js +2 -1
  29. package/dist/motion-tokens/dist/index.cjs +11 -0
  30. package/dist/motion-tokens/dist/index.d.cts +5 -1
  31. package/dist/motion-tokens/dist/index.d.ts +5 -1
  32. package/dist/motion-tokens/dist/index.js +11 -1
  33. package/dist/styles/styler.d.cts +67 -67
  34. package/dist/styles/styler.d.ts +67 -67
  35. package/dist/styles/variants.d.cts +57 -0
  36. package/dist/styles/variants.d.ts +57 -0
  37. package/dist/tailwind/dist/commands/generateComponentData.cjs +65 -0
  38. package/dist/tailwind/dist/commands/generateComponentData.d.ts +3 -0
  39. package/dist/tailwind/dist/commands/generateComponentData.js +64 -0
  40. package/dist/tailwind/dist/commands/generatePurgeCSSData.cjs +1 -1
  41. package/dist/tailwind/dist/commands/generatePurgeCSSData.js +1 -1
  42. package/dist/tailwind/dist/commands/purge.cjs +41 -11
  43. package/dist/tailwind/dist/commands/purge.d.ts +2 -1
  44. package/dist/tailwind/dist/commands/purge.js +41 -11
  45. package/dist/tailwind/dist/index.d.ts +1 -0
  46. package/dist/tailwind/dist/{utils → purger/legacy}/purgeCSS.cjs +7 -7
  47. package/dist/tailwind/dist/{utils → purger/legacy}/purgeCSS.js +6 -6
  48. package/dist/tailwind/dist/purger/optimized/ast/expressions.cjs +193 -0
  49. package/dist/tailwind/dist/purger/optimized/ast/expressions.js +192 -0
  50. package/dist/tailwind/dist/purger/optimized/ast/jsx.cjs +20 -0
  51. package/dist/tailwind/dist/purger/optimized/ast/jsx.js +19 -0
  52. package/dist/tailwind/dist/purger/optimized/purge.cjs +69 -0
  53. package/dist/tailwind/dist/purger/optimized/purge.js +66 -0
  54. package/dist/tailwind/dist/purger/optimized/purgeFromCode.cjs +273 -0
  55. package/dist/tailwind/dist/purger/optimized/purgeFromCode.js +272 -0
  56. package/dist/tailwind/dist/purger/optimized/utils/componentAnalyzer.cjs +408 -0
  57. package/dist/tailwind/dist/purger/optimized/utils/componentAnalyzer.js +405 -0
  58. package/dist/tailwind/dist/purger/optimized/utils/files.cjs +27 -0
  59. package/dist/tailwind/dist/purger/optimized/utils/files.js +24 -0
  60. package/dist/tailwind/dist/purger/optimized/utils/safelist.cjs +64 -0
  61. package/dist/tailwind/dist/purger/optimized/utils/safelist.js +60 -0
  62. package/dist/tailwind/dist/tailwind/utils/getColorModeStyles.cjs +1 -0
  63. package/dist/tailwind/dist/tailwind/utils/getColorModeStyles.js +1 -0
  64. package/dist/tailwind/dist/utils/tsMorph.cjs +1 -1
  65. package/dist/tokens/automation/index.cjs +2 -1
  66. package/dist/tokens/automation/index.d.cts +2 -1
  67. package/dist/tokens/automation/index.d.ts +2 -1
  68. package/dist/tokens/automation/index.js +2 -1
  69. package/dist/tokens/index.cjs +2 -1
  70. package/dist/tokens/index.d.cts +2 -1
  71. package/dist/tokens/index.d.ts +2 -1
  72. package/dist/tokens/index.js +2 -1
  73. package/dist/uds/generated/componentData.cjs +2110 -0
  74. package/dist/uds/generated/componentData.js +1720 -0
  75. package/dist/uds/generated/tailwindPurge.cjs +24 -24
  76. package/dist/uds/generated/tailwindPurge.js +24 -24
  77. package/package.json +1 -1
  78. /package/dist/tailwind/dist/{utils → purger/legacy}/purgeCSS.d.ts +0 -0
@@ -0,0 +1,408 @@
1
+ /*! © 2026 Yahoo, Inc. UDS v0.0.0-development */
2
+ const require_runtime = require('../../../../../_virtual/_rolldown/runtime.cjs');
3
+ const require_index = require('../../../../../motion-tokens/dist/index.cjs');
4
+ let node_path = require("node:path");
5
+ node_path = require_runtime.__toESM(node_path);
6
+ let ts_morph = require("ts-morph");
7
+
8
+ //#region ../tailwind/dist/purger/optimized/utils/componentAnalyzer.js
9
+ /*! © 2026 Yahoo, Inc. UDS Tailwind and Purger v0.0.0-development */
10
+ /**
11
+ * Known UDS component names (populated by scanning)
12
+ */
13
+ let knownComponents = null;
14
+ /**
15
+ * Map of component name -> file path
16
+ */
17
+ let componentPaths = null;
18
+ /**
19
+ * Scan src/components to build a map of all component files
20
+ */
21
+ async function scanComponentFiles(componentsDir) {
22
+ if (componentPaths) return componentPaths;
23
+ componentPaths = /* @__PURE__ */ new Map();
24
+ knownComponents = /* @__PURE__ */ new Set();
25
+ const glob = new Bun.Glob("**/*.tsx");
26
+ for await (const file of glob.scan({
27
+ cwd: componentsDir,
28
+ absolute: true
29
+ })) {
30
+ if (file.includes(".test.") || file.endsWith("index.tsx")) continue;
31
+ const fileName = node_path.default.basename(file, ".tsx");
32
+ if (/^[A-Z]/.test(fileName)) {
33
+ componentPaths.set(fileName, file);
34
+ knownComponents.add(fileName);
35
+ }
36
+ }
37
+ return componentPaths;
38
+ }
39
+ /**
40
+ * Analyze an object literal for variant key mappings.
41
+ * Handles:
42
+ * - Direct property assignments: { fontSize: variant } -> variant maps to fontSize
43
+ * - Nullish coalescing: { fontSize: fontSize ?? variant } -> variant maps to fontSize
44
+ * - Conditional spreads: ...(condition ? { props } : {}) -> recursively analyze props
45
+ */
46
+ function analyzeObjectForVariantMappings(objLiteral, styleProps, getStylesLiterals, propToVariantKeys, sourceFile) {
47
+ for (const prop of objLiteral.getProperties()) if (ts_morph.Node.isPropertyAssignment(prop)) {
48
+ const variantKey = prop.getName();
49
+ if (variantKey && !styleProps.includes(variantKey)) styleProps.push(variantKey);
50
+ const initializer = prop.getInitializer();
51
+ if (initializer && ts_morph.Node.isStringLiteral(initializer)) getStylesLiterals.set(variantKey, initializer.getLiteralValue());
52
+ if (initializer && ts_morph.Node.isIdentifier(initializer)) {
53
+ const propName = initializer.getText();
54
+ const existing = propToVariantKeys.get(propName) ?? [];
55
+ if (!existing.includes(variantKey)) {
56
+ existing.push(variantKey);
57
+ propToVariantKeys.set(propName, existing);
58
+ }
59
+ }
60
+ if (initializer && ts_morph.Node.isBinaryExpression(initializer)) {
61
+ const operatorToken = initializer.getOperatorToken();
62
+ if (operatorToken.getKind() === ts_morph.SyntaxKind.QuestionQuestionToken || operatorToken.getKind() === ts_morph.SyntaxKind.BarBarToken) {
63
+ const rightSide = initializer.getRight();
64
+ if (ts_morph.Node.isIdentifier(rightSide)) {
65
+ const fallbackPropName = rightSide.getText();
66
+ const existing = propToVariantKeys.get(fallbackPropName) ?? [];
67
+ if (!existing.includes(variantKey)) {
68
+ existing.push(variantKey);
69
+ propToVariantKeys.set(fallbackPropName, existing);
70
+ }
71
+ }
72
+ }
73
+ }
74
+ } else if (ts_morph.Node.isSpreadAssignment(prop)) {
75
+ const spreadExpr = prop.getExpression();
76
+ if (ts_morph.Node.isParenthesizedExpression(spreadExpr)) {
77
+ const inner = spreadExpr.getExpression();
78
+ if (ts_morph.Node.isConditionalExpression(inner)) {
79
+ const whenTrue = inner.getWhenTrue();
80
+ if (ts_morph.Node.isObjectLiteralExpression(whenTrue)) analyzeObjectForVariantMappings(whenTrue, styleProps, getStylesLiterals, propToVariantKeys, sourceFile);
81
+ }
82
+ }
83
+ if (ts_morph.Node.isIdentifier(spreadExpr)) {
84
+ const varName = spreadExpr.getText();
85
+ const varDecl = sourceFile.getDescendantsOfKind(ts_morph.SyntaxKind.VariableDeclaration).find((v) => v.getName() === varName);
86
+ if (varDecl) {
87
+ const varInit = varDecl.getInitializer();
88
+ if (varInit && ts_morph.Node.isObjectLiteralExpression(varInit)) analyzeObjectForVariantMappings(varInit, styleProps, getStylesLiterals, propToVariantKeys, sourceFile);
89
+ }
90
+ }
91
+ }
92
+ }
93
+ /**
94
+ * Analyzes a UDS component file to extract:
95
+ * 1. Default prop values (e.g., display = 'flex')
96
+ * 2. Props passed to getStyles()
97
+ * 3. Internal UDS component usage
98
+ */
99
+ function analyzeComponent(project, componentPath) {
100
+ const sourceFile = project.getSourceFile(componentPath);
101
+ if (!sourceFile) return null;
102
+ const componentName = node_path.default.basename(componentPath, ".tsx");
103
+ const defaultProps = /* @__PURE__ */ new Map();
104
+ const componentPropNames = /* @__PURE__ */ new Set();
105
+ const styleProps = [];
106
+ const getStylesLiterals = /* @__PURE__ */ new Map();
107
+ const cxLiterals = [];
108
+ const internalComponents = [];
109
+ const internalComponentProps = /* @__PURE__ */ new Map();
110
+ const propToVariantKeys = /* @__PURE__ */ new Map();
111
+ const functions = [...sourceFile.getFunctions(), ...sourceFile.getVariableDeclarations().filter((v) => {
112
+ const init = v.getInitializer();
113
+ return init && (ts_morph.Node.isArrowFunction(init) || ts_morph.Node.isCallExpression(init));
114
+ })];
115
+ for (const fn of functions) {
116
+ if (ts_morph.Node.isVariableDeclaration(fn)) {
117
+ const init = fn.getInitializer();
118
+ if (!init) continue;
119
+ if (ts_morph.Node.isCallExpression(init)) {
120
+ const args = init.getArguments();
121
+ for (const arg of args) if (ts_morph.Node.isFunctionExpression(arg) || ts_morph.Node.isArrowFunction(arg)) {
122
+ extractDefaultsFromFunction(arg, defaultProps);
123
+ extractAllPropNames(arg, componentPropNames);
124
+ }
125
+ }
126
+ if (ts_morph.Node.isArrowFunction(init)) {
127
+ extractDefaultsFromFunction(init, defaultProps);
128
+ extractAllPropNames(init, componentPropNames);
129
+ }
130
+ }
131
+ if (ts_morph.Node.isFunctionDeclaration(fn)) {
132
+ extractDefaultsFromFunction(fn, defaultProps);
133
+ extractAllPropNames(fn, componentPropNames);
134
+ }
135
+ }
136
+ const getStylesCalls = sourceFile.getDescendantsOfKind(ts_morph.SyntaxKind.CallExpression).filter((call) => call.getExpression().getText() === "getStyles");
137
+ for (const call of getStylesCalls) {
138
+ const args = call.getArguments();
139
+ if (args.length > 0 && ts_morph.Node.isObjectLiteralExpression(args[0])) {
140
+ const objLiteral = args[0];
141
+ for (const prop of objLiteral.getProperties()) if (ts_morph.Node.isPropertyAssignment(prop)) {
142
+ const variantKey = prop.getName();
143
+ if (variantKey && !styleProps.includes(variantKey)) styleProps.push(variantKey);
144
+ const initializer = prop.getInitializer();
145
+ if (initializer && ts_morph.Node.isStringLiteral(initializer)) getStylesLiterals.set(variantKey, initializer.getLiteralValue());
146
+ if (initializer && ts_morph.Node.isIdentifier(initializer)) {
147
+ const propName = initializer.getText();
148
+ const existing = propToVariantKeys.get(propName) ?? [];
149
+ if (!existing.includes(variantKey)) {
150
+ existing.push(variantKey);
151
+ propToVariantKeys.set(propName, existing);
152
+ }
153
+ }
154
+ if (initializer && ts_morph.Node.isBinaryExpression(initializer)) {
155
+ const operatorToken = initializer.getOperatorToken();
156
+ if (operatorToken.getKind() === ts_morph.SyntaxKind.QuestionQuestionToken || operatorToken.getKind() === ts_morph.SyntaxKind.BarBarToken) {
157
+ const rightSide = initializer.getRight();
158
+ if (ts_morph.Node.isIdentifier(rightSide)) {
159
+ const fallbackPropName = rightSide.getText();
160
+ const existing = propToVariantKeys.get(fallbackPropName) ?? [];
161
+ if (!existing.includes(variantKey)) {
162
+ existing.push(variantKey);
163
+ propToVariantKeys.set(fallbackPropName, existing);
164
+ }
165
+ }
166
+ }
167
+ }
168
+ if (initializer && ts_morph.Node.isConditionalExpression(initializer)) {
169
+ const whenTrue = initializer.getWhenTrue();
170
+ const whenFalse = initializer.getWhenFalse();
171
+ const extractLiterals = (node) => {
172
+ const literals = [];
173
+ if (ts_morph.Node.isStringLiteral(node)) literals.push(node.getLiteralValue());
174
+ else if (ts_morph.Node.isConditionalExpression(node)) {
175
+ literals.push(...extractLiterals(node.getWhenTrue()));
176
+ literals.push(...extractLiterals(node.getWhenFalse()));
177
+ }
178
+ return literals;
179
+ };
180
+ [...extractLiterals(whenTrue), ...extractLiterals(whenFalse)].forEach((value, index) => {
181
+ const literalKey = index === 0 ? variantKey : `${variantKey}:${index}`;
182
+ getStylesLiterals.set(literalKey, value);
183
+ });
184
+ }
185
+ } else if (ts_morph.Node.isShorthandPropertyAssignment(prop)) {
186
+ const propName = prop.getName();
187
+ if (propName && !styleProps.includes(propName)) styleProps.push(propName);
188
+ } else if (ts_morph.Node.isSpreadAssignment(prop)) {
189
+ const spreadExpr = prop.getExpression();
190
+ if (ts_morph.Node.isIdentifier(spreadExpr)) {
191
+ const varName = spreadExpr.getText();
192
+ const varDecl = sourceFile.getDescendantsOfKind(ts_morph.SyntaxKind.VariableDeclaration).find((v) => v.getName() === varName);
193
+ if (varDecl) {
194
+ const varInit = varDecl.getInitializer();
195
+ if (varInit && ts_morph.Node.isObjectLiteralExpression(varInit)) analyzeObjectForVariantMappings(varInit, styleProps, getStylesLiterals, propToVariantKeys, sourceFile);
196
+ }
197
+ }
198
+ }
199
+ }
200
+ }
201
+ const cxCalls = sourceFile.getDescendantsOfKind(ts_morph.SyntaxKind.CallExpression).filter((call) => call.getExpression().getText() === "cx");
202
+ for (const call of cxCalls) for (const arg of call.getArguments()) extractCxStringLiterals(arg, cxLiterals);
203
+ extractInternalComponents(sourceFile, internalComponents, internalComponentProps, propToVariantKeys, componentPropNames);
204
+ return {
205
+ name: componentName,
206
+ filePath: componentPath,
207
+ defaultProps,
208
+ styleProps,
209
+ getStylesLiterals,
210
+ cxLiterals,
211
+ internalComponents,
212
+ internalComponentProps,
213
+ propToVariantKeys,
214
+ motionVarPrefixes: extractMotionVarPrefixes(sourceFile)
215
+ };
216
+ }
217
+ /**
218
+ * Extract UDS components used internally in the file and their prop values.
219
+ * Also detects prop aliasing (e.g., columnGap={gap} means gap -> columnGap).
220
+ */
221
+ function extractInternalComponents(sourceFile, internalComponents, internalComponentProps, propToVariantKeys, componentProps) {
222
+ for (const importDecl of sourceFile.getImportDeclarations()) {
223
+ const moduleSpec = importDecl.getModuleSpecifierValue();
224
+ if (moduleSpec.startsWith("@yahoo/uds") || moduleSpec.startsWith("../") || moduleSpec.startsWith("./")) {
225
+ if (moduleSpec.includes("/components/") || moduleSpec === "@yahoo/uds") for (const namedImport of importDecl.getNamedImports()) {
226
+ const name = namedImport.getName();
227
+ if (/^[A-Z]/.test(name) && !internalComponents.includes(name)) internalComponents.push(name);
228
+ }
229
+ }
230
+ }
231
+ const jsxElements = [...sourceFile.getDescendantsOfKind(ts_morph.SyntaxKind.JsxSelfClosingElement), ...sourceFile.getDescendantsOfKind(ts_morph.SyntaxKind.JsxOpeningElement)];
232
+ for (const element of jsxElements) {
233
+ const tagName = element.getTagNameNode().getText();
234
+ if (!/^[A-Z]/.test(tagName)) continue;
235
+ if (!internalComponents.includes(tagName)) internalComponents.push(tagName);
236
+ const attrs = element.getAttributes();
237
+ for (const attr of attrs) if (ts_morph.Node.isJsxAttribute(attr)) {
238
+ const propName = attr.getNameNode().getText();
239
+ const initializer = attr.getInitializer();
240
+ let values = [];
241
+ if (initializer) {
242
+ if (ts_morph.Node.isStringLiteral(initializer)) values = [initializer.getLiteralValue()];
243
+ else if (ts_morph.Node.isJsxExpression(initializer)) {
244
+ const expr = initializer.getExpression();
245
+ if (expr && ts_morph.Node.isStringLiteral(expr)) values = [expr.getLiteralValue()];
246
+ else if (expr && ts_morph.Node.isIdentifier(expr)) {
247
+ const identifierName = expr.getText();
248
+ if (componentProps.has(identifierName) && identifierName !== propName) {
249
+ const existing = propToVariantKeys.get(identifierName) ?? [];
250
+ if (!existing.includes(propName)) {
251
+ existing.push(propName);
252
+ propToVariantKeys.set(identifierName, existing);
253
+ }
254
+ }
255
+ }
256
+ }
257
+ }
258
+ if (values.length > 0) {
259
+ let componentPropsMap = internalComponentProps.get(tagName);
260
+ if (!componentPropsMap) {
261
+ componentPropsMap = /* @__PURE__ */ new Map();
262
+ internalComponentProps.set(tagName, componentPropsMap);
263
+ }
264
+ const existingValues = componentPropsMap.get(propName) ?? [];
265
+ for (const v of values) if (!existingValues.includes(v)) existingValues.push(v);
266
+ componentPropsMap.set(propName, existingValues);
267
+ }
268
+ }
269
+ }
270
+ }
271
+ /**
272
+ * Extract default prop values from a function's parameter destructuring
273
+ */
274
+ function extractDefaultsFromFunction(fn, defaults) {
275
+ let params = [];
276
+ if (ts_morph.Node.isFunctionDeclaration(fn) || ts_morph.Node.isFunctionExpression(fn)) params = fn.getParameters();
277
+ else if (ts_morph.Node.isArrowFunction(fn)) params = fn.getParameters();
278
+ for (const param of params) {
279
+ if (!ts_morph.Node.isParameterDeclaration(param)) continue;
280
+ const nameNode = param.getNameNode();
281
+ if (!nameNode || !ts_morph.Node.isObjectBindingPattern(nameNode)) continue;
282
+ for (const element of nameNode.getElements()) {
283
+ const propName = element.getPropertyNameNode()?.getText() || element.getName();
284
+ const initializer = element.getInitializer();
285
+ if (initializer && ts_morph.Node.isStringLiteral(initializer)) defaults.set(propName, initializer.getLiteralValue());
286
+ }
287
+ }
288
+ }
289
+ /**
290
+ * Extract ALL prop names from a function's parameter destructuring (not just defaults)
291
+ */
292
+ function extractAllPropNames(fn, propNames) {
293
+ let params = [];
294
+ if (ts_morph.Node.isFunctionDeclaration(fn) || ts_morph.Node.isFunctionExpression(fn)) params = fn.getParameters();
295
+ else if (ts_morph.Node.isArrowFunction(fn)) params = fn.getParameters();
296
+ for (const param of params) {
297
+ if (!ts_morph.Node.isParameterDeclaration(param)) continue;
298
+ const nameNode = param.getNameNode();
299
+ if (!nameNode || !ts_morph.Node.isObjectBindingPattern(nameNode)) continue;
300
+ for (const element of nameNode.getElements()) {
301
+ const propName = element.getPropertyNameNode()?.getText() || element.getName();
302
+ propNames.add(propName);
303
+ }
304
+ }
305
+ }
306
+ /**
307
+ * Extract string literals from cx() call arguments.
308
+ * Handles:
309
+ * - Direct string literals: cx('class1', 'class2')
310
+ * - Object keys: cx({ 'class1': condition, 'class2': true })
311
+ * - Nested calls and arrays
312
+ */
313
+ function extractCxStringLiterals(node, literals) {
314
+ if (ts_morph.Node.isStringLiteral(node)) {
315
+ const classes = node.getLiteralValue().split(/\s+/).filter(Boolean);
316
+ for (const cls of classes) if (!literals.includes(cls)) literals.push(cls);
317
+ } else if (ts_morph.Node.isObjectLiteralExpression(node)) {
318
+ for (const prop of node.getProperties()) if (ts_morph.Node.isPropertyAssignment(prop)) {
319
+ const nameNode = prop.getNameNode();
320
+ if (ts_morph.Node.isStringLiteral(nameNode)) {
321
+ const classes = nameNode.getLiteralValue().split(/\s+/).filter(Boolean);
322
+ for (const cls of classes) if (!literals.includes(cls)) literals.push(cls);
323
+ } else if (ts_morph.Node.isIdentifier(nameNode)) {
324
+ const cls = nameNode.getText();
325
+ if (!literals.includes(cls)) literals.push(cls);
326
+ }
327
+ }
328
+ } else if (ts_morph.Node.isArrayLiteralExpression(node)) for (const element of node.getElements()) extractCxStringLiterals(element, literals);
329
+ else if (ts_morph.Node.isConditionalExpression(node)) {
330
+ extractCxStringLiterals(node.getWhenTrue(), literals);
331
+ extractCxStringLiterals(node.getWhenFalse(), literals);
332
+ } else if (ts_morph.Node.isBinaryExpression(node)) {
333
+ extractCxStringLiterals(node.getLeft(), literals);
334
+ extractCxStringLiterals(node.getRight(), literals);
335
+ }
336
+ }
337
+ /**
338
+ * Try to resolve an identifier to its initializer value (for const declarations)
339
+ */
340
+ function resolveIdentifierToObject(sourceFile, identifier) {
341
+ const varDecls = sourceFile.getDescendantsOfKind(ts_morph.SyntaxKind.VariableDeclaration);
342
+ for (const decl of varDecls) {
343
+ if (decl.getName() !== identifier) continue;
344
+ let initializer = decl.getInitializer();
345
+ if (!initializer) continue;
346
+ if (ts_morph.Node.isAsExpression(initializer)) initializer = initializer.getExpression();
347
+ if (!ts_morph.Node.isObjectLiteralExpression(initializer)) continue;
348
+ const result = {};
349
+ for (const prop of initializer.getProperties()) {
350
+ if (!ts_morph.Node.isPropertyAssignment(prop)) continue;
351
+ const propName = prop.getName();
352
+ const propInit = prop.getInitializer();
353
+ if (propInit && ts_morph.Node.isStringLiteral(propInit)) result[propName] = propInit.getLiteralValue();
354
+ }
355
+ return result;
356
+ }
357
+ return null;
358
+ }
359
+ /**
360
+ * Extract motion CSS variable prefixes from SpringMotionConfig usage.
361
+ * Returns prefixes like ['--uds-motion-bouncy-4-', '--uds-motion-smooth-3-']
362
+ */
363
+ function extractMotionVarPrefixes(sourceFile) {
364
+ const prefixes = [];
365
+ const jsxElements = [...sourceFile.getDescendantsOfKind(ts_morph.SyntaxKind.JsxSelfClosingElement), ...sourceFile.getDescendantsOfKind(ts_morph.SyntaxKind.JsxOpeningElement)];
366
+ for (const element of jsxElements) {
367
+ if (element.getTagNameNode().getText() !== "SpringMotionConfig") continue;
368
+ const props = {
369
+ layoutVariant: null,
370
+ layoutSpeed: null,
371
+ colorVariant: null,
372
+ colorSpeed: null
373
+ };
374
+ const attrs = element.getAttributes();
375
+ for (const attr of attrs) {
376
+ if (ts_morph.Node.isJsxSpreadAttribute(attr)) {
377
+ const expr = attr.getExpression();
378
+ if (ts_morph.Node.isIdentifier(expr)) {
379
+ const spreadObj = resolveIdentifierToObject(sourceFile, expr.getText());
380
+ if (spreadObj) {
381
+ for (const key of Object.keys(props)) if (key in spreadObj) props[key] = spreadObj[key];
382
+ }
383
+ }
384
+ continue;
385
+ }
386
+ if (!ts_morph.Node.isJsxAttribute(attr)) continue;
387
+ const propName = attr.getNameNode().getText();
388
+ if (!(propName in props)) continue;
389
+ const initializer = attr.getInitializer();
390
+ if (initializer) {
391
+ if (ts_morph.Node.isStringLiteral(initializer)) props[propName] = initializer.getLiteralValue();
392
+ else if (ts_morph.Node.isJsxExpression(initializer)) {
393
+ const expr = initializer.getExpression();
394
+ if (expr && ts_morph.Node.isStringLiteral(expr)) props[propName] = expr.getLiteralValue();
395
+ }
396
+ }
397
+ }
398
+ const layoutPrefix = `--uds-motion-${props.layoutVariant ?? require_index.SPRING_MOTION_DEFAULTS.layoutVariant}-${props.layoutSpeed ?? require_index.SPRING_MOTION_DEFAULTS.layoutSpeed}-`;
399
+ if (!prefixes.includes(layoutPrefix)) prefixes.push(layoutPrefix);
400
+ const colorPrefix = `--uds-motion-${props.colorVariant ?? require_index.SPRING_MOTION_DEFAULTS.colorVariant}-${props.colorSpeed ?? require_index.SPRING_MOTION_DEFAULTS.colorSpeed}-`;
401
+ if (!prefixes.includes(colorPrefix)) prefixes.push(colorPrefix);
402
+ }
403
+ return prefixes;
404
+ }
405
+
406
+ //#endregion
407
+ exports.analyzeComponent = analyzeComponent;
408
+ exports.scanComponentFiles = scanComponentFiles;