@mgcrea/react-native-tailwind 0.5.1 → 0.6.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 +108 -0
- package/dist/babel/index.cjs +362 -8
- package/dist/parser/__snapshots__/aspectRatio.test.js.snap +9 -0
- package/dist/parser/__snapshots__/borders.test.js.snap +23 -0
- package/dist/parser/__snapshots__/colors.test.js.snap +99 -0
- package/dist/parser/__snapshots__/shadows.test.js.snap +76 -0
- package/dist/parser/__snapshots__/sizing.test.js.snap +61 -0
- package/dist/parser/__snapshots__/spacing.test.js.snap +40 -0
- package/dist/parser/__snapshots__/typography.test.js.snap +30 -0
- 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/transforms.d.ts +13 -0
- package/dist/parser/transforms.js +1 -0
- package/dist/parser/transforms.test.js +1 -0
- package/dist/parser/typography.test.js +1 -1
- package/dist/react-native.d.ts +1 -1
- package/dist/types.d.ts +32 -2
- package/package.json +1 -1
- package/src/parser/colors.test.ts +10 -0
- package/src/parser/colors.ts +14 -0
- package/src/parser/index.ts +3 -0
- package/src/parser/layout.test.ts +92 -0
- package/src/parser/layout.ts +122 -16
- package/src/parser/transforms.test.ts +318 -0
- package/src/parser/transforms.ts +406 -0
- package/src/parser/typography.test.ts +2 -0
- package/src/react-native.d.ts +1 -1
- package/src/types.ts +22 -1
package/README.md
CHANGED
|
@@ -858,6 +858,108 @@ Use `aspect-[width/height]` for custom ratios:
|
|
|
858
858
|
|
|
859
859
|
> **Note:** The aspect ratio is calculated as `width / height`. When combined with `w-full`, the height will be automatically calculated to maintain the ratio.
|
|
860
860
|
|
|
861
|
+
### Transforms
|
|
862
|
+
|
|
863
|
+
Apply 2D and 3D transformations to views with React Native's transform API. All transforms compile to optimized transform arrays at build time:
|
|
864
|
+
|
|
865
|
+
**Scale:**
|
|
866
|
+
|
|
867
|
+
- `scale-{value}` — Scale uniformly (both X and Y)
|
|
868
|
+
- `scale-x-{value}`, `scale-y-{value}` — Scale on specific axis
|
|
869
|
+
- **Values:** `0`, `50`, `75`, `90`, `95`, `100`, `105`, `110`, `125`, `150`, `200`
|
|
870
|
+
- **Arbitrary:** `scale-[1.23]`, `scale-x-[0.5]`, `scale-y-[2.5]`
|
|
871
|
+
|
|
872
|
+
**Rotate:**
|
|
873
|
+
|
|
874
|
+
- `rotate-{degrees}`, `-rotate-{degrees}` — Rotate in 2D
|
|
875
|
+
- `rotate-x-{degrees}`, `rotate-y-{degrees}`, `rotate-z-{degrees}` — Rotate on specific axis
|
|
876
|
+
- **Values:** `0`, `1`, `2`, `3`, `6`, `12`, `45`, `90`, `180`
|
|
877
|
+
- **Arbitrary:** `rotate-[37deg]`, `-rotate-[15deg]`, `rotate-x-[30deg]`
|
|
878
|
+
|
|
879
|
+
**Translate:**
|
|
880
|
+
|
|
881
|
+
- `translate-x-{spacing}`, `translate-y-{spacing}` — Move on specific axis
|
|
882
|
+
- `-translate-x-{spacing}`, `-translate-y-{spacing}` — Negative translation
|
|
883
|
+
- **Values:** Uses spacing scale (same as `m-*`, `p-*`)
|
|
884
|
+
- **Arbitrary:** `translate-x-[50px]`, `translate-y-[100px]`, `translate-x-[50%]`
|
|
885
|
+
|
|
886
|
+
**Skew:**
|
|
887
|
+
|
|
888
|
+
- `skew-x-{degrees}`, `skew-y-{degrees}` — Skew on specific axis
|
|
889
|
+
- `-skew-x-{degrees}`, `-skew-y-{degrees}` — Negative skew
|
|
890
|
+
- **Values:** `0`, `1`, `2`, `3`, `6`, `12`
|
|
891
|
+
- **Arbitrary:** `skew-x-[15deg]`, `-skew-y-[8deg]`
|
|
892
|
+
|
|
893
|
+
**Perspective:**
|
|
894
|
+
|
|
895
|
+
- `perspective-{value}` — Apply perspective transformation
|
|
896
|
+
- **Values:** `0`, `100`, `200`, `300`, `400`, `500`, `600`, `700`, `800`, `900`, `1000`
|
|
897
|
+
- **Arbitrary:** `perspective-[1500]`, `perspective-[2000]`
|
|
898
|
+
|
|
899
|
+
**Examples:**
|
|
900
|
+
|
|
901
|
+
```tsx
|
|
902
|
+
// Scale
|
|
903
|
+
<View className="scale-110 p-4">
|
|
904
|
+
{/* 110% scale (1.1x larger) */}
|
|
905
|
+
<Text>Scaled content</Text>
|
|
906
|
+
</View>
|
|
907
|
+
|
|
908
|
+
// Rotate
|
|
909
|
+
<View className="rotate-45 w-16 h-16 bg-blue-500" />
|
|
910
|
+
|
|
911
|
+
// Translate
|
|
912
|
+
<View className="translate-x-4 translate-y-2 bg-red-500 p-4">
|
|
913
|
+
{/* Moved 16px right, 8px down */}
|
|
914
|
+
</View>
|
|
915
|
+
|
|
916
|
+
// Arbitrary values
|
|
917
|
+
<View className="scale-[1.23] w-16 h-16 bg-green-500" />
|
|
918
|
+
<View className="rotate-[37deg] w-16 h-16 bg-purple-500" />
|
|
919
|
+
<View className="translate-x-[50px] bg-orange-500 p-4" />
|
|
920
|
+
|
|
921
|
+
// Negative values
|
|
922
|
+
<View className="-rotate-45 w-16 h-16 bg-pink-500" />
|
|
923
|
+
<View className="-translate-x-4 -translate-y-2 bg-indigo-500 p-4" />
|
|
924
|
+
|
|
925
|
+
// 3D rotation
|
|
926
|
+
<View className="rotate-x-45 w-16 h-16 bg-yellow-500" />
|
|
927
|
+
<View className="rotate-y-30 w-16 h-16 bg-teal-500" />
|
|
928
|
+
|
|
929
|
+
// Skew
|
|
930
|
+
<View className="skew-x-6 w-16 h-16 bg-cyan-500" />
|
|
931
|
+
|
|
932
|
+
// Perspective
|
|
933
|
+
<View className="perspective-500">
|
|
934
|
+
<View className="rotate-x-45 w-16 h-16 bg-blue-500" />
|
|
935
|
+
</View>
|
|
936
|
+
```
|
|
937
|
+
|
|
938
|
+
**Multiple Transforms Limitation:**
|
|
939
|
+
|
|
940
|
+
Due to the current architecture, multiple transform classes on the same element will overwrite each other. For example:
|
|
941
|
+
|
|
942
|
+
```tsx
|
|
943
|
+
// ❌ Only rotate-45 will apply (overwrites scale-110)
|
|
944
|
+
<View className="scale-110 rotate-45 w-16 h-16 bg-blue-500" />
|
|
945
|
+
|
|
946
|
+
// ✅ Workaround: Use nested Views for multiple transforms
|
|
947
|
+
<View className="scale-110">
|
|
948
|
+
<View className="rotate-45">
|
|
949
|
+
<View className="w-16 h-16 bg-blue-500" />
|
|
950
|
+
</View>
|
|
951
|
+
</View>
|
|
952
|
+
```
|
|
953
|
+
|
|
954
|
+
This limitation exists because the current parser architecture uses `Object.assign()` which overwrites the `transform` property when multiple transform classes are present. This will be addressed in a future update by modifying the Babel plugin to detect multiple transform classes and generate style arrays.
|
|
955
|
+
|
|
956
|
+
**What's Not Supported:**
|
|
957
|
+
|
|
958
|
+
- `transform-origin` — Not available in React Native (transforms always use center as origin)
|
|
959
|
+
- Multiple transforms on one element — Use nested Views (see workaround above)
|
|
960
|
+
|
|
961
|
+
> **Note:** All transform parsing happens at compile-time with zero runtime overhead. Each transform compiles to a React Native transform array: `transform: [{ scale: 1.1 }]`, `transform: [{ rotate: '45deg' }]`, etc.
|
|
962
|
+
|
|
861
963
|
### Sizing
|
|
862
964
|
|
|
863
965
|
- `w-{size}`, `h-{size}` — Width/height
|
|
@@ -889,6 +991,12 @@ Use arbitrary values for custom sizes, spacing, and borders not in the preset sc
|
|
|
889
991
|
- **Sizing:** `w-[...]`, `h-[...]`, `min-w-[...]`, `min-h-[...]`, `max-w-[...]`, `max-h-[...]` (px and %)
|
|
890
992
|
- **Border width:** `border-[...]`, `border-t-[...]`, `border-r-[...]`, `border-b-[...]`, `border-l-[...]` (px only)
|
|
891
993
|
- **Border radius:** `rounded-[...]`, `rounded-t-[...]`, `rounded-tl-[...]`, etc. (px only)
|
|
994
|
+
- **Transforms:**
|
|
995
|
+
- **Scale:** `scale-[...]`, `scale-x-[...]`, `scale-y-[...]` (number only, e.g., `[1.23]`)
|
|
996
|
+
- **Rotate:** `rotate-[...]`, `rotate-x-[...]`, `rotate-y-[...]`, `rotate-z-[...]` (deg only, e.g., `[37deg]`)
|
|
997
|
+
- **Translate:** `translate-x-[...]`, `translate-y-[...]` (px or %, e.g., `[50px]` or `[50%]`)
|
|
998
|
+
- **Skew:** `skew-x-[...]`, `skew-y-[...]` (deg only, e.g., `[15deg]`)
|
|
999
|
+
- **Perspective:** `perspective-[...]` (number only, e.g., `[1500]`)
|
|
892
1000
|
|
|
893
1001
|
**Formats:**
|
|
894
1002
|
|
package/dist/babel/index.cjs
CHANGED
|
@@ -429,6 +429,9 @@ function parseColor(cls, customColors) {
|
|
|
429
429
|
};
|
|
430
430
|
if (cls.startsWith("bg-")) {
|
|
431
431
|
const colorKey = cls.substring(3);
|
|
432
|
+
if (colorKey.startsWith("[") && !colorKey.startsWith("[#")) {
|
|
433
|
+
return null;
|
|
434
|
+
}
|
|
432
435
|
const color = parseColorWithOpacity(colorKey);
|
|
433
436
|
if (color) {
|
|
434
437
|
return { backgroundColor: color };
|
|
@@ -436,6 +439,9 @@ function parseColor(cls, customColors) {
|
|
|
436
439
|
}
|
|
437
440
|
if (cls.startsWith("text-")) {
|
|
438
441
|
const colorKey = cls.substring(5);
|
|
442
|
+
if (colorKey.startsWith("[") && !colorKey.startsWith("[#")) {
|
|
443
|
+
return null;
|
|
444
|
+
}
|
|
439
445
|
const color = parseColorWithOpacity(colorKey);
|
|
440
446
|
if (color) {
|
|
441
447
|
return { color };
|
|
@@ -443,6 +449,9 @@ function parseColor(cls, customColors) {
|
|
|
443
449
|
}
|
|
444
450
|
if (cls.startsWith("border-") && !cls.match(/^border-[0-9]/)) {
|
|
445
451
|
const colorKey = cls.substring(7);
|
|
452
|
+
if (colorKey.startsWith("[") && !colorKey.startsWith("[#")) {
|
|
453
|
+
return null;
|
|
454
|
+
}
|
|
446
455
|
const color = parseColorWithOpacity(colorKey);
|
|
447
456
|
if (color) {
|
|
448
457
|
return { borderColor: color };
|
|
@@ -452,6 +461,40 @@ function parseColor(cls, customColors) {
|
|
|
452
461
|
}
|
|
453
462
|
|
|
454
463
|
// src/parser/layout.ts
|
|
464
|
+
function parseArbitraryInset(value) {
|
|
465
|
+
const pxMatch = value.match(/^\[(-?\d+)(?:px)?\]$/);
|
|
466
|
+
if (pxMatch) {
|
|
467
|
+
return parseInt(pxMatch[1], 10);
|
|
468
|
+
}
|
|
469
|
+
const percentMatch = value.match(/^\[(-?\d+(?:\.\d+)?)%\]$/);
|
|
470
|
+
if (percentMatch) {
|
|
471
|
+
return `${percentMatch[1]}%`;
|
|
472
|
+
}
|
|
473
|
+
if (value.startsWith("[") && value.endsWith("]")) {
|
|
474
|
+
if (process.env.NODE_ENV !== "production") {
|
|
475
|
+
console.warn(
|
|
476
|
+
`[react-native-tailwind] Unsupported arbitrary inset unit: ${value}. Only px and % are supported.`
|
|
477
|
+
);
|
|
478
|
+
}
|
|
479
|
+
return null;
|
|
480
|
+
}
|
|
481
|
+
return null;
|
|
482
|
+
}
|
|
483
|
+
function parseArbitraryZIndex(value) {
|
|
484
|
+
const zMatch = value.match(/^\[(-?\d+)\]$/);
|
|
485
|
+
if (zMatch) {
|
|
486
|
+
return parseInt(zMatch[1], 10);
|
|
487
|
+
}
|
|
488
|
+
if (value.startsWith("[") && value.endsWith("]")) {
|
|
489
|
+
if (process.env.NODE_ENV !== "production") {
|
|
490
|
+
console.warn(
|
|
491
|
+
`[react-native-tailwind] Invalid arbitrary z-index: ${value}. Only integers are supported.`
|
|
492
|
+
);
|
|
493
|
+
}
|
|
494
|
+
return null;
|
|
495
|
+
}
|
|
496
|
+
return null;
|
|
497
|
+
}
|
|
455
498
|
var DISPLAY_MAP = {
|
|
456
499
|
flex: { display: "flex" },
|
|
457
500
|
hidden: { display: "none" }
|
|
@@ -550,6 +593,10 @@ var INSET_SCALE = {
|
|
|
550
593
|
function parseLayout(cls) {
|
|
551
594
|
if (cls.startsWith("z-")) {
|
|
552
595
|
const zKey = cls.substring(2);
|
|
596
|
+
const arbitraryZ = parseArbitraryZIndex(zKey);
|
|
597
|
+
if (arbitraryZ !== null) {
|
|
598
|
+
return { zIndex: arbitraryZ };
|
|
599
|
+
}
|
|
553
600
|
const zValue = Z_INDEX_SCALE[zKey];
|
|
554
601
|
if (zValue !== void 0) {
|
|
555
602
|
return { zIndex: zValue };
|
|
@@ -560,6 +607,10 @@ function parseLayout(cls) {
|
|
|
560
607
|
if (topKey === "auto") {
|
|
561
608
|
return {};
|
|
562
609
|
}
|
|
610
|
+
const arbitraryTop = parseArbitraryInset(topKey);
|
|
611
|
+
if (arbitraryTop !== null) {
|
|
612
|
+
return { top: arbitraryTop };
|
|
613
|
+
}
|
|
563
614
|
const topValue = INSET_SCALE[topKey];
|
|
564
615
|
if (topValue !== void 0) {
|
|
565
616
|
return { top: topValue };
|
|
@@ -570,6 +621,10 @@ function parseLayout(cls) {
|
|
|
570
621
|
if (rightKey === "auto") {
|
|
571
622
|
return {};
|
|
572
623
|
}
|
|
624
|
+
const arbitraryRight = parseArbitraryInset(rightKey);
|
|
625
|
+
if (arbitraryRight !== null) {
|
|
626
|
+
return { right: arbitraryRight };
|
|
627
|
+
}
|
|
573
628
|
const rightValue = INSET_SCALE[rightKey];
|
|
574
629
|
if (rightValue !== void 0) {
|
|
575
630
|
return { right: rightValue };
|
|
@@ -580,6 +635,10 @@ function parseLayout(cls) {
|
|
|
580
635
|
if (bottomKey === "auto") {
|
|
581
636
|
return {};
|
|
582
637
|
}
|
|
638
|
+
const arbitraryBottom = parseArbitraryInset(bottomKey);
|
|
639
|
+
if (arbitraryBottom !== null) {
|
|
640
|
+
return { bottom: arbitraryBottom };
|
|
641
|
+
}
|
|
583
642
|
const bottomValue = INSET_SCALE[bottomKey];
|
|
584
643
|
if (bottomValue !== void 0) {
|
|
585
644
|
return { bottom: bottomValue };
|
|
@@ -590,20 +649,21 @@ function parseLayout(cls) {
|
|
|
590
649
|
if (leftKey === "auto") {
|
|
591
650
|
return {};
|
|
592
651
|
}
|
|
652
|
+
const arbitraryLeft = parseArbitraryInset(leftKey);
|
|
653
|
+
if (arbitraryLeft !== null) {
|
|
654
|
+
return { left: arbitraryLeft };
|
|
655
|
+
}
|
|
593
656
|
const leftValue = INSET_SCALE[leftKey];
|
|
594
657
|
if (leftValue !== void 0) {
|
|
595
658
|
return { left: leftValue };
|
|
596
659
|
}
|
|
597
660
|
}
|
|
598
|
-
if (cls.startsWith("inset-")) {
|
|
599
|
-
const insetKey = cls.substring(6);
|
|
600
|
-
const insetValue = INSET_SCALE[insetKey];
|
|
601
|
-
if (insetValue !== void 0) {
|
|
602
|
-
return { top: insetValue, right: insetValue, bottom: insetValue, left: insetValue };
|
|
603
|
-
}
|
|
604
|
-
}
|
|
605
661
|
if (cls.startsWith("inset-x-")) {
|
|
606
662
|
const insetKey = cls.substring(8);
|
|
663
|
+
const arbitraryInset = parseArbitraryInset(insetKey);
|
|
664
|
+
if (arbitraryInset !== null) {
|
|
665
|
+
return { left: arbitraryInset, right: arbitraryInset };
|
|
666
|
+
}
|
|
607
667
|
const insetValue = INSET_SCALE[insetKey];
|
|
608
668
|
if (insetValue !== void 0) {
|
|
609
669
|
return { left: insetValue, right: insetValue };
|
|
@@ -611,11 +671,26 @@ function parseLayout(cls) {
|
|
|
611
671
|
}
|
|
612
672
|
if (cls.startsWith("inset-y-")) {
|
|
613
673
|
const insetKey = cls.substring(8);
|
|
674
|
+
const arbitraryInset = parseArbitraryInset(insetKey);
|
|
675
|
+
if (arbitraryInset !== null) {
|
|
676
|
+
return { top: arbitraryInset, bottom: arbitraryInset };
|
|
677
|
+
}
|
|
614
678
|
const insetValue = INSET_SCALE[insetKey];
|
|
615
679
|
if (insetValue !== void 0) {
|
|
616
680
|
return { top: insetValue, bottom: insetValue };
|
|
617
681
|
}
|
|
618
682
|
}
|
|
683
|
+
if (cls.startsWith("inset-")) {
|
|
684
|
+
const insetKey = cls.substring(6);
|
|
685
|
+
const arbitraryInset = parseArbitraryInset(insetKey);
|
|
686
|
+
if (arbitraryInset !== null) {
|
|
687
|
+
return { top: arbitraryInset, right: arbitraryInset, bottom: arbitraryInset, left: arbitraryInset };
|
|
688
|
+
}
|
|
689
|
+
const insetValue = INSET_SCALE[insetKey];
|
|
690
|
+
if (insetValue !== void 0) {
|
|
691
|
+
return { top: insetValue, right: insetValue, bottom: insetValue, left: insetValue };
|
|
692
|
+
}
|
|
693
|
+
}
|
|
619
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;
|
|
620
695
|
}
|
|
621
696
|
|
|
@@ -984,6 +1059,284 @@ function getPaddingStyle(dir, value) {
|
|
|
984
1059
|
}
|
|
985
1060
|
}
|
|
986
1061
|
|
|
1062
|
+
// src/parser/transforms.ts
|
|
1063
|
+
var SCALE_MAP = {
|
|
1064
|
+
0: 0,
|
|
1065
|
+
50: 0.5,
|
|
1066
|
+
75: 0.75,
|
|
1067
|
+
90: 0.9,
|
|
1068
|
+
95: 0.95,
|
|
1069
|
+
100: 1,
|
|
1070
|
+
105: 1.05,
|
|
1071
|
+
110: 1.1,
|
|
1072
|
+
125: 1.25,
|
|
1073
|
+
150: 1.5,
|
|
1074
|
+
200: 2
|
|
1075
|
+
};
|
|
1076
|
+
var ROTATE_MAP = {
|
|
1077
|
+
0: 0,
|
|
1078
|
+
1: 1,
|
|
1079
|
+
2: 2,
|
|
1080
|
+
3: 3,
|
|
1081
|
+
6: 6,
|
|
1082
|
+
12: 12,
|
|
1083
|
+
45: 45,
|
|
1084
|
+
90: 90,
|
|
1085
|
+
180: 180
|
|
1086
|
+
};
|
|
1087
|
+
var SKEW_MAP = {
|
|
1088
|
+
0: 0,
|
|
1089
|
+
1: 1,
|
|
1090
|
+
2: 2,
|
|
1091
|
+
3: 3,
|
|
1092
|
+
6: 6,
|
|
1093
|
+
12: 12
|
|
1094
|
+
};
|
|
1095
|
+
var PERSPECTIVE_SCALE = {
|
|
1096
|
+
0: 0,
|
|
1097
|
+
100: 100,
|
|
1098
|
+
200: 200,
|
|
1099
|
+
300: 300,
|
|
1100
|
+
400: 400,
|
|
1101
|
+
500: 500,
|
|
1102
|
+
600: 600,
|
|
1103
|
+
700: 700,
|
|
1104
|
+
800: 800,
|
|
1105
|
+
900: 900,
|
|
1106
|
+
1e3: 1e3
|
|
1107
|
+
};
|
|
1108
|
+
function parseArbitraryScale(value) {
|
|
1109
|
+
const scaleMatch = value.match(/^\[(-?\d+(?:\.\d+)?)\]$/);
|
|
1110
|
+
if (scaleMatch) {
|
|
1111
|
+
return parseFloat(scaleMatch[1]);
|
|
1112
|
+
}
|
|
1113
|
+
if (value.startsWith("[") && value.endsWith("]")) {
|
|
1114
|
+
if (process.env.NODE_ENV !== "production") {
|
|
1115
|
+
console.warn(
|
|
1116
|
+
`[react-native-tailwind] Invalid arbitrary scale value: ${value}. Only numbers are supported (e.g., [1.5], [0.75]).`
|
|
1117
|
+
);
|
|
1118
|
+
}
|
|
1119
|
+
return null;
|
|
1120
|
+
}
|
|
1121
|
+
return null;
|
|
1122
|
+
}
|
|
1123
|
+
function parseArbitraryRotation(value) {
|
|
1124
|
+
const rotateMatch = value.match(/^\[(-?\d+(?:\.\d+)?)deg\]$/);
|
|
1125
|
+
if (rotateMatch) {
|
|
1126
|
+
return `${rotateMatch[1]}deg`;
|
|
1127
|
+
}
|
|
1128
|
+
if (value.startsWith("[") && value.endsWith("]")) {
|
|
1129
|
+
if (process.env.NODE_ENV !== "production") {
|
|
1130
|
+
console.warn(
|
|
1131
|
+
`[react-native-tailwind] Invalid arbitrary rotation value: ${value}. Only deg unit is supported (e.g., [45deg], [-15deg]).`
|
|
1132
|
+
);
|
|
1133
|
+
}
|
|
1134
|
+
return null;
|
|
1135
|
+
}
|
|
1136
|
+
return null;
|
|
1137
|
+
}
|
|
1138
|
+
function parseArbitraryTranslation(value) {
|
|
1139
|
+
const pxMatch = value.match(/^\[(-?\d+)(?:px)?\]$/);
|
|
1140
|
+
if (pxMatch) {
|
|
1141
|
+
return parseInt(pxMatch[1], 10);
|
|
1142
|
+
}
|
|
1143
|
+
const percentMatch = value.match(/^\[(-?\d+(?:\.\d+)?)%\]$/);
|
|
1144
|
+
if (percentMatch) {
|
|
1145
|
+
return `${percentMatch[1]}%`;
|
|
1146
|
+
}
|
|
1147
|
+
if (value.startsWith("[") && value.endsWith("]")) {
|
|
1148
|
+
if (process.env.NODE_ENV !== "production") {
|
|
1149
|
+
console.warn(
|
|
1150
|
+
`[react-native-tailwind] Unsupported arbitrary translation unit: ${value}. Only px and % are supported.`
|
|
1151
|
+
);
|
|
1152
|
+
}
|
|
1153
|
+
return null;
|
|
1154
|
+
}
|
|
1155
|
+
return null;
|
|
1156
|
+
}
|
|
1157
|
+
function parseArbitraryPerspective(value) {
|
|
1158
|
+
const perspectiveMatch = value.match(/^\[(-?\d+)\]$/);
|
|
1159
|
+
if (perspectiveMatch) {
|
|
1160
|
+
return parseInt(perspectiveMatch[1], 10);
|
|
1161
|
+
}
|
|
1162
|
+
if (value.startsWith("[") && value.endsWith("]")) {
|
|
1163
|
+
if (process.env.NODE_ENV !== "production") {
|
|
1164
|
+
console.warn(
|
|
1165
|
+
`[react-native-tailwind] Invalid arbitrary perspective value: ${value}. Only integers are supported (e.g., [1500]).`
|
|
1166
|
+
);
|
|
1167
|
+
}
|
|
1168
|
+
return null;
|
|
1169
|
+
}
|
|
1170
|
+
return null;
|
|
1171
|
+
}
|
|
1172
|
+
function parseTransform(cls) {
|
|
1173
|
+
if (cls.startsWith("origin-")) {
|
|
1174
|
+
if (process.env.NODE_ENV !== "production") {
|
|
1175
|
+
console.warn(
|
|
1176
|
+
`[react-native-tailwind] transform-origin is not supported in React Native. Class "${cls}" will be ignored.`
|
|
1177
|
+
);
|
|
1178
|
+
}
|
|
1179
|
+
return null;
|
|
1180
|
+
}
|
|
1181
|
+
if (cls.startsWith("scale-")) {
|
|
1182
|
+
const scaleKey = cls.substring(6);
|
|
1183
|
+
const arbitraryScale = parseArbitraryScale(scaleKey);
|
|
1184
|
+
if (arbitraryScale !== null) {
|
|
1185
|
+
return { transform: [{ scale: arbitraryScale }] };
|
|
1186
|
+
}
|
|
1187
|
+
const scaleValue = SCALE_MAP[scaleKey];
|
|
1188
|
+
if (scaleValue !== void 0) {
|
|
1189
|
+
return { transform: [{ scale: scaleValue }] };
|
|
1190
|
+
}
|
|
1191
|
+
}
|
|
1192
|
+
if (cls.startsWith("scale-x-")) {
|
|
1193
|
+
const scaleKey = cls.substring(8);
|
|
1194
|
+
const arbitraryScale = parseArbitraryScale(scaleKey);
|
|
1195
|
+
if (arbitraryScale !== null) {
|
|
1196
|
+
return { transform: [{ scaleX: arbitraryScale }] };
|
|
1197
|
+
}
|
|
1198
|
+
const scaleValue = SCALE_MAP[scaleKey];
|
|
1199
|
+
if (scaleValue !== void 0) {
|
|
1200
|
+
return { transform: [{ scaleX: scaleValue }] };
|
|
1201
|
+
}
|
|
1202
|
+
}
|
|
1203
|
+
if (cls.startsWith("scale-y-")) {
|
|
1204
|
+
const scaleKey = cls.substring(8);
|
|
1205
|
+
const arbitraryScale = parseArbitraryScale(scaleKey);
|
|
1206
|
+
if (arbitraryScale !== null) {
|
|
1207
|
+
return { transform: [{ scaleY: arbitraryScale }] };
|
|
1208
|
+
}
|
|
1209
|
+
const scaleValue = SCALE_MAP[scaleKey];
|
|
1210
|
+
if (scaleValue !== void 0) {
|
|
1211
|
+
return { transform: [{ scaleY: scaleValue }] };
|
|
1212
|
+
}
|
|
1213
|
+
}
|
|
1214
|
+
if (cls.startsWith("rotate-") || cls.startsWith("-rotate-")) {
|
|
1215
|
+
const isNegative = cls.startsWith("-");
|
|
1216
|
+
const rotateKey = isNegative ? cls.substring(8) : cls.substring(7);
|
|
1217
|
+
const arbitraryRotate = parseArbitraryRotation(rotateKey);
|
|
1218
|
+
if (arbitraryRotate !== null) {
|
|
1219
|
+
const degrees = isNegative ? `-${arbitraryRotate}` : arbitraryRotate;
|
|
1220
|
+
return { transform: [{ rotate: degrees }] };
|
|
1221
|
+
}
|
|
1222
|
+
const rotateValue = ROTATE_MAP[rotateKey];
|
|
1223
|
+
if (rotateValue !== void 0) {
|
|
1224
|
+
const degrees = isNegative ? -rotateValue : rotateValue;
|
|
1225
|
+
return { transform: [{ rotate: `${degrees}deg` }] };
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
if (cls.startsWith("rotate-x-") || cls.startsWith("-rotate-x-")) {
|
|
1229
|
+
const isNegative = cls.startsWith("-");
|
|
1230
|
+
const rotateKey = isNegative ? cls.substring(10) : cls.substring(9);
|
|
1231
|
+
const arbitraryRotate = parseArbitraryRotation(rotateKey);
|
|
1232
|
+
if (arbitraryRotate !== null) {
|
|
1233
|
+
const degrees = isNegative ? `-${arbitraryRotate}` : arbitraryRotate;
|
|
1234
|
+
return { transform: [{ rotateX: degrees }] };
|
|
1235
|
+
}
|
|
1236
|
+
const rotateValue = ROTATE_MAP[rotateKey];
|
|
1237
|
+
if (rotateValue !== void 0) {
|
|
1238
|
+
const degrees = isNegative ? -rotateValue : rotateValue;
|
|
1239
|
+
return { transform: [{ rotateX: `${degrees}deg` }] };
|
|
1240
|
+
}
|
|
1241
|
+
}
|
|
1242
|
+
if (cls.startsWith("rotate-y-") || cls.startsWith("-rotate-y-")) {
|
|
1243
|
+
const isNegative = cls.startsWith("-");
|
|
1244
|
+
const rotateKey = isNegative ? cls.substring(10) : cls.substring(9);
|
|
1245
|
+
const arbitraryRotate = parseArbitraryRotation(rotateKey);
|
|
1246
|
+
if (arbitraryRotate !== null) {
|
|
1247
|
+
const degrees = isNegative ? `-${arbitraryRotate}` : arbitraryRotate;
|
|
1248
|
+
return { transform: [{ rotateY: degrees }] };
|
|
1249
|
+
}
|
|
1250
|
+
const rotateValue = ROTATE_MAP[rotateKey];
|
|
1251
|
+
if (rotateValue !== void 0) {
|
|
1252
|
+
const degrees = isNegative ? -rotateValue : rotateValue;
|
|
1253
|
+
return { transform: [{ rotateY: `${degrees}deg` }] };
|
|
1254
|
+
}
|
|
1255
|
+
}
|
|
1256
|
+
if (cls.startsWith("rotate-z-") || cls.startsWith("-rotate-z-")) {
|
|
1257
|
+
const isNegative = cls.startsWith("-");
|
|
1258
|
+
const rotateKey = isNegative ? cls.substring(10) : cls.substring(9);
|
|
1259
|
+
const arbitraryRotate = parseArbitraryRotation(rotateKey);
|
|
1260
|
+
if (arbitraryRotate !== null) {
|
|
1261
|
+
const degrees = isNegative ? `-${arbitraryRotate}` : arbitraryRotate;
|
|
1262
|
+
return { transform: [{ rotateZ: degrees }] };
|
|
1263
|
+
}
|
|
1264
|
+
const rotateValue = ROTATE_MAP[rotateKey];
|
|
1265
|
+
if (rotateValue !== void 0) {
|
|
1266
|
+
const degrees = isNegative ? -rotateValue : rotateValue;
|
|
1267
|
+
return { transform: [{ rotateZ: `${degrees}deg` }] };
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1270
|
+
if (cls.startsWith("translate-x-") || cls.startsWith("-translate-x-")) {
|
|
1271
|
+
const isNegative = cls.startsWith("-");
|
|
1272
|
+
const translateKey = isNegative ? cls.substring(13) : cls.substring(12);
|
|
1273
|
+
const arbitraryTranslate = parseArbitraryTranslation(translateKey);
|
|
1274
|
+
if (arbitraryTranslate !== null) {
|
|
1275
|
+
const value = typeof arbitraryTranslate === "number" ? isNegative ? -arbitraryTranslate : arbitraryTranslate : isNegative ? `-${arbitraryTranslate}` : arbitraryTranslate;
|
|
1276
|
+
return { transform: [{ translateX: value }] };
|
|
1277
|
+
}
|
|
1278
|
+
const translateValue = SPACING_SCALE[translateKey];
|
|
1279
|
+
if (translateValue !== void 0) {
|
|
1280
|
+
const value = isNegative ? -translateValue : translateValue;
|
|
1281
|
+
return { transform: [{ translateX: value }] };
|
|
1282
|
+
}
|
|
1283
|
+
}
|
|
1284
|
+
if (cls.startsWith("translate-y-") || cls.startsWith("-translate-y-")) {
|
|
1285
|
+
const isNegative = cls.startsWith("-");
|
|
1286
|
+
const translateKey = isNegative ? cls.substring(13) : cls.substring(12);
|
|
1287
|
+
const arbitraryTranslate = parseArbitraryTranslation(translateKey);
|
|
1288
|
+
if (arbitraryTranslate !== null) {
|
|
1289
|
+
const value = typeof arbitraryTranslate === "number" ? isNegative ? -arbitraryTranslate : arbitraryTranslate : isNegative ? `-${arbitraryTranslate}` : arbitraryTranslate;
|
|
1290
|
+
return { transform: [{ translateY: value }] };
|
|
1291
|
+
}
|
|
1292
|
+
const translateValue = SPACING_SCALE[translateKey];
|
|
1293
|
+
if (translateValue !== void 0) {
|
|
1294
|
+
const value = isNegative ? -translateValue : translateValue;
|
|
1295
|
+
return { transform: [{ translateY: value }] };
|
|
1296
|
+
}
|
|
1297
|
+
}
|
|
1298
|
+
if (cls.startsWith("skew-x-") || cls.startsWith("-skew-x-")) {
|
|
1299
|
+
const isNegative = cls.startsWith("-");
|
|
1300
|
+
const skewKey = isNegative ? cls.substring(8) : cls.substring(7);
|
|
1301
|
+
const arbitrarySkew = parseArbitraryRotation(skewKey);
|
|
1302
|
+
if (arbitrarySkew !== null) {
|
|
1303
|
+
const degrees = isNegative ? `-${arbitrarySkew}` : arbitrarySkew;
|
|
1304
|
+
return { transform: [{ skewX: degrees }] };
|
|
1305
|
+
}
|
|
1306
|
+
const skewValue = SKEW_MAP[skewKey];
|
|
1307
|
+
if (skewValue !== void 0) {
|
|
1308
|
+
const degrees = isNegative ? -skewValue : skewValue;
|
|
1309
|
+
return { transform: [{ skewX: `${degrees}deg` }] };
|
|
1310
|
+
}
|
|
1311
|
+
}
|
|
1312
|
+
if (cls.startsWith("skew-y-") || cls.startsWith("-skew-y-")) {
|
|
1313
|
+
const isNegative = cls.startsWith("-");
|
|
1314
|
+
const skewKey = isNegative ? cls.substring(8) : cls.substring(7);
|
|
1315
|
+
const arbitrarySkew = parseArbitraryRotation(skewKey);
|
|
1316
|
+
if (arbitrarySkew !== null) {
|
|
1317
|
+
const degrees = isNegative ? `-${arbitrarySkew}` : arbitrarySkew;
|
|
1318
|
+
return { transform: [{ skewY: degrees }] };
|
|
1319
|
+
}
|
|
1320
|
+
const skewValue = SKEW_MAP[skewKey];
|
|
1321
|
+
if (skewValue !== void 0) {
|
|
1322
|
+
const degrees = isNegative ? -skewValue : skewValue;
|
|
1323
|
+
return { transform: [{ skewY: `${degrees}deg` }] };
|
|
1324
|
+
}
|
|
1325
|
+
}
|
|
1326
|
+
if (cls.startsWith("perspective-")) {
|
|
1327
|
+
const perspectiveKey = cls.substring(12);
|
|
1328
|
+
const arbitraryPerspective = parseArbitraryPerspective(perspectiveKey);
|
|
1329
|
+
if (arbitraryPerspective !== null) {
|
|
1330
|
+
return { transform: [{ perspective: arbitraryPerspective }] };
|
|
1331
|
+
}
|
|
1332
|
+
const perspectiveValue = PERSPECTIVE_SCALE[perspectiveKey];
|
|
1333
|
+
if (perspectiveValue !== void 0) {
|
|
1334
|
+
return { transform: [{ perspective: perspectiveValue }] };
|
|
1335
|
+
}
|
|
1336
|
+
}
|
|
1337
|
+
return null;
|
|
1338
|
+
}
|
|
1339
|
+
|
|
987
1340
|
// src/parser/typography.ts
|
|
988
1341
|
var FONT_SIZES = {
|
|
989
1342
|
xs: 12,
|
|
@@ -1157,7 +1510,8 @@ function parseClass(cls, customColors) {
|
|
|
1157
1510
|
parseTypography,
|
|
1158
1511
|
parseSizing,
|
|
1159
1512
|
parseShadow,
|
|
1160
|
-
parseAspectRatio
|
|
1513
|
+
parseAspectRatio,
|
|
1514
|
+
parseTransform
|
|
1161
1515
|
];
|
|
1162
1516
|
for (const parser of parsers) {
|
|
1163
1517
|
const result = parser(cls);
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
|
|
2
|
+
|
|
3
|
+
exports[`BORDER_WIDTH_SCALE should export complete border width scale 1`] = `
|
|
4
|
+
{
|
|
5
|
+
"0": 0,
|
|
6
|
+
"2": 2,
|
|
7
|
+
"4": 4,
|
|
8
|
+
"8": 8,
|
|
9
|
+
}
|
|
10
|
+
`;
|
|
11
|
+
|
|
12
|
+
exports[`BORDER_RADIUS_SCALE should export complete border radius scale 1`] = `
|
|
13
|
+
{
|
|
14
|
+
"2xl": 16,
|
|
15
|
+
"3xl": 24,
|
|
16
|
+
"full": 9999,
|
|
17
|
+
"lg": 8,
|
|
18
|
+
"md": 6,
|
|
19
|
+
"none": 0,
|
|
20
|
+
"sm": 2,
|
|
21
|
+
"xl": 12,
|
|
22
|
+
}
|
|
23
|
+
`;
|