@mgcrea/react-native-tailwind 0.4.0 → 0.5.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.
- package/README.md +527 -136
- package/dist/babel/index.cjs +767 -274
- package/dist/babel/index.d.ts +2 -1
- package/dist/babel/index.ts +319 -16
- package/dist/components/Pressable.d.ts +32 -0
- package/dist/components/Pressable.js +1 -0
- package/dist/components/TextInput.d.ts +56 -0
- package/dist/components/TextInput.js +1 -0
- package/dist/index.d.ts +9 -2
- package/dist/index.js +1 -1
- package/dist/parser/aspectRatio.d.ts +16 -0
- package/dist/parser/aspectRatio.js +1 -0
- package/dist/parser/aspectRatio.test.d.ts +1 -0
- package/dist/parser/aspectRatio.test.js +1 -0
- package/dist/parser/borders.js +1 -1
- package/dist/parser/borders.test.d.ts +1 -0
- package/dist/parser/borders.test.js +1 -0
- package/dist/parser/colors.d.ts +1 -0
- package/dist/parser/colors.js +1 -1
- package/dist/parser/colors.test.d.ts +1 -0
- package/dist/parser/colors.test.js +1 -0
- package/dist/parser/index.d.ts +4 -0
- package/dist/parser/index.js +1 -1
- package/dist/parser/layout.d.ts +2 -0
- package/dist/parser/layout.js +1 -1
- package/dist/parser/layout.test.d.ts +1 -0
- package/dist/parser/layout.test.js +1 -0
- package/dist/parser/modifiers.d.ts +47 -0
- package/dist/parser/modifiers.js +1 -0
- package/dist/parser/modifiers.test.d.ts +1 -0
- package/dist/parser/modifiers.test.js +1 -0
- package/dist/parser/shadows.d.ts +22 -0
- package/dist/parser/shadows.js +1 -0
- package/dist/parser/shadows.test.d.ts +1 -0
- package/dist/parser/shadows.test.js +1 -0
- package/dist/parser/sizing.test.d.ts +1 -0
- package/dist/parser/sizing.test.js +1 -0
- package/dist/parser/spacing.d.ts +1 -1
- package/dist/parser/spacing.js +1 -1
- package/dist/parser/spacing.test.d.ts +1 -0
- package/dist/parser/spacing.test.js +1 -0
- package/dist/parser/typography.d.ts +2 -1
- package/dist/parser/typography.js +1 -1
- package/dist/parser/typography.test.d.ts +1 -0
- package/dist/parser/typography.test.js +1 -0
- package/dist/types.d.ts +4 -3
- package/package.json +7 -6
- package/src/babel/index.ts +319 -16
- package/src/components/Pressable.tsx +46 -0
- package/src/components/TextInput.tsx +90 -0
- package/src/index.ts +20 -2
- package/src/parser/aspectRatio.test.ts +191 -0
- package/src/parser/aspectRatio.ts +73 -0
- package/src/parser/borders.test.ts +329 -0
- package/src/parser/borders.ts +187 -108
- package/src/parser/colors.test.ts +335 -0
- package/src/parser/colors.ts +117 -6
- package/src/parser/index.ts +13 -2
- package/src/parser/layout.test.ts +459 -0
- package/src/parser/layout.ts +128 -0
- package/src/parser/modifiers.test.ts +375 -0
- package/src/parser/modifiers.ts +104 -0
- package/src/parser/shadows.test.ts +192 -0
- package/src/parser/shadows.ts +84 -0
- package/src/parser/sizing.test.ts +256 -0
- package/src/parser/spacing.test.ts +226 -0
- package/src/parser/spacing.ts +93 -138
- package/src/parser/typography.test.ts +221 -0
- package/src/parser/typography.ts +143 -112
- package/src/types.ts +1 -3
- package/dist/react-native.d.js +0 -1
package/dist/babel/index.cjs
CHANGED
|
@@ -34,6 +34,49 @@ __export(index_exports, {
|
|
|
34
34
|
});
|
|
35
35
|
module.exports = __toCommonJS(index_exports);
|
|
36
36
|
|
|
37
|
+
// src/parser/aspectRatio.ts
|
|
38
|
+
var ASPECT_RATIO_PRESETS = {
|
|
39
|
+
"aspect-auto": void 0,
|
|
40
|
+
// Remove aspect ratio
|
|
41
|
+
"aspect-square": 1,
|
|
42
|
+
// 1:1
|
|
43
|
+
"aspect-video": 16 / 9
|
|
44
|
+
// 16:9
|
|
45
|
+
};
|
|
46
|
+
function parseArbitraryAspectRatio(value) {
|
|
47
|
+
const match = value.match(/^\[(\d+)\/(\d+)\]$/);
|
|
48
|
+
if (match) {
|
|
49
|
+
const numerator = Number.parseInt(match[1], 10);
|
|
50
|
+
const denominator = Number.parseInt(match[2], 10);
|
|
51
|
+
if (denominator === 0) {
|
|
52
|
+
if (process.env.NODE_ENV !== "production") {
|
|
53
|
+
console.warn(`[react-native-tailwind] Invalid aspect ratio: ${value}. Denominator cannot be zero.`);
|
|
54
|
+
}
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
return numerator / denominator;
|
|
58
|
+
}
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
function parseAspectRatio(cls) {
|
|
62
|
+
if (!cls.startsWith("aspect-")) {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
if (cls in ASPECT_RATIO_PRESETS) {
|
|
66
|
+
const aspectRatio2 = ASPECT_RATIO_PRESETS[cls];
|
|
67
|
+
if (aspectRatio2 === void 0) {
|
|
68
|
+
return {};
|
|
69
|
+
}
|
|
70
|
+
return { aspectRatio: aspectRatio2 };
|
|
71
|
+
}
|
|
72
|
+
const arbitraryValue = cls.substring(7);
|
|
73
|
+
const aspectRatio = parseArbitraryAspectRatio(arbitraryValue);
|
|
74
|
+
if (aspectRatio !== null) {
|
|
75
|
+
return { aspectRatio };
|
|
76
|
+
}
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
|
|
37
80
|
// src/parser/borders.ts
|
|
38
81
|
var BORDER_WIDTH_SCALE = {
|
|
39
82
|
"": 1,
|
|
@@ -53,7 +96,58 @@ var BORDER_RADIUS_SCALE = {
|
|
|
53
96
|
"3xl": 24,
|
|
54
97
|
full: 9999
|
|
55
98
|
};
|
|
99
|
+
var BORDER_WIDTH_PROP_MAP = {
|
|
100
|
+
t: "borderTopWidth",
|
|
101
|
+
r: "borderRightWidth",
|
|
102
|
+
b: "borderBottomWidth",
|
|
103
|
+
l: "borderLeftWidth"
|
|
104
|
+
};
|
|
105
|
+
var BORDER_RADIUS_CORNER_MAP = {
|
|
106
|
+
tl: "borderTopLeftRadius",
|
|
107
|
+
tr: "borderTopRightRadius",
|
|
108
|
+
bl: "borderBottomLeftRadius",
|
|
109
|
+
br: "borderBottomRightRadius"
|
|
110
|
+
};
|
|
111
|
+
var BORDER_RADIUS_SIDE_MAP = {
|
|
112
|
+
t: ["borderTopLeftRadius", "borderTopRightRadius"],
|
|
113
|
+
r: ["borderTopRightRadius", "borderBottomRightRadius"],
|
|
114
|
+
b: ["borderBottomLeftRadius", "borderBottomRightRadius"],
|
|
115
|
+
l: ["borderTopLeftRadius", "borderBottomLeftRadius"]
|
|
116
|
+
};
|
|
117
|
+
function parseArbitraryBorderWidth(value) {
|
|
118
|
+
const pxMatch = value.match(/^\[(\d+)(?:px)?\]$/);
|
|
119
|
+
if (pxMatch) {
|
|
120
|
+
return parseInt(pxMatch[1], 10);
|
|
121
|
+
}
|
|
122
|
+
if (value.startsWith("[") && value.endsWith("]")) {
|
|
123
|
+
if (process.env.NODE_ENV !== "production") {
|
|
124
|
+
console.warn(
|
|
125
|
+
`[react-native-tailwind] Unsupported arbitrary border width value: ${value}. Only px values are supported (e.g., [8px] or [8]).`
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
function parseArbitraryBorderRadius(value) {
|
|
133
|
+
const pxMatch = value.match(/^\[(\d+)(?:px)?\]$/);
|
|
134
|
+
if (pxMatch) {
|
|
135
|
+
return parseInt(pxMatch[1], 10);
|
|
136
|
+
}
|
|
137
|
+
if (value.startsWith("[") && value.endsWith("]")) {
|
|
138
|
+
if (process.env.NODE_ENV !== "production") {
|
|
139
|
+
console.warn(
|
|
140
|
+
`[react-native-tailwind] Unsupported arbitrary border radius value: ${value}. Only px values are supported (e.g., [12px] or [12]).`
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
56
147
|
function parseBorder(cls) {
|
|
148
|
+
if (cls === "border-solid") return { borderStyle: "solid" };
|
|
149
|
+
if (cls === "border-dotted") return { borderStyle: "dotted" };
|
|
150
|
+
if (cls === "border-dashed") return { borderStyle: "dashed" };
|
|
57
151
|
if (cls.startsWith("border-")) {
|
|
58
152
|
return parseBorderWidth(cls);
|
|
59
153
|
}
|
|
@@ -63,42 +157,25 @@ function parseBorder(cls) {
|
|
|
63
157
|
if (cls.startsWith("rounded")) {
|
|
64
158
|
return parseBorderRadius(cls);
|
|
65
159
|
}
|
|
66
|
-
if (cls === "border-solid") return { borderStyle: "solid" };
|
|
67
|
-
if (cls === "border-dotted") return { borderStyle: "dotted" };
|
|
68
|
-
if (cls === "border-dashed") return { borderStyle: "dashed" };
|
|
69
160
|
return null;
|
|
70
161
|
}
|
|
71
162
|
function parseBorderWidth(cls) {
|
|
72
|
-
const
|
|
73
|
-
if (allArbMatch) {
|
|
74
|
-
return { borderWidth: parseInt(allArbMatch[1], 10) };
|
|
75
|
-
}
|
|
76
|
-
const dirArbMatch = cls.match(/^border-([trbl])-\[(\d+)(?:px)?\]$/);
|
|
77
|
-
if (dirArbMatch) {
|
|
78
|
-
const dir = dirArbMatch[1];
|
|
79
|
-
const value = parseInt(dirArbMatch[2], 10);
|
|
80
|
-
const propMap = {
|
|
81
|
-
t: "borderTopWidth",
|
|
82
|
-
r: "borderRightWidth",
|
|
83
|
-
b: "borderBottomWidth",
|
|
84
|
-
l: "borderLeftWidth"
|
|
85
|
-
};
|
|
86
|
-
return { [propMap[dir]]: value };
|
|
87
|
-
}
|
|
88
|
-
const dirMatch = cls.match(/^border-([trbl])-?(\d*)$/);
|
|
163
|
+
const dirMatch = cls.match(/^border-([trbl])(?:-(.+))?$/);
|
|
89
164
|
if (dirMatch) {
|
|
90
165
|
const dir = dirMatch[1];
|
|
91
|
-
const
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
166
|
+
const valueStr = dirMatch[2] || "";
|
|
167
|
+
if (valueStr.startsWith("[")) {
|
|
168
|
+
const arbitraryValue = parseArbitraryBorderWidth(valueStr);
|
|
169
|
+
if (arbitraryValue !== null) {
|
|
170
|
+
return { [BORDER_WIDTH_PROP_MAP[dir]]: arbitraryValue };
|
|
171
|
+
}
|
|
172
|
+
return null;
|
|
173
|
+
}
|
|
174
|
+
const scaleValue = BORDER_WIDTH_SCALE[valueStr];
|
|
175
|
+
if (scaleValue !== void 0) {
|
|
176
|
+
return { [BORDER_WIDTH_PROP_MAP[dir]]: scaleValue };
|
|
101
177
|
}
|
|
178
|
+
return null;
|
|
102
179
|
}
|
|
103
180
|
const allMatch = cls.match(/^border-(\d+)$/);
|
|
104
181
|
if (allMatch) {
|
|
@@ -107,78 +184,76 @@ function parseBorderWidth(cls) {
|
|
|
107
184
|
return { borderWidth: value };
|
|
108
185
|
}
|
|
109
186
|
}
|
|
187
|
+
const allArbMatch = cls.match(/^border-(\[.+\])$/);
|
|
188
|
+
if (allArbMatch) {
|
|
189
|
+
const arbitraryValue = parseArbitraryBorderWidth(allArbMatch[1]);
|
|
190
|
+
if (arbitraryValue !== null) {
|
|
191
|
+
return { borderWidth: arbitraryValue };
|
|
192
|
+
}
|
|
193
|
+
}
|
|
110
194
|
return null;
|
|
111
195
|
}
|
|
112
196
|
function parseBorderRadius(cls) {
|
|
113
|
-
const
|
|
114
|
-
if (
|
|
115
|
-
return { borderRadius:
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
};
|
|
139
|
-
const result = {};
|
|
140
|
-
propMap[side].forEach((prop) => result[prop] = value);
|
|
141
|
-
return result;
|
|
142
|
-
}
|
|
143
|
-
const allMatch = cls.match(/^rounded(-\w+)?$/);
|
|
144
|
-
if (allMatch) {
|
|
145
|
-
const scaleKey = allMatch[1] ? allMatch[1].substring(1) : "";
|
|
146
|
-
const value = BORDER_RADIUS_SCALE[scaleKey];
|
|
147
|
-
if (value !== void 0) {
|
|
148
|
-
return { borderRadius: value };
|
|
197
|
+
const withoutPrefix = cls.substring(7);
|
|
198
|
+
if (withoutPrefix === "") {
|
|
199
|
+
return { borderRadius: BORDER_RADIUS_SCALE[""] };
|
|
200
|
+
}
|
|
201
|
+
if (!withoutPrefix.startsWith("-")) {
|
|
202
|
+
return null;
|
|
203
|
+
}
|
|
204
|
+
const rest = withoutPrefix.substring(1);
|
|
205
|
+
if (rest === "") {
|
|
206
|
+
return null;
|
|
207
|
+
}
|
|
208
|
+
const cornerMatch = rest.match(/^(tl|tr|bl|br)(?:-(.+))?$/);
|
|
209
|
+
if (cornerMatch) {
|
|
210
|
+
const corner = cornerMatch[1];
|
|
211
|
+
const valueStr = cornerMatch[2] || "";
|
|
212
|
+
if (valueStr.startsWith("[")) {
|
|
213
|
+
const arbitraryValue = parseArbitraryBorderRadius(valueStr);
|
|
214
|
+
if (arbitraryValue !== null) {
|
|
215
|
+
return { [BORDER_RADIUS_CORNER_MAP[corner]]: arbitraryValue };
|
|
216
|
+
}
|
|
217
|
+
return null;
|
|
218
|
+
}
|
|
219
|
+
const scaleValue2 = BORDER_RADIUS_SCALE[valueStr];
|
|
220
|
+
if (scaleValue2 !== void 0) {
|
|
221
|
+
return { [BORDER_RADIUS_CORNER_MAP[corner]]: scaleValue2 };
|
|
149
222
|
}
|
|
223
|
+
return null;
|
|
150
224
|
}
|
|
151
|
-
const sideMatch =
|
|
225
|
+
const sideMatch = rest.match(/^([trbl])(?:-(.+))?$/);
|
|
152
226
|
if (sideMatch) {
|
|
153
227
|
const side = sideMatch[1];
|
|
154
|
-
const
|
|
155
|
-
|
|
228
|
+
const valueStr = sideMatch[2] || "";
|
|
229
|
+
let value;
|
|
230
|
+
if (valueStr.startsWith("[")) {
|
|
231
|
+
const arbitraryValue = parseArbitraryBorderRadius(valueStr);
|
|
232
|
+
if (arbitraryValue !== null) {
|
|
233
|
+
value = arbitraryValue;
|
|
234
|
+
} else {
|
|
235
|
+
return null;
|
|
236
|
+
}
|
|
237
|
+
} else {
|
|
238
|
+
value = BORDER_RADIUS_SCALE[valueStr];
|
|
239
|
+
}
|
|
156
240
|
if (value !== void 0) {
|
|
157
|
-
const propMap = {
|
|
158
|
-
t: ["borderTopLeftRadius", "borderTopRightRadius"],
|
|
159
|
-
r: ["borderTopRightRadius", "borderBottomRightRadius"],
|
|
160
|
-
b: ["borderBottomLeftRadius", "borderBottomRightRadius"],
|
|
161
|
-
l: ["borderTopLeftRadius", "borderBottomLeftRadius"]
|
|
162
|
-
};
|
|
163
241
|
const result = {};
|
|
164
|
-
|
|
242
|
+
BORDER_RADIUS_SIDE_MAP[side].forEach((prop) => result[prop] = value);
|
|
165
243
|
return result;
|
|
166
244
|
}
|
|
245
|
+
return null;
|
|
167
246
|
}
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
const value = BORDER_RADIUS_SCALE[scaleKey];
|
|
173
|
-
if (value !== void 0) {
|
|
174
|
-
const propMap = {
|
|
175
|
-
tl: "borderTopLeftRadius",
|
|
176
|
-
tr: "borderTopRightRadius",
|
|
177
|
-
bl: "borderBottomLeftRadius",
|
|
178
|
-
br: "borderBottomRightRadius"
|
|
179
|
-
};
|
|
180
|
-
return { [propMap[corner]]: value };
|
|
247
|
+
if (rest.startsWith("[")) {
|
|
248
|
+
const arbitraryValue = parseArbitraryBorderRadius(rest);
|
|
249
|
+
if (arbitraryValue !== null) {
|
|
250
|
+
return { borderRadius: arbitraryValue };
|
|
181
251
|
}
|
|
252
|
+
return null;
|
|
253
|
+
}
|
|
254
|
+
const scaleValue = BORDER_RADIUS_SCALE[rest];
|
|
255
|
+
if (scaleValue !== void 0) {
|
|
256
|
+
return { borderRadius: scaleValue };
|
|
182
257
|
}
|
|
183
258
|
return null;
|
|
184
259
|
}
|
|
@@ -289,27 +364,86 @@ var COLORS = {
|
|
|
289
364
|
black: "#000000",
|
|
290
365
|
transparent: "transparent"
|
|
291
366
|
};
|
|
367
|
+
function applyOpacity(hex, opacity) {
|
|
368
|
+
if (hex === "transparent") {
|
|
369
|
+
return "transparent";
|
|
370
|
+
}
|
|
371
|
+
const cleanHex = hex.replace(/^#/, "");
|
|
372
|
+
const fullHex = cleanHex.length === 3 ? cleanHex.split("").map((char) => char + char).join("") : cleanHex;
|
|
373
|
+
const alpha = Math.round(opacity / 100 * 255);
|
|
374
|
+
const alphaHex = alpha.toString(16).padStart(2, "0").toUpperCase();
|
|
375
|
+
return `#${fullHex.toUpperCase()}${alphaHex}`;
|
|
376
|
+
}
|
|
377
|
+
function parseArbitraryColor(value) {
|
|
378
|
+
const hexMatch = value.match(/^\[#([0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})\]$/);
|
|
379
|
+
if (hexMatch) {
|
|
380
|
+
const hex = hexMatch[1];
|
|
381
|
+
if (hex.length === 3) {
|
|
382
|
+
const expanded = hex.split("").map((char) => char + char).join("");
|
|
383
|
+
return `#${expanded}`;
|
|
384
|
+
}
|
|
385
|
+
return `#${hex}`;
|
|
386
|
+
}
|
|
387
|
+
if (value.startsWith("[") && value.endsWith("]")) {
|
|
388
|
+
if (process.env.NODE_ENV !== "production") {
|
|
389
|
+
console.warn(
|
|
390
|
+
`[react-native-tailwind] Unsupported arbitrary color value: ${value}. Only hex colors are supported (e.g., [#ff0000], [#f00], or [#ff0000aa]).`
|
|
391
|
+
);
|
|
392
|
+
}
|
|
393
|
+
return null;
|
|
394
|
+
}
|
|
395
|
+
return null;
|
|
396
|
+
}
|
|
292
397
|
function parseColor(cls, customColors) {
|
|
293
398
|
const getColor = (key) => {
|
|
294
399
|
return customColors?.[key] ?? COLORS[key];
|
|
295
400
|
};
|
|
401
|
+
const parseColorWithOpacity = (colorKey) => {
|
|
402
|
+
const opacityMatch = colorKey.match(/^(.+)\/(\d+)$/);
|
|
403
|
+
if (opacityMatch) {
|
|
404
|
+
const baseColorKey = opacityMatch[1];
|
|
405
|
+
const opacity = Number.parseInt(opacityMatch[2], 10);
|
|
406
|
+
if (opacity < 0 || opacity > 100) {
|
|
407
|
+
if (process.env.NODE_ENV !== "production") {
|
|
408
|
+
console.warn(
|
|
409
|
+
`[react-native-tailwind] Invalid opacity value: ${opacity}. Opacity must be between 0 and 100.`
|
|
410
|
+
);
|
|
411
|
+
}
|
|
412
|
+
return null;
|
|
413
|
+
}
|
|
414
|
+
const arbitraryColor2 = parseArbitraryColor(baseColorKey);
|
|
415
|
+
if (arbitraryColor2 !== null) {
|
|
416
|
+
return applyOpacity(arbitraryColor2, opacity);
|
|
417
|
+
}
|
|
418
|
+
const color = getColor(baseColorKey);
|
|
419
|
+
if (color) {
|
|
420
|
+
return applyOpacity(color, opacity);
|
|
421
|
+
}
|
|
422
|
+
return null;
|
|
423
|
+
}
|
|
424
|
+
const arbitraryColor = parseArbitraryColor(colorKey);
|
|
425
|
+
if (arbitraryColor !== null) {
|
|
426
|
+
return arbitraryColor;
|
|
427
|
+
}
|
|
428
|
+
return getColor(colorKey) ?? null;
|
|
429
|
+
};
|
|
296
430
|
if (cls.startsWith("bg-")) {
|
|
297
431
|
const colorKey = cls.substring(3);
|
|
298
|
-
const color =
|
|
432
|
+
const color = parseColorWithOpacity(colorKey);
|
|
299
433
|
if (color) {
|
|
300
434
|
return { backgroundColor: color };
|
|
301
435
|
}
|
|
302
436
|
}
|
|
303
437
|
if (cls.startsWith("text-")) {
|
|
304
438
|
const colorKey = cls.substring(5);
|
|
305
|
-
const color =
|
|
439
|
+
const color = parseColorWithOpacity(colorKey);
|
|
306
440
|
if (color) {
|
|
307
441
|
return { color };
|
|
308
442
|
}
|
|
309
443
|
}
|
|
310
444
|
if (cls.startsWith("border-") && !cls.match(/^border-[0-9]/)) {
|
|
311
445
|
const colorKey = cls.substring(7);
|
|
312
|
-
const color =
|
|
446
|
+
const color = parseColorWithOpacity(colorKey);
|
|
313
447
|
if (color) {
|
|
314
448
|
return { borderColor: color };
|
|
315
449
|
}
|
|
@@ -384,10 +518,166 @@ var OVERFLOW_MAP = {
|
|
|
384
518
|
"overflow-visible": { overflow: "visible" },
|
|
385
519
|
"overflow-scroll": { overflow: "scroll" }
|
|
386
520
|
};
|
|
521
|
+
var Z_INDEX_SCALE = {
|
|
522
|
+
0: 0,
|
|
523
|
+
10: 10,
|
|
524
|
+
20: 20,
|
|
525
|
+
30: 30,
|
|
526
|
+
40: 40,
|
|
527
|
+
50: 50,
|
|
528
|
+
auto: 0
|
|
529
|
+
// React Native doesn't have 'auto', default to 0
|
|
530
|
+
};
|
|
531
|
+
var INSET_SCALE = {
|
|
532
|
+
0: 0,
|
|
533
|
+
0.5: 2,
|
|
534
|
+
1: 4,
|
|
535
|
+
1.5: 6,
|
|
536
|
+
2: 8,
|
|
537
|
+
2.5: 10,
|
|
538
|
+
3: 12,
|
|
539
|
+
3.5: 14,
|
|
540
|
+
4: 16,
|
|
541
|
+
5: 20,
|
|
542
|
+
6: 24,
|
|
543
|
+
8: 32,
|
|
544
|
+
10: 40,
|
|
545
|
+
12: 48,
|
|
546
|
+
16: 64,
|
|
547
|
+
20: 80,
|
|
548
|
+
24: 96
|
|
549
|
+
};
|
|
387
550
|
function parseLayout(cls) {
|
|
551
|
+
if (cls.startsWith("z-")) {
|
|
552
|
+
const zKey = cls.substring(2);
|
|
553
|
+
const zValue = Z_INDEX_SCALE[zKey];
|
|
554
|
+
if (zValue !== void 0) {
|
|
555
|
+
return { zIndex: zValue };
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
if (cls.startsWith("top-")) {
|
|
559
|
+
const topKey = cls.substring(4);
|
|
560
|
+
if (topKey === "auto") {
|
|
561
|
+
return {};
|
|
562
|
+
}
|
|
563
|
+
const topValue = INSET_SCALE[topKey];
|
|
564
|
+
if (topValue !== void 0) {
|
|
565
|
+
return { top: topValue };
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
if (cls.startsWith("right-")) {
|
|
569
|
+
const rightKey = cls.substring(6);
|
|
570
|
+
if (rightKey === "auto") {
|
|
571
|
+
return {};
|
|
572
|
+
}
|
|
573
|
+
const rightValue = INSET_SCALE[rightKey];
|
|
574
|
+
if (rightValue !== void 0) {
|
|
575
|
+
return { right: rightValue };
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
if (cls.startsWith("bottom-")) {
|
|
579
|
+
const bottomKey = cls.substring(7);
|
|
580
|
+
if (bottomKey === "auto") {
|
|
581
|
+
return {};
|
|
582
|
+
}
|
|
583
|
+
const bottomValue = INSET_SCALE[bottomKey];
|
|
584
|
+
if (bottomValue !== void 0) {
|
|
585
|
+
return { bottom: bottomValue };
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
if (cls.startsWith("left-")) {
|
|
589
|
+
const leftKey = cls.substring(5);
|
|
590
|
+
if (leftKey === "auto") {
|
|
591
|
+
return {};
|
|
592
|
+
}
|
|
593
|
+
const leftValue = INSET_SCALE[leftKey];
|
|
594
|
+
if (leftValue !== void 0) {
|
|
595
|
+
return { left: leftValue };
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
if (cls.startsWith("inset-")) {
|
|
599
|
+
const insetKey = cls.substring(6);
|
|
600
|
+
const insetValue = INSET_SCALE[insetKey];
|
|
601
|
+
if (insetValue !== void 0) {
|
|
602
|
+
return { top: insetValue, right: insetValue, bottom: insetValue, left: insetValue };
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
if (cls.startsWith("inset-x-")) {
|
|
606
|
+
const insetKey = cls.substring(8);
|
|
607
|
+
const insetValue = INSET_SCALE[insetKey];
|
|
608
|
+
if (insetValue !== void 0) {
|
|
609
|
+
return { left: insetValue, right: insetValue };
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
if (cls.startsWith("inset-y-")) {
|
|
613
|
+
const insetKey = cls.substring(8);
|
|
614
|
+
const insetValue = INSET_SCALE[insetKey];
|
|
615
|
+
if (insetValue !== void 0) {
|
|
616
|
+
return { top: insetValue, bottom: insetValue };
|
|
617
|
+
}
|
|
618
|
+
}
|
|
388
619
|
return DISPLAY_MAP[cls] ?? FLEX_DIRECTION_MAP[cls] ?? FLEX_WRAP_MAP[cls] ?? FLEX_MAP[cls] ?? GROW_SHRINK_MAP[cls] ?? JUSTIFY_CONTENT_MAP[cls] ?? ALIGN_ITEMS_MAP[cls] ?? ALIGN_SELF_MAP[cls] ?? ALIGN_CONTENT_MAP[cls] ?? POSITION_MAP[cls] ?? OVERFLOW_MAP[cls] ?? null;
|
|
389
620
|
}
|
|
390
621
|
|
|
622
|
+
// src/parser/shadows.ts
|
|
623
|
+
var SHADOW_SCALE = {
|
|
624
|
+
"shadow-sm": {
|
|
625
|
+
shadowColor: "#000000",
|
|
626
|
+
shadowOffset: { width: 0, height: 1 },
|
|
627
|
+
shadowOpacity: 0.05,
|
|
628
|
+
shadowRadius: 1,
|
|
629
|
+
elevation: 1
|
|
630
|
+
},
|
|
631
|
+
shadow: {
|
|
632
|
+
shadowColor: "#000000",
|
|
633
|
+
shadowOffset: { width: 0, height: 1 },
|
|
634
|
+
shadowOpacity: 0.1,
|
|
635
|
+
shadowRadius: 2,
|
|
636
|
+
elevation: 2
|
|
637
|
+
},
|
|
638
|
+
"shadow-md": {
|
|
639
|
+
shadowColor: "#000000",
|
|
640
|
+
shadowOffset: { width: 0, height: 3 },
|
|
641
|
+
shadowOpacity: 0.15,
|
|
642
|
+
shadowRadius: 4,
|
|
643
|
+
elevation: 4
|
|
644
|
+
},
|
|
645
|
+
"shadow-lg": {
|
|
646
|
+
shadowColor: "#000000",
|
|
647
|
+
shadowOffset: { width: 0, height: 6 },
|
|
648
|
+
shadowOpacity: 0.2,
|
|
649
|
+
shadowRadius: 8,
|
|
650
|
+
elevation: 8
|
|
651
|
+
},
|
|
652
|
+
"shadow-xl": {
|
|
653
|
+
shadowColor: "#000000",
|
|
654
|
+
shadowOffset: { width: 0, height: 10 },
|
|
655
|
+
shadowOpacity: 0.25,
|
|
656
|
+
shadowRadius: 12,
|
|
657
|
+
elevation: 12
|
|
658
|
+
},
|
|
659
|
+
"shadow-2xl": {
|
|
660
|
+
shadowColor: "#000000",
|
|
661
|
+
shadowOffset: { width: 0, height: 20 },
|
|
662
|
+
shadowOpacity: 0.3,
|
|
663
|
+
shadowRadius: 24,
|
|
664
|
+
elevation: 16
|
|
665
|
+
},
|
|
666
|
+
"shadow-none": {
|
|
667
|
+
shadowColor: "transparent",
|
|
668
|
+
shadowOffset: { width: 0, height: 0 },
|
|
669
|
+
shadowOpacity: 0,
|
|
670
|
+
shadowRadius: 0,
|
|
671
|
+
elevation: 0
|
|
672
|
+
}
|
|
673
|
+
};
|
|
674
|
+
function parseShadow(cls) {
|
|
675
|
+
if (cls in SHADOW_SCALE) {
|
|
676
|
+
return SHADOW_SCALE[cls];
|
|
677
|
+
}
|
|
678
|
+
return null;
|
|
679
|
+
}
|
|
680
|
+
|
|
391
681
|
// src/parser/sizing.ts
|
|
392
682
|
var SIZE_SCALE = {
|
|
393
683
|
0: 0,
|
|
@@ -599,131 +889,99 @@ var SPACING_SCALE = {
|
|
|
599
889
|
80: 320,
|
|
600
890
|
96: 384
|
|
601
891
|
};
|
|
602
|
-
function
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
if (cls.startsWith("p-") || cls.startsWith("p")) {
|
|
607
|
-
return parsePadding(cls);
|
|
892
|
+
function parseArbitrarySpacing(value) {
|
|
893
|
+
const pxMatch = value.match(/^\[(\d+)(?:px)?\]$/);
|
|
894
|
+
if (pxMatch) {
|
|
895
|
+
return parseInt(pxMatch[1], 10);
|
|
608
896
|
}
|
|
609
|
-
if (
|
|
610
|
-
|
|
897
|
+
if (value.startsWith("[") && value.endsWith("]")) {
|
|
898
|
+
if (process.env.NODE_ENV !== "production") {
|
|
899
|
+
console.warn(
|
|
900
|
+
`[react-native-tailwind] Unsupported arbitrary spacing value: ${value}. Only px values are supported (e.g., [16px] or [16]).`
|
|
901
|
+
);
|
|
902
|
+
}
|
|
903
|
+
return null;
|
|
611
904
|
}
|
|
612
905
|
return null;
|
|
613
906
|
}
|
|
614
|
-
function
|
|
615
|
-
const
|
|
616
|
-
if (
|
|
617
|
-
const
|
|
618
|
-
|
|
619
|
-
|
|
907
|
+
function parseSpacing(cls) {
|
|
908
|
+
const marginMatch = cls.match(/^m([xytrbls]?)-(.+)$/);
|
|
909
|
+
if (marginMatch) {
|
|
910
|
+
const [, dir, valueStr] = marginMatch;
|
|
911
|
+
const arbitraryValue = parseArbitrarySpacing(valueStr);
|
|
912
|
+
if (arbitraryValue !== null) {
|
|
913
|
+
return getMarginStyle(dir, arbitraryValue);
|
|
620
914
|
}
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
const value = SPACING_SCALE[xMatch[1]];
|
|
625
|
-
if (value !== void 0) {
|
|
626
|
-
return { marginHorizontal: value };
|
|
915
|
+
const scaleValue = SPACING_SCALE[valueStr];
|
|
916
|
+
if (scaleValue !== void 0) {
|
|
917
|
+
return getMarginStyle(dir, scaleValue);
|
|
627
918
|
}
|
|
628
919
|
}
|
|
629
|
-
const
|
|
630
|
-
if (
|
|
631
|
-
const
|
|
632
|
-
|
|
633
|
-
|
|
920
|
+
const paddingMatch = cls.match(/^p([xytrbls]?)-(.+)$/);
|
|
921
|
+
if (paddingMatch) {
|
|
922
|
+
const [, dir, valueStr] = paddingMatch;
|
|
923
|
+
const arbitraryValue = parseArbitrarySpacing(valueStr);
|
|
924
|
+
if (arbitraryValue !== null) {
|
|
925
|
+
return getPaddingStyle(dir, arbitraryValue);
|
|
634
926
|
}
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
const value = SPACING_SCALE[tMatch[1]];
|
|
639
|
-
if (value !== void 0) {
|
|
640
|
-
return { marginTop: value };
|
|
927
|
+
const scaleValue = SPACING_SCALE[valueStr];
|
|
928
|
+
if (scaleValue !== void 0) {
|
|
929
|
+
return getPaddingStyle(dir, scaleValue);
|
|
641
930
|
}
|
|
642
931
|
}
|
|
643
|
-
const
|
|
644
|
-
if (
|
|
645
|
-
const
|
|
646
|
-
|
|
647
|
-
|
|
932
|
+
const gapMatch = cls.match(/^gap-(.+)$/);
|
|
933
|
+
if (gapMatch) {
|
|
934
|
+
const valueStr = gapMatch[1];
|
|
935
|
+
const arbitraryValue = parseArbitrarySpacing(valueStr);
|
|
936
|
+
if (arbitraryValue !== null) {
|
|
937
|
+
return { gap: arbitraryValue };
|
|
648
938
|
}
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
const value = SPACING_SCALE[bMatch[1]];
|
|
653
|
-
if (value !== void 0) {
|
|
654
|
-
return { marginBottom: value };
|
|
939
|
+
const scaleValue = SPACING_SCALE[valueStr];
|
|
940
|
+
if (scaleValue !== void 0) {
|
|
941
|
+
return { gap: scaleValue };
|
|
655
942
|
}
|
|
656
943
|
}
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
944
|
+
return null;
|
|
945
|
+
}
|
|
946
|
+
function getMarginStyle(dir, value) {
|
|
947
|
+
switch (dir) {
|
|
948
|
+
case "":
|
|
949
|
+
return { margin: value };
|
|
950
|
+
case "x":
|
|
951
|
+
return { marginHorizontal: value };
|
|
952
|
+
case "y":
|
|
953
|
+
return { marginVertical: value };
|
|
954
|
+
case "t":
|
|
955
|
+
return { marginTop: value };
|
|
956
|
+
case "r":
|
|
957
|
+
return { marginRight: value };
|
|
958
|
+
case "b":
|
|
959
|
+
return { marginBottom: value };
|
|
960
|
+
case "l":
|
|
661
961
|
return { marginLeft: value };
|
|
662
|
-
|
|
962
|
+
default:
|
|
963
|
+
return {};
|
|
663
964
|
}
|
|
664
|
-
return null;
|
|
665
965
|
}
|
|
666
|
-
function
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
const value = SPACING_SCALE[allMatch[1]];
|
|
670
|
-
if (value !== void 0) {
|
|
966
|
+
function getPaddingStyle(dir, value) {
|
|
967
|
+
switch (dir) {
|
|
968
|
+
case "":
|
|
671
969
|
return { padding: value };
|
|
672
|
-
|
|
673
|
-
}
|
|
674
|
-
const xMatch = cls.match(/^px-(\d+(?:\.\d+)?)$/);
|
|
675
|
-
if (xMatch) {
|
|
676
|
-
const value = SPACING_SCALE[xMatch[1]];
|
|
677
|
-
if (value !== void 0) {
|
|
970
|
+
case "x":
|
|
678
971
|
return { paddingHorizontal: value };
|
|
679
|
-
|
|
680
|
-
}
|
|
681
|
-
const yMatch = cls.match(/^py-(\d+(?:\.\d+)?)$/);
|
|
682
|
-
if (yMatch) {
|
|
683
|
-
const value = SPACING_SCALE[yMatch[1]];
|
|
684
|
-
if (value !== void 0) {
|
|
972
|
+
case "y":
|
|
685
973
|
return { paddingVertical: value };
|
|
686
|
-
|
|
687
|
-
}
|
|
688
|
-
const tMatch = cls.match(/^pt-(\d+(?:\.\d+)?)$/);
|
|
689
|
-
if (tMatch) {
|
|
690
|
-
const value = SPACING_SCALE[tMatch[1]];
|
|
691
|
-
if (value !== void 0) {
|
|
974
|
+
case "t":
|
|
692
975
|
return { paddingTop: value };
|
|
693
|
-
|
|
694
|
-
}
|
|
695
|
-
const rMatch = cls.match(/^pr-(\d+(?:\.\d+)?)$/);
|
|
696
|
-
if (rMatch) {
|
|
697
|
-
const value = SPACING_SCALE[rMatch[1]];
|
|
698
|
-
if (value !== void 0) {
|
|
976
|
+
case "r":
|
|
699
977
|
return { paddingRight: value };
|
|
700
|
-
|
|
701
|
-
}
|
|
702
|
-
const bMatch = cls.match(/^pb-(\d+(?:\.\d+)?)$/);
|
|
703
|
-
if (bMatch) {
|
|
704
|
-
const value = SPACING_SCALE[bMatch[1]];
|
|
705
|
-
if (value !== void 0) {
|
|
978
|
+
case "b":
|
|
706
979
|
return { paddingBottom: value };
|
|
707
|
-
|
|
708
|
-
}
|
|
709
|
-
const lMatch = cls.match(/^pl-(\d+(?:\.\d+)?)$/);
|
|
710
|
-
if (lMatch) {
|
|
711
|
-
const value = SPACING_SCALE[lMatch[1]];
|
|
712
|
-
if (value !== void 0) {
|
|
980
|
+
case "l":
|
|
713
981
|
return { paddingLeft: value };
|
|
714
|
-
|
|
982
|
+
default:
|
|
983
|
+
return {};
|
|
715
984
|
}
|
|
716
|
-
return null;
|
|
717
|
-
}
|
|
718
|
-
function parseGap(cls) {
|
|
719
|
-
const match = cls.match(/^gap-(\d+(?:\.\d+)?)$/);
|
|
720
|
-
if (match) {
|
|
721
|
-
const value = SPACING_SCALE[match[1]];
|
|
722
|
-
if (value !== void 0) {
|
|
723
|
-
return { gap: value };
|
|
724
|
-
}
|
|
725
|
-
}
|
|
726
|
-
return null;
|
|
727
985
|
}
|
|
728
986
|
|
|
729
987
|
// src/parser/typography.ts
|
|
@@ -742,99 +1000,142 @@ var FONT_SIZES = {
|
|
|
742
1000
|
"8xl": 96,
|
|
743
1001
|
"9xl": 128
|
|
744
1002
|
};
|
|
1003
|
+
var FONT_WEIGHT_MAP = {
|
|
1004
|
+
"font-thin": { fontWeight: "100" },
|
|
1005
|
+
"font-extralight": { fontWeight: "200" },
|
|
1006
|
+
"font-light": { fontWeight: "300" },
|
|
1007
|
+
"font-normal": { fontWeight: "400" },
|
|
1008
|
+
"font-medium": { fontWeight: "500" },
|
|
1009
|
+
"font-semibold": { fontWeight: "600" },
|
|
1010
|
+
"font-bold": { fontWeight: "700" },
|
|
1011
|
+
"font-extrabold": { fontWeight: "800" },
|
|
1012
|
+
"font-black": { fontWeight: "900" }
|
|
1013
|
+
};
|
|
1014
|
+
var FONT_STYLE_MAP = {
|
|
1015
|
+
italic: { fontStyle: "italic" },
|
|
1016
|
+
"not-italic": { fontStyle: "normal" }
|
|
1017
|
+
};
|
|
1018
|
+
var TEXT_ALIGN_MAP = {
|
|
1019
|
+
"text-left": { textAlign: "left" },
|
|
1020
|
+
"text-center": { textAlign: "center" },
|
|
1021
|
+
"text-right": { textAlign: "right" },
|
|
1022
|
+
"text-justify": { textAlign: "justify" }
|
|
1023
|
+
};
|
|
1024
|
+
var TEXT_DECORATION_MAP = {
|
|
1025
|
+
underline: { textDecorationLine: "underline" },
|
|
1026
|
+
"line-through": { textDecorationLine: "line-through" },
|
|
1027
|
+
"no-underline": { textDecorationLine: "none" }
|
|
1028
|
+
};
|
|
1029
|
+
var TEXT_TRANSFORM_MAP = {
|
|
1030
|
+
uppercase: { textTransform: "uppercase" },
|
|
1031
|
+
lowercase: { textTransform: "lowercase" },
|
|
1032
|
+
capitalize: { textTransform: "capitalize" },
|
|
1033
|
+
"normal-case": { textTransform: "none" }
|
|
1034
|
+
};
|
|
1035
|
+
var LINE_HEIGHT_MAP = {
|
|
1036
|
+
"leading-none": { lineHeight: 16 },
|
|
1037
|
+
"leading-tight": { lineHeight: 20 },
|
|
1038
|
+
"leading-snug": { lineHeight: 22 },
|
|
1039
|
+
"leading-normal": { lineHeight: 24 },
|
|
1040
|
+
"leading-relaxed": { lineHeight: 28 },
|
|
1041
|
+
"leading-loose": { lineHeight: 32 }
|
|
1042
|
+
};
|
|
1043
|
+
var TRACKING_MAP = {
|
|
1044
|
+
"tracking-tighter": { letterSpacing: -0.8 },
|
|
1045
|
+
"tracking-tight": { letterSpacing: -0.4 },
|
|
1046
|
+
"tracking-normal": { letterSpacing: 0 },
|
|
1047
|
+
"tracking-wide": { letterSpacing: 0.4 },
|
|
1048
|
+
"tracking-wider": { letterSpacing: 0.8 },
|
|
1049
|
+
"tracking-widest": { letterSpacing: 1.6 }
|
|
1050
|
+
};
|
|
1051
|
+
function parseArbitraryFontSize(value) {
|
|
1052
|
+
const pxMatch = value.match(/^\[(\d+)(?:px)?\]$/);
|
|
1053
|
+
if (pxMatch) {
|
|
1054
|
+
return parseInt(pxMatch[1], 10);
|
|
1055
|
+
}
|
|
1056
|
+
if (value.startsWith("[") && value.endsWith("]")) {
|
|
1057
|
+
if (process.env.NODE_ENV !== "production") {
|
|
1058
|
+
console.warn(
|
|
1059
|
+
`[react-native-tailwind] Unsupported arbitrary font size value: ${value}. Only px values are supported (e.g., [18px] or [18]).`
|
|
1060
|
+
);
|
|
1061
|
+
}
|
|
1062
|
+
return null;
|
|
1063
|
+
}
|
|
1064
|
+
return null;
|
|
1065
|
+
}
|
|
1066
|
+
function parseArbitraryLineHeight(value) {
|
|
1067
|
+
const pxMatch = value.match(/^\[(\d+)(?:px)?\]$/);
|
|
1068
|
+
if (pxMatch) {
|
|
1069
|
+
return parseInt(pxMatch[1], 10);
|
|
1070
|
+
}
|
|
1071
|
+
if (value.startsWith("[") && value.endsWith("]")) {
|
|
1072
|
+
if (process.env.NODE_ENV !== "production") {
|
|
1073
|
+
console.warn(
|
|
1074
|
+
`[react-native-tailwind] Unsupported arbitrary line height value: ${value}. Only px values are supported (e.g., [24px] or [24]).`
|
|
1075
|
+
);
|
|
1076
|
+
}
|
|
1077
|
+
return null;
|
|
1078
|
+
}
|
|
1079
|
+
return null;
|
|
1080
|
+
}
|
|
745
1081
|
function parseTypography(cls) {
|
|
746
1082
|
if (cls.startsWith("text-")) {
|
|
747
1083
|
const sizeKey = cls.substring(5);
|
|
1084
|
+
const arbitraryValue = parseArbitraryFontSize(sizeKey);
|
|
1085
|
+
if (arbitraryValue !== null) {
|
|
1086
|
+
return { fontSize: arbitraryValue };
|
|
1087
|
+
}
|
|
748
1088
|
const fontSize = FONT_SIZES[sizeKey];
|
|
749
1089
|
if (fontSize !== void 0) {
|
|
750
1090
|
return { fontSize };
|
|
751
1091
|
}
|
|
752
1092
|
}
|
|
753
|
-
if (cls
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
if (cls === "font-light") {
|
|
760
|
-
return { fontWeight: "300" };
|
|
761
|
-
}
|
|
762
|
-
if (cls === "font-normal") {
|
|
763
|
-
return { fontWeight: "400" };
|
|
764
|
-
}
|
|
765
|
-
if (cls === "font-medium") {
|
|
766
|
-
return { fontWeight: "500" };
|
|
767
|
-
}
|
|
768
|
-
if (cls === "font-semibold") {
|
|
769
|
-
return { fontWeight: "600" };
|
|
770
|
-
}
|
|
771
|
-
if (cls === "font-bold") {
|
|
772
|
-
return { fontWeight: "700" };
|
|
773
|
-
}
|
|
774
|
-
if (cls === "font-extrabold") {
|
|
775
|
-
return { fontWeight: "800" };
|
|
776
|
-
}
|
|
777
|
-
if (cls === "font-black") {
|
|
778
|
-
return { fontWeight: "900" };
|
|
779
|
-
}
|
|
780
|
-
if (cls === "italic") {
|
|
781
|
-
return { fontStyle: "italic" };
|
|
782
|
-
}
|
|
783
|
-
if (cls === "not-italic") {
|
|
784
|
-
return { fontStyle: "normal" };
|
|
785
|
-
}
|
|
786
|
-
if (cls === "text-left") {
|
|
787
|
-
return { textAlign: "left" };
|
|
788
|
-
}
|
|
789
|
-
if (cls === "text-center") {
|
|
790
|
-
return { textAlign: "center" };
|
|
791
|
-
}
|
|
792
|
-
if (cls === "text-right") {
|
|
793
|
-
return { textAlign: "right" };
|
|
794
|
-
}
|
|
795
|
-
if (cls === "text-justify") {
|
|
796
|
-
return { textAlign: "justify" };
|
|
797
|
-
}
|
|
798
|
-
if (cls === "underline") {
|
|
799
|
-
return { textDecorationLine: "underline" };
|
|
800
|
-
}
|
|
801
|
-
if (cls === "line-through") {
|
|
802
|
-
return { textDecorationLine: "line-through" };
|
|
803
|
-
}
|
|
804
|
-
if (cls === "no-underline") {
|
|
805
|
-
return { textDecorationLine: "none" };
|
|
806
|
-
}
|
|
807
|
-
if (cls === "uppercase") {
|
|
808
|
-
return { textTransform: "uppercase" };
|
|
809
|
-
}
|
|
810
|
-
if (cls === "lowercase") {
|
|
811
|
-
return { textTransform: "lowercase" };
|
|
812
|
-
}
|
|
813
|
-
if (cls === "capitalize") {
|
|
814
|
-
return { textTransform: "capitalize" };
|
|
815
|
-
}
|
|
816
|
-
if (cls === "normal-case") {
|
|
817
|
-
return { textTransform: "none" };
|
|
818
|
-
}
|
|
819
|
-
if (cls === "leading-none") {
|
|
820
|
-
return { lineHeight: 16 };
|
|
1093
|
+
if (cls.startsWith("leading-")) {
|
|
1094
|
+
const heightKey = cls.substring(8);
|
|
1095
|
+
const arbitraryValue = parseArbitraryLineHeight(heightKey);
|
|
1096
|
+
if (arbitraryValue !== null) {
|
|
1097
|
+
return { lineHeight: arbitraryValue };
|
|
1098
|
+
}
|
|
821
1099
|
}
|
|
822
|
-
|
|
823
|
-
|
|
1100
|
+
return FONT_WEIGHT_MAP[cls] ?? FONT_STYLE_MAP[cls] ?? TEXT_ALIGN_MAP[cls] ?? TEXT_DECORATION_MAP[cls] ?? TEXT_TRANSFORM_MAP[cls] ?? LINE_HEIGHT_MAP[cls] ?? TRACKING_MAP[cls] ?? null;
|
|
1101
|
+
}
|
|
1102
|
+
|
|
1103
|
+
// src/parser/modifiers.ts
|
|
1104
|
+
var SUPPORTED_MODIFIERS = ["active", "hover", "focus", "disabled"];
|
|
1105
|
+
function parseModifier(cls) {
|
|
1106
|
+
const colonIndex = cls.indexOf(":");
|
|
1107
|
+
if (colonIndex === -1) {
|
|
1108
|
+
return null;
|
|
824
1109
|
}
|
|
825
|
-
|
|
826
|
-
|
|
1110
|
+
const potentialModifier = cls.slice(0, colonIndex);
|
|
1111
|
+
const baseClass = cls.slice(colonIndex + 1);
|
|
1112
|
+
if (!SUPPORTED_MODIFIERS.includes(potentialModifier)) {
|
|
1113
|
+
return null;
|
|
827
1114
|
}
|
|
828
|
-
if (
|
|
829
|
-
return
|
|
1115
|
+
if (baseClass.includes(":")) {
|
|
1116
|
+
return null;
|
|
830
1117
|
}
|
|
831
|
-
if (
|
|
832
|
-
return
|
|
1118
|
+
if (!baseClass) {
|
|
1119
|
+
return null;
|
|
833
1120
|
}
|
|
834
|
-
|
|
835
|
-
|
|
1121
|
+
return {
|
|
1122
|
+
modifier: potentialModifier,
|
|
1123
|
+
baseClass
|
|
1124
|
+
};
|
|
1125
|
+
}
|
|
1126
|
+
function splitModifierClasses(className) {
|
|
1127
|
+
const classes = className.trim().split(/\s+/).filter(Boolean);
|
|
1128
|
+
const baseClasses = [];
|
|
1129
|
+
const modifierClasses = [];
|
|
1130
|
+
for (const cls of classes) {
|
|
1131
|
+
const parsed = parseModifier(cls);
|
|
1132
|
+
if (parsed) {
|
|
1133
|
+
modifierClasses.push(parsed);
|
|
1134
|
+
} else {
|
|
1135
|
+
baseClasses.push(cls);
|
|
1136
|
+
}
|
|
836
1137
|
}
|
|
837
|
-
return
|
|
1138
|
+
return { baseClasses, modifierClasses };
|
|
838
1139
|
}
|
|
839
1140
|
|
|
840
1141
|
// src/parser/index.ts
|
|
@@ -850,11 +1151,13 @@ function parseClassName(className, customColors) {
|
|
|
850
1151
|
function parseClass(cls, customColors) {
|
|
851
1152
|
const parsers = [
|
|
852
1153
|
parseSpacing,
|
|
1154
|
+
parseBorder,
|
|
853
1155
|
(cls2) => parseColor(cls2, customColors),
|
|
854
1156
|
parseLayout,
|
|
855
1157
|
parseTypography,
|
|
856
|
-
|
|
857
|
-
|
|
1158
|
+
parseSizing,
|
|
1159
|
+
parseShadow,
|
|
1160
|
+
parseAspectRatio
|
|
858
1161
|
];
|
|
859
1162
|
for (const parser of parsers) {
|
|
860
1163
|
const result = parser(cls);
|
|
@@ -953,12 +1256,16 @@ function extractCustomColors(filename) {
|
|
|
953
1256
|
var STYLES_IDENTIFIER = "_twStyles";
|
|
954
1257
|
var SUPPORTED_CLASS_ATTRIBUTES = [
|
|
955
1258
|
"className",
|
|
1259
|
+
"containerClassName",
|
|
956
1260
|
"contentContainerClassName",
|
|
957
1261
|
"columnWrapperClassName",
|
|
958
1262
|
"ListHeaderComponentClassName",
|
|
959
1263
|
"ListFooterComponentClassName"
|
|
960
1264
|
];
|
|
961
1265
|
function getTargetStyleProp(attributeName) {
|
|
1266
|
+
if (attributeName === "containerClassName") {
|
|
1267
|
+
return "containerStyle";
|
|
1268
|
+
}
|
|
962
1269
|
if (attributeName === "contentContainerClassName") {
|
|
963
1270
|
return "contentContainerStyle";
|
|
964
1271
|
}
|
|
@@ -973,6 +1280,33 @@ function getTargetStyleProp(attributeName) {
|
|
|
973
1280
|
}
|
|
974
1281
|
return "style";
|
|
975
1282
|
}
|
|
1283
|
+
function getComponentModifierSupport(jsxElement, t) {
|
|
1284
|
+
if (!t.isJSXOpeningElement(jsxElement)) {
|
|
1285
|
+
return null;
|
|
1286
|
+
}
|
|
1287
|
+
const name = jsxElement.name;
|
|
1288
|
+
let componentName = null;
|
|
1289
|
+
if (t.isJSXIdentifier(name)) {
|
|
1290
|
+
componentName = name.name;
|
|
1291
|
+
}
|
|
1292
|
+
if (t.isJSXMemberExpression(name)) {
|
|
1293
|
+
const property = name.property;
|
|
1294
|
+
if (t.isJSXIdentifier(property)) {
|
|
1295
|
+
componentName = property.name;
|
|
1296
|
+
}
|
|
1297
|
+
}
|
|
1298
|
+
if (!componentName) {
|
|
1299
|
+
return null;
|
|
1300
|
+
}
|
|
1301
|
+
switch (componentName) {
|
|
1302
|
+
case "Pressable":
|
|
1303
|
+
return { component: "Pressable", supportedModifiers: ["active", "hover", "focus", "disabled"] };
|
|
1304
|
+
case "TextInput":
|
|
1305
|
+
return { component: "TextInput", supportedModifiers: ["focus", "disabled"] };
|
|
1306
|
+
default:
|
|
1307
|
+
return null;
|
|
1308
|
+
}
|
|
1309
|
+
}
|
|
976
1310
|
function processDynamicExpression(expression, state, t) {
|
|
977
1311
|
if (t.isTemplateLiteral(expression)) {
|
|
978
1312
|
return processTemplateLiteral(expression, state, t);
|
|
@@ -1069,6 +1403,77 @@ function processStringOrExpression(node, state, t) {
|
|
|
1069
1403
|
}
|
|
1070
1404
|
return null;
|
|
1071
1405
|
}
|
|
1406
|
+
function processStaticClassNameWithModifiers(className, state, t) {
|
|
1407
|
+
const { baseClasses, modifierClasses } = splitModifierClasses(className);
|
|
1408
|
+
let baseStyleExpression = null;
|
|
1409
|
+
if (baseClasses.length > 0) {
|
|
1410
|
+
const baseClassName = baseClasses.join(" ");
|
|
1411
|
+
const baseStyleObject = parseClassName2(baseClassName, state.customColors);
|
|
1412
|
+
const baseStyleKey = generateStyleKey2(baseClassName);
|
|
1413
|
+
state.styleRegistry.set(baseStyleKey, baseStyleObject);
|
|
1414
|
+
baseStyleExpression = t.memberExpression(t.identifier(STYLES_IDENTIFIER), t.identifier(baseStyleKey));
|
|
1415
|
+
}
|
|
1416
|
+
const modifiersByType = /* @__PURE__ */ new Map();
|
|
1417
|
+
for (const mod of modifierClasses) {
|
|
1418
|
+
if (!modifiersByType.has(mod.modifier)) {
|
|
1419
|
+
modifiersByType.set(mod.modifier, []);
|
|
1420
|
+
}
|
|
1421
|
+
const modGroup = modifiersByType.get(mod.modifier);
|
|
1422
|
+
if (modGroup) {
|
|
1423
|
+
modGroup.push(mod);
|
|
1424
|
+
}
|
|
1425
|
+
}
|
|
1426
|
+
const styleArrayElements = [];
|
|
1427
|
+
if (baseStyleExpression) {
|
|
1428
|
+
styleArrayElements.push(baseStyleExpression);
|
|
1429
|
+
}
|
|
1430
|
+
for (const [modifierType, modifiers] of modifiersByType) {
|
|
1431
|
+
const modifierClassNames = modifiers.map((m) => m.baseClass).join(" ");
|
|
1432
|
+
const modifierStyleObject = parseClassName2(modifierClassNames, state.customColors);
|
|
1433
|
+
const modifierStyleKey = generateStyleKey2(`${modifierType}_${modifierClassNames}`);
|
|
1434
|
+
state.styleRegistry.set(modifierStyleKey, modifierStyleObject);
|
|
1435
|
+
const stateProperty = getStatePropertyForModifier(modifierType);
|
|
1436
|
+
const conditionalExpression = t.logicalExpression(
|
|
1437
|
+
"&&",
|
|
1438
|
+
t.identifier(stateProperty),
|
|
1439
|
+
t.memberExpression(t.identifier(STYLES_IDENTIFIER), t.identifier(modifierStyleKey))
|
|
1440
|
+
);
|
|
1441
|
+
styleArrayElements.push(conditionalExpression);
|
|
1442
|
+
}
|
|
1443
|
+
if (styleArrayElements.length === 1) {
|
|
1444
|
+
return styleArrayElements[0];
|
|
1445
|
+
}
|
|
1446
|
+
return t.arrayExpression(styleArrayElements);
|
|
1447
|
+
}
|
|
1448
|
+
function getStatePropertyForModifier(modifier) {
|
|
1449
|
+
switch (modifier) {
|
|
1450
|
+
case "active":
|
|
1451
|
+
return "pressed";
|
|
1452
|
+
case "hover":
|
|
1453
|
+
return "hovered";
|
|
1454
|
+
case "focus":
|
|
1455
|
+
return "focused";
|
|
1456
|
+
case "disabled":
|
|
1457
|
+
return "disabled";
|
|
1458
|
+
default:
|
|
1459
|
+
return "pressed";
|
|
1460
|
+
}
|
|
1461
|
+
}
|
|
1462
|
+
function createStyleFunction(styleExpression, modifierTypes, t) {
|
|
1463
|
+
const paramProperties = [];
|
|
1464
|
+
const usedStateProps = /* @__PURE__ */ new Set();
|
|
1465
|
+
for (const modifierType of modifierTypes) {
|
|
1466
|
+
const stateProperty = getStatePropertyForModifier(modifierType);
|
|
1467
|
+
if (!usedStateProps.has(stateProperty)) {
|
|
1468
|
+
usedStateProps.add(stateProperty);
|
|
1469
|
+
paramProperties.push(
|
|
1470
|
+
t.objectProperty(t.identifier(stateProperty), t.identifier(stateProperty), false, true)
|
|
1471
|
+
);
|
|
1472
|
+
}
|
|
1473
|
+
}
|
|
1474
|
+
const param = t.objectPattern(paramProperties);
|
|
1475
|
+
return t.arrowFunctionExpression([param], styleExpression);
|
|
1476
|
+
}
|
|
1072
1477
|
function reactNativeTailwindBabelPlugin({
|
|
1073
1478
|
types: t
|
|
1074
1479
|
}) {
|
|
@@ -1126,6 +1531,69 @@ function reactNativeTailwindBabelPlugin({
|
|
|
1126
1531
|
return;
|
|
1127
1532
|
}
|
|
1128
1533
|
state.hasClassNames = true;
|
|
1534
|
+
const { baseClasses, modifierClasses } = splitModifierClasses(className);
|
|
1535
|
+
if (modifierClasses.length > 0) {
|
|
1536
|
+
const jsxOpeningElement = path2.parent;
|
|
1537
|
+
const componentSupport = getComponentModifierSupport(jsxOpeningElement, t);
|
|
1538
|
+
if (componentSupport) {
|
|
1539
|
+
const usedModifiers = Array.from(new Set(modifierClasses.map((m) => m.modifier)));
|
|
1540
|
+
const unsupportedModifiers = usedModifiers.filter(
|
|
1541
|
+
(mod) => !componentSupport.supportedModifiers.includes(mod)
|
|
1542
|
+
);
|
|
1543
|
+
if (unsupportedModifiers.length > 0) {
|
|
1544
|
+
if (process.env.NODE_ENV !== "production") {
|
|
1545
|
+
console.warn(
|
|
1546
|
+
`[react-native-tailwind] Modifiers (${unsupportedModifiers.map((m) => `${m}:`).join(", ")}) are not supported on ${componentSupport.component} component at ${state.file.opts.filename ?? "unknown"}. Supported modifiers: ${componentSupport.supportedModifiers.join(", ")}`
|
|
1547
|
+
);
|
|
1548
|
+
}
|
|
1549
|
+
const supportedModifierClasses = modifierClasses.filter(
|
|
1550
|
+
(m) => componentSupport.supportedModifiers.includes(m.modifier)
|
|
1551
|
+
);
|
|
1552
|
+
if (supportedModifierClasses.length === 0) {
|
|
1553
|
+
} else {
|
|
1554
|
+
const filteredClassName = baseClasses.join(" ") + " " + supportedModifierClasses.map((m) => `${m.modifier}:${m.baseClass}`).join(" ");
|
|
1555
|
+
const styleExpression = processStaticClassNameWithModifiers(
|
|
1556
|
+
filteredClassName.trim(),
|
|
1557
|
+
state,
|
|
1558
|
+
t
|
|
1559
|
+
);
|
|
1560
|
+
const modifierTypes = Array.from(new Set(supportedModifierClasses.map((m) => m.modifier)));
|
|
1561
|
+
const styleFunctionExpression = createStyleFunction(styleExpression, modifierTypes, t);
|
|
1562
|
+
const parent2 = path2.parent;
|
|
1563
|
+
const styleAttribute2 = parent2.attributes.find(
|
|
1564
|
+
(attr) => t.isJSXAttribute(attr) && attr.name.name === targetStyleProp
|
|
1565
|
+
);
|
|
1566
|
+
if (styleAttribute2) {
|
|
1567
|
+
mergeStyleFunctionAttribute(path2, styleAttribute2, styleFunctionExpression, t);
|
|
1568
|
+
} else {
|
|
1569
|
+
replaceWithStyleFunctionAttribute(path2, styleFunctionExpression, targetStyleProp, t);
|
|
1570
|
+
}
|
|
1571
|
+
return;
|
|
1572
|
+
}
|
|
1573
|
+
} else {
|
|
1574
|
+
const styleExpression = processStaticClassNameWithModifiers(className, state, t);
|
|
1575
|
+
const modifierTypes = usedModifiers;
|
|
1576
|
+
const styleFunctionExpression = createStyleFunction(styleExpression, modifierTypes, t);
|
|
1577
|
+
const parent2 = path2.parent;
|
|
1578
|
+
const styleAttribute2 = parent2.attributes.find(
|
|
1579
|
+
(attr) => t.isJSXAttribute(attr) && attr.name.name === targetStyleProp
|
|
1580
|
+
);
|
|
1581
|
+
if (styleAttribute2) {
|
|
1582
|
+
mergeStyleFunctionAttribute(path2, styleAttribute2, styleFunctionExpression, t);
|
|
1583
|
+
} else {
|
|
1584
|
+
replaceWithStyleFunctionAttribute(path2, styleFunctionExpression, targetStyleProp, t);
|
|
1585
|
+
}
|
|
1586
|
+
return;
|
|
1587
|
+
}
|
|
1588
|
+
} else {
|
|
1589
|
+
if (process.env.NODE_ENV !== "production") {
|
|
1590
|
+
const usedModifiers = Array.from(new Set(modifierClasses.map((m) => m.modifier)));
|
|
1591
|
+
console.warn(
|
|
1592
|
+
`[react-native-tailwind] Modifiers (${usedModifiers.map((m) => `${m}:`).join(", ")}) can only be used on compatible components (Pressable, TextInput). Found on unsupported element at ${state.file.opts.filename ?? "unknown"}`
|
|
1593
|
+
);
|
|
1594
|
+
}
|
|
1595
|
+
}
|
|
1596
|
+
}
|
|
1129
1597
|
const styleObject = parseClassName2(className, state.customColors);
|
|
1130
1598
|
const styleKey = generateStyleKey2(className);
|
|
1131
1599
|
state.styleRegistry.set(styleKey, styleObject);
|
|
@@ -1219,6 +1687,31 @@ function mergeDynamicStyleAttribute(classNamePath, styleAttribute, result, t) {
|
|
|
1219
1687
|
styleAttribute.value = t.jsxExpressionContainer(styleArray);
|
|
1220
1688
|
classNamePath.remove();
|
|
1221
1689
|
}
|
|
1690
|
+
function replaceWithStyleFunctionAttribute(classNamePath, styleFunctionExpression, targetStyleProp, t) {
|
|
1691
|
+
const styleAttribute = t.jsxAttribute(
|
|
1692
|
+
t.jsxIdentifier(targetStyleProp),
|
|
1693
|
+
t.jsxExpressionContainer(styleFunctionExpression)
|
|
1694
|
+
);
|
|
1695
|
+
classNamePath.replaceWith(styleAttribute);
|
|
1696
|
+
}
|
|
1697
|
+
function mergeStyleFunctionAttribute(classNamePath, styleAttribute, styleFunctionExpression, t) {
|
|
1698
|
+
const existingStyle = styleAttribute.value.expression;
|
|
1699
|
+
if (t.isArrowFunctionExpression(existingStyle) || t.isFunctionExpression(existingStyle)) {
|
|
1700
|
+
const paramIdentifier = t.identifier("_state");
|
|
1701
|
+
const newFunctionCall = t.callExpression(styleFunctionExpression, [paramIdentifier]);
|
|
1702
|
+
const existingFunctionCall = t.callExpression(existingStyle, [paramIdentifier]);
|
|
1703
|
+
const mergedArray = t.arrayExpression([newFunctionCall, existingFunctionCall]);
|
|
1704
|
+
const wrapperFunction = t.arrowFunctionExpression([paramIdentifier], mergedArray);
|
|
1705
|
+
styleAttribute.value = t.jsxExpressionContainer(wrapperFunction);
|
|
1706
|
+
} else {
|
|
1707
|
+
const paramIdentifier = t.identifier("_state");
|
|
1708
|
+
const functionCall = t.callExpression(styleFunctionExpression, [paramIdentifier]);
|
|
1709
|
+
const mergedArray = t.arrayExpression([functionCall, existingStyle]);
|
|
1710
|
+
const wrapperFunction = t.arrowFunctionExpression([paramIdentifier], mergedArray);
|
|
1711
|
+
styleAttribute.value = t.jsxExpressionContainer(wrapperFunction);
|
|
1712
|
+
}
|
|
1713
|
+
classNamePath.remove();
|
|
1714
|
+
}
|
|
1222
1715
|
function injectStyles(path2, styleRegistry, t) {
|
|
1223
1716
|
const styleProperties = [];
|
|
1224
1717
|
for (const [key, styleObject] of styleRegistry) {
|