@mgcrea/react-native-tailwind 0.2.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 (42) hide show
  1. package/README.md +576 -0
  2. package/dist/babel/config-loader.d.ts +25 -0
  3. package/dist/babel/config-loader.ts +134 -0
  4. package/dist/babel/index.cjs +1111 -0
  5. package/dist/babel/index.d.ts +16 -0
  6. package/dist/babel/index.ts +286 -0
  7. package/dist/index.d.ts +12 -0
  8. package/dist/index.js +1 -0
  9. package/dist/parser/borders.d.ts +10 -0
  10. package/dist/parser/borders.js +1 -0
  11. package/dist/parser/colors.d.ts +9 -0
  12. package/dist/parser/colors.js +1 -0
  13. package/dist/parser/index.d.ts +25 -0
  14. package/dist/parser/index.js +1 -0
  15. package/dist/parser/layout.d.ts +8 -0
  16. package/dist/parser/layout.js +1 -0
  17. package/dist/parser/sizing.d.ts +10 -0
  18. package/dist/parser/sizing.js +1 -0
  19. package/dist/parser/spacing.d.ts +10 -0
  20. package/dist/parser/spacing.js +1 -0
  21. package/dist/parser/typography.d.ts +9 -0
  22. package/dist/parser/typography.js +1 -0
  23. package/dist/react-native.d.js +1 -0
  24. package/dist/react-native.d.ts +138 -0
  25. package/dist/types.d.ts +11 -0
  26. package/dist/types.js +1 -0
  27. package/dist/utils/styleKey.d.ts +9 -0
  28. package/dist/utils/styleKey.js +1 -0
  29. package/package.json +83 -0
  30. package/src/babel/config-loader.ts +134 -0
  31. package/src/babel/index.ts +286 -0
  32. package/src/index.ts +20 -0
  33. package/src/parser/borders.ts +198 -0
  34. package/src/parser/colors.ts +160 -0
  35. package/src/parser/index.ts +71 -0
  36. package/src/parser/layout.ts +114 -0
  37. package/src/parser/sizing.ts +239 -0
  38. package/src/parser/spacing.ts +222 -0
  39. package/src/parser/typography.ts +156 -0
  40. package/src/react-native.d.ts +138 -0
  41. package/src/types.ts +15 -0
  42. package/src/utils/styleKey.ts +23 -0
package/README.md ADDED
@@ -0,0 +1,576 @@
1
+ # React Native Tailwind
2
+
3
+ <div align="center">
4
+
5
+ [![npm version](https://img.shields.io/npm/v/@mgcrea/react-native-tailwind.svg?style=for-the-badge)](https://www.npmjs.com/package/@mgcrea/react-native-tailwind)
6
+ [![npm downloads](https://img.shields.io/npm/dt/@mgcrea/react-native-tailwind.svg?style=for-the-badge)](https://www.npmjs.com/package/@mgcrea/react-native-tailwind)
7
+ [![license](https://img.shields.io/github/license/mgcrea/react-native-tailwind.svg?style=for-the-badge)](https://github.com/mgcrea/react-native-tailwind/blob/main/LICENSE)
8
+
9
+ </div>
10
+
11
+ ## Overview
12
+
13
+ Compile-time Tailwind CSS for React Native with zero runtime overhead. Transform `className` props to optimized `StyleSheet.create` calls at build time using a Babel plugin.
14
+
15
+ ## Features
16
+
17
+ - ⚡ **Zero runtime overhead** — All transformations happen at compile time
18
+ - 🎯 **Babel-only setup** — No Metro configuration required (like Reanimated)
19
+ - 📝 **TypeScript-first** — Full type safety and autocomplete support
20
+ - 🚀 **Optimized performance** — Uses `StyleSheet.create` for optimal React Native performance
21
+ - 📦 **Small bundle size** — Only includes actual styles used in your app
22
+ - 🔧 **No dependencies** — Direct-to-React-Native style generation without tailwindcss package
23
+ - 🎨 **Custom colors** — Extend the default palette via `tailwind.config.*`
24
+ - 📐 **Arbitrary values** — Use custom sizes and borders: `w-[123px]`, `rounded-[20px]`
25
+ - 📜 **Special style props** — Support for `contentContainerClassName`, `columnWrapperClassName`, and more
26
+
27
+ ## Installation
28
+
29
+ ```bash
30
+ npm install @mgcrea/react-native-tailwind
31
+ # or
32
+ yarn add @mgcrea/react-native-tailwind
33
+ # or
34
+ pnpm add @mgcrea/react-native-tailwind
35
+ ```
36
+
37
+ ## Setup
38
+
39
+ ### 1. Add Babel Plugin
40
+
41
+ Update your `babel.config.js`:
42
+
43
+ ```javascript
44
+ module.exports = {
45
+ presets: ["module:@react-native/babel-preset"],
46
+ plugins: [
47
+ "@mgcrea/react-native-tailwind/babel", // Add this line
48
+ ],
49
+ };
50
+ ```
51
+
52
+ ### 2. Enable TypeScript Support (TypeScript)
53
+
54
+ Create a type declaration file in your project to enable `className` prop autocomplete:
55
+
56
+ **Create `src/types/react-native-tailwind.d.ts`:**
57
+
58
+ ```typescript
59
+ import "@mgcrea/react-native-tailwind/react-native";
60
+ ```
61
+
62
+ This file will be automatically picked up by TypeScript and enables autocomplete for the `className` prop on all React Native components.
63
+
64
+ > **Why is this needed?** TypeScript module augmentation requires the declaration file to be part of your project's compilation context. This one-time setup ensures the `className` prop is recognized throughout your codebase.
65
+
66
+ ### 3. Start Using className
67
+
68
+ ```tsx
69
+ import { View, Text } from "react-native";
70
+
71
+ export function MyComponent() {
72
+ return (
73
+ <View className="flex-1 bg-gray-100 p-4">
74
+ <Text className="text-xl font-bold text-blue-500">Hello, Tailwind!</Text>
75
+ </View>
76
+ );
77
+ }
78
+ ```
79
+
80
+ ## How It Works
81
+
82
+ The Babel plugin transforms your code at compile time:
83
+
84
+ **Input** (what you write):
85
+
86
+ ```tsx
87
+ <View className="m-4 p-2 bg-blue-500 rounded-lg" />
88
+ <ScrollView contentContainerClassName="items-center gap-4" />
89
+ <FlatList columnWrapperClassName="gap-4" ListHeaderComponentClassName="p-4 bg-gray-100" />
90
+ ```
91
+
92
+ **Output** (what Babel generates):
93
+
94
+ ```tsx
95
+ import { StyleSheet } from "react-native";
96
+
97
+ <View style={styles._bg_blue_500_m_4_p_2_rounded_lg} />;
98
+ <ScrollView contentContainerStyle={styles._gap_4_items_center} />;
99
+ <FlatList columnWrapperStyle={styles._gap_4} ListHeaderComponentStyle={styles._bg_gray_100_p_4} />;
100
+
101
+ const styles = StyleSheet.create({
102
+ _bg_blue_500_m_4_p_2_rounded_lg: {
103
+ margin: 16,
104
+ padding: 8,
105
+ backgroundColor: "#3B82F6",
106
+ borderRadius: 8,
107
+ },
108
+ _gap_4_items_center: {
109
+ gap: 16,
110
+ alignItems: "center",
111
+ },
112
+ _gap_4: {
113
+ gap: 16,
114
+ },
115
+ _bg_gray_100_p_4: {
116
+ backgroundColor: "#F3F4F6",
117
+ padding: 16,
118
+ },
119
+ });
120
+ ```
121
+
122
+ ## API Reference
123
+
124
+ ### Spacing
125
+
126
+ **Margin & Padding:**
127
+
128
+ - `m-{size}`, `p-{size}` — All sides
129
+ - `mx-{size}`, `my-{size}`, `px-{size}`, `py-{size}` — Horizontal/vertical
130
+ - `mt-{size}`, `mr-{size}`, `mb-{size}`, `ml-{size}` — Directional margin
131
+ - `pt-{size}`, `pr-{size}`, `pb-{size}`, `pl-{size}` — Directional padding
132
+ - `gap-{size}` — Gap between flex items
133
+
134
+ **Available sizes:** `0`, `0.5`, `1`, `1.5`, `2`, `2.5`, `3`, `3.5`, `4`, `5`, `6`, `7`, `8`, `9`, `10`, `11`, `12`, `14`, `16`, `20`, `24`, `28`, `32`, `36`, `40`, `44`, `48`, `52`, `56`, `60`, `64`, `72`, `80`, `96`
135
+
136
+ ### Layout
137
+
138
+ **Flexbox:**
139
+
140
+ - `flex`, `flex-1`, `flex-auto`, `flex-none` — Flex sizing
141
+ - `flex-row`, `flex-row-reverse`, `flex-col`, `flex-col-reverse` — Direction
142
+ - `flex-wrap`, `flex-wrap-reverse`, `flex-nowrap` — Wrapping
143
+ - `items-start`, `items-end`, `items-center`, `items-baseline`, `items-stretch` — Align items
144
+ - `justify-start`, `justify-end`, `justify-center`, `justify-between`, `justify-around`, `justify-evenly` — Justify content
145
+ - `self-auto`, `self-start`, `self-end`, `self-center`, `self-stretch`, `self-baseline` — Align self
146
+ - `grow`, `grow-0`, `shrink`, `shrink-0` — Flex grow/shrink
147
+
148
+ **Other:**
149
+
150
+ - `absolute`, `relative` — Position
151
+ - `overflow-hidden`, `overflow-visible`, `overflow-scroll` — Overflow
152
+ - `flex`, `hidden` — Display
153
+
154
+ ### Colors
155
+
156
+ - `bg-{color}-{shade}` — Background color
157
+ - `text-{color}-{shade}` — Text color
158
+ - `border-{color}-{shade}` — Border color
159
+
160
+ **Available colors:** `gray`, `red`, `blue`, `green`, `yellow`, `purple`, `pink`, `orange`, `indigo`, `white`, `black`, `transparent`
161
+
162
+ **Available shades:** `50`, `100`, `200`, `300`, `400`, `500`, `600`, `700`, `800`, `900`
163
+
164
+ > **Note:** You can extend the color palette with custom colors via `tailwind.config.*` — see [Custom Colors](#custom-colors)
165
+
166
+ ### Typography
167
+
168
+ **Font Size:**
169
+
170
+ `text-xs`, `text-sm`, `text-base`, `text-lg`, `text-xl`, `text-2xl`, `text-3xl`, `text-4xl`, `text-5xl`, `text-6xl`, `text-7xl`, `text-8xl`, `text-9xl`
171
+
172
+ **Font Weight:**
173
+
174
+ `font-thin`, `font-extralight`, `font-light`, `font-normal`, `font-medium`, `font-semibold`, `font-bold`, `font-extrabold`, `font-black`
175
+
176
+ **Other:**
177
+
178
+ - `italic`, `not-italic` — Font style
179
+ - `text-left`, `text-center`, `text-right`, `text-justify` — Text alignment
180
+ - `underline`, `line-through`, `no-underline` — Text decoration
181
+ - `uppercase`, `lowercase`, `capitalize`, `normal-case` — Text transform
182
+ - `leading-none`, `leading-tight`, `leading-snug`, `leading-normal`, `leading-relaxed`, `leading-loose` — Line height
183
+
184
+ ### Borders
185
+
186
+ **Width:**
187
+
188
+ - `border`, `border-0`, `border-2`, `border-4`, `border-8` — All sides
189
+ - `border-t`, `border-r`, `border-b`, `border-l` (with variants `-0`, `-2`, `-4`, `-8`) — Directional
190
+ - `border-[8px]`, `border-t-[12px]` — Arbitrary values
191
+
192
+ **Radius:**
193
+
194
+ - `rounded-none`, `rounded-sm`, `rounded`, `rounded-md`, `rounded-lg`, `rounded-xl`, `rounded-2xl`, `rounded-3xl`, `rounded-full` — All corners
195
+ - `rounded-t`, `rounded-r`, `rounded-b`, `rounded-l` (with size variants) — Directional
196
+ - `rounded-tl`, `rounded-tr`, `rounded-bl`, `rounded-br` (with size variants) — Individual corners
197
+ - `rounded-[12px]`, `rounded-t-[8px]`, `rounded-tl-[16px]` — Arbitrary values
198
+
199
+ **Style:**
200
+
201
+ `border-solid`, `border-dotted`, `border-dashed`
202
+
203
+ ### Sizing
204
+
205
+ - `w-{size}`, `h-{size}` — Width/height
206
+ - `min-w-{size}`, `min-h-{size}` — Min width/height
207
+ - `max-w-{size}`, `max-h-{size}` — Max width/height
208
+
209
+ **Available sizes:**
210
+
211
+ - **Numeric:** `0`-`96` (same as spacing scale)
212
+ - **Fractional:** `1/2`, `1/3`, `2/3`, `1/4`, `3/4`, `1/5`, `2/5`, `3/5`, `4/5`, `1/6`, `2/6`, `3/6`, `4/6`, `5/6`
213
+ - **Special:** `full` (100%), `auto`
214
+ - **Arbitrary:** `w-[123px]`, `h-[50%]`, `min-w-[200px]`, `max-h-[80%]`
215
+
216
+ > **Note:** Arbitrary sizing supports pixel values (`[123px]` or `[123]`) and percentages (`[50%]`). Other units (`rem`, `em`, `vh`, `vw`) are not supported in React Native.
217
+
218
+ ## Usage Examples
219
+
220
+ ### Basic Example
221
+
222
+ ```tsx
223
+ import { View, Text } from "react-native";
224
+
225
+ export function MyComponent() {
226
+ return (
227
+ <View className="flex-1 bg-gray-100 p-4">
228
+ <Text className="text-xl font-bold text-blue-500">Hello, Tailwind!</Text>
229
+ </View>
230
+ );
231
+ }
232
+ ```
233
+
234
+ ### Card Component
235
+
236
+ ```tsx
237
+ import { View, Text, Pressable } from "react-native";
238
+
239
+ export function Card({ title, description, onPress }) {
240
+ return (
241
+ <View className="bg-white rounded-lg p-6 mb-4 border border-gray-200">
242
+ <Text className="text-xl font-semibold text-gray-900 mb-2">{title}</Text>
243
+ <Text className="text-base text-gray-600 mb-4">{description}</Text>
244
+ <Pressable className="bg-blue-500 px-4 py-2 rounded-lg items-center" onPress={onPress}>
245
+ <Text className="text-white font-semibold">Learn More</Text>
246
+ </Pressable>
247
+ </View>
248
+ );
249
+ }
250
+ ```
251
+
252
+ ### Combining with Inline Styles
253
+
254
+ You can use inline `style` prop alongside `className`:
255
+
256
+ ```tsx
257
+ <View className="flex-1 p-4 bg-blue-500" style={{ paddingTop: safeAreaInsets.top }}>
258
+ <Text>Content</Text>
259
+ </View>
260
+ ```
261
+
262
+ The Babel plugin will merge them:
263
+
264
+ ```tsx
265
+ <View style={[styles._className_styles, { paddingTop: safeAreaInsets.top }]}>
266
+ <Text>Content</Text>
267
+ </View>
268
+ ```
269
+
270
+ ### ScrollView Content Container
271
+
272
+ Use `contentContainerClassName` to style the ScrollView's content container:
273
+
274
+ ```tsx
275
+ import { ScrollView, View, Text } from "react-native";
276
+
277
+ export function MyScrollView() {
278
+ return (
279
+ <ScrollView className="flex-1 bg-gray-100" contentContainerClassName="items-center p-4 gap-4">
280
+ <View className="bg-white rounded-lg p-4">
281
+ <Text className="text-lg">Item 1</Text>
282
+ </View>
283
+ <View className="bg-white rounded-lg p-4">
284
+ <Text className="text-lg">Item 2</Text>
285
+ </View>
286
+ </ScrollView>
287
+ );
288
+ }
289
+ ```
290
+
291
+ ### FlatList with Column Wrapper
292
+
293
+ Use `columnWrapperClassName` for multi-column FlatLists:
294
+
295
+ ```tsx
296
+ import { FlatList, View, Text } from "react-native";
297
+
298
+ export function GridList({ items }) {
299
+ return (
300
+ <FlatList
301
+ className="flex-1 bg-gray-100"
302
+ contentContainerClassName="p-4"
303
+ columnWrapperClassName="gap-4 mb-4"
304
+ numColumns={2}
305
+ data={items}
306
+ renderItem={({ item }) => (
307
+ <View className="flex-1 bg-white rounded-lg p-4">
308
+ <Text className="text-lg">{item.name}</Text>
309
+ </View>
310
+ )}
311
+ />
312
+ );
313
+ }
314
+ ```
315
+
316
+ ### FlatList with Header and Footer
317
+
318
+ Use `ListHeaderComponentClassName` and `ListFooterComponentClassName`:
319
+
320
+ ```tsx
321
+ import { FlatList, View, Text } from "react-native";
322
+
323
+ export function ListWithHeaderFooter({ items }) {
324
+ return (
325
+ <FlatList
326
+ className="flex-1"
327
+ contentContainerClassName="p-4"
328
+ ListHeaderComponentClassName="p-4 bg-blue-500 mb-4 rounded-lg"
329
+ ListFooterComponentClassName="p-4 bg-gray-200 mt-4 rounded-lg"
330
+ data={items}
331
+ ListHeaderComponent={<Text className="text-white font-bold">Header</Text>}
332
+ ListFooterComponent={<Text className="text-gray-600">End of list</Text>}
333
+ renderItem={({ item }) => (
334
+ <View className="bg-white rounded-lg p-4 mb-2">
335
+ <Text>{item.name}</Text>
336
+ </View>
337
+ )}
338
+ />
339
+ );
340
+ }
341
+ ```
342
+
343
+ ## Architecture
344
+
345
+ ### Compile-Time Transformation
346
+
347
+ The Babel plugin performs all transformations during build time, ensuring zero runtime overhead:
348
+
349
+ 1. **AST Transformation** — Visits JSX elements and finds `className` attributes
350
+ 2. **Static Analysis** — Only processes string literals (dynamic values produce warnings)
351
+ 3. **Style Registry** — Collects all className → style mappings per file
352
+ 4. **Code Generation** — Injects `StyleSheet.create()` at end of file
353
+ 5. **Import Management** — Adds `StyleSheet` import if needed
354
+
355
+ ### Performance Characteristics
356
+
357
+ | Metric | Value |
358
+ | ---------------- | ------------------ |
359
+ | Runtime Overhead | 0ms (compile-time) |
360
+ | Bundle Size | ~4KB typical |
361
+ | Build Time | +50-200ms |
362
+
363
+ **Why it's fast:**
364
+
365
+ - ⚡ All className parsing happens at build time
366
+ - 🎯 Uses React Native's optimized `StyleSheet.create` API
367
+ - 📦 Tree shaking — only includes styles actually used
368
+ - 🔄 Deduplication — identical styles reused across components
369
+
370
+ ## Limitations
371
+
372
+ **Dynamic class names are not supported** — The Babel plugin can only transform static string literals:
373
+
374
+ ```tsx
375
+ // ❌ This will NOT work
376
+ const spacing = 4;
377
+ <View className={`m-${spacing} p-2`} />
378
+
379
+ // ✅ Use inline styles for dynamic values
380
+ <View className="p-2" style={{ margin: spacing * 4 }} />
381
+ ```
382
+
383
+ For dynamic styling, use the `style` prop alongside `className`.
384
+
385
+ ## Advanced
386
+
387
+ ### Arbitrary Values
388
+
389
+ Use arbitrary values for custom sizes and borders not in the preset scales:
390
+
391
+ ```tsx
392
+ <View className="w-[350px] h-[85%] border-[3px] rounded-[20px]" />
393
+ ```
394
+
395
+ **Supported:**
396
+
397
+ - **Sizing:** `w-[...]`, `h-[...]`, `min-w-[...]`, `min-h-[...]`, `max-w-[...]`, `max-h-[...]`
398
+ - **Border width:** `border-[...]`, `border-t-[...]`, `border-r-[...]`, `border-b-[...]`, `border-l-[...]`
399
+ - **Border radius:** `rounded-[...]`, `rounded-t-[...]`, `rounded-tl-[...]`, etc.
400
+
401
+ **Formats:**
402
+
403
+ - Pixels: `[123px]` or `[123]`
404
+ - Percentages: `[50%]`, `[33.333%]`
405
+
406
+ > **Note:** Only `px` and `%` units are supported. CSS units (`rem`, `em`, `vh`, `vw`) are not supported by React Native.
407
+
408
+ ### Custom Colors
409
+
410
+ Extend the default color palette via `tailwind.config.*` in your project root:
411
+
412
+ ```javascript
413
+ // tailwind.config.mjs
414
+ export default {
415
+ theme: {
416
+ extend: {
417
+ colors: {
418
+ primary: "#1d4ed8",
419
+ secondary: "#9333ea",
420
+ brand: {
421
+ light: "#f0f9ff",
422
+ DEFAULT: "#0284c7",
423
+ dark: "#0c4a6e",
424
+ },
425
+ },
426
+ },
427
+ },
428
+ };
429
+ ```
430
+
431
+ Then use your custom colors:
432
+
433
+ ```tsx
434
+ <View className="bg-primary p-4">
435
+ <Text className="text-brand">Custom branded text</Text>
436
+ <View className="bg-brand-light rounded-lg" />
437
+ </View>
438
+ ```
439
+
440
+ **How it works:**
441
+
442
+ - Babel plugin discovers config by traversing up from source files
443
+ - Custom colors merged with defaults at build time (custom takes precedence)
444
+ - Nested objects flattened with dash notation: `brand.light` → `brand-light`
445
+ - Zero runtime overhead — all loading happens during compilation
446
+
447
+ **Supported formats:** `.js`, `.mjs`, `.cjs`, `.ts`
448
+
449
+ > **Tip:** Use `theme.extend.colors` to keep default Tailwind colors. Using `theme.colors` directly will override all defaults.
450
+
451
+ ### Programmatic API
452
+
453
+ Access the parser and constants programmatically:
454
+
455
+ ```typescript
456
+ import { parseClassName, COLORS, SPACING_SCALE } from "@mgcrea/react-native-tailwind";
457
+
458
+ // Parse className strings
459
+ const styles = parseClassName("m-4 p-2 bg-blue-500");
460
+ // Returns: { margin: 16, padding: 8, backgroundColor: '#3B82F6' }
461
+
462
+ // Access default scales
463
+ const blueColor = COLORS["blue-500"]; // '#3B82F6'
464
+ const spacing = SPACING_SCALE[4]; // 16
465
+ ```
466
+
467
+ ## Troubleshooting
468
+
469
+ ### TypeScript `className` Errors
470
+
471
+ If TypeScript doesn't recognize the `className` prop:
472
+
473
+ 1. Create the type declaration file:
474
+
475
+ ```typescript
476
+ // src/types/react-native-tailwind.d.ts
477
+ import "@mgcrea/react-native-tailwind/react-native";
478
+ ```
479
+
480
+ 2. Verify it's covered by your `tsconfig.json` `include` pattern
481
+ 3. Restart TypeScript server (VS Code: Cmd+Shift+P → "TypeScript: Restart TS Server")
482
+
483
+ ### Babel Plugin Not Working
484
+
485
+ **Clear Metro cache:**
486
+
487
+ ```bash
488
+ npx react-native start --reset-cache
489
+ ```
490
+
491
+ **Verify `babel.config.js`:**
492
+
493
+ ```javascript
494
+ plugins: ["@mgcrea/react-native-tailwind/babel"];
495
+ ```
496
+
497
+ ### Custom Colors Not Recognized
498
+
499
+ 1. **Config location** — Must be in project root or parent directory
500
+ 2. **Config format** — Verify proper export:
501
+
502
+ ```javascript
503
+ // CommonJS
504
+ module.exports = { theme: { extend: { colors: { ... } } } };
505
+
506
+ // ESM
507
+ export default { theme: { extend: { colors: { ... } } } };
508
+ ```
509
+
510
+ 3. **Clear cache** — Config changes require Metro cache reset
511
+ 4. **Use `theme.extend.colors`** — Don't use `theme.colors` directly (overrides defaults)
512
+
513
+ ## Development
514
+
515
+ ### Project Setup
516
+
517
+ ```bash
518
+ git clone https://github.com/mgcrea/react-native-tailwind.git
519
+ cd react-native-tailwind
520
+ pnpm install
521
+ ```
522
+
523
+ ### Build
524
+
525
+ ```bash
526
+ pnpm build # Full build
527
+ pnpm build:babel # Compile TypeScript
528
+ pnpm build:babel-plugin # Bundle Babel plugin
529
+ pnpm build:types # Generate type declarations
530
+ ```
531
+
532
+ ### Testing
533
+
534
+ ```bash
535
+ pnpm test # Run all tests
536
+ pnpm lint # ESLint
537
+ pnpm check # TypeScript type check
538
+ pnpm spec # Jest tests
539
+ ```
540
+
541
+ ### Example App
542
+
543
+ ```bash
544
+ pnpm dev # Run example app
545
+ cd example && npm run dev -- --reset-cache
546
+ ```
547
+
548
+ ## Authors
549
+
550
+ - [Olivier Louvignes](https://github.com/mgcrea) - [@mgcrea](https://twitter.com/mgcrea)
551
+
552
+ ## License
553
+
554
+ ```text
555
+ MIT License
556
+
557
+ Copyright (c) 2025 Olivier Louvignes <olivier@mgcrea.io>
558
+
559
+ Permission is hereby granted, free of charge, to any person obtaining a copy
560
+ of this software and associated documentation files (the "Software"), to deal
561
+ in the Software without restriction, including without limitation the rights
562
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
563
+ copies of the Software, and to permit persons to whom the Software is
564
+ furnished to do so, subject to the following conditions:
565
+
566
+ The above copyright notice and this permission notice shall be included in all
567
+ copies or substantial portions of the Software.
568
+
569
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
570
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
571
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
572
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
573
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
574
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
575
+ SOFTWARE.
576
+ ```
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Tailwind config loader for Babel plugin
3
+ * Discovers and loads tailwind.config.* files from the project
4
+ */
5
+ export type TailwindConfig = {
6
+ theme?: {
7
+ extend?: {
8
+ colors?: Record<string, string | Record<string, string>>;
9
+ };
10
+ colors?: Record<string, string | Record<string, string>>;
11
+ };
12
+ };
13
+ /**
14
+ * Find tailwind.config.* file by traversing up from startDir
15
+ */
16
+ export declare function findTailwindConfig(startDir: string): string | null;
17
+ /**
18
+ * Load and parse tailwind config file
19
+ */
20
+ export declare function loadTailwindConfig(configPath: string): TailwindConfig | null;
21
+ /**
22
+ * Extract custom colors from tailwind config
23
+ * Prefers theme.extend.colors over theme.colors to avoid overriding defaults
24
+ */
25
+ export declare function extractCustomColors(filename: string): Record<string, string>;