@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.
- package/README.md +459 -39
- package/dist/babel/index.cjs +810 -279
- package/dist/babel/index.d.ts +2 -1
- package/dist/babel/index.ts +328 -22
- package/dist/components/Pressable.d.ts +32 -0
- package/dist/components/Pressable.js +1 -0
- package/dist/components/TextInput.d.ts +56 -0
- package/dist/components/TextInput.js +1 -0
- package/dist/index.d.ts +9 -2
- package/dist/index.js +1 -1
- package/dist/parser/aspectRatio.d.ts +16 -0
- package/dist/parser/aspectRatio.js +1 -0
- package/dist/parser/aspectRatio.test.d.ts +1 -0
- package/dist/parser/aspectRatio.test.js +1 -0
- package/dist/parser/borders.js +1 -1
- package/dist/parser/borders.test.d.ts +1 -0
- package/dist/parser/borders.test.js +1 -0
- package/dist/parser/colors.d.ts +1 -0
- package/dist/parser/colors.js +1 -1
- package/dist/parser/colors.test.d.ts +1 -0
- package/dist/parser/colors.test.js +1 -0
- package/dist/parser/index.d.ts +4 -0
- package/dist/parser/index.js +1 -1
- package/dist/parser/layout.d.ts +2 -0
- package/dist/parser/layout.js +1 -1
- package/dist/parser/layout.test.d.ts +1 -0
- package/dist/parser/layout.test.js +1 -0
- package/dist/parser/modifiers.d.ts +47 -0
- package/dist/parser/modifiers.js +1 -0
- package/dist/parser/modifiers.test.d.ts +1 -0
- package/dist/parser/modifiers.test.js +1 -0
- package/dist/parser/shadows.d.ts +26 -0
- package/dist/parser/shadows.js +1 -0
- package/dist/parser/shadows.test.d.ts +1 -0
- package/dist/parser/shadows.test.js +1 -0
- package/dist/parser/sizing.test.d.ts +1 -0
- package/dist/parser/sizing.test.js +1 -0
- package/dist/parser/spacing.d.ts +1 -1
- package/dist/parser/spacing.js +1 -1
- package/dist/parser/spacing.test.d.ts +1 -0
- package/dist/parser/spacing.test.js +1 -0
- package/dist/parser/typography.d.ts +2 -1
- package/dist/parser/typography.js +1 -1
- package/dist/parser/typography.test.d.ts +1 -0
- package/dist/parser/typography.test.js +1 -0
- package/dist/types.d.ts +5 -2
- package/package.json +7 -6
- package/src/babel/index.ts +328 -22
- package/src/components/Pressable.tsx +46 -0
- package/src/components/TextInput.tsx +90 -0
- package/src/index.ts +20 -2
- package/src/parser/aspectRatio.test.ts +191 -0
- package/src/parser/aspectRatio.ts +73 -0
- package/src/parser/borders.test.ts +329 -0
- package/src/parser/borders.ts +187 -108
- package/src/parser/colors.test.ts +335 -0
- package/src/parser/colors.ts +117 -6
- package/src/parser/index.ts +13 -2
- package/src/parser/layout.test.ts +459 -0
- package/src/parser/layout.ts +128 -0
- package/src/parser/modifiers.test.ts +375 -0
- package/src/parser/modifiers.ts +104 -0
- package/src/parser/shadows.test.ts +201 -0
- package/src/parser/shadows.ts +133 -0
- package/src/parser/sizing.test.ts +256 -0
- package/src/parser/spacing.test.ts +226 -0
- package/src/parser/spacing.ts +93 -138
- package/src/parser/typography.test.ts +221 -0
- package/src/parser/typography.ts +143 -112
- package/src/types.ts +2 -2
- package/dist/react-native.d.js +0 -1
package/src/index.ts
CHANGED
|
@@ -11,10 +11,28 @@ export { generateStyleKey } from "./utils/styleKey";
|
|
|
11
11
|
export type { RNStyle, StyleObject } from "./types";
|
|
12
12
|
|
|
13
13
|
// Re-export individual parsers for advanced usage
|
|
14
|
-
export {
|
|
14
|
+
export {
|
|
15
|
+
parseAspectRatio,
|
|
16
|
+
parseBorder,
|
|
17
|
+
parseColor,
|
|
18
|
+
parseLayout,
|
|
19
|
+
parseShadow,
|
|
20
|
+
parseSizing,
|
|
21
|
+
parseSpacing,
|
|
22
|
+
parseTypography,
|
|
23
|
+
} from "./parser";
|
|
15
24
|
|
|
16
25
|
// Re-export constants for customization
|
|
26
|
+
export { ASPECT_RATIO_PRESETS } from "./parser/aspectRatio";
|
|
17
27
|
export { COLORS } from "./parser/colors";
|
|
28
|
+
export { INSET_SCALE, Z_INDEX_SCALE } from "./parser/layout";
|
|
29
|
+
export { SHADOW_SCALE } from "./parser/shadows";
|
|
18
30
|
export { SIZE_PERCENTAGES, SIZE_SCALE } from "./parser/sizing";
|
|
19
31
|
export { SPACING_SCALE } from "./parser/spacing";
|
|
20
|
-
export { FONT_SIZES } from "./parser/typography";
|
|
32
|
+
export { FONT_SIZES, LETTER_SPACING_SCALE } from "./parser/typography";
|
|
33
|
+
|
|
34
|
+
// Re-export enhanced components with modifier support
|
|
35
|
+
export { Pressable } from "./components/Pressable";
|
|
36
|
+
export type { PressableProps } from "./components/Pressable";
|
|
37
|
+
export { TextInput } from "./components/TextInput";
|
|
38
|
+
export type { TextInputProps } from "./components/TextInput";
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { ASPECT_RATIO_PRESETS, parseAspectRatio } from "./aspectRatio";
|
|
3
|
+
|
|
4
|
+
describe("ASPECT_RATIO_PRESETS", () => {
|
|
5
|
+
it("should export aspect ratio presets", () => {
|
|
6
|
+
expect(ASPECT_RATIO_PRESETS).toMatchSnapshot();
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
it("should have all preset values", () => {
|
|
10
|
+
expect(ASPECT_RATIO_PRESETS).toHaveProperty("aspect-auto");
|
|
11
|
+
expect(ASPECT_RATIO_PRESETS).toHaveProperty("aspect-square");
|
|
12
|
+
expect(ASPECT_RATIO_PRESETS).toHaveProperty("aspect-video");
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it("should have correct preset values", () => {
|
|
16
|
+
expect(ASPECT_RATIO_PRESETS["aspect-auto"]).toBeUndefined();
|
|
17
|
+
expect(ASPECT_RATIO_PRESETS["aspect-square"]).toBe(1);
|
|
18
|
+
expect(ASPECT_RATIO_PRESETS["aspect-video"]).toBe(16 / 9);
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
describe("parseAspectRatio - preset values", () => {
|
|
23
|
+
it("should parse aspect-square", () => {
|
|
24
|
+
expect(parseAspectRatio("aspect-square")).toEqual({ aspectRatio: 1 });
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it("should parse aspect-video", () => {
|
|
28
|
+
expect(parseAspectRatio("aspect-video")).toEqual({ aspectRatio: 16 / 9 });
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it("should parse aspect-auto", () => {
|
|
32
|
+
// aspect-auto removes the aspect ratio constraint
|
|
33
|
+
expect(parseAspectRatio("aspect-auto")).toEqual({});
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
describe("parseAspectRatio - arbitrary values", () => {
|
|
38
|
+
it("should parse arbitrary aspect ratio values", () => {
|
|
39
|
+
expect(parseAspectRatio("aspect-[4/3]")).toEqual({ aspectRatio: 4 / 3 });
|
|
40
|
+
expect(parseAspectRatio("aspect-[16/9]")).toEqual({ aspectRatio: 16 / 9 });
|
|
41
|
+
expect(parseAspectRatio("aspect-[21/9]")).toEqual({ aspectRatio: 21 / 9 });
|
|
42
|
+
expect(parseAspectRatio("aspect-[1/1]")).toEqual({ aspectRatio: 1 });
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it("should handle arbitrary ratios with different aspect values", () => {
|
|
46
|
+
expect(parseAspectRatio("aspect-[2/1]")).toEqual({ aspectRatio: 2 });
|
|
47
|
+
expect(parseAspectRatio("aspect-[3/2]")).toEqual({ aspectRatio: 1.5 });
|
|
48
|
+
expect(parseAspectRatio("aspect-[9/16]")).toEqual({ aspectRatio: 9 / 16 });
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it("should handle arbitrary ratios with large numbers", () => {
|
|
52
|
+
expect(parseAspectRatio("aspect-[100/50]")).toEqual({ aspectRatio: 2 });
|
|
53
|
+
expect(parseAspectRatio("aspect-[1920/1080]")).toEqual({ aspectRatio: 1920 / 1080 });
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it("should calculate correct aspect ratio values", () => {
|
|
57
|
+
const result = parseAspectRatio("aspect-[4/3]");
|
|
58
|
+
expect(result?.aspectRatio).toBeCloseTo(1.333, 3);
|
|
59
|
+
|
|
60
|
+
const result2 = parseAspectRatio("aspect-[16/9]");
|
|
61
|
+
expect(result2?.aspectRatio).toBeCloseTo(1.778, 3);
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
describe("parseAspectRatio - edge cases", () => {
|
|
66
|
+
it("should return null for division by zero", () => {
|
|
67
|
+
expect(parseAspectRatio("aspect-[4/0]")).toBeNull();
|
|
68
|
+
expect(parseAspectRatio("aspect-[16/0]")).toBeNull();
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it("should return null for invalid arbitrary values", () => {
|
|
72
|
+
expect(parseAspectRatio("aspect-[4]")).toBeNull(); // Missing denominator
|
|
73
|
+
expect(parseAspectRatio("aspect-[/3]")).toBeNull(); // Missing numerator
|
|
74
|
+
expect(parseAspectRatio("aspect-[4/3/2]")).toBeNull(); // Extra slash
|
|
75
|
+
expect(parseAspectRatio("aspect-[abc/def]")).toBeNull(); // Non-numeric
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it("should return null for malformed brackets", () => {
|
|
79
|
+
expect(parseAspectRatio("aspect-[4/3")).toBeNull(); // Missing closing bracket
|
|
80
|
+
expect(parseAspectRatio("aspect-4/3]")).toBeNull(); // Missing opening bracket
|
|
81
|
+
expect(parseAspectRatio("aspect-4/3")).toBeNull(); // No brackets
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it("should return null for invalid class prefixes", () => {
|
|
85
|
+
expect(parseAspectRatio("ratio-[4/3]")).toBeNull();
|
|
86
|
+
expect(parseAspectRatio("ar-[4/3]")).toBeNull();
|
|
87
|
+
expect(parseAspectRatio("aspectRatio-[4/3]")).toBeNull();
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
describe("parseAspectRatio - invalid classes", () => {
|
|
92
|
+
it("should return null for non-aspect classes", () => {
|
|
93
|
+
expect(parseAspectRatio("bg-blue-500")).toBeNull();
|
|
94
|
+
expect(parseAspectRatio("p-4")).toBeNull();
|
|
95
|
+
expect(parseAspectRatio("text-white")).toBeNull();
|
|
96
|
+
expect(parseAspectRatio("w-full")).toBeNull();
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it("should return null for invalid aspect class names", () => {
|
|
100
|
+
expect(parseAspectRatio("aspect")).toBeNull();
|
|
101
|
+
expect(parseAspectRatio("aspect-")).toBeNull();
|
|
102
|
+
expect(parseAspectRatio("aspect-invalid")).toBeNull();
|
|
103
|
+
expect(parseAspectRatio("aspect-16-9")).toBeNull();
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it("should return null for empty or whitespace input", () => {
|
|
107
|
+
expect(parseAspectRatio("")).toBeNull();
|
|
108
|
+
expect(parseAspectRatio(" ")).toBeNull();
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
describe("parseAspectRatio - type validation", () => {
|
|
113
|
+
it("should return objects with correct property types", () => {
|
|
114
|
+
const square = parseAspectRatio("aspect-square");
|
|
115
|
+
expect(typeof square?.aspectRatio).toBe("number");
|
|
116
|
+
|
|
117
|
+
const video = parseAspectRatio("aspect-video");
|
|
118
|
+
expect(typeof video?.aspectRatio).toBe("number");
|
|
119
|
+
|
|
120
|
+
const arbitrary = parseAspectRatio("aspect-[4/3]");
|
|
121
|
+
expect(typeof arbitrary?.aspectRatio).toBe("number");
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it("should return null or object, never undefined", () => {
|
|
125
|
+
const valid = parseAspectRatio("aspect-square");
|
|
126
|
+
expect(valid).not.toBeUndefined();
|
|
127
|
+
expect(typeof valid).toBe("object");
|
|
128
|
+
|
|
129
|
+
const invalid = parseAspectRatio("invalid");
|
|
130
|
+
expect(invalid).toBeNull();
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
describe("parseAspectRatio - comprehensive coverage", () => {
|
|
135
|
+
it("should parse all preset variants without errors", () => {
|
|
136
|
+
const presets = ["aspect-auto", "aspect-square", "aspect-video"];
|
|
137
|
+
|
|
138
|
+
presets.forEach((preset) => {
|
|
139
|
+
const result = parseAspectRatio(preset);
|
|
140
|
+
expect(result).toBeTruthy();
|
|
141
|
+
expect(typeof result).toBe("object");
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
it("should return consistent results for same input", () => {
|
|
146
|
+
const result1 = parseAspectRatio("aspect-square");
|
|
147
|
+
const result2 = parseAspectRatio("aspect-square");
|
|
148
|
+
expect(result1).toEqual(result2);
|
|
149
|
+
|
|
150
|
+
const result3 = parseAspectRatio("aspect-[4/3]");
|
|
151
|
+
const result4 = parseAspectRatio("aspect-[4/3]");
|
|
152
|
+
expect(result3).toEqual(result4);
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
it("should handle case-sensitive class names", () => {
|
|
156
|
+
// Aspect ratio classes are case-sensitive
|
|
157
|
+
expect(parseAspectRatio("ASPECT-square")).toBeNull();
|
|
158
|
+
expect(parseAspectRatio("Aspect-video")).toBeNull();
|
|
159
|
+
expect(parseAspectRatio("aspect-SQUARE")).toBeNull();
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
it("should handle common aspect ratios", () => {
|
|
163
|
+
// Common aspect ratios
|
|
164
|
+
expect(parseAspectRatio("aspect-[1/1]")).toBeTruthy(); // Square
|
|
165
|
+
expect(parseAspectRatio("aspect-[4/3]")).toBeTruthy(); // Standard
|
|
166
|
+
expect(parseAspectRatio("aspect-[16/9]")).toBeTruthy(); // Widescreen
|
|
167
|
+
expect(parseAspectRatio("aspect-[21/9]")).toBeTruthy(); // Ultrawide
|
|
168
|
+
expect(parseAspectRatio("aspect-[9/16]")).toBeTruthy(); // Portrait video
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
it("should differentiate between preset and arbitrary values", () => {
|
|
172
|
+
// Preset
|
|
173
|
+
const preset = parseAspectRatio("aspect-video");
|
|
174
|
+
expect(preset).toEqual({ aspectRatio: 16 / 9 });
|
|
175
|
+
|
|
176
|
+
// Arbitrary with same ratio
|
|
177
|
+
const arbitrary = parseAspectRatio("aspect-[16/9]");
|
|
178
|
+
expect(arbitrary).toEqual({ aspectRatio: 16 / 9 });
|
|
179
|
+
|
|
180
|
+
// Both should produce same result
|
|
181
|
+
expect(preset).toEqual(arbitrary);
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
it("should handle fractional results correctly", () => {
|
|
185
|
+
const result = parseAspectRatio("aspect-[5/7]");
|
|
186
|
+
expect(result?.aspectRatio).toBeCloseTo(0.714, 3);
|
|
187
|
+
|
|
188
|
+
const result2 = parseAspectRatio("aspect-[3/4]");
|
|
189
|
+
expect(result2?.aspectRatio).toBe(0.75);
|
|
190
|
+
});
|
|
191
|
+
});
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Aspect ratio utilities for React Native
|
|
3
|
+
* Uses aspectRatio style property (React Native 0.71+)
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { StyleObject } from "../types";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Preset aspect ratios
|
|
10
|
+
*/
|
|
11
|
+
const ASPECT_RATIO_PRESETS: Record<string, number | undefined> = {
|
|
12
|
+
"aspect-auto": undefined, // Remove aspect ratio
|
|
13
|
+
"aspect-square": 1, // 1:1
|
|
14
|
+
"aspect-video": 16 / 9, // 16:9
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Parse arbitrary aspect ratio value: aspect-[4/3]
|
|
19
|
+
* @param value - Arbitrary value string (e.g., "[4/3]", "[16/9]")
|
|
20
|
+
* @returns Aspect ratio number or null
|
|
21
|
+
*/
|
|
22
|
+
function parseArbitraryAspectRatio(value: string): number | null {
|
|
23
|
+
const match = value.match(/^\[(\d+)\/(\d+)\]$/);
|
|
24
|
+
if (match) {
|
|
25
|
+
const numerator = Number.parseInt(match[1], 10);
|
|
26
|
+
const denominator = Number.parseInt(match[2], 10);
|
|
27
|
+
|
|
28
|
+
if (denominator === 0) {
|
|
29
|
+
if (process.env.NODE_ENV !== "production") {
|
|
30
|
+
console.warn(`[react-native-tailwind] Invalid aspect ratio: ${value}. Denominator cannot be zero.`);
|
|
31
|
+
}
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return numerator / denominator;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Parse aspect ratio classes
|
|
43
|
+
* @param cls - Class name to parse
|
|
44
|
+
* @returns Style object or null if not an aspect ratio class
|
|
45
|
+
*/
|
|
46
|
+
export function parseAspectRatio(cls: string): StyleObject | null {
|
|
47
|
+
if (!cls.startsWith("aspect-")) {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Check for preset values
|
|
52
|
+
if (cls in ASPECT_RATIO_PRESETS) {
|
|
53
|
+
const aspectRatio = ASPECT_RATIO_PRESETS[cls];
|
|
54
|
+
// aspect-auto removes the aspect ratio constraint by returning empty object
|
|
55
|
+
// (this effectively unsets the aspectRatio property)
|
|
56
|
+
if (aspectRatio === undefined) {
|
|
57
|
+
return {};
|
|
58
|
+
}
|
|
59
|
+
return { aspectRatio };
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Check for arbitrary values: aspect-[4/3]
|
|
63
|
+
const arbitraryValue = cls.substring(7); // Remove "aspect-"
|
|
64
|
+
const aspectRatio = parseArbitraryAspectRatio(arbitraryValue);
|
|
65
|
+
if (aspectRatio !== null) {
|
|
66
|
+
return { aspectRatio };
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Export presets for testing/advanced usage
|
|
73
|
+
export { ASPECT_RATIO_PRESETS };
|
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { BORDER_RADIUS_SCALE, BORDER_WIDTH_SCALE, parseBorder } from "./borders";
|
|
3
|
+
|
|
4
|
+
describe("BORDER_WIDTH_SCALE", () => {
|
|
5
|
+
it("should export complete border width scale", () => {
|
|
6
|
+
expect(BORDER_WIDTH_SCALE).toMatchSnapshot();
|
|
7
|
+
});
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
describe("BORDER_RADIUS_SCALE", () => {
|
|
11
|
+
it("should export complete border radius scale", () => {
|
|
12
|
+
expect(BORDER_RADIUS_SCALE).toMatchSnapshot();
|
|
13
|
+
});
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
describe("parseBorder - border width all sides", () => {
|
|
17
|
+
it("should parse border shorthand", () => {
|
|
18
|
+
expect(parseBorder("border")).toEqual({ borderWidth: 1 });
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it("should parse border with preset values", () => {
|
|
22
|
+
expect(parseBorder("border-0")).toEqual({ borderWidth: 0 });
|
|
23
|
+
expect(parseBorder("border-2")).toEqual({ borderWidth: 2 });
|
|
24
|
+
expect(parseBorder("border-4")).toEqual({ borderWidth: 4 });
|
|
25
|
+
expect(parseBorder("border-8")).toEqual({ borderWidth: 8 });
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it("should parse border with arbitrary pixel values", () => {
|
|
29
|
+
expect(parseBorder("border-[1px]")).toEqual({ borderWidth: 1 });
|
|
30
|
+
expect(parseBorder("border-[1]")).toEqual({ borderWidth: 1 });
|
|
31
|
+
expect(parseBorder("border-[3px]")).toEqual({ borderWidth: 3 });
|
|
32
|
+
expect(parseBorder("border-[10px]")).toEqual({ borderWidth: 10 });
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
describe("parseBorder - border width directional", () => {
|
|
37
|
+
it("should parse border top", () => {
|
|
38
|
+
expect(parseBorder("border-t")).toEqual({ borderTopWidth: 1 });
|
|
39
|
+
expect(parseBorder("border-t-0")).toEqual({ borderTopWidth: 0 });
|
|
40
|
+
expect(parseBorder("border-t-2")).toEqual({ borderTopWidth: 2 });
|
|
41
|
+
expect(parseBorder("border-t-4")).toEqual({ borderTopWidth: 4 });
|
|
42
|
+
expect(parseBorder("border-t-8")).toEqual({ borderTopWidth: 8 });
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it("should parse border right", () => {
|
|
46
|
+
expect(parseBorder("border-r")).toEqual({ borderRightWidth: 1 });
|
|
47
|
+
expect(parseBorder("border-r-0")).toEqual({ borderRightWidth: 0 });
|
|
48
|
+
expect(parseBorder("border-r-2")).toEqual({ borderRightWidth: 2 });
|
|
49
|
+
expect(parseBorder("border-r-4")).toEqual({ borderRightWidth: 4 });
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it("should parse border bottom", () => {
|
|
53
|
+
expect(parseBorder("border-b")).toEqual({ borderBottomWidth: 1 });
|
|
54
|
+
expect(parseBorder("border-b-0")).toEqual({ borderBottomWidth: 0 });
|
|
55
|
+
expect(parseBorder("border-b-2")).toEqual({ borderBottomWidth: 2 });
|
|
56
|
+
expect(parseBorder("border-b-4")).toEqual({ borderBottomWidth: 4 });
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it("should parse border left", () => {
|
|
60
|
+
expect(parseBorder("border-l")).toEqual({ borderLeftWidth: 1 });
|
|
61
|
+
expect(parseBorder("border-l-0")).toEqual({ borderLeftWidth: 0 });
|
|
62
|
+
expect(parseBorder("border-l-2")).toEqual({ borderLeftWidth: 2 });
|
|
63
|
+
expect(parseBorder("border-l-4")).toEqual({ borderLeftWidth: 4 });
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it("should parse directional borders with arbitrary values", () => {
|
|
67
|
+
expect(parseBorder("border-t-[3px]")).toEqual({ borderTopWidth: 3 });
|
|
68
|
+
expect(parseBorder("border-r-[5px]")).toEqual({ borderRightWidth: 5 });
|
|
69
|
+
expect(parseBorder("border-b-[7px]")).toEqual({ borderBottomWidth: 7 });
|
|
70
|
+
expect(parseBorder("border-l-[9px]")).toEqual({ borderLeftWidth: 9 });
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
describe("parseBorder - border style", () => {
|
|
75
|
+
it("should parse border styles", () => {
|
|
76
|
+
expect(parseBorder("border-solid")).toEqual({ borderStyle: "solid" });
|
|
77
|
+
expect(parseBorder("border-dotted")).toEqual({ borderStyle: "dotted" });
|
|
78
|
+
expect(parseBorder("border-dashed")).toEqual({ borderStyle: "dashed" });
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
describe("parseBorder - border radius all corners", () => {
|
|
83
|
+
it("should parse rounded shorthand", () => {
|
|
84
|
+
expect(parseBorder("rounded")).toEqual({ borderRadius: 4 });
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it("should parse rounded with preset values", () => {
|
|
88
|
+
expect(parseBorder("rounded-none")).toEqual({ borderRadius: 0 });
|
|
89
|
+
expect(parseBorder("rounded-sm")).toEqual({ borderRadius: 2 });
|
|
90
|
+
expect(parseBorder("rounded-md")).toEqual({ borderRadius: 6 });
|
|
91
|
+
expect(parseBorder("rounded-lg")).toEqual({ borderRadius: 8 });
|
|
92
|
+
expect(parseBorder("rounded-xl")).toEqual({ borderRadius: 12 });
|
|
93
|
+
expect(parseBorder("rounded-2xl")).toEqual({ borderRadius: 16 });
|
|
94
|
+
expect(parseBorder("rounded-3xl")).toEqual({ borderRadius: 24 });
|
|
95
|
+
expect(parseBorder("rounded-full")).toEqual({ borderRadius: 9999 });
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it("should parse rounded with arbitrary pixel values", () => {
|
|
99
|
+
expect(parseBorder("rounded-[5px]")).toEqual({ borderRadius: 5 });
|
|
100
|
+
expect(parseBorder("rounded-[10px]")).toEqual({ borderRadius: 10 });
|
|
101
|
+
expect(parseBorder("rounded-[15]")).toEqual({ borderRadius: 15 });
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
describe("parseBorder - border radius sides", () => {
|
|
106
|
+
it("should parse rounded top", () => {
|
|
107
|
+
expect(parseBorder("rounded-t")).toEqual({
|
|
108
|
+
borderTopLeftRadius: 4,
|
|
109
|
+
borderTopRightRadius: 4,
|
|
110
|
+
});
|
|
111
|
+
expect(parseBorder("rounded-t-lg")).toEqual({
|
|
112
|
+
borderTopLeftRadius: 8,
|
|
113
|
+
borderTopRightRadius: 8,
|
|
114
|
+
});
|
|
115
|
+
expect(parseBorder("rounded-t-[12px]")).toEqual({
|
|
116
|
+
borderTopLeftRadius: 12,
|
|
117
|
+
borderTopRightRadius: 12,
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it("should parse rounded right", () => {
|
|
122
|
+
expect(parseBorder("rounded-r")).toEqual({
|
|
123
|
+
borderTopRightRadius: 4,
|
|
124
|
+
borderBottomRightRadius: 4,
|
|
125
|
+
});
|
|
126
|
+
expect(parseBorder("rounded-r-lg")).toEqual({
|
|
127
|
+
borderTopRightRadius: 8,
|
|
128
|
+
borderBottomRightRadius: 8,
|
|
129
|
+
});
|
|
130
|
+
expect(parseBorder("rounded-r-[12px]")).toEqual({
|
|
131
|
+
borderTopRightRadius: 12,
|
|
132
|
+
borderBottomRightRadius: 12,
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
it("should parse rounded bottom", () => {
|
|
137
|
+
expect(parseBorder("rounded-b")).toEqual({
|
|
138
|
+
borderBottomLeftRadius: 4,
|
|
139
|
+
borderBottomRightRadius: 4,
|
|
140
|
+
});
|
|
141
|
+
expect(parseBorder("rounded-b-lg")).toEqual({
|
|
142
|
+
borderBottomLeftRadius: 8,
|
|
143
|
+
borderBottomRightRadius: 8,
|
|
144
|
+
});
|
|
145
|
+
expect(parseBorder("rounded-b-[12px]")).toEqual({
|
|
146
|
+
borderBottomLeftRadius: 12,
|
|
147
|
+
borderBottomRightRadius: 12,
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
it("should parse rounded left", () => {
|
|
152
|
+
expect(parseBorder("rounded-l")).toEqual({
|
|
153
|
+
borderTopLeftRadius: 4,
|
|
154
|
+
borderBottomLeftRadius: 4,
|
|
155
|
+
});
|
|
156
|
+
expect(parseBorder("rounded-l-lg")).toEqual({
|
|
157
|
+
borderTopLeftRadius: 8,
|
|
158
|
+
borderBottomLeftRadius: 8,
|
|
159
|
+
});
|
|
160
|
+
expect(parseBorder("rounded-l-[12px]")).toEqual({
|
|
161
|
+
borderTopLeftRadius: 12,
|
|
162
|
+
borderBottomLeftRadius: 12,
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
describe("parseBorder - border radius specific corners", () => {
|
|
168
|
+
it("should parse rounded top-left", () => {
|
|
169
|
+
expect(parseBorder("rounded-tl")).toEqual({ borderTopLeftRadius: 4 });
|
|
170
|
+
expect(parseBorder("rounded-tl-lg")).toEqual({ borderTopLeftRadius: 8 });
|
|
171
|
+
expect(parseBorder("rounded-tl-[12px]")).toEqual({
|
|
172
|
+
borderTopLeftRadius: 12,
|
|
173
|
+
});
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
it("should parse rounded top-right", () => {
|
|
177
|
+
expect(parseBorder("rounded-tr")).toEqual({ borderTopRightRadius: 4 });
|
|
178
|
+
expect(parseBorder("rounded-tr-lg")).toEqual({ borderTopRightRadius: 8 });
|
|
179
|
+
expect(parseBorder("rounded-tr-[12px]")).toEqual({
|
|
180
|
+
borderTopRightRadius: 12,
|
|
181
|
+
});
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
it("should parse rounded bottom-left", () => {
|
|
185
|
+
expect(parseBorder("rounded-bl")).toEqual({ borderBottomLeftRadius: 4 });
|
|
186
|
+
expect(parseBorder("rounded-bl-lg")).toEqual({ borderBottomLeftRadius: 8 });
|
|
187
|
+
expect(parseBorder("rounded-bl-[12px]")).toEqual({
|
|
188
|
+
borderBottomLeftRadius: 12,
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
it("should parse rounded bottom-right", () => {
|
|
193
|
+
expect(parseBorder("rounded-br")).toEqual({ borderBottomRightRadius: 4 });
|
|
194
|
+
expect(parseBorder("rounded-br-lg")).toEqual({
|
|
195
|
+
borderBottomRightRadius: 8,
|
|
196
|
+
});
|
|
197
|
+
expect(parseBorder("rounded-br-[12px]")).toEqual({
|
|
198
|
+
borderBottomRightRadius: 12,
|
|
199
|
+
});
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
describe("parseBorder - edge cases", () => {
|
|
204
|
+
it("should return null for invalid classes", () => {
|
|
205
|
+
expect(parseBorder("invalid")).toBeNull();
|
|
206
|
+
expect(parseBorder("border-")).toBeNull();
|
|
207
|
+
expect(parseBorder("rounded-")).toBeNull();
|
|
208
|
+
expect(parseBorder("borders-4")).toBeNull();
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
it("should return null for invalid border width values", () => {
|
|
212
|
+
expect(parseBorder("border-invalid")).toBeNull();
|
|
213
|
+
expect(parseBorder("border-3")).toBeNull(); // Not in scale
|
|
214
|
+
expect(parseBorder("border-16")).toBeNull(); // Not in scale
|
|
215
|
+
expect(parseBorder("border-t-3")).toBeNull(); // Not in scale
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
it("should return null for invalid border radius values", () => {
|
|
219
|
+
expect(parseBorder("rounded-invalid")).toBeNull();
|
|
220
|
+
expect(parseBorder("rounded-4xl")).toBeNull(); // Not in scale
|
|
221
|
+
expect(parseBorder("rounded-t-invalid")).toBeNull();
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
it("should return null for arbitrary values with unsupported units", () => {
|
|
225
|
+
expect(parseBorder("border-[2rem]")).toBeNull();
|
|
226
|
+
expect(parseBorder("border-[1em]")).toBeNull();
|
|
227
|
+
expect(parseBorder("rounded-[2rem]")).toBeNull();
|
|
228
|
+
expect(parseBorder("rounded-[1em]")).toBeNull();
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
it("should return null for malformed arbitrary values", () => {
|
|
232
|
+
expect(parseBorder("border-[8")).toBeNull();
|
|
233
|
+
expect(parseBorder("border-8]")).toBeNull();
|
|
234
|
+
expect(parseBorder("border-[]")).toBeNull();
|
|
235
|
+
expect(parseBorder("rounded-[12")).toBeNull();
|
|
236
|
+
expect(parseBorder("rounded-12]")).toBeNull();
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
it("should handle edge case values", () => {
|
|
240
|
+
expect(parseBorder("border-0")).toEqual({ borderWidth: 0 });
|
|
241
|
+
expect(parseBorder("border-t-0")).toEqual({ borderTopWidth: 0 });
|
|
242
|
+
expect(parseBorder("rounded-none")).toEqual({ borderRadius: 0 });
|
|
243
|
+
expect(parseBorder("rounded-full")).toEqual({ borderRadius: 9999 });
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
it("should not match partial class names", () => {
|
|
247
|
+
expect(parseBorder("myborder-4")).toBeNull();
|
|
248
|
+
expect(parseBorder("border-solid-extra")).toBeNull();
|
|
249
|
+
expect(parseBorder("myrounded-lg")).toBeNull();
|
|
250
|
+
});
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
describe("parseBorder - comprehensive coverage", () => {
|
|
254
|
+
it("should handle all border width directions with same value", () => {
|
|
255
|
+
expect(parseBorder("border-2")).toEqual({ borderWidth: 2 });
|
|
256
|
+
expect(parseBorder("border-t-2")).toEqual({ borderTopWidth: 2 });
|
|
257
|
+
expect(parseBorder("border-r-2")).toEqual({ borderRightWidth: 2 });
|
|
258
|
+
expect(parseBorder("border-b-2")).toEqual({ borderBottomWidth: 2 });
|
|
259
|
+
expect(parseBorder("border-l-2")).toEqual({ borderLeftWidth: 2 });
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
it("should handle all border radius types with same value", () => {
|
|
263
|
+
// All corners
|
|
264
|
+
expect(parseBorder("rounded-lg")).toEqual({ borderRadius: 8 });
|
|
265
|
+
|
|
266
|
+
// Sides
|
|
267
|
+
expect(parseBorder("rounded-t-lg")).toEqual({
|
|
268
|
+
borderTopLeftRadius: 8,
|
|
269
|
+
borderTopRightRadius: 8,
|
|
270
|
+
});
|
|
271
|
+
expect(parseBorder("rounded-r-lg")).toEqual({
|
|
272
|
+
borderTopRightRadius: 8,
|
|
273
|
+
borderBottomRightRadius: 8,
|
|
274
|
+
});
|
|
275
|
+
expect(parseBorder("rounded-b-lg")).toEqual({
|
|
276
|
+
borderBottomLeftRadius: 8,
|
|
277
|
+
borderBottomRightRadius: 8,
|
|
278
|
+
});
|
|
279
|
+
expect(parseBorder("rounded-l-lg")).toEqual({
|
|
280
|
+
borderTopLeftRadius: 8,
|
|
281
|
+
borderBottomLeftRadius: 8,
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
// Specific corners
|
|
285
|
+
expect(parseBorder("rounded-tl-lg")).toEqual({ borderTopLeftRadius: 8 });
|
|
286
|
+
expect(parseBorder("rounded-tr-lg")).toEqual({ borderTopRightRadius: 8 });
|
|
287
|
+
expect(parseBorder("rounded-bl-lg")).toEqual({ borderBottomLeftRadius: 8 });
|
|
288
|
+
expect(parseBorder("rounded-br-lg")).toEqual({
|
|
289
|
+
borderBottomRightRadius: 8,
|
|
290
|
+
});
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
it("should handle arbitrary values across all border width types", () => {
|
|
294
|
+
expect(parseBorder("border-[5px]")).toEqual({ borderWidth: 5 });
|
|
295
|
+
expect(parseBorder("border-t-[5px]")).toEqual({ borderTopWidth: 5 });
|
|
296
|
+
expect(parseBorder("border-r-[5px]")).toEqual({ borderRightWidth: 5 });
|
|
297
|
+
expect(parseBorder("border-b-[5px]")).toEqual({ borderBottomWidth: 5 });
|
|
298
|
+
expect(parseBorder("border-l-[5px]")).toEqual({ borderLeftWidth: 5 });
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
it("should handle arbitrary values across all border radius types", () => {
|
|
302
|
+
expect(parseBorder("rounded-[10px]")).toEqual({ borderRadius: 10 });
|
|
303
|
+
|
|
304
|
+
expect(parseBorder("rounded-t-[10px]")).toEqual({
|
|
305
|
+
borderTopLeftRadius: 10,
|
|
306
|
+
borderTopRightRadius: 10,
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
expect(parseBorder("rounded-tl-[10px]")).toEqual({
|
|
310
|
+
borderTopLeftRadius: 10,
|
|
311
|
+
});
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
it("should handle all border styles", () => {
|
|
315
|
+
expect(parseBorder("border-solid")).toEqual({ borderStyle: "solid" });
|
|
316
|
+
expect(parseBorder("border-dotted")).toEqual({ borderStyle: "dotted" });
|
|
317
|
+
expect(parseBorder("border-dashed")).toEqual({ borderStyle: "dashed" });
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
it("should handle shorthand classes correctly", () => {
|
|
321
|
+
expect(parseBorder("border")).toEqual({ borderWidth: 1 });
|
|
322
|
+
expect(parseBorder("rounded")).toEqual({ borderRadius: 4 });
|
|
323
|
+
expect(parseBorder("border-t")).toEqual({ borderTopWidth: 1 });
|
|
324
|
+
expect(parseBorder("rounded-t")).toEqual({
|
|
325
|
+
borderTopLeftRadius: 4,
|
|
326
|
+
borderTopRightRadius: 4,
|
|
327
|
+
});
|
|
328
|
+
});
|
|
329
|
+
});
|