styled-components-to-stylex-codemod 0.0.29 → 0.0.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +6 -1
- package/dist/index.mjs +1 -1
- package/dist/{logger-Dx-dRi_p.d.mts → logger-BQnWs1On.d.mts} +29 -1
- package/dist/transform.d.mts +1 -1
- package/dist/transform.mjs +222 -63
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as defineAdapter, i as AdapterInput, t as CollectedWarning } from "./logger-
|
|
1
|
+
import { a as defineAdapter, i as AdapterInput, t as CollectedWarning } from "./logger-BQnWs1On.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/run.d.ts
|
|
4
4
|
interface RunTransformOptions {
|
|
@@ -59,6 +59,11 @@ interface RunTransformOptions {
|
|
|
59
59
|
* @default 3
|
|
60
60
|
*/
|
|
61
61
|
maxExamples?: number;
|
|
62
|
+
/**
|
|
63
|
+
* Suppress jscodeshift runner output.
|
|
64
|
+
* @default false
|
|
65
|
+
*/
|
|
66
|
+
silent?: boolean;
|
|
62
67
|
}
|
|
63
68
|
interface RunTransformResult {
|
|
64
69
|
/** Number of files that had errors */
|
package/dist/index.mjs
CHANGED
|
@@ -231,7 +231,7 @@ async function runTransform(options) {
|
|
|
231
231
|
transformedFiles,
|
|
232
232
|
transientPropRenames,
|
|
233
233
|
runInBand: true,
|
|
234
|
-
silent:
|
|
234
|
+
silent: options.silent ?? false
|
|
235
235
|
});
|
|
236
236
|
if (sidecarFiles.size > 0 && !dryRun) for (const [sidecarPath, content] of sidecarFiles) await writeFile(sidecarPath, mergeSidecarContent(sidecarPath, content), "utf-8");
|
|
237
237
|
if (bridgeResults.size > 0 && !dryRun) {
|
|
@@ -260,6 +260,19 @@ type CallResolveResultWithExpr = {
|
|
|
260
260
|
* - Theme access in the original call is rewritten to use the wrapper `useTheme()` value.
|
|
261
261
|
*/
|
|
262
262
|
preserveRuntimeCall?: boolean;
|
|
263
|
+
/**
|
|
264
|
+
* Additional className expressions to merge into the component's className attribute.
|
|
265
|
+
*
|
|
266
|
+
* Used for CSS modules or other class-based styles that StyleX cannot express
|
|
267
|
+
* (child selectors like `& > *`, ancestor selectors like `html:not(.class) &`, etc.).
|
|
268
|
+
*
|
|
269
|
+
* Each entry provides an expression string (e.g., `cssModuleStyles.myClass`)
|
|
270
|
+
* and its required imports.
|
|
271
|
+
*
|
|
272
|
+
* When present, the codemod merges these expressions into the rendered element's
|
|
273
|
+
* className alongside any existing static className from `.attrs()` or bridge classes.
|
|
274
|
+
*/
|
|
275
|
+
extraClassNames?: ExprWithImports[];
|
|
263
276
|
};
|
|
264
277
|
type CallResolveRuntimeOnlyResult = {
|
|
265
278
|
/**
|
|
@@ -275,7 +288,17 @@ type CallResolveRuntimeOnlyResult = {
|
|
|
275
288
|
*/
|
|
276
289
|
usage?: "create";
|
|
277
290
|
};
|
|
278
|
-
|
|
291
|
+
/**
|
|
292
|
+
* Resolved result containing only className expressions (no StyleX style object).
|
|
293
|
+
* Used for CSS modules or other class-based styles that StyleX cannot express.
|
|
294
|
+
*/
|
|
295
|
+
type CallResolveClassNamesResult = {
|
|
296
|
+
/**
|
|
297
|
+
* className expressions to merge into the component's className attribute.
|
|
298
|
+
*/
|
|
299
|
+
extraClassNames: ExprWithImports[];
|
|
300
|
+
};
|
|
301
|
+
type CallResolveResult = CallResolveResultWithExpr | CallResolveRuntimeOnlyResult | CallResolveClassNamesResult;
|
|
279
302
|
type ImportSource = {
|
|
280
303
|
kind: "absolutePath";
|
|
281
304
|
value: string;
|
|
@@ -290,6 +313,11 @@ type ImportSpec = {
|
|
|
290
313
|
local?: string;
|
|
291
314
|
}>;
|
|
292
315
|
};
|
|
316
|
+
/** An expression string with its required imports, used for className emission. */
|
|
317
|
+
type ExprWithImports = {
|
|
318
|
+
expr: string;
|
|
319
|
+
imports: ImportSpec[];
|
|
320
|
+
};
|
|
293
321
|
type ResolveBaseComponentStaticValue = string | number | boolean;
|
|
294
322
|
interface ResolveBaseComponentContext {
|
|
295
323
|
/**
|
package/dist/transform.d.mts
CHANGED
package/dist/transform.mjs
CHANGED
|
@@ -2229,7 +2229,7 @@ function analyzeBeforeEmitStep(ctx) {
|
|
|
2229
2229
|
if (!hadWrapperBeforePrepass && decl.needsWrapperComponent) wrapperForcedByPrepass.add(decl.localName);
|
|
2230
2230
|
if (ctx.bridgeComponentNames?.has(decl.localName) || ctx.bridgeComponentNames?.has("default") && exportedComponents.get(decl.localName)?.isDefault) decl.bridgeClassName = generateBridgeClassName(resolve(file.path), decl.localName);
|
|
2231
2231
|
}
|
|
2232
|
-
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.needsWrapperComponent = false;
|
|
2232
|
+
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;
|
|
2233
2233
|
const jsxUsageCountCache = /* @__PURE__ */ new Map();
|
|
2234
2234
|
const relationChildStyleKeys = new Set((ctx.relationOverrides ?? []).map((o) => o.childStyleKey));
|
|
2235
2235
|
const getJsxUsageCount = (name) => {
|
|
@@ -3637,8 +3637,10 @@ function normalizeStylisAstToIR(stylisAst, slots, options = {}) {
|
|
|
3637
3637
|
const propsArr = Array.isArray(node.props) ? node.props : null;
|
|
3638
3638
|
const rule = ensureRule((() => {
|
|
3639
3639
|
if (!stripFormFeedInSelectors || !selectorValue.includes("\f") || !propsArr?.length) return selectorRaw;
|
|
3640
|
-
const
|
|
3641
|
-
|
|
3640
|
+
const resolved = propsArr.filter((p) => typeof p === "string").map((p) => `&${p}`).join(",");
|
|
3641
|
+
const hasSiblingCombinator = (s) => /[+~]/.test(s.replace(/\[[^\]]*\]/g, ""));
|
|
3642
|
+
if (hasSiblingCombinator(selectorRaw) || hasSiblingCombinator(resolved)) return selectorRaw;
|
|
3643
|
+
if (resolved.length > selectorRaw.length) return resolved;
|
|
3642
3644
|
return selectorRaw;
|
|
3643
3645
|
})(), atRuleStack);
|
|
3644
3646
|
const children = node.children;
|
|
@@ -9048,6 +9050,7 @@ function emitStylesAndImports(ctx) {
|
|
|
9048
9050
|
const moduleSpecifier = toModuleSpecifier(spec.from);
|
|
9049
9051
|
const existing = root.find(j.ImportDeclaration, { source: { value: moduleSpecifier } });
|
|
9050
9052
|
const toImportSpecifier = (imported, local) => {
|
|
9053
|
+
if (imported === "default") return j.importDefaultSpecifier(j.identifier(local ?? "default"));
|
|
9051
9054
|
const impId = j.identifier(imported);
|
|
9052
9055
|
if (local && local !== imported) return j.importSpecifier(impId, j.identifier(local));
|
|
9053
9056
|
return j.importSpecifier(impId);
|
|
@@ -10239,19 +10242,60 @@ function buildInterleavedExtraStyleArgs(j, stylesIdentifier, d, propsArgExprs) {
|
|
|
10239
10242
|
*
|
|
10240
10243
|
* Returns `undefined` when neither is provided.
|
|
10241
10244
|
*/
|
|
10242
|
-
|
|
10243
|
-
|
|
10244
|
-
|
|
10245
|
-
|
|
10246
|
-
|
|
10247
|
-
|
|
10248
|
-
|
|
10245
|
+
/** Escape characters that are special inside template literal quasi strings. */
|
|
10246
|
+
function escapeTemplateRaw(s) {
|
|
10247
|
+
return s.replace(/\\|`|\$\{/g, "\\$&");
|
|
10248
|
+
}
|
|
10249
|
+
function buildStaticClassNameExpr(j, staticClassName, bridgeClassVar, extraClassNames) {
|
|
10250
|
+
if (!(extraClassNames && extraClassNames.length > 0)) {
|
|
10251
|
+
if (staticClassName && bridgeClassVar) {
|
|
10252
|
+
const raw = escapeTemplateRaw(`${staticClassName} `);
|
|
10253
|
+
return j.templateLiteral([j.templateElement({
|
|
10254
|
+
raw,
|
|
10255
|
+
cooked: `${staticClassName} `
|
|
10256
|
+
}, false), j.templateElement({
|
|
10257
|
+
raw: "",
|
|
10258
|
+
cooked: ""
|
|
10259
|
+
}, true)], [j.identifier(bridgeClassVar)]);
|
|
10260
|
+
}
|
|
10261
|
+
if (bridgeClassVar) return j.identifier(bridgeClassVar);
|
|
10262
|
+
if (staticClassName) return j.literal(staticClassName);
|
|
10263
|
+
return;
|
|
10264
|
+
}
|
|
10265
|
+
const expressions = [];
|
|
10266
|
+
const quasis = [];
|
|
10267
|
+
const leadingText = staticClassName ? `${escapeTemplateRaw(staticClassName)} ` : "";
|
|
10268
|
+
quasis.push(j.templateElement({
|
|
10269
|
+
raw: leadingText,
|
|
10270
|
+
cooked: staticClassName ? `${staticClassName} ` : ""
|
|
10271
|
+
}, false));
|
|
10272
|
+
if (bridgeClassVar) {
|
|
10273
|
+
expressions.push(j.identifier(bridgeClassVar));
|
|
10274
|
+
quasis.push(j.templateElement({
|
|
10275
|
+
raw: " ",
|
|
10276
|
+
cooked: " "
|
|
10277
|
+
}, false));
|
|
10278
|
+
}
|
|
10279
|
+
for (let i = 0; i < extraClassNames.length; i++) {
|
|
10280
|
+
expressions.push(extraClassNames[i].expr);
|
|
10281
|
+
if (i === extraClassNames.length - 1) quasis.push(j.templateElement({
|
|
10249
10282
|
raw: "",
|
|
10250
10283
|
cooked: ""
|
|
10251
|
-
}, true)
|
|
10284
|
+
}, true));
|
|
10285
|
+
else quasis.push(j.templateElement({
|
|
10286
|
+
raw: " ",
|
|
10287
|
+
cooked: " "
|
|
10288
|
+
}, false));
|
|
10289
|
+
}
|
|
10290
|
+
if (expressions.length === 0) {
|
|
10291
|
+
if (staticClassName) return j.literal(staticClassName);
|
|
10292
|
+
return;
|
|
10252
10293
|
}
|
|
10253
|
-
if (bridgeClassVar)
|
|
10254
|
-
|
|
10294
|
+
if (!staticClassName && !bridgeClassVar) quasis[0] = j.templateElement({
|
|
10295
|
+
raw: "",
|
|
10296
|
+
cooked: ""
|
|
10297
|
+
}, false);
|
|
10298
|
+
return j.templateLiteral(quasis, expressions);
|
|
10255
10299
|
}
|
|
10256
10300
|
/**
|
|
10257
10301
|
* Extracts a static className value (if present) from attrsInfo.staticAttrs
|
|
@@ -10261,12 +10305,15 @@ function buildStaticClassNameExpr(j, staticClassName, bridgeClassVar) {
|
|
|
10261
10305
|
* When `bridgeClassVar` is provided, it is used as an identifier expression
|
|
10262
10306
|
* for the bridge class name. If a static className also exists, a template
|
|
10263
10307
|
* literal combining both is produced.
|
|
10308
|
+
*
|
|
10309
|
+
* When `extraClassNames` is provided, the expressions are merged into the
|
|
10310
|
+
* static className expression.
|
|
10264
10311
|
*/
|
|
10265
|
-
function splitAttrsInfo(j, attrsInfo, bridgeClassVar) {
|
|
10312
|
+
function splitAttrsInfo(j, attrsInfo, bridgeClassVar, extraClassNames) {
|
|
10266
10313
|
const className = attrsInfo?.staticAttrs?.className;
|
|
10267
10314
|
if (!attrsInfo) return {
|
|
10268
10315
|
attrsInfo,
|
|
10269
|
-
staticClassNameExpr: buildStaticClassNameExpr(j, void 0, bridgeClassVar)
|
|
10316
|
+
staticClassNameExpr: buildStaticClassNameExpr(j, void 0, bridgeClassVar, extraClassNames)
|
|
10270
10317
|
};
|
|
10271
10318
|
const normalized = {
|
|
10272
10319
|
...attrsInfo,
|
|
@@ -10274,7 +10321,8 @@ function splitAttrsInfo(j, attrsInfo, bridgeClassVar) {
|
|
|
10274
10321
|
conditionalAttrs: attrsInfo.conditionalAttrs ?? []
|
|
10275
10322
|
};
|
|
10276
10323
|
const hasStaticClassName = typeof className === "string";
|
|
10277
|
-
|
|
10324
|
+
const hasExtraClassNames = extraClassNames && extraClassNames.length > 0;
|
|
10325
|
+
if (!hasStaticClassName && !bridgeClassVar && !hasExtraClassNames) return {
|
|
10278
10326
|
attrsInfo: normalized,
|
|
10279
10327
|
staticClassNameExpr: void 0
|
|
10280
10328
|
};
|
|
@@ -10286,7 +10334,7 @@ function splitAttrsInfo(j, attrsInfo, bridgeClassVar) {
|
|
|
10286
10334
|
staticAttrs: rest
|
|
10287
10335
|
};
|
|
10288
10336
|
})() : normalized,
|
|
10289
|
-
staticClassNameExpr: buildStaticClassNameExpr(j, hasStaticClassName ? className : void 0, bridgeClassVar)
|
|
10337
|
+
staticClassNameExpr: buildStaticClassNameExpr(j, hasStaticClassName ? className : void 0, bridgeClassVar, extraClassNames)
|
|
10290
10338
|
};
|
|
10291
10339
|
}
|
|
10292
10340
|
/**
|
|
@@ -10590,10 +10638,6 @@ function buildVariantStyleExprs(opts) {
|
|
|
10590
10638
|
}), when);
|
|
10591
10639
|
}
|
|
10592
10640
|
}
|
|
10593
|
-
/** Escape characters that are special inside template literal quasi strings. */
|
|
10594
|
-
function escapeTemplateRaw(s) {
|
|
10595
|
-
return s.replace(/\\|`|\$\{/g, "\\$&");
|
|
10596
|
-
}
|
|
10597
10641
|
/**
|
|
10598
10642
|
* Appends conditional style args driven by theme boolean props (e.g., `theme.isDark`).
|
|
10599
10643
|
* Returns `true` if the hook is needed (and calls `markNeedsUseThemeImport`).
|
|
@@ -11611,8 +11655,8 @@ var WrapperEmitter = class {
|
|
|
11611
11655
|
buildInterleavedExtraStyleArgs(d, propsArgExprs) {
|
|
11612
11656
|
return buildInterleavedExtraStyleArgs(this.j, this.stylesIdentifier, d, propsArgExprs);
|
|
11613
11657
|
}
|
|
11614
|
-
splitAttrsInfo(attrsInfo, bridgeClassVar) {
|
|
11615
|
-
return splitAttrsInfo(this.j, attrsInfo, bridgeClassVar);
|
|
11658
|
+
splitAttrsInfo(attrsInfo, bridgeClassVar, extraClassNames) {
|
|
11659
|
+
return splitAttrsInfo(this.j, attrsInfo, bridgeClassVar, extraClassNames);
|
|
11616
11660
|
}
|
|
11617
11661
|
buildVariantDimensionLookups(args) {
|
|
11618
11662
|
buildVariantDimensionLookups(this.j, args);
|
|
@@ -12002,7 +12046,7 @@ function emitComponentWrappers(emitter) {
|
|
|
12002
12046
|
if (!firstPart) jsxTagName = j.jsxIdentifier(renderedComponent);
|
|
12003
12047
|
else jsxTagName = j.jsxMemberExpression(j.jsxIdentifier(firstPart), j.jsxIdentifier(parts.slice(1).join(".")));
|
|
12004
12048
|
} else jsxTagName = j.jsxIdentifier(renderedComponent);
|
|
12005
|
-
const { attrsInfo, staticClassNameExpr } = emitter.splitAttrsInfo(d.attrsInfo, getBridgeClassVar(d));
|
|
12049
|
+
const { attrsInfo, staticClassNameExpr } = emitter.splitAttrsInfo(d.attrsInfo, getBridgeClassVar(d), d.extraClassNames);
|
|
12006
12050
|
const defaultAttrs = attrsInfo?.defaultAttrs ?? [];
|
|
12007
12051
|
const staticAttrs = attrsInfo?.staticAttrs ?? {};
|
|
12008
12052
|
const needsSxVar = allowClassNameProp || allowStyleProp || !!d.inlineStyleProps?.length || !!staticClassNameExpr;
|
|
@@ -12777,7 +12821,7 @@ function emitIntrinsicPolymorphicWrappers(ctx) {
|
|
|
12777
12821
|
restId
|
|
12778
12822
|
});
|
|
12779
12823
|
const declStmt = j.variableDeclaration("const", [j.variableDeclarator(j.objectPattern(patternProps), propsId)]);
|
|
12780
|
-
const { attrsInfo, staticClassNameExpr } = emitter.splitAttrsInfo(d.attrsInfo, getBridgeClassVar(d));
|
|
12824
|
+
const { attrsInfo, staticClassNameExpr } = emitter.splitAttrsInfo(d.attrsInfo, getBridgeClassVar(d), d.extraClassNames);
|
|
12781
12825
|
const { attrsInfo: attrsInfoWithoutForwardedAsStatic, forwardedAsStaticFallback } = splitForwardedAsStaticAttrs({
|
|
12782
12826
|
attrsInfo,
|
|
12783
12827
|
includeForwardedAs: includesForwardedAs
|
|
@@ -13132,7 +13176,7 @@ function emitShouldForwardPropWrappers(ctx) {
|
|
|
13132
13176
|
});
|
|
13133
13177
|
const declStmt = j.variableDeclaration("const", [j.variableDeclarator(j.objectPattern(patternProps), propsId)]);
|
|
13134
13178
|
const cleanupPrefixStmt = dropPrefix && (isExportedComponent || (d.supportsExternalStyles ?? false) || shouldAllowAnyPrefixProps) && includeRest ? buildPrefixCleanupStatements(j, restId, dropPrefix) : null;
|
|
13135
|
-
const { attrsInfo, staticClassNameExpr } = emitter.splitAttrsInfo(d.attrsInfo, getBridgeClassVar(d));
|
|
13179
|
+
const { attrsInfo, staticClassNameExpr } = emitter.splitAttrsInfo(d.attrsInfo, getBridgeClassVar(d), d.extraClassNames);
|
|
13136
13180
|
let attrsInfoForJsx;
|
|
13137
13181
|
let forwardedAsStaticFallback;
|
|
13138
13182
|
if (!allowClassNameProp && !allowStyleProp) {
|
|
@@ -13365,7 +13409,7 @@ function emitSimpleWithConfigWrappers(ctx) {
|
|
|
13365
13409
|
restId
|
|
13366
13410
|
});
|
|
13367
13411
|
const declStmt = j.variableDeclaration("const", [j.variableDeclarator(j.objectPattern(patternProps), propsId)]);
|
|
13368
|
-
const { attrsInfo, staticClassNameExpr } = emitter.splitAttrsInfo(d.attrsInfo, getBridgeClassVar(d));
|
|
13412
|
+
const { attrsInfo, staticClassNameExpr } = emitter.splitAttrsInfo(d.attrsInfo, getBridgeClassVar(d), d.extraClassNames);
|
|
13369
13413
|
const merging = emitStyleMerging({
|
|
13370
13414
|
j,
|
|
13371
13415
|
emitter,
|
|
@@ -13696,7 +13740,7 @@ function emitSimpleExportedIntrinsicWrappers(ctx) {
|
|
|
13696
13740
|
});
|
|
13697
13741
|
const usePropsChildrenDirectly = emitter.isChildrenOnlyDestructurePattern(patternProps);
|
|
13698
13742
|
const declStmt = usePropsChildrenDirectly ? null : j.variableDeclaration("const", [j.variableDeclarator(j.objectPattern(patternProps), propsId)]);
|
|
13699
|
-
const { attrsInfo, staticClassNameExpr } = emitter.splitAttrsInfo(d.attrsInfo, getBridgeClassVar(d));
|
|
13743
|
+
const { attrsInfo, staticClassNameExpr } = emitter.splitAttrsInfo(d.attrsInfo, getBridgeClassVar(d), d.extraClassNames);
|
|
13700
13744
|
const { attrsInfo: attrsInfoWithoutForwardedAsStatic, forwardedAsStaticFallback } = splitForwardedAsStaticAttrs({
|
|
13701
13745
|
attrsInfo,
|
|
13702
13746
|
includeForwardedAs: includesForwardedAs
|
|
@@ -14505,13 +14549,18 @@ function parseSingleSelector(selector) {
|
|
|
14505
14549
|
kind: "unsupported",
|
|
14506
14550
|
reason: "attribute selector"
|
|
14507
14551
|
};
|
|
14508
|
-
if (
|
|
14552
|
+
if (pseudoElements.length > 0) return {
|
|
14509
14553
|
kind: "unsupported",
|
|
14510
|
-
reason: "attribute selector with pseudo"
|
|
14554
|
+
reason: "attribute selector with pseudo-element"
|
|
14555
|
+
};
|
|
14556
|
+
const attrStr = attributes.map((a) => a.toString()).join("");
|
|
14557
|
+
if (pseudoClasses.length > 0) return {
|
|
14558
|
+
kind: "pseudo",
|
|
14559
|
+
pseudos: [`${buildPseudoString(pseudoClasses)}:is(${attrStr})`]
|
|
14511
14560
|
};
|
|
14512
14561
|
return {
|
|
14513
14562
|
kind: "pseudo",
|
|
14514
|
-
pseudos: [`:is(${
|
|
14563
|
+
pseudos: [`:is(${attrStr})`]
|
|
14515
14564
|
};
|
|
14516
14565
|
}
|
|
14517
14566
|
if (!hasNesting && (pseudoClasses.length > 0 || pseudoElements.length > 0)) {}
|
|
@@ -15739,12 +15788,21 @@ const createImportResolver = (args) => {
|
|
|
15739
15788
|
};
|
|
15740
15789
|
//#endregion
|
|
15741
15790
|
//#region src/internal/lower-rules/state.ts
|
|
15791
|
+
/**
|
|
15792
|
+
* Builds shared state for the lower-rules pipeline.
|
|
15793
|
+
* Core concepts: resolver wiring, precomputed mixin values, and shared tracking maps.
|
|
15794
|
+
*/
|
|
15742
15795
|
function createLowerRulesState(ctx) {
|
|
15743
15796
|
const { api, j, root, file, warnings, resolverImports, keyframesNames, parseExpr, rewriteCssVarsInStyleObject } = ctx;
|
|
15744
15797
|
const filePath = file.path;
|
|
15745
15798
|
const resolveValue = ctx.resolveValueSafe;
|
|
15746
15799
|
const resolveValueDirectional = ctx.resolveValueDirectionalSafe;
|
|
15747
15800
|
const resolveCall = ctx.resolveCallSafe;
|
|
15801
|
+
const resolveValueOptional = (rvCtx) => {
|
|
15802
|
+
const res = ctx.adapter.resolveValue(rvCtx);
|
|
15803
|
+
if (res && isDirectionalResult(res)) return;
|
|
15804
|
+
return res;
|
|
15805
|
+
};
|
|
15748
15806
|
const resolveCallOptional = ctx.adapter.resolveCall.bind(ctx.adapter);
|
|
15749
15807
|
const resolveSelector = ctx.resolveSelectorSafe;
|
|
15750
15808
|
const importMap = ctx.importMap ?? /* @__PURE__ */ new Map();
|
|
@@ -15875,6 +15933,7 @@ function createLowerRulesState(ctx) {
|
|
|
15875
15933
|
parseExpr,
|
|
15876
15934
|
rewriteCssVarsInStyleObject,
|
|
15877
15935
|
resolveValue,
|
|
15936
|
+
resolveValueOptional,
|
|
15878
15937
|
resolveValueDirectional,
|
|
15879
15938
|
resolveCall,
|
|
15880
15939
|
resolveCallOptional,
|
|
@@ -16523,6 +16582,11 @@ function isAdapterResultCssValue(result, cssProperty) {
|
|
|
16523
16582
|
* or "resolvedStyles" for StyleX references (to be used in stylex.props arguments).
|
|
16524
16583
|
*/
|
|
16525
16584
|
function buildResolvedHandlerResult(result, cssProperty, payload) {
|
|
16585
|
+
if ("extraClassNames" in result && !("expr" in result)) return {
|
|
16586
|
+
type: "resolvedClassNames",
|
|
16587
|
+
extraClassNames: result.extraClassNames,
|
|
16588
|
+
...payload
|
|
16589
|
+
};
|
|
16526
16590
|
if (!("expr" in result)) return {
|
|
16527
16591
|
type: "runtimeCallOnly",
|
|
16528
16592
|
...payload
|
|
@@ -16537,6 +16601,7 @@ function buildResolvedHandlerResult(result, cssProperty, payload) {
|
|
|
16537
16601
|
expr: result.expr,
|
|
16538
16602
|
imports: result.imports,
|
|
16539
16603
|
...result.cssText ? { cssText: result.cssText } : {},
|
|
16604
|
+
...result.extraClassNames ? { extraClassNames: result.extraClassNames } : {},
|
|
16540
16605
|
...payload
|
|
16541
16606
|
};
|
|
16542
16607
|
}
|
|
@@ -16560,20 +16625,22 @@ function getArrowFnThemeParamInfo(fn) {
|
|
|
16560
16625
|
propsName: p.name
|
|
16561
16626
|
};
|
|
16562
16627
|
if (p?.type !== "ObjectPattern" || !Array.isArray(p.properties)) return null;
|
|
16628
|
+
let themeName = null;
|
|
16629
|
+
const siblingBindings = [];
|
|
16563
16630
|
for (const prop of p.properties) {
|
|
16564
16631
|
if (!prop || prop.type !== "Property" && prop.type !== "ObjectProperty") continue;
|
|
16565
16632
|
const key = prop.key;
|
|
16566
|
-
if (!key || key.type !== "Identifier"
|
|
16633
|
+
if (!key || key.type !== "Identifier") continue;
|
|
16567
16634
|
const value = prop.value;
|
|
16568
|
-
|
|
16569
|
-
|
|
16570
|
-
|
|
16571
|
-
};
|
|
16572
|
-
if (value?.type === "AssignmentPattern" && value.left?.type === "Identifier" && typeof value.left.name === "string") return {
|
|
16573
|
-
kind: "themeBinding",
|
|
16574
|
-
themeName: value.left.name
|
|
16575
|
-
};
|
|
16635
|
+
const binding = extractBindingName(value) ?? key.name;
|
|
16636
|
+
if (key.name === "theme") themeName = binding;
|
|
16637
|
+
else siblingBindings.push(binding);
|
|
16576
16638
|
}
|
|
16639
|
+
if (themeName) return {
|
|
16640
|
+
kind: "themeBinding",
|
|
16641
|
+
themeName,
|
|
16642
|
+
siblingBindings
|
|
16643
|
+
};
|
|
16577
16644
|
return null;
|
|
16578
16645
|
}
|
|
16579
16646
|
/**
|
|
@@ -16782,6 +16849,17 @@ function callArgFromNode(node, propsParamName, themeBindingName) {
|
|
|
16782
16849
|
}
|
|
16783
16850
|
return { kind: "unknown" };
|
|
16784
16851
|
}
|
|
16852
|
+
/**
|
|
16853
|
+
* Extracts the actual binding name from a destructured property value.
|
|
16854
|
+
* Handles: `{ x }` → "x", `{ x: alias }` → "alias", `{ x: alias = def }` → "alias"
|
|
16855
|
+
*/
|
|
16856
|
+
function extractBindingName(value) {
|
|
16857
|
+
if (!value || typeof value !== "object") return null;
|
|
16858
|
+
const v = value;
|
|
16859
|
+
if (v.type === "Identifier" && typeof v.name === "string") return v.name;
|
|
16860
|
+
if (v.type === "AssignmentPattern" && v.left?.type === "Identifier" && typeof v.left.name === "string") return v.left.name;
|
|
16861
|
+
return null;
|
|
16862
|
+
}
|
|
16785
16863
|
function callArgsFromNode(args, propsParamName, themeBindingName) {
|
|
16786
16864
|
if (!Array.isArray(args)) return [];
|
|
16787
16865
|
return args.map((arg) => callArgFromNode(arg, propsParamName, themeBindingName));
|
|
@@ -16807,7 +16885,7 @@ function tryResolveConditionalValue(node, ctx) {
|
|
|
16807
16885
|
if (!body || body.type !== "ConditionalExpression") return null;
|
|
16808
16886
|
const checkThemeBooleanTest = (test) => {
|
|
16809
16887
|
const check = (node) => {
|
|
16810
|
-
if (!node || typeof node !== "object" || node
|
|
16888
|
+
if (!node || typeof node !== "object" || !isMemberExpression(node)) return null;
|
|
16811
16889
|
if (info?.kind === "propsParam" && paramName) {
|
|
16812
16890
|
const parts = getMemberPathFromIdentifier(node, paramName);
|
|
16813
16891
|
const themeProp = parts?.[1];
|
|
@@ -16836,7 +16914,7 @@ function tryResolveConditionalValue(node, ctx) {
|
|
|
16836
16914
|
return null;
|
|
16837
16915
|
};
|
|
16838
16916
|
const resolveThemeFromMemberExpr = (node) => {
|
|
16839
|
-
if (!node || typeof node !== "object" || node
|
|
16917
|
+
if (!node || typeof node !== "object" || !isMemberExpression(node)) return null;
|
|
16840
16918
|
if (info?.kind === "propsParam" && paramName) {
|
|
16841
16919
|
const parts = getMemberPathFromIdentifier(node, paramName);
|
|
16842
16920
|
if (!parts || parts[0] !== "theme") return null;
|
|
@@ -16852,7 +16930,7 @@ function tryResolveConditionalValue(node, ctx) {
|
|
|
16852
16930
|
const resolveThemeBranchValue = (branch) => {
|
|
16853
16931
|
const themeInfo = resolveThemeFromMemberExpr(branch);
|
|
16854
16932
|
if (!themeInfo) return null;
|
|
16855
|
-
const res = ctx.resolveValue({
|
|
16933
|
+
const res = (ctx.resolveValueOptional ?? ctx.resolveValue)({
|
|
16856
16934
|
kind: "theme",
|
|
16857
16935
|
path: themeInfo.path,
|
|
16858
16936
|
filePath: ctx.filePath,
|
|
@@ -16960,7 +17038,7 @@ function tryResolveConditionalValue(node, ctx) {
|
|
|
16960
17038
|
const res = resolveImportedHelperCall(call, ctx, propsParamName, cssProperty, themeBindingName);
|
|
16961
17039
|
if (res.kind === "resolved") {
|
|
16962
17040
|
if ("expr" in res.result) return res.result;
|
|
16963
|
-
if (res.result.preserveRuntimeCall) {
|
|
17041
|
+
if ("preserveRuntimeCall" in res.result && res.result.preserveRuntimeCall) {
|
|
16964
17042
|
runtimeCallState.info = {
|
|
16965
17043
|
resolveCallContext: res.resolveCallContext,
|
|
16966
17044
|
resolveCallResult: res.resolveCallResult
|
|
@@ -16975,7 +17053,7 @@ function tryResolveConditionalValue(node, ctx) {
|
|
|
16975
17053
|
const innerRes = resolveImportedHelperCall(inner, ctx, propsParamName, cssProperty, themeBindingName);
|
|
16976
17054
|
if (innerRes.kind === "resolved") {
|
|
16977
17055
|
if ("expr" in innerRes.result) return innerRes.result;
|
|
16978
|
-
if (innerRes.result.preserveRuntimeCall) {
|
|
17056
|
+
if ("preserveRuntimeCall" in innerRes.result && innerRes.result.preserveRuntimeCall) {
|
|
16979
17057
|
runtimeCallState.info = {
|
|
16980
17058
|
resolveCallContext: innerRes.resolveCallContext,
|
|
16981
17059
|
resolveCallResult: innerRes.resolveCallResult
|
|
@@ -17736,10 +17814,9 @@ function tryBuildThemeBooleanInlineStyleFallback(args) {
|
|
|
17736
17814
|
const { trueValue, falseValue, trueImports, falseImports, trueBranch, falseBranch, themeBoolInfo, cssProp, paramName, info } = args;
|
|
17737
17815
|
if (trueValue === null === (falseValue === null)) return null;
|
|
17738
17816
|
const resolvedBranchIsTrue = trueValue !== null;
|
|
17739
|
-
const
|
|
17740
|
-
if (!hasCallExpression(unresolvableBranch)) return null;
|
|
17741
|
-
const transformed = replaceThemeRefsWithHookVar(unresolvableBranch, paramName, info);
|
|
17817
|
+
const transformed = replaceThemeRefsWithHookVar(resolvedBranchIsTrue ? falseBranch : trueBranch, paramName, info);
|
|
17742
17818
|
if (!transformed) return null;
|
|
17819
|
+
if (!isFullyTransformedThemeExpr(transformed, paramName, info)) return null;
|
|
17743
17820
|
return {
|
|
17744
17821
|
type: "splitThemeBooleanWithInlineStyleFallback",
|
|
17745
17822
|
cssProp,
|
|
@@ -17751,17 +17828,49 @@ function tryBuildThemeBooleanInlineStyleFallback(args) {
|
|
|
17751
17828
|
inlineExpr: transformed
|
|
17752
17829
|
};
|
|
17753
17830
|
}
|
|
17754
|
-
/**
|
|
17755
|
-
|
|
17756
|
-
|
|
17757
|
-
|
|
17758
|
-
|
|
17759
|
-
|
|
17760
|
-
|
|
17761
|
-
|
|
17762
|
-
|
|
17831
|
+
/**
|
|
17832
|
+
* Validates that a transformed expression has no dangling references to
|
|
17833
|
+
* the original arrow function parameter or theme binding name.
|
|
17834
|
+
* After `replaceThemeRefsWithHookVar`, all `<paramName>.theme.*` should
|
|
17835
|
+
* have been rewritten to `theme.*`. If the param name still appears,
|
|
17836
|
+
* the expression accesses non-theme props and can't be safely used
|
|
17837
|
+
* with `useTheme()` alone.
|
|
17838
|
+
*/
|
|
17839
|
+
function isFullyTransformedThemeExpr(transformed, paramName, info) {
|
|
17840
|
+
const ids = /* @__PURE__ */ new Set();
|
|
17841
|
+
collectFreeIdentifiers(transformed, ids);
|
|
17842
|
+
if (paramName && ids.has(paramName)) return false;
|
|
17843
|
+
if (info?.kind === "themeBinding") {
|
|
17844
|
+
if (info.themeName !== "theme" && ids.has(info.themeName)) return false;
|
|
17845
|
+
if (info.siblingBindings.some((b) => ids.has(b))) return false;
|
|
17846
|
+
}
|
|
17847
|
+
return true;
|
|
17848
|
+
}
|
|
17849
|
+
/**
|
|
17850
|
+
* Collects free variable identifiers from an AST node, excluding
|
|
17851
|
+
* non-computed property names in member expressions (e.g., in
|
|
17852
|
+
* `theme.color.bgSub`, only `theme` is a free variable; `color`
|
|
17853
|
+
* and `bgSub` are property accesses, not variable references).
|
|
17854
|
+
*/
|
|
17855
|
+
function collectFreeIdentifiers(node, out) {
|
|
17856
|
+
if (!node || typeof node !== "object") return;
|
|
17857
|
+
if (Array.isArray(node)) {
|
|
17858
|
+
for (const child of node) collectFreeIdentifiers(child, out);
|
|
17859
|
+
return;
|
|
17860
|
+
}
|
|
17861
|
+
const typed = node;
|
|
17862
|
+
const nodeType = typed.type;
|
|
17863
|
+
if (nodeType === "MemberExpression" || nodeType === "OptionalMemberExpression") {
|
|
17864
|
+
collectFreeIdentifiers(typed.object, out);
|
|
17865
|
+
if (typed.computed) collectFreeIdentifiers(typed.property, out);
|
|
17866
|
+
return;
|
|
17867
|
+
}
|
|
17868
|
+
if (nodeType === "Identifier" && typeof typed.name === "string") out.add(typed.name);
|
|
17869
|
+
for (const key of Object.keys(typed)) {
|
|
17870
|
+
if (key === "loc" || key === "comments" || key === "type") continue;
|
|
17871
|
+
const child = typed[key];
|
|
17872
|
+
if (child && typeof child === "object") collectFreeIdentifiers(child, out);
|
|
17763
17873
|
}
|
|
17764
|
-
return false;
|
|
17765
17874
|
}
|
|
17766
17875
|
/**
|
|
17767
17876
|
* Deep-clones an expression and replaces `<paramName>.theme.*` or `theme.*`
|
|
@@ -20725,7 +20834,7 @@ const createValuePatternHandlers = (ctx) => {
|
|
|
20725
20834
|
* Core concepts: per-component style buckets, helper factories, and resolver wiring.
|
|
20726
20835
|
*/
|
|
20727
20836
|
function createDeclProcessingState(state, decl) {
|
|
20728
|
-
const { api, j, root, filePath, warnings, resolverImports, parseExpr, resolveValue, resolveValueDirectional, resolveCall, resolveCallOptional, resolveSelector, importMap, cssHelperFunctions, stringMappingFns, hasLocalThemeBinding, isCssHelperTaggedTemplate, resolveCssHelperTemplate, resolveImportInScope, usedCssHelperFunctions, enumValueMap, markBail } = state;
|
|
20837
|
+
const { api, j, root, filePath, warnings, resolverImports, parseExpr, resolveValue, resolveValueOptional, resolveValueDirectional, resolveCall, resolveCallOptional, resolveSelector, importMap, cssHelperFunctions, stringMappingFns, hasLocalThemeBinding, isCssHelperTaggedTemplate, resolveCssHelperTemplate, resolveImportInScope, usedCssHelperFunctions, enumValueMap, markBail } = state;
|
|
20729
20838
|
const styleObj = {};
|
|
20730
20839
|
const perPropPseudo = {};
|
|
20731
20840
|
const perPropMedia = {};
|
|
@@ -20839,6 +20948,7 @@ function createDeclProcessingState(state, decl) {
|
|
|
20839
20948
|
api,
|
|
20840
20949
|
filePath,
|
|
20841
20950
|
resolveValue,
|
|
20951
|
+
resolveValueOptional,
|
|
20842
20952
|
resolveValueDirectional,
|
|
20843
20953
|
resolveCall,
|
|
20844
20954
|
resolveCallOptional,
|
|
@@ -22350,6 +22460,15 @@ function handleInterpolatedDeclaration(args) {
|
|
|
22350
22460
|
if (!imports) return;
|
|
22351
22461
|
for (const imp of imports) resolverImports.set(JSON.stringify(imp), imp);
|
|
22352
22462
|
};
|
|
22463
|
+
/** Parse and store extra className expressions (from CSS modules) on the decl. */
|
|
22464
|
+
const collectExtraClassNames = (entries) => {
|
|
22465
|
+
decl.extraClassNames ??= [];
|
|
22466
|
+
for (const cn of entries) {
|
|
22467
|
+
addResolverImports(cn.imports);
|
|
22468
|
+
const cnExpr = parseExpr(cn.expr);
|
|
22469
|
+
if (cnExpr) decl.extraClassNames.push({ expr: cnExpr });
|
|
22470
|
+
}
|
|
22471
|
+
};
|
|
22353
22472
|
/**
|
|
22354
22473
|
* Try to convert an identity prop with a finite string union type into static variant
|
|
22355
22474
|
* buckets. Returns true if the optimization applied and the caller should `continue`.
|
|
@@ -22371,7 +22490,7 @@ function handleInterpolatedDeclaration(args) {
|
|
|
22371
22490
|
};
|
|
22372
22491
|
const maybeEmitPreservedRuntimeCallOverride = (args) => {
|
|
22373
22492
|
const { resolveCallResult, originalExpr, loc } = args;
|
|
22374
|
-
if (!resolveCallResult
|
|
22493
|
+
if (!resolveCallResult || !("preserveRuntimeCall" in resolveCallResult) || !resolveCallResult.preserveRuntimeCall) return "not-requested";
|
|
22375
22494
|
if (!d.property) {
|
|
22376
22495
|
warnings.push({
|
|
22377
22496
|
severity: "error",
|
|
@@ -22861,10 +22980,16 @@ function handleInterpolatedDeclaration(args) {
|
|
|
22861
22980
|
expr: exprAst,
|
|
22862
22981
|
afterBase: hasStaticPropsBefore
|
|
22863
22982
|
});
|
|
22983
|
+
if (res.extraClassNames) collectExtraClassNames(res.extraClassNames);
|
|
22864
22984
|
notifyResolvedStylesArg();
|
|
22865
22985
|
decl.needsWrapperComponent = true;
|
|
22866
22986
|
continue;
|
|
22867
22987
|
}
|
|
22988
|
+
if (res && res.type === "resolvedClassNames") {
|
|
22989
|
+
collectExtraClassNames(res.extraClassNames);
|
|
22990
|
+
decl.needsWrapperComponent = true;
|
|
22991
|
+
continue;
|
|
22992
|
+
}
|
|
22868
22993
|
if (res && res.type === "resolvedDirectional") {
|
|
22869
22994
|
let directionalFailed = false;
|
|
22870
22995
|
for (const entry of res.directional) {
|
|
@@ -22973,6 +23098,14 @@ function handleInterpolatedDeclaration(args) {
|
|
|
22973
23098
|
continue;
|
|
22974
23099
|
}
|
|
22975
23100
|
if (res && res.type === "splitThemeBooleanWithInlineStyleFallback") {
|
|
23101
|
+
if (pseudos?.length || media || pseudoElement) {
|
|
23102
|
+
bail = true;
|
|
23103
|
+
continue;
|
|
23104
|
+
}
|
|
23105
|
+
if (isCssShorthandProperty(res.cssProp)) {
|
|
23106
|
+
bail = true;
|
|
23107
|
+
continue;
|
|
23108
|
+
}
|
|
22976
23109
|
addResolverImports(res.resolvedImports);
|
|
22977
23110
|
if (!decl.needsUseThemeHook) decl.needsUseThemeHook = [];
|
|
22978
23111
|
if (!decl.needsUseThemeHook.some((e) => e.themeProp === res.themeProp)) decl.needsUseThemeHook.push({
|
|
@@ -27514,15 +27647,22 @@ function rewriteJsxStep(ctx) {
|
|
|
27514
27647
|
styleAttr = null;
|
|
27515
27648
|
}
|
|
27516
27649
|
if (promotedMerge) styleAttr = null;
|
|
27517
|
-
const
|
|
27650
|
+
const extraClassNameExpr = decl.extraClassNames && decl.extraClassNames.length > 0 ? buildExtraClassNameExpr(j, decl.extraClassNames) : void 0;
|
|
27518
27651
|
const isIntrinsicTag = /^[a-z]/.test(finalTag) && !finalTag.includes(".");
|
|
27519
|
-
|
|
27652
|
+
let effectiveClassNameAttr = classNameAttr;
|
|
27653
|
+
if (extraClassNameExpr && !ctx.adapter.useSxProp) effectiveClassNameAttr = j.jsxAttribute(j.jsxIdentifier("className"), j.jsxExpressionContainer(extraClassNameExpr));
|
|
27654
|
+
const needsMerge = effectiveClassNameAttr !== null || styleAttr !== null;
|
|
27655
|
+
const useSxProp = ctx.adapter.useSxProp && !needsMerge && isIntrinsicTag;
|
|
27656
|
+
const stylexAttr = useSxProp ? (() => {
|
|
27520
27657
|
const sxExpr = styleArgs.length === 1 && styleArgs[0] ? styleArgs[0] : j.arrayExpression([...styleArgs]);
|
|
27521
27658
|
return j.jsxAttribute(j.jsxIdentifier("sx"), j.jsxExpressionContainer(sxExpr));
|
|
27522
|
-
})() : j.jsxSpreadAttribute(needsMerge ? buildInlineMergeCall(j, styleArgs,
|
|
27659
|
+
})() : j.jsxSpreadAttribute(needsMerge ? buildInlineMergeCall(j, styleArgs, effectiveClassNameAttr, styleAttr, ctx.adapter.styleMerger?.functionName) : j.callExpression(j.memberExpression(j.identifier("stylex"), j.identifier("props")), [...styleArgs]));
|
|
27660
|
+
const extraClassNameAttrs = [];
|
|
27661
|
+
if (extraClassNameExpr && useSxProp) extraClassNameAttrs.push(j.jsxAttribute(j.jsxIdentifier("className"), j.jsxExpressionContainer(extraClassNameExpr)));
|
|
27523
27662
|
const finalRest = [
|
|
27524
27663
|
...keptRestAfterVariants.slice(0, finalInsertIndex),
|
|
27525
27664
|
stylexAttr,
|
|
27665
|
+
...extraClassNameAttrs,
|
|
27526
27666
|
...keptRestAfterVariants.slice(finalInsertIndex)
|
|
27527
27667
|
];
|
|
27528
27668
|
opening.attributes = [
|
|
@@ -27575,6 +27715,25 @@ function extractJsxAttrValueExpr(j, attr) {
|
|
|
27575
27715
|
if (a.value.type === "JSXExpressionContainer") return a.value.expression;
|
|
27576
27716
|
}
|
|
27577
27717
|
/**
|
|
27718
|
+
* Builds a single expression from extra className entries (CSS module classes).
|
|
27719
|
+
* Single entry: returns the expression directly.
|
|
27720
|
+
* Multiple entries: joins with a template literal `${a} ${b}`.
|
|
27721
|
+
*/
|
|
27722
|
+
function buildExtraClassNameExpr(j, extraClassNames) {
|
|
27723
|
+
const exprs = extraClassNames.map((cn) => cn.expr);
|
|
27724
|
+
if (exprs.length === 1 && exprs[0]) return exprs[0];
|
|
27725
|
+
const qs = [];
|
|
27726
|
+
for (let i = 0; i <= exprs.length; i++) {
|
|
27727
|
+
const isLast = i === exprs.length;
|
|
27728
|
+
const raw = i === 0 || isLast ? "" : " ";
|
|
27729
|
+
qs.push(j.templateElement({
|
|
27730
|
+
raw,
|
|
27731
|
+
cooked: raw
|
|
27732
|
+
}, isLast));
|
|
27733
|
+
}
|
|
27734
|
+
return j.templateLiteral(qs, exprs);
|
|
27735
|
+
}
|
|
27736
|
+
/**
|
|
27578
27737
|
* Finds the combined style key matching the consumed props at a JSX call site.
|
|
27579
27738
|
* Returns the style key if a matching combination exists, or undefined otherwise.
|
|
27580
27739
|
*/
|