styled-components-to-stylex-codemod 0.0.2 → 0.0.3
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 +40 -0
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +2 -1
- package/dist/{logger-Ckk2VkqY.mjs → logger-Dhb8r1Ry.mjs} +29 -2
- package/dist/{transform-types-Cry4CAGJ.d.mts → transform-types-t2Vk9Bka.d.mts} +36 -0
- package/dist/transform.d.mts +1 -1
- package/dist/transform.mjs +2547 -1713
- package/package.json +22 -22
package/README.md
CHANGED
|
@@ -147,6 +147,46 @@ Adapters are the main extension point. They let you control:
|
|
|
147
147
|
- what extra imports to inject into transformed files (returned from `resolveValue`)
|
|
148
148
|
- how helper calls are resolved (via `resolveValue({ kind: "call", ... })`)
|
|
149
149
|
- which exported components should support external className/style extension (`shouldSupportExternalStyling`)
|
|
150
|
+
- how className/style merging is handled for components accepting external styling (`styleMerger`)
|
|
151
|
+
|
|
152
|
+
#### Style Merger
|
|
153
|
+
|
|
154
|
+
When a component accepts external `className` and/or `style` props (e.g., via `shouldSupportExternalStyling`, or when wrapping a base component that already accepts these props), the generated code needs to merge StyleX styles with externally passed values.
|
|
155
|
+
|
|
156
|
+
> **Note:** Allowing external className/style props is generally discouraged in StyleX as it bypasses the type-safe styling system. However, it can be useful during migration to maintain compatibility with existing code that passes these props.
|
|
157
|
+
|
|
158
|
+
By default, this generates verbose inline merging code. You can provide a `styleMerger` to use a helper function instead for cleaner output:
|
|
159
|
+
|
|
160
|
+
```ts
|
|
161
|
+
const adapter = defineAdapter({
|
|
162
|
+
resolveValue(ctx) {
|
|
163
|
+
// ... value resolution logic
|
|
164
|
+
return null;
|
|
165
|
+
},
|
|
166
|
+
|
|
167
|
+
shouldSupportExternalStyling(ctx) {
|
|
168
|
+
return ctx.filePath.includes("/shared/components/");
|
|
169
|
+
},
|
|
170
|
+
|
|
171
|
+
// Use a custom merger function for cleaner output
|
|
172
|
+
styleMerger: {
|
|
173
|
+
functionName: "mergedSx",
|
|
174
|
+
importSource: { kind: "specifier", value: "./lib/mergedSx" },
|
|
175
|
+
},
|
|
176
|
+
});
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
The merger function should have this signature:
|
|
180
|
+
|
|
181
|
+
```ts
|
|
182
|
+
function mergedSx(
|
|
183
|
+
styles: StyleXStyles,
|
|
184
|
+
className?: string,
|
|
185
|
+
style?: React.CSSProperties
|
|
186
|
+
): ReturnType<typeof stylex.props>;
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
See [`test-cases/lib/mergedSx.ts`](./test-cases/lib/mergedSx.ts) for a reference implementation.
|
|
150
190
|
|
|
151
191
|
#### External Styles Support
|
|
152
192
|
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as defineAdapter, i as Adapter, r as TransformWarning } from "./transform-types-
|
|
1
|
+
import { a as defineAdapter, i as Adapter, r as TransformWarning } from "./transform-types-t2Vk9Bka.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/internal/logger.d.ts
|
|
4
4
|
interface CollectedWarning extends TransformWarning {
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as describeValue, i as assertValidAdapter, n as logWarning, t as flushWarnings } from "./logger-
|
|
1
|
+
import { a as describeValue, i as assertValidAdapter, n as logWarning, t as flushWarnings } from "./logger-Dhb8r1Ry.mjs";
|
|
2
2
|
import { run } from "jscodeshift/src/Runner.js";
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
4
|
import { dirname, join } from "node:path";
|
|
@@ -93,6 +93,7 @@ async function runTransform(options) {
|
|
|
93
93
|
const adapter = options.adapter;
|
|
94
94
|
assertValidAdapter(adapter, "runTransform(options)");
|
|
95
95
|
const adapterWithLogging = {
|
|
96
|
+
styleMerger: adapter.styleMerger,
|
|
96
97
|
shouldSupportExternalStyling(ctx) {
|
|
97
98
|
return adapter.shouldSupportExternalStyling(ctx);
|
|
98
99
|
},
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
//#region src/internal/public-api-validation.ts
|
|
2
|
-
const ADAPTER_DOCS_URL = `https://github.com/skovhus/styled-components-to-stylex-codemod#adapter`;
|
|
3
2
|
function describeValue(value) {
|
|
4
3
|
if (value === null) return "null";
|
|
5
4
|
if (value === void 0) return "undefined";
|
|
@@ -52,11 +51,38 @@ function assertValidAdapter(candidate, where) {
|
|
|
52
51
|
`Docs/examples: ${ADAPTER_DOCS_URL}`
|
|
53
52
|
].join("\n"));
|
|
54
53
|
if (typeof shouldSupportExternalStyling !== "function") throw new Error([`[styled-components-to-stylex] ${where}: adapter.shouldSupportExternalStyling must be a function.`, `Received: shouldSupportExternalStyling=${describeValue(shouldSupportExternalStyling)}`].join("\n"));
|
|
54
|
+
const styleMerger = obj?.styleMerger;
|
|
55
|
+
if (styleMerger !== null && styleMerger !== void 0) {
|
|
56
|
+
if (typeof styleMerger !== "object") throw new Error([
|
|
57
|
+
`[styled-components-to-stylex] ${where}: adapter.styleMerger must be null or an object.`,
|
|
58
|
+
`Received: styleMerger=${describeValue(styleMerger)}`,
|
|
59
|
+
"",
|
|
60
|
+
"Expected shape:",
|
|
61
|
+
" {",
|
|
62
|
+
" functionName: \"stylexProps\",",
|
|
63
|
+
" importSource: { kind: \"specifier\", value: \"@company/ui-utils\" }",
|
|
64
|
+
" }"
|
|
65
|
+
].join("\n"));
|
|
66
|
+
const { functionName, importSource } = styleMerger;
|
|
67
|
+
if (typeof functionName !== "string" || !functionName.trim()) throw new Error([`[styled-components-to-stylex] ${where}: adapter.styleMerger.functionName must be a non-empty string.`, `Received: functionName=${describeValue(functionName)}`].join("\n"));
|
|
68
|
+
if (!importSource || typeof importSource !== "object") throw new Error([
|
|
69
|
+
`[styled-components-to-stylex] ${where}: adapter.styleMerger.importSource must be an object.`,
|
|
70
|
+
`Received: importSource=${describeValue(importSource)}`,
|
|
71
|
+
"",
|
|
72
|
+
"Expected shape:",
|
|
73
|
+
" { kind: \"specifier\", value: \"@company/ui-utils\" }",
|
|
74
|
+
" or",
|
|
75
|
+
" { kind: \"absolutePath\", value: \"/path/to/module.ts\" }"
|
|
76
|
+
].join("\n"));
|
|
77
|
+
const { kind, value } = importSource;
|
|
78
|
+
if (kind !== "specifier" && kind !== "absolutePath") throw new Error([`[styled-components-to-stylex] ${where}: adapter.styleMerger.importSource.kind must be "specifier" or "absolutePath".`, `Received: kind=${describeValue(kind)}`].join("\n"));
|
|
79
|
+
if (typeof value !== "string" || !value.trim()) throw new Error([`[styled-components-to-stylex] ${where}: adapter.styleMerger.importSource.value must be a non-empty string.`, `Received: value=${describeValue(value)}`].join("\n"));
|
|
80
|
+
}
|
|
55
81
|
}
|
|
82
|
+
const ADAPTER_DOCS_URL = `https://github.com/skovhus/styled-components-to-stylex-codemod#adapter`;
|
|
56
83
|
|
|
57
84
|
//#endregion
|
|
58
85
|
//#region src/internal/logger.ts
|
|
59
|
-
let collected = [];
|
|
60
86
|
/**
|
|
61
87
|
* Clear collected warnings and return them.
|
|
62
88
|
*/
|
|
@@ -84,6 +110,7 @@ function logWarnings(warnings, filePath) {
|
|
|
84
110
|
logWarning(`[styled-components-to-stylex] Warning${warning.loc ? ` (${filePath}:${warning.loc.line}:${warning.loc.column})` : ` (${filePath})`}: ${warning.message}\n`);
|
|
85
111
|
}
|
|
86
112
|
}
|
|
113
|
+
let collected = [];
|
|
87
114
|
|
|
88
115
|
//#endregion
|
|
89
116
|
export { describeValue as a, assertValidAdapter as i, logWarning as n, logWarnings as r, flushWarnings as t };
|
|
@@ -87,6 +87,26 @@ interface ExternalStylesContext {
|
|
|
87
87
|
/** Whether it's a default export */
|
|
88
88
|
isDefaultExport: boolean;
|
|
89
89
|
}
|
|
90
|
+
/**
|
|
91
|
+
* Configuration for a custom style merger function that combines stylex.props()
|
|
92
|
+
* results with external className/style props.
|
|
93
|
+
*
|
|
94
|
+
* When configured, generates cleaner output:
|
|
95
|
+
* `{...stylexProps(styles.foo, className, style)}`
|
|
96
|
+
* instead of the verbose pattern:
|
|
97
|
+
* `{...sx} className={[sx.className, className].filter(Boolean).join(" ")} style={{...sx.style, ...style}}`
|
|
98
|
+
*/
|
|
99
|
+
interface StyleMergerConfig {
|
|
100
|
+
/**
|
|
101
|
+
* Function name to use for merging (e.g., "stylexProps" or "mergeStylexProps").
|
|
102
|
+
*/
|
|
103
|
+
functionName: string;
|
|
104
|
+
/**
|
|
105
|
+
* Import source for the merger function.
|
|
106
|
+
* Example: `{ kind: "specifier", value: "@company/ui-utils" }`
|
|
107
|
+
*/
|
|
108
|
+
importSource: ImportSource;
|
|
109
|
+
}
|
|
90
110
|
interface Adapter {
|
|
91
111
|
/** Unified resolver for theme paths + CSS variables. Return null to leave unresolved. */
|
|
92
112
|
resolveValue: (context: ResolveContext) => ResolveResult | null;
|
|
@@ -96,6 +116,22 @@ interface Adapter {
|
|
|
96
116
|
* className/style/rest merging.
|
|
97
117
|
*/
|
|
98
118
|
shouldSupportExternalStyling: (context: ExternalStylesContext) => boolean;
|
|
119
|
+
/**
|
|
120
|
+
* Custom merger function for className/style combining.
|
|
121
|
+
* When provided, generates cleaner output using this function instead of
|
|
122
|
+
* the verbose className/style merging pattern.
|
|
123
|
+
* Set to `null` to use the verbose pattern (default).
|
|
124
|
+
*
|
|
125
|
+
* Expected merger function signature:
|
|
126
|
+
* ```typescript
|
|
127
|
+
* function merger(
|
|
128
|
+
* styles: StyleXStyles | StyleXStyles[],
|
|
129
|
+
* className?: string,
|
|
130
|
+
* style?: React.CSSProperties
|
|
131
|
+
* ): { className?: string; style?: React.CSSProperties }
|
|
132
|
+
* ```
|
|
133
|
+
*/
|
|
134
|
+
styleMerger: StyleMergerConfig | null;
|
|
99
135
|
}
|
|
100
136
|
/**
|
|
101
137
|
* Helper for nicer user authoring + type inference.
|
package/dist/transform.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as TransformResult, r as TransformWarning, t as TransformOptions } from "./transform-types-
|
|
1
|
+
import { n as TransformResult, r as TransformWarning, t as TransformOptions } from "./transform-types-t2Vk9Bka.mjs";
|
|
2
2
|
import { API, FileInfo, Options } from "jscodeshift";
|
|
3
3
|
|
|
4
4
|
//#region src/transform.d.ts
|