styled-components-to-stylex-codemod 0.0.47 → 0.0.48

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 (2) hide show
  1. package/dist/transform.mjs +516 -128
  2. package/package.json +1 -1
@@ -2605,8 +2605,76 @@ function typeContainsPolymorphicAs(args) {
2605
2605
  return visit(args.typeNode);
2606
2606
  }
2607
2607
  //#endregion
2608
+ //#region src/internal/utilities/typescript-metadata.ts
2609
+ function findTypeScriptComponentMetadata(metadata, filePath, componentNames) {
2610
+ if (!metadata) return;
2611
+ const names = new Set(componentNames);
2612
+ const resolvedFilePath = resolveExistingFilePath(filePath);
2613
+ return metadata.files.find((file) => file.filePath === resolvedFilePath)?.components.find((component) => names.has(component.name) || defaultExportMatches(component, names));
2614
+ }
2615
+ function applyTypeScriptMetadataToDecl(ctx, decl, names) {
2616
+ const typedComponent = findTypeScriptComponentMetadata(ctx.options.crossFileInfo?.typeScriptMetadata, ctx.file.path, names);
2617
+ if (!typedComponent) return;
2618
+ decl.typeScriptPropNames = new Set(typedComponent.props.map((prop) => prop.name));
2619
+ decl.typeScriptExplicitPropNames = new Set(typedComponent.explicitPropNames);
2620
+ decl.typeScriptPropTypes = new Map(typedComponent.props.map((prop) => [prop.name, prop.type]));
2621
+ decl.typeScriptOptionalProps = new Set(typedComponent.props.filter((prop) => prop.optional).map((prop) => prop.name));
2622
+ decl.typeScriptHasIndexSignature = typedComponent.hasIndexSignature;
2623
+ decl.typeScriptSupportsSxProp = typedComponent.supportsSxProp;
2624
+ }
2625
+ function defaultExportMatches(component, names) {
2626
+ return component.defaultExport && names.has("default");
2627
+ }
2628
+ //#endregion
2629
+ //#region src/internal/utilities/wrapped-component-interface.ts
2630
+ function wrappedComponentInterfaceFor(ctx, componentLocalName) {
2631
+ if (!ctx.adapter.useSxProp) return;
2632
+ const importInfo = ctx.importMap?.get(componentLocalName);
2633
+ if (importInfo) {
2634
+ const typedInterface = importInfo.source.kind === "absolutePath" ? typedComponentInterfaceFor(ctx, importInfo.source.value, importInfo.importedName === "default" ? [componentLocalName, importInfo.importedName] : [importInfo.importedName]) : void 0;
2635
+ const adapterResult = ctx.adapter.wrappedComponentInterface?.({
2636
+ localName: componentLocalName,
2637
+ importSource: importInfo.source.value,
2638
+ importedName: importInfo.importedName,
2639
+ filePath: ctx.file.path
2640
+ });
2641
+ if (adapterResult !== void 0) {
2642
+ if (adapterResult.acceptsSx && hasTypedSxConstraints(typedInterface)) return {
2643
+ ...adapterResult,
2644
+ sxExcludedProperties: mergeUniqueStrings(adapterResult.sxExcludedProperties, typedInterface.sxExcludedProperties ?? []),
2645
+ sxAllowedProperties: mergeAllowedPropertyLists(adapterResult.sxAllowedProperties, typedInterface.sxAllowedProperties)
2646
+ };
2647
+ return adapterResult;
2648
+ }
2649
+ return typedInterface;
2650
+ }
2651
+ return typedComponentInterfaceFor(ctx, ctx.file.path, [componentLocalName]);
2652
+ }
2653
+ function hasTypedSxConstraints(typedInterface) {
2654
+ return typedInterface !== void 0 && ((typedInterface.sxExcludedProperties?.length ?? 0) > 0 || typedInterface.sxAllowedProperties !== void 0);
2655
+ }
2656
+ function typedComponentInterfaceFor(ctx, filePath, componentNames) {
2657
+ const typedComponent = findTypeScriptComponentMetadata(ctx.options.crossFileInfo?.typeScriptMetadata, filePath, componentNames);
2658
+ if (typedComponent?.supportsSxProp) return {
2659
+ acceptsSx: true,
2660
+ sxExcludedProperties: typedComponent.sxExcludedProperties,
2661
+ sxAllowedProperties: typedComponent.sxAllowedProperties
2662
+ };
2663
+ }
2664
+ function mergeAllowedPropertyLists(first, second) {
2665
+ if (first === void 0) return second === void 0 ? void 0 : [...second];
2666
+ if (second === void 0) return [...first];
2667
+ const secondSet = new Set(second);
2668
+ return first.filter((name) => secondSet.has(name));
2669
+ }
2670
+ function mergeUniqueStrings(first, second) {
2671
+ return [...new Set([...first ?? [], ...second])];
2672
+ }
2673
+ //#endregion
2608
2674
  //#region src/internal/transform-steps/analyze-after-emit.ts
2609
2675
  const INLINE_USAGE_THRESHOLD$1 = 1;
2676
+ const AS_ATTR = new Set(["as"]);
2677
+ const FORWARDED_AS_ATTR = new Set(["forwardedAs"]);
2610
2678
  /**
2611
2679
  * Finalizes wrapper decisions, polymorphic handling, and base flattening after style emission.
2612
2680
  */
@@ -2762,6 +2830,16 @@ function analyzeAfterEmitStep(ctx) {
2762
2830
  if (!canDowngradeStyleFnIntrinsicWrapper(decl, exportedComponents, extendedBy, root, j)) continue;
2763
2831
  decl.needsWrapperComponent = false;
2764
2832
  }
2833
+ for (const decl of styledDecls) {
2834
+ if (!canInlineSingleUseSxAwareComponentWrapper({
2835
+ ctx,
2836
+ decl,
2837
+ exportedComponents,
2838
+ extendedBy,
2839
+ wrapperNames
2840
+ })) continue;
2841
+ decl.needsWrapperComponent = false;
2842
+ }
2765
2843
  ctx.wrapperNames = wrapperNames;
2766
2844
  return CONTINUE;
2767
2845
  }
@@ -2795,6 +2873,60 @@ function canDowngradeStyleFnIntrinsicWrapper(decl, exportedComponents, extendedB
2795
2873
  if (decl.receivesClassNameOrStyleInJsx) return false;
2796
2874
  return true;
2797
2875
  }
2876
+ function canInlineSingleUseSxAwareComponentWrapper(args) {
2877
+ const { ctx, decl, exportedComponents, extendedBy, wrapperNames } = args;
2878
+ const { root, j } = ctx;
2879
+ if (!decl.needsWrapperComponent || decl.isCssHelper || decl.isDirectJsxResolution) return false;
2880
+ if (decl.base.kind !== "component") return false;
2881
+ if (exportedComponents.has(decl.localName)) return false;
2882
+ if (wrapperNames.has(decl.localName) && !hasOnlyForwardedAsPolymorphicUsage(root, j, decl)) return false;
2883
+ if (extendedBy.has(decl.localName) || decl.usedAsValue) return false;
2884
+ if (countComponentJsxUsages(root, j, decl.localName) !== INLINE_USAGE_THRESHOLD$1) return false;
2885
+ if (hasJsxNamespaceUsage(root, j, decl.localName)) return false;
2886
+ if (hasSpreadInJsx(root, j, decl.localName)) return false;
2887
+ if (hasAttrsAsOverride(decl.attrsInfo) || hasAttrsPayload(decl.attrsInfo)) return false;
2888
+ if (needsShouldForwardPropWrapper(decl) || decl.attrWrapper || decl.bridgeClassName || decl.enumVariant || (decl.inlineStyleProps?.length ?? 0) > 0 || (decl.styleFnFromProps?.length ?? 0) > 0 || (decl.variantDimensions?.length ?? 0) > 0 || Object.keys(decl.variantStyleKeys ?? {}).length > 0 || (decl.compoundVariants?.length ?? 0) > 0 || (decl.pseudoAliasSelectors?.length ?? 0) > 0 || (decl.pseudoExpandSelectors?.length ?? 0) > 0 || (decl.localElementOverrides?.length ?? 0) > 0 || (decl.needsUseThemeHook?.length ?? 0) > 0 || (decl.extraStylexPropsArgs?.some((arg) => arg.when) ?? false)) return false;
2889
+ const componentInterface = wrappedComponentInterfaceFor(ctx, decl.base.ident);
2890
+ return componentInterface?.acceptsSx === true && (componentInterface.sxExcludedProperties?.length ?? 0) === 0 && componentInterface.sxAllowedProperties === void 0;
2891
+ }
2892
+ function hasAttrsPayload(attrsInfo) {
2893
+ return !!(Object.keys(attrsInfo?.staticAttrs ?? {}).length > 0 || (attrsInfo?.conditionalAttrs?.length ?? 0) > 0 || (attrsInfo?.defaultAttrs?.length ?? 0) > 0 || (attrsInfo?.dynamicAttrs?.length ?? 0) > 0 || (attrsInfo?.invertedBoolAttrs?.length ?? 0) > 0 || Object.keys(attrsInfo?.attrsStaticStyles ?? {}).length > 0 || attrsInfo?.attrsStaticStyleExpr || (attrsInfo?.attrsDynamicStyles?.length ?? 0) > 0);
2894
+ }
2895
+ function hasOnlyForwardedAsPolymorphicUsage(root, j, decl) {
2896
+ return decl.base.kind === "component" && hasAnyJsxAttribute(root, j, decl.localName, FORWARDED_AS_ATTR) && !hasAnyJsxAttribute(root, j, decl.localName, AS_ATTR);
2897
+ }
2898
+ function hasJsxNamespaceUsage(root, j, localName) {
2899
+ let found = false;
2900
+ root.find(j.JSXMemberExpression).forEach((p) => {
2901
+ if (getRootJsxIdentifierName(p.node) === localName) found = true;
2902
+ });
2903
+ return found;
2904
+ }
2905
+ function hasAnyJsxAttribute(root, j, name, attrNames) {
2906
+ let found = false;
2907
+ const checkOpening = (opening) => {
2908
+ for (const attr of opening.attributes ?? []) {
2909
+ const attrName = attr.name?.name;
2910
+ if (attr.type === "JSXAttribute" && attrName && attrNames.has(attrName)) {
2911
+ found = true;
2912
+ return;
2913
+ }
2914
+ }
2915
+ };
2916
+ root.find(j.JSXElement, { openingElement: { name: {
2917
+ type: "JSXIdentifier",
2918
+ name
2919
+ } } }).forEach((p) => {
2920
+ if (!found) checkOpening(p.node.openingElement);
2921
+ });
2922
+ root.find(j.JSXSelfClosingElement, { name: {
2923
+ type: "JSXIdentifier",
2924
+ name
2925
+ } }).forEach((p) => {
2926
+ if (!found) checkOpening(p.node);
2927
+ });
2928
+ return found;
2929
+ }
2798
2930
  //#endregion
2799
2931
  //#region src/internal/analyze-before-emit/exported-components.ts
2800
2932
  function collectExportedComponents(root, j, declByLocal) {
@@ -3035,27 +3167,6 @@ function specifierExportedName(spec) {
3035
3167
  return null;
3036
3168
  }
3037
3169
  //#endregion
3038
- //#region src/internal/utilities/typescript-metadata.ts
3039
- function findTypeScriptComponentMetadata(metadata, filePath, componentNames) {
3040
- if (!metadata) return;
3041
- const names = new Set(componentNames);
3042
- const resolvedFilePath = resolveExistingFilePath(filePath);
3043
- return metadata.files.find((file) => file.filePath === resolvedFilePath)?.components.find((component) => names.has(component.name) || defaultExportMatches(component, names));
3044
- }
3045
- function applyTypeScriptMetadataToDecl(ctx, decl, names) {
3046
- const typedComponent = findTypeScriptComponentMetadata(ctx.options.crossFileInfo?.typeScriptMetadata, ctx.file.path, names);
3047
- if (!typedComponent) return;
3048
- decl.typeScriptPropNames = new Set(typedComponent.props.map((prop) => prop.name));
3049
- decl.typeScriptExplicitPropNames = new Set(typedComponent.explicitPropNames);
3050
- decl.typeScriptPropTypes = new Map(typedComponent.props.map((prop) => [prop.name, prop.type]));
3051
- decl.typeScriptOptionalProps = new Set(typedComponent.props.filter((prop) => prop.optional).map((prop) => prop.name));
3052
- decl.typeScriptHasIndexSignature = typedComponent.hasIndexSignature;
3053
- decl.typeScriptSupportsSxProp = typedComponent.supportsSxProp;
3054
- }
3055
- function defaultExportMatches(component, names) {
3056
- return component.defaultExport && names.has("default");
3057
- }
3058
- //#endregion
3059
3170
  //#region src/internal/emit-wrappers/variant-condition.ts
3060
3171
  /**
3061
3172
  * Parse a variant "when" string into an AST condition expression.
@@ -4721,51 +4832,6 @@ function buildChildStyleObjectList(childKeys, resolvedStyleObjects) {
4721
4832
  return childStyleObjects;
4722
4833
  }
4723
4834
  //#endregion
4724
- //#region src/internal/utilities/wrapped-component-interface.ts
4725
- function wrappedComponentInterfaceFor(ctx, componentLocalName) {
4726
- if (!ctx.adapter.useSxProp) return;
4727
- const importInfo = ctx.importMap?.get(componentLocalName);
4728
- if (importInfo) {
4729
- const typedInterface = importInfo.source.kind === "absolutePath" ? typedComponentInterfaceFor(ctx, importInfo.source.value, importInfo.importedName === "default" ? [componentLocalName, importInfo.importedName] : [importInfo.importedName]) : void 0;
4730
- const adapterResult = ctx.adapter.wrappedComponentInterface?.({
4731
- localName: componentLocalName,
4732
- importSource: importInfo.source.value,
4733
- importedName: importInfo.importedName,
4734
- filePath: ctx.file.path
4735
- });
4736
- if (adapterResult !== void 0) {
4737
- if (adapterResult.acceptsSx && hasTypedSxConstraints(typedInterface)) return {
4738
- ...adapterResult,
4739
- sxExcludedProperties: mergeUniqueStrings(adapterResult.sxExcludedProperties, typedInterface.sxExcludedProperties ?? []),
4740
- sxAllowedProperties: mergeAllowedPropertyLists(adapterResult.sxAllowedProperties, typedInterface.sxAllowedProperties)
4741
- };
4742
- return adapterResult;
4743
- }
4744
- return typedInterface;
4745
- }
4746
- return typedComponentInterfaceFor(ctx, ctx.file.path, [componentLocalName]);
4747
- }
4748
- function hasTypedSxConstraints(typedInterface) {
4749
- return typedInterface !== void 0 && ((typedInterface.sxExcludedProperties?.length ?? 0) > 0 || typedInterface.sxAllowedProperties !== void 0);
4750
- }
4751
- function typedComponentInterfaceFor(ctx, filePath, componentNames) {
4752
- const typedComponent = findTypeScriptComponentMetadata(ctx.options.crossFileInfo?.typeScriptMetadata, filePath, componentNames);
4753
- if (typedComponent?.supportsSxProp) return {
4754
- acceptsSx: true,
4755
- sxExcludedProperties: typedComponent.sxExcludedProperties,
4756
- sxAllowedProperties: typedComponent.sxAllowedProperties
4757
- };
4758
- }
4759
- function mergeAllowedPropertyLists(first, second) {
4760
- if (first === void 0) return second === void 0 ? void 0 : [...second];
4761
- if (second === void 0) return [...first];
4762
- const secondSet = new Set(second);
4763
- return first.filter((name) => secondSet.has(name));
4764
- }
4765
- function mergeUniqueStrings(first, second) {
4766
- return [...new Set([...first ?? [], ...second])];
4767
- }
4768
- //#endregion
4769
4835
  //#region src/internal/utilities/style-composition-plan.ts
4770
4836
  function buildStyleKeySequence(ctx, decl, options) {
4771
4837
  const entries = [];
@@ -7348,6 +7414,11 @@ function coerceToStringForStyleX(cssProp, value) {
7348
7414
  */
7349
7415
  function inferTypeForCssProp(cssProp, expr) {
7350
7416
  if (isStylexStringOnlyCssProp(cssProp)) return "string";
7417
+ const conditionalType = inferTypeFromConditionalBranches(expr);
7418
+ if (conditionalType) {
7419
+ if (conditionalType === "number" && LENGTH_LIKE_CSS_PROP_RE.test(cssProp)) return "numberOrString";
7420
+ return conditionalType;
7421
+ }
7351
7422
  const staticVal = literalToStaticValue(expr);
7352
7423
  if (typeof staticVal === "number") return "number";
7353
7424
  if (typeof staticVal === "string") return "string";
@@ -7355,6 +7426,25 @@ function inferTypeForCssProp(cssProp, expr) {
7355
7426
  if (LENGTH_LIKE_CSS_PROP_RE.test(cssProp)) return "numberOrString";
7356
7427
  return "string";
7357
7428
  }
7429
+ function inferTypeFromConditionalBranches(expr) {
7430
+ if (!expr || typeof expr !== "object") return null;
7431
+ const node = expr;
7432
+ if (node.type !== "ConditionalExpression") return null;
7433
+ const consequent = inferTypeFromExpressionValue(node.consequent);
7434
+ const alternate = inferTypeFromExpressionValue(node.alternate);
7435
+ if (!consequent || !alternate) return null;
7436
+ if (consequent === alternate) return consequent;
7437
+ return "numberOrString";
7438
+ }
7439
+ function inferTypeFromExpressionValue(expr) {
7440
+ const nested = inferTypeFromConditionalBranches(expr);
7441
+ if (nested) return nested;
7442
+ if (expr && typeof expr === "object" && expr.type === "TemplateLiteral") return "string";
7443
+ const value = literalToStaticValue(expr);
7444
+ if (typeof value === "string") return "string";
7445
+ if (typeof value === "number") return "number";
7446
+ return null;
7447
+ }
7358
7448
  /**
7359
7449
  * Analyzes JSX call-site `style={{ ... }}` objects for all intrinsic styled components
7360
7450
  * and promotes analyzable style objects to proper `stylex.create` entries.
@@ -9364,6 +9454,32 @@ function findEnclosingFunction(path) {
9364
9454
  }
9365
9455
  return null;
9366
9456
  }
9457
+ function collectStyledComponentLocalNames(root, j, styledLocalNames) {
9458
+ const names = /* @__PURE__ */ new Set();
9459
+ root.find(j.VariableDeclarator).forEach((path) => {
9460
+ if (path.node.id?.type !== "Identifier") return;
9461
+ const init = path.node.init;
9462
+ if (!init) return;
9463
+ if (init.type === "TaggedTemplateExpression" && isStyledTag(styledLocalNames, init.tag)) {
9464
+ names.add(path.node.id.name);
9465
+ return;
9466
+ }
9467
+ if (init.type === "CallExpression" && init.callee?.type === "TaggedTemplateExpression" && isStyledTag(styledLocalNames, init.callee.tag)) names.add(path.node.id.name);
9468
+ });
9469
+ return names;
9470
+ }
9471
+ function templateReferencesStyledComponentSelector(template, styledLocalNames) {
9472
+ const parsed = parseStyledTemplateLiteral(template);
9473
+ for (const slot of parsed.slots) {
9474
+ const expr = slot.expression;
9475
+ if (expr.type !== "Identifier" || !expr.name || !styledLocalNames.has(expr.name)) continue;
9476
+ const after = parsed.rawCss.slice(slot.endOffset);
9477
+ const nextBlockStart = after.indexOf("{");
9478
+ const nextDeclarationEnd = after.indexOf(";");
9479
+ if (nextBlockStart >= 0 && (nextDeclarationEnd < 0 || nextBlockStart < nextDeclarationEnd)) return true;
9480
+ }
9481
+ return false;
9482
+ }
9367
9483
  /**
9368
9484
  * Checks a CSS template for closure variable references and returns an UnsupportedCssUsage
9369
9485
  * if any are found. Returns null if no closure variables are detected.
@@ -9509,8 +9625,11 @@ function detectUnsupportedCssHelperUsage(args) {
9509
9625
  return unsupportedUsages;
9510
9626
  }
9511
9627
  function extractAndRemoveCssHelpers(args) {
9512
- const { root, j, styledImports, cssLocal, toStyleKey, preserveDeclarationOnlyNames } = args;
9628
+ const { root, j, styledImports, cssLocal, toStyleKey, preserveDeclarationOnlyNames, preservedStyledComponentSelectorNames } = args;
9513
9629
  const styledLocalNames = collectStyledDefaultImportLocalNames(styledImports);
9630
+ const styledComponentLocalNames = collectStyledComponentLocalNames(root, j, styledLocalNames);
9631
+ const preservedSelectorNames = preservedStyledComponentSelectorNames ?? /* @__PURE__ */ new Set();
9632
+ const rewrittenStyledComponentLocalNames = new Set([...styledComponentLocalNames].filter((name) => !preservedSelectorNames.has(name)));
9514
9633
  const exportedLocalNames = buildExportedLocalNames(root, j);
9515
9634
  const cssHelperFunctions = /* @__PURE__ */ new Map();
9516
9635
  const cssHelperNames = /* @__PURE__ */ new Set();
@@ -9566,12 +9685,20 @@ function extractAndRemoveCssHelpers(args) {
9566
9685
  const styleKey = toStyleKey(localName);
9567
9686
  const placementHints = getCssHelperPlacementHints(root, p);
9568
9687
  const isExported = exportedLocalNames.has(localName);
9569
- const preserveDeclarationOnly = preserveDeclarationOnlyNames?.has(localName) ?? false;
9570
9688
  const template = init.quasi;
9571
9689
  const { rules, rawCss, templateExpressions } = parseCssHelperTemplate({
9572
9690
  template,
9573
9691
  noteUniversalSelector: noteCssHelperUniversalSelector
9574
9692
  });
9693
+ if (isExported && templateReferencesStyledComponentSelector(template, rewrittenStyledComponentLocalNames)) {
9694
+ unsupportedCssUsages.push({
9695
+ loc: getNodeLocStart(template),
9696
+ reason: "outside-styled-template"
9697
+ });
9698
+ return;
9699
+ }
9700
+ if (isExported && templateReferencesStyledComponentSelector(template, preservedSelectorNames)) return;
9701
+ const preserveDeclarationOnly = preserveDeclarationOnlyNames?.has(localName) ?? false;
9575
9702
  cssHelperDecls.push({
9576
9703
  ...placementHints,
9577
9704
  localName,
@@ -9614,6 +9741,18 @@ function extractAndRemoveCssHelpers(args) {
9614
9741
  }
9615
9742
  changed = true;
9616
9743
  });
9744
+ if (unsupportedCssUsages.length > 0) return {
9745
+ unsupportedCssUsages,
9746
+ cssHelperFunctions,
9747
+ cssHelperNames,
9748
+ cssHelperObjectMembers,
9749
+ cssHelperDecls,
9750
+ cssHelperHasUniversalSelectors,
9751
+ cssHelperUniversalSelectorLoc,
9752
+ cssHelperReplacements,
9753
+ cssHelperTemplateReplacements,
9754
+ changed
9755
+ };
9617
9756
  root.find(j.VariableDeclarator, { init: { type: "ArrowFunctionExpression" } }).forEach((p) => {
9618
9757
  if (p.node.id.type !== "Identifier") return;
9619
9758
  const name = p.node.id.name;
@@ -9865,10 +10004,6 @@ function cleanupCssImportStep(ctx) {
9865
10004
  //#endregion
9866
10005
  //#region src/internal/transform-steps/collect-static-props.ts
9867
10006
  /**
9868
- * Step: collect static property assignments on styled components.
9869
- * Core concepts: static metadata capture and inheritance generation.
9870
- */
9871
- /**
9872
10007
  * Collects static property assignments and generates inheritance statements.
9873
10008
  */
9874
10009
  function collectStaticPropsStep(ctx) {
@@ -9879,6 +10014,7 @@ function collectStaticPropsStep(ctx) {
9879
10014
  const staticPropertyAssignments = /* @__PURE__ */ new Map();
9880
10015
  const staticPropertyNames = /* @__PURE__ */ new Map();
9881
10016
  const styledNames = new Set(styledDecls.map((d) => d.localName));
10017
+ const objectExpressionByName = collectObjectExpressionVariables(root, j);
9882
10018
  const baseComponentNames = /* @__PURE__ */ new Set();
9883
10019
  for (const decl of styledDecls) {
9884
10020
  const baseIdent = getEffectiveBaseIdent(decl);
@@ -9895,12 +10031,8 @@ function collectStaticPropsStep(ctx) {
9895
10031
  }).forEach((p) => {
9896
10032
  const expr = p.node.expression;
9897
10033
  const componentName = expr.left.object.name;
9898
- const propName = expr.left.property?.name ?? expr.left.property?.value;
9899
- if (propName) {
9900
- const names = staticPropertyNames.get(componentName) ?? [];
9901
- names.push(propName);
9902
- staticPropertyNames.set(componentName, names);
9903
- }
10034
+ const propName = getStaticPropertyNameFromMemberExpression(expr.left);
10035
+ if (propName) addStaticPropertyName(staticPropertyNames, componentName, propName);
9904
10036
  if (baseComponentNames.has(componentName)) return;
9905
10037
  if (ctx.exportedComponents?.has(componentName) || ctx.extendedBy?.has(componentName)) {
9906
10038
  const existing = staticPropertyAssignments.get(componentName) ?? [];
@@ -9909,6 +10041,24 @@ function collectStaticPropsStep(ctx) {
9909
10041
  }
9910
10042
  j(p).remove();
9911
10043
  });
10044
+ root.find(j.CallExpression).forEach((path) => {
10045
+ const callee = path.node.callee;
10046
+ if (callee?.type !== "MemberExpression" || callee.object?.type !== "Identifier" || callee.object.name !== "Object" || callee.property?.type !== "Identifier" || callee.property.name !== "assign") return;
10047
+ const parent = path.parentPath?.node;
10048
+ const assignedName = parent?.type === "VariableDeclarator" && parent.id?.type === "Identifier" ? parent.id.name : null;
10049
+ const target = path.node.arguments?.[0];
10050
+ if (target?.type !== "Identifier") return;
10051
+ const componentNames = [target.name, ...assignedName ? [assignedName] : []].filter((name, index, names) => names.indexOf(name) === index && baseComponentNames.has(name));
10052
+ if (componentNames.length === 0) return;
10053
+ for (const componentName of componentNames) for (const source of path.node.arguments.slice(1)) {
10054
+ const statics = getObjectAssignStaticSource(source, objectExpressionByName);
10055
+ if (!statics) continue;
10056
+ for (const prop of statics.properties ?? []) {
10057
+ const propName = getStaticPropertyNameFromObjectProperty(prop);
10058
+ if (propName) addStaticPropertyName(staticPropertyNames, componentName, propName);
10059
+ }
10060
+ }
10061
+ });
9912
10062
  for (const decl of styledDecls) {
9913
10063
  const baseIdent = getEffectiveBaseIdent(decl);
9914
10064
  if (!baseIdent) continue;
@@ -9917,11 +10067,7 @@ function collectStaticPropsStep(ctx) {
9917
10067
  if (!baseProps || baseProps.length === 0) continue;
9918
10068
  if ((staticPropertyAssignments.get(decl.localName) ?? []).length > 0) continue;
9919
10069
  const inheritanceStatements = [];
9920
- for (const propName of baseProps) {
9921
- const rhs = ctx.j(`const __x = (${baseComponentName} as any).${propName};`).get().node.program.body[0].declarations[0].init;
9922
- const stmt = ctx.j.expressionStatement(ctx.j.assignmentExpression("=", ctx.j.memberExpression(ctx.j.identifier(decl.localName), ctx.j.identifier(propName)), rhs));
9923
- inheritanceStatements.push(stmt);
9924
- }
10070
+ for (const propName of baseProps) inheritanceStatements.push(buildStaticInheritanceStatement(ctx.j, decl.localName, baseComponentName, propName));
9925
10071
  if (inheritanceStatements.length > 0) staticPropertyAssignments.set(decl.localName, inheritanceStatements);
9926
10072
  }
9927
10073
  for (const decl of styledDecls) {
@@ -9967,6 +10113,46 @@ function collectStaticPropsStep(ctx) {
9967
10113
  ctx.staticPropertyNames = staticPropertyNames;
9968
10114
  return CONTINUE;
9969
10115
  }
10116
+ function collectObjectExpressionVariables(root, j) {
10117
+ const objectExpressionByName = /* @__PURE__ */ new Map();
10118
+ root.find(j.VariableDeclarator).forEach((path) => {
10119
+ if (path.node.id?.type === "Identifier" && path.node.init?.type === "ObjectExpression") objectExpressionByName.set(path.node.id.name, path.node.init);
10120
+ });
10121
+ return objectExpressionByName;
10122
+ }
10123
+ function getObjectAssignStaticSource(source, objectExpressionByName) {
10124
+ if (source?.type === "ObjectExpression") return source;
10125
+ if (source?.type === "Identifier" && source.name) return objectExpressionByName.get(source.name) ?? null;
10126
+ return null;
10127
+ }
10128
+ function addStaticPropertyName(staticPropertyNames, componentName, propName) {
10129
+ const names = staticPropertyNames.get(componentName) ?? [];
10130
+ if (!names.includes(propName)) {
10131
+ names.push(propName);
10132
+ staticPropertyNames.set(componentName, names);
10133
+ }
10134
+ }
10135
+ function getStaticPropertyNameFromMemberExpression(memberExpression) {
10136
+ const property = memberExpression.property;
10137
+ if (!memberExpression.computed && property?.type === "Identifier") return property.name ?? null;
10138
+ if ((property?.type === "Literal" || property?.type === "StringLiteral") && typeof property.value === "string") return property.value;
10139
+ return null;
10140
+ }
10141
+ function getStaticPropertyNameFromObjectProperty(prop) {
10142
+ if (!prop || typeof prop !== "object") return null;
10143
+ const property = prop;
10144
+ if (property.type === "SpreadElement" || property.type === "SpreadProperty") return null;
10145
+ const key = property.key;
10146
+ if (!property.computed && key?.type === "Identifier") return key.name ?? null;
10147
+ if ((key?.type === "Literal" || key?.type === "StringLiteral") && typeof key.value === "string") return key.value;
10148
+ return null;
10149
+ }
10150
+ function buildStaticInheritanceStatement(j, componentName, baseComponentName, propName) {
10151
+ return j(`${isIdentifierPropertyName(propName) ? `${componentName}.${propName}` : `(${componentName} as any)[${JSON.stringify(propName)}]`} = ${isIdentifierPropertyName(propName) ? `(${baseComponentName} as any).${propName}` : `(${baseComponentName} as any)[${JSON.stringify(propName)}]`};`).get().node.program.body[0];
10152
+ }
10153
+ function isIdentifierPropertyName(propName) {
10154
+ return /^[$A-Z_a-z][$\w]*$/.test(propName);
10155
+ }
9970
10156
  //#endregion
9971
10157
  //#region src/internal/utilities/ast-safety.ts
9972
10158
  /**
@@ -16466,6 +16652,13 @@ function buildShorthandDefaultPatternProp(j, name, defaultVal) {
16466
16652
  shorthand: true
16467
16653
  });
16468
16654
  }
16655
+ function shouldPassChildrenThroughRest(args) {
16656
+ const { includeChildren, includeRest = false, restId, destructureProps = [], defaultAttrs = [], dynamicAttrs = [], staticAttrs = {} } = args;
16657
+ if (!includeChildren || !includeRest || !restId) return false;
16658
+ if (destructureProps.some((name) => name === "children")) return false;
16659
+ if ([...defaultAttrs, ...dynamicAttrs].some((attr) => attr.attrName === "children" || attr.jsxProp === "children")) return false;
16660
+ return !Object.hasOwn(staticAttrs, "children");
16661
+ }
16469
16662
  function buildDestructurePatternProps(j, patternProp, args) {
16470
16663
  const { baseProps, destructureProps, propDefaults, includeRest = false, restId } = args;
16471
16664
  const patternProps = [...baseProps];
@@ -18197,6 +18390,16 @@ var WrapperEmitter = class {
18197
18390
  const allowForwardedAsProp = this.getUsedAttrs(localName).has("forwardedAs");
18198
18391
  const needsPolymorphicTypeParams = this.emitTypes && (allowAsProp || inlineTypeNeedsElementGeneric(inlineTypeText));
18199
18392
  const propsId = j.identifier("props");
18393
+ let restId = includeRest ? j.identifier("rest") : null;
18394
+ const passChildrenThroughRest = shouldPassChildrenThroughRest({
18395
+ includeChildren: !isVoidTag,
18396
+ includeRest,
18397
+ restId,
18398
+ destructureProps,
18399
+ defaultAttrs,
18400
+ dynamicAttrs,
18401
+ staticAttrs
18402
+ });
18200
18403
  const patternProps = [];
18201
18404
  if (allowAsProp) patternProps.push(j.property.from({
18202
18405
  kind: "init",
@@ -18205,7 +18408,7 @@ var WrapperEmitter = class {
18205
18408
  shorthand: false
18206
18409
  }));
18207
18410
  if (allowForwardedAsProp) patternProps.push(this.patternProp("forwardedAs"));
18208
- if (!isVoidTag) patternProps.push(this.patternProp("children"));
18411
+ if (!isVoidTag && !passChildrenThroughRest) patternProps.push(this.patternProp("children"));
18209
18412
  const shouldForwardRefExplicitly = includeRefProp && !includeRest;
18210
18413
  if (shouldForwardRefExplicitly) patternProps.push(this.patternProp("ref"));
18211
18414
  if (allowClassNameProp) patternProps.push(this.patternProp("className"));
@@ -18217,7 +18420,6 @@ var WrapperEmitter = class {
18217
18420
  }
18218
18421
  for (const a of defaultAttrs) if (!expandedDestructureProps.has(a.jsxProp)) patternProps.push(this.patternProp(a.jsxProp));
18219
18422
  for (const attr of dynamicAttrs) if (!expandedDestructureProps.has(attr.jsxProp)) patternProps.push(this.patternProp(attr.jsxProp));
18220
- let restId = includeRest ? j.identifier("rest") : null;
18221
18423
  if (includeRest && restId) patternProps.push(j.restElement(restId));
18222
18424
  const usePropsDirectlyForRest = includeRest && patternProps.length === 1 && patternProps[0]?.type === "RestElement";
18223
18425
  const useChildrenParamDestructure = this.isChildrenOnlyDestructurePattern(patternProps);
@@ -18281,9 +18483,9 @@ var WrapperEmitter = class {
18281
18483
  if (merging.classNameAttr) jsxAttrs.push(j.jsxAttribute(j.jsxIdentifier("className"), j.jsxExpressionContainer(merging.classNameAttr)));
18282
18484
  if (merging.styleAttr) jsxAttrs.push(j.jsxAttribute(j.jsxIdentifier("style"), j.jsxExpressionContainer(merging.styleAttr)));
18283
18485
  const renderedJsxName = jsxNameFromString(j, allowAsProp ? "Component" : attrsAsTag ?? tagName);
18284
- const openingEl = j.jsxOpeningElement(renderedJsxName, jsxAttrs, isVoidTag);
18486
+ const openingEl = j.jsxOpeningElement(renderedJsxName, jsxAttrs, isVoidTag || passChildrenThroughRest);
18285
18487
  const childrenExpr = j.identifier("children");
18286
- const jsx = j.jsxElement(openingEl, isVoidTag ? null : j.jsxClosingElement(renderedJsxName), isVoidTag ? [] : [j.jsxExpressionContainer(childrenExpr)]);
18488
+ const jsx = j.jsxElement(openingEl, isVoidTag || passChildrenThroughRest ? null : j.jsxClosingElement(renderedJsxName), isVoidTag || passChildrenThroughRest ? [] : [j.jsxExpressionContainer(childrenExpr)]);
18287
18489
  const bodyStmts = [];
18288
18490
  if (!usePropsDirectlyForRest && !useChildrenParamDestructure) bodyStmts.push(j.variableDeclaration("const", [j.variableDeclarator(j.objectPattern(patternProps), propsId)]));
18289
18491
  if (merging.sxDecl) bodyStmts.push(merging.sxDecl);
@@ -18371,6 +18573,9 @@ var WrapperEmitter = class {
18371
18573
  buildDestructurePatternProps(args) {
18372
18574
  return buildDestructurePatternProps(this.j, this.patternProp, args);
18373
18575
  }
18576
+ shouldPassChildrenThroughRest(args) {
18577
+ return shouldPassChildrenThroughRest(args);
18578
+ }
18374
18579
  isChildrenOnlyDestructurePattern(patternProps) {
18375
18580
  return isChildrenOnlyDestructurePattern(patternProps);
18376
18581
  }
@@ -19172,6 +19377,19 @@ function emitComponentWrappers(emitter) {
19172
19377
  node: arg,
19173
19378
  propNames: splicedStyleFnProps
19174
19379
  });
19380
+ const localOnlyPropsTypeText = localOnlyComponentWrapperPropsTypeText({
19381
+ d,
19382
+ emitter,
19383
+ allowClassNameProp,
19384
+ allowStyleProp,
19385
+ exposeSxProp,
19386
+ forceClassNameOptional,
19387
+ forceStyleOptional,
19388
+ functionParamTypeName,
19389
+ isPolymorphicComponentWrapper,
19390
+ shouldLowerForwardedAs
19391
+ });
19392
+ if (localOnlyPropsTypeText) inlineTypeText = localOnlyPropsTypeText;
19175
19393
  const propsParamId = j.identifier("props");
19176
19394
  let polymorphicFnTypeParams = null;
19177
19395
  if (isPolymorphicComponentWrapper && emitTypes) {
@@ -19211,7 +19429,7 @@ function emitComponentWrappers(emitter) {
19211
19429
  const classNameId = j.identifier("className");
19212
19430
  const styleId = j.identifier("style");
19213
19431
  const sxId = j.identifier("sx");
19214
- const restId = j.identifier("rest");
19432
+ let restId = j.identifier("rest");
19215
19433
  const componentId = j.identifier("Component");
19216
19434
  const forwardedAsId = j.identifier("forwardedAs");
19217
19435
  const wrappedComponentExpr = buildWrappedComponentExpr();
@@ -19224,11 +19442,20 @@ function emitComponentWrappers(emitter) {
19224
19442
  const destructureStyle = allowStyleProp && !canForwardClassNameStyleThroughRest;
19225
19443
  const destructureSx = exposeSxProp;
19226
19444
  const destructurePropsForPattern = needsUseTheme ? destructureProps.filter((name) => name !== "theme") : destructureProps;
19445
+ const passChildrenThroughRest = emitter.shouldPassChildrenThroughRest({
19446
+ includeChildren,
19447
+ includeRest: true,
19448
+ restId,
19449
+ destructureProps: destructurePropsForPattern,
19450
+ defaultAttrs,
19451
+ dynamicAttrs,
19452
+ staticAttrs: staticAttrsForJsx
19453
+ });
19227
19454
  const patternProps = emitter.buildDestructurePatternProps({
19228
19455
  baseProps: [
19229
19456
  ...isPolymorphicComponentWrapper ? [j.property("init", j.identifier("as"), j.assignmentPattern(componentId, wrappedComponentExpr))] : [],
19230
19457
  ...destructureClassName ? [patternProp("className", classNameId)] : [],
19231
- ...includeChildren ? [patternProp("children", childrenId)] : [],
19458
+ ...includeChildren && !passChildrenThroughRest ? [patternProp("children", childrenId)] : [],
19232
19459
  ...destructureStyle ? [patternProp("style", styleId)] : [],
19233
19460
  ...destructureSx ? [patternProp("sx", sxId)] : [],
19234
19461
  ...shouldLowerForwardedAs ? [patternProp("forwardedAs", forwardedAsId)] : []
@@ -19238,7 +19465,9 @@ function emitComponentWrappers(emitter) {
19238
19465
  includeRest: true,
19239
19466
  restId
19240
19467
  });
19241
- const declStmt = j.variableDeclaration("const", [j.variableDeclarator(j.objectPattern(patternProps), propsId)]);
19468
+ const usePropsDirectlyForRest = patternProps.length === 1 && patternProps[0]?.type === "RestElement";
19469
+ if (usePropsDirectlyForRest) restId = propsId;
19470
+ const declStmt = usePropsDirectlyForRest ? null : j.variableDeclaration("const", [j.variableDeclarator(j.objectPattern(patternProps), propsId)]);
19242
19471
  const merging = emitStyleMerging({
19243
19472
  j,
19244
19473
  emitter,
@@ -19255,7 +19484,8 @@ function emitComponentWrappers(emitter) {
19255
19484
  wrappedAcceptsSxProp: wrappedAcceptsSx,
19256
19485
  keepStylePropSeparate: shouldKeepStylePropSeparate(renderedComponent)
19257
19486
  });
19258
- const stmts = [declStmt];
19487
+ const stmts = [];
19488
+ if (declStmt) stmts.push(declStmt);
19259
19489
  if (needsUseTheme) stmts.push(buildUseThemeDeclaration(j, emitter.themeHookLocalName));
19260
19490
  if (merging.sxDecl) stmts.push(merging.sxDecl);
19261
19491
  const openingAttrs = [];
@@ -19325,7 +19555,7 @@ function emitComponentWrappers(emitter) {
19325
19555
  const jsx = emitter.buildJsxElement({
19326
19556
  tagName: jsxTagName,
19327
19557
  attrs: openingAttrs,
19328
- includeChildren,
19558
+ includeChildren: includeChildren && !passChildrenThroughRest,
19329
19559
  childrenExpr: childrenId
19330
19560
  });
19331
19561
  stmts.push(j.returnStatement(jsx));
@@ -19371,6 +19601,24 @@ function emitComponentWrappers(emitter) {
19371
19601
  function shouldKeepStylePropSeparate(componentName) {
19372
19602
  return componentName.startsWith("motion.") || componentName.startsWith("animated.");
19373
19603
  }
19604
+ function localOnlyComponentWrapperPropsTypeText(args) {
19605
+ const { d, emitter, allowClassNameProp, allowStyleProp, exposeSxProp, forceClassNameOptional, forceStyleOptional, functionParamTypeName, isPolymorphicComponentWrapper, shouldLowerForwardedAs } = args;
19606
+ if (!emitter.emitTypes || d.isExported || emitter.exportedComponents.has(d.localName) || d.propsType || d.consumerUsesSpread || emitter.isBroadValueUsage(d) || functionParamTypeName || isPolymorphicComponentWrapper || allowClassNameProp || allowStyleProp || exposeSxProp || forceClassNameOptional || forceStyleOptional || shouldLowerForwardedAs || !hasStaticComponentAttrs(d) || hasPropDrivenComponentWrapperBehavior(d) || hasRuntimeAttrsProps(d)) return null;
19607
+ const usedAttrs = emitter.getUsedAttrs(d.localName);
19608
+ if (usedAttrs.has("*") || [...usedAttrs].some((attr) => attr !== "children")) return null;
19609
+ if (!usedAttrs.has("children") && !emitter.hasJsxChildrenUsage(d.localName)) return null;
19610
+ return "{ children?: React.ReactNode }";
19611
+ }
19612
+ function hasStaticComponentAttrs(d) {
19613
+ return Object.keys(d.attrsInfo?.staticAttrs ?? {}).length > 0;
19614
+ }
19615
+ function hasRuntimeAttrsProps(d) {
19616
+ const attrsInfo = d.attrsInfo;
19617
+ return !!((attrsInfo?.defaultAttrs?.length ?? 0) > 0 || (attrsInfo?.dynamicAttrs?.length ?? 0) > 0 || (attrsInfo?.conditionalAttrs?.length ?? 0) > 0 || (attrsInfo?.invertedBoolAttrs?.length ?? 0) > 0 || (attrsInfo?.attrsDynamicStyles?.length ?? 0) > 0 || attrsInfo?.attrsStaticStyleExpr);
19618
+ }
19619
+ function hasPropDrivenComponentWrapperBehavior(d) {
19620
+ return !!(d.enumVariant || d.shouldForwardProp || (d.inlineStyleProps?.length ?? 0) > 0 || (d.styleFnFromProps?.length ?? 0) > 0 || (d.variantDimensions?.length ?? 0) > 0 || (d.compoundVariants?.length ?? 0) > 0 || Object.keys(d.variantStyleKeys ?? {}).length > 0 || (d.transientPropRenames?.size ?? 0) > 0 || (d.observedExpressionConditionDropProps?.size ?? 0) > 0 || (d.styleValueVariantProps?.size ?? 0) > 0);
19621
+ }
19374
19622
  function getExplicitAttrsOmitUnion(args) {
19375
19623
  const { attrsProvidedPropNames, emitter, propsType } = args;
19376
19624
  if (!propsType || attrsProvidedPropNames.size === 0) return null;
@@ -20333,6 +20581,12 @@ function buildAttrWrapperBody(ctx, args) {
20333
20581
  const forwardedAsId = j.identifier("forwardedAs");
20334
20582
  const componentId = j.identifier("Component");
20335
20583
  const sxId = j.identifier("sx");
20584
+ const passChildrenThroughRest = emitter.shouldPassChildrenThroughRest({
20585
+ includeChildren,
20586
+ includeRest: true,
20587
+ restId,
20588
+ destructureProps: [...extraDestructureProps, ...pseudoGuardProps]
20589
+ });
20336
20590
  const baseProps = [
20337
20591
  ...allowAsProp ? [j.property.from({
20338
20592
  kind: "init",
@@ -20343,7 +20597,7 @@ function buildAttrWrapperBody(ctx, args) {
20343
20597
  ...includesForwardedAs ? [ctx.patternProp("forwardedAs", forwardedAsId)] : [],
20344
20598
  ...extraDestructureProps.map((name) => ctx.patternProp(name, j.identifier(name))),
20345
20599
  ...allowClassNameProp ? [ctx.patternProp("className", classNameId)] : [],
20346
- ...includeChildren ? [ctx.patternProp("children", childrenId)] : []
20600
+ ...includeChildren && !passChildrenThroughRest ? [ctx.patternProp("children", childrenId)] : []
20347
20601
  ];
20348
20602
  const patternProps = emitter.buildDestructurePatternProps({
20349
20603
  baseProps,
@@ -20369,7 +20623,7 @@ function buildAttrWrapperBody(ctx, args) {
20369
20623
  const jsx = emitter.buildJsxElement({
20370
20624
  tagName: jsxTag,
20371
20625
  attrs: openingAttrs,
20372
- includeChildren,
20626
+ includeChildren: includeChildren && !passChildrenThroughRest,
20373
20627
  childrenExpr: childrenId
20374
20628
  });
20375
20629
  const fnBodyStmts = [
@@ -20726,6 +20980,15 @@ function emitIntrinsicPolymorphicWrappers(ctx) {
20726
20980
  const sxId = j.identifier("sx");
20727
20981
  const forwardedAsId = j.identifier("forwardedAs");
20728
20982
  if (allowSxProp) styleArgs.push(sxId);
20983
+ const passChildrenThroughRest = emitter.shouldPassChildrenThroughRest({
20984
+ includeChildren,
20985
+ includeRest: true,
20986
+ restId,
20987
+ destructureProps,
20988
+ defaultAttrs: d.attrsInfo?.defaultAttrs ?? [],
20989
+ dynamicAttrs: d.attrsInfo?.dynamicAttrs ?? [],
20990
+ staticAttrs: d.attrsInfo?.staticAttrs ?? {}
20991
+ });
20729
20992
  const patternProps = emitter.buildDestructurePatternProps({
20730
20993
  baseProps: [
20731
20994
  ...allowAsProp ? [j.property.from({
@@ -20736,7 +20999,7 @@ function emitIntrinsicPolymorphicWrappers(ctx) {
20736
20999
  })] : [],
20737
21000
  ...includesForwardedAs ? [ctx.patternProp("forwardedAs", forwardedAsId)] : [],
20738
21001
  ...allowClassNameProp ? [ctx.patternProp("className", classNameId)] : [],
20739
- ...includeChildren ? [ctx.patternProp("children", childrenId)] : [],
21002
+ ...includeChildren && !passChildrenThroughRest ? [ctx.patternProp("children", childrenId)] : [],
20740
21003
  ...allowStyleProp ? [ctx.patternProp("style", styleId)] : [],
20741
21004
  ...allowSxProp ? [ctx.patternProp("sx", sxId)] : []
20742
21005
  ],
@@ -20781,7 +21044,7 @@ function emitIntrinsicPolymorphicWrappers(ctx) {
20781
21044
  const jsx = emitter.buildJsxElement({
20782
21045
  tagName: allowAsProp ? "Component" : tagName,
20783
21046
  attrs,
20784
- includeChildren,
21047
+ includeChildren: includeChildren && !passChildrenThroughRest,
20785
21048
  childrenExpr: childrenId
20786
21049
  });
20787
21050
  const fnBodyStmts = [declStmt];
@@ -21068,12 +21331,21 @@ function emitShouldForwardPropWrappers(ctx) {
21068
21331
  const sxId = j.identifier("sx");
21069
21332
  if (allowSxProp) styleArgs.push(sxId);
21070
21333
  const destructurePartsForPattern = needsUseTheme ? destructureParts.filter((name) => name !== "theme") : destructureParts;
21334
+ const passChildrenThroughRest = emitter.shouldPassChildrenThroughRest({
21335
+ includeChildren,
21336
+ includeRest,
21337
+ restId,
21338
+ destructureProps: destructurePartsForPattern,
21339
+ defaultAttrs: d.attrsInfo?.defaultAttrs ?? [],
21340
+ dynamicAttrs: d.attrsInfo?.dynamicAttrs ?? [],
21341
+ staticAttrs: d.attrsInfo?.staticAttrs ?? {}
21342
+ });
21071
21343
  const patternProps = emitter.buildDestructurePatternProps({
21072
21344
  baseProps: [
21073
21345
  ...allowAsProp ? [asDestructureProp(tagName)] : [],
21074
21346
  ...includesForwardedAs ? [ctx.patternProp("forwardedAs", forwardedAsId)] : [],
21075
21347
  ...allowClassNameProp ? [ctx.patternProp("className", classNameId)] : [],
21076
- ...includeChildren ? [ctx.patternProp("children", childrenId)] : [],
21348
+ ...includeChildren && !passChildrenThroughRest ? [ctx.patternProp("children", childrenId)] : [],
21077
21349
  ...allowStyleProp ? [ctx.patternProp("style", styleId)] : [],
21078
21350
  ...shouldForwardRefExplicitly ? [ctx.patternProp("ref", refId)] : [],
21079
21351
  ...allowSxProp ? [ctx.patternProp("sx", sxId)] : []
@@ -21127,7 +21399,7 @@ function emitShouldForwardPropWrappers(ctx) {
21127
21399
  const jsx = emitter.buildJsxElement({
21128
21400
  tagName: allowAsProp ? "Component" : tagName,
21129
21401
  attrs: openingAttrs,
21130
- includeChildren,
21402
+ includeChildren: includeChildren && !passChildrenThroughRest,
21131
21403
  childrenExpr: childrenId
21132
21404
  });
21133
21405
  const fnBodyStmts = [declStmt];
@@ -21342,11 +21614,20 @@ function emitSimpleWithConfigWrappers(ctx) {
21342
21614
  }
21343
21615
  const sxId = j.identifier("sx");
21344
21616
  if (allowSxProp) styleArgs.push(sxId);
21617
+ const passChildrenThroughRest = emitter.shouldPassChildrenThroughRest({
21618
+ includeChildren: !isVoidTag,
21619
+ includeRest: true,
21620
+ restId,
21621
+ destructureProps: [...pseudoGuardProps],
21622
+ defaultAttrs: d.attrsInfo?.defaultAttrs ?? [],
21623
+ dynamicAttrs: d.attrsInfo?.dynamicAttrs ?? [],
21624
+ staticAttrs: d.attrsInfo?.staticAttrs ?? {}
21625
+ });
21345
21626
  const patternProps = emitter.buildDestructurePatternProps({
21346
21627
  baseProps: [
21347
21628
  ...allowAsProp ? [asDestructureProp(tagName)] : [],
21348
21629
  emitter.patternProp("className", classNameId),
21349
- ...isVoidTag ? [] : [emitter.patternProp("children", childrenId)],
21630
+ ...!isVoidTag && !passChildrenThroughRest ? [emitter.patternProp("children", childrenId)] : [],
21350
21631
  emitter.patternProp("style", styleId),
21351
21632
  ...allowSxProp ? [emitter.patternProp("sx", sxId)] : []
21352
21633
  ],
@@ -21382,8 +21663,8 @@ function emitSimpleWithConfigWrappers(ctx) {
21382
21663
  })
21383
21664
  ];
21384
21665
  emitter.appendMergingAttrs(openingAttrs, merging);
21385
- const openingEl = j.jsxOpeningElement(j.jsxIdentifier(allowAsProp ? "Component" : tagName), openingAttrs, false);
21386
- const jsx = isVoidTag ? {
21666
+ const openingEl = j.jsxOpeningElement(j.jsxIdentifier(allowAsProp ? "Component" : tagName), openingAttrs, isVoidTag || passChildrenThroughRest);
21667
+ const jsx = isVoidTag || passChildrenThroughRest ? {
21387
21668
  type: "JSXElement",
21388
21669
  openingElement: {
21389
21670
  ...openingEl,
@@ -21675,13 +21956,22 @@ function emitSimpleExportedIntrinsicWrappers(ctx) {
21675
21956
  const styleId = j.identifier("style");
21676
21957
  const sxId = j.identifier("sx");
21677
21958
  const refId = j.identifier("ref");
21678
- const restId = shouldIncludeRest ? j.identifier("rest") : null;
21959
+ let restId = shouldIncludeRest ? j.identifier("rest") : null;
21679
21960
  const shouldForwardRefExplicitly = !restId && ((d.supportsRefProp ?? false) || willForwardRef);
21680
21961
  const forwardedAsId = j.identifier("forwardedAs");
21681
21962
  if (allowSxProp) styleArgs.push(sxId);
21682
21963
  for (const attr of d.attrsInfo?.defaultAttrs ?? []) if (!destructureProps.includes(attr.jsxProp)) destructureProps.push(attr.jsxProp);
21683
21964
  for (const attr of d.attrsInfo?.dynamicAttrs ?? []) if (!destructureProps.includes(attr.jsxProp)) destructureProps.push(attr.jsxProp);
21684
21965
  const destructurePropsForPattern = needsUseTheme ? destructureProps.filter((name) => name !== "theme") : destructureProps;
21966
+ const passChildrenThroughRest = emitter.shouldPassChildrenThroughRest({
21967
+ includeChildren,
21968
+ includeRest: Boolean(restId),
21969
+ restId,
21970
+ destructureProps: destructurePropsForPattern,
21971
+ defaultAttrs: d.attrsInfo?.defaultAttrs ?? [],
21972
+ dynamicAttrs: d.attrsInfo?.dynamicAttrs ?? [],
21973
+ staticAttrs: d.attrsInfo?.staticAttrs ?? {}
21974
+ });
21685
21975
  const patternProps = emitter.buildDestructurePatternProps({
21686
21976
  baseProps: [
21687
21977
  ...useAsProp ? [j.property.from({
@@ -21692,7 +21982,7 @@ function emitSimpleExportedIntrinsicWrappers(ctx) {
21692
21982
  })] : [],
21693
21983
  ...includesForwardedAs ? [ctx.patternProp("forwardedAs", forwardedAsId)] : [],
21694
21984
  ...allowClassNameProp ? [ctx.patternProp("className", classNameId)] : [],
21695
- ...includeChildren ? [ctx.patternProp("children", childrenId)] : [],
21985
+ ...includeChildren && !passChildrenThroughRest ? [ctx.patternProp("children", childrenId)] : [],
21696
21986
  ...allowStyleProp ? [ctx.patternProp("style", styleId)] : [],
21697
21987
  ...shouldForwardRefExplicitly ? [ctx.patternProp("ref", refId)] : [],
21698
21988
  ...allowSxProp ? [ctx.patternProp("sx", sxId)] : []
@@ -21702,10 +21992,12 @@ function emitSimpleExportedIntrinsicWrappers(ctx) {
21702
21992
  includeRest: Boolean(restId),
21703
21993
  restId: restId ?? void 0
21704
21994
  });
21995
+ const usePropsDirectlyForRest = Boolean(restId) && patternProps.length === 1 && patternProps[0]?.type === "RestElement";
21996
+ if (usePropsDirectlyForRest) restId = propsId;
21705
21997
  const usePropsChildrenDirectly = emitter.isChildrenOnlyDestructurePattern(patternProps);
21706
21998
  const propsParam = usePropsChildrenDirectly ? emitter.buildChildrenOnlyParam(inlineTypeText ?? emitter.propsTypeNameFor(d.localName)) : j.identifier("props");
21707
21999
  if (!usePropsChildrenDirectly) emitter.annotatePropsParam(propsParam, d.localName, inlineTypeText);
21708
- const declStmt = usePropsChildrenDirectly ? null : j.variableDeclaration("const", [j.variableDeclarator(j.objectPattern(patternProps), propsId)]);
22000
+ const declStmt = usePropsChildrenDirectly || usePropsDirectlyForRest ? null : j.variableDeclaration("const", [j.variableDeclarator(j.objectPattern(patternProps), propsId)]);
21709
22001
  const { attrsInfo, staticClassNameExpr } = emitter.splitAttrsInfo(d.attrsInfo, getBridgeClassVar(d), d.extraClassNames);
21710
22002
  const { attrsInfo: attrsInfoWithoutForwardedAsStatic, forwardedAsStaticFallback } = splitForwardedAsStaticAttrs({
21711
22003
  attrsInfo,
@@ -21742,7 +22034,7 @@ function emitSimpleExportedIntrinsicWrappers(ctx) {
21742
22034
  const jsx = emitter.buildJsxElement({
21743
22035
  tagName: useAsProp ? "Component" : tagName,
21744
22036
  attrs: openingAttrs,
21745
- includeChildren,
22037
+ includeChildren: includeChildren && !passChildrenThroughRest,
21746
22038
  childrenExpr: childrenId
21747
22039
  });
21748
22040
  const bodyStmts = [];
@@ -22394,7 +22686,8 @@ function extractCssHelpersStep(ctx) {
22394
22686
  styledImports,
22395
22687
  cssLocal,
22396
22688
  toStyleKey,
22397
- preserveDeclarationOnlyNames: collectCssHelpersUsedBySkippedImportedRoots(ctx)
22689
+ preserveDeclarationOnlyNames: collectCssHelpersUsedBySkippedImportedRoots(ctx),
22690
+ preservedStyledComponentSelectorNames: collectSkippedImportedRootStyledComponentNames(ctx)
22398
22691
  });
22399
22692
  if (cssHelpers.unsupportedCssUsages.length > 0) return returnResult({
22400
22693
  code: null,
@@ -22404,6 +22697,26 @@ function extractCssHelpersStep(ctx) {
22404
22697
  if (cssHelpers.changed) ctx.markChanged();
22405
22698
  return CONTINUE;
22406
22699
  }
22700
+ function collectSkippedImportedRootStyledComponentNames(ctx) {
22701
+ if (ctx.options.allowPartialMigration !== true || ctx.options.transformMode === "leavesOnly") return /* @__PURE__ */ new Set();
22702
+ const names = /* @__PURE__ */ new Set();
22703
+ ctx.root.find(ctx.j.VariableDeclarator).forEach((path) => {
22704
+ const id = path.node.id;
22705
+ if (id.type !== "Identifier") return;
22706
+ if (initializerWrapsImportedComponent(ctx, path.node.init)) names.add(id.name);
22707
+ });
22708
+ return names;
22709
+ }
22710
+ function initializerWrapsImportedComponent(ctx, init) {
22711
+ const node = init;
22712
+ if (!node) return false;
22713
+ if (node.type === "TaggedTemplateExpression") return tagWrapsImportedComponent(ctx, node.tag);
22714
+ if (node.type === "CallExpression") {
22715
+ const callee = node.callee;
22716
+ return callee?.type === "TaggedTemplateExpression" && tagWrapsImportedComponent(ctx, callee.tag);
22717
+ }
22718
+ return false;
22719
+ }
22407
22720
  function collectCssHelpersUsedBySkippedImportedRoots(ctx) {
22408
22721
  if (ctx.options.allowPartialMigration !== true || ctx.options.transformMode === "leavesOnly") return /* @__PURE__ */ new Set();
22409
22722
  if ((ctx.importMap ?? /* @__PURE__ */ new Map()).size === 0) return /* @__PURE__ */ new Set();
@@ -26206,6 +26519,17 @@ function createCssHelperResolver(args) {
26206
26519
  if (!resolved && hasThemeAccessInExpr(expr, paramName)) return bail("Conditional `css` block: failed to parse expression", { property: d.property }, exprLoc);
26207
26520
  if (resolved) if (hasStaticParts) {
26208
26521
  const { prefix, suffix } = extractPrefixSuffix(parts);
26522
+ const borderParts = parseInterpolatedBorderStaticParts({
26523
+ prop: d.property.trim(),
26524
+ prefix,
26525
+ suffix
26526
+ });
26527
+ if (borderParts) {
26528
+ if (borderParts.width) target[borderParts.widthProp] = mergeIntoContext(borderParts.width, borderParts.widthProp, target);
26529
+ if (borderParts.style) target[borderParts.styleProp] = mergeIntoContext(borderParts.style, borderParts.styleProp, target);
26530
+ target[borderParts.colorProp] = mergeIntoContext(resolved.ast, borderParts.colorProp, target);
26531
+ continue;
26532
+ }
26209
26533
  const templateAst = parseExpr(wrapExprWithStaticParts(resolved.exprString, prefix, suffix));
26210
26534
  if (templateAst) {
26211
26535
  for (const mapped of cssDeclarationToStylexDeclarations(d)) target[mapped.prop] = mergeIntoContext(templateAst, mapped.prop, target);
@@ -31847,26 +32171,23 @@ function tryHandleInterpolatedBorder(ctx, args) {
31847
32171
  if (!hasStaticWidthOrStyle) {
31848
32172
  const parsedTpl = parseTemplateLiteralBorderShorthand(resolved.exprAst);
31849
32173
  if (parsedTpl) {
31850
- if (selector.trim() !== "&" || (atRuleStack ?? []).length > 0) {
31851
- if (parsedTpl.width) applyResolvedPropValue(widthProp, parsedTpl.width);
31852
- if (parsedTpl.style) applyResolvedPropValue(styleProp, parsedTpl.style);
31853
- applyResolvedPropValue(colorProp, parsedTpl.colorExpr);
31854
- return true;
31855
- }
31856
- const fullProp = direction ? `border${direction}` : "border";
31857
- const extraKey = styleKeyWithSuffix(decl.styleKey, fullProp);
31858
- const bucket = extraStyleObjects.get(extraKey) ?? {};
31859
- if (parsedTpl.width) bucket[widthProp] = parsedTpl.width;
31860
- if (parsedTpl.style) bucket[styleProp] = parsedTpl.style;
31861
- bucket[colorProp] = parsedTpl.colorExpr;
31862
- extraStyleObjects.set(extraKey, bucket);
31863
- decl.extraStylexPropsArgs ??= [];
31864
- const afterVariants = Object.keys(variantStyleKeys).length > 0;
31865
- decl.extraStylexPropsArgs.push({
31866
- expr: j.memberExpression(j.identifier("styles"), j.identifier(extraKey)),
31867
- ...afterVariants ? { afterVariants } : {}
31868
- });
31869
- decl.needsWrapperComponent = true;
32174
+ const expandedBorderEntries = [];
32175
+ if (parsedTpl.width) expandedBorderEntries.push([widthProp, parsedTpl.width]);
32176
+ if (parsedTpl.style) expandedBorderEntries.push([styleProp, parsedTpl.style]);
32177
+ expandedBorderEntries.push([colorProp, parsedTpl.colorExpr]);
32178
+ if (selector.trim() === "&" && (atRuleStack ?? []).length === 0 && hasConflictingEarlierVariant(Array.from(variantBuckets.values()), expandedBorderEntries)) {
32179
+ const fullProp = direction ? `border${direction}` : "border";
32180
+ const extraKey = styleKeyWithSuffix(decl.styleKey, fullProp);
32181
+ const bucket = extraStyleObjects.get(extraKey) ?? {};
32182
+ for (const [entryProp, entryValue] of expandedBorderEntries) bucket[entryProp] = entryValue;
32183
+ extraStyleObjects.set(extraKey, bucket);
32184
+ decl.extraStylexPropsArgs ??= [];
32185
+ decl.extraStylexPropsArgs.push({
32186
+ expr: j.memberExpression(j.identifier("styles"), j.identifier(extraKey)),
32187
+ afterVariants: true
32188
+ });
32189
+ decl.needsWrapperComponent = true;
32190
+ } else for (const [entryProp, entryValue] of expandedBorderEntries) applyResolvedPropValue(entryProp, entryValue);
31870
32191
  bumpResolverImportToEnd((spec) => {
31871
32192
  const from = spec?.from;
31872
32193
  const names = spec?.names;
@@ -31950,6 +32271,25 @@ function classifyBorderSlotRole(ast) {
31950
32271
  if ((node.type === "StringLiteral" || node.type === "Literal") && typeof node.value === "string") return looksLikeLength(node.value) ? "width" : "color";
31951
32272
  return null;
31952
32273
  }
32274
+ function hasConflictingEarlierVariant(variantBuckets, borderEntries) {
32275
+ const borderProps = borderEntries.map(([prop]) => prop);
32276
+ return variantBuckets.some((bucket) => Object.keys(bucket).some((variantProp) => borderProps.some((borderProp) => borderLonghandsConflict(variantProp, borderProp))));
32277
+ }
32278
+ function borderLonghandsConflict(left, right) {
32279
+ if (left === right) return true;
32280
+ const leftParts = parseBorderLonghand(left);
32281
+ const rightParts = parseBorderLonghand(right);
32282
+ if (!leftParts || !rightParts || leftParts.aspect !== rightParts.aspect) return false;
32283
+ return leftParts.side === null || rightParts.side === null || leftParts.side === rightParts.side;
32284
+ }
32285
+ function parseBorderLonghand(prop) {
32286
+ const match = prop.match(/^border(?:(Top|Right|Bottom|Left))?(Width|Style|Color)$/);
32287
+ if (!match) return null;
32288
+ return {
32289
+ side: match[1] ?? null,
32290
+ aspect: match[2]
32291
+ };
32292
+ }
31953
32293
  //#endregion
31954
32294
  //#region src/internal/lower-rules/interpolated-variant-resolvers.ts
31955
32295
  function handleSplitVariantsResolvedValue(ctx) {
@@ -32497,14 +32837,14 @@ function handleInlineStyleValueFromProps(ctx) {
32497
32837
  const valueExpr = prefix || suffix ? buildTemplateWithStaticParts(j, baseExpr, prefix, suffix) : baseExpr;
32498
32838
  const outs = cssDeclarationToStylexDeclarations(d);
32499
32839
  if (outs.every((out) => out.prop && !isStylexShorthandCamelCase(out.prop))) {
32500
- const baseKeyAvailable = outs.length === 1 && Object.keys(styleObj).length === 0 && !styleFnDecls.has(decl.styleKey);
32840
+ const baseKeyAvailable = outs.length === 1 && Object.keys(styleObj).length === 0 && !declarationHasFollowingStaticBaseStyles(decl, d) && !styleFnDecls.has(decl.styleKey);
32501
32841
  for (const out of outs) {
32502
32842
  if (!out.prop) continue;
32503
32843
  const fnKey = baseKeyAvailable ? decl.styleKey : styleKeyWithSuffix(decl.styleKey, out.prop);
32504
32844
  if (!styleFnDecls.has(fnKey)) {
32505
32845
  const paramName = cssPropertyToIdentifier(out.prop, ctx.avoidNames);
32506
32846
  const param = j.identifier(paramName);
32507
- if (/\.(ts|tsx)$/.test(filePath)) param.typeAnnotation = j.tsTypeAnnotation(j.tsUnionType([j.tsStringKeyword(), j.tsUndefinedKeyword()]));
32847
+ if (/\.(ts|tsx)$/.test(filePath)) param.typeAnnotation = j.tsTypeAnnotation(inferStyleFnParamType(j, out.prop, valueExpr));
32508
32848
  const propKey = makeCssPropKey(j, out.prop);
32509
32849
  const p = j.property("init", propKey, j.identifier(paramName));
32510
32850
  p.shorthand = propKey.type === "Identifier" && paramName === out.prop;
@@ -32573,6 +32913,54 @@ function handleInlineStyleValueFromProps(ctx) {
32573
32913
  function hasSimpleIdentifierParam(expr) {
32574
32914
  return expr.params?.length === 1 && expr.params[0]?.type === "Identifier";
32575
32915
  }
32916
+ function declarationHasFollowingStaticBaseStyles(decl, current) {
32917
+ for (const rule of decl.rules ?? []) {
32918
+ const index = rule.declarations.indexOf(current);
32919
+ if (index < 0) continue;
32920
+ return rule.declarations.slice(index + 1).some((next) => next.value.kind === "static");
32921
+ }
32922
+ return false;
32923
+ }
32924
+ function inferStyleFnParamType(j, stylexProp, callArg) {
32925
+ if (callArg.type === "TemplateLiteral" && expressionHasNullishFallback(callArg)) return j.tsStringKeyword();
32926
+ if (expressionHasNullishFallback(callArg) && NUMERIC_STYLEX_PROPS.has(stylexProp)) {
32927
+ if (getNullishFallbackType(callArg) !== "number") return j.tsUnionType([j.tsNumberKeyword(), j.tsStringKeyword()]);
32928
+ return j.tsNumberKeyword();
32929
+ }
32930
+ return j.tsUnionType([j.tsStringKeyword(), j.tsUndefinedKeyword()]);
32931
+ }
32932
+ const NUMERIC_STYLEX_PROPS = new Set([
32933
+ "zIndex",
32934
+ "opacity",
32935
+ "flexGrow",
32936
+ "flexShrink",
32937
+ "order"
32938
+ ]);
32939
+ function getNullishFallbackType(expr) {
32940
+ if (!expr || typeof expr !== "object") return null;
32941
+ const node = expr;
32942
+ if (node.type === "LogicalExpression" && node.operator === "??") return getExpressionPrimitiveType(node.right);
32943
+ if (node.type === "TemplateLiteral") for (const templateExpr of node.expressions ?? []) {
32944
+ const fallbackType = getNullishFallbackType(templateExpr);
32945
+ if (fallbackType) return fallbackType;
32946
+ }
32947
+ return null;
32948
+ }
32949
+ function getExpressionPrimitiveType(expr) {
32950
+ if (!expr || typeof expr !== "object") return "unknown";
32951
+ const node = expr;
32952
+ if (node.type === "NumericLiteral" || node.type === "Literal" && typeof node.value === "number") return "number";
32953
+ if (node.type === "StringLiteral" || node.type === "Literal" && typeof node.value === "string") return "string";
32954
+ if (node.type === "TemplateLiteral") return "string";
32955
+ return "unknown";
32956
+ }
32957
+ function expressionHasNullishFallback(expr) {
32958
+ if (!expr || typeof expr !== "object") return false;
32959
+ const node = expr;
32960
+ if (node.type === "LogicalExpression" && node.operator === "??") return true;
32961
+ if (node.type === "TemplateLiteral") return (node.expressions ?? []).some(expressionHasNullishFallback);
32962
+ return false;
32963
+ }
32576
32964
  /**
32577
32965
  * Emit one `${key}FromProps` style function entry per longhand expansion of
32578
32966
  * `d`, keyed by the StyleX prop name and wrapped in pseudo/media buckets.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "styled-components-to-stylex-codemod",
3
- "version": "0.0.47",
3
+ "version": "0.0.48",
4
4
  "description": "Codemod to transform styled-components to StyleX",
5
5
  "keywords": [
6
6
  "codemod",