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