styled-components-to-stylex-codemod 0.0.53 → 0.0.54

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.
@@ -1,10 +1,10 @@
1
1
  import { t as createModuleResolver } from "./resolve-imports-DgSAddIF.mjs";
2
2
  import { a as isDirectionalResult, n as mergeMarkerDeclarations, o as assertValidAdapter, r as DEFAULT_THEME_HOOK, t as transformedComponentAcceptsSx } from "./sx-surface-CEPFSTO1.mjs";
3
- import { a as findImportSource, c as resolveBarrelReExportBinding, d as UNSUPPORTED_SHOULD_FORWARD_PROP_WARNING, l as CASCADE_CONFLICT_WARNING, n as createPrepassParser, o as getReExportedSourceName, r as fileExports, t as walkAst, u as Logger } from "./ast-walk-BOXS-DT7.mjs";
3
+ import { a as findImportSource, c as resolveBarrelReExportBinding, d as PARTIAL_MIGRATION_INCOMPLETE_WARNING, f as UNSUPPORTED_SHOULD_FORWARD_PROP_WARNING, l as CASCADE_CONFLICT_WARNING, n as createPrepassParser, o as getReExportedSourceName, r as fileExports, t as walkAst, u as Logger } from "./ast-walk-CCXrDCKY.mjs";
4
4
  import { n as resolveExistingFilePath, r as toRealPath, t as isRelativeSpecifier } from "./path-utils-BC4U8X_q.mjs";
5
5
  import { a as hasTopLevelMatch, c as isPrettierIgnoreComment, d as isValidIdentifierName, f as kebabToCamelCase, g as sanitizeIdentifier, h as normalizeWhitespace, i as getCommentBody, l as isSingleBackgroundComponent, m as lowerFirst, n as capitalize$1, o as isBackgroundImageValue, p as looksLikeLength, r as escapeRegex, s as isJSDocBlockComment, t as camelToKebabCase, u as isStyleSectionMarkerComment } from "./string-utils-Bo3cWgss.mjs";
6
6
  import { a as terminateStandaloneInterpolationStatements, i as parseStyledTemplateLiteral, n as isTemplatePlaceholderInSelectorContext, r as PLACEHOLDER_RE } from "./selector-context-heuristic-LVizWWOR.mjs";
7
- import { _ as walkForImportsAndTemplates, a as mergeComponentPropUsage, i as getExhaustiveObservedStaticValues, n as createComponentPropUsageInfo, o as readStaticJsxLiteral, r as formatObservedVariantCondition, s as collectStylexExportNames, t as KNOWN_NON_ELEMENT_PROPS, u as buildImportMapFromNodes } from "./prop-usage-SADzZJdX.mjs";
7
+ import { _ as walkForImportsAndTemplates, a as mergeComponentPropUsage, i as getExhaustiveObservedStaticValues, n as createComponentPropUsageInfo, o as readStaticJsxLiteral, r as formatObservedVariantCondition, s as collectStylexExportNames, t as KNOWN_NON_ELEMENT_PROPS, u as buildImportMapFromNodes } from "./prop-usage-DyWABApg.mjs";
8
8
  import { createRequire } from "node:module";
9
9
  import jscodeshift from "jscodeshift";
10
10
  import { basename, dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
@@ -994,7 +994,7 @@ function createResolveAdapterSafe(args) {
994
994
  */
995
995
  const resolveValueCore = (ctx) => {
996
996
  if (bailRef.value) return;
997
- if (ctx.kind === "importedValue" && isStylexFileSource(ctx.source)) return stylexImportPassthrough(ctx.importedName, ctx.source, ctx.path);
997
+ if (ctx.kind === "importedValue" && isStylexFileSource$1(ctx.source)) return stylexImportPassthrough(ctx.importedName, ctx.source, ctx.path);
998
998
  const res = adapter.resolveValue(ctx);
999
999
  if (res === void 0 && ctx.kind !== "cssVariable") {
1000
1000
  bailRef.value = true;
@@ -1012,7 +1012,7 @@ function createResolveAdapterSafe(args) {
1012
1012
  };
1013
1013
  const resolveCallSafe = (ctx) => {
1014
1014
  if (bailRef.value) return;
1015
- if (isStylexFileSource(ctx.calleeSource)) return stylexImportPassthrough(ctx.calleeImportedName, ctx.calleeSource, ctx.calleeMemberPath?.join("."));
1015
+ if (isStylexFileSource$1(ctx.calleeSource)) return stylexImportPassthrough(ctx.calleeImportedName, ctx.calleeSource, ctx.calleeMemberPath?.join("."));
1016
1016
  const res = adapter.resolveCall(ctx);
1017
1017
  if (res === void 0) {
1018
1018
  bailRef.value = true;
@@ -1021,7 +1021,7 @@ function createResolveAdapterSafe(args) {
1021
1021
  return res;
1022
1022
  };
1023
1023
  const resolveSelectorSafe = (ctx) => {
1024
- if (isStylexFileSource(ctx.source)) return {
1024
+ if (isStylexFileSource$1(ctx.source)) return {
1025
1025
  kind: "media",
1026
1026
  ...stylexImportPassthrough(ctx.importedName, ctx.source, ctx.path)
1027
1027
  };
@@ -1035,10 +1035,10 @@ function createResolveAdapterSafe(args) {
1035
1035
  bailRef
1036
1036
  };
1037
1037
  }
1038
- const STYLEX_FILE_RE = /\.stylex(\.\w+)?$/;
1038
+ const STYLEX_FILE_RE$1 = /\.stylex(\.\w+)?$/;
1039
1039
  /** Imports from `.stylex` files are already StyleX-compatible and need no adapter resolution. */
1040
- function isStylexFileSource(source) {
1041
- return STYLEX_FILE_RE.test(source.value);
1040
+ function isStylexFileSource$1(source) {
1041
+ return STYLEX_FILE_RE$1.test(source.value);
1042
1042
  }
1043
1043
  /** Build a passthrough result that preserves the original import reference from a `.stylex` file. */
1044
1044
  function stylexImportPassthrough(importedName, source, path) {
@@ -1567,10 +1567,12 @@ function collectPatternBindingNames$2(node, names) {
1567
1567
  *
1568
1568
  * Returns null for non-literal or dynamic nodes.
1569
1569
  */
1570
- function literalToStaticValue(node) {
1570
+ function literalToStaticValue(node, options = {}) {
1571
1571
  if (!node || typeof node !== "object") return null;
1572
+ const allowCssTaggedTemplates = options.allowCssTaggedTemplates ?? true;
1573
+ const allowStaticArrowFunctions = options.allowStaticArrowFunctions ?? true;
1572
1574
  const type = node.type;
1573
- if (type === "TSAsExpression" || type === "TSSatisfiesExpression") return literalToStaticValue(node.expression);
1575
+ if (type === "TSAsExpression" || type === "TSSatisfiesExpression") return literalToStaticValue(node.expression, options);
1574
1576
  if (type === "StringLiteral") return node.value;
1575
1577
  if (type === "BooleanLiteral") return node.value;
1576
1578
  if (type === "Literal") {
@@ -1581,25 +1583,53 @@ function literalToStaticValue(node) {
1581
1583
  if (type === "UnaryExpression") {
1582
1584
  const n = node;
1583
1585
  if (n.prefix && (n.operator === "-" || n.operator === "+")) {
1584
- const argVal = literalToStaticValue(n.argument);
1586
+ const argVal = literalToStaticValue(n.argument, options);
1585
1587
  if (typeof argVal === "number") return n.operator === "-" ? -argVal : argVal;
1586
1588
  }
1587
1589
  }
1588
1590
  if (type === "TemplateLiteral") {
1589
1591
  const n = node;
1590
- if (!n.expressions || n.expressions.length === 0) return (n.quasis ?? []).map((q) => q.value?.raw ?? "").join("");
1592
+ if (!n.expressions || n.expressions.length === 0) {
1593
+ const quasis = n.quasis ?? [];
1594
+ const parts = [];
1595
+ for (const q of quasis) {
1596
+ const cooked = q.value?.cooked;
1597
+ if (cooked == null) return null;
1598
+ parts.push(cooked);
1599
+ }
1600
+ return parts.join("");
1601
+ }
1591
1602
  }
1592
- if (type === "TaggedTemplateExpression") {
1603
+ if (type === "TaggedTemplateExpression" && allowCssTaggedTemplates) {
1593
1604
  const n = node;
1594
- if (n.tag?.type === "Identifier" && n.tag.name === "css") return literalToStaticValue(n.quasi);
1605
+ if (n.tag?.type === "Identifier" && n.tag.name === "css") return literalToStaticValue(n.quasi, options);
1595
1606
  }
1596
- if (type === "ArrowFunctionExpression") {
1607
+ if (type === "ArrowFunctionExpression" && allowStaticArrowFunctions) {
1597
1608
  const n = node;
1598
- if (!n.params || n.params.length === 0) return literalToStaticValue(n.body);
1609
+ if (!n.params || n.params.length === 0) return literalToStaticValue(n.body, options);
1599
1610
  }
1600
1611
  return null;
1601
1612
  }
1602
1613
  /**
1614
+ * Extracts a static literal value from an AST node, distinguishing null literals
1615
+ * from extraction failure. Returns `undefined` when the node is not a recognized
1616
+ * static literal, and the actual value (including `null`) otherwise.
1617
+ *
1618
+ * Function expressions are not coerced by default: a function-valued expression
1619
+ * is runtime data, even if its body is a static literal.
1620
+ */
1621
+ function extractStaticLiteralValue(node, options = {}) {
1622
+ if (!node || typeof node !== "object") return;
1623
+ const typed = node;
1624
+ if (typed.type === "TSAsExpression" || typed.type === "TSSatisfiesExpression") return extractStaticLiteralValue(typed.expression, options);
1625
+ if (typed.type === "NullLiteral" || typed.type === "Literal" && typed.value === null) return null;
1626
+ const v = literalToStaticValue(node, {
1627
+ ...options,
1628
+ allowStaticArrowFunctions: options.allowStaticArrowFunctions ?? false
1629
+ });
1630
+ return v !== null ? v : void 0;
1631
+ }
1632
+ /**
1603
1633
  * Converts an AST literal node to a string value.
1604
1634
  * Returns null if the node is not a string literal.
1605
1635
  */
@@ -4290,6 +4320,7 @@ function buildResolvedHandlerResult(result, cssProperty, payload) {
4290
4320
  type: "resolvedValue",
4291
4321
  expr: result.expr,
4292
4322
  imports: result.imports,
4323
+ cssValueText: result.expr,
4293
4324
  ...payload
4294
4325
  } : {
4295
4326
  type: "resolvedStyles",
@@ -12357,8 +12388,9 @@ function collectStyledDeclsImpl(args) {
12357
12388
  const key = prop.key.type === "Identifier" ? prop.key.name : prop.key.type === "StringLiteral" ? prop.key.value : null;
12358
12389
  if (!key) continue;
12359
12390
  const v = prop.value;
12360
- if (v.type === "StringLiteral" || v.type === "NumericLiteral" || v.type === "BooleanLiteral") {
12361
- out.staticAttrs[key] = v.value;
12391
+ const literalValue = literalStaticValueFromNode(v);
12392
+ if (literalValue !== void 0) {
12393
+ out.staticAttrs[key] = literalValue;
12362
12394
  continue;
12363
12395
  }
12364
12396
  if (key === "as" && v.type === "Identifier" && v.name !== "undefined") {
@@ -13321,12 +13353,7 @@ function getAttrsParamInfo(params) {
13321
13353
  };
13322
13354
  }
13323
13355
  function literalStaticValueFromNode(node) {
13324
- if (!node || typeof node !== "object") return;
13325
- const typed = node;
13326
- if (typed.type === "StringLiteral" || typed.type === "NumericLiteral") return typeof typed.value === "string" || typeof typed.value === "number" ? typed.value : void 0;
13327
- if (typed.type === "BooleanLiteral") return typeof typed.value === "boolean" ? typed.value : void 0;
13328
- if (typed.type === "Literal" && (typeof typed.value === "string" || typeof typed.value === "number" || typeof typed.value === "boolean")) return typed.value;
13329
- if (typed.type === "TSAsExpression" || typed.type === "TSSatisfiesExpression") return literalStaticValueFromNode(typed.expression);
13356
+ return extractStaticLiteralValue(node, { allowCssTaggedTemplates: false });
13330
13357
  }
13331
13358
  function isStaticAttrExpression$1(node, attrsParamInfo) {
13332
13359
  if (!node || typeof node !== "object") return false;
@@ -18105,6 +18132,44 @@ function insertImportDeclarationNearStylex(root, decl) {
18105
18132
  insertAfterLastImport(body, decl);
18106
18133
  }
18107
18134
  //#endregion
18135
+ //#region src/internal/utilities/inline-keyframes-liveness.ts
18136
+ function pruneUnusedInlineKeyframes(args) {
18137
+ const { state, emittedStyleValues, styledDecls } = args;
18138
+ const inlineKeyframes = state.inlineKeyframes;
18139
+ if (!inlineKeyframes || inlineKeyframes.size === 0) return;
18140
+ const referenced = collectReferencedInlineKeyframes(inlineKeyframes, emittedStyleValues);
18141
+ collectReferencedTransformedVariantKeyframes(inlineKeyframes, styledDecls, referenced);
18142
+ deleteUnreferencedInlineKeyframes(state, referenced);
18143
+ }
18144
+ function collectReferencedInlineKeyframes(inlineKeyframes, values) {
18145
+ const referenced = /* @__PURE__ */ new Set();
18146
+ for (const value of values) collectReferencedInlineKeyframeNames(inlineKeyframes, value, referenced);
18147
+ return referenced;
18148
+ }
18149
+ function collectReferencedTransformedVariantKeyframes(inlineKeyframes, styledDecls, referenced) {
18150
+ for (const decl of styledDecls) {
18151
+ if (decl.skipTransform) continue;
18152
+ for (const dimension of decl.variantDimensions ?? []) collectReferencedInlineKeyframeNames(inlineKeyframes, dimension.variants, referenced);
18153
+ for (const variant of decl.staticBooleanVariants ?? []) collectReferencedInlineKeyframeNames(inlineKeyframes, variant.styles, referenced);
18154
+ for (const combined of decl.callSiteCombinedStyles ?? []) collectReferencedInlineKeyframeNames(inlineKeyframes, combined.styles, referenced);
18155
+ }
18156
+ }
18157
+ function collectReferencedInlineKeyframeNames(inlineKeyframes, value, referenced) {
18158
+ const identifiers = /* @__PURE__ */ new Set();
18159
+ collectIdentifiers(value, identifiers);
18160
+ for (const name of identifiers) if (inlineKeyframes.has(name)) referenced.add(name);
18161
+ }
18162
+ function deleteUnreferencedInlineKeyframes(state, referenced) {
18163
+ const inlineKeyframes = state.inlineKeyframes;
18164
+ if (!inlineKeyframes) return;
18165
+ for (const name of inlineKeyframes.keys()) if (!referenced.has(name)) inlineKeyframes.delete(name);
18166
+ if (!state.inlineKeyframeNameMap) return;
18167
+ for (const [cssName, jsName] of state.inlineKeyframeNameMap.entries()) if (!inlineKeyframes.has(jsName)) {
18168
+ state.inlineKeyframeNameMap.delete(cssName);
18169
+ state.keyframesNames.delete(cssName);
18170
+ }
18171
+ }
18172
+ //#endregion
18108
18173
  //#region src/internal/emit-styles.ts
18109
18174
  /**
18110
18175
  * CSS shorthands that must NEVER appear as property names in stylex.create() output.
@@ -18430,6 +18495,11 @@ function emitStylesAndImports(ctx) {
18430
18495
  stylesDecl.leadingComments = deduped;
18431
18496
  stylesDecl.comments = deduped;
18432
18497
  }
18498
+ pruneUnusedInlineKeyframes({
18499
+ state: ctx,
18500
+ emittedStyleValues: nonEmptyStyleEntries.map(([, value]) => value),
18501
+ styledDecls
18502
+ });
18433
18503
  const inlineKeyframeDecls = [];
18434
18504
  if (ctx.inlineKeyframes && ctx.inlineKeyframes.size > 0) for (const [name, frames] of ctx.inlineKeyframes) {
18435
18505
  const kfDecl = j.variableDeclaration("const", [j.variableDeclarator(j.identifier(name), j.callExpression(j.memberExpression(j.identifier("stylex"), j.identifier("keyframes")), [objectToAst(j, frames)]))]);
@@ -20256,7 +20326,10 @@ function buildStaticAttrsFromRecord(j, staticAttrs, options) {
20256
20326
  }
20257
20327
  function buildStaticAttrFromValue(j, key, value, options) {
20258
20328
  const booleanTrueAsShorthand = options?.booleanTrueAsShorthand ?? true;
20259
- if (typeof value === "string") return j.jsxAttribute(j.jsxIdentifier(key), j.literal(value));
20329
+ if (typeof value === "string") {
20330
+ if (stringNeedsExpressionContainer(value)) return j.jsxAttribute(j.jsxIdentifier(key), j.jsxExpressionContainer(j.literal(value)));
20331
+ return j.jsxAttribute(j.jsxIdentifier(key), j.literal(value));
20332
+ }
20260
20333
  if (typeof value === "boolean") return j.jsxAttribute(j.jsxIdentifier(key), value && booleanTrueAsShorthand ? null : j.jsxExpressionContainer(j.booleanLiteral(value)));
20261
20334
  if (typeof value === "number") return j.jsxAttribute(j.jsxIdentifier(key), j.jsxExpressionContainer(j.literal(value)));
20262
20335
  if (value === void 0) return j.jsxAttribute(j.jsxIdentifier(key), j.jsxExpressionContainer(j.identifier("undefined")));
@@ -20268,6 +20341,15 @@ function isStaticAttrExpression(value) {
20268
20341
  return !!value && typeof value === "object" && typeof value.type === "string";
20269
20342
  }
20270
20343
  /**
20344
+ * Check if a string contains characters that require escaping in a JS string literal.
20345
+ * Such strings must be emitted as JSX expression containers (`attr={"value"}`) rather
20346
+ * than direct JSX string attributes (`attr="value"`), because JSX string attributes
20347
+ * don't interpret JS escape sequences - they're literal strings.
20348
+ */
20349
+ function stringNeedsExpressionContainer(value) {
20350
+ return /[\u0000-\u001f\\]/.test(value);
20351
+ }
20352
+ /**
20271
20353
  * Build all attrs from attrsInfo in the correct order:
20272
20354
  * defaultAttrs, conditionalAttrs, invertedBoolAttrs, staticAttrs
20273
20355
  */
@@ -20749,7 +20831,7 @@ function buildVariantDimensionLookups(j, args) {
20749
20831
  }
20750
20832
  }
20751
20833
  function hasStyleSourceOrder(d) {
20752
- return !!(d.variantSourceOrder && Object.keys(d.variantSourceOrder).length > 0) || (d.pseudoAliasSelectors ?? []).some((entry) => entry.sourceOrder !== void 0);
20834
+ return !!(d.variantSourceOrder && Object.keys(d.variantSourceOrder).length > 0) || (d.pseudoAliasSelectors ?? []).some((entry) => entry.sourceOrder !== void 0) || (d.needsUseThemeHook ?? []).some((entry) => entry.sourceOrder !== void 0);
20753
20835
  }
20754
20836
  /**
20755
20837
  * Sort ordered entries by source order and append them to styleArgs.
@@ -20991,7 +21073,7 @@ function buildVariantStyleExprs(opts) {
20991
21073
  * Appends conditional style args driven by theme boolean props (e.g., `theme.isDark`).
20992
21074
  * Returns `true` if the hook is needed (and calls `markNeedsUseThemeImport`).
20993
21075
  */
20994
- function appendThemeBooleanStyleArgs(hooks, styleArgs, j, stylesIdentifier, markNeedsUseThemeImport) {
21076
+ function appendThemeBooleanStyleArgs(hooks, styleArgs, j, stylesIdentifier, markNeedsUseThemeImport, orderedEntries) {
20995
21077
  if (!hooks || hooks.length === 0) return false;
20996
21078
  markNeedsUseThemeImport();
20997
21079
  for (const entry of hooks) {
@@ -20999,7 +21081,12 @@ function appendThemeBooleanStyleArgs(hooks, styleArgs, j, stylesIdentifier, mark
20999
21081
  const trueExpr = entry.trueStyleKey ? styleRef(j, stylesIdentifier, entry.trueStyleKey) : j.identifier("undefined");
21000
21082
  const falseExpr = entry.falseStyleKey ? styleRef(j, stylesIdentifier, entry.falseStyleKey) : j.identifier("undefined");
21001
21083
  const condition = entry.conditionExpr ? cloneAstNode(entry.conditionExpr) : j.memberExpression(j.identifier("theme"), j.identifier(entry.themeProp));
21002
- styleArgs.push(j.conditionalExpression(condition, trueExpr, falseExpr));
21084
+ const finalExpr = j.conditionalExpression(condition, trueExpr, falseExpr);
21085
+ if (orderedEntries && entry.sourceOrder !== void 0) orderedEntries.push({
21086
+ order: entry.sourceOrder,
21087
+ expr: finalExpr
21088
+ });
21089
+ else styleArgs.push(finalExpr);
21003
21090
  }
21004
21091
  return true;
21005
21092
  }
@@ -21084,11 +21171,12 @@ function appendAllPseudoStyleArgs(d, styleArgs, j, stylesIdentifier, orderedEntr
21084
21171
  * and emit-component.
21085
21172
  */
21086
21173
  function buildAllVariantAndStyleExprs(opts) {
21087
- const { d, emitter, j, stylesIdentifier, styleArgs, destructureProps, propDefaults, compoundVariantKeys, afterVariantStyleArgs, enableComplementaryMerging, buildCompoundVariantExpressions } = opts;
21174
+ const { d, emitter, j, stylesIdentifier, styleArgs, destructureProps, propDefaults, compoundVariantKeys, afterVariantStyleArgs, enableComplementaryMerging, markNeedsUseThemeImport, buildCompoundVariantExpressions } = opts;
21088
21175
  const booleanProps = collectBooleanPropNames(d);
21089
21176
  const knownProps = collectKnownConditionPropNames(emitter, d);
21090
21177
  const hasSourceOrder = hasStyleSourceOrder(d);
21091
21178
  const orderedEntries = [];
21179
+ const needsUseTheme = markNeedsUseThemeImport ? appendThemeBooleanStyleArgs(d.needsUseThemeHook, styleArgs, j, stylesIdentifier, markNeedsUseThemeImport, hasSourceOrder ? orderedEntries : void 0) : false;
21092
21180
  buildVariantStyleExprs({
21093
21181
  d,
21094
21182
  emitter,
@@ -21127,6 +21215,7 @@ function buildAllVariantAndStyleExprs(opts) {
21127
21215
  });
21128
21216
  mergeOrderedEntries(orderedEntries, styleArgs);
21129
21217
  if (afterVariantStyleArgs && afterVariantStyleArgs.length > 0) styleArgs.push(...afterVariantStyleArgs);
21218
+ return needsUseTheme;
21130
21219
  }
21131
21220
  /** Builds a `const theme = useTheme();` variable declaration. */
21132
21221
  function buildUseThemeDeclaration(j, themeHookLocalName) {
@@ -23018,7 +23107,7 @@ function emitComponentWrappers(emitter) {
23018
23107
  }
23019
23108
  const needsUseTheme = appendThemeBooleanStyleArgs(d.needsUseThemeHook, styleArgs, j, stylesIdentifier, () => {
23020
23109
  needsUseThemeImport = true;
23021
- });
23110
+ }, hasSourceOrder ? orderedEntries : void 0);
23022
23111
  for (const gp of appendAllPseudoStyleArgs(d, styleArgs, j, stylesIdentifier, hasSourceOrder ? orderedEntries : void 0)) if (!destructureProps.includes(gp)) {
23023
23112
  destructureProps.push(gp);
23024
23113
  styleOnlyConditionProps.add(gp);
@@ -24730,7 +24819,7 @@ function emitIntrinsicPolymorphicWrappers(ctx) {
24730
24819
  }) : [];
24731
24820
  const { beforeBase: extraStyleArgs, afterBase: extraStyleArgsAfterBase, afterVariants: afterVariantStyleArgs } = emitter.buildInterleavedExtraStyleArgs(d, propsArgExprs);
24732
24821
  const styleArgs = buildInitialStyleArgs(j, stylesIdentifier, d, extraStyleArgs, extraStyleArgsAfterBase);
24733
- buildAllVariantAndStyleExprs({
24822
+ const needsUseTheme = buildAllVariantAndStyleExprs({
24734
24823
  d,
24735
24824
  emitter,
24736
24825
  j,
@@ -24740,6 +24829,7 @@ function emitIntrinsicPolymorphicWrappers(ctx) {
24740
24829
  propDefaults,
24741
24830
  compoundVariantKeys: collectCompoundVariantKeys(d.compoundVariants),
24742
24831
  afterVariantStyleArgs,
24832
+ markNeedsUseThemeImport: () => ctx.markNeedsUseThemeImport(),
24743
24833
  buildCompoundVariantExpressions
24744
24834
  });
24745
24835
  const isVoidTag = VOID_TAGS.has(tagName);
@@ -24763,6 +24853,7 @@ function emitIntrinsicPolymorphicWrappers(ctx) {
24763
24853
  dynamicAttrs: d.attrsInfo?.dynamicAttrs ?? [],
24764
24854
  staticAttrs: d.attrsInfo?.staticAttrs ?? {}
24765
24855
  });
24856
+ const destructurePropsForPattern = needsUseTheme ? destructureProps.filter((name) => name !== "theme") : destructureProps;
24766
24857
  const patternProps = emitter.buildDestructurePatternProps({
24767
24858
  baseProps: [
24768
24859
  ...allowAsProp ? [j.property.from({
@@ -24777,7 +24868,7 @@ function emitIntrinsicPolymorphicWrappers(ctx) {
24777
24868
  ...allowStyleProp ? [ctx.patternProp("style", styleId)] : [],
24778
24869
  ...allowSxProp ? [ctx.patternProp("sx", sxId)] : []
24779
24870
  ],
24780
- destructureProps,
24871
+ destructureProps: destructurePropsForPattern,
24781
24872
  propDefaults,
24782
24873
  includeRest: true,
24783
24874
  restId
@@ -24797,7 +24888,7 @@ function emitIntrinsicPolymorphicWrappers(ctx) {
24797
24888
  allowClassNameProp,
24798
24889
  allowStyleProp,
24799
24890
  allowSxProp,
24800
- inlineStyleProps: [],
24891
+ inlineStyleProps: d.inlineStyleProps ?? [],
24801
24892
  staticStyleExpr: attrsInfoWithoutForwardedAsStatic?.attrsStaticStyleExpr,
24802
24893
  staticClassNameExpr,
24803
24894
  isIntrinsicElement: false
@@ -24822,6 +24913,7 @@ function emitIntrinsicPolymorphicWrappers(ctx) {
24822
24913
  childrenExpr: childrenId
24823
24914
  });
24824
24915
  const fnBodyStmts = [declStmt];
24916
+ if (needsUseTheme) fnBodyStmts.push(buildUseThemeDeclaration(j, emitter.themeHookLocalName));
24825
24917
  if (merging.sxDecl) fnBodyStmts.push(merging.sxDecl);
24826
24918
  fnBodyStmts.push(j.returnStatement(jsx));
24827
24919
  const polymorphicFnTypeParams = emitTypes && allowAsProp ? buildPolymorphicTypeParams(j, tagName) : void 0;
@@ -24985,12 +25077,12 @@ function emitShouldForwardPropWrappers(ctx) {
24985
25077
  const propsArgExprs = d.extraStylexPropsArgs ? emitter.buildExtraStylexPropsExprEntries({ entries: d.extraStylexPropsArgs }) : [];
24986
25078
  const { beforeBase: extraStyleArgs, afterBase: extraStyleArgsAfterBase, afterVariants: afterVariantStyleArgs } = emitter.buildInterleavedExtraStyleArgs(d, propsArgExprs);
24987
25079
  const styleArgs = buildInitialStyleArgs(j, stylesIdentifier, d, extraStyleArgs, extraStyleArgsAfterBase);
24988
- const needsUseTheme = appendThemeBooleanStyleArgs(d.needsUseThemeHook, styleArgs, j, stylesIdentifier, () => ctx.markNeedsUseThemeImport());
24989
25080
  const compoundVariantKeys = collectCompoundVariantKeys(d.compoundVariants);
24990
25081
  const booleanProps = collectBooleanPropNames(d);
24991
25082
  const knownProps = collectKnownConditionPropNames(emitter, d);
24992
25083
  const hasSourceOrder = hasStyleSourceOrder(d);
24993
25084
  const orderedEntries = [];
25085
+ const needsUseTheme = appendThemeBooleanStyleArgs(d.needsUseThemeHook, styleArgs, j, stylesIdentifier, () => ctx.markNeedsUseThemeImport(), hasSourceOrder ? orderedEntries : void 0);
24994
25086
  const pseudoGuardProps = appendAllPseudoStyleArgs(d, styleArgs, j, stylesIdentifier, hasSourceOrder ? orderedEntries : void 0);
24995
25087
  buildVariantStyleExprs({
24996
25088
  d,
@@ -25688,8 +25780,7 @@ function emitSimpleExportedIntrinsicWrappers(ctx) {
25688
25780
  }) : [];
25689
25781
  const { beforeBase: extraStyleArgs, afterBase: extraStyleArgsAfterBase, afterVariants: afterVariantStyleArgs } = emitter.buildInterleavedExtraStyleArgs(d, propsArgExprs);
25690
25782
  const styleArgs = buildInitialStyleArgs(j, stylesIdentifier, d, extraStyleArgs, extraStyleArgsAfterBase);
25691
- const needsUseTheme = appendThemeBooleanStyleArgs(d.needsUseThemeHook, styleArgs, j, stylesIdentifier, () => ctx.markNeedsUseThemeImport());
25692
- buildAllVariantAndStyleExprs({
25783
+ const needsUseTheme = buildAllVariantAndStyleExprs({
25693
25784
  d,
25694
25785
  emitter,
25695
25786
  j,
@@ -25700,6 +25791,7 @@ function emitSimpleExportedIntrinsicWrappers(ctx) {
25700
25791
  compoundVariantKeys: collectCompoundVariantKeys(d.compoundVariants),
25701
25792
  afterVariantStyleArgs,
25702
25793
  enableComplementaryMerging: true,
25794
+ markNeedsUseThemeImport: () => ctx.markNeedsUseThemeImport(),
25703
25795
  buildCompoundVariantExpressions
25704
25796
  });
25705
25797
  for (const attr of d.attrsInfo?.defaultAttrs ?? []) if (destructureProps.includes(attr.jsxProp) && (typeof attr.value === "string" || typeof attr.value === "number")) propDefaults.set(attr.jsxProp, attr.value);
@@ -26647,6 +26739,485 @@ function getTransformedComponentNames(ctx) {
26647
26739
  return names && names.length > 0 ? names : void 0;
26648
26740
  }
26649
26741
  //#endregion
26742
+ //#region src/internal/transform-steps/inline-prop-conditional-css-helpers.ts
26743
+ /**
26744
+ * Inlines prop-conditional css`` helpers into consumers so their prop-dependent
26745
+ * styles are preserved. Helpers that cannot be safely inlined are left untouched
26746
+ * (their `${helper}` reference falls through to the existing mixin bail).
26747
+ */
26748
+ function inlinePropConditionalCssHelpersStep(ctx) {
26749
+ const styledDecls = ctx.styledDecls;
26750
+ const cssHelperNames = ctx.cssHelpers?.cssHelperNames;
26751
+ if (!styledDecls || !cssHelperNames || cssHelperNames.size === 0) return CONTINUE;
26752
+ const declByLocalName = /* @__PURE__ */ new Map();
26753
+ for (const decl of styledDecls) declByLocalName.set(decl.localName, decl);
26754
+ const fullyInlinedHelpers = /* @__PURE__ */ new Set();
26755
+ const retainedHelpers = /* @__PURE__ */ new Set();
26756
+ for (const consumer of styledDecls) {
26757
+ if (consumer.isCssHelper) continue;
26758
+ for (const reference of collectInlinableHelperReferences(consumer, declByLocalName)) {
26759
+ const helperDecl = reference.helperDecl;
26760
+ if (!inlinablePropDependentDeclaration(helperDecl) || inlineWouldContend(reference, consumer)) {
26761
+ retainedHelpers.add(helperDecl.localName);
26762
+ continue;
26763
+ }
26764
+ if (inlineHelperReference(consumer, reference)) {
26765
+ fullyInlinedHelpers.add(helperDecl.localName);
26766
+ ctx.markChanged();
26767
+ } else retainedHelpers.add(helperDecl.localName);
26768
+ }
26769
+ }
26770
+ for (const decl of styledDecls) {
26771
+ if (!decl.isCssHelper) continue;
26772
+ for (const rule of decl.rules) for (const declaration of rule.declarations) {
26773
+ const referencedName = referencedHelperName(declaration, decl);
26774
+ if (referencedName && declByLocalName.get(referencedName)?.isCssHelper) retainedHelpers.add(referencedName);
26775
+ }
26776
+ }
26777
+ for (const decl of styledDecls) if (decl.isCssHelper && fullyInlinedHelpers.has(decl.localName) && !retainedHelpers.has(decl.localName)) decl.rules = [];
26778
+ return CONTINUE;
26779
+ }
26780
+ /**
26781
+ * Finds property-less `${helper}` references (single-slot identifier interpolations)
26782
+ * that sit in the consumer's top-level `&` rule. Only top-level references are returned;
26783
+ * references nested under selectors/at-rules are left for the existing bail path because
26784
+ * merging a helper's own declarations under another selector is not generally safe.
26785
+ */
26786
+ function collectInlinableHelperReferences(consumer, declByLocalName) {
26787
+ const references = [];
26788
+ for (const rule of consumer.rules) {
26789
+ if (rule.selector.trim() !== "&" || rule.atRuleStack.length > 0) continue;
26790
+ for (const referenceDecl of rule.declarations) {
26791
+ const helperName = referencedHelperName(referenceDecl, consumer);
26792
+ if (!helperName) continue;
26793
+ const helperDecl = declByLocalName.get(helperName);
26794
+ if (helperDecl?.isCssHelper) references.push({
26795
+ rule,
26796
+ referenceDecl,
26797
+ helperDecl
26798
+ });
26799
+ }
26800
+ }
26801
+ return references;
26802
+ }
26803
+ /** Returns the helper identifier name if `d` is a standalone `${identifier}` interpolation. */
26804
+ function referencedHelperName(d, consumer) {
26805
+ if (d.property || d.value.kind !== "interpolated") return null;
26806
+ const parts = d.value.parts;
26807
+ if (parts.length !== 1 || parts[0]?.kind !== "slot") return null;
26808
+ const expr = consumer.templateExpressions[parts[0].slotId];
26809
+ return expr?.type === "Identifier" && typeof expr.name === "string" ? expr.name : null;
26810
+ }
26811
+ /**
26812
+ * Returns the helper's single prop-dependent declaration when the helper is structurally
26813
+ * inlinable — otherwise null. Inlinable means it carries a prop-based interpolation (the case
26814
+ * the mixin path bails on) and is shaped so its declarations can be spliced into the consumer's
26815
+ * `&` block:
26816
+ *
26817
+ * - private (not exported / preserved for cross-file use),
26818
+ * - every rule is the top-level `&` block (no nested selectors, no at-rules),
26819
+ * - no chained mixin references (a property-less `${otherMixin}` / `${parts.reset}` slot)
26820
+ * — those compose as separate style keys whose ordering we cannot preserve by splicing, and
26821
+ * - exactly one prop-dependent declaration. That single dynamic entry is the case the mixin
26822
+ * path bails on, and it has no intra-helper ordering ambiguity. Zero means a plain mixin
26823
+ * (handled by the shared-style-key path); two or more dynamic entries are emitted as
26824
+ * styleFns/variants whose precedence depends on per-declaration source order, which the
26825
+ * splice (which stamps the single reference order on every inlined declaration) cannot
26826
+ * preserve.
26827
+ *
26828
+ * Whether the inline is *override-safe* is decided per reference by `inlineWouldContend`, which
26829
+ * is independent of how the value lowers.
26830
+ */
26831
+ function inlinablePropDependentDeclaration(helperDecl) {
26832
+ if (helperDecl.isExported || helperDecl.preserveCssHelperDeclaration) return null;
26833
+ let propDependentDeclaration = null;
26834
+ let propDependentCount = 0;
26835
+ for (const rule of helperDecl.rules) {
26836
+ if (rule.selector.trim() !== "&" || rule.atRuleStack.length > 0) return null;
26837
+ for (const declaration of rule.declarations) {
26838
+ if (!declaration.property) return null;
26839
+ if (declarationReadsProps(declaration, helperDecl.templateExpressions)) {
26840
+ propDependentCount += 1;
26841
+ propDependentDeclaration = declaration;
26842
+ }
26843
+ }
26844
+ }
26845
+ return propDependentCount === 1 ? propDependentDeclaration : null;
26846
+ }
26847
+ /**
26848
+ * Splicing is override-safe only when the set of properties the helper sets is disjoint from
26849
+ * every other declaration in the merged block. When a property has a single contributor, however
26850
+ * the inlined value lowers (variant or style function) the result matches styled-components; when
26851
+ * two declarations contend, their relative precedence depends on the lowering path, which the
26852
+ * splice cannot guarantee — so bail. This checks:
26853
+ *
26854
+ * - helper-internal overlap: two helper declarations touching the same leaf (e.g.
26855
+ * `color: ${dyn}; color: red`) have order-dependent precedence the splice may invert;
26856
+ * - helper-vs-consumer overlap: any helper property (its prop-dependent one *or* a static, which
26857
+ * could override an earlier dynamic consumer declaration) overlapping a consumer declaration;
26858
+ * - any property-less consumer declaration — a sibling mixin (`${reset}`) or dynamic block whose
26859
+ * emitted properties are unknown here.
26860
+ *
26861
+ * Every consumer rule is scanned (not just the reference's), so a later top-level `&` rule or a
26862
+ * nested selector/at-rule the consumer authors is included.
26863
+ */
26864
+ function inlineWouldContend(reference, consumer) {
26865
+ const helperDeclarations = reference.helperDecl.rules.flatMap((rule) => rule.declarations);
26866
+ for (let i = 0; i < helperDeclarations.length; i += 1) for (let j = i + 1; j < helperDeclarations.length; j += 1) if (propertiesConflict(helperDeclarations[i].property, helperDeclarations[j].property)) return true;
26867
+ for (const rule of consumer.rules) for (const declaration of rule.declarations) {
26868
+ if (declaration === reference.referenceDecl) continue;
26869
+ if (!declaration.property) return true;
26870
+ if (helperDeclarations.some((hd) => propertiesConflict(hd.property, declaration.property))) return true;
26871
+ }
26872
+ return false;
26873
+ }
26874
+ /**
26875
+ * Whether two CSS properties can set a common atomic StyleX longhand — i.e. they are equal, or
26876
+ * one is a shorthand whose expansion overlaps the other. Each property is expanded to its set of
26877
+ * atomic leaf longhands (a shorthand to its leaves, a longhand to itself) and the sets are
26878
+ * intersected. This correctly distinguishes overlapping families (`borderColor` vs
26879
+ * `borderTopColor`) from disjoint ones (`borderRadius` vs `border`, `width` vs `padding`).
26880
+ *
26881
+ * Backstop for shorthands the leaf table does not model: most CSS shorthands name their longhands
26882
+ * with their own camelCase prefix (`font` → `fontVariantNumeric`, `overscrollBehavior` →
26883
+ * `overscrollBehaviorX`). When the table cannot vouch for *both* properties (one is neither a known
26884
+ * shorthand nor a known leaf), a word-prefix relationship is treated as contention so an unmodeled
26885
+ * shorthand/longhand pair conservatively bails. Fully-modeled families skip this (so `border` and
26886
+ * `borderRadius`, which share the `border` prefix but are disjoint, still inline).
26887
+ */
26888
+ function propertiesConflict(a, b) {
26889
+ const stylexA = cssPropertyToStylexProp(a);
26890
+ const stylexB = cssPropertyToStylexProp(b);
26891
+ const leavesA = leafLonghands(stylexA);
26892
+ const leavesB = leafLonghands(stylexB);
26893
+ for (const leaf of leavesA) if (leavesB.has(leaf)) return true;
26894
+ if (isModeledProperty(stylexA) && isModeledProperty(stylexB)) return false;
26895
+ return isWordPrefix(stylexA, stylexB) || isWordPrefix(stylexB, stylexA);
26896
+ }
26897
+ /** Whether the leaf table reliably classifies a StyleX property (a known shorthand or leaf). */
26898
+ function isModeledProperty(stylexProp) {
26899
+ return KNOWN_SHORTHANDS.has(stylexProp) || KNOWN_LEAVES.has(stylexProp);
26900
+ }
26901
+ /** Whether `prefix` is `full` truncated at a camelCase word boundary (`font` ⊂ `fontVariant`). */
26902
+ function isWordPrefix(prefix, full) {
26903
+ if (full.length <= prefix.length || !full.startsWith(prefix)) return false;
26904
+ const next = full[prefix.length] ?? "";
26905
+ return next !== next.toLowerCase() && next === next.toUpperCase();
26906
+ }
26907
+ /**
26908
+ * The atomic physical StyleX longhands a property can set. A shorthand expands to its leaves; a
26909
+ * longhand resolves to itself. A logical longhand resolves to *both* physical sides on its axis
26910
+ * (e.g. `marginInlineStart` → `marginLeft` and `marginRight`) because the writing direction is
26911
+ * unknown — in RTL `inline-start` is the right side — so a logical declaration conservatively
26912
+ * contends with either physical side it could map to.
26913
+ */
26914
+ function leafLonghands(stylexProp) {
26915
+ const canonical = CSS_ALIASES[stylexProp] ?? stylexProp;
26916
+ if (LOGICAL_LEAF_TO_PHYSICAL[canonical]) return new Set(LOGICAL_LEAF_TO_PHYSICAL[canonical]);
26917
+ const leaves = SHORTHAND_LEAVES[canonical] ?? LOGICAL_TO_PHYSICAL[canonical] ?? [canonical];
26918
+ return new Set(leaves.flatMap(physicalLeaves));
26919
+ }
26920
+ /**
26921
+ * Legacy CSS property aliases → their canonical StyleX property. `cssPropertyToStylexProp` only
26922
+ * camelCases authored names, so an alias and its modern name read as disjoint leaves unless
26923
+ * collapsed here. This is the standard set of legacy name aliases: `word-wrap` for `overflow-wrap`;
26924
+ * `grid-gap`/`grid-row-gap`/`grid-column-gap` for `gap`/`row-gap`/`column-gap`; and
26925
+ * `page-break-before`/`page-break-after`/`page-break-inside` for `break-before`/`break-after`/
26926
+ * `break-inside`.
26927
+ */
26928
+ const CSS_ALIASES = {
26929
+ wordWrap: "overflowWrap",
26930
+ gridGap: "gap",
26931
+ gridRowGap: "rowGap",
26932
+ gridColumnGap: "columnGap",
26933
+ pageBreakBefore: "breakBefore",
26934
+ pageBreakAfter: "breakAfter",
26935
+ pageBreakInside: "breakInside"
26936
+ };
26937
+ /**
26938
+ * Maps a logical atomic longhand to every physical longhand it could map to under any writing
26939
+ * mode and direction. Flow-relative sides are not just RTL-swapped: in vertical writing modes the
26940
+ * block axis is horizontal and the inline axis is vertical, so a logical side can land on *any*
26941
+ * physical side. The mapping is therefore the full physical family, which is conservative but safe.
26942
+ */
26943
+ function physicalLeaves(stylexProp) {
26944
+ return LOGICAL_LEAF_TO_PHYSICAL[stylexProp] ?? [stylexProp];
26945
+ }
26946
+ const PHYSICAL_SIDES = [
26947
+ "Top",
26948
+ "Right",
26949
+ "Bottom",
26950
+ "Left"
26951
+ ];
26952
+ const BORDER_KINDS = [
26953
+ "Width",
26954
+ "Style",
26955
+ "Color"
26956
+ ];
26957
+ const ALL_INSET_SIDES = [
26958
+ "top",
26959
+ "right",
26960
+ "bottom",
26961
+ "left"
26962
+ ];
26963
+ const ALL_RADIUS_CORNERS = [
26964
+ "borderTopLeftRadius",
26965
+ "borderTopRightRadius",
26966
+ "borderBottomLeftRadius",
26967
+ "borderBottomRightRadius"
26968
+ ];
26969
+ /** Logical atomic longhand → every physical longhand it could map to under any writing mode. */
26970
+ const LOGICAL_LEAF_TO_PHYSICAL = {
26971
+ inlineSize: ["width", "height"],
26972
+ blockSize: ["width", "height"],
26973
+ minInlineSize: ["minWidth", "minHeight"],
26974
+ minBlockSize: ["minWidth", "minHeight"],
26975
+ maxInlineSize: ["maxWidth", "maxHeight"],
26976
+ maxBlockSize: ["maxWidth", "maxHeight"],
26977
+ containIntrinsicInlineSize: ["containIntrinsicWidth", "containIntrinsicHeight"],
26978
+ containIntrinsicBlockSize: ["containIntrinsicWidth", "containIntrinsicHeight"],
26979
+ overflowBlock: ["overflowX", "overflowY"],
26980
+ overflowInline: ["overflowX", "overflowY"],
26981
+ overscrollBehaviorBlock: ["overscrollBehaviorX", "overscrollBehaviorY"],
26982
+ overscrollBehaviorInline: ["overscrollBehaviorX", "overscrollBehaviorY"],
26983
+ borderStartStartRadius: ALL_RADIUS_CORNERS,
26984
+ borderStartEndRadius: ALL_RADIUS_CORNERS,
26985
+ borderEndStartRadius: ALL_RADIUS_CORNERS,
26986
+ borderEndEndRadius: ALL_RADIUS_CORNERS
26987
+ };
26988
+ for (const axis of ["Block", "Inline"]) for (const end of ["Start", "End"]) {
26989
+ for (const base of [
26990
+ "margin",
26991
+ "padding",
26992
+ "scrollMargin",
26993
+ "scrollPadding"
26994
+ ]) LOGICAL_LEAF_TO_PHYSICAL[`${base}${axis}${end}`] = PHYSICAL_SIDES.map((side) => `${base}${side}`);
26995
+ LOGICAL_LEAF_TO_PHYSICAL[`inset${axis}${end}`] = ALL_INSET_SIDES;
26996
+ for (const kind of BORDER_KINDS) LOGICAL_LEAF_TO_PHYSICAL[`border${axis}${end}${kind}`] = PHYSICAL_SIDES.map((side) => `border${side}${kind}`);
26997
+ }
26998
+ /**
26999
+ * StyleX shorthand → its atomic leaf longhands (in physical form). Used to decide whether two
27000
+ * declarations contend for the same property. Mid-level shorthands (`borderTop`, `borderColor`,
27001
+ * `borderBlock`) are included so intersection captures partial overlap (e.g. `border` vs
27002
+ * `borderTopColor`). Directional families (margin/padding/inset/border) are generated for both
27003
+ * their physical and logical names; logical leaves are normalized to physical via `toPhysicalLeaf`.
27004
+ */
27005
+ const SHORTHAND_LEAVES = {
27006
+ gap: ["rowGap", "columnGap"],
27007
+ overflow: ["overflowX", "overflowY"],
27008
+ overscrollBehavior: ["overscrollBehaviorX", "overscrollBehaviorY"],
27009
+ containIntrinsicSize: ["containIntrinsicWidth", "containIntrinsicHeight"],
27010
+ textEmphasis: ["textEmphasisStyle", "textEmphasisColor"],
27011
+ mask: [
27012
+ "maskImage",
27013
+ "maskMode",
27014
+ "maskRepeat",
27015
+ "maskPosition",
27016
+ "maskClip",
27017
+ "maskOrigin",
27018
+ "maskSize",
27019
+ "maskComposite"
27020
+ ],
27021
+ offset: [
27022
+ "offsetPath",
27023
+ "offsetDistance",
27024
+ "offsetRotate",
27025
+ "offsetAnchor",
27026
+ "offsetPosition"
27027
+ ],
27028
+ borderRadius: [
27029
+ "borderTopLeftRadius",
27030
+ "borderTopRightRadius",
27031
+ "borderBottomRightRadius",
27032
+ "borderBottomLeftRadius"
27033
+ ],
27034
+ borderImage: [
27035
+ "borderImageSource",
27036
+ "borderImageSlice",
27037
+ "borderImageWidth",
27038
+ "borderImageOutset",
27039
+ "borderImageRepeat"
27040
+ ],
27041
+ outline: [
27042
+ "outlineWidth",
27043
+ "outlineStyle",
27044
+ "outlineColor"
27045
+ ],
27046
+ font: [
27047
+ "fontStyle",
27048
+ "fontVariant",
27049
+ "fontWeight",
27050
+ "fontStretch",
27051
+ "fontSize",
27052
+ "lineHeight",
27053
+ "fontFamily"
27054
+ ],
27055
+ background: [
27056
+ "backgroundColor",
27057
+ "backgroundImage",
27058
+ "backgroundPositionX",
27059
+ "backgroundPositionY",
27060
+ "backgroundSize",
27061
+ "backgroundRepeat",
27062
+ "backgroundOrigin",
27063
+ "backgroundClip",
27064
+ "backgroundAttachment"
27065
+ ],
27066
+ backgroundPosition: ["backgroundPositionX", "backgroundPositionY"],
27067
+ flex: [
27068
+ "flexGrow",
27069
+ "flexShrink",
27070
+ "flexBasis"
27071
+ ],
27072
+ flexFlow: ["flexDirection", "flexWrap"],
27073
+ placeItems: ["alignItems", "justifyItems"],
27074
+ placeContent: ["alignContent", "justifyContent"],
27075
+ placeSelf: ["alignSelf", "justifySelf"],
27076
+ gridArea: [
27077
+ "gridRowStart",
27078
+ "gridColumnStart",
27079
+ "gridRowEnd",
27080
+ "gridColumnEnd"
27081
+ ],
27082
+ gridColumn: ["gridColumnStart", "gridColumnEnd"],
27083
+ gridRow: ["gridRowStart", "gridRowEnd"],
27084
+ gridTemplate: [
27085
+ "gridTemplateRows",
27086
+ "gridTemplateColumns",
27087
+ "gridTemplateAreas"
27088
+ ],
27089
+ grid: [
27090
+ "gridTemplateRows",
27091
+ "gridTemplateColumns",
27092
+ "gridTemplateAreas",
27093
+ "gridAutoRows",
27094
+ "gridAutoColumns",
27095
+ "gridAutoFlow"
27096
+ ],
27097
+ columns: ["columnWidth", "columnCount"],
27098
+ columnRule: [
27099
+ "columnRuleWidth",
27100
+ "columnRuleStyle",
27101
+ "columnRuleColor"
27102
+ ],
27103
+ transition: [
27104
+ "transitionProperty",
27105
+ "transitionDuration",
27106
+ "transitionTimingFunction",
27107
+ "transitionDelay"
27108
+ ],
27109
+ animation: [
27110
+ "animationName",
27111
+ "animationDuration",
27112
+ "animationTimingFunction",
27113
+ "animationDelay",
27114
+ "animationIterationCount",
27115
+ "animationDirection",
27116
+ "animationFillMode",
27117
+ "animationPlayState"
27118
+ ],
27119
+ textDecoration: [
27120
+ "textDecorationLine",
27121
+ "textDecorationStyle",
27122
+ "textDecorationColor",
27123
+ "textDecorationThickness"
27124
+ ],
27125
+ whiteSpace: ["whiteSpaceCollapse", "textWrapMode"],
27126
+ textWrap: ["textWrapMode", "textWrapStyle"],
27127
+ listStyle: [
27128
+ "listStyleType",
27129
+ "listStylePosition",
27130
+ "listStyleImage"
27131
+ ]
27132
+ };
27133
+ const borderLeaf = (side, kind) => `border${side}${kind}`;
27134
+ const ALL_BORDER_LEAVES = PHYSICAL_SIDES.flatMap((side) => BORDER_KINDS.map((kind) => borderLeaf(side, kind)));
27135
+ for (const base of [
27136
+ "margin",
27137
+ "padding",
27138
+ "scrollMargin",
27139
+ "scrollPadding"
27140
+ ]) {
27141
+ const allSides = PHYSICAL_SIDES.map((side) => `${base}${side}`);
27142
+ SHORTHAND_LEAVES[base] = allSides;
27143
+ SHORTHAND_LEAVES[`${base}Block`] = allSides;
27144
+ SHORTHAND_LEAVES[`${base}Inline`] = allSides;
27145
+ }
27146
+ SHORTHAND_LEAVES.inset = ALL_INSET_SIDES;
27147
+ SHORTHAND_LEAVES.insetBlock = ALL_INSET_SIDES;
27148
+ SHORTHAND_LEAVES.insetInline = ALL_INSET_SIDES;
27149
+ SHORTHAND_LEAVES.border = [...ALL_BORDER_LEAVES, ...SHORTHAND_LEAVES.borderImage];
27150
+ SHORTHAND_LEAVES.borderBlock = ALL_BORDER_LEAVES;
27151
+ SHORTHAND_LEAVES.borderInline = ALL_BORDER_LEAVES;
27152
+ for (const side of PHYSICAL_SIDES) SHORTHAND_LEAVES[`border${side}`] = BORDER_KINDS.map((kind) => borderLeaf(side, kind));
27153
+ for (const kind of BORDER_KINDS) {
27154
+ const allOfKind = PHYSICAL_SIDES.map((side) => borderLeaf(side, kind));
27155
+ SHORTHAND_LEAVES[`border${kind}`] = allOfKind;
27156
+ SHORTHAND_LEAVES[`borderBlock${kind}`] = allOfKind;
27157
+ SHORTHAND_LEAVES[`borderInline${kind}`] = allOfKind;
27158
+ }
27159
+ for (const axis of ["Block", "Inline"]) for (const end of ["Start", "End"]) SHORTHAND_LEAVES[`border${axis}${end}`] = ALL_BORDER_LEAVES;
27160
+ const KNOWN_SHORTHANDS = new Set(Object.keys(SHORTHAND_LEAVES));
27161
+ const KNOWN_LEAVES = /* @__PURE__ */ new Set();
27162
+ for (const leaves of Object.values(SHORTHAND_LEAVES)) for (const leaf of leaves) KNOWN_LEAVES.add(leaf);
27163
+ for (const leaves of Object.values(LOGICAL_LEAF_TO_PHYSICAL)) for (const leaf of leaves) KNOWN_LEAVES.add(leaf);
27164
+ /** True when a declaration's interpolated value reads a non-theme component prop. */
27165
+ function declarationReadsProps(declaration, templateExpressions) {
27166
+ if (declaration.value.kind !== "interpolated") return false;
27167
+ for (const part of declaration.value.parts) if (part.kind === "slot" && expressionReadsNonThemeProps(templateExpressions[part.slotId])) return true;
27168
+ return false;
27169
+ }
27170
+ /** Mirrors the mixin-bail detection: an arrow/function interpolation that reads non-theme props. */
27171
+ function expressionReadsNonThemeProps(expr) {
27172
+ const node = expr;
27173
+ if (!node || node.type !== "ArrowFunctionExpression" && node.type !== "FunctionExpression") return false;
27174
+ const propsUsed = new Set([...collectPropsFromArrowFn(node), ...collectPropsFromArrowFnDestructured(node)]);
27175
+ propsUsed.delete("theme");
27176
+ return propsUsed.size > 0;
27177
+ }
27178
+ /**
27179
+ * Splices the helper's `&`-block declarations into the consumer at the reference site,
27180
+ * remapping the helper's interpolation slots onto freshly-appended consumer template
27181
+ * expressions. Returns false (without mutating) when the reference is no longer present.
27182
+ */
27183
+ function inlineHelperReference(consumer, reference) {
27184
+ const { rule, referenceDecl, helperDecl } = reference;
27185
+ const declIndex = rule.declarations.indexOf(referenceDecl);
27186
+ if (declIndex === -1) return false;
27187
+ const slotOffset = consumer.templateExpressions.length;
27188
+ const inheritedSourceOrder = referenceDecl.sourceOrder;
27189
+ const inlinedDecls = helperDecl.rules.flatMap((helperRule) => helperRule.declarations.map((d) => remapDeclaration(d, slotOffset, inheritedSourceOrder)));
27190
+ for (const expr of helperDecl.templateExpressions) consumer.templateExpressions.push(cloneAstNode(expr));
27191
+ rule.declarations.splice(declIndex, 1, ...inlinedDecls);
27192
+ return true;
27193
+ }
27194
+ /** Deep-clones a CSS declaration, offsetting every interpolation slot id by `slotOffset`. */
27195
+ function remapDeclaration(d, slotOffset, sourceOrder) {
27196
+ const value = d.value.kind === "interpolated" ? {
27197
+ kind: "interpolated",
27198
+ parts: d.value.parts.map((part) => part.kind === "slot" ? {
27199
+ kind: "slot",
27200
+ slotId: part.slotId + slotOffset
27201
+ } : {
27202
+ kind: "static",
27203
+ value: part.value
27204
+ })
27205
+ } : {
27206
+ kind: "static",
27207
+ value: d.value.value
27208
+ };
27209
+ return {
27210
+ ...d,
27211
+ value,
27212
+ valueRaw: offsetPlaceholders(d.valueRaw, slotOffset),
27213
+ sourceOrder
27214
+ };
27215
+ }
27216
+ /** Rewrites `__SC_EXPR_<n>__` placeholders in a raw value string by adding `slotOffset`. */
27217
+ function offsetPlaceholders(valueRaw, slotOffset) {
27218
+ return valueRaw.replace(/__SC_EXPR_(\d+)__/g, (_, n) => `__SC_EXPR_${Number(n) + slotOffset}__`);
27219
+ }
27220
+ //#endregion
26650
27221
  //#region src/internal/lower-rules/slot-utils.ts
26651
27222
  /**
26652
27223
  * Locate the slot interpolation in a `${...}` value and return its
@@ -27071,8 +27642,45 @@ function tryResolveConditionalValue(node, ctx) {
27071
27642
  const buildRuntimeCallResult = () => runtimeCallState.info ? {
27072
27643
  type: "runtimeCallOnly",
27073
27644
  resolveCallContext: runtimeCallState.info.resolveCallContext,
27074
- resolveCallResult: runtimeCallState.info.resolveCallResult
27645
+ resolveCallResult: runtimeCallState.info.resolveCallResult,
27646
+ ...runtimeCallState.info.cssValueText ? { cssValueText: runtimeCallState.info.cssValueText } : {}
27075
27647
  } : null;
27648
+ const markAsRuntimeCall = (call) => {
27649
+ runtimeCallState.info = {
27650
+ resolveCallContext: {
27651
+ callSiteFilePath: ctx.filePath,
27652
+ calleeImportedName: "<local>",
27653
+ calleeSource: {
27654
+ kind: "specifier",
27655
+ value: ctx.filePath
27656
+ },
27657
+ args: [],
27658
+ ...call.loc?.start ? { loc: {
27659
+ line: call.loc.start.line,
27660
+ column: call.loc.start.column
27661
+ } } : {}
27662
+ },
27663
+ resolveCallResult: { preserveRuntimeCall: true }
27664
+ };
27665
+ };
27666
+ const markFirstRuntimeCallInBranch = (branch) => {
27667
+ const pending = [branch];
27668
+ const seen = /* @__PURE__ */ new Set();
27669
+ while (pending.length > 0) {
27670
+ const current = pending.pop();
27671
+ if (!current || typeof current !== "object" || seen.has(current)) continue;
27672
+ seen.add(current);
27673
+ if (isCallExpressionNode(current)) {
27674
+ markAsRuntimeCall(current);
27675
+ return;
27676
+ }
27677
+ const node = current;
27678
+ if (node.type === "BinaryExpression" || node.type === "LogicalExpression") pending.push(node.left, node.right);
27679
+ else if (node.type === "TemplateLiteral") pending.push(...node.expressions ?? []);
27680
+ else if (node.type === "ConditionalExpression") pending.push(node.test, node.consequent, node.alternate);
27681
+ else if (node.expression) pending.push(node.expression);
27682
+ }
27683
+ };
27076
27684
  const body = getFunctionBodyExpr(expr);
27077
27685
  if (!body || body.type !== "ConditionalExpression") return null;
27078
27686
  const checkThemeBooleanTest = (test) => {
@@ -27119,93 +27727,41 @@ function tryResolveConditionalValue(node, ctx) {
27119
27727
  }
27120
27728
  return null;
27121
27729
  };
27122
- const resolveThemeBranchValue = (branch) => {
27123
- const themeInfo = resolveThemeFromMemberExpr(branch);
27124
- if (!themeInfo) return null;
27125
- const res = (ctx.resolveValueOptional ?? ctx.resolveValue)({
27126
- kind: "theme",
27127
- path: themeInfo.path,
27128
- filePath: ctx.filePath,
27129
- loc: getNodeLocStart(branch) ?? void 0
27130
- });
27131
- if (!res) return null;
27132
- const astNode = parseExpr(ctx.api, res.expr);
27133
- if (!astNode) return null;
27134
- return {
27135
- astNode,
27136
- imports: res.imports
27137
- };
27138
- };
27139
- const themeBoolInfo = checkThemeBooleanTest(body.test);
27140
- if (themeBoolInfo && node.css.property) {
27141
- const { consequent, alternate } = body;
27142
- const trueBranch = themeBoolInfo.isNegated ? alternate : consequent;
27143
- const falseBranch = themeBoolInfo.isNegated ? consequent : alternate;
27144
- const trueRaw = literalToStaticValue(trueBranch);
27145
- const falseRaw = literalToStaticValue(falseBranch);
27146
- let trueValue = trueRaw !== null && typeof trueRaw !== "boolean" ? trueRaw : null;
27147
- let falseValue = falseRaw !== null && typeof falseRaw !== "boolean" ? falseRaw : null;
27148
- const trueImports = [];
27149
- const falseImports = [];
27150
- if (trueValue === null) {
27151
- const resolved = resolveThemeBranchValue(trueBranch);
27152
- if (resolved) {
27153
- trueValue = resolved.astNode;
27154
- trueImports.push(...resolved.imports);
27155
- }
27156
- }
27157
- if (falseValue === null) {
27158
- const resolved = resolveThemeBranchValue(falseBranch);
27159
- if (resolved) {
27160
- falseValue = resolved.astNode;
27161
- falseImports.push(...resolved.imports);
27162
- }
27163
- }
27164
- if (trueValue !== null && falseValue !== null) return {
27165
- type: "splitThemeBooleanVariants",
27166
- cssProp: node.css.property,
27167
- themeProp: themeBoolInfo.themeProp,
27168
- trueValue,
27169
- falseValue,
27170
- trueImports,
27171
- falseImports
27172
- };
27173
- const inlineStyleFallback = tryBuildThemeBooleanInlineStyleFallback({
27174
- trueValue,
27175
- falseValue,
27176
- trueImports,
27177
- falseImports,
27178
- trueBranch,
27179
- falseBranch,
27180
- themeBoolInfo,
27181
- cssProp: node.css.property,
27182
- paramName,
27183
- info
27184
- });
27185
- if (inlineStyleFallback) return inlineStyleFallback;
27186
- }
27187
27730
  const expectedUsage = node.css.property ? "create" : "props";
27188
- const branchToExpr = (b) => {
27731
+ const branchToExpr = (b, mode = "default") => {
27732
+ const resolveValue = mode === "optional" ? ctx.resolveValueOptional ?? ctx.resolveValue : ctx.resolveValue;
27733
+ const resolverCtx = mode === "optional" ? {
27734
+ ...ctx,
27735
+ resolveValue,
27736
+ resolveCall: ctx.resolveCallOptional ?? ctx.resolveCall
27737
+ } : ctx;
27189
27738
  const v = literalToStaticValue(b);
27190
27739
  if (v !== null) {
27191
27740
  if (typeof v === "boolean") return null;
27192
27741
  return {
27193
27742
  usage: "create",
27194
27743
  expr: typeof v === "string" ? JSON.stringify(v) : String(v),
27195
- imports: []
27744
+ imports: [],
27745
+ ...typeof v === "string" ? { cssValueText: v } : {}
27196
27746
  };
27197
27747
  }
27198
27748
  if (!b || typeof b !== "object") return null;
27199
27749
  if (b.type === "BinaryExpression") {
27200
27750
  const binary = b;
27201
27751
  if (isCssCalcOperator$1(binary.operator)) {
27202
- const left = branchToExpr(binary.left);
27203
- const right = branchToExpr(binary.right);
27204
- if (left && right && left.usage === expectedUsage && right.usage === expectedUsage && (left.imports.length > 0 || right.imports.length > 0) && isCssCalcSafeOperand(left) && isCssCalcSafeOperand(right)) return {
27205
- usage: expectedUsage,
27206
- expr: buildCssCalcExprSource(left, binary.operator, right),
27207
- imports: [...left.imports, ...right.imports]
27208
- };
27752
+ const left = branchToExpr(binary.left, mode);
27753
+ const right = branchToExpr(binary.right, mode);
27754
+ if (left && right && left.usage === expectedUsage && right.usage === expectedUsage && (left.imports.length > 0 || right.imports.length > 0) && isCssCalcSafeOperand(left) && isCssCalcSafeOperand(right)) {
27755
+ if (left.dynamicArgUsage || right.dynamicArgUsage) {
27756
+ markFirstRuntimeCallInBranch(left.dynamicArgUsage ? binary.left : binary.right);
27757
+ return null;
27758
+ }
27759
+ return {
27760
+ usage: expectedUsage,
27761
+ expr: buildCssCalcExprSource(left, binary.operator, right),
27762
+ imports: [...left.imports, ...right.imports]
27763
+ };
27764
+ }
27209
27765
  }
27210
27766
  }
27211
27767
  const callHasThemeArg = (call) => (call.arguments ?? []).some((arg) => {
@@ -27220,28 +27776,17 @@ function tryResolveConditionalValue(node, ctx) {
27220
27776
  }
27221
27777
  return false;
27222
27778
  });
27223
- const markAsRuntimeCall = (call) => {
27224
- runtimeCallState.info = {
27225
- resolveCallContext: {
27226
- callSiteFilePath: ctx.filePath,
27227
- calleeImportedName: "<local>",
27228
- calleeSource: {
27229
- kind: "specifier",
27230
- value: ctx.filePath
27231
- },
27232
- args: [],
27233
- ...call.loc?.start ? { loc: {
27234
- line: call.loc.start.line,
27235
- column: call.loc.start.column
27236
- } } : {}
27237
- },
27238
- resolveCallResult: { preserveRuntimeCall: true }
27239
- };
27240
- };
27241
27779
  const resolveCallExpr = (call, cssProperty) => {
27242
- const res = resolveImportedHelperCall(call, ctx, propsParamName, cssProperty, themeBindingName);
27780
+ const res = resolveImportedHelperCall(call, resolverCtx, propsParamName, cssProperty, themeBindingName);
27243
27781
  if (res.kind === "resolved") {
27244
- if ("expr" in res.result) return res.result;
27782
+ if ("expr" in res.result) {
27783
+ if ("preserveRuntimeCall" in res.result && res.result.preserveRuntimeCall) runtimeCallState.info = {
27784
+ resolveCallContext: res.resolveCallContext,
27785
+ resolveCallResult: res.resolveCallResult,
27786
+ cssValueText: res.result.expr
27787
+ };
27788
+ return res.result;
27789
+ }
27245
27790
  if ("preserveRuntimeCall" in res.result && res.result.preserveRuntimeCall) {
27246
27791
  runtimeCallState.info = {
27247
27792
  resolveCallContext: res.resolveCallContext,
@@ -27253,10 +27798,17 @@ function tryResolveConditionalValue(node, ctx) {
27253
27798
  if (isCallExpressionNode(call.callee)) {
27254
27799
  const inner = call.callee;
27255
27800
  const outerArgs = call.arguments ?? [];
27256
- if (outerArgs.length === 1 && outerArgs[0] && typeof outerArgs[0] === "object") {
27257
- const innerRes = resolveImportedHelperCall(inner, ctx, propsParamName, cssProperty, themeBindingName);
27801
+ if (outerArgs.length === 1 && isCurrentCurriedHelperContextArg(outerArgs[0], propsParamName, themeBindingName)) {
27802
+ const innerRes = resolveImportedHelperCall(inner, resolverCtx, propsParamName, cssProperty, themeBindingName);
27258
27803
  if (innerRes.kind === "resolved") {
27259
- if ("expr" in innerRes.result) return innerRes.result;
27804
+ if ("expr" in innerRes.result) {
27805
+ if ("preserveRuntimeCall" in innerRes.result && innerRes.result.preserveRuntimeCall) runtimeCallState.info = {
27806
+ resolveCallContext: innerRes.resolveCallContext,
27807
+ resolveCallResult: innerRes.resolveCallResult,
27808
+ cssValueText: innerRes.result.expr
27809
+ };
27810
+ return innerRes.result;
27811
+ }
27260
27812
  if ("preserveRuntimeCall" in innerRes.result && innerRes.result.preserveRuntimeCall) {
27261
27813
  runtimeCallState.info = {
27262
27814
  resolveCallContext: innerRes.resolveCallContext,
@@ -27270,9 +27822,10 @@ function tryResolveConditionalValue(node, ctx) {
27270
27822
  if (callHasThemeArg(call)) markAsRuntimeCall(call);
27271
27823
  return null;
27272
27824
  };
27825
+ let templateHasDynamicArgUsage = false;
27273
27826
  const templateResult = resolveTemplateLiteralExpressions(b, (expr) => {
27274
27827
  const themeInfo = resolveThemeFromMemberExpr(expr);
27275
- if (themeInfo) return ctx.resolveValue({
27828
+ if (themeInfo) return resolveValue({
27276
27829
  kind: "theme",
27277
27830
  path: themeInfo.path,
27278
27831
  filePath: ctx.filePath,
@@ -27280,6 +27833,10 @@ function tryResolveConditionalValue(node, ctx) {
27280
27833
  }) ?? null;
27281
27834
  if (isCallExpressionNode(expr)) {
27282
27835
  const callRes = resolveCallExpr(expr, node.css.property);
27836
+ if (callRes?.dynamicArgUsage) {
27837
+ templateHasDynamicArgUsage = true;
27838
+ markAsRuntimeCall(expr);
27839
+ }
27283
27840
  return callRes ? {
27284
27841
  expr: callRes.expr,
27285
27842
  imports: callRes.imports
@@ -27287,22 +27844,29 @@ function tryResolveConditionalValue(node, ctx) {
27287
27844
  }
27288
27845
  return null;
27289
27846
  });
27290
- if (templateResult) return {
27291
- usage: "create",
27292
- ...templateResult
27293
- };
27847
+ if (templateResult) {
27848
+ if (templateHasDynamicArgUsage && runtimeCallState.info) runtimeCallState.info.cssValueText = templateResult.expr;
27849
+ return {
27850
+ usage: "create",
27851
+ ...templateResult,
27852
+ cssValueText: templateResult.expr,
27853
+ ...templateHasDynamicArgUsage ? { dynamicArgUsage: "call" } : {}
27854
+ };
27855
+ }
27294
27856
  if (isCallExpressionNode(b)) {
27295
27857
  const resolved = resolveCallExpr(b, node.css.property);
27296
27858
  if (resolved) return {
27297
27859
  usage: isAdapterResultCssValue(resolved, node.css.property) ? "create" : "props",
27298
27860
  expr: resolved.expr,
27299
- imports: resolved.imports
27861
+ imports: resolved.imports,
27862
+ cssValueText: resolved.expr,
27863
+ ...resolved.dynamicArgUsage ? { dynamicArgUsage: resolved.dynamicArgUsage } : {}
27300
27864
  };
27301
27865
  return null;
27302
27866
  }
27303
27867
  const themeInfo = resolveThemeFromMemberExpr(b);
27304
27868
  if (themeInfo) {
27305
- const res = ctx.resolveValue({
27869
+ const res = resolveValue({
27306
27870
  kind: "theme",
27307
27871
  path: themeInfo.path,
27308
27872
  filePath: ctx.filePath,
@@ -27312,14 +27876,15 @@ function tryResolveConditionalValue(node, ctx) {
27312
27876
  return {
27313
27877
  usage: expectedUsage,
27314
27878
  expr: res.expr,
27315
- imports: res.imports
27879
+ imports: res.imports,
27880
+ cssValueText: res.expr
27316
27881
  };
27317
27882
  }
27318
27883
  const importedInfo = extractRootAndPath(b);
27319
27884
  if (importedInfo) {
27320
27885
  const imp = ctx.resolveImport(importedInfo.rootName, importedInfo.rootNode);
27321
27886
  if (imp) {
27322
- const res = ctx.resolveValue({
27887
+ const res = resolveValue({
27323
27888
  kind: "importedValue",
27324
27889
  importedName: imp.importedName,
27325
27890
  source: imp.source,
@@ -27330,7 +27895,8 @@ function tryResolveConditionalValue(node, ctx) {
27330
27895
  if (res) return {
27331
27896
  usage: expectedUsage,
27332
27897
  expr: res.expr,
27333
- imports: res.imports
27898
+ imports: res.imports,
27899
+ cssValueText: res.expr
27334
27900
  };
27335
27901
  }
27336
27902
  }
@@ -27339,6 +27905,106 @@ function tryResolveConditionalValue(node, ctx) {
27339
27905
  const getBranch = (value) => {
27340
27906
  return branchToExpr(value);
27341
27907
  };
27908
+ const getBranchOptional = (value) => {
27909
+ return branchToExpr(value, "optional");
27910
+ };
27911
+ const isEmptyCssInterpolationBranch = (value) => isEmptyCssBranch(value);
27912
+ const resolveThemeBooleanStyleValue = (branch) => {
27913
+ if (isEmptyCssBranch(branch)) return null;
27914
+ const raw = literalToStaticValue(branch);
27915
+ if (raw !== null && typeof raw !== "boolean") return {
27916
+ value: raw,
27917
+ imports: [],
27918
+ ...typeof raw === "string" ? { cssValueText: raw } : {}
27919
+ };
27920
+ const themeInfo = resolveThemeFromMemberExpr(branch);
27921
+ if (themeInfo) {
27922
+ const res = (ctx.resolveValueOptional ?? ctx.resolveValue)({
27923
+ kind: "theme",
27924
+ path: themeInfo.path,
27925
+ filePath: ctx.filePath,
27926
+ loc: getNodeLocStart(branch) ?? void 0
27927
+ });
27928
+ if (!res) return null;
27929
+ const astNode = parseExpr(ctx.api, res.expr);
27930
+ return astNode ? {
27931
+ value: astNode,
27932
+ imports: res.imports,
27933
+ cssValueText: res.expr
27934
+ } : null;
27935
+ }
27936
+ const resolved = getBranchOptional(branch);
27937
+ if (!resolved || resolved.usage !== "create") return null;
27938
+ if (resolved.dynamicArgUsage) {
27939
+ if (isCallExpressionNode(branch)) markAsRuntimeCall(branch);
27940
+ return null;
27941
+ }
27942
+ const astNode = parseExpr(ctx.api, resolved.expr);
27943
+ return astNode ? {
27944
+ value: astNode,
27945
+ imports: resolved.imports,
27946
+ cssValueText: resolved.cssValueText ?? resolved.expr
27947
+ } : null;
27948
+ };
27949
+ const themeBoolInfo = checkThemeBooleanTest(body.test);
27950
+ if (themeBoolInfo && node.css.property) {
27951
+ const { consequent, alternate } = body;
27952
+ const trueBranch = themeBoolInfo.isNegated ? alternate : consequent;
27953
+ const falseBranch = themeBoolInfo.isNegated ? consequent : alternate;
27954
+ let runtimeCallBranch = null;
27955
+ const noteRuntimeCallBranch = (branch, before) => {
27956
+ if (runtimeCallState.info === before) return;
27957
+ runtimeCallBranch = runtimeCallBranch && runtimeCallBranch !== branch ? "both" : branch;
27958
+ };
27959
+ const beforeTrueResolve = runtimeCallState.info;
27960
+ const trueResolved = resolveThemeBooleanStyleValue(trueBranch);
27961
+ noteRuntimeCallBranch("true", beforeTrueResolve);
27962
+ const beforeFalseResolve = runtimeCallState.info;
27963
+ const falseResolved = resolveThemeBooleanStyleValue(falseBranch);
27964
+ noteRuntimeCallBranch("false", beforeFalseResolve);
27965
+ const trueValue = trueResolved?.value ?? null;
27966
+ const falseValue = falseResolved?.value ?? null;
27967
+ const trueImports = trueResolved?.imports ?? [];
27968
+ const falseImports = falseResolved?.imports ?? [];
27969
+ const trueCssValueText = trueResolved?.cssValueText;
27970
+ const falseCssValueText = falseResolved?.cssValueText;
27971
+ if (trueValue !== null && falseValue !== null) {
27972
+ const runtimeCallInfo = runtimeCallState.info;
27973
+ return {
27974
+ type: "splitThemeBooleanVariants",
27975
+ cssProp: node.css.property,
27976
+ themeProp: themeBoolInfo.themeProp,
27977
+ trueValue,
27978
+ falseValue,
27979
+ trueImports,
27980
+ falseImports,
27981
+ ...trueCssValueText ? { trueCssValueText } : {},
27982
+ ...falseCssValueText ? { falseCssValueText } : {},
27983
+ ...runtimeCallInfo?.resolveCallResult ? { runtimeResolveCallResult: runtimeCallInfo.resolveCallResult } : {},
27984
+ ...runtimeCallInfo?.cssValueText ? { runtimeCssValueText: runtimeCallInfo.cssValueText } : {}
27985
+ };
27986
+ }
27987
+ if (trueValue === null !== (falseValue === null) && isEmptyCssInterpolationBranch(trueValue === null ? trueBranch : falseBranch)) return null;
27988
+ const inlineStyleFallback = tryBuildThemeBooleanInlineStyleFallback({
27989
+ trueValue,
27990
+ falseValue,
27991
+ trueImports,
27992
+ falseImports,
27993
+ trueBranch,
27994
+ falseBranch,
27995
+ themeBoolInfo,
27996
+ cssProp: node.css.property,
27997
+ paramName,
27998
+ info
27999
+ });
28000
+ if (inlineStyleFallback) {
28001
+ if (inlineStyleFallback.type === "splitThemeBooleanWithInlineStyleFallback") {
28002
+ const resolvedRuntimeBranch = inlineStyleFallback.resolvedBranchIsTrue ? "true" : "false";
28003
+ if (runtimeCallBranch === resolvedRuntimeBranch || runtimeCallBranch === "both") return null;
28004
+ }
28005
+ return inlineStyleFallback;
28006
+ }
28007
+ }
27342
28008
  const buildOneSidedVariantResult = (args) => {
27343
28009
  const { cons, alt, alternate, truthyWhen } = args;
27344
28010
  if (!cons || alt || !isEmptyCssBranch(alternate)) return null;
@@ -28057,6 +28723,21 @@ function isDestructuredFromParam(arrowFn, name) {
28057
28723
  return p.key?.type === "Identifier" && p.key.name === name;
28058
28724
  });
28059
28725
  }
28726
+ function isCurrentCurriedHelperContextArg(arg, propsParamName, themeBindingName) {
28727
+ if (!arg || typeof arg !== "object") return false;
28728
+ const node = arg;
28729
+ if (node.type === "Identifier") return node.name === propsParamName || node.name === themeBindingName;
28730
+ if (node.type !== "ObjectExpression" || node.properties?.length !== 1) return false;
28731
+ const property = node.properties[0];
28732
+ if (property.type !== "Property" && property.type !== "ObjectProperty" || property.computed || property.key?.type !== "Identifier" || property.key.name !== "theme") return false;
28733
+ const value = property.value;
28734
+ if (value?.type === "Identifier" && value.name === themeBindingName) return true;
28735
+ if (propsParamName) {
28736
+ const valuePath = getMemberPathFromIdentifier(property.value, propsParamName);
28737
+ return valuePath?.length === 1 && valuePath[0] === "theme";
28738
+ }
28739
+ return false;
28740
+ }
28060
28741
  /**
28061
28742
  * Parses a template literal that contains a simple prop-based ternary expression.
28062
28743
  * Supports patterns like: `background: ${props.$primary ? "red" : "blue"}`
@@ -28105,7 +28786,6 @@ function tryBuildThemeBooleanInlineStyleFallback(args) {
28105
28786
  type: "splitThemeBooleanWithInlineStyleFallback",
28106
28787
  cssProp,
28107
28788
  themeProp: themeBoolInfo.themeProp,
28108
- isNegated: themeBoolInfo.isNegated,
28109
28789
  resolvedValue: resolvedBranchIsTrue ? trueValue : falseValue,
28110
28790
  resolvedImports: resolvedBranchIsTrue ? trueImports : falseImports,
28111
28791
  resolvedBranchIsTrue,
@@ -28488,20 +29168,6 @@ function tryResolveArrowFnCallWithConditionalArgs(node, ctx) {
28488
29168
  };
28489
29169
  }
28490
29170
  /**
28491
- * Extracts a static literal value from an AST node, distinguishing null literals
28492
- * from extraction failure. Returns `undefined` when the node is not a recognized
28493
- * static literal, and the actual value (including `null`) otherwise.
28494
- */
28495
- function extractStaticLiteralValue(node) {
28496
- if (!node || typeof node !== "object") return;
28497
- const type = node.type;
28498
- if (type === "ArrowFunctionExpression" || type === "FunctionExpression") return;
28499
- if (type === "NullLiteral") return null;
28500
- if (type === "Literal" && node.value === null) return null;
28501
- const v = literalToStaticValue(node);
28502
- return v !== null ? v : void 0;
28503
- }
28504
- /**
28505
29171
  * Extracts the prop name from a conditional expression's test node.
28506
29172
  *
28507
29173
  * Supports:
@@ -29704,6 +30370,13 @@ function tryHandleInterpolatedStringValue(args) {
29704
30370
  }
29705
30371
  return true;
29706
30372
  }
30373
+ if (tryHandleTwoValueShorthandLeadingExpression({
30374
+ decl,
30375
+ d,
30376
+ resolveImportedValueExpr,
30377
+ addImport,
30378
+ setValue
30379
+ })) return true;
29707
30380
  const tl = buildInterpolatedTemplate({
29708
30381
  j,
29709
30382
  decl,
@@ -29730,6 +30403,48 @@ function tryHandleInterpolatedStringValue(args) {
29730
30403
  }
29731
30404
  return true;
29732
30405
  }
30406
+ function tryHandleTwoValueShorthandLeadingExpression(args) {
30407
+ const { decl, d, resolveImportedValueExpr, addImport, setValue } = args;
30408
+ const prop = (d.property ?? "").trim();
30409
+ if (prop !== "padding" && prop !== "margin") return false;
30410
+ if (!resolveImportedValueExpr || d.value?.kind !== "interpolated") return false;
30411
+ const parts = d.value.parts ?? [];
30412
+ if (parts.length !== 2 || parts[0]?.kind !== "slot" || parts[1]?.kind !== "static") return false;
30413
+ const slotId = parts[0].slotId;
30414
+ if (slotId === void 0) return false;
30415
+ const suffixMatch = (parts[1].value ?? "").match(/^([a-zA-Z%]+)\s+(.+)$/);
30416
+ if (!suffixMatch) return false;
30417
+ const expr = decl.templateExpressions[slotId];
30418
+ if (!expr || expr.type === "ArrowFunctionExpression") return false;
30419
+ const resolved = resolveImportedValueExpr(expr, {
30420
+ allowCssCalc: true,
30421
+ cssCalcUnit: suffixMatch[1]
30422
+ });
30423
+ if (!resolved || "bail" in resolved || !resolved.skipStaticWrap) return false;
30424
+ const entries = splitDirectionalProperty({
30425
+ prop,
30426
+ rawValue: (d.valueRaw ?? "").trim(),
30427
+ important: d.important,
30428
+ useLogical: getUseLogicalProperties()
30429
+ });
30430
+ if (!entries.length) return false;
30431
+ for (const imp of resolved.imports ?? []) addImport?.(imp);
30432
+ const placeholder = `__SC_EXPR_${slotId}__`;
30433
+ for (const entry of entries) {
30434
+ if (!entry.value.includes(placeholder)) {
30435
+ setValue(entry.prop, normalizeWhitespace(entry.value));
30436
+ continue;
30437
+ }
30438
+ if (resolvedValueCarriesUnit(resolved.resolved)) {
30439
+ setValue(entry.prop, resolved.resolved);
30440
+ continue;
30441
+ }
30442
+ const literalValue = literalToStaticValue(resolved.resolved);
30443
+ if (literalValue === null || typeof literalValue === "boolean") return false;
30444
+ setValue(entry.prop, normalizeWhitespace(entry.value.replace(placeholder, String(literalValue))));
30445
+ }
30446
+ return true;
30447
+ }
29733
30448
  function buildInterpolatedTemplate(args) {
29734
30449
  const { j, decl, cssValue, resolveCallExpr, resolveImportedValueExpr, addImport, multiline } = args;
29735
30450
  if (!cssValue || cssValue.kind !== "interpolated") return null;
@@ -29739,17 +30454,23 @@ function buildInterpolatedTemplate(args) {
29739
30454
  let allStatic = true;
29740
30455
  const quasis = [];
29741
30456
  let q = "";
30457
+ let staticPrefixToConsume = "";
29742
30458
  for (let partIndex = 0; partIndex < parts.length; partIndex++) {
29743
30459
  const part = parts[partIndex];
29744
30460
  if (part.kind === "static") {
29745
- q += part.value;
29746
- fullStaticValue += part.value;
30461
+ const rawValue = part.value ?? "";
30462
+ const value = staticPrefixToConsume && rawValue.startsWith(staticPrefixToConsume) ? rawValue.slice(staticPrefixToConsume.length) : rawValue;
30463
+ staticPrefixToConsume = "";
30464
+ q += value;
30465
+ fullStaticValue += value;
29747
30466
  continue;
29748
30467
  }
29749
30468
  if (part.kind === "slot") {
29750
30469
  const expr = decl.templateExpressions[part.slotId];
29751
30470
  if (!expr || expr.type === "ArrowFunctionExpression") return null;
29752
- if (expr.type === "CallExpression" && resolveCallExpr) {
30471
+ const adjacentUnit = getAdjacentUnitAfterParts(parts, partIndex);
30472
+ const negateResolvedUnit = Boolean(adjacentUnit && q.endsWith("-"));
30473
+ if (expr.type === "CallExpression" && resolveCallExpr && !adjacentUnit) {
29753
30474
  const resolved = resolveCallExpr(expr);
29754
30475
  if (resolved) {
29755
30476
  if (hasAdjacentUnitInParts(parts, partIndex)) return null;
@@ -29760,18 +30481,17 @@ function buildInterpolatedTemplate(args) {
29760
30481
  for (const imp of resolved.imports ?? []) addImport?.(imp);
29761
30482
  continue;
29762
30483
  }
29763
- quasis.push(j.templateElement({
29764
- raw: q,
29765
- cooked: q
29766
- }, false));
29767
- q = "";
29768
30484
  allStatic = false;
29769
30485
  for (const imp of resolved.imports ?? []) addImport?.(imp);
29770
- exprs.push(resolved.resolved);
30486
+ q = appendExpressionToTemplate(j, quasis, exprs, q, resolved.resolved);
29771
30487
  continue;
29772
30488
  }
29773
30489
  }
29774
- const importedResolved = resolveImportedValueExpr?.(expr);
30490
+ const importedResolved = resolveImportedValueExpr?.(expr, adjacentUnit ? {
30491
+ allowCssCalc: true,
30492
+ cssCalcUnit: adjacentUnit,
30493
+ negate: negateResolvedUnit
30494
+ } : void 0);
29775
30495
  if (importedResolved) {
29776
30496
  if ("bail" in importedResolved) return null;
29777
30497
  const resolved = importedResolved;
@@ -29779,7 +30499,13 @@ function buildInterpolatedTemplate(args) {
29779
30499
  for (const imp of resolved.imports ?? []) addImport?.(imp);
29780
30500
  return resolved.resolved;
29781
30501
  }
29782
- if (hasAdjacentUnitInParts(parts, partIndex) && !hasSingleSlotUnitSuffix(cssValue)) return null;
30502
+ if (hasAdjacentUnitInParts(parts, partIndex) && !hasSingleSlotUnitSuffix(cssValue)) {
30503
+ if (!adjacentUnit || !resolved.skipStaticWrap) return null;
30504
+ if (resolvedValueCarriesUnit(resolved.resolved)) {
30505
+ staticPrefixToConsume = adjacentUnit;
30506
+ if (negateResolvedUnit) q = q.slice(0, -1);
30507
+ }
30508
+ }
29783
30509
  if (resolved.resolved?.type === "StringLiteral" || resolved.resolved?.type === "Literal" && typeof resolved.resolved.value === "string") {
29784
30510
  const strValue = resolved.resolved.value;
29785
30511
  q += strValue;
@@ -29787,14 +30513,9 @@ function buildInterpolatedTemplate(args) {
29787
30513
  for (const imp of resolved.imports ?? []) addImport?.(imp);
29788
30514
  continue;
29789
30515
  }
29790
- quasis.push(j.templateElement({
29791
- raw: q,
29792
- cooked: q
29793
- }, false));
29794
- q = "";
29795
30516
  allStatic = false;
29796
30517
  for (const imp of resolved.imports ?? []) addImport?.(imp);
29797
- exprs.push(resolved.resolved);
30518
+ q = appendExpressionToTemplate(j, quasis, exprs, q, resolved.resolved);
29798
30519
  continue;
29799
30520
  }
29800
30521
  const literalValue = literalToStaticValue(expr);
@@ -29827,6 +30548,39 @@ function buildInterpolatedTemplate(args) {
29827
30548
  stylisValueRaw: multiline.stylisValueRaw
29828
30549
  });
29829
30550
  }
30551
+ function resolvedValueCarriesUnit(node) {
30552
+ if (!node || typeof node !== "object") return false;
30553
+ if (node.type === "NumericLiteral" || node.type === "Literal" && typeof node.value === "number") return false;
30554
+ if (node.type === "StringLiteral" || node.type === "Literal" && typeof node.value === "string") return /[a-zA-Z%]$/.test(String(node.value));
30555
+ return true;
30556
+ }
30557
+ const CSS_UNIT_PATTERN = /^(?:px|rem|em|ex|ch|cap|ic|lh|rlh|vw|vh|vi|vb|vmin|vmax|svw|svh|lvw|lvh|dvw|dvh|cqw|cqh|cqi|cqb|cqmin|cqmax|cm|mm|q|in|pt|pc|fr|%)$/i;
30558
+ function getAdjacentUnitAfterParts(parts, slotIndex) {
30559
+ const candidate = (parts[slotIndex + 1]?.kind === "static" ? parts[slotIndex + 1]?.value ?? "" : "").match(/^([a-zA-Z%]+)/)?.[1];
30560
+ return candidate && CSS_UNIT_PATTERN.test(candidate) ? candidate : null;
30561
+ }
30562
+ function appendExpressionToTemplate(j, quasis, expressions, currentQuasi, expression) {
30563
+ if (expression?.type !== "TemplateLiteral") {
30564
+ quasis.push(j.templateElement({
30565
+ raw: currentQuasi,
30566
+ cooked: currentQuasi
30567
+ }, false));
30568
+ expressions.push(expression);
30569
+ return "";
30570
+ }
30571
+ const nestedQuasis = expression.quasis ?? [];
30572
+ const nestedExpressions = expression.expressions ?? [];
30573
+ currentQuasi += nestedQuasis[0]?.value?.raw ?? nestedQuasis[0]?.value?.cooked ?? "";
30574
+ for (let index = 0; index < nestedExpressions.length; index++) {
30575
+ quasis.push(j.templateElement({
30576
+ raw: currentQuasi,
30577
+ cooked: currentQuasi
30578
+ }, false));
30579
+ expressions.push(nestedExpressions[index]);
30580
+ currentQuasi = nestedQuasis[index + 1]?.value?.raw ?? nestedQuasis[index + 1]?.value?.cooked ?? "";
30581
+ }
30582
+ return currentQuasi;
30583
+ }
29830
30584
  function hasAdjacentUnitInParts(parts, slotIndex) {
29831
30585
  const before = parts[slotIndex - 1]?.kind === "static" ? parts[slotIndex - 1]?.value ?? "" : "";
29832
30586
  const after = parts[slotIndex + 1]?.kind === "static" ? parts[slotIndex + 1]?.value ?? "" : "";
@@ -37339,10 +38093,11 @@ function tryHandleInterpolatedBorder(ctx, args) {
37339
38093
  {
37340
38094
  const slotIndices = [];
37341
38095
  for (let i = 0; i < tokens.length; i++) {
37342
- const m = tokens[i].match(/^__SC_EXPR_(\d+)__$/);
38096
+ const m = tokens[i].match(/^__SC_EXPR_(\d+)__(?:([a-zA-Z%]+))?$/);
37343
38097
  if (m?.[1]) slotIndices.push({
37344
38098
  idx: i,
37345
- slotId: Number(m[1])
38099
+ slotId: Number(m[1]),
38100
+ ...m[2] ? { unit: m[2] } : {}
37346
38101
  });
37347
38102
  }
37348
38103
  if (slotIndices.length === 2 && tokens.length === 3) {
@@ -37370,7 +38125,7 @@ function tryHandleInterpolatedBorder(ctx, args) {
37370
38125
  return true;
37371
38126
  }
37372
38127
  const shouldSwap = slot0Role === "color" || slot1Role === "width";
37373
- const widthAst = shouldSwap ? slot1Ast : slot0Ast;
38128
+ const widthAst = withBorderWidthUnit(shouldSwap ? slot1Ast : slot0Ast, shouldSwap ? slot1.unit : slot0.unit);
37374
38129
  const colorAst = shouldSwap ? slot0Ast : slot1Ast;
37375
38130
  applyResolvedPropValue(widthProp, widthAst);
37376
38131
  applyResolvedPropValue(styleProp, middleStyle);
@@ -37737,6 +38492,16 @@ function classifyBorderSlotRole(ast) {
37737
38492
  if ((node.type === "StringLiteral" || node.type === "Literal") && typeof node.value === "string") return looksLikeLength(node.value) ? "width" : "color";
37738
38493
  return null;
37739
38494
  }
38495
+ function withBorderWidthUnit(expr, unit) {
38496
+ if (!unit) return expr;
38497
+ const staticValue = literalToStaticValue(expr);
38498
+ if (typeof staticValue === "number") return `${staticValue}${unit}`;
38499
+ if (typeof staticValue === "string" && looksLikeLength(staticValue)) {
38500
+ const trimmed = staticValue.trim();
38501
+ return /[a-zA-Z%]$/.test(trimmed) || Number.parseFloat(trimmed) === 0 ? staticValue : `${staticValue}${unit}`;
38502
+ }
38503
+ return expr;
38504
+ }
37740
38505
  function hasConflictingEarlierVariant(variantBuckets, borderEntries) {
37741
38506
  const borderProps = borderEntries.map(([prop]) => prop);
37742
38507
  return variantBuckets.some((bucket) => Object.keys(bucket).some((variantProp) => borderProps.some((borderProp) => borderLonghandsConflict(variantProp, borderProp))));
@@ -37757,6 +38522,61 @@ function parseBorderLonghand(prop) {
37757
38522
  };
37758
38523
  }
37759
38524
  //#endregion
38525
+ //#region src/internal/lower-rules/important-values.ts
38526
+ function appendImportantToStyleValue(j, valueAst, important) {
38527
+ if (!important) return valueAst;
38528
+ if (typeof valueAst === "string") return valueAst.includes("!important") ? valueAst : `${valueAst} !important`;
38529
+ if (typeof valueAst === "number") return `${valueAst} !important`;
38530
+ if (!valueAst || typeof valueAst !== "object") return valueAst;
38531
+ const node = valueAst;
38532
+ if (node.type === "ExpressionStatement") return appendImportantToStyleValue(j, node.expression, important);
38533
+ if (node.type === "StringLiteral" || node.type === "Literal" || node.type === "NumericLiteral") {
38534
+ if (typeof node.value === "string") return node.value.includes("!important") ? valueAst : j.literal(`${node.value} !important`);
38535
+ if (typeof node.value === "number") return j.literal(`${node.value} !important`);
38536
+ return valueAst;
38537
+ }
38538
+ if (node.type === "TemplateLiteral" && Array.isArray(node.quasis)) return appendImportantToTemplateLiteral(j, node.quasis, node.expressions, valueAst);
38539
+ return j.templateLiteral([j.templateElement({
38540
+ raw: "",
38541
+ cooked: ""
38542
+ }, false), j.templateElement({
38543
+ raw: " !important",
38544
+ cooked: " !important"
38545
+ }, true)], [valueAst]);
38546
+ }
38547
+ function cssValueIsImportant(value) {
38548
+ if (typeof value === "string") return value.includes("!important");
38549
+ if (!value || typeof value !== "object") return false;
38550
+ const node = value;
38551
+ if (node.type === "ExpressionStatement") return cssValueIsImportant(node.expression);
38552
+ if ((node.type === "StringLiteral" || node.type === "Literal") && typeof node.value === "string") return node.value.includes("!important");
38553
+ if (node.type === "TemplateLiteral" && Array.isArray(node.quasis)) return node.quasis.some((q) => {
38554
+ const raw = q?.value?.raw ?? "";
38555
+ const cooked = q?.value?.cooked ?? "";
38556
+ return raw.includes("!important") || cooked.includes("!important");
38557
+ });
38558
+ return false;
38559
+ }
38560
+ function appendImportantToTemplateLiteral(j, quasis, expressions, originalValue) {
38561
+ const lastIndex = quasis.length - 1;
38562
+ const last = quasis[lastIndex];
38563
+ const lastRaw = last?.value?.raw ?? last?.value?.cooked ?? "";
38564
+ const lastCooked = last?.value?.cooked ?? last?.value?.raw ?? "";
38565
+ if (lastRaw.includes("!important") || lastCooked.includes("!important")) return originalValue;
38566
+ const importantQuasis = quasis.map((quasi, i) => {
38567
+ const raw = quasi?.value?.raw ?? quasi?.value?.cooked ?? "";
38568
+ const cooked = quasi?.value?.cooked ?? quasi?.value?.raw ?? "";
38569
+ return i === lastIndex ? j.templateElement({
38570
+ raw: `${raw} !important`,
38571
+ cooked: `${cooked} !important`
38572
+ }, true) : j.templateElement({
38573
+ raw,
38574
+ cooked
38575
+ }, false);
38576
+ });
38577
+ return j.templateLiteral(importantQuasis, expressions ?? []);
38578
+ }
38579
+ //#endregion
37760
38580
  //#region src/internal/lower-rules/interpolated-variant-resolvers.ts
37761
38581
  function handleSplitVariantsResolvedValue(ctx) {
37762
38582
  const { j, decl, d, res, styleObj, variantBuckets, variantStyleKeys, pseudos, media, resolvedSelectorMedia, parseExpr, resolverImports, warnings, setBail, bailUnsupported } = ctx;
@@ -37874,39 +38694,8 @@ function handleSplitVariantsResolvedValue(ctx) {
37874
38694
  target[prop] = map;
37875
38695
  return map;
37876
38696
  };
37877
- const withImportant = (valueAst) => {
37878
- if (!d.important || !valueAst || typeof valueAst !== "object") return valueAst;
37879
- const node = valueAst;
37880
- if (node.type === "StringLiteral" || node.type === "Literal" || node.type === "NumericLiteral") {
37881
- if (typeof node.value === "string") return node.value.includes("!important") ? valueAst : j.literal(`${node.value} !important`);
37882
- if (typeof node.value === "number") return j.literal(`${node.value} !important`);
37883
- return valueAst;
37884
- }
37885
- if (node.type === "TemplateLiteral" && Array.isArray(node.quasis)) {
37886
- const quasis = node.quasis;
37887
- const lastIndex = quasis.length - 1;
37888
- const last = quasis[lastIndex];
37889
- const lastText = last?.value?.cooked ?? last?.value?.raw ?? "";
37890
- if (lastText.includes("!important")) return valueAst;
37891
- const newQuasis = quasis.map((q, i) => i === lastIndex ? j.templateElement({
37892
- raw: `${lastText} !important`,
37893
- cooked: `${lastText} !important`
37894
- }, true) : j.templateElement({
37895
- raw: q?.value?.raw ?? q?.value?.cooked ?? "",
37896
- cooked: q?.value?.cooked ?? q?.value?.raw ?? ""
37897
- }, false));
37898
- return j.templateLiteral(newQuasis, node.expressions ?? []);
37899
- }
37900
- return j.templateLiteral([j.templateElement({
37901
- raw: "",
37902
- cooked: ""
37903
- }, false), j.templateElement({
37904
- raw: " !important",
37905
- cooked: " !important"
37906
- }, true)], [valueAst]);
37907
- };
37908
38697
  const applyWithContext = (prop, valueAstRaw) => {
37909
- const valueAst = withImportant(valueAstRaw);
38698
+ const valueAst = appendImportantToStyleValue(j, valueAstRaw, d.important);
37910
38699
  if (media) {
37911
38700
  const map = getOrCreateConditionMap(prop);
37912
38701
  map[media] = valueAst;
@@ -38496,7 +39285,7 @@ function emitPseudoMediaStyleFnFromProps(args) {
38496
39285
  //#endregion
38497
39286
  //#region src/internal/lower-rules/rule-interpolated-declaration.ts
38498
39287
  function handleInterpolatedDeclaration(args) {
38499
- const { ctx, rule, allRules, d, media, pseudos, pseudoElement, attrTarget, resolvedSelectorMedia, applyResolvedPropValue } = args;
39288
+ const { ctx, rule, allRules, d, media, pseudos, pseudoElement, attrTarget, resolvedSelectorMedia, hasAncestorAttributeScope, applyResolvedPropValue } = args;
38500
39289
  const { state, decl, styleObj, perPropPseudo, variantBuckets, variantStyleKeys, variantSourceOrder, observedVariantFallbackFns, extraStyleObjects, styleFnFromProps, styleFnDecls, inlineStyleProps, cssHelperPropValues, tryHandleMappedFunctionColor, tryHandleLogicalOrDefault, tryHandleConditionalPropCoalesceWithTheme, tryHandleEnumIfChainValue, tryHandleThemeIndexedLookup, handlerContext, componentInfo, tryHandlePropertyTernaryTemplateLiteral, tryHandleCssHelperFunctionSwitchBlock, tryHandleCssHelperConditionalBlock, findJsxPropTsType, findJsxPropTsTypeForVariantExtraction, annotateParamFromJsxProp, isJsxPropOptional, applyVariant, getBaseStyleTarget, notifyResolvedStylesArg } = ctx;
38501
39290
  const hasStaticPropsBeforeResolvedStylesArg = () => Object.keys(styleObj).length > 0 || getBaseStyleTarget() !== styleObj;
38502
39291
  const annotateScalarParams = (params, propNames) => {
@@ -38508,7 +39297,7 @@ function handleInterpolatedDeclaration(args) {
38508
39297
  if (isJsxPropOptional(propName)) addUndefinedToParamType(j, param);
38509
39298
  });
38510
39299
  };
38511
- const { api, j, filePath, warnings, resolverImports, keyframesNames, parseExpr, resolveValue, resolveCall, importMap, cssHelperNames, cssHelperObjectMembers, declByLocalName, cssHelperValuesByKey, staticPropertyValues, warnPropInlineStyle, applyCssHelperMixin, hasLocalThemeBinding, resolveThemeValue, resolveThemeValueFromFn, getOrCreateLocalStylexVar, resolveImportInScope, resolveImportForExpr } = state;
39300
+ const { api, j, filePath, warnings, resolverImports, keyframesNames, parseExpr, resolveValue, resolveCall, importMap, cssHelperNames, cssHelperObjectMembers, declByLocalName, cssHelperValuesByKey, staticPropertyValues, staticIdentifierValues, warnPropInlineStyle, applyCssHelperMixin, hasLocalThemeBinding, resolveThemeValue, resolveThemeValueFromFn, getOrCreateLocalStylexVar, resolveImportInScope, resolveImportForExpr } = state;
38512
39301
  const avoidNames = new Set(importMap.keys());
38513
39302
  if (state.bail) return;
38514
39303
  if (d.value.kind !== "interpolated") return;
@@ -38856,7 +39645,7 @@ function handleInterpolatedDeclaration(args) {
38856
39645
  return (observedNumericCssTextProps.has(jsxProp) || isNumberLikeTsType(findJsxPropTsType(jsxProp))) && getNumericCssEmissionMode(stylexProp) === "cssText";
38857
39646
  };
38858
39647
  const maybeEmitPreservedRuntimeCallOverride = (args) => {
38859
- const { resolveCallResult, originalExpr, loc } = args;
39648
+ const { resolveCallResult, originalExpr, loc, cssValueText } = args;
38860
39649
  if (!resolveCallResult || !("preserveRuntimeCall" in resolveCallResult) || !resolveCallResult.preserveRuntimeCall) return "not-requested";
38861
39650
  if (!d.property) {
38862
39651
  warnings.push({
@@ -38900,7 +39689,17 @@ function handleInterpolatedDeclaration(args) {
38900
39689
  const effectiveSuffix = d.important ? `${suffix} !important` : suffix;
38901
39690
  const runtimeCallArg = prefix || effectiveSuffix ? buildTemplateWithStaticParts(j, baseRuntimeExpr, prefix, effectiveSuffix) : baseRuntimeExpr;
38902
39691
  if (runtimeExprNeedsTheme) markDeclNeedsUseThemeHook(decl);
38903
- const outs = cssDeclarationToStylexDeclarations(d);
39692
+ const runtimeBackgroundProp = d.property === "background" ? resolveRuntimeBackgroundStylexProp(baseRuntimeExpr, cssValueText) : null;
39693
+ if (runtimeBackgroundProp === "unsupported") {
39694
+ warnings.push({
39695
+ severity: "error",
39696
+ type: "Arrow function: helper call body is not supported",
39697
+ loc
39698
+ });
39699
+ bail = true;
39700
+ return "failed";
39701
+ }
39702
+ const outs = runtimeBackgroundProp ? [{ prop: runtimeBackgroundProp }] : cssDeclarationToStylexDeclarations(d);
38904
39703
  if (outs.length !== 1 || !outs[0]?.prop) {
38905
39704
  warnings.push({
38906
39705
  severity: "error",
@@ -38910,21 +39709,38 @@ function handleInterpolatedDeclaration(args) {
38910
39709
  bail = true;
38911
39710
  return "failed";
38912
39711
  }
38913
- const out = outs[0];
38914
- const fnKey = styleKeyWithSuffix(decl.styleKey, out.prop);
38915
- if (!styleFnDecls.has(fnKey)) {
38916
- const outParamName = cssPropertyToIdentifier(out.prop, avoidNames);
38917
- const param = j.identifier(outParamName);
38918
- if (/\.(ts|tsx)$/.test(filePath)) param.typeAnnotation = j.tsTypeAnnotation(j.tsStringKeyword());
38919
- const body = j.objectExpression([makeCssProperty(j, out.prop, outParamName)]);
38920
- styleFnDecls.set(fnKey, j.arrowFunctionExpression([param], body));
39712
+ const runtimeProp = outs[0].prop;
39713
+ const runtimeStyle = { [runtimeProp]: runtimeCallArg };
39714
+ if (runtimeBackgroundProp) applyBackgroundShorthandLayerReset(j, runtimeStyle, runtimeBackgroundProp, d.important);
39715
+ if (!subtractLaterStaticOverrides({
39716
+ rule,
39717
+ allRules,
39718
+ currentDecl: d,
39719
+ branchStyles: [runtimeStyle],
39720
+ ignoreUnsafeOverlaps: true
39721
+ })) {
39722
+ warnings.push({
39723
+ severity: "error",
39724
+ type: "Arrow function: helper call body is not supported",
39725
+ loc
39726
+ });
39727
+ bail = true;
39728
+ return "failed";
38921
39729
  }
39730
+ if (Object.keys(runtimeStyle).length === 0) return "suppressed";
39731
+ const fnKey = styleKeyWithSuffix(decl.styleKey, runtimeProp);
39732
+ const outParamName = cssPropertyToIdentifier(runtimeProp, avoidNames);
39733
+ const param = j.identifier(outParamName);
39734
+ if (/\.(ts|tsx)$/.test(filePath)) param.typeAnnotation = j.tsTypeAnnotation(j.tsStringKeyword());
39735
+ const body = j.objectExpression(Object.entries(runtimeStyle).map(([prop, value]) => prop === runtimeProp ? makeCssProperty(j, runtimeProp, outParamName) : j.property("init", makeCssPropKey(j, prop), cloneAstNode(value))));
39736
+ styleFnDecls.set(fnKey, j.arrowFunctionExpression([param], body));
38922
39737
  const existingIdx = styleFnFromProps.findIndex((entry) => entry.fnKey === fnKey && entry.jsxProp === "__props" && entry.condition === "always");
38923
39738
  const newEntry = {
38924
39739
  fnKey,
38925
39740
  jsxProp: "__props",
38926
39741
  condition: "always",
38927
- callArg: cloneAstNode(runtimeCallArg)
39742
+ callArg: cloneAstNode(runtimeCallArg),
39743
+ sourceOrder: ctx.allocateSourceOrder()
38928
39744
  };
38929
39745
  if (existingIdx >= 0) styleFnFromProps[existingIdx] = newEntry;
38930
39746
  else styleFnFromProps.push(newEntry);
@@ -39057,7 +39873,10 @@ function handleInterpolatedDeclaration(args) {
39057
39873
  return null;
39058
39874
  };
39059
39875
  const allowCssCalcForImportedArithmetic = isEntireInterpolatedValueSingleSlot(d, decl);
39060
- const resolveImportedValueExpr = (expr, allowCssCalc = allowCssCalcForImportedArithmetic) => {
39876
+ const resolveImportedValueExpr = (expr, options = allowCssCalcForImportedArithmetic) => {
39877
+ const allowCssCalc = typeof options === "boolean" ? options : options.allowCssCalc ?? false;
39878
+ const cssCalcUnit = typeof options === "boolean" ? void 0 : options.cssCalcUnit;
39879
+ const forceNegate = typeof options === "boolean" ? false : options.negate === true;
39061
39880
  const resolveChildExpression = (child) => resolveImportedValueExpr(child, false);
39062
39881
  const isBailResolution = (result) => Boolean(result && "bail" in result);
39063
39882
  const resolvedOrOriginal = (result, original) => result && !isBailResolution(result) ? result.resolved : original;
@@ -39094,7 +39913,9 @@ function handleInterpolatedDeclaration(args) {
39094
39913
  prefix: "",
39095
39914
  suffix: ""
39096
39915
  };
39097
- if (staticParts.prefix) {
39916
+ const calcUnit = cssCalcUnit ?? staticParts.suffix;
39917
+ const hasNegativePrefix = !cssCalcUnit && staticParts.prefix === "-" && /^-?(?:[a-zA-Z%]+)$/.test(staticParts.suffix) && (expr.operator === "+" || expr.operator === "-");
39918
+ if (staticParts.prefix && !hasNegativePrefix && !cssCalcUnit) {
39098
39919
  warnings.push({
39099
39920
  severity: "warning",
39100
39921
  type: "Unsupported interpolation: call expression",
@@ -39106,7 +39927,9 @@ function handleInterpolatedDeclaration(args) {
39106
39927
  const calcExpr = buildCssCalcTemplateExpression({
39107
39928
  j,
39108
39929
  operator: expr.operator,
39109
- unit: expr.operator === "+" || expr.operator === "-" ? staticParts.suffix : "",
39930
+ unit: expr.operator === "+" || expr.operator === "-" ? calcUnit : "",
39931
+ negate: forceNegate || hasNegativePrefix,
39932
+ staticIdentifierValues,
39110
39933
  left: {
39111
39934
  node: resolvedLeft,
39112
39935
  allowExpression: Boolean(leftResult)
@@ -39119,9 +39942,9 @@ function handleInterpolatedDeclaration(args) {
39119
39942
  if (calcExpr) return {
39120
39943
  resolved: calcExpr,
39121
39944
  imports,
39122
- skipStaticWrap: staticParts.suffix !== ""
39945
+ skipStaticWrap: calcUnit !== ""
39123
39946
  };
39124
- if (staticParts.suffix && imports.length > 0) return bailResolvedUnitExpression(expr);
39947
+ if (calcUnit && imports.length > 0) return bailResolvedUnitExpression(expr);
39125
39948
  }
39126
39949
  return {
39127
39950
  resolved: j.binaryExpression(expr.operator, resolvedLeft, resolvedRight),
@@ -39229,7 +40052,25 @@ function handleInterpolatedDeclaration(args) {
39229
40052
  const imp = calleeInfo ? resolveImportInScope(calleeInfo.rootName, calleeInfo.rootNode) : null;
39230
40053
  if (!imp) return null;
39231
40054
  const resolvedCall = resolveCallExpr(expr);
39232
- if (resolvedCall) return resolvedCall;
40055
+ if (resolvedCall) {
40056
+ if (!cssCalcUnit) return resolvedCall;
40057
+ const literalValue = literalToStaticValue(resolvedCall.resolved);
40058
+ const numericLiteral = typeof literalValue === "number" ? literalValue : typeof literalValue === "string" && literalValue.trim() !== "" && Number.isFinite(Number(literalValue)) ? Number(literalValue) : null;
40059
+ if (numericLiteral !== null) return {
40060
+ resolved: j.literal(`${numericLiteral}${cssCalcUnit}`),
40061
+ imports: resolvedCall.imports,
40062
+ skipStaticWrap: true
40063
+ };
40064
+ if (forceNegate) return {
40065
+ resolved: buildNegatedCssTokenTemplate(j, resolvedCall.resolved),
40066
+ imports: resolvedCall.imports,
40067
+ skipStaticWrap: true
40068
+ };
40069
+ return {
40070
+ ...resolvedCall,
40071
+ skipStaticWrap: true
40072
+ };
40073
+ }
39233
40074
  warnings.push({
39234
40075
  severity: "warning",
39235
40076
  type: "Adapter resolveCall returned undefined for helper call",
@@ -39623,6 +40464,10 @@ function handleInterpolatedDeclaration(args) {
39623
40464
  bail = true;
39624
40465
  break;
39625
40466
  }
40467
+ if (hasSourceOrderedThemeStyleOverlap(decl, extraStyleObjects, res.cssText)) {
40468
+ bail = true;
40469
+ continue;
40470
+ }
39626
40471
  addResolverImports(res.imports);
39627
40472
  const exprAst = parseExpr(res.expr);
39628
40473
  if (!exprAst) {
@@ -39708,7 +40553,9 @@ function handleInterpolatedDeclaration(args) {
39708
40553
  addResolverImports(res.imports);
39709
40554
  const { prefix, suffix } = extractStaticPartsForDecl(d);
39710
40555
  const effectiveSuffix = d.important ? `${suffix} !important` : suffix;
39711
- const exprAst = parseExpr(wrapExprWithStaticParts(res.expr, prefix, effectiveSuffix));
40556
+ const wrappedExpr = wrapExprWithStaticParts(res.expr, prefix, effectiveSuffix);
40557
+ const cssValueTextForClassification = prefix || effectiveSuffix ? wrappedExpr : res.cssValueText;
40558
+ const exprAst = parseExpr(wrappedExpr);
39712
40559
  if (!exprAst) {
39713
40560
  const resolveCallMeta = res.resolveCallContext && res.resolveCallResult ? {
39714
40561
  resolveCallContext: res.resolveCallContext,
@@ -39730,7 +40577,7 @@ function handleInterpolatedDeclaration(args) {
39730
40577
  bail = true;
39731
40578
  break;
39732
40579
  }
39733
- const outs = cssDeclarationToStylexDeclarations(d);
40580
+ const outs = d.property === "background" && cssValueTextForClassification ? [{ prop: resolveBackgroundStylexProp(cssValueTextForClassification) }] : cssDeclarationToStylexDeclarations(d);
39734
40581
  for (let i = 0; i < outs.length; i++) {
39735
40582
  const out = outs[i];
39736
40583
  const commentSource = i === 0 ? {
@@ -39738,12 +40585,13 @@ function handleInterpolatedDeclaration(args) {
39738
40585
  leadingLine: d.leadingLineComment,
39739
40586
  trailingLine: d.trailingLineComment
39740
40587
  } : null;
39741
- applyResolvedPropValue(out.prop, exprAst, commentSource);
40588
+ applyResolvedPropValue(out.prop, exprAst, commentSource, d.property);
39742
40589
  }
39743
40590
  if (maybeEmitPreservedRuntimeCallOverride({
39744
40591
  resolveCallResult: res.resolveCallResult,
39745
40592
  originalExpr: expr,
39746
- loc
40593
+ loc,
40594
+ cssValueText: cssValueTextForClassification
39747
40595
  }) === "failed") break;
39748
40596
  continue;
39749
40597
  }
@@ -39751,43 +40599,89 @@ function handleInterpolatedDeclaration(args) {
39751
40599
  if (maybeEmitPreservedRuntimeCallOverride({
39752
40600
  resolveCallResult: res.resolveCallResult,
39753
40601
  originalExpr: expr,
39754
- loc
40602
+ loc,
40603
+ cssValueText: res.cssValueText
39755
40604
  }) === "failed") break;
39756
40605
  continue;
39757
40606
  }
39758
40607
  if (res && res.type === "splitThemeBooleanVariants") {
40608
+ if (pseudos?.length || media || pseudoElement || attrTarget || resolvedSelectorMedia || hasAncestorAttributeScope) {
40609
+ bail = true;
40610
+ continue;
40611
+ }
39759
40612
  addResolverImports(res.trueImports);
39760
40613
  addResolverImports(res.falseImports);
39761
- const { trueKey: trueStyleKey, falseKey: falseStyleKey } = buildThemeStyleKeys(decl.styleKey, res.themeProp);
39762
- if (!decl.needsUseThemeHook) decl.needsUseThemeHook = [];
39763
- let entry = decl.needsUseThemeHook.find((e) => e.themeProp === res.themeProp);
39764
- if (!entry) {
39765
- entry = {
39766
- themeProp: res.themeProp,
39767
- trueStyleKey,
39768
- falseStyleKey
39769
- };
39770
- decl.needsUseThemeHook.push(entry);
39771
- extraStyleObjects.set(trueStyleKey, {});
39772
- extraStyleObjects.set(falseStyleKey, {});
39773
- }
39774
- const trueStyle = extraStyleObjects.get(trueStyleKey) ?? {};
39775
- const falseStyle = extraStyleObjects.get(falseStyleKey) ?? {};
39776
- if (!applyThemeBooleanValue(j, res.cssProp, res.trueValue, trueStyle)) {
40614
+ const trueStyle = {};
40615
+ const falseStyle = {};
40616
+ if (!applyThemeBooleanValue(j, res.cssProp, res.trueValue, trueStyle, d.important, res.trueCssValueText)) {
39777
40617
  bail = true;
39778
40618
  continue;
39779
40619
  }
39780
- if (!applyThemeBooleanValue(j, res.cssProp, res.falseValue, falseStyle)) {
40620
+ if (!applyThemeBooleanValue(j, res.cssProp, res.falseValue, falseStyle, d.important, res.falseCssValueText)) {
39781
40621
  bail = true;
39782
40622
  continue;
39783
40623
  }
39784
- extraStyleObjects.set(trueStyleKey, trueStyle);
39785
- extraStyleObjects.set(falseStyleKey, falseStyle);
40624
+ const { trueKey: baseTrueStyleKey, falseKey: baseFalseStyleKey } = buildThemeStyleKeys(decl.styleKey, res.themeProp);
40625
+ if (!decl.needsUseThemeHook) decl.needsUseThemeHook = [];
40626
+ const latestSourceOrder = getLatestThemeInterleavableSourceOrder({
40627
+ decl,
40628
+ variantSourceOrder,
40629
+ styleFnFromProps
40630
+ });
40631
+ const matchingThemeEntries = decl.needsUseThemeHook.filter((entry) => entry.themeProp === res.themeProp && (entry.trueStyleKey || entry.falseStyleKey));
40632
+ let reusableEntry = null;
40633
+ for (let i = matchingThemeEntries.length - 1; i >= 0; i--) {
40634
+ const entry = matchingThemeEntries[i];
40635
+ if (entry.sourceOrder !== void 0 && entry.sourceOrder === latestSourceOrder) {
40636
+ reusableEntry = entry;
40637
+ break;
40638
+ }
40639
+ }
40640
+ const mergeExtraStyleObject = (styleKey, style) => {
40641
+ const existing = extraStyleObjects.get(styleKey);
40642
+ if (!existing) {
40643
+ extraStyleObjects.set(styleKey, style);
40644
+ return;
40645
+ }
40646
+ const merged = { ...existing };
40647
+ for (const [prop, value] of Object.entries(style)) {
40648
+ if (Object.hasOwn(merged, prop) && cssValueIsImportant(merged[prop]) && !cssValueIsImportant(value)) continue;
40649
+ merged[prop] = value;
40650
+ }
40651
+ extraStyleObjects.set(styleKey, merged);
40652
+ };
40653
+ if (reusableEntry) {
40654
+ const restoredTrueStyleKey = reusableEntry.trueStyleKey ?? restoreThemeStyleKeyFromPairedSide(baseTrueStyleKey, baseFalseStyleKey, reusableEntry.falseStyleKey);
40655
+ const restoredFalseStyleKey = reusableEntry.falseStyleKey ?? restoreThemeStyleKeyFromPairedSide(baseFalseStyleKey, baseTrueStyleKey, reusableEntry.trueStyleKey);
40656
+ reusableEntry.trueStyleKey = restoredTrueStyleKey;
40657
+ reusableEntry.falseStyleKey = restoredFalseStyleKey;
40658
+ mergeExtraStyleObject(restoredTrueStyleKey, trueStyle);
40659
+ mergeExtraStyleObject(restoredFalseStyleKey, falseStyle);
40660
+ } else {
40661
+ const sourceOrder = ctx.allocateSourceOrder();
40662
+ const hasExistingStyleBucketForThemeProp = matchingThemeEntries.length > 0;
40663
+ const trueStyleKey = hasExistingStyleBucketForThemeProp ? styleKeyWithSuffix(baseTrueStyleKey, `theme${sourceOrder}`) : baseTrueStyleKey;
40664
+ const falseStyleKey = hasExistingStyleBucketForThemeProp ? styleKeyWithSuffix(baseFalseStyleKey, `theme${sourceOrder}`) : baseFalseStyleKey;
40665
+ decl.needsUseThemeHook.push({
40666
+ themeProp: res.themeProp,
40667
+ trueStyleKey,
40668
+ falseStyleKey,
40669
+ sourceOrder
40670
+ });
40671
+ extraStyleObjects.set(trueStyleKey, trueStyle);
40672
+ extraStyleObjects.set(falseStyleKey, falseStyle);
40673
+ }
40674
+ if (maybeEmitPreservedRuntimeCallOverride({
40675
+ resolveCallResult: res.runtimeResolveCallResult,
40676
+ originalExpr: expr,
40677
+ loc,
40678
+ cssValueText: res.runtimeCssValueText
40679
+ }) === "failed") break;
39786
40680
  decl.needsWrapperComponent = true;
39787
40681
  continue;
39788
40682
  }
39789
40683
  if (res && res.type === "splitThemeBooleanWithInlineStyleFallback") {
39790
- if (pseudos?.length || media || pseudoElement) {
40684
+ if (pseudos?.length || media || pseudoElement || attrTarget || resolvedSelectorMedia || hasAncestorAttributeScope) {
39791
40685
  bail = true;
39792
40686
  continue;
39793
40687
  }
@@ -39795,9 +40689,14 @@ function handleInterpolatedDeclaration(args) {
39795
40689
  bail = true;
39796
40690
  continue;
39797
40691
  }
40692
+ const stylexDeclarations = cssDeclarationToStylexDeclarations(d);
40693
+ if (hasLaterDeclarationForStylexProps(d, allRules, new Set(stylexDeclarations.map((out) => out.prop).filter(Boolean)))) {
40694
+ bail = true;
40695
+ continue;
40696
+ }
39798
40697
  addResolverImports(res.resolvedImports);
39799
40698
  if (!decl.needsUseThemeHook) decl.needsUseThemeHook = [];
39800
- if (!decl.needsUseThemeHook.some((e) => e.themeProp === res.themeProp)) decl.needsUseThemeHook.push({
40699
+ if (!decl.needsUseThemeHook.some((e) => e.themeProp === res.themeProp && e.trueStyleKey === null && e.falseStyleKey === null)) decl.needsUseThemeHook.push({
39801
40700
  themeProp: res.themeProp,
39802
40701
  trueStyleKey: null,
39803
40702
  falseStyleKey: null
@@ -39805,8 +40704,8 @@ function handleInterpolatedDeclaration(args) {
39805
40704
  const themeCondition = j.memberExpression(j.identifier("theme"), j.identifier(res.themeProp));
39806
40705
  const undefinedExpr = j.identifier("undefined");
39807
40706
  const inlineExpr = res.inlineExpr;
39808
- const conditionalExpr = !res.resolvedBranchIsTrue !== res.isNegated ? j.conditionalExpression(themeCondition, inlineExpr, undefinedExpr) : j.conditionalExpression(themeCondition, undefinedExpr, inlineExpr);
39809
- for (const out of cssDeclarationToStylexDeclarations(d)) {
40707
+ const conditionalExpr = !res.resolvedBranchIsTrue ? j.conditionalExpression(themeCondition, inlineExpr, undefinedExpr) : j.conditionalExpression(themeCondition, undefinedExpr, inlineExpr);
40708
+ for (const out of stylexDeclarations) {
39810
40709
  if (!out.prop) continue;
39811
40710
  styleObj[out.prop] = res.resolvedValue;
39812
40711
  inlineStyleProps.push({
@@ -40644,13 +41543,23 @@ function handleInterpolatedDeclaration(args) {
40644
41543
  hint: "Expected: props.x && 'css-string'"
40645
41544
  }
40646
41545
  };
40647
- if (op === "||" || op === "??") return {
40648
- type: "Arrow function: indexed theme lookup pattern not matched",
40649
- context: {
40650
- property: d.property,
40651
- operator: op
40652
- }
40653
- };
41546
+ if (op === "||" || op === "??") {
41547
+ const left = body?.left;
41548
+ if (isMemberExpression(left) && !memberExpressionTouchesTheme(left)) return {
41549
+ type: "Unsupported interpolation: member expression",
41550
+ context: {
41551
+ memberExpression: left?.type,
41552
+ operator: op
41553
+ }
41554
+ };
41555
+ return {
41556
+ type: "Arrow function: indexed theme lookup pattern not matched",
41557
+ context: {
41558
+ property: d.property,
41559
+ operator: op
41560
+ }
41561
+ };
41562
+ }
40654
41563
  }
40655
41564
  if (bodyType === "CallExpression") return {
40656
41565
  type: "Arrow function: helper call body is not supported",
@@ -40705,6 +41614,18 @@ function handleInterpolatedDeclaration(args) {
40705
41614
  if (bail) state.markBail();
40706
41615
  }
40707
41616
  /**
41617
+ * Returns true if any part of a member/identifier chain references `theme`
41618
+ * (e.g. `props.theme.color[x]` or a destructured `theme.color[x]`). Used to
41619
+ * distinguish indexed theme lookups from prop-rooted member accesses.
41620
+ */
41621
+ function memberExpressionTouchesTheme(node) {
41622
+ if (!node || typeof node !== "object") return false;
41623
+ const n = node;
41624
+ if (n.type === "Identifier") return n.name === "theme";
41625
+ if (isMemberExpression(n)) return memberExpressionTouchesTheme(n.property) || memberExpressionTouchesTheme(n.object);
41626
+ return false;
41627
+ }
41628
+ /**
40708
41629
  * Searches the function body for a local variable with the given name whose
40709
41630
  * initializer references `fnParamName`. Returns a cloned expression with
40710
41631
  * `fnParamName` replaced by `jsxProp`, or null if no such variable is found.
@@ -40895,7 +41816,7 @@ function sameStyleProps(left, right) {
40895
41816
  * must bail in that case.
40896
41817
  */
40897
41818
  function subtractLaterStaticOverrides(args) {
40898
- const { rule, allRules, currentDecl, branchStyles } = args;
41819
+ const { rule, allRules, currentDecl, branchStyles, ignoreUnsafeOverlaps = false } = args;
40899
41820
  const currentIndex = rule.declarations.indexOf(currentDecl);
40900
41821
  if (currentIndex === -1) return true;
40901
41822
  const laterContexts = [{
@@ -40921,12 +41842,32 @@ function subtractLaterStaticOverrides(args) {
40921
41842
  if (branchProps().some((prop) => [...borderProps].some((borderProp) => stylexPropsOverlap(prop, borderProp)))) return false;
40922
41843
  continue;
40923
41844
  }
41845
+ if (laterDecl.property.trim() === "background") {
41846
+ const overlapped = branchProps().filter((prop) => prop.startsWith("background"));
41847
+ if (!overlapped.length) continue;
41848
+ if (currentDecl.important && !laterDecl.important) {
41849
+ if (ignoreUnsafeOverlaps) continue;
41850
+ return false;
41851
+ }
41852
+ if (!context.unconditional || laterDecl.value.kind !== "static") {
41853
+ if (ignoreUnsafeOverlaps) continue;
41854
+ return false;
41855
+ }
41856
+ for (const branch of branchStyles) for (const prop of overlapped) delete branch[prop];
41857
+ continue;
41858
+ }
40924
41859
  for (const out of cssDeclarationToStylexDeclarations(laterDecl)) {
40925
41860
  const overrideProp = out.prop;
40926
41861
  const overlapped = branchProps().filter((prop) => stylexPropsOverlap(prop, overrideProp));
40927
41862
  if (!overlapped.length) continue;
40928
- if (currentDecl.important && !laterDecl.important) return false;
40929
- if (!context.unconditional || laterDecl.value.kind !== "static") return false;
41863
+ if (currentDecl.important && !laterDecl.important) {
41864
+ if (ignoreUnsafeOverlaps) continue;
41865
+ return false;
41866
+ }
41867
+ if (!context.unconditional || laterDecl.value.kind !== "static") {
41868
+ if (ignoreUnsafeOverlaps) continue;
41869
+ return false;
41870
+ }
40930
41871
  for (const branch of branchStyles) if (!subtractOverrideFromBranch(branch, overlapped, overrideProp)) return false;
40931
41872
  }
40932
41873
  }
@@ -41358,20 +42299,22 @@ function buildCssCalcTemplateExpression(args) {
41358
42299
  const expressions = [];
41359
42300
  const quasis = [];
41360
42301
  let currentQuasi = "calc(";
41361
- const appendOperand = (operand) => {
41362
- const staticText = expressionToCalcStaticText(operand.node, args.unit);
42302
+ const appendOperand = (operand, options = {}) => {
42303
+ const staticText = expressionToCalcStaticText(operand.node, args.unit, args.staticIdentifierValues);
41363
42304
  if (staticText !== null) {
41364
- currentQuasi += staticText;
42305
+ currentQuasi += options.negate ? negateCalcStaticText(staticText) : staticText;
41365
42306
  return true;
41366
42307
  }
41367
42308
  if (!operand.allowExpression || !isStylexCalcExpression(operand.node)) return false;
42309
+ if (options.negate) currentQuasi += "-1 * ";
41368
42310
  quasis.push(currentQuasi);
41369
42311
  currentQuasi = "";
41370
42312
  expressions.push(operand.node);
41371
42313
  return true;
41372
42314
  };
41373
- if (!appendOperand(args.left)) return null;
41374
- currentQuasi += ` ${args.operator} `;
42315
+ if (!appendOperand(args.left, { negate: args.negate })) return null;
42316
+ const operator = args.negate ? negateCssCalcOperator(args.operator) : args.operator;
42317
+ currentQuasi += ` ${operator} `;
41375
42318
  if (!appendOperand(args.right)) return null;
41376
42319
  currentQuasi += ")";
41377
42320
  if (expressions.length === 0) return args.j.literal(currentQuasi);
@@ -41382,9 +42325,27 @@ function buildCssCalcTemplateExpression(args) {
41382
42325
  cooked: raw
41383
42326
  }, index === quasis.length - 1)), expressions);
41384
42327
  }
41385
- function expressionToCalcStaticText(node, unit = "") {
42328
+ function buildNegatedCssTokenTemplate(j, expression) {
42329
+ return j.templateLiteral([j.templateElement({
42330
+ raw: "calc(-1 * ",
42331
+ cooked: "calc(-1 * "
42332
+ }, false), j.templateElement({
42333
+ raw: ")",
42334
+ cooked: ")"
42335
+ }, true)], [expression]);
42336
+ }
42337
+ function negateCssCalcOperator(operator) {
42338
+ return operator === "+" ? "-" : operator === "-" ? "+" : operator;
42339
+ }
42340
+ function negateCalcStaticText(value) {
42341
+ return value.startsWith("-") ? value.slice(1) : `-${value}`;
42342
+ }
42343
+ function expressionToCalcStaticText(node, unit = "", staticIdentifierValues) {
41386
42344
  const staticValue = literalToStaticValue(node);
41387
42345
  if (typeof staticValue === "number") return `${staticValue}${unit}`;
42346
+ const identifierName = node && typeof node === "object" && node.type === "Identifier" ? node.name : void 0;
42347
+ const identifierValue = identifierName ? staticIdentifierValues?.get(identifierName) : void 0;
42348
+ if (typeof identifierValue === "number") return `${identifierValue}${unit}`;
41388
42349
  return null;
41389
42350
  }
41390
42351
  function hasAdjacentTemplateUnit(quasis, expressionIndex) {
@@ -41547,7 +42508,7 @@ function tryHandleDynamicPseudoElementStyleFunction(args) {
41547
42508
  * Apply a resolved theme boolean value to a style object, expanding CSS shorthands.
41548
42509
  * Returns false if the value cannot be expanded (caller should bail).
41549
42510
  */
41550
- function applyThemeBooleanValue(j, cssProp, value, target) {
42511
+ function applyThemeBooleanValue(j, cssProp, value, target, important, cssValueText) {
41551
42512
  const node = value;
41552
42513
  const unwrapped = node?.type === "ExpressionStatement" ? node.expression : node;
41553
42514
  const strValue = unwrapped && (unwrapped.type === "StringLiteral" || unwrapped.type === "Literal") && typeof unwrapped.value === "string" ? unwrapped.value : null;
@@ -41557,18 +42518,85 @@ function applyThemeBooleanValue(j, cssProp, value, target) {
41557
42518
  const direction = borderMatch[1] ? borderMatch[1].slice(1).charAt(0).toUpperCase() + borderMatch[1].slice(2) : "";
41558
42519
  const parsed = parseBorderShorthandParts(strValue);
41559
42520
  if (!parsed) return false;
41560
- if (parsed.width) target[`border${direction}Width`] = j.literal(parsed.width);
41561
- if (parsed.style) target[`border${direction}Style`] = j.literal(parsed.style);
41562
- if (parsed.color) target[`border${direction}Color`] = j.literal(parsed.color);
42521
+ if (parsed.width) target[`border${direction}Width`] = appendImportantToStyleValue(j, j.literal(parsed.width), important);
42522
+ if (parsed.style) target[`border${direction}Style`] = appendImportantToStyleValue(j, j.literal(parsed.style), important);
42523
+ if (parsed.color) target[`border${direction}Color`] = appendImportantToStyleValue(j, j.literal(parsed.color), important);
41563
42524
  return true;
41564
42525
  }
41565
42526
  if (cssProp === "background") {
41566
- target[resolveBackgroundStylexProp(strValue ?? "")] = value;
42527
+ const backgroundText = strValue ?? cssValueText ?? "";
42528
+ if (backgroundText.trim() === "none") {
42529
+ target.backgroundImage = appendImportantToStyleValue(j, j.literal("none"), important);
42530
+ target.backgroundColor = appendImportantToStyleValue(j, j.literal("transparent"), important);
42531
+ return true;
42532
+ }
42533
+ const backgroundProp = resolveBackgroundStylexProp(backgroundText);
42534
+ target[backgroundProp] = appendImportantToStyleValue(j, value, important);
42535
+ applyBackgroundShorthandLayerReset(j, target, backgroundProp, important);
41567
42536
  return true;
41568
42537
  }
41569
- target[cssPropertyToStylexProp(cssProp)] = value;
42538
+ if (isCssShorthandProperty(cssProp)) return false;
42539
+ target[cssPropertyToStylexProp(cssProp)] = appendImportantToStyleValue(j, value, important);
41570
42540
  return true;
41571
42541
  }
42542
+ function restoreThemeStyleKeyFromPairedSide(targetBaseKey, pairedBaseKey, pairedStyleKey) {
42543
+ if (pairedStyleKey?.startsWith(pairedBaseKey)) return `${targetBaseKey}${pairedStyleKey.slice(pairedBaseKey.length)}`;
42544
+ return targetBaseKey;
42545
+ }
42546
+ function getLatestThemeInterleavableSourceOrder(args) {
42547
+ const sourceOrders = Object.values(args.variantSourceOrder);
42548
+ appendSourceOrders(sourceOrders, args.styleFnFromProps);
42549
+ appendSourceOrders(sourceOrders, args.decl.needsUseThemeHook);
42550
+ appendSourceOrders(sourceOrders, args.decl.pseudoAliasSelectors);
42551
+ appendSourceOrders(sourceOrders, args.decl.variantDimensions);
42552
+ return sourceOrders.length > 0 ? Math.max(...sourceOrders) : -1;
42553
+ }
42554
+ function appendSourceOrders(sourceOrders, entries) {
42555
+ for (const entry of entries ?? []) if (entry.sourceOrder !== void 0) sourceOrders.push(entry.sourceOrder);
42556
+ }
42557
+ function applyBackgroundShorthandLayerReset(j, target, backgroundProp, important) {
42558
+ if (backgroundProp === "backgroundColor") {
42559
+ target.backgroundImage = appendImportantToStyleValue(j, j.literal("none"), important);
42560
+ return;
42561
+ }
42562
+ target.backgroundColor = appendImportantToStyleValue(j, j.literal("transparent"), important);
42563
+ }
42564
+ function resolveRuntimeBackgroundStylexProp(value, cssValueText) {
42565
+ const node = unwrapExpressionNode(value);
42566
+ if (node?.type !== "ConditionalExpression") {
42567
+ const staticText = getRuntimeBackgroundStaticText(node);
42568
+ if (staticText !== null) return resolveBackgroundStylexProp(staticText);
42569
+ return cssValueText ? resolveBackgroundStylexProp(cssValueText) : null;
42570
+ }
42571
+ const consequentProp = classifyRuntimeBackgroundBranch(node.consequent);
42572
+ const alternateProp = classifyRuntimeBackgroundBranch(node.alternate);
42573
+ if (consequentProp && alternateProp) return consequentProp === alternateProp ? consequentProp : "unsupported";
42574
+ const cssTextProp = cssValueText ? resolveBackgroundStylexProp(cssValueText) : null;
42575
+ const knownProp = consequentProp ?? alternateProp;
42576
+ if (knownProp) {
42577
+ if (knownProp === "backgroundImage") return "unsupported";
42578
+ if (cssTextProp && cssTextProp !== knownProp) return "unsupported";
42579
+ return "backgroundColor";
42580
+ }
42581
+ if (cssTextProp === "backgroundImage") return "unsupported";
42582
+ return "backgroundColor";
42583
+ }
42584
+ function classifyRuntimeBackgroundBranch(value) {
42585
+ const staticText = getRuntimeBackgroundStaticText(unwrapExpressionNode(value));
42586
+ return staticText === null ? null : resolveBackgroundStylexProp(staticText);
42587
+ }
42588
+ function unwrapExpressionNode(value) {
42589
+ if (!value || typeof value !== "object") return null;
42590
+ const node = value;
42591
+ if (node.type === "ExpressionStatement" || node.type === "TSAsExpression" || node.type === "TSSatisfiesExpression") return unwrapExpressionNode(node.expression);
42592
+ return node;
42593
+ }
42594
+ function getRuntimeBackgroundStaticText(value) {
42595
+ if (!value) return null;
42596
+ if ((value.type === "StringLiteral" || value.type === "Literal") && typeof value.value === "string") return value.value;
42597
+ if (value.type === "TemplateLiteral") return (value.quasis ?? []).map((quasi) => quasi.value?.cooked ?? quasi.value?.raw ?? "").join("") || null;
42598
+ return null;
42599
+ }
41572
42600
  function scalarizePropsObjectDynamicValue(args) {
41573
42601
  const propNames = uniqueScalarPropNames(args.propNames);
41574
42602
  if (propNames.length === 0) return null;
@@ -42212,6 +43240,84 @@ function tryHandleMultiSlotTernary(ctx, d) {
42212
43240
  function hasRuntimeImport(imports) {
42213
43241
  return (imports ?? []).some((imp) => !isStylexImportSource(imp.from.value));
42214
43242
  }
43243
+ function hasSourceOrderedThemeStyleOverlap(decl, extraStyleObjects, cssText) {
43244
+ const themeProps = /* @__PURE__ */ new Set();
43245
+ for (const entry of decl.needsUseThemeHook ?? []) {
43246
+ if (entry.sourceOrder === void 0) continue;
43247
+ collectStyleObjectProps(extraStyleObjects.get(entry.trueStyleKey ?? ""), themeProps);
43248
+ collectStyleObjectProps(extraStyleObjects.get(entry.falseStyleKey ?? ""), themeProps);
43249
+ }
43250
+ return cssTextMayOverlapStylexProps(cssText, themeProps);
43251
+ }
43252
+ function collectStyleObjectProps(style, props) {
43253
+ if (!style) return;
43254
+ for (const prop of Object.keys(style)) props.add(prop);
43255
+ }
43256
+ function cssTextMayOverlapStylexProps(cssText, props) {
43257
+ if (props.size === 0) return false;
43258
+ if (!cssText) return true;
43259
+ const chunks = cssText.split(";").map((chunk) => chunk.trim()).filter(Boolean);
43260
+ if (chunks.length === 0) return true;
43261
+ for (const chunk of chunks) {
43262
+ const match = chunk.match(/^([^:]+):([\s\S]+)$/);
43263
+ if (!match?.[1] || !match[2]) return true;
43264
+ const property = match[1].trim();
43265
+ const valueRaw = match[2].trim();
43266
+ if (laterDeclarationMayResetStylexProps(property, props)) return true;
43267
+ for (const out of cssDeclarationToStylexDeclarations({
43268
+ property,
43269
+ value: {
43270
+ kind: "static",
43271
+ value: valueRaw
43272
+ },
43273
+ important: false,
43274
+ valueRaw
43275
+ })) if (hasOverlappingStylexProp(props, out.prop)) return true;
43276
+ }
43277
+ return false;
43278
+ }
43279
+ function hasLaterDeclarationForStylexProps(current, rules, props) {
43280
+ if (props.size === 0) return false;
43281
+ let sawCurrent = false;
43282
+ for (const rule of rules) for (const candidate of rule.declarations) {
43283
+ if (candidate === current) {
43284
+ sawCurrent = true;
43285
+ continue;
43286
+ }
43287
+ if (!isDeclarationAfter(current, candidate, sawCurrent)) continue;
43288
+ if (!candidate.property) return true;
43289
+ if (laterDeclarationMayResetStylexProps(candidate.property, props)) return true;
43290
+ for (const out of cssDeclarationToStylexDeclarations(candidate)) if (hasOverlappingStylexProp(props, out.prop)) return true;
43291
+ }
43292
+ return false;
43293
+ }
43294
+ function isDeclarationAfter(current, candidate, sawCurrent) {
43295
+ if (current.sourceOrder !== void 0 && candidate.sourceOrder !== void 0) return candidate.sourceOrder > current.sourceOrder;
43296
+ return sawCurrent;
43297
+ }
43298
+ function hasOverlappingStylexProp(props, candidate) {
43299
+ for (const prop of props) if (stylexPropsOverlap(prop, candidate)) return true;
43300
+ return false;
43301
+ }
43302
+ function laterDeclarationMayResetStylexProps(cssProperty, props) {
43303
+ const property = cssProperty.trim();
43304
+ if (property === "background") return hasStylexPropWithPrefix(props, "background");
43305
+ if (!isBorderShorthandProperty(property)) return false;
43306
+ const side = property.match(/^border-(top|right|bottom|left)$/)?.[1];
43307
+ return hasBorderResetOverlap(props, side);
43308
+ }
43309
+ function hasStylexPropWithPrefix(props, prefix) {
43310
+ for (const prop of props) if (prop.startsWith(prefix)) return true;
43311
+ return false;
43312
+ }
43313
+ function hasBorderResetOverlap(props, side) {
43314
+ const sidePrefix = side ? `border${side.charAt(0).toUpperCase()}${side.slice(1)}` : "border";
43315
+ for (const prop of props) {
43316
+ if (!/^border(?:Top|Right|Bottom|Left)?(?:Width|Style|Color)$/.test(prop)) continue;
43317
+ if (!side || prop.startsWith(sidePrefix) || /^border(?:Width|Style|Color)$/.test(prop)) return true;
43318
+ }
43319
+ return false;
43320
+ }
42215
43321
  /**
42216
43322
  * If any variant `when` condition references the styled-components theme object,
42217
43323
  * mark the declaration as needing the `useTheme()` hook so the emitted wrapper
@@ -42783,7 +43889,7 @@ function findFirst(collection, predicate) {
42783
43889
  //#endregion
42784
43890
  //#region src/internal/lower-rules/process-rule-declarations.ts
42785
43891
  function processRuleDeclarations(args) {
42786
- const { ctx, rule, allRules, media, pseudos, pseudoElement, attrTarget, resolvedSelectorMedia, applyResolvedPropValue } = args;
43892
+ const { ctx, rule, allRules, media, pseudos, pseudoElement, attrTarget, resolvedSelectorMedia, hasAncestorAttributeScope, applyResolvedPropValue } = args;
42787
43893
  const { state } = ctx;
42788
43894
  for (const d of rule.declarations) {
42789
43895
  ctx.setCurrentDeclarationSourceOrder(d.sourceOrder);
@@ -42812,6 +43918,7 @@ function processRuleDeclarations(args) {
42812
43918
  pseudoElement,
42813
43919
  attrTarget,
42814
43920
  resolvedSelectorMedia,
43921
+ hasAncestorAttributeScope,
42815
43922
  applyResolvedPropValue
42816
43923
  });
42817
43924
  if (state.bail) break;
@@ -42931,7 +44038,7 @@ function hasOtherBackgroundDeclaration(allRules, current) {
42931
44038
  //#endregion
42932
44039
  //#region src/internal/lower-rules/process-rules.ts
42933
44040
  function processDeclRules(ctx) {
42934
- const { state, decl, styleObj, perPropPseudo, perPropMedia, nestedSelectors, variantBuckets, styleFnDecls, attrBuckets, localVarValues, cssHelperPropValues, getComposedDefaultValue } = ctx;
44041
+ const { state, decl, styleObj, perPropPseudo, perPropMedia, nestedSelectors, variantBuckets, extraStyleObjects, styleFnDecls, attrBuckets, localVarValues, cssHelperPropValues, getComposedDefaultValue } = ctx;
42935
44042
  const { j, root, warnings, resolverImports, resolveSelector, parseExpr, cssHelperNames, declByLocalName, relationOverridePseudoBuckets, relationOverrides, ancestorSelectorParents, resolveThemeValue, resolveThemeValueFromFn, resolveImportInScope } = state;
42936
44043
  const getConditionDefaultValue = (propName) => cssHelperPropValues.has(propName) ? getComposedDefaultValue(propName) : ctx.getWrappedComponentBaseDefaultValue(propName) ?? null;
42937
44044
  /**
@@ -43605,6 +44712,39 @@ function processDeclRules(ctx) {
43605
44712
  }
43606
44713
  }
43607
44714
  };
44715
+ const clearEarlierThemeBaseValues = (prop, laterBaseValue, sourceCssProperty) => {
44716
+ const hooks = decl.needsUseThemeHook;
44717
+ if (!hooks?.length) return;
44718
+ const propsToClear = sourceCssProperty === "background" ? ["backgroundColor", "backgroundImage"] : [prop];
44719
+ const laterBaseIsImportant = cssValueIsImportant(laterBaseValue);
44720
+ const clearHookStyleKey = (hook, side) => {
44721
+ const styleKey = hook[side];
44722
+ if (!styleKey) return false;
44723
+ const bucket = extraStyleObjects.get(styleKey);
44724
+ if (!bucket) return false;
44725
+ let changed = false;
44726
+ for (const propToClear of propsToClear) {
44727
+ if (!Object.hasOwn(bucket, propToClear)) continue;
44728
+ const bucketValue = bucket[propToClear];
44729
+ if (!laterBaseIsImportant && cssValueIsImportant(bucketValue)) continue;
44730
+ delete bucket[propToClear];
44731
+ changed = true;
44732
+ }
44733
+ if (!changed) return false;
44734
+ if (Object.keys(bucket).length === 0) {
44735
+ extraStyleObjects.delete(styleKey);
44736
+ hook[side] = null;
44737
+ }
44738
+ return true;
44739
+ };
44740
+ for (let i = hooks.length - 1; i >= 0; i--) {
44741
+ const hook = hooks[i];
44742
+ const hadStyleKeys = Boolean(hook.trueStyleKey || hook.falseStyleKey);
44743
+ const clearedTrue = clearHookStyleKey(hook, "trueStyleKey");
44744
+ const clearedFalse = clearHookStyleKey(hook, "falseStyleKey");
44745
+ if ((clearedTrue || clearedFalse) && hadStyleKeys && !hook.trueStyleKey && !hook.falseStyleKey) hooks.splice(i, 1);
44746
+ }
44747
+ };
43608
44748
  const applyResolvedPropValue = (prop, value, commentSource, sourceCssProperty) => {
43609
44749
  const noteSourceCssProperty = (target) => {
43610
44750
  if (sourceCssProperty) {
@@ -43820,6 +44960,7 @@ function processDeclRules(ctx) {
43820
44960
  return;
43821
44961
  }
43822
44962
  clearEarlierVariantBaseValues(prop, value);
44963
+ clearEarlierThemeBaseValues(prop, value, sourceCssProperty);
43823
44964
  const target = ctx.getBaseStyleTarget();
43824
44965
  setStyleObjectValue(target, prop, value);
43825
44966
  noteSourceCssProperty(target);
@@ -43838,6 +44979,7 @@ function processDeclRules(ctx) {
43838
44979
  pseudoElement: pseudoElement ?? (pseudoElementsList ? pseudoElementsList[0] ?? null : null),
43839
44980
  attrTarget,
43840
44981
  resolvedSelectorMedia,
44982
+ hasAncestorAttributeScope: Boolean(ancestorAttrs?.length),
43841
44983
  applyResolvedPropValue
43842
44984
  });
43843
44985
  if (state.bail) break;
@@ -44348,18 +45490,6 @@ function recoverStandaloneInterpolationsInPseudoBlock(rule, decl) {
44348
45490
  cssProps
44349
45491
  };
44350
45492
  }
44351
- /**
44352
- * Whether a lowered StyleX value carries `!important`. Values are stored either
44353
- * as plain strings (e.g. `"red !important"`) or as AST string/template literals.
44354
- */
44355
- function cssValueIsImportant(value) {
44356
- if (typeof value === "string") return value.includes("!important");
44357
- if (!value || typeof value !== "object") return false;
44358
- const node = value;
44359
- if ((node.type === "StringLiteral" || node.type === "Literal") && typeof node.value === "string") return node.value.includes("!important");
44360
- if (node.type === "TemplateLiteral" && Array.isArray(node.quasis)) return node.quasis.some((q) => (q?.value?.cooked ?? q?.value?.raw ?? "").includes("!important"));
44361
- return false;
44362
- }
44363
45493
  /** Negates a `when` condition string (e.g. `$active` → `!$active`, `!$x` → `$x`). */
44364
45494
  function negateWhen(when) {
44365
45495
  if (when.startsWith("!(") && when.endsWith(")")) return when.slice(2, -1);
@@ -44848,6 +45978,7 @@ function createLowerRulesState(ctx) {
44848
45978
  const resolveValueDirectional = ctx.resolveValueDirectionalSafe;
44849
45979
  const resolveCall = ctx.resolveCallSafe;
44850
45980
  const resolveValueOptional = (rvCtx) => {
45981
+ if (rvCtx.kind === "importedValue" && isStylexFileSource(rvCtx.source)) return resolveValue(rvCtx);
44851
45982
  const res = ctx.adapter.resolveValue(rvCtx);
44852
45983
  if (res && isDirectionalResult(res)) return;
44853
45984
  return res;
@@ -44914,6 +46045,30 @@ function createLowerRulesState(ctx) {
44914
46045
  }
44915
46046
  };
44916
46047
  const staticPropertyValues = /* @__PURE__ */ new Map();
46048
+ const staticIdentifierValues = /* @__PURE__ */ new Map();
46049
+ root.find(j.VariableDeclarator).forEach((p) => {
46050
+ if (!isTopLevelConstDeclarator(p)) return;
46051
+ const node = p.node;
46052
+ if (node.id?.type !== "Identifier" || !node.id.name) return;
46053
+ const staticValue = literalToStaticValue(node.init, { allowStaticArrowFunctions: false });
46054
+ if (staticValue !== null) staticIdentifierValues.set(node.id.name, staticValue);
46055
+ });
46056
+ if (staticIdentifierValues.size > 0) {
46057
+ const shadowingNames = /* @__PURE__ */ new Set();
46058
+ root.find(j.Function).forEach((fnPath) => {
46059
+ collectPatternBindingNames$2(fnPath.node.params, shadowingNames);
46060
+ const fnId = fnPath.node.id;
46061
+ if (fnId?.name) shadowingNames.add(fnId.name);
46062
+ });
46063
+ root.find(j.ClassDeclaration).forEach((classPath) => {
46064
+ const classId = classPath.node.id;
46065
+ if (classId?.name) shadowingNames.add(classId.name);
46066
+ });
46067
+ root.find(j.VariableDeclarator).forEach((declPath) => {
46068
+ if (!isTopLevelConstDeclarator(declPath)) collectPatternBindingNames$2(declPath.node.id, shadowingNames);
46069
+ });
46070
+ for (const name of shadowingNames) staticIdentifierValues.delete(name);
46071
+ }
44917
46072
  root.find(j.ExpressionStatement, { expression: {
44918
46073
  type: "AssignmentExpression",
44919
46074
  operator: "=",
@@ -44927,7 +46082,7 @@ function createLowerRulesState(ctx) {
44927
46082
  const ownerName = expr.left?.object?.name;
44928
46083
  const propName = expr.left?.property?.name;
44929
46084
  if (ownerName && propName) {
44930
- const staticValue = literalToStaticValue(expr.right);
46085
+ const staticValue = literalToStaticValue(expr.right, { allowStaticArrowFunctions: false });
44931
46086
  let ownerMap = staticPropertyValues.get(ownerName);
44932
46087
  if (!ownerMap) {
44933
46088
  ownerMap = /* @__PURE__ */ new Map();
@@ -45023,6 +46178,7 @@ function createLowerRulesState(ctx) {
45023
46178
  cssHelperValuesByKey,
45024
46179
  mixinValuesByKey,
45025
46180
  staticPropertyValues,
46181
+ staticIdentifierValues,
45026
46182
  usedCssHelperFunctions: /* @__PURE__ */ new Set(),
45027
46183
  warnPropInlineStyle,
45028
46184
  applyCssHelperMixin,
@@ -45109,6 +46265,20 @@ function clonePropUsageByComponent(source) {
45109
46265
  });
45110
46266
  return cloned;
45111
46267
  }
46268
+ function isTopLevelConstDeclarator(path) {
46269
+ const declarationPath = path.parentPath;
46270
+ if (!declarationPath) return false;
46271
+ const declaration = declarationPath?.node;
46272
+ if (declaration?.type !== "VariableDeclaration" || declaration.kind !== "const") return false;
46273
+ let current = declarationPath.parentPath;
46274
+ while (current?.node) {
46275
+ const type = current.node.type;
46276
+ if (type === "Program") return true;
46277
+ if (type !== "VariableDeclaration" && type !== "ExportNamedDeclaration") return false;
46278
+ current = current.parentPath;
46279
+ }
46280
+ return false;
46281
+ }
45112
46282
  function collectOpeningPropUsage(attributes) {
45113
46283
  const props = {};
45114
46284
  let hasSpread = false;
@@ -45138,6 +46308,10 @@ function getJsxIdentifierName(node) {
45138
46308
  const record = node;
45139
46309
  return record.type === "JSXIdentifier" && typeof record.name === "string" ? record.name : null;
45140
46310
  }
46311
+ const STYLEX_FILE_RE = /\.stylex(\.\w+)?$/;
46312
+ function isStylexFileSource(source) {
46313
+ return STYLEX_FILE_RE.test(source.value);
46314
+ }
45141
46315
  //#endregion
45142
46316
  //#region src/internal/transform-steps/lower-rules.ts
45143
46317
  /**
@@ -47850,6 +49024,43 @@ function upgradePolymorphicAsPropTypesStep(ctx) {
47850
49024
  return CONTINUE;
47851
49025
  }
47852
49026
  //#endregion
49027
+ //#region src/internal/transform-steps/warn-partial-migration-incomplete.ts
49028
+ /**
49029
+ * Step: warn when partial migration leaves styled-components declarations behind.
49030
+ * Core concepts: partial migration diagnostics and converted declaration accounting.
49031
+ */
49032
+ function warnPartialMigrationIncompleteStep(ctx) {
49033
+ if (!shouldWarnForPartialMigration(ctx)) return CONTINUE;
49034
+ const skippedDecls = collectSkippedStyledDeclarations(ctx.styledDecls);
49035
+ const convertedDecls = collectConvertedStyleDeclarations(ctx.styledDecls);
49036
+ if (skippedDecls.length === 0 || convertedDecls.length === 0) return CONTINUE;
49037
+ ctx.warnings.push({
49038
+ severity: "warning",
49039
+ type: PARTIAL_MIGRATION_INCOMPLETE_WARNING,
49040
+ loc: skippedDecls[0]?.loc,
49041
+ context: {
49042
+ skippedDeclarationCount: skippedDecls.length,
49043
+ skippedDeclarations: declarationNames(skippedDecls),
49044
+ convertedDeclarationCount: convertedDecls.length,
49045
+ convertedDeclarations: declarationNames(convertedDecls)
49046
+ }
49047
+ });
49048
+ return CONTINUE;
49049
+ }
49050
+ const MAX_PARTIAL_MIGRATION_WARNING_NAMES = 20;
49051
+ function shouldWarnForPartialMigration(ctx) {
49052
+ return ctx.hasChanges && ctx.options.allowPartialMigration === true && ctx.options.transformMode !== "leavesOnly";
49053
+ }
49054
+ function collectSkippedStyledDeclarations(styledDecls) {
49055
+ return styledDecls?.filter((decl) => decl.skipTransform && !decl.isCssHelper && !decl.isDirectJsxResolution) ?? [];
49056
+ }
49057
+ function collectConvertedStyleDeclarations(styledDecls) {
49058
+ return styledDecls?.filter((decl) => !decl.skipTransform && !decl.isCssHelper) ?? [];
49059
+ }
49060
+ function declarationNames(decls) {
49061
+ return decls.slice(0, MAX_PARTIAL_MIGRATION_WARNING_NAMES).map((decl) => decl.localName);
49062
+ }
49063
+ //#endregion
47853
49064
  //#region src/transform.ts
47854
49065
  /**
47855
49066
  * Transform styled-components to StyleX
@@ -47859,8 +49070,9 @@ function upgradePolymorphicAsPropTypesStep(ctx) {
47859
49070
  */
47860
49071
  function transform(file, api, options) {
47861
49072
  try {
47862
- const result = transformWithWarnings(file, api, options);
47863
- Logger.logWarnings(result.warnings, file.path);
49073
+ const transformOptions = options;
49074
+ const result = transformWithWarnings(file, api, transformOptions);
49075
+ Logger.logWarnings(result.warnings, file.path, { silent: transformOptions.silent === true });
47864
49076
  if (result.sidecarFiles && result.sidecarFiles.length > 0) {
47865
49077
  const sidecarFilesMap = options.sidecarFiles;
47866
49078
  if (sidecarFilesMap) {
@@ -47908,6 +49120,7 @@ function transformWithWarnings(file, api, options) {
47908
49120
  extractCssHelpersStep,
47909
49121
  detectStringMappingFnsStep,
47910
49122
  collectStyledDeclsStep,
49123
+ inlinePropConditionalCssHelpersStep,
47911
49124
  resolveBaseComponentsStep,
47912
49125
  applyLeavesOnlyPolicyStep,
47913
49126
  markPartialImportedRootsStep,
@@ -47930,7 +49143,8 @@ function transformWithWarnings(file, api, options) {
47930
49143
  reinsertStaticPropsStep,
47931
49144
  postProcessStep,
47932
49145
  cleanupCssImportStep,
47933
- ensureReactImportStep
49146
+ ensureReactImportStep,
49147
+ warnPartialMigrationIncompleteStep
47934
49148
  ];
47935
49149
  for (const step of pipeline) {
47936
49150
  const outcome = step(ctx);