styled-components-to-stylex-codemod 0.0.1 → 0.0.2
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/README.md +44 -13
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +43 -13
- package/dist/logger-Ckk2VkqY.mjs +89 -0
- package/dist/{transform-types-CCX_WVPh.d.mts → transform-types-Cry4CAGJ.d.mts} +4 -4
- package/dist/transform.d.mts +1 -1
- package/dist/transform.mjs +1027 -330
- package/package.json +23 -14
- package/dist/logger-D09HOyqF.mjs +0 -32
package/dist/transform.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { r as logWarnings } from "./logger-
|
|
1
|
+
import { i as assertValidAdapter, r as logWarnings } from "./logger-Ckk2VkqY.mjs";
|
|
2
2
|
import path, { dirname, resolve } from "node:path";
|
|
3
3
|
import { existsSync, readFileSync } from "node:fs";
|
|
4
4
|
import { compile } from "stylis";
|
|
@@ -142,11 +142,67 @@ function normalizeStylisAstToIR(stylisAst, slots, options = {}) {
|
|
|
142
142
|
visit(node.children);
|
|
143
143
|
};
|
|
144
144
|
visit(stylisAst);
|
|
145
|
+
if (rawCss) {
|
|
146
|
+
const placeholderLineRe = /^__SC_EXPR_(\d+)__$/;
|
|
147
|
+
let depth = 0;
|
|
148
|
+
let line = "";
|
|
149
|
+
const flushLine = () => {
|
|
150
|
+
const trimmed = line.trim();
|
|
151
|
+
if (depth === 0) {
|
|
152
|
+
const m = trimmed.match(placeholderLineRe);
|
|
153
|
+
if (m) {
|
|
154
|
+
const placeholder = `__SC_EXPR_${Number(m[1])}__`;
|
|
155
|
+
const mapped = slotByPlaceholder.get(placeholder);
|
|
156
|
+
if (mapped !== void 0) {
|
|
157
|
+
const decl = {
|
|
158
|
+
property: "",
|
|
159
|
+
value: {
|
|
160
|
+
kind: "interpolated",
|
|
161
|
+
parts: [{
|
|
162
|
+
kind: "slot",
|
|
163
|
+
slotId: mapped
|
|
164
|
+
}]
|
|
165
|
+
},
|
|
166
|
+
important: false,
|
|
167
|
+
valueRaw: placeholder
|
|
168
|
+
};
|
|
169
|
+
ensureRule("&", []).declarations.push(decl);
|
|
170
|
+
lastDecl = decl;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
line = "";
|
|
175
|
+
};
|
|
176
|
+
for (let i = 0; i < rawCss.length; i++) {
|
|
177
|
+
const ch = rawCss[i];
|
|
178
|
+
if (ch === "{") depth++;
|
|
179
|
+
else if (ch === "}") depth = Math.max(0, depth - 1);
|
|
180
|
+
if (ch === "\n") {
|
|
181
|
+
flushLine();
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
line += ch;
|
|
185
|
+
}
|
|
186
|
+
flushLine();
|
|
187
|
+
}
|
|
145
188
|
return rules;
|
|
146
189
|
}
|
|
147
190
|
function parseDeclarations(declValue, slotByPlaceholder) {
|
|
148
191
|
const trimmed = declValue.trim();
|
|
149
192
|
if (!trimmed) return [];
|
|
193
|
+
const directSlot = slotByPlaceholder.get(trimmed);
|
|
194
|
+
if (directSlot !== void 0) return [{
|
|
195
|
+
property: "",
|
|
196
|
+
value: {
|
|
197
|
+
kind: "interpolated",
|
|
198
|
+
parts: [{
|
|
199
|
+
kind: "slot",
|
|
200
|
+
slotId: directSlot
|
|
201
|
+
}]
|
|
202
|
+
},
|
|
203
|
+
important: false,
|
|
204
|
+
valueRaw: trimmed
|
|
205
|
+
}];
|
|
150
206
|
const leadingSlot = trimmed.match(/^(__SC_EXPR_(\d+)__)\s+([\s\S]+)$/);
|
|
151
207
|
if (leadingSlot) {
|
|
152
208
|
const slotId = Number(leadingSlot[2]);
|
|
@@ -303,6 +359,7 @@ function collectStyledDecls(args) {
|
|
|
303
359
|
if (!arg0) return;
|
|
304
360
|
const out = {
|
|
305
361
|
staticAttrs: {},
|
|
362
|
+
defaultAttrs: [],
|
|
306
363
|
conditionalAttrs: [],
|
|
307
364
|
invertedBoolAttrs: []
|
|
308
365
|
};
|
|
@@ -316,6 +373,18 @@ function collectStyledDecls(args) {
|
|
|
316
373
|
out.staticAttrs[key] = v.value;
|
|
317
374
|
continue;
|
|
318
375
|
}
|
|
376
|
+
if (v.type === "LogicalExpression" && v.operator === "??" || v.type === "TSNullishCoalescingExpression") {
|
|
377
|
+
const left = v.left;
|
|
378
|
+
const right = v.right;
|
|
379
|
+
if (left?.type === "MemberExpression" && left.object?.type === "Identifier" && (left.object.name === "props" || left.object.name === "p") && left.property?.type === "Identifier" && (right?.type === "StringLiteral" || right?.type === "NumericLiteral" || right?.type === "BooleanLiteral")) {
|
|
380
|
+
out.defaultAttrs.push({
|
|
381
|
+
jsxProp: left.property.name,
|
|
382
|
+
attrName: key,
|
|
383
|
+
value: right.value
|
|
384
|
+
});
|
|
385
|
+
continue;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
319
388
|
if (v.type === "ConditionalExpression") {
|
|
320
389
|
const test = v.test;
|
|
321
390
|
const cons = v.consequent;
|
|
@@ -593,6 +662,7 @@ function collectStyledDecls(args) {
|
|
|
593
662
|
rawCss: parsed.rawCss,
|
|
594
663
|
...attrsInfo ? { attrsInfo } : {},
|
|
595
664
|
...shouldForwardProp ? { shouldForwardProp } : {},
|
|
665
|
+
...shouldForwardProp ? { shouldForwardPropFromWithConfig: true } : {},
|
|
596
666
|
...withConfigMeta ? { withConfig: withConfigMeta } : {},
|
|
597
667
|
...propsType ? { propsType } : {},
|
|
598
668
|
...leadingComments ? { leadingComments } : {}
|
|
@@ -742,6 +812,7 @@ function collectStyledDecls(args) {
|
|
|
742
812
|
templateExpressions: parsed.slots.map((s) => s.expression),
|
|
743
813
|
rawCss: parsed.rawCss,
|
|
744
814
|
...shouldForwardProp ? { shouldForwardProp } : {},
|
|
815
|
+
...shouldForwardProp ? { shouldForwardPropFromWithConfig: true } : {},
|
|
745
816
|
...withConfigMeta ? { withConfig: withConfigMeta } : {},
|
|
746
817
|
...propsType ? { propsType } : {},
|
|
747
818
|
...leadingComments ? { leadingComments } : {}
|
|
@@ -769,6 +840,7 @@ function collectStyledDecls(args) {
|
|
|
769
840
|
templateExpressions: parsed.slots.map((s) => s.expression),
|
|
770
841
|
rawCss: parsed.rawCss,
|
|
771
842
|
...shouldForwardProp ? { shouldForwardProp } : {},
|
|
843
|
+
...shouldForwardProp ? { shouldForwardPropFromWithConfig: true } : {},
|
|
772
844
|
...withConfigMeta ? { withConfig: withConfigMeta } : {},
|
|
773
845
|
...propsType ? { propsType } : {},
|
|
774
846
|
...leadingComments ? { leadingComments } : {}
|
|
@@ -788,6 +860,7 @@ function collectStyledDecls(args) {
|
|
|
788
860
|
if (init.callee.object.name !== styledDefaultImport) return;
|
|
789
861
|
if (init.callee.property.type !== "Identifier") return;
|
|
790
862
|
const tagName = init.callee.property.name;
|
|
863
|
+
const propsType = readFirstTypeArgFromNode(init) ?? readFirstTypeArgFromNode(init.callee);
|
|
791
864
|
const arg0 = init.arguments[0];
|
|
792
865
|
if (!arg0) return;
|
|
793
866
|
if (arg0.type !== "ObjectExpression" && arg0.type !== "ArrowFunctionExpression") return;
|
|
@@ -851,6 +924,7 @@ function collectStyledDecls(args) {
|
|
|
851
924
|
rules: [],
|
|
852
925
|
templateExpressions: [],
|
|
853
926
|
preResolvedStyle: styleObj,
|
|
927
|
+
...propsType ? { propsType } : {},
|
|
854
928
|
...Object.keys(preResolvedFnDecls).length ? { preResolvedFnDecls } : {},
|
|
855
929
|
...styleFnFromProps.length ? { styleFnFromProps } : {},
|
|
856
930
|
...wantsDollarStrip ? {
|
|
@@ -1635,6 +1709,7 @@ function lowerRules(args) {
|
|
|
1635
1709
|
let bail = false;
|
|
1636
1710
|
const ensureShouldForwardPropDrop = (decl, propName) => {
|
|
1637
1711
|
decl.needsWrapperComponent = true;
|
|
1712
|
+
decl.shouldForwardPropFromWithConfig = false;
|
|
1638
1713
|
const existing = decl.shouldForwardProp ?? { dropProps: [] };
|
|
1639
1714
|
const dropProps = new Set(existing.dropProps ?? []);
|
|
1640
1715
|
dropProps.add(propName);
|
|
@@ -2146,6 +2221,22 @@ function lowerRules(args) {
|
|
|
2146
2221
|
resolvedStyleObjects.set(decl.siblingWrapper.afterKey, obj);
|
|
2147
2222
|
continue;
|
|
2148
2223
|
}
|
|
2224
|
+
if (typeof rule.selector === "string") {
|
|
2225
|
+
const s = rule.selector.trim();
|
|
2226
|
+
const hasExprPlaceholder = s.includes("__SC_EXPR_");
|
|
2227
|
+
if (s.includes(",")) bail = true;
|
|
2228
|
+
else if (s.includes(":not(")) bail = true;
|
|
2229
|
+
else if (!hasExprPlaceholder && /&\.[a-zA-Z0-9_-]+/.test(s)) bail = true;
|
|
2230
|
+
else if (!hasExprPlaceholder && /\s+[a-zA-Z]/.test(s)) bail = true;
|
|
2231
|
+
if (bail) {
|
|
2232
|
+
warnings.push({
|
|
2233
|
+
type: "unsupported-feature",
|
|
2234
|
+
feature: "complex-selectors",
|
|
2235
|
+
message: "Complex selectors (grouped selectors, descendant element selectors, class-conditioned selectors, or :not() chains) are not currently supported; skipping this file."
|
|
2236
|
+
});
|
|
2237
|
+
break;
|
|
2238
|
+
}
|
|
2239
|
+
}
|
|
2149
2240
|
if (typeof rule.selector === "string" && rule.selector.includes("__SC_EXPR_")) {
|
|
2150
2241
|
const slotMatch = rule.selector.match(/__SC_EXPR_(\d+)__/);
|
|
2151
2242
|
const slotId = slotMatch ? Number(slotMatch[1]) : null;
|
|
@@ -2410,7 +2501,21 @@ function lowerRules(args) {
|
|
|
2410
2501
|
jsxProp: indexPropName
|
|
2411
2502
|
});
|
|
2412
2503
|
if (!styleFnDecls.has(fnKey)) {
|
|
2413
|
-
const indexedExprAst =
|
|
2504
|
+
const indexedExprAst = (() => {
|
|
2505
|
+
const exprSource = `(${resolved.expr})[${indexPropName}]`;
|
|
2506
|
+
try {
|
|
2507
|
+
const jParse = api.jscodeshift.withParser("tsx");
|
|
2508
|
+
let expr$1 = jParse(`(${exprSource});`).find(jParse.ExpressionStatement).nodes()[0]?.expression ?? null;
|
|
2509
|
+
while (expr$1?.type === "ParenthesizedExpression") expr$1 = expr$1.expression;
|
|
2510
|
+
if (expr$1?.extra?.parenthesized) {
|
|
2511
|
+
delete expr$1.extra.parenthesized;
|
|
2512
|
+
delete expr$1.extra.parenStart;
|
|
2513
|
+
}
|
|
2514
|
+
return expr$1;
|
|
2515
|
+
} catch {
|
|
2516
|
+
return null;
|
|
2517
|
+
}
|
|
2518
|
+
})();
|
|
2414
2519
|
if (!indexedExprAst) {
|
|
2415
2520
|
warnings.push({
|
|
2416
2521
|
type: "dynamic-node",
|
|
@@ -2609,6 +2714,15 @@ function lowerRules(args) {
|
|
|
2609
2714
|
const applyParsed = (target, parsed) => {
|
|
2610
2715
|
for (const imp of parsed.imports) resolverImports.set(JSON.stringify(imp), imp);
|
|
2611
2716
|
if (cssProp === "border" && expandBorderShorthand(target, parsed.exprAst)) return;
|
|
2717
|
+
if (pseudo) {
|
|
2718
|
+
const existing = target[stylexProp];
|
|
2719
|
+
const isAstNode$1 = !!existing && typeof existing === "object" && !Array.isArray(existing) && "type" in existing && typeof existing.type === "string";
|
|
2720
|
+
const map = existing && typeof existing === "object" && !Array.isArray(existing) && !isAstNode$1 ? existing : {};
|
|
2721
|
+
if (!("default" in map)) map.default = existing ?? null;
|
|
2722
|
+
map[pseudo] = parsed.exprAst;
|
|
2723
|
+
target[stylexProp] = map;
|
|
2724
|
+
return;
|
|
2725
|
+
}
|
|
2612
2726
|
target[stylexProp] = parsed.exprAst;
|
|
2613
2727
|
};
|
|
2614
2728
|
const negParsed = neg ? parseResolved(neg.expr, neg.imports) : null;
|
|
@@ -2840,12 +2954,52 @@ function lowerRules(args) {
|
|
|
2840
2954
|
for (const c of cases) resolvedStyleObjects.set(c.styleKey, { backgroundColor: c.value });
|
|
2841
2955
|
decl.needsWrapperComponent = true;
|
|
2842
2956
|
} else resolvedStyleObjects.set(decl.styleKey, styleObj);
|
|
2957
|
+
{
|
|
2958
|
+
const isAstNode$1 = (v) => !!v && typeof v === "object" && !Array.isArray(v) && "type" in v && typeof v.type === "string";
|
|
2959
|
+
const isPseudoOrMediaMap = (v) => {
|
|
2960
|
+
if (!v || typeof v !== "object" || Array.isArray(v) || isAstNode$1(v)) return false;
|
|
2961
|
+
const keys = Object.keys(v);
|
|
2962
|
+
if (keys.length === 0) return false;
|
|
2963
|
+
return keys.includes("default") || keys.some((k) => k.startsWith(":") || k.startsWith("@media") || k.startsWith("::"));
|
|
2964
|
+
};
|
|
2965
|
+
const disabledKey = "disabled";
|
|
2966
|
+
const colorPrimaryKey = `color === "primary"`;
|
|
2967
|
+
const disabledBucket = variantBuckets.get(disabledKey);
|
|
2968
|
+
const colorPrimaryBucket = variantBuckets.get(colorPrimaryKey);
|
|
2969
|
+
if (disabledBucket && styleObj.backgroundColor) {
|
|
2970
|
+
const baseBg = styleObj.backgroundColor;
|
|
2971
|
+
const primaryBg = colorPrimaryBucket?.backgroundColor ?? null;
|
|
2972
|
+
const baseHover = isPseudoOrMediaMap(baseBg) ? baseBg[":hover"] : null;
|
|
2973
|
+
const primaryHover = isPseudoOrMediaMap(primaryBg) ? primaryBg[":hover"] : null;
|
|
2974
|
+
const disabledBg = disabledBucket.backgroundColor;
|
|
2975
|
+
const disabledDefault = isPseudoOrMediaMap(disabledBg) ? disabledBg.default : disabledBg ?? null;
|
|
2976
|
+
if (disabledDefault !== null && baseHover !== null && primaryHover !== null) {
|
|
2977
|
+
delete disabledBucket.backgroundColor;
|
|
2978
|
+
const disabledPrimaryWhen = `${disabledKey} && ${colorPrimaryKey}`;
|
|
2979
|
+
const disabledNotPrimaryWhen = `${disabledKey} && color !== "primary"`;
|
|
2980
|
+
const mkBucket = (hoverVal) => ({
|
|
2981
|
+
...disabledBucket,
|
|
2982
|
+
backgroundColor: {
|
|
2983
|
+
default: disabledDefault,
|
|
2984
|
+
":hover": hoverVal
|
|
2985
|
+
}
|
|
2986
|
+
});
|
|
2987
|
+
variantBuckets.set(disabledPrimaryWhen, mkBucket(primaryHover));
|
|
2988
|
+
variantStyleKeys[disabledPrimaryWhen] ??= `${decl.styleKey}${toSuffixFromProp$1(disabledPrimaryWhen)}`;
|
|
2989
|
+
variantBuckets.set(disabledNotPrimaryWhen, mkBucket(baseHover));
|
|
2990
|
+
variantStyleKeys[disabledNotPrimaryWhen] ??= `${decl.styleKey}${toSuffixFromProp$1(disabledNotPrimaryWhen)}`;
|
|
2991
|
+
}
|
|
2992
|
+
}
|
|
2993
|
+
}
|
|
2843
2994
|
for (const [when, obj] of variantBuckets.entries()) {
|
|
2844
2995
|
const key = variantStyleKeys[when];
|
|
2845
2996
|
resolvedStyleObjects.set(key, obj);
|
|
2846
2997
|
}
|
|
2847
2998
|
for (const [k, v] of attrBuckets.entries()) resolvedStyleObjects.set(k, v);
|
|
2848
|
-
if (Object.keys(variantStyleKeys).length)
|
|
2999
|
+
if (Object.keys(variantStyleKeys).length) {
|
|
3000
|
+
decl.variantStyleKeys = variantStyleKeys;
|
|
3001
|
+
decl.needsWrapperComponent = true;
|
|
3002
|
+
}
|
|
2849
3003
|
if (styleFnFromProps.length) {
|
|
2850
3004
|
decl.styleFnFromProps = styleFnFromProps;
|
|
2851
3005
|
for (const [k, v] of styleFnDecls.entries()) resolvedStyleObjects.set(k, v);
|
|
@@ -3247,26 +3401,61 @@ const withLeadingCommentsOnFirstFunction = (nodes, d) => {
|
|
|
3247
3401
|
* Uses props.children directly instead of destructuring it.
|
|
3248
3402
|
*/
|
|
3249
3403
|
function emitMinimalWrapper(args) {
|
|
3250
|
-
const { j, localName, tagName, propsTypeName, inlineTypeText, emitTypes = false, styleArgs, destructureProps, patternProp, staticAttrs = {} } = args;
|
|
3404
|
+
const { j, localName, tagName, propsTypeName, inlineTypeText, emitTypes = false, styleArgs, destructureProps, allowClassNameProp = false, allowStyleProp = false, includeRest = true, patternProp, defaultAttrs = [], conditionalAttrs = [], invertedBoolAttrs = [], staticAttrs = {}, inlineStyleProps = [] } = args;
|
|
3251
3405
|
const isVoidTag = VOID_TAGS.has(tagName);
|
|
3252
3406
|
const propsParamId = j.identifier("props");
|
|
3253
3407
|
if (emitTypes) if (inlineTypeText) {
|
|
3254
|
-
|
|
3408
|
+
let typeNode;
|
|
3409
|
+
try {
|
|
3410
|
+
typeNode = j(`const x: ${inlineTypeText} = null`).get().node.program.body[0].declarations[0].id.typeAnnotation.typeAnnotation;
|
|
3411
|
+
} catch (e) {
|
|
3412
|
+
throw new Error([
|
|
3413
|
+
`Failed to parse inline wrapper props type for ${localName} (${tagName}).`,
|
|
3414
|
+
`Inline type: ${inlineTypeText}`,
|
|
3415
|
+
`Error: ${e?.message ?? String(e)}`
|
|
3416
|
+
].join("\n"));
|
|
3417
|
+
}
|
|
3255
3418
|
propsParamId.typeAnnotation = j.tsTypeAnnotation(typeNode);
|
|
3256
3419
|
} else propsParamId.typeAnnotation = j.tsTypeAnnotation(j.tsTypeReference(j.identifier(propsTypeName)));
|
|
3257
3420
|
const propsId = j.identifier("props");
|
|
3258
3421
|
const patternProps = [];
|
|
3259
3422
|
if (!isVoidTag) patternProps.push(patternProp("children"));
|
|
3260
|
-
patternProps.push(patternProp("
|
|
3261
|
-
|
|
3423
|
+
if (allowClassNameProp) patternProps.push(patternProp("className"));
|
|
3424
|
+
if (allowStyleProp) patternProps.push(patternProp("style"));
|
|
3425
|
+
for (const name of destructureProps.filter(Boolean)) if (name !== "children" && name !== "style" && name !== "className") patternProps.push(patternProp(name));
|
|
3262
3426
|
const restId = j.identifier("rest");
|
|
3263
|
-
patternProps.push(j.restElement(restId));
|
|
3427
|
+
if (includeRest) patternProps.push(j.restElement(restId));
|
|
3428
|
+
const needsSxVar = allowClassNameProp || allowStyleProp || inlineStyleProps.length > 0;
|
|
3264
3429
|
const stylexPropsCall = j.callExpression(j.memberExpression(j.identifier("stylex"), j.identifier("props")), styleArgs);
|
|
3265
3430
|
const jsxAttrs = [];
|
|
3431
|
+
for (const a of defaultAttrs) {
|
|
3432
|
+
const propExpr = j.memberExpression(propsId, j.identifier(a.jsxProp));
|
|
3433
|
+
const fallback = typeof a.value === "string" ? j.literal(a.value) : typeof a.value === "number" ? j.literal(a.value) : typeof a.value === "boolean" ? j.booleanLiteral(a.value) : j.literal(String(a.value));
|
|
3434
|
+
jsxAttrs.push(j.jsxAttribute(j.jsxIdentifier(a.attrName), j.jsxExpressionContainer(j.logicalExpression("??", propExpr, fallback))));
|
|
3435
|
+
}
|
|
3436
|
+
for (const cond of conditionalAttrs) jsxAttrs.push(j.jsxAttribute(j.jsxIdentifier(cond.attrName), j.jsxExpressionContainer(j.conditionalExpression(j.identifier(cond.jsxProp), j.literal(cond.value), j.identifier("undefined")))));
|
|
3437
|
+
for (const inv of invertedBoolAttrs) jsxAttrs.push(j.jsxAttribute(j.jsxIdentifier(inv.attrName), j.jsxExpressionContainer(j.binaryExpression("!==", j.identifier(inv.jsxProp), j.booleanLiteral(true)))));
|
|
3266
3438
|
for (const [key, value] of Object.entries(staticAttrs)) if (typeof value === "string") jsxAttrs.push(j.jsxAttribute(j.jsxIdentifier(key), j.literal(value)));
|
|
3267
3439
|
else if (typeof value === "boolean") jsxAttrs.push(j.jsxAttribute(j.jsxIdentifier(key), value ? null : j.jsxExpressionContainer(j.literal(false))));
|
|
3268
3440
|
else if (typeof value === "number") jsxAttrs.push(j.jsxAttribute(j.jsxIdentifier(key), j.jsxExpressionContainer(j.literal(value))));
|
|
3269
|
-
|
|
3441
|
+
if (tagName === "button" && destructureProps.includes("disabled")) jsxAttrs.push(j.jsxAttribute(j.jsxIdentifier("disabled"), j.jsxExpressionContainer(j.identifier("disabled"))));
|
|
3442
|
+
if (includeRest) jsxAttrs.push(j.jsxSpreadAttribute(restId));
|
|
3443
|
+
if (!needsSxVar) jsxAttrs.push(j.jsxSpreadAttribute(stylexPropsCall));
|
|
3444
|
+
else {
|
|
3445
|
+
jsxAttrs.push(j.jsxSpreadAttribute(j.identifier("sx")));
|
|
3446
|
+
if (allowClassNameProp) {
|
|
3447
|
+
const mergedClassName = j.callExpression(j.memberExpression(j.callExpression(j.memberExpression(j.arrayExpression([j.memberExpression(j.identifier("sx"), j.identifier("className")), j.identifier("className")]), j.identifier("filter")), [j.identifier("Boolean")]), j.identifier("join")), [j.literal(" ")]);
|
|
3448
|
+
jsxAttrs.push(j.jsxAttribute(j.jsxIdentifier("className"), j.jsxExpressionContainer(mergedClassName)));
|
|
3449
|
+
}
|
|
3450
|
+
if (allowStyleProp || inlineStyleProps.length > 0) {
|
|
3451
|
+
const spreads = [
|
|
3452
|
+
j.spreadElement(j.memberExpression(j.identifier("sx"), j.identifier("style"))),
|
|
3453
|
+
...allowStyleProp ? [j.spreadElement(j.identifier("style"))] : [],
|
|
3454
|
+
...inlineStyleProps.map((p) => j.property("init", j.identifier(p.prop), p.expr))
|
|
3455
|
+
];
|
|
3456
|
+
jsxAttrs.push(j.jsxAttribute(j.jsxIdentifier("style"), j.jsxExpressionContainer(j.objectExpression(spreads))));
|
|
3457
|
+
}
|
|
3458
|
+
}
|
|
3270
3459
|
const openingEl = j.jsxOpeningElement(j.jsxIdentifier(tagName), jsxAttrs, isVoidTag);
|
|
3271
3460
|
const jsx = isVoidTag ? {
|
|
3272
3461
|
type: "JSXElement",
|
|
@@ -3274,11 +3463,57 @@ function emitMinimalWrapper(args) {
|
|
|
3274
3463
|
closingElement: null,
|
|
3275
3464
|
children: []
|
|
3276
3465
|
} : j.jsxElement(openingEl, j.jsxClosingElement(j.jsxIdentifier(tagName)), [j.jsxExpressionContainer(j.identifier("children"))]);
|
|
3277
|
-
const bodyStmts = [
|
|
3466
|
+
const bodyStmts = [];
|
|
3467
|
+
bodyStmts.push(j.variableDeclaration("const", [j.variableDeclarator(j.objectPattern(patternProps), propsId)]));
|
|
3468
|
+
if (needsSxVar) bodyStmts.push(j.variableDeclaration("const", [j.variableDeclarator(j.identifier("sx"), stylexPropsCall)]));
|
|
3469
|
+
bodyStmts.push(j.returnStatement(jsx));
|
|
3278
3470
|
return [j.functionDeclaration(j.identifier(localName), [propsParamId], j.blockStatement(bodyStmts))];
|
|
3279
3471
|
}
|
|
3472
|
+
function parseVariantWhenToAst(j, when) {
|
|
3473
|
+
const trimmed = String(when ?? "").trim();
|
|
3474
|
+
if (!trimmed) return {
|
|
3475
|
+
cond: j.identifier("true"),
|
|
3476
|
+
props: []
|
|
3477
|
+
};
|
|
3478
|
+
if (trimmed.includes("&&")) {
|
|
3479
|
+
const parsed = trimmed.split("&&").map((s) => s.trim()).filter(Boolean).map((p) => parseVariantWhenToAst(j, p));
|
|
3480
|
+
return {
|
|
3481
|
+
cond: parsed.slice(1).reduce((acc, cur) => j.logicalExpression("&&", acc, cur.cond), parsed[0].cond),
|
|
3482
|
+
props: [...new Set(parsed.flatMap((x) => x.props))]
|
|
3483
|
+
};
|
|
3484
|
+
}
|
|
3485
|
+
if (trimmed.startsWith("!(") && trimmed.endsWith(")")) {
|
|
3486
|
+
const innerParsed = parseVariantWhenToAst(j, trimmed.slice(2, -1).trim());
|
|
3487
|
+
return {
|
|
3488
|
+
cond: j.unaryExpression("!", innerParsed.cond),
|
|
3489
|
+
props: innerParsed.props
|
|
3490
|
+
};
|
|
3491
|
+
}
|
|
3492
|
+
if (trimmed.startsWith("!")) {
|
|
3493
|
+
const innerParsed = parseVariantWhenToAst(j, trimmed.slice(1).trim());
|
|
3494
|
+
return {
|
|
3495
|
+
cond: j.unaryExpression("!", innerParsed.cond),
|
|
3496
|
+
props: innerParsed.props
|
|
3497
|
+
};
|
|
3498
|
+
}
|
|
3499
|
+
if (trimmed.includes("===") || trimmed.includes("!==")) {
|
|
3500
|
+
const op = trimmed.includes("!==") ? "!==" : "===";
|
|
3501
|
+
const [lhs, rhsRaw0] = trimmed.split(op).map((s) => s.trim());
|
|
3502
|
+
const rhsRaw = rhsRaw0 ?? "";
|
|
3503
|
+
const rhs = rhsRaw?.startsWith("\"") || rhsRaw?.startsWith("'") ? j.literal(JSON.parse(rhsRaw.replace(/^'/, "\"").replace(/'$/, "\""))) : /^-?\d+(\.\d+)?$/.test(rhsRaw) ? j.literal(Number(rhsRaw)) : j.identifier(rhsRaw);
|
|
3504
|
+
const propName = lhs ?? "";
|
|
3505
|
+
return {
|
|
3506
|
+
cond: j.binaryExpression(op, j.identifier(propName), rhs),
|
|
3507
|
+
props: propName ? [propName] : []
|
|
3508
|
+
};
|
|
3509
|
+
}
|
|
3510
|
+
return {
|
|
3511
|
+
cond: j.identifier(trimmed),
|
|
3512
|
+
props: [trimmed]
|
|
3513
|
+
};
|
|
3514
|
+
}
|
|
3280
3515
|
function emitWrappers(args) {
|
|
3281
|
-
const { root, j, filePath, styledDecls, wrapperNames,
|
|
3516
|
+
const { root, j, filePath, styledDecls, wrapperNames, patternProp, exportedComponents, stylesIdentifier } = args;
|
|
3282
3517
|
const emitTypes = filePath.endsWith(".ts") || filePath.endsWith(".tsx");
|
|
3283
3518
|
const wrapperDecls = styledDecls.filter((d) => d.needsWrapperComponent);
|
|
3284
3519
|
if (wrapperDecls.length === 0) return;
|
|
@@ -3308,6 +3543,68 @@ function emitWrappers(args) {
|
|
|
3308
3543
|
usedAttrsCache.set(localName, attrs);
|
|
3309
3544
|
return attrs;
|
|
3310
3545
|
};
|
|
3546
|
+
const jsxCallsitesCache = /* @__PURE__ */ new Map();
|
|
3547
|
+
const getJsxCallsites = (localName) => {
|
|
3548
|
+
const cached = jsxCallsitesCache.get(localName);
|
|
3549
|
+
if (cached) return cached;
|
|
3550
|
+
const out = { hasAny: root.find(j.JSXElement, { openingElement: { name: {
|
|
3551
|
+
type: "JSXIdentifier",
|
|
3552
|
+
name: localName
|
|
3553
|
+
} } }).size() > 0 || root.find(j.JSXSelfClosingElement, { name: {
|
|
3554
|
+
type: "JSXIdentifier",
|
|
3555
|
+
name: localName
|
|
3556
|
+
} }).size() > 0 };
|
|
3557
|
+
jsxCallsitesCache.set(localName, out);
|
|
3558
|
+
return out;
|
|
3559
|
+
};
|
|
3560
|
+
const jsxChildrenUsageCache = /* @__PURE__ */ new Map();
|
|
3561
|
+
const hasJsxChildrenUsage = (localName) => {
|
|
3562
|
+
const cached = jsxChildrenUsageCache.get(localName);
|
|
3563
|
+
if (cached !== void 0) return cached;
|
|
3564
|
+
const hasChildren = root.find(j.JSXElement, { openingElement: { name: {
|
|
3565
|
+
type: "JSXIdentifier",
|
|
3566
|
+
name: localName
|
|
3567
|
+
} } }).filter((p) => {
|
|
3568
|
+
return (p.node.children ?? []).some((c) => {
|
|
3569
|
+
if (!c) return false;
|
|
3570
|
+
if (c.type === "JSXText") return String(c.value ?? "").trim().length > 0;
|
|
3571
|
+
if (c.type === "JSXExpressionContainer") return c.expression?.type !== "JSXEmptyExpression";
|
|
3572
|
+
return true;
|
|
3573
|
+
});
|
|
3574
|
+
}).size() > 0;
|
|
3575
|
+
jsxChildrenUsageCache.set(localName, hasChildren);
|
|
3576
|
+
return hasChildren;
|
|
3577
|
+
};
|
|
3578
|
+
const usedAsValueCache = /* @__PURE__ */ new Map();
|
|
3579
|
+
const isUsedAsValueInFile = (localName) => {
|
|
3580
|
+
const cached = usedAsValueCache.get(localName);
|
|
3581
|
+
if (cached !== void 0) return cached;
|
|
3582
|
+
const inJsxExpr = root.find(j.JSXExpressionContainer, { expression: {
|
|
3583
|
+
type: "Identifier",
|
|
3584
|
+
name: localName
|
|
3585
|
+
} }).size() > 0;
|
|
3586
|
+
usedAsValueCache.set(localName, inJsxExpr);
|
|
3587
|
+
return inJsxExpr;
|
|
3588
|
+
};
|
|
3589
|
+
/**
|
|
3590
|
+
* Decide whether a wrapper component should accept/merge external `className`/`style`.
|
|
3591
|
+
*
|
|
3592
|
+
* - Exported components and components extended by other styled components set `supportsExternalStyles`.
|
|
3593
|
+
* - Components used as values (passed around) may receive `className`/`style` even without direct JSX callsites.
|
|
3594
|
+
* - For local-only components, only support these props if a callsite actually passes them (or spreads unknown props).
|
|
3595
|
+
*/
|
|
3596
|
+
const shouldAllowClassNameProp = (d) => {
|
|
3597
|
+
if (d.supportsExternalStyles) return true;
|
|
3598
|
+
if (d.usedAsValue) return true;
|
|
3599
|
+
const used = getUsedAttrs(d.localName);
|
|
3600
|
+
return used.has("*") || used.has("className");
|
|
3601
|
+
};
|
|
3602
|
+
const shouldAllowStyleProp = (d) => {
|
|
3603
|
+
if (d.supportsExternalStyles) return true;
|
|
3604
|
+
if (d.usedAsValue) return true;
|
|
3605
|
+
const used = getUsedAttrs(d.localName);
|
|
3606
|
+
return used.has("*") || used.has("style");
|
|
3607
|
+
};
|
|
3311
3608
|
const inputWrapperDecls = wrapperDecls.filter((d) => d.base.kind === "intrinsic" && d.base.tagName === "input" && d.attrWrapper?.kind === "input");
|
|
3312
3609
|
const linkWrapperDecls = wrapperDecls.filter((d) => d.base.kind === "intrinsic" && d.base.tagName === "a" && d.attrWrapper?.kind === "link");
|
|
3313
3610
|
const intrinsicPolymorphicWrapperDecls = wrapperDecls.filter((d) => d.base.kind === "intrinsic" && wrapperNames.has(d.localName));
|
|
@@ -3458,7 +3755,18 @@ function emitWrappers(args) {
|
|
|
3458
3755
|
if (typeExistsInFile(typeName)) return false;
|
|
3459
3756
|
const typeNamePattern = /* @__PURE__ */ new RegExp(`\\b${typeName}\\b`);
|
|
3460
3757
|
if (typeExprText.trim() === typeName || typeNamePattern.test(typeExprText)) return false;
|
|
3461
|
-
const
|
|
3758
|
+
const typeNameWithParams = genericParams ? `${typeName}<${genericParams}>` : typeName;
|
|
3759
|
+
let stmt;
|
|
3760
|
+
try {
|
|
3761
|
+
stmt = j(`${`type ${typeNameWithParams} = ${typeExprText};`}`).get().node.program.body[0];
|
|
3762
|
+
} catch (e) {
|
|
3763
|
+
throw new Error([
|
|
3764
|
+
`Failed to parse emitted props type for ${localName} (${filePath}).`,
|
|
3765
|
+
`Type name: ${typeNameWithParams}`,
|
|
3766
|
+
`Type expr: ${typeExprText}`,
|
|
3767
|
+
`Error: ${e?.message ?? String(e)}`
|
|
3768
|
+
].join("\n"));
|
|
3769
|
+
}
|
|
3462
3770
|
emitted.push(stmt);
|
|
3463
3771
|
return true;
|
|
3464
3772
|
};
|
|
@@ -3469,14 +3777,23 @@ function emitWrappers(args) {
|
|
|
3469
3777
|
const annotatePropsParam = (propsId, localName, inlineTypeText) => {
|
|
3470
3778
|
if (!emitTypes) return;
|
|
3471
3779
|
if (inlineTypeText) {
|
|
3472
|
-
|
|
3780
|
+
let typeNode;
|
|
3781
|
+
try {
|
|
3782
|
+
typeNode = j(`const x: ${inlineTypeText} = null`).get().node.program.body[0].declarations[0].id.typeAnnotation.typeAnnotation;
|
|
3783
|
+
} catch (e) {
|
|
3784
|
+
throw new Error([
|
|
3785
|
+
`Failed to parse inline props param type for ${localName} (${filePath}).`,
|
|
3786
|
+
`Inline type: ${inlineTypeText}`,
|
|
3787
|
+
`Error: ${e?.message ?? String(e)}`
|
|
3788
|
+
].join("\n"));
|
|
3789
|
+
}
|
|
3473
3790
|
propsId.typeAnnotation = j.tsTypeAnnotation(typeNode);
|
|
3474
3791
|
} else propsId.typeAnnotation = j.tsTypeAnnotation(j.tsTypeReference(j.identifier(propsTypeNameFor(localName))));
|
|
3475
3792
|
};
|
|
3476
3793
|
const withChildren = (innerTypeText) => {
|
|
3477
3794
|
const t = innerTypeText.trim();
|
|
3478
3795
|
if (t.startsWith("React.PropsWithChildren<")) return t;
|
|
3479
|
-
if (t.startsWith("React.ComponentProps<") || t.startsWith("React.ComponentPropsWithoutRef<")) return t;
|
|
3796
|
+
if (t.startsWith("React.ComponentProps<") || t.startsWith("React.ComponentPropsWithoutRef<") || t.startsWith("React.HTMLAttributes<") || t.startsWith("React.AnchorHTMLAttributes<") || t.startsWith("React.ButtonHTMLAttributes<") || t.startsWith("React.InputHTMLAttributes<") || t.startsWith("React.ImgHTMLAttributes<") || t.startsWith("React.LabelHTMLAttributes<") || t.startsWith("React.SelectHTMLAttributes<") || t.startsWith("React.TextareaHTMLAttributes<") || /^(Omit|Pick|Partial|Required|Readonly|ReadonlyArray|NonNullable|Extract|Exclude)<\s*React\.ComponentProps(?:WithoutRef)?</.test(t) || /^(Omit|Pick|Partial|Required|Readonly|ReadonlyArray|NonNullable|Extract|Exclude)<\s*React\..*HTMLAttributes</.test(t)) return t;
|
|
3480
3797
|
return `React.PropsWithChildren<${t}>`;
|
|
3481
3798
|
};
|
|
3482
3799
|
const joinIntersection = (...parts) => {
|
|
@@ -3485,19 +3802,152 @@ function emitWrappers(args) {
|
|
|
3485
3802
|
if (xs.length === 1) return xs[0];
|
|
3486
3803
|
return xs.join(" & ");
|
|
3487
3804
|
};
|
|
3805
|
+
const isValidTypeKeyIdentifier = (name) => /^[$A-Z_][0-9A-Z_$]*$/i.test(name);
|
|
3806
|
+
const toTypeKey = (name) => isValidTypeKeyIdentifier(name) ? name : JSON.stringify(name);
|
|
3807
|
+
const reactIntrinsicAttrsType = (tagName) => {
|
|
3808
|
+
switch (tagName) {
|
|
3809
|
+
case "a": return "React.AnchorHTMLAttributes<HTMLAnchorElement>";
|
|
3810
|
+
case "button": return "React.ButtonHTMLAttributes<HTMLButtonElement>";
|
|
3811
|
+
case "div": return "React.HTMLAttributes<HTMLDivElement>";
|
|
3812
|
+
case "input": return "React.InputHTMLAttributes<HTMLInputElement>";
|
|
3813
|
+
case "img": return "React.ImgHTMLAttributes<HTMLImageElement>";
|
|
3814
|
+
case "label": return "React.LabelHTMLAttributes<HTMLLabelElement>";
|
|
3815
|
+
case "select": return "React.SelectHTMLAttributes<HTMLSelectElement>";
|
|
3816
|
+
case "span": return "React.HTMLAttributes<HTMLSpanElement>";
|
|
3817
|
+
case "textarea": return "React.TextareaHTMLAttributes<HTMLTextAreaElement>";
|
|
3818
|
+
default: return "React.HTMLAttributes<HTMLElement>";
|
|
3819
|
+
}
|
|
3820
|
+
};
|
|
3821
|
+
const getExplicitPropNames = (propsType) => {
|
|
3822
|
+
const names = /* @__PURE__ */ new Set();
|
|
3823
|
+
const extractFromLiteral = (literal) => {
|
|
3824
|
+
if (!literal || literal.type !== "TSTypeLiteral") return;
|
|
3825
|
+
for (const member of literal.members ?? []) {
|
|
3826
|
+
if (member?.type !== "TSPropertySignature") continue;
|
|
3827
|
+
const key = member.key;
|
|
3828
|
+
const name = key?.type === "Identifier" ? key.name : key?.type === "StringLiteral" ? key.value : key?.type === "Literal" && typeof key.value === "string" ? key.value : null;
|
|
3829
|
+
if (name) names.add(name);
|
|
3830
|
+
}
|
|
3831
|
+
};
|
|
3832
|
+
const extractFromType = (type) => {
|
|
3833
|
+
if (!type) return;
|
|
3834
|
+
if (type.type === "TSTypeLiteral") extractFromLiteral(type);
|
|
3835
|
+
else if (type.type === "TSIntersectionType") for (const t of type.types ?? []) extractFromType(t);
|
|
3836
|
+
else if (type.type === "TSTypeReference" && type.typeName?.type === "Identifier") {
|
|
3837
|
+
const typeName = type.typeName.name;
|
|
3838
|
+
const interfaceDecl = root.find(j.TSInterfaceDeclaration).filter((p) => p.node.id?.name === typeName);
|
|
3839
|
+
if (interfaceDecl.size() > 0) {
|
|
3840
|
+
const body = interfaceDecl.get().node.body?.body ?? [];
|
|
3841
|
+
for (const member of body) {
|
|
3842
|
+
if (member?.type !== "TSPropertySignature") continue;
|
|
3843
|
+
const key = member.key;
|
|
3844
|
+
const name = key?.type === "Identifier" ? key.name : null;
|
|
3845
|
+
if (name) names.add(name);
|
|
3846
|
+
}
|
|
3847
|
+
}
|
|
3848
|
+
const typeAlias = root.find(j.TSTypeAliasDeclaration).filter((p) => p.node.id?.name === typeName);
|
|
3849
|
+
if (typeAlias.size() > 0) extractFromType(typeAlias.get().node.typeAnnotation);
|
|
3850
|
+
}
|
|
3851
|
+
};
|
|
3852
|
+
extractFromType(propsType);
|
|
3853
|
+
return names;
|
|
3854
|
+
};
|
|
3855
|
+
const inferredIntrinsicPropsTypeText = (args$1) => {
|
|
3856
|
+
const { d, tagName, allowClassNameProp, allowStyleProp, includeAsProp = false, skipProps } = args$1;
|
|
3857
|
+
const used = getUsedAttrs(d.localName);
|
|
3858
|
+
const needsBroadAttrs = used.has("*") || !!d.usedAsValue;
|
|
3859
|
+
const lines = [];
|
|
3860
|
+
if (includeAsProp) lines.push(` as?: React.ElementType;`);
|
|
3861
|
+
if (!needsBroadAttrs) {
|
|
3862
|
+
if (allowClassNameProp) lines.push(` className?: string;`);
|
|
3863
|
+
if (allowStyleProp) lines.push(` style?: React.CSSProperties;`);
|
|
3864
|
+
}
|
|
3865
|
+
for (const attr of [...used].sort()) {
|
|
3866
|
+
if (attr === "*" || attr === "children") continue;
|
|
3867
|
+
if (attr === "as" || attr === "forwardedAs") continue;
|
|
3868
|
+
if (attr === "className" || attr === "style") continue;
|
|
3869
|
+
if (skipProps?.has(attr)) continue;
|
|
3870
|
+
lines.push(` ${toTypeKey(attr)}?: any;`);
|
|
3871
|
+
}
|
|
3872
|
+
const literal = lines.length > 0 ? `{\n${lines.join("\n")}\n}` : "{}";
|
|
3873
|
+
if (!needsBroadAttrs) {
|
|
3874
|
+
if (VOID_TAGS.has(tagName)) {
|
|
3875
|
+
const base$1 = reactIntrinsicAttrsType(tagName);
|
|
3876
|
+
const omitted$1 = [];
|
|
3877
|
+
if (!allowClassNameProp) omitted$1.push("\"className\"");
|
|
3878
|
+
if (!allowStyleProp) omitted$1.push("\"style\"");
|
|
3879
|
+
return omitted$1.length ? `Omit<${base$1}, ${omitted$1.join(" | ")}>` : base$1;
|
|
3880
|
+
}
|
|
3881
|
+
return withChildren(literal);
|
|
3882
|
+
}
|
|
3883
|
+
const base = reactIntrinsicAttrsType(tagName);
|
|
3884
|
+
const omitted = [];
|
|
3885
|
+
if (!allowClassNameProp) omitted.push("\"className\"");
|
|
3886
|
+
if (!allowStyleProp) omitted.push("\"style\"");
|
|
3887
|
+
const composed = joinIntersection(omitted.length ? `Omit<${base}, ${omitted.join(" | ")}>` : base, literal);
|
|
3888
|
+
return VOID_TAGS.has(tagName) ? composed : withChildren(composed);
|
|
3889
|
+
};
|
|
3890
|
+
const inferredComponentWrapperPropsTypeText = (args$1) => {
|
|
3891
|
+
const { d, allowClassNameProp, allowStyleProp, includeAsProp = false, includeChildren = true } = args$1;
|
|
3892
|
+
const lines = [];
|
|
3893
|
+
if (includeAsProp) lines.push(` as?: React.ElementType;`);
|
|
3894
|
+
const literal = lines.length > 0 ? `{\n${lines.join("\n")}\n}` : "{}";
|
|
3895
|
+
const base = `React.ComponentProps<typeof ${d.base.ident}>`;
|
|
3896
|
+
const omitted = [];
|
|
3897
|
+
if (!includeChildren) omitted.push("\"children\"");
|
|
3898
|
+
if (!allowClassNameProp) omitted.push("\"className\"");
|
|
3899
|
+
if (!allowStyleProp) omitted.push("\"style\"");
|
|
3900
|
+
const baseMaybeOmitted = omitted.length ? `Omit<${base}, ${omitted.join(" | ")}>` : base;
|
|
3901
|
+
return includeChildren ? withChildren(joinIntersection(baseMaybeOmitted, literal)) : baseMaybeOmitted;
|
|
3902
|
+
};
|
|
3488
3903
|
const isPropRequiredInPropsTypeLiteral = (propsType, propName) => {
|
|
3489
|
-
|
|
3490
|
-
|
|
3491
|
-
|
|
3492
|
-
|
|
3493
|
-
|
|
3494
|
-
|
|
3904
|
+
const checkInLiteral = (literal) => {
|
|
3905
|
+
if (!literal || literal.type !== "TSTypeLiteral") return null;
|
|
3906
|
+
for (const m of literal.members ?? []) {
|
|
3907
|
+
if (!m || m.type !== "TSPropertySignature") continue;
|
|
3908
|
+
const k = m.key;
|
|
3909
|
+
if ((k?.type === "Identifier" ? k.name : k?.type === "StringLiteral" ? k.value : k?.type === "Literal" && typeof k.value === "string" ? k.value : null) !== propName) continue;
|
|
3910
|
+
return m.optional !== true;
|
|
3911
|
+
}
|
|
3912
|
+
return null;
|
|
3913
|
+
};
|
|
3914
|
+
const checkInInterfaceBody = (body) => {
|
|
3915
|
+
for (const member of body) {
|
|
3916
|
+
if (member?.type !== "TSPropertySignature") continue;
|
|
3917
|
+
const k = member.key;
|
|
3918
|
+
if ((k?.type === "Identifier" ? k.name : null) !== propName) continue;
|
|
3919
|
+
return member.optional !== true;
|
|
3920
|
+
}
|
|
3921
|
+
return null;
|
|
3922
|
+
};
|
|
3923
|
+
if (propsType?.type === "TSTypeLiteral") return checkInLiteral(propsType) === true;
|
|
3924
|
+
if (propsType?.type === "TSTypeReference" && propsType.typeName?.type === "Identifier") {
|
|
3925
|
+
const typeName = propsType.typeName.name;
|
|
3926
|
+
const interfaceDecl = root.find(j.TSInterfaceDeclaration).filter((p) => p.node.id?.name === typeName);
|
|
3927
|
+
if (interfaceDecl.size() > 0) {
|
|
3928
|
+
const result = checkInInterfaceBody(interfaceDecl.get().node.body?.body ?? []);
|
|
3929
|
+
if (result !== null) return result;
|
|
3930
|
+
}
|
|
3931
|
+
const typeAlias = root.find(j.TSTypeAliasDeclaration).filter((p) => p.node.id?.name === typeName);
|
|
3932
|
+
if (typeAlias.size() > 0) {
|
|
3933
|
+
const typeAnnotation = typeAlias.get().node.typeAnnotation;
|
|
3934
|
+
const result = checkInLiteral(typeAnnotation);
|
|
3935
|
+
if (result !== null) return result;
|
|
3936
|
+
}
|
|
3495
3937
|
}
|
|
3496
3938
|
return false;
|
|
3497
3939
|
};
|
|
3498
3940
|
if (inputWrapperDecls.length > 0) for (const d of inputWrapperDecls) {
|
|
3941
|
+
const allowClassNameProp = shouldAllowClassNameProp(d);
|
|
3942
|
+
const allowStyleProp = shouldAllowStyleProp(d);
|
|
3499
3943
|
const explicit = stringifyTsType(d.propsType);
|
|
3500
|
-
emitNamedPropsType(d.localName, explicit ??
|
|
3944
|
+
emitNamedPropsType(d.localName, explicit ?? (() => {
|
|
3945
|
+
const base = "React.InputHTMLAttributes<HTMLInputElement>";
|
|
3946
|
+
const omitted = [];
|
|
3947
|
+
if (!allowClassNameProp) omitted.push("\"className\"");
|
|
3948
|
+
if (!allowStyleProp) omitted.push("\"style\"");
|
|
3949
|
+
return omitted.length > 0 ? `Omit<${base}, ${omitted.join(" | ")}>` : base;
|
|
3950
|
+
})());
|
|
3501
3951
|
needsReactTypeImport = true;
|
|
3502
3952
|
const aw = d.attrWrapper;
|
|
3503
3953
|
const styleArgs = [
|
|
@@ -3505,21 +3955,8 @@ function emitWrappers(args) {
|
|
|
3505
3955
|
...aw.checkboxKey ? [j.logicalExpression("&&", j.binaryExpression("===", j.identifier("type"), j.literal("checkbox")), j.memberExpression(j.identifier(stylesIdentifier), j.identifier(aw.checkboxKey)))] : [],
|
|
3506
3956
|
...aw.radioKey ? [j.logicalExpression("&&", j.binaryExpression("===", j.identifier("type"), j.literal("radio")), j.memberExpression(j.identifier(stylesIdentifier), j.identifier(aw.radioKey)))] : []
|
|
3507
3957
|
];
|
|
3508
|
-
emitted.push(emitTypes ? j.template.statement`
|
|
3509
|
-
|
|
3510
|
-
const { type, className, ...rest } = props;
|
|
3511
|
-
const sx = stylex.props(${styleArgs});
|
|
3512
|
-
return (
|
|
3513
|
-
<input
|
|
3514
|
-
{...sx}
|
|
3515
|
-
className={[sx.className, className].filter(Boolean).join(" ")}
|
|
3516
|
-
type={type}
|
|
3517
|
-
{...rest}
|
|
3518
|
-
/>
|
|
3519
|
-
);
|
|
3520
|
-
}
|
|
3521
|
-
` : j.template.statement`
|
|
3522
|
-
function ${j.identifier(d.localName)}(props) {
|
|
3958
|
+
emitted.push(allowClassNameProp ? emitTypes ? j.template.statement`
|
|
3959
|
+
function ${j.identifier(d.localName)}(props: ${j.identifier(propsTypeNameFor(d.localName))}) {
|
|
3523
3960
|
const { type, className, ...rest } = props;
|
|
3524
3961
|
const sx = stylex.props(${styleArgs});
|
|
3525
3962
|
return (
|
|
@@ -3531,11 +3968,44 @@ function emitWrappers(args) {
|
|
|
3531
3968
|
/>
|
|
3532
3969
|
);
|
|
3533
3970
|
}
|
|
3534
|
-
|
|
3971
|
+
` : j.template.statement`
|
|
3972
|
+
function ${j.identifier(d.localName)}(props) {
|
|
3973
|
+
const { type, className, ...rest } = props;
|
|
3974
|
+
const sx = stylex.props(${styleArgs});
|
|
3975
|
+
return (
|
|
3976
|
+
<input
|
|
3977
|
+
{...sx}
|
|
3978
|
+
className={[sx.className, className].filter(Boolean).join(" ")}
|
|
3979
|
+
type={type}
|
|
3980
|
+
{...rest}
|
|
3981
|
+
/>
|
|
3982
|
+
);
|
|
3983
|
+
}
|
|
3984
|
+
` : emitTypes ? j.template.statement`
|
|
3985
|
+
function ${j.identifier(d.localName)}(props: ${j.identifier(propsTypeNameFor(d.localName))}) {
|
|
3986
|
+
const { type, ...rest } = props;
|
|
3987
|
+
const sx = stylex.props(${styleArgs});
|
|
3988
|
+
return <input type={type} {...rest} {...sx} />;
|
|
3989
|
+
}
|
|
3990
|
+
` : j.template.statement`
|
|
3991
|
+
function ${j.identifier(d.localName)}(props) {
|
|
3992
|
+
const { type, ...rest } = props;
|
|
3993
|
+
const sx = stylex.props(${styleArgs});
|
|
3994
|
+
return <input type={type} {...rest} {...sx} />;
|
|
3995
|
+
}
|
|
3996
|
+
`);
|
|
3535
3997
|
}
|
|
3536
3998
|
if (linkWrapperDecls.length > 0) for (const d of linkWrapperDecls) {
|
|
3999
|
+
const allowClassNameProp = shouldAllowClassNameProp(d);
|
|
4000
|
+
const allowStyleProp = shouldAllowStyleProp(d);
|
|
3537
4001
|
const explicit = stringifyTsType(d.propsType);
|
|
3538
|
-
emitNamedPropsType(d.localName, explicit ?? withChildren(
|
|
4002
|
+
emitNamedPropsType(d.localName, explicit ?? withChildren((() => {
|
|
4003
|
+
const base = "React.AnchorHTMLAttributes<HTMLAnchorElement>";
|
|
4004
|
+
const omitted = [];
|
|
4005
|
+
if (!allowClassNameProp) omitted.push("\"className\"");
|
|
4006
|
+
if (!allowStyleProp) omitted.push("\"style\"");
|
|
4007
|
+
return omitted.length > 0 ? `Omit<${base}, ${omitted.join(" | ")}>` : base;
|
|
4008
|
+
})()));
|
|
3539
4009
|
needsReactTypeImport = true;
|
|
3540
4010
|
const aw = d.attrWrapper;
|
|
3541
4011
|
const styleArgs = [
|
|
@@ -3544,28 +4014,9 @@ function emitWrappers(args) {
|
|
|
3544
4014
|
...aw.httpsKey ? [j.logicalExpression("&&", j.identifier("isHttps"), j.memberExpression(j.identifier(stylesIdentifier), j.identifier(aw.httpsKey)))] : [],
|
|
3545
4015
|
...aw.pdfKey ? [j.logicalExpression("&&", j.identifier("isPdf"), j.memberExpression(j.identifier(stylesIdentifier), j.identifier(aw.pdfKey)))] : []
|
|
3546
4016
|
];
|
|
3547
|
-
emitted.push(emitTypes ? j.template.statement`
|
|
3548
|
-
|
|
3549
|
-
|
|
3550
|
-
const isHttps = href?.startsWith("https");
|
|
3551
|
-
const isPdf = href?.endsWith(".pdf");
|
|
3552
|
-
const isExternal = target === "_blank";
|
|
3553
|
-
const sx = stylex.props(${styleArgs});
|
|
3554
|
-
return (
|
|
3555
|
-
<a
|
|
3556
|
-
{...sx}
|
|
3557
|
-
className={[sx.className, className].filter(Boolean).join(" ")}
|
|
3558
|
-
href={href}
|
|
3559
|
-
target={target}
|
|
3560
|
-
{...rest}
|
|
3561
|
-
>
|
|
3562
|
-
{children}
|
|
3563
|
-
</a>
|
|
3564
|
-
);
|
|
3565
|
-
}
|
|
3566
|
-
` : j.template.statement`
|
|
3567
|
-
function ${j.identifier(d.localName)}(props) {
|
|
3568
|
-
const { href, target, className, children, ...rest } = props;
|
|
4017
|
+
emitted.push(allowClassNameProp ? emitTypes ? j.template.statement`
|
|
4018
|
+
function ${j.identifier(d.localName)}(props: ${j.identifier(propsTypeNameFor(d.localName))}) {
|
|
4019
|
+
const { href, target, className, children, ...rest } = props;
|
|
3569
4020
|
const isHttps = href?.startsWith("https");
|
|
3570
4021
|
const isPdf = href?.endsWith(".pdf");
|
|
3571
4022
|
const isExternal = target === "_blank";
|
|
@@ -3576,73 +4027,125 @@ function emitWrappers(args) {
|
|
|
3576
4027
|
className={[sx.className, className].filter(Boolean).join(" ")}
|
|
3577
4028
|
href={href}
|
|
3578
4029
|
target={target}
|
|
3579
|
-
|
|
4030
|
+
{...rest}
|
|
3580
4031
|
>
|
|
3581
4032
|
{children}
|
|
3582
4033
|
</a>
|
|
3583
4034
|
);
|
|
3584
4035
|
}
|
|
3585
|
-
|
|
3586
|
-
|
|
3587
|
-
|
|
3588
|
-
|
|
3589
|
-
|
|
3590
|
-
|
|
3591
|
-
|
|
3592
|
-
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
|
|
3596
|
-
|
|
3597
|
-
|
|
3598
|
-
|
|
3599
|
-
|
|
3600
|
-
|
|
3601
|
-
|
|
3602
|
-
|
|
3603
|
-
|
|
3604
|
-
|
|
3605
|
-
}], j.blockStatement([j.variableDeclaration("const", [j.variableDeclarator(j.objectPattern([
|
|
3606
|
-
j.property.from({
|
|
3607
|
-
kind: "init",
|
|
3608
|
-
key: j.identifier("as"),
|
|
3609
|
-
value: j.assignmentPattern(j.identifier("Component"), j.tsAsExpression(j.literal(tagName), j.tsTypeReference(j.identifier("C")))),
|
|
3610
|
-
shorthand: false
|
|
3611
|
-
}),
|
|
3612
|
-
patternProp("children"),
|
|
3613
|
-
patternProp("style"),
|
|
3614
|
-
j.restElement(j.identifier("rest"))
|
|
3615
|
-
]), j.identifier("props"))]), j.returnStatement(j.jsxElement(j.jsxOpeningElement(j.jsxIdentifier("Component"), [
|
|
3616
|
-
j.jsxSpreadAttribute(j.identifier("rest")),
|
|
3617
|
-
j.jsxSpreadAttribute(stylexPropsCall),
|
|
3618
|
-
j.jsxAttribute(j.jsxIdentifier("style"), j.jsxExpressionContainer(j.identifier("style")))
|
|
3619
|
-
]), j.jsxClosingElement(j.jsxIdentifier("Component")), [j.jsxExpressionContainer(j.identifier("children"))]))]));
|
|
3620
|
-
funcDecl.typeParameters = j.tsTypeParameterDeclaration([j.tsTypeParameter.from({
|
|
3621
|
-
name: "C",
|
|
3622
|
-
constraint: j.tsTypeReference(j.tsQualifiedName(j.identifier("React"), j.identifier("ElementType"))),
|
|
3623
|
-
default: j.tsLiteralType(j.stringLiteral(tagName))
|
|
3624
|
-
})]);
|
|
3625
|
-
emitted.push(funcDecl);
|
|
3626
|
-
} else emitted.push(emitTypes ? j.template.statement`
|
|
4036
|
+
` : j.template.statement`
|
|
4037
|
+
function ${j.identifier(d.localName)}(props) {
|
|
4038
|
+
const { href, target, className, children, ...rest } = props;
|
|
4039
|
+
const isHttps = href?.startsWith("https");
|
|
4040
|
+
const isPdf = href?.endsWith(".pdf");
|
|
4041
|
+
const isExternal = target === "_blank";
|
|
4042
|
+
const sx = stylex.props(${styleArgs});
|
|
4043
|
+
return (
|
|
4044
|
+
<a
|
|
4045
|
+
{...sx}
|
|
4046
|
+
className={[sx.className, className].filter(Boolean).join(" ")}
|
|
4047
|
+
href={href}
|
|
4048
|
+
target={target}
|
|
4049
|
+
{...rest}
|
|
4050
|
+
>
|
|
4051
|
+
{children}
|
|
4052
|
+
</a>
|
|
4053
|
+
);
|
|
4054
|
+
}
|
|
4055
|
+
` : emitTypes ? j.template.statement`
|
|
3627
4056
|
function ${j.identifier(d.localName)}(props: ${j.identifier(propsTypeNameFor(d.localName))}) {
|
|
3628
|
-
const {
|
|
4057
|
+
const { href, target, children, ...rest } = props;
|
|
4058
|
+
const isHttps = href?.startsWith("https");
|
|
4059
|
+
const isPdf = href?.endsWith(".pdf");
|
|
4060
|
+
const isExternal = target === "_blank";
|
|
4061
|
+
const sx = stylex.props(${styleArgs});
|
|
3629
4062
|
return (
|
|
3630
|
-
<
|
|
3631
|
-
|
|
3632
|
-
|
|
3633
|
-
|
|
3634
|
-
|
|
4063
|
+
<a href={href} target={target} {...rest} {...sx}>
|
|
4064
|
+
{children}
|
|
4065
|
+
</a>
|
|
4066
|
+
);
|
|
4067
|
+
}
|
|
3635
4068
|
` : j.template.statement`
|
|
3636
4069
|
function ${j.identifier(d.localName)}(props) {
|
|
3637
|
-
const {
|
|
4070
|
+
const { href, target, children, ...rest } = props;
|
|
4071
|
+
const isHttps = href?.startsWith("https");
|
|
4072
|
+
const isPdf = href?.endsWith(".pdf");
|
|
4073
|
+
const isExternal = target === "_blank";
|
|
4074
|
+
const sx = stylex.props(${styleArgs});
|
|
3638
4075
|
return (
|
|
3639
|
-
<
|
|
4076
|
+
<a href={href} target={target} {...rest} {...sx}>
|
|
3640
4077
|
{children}
|
|
3641
|
-
</
|
|
4078
|
+
</a>
|
|
3642
4079
|
);
|
|
3643
4080
|
}
|
|
3644
4081
|
`);
|
|
3645
4082
|
}
|
|
4083
|
+
if (intrinsicPolymorphicWrapperDecls.length > 0) for (const d of intrinsicPolymorphicWrapperDecls) {
|
|
4084
|
+
if (d.base.kind !== "intrinsic") continue;
|
|
4085
|
+
const tagName = d.base.tagName;
|
|
4086
|
+
const allowStyleProp = shouldAllowStyleProp(d);
|
|
4087
|
+
const explicit = stringifyTsType(d.propsType);
|
|
4088
|
+
const typeText = (() => {
|
|
4089
|
+
if (explicit) return explicit;
|
|
4090
|
+
const baseMaybeOmitted = `Omit<React.ComponentPropsWithoutRef<C>, "className" | "style">`;
|
|
4091
|
+
const hasAsExpression = getUsedAttrs(d.localName).has("as") && (root.find(j.JSXElement, { openingElement: { name: {
|
|
4092
|
+
type: "JSXIdentifier",
|
|
4093
|
+
name: d.localName
|
|
4094
|
+
} } }).filter((p) => {
|
|
4095
|
+
return (p.node.openingElement?.attributes ?? []).some((a) => a?.type === "JSXAttribute" && a.name?.type === "JSXIdentifier" && a.name.name === "as" && a.value?.type === "JSXExpressionContainer");
|
|
4096
|
+
}).size() > 0 || root.find(j.JSXSelfClosingElement, { name: {
|
|
4097
|
+
type: "JSXIdentifier",
|
|
4098
|
+
name: d.localName
|
|
4099
|
+
} }).filter((p) => {
|
|
4100
|
+
return (p.node.attributes ?? []).some((a) => a?.type === "JSXAttribute" && a.name?.type === "JSXIdentifier" && a.name.name === "as" && a.value?.type === "JSXExpressionContainer");
|
|
4101
|
+
}).size() > 0);
|
|
4102
|
+
return joinIntersection(baseMaybeOmitted, allowStyleProp && hasAsExpression ? "{ as?: C; style?: any }" : "{ as?: C }");
|
|
4103
|
+
})();
|
|
4104
|
+
emitNamedPropsType(d.localName, typeText, `C extends React.ElementType = "${tagName}"`);
|
|
4105
|
+
needsReactTypeImport = true;
|
|
4106
|
+
const styleArgs = [...d.extendsStyleKey ? [j.memberExpression(j.identifier(stylesIdentifier), j.identifier(d.extendsStyleKey))] : [], j.memberExpression(j.identifier(stylesIdentifier), j.identifier(d.styleKey))];
|
|
4107
|
+
const stylexPropsCall = j.callExpression(j.memberExpression(j.identifier("stylex"), j.identifier("props")), styleArgs);
|
|
4108
|
+
const isVoidTag = VOID_TAGS.has(tagName);
|
|
4109
|
+
const propsParamId = j.identifier("props");
|
|
4110
|
+
if (emitTypes) {
|
|
4111
|
+
const tp = j(`function _<C extends React.ElementType = "${tagName}">() { return null }`).get().node.program.body[0].typeParameters;
|
|
4112
|
+
propsParamId.typeAnnotation = j(`const x: ${propsTypeNameFor(d.localName)}<C> = null`).get().node.program.body[0].declarations[0].id.typeAnnotation;
|
|
4113
|
+
propsParamId.typeParameters = tp;
|
|
4114
|
+
}
|
|
4115
|
+
const propsId = j.identifier("props");
|
|
4116
|
+
const childrenId = j.identifier("children");
|
|
4117
|
+
const restId = j.identifier("rest");
|
|
4118
|
+
const styleId = j.identifier("style");
|
|
4119
|
+
const declStmt = j.variableDeclaration("const", [j.variableDeclarator(j.objectPattern([
|
|
4120
|
+
j.property.from({
|
|
4121
|
+
kind: "init",
|
|
4122
|
+
key: j.identifier("as"),
|
|
4123
|
+
value: j.assignmentPattern(j.identifier("Component"), j.literal(tagName)),
|
|
4124
|
+
shorthand: false
|
|
4125
|
+
}),
|
|
4126
|
+
...isVoidTag ? [] : [patternProp("children", childrenId)],
|
|
4127
|
+
...allowStyleProp ? [patternProp("style", styleId)] : [],
|
|
4128
|
+
j.restElement(restId)
|
|
4129
|
+
]), propsId)]);
|
|
4130
|
+
const attrs = [
|
|
4131
|
+
j.jsxSpreadAttribute(restId),
|
|
4132
|
+
j.jsxSpreadAttribute(stylexPropsCall),
|
|
4133
|
+
...allowStyleProp ? [j.jsxAttribute(j.jsxIdentifier("style"), j.jsxExpressionContainer(styleId))] : []
|
|
4134
|
+
];
|
|
4135
|
+
const openingEl = j.jsxOpeningElement(j.jsxIdentifier("Component"), attrs, isVoidTag);
|
|
4136
|
+
const jsx = isVoidTag ? {
|
|
4137
|
+
type: "JSXElement",
|
|
4138
|
+
openingElement: openingEl,
|
|
4139
|
+
closingElement: null,
|
|
4140
|
+
children: []
|
|
4141
|
+
} : j.jsxElement(openingEl, j.jsxClosingElement(j.jsxIdentifier("Component")), [j.jsxExpressionContainer(childrenId)]);
|
|
4142
|
+
const fn = j.functionDeclaration(j.identifier(d.localName), [propsParamId], j.blockStatement([declStmt, j.returnStatement(jsx)]));
|
|
4143
|
+
if (propsParamId.typeParameters) {
|
|
4144
|
+
fn.typeParameters = propsParamId.typeParameters;
|
|
4145
|
+
propsParamId.typeParameters = void 0;
|
|
4146
|
+
}
|
|
4147
|
+
emitted.push(fn);
|
|
4148
|
+
}
|
|
3646
4149
|
const enumVariantWrappers = wrapperDecls.filter((d) => d.enumVariant);
|
|
3647
4150
|
if (enumVariantWrappers.length > 0) for (const d of enumVariantWrappers) {
|
|
3648
4151
|
if (!d.enumVariant) continue;
|
|
@@ -3652,7 +4155,7 @@ function emitWrappers(args) {
|
|
|
3652
4155
|
if (!primary || !secondary) continue;
|
|
3653
4156
|
const explicit = stringifyTsType(d.propsType);
|
|
3654
4157
|
if (explicit) {
|
|
3655
|
-
emitNamedPropsType(d.localName, explicit);
|
|
4158
|
+
emitNamedPropsType(d.localName, withChildren(explicit));
|
|
3656
4159
|
needsReactTypeImport = true;
|
|
3657
4160
|
} else {
|
|
3658
4161
|
const hasNeq = cases.some((c) => c.kind === "neq");
|
|
@@ -3666,14 +4169,7 @@ function emitWrappers(args) {
|
|
|
3666
4169
|
const propsId = j.identifier("props");
|
|
3667
4170
|
const variantId = j.identifier(propName);
|
|
3668
4171
|
const childrenId = j.identifier("children");
|
|
3669
|
-
const
|
|
3670
|
-
const restId = j.identifier("rest");
|
|
3671
|
-
const declStmt = j.variableDeclaration("const", [j.variableDeclarator(j.objectPattern([
|
|
3672
|
-
patternProp(propName, variantId),
|
|
3673
|
-
patternProp("children", childrenId),
|
|
3674
|
-
patternProp("className", classNameId),
|
|
3675
|
-
j.restElement(restId)
|
|
3676
|
-
]), propsId)]);
|
|
4172
|
+
const declStmt = j.variableDeclaration("const", [j.variableDeclarator(j.objectPattern([patternProp(propName, variantId), patternProp("children", childrenId)]), propsId)]);
|
|
3677
4173
|
const base = j.memberExpression(j.identifier(stylesIdentifier), j.identifier(baseKey));
|
|
3678
4174
|
const condPrimary = j.binaryExpression("===", variantId, j.literal(primary.whenValue));
|
|
3679
4175
|
const condSecondary = secondary.kind === "neq" ? j.binaryExpression("!==", variantId, j.literal(secondary.whenValue)) : j.binaryExpression("===", variantId, j.literal(secondary.whenValue));
|
|
@@ -3682,12 +4178,7 @@ function emitWrappers(args) {
|
|
|
3682
4178
|
j.logicalExpression("&&", condPrimary, j.memberExpression(j.identifier(stylesIdentifier), j.identifier(primary.styleKey))),
|
|
3683
4179
|
j.logicalExpression("&&", condSecondary, j.memberExpression(j.identifier(stylesIdentifier), j.identifier(secondary.styleKey)))
|
|
3684
4180
|
]))]);
|
|
3685
|
-
const
|
|
3686
|
-
const openingEl = j.jsxOpeningElement(j.jsxIdentifier("div"), [
|
|
3687
|
-
j.jsxSpreadAttribute(j.identifier("sx")),
|
|
3688
|
-
j.jsxAttribute(j.jsxIdentifier("className"), j.jsxExpressionContainer(mergedClassName)),
|
|
3689
|
-
j.jsxSpreadAttribute(restId)
|
|
3690
|
-
], false);
|
|
4181
|
+
const openingEl = j.jsxOpeningElement(j.jsxIdentifier("div"), [j.jsxSpreadAttribute(j.identifier("sx"))], false);
|
|
3691
4182
|
const jsx = j.jsxElement(openingEl, j.jsxClosingElement(j.jsxIdentifier("div")), [j.jsxExpressionContainer(childrenId)]);
|
|
3692
4183
|
emitted.push(withLeadingComments(j.functionDeclaration(j.identifier(d.localName), [propsParamId], j.blockStatement([
|
|
3693
4184
|
declStmt,
|
|
@@ -3698,9 +4189,14 @@ function emitWrappers(args) {
|
|
|
3698
4189
|
for (const d of shouldForwardPropWrapperDecls) {
|
|
3699
4190
|
if (d.base.kind !== "intrinsic") continue;
|
|
3700
4191
|
const tagName = d.base.tagName;
|
|
3701
|
-
const
|
|
4192
|
+
const allowClassNameProp = shouldAllowClassNameProp(d);
|
|
4193
|
+
const allowStyleProp = shouldAllowStyleProp(d);
|
|
3702
4194
|
const extraProps = /* @__PURE__ */ new Set();
|
|
3703
4195
|
for (const p of d.shouldForwardProp?.dropProps ?? []) if (p) extraProps.add(p);
|
|
4196
|
+
for (const when of Object.keys(d.variantStyleKeys ?? {})) {
|
|
4197
|
+
const { props } = parseVariantWhenToAst(j, when);
|
|
4198
|
+
for (const p of props) if (p) extraProps.add(p);
|
|
4199
|
+
}
|
|
3704
4200
|
for (const p of d.styleFnFromProps ?? []) if (p?.jsxProp) extraProps.add(p.jsxProp);
|
|
3705
4201
|
const dropPrefixFromFilter = d.shouldForwardProp?.dropPrefix;
|
|
3706
4202
|
const usedAttrs = getUsedAttrs(d.localName);
|
|
@@ -3709,6 +4205,7 @@ function emitWrappers(args) {
|
|
|
3709
4205
|
const knownPrefixProps = dropPrefixFromFilter ? [...extraProps].filter((p) => p.startsWith(dropPrefixFromFilter) && isValidIdentifier(p)) : [];
|
|
3710
4206
|
const knownPrefixPropsSet = new Set(knownPrefixProps);
|
|
3711
4207
|
const explicit = stringifyTsType(d.propsType);
|
|
4208
|
+
const explicitPropNames = d.propsType ? getExplicitPropNames(d.propsType) : /* @__PURE__ */ new Set();
|
|
3712
4209
|
const extrasTypeText = (() => {
|
|
3713
4210
|
if (explicit && explicit.trim()) return dropPrefixFromFilter === "$" && shouldAllowAnyPrefixProps ? `${explicit} & { [K in \`$\${string}\`]?: any }` : explicit;
|
|
3714
4211
|
const lines = [];
|
|
@@ -3717,29 +4214,51 @@ function emitWrappers(args) {
|
|
|
3717
4214
|
if (dropPrefixFromFilter === "$") return `${literal} & { [K in \`$\${string}\`]?: any }`;
|
|
3718
4215
|
return literal;
|
|
3719
4216
|
})();
|
|
3720
|
-
const
|
|
3721
|
-
|
|
3722
|
-
|
|
4217
|
+
const finalTypeText = (() => {
|
|
4218
|
+
if (explicit) {
|
|
4219
|
+
if (VOID_TAGS.has(tagName)) {
|
|
4220
|
+
const base$1 = reactIntrinsicAttrsType(tagName);
|
|
4221
|
+
const omitted$1 = [];
|
|
4222
|
+
if (!allowClassNameProp) omitted$1.push("\"className\"");
|
|
4223
|
+
if (!allowStyleProp) omitted$1.push("\"style\"");
|
|
4224
|
+
return joinIntersection(omitted$1.length ? `Omit<${base$1}, ${omitted$1.join(" | ")}>` : base$1, extrasTypeText);
|
|
4225
|
+
}
|
|
4226
|
+
if (!d.shouldForwardPropFromWithConfig) {
|
|
4227
|
+
const supplementalLines = [];
|
|
4228
|
+
if (allowClassNameProp) supplementalLines.push(` className?: string;`);
|
|
4229
|
+
if (allowStyleProp) supplementalLines.push(` style?: React.CSSProperties;`);
|
|
4230
|
+
return withChildren(joinIntersection(extrasTypeText, supplementalLines.length > 0 ? `{\n${supplementalLines.join("\n")}\n}` : "{}"));
|
|
4231
|
+
}
|
|
4232
|
+
const base = `React.ComponentProps<"${tagName}">`;
|
|
4233
|
+
const omitted = [];
|
|
4234
|
+
if (!allowClassNameProp) omitted.push("\"className\"");
|
|
4235
|
+
if (!allowStyleProp) omitted.push("\"style\"");
|
|
4236
|
+
return joinIntersection(omitted.length ? `Omit<${base}, ${omitted.join(" | ")}>` : base, extrasTypeText);
|
|
4237
|
+
}
|
|
4238
|
+
const inferred = inferredIntrinsicPropsTypeText({
|
|
4239
|
+
d,
|
|
4240
|
+
tagName,
|
|
4241
|
+
allowClassNameProp,
|
|
4242
|
+
allowStyleProp,
|
|
4243
|
+
skipProps: explicitPropNames
|
|
4244
|
+
});
|
|
4245
|
+
return VOID_TAGS.has(tagName) ? inferred : withChildren(inferred);
|
|
4246
|
+
})();
|
|
3723
4247
|
if (!emitNamedPropsType(d.localName, finalTypeText) && explicit) {
|
|
3724
4248
|
const propsTypeName = propsTypeNameFor(d.localName);
|
|
3725
|
-
|
|
4249
|
+
const extendBaseTypeText = (() => {
|
|
4250
|
+
const base = reactIntrinsicAttrsType(tagName);
|
|
4251
|
+
const omitted = [];
|
|
4252
|
+
if (!allowClassNameProp) omitted.push("\"className\"");
|
|
4253
|
+
if (!allowStyleProp) omitted.push("\"style\"");
|
|
4254
|
+
return omitted.length ? `Omit<${base}, ${omitted.join(" | ")}>` : base;
|
|
4255
|
+
})();
|
|
4256
|
+
if (!extendExistingInterface(propsTypeName, extendBaseTypeText)) extendExistingTypeAlias(propsTypeName, extendBaseTypeText);
|
|
3726
4257
|
}
|
|
3727
4258
|
needsReactTypeImport = true;
|
|
3728
4259
|
const styleArgs = [...d.extendsStyleKey ? [j.memberExpression(j.identifier(stylesIdentifier), j.identifier(d.extendsStyleKey))] : [], j.memberExpression(j.identifier(stylesIdentifier), j.identifier(d.styleKey))];
|
|
3729
4260
|
if (d.variantStyleKeys) for (const [when, variantKey] of Object.entries(d.variantStyleKeys)) {
|
|
3730
|
-
|
|
3731
|
-
const trimmed = when.trim();
|
|
3732
|
-
if (trimmed.startsWith("!(") && trimmed.endsWith(")")) {
|
|
3733
|
-
const inner = trimmed.slice(2, -1).trim();
|
|
3734
|
-
cond = j.unaryExpression("!", j.identifier(inner));
|
|
3735
|
-
} else if (trimmed.startsWith("!")) cond = j.unaryExpression("!", j.identifier(trimmed.slice(1)));
|
|
3736
|
-
else if (trimmed.includes("===") || trimmed.includes("!==")) {
|
|
3737
|
-
const op = trimmed.includes("!==") ? "!==" : "===";
|
|
3738
|
-
const [lhs, rhsRaw0] = trimmed.split(op).map((s) => s.trim());
|
|
3739
|
-
const rhsRaw = rhsRaw0 ?? "";
|
|
3740
|
-
const rhs = rhsRaw?.startsWith("\"") || rhsRaw?.startsWith("'") ? j.literal(JSON.parse(rhsRaw.replace(/^'/, "\"").replace(/'$/, "\""))) : /^-?\d+(\.\d+)?$/.test(rhsRaw) ? j.literal(Number(rhsRaw)) : j.identifier(rhsRaw);
|
|
3741
|
-
cond = j.binaryExpression(op, j.identifier(lhs ?? ""), rhs);
|
|
3742
|
-
} else cond = j.identifier(trimmed);
|
|
4261
|
+
const { cond } = parseVariantWhenToAst(j, when);
|
|
3743
4262
|
styleArgs.push(j.logicalExpression("&&", cond, j.memberExpression(j.identifier(stylesIdentifier), j.identifier(variantKey))));
|
|
3744
4263
|
}
|
|
3745
4264
|
const styleFnPairs = d.styleFnFromProps ?? [];
|
|
@@ -3763,31 +4282,25 @@ function emitWrappers(args) {
|
|
|
3763
4282
|
const styleId = j.identifier("style");
|
|
3764
4283
|
const restId = j.identifier("rest");
|
|
3765
4284
|
const isVoidTag = tagName === "input";
|
|
3766
|
-
const
|
|
3767
|
-
|
|
4285
|
+
const { hasAny: hasLocalUsage } = getJsxCallsites(d.localName);
|
|
4286
|
+
const shouldIncludeRest = isUsedAsValueInFile(d.localName) || hasLocalUsage && usedAttrs.has("*") || hasLocalUsage && [...usedAttrs].some((n) => {
|
|
4287
|
+
if (n === "children" || n === "className" || n === "style" || n === "as" || n === "forwardedAs") return false;
|
|
4288
|
+
return !destructureParts.includes(n);
|
|
4289
|
+
});
|
|
4290
|
+
const includeRest = !(!dropPrefix && dropProps.length > 0 && dropProps.every((p) => p.startsWith("$")) && !usedAttrs.has("*") && [...usedAttrs].every((n) => n === "children" || dropProps.includes(n))) && shouldIncludeRest;
|
|
4291
|
+
if (!allowClassNameProp && !allowStyleProp) {
|
|
3768
4292
|
const isVoid = VOID_TAGS.has(tagName);
|
|
3769
4293
|
const patternProps$1 = [
|
|
3770
4294
|
...isVoid ? [] : [patternProp("children", childrenId)],
|
|
3771
|
-
patternProp("className", classNameId),
|
|
3772
|
-
patternProp("style", styleId),
|
|
3773
4295
|
...destructureParts.filter(Boolean).map((name) => patternProp(name)),
|
|
3774
|
-
...
|
|
4296
|
+
...includeRest ? [j.restElement(restId)] : []
|
|
3775
4297
|
];
|
|
3776
4298
|
const declStmt$1 = j.variableDeclaration("const", [j.variableDeclarator(j.objectPattern(patternProps$1), propsId)]);
|
|
3777
|
-
const cleanupPrefixStmt$1 = dropPrefix && shouldAllowAnyPrefixProps ? j.forOfStatement(j.variableDeclaration("const", [j.variableDeclarator(j.identifier("k"), null)]), j.callExpression(j.memberExpression(j.identifier("Object"), j.identifier("keys")), [restId]), j.blockStatement([j.ifStatement(j.callExpression(j.memberExpression(j.identifier("k"), j.identifier("startsWith")), [j.literal(dropPrefix)]), j.expressionStatement(j.unaryExpression("delete", j.memberExpression(restId, j.identifier("k"), true))))])) : null;
|
|
3778
|
-
const
|
|
3779
|
-
const
|
|
3780
|
-
|
|
3781
|
-
const openingEl$1 = j.jsxOpeningElement(j.jsxIdentifier(tagName),
|
|
3782
|
-
j.jsxSpreadAttribute(j.identifier("sx")),
|
|
3783
|
-
j.jsxAttribute(j.jsxIdentifier("className"), j.jsxExpressionContainer(mergedClassName$1)),
|
|
3784
|
-
...d.inlineStyleProps && d.inlineStyleProps.length ? [j.jsxAttribute(j.jsxIdentifier("style"), j.jsxExpressionContainer(j.objectExpression([
|
|
3785
|
-
j.spreadElement(j.memberExpression(j.identifier("sx"), j.identifier("style"))),
|
|
3786
|
-
j.spreadElement(styleId),
|
|
3787
|
-
...d.inlineStyleProps.map((p) => j.property("init", j.identifier(p.prop), p.expr))
|
|
3788
|
-
])))] : [j.jsxAttribute(j.jsxIdentifier("style"), j.jsxExpressionContainer(j.objectExpression([j.spreadElement(j.memberExpression(j.identifier("sx"), j.identifier("style"))), j.spreadElement(styleId)])))],
|
|
3789
|
-
...shouldOmitRestSpread ? [] : [j.jsxSpreadAttribute(restId)]
|
|
3790
|
-
], false);
|
|
4299
|
+
const cleanupPrefixStmt$1 = dropPrefix && shouldAllowAnyPrefixProps && includeRest ? j.forOfStatement(j.variableDeclaration("const", [j.variableDeclarator(j.identifier("k"), null)]), j.callExpression(j.memberExpression(j.identifier("Object"), j.identifier("keys")), [restId]), j.blockStatement([j.ifStatement(j.callExpression(j.memberExpression(j.identifier("k"), j.identifier("startsWith")), [j.literal(dropPrefix)]), j.expressionStatement(j.unaryExpression("delete", j.memberExpression(restId, j.identifier("k"), true))))])) : null;
|
|
4300
|
+
const sxDecl$1 = j.variableDeclaration("const", [j.variableDeclarator(j.identifier("sx"), j.callExpression(j.memberExpression(j.identifier("stylex"), j.identifier("props")), styleArgs))]);
|
|
4301
|
+
const openingAttrs$1 = [...includeRest ? [j.jsxSpreadAttribute(restId)] : [], j.jsxSpreadAttribute(j.identifier("sx"))];
|
|
4302
|
+
if (d.inlineStyleProps && d.inlineStyleProps.length) openingAttrs$1.push(j.jsxAttribute(j.jsxIdentifier("style"), j.jsxExpressionContainer(j.objectExpression([j.spreadElement(j.memberExpression(j.identifier("sx"), j.identifier("style"))), ...d.inlineStyleProps.map((p) => j.property("init", j.identifier(p.prop), p.expr))]))));
|
|
4303
|
+
const openingEl$1 = j.jsxOpeningElement(j.jsxIdentifier(tagName), openingAttrs$1, false);
|
|
3791
4304
|
const jsx$1 = isVoid ? {
|
|
3792
4305
|
type: "JSXElement",
|
|
3793
4306
|
openingElement: {
|
|
@@ -3805,26 +4318,27 @@ function emitWrappers(args) {
|
|
|
3805
4318
|
continue;
|
|
3806
4319
|
}
|
|
3807
4320
|
const patternProps = [
|
|
3808
|
-
patternProp("className", classNameId),
|
|
4321
|
+
...allowClassNameProp ? [patternProp("className", classNameId)] : [],
|
|
3809
4322
|
...isVoidTag ? [] : [patternProp("children", childrenId)],
|
|
3810
|
-
patternProp("style", styleId),
|
|
4323
|
+
...allowStyleProp ? [patternProp("style", styleId)] : [],
|
|
3811
4324
|
...destructureParts.filter(Boolean).map((name) => patternProp(name)),
|
|
3812
|
-
...
|
|
4325
|
+
...includeRest ? [j.restElement(restId)] : []
|
|
3813
4326
|
];
|
|
3814
4327
|
const declStmt = j.variableDeclaration("const", [j.variableDeclarator(j.objectPattern(patternProps), propsId)]);
|
|
3815
|
-
const cleanupPrefixStmt = dropPrefix && shouldAllowAnyPrefixProps ? j.forOfStatement(j.variableDeclaration("const", [j.variableDeclarator(j.identifier("k"), null)]), j.callExpression(j.memberExpression(j.identifier("Object"), j.identifier("keys")), [restId]), j.blockStatement([j.ifStatement(j.callExpression(j.memberExpression(j.identifier("k"), j.identifier("startsWith")), [j.literal(dropPrefix)]), j.expressionStatement(j.unaryExpression("delete", j.memberExpression(restId, j.identifier("k"), true))))])) : null;
|
|
4328
|
+
const cleanupPrefixStmt = dropPrefix && shouldAllowAnyPrefixProps && includeRest ? j.forOfStatement(j.variableDeclaration("const", [j.variableDeclarator(j.identifier("k"), null)]), j.callExpression(j.memberExpression(j.identifier("Object"), j.identifier("keys")), [restId]), j.blockStatement([j.ifStatement(j.callExpression(j.memberExpression(j.identifier("k"), j.identifier("startsWith")), [j.literal(dropPrefix)]), j.expressionStatement(j.unaryExpression("delete", j.memberExpression(restId, j.identifier("k"), true))))])) : null;
|
|
3816
4329
|
const sxDecl = j.variableDeclaration("const", [j.variableDeclarator(j.identifier("sx"), j.callExpression(j.memberExpression(j.identifier("stylex"), j.identifier("props")), styleArgs))]);
|
|
3817
|
-
const
|
|
3818
|
-
|
|
3819
|
-
j.
|
|
3820
|
-
j.jsxAttribute(j.jsxIdentifier("className"), j.jsxExpressionContainer(mergedClassName))
|
|
3821
|
-
|
|
3822
|
-
|
|
3823
|
-
|
|
3824
|
-
|
|
3825
|
-
|
|
3826
|
-
|
|
3827
|
-
|
|
4330
|
+
const openingAttrs = [j.jsxSpreadAttribute(j.identifier("sx"))];
|
|
4331
|
+
if (allowClassNameProp) {
|
|
4332
|
+
const mergedClassName = j.callExpression(j.memberExpression(j.callExpression(j.memberExpression(j.arrayExpression([j.memberExpression(j.identifier("sx"), j.identifier("className")), classNameId]), j.identifier("filter")), [j.identifier("Boolean")]), j.identifier("join")), [j.literal(" ")]);
|
|
4333
|
+
openingAttrs.push(j.jsxAttribute(j.jsxIdentifier("className"), j.jsxExpressionContainer(mergedClassName)));
|
|
4334
|
+
}
|
|
4335
|
+
if (allowStyleProp || d.inlineStyleProps && d.inlineStyleProps.length) openingAttrs.push(j.jsxAttribute(j.jsxIdentifier("style"), j.jsxExpressionContainer(j.objectExpression([
|
|
4336
|
+
j.spreadElement(j.memberExpression(j.identifier("sx"), j.identifier("style"))),
|
|
4337
|
+
...allowStyleProp ? [j.spreadElement(styleId)] : [],
|
|
4338
|
+
...d.inlineStyleProps && d.inlineStyleProps.length ? d.inlineStyleProps.map((p) => j.property("init", j.identifier(p.prop), p.expr)) : []
|
|
4339
|
+
]))));
|
|
4340
|
+
if (includeRest) openingAttrs.push(j.jsxSpreadAttribute(restId));
|
|
4341
|
+
const openingEl = j.jsxOpeningElement(j.jsxIdentifier(tagName), openingAttrs, false);
|
|
3828
4342
|
const jsx = isVoidTag ? {
|
|
3829
4343
|
type: "JSXElement",
|
|
3830
4344
|
openingElement: {
|
|
@@ -3856,6 +4370,8 @@ function emitWrappers(args) {
|
|
|
3856
4370
|
if (d.base.kind !== "intrinsic") continue;
|
|
3857
4371
|
const tagName = d.base.tagName;
|
|
3858
4372
|
const supportsExternalStyles = d.supportsExternalStyles ?? false;
|
|
4373
|
+
const allowClassNameProp = shouldAllowClassNameProp(d);
|
|
4374
|
+
const allowStyleProp = shouldAllowStyleProp(d);
|
|
3859
4375
|
{
|
|
3860
4376
|
const explicit = stringifyTsType(d.propsType);
|
|
3861
4377
|
const baseTypeText = (() => {
|
|
@@ -3863,8 +4379,14 @@ function emitWrappers(args) {
|
|
|
3863
4379
|
const used = getUsedAttrs(d.localName);
|
|
3864
4380
|
if (used.has("*")) return true;
|
|
3865
4381
|
return used.size > 0;
|
|
3866
|
-
})() ?
|
|
3867
|
-
|
|
4382
|
+
})() ? inferredIntrinsicPropsTypeText({
|
|
4383
|
+
d,
|
|
4384
|
+
tagName,
|
|
4385
|
+
allowClassNameProp,
|
|
4386
|
+
allowStyleProp
|
|
4387
|
+
}) : "{}";
|
|
4388
|
+
const typeWithChildren = !explicit && !VOID_TAGS.has(tagName) ? withChildren(baseTypeText) : baseTypeText;
|
|
4389
|
+
emitNamedPropsType(d.localName, explicit ?? typeWithChildren);
|
|
3868
4390
|
needsReactTypeImport = true;
|
|
3869
4391
|
}
|
|
3870
4392
|
const styleArgs = [...d.extendsStyleKey ? [j.memberExpression(j.identifier(stylesIdentifier), j.identifier(d.extendsStyleKey))] : [], j.memberExpression(j.identifier(stylesIdentifier), j.identifier(d.styleKey))];
|
|
@@ -3876,7 +4398,9 @@ function emitWrappers(args) {
|
|
|
3876
4398
|
const styleId = j.identifier("style");
|
|
3877
4399
|
const restId = j.identifier("rest");
|
|
3878
4400
|
const isVoidTag = VOID_TAGS.has(tagName);
|
|
3879
|
-
if (!
|
|
4401
|
+
if (!allowClassNameProp && !allowStyleProp) {
|
|
4402
|
+
const usedAttrs = getUsedAttrs(d.localName);
|
|
4403
|
+
const includeRest = usedAttrs.has("*") || !!d.usedAsValue || usedAttrs.size > 0;
|
|
3880
4404
|
emitted.push(...withLeadingCommentsOnFirstFunction(emitMinimalWrapper({
|
|
3881
4405
|
j,
|
|
3882
4406
|
localName: d.localName,
|
|
@@ -3885,7 +4409,11 @@ function emitWrappers(args) {
|
|
|
3885
4409
|
emitTypes,
|
|
3886
4410
|
styleArgs,
|
|
3887
4411
|
destructureProps: [],
|
|
3888
|
-
|
|
4412
|
+
allowClassNameProp: false,
|
|
4413
|
+
allowStyleProp: false,
|
|
4414
|
+
includeRest,
|
|
4415
|
+
patternProp,
|
|
4416
|
+
inlineStyleProps: d.inlineStyleProps ?? []
|
|
3889
4417
|
}), d));
|
|
3890
4418
|
continue;
|
|
3891
4419
|
}
|
|
@@ -3929,7 +4457,13 @@ function emitWrappers(args) {
|
|
|
3929
4457
|
extras.push(`${sw.propAdjacent}?: boolean;`);
|
|
3930
4458
|
if (sw.propAfter) extras.push(`${sw.propAfter}?: boolean;`);
|
|
3931
4459
|
const extraType = `{ ${extras.join(" ")} }`;
|
|
3932
|
-
|
|
4460
|
+
const baseTypeText = inferredIntrinsicPropsTypeText({
|
|
4461
|
+
d,
|
|
4462
|
+
tagName: "div",
|
|
4463
|
+
allowClassNameProp: shouldAllowClassNameProp(d),
|
|
4464
|
+
allowStyleProp: shouldAllowStyleProp(d)
|
|
4465
|
+
});
|
|
4466
|
+
emitNamedPropsType(d.localName, explicit ?? joinIntersection(baseTypeText, extraType));
|
|
3933
4467
|
needsReactTypeImport = true;
|
|
3934
4468
|
}
|
|
3935
4469
|
const propsParamId = j.identifier("props");
|
|
@@ -3978,16 +4512,30 @@ function emitWrappers(args) {
|
|
|
3978
4512
|
for (const d of simpleExportedIntrinsicWrappers) {
|
|
3979
4513
|
if (d.base.kind !== "intrinsic") continue;
|
|
3980
4514
|
const tagName = d.base.tagName;
|
|
3981
|
-
const
|
|
4515
|
+
const allowClassNameProp = shouldAllowClassNameProp(d);
|
|
4516
|
+
const allowStyleProp = shouldAllowStyleProp(d);
|
|
3982
4517
|
let inlineTypeText;
|
|
3983
4518
|
{
|
|
3984
4519
|
const explicit = stringifyTsType(d.propsType);
|
|
3985
|
-
const baseTypeText =
|
|
3986
|
-
|
|
4520
|
+
const baseTypeText = inferredIntrinsicPropsTypeText({
|
|
4521
|
+
d,
|
|
4522
|
+
tagName,
|
|
4523
|
+
allowClassNameProp,
|
|
4524
|
+
allowStyleProp,
|
|
4525
|
+
skipProps: d.propsType ? getExplicitPropNames(d.propsType) : /* @__PURE__ */ new Set()
|
|
4526
|
+
});
|
|
4527
|
+
const extendBaseTypeText = (() => {
|
|
4528
|
+
const base = reactIntrinsicAttrsType(tagName);
|
|
4529
|
+
const omitted = [];
|
|
4530
|
+
if (!allowClassNameProp) omitted.push("\"className\"");
|
|
4531
|
+
if (!allowStyleProp) omitted.push("\"style\"");
|
|
4532
|
+
return omitted.length ? `Omit<${base}, ${omitted.join(" | ")}>` : base;
|
|
4533
|
+
})();
|
|
4534
|
+
const typeText = explicit ? VOID_TAGS.has(tagName) ? joinIntersection(extendBaseTypeText, explicit) : withChildren(explicit) : baseTypeText;
|
|
3987
4535
|
if (!emitNamedPropsType(d.localName, typeText) && explicit) {
|
|
3988
4536
|
const propsTypeName = propsTypeNameFor(d.localName);
|
|
3989
|
-
if (!extendExistingInterface(propsTypeName,
|
|
3990
|
-
if (!extendExistingTypeAlias(propsTypeName,
|
|
4537
|
+
if (!extendExistingInterface(propsTypeName, extendBaseTypeText)) {
|
|
4538
|
+
if (!extendExistingTypeAlias(propsTypeName, extendBaseTypeText)) inlineTypeText = VOID_TAGS.has(tagName) ? explicit : withChildren(explicit);
|
|
3991
4539
|
}
|
|
3992
4540
|
}
|
|
3993
4541
|
needsReactTypeImport = true;
|
|
@@ -3995,28 +4543,8 @@ function emitWrappers(args) {
|
|
|
3995
4543
|
const styleArgs = [...d.extendsStyleKey ? [j.memberExpression(j.identifier(stylesIdentifier), j.identifier(d.extendsStyleKey))] : [], j.memberExpression(j.identifier(stylesIdentifier), j.identifier(d.styleKey))];
|
|
3996
4544
|
const destructureProps = [];
|
|
3997
4545
|
if (d.variantStyleKeys) for (const [when, variantKey] of Object.entries(d.variantStyleKeys)) {
|
|
3998
|
-
|
|
3999
|
-
const
|
|
4000
|
-
let propName = "";
|
|
4001
|
-
if (trimmed.startsWith("!(") && trimmed.endsWith(")")) {
|
|
4002
|
-
const inner = trimmed.slice(2, -1).trim();
|
|
4003
|
-
cond = j.unaryExpression("!", j.identifier(inner));
|
|
4004
|
-
propName = inner;
|
|
4005
|
-
} else if (trimmed.startsWith("!")) {
|
|
4006
|
-
propName = trimmed.slice(1);
|
|
4007
|
-
cond = j.unaryExpression("!", j.identifier(propName));
|
|
4008
|
-
} else if (trimmed.includes("===") || trimmed.includes("!==")) {
|
|
4009
|
-
const op = trimmed.includes("!==") ? "!==" : "===";
|
|
4010
|
-
const [lhs, rhsRaw0] = trimmed.split(op).map((s) => s.trim());
|
|
4011
|
-
const rhsRaw = rhsRaw0 ?? "";
|
|
4012
|
-
const rhs = rhsRaw?.startsWith("\"") || rhsRaw?.startsWith("'") ? j.literal(JSON.parse(rhsRaw.replace(/^'/, "\"").replace(/'$/, "\""))) : /^-?\d+(\.\d+)?$/.test(rhsRaw) ? j.literal(Number(rhsRaw)) : j.identifier(rhsRaw);
|
|
4013
|
-
propName = lhs ?? "";
|
|
4014
|
-
cond = j.binaryExpression(op, j.identifier(propName), rhs);
|
|
4015
|
-
} else {
|
|
4016
|
-
propName = trimmed;
|
|
4017
|
-
cond = j.identifier(trimmed);
|
|
4018
|
-
}
|
|
4019
|
-
if (propName && !destructureProps.includes(propName)) destructureProps.push(propName);
|
|
4546
|
+
const { cond, props } = parseVariantWhenToAst(j, when);
|
|
4547
|
+
for (const p of props) if (p && !destructureProps.includes(p)) destructureProps.push(p);
|
|
4020
4548
|
styleArgs.push(j.logicalExpression("&&", cond, j.memberExpression(j.identifier(stylesIdentifier), j.identifier(variantKey))));
|
|
4021
4549
|
}
|
|
4022
4550
|
const styleFnPairs = d.styleFnFromProps ?? [];
|
|
@@ -4027,7 +4555,19 @@ function emitWrappers(args) {
|
|
|
4027
4555
|
if (isPropRequiredInPropsTypeLiteral(d.propsType, p.jsxProp)) styleArgs.push(call);
|
|
4028
4556
|
else styleArgs.push(j.logicalExpression("&&", j.binaryExpression("!=", propExpr, j.nullLiteral()), call));
|
|
4029
4557
|
}
|
|
4030
|
-
if (
|
|
4558
|
+
if (d.attrsInfo?.conditionalAttrs?.length) {
|
|
4559
|
+
for (const c of d.attrsInfo.conditionalAttrs) if (c?.jsxProp && !destructureProps.includes(c.jsxProp)) destructureProps.push(c.jsxProp);
|
|
4560
|
+
}
|
|
4561
|
+
if (d.attrsInfo?.invertedBoolAttrs?.length) {
|
|
4562
|
+
for (const inv of d.attrsInfo.invertedBoolAttrs) if (inv?.jsxProp && !destructureProps.includes(inv.jsxProp)) destructureProps.push(inv.jsxProp);
|
|
4563
|
+
}
|
|
4564
|
+
const usedAttrs = getUsedAttrs(d.localName);
|
|
4565
|
+
const { hasAny: hasLocalUsage } = getJsxCallsites(d.localName);
|
|
4566
|
+
const shouldIncludeRest = isUsedAsValueInFile(d.localName) || hasLocalUsage && usedAttrs.has("*") || hasLocalUsage && [...usedAttrs].some((n) => {
|
|
4567
|
+
if (n === "children" || n === "className" || n === "style" || n === "as" || n === "forwardedAs") return false;
|
|
4568
|
+
return !destructureProps.includes(n);
|
|
4569
|
+
});
|
|
4570
|
+
if (allowClassNameProp || allowStyleProp) {
|
|
4031
4571
|
const isVoidTag = VOID_TAGS.has(tagName);
|
|
4032
4572
|
const propsParamId = j.identifier("props");
|
|
4033
4573
|
annotatePropsParam(propsParamId, d.localName, inlineTypeText);
|
|
@@ -4035,22 +4575,26 @@ function emitWrappers(args) {
|
|
|
4035
4575
|
const classNameId = j.identifier("className");
|
|
4036
4576
|
const childrenId = j.identifier("children");
|
|
4037
4577
|
const styleId = j.identifier("style");
|
|
4038
|
-
const restId = j.identifier("rest");
|
|
4578
|
+
const restId = shouldIncludeRest ? j.identifier("rest") : null;
|
|
4039
4579
|
const patternProps = [
|
|
4040
|
-
patternProp("className", classNameId),
|
|
4580
|
+
...allowClassNameProp ? [patternProp("className", classNameId)] : [],
|
|
4041
4581
|
...isVoidTag ? [] : [patternProp("children", childrenId)],
|
|
4042
|
-
patternProp("style", styleId),
|
|
4582
|
+
...allowStyleProp ? [patternProp("style", styleId)] : [],
|
|
4043
4583
|
...destructureProps.map((name) => patternProp(name)),
|
|
4044
|
-
j.restElement(restId)
|
|
4584
|
+
...restId ? [j.restElement(restId)] : []
|
|
4045
4585
|
];
|
|
4046
4586
|
const declStmt = j.variableDeclaration("const", [j.variableDeclarator(j.objectPattern(patternProps), propsId)]);
|
|
4047
4587
|
const sxDecl = j.variableDeclaration("const", [j.variableDeclarator(j.identifier("sx"), j.callExpression(j.memberExpression(j.identifier("stylex"), j.identifier("props")), styleArgs))]);
|
|
4048
|
-
const mergedClassName = j.callExpression(j.memberExpression(j.callExpression(j.memberExpression(j.arrayExpression([j.memberExpression(j.identifier("sx"), j.identifier("className")), classNameId]), j.identifier("filter")), [j.identifier("Boolean")]), j.identifier("join")), [j.literal(" ")]);
|
|
4588
|
+
const mergedClassName = allowClassNameProp ? j.callExpression(j.memberExpression(j.callExpression(j.memberExpression(j.arrayExpression([j.memberExpression(j.identifier("sx"), j.identifier("className")), classNameId]), j.identifier("filter")), [j.identifier("Boolean")]), j.identifier("join")), [j.literal(" ")]) : null;
|
|
4049
4589
|
const openingEl = j.jsxOpeningElement(j.jsxIdentifier(tagName), [
|
|
4050
4590
|
j.jsxSpreadAttribute(j.identifier("sx")),
|
|
4051
|
-
j.jsxAttribute(j.jsxIdentifier("className"), j.jsxExpressionContainer(mergedClassName)),
|
|
4052
|
-
j.jsxAttribute(j.jsxIdentifier("style"), j.jsxExpressionContainer(j.objectExpression([
|
|
4053
|
-
|
|
4591
|
+
...allowClassNameProp ? [j.jsxAttribute(j.jsxIdentifier("className"), j.jsxExpressionContainer(mergedClassName))] : [],
|
|
4592
|
+
...allowStyleProp || d.inlineStyleProps && d.inlineStyleProps.length ? [j.jsxAttribute(j.jsxIdentifier("style"), j.jsxExpressionContainer(j.objectExpression([
|
|
4593
|
+
j.spreadElement(j.memberExpression(j.identifier("sx"), j.identifier("style"))),
|
|
4594
|
+
...allowStyleProp ? [j.spreadElement(styleId)] : [],
|
|
4595
|
+
...d.inlineStyleProps && d.inlineStyleProps.length ? d.inlineStyleProps.map((p) => j.property("init", j.identifier(p.prop), p.expr)) : []
|
|
4596
|
+
])))] : [],
|
|
4597
|
+
...restId ? [j.jsxSpreadAttribute(restId)] : []
|
|
4054
4598
|
], false);
|
|
4055
4599
|
const jsx = isVoidTag ? {
|
|
4056
4600
|
type: "JSXElement",
|
|
@@ -4078,37 +4622,61 @@ function emitWrappers(args) {
|
|
|
4078
4622
|
emitTypes,
|
|
4079
4623
|
styleArgs,
|
|
4080
4624
|
destructureProps,
|
|
4625
|
+
allowClassNameProp: false,
|
|
4626
|
+
allowStyleProp: false,
|
|
4627
|
+
includeRest: shouldIncludeRest,
|
|
4081
4628
|
patternProp,
|
|
4082
|
-
...d.attrsInfo?.
|
|
4629
|
+
...d.attrsInfo?.defaultAttrs ? { defaultAttrs: d.attrsInfo.defaultAttrs } : {},
|
|
4630
|
+
...d.attrsInfo?.conditionalAttrs ? { conditionalAttrs: d.attrsInfo.conditionalAttrs } : {},
|
|
4631
|
+
...d.attrsInfo?.invertedBoolAttrs ? { invertedBoolAttrs: d.attrsInfo.invertedBoolAttrs } : {},
|
|
4632
|
+
...d.attrsInfo?.staticAttrs ? { staticAttrs: d.attrsInfo.staticAttrs } : {},
|
|
4633
|
+
inlineStyleProps: d.inlineStyleProps ?? []
|
|
4083
4634
|
}), d));
|
|
4084
4635
|
}
|
|
4085
4636
|
const componentWrappers = wrapperDecls.filter((d) => d.base.kind === "component");
|
|
4086
4637
|
for (const d of componentWrappers) {
|
|
4087
4638
|
if (d.base.kind !== "component") continue;
|
|
4088
4639
|
const wrappedComponent = d.base.ident;
|
|
4640
|
+
const wrappedComponentHasAs = wrapperNames.has(wrappedComponent);
|
|
4641
|
+
const isPolymorphicComponentWrapper = wrapperNames.has(d.localName) && !wrappedComponentHasAs;
|
|
4642
|
+
const allowClassNameProp = shouldAllowClassNameProp(d);
|
|
4643
|
+
const allowStyleProp = shouldAllowStyleProp(d);
|
|
4644
|
+
const propsIdForExpr = j.identifier("props");
|
|
4089
4645
|
let functionParamTypeName = null;
|
|
4090
|
-
let needsGenericPolymorphicType = false;
|
|
4091
4646
|
{
|
|
4092
4647
|
const explicit = stringifyTsType(d.propsType);
|
|
4093
|
-
const baseTypeText = `React.ComponentProps<typeof ${wrappedComponent}>`;
|
|
4094
4648
|
const explicitTypeName = d.propsType?.type === "TSTypeReference" && d.propsType?.typeName?.type === "Identifier" ? d.propsType?.typeName?.name : null;
|
|
4095
|
-
if (explicitTypeName && typeExistsInFile(explicitTypeName) && explicit) {
|
|
4649
|
+
if (explicitTypeName && typeExistsInFile(explicitTypeName) && explicit && explicitTypeName) {
|
|
4650
|
+
const baseTypeText = (() => {
|
|
4651
|
+
const base = `React.ComponentProps<typeof ${wrappedComponent}>`;
|
|
4652
|
+
const omitted = [];
|
|
4653
|
+
if (!allowClassNameProp) omitted.push("\"className\"");
|
|
4654
|
+
if (!allowStyleProp) omitted.push("\"style\"");
|
|
4655
|
+
return omitted.length ? `Omit<${base}, ${omitted.join(" | ")}>` : base;
|
|
4656
|
+
})();
|
|
4096
4657
|
if (!extendExistingInterface(explicitTypeName, baseTypeText)) extendExistingTypeAlias(explicitTypeName, baseTypeText);
|
|
4097
4658
|
functionParamTypeName = explicitTypeName;
|
|
4098
4659
|
} else {
|
|
4099
|
-
const
|
|
4100
|
-
if (
|
|
4101
|
-
|
|
4102
|
-
const
|
|
4103
|
-
|
|
4104
|
-
|
|
4105
|
-
|
|
4660
|
+
const explicitPropNames = d.propsType ? getExplicitPropNames(d.propsType) : /* @__PURE__ */ new Set();
|
|
4661
|
+
if (isPolymorphicComponentWrapper) {
|
|
4662
|
+
const baseProps = `React.ComponentProps<typeof ${wrappedComponent}>`;
|
|
4663
|
+
const omitted = [];
|
|
4664
|
+
if (!allowClassNameProp) omitted.push("\"className\"");
|
|
4665
|
+
if (!allowStyleProp) omitted.push("\"style\"");
|
|
4666
|
+
const typeText = joinIntersection(omitted.length ? `Omit<${baseProps}, ${omitted.join(" | ")}>` : baseProps, "{ as?: C }", `Omit<React.ComponentPropsWithoutRef<C>, keyof ${baseProps} | "as">`);
|
|
4667
|
+
emitNamedPropsType(d.localName, typeText, `C extends React.ElementType = typeof ${wrappedComponent}`);
|
|
4106
4668
|
} else {
|
|
4107
|
-
const
|
|
4108
|
-
|
|
4109
|
-
|
|
4110
|
-
|
|
4111
|
-
|
|
4669
|
+
const inferred = inferredComponentWrapperPropsTypeText({
|
|
4670
|
+
d,
|
|
4671
|
+
allowClassNameProp,
|
|
4672
|
+
allowStyleProp,
|
|
4673
|
+
includeAsProp: false,
|
|
4674
|
+
includeChildren: hasJsxChildrenUsage(d.localName),
|
|
4675
|
+
skipProps: explicitPropNames
|
|
4676
|
+
});
|
|
4677
|
+
const explicitWithChildren = explicit ? withChildren(explicit) : null;
|
|
4678
|
+
const typeText = explicitWithChildren ? joinIntersection(inferred, explicitWithChildren) : inferred;
|
|
4679
|
+
emitNamedPropsType(d.localName, typeText);
|
|
4112
4680
|
}
|
|
4113
4681
|
}
|
|
4114
4682
|
needsReactTypeImport = true;
|
|
@@ -4116,42 +4684,36 @@ function emitWrappers(args) {
|
|
|
4116
4684
|
const styleArgs = [j.memberExpression(j.identifier(stylesIdentifier), j.identifier(d.styleKey))];
|
|
4117
4685
|
const destructureProps = [];
|
|
4118
4686
|
if (d.variantStyleKeys) for (const [when, variantKey] of Object.entries(d.variantStyleKeys)) {
|
|
4119
|
-
|
|
4120
|
-
const
|
|
4121
|
-
let propName = "";
|
|
4122
|
-
if (trimmed.startsWith("!(") && trimmed.endsWith(")")) {
|
|
4123
|
-
const inner = trimmed.slice(2, -1).trim();
|
|
4124
|
-
cond = j.unaryExpression("!", j.identifier(inner));
|
|
4125
|
-
propName = inner;
|
|
4126
|
-
} else if (trimmed.startsWith("!")) {
|
|
4127
|
-
propName = trimmed.slice(1);
|
|
4128
|
-
cond = j.unaryExpression("!", j.identifier(propName));
|
|
4129
|
-
} else if (trimmed.includes("===") || trimmed.includes("!==")) {
|
|
4130
|
-
const op = trimmed.includes("!==") ? "!==" : "===";
|
|
4131
|
-
const [lhs, rhsRaw0] = trimmed.split(op).map((s) => s.trim());
|
|
4132
|
-
const rhsRaw = rhsRaw0 ?? "";
|
|
4133
|
-
const rhs = rhsRaw?.startsWith("\"") || rhsRaw?.startsWith("'") ? j.literal(JSON.parse(rhsRaw.replace(/^'/, "\"").replace(/'$/, "\""))) : /^-?\d+(\.\d+)?$/.test(rhsRaw) ? j.literal(Number(rhsRaw)) : j.identifier(rhsRaw);
|
|
4134
|
-
propName = lhs ?? "";
|
|
4135
|
-
cond = j.binaryExpression(op, j.identifier(propName), rhs);
|
|
4136
|
-
} else {
|
|
4137
|
-
propName = trimmed;
|
|
4138
|
-
cond = j.identifier(trimmed);
|
|
4139
|
-
}
|
|
4140
|
-
if (propName && !destructureProps.includes(propName)) destructureProps.push(propName);
|
|
4687
|
+
const { cond, props } = parseVariantWhenToAst(j, when);
|
|
4688
|
+
for (const p of props) if (p && !destructureProps.includes(p)) destructureProps.push(p);
|
|
4141
4689
|
styleArgs.push(j.logicalExpression("&&", cond, j.memberExpression(j.identifier(stylesIdentifier), j.identifier(variantKey))));
|
|
4142
4690
|
}
|
|
4143
4691
|
const styleFnPairs = d.styleFnFromProps ?? [];
|
|
4144
4692
|
for (const p of styleFnPairs) {
|
|
4145
|
-
const propExpr = j.identifier(p.jsxProp);
|
|
4693
|
+
const propExpr = j.memberExpression(propsIdForExpr, j.identifier(p.jsxProp));
|
|
4146
4694
|
const call = j.callExpression(j.memberExpression(j.identifier(stylesIdentifier), j.identifier(p.fnKey)), [propExpr]);
|
|
4147
|
-
if (!destructureProps.includes(p.jsxProp)) destructureProps.push(p.jsxProp);
|
|
4148
4695
|
if (isPropRequiredInPropsTypeLiteral(d.propsType, p.jsxProp)) styleArgs.push(call);
|
|
4149
4696
|
else styleArgs.push(j.logicalExpression("&&", j.binaryExpression("!=", propExpr, j.nullLiteral()), call));
|
|
4150
4697
|
}
|
|
4151
4698
|
const filterOnlyTransientProps = [];
|
|
4699
|
+
const wrapperOnlyTransientProps = [];
|
|
4152
4700
|
{
|
|
4153
4701
|
const findTransientPropsInTypeName = (typeName) => {
|
|
4154
4702
|
const props = [];
|
|
4703
|
+
const collectFromTypeNode = (typeNode) => {
|
|
4704
|
+
if (!typeNode) return;
|
|
4705
|
+
if (typeNode.type === "TSParenthesizedType") {
|
|
4706
|
+
collectFromTypeNode(typeNode.typeAnnotation);
|
|
4707
|
+
return;
|
|
4708
|
+
}
|
|
4709
|
+
if (typeNode.type === "TSIntersectionType") {
|
|
4710
|
+
for (const t of typeNode.types ?? []) collectFromTypeNode(t);
|
|
4711
|
+
return;
|
|
4712
|
+
}
|
|
4713
|
+
if (typeNode.type === "TSTypeLiteral" && typeNode.members) {
|
|
4714
|
+
for (const member of typeNode.members) if (member.type === "TSPropertySignature" && member.key?.type === "Identifier" && member.key.name.startsWith("$")) props.push(member.key.name);
|
|
4715
|
+
}
|
|
4716
|
+
};
|
|
4155
4717
|
const interfaceDecl = root.find(j.TSInterfaceDeclaration).filter((p) => p.node.id?.name === typeName);
|
|
4156
4718
|
if (interfaceDecl.size() > 0) {
|
|
4157
4719
|
const body = interfaceDecl.get().node.body?.body ?? [];
|
|
@@ -4160,19 +4722,21 @@ function emitWrappers(args) {
|
|
|
4160
4722
|
const typeAlias = root.find(j.TSTypeAliasDeclaration).filter((p) => p.node.id?.name === typeName);
|
|
4161
4723
|
if (typeAlias.size() > 0) {
|
|
4162
4724
|
const typeAnnotation = typeAlias.get().node.typeAnnotation;
|
|
4163
|
-
|
|
4164
|
-
for (const member of typeAnnotation.members) if (member.type === "TSPropertySignature" && member.key?.type === "Identifier" && member.key.name.startsWith("$")) props.push(member.key.name);
|
|
4165
|
-
}
|
|
4725
|
+
collectFromTypeNode(typeAnnotation);
|
|
4166
4726
|
}
|
|
4167
4727
|
return props;
|
|
4168
4728
|
};
|
|
4169
4729
|
const explicit = d.propsType;
|
|
4170
4730
|
let transientProps = [];
|
|
4171
4731
|
if (explicit?.type === "TSTypeLiteral" && explicit.members) {
|
|
4172
|
-
for (const member of explicit.members) if (member.type === "TSPropertySignature" && member.key?.type === "Identifier" && member.key.name.startsWith("$"))
|
|
4732
|
+
for (const member of explicit.members) if (member.type === "TSPropertySignature" && member.key?.type === "Identifier" && member.key.name.startsWith("$")) {
|
|
4733
|
+
transientProps.push(member.key.name);
|
|
4734
|
+
wrapperOnlyTransientProps.push(member.key.name);
|
|
4735
|
+
}
|
|
4173
4736
|
} else if (explicit?.type === "TSTypeReference" && explicit.typeName?.type === "Identifier") {
|
|
4174
4737
|
const typeName = explicit.typeName.name;
|
|
4175
4738
|
transientProps = findTransientPropsInTypeName(typeName);
|
|
4739
|
+
wrapperOnlyTransientProps.push(...transientProps);
|
|
4176
4740
|
}
|
|
4177
4741
|
if (transientProps.length === 0) {
|
|
4178
4742
|
const funcDecls = root.find(j.FunctionDeclaration).filter((p) => p.node.id?.name === wrappedComponent);
|
|
@@ -4201,9 +4765,13 @@ function emitWrappers(args) {
|
|
|
4201
4765
|
}
|
|
4202
4766
|
}
|
|
4203
4767
|
const propsParamId = j.identifier("props");
|
|
4204
|
-
|
|
4205
|
-
|
|
4206
|
-
|
|
4768
|
+
let polymorphicFnTypeParams = null;
|
|
4769
|
+
if (isPolymorphicComponentWrapper && emitTypes) {
|
|
4770
|
+
polymorphicFnTypeParams = j(`function _<C extends React.ElementType = typeof ${wrappedComponent}>() { return null }`).get().node.program.body[0].typeParameters;
|
|
4771
|
+
propsParamId.typeAnnotation = j(`const x: ${propsTypeNameFor(d.localName)}<C> = null`).get().node.program.body[0].declarations[0].id.typeAnnotation;
|
|
4772
|
+
}
|
|
4773
|
+
if (!isPolymorphicComponentWrapper && functionParamTypeName && emitTypes) propsParamId.typeAnnotation = j.tsTypeAnnotation(j.tsTypeReference(j.identifier(functionParamTypeName)));
|
|
4774
|
+
else if (!isPolymorphicComponentWrapper) annotatePropsParam(propsParamId, d.localName);
|
|
4207
4775
|
const propsId = j.identifier("props");
|
|
4208
4776
|
const stylexPropsCall = j.callExpression(j.memberExpression(j.identifier("stylex"), j.identifier("props")), styleArgs);
|
|
4209
4777
|
let jsxTagName;
|
|
@@ -4211,42 +4779,70 @@ function emitWrappers(args) {
|
|
|
4211
4779
|
const parts = wrappedComponent.split(".");
|
|
4212
4780
|
jsxTagName = j.jsxMemberExpression(j.jsxIdentifier(parts[0]), j.jsxIdentifier(parts.slice(1).join(".")));
|
|
4213
4781
|
} else jsxTagName = j.jsxIdentifier(wrappedComponent);
|
|
4214
|
-
|
|
4782
|
+
const defaultAttrs = d.attrsInfo?.defaultAttrs ?? [];
|
|
4783
|
+
const staticAttrs = d.attrsInfo?.staticAttrs ?? {};
|
|
4784
|
+
const needsSxVar = allowClassNameProp || allowStyleProp || !!d.inlineStyleProps?.length;
|
|
4785
|
+
const needsDestructure = destructureProps.length > 0 || needsSxVar;
|
|
4786
|
+
const includeChildren = hasJsxChildrenUsage(d.localName);
|
|
4787
|
+
if (needsDestructure) {
|
|
4788
|
+
const childrenId = j.identifier("children");
|
|
4789
|
+
const classNameId = j.identifier("className");
|
|
4215
4790
|
const styleId = j.identifier("style");
|
|
4216
4791
|
const restId = j.identifier("rest");
|
|
4217
|
-
const patternProps =
|
|
4218
|
-
|
|
4219
|
-
|
|
4220
|
-
|
|
4221
|
-
|
|
4222
|
-
|
|
4223
|
-
|
|
4224
|
-
|
|
4225
|
-
|
|
4226
|
-
|
|
4227
|
-
|
|
4228
|
-
const
|
|
4229
|
-
|
|
4230
|
-
|
|
4231
|
-
|
|
4232
|
-
|
|
4233
|
-
|
|
4234
|
-
const
|
|
4235
|
-
|
|
4236
|
-
|
|
4237
|
-
|
|
4238
|
-
|
|
4239
|
-
|
|
4240
|
-
|
|
4792
|
+
const patternProps = [
|
|
4793
|
+
...allowClassNameProp ? [patternProp("className", classNameId)] : [],
|
|
4794
|
+
...includeChildren ? [patternProp("children", childrenId)] : [],
|
|
4795
|
+
...allowStyleProp ? [patternProp("style", styleId)] : [],
|
|
4796
|
+
...destructureProps.filter(Boolean).map((name) => patternProp(name)),
|
|
4797
|
+
j.restElement(restId)
|
|
4798
|
+
];
|
|
4799
|
+
const stmts = [j.variableDeclaration("const", [j.variableDeclarator(j.objectPattern(patternProps), propsId)])];
|
|
4800
|
+
const sxId = j.identifier("sx");
|
|
4801
|
+
if (needsSxVar) stmts.push(j.variableDeclaration("const", [j.variableDeclarator(sxId, stylexPropsCall)]));
|
|
4802
|
+
const openingAttrs = [];
|
|
4803
|
+
for (const a of defaultAttrs) if (typeof a.value === "string") openingAttrs.push(j.jsxAttribute(j.jsxIdentifier(a.attrName), j.literal(a.value)));
|
|
4804
|
+
else if (typeof a.value === "number") openingAttrs.push(j.jsxAttribute(j.jsxIdentifier(a.attrName), j.jsxExpressionContainer(j.literal(a.value))));
|
|
4805
|
+
else if (typeof a.value === "boolean") openingAttrs.push(j.jsxAttribute(j.jsxIdentifier(a.attrName), j.jsxExpressionContainer(j.booleanLiteral(a.value))));
|
|
4806
|
+
for (const [key, value] of Object.entries(staticAttrs)) if (typeof value === "string") openingAttrs.push(j.jsxAttribute(j.jsxIdentifier(key), j.literal(value)));
|
|
4807
|
+
else if (typeof value === "number") openingAttrs.push(j.jsxAttribute(j.jsxIdentifier(key), j.jsxExpressionContainer(j.literal(value))));
|
|
4808
|
+
else if (typeof value === "boolean") openingAttrs.push(j.jsxAttribute(j.jsxIdentifier(key), j.jsxExpressionContainer(j.booleanLiteral(value))));
|
|
4809
|
+
for (const propName of destructureProps) if (propName.startsWith("$") && !filterOnlyTransientProps.includes(propName) && !wrapperOnlyTransientProps.includes(propName)) openingAttrs.push(j.jsxAttribute(j.jsxIdentifier(propName), j.jsxExpressionContainer(j.identifier(propName))));
|
|
4810
|
+
openingAttrs.push(j.jsxSpreadAttribute(restId));
|
|
4811
|
+
openingAttrs.push(j.jsxSpreadAttribute(needsSxVar ? sxId : stylexPropsCall));
|
|
4812
|
+
if (allowClassNameProp) {
|
|
4813
|
+
const mergedClassName = j.callExpression(j.memberExpression(j.callExpression(j.memberExpression(j.arrayExpression([j.memberExpression(sxId, j.identifier("className")), classNameId]), j.identifier("filter")), [j.identifier("Boolean")]), j.identifier("join")), [j.literal(" ")]);
|
|
4814
|
+
openingAttrs.push(j.jsxAttribute(j.jsxIdentifier("className"), j.jsxExpressionContainer(mergedClassName)));
|
|
4815
|
+
}
|
|
4816
|
+
if (allowStyleProp || d.inlineStyleProps && d.inlineStyleProps.length) openingAttrs.push(j.jsxAttribute(j.jsxIdentifier("style"), j.jsxExpressionContainer(j.objectExpression([
|
|
4817
|
+
j.spreadElement(j.memberExpression(sxId, j.identifier("style"))),
|
|
4818
|
+
...allowStyleProp ? [j.spreadElement(styleId)] : [],
|
|
4819
|
+
...d.inlineStyleProps && d.inlineStyleProps.length ? d.inlineStyleProps.map((p) => j.property("init", j.identifier(p.prop), p.expr)) : []
|
|
4820
|
+
]))));
|
|
4821
|
+
const openingEl = j.jsxOpeningElement(jsxTagName, openingAttrs, !includeChildren);
|
|
4822
|
+
const jsx = includeChildren ? j.jsxElement(openingEl, j.jsxClosingElement(jsxTagName), [j.jsxExpressionContainer(childrenId)]) : {
|
|
4823
|
+
type: "JSXElement",
|
|
4824
|
+
openingElement: openingEl,
|
|
4825
|
+
closingElement: null,
|
|
4826
|
+
children: []
|
|
4827
|
+
};
|
|
4828
|
+
stmts.push(j.returnStatement(jsx));
|
|
4829
|
+
const fn = j.functionDeclaration(j.identifier(d.localName), [propsParamId], j.blockStatement(stmts));
|
|
4830
|
+
if (polymorphicFnTypeParams) fn.typeParameters = polymorphicFnTypeParams;
|
|
4831
|
+
emitted.push(fn);
|
|
4241
4832
|
} else {
|
|
4242
|
-
const
|
|
4243
|
-
const
|
|
4244
|
-
if (
|
|
4245
|
-
|
|
4246
|
-
|
|
4247
|
-
|
|
4248
|
-
|
|
4249
|
-
|
|
4833
|
+
const openingAttrs = [];
|
|
4834
|
+
for (const a of defaultAttrs) if (typeof a.value === "string") openingAttrs.push(j.jsxAttribute(j.jsxIdentifier(a.attrName), j.literal(a.value)));
|
|
4835
|
+
else if (typeof a.value === "number") openingAttrs.push(j.jsxAttribute(j.jsxIdentifier(a.attrName), j.jsxExpressionContainer(j.literal(a.value))));
|
|
4836
|
+
else if (typeof a.value === "boolean") openingAttrs.push(j.jsxAttribute(j.jsxIdentifier(a.attrName), j.jsxExpressionContainer(j.booleanLiteral(a.value))));
|
|
4837
|
+
openingAttrs.push(j.jsxSpreadAttribute(propsId));
|
|
4838
|
+
for (const [key, value] of Object.entries(staticAttrs)) if (typeof value === "string") openingAttrs.push(j.jsxAttribute(j.jsxIdentifier(key), j.literal(value)));
|
|
4839
|
+
else if (typeof value === "number") openingAttrs.push(j.jsxAttribute(j.jsxIdentifier(key), j.jsxExpressionContainer(j.literal(value))));
|
|
4840
|
+
else if (typeof value === "boolean") openingAttrs.push(j.jsxAttribute(j.jsxIdentifier(key), j.jsxExpressionContainer(j.booleanLiteral(value))));
|
|
4841
|
+
openingAttrs.push(j.jsxSpreadAttribute(stylexPropsCall));
|
|
4842
|
+
const jsx = j.jsxElement(j.jsxOpeningElement(jsxTagName, openingAttrs, true), null, []);
|
|
4843
|
+
const fn = j.functionDeclaration(j.identifier(d.localName), [propsParamId], j.blockStatement([j.returnStatement(jsx)]));
|
|
4844
|
+
if (polymorphicFnTypeParams) fn.typeParameters = polymorphicFnTypeParams;
|
|
4845
|
+
emitted.push(fn);
|
|
4250
4846
|
}
|
|
4251
4847
|
}
|
|
4252
4848
|
if (emitted.length > 0) {
|
|
@@ -4588,6 +5184,55 @@ function universalSelectorUnsupportedWarning(loc) {
|
|
|
4588
5184
|
};
|
|
4589
5185
|
}
|
|
4590
5186
|
|
|
5187
|
+
//#endregion
|
|
5188
|
+
//#region src/internal/dom-attrs.ts
|
|
5189
|
+
/**
|
|
5190
|
+
* DOM attribute filtering (inline-to-intrinsic only)
|
|
5191
|
+
*
|
|
5192
|
+
* When we inline a styled component into a native DOM/SVG element, we remove the component boundary.
|
|
5193
|
+
* That can turn "custom" props (which styled-components might have forwarded) into invalid DOM attrs.
|
|
5194
|
+
*
|
|
5195
|
+
* We keep a small allowlist here to avoid leaking obvious non-DOM props while preserving the props
|
|
5196
|
+
* commonly used in fixtures. This is intentionally conservative and centralized so it's easy to audit.
|
|
5197
|
+
*/
|
|
5198
|
+
const KNOWN_SAFE_DOM_ATTRS = new Set([
|
|
5199
|
+
"className",
|
|
5200
|
+
"style",
|
|
5201
|
+
"ref",
|
|
5202
|
+
"key",
|
|
5203
|
+
"id",
|
|
5204
|
+
"title",
|
|
5205
|
+
"role",
|
|
5206
|
+
"tabIndex",
|
|
5207
|
+
"href",
|
|
5208
|
+
"target",
|
|
5209
|
+
"rel",
|
|
5210
|
+
"type",
|
|
5211
|
+
"name",
|
|
5212
|
+
"value",
|
|
5213
|
+
"placeholder",
|
|
5214
|
+
"disabled",
|
|
5215
|
+
"readOnly",
|
|
5216
|
+
"htmlFor",
|
|
5217
|
+
"src",
|
|
5218
|
+
"alt",
|
|
5219
|
+
"width",
|
|
5220
|
+
"height",
|
|
5221
|
+
"viewBox",
|
|
5222
|
+
"d",
|
|
5223
|
+
"x",
|
|
5224
|
+
"y",
|
|
5225
|
+
"rx",
|
|
5226
|
+
"ry",
|
|
5227
|
+
"fill"
|
|
5228
|
+
]);
|
|
5229
|
+
function isLikelyValidDomAttr(name) {
|
|
5230
|
+
if (KNOWN_SAFE_DOM_ATTRS.has(name)) return true;
|
|
5231
|
+
if (name.startsWith("data-") || name.startsWith("aria-")) return true;
|
|
5232
|
+
if (/^on[A-Z]/.test(name)) return true;
|
|
5233
|
+
return false;
|
|
5234
|
+
}
|
|
5235
|
+
|
|
4591
5236
|
//#endregion
|
|
4592
5237
|
//#region src/transform.ts
|
|
4593
5238
|
/**
|
|
@@ -4672,9 +5317,55 @@ function transformWithWarnings(file, api, options) {
|
|
|
4672
5317
|
}
|
|
4673
5318
|
};
|
|
4674
5319
|
const adapter = options.adapter;
|
|
4675
|
-
|
|
5320
|
+
assertValidAdapter(adapter, "transform(options) - missing `adapter` (if you run the jscodeshift transform directly, pass options.adapter)");
|
|
4676
5321
|
const resolverImports = /* @__PURE__ */ new Map();
|
|
4677
5322
|
let hasChanges = false;
|
|
5323
|
+
let bailDueToUndefinedResolveValue = false;
|
|
5324
|
+
const formatResolveValueContext = (ctx) => {
|
|
5325
|
+
const c = ctx;
|
|
5326
|
+
const kind = c?.kind;
|
|
5327
|
+
if (kind === "theme") return `kind=theme path=${JSON.stringify(String(c?.path ?? ""))}`;
|
|
5328
|
+
if (kind === "cssVariable") {
|
|
5329
|
+
const parts = [`kind=cssVariable name=${JSON.stringify(String(c?.name ?? ""))}`];
|
|
5330
|
+
if (typeof c?.fallback === "string") parts.push(`fallback=${JSON.stringify(c.fallback)}`);
|
|
5331
|
+
if (typeof c?.definedValue === "string") parts.push(`definedValue=${JSON.stringify(c.definedValue)}`);
|
|
5332
|
+
return parts.join(" ");
|
|
5333
|
+
}
|
|
5334
|
+
if (kind === "call") {
|
|
5335
|
+
const args = Array.isArray(c?.args) ? c.args : [];
|
|
5336
|
+
return [
|
|
5337
|
+
"kind=call",
|
|
5338
|
+
`calleeImportedName=${JSON.stringify(String(c?.calleeImportedName ?? ""))}`,
|
|
5339
|
+
`calleeSource=${JSON.stringify(c?.calleeSource ?? null)}`,
|
|
5340
|
+
`callSiteFilePath=${JSON.stringify(String(c?.callSiteFilePath ?? ""))}`,
|
|
5341
|
+
`args=${JSON.stringify(args)}`
|
|
5342
|
+
].join(" ");
|
|
5343
|
+
}
|
|
5344
|
+
try {
|
|
5345
|
+
return `ctx=${JSON.stringify(ctx)}`;
|
|
5346
|
+
} catch {
|
|
5347
|
+
return `ctx=${String(ctx)}`;
|
|
5348
|
+
}
|
|
5349
|
+
};
|
|
5350
|
+
const resolveValueSafe = (ctx) => {
|
|
5351
|
+
if (bailDueToUndefinedResolveValue) return null;
|
|
5352
|
+
const res = adapter.resolveValue(ctx);
|
|
5353
|
+
if (typeof res === "undefined") {
|
|
5354
|
+
bailDueToUndefinedResolveValue = true;
|
|
5355
|
+
warnings.push({
|
|
5356
|
+
type: "dynamic-node",
|
|
5357
|
+
feature: "adapter-resolveValue",
|
|
5358
|
+
message: [
|
|
5359
|
+
"Adapter.resolveValue returned undefined. This usually means your adapter forgot to return a value.",
|
|
5360
|
+
"Return null to leave a value unresolved, or return { expr, imports } to resolve it.",
|
|
5361
|
+
`Skipping transformation for this file to avoid producing incorrect output.`,
|
|
5362
|
+
`resolveValue was called with: ${formatResolveValueContext(ctx)}`
|
|
5363
|
+
].join(" ")
|
|
5364
|
+
});
|
|
5365
|
+
return null;
|
|
5366
|
+
}
|
|
5367
|
+
return res;
|
|
5368
|
+
};
|
|
4678
5369
|
const styledImports = root.find(j.ImportDeclaration, { source: { value: "styled-components" } });
|
|
4679
5370
|
if (styledImports.length === 0) return {
|
|
4680
5371
|
code: null,
|
|
@@ -4710,7 +5401,8 @@ function transformWithWarnings(file, api, options) {
|
|
|
4710
5401
|
let keyframesNames = /* @__PURE__ */ new Set();
|
|
4711
5402
|
const parseExpr = (exprSource) => {
|
|
4712
5403
|
try {
|
|
4713
|
-
|
|
5404
|
+
const jParse = api.jscodeshift.withParser("tsx");
|
|
5405
|
+
let expr = jParse(`(${exprSource});`).find(jParse.ExpressionStatement).nodes()[0]?.expression ?? null;
|
|
4714
5406
|
while (expr?.type === "ParenthesizedExpression") expr = expr.expression;
|
|
4715
5407
|
if (expr?.extra?.parenthesized) {
|
|
4716
5408
|
delete expr.extra.parenthesized;
|
|
@@ -4728,18 +5420,15 @@ function transformWithWarnings(file, api, options) {
|
|
|
4728
5420
|
rewriteCssVarsInStyleObject(v, definedVars, varsToDrop);
|
|
4729
5421
|
continue;
|
|
4730
5422
|
}
|
|
4731
|
-
if (typeof v === "string") {
|
|
4732
|
-
|
|
4733
|
-
|
|
4734
|
-
|
|
4735
|
-
|
|
4736
|
-
|
|
4737
|
-
|
|
4738
|
-
|
|
4739
|
-
|
|
4740
|
-
j
|
|
4741
|
-
});
|
|
4742
|
-
}
|
|
5423
|
+
if (typeof v === "string") obj[k] = rewriteCssVarsInString({
|
|
5424
|
+
raw: v,
|
|
5425
|
+
definedVars,
|
|
5426
|
+
varsToDrop,
|
|
5427
|
+
resolveValue: resolveValueSafe,
|
|
5428
|
+
addImport: (imp) => resolverImports.set(JSON.stringify(imp), imp),
|
|
5429
|
+
parseExpr,
|
|
5430
|
+
j
|
|
5431
|
+
});
|
|
4743
5432
|
}
|
|
4744
5433
|
};
|
|
4745
5434
|
if (keyframesLocal) {
|
|
@@ -4908,6 +5597,10 @@ function transformWithWarnings(file, api, options) {
|
|
|
4908
5597
|
loc: componentSelectorLoc
|
|
4909
5598
|
});
|
|
4910
5599
|
else warnings.push(warning);
|
|
5600
|
+
return {
|
|
5601
|
+
code: null,
|
|
5602
|
+
warnings
|
|
5603
|
+
};
|
|
4911
5604
|
}
|
|
4912
5605
|
if (hasSpecificityHack) {
|
|
4913
5606
|
const warning = {
|
|
@@ -5009,7 +5702,7 @@ function transformWithWarnings(file, api, options) {
|
|
|
5009
5702
|
j,
|
|
5010
5703
|
root,
|
|
5011
5704
|
filePath: file.path,
|
|
5012
|
-
resolveValue:
|
|
5705
|
+
resolveValue: resolveValueSafe,
|
|
5013
5706
|
importMap,
|
|
5014
5707
|
warnings,
|
|
5015
5708
|
resolverImports,
|
|
@@ -5027,7 +5720,7 @@ function transformWithWarnings(file, api, options) {
|
|
|
5027
5720
|
const resolvedStyleObjects = lowered.resolvedStyleObjects;
|
|
5028
5721
|
const descendantOverrides = lowered.descendantOverrides;
|
|
5029
5722
|
const ancestorSelectorParents = lowered.ancestorSelectorParents;
|
|
5030
|
-
if (lowered.bail) return {
|
|
5723
|
+
if (lowered.bail || bailDueToUndefinedResolveValue) return {
|
|
5031
5724
|
code: null,
|
|
5032
5725
|
warnings
|
|
5033
5726
|
};
|
|
@@ -5094,6 +5787,7 @@ function transformWithWarnings(file, api, options) {
|
|
|
5094
5787
|
if (new Set(styledDecls.map((d) => d.localName)).has(obj.name)) componentsWithStaticProps.add(obj.name);
|
|
5095
5788
|
});
|
|
5096
5789
|
for (const decl of styledDecls) {
|
|
5790
|
+
if (decl.base.kind === "intrinsic" && (decl.attrsInfo?.conditionalAttrs?.length ?? 0) > 0) decl.needsWrapperComponent = true;
|
|
5097
5791
|
if (decl.shouldForwardProp) decl.needsWrapperComponent = true;
|
|
5098
5792
|
if (decl.base.kind === "intrinsic" && decl.withConfig?.componentId) decl.needsWrapperComponent = true;
|
|
5099
5793
|
if (extendedBy.has(decl.localName) && componentsWithStaticProps.has(decl.localName)) decl.needsWrapperComponent = true;
|
|
@@ -5155,11 +5849,7 @@ function transformWithWarnings(file, api, options) {
|
|
|
5155
5849
|
decl.supportsExternalStyles = false;
|
|
5156
5850
|
continue;
|
|
5157
5851
|
}
|
|
5158
|
-
|
|
5159
|
-
decl.supportsExternalStyles = true;
|
|
5160
|
-
continue;
|
|
5161
|
-
}
|
|
5162
|
-
decl.supportsExternalStyles = adapter.shouldSupportExternalStyles({
|
|
5852
|
+
decl.supportsExternalStyles = adapter.shouldSupportExternalStyling({
|
|
5163
5853
|
filePath: file.path,
|
|
5164
5854
|
componentName: decl.localName,
|
|
5165
5855
|
exportName: exportInfo.exportName,
|
|
@@ -5258,7 +5948,10 @@ function transformWithWarnings(file, api, options) {
|
|
|
5258
5948
|
if (p.parentPath?.node?.type === "CallExpression" && p.parentPath.parentPath?.node?.type === "TaggedTemplateExpression") return false;
|
|
5259
5949
|
if (p.parentPath?.node?.type === "TemplateLiteral") return false;
|
|
5260
5950
|
return true;
|
|
5261
|
-
}).size() > 0)
|
|
5951
|
+
}).size() > 0) {
|
|
5952
|
+
decl.usedAsValue = true;
|
|
5953
|
+
decl.needsWrapperComponent = true;
|
|
5954
|
+
}
|
|
5262
5955
|
}
|
|
5263
5956
|
for (const decl of styledDecls) if (decl.base.kind === "component") {
|
|
5264
5957
|
const baseDecl = declByLocal.get(decl.base.ident);
|
|
@@ -5295,7 +5988,7 @@ function transformWithWarnings(file, api, options) {
|
|
|
5295
5988
|
staticPropertyNames.set(componentName, names);
|
|
5296
5989
|
}
|
|
5297
5990
|
if (baseComponentNames.has(componentName)) return;
|
|
5298
|
-
if (exportedComponents.has(componentName)) {
|
|
5991
|
+
if (exportedComponents.has(componentName) || extendedBy.has(componentName)) {
|
|
5299
5992
|
const existing = staticPropertyAssignments.get(componentName) ?? [];
|
|
5300
5993
|
existing.push(p.node);
|
|
5301
5994
|
staticPropertyAssignments.set(componentName, existing);
|
|
@@ -5308,16 +6001,14 @@ function transformWithWarnings(file, api, options) {
|
|
|
5308
6001
|
const baseComponentName = declByLocal.get(baseIdent)?.localName ?? baseIdent;
|
|
5309
6002
|
const baseProps = staticPropertyNames.get(baseComponentName);
|
|
5310
6003
|
if (!baseProps || baseProps.length === 0) continue;
|
|
6004
|
+
if ((staticPropertyAssignments.get(decl.localName) ?? []).length > 0) continue;
|
|
5311
6005
|
const inheritanceStatements = [];
|
|
5312
6006
|
for (const propName of baseProps) {
|
|
5313
|
-
const
|
|
6007
|
+
const rhs = j(`const __x = (${baseComponentName} as any).${propName};`).get().node.program.body[0].declarations[0].init;
|
|
6008
|
+
const stmt = j.expressionStatement(j.assignmentExpression("=", j.memberExpression(j.identifier(decl.localName), j.identifier(propName)), rhs));
|
|
5314
6009
|
inheritanceStatements.push(stmt);
|
|
5315
6010
|
}
|
|
5316
|
-
if (inheritanceStatements.length > 0)
|
|
5317
|
-
const existing = staticPropertyAssignments.get(decl.localName) ?? [];
|
|
5318
|
-
existing.push(...inheritanceStatements);
|
|
5319
|
-
staticPropertyAssignments.set(decl.localName, existing);
|
|
5320
|
-
}
|
|
6011
|
+
if (inheritanceStatements.length > 0) staticPropertyAssignments.set(decl.localName, inheritanceStatements);
|
|
5321
6012
|
}
|
|
5322
6013
|
for (const decl of styledDecls) {
|
|
5323
6014
|
const baseIdent = decl.originalBaseIdent ?? (decl.base.kind === "component" ? decl.base.ident : null);
|
|
@@ -5528,6 +6219,9 @@ function transformWithWarnings(file, api, options) {
|
|
|
5528
6219
|
}
|
|
5529
6220
|
if (!variantProps.has(n)) {
|
|
5530
6221
|
if (n.startsWith("$")) continue;
|
|
6222
|
+
if (decl.base.kind === "intrinsic") {
|
|
6223
|
+
if (!isLikelyValidDomAttr(n)) continue;
|
|
6224
|
+
}
|
|
5531
6225
|
keptAfterVariants.push(attr);
|
|
5532
6226
|
continue;
|
|
5533
6227
|
}
|
|
@@ -5554,7 +6248,6 @@ function transformWithWarnings(file, api, options) {
|
|
|
5554
6248
|
filePath: file.path,
|
|
5555
6249
|
styledDecls,
|
|
5556
6250
|
wrapperNames,
|
|
5557
|
-
expressionAsWrapperNames,
|
|
5558
6251
|
patternProp,
|
|
5559
6252
|
exportedComponents,
|
|
5560
6253
|
stylesIdentifier
|
|
@@ -5693,6 +6386,10 @@ function toSuffixFromProp(propName) {
|
|
|
5693
6386
|
const raw = propName.startsWith("$") ? propName.slice(1) : propName;
|
|
5694
6387
|
if (!raw) return "Variant";
|
|
5695
6388
|
const trimmed = raw.trim();
|
|
6389
|
+
if (trimmed.includes("&&")) {
|
|
6390
|
+
const parts = trimmed.split("&&").map((s) => s.trim()).filter(Boolean);
|
|
6391
|
+
if (parts.length) return parts.map((p) => toSuffixFromProp(p)).join("");
|
|
6392
|
+
}
|
|
5696
6393
|
if (trimmed.startsWith("!")) return `Not${toSuffixFromProp(trimmed.slice(1).trim().replace(/^\(|\)$/g, ""))}`;
|
|
5697
6394
|
const eq = trimmed.includes("!==") ? "!==" : trimmed.includes("===") ? "===" : null;
|
|
5698
6395
|
if (eq) {
|