@mgcrea/react-native-tailwind 0.15.3 → 0.15.4

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.
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Shared color utilities for parsing and manipulating colors
3
+ */
4
+
5
+ import { TAILWIND_COLORS } from "../config/tailwind";
6
+ import { flattenColors } from "./flattenColors";
7
+
8
+ /**
9
+ * Tailwind color palette (flattened from config) with basic colors
10
+ */
11
+ export const COLORS: Record<string, string> = {
12
+ ...flattenColors(TAILWIND_COLORS),
13
+ white: "#FFFFFF",
14
+ black: "#000000",
15
+ transparent: "transparent",
16
+ };
17
+
18
+ /**
19
+ * Apply opacity to hex color by appending alpha channel
20
+ * @param hex - Hex color string (e.g., "#ff0000", "#f00", or "transparent")
21
+ * @param opacity - Opacity value 0-100 (e.g., 50 for 50%)
22
+ * @returns 8-digit hex with alpha (e.g., "#FF000080") or transparent
23
+ */
24
+ export function applyOpacity(hex: string, opacity: number): string {
25
+ if (hex === "transparent") {
26
+ return "transparent";
27
+ }
28
+
29
+ const cleanHex = hex.replace(/^#/, "");
30
+ const fullHex =
31
+ cleanHex.length === 3
32
+ ? cleanHex
33
+ .split("")
34
+ .map((char) => char + char)
35
+ .join("")
36
+ : cleanHex;
37
+
38
+ const alpha = Math.round((opacity / 100) * 255);
39
+ const alphaHex = alpha.toString(16).padStart(2, "0").toUpperCase();
40
+
41
+ return `#${fullHex.toUpperCase()}${alphaHex}`;
42
+ }
43
+
44
+ /**
45
+ * Parse arbitrary color value: [#ff0000], [#f00], [#FF0000AA]
46
+ * Supports 3-digit, 6-digit, and 8-digit (with alpha) hex colors
47
+ * @param value - Arbitrary value string like "[#ff0000]"
48
+ * @returns Hex string if valid, null otherwise (preserves input case)
49
+ */
50
+ export function parseArbitraryColor(value: string): string | null {
51
+ const hexMatch = value.match(/^\[#([0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})\]$/);
52
+ if (hexMatch) {
53
+ const hex = hexMatch[1];
54
+ if (hex.length === 3) {
55
+ // Expand 3-digit hex to 6-digit: #abc -> #aabbcc (preserve case)
56
+ const expanded = hex
57
+ .split("")
58
+ .map((char) => char + char)
59
+ .join("");
60
+ return `#${expanded}`;
61
+ }
62
+ return `#${hex}`;
63
+ }
64
+ return null;
65
+ }
66
+
67
+ /**
68
+ * Parse a color value with optional opacity modifier
69
+ * Handles preset colors, custom colors, arbitrary hex values, and opacity modifiers
70
+ *
71
+ * @param colorKey - Color key like "red-500", "red-500/50", "[#ff0000]", "[#ff0000]/80"
72
+ * @param customColors - Optional custom colors from tailwind.config
73
+ * @returns Hex color string or null if invalid
74
+ */
75
+ export function parseColorValue(colorKey: string, customColors?: Record<string, string>): string | null {
76
+ const getColor = (key: string): string | undefined => {
77
+ return customColors?.[key] ?? COLORS[key];
78
+ };
79
+
80
+ // Check for opacity modifier: red-500/50, [#ff0000]/80
81
+ const opacityMatch = colorKey.match(/^(.+)\/(\d+)$/);
82
+ if (opacityMatch) {
83
+ const baseColorKey = opacityMatch[1];
84
+ const opacity = Number.parseInt(opacityMatch[2], 10);
85
+
86
+ // Validate opacity range (0-100)
87
+ if (opacity < 0 || opacity > 100) {
88
+ return null;
89
+ }
90
+
91
+ // Try arbitrary color first: [#ff0000]/50
92
+ const arbitraryColor = parseArbitraryColor(baseColorKey);
93
+ if (arbitraryColor !== null) {
94
+ return applyOpacity(arbitraryColor, opacity);
95
+ }
96
+
97
+ // Try preset/custom colors: red-500/50
98
+ const color = getColor(baseColorKey);
99
+ if (color) {
100
+ return applyOpacity(color, opacity);
101
+ }
102
+
103
+ return null;
104
+ }
105
+
106
+ // No opacity modifier
107
+ // Try arbitrary value first: [#ff0000]
108
+ const arbitraryColor = parseArbitraryColor(colorKey);
109
+ if (arbitraryColor !== null) {
110
+ return arbitraryColor;
111
+ }
112
+
113
+ // Try preset/custom colors: red-500
114
+ return getColor(colorKey) ?? null;
115
+ }