@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
@@ -0,0 +1,304 @@
1
+ export type TailwindPalette = {
2
+ "50": string;
3
+ "100": string;
4
+ "200": string;
5
+ "300": string;
6
+ "400": string;
7
+ "500": string;
8
+ "600": string;
9
+ "700": string;
10
+ "800": string;
11
+ "900": string;
12
+ "950": string;
13
+ };
14
+
15
+ export const TAILWIND_PALETTES = {
16
+ red: {
17
+ "50": "#fef2f2",
18
+ "100": "#ffe2e2",
19
+ "200": "#ffc9c9",
20
+ "300": "#ffa2a2",
21
+ "400": "#ff6467",
22
+ "500": "#fb2c36",
23
+ "600": "#e7000b",
24
+ "700": "#c10007",
25
+ "800": "#9f0712",
26
+ "900": "#82181a",
27
+ "950": "#460809",
28
+ },
29
+ orange: {
30
+ "50": "#fff7ed",
31
+ "100": "#ffedd4",
32
+ "200": "#ffd6a7",
33
+ "300": "#ffb86a",
34
+ "400": "#ff8904",
35
+ "500": "#ff6900",
36
+ "600": "#f54900",
37
+ "700": "#ca3500",
38
+ "800": "#9f2d00",
39
+ "900": "#7e2a0c",
40
+ "950": "#441306",
41
+ },
42
+ amber: {
43
+ "50": "#fffbeb",
44
+ "100": "#fef3c6",
45
+ "200": "#fee685",
46
+ "300": "#ffd230",
47
+ "400": "#ffb900",
48
+ "500": "#fe9a00",
49
+ "600": "#e17100",
50
+ "700": "#bb4d00",
51
+ "800": "#973c00",
52
+ "900": "#7b3306",
53
+ "950": "#461901",
54
+ },
55
+ yellow: {
56
+ "50": "#fefce8",
57
+ "100": "#fef9c2",
58
+ "200": "#fff085",
59
+ "300": "#ffdf20",
60
+ "400": "#fdc700",
61
+ "500": "#f0b100",
62
+ "600": "#d08700",
63
+ "700": "#a65f00",
64
+ "800": "#894b00",
65
+ "900": "#733e0a",
66
+ "950": "#432004",
67
+ },
68
+ lime: {
69
+ "50": "#f7fee7",
70
+ "100": "#ecfcca",
71
+ "200": "#d8f999",
72
+ "300": "#bbf451",
73
+ "400": "#9ae600",
74
+ "500": "#7ccf00",
75
+ "600": "#5ea500",
76
+ "700": "#497d00",
77
+ "800": "#3c6300",
78
+ "900": "#35530e",
79
+ "950": "#192e03",
80
+ },
81
+ green: {
82
+ "50": "#f0fdf4",
83
+ "100": "#dcfce7",
84
+ "200": "#b9f8cf",
85
+ "300": "#7bf1a8",
86
+ "400": "#05df72",
87
+ "500": "#00c950",
88
+ "600": "#00a63e",
89
+ "700": "#008236",
90
+ "800": "#016630",
91
+ "900": "#0d542b",
92
+ "950": "#032e15",
93
+ },
94
+ emerald: {
95
+ "50": "#ecfdf5",
96
+ "100": "#d0fae5",
97
+ "200": "#a4f4cf",
98
+ "300": "#5ee9b5",
99
+ "400": "#00d492",
100
+ "500": "#00bc7d",
101
+ "600": "#009966",
102
+ "700": "#007a55",
103
+ "800": "#006045",
104
+ "900": "#004f3b",
105
+ "950": "#002c22",
106
+ },
107
+ teal: {
108
+ "50": "#f0fdfa",
109
+ "100": "#cbfbf1",
110
+ "200": "#96f7e4",
111
+ "300": "#46ecd5",
112
+ "400": "#00d5be",
113
+ "500": "#00bba7",
114
+ "600": "#009689",
115
+ "700": "#00786f",
116
+ "800": "#005f5a",
117
+ "900": "#0b4f4a",
118
+ "950": "#022f2e",
119
+ },
120
+ cyan: {
121
+ "50": "#ecfeff",
122
+ "100": "#cefafe",
123
+ "200": "#a2f4fd",
124
+ "300": "#53eafd",
125
+ "400": "#00d3f2",
126
+ "500": "#00b8db",
127
+ "600": "#0092b8",
128
+ "700": "#007595",
129
+ "800": "#005f78",
130
+ "900": "#104e64",
131
+ "950": "#053345",
132
+ },
133
+ sky: {
134
+ "50": "#f0f9ff",
135
+ "100": "#dff2fe",
136
+ "200": "#b8e6fe",
137
+ "300": "#74d4ff",
138
+ "400": "#00bcff",
139
+ "500": "#00a6f4",
140
+ "600": "#0084d1",
141
+ "700": "#0069a8",
142
+ "800": "#00598a",
143
+ "900": "#024a70",
144
+ "950": "#052f4a",
145
+ },
146
+ blue: {
147
+ "50": "#eff6ff",
148
+ "100": "#dbeafe",
149
+ "200": "#bedbff",
150
+ "300": "#8ec5ff",
151
+ "400": "#51a2ff",
152
+ "500": "#2b7fff",
153
+ "600": "#155dfc",
154
+ "700": "#1447e6",
155
+ "800": "#193cb8",
156
+ "900": "#1c398e",
157
+ "950": "#162456",
158
+ },
159
+ indigo: {
160
+ "50": "#eef2ff",
161
+ "100": "#e0e7ff",
162
+ "200": "#c6d2ff",
163
+ "300": "#a3b3ff",
164
+ "400": "#7c86ff",
165
+ "500": "#615fff",
166
+ "600": "#4f39f6",
167
+ "700": "#432dd7",
168
+ "800": "#372aac",
169
+ "900": "#312c85",
170
+ "950": "#1e1a4d",
171
+ },
172
+ violet: {
173
+ "50": "#f5f3ff",
174
+ "100": "#ede9fe",
175
+ "200": "#ddd6ff",
176
+ "300": "#c4b4ff",
177
+ "400": "#a684ff",
178
+ "500": "#8e51ff",
179
+ "600": "#7f22fe",
180
+ "700": "#7008e7",
181
+ "800": "#5d0ec0",
182
+ "900": "#4d179a",
183
+ "950": "#2f0d68",
184
+ },
185
+ purple: {
186
+ "50": "#faf5ff",
187
+ "100": "#f3e8ff",
188
+ "200": "#e9d4ff",
189
+ "300": "#dab2ff",
190
+ "400": "#c27aff",
191
+ "500": "#ad46ff",
192
+ "600": "#9810fa",
193
+ "700": "#8200db",
194
+ "800": "#6e11b0",
195
+ "900": "#59168b",
196
+ "950": "#3c0366",
197
+ },
198
+ fuchsia: {
199
+ "50": "#fdf4ff",
200
+ "100": "#fae8ff",
201
+ "200": "#f6cfff",
202
+ "300": "#f4a8ff",
203
+ "400": "#ed6aff",
204
+ "500": "#e12afb",
205
+ "600": "#c800de",
206
+ "700": "#a800b7",
207
+ "800": "#8a0194",
208
+ "900": "#721378",
209
+ "950": "#4b004f",
210
+ },
211
+ pink: {
212
+ "50": "#fdf2f8",
213
+ "100": "#fce7f3",
214
+ "200": "#fccee8",
215
+ "300": "#fda5d5",
216
+ "400": "#fb64b6",
217
+ "500": "#f6339a",
218
+ "600": "#e60076",
219
+ "700": "#c6005c",
220
+ "800": "#a3004c",
221
+ "900": "#861043",
222
+ "950": "#510424",
223
+ },
224
+ rose: {
225
+ "50": "#fff1f2",
226
+ "100": "#ffe4e6",
227
+ "200": "#ffccd3",
228
+ "300": "#ffa1ad",
229
+ "400": "#ff637e",
230
+ "500": "#ff2056",
231
+ "600": "#ec003f",
232
+ "700": "#c70036",
233
+ "800": "#a50036",
234
+ "900": "#8b0836",
235
+ "950": "#4d0218",
236
+ },
237
+ slate: {
238
+ "50": "#f8fafc",
239
+ "100": "#f1f5f9",
240
+ "200": "#e2e8f0",
241
+ "300": "#cad5e2",
242
+ "400": "#90a1b9",
243
+ "500": "#62748e",
244
+ "600": "#45556c",
245
+ "700": "#314158",
246
+ "800": "#1d293d",
247
+ "900": "#0f172b",
248
+ "950": "#020618",
249
+ },
250
+ gray: {
251
+ "50": "#f9fafb",
252
+ "100": "#f3f4f6",
253
+ "200": "#e5e7eb",
254
+ "300": "#d1d5dc",
255
+ "400": "#99a1af",
256
+ "500": "#6a7282",
257
+ "600": "#4a5565",
258
+ "700": "#364153",
259
+ "800": "#1e2939",
260
+ "900": "#101828",
261
+ "950": "#030712",
262
+ },
263
+ zinc: {
264
+ "50": "#fafafa",
265
+ "100": "#f4f4f5",
266
+ "200": "#e4e4e7",
267
+ "300": "#d4d4d8",
268
+ "400": "#9f9fa9",
269
+ "500": "#71717b",
270
+ "600": "#52525c",
271
+ "700": "#3f3f46",
272
+ "800": "#27272a",
273
+ "900": "#18181b",
274
+ "950": "#09090b",
275
+ },
276
+ neutral: {
277
+ "50": "#fafafa",
278
+ "100": "#f5f5f5",
279
+ "200": "#e5e5e5",
280
+ "300": "#d4d4d4",
281
+ "400": "#a1a1a1",
282
+ "500": "#737373",
283
+ "600": "#525252",
284
+ "700": "#404040",
285
+ "800": "#262626",
286
+ "900": "#171717",
287
+ "950": "#0a0a0a",
288
+ },
289
+ stone: {
290
+ "50": "#fafaf9",
291
+ "100": "#f5f5f4",
292
+ "200": "#e7e5e4",
293
+ "300": "#d6d3d1",
294
+ "400": "#a6a09b",
295
+ "500": "#79716b",
296
+ "600": "#57534d",
297
+ "700": "#44403b",
298
+ "800": "#292524",
299
+ "900": "#1c1917",
300
+ "950": "#0c0a09",
301
+ },
302
+ } satisfies Record<string, TailwindPalette>;
303
+
304
+ export type TailwindColor = keyof typeof TAILWIND_PALETTES;
package/src/index.ts CHANGED
@@ -3,8 +3,13 @@
3
3
  * Compile-time Tailwind CSS for React Native
4
4
  */
5
5
 
6
+ // Compile-time tw/twStyle functions (transformed by Babel plugin)
7
+ export { tw, twStyle } from "./stubs/tw.js";
8
+ export type { NativeStyle, TwStyle } from "./stubs/tw.js";
9
+
6
10
  // Main parser functions
7
11
  export { parseClass, parseClassName } from "./parser";
12
+ export { flattenColors } from "./utils/flattenColors";
8
13
  export { generateStyleKey } from "./utils/styleKey";
9
14
 
10
15
  // Re-export types
@@ -1,6 +1,22 @@
1
1
  import { describe, expect, it } from "vitest";
2
2
  import { COLORS, parseColor } from "./colors";
3
3
 
4
+ // Helper to apply opacity to hex color for testing
5
+ function applyOpacity(hex: string, opacity: number): string {
6
+ if (hex === "transparent") return "transparent";
7
+ const cleanHex = hex.replace(/^#/, "");
8
+ const fullHex =
9
+ cleanHex.length === 3
10
+ ? cleanHex
11
+ .split("")
12
+ .map((char) => char + char)
13
+ .join("")
14
+ : cleanHex;
15
+ const alpha = Math.round((opacity / 100) * 255);
16
+ const alphaHex = alpha.toString(16).padStart(2, "0").toUpperCase();
17
+ return `#${fullHex.toUpperCase()}${alphaHex}`;
18
+ }
19
+
4
20
  describe("COLORS", () => {
5
21
  it("should export complete color palette", () => {
6
22
  expect(COLORS).toMatchSnapshot();
@@ -9,10 +25,10 @@ describe("COLORS", () => {
9
25
 
10
26
  describe("parseColor - background colors", () => {
11
27
  it("should parse background colors with preset values", () => {
12
- expect(parseColor("bg-blue-500")).toEqual({ backgroundColor: "#3B82F6" });
13
- expect(parseColor("bg-red-500")).toEqual({ backgroundColor: "#EF4444" });
14
- expect(parseColor("bg-green-500")).toEqual({ backgroundColor: "#22C55E" });
15
- expect(parseColor("bg-gray-300")).toEqual({ backgroundColor: "#D1D5DB" });
28
+ expect(parseColor("bg-blue-500")).toEqual({ backgroundColor: COLORS["blue-500"] });
29
+ expect(parseColor("bg-red-500")).toEqual({ backgroundColor: COLORS["red-500"] });
30
+ expect(parseColor("bg-green-500")).toEqual({ backgroundColor: COLORS["green-500"] });
31
+ expect(parseColor("bg-gray-300")).toEqual({ backgroundColor: COLORS["gray-300"] });
16
32
  });
17
33
 
18
34
  it("should parse background colors with basic values", () => {
@@ -57,10 +73,10 @@ describe("parseColor - background colors", () => {
57
73
 
58
74
  describe("parseColor - text colors", () => {
59
75
  it("should parse text colors with preset values", () => {
60
- expect(parseColor("text-blue-500")).toEqual({ color: "#3B82F6" });
61
- expect(parseColor("text-red-500")).toEqual({ color: "#EF4444" });
62
- expect(parseColor("text-green-500")).toEqual({ color: "#22C55E" });
63
- expect(parseColor("text-gray-700")).toEqual({ color: "#374151" });
76
+ expect(parseColor("text-blue-500")).toEqual({ color: COLORS["blue-500"] });
77
+ expect(parseColor("text-red-500")).toEqual({ color: COLORS["red-500"] });
78
+ expect(parseColor("text-green-500")).toEqual({ color: COLORS["green-500"] });
79
+ expect(parseColor("text-gray-700")).toEqual({ color: COLORS["gray-700"] });
64
80
  });
65
81
 
66
82
  it("should parse text colors with basic values", () => {
@@ -88,10 +104,10 @@ describe("parseColor - text colors", () => {
88
104
 
89
105
  describe("parseColor - border colors", () => {
90
106
  it("should parse border colors with preset values", () => {
91
- expect(parseColor("border-blue-500")).toEqual({ borderColor: "#3B82F6" });
92
- expect(parseColor("border-red-500")).toEqual({ borderColor: "#EF4444" });
93
- expect(parseColor("border-green-500")).toEqual({ borderColor: "#22C55E" });
94
- expect(parseColor("border-gray-200")).toEqual({ borderColor: "#E5E7EB" });
107
+ expect(parseColor("border-blue-500")).toEqual({ borderColor: COLORS["blue-500"] });
108
+ expect(parseColor("border-red-500")).toEqual({ borderColor: COLORS["red-500"] });
109
+ expect(parseColor("border-green-500")).toEqual({ borderColor: COLORS["green-500"] });
110
+ expect(parseColor("border-gray-200")).toEqual({ borderColor: COLORS["gray-200"] });
95
111
  });
96
112
 
97
113
  it("should parse border colors with basic values", () => {
@@ -153,7 +169,7 @@ describe("parseColor - custom colors", () => {
153
169
  });
154
170
 
155
171
  it("should fallback to preset colors when custom color not found", () => {
156
- expect(parseColor("bg-red-500", customColors)).toEqual({ backgroundColor: "#EF4444" });
172
+ expect(parseColor("bg-red-500", customColors)).toEqual({ backgroundColor: COLORS["red-500"] });
157
173
  });
158
174
  });
159
175
 
@@ -220,9 +236,9 @@ describe("parseColor - edge cases", () => {
220
236
 
221
237
  describe("parseColor - comprehensive coverage", () => {
222
238
  it("should parse all color types with same preset color", () => {
223
- expect(parseColor("bg-blue-500")).toEqual({ backgroundColor: "#3B82F6" });
224
- expect(parseColor("text-blue-500")).toEqual({ color: "#3B82F6" });
225
- expect(parseColor("border-blue-500")).toEqual({ borderColor: "#3B82F6" });
239
+ expect(parseColor("bg-blue-500")).toEqual({ backgroundColor: COLORS["blue-500"] });
240
+ expect(parseColor("text-blue-500")).toEqual({ color: COLORS["blue-500"] });
241
+ expect(parseColor("border-blue-500")).toEqual({ borderColor: COLORS["blue-500"] });
226
242
  });
227
243
 
228
244
  it("should parse all color types with same arbitrary hex", () => {
@@ -261,23 +277,23 @@ describe("parseColor - comprehensive coverage", () => {
261
277
 
262
278
  describe("parseColor - opacity modifiers", () => {
263
279
  it("should parse background colors with opacity modifiers", () => {
264
- expect(parseColor("bg-black/50")).toEqual({ backgroundColor: "#00000080" });
265
- expect(parseColor("bg-white/50")).toEqual({ backgroundColor: "#FFFFFF80" });
266
- expect(parseColor("bg-blue-500/80")).toEqual({ backgroundColor: "#3B82F6CC" });
267
- expect(parseColor("bg-red-500/30")).toEqual({ backgroundColor: "#EF44444D" });
280
+ expect(parseColor("bg-black/50")).toEqual({ backgroundColor: applyOpacity(COLORS.black, 50) });
281
+ expect(parseColor("bg-white/50")).toEqual({ backgroundColor: applyOpacity(COLORS.white, 50) });
282
+ expect(parseColor("bg-blue-500/80")).toEqual({ backgroundColor: applyOpacity(COLORS["blue-500"], 80) });
283
+ expect(parseColor("bg-red-500/30")).toEqual({ backgroundColor: applyOpacity(COLORS["red-500"], 30) });
268
284
  });
269
285
 
270
286
  it("should parse text colors with opacity modifiers", () => {
271
- expect(parseColor("text-black/80")).toEqual({ color: "#000000CC" });
272
- expect(parseColor("text-white/90")).toEqual({ color: "#FFFFFFE6" });
273
- expect(parseColor("text-gray-900/70")).toEqual({ color: "#111827B3" });
274
- expect(parseColor("text-blue-500/50")).toEqual({ color: "#3B82F680" });
287
+ expect(parseColor("text-black/80")).toEqual({ color: applyOpacity(COLORS.black, 80) });
288
+ expect(parseColor("text-white/90")).toEqual({ color: applyOpacity(COLORS.white, 90) });
289
+ expect(parseColor("text-gray-900/70")).toEqual({ color: applyOpacity(COLORS["gray-900"], 70) });
290
+ expect(parseColor("text-blue-500/50")).toEqual({ color: applyOpacity(COLORS["blue-500"], 50) });
275
291
  });
276
292
 
277
293
  it("should parse border colors with opacity modifiers", () => {
278
- expect(parseColor("border-black/25")).toEqual({ borderColor: "#00000040" });
279
- expect(parseColor("border-red-500/60")).toEqual({ borderColor: "#EF444499" });
280
- expect(parseColor("border-gray-200/40")).toEqual({ borderColor: "#E5E7EB66" });
294
+ expect(parseColor("border-black/25")).toEqual({ borderColor: applyOpacity(COLORS.black, 25) });
295
+ expect(parseColor("border-red-500/60")).toEqual({ borderColor: applyOpacity(COLORS["red-500"], 60) });
296
+ expect(parseColor("border-gray-200/40")).toEqual({ borderColor: applyOpacity(COLORS["gray-200"], 40) });
281
297
  });
282
298
 
283
299
  it("should handle opacity modifier with arbitrary hex colors", () => {
@@ -293,13 +309,13 @@ describe("parseColor - opacity modifiers", () => {
293
309
  });
294
310
 
295
311
  it("should handle opacity 0 (fully transparent)", () => {
296
- expect(parseColor("bg-black/0")).toEqual({ backgroundColor: "#00000000" });
297
- expect(parseColor("text-red-500/0")).toEqual({ color: "#EF444400" });
312
+ expect(parseColor("bg-black/0")).toEqual({ backgroundColor: applyOpacity(COLORS.black, 0) });
313
+ expect(parseColor("text-red-500/0")).toEqual({ color: applyOpacity(COLORS["red-500"], 0) });
298
314
  });
299
315
 
300
316
  it("should handle opacity 100 (fully opaque)", () => {
301
- expect(parseColor("bg-black/100")).toEqual({ backgroundColor: "#000000FF" });
302
- expect(parseColor("text-blue-500/100")).toEqual({ color: "#3B82F6FF" });
317
+ expect(parseColor("bg-black/100")).toEqual({ backgroundColor: applyOpacity(COLORS.black, 100) });
318
+ expect(parseColor("text-blue-500/100")).toEqual({ color: applyOpacity(COLORS["blue-500"], 100) });
303
319
  });
304
320
 
305
321
  it("should handle transparent color with opacity modifier", () => {
@@ -2,119 +2,14 @@
2
2
  * Color utilities (background, text, border colors)
3
3
  */
4
4
 
5
+ import { TAILWIND_PALETTES } from "../config/palettes";
5
6
  import type { StyleObject } from "../types";
7
+ import { flattenColors } from "../utils/flattenColors";
6
8
 
7
- // Tailwind color palette
9
+ // Tailwind color palette (flattened from config)
8
10
  export const COLORS: Record<string, string> = {
9
- // Gray
10
- "gray-50": "#F9FAFB",
11
- "gray-100": "#F3F4F6",
12
- "gray-200": "#E5E7EB",
13
- "gray-300": "#D1D5DB",
14
- "gray-400": "#9CA3AF",
15
- "gray-500": "#6B7280",
16
- "gray-600": "#4B5563",
17
- "gray-700": "#374151",
18
- "gray-800": "#1F2937",
19
- "gray-900": "#111827",
20
-
21
- // Red
22
- "red-50": "#FEF2F2",
23
- "red-100": "#FEE2E2",
24
- "red-200": "#FECACA",
25
- "red-300": "#FCA5A5",
26
- "red-400": "#F87171",
27
- "red-500": "#EF4444",
28
- "red-600": "#DC2626",
29
- "red-700": "#B91C1C",
30
- "red-800": "#991B1B",
31
- "red-900": "#7F1D1D",
32
-
33
- // Blue
34
- "blue-50": "#EFF6FF",
35
- "blue-100": "#DBEAFE",
36
- "blue-200": "#BFDBFE",
37
- "blue-300": "#93C5FD",
38
- "blue-400": "#60A5FA",
39
- "blue-500": "#3B82F6",
40
- "blue-600": "#2563EB",
41
- "blue-700": "#1D4ED8",
42
- "blue-800": "#1E40AF",
43
- "blue-900": "#1E3A8A",
44
-
45
- // Green
46
- "green-50": "#F0FDF4",
47
- "green-100": "#DCFCE7",
48
- "green-200": "#BBF7D0",
49
- "green-300": "#86EFAC",
50
- "green-400": "#4ADE80",
51
- "green-500": "#22C55E",
52
- "green-600": "#16A34A",
53
- "green-700": "#15803D",
54
- "green-800": "#166534",
55
- "green-900": "#14532D",
56
-
57
- // Yellow
58
- "yellow-50": "#FEFCE8",
59
- "yellow-100": "#FEF9C3",
60
- "yellow-200": "#FEF08A",
61
- "yellow-300": "#FDE047",
62
- "yellow-400": "#FACC15",
63
- "yellow-500": "#EAB308",
64
- "yellow-600": "#CA8A04",
65
- "yellow-700": "#A16207",
66
- "yellow-800": "#854D0E",
67
- "yellow-900": "#713F12",
68
-
69
- // Purple
70
- "purple-50": "#FAF5FF",
71
- "purple-100": "#F3E8FF",
72
- "purple-200": "#E9D5FF",
73
- "purple-300": "#D8B4FE",
74
- "purple-400": "#C084FC",
75
- "purple-500": "#A855F7",
76
- "purple-600": "#9333EA",
77
- "purple-700": "#7E22CE",
78
- "purple-800": "#6B21A8",
79
- "purple-900": "#581C87",
80
-
81
- // Pink
82
- "pink-50": "#FDF2F8",
83
- "pink-100": "#FCE7F3",
84
- "pink-200": "#FBCFE8",
85
- "pink-300": "#F9A8D4",
86
- "pink-400": "#F472B6",
87
- "pink-500": "#EC4899",
88
- "pink-600": "#DB2777",
89
- "pink-700": "#BE185D",
90
- "pink-800": "#9D174D",
91
- "pink-900": "#831843",
92
-
93
- // Orange
94
- "orange-50": "#FFF7ED",
95
- "orange-100": "#FFEDD5",
96
- "orange-200": "#FED7AA",
97
- "orange-300": "#FDBA74",
98
- "orange-400": "#FB923C",
99
- "orange-500": "#F97316",
100
- "orange-600": "#EA580C",
101
- "orange-700": "#C2410C",
102
- "orange-800": "#9A3412",
103
- "orange-900": "#7C2D12",
104
-
105
- // Indigo
106
- "indigo-50": "#EEF2FF",
107
- "indigo-100": "#E0E7FF",
108
- "indigo-200": "#C7D2FE",
109
- "indigo-300": "#A5B4FC",
110
- "indigo-400": "#818CF8",
111
- "indigo-500": "#6366F1",
112
- "indigo-600": "#4F46E5",
113
- "indigo-700": "#4338CA",
114
- "indigo-800": "#3730A3",
115
- "indigo-900": "#312E81",
116
-
117
- // Basic colors
11
+ ...flattenColors(TAILWIND_PALETTES),
12
+ // Add basic colors
118
13
  white: "#FFFFFF",
119
14
  black: "#000000",
120
15
  transparent: "transparent",
@@ -199,6 +199,41 @@ describe("parseLayout - overflow utilities", () => {
199
199
  });
200
200
  });
201
201
 
202
+ describe("parseLayout - opacity utilities", () => {
203
+ it("should parse opacity-0 (fully transparent)", () => {
204
+ expect(parseLayout("opacity-0")).toEqual({ opacity: 0 });
205
+ });
206
+
207
+ it("should parse opacity-50 (half transparent)", () => {
208
+ expect(parseLayout("opacity-50")).toEqual({ opacity: 0.5 });
209
+ });
210
+
211
+ it("should parse opacity-100 (fully opaque)", () => {
212
+ expect(parseLayout("opacity-100")).toEqual({ opacity: 1 });
213
+ });
214
+
215
+ it("should parse all opacity values", () => {
216
+ expect(parseLayout("opacity-5")).toEqual({ opacity: 0.05 });
217
+ expect(parseLayout("opacity-10")).toEqual({ opacity: 0.1 });
218
+ expect(parseLayout("opacity-15")).toEqual({ opacity: 0.15 });
219
+ expect(parseLayout("opacity-20")).toEqual({ opacity: 0.2 });
220
+ expect(parseLayout("opacity-25")).toEqual({ opacity: 0.25 });
221
+ expect(parseLayout("opacity-30")).toEqual({ opacity: 0.3 });
222
+ expect(parseLayout("opacity-35")).toEqual({ opacity: 0.35 });
223
+ expect(parseLayout("opacity-40")).toEqual({ opacity: 0.4 });
224
+ expect(parseLayout("opacity-45")).toEqual({ opacity: 0.45 });
225
+ expect(parseLayout("opacity-55")).toEqual({ opacity: 0.55 });
226
+ expect(parseLayout("opacity-60")).toEqual({ opacity: 0.6 });
227
+ expect(parseLayout("opacity-65")).toEqual({ opacity: 0.65 });
228
+ expect(parseLayout("opacity-70")).toEqual({ opacity: 0.7 });
229
+ expect(parseLayout("opacity-75")).toEqual({ opacity: 0.75 });
230
+ expect(parseLayout("opacity-80")).toEqual({ opacity: 0.8 });
231
+ expect(parseLayout("opacity-85")).toEqual({ opacity: 0.85 });
232
+ expect(parseLayout("opacity-90")).toEqual({ opacity: 0.9 });
233
+ expect(parseLayout("opacity-95")).toEqual({ opacity: 0.95 });
234
+ });
235
+ });
236
+
202
237
  describe("parseLayout - edge cases", () => {
203
238
  it("should return null for invalid classes", () => {
204
239
  expect(parseLayout("invalid")).toBeNull();
@@ -146,6 +146,31 @@ const OVERFLOW_MAP: Record<string, StyleObject> = {
146
146
  "overflow-scroll": { overflow: "scroll" },
147
147
  };
148
148
 
149
+ // Opacity utilities
150
+ const OPACITY_MAP: Record<string, StyleObject> = {
151
+ "opacity-0": { opacity: 0 },
152
+ "opacity-5": { opacity: 0.05 },
153
+ "opacity-10": { opacity: 0.1 },
154
+ "opacity-15": { opacity: 0.15 },
155
+ "opacity-20": { opacity: 0.2 },
156
+ "opacity-25": { opacity: 0.25 },
157
+ "opacity-30": { opacity: 0.3 },
158
+ "opacity-35": { opacity: 0.35 },
159
+ "opacity-40": { opacity: 0.4 },
160
+ "opacity-45": { opacity: 0.45 },
161
+ "opacity-50": { opacity: 0.5 },
162
+ "opacity-55": { opacity: 0.55 },
163
+ "opacity-60": { opacity: 0.6 },
164
+ "opacity-65": { opacity: 0.65 },
165
+ "opacity-70": { opacity: 0.7 },
166
+ "opacity-75": { opacity: 0.75 },
167
+ "opacity-80": { opacity: 0.8 },
168
+ "opacity-85": { opacity: 0.85 },
169
+ "opacity-90": { opacity: 0.9 },
170
+ "opacity-95": { opacity: 0.95 },
171
+ "opacity-100": { opacity: 1 },
172
+ };
173
+
149
174
  // Z-index scale
150
175
  export const Z_INDEX_SCALE: Record<string, number> = {
151
176
  0: 0,
@@ -343,6 +368,7 @@ export function parseLayout(cls: string): StyleObject | null {
343
368
  ALIGN_CONTENT_MAP[cls] ??
344
369
  POSITION_MAP[cls] ??
345
370
  OVERFLOW_MAP[cls] ??
371
+ OPACITY_MAP[cls] ??
346
372
  null
347
373
  );
348
374
  }