@mgcrea/react-native-tailwind 0.3.0 → 0.5.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 (71) hide show
  1. package/README.md +459 -39
  2. package/dist/babel/index.cjs +810 -279
  3. package/dist/babel/index.d.ts +2 -1
  4. package/dist/babel/index.ts +328 -22
  5. package/dist/components/Pressable.d.ts +32 -0
  6. package/dist/components/Pressable.js +1 -0
  7. package/dist/components/TextInput.d.ts +56 -0
  8. package/dist/components/TextInput.js +1 -0
  9. package/dist/index.d.ts +9 -2
  10. package/dist/index.js +1 -1
  11. package/dist/parser/aspectRatio.d.ts +16 -0
  12. package/dist/parser/aspectRatio.js +1 -0
  13. package/dist/parser/aspectRatio.test.d.ts +1 -0
  14. package/dist/parser/aspectRatio.test.js +1 -0
  15. package/dist/parser/borders.js +1 -1
  16. package/dist/parser/borders.test.d.ts +1 -0
  17. package/dist/parser/borders.test.js +1 -0
  18. package/dist/parser/colors.d.ts +1 -0
  19. package/dist/parser/colors.js +1 -1
  20. package/dist/parser/colors.test.d.ts +1 -0
  21. package/dist/parser/colors.test.js +1 -0
  22. package/dist/parser/index.d.ts +4 -0
  23. package/dist/parser/index.js +1 -1
  24. package/dist/parser/layout.d.ts +2 -0
  25. package/dist/parser/layout.js +1 -1
  26. package/dist/parser/layout.test.d.ts +1 -0
  27. package/dist/parser/layout.test.js +1 -0
  28. package/dist/parser/modifiers.d.ts +47 -0
  29. package/dist/parser/modifiers.js +1 -0
  30. package/dist/parser/modifiers.test.d.ts +1 -0
  31. package/dist/parser/modifiers.test.js +1 -0
  32. package/dist/parser/shadows.d.ts +26 -0
  33. package/dist/parser/shadows.js +1 -0
  34. package/dist/parser/shadows.test.d.ts +1 -0
  35. package/dist/parser/shadows.test.js +1 -0
  36. package/dist/parser/sizing.test.d.ts +1 -0
  37. package/dist/parser/sizing.test.js +1 -0
  38. package/dist/parser/spacing.d.ts +1 -1
  39. package/dist/parser/spacing.js +1 -1
  40. package/dist/parser/spacing.test.d.ts +1 -0
  41. package/dist/parser/spacing.test.js +1 -0
  42. package/dist/parser/typography.d.ts +2 -1
  43. package/dist/parser/typography.js +1 -1
  44. package/dist/parser/typography.test.d.ts +1 -0
  45. package/dist/parser/typography.test.js +1 -0
  46. package/dist/types.d.ts +5 -2
  47. package/package.json +7 -6
  48. package/src/babel/index.ts +328 -22
  49. package/src/components/Pressable.tsx +46 -0
  50. package/src/components/TextInput.tsx +90 -0
  51. package/src/index.ts +20 -2
  52. package/src/parser/aspectRatio.test.ts +191 -0
  53. package/src/parser/aspectRatio.ts +73 -0
  54. package/src/parser/borders.test.ts +329 -0
  55. package/src/parser/borders.ts +187 -108
  56. package/src/parser/colors.test.ts +335 -0
  57. package/src/parser/colors.ts +117 -6
  58. package/src/parser/index.ts +13 -2
  59. package/src/parser/layout.test.ts +459 -0
  60. package/src/parser/layout.ts +128 -0
  61. package/src/parser/modifiers.test.ts +375 -0
  62. package/src/parser/modifiers.ts +104 -0
  63. package/src/parser/shadows.test.ts +201 -0
  64. package/src/parser/shadows.ts +133 -0
  65. package/src/parser/sizing.test.ts +256 -0
  66. package/src/parser/spacing.test.ts +226 -0
  67. package/src/parser/spacing.ts +93 -138
  68. package/src/parser/typography.test.ts +221 -0
  69. package/src/parser/typography.ts +143 -112
  70. package/src/types.ts +2 -2
  71. package/dist/react-native.d.js +0 -1
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Typography utilities (font size, weight, line height, text align)
2
+ * Typography utilities (font size, weight, line height, text align, letter spacing)
3
3
  */
4
4
 
5
5
  import type { StyleObject } from "../types";
@@ -21,136 +21,167 @@ export const FONT_SIZES: Record<string, number> = {
21
21
  "9xl": 128,
22
22
  };
23
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
- }
24
+ // Letter spacing scale
25
+ export const LETTER_SPACING_SCALE: Record<string, number> = {
26
+ tighter: -0.8,
27
+ tight: -0.4,
28
+ normal: 0,
29
+ wide: 0.4,
30
+ wider: 0.8,
31
+ widest: 1.6,
32
+ };
87
33
 
88
- if (cls === "text-center") {
89
- return { textAlign: "center" };
90
- }
34
+ // Font weight utilities
35
+ const FONT_WEIGHT_MAP: Record<string, StyleObject> = {
36
+ "font-thin": { fontWeight: "100" },
37
+ "font-extralight": { fontWeight: "200" },
38
+ "font-light": { fontWeight: "300" },
39
+ "font-normal": { fontWeight: "400" },
40
+ "font-medium": { fontWeight: "500" },
41
+ "font-semibold": { fontWeight: "600" },
42
+ "font-bold": { fontWeight: "700" },
43
+ "font-extrabold": { fontWeight: "800" },
44
+ "font-black": { fontWeight: "900" },
45
+ };
91
46
 
92
- if (cls === "text-right") {
93
- return { textAlign: "right" };
94
- }
47
+ // Font style utilities
48
+ const FONT_STYLE_MAP: Record<string, StyleObject> = {
49
+ italic: { fontStyle: "italic" },
50
+ "not-italic": { fontStyle: "normal" },
51
+ };
95
52
 
96
- if (cls === "text-justify") {
97
- return { textAlign: "justify" };
98
- }
53
+ // Text alignment utilities
54
+ const TEXT_ALIGN_MAP: Record<string, StyleObject> = {
55
+ "text-left": { textAlign: "left" },
56
+ "text-center": { textAlign: "center" },
57
+ "text-right": { textAlign: "right" },
58
+ "text-justify": { textAlign: "justify" },
59
+ };
99
60
 
100
- // Text decoration
101
- if (cls === "underline") {
102
- return { textDecorationLine: "underline" };
103
- }
61
+ // Text decoration utilities
62
+ const TEXT_DECORATION_MAP: Record<string, StyleObject> = {
63
+ underline: { textDecorationLine: "underline" },
64
+ "line-through": { textDecorationLine: "line-through" },
65
+ "no-underline": { textDecorationLine: "none" },
66
+ };
104
67
 
105
- if (cls === "line-through") {
106
- return { textDecorationLine: "line-through" };
107
- }
68
+ // Text transform utilities
69
+ const TEXT_TRANSFORM_MAP: Record<string, StyleObject> = {
70
+ uppercase: { textTransform: "uppercase" },
71
+ lowercase: { textTransform: "lowercase" },
72
+ capitalize: { textTransform: "capitalize" },
73
+ "normal-case": { textTransform: "none" },
74
+ };
108
75
 
109
- if (cls === "no-underline") {
110
- return { textDecorationLine: "none" };
111
- }
76
+ // Line height utilities
77
+ const LINE_HEIGHT_MAP: Record<string, StyleObject> = {
78
+ "leading-none": { lineHeight: 16 },
79
+ "leading-tight": { lineHeight: 20 },
80
+ "leading-snug": { lineHeight: 22 },
81
+ "leading-normal": { lineHeight: 24 },
82
+ "leading-relaxed": { lineHeight: 28 },
83
+ "leading-loose": { lineHeight: 32 },
84
+ };
112
85
 
113
- // Text transform
114
- if (cls === "uppercase") {
115
- return { textTransform: "uppercase" };
116
- }
86
+ // Letter spacing utilities
87
+ const TRACKING_MAP: Record<string, StyleObject> = {
88
+ "tracking-tighter": { letterSpacing: -0.8 },
89
+ "tracking-tight": { letterSpacing: -0.4 },
90
+ "tracking-normal": { letterSpacing: 0 },
91
+ "tracking-wide": { letterSpacing: 0.4 },
92
+ "tracking-wider": { letterSpacing: 0.8 },
93
+ "tracking-widest": { letterSpacing: 1.6 },
94
+ };
117
95
 
118
- if (cls === "lowercase") {
119
- return { textTransform: "lowercase" };
96
+ /**
97
+ * Parse arbitrary font size value: [18px], [20]
98
+ * Returns number for px values, null for unsupported formats
99
+ */
100
+ function parseArbitraryFontSize(value: string): number | null {
101
+ // Match: [18px] or [18] (pixels only)
102
+ const pxMatch = value.match(/^\[(\d+)(?:px)?\]$/);
103
+ if (pxMatch) {
104
+ return parseInt(pxMatch[1], 10);
105
+ }
106
+
107
+ // Warn about unsupported formats
108
+ if (value.startsWith("[") && value.endsWith("]")) {
109
+ if (process.env.NODE_ENV !== "production") {
110
+ console.warn(
111
+ `[react-native-tailwind] Unsupported arbitrary font size value: ${value}. Only px values are supported (e.g., [18px] or [18]).`,
112
+ );
113
+ }
114
+ return null;
120
115
  }
121
116
 
122
- if (cls === "capitalize") {
123
- return { textTransform: "capitalize" };
124
- }
117
+ return null;
118
+ }
125
119
 
126
- if (cls === "normal-case") {
127
- return { textTransform: "none" };
120
+ /**
121
+ * Parse arbitrary line height value: [24px], [28]
122
+ * Returns number for px values, null for unsupported formats
123
+ */
124
+ function parseArbitraryLineHeight(value: string): number | null {
125
+ // Match: [24px] or [24] (pixels only)
126
+ const pxMatch = value.match(/^\[(\d+)(?:px)?\]$/);
127
+ if (pxMatch) {
128
+ return parseInt(pxMatch[1], 10);
129
+ }
130
+
131
+ // Warn about unsupported formats
132
+ if (value.startsWith("[") && value.endsWith("]")) {
133
+ if (process.env.NODE_ENV !== "production") {
134
+ console.warn(
135
+ `[react-native-tailwind] Unsupported arbitrary line height value: ${value}. Only px values are supported (e.g., [24px] or [24]).`,
136
+ );
137
+ }
138
+ return null;
128
139
  }
129
140
 
130
- // Line height
131
- if (cls === "leading-none") {
132
- return { lineHeight: 16 };
133
- }
141
+ return null;
142
+ }
134
143
 
135
- if (cls === "leading-tight") {
136
- return { lineHeight: 20 };
137
- }
144
+ /**
145
+ * Parse typography classes
146
+ */
147
+ export function parseTypography(cls: string): StyleObject | null {
148
+ // Font size: text-base, text-lg, text-[18px], etc.
149
+ if (cls.startsWith("text-")) {
150
+ const sizeKey = cls.substring(5);
138
151
 
139
- if (cls === "leading-snug") {
140
- return { lineHeight: 22 };
141
- }
152
+ // Try arbitrary value first
153
+ const arbitraryValue = parseArbitraryFontSize(sizeKey);
154
+ if (arbitraryValue !== null) {
155
+ return { fontSize: arbitraryValue };
156
+ }
142
157
 
143
- if (cls === "leading-normal") {
144
- return { lineHeight: 24 };
158
+ // Try preset scale
159
+ const fontSize = FONT_SIZES[sizeKey];
160
+ if (fontSize !== undefined) {
161
+ return { fontSize };
162
+ }
145
163
  }
146
164
 
147
- if (cls === "leading-relaxed") {
148
- return { lineHeight: 28 };
149
- }
165
+ // Line height: leading-normal, leading-[24px], etc.
166
+ if (cls.startsWith("leading-")) {
167
+ const heightKey = cls.substring(8);
150
168
 
151
- if (cls === "leading-loose") {
152
- return { lineHeight: 32 };
169
+ // Try arbitrary value first
170
+ const arbitraryValue = parseArbitraryLineHeight(heightKey);
171
+ if (arbitraryValue !== null) {
172
+ return { lineHeight: arbitraryValue };
173
+ }
153
174
  }
154
175
 
155
- return null;
176
+ // Try each lookup table in order
177
+ return (
178
+ FONT_WEIGHT_MAP[cls] ??
179
+ FONT_STYLE_MAP[cls] ??
180
+ TEXT_ALIGN_MAP[cls] ??
181
+ TEXT_DECORATION_MAP[cls] ??
182
+ TEXT_TRANSFORM_MAP[cls] ??
183
+ LINE_HEIGHT_MAP[cls] ??
184
+ TRACKING_MAP[cls] ??
185
+ null
186
+ );
156
187
  }
package/src/types.ts CHANGED
@@ -6,8 +6,8 @@ import type { ImageStyle, TextStyle, ViewStyle } from "react-native";
6
6
 
7
7
  export type RNStyle = ViewStyle | TextStyle | ImageStyle;
8
8
 
9
- export type StyleObject = {
10
- [key: string]: string | number;
9
+ export type StyleObject = Record<Exclude<string, "shadowOffset">, string | number | undefined> & {
10
+ shadowOffset?: { width: number; height: number };
11
11
  };
12
12
 
13
13
  export type SpacingValue = number;
@@ -1 +0,0 @@
1
- require("react-native");