styled-components-to-stylex-codemod 0.0.38 → 0.0.39

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.
@@ -2,8 +2,8 @@ import { t as createModuleResolver } from "./resolve-imports-BlxKezSJ.mjs";
2
2
  import { a as assertValidAdapter, i as isDirectionalResult, n as DEFAULT_THEME_HOOK, t as mergeMarkerDeclarations } from "./merge-markers-BC5YNB7D.mjs";
3
3
  import { a as Logger, i as resolveBarrelReExport, r as findImportSource } from "./extract-external-interface-CdHbvfxu.mjs";
4
4
  import { n as toRealPath, t as isRelativeSpecifier } from "./path-utils-BIpoL4Ue.mjs";
5
- import { a as isPrettierIgnoreComment, c as kebabToCamelCase, d as normalizeWhitespace, f as sanitizeIdentifier, i as isBackgroundImageValue, l as looksLikeLength, n as capitalize, o as isSingleBackgroundComponent, r as escapeRegex, s as isValidIdentifierName, t as camelToKebabCase, u as lowerFirst } from "./string-utils-KggM5TNH.mjs";
6
- import { n as parseStyledTemplateLiteral, r as terminateStandaloneInterpolationStatements, t as PLACEHOLDER_RE } from "./styled-css-BVR82jN5.mjs";
5
+ import { a as isBackgroundImageValue, c as isSingleBackgroundComponent, d as kebabToCamelCase, f as looksLikeLength, h as sanitizeIdentifier, i as getCommentBody, l as isStyleSectionMarkerComment, m as normalizeWhitespace, n as capitalize, o as isJSDocBlockComment, p as lowerFirst, r as escapeRegex, s as isPrettierIgnoreComment, t as camelToKebabCase, u as isValidIdentifierName } from "./string-utils-DD9wdRHW.mjs";
6
+ import { a as PLACEHOLDER_RE, i as readStaticJsxLiteral, n as createComponentPropUsageInfo, o as parseStyledTemplateLiteral, r as mergeComponentPropUsage, s as terminateStandaloneInterpolationStatements, t as KNOWN_NON_ELEMENT_PROPS } from "./prop-usage-D6ZiDfzz.mjs";
7
7
  import { t as isSelectorContext } from "./selector-context-heuristic-6_jSRGkZ.mjs";
8
8
  import jscodeshift from "jscodeshift";
9
9
  import { basename, dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
@@ -2143,6 +2143,8 @@ var TransformContext = class {
2143
2143
  crossFileSelectorUsages;
2144
2144
  /** Component names in this file that need a global selector bridge className */
2145
2145
  bridgeComponentNames;
2146
+ /** Prepass prop usage inventory for styled components defined in this file. */
2147
+ propUsageByComponent;
2146
2148
  /** Marker variable names generated for cross-file parent components and sibling selectors (parentStyleKey → markerName) */
2147
2149
  crossFileMarkers;
2148
2150
  /** Style keys that use sibling markers (scoped marker replaces defaultMarker) */
@@ -2263,6 +2265,7 @@ var TransformContext = class {
2263
2265
  if (options.crossFileInfo) {
2264
2266
  this.crossFileSelectorUsages = options.crossFileInfo.selectorUsages;
2265
2267
  this.bridgeComponentNames = options.crossFileInfo.bridgeComponentNames;
2268
+ this.propUsageByComponent = options.crossFileInfo.propUsageByComponent;
2266
2269
  }
2267
2270
  }
2268
2271
  markChanged() {
@@ -3282,6 +3285,15 @@ function resolveImportedHelperCall(callExpr, ctx, propsParamName, cssProperty, t
3282
3285
  resolveCallResult: void 0
3283
3286
  };
3284
3287
  }
3288
+ function resolveImportedCurriedHelperCall(callExpr, ctx, cssProperty) {
3289
+ if (!isCallExpressionNode(callExpr.callee)) return null;
3290
+ if ((callExpr.arguments ?? []).length !== 1) return null;
3291
+ const innerCall = callExpr.callee;
3292
+ return {
3293
+ innerCall,
3294
+ result: resolveImportedHelperCall(innerCall, ctx, void 0, cssProperty)
3295
+ };
3296
+ }
3285
3297
  /**
3286
3298
  * Resolves a DynamicNode whose expression is a direct (non-arrow) call expression.
3287
3299
  * Handles both simple `helper(...)` and curried `helper(...)(props)` patterns.
@@ -3294,16 +3306,12 @@ function tryResolveCallExpression(node, ctx) {
3294
3306
  resolveCallContext: simple.resolveCallContext,
3295
3307
  resolveCallResult: simple.resolveCallResult
3296
3308
  });
3297
- if (isCallExpressionNode(expr.callee)) {
3298
- if ((expr.arguments ?? []).length === 1) {
3299
- const innerCall = expr.callee;
3300
- const innerRes = resolveImportedHelperCall(innerCall, ctx, void 0, node.css.property);
3301
- if (innerRes.kind === "resolved") return buildResolvedHandlerResult(innerRes.result, node.css.property, {
3302
- resolveCallContext: innerRes.resolveCallContext,
3303
- resolveCallResult: innerRes.resolveCallResult
3304
- });
3305
- }
3306
- }
3309
+ const curried = resolveImportedCurriedHelperCall(expr, ctx, node.css.property);
3310
+ if (curried?.result.kind === "resolved") return buildResolvedHandlerResult(curried.result.result, node.css.property, {
3311
+ resolveCallContext: curried.result.resolveCallContext,
3312
+ resolveCallResult: curried.result.resolveCallResult
3313
+ });
3314
+ if (curried?.result.kind === "unresolved") return buildUnresolvedHelperResult(curried.innerCall.callee, ctx);
3307
3315
  if (simple.kind === "unresolved") return buildUnresolvedHelperResult(expr.callee, ctx);
3308
3316
  if (simple.kind === "keepOriginal" && node.css.property) {
3309
3317
  const calleeIdent = getCalleeIdentName(expr.callee);
@@ -4268,7 +4276,7 @@ function analyzeBeforeEmitStep(ctx) {
4268
4276
  for (const decl of styledDecls) {
4269
4277
  if (decl.isDirectJsxResolution) continue;
4270
4278
  if (root.find(j.Identifier, { name: decl.localName }).filter((p) => {
4271
- if (p.parentPath?.node?.type === "VariableDeclarator") return false;
4279
+ if (p.parentPath?.node?.type === "VariableDeclarator" && p.parentPath.node.id === p.node) return false;
4272
4280
  if (p.parentPath?.node?.type === "JSXOpeningElement" || p.parentPath?.node?.type === "JSXClosingElement") return false;
4273
4281
  if (p.parentPath?.node?.type === "JSXMemberExpression" && p.parentPath.node.object === p.node) return false;
4274
4282
  if (p.parentPath?.node?.type === "CallExpression") {
@@ -7600,8 +7608,8 @@ function collectStyledDeclsImpl(args) {
7600
7608
  return Array.isArray(arr) && arr.length > 0 ? arr[0] : void 0;
7601
7609
  };
7602
7610
  /**
7603
- * Extract leading comments from the parent VariableDeclaration if it has a single declarator.
7604
- * This captures JSDoc and line comments for preservation in the output.
7611
+ * Extract preserved leading comments from the parent VariableDeclaration if it has a single
7612
+ * declarator.
7605
7613
  */
7606
7614
  const getLeadingComments = (declaratorPath) => {
7607
7615
  const parentPath = declaratorPath.parentPath;
@@ -7622,7 +7630,7 @@ function collectStyledDeclsImpl(args) {
7622
7630
  }
7623
7631
  }
7624
7632
  if (!comments || !Array.isArray(comments) || comments.length === 0) return;
7625
- const filtered = comments.filter((c) => c.leading !== false && !isPrettierIgnoreComment(String(c.value ?? "")));
7633
+ const filtered = comments.filter((c) => !shouldDropStyledLeadingComment(c));
7626
7634
  return filtered.length > 0 ? filtered : void 0;
7627
7635
  };
7628
7636
  /**
@@ -8221,6 +8229,14 @@ function extractDynamicStyleValue(value, attrsParamPropNames) {
8221
8229
  }
8222
8230
  return null;
8223
8231
  }
8232
+ function shouldDropStyledLeadingComment(comment) {
8233
+ const body = getCommentBody(comment);
8234
+ return hasLeadingFalse(comment) || isPrettierIgnoreComment(body) || isStyleSectionMarkerComment(body);
8235
+ }
8236
+ function hasLeadingFalse(comment) {
8237
+ if (!comment || typeof comment !== "object") return false;
8238
+ return comment.leading === false;
8239
+ }
8224
8240
  function extractPropName(value, attrsParamPropNames) {
8225
8241
  if (value?.type === "Identifier" && typeof value.name === "string" && attrsParamPropNames.has(value.name)) return value.name;
8226
8242
  if (value?.type === "MemberExpression" && value.object?.type === "Identifier" && (value.object.name === "props" || value.object.name === "p") && value.property?.type === "Identifier" && typeof value.property.name === "string") return value.property.name;
@@ -10852,27 +10868,6 @@ function getActiveStyledNames(styledDecls) {
10852
10868
  return names;
10853
10869
  }
10854
10870
  //#endregion
10855
- //#region src/internal/transform-steps/jsx-static-literal.ts
10856
- function readStaticJsxLiteral(attr) {
10857
- if (!isObjectRecord(attr) || attr.type !== "JSXAttribute") return;
10858
- if (!("value" in attr) || attr.value == null) return true;
10859
- const directLiteral = readLiteralNodeValue(attr.value);
10860
- if (directLiteral !== void 0) return directLiteral;
10861
- if (!isObjectRecord(attr.value) || attr.value.type !== "JSXExpressionContainer") return;
10862
- return readLiteralNodeValue(attr.value.expression);
10863
- }
10864
- function readLiteralNodeValue(node) {
10865
- if (!isObjectRecord(node)) return;
10866
- if (node.type === "StringLiteral" || node.type === "NumericLiteral" || node.type === "BooleanLiteral") return isStaticLiteral$1(node.value) ? node.value : void 0;
10867
- if (node.type === "Literal") return isStaticLiteral$1(node.value) ? node.value : void 0;
10868
- }
10869
- function isObjectRecord(value) {
10870
- return typeof value === "object" && value !== null;
10871
- }
10872
- function isStaticLiteral$1(value) {
10873
- return typeof value === "string" || typeof value === "number" || typeof value === "boolean";
10874
- }
10875
- //#endregion
10876
10871
  //#region src/internal/transform-steps/resolve-base-components.ts
10877
10872
  /**
10878
10873
  * Step: resolve and inline eligible styled(ImportedComponent) bases.
@@ -12144,7 +12139,8 @@ function emitStylesAndImports(ctx) {
12144
12139
  if (decl.skipTransform || decl.needsWrapperComponent) continue;
12145
12140
  if (decl.leadingComments && decl.leadingComments.length > 0) {
12146
12141
  const { property } = splitBugNarrativeLeadingComments(decl.leadingComments);
12147
- if (property.length > 0) styleKeyToComments.set(decl.styleKey, property);
12142
+ const stylexCreateComments = property.filter((comment) => !isJSDocBlockComment(comment));
12143
+ if (stylexCreateComments.length > 0) styleKeyToComments.set(decl.styleKey, stylexCreateComments);
12148
12144
  }
12149
12145
  }
12150
12146
  normalizeShorthandLonghandConflicts(styledDecls, resolvedStyleObjects);
@@ -12753,6 +12749,15 @@ function emitStyleMerging(args) {
12753
12749
  emitTypes
12754
12750
  });
12755
12751
  if (wrappedAcceptsSxProp && inlineStyleProps.length === 0 && !staticClassNameExpr) return buildSxOnlyResult(j, styleArgs, { normalizeOptionalEntries: true });
12752
+ if (wrappedAcceptsSxProp && inlineStyleProps.length === 0 && staticClassNameExpr) return buildSxWithExternalPropsResult({
12753
+ j,
12754
+ styleArgs,
12755
+ classNameId,
12756
+ styleId,
12757
+ allowClassNameProp,
12758
+ allowStyleProp,
12759
+ staticClassNameExpr
12760
+ });
12756
12761
  if (!allowClassNameProp && !allowStyleProp && inlineStyleProps.length === 0 && !staticClassNameExpr) {
12757
12762
  const sid = emitter.stylesIdentifier;
12758
12763
  const hasLocalRef = styleArgs.some((a) => j([a]).find(j.Identifier, { name: sid }).size() > 0);
@@ -12865,6 +12870,15 @@ function buildMergerClassNameArg(args) {
12865
12870
  if (parts.length === 1) return parts[0] ?? null;
12866
12871
  return j.arrayExpression(parts);
12867
12872
  }
12873
+ function buildClassNameAttributeExpr(args) {
12874
+ const { j, classNameId, allowClassNameProp, staticClassNameExpr } = args;
12875
+ const parts = [];
12876
+ if (staticClassNameExpr) parts.push(staticClassNameExpr);
12877
+ if (allowClassNameProp) parts.push(classNameId);
12878
+ if (parts.length === 0) return null;
12879
+ if (parts.length === 1) return parts[0] ?? null;
12880
+ return j.callExpression(j.memberExpression(j.callExpression(j.memberExpression(j.arrayExpression(parts), j.identifier("filter")), [j.identifier("Boolean")]), j.identifier("join")), [j.literal(" ")]);
12881
+ }
12868
12882
  /**
12869
12883
  * Generates the verbose className/style merging pattern.
12870
12884
  */
@@ -12942,6 +12956,20 @@ function buildSxOnlyResult(j, styleArgs, options = {}) {
12942
12956
  styleAttr: null
12943
12957
  };
12944
12958
  }
12959
+ function buildSxWithExternalPropsResult(args) {
12960
+ const { j, styleArgs, classNameId, styleId, allowClassNameProp, allowStyleProp, staticClassNameExpr } = args;
12961
+ return {
12962
+ ...buildSxOnlyResult(j, styleArgs, { normalizeOptionalEntries: true }),
12963
+ classNameAttr: buildClassNameAttributeExpr({
12964
+ j,
12965
+ classNameId,
12966
+ allowClassNameProp,
12967
+ staticClassNameExpr
12968
+ }),
12969
+ styleAttr: allowStyleProp ? styleId : null,
12970
+ externalAttrsBeforeSxProp: true
12971
+ };
12972
+ }
12945
12973
  function flattenSxArrayArgs(j, styleArgs) {
12946
12974
  const sxArgs = [];
12947
12975
  for (const arg of styleArgs) appendSxArrayArg(j, sxArgs, arg);
@@ -13059,7 +13087,7 @@ function isWrappedComponentSxAware(args) {
13059
13087
  const importInfo = importMap?.get(componentLocalName);
13060
13088
  if (!importInfo) {
13061
13089
  const source = readSourceOverride(filePath, sourceOverrides) ?? localSource;
13062
- return source ? computeDetectionFromSource(source, componentLocalName) : false;
13090
+ return source ? computeDetectionFromSource(source, componentLocalName, filePath, sourceOverrides) : false;
13063
13091
  }
13064
13092
  const adapterResult = adapter.wrappedComponentInterface?.({
13065
13093
  localName: componentLocalName,
@@ -13093,7 +13121,7 @@ function resolveWrappedComponentSource(source, filePath) {
13093
13121
  }
13094
13122
  function detectExportedSxProp(absolutePath, componentName, sourceOverrides) {
13095
13123
  const sourceOverride = readSourceOverride(absolutePath, sourceOverrides);
13096
- if (sourceOverride !== void 0) return computeDetectionFromSource(sourceOverride, componentName);
13124
+ if (sourceOverride !== void 0) return computeDetectionFromSource(sourceOverride, componentName, resolveSourcePath(absolutePath) ?? absolutePath, sourceOverrides);
13097
13125
  const cacheKey = `${absolutePath}\u0000${componentName}`;
13098
13126
  const cached = detectionCache.get(cacheKey);
13099
13127
  if (cached !== void 0) return cached;
@@ -13110,21 +13138,33 @@ function computeDetection(absolutePath, componentName) {
13110
13138
  } catch {
13111
13139
  return false;
13112
13140
  }
13113
- return computeDetectionFromSource(source, componentName);
13141
+ return computeDetectionFromSource(source, componentName, resolved);
13114
13142
  }
13115
- function computeDetectionFromSource(source, componentName) {
13116
- if (!source.includes(SX_PROP_NAME) || !source.includes(componentName)) return false;
13117
- let j;
13118
- let root;
13143
+ function computeDetectionFromSource(source, componentName, filePath, sourceOverrides) {
13144
+ if (!source.includes(componentName)) return false;
13145
+ const parsed = parseSource(source);
13146
+ if (!parsed) return false;
13147
+ const { j, root } = parsed;
13148
+ const propsTypeNode = findComponentPropsType(root, componentName);
13149
+ if (!propsTypeNode) return false;
13150
+ return typeMentionsSxMember({
13151
+ j,
13152
+ root,
13153
+ filePath,
13154
+ sourceOverrides,
13155
+ visitedTypeNames: /* @__PURE__ */ new Set()
13156
+ }, propsTypeNode);
13157
+ }
13158
+ function parseSource(source) {
13119
13159
  try {
13120
- j = jscodeshift.withParser("tsx");
13121
- root = j(source);
13160
+ const j = jscodeshift.withParser("tsx");
13161
+ return {
13162
+ j,
13163
+ root: j(source)
13164
+ };
13122
13165
  } catch {
13123
- return false;
13166
+ return null;
13124
13167
  }
13125
- const propsTypeNode = findComponentPropsType(root, componentName);
13126
- if (!propsTypeNode) return false;
13127
- return typeMentionsSxMember(j, root, propsTypeNode, /* @__PURE__ */ new Set());
13128
13168
  }
13129
13169
  function resolveSourcePath(absolutePath) {
13130
13170
  for (const candidate of sourcePathCandidates(absolutePath)) if (existsSync(candidate)) return candidate;
@@ -13173,47 +13213,107 @@ function findComponentPropsType(root, componentName) {
13173
13213
  }
13174
13214
  return propsType;
13175
13215
  }
13176
- /**
13177
- * Walk a TS type AST node and return true iff any reachable member is
13178
- * named `sx`. Resolves type references against same-file
13179
- * `TSTypeAliasDeclaration` / `TSInterfaceDeclaration` declarations.
13180
- *
13181
- * Opaque utility types like `Omit`/`Pick`/`Partial`/`React.ComponentProps`
13182
- * are skipped (we can't peek inside their structural result), which is fine:
13183
- * the convention places `sx` on a sibling literal in the intersection.
13184
- */
13185
- function typeMentionsSxMember(j, root, node, visitedTypeNames) {
13216
+ function typeMentionsSxMember(ctx, node) {
13186
13217
  const n = node;
13187
13218
  switch (n.type) {
13188
13219
  case "TSTypeLiteral": return literalContainsSxMember(n.members);
13189
13220
  case "TSIntersectionType":
13190
13221
  case "TSUnionType":
13191
- for (const member of n.types ?? []) if (typeMentionsSxMember(j, root, member, visitedTypeNames)) return true;
13222
+ for (const member of n.types ?? []) if (typeMentionsSxMember(ctx, member)) return true;
13192
13223
  return false;
13193
- case "TSParenthesizedType": return n.typeAnnotation ? typeMentionsSxMember(j, root, n.typeAnnotation, visitedTypeNames) : false;
13224
+ case "TSParenthesizedType": return n.typeAnnotation ? typeMentionsSxMember(ctx, n.typeAnnotation) : false;
13194
13225
  case "TSTypeReference": {
13195
13226
  const typeName = n.typeName?.name;
13196
- if (!typeName || visitedTypeNames.has(typeName)) return false;
13197
- visitedTypeNames.add(typeName);
13198
- const aliased = root.find(j.TSTypeAliasDeclaration).filter((p) => {
13199
- return p.node.id?.name === typeName;
13200
- });
13201
- if (aliased.size() > 0) {
13202
- const annotation = aliased.get().node.typeAnnotation;
13203
- if (annotation && typeMentionsSxMember(j, root, annotation, visitedTypeNames)) return true;
13204
- }
13205
- const iface = root.find(j.TSInterfaceDeclaration).filter((p) => {
13206
- return p.node.id?.name === typeName;
13207
- });
13208
- if (iface.size() > 0) {
13209
- const body = iface.get().node.body?.body;
13210
- if (literalContainsSxMember(body)) return true;
13211
- }
13212
- return false;
13227
+ return typeName ? typeReferenceMentionsSx(ctx, typeName, { allowImported: false }) : false;
13213
13228
  }
13214
13229
  default: return false;
13215
13230
  }
13216
13231
  }
13232
+ function typeReferenceMentionsSx(ctx, typeName, options) {
13233
+ const visitedKey = `${ctx.filePath ?? "<memory>"}\u0000${typeName}`;
13234
+ if (ctx.visitedTypeNames.has(visitedKey)) return false;
13235
+ ctx.visitedTypeNames.add(visitedKey);
13236
+ const aliased = ctx.root.find(ctx.j.TSTypeAliasDeclaration).filter((p) => {
13237
+ return p.node.id?.name === typeName;
13238
+ });
13239
+ if (aliased.size() > 0) {
13240
+ const annotation = aliased.get().node.typeAnnotation;
13241
+ if (annotation && typeMentionsSxMember(ctx, annotation)) return true;
13242
+ }
13243
+ const iface = ctx.root.find(ctx.j.TSInterfaceDeclaration).filter((p) => {
13244
+ return p.node.id?.name === typeName;
13245
+ });
13246
+ if (iface.size() > 0) {
13247
+ const node = iface.get().node;
13248
+ if (literalContainsSxMember(node.body?.body)) return true;
13249
+ if (interfaceExtendsMentionSx(ctx, node.extends)) return true;
13250
+ }
13251
+ return options.allowImported ? importedTypeReferenceMentionsSx(ctx, typeName) : false;
13252
+ }
13253
+ function interfaceExtendsMentionSx(ctx, heritage) {
13254
+ if (!Array.isArray(heritage)) return false;
13255
+ for (const item of heritage) {
13256
+ const typeName = getHeritageTypeName(item);
13257
+ if (typeName && typeReferenceMentionsSx(ctx, typeName, { allowImported: true })) return true;
13258
+ }
13259
+ return false;
13260
+ }
13261
+ function getHeritageTypeName(node) {
13262
+ if (!node || typeof node !== "object") return null;
13263
+ const n = node;
13264
+ if (n.expression?.type === "Identifier") return n.expression.name ?? null;
13265
+ if (n.typeName?.type === "Identifier") return n.typeName.name ?? null;
13266
+ return null;
13267
+ }
13268
+ function importedTypeReferenceMentionsSx(ctx, localTypeName) {
13269
+ const importInfo = findTypeImport(ctx.root, localTypeName);
13270
+ if (!importInfo || !ctx.filePath) return false;
13271
+ const resolvedPath = moduleResolver.resolve(ctx.filePath, importInfo.source);
13272
+ if (!resolvedPath) return false;
13273
+ const source = readSourceOverride(resolvedPath, ctx.sourceOverrides) ?? readSource(resolvedPath);
13274
+ if (!source) return false;
13275
+ const parsed = parseSource(source);
13276
+ if (!parsed) return false;
13277
+ return typeReferenceMentionsSx({
13278
+ ...ctx,
13279
+ j: parsed.j,
13280
+ root: parsed.root,
13281
+ filePath: resolvedPath
13282
+ }, importInfo.importedName, { allowImported: true });
13283
+ }
13284
+ function findTypeImport(root, localTypeName) {
13285
+ const body = root.get().node.program.body;
13286
+ for (const statement of body) {
13287
+ if (statement.type !== "ImportDeclaration") continue;
13288
+ const source = statement.source.value;
13289
+ if (typeof source !== "string") continue;
13290
+ for (const specifier of statement.specifiers ?? []) {
13291
+ const spec = specifier;
13292
+ if (spec.local?.name !== localTypeName) continue;
13293
+ if (spec.type === "ImportSpecifier") {
13294
+ const importedName = spec.imported?.name ?? (typeof spec.imported?.value === "string" ? spec.imported.value : void 0);
13295
+ return importedName ? {
13296
+ importedName,
13297
+ source
13298
+ } : null;
13299
+ }
13300
+ if (spec.type === "ImportDefaultSpecifier") return {
13301
+ importedName: "default",
13302
+ source
13303
+ };
13304
+ }
13305
+ }
13306
+ return null;
13307
+ }
13308
+ function readSource(absolutePath) {
13309
+ const resolved = resolveSourcePath(absolutePath);
13310
+ if (!resolved) return null;
13311
+ try {
13312
+ return readFileSync(resolved, "utf8");
13313
+ } catch {
13314
+ return null;
13315
+ }
13316
+ }
13217
13317
  function literalContainsSxMember(members) {
13218
13318
  if (!Array.isArray(members)) return false;
13219
13319
  for (const member of members) {
@@ -13224,6 +13324,229 @@ function literalContainsSxMember(members) {
13224
13324
  return false;
13225
13325
  }
13226
13326
  //#endregion
13327
+ //#region src/internal/lower-rules/variants.ts
13328
+ function parseVariantCondition(when) {
13329
+ const trimmed = when.trim();
13330
+ if (trimmed.includes("&&")) return { type: "compound" };
13331
+ if (trimmed.startsWith("!")) {
13332
+ const inner = trimmed.slice(1).trim().replace(/^\(|\)$/g, "");
13333
+ if (/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(inner)) return {
13334
+ type: "boolean",
13335
+ propName: inner,
13336
+ negated: true
13337
+ };
13338
+ return { type: "unknown" };
13339
+ }
13340
+ const eqMatch = trimmed.match(/^([a-zA-Z_$][a-zA-Z0-9_$]*)\s*(===|!==)\s*"([^"]*)"$/);
13341
+ if (eqMatch && eqMatch[1] && eqMatch[2] && eqMatch[3] !== void 0) {
13342
+ const value = eqMatch[3];
13343
+ return {
13344
+ type: "equality",
13345
+ propName: eqMatch[1],
13346
+ operator: eqMatch[2],
13347
+ value,
13348
+ staticValue: value
13349
+ };
13350
+ }
13351
+ const numberMatch = trimmed.match(/^([a-zA-Z_$][a-zA-Z0-9_$]*)\s*(===|!==)\s*(-?(?:0|[1-9]\d*)(?:\.\d+)?)$/);
13352
+ if (numberMatch && numberMatch[1] && numberMatch[2] && numberMatch[3] !== void 0) {
13353
+ const value = Number(numberMatch[3]);
13354
+ if (Number.isFinite(value) && String(value) === numberMatch[3]) return {
13355
+ type: "equality",
13356
+ propName: numberMatch[1],
13357
+ operator: numberMatch[2],
13358
+ value: numberMatch[3],
13359
+ staticValue: value
13360
+ };
13361
+ }
13362
+ if (/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(trimmed)) return {
13363
+ type: "boolean",
13364
+ propName: trimmed,
13365
+ negated: false
13366
+ };
13367
+ return { type: "unknown" };
13368
+ }
13369
+ /**
13370
+ * Extract string literal values from a TypeScript union type.
13371
+ * Returns an array of literal values, or null if the type doesn't contain string literals.
13372
+ */
13373
+ function extractUnionLiteralValues(tsType) {
13374
+ if (!tsType || typeof tsType !== "object") return null;
13375
+ const type = tsType;
13376
+ if (type.type === "TSUnionType" && Array.isArray(type.types)) {
13377
+ const values = [];
13378
+ for (const t of type.types) {
13379
+ const inner = t;
13380
+ if (inner.type === "TSLiteralType" && typeof inner.literal?.value === "string") values.push(inner.literal.value);
13381
+ }
13382
+ return values.length > 0 ? values : null;
13383
+ }
13384
+ if (type.type === "TSLiteralType" && typeof type.literal?.value === "string") return [type.literal.value];
13385
+ return null;
13386
+ }
13387
+ function hasFiniteNumericVariantKey(dimension) {
13388
+ return Object.keys(dimension.variants).some((key) => {
13389
+ if (key === "") return false;
13390
+ const value = Number(key);
13391
+ return Number.isFinite(value) && String(value) === key;
13392
+ });
13393
+ }
13394
+ /**
13395
+ * Groups variant buckets into dimensions for the StyleX variants recipe pattern.
13396
+ *
13397
+ * A dimension is created when:
13398
+ * - Multiple conditions test the same prop with `===` against different string values
13399
+ * - OR a single `===` condition exists (the else branch becomes a default variant)
13400
+ *
13401
+ * Compound conditions (e.g., `disabled && color === "primary"`) are kept separate
13402
+ * and not grouped into dimensions.
13403
+ */
13404
+ function groupVariantBucketsIntoDimensions(variantBuckets, variantStyleKeys, _baseStyleKey, baseStyles, findJsxPropTsType, isJsxPropOptional) {
13405
+ const getVariantObjectName = (propName, suffix) => {
13406
+ if (propName === "variant") return suffix ? `${suffix.toLowerCase()}Variants` : "variants";
13407
+ return suffix ? `${propName}${suffix}Variants` : `${propName}Variants`;
13408
+ };
13409
+ const propGroups = /* @__PURE__ */ new Map();
13410
+ const remainingBuckets = /* @__PURE__ */ new Map();
13411
+ const remainingStyleKeys = {};
13412
+ const propsToStrip = /* @__PURE__ */ new Set();
13413
+ for (const [when, styles] of variantBuckets.entries()) {
13414
+ const parsed = parseVariantCondition(when);
13415
+ if (parsed.type === "equality" && parsed.operator === "===") {
13416
+ const existing = propGroups.get(parsed.propName) ?? [];
13417
+ existing.push({
13418
+ when,
13419
+ value: parsed.value,
13420
+ styles
13421
+ });
13422
+ propGroups.set(parsed.propName, existing);
13423
+ } else {
13424
+ remainingBuckets.set(when, styles);
13425
+ if (variantStyleKeys[when]) remainingStyleKeys[when] = variantStyleKeys[when];
13426
+ }
13427
+ }
13428
+ const dimensions = [];
13429
+ const booleanBuckets = /* @__PURE__ */ new Map();
13430
+ for (const [when, styles] of variantBuckets.entries()) {
13431
+ const parsed = parseVariantCondition(when);
13432
+ if (parsed.type === "boolean" && !parsed.negated) booleanBuckets.set(parsed.propName, {
13433
+ cssProps: new Set(Object.keys(styles)),
13434
+ styles
13435
+ });
13436
+ }
13437
+ let isVariantsRecipePattern = false;
13438
+ for (const [, variants] of propGroups.entries()) {
13439
+ const variantCssProps = new Set(variants.flatMap((v) => Object.keys(v.styles)));
13440
+ for (const [, boolData] of booleanBuckets) {
13441
+ for (const cssProp of variantCssProps) if (boolData.cssProps.has(cssProp)) {
13442
+ isVariantsRecipePattern = true;
13443
+ break;
13444
+ }
13445
+ if (isVariantsRecipePattern) break;
13446
+ }
13447
+ if (isVariantsRecipePattern) break;
13448
+ }
13449
+ for (const [propName, variants] of propGroups.entries()) {
13450
+ const propType = findJsxPropTsType?.(propName);
13451
+ const unionValues = extractUnionLiteralValues(propType);
13452
+ const firstVariant = variants[0];
13453
+ if (variants.length === 1 && firstVariant) {
13454
+ const explicitValue = firstVariant.value;
13455
+ if (isVariantsRecipePattern && unionValues && unionValues.length === 2 && unionValues.includes(explicitValue)) {} else {
13456
+ for (const v of variants) {
13457
+ remainingBuckets.set(v.when, v.styles);
13458
+ const styleKey = variantStyleKeys[v.when];
13459
+ if (styleKey) remainingStyleKeys[v.when] = styleKey;
13460
+ }
13461
+ continue;
13462
+ }
13463
+ }
13464
+ const variantMap = {};
13465
+ const allOverriddenProps = /* @__PURE__ */ new Set();
13466
+ for (const v of variants) {
13467
+ variantMap[v.value] = v.styles;
13468
+ for (const cssProp of Object.keys(v.styles)) allOverriddenProps.add(cssProp);
13469
+ }
13470
+ const defaultStyles = {};
13471
+ for (const cssProp of allOverriddenProps) if (cssProp in baseStyles) defaultStyles[cssProp] = baseStyles[cssProp];
13472
+ let defaultValue;
13473
+ const propIsOptional = isJsxPropOptional?.(propName) ?? false;
13474
+ if (Object.keys(defaultStyles).length > 0 && unionValues) {
13475
+ const explicitValues = new Set(variants.map((v) => v.value));
13476
+ const remainingValues = unionValues.map(String).filter((v) => !explicitValues.has(v));
13477
+ if (remainingValues.length === 1 && remainingValues[0]) {
13478
+ defaultValue = remainingValues[0];
13479
+ variantMap[defaultValue] = defaultStyles;
13480
+ } else {
13481
+ defaultValue = "default";
13482
+ variantMap["default"] = defaultStyles;
13483
+ }
13484
+ }
13485
+ const firstVariantForProps = variants[0];
13486
+ if (!firstVariantForProps) continue;
13487
+ const variantCssProps = new Set(Object.keys(firstVariantForProps.styles));
13488
+ let overlappingBoolProp;
13489
+ let overlappingBoolStyles;
13490
+ for (const [boolProp, boolData] of booleanBuckets) {
13491
+ for (const cssProp of variantCssProps) if (boolData.cssProps.has(cssProp)) {
13492
+ overlappingBoolProp = boolProp;
13493
+ overlappingBoolStyles = boolData.styles;
13494
+ break;
13495
+ }
13496
+ if (overlappingBoolProp) break;
13497
+ }
13498
+ if (overlappingBoolProp && overlappingBoolStyles) {
13499
+ dimensions.push({
13500
+ propName,
13501
+ variantObjectName: getVariantObjectName(propName, "Enabled"),
13502
+ variants: variantMap,
13503
+ defaultValue,
13504
+ namespaceBooleanProp: overlappingBoolProp,
13505
+ isDisabledNamespace: false,
13506
+ isOptional: propIsOptional
13507
+ });
13508
+ const disabledVariantMap = {};
13509
+ for (const [variantValue, variantStyles] of Object.entries(variantMap)) {
13510
+ const merged = { ...variantStyles };
13511
+ for (const [cssProp, boolValue] of Object.entries(overlappingBoolStyles)) {
13512
+ const variantValue2 = merged[cssProp];
13513
+ if (typeof variantValue2 === "object" && variantValue2 !== null && typeof boolValue === "string") merged[cssProp] = {
13514
+ ...variantValue2,
13515
+ default: boolValue
13516
+ };
13517
+ else merged[cssProp] = boolValue;
13518
+ }
13519
+ for (const [cssProp, boolValue] of Object.entries(overlappingBoolStyles)) if (!(cssProp in merged)) merged[cssProp] = boolValue;
13520
+ disabledVariantMap[variantValue] = merged;
13521
+ }
13522
+ dimensions.push({
13523
+ propName,
13524
+ variantObjectName: getVariantObjectName(propName, "Disabled"),
13525
+ variants: disabledVariantMap,
13526
+ defaultValue,
13527
+ namespaceBooleanProp: overlappingBoolProp,
13528
+ isDisabledNamespace: true,
13529
+ isOptional: propIsOptional
13530
+ });
13531
+ remainingBuckets.delete(overlappingBoolProp);
13532
+ delete remainingStyleKeys[overlappingBoolProp];
13533
+ for (const cssProp of variantCssProps) propsToStrip.add(cssProp);
13534
+ } else dimensions.push({
13535
+ propName,
13536
+ variantObjectName: getVariantObjectName(propName),
13537
+ variants: variantMap,
13538
+ defaultValue,
13539
+ isOptional: propIsOptional
13540
+ });
13541
+ }
13542
+ return {
13543
+ dimensions,
13544
+ remainingBuckets,
13545
+ remainingStyleKeys,
13546
+ propsToStrip
13547
+ };
13548
+ }
13549
+ //#endregion
13227
13550
  //#region src/internal/emit-wrappers/type-helpers.ts
13228
13551
  /**
13229
13552
  * Sorts variant style entries by condition specificity.
@@ -13308,7 +13631,7 @@ function buildStaticVariantPropTypes(d) {
13308
13631
  * all others get `keyof typeof <variantObjectName>`.
13309
13632
  */
13310
13633
  function buildVariantDimPropTypeMap(d) {
13311
- return new Map((d.variantDimensions ?? []).filter((dim) => dim.propTypeFromKeyof).map((dim) => {
13634
+ return new Map((d.variantDimensions ?? []).filter((dim) => dim.propTypeFromKeyof || !dim.fallbackFnKey && hasFiniteNumericVariantKey(dim)).map((dim) => {
13312
13635
  const typeText = dim.isBooleanProp ? "boolean" : `keyof typeof ${dim.variantObjectName}`;
13313
13636
  return [dim.propName, typeText];
13314
13637
  }));
@@ -13469,6 +13792,12 @@ function buildAttrsFromAttrsInfo(j, args) {
13469
13792
  ];
13470
13793
  }
13471
13794
  function appendMergingAttrs(j, attrs, merging) {
13795
+ if (merging.externalAttrsBeforeSxProp && merging.sxPropExpr) {
13796
+ if (merging.classNameAttr) attrs.push(j.jsxAttribute(j.jsxIdentifier("className"), j.jsxExpressionContainer(merging.classNameAttr)));
13797
+ if (merging.styleAttr) attrs.push(j.jsxAttribute(j.jsxIdentifier("style"), j.jsxExpressionContainer(merging.styleAttr)));
13798
+ attrs.push(j.jsxAttribute(j.jsxIdentifier("sx"), j.jsxExpressionContainer(merging.sxPropExpr)));
13799
+ return;
13800
+ }
13472
13801
  if (merging.classNameBeforeSpread && merging.classNameAttr) attrs.push(j.jsxAttribute(j.jsxIdentifier("className"), j.jsxExpressionContainer(merging.classNameAttr)));
13473
13802
  if (merging.sxPropExpr) attrs.push(j.jsxAttribute(j.jsxIdentifier("sx"), j.jsxExpressionContainer(merging.sxPropExpr)));
13474
13803
  else if (merging.jsxSpreadExpr) attrs.push(j.jsxSpreadAttribute(merging.jsxSpreadExpr));
@@ -13783,6 +14112,13 @@ function buildVariantDimensionLookups(j, args) {
13783
14112
  });
13784
14113
  else styleArgs.push(expr);
13785
14114
  };
14115
+ const buildFallbackExpr = (dim, propId) => {
14116
+ const castProp = buildKeyofTypeofCast(j, propId, dim.variantObjectName);
14117
+ const lookup = j.memberExpression(j.identifier(dim.variantObjectName), castProp, true);
14118
+ if (!dim.fallbackFnKey) return lookup;
14119
+ const fallbackCall = j.callExpression(styleRef(j, args.stylesIdentifier, dim.fallbackFnKey), [propId]);
14120
+ return j.logicalExpression("??", lookup, fallbackCall);
14121
+ };
13786
14122
  const namespacePairs = /* @__PURE__ */ new Map();
13787
14123
  const regularDimensions = [];
13788
14124
  for (const dim of dimensions) if (dim.namespaceBooleanProp) {
@@ -13808,7 +14144,7 @@ function buildVariantDimensionLookups(j, args) {
13808
14144
  pushExpr(j.logicalExpression("??", lookup, defaultAccess), dim);
13809
14145
  } else {
13810
14146
  if (dim.defaultValue && dim.isOptional && propDefaults) propDefaults.set(dim.propName, dim.defaultValue);
13811
- const lookup = j.memberExpression(variantsId, propId, true);
14147
+ const lookup = dim.fallbackFnKey ? buildFallbackExpr(dim, propId) : j.memberExpression(variantsId, propId, true);
13812
14148
  if (dim.isOptional && !dim.defaultValue) {
13813
14149
  const guard = j.binaryExpression("!=", j.identifier(dim.propName), j.literal(null));
13814
14150
  pushExpr(j.logicalExpression("&&", guard, lookup), dim);
@@ -14218,6 +14554,7 @@ var WrapperEmitter = class {
14218
14554
  jsxCallsitesCache = /* @__PURE__ */ new Map();
14219
14555
  jsxChildrenUsageCache = /* @__PURE__ */ new Map();
14220
14556
  usedAsValueCache = /* @__PURE__ */ new Map();
14557
+ aliasedJsxSpreadUsageCache = /* @__PURE__ */ new Map();
14221
14558
  forwardedAsUsageCache = /* @__PURE__ */ new Map();
14222
14559
  constructor(args) {
14223
14560
  this.root = args.root;
@@ -14357,20 +14694,51 @@ var WrapperEmitter = class {
14357
14694
  this.usedAsValueCache.set(localName, inJsxExpr);
14358
14695
  return inJsxExpr;
14359
14696
  }
14697
+ isUsedAsValue(d) {
14698
+ return Boolean(d.usedAsValue) || this.isUsedAsValueInFile(d.localName);
14699
+ }
14700
+ requiresRestForValueUsage(d) {
14701
+ return this.isUsedAsValueInFile(d.localName) || this.hasAliasedJsxSpreadUsage(d.localName);
14702
+ }
14703
+ hasAliasedJsxSpreadUsage(localName) {
14704
+ const cached = this.aliasedJsxSpreadUsageCache.get(localName);
14705
+ if (cached !== void 0) return cached;
14706
+ const { root, j } = this;
14707
+ const aliasNames = new Set([localName]);
14708
+ let changed = true;
14709
+ while (changed) {
14710
+ changed = false;
14711
+ root.find(j.VariableDeclarator).forEach((p) => {
14712
+ const { id, init } = p.node;
14713
+ if (id.type !== "Identifier" || aliasNames.has(id.name) || !init) return;
14714
+ if (expressionReferencesComponentAlias(init, aliasNames)) {
14715
+ aliasNames.add(id.name);
14716
+ changed = true;
14717
+ }
14718
+ });
14719
+ }
14720
+ aliasNames.delete(localName);
14721
+ const hasSpread = aliasNames.size > 0 && [...aliasNames].some((aliasName) => root.find(j.JSXElement, { openingElement: { name: {
14722
+ type: "JSXIdentifier",
14723
+ name: aliasName
14724
+ } } }).filter((p) => (p.node.openingElement.attributes ?? []).some((attr) => attr.type === "JSXSpreadAttribute")).size() > 0);
14725
+ this.aliasedJsxSpreadUsageCache.set(localName, hasSpread);
14726
+ return hasSpread;
14727
+ }
14360
14728
  /**
14361
14729
  * Decide whether a wrapper component should accept/merge external `className`/`style`.
14362
14730
  */
14363
14731
  shouldAllowClassNameProp(d) {
14364
14732
  if (d.consumerUsesClassName ?? d.supportsExternalStyles) return true;
14365
14733
  if (d.consumerUsesSpread) return true;
14366
- if (d.usedAsValue) return true;
14734
+ if (this.isUsedAsValue(d)) return true;
14367
14735
  const used = this.getUsedAttrs(d.localName);
14368
14736
  return used.has("*") || used.has("className");
14369
14737
  }
14370
14738
  shouldAllowStyleProp(d) {
14371
14739
  if (d.consumerUsesStyle ?? d.supportsExternalStyles) return true;
14372
14740
  if (d.consumerUsesSpread) return true;
14373
- if (d.usedAsValue) return true;
14741
+ if (this.isUsedAsValue(d)) return true;
14374
14742
  const used = this.getUsedAttrs(d.localName);
14375
14743
  return used.has("*") || used.has("style");
14376
14744
  }
@@ -14858,7 +15226,7 @@ var WrapperEmitter = class {
14858
15226
  inferredIntrinsicPropsTypeText(args) {
14859
15227
  const { d, tagName, allowClassNameProp, allowStyleProp, allowSxProp, skipProps, includeRef, forceNarrow } = args;
14860
15228
  const used = this.getUsedAttrs(d.localName);
14861
- const needsBroadAttrs = used.has("*") || !!d.usedAsValue;
15229
+ const needsBroadAttrs = used.has("*") || this.isUsedAsValue(d);
14862
15230
  const lines = [];
14863
15231
  const pickedAttrKeys = [];
14864
15232
  if (!needsBroadAttrs) {
@@ -14898,28 +15266,24 @@ var WrapperEmitter = class {
14898
15266
  }
14899
15267
  const literal = lines.length > 1 ? `{\n ${lines.join(",\n ")}\n}` : lines.length === 1 ? `{ ${lines[0]} }` : "{}";
14900
15268
  const intrinsicBase = `React.ComponentProps<"${tagName}">`;
15269
+ const intrinsicBaseOmitted = [];
15270
+ if (!allowClassNameProp) intrinsicBaseOmitted.push("\"className\"");
15271
+ if (!allowStyleProp) intrinsicBaseOmitted.push("\"style\"");
15272
+ const intrinsicBaseMaybeOmitted = intrinsicBaseOmitted.length ? `Omit<${intrinsicBase}, ${intrinsicBaseOmitted.join(" | ")}>` : intrinsicBase;
14901
15273
  const pickExpr = pickedAttrKeys.length > 0 ? `Pick<${intrinsicBase}, ${pickedAttrKeys.map((k) => `"${k}"`).join(" | ")}>` : void 0;
14902
15274
  if (!needsBroadAttrs) {
14903
15275
  const narrowResult = this.joinIntersection(literal, pickExpr);
14904
15276
  if (forceNarrow) {
14905
- if (hasElementSpecificPicks) return intrinsicBase;
15277
+ if (hasElementSpecificPicks) return intrinsicBaseMaybeOmitted;
14906
15278
  return narrowResult;
14907
15279
  }
14908
15280
  if (VOID_TAGS.has(tagName)) {
14909
- const omittedVoid = [];
14910
- if (!allowClassNameProp) omittedVoid.push("\"className\"");
14911
- if (!allowStyleProp) omittedVoid.push("\"style\"");
14912
- const baseType = omittedVoid.length ? `Omit<${intrinsicBase}, ${omittedVoid.join(" | ")}>` : intrinsicBase;
14913
- if (allowSxProp) return this.joinIntersection(baseType, `{ ${SX_PROP_TYPE_TEXT} }`);
14914
- return baseType;
15281
+ if (allowSxProp) return this.joinIntersection(intrinsicBaseMaybeOmitted, `{ ${SX_PROP_TYPE_TEXT} }`);
15282
+ return intrinsicBaseMaybeOmitted;
14915
15283
  }
14916
15284
  return narrowResult;
14917
15285
  }
14918
- const omitted = [];
14919
- if (!allowClassNameProp) omitted.push("\"className\"");
14920
- if (!allowStyleProp) omitted.push("\"style\"");
14921
- const baseMaybeOmitted = omitted.length ? `Omit<${intrinsicBase}, ${omitted.join(" | ")}>` : intrinsicBase;
14922
- const composed = this.joinIntersection(literal, baseMaybeOmitted);
15286
+ const composed = this.joinIntersection(literal, intrinsicBaseMaybeOmitted);
14923
15287
  return VOID_TAGS.has(tagName) ? composed : this.withChildren(composed);
14924
15288
  }
14925
15289
  /**
@@ -15077,7 +15441,7 @@ var WrapperEmitter = class {
15077
15441
  const isVoidTag = VOID_TAGS.has(tagName);
15078
15442
  const allowForwardedAsProp = this.getUsedAttrs(localName).has("forwardedAs");
15079
15443
  const propsParamId = j.identifier("props");
15080
- const needsPolymorphicTypeParams = this.emitTypes && (allowAsProp || Boolean(inlineTypeText?.includes("<C")));
15444
+ const needsPolymorphicTypeParams = this.emitTypes && (allowAsProp || inlineTypeNeedsElementGeneric(inlineTypeText));
15081
15445
  if (this.emitTypes) if (inlineTypeText) {
15082
15446
  let typeNode = null;
15083
15447
  try {
@@ -15241,7 +15605,10 @@ var WrapperEmitter = class {
15241
15605
  return splitAttrsInfo(this.j, attrsInfo, bridgeClassVar, extraClassNames);
15242
15606
  }
15243
15607
  buildVariantDimensionLookups(args) {
15244
- buildVariantDimensionLookups(this.j, args);
15608
+ buildVariantDimensionLookups(this.j, {
15609
+ ...args,
15610
+ stylesIdentifier: this.stylesIdentifier
15611
+ });
15245
15612
  }
15246
15613
  buildStyleFnExpressions(args) {
15247
15614
  buildStyleFnExpressions(this, args);
@@ -15255,6 +15622,20 @@ const UNIVERSAL_PROP_TYPES = {
15255
15622
  className: "className?: string",
15256
15623
  style: "style?: React.CSSProperties"
15257
15624
  };
15625
+ function inlineTypeNeedsElementGeneric(typeText) {
15626
+ if (!typeText) return false;
15627
+ return /\bReact\.ComponentProps(?:WithRef)?<C\b/.test(typeText) || /\bas\??:\s*C\b/.test(typeText);
15628
+ }
15629
+ function expressionReferencesComponentAlias(node, aliasNames, seen = /* @__PURE__ */ new WeakSet()) {
15630
+ if (!node || typeof node !== "object") return false;
15631
+ if (seen.has(node)) return false;
15632
+ seen.add(node);
15633
+ const maybeNode = node;
15634
+ if (maybeNode.type === "Identifier") return Boolean(maybeNode.name && aliasNames.has(maybeNode.name));
15635
+ if (maybeNode.type === "ConditionalExpression" || maybeNode.type === "LogicalExpression" || maybeNode.type === "SequenceExpression") return Object.values(node).some((child) => expressionReferencesComponentAlias(child, aliasNames, seen));
15636
+ if (maybeNode.type === "TSAsExpression" || maybeNode.type === "TSTypeAssertion" || maybeNode.type === "TSNonNullExpression" || maybeNode.type === "ParenthesizedExpression") return expressionReferencesComponentAlias(node.expression, aliasNames, seen);
15637
+ return false;
15638
+ }
15258
15639
  /**
15259
15640
  * If `typeText` is a simple `{ prop?: type; … }` object literal, returns the
15260
15641
  * individual member strings. Returns `null` for any other shape (Pick, Omit,
@@ -15722,7 +16103,7 @@ function emitComponentWrappers(emitter) {
15722
16103
  } else jsxTagName = j.jsxIdentifier(renderedComponent);
15723
16104
  const { attrsInfo, staticClassNameExpr } = emitter.splitAttrsInfo(d.attrsInfo, getBridgeClassVar(d), d.extraClassNames);
15724
16105
  const defaultAttrs = attrsInfo?.defaultAttrs ?? [];
15725
- const staticAttrs = attrsInfo?.staticAttrs ?? {};
16106
+ const staticAttrs = normalizeStaticForwardedAsAttr(attrsInfo?.staticAttrs ?? {}, shouldLowerForwardedAs);
15726
16107
  const needsSxVar = allowClassNameProp || allowStyleProp || wrappedAcceptsSx || !!d.inlineStyleProps?.length || !!staticClassNameExpr;
15727
16108
  const needsDestructure = destructureProps.length > 0 || needsSxVar || isPolymorphicComponentWrapper || defaultAttrs.length > 0 || shouldLowerForwardedAs || (d.supportsRefProp ?? false);
15728
16109
  const includeChildren = !isPolymorphicComponentWrapper && emitter.hasJsxChildrenUsage(d.localName);
@@ -15777,11 +16158,12 @@ function emitComponentWrappers(emitter) {
15777
16158
  if (needsUseTheme) stmts.push(buildUseThemeDeclaration(j, emitter.themeHookLocalName));
15778
16159
  if (merging.sxDecl) stmts.push(merging.sxDecl);
15779
16160
  const openingAttrs = [];
15780
- const hasStaticForwardedAsFallback = shouldLowerForwardedAs && Object.hasOwn(staticAttrs, "as");
15781
- const staticForwardedAsFallback = hasStaticForwardedAsFallback ? staticAttrs.as : void 0;
16161
+ const staticForwardedAsFallbackKey = shouldLowerForwardedAs && Object.hasOwn(staticAttrs, "as") ? "as" : shouldLowerForwardedAs && Object.hasOwn(staticAttrs, "forwardedAs") ? "forwardedAs" : null;
16162
+ const hasStaticForwardedAsFallback = staticForwardedAsFallbackKey !== null;
16163
+ const staticForwardedAsFallback = hasStaticForwardedAsFallback ? staticAttrs[staticForwardedAsFallbackKey] : void 0;
15782
16164
  const staticAttrsWithoutForwardedAsFallback = (() => {
15783
16165
  if (!hasStaticForwardedAsFallback) return staticAttrs;
15784
- const { as: _omitAs, ...restStaticAttrs } = staticAttrs;
16166
+ const { [staticForwardedAsFallbackKey]: _omitAs, ...restStaticAttrs } = staticAttrs;
15785
16167
  return restStaticAttrs;
15786
16168
  })();
15787
16169
  openingAttrs.push(...emitter.buildDefaultAttrsFromProps({
@@ -15878,6 +16260,15 @@ function emitComponentWrappers(emitter) {
15878
16260
  function shouldKeepStylePropSeparate(componentName) {
15879
16261
  return componentName.startsWith("motion.") || componentName.startsWith("animated.");
15880
16262
  }
16263
+ function normalizeStaticForwardedAsAttr(staticAttrs, shouldLowerForwardedAs) {
16264
+ if (shouldLowerForwardedAs || !Object.hasOwn(staticAttrs, "forwardedAs")) return staticAttrs;
16265
+ const { forwardedAs, ...restStaticAttrs } = staticAttrs;
16266
+ if (Object.hasOwn(restStaticAttrs, "as")) return restStaticAttrs;
16267
+ return {
16268
+ ...restStaticAttrs,
16269
+ as: forwardedAs
16270
+ };
16271
+ }
15881
16272
  function resolveRenderedAsProp(args) {
15882
16273
  const { emitter, fallbackTypeName, propsType } = args;
15883
16274
  if (!propsType) return null;
@@ -16900,7 +17291,7 @@ function emitShouldForwardPropWrappers(ctx) {
16900
17291
  const forwardedAsId = j.identifier("forwardedAs");
16901
17292
  const { hasAny: hasLocalUsage } = emitter.getJsxCallsites(d.localName);
16902
17293
  const shouldIncludeRest = shouldIncludeRestForProps({
16903
- usedAsValue: emitter.isUsedAsValueInFile(d.localName),
17294
+ usedAsValue: emitter.requiresRestForValueUsage(d),
16904
17295
  hasLocalUsage,
16905
17296
  usedAttrs,
16906
17297
  destructureProps: destructureParts,
@@ -17079,6 +17470,8 @@ function emitSimpleWithConfigWrappers(ctx) {
17079
17470
  }) : "{}";
17080
17471
  const typeWithChildren = !explicit && !VOID_TAGS.has(tagName) && !shouldUseIntrinsicProps ? emitter.withChildren(baseTypeText) : baseTypeText;
17081
17472
  const needsElementProps = hasElementPropsInDefaultAttrs(d);
17473
+ const variantDimByProp = buildVariantDimPropTypeMap(d);
17474
+ const variantPropOverrideTypeText = explicit && variantDimByProp.size > 0 ? `{\n${[...variantDimByProp.entries()].map(([propName, typeText]) => ` ${propName}?: ${typeText};`).join("\n")}\n}` : void 0;
17082
17475
  const typeText = (() => {
17083
17476
  if (explicit) {
17084
17477
  if (needsElementProps) {
@@ -17091,9 +17484,9 @@ function emitSimpleWithConfigWrappers(ctx) {
17091
17484
  includeRef: willForwardRef
17092
17485
  });
17093
17486
  ctx.markNeedsReactTypeImport();
17094
- return emitter.joinIntersection(explicit, intrinsicBaseType);
17487
+ return emitter.joinIntersection(explicit, variantPropOverrideTypeText, intrinsicBaseType);
17095
17488
  }
17096
- return explicit;
17489
+ return emitter.joinIntersection(explicit, variantPropOverrideTypeText);
17097
17490
  }
17098
17491
  return typeWithChildren;
17099
17492
  })();
@@ -17328,9 +17721,9 @@ function emitSimpleExportedIntrinsicWrappers(ctx) {
17328
17721
  for (const sbv of d.staticBooleanVariants ?? []) keys.add(sbv.propName);
17329
17722
  const compoundVariantWhenKeys = collectCompoundVariantKeys(d.compoundVariants, { syntheticOnly: true });
17330
17723
  for (const k of compoundVariantWhenKeys) keys.delete(k);
17331
- const filtered = [...keys].filter((k) => k && isValidIdentifierName(k) && k !== "children" && k !== "className" && k !== "style" && k !== "as" && k !== "forwardedAs" && !explicitPropNames.has(k));
17332
- if (filtered.length === 0) return "{}";
17333
17724
  const variantDimByProp = buildVariantDimPropTypeMap(d);
17725
+ const filtered = [...keys].filter((k) => k && isValidIdentifierName(k) && k !== "children" && k !== "className" && k !== "style" && k !== "as" && k !== "forwardedAs" && (!explicitPropNames.has(k) || variantDimByProp.has(k)));
17726
+ if (filtered.length === 0) return "{}";
17334
17727
  const staticVariantPropTypes = buildStaticVariantPropTypes(d);
17335
17728
  return `{\n${filtered.map((k) => {
17336
17729
  const variantType = variantDimByProp.get(k);
@@ -17341,6 +17734,17 @@ function emitSimpleExportedIntrinsicWrappers(ctx) {
17341
17734
  }).join("\n")}\n}`;
17342
17735
  })();
17343
17736
  const sxTypeIntersection = allowSxProp ? `{ ${SX_PROP_TYPE_TEXT} }` : void 0;
17737
+ const explicitBaseText = explicit ? maybeOmitExternalStylePropsFromExplicitTypeText({
17738
+ ctx,
17739
+ propsType: d.propsType,
17740
+ typeText: explicit,
17741
+ allowClassNameProp,
17742
+ allowStyleProp
17743
+ }) : void 0;
17744
+ const explicitTypeIncludesIntrinsicProps = !!d.propsType && explicitTypeMayContainExternalStyleProps({
17745
+ ctx,
17746
+ propsType: d.propsType
17747
+ });
17344
17748
  const typeTextWithForwardedAs = withForwardedAsType((() => {
17345
17749
  if (!explicit) {
17346
17750
  if (useSlimType) {
@@ -17351,16 +17755,16 @@ function emitSimpleExportedIntrinsicWrappers(ctx) {
17351
17755
  return customStyleDrivingPropsTypeText !== "{}" ? emitter.joinIntersection(baseTypeText, customStyleDrivingPropsTypeText) : baseTypeText;
17352
17756
  }
17353
17757
  if (useSlimType) {
17354
- const combined = emitter.joinIntersection(explicit, customStyleDrivingPropsTypeText, baseTypeText, sxTypeIntersection);
17758
+ const combined = emitter.joinIntersection(explicitBaseText, customStyleDrivingPropsTypeText, needsRestForType || explicitTypeIncludesIntrinsicProps ? extendBaseTypeText : baseTypeText, sxTypeIntersection);
17355
17759
  return VOID_TAGS.has(tagName) ? combined : emitter.withChildren(combined);
17356
17760
  }
17357
- if (VOID_TAGS.has(tagName)) return emitter.joinIntersection(explicit, customStyleDrivingPropsTypeText, extendBaseTypeText, sxTypeIntersection);
17761
+ if (VOID_TAGS.has(tagName)) return emitter.joinIntersection(explicitBaseText, customStyleDrivingPropsTypeText, extendBaseTypeText, sxTypeIntersection);
17358
17762
  if (needsRestForType) {
17359
17763
  if (!supportsExternalStyles && canUseSimplePropsType({
17360
17764
  isExported: d.isExported ?? false,
17361
17765
  usedAttrs: usedAttrsForType
17362
17766
  })) return emitter.withChildren(explicit);
17363
- return emitter.joinIntersection(explicit, customStyleDrivingPropsTypeText, extendBaseTypeText, sxTypeIntersection);
17767
+ return emitter.joinIntersection(explicitBaseText, customStyleDrivingPropsTypeText, extendBaseTypeText, sxTypeIntersection);
17364
17768
  }
17365
17769
  if (allowClassNameProp || allowStyleProp) {
17366
17770
  const extras = [];
@@ -17368,9 +17772,9 @@ function emitSimpleExportedIntrinsicWrappers(ctx) {
17368
17772
  if (allowStyleProp) extras.push("style?: React.CSSProperties");
17369
17773
  if (allowSxProp) extras.push(SX_PROP_TYPE_TEXT);
17370
17774
  extras.push("children?: React.ReactNode");
17371
- return emitter.joinIntersection(explicit, `{ ${extras.join("; ")} }`);
17775
+ return emitter.joinIntersection(explicitBaseText, `{ ${extras.join("; ")} }`);
17372
17776
  }
17373
- return emitter.withChildren(explicit);
17777
+ return emitter.withChildren(explicitBaseText ?? explicit);
17374
17778
  })(), includesForwardedAs);
17375
17779
  const hasNoCustomProps = !explicit && customStyleDrivingPropsTypeText === "{}";
17376
17780
  const explicitIsExistingTypeRef = !!emitter.getExplicitTypeNameIfExists(d.propsType);
@@ -17414,7 +17818,7 @@ function emitSimpleExportedIntrinsicWrappers(ctx) {
17414
17818
  }).typeExprText;
17415
17819
  else inlineTypeText = `${emitter.propsTypeNameFor(d.localName)}<C>`;
17416
17820
  else if (explicitIsExistingTypeRef && explicit) if (useSlimType) inlineTypeText = typeTextWithForwardedAs;
17417
- else inlineTypeText = withForwardedAsType(withSimpleAsPropType(emitter.joinIntersection(explicit, extendBaseTypeText, sxTypeIntersection), allowAsProp), includesForwardedAs);
17821
+ else inlineTypeText = withForwardedAsType(withSimpleAsPropType(emitter.joinIntersection(explicitBaseText, extendBaseTypeText, sxTypeIntersection), allowAsProp), includesForwardedAs);
17418
17822
  else inlineTypeText = withSimpleAsPropType(typeTextWithForwardedAs, allowAsProp);
17419
17823
  }
17420
17824
  const destructureProps = [];
@@ -17469,7 +17873,7 @@ function emitSimpleExportedIntrinsicWrappers(ctx) {
17469
17873
  return !destructureProps.includes(n);
17470
17874
  });
17471
17875
  let shouldIncludeRest = shouldIncludeRestForProps({
17472
- usedAsValue: emitter.isUsedAsValueInFile(d.localName),
17876
+ usedAsValue: emitter.requiresRestForValueUsage(d),
17473
17877
  hasLocalUsage,
17474
17878
  usedAttrs,
17475
17879
  destructureProps,
@@ -17629,6 +18033,53 @@ function hasComplementaryVariantPairs(d) {
17629
18033
  for (let i = 0; i < keys.length; i++) for (let k = i + 1; k < keys.length; k++) if (getPositiveWhen(keys[i], keys[k]) !== null) return true;
17630
18034
  return false;
17631
18035
  }
18036
+ function maybeOmitExternalStylePropsFromExplicitTypeText(args) {
18037
+ if (!explicitTypeMayContainExternalStyleProps({
18038
+ ctx: args.ctx,
18039
+ propsType: args.propsType
18040
+ })) return args.typeText;
18041
+ const omitted = [];
18042
+ if (!args.allowClassNameProp) omitted.push("\"className\"");
18043
+ if (!args.allowStyleProp) omitted.push("\"style\"");
18044
+ return omitted.length > 0 ? `Omit<${args.typeText}, ${omitted.join(" | ")}>` : args.typeText;
18045
+ }
18046
+ function explicitTypeMayContainExternalStyleProps(args) {
18047
+ const visit = (node, seen) => {
18048
+ if (!node || typeof node !== "object") return false;
18049
+ const typed = node;
18050
+ if (typed.type === "TSIntersectionType" || typed.type === "TSUnionType") return (typed.types ?? []).some((member) => visit(member, seen));
18051
+ if (typed.type === "TSParenthesizedType") return visit(typed.typeAnnotation, seen);
18052
+ if (typed.type !== "TSTypeReference") return false;
18053
+ if (isReactPropsUtilityType(typed.typeName)) return true;
18054
+ const typeName = getIdentifierTypeName(typed.typeName);
18055
+ if (!typeName || seen.has(typeName)) return false;
18056
+ seen.add(typeName);
18057
+ const typeAlias = args.ctx.emitter.root.find(args.ctx.j.TSTypeAliasDeclaration).filter((path) => path.node.id.name === typeName);
18058
+ if (typeAlias.size() > 0) return visit(typeAlias.get().node.typeAnnotation, seen);
18059
+ const iface = args.ctx.emitter.root.find(args.ctx.j.TSInterfaceDeclaration).filter((path) => path.node.id.name === typeName);
18060
+ if (iface.size() === 0) return false;
18061
+ return (iface.get().node.extends ?? []).some((extended) => visit(extended, seen));
18062
+ };
18063
+ return visit(args.propsType, /* @__PURE__ */ new Set());
18064
+ }
18065
+ function isReactPropsUtilityType(typeName) {
18066
+ const name = getTypeNameText(typeName);
18067
+ return name === "React.ComponentProps" || name === "React.ComponentPropsWithRef" || name === "React.HTMLAttributes" || name === "ComponentProps" || name === "ComponentPropsWithRef" || name === "HTMLAttributes";
18068
+ }
18069
+ function getIdentifierTypeName(typeName) {
18070
+ return typeof typeName === "object" && typeName !== null && typeName.type === "Identifier" ? typeName.name ?? null : null;
18071
+ }
18072
+ function getTypeNameText(typeName) {
18073
+ if (!typeName || typeof typeName !== "object") return null;
18074
+ const node = typeName;
18075
+ if (node.type === "Identifier") return node.name ?? null;
18076
+ if (node.type === "TSQualifiedName") {
18077
+ const left = getTypeNameText(node.left);
18078
+ const right = getTypeNameText(node.right);
18079
+ return left && right ? `${left}.${right}` : null;
18080
+ }
18081
+ return null;
18082
+ }
17632
18083
  function collectPropsUsedOutsideExtraStyleConditionals(j, d) {
17633
18084
  const used = /* @__PURE__ */ new Set();
17634
18085
  const add = (name) => {
@@ -19051,19 +19502,40 @@ function tryResolveConditionalValue(node, ctx) {
19051
19502
  return null;
19052
19503
  }
19053
19504
  const themeInfo = resolveThemeFromMemberExpr(b);
19054
- if (!themeInfo) return null;
19055
- const res = ctx.resolveValue({
19056
- kind: "theme",
19057
- path: themeInfo.path,
19058
- filePath: ctx.filePath,
19059
- loc: getNodeLocStart(b) ?? void 0
19060
- });
19061
- if (!res) return null;
19062
- return {
19063
- usage: expectedUsage,
19064
- expr: res.expr,
19065
- imports: res.imports
19066
- };
19505
+ if (themeInfo) {
19506
+ const res = ctx.resolveValue({
19507
+ kind: "theme",
19508
+ path: themeInfo.path,
19509
+ filePath: ctx.filePath,
19510
+ loc: getNodeLocStart(b) ?? void 0
19511
+ });
19512
+ if (!res) return null;
19513
+ return {
19514
+ usage: expectedUsage,
19515
+ expr: res.expr,
19516
+ imports: res.imports
19517
+ };
19518
+ }
19519
+ const importedInfo = extractRootAndPath(b);
19520
+ if (importedInfo) {
19521
+ const imp = ctx.resolveImport(importedInfo.rootName, importedInfo.rootNode);
19522
+ if (imp) {
19523
+ const res = ctx.resolveValue({
19524
+ kind: "importedValue",
19525
+ importedName: imp.importedName,
19526
+ source: imp.source,
19527
+ path: importedInfo.path.length > 0 ? importedInfo.path.join(".") : void 0,
19528
+ filePath: ctx.filePath,
19529
+ loc: getNodeLocStart(b) ?? void 0
19530
+ });
19531
+ if (res) return {
19532
+ usage: expectedUsage,
19533
+ expr: res.expr,
19534
+ imports: res.imports
19535
+ };
19536
+ }
19537
+ }
19538
+ return null;
19067
19539
  };
19068
19540
  const getBranch = (value) => {
19069
19541
  return branchToExpr(value);
@@ -19911,7 +20383,7 @@ function replaceThemeRefsWithHookVar(expr, paramName, info) {
19911
20383
  * Order matters: more-specific transforms first, then fall back to prop-access emission.
19912
20384
  */
19913
20385
  function resolveDynamicNode(node, ctx) {
19914
- return tryResolveThemeAccess(node, ctx) ?? tryResolveCallExpression(node, ctx) ?? tryResolveArrowFnHelperCallWithThemeArg(node, ctx) ?? tryResolveArrowFnPreservedRuntimeCall(node, ctx) ?? tryResolveArrowFnCallWithConditionalArgs(node, ctx) ?? tryResolveConditionalValue(node, ctx) ?? tryResolveIndexedThemeWithPropFallback(node, ctx) ?? tryResolveConditionalCssBlockTernary(node, ctx) ?? tryResolveConditionalCssBlock(node, ctx) ?? tryResolveArrowFnCallWithSinglePropArg(node, ctx) ?? tryResolveArrowFnCurriedHelperCallWithPropFallback(node, ctx) ?? tryResolveThemeDependentTemplateLiteral(node, ctx) ?? tryResolveStyleFunctionFromTemplateLiteral(node) ?? tryResolveInlineStyleValueForNestedPropAccess(node) ?? tryResolvePropAccess(node) ?? tryResolveConditionalPropStyleFunction(node) ?? tryResolveArrowFnPropExpression(node) ?? tryResolveInlineStyleValueForConditionalExpression(node) ?? tryResolveInlineStyleValueForLogicalExpression(node) ?? tryResolveInlineStyleValueFromArrowFn(node);
20386
+ return tryResolveThemeAccess(node, ctx) ?? tryResolveCallExpression(node, ctx) ?? tryResolveArrowFnHelperCallWithThemeArg(node, ctx) ?? tryResolveArrowFnPreservedRuntimeCall(node, ctx) ?? tryResolveArrowFnCallWithConditionalArgs(node, ctx) ?? tryResolveConditionalValue(node, ctx) ?? tryResolveIndexedThemeWithPropFallback(node, ctx) ?? tryResolveConditionalCssBlockTernary(node, ctx) ?? tryResolveConditionalCssBlock(node, ctx) ?? tryResolveArrowFnCallWithSinglePropArg(node, ctx) ?? tryResolveArrowFnCurriedHelperCallWithPropFallback(node, ctx) ?? tryResolveArrowFnImportedCurriedHelperCallWithPropsArg(node, ctx) ?? tryResolveThemeDependentTemplateLiteral(node, ctx) ?? tryResolveStyleFunctionFromTemplateLiteral(node) ?? tryResolveInlineStyleValueForNestedPropAccess(node) ?? tryResolvePropAccess(node) ?? tryResolveConditionalPropStyleFunction(node) ?? tryResolveArrowFnPropExpression(node) ?? tryResolveInlineStyleValueForConditionalExpression(node) ?? tryResolveInlineStyleValueForLogicalExpression(node) ?? tryResolveInlineStyleValueFromArrowFn(node);
19915
20387
  }
19916
20388
  function tryResolveThemeAccess(node, ctx) {
19917
20389
  const expr = node.expr;
@@ -20260,6 +20732,24 @@ function tryResolveArrowFnCurriedHelperCallWithPropFallback(node, ctx) {
20260
20732
  props
20261
20733
  };
20262
20734
  }
20735
+ function tryResolveArrowFnImportedCurriedHelperCallWithPropsArg(node, ctx) {
20736
+ if (!node.css.property) return null;
20737
+ const expr = node.expr;
20738
+ if (!isArrowFunctionExpression(expr)) return null;
20739
+ const paramName = getArrowFnSingleParamName(expr);
20740
+ if (!paramName) return null;
20741
+ const body = getFunctionBodyExpr(expr);
20742
+ if (!isCallExpressionNode(body)) return null;
20743
+ const outerArgs = body.arguments ?? [];
20744
+ if (outerArgs.length !== 1 || outerArgs[0]?.type !== "Identifier" || outerArgs[0].name !== paramName) return null;
20745
+ const curried = resolveImportedCurriedHelperCall(body, ctx, node.css.property);
20746
+ if (curried?.result.kind === "resolved") return buildResolvedHandlerResult(curried.result.result, node.css.property, {
20747
+ resolveCallContext: curried.result.resolveCallContext,
20748
+ resolveCallResult: curried.result.resolveCallResult
20749
+ });
20750
+ if (curried?.result.kind === "unresolved") return buildUnresolvedHelperResult(curried.innerCall.callee, ctx);
20751
+ return null;
20752
+ }
20263
20753
  /**
20264
20754
  * Attempts to resolve a callee identifier through the adapter's resolveCall hook.
20265
20755
  * Uses `resolveCallOptional` (non-bailing) so that an unhandled helper does NOT
@@ -22917,7 +23407,7 @@ function createCssHelperConditionalHandler(ctx) {
22917
23407
  return entries;
22918
23408
  };
22919
23409
  const wrapValueWithResolvedPseudos = (prop, value, pseudoEntries) => {
22920
- const properties = styleObj[prop] !== void 0 ? [j.property("init", j.identifier("default"), styleValueToExpression(j, styleObj[prop]))] : [];
23410
+ const properties = [j.property("init", j.identifier("default"), styleObj[prop] !== void 0 ? styleValueToExpression(j, styleObj[prop]) : j.literal(null))];
22921
23411
  for (const entry of pseudoEntries) {
22922
23412
  let entryValue = value;
22923
23413
  if (entry.conditionExpr) entryValue = j.objectExpression([j.property("init", j.identifier("default"), j.literal(null)), (() => {
@@ -24657,6 +25147,7 @@ function createDeclProcessingState(state, decl) {
24657
25147
  } });
24658
25148
  const styleFnDecls = /* @__PURE__ */ new Map();
24659
25149
  const attrBuckets = /* @__PURE__ */ new Map();
25150
+ const observedVariantFallbackFns = /* @__PURE__ */ new Map();
24660
25151
  const inlineStyleProps = [];
24661
25152
  const localVarValues = /* @__PURE__ */ new Map();
24662
25153
  const cssHelperPropValues = /* @__PURE__ */ new Map();
@@ -24852,6 +25343,7 @@ function createDeclProcessingState(state, decl) {
24852
25343
  styleFnFromProps,
24853
25344
  styleFnDecls,
24854
25345
  attrBuckets,
25346
+ observedVariantFallbackFns,
24855
25347
  inlineStyleProps,
24856
25348
  localVarValues,
24857
25349
  cssHelperPropValues,
@@ -24903,214 +25395,13 @@ function createDeclProcessingState(state, decl) {
24903
25395
  };
24904
25396
  }
24905
25397
  //#endregion
24906
- //#region src/internal/lower-rules/variants.ts
24907
- function parseVariantCondition(when) {
24908
- const trimmed = when.trim();
24909
- if (trimmed.includes("&&")) return { type: "compound" };
24910
- if (trimmed.startsWith("!")) {
24911
- const inner = trimmed.slice(1).trim().replace(/^\(|\)$/g, "");
24912
- if (/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(inner)) return {
24913
- type: "boolean",
24914
- propName: inner,
24915
- negated: true
24916
- };
24917
- return { type: "unknown" };
24918
- }
24919
- const eqMatch = trimmed.match(/^([a-zA-Z_$][a-zA-Z0-9_$]*)\s*(===|!==)\s*"([^"]*)"$/);
24920
- if (eqMatch && eqMatch[1] && eqMatch[2] && eqMatch[3] !== void 0) return {
24921
- type: "equality",
24922
- propName: eqMatch[1],
24923
- operator: eqMatch[2],
24924
- value: eqMatch[3]
24925
- };
24926
- if (/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(trimmed)) return {
24927
- type: "boolean",
24928
- propName: trimmed,
24929
- negated: false
24930
- };
24931
- return { type: "unknown" };
24932
- }
24933
- /**
24934
- * Extract string literal values from a TypeScript union type.
24935
- * Returns an array of literal values, or null if the type doesn't contain string literals.
24936
- */
24937
- function extractUnionLiteralValues(tsType) {
24938
- if (!tsType || typeof tsType !== "object") return null;
24939
- const type = tsType;
24940
- if (type.type === "TSUnionType" && Array.isArray(type.types)) {
24941
- const values = [];
24942
- for (const t of type.types) {
24943
- const inner = t;
24944
- if (inner.type === "TSLiteralType" && typeof inner.literal?.value === "string") values.push(inner.literal.value);
24945
- }
24946
- return values.length > 0 ? values : null;
24947
- }
24948
- if (type.type === "TSLiteralType" && typeof type.literal?.value === "string") return [type.literal.value];
24949
- return null;
24950
- }
24951
- /**
24952
- * Groups variant buckets into dimensions for the StyleX variants recipe pattern.
24953
- *
24954
- * A dimension is created when:
24955
- * - Multiple conditions test the same prop with `===` against different string values
24956
- * - OR a single `===` condition exists (the else branch becomes a default variant)
24957
- *
24958
- * Compound conditions (e.g., `disabled && color === "primary"`) are kept separate
24959
- * and not grouped into dimensions.
24960
- */
24961
- function groupVariantBucketsIntoDimensions(variantBuckets, variantStyleKeys, _baseStyleKey, baseStyles, findJsxPropTsType, isJsxPropOptional) {
24962
- const getVariantObjectName = (propName, suffix) => {
24963
- if (propName === "variant") return suffix ? `${suffix.toLowerCase()}Variants` : "variants";
24964
- return suffix ? `${propName}${suffix}Variants` : `${propName}Variants`;
24965
- };
24966
- const propGroups = /* @__PURE__ */ new Map();
24967
- const remainingBuckets = /* @__PURE__ */ new Map();
24968
- const remainingStyleKeys = {};
24969
- const propsToStrip = /* @__PURE__ */ new Set();
24970
- for (const [when, styles] of variantBuckets.entries()) {
24971
- const parsed = parseVariantCondition(when);
24972
- if (parsed.type === "equality" && parsed.operator === "===") {
24973
- const existing = propGroups.get(parsed.propName) ?? [];
24974
- existing.push({
24975
- when,
24976
- value: parsed.value,
24977
- styles
24978
- });
24979
- propGroups.set(parsed.propName, existing);
24980
- } else {
24981
- remainingBuckets.set(when, styles);
24982
- if (variantStyleKeys[when]) remainingStyleKeys[when] = variantStyleKeys[when];
24983
- }
24984
- }
24985
- const dimensions = [];
24986
- const booleanBuckets = /* @__PURE__ */ new Map();
24987
- for (const [when, styles] of variantBuckets.entries()) {
24988
- const parsed = parseVariantCondition(when);
24989
- if (parsed.type === "boolean" && !parsed.negated) booleanBuckets.set(parsed.propName, {
24990
- cssProps: new Set(Object.keys(styles)),
24991
- styles
24992
- });
24993
- }
24994
- let isVariantsRecipePattern = false;
24995
- for (const [, variants] of propGroups.entries()) {
24996
- const variantCssProps = new Set(variants.flatMap((v) => Object.keys(v.styles)));
24997
- for (const [, boolData] of booleanBuckets) {
24998
- for (const cssProp of variantCssProps) if (boolData.cssProps.has(cssProp)) {
24999
- isVariantsRecipePattern = true;
25000
- break;
25001
- }
25002
- if (isVariantsRecipePattern) break;
25003
- }
25004
- if (isVariantsRecipePattern) break;
25005
- }
25006
- for (const [propName, variants] of propGroups.entries()) {
25007
- const propType = findJsxPropTsType?.(propName);
25008
- const unionValues = extractUnionLiteralValues(propType);
25009
- const firstVariant = variants[0];
25010
- if (variants.length === 1 && firstVariant) {
25011
- const explicitValue = firstVariant.value;
25012
- if (isVariantsRecipePattern && unionValues && unionValues.length === 2 && unionValues.includes(explicitValue)) {} else {
25013
- for (const v of variants) {
25014
- remainingBuckets.set(v.when, v.styles);
25015
- const styleKey = variantStyleKeys[v.when];
25016
- if (styleKey) remainingStyleKeys[v.when] = styleKey;
25017
- }
25018
- continue;
25019
- }
25020
- }
25021
- const variantMap = {};
25022
- const allOverriddenProps = /* @__PURE__ */ new Set();
25023
- for (const v of variants) {
25024
- variantMap[v.value] = v.styles;
25025
- for (const cssProp of Object.keys(v.styles)) allOverriddenProps.add(cssProp);
25026
- }
25027
- const defaultStyles = {};
25028
- for (const cssProp of allOverriddenProps) if (cssProp in baseStyles) defaultStyles[cssProp] = baseStyles[cssProp];
25029
- let defaultValue;
25030
- const propIsOptional = isJsxPropOptional?.(propName) ?? false;
25031
- if (Object.keys(defaultStyles).length > 0 && unionValues) {
25032
- const explicitValues = new Set(variants.map((v) => v.value));
25033
- const remainingValues = unionValues.filter((v) => !explicitValues.has(v));
25034
- if (remainingValues.length === 1 && remainingValues[0]) {
25035
- defaultValue = remainingValues[0];
25036
- variantMap[defaultValue] = defaultStyles;
25037
- } else {
25038
- defaultValue = "default";
25039
- variantMap["default"] = defaultStyles;
25040
- }
25041
- }
25042
- const firstVariantForProps = variants[0];
25043
- if (!firstVariantForProps) continue;
25044
- const variantCssProps = new Set(Object.keys(firstVariantForProps.styles));
25045
- let overlappingBoolProp;
25046
- let overlappingBoolStyles;
25047
- for (const [boolProp, boolData] of booleanBuckets) {
25048
- for (const cssProp of variantCssProps) if (boolData.cssProps.has(cssProp)) {
25049
- overlappingBoolProp = boolProp;
25050
- overlappingBoolStyles = boolData.styles;
25051
- break;
25052
- }
25053
- if (overlappingBoolProp) break;
25054
- }
25055
- if (overlappingBoolProp && overlappingBoolStyles) {
25056
- dimensions.push({
25057
- propName,
25058
- variantObjectName: getVariantObjectName(propName, "Enabled"),
25059
- variants: variantMap,
25060
- defaultValue,
25061
- namespaceBooleanProp: overlappingBoolProp,
25062
- isDisabledNamespace: false,
25063
- isOptional: propIsOptional
25064
- });
25065
- const disabledVariantMap = {};
25066
- for (const [variantValue, variantStyles] of Object.entries(variantMap)) {
25067
- const merged = { ...variantStyles };
25068
- for (const [cssProp, boolValue] of Object.entries(overlappingBoolStyles)) {
25069
- const variantValue2 = merged[cssProp];
25070
- if (typeof variantValue2 === "object" && variantValue2 !== null && typeof boolValue === "string") merged[cssProp] = {
25071
- ...variantValue2,
25072
- default: boolValue
25073
- };
25074
- else merged[cssProp] = boolValue;
25075
- }
25076
- for (const [cssProp, boolValue] of Object.entries(overlappingBoolStyles)) if (!(cssProp in merged)) merged[cssProp] = boolValue;
25077
- disabledVariantMap[variantValue] = merged;
25078
- }
25079
- dimensions.push({
25080
- propName,
25081
- variantObjectName: getVariantObjectName(propName, "Disabled"),
25082
- variants: disabledVariantMap,
25083
- defaultValue,
25084
- namespaceBooleanProp: overlappingBoolProp,
25085
- isDisabledNamespace: true,
25086
- isOptional: propIsOptional
25087
- });
25088
- remainingBuckets.delete(overlappingBoolProp);
25089
- delete remainingStyleKeys[overlappingBoolProp];
25090
- for (const cssProp of variantCssProps) propsToStrip.add(cssProp);
25091
- } else dimensions.push({
25092
- propName,
25093
- variantObjectName: getVariantObjectName(propName),
25094
- variants: variantMap,
25095
- defaultValue,
25096
- isOptional: propIsOptional
25097
- });
25098
- }
25099
- return {
25100
- dimensions,
25101
- remainingBuckets,
25102
- remainingStyleKeys,
25103
- propsToStrip
25104
- };
25105
- }
25106
- //#endregion
25107
25398
  //#region src/internal/lower-rules/finalize-decl.ts
25108
25399
  /**
25109
25400
  * Finalizes per-declaration style objects after rule processing.
25110
25401
  * Core concepts: merge pseudo/media buckets, rewrite CSS vars, and emit variants.
25111
25402
  */
25112
25403
  function finalizeDeclProcessing(ctx) {
25113
- const { state, decl, styleObj, perPropPseudo, perPropMedia, perPropComputedMedia, nestedSelectors, variantBuckets, variantStyleKeys, variantSourceOrder, extraStyleObjects, styleFnFromProps, styleFnDecls, attrBuckets, inlineStyleProps, localVarValues, cssHelperPropValues } = ctx;
25404
+ const { state, decl, styleObj, perPropPseudo, perPropMedia, perPropComputedMedia, nestedSelectors, variantBuckets, variantStyleKeys, variantSourceOrder, extraStyleObjects, styleFnFromProps, styleFnDecls, attrBuckets, observedVariantFallbackFns, inlineStyleProps, localVarValues, cssHelperPropValues } = ctx;
25114
25405
  const { rewriteCssVarsInStyleObject, rewriteCssVarsInAstNode, relationOverridePseudoBuckets, relationOverrides, ancestorSelectorParents, resolvedStyleObjects, warnings } = state;
25115
25406
  mergeConditionBucket(styleObj, perPropPseudo);
25116
25407
  mergeConditionBucket(styleObj, perPropMedia);
@@ -25159,7 +25450,7 @@ function finalizeDeclProcessing(ctx) {
25159
25450
  }
25160
25451
  for (const bucket of bucketsForVarRewrite) rewriteCssVarsInStyleObject(bucket, localVarValues, varsToDrop);
25161
25452
  for (const name of varsToDrop) for (const bucket of bucketsForVarRewrite) dropCssVariableDefinitionsFromBucket(bucket, name);
25162
- moveUnsafeRawCssVarPropsToInlineStyles({
25453
+ if (decl.base.kind !== "component") moveUnsafeRawCssVarPropsToInlineStyles({
25163
25454
  styleObj,
25164
25455
  inlineStyleProps,
25165
25456
  staticInlineStyleProps,
@@ -25362,6 +25653,11 @@ function finalizeDeclProcessing(ctx) {
25362
25653
  }
25363
25654
  if (minOrder !== void 0) dim.sourceOrder = minOrder;
25364
25655
  }
25656
+ for (const dim of dimensions) {
25657
+ const observedFallbackFnKey = observedVariantFallbackFns.get(dim.propName);
25658
+ if (observedFallbackFnKey) dim.fallbackFnKey = observedFallbackFnKey;
25659
+ if (!observedFallbackFnKey && hasFiniteNumericVariantKey(dim)) dim.propTypeFromKeyof = true;
25660
+ }
25365
25661
  decl.variantDimensions = mergeVariantDimensions(decl.variantDimensions, dimensions);
25366
25662
  decl.needsWrapperComponent = true;
25367
25663
  for (const prop of propsToStrip) delete styleObj[prop];
@@ -27551,7 +27847,7 @@ function emitPseudoMediaStyleFnFromProps(args) {
27551
27847
  //#region src/internal/lower-rules/rule-interpolated-declaration.ts
27552
27848
  function handleInterpolatedDeclaration(args) {
27553
27849
  const { ctx, rule, d, media, pseudos, pseudoElement, attrTarget, resolvedSelectorMedia, applyResolvedPropValue } = args;
27554
- const { state, decl, styleObj, perPropPseudo, variantBuckets, variantStyleKeys, variantSourceOrder, extraStyleObjects, styleFnFromProps, styleFnDecls, inlineStyleProps, cssHelperPropValues, tryHandleMappedFunctionColor, tryHandleLogicalOrDefault, tryHandleConditionalPropCoalesceWithTheme, tryHandleEnumIfChainValue, tryHandleThemeIndexedLookup, handlerContext, componentInfo, tryHandlePropertyTernaryTemplateLiteral, tryHandleCssHelperFunctionSwitchBlock, tryHandleCssHelperConditionalBlock, findJsxPropTsType, findJsxPropTsTypeForVariantExtraction, annotateParamFromJsxProp, applyVariant, notifyResolvedStylesArg } = ctx;
27850
+ 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, applyVariant, notifyResolvedStylesArg } = ctx;
27555
27851
  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;
27556
27852
  const avoidNames = new Set(importMap.keys());
27557
27853
  if (state.bail) return;
@@ -27575,6 +27871,16 @@ function handleInterpolatedDeclaration(args) {
27575
27871
  if (cnExpr) decl.extraClassNames.push({ expr: cnExpr });
27576
27872
  }
27577
27873
  };
27874
+ const getObservedStaticVariantValues = (jsxProp) => {
27875
+ const usage = state.propUsageByComponent.get(decl.localName);
27876
+ if (!usage) return null;
27877
+ const propUsage = usage.props[jsxProp];
27878
+ if (!propUsage || propUsage.values.length < 2) return null;
27879
+ const values = propUsage.values.filter((value) => typeof value === "number");
27880
+ if (values.length !== propUsage.values.length) return null;
27881
+ return values;
27882
+ };
27883
+ const observedNumericCssTextProps = /* @__PURE__ */ new Set();
27578
27884
  const tryHandleMultiSlotRuntimeValue = () => {
27579
27885
  if (!d.property || d.value.kind !== "interpolated") return false;
27580
27886
  const cssProperty = d.property.trim();
@@ -27668,18 +27974,50 @@ function handleInterpolatedDeclaration(args) {
27668
27974
  * and should be skipped in the variant buckets.
27669
27975
  */
27670
27976
  const tryEmitIdentityVariantBuckets = (jsxProp, stylexProp, skipValue) => {
27977
+ const staticParts = getSingleSlotStaticParts(d, decl);
27978
+ if (!staticParts) return false;
27671
27979
  const unionValues = extractUnionLiteralValues(findJsxPropTsTypeForVariantExtraction(jsxProp));
27672
- if (!unionValues || unionValues.length < 2 || unionValues.length > 20) return false;
27673
- for (const value of unionValues) {
27980
+ const observedValues = unionValues ? null : getObservedStaticVariantValues(jsxProp);
27981
+ const hasStaticText = staticParts.prefix !== "" || staticParts.suffix !== "";
27982
+ if (observedValues && getNumericCssEmissionMode(stylexProp) === "cssText" && !hasStaticText) {
27983
+ observedNumericCssTextProps.add(jsxProp);
27984
+ return false;
27985
+ }
27986
+ const values = unionValues ?? observedValues;
27987
+ if (!values || values.length < 2 || values.length > 20) return false;
27988
+ for (const value of values) {
27674
27989
  if (value === skipValue) continue;
27675
27990
  applyVariant({
27676
- when: `${jsxProp} === "${value}"`,
27991
+ when: `${jsxProp} === ${typeof value === "number" ? String(value) : JSON.stringify(value)}`,
27677
27992
  propName: jsxProp
27678
- }, { [stylexProp]: value });
27993
+ }, { [stylexProp]: emitStaticObservedValue(value, stylexProp, observedValues !== null, staticParts) });
27679
27994
  }
27995
+ if (observedValues) observedVariantFallbackFns.set(jsxProp, ensureObservedVariantFallbackFn(jsxProp, stylexProp, staticParts));
27680
27996
  if (jsxProp.startsWith("$")) ensureShouldForwardPropDrop(decl, jsxProp);
27681
27997
  return true;
27682
27998
  };
27999
+ const ensureObservedVariantFallbackFn = (jsxProp, stylexProp, staticParts) => {
28000
+ const normalizedJsxProp = jsxProp.startsWith("$") ? jsxProp.slice(1) : jsxProp;
28001
+ const fnKey = styleKeyWithSuffix(decl.styleKey, normalizedJsxProp);
28002
+ const paramName = cssPropertyToIdentifier(normalizedJsxProp || stylexProp, avoidNames);
28003
+ const valueExpr = buildRuntimeObservedValueExpr(j, stylexProp, j.identifier(paramName), staticParts);
28004
+ const property = j.property("init", makeCssPropKey(j, stylexProp), valueExpr);
28005
+ const existing = styleFnDecls.get(fnKey);
28006
+ if (existing?.type === "ArrowFunctionExpression" && existing.body?.type === "ObjectExpression") {
28007
+ existing.body.properties.push(property);
28008
+ return fnKey;
28009
+ }
28010
+ if (!styleFnDecls.has(fnKey)) {
28011
+ const param = j.identifier(paramName);
28012
+ if (jsxProp !== "__props") annotateParamFromJsxProp(param, jsxProp);
28013
+ const body = j.objectExpression([property]);
28014
+ styleFnDecls.set(fnKey, j.arrowFunctionExpression([param], body));
28015
+ }
28016
+ return fnKey;
28017
+ };
28018
+ const shouldPreserveNumericCssTextForProp = (jsxProp, stylexProp) => {
28019
+ return (observedNumericCssTextProps.has(jsxProp) || isNumberLikeTsType(findJsxPropTsType(jsxProp))) && getNumericCssEmissionMode(stylexProp) === "cssText";
28020
+ };
27683
28021
  const maybeEmitPreservedRuntimeCallOverride = (args) => {
27684
28022
  const { resolveCallResult, originalExpr, loc } = args;
27685
28023
  if (!resolveCallResult || !("preserveRuntimeCall" in resolveCallResult) || !resolveCallResult.preserveRuntimeCall) return "not-requested";
@@ -28932,7 +29270,16 @@ function handleInterpolatedDeclaration(args) {
28932
29270
  const slotParts = parts.filter((p) => p?.kind === "slot");
28933
29271
  if (slotParts.length !== 1) return transformedValue;
28934
29272
  if (slotParts[0].slotId !== slotId) return transformedValue;
28935
- if (!parts.some((p) => p?.kind === "static" && p.value !== "")) return transformedValue;
29273
+ if (!parts.some((p) => p?.kind === "static" && p.value !== "")) {
29274
+ if (shouldPreserveNumericCssTextForProp(jsxProp, out.prop)) return j.templateLiteral([j.templateElement({
29275
+ raw: "",
29276
+ cooked: ""
29277
+ }, false), j.templateElement({
29278
+ raw: "",
29279
+ cooked: ""
29280
+ }, true)], [transformed]);
29281
+ return transformedValue;
29282
+ }
28936
29283
  const quasis = [];
28937
29284
  const exprs = [];
28938
29285
  let q = "";
@@ -29308,11 +29655,86 @@ function tryResolveIndexedThemeForPseudoElement(expr, state) {
29308
29655
  }
29309
29656
  }
29310
29657
  function isEntireInterpolatedValueSingleSlot(d, decl) {
29311
- if (d.value.kind !== "interpolated") return false;
29312
- const parts = d.value.parts ?? [];
29313
- if (parts.length !== 1 || parts[0]?.kind !== "slot") return false;
29314
- return decl.templateExpressions[parts[0].slotId] !== void 0;
29658
+ return getSingleSlotStaticParts(d, decl) !== null;
29659
+ }
29660
+ function getSingleSlotStaticParts(d, decl) {
29661
+ if (d.value.kind !== "interpolated") return null;
29662
+ const slotParts = (d.value.parts ?? []).filter((part) => part.kind === "slot");
29663
+ if (slotParts.length !== 1) return null;
29664
+ const slot = slotParts[0];
29665
+ if (decl.templateExpressions[slot.slotId] === void 0) return null;
29666
+ return extractStaticPartsForDecl(d);
29667
+ }
29668
+ function getNumericCssEmissionMode(stylexProp) {
29669
+ if (stylexProp.startsWith("--")) return "cssText";
29670
+ return UNITLESS_NUMERIC_STYLEX_PROPS.has(stylexProp) ? "stylexNumber" : "cssText";
29671
+ }
29672
+ function emitStaticObservedValue(value, stylexProp, isObservedNumeric, staticParts) {
29673
+ if (typeof value !== "number" || !isObservedNumeric) return value;
29674
+ if (staticParts.prefix || staticParts.suffix) return `${staticParts.prefix}${value}${staticParts.suffix}`;
29675
+ return getNumericCssEmissionMode(stylexProp) === "stylexNumber" ? value : String(value);
29676
+ }
29677
+ function buildRuntimeObservedValueExpr(j, stylexProp, valueExpr, staticParts) {
29678
+ if (getNumericCssEmissionMode(stylexProp) === "stylexNumber" && !staticParts.prefix && !staticParts.suffix) return valueExpr;
29679
+ return j.templateLiteral([j.templateElement({
29680
+ raw: staticParts.prefix,
29681
+ cooked: staticParts.prefix
29682
+ }, false), j.templateElement({
29683
+ raw: staticParts.suffix,
29684
+ cooked: staticParts.suffix
29685
+ }, true)], [valueExpr]);
29315
29686
  }
29687
+ function isNumberLikeTsType(tsType) {
29688
+ if (!tsType || typeof tsType !== "object") return false;
29689
+ const type = tsType;
29690
+ if (type.type === "TSNumberKeyword") return true;
29691
+ if (type.type === "TSLiteralType") return typeof type.literal?.value === "number";
29692
+ if (type.type === "TSUnionType" && Array.isArray(type.types)) return type.types.length > 0 && type.types.every(isNumberLikeTsType);
29693
+ return false;
29694
+ }
29695
+ const UNITLESS_NUMERIC_STYLEX_PROPS = new Set([
29696
+ "animationIterationCount",
29697
+ "aspectRatio",
29698
+ "borderImageOutset",
29699
+ "borderImageSlice",
29700
+ "borderImageWidth",
29701
+ "boxFlex",
29702
+ "boxFlexGroup",
29703
+ "boxOrdinalGroup",
29704
+ "columnCount",
29705
+ "columns",
29706
+ "flex",
29707
+ "flexGrow",
29708
+ "flexPositive",
29709
+ "flexShrink",
29710
+ "flexNegative",
29711
+ "flexOrder",
29712
+ "fontWeight",
29713
+ "gridArea",
29714
+ "gridColumn",
29715
+ "gridColumnEnd",
29716
+ "gridColumnStart",
29717
+ "gridRow",
29718
+ "gridRowEnd",
29719
+ "gridRowStart",
29720
+ "lineClamp",
29721
+ "lineHeight",
29722
+ "opacity",
29723
+ "order",
29724
+ "orphans",
29725
+ "tabSize",
29726
+ "widows",
29727
+ "zIndex",
29728
+ "zoom",
29729
+ "fillOpacity",
29730
+ "floodOpacity",
29731
+ "stopOpacity",
29732
+ "strokeDasharray",
29733
+ "strokeDashoffset",
29734
+ "strokeMiterlimit",
29735
+ "strokeOpacity",
29736
+ "strokeWidth"
29737
+ ]);
29316
29738
  function buildFullInterpolatedDeclarationValueExpr(j, decl, d) {
29317
29739
  if (d.value.kind !== "interpolated") return null;
29318
29740
  const parts = d.value.parts ?? [];
@@ -30557,6 +30979,15 @@ function processDeclRules(ctx) {
30557
30979
  }
30558
30980
  continue;
30559
30981
  }
30982
+ if (hasEnabledCompoundPseudoSelector(s)) {
30983
+ state.markBail();
30984
+ warnings.push({
30985
+ severity: "warning",
30986
+ type: "Unsupported selector: compound pseudo selector",
30987
+ loc: computeSelectorWarningLoc(decl.loc, decl.rawCss, rule.selector)
30988
+ });
30989
+ break;
30990
+ }
30560
30991
  const selectorTrimmed = selectorForAnalysis.trim();
30561
30992
  const isHandledComponentPattern = hasComponentExpr && (/^__SC_EXPR_\d+__:[a-z][a-z0-9()-]*\s+&\s*$/.test(selectorTrimmed) || isCommaGroupedReverseSelectorPattern(selectorTrimmed) || /^__SC_EXPR_\d+__\s+&\s*$/.test(selectorTrimmed) || selectorTrimmed.startsWith("&") || /^__SC_EXPR_\d+__\s*\{/.test(selectorTrimmed) || /^__SC_EXPR_\d+__:[a-z][a-z0-9()-]*\s*[+~]\s*&\s*$/.test(selectorTrimmed) || HAS_COMPONENT_SELECTOR_STRICT_RE.test(selectorTrimmed));
30562
30993
  if (/&\s+:/.test(rule.selector)) {
@@ -30970,6 +31401,15 @@ function processDeclRules(ctx) {
30970
31401
  const pseudos = parsedSelector.kind === "pseudo" ? parsedSelector.pseudos : parsedSelector.kind === "pseudoElementWithPseudo" ? parsedSelector.pseudos : null;
30971
31402
  const pseudoElement = parsedSelector.kind === "pseudoElement" ? parsedSelector.element : parsedSelector.kind === "pseudoElementWithPseudo" ? parsedSelector.element : null;
30972
31403
  const pseudoElementsList = parsedSelector.kind === "pseudoElements" ? parsedSelector.elements : null;
31404
+ if ((pseudoElement ? [pseudoElement] : pseudoElementsList)?.some((pe) => !isStylexCompilerPseudoElement(pe))) {
31405
+ state.markBail();
31406
+ warnings.push({
31407
+ severity: "warning",
31408
+ type: "Unsupported selector: unsupported pseudo-element",
31409
+ loc: computeSelectorWarningLoc(decl.loc, decl.rawCss, rule.selector)
31410
+ });
31411
+ break;
31412
+ }
30973
31413
  const attrSel = parsedSelector.kind === "attribute" ? {
30974
31414
  kind: parsedSelector.attr.type,
30975
31415
  suffix: parsedSelector.attr.suffix,
@@ -31530,9 +31970,29 @@ function tryResolveInterpolatedPseudo(slotExpr, rule, ctx, prefixPseudo) {
31530
31970
  if (prefixPseudo) return "bail";
31531
31971
  return handlePseudoAlias(selectorResult, rule, ctx);
31532
31972
  }
31533
- if (selectorResult.kind === "pseudoExpand") return handlePseudoExpand(selectorResult, imp.importedName, rule, ctx, prefixPseudo);
31973
+ if (selectorResult.kind === "pseudoExpand") {
31974
+ if (prefixPseudo && containsPseudoToken(prefixPseudo, "enabled")) return "bail";
31975
+ return handlePseudoExpand(selectorResult, imp.importedName, rule, ctx, prefixPseudo);
31976
+ }
31534
31977
  return "bail";
31535
31978
  }
31979
+ function hasEnabledCompoundPseudoSelector(selector) {
31980
+ return selector.split(",").some((part) => {
31981
+ const trimmed = part.trim();
31982
+ if (!trimmed.startsWith("&")) return false;
31983
+ const pseudoTokens = extractPseudoTokens(trimmed);
31984
+ return pseudoTokens.includes("enabled") && pseudoTokens.length > 1;
31985
+ });
31986
+ }
31987
+ function isStylexCompilerPseudoElement(selector) {
31988
+ return selector.startsWith("::");
31989
+ }
31990
+ function containsPseudoToken(selector, token) {
31991
+ return extractPseudoTokens(selector).includes(token);
31992
+ }
31993
+ function extractPseudoTokens(selector) {
31994
+ return [...selector.matchAll(/:(?!:)([a-zA-Z][a-zA-Z0-9-]*)/g)].map((match) => match[1]).filter((value) => value !== void 0);
31995
+ }
31536
31996
  /**
31537
31997
  * Handles `pseudoAlias` result: builds N extra style objects (one per pseudo value)
31538
31998
  * and registers them on `decl.pseudoAliasSelectors` for the emit phase.
@@ -32382,6 +32842,7 @@ function createLowerRulesState(ctx) {
32382
32842
  j
32383
32843
  });
32384
32844
  const enumValueMap = buildEnumValueMap(root, j);
32845
+ const propUsageByComponent = collectPropUsageByComponent(ctx, styledDecls);
32385
32846
  const crossFileSelectorsByLocal = /* @__PURE__ */ new Map();
32386
32847
  if (ctx.crossFileSelectorUsages) for (const usage of ctx.crossFileSelectorUsages) crossFileSelectorsByLocal.set(usage.localName, usage);
32387
32848
  const state = {
@@ -32437,6 +32898,7 @@ function createLowerRulesState(ctx) {
32437
32898
  isIdentifierShadowed,
32438
32899
  enumValueMap,
32439
32900
  crossFileSelectorsByLocal,
32901
+ propUsageByComponent,
32440
32902
  inlineKeyframeNameMap: void 0,
32441
32903
  /**
32442
32904
  * File-level bail flag. Used only for bails that cannot be scoped to a single
@@ -32470,6 +32932,74 @@ function createLowerRulesState(ctx) {
32470
32932
  };
32471
32933
  return state;
32472
32934
  }
32935
+ function collectPropUsageByComponent(ctx, styledDecls) {
32936
+ const byComponent = clonePropUsageByComponent(ctx.propUsageByComponent);
32937
+ const localNames = new Set(styledDecls.map((decl) => decl.localName));
32938
+ const recordOpening = (opening) => {
32939
+ if (!opening || typeof opening !== "object") return;
32940
+ const openingRecord = opening;
32941
+ const name = getJsxIdentifierName(openingRecord.name);
32942
+ if (!name || !localNames.has(name)) return;
32943
+ const usage = collectOpeningPropUsage(openingRecord.attributes);
32944
+ let info = byComponent.get(name);
32945
+ if (!info) {
32946
+ info = createComponentPropUsageInfo(name);
32947
+ byComponent.set(name, info);
32948
+ }
32949
+ mergeComponentPropUsage(info, usage);
32950
+ };
32951
+ ctx.root.find(ctx.j.JSXElement).forEach((path) => {
32952
+ recordOpening(path.node.openingElement);
32953
+ });
32954
+ ctx.root.find(ctx.j.JSXSelfClosingElement).forEach((path) => {
32955
+ recordOpening(path.node);
32956
+ });
32957
+ return byComponent;
32958
+ }
32959
+ function clonePropUsageByComponent(source) {
32960
+ const cloned = /* @__PURE__ */ new Map();
32961
+ for (const [name, info] of source ?? []) cloned.set(name, {
32962
+ componentName: info.componentName,
32963
+ usageCount: info.usageCount,
32964
+ hasUnknownUsage: info.hasUnknownUsage,
32965
+ props: Object.fromEntries(Object.entries(info.props).map(([propName, propInfo]) => [propName, {
32966
+ values: [...propInfo.values],
32967
+ hasUnknown: propInfo.hasUnknown,
32968
+ usageCount: propInfo.usageCount,
32969
+ omittedCount: propInfo.omittedCount
32970
+ }]))
32971
+ });
32972
+ return cloned;
32973
+ }
32974
+ function collectOpeningPropUsage(attributes) {
32975
+ const props = {};
32976
+ let hasSpread = false;
32977
+ for (const attr of attributes ?? []) {
32978
+ if (!attr || typeof attr !== "object") continue;
32979
+ const attrRecord = attr;
32980
+ if (attrRecord.type === "JSXSpreadAttribute") {
32981
+ hasSpread = true;
32982
+ continue;
32983
+ }
32984
+ if (attrRecord.type !== "JSXAttribute") continue;
32985
+ const propName = getJsxIdentifierName(attrRecord.name);
32986
+ if (!propName || KNOWN_NON_ELEMENT_PROPS.has(propName)) continue;
32987
+ const value = readStaticJsxLiteral(attr);
32988
+ props[propName] = value === void 0 ? { kind: "unknown" } : {
32989
+ kind: "static",
32990
+ value
32991
+ };
32992
+ }
32993
+ return {
32994
+ props,
32995
+ hasSpread
32996
+ };
32997
+ }
32998
+ function getJsxIdentifierName(node) {
32999
+ if (!node || typeof node !== "object") return null;
33000
+ const record = node;
33001
+ return record.type === "JSXIdentifier" && typeof record.name === "string" ? record.name : null;
33002
+ }
32473
33003
  //#endregion
32474
33004
  //#region src/internal/transform-steps/lower-rules.ts
32475
33005
  /**
@@ -34289,13 +34819,16 @@ function extractCrossFileInfoForFile(filePath, options) {
34289
34819
  const absPath = resolveToPrepassKey(filePath, prepass);
34290
34820
  const selectorUsages = prepass.selectorUsages.get(absPath);
34291
34821
  const bridgeComponentNames = prepass.componentsNeedingGlobalSelectorBridge?.get(absPath);
34822
+ const propUsageByComponent = prepass.propUsageByFile?.get(absPath);
34292
34823
  const hasStyledDefFiles = prepass.styledDefFiles && prepass.styledDefFiles.size > 0;
34824
+ const hasPropUsage = propUsageByComponent && propUsageByComponent.size > 0;
34293
34825
  const hasGlobalLeafKeys = prepass.globalLeafKeys && prepass.globalLeafKeys.size > 0;
34294
34826
  const hasTransformedFiles = prepass.transformedFiles !== void 0;
34295
- if ((!selectorUsages || selectorUsages.length === 0) && !bridgeComponentNames && !hasStyledDefFiles && !hasGlobalLeafKeys && !hasTransformedFiles) return options;
34827
+ if ((!selectorUsages || selectorUsages.length === 0) && !bridgeComponentNames && !hasPropUsage && !hasStyledDefFiles && !hasGlobalLeafKeys && !hasTransformedFiles) return options;
34296
34828
  const crossFileInfo = {
34297
34829
  selectorUsages: selectorUsages ?? [],
34298
34830
  bridgeComponentNames,
34831
+ propUsageByComponent,
34299
34832
  styledDefFiles: prepass.styledDefFiles,
34300
34833
  globalLeafKeys: prepass.globalLeafKeys,
34301
34834
  transformedFiles: prepass.transformedFiles
@@ -34313,7 +34846,7 @@ function extractCrossFileInfoForFile(filePath, options) {
34313
34846
  */
34314
34847
  function resolveToPrepassKey(filePath, prepass) {
34315
34848
  const resolved = resolve(filePath);
34316
- if (prepass.selectorUsages.has(resolved) || prepass.componentsNeedingGlobalSelectorBridge?.has(resolved)) return resolved;
34849
+ if (prepass.selectorUsages.has(resolved) || prepass.componentsNeedingGlobalSelectorBridge?.has(resolved) || prepass.propUsageByFile?.has(resolved)) return resolved;
34317
34850
  try {
34318
34851
  const real = realpathSync(resolved);
34319
34852
  if (real !== resolved) return real;