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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,10 +1,11 @@
1
- import { t as createModuleResolver } from "./resolve-imports-BlxKezSJ.mjs";
1
+ import { t as createModuleResolver } from "./resolve-imports-DgSAddIF.mjs";
2
2
  import { a as assertValidAdapter, i as isDirectionalResult, n as DEFAULT_THEME_HOOK, t as mergeMarkerDeclarations } from "./merge-markers-BC5YNB7D.mjs";
3
- import { a as Logger, i as resolveBarrelReExport, r as findImportSource } from "./extract-external-interface-CdHbvfxu.mjs";
3
+ import { i as getReExportedSourceName, o as resolveBarrelReExportBinding, r as findImportSource, s as Logger, t as fileExports } from "./extract-external-interface-DbzIPO0Z.mjs";
4
4
  import { n as toRealPath, t as isRelativeSpecifier } from "./path-utils-BIpoL4Ue.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";
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$1 } from "./string-utils-DD9wdRHW.mjs";
6
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
+ import { createRequire } from "node:module";
8
9
  import jscodeshift from "jscodeshift";
9
10
  import { basename, dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
10
11
  import { existsSync, readFileSync, realpathSync } from "node:fs";
@@ -749,23 +750,21 @@ function rewriteCssVarsInStringImpl(args) {
749
750
  */
750
751
  function extractRootAndPath(node) {
751
752
  if (!node || typeof node !== "object") return null;
752
- const typed = node;
753
753
  if (isIdentifierNode(node)) return {
754
754
  rootName: node.name,
755
755
  rootNode: node,
756
756
  path: []
757
757
  };
758
- if (typed.type !== "MemberExpression" && typed.type !== "OptionalMemberExpression") return null;
758
+ if (!isMemberExpressionNode(node)) return null;
759
759
  const parts = [];
760
760
  let cur = node;
761
761
  while (cur && typeof cur === "object") {
762
- const curTyped = cur;
763
- if (curTyped.type !== "MemberExpression" && curTyped.type !== "OptionalMemberExpression") break;
764
- if (curTyped.computed) return null;
765
- const prop = curTyped.property;
762
+ if (!isMemberExpressionNode(cur)) break;
763
+ if (cur.computed) return null;
764
+ const prop = cur.property;
766
765
  if (!isIdentifierNode(prop)) return null;
767
766
  parts.unshift(prop.name);
768
- cur = curTyped.object;
767
+ cur = cur.object;
769
768
  }
770
769
  if (!cur || typeof cur !== "object") return null;
771
770
  if (!isIdentifierNode(cur)) return null;
@@ -849,6 +848,26 @@ function isIdentifierNode(node) {
849
848
  function isCallExpressionNode(node) {
850
849
  return !!node && typeof node === "object" && node.type === "CallExpression";
851
850
  }
851
+ /** Type guard for `MemberExpression` and `OptionalMemberExpression` nodes. */
852
+ function isMemberExpressionNode(node) {
853
+ if (!node || typeof node !== "object") return false;
854
+ const type = node.type;
855
+ return type === "MemberExpression" || type === "OptionalMemberExpression";
856
+ }
857
+ /**
858
+ * Reads `object.property` when both sides are identifiers and the property is
859
+ * non-optional and non-computed. Returns null for optional/computed paths the
860
+ * caller cannot safely treat as a static member reference.
861
+ */
862
+ function getIdentifierMemberPropertyName(node, objectName) {
863
+ if (!isMemberExpressionNode(node) || node.type !== "MemberExpression" || node.computed) return null;
864
+ if (!isIdentifierNode(node.object) || node.object.name !== objectName) return null;
865
+ return isIdentifierNode(node.property) ? node.property.name : null;
866
+ }
867
+ /** Matches a static `objectName.propertyName` member reference. */
868
+ function isIdentifierMemberExpression(node, objectName, propertyName) {
869
+ return getIdentifierMemberPropertyName(node, objectName) === propertyName;
870
+ }
852
871
  /**
853
872
  * Type guard for AstPath objects (jscodeshift path wrappers).
854
873
  */
@@ -1312,7 +1331,7 @@ function isLogicalExpressionNode(node) {
1312
1331
  * responsible for re-wrapping the resolved value with the original fallback.
1313
1332
  */
1314
1333
  function unwrapLogicalFallback(expr) {
1315
- if (isLogicalExpressionNode(expr) && (expr.operator === "??" || expr.operator === "||") && isMemberOrOptionalMemberExpression(expr.left)) return expr.left;
1334
+ if (isLogicalExpressionNode(expr) && (expr.operator === "??" || expr.operator === "||") && isMemberExpressionNode(expr.left)) return expr.left;
1316
1335
  return null;
1317
1336
  }
1318
1337
  /**
@@ -1364,11 +1383,6 @@ function isJsxIdentifierNode(node) {
1364
1383
  const typed = node;
1365
1384
  return typed.type === "JSXIdentifier" && typeof typed.name === "string";
1366
1385
  }
1367
- function isMemberOrOptionalMemberExpression(node) {
1368
- if (!node || typeof node !== "object") return false;
1369
- const t = node.type;
1370
- return t === "MemberExpression" || t === "OptionalMemberExpression";
1371
- }
1372
1386
  /** Allow `void 0`, `void null`, `void ""`, `void 1`, `void false` as empty. */
1373
1387
  function isTriviallyPureVoidArg(arg) {
1374
1388
  if (!arg || typeof arg !== "object") return false;
@@ -2155,6 +2169,8 @@ var TransformContext = class {
2155
2169
  ancestorAttrsByStyleKey;
2156
2170
  /** Adjacent-sibling selectors (`& + &`) deferred for same-file JSX adjacency analysis. */
2157
2171
  deferredAdjacentSiblingWarnings;
2172
+ /** Same-file element-selector overrides deferred for local JSX topology proof. */
2173
+ deferredLocalElementWarnings;
2158
2174
  /** Sidecar .stylex.ts files (defineMarker declarations), populated by emitStylesStep */
2159
2175
  sidecarFiles;
2160
2176
  /** Bridge components emitted for unconverted consumer selectors. */
@@ -2692,6 +2708,116 @@ function canDowngradeStyleFnIntrinsicWrapper(decl, exportedComponents, extendedB
2692
2708
  return true;
2693
2709
  }
2694
2710
  //#endregion
2711
+ //#region src/internal/analyze-before-emit/exported-components.ts
2712
+ function collectExportedComponents(root, j, declByLocal) {
2713
+ const exportedComponents = /* @__PURE__ */ new Map();
2714
+ root.find(j.ExportNamedDeclaration).forEach((p) => {
2715
+ const decl = p.node.declaration;
2716
+ if (decl?.type === "VariableDeclaration") for (const d of decl.declarations) {
2717
+ if (d.type !== "VariableDeclarator") continue;
2718
+ const name = getIdentifierName(d.id);
2719
+ if (name && declByLocal.has(name)) exportedComponents.set(name, {
2720
+ exportName: name,
2721
+ isDefault: false,
2722
+ isSpecifier: false
2723
+ });
2724
+ }
2725
+ for (const spec of p.node.specifiers ?? []) {
2726
+ if (spec.type !== "ExportSpecifier") continue;
2727
+ const localName = getIdentifierName(spec.local);
2728
+ if (localName && declByLocal.has(localName)) {
2729
+ const exportName = getIdentifierName(spec.exported) ?? localName;
2730
+ exportedComponents.set(localName, {
2731
+ exportName,
2732
+ isDefault: false,
2733
+ isSpecifier: true
2734
+ });
2735
+ }
2736
+ }
2737
+ });
2738
+ collectDottedExportedComponents(root, j, declByLocal, exportedComponents);
2739
+ root.find(j.ExportDefaultDeclaration).forEach((p) => {
2740
+ const name = getIdentifierName(p.node.declaration);
2741
+ if (name && declByLocal.has(name)) exportedComponents.set(name, {
2742
+ exportName: "default",
2743
+ isDefault: true,
2744
+ isSpecifier: false
2745
+ });
2746
+ });
2747
+ return exportedComponents;
2748
+ }
2749
+ function collectDottedExportedComponents(root, j, declByLocal, exportedComponents) {
2750
+ const setDottedExport = (localName, exportName) => {
2751
+ if (!declByLocal.has(localName)) return;
2752
+ const existing = exportedComponents.get(localName)?.exportName;
2753
+ if (existing && existing.split(".").length > exportName.split(".").length) return;
2754
+ exportedComponents.set(localName, {
2755
+ exportName,
2756
+ isDefault: false,
2757
+ isSpecifier: false
2758
+ });
2759
+ };
2760
+ const collectObjectProperties = (objectExpression, prefix) => {
2761
+ const objectNode = objectExpression;
2762
+ if (objectNode?.type !== "ObjectExpression" || !Array.isArray(objectNode.properties)) return;
2763
+ for (const property of objectNode.properties) {
2764
+ if (property?.type !== "Property" && property?.type !== "ObjectProperty") continue;
2765
+ const keyName = getIdentifierName(property.key);
2766
+ if (!keyName) continue;
2767
+ const valueName = getIdentifierName(property.value);
2768
+ if (valueName) {
2769
+ setDottedExport(valueName, `${prefix}.${keyName}`);
2770
+ continue;
2771
+ }
2772
+ collectObjectProperties(property.value, `${prefix}.${keyName}`);
2773
+ }
2774
+ };
2775
+ root.find(j.ExportNamedDeclaration).forEach((p) => {
2776
+ const declaration = p.node.declaration;
2777
+ if (declaration?.type !== "VariableDeclaration") return;
2778
+ for (const declarator of declaration.declarations) {
2779
+ if (declarator.type !== "VariableDeclarator") continue;
2780
+ const exportName = getIdentifierName(declarator.id);
2781
+ if (exportName) collectObjectProperties(declarator.init, exportName);
2782
+ }
2783
+ });
2784
+ const collectNamespaceExports = (node, namespacePath) => {
2785
+ const current = node;
2786
+ if (!current) return;
2787
+ if (current.type === "TSModuleDeclaration") {
2788
+ const namespaceName = getIdentifierName(current.id);
2789
+ if (!namespaceName) return;
2790
+ const nextPath = [...namespacePath, namespaceName];
2791
+ if (current.body?.type === "TSModuleBlock") for (const statement of current.body.body ?? []) collectNamespaceExports(statement, nextPath);
2792
+ else collectNamespaceExports(current.body, nextPath);
2793
+ return;
2794
+ }
2795
+ if (current.type !== "ExportNamedDeclaration") return;
2796
+ const declaration = current.declaration;
2797
+ if (!declaration) return;
2798
+ if (declaration.type === "TSModuleDeclaration") {
2799
+ collectNamespaceExports(declaration, namespacePath);
2800
+ return;
2801
+ }
2802
+ if (declaration.type === "FunctionDeclaration") {
2803
+ const localName = getIdentifierName(declaration.id);
2804
+ if (localName) setDottedExport(localName, [...namespacePath, localName].join("."));
2805
+ return;
2806
+ }
2807
+ if (declaration.type === "VariableDeclaration" && Array.isArray(declaration.declarations)) for (const declarator of declaration.declarations) {
2808
+ const localName = getIdentifierName(declarator.id);
2809
+ if (localName) setDottedExport(localName, [...namespacePath, localName].join("."));
2810
+ }
2811
+ };
2812
+ root.find(j.TSModuleDeclaration).forEach((p) => {
2813
+ collectNamespaceExports(p.node, []);
2814
+ });
2815
+ }
2816
+ function getIdentifierName(node) {
2817
+ const n = node;
2818
+ return n?.type === "Identifier" && n.name ? n.name : null;
2819
+ }
2820
+ //#endregion
2695
2821
  //#region src/internal/utilities/bridge-classname.ts
2696
2822
  /**
2697
2823
  * Utilities for generating deterministic bridge classNames and export names.
@@ -2757,7 +2883,7 @@ function parseVariantWhenToAst(j, when, booleanProps) {
2757
2883
  const buildMemberExpr = (raw) => {
2758
2884
  if (!raw.includes(".")) return null;
2759
2885
  const parts = raw.split(".").map((part) => part.trim()).filter(Boolean);
2760
- if (parts.length < 2 || parts.some((part) => !isValidIdentifierName(part))) return null;
2886
+ if (parts.length < 2 || parts.some((part) => !isValidIdentifierName$1(part))) return null;
2761
2887
  return parts.slice(1).reduce((acc, part) => j.memberExpression(acc, j.identifier(part)), j.identifier(parts[0]));
2762
2888
  };
2763
2889
  const parsePropRef = (raw) => {
@@ -2769,14 +2895,14 @@ function parseVariantWhenToAst(j, when, booleanProps) {
2769
2895
  if (trimmedRaw.includes(".")) {
2770
2896
  const parts = trimmedRaw.split(".").map((part) => part.trim()).filter(Boolean);
2771
2897
  const last = parts[parts.length - 1];
2772
- if (!last || !isValidIdentifierName(last)) return {
2898
+ if (!last || !isValidIdentifierName$1(last)) return {
2773
2899
  propName: null,
2774
2900
  expr: j.identifier(trimmedRaw)
2775
2901
  };
2776
2902
  const root = parts[0];
2777
2903
  if (root === "props" || root === "p") {
2778
2904
  const propRoot = parts[1];
2779
- if (!propRoot || !isValidIdentifierName(propRoot)) return {
2905
+ if (!propRoot || !isValidIdentifierName$1(propRoot)) return {
2780
2906
  propName: null,
2781
2907
  expr: j.identifier(trimmedRaw)
2782
2908
  };
@@ -3625,7 +3751,7 @@ function registerImports(imports, resolverImports) {
3625
3751
  }
3626
3752
  /** Returns true if the AST node is a `MemberExpression` or `OptionalMemberExpression`. */
3627
3753
  function isMemberExpression(node) {
3628
- return node?.type === "MemberExpression" || node?.type === "OptionalMemberExpression";
3754
+ return isMemberExpressionNode(node);
3629
3755
  }
3630
3756
  /** Returns true for at-rules the codemod can transform (`@media`, `@container`). */
3631
3757
  function isSupportedAtRule(atRule) {
@@ -3936,6 +4062,255 @@ function collectInlineStylePropNames(inlineStyleProps) {
3936
4062
  return [...names];
3937
4063
  }
3938
4064
  //#endregion
4065
+ //#region src/internal/lower-rules/shared.ts
4066
+ function findPlaceholderBlock(rawCss, placeholder) {
4067
+ let searchFrom = 0;
4068
+ while (true) {
4069
+ const start = rawCss.indexOf(placeholder, searchFrom);
4070
+ if (start < 0) return null;
4071
+ const blockOpen = readNextNonWhitespace(rawCss, start + placeholder.length);
4072
+ if (blockOpen?.value !== "{") {
4073
+ searchFrom = start + placeholder.length;
4074
+ continue;
4075
+ }
4076
+ return {
4077
+ start,
4078
+ end: blockOpen.index
4079
+ };
4080
+ }
4081
+ }
4082
+ function findPreviousOpeningBraceBeforeSelector(rawCss, position) {
4083
+ let depth = 0;
4084
+ for (let i = position - 1; i >= 0; i--) {
4085
+ const ch = rawCss[i];
4086
+ if (ch === ";") continue;
4087
+ if (ch === "}") {
4088
+ depth++;
4089
+ continue;
4090
+ }
4091
+ if (ch === "{") {
4092
+ if (depth > 0) {
4093
+ depth--;
4094
+ continue;
4095
+ }
4096
+ return i;
4097
+ }
4098
+ }
4099
+ return null;
4100
+ }
4101
+ function readSelectorBeforeBlock(rawCss, blockStart) {
4102
+ let selectorStart = blockStart - 1;
4103
+ while (selectorStart >= 0) {
4104
+ const ch = rawCss[selectorStart];
4105
+ if (ch === "}" || ch === "{" || ch === ";") break;
4106
+ selectorStart--;
4107
+ }
4108
+ return rawCss.slice(selectorStart + 1, blockStart).trim();
4109
+ }
4110
+ function readPrefixSinceLastBlockBoundary(rawCss, position) {
4111
+ let start = position - 1;
4112
+ while (start >= 0) {
4113
+ const ch = rawCss[start];
4114
+ if (ch === "{" || ch === "}") break;
4115
+ start--;
4116
+ }
4117
+ return rawCss.slice(start + 1, position);
4118
+ }
4119
+ function parseSimpleParentPseudoSelectorList(selectorText) {
4120
+ const parts = selectorText.split(",").map((part) => part.trim()).filter(Boolean);
4121
+ if (parts.length === 0) return null;
4122
+ const pseudos = [];
4123
+ for (const part of parts) {
4124
+ const match = part.match(/^&(:[a-z-]+(?:\([^)]*\))?)$/i);
4125
+ if (!match?.[1]) return null;
4126
+ pseudos.push(match[1]);
4127
+ }
4128
+ return pseudos;
4129
+ }
4130
+ /**
4131
+ * Builds a `stylex.when.ancestor(pseudo, marker?)` AST call expression.
4132
+ */
4133
+ function makeAncestorKeyExpr(j, pseudo, markerVarName) {
4134
+ const callArgs = [j.literal(pseudo)];
4135
+ if (markerVarName) callArgs.push(j.identifier(markerVarName));
4136
+ return j.callExpression(j.memberExpression(j.memberExpression(j.identifier("stylex"), j.identifier("when")), j.identifier("ancestor")), callArgs);
4137
+ }
4138
+ /**
4139
+ * Builds a `stylex.when.descendant(":is(*)", marker)` AST call expression.
4140
+ * Used for `&:has(${Component})` selectors where styles apply to self
4141
+ * when a descendant matching the marker is present.
4142
+ * Uses `:is(*)` as a required pseudo argument (StyleX API mandates a pseudo string).
4143
+ */
4144
+ function makeDescendantKeyExpr(j, markerVarName) {
4145
+ return j.callExpression(j.memberExpression(j.memberExpression(j.identifier("stylex"), j.identifier("when")), j.identifier("descendant")), [j.literal(":is(*)"), j.identifier(markerVarName)]);
4146
+ }
4147
+ /**
4148
+ * Creates an AST key node for a CSS property name.
4149
+ * For CSS variables (e.g., --component-width), returns a string literal.
4150
+ * For regular property names (e.g., backgroundColor), returns an identifier.
4151
+ */
4152
+ function makeCssPropKey(j, prop) {
4153
+ if (!prop.match(/^[a-zA-Z_$][a-zA-Z0-9_$]*$/)) return j.literal(prop);
4154
+ return j.identifier(prop);
4155
+ }
4156
+ /**
4157
+ * Converts a CSS property name to a valid JavaScript identifier.
4158
+ * For CSS variables (e.g., --component-width), converts to camelCase (componentWidth).
4159
+ * For regular property names (e.g., backgroundColor), returns as-is.
4160
+ *
4161
+ * When `avoidNames` is provided, appends "Value" to the result if it would
4162
+ * conflict with an existing binding (e.g., a top-level import). This prevents
4163
+ * `no-shadow` lint errors when the generated identifier becomes a function
4164
+ * parameter name.
4165
+ */
4166
+ function cssPropertyToIdentifier(prop, avoidNames) {
4167
+ let name;
4168
+ if (prop.startsWith("--")) name = prop.slice(2).replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
4169
+ else name = prop;
4170
+ if (avoidNames?.has(name)) return `${name}Value`;
4171
+ return name;
4172
+ }
4173
+ /**
4174
+ * Get or create a pseudo bucket for a relation override style key.
4175
+ * Registers the override in `relationOverrides` if not already present.
4176
+ */
4177
+ function getOrCreateRelationOverrideBucket(overrideStyleKey, parentStyleKey, childStyleKey, ancestorPseudo, relationOverrides, relationOverridePseudoBuckets, childExtraStyleKeys) {
4178
+ if (!relationOverridePseudoBuckets.has(overrideStyleKey)) relationOverrides.push({
4179
+ parentStyleKey,
4180
+ childStyleKey,
4181
+ overrideStyleKey,
4182
+ childExtraStyleKeys
4183
+ });
4184
+ else if (childExtraStyleKeys?.length) {
4185
+ const existing = relationOverrides.find((o) => o.overrideStyleKey === overrideStyleKey);
4186
+ if (existing && !existing.childExtraStyleKeys?.length) existing.childExtraStyleKeys = childExtraStyleKeys;
4187
+ }
4188
+ let pseudoBuckets = relationOverridePseudoBuckets.get(overrideStyleKey);
4189
+ if (!pseudoBuckets) {
4190
+ pseudoBuckets = /* @__PURE__ */ new Map();
4191
+ relationOverridePseudoBuckets.set(overrideStyleKey, pseudoBuckets);
4192
+ }
4193
+ let bucket = pseudoBuckets.get(ancestorPseudo);
4194
+ if (!bucket) {
4195
+ bucket = {};
4196
+ pseudoBuckets.set(ancestorPseudo, bucket);
4197
+ }
4198
+ return bucket;
4199
+ }
4200
+ function readNextNonWhitespace(rawCss, position) {
4201
+ for (let i = position; i < rawCss.length; i++) {
4202
+ const ch = rawCss[i];
4203
+ if (!/\s/.test(ch)) return {
4204
+ index: i,
4205
+ value: ch
4206
+ };
4207
+ }
4208
+ return null;
4209
+ }
4210
+ /**
4211
+ * Creates an object property for a CSS property with shorthand support.
4212
+ * Uses shorthand ({ color }) for regular properties when key matches value,
4213
+ * but never for CSS variables (which need string literal keys).
4214
+ */
4215
+ function makeCssProperty(j, cssProp, valueIdentifierName) {
4216
+ const key = makeCssPropKey(j, cssProp);
4217
+ const p = j.property("init", key, j.identifier(valueIdentifierName));
4218
+ if (key.type === "Identifier" && key.name === valueIdentifierName) p.shorthand = true;
4219
+ return p;
4220
+ }
4221
+ //#endregion
4222
+ //#region src/internal/lower-rules/relation-overrides.ts
4223
+ const finalizeRelationOverrides = (args) => {
4224
+ const { j, relationOverridePseudoBuckets, relationOverrides, resolvedStyleObjects, makeCssPropKey, childPseudoMarkers } = args;
4225
+ if (relationOverridePseudoBuckets.size === 0) return;
4226
+ const overrideToChildKeys = /* @__PURE__ */ new Map();
4227
+ const overrideToMarker = /* @__PURE__ */ new Map();
4228
+ for (const o of relationOverrides) {
4229
+ overrideToChildKeys.set(o.overrideStyleKey, [o.childStyleKey, ...o.childExtraStyleKeys ?? []]);
4230
+ if (o.markerVarName) overrideToMarker.set(o.overrideStyleKey, o.markerVarName);
4231
+ }
4232
+ for (const [overrideKey, pseudoBuckets] of relationOverridePseudoBuckets.entries()) {
4233
+ const props = buildRelationOverrideProperties({
4234
+ j,
4235
+ pseudoBuckets,
4236
+ childStyleObjects: buildChildStyleObjectList(overrideToChildKeys.get(overrideKey) ?? [], resolvedStyleObjects),
4237
+ makeCssPropKey,
4238
+ childPseudos: childPseudoMarkers.get(overrideKey),
4239
+ markerVarName: overrideToMarker.get(overrideKey)
4240
+ });
4241
+ if (props.length > 0) resolvedStyleObjects.set(overrideKey, j.objectExpression(props));
4242
+ }
4243
+ };
4244
+ function buildRelationOverrideProperties(args) {
4245
+ const { j, pseudoBuckets, childStyleObjects = [], makeCssPropKey, childPseudos, markerVarName } = args;
4246
+ const props = [];
4247
+ const baseBucket = pseudoBuckets.get(null) ?? {};
4248
+ const isExpressionNode = (v) => isAstNode(v);
4249
+ const allPropNames = /* @__PURE__ */ new Set();
4250
+ for (const bucket of pseudoBuckets.values()) for (const prop of Object.keys(bucket)) allPropNames.add(prop);
4251
+ for (const prop of allPropNames) {
4252
+ let baseVal = baseBucket[prop];
4253
+ if (baseVal === void 0) for (const childStyle of childStyleObjects) {
4254
+ const val = childStyle[prop];
4255
+ if (val !== void 0) {
4256
+ baseVal = val;
4257
+ break;
4258
+ }
4259
+ }
4260
+ baseVal = extractScalarDefault$1(baseVal);
4261
+ const pseudoValues = [];
4262
+ for (const [pseudo, bucket] of pseudoBuckets.entries()) {
4263
+ if (pseudo === null) continue;
4264
+ const val = bucket[prop];
4265
+ if (val !== void 0) pseudoValues.push({
4266
+ pseudo,
4267
+ value: val
4268
+ });
4269
+ }
4270
+ if (pseudoValues.length > 0) {
4271
+ const objProps = [j.property("init", j.identifier("default"), isExpressionNode(baseVal) ? baseVal : literalToAst(j, baseVal ?? null))];
4272
+ for (const { pseudo, value } of pseudoValues) {
4273
+ const valExpr = isExpressionNode(value) ? value : literalToAst(j, value);
4274
+ if (childPseudos?.has(pseudo)) objProps.push(j.property("init", j.literal(pseudo), valExpr));
4275
+ else {
4276
+ const ancestorKey = makeAncestorKeyExpr(j, pseudo, markerVarName);
4277
+ const propNode = Object.assign(j.property("init", ancestorKey, valExpr), { computed: true });
4278
+ objProps.push(propNode);
4279
+ }
4280
+ }
4281
+ props.push(j.property("init", makeCssPropKey(j, prop), j.objectExpression(objProps)));
4282
+ } else if (baseVal !== void 0) props.push(j.property("init", makeCssPropKey(j, prop), isExpressionNode(baseVal) ? baseVal : literalToAst(j, baseVal)));
4283
+ }
4284
+ return props;
4285
+ }
4286
+ /**
4287
+ * If a value is a pseudo/media map (e.g., `{ default: "gray", ":focus": "orange" }`),
4288
+ * extracts its scalar `default` property. AST nodes and non-map values pass through.
4289
+ */
4290
+ function extractScalarDefault$1(value) {
4291
+ if (!value || typeof value !== "object" || Array.isArray(value) || isAstNode(value)) {
4292
+ if (isAstNode(value) && value.type === "ObjectExpression") {
4293
+ const objectExpression = value;
4294
+ for (const property of objectExpression.properties ?? []) {
4295
+ if (property.type !== "Property") continue;
4296
+ if ((property.key?.type === "Identifier" ? property.key.name : property.key?.type === "Literal" || property.key?.type === "StringLiteral" ? String(property.key.value) : null) === "default") return property.value;
4297
+ }
4298
+ }
4299
+ return value;
4300
+ }
4301
+ const map = value;
4302
+ if ("default" in map) return map.default;
4303
+ return value;
4304
+ }
4305
+ function buildChildStyleObjectList(childKeys, resolvedStyleObjects) {
4306
+ const childStyleObjects = [];
4307
+ for (const key of childKeys) {
4308
+ const obj = resolvedStyleObjects.get(key);
4309
+ if (obj && typeof obj === "object" && !isAstNode(obj)) childStyleObjects.push(obj);
4310
+ }
4311
+ return childStyleObjects;
4312
+ }
4313
+ //#endregion
3939
4314
  //#region src/internal/transform-steps/analyze-before-emit.ts
3940
4315
  const INLINE_USAGE_THRESHOLD = 1;
3941
4316
  /**
@@ -3959,44 +4334,7 @@ function analyzeBeforeEmitStep(ctx) {
3959
4334
  }
3960
4335
  ctx.declByLocal = declByLocal;
3961
4336
  ctx.extendedBy = extendedBy;
3962
- const getIdentifierName = (node) => {
3963
- const n = node;
3964
- return n?.type === "Identifier" && n.name ? n.name : null;
3965
- };
3966
- const exportedComponents = /* @__PURE__ */ new Map();
3967
- root.find(j.ExportNamedDeclaration).forEach((p) => {
3968
- const decl = p.node.declaration;
3969
- if (decl?.type === "VariableDeclaration") for (const d of decl.declarations) {
3970
- if (d.type !== "VariableDeclarator") continue;
3971
- const name = getIdentifierName(d.id);
3972
- if (name && declByLocal.has(name)) exportedComponents.set(name, {
3973
- exportName: name,
3974
- isDefault: false,
3975
- isSpecifier: false
3976
- });
3977
- }
3978
- for (const spec of p.node.specifiers ?? []) {
3979
- if (spec.type !== "ExportSpecifier") continue;
3980
- const localName = getIdentifierName(spec.local);
3981
- if (localName && declByLocal.has(localName)) {
3982
- const exportName = getIdentifierName(spec.exported) ?? localName;
3983
- exportedComponents.set(localName, {
3984
- exportName,
3985
- isDefault: false,
3986
- isSpecifier: true
3987
- });
3988
- }
3989
- }
3990
- });
3991
- collectDottedExportedComponents(root, j, declByLocal, exportedComponents);
3992
- root.find(j.ExportDefaultDeclaration).forEach((p) => {
3993
- const name = getIdentifierName(p.node.declaration);
3994
- if (name && declByLocal.has(name)) exportedComponents.set(name, {
3995
- exportName: "default",
3996
- isDefault: true,
3997
- isSpecifier: false
3998
- });
3999
- });
4337
+ const exportedComponents = collectExportedComponents(root, j, declByLocal);
4000
4338
  for (const decl of styledDecls) decl.isExported = exportedComponents.has(decl.localName);
4001
4339
  ctx.exportedComponents = exportedComponents;
4002
4340
  const componentsWithStaticProps = /* @__PURE__ */ new Set();
@@ -4016,11 +4354,12 @@ function analyzeBeforeEmitStep(ctx) {
4016
4354
  if (decl.base.kind === "component") {
4017
4355
  const baseDecl = declByLocal.get(decl.base.ident);
4018
4356
  if (baseDecl?.attrsInfo) decl.attrsInfo = mergeInheritedAttrsInfo(baseDecl.attrsInfo, decl.attrsInfo);
4019
- if (decl.attrsInfo && ((decl.attrsInfo.defaultAttrs?.length ?? 0) > 0 || Object.keys(decl.attrsInfo.staticAttrs ?? {}).length > 0 || (decl.attrsInfo.attrsDynamicStyles?.length ?? 0) > 0 || decl.attrsInfo.attrsStaticStyles && Object.keys(decl.attrsInfo.attrsStaticStyles).length > 0)) decl.needsWrapperComponent = true;
4357
+ if (decl.attrsInfo && ((decl.attrsInfo.defaultAttrs?.length ?? 0) > 0 || (decl.attrsInfo.dynamicAttrs?.length ?? 0) > 0 || Object.keys(decl.attrsInfo.staticAttrs ?? {}).length > 0 || !!decl.attrsInfo.attrsStaticStyleExpr || (decl.attrsInfo.attrsDynamicStyles?.length ?? 0) > 0 || decl.attrsInfo.attrsStaticStyles && Object.keys(decl.attrsInfo.attrsStaticStyles).length > 0)) decl.needsWrapperComponent = true;
4020
4358
  }
4021
4359
  const hadWrapperBeforePrepass = decl.needsWrapperComponent;
4022
4360
  if (decl.base.kind === "intrinsic" && (decl.attrsInfo?.conditionalAttrs?.length ?? 0) > 0) decl.needsWrapperComponent = true;
4023
4361
  if (decl.base.kind === "intrinsic" && (decl.attrsInfo?.defaultAttrs?.length ?? 0) > 0) decl.needsWrapperComponent = true;
4362
+ if (decl.base.kind === "intrinsic" && (decl.attrsInfo?.dynamicAttrs?.length ?? 0) > 0) decl.needsWrapperComponent = true;
4024
4363
  const resolverOnlyShouldForwardProp = !!decl.inlinedBaseComponent && !decl.shouldForwardPropFromWithConfig;
4025
4364
  if (decl.shouldForwardProp && !resolverOnlyShouldForwardProp) decl.needsWrapperComponent = true;
4026
4365
  if (decl.base.kind === "intrinsic" && decl.withConfig?.componentId) decl.needsWrapperComponent = true;
@@ -4030,7 +4369,7 @@ function analyzeBeforeEmitStep(ctx) {
4030
4369
  if (!hadWrapperBeforePrepass && decl.needsWrapperComponent) wrapperForcedByPrepass.add(decl.localName);
4031
4370
  if (ctx.bridgeComponentNames?.has(decl.localName) || ctx.bridgeComponentNames?.has("default") && exportedComponents.get(decl.localName)?.isDefault) decl.bridgeClassName = generateBridgeClassName(resolve(file.path), decl.localName);
4032
4371
  }
4033
- for (const decl of styledDecls) if (decl.needsWrapperComponent && !wrapperForcedByPrepass.has(decl.localName) && !decl.isCssHelper && !decl.isDirectJsxResolution && decl.base.kind === "intrinsic" && !decl.bridgeClassName && !decl.attrWrapper && (decl.styleFnFromProps ?? []).length === 0 && !decl.needsUseThemeHook?.length && Object.keys(decl.variantStyleKeys ?? {}).length === 0 && !decl.enumVariant && !decl.inlineStyleProps?.length && (decl.attrsInfo?.conditionalAttrs?.length ?? 0) === 0 && (decl.attrsInfo?.defaultAttrs?.length ?? 0) === 0 && (decl.attrsInfo?.invertedBoolAttrs?.length ?? 0) === 0 && !(decl.extraStylexPropsArgs ?? []).some((arg) => arg.when) && ((decl.extraStylexPropsArgs ?? []).length > 0 || (decl.extraStyleKeys ?? []).length > 0 || (decl.extraClassNames ?? []).length > 0)) decl.needsWrapperComponent = false;
4372
+ for (const decl of styledDecls) if (decl.needsWrapperComponent && !wrapperForcedByPrepass.has(decl.localName) && !decl.isCssHelper && !decl.isDirectJsxResolution && decl.base.kind === "intrinsic" && !decl.bridgeClassName && !decl.attrWrapper && (decl.styleFnFromProps ?? []).length === 0 && !decl.needsUseThemeHook?.length && Object.keys(decl.variantStyleKeys ?? {}).length === 0 && !decl.enumVariant && !decl.inlineStyleProps?.length && (decl.attrsInfo?.conditionalAttrs?.length ?? 0) === 0 && (decl.attrsInfo?.defaultAttrs?.length ?? 0) === 0 && (decl.attrsInfo?.dynamicAttrs?.length ?? 0) === 0 && (decl.attrsInfo?.invertedBoolAttrs?.length ?? 0) === 0 && !(decl.extraStylexPropsArgs ?? []).some((arg) => arg.when) && ((decl.extraStylexPropsArgs ?? []).length > 0 || (decl.extraStyleKeys ?? []).length > 0 || (decl.extraClassNames ?? []).length > 0)) decl.needsWrapperComponent = false;
4034
4373
  for (const decl of styledDecls) {
4035
4374
  if (!canDowngradeStyleFnOnlyWrapper(decl, wrapperForcedByPrepass)) continue;
4036
4375
  decl.needsWrapperComponent = false;
@@ -4057,6 +4396,7 @@ function analyzeBeforeEmitStep(ctx) {
4057
4396
  if (decl.attrsInfo) {
4058
4397
  if (decl.attrsInfo.conditionalAttrs?.length) return false;
4059
4398
  if (decl.attrsInfo.defaultAttrs?.length) return false;
4399
+ if (decl.attrsInfo.dynamicAttrs?.length) return false;
4060
4400
  if (decl.attrsInfo.invertedBoolAttrs?.length) return false;
4061
4401
  }
4062
4402
  return true;
@@ -4114,6 +4454,24 @@ function analyzeBeforeEmitStep(ctx) {
4114
4454
  ref: foundRef
4115
4455
  };
4116
4456
  };
4457
+ const isInlineableLocalElementTarget = (targetDecl) => {
4458
+ const { className, style, ref } = getJsxAttributeUsage(targetDecl.localName);
4459
+ return targetDecl.base.kind === "intrinsic" && !targetDecl.isExported && !targetDecl.needsWrapperComponent && !className && !style && !ref && !hasSpreadInJsx(root, j, targetDecl.localName);
4460
+ };
4461
+ const hasNonJsxComponentValueReference = (name) => root.find(j.Identifier, { name }).filter((p) => {
4462
+ if (p.parentPath?.node?.type === "VariableDeclarator" && p.parentPath.node.id === p.node) return false;
4463
+ if (p.parentPath?.node?.type === "JSXOpeningElement" || p.parentPath?.node?.type === "JSXClosingElement") return false;
4464
+ if (p.parentPath?.node?.type === "JSXMemberExpression" && p.parentPath.node.object === p.node) return false;
4465
+ if (p.parentPath?.node?.type === "CallExpression") {
4466
+ const callee = p.parentPath.node.callee;
4467
+ if (callee?.type === "Identifier" && callee.name === ctx.styledDefaultImport) return false;
4468
+ if (callee?.type === "MemberExpression" && callee.object?.type === "CallExpression" && callee.object.callee?.type === "Identifier" && callee.object.callee.name === ctx.styledDefaultImport) return false;
4469
+ }
4470
+ if (p.parentPath?.node?.type === "TaggedTemplateExpression") return false;
4471
+ if (p.parentPath?.node?.type === "CallExpression" && p.parentPath.parentPath?.node?.type === "TaggedTemplateExpression") return false;
4472
+ if (p.parentPath?.node?.type === "TemplateLiteral") return false;
4473
+ return true;
4474
+ }).size() > 0;
4117
4475
  for (const decl of styledDecls) {
4118
4476
  if (!decl.adjacentSiblingStyleKey) continue;
4119
4477
  const { className, style, ref } = getJsxAttributeUsage(decl.localName);
@@ -4130,7 +4488,22 @@ function analyzeBeforeEmitStep(ctx) {
4130
4488
  warnings: ctx.warnings
4131
4489
  }, "bail");
4132
4490
  }
4491
+ const reservedStyleKeys = collectReservedStyleKeys(ctx.resolvedStyleObjects ?? /* @__PURE__ */ new Map(), styledDecls);
4492
+ const usedLocalElementStyleKeys = /* @__PURE__ */ new Set();
4493
+ const localElementTargetStyleKeys = /* @__PURE__ */ new Set();
4494
+ const localElementProofs = /* @__PURE__ */ new Map();
4495
+ for (const decl of styledDecls) {
4496
+ if (!decl.localElementOverrides?.length) continue;
4497
+ const { className, style, ref } = getJsxAttributeUsage(decl.localName);
4498
+ const proof = proveLocalElementOverrideUsages(root, j, decl.localName, decl.localElementOverrides, declByLocal);
4499
+ const unsupportedReason = decl.isExported ? "exported-parent" : decl.base.kind !== "intrinsic" || decl.needsWrapperComponent || className || style || ref || extendedBy.has(decl.localName) || hasNonJsxComponentValueReference(decl.localName) || hasSpreadInJsx(root, j, decl.localName) ? "dynamic" : proof.safe ? "none" : proof.reason;
4500
+ localElementProofs.set(decl.localName, {
4501
+ proof,
4502
+ unsupportedReason
4503
+ });
4504
+ }
4133
4505
  analyzePromotableStyleProps(root, j, styledDecls, allStyledDecls, declByLocal, getJsxUsageCount, ctx.resolvedStyleObjects ?? /* @__PURE__ */ new Map());
4506
+ for (const decl of styledDecls) for (const entry of decl.promotedStyleProps ?? []) if (!entry.mergeIntoBase) reservedStyleKeys.add(entry.styleKey);
4134
4507
  for (const decl of styledDecls) {
4135
4508
  if (decl.isDirectJsxResolution) continue;
4136
4509
  const { className, style } = getJsxAttributeUsage(decl.localName);
@@ -4141,11 +4514,101 @@ function analyzeBeforeEmitStep(ctx) {
4141
4514
  if (!decl.needsWrapperComponent) decl.needsWrapperComponent = true;
4142
4515
  }
4143
4516
  }
4517
+ for (const decl of styledDecls) {
4518
+ if (!decl.localElementOverrides?.length) continue;
4519
+ const proofInfo = localElementProofs.get(decl.localName);
4520
+ if (!proofInfo) continue;
4521
+ const localElementUnsupportedReason = proofInfo.unsupportedReason;
4522
+ if (localElementUnsupportedReason !== "none") {
4523
+ for (const override of decl.localElementOverrides) ctx.warnings.push({
4524
+ severity: "warning",
4525
+ type: getLocalElementWarningType(override, localElementUnsupportedReason),
4526
+ loc: override.loc
4527
+ });
4528
+ return returnResult({
4529
+ code: null,
4530
+ warnings: ctx.warnings
4531
+ }, "bail");
4532
+ }
4533
+ const nextOverrides = [];
4534
+ for (const override of decl.localElementOverrides) {
4535
+ const targetIds = proofInfo.proof.targetsByStyleKey.get(override.styleKey) ?? /* @__PURE__ */ new Set();
4536
+ const styleKeysByTargetId = {};
4537
+ for (const targetId of [...targetIds].sort()) {
4538
+ if (hasOverlappingPseudoOnlyLocalOverride(nextOverrides, override, targetId)) {
4539
+ ctx.warnings.push({
4540
+ severity: "warning",
4541
+ type: "Unsupported selector: ambiguous element selector",
4542
+ loc: override.loc
4543
+ });
4544
+ return returnResult({
4545
+ code: null,
4546
+ warnings: ctx.warnings
4547
+ }, "bail");
4548
+ }
4549
+ const targetDecl = targetId.startsWith("styled:") ? declByLocal.get(targetId.slice(7)) : void 0;
4550
+ if (targetDecl) {
4551
+ const childInlineable = isInlineableLocalElementTarget(targetDecl);
4552
+ if (!childInlineable) {
4553
+ ctx.warnings.push({
4554
+ severity: "warning",
4555
+ type: "Unsupported selector: ambiguous element selector",
4556
+ loc: override.loc
4557
+ });
4558
+ return returnResult({
4559
+ code: null,
4560
+ warnings: ctx.warnings
4561
+ }, "bail");
4562
+ }
4563
+ if (hasPseudoLocalElementOverride(override) && hasRuntimeStyleEntriesForLocalElementTarget(targetDecl)) {
4564
+ ctx.warnings.push({
4565
+ severity: "warning",
4566
+ type: "Unsupported selector: ambiguous element selector",
4567
+ loc: override.loc
4568
+ });
4569
+ return returnResult({
4570
+ code: null,
4571
+ warnings: ctx.warnings
4572
+ }, "bail");
4573
+ }
4574
+ targetDecl.localElementTargetProofs ??= [];
4575
+ targetDecl.localElementTargetProofs.push({
4576
+ targetId,
4577
+ wasInlineableAtProofTime: childInlineable,
4578
+ loc: override.loc
4579
+ });
4580
+ localElementTargetStyleKeys.add(targetDecl.styleKey);
4581
+ }
4582
+ const emittedStyleKey = ensureUniqueKey$1(makeLocalElementTargetStyleKey(override, targetId), usedLocalElementStyleKeys, reservedStyleKeys);
4583
+ usedLocalElementStyleKeys.add(emittedStyleKey);
4584
+ reservedStyleKeys.add(emittedStyleKey);
4585
+ styleKeysByTargetId[targetId] = emittedStyleKey;
4586
+ const resolvedStyleObjects = ctx.resolvedStyleObjects;
4587
+ const props = buildLocalElementOverrideProperties({
4588
+ j,
4589
+ override,
4590
+ childStyleObjects: [...resolvedStyleObjects ? nextOverrides.slice().reverse().map((priorOverride) => priorOverride.styleKeysByTargetId?.[targetId]).filter((key) => !!key).map((key) => resolvedStyleObjects.get(key)).flatMap(getPlainStyleObjectsFromResolvedValue) : [], ...targetDecl && resolvedStyleObjects ? buildResolvedStyleObjectList(targetDecl, resolvedStyleObjects) : []]
4591
+ });
4592
+ if (props.length > 0) ctx.resolvedStyleObjects?.set(emittedStyleKey, j.objectExpression(props));
4593
+ }
4594
+ nextOverrides.push({
4595
+ ...override,
4596
+ styleKeysByTargetId
4597
+ });
4598
+ if (override.ancestorPseudo) {
4599
+ ctx.ancestorSelectorParents ??= /* @__PURE__ */ new Set();
4600
+ ctx.ancestorSelectorParents.add(decl.styleKey);
4601
+ ctx.parentsNeedingDefaultMarker ??= /* @__PURE__ */ new Set();
4602
+ ctx.parentsNeedingDefaultMarker.add(decl.styleKey);
4603
+ }
4604
+ }
4605
+ decl.localElementOverrides = nextOverrides;
4606
+ }
4144
4607
  for (const decl of styledDecls) {
4145
4608
  if (decl.isCssHelper || decl.needsWrapperComponent) continue;
4146
4609
  if (decl.isDirectJsxResolution) continue;
4147
4610
  if (decl.base.kind !== "intrinsic") continue;
4148
- if (relationChildStyleKeys.has(decl.styleKey)) continue;
4611
+ if (relationChildStyleKeys.has(decl.styleKey) || localElementTargetStyleKeys.has(decl.styleKey)) continue;
4149
4612
  const usageCount = getJsxUsageCount(decl.localName);
4150
4613
  if (decl.promotedStyleProps?.length && decl.promotedStyleProps.length >= usageCount) continue;
4151
4614
  const { ref } = getJsxAttributeUsage(decl.localName);
@@ -4275,20 +4738,7 @@ function analyzeBeforeEmitStep(ctx) {
4275
4738
  }
4276
4739
  for (const decl of styledDecls) {
4277
4740
  if (decl.isDirectJsxResolution) continue;
4278
- if (root.find(j.Identifier, { name: decl.localName }).filter((p) => {
4279
- if (p.parentPath?.node?.type === "VariableDeclarator" && p.parentPath.node.id === p.node) return false;
4280
- if (p.parentPath?.node?.type === "JSXOpeningElement" || p.parentPath?.node?.type === "JSXClosingElement") return false;
4281
- if (p.parentPath?.node?.type === "JSXMemberExpression" && p.parentPath.node.object === p.node) return false;
4282
- if (p.parentPath?.node?.type === "CallExpression") {
4283
- const callee = p.parentPath.node.callee;
4284
- if (callee?.type === "Identifier" && callee.name === ctx.styledDefaultImport) return false;
4285
- if (callee?.type === "MemberExpression" && callee.object?.type === "CallExpression" && callee.object.callee?.type === "Identifier" && callee.object.callee.name === ctx.styledDefaultImport) return false;
4286
- }
4287
- if (p.parentPath?.node?.type === "TaggedTemplateExpression") return false;
4288
- if (p.parentPath?.node?.type === "CallExpression" && p.parentPath.parentPath?.node?.type === "TaggedTemplateExpression") return false;
4289
- if (p.parentPath?.node?.type === "TemplateLiteral") return false;
4290
- return true;
4291
- }).size() > 0) {
4741
+ if (hasNonJsxComponentValueReference(decl.localName)) {
4292
4742
  decl.usedAsValue = true;
4293
4743
  decl.needsWrapperComponent = true;
4294
4744
  }
@@ -4328,6 +4778,21 @@ function analyzeBeforeEmitStep(ctx) {
4328
4778
  });
4329
4779
  if (hasAs || hasForwardedAs || propsTypeHasAs) decl.isPolymorphicIntrinsicWrapper = true;
4330
4780
  }
4781
+ for (const decl of styledDecls) {
4782
+ if (!decl.localElementTargetProofs?.length) continue;
4783
+ const isInlineableNow = isInlineableLocalElementTarget(decl);
4784
+ if (decl.localElementTargetProofs.some((proof) => proof.wasInlineableAtProofTime) && !isInlineableNow) {
4785
+ ctx.warnings.push({
4786
+ severity: "warning",
4787
+ type: "Unsupported selector: ambiguous element selector",
4788
+ loc: decl.localElementTargetProofs.find((proof) => proof.wasInlineableAtProofTime)?.loc
4789
+ });
4790
+ return returnResult({
4791
+ code: null,
4792
+ warnings: ctx.warnings
4793
+ }, "bail");
4794
+ }
4795
+ }
4331
4796
  const isUsedOutsideStyledTemplates = (localName) => root.find(j.Identifier, { name: localName }).filter((p) => {
4332
4797
  if (j(p).closest(j.ImportDeclaration).size() > 0) return false;
4333
4798
  if (j(p).closest(j.TaggedTemplateExpression).filter((tp) => ctx.isStyledTag(tp.node.tag)).size() > 0) return false;
@@ -4888,6 +5353,10 @@ function applyTransientPropRenames(decl, renames) {
4888
5353
  attr.jsxProp = renames.get(attr.jsxProp) ?? attr.jsxProp;
4889
5354
  attr.attrName = renames.get(attr.attrName) ?? attr.attrName;
4890
5355
  }
5356
+ if (decl.attrsInfo?.dynamicAttrs) for (const attr of decl.attrsInfo.dynamicAttrs) {
5357
+ attr.jsxProp = renames.get(attr.jsxProp) ?? attr.jsxProp;
5358
+ attr.attrName = renames.get(attr.attrName) ?? attr.attrName;
5359
+ }
4891
5360
  if (decl.attrsInfo?.staticAttrs) decl.attrsInfo.staticAttrs = renameStaticAttrKeys(decl.attrsInfo.staticAttrs, renames);
4892
5361
  if (decl.attrsInfo?.attrsDynamicStyles) for (const ds of decl.attrsInfo.attrsDynamicStyles) {
4893
5362
  ds.jsxProp = renames.get(ds.jsxProp) ?? ds.jsxProp;
@@ -5054,77 +5523,6 @@ function emitTransientPropRenameWarning(ctx, decl, renames, exportedComponents)
5054
5523
  renames: renameRecord
5055
5524
  });
5056
5525
  }
5057
- function collectDottedExportedComponents(root, j, declByLocal, exportedComponents) {
5058
- const getIdentifierName = (node) => {
5059
- const n = node;
5060
- return n?.type === "Identifier" && n.name ? n.name : null;
5061
- };
5062
- const setDottedExport = (localName, exportName) => {
5063
- if (!declByLocal.has(localName)) return;
5064
- const existing = exportedComponents.get(localName)?.exportName;
5065
- if (existing && existing.split(".").length > exportName.split(".").length) return;
5066
- exportedComponents.set(localName, {
5067
- exportName,
5068
- isDefault: false,
5069
- isSpecifier: false
5070
- });
5071
- };
5072
- const collectObjectProperties = (objectExpression, prefix) => {
5073
- const objectNode = objectExpression;
5074
- if (objectNode?.type !== "ObjectExpression" || !Array.isArray(objectNode.properties)) return;
5075
- for (const property of objectNode.properties) {
5076
- if (property?.type !== "Property" && property?.type !== "ObjectProperty") continue;
5077
- const keyName = getIdentifierName(property.key);
5078
- if (!keyName) continue;
5079
- const valueName = getIdentifierName(property.value);
5080
- if (valueName) {
5081
- setDottedExport(valueName, `${prefix}.${keyName}`);
5082
- continue;
5083
- }
5084
- collectObjectProperties(property.value, `${prefix}.${keyName}`);
5085
- }
5086
- };
5087
- root.find(j.ExportNamedDeclaration).forEach((p) => {
5088
- const declaration = p.node.declaration;
5089
- if (declaration?.type !== "VariableDeclaration") return;
5090
- for (const declarator of declaration.declarations) {
5091
- if (declarator.type !== "VariableDeclarator") continue;
5092
- const exportName = getIdentifierName(declarator.id);
5093
- if (exportName) collectObjectProperties(declarator.init, exportName);
5094
- }
5095
- });
5096
- const collectNamespaceExports = (node, namespacePath) => {
5097
- const current = node;
5098
- if (!current) return;
5099
- if (current.type === "TSModuleDeclaration") {
5100
- const namespaceName = getIdentifierName(current.id);
5101
- if (!namespaceName) return;
5102
- const nextPath = [...namespacePath, namespaceName];
5103
- if (current.body?.type === "TSModuleBlock") for (const statement of current.body.body ?? []) collectNamespaceExports(statement, nextPath);
5104
- else collectNamespaceExports(current.body, nextPath);
5105
- return;
5106
- }
5107
- if (current.type !== "ExportNamedDeclaration") return;
5108
- const declaration = current.declaration;
5109
- if (!declaration) return;
5110
- if (declaration.type === "TSModuleDeclaration") {
5111
- collectNamespaceExports(declaration, namespacePath);
5112
- return;
5113
- }
5114
- if (declaration.type === "FunctionDeclaration") {
5115
- const localName = getIdentifierName(declaration.id);
5116
- if (localName) setDottedExport(localName, [...namespacePath, localName].join("."));
5117
- return;
5118
- }
5119
- if (declaration.type === "VariableDeclaration" && Array.isArray(declaration.declarations)) for (const declarator of declaration.declarations) {
5120
- const localName = getIdentifierName(declarator.id);
5121
- if (localName) setDottedExport(localName, [...namespacePath, localName].join("."));
5122
- }
5123
- };
5124
- root.find(j.TSModuleDeclaration).forEach((p) => {
5125
- collectNamespaceExports(p.node, []);
5126
- });
5127
- }
5128
5526
  /** Recursively check if a pattern (Identifier, ArrayPattern, ObjectPattern, etc.) contains a binding with the given name. */
5129
5527
  function patternContainsName(node, name) {
5130
5528
  if (!node || typeof node !== "object") return false;
@@ -5375,7 +5773,7 @@ function analyzePromotableStyleProps(root, j, styledDecls, allStyledDecls, declB
5375
5773
  siteBail = true;
5376
5774
  break;
5377
5775
  }
5378
- if (!isValidIdentifierName(keyName)) {
5776
+ if (!isValidIdentifierName$1(keyName)) {
5379
5777
  siteBail = true;
5380
5778
  break;
5381
5779
  }
@@ -5798,28 +6196,225 @@ function classifyAdjacentSiblingChild(child, componentName) {
5798
6196
  }
5799
6197
  return { kind: "other" };
5800
6198
  }
6199
+ function proveLocalElementOverrideUsages(root, j, componentName, overrides, declByLocal) {
6200
+ const targetsByStyleKey = new Map(overrides.map((override) => [override.styleKey, /* @__PURE__ */ new Set()]));
6201
+ let sawUsage = false;
6202
+ let sawCandidateMatch = false;
6203
+ let reason = "ok";
6204
+ const inspectChildren = (children, relation, tagName) => {
6205
+ const matches = /* @__PURE__ */ new Set();
6206
+ let failureReason;
6207
+ const visitChild = (child, isDirectChild) => {
6208
+ if (!child || typeof child !== "object") return true;
6209
+ const node = child;
6210
+ if (node.type === "JSXText") return true;
6211
+ if (node.type === "JSXFragment") return false;
6212
+ if (node.type === "JSXExpressionContainer") {
6213
+ const exprType = node.expression?.type;
6214
+ return exprType === "JSXEmptyExpression" || exprType === "Literal" || exprType === "StringLiteral" || exprType === "TemplateLiteral";
6215
+ }
6216
+ if (node.type !== "JSXElement") return false;
6217
+ const name = getRootJsxIdentifierName(node.openingElement?.name);
6218
+ if (!name) return false;
6219
+ const decl = declByLocal.get(name);
6220
+ const isIntrinsicTagName = /^[a-z]/.test(name);
6221
+ const isIntrinsicMatch = isIntrinsicTagName && name === tagName;
6222
+ const staticAsTag = typeof decl?.attrsInfo?.staticAttrs?.as === "string" ? decl.attrsInfo.staticAttrs.as : void 0;
6223
+ const renderedTagName = decl?.attrsInfo?.attrsAsTag ?? staticAsTag ?? (decl?.base.kind === "intrinsic" ? decl.base.tagName : void 0);
6224
+ const isStyledIntrinsicMatch = !!decl && decl.base.kind === "intrinsic" && renderedTagName === tagName;
6225
+ const isUnknownWrapperBoundary = !isIntrinsicMatch && !isStyledIntrinsicMatch && (!!decl || !isIntrinsicTagName);
6226
+ if ((relation === "child" ? isDirectChild : true) && (isIntrinsicMatch || isStyledIntrinsicMatch)) {
6227
+ sawCandidateMatch = true;
6228
+ matches.add(isStyledIntrinsicMatch ? `styled:${name}` : `intrinsic:${tagName}`);
6229
+ }
6230
+ if (relation === "descendant") {
6231
+ if (isUnknownWrapperBoundary) {
6232
+ failureReason = "unsupported-wrapper";
6233
+ return false;
6234
+ }
6235
+ for (const grandchild of node.children ?? []) if (!visitChild(grandchild, false)) return false;
6236
+ }
6237
+ if (relation === "child" && isDirectChild && isUnknownWrapperBoundary) {
6238
+ failureReason = "unsupported-wrapper";
6239
+ return false;
6240
+ }
6241
+ return true;
6242
+ };
6243
+ for (const child of children) if (!visitChild(child, true)) return {
6244
+ safe: false,
6245
+ matches,
6246
+ ...failureReason ? { reason: failureReason } : {}
6247
+ };
6248
+ return {
6249
+ safe: true,
6250
+ matches
6251
+ };
6252
+ };
6253
+ root.find(j.JSXElement, { openingElement: { name: {
6254
+ type: "JSXIdentifier",
6255
+ name: componentName
6256
+ } } }).forEach((path) => {
6257
+ sawUsage = true;
6258
+ for (const override of overrides) {
6259
+ const inspected = inspectChildren(path.node.children ?? [], override.relation, override.tagName);
6260
+ if (!inspected.safe) {
6261
+ reason = inspected.reason ?? "dynamic-usage";
6262
+ return;
6263
+ }
6264
+ const targetSet = targetsByStyleKey.get(override.styleKey);
6265
+ for (const match of inspected.matches) targetSet.add(match);
6266
+ }
6267
+ });
6268
+ if (reason !== "ok") return {
6269
+ safe: false,
6270
+ reason,
6271
+ targetsByStyleKey,
6272
+ sawCandidateMatch
6273
+ };
6274
+ if (!sawUsage) return {
6275
+ safe: false,
6276
+ reason: "no-usage",
6277
+ targetsByStyleKey,
6278
+ sawCandidateMatch
6279
+ };
6280
+ if ([...targetsByStyleKey.values()].some((set) => set.size === 0)) return {
6281
+ safe: false,
6282
+ reason: sawCandidateMatch ? "dynamic-usage" : "no-usage",
6283
+ targetsByStyleKey,
6284
+ sawCandidateMatch
6285
+ };
6286
+ return {
6287
+ safe: true,
6288
+ reason: "ok",
6289
+ targetsByStyleKey,
6290
+ sawCandidateMatch
6291
+ };
6292
+ }
6293
+ function getLocalElementWarningType(override, reason) {
6294
+ if (reason === "no-usage") return "Unsupported selector: descendant/child/sibling selector";
6295
+ if (reason === "dynamic-usage" || reason === "unsupported-wrapper") return "Unsupported selector: element selector with dynamic children";
6296
+ if (reason === "child-not-inlineable" || reason === "non-jsx-usage") return "Unsupported selector: ambiguous element selector";
6297
+ return override.tagName === "svg" || override.tagName === "button" ? "Unsupported selector: element selector with plain intrinsic children" : "Unsupported selector: ambiguous element selector";
6298
+ }
6299
+ function makeLocalElementTargetStyleKey(override, targetId) {
6300
+ const targetName = targetId.startsWith("styled:") ? targetId.slice(7) : targetId.slice(10);
6301
+ const normalizedTargetName = targetName[0]?.toLowerCase() === targetName[0] ? targetName : `${targetName[0]?.toLowerCase() ?? ""}${targetName.slice(1)}`;
6302
+ const relationPrefix = override.relation === "child" ? "child" : "descendant";
6303
+ const targetSuffix = camelToKebabCase(normalizedTargetName).replace(/-([a-z])/g, (_, c) => c.toUpperCase());
6304
+ return `${relationPrefix}${targetSuffix[0]?.toUpperCase() ?? ""}${targetSuffix.slice(1)}`;
6305
+ }
6306
+ function buildLocalElementOverrideProperties(args) {
6307
+ const { j, override, childStyleObjects } = args;
6308
+ return buildRelationOverrideProperties({
6309
+ j,
6310
+ pseudoBuckets: override.pseudoBuckets,
6311
+ childStyleObjects,
6312
+ makeCssPropKey,
6313
+ childPseudos: override.childPseudo ? new Set([override.childPseudo]) : void 0,
6314
+ markerVarName: void 0
6315
+ });
6316
+ }
6317
+ function hasPseudoLocalElementOverride(override) {
6318
+ return [...override.pseudoBuckets.keys()].some((pseudo) => pseudo !== null);
6319
+ }
6320
+ function hasPseudoOnlyLocalElementOverride(override) {
6321
+ return override.pseudoBuckets.size > 0 && !override.pseudoBuckets.has(null);
6322
+ }
6323
+ function hasOverlappingPseudoOnlyLocalOverride(priorOverrides, nextOverride, targetId) {
6324
+ if (!hasPseudoOnlyLocalElementOverride(nextOverride)) return false;
6325
+ const nextProps = new Set(getLocalElementOverridePropNames(nextOverride));
6326
+ return priorOverrides.some((priorOverride) => {
6327
+ if (!hasPseudoOnlyLocalElementOverride(priorOverride)) return false;
6328
+ if (!priorOverride.styleKeysByTargetId?.[targetId]) return false;
6329
+ return getLocalElementOverridePropNames(priorOverride).some((prop) => nextProps.has(prop));
6330
+ });
6331
+ }
6332
+ function getLocalElementOverridePropNames(override) {
6333
+ return [...override.pseudoBuckets.values()].flatMap((bucket) => Object.keys(bucket));
6334
+ }
6335
+ function hasRuntimeStyleEntriesForLocalElementTarget(decl) {
6336
+ return Object.keys(decl.variantStyleKeys ?? {}).length > 0 || (decl.variantDimensions?.length ?? 0) > 0 || (decl.staticBooleanVariants?.length ?? 0) > 0 || (decl.callSiteCombinedStyles?.length ?? 0) > 0 || (decl.styleFnFromProps?.length ?? 0) > 0 || (decl.extraStylexPropsArgs?.length ?? 0) > 0;
6337
+ }
6338
+ function buildResolvedStyleObjectList(decl, resolvedStyleObjects) {
6339
+ const afterBaseKeys = new Set(decl.extraStyleKeysAfterBase ?? []);
6340
+ const beforeBaseKeys = [];
6341
+ const afterBaseKeysInOrder = [];
6342
+ for (const key of decl.extraStyleKeys ?? []) if (afterBaseKeys.has(key)) afterBaseKeysInOrder.push(key);
6343
+ else beforeBaseKeys.push(key);
6344
+ const keys = [
6345
+ ...afterBaseKeysInOrder.reverse(),
6346
+ decl.styleKey,
6347
+ ...beforeBaseKeys.reverse(),
6348
+ ...decl.extendsStyleKey ? [decl.extendsStyleKey] : []
6349
+ ];
6350
+ const results = [];
6351
+ for (const key of keys) {
6352
+ const value = resolvedStyleObjects.get(key);
6353
+ results.push(...getPlainStyleObjectsFromResolvedValue(value));
6354
+ }
6355
+ return results;
6356
+ }
6357
+ function getPlainStyleObjectsFromResolvedValue(value) {
6358
+ if (isPlainStyleObject(value)) return [value];
6359
+ if (isAstNode(value) && value.type === "ObjectExpression") {
6360
+ const converted = objectExpressionToPlainStyleObject(value);
6361
+ return converted ? [converted] : [];
6362
+ }
6363
+ return [];
6364
+ }
6365
+ function objectExpressionToPlainStyleObject(node) {
6366
+ const result = {};
6367
+ for (const property of node.properties ?? []) {
6368
+ if (property.type !== "Property") return null;
6369
+ const key = property.key?.type === "Identifier" ? property.key.name : property.key?.type === "Literal" || property.key?.type === "StringLiteral" ? String(property.key.value) : null;
6370
+ if (!key) return null;
6371
+ result[key] = property.value;
6372
+ }
6373
+ return result;
6374
+ }
5801
6375
  function isPlainStyleObject(value) {
5802
6376
  return !!value && typeof value === "object" && !Array.isArray(value) && !isAstNode(value) && Object.values(value).every((v) => typeof v === "string" || typeof v === "number" || typeof v === "boolean" || isAstNode(v));
5803
6377
  }
5804
6378
  function mergeInheritedAttrsInfo(baseAttrsInfo, ownAttrsInfo) {
6379
+ const ownAttrNames = collectAttrsInfoAttrNames(ownAttrsInfo);
5805
6380
  return {
5806
6381
  staticAttrs: {
5807
- ...baseAttrsInfo.staticAttrs,
6382
+ ...Object.fromEntries(Object.entries(baseAttrsInfo.staticAttrs ?? {}).filter(([key]) => !ownAttrNames.has(key))),
5808
6383
  ...ownAttrsInfo?.staticAttrs
5809
6384
  },
5810
6385
  sourceKind: ownAttrsInfo?.sourceKind ?? baseAttrsInfo.sourceKind,
5811
6386
  hasUnsupportedValues: (baseAttrsInfo.hasUnsupportedValues ?? false) || (ownAttrsInfo?.hasUnsupportedValues ?? false),
5812
6387
  attrsAsTag: ownAttrsInfo?.attrsAsTag ?? baseAttrsInfo.attrsAsTag,
5813
- defaultAttrs: [...baseAttrsInfo.defaultAttrs ?? [], ...ownAttrsInfo?.defaultAttrs ?? []],
5814
- conditionalAttrs: [...baseAttrsInfo.conditionalAttrs ?? [], ...ownAttrsInfo?.conditionalAttrs ?? []],
5815
- invertedBoolAttrs: [...baseAttrsInfo.invertedBoolAttrs ?? [], ...ownAttrsInfo?.invertedBoolAttrs ?? []],
6388
+ defaultAttrs: mergeAttrEntriesByAttrName(filterAttrEntriesByAttrName(baseAttrsInfo.defaultAttrs, ownAttrNames), ownAttrsInfo?.defaultAttrs),
6389
+ conditionalAttrs: [...filterAttrEntriesByAttrName(baseAttrsInfo.conditionalAttrs, ownAttrNames), ...ownAttrsInfo?.conditionalAttrs ?? []],
6390
+ invertedBoolAttrs: [...filterAttrEntriesByAttrName(baseAttrsInfo.invertedBoolAttrs, ownAttrNames), ...ownAttrsInfo?.invertedBoolAttrs ?? []],
6391
+ dynamicAttrs: mergeAttrEntriesByAttrName(filterAttrEntriesByAttrName(baseAttrsInfo.dynamicAttrs, ownAttrNames), ownAttrsInfo?.dynamicAttrs),
5816
6392
  attrsStaticStyles: {
5817
6393
  ...baseAttrsInfo.attrsStaticStyles,
5818
6394
  ...ownAttrsInfo?.attrsStaticStyles
5819
6395
  },
6396
+ attrsStaticStyleExpr: ownAttrsInfo?.attrsStaticStyleExpr ?? baseAttrsInfo.attrsStaticStyleExpr,
5820
6397
  attrsDynamicStyles: [...baseAttrsInfo.attrsDynamicStyles ?? [], ...ownAttrsInfo?.attrsDynamicStyles ?? []]
5821
6398
  };
5822
6399
  }
6400
+ function collectAttrsInfoAttrNames(attrsInfo) {
6401
+ const names = /* @__PURE__ */ new Set();
6402
+ for (const key of Object.keys(attrsInfo?.staticAttrs ?? {})) names.add(key);
6403
+ for (const entry of attrsInfo?.defaultAttrs ?? []) names.add(entry.attrName);
6404
+ for (const entry of attrsInfo?.dynamicAttrs ?? []) names.add(entry.attrName);
6405
+ for (const entry of attrsInfo?.conditionalAttrs ?? []) names.add(entry.attrName);
6406
+ for (const entry of attrsInfo?.invertedBoolAttrs ?? []) names.add(entry.attrName);
6407
+ return names;
6408
+ }
6409
+ function filterAttrEntriesByAttrName(entries, names) {
6410
+ return (entries ?? []).filter((entry) => !names.has(entry.attrName));
6411
+ }
6412
+ function mergeAttrEntriesByAttrName(baseEntries, ownEntries) {
6413
+ const byAttrName = /* @__PURE__ */ new Map();
6414
+ for (const entry of baseEntries ?? []) byAttrName.set(entry.attrName, entry);
6415
+ for (const entry of ownEntries ?? []) byAttrName.set(entry.attrName, entry);
6416
+ return [...byAttrName.values()];
6417
+ }
5823
6418
  //#endregion
5824
6419
  //#region src/internal/policy.ts
5825
6420
  function collectCreateGlobalStyleWarnings(styledImports) {
@@ -5880,18 +6475,19 @@ function buildImportMapStep(ctx) {
5880
6475
  ctx.importMap = buildImportMap({
5881
6476
  root: ctx.root,
5882
6477
  j: ctx.j,
5883
- filePath: ctx.file.path
6478
+ filePath: ctx.file.path,
6479
+ resolveModule: ctx.options.resolveModule
5884
6480
  });
5885
6481
  return CONTINUE;
5886
6482
  }
5887
6483
  function buildImportMap(args) {
5888
- const { root, j, filePath } = args;
6484
+ const { root, j, filePath, resolveModule } = args;
5889
6485
  const importMap = /* @__PURE__ */ new Map();
5890
6486
  const baseDir = dirname(filePath);
5891
6487
  root.find(j.ImportDeclaration).forEach((p) => {
5892
6488
  const source = p.node.source?.value;
5893
6489
  if (typeof source !== "string") return;
5894
- const resolvedSource = resolveImportSource(source, baseDir);
6490
+ const resolvedSource = resolveImportSource(source, baseDir, filePath, resolveModule);
5895
6491
  for (const s of p.node.specifiers ?? []) {
5896
6492
  if (!s) continue;
5897
6493
  if (s.type === "ImportDefaultSpecifier") {
@@ -5915,20 +6511,53 @@ function buildImportMap(args) {
5915
6511
  });
5916
6512
  return importMap;
5917
6513
  }
5918
- /**
5919
- * Deterministic resolution: relative specifiers resolve against the current
5920
- * file's directory. This intentionally does NOT probe extensions, consult
5921
- * tsconfig paths, or use Node resolution.
5922
- */
5923
- function resolveImportSource(specifier, baseDir) {
5924
- return isRelativeSpecifier(specifier) ? {
6514
+ function resolveImportSource(specifier, baseDir, filePath, resolveModule) {
6515
+ if (!isRelativeSpecifier(specifier)) {
6516
+ if (isResolvablePackageSpecifier(specifier, filePath)) return {
6517
+ kind: "specifier",
6518
+ value: specifier
6519
+ };
6520
+ const resolved = resolveModule?.(filePath, specifier);
6521
+ return resolved ? {
6522
+ kind: "absolutePath",
6523
+ value: resolved
6524
+ } : {
6525
+ kind: "specifier",
6526
+ value: specifier
6527
+ };
6528
+ }
6529
+ return {
5925
6530
  kind: "absolutePath",
5926
- value: resolve(baseDir, specifier)
5927
- } : {
5928
- kind: "specifier",
5929
- value: specifier
6531
+ value: resolveModule?.(filePath, specifier) ?? resolve(baseDir, specifier)
5930
6532
  };
5931
6533
  }
6534
+ function isResolvablePackageSpecifier(specifier, filePath) {
6535
+ const packageName = packageNameFromSpecifier(specifier);
6536
+ if (!packageName) return false;
6537
+ const requireFromFile = createRequire(resolve(filePath));
6538
+ try {
6539
+ requireFromFile.resolve(`${packageName}/package.json`);
6540
+ return true;
6541
+ } catch {
6542
+ try {
6543
+ requireFromFile.resolve(packageName);
6544
+ return true;
6545
+ } catch {
6546
+ return false;
6547
+ }
6548
+ }
6549
+ }
6550
+ function packageNameFromSpecifier(specifier) {
6551
+ if (specifier.startsWith("#")) return null;
6552
+ const parts = specifier.split("/");
6553
+ const first = parts[0];
6554
+ if (!first) return null;
6555
+ if (first.startsWith("@")) {
6556
+ const second = parts[1];
6557
+ return second ? `${first}/${second}` : null;
6558
+ }
6559
+ return first;
6560
+ }
5932
6561
  //#endregion
5933
6562
  //#region src/internal/css-ir.ts
5934
6563
  function normalizeStylisAstToIR(stylisAst, slots, options = {}) {
@@ -7379,10 +8008,11 @@ function collectStyledDeclsImpl(args) {
7379
8008
  sourceKind: "unknown",
7380
8009
  hasUnsupportedValues: false,
7381
8010
  defaultAttrs: [],
8011
+ dynamicAttrs: [],
7382
8012
  conditionalAttrs: [],
7383
8013
  invertedBoolAttrs: []
7384
8014
  };
7385
- const fillFromObject = (obj, attrsParamPropNames = /* @__PURE__ */ new Set()) => {
8015
+ const fillFromObject = (obj, attrsParamInfo = emptyAttrsParamInfo()) => {
7386
8016
  for (const prop of obj.properties ?? []) {
7387
8017
  if (!prop || prop.type !== "ObjectProperty" && prop.type !== "Property") continue;
7388
8018
  const key = prop.key.type === "Identifier" ? prop.key.name : prop.key.type === "StringLiteral" ? prop.key.value : null;
@@ -7396,6 +8026,31 @@ function collectStyledDeclsImpl(args) {
7396
8026
  out.attrsAsTag = v.name;
7397
8027
  continue;
7398
8028
  }
8029
+ if (key === "as") {
8030
+ const asTag = staticAttrExpressionToReference(v, attrsParamInfo);
8031
+ if (asTag) {
8032
+ out.attrsAsTag = asTag;
8033
+ continue;
8034
+ }
8035
+ }
8036
+ if (key === "style" && isStaticAttrExpression$1(v, attrsParamInfo)) {
8037
+ out.attrsStaticStyleExpr = cloneAstNode(v);
8038
+ continue;
8039
+ }
8040
+ const dynamicAttrProp = extractPropName(v, attrsParamInfo);
8041
+ if (dynamicAttrProp) {
8042
+ const dynamicAttrDefault = extractPropDefault(v, attrsParamInfo);
8043
+ out.dynamicAttrs.push({
8044
+ jsxProp: dynamicAttrProp,
8045
+ attrName: key,
8046
+ ...dynamicAttrDefault !== void 0 ? { defaultValue: dynamicAttrDefault } : {}
8047
+ });
8048
+ continue;
8049
+ }
8050
+ if (isStaticAttrExpression$1(v, attrsParamInfo)) {
8051
+ out.staticAttrs[key] = cloneAstNode(v);
8052
+ continue;
8053
+ }
7399
8054
  if (v.type === "Identifier" && v.name === "undefined" || v.type === "NullLiteral") {
7400
8055
  out.staticAttrs[key] = v.type === "NullLiteral" ? null : void 0;
7401
8056
  continue;
@@ -7403,9 +8058,10 @@ function collectStyledDeclsImpl(args) {
7403
8058
  if (v.type === "LogicalExpression" && v.operator === "??" || v.type === "TSNullishCoalescingExpression") {
7404
8059
  const left = v.left;
7405
8060
  const right = v.right;
7406
- if (left?.type === "MemberExpression" && left.object?.type === "Identifier" && (left.object.name === "props" || left.object.name === "p") && left.property?.type === "Identifier" && (right?.type === "StringLiteral" || right?.type === "NumericLiteral" || right?.type === "BooleanLiteral")) {
8061
+ const leftPropName = extractPropName(left, attrsParamInfo);
8062
+ if (leftPropName && (right?.type === "StringLiteral" || right?.type === "NumericLiteral" || right?.type === "BooleanLiteral")) {
7407
8063
  out.defaultAttrs.push({
7408
- jsxProp: left.property.name,
8064
+ jsxProp: leftPropName,
7409
8065
  attrName: key,
7410
8066
  value: right.value
7411
8067
  });
@@ -7432,7 +8088,7 @@ function collectStyledDeclsImpl(args) {
7432
8088
  });
7433
8089
  continue;
7434
8090
  }
7435
- if (key === "style" && v.type === "ObjectExpression" && tryExtractStyleObject(v, out, attrsParamPropNames, resolveModuleScopeStaticValue)) continue;
8091
+ if (key === "style" && v.type === "ObjectExpression" && tryExtractStyleObject(v, out, attrsParamInfo.propNames, resolveModuleScopeStaticValue)) continue;
7436
8092
  out.hasUnsupportedValues = true;
7437
8093
  }
7438
8094
  };
@@ -7443,16 +8099,19 @@ function collectStyledDeclsImpl(args) {
7443
8099
  }
7444
8100
  if (arg0.type === "ArrowFunctionExpression") {
7445
8101
  out.sourceKind = "function";
7446
- const attrsParamPropNames = getAttrsParamPropNames(arg0.params);
8102
+ const attrsParamInfo = getAttrsParamInfo(arg0.params);
7447
8103
  const body = arg0.body;
7448
8104
  if (body?.type === "ObjectExpression") {
7449
- fillFromObject(body, attrsParamPropNames);
8105
+ fillFromObject(body, attrsParamInfo);
7450
8106
  return out;
7451
8107
  }
7452
8108
  if (body?.type === "BlockStatement") {
7453
8109
  const ret = body.body.find((s) => s.type === "ReturnStatement");
7454
8110
  if (ret?.argument?.type === "ObjectExpression") {
7455
- fillFromObject(ret.argument, attrsParamPropNames);
8111
+ fillFromObject(ret.argument, {
8112
+ ...attrsParamInfo,
8113
+ localNames: collectBlockLocalNames(body)
8114
+ });
7456
8115
  return out;
7457
8116
  }
7458
8117
  }
@@ -7485,7 +8144,8 @@ function collectStyledDeclsImpl(args) {
7485
8144
  return isModuleScopeDeclarator(path);
7486
8145
  });
7487
8146
  if (decls.length !== 1) return;
7488
- return literalStaticValueFromNode(decls.get().node.init);
8147
+ const value = literalStaticValueFromNode(decls.get().node.init);
8148
+ return typeof value === "string" || typeof value === "number" ? value : void 0;
7489
8149
  };
7490
8150
  const parseShouldForwardProp = (arg0) => {
7491
8151
  if (!arg0 || arg0.type !== "ObjectExpression") return;
@@ -8211,13 +8871,20 @@ function extractTernaryJsxProp(ternary, attrsParamPropNames) {
8211
8871
  return null;
8212
8872
  }
8213
8873
  function extractDynamicStyleValue(value, attrsParamPropNames) {
8214
- const propName = extractPropName(value, attrsParamPropNames);
8874
+ const attrsParamInfo = {
8875
+ propNames: attrsParamPropNames,
8876
+ propByLocalName: /* @__PURE__ */ new Map(),
8877
+ defaultsByPropName: /* @__PURE__ */ new Map(),
8878
+ rootNames: new Set(["props", "p"]),
8879
+ localNames: /* @__PURE__ */ new Set()
8880
+ };
8881
+ const propName = extractPropName(value, attrsParamInfo);
8215
8882
  if (propName) return {
8216
8883
  jsxProp: propName,
8217
8884
  callArgExpr: identifierNode(propName)
8218
8885
  };
8219
8886
  if (value?.type === "LogicalExpression" && value.operator === "??" || value?.type === "TSNullishCoalescingExpression") {
8220
- const leftPropName = extractPropName(value.left, attrsParamPropNames);
8887
+ const leftPropName = extractPropName(value.left, attrsParamInfo);
8221
8888
  if (leftPropName) return {
8222
8889
  jsxProp: leftPropName,
8223
8890
  callArgExpr: {
@@ -8237,31 +8904,142 @@ function hasLeadingFalse(comment) {
8237
8904
  if (!comment || typeof comment !== "object") return false;
8238
8905
  return comment.leading === false;
8239
8906
  }
8240
- function extractPropName(value, attrsParamPropNames) {
8241
- if (value?.type === "Identifier" && typeof value.name === "string" && attrsParamPropNames.has(value.name)) return value.name;
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;
8907
+ function emptyAttrsParamInfo() {
8908
+ return {
8909
+ propNames: /* @__PURE__ */ new Set(),
8910
+ propByLocalName: /* @__PURE__ */ new Map(),
8911
+ defaultsByPropName: /* @__PURE__ */ new Map(),
8912
+ rootNames: /* @__PURE__ */ new Set(),
8913
+ localNames: /* @__PURE__ */ new Set()
8914
+ };
8915
+ }
8916
+ function extractPropName(value, attrsParamInfo) {
8917
+ if (value?.type === "Identifier" && typeof value.name === "string" && attrsParamInfo.propNames.has(value.name)) return attrsParamInfo.propByLocalName.get(value.name) ?? value.name;
8918
+ if (value?.type === "MemberExpression" && value.object?.type === "Identifier" && attrsParamInfo.rootNames.has(value.object.name) && value.property?.type === "Identifier" && typeof value.property.name === "string") return value.property.name;
8243
8919
  return null;
8244
8920
  }
8245
- function getAttrsParamPropNames(params) {
8921
+ function extractPropDefault(value, attrsParamInfo) {
8922
+ const propName = extractPropName(value, attrsParamInfo);
8923
+ return propName ? attrsParamInfo.defaultsByPropName.get(propName) : void 0;
8924
+ }
8925
+ function getAttrsParamInfo(params) {
8246
8926
  const names = /* @__PURE__ */ new Set();
8247
- const firstParam = params?.[0];
8248
- if (firstParam?.type !== "ObjectPattern") return names;
8927
+ const propByLocalName = /* @__PURE__ */ new Map();
8928
+ const defaultsByPropName = /* @__PURE__ */ new Map();
8929
+ const rootNames = /* @__PURE__ */ new Set();
8930
+ const localNames = /* @__PURE__ */ new Set();
8931
+ const firstParamRaw = params?.[0];
8932
+ const firstParam = firstParamRaw?.type === "AssignmentPattern" ? firstParamRaw.left : firstParamRaw;
8933
+ if (firstParam?.type === "Identifier" && typeof firstParam.name === "string") {
8934
+ rootNames.add(firstParam.name);
8935
+ return {
8936
+ propNames: names,
8937
+ propByLocalName,
8938
+ defaultsByPropName,
8939
+ rootNames,
8940
+ localNames
8941
+ };
8942
+ }
8943
+ if (firstParam?.type !== "ObjectPattern") return {
8944
+ propNames: names,
8945
+ propByLocalName,
8946
+ defaultsByPropName,
8947
+ rootNames,
8948
+ localNames
8949
+ };
8249
8950
  for (const prop of firstParam.properties ?? []) {
8250
- if (!prop || prop.type === "RestElement") continue;
8951
+ if (!prop) continue;
8952
+ if (prop.type === "RestElement") {
8953
+ if (prop.argument?.type === "Identifier" && typeof prop.argument.name === "string") if ((firstParam.properties ?? []).length === 1) rootNames.add(prop.argument.name);
8954
+ else localNames.add(prop.argument.name);
8955
+ continue;
8956
+ }
8957
+ const propName = prop.key?.type === "Identifier" ? prop.key.name : prop.key?.type === "StringLiteral" ? prop.key.value : null;
8958
+ if (!propName) continue;
8251
8959
  const value = prop.value ?? prop.argument;
8960
+ if (!isValidIdentifierName(propName)) {
8961
+ collectPatternNames(value, localNames);
8962
+ continue;
8963
+ }
8252
8964
  if (value?.type === "Identifier" && typeof value.name === "string") {
8253
8965
  names.add(value.name);
8966
+ propByLocalName.set(value.name, propName);
8254
8967
  continue;
8255
8968
  }
8256
- if (value?.type === "AssignmentPattern" && value.left?.type === "Identifier" && typeof value.left.name === "string") names.add(value.left.name);
8969
+ if (value?.type === "AssignmentPattern" && value.left?.type === "Identifier" && typeof value.left.name === "string") {
8970
+ names.add(value.left.name);
8971
+ propByLocalName.set(value.left.name, propName);
8972
+ const defaultValue = literalStaticValueFromNode(value.right);
8973
+ if (defaultValue !== void 0) defaultsByPropName.set(propName, defaultValue);
8974
+ }
8257
8975
  }
8258
- return names;
8976
+ return {
8977
+ propNames: names,
8978
+ propByLocalName,
8979
+ defaultsByPropName,
8980
+ rootNames,
8981
+ localNames
8982
+ };
8259
8983
  }
8260
8984
  function literalStaticValueFromNode(node) {
8261
8985
  if (node?.type === "StringLiteral" || node?.type === "NumericLiteral") return node.value;
8262
- if (node?.type === "Literal" && (typeof node.value === "string" || typeof node.value === "number")) return node.value;
8986
+ if (node?.type === "BooleanLiteral") return node.value;
8987
+ if (node?.type === "Literal" && (typeof node.value === "string" || typeof node.value === "number" || typeof node.value === "boolean")) return node.value;
8263
8988
  if (node?.type === "TSAsExpression" || node?.type === "TSSatisfiesExpression") return literalStaticValueFromNode(node.expression);
8264
8989
  }
8990
+ function isStaticAttrExpression$1(node, attrsParamInfo) {
8991
+ if (!node || typeof node !== "object") return false;
8992
+ if (node.type === "TSAsExpression" || node.type === "TSSatisfiesExpression") return isStaticAttrExpression$1(node.expression, attrsParamInfo);
8993
+ const rootName = getStaticAttrExpressionRootName(node);
8994
+ return rootName != null && !attrsParamInfo.propNames.has(rootName) && !attrsParamInfo.rootNames.has(rootName) && !attrsParamInfo.localNames.has(rootName);
8995
+ }
8996
+ function getStaticAttrExpressionRootName(node) {
8997
+ if (node?.type === "Identifier" && node.name !== "undefined") return node.name;
8998
+ if (node?.type !== "MemberExpression" || node.computed) return null;
8999
+ if (node.property?.type !== "Identifier" && node.property?.type !== "PrivateName") return null;
9000
+ return getStaticAttrExpressionRootName(node.object);
9001
+ }
9002
+ function isValidIdentifierName(name) {
9003
+ return /^[$A-Z_a-z][$\w]*$/.test(name);
9004
+ }
9005
+ function staticAttrExpressionToReference(node, attrsParamInfo) {
9006
+ if (!isStaticAttrExpression$1(node, attrsParamInfo)) return null;
9007
+ if (node?.type === "TSAsExpression" || node?.type === "TSSatisfiesExpression") return staticAttrExpressionToReference(node.expression, attrsParamInfo);
9008
+ if (node?.type === "Identifier" && node.name !== "undefined") return node.name;
9009
+ if (node?.type === "MemberExpression" && !node.computed) {
9010
+ const objectRef = staticAttrExpressionToReference(node.object, attrsParamInfo);
9011
+ if (objectRef && node.property?.type === "Identifier") return `${objectRef}.${node.property.name}`;
9012
+ }
9013
+ return null;
9014
+ }
9015
+ function collectBlockLocalNames(block) {
9016
+ const names = /* @__PURE__ */ new Set();
9017
+ for (const stmt of block.body ?? []) {
9018
+ if (stmt?.type === "FunctionDeclaration" || stmt?.type === "ClassDeclaration") {
9019
+ if (stmt.id?.type === "Identifier") names.add(stmt.id.name);
9020
+ continue;
9021
+ }
9022
+ if (stmt?.type !== "VariableDeclaration") continue;
9023
+ for (const decl of stmt.declarations ?? []) collectPatternNames(decl?.id, names);
9024
+ }
9025
+ return names;
9026
+ }
9027
+ function collectPatternNames(pattern, names) {
9028
+ if (!pattern) return;
9029
+ if (pattern.type === "Identifier") {
9030
+ names.add(pattern.name);
9031
+ return;
9032
+ }
9033
+ if (pattern.type === "ObjectPattern") {
9034
+ for (const prop of pattern.properties ?? []) collectPatternNames(prop?.value ?? prop?.argument, names);
9035
+ return;
9036
+ }
9037
+ if (pattern.type === "ArrayPattern") {
9038
+ for (const element of pattern.elements ?? []) collectPatternNames(element, names);
9039
+ return;
9040
+ }
9041
+ if (pattern.type === "AssignmentPattern" || pattern.type === "RestElement") collectPatternNames(pattern.left ?? pattern.argument, names);
9042
+ }
8265
9043
  function identifierNode(name) {
8266
9044
  return {
8267
9045
  type: "Identifier",
@@ -8550,6 +9328,18 @@ function collectStyledDeclsStep(ctx) {
8550
9328
  warnings: ctx.warnings
8551
9329
  }, "bail");
8552
9330
  }
9331
+ const unsupportedFunctionAttrsDecl = styledDecls.find((d) => !d.skipTransform && d.attrsInfo?.sourceKind === "function" && d.attrsInfo.hasUnsupportedValues);
9332
+ if (unsupportedFunctionAttrsDecl && ctx.options.transformMode !== "leavesOnly") {
9333
+ ctx.warnings.push({
9334
+ severity: "warning",
9335
+ type: "Unsupported .attrs() callback pattern",
9336
+ loc: unsupportedFunctionAttrsDecl.loc
9337
+ });
9338
+ return returnResult({
9339
+ code: null,
9340
+ warnings: ctx.warnings
9341
+ }, "bail");
9342
+ }
8553
9343
  if (styledDecls.length === 0) return returnResult({
8554
9344
  code: ctx.hasChanges ? formatOutput((assertNoNullNodesInArrays(root.get().node), root.toSource({
8555
9345
  quote: "double",
@@ -8882,163 +9672,6 @@ function isAstMetadataKey(key) {
8882
9672
  return key === "comments" || key === "end" || key === "extra" || key === "leadingComments" || key === "loc" || key === "start" || key === "trailingComments";
8883
9673
  }
8884
9674
  //#endregion
8885
- //#region src/internal/lower-rules/shared.ts
8886
- function findPlaceholderBlock(rawCss, placeholder) {
8887
- let searchFrom = 0;
8888
- while (true) {
8889
- const start = rawCss.indexOf(placeholder, searchFrom);
8890
- if (start < 0) return null;
8891
- const blockOpen = readNextNonWhitespace(rawCss, start + placeholder.length);
8892
- if (blockOpen?.value !== "{") {
8893
- searchFrom = start + placeholder.length;
8894
- continue;
8895
- }
8896
- return {
8897
- start,
8898
- end: blockOpen.index
8899
- };
8900
- }
8901
- }
8902
- function findPreviousOpeningBraceBeforeSelector(rawCss, position) {
8903
- let depth = 0;
8904
- for (let i = position - 1; i >= 0; i--) {
8905
- const ch = rawCss[i];
8906
- if (ch === ";") continue;
8907
- if (ch === "}") {
8908
- depth++;
8909
- continue;
8910
- }
8911
- if (ch === "{") {
8912
- if (depth > 0) {
8913
- depth--;
8914
- continue;
8915
- }
8916
- return i;
8917
- }
8918
- }
8919
- return null;
8920
- }
8921
- function readSelectorBeforeBlock(rawCss, blockStart) {
8922
- let selectorStart = blockStart - 1;
8923
- while (selectorStart >= 0) {
8924
- const ch = rawCss[selectorStart];
8925
- if (ch === "}" || ch === "{" || ch === ";") break;
8926
- selectorStart--;
8927
- }
8928
- return rawCss.slice(selectorStart + 1, blockStart).trim();
8929
- }
8930
- function readPrefixSinceLastBlockBoundary(rawCss, position) {
8931
- let start = position - 1;
8932
- while (start >= 0) {
8933
- const ch = rawCss[start];
8934
- if (ch === "{" || ch === "}") break;
8935
- start--;
8936
- }
8937
- return rawCss.slice(start + 1, position);
8938
- }
8939
- function parseSimpleParentPseudoSelectorList(selectorText) {
8940
- const parts = selectorText.split(",").map((part) => part.trim()).filter(Boolean);
8941
- if (parts.length === 0) return null;
8942
- const pseudos = [];
8943
- for (const part of parts) {
8944
- const match = part.match(/^&(:[a-z-]+(?:\([^)]*\))?)$/i);
8945
- if (!match?.[1]) return null;
8946
- pseudos.push(match[1]);
8947
- }
8948
- return pseudos;
8949
- }
8950
- /**
8951
- * Builds a `stylex.when.ancestor(pseudo, marker?)` AST call expression.
8952
- */
8953
- function makeAncestorKeyExpr(j, pseudo, markerVarName) {
8954
- const callArgs = [j.literal(pseudo)];
8955
- if (markerVarName) callArgs.push(j.identifier(markerVarName));
8956
- return j.callExpression(j.memberExpression(j.memberExpression(j.identifier("stylex"), j.identifier("when")), j.identifier("ancestor")), callArgs);
8957
- }
8958
- /**
8959
- * Builds a `stylex.when.descendant(":is(*)", marker)` AST call expression.
8960
- * Used for `&:has(${Component})` selectors where styles apply to self
8961
- * when a descendant matching the marker is present.
8962
- * Uses `:is(*)` as a required pseudo argument (StyleX API mandates a pseudo string).
8963
- */
8964
- function makeDescendantKeyExpr(j, markerVarName) {
8965
- return j.callExpression(j.memberExpression(j.memberExpression(j.identifier("stylex"), j.identifier("when")), j.identifier("descendant")), [j.literal(":is(*)"), j.identifier(markerVarName)]);
8966
- }
8967
- /**
8968
- * Creates an AST key node for a CSS property name.
8969
- * For CSS variables (e.g., --component-width), returns a string literal.
8970
- * For regular property names (e.g., backgroundColor), returns an identifier.
8971
- */
8972
- function makeCssPropKey(j, prop) {
8973
- if (!prop.match(/^[a-zA-Z_$][a-zA-Z0-9_$]*$/)) return j.literal(prop);
8974
- return j.identifier(prop);
8975
- }
8976
- /**
8977
- * Converts a CSS property name to a valid JavaScript identifier.
8978
- * For CSS variables (e.g., --component-width), converts to camelCase (componentWidth).
8979
- * For regular property names (e.g., backgroundColor), returns as-is.
8980
- *
8981
- * When `avoidNames` is provided, appends "Value" to the result if it would
8982
- * conflict with an existing binding (e.g., a top-level import). This prevents
8983
- * `no-shadow` lint errors when the generated identifier becomes a function
8984
- * parameter name.
8985
- */
8986
- function cssPropertyToIdentifier(prop, avoidNames) {
8987
- let name;
8988
- if (prop.startsWith("--")) name = prop.slice(2).replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
8989
- else name = prop;
8990
- if (avoidNames?.has(name)) return `${name}Value`;
8991
- return name;
8992
- }
8993
- /**
8994
- * Get or create a pseudo bucket for a relation override style key.
8995
- * Registers the override in `relationOverrides` if not already present.
8996
- */
8997
- function getOrCreateRelationOverrideBucket(overrideStyleKey, parentStyleKey, childStyleKey, ancestorPseudo, relationOverrides, relationOverridePseudoBuckets, childExtraStyleKeys) {
8998
- if (!relationOverridePseudoBuckets.has(overrideStyleKey)) relationOverrides.push({
8999
- parentStyleKey,
9000
- childStyleKey,
9001
- overrideStyleKey,
9002
- childExtraStyleKeys
9003
- });
9004
- else if (childExtraStyleKeys?.length) {
9005
- const existing = relationOverrides.find((o) => o.overrideStyleKey === overrideStyleKey);
9006
- if (existing && !existing.childExtraStyleKeys?.length) existing.childExtraStyleKeys = childExtraStyleKeys;
9007
- }
9008
- let pseudoBuckets = relationOverridePseudoBuckets.get(overrideStyleKey);
9009
- if (!pseudoBuckets) {
9010
- pseudoBuckets = /* @__PURE__ */ new Map();
9011
- relationOverridePseudoBuckets.set(overrideStyleKey, pseudoBuckets);
9012
- }
9013
- let bucket = pseudoBuckets.get(ancestorPseudo);
9014
- if (!bucket) {
9015
- bucket = {};
9016
- pseudoBuckets.set(ancestorPseudo, bucket);
9017
- }
9018
- return bucket;
9019
- }
9020
- function readNextNonWhitespace(rawCss, position) {
9021
- for (let i = position; i < rawCss.length; i++) {
9022
- const ch = rawCss[i];
9023
- if (!/\s/.test(ch)) return {
9024
- index: i,
9025
- value: ch
9026
- };
9027
- }
9028
- return null;
9029
- }
9030
- /**
9031
- * Creates an object property for a CSS property with shorthand support.
9032
- * Uses shorthand ({ color }) for regular properties when key matches value,
9033
- * but never for CSS variables (which need string literal keys).
9034
- */
9035
- function makeCssProperty(j, cssProp, valueIdentifierName) {
9036
- const key = makeCssPropKey(j, cssProp);
9037
- const p = j.property("init", key, j.identifier(valueIdentifierName));
9038
- if (key.type === "Identifier" && key.name === valueIdentifierName) p.shorthand = true;
9039
- return p;
9040
- }
9041
- //#endregion
9042
9675
  //#region src/internal/lower-rules/animation.ts
9043
9676
  /**
9044
9677
  * Handles animation declarations that reference keyframes.
@@ -10405,18 +11038,24 @@ function detectCascadeConflictStep(ctx) {
10405
11038
  const importEntry = importMap.get(baseIdent);
10406
11039
  if (!importEntry || importEntry.source.kind !== "absolutePath") continue;
10407
11040
  const importedPath = importEntry.source.value;
10408
- if (transformedFiles && pathSetContainsWithExtensionFallback(importedPath, transformedFiles)) continue;
11041
+ const definition = resolveImportedDefinition(ctx, importedPath, importEntry.importedName) ?? {
11042
+ path: importedPath,
11043
+ importedName: importEntry.importedName
11044
+ };
11045
+ if (transformedFiles && (pathSetContainsWithExtensionFallback(importedPath, transformedFiles) || pathSetContainsWithExtensionFallback(definition.path, transformedFiles))) continue;
10409
11046
  if (ctx.options.transformMode === "leavesOnly" && ctx.options.globalLeafKeys?.size) {
10410
- if (globalLeafKeyExists(ctx.options.globalLeafKeys, importedPath, importEntry.importedName, importEntry.importedName === "default")) continue;
11047
+ if (globalLeafKeyExists(ctx.options.globalLeafKeys, definition.path, definition.importedName, definition.importedName === "default")) continue;
10411
11048
  }
10412
- if (!(styledDefFiles && resolveStyledDefFile(importedPath, styledDefFiles) || scanFileForStyledDefs(importedPath))) continue;
11049
+ if (!(styledDefFiles && resolveStyledDefFile(definition.path, styledDefFiles) || scanFileForStyledDefs(definition.path, definition.importedName, ctx.options.resolveModule))) continue;
10413
11050
  ctx.warnings.push({
10414
11051
  severity: "warning",
10415
11052
  type: "styled(ImportedComponent) wraps a component whose file uses styled-components — convert the base component's file first to avoid CSS cascade conflicts",
10416
11053
  loc: decl.loc,
10417
11054
  context: {
10418
11055
  component: decl.localName,
10419
- base: baseIdent
11056
+ base: baseIdent,
11057
+ importedPath,
11058
+ definitionPath: definition.path
10420
11059
  }
10421
11060
  });
10422
11061
  return returnResult({
@@ -10426,6 +11065,15 @@ function detectCascadeConflictStep(ctx) {
10426
11065
  }
10427
11066
  return CONTINUE;
10428
11067
  }
11068
+ function resolveImportedDefinition(ctx, importedPath, importedName) {
11069
+ const resolve$2 = ctx.options.resolveModule;
11070
+ if (!resolve$2) return null;
11071
+ const resolved = resolveBarrelReExportBinding(resolve(importedPath), importedName, (specifier, fromFile) => resolve$2(fromFile, specifier) ?? null, readResolvedFile);
11072
+ return resolved ? {
11073
+ path: resolved.filePath,
11074
+ importedName: resolved.exportedName
11075
+ } : null;
11076
+ }
10429
11077
  /** Common TypeScript/JavaScript file extensions to try when matching import paths to styledDefFiles keys. */
10430
11078
  const EXTENSIONS = [
10431
11079
  ".tsx",
@@ -10496,23 +11144,91 @@ function pathCandidates(filePath) {
10496
11144
  * Fallback: read an imported file and scan for styled-component definitions.
10497
11145
  * Used when styledDefFiles is not available (single-file mode, tests without prepass).
10498
11146
  */
10499
- function scanFileForStyledDefs(importedPath) {
10500
- const source = tryReadFile(importedPath);
10501
- if (!source || !source.includes("styled-components")) return;
11147
+ function scanFileForStyledDefs(importedPath, importedName, resolveModule, visited = /* @__PURE__ */ new Set()) {
11148
+ const file = tryReadFileWithPath(importedPath);
11149
+ if (!file || visited.has(file.path)) return;
11150
+ visited.add(file.path);
11151
+ const source = file.source;
10502
11152
  const names = /* @__PURE__ */ new Set();
10503
- STYLED_DEF_RE.lastIndex = 0;
10504
- for (const m of source.matchAll(STYLED_DEF_RE)) if (m[1]) names.add(m[1]);
10505
- return names.size > 0 ? names : void 0;
11153
+ if (source.includes("styled-components")) {
11154
+ STYLED_DEF_RE.lastIndex = 0;
11155
+ for (const m of source.matchAll(STYLED_DEF_RE)) if (m[1]) names.add(m[1]);
11156
+ }
11157
+ if (names.size > 0) return names;
11158
+ if (!importedName) return;
11159
+ for (const reExport of reExportPaths(source, file.path, importedName, resolveModule)) {
11160
+ const nested = scanFileForStyledDefs(reExport.path, reExport.importedName, resolveModule, visited);
11161
+ if (nested) return nested;
11162
+ }
10506
11163
  }
10507
11164
  /**
10508
11165
  * Try reading a file at the given path, with extension fallback.
10509
11166
  * Import paths may lack extensions; tries exact match then common extensions.
10510
11167
  */
10511
11168
  function tryReadFile(importedPath) {
11169
+ return tryReadFileWithPath(importedPath)?.source;
11170
+ }
11171
+ function tryReadFileWithPath(importedPath) {
10512
11172
  for (const candidate of pathCandidates(importedPath)) try {
10513
- return readFileSync(candidate, "utf-8");
11173
+ return {
11174
+ path: toRealPath(candidate),
11175
+ source: readFileSync(candidate, "utf-8")
11176
+ };
10514
11177
  } catch {}
10515
11178
  }
11179
+ function reExportPaths(source, filePath, importedName, resolveModule) {
11180
+ const paths = [];
11181
+ for (const match of source.matchAll(/export\s*\{([^}]+)\}\s*from\s*["']([^"']+)["']/g)) {
11182
+ const specifiers = match[1] ?? "";
11183
+ const specifier = match[2];
11184
+ if (!specifier) continue;
11185
+ const nextImportedName = getReExportedSourceName(specifiers, importedName);
11186
+ if (!nextImportedName) continue;
11187
+ const resolved = resolveReExportSpecifier(filePath, specifier, resolveModule);
11188
+ if (resolved) paths.push({
11189
+ path: resolved,
11190
+ importedName: nextImportedName
11191
+ });
11192
+ }
11193
+ for (const match of source.matchAll(/export\s*\*\s*from\s*["']([^"']+)["']/g)) {
11194
+ const specifier = match[1];
11195
+ if (!specifier || importedName === "default") continue;
11196
+ const resolved = resolveReExportSpecifier(filePath, specifier, resolveModule);
11197
+ if (resolved && fileExportsNameThroughReExports(resolved, importedName, resolveModule)) paths.push({
11198
+ path: resolved,
11199
+ importedName
11200
+ });
11201
+ }
11202
+ return paths;
11203
+ }
11204
+ function resolveReExportSpecifier(fromFile, specifier, resolveModule) {
11205
+ if (isRelativeSpecifier(specifier)) return resolve(dirname(fromFile), specifier);
11206
+ return resolveModule?.(fromFile, specifier);
11207
+ }
11208
+ function fileExportsNameThroughReExports(importedPath, importedName, resolveModule, visited = /* @__PURE__ */ new Set()) {
11209
+ const file = tryReadFileWithPath(importedPath);
11210
+ if (!file || visited.has(file.path)) return false;
11211
+ visited.add(file.path);
11212
+ if (fileExports(file.source, importedName)) return true;
11213
+ for (const match of file.source.matchAll(/export\s*\{([^}]+)\}\s*from\s*["']([^"']+)["']/g)) {
11214
+ const specifiers = match[1] ?? "";
11215
+ const specifier = match[2];
11216
+ if (!specifier || !getReExportedSourceName(specifiers, importedName)) continue;
11217
+ if (resolveReExportSpecifier(file.path, specifier, resolveModule)) return true;
11218
+ }
11219
+ for (const match of file.source.matchAll(/export\s*\*\s*from\s*["']([^"']+)["']/g)) {
11220
+ const specifier = match[1];
11221
+ if (!specifier) continue;
11222
+ const resolved = resolveReExportSpecifier(file.path, specifier, resolveModule);
11223
+ if (resolved && fileExportsNameThroughReExports(resolved, importedName, resolveModule, visited)) return true;
11224
+ }
11225
+ return false;
11226
+ }
11227
+ function readResolvedFile(importedPath) {
11228
+ const source = tryReadFile(importedPath);
11229
+ if (source === void 0) throw new Error(`Unable to read ${importedPath}`);
11230
+ return source;
11231
+ }
10516
11232
  //#endregion
10517
11233
  //#region src/internal/transform-steps/detect-partial-cascade-conflict.ts
10518
11234
  /**
@@ -11008,7 +11724,9 @@ function canResolveBaseFromAttrs(attrsInfo) {
11008
11724
  if (attrsInfo.sourceKind === "function") return false;
11009
11725
  if (attrsInfo.sourceKind !== "object") return false;
11010
11726
  if (attrsInfo.hasUnsupportedValues) return false;
11727
+ if (Object.values(attrsInfo.staticAttrs).some((value) => !isStaticLiteral(value))) return false;
11011
11728
  if ((attrsInfo.defaultAttrs?.length ?? 0) > 0) return false;
11729
+ if ((attrsInfo.dynamicAttrs?.length ?? 0) > 0) return false;
11012
11730
  if ((attrsInfo.conditionalAttrs?.length ?? 0) > 0) return false;
11013
11731
  if ((attrsInfo.invertedBoolAttrs?.length ?? 0) > 0) return false;
11014
11732
  return true;
@@ -11730,7 +12448,10 @@ function isImportedLeafBinding(source, ident, globalLeafKeys, resolveModule, abs
11730
12448
  const initialDefFile = resolve$1(importInfo.source, absFile);
11731
12449
  if (!initialDefFile) return false;
11732
12450
  const cachedRead = (p) => readFileSync(p, "utf-8");
11733
- return importedLeafKeyExists(globalLeafKeys, toRealPath(resolveBarrelReExport(initialDefFile, importInfo.isDefault ? "default" : importInfo.exportedName, resolve$1, cachedRead) ?? initialDefFile), importInfo.exportedName, importInfo.isDefault, cachedRead);
12451
+ const reExport = resolveBarrelReExportBinding(initialDefFile, importInfo.isDefault ? "default" : importInfo.exportedName, resolve$1, cachedRead);
12452
+ const defFile = reExport?.filePath ?? initialDefFile;
12453
+ const exportedName = reExport?.exportedName ?? importInfo.exportedName;
12454
+ return importedLeafKeyExists(globalLeafKeys, toRealPath(defFile), exportedName, exportedName === "default" || importInfo.isDefault, cachedRead);
11734
12455
  }
11735
12456
  function importedLeafKeyExists(globalLeafKeys, defFile, exportedName, allowDefaultFallback, cachedRead) {
11736
12457
  if (globalLeafKeys.has(`${defFile}:${exportedName}`)) return true;
@@ -12705,7 +13426,7 @@ function emitBridgeExportsStep(ctx) {
12705
13426
  * ```
12706
13427
  */
12707
13428
  function emitStyleMerging(args) {
12708
- const { j, emitter, styleArgs: rawStyleArgs, classNameId, styleId, allowClassNameProp, allowStyleProp, allowSxProp, inlineStyleProps = [], staticClassNameExpr, isIntrinsicElement = true, wrappedAcceptsSxProp = false, keepStylePropSeparate = false } = args;
13429
+ const { j, emitter, styleArgs: rawStyleArgs, classNameId, styleId, allowClassNameProp, allowStyleProp, allowSxProp, inlineStyleProps = [], staticStyleExpr, staticClassNameExpr, isIntrinsicElement = true, wrappedAcceptsSxProp = false, keepStylePropSeparate = false } = args;
12709
13430
  const { styleMerger, emptyStyleKeys, stylesIdentifier, ancestorSelectorParents, crossFileMarkers, parentsNeedingDefaultMarker, emitTypes } = emitter;
12710
13431
  const styleArgs = filterEmptyStyleArgs({
12711
13432
  styleArgs: rawStyleArgs,
@@ -12733,10 +13454,11 @@ function emitStyleMerging(args) {
12733
13454
  allowClassNameProp,
12734
13455
  allowStyleProp,
12735
13456
  inlineStyleProps,
13457
+ staticStyleExpr,
12736
13458
  staticClassNameExpr,
12737
13459
  emitTypes
12738
13460
  });
12739
- if (keepStylePropSeparate && allowStyleProp && !wrappedAcceptsSxProp && inlineStyleProps.length === 0) return emitVerbosePattern({
13461
+ if (keepStylePropSeparate && allowStyleProp && !wrappedAcceptsSxProp && inlineStyleProps.length === 0 && !staticStyleExpr) return emitVerbosePattern({
12740
13462
  j,
12741
13463
  styleArgs,
12742
13464
  classNameId,
@@ -12748,8 +13470,8 @@ function emitStyleMerging(args) {
12748
13470
  staticClassNameExpr,
12749
13471
  emitTypes
12750
13472
  });
12751
- if (wrappedAcceptsSxProp && inlineStyleProps.length === 0 && !staticClassNameExpr) return buildSxOnlyResult(j, styleArgs, { normalizeOptionalEntries: true });
12752
- if (wrappedAcceptsSxProp && inlineStyleProps.length === 0 && staticClassNameExpr) return buildSxWithExternalPropsResult({
13473
+ if (wrappedAcceptsSxProp && inlineStyleProps.length === 0 && !staticStyleExpr && !staticClassNameExpr) return buildSxOnlyResult(j, styleArgs, { normalizeOptionalEntries: true });
13474
+ if (wrappedAcceptsSxProp && inlineStyleProps.length === 0 && !staticStyleExpr && staticClassNameExpr) return buildSxWithExternalPropsResult({
12753
13475
  j,
12754
13476
  styleArgs,
12755
13477
  classNameId,
@@ -12758,7 +13480,7 @@ function emitStyleMerging(args) {
12758
13480
  allowStyleProp,
12759
13481
  staticClassNameExpr
12760
13482
  });
12761
- if (!allowClassNameProp && !allowStyleProp && inlineStyleProps.length === 0 && !staticClassNameExpr) {
13483
+ if (!allowClassNameProp && !allowStyleProp && inlineStyleProps.length === 0 && !staticStyleExpr && !staticClassNameExpr) {
12762
13484
  const sid = emitter.stylesIdentifier;
12763
13485
  const hasLocalRef = styleArgs.some((a) => j([a]).find(j.Identifier, { name: sid }).size() > 0);
12764
13486
  if (emitter.useSxProp && isIntrinsicElement && hasLocalRef) return buildSxOnlyResult(j, styleArgs);
@@ -12772,7 +13494,7 @@ function emitStyleMerging(args) {
12772
13494
  styleAttr: null
12773
13495
  };
12774
13496
  }
12775
- if (styleMerger && (allowClassNameProp || allowStyleProp)) return emitWithMerger({
13497
+ if (styleMerger && (allowClassNameProp || allowStyleProp || staticStyleExpr)) return emitWithMerger({
12776
13498
  j,
12777
13499
  styleMerger,
12778
13500
  styleArgs,
@@ -12781,6 +13503,7 @@ function emitStyleMerging(args) {
12781
13503
  allowClassNameProp,
12782
13504
  allowStyleProp,
12783
13505
  inlineStyleProps,
13506
+ staticStyleExpr,
12784
13507
  staticClassNameExpr,
12785
13508
  emitTypes
12786
13509
  });
@@ -12793,6 +13516,7 @@ function emitStyleMerging(args) {
12793
13516
  allowStyleProp,
12794
13517
  allowSxProp: allowSxProp || wrappedAcceptsSxProp,
12795
13518
  inlineStyleProps,
13519
+ staticStyleExpr,
12796
13520
  staticClassNameExpr,
12797
13521
  emitTypes
12798
13522
  });
@@ -12812,12 +13536,16 @@ function filterEmptyStyleArgs(args) {
12812
13536
  return styleArgs.filter((arg) => !isEmptyStyleArg(arg));
12813
13537
  }
12814
13538
  function emitWithoutStylex(args) {
12815
- const { j, classNameId, styleId, allowClassNameProp, allowStyleProp, inlineStyleProps, staticClassNameExpr, emitTypes } = args;
13539
+ const { j, classNameId, styleId, allowClassNameProp, allowStyleProp, inlineStyleProps, staticStyleExpr, staticClassNameExpr, emitTypes } = args;
12816
13540
  const classNameAttr = allowClassNameProp ? classNameId : staticClassNameExpr ?? null;
12817
13541
  let styleAttr = null;
12818
- if (allowStyleProp) if (inlineStyleProps.length > 0) styleAttr = maybeCastStyleForCustomProps(j, j.objectExpression([...inlineStyleProps.map((p) => inlineStyleProperty(j, p)), j.spreadElement(styleId)]), inlineStyleProps, emitTypes);
13542
+ if (allowStyleProp) if (inlineStyleProps.length > 0 || staticStyleExpr) styleAttr = maybeCastStyleForCustomProps(j, j.objectExpression([
13543
+ ...staticStyleExpr ? [j.spreadElement(staticStyleExpr)] : [],
13544
+ ...inlineStyleProps.map((p) => inlineStyleProperty(j, p)),
13545
+ j.spreadElement(styleId)
13546
+ ]), inlineStyleProps, emitTypes);
12819
13547
  else styleAttr = styleId;
12820
- else if (inlineStyleProps.length > 0) styleAttr = maybeCastStyleForCustomProps(j, j.objectExpression(inlineStyleProps.map((p) => inlineStyleProperty(j, p))), inlineStyleProps, emitTypes);
13548
+ else if (inlineStyleProps.length > 0 || staticStyleExpr) styleAttr = maybeCastStyleForCustomProps(j, staticStyleExpr && inlineStyleProps.length === 0 ? staticStyleExpr : j.objectExpression([...staticStyleExpr ? [j.spreadElement(staticStyleExpr)] : [], ...inlineStyleProps.map((p) => inlineStyleProperty(j, p))]), inlineStyleProps, emitTypes);
12821
13549
  return {
12822
13550
  needsSxVar: false,
12823
13551
  sxDecl: null,
@@ -12832,7 +13560,7 @@ function emitWithoutStylex(args) {
12832
13560
  * Generates the merger function call pattern.
12833
13561
  */
12834
13562
  function emitWithMerger(args) {
12835
- const { j, styleMerger, styleArgs, classNameId, styleId, allowClassNameProp, allowStyleProp, inlineStyleProps, staticClassNameExpr, emitTypes } = args;
13563
+ const { j, styleMerger, styleArgs, classNameId, styleId, allowClassNameProp, allowStyleProp, inlineStyleProps, staticStyleExpr, staticClassNameExpr, emitTypes } = args;
12836
13564
  const firstStyleArg = styleArgs[0];
12837
13565
  const mergerArgs = [styleArgs.length === 1 && firstStyleArg ? firstStyleArg : j.arrayExpression(styleArgs)];
12838
13566
  const classNameArg = buildMergerClassNameArg({
@@ -12841,15 +13569,16 @@ function emitWithMerger(args) {
12841
13569
  allowClassNameProp,
12842
13570
  staticClassNameExpr
12843
13571
  });
12844
- if (allowClassNameProp || allowStyleProp || classNameArg) {
13572
+ if (allowClassNameProp || allowStyleProp || classNameArg || staticStyleExpr) {
12845
13573
  if (classNameArg) mergerArgs.push(classNameArg);
12846
- else if (allowStyleProp) mergerArgs.push(j.identifier("undefined"));
12847
- if (allowStyleProp) if (inlineStyleProps.length > 0) mergerArgs.push(maybeCastStyleForCustomProps(j, j.objectExpression([...inlineStyleProps.map((p) => inlineStyleProperty(j, p)), j.spreadElement(styleId)]), inlineStyleProps, emitTypes));
13574
+ else if (allowStyleProp || staticStyleExpr || inlineStyleProps.length > 0) mergerArgs.push(j.identifier("undefined"));
13575
+ if (allowStyleProp) if (inlineStyleProps.length > 0 || staticStyleExpr) mergerArgs.push(maybeCastStyleForCustomProps(j, j.objectExpression([
13576
+ ...staticStyleExpr ? [j.spreadElement(staticStyleExpr)] : [],
13577
+ ...inlineStyleProps.map((p) => inlineStyleProperty(j, p)),
13578
+ j.spreadElement(styleId)
13579
+ ]), inlineStyleProps, emitTypes));
12848
13580
  else mergerArgs.push(styleId);
12849
- else if (inlineStyleProps.length > 0) {
12850
- mergerArgs.push(j.identifier("undefined"));
12851
- mergerArgs.push(maybeCastStyleForCustomProps(j, j.objectExpression(inlineStyleProps.map((p) => inlineStyleProperty(j, p))), inlineStyleProps, emitTypes));
12852
- }
13581
+ else if (inlineStyleProps.length > 0 || staticStyleExpr) mergerArgs.push(maybeCastStyleForCustomProps(j, staticStyleExpr && inlineStyleProps.length === 0 ? staticStyleExpr : j.objectExpression([...staticStyleExpr ? [j.spreadElement(staticStyleExpr)] : [], ...inlineStyleProps.map((p) => inlineStyleProperty(j, p))]), inlineStyleProps, emitTypes));
12853
13582
  }
12854
13583
  return {
12855
13584
  needsSxVar: false,
@@ -12883,7 +13612,7 @@ function buildClassNameAttributeExpr(args) {
12883
13612
  * Generates the verbose className/style merging pattern.
12884
13613
  */
12885
13614
  function emitVerbosePattern(args) {
12886
- const { j, styleArgs, classNameId, styleId, allowClassNameProp, allowStyleProp, allowSxProp, inlineStyleProps, staticClassNameExpr, emitTypes } = args;
13615
+ const { j, styleArgs, classNameId, styleId, allowClassNameProp, allowStyleProp, allowSxProp, inlineStyleProps, staticStyleExpr, staticClassNameExpr, emitTypes } = args;
12887
13616
  const sxVarName = allowSxProp ? "_sx" : "sx";
12888
13617
  const stylexPropsCall = j.callExpression(j.memberExpression(j.identifier("stylex"), j.identifier("props")), styleArgs);
12889
13618
  const sxDecl = j.variableDeclaration("const", [j.variableDeclarator(j.identifier(sxVarName), stylexPropsCall)]);
@@ -12897,9 +13626,10 @@ function emitVerbosePattern(args) {
12897
13626
  classNameAttr = j.callExpression(j.memberExpression(j.callExpression(j.memberExpression(j.arrayExpression(parts), j.identifier("filter")), [j.identifier("Boolean")]), j.identifier("join")), [j.literal(" ")]);
12898
13627
  }
12899
13628
  let styleAttr = null;
12900
- if (allowStyleProp || inlineStyleProps.length > 0) {
13629
+ if (allowStyleProp || inlineStyleProps.length > 0 || staticStyleExpr) {
12901
13630
  const spreads = [
12902
13631
  j.spreadElement(j.memberExpression(j.identifier(sxVarName), j.identifier("style"))),
13632
+ ...staticStyleExpr ? [j.spreadElement(staticStyleExpr)] : [],
12903
13633
  ...inlineStyleProps.map((p) => inlineStyleProperty(j, p)),
12904
13634
  ...allowStyleProp ? [j.spreadElement(styleId)] : []
12905
13635
  ];
@@ -13757,17 +14487,40 @@ function buildInvertedBoolAttrs(j, args) {
13757
14487
  const { invertedBoolAttrs, testExprFor } = args;
13758
14488
  return invertedBoolAttrs.map((inv) => j.jsxAttribute(j.jsxIdentifier(inv.attrName), j.jsxExpressionContainer(j.binaryExpression("!==", testExprFor(inv.jsxProp), j.booleanLiteral(true)))));
13759
14489
  }
14490
+ function buildDynamicAttrsFromProps(j, args) {
14491
+ const { dynamicAttrs, propExprFor } = args;
14492
+ return dynamicAttrs.map((attr) => {
14493
+ const propExpr = propExprFor(attr.jsxProp);
14494
+ const valueExpr = attr.defaultValue === void 0 ? propExpr : j.conditionalExpression(j.binaryExpression("===", propExpr, j.identifier("undefined")), literalExprForAttrDefault(j, attr.defaultValue), propExpr);
14495
+ return j.jsxAttribute(j.jsxIdentifier(attr.attrName), j.jsxExpressionContainer(valueExpr));
14496
+ });
14497
+ }
14498
+ function literalExprForAttrDefault(j, value) {
14499
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") return j.literal(value);
14500
+ if (value === null) return j.literal(null);
14501
+ return j.identifier("undefined");
14502
+ }
13760
14503
  function buildStaticAttrsFromRecord(j, staticAttrs, options) {
13761
- const booleanTrueAsShorthand = options?.booleanTrueAsShorthand ?? true;
13762
14504
  const attrs = [];
13763
- for (const [key, value] of Object.entries(staticAttrs)) if (typeof value === "string") attrs.push(j.jsxAttribute(j.jsxIdentifier(key), j.literal(value)));
13764
- else if (typeof value === "boolean") if (value) attrs.push(j.jsxAttribute(j.jsxIdentifier(key), booleanTrueAsShorthand ? null : j.jsxExpressionContainer(j.booleanLiteral(true))));
13765
- else attrs.push(j.jsxAttribute(j.jsxIdentifier(key), j.jsxExpressionContainer(j.literal(false))));
13766
- else if (typeof value === "number") attrs.push(j.jsxAttribute(j.jsxIdentifier(key), j.jsxExpressionContainer(j.literal(value))));
13767
- else if (value === void 0) attrs.push(j.jsxAttribute(j.jsxIdentifier(key), j.jsxExpressionContainer(j.identifier("undefined"))));
13768
- else if (value === null) attrs.push(j.jsxAttribute(j.jsxIdentifier(key), j.jsxExpressionContainer(j.literal(null))));
14505
+ for (const [key, value] of Object.entries(staticAttrs)) {
14506
+ const attr = buildStaticAttrFromValue(j, key, value, options);
14507
+ if (attr) attrs.push(attr);
14508
+ }
13769
14509
  return attrs;
13770
14510
  }
14511
+ function buildStaticAttrFromValue(j, key, value, options) {
14512
+ const booleanTrueAsShorthand = options?.booleanTrueAsShorthand ?? true;
14513
+ if (typeof value === "string") return j.jsxAttribute(j.jsxIdentifier(key), j.literal(value));
14514
+ if (typeof value === "boolean") return j.jsxAttribute(j.jsxIdentifier(key), value && booleanTrueAsShorthand ? null : j.jsxExpressionContainer(j.booleanLiteral(value)));
14515
+ if (typeof value === "number") return j.jsxAttribute(j.jsxIdentifier(key), j.jsxExpressionContainer(j.literal(value)));
14516
+ if (value === void 0) return j.jsxAttribute(j.jsxIdentifier(key), j.jsxExpressionContainer(j.identifier("undefined")));
14517
+ if (value === null) return j.jsxAttribute(j.jsxIdentifier(key), j.jsxExpressionContainer(j.literal(null)));
14518
+ if (isStaticAttrExpression(value)) return j.jsxAttribute(j.jsxIdentifier(key), j.jsxExpressionContainer(cloneAstNode(value)));
14519
+ return null;
14520
+ }
14521
+ function isStaticAttrExpression(value) {
14522
+ return !!value && typeof value === "object" && typeof value.type === "string";
14523
+ }
13771
14524
  /**
13772
14525
  * Build all attrs from attrsInfo in the correct order:
13773
14526
  * defaultAttrs, conditionalAttrs, invertedBoolAttrs, staticAttrs
@@ -13997,8 +14750,11 @@ function escapeTemplateRaw(s) {
13997
14750
  return s.replace(/\\|`|\$\{/g, "\\$&");
13998
14751
  }
13999
14752
  function buildStaticClassNameExpr(j, staticClassName, bridgeClassVar, extraClassNames) {
14000
- if (!(extraClassNames && extraClassNames.length > 0)) {
14001
- if (staticClassName && bridgeClassVar) {
14753
+ const hasExtra = extraClassNames && extraClassNames.length > 0;
14754
+ const staticClassNameExpr = typeof staticClassName === "string" ? void 0 : isExpressionLike(staticClassName) ? cloneAstNode(staticClassName) : void 0;
14755
+ if (!hasExtra) {
14756
+ if (staticClassNameExpr && bridgeClassVar) return j.callExpression(j.memberExpression(j.callExpression(j.memberExpression(j.arrayExpression([staticClassNameExpr, j.identifier(bridgeClassVar)]), j.identifier("filter")), [j.identifier("Boolean")]), j.identifier("join")), [j.literal(" ")]);
14757
+ if (typeof staticClassName === "string" && bridgeClassVar) {
14002
14758
  const raw = escapeTemplateRaw(`${staticClassName} `);
14003
14759
  return j.templateLiteral([j.templateElement({
14004
14760
  raw,
@@ -14009,16 +14765,29 @@ function buildStaticClassNameExpr(j, staticClassName, bridgeClassVar, extraClass
14009
14765
  }, true)], [j.identifier(bridgeClassVar)]);
14010
14766
  }
14011
14767
  if (bridgeClassVar) return j.identifier(bridgeClassVar);
14012
- if (staticClassName) return j.literal(staticClassName);
14768
+ if (staticClassNameExpr) return staticClassNameExpr;
14769
+ if (typeof staticClassName === "string" && staticClassName) return j.literal(staticClassName);
14013
14770
  return;
14014
14771
  }
14772
+ if (staticClassNameExpr) return buildClassNameJoinExpr$1(j, [
14773
+ staticClassNameExpr,
14774
+ ...bridgeClassVar ? [j.identifier(bridgeClassVar)] : [],
14775
+ ...(extraClassNames ?? []).map((extra) => extra.expr)
14776
+ ]);
14015
14777
  const expressions = [];
14016
14778
  const quasis = [];
14017
- const leadingText = staticClassName ? `${escapeTemplateRaw(staticClassName)} ` : "";
14779
+ const leadingText = typeof staticClassName === "string" && staticClassName ? `${escapeTemplateRaw(staticClassName)} ` : "";
14018
14780
  quasis.push(j.templateElement({
14019
14781
  raw: leadingText,
14020
- cooked: staticClassName ? `${staticClassName} ` : ""
14782
+ cooked: typeof staticClassName === "string" && staticClassName ? `${staticClassName} ` : ""
14021
14783
  }, false));
14784
+ if (staticClassNameExpr) {
14785
+ expressions.push(staticClassNameExpr);
14786
+ quasis.push(j.templateElement({
14787
+ raw: " ",
14788
+ cooked: " "
14789
+ }, false));
14790
+ }
14022
14791
  if (bridgeClassVar) {
14023
14792
  expressions.push(j.identifier(bridgeClassVar));
14024
14793
  quasis.push(j.templateElement({
@@ -14038,15 +14807,18 @@ function buildStaticClassNameExpr(j, staticClassName, bridgeClassVar, extraClass
14038
14807
  }, false));
14039
14808
  }
14040
14809
  if (expressions.length === 0) {
14041
- if (staticClassName) return j.literal(staticClassName);
14810
+ if (typeof staticClassName === "string" && staticClassName) return j.literal(staticClassName);
14042
14811
  return;
14043
14812
  }
14044
- if (!staticClassName && !bridgeClassVar) quasis[0] = j.templateElement({
14813
+ if (!staticClassName && !staticClassNameExpr && !bridgeClassVar) quasis[0] = j.templateElement({
14045
14814
  raw: "",
14046
14815
  cooked: ""
14047
14816
  }, false);
14048
14817
  return j.templateLiteral(quasis, expressions);
14049
14818
  }
14819
+ function buildClassNameJoinExpr$1(j, parts) {
14820
+ return j.callExpression(j.memberExpression(j.callExpression(j.memberExpression(j.arrayExpression(parts), j.identifier("filter")), [j.identifier("Boolean")]), j.identifier("join")), [j.literal(" ")]);
14821
+ }
14050
14822
  /**
14051
14823
  * Extracts a static className value (if present) from attrsInfo.staticAttrs
14052
14824
  * so it can be passed to the style merger separately, and returns the
@@ -14070,7 +14842,7 @@ function splitAttrsInfo(j, attrsInfo, bridgeClassVar, extraClassNames) {
14070
14842
  staticAttrs: attrsInfo.staticAttrs ?? {},
14071
14843
  conditionalAttrs: attrsInfo.conditionalAttrs ?? []
14072
14844
  };
14073
- const hasStaticClassName = typeof className === "string";
14845
+ const hasStaticClassName = typeof className === "string" || isExpressionLike(className);
14074
14846
  const hasExtraClassNames = extraClassNames && extraClassNames.length > 0;
14075
14847
  if (!hasStaticClassName && !bridgeClassVar && !hasExtraClassNames) return {
14076
14848
  attrsInfo: normalized,
@@ -14087,6 +14859,9 @@ function splitAttrsInfo(j, attrsInfo, bridgeClassVar, extraClassNames) {
14087
14859
  staticClassNameExpr: buildStaticClassNameExpr(j, hasStaticClassName ? className : void 0, bridgeClassVar, extraClassNames)
14088
14860
  };
14089
14861
  }
14862
+ function isExpressionLike(value) {
14863
+ return !!value && typeof value === "object" && typeof value.type === "string";
14864
+ }
14090
14865
  /**
14091
14866
  * Build variant dimension lookup expressions for StyleX variants recipe
14092
14867
  * pattern.
@@ -15417,7 +16192,7 @@ var WrapperEmitter = class {
15417
16192
  return false;
15418
16193
  }
15419
16194
  emitMinimalWrapper(args) {
15420
- const { localName, tagName, propsTypeName, inlineTypeText, styleArgs, destructureProps, propDefaults, allowClassNameProp = false, allowStyleProp = false, allowAsProp = false, includeRefProp = false, includeRest = true, defaultAttrs = [], conditionalAttrs = [], invertedBoolAttrs = [], staticAttrs = {}, inlineStyleProps = [], attrsAsTag, bridgeClassVar } = args;
16195
+ const { localName, tagName, propsTypeName, inlineTypeText, styleArgs, destructureProps, propDefaults, allowClassNameProp = false, allowStyleProp = false, allowAsProp = false, includeRefProp = false, includeRest = true, defaultAttrs = [], dynamicAttrs = [], conditionalAttrs = [], invertedBoolAttrs = [], staticAttrs = {}, attrsStaticStyleExpr, inlineStyleProps = [], attrsAsTag, bridgeClassVar } = args;
15421
16196
  const { j } = this;
15422
16197
  const expandedDestructureProps = new Set(destructureProps.filter(Boolean));
15423
16198
  const collectCondIdentifiers = (node) => {
@@ -15479,6 +16254,7 @@ var WrapperEmitter = class {
15479
16254
  else patternProps.push(this.patternProp(name));
15480
16255
  }
15481
16256
  for (const a of defaultAttrs) if (!expandedDestructureProps.has(a.jsxProp)) patternProps.push(this.patternProp(a.jsxProp));
16257
+ for (const attr of dynamicAttrs) if (!expandedDestructureProps.has(attr.jsxProp)) patternProps.push(this.patternProp(attr.jsxProp));
15482
16258
  let restId = includeRest ? j.identifier("rest") : null;
15483
16259
  if (includeRest && restId) patternProps.push(j.restElement(restId));
15484
16260
  const usePropsDirectlyForRest = includeRest && patternProps.length === 1 && patternProps[0]?.type === "RestElement";
@@ -15486,7 +16262,7 @@ var WrapperEmitter = class {
15486
16262
  if (usePropsDirectlyForRest) restId = propsId;
15487
16263
  const classNameId = j.identifier("className");
15488
16264
  const styleId = j.identifier("style");
15489
- const staticClassName = typeof staticAttrs.className === "string" ? staticAttrs.className : void 0;
16265
+ const staticClassName = staticAttrs.className;
15490
16266
  const hasStaticAsFallback = allowForwardedAsProp && Object.hasOwn(staticAttrs, "as");
15491
16267
  const staticAsFallback = hasStaticAsFallback ? staticAttrs.as : void 0;
15492
16268
  const filteredStaticAttrs = (() => {
@@ -15507,6 +16283,7 @@ var WrapperEmitter = class {
15507
16283
  allowClassNameProp,
15508
16284
  allowStyleProp,
15509
16285
  inlineStyleProps,
16286
+ staticStyleExpr: attrsStaticStyleExpr,
15510
16287
  staticClassNameExpr,
15511
16288
  isIntrinsicElement: !allowAsProp
15512
16289
  });
@@ -15519,9 +16296,11 @@ var WrapperEmitter = class {
15519
16296
  for (const inv of invertedBoolAttrs) jsxAttrs.push(j.jsxAttribute(j.jsxIdentifier(inv.attrName), j.jsxExpressionContainer(j.binaryExpression("!==", j.identifier(inv.jsxProp), j.booleanLiteral(true)))));
15520
16297
  if (includeRefProp) jsxAttrs.push(j.jsxAttribute(j.jsxIdentifier("ref"), j.jsxExpressionContainer(j.identifier("ref"))));
15521
16298
  if (includeRest && restId) jsxAttrs.push(j.jsxSpreadAttribute(restId));
15522
- for (const [key, value] of Object.entries(filteredStaticAttrs)) if (typeof value === "string") jsxAttrs.push(j.jsxAttribute(j.jsxIdentifier(key), j.literal(value)));
15523
- else if (typeof value === "boolean") jsxAttrs.push(j.jsxAttribute(j.jsxIdentifier(key), value ? null : j.jsxExpressionContainer(j.literal(false))));
15524
- else if (typeof value === "number") jsxAttrs.push(j.jsxAttribute(j.jsxIdentifier(key), j.jsxExpressionContainer(j.literal(value))));
16299
+ jsxAttrs.push(...buildDynamicAttrsFromProps(j, {
16300
+ dynamicAttrs,
16301
+ propExprFor: (prop) => j.identifier(prop)
16302
+ }));
16303
+ jsxAttrs.push(...buildStaticAttrsFromRecord(j, filteredStaticAttrs));
15525
16304
  if (allowForwardedAsProp) {
15526
16305
  const forwardedAsValueExpr = hasStaticAsFallback ? j.logicalExpression("??", j.identifier("forwardedAs"), this.literalExpr(staticAsFallback)) : j.identifier("forwardedAs");
15527
16306
  jsxAttrs.push(j.jsxAttribute(j.jsxIdentifier("as"), j.jsxExpressionContainer(forwardedAsValueExpr)));
@@ -15531,10 +16310,10 @@ var WrapperEmitter = class {
15531
16310
  else if (merging.jsxSpreadExpr) jsxAttrs.push(j.jsxSpreadAttribute(merging.jsxSpreadExpr));
15532
16311
  if (merging.classNameAttr) jsxAttrs.push(j.jsxAttribute(j.jsxIdentifier("className"), j.jsxExpressionContainer(merging.classNameAttr)));
15533
16312
  if (merging.styleAttr) jsxAttrs.push(j.jsxAttribute(j.jsxIdentifier("style"), j.jsxExpressionContainer(merging.styleAttr)));
15534
- const renderedTagName = allowAsProp ? "Component" : attrsAsTag ?? tagName;
15535
- const openingEl = j.jsxOpeningElement(j.jsxIdentifier(renderedTagName), jsxAttrs, isVoidTag);
16313
+ const renderedJsxName = jsxNameFromString(j, allowAsProp ? "Component" : attrsAsTag ?? tagName);
16314
+ const openingEl = j.jsxOpeningElement(renderedJsxName, jsxAttrs, isVoidTag);
15536
16315
  const childrenExpr = usePropsChildrenDirectly ? j.memberExpression(propsId, j.identifier("children")) : j.identifier("children");
15537
- const jsx = j.jsxElement(openingEl, isVoidTag ? null : j.jsxClosingElement(j.jsxIdentifier(renderedTagName)), isVoidTag ? [] : [j.jsxExpressionContainer(childrenExpr)]);
16316
+ const jsx = j.jsxElement(openingEl, isVoidTag ? null : j.jsxClosingElement(renderedJsxName), isVoidTag ? [] : [j.jsxExpressionContainer(childrenExpr)]);
15538
16317
  const bodyStmts = [];
15539
16318
  if (!usePropsDirectlyForRest && !usePropsChildrenDirectly) bodyStmts.push(j.variableDeclaration("const", [j.variableDeclarator(j.objectPattern(patternProps), propsId)]));
15540
16319
  if (merging.sxDecl) bodyStmts.push(merging.sxDecl);
@@ -15571,6 +16350,9 @@ var WrapperEmitter = class {
15571
16350
  buildInvertedBoolAttrs(args) {
15572
16351
  return buildInvertedBoolAttrs(this.j, args);
15573
16352
  }
16353
+ buildDynamicAttrsFromProps(args) {
16354
+ return buildDynamicAttrsFromProps(this.j, args);
16355
+ }
15574
16356
  buildStaticAttrsFromRecord(staticAttrs, options) {
15575
16357
  return buildStaticAttrsFromRecord(this.j, staticAttrs, options);
15576
16358
  }
@@ -15673,6 +16455,12 @@ function extractObjectLiteralMembers(typeText) {
15673
16455
  if (last) members.push(last);
15674
16456
  return members.length > 0 ? members : null;
15675
16457
  }
16458
+ function jsxNameFromString(j, name) {
16459
+ if (!name.includes(".")) return j.jsxIdentifier(name);
16460
+ const [root, ...members] = name.split(".");
16461
+ if (!root || members.length === 0) return j.jsxIdentifier(name);
16462
+ return members.reduce((object, member) => j.jsxMemberExpression(object, j.jsxIdentifier(member)), j.jsxIdentifier(root));
16463
+ }
15676
16464
  //#endregion
15677
16465
  //#region src/internal/emit-wrappers/compound-variants.ts
15678
16466
  function collectCompoundVariantKeys(compoundVariants, opts) {
@@ -16096,16 +16884,17 @@ function emitComponentWrappers(emitter) {
16096
16884
  let jsxTagName;
16097
16885
  if (isPolymorphicComponentWrapper) jsxTagName = j.jsxIdentifier("Component");
16098
16886
  else if (renderedComponent.includes(".")) {
16099
- const parts = renderedComponent.split(".");
16100
- const firstPart = parts[0];
16101
- if (!firstPart) jsxTagName = j.jsxIdentifier(renderedComponent);
16102
- else jsxTagName = j.jsxMemberExpression(j.jsxIdentifier(firstPart), j.jsxIdentifier(parts.slice(1).join(".")));
16887
+ const [firstPart, ...memberParts] = renderedComponent.split(".");
16888
+ if (!firstPart || memberParts.length === 0) jsxTagName = j.jsxIdentifier(renderedComponent);
16889
+ else jsxTagName = memberParts.reduce((object, member) => j.jsxMemberExpression(object, j.jsxIdentifier(member)), j.jsxIdentifier(firstPart));
16103
16890
  } else jsxTagName = j.jsxIdentifier(renderedComponent);
16104
16891
  const { attrsInfo, staticClassNameExpr } = emitter.splitAttrsInfo(d.attrsInfo, getBridgeClassVar(d), d.extraClassNames);
16105
16892
  const defaultAttrs = attrsInfo?.defaultAttrs ?? [];
16893
+ const dynamicAttrs = attrsInfo?.dynamicAttrs ?? [];
16106
16894
  const staticAttrs = normalizeStaticForwardedAsAttr(attrsInfo?.staticAttrs ?? {}, shouldLowerForwardedAs);
16107
- const needsSxVar = allowClassNameProp || allowStyleProp || wrappedAcceptsSx || !!d.inlineStyleProps?.length || !!staticClassNameExpr;
16108
- const needsDestructure = destructureProps.length > 0 || needsSxVar || isPolymorphicComponentWrapper || defaultAttrs.length > 0 || shouldLowerForwardedAs || (d.supportsRefProp ?? false);
16895
+ const attrsStaticStyleExpr = attrsInfo?.attrsStaticStyleExpr;
16896
+ const needsSxVar = allowClassNameProp || allowStyleProp || wrappedAcceptsSx || !!d.inlineStyleProps?.length || !!attrsStaticStyleExpr || !!staticClassNameExpr;
16897
+ const needsDestructure = destructureProps.length > 0 || needsSxVar || isPolymorphicComponentWrapper || defaultAttrs.length > 0 || dynamicAttrs.length > 0 || shouldLowerForwardedAs || (d.supportsRefProp ?? false);
16109
16898
  const includeChildren = !isPolymorphicComponentWrapper && emitter.hasJsxChildrenUsage(d.localName);
16110
16899
  if (needsDestructure) {
16111
16900
  const childrenId = j.identifier("children");
@@ -16119,7 +16908,8 @@ function emitComponentWrappers(emitter) {
16119
16908
  const wrappedComponentExpr = buildWrappedComponentExpr();
16120
16909
  if (allowSxProp || wrappedAcceptsSx) styleArgs.push(sxId);
16121
16910
  for (const attr of defaultAttrs) if (!destructureProps.includes(attr.jsxProp)) destructureProps.push(attr.jsxProp);
16122
- const canForwardClassNameStyleThroughRest = wrappedAcceptsSx && !(staticClassNameExpr || d.inlineStyleProps?.length);
16911
+ for (const attr of dynamicAttrs) if (!destructureProps.includes(attr.jsxProp)) destructureProps.push(attr.jsxProp);
16912
+ const canForwardClassNameStyleThroughRest = wrappedAcceptsSx && !(staticClassNameExpr || attrsStaticStyleExpr || d.inlineStyleProps?.length);
16123
16913
  const destructureClassName = allowClassNameProp && !canForwardClassNameStyleThroughRest;
16124
16914
  const destructureStyle = allowStyleProp && !canForwardClassNameStyleThroughRest;
16125
16915
  const destructureSx = allowSxProp || wrappedAcceptsSx;
@@ -16149,6 +16939,7 @@ function emitComponentWrappers(emitter) {
16149
16939
  allowStyleProp,
16150
16940
  allowSxProp,
16151
16941
  inlineStyleProps: d.inlineStyleProps ?? [],
16942
+ staticStyleExpr: attrsStaticStyleExpr,
16152
16943
  staticClassNameExpr,
16153
16944
  isIntrinsicElement: false,
16154
16945
  wrappedAcceptsSxProp: wrappedAcceptsSx,
@@ -16173,6 +16964,7 @@ function emitComponentWrappers(emitter) {
16173
16964
  if (d.supportsRefProp ?? false) openingAttrs.push(j.jsxAttribute(j.jsxIdentifier("ref"), j.jsxExpressionContainer(refId)));
16174
16965
  const forwardedProps = /* @__PURE__ */ new Set();
16175
16966
  for (const attr of defaultAttrs) forwardedProps.add(attr.attrName);
16967
+ for (const attr of dynamicAttrs) forwardedProps.add(attr.attrName);
16176
16968
  for (const key of Object.keys(staticAttrsWithoutForwardedAsFallback)) forwardedProps.add(key);
16177
16969
  const pushForwardedProp = (propName) => {
16178
16970
  if (forwardedProps.has(propName)) return;
@@ -16204,8 +16996,13 @@ function emitComponentWrappers(emitter) {
16204
16996
  if (!baseExplicitProps || baseExplicitProps.has(propName)) pushForwardedProp(propName);
16205
16997
  }
16206
16998
  for (const attr of defaultAttrs) if (attr.jsxProp !== attr.attrName && !attr.jsxProp.startsWith("$")) pushForwardedProp(attr.jsxProp);
16999
+ for (const attr of dynamicAttrs) if (attr.jsxProp !== attr.attrName && !attr.jsxProp.startsWith("$")) pushForwardedProp(attr.jsxProp);
16207
17000
  for (const propName of namespaceBooleanProps) pushForwardedProp(propName);
16208
17001
  openingAttrs.push(j.jsxSpreadAttribute(restId));
17002
+ openingAttrs.push(...emitter.buildDynamicAttrsFromProps({
17003
+ dynamicAttrs,
17004
+ propExprFor: (prop) => j.identifier(prop)
17005
+ }));
16209
17006
  openingAttrs.push(...emitter.buildStaticAttrsFromRecord(staticAttrsWithoutForwardedAsFallback, { booleanTrueAsShorthand: false }));
16210
17007
  if (shouldLowerForwardedAs) {
16211
17008
  let forwardedAsValueExpr = forwardedAsId;
@@ -16232,6 +17029,10 @@ function emitComponentWrappers(emitter) {
16232
17029
  const openingAttrs = [];
16233
17030
  openingAttrs.push(...emitter.buildStaticValueAttrs({ attrs: defaultAttrs }));
16234
17031
  openingAttrs.push(j.jsxSpreadAttribute(propsId));
17032
+ openingAttrs.push(...emitter.buildDynamicAttrsFromProps({
17033
+ dynamicAttrs,
17034
+ propExprFor: (prop) => j.memberExpression(propsId, j.identifier(prop))
17035
+ }));
16235
17036
  openingAttrs.push(...emitter.buildStaticAttrsFromRecord(staticAttrs, { booleanTrueAsShorthand: false }));
16236
17037
  if (wrappedAcceptsSx) {
16237
17038
  const composedStyleArgs = [...styleArgs, j.memberExpression(propsId, j.identifier("sx"))];
@@ -17005,6 +17806,7 @@ function emitIntrinsicPolymorphicWrappers(ctx) {
17005
17806
  allowStyleProp,
17006
17807
  allowSxProp,
17007
17808
  inlineStyleProps: [],
17809
+ staticStyleExpr: attrsInfoWithoutForwardedAsStatic?.attrsStaticStyleExpr,
17008
17810
  staticClassNameExpr,
17009
17811
  isIntrinsicElement: false
17010
17812
  });
@@ -17014,6 +17816,10 @@ function emitIntrinsicPolymorphicWrappers(ctx) {
17014
17816
  propExprFor: (prop) => j.identifier(prop)
17015
17817
  }),
17016
17818
  j.jsxSpreadAttribute(restId),
17819
+ ...emitter.buildDynamicAttrsFromProps({
17820
+ dynamicAttrs: attrsInfoWithoutForwardedAsStatic?.dynamicAttrs ?? [],
17821
+ propExprFor: (prop) => j.identifier(prop)
17822
+ }),
17017
17823
  ...includesForwardedAs ? [j.jsxAttribute(j.jsxIdentifier("as"), j.jsxExpressionContainer(buildForwardedAsValueExpr(forwardedAsId, forwardedAsStaticFallback)))] : []
17018
17824
  ];
17019
17825
  emitter.appendMergingAttrs(attrs, merging);
@@ -17079,7 +17885,7 @@ function emitShouldForwardPropWrappers(ctx) {
17079
17885
  const dropPrefixFromFilter = d.shouldForwardProp?.dropPrefix;
17080
17886
  const usedAttrs = emitter.getUsedAttrs(d.localName);
17081
17887
  const shouldAllowAnyPrefixProps = !!dropPrefixFromFilter && (usedAttrs.has("*") || [...usedAttrs].some((n) => n.startsWith(dropPrefixFromFilter) && !extraProps.has(n)));
17082
- const knownPrefixProps = dropPrefixFromFilter ? [...extraProps].filter((p) => p.startsWith(dropPrefixFromFilter) && isValidIdentifierName(p)) : [];
17888
+ const knownPrefixProps = dropPrefixFromFilter ? [...extraProps].filter((p) => p.startsWith(dropPrefixFromFilter) && isValidIdentifierName$1(p)) : [];
17083
17889
  const knownPrefixPropsSet = new Set(knownPrefixProps);
17084
17890
  const isExportedComponent = d.isExported ?? false;
17085
17891
  const useSlimType = !isExportedComponent && !(d.supportsExternalStyles ?? false) && !d.usedAsValue;
@@ -17341,6 +18147,7 @@ function emitShouldForwardPropWrappers(ctx) {
17341
18147
  allowStyleProp,
17342
18148
  allowSxProp,
17343
18149
  inlineStyleProps: d.inlineStyleProps ?? [],
18150
+ staticStyleExpr: attrsInfoForJsx?.attrsStaticStyleExpr,
17344
18151
  staticClassNameExpr,
17345
18152
  isIntrinsicElement: !allowAsProp
17346
18153
  });
@@ -17351,6 +18158,10 @@ function emitShouldForwardPropWrappers(ctx) {
17351
18158
  }) : [],
17352
18159
  ...d.supportsRefProp ?? false ? [j.jsxAttribute(j.jsxIdentifier("ref"), j.jsxExpressionContainer(refId))] : [],
17353
18160
  ...includeRest ? [j.jsxSpreadAttribute(restId)] : [],
18161
+ ...emitter.buildDynamicAttrsFromProps({
18162
+ dynamicAttrs: attrsInfoForJsx?.dynamicAttrs ?? [],
18163
+ propExprFor: (prop) => j.identifier(prop)
18164
+ }),
17354
18165
  ...includesForwardedAs ? [j.jsxAttribute(j.jsxIdentifier("as"), j.jsxExpressionContainer(buildForwardedAsValueExpr(forwardedAsId, forwardedAsStaticFallback)))] : []
17355
18166
  ];
17356
18167
  emitter.appendMergingAttrs(openingAttrs, merging);
@@ -17383,10 +18194,11 @@ function filterAttrsForShouldForwardProp(attrsInfo, sfp) {
17383
18194
  const dropSet = new Set(sfp.dropProps);
17384
18195
  const dropPrefix = sfp.dropPrefix;
17385
18196
  const shouldDrop = (name) => dropSet.has(name) || dropPrefix != null && name.startsWith(dropPrefix);
17386
- if (!((attrsInfo.defaultAttrs ?? []).some((a) => shouldDrop(a.attrName)) || attrsInfo.conditionalAttrs.some((a) => shouldDrop(a.attrName)) || (attrsInfo.invertedBoolAttrs ?? []).some((a) => shouldDrop(a.attrName)) || Object.keys(attrsInfo.staticAttrs).some(shouldDrop))) return attrsInfo;
18197
+ if (!((attrsInfo.defaultAttrs ?? []).some((a) => shouldDrop(a.attrName)) || (attrsInfo.dynamicAttrs ?? []).some((a) => shouldDrop(a.attrName)) || attrsInfo.conditionalAttrs.some((a) => shouldDrop(a.attrName)) || (attrsInfo.invertedBoolAttrs ?? []).some((a) => shouldDrop(a.attrName)) || Object.keys(attrsInfo.staticAttrs).some(shouldDrop))) return attrsInfo;
17387
18198
  return {
17388
18199
  ...attrsInfo,
17389
18200
  defaultAttrs: (attrsInfo.defaultAttrs ?? []).filter((a) => !shouldDrop(a.attrName)),
18201
+ dynamicAttrs: (attrsInfo.dynamicAttrs ?? []).filter((a) => !shouldDrop(a.attrName)),
17390
18202
  conditionalAttrs: attrsInfo.conditionalAttrs.filter((a) => !shouldDrop(a.attrName)),
17391
18203
  invertedBoolAttrs: (attrsInfo.invertedBoolAttrs ?? []).filter((a) => !shouldDrop(a.attrName)),
17392
18204
  staticAttrs: Object.fromEntries(Object.entries(attrsInfo.staticAttrs).filter(([key]) => !shouldDrop(key)))
@@ -17405,7 +18217,7 @@ function buildExtraPropTypeLines(d, extraProps, skip) {
17405
18217
  const staticVariantPropTypes = buildStaticVariantPropTypes(d);
17406
18218
  const lines = [];
17407
18219
  for (const p of extraProps) {
17408
- if (!isValidIdentifierName(p) || skip?.(p)) continue;
18220
+ if (!isValidIdentifierName$1(p) || skip?.(p)) continue;
17409
18221
  const variantType = variantDimByProp.get(p);
17410
18222
  if (variantType) {
17411
18223
  lines.push(` ${p}?: ${variantType};`);
@@ -17559,9 +18371,11 @@ function emitSimpleWithConfigWrappers(ctx) {
17559
18371
  includeRefProp: (d.supportsRefProp ?? false) || !includeRest && willForwardRef,
17560
18372
  includeRest,
17561
18373
  defaultAttrs: d.attrsInfo?.defaultAttrs ?? [],
18374
+ dynamicAttrs: d.attrsInfo?.dynamicAttrs ?? [],
17562
18375
  conditionalAttrs: d.attrsInfo?.conditionalAttrs ?? [],
17563
18376
  invertedBoolAttrs: d.attrsInfo?.invertedBoolAttrs ?? [],
17564
18377
  staticAttrs: d.attrsInfo?.staticAttrs ?? {},
18378
+ attrsStaticStyleExpr: d.attrsInfo?.attrsStaticStyleExpr,
17565
18379
  inlineStyleProps: d.inlineStyleProps ?? [],
17566
18380
  attrsAsTag: d.attrsInfo?.attrsAsTag,
17567
18381
  bridgeClassVar: getBridgeClassVar(d)
@@ -17595,6 +18409,7 @@ function emitSimpleWithConfigWrappers(ctx) {
17595
18409
  allowStyleProp,
17596
18410
  allowSxProp,
17597
18411
  inlineStyleProps: [],
18412
+ staticStyleExpr: attrsInfo?.attrsStaticStyleExpr,
17598
18413
  staticClassNameExpr,
17599
18414
  isIntrinsicElement: !allowAsProp
17600
18415
  });
@@ -17604,7 +18419,11 @@ function emitSimpleWithConfigWrappers(ctx) {
17604
18419
  propExprFor: (prop) => j.identifier(prop)
17605
18420
  }),
17606
18421
  ...d.supportsRefProp ?? false ? [j.jsxAttribute(j.jsxIdentifier("ref"), j.jsxExpressionContainer(refId))] : [],
17607
- j.jsxSpreadAttribute(restId)
18422
+ j.jsxSpreadAttribute(restId),
18423
+ ...emitter.buildDynamicAttrsFromProps({
18424
+ dynamicAttrs: attrsInfo?.dynamicAttrs ?? [],
18425
+ propExprFor: (prop) => j.identifier(prop)
18426
+ })
17608
18427
  ];
17609
18428
  emitter.appendMergingAttrs(openingAttrs, merging);
17610
18429
  const openingEl = j.jsxOpeningElement(j.jsxIdentifier(allowAsProp ? "Component" : tagName), openingAttrs, false);
@@ -17722,7 +18541,7 @@ function emitSimpleExportedIntrinsicWrappers(ctx) {
17722
18541
  const compoundVariantWhenKeys = collectCompoundVariantKeys(d.compoundVariants, { syntheticOnly: true });
17723
18542
  for (const k of compoundVariantWhenKeys) keys.delete(k);
17724
18543
  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)));
18544
+ const filtered = [...keys].filter((k) => k && isValidIdentifierName$1(k) && k !== "children" && k !== "className" && k !== "style" && k !== "as" && k !== "forwardedAs" && (!explicitPropNames.has(k) || variantDimByProp.has(k)));
17726
18545
  if (filtered.length === 0) return "{}";
17727
18546
  const staticVariantPropTypes = buildStaticVariantPropTypes(d);
17728
18547
  return `{\n${filtered.map((k) => {
@@ -17904,6 +18723,7 @@ function emitSimpleExportedIntrinsicWrappers(ctx) {
17904
18723
  const forwardedAsId = j.identifier("forwardedAs");
17905
18724
  if (allowSxProp) styleArgs.push(sxId);
17906
18725
  for (const attr of d.attrsInfo?.defaultAttrs ?? []) if (!destructureProps.includes(attr.jsxProp)) destructureProps.push(attr.jsxProp);
18726
+ for (const attr of d.attrsInfo?.dynamicAttrs ?? []) if (!destructureProps.includes(attr.jsxProp)) destructureProps.push(attr.jsxProp);
17907
18727
  const patternProps = emitter.buildDestructurePatternProps({
17908
18728
  baseProps: [
17909
18729
  ...useAsProp ? [j.property.from({
@@ -17941,6 +18761,7 @@ function emitSimpleExportedIntrinsicWrappers(ctx) {
17941
18761
  allowStyleProp,
17942
18762
  allowSxProp,
17943
18763
  inlineStyleProps: d.inlineStyleProps ?? [],
18764
+ staticStyleExpr: attrsInfoWithoutForwardedAsStatic?.attrsStaticStyleExpr,
17944
18765
  staticClassNameExpr,
17945
18766
  isIntrinsicElement: !useAsProp
17946
18767
  });
@@ -17951,6 +18772,10 @@ function emitSimpleExportedIntrinsicWrappers(ctx) {
17951
18772
  }),
17952
18773
  ...(d.supportsRefProp ?? false) || !restId && willForwardRef ? [j.jsxAttribute(j.jsxIdentifier("ref"), j.jsxExpressionContainer(refId))] : [],
17953
18774
  ...restId ? [j.jsxSpreadAttribute(restId)] : [],
18775
+ ...emitter.buildDynamicAttrsFromProps({
18776
+ dynamicAttrs: attrsInfoWithoutForwardedAsStatic?.dynamicAttrs ?? [],
18777
+ propExprFor: (prop) => j.identifier(prop)
18778
+ }),
17954
18779
  ...includesForwardedAs ? [j.jsxAttribute(j.jsxIdentifier("as"), j.jsxExpressionContainer(buildForwardedAsValueExpr(forwardedAsId, forwardedAsStaticFallback)))] : []
17955
18780
  ];
17956
18781
  emitter.appendMergingAttrs(openingAttrs, merging);
@@ -17988,9 +18813,11 @@ function emitSimpleExportedIntrinsicWrappers(ctx) {
17988
18813
  includeRefProp: (d.supportsRefProp ?? false) || !shouldIncludeRest && willForwardRef,
17989
18814
  includeRest: shouldIncludeRest,
17990
18815
  defaultAttrs: d.attrsInfo?.defaultAttrs ?? [],
18816
+ dynamicAttrs: d.attrsInfo?.dynamicAttrs ?? [],
17991
18817
  conditionalAttrs: d.attrsInfo?.conditionalAttrs ?? [],
17992
18818
  invertedBoolAttrs: d.attrsInfo?.invertedBoolAttrs ?? [],
17993
18819
  staticAttrs: d.attrsInfo?.staticAttrs ?? {},
18820
+ attrsStaticStyleExpr: d.attrsInfo?.attrsStaticStyleExpr,
17994
18821
  inlineStyleProps: d.inlineStyleProps ?? [],
17995
18822
  attrsAsTag: d.attrsInfo?.attrsAsTag,
17996
18823
  bridgeClassVar: getBridgeClassVar(d)
@@ -20383,7 +21210,7 @@ function replaceThemeRefsWithHookVar(expr, paramName, info) {
20383
21210
  * Order matters: more-specific transforms first, then fall back to prop-access emission.
20384
21211
  */
20385
21212
  function resolveDynamicNode(node, ctx) {
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);
21213
+ 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) ?? tryResolveArrowFnImportedHelperCall(node, ctx) ?? tryResolveThemeDependentTemplateLiteral(node, ctx) ?? tryResolveStyleFunctionFromTemplateLiteral(node) ?? tryResolveInlineStyleValueForNestedPropAccess(node) ?? tryResolvePropAccess(node) ?? tryResolveConditionalPropStyleFunction(node) ?? tryResolveArrowFnPropExpression(node) ?? tryResolveInlineStyleValueForConditionalExpression(node) ?? tryResolveInlineStyleValueForLogicalExpression(node) ?? tryResolveInlineStyleValueFromArrowFn(node);
20387
21214
  }
20388
21215
  function tryResolveThemeAccess(node, ctx) {
20389
21216
  const expr = node.expr;
@@ -20750,6 +21577,24 @@ function tryResolveArrowFnImportedCurriedHelperCallWithPropsArg(node, ctx) {
20750
21577
  if (curried?.result.kind === "unresolved") return buildUnresolvedHelperResult(curried.innerCall.callee, ctx);
20751
21578
  return null;
20752
21579
  }
21580
+ function tryResolveArrowFnImportedHelperCall(node, ctx) {
21581
+ if (!node.css.property) return null;
21582
+ const expr = node.expr;
21583
+ if (!isArrowFunctionExpression(expr)) return null;
21584
+ const body = getFunctionBodyExpr(expr);
21585
+ if (!isCallExpressionNode(body)) return null;
21586
+ const callee = body.callee;
21587
+ const calleeInfo = extractRootAndPath(callee);
21588
+ if (!(calleeInfo ? ctx.resolveImport(calleeInfo.rootName, calleeInfo.rootNode) : null)) return null;
21589
+ if ((body.arguments ?? []).some((arg) => literalToStaticValue(arg) === null)) return { type: "emitInlineStyleValueFromProps" };
21590
+ const resolved = resolveImportedHelperCall(body, ctx, getArrowFnSingleParamName(expr) ?? void 0, node.css.property);
21591
+ if (resolved.kind === "resolved") return buildResolvedHandlerResult(resolved.result, node.css.property, {
21592
+ resolveCallContext: resolved.resolveCallContext,
21593
+ resolveCallResult: resolved.resolveCallResult
21594
+ });
21595
+ if (resolved.kind === "unresolved") return { type: "emitInlineStyleValueFromProps" };
21596
+ return null;
21597
+ }
20753
21598
  /**
20754
21599
  * Attempts to resolve a callee identifier through the adapter's resolveCall hook.
20755
21600
  * Uses `resolveCallOptional` (non-bailing) so that an unhandled helper does NOT
@@ -21418,10 +22263,6 @@ function mapAttributeToPseudo(attr, tagName) {
21418
22263
  * Parses selectors like "& svg", "& > button", "&:hover svg", "& svg:hover",
21419
22264
  * "&:focus > button:disabled", "& > button[disabled]".
21420
22265
  *
21421
- * Both descendant (space) and child (>) combinators are mapped the same way
21422
- * because `stylex.when.ancestor()` matches ANY ancestor, not just a direct parent.
21423
- * The child combinator is therefore less strict in the output than the original CSS.
21424
- *
21425
22266
  * Attribute selectors on child elements (e.g., `button[disabled]`) are mapped to
21426
22267
  * their pseudo-class equivalents (`:disabled`) for StyleX compatibility.
21427
22268
  *
@@ -21432,6 +22273,7 @@ function parseElementSelectorPattern(selector) {
21432
22273
  const m = trimmed.match(/^&((?::[\w-]+(?:\([^)]*\))?)*)\s*(>?\s*)([a-zA-Z][a-zA-Z0-9]*)((?:\[[^\]]+\])?)((?::[\w-]+(?:\([^)]*\))?)*)$/);
21433
22274
  if (m) {
21434
22275
  const ancestorPseudoRaw = m[1] ?? "";
22276
+ const combinatorRaw = m[2] ?? "";
21435
22277
  const tagName = m[3];
21436
22278
  const attrRaw = m[4] ?? "";
21437
22279
  const childPseudo = resolveChildPseudoWithAttr(m[5] ?? "", attrRaw, tagName);
@@ -21440,7 +22282,7 @@ function parseElementSelectorPattern(selector) {
21440
22282
  tagName,
21441
22283
  ancestorPseudo: ancestorPseudoRaw || null,
21442
22284
  childPseudo,
21443
- usesChildCombinator: (m[2] ?? "").includes(">")
22285
+ directOnly: combinatorRaw.includes(">")
21444
22286
  };
21445
22287
  }
21446
22288
  const bareM = trimmed.match(/^([a-zA-Z][a-zA-Z0-9]*)((?:\[[^\]]+\])?)((?::[\w-]+(?:\([^)]*\))?)*)$/);
@@ -21453,7 +22295,7 @@ function parseElementSelectorPattern(selector) {
21453
22295
  tagName: bareTagName,
21454
22296
  ancestorPseudo: null,
21455
22297
  childPseudo,
21456
- usesChildCombinator: false
22298
+ directOnly: false
21457
22299
  };
21458
22300
  }
21459
22301
  const childCombM = trimmed.match(/^>\s*([a-zA-Z][a-zA-Z0-9]*)((?:\[[^\]]+\])?)((?::[\w-]+(?:\([^)]*\))?)*)$/);
@@ -21466,7 +22308,7 @@ function parseElementSelectorPattern(selector) {
21466
22308
  tagName: combTagName,
21467
22309
  ancestorPseudo: null,
21468
22310
  childPseudo,
21469
- usesChildCombinator: true
22311
+ directOnly: true
21470
22312
  };
21471
22313
  }
21472
22314
  return null;
@@ -21874,7 +22716,8 @@ function buildInterpolatedTemplate(args) {
21874
22716
  let allStatic = true;
21875
22717
  const quasis = [];
21876
22718
  let q = "";
21877
- for (const part of parts) {
22719
+ for (let partIndex = 0; partIndex < parts.length; partIndex++) {
22720
+ const part = parts[partIndex];
21878
22721
  if (part.kind === "static") {
21879
22722
  q += part.value;
21880
22723
  fullStaticValue += part.value;
@@ -21886,6 +22729,7 @@ function buildInterpolatedTemplate(args) {
21886
22729
  if (expr.type === "CallExpression" && resolveCallExpr) {
21887
22730
  const resolved = resolveCallExpr(expr);
21888
22731
  if (resolved) {
22732
+ if (hasAdjacentUnitInParts(parts, partIndex)) return null;
21889
22733
  if (resolved.resolved?.type === "StringLiteral" || resolved.resolved?.type === "Literal" && typeof resolved.resolved.value === "string") {
21890
22734
  const strValue = resolved.resolved.value;
21891
22735
  q += strValue;
@@ -21908,6 +22752,11 @@ function buildInterpolatedTemplate(args) {
21908
22752
  if (importedResolved) {
21909
22753
  if ("bail" in importedResolved) return null;
21910
22754
  const resolved = importedResolved;
22755
+ if (resolved.skipStaticWrap && hasSingleSlotUnitSuffix(cssValue)) {
22756
+ for (const imp of resolved.imports ?? []) addImport?.(imp);
22757
+ return resolved.resolved;
22758
+ }
22759
+ if (hasAdjacentUnitInParts(parts, partIndex)) return null;
21911
22760
  if (resolved.resolved?.type === "StringLiteral" || resolved.resolved?.type === "Literal" && typeof resolved.resolved.value === "string") {
21912
22761
  const strValue = resolved.resolved.value;
21913
22762
  q += strValue;
@@ -21949,6 +22798,28 @@ function buildInterpolatedTemplate(args) {
21949
22798
  }, true));
21950
22799
  return j.templateLiteral(quasis, exprs);
21951
22800
  }
22801
+ function hasAdjacentUnitInParts(parts, slotIndex) {
22802
+ const before = parts[slotIndex - 1]?.kind === "static" ? parts[slotIndex - 1]?.value ?? "" : "";
22803
+ const after = parts[slotIndex + 1]?.kind === "static" ? parts[slotIndex + 1]?.value ?? "" : "";
22804
+ return /[a-zA-Z%]$/.test(before) || /^[a-zA-Z%]/.test(after);
22805
+ }
22806
+ function hasSingleSlotUnitSuffix(cssValue) {
22807
+ const parts = cssValue?.parts ?? [];
22808
+ const slotCount = parts.filter((part) => part?.kind === "slot").length;
22809
+ let prefix = "";
22810
+ let suffix = "";
22811
+ let foundSlot = false;
22812
+ for (const part of parts) {
22813
+ if (part?.kind === "slot") {
22814
+ foundSlot = true;
22815
+ continue;
22816
+ }
22817
+ if (part?.kind !== "static") continue;
22818
+ if (foundSlot) suffix += part.value ?? "";
22819
+ else prefix += part.value ?? "";
22820
+ }
22821
+ return slotCount === 1 && prefix === "" && suffix !== "" && /^-?(?:[a-zA-Z%]+)$/.test(suffix);
22822
+ }
21952
22823
  //#endregion
21953
22824
  //#region src/internal/lower-rules/css-helper.ts
21954
22825
  /**
@@ -22904,7 +23775,7 @@ function resolveStaticTemplateExpressionAst(args) {
22904
23775
  return null;
22905
23776
  }
22906
23777
  function buildPropAccessExpr(j, propName, defaultValue) {
22907
- const baseExpr = isValidIdentifierName(propName) ? j.identifier(propName) : j.memberExpression(j.identifier("props"), j.literal(propName), true);
23778
+ const baseExpr = isValidIdentifierName$1(propName) ? j.identifier(propName) : j.memberExpression(j.identifier("props"), j.literal(propName), true);
22908
23779
  if (defaultValue !== void 0) return j.logicalExpression("??", baseExpr, cloneAstNode(defaultValue));
22909
23780
  return baseExpr;
22910
23781
  }
@@ -24454,7 +25325,7 @@ function buildFallbackPropSuffix(consMap, altMap) {
24454
25325
  //#endregion
24455
25326
  //#region src/internal/lower-rules/import-resolution.ts
24456
25327
  const buildSafeIndexedParamName = (preferred, containerExpr) => {
24457
- if (!isValidIdentifierName(preferred)) return "propValue";
25328
+ if (!isValidIdentifierName$1(preferred)) return "propValue";
24458
25329
  if (containerExpr?.type === "Identifier" && containerExpr.name === preferred) return `${preferred}Value`;
24459
25330
  return preferred;
24460
25331
  };
@@ -24782,7 +25653,7 @@ const createValuePatternHandlers = (ctx) => {
24782
25653
  const consTheme = resolveThemeAst(body.consequent);
24783
25654
  const altTheme = resolveThemeAst(body.alternate);
24784
25655
  const buildPropAccess = (prop) => {
24785
- return isValidIdentifierName(prop) ? j.memberExpression(j.identifier("props"), j.identifier(prop)) : j.memberExpression(j.identifier("props"), j.literal(prop), true);
25656
+ return isValidIdentifierName$1(prop) ? j.memberExpression(j.identifier("props"), j.identifier(prop)) : j.memberExpression(j.identifier("props"), j.literal(prop), true);
24786
25657
  };
24787
25658
  let nullishPropName = null;
24788
25659
  let baseTheme = null;
@@ -24818,7 +25689,7 @@ const createValuePatternHandlers = (ctx) => {
24818
25689
  styleFnDecls.set(fnKey, j.arrowFunctionExpression([param], bodyExpr));
24819
25690
  }
24820
25691
  if (!styleFnFromProps.some((p) => p.fnKey === fnKey)) {
24821
- const baseArg = isValidIdentifierName(nullishPropName) ? j.identifier(nullishPropName) : buildPropAccess(nullishPropName);
25692
+ const baseArg = isValidIdentifierName$1(nullishPropName) ? j.identifier(nullishPropName) : buildPropAccess(nullishPropName);
24822
25693
  const callArg = j.logicalExpression("??", baseArg, fallbackTheme);
24823
25694
  styleFnFromProps.push({
24824
25695
  fnKey,
@@ -26216,7 +27087,7 @@ function warnOpaqueShorthands(styleObj, decl, warnings) {
26216
27087
  * returns its `.default` property to avoid nesting maps which produces invalid StyleX values.
26217
27088
  * Otherwise returns the value as-is (string, number, or null).
26218
27089
  */
26219
- function extractScalarDefault$1(value) {
27090
+ function extractScalarDefault(value) {
26220
27091
  if (value && typeof value === "object" && !Array.isArray(value) && !isAstNode(value)) {
26221
27092
  const map = value;
26222
27093
  return "default" in map ? map.default : null;
@@ -26349,7 +27220,7 @@ function tryResolveConditionalHelperCallInPseudo(ctx, expr, pseudo) {
26349
27220
  const helperRaw = cssHelperPropValues.has(prop) ? resolveComposedDefaultValue(cssHelperPropValues.get(prop), prop) : void 0;
26350
27221
  const sourceMap = raw !== void 0 ? raw : helperRaw;
26351
27222
  const propMap = {
26352
- default: extractScalarDefault$1(sourceMap ?? null),
27223
+ default: extractScalarDefault(sourceMap ?? null),
26353
27224
  [pseudo]: value
26354
27225
  };
26355
27226
  mergeExistingPseudoEntries(propMap, sourceMap);
@@ -27881,7 +28752,7 @@ function handleInterpolatedDeclaration(args) {
27881
28752
  return values;
27882
28753
  };
27883
28754
  const observedNumericCssTextProps = /* @__PURE__ */ new Set();
27884
- const tryHandleMultiSlotRuntimeValue = () => {
28755
+ const tryHandleMultiSlotRuntimeValue = (resolveImportedValueExprArg) => {
27885
28756
  if (!d.property || d.value.kind !== "interpolated") return false;
27886
28757
  const cssProperty = d.property.trim();
27887
28758
  if (cssProperty !== "background" && cssProperty !== "background-image") return false;
@@ -27897,7 +28768,8 @@ function handleInterpolatedDeclaration(args) {
27897
28768
  const quasis = [];
27898
28769
  let currentStaticPart = "";
27899
28770
  let needsTheme = false;
27900
- for (const part of parts) {
28771
+ for (let partIndex = 0; partIndex < parts.length; partIndex++) {
28772
+ const part = parts[partIndex];
27901
28773
  if (part.kind === "static") {
27902
28774
  currentStaticPart += part.value ?? "";
27903
28775
  continue;
@@ -27907,6 +28779,21 @@ function handleInterpolatedDeclaration(args) {
27907
28779
  if (!rawExpr || rawExpr.type === "FunctionExpression") return false;
27908
28780
  let slotExpr = rawExpr.type === "ArrowFunctionExpression" ? inlineArrowFunctionBody(j, rawExpr) : cloneAstNode(rawExpr);
27909
28781
  if (!slotExpr) return false;
28782
+ const importedValueResolution = resolveImportedValueExprArg(slotExpr);
28783
+ if (importedValueResolution && "bail" in importedValueResolution) return true;
28784
+ if (importedValueResolution) {
28785
+ if (hasAdjacentUnitInInterpolatedParts(parts, partIndex)) {
28786
+ warnings.push({
28787
+ severity: "warning",
28788
+ type: "Unsupported interpolation: call expression",
28789
+ loc: getNodeLocStart(slotExpr) ?? decl.loc
28790
+ });
28791
+ bail = true;
28792
+ return true;
28793
+ }
28794
+ addResolverImports(importedValueResolution.imports);
28795
+ slotExpr = importedValueResolution.resolved;
28796
+ }
27910
28797
  if (rawExpr.type === "ArrowFunctionExpression") {
27911
28798
  for (const propName of collectPropsFromArrowFn(rawExpr)) if (propName !== "theme") propsUsed.add(propName);
27912
28799
  if (hasThemeAccessInArrowFn(rawExpr)) {
@@ -28183,21 +29070,87 @@ function handleInterpolatedDeclaration(args) {
28183
29070
  return true;
28184
29071
  };
28185
29072
  if (tryHandleThemeValueInPseudo()) continue;
29073
+ const resolveCallExpr = (expr) => {
29074
+ if (expr?.type !== "CallExpression") return null;
29075
+ const res = resolveDynamicNode({
29076
+ slotId: 0,
29077
+ expr,
29078
+ css: {
29079
+ kind: "declaration",
29080
+ selector: rule.selector,
29081
+ atRuleStack: rule.atRuleStack,
29082
+ ...d.property ? { property: d.property } : {},
29083
+ valueRaw: d.valueRaw
29084
+ },
29085
+ component: componentInfo,
29086
+ usage: {
29087
+ jsxUsages: 0,
29088
+ hasPropsSpread: false
29089
+ }
29090
+ }, {
29091
+ ...handlerContext,
29092
+ resolveImport: (localName, identNode) => resolveImportInScope(localName, identNode)
29093
+ });
29094
+ if (res && res.type === "resolvedValue") {
29095
+ const exprAst = parseExpr(res.expr);
29096
+ if (exprAst) return {
29097
+ resolved: exprAst,
29098
+ imports: res.imports
29099
+ };
29100
+ }
29101
+ return null;
29102
+ };
28186
29103
  const allowCssCalcForImportedArithmetic = isEntireInterpolatedValueSingleSlot(d, decl);
28187
29104
  const resolveImportedValueExpr = (expr, allowCssCalc = allowCssCalcForImportedArithmetic) => {
29105
+ const resolveChildExpression = (child) => resolveImportedValueExpr(child, false);
29106
+ const isBailResolution = (result) => Boolean(result && "bail" in result);
29107
+ const resolvedOrOriginal = (result, original) => result && !isBailResolution(result) ? result.resolved : original;
29108
+ const skipStaticWrap = (...results) => results.some((result) => result && !isBailResolution(result) && result.skipStaticWrap);
29109
+ const mergeImports = (...results) => results.flatMap((result) => result && !isBailResolution(result) ? result.imports ?? [] : []);
29110
+ const bailResolvedUnitExpression = (exprArg) => {
29111
+ warnings.push({
29112
+ severity: "warning",
29113
+ type: "Unsupported interpolation: call expression",
29114
+ loc: getNodeLocStart(exprArg) ?? decl.loc
29115
+ });
29116
+ bail = true;
29117
+ return { bail: true };
29118
+ };
29119
+ const singleSlotStaticParts = getSingleSlotStaticParts(d, decl);
29120
+ const canFoldUnitSuffix = !!singleSlotStaticParts && singleSlotStaticParts.prefix === "" && singleSlotStaticParts.suffix !== "" && /^-?(?:[a-zA-Z%]+)$/.test(singleSlotStaticParts.suffix);
29121
+ const resolveUnitBranch = (result, original) => {
29122
+ if (result && !isBailResolution(result)) return result.resolved;
29123
+ const staticValue = literalToStaticValue(original);
29124
+ if (typeof staticValue === "number" && singleSlotStaticParts) return j.literal(`${staticValue}${singleSlotStaticParts.suffix}`);
29125
+ return null;
29126
+ };
28188
29127
  if (expr?.type === "BinaryExpression") {
28189
- const leftResult = resolveImportedValueExpr(expr.left, false);
28190
- const rightResult = resolveImportedValueExpr(expr.right, false);
29128
+ const leftResult = resolveChildExpression(expr.left);
29129
+ const rightResult = resolveChildExpression(expr.right);
28191
29130
  if (!leftResult && !rightResult) return null;
28192
- if (leftResult && "bail" in leftResult) return leftResult;
28193
- if (rightResult && "bail" in rightResult) return rightResult;
28194
- const resolvedLeft = leftResult ? leftResult.resolved : expr.left;
28195
- const resolvedRight = rightResult ? rightResult.resolved : expr.right;
28196
- const imports = [...leftResult?.imports ?? [], ...rightResult?.imports ?? []];
29131
+ if (isBailResolution(leftResult)) return leftResult;
29132
+ if (isBailResolution(rightResult)) return rightResult;
29133
+ const resolvedLeft = resolvedOrOriginal(leftResult, expr.left);
29134
+ const resolvedRight = resolvedOrOriginal(rightResult, expr.right);
29135
+ const imports = mergeImports(leftResult, rightResult);
28197
29136
  if (allowCssCalc && isCssCalcOperator(expr.operator)) {
29137
+ const staticParts = singleSlotStaticParts ?? {
29138
+ prefix: "",
29139
+ suffix: ""
29140
+ };
29141
+ if (staticParts.prefix) {
29142
+ warnings.push({
29143
+ severity: "warning",
29144
+ type: "Unsupported interpolation: call expression",
29145
+ loc: getNodeLocStart(expr) ?? decl.loc
29146
+ });
29147
+ bail = true;
29148
+ return { bail: true };
29149
+ }
28198
29150
  const calcExpr = buildCssCalcTemplateExpression({
28199
29151
  j,
28200
29152
  operator: expr.operator,
29153
+ unit: expr.operator === "+" || expr.operator === "-" ? staticParts.suffix : "",
28201
29154
  left: {
28202
29155
  node: resolvedLeft,
28203
29156
  allowExpression: Boolean(leftResult)
@@ -28209,14 +29162,131 @@ function handleInterpolatedDeclaration(args) {
28209
29162
  });
28210
29163
  if (calcExpr) return {
28211
29164
  resolved: calcExpr,
28212
- imports
29165
+ imports,
29166
+ skipStaticWrap: staticParts.suffix !== ""
28213
29167
  };
29168
+ if (staticParts.suffix && imports.length > 0) return bailResolvedUnitExpression(expr);
28214
29169
  }
28215
29170
  return {
28216
29171
  resolved: j.binaryExpression(expr.operator, resolvedLeft, resolvedRight),
28217
29172
  imports
28218
29173
  };
28219
29174
  }
29175
+ if (expr?.type === "UnaryExpression") {
29176
+ const argumentResult = resolveChildExpression(expr.argument);
29177
+ if (!argumentResult) return null;
29178
+ if (isBailResolution(argumentResult)) return argumentResult;
29179
+ if (canFoldUnitSuffix) {
29180
+ if (expr.operator !== "-") return bailResolvedUnitExpression(expr);
29181
+ return {
29182
+ resolved: j.templateLiteral([j.templateElement({
29183
+ raw: "calc(-1 * ",
29184
+ cooked: "calc(-1 * "
29185
+ }, false), j.templateElement({
29186
+ raw: ")",
29187
+ cooked: ")"
29188
+ }, true)], [argumentResult.resolved]),
29189
+ imports: argumentResult.imports,
29190
+ skipStaticWrap: true
29191
+ };
29192
+ }
29193
+ return {
29194
+ resolved: j.unaryExpression(expr.operator, argumentResult.resolved, expr.prefix),
29195
+ imports: argumentResult.imports,
29196
+ skipStaticWrap: argumentResult.skipStaticWrap
29197
+ };
29198
+ }
29199
+ if (expr?.type === "ConditionalExpression") {
29200
+ const testResult = resolveChildExpression(expr.test);
29201
+ const consequentResult = resolveImportedValueExpr(expr.consequent, canFoldUnitSuffix);
29202
+ const alternateResult = resolveImportedValueExpr(expr.alternate, canFoldUnitSuffix);
29203
+ if (!testResult && !consequentResult && !alternateResult) return null;
29204
+ if (isBailResolution(testResult)) return testResult;
29205
+ if (isBailResolution(consequentResult)) return consequentResult;
29206
+ if (isBailResolution(alternateResult)) return alternateResult;
29207
+ if (testResult) return bailResolvedUnitExpression(expr.test);
29208
+ if (canFoldUnitSuffix) {
29209
+ const consequent = resolveUnitBranch(consequentResult, expr.consequent);
29210
+ const alternate = resolveUnitBranch(alternateResult, expr.alternate);
29211
+ if (!consequent || !alternate) return bailResolvedUnitExpression(expr);
29212
+ return {
29213
+ resolved: j.conditionalExpression(resolvedOrOriginal(testResult, expr.test), consequent, alternate),
29214
+ imports: mergeImports(testResult, consequentResult, alternateResult),
29215
+ skipStaticWrap: true
29216
+ };
29217
+ }
29218
+ return {
29219
+ resolved: j.conditionalExpression(resolvedOrOriginal(testResult, expr.test), resolvedOrOriginal(consequentResult, expr.consequent), resolvedOrOriginal(alternateResult, expr.alternate)),
29220
+ imports: mergeImports(testResult, consequentResult, alternateResult),
29221
+ skipStaticWrap: canFoldUnitSuffix || skipStaticWrap(testResult, consequentResult, alternateResult)
29222
+ };
29223
+ }
29224
+ if (expr?.type === "LogicalExpression") {
29225
+ const leftResult = resolveChildExpression(expr.left);
29226
+ const rightResult = resolveImportedValueExpr(expr.right, canFoldUnitSuffix);
29227
+ if (!leftResult && !rightResult) return null;
29228
+ if (isBailResolution(leftResult)) return leftResult;
29229
+ if (isBailResolution(rightResult)) return rightResult;
29230
+ if (canFoldUnitSuffix) {
29231
+ const left = resolveUnitBranch(leftResult, expr.left);
29232
+ const right = resolveUnitBranch(rightResult, expr.right);
29233
+ if (!left || !right) return bailResolvedUnitExpression(expr);
29234
+ return {
29235
+ resolved: j.logicalExpression(expr.operator, left, right),
29236
+ imports: mergeImports(leftResult, rightResult),
29237
+ skipStaticWrap: true
29238
+ };
29239
+ }
29240
+ return {
29241
+ resolved: j.logicalExpression(expr.operator, resolvedOrOriginal(leftResult, expr.left), resolvedOrOriginal(rightResult, expr.right)),
29242
+ imports: mergeImports(leftResult, rightResult),
29243
+ skipStaticWrap: canFoldUnitSuffix || skipStaticWrap(leftResult, rightResult)
29244
+ };
29245
+ }
29246
+ if (expr?.type === "TemplateLiteral") {
29247
+ let didResolve = false;
29248
+ const imports = [];
29249
+ const expressions = [];
29250
+ const expressionResults = [];
29251
+ const templateExpressions = expr.expressions ?? [];
29252
+ for (let index = 0; index < templateExpressions.length; index++) {
29253
+ const templateExpr = templateExpressions[index];
29254
+ const expressionResult = resolveChildExpression(templateExpr);
29255
+ expressionResults.push(expressionResult);
29256
+ if (isBailResolution(expressionResult)) return expressionResult;
29257
+ if (expressionResult) {
29258
+ if (hasAdjacentTemplateUnit(expr.quasis ?? [], index)) return bailResolvedUnitExpression(templateExpr);
29259
+ didResolve = true;
29260
+ imports.push(...expressionResult.imports ?? []);
29261
+ expressions.push(expressionResult.resolved);
29262
+ } else expressions.push(templateExpr);
29263
+ }
29264
+ if (!didResolve) return null;
29265
+ return {
29266
+ resolved: j.templateLiteral(expr.quasis, expressions),
29267
+ imports,
29268
+ skipStaticWrap: skipStaticWrap(...expressionResults)
29269
+ };
29270
+ }
29271
+ if (expr?.type === "CallExpression") {
29272
+ const calleeInfo = extractRootAndPath(expr.callee);
29273
+ const imp = calleeInfo ? resolveImportInScope(calleeInfo.rootName, calleeInfo.rootNode) : null;
29274
+ if (!imp) return null;
29275
+ const resolvedCall = resolveCallExpr(expr);
29276
+ if (resolvedCall) return resolvedCall;
29277
+ warnings.push({
29278
+ severity: "warning",
29279
+ type: "Adapter resolveCall returned undefined for helper call",
29280
+ loc: getNodeLocStart(expr) ?? decl.loc,
29281
+ context: {
29282
+ localName: decl.localName,
29283
+ importedName: imp.importedName,
29284
+ source: imp.source.value
29285
+ }
29286
+ });
29287
+ bail = true;
29288
+ return { bail: true };
29289
+ }
28220
29290
  const info = getRootIdentifierInfo(expr);
28221
29291
  if (!info) return null;
28222
29292
  const imp = resolveImportInScope(info.rootName, info.rootNode);
@@ -28264,36 +29334,6 @@ function handleInterpolatedDeclaration(args) {
28264
29334
  imports: resolveValueResult.imports
28265
29335
  };
28266
29336
  };
28267
- const resolveCallExpr = (expr) => {
28268
- if (expr?.type !== "CallExpression") return null;
28269
- const res = resolveDynamicNode({
28270
- slotId: 0,
28271
- expr,
28272
- css: {
28273
- kind: "declaration",
28274
- selector: rule.selector,
28275
- atRuleStack: rule.atRuleStack,
28276
- ...d.property ? { property: d.property } : {},
28277
- valueRaw: d.valueRaw
28278
- },
28279
- component: componentInfo,
28280
- usage: {
28281
- jsxUsages: 0,
28282
- hasPropsSpread: false
28283
- }
28284
- }, {
28285
- ...handlerContext,
28286
- resolveImport: (localName) => resolveImportForExpr(expr, localName)
28287
- });
28288
- if (res && res.type === "resolvedValue") {
28289
- const exprAst = parseExpr(res.expr);
28290
- if (exprAst) return {
28291
- resolved: exprAst,
28292
- imports: res.imports
28293
- };
28294
- }
28295
- return null;
28296
- };
28297
29337
  const addImport = (imp) => {
28298
29338
  addResolverImports([imp]);
28299
29339
  };
@@ -28496,7 +29536,7 @@ function handleInterpolatedDeclaration(args) {
28496
29536
  pseudoElement
28497
29537
  })) continue;
28498
29538
  if (d.property && d.value.kind === "interpolated" && tryHandleMultiSlotTernary(ctx, d)) continue;
28499
- if (tryHandleMultiSlotRuntimeValue()) continue;
29539
+ if (tryHandleMultiSlotRuntimeValue(resolveImportedValueExpr)) continue;
28500
29540
  const slotPart = d.value.parts.find((p) => p.kind === "slot");
28501
29541
  const slotId = slotPart && slotPart.kind === "slot" ? slotPart.slotId : 0;
28502
29542
  const expr = decl.templateExpressions[slotId];
@@ -29085,6 +30125,7 @@ function handleInterpolatedDeclaration(args) {
29085
30125
  cssProperty: out.prop,
29086
30126
  paramName,
29087
30127
  resolveImportForExpr,
30128
+ resolveImportInScope,
29088
30129
  resolveCall,
29089
30130
  parseExpr,
29090
30131
  filePath,
@@ -29773,7 +30814,7 @@ function buildCssCalcTemplateExpression(args) {
29773
30814
  const quasis = [];
29774
30815
  let currentQuasi = "calc(";
29775
30816
  const appendOperand = (operand) => {
29776
- const staticText = expressionToCalcStaticText(operand.node);
30817
+ const staticText = expressionToCalcStaticText(operand.node, args.unit);
29777
30818
  if (staticText !== null) {
29778
30819
  currentQuasi += staticText;
29779
30820
  return true;
@@ -29796,11 +30837,21 @@ function buildCssCalcTemplateExpression(args) {
29796
30837
  cooked: raw
29797
30838
  }, index === quasis.length - 1)), expressions);
29798
30839
  }
29799
- function expressionToCalcStaticText(node) {
30840
+ function expressionToCalcStaticText(node, unit = "") {
29800
30841
  const staticValue = literalToStaticValue(node);
29801
- if (typeof staticValue === "number") return String(staticValue);
30842
+ if (typeof staticValue === "number") return `${staticValue}${unit}`;
29802
30843
  return null;
29803
30844
  }
30845
+ function hasAdjacentTemplateUnit(quasis, expressionIndex) {
30846
+ const before = quasis[expressionIndex]?.value?.raw ?? quasis[expressionIndex]?.value?.cooked ?? "";
30847
+ const after = quasis[expressionIndex + 1]?.value?.raw ?? quasis[expressionIndex + 1]?.value?.cooked ?? "";
30848
+ return /[a-zA-Z%]$/.test(before) || /^[a-zA-Z%]/.test(after);
30849
+ }
30850
+ function hasAdjacentUnitInInterpolatedParts(parts, slotIndex) {
30851
+ const before = parts[slotIndex - 1]?.kind === "static" ? parts[slotIndex - 1]?.value ?? "" : "";
30852
+ const after = parts[slotIndex + 1]?.kind === "static" ? parts[slotIndex + 1]?.value ?? "" : "";
30853
+ return /[a-zA-Z%]$/.test(before) || /^[a-zA-Z%]/.test(after);
30854
+ }
29804
30855
  function isStylexCalcExpression(node) {
29805
30856
  if (!node || typeof node !== "object") return false;
29806
30857
  const n = node;
@@ -29826,7 +30877,7 @@ function isStylexCalcExpression(node) {
29826
30877
  function tryHandleDynamicPseudoElementStyleFunction(args) {
29827
30878
  const { ctx, d, pseudoElement, pseudos, media } = args;
29828
30879
  const { state, decl, styleFnDecls, styleFnFromProps } = ctx;
29829
- const { j, filePath, parseExpr, resolveCall, resolveImportForExpr, resolverImports } = state;
30880
+ const { j, filePath, parseExpr, resolveCall, resolveImportForExpr, resolveImportInScope, resolverImports } = state;
29830
30881
  const avoidNames = new Set(state.importMap.keys());
29831
30882
  const addResolverImports = (imports) => {
29832
30883
  if (!imports) return;
@@ -29881,6 +30932,7 @@ function tryHandleDynamicPseudoElementStyleFunction(args) {
29881
30932
  bindings,
29882
30933
  allowedPropIdentifiers: propsUsed,
29883
30934
  resolveImportForExpr,
30935
+ resolveImportInScope,
29884
30936
  resolveCall,
29885
30937
  parseExpr,
29886
30938
  filePath,
@@ -30040,7 +31092,7 @@ function isUnsupportedCurriedHelperCall(callExpr, ctx) {
30040
31092
  const innerCall = callExpr.callee;
30041
31093
  const calleeInfo = extractRootAndPath(innerCall.callee);
30042
31094
  if (!calleeInfo) return false;
30043
- if (!ctx.resolveImportForExpr(innerCall, calleeInfo.rootName)) return false;
31095
+ if (!ctx.resolveImportInScope(calleeInfo.rootName, calleeInfo.rootNode)) return false;
30044
31096
  const innerArgs = innerCall.arguments ?? [];
30045
31097
  const outerArgs = callExpr.arguments ?? [];
30046
31098
  return innerArgs.length !== 1 || outerArgs.length !== 1 || !isIdentifierNamed(outerArgs[0], ctx.paramName);
@@ -30052,20 +31104,20 @@ function tryResolveDynamicHelperCall(callExpr, ctx) {
30052
31104
  const { innerCall, dynamicArg } = helperCall;
30053
31105
  const calleeInfo = extractRootAndPath(innerCall.callee);
30054
31106
  if (!calleeInfo) return false;
30055
- const imp = ctx.resolveImportForExpr(innerCall, calleeInfo.rootName);
31107
+ const imp = ctx.resolveImportInScope(calleeInfo.rootName, calleeInfo.rootNode);
30056
31108
  if (!imp) return false;
30057
- const dynamicProp = unwrapParamMemberArg(ctx.j, dynamicArg, ctx.paramName, ctx.bindings, ctx.allowedPropIdentifiers);
30058
- if (!dynamicProp) return false;
30059
31109
  const result = ctx.resolveCall({
30060
31110
  callSiteFilePath: ctx.filePath,
30061
31111
  calleeImportedName: imp.importedName,
30062
31112
  calleeSource: imp.source,
30063
- args: [{ kind: "unknown" }],
31113
+ args: callArgsFromNode(innerCall.arguments),
30064
31114
  ...calleeInfo.path.length > 0 ? { calleeMemberPath: calleeInfo.path } : {},
30065
31115
  ...ctx.loc ? { loc: ctx.loc } : {},
30066
31116
  cssProperty: ctx.cssProperty
30067
31117
  });
30068
31118
  if (!result || !("expr" in result)) return false;
31119
+ const dynamicProp = unwrapParamMemberArg(ctx.j, dynamicArg, ctx.paramName, ctx.bindings, ctx.allowedPropIdentifiers);
31120
+ if (!dynamicProp) return false;
30069
31121
  const resolvedExpr = ctx.parseExpr(result.expr);
30070
31122
  if (!resolvedExpr) return null;
30071
31123
  ctx.addResolverImports(result.imports);
@@ -30082,22 +31134,22 @@ function tryResolveDynamicHelperCall(callExpr, ctx) {
30082
31134
  function tryResolveDirectHelperCall(callExpr, ctx) {
30083
31135
  const calleeInfo = extractRootAndPath(callExpr.callee);
30084
31136
  if (!calleeInfo) return false;
30085
- const imp = ctx.resolveImportForExpr(callExpr, calleeInfo.rootName);
31137
+ const imp = ctx.resolveImportInScope(calleeInfo.rootName, calleeInfo.rootNode);
30086
31138
  if (!imp) return false;
30087
- const args = callExpr.arguments ?? [];
30088
- if (args.length !== 1) return false;
30089
- const dynamicProp = unwrapParamMemberArg(ctx.j, args[0], ctx.paramName, ctx.bindings, ctx.allowedPropIdentifiers);
30090
- if (!dynamicProp) return false;
30091
31139
  const result = ctx.resolveCall({
30092
31140
  callSiteFilePath: ctx.filePath,
30093
31141
  calleeImportedName: imp.importedName,
30094
31142
  calleeSource: imp.source,
30095
- args: [{ kind: "unknown" }],
31143
+ args: callArgsFromNode(callExpr.arguments),
30096
31144
  ...calleeInfo.path.length > 0 ? { calleeMemberPath: calleeInfo.path } : {},
30097
31145
  ...ctx.loc ? { loc: ctx.loc } : {},
30098
31146
  cssProperty: ctx.cssProperty
30099
31147
  });
30100
31148
  if (!result || !("expr" in result)) return false;
31149
+ const args = callExpr.arguments ?? [];
31150
+ if (args.length !== 1) return false;
31151
+ const dynamicProp = unwrapParamMemberArg(ctx.j, args[0], ctx.paramName, ctx.bindings, ctx.allowedPropIdentifiers);
31152
+ if (!dynamicProp) return false;
30101
31153
  const resolvedExpr = ctx.parseExpr(result.expr);
30102
31154
  if (!resolvedExpr) return null;
30103
31155
  ctx.addResolverImports(result.imports);
@@ -30420,6 +31472,15 @@ function markThemeHookForVariants(decl, variants) {
30420
31472
  * `import + export {}`) are walked transitively up to a small depth limit
30421
31473
  * with a per-resolution visit set to guard against cycles.
30422
31474
  */
31475
+ function resolveExpressionToStaticString(expr, state) {
31476
+ const direct = literalToStaticValue(expr);
31477
+ if (typeof direct === "string") return direct;
31478
+ if (!isIdentifierNode(expr)) return null;
31479
+ if (state.isIdentifierShadowed(expr, expr.name)) return null;
31480
+ const fromImport = resolveImportedConstStringInit(expr.name, state);
31481
+ if (fromImport !== null) return fromImport;
31482
+ return findTopLevelConstStringInit(expr.name, state);
31483
+ }
30423
31484
  function resolveImportedConstStringInit(localName, state) {
30424
31485
  const importEntry = state.importMap.get(localName);
30425
31486
  if (!importEntry || importEntry.source.kind !== "absolutePath") return null;
@@ -30598,6 +31659,19 @@ function findTopLevelLocalConstString(program, name, state) {
30598
31659
  return (p.parent?.node)?.type === "Program";
30599
31660
  }), (p) => findConstDeclaratorString(p.node.declarations, name));
30600
31661
  }
31662
+ function findTopLevelConstStringInit(name, state) {
31663
+ const { root, j } = state;
31664
+ let resolved = null;
31665
+ root.find(j.VariableDeclaration, { kind: "const" }).filter((p) => {
31666
+ const parentType = (p.parent?.node)?.type;
31667
+ return parentType === "Program" || parentType === "ExportNamedDeclaration";
31668
+ }).forEach((p) => {
31669
+ if (resolved !== null) return;
31670
+ const found = findConstDeclaratorString(p.node.declarations, name);
31671
+ if (found !== null) resolved = found;
31672
+ });
31673
+ return resolved;
31674
+ }
30601
31675
  /**
30602
31676
  * Tries to follow re-exports for `<exportedName>` from `<program>`:
30603
31677
  * - `export { exportedName } from "./other"` (direct)
@@ -30824,58 +31898,18 @@ function resolveInterpolatedPropertyName(property, ctx) {
30824
31898
  if (!resolved.startsWith("--")) return null;
30825
31899
  return resolved;
30826
31900
  }
30827
- /**
30828
- * Resolves an AST expression to a static string. Handles direct string
30829
- * literals and identifiers bound to:
30830
- * - a top-level `const NAME = "..."` declaration in the file being
30831
- * transformed, or
30832
- * - an imported binding whose source file declares a top-level
30833
- * `export const NAME = "..."`.
30834
- *
30835
- * Identifiers that are shadowed by an enclosing scope (e.g. a local `const
30836
- * NAME = "..."` inside the function containing the styled template) are not
30837
- * resolved — bailing is safer than substituting the wrong value.
30838
- */
30839
- function resolveExpressionToStaticString(expr, state) {
30840
- const direct = literalToStaticValue(expr);
30841
- if (typeof direct === "string") return direct;
30842
- if (!isIdentifierNode(expr)) return null;
30843
- if (state.isIdentifierShadowed(expr, expr.name)) return null;
30844
- const fromImport = resolveImportedConstStringInit(expr.name, state);
30845
- if (fromImport !== null) return fromImport;
30846
- return findTopLevelConstStringInit(expr.name, state);
30847
- }
30848
- /**
30849
- * Finds a top-level `const <name> = <literal>` declaration in the current file
30850
- * and returns its initializer when it resolves to a static string. Skips
30851
- * non-`const` declarations and declarators whose initializer is not a static
30852
- * literal so we never substitute a value that could change at runtime.
30853
- */
30854
- function findTopLevelConstStringInit(name, state) {
30855
- const { root, j } = state;
30856
- let resolved = null;
30857
- root.find(j.VariableDeclaration, { kind: "const" }).filter((p) => {
30858
- const parentType = (p.parent?.node)?.type;
30859
- return parentType === "Program" || parentType === "ExportNamedDeclaration";
30860
- }).forEach((p) => {
30861
- if (resolved !== null) return;
30862
- const found = findConstDeclaratorString(p.node.declarations, name);
30863
- if (found !== null) resolved = found;
30864
- });
30865
- return resolved;
30866
- }
30867
31901
  //#endregion
30868
31902
  //#region src/internal/lower-rules/process-rules.ts
30869
31903
  function processDeclRules(ctx) {
30870
31904
  const { state, decl, styleObj, perPropPseudo, perPropMedia, nestedSelectors, variantBuckets, styleFnDecls, attrBuckets, localVarValues, cssHelperPropValues, getComposedDefaultValue } = ctx;
30871
- const { j, root, warnings, resolverImports, resolveSelector, parseExpr, cssHelperNames, declByLocalName, styledDecls, relationOverridePseudoBuckets, relationOverrides, ancestorSelectorParents, childPseudoMarkers, resolveThemeValue, resolveThemeValueFromFn, resolveImportInScope } = state;
31905
+ const { j, root, warnings, resolverImports, resolveSelector, parseExpr, cssHelperNames, declByLocalName, relationOverridePseudoBuckets, relationOverrides, ancestorSelectorParents, resolveThemeValue, resolveThemeValueFromFn, resolveImportInScope } = state;
30872
31906
  /**
30873
31907
  * Attempts to resolve an element selector (e.g., `& svg`, `& > button`) to a
30874
31908
  * styled component override. Returns "break" to bail, "continue" to skip to next
30875
31909
  * rule, or null if the selector isn't an element pattern.
30876
31910
  */
30877
31911
  const tryHandleElementSelector = (selectorStr, rule, parentDecl) => {
30878
- const elementResult = resolveElementSelectorTarget(selectorStr, parentDecl, styledDecls, root, j);
31912
+ const elementResult = resolveElementSelectorTarget(selectorStr, parentDecl, root, j);
30879
31913
  if (typeof elementResult === "string") {
30880
31914
  state.markBail();
30881
31915
  warnings.push({
@@ -30886,38 +31920,38 @@ function processDeclRules(ctx) {
30886
31920
  return "break";
30887
31921
  }
30888
31922
  if (!elementResult) return null;
30889
- const { childDecl, ancestorPseudo, childPseudo, directChildOnly } = elementResult;
30890
- const overrideStyleKey = directChildOnly ? `${toStyleKey(childDecl.localName)}DirectChildIn${parentDecl.localName}` : `${toStyleKey(childDecl.localName)}In${parentDecl.localName}`;
30891
- ancestorSelectorParents.add(parentDecl.styleKey);
30892
- const pseudoForBucket = childPseudo ?? ancestorPseudo;
30893
- if (pseudoForBucket) {
30894
- const existingChildPseudos = childPseudoMarkers.get(overrideStyleKey);
30895
- const existingBuckets = relationOverridePseudoBuckets.get(overrideStyleKey);
30896
- const isAlreadyUsedAsAncestor = !childPseudo && existingChildPseudos?.has(pseudoForBucket);
30897
- const isAlreadyUsedAsChild = childPseudo && existingBuckets?.has(pseudoForBucket) && !existingChildPseudos?.has(pseudoForBucket);
30898
- if (isAlreadyUsedAsAncestor || isAlreadyUsedAsChild) {
30899
- state.markBail();
30900
- warnings.push({
30901
- severity: "warning",
30902
- type: ELEMENT_BAIL_WARNING_MAP["bail-pseudo-collision"],
30903
- loc: computeSelectorWarningLoc(parentDecl.loc, parentDecl.rawCss, rule.selector)
30904
- });
30905
- return "break";
30906
- }
31923
+ const { tagName, ancestorPseudo, childPseudo, directOnly } = elementResult;
31924
+ if (rule.atRuleStack.length > 0) {
31925
+ state.markBail();
31926
+ warnings.push({
31927
+ severity: "warning",
31928
+ type: "Unsupported selector: descendant/child/sibling selector",
31929
+ loc: computeSelectorWarningLoc(parentDecl.loc, parentDecl.rawCss, rule.selector)
31930
+ });
31931
+ return "break";
30907
31932
  }
30908
- if (childPseudo) {
30909
- let markers = childPseudoMarkers.get(overrideStyleKey);
30910
- if (!markers) {
30911
- markers = /* @__PURE__ */ new Set();
30912
- childPseudoMarkers.set(overrideStyleKey, markers);
30913
- }
30914
- markers.add(childPseudo);
31933
+ if (hasDynamicJsxChildren(parentDecl.localName, root, j)) {
31934
+ state.markBail();
31935
+ warnings.push({
31936
+ severity: "warning",
31937
+ type: ELEMENT_BAIL_WARNING_MAP["bail-dynamic"],
31938
+ loc: computeSelectorWarningLoc(parentDecl.loc, parentDecl.rawCss, rule.selector)
31939
+ });
31940
+ return "break";
30915
31941
  }
30916
- const bucket = getOrCreateRelationOverrideBucket(overrideStyleKey, parentDecl.styleKey, childDecl.styleKey, pseudoForBucket, relationOverrides, relationOverridePseudoBuckets, childDecl.extraStyleKeys);
30917
- if (directChildOnly) {
30918
- const override = relationOverrides.find((o) => o.overrideStyleKey === overrideStyleKey);
30919
- if (override) override.directChildOnly = true;
31942
+ if (hasLocalElementPseudoCollision(parentDecl.localElementOverrides ?? [], tagName, ancestorPseudo, childPseudo)) {
31943
+ state.markBail();
31944
+ warnings.push({
31945
+ severity: "warning",
31946
+ type: ELEMENT_BAIL_WARNING_MAP["bail-pseudo-collision"],
31947
+ loc: computeSelectorWarningLoc(parentDecl.loc, parentDecl.rawCss, rule.selector)
31948
+ });
31949
+ return "break";
30920
31950
  }
31951
+ const overrideIndex = (parentDecl.localElementOverrides?.length ?? 0) + 1;
31952
+ const overrideStyleKey = `${parentDecl.styleKey}Element${overrideIndex}`;
31953
+ const pseudoForBucket = childPseudo ?? ancestorPseudo;
31954
+ const bucket = {};
30921
31955
  if (processDeclarationsIntoBucket(rule, bucket, j, parentDecl, resolveThemeValue, resolveThemeValueFromFn, { bailOnUnresolved: true }) === "bail") {
30922
31956
  state.markBail();
30923
31957
  warnings.push({
@@ -30927,6 +31961,18 @@ function processDeclRules(ctx) {
30927
31961
  });
30928
31962
  return "break";
30929
31963
  }
31964
+ const pseudoBuckets = /* @__PURE__ */ new Map();
31965
+ pseudoBuckets.set(pseudoForBucket, bucket);
31966
+ parentDecl.localElementOverrides ??= [];
31967
+ parentDecl.localElementOverrides.push({
31968
+ styleKey: overrideStyleKey,
31969
+ tagName,
31970
+ relation: directOnly ? "child" : "descendant",
31971
+ ancestorPseudo,
31972
+ childPseudo,
31973
+ pseudoBuckets,
31974
+ loc: computeSelectorWarningLoc(parentDecl.loc, parentDecl.rawCss, rule.selector)
31975
+ });
30930
31976
  return "continue";
30931
31977
  };
30932
31978
  const ancestorAttrEntryByKey = /* @__PURE__ */ new Map();
@@ -30938,6 +31984,19 @@ function processDeclRules(ctx) {
30938
31984
  if (state.keyframesNames.has(kfName)) continue;
30939
31985
  }
30940
31986
  let resolvedSelectorMedia = null;
31987
+ if (typeof rule.selector === "string") {
31988
+ const selectorWithStaticAttrs = resolveStaticAttributeSelectorPlaceholders(rule.selector, decl, state);
31989
+ if (selectorWithStaticAttrs === null) {
31990
+ state.markBail();
31991
+ warnings.push({
31992
+ severity: "warning",
31993
+ type: "Unsupported selector: unresolved interpolation in attribute selector",
31994
+ loc: computeSelectorWarningLoc(decl.loc, decl.rawCss, rule.selector)
31995
+ });
31996
+ break;
31997
+ }
31998
+ rule.selector = selectorWithStaticAttrs;
31999
+ }
30941
32000
  if (typeof rule.selector === "string") {
30942
32001
  const specificityResult = normalizeSpecificityHacks(rule.selector);
30943
32002
  if (specificityResult.hasHigherTier) {
@@ -31868,22 +32927,17 @@ const ELEMENT_BAIL_WARNING_MAP = {
31868
32927
  * the resolved child declaration + pseudo info, a bail reason, or null if not an
31869
32928
  * element selector pattern.
31870
32929
  */
31871
- function resolveElementSelectorTarget(selector, parentDecl, styledDecls, root, j) {
32930
+ function resolveElementSelectorTarget(selector, parentDecl, root, j) {
31872
32931
  const parsed = parseElementSelectorPattern(selector);
31873
32932
  if (!parsed) return null;
31874
- const { tagName, ancestorPseudo, childPseudo } = parsed;
32933
+ const { tagName, ancestorPseudo, childPseudo, directOnly } = parsed;
31875
32934
  if (ancestorPseudo && childPseudo) return "bail-combined-pseudo";
31876
32935
  if (isComponentExported(parentDecl.localName, root, j)) return "bail-exported";
31877
- const matches = styledDecls.filter((d) => !d.isCssHelper && d.localName !== parentDecl.localName && d.base.kind === "intrinsic" && d.base.tagName === tagName);
31878
- if (matches.length === 0) return null;
31879
- if (matches.length > 1) return "bail-ambiguous";
31880
- if (hasDynamicJsxChildren(parentDecl.localName, root, j)) return "bail-dynamic";
31881
- if (hasPlainIntrinsicDescendant(parentDecl.localName, tagName, matches[0].localName, root, j)) return "bail-plain-intrinsic";
31882
32936
  return {
31883
- childDecl: matches[0],
32937
+ tagName,
31884
32938
  ancestorPseudo,
31885
32939
  childPseudo,
31886
- directChildOnly: parsed.usesChildCombinator
32940
+ directOnly
31887
32941
  };
31888
32942
  }
31889
32943
  /**
@@ -31902,30 +32956,6 @@ function isComponentExported(name, root, j) {
31902
32956
  return decl?.type === "Identifier" && decl.name === name;
31903
32957
  }).size() > 0;
31904
32958
  }
31905
- /**
31906
- * Checks whether any JSX usage of the given parent component contains a plain
31907
- * intrinsic element matching `tagName` that is NOT the styled component. For example,
31908
- * if parent renders both `<Icon />` (styled.svg) and a plain `<svg>`, returns true.
31909
- */
31910
- function hasPlainIntrinsicDescendant(parentName, tagName, styledChildName, root, j) {
31911
- let found = false;
31912
- root.find(j.JSXElement, { openingElement: { name: {
31913
- type: "JSXIdentifier",
31914
- name: parentName
31915
- } } }).forEach((path) => {
31916
- if (found) return;
31917
- for (const child of path.node.children ?? []) if (child.type === "JSXElement" && child.openingElement.name.type === "JSXIdentifier" && child.openingElement.name.name === tagName && child.openingElement.name.name !== styledChildName) {
31918
- found = true;
31919
- return;
31920
- }
31921
- });
31922
- return found;
31923
- }
31924
- /**
31925
- * Checks whether any JSX usage of the given component has dynamic children
31926
- * ({children}, {props.children}, or non-empty JSXExpressionContainers).
31927
- * Static JSX children (<Icon />, <div>text</div>) are OK.
31928
- */
31929
32959
  function hasDynamicJsxChildren(componentName, root, j) {
31930
32960
  let hasDynamic = false;
31931
32961
  root.find(j.JSXElement, { openingElement: { name: {
@@ -31941,6 +32971,14 @@ function hasDynamicJsxChildren(componentName, root, j) {
31941
32971
  });
31942
32972
  return hasDynamic;
31943
32973
  }
32974
+ function hasLocalElementPseudoCollision(overrides, tagName, ancestorPseudo, childPseudo) {
32975
+ const nextPseudo = childPseudo ?? ancestorPseudo;
32976
+ if (!nextPseudo) return false;
32977
+ return overrides.some((override) => {
32978
+ if (override.tagName !== tagName) return false;
32979
+ return (override.childPseudo ?? override.ancestorPseudo) === nextPseudo && override.childPseudo !== childPseudo;
32980
+ });
32981
+ }
31944
32982
  /**
31945
32983
  * Attempts to resolve an interpolated pseudo-class selector (`&:${expr}`) via the
31946
32984
  * adapter's `resolveSelector`. Handles `pseudoAlias` (builds N separate style
@@ -32215,10 +33253,32 @@ function extractCssTextFromNode(node) {
32215
33253
  if (n.type === "TemplateLiteral" && (!n.expressions || n.expressions.length === 0)) return (n.quasis ?? []).map((q) => q.value?.raw ?? "").join("");
32216
33254
  return null;
32217
33255
  }
33256
+ function resolveStaticAttributeSelectorPlaceholders(selector, decl, state) {
33257
+ if (!selector.includes("__SC_EXPR_")) return selector;
33258
+ let failed = false;
33259
+ const resolvedSelector = selector.replace(ATTRIBUTE_SELECTOR_WITH_PLACEHOLDER_RE, (attributeSelector) => {
33260
+ const match = attributeSelector.match(ATTRIBUTE_NAME_PLACEHOLDER_RE);
33261
+ if (!match?.[1]) {
33262
+ failed = true;
33263
+ return attributeSelector;
33264
+ }
33265
+ const slotId = Number(match[1]);
33266
+ const value = resolveExpressionToStaticString(decl.templateExpressions[slotId], state);
33267
+ if (value === null || !CSS_ATTRIBUTE_NAME_RE.test(value)) {
33268
+ failed = true;
33269
+ return attributeSelector;
33270
+ }
33271
+ return `[${value}${match[2] ?? ""}]`;
33272
+ });
33273
+ return failed ? null : resolvedSelector;
33274
+ }
32218
33275
  /** Descendant-has pattern (full selector match): exactly `&:has(__SC_EXPR_N__)` */
32219
33276
  const HAS_COMPONENT_SELECTOR_STRICT_RE = /^&:has\(__SC_EXPR_\d+__\)\s*$/;
32220
33277
  /** Reverse selector pattern for a single part: `__SC_EXPR_N__:pseudo &` */
32221
33278
  const REVERSE_SELECTOR_PART_RE = /^__SC_EXPR_\d+__:[a-z][a-z0-9()-]*\s+&$/;
33279
+ const ATTRIBUTE_SELECTOR_WITH_PLACEHOLDER_RE = /\[[^\][]*__SC_EXPR_\d+__[^\][]*\]/g;
33280
+ const ATTRIBUTE_NAME_PLACEHOLDER_RE = /^\[\s*__SC_EXPR_(\d+)__(\s*(?:(?:[~|^$*]?=)\s*(?:"[^"]*"|'[^']*'|[^\]\s]+)\s*(?:[iIsS]\s*)?)?)\]$/;
33281
+ const CSS_ATTRIBUTE_NAME_RE = /^(?:-?[_a-zA-Z]|--)[-_a-zA-Z0-9:.]*$/;
32222
33282
  function extractParentPseudosForNestedComponentBlock(rawCss, slotId) {
32223
33283
  if (!rawCss) return null;
32224
33284
  const placeholder = `__SC_EXPR_${slotId}__`;
@@ -32629,81 +33689,6 @@ function isDirectAttrsPropValue(entry) {
32629
33689
  return node.type === "Identifier" && node.name === entry.jsxProp;
32630
33690
  }
32631
33691
  //#endregion
32632
- //#region src/internal/lower-rules/relation-overrides.ts
32633
- const finalizeRelationOverrides = (args) => {
32634
- const { j, relationOverridePseudoBuckets, relationOverrides, resolvedStyleObjects, makeCssPropKey, childPseudoMarkers } = args;
32635
- if (relationOverridePseudoBuckets.size === 0) return;
32636
- const overrideToChildKeys = /* @__PURE__ */ new Map();
32637
- const overrideToMarker = /* @__PURE__ */ new Map();
32638
- for (const o of relationOverrides) {
32639
- overrideToChildKeys.set(o.overrideStyleKey, [o.childStyleKey, ...o.childExtraStyleKeys ?? []]);
32640
- if (o.markerVarName) overrideToMarker.set(o.overrideStyleKey, o.markerVarName);
32641
- }
32642
- const isExpressionNode = (v) => isAstNode(v);
32643
- for (const [overrideKey, pseudoBuckets] of relationOverridePseudoBuckets.entries()) {
32644
- const baseBucket = pseudoBuckets.get(null) ?? {};
32645
- const props = [];
32646
- const markerVarName = overrideToMarker.get(overrideKey);
32647
- const childStyleObjects = buildChildStyleObjectList(overrideToChildKeys.get(overrideKey) ?? [], resolvedStyleObjects);
32648
- const allPropNames = /* @__PURE__ */ new Set();
32649
- for (const bucket of pseudoBuckets.values()) for (const prop of Object.keys(bucket)) allPropNames.add(prop);
32650
- for (const prop of allPropNames) {
32651
- let baseVal = baseBucket[prop];
32652
- if (baseVal === void 0) for (const childStyle of childStyleObjects) {
32653
- const val = childStyle[prop];
32654
- if (val !== void 0) {
32655
- baseVal = val;
32656
- break;
32657
- }
32658
- }
32659
- baseVal = extractScalarDefault(baseVal);
32660
- const pseudoValues = [];
32661
- for (const [pseudo, bucket] of pseudoBuckets.entries()) {
32662
- if (pseudo === null) continue;
32663
- const val = bucket[prop];
32664
- if (val !== void 0) pseudoValues.push({
32665
- pseudo,
32666
- value: val
32667
- });
32668
- }
32669
- if (pseudoValues.length > 0) {
32670
- const objProps = [j.property("init", j.identifier("default"), isExpressionNode(baseVal) ? baseVal : literalToAst(j, baseVal ?? null))];
32671
- const childPseudos = childPseudoMarkers.get(overrideKey);
32672
- for (const { pseudo, value } of pseudoValues) {
32673
- const valExpr = isExpressionNode(value) ? value : literalToAst(j, value);
32674
- if (childPseudos?.has(pseudo)) objProps.push(j.property("init", j.literal(pseudo), valExpr));
32675
- else {
32676
- const ancestorKey = makeAncestorKeyExpr(j, pseudo, markerVarName);
32677
- const propNode = Object.assign(j.property("init", ancestorKey, valExpr), { computed: true });
32678
- objProps.push(propNode);
32679
- }
32680
- }
32681
- const mapExpr = j.objectExpression(objProps);
32682
- props.push(j.property("init", makeCssPropKey(j, prop), mapExpr));
32683
- } else if (baseVal !== void 0) props.push(j.property("init", makeCssPropKey(j, prop), isExpressionNode(baseVal) ? baseVal : literalToAst(j, baseVal)));
32684
- }
32685
- if (props.length > 0) resolvedStyleObjects.set(overrideKey, j.objectExpression(props));
32686
- }
32687
- };
32688
- /**
32689
- * If a value is a pseudo/media map (e.g., `{ default: "gray", ":focus": "orange" }`),
32690
- * extracts its scalar `default` property. AST nodes and non-map values pass through.
32691
- */
32692
- function extractScalarDefault(value) {
32693
- if (!value || typeof value !== "object" || Array.isArray(value) || isAstNode(value)) return value;
32694
- const map = value;
32695
- if ("default" in map) return map.default;
32696
- return value;
32697
- }
32698
- function buildChildStyleObjectList(childKeys, resolvedStyleObjects) {
32699
- const childStyleObjects = [];
32700
- for (const key of childKeys) {
32701
- const obj = resolvedStyleObjects.get(key);
32702
- if (obj && typeof obj === "object" && !isAstNode(obj)) childStyleObjects.push(obj);
32703
- }
32704
- return childStyleObjects;
32705
- }
32706
- //#endregion
32707
33692
  //#region src/internal/lower-rules/state.ts
32708
33693
  /**
32709
33694
  * Builds shared state for the lower-rules pipeline.
@@ -33374,9 +34359,196 @@ function collectTemplateSelectorIdentifiersFromParts(rawCss, templateExpressions
33374
34359
  return identifiers;
33375
34360
  }
33376
34361
  //#endregion
34362
+ //#region src/internal/post-process-consumed-helpers.ts
34363
+ function cleanupConsumedLocalHelpers(ctx, styledDecls) {
34364
+ const { root, j } = ctx;
34365
+ for (const decl of styledDecls) for (const helperName of decl.consumedLocalHelpers ?? []) {
34366
+ const fnPaths = root.find(j.FunctionDeclaration, { id: { name: helperName } });
34367
+ if (fnPaths.size() === 0) continue;
34368
+ if (isExportedFunction(fnPaths)) continue;
34369
+ if (root.find(j.Identifier, { name: helperName }).filter((idPath) => {
34370
+ const parent = idPath.parentPath?.node;
34371
+ if (parent?.type === "FunctionDeclaration" && parent.id === idPath.node) return false;
34372
+ return true;
34373
+ }).size() === 0) fnPaths.forEach((p) => p.prune());
34374
+ }
34375
+ }
34376
+ function isExportedFunction(fnPaths) {
34377
+ return fnPaths.some((p) => p.parentPath?.node?.type === "ExportNamedDeclaration" || p.parentPath?.node?.type === "ExportDefaultDeclaration");
34378
+ }
34379
+ //#endregion
34380
+ //#region src/internal/post-process-empty-style-references.ts
34381
+ function cleanupEmptyStyleReferences(args) {
34382
+ const { root, j, emptyStyleKeys, stylesIdentifier } = args;
34383
+ if (!emptyStyleKeys || emptyStyleKeys.size === 0) return false;
34384
+ let changed = false;
34385
+ const isEmptyStyleRef = (a) => {
34386
+ const propertyName = getIdentifierMemberPropertyName(a, stylesIdentifier);
34387
+ return propertyName !== null && emptyStyleKeys.has(propertyName);
34388
+ };
34389
+ root.find(j.CallExpression).forEach((p) => {
34390
+ const call = p.node;
34391
+ if (isIdentifierMemberExpression(call?.callee, "stylex", "props")) {
34392
+ const originalLength = (call.arguments ?? []).length;
34393
+ call.arguments = (call.arguments ?? []).filter((a) => !isEmptyStyleRef(a));
34394
+ if (call.arguments.length !== originalLength) changed = true;
34395
+ if (call.arguments.length === 0) {
34396
+ const parentNode = p.parentPath?.node;
34397
+ if (parentNode?.type === "JSXSpreadAttribute") {
34398
+ const jsxOpening = p.parentPath?.parentPath?.node;
34399
+ if (jsxOpening?.type === "JSXOpeningElement" && Array.isArray(jsxOpening.attributes)) {
34400
+ jsxOpening.attributes = jsxOpening.attributes.filter((attr) => attr !== parentNode);
34401
+ changed = true;
34402
+ }
34403
+ }
34404
+ }
34405
+ }
34406
+ if (call?.callee?.type === "Identifier") {
34407
+ const firstArg = call.arguments?.[0];
34408
+ if (firstArg?.type === "ArrayExpression") {
34409
+ const arr = firstArg;
34410
+ const originalLength = (arr.elements ?? []).length;
34411
+ arr.elements = (arr.elements ?? []).filter((e) => !isEmptyStyleRef(e));
34412
+ if (arr.elements.length !== originalLength) changed = true;
34413
+ }
34414
+ if (isEmptyStyleRef(firstArg)) {
34415
+ call.arguments[0] = j.identifier("undefined");
34416
+ changed = true;
34417
+ }
34418
+ }
34419
+ });
34420
+ root.find(j.JSXAttribute, { name: { name: "sx" } }).forEach((p) => {
34421
+ const val = p.node.value;
34422
+ if (!val || val.type !== "JSXExpressionContainer") return;
34423
+ const expr = val.expression;
34424
+ if (expr?.type === "ArrayExpression") {
34425
+ const orig = (expr.elements ?? []).length;
34426
+ expr.elements = (expr.elements ?? []).filter((e) => !isEmptyStyleRef(e));
34427
+ if (expr.elements.length !== orig) changed = true;
34428
+ if (expr.elements.length === 1) {
34429
+ val.expression = expr.elements[0];
34430
+ changed = true;
34431
+ }
34432
+ if (expr.elements.length === 0) {
34433
+ const opening = p.parentPath?.node;
34434
+ if (opening?.type === "JSXOpeningElement" && Array.isArray(opening.attributes)) {
34435
+ opening.attributes = opening.attributes.filter((attr) => attr !== p.node);
34436
+ changed = true;
34437
+ }
34438
+ }
34439
+ } else if (isEmptyStyleRef(expr)) {
34440
+ const opening = p.parentPath?.node;
34441
+ if (opening?.type === "JSXOpeningElement" && Array.isArray(opening.attributes)) {
34442
+ opening.attributes = opening.attributes.filter((attr) => attr !== p.node);
34443
+ changed = true;
34444
+ }
34445
+ }
34446
+ });
34447
+ return changed;
34448
+ }
34449
+ //#endregion
34450
+ //#region src/internal/post-process-imports.ts
34451
+ function cleanupPostProcessImports(args) {
34452
+ const { root, j, preserveReactImport, newImportLocalNames, newImportSourcesByLocal } = args;
34453
+ let changed = false;
34454
+ root.find(j.ImportDeclaration, { source: { value: "@emotion/is-prop-valid" } }).forEach((p) => {
34455
+ const spec = p.node.specifiers?.find((s) => s.type === "ImportDefaultSpecifier");
34456
+ const local = spec?.local?.type === "Identifier" ? spec.local.name : null;
34457
+ if (!local) return;
34458
+ if (!(root.find(j.Identifier, { name: local }).filter((idPath) => j(idPath).closest(j.ImportDeclaration).size() === 0).size() > 0)) {
34459
+ j(p).remove();
34460
+ changed = true;
34461
+ }
34462
+ });
34463
+ root.find(j.ImportDeclaration).forEach((p) => {
34464
+ if (preserveReactImport && (p.node?.source)?.value === "react") {
34465
+ if ((p.node.specifiers ?? []).some((s) => (s.type === "ImportDefaultSpecifier" || s.type === "ImportNamespaceSpecifier") && s.local?.type === "Identifier" && s.local.name === "React")) return;
34466
+ }
34467
+ const specs = p.node.specifiers ?? [];
34468
+ if (specs.length === 0) return;
34469
+ if (p.node.importKind === "type") return;
34470
+ const nextSpecs = specs.filter((s) => {
34471
+ if (s?.importKind === "type") return true;
34472
+ const local = s?.local?.type === "Identifier" ? s.local.name : s?.type === "ImportDefaultSpecifier" && s.local?.type === "Identifier" ? s.local.name : s?.type === "ImportNamespaceSpecifier" && s.local?.type === "Identifier" ? s.local.name : null;
34473
+ if (!local) return true;
34474
+ if (newImportLocalNames?.has(local)) {
34475
+ const sourceValue = (p.node?.source)?.value;
34476
+ const allowedSources = newImportSourcesByLocal?.get(local);
34477
+ if (!allowedSources || !allowedSources.has(sourceValue)) return false;
34478
+ }
34479
+ return usedOutsideImports(root, j, local, s.local?.type === "Identifier" ? s.local : null);
34480
+ });
34481
+ if (nextSpecs.length !== specs.length) {
34482
+ p.node.specifiers = nextSpecs;
34483
+ changed = true;
34484
+ }
34485
+ if ((p.node.specifiers?.length ?? 0) === 0) {
34486
+ j(p).remove();
34487
+ changed = true;
34488
+ }
34489
+ });
34490
+ return {
34491
+ changed,
34492
+ needsReactImport: usesReactIdentifierWithoutImport(root, j)
34493
+ };
34494
+ }
34495
+ function collectNewImportMetadata(resolverImports, filePath) {
34496
+ const newImportLocalNames = /* @__PURE__ */ new Set();
34497
+ const newImportSourcesByLocal = /* @__PURE__ */ new Map();
34498
+ for (const imp of resolverImports.values()) {
34499
+ const source = importSourceToModuleSpecifier(imp.from, filePath);
34500
+ for (const n of imp.names ?? []) {
34501
+ const local = n.local ?? n.imported;
34502
+ if (local) {
34503
+ newImportLocalNames.add(local);
34504
+ const sources = newImportSourcesByLocal.get(local) ?? /* @__PURE__ */ new Set();
34505
+ sources.add(source);
34506
+ newImportSourcesByLocal.set(local, sources);
34507
+ }
34508
+ }
34509
+ }
34510
+ return {
34511
+ newImportLocalNames,
34512
+ newImportSourcesByLocal
34513
+ };
34514
+ }
34515
+ function usedOutsideImports(root, j, localName, importLocalNode) {
34516
+ const usedByIdentifier = root.find(j.Identifier, { name: localName }).filter((idPath) => {
34517
+ if (j(idPath).closest(j.ImportDeclaration).size() > 0) return false;
34518
+ const parent = idPath.parent?.node;
34519
+ if (parent && isMemberExpression(parent) && parent.property === idPath.node && parent.computed === false) return false;
34520
+ if (parent && parent.type === "Property" && parent.key === idPath.node && parent.shorthand !== true) return false;
34521
+ if (parent?.type === "TSPropertySignature" && parent.key === idPath.node) return false;
34522
+ if (parent?.type === "JSXAttribute" && parent.name === idPath.node) return false;
34523
+ return resolvesToImportBinding(idPath, localName, importLocalNode);
34524
+ }).size() > 0;
34525
+ const usedByJsxIdentifier = isProbablyJsxBindingName(localName) && root.find(j.JSXIdentifier, { name: localName }).filter((jsxPath) => {
34526
+ if (j(jsxPath).closest(j.ImportDeclaration).size() > 0) return false;
34527
+ return true;
34528
+ }).size() > 0;
34529
+ return usedByIdentifier || usedByJsxIdentifier;
34530
+ }
34531
+ function isProbablyJsxBindingName(name) {
34532
+ const first = name[0] ?? "";
34533
+ return first.toUpperCase() === first && first.toLowerCase() !== first;
34534
+ }
34535
+ function resolvesToImportBinding(idPath, localName, importLocalNode) {
34536
+ try {
34537
+ const bindings = (idPath.scope?.lookup?.(localName))?.getBindings?.()?.[localName];
34538
+ if (!Array.isArray(bindings)) return true;
34539
+ return bindings.some((bindingPath) => bindingPath?.node === importLocalNode);
34540
+ } catch {
34541
+ return true;
34542
+ }
34543
+ }
34544
+ function usesReactIdentifierWithoutImport(root, j) {
34545
+ const hasReactImport = root.find(j.ImportDeclaration).filter((p) => (p.node?.source)?.value === "react").filter((p) => (p.node.specifiers ?? []).some((s) => (s.type === "ImportDefaultSpecifier" || s.type === "ImportNamespaceSpecifier") && s.local?.type === "Identifier" && s.local.name === "React")).size() > 0;
34546
+ return root.find(j.Identifier, { name: "React" }).size() > 0 && !hasReactImport;
34547
+ }
34548
+ //#endregion
33377
34549
  //#region src/internal/rewrite-jsx.ts
33378
34550
  function postProcessTransformedAst(args) {
33379
- const { root, j, relationOverrides, ancestorSelectorParents, componentNameToStyleKey, emptyStyleKeys, preserveReactImport, newImportLocalNames, newImportSourcesByLocal, stylesIdentifier = "styles", crossFileMarkers, parentsNeedingDefaultMarker, ancestorAttrsByStyleKey } = args;
34551
+ const { root, j, relationOverrides, ancestorSelectorParents, styledDecls, localElementOverridesByParent = /* @__PURE__ */ new Map(), componentNameToStyleKey, emptyStyleKeys, preserveReactImport, newImportLocalNames, newImportSourcesByLocal, stylesIdentifier = "styles", crossFileMarkers, parentsNeedingDefaultMarker, ancestorAttrsByStyleKey } = args;
33380
34552
  let changed = false;
33381
34553
  root.find(j.VariableDeclaration).forEach((p) => {
33382
34554
  if (p.node.declarations.length === 0) {
@@ -33384,7 +34556,7 @@ function postProcessTransformedAst(args) {
33384
34556
  changed = true;
33385
34557
  }
33386
34558
  });
33387
- if (relationOverrides.length > 0 || ancestorSelectorParents.size > 0 || ancestorAttrsByStyleKey && ancestorAttrsByStyleKey.size > 0) {
34559
+ if (relationOverrides.length > 0 || ancestorSelectorParents.size > 0 || localElementOverridesByParent.size > 0 || ancestorAttrsByStyleKey && ancestorAttrsByStyleKey.size > 0) {
33388
34560
  const makeDefaultMarkerCall = () => j.callExpression(j.memberExpression(j.identifier("stylex"), j.identifier("defaultMarker")), []);
33389
34561
  const crossFileChildOverrides = /* @__PURE__ */ new Map();
33390
34562
  const crossFileParentMarkers = /* @__PURE__ */ new Map();
@@ -33392,7 +34564,7 @@ function postProcessTransformedAst(args) {
33392
34564
  if (!o.crossFile || !o.crossFileComponentLocalName) continue;
33393
34565
  appendToMapList(componentNameToStyleKey?.get(o.crossFileComponentLocalName) === o.parentStyleKey || o.parentStyleKey === toStyleKey(o.crossFileComponentLocalName) ? crossFileParentMarkers : crossFileChildOverrides, o.crossFileComponentLocalName, o);
33394
34566
  }
33395
- const isStylexPropsCall = (n) => n?.type === "CallExpression" && n.callee?.type === "MemberExpression" && n.callee.object?.type === "Identifier" && n.callee.object.name === "stylex" && n.callee.property?.type === "Identifier" && n.callee.property.name === "props";
34567
+ const isStylexPropsCall = (n) => n?.type === "CallExpression" && isIdentifierMemberExpression(n.callee, "stylex", "props");
33396
34568
  const getStylexPropsCallFromAttrs = (attrs) => {
33397
34569
  for (const a of attrs ?? []) {
33398
34570
  if (a.type !== "JSXSpreadAttribute") continue;
@@ -33410,7 +34582,7 @@ function postProcessTransformedAst(args) {
33410
34582
  for (const a of attrs ?? []) if (a.type === "JSXAttribute" && a.name?.type === "JSXIdentifier" && a.name.name === "sx" && a.value?.type === "JSXExpressionContainer") return a;
33411
34583
  };
33412
34584
  const isStyleKeyRef = (node, key) => {
33413
- if (node?.type === "MemberExpression" && node.object?.type === "Identifier" && node.object.name === stylesIdentifier && node.property?.type === "Identifier" && node.property.name === key) return true;
34585
+ if (isIdentifierMemberExpression(node, stylesIdentifier, key)) return true;
33414
34586
  if (node?.type === "CallExpression") return isStyleKeyRef(node.callee, key);
33415
34587
  return false;
33416
34588
  };
@@ -33433,22 +34605,27 @@ function postProcessTransformedAst(args) {
33433
34605
  else container.expression = j.arrayExpression([expr, ...newArgs]);
33434
34606
  };
33435
34607
  const isIdentifierNamed = (a, name) => a?.type === "Identifier" && a.name === name;
33436
- const isDefaultMarkerCall = (a) => a?.type === "CallExpression" && a.callee?.type === "MemberExpression" && a.callee.object?.type === "Identifier" && a.callee.object.name === "stylex" && a.callee.property?.type === "Identifier" && a.callee.property.name === "defaultMarker";
34608
+ const isDefaultMarkerCall = (a) => a?.type === "CallExpression" && isIdentifierMemberExpression(a.callee, "stylex", "defaultMarker");
33437
34609
  const hasIdentifierArg = (call, name) => (call.arguments ?? []).some((a) => isIdentifierNamed(a, name));
33438
34610
  const hasIdentifierInSxArgs = (sxAttr, name) => getSxAttrArgs(sxAttr.value.expression).some((a) => isIdentifierNamed(a, name));
33439
34611
  const hasDefaultMarker = (call) => (call.arguments ?? []).some(isDefaultMarkerCall);
33440
34612
  const hasDefaultMarkerInSxArgs = (sxAttr) => getSxAttrArgs(sxAttr.value.expression).some(isDefaultMarkerCall);
33441
34613
  const overridesByChild = /* @__PURE__ */ new Map();
33442
34614
  for (const o of relationOverrides) overridesByChild.set(o.childStyleKey, [...overridesByChild.get(o.childStyleKey) ?? [], o]);
34615
+ const componentNameToDecl = /* @__PURE__ */ new Map();
34616
+ for (const decl of styledDecls ?? []) componentNameToDecl.set(decl.localName, decl);
34617
+ const ancestorEntryHasParentKey = (ancestor, parentStyleKey) => {
34618
+ const markerVarName = crossFileMarkers?.get(parentStyleKey);
34619
+ return ancestor?.call && hasStyleKeyArg(ancestor.call, parentStyleKey) || ancestor?.sxAttr && getSxAttrArgs(ancestor.sxAttr.value.expression).some((arg) => isStyleKeyRef(arg, parentStyleKey)) || ancestor?.elementStyleKey && ancestor.elementStyleKey === parentStyleKey || markerVarName && ancestor?.markerVarName === markerVarName;
34620
+ };
33443
34621
  /** Check if any ancestor in the JSX tree contains the given parent style key. */
33444
34622
  const ancestorHasParentKey = (ancestors, parentStyleKey) => {
33445
- const markerVarName = crossFileMarkers?.get(parentStyleKey);
33446
- return ancestors.some((a) => a?.call && hasStyleKeyArg(a.call, parentStyleKey) || a?.sxAttr && getSxAttrArgs(a.sxAttr.value.expression).some((arg) => isStyleKeyRef(arg, parentStyleKey)) || a?.elementStyleKey && a.elementStyleKey === parentStyleKey || markerVarName && a?.markerVarName === markerVarName);
34623
+ return ancestors.some((a) => ancestorEntryHasParentKey(a, parentStyleKey));
33447
34624
  };
33448
34625
  const directParentHasParentKey = (ancestors, parentStyleKey) => {
33449
34626
  const directParent = ancestors.at(-1);
33450
34627
  if (!directParent) return false;
33451
- return directParent.call && hasStyleKeyArg(directParent.call, parentStyleKey) || directParent.sxAttr && getSxAttrArgs(directParent.sxAttr.value.expression).some((arg) => isStyleKeyRef(arg, parentStyleKey)) || directParent.elementStyleKey === parentStyleKey;
34628
+ return ancestorEntryHasParentKey(directParent, parentStyleKey);
33452
34629
  };
33453
34630
  const pendingEmptyKeyRemovals = [];
33454
34631
  const visit = (node, ancestors) => {
@@ -33459,6 +34636,7 @@ function postProcessTransformedAst(args) {
33459
34636
  const sxAttr = getSxAttrFromAttrs(attrs);
33460
34637
  const elementName = getJsxElementName(opening?.name, { allowMemberExpression: false });
33461
34638
  const elementStyleKey = elementName ? componentNameToStyleKey?.get(elementName) : null;
34639
+ const originalStyledName = opening.__styledComponentLocalName;
33462
34640
  if (call) {
33463
34641
  for (const parentKey of ancestorSelectorParents) if (hasStyleKeyArg(call, parentKey)) {
33464
34642
  if (emptyStyleKeys?.has(parentKey)) pendingEmptyKeyRemovals.push({
@@ -33503,6 +34681,35 @@ function postProcessTransformedAst(args) {
33503
34681
  changed = true;
33504
34682
  }
33505
34683
  }
34684
+ const nearestAncestor = ancestors[ancestors.length - 1];
34685
+ const targetId = getLocalElementTargetId(opening, elementName ?? null, originalStyledName);
34686
+ if (targetId || localElementOverridesByParent.size > 0) for (const [parentStyleKey, localOverrides] of localElementOverridesByParent.entries()) {
34687
+ if (!ancestorHasParentKey(ancestors, parentStyleKey)) continue;
34688
+ for (const override of localOverrides) {
34689
+ if (override.relation === "child" && (!nearestAncestor || !ancestorEntryHasParentKey(nearestAncestor, parentStyleKey))) continue;
34690
+ const resolvedTargetId = resolveLocalElementTargetForNode({
34691
+ targetId,
34692
+ override,
34693
+ attrs,
34694
+ opening,
34695
+ componentNameToDecl,
34696
+ hasStyleKeyInAttrs
34697
+ });
34698
+ if (!resolvedTargetId) continue;
34699
+ const localStyleKey = override.styleKeysByTargetId?.[resolvedTargetId];
34700
+ if (!localStyleKey) continue;
34701
+ if (call ? hasStyleKeyArg(call, localStyleKey) : hasStyleKeyInAttrs(attrs, localStyleKey)) continue;
34702
+ const overrideArg = j.memberExpression(j.identifier(stylesIdentifier), j.identifier(localStyleKey));
34703
+ if (call) call.arguments = [...call.arguments ?? [], overrideArg];
34704
+ else if (sxAttr) addArgsToSxAttr(sxAttr, [overrideArg]);
34705
+ else {
34706
+ const existingSxAttr = getSxAttrFromAttrs(opening.attributes ?? []);
34707
+ if (existingSxAttr) addArgsToSxAttr(existingSxAttr, [overrideArg]);
34708
+ else opening.attributes = [...opening.attributes ?? [], j.jsxAttribute(j.jsxIdentifier("sx"), j.jsxExpressionContainer(overrideArg))];
34709
+ }
34710
+ changed = true;
34711
+ }
34712
+ }
33506
34713
  const childOverrides = elementName ? crossFileChildOverrides.get(elementName) : void 0;
33507
34714
  if (childOverrides) {
33508
34715
  const overrideArgs = [];
@@ -33635,148 +34842,35 @@ function postProcessTransformedAst(args) {
33635
34842
  });
33636
34843
  for (const { call, key } of pendingEmptyKeyRemovals) {
33637
34844
  const originalLength = (call.arguments ?? []).length;
33638
- call.arguments = (call.arguments ?? []).filter((a) => !(a?.type === "MemberExpression" && a.object?.type === "Identifier" && a.object.name === stylesIdentifier && a.property?.type === "Identifier" && a.property.name === key));
34845
+ call.arguments = (call.arguments ?? []).filter((a) => !isIdentifierMemberExpression(a, stylesIdentifier, key));
33639
34846
  if ((call.arguments ?? []).length !== originalLength) changed = true;
33640
34847
  }
33641
34848
  }
33642
- if (emptyStyleKeys && emptyStyleKeys.size > 0) {
33643
- const isEmptyStyleRef = (a) => a?.type === "MemberExpression" && a.object?.type === "Identifier" && a.object.name === stylesIdentifier && a.property?.type === "Identifier" && emptyStyleKeys.has(a.property.name);
33644
- root.find(j.CallExpression).forEach((p) => {
33645
- const call = p.node;
33646
- if (call?.callee?.type === "MemberExpression" && call.callee.object?.type === "Identifier" && call.callee.object.name === "stylex" && call.callee.property?.type === "Identifier" && call.callee.property.name === "props") {
33647
- const originalLength = (call.arguments ?? []).length;
33648
- call.arguments = (call.arguments ?? []).filter((a) => !isEmptyStyleRef(a));
33649
- if (call.arguments.length !== originalLength) changed = true;
33650
- if (call.arguments.length === 0) {
33651
- const parentNode = p.parentPath?.node;
33652
- if (parentNode?.type === "JSXSpreadAttribute") {
33653
- const jsxOpening = p.parentPath?.parentPath?.node;
33654
- if (jsxOpening?.type === "JSXOpeningElement" && Array.isArray(jsxOpening.attributes)) {
33655
- jsxOpening.attributes = jsxOpening.attributes.filter((attr) => attr !== parentNode);
33656
- changed = true;
33657
- }
33658
- }
33659
- }
33660
- }
33661
- if (call?.callee?.type === "Identifier") {
33662
- const firstArg = call.arguments?.[0];
33663
- if (firstArg?.type === "ArrayExpression") {
33664
- const arr = firstArg;
33665
- const originalLength = (arr.elements ?? []).length;
33666
- arr.elements = (arr.elements ?? []).filter((e) => !isEmptyStyleRef(e));
33667
- if (arr.elements.length !== originalLength) changed = true;
33668
- }
33669
- if (isEmptyStyleRef(firstArg)) {
33670
- call.arguments[0] = j.identifier("undefined");
33671
- changed = true;
33672
- }
33673
- }
33674
- });
33675
- root.find(j.JSXAttribute, { name: { name: "sx" } }).forEach((p) => {
33676
- const val = p.node.value;
33677
- if (!val || val.type !== "JSXExpressionContainer") return;
33678
- const expr = val.expression;
33679
- if (expr?.type === "ArrayExpression") {
33680
- const orig = (expr.elements ?? []).length;
33681
- expr.elements = (expr.elements ?? []).filter((e) => !isEmptyStyleRef(e));
33682
- if (expr.elements.length !== orig) changed = true;
33683
- if (expr.elements.length === 1) {
33684
- val.expression = expr.elements[0];
33685
- changed = true;
33686
- }
33687
- if (expr.elements.length === 0) {
33688
- const opening = p.parentPath?.node;
33689
- if (opening?.type === "JSXOpeningElement" && Array.isArray(opening.attributes)) {
33690
- opening.attributes = opening.attributes.filter((attr) => attr !== p.node);
33691
- changed = true;
33692
- }
33693
- }
33694
- } else if (isEmptyStyleRef(expr)) {
33695
- const opening = p.parentPath?.node;
33696
- if (opening?.type === "JSXOpeningElement" && Array.isArray(opening.attributes)) {
33697
- opening.attributes = opening.attributes.filter((attr) => attr !== p.node);
33698
- changed = true;
33699
- }
33700
- }
33701
- });
33702
- }
33703
- root.find(j.ImportDeclaration, { source: { value: "@emotion/is-prop-valid" } }).forEach((p) => {
33704
- const spec = p.node.specifiers?.find((s) => s.type === "ImportDefaultSpecifier");
33705
- const local = spec?.local?.type === "Identifier" ? spec.local.name : null;
33706
- if (!local) return;
33707
- if (!(root.find(j.Identifier, { name: local }).filter((idPath) => j(idPath).closest(j.ImportDeclaration).size() === 0).size() > 0)) {
33708
- j(p).remove();
33709
- changed = true;
33710
- }
33711
- });
33712
- root.find(j.ImportDeclaration).forEach((p) => {
33713
- if (preserveReactImport && (p.node?.source)?.value === "react") {
33714
- if ((p.node.specifiers ?? []).some((s) => (s.type === "ImportDefaultSpecifier" || s.type === "ImportNamespaceSpecifier") && s.local?.type === "Identifier" && s.local.name === "React")) return;
33715
- }
33716
- const specs = p.node.specifiers ?? [];
33717
- if (specs.length === 0) return;
33718
- const usedOutsideImports = (localName, importLocalNode) => {
33719
- const isProbablyJsxBindingName = (name) => {
33720
- const first = name[0] ?? "";
33721
- return first.toUpperCase() === first && first.toLowerCase() !== first;
33722
- };
33723
- const resolvesToImportBinding = (idPath) => {
33724
- try {
33725
- const bindings = (idPath.scope?.lookup?.(localName))?.getBindings?.()?.[localName];
33726
- if (!Array.isArray(bindings)) return true;
33727
- return bindings.some((bindingPath) => bindingPath?.node === importLocalNode);
33728
- } catch {
33729
- return true;
33730
- }
33731
- };
33732
- const usedByIdentifier = root.find(j.Identifier, { name: localName }).filter((idPath) => {
33733
- if (j(idPath).closest(j.ImportDeclaration).size() > 0) return false;
33734
- const parent = idPath.parent?.node;
33735
- if (parent && isMemberExpression(parent) && parent.property === idPath.node && parent.computed === false) return false;
33736
- if (parent && parent.type === "Property" && parent.key === idPath.node && parent.shorthand !== true) return false;
33737
- if (parent?.type === "TSPropertySignature" && parent.key === idPath.node) return false;
33738
- if (parent?.type === "JSXAttribute" && parent.name === idPath.node) return false;
33739
- return resolvesToImportBinding(idPath);
33740
- }).size() > 0;
33741
- const usedByJsxIdentifier = isProbablyJsxBindingName(localName) && root.find(j.JSXIdentifier, { name: localName }).filter((jsxPath) => {
33742
- if (j(jsxPath).closest(j.ImportDeclaration).size() > 0) return false;
33743
- return true;
33744
- }).size() > 0;
33745
- return usedByIdentifier || usedByJsxIdentifier;
33746
- };
33747
- if (p.node.importKind === "type") return;
33748
- const nextSpecs = specs.filter((s) => {
33749
- if (s?.importKind === "type") return true;
33750
- const local = s?.local?.type === "Identifier" ? s.local.name : s?.type === "ImportDefaultSpecifier" && s.local?.type === "Identifier" ? s.local.name : s?.type === "ImportNamespaceSpecifier" && s.local?.type === "Identifier" ? s.local.name : null;
33751
- if (!local) return true;
33752
- if (newImportLocalNames?.has(local)) {
33753
- const sourceValue = (p.node?.source)?.value;
33754
- const allowedSources = newImportSourcesByLocal?.get(local);
33755
- if (!allowedSources || !allowedSources.has(sourceValue)) return false;
33756
- }
33757
- return usedOutsideImports(local, s.local?.type === "Identifier" ? s.local : null);
33758
- });
33759
- if (nextSpecs.length !== specs.length) {
33760
- p.node.specifiers = nextSpecs;
33761
- changed = true;
33762
- }
33763
- if ((p.node.specifiers?.length ?? 0) === 0) {
33764
- j(p).remove();
33765
- changed = true;
33766
- }
34849
+ if (cleanupEmptyStyleReferences({
34850
+ root,
34851
+ j,
34852
+ emptyStyleKeys,
34853
+ stylesIdentifier
34854
+ })) changed = true;
34855
+ const importCleanup = cleanupPostProcessImports({
34856
+ root,
34857
+ j,
34858
+ preserveReactImport,
34859
+ newImportLocalNames,
34860
+ newImportSourcesByLocal
33767
34861
  });
33768
- const hasReactImport = root.find(j.ImportDeclaration).filter((p) => (p.node?.source)?.value === "react").filter((p) => (p.node.specifiers ?? []).some((s) => (s.type === "ImportDefaultSpecifier" || s.type === "ImportNamespaceSpecifier") && s.local?.type === "Identifier" && s.local.name === "React")).size() > 0;
33769
- const usesReactIdent = root.find(j.Identifier, { name: "React" }).size() > 0;
34862
+ if (importCleanup.changed) changed = true;
33770
34863
  return {
33771
34864
  changed,
33772
- needsReactImport: usesReactIdent && !hasReactImport
34865
+ needsReactImport: importCleanup.needsReactImport
33773
34866
  };
33774
34867
  }
33775
34868
  /** Extracts style key names referenced in a stylex.props() call or sx attribute. */
33776
34869
  function getUsedStyleKeys(call, sxAttr, stylesIdentifier) {
33777
34870
  const keys = [];
33778
34871
  const extractKey = (node) => {
33779
- if (node?.type === "MemberExpression" && node.object?.type === "Identifier" && node.object.name === stylesIdentifier && node.property?.type === "Identifier") keys.push(node.property.name);
34872
+ const propertyName = getIdentifierMemberPropertyName(node, stylesIdentifier);
34873
+ if (propertyName) keys.push(propertyName);
33780
34874
  if (node?.type === "CallExpression") extractKey(node.callee);
33781
34875
  };
33782
34876
  if (call) for (const arg of call.arguments ?? []) extractKey(arg);
@@ -33803,6 +34897,27 @@ function appendToMapList(map, key, value) {
33803
34897
  if (list) list.push(value);
33804
34898
  else map.set(key, [value]);
33805
34899
  }
34900
+ function getLocalElementTargetId(opening, _elementName, originalStyledName) {
34901
+ if (!opening?.name) return null;
34902
+ if (originalStyledName) return `styled:${originalStyledName}`;
34903
+ if (opening.name.type === "JSXIdentifier" && /^[a-z]/.test(opening.name.name)) return `intrinsic:${opening.name.name}`;
34904
+ return null;
34905
+ }
34906
+ function resolveLocalElementTargetForNode(args) {
34907
+ const { targetId, override, attrs, opening, componentNameToDecl, hasStyleKeyInAttrs } = args;
34908
+ if (targetId && override.styleKeysByTargetId?.[targetId]) return targetId;
34909
+ for (const candidateId of Object.keys(override.styleKeysByTargetId ?? {})) {
34910
+ if (!candidateId.startsWith("styled:")) continue;
34911
+ const localName = candidateId.slice(7);
34912
+ const decl = componentNameToDecl.get(localName);
34913
+ if (decl && hasStyleKeyInAttrs(attrs, decl.styleKey)) return candidateId;
34914
+ }
34915
+ if (opening?.name?.type === "JSXIdentifier" && /^[a-z]/.test(opening.name.name)) {
34916
+ const intrinsicId = `intrinsic:${opening.name.name}`;
34917
+ if (override.styleKeysByTargetId?.[intrinsicId]) return intrinsicId;
34918
+ }
34919
+ return null;
34920
+ }
33806
34921
  //#endregion
33807
34922
  //#region src/internal/transform-steps/post-process.ts
33808
34923
  /**
@@ -33817,20 +34932,7 @@ function postProcessStep(ctx) {
33817
34932
  const allStyledDecls = ctx.styledDecls;
33818
34933
  if (!allStyledDecls) return CONTINUE;
33819
34934
  const styledDecls = getActiveStyledDecls(allStyledDecls) ?? [];
33820
- const newImportLocalNames = /* @__PURE__ */ new Set();
33821
- const newImportSourcesByLocal = /* @__PURE__ */ new Map();
33822
- for (const imp of ctx.resolverImports.values()) {
33823
- const source = importSourceToModuleSpecifier(imp.from, String(file.path));
33824
- for (const n of imp.names ?? []) {
33825
- const local = n.local ?? n.imported;
33826
- if (local) {
33827
- newImportLocalNames.add(local);
33828
- const sources = newImportSourcesByLocal.get(local) ?? /* @__PURE__ */ new Set();
33829
- sources.add(source);
33830
- newImportSourcesByLocal.set(local, sources);
33831
- }
33832
- }
33833
- }
34935
+ const { newImportLocalNames, newImportSourcesByLocal } = collectNewImportMetadata(ctx.resolverImports, String(file.path));
33834
34936
  ctx.newImportLocalNames = newImportLocalNames;
33835
34937
  ctx.newImportSourcesByLocal = newImportSourcesByLocal;
33836
34938
  const componentNameToStyleKey = /* @__PURE__ */ new Map();
@@ -33840,6 +34942,7 @@ function postProcessStep(ctx) {
33840
34942
  j,
33841
34943
  relationOverrides: ctx.relationOverrides ?? [],
33842
34944
  ancestorSelectorParents: ctx.ancestorSelectorParents ?? /* @__PURE__ */ new Set(),
34945
+ localElementOverridesByParent: new Map(styledDecls.filter((decl) => decl.localElementOverrides?.length).map((decl) => [decl.styleKey, decl.localElementOverrides ?? []])),
33843
34946
  componentNameToStyleKey,
33844
34947
  emptyStyleKeys: ctx.emptyStyleKeys ?? /* @__PURE__ */ new Set(),
33845
34948
  preserveReactImport: ctx.preserveReactImport,
@@ -33852,17 +34955,7 @@ function postProcessStep(ctx) {
33852
34955
  });
33853
34956
  if (post.changed) ctx.markChanged();
33854
34957
  ctx.needsReactImport = post.needsReactImport;
33855
- for (const decl of styledDecls) for (const helperName of decl.consumedLocalHelpers ?? []) {
33856
- const fnPaths = root.find(j.FunctionDeclaration, { id: { name: helperName } });
33857
- if (fnPaths.size() === 0) continue;
33858
- if (fnPaths.some((p) => p.parentPath?.node?.type === "ExportNamedDeclaration" || p.parentPath?.node?.type === "ExportDefaultDeclaration")) continue;
33859
- if (root.find(j.Identifier, { name: helperName }).filter((idPath) => {
33860
- const parent = idPath.parentPath?.node;
33861
- if (parent?.type === "FunctionDeclaration" && parent.id === idPath.node) return false;
33862
- return true;
33863
- }).size() === 0) fnPaths.forEach((p) => p.prune());
33864
- }
33865
- if (/\.(ts|tsx)$/.test(file.path)) {}
34958
+ cleanupConsumedLocalHelpers(ctx, styledDecls);
33866
34959
  return CONTINUE;
33867
34960
  }
33868
34961
  //#endregion
@@ -33919,6 +35012,25 @@ function reinsertStaticPropsStep(ctx) {
33919
35012
  return CONTINUE;
33920
35013
  }
33921
35014
  //#endregion
35015
+ //#region src/internal/utilities/jsx-children.ts
35016
+ function findContainingJsxChildrenOwner(path) {
35017
+ const currentNode = path.node;
35018
+ let cursor = path.parentPath;
35019
+ while (cursor) {
35020
+ const candidate = cursor.node;
35021
+ if (candidate && (candidate.type === "JSXElement" || candidate.type === "JSXFragment") && Array.isArray(candidate.children) && candidate.children.includes(currentNode)) return candidate;
35022
+ cursor = cursor.parentPath;
35023
+ }
35024
+ }
35025
+ function isJsxTextChild(child) {
35026
+ return typeof child === "object" && child !== null && child.type === "JSXText" && typeof child.value === "string";
35027
+ }
35028
+ function isJsxEmptyExpressionContainer(child) {
35029
+ if (typeof child !== "object" || child === null) return false;
35030
+ const maybeExpression = child;
35031
+ return maybeExpression.type === "JSXExpressionContainer" && maybeExpression.expression?.type === "JSXEmptyExpression";
35032
+ }
35033
+ //#endregion
33922
35034
  //#region src/internal/transform-steps/rewrite-jsx.ts
33923
35035
  /**
33924
35036
  * Step: rewrite JSX usage and remove unused styled declarations.
@@ -33988,7 +35100,7 @@ function rewriteJsxStep(ctx) {
33988
35100
  }
33989
35101
  const closing = p.node.closingElement;
33990
35102
  opening.__styledComponentLocalName = decl.localName;
33991
- let finalTag = decl.base.kind === "intrinsic" ? decl.base.tagName : decl.base.ident;
35103
+ let finalTag = decl.attrsInfo?.attrsAsTag ?? (decl.base.kind === "intrinsic" ? decl.base.tagName : decl.base.ident);
33992
35104
  const inlineVariantDimensions = decl.inlinedBaseComponent?.hasInlineJsxVariants ? decl.variantDimensions ?? [] : [];
33993
35105
  const inlineVariantByProp = new Map(inlineVariantDimensions.map((dimension) => [dimension.propName, dimension]));
33994
35106
  const inlineVariantProps = new Set(inlineVariantDimensions.map((dimension) => dimension.propName));
@@ -34006,10 +35118,9 @@ function rewriteJsxStep(ctx) {
34006
35118
  }
34007
35119
  const createJsxName = (tag) => {
34008
35120
  if (tag.includes(".")) {
34009
- const parts = tag.split(".");
34010
- const firstPart = parts[0];
34011
- if (!firstPart) return j.jsxIdentifier(tag);
34012
- return j.jsxMemberExpression(j.jsxIdentifier(firstPart), j.jsxIdentifier(parts.slice(1).join(".")));
35121
+ const [firstPart, ...memberParts] = tag.split(".");
35122
+ if (!firstPart || memberParts.length === 0) return j.jsxIdentifier(tag);
35123
+ return memberParts.reduce((object, member) => j.jsxMemberExpression(object, j.jsxIdentifier(member)), j.jsxIdentifier(firstPart));
34013
35124
  }
34014
35125
  return j.jsxIdentifier(tag);
34015
35126
  };
@@ -34041,7 +35152,7 @@ function rewriteJsxStep(ctx) {
34041
35152
  return true;
34042
35153
  });
34043
35154
  if (decl.attrsInfo) {
34044
- const { staticAttrs, conditionalAttrs, invertedBoolAttrs } = decl.attrsInfo;
35155
+ const { staticAttrs, dynamicAttrs, conditionalAttrs, invertedBoolAttrs, attrsStaticStyleExpr } = decl.attrsInfo;
34045
35156
  const hasAttr = (name) => keptAttrs.some((a) => a.type === "JSXAttribute" && a.name.type === "JSXIdentifier" && a.name.name === name);
34046
35157
  for (const cond of conditionalAttrs) {
34047
35158
  const idx = keptAttrs.findIndex((a) => a.type === "JSXAttribute" && a.name.type === "JSXIdentifier" && a.name.name === cond.jsxProp);
@@ -34063,11 +35174,31 @@ function rewriteJsxStep(ctx) {
34063
35174
  if (!hasAttr(inv.attrName)) keptAttrs.unshift(j.jsxAttribute(j.jsxIdentifier(inv.attrName), j.jsxExpressionContainer(j.literal(!isTrue))));
34064
35175
  } else if (!hasAttr(inv.attrName)) keptAttrs.unshift(j.jsxAttribute(j.jsxIdentifier(inv.attrName), j.jsxExpressionContainer(j.literal(true))));
34065
35176
  }
35177
+ for (const dyn of dynamicAttrs ?? []) {
35178
+ const idx = keptAttrs.findIndex((a) => a.type === "JSXAttribute" && a.name.type === "JSXIdentifier" && a.name.name === dyn.jsxProp);
35179
+ if (idx !== -1) {
35180
+ const propAttr = keptAttrs[idx];
35181
+ const valueExpr = extractJsxAttrValueExpr(j, propAttr);
35182
+ if (valueExpr) {
35183
+ removeJsxAttrsByName(keptAttrs, dyn.attrName);
35184
+ keptAttrs.unshift(j.jsxAttribute(j.jsxIdentifier(dyn.attrName), j.jsxExpressionContainer(dyn.defaultValue === void 0 ? valueExpr : j.conditionalExpression(j.binaryExpression("===", valueExpr, j.identifier("undefined")), literalExprForDynamicAttrDefault(j, dyn.defaultValue), valueExpr))));
35185
+ }
35186
+ } else if (dyn.defaultValue !== void 0) {
35187
+ removeJsxAttrsByName(keptAttrs, dyn.attrName);
35188
+ keptAttrs.unshift(j.jsxAttribute(j.jsxIdentifier(dyn.attrName), j.jsxExpressionContainer(literalExprForDynamicAttrDefault(j, dyn.defaultValue))));
35189
+ }
35190
+ }
34066
35191
  for (const [k, v] of Object.entries(staticAttrs)) {
35192
+ if (k === "className") continue;
34067
35193
  if (hasAttr(k)) continue;
34068
- const valNode = typeof v === "string" ? j.literal(v) : typeof v === "number" || typeof v === "boolean" ? j.jsxExpressionContainer(j.literal(v)) : v === void 0 ? j.jsxExpressionContainer(j.identifier("undefined")) : v === null ? j.jsxExpressionContainer(j.literal(null)) : j.literal(String(v));
34069
- keptAttrs.unshift(j.jsxAttribute(j.jsxIdentifier(k), valNode));
35194
+ const attr = buildStaticAttrFromValue(j, k, v, { booleanTrueAsShorthand: false });
35195
+ if (attr) keptAttrs.unshift(attr);
35196
+ }
35197
+ if (staticAttrs.className !== void 0) {
35198
+ const attr = buildStaticAttrFromValue(j, "className", staticAttrs.className, { booleanTrueAsShorthand: false });
35199
+ if (attr) keptAttrs.unshift(attr);
34070
35200
  }
35201
+ if (attrsStaticStyleExpr) keptAttrs.unshift(j.jsxAttribute(j.jsxIdentifier("style"), j.jsxExpressionContainer(cloneAstNode(attrsStaticStyleExpr))));
34071
35202
  }
34072
35203
  const leading = [];
34073
35204
  const rest = [];
@@ -34078,11 +35209,15 @@ function rewriteJsxStep(ctx) {
34078
35209
  let seenSpread = false;
34079
35210
  for (const attr of keptAttrs) if (attr.type === "JSXAttribute" && attr.name.type === "JSXIdentifier" && attr.name.name === "style") {
34080
35211
  hasCallerStyleAttr = true;
34081
- if (staticInlineStyleExpr) {
34082
- const callerStyleExpr = extractJsxAttrValueExpr(j, attr);
34083
- styleAttr = j.jsxAttribute(j.jsxIdentifier("style"), j.jsxExpressionContainer(callerStyleExpr ? j.objectExpression([j.spreadElement(staticInlineStyleExpr), j.spreadElement(callerStyleExpr)]) : staticInlineStyleExpr));
34084
- } else styleAttr = attr;
34085
- } else if (attr.type === "JSXAttribute" && attr.name.type === "JSXIdentifier" && attr.name.name === "className") classNameAttr = attr;
35212
+ const callerStyleExpr = extractJsxAttrValueExpr(j, attr);
35213
+ const existingStyleExpr = extractJsxAttrValueExpr(j, styleAttr);
35214
+ if (existingStyleExpr || staticInlineStyleExpr) styleAttr = j.jsxAttribute(j.jsxIdentifier("style"), j.jsxExpressionContainer(callerStyleExpr ? j.objectExpression([
35215
+ ...staticInlineStyleExpr ? [j.spreadElement(staticInlineStyleExpr)] : [],
35216
+ ...existingStyleExpr ? [j.spreadElement(existingStyleExpr)] : [],
35217
+ j.spreadElement(callerStyleExpr)
35218
+ ]) : existingStyleExpr ?? staticInlineStyleExpr));
35219
+ else styleAttr = attr;
35220
+ } else if (attr.type === "JSXAttribute" && attr.name.type === "JSXIdentifier" && attr.name.name === "className") classNameAttr = mergeClassNameAttrs(j, classNameAttr, attr);
34086
35221
  else if (attr.type === "JSXAttribute" && attr.name.type === "JSXIdentifier" && attr.name.name === "sx") sxAttr = attr;
34087
35222
  else if (attr.type === "JSXSpreadAttribute") {
34088
35223
  rest.push(attr);
@@ -34260,6 +35395,7 @@ function rewriteJsxStep(ctx) {
34260
35395
  styleArgs.push(j.logicalExpression("&&", promotedConditionalVariant.conditionExpr, j.memberExpression(j.identifier(stylesId), j.identifier(promotedConditionalVariant.styleKey))));
34261
35396
  }
34262
35397
  const extraClassNameExpr = decl.extraClassNames && decl.extraClassNames.length > 0 ? buildExtraClassNameExpr(j, decl.extraClassNames) : void 0;
35398
+ if (!styleAttr && decl.attrsInfo?.attrsStaticStyleExpr) styleAttr = j.jsxAttribute(j.jsxIdentifier("style"), j.jsxExpressionContainer(cloneAstNode(decl.attrsInfo.attrsStaticStyleExpr)));
34263
35399
  if (staticInlineStyleExpr && !styleAttr) styleAttr = j.jsxAttribute(j.jsxIdentifier("style"), j.jsxExpressionContainer(staticInlineStyleExpr));
34264
35400
  const wrappedAcceptsSxProp = !isIntrinsicTag && isWrappedComponentSxAware({
34265
35401
  adapter: ctx.adapter,
@@ -34270,7 +35406,10 @@ function rewriteJsxStep(ctx) {
34270
35406
  sourceOverrides: ctx.options.transformedFileSources
34271
35407
  });
34272
35408
  let effectiveClassNameAttr = classNameAttr;
34273
- if (extraClassNameExpr && !ctx.adapter.useSxProp) effectiveClassNameAttr = j.jsxAttribute(j.jsxIdentifier("className"), j.jsxExpressionContainer(extraClassNameExpr));
35409
+ if (extraClassNameExpr && !ctx.adapter.useSxProp) {
35410
+ const extraClassNameAttr = j.jsxAttribute(j.jsxIdentifier("className"), j.jsxExpressionContainer(extraClassNameExpr));
35411
+ effectiveClassNameAttr = effectiveClassNameAttr ? mergeClassNameAttrs(j, effectiveClassNameAttr, extraClassNameAttr) : extraClassNameAttr;
35412
+ }
34274
35413
  const hasRestSpreadAttr = keptRestAfterVariants.some((attr) => attr.type === "JSXSpreadAttribute");
34275
35414
  const needsMerge = effectiveClassNameAttr !== null || styleAttr !== null && !(staticInlineStyleExpr !== null && styleAttr !== null && effectiveClassNameAttr === null && !hasCallerStyleAttr && !hasRestSpreadAttr);
34276
35415
  const stylesId = ctx.stylesIdentifier ?? "styles";
@@ -34302,6 +35441,7 @@ function rewriteJsxStep(ctx) {
34302
35441
  ...finalRest,
34303
35442
  ...styleAttr && !needsMerge && !useSxPropForWrapped ? [styleAttr] : []
34304
35443
  ];
35444
+ preserveInlineJsxTextWhitespace(ctx, p, styledDecls);
34305
35445
  });
34306
35446
  }
34307
35447
  return CONTINUE;
@@ -34330,14 +35470,36 @@ function buildInlineMergeCall(j, styleArgs, classNameAttr, styleAttr, styleMerge
34330
35470
  ]);
34331
35471
  return buildInlineVerboseMergeFallback(j, stylesArg, classNameExpr, styleExpr);
34332
35472
  }
35473
+ function mergeClassNameAttrs(j, first, second) {
35474
+ const parts = [extractJsxAttrValueExpr(j, first), extractJsxAttrValueExpr(j, second)].filter((expr) => !!expr);
35475
+ const expr = parts.length === 1 ? parts[0] : buildClassNameJoinExpr(j, parts);
35476
+ return j.jsxAttribute(j.jsxIdentifier("className"), j.jsxExpressionContainer(expr));
35477
+ }
35478
+ function removeJsxAttrsByName(attrs, name) {
35479
+ for (let i = attrs.length - 1; i >= 0; i--) {
35480
+ const attr = attrs[i];
35481
+ if (attr?.type === "JSXAttribute" && attr.name?.type === "JSXIdentifier" && attr.name.name === name) attrs.splice(i, 1);
35482
+ }
35483
+ }
35484
+ function literalExprForDynamicAttrDefault(j, value) {
35485
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") return j.literal(value);
35486
+ if (value === null) return j.literal(null);
35487
+ return j.identifier("undefined");
35488
+ }
34333
35489
  function buildInlineVerboseMergeFallback(j, stylesArg, classNameExpr, styleExpr) {
34334
35490
  const sxIdentifier = j.identifier("sx");
34335
35491
  const sxClassName = j.memberExpression(sxIdentifier, j.identifier("className"));
34336
35492
  const sxStyle = j.memberExpression(sxIdentifier, j.identifier("style"));
34337
- const classNameValue = classNameExpr ? j.callExpression(j.memberExpression(j.callExpression(j.memberExpression(j.arrayExpression([sxClassName, classNameExpr]), j.identifier("filter")), [j.identifier("Boolean")]), j.identifier("join")), [j.literal(" ")]) : sxClassName;
35493
+ const classNameValue = classNameExpr ? j.callExpression(j.memberExpression(j.callExpression(j.memberExpression(j.arrayExpression([sxClassName, ...flattenClassNameExpr(classNameExpr)]), j.identifier("filter")), [j.identifier("Boolean")]), j.identifier("join")), [j.literal(" ")]) : sxClassName;
34338
35494
  const styleValue = styleExpr ? j.conditionalExpression(sxStyle, j.objectExpression([j.spreadElement(sxStyle), j.spreadElement(styleExpr)]), styleExpr) : sxStyle;
34339
35495
  return j.callExpression(j.arrowFunctionExpression([], j.blockStatement([j.variableDeclaration("const", [j.variableDeclarator(sxIdentifier, j.callExpression(j.memberExpression(j.identifier("stylex"), j.identifier("props")), [stylesArg]))]), j.returnStatement(j.objectExpression([j.property("init", j.identifier("className"), classNameValue), j.property("init", j.identifier("style"), styleValue)]))])), []);
34340
35496
  }
35497
+ function flattenClassNameExpr(classNameExpr) {
35498
+ return classNameExpr.type === "ArrayExpression" && classNameExpr.elements.every((element) => !!element) ? [...classNameExpr.elements] : [classNameExpr];
35499
+ }
35500
+ function buildClassNameJoinExpr(j, parts) {
35501
+ return j.callExpression(j.memberExpression(j.callExpression(j.memberExpression(j.arrayExpression(parts), j.identifier("filter")), [j.identifier("Boolean")]), j.identifier("join")), [j.literal(" ")]);
35502
+ }
34341
35503
  /** Extracts the value expression from a JSX attribute node. */
34342
35504
  function extractJsxAttrValueExpr(j, attr) {
34343
35505
  if (!attr) return;
@@ -34348,16 +35510,7 @@ function extractJsxAttrValueExpr(j, attr) {
34348
35510
  }
34349
35511
  function hasPreviousStaticSiblingWithName(path, componentName) {
34350
35512
  const currentNode = path.node;
34351
- let cursor = path.parentPath;
34352
- let parentNode;
34353
- while (cursor) {
34354
- const candidate = cursor.node;
34355
- if (candidate && (candidate.type === "JSXElement" || candidate.type === "JSXFragment") && Array.isArray(candidate.children) && candidate.children.includes(currentNode)) {
34356
- parentNode = candidate;
34357
- break;
34358
- }
34359
- cursor = cursor.parentPath;
34360
- }
35513
+ const parentNode = findContainingJsxChildrenOwner(path);
34361
35514
  if (!parentNode?.children) return false;
34362
35515
  const siblings = parentNode.children;
34363
35516
  const currentIndex = siblings.indexOf(currentNode);
@@ -34382,6 +35535,83 @@ function hasPreviousStaticSiblingWithName(path, componentName) {
34382
35535
  }
34383
35536
  return false;
34384
35537
  }
35538
+ function preserveInlineJsxTextWhitespace(ctx, path, styledDecls) {
35539
+ const { j } = ctx;
35540
+ const parentNode = findContainingJsxChildrenOwner(path);
35541
+ const children = parentNode?.children;
35542
+ if (!children || isCustomComponentJsxElement(ctx, parentNode, styledDecls)) return;
35543
+ for (let i = 0; i < children.length; i++) {
35544
+ const child = children[i];
35545
+ if (!isJsxTextChild(child)) continue;
35546
+ if (!child.value.trim()) {
35547
+ if (/^[ \t]+$/.test(child.value) && hasRenderableJsxSibling(children, i - 1, -1) && hasRenderableJsxSibling(children, i + 1, 1)) children.splice(i, 1, createJsxSpaceExpression(j, child.value));
35548
+ continue;
35549
+ }
35550
+ const leading = child.value.match(/^[ \t]+(?=\S)/)?.[0];
35551
+ if (leading && hasRenderableJsxSibling(children, i - 1, -1)) {
35552
+ child.value = child.value.slice(leading.length);
35553
+ children.splice(i, 0, createJsxSpaceExpression(j, leading));
35554
+ i++;
35555
+ }
35556
+ const trailing = child.value.match(/\S([ \t]+)$/)?.[1];
35557
+ if (trailing && hasRenderableJsxSibling(children, i + 1, 1)) {
35558
+ child.value = child.value.slice(0, -trailing.length);
35559
+ children.splice(i + 1, 0, createJsxSpaceExpression(j, trailing));
35560
+ i++;
35561
+ }
35562
+ }
35563
+ }
35564
+ function isCustomComponentJsxElement(ctx, parentNode, styledDecls) {
35565
+ const parentName = parentNode.openingElement?.name;
35566
+ if (isReactFragmentJsxName(ctx, parentName)) return false;
35567
+ if (isInlineStyledParent(parentName, styledDecls)) return false;
35568
+ if (isCustomElementJsxName(parentName)) return true;
35569
+ if (isJsxIdentifierName(parentName)) return !parentName.name || !/^[a-z]/.test(parentName.name);
35570
+ return parentNode.type === "JSXElement";
35571
+ }
35572
+ function isInlineStyledParent(name, styledDecls) {
35573
+ if (!isJsxIdentifierName(name)) return false;
35574
+ return styledDecls.some((decl) => decl.localName === name.name && decl.base.kind === "intrinsic" && !decl.skipTransform && !decl.needsWrapperComponent && !decl.isCssHelper);
35575
+ }
35576
+ function isReactFragmentJsxName(ctx, name) {
35577
+ if (isJsxIdentifierName(name)) {
35578
+ const importInfo = ctx.importMap?.get(name.name);
35579
+ return importInfo?.importedName === "Fragment" && isReactImportSource(importInfo.source);
35580
+ }
35581
+ if (!isJsxMemberExpressionName(name)) return false;
35582
+ return isJsxIdentifierName(name.object) && isReactNamespaceBinding(ctx, name.object.name) && isJsxIdentifierName(name.property) && name.property.name === "Fragment";
35583
+ }
35584
+ function isReactImportSource(source) {
35585
+ return typeof source === "object" && source !== null && source.kind === "specifier" && source.value === "react";
35586
+ }
35587
+ function isReactNamespaceBinding(ctx, localName) {
35588
+ const { root, j } = ctx;
35589
+ return root.find(j.ImportDeclaration).filter((path) => path.node.source?.value === "react").filter((path) => (path.node.specifiers ?? []).some((specifier) => (specifier.type === "ImportDefaultSpecifier" || specifier.type === "ImportNamespaceSpecifier") && specifier.local?.type === "Identifier" && specifier.local.name === localName)).size() > 0;
35590
+ }
35591
+ function isCustomElementJsxName(name) {
35592
+ return isJsxIdentifierName(name) && name.name.includes("-");
35593
+ }
35594
+ function isJsxIdentifierName(name) {
35595
+ return typeof name === "object" && name !== null && name.type === "JSXIdentifier" && typeof name.name === "string";
35596
+ }
35597
+ function isJsxMemberExpressionName(name) {
35598
+ return typeof name === "object" && name !== null && name.type === "JSXMemberExpression";
35599
+ }
35600
+ function hasRenderableJsxSibling(children, startIndex, step) {
35601
+ for (let i = startIndex; i >= 0 && i < children.length; i += step) {
35602
+ const sibling = children[i];
35603
+ if (isJsxTextChild(sibling)) {
35604
+ if (sibling.value.trim()) return true;
35605
+ continue;
35606
+ }
35607
+ if (isJsxEmptyExpressionContainer(sibling)) continue;
35608
+ if (sibling) return true;
35609
+ }
35610
+ return false;
35611
+ }
35612
+ function createJsxSpaceExpression(j, value) {
35613
+ return j.jsxExpressionContainer(j.literal(value));
35614
+ }
34385
35615
  /**
34386
35616
  * Builds a single expression from extra className entries (CSS module classes).
34387
35617
  * Single entry: returns the expression directly.