@mgcrea/react-native-tailwind 0.13.0 → 0.15.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.
Files changed (73) hide show
  1. package/README.md +33 -30
  2. package/dist/babel/config-loader.d.ts +10 -0
  3. package/dist/babel/config-loader.test.ts +75 -21
  4. package/dist/babel/config-loader.ts +100 -2
  5. package/dist/babel/index.cjs +439 -46
  6. package/dist/babel/plugin/state.d.ts +4 -0
  7. package/dist/babel/plugin/state.ts +8 -0
  8. package/dist/babel/plugin/visitors/className.test.ts +313 -0
  9. package/dist/babel/plugin/visitors/className.ts +36 -8
  10. package/dist/babel/plugin/visitors/imports.ts +16 -1
  11. package/dist/babel/plugin/visitors/program.ts +19 -2
  12. package/dist/babel/plugin/visitors/tw.test.ts +151 -0
  13. package/dist/babel/utils/directionalModifierProcessing.d.ts +34 -0
  14. package/dist/babel/utils/directionalModifierProcessing.ts +99 -0
  15. package/dist/babel/utils/styleInjection.d.ts +16 -0
  16. package/dist/babel/utils/styleInjection.ts +138 -7
  17. package/dist/babel/utils/twProcessing.d.ts +2 -0
  18. package/dist/babel/utils/twProcessing.ts +92 -3
  19. package/dist/parser/borders.js +1 -1
  20. package/dist/parser/borders.test.js +1 -1
  21. package/dist/parser/index.d.ts +3 -2
  22. package/dist/parser/index.js +1 -1
  23. package/dist/parser/layout.d.ts +3 -1
  24. package/dist/parser/layout.js +1 -1
  25. package/dist/parser/layout.test.js +1 -1
  26. package/dist/parser/modifiers.d.ts +32 -2
  27. package/dist/parser/modifiers.js +1 -1
  28. package/dist/parser/modifiers.test.js +1 -1
  29. package/dist/parser/sizing.d.ts +3 -1
  30. package/dist/parser/sizing.js +1 -1
  31. package/dist/parser/sizing.test.js +1 -1
  32. package/dist/parser/spacing.d.ts +4 -2
  33. package/dist/parser/spacing.js +1 -1
  34. package/dist/parser/spacing.test.js +1 -1
  35. package/dist/parser/transforms.d.ts +3 -1
  36. package/dist/parser/transforms.js +1 -1
  37. package/dist/parser/transforms.test.js +1 -1
  38. package/dist/parser/typography.test.js +1 -1
  39. package/dist/runtime.cjs +1 -1
  40. package/dist/runtime.cjs.map +3 -3
  41. package/dist/runtime.d.ts +2 -0
  42. package/dist/runtime.js +1 -1
  43. package/dist/runtime.js.map +3 -3
  44. package/dist/runtime.test.js +1 -1
  45. package/package.json +6 -6
  46. package/src/babel/config-loader.test.ts +75 -21
  47. package/src/babel/config-loader.ts +100 -2
  48. package/src/babel/plugin/state.ts +8 -0
  49. package/src/babel/plugin/visitors/className.test.ts +313 -0
  50. package/src/babel/plugin/visitors/className.ts +36 -8
  51. package/src/babel/plugin/visitors/imports.ts +16 -1
  52. package/src/babel/plugin/visitors/program.ts +19 -2
  53. package/src/babel/plugin/visitors/tw.test.ts +151 -0
  54. package/src/babel/utils/directionalModifierProcessing.ts +99 -0
  55. package/src/babel/utils/styleInjection.ts +138 -7
  56. package/src/babel/utils/twProcessing.ts +92 -3
  57. package/src/parser/borders.test.ts +104 -0
  58. package/src/parser/borders.ts +50 -7
  59. package/src/parser/index.ts +8 -5
  60. package/src/parser/layout.test.ts +168 -0
  61. package/src/parser/layout.ts +107 -8
  62. package/src/parser/modifiers.test.ts +206 -0
  63. package/src/parser/modifiers.ts +62 -3
  64. package/src/parser/sizing.test.ts +56 -0
  65. package/src/parser/sizing.ts +20 -15
  66. package/src/parser/spacing.test.ts +123 -0
  67. package/src/parser/spacing.ts +30 -15
  68. package/src/parser/transforms.test.ts +57 -0
  69. package/src/parser/transforms.ts +7 -3
  70. package/src/parser/typography.test.ts +8 -0
  71. package/src/parser/typography.ts +4 -0
  72. package/src/runtime.test.ts +149 -0
  73. package/src/runtime.ts +53 -1
@@ -209,6 +209,155 @@ describe("runtime", () => {
209
209
  backgroundColor: "#007AFF",
210
210
  });
211
211
  });
212
+
213
+ it("should set custom fontFamily", () => {
214
+ setConfig({
215
+ theme: {
216
+ extend: {
217
+ fontFamily: {
218
+ display: "Inter",
219
+ body: ["Roboto", "sans-serif"], // Array format - takes first value
220
+ },
221
+ },
222
+ },
223
+ });
224
+
225
+ const theme = getCustomTheme();
226
+ expect(theme.fontFamily).toEqual({
227
+ display: "Inter",
228
+ body: "Roboto",
229
+ });
230
+ });
231
+
232
+ it("should set custom fontSize", () => {
233
+ setConfig({
234
+ theme: {
235
+ extend: {
236
+ fontSize: {
237
+ tiny: 10,
238
+ small: "12px",
239
+ medium: 16,
240
+ large: "24",
241
+ },
242
+ },
243
+ },
244
+ });
245
+
246
+ const theme = getCustomTheme();
247
+ expect(theme.fontSize).toEqual({
248
+ tiny: 10,
249
+ small: 12,
250
+ medium: 16,
251
+ large: 24,
252
+ });
253
+ });
254
+
255
+ it("should set custom spacing", () => {
256
+ setConfig({
257
+ theme: {
258
+ extend: {
259
+ spacing: {
260
+ xs: 4,
261
+ sm: "8px",
262
+ md: 16,
263
+ lg: "2rem", // 2rem = 32px
264
+ },
265
+ },
266
+ },
267
+ });
268
+
269
+ const theme = getCustomTheme();
270
+ expect(theme.spacing).toEqual({
271
+ xs: 4,
272
+ sm: 8,
273
+ md: 16,
274
+ lg: 32,
275
+ });
276
+ });
277
+
278
+ it("should use custom fontSize in parsing", () => {
279
+ setConfig({
280
+ theme: {
281
+ extend: {
282
+ fontSize: {
283
+ tiny: 10,
284
+ },
285
+ },
286
+ },
287
+ });
288
+
289
+ const result = tw`text-tiny`;
290
+ expect(result?.style).toEqual({
291
+ fontSize: 10,
292
+ });
293
+ });
294
+
295
+ it("should use custom spacing in parsing", () => {
296
+ setConfig({
297
+ theme: {
298
+ extend: {
299
+ spacing: {
300
+ xs: 4,
301
+ },
302
+ },
303
+ },
304
+ });
305
+
306
+ const result = tw`m-xs p-xs`;
307
+ expect(result?.style).toEqual({
308
+ margin: 4,
309
+ padding: 4,
310
+ });
311
+ });
312
+
313
+ it("should reset fontSize and spacing when config is cleared", () => {
314
+ setConfig({
315
+ theme: {
316
+ extend: {
317
+ fontSize: { tiny: 10 },
318
+ spacing: { xs: 4 },
319
+ },
320
+ },
321
+ });
322
+
323
+ let theme = getCustomTheme();
324
+ expect(theme.fontSize).toEqual({ tiny: 10 });
325
+ expect(theme.spacing).toEqual({ xs: 4 });
326
+
327
+ setConfig({});
328
+
329
+ theme = getCustomTheme();
330
+ expect(theme.fontSize).toEqual({});
331
+ expect(theme.spacing).toEqual({});
332
+ });
333
+
334
+ it("should handle all theme extensions together", () => {
335
+ setConfig({
336
+ theme: {
337
+ extend: {
338
+ colors: { primary: "#007AFF" },
339
+ fontFamily: { display: "Inter" },
340
+ fontSize: { tiny: 10 },
341
+ spacing: { xs: 4 },
342
+ },
343
+ },
344
+ });
345
+
346
+ const theme = getCustomTheme();
347
+ expect(theme.colors).toEqual({ primary: "#007AFF" });
348
+ expect(theme.fontFamily).toEqual({ display: "Inter" });
349
+ expect(theme.fontSize).toEqual({ tiny: 10 });
350
+ expect(theme.spacing).toEqual({ xs: 4 });
351
+
352
+ // Test that parsing uses all of them
353
+ const result = tw`bg-primary font-display text-tiny m-xs`;
354
+ expect(result?.style).toEqual({
355
+ backgroundColor: "#007AFF",
356
+ fontFamily: "Inter",
357
+ fontSize: 10,
358
+ margin: 4,
359
+ });
360
+ });
212
361
  });
213
362
 
214
363
  describe("cache", () => {
package/src/runtime.ts CHANGED
@@ -12,12 +12,19 @@ export type RuntimeConfig = {
12
12
  extend?: {
13
13
  colors?: Record<string, string | Record<string, string>>;
14
14
  fontFamily?: Record<string, string | string[]>;
15
+ fontSize?: Record<string, string | number>;
16
+ spacing?: Record<string, string | number>;
15
17
  };
16
18
  };
17
19
  };
18
20
 
19
21
  // Global custom theme configuration
20
- const globalCustomTheme: CustomTheme = { colors: {}, fontFamily: {} };
22
+ const globalCustomTheme: CustomTheme = {
23
+ colors: {},
24
+ fontFamily: {},
25
+ fontSize: {},
26
+ spacing: {},
27
+ };
21
28
 
22
29
  // Simple memoization cache
23
30
  const styleCache = new Map<string, TwStyle>();
@@ -72,6 +79,51 @@ export function setConfig(config: RuntimeConfig): void {
72
79
  globalCustomTheme.fontFamily = {};
73
80
  }
74
81
 
82
+ // Extract custom fontSize
83
+ if (config.theme?.extend?.fontSize) {
84
+ const fontSizeResult: Record<string, number> = {};
85
+ for (const [key, value] of Object.entries(config.theme.extend.fontSize)) {
86
+ if (typeof value === "number") {
87
+ fontSizeResult[key] = value;
88
+ } else if (typeof value === "string") {
89
+ // Parse string values like "18px" or "18" to number
90
+ const parsed = parseFloat(value.replace(/px$/, ""));
91
+ if (!isNaN(parsed)) {
92
+ fontSizeResult[key] = parsed;
93
+ }
94
+ }
95
+ }
96
+ globalCustomTheme.fontSize = fontSizeResult;
97
+ } else {
98
+ globalCustomTheme.fontSize = {};
99
+ }
100
+
101
+ // Extract custom spacing
102
+ if (config.theme?.extend?.spacing) {
103
+ const spacingResult: Record<string, number> = {};
104
+ for (const [key, value] of Object.entries(config.theme.extend.spacing)) {
105
+ if (typeof value === "number") {
106
+ spacingResult[key] = value;
107
+ } else if (typeof value === "string") {
108
+ // Parse string values: "18rem" -> 288, "16px" -> 16, "16" -> 16
109
+ let parsed: number;
110
+ if (value.endsWith("rem")) {
111
+ // Convert rem to px (1rem = 16px)
112
+ parsed = parseFloat(value.replace(/rem$/, "")) * 16;
113
+ } else {
114
+ // Parse px or unitless values
115
+ parsed = parseFloat(value.replace(/px$/, ""));
116
+ }
117
+ if (!isNaN(parsed)) {
118
+ spacingResult[key] = parsed;
119
+ }
120
+ }
121
+ }
122
+ globalCustomTheme.spacing = spacingResult;
123
+ } else {
124
+ globalCustomTheme.spacing = {};
125
+ }
126
+
75
127
  // Clear cache when config changes
76
128
  styleCache.clear();
77
129
  }