@colorye/react-native-css 0.3.1 → 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 +3 -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/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/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
|
@@ -7,6 +7,7 @@ try {
|
|
|
7
7
|
|
|
8
8
|
const Appearance = RN.Appearance || { getColorScheme: () => "light" };
|
|
9
9
|
const Dimensions = RN.Dimensions || { get: () => ({ width: 375, height: 812 }) };
|
|
10
|
+
const Platform = RN.Platform || { OS: "ios" };
|
|
10
11
|
|
|
11
12
|
// ============================================================================
|
|
12
13
|
// Constants
|
|
@@ -57,7 +58,8 @@ function getColorScheme() {
|
|
|
57
58
|
function getCacheKey() {
|
|
58
59
|
const { width, height } = getDimensions();
|
|
59
60
|
const colorScheme = getColorScheme();
|
|
60
|
-
|
|
61
|
+
const os = Platform?.OS || "ios";
|
|
62
|
+
return `${width}x${height}:${colorScheme}:${os}`;
|
|
61
63
|
}
|
|
62
64
|
|
|
63
65
|
function invalidateCache() {
|
|
@@ -120,6 +122,110 @@ function getFlattenStyle(declarations) {
|
|
|
120
122
|
return Object.keys(result).length > 0 ? result : undefined;
|
|
121
123
|
}
|
|
122
124
|
|
|
125
|
+
function resolveCssVars(val, rootVars, localVars) {
|
|
126
|
+
if (typeof val !== "string" || !val.includes("var(")) return val;
|
|
127
|
+
let res = val;
|
|
128
|
+
let iterations = 0;
|
|
129
|
+
while (res.includes("var(") && iterations < 5) {
|
|
130
|
+
iterations++;
|
|
131
|
+
res = res.replace(/var\(\s*(--[a-zA-Z0-9_-]+)(?:\s*,\s*([^)]+))?\s*\)/g, (_, name, fb) => {
|
|
132
|
+
if (localVars && localVars[name] !== undefined) return localVars[name];
|
|
133
|
+
return rootVars[name] !== undefined ? rootVars[name] : (fb || "");
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
return res;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function resolveCssValue(prop, val, rootVars, localVars) {
|
|
140
|
+
if (typeof val !== "string") return val;
|
|
141
|
+
let v = resolveCssVars(val, rootVars, localVars).trim();
|
|
142
|
+
|
|
143
|
+
if (prop === "boxShadow") {
|
|
144
|
+
const parts = v
|
|
145
|
+
.split(/,(?![^(]*\))/)
|
|
146
|
+
.map((p) => p.trim())
|
|
147
|
+
.filter((p) => p && !p.includes("0 0 #0000") && !p.includes("0 0 #000") && !p.includes("0 0 0 0"));
|
|
148
|
+
if (parts.length === 0) return undefined;
|
|
149
|
+
v = parts.join(", ");
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
if (v.startsWith("calc(") && v.endsWith(")")) {
|
|
153
|
+
let inner = v.slice(5, -1).trim();
|
|
154
|
+
inner = inner.replace(/([\d.]+)rem/g, (_, n) => parseFloat(n) * 16 + "px");
|
|
155
|
+
inner = inner.replace(/px/g, "");
|
|
156
|
+
try {
|
|
157
|
+
v = Function('"use strict"; return (' + inner + ')')();
|
|
158
|
+
} catch {}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (typeof v === "string" && v.endsWith("rem")) {
|
|
162
|
+
v = parseFloat(v) * 16;
|
|
163
|
+
} else if (typeof v === "string" && v.endsWith("px")) {
|
|
164
|
+
v = parseFloat(v);
|
|
165
|
+
} else if (typeof v === "string" && (v.endsWith("vh") || v.endsWith("vw"))) {
|
|
166
|
+
v = parseFloat(v) + "%";
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (prop.toLowerCase().endsWith("radius") && (v === "50%" || v === "9999px" || v === 9999)) {
|
|
170
|
+
return 9999;
|
|
171
|
+
}
|
|
172
|
+
if (prop === "fontWeight") {
|
|
173
|
+
return String(v).replace("px", "").replace("rem", "");
|
|
174
|
+
}
|
|
175
|
+
if (
|
|
176
|
+
typeof v === "string" &&
|
|
177
|
+
!isNaN(Number(v)) &&
|
|
178
|
+
!["color", "fontFamily", "fontWeight"].includes(prop) &&
|
|
179
|
+
!prop.endsWith("Color")
|
|
180
|
+
) {
|
|
181
|
+
v = Number(v);
|
|
182
|
+
}
|
|
183
|
+
return v;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
function applyResolvedEntry(resolved, entry, rootVars) {
|
|
187
|
+
if (!entry) return;
|
|
188
|
+
|
|
189
|
+
const localVars = {};
|
|
190
|
+
if (entry._static) {
|
|
191
|
+
for (const [k, v] of Object.entries(entry._static)) {
|
|
192
|
+
if (k.startsWith("--") && typeof v === "string") {
|
|
193
|
+
localVars[k] = v;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
if (entry._static) {
|
|
199
|
+
for (const [k, v] of Object.entries(entry._static)) {
|
|
200
|
+
if (k.startsWith("--")) continue;
|
|
201
|
+
const val = resolveCssValue(k, v, rootVars, localVars);
|
|
202
|
+
if (val !== undefined && val !== null) {
|
|
203
|
+
resolved[k] = val;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
if (entry._dynamic) {
|
|
209
|
+
for (const [k, v] of Object.entries(entry._dynamic)) {
|
|
210
|
+
if (k.startsWith("--")) continue;
|
|
211
|
+
const val = resolveCssValue(k, v, rootVars, localVars);
|
|
212
|
+
if (val !== undefined && val !== null) {
|
|
213
|
+
resolved[k] = val;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
if (!entry._static && !entry._dynamic) {
|
|
219
|
+
for (const [k, v] of Object.entries(entry)) {
|
|
220
|
+
if (k.startsWith("--")) continue;
|
|
221
|
+
const val = resolveCssValue(k, v, rootVars, localVars);
|
|
222
|
+
if (val !== undefined && val !== null) {
|
|
223
|
+
resolved[k] = val;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
123
229
|
// ============================================================================
|
|
124
230
|
// Main Native Rust Stylesheet Transform
|
|
125
231
|
// ============================================================================
|
|
@@ -129,6 +235,7 @@ function transformStyles(stylesheet, classNames) {
|
|
|
129
235
|
stylesheet = stylesheet.default;
|
|
130
236
|
}
|
|
131
237
|
|
|
238
|
+
const rootVars = stylesheet[":root"] || {};
|
|
132
239
|
const { width, height } = getDimensions();
|
|
133
240
|
const colorScheme = getColorScheme();
|
|
134
241
|
|
|
@@ -145,18 +252,54 @@ function transformStyles(stylesheet, classNames) {
|
|
|
145
252
|
const classes = classNames.trim().split(/\s+/);
|
|
146
253
|
const resolved = {};
|
|
147
254
|
|
|
148
|
-
|
|
255
|
+
const os = Platform?.OS || "ios";
|
|
256
|
+
|
|
257
|
+
for (let cls of classes) {
|
|
149
258
|
if (!cls) continue;
|
|
259
|
+
|
|
260
|
+
// Platform variants: ios:, android:, web:
|
|
261
|
+
if (cls.startsWith("ios:")) {
|
|
262
|
+
if (os !== "ios") continue;
|
|
263
|
+
cls = cls.slice(4);
|
|
264
|
+
} else if (cls.startsWith("android:")) {
|
|
265
|
+
if (os !== "android") continue;
|
|
266
|
+
cls = cls.slice(8);
|
|
267
|
+
} else if (cls.startsWith("web:")) {
|
|
268
|
+
if (os !== "web") continue;
|
|
269
|
+
cls = cls.slice(4);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// Media query variants: sm:, md:, lg:, xl:, 2xl:
|
|
273
|
+
if (cls.startsWith("sm:")) {
|
|
274
|
+
if (width < 640) continue;
|
|
275
|
+
cls = cls.slice(3);
|
|
276
|
+
} else if (cls.startsWith("md:")) {
|
|
277
|
+
if (width < 768) continue;
|
|
278
|
+
cls = cls.slice(3);
|
|
279
|
+
} else if (cls.startsWith("lg:")) {
|
|
280
|
+
if (width < 1024) continue;
|
|
281
|
+
cls = cls.slice(3);
|
|
282
|
+
} else if (cls.startsWith("xl:")) {
|
|
283
|
+
if (width < 1280) continue;
|
|
284
|
+
cls = cls.slice(3);
|
|
285
|
+
} else if (cls.startsWith("2xl:")) {
|
|
286
|
+
if (width < 1536) continue;
|
|
287
|
+
cls = cls.slice(4);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// Dark / Light variants
|
|
291
|
+
if (cls.startsWith("dark:")) {
|
|
292
|
+
if (colorScheme !== "dark") continue;
|
|
293
|
+
cls = cls.slice(5);
|
|
294
|
+
} else if (cls.startsWith("light:")) {
|
|
295
|
+
if (colorScheme !== "light") continue;
|
|
296
|
+
cls = cls.slice(6);
|
|
297
|
+
}
|
|
298
|
+
|
|
150
299
|
const entry = stylesheet[cls];
|
|
151
300
|
if (!entry) continue;
|
|
152
301
|
|
|
153
|
-
|
|
154
|
-
Object.assign(resolved, entry._static);
|
|
155
|
-
} else if (entry._dynamic) {
|
|
156
|
-
Object.assign(resolved, entry._dynamic);
|
|
157
|
-
} else if (typeof entry === "object") {
|
|
158
|
-
Object.assign(resolved, entry);
|
|
159
|
-
}
|
|
302
|
+
applyResolvedEntry(resolved, entry, rootVars);
|
|
160
303
|
}
|
|
161
304
|
|
|
162
305
|
const result = Object.keys(resolved).length > 0 ? resolved : undefined;
|
|
@@ -170,10 +313,13 @@ function transformStyles(stylesheet, classNames) {
|
|
|
170
313
|
function getInheritStyle(declarations) {
|
|
171
314
|
if (!declarations) return undefined;
|
|
172
315
|
|
|
316
|
+
const flat = Array.isArray(declarations) ? getFlattenStyle(declarations) : declarations;
|
|
317
|
+
if (!flat || typeof flat !== "object") return undefined;
|
|
318
|
+
|
|
173
319
|
const inheritDeclarations = {};
|
|
174
320
|
for (const key of INHERIT_PROPERTIES) {
|
|
175
|
-
if (
|
|
176
|
-
inheritDeclarations[key] =
|
|
321
|
+
if (flat[key] !== undefined) {
|
|
322
|
+
inheritDeclarations[key] = flat[key];
|
|
177
323
|
}
|
|
178
324
|
}
|
|
179
325
|
|
|
@@ -221,13 +367,21 @@ function mergeStyles(inheritStyle, staticStyles, inlineStyle) {
|
|
|
221
367
|
const result = {};
|
|
222
368
|
if (inherited) Object.assign(result, inherited);
|
|
223
369
|
if (staticStyles) {
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
370
|
+
const flatStatic = Array.isArray(staticStyles) ? getFlattenStyle(staticStyles) : staticStyles;
|
|
371
|
+
if (flatStatic && typeof flatStatic === "object") {
|
|
372
|
+
for (const key in flatStatic) {
|
|
373
|
+
if (!key.startsWith("--")) {
|
|
374
|
+
result[key] = flatStatic[key];
|
|
375
|
+
}
|
|
227
376
|
}
|
|
228
377
|
}
|
|
229
378
|
}
|
|
230
|
-
if (inlineStyle)
|
|
379
|
+
if (inlineStyle) {
|
|
380
|
+
const flatInline = Array.isArray(inlineStyle) ? getFlattenStyle(inlineStyle) : inlineStyle;
|
|
381
|
+
if (flatInline && typeof flatInline === "object") {
|
|
382
|
+
Object.assign(result, flatInline);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
231
385
|
|
|
232
386
|
return Object.keys(result).length > 0 ? result : undefined;
|
|
233
387
|
}
|
package/src/transformer.js
CHANGED
|
@@ -1,14 +1,46 @@
|
|
|
1
1
|
import fs from "fs";
|
|
2
2
|
import path from "path";
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
|
|
4
|
+
let native = null;
|
|
5
|
+
try {
|
|
6
|
+
native = require("./native");
|
|
7
|
+
} catch {
|
|
8
|
+
try {
|
|
9
|
+
native = require("../crates/transformer");
|
|
10
|
+
} catch {}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
let cachedStylesheet = null;
|
|
14
|
+
|
|
15
|
+
function getCachedStylesheetJson(projectRoot) {
|
|
16
|
+
if (cachedStylesheet) return cachedStylesheet;
|
|
17
|
+
try {
|
|
18
|
+
const root = projectRoot || process.cwd();
|
|
19
|
+
const candidates = [
|
|
20
|
+
path.resolve(root, "index.css.json"),
|
|
21
|
+
path.resolve(root, "src/assets/styles/index.css.json"),
|
|
22
|
+
path.join(__dirname, "exported-stylesheet.json"),
|
|
23
|
+
path.resolve(__dirname, "../src/exported-stylesheet.json"),
|
|
24
|
+
];
|
|
25
|
+
for (const p of candidates) {
|
|
26
|
+
if (fs.existsSync(p)) {
|
|
27
|
+
cachedStylesheet = fs.readFileSync(p, "utf-8");
|
|
28
|
+
return cachedStylesheet;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
} catch {}
|
|
32
|
+
return "{}";
|
|
33
|
+
}
|
|
5
34
|
|
|
6
35
|
export function getStylesheet(css, filename) {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
36
|
+
if (!native || !native.compileCss) {
|
|
37
|
+
throw new Error(
|
|
38
|
+
"[@colorye/react-native-css] Native Rust transformer binding is not loaded. Cannot compile CSS.",
|
|
39
|
+
);
|
|
40
|
+
}
|
|
10
41
|
|
|
11
|
-
const jsonContent =
|
|
42
|
+
const jsonContent = native.compileCss(css);
|
|
43
|
+
cachedStylesheet = jsonContent;
|
|
12
44
|
writeStylesheetJSON(jsonContent, filename);
|
|
13
45
|
|
|
14
46
|
return jsonContent;
|
|
@@ -58,9 +90,7 @@ export function transform({ src, filename, options }) {
|
|
|
58
90
|
const resolved = require.resolve("metro-react-native-babel-transformer", resolveOptions);
|
|
59
91
|
return eval("require")(resolved);
|
|
60
92
|
} catch {
|
|
61
|
-
|
|
62
|
-
"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.",
|
|
63
|
-
);
|
|
93
|
+
return null;
|
|
64
94
|
}
|
|
65
95
|
}
|
|
66
96
|
}
|
|
@@ -71,13 +101,43 @@ export function transform({ src, filename, options }) {
|
|
|
71
101
|
|
|
72
102
|
if (filename.endsWith(".css")) {
|
|
73
103
|
const jsonContent = getStylesheet(src, filename);
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
104
|
+
const cssCode = `const sheet = ${jsonContent};\nmodule.exports = sheet;\nmodule.exports.default = sheet;\nmodule.exports.__esModule = true;`;
|
|
105
|
+
if (resolveTransformer && resolveTransformer.transform) {
|
|
106
|
+
return resolveTransformer.transform({
|
|
107
|
+
src: cssCode,
|
|
108
|
+
filename,
|
|
109
|
+
options,
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
return { code: cssCode, map: null };
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Fast native Rust SWC transformer for JSX/TSX
|
|
116
|
+
if (
|
|
117
|
+
native &&
|
|
118
|
+
native.transformJsx &&
|
|
119
|
+
(filename.endsWith(".tsx") || filename.endsWith(".jsx")) &&
|
|
120
|
+
!filename.includes("node_modules")
|
|
121
|
+
) {
|
|
122
|
+
try {
|
|
123
|
+
const stylesheetJson = options?.stylesheetJson || getCachedStylesheetJson(projectRoot);
|
|
124
|
+
const res = native.transformJsx(src, {
|
|
125
|
+
filename,
|
|
126
|
+
stylesheetJson,
|
|
127
|
+
sourceMaps: true,
|
|
128
|
+
});
|
|
129
|
+
if (res && res.code) {
|
|
130
|
+
src = res.code;
|
|
131
|
+
}
|
|
132
|
+
} catch {
|
|
133
|
+
// Graceful fallback to Babel if native transform hits unexpected syntax
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (resolveTransformer && resolveTransformer.transform) {
|
|
138
|
+
return resolveTransformer.transform({ src, filename, options });
|
|
79
139
|
}
|
|
80
|
-
return
|
|
140
|
+
return { code: src, map: null };
|
|
81
141
|
}
|
|
82
142
|
|
|
83
143
|
export default {
|