@mgcrea/react-native-tailwind 0.2.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 (42) hide show
  1. package/README.md +576 -0
  2. package/dist/babel/config-loader.d.ts +25 -0
  3. package/dist/babel/config-loader.ts +134 -0
  4. package/dist/babel/index.cjs +1111 -0
  5. package/dist/babel/index.d.ts +16 -0
  6. package/dist/babel/index.ts +286 -0
  7. package/dist/index.d.ts +12 -0
  8. package/dist/index.js +1 -0
  9. package/dist/parser/borders.d.ts +10 -0
  10. package/dist/parser/borders.js +1 -0
  11. package/dist/parser/colors.d.ts +9 -0
  12. package/dist/parser/colors.js +1 -0
  13. package/dist/parser/index.d.ts +25 -0
  14. package/dist/parser/index.js +1 -0
  15. package/dist/parser/layout.d.ts +8 -0
  16. package/dist/parser/layout.js +1 -0
  17. package/dist/parser/sizing.d.ts +10 -0
  18. package/dist/parser/sizing.js +1 -0
  19. package/dist/parser/spacing.d.ts +10 -0
  20. package/dist/parser/spacing.js +1 -0
  21. package/dist/parser/typography.d.ts +9 -0
  22. package/dist/parser/typography.js +1 -0
  23. package/dist/react-native.d.js +1 -0
  24. package/dist/react-native.d.ts +138 -0
  25. package/dist/types.d.ts +11 -0
  26. package/dist/types.js +1 -0
  27. package/dist/utils/styleKey.d.ts +9 -0
  28. package/dist/utils/styleKey.js +1 -0
  29. package/package.json +83 -0
  30. package/src/babel/config-loader.ts +134 -0
  31. package/src/babel/index.ts +286 -0
  32. package/src/index.ts +20 -0
  33. package/src/parser/borders.ts +198 -0
  34. package/src/parser/colors.ts +160 -0
  35. package/src/parser/index.ts +71 -0
  36. package/src/parser/layout.ts +114 -0
  37. package/src/parser/sizing.ts +239 -0
  38. package/src/parser/spacing.ts +222 -0
  39. package/src/parser/typography.ts +156 -0
  40. package/src/react-native.d.ts +138 -0
  41. package/src/types.ts +15 -0
  42. package/src/utils/styleKey.ts +23 -0
@@ -0,0 +1,239 @@
1
+ /**
2
+ * Sizing utilities (width, height, min/max)
3
+ */
4
+
5
+ import type { StyleObject } from "../types";
6
+
7
+ // Size scale (in pixels/percentages)
8
+ export const SIZE_SCALE: Record<string, number> = {
9
+ 0: 0,
10
+ 0.5: 2,
11
+ 1: 4,
12
+ 1.5: 6,
13
+ 2: 8,
14
+ 2.5: 10,
15
+ 3: 12,
16
+ 3.5: 14,
17
+ 4: 16,
18
+ 5: 20,
19
+ 6: 24,
20
+ 7: 28,
21
+ 8: 32,
22
+ 9: 36,
23
+ 10: 40,
24
+ 11: 44,
25
+ 12: 48,
26
+ 14: 56,
27
+ 16: 64,
28
+ 20: 80,
29
+ 24: 96,
30
+ 28: 112,
31
+ 32: 128,
32
+ 36: 144,
33
+ 40: 160,
34
+ 44: 176,
35
+ 48: 192,
36
+ 52: 208,
37
+ 56: 224,
38
+ 60: 240,
39
+ 64: 256,
40
+ 72: 288,
41
+ 80: 320,
42
+ 96: 384,
43
+ };
44
+
45
+ export const SIZE_PERCENTAGES: Record<string, string> = {
46
+ full: "100%",
47
+ "1/2": "50%",
48
+ "1/3": "33.333333%",
49
+ "2/3": "66.666667%",
50
+ "1/4": "25%",
51
+ "2/4": "50%",
52
+ "3/4": "75%",
53
+ "1/5": "20%",
54
+ "2/5": "40%",
55
+ "3/5": "60%",
56
+ "4/5": "80%",
57
+ "1/6": "16.666667%",
58
+ "2/6": "33.333333%",
59
+ "3/6": "50%",
60
+ "4/6": "66.666667%",
61
+ "5/6": "83.333333%",
62
+ };
63
+
64
+ /**
65
+ * Parse arbitrary size value: [123px], [50%], [10rem]
66
+ * Returns number for px values, string for % values, null for unsupported units
67
+ */
68
+ function parseArbitrarySize(value: string): number | string | null {
69
+ // Match: [123px] or [123] (pixels)
70
+ const pxMatch = value.match(/^\[(\d+)(?:px)?\]$/);
71
+ if (pxMatch) {
72
+ return parseInt(pxMatch[1], 10);
73
+ }
74
+
75
+ // Match: [50%] (percentage)
76
+ const percentMatch = value.match(/^\[(\d+(?:\.\d+)?)%\]$/);
77
+ if (percentMatch) {
78
+ return `${percentMatch[1]}%`;
79
+ }
80
+
81
+ // Unsupported units (rem, em, vh, vw, etc.) - warn and reject
82
+ if (value.startsWith("[") && value.endsWith("]")) {
83
+ if (process.env.NODE_ENV !== "production") {
84
+ console.warn(
85
+ `[react-native-tailwind] Unsupported arbitrary size unit: ${value}. Only px and % are supported.`,
86
+ );
87
+ }
88
+ return null;
89
+ }
90
+
91
+ return null;
92
+ }
93
+
94
+ /**
95
+ * Parse sizing classes
96
+ */
97
+ export function parseSizing(cls: string): StyleObject | null {
98
+ // Width
99
+ if (cls.startsWith("w-")) {
100
+ const sizeKey = cls.substring(2);
101
+
102
+ // Arbitrary values: w-[123px], w-[50%]
103
+ const arbitrarySize = parseArbitrarySize(sizeKey);
104
+ if (arbitrarySize !== null) {
105
+ return { width: arbitrarySize };
106
+ }
107
+
108
+ // Percentage widths: w-full, w-1/2, etc.
109
+ const percentage = SIZE_PERCENTAGES[sizeKey];
110
+ if (percentage) {
111
+ return { width: percentage };
112
+ }
113
+
114
+ // Numeric widths: w-4, w-8, etc.
115
+ const numericSize = SIZE_SCALE[sizeKey];
116
+ if (numericSize !== undefined) {
117
+ return { width: numericSize };
118
+ }
119
+
120
+ // Special values
121
+ if (sizeKey === "auto") {
122
+ return { width: "auto" };
123
+ }
124
+ }
125
+
126
+ // Height
127
+ if (cls.startsWith("h-")) {
128
+ const sizeKey = cls.substring(2);
129
+
130
+ // Arbitrary values: h-[123px], h-[50%]
131
+ const arbitrarySize = parseArbitrarySize(sizeKey);
132
+ if (arbitrarySize !== null) {
133
+ return { height: arbitrarySize };
134
+ }
135
+
136
+ // Percentage heights: h-full, h-1/2, etc.
137
+ const percentage = SIZE_PERCENTAGES[sizeKey];
138
+ if (percentage) {
139
+ return { height: percentage };
140
+ }
141
+
142
+ // Numeric heights: h-4, h-8, etc.
143
+ const numericSize = SIZE_SCALE[sizeKey];
144
+ if (numericSize !== undefined) {
145
+ return { height: numericSize };
146
+ }
147
+
148
+ // Special values
149
+ if (sizeKey === "auto") {
150
+ return { height: "auto" };
151
+ }
152
+ }
153
+
154
+ // Min width
155
+ if (cls.startsWith("min-w-")) {
156
+ const sizeKey = cls.substring(6);
157
+
158
+ // Arbitrary values: min-w-[123px], min-w-[50%]
159
+ const arbitrarySize = parseArbitrarySize(sizeKey);
160
+ if (arbitrarySize !== null) {
161
+ return { minWidth: arbitrarySize };
162
+ }
163
+
164
+ const percentage = SIZE_PERCENTAGES[sizeKey];
165
+ if (percentage) {
166
+ return { minWidth: percentage };
167
+ }
168
+
169
+ const numericSize = SIZE_SCALE[sizeKey];
170
+ if (numericSize !== undefined) {
171
+ return { minWidth: numericSize };
172
+ }
173
+ }
174
+
175
+ // Min height
176
+ if (cls.startsWith("min-h-")) {
177
+ const sizeKey = cls.substring(6);
178
+
179
+ // Arbitrary values: min-h-[123px], min-h-[50%]
180
+ const arbitrarySize = parseArbitrarySize(sizeKey);
181
+ if (arbitrarySize !== null) {
182
+ return { minHeight: arbitrarySize };
183
+ }
184
+
185
+ const percentage = SIZE_PERCENTAGES[sizeKey];
186
+ if (percentage) {
187
+ return { minHeight: percentage };
188
+ }
189
+
190
+ const numericSize = SIZE_SCALE[sizeKey];
191
+ if (numericSize !== undefined) {
192
+ return { minHeight: numericSize };
193
+ }
194
+ }
195
+
196
+ // Max width
197
+ if (cls.startsWith("max-w-")) {
198
+ const sizeKey = cls.substring(6);
199
+
200
+ // Arbitrary values: max-w-[123px], max-w-[50%]
201
+ const arbitrarySize = parseArbitrarySize(sizeKey);
202
+ if (arbitrarySize !== null) {
203
+ return { maxWidth: arbitrarySize };
204
+ }
205
+
206
+ const percentage = SIZE_PERCENTAGES[sizeKey];
207
+ if (percentage) {
208
+ return { maxWidth: percentage };
209
+ }
210
+
211
+ const numericSize = SIZE_SCALE[sizeKey];
212
+ if (numericSize !== undefined) {
213
+ return { maxWidth: numericSize };
214
+ }
215
+ }
216
+
217
+ // Max height
218
+ if (cls.startsWith("max-h-")) {
219
+ const sizeKey = cls.substring(6);
220
+
221
+ // Arbitrary values: max-h-[123px], max-h-[50%]
222
+ const arbitrarySize = parseArbitrarySize(sizeKey);
223
+ if (arbitrarySize !== null) {
224
+ return { maxHeight: arbitrarySize };
225
+ }
226
+
227
+ const percentage = SIZE_PERCENTAGES[sizeKey];
228
+ if (percentage) {
229
+ return { maxHeight: percentage };
230
+ }
231
+
232
+ const numericSize = SIZE_SCALE[sizeKey];
233
+ if (numericSize !== undefined) {
234
+ return { maxHeight: numericSize };
235
+ }
236
+ }
237
+
238
+ return null;
239
+ }
@@ -0,0 +1,222 @@
1
+ /**
2
+ * Spacing utilities (margin, padding, gap)
3
+ */
4
+
5
+ import type { StyleObject } from "../types";
6
+
7
+ // Tailwind spacing scale (in pixels, converted to React Native units)
8
+ export const SPACING_SCALE: Record<string, number> = {
9
+ 0: 0,
10
+ 0.5: 2,
11
+ 1: 4,
12
+ 1.5: 6,
13
+ 2: 8,
14
+ 2.5: 10,
15
+ 3: 12,
16
+ 3.5: 14,
17
+ 4: 16,
18
+ 5: 20,
19
+ 6: 24,
20
+ 7: 28,
21
+ 8: 32,
22
+ 9: 36,
23
+ 10: 40,
24
+ 11: 44,
25
+ 12: 48,
26
+ 14: 56,
27
+ 16: 64,
28
+ 20: 80,
29
+ 24: 96,
30
+ 28: 112,
31
+ 32: 128,
32
+ 36: 144,
33
+ 40: 160,
34
+ 44: 176,
35
+ 48: 192,
36
+ 52: 208,
37
+ 56: 224,
38
+ 60: 240,
39
+ 64: 256,
40
+ 72: 288,
41
+ 80: 320,
42
+ 96: 384,
43
+ };
44
+
45
+ /**
46
+ * Parse spacing classes (margin, padding, gap)
47
+ * Examples: m-4, mx-2, mt-8, p-4, px-2, pt-8, gap-4
48
+ */
49
+ export function parseSpacing(cls: string): StyleObject | null {
50
+ // Margin
51
+ if (cls.startsWith("m-") || cls.startsWith("m")) {
52
+ return parseMargin(cls);
53
+ }
54
+
55
+ // Padding
56
+ if (cls.startsWith("p-") || cls.startsWith("p")) {
57
+ return parsePadding(cls);
58
+ }
59
+
60
+ // Gap
61
+ if (cls.startsWith("gap-")) {
62
+ return parseGap(cls);
63
+ }
64
+
65
+ return null;
66
+ }
67
+
68
+ /**
69
+ * Parse margin classes
70
+ */
71
+ function parseMargin(cls: string): StyleObject | null {
72
+ // m-4 -> margin: 16
73
+ const allMatch = cls.match(/^m-(\d+(?:\.\d+)?)$/);
74
+ if (allMatch) {
75
+ const value = SPACING_SCALE[allMatch[1]];
76
+ if (value !== undefined) {
77
+ return { margin: value };
78
+ }
79
+ }
80
+
81
+ // mx-4 -> marginHorizontal: 16
82
+ const xMatch = cls.match(/^mx-(\d+(?:\.\d+)?)$/);
83
+ if (xMatch) {
84
+ const value = SPACING_SCALE[xMatch[1]];
85
+ if (value !== undefined) {
86
+ return { marginHorizontal: value };
87
+ }
88
+ }
89
+
90
+ // my-4 -> marginVertical: 16
91
+ const yMatch = cls.match(/^my-(\d+(?:\.\d+)?)$/);
92
+ if (yMatch) {
93
+ const value = SPACING_SCALE[yMatch[1]];
94
+ if (value !== undefined) {
95
+ return { marginVertical: value };
96
+ }
97
+ }
98
+
99
+ // mt-4 -> marginTop: 16
100
+ const tMatch = cls.match(/^mt-(\d+(?:\.\d+)?)$/);
101
+ if (tMatch) {
102
+ const value = SPACING_SCALE[tMatch[1]];
103
+ if (value !== undefined) {
104
+ return { marginTop: value };
105
+ }
106
+ }
107
+
108
+ // mr-4 -> marginRight: 16
109
+ const rMatch = cls.match(/^mr-(\d+(?:\.\d+)?)$/);
110
+ if (rMatch) {
111
+ const value = SPACING_SCALE[rMatch[1]];
112
+ if (value !== undefined) {
113
+ return { marginRight: value };
114
+ }
115
+ }
116
+
117
+ // mb-4 -> marginBottom: 16
118
+ const bMatch = cls.match(/^mb-(\d+(?:\.\d+)?)$/);
119
+ if (bMatch) {
120
+ const value = SPACING_SCALE[bMatch[1]];
121
+ if (value !== undefined) {
122
+ return { marginBottom: value };
123
+ }
124
+ }
125
+
126
+ // ml-4 -> marginLeft: 16
127
+ const lMatch = cls.match(/^ml-(\d+(?:\.\d+)?)$/);
128
+ if (lMatch) {
129
+ const value = SPACING_SCALE[lMatch[1]];
130
+ if (value !== undefined) {
131
+ return { marginLeft: value };
132
+ }
133
+ }
134
+
135
+ return null;
136
+ }
137
+
138
+ /**
139
+ * Parse padding classes
140
+ */
141
+ function parsePadding(cls: string): StyleObject | null {
142
+ // p-4 -> padding: 16
143
+ const allMatch = cls.match(/^p-(\d+(?:\.\d+)?)$/);
144
+ if (allMatch) {
145
+ const value = SPACING_SCALE[allMatch[1]];
146
+ if (value !== undefined) {
147
+ return { padding: value };
148
+ }
149
+ }
150
+
151
+ // px-4 -> paddingHorizontal: 16
152
+ const xMatch = cls.match(/^px-(\d+(?:\.\d+)?)$/);
153
+ if (xMatch) {
154
+ const value = SPACING_SCALE[xMatch[1]];
155
+ if (value !== undefined) {
156
+ return { paddingHorizontal: value };
157
+ }
158
+ }
159
+
160
+ // py-4 -> paddingVertical: 16
161
+ const yMatch = cls.match(/^py-(\d+(?:\.\d+)?)$/);
162
+ if (yMatch) {
163
+ const value = SPACING_SCALE[yMatch[1]];
164
+ if (value !== undefined) {
165
+ return { paddingVertical: value };
166
+ }
167
+ }
168
+
169
+ // pt-4 -> paddingTop: 16
170
+ const tMatch = cls.match(/^pt-(\d+(?:\.\d+)?)$/);
171
+ if (tMatch) {
172
+ const value = SPACING_SCALE[tMatch[1]];
173
+ if (value !== undefined) {
174
+ return { paddingTop: value };
175
+ }
176
+ }
177
+
178
+ // pr-4 -> paddingRight: 16
179
+ const rMatch = cls.match(/^pr-(\d+(?:\.\d+)?)$/);
180
+ if (rMatch) {
181
+ const value = SPACING_SCALE[rMatch[1]];
182
+ if (value !== undefined) {
183
+ return { paddingRight: value };
184
+ }
185
+ }
186
+
187
+ // pb-4 -> paddingBottom: 16
188
+ const bMatch = cls.match(/^pb-(\d+(?:\.\d+)?)$/);
189
+ if (bMatch) {
190
+ const value = SPACING_SCALE[bMatch[1]];
191
+ if (value !== undefined) {
192
+ return { paddingBottom: value };
193
+ }
194
+ }
195
+
196
+ // pl-4 -> paddingLeft: 16
197
+ const lMatch = cls.match(/^pl-(\d+(?:\.\d+)?)$/);
198
+ if (lMatch) {
199
+ const value = SPACING_SCALE[lMatch[1]];
200
+ if (value !== undefined) {
201
+ return { paddingLeft: value };
202
+ }
203
+ }
204
+
205
+ return null;
206
+ }
207
+
208
+ /**
209
+ * Parse gap classes
210
+ */
211
+ function parseGap(cls: string): StyleObject | null {
212
+ // gap-4 -> gap: 16
213
+ const match = cls.match(/^gap-(\d+(?:\.\d+)?)$/);
214
+ if (match) {
215
+ const value = SPACING_SCALE[match[1]];
216
+ if (value !== undefined) {
217
+ return { gap: value };
218
+ }
219
+ }
220
+
221
+ return null;
222
+ }
@@ -0,0 +1,156 @@
1
+ /**
2
+ * Typography utilities (font size, weight, line height, text align)
3
+ */
4
+
5
+ import type { StyleObject } from "../types";
6
+
7
+ // Font sizes
8
+ export const FONT_SIZES: Record<string, number> = {
9
+ xs: 12,
10
+ sm: 14,
11
+ base: 16,
12
+ lg: 18,
13
+ xl: 20,
14
+ "2xl": 24,
15
+ "3xl": 30,
16
+ "4xl": 36,
17
+ "5xl": 48,
18
+ "6xl": 60,
19
+ "7xl": 72,
20
+ "8xl": 96,
21
+ "9xl": 128,
22
+ };
23
+
24
+ /**
25
+ * Parse typography classes
26
+ */
27
+ export function parseTypography(cls: string): StyleObject | null {
28
+ // Font size: text-base, text-lg, etc.
29
+ if (cls.startsWith("text-")) {
30
+ const sizeKey = cls.substring(5);
31
+ const fontSize = FONT_SIZES[sizeKey];
32
+ if (fontSize !== undefined) {
33
+ return { fontSize };
34
+ }
35
+ }
36
+
37
+ // Font weight
38
+ if (cls === "font-thin") {
39
+ return { fontWeight: "100" };
40
+ }
41
+
42
+ if (cls === "font-extralight") {
43
+ return { fontWeight: "200" };
44
+ }
45
+
46
+ if (cls === "font-light") {
47
+ return { fontWeight: "300" };
48
+ }
49
+
50
+ if (cls === "font-normal") {
51
+ return { fontWeight: "400" };
52
+ }
53
+
54
+ if (cls === "font-medium") {
55
+ return { fontWeight: "500" };
56
+ }
57
+
58
+ if (cls === "font-semibold") {
59
+ return { fontWeight: "600" };
60
+ }
61
+
62
+ if (cls === "font-bold") {
63
+ return { fontWeight: "700" };
64
+ }
65
+
66
+ if (cls === "font-extrabold") {
67
+ return { fontWeight: "800" };
68
+ }
69
+
70
+ if (cls === "font-black") {
71
+ return { fontWeight: "900" };
72
+ }
73
+
74
+ // Font style
75
+ if (cls === "italic") {
76
+ return { fontStyle: "italic" };
77
+ }
78
+
79
+ if (cls === "not-italic") {
80
+ return { fontStyle: "normal" };
81
+ }
82
+
83
+ // Text align
84
+ if (cls === "text-left") {
85
+ return { textAlign: "left" };
86
+ }
87
+
88
+ if (cls === "text-center") {
89
+ return { textAlign: "center" };
90
+ }
91
+
92
+ if (cls === "text-right") {
93
+ return { textAlign: "right" };
94
+ }
95
+
96
+ if (cls === "text-justify") {
97
+ return { textAlign: "justify" };
98
+ }
99
+
100
+ // Text decoration
101
+ if (cls === "underline") {
102
+ return { textDecorationLine: "underline" };
103
+ }
104
+
105
+ if (cls === "line-through") {
106
+ return { textDecorationLine: "line-through" };
107
+ }
108
+
109
+ if (cls === "no-underline") {
110
+ return { textDecorationLine: "none" };
111
+ }
112
+
113
+ // Text transform
114
+ if (cls === "uppercase") {
115
+ return { textTransform: "uppercase" };
116
+ }
117
+
118
+ if (cls === "lowercase") {
119
+ return { textTransform: "lowercase" };
120
+ }
121
+
122
+ if (cls === "capitalize") {
123
+ return { textTransform: "capitalize" };
124
+ }
125
+
126
+ if (cls === "normal-case") {
127
+ return { textTransform: "none" };
128
+ }
129
+
130
+ // Line height
131
+ if (cls === "leading-none") {
132
+ return { lineHeight: 16 };
133
+ }
134
+
135
+ if (cls === "leading-tight") {
136
+ return { lineHeight: 20 };
137
+ }
138
+
139
+ if (cls === "leading-snug") {
140
+ return { lineHeight: 22 };
141
+ }
142
+
143
+ if (cls === "leading-normal") {
144
+ return { lineHeight: 24 };
145
+ }
146
+
147
+ if (cls === "leading-relaxed") {
148
+ return { lineHeight: 28 };
149
+ }
150
+
151
+ if (cls === "leading-loose") {
152
+ return { lineHeight: 32 };
153
+ }
154
+
155
+ return null;
156
+ }