@mgcrea/react-native-tailwind 0.6.0 → 0.7.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 (57) hide show
  1. package/README.md +437 -10
  2. package/dist/babel/config-loader.ts +1 -23
  3. package/dist/babel/index.cjs +543 -150
  4. package/dist/babel/index.d.ts +27 -2
  5. package/dist/babel/index.test.ts +268 -0
  6. package/dist/babel/index.ts +352 -44
  7. package/dist/components/Pressable.d.ts +2 -0
  8. package/dist/components/TextInput.d.ts +2 -0
  9. package/dist/config/palettes.d.ts +302 -0
  10. package/dist/config/palettes.js +1 -0
  11. package/dist/index.d.ts +3 -0
  12. package/dist/index.js +1 -1
  13. package/dist/parser/__snapshots__/colors.test.js.snap +242 -90
  14. package/dist/parser/__snapshots__/transforms.test.js.snap +58 -0
  15. package/dist/parser/colors.js +1 -1
  16. package/dist/parser/colors.test.js +1 -1
  17. package/dist/parser/layout.js +1 -1
  18. package/dist/parser/layout.test.js +1 -1
  19. package/dist/parser/typography.js +1 -1
  20. package/dist/parser/typography.test.js +1 -1
  21. package/dist/runtime.cjs +2 -0
  22. package/dist/runtime.cjs.map +7 -0
  23. package/dist/runtime.d.ts +139 -0
  24. package/dist/runtime.js +2 -0
  25. package/dist/runtime.js.map +7 -0
  26. package/dist/runtime.test.js +1 -0
  27. package/dist/stubs/tw.d.ts +60 -0
  28. package/dist/stubs/tw.js +1 -0
  29. package/dist/utils/flattenColors.d.ts +16 -0
  30. package/dist/utils/flattenColors.js +1 -0
  31. package/dist/utils/flattenColors.test.js +1 -0
  32. package/dist/utils/modifiers.d.ts +29 -0
  33. package/dist/utils/modifiers.js +1 -0
  34. package/dist/utils/modifiers.test.js +1 -0
  35. package/dist/utils/styleKey.test.js +1 -0
  36. package/package.json +15 -3
  37. package/src/babel/config-loader.ts +1 -23
  38. package/src/babel/index.test.ts +268 -0
  39. package/src/babel/index.ts +352 -44
  40. package/src/components/Pressable.tsx +1 -0
  41. package/src/components/TextInput.tsx +1 -0
  42. package/src/config/palettes.ts +304 -0
  43. package/src/index.ts +5 -0
  44. package/src/parser/colors.test.ts +47 -31
  45. package/src/parser/colors.ts +5 -110
  46. package/src/parser/layout.test.ts +35 -0
  47. package/src/parser/layout.ts +26 -0
  48. package/src/parser/typography.test.ts +10 -0
  49. package/src/parser/typography.ts +8 -0
  50. package/src/runtime.test.ts +325 -0
  51. package/src/runtime.ts +280 -0
  52. package/src/stubs/tw.ts +80 -0
  53. package/src/utils/flattenColors.test.ts +361 -0
  54. package/src/utils/flattenColors.ts +32 -0
  55. package/src/utils/modifiers.test.ts +286 -0
  56. package/src/utils/modifiers.ts +63 -0
  57. package/src/utils/styleKey.test.ts +168 -0
@@ -258,108 +258,314 @@ function parseBorderRadius(cls) {
258
258
  return null;
259
259
  }
260
260
 
261
+ // src/config/palettes.ts
262
+ var TAILWIND_PALETTES = {
263
+ red: {
264
+ "50": "#fef2f2",
265
+ "100": "#ffe2e2",
266
+ "200": "#ffc9c9",
267
+ "300": "#ffa2a2",
268
+ "400": "#ff6467",
269
+ "500": "#fb2c36",
270
+ "600": "#e7000b",
271
+ "700": "#c10007",
272
+ "800": "#9f0712",
273
+ "900": "#82181a",
274
+ "950": "#460809"
275
+ },
276
+ orange: {
277
+ "50": "#fff7ed",
278
+ "100": "#ffedd4",
279
+ "200": "#ffd6a7",
280
+ "300": "#ffb86a",
281
+ "400": "#ff8904",
282
+ "500": "#ff6900",
283
+ "600": "#f54900",
284
+ "700": "#ca3500",
285
+ "800": "#9f2d00",
286
+ "900": "#7e2a0c",
287
+ "950": "#441306"
288
+ },
289
+ amber: {
290
+ "50": "#fffbeb",
291
+ "100": "#fef3c6",
292
+ "200": "#fee685",
293
+ "300": "#ffd230",
294
+ "400": "#ffb900",
295
+ "500": "#fe9a00",
296
+ "600": "#e17100",
297
+ "700": "#bb4d00",
298
+ "800": "#973c00",
299
+ "900": "#7b3306",
300
+ "950": "#461901"
301
+ },
302
+ yellow: {
303
+ "50": "#fefce8",
304
+ "100": "#fef9c2",
305
+ "200": "#fff085",
306
+ "300": "#ffdf20",
307
+ "400": "#fdc700",
308
+ "500": "#f0b100",
309
+ "600": "#d08700",
310
+ "700": "#a65f00",
311
+ "800": "#894b00",
312
+ "900": "#733e0a",
313
+ "950": "#432004"
314
+ },
315
+ lime: {
316
+ "50": "#f7fee7",
317
+ "100": "#ecfcca",
318
+ "200": "#d8f999",
319
+ "300": "#bbf451",
320
+ "400": "#9ae600",
321
+ "500": "#7ccf00",
322
+ "600": "#5ea500",
323
+ "700": "#497d00",
324
+ "800": "#3c6300",
325
+ "900": "#35530e",
326
+ "950": "#192e03"
327
+ },
328
+ green: {
329
+ "50": "#f0fdf4",
330
+ "100": "#dcfce7",
331
+ "200": "#b9f8cf",
332
+ "300": "#7bf1a8",
333
+ "400": "#05df72",
334
+ "500": "#00c950",
335
+ "600": "#00a63e",
336
+ "700": "#008236",
337
+ "800": "#016630",
338
+ "900": "#0d542b",
339
+ "950": "#032e15"
340
+ },
341
+ emerald: {
342
+ "50": "#ecfdf5",
343
+ "100": "#d0fae5",
344
+ "200": "#a4f4cf",
345
+ "300": "#5ee9b5",
346
+ "400": "#00d492",
347
+ "500": "#00bc7d",
348
+ "600": "#009966",
349
+ "700": "#007a55",
350
+ "800": "#006045",
351
+ "900": "#004f3b",
352
+ "950": "#002c22"
353
+ },
354
+ teal: {
355
+ "50": "#f0fdfa",
356
+ "100": "#cbfbf1",
357
+ "200": "#96f7e4",
358
+ "300": "#46ecd5",
359
+ "400": "#00d5be",
360
+ "500": "#00bba7",
361
+ "600": "#009689",
362
+ "700": "#00786f",
363
+ "800": "#005f5a",
364
+ "900": "#0b4f4a",
365
+ "950": "#022f2e"
366
+ },
367
+ cyan: {
368
+ "50": "#ecfeff",
369
+ "100": "#cefafe",
370
+ "200": "#a2f4fd",
371
+ "300": "#53eafd",
372
+ "400": "#00d3f2",
373
+ "500": "#00b8db",
374
+ "600": "#0092b8",
375
+ "700": "#007595",
376
+ "800": "#005f78",
377
+ "900": "#104e64",
378
+ "950": "#053345"
379
+ },
380
+ sky: {
381
+ "50": "#f0f9ff",
382
+ "100": "#dff2fe",
383
+ "200": "#b8e6fe",
384
+ "300": "#74d4ff",
385
+ "400": "#00bcff",
386
+ "500": "#00a6f4",
387
+ "600": "#0084d1",
388
+ "700": "#0069a8",
389
+ "800": "#00598a",
390
+ "900": "#024a70",
391
+ "950": "#052f4a"
392
+ },
393
+ blue: {
394
+ "50": "#eff6ff",
395
+ "100": "#dbeafe",
396
+ "200": "#bedbff",
397
+ "300": "#8ec5ff",
398
+ "400": "#51a2ff",
399
+ "500": "#2b7fff",
400
+ "600": "#155dfc",
401
+ "700": "#1447e6",
402
+ "800": "#193cb8",
403
+ "900": "#1c398e",
404
+ "950": "#162456"
405
+ },
406
+ indigo: {
407
+ "50": "#eef2ff",
408
+ "100": "#e0e7ff",
409
+ "200": "#c6d2ff",
410
+ "300": "#a3b3ff",
411
+ "400": "#7c86ff",
412
+ "500": "#615fff",
413
+ "600": "#4f39f6",
414
+ "700": "#432dd7",
415
+ "800": "#372aac",
416
+ "900": "#312c85",
417
+ "950": "#1e1a4d"
418
+ },
419
+ violet: {
420
+ "50": "#f5f3ff",
421
+ "100": "#ede9fe",
422
+ "200": "#ddd6ff",
423
+ "300": "#c4b4ff",
424
+ "400": "#a684ff",
425
+ "500": "#8e51ff",
426
+ "600": "#7f22fe",
427
+ "700": "#7008e7",
428
+ "800": "#5d0ec0",
429
+ "900": "#4d179a",
430
+ "950": "#2f0d68"
431
+ },
432
+ purple: {
433
+ "50": "#faf5ff",
434
+ "100": "#f3e8ff",
435
+ "200": "#e9d4ff",
436
+ "300": "#dab2ff",
437
+ "400": "#c27aff",
438
+ "500": "#ad46ff",
439
+ "600": "#9810fa",
440
+ "700": "#8200db",
441
+ "800": "#6e11b0",
442
+ "900": "#59168b",
443
+ "950": "#3c0366"
444
+ },
445
+ fuchsia: {
446
+ "50": "#fdf4ff",
447
+ "100": "#fae8ff",
448
+ "200": "#f6cfff",
449
+ "300": "#f4a8ff",
450
+ "400": "#ed6aff",
451
+ "500": "#e12afb",
452
+ "600": "#c800de",
453
+ "700": "#a800b7",
454
+ "800": "#8a0194",
455
+ "900": "#721378",
456
+ "950": "#4b004f"
457
+ },
458
+ pink: {
459
+ "50": "#fdf2f8",
460
+ "100": "#fce7f3",
461
+ "200": "#fccee8",
462
+ "300": "#fda5d5",
463
+ "400": "#fb64b6",
464
+ "500": "#f6339a",
465
+ "600": "#e60076",
466
+ "700": "#c6005c",
467
+ "800": "#a3004c",
468
+ "900": "#861043",
469
+ "950": "#510424"
470
+ },
471
+ rose: {
472
+ "50": "#fff1f2",
473
+ "100": "#ffe4e6",
474
+ "200": "#ffccd3",
475
+ "300": "#ffa1ad",
476
+ "400": "#ff637e",
477
+ "500": "#ff2056",
478
+ "600": "#ec003f",
479
+ "700": "#c70036",
480
+ "800": "#a50036",
481
+ "900": "#8b0836",
482
+ "950": "#4d0218"
483
+ },
484
+ slate: {
485
+ "50": "#f8fafc",
486
+ "100": "#f1f5f9",
487
+ "200": "#e2e8f0",
488
+ "300": "#cad5e2",
489
+ "400": "#90a1b9",
490
+ "500": "#62748e",
491
+ "600": "#45556c",
492
+ "700": "#314158",
493
+ "800": "#1d293d",
494
+ "900": "#0f172b",
495
+ "950": "#020618"
496
+ },
497
+ gray: {
498
+ "50": "#f9fafb",
499
+ "100": "#f3f4f6",
500
+ "200": "#e5e7eb",
501
+ "300": "#d1d5dc",
502
+ "400": "#99a1af",
503
+ "500": "#6a7282",
504
+ "600": "#4a5565",
505
+ "700": "#364153",
506
+ "800": "#1e2939",
507
+ "900": "#101828",
508
+ "950": "#030712"
509
+ },
510
+ zinc: {
511
+ "50": "#fafafa",
512
+ "100": "#f4f4f5",
513
+ "200": "#e4e4e7",
514
+ "300": "#d4d4d8",
515
+ "400": "#9f9fa9",
516
+ "500": "#71717b",
517
+ "600": "#52525c",
518
+ "700": "#3f3f46",
519
+ "800": "#27272a",
520
+ "900": "#18181b",
521
+ "950": "#09090b"
522
+ },
523
+ neutral: {
524
+ "50": "#fafafa",
525
+ "100": "#f5f5f5",
526
+ "200": "#e5e5e5",
527
+ "300": "#d4d4d4",
528
+ "400": "#a1a1a1",
529
+ "500": "#737373",
530
+ "600": "#525252",
531
+ "700": "#404040",
532
+ "800": "#262626",
533
+ "900": "#171717",
534
+ "950": "#0a0a0a"
535
+ },
536
+ stone: {
537
+ "50": "#fafaf9",
538
+ "100": "#f5f5f4",
539
+ "200": "#e7e5e4",
540
+ "300": "#d6d3d1",
541
+ "400": "#a6a09b",
542
+ "500": "#79716b",
543
+ "600": "#57534d",
544
+ "700": "#44403b",
545
+ "800": "#292524",
546
+ "900": "#1c1917",
547
+ "950": "#0c0a09"
548
+ }
549
+ };
550
+
551
+ // src/utils/flattenColors.ts
552
+ function flattenColors(colors, prefix = "") {
553
+ const result = {};
554
+ for (const [key, value] of Object.entries(colors)) {
555
+ const newKey = prefix ? `${prefix}-${key}` : key;
556
+ if (typeof value === "string") {
557
+ result[newKey] = value;
558
+ } else if (typeof value === "object" && value !== null) {
559
+ Object.assign(result, flattenColors(value, newKey));
560
+ }
561
+ }
562
+ return result;
563
+ }
564
+
261
565
  // src/parser/colors.ts
262
566
  var COLORS = {
263
- // Gray
264
- "gray-50": "#F9FAFB",
265
- "gray-100": "#F3F4F6",
266
- "gray-200": "#E5E7EB",
267
- "gray-300": "#D1D5DB",
268
- "gray-400": "#9CA3AF",
269
- "gray-500": "#6B7280",
270
- "gray-600": "#4B5563",
271
- "gray-700": "#374151",
272
- "gray-800": "#1F2937",
273
- "gray-900": "#111827",
274
- // Red
275
- "red-50": "#FEF2F2",
276
- "red-100": "#FEE2E2",
277
- "red-200": "#FECACA",
278
- "red-300": "#FCA5A5",
279
- "red-400": "#F87171",
280
- "red-500": "#EF4444",
281
- "red-600": "#DC2626",
282
- "red-700": "#B91C1C",
283
- "red-800": "#991B1B",
284
- "red-900": "#7F1D1D",
285
- // Blue
286
- "blue-50": "#EFF6FF",
287
- "blue-100": "#DBEAFE",
288
- "blue-200": "#BFDBFE",
289
- "blue-300": "#93C5FD",
290
- "blue-400": "#60A5FA",
291
- "blue-500": "#3B82F6",
292
- "blue-600": "#2563EB",
293
- "blue-700": "#1D4ED8",
294
- "blue-800": "#1E40AF",
295
- "blue-900": "#1E3A8A",
296
- // Green
297
- "green-50": "#F0FDF4",
298
- "green-100": "#DCFCE7",
299
- "green-200": "#BBF7D0",
300
- "green-300": "#86EFAC",
301
- "green-400": "#4ADE80",
302
- "green-500": "#22C55E",
303
- "green-600": "#16A34A",
304
- "green-700": "#15803D",
305
- "green-800": "#166534",
306
- "green-900": "#14532D",
307
- // Yellow
308
- "yellow-50": "#FEFCE8",
309
- "yellow-100": "#FEF9C3",
310
- "yellow-200": "#FEF08A",
311
- "yellow-300": "#FDE047",
312
- "yellow-400": "#FACC15",
313
- "yellow-500": "#EAB308",
314
- "yellow-600": "#CA8A04",
315
- "yellow-700": "#A16207",
316
- "yellow-800": "#854D0E",
317
- "yellow-900": "#713F12",
318
- // Purple
319
- "purple-50": "#FAF5FF",
320
- "purple-100": "#F3E8FF",
321
- "purple-200": "#E9D5FF",
322
- "purple-300": "#D8B4FE",
323
- "purple-400": "#C084FC",
324
- "purple-500": "#A855F7",
325
- "purple-600": "#9333EA",
326
- "purple-700": "#7E22CE",
327
- "purple-800": "#6B21A8",
328
- "purple-900": "#581C87",
329
- // Pink
330
- "pink-50": "#FDF2F8",
331
- "pink-100": "#FCE7F3",
332
- "pink-200": "#FBCFE8",
333
- "pink-300": "#F9A8D4",
334
- "pink-400": "#F472B6",
335
- "pink-500": "#EC4899",
336
- "pink-600": "#DB2777",
337
- "pink-700": "#BE185D",
338
- "pink-800": "#9D174D",
339
- "pink-900": "#831843",
340
- // Orange
341
- "orange-50": "#FFF7ED",
342
- "orange-100": "#FFEDD5",
343
- "orange-200": "#FED7AA",
344
- "orange-300": "#FDBA74",
345
- "orange-400": "#FB923C",
346
- "orange-500": "#F97316",
347
- "orange-600": "#EA580C",
348
- "orange-700": "#C2410C",
349
- "orange-800": "#9A3412",
350
- "orange-900": "#7C2D12",
351
- // Indigo
352
- "indigo-50": "#EEF2FF",
353
- "indigo-100": "#E0E7FF",
354
- "indigo-200": "#C7D2FE",
355
- "indigo-300": "#A5B4FC",
356
- "indigo-400": "#818CF8",
357
- "indigo-500": "#6366F1",
358
- "indigo-600": "#4F46E5",
359
- "indigo-700": "#4338CA",
360
- "indigo-800": "#3730A3",
361
- "indigo-900": "#312E81",
362
- // Basic colors
567
+ ...flattenColors(TAILWIND_PALETTES),
568
+ // Add basic colors
363
569
  white: "#FFFFFF",
364
570
  black: "#000000",
365
571
  transparent: "transparent"
@@ -561,6 +767,29 @@ var OVERFLOW_MAP = {
561
767
  "overflow-visible": { overflow: "visible" },
562
768
  "overflow-scroll": { overflow: "scroll" }
563
769
  };
770
+ var OPACITY_MAP = {
771
+ "opacity-0": { opacity: 0 },
772
+ "opacity-5": { opacity: 0.05 },
773
+ "opacity-10": { opacity: 0.1 },
774
+ "opacity-15": { opacity: 0.15 },
775
+ "opacity-20": { opacity: 0.2 },
776
+ "opacity-25": { opacity: 0.25 },
777
+ "opacity-30": { opacity: 0.3 },
778
+ "opacity-35": { opacity: 0.35 },
779
+ "opacity-40": { opacity: 0.4 },
780
+ "opacity-45": { opacity: 0.45 },
781
+ "opacity-50": { opacity: 0.5 },
782
+ "opacity-55": { opacity: 0.55 },
783
+ "opacity-60": { opacity: 0.6 },
784
+ "opacity-65": { opacity: 0.65 },
785
+ "opacity-70": { opacity: 0.7 },
786
+ "opacity-75": { opacity: 0.75 },
787
+ "opacity-80": { opacity: 0.8 },
788
+ "opacity-85": { opacity: 0.85 },
789
+ "opacity-90": { opacity: 0.9 },
790
+ "opacity-95": { opacity: 0.95 },
791
+ "opacity-100": { opacity: 1 }
792
+ };
564
793
  var Z_INDEX_SCALE = {
565
794
  0: 0,
566
795
  10: 10,
@@ -691,7 +920,7 @@ function parseLayout(cls) {
691
920
  return { top: insetValue, right: insetValue, bottom: insetValue, left: insetValue };
692
921
  }
693
922
  }
694
- 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;
923
+ 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] ?? OPACITY_MAP[cls] ?? null;
695
924
  }
696
925
 
697
926
  // src/parser/shadows.ts
@@ -1353,6 +1582,11 @@ var FONT_SIZES = {
1353
1582
  "8xl": 96,
1354
1583
  "9xl": 128
1355
1584
  };
1585
+ var FONT_FAMILY_MAP = {
1586
+ "font-sans": { fontFamily: "System" },
1587
+ "font-serif": { fontFamily: "serif" },
1588
+ "font-mono": { fontFamily: "Courier" }
1589
+ };
1356
1590
  var FONT_WEIGHT_MAP = {
1357
1591
  "font-thin": { fontWeight: "100" },
1358
1592
  "font-extralight": { fontWeight: "200" },
@@ -1450,7 +1684,7 @@ function parseTypography(cls) {
1450
1684
  return { lineHeight: arbitraryValue };
1451
1685
  }
1452
1686
  }
1453
- 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;
1687
+ return FONT_FAMILY_MAP[cls] ?? 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;
1454
1688
  }
1455
1689
 
1456
1690
  // src/parser/modifiers.ts
@@ -1575,18 +1809,6 @@ function loadTailwindConfig(configPath) {
1575
1809
  return null;
1576
1810
  }
1577
1811
  }
1578
- function flattenColors(colors, prefix = "") {
1579
- const result = {};
1580
- for (const [key, value] of Object.entries(colors)) {
1581
- const newKey = prefix ? `${prefix}-${key}` : key;
1582
- if (typeof value === "string") {
1583
- result[newKey] = value;
1584
- } else if (typeof value === "object" && value !== null) {
1585
- Object.assign(result, flattenColors(value, newKey));
1586
- }
1587
- }
1588
- return result;
1589
- }
1590
1812
  function extractCustomColors(filename) {
1591
1813
  const projectDir = path.dirname(filename);
1592
1814
  const configPath = findTailwindConfig(projectDir);
@@ -1607,32 +1829,40 @@ function extractCustomColors(filename) {
1607
1829
  }
1608
1830
 
1609
1831
  // src/babel/index.ts
1610
- var STYLES_IDENTIFIER = "_twStyles";
1611
- var SUPPORTED_CLASS_ATTRIBUTES = [
1832
+ var DEFAULT_STYLES_IDENTIFIER = "_twStyles";
1833
+ var DEFAULT_CLASS_ATTRIBUTES = [
1612
1834
  "className",
1613
- "containerClassName",
1614
1835
  "contentContainerClassName",
1615
1836
  "columnWrapperClassName",
1616
1837
  "ListHeaderComponentClassName",
1617
1838
  "ListFooterComponentClassName"
1618
1839
  ];
1619
- function getTargetStyleProp(attributeName) {
1620
- if (attributeName === "containerClassName") {
1621
- return "containerStyle";
1622
- }
1623
- if (attributeName === "contentContainerClassName") {
1624
- return "contentContainerStyle";
1625
- }
1626
- if (attributeName === "columnWrapperClassName") {
1627
- return "columnWrapperStyle";
1840
+ function buildAttributeMatchers(attributes) {
1841
+ const exactMatches = /* @__PURE__ */ new Set();
1842
+ const patterns = [];
1843
+ for (const attr of attributes) {
1844
+ if (attr.includes("*")) {
1845
+ const regexPattern = "^" + attr.replace(/\*/g, ".*") + "$";
1846
+ patterns.push(new RegExp(regexPattern));
1847
+ } else {
1848
+ exactMatches.add(attr);
1849
+ }
1628
1850
  }
1629
- if (attributeName === "ListHeaderComponentClassName") {
1630
- return "ListHeaderComponentStyle";
1851
+ return { exactMatches, patterns };
1852
+ }
1853
+ function isAttributeSupported(attributeName, exactMatches, patterns) {
1854
+ if (exactMatches.has(attributeName)) {
1855
+ return true;
1631
1856
  }
1632
- if (attributeName === "ListFooterComponentClassName") {
1633
- return "ListFooterComponentStyle";
1857
+ for (const pattern of patterns) {
1858
+ if (pattern.test(attributeName)) {
1859
+ return true;
1860
+ }
1634
1861
  }
1635
- return "style";
1862
+ return false;
1863
+ }
1864
+ function getTargetStyleProp(attributeName) {
1865
+ return attributeName.endsWith("ClassName") ? attributeName.replace("ClassName", "Style") : "style";
1636
1866
  }
1637
1867
  function getComponentModifierSupport(jsxElement, t) {
1638
1868
  if (!t.isJSXOpeningElement(jsxElement)) {
@@ -1686,7 +1916,7 @@ function processTemplateLiteral(node, state, t) {
1686
1916
  const styleKey = generateStyleKey2(cls);
1687
1917
  state.styleRegistry.set(styleKey, styleObject);
1688
1918
  staticParts.push(cls);
1689
- parts.push(t.memberExpression(t.identifier(STYLES_IDENTIFIER), t.identifier(styleKey)));
1919
+ parts.push(t.memberExpression(t.identifier(state.stylesIdentifier), t.identifier(styleKey)));
1690
1920
  }
1691
1921
  }
1692
1922
  if (i < node.expressions.length) {
@@ -1741,7 +1971,7 @@ function processStringOrExpression(node, state, t) {
1741
1971
  const styleObject = parseClassName2(className, state.customColors);
1742
1972
  const styleKey = generateStyleKey2(className);
1743
1973
  state.styleRegistry.set(styleKey, styleObject);
1744
- return t.memberExpression(t.identifier(STYLES_IDENTIFIER), t.identifier(styleKey));
1974
+ return t.memberExpression(t.identifier(state.stylesIdentifier), t.identifier(styleKey));
1745
1975
  }
1746
1976
  if (t.isConditionalExpression(node)) {
1747
1977
  const result = processConditionalExpression(node, state, t);
@@ -1765,7 +1995,7 @@ function processStaticClassNameWithModifiers(className, state, t) {
1765
1995
  const baseStyleObject = parseClassName2(baseClassName, state.customColors);
1766
1996
  const baseStyleKey = generateStyleKey2(baseClassName);
1767
1997
  state.styleRegistry.set(baseStyleKey, baseStyleObject);
1768
- baseStyleExpression = t.memberExpression(t.identifier(STYLES_IDENTIFIER), t.identifier(baseStyleKey));
1998
+ baseStyleExpression = t.memberExpression(t.identifier(state.stylesIdentifier), t.identifier(baseStyleKey));
1769
1999
  }
1770
2000
  const modifiersByType = /* @__PURE__ */ new Map();
1771
2001
  for (const mod of modifierClasses) {
@@ -1790,7 +2020,7 @@ function processStaticClassNameWithModifiers(className, state, t) {
1790
2020
  const conditionalExpression = t.logicalExpression(
1791
2021
  "&&",
1792
2022
  t.identifier(stateProperty),
1793
- t.memberExpression(t.identifier(STYLES_IDENTIFIER), t.identifier(modifierStyleKey))
2023
+ t.memberExpression(t.identifier(state.stylesIdentifier), t.identifier(modifierStyleKey))
1794
2024
  );
1795
2025
  styleArrayElements.push(conditionalExpression);
1796
2026
  }
@@ -1828,9 +2058,53 @@ function createStyleFunction(styleExpression, modifierTypes, t) {
1828
2058
  const param = t.objectPattern(paramProperties);
1829
2059
  return t.arrowFunctionExpression([param], styleExpression);
1830
2060
  }
1831
- function reactNativeTailwindBabelPlugin({
1832
- types: t
1833
- }) {
2061
+ function processTwCall(className, path2, state, t) {
2062
+ const { baseClasses, modifierClasses } = splitModifierClasses(className);
2063
+ const objectProperties = [];
2064
+ if (baseClasses.length > 0) {
2065
+ const baseClassName = baseClasses.join(" ");
2066
+ const baseStyleObject = parseClassName2(baseClassName, state.customColors);
2067
+ const baseStyleKey = generateStyleKey2(baseClassName);
2068
+ state.styleRegistry.set(baseStyleKey, baseStyleObject);
2069
+ objectProperties.push(
2070
+ t.objectProperty(
2071
+ t.identifier("style"),
2072
+ t.memberExpression(t.identifier(state.stylesIdentifier), t.identifier(baseStyleKey))
2073
+ )
2074
+ );
2075
+ } else {
2076
+ objectProperties.push(t.objectProperty(t.identifier("style"), t.objectExpression([])));
2077
+ }
2078
+ const modifiersByType = /* @__PURE__ */ new Map();
2079
+ for (const mod of modifierClasses) {
2080
+ if (!modifiersByType.has(mod.modifier)) {
2081
+ modifiersByType.set(mod.modifier, []);
2082
+ }
2083
+ const modGroup = modifiersByType.get(mod.modifier);
2084
+ if (modGroup) {
2085
+ modGroup.push(mod);
2086
+ }
2087
+ }
2088
+ for (const [modifierType, modifiers] of modifiersByType) {
2089
+ const modifierClassNames = modifiers.map((m) => m.baseClass).join(" ");
2090
+ const modifierStyleObject = parseClassName2(modifierClassNames, state.customColors);
2091
+ const modifierStyleKey = generateStyleKey2(`${modifierType}_${modifierClassNames}`);
2092
+ state.styleRegistry.set(modifierStyleKey, modifierStyleObject);
2093
+ const propertyName = `${modifierType}Style`;
2094
+ objectProperties.push(
2095
+ t.objectProperty(
2096
+ t.identifier(propertyName),
2097
+ t.memberExpression(t.identifier(state.stylesIdentifier), t.identifier(modifierStyleKey))
2098
+ )
2099
+ );
2100
+ }
2101
+ const twStyleObject = t.objectExpression(objectProperties);
2102
+ path2.replaceWith(twStyleObject);
2103
+ }
2104
+ function reactNativeTailwindBabelPlugin({ types: t }, options) {
2105
+ const attributes = options?.attributes ?? [...DEFAULT_CLASS_ATTRIBUTES];
2106
+ const { exactMatches, patterns } = buildAttributeMatchers(attributes);
2107
+ const stylesIdentifier = options?.stylesIdentifier ?? DEFAULT_STYLES_IDENTIFIER;
1834
2108
  return {
1835
2109
  name: "react-native-tailwind",
1836
2110
  visitor: {
@@ -1839,19 +2113,27 @@ function reactNativeTailwindBabelPlugin({
1839
2113
  state.styleRegistry = /* @__PURE__ */ new Map();
1840
2114
  state.hasClassNames = false;
1841
2115
  state.hasStyleSheetImport = false;
2116
+ state.supportedAttributes = exactMatches;
2117
+ state.attributePatterns = patterns;
2118
+ state.stylesIdentifier = stylesIdentifier;
2119
+ state.twImportNames = /* @__PURE__ */ new Set();
2120
+ state.hasTwImport = false;
1842
2121
  state.customColors = extractCustomColors(state.file.opts.filename ?? "");
1843
2122
  },
1844
2123
  exit(path2, state) {
2124
+ if (state.hasTwImport) {
2125
+ removeTwImports(path2, t);
2126
+ }
1845
2127
  if (!state.hasClassNames || state.styleRegistry.size === 0) {
1846
2128
  return;
1847
2129
  }
1848
2130
  if (!state.hasStyleSheetImport) {
1849
2131
  addStyleSheetImport(path2, t);
1850
2132
  }
1851
- injectStyles(path2, state.styleRegistry, t);
2133
+ injectStylesAtTop(path2, state.styleRegistry, state.stylesIdentifier, t);
1852
2134
  }
1853
2135
  },
1854
- // Check if StyleSheet is already imported
2136
+ // Check if StyleSheet is already imported and track tw/twStyle imports
1855
2137
  ImportDeclaration(path2, state) {
1856
2138
  const node = path2.node;
1857
2139
  if (node.source.value === "react-native") {
@@ -1869,11 +2151,91 @@ function reactNativeTailwindBabelPlugin({
1869
2151
  state.hasStyleSheetImport = true;
1870
2152
  }
1871
2153
  }
2154
+ if (node.source.value === "@mgcrea/react-native-tailwind") {
2155
+ const specifiers = node.specifiers;
2156
+ specifiers.forEach((spec) => {
2157
+ if (t.isImportSpecifier(spec) && t.isIdentifier(spec.imported)) {
2158
+ const importedName = spec.imported.name;
2159
+ if (importedName === "tw" || importedName === "twStyle") {
2160
+ const localName = spec.local.name;
2161
+ state.twImportNames.add(localName);
2162
+ state.hasTwImport = true;
2163
+ }
2164
+ }
2165
+ });
2166
+ }
2167
+ },
2168
+ // Handle tw`...` tagged template expressions
2169
+ TaggedTemplateExpression(path2, state) {
2170
+ const node = path2.node;
2171
+ if (!t.isIdentifier(node.tag)) {
2172
+ return;
2173
+ }
2174
+ const tagName = node.tag.name;
2175
+ if (!state.twImportNames.has(tagName)) {
2176
+ return;
2177
+ }
2178
+ const quasi = node.quasi;
2179
+ if (!t.isTemplateLiteral(quasi)) {
2180
+ return;
2181
+ }
2182
+ if (quasi.expressions.length > 0) {
2183
+ if (process.env.NODE_ENV !== "production") {
2184
+ console.warn(
2185
+ `[react-native-tailwind] Dynamic tw\`...\` with interpolations is not supported at ${state.file.opts.filename ?? "unknown"}. Use style prop for dynamic values.`
2186
+ );
2187
+ }
2188
+ return;
2189
+ }
2190
+ const className = quasi.quasis[0]?.value.cooked?.trim() ?? "";
2191
+ if (!className) {
2192
+ path2.replaceWith(
2193
+ t.objectExpression([t.objectProperty(t.identifier("style"), t.objectExpression([]))])
2194
+ );
2195
+ return;
2196
+ }
2197
+ state.hasClassNames = true;
2198
+ processTwCall(className, path2, state, t);
2199
+ },
2200
+ // Handle twStyle('...') call expressions
2201
+ CallExpression(path2, state) {
2202
+ const node = path2.node;
2203
+ if (!t.isIdentifier(node.callee)) {
2204
+ return;
2205
+ }
2206
+ const calleeName = node.callee.name;
2207
+ if (!state.twImportNames.has(calleeName)) {
2208
+ return;
2209
+ }
2210
+ if (node.arguments.length !== 1) {
2211
+ if (process.env.NODE_ENV !== "production") {
2212
+ console.warn(
2213
+ `[react-native-tailwind] twStyle() expects exactly one argument at ${state.file.opts.filename ?? "unknown"}`
2214
+ );
2215
+ }
2216
+ return;
2217
+ }
2218
+ const arg = node.arguments[0];
2219
+ if (!t.isStringLiteral(arg)) {
2220
+ if (process.env.NODE_ENV !== "production") {
2221
+ console.warn(
2222
+ `[react-native-tailwind] twStyle() only supports static string literals at ${state.file.opts.filename ?? "unknown"}. Use style prop for dynamic values.`
2223
+ );
2224
+ }
2225
+ return;
2226
+ }
2227
+ const className = arg.value.trim();
2228
+ if (!className) {
2229
+ path2.replaceWith(t.identifier("undefined"));
2230
+ return;
2231
+ }
2232
+ state.hasClassNames = true;
2233
+ processTwCall(className, path2, state, t);
1872
2234
  },
1873
2235
  JSXAttribute(path2, state) {
1874
2236
  const node = path2.node;
1875
2237
  const attributeName = node.name.name;
1876
- if (!SUPPORTED_CLASS_ATTRIBUTES.includes(attributeName)) {
2238
+ if (!isAttributeSupported(attributeName, state.supportedAttributes, state.attributePatterns)) {
1877
2239
  return;
1878
2240
  }
1879
2241
  const value = node.value;
@@ -1956,9 +2318,9 @@ function reactNativeTailwindBabelPlugin({
1956
2318
  (attr) => t.isJSXAttribute(attr) && attr.name.name === targetStyleProp
1957
2319
  );
1958
2320
  if (styleAttribute) {
1959
- mergeStyleAttribute(path2, styleAttribute, styleKey, t);
2321
+ mergeStyleAttribute(path2, styleAttribute, styleKey, state.stylesIdentifier, t);
1960
2322
  } else {
1961
- replaceWithStyleAttribute(path2, styleKey, targetStyleProp, t);
2323
+ replaceWithStyleAttribute(path2, styleKey, targetStyleProp, state.stylesIdentifier, t);
1962
2324
  }
1963
2325
  return;
1964
2326
  }
@@ -2007,17 +2369,39 @@ function addStyleSheetImport(path2, t) {
2007
2369
  );
2008
2370
  path2.unshiftContainer("body", importDeclaration);
2009
2371
  }
2010
- function replaceWithStyleAttribute(classNamePath, styleKey, targetStyleProp, t) {
2372
+ function removeTwImports(path2, t) {
2373
+ path2.traverse({
2374
+ ImportDeclaration(importPath) {
2375
+ const node = importPath.node;
2376
+ if (node.source.value !== "@mgcrea/react-native-tailwind") {
2377
+ return;
2378
+ }
2379
+ const remainingSpecifiers = node.specifiers.filter((spec) => {
2380
+ if (t.isImportSpecifier(spec) && t.isIdentifier(spec.imported)) {
2381
+ const importedName = spec.imported.name;
2382
+ return importedName !== "tw" && importedName !== "twStyle";
2383
+ }
2384
+ return true;
2385
+ });
2386
+ if (remainingSpecifiers.length === 0) {
2387
+ importPath.remove();
2388
+ } else if (remainingSpecifiers.length < node.specifiers.length) {
2389
+ node.specifiers = remainingSpecifiers;
2390
+ }
2391
+ }
2392
+ });
2393
+ }
2394
+ function replaceWithStyleAttribute(classNamePath, styleKey, targetStyleProp, stylesIdentifier, t) {
2011
2395
  const styleAttribute = t.jsxAttribute(
2012
2396
  t.jsxIdentifier(targetStyleProp),
2013
- t.jsxExpressionContainer(t.memberExpression(t.identifier(STYLES_IDENTIFIER), t.identifier(styleKey)))
2397
+ t.jsxExpressionContainer(t.memberExpression(t.identifier(stylesIdentifier), t.identifier(styleKey)))
2014
2398
  );
2015
2399
  classNamePath.replaceWith(styleAttribute);
2016
2400
  }
2017
- function mergeStyleAttribute(classNamePath, styleAttribute, styleKey, t) {
2401
+ function mergeStyleAttribute(classNamePath, styleAttribute, styleKey, stylesIdentifier, t) {
2018
2402
  const existingStyle = styleAttribute.value.expression;
2019
2403
  const styleArray = t.arrayExpression([
2020
- t.memberExpression(t.identifier(STYLES_IDENTIFIER), t.identifier(styleKey)),
2404
+ t.memberExpression(t.identifier(stylesIdentifier), t.identifier(styleKey)),
2021
2405
  existingStyle
2022
2406
  ]);
2023
2407
  styleAttribute.value = t.jsxExpressionContainer(styleArray);
@@ -2066,7 +2450,7 @@ function mergeStyleFunctionAttribute(classNamePath, styleAttribute, styleFunctio
2066
2450
  }
2067
2451
  classNamePath.remove();
2068
2452
  }
2069
- function injectStyles(path2, styleRegistry, t) {
2453
+ function injectStylesAtTop(path2, styleRegistry, stylesIdentifier, t) {
2070
2454
  const styleProperties = [];
2071
2455
  for (const [key, styleObject] of styleRegistry) {
2072
2456
  const properties = Object.entries(styleObject).map(([styleProp, styleValue]) => {
@@ -2084,13 +2468,22 @@ function injectStyles(path2, styleRegistry, t) {
2084
2468
  }
2085
2469
  const styleSheet = t.variableDeclaration("const", [
2086
2470
  t.variableDeclarator(
2087
- t.identifier(STYLES_IDENTIFIER),
2471
+ t.identifier(stylesIdentifier),
2088
2472
  t.callExpression(t.memberExpression(t.identifier("StyleSheet"), t.identifier("create")), [
2089
2473
  t.objectExpression(styleProperties)
2090
2474
  ])
2091
2475
  )
2092
2476
  ]);
2093
- path2.pushContainer("body", styleSheet);
2477
+ const body = path2.node.body;
2478
+ let insertIndex = 0;
2479
+ for (let i = 0; i < body.length; i++) {
2480
+ if (t.isImportDeclaration(body[i])) {
2481
+ insertIndex = i + 1;
2482
+ } else {
2483
+ break;
2484
+ }
2485
+ }
2486
+ body.splice(insertIndex, 0, styleSheet);
2094
2487
  }
2095
2488
  function parseClassName2(className, customColors) {
2096
2489
  return parseClassName(className, customColors);