Skip to content

Commit f2954ad

Browse files
skovhusclaude
andcommitted
refactor: extract shared ExprWithImports type and deduplicate extraClassNames processing
- Extract ExprWithImports type alias to eliminate repeated inline { expr, imports } definitions - Extract collectExtraClassNames helper to deduplicate identical parsing logic - Add missing draggableRegion export and CSS module fixture for test/storybook - Clean up empty section header left after moving escapeTemplateRaw Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent b7d0a65 commit f2954ad

File tree

7 files changed

+45
-28
lines changed

7 files changed

+45
-28
lines changed

src/adapter.ts

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -283,10 +283,7 @@ export type CallResolveResultWithExpr = {
283283
* When present, the codemod merges these expressions into the rendered element's
284284
* className alongside any existing static className from `.attrs()` or bridge classes.
285285
*/
286-
extraClassNames?: Array<{
287-
expr: string;
288-
imports: ImportSpec[];
289-
}>;
286+
extraClassNames?: ExprWithImports[];
290287
};
291288

292289
export type CallResolveRuntimeOnlyResult = {
@@ -312,10 +309,7 @@ export type CallResolveClassNamesResult = {
312309
/**
313310
* className expressions to merge into the component's className attribute.
314311
*/
315-
extraClassNames: Array<{
316-
expr: string;
317-
imports: ImportSpec[];
318-
}>;
312+
extraClassNames: ExprWithImports[];
319313
};
320314

321315
export type CallResolveResult =
@@ -334,6 +328,9 @@ export type ImportSource =
334328

335329
export type ImportSpec = { from: ImportSource; names: Array<{ imported: string; local?: string }> };
336330

331+
/** An expression string with its required imports, used for className emission. */
332+
export type ExprWithImports = { expr: string; imports: ImportSpec[] };
333+
337334
// ────────────────────────────────────────────────────────────────────────────
338335
// Base Component Resolution
339336
// ────────────────────────────────────────────────────────────────────────────

src/internal/builtin-handlers/types.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import type { API, JSCodeshift } from "jscodeshift";
66
import type {
77
CallResolveContext,
88
CallResolveResult,
9+
ExprWithImports,
910
ImportSource,
1011
ImportSpec,
1112
ResolveValueContext,
@@ -92,15 +93,15 @@ export type HandlerResult =
9293
/** Raw CSS text from the adapter, enabling pseudo-selector wrapping of individual properties. */
9394
cssText?: string;
9495
/** Extra className expressions from CSS modules to merge into the rendered element. */
95-
extraClassNames?: Array<{ expr: string; imports: ImportSpec[] }>;
96+
extraClassNames?: ExprWithImports[];
9697
}
9798
| {
9899
/**
99100
* The node was resolved to className expressions only (no StyleX style object).
100101
* Used for CSS modules or other class-based styles that StyleX cannot express.
101102
*/
102103
type: "resolvedClassNames";
103-
extraClassNames: Array<{ expr: string; imports: ImportSpec[] }>;
104+
extraClassNames: ExprWithImports[];
104105
resolveCallContext?: CallResolveContext;
105106
resolveCallResult?: CallResolveResult;
106107
}

src/internal/emit-wrappers/style-expr-builders.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -918,7 +918,6 @@ export function buildVariantStyleExprs(opts: {
918918
}
919919
}
920920

921-
// ---------------------------------------------------------------------------
922921
// ---------------------------------------------------------------------------
923922
// Theme boolean & pseudo style-arg helpers
924923
// ---------------------------------------------------------------------------

src/internal/lower-rules/rule-interpolated-declaration.ts

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*/
55
import type { JSCodeshift } from "jscodeshift";
66
import type { CssDeclarationIR, CssRuleIR } from "../css-ir.js";
7-
import type { CallResolveResult, ResolveValueContext } from "../../adapter.js";
7+
import type { CallResolveResult, ExprWithImports, ResolveValueContext } from "../../adapter.js";
88
import type { CallValueTransform } from "../builtin-handlers/types.js";
99
import type { StyledDecl } from "../transform-types.js";
1010
import type { WarningType } from "../logger.js";
@@ -170,6 +170,18 @@ export function handleInterpolatedDeclaration(args: InterpolatedDeclarationConte
170170
}
171171
};
172172

173+
/** Parse and store extra className expressions (from CSS modules) on the decl. */
174+
const collectExtraClassNames = (entries: ExprWithImports[]) => {
175+
decl.extraClassNames ??= [];
176+
for (const cn of entries) {
177+
addResolverImports(cn.imports);
178+
const cnExpr = parseExpr(cn.expr);
179+
if (cnExpr) {
180+
decl.extraClassNames.push({ expr: cnExpr as any });
181+
}
182+
}
183+
};
184+
173185
/**
174186
* Try to convert an identity prop with a finite string union type into static variant
175187
* buckets. Returns true if the optimization applied and the caller should `continue`.
@@ -904,14 +916,7 @@ export function handleInterpolatedDeclaration(args: InterpolatedDeclarationConte
904916
});
905917
// Store any extra className expressions (from CSS modules) on the decl
906918
if (res.extraClassNames) {
907-
decl.extraClassNames ??= [];
908-
for (const cn of res.extraClassNames) {
909-
addResolverImports(cn.imports);
910-
const cnExpr = parseExpr(cn.expr);
911-
if (cnExpr) {
912-
decl.extraClassNames.push({ expr: cnExpr as any });
913-
}
914-
}
919+
collectExtraClassNames(res.extraClassNames);
915920
}
916921
// Create an after-base segment so subsequent static properties
917922
// are placed after this helper in the stylex.props() call
@@ -923,14 +928,7 @@ export function handleInterpolatedDeclaration(args: InterpolatedDeclarationConte
923928
if (res && res.type === "resolvedClassNames") {
924929
// Adapter returned className-only result (no StyleX expr).
925930
// Store the className expressions on the decl for the emitter to merge.
926-
decl.extraClassNames ??= [];
927-
for (const cn of res.extraClassNames) {
928-
addResolverImports(cn.imports);
929-
const cnExpr = parseExpr(cn.expr);
930-
if (cnExpr) {
931-
decl.extraClassNames.push({ expr: cnExpr as any });
932-
}
933-
}
931+
collectExtraClassNames(res.extraClassNames);
934932
decl.needsWrapperComponent = true;
935933
continue;
936934
}

test-cases/fixtures.d.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@ declare module "styled-components" {
1717
export function useTheme(): TestCaseTheme;
1818
}
1919

20+
// CSS module type declarations for test fixtures.
21+
declare module "*.module.css" {
22+
const classes: Record<string, string>;
23+
export default classes;
24+
}
25+
2026
// Augment React JSX to accept the `sx` prop on intrinsic elements.
2127
// The StyleX babel plugin (≥0.18, sxPropName option) transforms
2228
// `<div sx={styles.base} />` to `<div {...stylex.props(styles.base)} />`
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
.draggableRegionDisableChildren {
2+
-webkit-app-region: drag;
3+
}
4+
5+
.draggableRegionDisableChildren > * {
6+
-webkit-app-region: no-drag;
7+
}

test-cases/lib/helpers.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,15 @@ export const scrollFadeMaskStyles = (size: number, direction?: "top" | "bottom"
247247
);
248248
`;
249249

250+
// Draggable region helper — returns a css`` RuleSet that applies electron draggable region styles.
251+
// The adapter resolves this to a CSS module className instead of a StyleX expression.
252+
export const draggableRegion = (_enable: boolean) => css`
253+
-webkit-app-region: drag;
254+
& > * {
255+
-webkit-app-region: no-drag;
256+
}
257+
`;
258+
250259
// Shadow helper — returns a box-shadow CSS string for a given level.
251260
// Used to test adapter resolution for dynamic prop args.
252261
export const shadow = (level: string): string => {

0 commit comments

Comments
 (0)