Skip to content

Commit 79c29a2

Browse files
committed
feat: add fontSize and spacing extraction to babel config loader
Extract fontSize and spacing from tailwind.config alongside existing colors and fontFamily: - Convert string values to numbers ("18px" -> 18, "2rem" -> 32) - Update SUPPORTED_THEME_KEYS to include fontSize and spacing - Add tests for supported theme keys validation
1 parent 320a8cf commit 79c29a2

File tree

2 files changed

+54
-8
lines changed

2 files changed

+54
-8
lines changed

src/babel/config-loader.test.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ describe("config-loader", () => {
125125
vi.spyOn(fs, "existsSync").mockReturnValue(false);
126126

127127
const result = extractCustomTheme("/project/src/file.ts");
128-
expect(result).toEqual({ colors: {}, fontFamily: {}, fontSize: {} });
128+
expect(result).toEqual({ colors: {}, fontFamily: {}, fontSize: {}, spacing: {} });
129129
});
130130
});
131131

@@ -136,8 +136,9 @@ describe("config-loader", () => {
136136
theme: {
137137
extend: {
138138
colors: { brand: "#123456" },
139-
spacing: { "72": "18rem" }, // Unsupported
139+
spacing: { "72": "18rem" }, // Supported (now!)
140140
borderRadius: { xl: "1rem" }, // Unsupported
141+
lineHeight: { tight: "1.25" }, // Unsupported
141142
},
142143
screens: { tablet: "640px" }, // Unsupported
143144
},
@@ -150,8 +151,10 @@ describe("config-loader", () => {
150151
expect(consoleSpy).toHaveBeenCalledWith(
151152
expect.stringContaining("Unsupported theme configuration detected"),
152153
);
153-
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("theme.extend.spacing"));
154+
// spacing is now supported, so should NOT warn about it
155+
expect(consoleSpy).not.toHaveBeenCalledWith(expect.stringContaining("theme.extend.spacing"));
154156
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("theme.extend.borderRadius"));
157+
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("theme.extend.lineHeight"));
155158
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("theme.screens"));
156159
expect(consoleSpy).toHaveBeenCalledWith(
157160
expect.stringContaining("https://github.com/mgcrea/react-native-tailwind/issues/new"),
@@ -168,6 +171,7 @@ describe("config-loader", () => {
168171
colors: { brand: "#123456" },
169172
fontFamily: { custom: "CustomFont" },
170173
fontSize: { huge: "48px" },
174+
spacing: { "72": "18rem" },
171175
},
172176
},
173177
};
@@ -186,7 +190,7 @@ describe("config-loader", () => {
186190
const mockConfig = {
187191
theme: {
188192
extend: {
189-
spacing: { "72": "18rem" },
193+
borderRadius: { xl: "1rem" }, // Unsupported
190194
},
191195
},
192196
};

src/babel/config-loader.ts

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,21 @@ export type TailwindConfig = {
1515
colors?: Record<string, string | Record<string, string>>;
1616
fontFamily?: Record<string, string | string[]>;
1717
fontSize?: Record<string, string | number>;
18+
spacing?: Record<string, string | number>;
1819
[key: string]: unknown;
1920
};
2021
colors?: Record<string, string | Record<string, string>>;
2122
fontFamily?: Record<string, string | string[]>;
2223
fontSize?: Record<string, string | number>;
24+
spacing?: Record<string, string | number>;
2325
[key: string]: unknown;
2426
};
2527
};
2628

2729
/**
2830
* Theme keys currently supported by react-native-tailwind
2931
*/
30-
const SUPPORTED_THEME_KEYS = new Set(["colors", "fontFamily", "fontSize", "extend"]);
32+
const SUPPORTED_THEME_KEYS = new Set(["colors", "fontFamily", "fontSize", "spacing", "extend"]);
3133

3234
/**
3335
* Cache for warned config paths to avoid duplicate warnings
@@ -68,7 +70,7 @@ export function warnUnsupportedThemeKeys(config: TailwindConfig, configPath: str
6870
console.warn(
6971
`[react-native-tailwind] Unsupported theme configuration detected:\n` +
7072
` ${unsupportedKeys.join(", ")}\n\n` +
71-
` Currently supported: colors, fontFamily, fontSize\n\n` +
73+
` Currently supported: colors, fontFamily, fontSize, spacing\n\n` +
7274
` These extensions will be ignored. If you need support for these features,\n` +
7375
` please open an issue: https://github.com/mgcrea/react-native-tailwind/issues/new`,
7476
);
@@ -145,6 +147,7 @@ export type CustomTheme = {
145147
colors: Record<string, string>;
146148
fontFamily: Record<string, string>;
147149
fontSize: Record<string, number>;
150+
spacing: Record<string, number>;
148151
};
149152

150153
/**
@@ -156,12 +159,12 @@ export function extractCustomTheme(filename: string): CustomTheme {
156159
const configPath = findTailwindConfig(projectDir);
157160

158161
if (!configPath) {
159-
return { colors: {}, fontFamily: {}, fontSize: {} };
162+
return { colors: {}, fontFamily: {}, fontSize: {}, spacing: {} };
160163
}
161164

162165
const config = loadTailwindConfig(configPath);
163166
if (!config?.theme) {
164-
return { colors: {}, fontFamily: {}, fontSize: {} };
167+
return { colors: {}, fontFamily: {}, fontSize: {}, spacing: {} };
165168
}
166169

167170
// Warn about unsupported theme keys
@@ -229,9 +232,48 @@ export function extractCustomTheme(filename: string): CustomTheme {
229232
}
230233
}
231234

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+
232273
return {
233274
colors: flattenColors(colors),
234275
fontFamily: fontFamilyResult,
235276
fontSize: fontSizeResult,
277+
spacing: spacingResult,
236278
};
237279
}

0 commit comments

Comments
 (0)