@mgcrea/react-native-tailwind 0.12.0 → 0.13.0
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 +29 -2014
- package/dist/babel/config-loader.d.ts +3 -0
- package/dist/babel/config-loader.test.ts +2 -2
- package/dist/babel/config-loader.ts +37 -2
- package/dist/babel/index.cjs +2855 -2434
- package/dist/babel/plugin/componentScope.d.ts +26 -0
- package/dist/babel/plugin/componentScope.ts +87 -0
- package/dist/babel/plugin/state.d.ts +119 -0
- package/dist/babel/plugin/state.ts +177 -0
- package/dist/babel/plugin/visitors/className.d.ts +11 -0
- package/{src/babel/plugin.test.ts → dist/babel/plugin/visitors/className.test.ts} +74 -674
- package/dist/babel/plugin/visitors/className.ts +624 -0
- package/dist/babel/plugin/visitors/className.windowDimensions.test.ts +406 -0
- package/dist/babel/plugin/visitors/imports.d.ts +11 -0
- package/dist/babel/plugin/visitors/imports.test.ts +88 -0
- package/dist/babel/plugin/visitors/imports.ts +101 -0
- package/dist/babel/plugin/visitors/program.d.ts +15 -0
- package/dist/babel/plugin/visitors/program.test.ts +325 -0
- package/dist/babel/plugin/visitors/program.ts +99 -0
- package/dist/babel/plugin/visitors/tw.d.ts +16 -0
- package/dist/babel/plugin/visitors/tw.test.ts +620 -0
- package/dist/babel/plugin/visitors/tw.ts +148 -0
- package/dist/babel/plugin.d.ts +3 -96
- package/dist/babel/plugin.test.ts +470 -0
- package/dist/babel/plugin.ts +28 -953
- package/dist/babel/utils/colorSchemeModifierProcessing.ts +11 -0
- package/dist/babel/utils/componentSupport.test.ts +20 -7
- package/dist/babel/utils/componentSupport.ts +2 -0
- package/dist/babel/utils/modifierProcessing.ts +21 -0
- package/dist/babel/utils/platformModifierProcessing.ts +11 -0
- package/dist/babel/utils/styleInjection.d.ts +15 -0
- package/dist/babel/utils/styleInjection.ts +172 -17
- package/dist/babel/utils/twProcessing.ts +11 -0
- package/dist/babel/utils/windowDimensionsProcessing.d.ts +56 -0
- package/dist/babel/utils/windowDimensionsProcessing.ts +121 -0
- package/dist/components/TouchableOpacity.d.ts +35 -0
- package/dist/components/TouchableOpacity.js +1 -0
- package/dist/components/index.d.ts +3 -0
- package/dist/components/index.js +1 -0
- package/dist/config/markers.d.ts +5 -0
- package/dist/config/markers.js +1 -0
- package/dist/index.d.ts +2 -5
- package/dist/index.js +1 -1
- package/dist/parser/borders.d.ts +3 -1
- package/dist/parser/borders.js +1 -1
- package/dist/parser/borders.test.js +1 -1
- package/dist/parser/colors.js +1 -1
- package/dist/parser/colors.test.js +1 -1
- package/dist/parser/index.d.ts +1 -0
- package/dist/parser/index.js +1 -1
- package/dist/parser/layout.js +1 -1
- package/dist/parser/layout.test.js +1 -1
- package/dist/parser/sizing.js +1 -1
- package/dist/parser/typography.d.ts +2 -1
- package/dist/parser/typography.js +1 -1
- package/dist/parser/typography.test.js +1 -1
- package/dist/runtime.cjs +1 -1
- package/dist/runtime.cjs.map +4 -4
- package/dist/runtime.js +1 -1
- package/dist/runtime.js.map +4 -4
- package/package.json +1 -1
- package/src/babel/config-loader.test.ts +2 -2
- package/src/babel/config-loader.ts +37 -2
- package/src/babel/plugin/componentScope.ts +87 -0
- package/src/babel/plugin/state.ts +177 -0
- package/src/babel/plugin/visitors/className.test.ts +1312 -0
- package/src/babel/plugin/visitors/className.ts +624 -0
- package/src/babel/plugin/visitors/className.windowDimensions.test.ts +406 -0
- package/src/babel/plugin/visitors/imports.test.ts +88 -0
- package/src/babel/plugin/visitors/imports.ts +101 -0
- package/src/babel/plugin/visitors/program.test.ts +325 -0
- package/src/babel/plugin/visitors/program.ts +99 -0
- package/src/babel/plugin/visitors/tw.test.ts +620 -0
- package/src/babel/plugin/visitors/tw.ts +148 -0
- package/src/babel/plugin.ts +28 -953
- package/src/babel/utils/colorSchemeModifierProcessing.ts +11 -0
- package/src/babel/utils/componentSupport.test.ts +20 -7
- package/src/babel/utils/componentSupport.ts +2 -0
- package/src/babel/utils/modifierProcessing.ts +21 -0
- package/src/babel/utils/platformModifierProcessing.ts +11 -0
- package/src/babel/utils/styleInjection.ts +172 -17
- package/src/babel/utils/twProcessing.ts +11 -0
- package/src/babel/utils/windowDimensionsProcessing.ts +121 -0
- package/src/components/TouchableOpacity.tsx +71 -0
- package/src/components/index.ts +3 -0
- package/src/config/markers.ts +5 -0
- package/src/index.ts +4 -5
- package/src/parser/borders.test.ts +58 -0
- package/src/parser/borders.ts +18 -3
- package/src/parser/colors.test.ts +249 -0
- package/src/parser/colors.ts +38 -0
- package/src/parser/index.ts +4 -3
- package/src/parser/layout.test.ts +61 -0
- package/src/parser/layout.ts +55 -1
- package/src/parser/sizing.ts +11 -0
- package/src/parser/typography.test.ts +102 -0
- package/src/parser/typography.ts +61 -15
|
@@ -1,236 +1,8 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-empty-function */
|
|
2
|
-
import { transformSync } from "@babel/core";
|
|
3
2
|
import { describe, expect, it, vi } from "vitest";
|
|
4
|
-
import
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Helper to transform code with the Babel plugin
|
|
8
|
-
*/
|
|
9
|
-
function transform(code: string, options?: PluginOptions, includeJsx = false) {
|
|
10
|
-
const presets = includeJsx
|
|
11
|
-
? ["@babel/preset-react", ["@babel/preset-typescript", { isTSX: true, allExtensions: true }]]
|
|
12
|
-
: [];
|
|
13
|
-
|
|
14
|
-
const result = transformSync(code, {
|
|
15
|
-
presets,
|
|
16
|
-
plugins: [[babelPlugin, options]],
|
|
17
|
-
filename: "test.tsx",
|
|
18
|
-
configFile: false,
|
|
19
|
-
babelrc: false,
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
return result?.code ?? "";
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
describe("Babel plugin - tw template tag transformation", () => {
|
|
26
|
-
it("should transform simple tw template literal", () => {
|
|
27
|
-
const input = `
|
|
28
|
-
import { tw } from '@mgcrea/react-native-tailwind';
|
|
29
|
-
const styles = tw\`bg-blue-500 m-4\`;
|
|
30
|
-
`;
|
|
31
|
-
|
|
32
|
-
const output = transform(input);
|
|
33
|
-
|
|
34
|
-
// Should have StyleSheet import (either ESM or CommonJS)
|
|
35
|
-
expect(output).toMatch(/import.*StyleSheet.*from "react-native"|require\("react-native"\)/);
|
|
36
|
-
expect(output).toContain("StyleSheet");
|
|
37
|
-
|
|
38
|
-
// Should have _twStyles definition
|
|
39
|
-
expect(output).toContain("_twStyles");
|
|
40
|
-
expect(output).toContain("StyleSheet.create");
|
|
41
|
-
|
|
42
|
-
// Should transform tw call to object with style property
|
|
43
|
-
expect(output).toContain("style:");
|
|
44
|
-
expect(output).toContain("_twStyles._bg_blue_500_m_4");
|
|
45
|
-
|
|
46
|
-
// Should remove tw import
|
|
47
|
-
expect(output).not.toContain("from '@mgcrea/react-native-tailwind'");
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
it("should transform tw with state modifiers", () => {
|
|
51
|
-
const input = `
|
|
52
|
-
import { tw } from '@mgcrea/react-native-tailwind';
|
|
53
|
-
const styles = tw\`bg-blue-500 active:bg-blue-700 disabled:bg-gray-300\`;
|
|
54
|
-
`;
|
|
55
|
-
|
|
56
|
-
const output = transform(input);
|
|
57
|
-
|
|
58
|
-
// Should have base style
|
|
59
|
-
expect(output).toContain("style:");
|
|
60
|
-
expect(output).toContain("_bg_blue_500");
|
|
61
|
-
|
|
62
|
-
// Should have activeStyle
|
|
63
|
-
expect(output).toContain("activeStyle:");
|
|
64
|
-
expect(output).toContain("_active_bg_blue_700");
|
|
65
|
-
|
|
66
|
-
// Should have disabledStyle
|
|
67
|
-
expect(output).toContain("disabledStyle:");
|
|
68
|
-
expect(output).toContain("_disabled_bg_gray_300");
|
|
69
|
-
|
|
70
|
-
// Should create StyleSheet with all styles
|
|
71
|
-
expect(output).toContain("backgroundColor:");
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
it("should inject StyleSheet.create after imports", () => {
|
|
75
|
-
const input = `
|
|
76
|
-
import { tw } from '@mgcrea/react-native-tailwind';
|
|
77
|
-
import { View } from 'react-native';
|
|
78
|
-
|
|
79
|
-
const styles = tw\`m-4\`;
|
|
80
|
-
`;
|
|
81
|
-
|
|
82
|
-
const output = transform(input);
|
|
83
|
-
|
|
84
|
-
// Find the position of imports and StyleSheet.create
|
|
85
|
-
const viewImportPos = output.indexOf('require("react-native")');
|
|
86
|
-
const styleSheetCreatePos = output.indexOf("_twStyles");
|
|
87
|
-
|
|
88
|
-
// StyleSheet.create should come after imports
|
|
89
|
-
expect(styleSheetCreatePos).toBeGreaterThan(viewImportPos);
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
it("should handle tw in object literals", () => {
|
|
93
|
-
const input = `
|
|
94
|
-
import { tw } from '@mgcrea/react-native-tailwind';
|
|
95
|
-
|
|
96
|
-
const sizeVariants = {
|
|
97
|
-
sm: {
|
|
98
|
-
container: tw\`h-9 px-3\`,
|
|
99
|
-
text: tw\`text-sm\`,
|
|
100
|
-
},
|
|
101
|
-
};
|
|
102
|
-
`;
|
|
103
|
-
|
|
104
|
-
const output = transform(input);
|
|
105
|
-
|
|
106
|
-
// Should define _twStyles before object literal
|
|
107
|
-
const twStylesPos = output.indexOf("_twStyles");
|
|
108
|
-
const sizeVariantsPos = output.indexOf("sizeVariants");
|
|
109
|
-
|
|
110
|
-
expect(twStylesPos).toBeGreaterThan(0);
|
|
111
|
-
expect(twStylesPos).toBeLessThan(sizeVariantsPos);
|
|
112
|
-
|
|
113
|
-
// Should have both styles
|
|
114
|
-
expect(output).toContain("_h_9_px_3");
|
|
115
|
-
expect(output).toContain("_text_sm");
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
it("should handle empty tw template literal", () => {
|
|
119
|
-
const input = `
|
|
120
|
-
import { tw } from '@mgcrea/react-native-tailwind';
|
|
121
|
-
const styles = tw\`\`;
|
|
122
|
-
`;
|
|
123
|
-
|
|
124
|
-
const output = transform(input);
|
|
125
|
-
|
|
126
|
-
// Should replace with empty style object
|
|
127
|
-
expect(output).toContain("style:");
|
|
128
|
-
expect(output).toContain("{}");
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
it("should preserve other imports from the same package", () => {
|
|
132
|
-
const input = `
|
|
133
|
-
import { tw, TwStyle, COLORS } from '@mgcrea/react-native-tailwind';
|
|
134
|
-
const styles = tw\`m-4\`;
|
|
135
|
-
`;
|
|
136
|
-
|
|
137
|
-
const output = transform(input);
|
|
138
|
-
|
|
139
|
-
// Should remove tw but keep other imports
|
|
140
|
-
expect(output).not.toContain('"tw"');
|
|
141
|
-
expect(output).toContain("TwStyle");
|
|
142
|
-
expect(output).toContain("COLORS");
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
it("should handle renamed tw import", () => {
|
|
146
|
-
const input = `
|
|
147
|
-
import { tw as customTw } from '@mgcrea/react-native-tailwind';
|
|
148
|
-
const styles = customTw\`m-4 p-2\`;
|
|
149
|
-
`;
|
|
150
|
-
|
|
151
|
-
const output = transform(input);
|
|
152
|
-
|
|
153
|
-
// Should still transform the renamed import
|
|
154
|
-
expect(output).toContain("_twStyles");
|
|
155
|
-
expect(output).toContain("_m_4_p_2");
|
|
156
|
-
expect(output).not.toContain("customTw");
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
it("should handle multiple tw calls", () => {
|
|
160
|
-
const input = `
|
|
161
|
-
import { tw } from '@mgcrea/react-native-tailwind';
|
|
162
|
-
const style1 = tw\`bg-red-500\`;
|
|
163
|
-
const style2 = tw\`bg-blue-500\`;
|
|
164
|
-
const style3 = tw\`bg-green-500\`;
|
|
165
|
-
`;
|
|
166
|
-
|
|
167
|
-
const output = transform(input);
|
|
168
|
-
|
|
169
|
-
// Should have all three styles in StyleSheet
|
|
170
|
-
expect(output).toContain("_bg_red_500");
|
|
171
|
-
expect(output).toContain("_bg_blue_500");
|
|
172
|
-
expect(output).toContain("_bg_green_500");
|
|
173
|
-
|
|
174
|
-
// Should have StyleSheet.create with all styles
|
|
175
|
-
expect(output).toContain("StyleSheet.create");
|
|
176
|
-
});
|
|
177
|
-
|
|
178
|
-
it("should use custom stylesIdentifier option", () => {
|
|
179
|
-
const input = `
|
|
180
|
-
import { tw } from '@mgcrea/react-native-tailwind';
|
|
181
|
-
const styles = tw\`m-4\`;
|
|
182
|
-
`;
|
|
183
|
-
|
|
184
|
-
const output = transform(input, { stylesIdentifier: "myStyles" });
|
|
185
|
-
|
|
186
|
-
// Should use custom identifier
|
|
187
|
-
expect(output).toContain("myStyles");
|
|
188
|
-
expect(output).toContain("myStyles._m_4");
|
|
189
|
-
expect(output).not.toContain("_twStyles");
|
|
190
|
-
});
|
|
191
|
-
});
|
|
192
|
-
|
|
193
|
-
describe("Babel plugin - twStyle function transformation", () => {
|
|
194
|
-
it("should transform twStyle function call", () => {
|
|
195
|
-
const input = `
|
|
196
|
-
import { twStyle } from '@mgcrea/react-native-tailwind';
|
|
197
|
-
const styles = twStyle('bg-blue-500 m-4');
|
|
198
|
-
`;
|
|
199
|
-
|
|
200
|
-
const output = transform(input);
|
|
201
|
-
|
|
202
|
-
// Should transform to object with style property
|
|
203
|
-
expect(output).toContain("style:");
|
|
204
|
-
expect(output).toContain("_twStyles._bg_blue_500_m_4");
|
|
205
|
-
});
|
|
206
|
-
|
|
207
|
-
it("should transform twStyle with modifiers", () => {
|
|
208
|
-
const input = `
|
|
209
|
-
import { twStyle } from '@mgcrea/react-native-tailwind';
|
|
210
|
-
const styles = twStyle('bg-blue-500 active:bg-blue-700');
|
|
211
|
-
`;
|
|
212
|
-
|
|
213
|
-
const output = transform(input);
|
|
214
|
-
|
|
215
|
-
expect(output).toContain("style:");
|
|
216
|
-
expect(output).toContain("activeStyle:");
|
|
217
|
-
});
|
|
218
|
-
|
|
219
|
-
it("should handle empty twStyle call", () => {
|
|
220
|
-
const input = `
|
|
221
|
-
import { twStyle } from '@mgcrea/react-native-tailwind';
|
|
222
|
-
const styles = twStyle('');
|
|
223
|
-
`;
|
|
224
|
-
|
|
225
|
-
const output = transform(input);
|
|
226
|
-
|
|
227
|
-
// Should replace with undefined
|
|
228
|
-
expect(output).toContain("undefined");
|
|
229
|
-
});
|
|
230
|
-
});
|
|
3
|
+
import { transform } from "../../../../test/helpers/babelTransform.js";
|
|
231
4
|
|
|
232
|
-
|
|
233
|
-
describe("Babel plugin - className transformation (existing behavior)", () => {
|
|
5
|
+
describe("className visitor - basic transformation", () => {
|
|
234
6
|
it("should still transform className props", () => {
|
|
235
7
|
const input = `
|
|
236
8
|
import { View } from 'react-native';
|
|
@@ -419,7 +191,7 @@ describe("Babel plugin - className transformation (existing behavior)", () => {
|
|
|
419
191
|
});
|
|
420
192
|
});
|
|
421
193
|
|
|
422
|
-
describe("
|
|
194
|
+
describe("className visitor - placeholder: modifier", () => {
|
|
423
195
|
it("should transform placeholder:text-{color} to placeholderTextColor prop", () => {
|
|
424
196
|
const input = `
|
|
425
197
|
import { TextInput } from 'react-native';
|
|
@@ -566,7 +338,7 @@ describe("Babel plugin - placeholder: modifier transformation", () => {
|
|
|
566
338
|
});
|
|
567
339
|
});
|
|
568
340
|
|
|
569
|
-
describe("
|
|
341
|
+
describe("className visitor - platform modifiers", () => {
|
|
570
342
|
it("should transform platform modifiers to Platform.select()", () => {
|
|
571
343
|
const input = `
|
|
572
344
|
import React from 'react';
|
|
@@ -807,7 +579,7 @@ describe("Babel plugin - platform modifier transformation", () => {
|
|
|
807
579
|
});
|
|
808
580
|
});
|
|
809
581
|
|
|
810
|
-
describe("
|
|
582
|
+
describe("className visitor - color scheme modifiers", () => {
|
|
811
583
|
it("should transform dark: modifier to conditional expression", () => {
|
|
812
584
|
const input = `
|
|
813
585
|
import React from 'react';
|
|
@@ -1107,7 +879,7 @@ describe("Babel plugin - color scheme modifier transformation", () => {
|
|
|
1107
879
|
});
|
|
1108
880
|
});
|
|
1109
881
|
|
|
1110
|
-
describe("
|
|
882
|
+
describe("className visitor - custom color scheme hook", () => {
|
|
1111
883
|
it("should use custom import source for color scheme hook", () => {
|
|
1112
884
|
const input = `
|
|
1113
885
|
import React from 'react';
|
|
@@ -1407,506 +1179,134 @@ describe("Babel plugin - custom color scheme hook import", () => {
|
|
|
1407
1179
|
});
|
|
1408
1180
|
});
|
|
1409
1181
|
|
|
1410
|
-
describe("
|
|
1411
|
-
it("should
|
|
1182
|
+
describe("className visitor - directional border colors", () => {
|
|
1183
|
+
it("should transform directional border colors with preset values", () => {
|
|
1412
1184
|
const input = `
|
|
1413
|
-
import { View
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
return <View><Text>Hello</Text></View>;
|
|
1185
|
+
import { View } from 'react-native';
|
|
1186
|
+
export function Component() {
|
|
1187
|
+
return <View className="border-t-red-500 border-l-blue-500" />;
|
|
1417
1188
|
}
|
|
1418
1189
|
`;
|
|
1419
1190
|
|
|
1420
1191
|
const output = transform(input, undefined, true);
|
|
1421
1192
|
|
|
1422
|
-
// Should
|
|
1423
|
-
|
|
1424
|
-
const styleSheetCount = (output.match(/StyleSheet/g) ?? []).length;
|
|
1425
|
-
expect(styleSheetCount).toBe(0);
|
|
1193
|
+
// Should have StyleSheet
|
|
1194
|
+
expect(output).toContain("StyleSheet.create");
|
|
1426
1195
|
|
|
1427
|
-
// Should
|
|
1428
|
-
expect(output).
|
|
1429
|
-
expect(output).
|
|
1196
|
+
// Should generate styles with borderTopColor and borderLeftColor
|
|
1197
|
+
expect(output).toMatch(/borderTopColor[:\s]*['"]#[0-9A-F]{6}['"]/i);
|
|
1198
|
+
expect(output).toMatch(/borderLeftColor[:\s]*['"]#[0-9A-F]{6}['"]/i);
|
|
1430
1199
|
|
|
1431
|
-
//
|
|
1432
|
-
expect(output).toContain("
|
|
1433
|
-
expect(output).toContain("Text");
|
|
1200
|
+
// Should not have className in output
|
|
1201
|
+
expect(output).not.toContain("className");
|
|
1434
1202
|
});
|
|
1435
1203
|
|
|
1436
|
-
it("should
|
|
1204
|
+
it("should combine directional border width and color", () => {
|
|
1437
1205
|
const input = `
|
|
1438
1206
|
import { View } from 'react-native';
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
return <View className="m-4 p-2" />;
|
|
1207
|
+
export function Component() {
|
|
1208
|
+
return <View className="border-l-2 border-l-red-500" />;
|
|
1442
1209
|
}
|
|
1443
1210
|
`;
|
|
1444
1211
|
|
|
1445
1212
|
const output = transform(input, undefined, true);
|
|
1446
1213
|
|
|
1447
|
-
// Should have
|
|
1448
|
-
expect(output).toMatch(/
|
|
1214
|
+
// Should have both borderLeftWidth and borderLeftColor in the StyleSheet
|
|
1215
|
+
expect(output).toMatch(/borderLeftWidth[:\s]*2/);
|
|
1216
|
+
expect(output).toMatch(/borderLeftColor[:\s]*['"]#[0-9A-F]{6}['"]/i);
|
|
1449
1217
|
|
|
1450
|
-
// Should have
|
|
1451
|
-
expect(output).toContain("
|
|
1452
|
-
expect(output).toContain("StyleSheet.create");
|
|
1218
|
+
// Should not have className in output
|
|
1219
|
+
expect(output).not.toContain("className");
|
|
1453
1220
|
});
|
|
1454
1221
|
|
|
1455
|
-
it("should
|
|
1222
|
+
it("should support directional border colors with opacity", () => {
|
|
1456
1223
|
const input = `
|
|
1457
1224
|
import { View } from 'react-native';
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
return <View className="ios:m-4 android:m-2" />;
|
|
1225
|
+
export function Component() {
|
|
1226
|
+
return <View className="border-t-red-500/50 border-b-blue-500/80" />;
|
|
1461
1227
|
}
|
|
1462
1228
|
`;
|
|
1463
1229
|
|
|
1464
1230
|
const output = transform(input, undefined, true);
|
|
1465
1231
|
|
|
1466
|
-
// Should have
|
|
1467
|
-
expect(output).
|
|
1468
|
-
|
|
1469
|
-
// Should have StyleSheet import too
|
|
1470
|
-
expect(output).toContain("StyleSheet");
|
|
1471
|
-
|
|
1472
|
-
// Should use Platform.select
|
|
1473
|
-
expect(output).toContain("Platform.select");
|
|
1232
|
+
// Should have 8-digit hex colors with alpha channel
|
|
1233
|
+
expect(output).toMatch(/borderTopColor[:\s]*['"]#[0-9A-F]{8}['"]/i);
|
|
1234
|
+
expect(output).toMatch(/borderBottomColor[:\s]*['"]#[0-9A-F]{8}['"]/i);
|
|
1474
1235
|
});
|
|
1475
1236
|
|
|
1476
|
-
it("should
|
|
1237
|
+
it("should support directional border colors with arbitrary hex values", () => {
|
|
1477
1238
|
const input = `
|
|
1478
1239
|
import { View } from 'react-native';
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
return <View className="m-4 p-2" />;
|
|
1240
|
+
export function Component() {
|
|
1241
|
+
return <View className="border-t-[#ff0000] border-r-[#abc]" />;
|
|
1482
1242
|
}
|
|
1483
1243
|
`;
|
|
1484
1244
|
|
|
1485
1245
|
const output = transform(input, undefined, true);
|
|
1486
1246
|
|
|
1487
|
-
// Should
|
|
1488
|
-
|
|
1489
|
-
expect(
|
|
1490
|
-
|
|
1491
|
-
// Should still have StyleSheet
|
|
1492
|
-
expect(output).toContain("StyleSheet");
|
|
1247
|
+
// Should have borderTopColor and borderRightColor
|
|
1248
|
+
expect(output).toMatch(/borderTopColor[:\s]*['"]#[0-9a-fA-F]{6}['"]/);
|
|
1249
|
+
expect(output).toMatch(/borderRightColor[:\s]*['"]#[0-9a-fA-F]{6}['"]/);
|
|
1493
1250
|
});
|
|
1494
|
-
});
|
|
1495
1251
|
|
|
1496
|
-
|
|
1497
|
-
it.skip("should expand scheme: modifier into dark: and light: modifiers", () => {
|
|
1498
|
-
// Note: This test requires tailwind.config.js with custom colors defined
|
|
1499
|
-
// The scheme: modifier expands to dark: and light: modifiers which require
|
|
1500
|
-
// the color variants to exist in customColors (e.g., systemGray-dark, systemGray-light)
|
|
1501
|
-
//
|
|
1502
|
-
// Integration test should be done in a real project with tailwind.config.js
|
|
1252
|
+
it("should support all four directional border colors", () => {
|
|
1503
1253
|
const input = `
|
|
1504
1254
|
import { View } from 'react-native';
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1255
|
+
export function Component() {
|
|
1256
|
+
return (
|
|
1257
|
+
<View className="border-t-red-500 border-r-blue-500 border-b-green-500 border-l-yellow-500" />
|
|
1258
|
+
);
|
|
1508
1259
|
}
|
|
1509
1260
|
`;
|
|
1510
1261
|
|
|
1511
1262
|
const output = transform(input, undefined, true);
|
|
1512
1263
|
|
|
1513
|
-
// Should
|
|
1514
|
-
expect(output).
|
|
1515
|
-
expect(output).
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
expect(output).toContain("useColorScheme");
|
|
1519
|
-
expect(output).toContain("_twColorScheme");
|
|
1520
|
-
|
|
1521
|
-
// Should have conditional expressions
|
|
1522
|
-
expect(output).toContain("_twColorScheme === 'dark'");
|
|
1523
|
-
expect(output).toContain("_twColorScheme === 'light'");
|
|
1524
|
-
});
|
|
1525
|
-
});
|
|
1526
|
-
|
|
1527
|
-
describe("Babel plugin - color scheme modifiers in tw/twStyle", () => {
|
|
1528
|
-
it("should transform tw with dark: modifier inside component", () => {
|
|
1529
|
-
const input = `
|
|
1530
|
-
import { tw } from '@mgcrea/react-native-tailwind';
|
|
1531
|
-
|
|
1532
|
-
function MyComponent() {
|
|
1533
|
-
const styles = tw\`bg-white dark:bg-gray-900\`;
|
|
1534
|
-
return null;
|
|
1535
|
-
}
|
|
1536
|
-
`;
|
|
1537
|
-
|
|
1538
|
-
const output = transform(input);
|
|
1539
|
-
|
|
1540
|
-
// Should inject useColorScheme hook
|
|
1541
|
-
expect(output).toContain("useColorScheme");
|
|
1542
|
-
expect(output).toContain("_twColorScheme");
|
|
1543
|
-
|
|
1544
|
-
// Should generate style array with conditionals
|
|
1545
|
-
expect(output).toContain("style: [");
|
|
1546
|
-
expect(output).toContain('_twColorScheme === "dark"');
|
|
1547
|
-
expect(output).toContain("_twStyles._dark_bg_gray_900");
|
|
1548
|
-
expect(output).toContain("_twStyles._bg_white");
|
|
1549
|
-
|
|
1550
|
-
// Should have StyleSheet.create
|
|
1551
|
-
expect(output).toContain("StyleSheet.create");
|
|
1264
|
+
// Should have all four directional color properties
|
|
1265
|
+
expect(output).toMatch(/borderTopColor[:\s]*['"]#[0-9A-F]{6}['"]/i);
|
|
1266
|
+
expect(output).toMatch(/borderRightColor[:\s]*['"]#[0-9A-F]{6}['"]/i);
|
|
1267
|
+
expect(output).toMatch(/borderBottomColor[:\s]*['"]#[0-9A-F]{6}['"]/i);
|
|
1268
|
+
expect(output).toMatch(/borderLeftColor[:\s]*['"]#[0-9A-F]{6}['"]/i);
|
|
1552
1269
|
});
|
|
1553
1270
|
|
|
1554
|
-
it("should
|
|
1271
|
+
it("should combine directional widths, colors, and general border color", () => {
|
|
1555
1272
|
const input = `
|
|
1556
|
-
import {
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
};
|
|
1562
|
-
`;
|
|
1563
|
-
|
|
1564
|
-
const output = transform(input);
|
|
1565
|
-
|
|
1566
|
-
// Should inject useColorScheme hook
|
|
1567
|
-
expect(output).toContain("useColorScheme");
|
|
1568
|
-
expect(output).toContain("_twColorScheme");
|
|
1569
|
-
|
|
1570
|
-
// Should generate style array with conditionals
|
|
1571
|
-
expect(output).toContain("style: [");
|
|
1572
|
-
expect(output).toContain('_twColorScheme === "light"');
|
|
1573
|
-
expect(output).toContain("_twStyles._light_text_gray_100");
|
|
1574
|
-
expect(output).toContain("_twStyles._text_gray_900");
|
|
1575
|
-
});
|
|
1576
|
-
|
|
1577
|
-
it("should transform tw with both dark: and light: modifiers", () => {
|
|
1578
|
-
const input = `
|
|
1579
|
-
import { tw } from '@mgcrea/react-native-tailwind';
|
|
1580
|
-
|
|
1581
|
-
function MyComponent() {
|
|
1582
|
-
const styles = tw\`bg-blue-500 dark:bg-blue-900 light:bg-blue-100\`;
|
|
1583
|
-
return null;
|
|
1584
|
-
}
|
|
1585
|
-
`;
|
|
1586
|
-
|
|
1587
|
-
const output = transform(input);
|
|
1588
|
-
|
|
1589
|
-
// Should have both conditionals
|
|
1590
|
-
expect(output).toContain('_twColorScheme === "dark"');
|
|
1591
|
-
expect(output).toContain('_twColorScheme === "light"');
|
|
1592
|
-
expect(output).toContain("_twStyles._dark_bg_blue_900");
|
|
1593
|
-
expect(output).toContain("_twStyles._light_bg_blue_100");
|
|
1594
|
-
expect(output).toContain("_twStyles._bg_blue_500");
|
|
1595
|
-
});
|
|
1596
|
-
|
|
1597
|
-
it("should combine color scheme modifiers with state modifiers", () => {
|
|
1598
|
-
const input = `
|
|
1599
|
-
import { tw } from '@mgcrea/react-native-tailwind';
|
|
1600
|
-
|
|
1601
|
-
function MyComponent() {
|
|
1602
|
-
const styles = tw\`bg-white dark:bg-gray-900 active:bg-blue-500\`;
|
|
1603
|
-
return null;
|
|
1604
|
-
}
|
|
1605
|
-
`;
|
|
1606
|
-
|
|
1607
|
-
const output = transform(input);
|
|
1608
|
-
|
|
1609
|
-
// Should have color scheme conditionals in style array
|
|
1610
|
-
expect(output).toContain("style: [");
|
|
1611
|
-
expect(output).toContain('_twColorScheme === "dark"');
|
|
1612
|
-
|
|
1613
|
-
// Should have activeStyle property (separate from color scheme)
|
|
1614
|
-
expect(output).toContain("activeStyle:");
|
|
1615
|
-
expect(output).toContain("_twStyles._active_bg_blue_500");
|
|
1616
|
-
});
|
|
1617
|
-
|
|
1618
|
-
it("should warn if tw with color scheme modifiers used outside component", () => {
|
|
1619
|
-
const consoleWarnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
|
|
1620
|
-
|
|
1621
|
-
const input = `
|
|
1622
|
-
import { tw } from '@mgcrea/react-native-tailwind';
|
|
1623
|
-
|
|
1624
|
-
const globalStyles = tw\`bg-white dark:bg-gray-900\`;
|
|
1625
|
-
`;
|
|
1626
|
-
|
|
1627
|
-
const output = transform(input);
|
|
1628
|
-
|
|
1629
|
-
// Should warn about usage outside component
|
|
1630
|
-
expect(consoleWarnSpy).toHaveBeenCalledWith(
|
|
1631
|
-
expect.stringContaining("Color scheme modifiers (dark:, light:) in tw/twStyle calls"),
|
|
1632
|
-
);
|
|
1633
|
-
|
|
1634
|
-
// Should not inject hook (no component scope)
|
|
1635
|
-
expect(output).not.toContain("useColorScheme");
|
|
1636
|
-
|
|
1637
|
-
// Should still generate styles but without runtime conditionals
|
|
1638
|
-
expect(output).toContain("_twStyles");
|
|
1639
|
-
|
|
1640
|
-
consoleWarnSpy.mockRestore();
|
|
1641
|
-
});
|
|
1642
|
-
|
|
1643
|
-
it("should handle tw with only dark: modifier (no base class)", () => {
|
|
1644
|
-
const input = `
|
|
1645
|
-
import { tw } from '@mgcrea/react-native-tailwind';
|
|
1646
|
-
|
|
1647
|
-
function MyComponent() {
|
|
1648
|
-
const styles = tw\`dark:bg-gray-900\`;
|
|
1649
|
-
return null;
|
|
1650
|
-
}
|
|
1651
|
-
`;
|
|
1652
|
-
|
|
1653
|
-
const output = transform(input);
|
|
1654
|
-
|
|
1655
|
-
// Should still generate style array
|
|
1656
|
-
expect(output).toContain("style: [");
|
|
1657
|
-
expect(output).toContain('_twColorScheme === "dark"');
|
|
1658
|
-
expect(output).toContain("_twStyles._dark_bg_gray_900");
|
|
1659
|
-
});
|
|
1660
|
-
|
|
1661
|
-
it("should work with custom color scheme hook import", () => {
|
|
1662
|
-
const input = `
|
|
1663
|
-
import { tw } from '@mgcrea/react-native-tailwind';
|
|
1664
|
-
import { useTheme } from '@react-navigation/native';
|
|
1665
|
-
|
|
1666
|
-
function MyComponent() {
|
|
1667
|
-
const styles = tw\`bg-white dark:bg-gray-900\`;
|
|
1668
|
-
return null;
|
|
1669
|
-
}
|
|
1670
|
-
`;
|
|
1671
|
-
|
|
1672
|
-
const options: PluginOptions = {
|
|
1673
|
-
colorScheme: {
|
|
1674
|
-
importFrom: "@react-navigation/native",
|
|
1675
|
-
importName: "useTheme",
|
|
1676
|
-
},
|
|
1677
|
-
};
|
|
1678
|
-
|
|
1679
|
-
const output = transform(input, options);
|
|
1680
|
-
|
|
1681
|
-
// Should use existing import (not duplicate)
|
|
1682
|
-
const themeImportCount = (output.match(/useTheme/g) ?? []).length;
|
|
1683
|
-
// Should appear in import statement and hook call
|
|
1684
|
-
expect(themeImportCount).toBeGreaterThanOrEqual(2);
|
|
1685
|
-
|
|
1686
|
-
// Should call the custom hook
|
|
1687
|
-
expect(output).toContain("useTheme()");
|
|
1688
|
-
});
|
|
1689
|
-
|
|
1690
|
-
it("should generate both style array and darkStyle/lightStyle properties", () => {
|
|
1691
|
-
const input = `
|
|
1692
|
-
import { tw } from '@mgcrea/react-native-tailwind';
|
|
1693
|
-
|
|
1694
|
-
function MyComponent() {
|
|
1695
|
-
const styles = tw\`bg-white dark:bg-gray-900 light:bg-gray-50\`;
|
|
1696
|
-
return null;
|
|
1697
|
-
}
|
|
1698
|
-
`;
|
|
1699
|
-
|
|
1700
|
-
const output = transform(input);
|
|
1701
|
-
|
|
1702
|
-
// Should have runtime conditional in style array
|
|
1703
|
-
expect(output).toContain("style: [");
|
|
1704
|
-
expect(output).toContain('_twColorScheme === "dark"');
|
|
1705
|
-
expect(output).toContain('_twColorScheme === "light"');
|
|
1706
|
-
|
|
1707
|
-
// Should ALSO have darkStyle and lightStyle properties for manual access
|
|
1708
|
-
expect(output).toContain("darkStyle:");
|
|
1709
|
-
expect(output).toContain("lightStyle:");
|
|
1710
|
-
expect(output).toContain("_twStyles._dark_bg_gray_900");
|
|
1711
|
-
expect(output).toContain("_twStyles._light_bg_gray_50");
|
|
1712
|
-
});
|
|
1713
|
-
|
|
1714
|
-
it("should allow accessing raw color values from darkStyle/lightStyle", () => {
|
|
1715
|
-
const input = `
|
|
1716
|
-
import { tw } from '@mgcrea/react-native-tailwind';
|
|
1717
|
-
|
|
1718
|
-
function MyComponent() {
|
|
1719
|
-
const btnStyles = tw\`bg-blue-500 dark:bg-blue-900\`;
|
|
1720
|
-
// User can access raw hex for Reanimated
|
|
1721
|
-
const darkBgColor = btnStyles.darkStyle?.backgroundColor;
|
|
1722
|
-
return null;
|
|
1723
|
-
}
|
|
1724
|
-
`;
|
|
1725
|
-
|
|
1726
|
-
const output = transform(input);
|
|
1727
|
-
|
|
1728
|
-
// Should have darkStyle property available
|
|
1729
|
-
expect(output).toContain("darkStyle:");
|
|
1730
|
-
expect(output).toContain("_twStyles._dark_bg_blue_900");
|
|
1731
|
-
|
|
1732
|
-
// The actual usage line should be preserved (TypeScript/Babel doesn't remove it)
|
|
1733
|
-
expect(output).toContain("btnStyles.darkStyle");
|
|
1734
|
-
});
|
|
1735
|
-
|
|
1736
|
-
// Platform modifier tests for tw/twStyle
|
|
1737
|
-
it("should transform tw with ios: modifier", () => {
|
|
1738
|
-
const input = `
|
|
1739
|
-
import { tw } from '@mgcrea/react-native-tailwind';
|
|
1740
|
-
|
|
1741
|
-
function MyComponent() {
|
|
1742
|
-
const styles = tw\`bg-white ios:p-6\`;
|
|
1743
|
-
return null;
|
|
1744
|
-
}
|
|
1745
|
-
`;
|
|
1746
|
-
|
|
1747
|
-
const output = transform(input);
|
|
1748
|
-
|
|
1749
|
-
// Should add Platform import
|
|
1750
|
-
expect(output).toContain("Platform");
|
|
1751
|
-
expect(output).toContain('from "react-native"');
|
|
1752
|
-
|
|
1753
|
-
// Should generate style array with Platform.select()
|
|
1754
|
-
expect(output).toContain("style: [");
|
|
1755
|
-
expect(output).toContain("Platform.select");
|
|
1756
|
-
expect(output).toContain("ios:");
|
|
1757
|
-
expect(output).toContain("_twStyles._ios_p_6");
|
|
1758
|
-
expect(output).toContain("_twStyles._bg_white");
|
|
1759
|
-
|
|
1760
|
-
// Should have StyleSheet.create
|
|
1761
|
-
expect(output).toContain("StyleSheet.create");
|
|
1762
|
-
});
|
|
1763
|
-
|
|
1764
|
-
it("should transform twStyle with android: modifier", () => {
|
|
1765
|
-
const input = `
|
|
1766
|
-
import { twStyle } from '@mgcrea/react-native-tailwind';
|
|
1767
|
-
|
|
1768
|
-
export const MyComponent = () => {
|
|
1769
|
-
const buttonStyles = twStyle('bg-blue-500 android:p-8');
|
|
1770
|
-
return null;
|
|
1771
|
-
};
|
|
1772
|
-
`;
|
|
1773
|
-
|
|
1774
|
-
const output = transform(input);
|
|
1775
|
-
|
|
1776
|
-
// Should add Platform import
|
|
1777
|
-
expect(output).toContain("Platform");
|
|
1778
|
-
|
|
1779
|
-
// Should generate style array with Platform.select()
|
|
1780
|
-
expect(output).toContain("style: [");
|
|
1781
|
-
expect(output).toContain("Platform.select");
|
|
1782
|
-
expect(output).toContain("android:");
|
|
1783
|
-
expect(output).toContain("_twStyles._android_p_8");
|
|
1784
|
-
expect(output).toContain("_twStyles._bg_blue_500");
|
|
1785
|
-
});
|
|
1786
|
-
|
|
1787
|
-
it("should transform tw with multiple platform modifiers", () => {
|
|
1788
|
-
const input = `
|
|
1789
|
-
import { tw } from '@mgcrea/react-native-tailwind';
|
|
1790
|
-
|
|
1791
|
-
function MyComponent() {
|
|
1792
|
-
const styles = tw\`bg-white ios:p-6 android:p-8 web:p-4\`;
|
|
1793
|
-
return null;
|
|
1794
|
-
}
|
|
1795
|
-
`;
|
|
1796
|
-
|
|
1797
|
-
const output = transform(input);
|
|
1798
|
-
|
|
1799
|
-
// Should generate Platform.select() with all platforms
|
|
1800
|
-
expect(output).toContain("Platform.select");
|
|
1801
|
-
expect(output).toContain("ios:");
|
|
1802
|
-
expect(output).toContain("android:");
|
|
1803
|
-
expect(output).toContain("web:");
|
|
1804
|
-
expect(output).toContain("_twStyles._ios_p_6");
|
|
1805
|
-
expect(output).toContain("_twStyles._android_p_8");
|
|
1806
|
-
expect(output).toContain("_twStyles._web_p_4");
|
|
1807
|
-
});
|
|
1808
|
-
|
|
1809
|
-
it("should combine platform modifiers with color-scheme modifiers", () => {
|
|
1810
|
-
const input = `
|
|
1811
|
-
import { tw } from '@mgcrea/react-native-tailwind';
|
|
1812
|
-
|
|
1813
|
-
function MyComponent() {
|
|
1814
|
-
const styles = tw\`bg-white ios:p-6 dark:bg-gray-900\`;
|
|
1815
|
-
return null;
|
|
1816
|
-
}
|
|
1817
|
-
`;
|
|
1818
|
-
|
|
1819
|
-
const output = transform(input);
|
|
1820
|
-
|
|
1821
|
-
// Should have both Platform and useColorScheme
|
|
1822
|
-
expect(output).toContain("Platform");
|
|
1823
|
-
expect(output).toContain("useColorScheme");
|
|
1824
|
-
expect(output).toContain("_twColorScheme");
|
|
1825
|
-
|
|
1826
|
-
// Should have both conditionals in style array
|
|
1827
|
-
expect(output).toContain("Platform.select");
|
|
1828
|
-
expect(output).toContain('_twColorScheme === "dark"');
|
|
1829
|
-
});
|
|
1830
|
-
|
|
1831
|
-
it("should generate iosStyle/androidStyle/webStyle properties for manual access", () => {
|
|
1832
|
-
const input = `
|
|
1833
|
-
import { tw } from '@mgcrea/react-native-tailwind';
|
|
1834
|
-
|
|
1835
|
-
function MyComponent() {
|
|
1836
|
-
const styles = tw\`bg-white ios:p-6 android:p-8 web:p-4\`;
|
|
1837
|
-
return null;
|
|
1273
|
+
import { View } from 'react-native';
|
|
1274
|
+
export function Component() {
|
|
1275
|
+
return (
|
|
1276
|
+
<View className="border border-gray-300 border-l-4 border-l-blue-500" />
|
|
1277
|
+
);
|
|
1838
1278
|
}
|
|
1839
1279
|
`;
|
|
1840
1280
|
|
|
1841
|
-
const output = transform(input);
|
|
1842
|
-
|
|
1843
|
-
// Should have separate platform style properties
|
|
1844
|
-
expect(output).toContain("iosStyle:");
|
|
1845
|
-
expect(output).toContain("_twStyles._ios_p_6");
|
|
1846
|
-
expect(output).toContain("androidStyle:");
|
|
1847
|
-
expect(output).toContain("_twStyles._android_p_8");
|
|
1848
|
-
expect(output).toContain("webStyle:");
|
|
1849
|
-
expect(output).toContain("_twStyles._web_p_4");
|
|
1850
|
-
|
|
1851
|
-
// Should also have runtime Platform.select() in style array
|
|
1852
|
-
expect(output).toContain("Platform.select");
|
|
1853
|
-
});
|
|
1854
|
-
|
|
1855
|
-
it("should work with only platform modifiers (no base class)", () => {
|
|
1856
|
-
const input = `
|
|
1857
|
-
import { tw } from '@mgcrea/react-native-tailwind';
|
|
1858
|
-
|
|
1859
|
-
function MyComponent() {
|
|
1860
|
-
const styles = tw\`ios:p-6 android:p-8\`;
|
|
1861
|
-
return null;
|
|
1862
|
-
}
|
|
1863
|
-
`;
|
|
1281
|
+
const output = transform(input, undefined, true);
|
|
1864
1282
|
|
|
1865
|
-
|
|
1283
|
+
// Should have general border properties
|
|
1284
|
+
expect(output).toMatch(/borderWidth[:\s]*1/);
|
|
1285
|
+
expect(output).toMatch(/borderColor[:\s]*['"]#[0-9A-F]{6}['"]/i);
|
|
1866
1286
|
|
|
1867
|
-
// Should
|
|
1868
|
-
expect(output).
|
|
1869
|
-
expect(output).
|
|
1870
|
-
expect(output).toContain("_twStyles._android_p_8");
|
|
1287
|
+
// Should have directional left border properties
|
|
1288
|
+
expect(output).toMatch(/borderLeftWidth[:\s]*4/);
|
|
1289
|
+
expect(output).toMatch(/borderLeftColor[:\s]*['"]#[0-9A-F]{6}['"]/i);
|
|
1871
1290
|
});
|
|
1872
1291
|
|
|
1873
|
-
it("should
|
|
1292
|
+
it("should work with dynamic className containing directional border colors", () => {
|
|
1874
1293
|
const input = `
|
|
1875
|
-
import {
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
return null;
|
|
1294
|
+
import { View } from 'react-native';
|
|
1295
|
+
export function Component({ isError }) {
|
|
1296
|
+
return (
|
|
1297
|
+
<View className={\`border-t-2 \${isError ? 'border-t-red-500' : 'border-t-gray-300'}\`} />
|
|
1298
|
+
);
|
|
1881
1299
|
}
|
|
1882
1300
|
`;
|
|
1883
1301
|
|
|
1884
|
-
const output = transform(input);
|
|
1885
|
-
|
|
1886
|
-
// Should have iosStyle property available
|
|
1887
|
-
expect(output).toContain("iosStyle:");
|
|
1888
|
-
expect(output).toContain("_twStyles._ios_p_6");
|
|
1889
|
-
|
|
1890
|
-
// The actual usage line should be preserved
|
|
1891
|
-
expect(output).toContain("btnStyles.iosStyle");
|
|
1892
|
-
});
|
|
1893
|
-
|
|
1894
|
-
it("should combine state modifiers with platform modifiers", () => {
|
|
1895
|
-
const input = `
|
|
1896
|
-
import { tw } from '@mgcrea/react-native-tailwind';
|
|
1897
|
-
|
|
1898
|
-
function MyComponent() {
|
|
1899
|
-
const styles = tw\`bg-white active:bg-blue-500 ios:p-6\`;
|
|
1900
|
-
return null;
|
|
1901
|
-
}
|
|
1902
|
-
`;
|
|
1302
|
+
const output = transform(input, undefined, true);
|
|
1903
1303
|
|
|
1904
|
-
|
|
1304
|
+
// Should have StyleSheet with both color options
|
|
1305
|
+
expect(output).toContain("_border_t_2");
|
|
1306
|
+
expect(output).toContain("_border_t_red_500");
|
|
1307
|
+
expect(output).toContain("_border_t_gray_300");
|
|
1905
1308
|
|
|
1906
|
-
// Should have
|
|
1907
|
-
expect(output).
|
|
1908
|
-
expect(output).toContain("_twStyles._active_bg_blue_500");
|
|
1909
|
-
expect(output).toContain("Platform.select");
|
|
1910
|
-
expect(output).toContain("_twStyles._ios_p_6");
|
|
1309
|
+
// Should have conditional expression with both styles
|
|
1310
|
+
expect(output).toMatch(/isError\s*\?\s*_twStyles\._border_t_red_500/);
|
|
1911
1311
|
});
|
|
1912
1312
|
});
|