styled-components-to-stylex-codemod 0.0.20 → 0.0.21
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/index.d.mts
CHANGED
|
@@ -613,7 +613,7 @@ declare function defineAdapter<T extends AdapterInput>(adapter: T): T;
|
|
|
613
613
|
//#endregion
|
|
614
614
|
//#region src/internal/logger.d.ts
|
|
615
615
|
type Severity = "info" | "warning" | "error";
|
|
616
|
-
type WarningType = "`css` helper function switch must return css templates in all branches" | "`css` helper usage as a function call (css(...)) is not supported" | "`css` helper used outside of a styled component template cannot be statically transformed" | "Adapter helper call in border interpolation did not resolve to a single CSS value" | "Adapter resolveCall returned an unparseable styles expression" | "Adapter resolveCall returned an unparseable value expression" | "Adapter resolveCall returned StyleX styles for helper call where a CSS value was expected" | "Adapter resolveCall returned undefined for helper call" | "Adapter resolveBaseComponent threw an error" | "Adapter resolved StyleX styles cannot be applied under nested selectors/at-rules" | "Adapter resolved StyleX styles inside pseudo selector but did not provide cssText for property expansion — add cssText to resolveCall result to enable pseudo-wrapping" | 'Adapter resolveCall cssText could not be parsed as CSS declarations — expected semicolon-separated property: value pairs (e.g. "white-space: nowrap; overflow: hidden;")' | "Adapter resolveValue returned an unparseable value expression" | "Adapter resolveValue returned undefined for imported value" | "Arrow function: body is not a recognized pattern (expected ternary, logical, call, or member expression)" | "Arrow function: conditional branches could not be resolved to static or theme values" | "Arrow function: helper call body is not supported" | "Arrow function: indexed theme lookup pattern not matched" | "Arrow function: logical expression pattern not supported" | "Arrow function: prop access cannot be converted to style function for this CSS property" | "Arrow function: theme access path could not be resolved" | "Component selectors like `${OtherComponent}:hover &` are not directly representable in StyleX. Manual refactor is required" | "Conditional `css` block: !important is not supported in StyleX" | "Conditional `css` block: @-rules (e.g., @media, @supports) are not supported" | "CSS block contains unsupported at-rule (only @media and @container are supported; @supports, etc. require manual handling)" | "Conditional `css` block: dynamic interpolation could not be resolved to a single component prop" | "Conditional `css` block: failed to parse expression" | "Conditional `css` block: missing CSS property name" | "Conditional `css` block: missing interpolation expression" | "Conditional `css` block: mixed static/dynamic values with non-theme expressions cannot be safely transformed" | "Conditional `css` block: multiple interpolation slots in a single property value" | "Conditional `css` block: ternary branch value could not be resolved (imported values require adapter support)" | "Conditional `css` block: ternary expressions inside pseudo selectors are not supported" | "Conditional `css` block: unsupported selector" | "Directional border helper styles are not supported" | "Multi-slot border interpolation could not be resolved" | "createGlobalStyle is not supported in StyleX. Global styles should be handled separately (e.g., in a CSS file or using CSS reset libraries)" | "Dynamic styles inside pseudo elements (::before/::after) are not supported by StyleX. See https://github.com/facebook/stylex/issues/1396" | "Failed to parse theme expressions" | "Heterogeneous background values (mix of gradients and colors) not currently supported" | "Higher-order styled factory wrappers (e.g. hoc(styled)) are not supported" | "Imported CSS helper mixins: cannot determine inherited properties for correct pseudo selector handling" | "Local helper function returns CSS that cannot be decomposed into individual properties" | "Local helper function computes CSS values that cannot be statically traced to the component prop" | "Styled-components specificity hacks like `&&` / `&&&` are not representable in StyleX" | "Theme-dependent block-level conditional could not be fully resolved (branches may contain dynamic interpolations)" | "Theme-dependant call expression could not be resolved (e.g. theme helper calls like theme.highlight() are not supported)" | "Theme value with fallback (props.theme.X ?? / || default) cannot be resolved statically — use adapter.resolveValue to map theme paths to StyleX tokens" | "Theme-dependent nested prop access requires a project-specific theme source (e.g. useTheme())" | "Theme-dependent template literals require a project-specific theme source (e.g. useTheme())" | "Theme prop overrides on styled components are not supported" | "Universal selectors (`*`) are currently unsupported" | "Unsupported call expression (expected imported helper(...) or imported helper(...)(...))" | "Unsupported conditional test in shouldForwardProp" | "Unsupported shouldForwardProp pattern (only !prop.startsWith(), ![].includes(prop), and prop !== are supported)" | "Unsupported interpolation: arrow function" | "Unsupported interpolation: call expression" | "Unsupported interpolation: identifier" | "Unsupported interpolation: member expression" | "Unsupported interpolation: property" | "Unsupported interpolation: unknown" | "Unsupported nested conditional interpolation" | "Unsupported prop-based inline style expression cannot be safely inlined" | "Unsupported prop-based inline style props.theme access is not supported" | "Unsupported selector interpolation: imported value in selector position" | "Unsupported selector: class selector" | "Unsupported selector: comma-separated selectors must all be simple pseudos or pseudo-elements" | "Unsupported selector: descendant pseudo selector (space before pseudo)" | "Unsupported selector: descendant/child/sibling selector" | "Unsupported selector: interpolated pseudo selector" | "Unsupported selector: sibling combinator" | "Unsupported selector: unresolved interpolation in sibling selector" | "Unsupported selector: ambiguous element selector" | "Unsupported selector: attribute selector on unsupported element" | "Unsupported selector: element selector on exported component" | "Unsupported selector: element selector with combined ancestor and child pseudos" | "Unsupported selector: element selector with dynamic children" | "Unsupported selector: element selector with plain intrinsic children" | "Unsupported selector: element selector pseudo collision" | "Unsupported selector: unresolved interpolation in cross-file component selector" | "Unsupported selector: unresolved interpolation in descendant component selector" | "Unsupported selector: unresolved interpolation in element selector" | "Unsupported selector: unresolved interpolation in reverse component selector" | "Unsupported selector: grouped reverse selector references different components" | "Unsupported selector: unknown component selector" | "Unsupported css`` mixin: after-base mixin style is not a plain object" | "Unsupported css`` mixin: nested contextual conditions in after-base mixin" | "Unsupported css`` mixin: cannot infer base default for after-base contextual override (base value is non-literal)" | "css`` helper function interpolation references closure variable that cannot be hoisted" | "Sibling selector broadened: & + & (adjacent) becomes general sibling (~) in StyleX — interleaved non-matching elements will no longer block the match" | "Using styled-components components as mixins is not supported; use css`` mixins or strings instead" | "styled(ImportedComponent) wraps a component whose file contains internal styled-components — convert the base component's file first to avoid CSS cascade conflicts";
|
|
616
|
+
type WarningType = "`css` helper function switch must return css templates in all branches" | "`css` helper usage as a function call (css(...)) is not supported" | "`css` helper used outside of a styled component template cannot be statically transformed" | "Adapter helper call in border interpolation did not resolve to a single CSS value" | "Adapter resolveCall returned an unparseable styles expression" | "Adapter resolveCall returned an unparseable value expression" | "Adapter resolveCall returned StyleX styles for helper call where a CSS value was expected" | "Adapter resolveCall returned undefined for helper call" | "Adapter resolveBaseComponent threw an error" | "Adapter resolved StyleX styles cannot be applied under nested selectors/at-rules" | "Adapter resolved StyleX styles inside pseudo selector but did not provide cssText for property expansion — add cssText to resolveCall result to enable pseudo-wrapping" | 'Adapter resolveCall cssText could not be parsed as CSS declarations — expected semicolon-separated property: value pairs (e.g. "white-space: nowrap; overflow: hidden;")' | "Adapter resolveValue returned an unparseable value expression" | "Adapter resolveValue returned undefined for imported value" | "Arrow function: body is not a recognized pattern (expected ternary, logical, call, or member expression)" | "Arrow function: conditional branches could not be resolved to static or theme values" | "Arrow function: helper call body is not supported" | "Arrow function: indexed theme lookup pattern not matched" | "Arrow function: logical expression pattern not supported" | "Arrow function: prop access cannot be converted to style function for this CSS property" | "Arrow function: theme access path could not be resolved" | "Component selectors like `${OtherComponent}:hover &` are not directly representable in StyleX. Manual refactor is required" | "Conditional `css` block: !important is not supported in StyleX" | "Conditional `css` block: @-rules (e.g., @media, @supports) are not supported" | "CSS block contains unsupported at-rule (only @media and @container are supported; @supports, etc. require manual handling)" | "Conditional `css` block: dynamic interpolation could not be resolved to a single component prop" | "Conditional `css` block: failed to parse expression" | "Conditional `css` block: missing CSS property name" | "Conditional `css` block: missing interpolation expression" | "Conditional `css` block: mixed static/dynamic values with non-theme expressions cannot be safely transformed" | "Conditional `css` block: multiple interpolation slots in a single property value" | "Conditional `css` block: ternary branch value could not be resolved (imported values require adapter support)" | "Conditional `css` block: ternary expressions inside pseudo selectors are not supported" | "Conditional `css` block: media query contains unresolvable interpolation" | "Conditional `css` block: unsupported selector" | "Directional border helper styles are not supported" | "Multi-slot border interpolation could not be resolved" | "Resolved border helper value could not be expanded to longhand properties" | "createGlobalStyle is not supported in StyleX. Global styles should be handled separately (e.g., in a CSS file or using CSS reset libraries)" | "Dynamic styles inside pseudo elements (::before/::after) are not supported by StyleX. See https://github.com/facebook/stylex/issues/1396" | "Failed to parse theme expressions" | "Heterogeneous background values (mix of gradients and colors) not currently supported" | "Higher-order styled factory wrappers (e.g. hoc(styled)) are not supported" | "Imported CSS helper mixins: cannot determine inherited properties for correct pseudo selector handling" | "Local helper function returns CSS that cannot be decomposed into individual properties" | "Local helper function computes CSS values that cannot be statically traced to the component prop" | "Styled-components specificity hacks like `&&` / `&&&` are not representable in StyleX" | "Theme-dependent block-level conditional could not be fully resolved (branches may contain dynamic interpolations)" | "Theme-dependant call expression could not be resolved (e.g. theme helper calls like theme.highlight() are not supported)" | "Theme value with fallback (props.theme.X ?? / || default) cannot be resolved statically — use adapter.resolveValue to map theme paths to StyleX tokens" | "Theme-dependent nested prop access requires a project-specific theme source (e.g. useTheme())" | "Theme-dependent template literals require a project-specific theme source (e.g. useTheme())" | "Theme prop overrides on styled components are not supported" | "Universal selectors (`*`) are currently unsupported" | "Unsupported call expression (expected imported helper(...) or imported helper(...)(...))" | "Unsupported conditional test in shouldForwardProp" | "Unsupported shouldForwardProp pattern (only !prop.startsWith(), ![].includes(prop), and prop !== are supported)" | "Unsupported interpolation: arrow function" | "Unsupported interpolation: call expression" | "Unsupported interpolation: identifier" | "Unsupported interpolation: member expression" | "Unsupported interpolation: property" | "Unsupported interpolation: unknown" | "Unsupported nested conditional interpolation" | "Unsupported prop-based inline style expression cannot be safely inlined" | "Unsupported prop-based inline style props.theme access is not supported" | "Unsupported selector interpolation: imported value in selector position" | "Unsupported: media query contains unresolvable interpolation" | "Unsupported selector: class selector" | "Unsupported selector: comma-separated selectors must all be simple pseudos or pseudo-elements" | "Unsupported selector: descendant pseudo selector (space before pseudo)" | "Unsupported selector: descendant/child/sibling selector" | "Unsupported selector: interpolated pseudo selector" | "Unsupported selector: sibling combinator" | "Unsupported selector: unresolved interpolation in sibling selector" | "Unsupported selector: ambiguous element selector" | "Unsupported selector: attribute selector on unsupported element" | "Unsupported selector: element selector on exported component" | "Unsupported selector: element selector with combined ancestor and child pseudos" | "Unsupported selector: element selector with dynamic children" | "Unsupported selector: element selector with plain intrinsic children" | "Unsupported selector: element selector pseudo collision" | "Unsupported selector: unresolved interpolation in cross-file component selector" | "Unsupported selector: unresolved interpolation in descendant component selector" | "Unsupported selector: unresolved interpolation in element selector" | "Unsupported selector: unresolved interpolation in reverse component selector" | "Unsupported selector: grouped reverse selector references different components" | "Unsupported selector: unknown component selector" | "Unsupported css`` mixin: after-base mixin style is not a plain object" | "Unsupported css`` mixin: nested contextual conditions in after-base mixin" | "Unsupported css`` mixin: cannot infer base default for after-base contextual override (base value is non-literal)" | "css`` helper function interpolation references closure variable that cannot be hoisted" | "Sibling selector broadened: & + & (adjacent) becomes general sibling (~) in StyleX — interleaved non-matching elements will no longer block the match" | "Using styled-components components as mixins is not supported; use css`` mixins or strings instead" | "styled(ImportedComponent) wraps a component whose file contains internal styled-components — convert the base component's file first to avoid CSS cascade conflicts";
|
|
617
617
|
interface WarningLog {
|
|
618
618
|
severity: Severity;
|
|
619
619
|
type: WarningType;
|
package/dist/transform.d.mts
CHANGED
package/dist/transform.mjs
CHANGED
|
@@ -1600,12 +1600,12 @@ function analyzeBeforeEmitStep(ctx) {
|
|
|
1600
1600
|
};
|
|
1601
1601
|
if (!ctx.stylesInsertPosition && isUsedAtModuleLevel()) ctx.stylesInsertPosition = "afterImports";
|
|
1602
1602
|
if (ctx.resolvedStyleObjects) for (const decl of styledDecls) {
|
|
1603
|
-
if (
|
|
1604
|
-
for (const { propName, styleKey, styles } of decl.staticBooleanVariants) {
|
|
1603
|
+
if (decl.staticBooleanVariants?.length) for (const { propName, styleKey, styles } of decl.staticBooleanVariants) {
|
|
1605
1604
|
ctx.resolvedStyleObjects.set(styleKey, styles);
|
|
1606
1605
|
if (!decl.variantStyleKeys) decl.variantStyleKeys = {};
|
|
1607
1606
|
decl.variantStyleKeys[propName] = styleKey;
|
|
1608
1607
|
}
|
|
1608
|
+
if (decl.callSiteCombinedStyles?.length) for (const { styleKey, styles } of decl.callSiteCombinedStyles) ctx.resolvedStyleObjects.set(styleKey, styles);
|
|
1609
1609
|
}
|
|
1610
1610
|
return CONTINUE;
|
|
1611
1611
|
}
|
|
@@ -6439,7 +6439,8 @@ function emptyOkVariantOutcome(hasLocalCallsites, usedConsumedPropsAtCallSites)
|
|
|
6439
6439
|
usedConsumedPropsAtCallSites,
|
|
6440
6440
|
foldedBaseSx: {},
|
|
6441
6441
|
bakedInConsumedProps: [],
|
|
6442
|
-
staticBooleanVariants: []
|
|
6442
|
+
staticBooleanVariants: [],
|
|
6443
|
+
callSiteCombinedStyles: []
|
|
6443
6444
|
};
|
|
6444
6445
|
}
|
|
6445
6446
|
function applyBaseComponentResolution(ctx, styledDecls) {
|
|
@@ -6490,7 +6491,8 @@ function applyBaseComponentResolution(ctx, styledDecls) {
|
|
|
6490
6491
|
usedConsumedPropsAtCallSites: variantOutcome.usedConsumedPropsAtCallSites,
|
|
6491
6492
|
foldedBaseSx: variantOutcome.foldedBaseSx,
|
|
6492
6493
|
bakedInConsumedProps: variantOutcome.bakedInConsumedProps,
|
|
6493
|
-
staticBooleanVariants: variantOutcome.staticBooleanVariants
|
|
6494
|
+
staticBooleanVariants: variantOutcome.staticBooleanVariants,
|
|
6495
|
+
callSiteCombinedStyles: variantOutcome.callSiteCombinedStyles
|
|
6494
6496
|
});
|
|
6495
6497
|
}
|
|
6496
6498
|
}
|
|
@@ -6644,7 +6646,7 @@ function buildInlineResolverVariantDimensions(args) {
|
|
|
6644
6646
|
continue;
|
|
6645
6647
|
}
|
|
6646
6648
|
const [singleKey, singleVariantStyles] = Object.entries(variants)[0];
|
|
6647
|
-
if (singleKey
|
|
6649
|
+
if (isSingleVariantKeyTruthy(singleKey, booleanOnlyProps.has(propName))) {
|
|
6648
6650
|
staticBooleanVariants.push({
|
|
6649
6651
|
propName,
|
|
6650
6652
|
styleKey: `${decl.styleKey}${toSuffixFromProp(propName)}`,
|
|
@@ -6661,6 +6663,31 @@ function buildInlineResolverVariantDimensions(args) {
|
|
|
6661
6663
|
propTypeFromKeyof: true
|
|
6662
6664
|
});
|
|
6663
6665
|
}
|
|
6666
|
+
const callSiteCombinedStyles = buildCallSiteCombinedStyles({
|
|
6667
|
+
decl,
|
|
6668
|
+
staticBooleanVariants,
|
|
6669
|
+
dimensions,
|
|
6670
|
+
baseSx: {
|
|
6671
|
+
...baseResult.sx,
|
|
6672
|
+
...foldedBaseSx
|
|
6673
|
+
},
|
|
6674
|
+
propsByUsage: usageResult.propsByUsage,
|
|
6675
|
+
hasCompleteCallsiteVisibility: !willHaveExternalInterface(ctx, decl, styledDecls) && !decl.usedAsValue,
|
|
6676
|
+
hasPropReferencingTemplateExpressions: (decl.templateExpressions ?? []).some((expr) => {
|
|
6677
|
+
const type = expr?.type;
|
|
6678
|
+
return type === "ArrowFunctionExpression" || type === "FunctionExpression";
|
|
6679
|
+
})
|
|
6680
|
+
});
|
|
6681
|
+
if (callSiteCombinedStyles) return {
|
|
6682
|
+
kind: "ok",
|
|
6683
|
+
variantDimensions: dimensions,
|
|
6684
|
+
hasLocalCallsites,
|
|
6685
|
+
usedConsumedPropsAtCallSites,
|
|
6686
|
+
foldedBaseSx,
|
|
6687
|
+
bakedInConsumedProps,
|
|
6688
|
+
staticBooleanVariants: [],
|
|
6689
|
+
callSiteCombinedStyles
|
|
6690
|
+
};
|
|
6664
6691
|
return {
|
|
6665
6692
|
kind: "ok",
|
|
6666
6693
|
variantDimensions: dimensions,
|
|
@@ -6668,7 +6695,8 @@ function buildInlineResolverVariantDimensions(args) {
|
|
|
6668
6695
|
usedConsumedPropsAtCallSites,
|
|
6669
6696
|
foldedBaseSx,
|
|
6670
6697
|
bakedInConsumedProps,
|
|
6671
|
-
staticBooleanVariants
|
|
6698
|
+
staticBooleanVariants,
|
|
6699
|
+
callSiteCombinedStyles: []
|
|
6672
6700
|
};
|
|
6673
6701
|
}
|
|
6674
6702
|
/**
|
|
@@ -6804,12 +6832,59 @@ function diffSx(baseSx, siteSx) {
|
|
|
6804
6832
|
for (const [prop, value] of Object.entries(siteSx)) if (!(prop in baseSx)) out[prop] = value;
|
|
6805
6833
|
return out;
|
|
6806
6834
|
}
|
|
6835
|
+
/**
|
|
6836
|
+
* For direct JSX resolution, merges individual single-key variant styles into
|
|
6837
|
+
* combined per-call-site entries. Returns the combined styles, or null if
|
|
6838
|
+
* combining is not applicable (e.g., multi-key variants, wrapper components).
|
|
6839
|
+
*/
|
|
6840
|
+
function buildCallSiteCombinedStyles(args) {
|
|
6841
|
+
const { decl, staticBooleanVariants, dimensions, baseSx, propsByUsage, hasCompleteCallsiteVisibility, hasPropReferencingTemplateExpressions } = args;
|
|
6842
|
+
if (!decl.isDirectJsxResolution || !hasCompleteCallsiteVisibility || hasPropReferencingTemplateExpressions || staticBooleanVariants.length < 2 || dimensions.length > 0) return null;
|
|
6843
|
+
const variantsByProp = new Map(staticBooleanVariants.map((v) => [v.propName, v]));
|
|
6844
|
+
const combinationGroups = /* @__PURE__ */ new Map();
|
|
6845
|
+
for (const siteProps of propsByUsage) {
|
|
6846
|
+
const matchingPropNames = Object.keys(siteProps).filter((p) => variantsByProp.has(p)).sort();
|
|
6847
|
+
if (matchingPropNames.length === 0) continue;
|
|
6848
|
+
const groupKey = matchingPropNames.join(",");
|
|
6849
|
+
if (combinationGroups.has(groupKey)) continue;
|
|
6850
|
+
const mergedStyles = { ...baseSx };
|
|
6851
|
+
for (const propName of matchingPropNames) {
|
|
6852
|
+
const variant = variantsByProp.get(propName);
|
|
6853
|
+
Object.assign(mergedStyles, variant.styles);
|
|
6854
|
+
}
|
|
6855
|
+
combinationGroups.set(groupKey, {
|
|
6856
|
+
propNames: matchingPropNames,
|
|
6857
|
+
styles: mergedStyles
|
|
6858
|
+
});
|
|
6859
|
+
}
|
|
6860
|
+
if (combinationGroups.size === 0 || combinationGroups.size >= staticBooleanVariants.length) return null;
|
|
6861
|
+
const result = [];
|
|
6862
|
+
for (const [, { propNames, styles }] of combinationGroups) {
|
|
6863
|
+
const suffix = propNames.map((p) => toSuffixFromProp(p)).join("");
|
|
6864
|
+
result.push({
|
|
6865
|
+
propNames,
|
|
6866
|
+
styleKey: `${decl.styleKey}${suffix}`,
|
|
6867
|
+
styles
|
|
6868
|
+
});
|
|
6869
|
+
}
|
|
6870
|
+
return result;
|
|
6871
|
+
}
|
|
6872
|
+
/**
|
|
6873
|
+
* Checks whether a single variant key represents a value that is truthy at runtime.
|
|
6874
|
+
* For boolean props, only `"true"` is truthy (`false` is falsy).
|
|
6875
|
+
* For non-boolean props (numbers, strings), "0" and "" are falsy; everything else is truthy.
|
|
6876
|
+
* Falsy values cannot use the truthy-guard pattern (`prop && styles.key`) safely.
|
|
6877
|
+
*/
|
|
6878
|
+
function isSingleVariantKeyTruthy(key, isBooleanProp) {
|
|
6879
|
+
if (isBooleanProp) return key === "true";
|
|
6880
|
+
return key !== "0" && key !== "";
|
|
6881
|
+
}
|
|
6807
6882
|
function serializeRecord(record) {
|
|
6808
6883
|
const ordered = Object.keys(record).sort().map((key) => [key, record[key]]);
|
|
6809
6884
|
return JSON.stringify(ordered);
|
|
6810
6885
|
}
|
|
6811
6886
|
function inlineResolvedBaseComponent(args) {
|
|
6812
|
-
const { ctx, decl, baseStaticProps, importSource, importedName, baseResult, consumedProps, variantDimensions, hasLocalCallsites, usedConsumedPropsAtCallSites, foldedBaseSx, bakedInConsumedProps, staticBooleanVariants } = args;
|
|
6887
|
+
const { ctx, decl, baseStaticProps, importSource, importedName, baseResult, consumedProps, variantDimensions, hasLocalCallsites, usedConsumedPropsAtCallSites, foldedBaseSx, bakedInConsumedProps, staticBooleanVariants, callSiteCombinedStyles } = args;
|
|
6813
6888
|
const sxRule = createRuleFromStylexDeclarations(Object.keys(foldedBaseSx).length > 0 ? {
|
|
6814
6889
|
...baseResult.sx,
|
|
6815
6890
|
...foldedBaseSx
|
|
@@ -6853,6 +6928,7 @@ function inlineResolvedBaseComponent(args) {
|
|
|
6853
6928
|
};
|
|
6854
6929
|
if (variantDimensions.length > 0) decl.variantDimensions = [...decl.variantDimensions ?? [], ...variantDimensions];
|
|
6855
6930
|
if (staticBooleanVariants.length > 0) decl.staticBooleanVariants = [...decl.staticBooleanVariants ?? [], ...staticBooleanVariants];
|
|
6931
|
+
if (callSiteCombinedStyles.length > 0) decl.callSiteCombinedStyles = [...decl.callSiteCombinedStyles ?? [], ...callSiteCombinedStyles];
|
|
6856
6932
|
decl.inlinedBaseComponent = {
|
|
6857
6933
|
importSource,
|
|
6858
6934
|
importedName,
|
|
@@ -6986,7 +7062,8 @@ function resolveDirectJsxUsages(ctx, styledDecls) {
|
|
|
6986
7062
|
usedConsumedPropsAtCallSites: variantOutcome.usedConsumedPropsAtCallSites,
|
|
6987
7063
|
foldedBaseSx: variantOutcome.foldedBaseSx,
|
|
6988
7064
|
bakedInConsumedProps: variantOutcome.bakedInConsumedProps,
|
|
6989
|
-
staticBooleanVariants: variantOutcome.staticBooleanVariants
|
|
7065
|
+
staticBooleanVariants: variantOutcome.staticBooleanVariants,
|
|
7066
|
+
callSiteCombinedStyles: variantOutcome.callSiteCombinedStyles
|
|
6990
7067
|
});
|
|
6991
7068
|
usedStyleKeys.add(syntheticDecl.styleKey);
|
|
6992
7069
|
styledDecls.push(syntheticDecl);
|
|
@@ -13672,6 +13749,149 @@ function buildInterpolatedTemplate(args) {
|
|
|
13672
13749
|
return j.templateLiteral(quasis, exprs);
|
|
13673
13750
|
}
|
|
13674
13751
|
|
|
13752
|
+
//#endregion
|
|
13753
|
+
//#region src/internal/lower-rules/utils.ts
|
|
13754
|
+
/**
|
|
13755
|
+
* Shared lower-rules helpers for merging and formatting style objects.
|
|
13756
|
+
* Core concepts: deep merge semantics, AST node detection, and media query resolution.
|
|
13757
|
+
*/
|
|
13758
|
+
/** Returns true for at-rules the codemod can transform (`@media`, `@container`). */
|
|
13759
|
+
function isSupportedAtRule(atRule) {
|
|
13760
|
+
return atRule.startsWith("@media") || atRule.startsWith("@container");
|
|
13761
|
+
}
|
|
13762
|
+
/** Finds the first supported at-rule (`@media` or `@container`) in the stack, if any. */
|
|
13763
|
+
function findSupportedAtRule(atRuleStack) {
|
|
13764
|
+
return atRuleStack.find(isSupportedAtRule);
|
|
13765
|
+
}
|
|
13766
|
+
/**
|
|
13767
|
+
* Resolves a media/container at-rule string that may contain `__SC_EXPR_N__` placeholders.
|
|
13768
|
+
*
|
|
13769
|
+
* First tries `resolveSelector` (when available) to produce a computed key like
|
|
13770
|
+
* `[breakpoints.phone]`. Falls back to static value substitution.
|
|
13771
|
+
*
|
|
13772
|
+
* Returns null if the placeholder cannot be resolved at all.
|
|
13773
|
+
*/
|
|
13774
|
+
function resolveMediaAtRulePlaceholders(media, getSlotExpr, ctx) {
|
|
13775
|
+
if (!media.includes("__SC_EXPR_")) return {
|
|
13776
|
+
kind: "static",
|
|
13777
|
+
value: media
|
|
13778
|
+
};
|
|
13779
|
+
const globalRe = new RegExp(PLACEHOLDER_RE.source, "g");
|
|
13780
|
+
const matches = [...media.matchAll(globalRe)];
|
|
13781
|
+
if (matches.length === 1 && ctx.resolveSelector && ctx.parseExpr) {
|
|
13782
|
+
const expr = getSlotExpr(Number(matches[0][1]));
|
|
13783
|
+
if (expr && typeof expr === "object") {
|
|
13784
|
+
const info = extractRootAndPath(expr);
|
|
13785
|
+
if (info) {
|
|
13786
|
+
const imp = ctx.lookupImport(info.rootName, info.rootNode);
|
|
13787
|
+
if (imp) {
|
|
13788
|
+
const result = ctx.resolveSelector({
|
|
13789
|
+
kind: "selectorInterpolation",
|
|
13790
|
+
importedName: imp.importedName,
|
|
13791
|
+
source: imp.source,
|
|
13792
|
+
path: info.path.length > 0 ? info.path.join(".") : void 0,
|
|
13793
|
+
filePath: ctx.filePath
|
|
13794
|
+
});
|
|
13795
|
+
if (result?.kind === "media") {
|
|
13796
|
+
const keyExpr = ctx.parseExpr(result.expr);
|
|
13797
|
+
if (keyExpr) {
|
|
13798
|
+
for (const impSpec of result.imports ?? []) ctx.resolverImports.set(JSON.stringify(impSpec), impSpec);
|
|
13799
|
+
return {
|
|
13800
|
+
kind: "computed",
|
|
13801
|
+
keyExpr,
|
|
13802
|
+
imports: result.imports ?? []
|
|
13803
|
+
};
|
|
13804
|
+
}
|
|
13805
|
+
}
|
|
13806
|
+
}
|
|
13807
|
+
}
|
|
13808
|
+
}
|
|
13809
|
+
}
|
|
13810
|
+
const resolved = resolveMediaQueryPlaceholders(media, (slotId) => resolveSlotExprToStaticValue(getSlotExpr(slotId), ctx.lookupImport, ctx.resolveValue, ctx.filePath, ctx.resolverImports));
|
|
13811
|
+
if (resolved === null) return null;
|
|
13812
|
+
return {
|
|
13813
|
+
kind: "static",
|
|
13814
|
+
value: resolved
|
|
13815
|
+
};
|
|
13816
|
+
}
|
|
13817
|
+
/** Returns true if the key looks like a StyleX style condition (pseudo, media, container). */
|
|
13818
|
+
function isStyleConditionKey(key) {
|
|
13819
|
+
return key.startsWith(":") || key.startsWith("::") || key.startsWith("@media") || key.startsWith("@container");
|
|
13820
|
+
}
|
|
13821
|
+
/**
|
|
13822
|
+
* Merges tracked @media values into a base style object as nested StyleX objects.
|
|
13823
|
+
* Each property that has media-scoped values is wrapped in:
|
|
13824
|
+
* `{ default: baseValue, "@media (...)": mediaValue }`
|
|
13825
|
+
*/
|
|
13826
|
+
function mergeMediaIntoStyles(base, mediaStyles) {
|
|
13827
|
+
for (const [mediaQuery, mediaStyle] of mediaStyles) for (const [prop, mediaValue] of Object.entries(mediaStyle)) base[prop] = {
|
|
13828
|
+
default: base[prop] ?? null,
|
|
13829
|
+
[mediaQuery]: mediaValue
|
|
13830
|
+
};
|
|
13831
|
+
}
|
|
13832
|
+
/**
|
|
13833
|
+
* Recursively merges style objects, combining nested objects rather than overwriting.
|
|
13834
|
+
*
|
|
13835
|
+
* Note: Security scanners may flag this as prototype pollution, but this is a false positive.
|
|
13836
|
+
* This is a codemod that runs locally on the developer's own source code - there is no
|
|
13837
|
+
* untrusted input that could exploit prototype pollution. The source objects are style
|
|
13838
|
+
* declarations extracted from the developer's own styled-components code.
|
|
13839
|
+
*/
|
|
13840
|
+
function mergeStyleObjects(target, source) {
|
|
13841
|
+
for (const [key, value] of Object.entries(source)) {
|
|
13842
|
+
const existing = target[key];
|
|
13843
|
+
if (existing && value && typeof existing === "object" && typeof value === "object" && !Array.isArray(existing) && !Array.isArray(value) && !isAstNode(existing) && !isAstNode(value)) mergeStyleObjects(existing, value);
|
|
13844
|
+
else target[key] = value;
|
|
13845
|
+
}
|
|
13846
|
+
}
|
|
13847
|
+
/** Resolves `__SC_EXPR_N__` placeholders in a string to static values via a callback. */
|
|
13848
|
+
function resolveMediaQueryPlaceholders(mediaQuery, resolveSlot) {
|
|
13849
|
+
if (!mediaQuery.includes("__SC_EXPR_")) return mediaQuery;
|
|
13850
|
+
const globalRe = new RegExp(PLACEHOLDER_RE.source, "g");
|
|
13851
|
+
const matches = [];
|
|
13852
|
+
let match;
|
|
13853
|
+
while ((match = globalRe.exec(mediaQuery)) !== null) matches.push({
|
|
13854
|
+
full: match[0],
|
|
13855
|
+
slotId: Number(match[1])
|
|
13856
|
+
});
|
|
13857
|
+
let resolved = mediaQuery;
|
|
13858
|
+
for (const m of matches) {
|
|
13859
|
+
const staticVal = resolveSlot(m.slotId);
|
|
13860
|
+
if (staticVal === null) return null;
|
|
13861
|
+
resolved = resolved.replace(m.full, String(staticVal));
|
|
13862
|
+
}
|
|
13863
|
+
return resolved;
|
|
13864
|
+
}
|
|
13865
|
+
/** Resolves a slot expression AST node to a static string or number via the adapter. */
|
|
13866
|
+
function resolveSlotExprToStaticValue(expr, lookupImport, resolveValue, filePath, resolverImports) {
|
|
13867
|
+
if (!expr || typeof expr !== "object") return null;
|
|
13868
|
+
const staticVal = literalToStaticValue(expr);
|
|
13869
|
+
if (typeof staticVal === "string" || typeof staticVal === "number") return staticVal;
|
|
13870
|
+
const info = extractRootAndPath(expr);
|
|
13871
|
+
if (!info) return null;
|
|
13872
|
+
const imp = lookupImport(info.rootName, info.rootNode);
|
|
13873
|
+
if (!imp) return null;
|
|
13874
|
+
const result = resolveValue({
|
|
13875
|
+
kind: "importedValue",
|
|
13876
|
+
importedName: imp.importedName,
|
|
13877
|
+
source: imp.source,
|
|
13878
|
+
...info.path.length > 0 ? { path: info.path.join(".") } : {},
|
|
13879
|
+
filePath
|
|
13880
|
+
});
|
|
13881
|
+
if (!result || !("expr" in result)) return null;
|
|
13882
|
+
for (const impSpec of result.imports ?? []) resolverImports.set(JSON.stringify(impSpec), impSpec);
|
|
13883
|
+
return parseStaticExprString(result.expr);
|
|
13884
|
+
}
|
|
13885
|
+
/** Parses a JS expression string as a static numeric or quoted string value. */
|
|
13886
|
+
function parseStaticExprString(expr) {
|
|
13887
|
+
const trimmed = expr.trim();
|
|
13888
|
+
if (!trimmed) return null;
|
|
13889
|
+
const num = Number(trimmed);
|
|
13890
|
+
if (!isNaN(num) && trimmed !== "") return num;
|
|
13891
|
+
if (trimmed.startsWith("\"") && trimmed.endsWith("\"") || trimmed.startsWith("'") && trimmed.endsWith("'")) return trimmed.slice(1, -1);
|
|
13892
|
+
return null;
|
|
13893
|
+
}
|
|
13894
|
+
|
|
13675
13895
|
//#endregion
|
|
13676
13896
|
//#region src/internal/lower-rules/css-helper.ts
|
|
13677
13897
|
/**
|
|
@@ -13816,14 +14036,15 @@ function createCssHelperResolver(args) {
|
|
|
13816
14036
|
exprString: JSON.stringify(v)
|
|
13817
14037
|
};
|
|
13818
14038
|
}
|
|
13819
|
-
|
|
13820
|
-
|
|
13821
|
-
const imp = importMap.get(
|
|
14039
|
+
const info = extractRootAndPath(branch);
|
|
14040
|
+
if (info) {
|
|
14041
|
+
const imp = importMap.get(info.rootName);
|
|
13822
14042
|
if (imp) {
|
|
13823
14043
|
const res = resolveValue({
|
|
13824
14044
|
kind: "importedValue",
|
|
13825
14045
|
importedName: imp.importedName,
|
|
13826
14046
|
source: imp.source,
|
|
14047
|
+
...info.path.length > 0 ? { path: info.path.join(".") } : {},
|
|
13827
14048
|
filePath,
|
|
13828
14049
|
loc: getNodeLocStart(branch) ?? void 0
|
|
13829
14050
|
});
|
|
@@ -13835,9 +14056,9 @@ function createCssHelperResolver(args) {
|
|
|
13835
14056
|
exprString: res.expr
|
|
13836
14057
|
} : null;
|
|
13837
14058
|
}
|
|
13838
|
-
return {
|
|
14059
|
+
if (branch.type === "Identifier") return {
|
|
13839
14060
|
ast: branch,
|
|
13840
|
-
exprString:
|
|
14061
|
+
exprString: info.rootName
|
|
13841
14062
|
};
|
|
13842
14063
|
}
|
|
13843
14064
|
return null;
|
|
@@ -13872,9 +14093,28 @@ function createCssHelperResolver(args) {
|
|
|
13872
14093
|
const dynamicProps = [];
|
|
13873
14094
|
const dynamicPropKeys = /* @__PURE__ */ new Set();
|
|
13874
14095
|
const conditionalVariants = [];
|
|
14096
|
+
const lookupImport = (localName) => importMap.get(localName) ?? null;
|
|
13875
14097
|
for (const rule of rules) {
|
|
13876
|
-
const
|
|
13877
|
-
if (rule.atRuleStack.length > 0 && !
|
|
14098
|
+
const rawMedia = findSupportedAtRule(rule.atRuleStack);
|
|
14099
|
+
if (rule.atRuleStack.length > 0 && !rawMedia) return bail("Conditional `css` block: @-rules (e.g., @media, @supports) are not supported");
|
|
14100
|
+
let media = rawMedia;
|
|
14101
|
+
let computedMediaKey = null;
|
|
14102
|
+
if (rawMedia) {
|
|
14103
|
+
const resolved = resolveMediaAtRulePlaceholders(rawMedia, (slotId) => slotExprById.get(slotId), {
|
|
14104
|
+
lookupImport,
|
|
14105
|
+
resolveValue,
|
|
14106
|
+
resolveSelector: args.resolveSelector,
|
|
14107
|
+
parseExpr,
|
|
14108
|
+
filePath,
|
|
14109
|
+
resolverImports
|
|
14110
|
+
});
|
|
14111
|
+
if (resolved === null) return bail("Conditional `css` block: media query contains unresolvable interpolation");
|
|
14112
|
+
if (resolved.kind === "static") media = resolved.value;
|
|
14113
|
+
else {
|
|
14114
|
+
computedMediaKey = resolved;
|
|
14115
|
+
media = void 0;
|
|
14116
|
+
}
|
|
14117
|
+
}
|
|
13878
14118
|
const selector = (rule.selector ?? "").trim();
|
|
13879
14119
|
const allowDynamicValues = selector === "&";
|
|
13880
14120
|
let target = out;
|
|
@@ -13906,7 +14146,19 @@ function createCssHelperResolver(args) {
|
|
|
13906
14146
|
}
|
|
13907
14147
|
const mergeIntoContext = (value, prop, targetObj) => {
|
|
13908
14148
|
const existing = targetObj[prop];
|
|
13909
|
-
if (
|
|
14149
|
+
if (computedMediaKey) {
|
|
14150
|
+
const nested = existing && typeof existing === "object" && !Array.isArray(existing) && !isAstNode(existing) ? existing : { default: existing ?? null };
|
|
14151
|
+
if (!("default" in nested)) nested.default = null;
|
|
14152
|
+
nested.__computedKeys = [...nested.__computedKeys ?? [], {
|
|
14153
|
+
keyExpr: computedMediaKey.keyExpr,
|
|
14154
|
+
value
|
|
14155
|
+
}];
|
|
14156
|
+
return nested;
|
|
14157
|
+
}
|
|
14158
|
+
if (media && currentPseudoClass) {
|
|
14159
|
+
const pseudoExisting = existing && typeof existing === "object" && !Array.isArray(existing) && !isAstNode(existing) ? existing[currentPseudoClass] : void 0;
|
|
14160
|
+
return mergeIntoPseudoContext(mergeIntoPseudoContext(value, media, pseudoExisting), currentPseudoClass, existing);
|
|
14161
|
+
}
|
|
13910
14162
|
if (media) return mergeIntoPseudoContext(value, media, existing);
|
|
13911
14163
|
return mergeIntoPseudoContext(value, currentPseudoClass, existing);
|
|
13912
14164
|
};
|
|
@@ -14484,6 +14736,7 @@ function createLowerRulesState(ctx) {
|
|
|
14484
14736
|
importMap,
|
|
14485
14737
|
filePath,
|
|
14486
14738
|
resolveValue,
|
|
14739
|
+
resolveSelector,
|
|
14487
14740
|
parseExpr,
|
|
14488
14741
|
resolverImports,
|
|
14489
14742
|
warnings,
|
|
@@ -14556,39 +14809,6 @@ function createLowerRulesState(ctx) {
|
|
|
14556
14809
|
return state;
|
|
14557
14810
|
}
|
|
14558
14811
|
|
|
14559
|
-
//#endregion
|
|
14560
|
-
//#region src/internal/lower-rules/utils.ts
|
|
14561
|
-
/**
|
|
14562
|
-
* Shared lower-rules helpers for merging and formatting style objects.
|
|
14563
|
-
* Core concepts: deep merge semantics and AST node detection.
|
|
14564
|
-
*/
|
|
14565
|
-
/**
|
|
14566
|
-
* Merges tracked @media values into a base style object as nested StyleX objects.
|
|
14567
|
-
* Each property that has media-scoped values is wrapped in:
|
|
14568
|
-
* `{ default: baseValue, "@media (...)": mediaValue }`
|
|
14569
|
-
*/
|
|
14570
|
-
function mergeMediaIntoStyles(base, mediaStyles) {
|
|
14571
|
-
for (const [mediaQuery, mediaStyle] of mediaStyles) for (const [prop, mediaValue] of Object.entries(mediaStyle)) base[prop] = {
|
|
14572
|
-
default: base[prop] ?? null,
|
|
14573
|
-
[mediaQuery]: mediaValue
|
|
14574
|
-
};
|
|
14575
|
-
}
|
|
14576
|
-
/**
|
|
14577
|
-
* Recursively merges style objects, combining nested objects rather than overwriting.
|
|
14578
|
-
*
|
|
14579
|
-
* Note: Security scanners may flag this as prototype pollution, but this is a false positive.
|
|
14580
|
-
* This is a codemod that runs locally on the developer's own source code - there is no
|
|
14581
|
-
* untrusted input that could exploit prototype pollution. The source objects are style
|
|
14582
|
-
* declarations extracted from the developer's own styled-components code.
|
|
14583
|
-
*/
|
|
14584
|
-
function mergeStyleObjects(target, source) {
|
|
14585
|
-
for (const [key, value] of Object.entries(source)) {
|
|
14586
|
-
const existing = target[key];
|
|
14587
|
-
if (existing && value && typeof existing === "object" && typeof value === "object" && !Array.isArray(existing) && !Array.isArray(value) && !isAstNode(existing) && !isAstNode(value)) mergeStyleObjects(existing, value);
|
|
14588
|
-
else target[key] = value;
|
|
14589
|
-
}
|
|
14590
|
-
}
|
|
14591
|
-
|
|
14592
14812
|
//#endregion
|
|
14593
14813
|
//#region src/internal/lower-rules/variant-utils.ts
|
|
14594
14814
|
/**
|
|
@@ -16933,8 +17153,8 @@ function tryResolveInlineStyleValueForNestedPropAccess(node) {
|
|
|
16933
17153
|
}
|
|
16934
17154
|
function tryResolveInlineStyleValueFromArrowFn(node) {
|
|
16935
17155
|
if (!node.css.property) return null;
|
|
16936
|
-
const hasMediaAtRule = (node.css.atRuleStack ?? []).some(
|
|
16937
|
-
const isMediaSelector = (node.css.selector ?? "").trim()
|
|
17156
|
+
const hasMediaAtRule = (node.css.atRuleStack ?? []).some(isSupportedAtRule);
|
|
17157
|
+
const isMediaSelector = isSupportedAtRule((node.css.selector ?? "").trim());
|
|
16938
17158
|
if (!hasMediaAtRule && !isMediaSelector) return null;
|
|
16939
17159
|
const expr = node.expr;
|
|
16940
17160
|
if (!isArrowFunctionExpression(expr)) return null;
|
|
@@ -17032,7 +17252,7 @@ function resolveTemplateLiteralBranch(ctx, args) {
|
|
|
17032
17252
|
const inlineEntries = [];
|
|
17033
17253
|
const mediaStyles = /* @__PURE__ */ new Map();
|
|
17034
17254
|
for (const rule of rules) {
|
|
17035
|
-
|
|
17255
|
+
let media = findSupportedAtRule(rule.atRuleStack);
|
|
17036
17256
|
if (rule.atRuleStack.length > 0 && !media) {
|
|
17037
17257
|
ctx.warnings?.push({
|
|
17038
17258
|
severity: "warning",
|
|
@@ -17041,8 +17261,36 @@ function resolveTemplateLiteralBranch(ctx, args) {
|
|
|
17041
17261
|
});
|
|
17042
17262
|
return null;
|
|
17043
17263
|
}
|
|
17264
|
+
let computedMediaKeyExpr;
|
|
17265
|
+
if (media) {
|
|
17266
|
+
const resolved = resolveMediaAtRulePlaceholders(media, (slotId) => slotExprById.get(slotId), {
|
|
17267
|
+
lookupImport: resolveImportInScope,
|
|
17268
|
+
resolveValue,
|
|
17269
|
+
resolveSelector: ctx.resolveSelector,
|
|
17270
|
+
parseExpr,
|
|
17271
|
+
filePath,
|
|
17272
|
+
resolverImports
|
|
17273
|
+
});
|
|
17274
|
+
if (resolved === null) return null;
|
|
17275
|
+
if (resolved.kind === "static") media = resolved.value;
|
|
17276
|
+
else {
|
|
17277
|
+
computedMediaKeyExpr = resolved.keyExpr;
|
|
17278
|
+
media = void 0;
|
|
17279
|
+
}
|
|
17280
|
+
}
|
|
17044
17281
|
if ((rule.selector ?? "").trim() !== "&") return null;
|
|
17045
17282
|
const setStyleValue = (prop, value) => {
|
|
17283
|
+
if (computedMediaKeyExpr) {
|
|
17284
|
+
const existing = style[prop];
|
|
17285
|
+
const nested = existing && typeof existing === "object" && !Array.isArray(existing) ? existing : { default: existing ?? null };
|
|
17286
|
+
if (!("default" in nested)) nested.default = null;
|
|
17287
|
+
nested.__computedKeys = [...nested.__computedKeys ?? [], {
|
|
17288
|
+
keyExpr: computedMediaKeyExpr,
|
|
17289
|
+
value
|
|
17290
|
+
}];
|
|
17291
|
+
style[prop] = nested;
|
|
17292
|
+
return;
|
|
17293
|
+
}
|
|
17046
17294
|
if (media) {
|
|
17047
17295
|
const target = mediaStyles.get(media) ?? {};
|
|
17048
17296
|
mediaStyles.set(media, target);
|
|
@@ -17741,7 +17989,7 @@ const createCssHelperHandlers = (ctx) => {
|
|
|
17741
17989
|
//#endregion
|
|
17742
17990
|
//#region src/internal/lower-rules/css-helper-conditional.ts
|
|
17743
17991
|
function createCssHelperConditionalHandler(ctx) {
|
|
17744
|
-
const { j, decl, filePath, warnings, parseExpr, resolveValue, resolveCall, resolveImportInScope, resolverImports, componentInfo, handlerContext, styleObj, styleFnFromProps, styleFnDecls, inlineStyleProps, isCssHelperTaggedTemplate, resolveCssHelperTemplate, resolveStaticCssBlock, isPlainTemplateLiteral, isThemeAccessTest, applyVariant, dropAllTestInfoProps, annotateParamFromJsxProp, findJsxPropTsType, isJsxPropOptional, markBail, importMap, extraStyleObjects, resolvedStyleObjects } = ctx;
|
|
17992
|
+
const { j, decl, filePath, warnings, parseExpr, resolveValue, resolveCall, resolveSelector, resolveImportInScope, resolverImports, componentInfo, handlerContext, styleObj, styleFnFromProps, styleFnDecls, inlineStyleProps, isCssHelperTaggedTemplate, resolveCssHelperTemplate, resolveStaticCssBlock, isPlainTemplateLiteral, isThemeAccessTest, applyVariant, dropAllTestInfoProps, annotateParamFromJsxProp, findJsxPropTsType, isJsxPropOptional, markBail, importMap, extraStyleObjects, resolvedStyleObjects } = ctx;
|
|
17745
17993
|
const avoidNames = new Set(importMap.keys());
|
|
17746
17994
|
/**
|
|
17747
17995
|
* Resolve the TS type node for a prop used in a style function parameter.
|
|
@@ -17910,15 +18158,41 @@ function createCssHelperConditionalHandler(ctx) {
|
|
|
17910
18158
|
const { rules, slotExprById } = parseCssTemplateToRules(tpl);
|
|
17911
18159
|
const out = /* @__PURE__ */ new Map();
|
|
17912
18160
|
const mediaValues = /* @__PURE__ */ new Map();
|
|
17913
|
-
const
|
|
17914
|
-
|
|
18161
|
+
const computedMediaValues = /* @__PURE__ */ new Map();
|
|
18162
|
+
const setValueForProp = (prop, value, media, computedKey) => {
|
|
18163
|
+
if (computedKey) {
|
|
18164
|
+
const arr = computedMediaValues.get(prop) ?? [];
|
|
18165
|
+
arr.push({
|
|
18166
|
+
keyExpr: computedKey,
|
|
18167
|
+
value
|
|
18168
|
+
});
|
|
18169
|
+
computedMediaValues.set(prop, arr);
|
|
18170
|
+
} else if (media) {
|
|
17915
18171
|
if (!mediaValues.has(prop)) mediaValues.set(prop, /* @__PURE__ */ new Map());
|
|
17916
18172
|
mediaValues.get(prop).set(media, value);
|
|
17917
18173
|
} else out.set(prop, value);
|
|
17918
18174
|
};
|
|
17919
18175
|
for (const rule of rules) {
|
|
17920
|
-
const
|
|
17921
|
-
if (rule.atRuleStack.length > 0 && !
|
|
18176
|
+
const rawMedia = findSupportedAtRule(rule.atRuleStack);
|
|
18177
|
+
if (rule.atRuleStack.length > 0 && !rawMedia) return null;
|
|
18178
|
+
let media = rawMedia;
|
|
18179
|
+
let computedMediaKeyExpr;
|
|
18180
|
+
if (rawMedia) {
|
|
18181
|
+
const resolved = resolveMediaAtRulePlaceholders(rawMedia, (slotId) => slotExprById.get(slotId), {
|
|
18182
|
+
lookupImport: resolveImportInScope,
|
|
18183
|
+
resolveValue,
|
|
18184
|
+
resolveSelector,
|
|
18185
|
+
parseExpr,
|
|
18186
|
+
filePath,
|
|
18187
|
+
resolverImports
|
|
18188
|
+
});
|
|
18189
|
+
if (resolved === null) return null;
|
|
18190
|
+
if (resolved.kind === "static") media = resolved.value;
|
|
18191
|
+
else {
|
|
18192
|
+
computedMediaKeyExpr = resolved.keyExpr;
|
|
18193
|
+
media = void 0;
|
|
18194
|
+
}
|
|
18195
|
+
}
|
|
17922
18196
|
if ((rule.selector ?? "").trim() !== "&") return null;
|
|
17923
18197
|
for (const d of rule.declarations) {
|
|
17924
18198
|
if (!d.property) return null;
|
|
@@ -17932,7 +18206,7 @@ function createCssHelperConditionalHandler(ctx) {
|
|
|
17932
18206
|
if (m) value = `"${m[1]}"`;
|
|
17933
18207
|
else if (!value.startsWith("\"") && !value.endsWith("\"")) value = `"${value}"`;
|
|
17934
18208
|
}
|
|
17935
|
-
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") setValueForProp(mapped.prop, staticValueToLiteral(j, value), media);
|
|
18209
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") setValueForProp(mapped.prop, staticValueToLiteral(j, value), media, computedMediaKeyExpr);
|
|
17936
18210
|
else return null;
|
|
17937
18211
|
}
|
|
17938
18212
|
continue;
|
|
@@ -17945,13 +18219,21 @@ function createCssHelperConditionalHandler(ctx) {
|
|
|
17945
18219
|
const rawExpr = replaceParamWithProps(slotExpr);
|
|
17946
18220
|
const { prefix, suffix } = extractStaticPartsForDecl(d);
|
|
17947
18221
|
const valueExpr = prefix || suffix ? buildTemplateWithStaticParts(j, rawExpr, prefix, suffix) : rawExpr;
|
|
17948
|
-
for (const mapped of cssDeclarationToStylexDeclarations(d)) setValueForProp(mapped.prop, valueExpr, media);
|
|
18222
|
+
for (const mapped of cssDeclarationToStylexDeclarations(d)) setValueForProp(mapped.prop, valueExpr, media, computedMediaKeyExpr);
|
|
17949
18223
|
}
|
|
17950
18224
|
}
|
|
17951
|
-
|
|
18225
|
+
const allMediaProps = new Set([...mediaValues.keys(), ...computedMediaValues.keys()]);
|
|
18226
|
+
for (const prop of allMediaProps) {
|
|
17952
18227
|
const baseValue = out.get(prop);
|
|
17953
18228
|
const properties = [j.property("init", j.identifier("default"), baseValue ?? j.literal(null))];
|
|
17954
|
-
|
|
18229
|
+
const queries = mediaValues.get(prop);
|
|
18230
|
+
if (queries) for (const [query, value] of queries) properties.push(j.property("init", j.literal(query), value));
|
|
18231
|
+
const computed = computedMediaValues.get(prop);
|
|
18232
|
+
if (computed) for (const { keyExpr, value } of computed) {
|
|
18233
|
+
const p = j.property("init", keyExpr, value);
|
|
18234
|
+
p.computed = true;
|
|
18235
|
+
properties.push(p);
|
|
18236
|
+
}
|
|
17955
18237
|
out.set(prop, j.objectExpression(properties));
|
|
17956
18238
|
}
|
|
17957
18239
|
return out;
|
|
@@ -19284,7 +19566,7 @@ const createValuePatternHandlers = (ctx) => {
|
|
|
19284
19566
|
* Core concepts: per-component style buckets, helper factories, and resolver wiring.
|
|
19285
19567
|
*/
|
|
19286
19568
|
function createDeclProcessingState(state, decl) {
|
|
19287
|
-
const { api, j, root, filePath, warnings, resolverImports, parseExpr, resolveValue, resolveCall, resolveCallOptional, importMap, cssHelperFunctions, stringMappingFns, hasLocalThemeBinding, isCssHelperTaggedTemplate, resolveCssHelperTemplate, resolveImportInScope, usedCssHelperFunctions, markBail } = state;
|
|
19569
|
+
const { api, j, root, filePath, warnings, resolverImports, parseExpr, resolveValue, resolveCall, resolveCallOptional, resolveSelector, importMap, cssHelperFunctions, stringMappingFns, hasLocalThemeBinding, isCssHelperTaggedTemplate, resolveCssHelperTemplate, resolveImportInScope, usedCssHelperFunctions, markBail } = state;
|
|
19288
19570
|
const styleObj = {};
|
|
19289
19571
|
const perPropPseudo = {};
|
|
19290
19572
|
const perPropMedia = {};
|
|
@@ -19371,6 +19653,7 @@ function createDeclProcessingState(state, decl) {
|
|
|
19371
19653
|
parseExpr,
|
|
19372
19654
|
resolveValue,
|
|
19373
19655
|
resolveCall,
|
|
19656
|
+
resolveSelector,
|
|
19374
19657
|
resolveImportInScope,
|
|
19375
19658
|
resolverImports,
|
|
19376
19659
|
isCssHelperTaggedTemplate,
|
|
@@ -19432,7 +19715,7 @@ function createDeclProcessingState(state, decl) {
|
|
|
19432
19715
|
const out = {};
|
|
19433
19716
|
const mediaStyles = /* @__PURE__ */ new Map();
|
|
19434
19717
|
for (const rule of rules) {
|
|
19435
|
-
const media = rule.atRuleStack
|
|
19718
|
+
const media = findSupportedAtRule(rule.atRuleStack);
|
|
19436
19719
|
if (rule.atRuleStack.length > 0 && !media) {
|
|
19437
19720
|
warnings.push({
|
|
19438
19721
|
severity: "warning",
|
|
@@ -19878,18 +20161,26 @@ function tryHandleInterpolatedBorder(ctx, args) {
|
|
|
19878
20161
|
if (quasis.length === 2 && exprs.length === 1) {
|
|
19879
20162
|
const prefix = quasis[0]?.value?.cooked ?? quasis[0]?.value?.raw ?? "";
|
|
19880
20163
|
const suffix = quasis[1]?.value?.cooked ?? quasis[1]?.value?.raw ?? "";
|
|
19881
|
-
if (suffix.trim()
|
|
19882
|
-
|
|
19883
|
-
|
|
19884
|
-
|
|
19885
|
-
|
|
19886
|
-
|
|
19887
|
-
|
|
19888
|
-
|
|
19889
|
-
|
|
19890
|
-
|
|
19891
|
-
|
|
19892
|
-
}
|
|
20164
|
+
if (suffix.trim() === "") {
|
|
20165
|
+
const parsed = parseInterpolatedBorderStaticParts({
|
|
20166
|
+
prop,
|
|
20167
|
+
prefix,
|
|
20168
|
+
suffix
|
|
20169
|
+
});
|
|
20170
|
+
if (parsed?.width && parsed?.style) return {
|
|
20171
|
+
width: parsed.width,
|
|
20172
|
+
style: parsed.style,
|
|
20173
|
+
colorExpr: exprs[0]
|
|
20174
|
+
};
|
|
20175
|
+
}
|
|
20176
|
+
if (prefix.trim() === "" && suffix.trim() !== "") {
|
|
20177
|
+
const parsed = parseBorderShorthandParts(suffix.trim());
|
|
20178
|
+
if (parsed?.style && parsed?.color) return {
|
|
20179
|
+
width: exprs[0],
|
|
20180
|
+
style: parsed.style,
|
|
20181
|
+
colorExpr: parsed.color
|
|
20182
|
+
};
|
|
20183
|
+
}
|
|
19893
20184
|
}
|
|
19894
20185
|
if (quasis.length === 3 && exprs.length === 2) {
|
|
19895
20186
|
const prefix = quasis[0]?.value?.cooked ?? quasis[0]?.value?.raw ?? "";
|
|
@@ -19993,7 +20284,7 @@ function tryHandleInterpolatedBorder(ctx, args) {
|
|
|
19993
20284
|
}
|
|
19994
20285
|
}
|
|
19995
20286
|
if (hasStaticWidthOrStyle) applyResolvedPropValue(targetProp, resolved.exprAst);
|
|
19996
|
-
else
|
|
20287
|
+
else bailUnsupportedWithContext("Resolved border helper value could not be expanded to longhand properties", { property: prop }, getNodeLocStart(expr));
|
|
19997
20288
|
return true;
|
|
19998
20289
|
}
|
|
19999
20290
|
}
|
|
@@ -21058,6 +21349,20 @@ function handleInterpolatedDeclaration(args) {
|
|
|
21058
21349
|
};
|
|
21059
21350
|
if (tryHandleThemeValueInPseudo()) continue;
|
|
21060
21351
|
const resolveImportedValueExpr = (expr) => {
|
|
21352
|
+
if (expr?.type === "BinaryExpression") {
|
|
21353
|
+
const leftResult = resolveImportedValueExpr(expr.left);
|
|
21354
|
+
const rightResult = resolveImportedValueExpr(expr.right);
|
|
21355
|
+
if (!leftResult && !rightResult) return null;
|
|
21356
|
+
if (leftResult && "bail" in leftResult) return leftResult;
|
|
21357
|
+
if (rightResult && "bail" in rightResult) return rightResult;
|
|
21358
|
+
const resolvedLeft = leftResult ? leftResult.resolved : expr.left;
|
|
21359
|
+
const resolvedRight = rightResult ? rightResult.resolved : expr.right;
|
|
21360
|
+
const imports = [...leftResult?.imports ?? [], ...rightResult?.imports ?? []];
|
|
21361
|
+
return {
|
|
21362
|
+
resolved: j.binaryExpression(expr.operator, resolvedLeft, resolvedRight),
|
|
21363
|
+
imports
|
|
21364
|
+
};
|
|
21365
|
+
}
|
|
21061
21366
|
const info = getRootIdentifierInfo(expr);
|
|
21062
21367
|
if (!info) return null;
|
|
21063
21368
|
const imp = resolveImportInScope(info.rootName, info.rootNode);
|
|
@@ -22830,7 +23135,7 @@ function processDeclRules(ctx) {
|
|
|
22830
23135
|
}
|
|
22831
23136
|
}
|
|
22832
23137
|
}
|
|
22833
|
-
let media = rule.atRuleStack
|
|
23138
|
+
let media = findSupportedAtRule(rule.atRuleStack);
|
|
22834
23139
|
const intrinsicTagName = decl.base.kind === "intrinsic" ? decl.base.tagName : null;
|
|
22835
23140
|
let selector = normalizeSelectorForAttributePseudos(rule.selector, intrinsicTagName);
|
|
22836
23141
|
selector = normalizeInterpolatedSelector(selector);
|
|
@@ -22843,10 +23148,37 @@ function processDeclRules(ctx) {
|
|
|
22843
23148
|
first.leadingComment = first.leadingComment ? `${note}\n${first.leadingComment}` : note;
|
|
22844
23149
|
}
|
|
22845
23150
|
}
|
|
22846
|
-
if (!media && (selector.trim()
|
|
23151
|
+
if (!media && isSupportedAtRule(selector.trim())) {
|
|
22847
23152
|
media = selector.trim();
|
|
22848
23153
|
selector = "&";
|
|
22849
23154
|
}
|
|
23155
|
+
if (media) {
|
|
23156
|
+
const resolved = resolveMediaAtRulePlaceholders(media, (slotId) => decl.templateExpressions[slotId], {
|
|
23157
|
+
lookupImport: resolveImportInScope,
|
|
23158
|
+
resolveValue: state.resolveValue,
|
|
23159
|
+
resolveSelector,
|
|
23160
|
+
parseExpr,
|
|
23161
|
+
filePath: state.filePath,
|
|
23162
|
+
resolverImports
|
|
23163
|
+
});
|
|
23164
|
+
if (resolved === null) {
|
|
23165
|
+
state.markBail();
|
|
23166
|
+
warnings.push({
|
|
23167
|
+
severity: "warning",
|
|
23168
|
+
type: "Unsupported: media query contains unresolvable interpolation",
|
|
23169
|
+
loc: computeSelectorWarningLoc(decl.loc, decl.rawCss, rule.selector)
|
|
23170
|
+
});
|
|
23171
|
+
break;
|
|
23172
|
+
}
|
|
23173
|
+
if (resolved.kind === "static") media = resolved.value;
|
|
23174
|
+
else {
|
|
23175
|
+
resolvedSelectorMedia = {
|
|
23176
|
+
keyExpr: resolved.keyExpr,
|
|
23177
|
+
exprSource: ""
|
|
23178
|
+
};
|
|
23179
|
+
media = void 0;
|
|
23180
|
+
}
|
|
23181
|
+
}
|
|
22850
23182
|
const parsedSelector = parseSelector(selector);
|
|
22851
23183
|
if (parsedSelector.kind === "unsupported" && selector !== "&" && !rule.selector.includes("__SC_EXPR_")) {
|
|
22852
23184
|
const elementAction = tryHandleElementSelector(selector, rule, decl);
|
|
@@ -23444,7 +23776,27 @@ function handleSiblingSelector(selector, rule, ctx) {
|
|
|
23444
23776
|
return "break";
|
|
23445
23777
|
}
|
|
23446
23778
|
const makeSiblingKeyExpr = () => j.callExpression(j.memberExpression(j.memberExpression(j.identifier("stylex"), j.identifier("when")), j.identifier("siblingBefore")), [j.literal(":is(*)")]);
|
|
23447
|
-
|
|
23779
|
+
let media = findSupportedAtRule(rule.atRuleStack);
|
|
23780
|
+
if (media) {
|
|
23781
|
+
const resolved = resolveMediaAtRulePlaceholders(media, (slotId) => decl.templateExpressions[slotId], {
|
|
23782
|
+
lookupImport: state.resolveImportInScope,
|
|
23783
|
+
resolveValue: state.resolveValue,
|
|
23784
|
+
resolveSelector: state.resolveSelector,
|
|
23785
|
+
parseExpr: state.parseExpr,
|
|
23786
|
+
filePath: state.filePath,
|
|
23787
|
+
resolverImports: state.resolverImports
|
|
23788
|
+
});
|
|
23789
|
+
if (resolved === null) {
|
|
23790
|
+
warnings.push({
|
|
23791
|
+
severity: "warning",
|
|
23792
|
+
type: "Unsupported: media query contains unresolvable interpolation",
|
|
23793
|
+
loc: computeSelectorWarningLoc(decl.loc, decl.rawCss, rule.selector)
|
|
23794
|
+
});
|
|
23795
|
+
return "break";
|
|
23796
|
+
}
|
|
23797
|
+
if (resolved.kind === "static") media = resolved.value;
|
|
23798
|
+
else media = void 0;
|
|
23799
|
+
}
|
|
23448
23800
|
for (const [prop, value] of Object.entries(bucket)) {
|
|
23449
23801
|
const siblingValue = media ? {
|
|
23450
23802
|
default: null,
|
|
@@ -23646,7 +23998,7 @@ function finalizeDeclProcessing(ctx) {
|
|
|
23646
23998
|
if (!v || typeof v !== "object" || Array.isArray(v) || isAstNode(v)) return false;
|
|
23647
23999
|
const keys = Object.keys(v);
|
|
23648
24000
|
if (keys.length === 0) return false;
|
|
23649
|
-
return keys.includes("default") || keys.some(
|
|
24001
|
+
return keys.includes("default") || keys.some(isStyleConditionKey);
|
|
23650
24002
|
};
|
|
23651
24003
|
if (!(() => {
|
|
23652
24004
|
const disabledBucket = variantBuckets.get("disabled");
|
|
@@ -24871,6 +25223,8 @@ function rewriteJsxStep(ctx) {
|
|
|
24871
25223
|
const inlineVariantDimensions = decl.inlinedBaseComponent?.hasInlineJsxVariants ? decl.variantDimensions ?? [] : [];
|
|
24872
25224
|
const inlineVariantByProp = new Map(inlineVariantDimensions.map((dimension) => [dimension.propName, dimension]));
|
|
24873
25225
|
const inlineVariantProps = new Set(inlineVariantDimensions.map((dimension) => dimension.propName));
|
|
25226
|
+
const combinedStylePropNames = new Set((decl.callSiteCombinedStyles ?? []).flatMap((c) => c.propNames));
|
|
25227
|
+
const matchedCombinedStyleKey = matchCallSiteCombinedStyle(decl.callSiteCombinedStyles, opening.attributes ?? []);
|
|
24874
25228
|
const attrs = opening.attributes ?? [];
|
|
24875
25229
|
for (const attr of attrs) {
|
|
24876
25230
|
if (attr.type !== "JSXAttribute") continue;
|
|
@@ -24898,6 +25252,7 @@ function rewriteJsxStep(ctx) {
|
|
|
24898
25252
|
const n = attr.name.name;
|
|
24899
25253
|
if (decl.shouldForwardProp.dropProps.includes(n)) {
|
|
24900
25254
|
if (inlineVariantProps.has(n)) return true;
|
|
25255
|
+
if (decl.variantStyleKeys && n in decl.variantStyleKeys) return true;
|
|
24901
25256
|
return false;
|
|
24902
25257
|
}
|
|
24903
25258
|
if (decl.shouldForwardProp.dropPrefix && n.startsWith(decl.shouldForwardProp.dropPrefix)) return false;
|
|
@@ -24981,10 +25336,11 @@ function rewriteJsxStep(ctx) {
|
|
|
24981
25336
|
else extraMixinArgs.push(expr);
|
|
24982
25337
|
}
|
|
24983
25338
|
}
|
|
25339
|
+
const baseStyleKey = matchedCombinedStyleKey ?? decl.styleKey;
|
|
24984
25340
|
const styleArgs = [
|
|
24985
25341
|
...decl.extendsStyleKey ? [j.memberExpression(j.identifier(ctx.stylesIdentifier ?? "styles"), j.identifier(decl.extendsStyleKey))] : [],
|
|
24986
25342
|
...extraMixinArgs,
|
|
24987
|
-
j.memberExpression(j.identifier(ctx.stylesIdentifier ?? "styles"), j.identifier(
|
|
25343
|
+
j.memberExpression(j.identifier(ctx.stylesIdentifier ?? "styles"), j.identifier(baseStyleKey)),
|
|
24988
25344
|
...extraAfterBaseArgs
|
|
24989
25345
|
];
|
|
24990
25346
|
const variantKeys = decl.variantStyleKeys ?? {};
|
|
@@ -25006,6 +25362,7 @@ function rewriteJsxStep(ctx) {
|
|
|
25006
25362
|
if (valueExpr) for (const p of pairs) styleArgs.push(j.callExpression(j.memberExpression(j.identifier(ctx.stylesIdentifier ?? "styles"), j.identifier(p.fnKey)), [valueExpr]));
|
|
25007
25363
|
return;
|
|
25008
25364
|
}
|
|
25365
|
+
if (combinedStylePropNames.has(n) && matchedCombinedStyleKey) return;
|
|
25009
25366
|
const inlineVariantDimension = inlineVariantByProp.get(n);
|
|
25010
25367
|
if (inlineVariantDimension) {
|
|
25011
25368
|
const variantLookup = buildInlineVariantLookupFromAttr(j, inlineVariantDimension.variantObjectName, attr);
|
|
@@ -25028,9 +25385,19 @@ function rewriteJsxStep(ctx) {
|
|
|
25028
25385
|
return;
|
|
25029
25386
|
}
|
|
25030
25387
|
if (attr.value.type === "JSXExpressionContainer") {
|
|
25388
|
+
const staticLiteralValue = readStaticJsxLiteral(attr);
|
|
25389
|
+
if (staticLiteralValue !== void 0 && staticLiteralValue) {
|
|
25390
|
+
styleArgs.push(j.memberExpression(j.identifier(ctx.stylesIdentifier ?? "styles"), j.identifier(variantStyleKey)));
|
|
25391
|
+
return;
|
|
25392
|
+
}
|
|
25031
25393
|
styleArgs.push(j.logicalExpression("&&", attr.value.expression, j.memberExpression(j.identifier(ctx.stylesIdentifier ?? "styles"), j.identifier(variantStyleKey))));
|
|
25032
25394
|
return;
|
|
25033
25395
|
}
|
|
25396
|
+
if (attr.value.type === "StringLiteral" || attr.value.type === "NumericLiteral" || attr.value.type === "Literal") {
|
|
25397
|
+
const literalVal = readStaticJsxLiteral(attr);
|
|
25398
|
+
if (literalVal !== void 0 && literalVal) styleArgs.push(j.memberExpression(j.identifier(ctx.stylesIdentifier ?? "styles"), j.identifier(variantStyleKey)));
|
|
25399
|
+
return;
|
|
25400
|
+
}
|
|
25034
25401
|
};
|
|
25035
25402
|
for (const attr of leading) processAttr(attr, keptLeadingAfterVariants);
|
|
25036
25403
|
for (const attr of rest) processAttr(attr, keptRestAfterVariants);
|
|
@@ -25087,6 +25454,22 @@ function extractJsxAttrValueExpr(j, attr) {
|
|
|
25087
25454
|
if (a.value.type === "StringLiteral" || a.value.type === "Literal") return j.literal(a.value.value);
|
|
25088
25455
|
if (a.value.type === "JSXExpressionContainer") return a.value.expression;
|
|
25089
25456
|
}
|
|
25457
|
+
/**
|
|
25458
|
+
* Finds the combined style key matching the consumed props at a JSX call site.
|
|
25459
|
+
* Returns the style key if a matching combination exists, or undefined otherwise.
|
|
25460
|
+
*/
|
|
25461
|
+
function matchCallSiteCombinedStyle(combinedStyles, attrs) {
|
|
25462
|
+
if (!combinedStyles?.length) return;
|
|
25463
|
+
const attrNames = /* @__PURE__ */ new Set();
|
|
25464
|
+
for (const a of attrs) {
|
|
25465
|
+
const attr = a;
|
|
25466
|
+
if (attr.type === "JSXAttribute" && attr.name?.type === "JSXIdentifier" && typeof attr.name.name === "string") attrNames.add(attr.name.name);
|
|
25467
|
+
}
|
|
25468
|
+
const presentPropNames = [...new Set(combinedStyles.flatMap((c) => c.propNames))].filter((p) => attrNames.has(p)).sort();
|
|
25469
|
+
if (presentPropNames.length === 0) return;
|
|
25470
|
+
const key = presentPropNames.join(",");
|
|
25471
|
+
return combinedStyles.find((c) => [...c.propNames].sort().join(",") === key)?.styleKey;
|
|
25472
|
+
}
|
|
25090
25473
|
|
|
25091
25474
|
//#endregion
|
|
25092
25475
|
//#region src/internal/transform-steps/upgrade-polymorphic-as-prop-types.ts
|