@yahoo/uds 3.161.0 → 3.162.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/dist/cli/commands/purge.cjs +8 -1
- package/dist/cli/commands/purge.helpers.cjs +7 -0
- package/dist/cli/commands/purge.helpers.d.cts +3 -0
- package/dist/cli/commands/purge.helpers.d.ts +3 -0
- package/dist/cli/commands/purge.helpers.js +7 -0
- package/dist/cli/commands/purge.js +8 -1
- package/dist/components/client/Checkbox/Checkbox.cjs +118 -0
- package/dist/components/client/{Checkbox.d.cts → Checkbox/Checkbox.d.cts} +5 -18
- package/dist/components/client/{Checkbox.d.ts → Checkbox/Checkbox.d.ts} +5 -18
- package/dist/components/client/Checkbox/Checkbox.js +113 -0
- package/dist/components/client/Checkbox/CheckboxBase.cjs +141 -0
- package/dist/components/client/Checkbox/CheckboxBase.d.cts +48 -0
- package/dist/components/client/Checkbox/CheckboxBase.d.ts +49 -0
- package/dist/components/client/Checkbox/CheckboxBase.js +138 -0
- package/dist/components/client/Checkbox/checkboxConstants.cjs +23 -0
- package/dist/components/client/Checkbox/checkboxConstants.d.cts +25 -0
- package/dist/components/client/Checkbox/checkboxConstants.d.ts +26 -0
- package/dist/components/client/Checkbox/checkboxConstants.js +17 -0
- package/dist/components/client/Checkbox/index.cjs +10 -0
- package/dist/components/client/Checkbox/index.d.cts +6 -0
- package/dist/components/client/Checkbox/index.d.ts +7 -0
- package/dist/components/client/Checkbox/index.js +6 -0
- package/dist/components/client/Checkbox/types.cjs +2 -0
- package/dist/components/client/Checkbox/types.d.cts +22 -0
- package/dist/components/client/Checkbox/types.d.ts +23 -0
- package/dist/components/client/Checkbox/types.js +2 -0
- package/dist/components/client/Popover/UDSPopoverConfigProvider.d.cts +1 -1
- package/dist/components/client/Popover/UDSPopoverConfigProvider.d.ts +1 -1
- package/dist/components/client/Radio/Radio.cjs +67 -164
- package/dist/components/client/Radio/Radio.d.cts +4 -17
- package/dist/components/client/Radio/Radio.d.ts +4 -17
- package/dist/components/client/Radio/Radio.js +66 -163
- package/dist/components/client/Radio/RadioBase.cjs +133 -0
- package/dist/components/client/Radio/RadioBase.d.cts +45 -0
- package/dist/components/client/Radio/RadioBase.d.ts +46 -0
- package/dist/components/client/Radio/RadioBase.js +130 -0
- package/dist/components/client/Radio/radioConstants.cjs +14 -0
- package/dist/components/client/Radio/radioConstants.d.cts +8 -0
- package/dist/components/client/Radio/radioConstants.d.ts +9 -0
- package/dist/components/client/Radio/radioConstants.js +11 -0
- package/dist/components/client/Radio/types.cjs +2 -0
- package/dist/components/client/Radio/types.d.cts +20 -0
- package/dist/components/client/Radio/types.d.ts +21 -0
- package/dist/components/client/Radio/types.js +2 -0
- package/dist/components/client/Toast/UDSToastConfigProvider.d.cts +1 -1
- package/dist/components/client/Toast/UDSToastConfigProvider.d.ts +1 -1
- package/dist/components/client/index.cjs +2 -2
- package/dist/components/client/index.d.cts +1 -1
- package/dist/components/client/index.d.ts +1 -1
- package/dist/components/client/index.js +1 -1
- package/dist/components/index.cjs +2 -2
- package/dist/components/index.d.cts +1 -1
- package/dist/components/index.d.ts +1 -1
- package/dist/components/index.js +1 -1
- package/dist/css/dist/commands/css.cjs +2 -0
- package/dist/css/dist/commands/css.helpers.cjs +2 -0
- package/dist/css/dist/commands/css.helpers.js +2 -0
- package/dist/css/dist/commands/css.js +2 -0
- package/dist/css/dist/css/nodeUtils.cjs +28 -11
- package/dist/css/dist/css/nodeUtils.js +29 -12
- package/dist/css/dist/css/runner.cjs +8 -3
- package/dist/css/dist/css/runner.js +8 -3
- package/dist/css/dist/css/theme.d.cts +16 -0
- package/dist/css/dist/css/theme.d.ts +16 -0
- package/dist/css/dist/css/workerPool.cjs +2 -1
- package/dist/css/dist/css/workerPool.js +2 -1
- package/dist/css/dist/purger/optimized/ast/expressions.cjs +104 -11
- package/dist/css/dist/purger/optimized/ast/expressions.js +104 -11
- package/dist/css/dist/purger/optimized/ast/jsx.cjs +74 -0
- package/dist/css/dist/purger/optimized/ast/jsx.js +73 -0
- package/dist/css/dist/purger/optimized/ast/props.cjs +47 -0
- package/dist/css/dist/purger/optimized/ast/props.js +46 -0
- package/dist/css/dist/purger/optimized/ast/spread.cjs +87 -0
- package/dist/css/dist/purger/optimized/ast/spread.js +86 -0
- package/dist/css/dist/purger/optimized/purge.cjs +14 -8
- package/dist/css/dist/purger/optimized/purge.js +15 -9
- package/dist/css/dist/purger/optimized/purgeFromCode.cjs +176 -18
- package/dist/css/dist/purger/optimized/purgeFromCode.js +176 -19
- package/dist/css/dist/purger/optimized/utils/files.cjs +22 -2
- package/dist/css/dist/purger/optimized/utils/files.js +21 -3
- package/dist/css-animation/Checkbox/Checkbox.cjs +75 -0
- package/dist/css-animation/Checkbox/Checkbox.d.cts +22 -0
- package/dist/css-animation/Checkbox/Checkbox.d.ts +23 -0
- package/dist/css-animation/Checkbox/Checkbox.js +72 -0
- package/dist/css-animation/Checkbox/index.cjs +5 -0
- package/dist/css-animation/Checkbox/index.d.cts +3 -0
- package/dist/css-animation/Checkbox/index.d.ts +4 -0
- package/dist/css-animation/Checkbox/index.js +4 -0
- package/dist/css-animation/Radio/Radio.cjs +92 -0
- package/dist/css-animation/Radio/Radio.d.cts +22 -0
- package/dist/css-animation/Radio/Radio.d.ts +23 -0
- package/dist/css-animation/Radio/Radio.js +89 -0
- package/dist/css-animation/Radio/index.cjs +5 -0
- package/dist/css-animation/Radio/index.d.cts +3 -0
- package/dist/css-animation/Radio/index.d.ts +4 -0
- package/dist/css-animation/Radio/index.js +4 -0
- package/dist/css-animation/index.cjs +4 -0
- package/dist/css-animation/index.d.cts +3 -1
- package/dist/css-animation/index.d.ts +3 -1
- package/dist/css-animation/index.js +3 -1
- package/dist/index.cjs +2 -2
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/styles/styler.d.cts +26 -26
- package/dist/styles/styler.d.ts +26 -26
- package/dist/uds/generated/componentData.cjs +343 -293
- package/dist/uds/generated/componentData.js +343 -293
- package/dist/uds/generated/tailwindPurge.cjs +12 -12
- package/dist/uds/generated/tailwindPurge.js +12 -12
- package/generated/componentData.json +471 -382
- package/generated/tailwindPurge.ts +2 -2
- package/package.json +1 -1
- package/dist/components/client/Checkbox.cjs +0 -224
- package/dist/components/client/Checkbox.js +0 -219
|
@@ -59,7 +59,8 @@ const createWorkerPool = async (config, numWorkers) => {
|
|
|
59
59
|
colorModes: options.colorModes,
|
|
60
60
|
variantDefaults: options.variantDefaults,
|
|
61
61
|
runtimeConfigValues: options.runtimeConfigValues,
|
|
62
|
-
includeAllClassNamePrimitives: options.includeAllClassNamePrimitives
|
|
62
|
+
includeAllClassNamePrimitives: options.includeAllClassNamePrimitives,
|
|
63
|
+
deferWrapperSpreadResolution: options.deferWrapperSpreadResolution
|
|
63
64
|
};
|
|
64
65
|
const task = {
|
|
65
66
|
resolve,
|
|
@@ -223,30 +223,114 @@ const extractCallExpressionValues = (node, visited) => {
|
|
|
223
223
|
const fromArguments = node.getArguments().flatMap((arg) => extractStringLiterals(arg, visited));
|
|
224
224
|
return [...fromDefinitions, ...fromArguments];
|
|
225
225
|
};
|
|
226
|
+
/** Array methods that return (a subset of) the receiver's elements. */
|
|
227
|
+
const ARRAY_CHAIN_METHODS = new Set([
|
|
228
|
+
"concat",
|
|
229
|
+
"filter",
|
|
230
|
+
"flat",
|
|
231
|
+
"reverse",
|
|
232
|
+
"slice",
|
|
233
|
+
"sort",
|
|
234
|
+
"toReversed",
|
|
235
|
+
"toSorted"
|
|
236
|
+
]);
|
|
237
|
+
/**
|
|
238
|
+
* If the definition is the first parameter of a `.map()`/`.flatMap()` callback,
|
|
239
|
+
* return the expression being mapped over (the array source).
|
|
240
|
+
*/
|
|
241
|
+
const getMappedArraySource = (definition) => {
|
|
242
|
+
if (!ts_morph.Node.isParameterDeclaration(definition)) return null;
|
|
243
|
+
const callback = definition.getParentIfKind(ts_morph.SyntaxKind.ArrowFunction);
|
|
244
|
+
if (!callback) return null;
|
|
245
|
+
const callExpression = callback.getParentIfKind(ts_morph.SyntaxKind.CallExpression);
|
|
246
|
+
if (!callExpression) return null;
|
|
247
|
+
const expression = callExpression.getExpression();
|
|
248
|
+
if (!ts_morph.Node.isPropertyAccessExpression(expression)) return null;
|
|
249
|
+
if (!["map", "flatMap"].includes(expression.getName())) return null;
|
|
250
|
+
if (callback.getParameters().findIndex((parameter) => {
|
|
251
|
+
return parameter.getNameNode().getText() === definition.getNameNode().getText();
|
|
252
|
+
}) !== 0) return null;
|
|
253
|
+
return expression.getExpression();
|
|
254
|
+
};
|
|
255
|
+
/**
|
|
256
|
+
* Resolve a node to the object-literal AST nodes it may evaluate to.
|
|
257
|
+
* Handles arrays of objects (each element is a candidate), element access,
|
|
258
|
+
* array-method chains, and `.map()` callback parameters (UDS-2557 follow-up:
|
|
259
|
+
* variant arrays nested inside const structures).
|
|
260
|
+
*/
|
|
261
|
+
const resolveObjectLiteralNodes = (node, visited) => {
|
|
262
|
+
if (visited.has(node)) return [];
|
|
263
|
+
visited.add(node);
|
|
264
|
+
if (ts_morph.Node.isObjectLiteralExpression(node)) return [node];
|
|
265
|
+
if (ts_morph.Node.isParenthesizedExpression(node) || ts_morph.Node.isAsExpression(node) || ts_morph.Node.isTypeAssertion(node) || ts_morph.Node.isSatisfiesExpression(node)) return resolveObjectLiteralNodes(node.getExpression(), visited);
|
|
266
|
+
if (ts_morph.Node.isArrayLiteralExpression(node)) return node.getElements().flatMap((element) => resolveObjectLiteralNodes(element, visited));
|
|
267
|
+
if (ts_morph.Node.isElementAccessExpression(node)) return resolveObjectLiteralNodes(node.getExpression(), visited);
|
|
268
|
+
if (ts_morph.Node.isCallExpression(node)) {
|
|
269
|
+
const expression = node.getExpression();
|
|
270
|
+
if (ts_morph.Node.isPropertyAccessExpression(expression) && ARRAY_CHAIN_METHODS.has(expression.getName())) return resolveObjectLiteralNodes(expression.getExpression(), visited);
|
|
271
|
+
return [];
|
|
272
|
+
}
|
|
273
|
+
if (ts_morph.Node.isIdentifier(node)) return getLocalDefinitionNodes(node).flatMap((definition) => {
|
|
274
|
+
if (ts_morph.Node.isVariableDeclaration(definition)) {
|
|
275
|
+
const initializer = definition.getInitializer();
|
|
276
|
+
return initializer ? resolveObjectLiteralNodes(initializer, visited) : [];
|
|
277
|
+
}
|
|
278
|
+
const mappedSource = getMappedArraySource(definition);
|
|
279
|
+
if (mappedSource) return resolveObjectLiteralNodes(mappedSource, visited);
|
|
280
|
+
return [];
|
|
281
|
+
});
|
|
282
|
+
return [];
|
|
283
|
+
};
|
|
284
|
+
/**
|
|
285
|
+
* Collect the initializers of a named property across object-literal candidates.
|
|
286
|
+
*/
|
|
287
|
+
const getPropertyInitializers = (objectLiterals, propertyName) => objectLiterals.flatMap((obj) => {
|
|
288
|
+
if (!ts_morph.Node.isObjectLiteralExpression(obj)) return [];
|
|
289
|
+
return obj.getProperties().flatMap((prop) => {
|
|
290
|
+
if (!ts_morph.Node.isPropertyAssignment(prop) || prop.getName() !== propertyName) return [];
|
|
291
|
+
const initializer = prop.getInitializer();
|
|
292
|
+
return initializer ? [initializer] : [];
|
|
293
|
+
});
|
|
294
|
+
});
|
|
295
|
+
/**
|
|
296
|
+
* For a destructured binding (e.g. `({ variants }) =>` map param or
|
|
297
|
+
* `const { variants } = GROUPS[0]`), resolve the bound property's initializers.
|
|
298
|
+
*/
|
|
299
|
+
const getBindingElementSources = (definition) => {
|
|
300
|
+
if (!ts_morph.Node.isBindingElement(definition)) return [];
|
|
301
|
+
const bindingPattern = definition.getParent();
|
|
302
|
+
if (!ts_morph.Node.isObjectBindingPattern(bindingPattern)) return [];
|
|
303
|
+
const propertyName = definition.getPropertyNameNode()?.getText() ?? definition.getName();
|
|
304
|
+
const holder = bindingPattern.getParent();
|
|
305
|
+
let source = null;
|
|
306
|
+
if (ts_morph.Node.isParameterDeclaration(holder)) source = getMappedArraySource(holder);
|
|
307
|
+
else if (ts_morph.Node.isVariableDeclaration(holder)) source = holder.getInitializer() ?? null;
|
|
308
|
+
if (!source) return [];
|
|
309
|
+
return getPropertyInitializers(resolveObjectLiteralNodes(source, /* @__PURE__ */ new Set()), propertyName);
|
|
310
|
+
};
|
|
226
311
|
const extractArrayElementValues = (node, visited) => {
|
|
227
312
|
if (ts_morph.Node.isArrayLiteralExpression(node)) return node.getElements().flatMap((element) => extractStringLiterals(element, visited)).filter((value, index, values) => values.indexOf(value) === index);
|
|
228
313
|
if (ts_morph.Node.isParenthesizedExpression(node)) return extractArrayElementValues(node.getExpression(), visited);
|
|
229
314
|
if (ts_morph.Node.isAsExpression(node) || ts_morph.Node.isTypeAssertion(node) || ts_morph.Node.isSatisfiesExpression(node)) return extractArrayElementValues(node.getExpression(), visited);
|
|
315
|
+
if (ts_morph.Node.isPropertyAccessExpression(node)) return getPropertyInitializers(resolveObjectLiteralNodes(node.getExpression(), /* @__PURE__ */ new Set()), node.getName()).flatMap((initializer) => extractArrayElementValues(initializer, visited)).filter((value, index, values) => values.indexOf(value) === index);
|
|
316
|
+
if (ts_morph.Node.isCallExpression(node)) {
|
|
317
|
+
const expression = node.getExpression();
|
|
318
|
+
if (ts_morph.Node.isPropertyAccessExpression(expression) && ARRAY_CHAIN_METHODS.has(expression.getName())) return extractArrayElementValues(expression.getExpression(), visited);
|
|
319
|
+
return [];
|
|
320
|
+
}
|
|
230
321
|
if (ts_morph.Node.isIdentifier(node)) return getLocalDefinitionNodes(node).flatMap((definition) => {
|
|
231
322
|
if (ts_morph.Node.isVariableDeclaration(definition)) {
|
|
232
323
|
const initializer = definition.getInitializer();
|
|
233
324
|
return initializer ? extractArrayElementValues(initializer, visited) : [];
|
|
234
325
|
}
|
|
235
|
-
return
|
|
326
|
+
return getBindingElementSources(definition).flatMap((source) => extractArrayElementValues(source, visited));
|
|
236
327
|
}).filter((value, index, values) => values.indexOf(value) === index);
|
|
237
328
|
return [];
|
|
238
329
|
};
|
|
239
330
|
const extractMappedParameterValues = (definition, visited) => {
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
const callExpression = callback.getParentIfKind(ts_morph.SyntaxKind.CallExpression);
|
|
244
|
-
if (!callExpression) return [];
|
|
245
|
-
const expression = callExpression.getExpression();
|
|
246
|
-
if (!ts_morph.Node.isPropertyAccessExpression(expression)) return [];
|
|
247
|
-
if (!["map", "flatMap"].includes(expression.getName())) return [];
|
|
248
|
-
if (callback.getParameters().findIndex((parameter) => parameter.getNameNode().getText() === definition.getNameNode().getText()) !== 0) return [];
|
|
249
|
-
return extractArrayElementValues(expression.getExpression(), visited);
|
|
331
|
+
const mappedSource = getMappedArraySource(definition);
|
|
332
|
+
if (!mappedSource) return [];
|
|
333
|
+
return extractArrayElementValues(mappedSource, visited);
|
|
250
334
|
};
|
|
251
335
|
const extractIdentifierValues = (node, visited) => {
|
|
252
336
|
if (!ts_morph.Node.isIdentifier(node)) return null;
|
|
@@ -331,6 +415,15 @@ const extractObjectValues = (node, visited) => {
|
|
|
331
415
|
} else values.push(...extractObjectValues(initializer, visited));
|
|
332
416
|
}
|
|
333
417
|
});
|
|
418
|
+
const enumDecl = node.getSourceFile().getEnum(node.getText());
|
|
419
|
+
if (enumDecl) {
|
|
420
|
+
const obj = {};
|
|
421
|
+
enumDecl.getMembers().forEach((member) => {
|
|
422
|
+
const initializer = member.getInitializer();
|
|
423
|
+
if (initializer && ts_morph.Node.isStringLiteral(initializer)) obj[member.getName()] = initializer.getLiteralValue();
|
|
424
|
+
});
|
|
425
|
+
if (Object.keys(obj).length > 0) values.push(obj);
|
|
426
|
+
}
|
|
334
427
|
return values;
|
|
335
428
|
}
|
|
336
429
|
if (ts_morph.Node.isCallExpression(node)) {
|
|
@@ -220,30 +220,114 @@ const extractCallExpressionValues = (node, visited) => {
|
|
|
220
220
|
const fromArguments = node.getArguments().flatMap((arg) => extractStringLiterals(arg, visited));
|
|
221
221
|
return [...fromDefinitions, ...fromArguments];
|
|
222
222
|
};
|
|
223
|
+
/** Array methods that return (a subset of) the receiver's elements. */
|
|
224
|
+
const ARRAY_CHAIN_METHODS = new Set([
|
|
225
|
+
"concat",
|
|
226
|
+
"filter",
|
|
227
|
+
"flat",
|
|
228
|
+
"reverse",
|
|
229
|
+
"slice",
|
|
230
|
+
"sort",
|
|
231
|
+
"toReversed",
|
|
232
|
+
"toSorted"
|
|
233
|
+
]);
|
|
234
|
+
/**
|
|
235
|
+
* If the definition is the first parameter of a `.map()`/`.flatMap()` callback,
|
|
236
|
+
* return the expression being mapped over (the array source).
|
|
237
|
+
*/
|
|
238
|
+
const getMappedArraySource = (definition) => {
|
|
239
|
+
if (!Node.isParameterDeclaration(definition)) return null;
|
|
240
|
+
const callback = definition.getParentIfKind(SyntaxKind.ArrowFunction);
|
|
241
|
+
if (!callback) return null;
|
|
242
|
+
const callExpression = callback.getParentIfKind(SyntaxKind.CallExpression);
|
|
243
|
+
if (!callExpression) return null;
|
|
244
|
+
const expression = callExpression.getExpression();
|
|
245
|
+
if (!Node.isPropertyAccessExpression(expression)) return null;
|
|
246
|
+
if (!["map", "flatMap"].includes(expression.getName())) return null;
|
|
247
|
+
if (callback.getParameters().findIndex((parameter) => {
|
|
248
|
+
return parameter.getNameNode().getText() === definition.getNameNode().getText();
|
|
249
|
+
}) !== 0) return null;
|
|
250
|
+
return expression.getExpression();
|
|
251
|
+
};
|
|
252
|
+
/**
|
|
253
|
+
* Resolve a node to the object-literal AST nodes it may evaluate to.
|
|
254
|
+
* Handles arrays of objects (each element is a candidate), element access,
|
|
255
|
+
* array-method chains, and `.map()` callback parameters (UDS-2557 follow-up:
|
|
256
|
+
* variant arrays nested inside const structures).
|
|
257
|
+
*/
|
|
258
|
+
const resolveObjectLiteralNodes = (node, visited) => {
|
|
259
|
+
if (visited.has(node)) return [];
|
|
260
|
+
visited.add(node);
|
|
261
|
+
if (Node.isObjectLiteralExpression(node)) return [node];
|
|
262
|
+
if (Node.isParenthesizedExpression(node) || Node.isAsExpression(node) || Node.isTypeAssertion(node) || Node.isSatisfiesExpression(node)) return resolveObjectLiteralNodes(node.getExpression(), visited);
|
|
263
|
+
if (Node.isArrayLiteralExpression(node)) return node.getElements().flatMap((element) => resolveObjectLiteralNodes(element, visited));
|
|
264
|
+
if (Node.isElementAccessExpression(node)) return resolveObjectLiteralNodes(node.getExpression(), visited);
|
|
265
|
+
if (Node.isCallExpression(node)) {
|
|
266
|
+
const expression = node.getExpression();
|
|
267
|
+
if (Node.isPropertyAccessExpression(expression) && ARRAY_CHAIN_METHODS.has(expression.getName())) return resolveObjectLiteralNodes(expression.getExpression(), visited);
|
|
268
|
+
return [];
|
|
269
|
+
}
|
|
270
|
+
if (Node.isIdentifier(node)) return getLocalDefinitionNodes(node).flatMap((definition) => {
|
|
271
|
+
if (Node.isVariableDeclaration(definition)) {
|
|
272
|
+
const initializer = definition.getInitializer();
|
|
273
|
+
return initializer ? resolveObjectLiteralNodes(initializer, visited) : [];
|
|
274
|
+
}
|
|
275
|
+
const mappedSource = getMappedArraySource(definition);
|
|
276
|
+
if (mappedSource) return resolveObjectLiteralNodes(mappedSource, visited);
|
|
277
|
+
return [];
|
|
278
|
+
});
|
|
279
|
+
return [];
|
|
280
|
+
};
|
|
281
|
+
/**
|
|
282
|
+
* Collect the initializers of a named property across object-literal candidates.
|
|
283
|
+
*/
|
|
284
|
+
const getPropertyInitializers = (objectLiterals, propertyName) => objectLiterals.flatMap((obj) => {
|
|
285
|
+
if (!Node.isObjectLiteralExpression(obj)) return [];
|
|
286
|
+
return obj.getProperties().flatMap((prop) => {
|
|
287
|
+
if (!Node.isPropertyAssignment(prop) || prop.getName() !== propertyName) return [];
|
|
288
|
+
const initializer = prop.getInitializer();
|
|
289
|
+
return initializer ? [initializer] : [];
|
|
290
|
+
});
|
|
291
|
+
});
|
|
292
|
+
/**
|
|
293
|
+
* For a destructured binding (e.g. `({ variants }) =>` map param or
|
|
294
|
+
* `const { variants } = GROUPS[0]`), resolve the bound property's initializers.
|
|
295
|
+
*/
|
|
296
|
+
const getBindingElementSources = (definition) => {
|
|
297
|
+
if (!Node.isBindingElement(definition)) return [];
|
|
298
|
+
const bindingPattern = definition.getParent();
|
|
299
|
+
if (!Node.isObjectBindingPattern(bindingPattern)) return [];
|
|
300
|
+
const propertyName = definition.getPropertyNameNode()?.getText() ?? definition.getName();
|
|
301
|
+
const holder = bindingPattern.getParent();
|
|
302
|
+
let source = null;
|
|
303
|
+
if (Node.isParameterDeclaration(holder)) source = getMappedArraySource(holder);
|
|
304
|
+
else if (Node.isVariableDeclaration(holder)) source = holder.getInitializer() ?? null;
|
|
305
|
+
if (!source) return [];
|
|
306
|
+
return getPropertyInitializers(resolveObjectLiteralNodes(source, /* @__PURE__ */ new Set()), propertyName);
|
|
307
|
+
};
|
|
223
308
|
const extractArrayElementValues = (node, visited) => {
|
|
224
309
|
if (Node.isArrayLiteralExpression(node)) return node.getElements().flatMap((element) => extractStringLiterals(element, visited)).filter((value, index, values) => values.indexOf(value) === index);
|
|
225
310
|
if (Node.isParenthesizedExpression(node)) return extractArrayElementValues(node.getExpression(), visited);
|
|
226
311
|
if (Node.isAsExpression(node) || Node.isTypeAssertion(node) || Node.isSatisfiesExpression(node)) return extractArrayElementValues(node.getExpression(), visited);
|
|
312
|
+
if (Node.isPropertyAccessExpression(node)) return getPropertyInitializers(resolveObjectLiteralNodes(node.getExpression(), /* @__PURE__ */ new Set()), node.getName()).flatMap((initializer) => extractArrayElementValues(initializer, visited)).filter((value, index, values) => values.indexOf(value) === index);
|
|
313
|
+
if (Node.isCallExpression(node)) {
|
|
314
|
+
const expression = node.getExpression();
|
|
315
|
+
if (Node.isPropertyAccessExpression(expression) && ARRAY_CHAIN_METHODS.has(expression.getName())) return extractArrayElementValues(expression.getExpression(), visited);
|
|
316
|
+
return [];
|
|
317
|
+
}
|
|
227
318
|
if (Node.isIdentifier(node)) return getLocalDefinitionNodes(node).flatMap((definition) => {
|
|
228
319
|
if (Node.isVariableDeclaration(definition)) {
|
|
229
320
|
const initializer = definition.getInitializer();
|
|
230
321
|
return initializer ? extractArrayElementValues(initializer, visited) : [];
|
|
231
322
|
}
|
|
232
|
-
return
|
|
323
|
+
return getBindingElementSources(definition).flatMap((source) => extractArrayElementValues(source, visited));
|
|
233
324
|
}).filter((value, index, values) => values.indexOf(value) === index);
|
|
234
325
|
return [];
|
|
235
326
|
};
|
|
236
327
|
const extractMappedParameterValues = (definition, visited) => {
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
const callExpression = callback.getParentIfKind(SyntaxKind.CallExpression);
|
|
241
|
-
if (!callExpression) return [];
|
|
242
|
-
const expression = callExpression.getExpression();
|
|
243
|
-
if (!Node.isPropertyAccessExpression(expression)) return [];
|
|
244
|
-
if (!["map", "flatMap"].includes(expression.getName())) return [];
|
|
245
|
-
if (callback.getParameters().findIndex((parameter) => parameter.getNameNode().getText() === definition.getNameNode().getText()) !== 0) return [];
|
|
246
|
-
return extractArrayElementValues(expression.getExpression(), visited);
|
|
328
|
+
const mappedSource = getMappedArraySource(definition);
|
|
329
|
+
if (!mappedSource) return [];
|
|
330
|
+
return extractArrayElementValues(mappedSource, visited);
|
|
247
331
|
};
|
|
248
332
|
const extractIdentifierValues = (node, visited) => {
|
|
249
333
|
if (!Node.isIdentifier(node)) return null;
|
|
@@ -328,6 +412,15 @@ const extractObjectValues = (node, visited) => {
|
|
|
328
412
|
} else values.push(...extractObjectValues(initializer, visited));
|
|
329
413
|
}
|
|
330
414
|
});
|
|
415
|
+
const enumDecl = node.getSourceFile().getEnum(node.getText());
|
|
416
|
+
if (enumDecl) {
|
|
417
|
+
const obj = {};
|
|
418
|
+
enumDecl.getMembers().forEach((member) => {
|
|
419
|
+
const initializer = member.getInitializer();
|
|
420
|
+
if (initializer && Node.isStringLiteral(initializer)) obj[member.getName()] = initializer.getLiteralValue();
|
|
421
|
+
});
|
|
422
|
+
if (Object.keys(obj).length > 0) values.push(obj);
|
|
423
|
+
}
|
|
331
424
|
return values;
|
|
332
425
|
}
|
|
333
426
|
if (Node.isCallExpression(node)) {
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/*! © 2026 Yahoo, Inc. UDS v0.0.0-development */
|
|
2
|
+
require("../../../../../_virtual/_rolldown/runtime.cjs");
|
|
3
|
+
let ts_morph = require("ts-morph");
|
|
4
|
+
//#region ../css/dist/purger/optimized/ast/jsx.mjs
|
|
5
|
+
/*! © 2026 Yahoo, Inc. UDS CSS v0.0.0-development */
|
|
6
|
+
/**
|
|
7
|
+
* Check if an expression is using React.forwardRef
|
|
8
|
+
*/
|
|
9
|
+
const isForwardRefExpression = (node) => {
|
|
10
|
+
if (!ts_morph.Node.isCallExpression(node)) return false;
|
|
11
|
+
const expression = node.getExpression();
|
|
12
|
+
if (ts_morph.Node.isIdentifier(expression) && expression.getText() === "forwardRef") return true;
|
|
13
|
+
if (ts_morph.Node.isPropertyAccessExpression(expression) && expression.getText() === "React.forwardRef") return true;
|
|
14
|
+
return false;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Check if a node is a JSX component (PascalCase name)
|
|
18
|
+
*/
|
|
19
|
+
const isJsxComponent = (node) => {
|
|
20
|
+
let name;
|
|
21
|
+
if (ts_morph.Node.isVariableDeclaration(node) || ts_morph.Node.isFunctionDeclaration(node) || ts_morph.Node.isClassDeclaration(node)) name = node.getName();
|
|
22
|
+
else if (ts_morph.Node.isFunctionExpression(node) || ts_morph.Node.isArrowFunction(node)) name = node.getFirstAncestorByKind(ts_morph.SyntaxKind.VariableDeclaration)?.getName();
|
|
23
|
+
return name ? /^[A-Z]/.test(name) : false;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Get the function declaration from a component, unwrapping forwardRef if needed
|
|
27
|
+
*/
|
|
28
|
+
const getReactFunctionDeclaration = (declaration) => {
|
|
29
|
+
if (!isJsxComponent(declaration)) return null;
|
|
30
|
+
if (ts_morph.Node.isFunctionDeclaration(declaration)) return declaration;
|
|
31
|
+
if (ts_morph.Node.isVariableDeclaration(declaration)) {
|
|
32
|
+
const initializer = declaration.getInitializer();
|
|
33
|
+
if (!initializer) return null;
|
|
34
|
+
if (isForwardRefExpression(initializer)) {
|
|
35
|
+
const [arg] = initializer.getArguments();
|
|
36
|
+
if (ts_morph.Node.isFunctionDeclaration(arg) || ts_morph.Node.isFunctionExpression(arg) || ts_morph.Node.isArrowFunction(arg)) return arg;
|
|
37
|
+
} else if (ts_morph.Node.isFunctionDeclaration(initializer) || ts_morph.Node.isFunctionExpression(initializer) || ts_morph.Node.isArrowFunction(initializer)) return initializer;
|
|
38
|
+
}
|
|
39
|
+
return null;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Get the parent component that contains a JSX reference.
|
|
43
|
+
* Returns information about the component including spread rest identifier.
|
|
44
|
+
*/
|
|
45
|
+
const getParentComponentInfo = (reference) => {
|
|
46
|
+
const block = reference.getParentWhile((parent) => !getReactFunctionDeclaration(parent));
|
|
47
|
+
if (!block) return;
|
|
48
|
+
const blockParent = block.getParent();
|
|
49
|
+
if (!blockParent) return;
|
|
50
|
+
const reactComponent = getReactFunctionDeclaration(blockParent);
|
|
51
|
+
if (!reactComponent) return;
|
|
52
|
+
let componentName;
|
|
53
|
+
const variableDeclaration = reactComponent.getFirstAncestorByKind(ts_morph.SyntaxKind.VariableDeclaration);
|
|
54
|
+
if (variableDeclaration) componentName = variableDeclaration.getName();
|
|
55
|
+
else if (ts_morph.Node.isFunctionDeclaration(reactComponent)) componentName = reactComponent.getName();
|
|
56
|
+
if (!componentName) return;
|
|
57
|
+
let spreadRestIdentifier;
|
|
58
|
+
let paramIdentifier;
|
|
59
|
+
reactComponent.getParameters().forEach((parameter) => {
|
|
60
|
+
const objectBindingPattern = parameter.getChildrenOfKind(ts_morph.SyntaxKind.ObjectBindingPattern)[0];
|
|
61
|
+
const identifier = parameter.getChildrenOfKind(ts_morph.SyntaxKind.Identifier)[0];
|
|
62
|
+
if (objectBindingPattern) {
|
|
63
|
+
const dotDotToken = objectBindingPattern.getFirstDescendantByKind(ts_morph.SyntaxKind.DotDotDotToken);
|
|
64
|
+
if (dotDotToken) spreadRestIdentifier = dotDotToken.getParent()?.getFirstChildByKindOrThrow(ts_morph.SyntaxKind.Identifier).getText();
|
|
65
|
+
} else if (identifier) paramIdentifier = identifier.getText();
|
|
66
|
+
});
|
|
67
|
+
return {
|
|
68
|
+
componentName,
|
|
69
|
+
spreadRestIdentifier,
|
|
70
|
+
paramIdentifier
|
|
71
|
+
};
|
|
72
|
+
};
|
|
73
|
+
//#endregion
|
|
74
|
+
exports.getParentComponentInfo = getParentComponentInfo;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/*! © 2026 Yahoo, Inc. UDS v0.0.0-development */
|
|
2
|
+
import { Node, SyntaxKind } from "ts-morph";
|
|
3
|
+
//#region ../css/dist/purger/optimized/ast/jsx.mjs
|
|
4
|
+
/*! © 2026 Yahoo, Inc. UDS CSS v0.0.0-development */
|
|
5
|
+
/**
|
|
6
|
+
* Check if an expression is using React.forwardRef
|
|
7
|
+
*/
|
|
8
|
+
const isForwardRefExpression = (node) => {
|
|
9
|
+
if (!Node.isCallExpression(node)) return false;
|
|
10
|
+
const expression = node.getExpression();
|
|
11
|
+
if (Node.isIdentifier(expression) && expression.getText() === "forwardRef") return true;
|
|
12
|
+
if (Node.isPropertyAccessExpression(expression) && expression.getText() === "React.forwardRef") return true;
|
|
13
|
+
return false;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Check if a node is a JSX component (PascalCase name)
|
|
17
|
+
*/
|
|
18
|
+
const isJsxComponent = (node) => {
|
|
19
|
+
let name;
|
|
20
|
+
if (Node.isVariableDeclaration(node) || Node.isFunctionDeclaration(node) || Node.isClassDeclaration(node)) name = node.getName();
|
|
21
|
+
else if (Node.isFunctionExpression(node) || Node.isArrowFunction(node)) name = node.getFirstAncestorByKind(SyntaxKind.VariableDeclaration)?.getName();
|
|
22
|
+
return name ? /^[A-Z]/.test(name) : false;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Get the function declaration from a component, unwrapping forwardRef if needed
|
|
26
|
+
*/
|
|
27
|
+
const getReactFunctionDeclaration = (declaration) => {
|
|
28
|
+
if (!isJsxComponent(declaration)) return null;
|
|
29
|
+
if (Node.isFunctionDeclaration(declaration)) return declaration;
|
|
30
|
+
if (Node.isVariableDeclaration(declaration)) {
|
|
31
|
+
const initializer = declaration.getInitializer();
|
|
32
|
+
if (!initializer) return null;
|
|
33
|
+
if (isForwardRefExpression(initializer)) {
|
|
34
|
+
const [arg] = initializer.getArguments();
|
|
35
|
+
if (Node.isFunctionDeclaration(arg) || Node.isFunctionExpression(arg) || Node.isArrowFunction(arg)) return arg;
|
|
36
|
+
} else if (Node.isFunctionDeclaration(initializer) || Node.isFunctionExpression(initializer) || Node.isArrowFunction(initializer)) return initializer;
|
|
37
|
+
}
|
|
38
|
+
return null;
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Get the parent component that contains a JSX reference.
|
|
42
|
+
* Returns information about the component including spread rest identifier.
|
|
43
|
+
*/
|
|
44
|
+
const getParentComponentInfo = (reference) => {
|
|
45
|
+
const block = reference.getParentWhile((parent) => !getReactFunctionDeclaration(parent));
|
|
46
|
+
if (!block) return;
|
|
47
|
+
const blockParent = block.getParent();
|
|
48
|
+
if (!blockParent) return;
|
|
49
|
+
const reactComponent = getReactFunctionDeclaration(blockParent);
|
|
50
|
+
if (!reactComponent) return;
|
|
51
|
+
let componentName;
|
|
52
|
+
const variableDeclaration = reactComponent.getFirstAncestorByKind(SyntaxKind.VariableDeclaration);
|
|
53
|
+
if (variableDeclaration) componentName = variableDeclaration.getName();
|
|
54
|
+
else if (Node.isFunctionDeclaration(reactComponent)) componentName = reactComponent.getName();
|
|
55
|
+
if (!componentName) return;
|
|
56
|
+
let spreadRestIdentifier;
|
|
57
|
+
let paramIdentifier;
|
|
58
|
+
reactComponent.getParameters().forEach((parameter) => {
|
|
59
|
+
const objectBindingPattern = parameter.getChildrenOfKind(SyntaxKind.ObjectBindingPattern)[0];
|
|
60
|
+
const identifier = parameter.getChildrenOfKind(SyntaxKind.Identifier)[0];
|
|
61
|
+
if (objectBindingPattern) {
|
|
62
|
+
const dotDotToken = objectBindingPattern.getFirstDescendantByKind(SyntaxKind.DotDotDotToken);
|
|
63
|
+
if (dotDotToken) spreadRestIdentifier = dotDotToken.getParent()?.getFirstChildByKindOrThrow(SyntaxKind.Identifier).getText();
|
|
64
|
+
} else if (identifier) paramIdentifier = identifier.getText();
|
|
65
|
+
});
|
|
66
|
+
return {
|
|
67
|
+
componentName,
|
|
68
|
+
spreadRestIdentifier,
|
|
69
|
+
paramIdentifier
|
|
70
|
+
};
|
|
71
|
+
};
|
|
72
|
+
//#endregion
|
|
73
|
+
export { getParentComponentInfo };
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/*! © 2026 Yahoo, Inc. UDS v0.0.0-development */
|
|
2
|
+
require("../../../../../_virtual/_rolldown/runtime.cjs");
|
|
3
|
+
const require_expressions = require("./expressions.cjs");
|
|
4
|
+
let ts_morph = require("ts-morph");
|
|
5
|
+
//#region ../css/dist/purger/optimized/ast/props.mjs
|
|
6
|
+
/*! © 2026 Yahoo, Inc. UDS CSS v0.0.0-development */
|
|
7
|
+
/**
|
|
8
|
+
* Extract all props from a JSX element (both explicit props and spread props).
|
|
9
|
+
*
|
|
10
|
+
* For explicit props like `<Box color="brand" />`, extracts the prop name and value.
|
|
11
|
+
* For spread props like `<Box {...props} />`, marks them as fromSpread for later resolution.
|
|
12
|
+
*
|
|
13
|
+
* @param element The JSX element to extract props from
|
|
14
|
+
* @returns Array of extracted props with their values
|
|
15
|
+
*/
|
|
16
|
+
const extractPropsFromElement = (element) => element.getAttributes().flatMap((attr) => {
|
|
17
|
+
if (ts_morph.Node.isJsxAttribute(attr)) {
|
|
18
|
+
const propName = attr.getNameNode().getText();
|
|
19
|
+
const stringLiterals = attr.getDescendantsOfKind(ts_morph.SyntaxKind.StringLiteral);
|
|
20
|
+
return [{
|
|
21
|
+
name: propName,
|
|
22
|
+
values: stringLiterals.length > 0 ? stringLiterals.map((lit) => lit.getLiteralText()) : (() => {
|
|
23
|
+
const initializer = attr.getInitializer();
|
|
24
|
+
if (!initializer || !ts_morph.Node.isJsxExpression(initializer)) return [];
|
|
25
|
+
const expression = initializer.getExpression();
|
|
26
|
+
return expression ? require_expressions.extractStringLiterals(expression) : [];
|
|
27
|
+
})(),
|
|
28
|
+
fromSpread: false
|
|
29
|
+
}];
|
|
30
|
+
}
|
|
31
|
+
if (ts_morph.Node.isJsxSpreadAttribute(attr)) {
|
|
32
|
+
const expression = attr.getExpression();
|
|
33
|
+
return [{
|
|
34
|
+
name: `__spread__:${ts_morph.Node.isIdentifier(expression) ? expression.getText() : expression.getChildren().pop()?.getText() ?? ""}`,
|
|
35
|
+
values: [],
|
|
36
|
+
fromSpread: true
|
|
37
|
+
}];
|
|
38
|
+
}
|
|
39
|
+
return [];
|
|
40
|
+
});
|
|
41
|
+
/**
|
|
42
|
+
* Extract only explicit (non-spread) props from a JSX element.
|
|
43
|
+
* Used when we want to avoid including spread-derived values.
|
|
44
|
+
*/
|
|
45
|
+
const extractExplicitProps = (element) => extractPropsFromElement(element).filter((p) => !p.fromSpread);
|
|
46
|
+
//#endregion
|
|
47
|
+
exports.extractExplicitProps = extractExplicitProps;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/*! © 2026 Yahoo, Inc. UDS v0.0.0-development */
|
|
2
|
+
import { extractStringLiterals } from "./expressions.js";
|
|
3
|
+
import { Node, SyntaxKind } from "ts-morph";
|
|
4
|
+
//#region ../css/dist/purger/optimized/ast/props.mjs
|
|
5
|
+
/*! © 2026 Yahoo, Inc. UDS CSS v0.0.0-development */
|
|
6
|
+
/**
|
|
7
|
+
* Extract all props from a JSX element (both explicit props and spread props).
|
|
8
|
+
*
|
|
9
|
+
* For explicit props like `<Box color="brand" />`, extracts the prop name and value.
|
|
10
|
+
* For spread props like `<Box {...props} />`, marks them as fromSpread for later resolution.
|
|
11
|
+
*
|
|
12
|
+
* @param element The JSX element to extract props from
|
|
13
|
+
* @returns Array of extracted props with their values
|
|
14
|
+
*/
|
|
15
|
+
const extractPropsFromElement = (element) => element.getAttributes().flatMap((attr) => {
|
|
16
|
+
if (Node.isJsxAttribute(attr)) {
|
|
17
|
+
const propName = attr.getNameNode().getText();
|
|
18
|
+
const stringLiterals = attr.getDescendantsOfKind(SyntaxKind.StringLiteral);
|
|
19
|
+
return [{
|
|
20
|
+
name: propName,
|
|
21
|
+
values: stringLiterals.length > 0 ? stringLiterals.map((lit) => lit.getLiteralText()) : (() => {
|
|
22
|
+
const initializer = attr.getInitializer();
|
|
23
|
+
if (!initializer || !Node.isJsxExpression(initializer)) return [];
|
|
24
|
+
const expression = initializer.getExpression();
|
|
25
|
+
return expression ? extractStringLiterals(expression) : [];
|
|
26
|
+
})(),
|
|
27
|
+
fromSpread: false
|
|
28
|
+
}];
|
|
29
|
+
}
|
|
30
|
+
if (Node.isJsxSpreadAttribute(attr)) {
|
|
31
|
+
const expression = attr.getExpression();
|
|
32
|
+
return [{
|
|
33
|
+
name: `__spread__:${Node.isIdentifier(expression) ? expression.getText() : expression.getChildren().pop()?.getText() ?? ""}`,
|
|
34
|
+
values: [],
|
|
35
|
+
fromSpread: true
|
|
36
|
+
}];
|
|
37
|
+
}
|
|
38
|
+
return [];
|
|
39
|
+
});
|
|
40
|
+
/**
|
|
41
|
+
* Extract only explicit (non-spread) props from a JSX element.
|
|
42
|
+
* Used when we want to avoid including spread-derived values.
|
|
43
|
+
*/
|
|
44
|
+
const extractExplicitProps = (element) => extractPropsFromElement(element).filter((p) => !p.fromSpread);
|
|
45
|
+
//#endregion
|
|
46
|
+
export { extractExplicitProps };
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/*! © 2026 Yahoo, Inc. UDS v0.0.0-development */
|
|
2
|
+
require("../../../../../_virtual/_rolldown/runtime.cjs");
|
|
3
|
+
const require_jsx = require("./jsx.cjs");
|
|
4
|
+
const require_props = require("./props.cjs");
|
|
5
|
+
let ts_morph = require("ts-morph");
|
|
6
|
+
//#region ../css/dist/purger/optimized/ast/spread.mjs
|
|
7
|
+
/*! © 2026 Yahoo, Inc. UDS CSS v0.0.0-development */
|
|
8
|
+
/**
|
|
9
|
+
* Find all usages of a component across the entire project.
|
|
10
|
+
* This is the key function for spread resolution - when we encounter
|
|
11
|
+
* {...props} on a UDS component inside a wrapper, we trace back to
|
|
12
|
+
* find all places where the wrapper is used and extract actual values.
|
|
13
|
+
*
|
|
14
|
+
* @param componentName Name of the component to find usages of
|
|
15
|
+
* @param project The ts-morph project
|
|
16
|
+
* @param cache Optional cache to avoid re-scanning
|
|
17
|
+
* @returns Array of component usages with their props
|
|
18
|
+
*/
|
|
19
|
+
const findComponentUsages = (componentName, project, cache) => {
|
|
20
|
+
if (cache?.has(componentName)) return cache.get(componentName);
|
|
21
|
+
const usages = [];
|
|
22
|
+
project.getSourceFiles().forEach((sourceFile) => {
|
|
23
|
+
if (!fileReferencesComponent(sourceFile, componentName)) return;
|
|
24
|
+
[...sourceFile.getDescendantsOfKind(ts_morph.SyntaxKind.JsxSelfClosingElement), ...sourceFile.getDescendantsOfKind(ts_morph.SyntaxKind.JsxOpeningElement)].filter((el) => el.getTagNameNode().getText() === componentName).forEach((element) => {
|
|
25
|
+
const props = require_props.extractExplicitProps(element);
|
|
26
|
+
usages.push({
|
|
27
|
+
componentName,
|
|
28
|
+
filePath: sourceFile.getFilePath(),
|
|
29
|
+
line: element.getStartLineNumber(),
|
|
30
|
+
props
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
if (cache) cache.set(componentName, usages);
|
|
35
|
+
return usages;
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Check if a source file references a component (by import or definition)
|
|
39
|
+
*/
|
|
40
|
+
const fileReferencesComponent = (sourceFile, componentName) => {
|
|
41
|
+
if (sourceFile.getImportDeclarations().some((imp) => imp.getNamedImports().some((named) => named.getName() === componentName))) return true;
|
|
42
|
+
if (sourceFile.getVariableDeclaration(componentName)) return true;
|
|
43
|
+
if (sourceFile.getFunction(componentName)) return true;
|
|
44
|
+
return false;
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Resolve spread props by tracing component usage.
|
|
48
|
+
*
|
|
49
|
+
* When we encounter {...props} on a UDS component inside a wrapper:
|
|
50
|
+
* 1. Find the parent component that contains this spread
|
|
51
|
+
* 2. Search ALL files for usages of that parent component
|
|
52
|
+
* 3. Extract actual prop values passed at each usage site
|
|
53
|
+
* 4. Return ONLY those values - never fall back to type properties
|
|
54
|
+
*
|
|
55
|
+
* @param element The JSX element with the spread
|
|
56
|
+
* @param spreadIdentifier The identifier being spread (e.g., 'rest' from {...rest})
|
|
57
|
+
* @param context The purge context for caching
|
|
58
|
+
* @returns Map of prop names to their resolved values, or undefined if couldn't trace
|
|
59
|
+
*/
|
|
60
|
+
const resolveSpreadFromUsages = (element, spreadIdentifier, context) => {
|
|
61
|
+
const parentInfo = require_jsx.getParentComponentInfo(element);
|
|
62
|
+
if (!parentInfo) return;
|
|
63
|
+
if (!(parentInfo.spreadRestIdentifier === spreadIdentifier || parentInfo.paramIdentifier === spreadIdentifier)) return;
|
|
64
|
+
const usages = findComponentUsages(parentInfo.componentName, context.project, context.componentUsageCache);
|
|
65
|
+
if (usages.length === 0) return;
|
|
66
|
+
context.stats.spreadsTraced++;
|
|
67
|
+
const resolvedProps = /* @__PURE__ */ new Map();
|
|
68
|
+
usages.forEach((usage) => {
|
|
69
|
+
usage.props.forEach((prop) => {
|
|
70
|
+
if (prop.fromSpread) return;
|
|
71
|
+
const existing = resolvedProps.get(prop.name) ?? [];
|
|
72
|
+
prop.values.forEach((value) => {
|
|
73
|
+
if (!existing.includes(value)) existing.push(value);
|
|
74
|
+
});
|
|
75
|
+
resolvedProps.set(prop.name, existing);
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
const cacheKey = `${element.getSourceFile().getFilePath()}:${element.getStartLineNumber()}:${spreadIdentifier}`;
|
|
79
|
+
context.spreadCache.set(cacheKey, Array.from(resolvedProps).map(([name, values]) => ({
|
|
80
|
+
name,
|
|
81
|
+
values,
|
|
82
|
+
fromSpread: true
|
|
83
|
+
})));
|
|
84
|
+
return resolvedProps;
|
|
85
|
+
};
|
|
86
|
+
//#endregion
|
|
87
|
+
exports.resolveSpreadFromUsages = resolveSpreadFromUsages;
|