@mgcrea/react-native-tailwind 0.12.1 → 0.14.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 +45 -2031
- package/dist/babel/index.cjs +1726 -1094
- package/dist/babel/plugin/componentScope.d.ts +26 -0
- package/dist/babel/plugin/componentScope.ts +87 -0
- package/dist/babel/plugin/state.d.ts +123 -0
- package/dist/babel/plugin/state.ts +185 -0
- package/dist/babel/plugin/visitors/className.d.ts +11 -0
- package/{src/babel/plugin.test.ts → dist/babel/plugin/visitors/className.test.ts} +285 -572
- package/dist/babel/plugin/visitors/className.ts +652 -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 +116 -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 +116 -0
- package/dist/babel/plugin/visitors/tw.d.ts +16 -0
- package/dist/babel/plugin/visitors/tw.test.ts +771 -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 -963
- 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/directionalModifierProcessing.d.ts +34 -0
- package/dist/babel/utils/directionalModifierProcessing.ts +99 -0
- package/dist/babel/utils/modifierProcessing.ts +21 -0
- package/dist/babel/utils/platformModifierProcessing.ts +11 -0
- package/dist/babel/utils/styleInjection.d.ts +31 -0
- package/dist/babel/utils/styleInjection.ts +253 -7
- package/dist/babel/utils/twProcessing.d.ts +2 -0
- package/dist/babel/utils/twProcessing.ts +103 -3
- 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 +2 -2
- 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/modifiers.d.ts +32 -2
- package/dist/parser/modifiers.js +1 -1
- package/dist/parser/modifiers.test.js +1 -1
- package/dist/parser/sizing.js +1 -1
- package/dist/parser/spacing.d.ts +1 -1
- package/dist/parser/spacing.js +1 -1
- package/dist/parser/spacing.test.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 +6 -6
- package/src/babel/plugin/componentScope.ts +87 -0
- package/src/babel/plugin/state.ts +185 -0
- package/src/babel/plugin/visitors/className.test.ts +1625 -0
- package/src/babel/plugin/visitors/className.ts +652 -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 +116 -0
- package/src/babel/plugin/visitors/program.test.ts +325 -0
- package/src/babel/plugin/visitors/program.ts +116 -0
- package/src/babel/plugin/visitors/tw.test.ts +771 -0
- package/src/babel/plugin/visitors/tw.ts +148 -0
- package/src/babel/plugin.ts +28 -963
- 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/directionalModifierProcessing.ts +99 -0
- package/src/babel/utils/modifierProcessing.ts +21 -0
- package/src/babel/utils/platformModifierProcessing.ts +11 -0
- package/src/babel/utils/styleInjection.ts +253 -7
- package/src/babel/utils/twProcessing.ts +103 -3
- 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 +162 -0
- package/src/parser/borders.ts +67 -9
- package/src/parser/colors.test.ts +249 -0
- package/src/parser/colors.ts +38 -0
- package/src/parser/index.ts +4 -2
- package/src/parser/layout.test.ts +74 -0
- package/src/parser/layout.ts +94 -0
- package/src/parser/modifiers.test.ts +206 -0
- package/src/parser/modifiers.ts +62 -3
- package/src/parser/sizing.ts +11 -0
- package/src/parser/spacing.test.ts +66 -0
- package/src/parser/spacing.ts +15 -5
- package/src/parser/typography.test.ts +8 -0
- package/src/parser/typography.ts +4 -0
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { transform } from "../../../../test/helpers/babelTransform.js";
|
|
3
|
+
|
|
4
|
+
describe("program visitor - Program.exit behavior", () => {
|
|
5
|
+
describe("StyleSheet injection", () => {
|
|
6
|
+
it("should inject StyleSheet.create when className is used", () => {
|
|
7
|
+
const input = `
|
|
8
|
+
import { View } from 'react-native';
|
|
9
|
+
|
|
10
|
+
function MyComponent() {
|
|
11
|
+
return <View className="m-4 p-2 bg-blue-500" />;
|
|
12
|
+
}
|
|
13
|
+
`;
|
|
14
|
+
|
|
15
|
+
const output = transform(input, undefined, true);
|
|
16
|
+
|
|
17
|
+
// Should have StyleSheet import
|
|
18
|
+
expect(output).toContain("StyleSheet");
|
|
19
|
+
|
|
20
|
+
// Should inject StyleSheet.create
|
|
21
|
+
expect(output).toContain("StyleSheet.create");
|
|
22
|
+
expect(output).toContain("_twStyles");
|
|
23
|
+
|
|
24
|
+
// Should have the styles
|
|
25
|
+
expect(output).toMatch(/margin:\s*16/);
|
|
26
|
+
expect(output).toMatch(/padding:\s*8/);
|
|
27
|
+
expect(output).toMatch(/backgroundColor:/);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it("should not inject StyleSheet when no className is used", () => {
|
|
31
|
+
const input = `
|
|
32
|
+
import { View } from 'react-native';
|
|
33
|
+
|
|
34
|
+
function MyComponent() {
|
|
35
|
+
return <View />;
|
|
36
|
+
}
|
|
37
|
+
`;
|
|
38
|
+
|
|
39
|
+
const output = transform(input, undefined, true);
|
|
40
|
+
|
|
41
|
+
// Should not add StyleSheet import
|
|
42
|
+
expect(output).not.toContain("StyleSheet");
|
|
43
|
+
expect(output).not.toContain("_twStyles");
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it("should inject styles at top of file after imports", () => {
|
|
47
|
+
const input = `
|
|
48
|
+
import React from 'react';
|
|
49
|
+
import { View } from 'react-native';
|
|
50
|
+
|
|
51
|
+
function MyComponent() {
|
|
52
|
+
return <View className="m-4" />;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function AnotherComponent() {
|
|
56
|
+
return <View className="p-2" />;
|
|
57
|
+
}
|
|
58
|
+
`;
|
|
59
|
+
|
|
60
|
+
const output = transform(input, undefined, true);
|
|
61
|
+
|
|
62
|
+
// StyleSheet.create should come before component definitions
|
|
63
|
+
const styleSheetIndex = output.indexOf("StyleSheet.create");
|
|
64
|
+
const firstComponentIndex = output.indexOf("function MyComponent");
|
|
65
|
+
|
|
66
|
+
expect(styleSheetIndex).toBeGreaterThan(0);
|
|
67
|
+
expect(styleSheetIndex).toBeLessThan(firstComponentIndex);
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
describe("tw import removal", () => {
|
|
72
|
+
it("should remove tw import when tw tagged template is used", () => {
|
|
73
|
+
const input = `
|
|
74
|
+
import { tw } from '@mgcrea/react-native-tailwind';
|
|
75
|
+
import { View } from 'react-native';
|
|
76
|
+
|
|
77
|
+
function MyComponent() {
|
|
78
|
+
const styles = tw\`m-4 p-2\`;
|
|
79
|
+
return <View style={styles.style} />;
|
|
80
|
+
}
|
|
81
|
+
`;
|
|
82
|
+
|
|
83
|
+
const output = transform(input, undefined, true);
|
|
84
|
+
|
|
85
|
+
// Should not have tw import anymore
|
|
86
|
+
expect(output).not.toMatch(/import.*tw.*from ['"]@mgcrea\/react-native-tailwind['"]/);
|
|
87
|
+
|
|
88
|
+
// Should have StyleSheet instead
|
|
89
|
+
expect(output).toContain("StyleSheet");
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it("should remove twStyle import when twStyle call is used", () => {
|
|
93
|
+
const input = `
|
|
94
|
+
import { twStyle } from '@mgcrea/react-native-tailwind';
|
|
95
|
+
import { View } from 'react-native';
|
|
96
|
+
|
|
97
|
+
function MyComponent() {
|
|
98
|
+
const styles = twStyle('m-4 p-2');
|
|
99
|
+
return <View style={styles.style} />;
|
|
100
|
+
}
|
|
101
|
+
`;
|
|
102
|
+
|
|
103
|
+
const output = transform(input, undefined, true);
|
|
104
|
+
|
|
105
|
+
// Should not have twStyle import anymore
|
|
106
|
+
expect(output).not.toMatch(/import.*twStyle.*from ['"]@mgcrea\/react-native-tailwind['"]/);
|
|
107
|
+
|
|
108
|
+
// Should have StyleSheet instead
|
|
109
|
+
expect(output).toContain("StyleSheet");
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
describe("hook injection - color scheme", () => {
|
|
114
|
+
it("should inject useColorScheme hook when dark: modifier is used", () => {
|
|
115
|
+
const input = `
|
|
116
|
+
import { View } from 'react-native';
|
|
117
|
+
|
|
118
|
+
function MyComponent() {
|
|
119
|
+
return <View className="bg-white dark:bg-gray-900" />;
|
|
120
|
+
}
|
|
121
|
+
`;
|
|
122
|
+
|
|
123
|
+
const output = transform(input, undefined, true);
|
|
124
|
+
|
|
125
|
+
// Should import useColorScheme
|
|
126
|
+
expect(output).toContain("useColorScheme");
|
|
127
|
+
|
|
128
|
+
// Should inject hook call
|
|
129
|
+
expect(output).toContain("_twColorScheme");
|
|
130
|
+
expect(output).toContain("useColorScheme()");
|
|
131
|
+
|
|
132
|
+
// Should use in conditional
|
|
133
|
+
expect(output).toMatch(/_twColorScheme\s*===\s*['"]dark['"]/);
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
it("should inject useColorScheme hook when light: modifier is used", () => {
|
|
137
|
+
const input = `
|
|
138
|
+
import { View } from 'react-native';
|
|
139
|
+
|
|
140
|
+
function MyComponent() {
|
|
141
|
+
return <View className="bg-gray-900 light:bg-white" />;
|
|
142
|
+
}
|
|
143
|
+
`;
|
|
144
|
+
|
|
145
|
+
const output = transform(input, undefined, true);
|
|
146
|
+
|
|
147
|
+
// Should import and inject hook
|
|
148
|
+
expect(output).toContain("useColorScheme");
|
|
149
|
+
expect(output).toContain("_twColorScheme");
|
|
150
|
+
|
|
151
|
+
// Should use in conditional
|
|
152
|
+
expect(output).toMatch(/_twColorScheme\s*===\s*['"]light['"]/);
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
it("should inject hook only once for multiple color scheme modifiers", () => {
|
|
156
|
+
const input = `
|
|
157
|
+
import { View } from 'react-native';
|
|
158
|
+
|
|
159
|
+
function MyComponent() {
|
|
160
|
+
return (
|
|
161
|
+
<>
|
|
162
|
+
<View className="dark:bg-gray-900" />
|
|
163
|
+
<View className="light:bg-white" />
|
|
164
|
+
<View className="dark:text-white" />
|
|
165
|
+
</>
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
`;
|
|
169
|
+
|
|
170
|
+
const output = transform(input, undefined, true);
|
|
171
|
+
|
|
172
|
+
// Count hook injections (should be exactly 1)
|
|
173
|
+
const hookMatches = output.match(/_twColorScheme\s*=\s*useColorScheme\(\)/g) ?? [];
|
|
174
|
+
expect(hookMatches.length).toBe(1);
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
it("should use custom color scheme hook when configured", () => {
|
|
178
|
+
const input = `
|
|
179
|
+
import { View } from 'react-native';
|
|
180
|
+
|
|
181
|
+
function MyComponent() {
|
|
182
|
+
return <View className="dark:bg-gray-900" />;
|
|
183
|
+
}
|
|
184
|
+
`;
|
|
185
|
+
|
|
186
|
+
const output = transform(
|
|
187
|
+
input,
|
|
188
|
+
{
|
|
189
|
+
colorScheme: {
|
|
190
|
+
importFrom: "@react-navigation/native",
|
|
191
|
+
importName: "useTheme",
|
|
192
|
+
},
|
|
193
|
+
},
|
|
194
|
+
true,
|
|
195
|
+
);
|
|
196
|
+
|
|
197
|
+
// Should import from custom source
|
|
198
|
+
expect(output).toContain("@react-navigation/native");
|
|
199
|
+
expect(output).toContain("useTheme");
|
|
200
|
+
|
|
201
|
+
// Should use custom hook
|
|
202
|
+
expect(output).toContain("useTheme()");
|
|
203
|
+
});
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
describe("hook injection - window dimensions", () => {
|
|
207
|
+
it("should inject useWindowDimensions hook when w-screen is used", () => {
|
|
208
|
+
const input = `
|
|
209
|
+
import { View } from 'react-native';
|
|
210
|
+
|
|
211
|
+
function MyComponent() {
|
|
212
|
+
return <View className="w-screen bg-white" />;
|
|
213
|
+
}
|
|
214
|
+
`;
|
|
215
|
+
|
|
216
|
+
const output = transform(input, undefined, true);
|
|
217
|
+
|
|
218
|
+
// Should import useWindowDimensions
|
|
219
|
+
expect(output).toContain("useWindowDimensions");
|
|
220
|
+
|
|
221
|
+
// Should inject hook call
|
|
222
|
+
expect(output).toContain("_twDimensions");
|
|
223
|
+
expect(output).toContain("useWindowDimensions()");
|
|
224
|
+
|
|
225
|
+
// Should use in inline style
|
|
226
|
+
expect(output).toMatch(/width:\s*_twDimensions\.width/);
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
it("should inject useWindowDimensions hook when h-screen is used", () => {
|
|
230
|
+
const input = `
|
|
231
|
+
import { View } from 'react-native';
|
|
232
|
+
|
|
233
|
+
function MyComponent() {
|
|
234
|
+
return <View className="h-screen bg-white" />;
|
|
235
|
+
}
|
|
236
|
+
`;
|
|
237
|
+
|
|
238
|
+
const output = transform(input, undefined, true);
|
|
239
|
+
|
|
240
|
+
// Should import and inject hook
|
|
241
|
+
expect(output).toContain("useWindowDimensions");
|
|
242
|
+
expect(output).toContain("_twDimensions");
|
|
243
|
+
|
|
244
|
+
// Should use in inline style
|
|
245
|
+
expect(output).toMatch(/height:\s*_twDimensions\.height/);
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
it("should inject hook only once for multiple w-screen/h-screen uses", () => {
|
|
249
|
+
const input = `
|
|
250
|
+
import { View } from 'react-native';
|
|
251
|
+
|
|
252
|
+
function MyComponent() {
|
|
253
|
+
return (
|
|
254
|
+
<>
|
|
255
|
+
<View className="w-screen" />
|
|
256
|
+
<View className="h-screen" />
|
|
257
|
+
<View className="w-screen h-screen" />
|
|
258
|
+
</>
|
|
259
|
+
);
|
|
260
|
+
}
|
|
261
|
+
`;
|
|
262
|
+
|
|
263
|
+
const output = transform(input, undefined, true);
|
|
264
|
+
|
|
265
|
+
// Count hook injections (should be exactly 1)
|
|
266
|
+
const hookMatches = output.match(/_twDimensions\s*=\s*useWindowDimensions\(\)/g) ?? [];
|
|
267
|
+
expect(hookMatches.length).toBe(1);
|
|
268
|
+
});
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
describe("combined scenarios", () => {
|
|
272
|
+
it("should inject color scheme and platform imports together", () => {
|
|
273
|
+
const input = `
|
|
274
|
+
import { View } from 'react-native';
|
|
275
|
+
|
|
276
|
+
function MyComponent() {
|
|
277
|
+
return (
|
|
278
|
+
<View className="ios:p-4 android:p-2 dark:bg-gray-900 light:bg-white" />
|
|
279
|
+
);
|
|
280
|
+
}
|
|
281
|
+
`;
|
|
282
|
+
|
|
283
|
+
const output = transform(input, undefined, true);
|
|
284
|
+
|
|
285
|
+
// Should have all imports
|
|
286
|
+
expect(output).toContain("StyleSheet");
|
|
287
|
+
expect(output).toContain("Platform");
|
|
288
|
+
expect(output).toContain("useColorScheme");
|
|
289
|
+
|
|
290
|
+
// Should have color scheme hook
|
|
291
|
+
expect(output).toContain("_twColorScheme");
|
|
292
|
+
expect(output).toContain("useColorScheme()");
|
|
293
|
+
|
|
294
|
+
// Should have platform select
|
|
295
|
+
expect(output).toContain("Platform.select");
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
it("should inject window dimensions and color scheme hooks in separate components", () => {
|
|
299
|
+
const input = `
|
|
300
|
+
import { View } from 'react-native';
|
|
301
|
+
|
|
302
|
+
function ComponentA() {
|
|
303
|
+
return <View className="w-screen h-screen" />;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
function ComponentB() {
|
|
307
|
+
return <View className="dark:bg-gray-900 light:bg-white" />;
|
|
308
|
+
}
|
|
309
|
+
`;
|
|
310
|
+
|
|
311
|
+
const output = transform(input, undefined, true);
|
|
312
|
+
|
|
313
|
+
// Should have both hooks
|
|
314
|
+
expect(output).toContain("useColorScheme");
|
|
315
|
+
expect(output).toContain("useWindowDimensions");
|
|
316
|
+
|
|
317
|
+
// Should have both hook calls
|
|
318
|
+
expect(output).toContain("_twColorScheme");
|
|
319
|
+
expect(output).toContain("_twDimensions");
|
|
320
|
+
|
|
321
|
+
// Should have StyleSheet
|
|
322
|
+
expect(output).toContain("StyleSheet.create");
|
|
323
|
+
});
|
|
324
|
+
});
|
|
325
|
+
});
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Program visitor - entry and exit points for file processing
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { NodePath } from "@babel/core";
|
|
6
|
+
import type * as BabelTypes from "@babel/types";
|
|
7
|
+
import {
|
|
8
|
+
addColorSchemeImport,
|
|
9
|
+
addI18nManagerImport,
|
|
10
|
+
addPlatformImport,
|
|
11
|
+
addStyleSheetImport,
|
|
12
|
+
addWindowDimensionsImport,
|
|
13
|
+
injectColorSchemeHook,
|
|
14
|
+
injectI18nManagerVariable,
|
|
15
|
+
injectStylesAtTop,
|
|
16
|
+
injectWindowDimensionsHook,
|
|
17
|
+
} from "../../utils/styleInjection.js";
|
|
18
|
+
import { removeTwImports } from "../../utils/twProcessing.js";
|
|
19
|
+
import type { PluginState } from "../state.js";
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Program enter visitor - initialize state for each file
|
|
23
|
+
*/
|
|
24
|
+
export function programEnter(_path: NodePath<BabelTypes.Program>, _state: PluginState): void {
|
|
25
|
+
// Note: State initialization is already handled by the createInitialState function
|
|
26
|
+
// This is called before any other visitors and receives the initialized state
|
|
27
|
+
// The actual initialization happens in the main plugin.ts file via Object.assign
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Program exit visitor - finalize transformations
|
|
32
|
+
* Injects imports, hooks, and StyleSheet.create
|
|
33
|
+
*/
|
|
34
|
+
export function programExit(
|
|
35
|
+
path: NodePath<BabelTypes.Program>,
|
|
36
|
+
state: PluginState,
|
|
37
|
+
t: typeof BabelTypes,
|
|
38
|
+
): void {
|
|
39
|
+
// Remove tw/twStyle imports if they were used (and transformed)
|
|
40
|
+
if (state.hasTwImport) {
|
|
41
|
+
removeTwImports(path, t);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// If no classNames were found and no hooks/imports needed, skip processing
|
|
45
|
+
if (
|
|
46
|
+
!state.hasClassNames &&
|
|
47
|
+
!state.needsWindowDimensionsImport &&
|
|
48
|
+
!state.needsColorSchemeImport &&
|
|
49
|
+
!state.needsI18nManagerImport
|
|
50
|
+
) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Add StyleSheet import if not already present (and we have styles to inject)
|
|
55
|
+
if (!state.hasStyleSheetImport && state.styleRegistry.size > 0) {
|
|
56
|
+
addStyleSheetImport(path, t);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Add Platform import if platform modifiers were used and not already present
|
|
60
|
+
if (state.needsPlatformImport && !state.hasPlatformImport) {
|
|
61
|
+
addPlatformImport(path, t);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Add I18nManager import if directional modifiers were used and not already present
|
|
65
|
+
if (state.needsI18nManagerImport && !state.hasI18nManagerImport) {
|
|
66
|
+
addI18nManagerImport(path, t);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Inject I18nManager.isRTL variable at module level (not a hook, so no component scope needed)
|
|
70
|
+
if (state.needsI18nManagerImport) {
|
|
71
|
+
injectI18nManagerVariable(path, state.i18nManagerVariableName, state.i18nManagerLocalIdentifier, t);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Add color scheme hook import if color scheme modifiers were used and not already present
|
|
75
|
+
if (state.needsColorSchemeImport && !state.hasColorSchemeImport) {
|
|
76
|
+
addColorSchemeImport(path, state.colorSchemeImportSource, state.colorSchemeHookName, t);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Inject color scheme hook in function components that need it
|
|
80
|
+
if (state.needsColorSchemeImport) {
|
|
81
|
+
for (const functionPath of state.functionComponentsNeedingColorScheme) {
|
|
82
|
+
injectColorSchemeHook(
|
|
83
|
+
functionPath,
|
|
84
|
+
state.colorSchemeVariableName,
|
|
85
|
+
state.colorSchemeHookName,
|
|
86
|
+
state.colorSchemeLocalIdentifier,
|
|
87
|
+
t,
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Add useWindowDimensions import if w-screen/h-screen classes were used and not already present
|
|
93
|
+
if (state.needsWindowDimensionsImport && !state.hasWindowDimensionsImport) {
|
|
94
|
+
addWindowDimensionsImport(path, t);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Inject useWindowDimensions hook in function components that need it
|
|
98
|
+
if (state.needsWindowDimensionsImport) {
|
|
99
|
+
for (const functionPath of state.functionComponentsNeedingWindowDimensions) {
|
|
100
|
+
injectWindowDimensionsHook(
|
|
101
|
+
functionPath,
|
|
102
|
+
state.windowDimensionsVariableName,
|
|
103
|
+
"useWindowDimensions",
|
|
104
|
+
state.windowDimensionsLocalIdentifier,
|
|
105
|
+
t,
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Generate and inject StyleSheet.create at the beginning of the file (after imports)
|
|
111
|
+
// This ensures _twStyles is defined before any code that references it
|
|
112
|
+
// Only inject if we actually have styles to inject
|
|
113
|
+
if (state.styleRegistry.size > 0) {
|
|
114
|
+
injectStylesAtTop(path, state.styleRegistry, state.stylesIdentifier, t);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* tw and twStyle visitors - handles compile-time tw tagged templates and twStyle calls
|
|
3
|
+
*/
|
|
4
|
+
import type { NodePath } from "@babel/core";
|
|
5
|
+
import type * as BabelTypes from "@babel/types";
|
|
6
|
+
import type { PluginState } from "../state.js";
|
|
7
|
+
/**
|
|
8
|
+
* TaggedTemplateExpression visitor
|
|
9
|
+
* Handles tw`...` tagged template expressions
|
|
10
|
+
*/
|
|
11
|
+
export declare function taggedTemplateVisitor(path: NodePath<BabelTypes.TaggedTemplateExpression>, state: PluginState, t: typeof BabelTypes): void;
|
|
12
|
+
/**
|
|
13
|
+
* CallExpression visitor
|
|
14
|
+
* Handles twStyle('...') call expressions
|
|
15
|
+
*/
|
|
16
|
+
export declare function callExpressionVisitor(path: NodePath<BabelTypes.CallExpression>, state: PluginState, t: typeof BabelTypes): void;
|