styled-components-to-stylex-codemod 0.0.20 → 0.0.22
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
package/dist/index.mjs
CHANGED
|
@@ -143,7 +143,7 @@ async function runTransform(options) {
|
|
|
143
143
|
].join("\n"));
|
|
144
144
|
const { createModuleResolver } = await import("./resolve-imports-4bFqrkrQ.mjs");
|
|
145
145
|
const sharedResolver = createModuleResolver();
|
|
146
|
-
const { runPrepass } = await import("./run-prepass-
|
|
146
|
+
const { runPrepass } = await import("./run-prepass-DtSt5v9e.mjs");
|
|
147
147
|
const absoluteFiles = filePaths.map((f) => resolve(f));
|
|
148
148
|
const absoluteConsumers = consumerFilePaths.map((f) => resolve(f));
|
|
149
149
|
let prepassResult;
|
|
@@ -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 interpolation must be a simple imported reference (expressions like `value + 1` are not supported)" | "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 interpolation must be a simple imported reference (expressions like `value + 1` are not supported)" | "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;
|
|
@@ -575,13 +575,20 @@ async function runPrepass(options) {
|
|
|
575
575
|
wrappedName: m[2]
|
|
576
576
|
});
|
|
577
577
|
}
|
|
578
|
-
if (hasAsProp) {
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
578
|
+
if (hasAsProp || hasRefProp) {
|
|
579
|
+
let aliasMap;
|
|
580
|
+
const resolveTagName = (tagName) => {
|
|
581
|
+
aliasMap ??= buildLocalToImportedMap(source);
|
|
582
|
+
return aliasMap.get(tagName) ?? tagName;
|
|
583
|
+
};
|
|
584
|
+
if (hasAsProp) {
|
|
585
|
+
JSX_AS_COMPONENT_RE.lastIndex = 0;
|
|
586
|
+
for (const m of source.matchAll(JSX_AS_COMPONENT_RE)) if (m[1]) addToSetMap(asUsages, resolveTagName(m[1]), filePath);
|
|
587
|
+
}
|
|
588
|
+
if (hasRefProp) {
|
|
589
|
+
JSX_REF_COMPONENT_RE.lastIndex = 0;
|
|
590
|
+
for (const m of source.matchAll(JSX_REF_COMPONENT_RE)) if (m[1]) addToSetMap(refUsages, resolveTagName(m[1]), filePath);
|
|
591
|
+
}
|
|
585
592
|
}
|
|
586
593
|
}
|
|
587
594
|
const styledFileCount = fileContents.size;
|
|
@@ -746,11 +753,14 @@ const IMPORT_ALIAS_ENTRY_RE = /\b(\w+)\s+as\s+(\w+)/g;
|
|
|
746
753
|
/**
|
|
747
754
|
* Build a mapping from local alias names to original imported names for a source file.
|
|
748
755
|
* Only includes PascalCase names that differ from their original (actual aliases).
|
|
756
|
+
* Scans only import declarations to avoid false positives from TypeScript `as` casts
|
|
757
|
+
* (e.g., `foo as Button` would incorrectly map `Button → foo`).
|
|
749
758
|
*/
|
|
750
759
|
function buildLocalToImportedMap(source) {
|
|
760
|
+
const importText = collectImportDeclarationText(source);
|
|
751
761
|
const map = /* @__PURE__ */ new Map();
|
|
752
762
|
IMPORT_ALIAS_ENTRY_RE.lastIndex = 0;
|
|
753
|
-
for (const m of
|
|
763
|
+
for (const m of importText.matchAll(IMPORT_ALIAS_ENTRY_RE)) {
|
|
754
764
|
const original = m[1];
|
|
755
765
|
const local = m[2];
|
|
756
766
|
if (original !== local && /^[A-Z]/.test(local)) map.set(local, original);
|
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
|
}
|
|
@@ -5933,6 +5933,61 @@ function expandStaticAnimationShorthand(value, inlineKeyframeNames, j, styleObj,
|
|
|
5933
5933
|
if (classified.iteration) styleObj.animationIterationCount = classified.iteration;
|
|
5934
5934
|
return true;
|
|
5935
5935
|
}
|
|
5936
|
+
/**
|
|
5937
|
+
* Resolves an interpolated animation declaration whose slot expressions
|
|
5938
|
+
* reference keyframes identifiers.
|
|
5939
|
+
*
|
|
5940
|
+
* Supports both the `animation` shorthand and `animation-name` longhand.
|
|
5941
|
+
* For shorthands, replaces each `__SC_EXPR_N__` placeholder with the
|
|
5942
|
+
* corresponding keyframes name, then delegates to
|
|
5943
|
+
* `expandStaticAnimationShorthand`. For `animation-name`, resolves the
|
|
5944
|
+
* single slot directly to a JS identifier.
|
|
5945
|
+
*
|
|
5946
|
+
* Bails (returns null) on comma-separated multi-animation shorthands,
|
|
5947
|
+
* which the single-tuple parser cannot correctly model.
|
|
5948
|
+
*/
|
|
5949
|
+
function expandInterpolatedAnimationShorthand(args) {
|
|
5950
|
+
const { property = "animation", valueRaw, slotExprById, keyframesNames, j, inlineKeyframeNameMap } = args;
|
|
5951
|
+
if (property === "animation-name") return resolveAnimationNameSlot(valueRaw, slotExprById, keyframesNames, j);
|
|
5952
|
+
if (valueRaw.includes(",")) return null;
|
|
5953
|
+
return resolveAnimationShorthandSlots(valueRaw, slotExprById, keyframesNames, j, inlineKeyframeNameMap);
|
|
5954
|
+
}
|
|
5955
|
+
/** Resolves `animation-name: ${kf}` where the sole slot is a keyframes identifier. */
|
|
5956
|
+
function resolveAnimationNameSlot(valueRaw, slotExprById, keyframesNames, j) {
|
|
5957
|
+
const kfName = extractKeyframesIdentifierFromSlot(valueRaw, slotExprById, keyframesNames);
|
|
5958
|
+
if (!kfName) return null;
|
|
5959
|
+
return { animationName: j.identifier(kfName) };
|
|
5960
|
+
}
|
|
5961
|
+
/** Resolves `animation: ${kf} 1.6s ease-in-out infinite` by replacing placeholders and expanding. */
|
|
5962
|
+
function resolveAnimationShorthandSlots(valueRaw, slotExprById, keyframesNames, j, inlineKeyframeNameMap) {
|
|
5963
|
+
let modifiedValue = valueRaw;
|
|
5964
|
+
const usedKeyframeNames = /* @__PURE__ */ new Set();
|
|
5965
|
+
const placeholderRe = /__SC_EXPR_(\d+)__/g;
|
|
5966
|
+
let match;
|
|
5967
|
+
while (match = placeholderRe.exec(valueRaw)) {
|
|
5968
|
+
const slotId = Number(match[1]);
|
|
5969
|
+
const expr = slotExprById.get(slotId);
|
|
5970
|
+
if (!expr || expr.type !== "Identifier" || !expr.name || !keyframesNames.has(expr.name)) return null;
|
|
5971
|
+
modifiedValue = modifiedValue.replace(match[0], expr.name);
|
|
5972
|
+
usedKeyframeNames.add(expr.name);
|
|
5973
|
+
}
|
|
5974
|
+
if (usedKeyframeNames.size === 0) return null;
|
|
5975
|
+
const expanded = {};
|
|
5976
|
+
if (expandStaticAnimationShorthand(modifiedValue, usedKeyframeNames, j, expanded, inlineKeyframeNameMap)) return expanded;
|
|
5977
|
+
return null;
|
|
5978
|
+
}
|
|
5979
|
+
/**
|
|
5980
|
+
* If `valueRaw` is exactly a single `__SC_EXPR_N__` placeholder whose slot
|
|
5981
|
+
* expression is a keyframes identifier, returns the identifier name.
|
|
5982
|
+
*/
|
|
5983
|
+
function extractKeyframesIdentifierFromSlot(valueRaw, slotExprById, keyframesNames) {
|
|
5984
|
+
const m = valueRaw.match(/^__SC_EXPR_(\d+)__$/);
|
|
5985
|
+
if (!m) return null;
|
|
5986
|
+
const slotId = Number(m[1]);
|
|
5987
|
+
const expr = slotExprById.get(slotId);
|
|
5988
|
+
if (!expr || expr.type !== "Identifier" || !expr.name || !keyframesNames.has(expr.name)) return null;
|
|
5989
|
+
return expr.name;
|
|
5990
|
+
}
|
|
5936
5991
|
|
|
5937
5992
|
//#endregion
|
|
5938
5993
|
//#region src/internal/transform-steps/convert-keyframes.ts
|
|
@@ -6439,7 +6494,8 @@ function emptyOkVariantOutcome(hasLocalCallsites, usedConsumedPropsAtCallSites)
|
|
|
6439
6494
|
usedConsumedPropsAtCallSites,
|
|
6440
6495
|
foldedBaseSx: {},
|
|
6441
6496
|
bakedInConsumedProps: [],
|
|
6442
|
-
staticBooleanVariants: []
|
|
6497
|
+
staticBooleanVariants: [],
|
|
6498
|
+
callSiteCombinedStyles: []
|
|
6443
6499
|
};
|
|
6444
6500
|
}
|
|
6445
6501
|
function applyBaseComponentResolution(ctx, styledDecls) {
|
|
@@ -6490,7 +6546,8 @@ function applyBaseComponentResolution(ctx, styledDecls) {
|
|
|
6490
6546
|
usedConsumedPropsAtCallSites: variantOutcome.usedConsumedPropsAtCallSites,
|
|
6491
6547
|
foldedBaseSx: variantOutcome.foldedBaseSx,
|
|
6492
6548
|
bakedInConsumedProps: variantOutcome.bakedInConsumedProps,
|
|
6493
|
-
staticBooleanVariants: variantOutcome.staticBooleanVariants
|
|
6549
|
+
staticBooleanVariants: variantOutcome.staticBooleanVariants,
|
|
6550
|
+
callSiteCombinedStyles: variantOutcome.callSiteCombinedStyles
|
|
6494
6551
|
});
|
|
6495
6552
|
}
|
|
6496
6553
|
}
|
|
@@ -6644,7 +6701,7 @@ function buildInlineResolverVariantDimensions(args) {
|
|
|
6644
6701
|
continue;
|
|
6645
6702
|
}
|
|
6646
6703
|
const [singleKey, singleVariantStyles] = Object.entries(variants)[0];
|
|
6647
|
-
if (singleKey
|
|
6704
|
+
if (isSingleVariantKeyTruthy(singleKey, booleanOnlyProps.has(propName))) {
|
|
6648
6705
|
staticBooleanVariants.push({
|
|
6649
6706
|
propName,
|
|
6650
6707
|
styleKey: `${decl.styleKey}${toSuffixFromProp(propName)}`,
|
|
@@ -6661,6 +6718,31 @@ function buildInlineResolverVariantDimensions(args) {
|
|
|
6661
6718
|
propTypeFromKeyof: true
|
|
6662
6719
|
});
|
|
6663
6720
|
}
|
|
6721
|
+
const callSiteCombinedStyles = buildCallSiteCombinedStyles({
|
|
6722
|
+
decl,
|
|
6723
|
+
staticBooleanVariants,
|
|
6724
|
+
dimensions,
|
|
6725
|
+
baseSx: {
|
|
6726
|
+
...baseResult.sx,
|
|
6727
|
+
...foldedBaseSx
|
|
6728
|
+
},
|
|
6729
|
+
propsByUsage: usageResult.propsByUsage,
|
|
6730
|
+
hasCompleteCallsiteVisibility: !willHaveExternalInterface(ctx, decl, styledDecls) && !decl.usedAsValue,
|
|
6731
|
+
hasPropReferencingTemplateExpressions: (decl.templateExpressions ?? []).some((expr) => {
|
|
6732
|
+
const type = expr?.type;
|
|
6733
|
+
return type === "ArrowFunctionExpression" || type === "FunctionExpression";
|
|
6734
|
+
})
|
|
6735
|
+
});
|
|
6736
|
+
if (callSiteCombinedStyles) return {
|
|
6737
|
+
kind: "ok",
|
|
6738
|
+
variantDimensions: dimensions,
|
|
6739
|
+
hasLocalCallsites,
|
|
6740
|
+
usedConsumedPropsAtCallSites,
|
|
6741
|
+
foldedBaseSx,
|
|
6742
|
+
bakedInConsumedProps,
|
|
6743
|
+
staticBooleanVariants: [],
|
|
6744
|
+
callSiteCombinedStyles
|
|
6745
|
+
};
|
|
6664
6746
|
return {
|
|
6665
6747
|
kind: "ok",
|
|
6666
6748
|
variantDimensions: dimensions,
|
|
@@ -6668,7 +6750,8 @@ function buildInlineResolverVariantDimensions(args) {
|
|
|
6668
6750
|
usedConsumedPropsAtCallSites,
|
|
6669
6751
|
foldedBaseSx,
|
|
6670
6752
|
bakedInConsumedProps,
|
|
6671
|
-
staticBooleanVariants
|
|
6753
|
+
staticBooleanVariants,
|
|
6754
|
+
callSiteCombinedStyles: []
|
|
6672
6755
|
};
|
|
6673
6756
|
}
|
|
6674
6757
|
/**
|
|
@@ -6804,12 +6887,59 @@ function diffSx(baseSx, siteSx) {
|
|
|
6804
6887
|
for (const [prop, value] of Object.entries(siteSx)) if (!(prop in baseSx)) out[prop] = value;
|
|
6805
6888
|
return out;
|
|
6806
6889
|
}
|
|
6890
|
+
/**
|
|
6891
|
+
* For direct JSX resolution, merges individual single-key variant styles into
|
|
6892
|
+
* combined per-call-site entries. Returns the combined styles, or null if
|
|
6893
|
+
* combining is not applicable (e.g., multi-key variants, wrapper components).
|
|
6894
|
+
*/
|
|
6895
|
+
function buildCallSiteCombinedStyles(args) {
|
|
6896
|
+
const { decl, staticBooleanVariants, dimensions, baseSx, propsByUsage, hasCompleteCallsiteVisibility, hasPropReferencingTemplateExpressions } = args;
|
|
6897
|
+
if (!decl.isDirectJsxResolution || !hasCompleteCallsiteVisibility || hasPropReferencingTemplateExpressions || staticBooleanVariants.length < 2 || dimensions.length > 0) return null;
|
|
6898
|
+
const variantsByProp = new Map(staticBooleanVariants.map((v) => [v.propName, v]));
|
|
6899
|
+
const combinationGroups = /* @__PURE__ */ new Map();
|
|
6900
|
+
for (const siteProps of propsByUsage) {
|
|
6901
|
+
const matchingPropNames = Object.keys(siteProps).filter((p) => variantsByProp.has(p)).sort();
|
|
6902
|
+
if (matchingPropNames.length === 0) continue;
|
|
6903
|
+
const groupKey = matchingPropNames.join(",");
|
|
6904
|
+
if (combinationGroups.has(groupKey)) continue;
|
|
6905
|
+
const mergedStyles = { ...baseSx };
|
|
6906
|
+
for (const propName of matchingPropNames) {
|
|
6907
|
+
const variant = variantsByProp.get(propName);
|
|
6908
|
+
Object.assign(mergedStyles, variant.styles);
|
|
6909
|
+
}
|
|
6910
|
+
combinationGroups.set(groupKey, {
|
|
6911
|
+
propNames: matchingPropNames,
|
|
6912
|
+
styles: mergedStyles
|
|
6913
|
+
});
|
|
6914
|
+
}
|
|
6915
|
+
if (combinationGroups.size === 0 || combinationGroups.size >= staticBooleanVariants.length) return null;
|
|
6916
|
+
const result = [];
|
|
6917
|
+
for (const [, { propNames, styles }] of combinationGroups) {
|
|
6918
|
+
const suffix = propNames.map((p) => toSuffixFromProp(p)).join("");
|
|
6919
|
+
result.push({
|
|
6920
|
+
propNames,
|
|
6921
|
+
styleKey: `${decl.styleKey}${suffix}`,
|
|
6922
|
+
styles
|
|
6923
|
+
});
|
|
6924
|
+
}
|
|
6925
|
+
return result;
|
|
6926
|
+
}
|
|
6927
|
+
/**
|
|
6928
|
+
* Checks whether a single variant key represents a value that is truthy at runtime.
|
|
6929
|
+
* For boolean props, only `"true"` is truthy (`false` is falsy).
|
|
6930
|
+
* For non-boolean props (numbers, strings), "0" and "" are falsy; everything else is truthy.
|
|
6931
|
+
* Falsy values cannot use the truthy-guard pattern (`prop && styles.key`) safely.
|
|
6932
|
+
*/
|
|
6933
|
+
function isSingleVariantKeyTruthy(key, isBooleanProp) {
|
|
6934
|
+
if (isBooleanProp) return key === "true";
|
|
6935
|
+
return key !== "0" && key !== "";
|
|
6936
|
+
}
|
|
6807
6937
|
function serializeRecord(record) {
|
|
6808
6938
|
const ordered = Object.keys(record).sort().map((key) => [key, record[key]]);
|
|
6809
6939
|
return JSON.stringify(ordered);
|
|
6810
6940
|
}
|
|
6811
6941
|
function inlineResolvedBaseComponent(args) {
|
|
6812
|
-
const { ctx, decl, baseStaticProps, importSource, importedName, baseResult, consumedProps, variantDimensions, hasLocalCallsites, usedConsumedPropsAtCallSites, foldedBaseSx, bakedInConsumedProps, staticBooleanVariants } = args;
|
|
6942
|
+
const { ctx, decl, baseStaticProps, importSource, importedName, baseResult, consumedProps, variantDimensions, hasLocalCallsites, usedConsumedPropsAtCallSites, foldedBaseSx, bakedInConsumedProps, staticBooleanVariants, callSiteCombinedStyles } = args;
|
|
6813
6943
|
const sxRule = createRuleFromStylexDeclarations(Object.keys(foldedBaseSx).length > 0 ? {
|
|
6814
6944
|
...baseResult.sx,
|
|
6815
6945
|
...foldedBaseSx
|
|
@@ -6853,6 +6983,7 @@ function inlineResolvedBaseComponent(args) {
|
|
|
6853
6983
|
};
|
|
6854
6984
|
if (variantDimensions.length > 0) decl.variantDimensions = [...decl.variantDimensions ?? [], ...variantDimensions];
|
|
6855
6985
|
if (staticBooleanVariants.length > 0) decl.staticBooleanVariants = [...decl.staticBooleanVariants ?? [], ...staticBooleanVariants];
|
|
6986
|
+
if (callSiteCombinedStyles.length > 0) decl.callSiteCombinedStyles = [...decl.callSiteCombinedStyles ?? [], ...callSiteCombinedStyles];
|
|
6856
6987
|
decl.inlinedBaseComponent = {
|
|
6857
6988
|
importSource,
|
|
6858
6989
|
importedName,
|
|
@@ -6986,7 +7117,8 @@ function resolveDirectJsxUsages(ctx, styledDecls) {
|
|
|
6986
7117
|
usedConsumedPropsAtCallSites: variantOutcome.usedConsumedPropsAtCallSites,
|
|
6987
7118
|
foldedBaseSx: variantOutcome.foldedBaseSx,
|
|
6988
7119
|
bakedInConsumedProps: variantOutcome.bakedInConsumedProps,
|
|
6989
|
-
staticBooleanVariants: variantOutcome.staticBooleanVariants
|
|
7120
|
+
staticBooleanVariants: variantOutcome.staticBooleanVariants,
|
|
7121
|
+
callSiteCombinedStyles: variantOutcome.callSiteCombinedStyles
|
|
6990
7122
|
});
|
|
6991
7123
|
usedStyleKeys.add(syntheticDecl.styleKey);
|
|
6992
7124
|
styledDecls.push(syntheticDecl);
|
|
@@ -10273,7 +10405,7 @@ function emitSimpleWithConfigWrappers(ctx) {
|
|
|
10273
10405
|
allowAsProp,
|
|
10274
10406
|
allowClassNameProp: false,
|
|
10275
10407
|
allowStyleProp: false,
|
|
10276
|
-
includeRefProp: d.supportsRefProp ?? false,
|
|
10408
|
+
includeRefProp: (d.supportsRefProp ?? false) || !includeRest && willForwardRef,
|
|
10277
10409
|
includeRest,
|
|
10278
10410
|
defaultAttrs: d.attrsInfo?.defaultAttrs ?? [],
|
|
10279
10411
|
conditionalAttrs: d.attrsInfo?.conditionalAttrs ?? [],
|
|
@@ -10680,7 +10812,7 @@ function emitSimpleExportedIntrinsicWrappers(ctx) {
|
|
|
10680
10812
|
...allowClassNameProp ? [ctx.patternProp("className", classNameId)] : [],
|
|
10681
10813
|
...includeChildren ? [ctx.patternProp("children", childrenId)] : [],
|
|
10682
10814
|
...allowStyleProp ? [ctx.patternProp("style", styleId)] : [],
|
|
10683
|
-
...d.supportsRefProp ?? false ? [ctx.patternProp("ref", refId)] : [],
|
|
10815
|
+
...(d.supportsRefProp ?? false) || !restId && willForwardRef ? [ctx.patternProp("ref", refId)] : [],
|
|
10684
10816
|
...allowSxProp ? [ctx.patternProp("sx", sxId)] : []
|
|
10685
10817
|
],
|
|
10686
10818
|
destructureProps,
|
|
@@ -10712,7 +10844,7 @@ function emitSimpleExportedIntrinsicWrappers(ctx) {
|
|
|
10712
10844
|
attrsInfo: attrsInfoWithoutForwardedAsStatic,
|
|
10713
10845
|
propExprFor: (prop) => j.identifier(prop)
|
|
10714
10846
|
}),
|
|
10715
|
-
...d.supportsRefProp ?? false ? [j.jsxAttribute(j.jsxIdentifier("ref"), j.jsxExpressionContainer(refId))] : [],
|
|
10847
|
+
...(d.supportsRefProp ?? false) || !restId && willForwardRef ? [j.jsxAttribute(j.jsxIdentifier("ref"), j.jsxExpressionContainer(refId))] : [],
|
|
10716
10848
|
...restId ? [j.jsxSpreadAttribute(restId)] : [],
|
|
10717
10849
|
...includesForwardedAs ? [j.jsxAttribute(j.jsxIdentifier("as"), j.jsxExpressionContainer(buildForwardedAsValueExpr(forwardedAsId, forwardedAsStaticFallback)))] : []
|
|
10718
10850
|
];
|
|
@@ -10748,7 +10880,7 @@ function emitSimpleExportedIntrinsicWrappers(ctx) {
|
|
|
10748
10880
|
allowAsProp,
|
|
10749
10881
|
allowClassNameProp: false,
|
|
10750
10882
|
allowStyleProp: false,
|
|
10751
|
-
includeRefProp: d.supportsRefProp ?? false,
|
|
10883
|
+
includeRefProp: (d.supportsRefProp ?? false) || !shouldIncludeRest && willForwardRef,
|
|
10752
10884
|
includeRest: shouldIncludeRest,
|
|
10753
10885
|
defaultAttrs: d.attrsInfo?.defaultAttrs ?? [],
|
|
10754
10886
|
conditionalAttrs: d.attrsInfo?.conditionalAttrs ?? [],
|
|
@@ -13672,6 +13804,149 @@ function buildInterpolatedTemplate(args) {
|
|
|
13672
13804
|
return j.templateLiteral(quasis, exprs);
|
|
13673
13805
|
}
|
|
13674
13806
|
|
|
13807
|
+
//#endregion
|
|
13808
|
+
//#region src/internal/lower-rules/utils.ts
|
|
13809
|
+
/**
|
|
13810
|
+
* Shared lower-rules helpers for merging and formatting style objects.
|
|
13811
|
+
* Core concepts: deep merge semantics, AST node detection, and media query resolution.
|
|
13812
|
+
*/
|
|
13813
|
+
/** Returns true for at-rules the codemod can transform (`@media`, `@container`). */
|
|
13814
|
+
function isSupportedAtRule(atRule) {
|
|
13815
|
+
return atRule.startsWith("@media") || atRule.startsWith("@container");
|
|
13816
|
+
}
|
|
13817
|
+
/** Finds the first supported at-rule (`@media` or `@container`) in the stack, if any. */
|
|
13818
|
+
function findSupportedAtRule(atRuleStack) {
|
|
13819
|
+
return atRuleStack.find(isSupportedAtRule);
|
|
13820
|
+
}
|
|
13821
|
+
/**
|
|
13822
|
+
* Resolves a media/container at-rule string that may contain `__SC_EXPR_N__` placeholders.
|
|
13823
|
+
*
|
|
13824
|
+
* First tries `resolveSelector` (when available) to produce a computed key like
|
|
13825
|
+
* `[breakpoints.phone]`. Falls back to static value substitution.
|
|
13826
|
+
*
|
|
13827
|
+
* Returns null if the placeholder cannot be resolved at all.
|
|
13828
|
+
*/
|
|
13829
|
+
function resolveMediaAtRulePlaceholders(media, getSlotExpr, ctx) {
|
|
13830
|
+
if (!media.includes("__SC_EXPR_")) return {
|
|
13831
|
+
kind: "static",
|
|
13832
|
+
value: media
|
|
13833
|
+
};
|
|
13834
|
+
const globalRe = new RegExp(PLACEHOLDER_RE.source, "g");
|
|
13835
|
+
const matches = [...media.matchAll(globalRe)];
|
|
13836
|
+
if (matches.length === 1 && ctx.resolveSelector && ctx.parseExpr) {
|
|
13837
|
+
const expr = getSlotExpr(Number(matches[0][1]));
|
|
13838
|
+
if (expr && typeof expr === "object") {
|
|
13839
|
+
const info = extractRootAndPath(expr);
|
|
13840
|
+
if (info) {
|
|
13841
|
+
const imp = ctx.lookupImport(info.rootName, info.rootNode);
|
|
13842
|
+
if (imp) {
|
|
13843
|
+
const result = ctx.resolveSelector({
|
|
13844
|
+
kind: "selectorInterpolation",
|
|
13845
|
+
importedName: imp.importedName,
|
|
13846
|
+
source: imp.source,
|
|
13847
|
+
path: info.path.length > 0 ? info.path.join(".") : void 0,
|
|
13848
|
+
filePath: ctx.filePath
|
|
13849
|
+
});
|
|
13850
|
+
if (result?.kind === "media") {
|
|
13851
|
+
const keyExpr = ctx.parseExpr(result.expr);
|
|
13852
|
+
if (keyExpr) {
|
|
13853
|
+
for (const impSpec of result.imports ?? []) ctx.resolverImports.set(JSON.stringify(impSpec), impSpec);
|
|
13854
|
+
return {
|
|
13855
|
+
kind: "computed",
|
|
13856
|
+
keyExpr,
|
|
13857
|
+
imports: result.imports ?? []
|
|
13858
|
+
};
|
|
13859
|
+
}
|
|
13860
|
+
}
|
|
13861
|
+
}
|
|
13862
|
+
}
|
|
13863
|
+
}
|
|
13864
|
+
}
|
|
13865
|
+
const resolved = resolveMediaQueryPlaceholders(media, (slotId) => resolveSlotExprToStaticValue(getSlotExpr(slotId), ctx.lookupImport, ctx.resolveValue, ctx.filePath, ctx.resolverImports));
|
|
13866
|
+
if (resolved === null) return null;
|
|
13867
|
+
return {
|
|
13868
|
+
kind: "static",
|
|
13869
|
+
value: resolved
|
|
13870
|
+
};
|
|
13871
|
+
}
|
|
13872
|
+
/** Returns true if the key looks like a StyleX style condition (pseudo, media, container). */
|
|
13873
|
+
function isStyleConditionKey(key) {
|
|
13874
|
+
return key.startsWith(":") || key.startsWith("::") || key.startsWith("@media") || key.startsWith("@container");
|
|
13875
|
+
}
|
|
13876
|
+
/**
|
|
13877
|
+
* Merges tracked @media values into a base style object as nested StyleX objects.
|
|
13878
|
+
* Each property that has media-scoped values is wrapped in:
|
|
13879
|
+
* `{ default: baseValue, "@media (...)": mediaValue }`
|
|
13880
|
+
*/
|
|
13881
|
+
function mergeMediaIntoStyles(base, mediaStyles) {
|
|
13882
|
+
for (const [mediaQuery, mediaStyle] of mediaStyles) for (const [prop, mediaValue] of Object.entries(mediaStyle)) base[prop] = {
|
|
13883
|
+
default: base[prop] ?? null,
|
|
13884
|
+
[mediaQuery]: mediaValue
|
|
13885
|
+
};
|
|
13886
|
+
}
|
|
13887
|
+
/**
|
|
13888
|
+
* Recursively merges style objects, combining nested objects rather than overwriting.
|
|
13889
|
+
*
|
|
13890
|
+
* Note: Security scanners may flag this as prototype pollution, but this is a false positive.
|
|
13891
|
+
* This is a codemod that runs locally on the developer's own source code - there is no
|
|
13892
|
+
* untrusted input that could exploit prototype pollution. The source objects are style
|
|
13893
|
+
* declarations extracted from the developer's own styled-components code.
|
|
13894
|
+
*/
|
|
13895
|
+
function mergeStyleObjects(target, source) {
|
|
13896
|
+
for (const [key, value] of Object.entries(source)) {
|
|
13897
|
+
const existing = target[key];
|
|
13898
|
+
if (existing && value && typeof existing === "object" && typeof value === "object" && !Array.isArray(existing) && !Array.isArray(value) && !isAstNode(existing) && !isAstNode(value)) mergeStyleObjects(existing, value);
|
|
13899
|
+
else target[key] = value;
|
|
13900
|
+
}
|
|
13901
|
+
}
|
|
13902
|
+
/** Resolves `__SC_EXPR_N__` placeholders in a string to static values via a callback. */
|
|
13903
|
+
function resolveMediaQueryPlaceholders(mediaQuery, resolveSlot) {
|
|
13904
|
+
if (!mediaQuery.includes("__SC_EXPR_")) return mediaQuery;
|
|
13905
|
+
const globalRe = new RegExp(PLACEHOLDER_RE.source, "g");
|
|
13906
|
+
const matches = [];
|
|
13907
|
+
let match;
|
|
13908
|
+
while ((match = globalRe.exec(mediaQuery)) !== null) matches.push({
|
|
13909
|
+
full: match[0],
|
|
13910
|
+
slotId: Number(match[1])
|
|
13911
|
+
});
|
|
13912
|
+
let resolved = mediaQuery;
|
|
13913
|
+
for (const m of matches) {
|
|
13914
|
+
const staticVal = resolveSlot(m.slotId);
|
|
13915
|
+
if (staticVal === null) return null;
|
|
13916
|
+
resolved = resolved.replace(m.full, String(staticVal));
|
|
13917
|
+
}
|
|
13918
|
+
return resolved;
|
|
13919
|
+
}
|
|
13920
|
+
/** Resolves a slot expression AST node to a static string or number via the adapter. */
|
|
13921
|
+
function resolveSlotExprToStaticValue(expr, lookupImport, resolveValue, filePath, resolverImports) {
|
|
13922
|
+
if (!expr || typeof expr !== "object") return null;
|
|
13923
|
+
const staticVal = literalToStaticValue(expr);
|
|
13924
|
+
if (typeof staticVal === "string" || typeof staticVal === "number") return staticVal;
|
|
13925
|
+
const info = extractRootAndPath(expr);
|
|
13926
|
+
if (!info) return null;
|
|
13927
|
+
const imp = lookupImport(info.rootName, info.rootNode);
|
|
13928
|
+
if (!imp) return null;
|
|
13929
|
+
const result = resolveValue({
|
|
13930
|
+
kind: "importedValue",
|
|
13931
|
+
importedName: imp.importedName,
|
|
13932
|
+
source: imp.source,
|
|
13933
|
+
...info.path.length > 0 ? { path: info.path.join(".") } : {},
|
|
13934
|
+
filePath
|
|
13935
|
+
});
|
|
13936
|
+
if (!result || !("expr" in result)) return null;
|
|
13937
|
+
for (const impSpec of result.imports ?? []) resolverImports.set(JSON.stringify(impSpec), impSpec);
|
|
13938
|
+
return parseStaticExprString(result.expr);
|
|
13939
|
+
}
|
|
13940
|
+
/** Parses a JS expression string as a static numeric or quoted string value. */
|
|
13941
|
+
function parseStaticExprString(expr) {
|
|
13942
|
+
const trimmed = expr.trim();
|
|
13943
|
+
if (!trimmed) return null;
|
|
13944
|
+
const num = Number(trimmed);
|
|
13945
|
+
if (!isNaN(num) && trimmed !== "") return num;
|
|
13946
|
+
if (trimmed.startsWith("\"") && trimmed.endsWith("\"") || trimmed.startsWith("'") && trimmed.endsWith("'")) return trimmed.slice(1, -1);
|
|
13947
|
+
return null;
|
|
13948
|
+
}
|
|
13949
|
+
|
|
13675
13950
|
//#endregion
|
|
13676
13951
|
//#region src/internal/lower-rules/css-helper.ts
|
|
13677
13952
|
/**
|
|
@@ -13816,14 +14091,15 @@ function createCssHelperResolver(args) {
|
|
|
13816
14091
|
exprString: JSON.stringify(v)
|
|
13817
14092
|
};
|
|
13818
14093
|
}
|
|
13819
|
-
|
|
13820
|
-
|
|
13821
|
-
const imp = importMap.get(
|
|
14094
|
+
const info = extractRootAndPath(branch);
|
|
14095
|
+
if (info) {
|
|
14096
|
+
const imp = importMap.get(info.rootName);
|
|
13822
14097
|
if (imp) {
|
|
13823
14098
|
const res = resolveValue({
|
|
13824
14099
|
kind: "importedValue",
|
|
13825
14100
|
importedName: imp.importedName,
|
|
13826
14101
|
source: imp.source,
|
|
14102
|
+
...info.path.length > 0 ? { path: info.path.join(".") } : {},
|
|
13827
14103
|
filePath,
|
|
13828
14104
|
loc: getNodeLocStart(branch) ?? void 0
|
|
13829
14105
|
});
|
|
@@ -13835,9 +14111,9 @@ function createCssHelperResolver(args) {
|
|
|
13835
14111
|
exprString: res.expr
|
|
13836
14112
|
} : null;
|
|
13837
14113
|
}
|
|
13838
|
-
return {
|
|
14114
|
+
if (branch.type === "Identifier") return {
|
|
13839
14115
|
ast: branch,
|
|
13840
|
-
exprString:
|
|
14116
|
+
exprString: info.rootName
|
|
13841
14117
|
};
|
|
13842
14118
|
}
|
|
13843
14119
|
return null;
|
|
@@ -13872,9 +14148,28 @@ function createCssHelperResolver(args) {
|
|
|
13872
14148
|
const dynamicProps = [];
|
|
13873
14149
|
const dynamicPropKeys = /* @__PURE__ */ new Set();
|
|
13874
14150
|
const conditionalVariants = [];
|
|
14151
|
+
const lookupImport = (localName) => importMap.get(localName) ?? null;
|
|
13875
14152
|
for (const rule of rules) {
|
|
13876
|
-
const
|
|
13877
|
-
if (rule.atRuleStack.length > 0 && !
|
|
14153
|
+
const rawMedia = findSupportedAtRule(rule.atRuleStack);
|
|
14154
|
+
if (rule.atRuleStack.length > 0 && !rawMedia) return bail("Conditional `css` block: @-rules (e.g., @media, @supports) are not supported");
|
|
14155
|
+
let media = rawMedia;
|
|
14156
|
+
let computedMediaKey = null;
|
|
14157
|
+
if (rawMedia) {
|
|
14158
|
+
const resolved = resolveMediaAtRulePlaceholders(rawMedia, (slotId) => slotExprById.get(slotId), {
|
|
14159
|
+
lookupImport,
|
|
14160
|
+
resolveValue,
|
|
14161
|
+
resolveSelector: args.resolveSelector,
|
|
14162
|
+
parseExpr,
|
|
14163
|
+
filePath,
|
|
14164
|
+
resolverImports
|
|
14165
|
+
});
|
|
14166
|
+
if (resolved === null) return bail("Conditional `css` block: media query interpolation must be a simple imported reference (expressions like `value + 1` are not supported)");
|
|
14167
|
+
if (resolved.kind === "static") media = resolved.value;
|
|
14168
|
+
else {
|
|
14169
|
+
computedMediaKey = resolved;
|
|
14170
|
+
media = void 0;
|
|
14171
|
+
}
|
|
14172
|
+
}
|
|
13878
14173
|
const selector = (rule.selector ?? "").trim();
|
|
13879
14174
|
const allowDynamicValues = selector === "&";
|
|
13880
14175
|
let target = out;
|
|
@@ -13906,7 +14201,19 @@ function createCssHelperResolver(args) {
|
|
|
13906
14201
|
}
|
|
13907
14202
|
const mergeIntoContext = (value, prop, targetObj) => {
|
|
13908
14203
|
const existing = targetObj[prop];
|
|
13909
|
-
if (
|
|
14204
|
+
if (computedMediaKey) {
|
|
14205
|
+
const nested = existing && typeof existing === "object" && !Array.isArray(existing) && !isAstNode(existing) ? existing : { default: existing ?? null };
|
|
14206
|
+
if (!("default" in nested)) nested.default = null;
|
|
14207
|
+
nested.__computedKeys = [...nested.__computedKeys ?? [], {
|
|
14208
|
+
keyExpr: computedMediaKey.keyExpr,
|
|
14209
|
+
value
|
|
14210
|
+
}];
|
|
14211
|
+
return nested;
|
|
14212
|
+
}
|
|
14213
|
+
if (media && currentPseudoClass) {
|
|
14214
|
+
const pseudoExisting = existing && typeof existing === "object" && !Array.isArray(existing) && !isAstNode(existing) ? existing[currentPseudoClass] : void 0;
|
|
14215
|
+
return mergeIntoPseudoContext(mergeIntoPseudoContext(value, media, pseudoExisting), currentPseudoClass, existing);
|
|
14216
|
+
}
|
|
13910
14217
|
if (media) return mergeIntoPseudoContext(value, media, existing);
|
|
13911
14218
|
return mergeIntoPseudoContext(value, currentPseudoClass, existing);
|
|
13912
14219
|
};
|
|
@@ -13933,6 +14240,20 @@ function createCssHelperResolver(args) {
|
|
|
13933
14240
|
continue;
|
|
13934
14241
|
}
|
|
13935
14242
|
if (d.important) return bail("Conditional `css` block: !important is not supported in StyleX", { property: d.property });
|
|
14243
|
+
if ((d.property === "animation" || d.property === "animation-name") && args.keyframesNames && args.keyframesNames.size > 0 && args.j) {
|
|
14244
|
+
const expanded = expandInterpolatedAnimationShorthand({
|
|
14245
|
+
property: d.property,
|
|
14246
|
+
valueRaw: d.valueRaw,
|
|
14247
|
+
slotExprById,
|
|
14248
|
+
keyframesNames: args.keyframesNames,
|
|
14249
|
+
j: args.j,
|
|
14250
|
+
inlineKeyframeNameMap: args.inlineKeyframeNameMap
|
|
14251
|
+
});
|
|
14252
|
+
if (expanded) {
|
|
14253
|
+
for (const [prop, value] of Object.entries(expanded)) target[prop] = mergeIntoContext(value, prop, target);
|
|
14254
|
+
continue;
|
|
14255
|
+
}
|
|
14256
|
+
}
|
|
13936
14257
|
const parts = d.value.parts ?? [];
|
|
13937
14258
|
const slotParts = parts.filter((p) => p.kind === "slot");
|
|
13938
14259
|
if (slotParts.length !== 1) return bail("Conditional `css` block: multiple interpolation slots in a single property value", { property: d.property });
|
|
@@ -14484,6 +14805,7 @@ function createLowerRulesState(ctx) {
|
|
|
14484
14805
|
importMap,
|
|
14485
14806
|
filePath,
|
|
14486
14807
|
resolveValue,
|
|
14808
|
+
resolveSelector,
|
|
14487
14809
|
parseExpr,
|
|
14488
14810
|
resolverImports,
|
|
14489
14811
|
warnings,
|
|
@@ -14556,39 +14878,6 @@ function createLowerRulesState(ctx) {
|
|
|
14556
14878
|
return state;
|
|
14557
14879
|
}
|
|
14558
14880
|
|
|
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
14881
|
//#endregion
|
|
14593
14882
|
//#region src/internal/lower-rules/variant-utils.ts
|
|
14594
14883
|
/**
|
|
@@ -16933,8 +17222,8 @@ function tryResolveInlineStyleValueForNestedPropAccess(node) {
|
|
|
16933
17222
|
}
|
|
16934
17223
|
function tryResolveInlineStyleValueFromArrowFn(node) {
|
|
16935
17224
|
if (!node.css.property) return null;
|
|
16936
|
-
const hasMediaAtRule = (node.css.atRuleStack ?? []).some(
|
|
16937
|
-
const isMediaSelector = (node.css.selector ?? "").trim()
|
|
17225
|
+
const hasMediaAtRule = (node.css.atRuleStack ?? []).some(isSupportedAtRule);
|
|
17226
|
+
const isMediaSelector = isSupportedAtRule((node.css.selector ?? "").trim());
|
|
16938
17227
|
if (!hasMediaAtRule && !isMediaSelector) return null;
|
|
16939
17228
|
const expr = node.expr;
|
|
16940
17229
|
if (!isArrowFunctionExpression(expr)) return null;
|
|
@@ -17032,7 +17321,7 @@ function resolveTemplateLiteralBranch(ctx, args) {
|
|
|
17032
17321
|
const inlineEntries = [];
|
|
17033
17322
|
const mediaStyles = /* @__PURE__ */ new Map();
|
|
17034
17323
|
for (const rule of rules) {
|
|
17035
|
-
|
|
17324
|
+
let media = findSupportedAtRule(rule.atRuleStack);
|
|
17036
17325
|
if (rule.atRuleStack.length > 0 && !media) {
|
|
17037
17326
|
ctx.warnings?.push({
|
|
17038
17327
|
severity: "warning",
|
|
@@ -17041,8 +17330,36 @@ function resolveTemplateLiteralBranch(ctx, args) {
|
|
|
17041
17330
|
});
|
|
17042
17331
|
return null;
|
|
17043
17332
|
}
|
|
17333
|
+
let computedMediaKeyExpr;
|
|
17334
|
+
if (media) {
|
|
17335
|
+
const resolved = resolveMediaAtRulePlaceholders(media, (slotId) => slotExprById.get(slotId), {
|
|
17336
|
+
lookupImport: resolveImportInScope,
|
|
17337
|
+
resolveValue,
|
|
17338
|
+
resolveSelector: ctx.resolveSelector,
|
|
17339
|
+
parseExpr,
|
|
17340
|
+
filePath,
|
|
17341
|
+
resolverImports
|
|
17342
|
+
});
|
|
17343
|
+
if (resolved === null) return null;
|
|
17344
|
+
if (resolved.kind === "static") media = resolved.value;
|
|
17345
|
+
else {
|
|
17346
|
+
computedMediaKeyExpr = resolved.keyExpr;
|
|
17347
|
+
media = void 0;
|
|
17348
|
+
}
|
|
17349
|
+
}
|
|
17044
17350
|
if ((rule.selector ?? "").trim() !== "&") return null;
|
|
17045
17351
|
const setStyleValue = (prop, value) => {
|
|
17352
|
+
if (computedMediaKeyExpr) {
|
|
17353
|
+
const existing = style[prop];
|
|
17354
|
+
const nested = existing && typeof existing === "object" && !Array.isArray(existing) ? existing : { default: existing ?? null };
|
|
17355
|
+
if (!("default" in nested)) nested.default = null;
|
|
17356
|
+
nested.__computedKeys = [...nested.__computedKeys ?? [], {
|
|
17357
|
+
keyExpr: computedMediaKeyExpr,
|
|
17358
|
+
value
|
|
17359
|
+
}];
|
|
17360
|
+
style[prop] = nested;
|
|
17361
|
+
return;
|
|
17362
|
+
}
|
|
17046
17363
|
if (media) {
|
|
17047
17364
|
const target = mediaStyles.get(media) ?? {};
|
|
17048
17365
|
mediaStyles.set(media, target);
|
|
@@ -17072,6 +17389,20 @@ function resolveTemplateLiteralBranch(ctx, args) {
|
|
|
17072
17389
|
continue;
|
|
17073
17390
|
}
|
|
17074
17391
|
if (d.value.kind !== "interpolated") return null;
|
|
17392
|
+
if ((d.property === "animation" || d.property === "animation-name") && ctx.keyframesNames && ctx.keyframesNames.size > 0) {
|
|
17393
|
+
const expanded = expandInterpolatedAnimationShorthand({
|
|
17394
|
+
property: d.property,
|
|
17395
|
+
valueRaw: d.valueRaw,
|
|
17396
|
+
slotExprById,
|
|
17397
|
+
keyframesNames: ctx.keyframesNames,
|
|
17398
|
+
j,
|
|
17399
|
+
inlineKeyframeNameMap: ctx.inlineKeyframeNameMap
|
|
17400
|
+
});
|
|
17401
|
+
if (expanded) {
|
|
17402
|
+
for (const [prop, value] of Object.entries(expanded)) setStyleValue(prop, value);
|
|
17403
|
+
continue;
|
|
17404
|
+
}
|
|
17405
|
+
}
|
|
17075
17406
|
const parts = d.value.parts ?? [];
|
|
17076
17407
|
const slotParts = parts.filter((p) => p.kind === "slot");
|
|
17077
17408
|
if (slotParts.length === 0) return null;
|
|
@@ -17741,7 +18072,7 @@ const createCssHelperHandlers = (ctx) => {
|
|
|
17741
18072
|
//#endregion
|
|
17742
18073
|
//#region src/internal/lower-rules/css-helper-conditional.ts
|
|
17743
18074
|
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;
|
|
18075
|
+
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
18076
|
const avoidNames = new Set(importMap.keys());
|
|
17746
18077
|
/**
|
|
17747
18078
|
* Resolve the TS type node for a prop used in a style function parameter.
|
|
@@ -17910,21 +18241,57 @@ function createCssHelperConditionalHandler(ctx) {
|
|
|
17910
18241
|
const { rules, slotExprById } = parseCssTemplateToRules(tpl);
|
|
17911
18242
|
const out = /* @__PURE__ */ new Map();
|
|
17912
18243
|
const mediaValues = /* @__PURE__ */ new Map();
|
|
17913
|
-
const
|
|
17914
|
-
|
|
18244
|
+
const computedMediaValues = /* @__PURE__ */ new Map();
|
|
18245
|
+
const setValueForProp = (prop, value, media, computedKey) => {
|
|
18246
|
+
if (computedKey) {
|
|
18247
|
+
const arr = computedMediaValues.get(prop) ?? [];
|
|
18248
|
+
arr.push({
|
|
18249
|
+
keyExpr: computedKey,
|
|
18250
|
+
value
|
|
18251
|
+
});
|
|
18252
|
+
computedMediaValues.set(prop, arr);
|
|
18253
|
+
} else if (media) {
|
|
17915
18254
|
if (!mediaValues.has(prop)) mediaValues.set(prop, /* @__PURE__ */ new Map());
|
|
17916
18255
|
mediaValues.get(prop).set(media, value);
|
|
17917
18256
|
} else out.set(prop, value);
|
|
17918
18257
|
};
|
|
17919
18258
|
for (const rule of rules) {
|
|
17920
|
-
const
|
|
17921
|
-
if (rule.atRuleStack.length > 0 && !
|
|
18259
|
+
const rawMedia = findSupportedAtRule(rule.atRuleStack);
|
|
18260
|
+
if (rule.atRuleStack.length > 0 && !rawMedia) return null;
|
|
18261
|
+
let media = rawMedia;
|
|
18262
|
+
let computedMediaKeyExpr;
|
|
18263
|
+
if (rawMedia) {
|
|
18264
|
+
const resolved = resolveMediaAtRulePlaceholders(rawMedia, (slotId) => slotExprById.get(slotId), {
|
|
18265
|
+
lookupImport: resolveImportInScope,
|
|
18266
|
+
resolveValue,
|
|
18267
|
+
resolveSelector,
|
|
18268
|
+
parseExpr,
|
|
18269
|
+
filePath,
|
|
18270
|
+
resolverImports
|
|
18271
|
+
});
|
|
18272
|
+
if (resolved === null) return null;
|
|
18273
|
+
if (resolved.kind === "static") media = resolved.value;
|
|
18274
|
+
else {
|
|
18275
|
+
computedMediaKeyExpr = resolved.keyExpr;
|
|
18276
|
+
media = void 0;
|
|
18277
|
+
}
|
|
18278
|
+
}
|
|
17922
18279
|
if ((rule.selector ?? "").trim() !== "&") return null;
|
|
18280
|
+
const applyExpandedAnimation = (expanded) => {
|
|
18281
|
+
for (const [prop, value] of Object.entries(expanded)) setValueForProp(prop, typeof value === "string" || typeof value === "number" ? staticValueToLiteral(j, value) : value, media, computedMediaKeyExpr);
|
|
18282
|
+
};
|
|
17923
18283
|
for (const d of rule.declarations) {
|
|
17924
18284
|
if (!d.property) return null;
|
|
17925
18285
|
if (d.property.includes("__SC_EXPR_")) return null;
|
|
17926
18286
|
if (d.important) return null;
|
|
17927
18287
|
if (d.value.kind === "static") {
|
|
18288
|
+
if (d.property === "animation" && ctx.keyframesNames && ctx.keyframesNames.size > 0) {
|
|
18289
|
+
const expanded = {};
|
|
18290
|
+
if (expandStaticAnimationShorthand(d.valueRaw, ctx.keyframesNames, j, expanded, ctx.inlineKeyframeNameMap)) {
|
|
18291
|
+
applyExpandedAnimation(expanded);
|
|
18292
|
+
continue;
|
|
18293
|
+
}
|
|
18294
|
+
}
|
|
17928
18295
|
for (const mapped of cssDeclarationToStylexDeclarations(d)) {
|
|
17929
18296
|
let value = cssValueToJs(mapped.value, d.important, mapped.prop);
|
|
17930
18297
|
if (mapped.prop === "content" && typeof value === "string") {
|
|
@@ -17932,12 +18299,26 @@ function createCssHelperConditionalHandler(ctx) {
|
|
|
17932
18299
|
if (m) value = `"${m[1]}"`;
|
|
17933
18300
|
else if (!value.startsWith("\"") && !value.endsWith("\"")) value = `"${value}"`;
|
|
17934
18301
|
}
|
|
17935
|
-
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") setValueForProp(mapped.prop, staticValueToLiteral(j, value), media);
|
|
18302
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") setValueForProp(mapped.prop, staticValueToLiteral(j, value), media, computedMediaKeyExpr);
|
|
17936
18303
|
else return null;
|
|
17937
18304
|
}
|
|
17938
18305
|
continue;
|
|
17939
18306
|
}
|
|
17940
18307
|
if (d.value.kind !== "interpolated") return null;
|
|
18308
|
+
if ((d.property === "animation" || d.property === "animation-name") && ctx.keyframesNames && ctx.keyframesNames.size > 0) {
|
|
18309
|
+
const expanded = expandInterpolatedAnimationShorthand({
|
|
18310
|
+
property: d.property,
|
|
18311
|
+
valueRaw: d.valueRaw,
|
|
18312
|
+
slotExprById,
|
|
18313
|
+
keyframesNames: ctx.keyframesNames,
|
|
18314
|
+
j,
|
|
18315
|
+
inlineKeyframeNameMap: ctx.inlineKeyframeNameMap
|
|
18316
|
+
});
|
|
18317
|
+
if (expanded) {
|
|
18318
|
+
applyExpandedAnimation(expanded);
|
|
18319
|
+
continue;
|
|
18320
|
+
}
|
|
18321
|
+
}
|
|
17941
18322
|
const slotParts = (d.value.parts ?? []).filter((p) => p.kind === "slot");
|
|
17942
18323
|
if (slotParts.length !== 1) return null;
|
|
17943
18324
|
const slotExpr = slotExprById.get(slotParts[0].slotId);
|
|
@@ -17945,13 +18326,21 @@ function createCssHelperConditionalHandler(ctx) {
|
|
|
17945
18326
|
const rawExpr = replaceParamWithProps(slotExpr);
|
|
17946
18327
|
const { prefix, suffix } = extractStaticPartsForDecl(d);
|
|
17947
18328
|
const valueExpr = prefix || suffix ? buildTemplateWithStaticParts(j, rawExpr, prefix, suffix) : rawExpr;
|
|
17948
|
-
for (const mapped of cssDeclarationToStylexDeclarations(d)) setValueForProp(mapped.prop, valueExpr, media);
|
|
18329
|
+
for (const mapped of cssDeclarationToStylexDeclarations(d)) setValueForProp(mapped.prop, valueExpr, media, computedMediaKeyExpr);
|
|
17949
18330
|
}
|
|
17950
18331
|
}
|
|
17951
|
-
|
|
18332
|
+
const allMediaProps = new Set([...mediaValues.keys(), ...computedMediaValues.keys()]);
|
|
18333
|
+
for (const prop of allMediaProps) {
|
|
17952
18334
|
const baseValue = out.get(prop);
|
|
17953
18335
|
const properties = [j.property("init", j.identifier("default"), baseValue ?? j.literal(null))];
|
|
17954
|
-
|
|
18336
|
+
const queries = mediaValues.get(prop);
|
|
18337
|
+
if (queries) for (const [query, value] of queries) properties.push(j.property("init", j.literal(query), value));
|
|
18338
|
+
const computed = computedMediaValues.get(prop);
|
|
18339
|
+
if (computed) for (const { keyExpr, value } of computed) {
|
|
18340
|
+
const p = j.property("init", keyExpr, value);
|
|
18341
|
+
p.computed = true;
|
|
18342
|
+
properties.push(p);
|
|
18343
|
+
}
|
|
17955
18344
|
out.set(prop, j.objectExpression(properties));
|
|
17956
18345
|
}
|
|
17957
18346
|
return out;
|
|
@@ -19284,7 +19673,7 @@ const createValuePatternHandlers = (ctx) => {
|
|
|
19284
19673
|
* Core concepts: per-component style buckets, helper factories, and resolver wiring.
|
|
19285
19674
|
*/
|
|
19286
19675
|
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;
|
|
19676
|
+
const { api, j, root, filePath, warnings, resolverImports, parseExpr, resolveValue, resolveCall, resolveCallOptional, resolveSelector, importMap, cssHelperFunctions, stringMappingFns, hasLocalThemeBinding, isCssHelperTaggedTemplate, resolveCssHelperTemplate, resolveImportInScope, usedCssHelperFunctions, markBail } = state;
|
|
19288
19677
|
const styleObj = {};
|
|
19289
19678
|
const perPropPseudo = {};
|
|
19290
19679
|
const perPropMedia = {};
|
|
@@ -19371,6 +19760,7 @@ function createDeclProcessingState(state, decl) {
|
|
|
19371
19760
|
parseExpr,
|
|
19372
19761
|
resolveValue,
|
|
19373
19762
|
resolveCall,
|
|
19763
|
+
resolveSelector,
|
|
19374
19764
|
resolveImportInScope,
|
|
19375
19765
|
resolverImports,
|
|
19376
19766
|
isCssHelperTaggedTemplate,
|
|
@@ -19432,7 +19822,7 @@ function createDeclProcessingState(state, decl) {
|
|
|
19432
19822
|
const out = {};
|
|
19433
19823
|
const mediaStyles = /* @__PURE__ */ new Map();
|
|
19434
19824
|
for (const rule of rules) {
|
|
19435
|
-
const media = rule.atRuleStack
|
|
19825
|
+
const media = findSupportedAtRule(rule.atRuleStack);
|
|
19436
19826
|
if (rule.atRuleStack.length > 0 && !media) {
|
|
19437
19827
|
warnings.push({
|
|
19438
19828
|
severity: "warning",
|
|
@@ -19878,18 +20268,26 @@ function tryHandleInterpolatedBorder(ctx, args) {
|
|
|
19878
20268
|
if (quasis.length === 2 && exprs.length === 1) {
|
|
19879
20269
|
const prefix = quasis[0]?.value?.cooked ?? quasis[0]?.value?.raw ?? "";
|
|
19880
20270
|
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
|
-
}
|
|
20271
|
+
if (suffix.trim() === "") {
|
|
20272
|
+
const parsed = parseInterpolatedBorderStaticParts({
|
|
20273
|
+
prop,
|
|
20274
|
+
prefix,
|
|
20275
|
+
suffix
|
|
20276
|
+
});
|
|
20277
|
+
if (parsed?.width && parsed?.style) return {
|
|
20278
|
+
width: parsed.width,
|
|
20279
|
+
style: parsed.style,
|
|
20280
|
+
colorExpr: exprs[0]
|
|
20281
|
+
};
|
|
20282
|
+
}
|
|
20283
|
+
if (prefix.trim() === "" && suffix.trim() !== "") {
|
|
20284
|
+
const parsed = parseBorderShorthandParts(suffix.trim());
|
|
20285
|
+
if (parsed?.style && parsed?.color) return {
|
|
20286
|
+
width: exprs[0],
|
|
20287
|
+
style: parsed.style,
|
|
20288
|
+
colorExpr: parsed.color
|
|
20289
|
+
};
|
|
20290
|
+
}
|
|
19893
20291
|
}
|
|
19894
20292
|
if (quasis.length === 3 && exprs.length === 2) {
|
|
19895
20293
|
const prefix = quasis[0]?.value?.cooked ?? quasis[0]?.value?.raw ?? "";
|
|
@@ -19993,7 +20391,7 @@ function tryHandleInterpolatedBorder(ctx, args) {
|
|
|
19993
20391
|
}
|
|
19994
20392
|
}
|
|
19995
20393
|
if (hasStaticWidthOrStyle) applyResolvedPropValue(targetProp, resolved.exprAst);
|
|
19996
|
-
else
|
|
20394
|
+
else bailUnsupportedWithContext("Resolved border helper value could not be expanded to longhand properties", { property: prop }, getNodeLocStart(expr));
|
|
19997
20395
|
return true;
|
|
19998
20396
|
}
|
|
19999
20397
|
}
|
|
@@ -21058,6 +21456,20 @@ function handleInterpolatedDeclaration(args) {
|
|
|
21058
21456
|
};
|
|
21059
21457
|
if (tryHandleThemeValueInPseudo()) continue;
|
|
21060
21458
|
const resolveImportedValueExpr = (expr) => {
|
|
21459
|
+
if (expr?.type === "BinaryExpression") {
|
|
21460
|
+
const leftResult = resolveImportedValueExpr(expr.left);
|
|
21461
|
+
const rightResult = resolveImportedValueExpr(expr.right);
|
|
21462
|
+
if (!leftResult && !rightResult) return null;
|
|
21463
|
+
if (leftResult && "bail" in leftResult) return leftResult;
|
|
21464
|
+
if (rightResult && "bail" in rightResult) return rightResult;
|
|
21465
|
+
const resolvedLeft = leftResult ? leftResult.resolved : expr.left;
|
|
21466
|
+
const resolvedRight = rightResult ? rightResult.resolved : expr.right;
|
|
21467
|
+
const imports = [...leftResult?.imports ?? [], ...rightResult?.imports ?? []];
|
|
21468
|
+
return {
|
|
21469
|
+
resolved: j.binaryExpression(expr.operator, resolvedLeft, resolvedRight),
|
|
21470
|
+
imports
|
|
21471
|
+
};
|
|
21472
|
+
}
|
|
21061
21473
|
const info = getRootIdentifierInfo(expr);
|
|
21062
21474
|
if (!info) return null;
|
|
21063
21475
|
const imp = resolveImportInScope(info.rootName, info.rootNode);
|
|
@@ -22830,7 +23242,7 @@ function processDeclRules(ctx) {
|
|
|
22830
23242
|
}
|
|
22831
23243
|
}
|
|
22832
23244
|
}
|
|
22833
|
-
let media = rule.atRuleStack
|
|
23245
|
+
let media = findSupportedAtRule(rule.atRuleStack);
|
|
22834
23246
|
const intrinsicTagName = decl.base.kind === "intrinsic" ? decl.base.tagName : null;
|
|
22835
23247
|
let selector = normalizeSelectorForAttributePseudos(rule.selector, intrinsicTagName);
|
|
22836
23248
|
selector = normalizeInterpolatedSelector(selector);
|
|
@@ -22843,10 +23255,37 @@ function processDeclRules(ctx) {
|
|
|
22843
23255
|
first.leadingComment = first.leadingComment ? `${note}\n${first.leadingComment}` : note;
|
|
22844
23256
|
}
|
|
22845
23257
|
}
|
|
22846
|
-
if (!media && (selector.trim()
|
|
23258
|
+
if (!media && isSupportedAtRule(selector.trim())) {
|
|
22847
23259
|
media = selector.trim();
|
|
22848
23260
|
selector = "&";
|
|
22849
23261
|
}
|
|
23262
|
+
if (media) {
|
|
23263
|
+
const resolved = resolveMediaAtRulePlaceholders(media, (slotId) => decl.templateExpressions[slotId], {
|
|
23264
|
+
lookupImport: resolveImportInScope,
|
|
23265
|
+
resolveValue: state.resolveValue,
|
|
23266
|
+
resolveSelector,
|
|
23267
|
+
parseExpr,
|
|
23268
|
+
filePath: state.filePath,
|
|
23269
|
+
resolverImports
|
|
23270
|
+
});
|
|
23271
|
+
if (resolved === null) {
|
|
23272
|
+
state.markBail();
|
|
23273
|
+
warnings.push({
|
|
23274
|
+
severity: "warning",
|
|
23275
|
+
type: "Unsupported: media query interpolation must be a simple imported reference (expressions like `value + 1` are not supported)",
|
|
23276
|
+
loc: computeSelectorWarningLoc(decl.loc, decl.rawCss, rule.selector)
|
|
23277
|
+
});
|
|
23278
|
+
break;
|
|
23279
|
+
}
|
|
23280
|
+
if (resolved.kind === "static") media = resolved.value;
|
|
23281
|
+
else {
|
|
23282
|
+
resolvedSelectorMedia = {
|
|
23283
|
+
keyExpr: resolved.keyExpr,
|
|
23284
|
+
exprSource: ""
|
|
23285
|
+
};
|
|
23286
|
+
media = void 0;
|
|
23287
|
+
}
|
|
23288
|
+
}
|
|
22850
23289
|
const parsedSelector = parseSelector(selector);
|
|
22851
23290
|
if (parsedSelector.kind === "unsupported" && selector !== "&" && !rule.selector.includes("__SC_EXPR_")) {
|
|
22852
23291
|
const elementAction = tryHandleElementSelector(selector, rule, decl);
|
|
@@ -23444,7 +23883,27 @@ function handleSiblingSelector(selector, rule, ctx) {
|
|
|
23444
23883
|
return "break";
|
|
23445
23884
|
}
|
|
23446
23885
|
const makeSiblingKeyExpr = () => j.callExpression(j.memberExpression(j.memberExpression(j.identifier("stylex"), j.identifier("when")), j.identifier("siblingBefore")), [j.literal(":is(*)")]);
|
|
23447
|
-
|
|
23886
|
+
let media = findSupportedAtRule(rule.atRuleStack);
|
|
23887
|
+
if (media) {
|
|
23888
|
+
const resolved = resolveMediaAtRulePlaceholders(media, (slotId) => decl.templateExpressions[slotId], {
|
|
23889
|
+
lookupImport: state.resolveImportInScope,
|
|
23890
|
+
resolveValue: state.resolveValue,
|
|
23891
|
+
resolveSelector: state.resolveSelector,
|
|
23892
|
+
parseExpr: state.parseExpr,
|
|
23893
|
+
filePath: state.filePath,
|
|
23894
|
+
resolverImports: state.resolverImports
|
|
23895
|
+
});
|
|
23896
|
+
if (resolved === null) {
|
|
23897
|
+
warnings.push({
|
|
23898
|
+
severity: "warning",
|
|
23899
|
+
type: "Unsupported: media query interpolation must be a simple imported reference (expressions like `value + 1` are not supported)",
|
|
23900
|
+
loc: computeSelectorWarningLoc(decl.loc, decl.rawCss, rule.selector)
|
|
23901
|
+
});
|
|
23902
|
+
return "break";
|
|
23903
|
+
}
|
|
23904
|
+
if (resolved.kind === "static") media = resolved.value;
|
|
23905
|
+
else media = void 0;
|
|
23906
|
+
}
|
|
23448
23907
|
for (const [prop, value] of Object.entries(bucket)) {
|
|
23449
23908
|
const siblingValue = media ? {
|
|
23450
23909
|
default: null,
|
|
@@ -23646,7 +24105,7 @@ function finalizeDeclProcessing(ctx) {
|
|
|
23646
24105
|
if (!v || typeof v !== "object" || Array.isArray(v) || isAstNode(v)) return false;
|
|
23647
24106
|
const keys = Object.keys(v);
|
|
23648
24107
|
if (keys.length === 0) return false;
|
|
23649
|
-
return keys.includes("default") || keys.some(
|
|
24108
|
+
return keys.includes("default") || keys.some(isStyleConditionKey);
|
|
23650
24109
|
};
|
|
23651
24110
|
if (!(() => {
|
|
23652
24111
|
const disabledBucket = variantBuckets.get("disabled");
|
|
@@ -24871,6 +25330,8 @@ function rewriteJsxStep(ctx) {
|
|
|
24871
25330
|
const inlineVariantDimensions = decl.inlinedBaseComponent?.hasInlineJsxVariants ? decl.variantDimensions ?? [] : [];
|
|
24872
25331
|
const inlineVariantByProp = new Map(inlineVariantDimensions.map((dimension) => [dimension.propName, dimension]));
|
|
24873
25332
|
const inlineVariantProps = new Set(inlineVariantDimensions.map((dimension) => dimension.propName));
|
|
25333
|
+
const combinedStylePropNames = new Set((decl.callSiteCombinedStyles ?? []).flatMap((c) => c.propNames));
|
|
25334
|
+
const matchedCombinedStyleKey = matchCallSiteCombinedStyle(decl.callSiteCombinedStyles, opening.attributes ?? []);
|
|
24874
25335
|
const attrs = opening.attributes ?? [];
|
|
24875
25336
|
for (const attr of attrs) {
|
|
24876
25337
|
if (attr.type !== "JSXAttribute") continue;
|
|
@@ -24898,6 +25359,7 @@ function rewriteJsxStep(ctx) {
|
|
|
24898
25359
|
const n = attr.name.name;
|
|
24899
25360
|
if (decl.shouldForwardProp.dropProps.includes(n)) {
|
|
24900
25361
|
if (inlineVariantProps.has(n)) return true;
|
|
25362
|
+
if (decl.variantStyleKeys && n in decl.variantStyleKeys) return true;
|
|
24901
25363
|
return false;
|
|
24902
25364
|
}
|
|
24903
25365
|
if (decl.shouldForwardProp.dropPrefix && n.startsWith(decl.shouldForwardProp.dropPrefix)) return false;
|
|
@@ -24981,10 +25443,11 @@ function rewriteJsxStep(ctx) {
|
|
|
24981
25443
|
else extraMixinArgs.push(expr);
|
|
24982
25444
|
}
|
|
24983
25445
|
}
|
|
25446
|
+
const baseStyleKey = matchedCombinedStyleKey ?? decl.styleKey;
|
|
24984
25447
|
const styleArgs = [
|
|
24985
25448
|
...decl.extendsStyleKey ? [j.memberExpression(j.identifier(ctx.stylesIdentifier ?? "styles"), j.identifier(decl.extendsStyleKey))] : [],
|
|
24986
25449
|
...extraMixinArgs,
|
|
24987
|
-
j.memberExpression(j.identifier(ctx.stylesIdentifier ?? "styles"), j.identifier(
|
|
25450
|
+
j.memberExpression(j.identifier(ctx.stylesIdentifier ?? "styles"), j.identifier(baseStyleKey)),
|
|
24988
25451
|
...extraAfterBaseArgs
|
|
24989
25452
|
];
|
|
24990
25453
|
const variantKeys = decl.variantStyleKeys ?? {};
|
|
@@ -25006,6 +25469,7 @@ function rewriteJsxStep(ctx) {
|
|
|
25006
25469
|
if (valueExpr) for (const p of pairs) styleArgs.push(j.callExpression(j.memberExpression(j.identifier(ctx.stylesIdentifier ?? "styles"), j.identifier(p.fnKey)), [valueExpr]));
|
|
25007
25470
|
return;
|
|
25008
25471
|
}
|
|
25472
|
+
if (combinedStylePropNames.has(n) && matchedCombinedStyleKey) return;
|
|
25009
25473
|
const inlineVariantDimension = inlineVariantByProp.get(n);
|
|
25010
25474
|
if (inlineVariantDimension) {
|
|
25011
25475
|
const variantLookup = buildInlineVariantLookupFromAttr(j, inlineVariantDimension.variantObjectName, attr);
|
|
@@ -25028,9 +25492,19 @@ function rewriteJsxStep(ctx) {
|
|
|
25028
25492
|
return;
|
|
25029
25493
|
}
|
|
25030
25494
|
if (attr.value.type === "JSXExpressionContainer") {
|
|
25495
|
+
const staticLiteralValue = readStaticJsxLiteral(attr);
|
|
25496
|
+
if (staticLiteralValue !== void 0 && staticLiteralValue) {
|
|
25497
|
+
styleArgs.push(j.memberExpression(j.identifier(ctx.stylesIdentifier ?? "styles"), j.identifier(variantStyleKey)));
|
|
25498
|
+
return;
|
|
25499
|
+
}
|
|
25031
25500
|
styleArgs.push(j.logicalExpression("&&", attr.value.expression, j.memberExpression(j.identifier(ctx.stylesIdentifier ?? "styles"), j.identifier(variantStyleKey))));
|
|
25032
25501
|
return;
|
|
25033
25502
|
}
|
|
25503
|
+
if (attr.value.type === "StringLiteral" || attr.value.type === "NumericLiteral" || attr.value.type === "Literal") {
|
|
25504
|
+
const literalVal = readStaticJsxLiteral(attr);
|
|
25505
|
+
if (literalVal !== void 0 && literalVal) styleArgs.push(j.memberExpression(j.identifier(ctx.stylesIdentifier ?? "styles"), j.identifier(variantStyleKey)));
|
|
25506
|
+
return;
|
|
25507
|
+
}
|
|
25034
25508
|
};
|
|
25035
25509
|
for (const attr of leading) processAttr(attr, keptLeadingAfterVariants);
|
|
25036
25510
|
for (const attr of rest) processAttr(attr, keptRestAfterVariants);
|
|
@@ -25087,6 +25561,22 @@ function extractJsxAttrValueExpr(j, attr) {
|
|
|
25087
25561
|
if (a.value.type === "StringLiteral" || a.value.type === "Literal") return j.literal(a.value.value);
|
|
25088
25562
|
if (a.value.type === "JSXExpressionContainer") return a.value.expression;
|
|
25089
25563
|
}
|
|
25564
|
+
/**
|
|
25565
|
+
* Finds the combined style key matching the consumed props at a JSX call site.
|
|
25566
|
+
* Returns the style key if a matching combination exists, or undefined otherwise.
|
|
25567
|
+
*/
|
|
25568
|
+
function matchCallSiteCombinedStyle(combinedStyles, attrs) {
|
|
25569
|
+
if (!combinedStyles?.length) return;
|
|
25570
|
+
const attrNames = /* @__PURE__ */ new Set();
|
|
25571
|
+
for (const a of attrs) {
|
|
25572
|
+
const attr = a;
|
|
25573
|
+
if (attr.type === "JSXAttribute" && attr.name?.type === "JSXIdentifier" && typeof attr.name.name === "string") attrNames.add(attr.name.name);
|
|
25574
|
+
}
|
|
25575
|
+
const presentPropNames = [...new Set(combinedStyles.flatMap((c) => c.propNames))].filter((p) => attrNames.has(p)).sort();
|
|
25576
|
+
if (presentPropNames.length === 0) return;
|
|
25577
|
+
const key = presentPropNames.join(",");
|
|
25578
|
+
return combinedStyles.find((c) => [...c.propNames].sort().join(",") === key)?.styleKey;
|
|
25579
|
+
}
|
|
25090
25580
|
|
|
25091
25581
|
//#endregion
|
|
25092
25582
|
//#region src/internal/transform-steps/upgrade-polymorphic-as-prop-types.ts
|