@colorye/react-native-css 0.3.0 → 0.3.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/crates/transformer/index.js +1 -0
- package/crates/transformer/transformer.darwin-arm64.node +0 -0
- package/crates/transformer/transformer.darwin-x64.node +0 -0
- package/crates/transformer/transformer.linux-x64-gnu.node +0 -0
- package/crates/transformer/transformer.node +0 -0
- package/crates/transformer/transformer.win32-x64-msvc.node +0 -0
- package/dist/babel.js +68 -159
- package/dist/index.d.ts +22 -8
- package/dist/interop.js +17 -5
- package/dist/metro.js +55 -0
- package/dist/transformer-runtime.js +170 -18
- package/dist/transformer.js +73 -20
- package/package.json +10 -1
- package/src/babel.js +71 -224
- package/src/index.d.ts +22 -8
- package/src/interop.js +13 -1
- package/src/metro.js +42 -0
- package/src/transformer-runtime.js +169 -15
- package/src/transformer.js +75 -15
- package/dist/exported-stylesheet.json +0 -1
- package/dist/features/build-transform.js +0 -575
- package/dist/features/css-calc.js +0 -539
- package/dist/features/css-media.js +0 -77
- package/dist/features/css-transform.js +0 -426
- package/dist/features/css-vars.js +0 -153
- package/dist/features/stylesheet.js +0 -45
- package/dist/utils/babel.js +0 -363
- package/dist/utils/css.js +0 -263
- package/dist/utils/helper.js +0 -11
- package/src/exported-stylesheet.json +0 -1
- package/src/features/build-transform.js +0 -536
- package/src/features/css-calc.js +0 -490
- package/src/features/css-media.js +0 -78
- package/src/features/css-transform.js +0 -446
- package/src/features/css-vars.js +0 -138
- package/src/features/stylesheet.js +0 -29
- package/src/utils/babel.js +0 -425
- package/src/utils/css.js +0 -221
- package/src/utils/helper.js +0 -3
package/src/babel.js
CHANGED
|
@@ -1,26 +1,21 @@
|
|
|
1
1
|
import fs from "fs";
|
|
2
2
|
import nodePath from "path";
|
|
3
|
-
import {
|
|
4
|
-
getInheritStyleExpression,
|
|
5
|
-
getRootInheritStyleExpression,
|
|
6
|
-
getStaticMergeExpression,
|
|
7
|
-
getStyleExpression,
|
|
8
|
-
inlineStaticAttributes,
|
|
9
|
-
isFragmentElement,
|
|
10
|
-
isImportOrRequire,
|
|
11
|
-
isRootLevelJSXElement,
|
|
12
|
-
tryGetStaticStyleInfo,
|
|
13
|
-
} from "./utils/babel.js";
|
|
3
|
+
import { parseSync } from "@babel/core";
|
|
14
4
|
|
|
15
|
-
|
|
5
|
+
let native = null;
|
|
6
|
+
try {
|
|
7
|
+
native = require("./native");
|
|
8
|
+
} catch {
|
|
9
|
+
try {
|
|
10
|
+
native = require("../crates/transformer");
|
|
11
|
+
} catch {}
|
|
12
|
+
}
|
|
16
13
|
|
|
17
|
-
|
|
14
|
+
const libRoot = nodePath.dirname(__filename);
|
|
18
15
|
const stylesheetCache = new Map();
|
|
19
16
|
|
|
20
|
-
/**
|
|
21
|
-
* Load pre-computed stylesheet JSON (generated by Metro transformer)
|
|
22
|
-
*/
|
|
23
17
|
function loadStylesheet(cssPath, fileDir) {
|
|
18
|
+
if (!cssPath) return "{}";
|
|
24
19
|
if (stylesheetCache.has(cssPath)) {
|
|
25
20
|
return stylesheetCache.get(cssPath);
|
|
26
21
|
}
|
|
@@ -29,242 +24,94 @@ function loadStylesheet(cssPath, fileDir) {
|
|
|
29
24
|
const cwd = process.cwd();
|
|
30
25
|
const cleanPath = cssPath.replace(/^@\//, "");
|
|
31
26
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
if (fileDir) {
|
|
51
|
-
const localJson = nodePath.resolve(fileDir, cssPath);
|
|
52
|
-
if (fs.existsSync(localJson)) {
|
|
53
|
-
const content = fs.readFileSync(localJson, "utf-8");
|
|
54
|
-
const stylesheet = JSON.parse(content);
|
|
55
|
-
stylesheetCache.set(cssPath, stylesheet);
|
|
56
|
-
return stylesheet;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// 3. Try resolving the module if it's a module specifier like @colorye/react-native-css/exported-stylesheet.json
|
|
61
|
-
try {
|
|
62
|
-
const resolvedModule = require.resolve(cssPath, { paths: [cwd, libRoot] });
|
|
63
|
-
if (fs.existsSync(resolvedModule)) {
|
|
64
|
-
const content = fs.readFileSync(resolvedModule, "utf-8");
|
|
65
|
-
const stylesheet = JSON.parse(content);
|
|
66
|
-
stylesheetCache.set(cssPath, stylesheet);
|
|
67
|
-
return stylesheet;
|
|
27
|
+
const candidates = [
|
|
28
|
+
nodePath.resolve(cwd, cleanPath),
|
|
29
|
+
nodePath.resolve(cwd, cleanPath.endsWith(".json") ? cleanPath : `${cleanPath}.json`),
|
|
30
|
+
fileDir ? nodePath.resolve(fileDir, cssPath) : null,
|
|
31
|
+
nodePath.resolve(cwd, "index.css.json"),
|
|
32
|
+
nodePath.resolve(cwd, "index.css"),
|
|
33
|
+
nodePath.join(libRoot, "exported-stylesheet.json"),
|
|
34
|
+
].filter(Boolean);
|
|
35
|
+
|
|
36
|
+
for (const p of candidates) {
|
|
37
|
+
if (fs.existsSync(p)) {
|
|
38
|
+
const content = fs.readFileSync(p, "utf-8");
|
|
39
|
+
let sheetJson = content;
|
|
40
|
+
if (p.endsWith(".css") && native && native.compileCss) {
|
|
41
|
+
sheetJson = native.compileCss(content);
|
|
42
|
+
}
|
|
43
|
+
stylesheetCache.set(cssPath, sheetJson);
|
|
44
|
+
return sheetJson;
|
|
68
45
|
}
|
|
69
|
-
} catch {}
|
|
70
|
-
|
|
71
|
-
// 4. Try the exported-stylesheet.json from lib directory
|
|
72
|
-
const exportedPath = nodePath.join(libRoot, "exported-stylesheet.json");
|
|
73
|
-
if (fs.existsSync(exportedPath)) {
|
|
74
|
-
const content = fs.readFileSync(exportedPath, "utf-8");
|
|
75
|
-
const stylesheet = JSON.parse(content);
|
|
76
|
-
stylesheetCache.set(cssPath, stylesheet);
|
|
77
|
-
return stylesheet;
|
|
78
46
|
}
|
|
47
|
+
} catch {}
|
|
79
48
|
|
|
80
|
-
|
|
81
|
-
const cssJsonPath = `${cssPath}.json`;
|
|
82
|
-
if (fs.existsSync(cssJsonPath)) {
|
|
83
|
-
const content = fs.readFileSync(cssJsonPath, "utf-8");
|
|
84
|
-
const stylesheet = JSON.parse(content);
|
|
85
|
-
stylesheetCache.set(cssPath, stylesheet);
|
|
86
|
-
return stylesheet;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
return null;
|
|
90
|
-
} catch {
|
|
91
|
-
return null;
|
|
92
|
-
}
|
|
49
|
+
return "{}";
|
|
93
50
|
}
|
|
94
51
|
|
|
95
|
-
export default function (
|
|
52
|
+
export default function () {
|
|
96
53
|
return {
|
|
97
54
|
name: "@colorye/react-native-css",
|
|
98
55
|
visitor: {
|
|
99
56
|
Program: {
|
|
100
57
|
enter(path, state) {
|
|
101
|
-
if (!this.opts.css) {
|
|
102
|
-
console.warn("No css file provided");
|
|
103
|
-
return;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
58
|
const { filename } = state.file.opts;
|
|
59
|
+
if (!filename || filename.includes("node_modules")) return;
|
|
60
|
+
|
|
107
61
|
const options = {
|
|
108
|
-
paths: this.opts
|
|
109
|
-
excludes: this.opts
|
|
110
|
-
css: this.opts
|
|
62
|
+
paths: this.opts?.paths || [],
|
|
63
|
+
excludes: this.opts?.excludes || [],
|
|
64
|
+
css: this.opts?.css,
|
|
111
65
|
};
|
|
112
66
|
|
|
113
|
-
// Normalize filename for cross-platform regex matching
|
|
114
67
|
const normalizedFilename = filename.replace(/\\/g, "/");
|
|
115
68
|
const regex = options.paths.map((p) => new RegExp(p));
|
|
116
69
|
const excludesRegex = options.excludes.map((p) => new RegExp(p));
|
|
70
|
+
|
|
117
71
|
if (
|
|
118
|
-
|
|
119
|
-
|
|
72
|
+
options.paths.length > 0 &&
|
|
73
|
+
!regex.some((re) => normalizedFilename.match(re) || filename.match(re))
|
|
120
74
|
) {
|
|
121
75
|
return;
|
|
122
76
|
}
|
|
77
|
+
if (excludesRegex.some((re) => normalizedFilename.match(re) || filename.match(re))) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
123
80
|
|
|
124
|
-
|
|
81
|
+
if (!native || !native.transformJsx) return;
|
|
125
82
|
|
|
126
|
-
|
|
127
|
-
state.stylesheetData = loadStylesheet(
|
|
83
|
+
const stylesheetJson = loadStylesheet(
|
|
128
84
|
options.css,
|
|
129
85
|
filename ? nodePath.dirname(filename) : null,
|
|
130
86
|
);
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
]),
|
|
155
|
-
t.identifier("default"),
|
|
156
|
-
),
|
|
157
|
-
t.identifier("getStyle"),
|
|
158
|
-
),
|
|
159
|
-
),
|
|
160
|
-
]);
|
|
161
|
-
|
|
162
|
-
state.getInheritStyleId = path.scope.generateUidIdentifier();
|
|
163
|
-
state.getInheritStyle = t.variableDeclaration("var", [
|
|
164
|
-
t.variableDeclarator(
|
|
165
|
-
state.getInheritStyleId,
|
|
166
|
-
t.memberExpression(
|
|
167
|
-
t.memberExpression(
|
|
168
|
-
t.callExpression(t.identifier("require"), [
|
|
169
|
-
t.stringLiteral("@colorye/react-native-css/dist/transformer-runtime"),
|
|
170
|
-
]),
|
|
171
|
-
t.identifier("default"),
|
|
172
|
-
),
|
|
173
|
-
t.identifier("getInheritStyle"),
|
|
174
|
-
),
|
|
175
|
-
),
|
|
176
|
-
]);
|
|
177
|
-
|
|
178
|
-
state.mergeStylesId = path.scope.generateUidIdentifier();
|
|
179
|
-
state.mergeStyles = t.variableDeclaration("var", [
|
|
180
|
-
t.variableDeclarator(
|
|
181
|
-
state.mergeStylesId,
|
|
182
|
-
t.memberExpression(
|
|
183
|
-
t.memberExpression(
|
|
184
|
-
t.callExpression(t.identifier("require"), [
|
|
185
|
-
t.stringLiteral("@colorye/react-native-css/dist/transformer-runtime"),
|
|
186
|
-
]),
|
|
187
|
-
t.identifier("default"),
|
|
188
|
-
),
|
|
189
|
-
t.identifier("mergeStyles"),
|
|
190
|
-
),
|
|
191
|
-
),
|
|
192
|
-
]);
|
|
193
|
-
},
|
|
194
|
-
exit(path, state) {
|
|
195
|
-
if (!state.enabled) return;
|
|
196
|
-
|
|
197
|
-
const helpers = [];
|
|
198
|
-
|
|
199
|
-
// Only inject helpers that are actually used
|
|
200
|
-
if (state.needsGetStyle) {
|
|
201
|
-
helpers.push(state.stylesheet);
|
|
202
|
-
helpers.push(state.getStyle);
|
|
203
|
-
}
|
|
204
|
-
if (state.needsGetInheritStyle) {
|
|
205
|
-
helpers.push(state.getInheritStyle);
|
|
206
|
-
}
|
|
207
|
-
if (state.needsMergeStyles) {
|
|
208
|
-
helpers.push(state.mergeStyles);
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
if (helpers.length === 0) return;
|
|
212
|
-
|
|
213
|
-
const lastImport = path
|
|
214
|
-
.get("body")
|
|
215
|
-
.filter((p) => isImportOrRequire(p))
|
|
216
|
-
.pop();
|
|
217
|
-
|
|
218
|
-
helpers
|
|
219
|
-
.reverse()
|
|
220
|
-
.forEach((node) =>
|
|
221
|
-
lastImport ? lastImport.insertAfter(node) : path.unshiftContainer("body", node),
|
|
222
|
-
);
|
|
223
|
-
},
|
|
224
|
-
},
|
|
225
|
-
JSXElement(path, state) {
|
|
226
|
-
if (!state.enabled) return;
|
|
227
|
-
if (isFragmentElement(t, path.node.openingElement.name)) return;
|
|
228
|
-
|
|
229
|
-
// Perform zero-runtime static style inlining for static classes
|
|
230
|
-
inlineStaticAttributes(path, state, t);
|
|
231
|
-
|
|
232
|
-
const openingElement = path.node.openingElement;
|
|
233
|
-
const isRootLevel = isRootLevelJSXElement(path);
|
|
234
|
-
|
|
235
|
-
const shouldCombineStyles = openingElement.attributes.some(
|
|
236
|
-
(attr) => attr.name?.name === "__combinedStyles",
|
|
237
|
-
);
|
|
238
|
-
|
|
239
|
-
if (shouldCombineStyles) {
|
|
240
|
-
let styleExpressions;
|
|
241
|
-
|
|
242
|
-
// Try static inlining first (if stylesheet loaded and class is static)
|
|
243
|
-
if (state.stylesheetData) {
|
|
244
|
-
const staticInfo = tryGetStaticStyleInfo(path, state, t);
|
|
245
|
-
|
|
246
|
-
if (staticInfo) {
|
|
247
|
-
// Static class! Use lightweight mergeStyles
|
|
248
|
-
styleExpressions = getStaticMergeExpression(path, state, t, staticInfo);
|
|
249
|
-
state.needsMergeStyles = true;
|
|
87
|
+
const rawCode = state.file.code;
|
|
88
|
+
|
|
89
|
+
try {
|
|
90
|
+
const res = native.transformJsx(rawCode, {
|
|
91
|
+
filename,
|
|
92
|
+
stylesheetJson,
|
|
93
|
+
sourceMaps: false,
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
if (res && res.code && res.code !== rawCode) {
|
|
97
|
+
const newAst = parseSync(res.code, {
|
|
98
|
+
filename,
|
|
99
|
+
parserOpts: {
|
|
100
|
+
plugins: ["jsx", "typescript"],
|
|
101
|
+
},
|
|
102
|
+
configFile: false,
|
|
103
|
+
babelrc: false,
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
if (newAst && newAst.program) {
|
|
107
|
+
path.replaceWith(newAst.program);
|
|
108
|
+
path.stop();
|
|
109
|
+
}
|
|
250
110
|
}
|
|
111
|
+
} catch {
|
|
112
|
+
// Silently fall back if native transformation fails
|
|
251
113
|
}
|
|
252
|
-
|
|
253
|
-
if (!styleExpressions) {
|
|
254
|
-
// Fall back to full runtime getStyle
|
|
255
|
-
state.needsGetStyle = true;
|
|
256
|
-
styleExpressions = getStyleExpression(path, state, t);
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
const style = openingElement.attributes.find((attr) => attr.name?.name === "style");
|
|
260
|
-
if (style) {
|
|
261
|
-
style.value = t.jsxExpressionContainer(styleExpressions);
|
|
262
|
-
} else {
|
|
263
|
-
openingElement.attributes.push(
|
|
264
|
-
t.jsxAttribute(t.jsxIdentifier("style"), t.jsxExpressionContainer(styleExpressions)),
|
|
265
|
-
);
|
|
266
|
-
}
|
|
267
|
-
}
|
|
114
|
+
},
|
|
268
115
|
},
|
|
269
116
|
},
|
|
270
117
|
};
|
package/src/index.d.ts
CHANGED
|
@@ -13,8 +13,20 @@ export interface GroupState {
|
|
|
13
13
|
focus?: boolean;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
+
export interface InheritedStyles {
|
|
17
|
+
color?: string;
|
|
18
|
+
fontSize?: number;
|
|
19
|
+
fontWeight?: string;
|
|
20
|
+
fontFamily?: string;
|
|
21
|
+
letterSpacing?: number;
|
|
22
|
+
lineHeight?: number;
|
|
23
|
+
textAlign?: string;
|
|
24
|
+
textTransform?: string;
|
|
25
|
+
[key: string]: any;
|
|
26
|
+
}
|
|
27
|
+
|
|
16
28
|
export const GroupContext: React.Context<GroupState>;
|
|
17
|
-
export const InheritContext: React.Context<
|
|
29
|
+
export const InheritContext: React.Context<InheritedStyles | undefined>;
|
|
18
30
|
|
|
19
31
|
export function setGlobalStylesheet(sheet: Record<string, any>): void;
|
|
20
32
|
export function getGlobalStylesheet(): Record<string, any>;
|
|
@@ -33,7 +45,7 @@ export function getGlobalStylesheet(): Record<string, any>;
|
|
|
33
45
|
* });
|
|
34
46
|
* ```
|
|
35
47
|
*/
|
|
36
|
-
export function cssInterop<P extends object>(
|
|
48
|
+
export function cssInterop<T = any, P extends object = any>(
|
|
37
49
|
Component: React.ComponentType<P>,
|
|
38
50
|
mapping?: StyleMapping
|
|
39
51
|
): React.ForwardRefExoticComponent<
|
|
@@ -41,13 +53,13 @@ export function cssInterop<P extends object>(
|
|
|
41
53
|
className?: string;
|
|
42
54
|
contentContainerClassName?: string;
|
|
43
55
|
inheritStyle?: any;
|
|
44
|
-
} & React.RefAttributes<
|
|
56
|
+
} & React.RefAttributes<T>
|
|
45
57
|
>;
|
|
46
58
|
|
|
47
59
|
/**
|
|
48
60
|
* Alias for cssInterop.
|
|
49
61
|
*/
|
|
50
|
-
export function remapProps<P extends object>(
|
|
62
|
+
export function remapProps<T = any, P extends object = any>(
|
|
51
63
|
Component: React.ComponentType<P>,
|
|
52
64
|
mapping: StyleMapping
|
|
53
65
|
): React.ForwardRefExoticComponent<
|
|
@@ -55,7 +67,7 @@ export function remapProps<P extends object>(
|
|
|
55
67
|
className?: string;
|
|
56
68
|
contentContainerClassName?: string;
|
|
57
69
|
inheritStyle?: any;
|
|
58
|
-
} & React.RefAttributes<
|
|
70
|
+
} & React.RefAttributes<T>
|
|
59
71
|
>;
|
|
60
72
|
|
|
61
73
|
export namespace Runtime {
|
|
@@ -73,6 +85,11 @@ export function getStylesheet(css: string, filename?: string): string;
|
|
|
73
85
|
export function writeStylesheetJSON(content: string, filename?: string): void;
|
|
74
86
|
export function transform(args: { src: string; filename: string; options?: any }): any;
|
|
75
87
|
|
|
88
|
+
/**
|
|
89
|
+
* Plug-and-play zero-configuration helper for Expo and React Native Metro bundler.
|
|
90
|
+
*/
|
|
91
|
+
export function withReactNativeCss<T = any>(metroConfig: T, options?: { input?: string }): T;
|
|
92
|
+
|
|
76
93
|
declare const _default: {
|
|
77
94
|
cssInterop: typeof cssInterop;
|
|
78
95
|
remapProps: typeof remapProps;
|
|
@@ -81,9 +98,6 @@ declare const _default: {
|
|
|
81
98
|
GroupContext: typeof GroupContext;
|
|
82
99
|
InheritContext: typeof InheritContext;
|
|
83
100
|
Runtime: typeof Runtime;
|
|
84
|
-
getStylesheet: typeof getStylesheet;
|
|
85
|
-
transform: typeof transform;
|
|
86
|
-
writeStylesheetJSON: typeof writeStylesheetJSON;
|
|
87
101
|
};
|
|
88
102
|
|
|
89
103
|
export default _default;
|
package/src/interop.js
CHANGED
|
@@ -1,6 +1,18 @@
|
|
|
1
1
|
import React, { createContext, forwardRef, useContext } from "react";
|
|
2
2
|
import Runtime from "./transformer-runtime.js";
|
|
3
3
|
|
|
4
|
+
function shallowEqual(a, b) {
|
|
5
|
+
if (a === b) return true;
|
|
6
|
+
if (!a || !b || typeof a !== "object" || typeof b !== "object") return false;
|
|
7
|
+
const keysA = Object.keys(a);
|
|
8
|
+
const keysB = Object.keys(b);
|
|
9
|
+
if (keysA.length !== keysB.length) return false;
|
|
10
|
+
for (const k of keysA) {
|
|
11
|
+
if (a[k] !== b[k]) return false;
|
|
12
|
+
}
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
|
|
4
16
|
export const InheritContext = createContext(undefined);
|
|
5
17
|
export const GroupContext = createContext({ pressed: false, hovered: false, focus: false });
|
|
6
18
|
|
|
@@ -249,7 +261,7 @@ export function cssInterop(Component, mapping = { className: "style" }) {
|
|
|
249
261
|
);
|
|
250
262
|
}
|
|
251
263
|
|
|
252
|
-
if (currentInherit && currentInherit
|
|
264
|
+
if (currentInherit && !shallowEqual(currentInherit, parentInherit)) {
|
|
253
265
|
return React.createElement(InheritContext.Provider, { value: currentInherit }, element);
|
|
254
266
|
}
|
|
255
267
|
|
package/src/metro.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
const fs = require("fs");
|
|
2
|
+
const path = require("path");
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* withReactNativeCss
|
|
6
|
+
*
|
|
7
|
+
* Plug-and-play zero-configuration helper for Expo and React Native Metro bundler.
|
|
8
|
+
*
|
|
9
|
+
* Automatically:
|
|
10
|
+
* 1. Configures Metro to handle .css files via @colorye/react-native-css/transformer.
|
|
11
|
+
* 2. Connects the high-performance Rust SWC native transformer for JSX/TSX.
|
|
12
|
+
* 3. Adds 'css' to sourceExts.
|
|
13
|
+
* 4. In-process caches and synchronizes stylesheet JSON without manual setup.
|
|
14
|
+
*
|
|
15
|
+
* @param {import('metro-config').MetroConfig} metroConfig
|
|
16
|
+
* @param {Object} [options]
|
|
17
|
+
* @param {string} [options.input] - Input CSS path relative to project root (default: 'src/assets/styles/index.css' or 'index.css')
|
|
18
|
+
* @returns {import('metro-config').MetroConfig}
|
|
19
|
+
*/
|
|
20
|
+
function withReactNativeCss(metroConfig, options = {}) {
|
|
21
|
+
const config = { ...metroConfig };
|
|
22
|
+
|
|
23
|
+
// Ensure resolver & transformer objects exist
|
|
24
|
+
config.resolver = config.resolver || {};
|
|
25
|
+
config.transformer = config.transformer || {};
|
|
26
|
+
|
|
27
|
+
// 1. Add 'css' to sourceExts if missing
|
|
28
|
+
const currentSourceExts = config.resolver.sourceExts || [];
|
|
29
|
+
if (!currentSourceExts.includes("css")) {
|
|
30
|
+
config.resolver.sourceExts = [...currentSourceExts, "css"];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// 2. Wrap or assign babelTransformerPath
|
|
34
|
+
const defaultTransformerPath = config.transformer.babelTransformerPath || require.resolve("./transformer");
|
|
35
|
+
config.transformer.babelTransformerPath = defaultTransformerPath;
|
|
36
|
+
|
|
37
|
+
return config;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
module.exports = {
|
|
41
|
+
withReactNativeCss,
|
|
42
|
+
};
|