@colorye/react-native-css 0.2.1

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.
@@ -0,0 +1,419 @@
1
+ const UNSUPPORTED_PROPERTIES = ["outline"];
2
+ const remOrEmUnitRe = /([\d.]+)(?:rem|em)\b/g;
3
+
4
+ export default function CssTransform() {
5
+ this.transformUnsafeValue = (property, value) => {
6
+ if (!this.isPropertySupported(property, value)) {
7
+ console.info("UNSUPPORTED", property, value);
8
+ return [];
9
+ }
10
+
11
+ if (typeof value === "string") {
12
+ value = value.trim();
13
+ value = this.transformImportant(property, value);
14
+ }
15
+ value = this.transformPosition(property, value);
16
+ value = this.transformBorderRadius(property, value);
17
+ value = this.transformOpacity(property, value);
18
+
19
+ property = this.getAliasedPropertyName(property);
20
+
21
+ return [property, value];
22
+ };
23
+
24
+ this.transformUnsupportedUnit = (value) => {
25
+ if (value === undefined || typeof value !== "string") return value;
26
+ remOrEmUnitRe.lastIndex = 0;
27
+ return value.replace(remOrEmUnitRe, (_, rem) => {
28
+ return rem * 16;
29
+ });
30
+ };
31
+
32
+ this.transformViewportUnit = (value, { width, height } = {}) => {
33
+ if (value === undefined || typeof value !== "string") return value;
34
+ if (!width || !height) return value;
35
+
36
+ const viewportUnitRe = /([+-]?[0-9.]+)(vh|vw|vmin|vmax)\b/g;
37
+ const dimensionsMap = {
38
+ vw: width,
39
+ vh: height,
40
+ };
41
+ return value.replace(viewportUnitRe, (_, number, unit) => {
42
+ return (parseFloat(number) * dimensionsMap[unit]) / 100;
43
+ });
44
+ };
45
+
46
+ this.removeUnit = (value) => {
47
+ if (value === undefined || typeof value !== "string") return value;
48
+ return value.replace(/px/g, "");
49
+ };
50
+
51
+ this.isPropertySupported = (property, value) => {
52
+ if (UNSUPPORTED_PROPERTIES.includes(property)) return false;
53
+ if (value === undefined) return false;
54
+ if (!["number", "string"].includes(typeof value)) return false;
55
+ return true;
56
+ };
57
+
58
+ this.transformImportant = (property, value) => {
59
+ if (typeof value !== "string") return value;
60
+ return value.replace(/!important/g, "");
61
+ };
62
+
63
+ this.transformPosition = (property, value) => {
64
+ if (property === "position" && value === "fixed") {
65
+ return "absolute";
66
+ }
67
+ return value;
68
+ };
69
+
70
+ this.transformBorderRadius = (property, value) => {
71
+ if (property.toLowerCase().endsWith("radius") && typeof value === "string" && value.includes("%")) {
72
+ return 9999;
73
+ }
74
+ return value;
75
+ };
76
+
77
+ this.transformOpacity = (property, value) => {
78
+ if (property === "opacity" && typeof value === "string" && value.endsWith("%")) {
79
+ const num = parseFloat(value);
80
+ if (!isNaN(num)) {
81
+ return num / 100;
82
+ }
83
+ }
84
+ return value;
85
+ };
86
+
87
+ this.transformBorder = (property, value) => {
88
+ if (value === "none") {
89
+ return { [`${property}Width`]: 0 };
90
+ }
91
+
92
+ const borderRe = /(\S+)(?:\s+(solid|dashed|dotted)(?:\s+(\S+))?)?/g;
93
+ const [, width, style, color] = borderRe.exec(String(value)) || [];
94
+
95
+ const transformed = {};
96
+
97
+ if (width) {
98
+ transformed[`${property}Width`] = isNaN(width) ? width : Number(width);
99
+ } else {
100
+ transformed[`${property}Width`] = 0;
101
+ }
102
+
103
+ if (style) {
104
+ transformed[`${property}Style`] = style;
105
+ }
106
+
107
+ if (color) {
108
+ transformed[`${property}Color`] = color;
109
+ }
110
+
111
+ return transformed;
112
+ };
113
+
114
+ this.transformSpacing = (property, value) => {
115
+ const strValue = String(value).trim();
116
+ const parts = [];
117
+ let current = "";
118
+ let depth = 0;
119
+ for (let i = 0; i < strValue.length; i++) {
120
+ const char = strValue[i];
121
+ if (char === "(") {
122
+ depth++;
123
+ current += char;
124
+ } else if (char === ")") {
125
+ depth--;
126
+ current += char;
127
+ } else if (char === " " && depth === 0) {
128
+ if (current) {
129
+ parts.push(current);
130
+ current = "";
131
+ }
132
+ } else {
133
+ current += char;
134
+ }
135
+ }
136
+ if (current) {
137
+ parts.push(current);
138
+ }
139
+
140
+ const cleanedParts = parts.filter(Boolean);
141
+
142
+ const toNumberOrString = (val) => {
143
+ return isNaN(val) ? val : Number(val);
144
+ };
145
+
146
+ const transformed = {};
147
+
148
+ if (cleanedParts.length === 0) {
149
+ transformed[`${property}Top`] = 0;
150
+ transformed[`${property}Right`] = 0;
151
+ transformed[`${property}Bottom`] = 0;
152
+ transformed[`${property}Left`] = 0;
153
+ } else if (cleanedParts.length === 1) {
154
+ const top = cleanedParts[0];
155
+ transformed[`${property}Top`] = toNumberOrString(top);
156
+ transformed[`${property}Right`] = toNumberOrString(top);
157
+ transformed[`${property}Bottom`] = toNumberOrString(top);
158
+ transformed[`${property}Left`] = toNumberOrString(top);
159
+ } else if (cleanedParts.length === 2) {
160
+ const top = cleanedParts[0];
161
+ const right = cleanedParts[1];
162
+ transformed[`${property}Top`] = toNumberOrString(top);
163
+ transformed[`${property}Right`] = toNumberOrString(right);
164
+ transformed[`${property}Bottom`] = toNumberOrString(top);
165
+ transformed[`${property}Left`] = toNumberOrString(right);
166
+ } else if (cleanedParts.length === 3) {
167
+ const top = cleanedParts[0];
168
+ const right = cleanedParts[1];
169
+ const bottom = cleanedParts[2];
170
+ transformed[`${property}Top`] = toNumberOrString(top);
171
+ transformed[`${property}Right`] = toNumberOrString(right);
172
+ transformed[`${property}Bottom`] = toNumberOrString(bottom);
173
+ transformed[`${property}Left`] = toNumberOrString(right);
174
+ } else {
175
+ const top = cleanedParts[0];
176
+ const right = cleanedParts[1];
177
+ const bottom = cleanedParts[2];
178
+ const left = cleanedParts[3];
179
+ transformed[`${property}Top`] = toNumberOrString(top);
180
+ transformed[`${property}Right`] = toNumberOrString(right);
181
+ transformed[`${property}Bottom`] = toNumberOrString(bottom);
182
+ transformed[`${property}Left`] = toNumberOrString(left);
183
+ }
184
+
185
+ return transformed;
186
+ };
187
+
188
+ this.transformFontWeight = (property, value) => {
189
+ const fontWeightRe = /(normal|bold|100|200|300|400|500|600|700|800|900)/g;
190
+
191
+ if (!fontWeightRe.test(String(value))) return;
192
+ return {
193
+ [property]: String(value),
194
+ };
195
+ };
196
+
197
+ this.transformTransform = (property, value) => {
198
+ const transformRe =
199
+ /(perspective|rotate|rotateX|rotateY|scale|scaleX|scaleY|translate|translateX|translateY|skew|skewX|skewY)\s*\(\s*([^,)]+)[,\s]*([^)]+)?\)/g;
200
+
201
+ const transforms = [];
202
+ let match;
203
+ const strValue = String(value);
204
+ do {
205
+ match = transformRe.exec(strValue);
206
+ if (!match) break;
207
+
208
+ const [, token, val1, val2] = match;
209
+
210
+ if (["translate", "skew"].includes(token)) {
211
+ transforms.push({ [`${token}X`]: isNaN(val1) ? val1 : Number(val1) });
212
+ transforms.push({ [`${token}Y`]: isNaN(val2) ? val2 : Number(val2) });
213
+ } else {
214
+ transforms.push({ [token]: isNaN(val1) ? val1 : Number(val1) });
215
+ }
216
+ } while (match);
217
+
218
+ return {
219
+ [property]: transforms,
220
+ };
221
+ };
222
+
223
+ this.transformFontScaling = (property, value, { width, roundFn }) => {
224
+ if (!["fontSize", "lineHeight"].includes(property)) return value;
225
+
226
+ // Base width for design (iPhone 6/7/8)
227
+ const baseWidth = 375;
228
+
229
+ // Calculate scaling factor based on device width
230
+ const scaleFactor = width ? width / baseWidth : 1;
231
+ if (!isNaN(value)) {
232
+ return roundFn(Number(value) * scaleFactor);
233
+ }
234
+
235
+ return value;
236
+ };
237
+
238
+ this.transformLogicalProperty = (property, value) => {
239
+ const strValue = String(value).trim();
240
+ const parts = [];
241
+ let current = "";
242
+ let depth = 0;
243
+ for (let i = 0; i < strValue.length; i++) {
244
+ const char = strValue[i];
245
+ if (char === "(") {
246
+ depth++;
247
+ current += char;
248
+ } else if (char === ")") {
249
+ depth--;
250
+ current += char;
251
+ } else if (char === " " && depth === 0) {
252
+ if (current) {
253
+ parts.push(current);
254
+ current = "";
255
+ }
256
+ } else {
257
+ current += char;
258
+ }
259
+ }
260
+ if (current) {
261
+ parts.push(current);
262
+ }
263
+
264
+ const cleanedParts = parts.filter(Boolean);
265
+
266
+ const toNumberOrString = (val) => {
267
+ return isNaN(val) ? val : Number(val);
268
+ };
269
+
270
+ if (property === "paddingInlineStart") return { paddingStart: toNumberOrString(value) };
271
+ if (property === "paddingInlineEnd") return { paddingEnd: toNumberOrString(value) };
272
+ if (property === "marginInlineStart") return { marginStart: toNumberOrString(value) };
273
+ if (property === "marginInlineEnd") return { marginEnd: toNumberOrString(value) };
274
+ if (property === "insetInlineStart") return { start: toNumberOrString(value) };
275
+ if (property === "insetInlineEnd") return { end: toNumberOrString(value) };
276
+ if (property === "insetBlockStart") return { top: toNumberOrString(value) };
277
+ if (property === "insetBlockEnd") return { bottom: toNumberOrString(value) };
278
+
279
+ if (property === "paddingInline") {
280
+ if (cleanedParts.length === 1) {
281
+ return { paddingHorizontal: toNumberOrString(cleanedParts[0]) };
282
+ }
283
+ if (cleanedParts.length >= 2) {
284
+ return {
285
+ paddingStart: toNumberOrString(cleanedParts[0]),
286
+ paddingEnd: toNumberOrString(cleanedParts[1]),
287
+ };
288
+ }
289
+ }
290
+
291
+ if (property === "marginInline") {
292
+ if (cleanedParts.length === 1) {
293
+ return { marginHorizontal: toNumberOrString(cleanedParts[0]) };
294
+ }
295
+ if (cleanedParts.length >= 2) {
296
+ return {
297
+ marginStart: toNumberOrString(cleanedParts[0]),
298
+ marginEnd: toNumberOrString(cleanedParts[1]),
299
+ };
300
+ }
301
+ }
302
+
303
+ if (property === "paddingBlock") {
304
+ if (cleanedParts.length === 1) {
305
+ return { paddingVertical: toNumberOrString(cleanedParts[0]) };
306
+ }
307
+ if (cleanedParts.length >= 2) {
308
+ return {
309
+ paddingTop: toNumberOrString(cleanedParts[0]),
310
+ paddingBottom: toNumberOrString(cleanedParts[1]),
311
+ };
312
+ }
313
+ }
314
+
315
+ if (property === "marginBlock") {
316
+ if (cleanedParts.length === 1) {
317
+ return { marginVertical: toNumberOrString(cleanedParts[0]) };
318
+ }
319
+ if (cleanedParts.length >= 2) {
320
+ return {
321
+ marginTop: toNumberOrString(cleanedParts[0]),
322
+ marginBottom: toNumberOrString(cleanedParts[1]),
323
+ };
324
+ }
325
+ }
326
+
327
+ if (property === "insetInline") {
328
+ if (cleanedParts.length === 1) {
329
+ return {
330
+ left: toNumberOrString(cleanedParts[0]),
331
+ right: toNumberOrString(cleanedParts[0]),
332
+ };
333
+ }
334
+ if (cleanedParts.length >= 2) {
335
+ return {
336
+ start: toNumberOrString(cleanedParts[0]),
337
+ end: toNumberOrString(cleanedParts[1]),
338
+ };
339
+ }
340
+ }
341
+
342
+ if (property === "insetBlock") {
343
+ if (cleanedParts.length === 1) {
344
+ return {
345
+ top: toNumberOrString(cleanedParts[0]),
346
+ bottom: toNumberOrString(cleanedParts[0]),
347
+ };
348
+ }
349
+ if (cleanedParts.length >= 2) {
350
+ return {
351
+ top: toNumberOrString(cleanedParts[0]),
352
+ bottom: toNumberOrString(cleanedParts[1]),
353
+ };
354
+ }
355
+ }
356
+
357
+ return null;
358
+ };
359
+
360
+ this.transform = (property, value, { width, height }) => {
361
+ if (property.toLowerCase().endsWith("radius")) {
362
+ value = this.transformBorderRadius(property, value);
363
+ }
364
+
365
+ if (property === "opacity") {
366
+ value = this.transformOpacity(property, value);
367
+ }
368
+
369
+ if (
370
+ [
371
+ "paddingInline",
372
+ "marginInline",
373
+ "paddingBlock",
374
+ "marginBlock",
375
+ "paddingInlineStart",
376
+ "paddingInlineEnd",
377
+ "marginInlineStart",
378
+ "marginInlineEnd",
379
+ "insetInline",
380
+ "insetInlineStart",
381
+ "insetInlineEnd",
382
+ "insetBlock",
383
+ "insetBlockStart",
384
+ "insetBlockEnd",
385
+ ].includes(property)
386
+ ) {
387
+ return this.transformLogicalProperty(property, value);
388
+ }
389
+
390
+ if (["border", "borderTop", "borderBottom", "borderLeft", "borderRight"].includes(property)) {
391
+ return this.transformBorder(property, value);
392
+ }
393
+
394
+ if (["padding", "margin"].includes(property)) {
395
+ return this.transformSpacing(property, value);
396
+ }
397
+
398
+ if (["flex"].includes(property)) {
399
+ return { flex: parseInt(value) };
400
+ }
401
+
402
+ if (["fontWeight"].includes(property)) {
403
+ return this.transformFontWeight(property, value);
404
+ }
405
+
406
+ if (["transform"].includes(property)) {
407
+ return this.transformTransform(property, value);
408
+ }
409
+
410
+ return { [property]: isNaN(value) ? value : Number(value) };
411
+ };
412
+
413
+ this.getAliasedPropertyName = (property) => {
414
+ if (property === "background") property = "backgroundColor";
415
+ return property;
416
+ };
417
+
418
+ return this;
419
+ }
@@ -0,0 +1,93 @@
1
+ import CssMedia from "./css-media";
2
+
3
+ const DEFAULT_VARIABLE_VALUE = 0;
4
+
5
+ export default function CssVars() {
6
+ this.global = {};
7
+ this.data = {};
8
+
9
+ const media = new CssMedia();
10
+
11
+ this.setGlobal = (declarations, { width, height } = {}) => {
12
+ for (const property in declarations) {
13
+ const value = declarations[property];
14
+
15
+ const [isMedia, matchedMedia] = media.match(property, { width, height });
16
+ if (isMedia) {
17
+ if (matchedMedia) {
18
+ this.setGlobal(value);
19
+ }
20
+
21
+ continue;
22
+ }
23
+
24
+ if (this.isVar(property)) {
25
+ this.global[property] = value;
26
+ }
27
+ }
28
+ };
29
+
30
+ this.getGlobal = () => {
31
+ return this.global;
32
+ };
33
+
34
+ this.set = (selector, declarations, { width, height } = {}) => {
35
+ for (const property in declarations) {
36
+ const value = declarations[property];
37
+
38
+ const [isMedia, matchedMedia] = media.match(property, { width, height });
39
+ if (isMedia) {
40
+ if (matchedMedia) {
41
+ this.set(selector, value);
42
+ }
43
+
44
+ continue;
45
+ }
46
+
47
+ if (this.isVar(property)) {
48
+ if (!this.data[selector]) this.data[selector] = {};
49
+ this.data[selector][property] = value;
50
+ }
51
+ }
52
+ };
53
+
54
+ this.get = (selector) => {
55
+ return {
56
+ ...this.global,
57
+ ...(this.data[selector] || {}),
58
+ };
59
+ };
60
+
61
+ this.isVar = (property) => {
62
+ return /^--[\w-]+/.test(property);
63
+ };
64
+
65
+ this.injectVar = (selector, value) => {
66
+ if (value === undefined) return value;
67
+
68
+ const variables = this.get(selector);
69
+ const resolve = (val, seen = new Set()) => {
70
+ if (typeof val !== "string") return val;
71
+
72
+ return val.replace(
73
+ /var\((--[^,)]+)(?:,\s*([^)]*))?\)/g,
74
+ function (match, variableName, defaultValue) {
75
+ if (seen.has(variableName)) {
76
+ return defaultValue !== undefined ? defaultValue : DEFAULT_VARIABLE_VALUE;
77
+ }
78
+ seen.add(variableName);
79
+ const resolvedVal = variables[variableName];
80
+ if (resolvedVal === undefined || resolvedVal === "initial") {
81
+ return defaultValue !== undefined ? defaultValue : DEFAULT_VARIABLE_VALUE;
82
+ }
83
+ return resolve(resolvedVal, seen);
84
+ },
85
+ );
86
+ };
87
+
88
+ const resolved = resolve(value);
89
+ return resolved;
90
+ };
91
+
92
+ return this;
93
+ }
@@ -0,0 +1,82 @@
1
+ import { camelize } from "../utils/helper";
2
+ import { precomputeDeclaration } from "./build-transform";
3
+
4
+ const SUPPORTED_RULE_TYPES = ["rule", "media"];
5
+
6
+ // Regex for CSS variable detection
7
+ const cssVarRe = /^--[\w-]+/;
8
+
9
+ export default function Stylesheet() {
10
+ // Store raw declarations (before pre-computation)
11
+ this.rawStylesheet = {};
12
+ // Store pre-computed declarations
13
+ this.stylesheet = {};
14
+
15
+ const _getSelectorName = (selector) => {
16
+ if (selector === ":root") return selector;
17
+ return selector.replace(/^\./, "").replace(/\\/g, ""); // remove escape backslash
18
+ };
19
+
20
+ const isVar = (property) => {
21
+ return cssVarRe.test(property);
22
+ };
23
+
24
+ this.isRuleTypeSupported = (type) => {
25
+ return SUPPORTED_RULE_TYPES.includes(type);
26
+ };
27
+
28
+ this.isSelectorSupported = (selector) => {
29
+ if (selector === ":root") return true;
30
+ if (selector.includes(" ")) return false;
31
+ if (!selector.startsWith(".")) return false;
32
+ return true;
33
+ };
34
+
35
+ this.simplifyDeclarations = (declarations) => {
36
+ return (declarations || []).reduce((res, declaration) => {
37
+ if (declaration.type !== "declaration") return res;
38
+
39
+ const { property, value } = declaration;
40
+ if (isVar(property)) {
41
+ res[property] = value;
42
+ } else {
43
+ res[camelize(property)] = value;
44
+ }
45
+
46
+ return res;
47
+ }, {});
48
+ };
49
+
50
+ this.upsert = (selector, declarations) => {
51
+ const selectorName = _getSelectorName(selector);
52
+
53
+ // Merge raw declarations
54
+ this.rawStylesheet[selectorName] = {
55
+ ...this.rawStylesheet[selectorName],
56
+ ...declarations,
57
+ };
58
+ };
59
+
60
+ this.finalize = () => {
61
+ // Pre-compute all declarations at the end
62
+ for (const [selector, rawDecl] of Object.entries(this.rawStylesheet)) {
63
+ const { _static, _dynamic, _hasDynamic } = precomputeDeclaration(rawDecl);
64
+
65
+ if (_hasDynamic) {
66
+ // Has dynamic properties - store both static and dynamic
67
+ this.stylesheet[selector] = { _static, _dynamic };
68
+ } else {
69
+ // Fully static - just store the static object directly
70
+ this.stylesheet[selector] = _static;
71
+ }
72
+ }
73
+ };
74
+
75
+ this.toJSON = () => {
76
+ // Finalize pre-computation before serializing
77
+ this.finalize();
78
+ return JSON.stringify(this.stylesheet);
79
+ };
80
+
81
+ return this;
82
+ }
package/src/index.js ADDED
@@ -0,0 +1,123 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import { parse as cssParse } from "css";
4
+ import Stylesheet from "./features/stylesheet";
5
+ import { preprocessTailwindCss } from "./utils/css";
6
+
7
+ function getStylesheet(css, filename) {
8
+ // 1. Run Tailwind CSS v4 preprocessing (supports oklch, @layer flattening, etc.)
9
+ const preprocessedCss = preprocessTailwindCss(css);
10
+ const ast = cssParse(preprocessedCss);
11
+ const stylesheet = new Stylesheet();
12
+
13
+ // Process regular rules
14
+ for (const rule of ast.stylesheet.rules || []) {
15
+ if (!stylesheet.isRuleTypeSupported(rule.type)) continue;
16
+ if (rule.type === "rule") {
17
+ const declarations = stylesheet.simplifyDeclarations(rule.declarations);
18
+
19
+ rule.selectors.forEach((selector) => {
20
+ if (!stylesheet.isSelectorSupported(selector)) return;
21
+ stylesheet.upsert(selector, declarations);
22
+ });
23
+ }
24
+ }
25
+
26
+ // Process @media rules (injected at the end)
27
+ for (const rule of ast.stylesheet.rules || []) {
28
+ if (!stylesheet.isRuleTypeSupported(rule.type)) continue;
29
+ if (rule.type === "media") {
30
+ for (const mediaRule of rule.rules || []) {
31
+ if (!stylesheet.isRuleTypeSupported(mediaRule.type)) continue;
32
+ if (mediaRule.type === "rule") {
33
+ const declarations = stylesheet.simplifyDeclarations(mediaRule.declarations);
34
+
35
+ mediaRule.selectors.forEach((selector) => {
36
+ if (!stylesheet.isSelectorSupported(selector)) return;
37
+ stylesheet.upsert(selector, { [`@media ${rule.media}`]: declarations });
38
+ });
39
+ }
40
+ }
41
+ }
42
+ }
43
+
44
+ const jsonContent = stylesheet.toJSON();
45
+
46
+ // Always write the pre-computed stylesheet for Babel to read
47
+ writeStylesheetJSON(jsonContent, filename);
48
+
49
+ return jsonContent;
50
+ }
51
+
52
+ function writeStylesheetJSON(content, filename) {
53
+ try {
54
+ // Write to lib directory (where dist will be)
55
+ const libDir = path.join(__dirname);
56
+ fs.writeFileSync(path.join(libDir, "exported-stylesheet.json"), content, { mode: 0o755 });
57
+
58
+ // Also write next to the source CSS file for easier debugging
59
+ if (filename) {
60
+ fs.writeFileSync(`${filename}.json`, content, { mode: 0o755 });
61
+ }
62
+ } catch {
63
+ // Silently fail - Babel will fall back to runtime
64
+ }
65
+ }
66
+
67
+ module.exports.transform = function ({ src, filename, options }) {
68
+ const projectRoot =
69
+ options && options.projectRoot ? options.projectRoot : process.cwd();
70
+
71
+ const resolveTransformer = (() => {
72
+ const resolveOptions = { paths: [projectRoot] };
73
+ try {
74
+ return require(
75
+ require.resolve("@expo/metro-config/babel-transformer", resolveOptions),
76
+ );
77
+ } catch (error) {
78
+ try {
79
+ return require(
80
+ require.resolve(
81
+ "@react-native/metro-babel-transformer",
82
+ resolveOptions,
83
+ ),
84
+ );
85
+ } catch (error2) {
86
+ try {
87
+ return require(
88
+ require.resolve(
89
+ "metro-react-native-babel-transformer",
90
+ resolveOptions,
91
+ ),
92
+ );
93
+ } catch (err) {
94
+ // Fallback to normal require in case of non-standard setups
95
+ try {
96
+ return require("@expo/metro-config/babel-transformer");
97
+ } catch (e) {
98
+ try {
99
+ return require("@react-native/metro-babel-transformer");
100
+ } catch (e2) {
101
+ try {
102
+ return require("metro-react-native-babel-transformer");
103
+ } catch (e3) {
104
+ throw new Error(
105
+ "Failed to load any upstream babel-transformer. Please ensure either '@expo/metro-config', '@react-native/metro-babel-transformer', or 'metro-react-native-babel-transformer' is installed."
106
+ );
107
+ }
108
+ }
109
+ }
110
+ }
111
+ }
112
+ }
113
+ })();
114
+
115
+ if (filename.endsWith(".css")) {
116
+ return resolveTransformer.transform({
117
+ src: `module.exports = ${getStylesheet(src, filename)}`,
118
+ filename,
119
+ options,
120
+ });
121
+ }
122
+ return resolveTransformer.transform({ src, filename, options });
123
+ };