@mgcrea/react-native-tailwind 0.13.0 → 0.15.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 +33 -30
- package/dist/babel/config-loader.d.ts +10 -0
- package/dist/babel/config-loader.test.ts +75 -21
- package/dist/babel/config-loader.ts +100 -2
- package/dist/babel/index.cjs +439 -46
- package/dist/babel/plugin/state.d.ts +4 -0
- package/dist/babel/plugin/state.ts +8 -0
- package/dist/babel/plugin/visitors/className.test.ts +313 -0
- package/dist/babel/plugin/visitors/className.ts +36 -8
- package/dist/babel/plugin/visitors/imports.ts +16 -1
- package/dist/babel/plugin/visitors/program.ts +19 -2
- package/dist/babel/plugin/visitors/tw.test.ts +151 -0
- package/dist/babel/utils/directionalModifierProcessing.d.ts +34 -0
- package/dist/babel/utils/directionalModifierProcessing.ts +99 -0
- package/dist/babel/utils/styleInjection.d.ts +16 -0
- package/dist/babel/utils/styleInjection.ts +138 -7
- package/dist/babel/utils/twProcessing.d.ts +2 -0
- package/dist/babel/utils/twProcessing.ts +92 -3
- package/dist/parser/borders.js +1 -1
- package/dist/parser/borders.test.js +1 -1
- package/dist/parser/index.d.ts +3 -2
- package/dist/parser/index.js +1 -1
- package/dist/parser/layout.d.ts +3 -1
- package/dist/parser/layout.js +1 -1
- package/dist/parser/layout.test.js +1 -1
- package/dist/parser/modifiers.d.ts +32 -2
- package/dist/parser/modifiers.js +1 -1
- package/dist/parser/modifiers.test.js +1 -1
- package/dist/parser/sizing.d.ts +3 -1
- package/dist/parser/sizing.js +1 -1
- package/dist/parser/sizing.test.js +1 -1
- package/dist/parser/spacing.d.ts +4 -2
- package/dist/parser/spacing.js +1 -1
- package/dist/parser/spacing.test.js +1 -1
- package/dist/parser/transforms.d.ts +3 -1
- package/dist/parser/transforms.js +1 -1
- package/dist/parser/transforms.test.js +1 -1
- package/dist/parser/typography.test.js +1 -1
- package/dist/runtime.cjs +1 -1
- package/dist/runtime.cjs.map +3 -3
- package/dist/runtime.d.ts +2 -0
- package/dist/runtime.js +1 -1
- package/dist/runtime.js.map +3 -3
- package/dist/runtime.test.js +1 -1
- package/package.json +6 -6
- package/src/babel/config-loader.test.ts +75 -21
- package/src/babel/config-loader.ts +100 -2
- package/src/babel/plugin/state.ts +8 -0
- package/src/babel/plugin/visitors/className.test.ts +313 -0
- package/src/babel/plugin/visitors/className.ts +36 -8
- package/src/babel/plugin/visitors/imports.ts +16 -1
- package/src/babel/plugin/visitors/program.ts +19 -2
- package/src/babel/plugin/visitors/tw.test.ts +151 -0
- package/src/babel/utils/directionalModifierProcessing.ts +99 -0
- package/src/babel/utils/styleInjection.ts +138 -7
- package/src/babel/utils/twProcessing.ts +92 -3
- package/src/parser/borders.test.ts +104 -0
- package/src/parser/borders.ts +50 -7
- package/src/parser/index.ts +8 -5
- package/src/parser/layout.test.ts +168 -0
- package/src/parser/layout.ts +107 -8
- package/src/parser/modifiers.test.ts +206 -0
- package/src/parser/modifiers.ts +62 -3
- package/src/parser/sizing.test.ts +56 -0
- package/src/parser/sizing.ts +20 -15
- package/src/parser/spacing.test.ts +123 -0
- package/src/parser/spacing.ts +30 -15
- package/src/parser/transforms.test.ts +57 -0
- package/src/parser/transforms.ts +7 -3
- package/src/parser/typography.test.ts +8 -0
- package/src/parser/typography.ts +4 -0
- package/src/runtime.test.ts +149 -0
- package/src/runtime.ts +53 -1
package/README.md
CHANGED
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
<img src="https://img.shields.io/codecov/c/github/mgcrea/react-native-tailwind?style=for-the-badge" alt="coverage" />
|
|
28
28
|
</a>
|
|
29
29
|
<a href="https://depfu.com/github/mgcrea/react-native-tailwind">
|
|
30
|
-
<img src="https://img.shields.io/
|
|
30
|
+
<img src="https://img.shields.io/badge/dependencies-none-brightgreen?style=for-the-badge" alt="dependencies status" />
|
|
31
31
|
</a>
|
|
32
32
|
</p>
|
|
33
33
|
|
|
@@ -37,22 +37,21 @@ Compile-time Tailwind CSS for React Native with zero runtime overhead. Transform
|
|
|
37
37
|
|
|
38
38
|
## Features
|
|
39
39
|
|
|
40
|
-
-
|
|
41
|
-
-
|
|
42
|
-
-
|
|
43
|
-
-
|
|
44
|
-
-
|
|
45
|
-
-
|
|
46
|
-
-
|
|
47
|
-
-
|
|
48
|
-
-
|
|
49
|
-
-
|
|
50
|
-
-
|
|
51
|
-
-
|
|
52
|
-
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
- 🎛️ **Custom attributes** — Configure which props to transform with exact matching or glob patterns
|
|
40
|
+
- **⚡ Zero Runtime Overhead** - All transformations happen at compile time
|
|
41
|
+
- **🔧 No Dependencies** - Direct-to-React-Native style generation without tailwindcss package
|
|
42
|
+
- **🎯 Babel-only Setup** - No Metro configuration required
|
|
43
|
+
- **📝 TypeScript-first** - Full type safety and autocomplete support
|
|
44
|
+
- **🚀 Optimized Performance** - Compiles down to StyleSheet.create for optimal performance
|
|
45
|
+
- **🔀 Dynamic className** - Conditional styles support with compile-time optimization
|
|
46
|
+
- **📦 Small Bundle Size** - Only includes actual styles used in your app
|
|
47
|
+
- **🎯 State Modifiers** - `active:`, `hover:`, `focus:`, and `disabled:` modifiers for interactive components
|
|
48
|
+
- **📱 Platform Modifiers** - `ios:`, `android:`, and `web:` modifiers for platform-specific styling
|
|
49
|
+
- **🌓 Color Scheme Modifiers** - `dark:` and `light:` and `scheme:` modifiers for automatic theme adaptation
|
|
50
|
+
- **🎨 Custom Colors** - Extend the default palette via tailwind.config.\*
|
|
51
|
+
- **📐 Arbitrary Values** - Use custom sizes and borders: `w-[123px]`, `rounded-[20px]`
|
|
52
|
+
- **📜 Special Style Props** - Support for `contentContainerClassName`, `columnWrapperClassName`, and more
|
|
53
|
+
|
|
54
|
+
📊 **[How It Compares](https://mgcrea.github.io/react-native-tailwind/getting-started/how-it-compares/)** - See how this library stacks up against other React Native styling solutions.
|
|
56
55
|
|
|
57
56
|
## Demo
|
|
58
57
|
|
|
@@ -113,7 +112,7 @@ The Babel plugin transforms your code at compile time:
|
|
|
113
112
|
**Input** (what you write):
|
|
114
113
|
|
|
115
114
|
```tsx
|
|
116
|
-
<View className=
|
|
115
|
+
<View className={`rounded-lg p-4 ${isSelected ? "bg-blue-500 border border-blue-700" : "bg-gray-200"}`} />
|
|
117
116
|
```
|
|
118
117
|
|
|
119
118
|
**Output** (what Babel generates):
|
|
@@ -121,15 +120,19 @@ The Babel plugin transforms your code at compile time:
|
|
|
121
120
|
```tsx
|
|
122
121
|
import { StyleSheet } from "react-native";
|
|
123
122
|
|
|
124
|
-
<View
|
|
123
|
+
<View
|
|
124
|
+
style={[
|
|
125
|
+
_twStyles._rounded_lg,
|
|
126
|
+
_twStyles._p_4,
|
|
127
|
+
isSelected ? _twStyles._bg_blue_500_border_border_blue_700 : _twStyles._bg_gray_200,
|
|
128
|
+
]}
|
|
129
|
+
/>;
|
|
125
130
|
|
|
126
131
|
const _twStyles = StyleSheet.create({
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
borderRadius: 8,
|
|
132
|
-
},
|
|
132
|
+
_rounded_lg: { borderRadius: 8 },
|
|
133
|
+
_p_4: { padding: 16 },
|
|
134
|
+
_bg_blue_500_border_border_blue_700: { backgroundColor: "#3B82F6", borderWidth: 1, borderColor: "#1D4ED8" },
|
|
135
|
+
_bg_gray_200: { backgroundColor: "#E5E7EB" },
|
|
133
136
|
});
|
|
134
137
|
```
|
|
135
138
|
|
|
@@ -200,9 +203,7 @@ import { View, Text } from "react-native";
|
|
|
200
203
|
export function PlatformCard() {
|
|
201
204
|
return (
|
|
202
205
|
<View className="p-4 ios:p-6 android:p-8 bg-white rounded-lg">
|
|
203
|
-
<Text className="text-base ios:text-blue-600 android:text-green-600">
|
|
204
|
-
Platform-specific styles
|
|
205
|
-
</Text>
|
|
206
|
+
<Text className="text-base ios:text-blue-600 android:text-green-600">Platform-specific styles</Text>
|
|
206
207
|
</View>
|
|
207
208
|
);
|
|
208
209
|
}
|
|
@@ -212,12 +213,14 @@ export function PlatformCard() {
|
|
|
212
213
|
|
|
213
214
|
Contributions are welcome! Please read our [Contributing Guide](https://mgcrea.github.io/react-native-tailwind/advanced/contributing/) for details.
|
|
214
215
|
|
|
216
|
+
## Credits
|
|
217
|
+
|
|
218
|
+
- [Tailwind CSS](https://tailwindcss.com/) - The utility-first CSS framework that revolutionized the way we style applications. If you enjoy this library, consider supporting them by purchasing [Tailwind Plus](https://tailwindcss.com/plus).
|
|
219
|
+
|
|
215
220
|
## Authors
|
|
216
221
|
|
|
217
222
|
- [Olivier Louvignes](https://github.com/mgcrea) - [@mgcrea](https://twitter.com/mgcrea)
|
|
218
223
|
|
|
219
|
-
## License
|
|
220
|
-
|
|
221
224
|
```text
|
|
222
225
|
MIT License
|
|
223
226
|
|
|
@@ -8,12 +8,21 @@ export type TailwindConfig = {
|
|
|
8
8
|
colors?: Record<string, string | Record<string, string>>;
|
|
9
9
|
fontFamily?: Record<string, string | string[]>;
|
|
10
10
|
fontSize?: Record<string, string | number>;
|
|
11
|
+
spacing?: Record<string, string | number>;
|
|
12
|
+
[key: string]: unknown;
|
|
11
13
|
};
|
|
12
14
|
colors?: Record<string, string | Record<string, string>>;
|
|
13
15
|
fontFamily?: Record<string, string | string[]>;
|
|
14
16
|
fontSize?: Record<string, string | number>;
|
|
17
|
+
spacing?: Record<string, string | number>;
|
|
18
|
+
[key: string]: unknown;
|
|
15
19
|
};
|
|
16
20
|
};
|
|
21
|
+
/**
|
|
22
|
+
* Check for unsupported theme extensions and warn the user
|
|
23
|
+
* @internal Exported for testing
|
|
24
|
+
*/
|
|
25
|
+
export declare function warnUnsupportedThemeKeys(config: TailwindConfig, configPath: string): void;
|
|
17
26
|
/**
|
|
18
27
|
* Find tailwind.config.* file by traversing up from startDir
|
|
19
28
|
*/
|
|
@@ -29,6 +38,7 @@ export type CustomTheme = {
|
|
|
29
38
|
colors: Record<string, string>;
|
|
30
39
|
fontFamily: Record<string, string>;
|
|
31
40
|
fontSize: Record<string, number>;
|
|
41
|
+
spacing: Record<string, number>;
|
|
32
42
|
};
|
|
33
43
|
/**
|
|
34
44
|
* Extract all custom theme extensions from tailwind config
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import * as fs from "fs";
|
|
2
2
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
extractCustomTheme,
|
|
5
|
+
findTailwindConfig,
|
|
6
|
+
loadTailwindConfig,
|
|
7
|
+
warnUnsupportedThemeKeys,
|
|
8
|
+
} from "./config-loader";
|
|
4
9
|
|
|
5
10
|
// Mock fs
|
|
6
11
|
vi.mock("fs");
|
|
@@ -120,35 +125,84 @@ describe("config-loader", () => {
|
|
|
120
125
|
vi.spyOn(fs, "existsSync").mockReturnValue(false);
|
|
121
126
|
|
|
122
127
|
const result = extractCustomTheme("/project/src/file.ts");
|
|
123
|
-
expect(result).toEqual({ colors: {}, fontFamily: {}, fontSize: {} });
|
|
128
|
+
expect(result).toEqual({ colors: {}, fontFamily: {}, fontSize: {}, spacing: {} });
|
|
124
129
|
});
|
|
130
|
+
});
|
|
125
131
|
|
|
126
|
-
|
|
127
|
-
|
|
132
|
+
describe("warnUnsupportedThemeKeys", () => {
|
|
133
|
+
it("should warn about unsupported theme keys", () => {
|
|
134
|
+
const configPath = "/project/unsupported/tailwind.config.js";
|
|
135
|
+
const mockConfig = {
|
|
136
|
+
theme: {
|
|
137
|
+
extend: {
|
|
138
|
+
colors: { brand: "#123456" },
|
|
139
|
+
spacing: { "72": "18rem" }, // Supported (now!)
|
|
140
|
+
borderRadius: { xl: "1rem" }, // Unsupported
|
|
141
|
+
lineHeight: { tight: "1.25" }, // Unsupported
|
|
142
|
+
},
|
|
143
|
+
screens: { tablet: "640px" }, // Unsupported
|
|
144
|
+
},
|
|
145
|
+
};
|
|
128
146
|
|
|
129
|
-
vi.spyOn(
|
|
130
|
-
vi.spyOn(require, "resolve").mockReturnValue(configPath);
|
|
147
|
+
const consoleSpy = vi.spyOn(console, "warn").mockImplementation(vi.fn());
|
|
131
148
|
|
|
132
|
-
|
|
133
|
-
// For integration, we'd need to mock the entire flow
|
|
134
|
-
const result = extractCustomTheme("/project/src/file.ts");
|
|
149
|
+
warnUnsupportedThemeKeys(mockConfig, configPath);
|
|
135
150
|
|
|
136
|
-
|
|
137
|
-
|
|
151
|
+
expect(consoleSpy).toHaveBeenCalledWith(
|
|
152
|
+
expect.stringContaining("Unsupported theme configuration detected"),
|
|
153
|
+
);
|
|
154
|
+
// spacing is now supported, so should NOT warn about it
|
|
155
|
+
expect(consoleSpy).not.toHaveBeenCalledWith(expect.stringContaining("theme.extend.spacing"));
|
|
156
|
+
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("theme.extend.borderRadius"));
|
|
157
|
+
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("theme.extend.lineHeight"));
|
|
158
|
+
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("theme.screens"));
|
|
159
|
+
expect(consoleSpy).toHaveBeenCalledWith(
|
|
160
|
+
expect.stringContaining("https://github.com/mgcrea/react-native-tailwind/issues/new"),
|
|
161
|
+
);
|
|
162
|
+
|
|
163
|
+
consoleSpy.mockRestore();
|
|
138
164
|
});
|
|
139
165
|
|
|
140
|
-
it("should
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
166
|
+
it("should not warn for supported theme keys only", () => {
|
|
167
|
+
const configPath = "/project/supported/tailwind.config.js";
|
|
168
|
+
const mockConfig = {
|
|
169
|
+
theme: {
|
|
170
|
+
extend: {
|
|
171
|
+
colors: { brand: "#123456" },
|
|
172
|
+
fontFamily: { custom: "CustomFont" },
|
|
173
|
+
fontSize: { huge: "48px" },
|
|
174
|
+
spacing: { "72": "18rem" },
|
|
175
|
+
},
|
|
176
|
+
},
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
const consoleSpy = vi.spyOn(console, "warn").mockImplementation(vi.fn());
|
|
180
|
+
|
|
181
|
+
warnUnsupportedThemeKeys(mockConfig, configPath);
|
|
182
|
+
|
|
183
|
+
expect(consoleSpy).not.toHaveBeenCalled();
|
|
184
|
+
|
|
185
|
+
consoleSpy.mockRestore();
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
it("should only warn once per config path", () => {
|
|
189
|
+
const configPath = "/project/once/tailwind.config.js";
|
|
190
|
+
const mockConfig = {
|
|
191
|
+
theme: {
|
|
192
|
+
extend: {
|
|
193
|
+
borderRadius: { xl: "1rem" }, // Unsupported
|
|
194
|
+
},
|
|
195
|
+
},
|
|
147
196
|
};
|
|
148
197
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
198
|
+
const consoleSpy = vi.spyOn(console, "warn").mockImplementation(vi.fn());
|
|
199
|
+
|
|
200
|
+
warnUnsupportedThemeKeys(mockConfig, configPath);
|
|
201
|
+
warnUnsupportedThemeKeys(mockConfig, configPath);
|
|
202
|
+
|
|
203
|
+
expect(consoleSpy).toHaveBeenCalledTimes(1);
|
|
204
|
+
|
|
205
|
+
consoleSpy.mockRestore();
|
|
152
206
|
});
|
|
153
207
|
});
|
|
154
208
|
});
|
|
@@ -15,13 +15,68 @@ export type TailwindConfig = {
|
|
|
15
15
|
colors?: Record<string, string | Record<string, string>>;
|
|
16
16
|
fontFamily?: Record<string, string | string[]>;
|
|
17
17
|
fontSize?: Record<string, string | number>;
|
|
18
|
+
spacing?: Record<string, string | number>;
|
|
19
|
+
[key: string]: unknown;
|
|
18
20
|
};
|
|
19
21
|
colors?: Record<string, string | Record<string, string>>;
|
|
20
22
|
fontFamily?: Record<string, string | string[]>;
|
|
21
23
|
fontSize?: Record<string, string | number>;
|
|
24
|
+
spacing?: Record<string, string | number>;
|
|
25
|
+
[key: string]: unknown;
|
|
22
26
|
};
|
|
23
27
|
};
|
|
24
28
|
|
|
29
|
+
/**
|
|
30
|
+
* Theme keys currently supported by react-native-tailwind
|
|
31
|
+
*/
|
|
32
|
+
const SUPPORTED_THEME_KEYS = new Set(["colors", "fontFamily", "fontSize", "spacing", "extend"]);
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Cache for warned config paths to avoid duplicate warnings
|
|
36
|
+
*/
|
|
37
|
+
const warnedConfigPaths = new Set<string>();
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Check for unsupported theme extensions and warn the user
|
|
41
|
+
* @internal Exported for testing
|
|
42
|
+
*/
|
|
43
|
+
export function warnUnsupportedThemeKeys(config: TailwindConfig, configPath: string): void {
|
|
44
|
+
if (process.env.NODE_ENV === "production" || warnedConfigPaths.has(configPath)) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const unsupportedKeys: string[] = [];
|
|
49
|
+
|
|
50
|
+
// Check theme.extend keys
|
|
51
|
+
if (config.theme?.extend && typeof config.theme.extend === "object") {
|
|
52
|
+
for (const key of Object.keys(config.theme.extend)) {
|
|
53
|
+
if (!SUPPORTED_THEME_KEYS.has(key)) {
|
|
54
|
+
unsupportedKeys.push(`theme.extend.${key}`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Check direct theme keys (excluding 'extend')
|
|
60
|
+
if (config.theme && typeof config.theme === "object") {
|
|
61
|
+
for (const key of Object.keys(config.theme)) {
|
|
62
|
+
if (key !== "extend" && !SUPPORTED_THEME_KEYS.has(key)) {
|
|
63
|
+
unsupportedKeys.push(`theme.${key}`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (unsupportedKeys.length > 0) {
|
|
69
|
+
warnedConfigPaths.add(configPath);
|
|
70
|
+
console.warn(
|
|
71
|
+
`[react-native-tailwind] Unsupported theme configuration detected:\n` +
|
|
72
|
+
` ${unsupportedKeys.join(", ")}\n\n` +
|
|
73
|
+
` Currently supported: colors, fontFamily, fontSize, spacing\n\n` +
|
|
74
|
+
` These extensions will be ignored. If you need support for these features,\n` +
|
|
75
|
+
` please open an issue: https://github.com/mgcrea/react-native-tailwind/issues/new`,
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
25
80
|
// Cache configs per path to avoid repeated file I/O
|
|
26
81
|
const configCache = new Map<string, TailwindConfig | null>();
|
|
27
82
|
|
|
@@ -92,6 +147,7 @@ export type CustomTheme = {
|
|
|
92
147
|
colors: Record<string, string>;
|
|
93
148
|
fontFamily: Record<string, string>;
|
|
94
149
|
fontSize: Record<string, number>;
|
|
150
|
+
spacing: Record<string, number>;
|
|
95
151
|
};
|
|
96
152
|
|
|
97
153
|
/**
|
|
@@ -103,14 +159,17 @@ export function extractCustomTheme(filename: string): CustomTheme {
|
|
|
103
159
|
const configPath = findTailwindConfig(projectDir);
|
|
104
160
|
|
|
105
161
|
if (!configPath) {
|
|
106
|
-
return { colors: {}, fontFamily: {}, fontSize: {} };
|
|
162
|
+
return { colors: {}, fontFamily: {}, fontSize: {}, spacing: {} };
|
|
107
163
|
}
|
|
108
164
|
|
|
109
165
|
const config = loadTailwindConfig(configPath);
|
|
110
166
|
if (!config?.theme) {
|
|
111
|
-
return { colors: {}, fontFamily: {}, fontSize: {} };
|
|
167
|
+
return { colors: {}, fontFamily: {}, fontSize: {}, spacing: {} };
|
|
112
168
|
}
|
|
113
169
|
|
|
170
|
+
// Warn about unsupported theme keys
|
|
171
|
+
warnUnsupportedThemeKeys(config, configPath);
|
|
172
|
+
|
|
114
173
|
// Extract colors
|
|
115
174
|
/* v8 ignore next 5 */
|
|
116
175
|
if (config.theme.colors && !config.theme.extend?.colors && process.env.NODE_ENV !== "production") {
|
|
@@ -173,9 +232,48 @@ export function extractCustomTheme(filename: string): CustomTheme {
|
|
|
173
232
|
}
|
|
174
233
|
}
|
|
175
234
|
|
|
235
|
+
// Extract spacing
|
|
236
|
+
/* v8 ignore next 5 */
|
|
237
|
+
if (config.theme.spacing && !config.theme.extend?.spacing && process.env.NODE_ENV !== "production") {
|
|
238
|
+
console.warn(
|
|
239
|
+
"[react-native-tailwind] Using theme.spacing will override all default spacing. " +
|
|
240
|
+
"Use theme.extend.spacing to add custom spacing while keeping defaults.",
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
const spacing = config.theme.extend?.spacing ?? config.theme.spacing ?? {};
|
|
244
|
+
|
|
245
|
+
// Convert spacing values to numbers (handle rem, px, or number values)
|
|
246
|
+
const spacingResult: Record<string, number> = {};
|
|
247
|
+
for (const [key, value] of Object.entries(spacing)) {
|
|
248
|
+
if (typeof value === "number") {
|
|
249
|
+
spacingResult[key] = value;
|
|
250
|
+
} else if (typeof value === "string") {
|
|
251
|
+
// Parse string values: "18rem" -> 288, "16px" -> 16, "16" -> 16
|
|
252
|
+
let parsed: number;
|
|
253
|
+
if (value.endsWith("rem")) {
|
|
254
|
+
// Convert rem to px (1rem = 16px)
|
|
255
|
+
parsed = parseFloat(value.replace(/rem$/, "")) * 16;
|
|
256
|
+
} else {
|
|
257
|
+
// Parse px or unitless values
|
|
258
|
+
parsed = parseFloat(value.replace(/px$/, ""));
|
|
259
|
+
}
|
|
260
|
+
if (!isNaN(parsed)) {
|
|
261
|
+
spacingResult[key] = parsed;
|
|
262
|
+
} else {
|
|
263
|
+
/* v8 ignore next 5 */
|
|
264
|
+
if (process.env.NODE_ENV !== "production") {
|
|
265
|
+
console.warn(
|
|
266
|
+
`[react-native-tailwind] Invalid spacing value for "${key}": ${value}. Expected number or string like "16px" or "1rem".`,
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
176
273
|
return {
|
|
177
274
|
colors: flattenColors(colors),
|
|
178
275
|
fontFamily: fontFamilyResult,
|
|
179
276
|
fontSize: fontSizeResult,
|
|
277
|
+
spacing: spacingResult,
|
|
180
278
|
};
|
|
181
279
|
}
|