@mgcrea/react-native-tailwind 0.6.1 → 0.7.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 +404 -0
- package/dist/babel/config-loader.ts +1 -23
- package/dist/babel/index.cjs +227 -60
- package/dist/babel/index.d.ts +27 -2
- package/dist/babel/index.test.ts +268 -0
- package/dist/babel/index.ts +352 -44
- package/dist/index.d.ts +3 -0
- package/dist/index.js +1 -1
- package/dist/parser/__snapshots__/colors.test.js.snap +242 -90
- package/dist/parser/__snapshots__/transforms.test.js.snap +58 -0
- package/dist/parser/colors.js +1 -1
- package/dist/runtime.cjs +2 -0
- package/dist/runtime.cjs.map +7 -0
- package/dist/runtime.d.ts +139 -0
- package/dist/runtime.js +2 -0
- package/dist/runtime.js.map +7 -0
- package/dist/runtime.test.js +1 -0
- package/dist/stubs/tw.d.ts +60 -0
- package/dist/stubs/tw.js +1 -0
- package/dist/utils/flattenColors.d.ts +16 -0
- package/dist/utils/flattenColors.js +1 -0
- package/dist/utils/flattenColors.test.js +1 -0
- package/dist/utils/modifiers.d.ts +29 -0
- package/dist/utils/modifiers.js +1 -0
- package/dist/utils/modifiers.test.js +1 -0
- package/dist/utils/styleKey.test.js +1 -0
- package/package.json +15 -3
- package/src/babel/config-loader.ts +1 -23
- package/src/babel/index.test.ts +268 -0
- package/src/babel/index.ts +352 -44
- package/src/index.ts +5 -0
- package/src/parser/colors.ts +8 -22
- package/src/runtime.test.ts +325 -0
- package/src/runtime.ts +280 -0
- package/src/stubs/tw.ts +80 -0
- package/src/utils/flattenColors.test.ts +361 -0
- package/src/utils/flattenColors.ts +32 -0
- package/src/utils/modifiers.test.ts +286 -0
- package/src/utils/modifiers.ts +63 -0
- package/src/utils/styleKey.test.ts +168 -0
package/README.md
CHANGED
|
@@ -43,8 +43,10 @@ Compile-time Tailwind CSS for React Native with zero runtime overhead. Transform
|
|
|
43
43
|
- 🎨 **Custom colors** — Extend the default palette via `tailwind.config.*`
|
|
44
44
|
- 📐 **Arbitrary values** — Use custom sizes and borders: `w-[123px]`, `rounded-[20px]`
|
|
45
45
|
- 🔀 **Dynamic className** — Conditional styles with hybrid compile-time optimization
|
|
46
|
+
- 🏃 **Runtime option** — Optional `tw` template tag for fully dynamic styling (~25KB)
|
|
46
47
|
- 🎯 **State modifiers** — `active:`, `hover:`, `focus:`, and `disabled:` modifiers for interactive components
|
|
47
48
|
- 📜 **Special style props** — Support for `contentContainerClassName`, `columnWrapperClassName`, and more
|
|
49
|
+
- 🎛️ **Custom attributes** — Configure which props to transform with exact matching or glob patterns
|
|
48
50
|
|
|
49
51
|
## Demo
|
|
50
52
|
|
|
@@ -75,6 +77,28 @@ module.exports = {
|
|
|
75
77
|
};
|
|
76
78
|
```
|
|
77
79
|
|
|
80
|
+
**Advanced:** You can customize which attributes are transformed and the generated styles identifier:
|
|
81
|
+
|
|
82
|
+
```javascript
|
|
83
|
+
module.exports = {
|
|
84
|
+
presets: ["module:@react-native/babel-preset"],
|
|
85
|
+
plugins: [
|
|
86
|
+
[
|
|
87
|
+
"@mgcrea/react-native-tailwind/babel",
|
|
88
|
+
{
|
|
89
|
+
// Specify which attributes to transform
|
|
90
|
+
// Default: ['className', 'contentContainerClassName', 'columnWrapperClassName', 'ListHeaderComponentClassName', 'ListFooterComponentClassName']
|
|
91
|
+
attributes: ["className", "buttonClassName", "containerClassName"],
|
|
92
|
+
|
|
93
|
+
// Custom identifier for the generated StyleSheet constant
|
|
94
|
+
// Default: '_twStyles'
|
|
95
|
+
stylesIdentifier: "styles",
|
|
96
|
+
},
|
|
97
|
+
],
|
|
98
|
+
],
|
|
99
|
+
};
|
|
100
|
+
```
|
|
101
|
+
|
|
78
102
|
### 2. Enable TypeScript Support (TypeScript)
|
|
79
103
|
|
|
80
104
|
Create a type declaration file in your project to enable `className` prop autocomplete:
|
|
@@ -301,6 +325,219 @@ The Babel plugin will merge them:
|
|
|
301
325
|
</View>
|
|
302
326
|
```
|
|
303
327
|
|
|
328
|
+
### Compile-Time `tw` Template Tag
|
|
329
|
+
|
|
330
|
+
For static or compile-time determinable styles, you can use the `tw` template tag that gets transformed by the Babel plugin. This provides **zero runtime overhead** as all styles are compiled to `StyleSheet.create` calls.
|
|
331
|
+
|
|
332
|
+
#### Import
|
|
333
|
+
|
|
334
|
+
```typescript
|
|
335
|
+
import { tw } from "@mgcrea/react-native-tailwind";
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
#### Basic Usage
|
|
339
|
+
|
|
340
|
+
```tsx
|
|
341
|
+
import { View, Text, Pressable } from "react-native";
|
|
342
|
+
import { tw } from "@mgcrea/react-native-tailwind";
|
|
343
|
+
|
|
344
|
+
// Static styles - transformed at compile time
|
|
345
|
+
const containerStyles = tw`flex-1 p-4 bg-gray-100`;
|
|
346
|
+
const buttonStyles = tw`p-4 rounded-lg bg-blue-500`;
|
|
347
|
+
const textStyles = tw`text-white font-bold text-center`;
|
|
348
|
+
|
|
349
|
+
export function Example() {
|
|
350
|
+
return (
|
|
351
|
+
<View style={containerStyles.style}>
|
|
352
|
+
<Pressable style={buttonStyles.style}>
|
|
353
|
+
<Text style={textStyles.style}>Click me</Text>
|
|
354
|
+
</Pressable>
|
|
355
|
+
</View>
|
|
356
|
+
);
|
|
357
|
+
}
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
#### With State Modifiers
|
|
361
|
+
|
|
362
|
+
The compile-time `tw` supports state modifiers (`active:`, `focus:`, `disabled:`) that return a `TwStyle` object with separate style properties:
|
|
363
|
+
|
|
364
|
+
```tsx
|
|
365
|
+
import { Pressable, Text } from "react-native";
|
|
366
|
+
import { tw } from "@mgcrea/react-native-tailwind";
|
|
367
|
+
|
|
368
|
+
const buttonStyles = tw`bg-blue-500 active:bg-blue-700 disabled:bg-gray-300`;
|
|
369
|
+
|
|
370
|
+
export function Button({ disabled }) {
|
|
371
|
+
return (
|
|
372
|
+
<Pressable
|
|
373
|
+
disabled={disabled}
|
|
374
|
+
style={(state) => [
|
|
375
|
+
buttonStyles.style,
|
|
376
|
+
state.pressed && buttonStyles.activeStyle,
|
|
377
|
+
disabled && buttonStyles.disabledStyle,
|
|
378
|
+
]}
|
|
379
|
+
>
|
|
380
|
+
<Text style={tw`text-white font-bold`.style}>Press me</Text>
|
|
381
|
+
</Pressable>
|
|
382
|
+
);
|
|
383
|
+
}
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
#### Transformation Example
|
|
387
|
+
|
|
388
|
+
The Babel plugin transforms your code at compile time:
|
|
389
|
+
|
|
390
|
+
```tsx
|
|
391
|
+
// Input
|
|
392
|
+
const styles = tw`bg-blue-500 active:bg-blue-700 m-4`;
|
|
393
|
+
|
|
394
|
+
// Compiled Output
|
|
395
|
+
const styles = {
|
|
396
|
+
style: _twStyles._bg_blue_500_m_4,
|
|
397
|
+
activeStyle: _twStyles._active_bg_blue_700,
|
|
398
|
+
};
|
|
399
|
+
|
|
400
|
+
const _twStyles = StyleSheet.create({
|
|
401
|
+
_bg_blue_500_m_4: { backgroundColor: "#2b7fff", margin: 16 },
|
|
402
|
+
_active_bg_blue_700: { backgroundColor: "#1854d6" },
|
|
403
|
+
});
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
### Runtime `tw` Template Tag
|
|
407
|
+
|
|
408
|
+
For cases where you need **fully dynamic styling** (values only known at runtime), you can use the runtime `tw` template tag function. This provides runtime parsing of Tailwind classes with memoization for performance.
|
|
409
|
+
|
|
410
|
+
> **Note:** Use the compile-time `tw` (imported from `@mgcrea/react-native-tailwind`) when possible for zero runtime overhead. Only use the runtime version (imported from `@mgcrea/react-native-tailwind/runtime`) when styles must be determined at runtime.
|
|
411
|
+
|
|
412
|
+
#### Installation
|
|
413
|
+
|
|
414
|
+
The runtime module is already included in the package. Import it separately:
|
|
415
|
+
|
|
416
|
+
```typescript
|
|
417
|
+
import { tw, setConfig } from "@mgcrea/react-native-tailwind/runtime";
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
#### Basic Usage
|
|
421
|
+
|
|
422
|
+
```tsx
|
|
423
|
+
import { View, Text, Pressable } from "react-native";
|
|
424
|
+
import { tw } from "@mgcrea/react-native-tailwind/runtime";
|
|
425
|
+
|
|
426
|
+
export function RuntimeExample() {
|
|
427
|
+
const [isActive, setIsActive] = useState(false);
|
|
428
|
+
|
|
429
|
+
return (
|
|
430
|
+
<View style={tw`flex-1 p-4 bg-gray-100`}>
|
|
431
|
+
<Pressable
|
|
432
|
+
onPress={() => setIsActive(!isActive)}
|
|
433
|
+
style={tw`p-4 rounded-lg ${isActive ? "bg-green-500" : "bg-red-500"}`}
|
|
434
|
+
>
|
|
435
|
+
<Text style={tw`text-white font-bold text-center`}>{isActive ? "Active" : "Inactive"}</Text>
|
|
436
|
+
</Pressable>
|
|
437
|
+
</View>
|
|
438
|
+
);
|
|
439
|
+
}
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
#### Configuration
|
|
443
|
+
|
|
444
|
+
Configure custom colors and other theme options using `setConfig()`:
|
|
445
|
+
|
|
446
|
+
```typescript
|
|
447
|
+
import { setConfig } from '@mgcrea/react-native-tailwind/runtime';
|
|
448
|
+
|
|
449
|
+
// Match your tailwind.config structure
|
|
450
|
+
setConfig({
|
|
451
|
+
theme: {
|
|
452
|
+
extend: {
|
|
453
|
+
colors: {
|
|
454
|
+
primary: '#007AFF',
|
|
455
|
+
secondary: '#5856D6',
|
|
456
|
+
brand: {
|
|
457
|
+
light: '#FF6B6B',
|
|
458
|
+
dark: '#CC0000',
|
|
459
|
+
},
|
|
460
|
+
},
|
|
461
|
+
},
|
|
462
|
+
},
|
|
463
|
+
});
|
|
464
|
+
|
|
465
|
+
// Now you can use custom colors
|
|
466
|
+
<View style={tw`bg-primary p-4`} />
|
|
467
|
+
<Text style={tw`text-brand-light`}>Custom color</Text>
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
#### API Reference
|
|
471
|
+
|
|
472
|
+
**`tw` tagged template**
|
|
473
|
+
|
|
474
|
+
```typescript
|
|
475
|
+
function tw(strings: TemplateStringsArray, ...values: unknown[]): TwStyle;
|
|
476
|
+
|
|
477
|
+
type TwStyle = {
|
|
478
|
+
style: ViewStyle | TextStyle | ImageStyle;
|
|
479
|
+
activeStyle?: ViewStyle | TextStyle | ImageStyle;
|
|
480
|
+
focusStyle?: ViewStyle | TextStyle | ImageStyle;
|
|
481
|
+
disabledStyle?: ViewStyle | TextStyle | ImageStyle;
|
|
482
|
+
};
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
Parses Tailwind classes at runtime and returns a `TwStyle` object with separate properties for base styles and state modifiers. Results are automatically memoized for performance.
|
|
486
|
+
|
|
487
|
+
**`twStyle(className: string)`**
|
|
488
|
+
|
|
489
|
+
```typescript
|
|
490
|
+
function twStyle(className: string): TwStyle | undefined;
|
|
491
|
+
```
|
|
492
|
+
|
|
493
|
+
String version for cases where template literals aren't needed. Returns `undefined` for empty strings.
|
|
494
|
+
|
|
495
|
+
**`setConfig(config: RuntimeConfig)`**
|
|
496
|
+
|
|
497
|
+
```typescript
|
|
498
|
+
function setConfig(config: RuntimeConfig): void;
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
Configure runtime theme settings (colors, etc.). Matches `tailwind.config.mjs` structure.
|
|
502
|
+
|
|
503
|
+
**`clearCache()`**
|
|
504
|
+
|
|
505
|
+
```typescript
|
|
506
|
+
function clearCache(): void;
|
|
507
|
+
```
|
|
508
|
+
|
|
509
|
+
Clears the internal memoization cache. Useful for testing.
|
|
510
|
+
|
|
511
|
+
**`getCacheStats()`**
|
|
512
|
+
|
|
513
|
+
```typescript
|
|
514
|
+
function getCacheStats(): { size: number; keys: string[] };
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
Returns cache statistics for debugging/monitoring.
|
|
518
|
+
|
|
519
|
+
#### Performance Considerations
|
|
520
|
+
|
|
521
|
+
- **Bundle Size**: The runtime module adds ~25KB minified (~15-20KB gzipped) to your bundle
|
|
522
|
+
- **Caching**: All parsed styles are automatically memoized, so repeated className strings have minimal overhead
|
|
523
|
+
- **When to Use**:
|
|
524
|
+
- ✅ Truly dynamic values that can't be determined at compile-time
|
|
525
|
+
- ✅ Prototyping and rapid development
|
|
526
|
+
- ❌ Static styles (use compile-time `className` instead for zero overhead)
|
|
527
|
+
- ❌ Performance-critical hot paths (compile-time is faster)
|
|
528
|
+
|
|
529
|
+
#### Runtime vs Compile-Time
|
|
530
|
+
|
|
531
|
+
| Feature | Compile-Time (`className`) | Runtime (`tw` tag) |
|
|
532
|
+
| -------------- | ------------------------------- | ----------------------- |
|
|
533
|
+
| Bundle Size | Only used styles (~4KB typical) | Full parser (~25KB) |
|
|
534
|
+
| Performance | Zero overhead (pre-compiled) | Fast (memoized parsing) |
|
|
535
|
+
| Dynamic Values | Conditional only | Fully dynamic |
|
|
536
|
+
| Custom Colors | Via `tailwind.config.*` | Via `setConfig()` |
|
|
537
|
+
| Type Safety | Full TypeScript support | Full TypeScript support |
|
|
538
|
+
|
|
539
|
+
**Recommendation**: Use compile-time `className` by default for best performance. Use runtime `tw` only when you need fully dynamic styling that can't be expressed with conditional logic.
|
|
540
|
+
|
|
304
541
|
### State Modifiers
|
|
305
542
|
|
|
306
543
|
Apply styles based on component state with zero runtime overhead. The Babel plugin automatically generates optimized style functions.
|
|
@@ -1000,6 +1237,173 @@ This limitation exists because the current parser architecture uses `Object.assi
|
|
|
1000
1237
|
|
|
1001
1238
|
## Advanced
|
|
1002
1239
|
|
|
1240
|
+
### Custom Attributes
|
|
1241
|
+
|
|
1242
|
+
By default, the Babel plugin transforms these className-like attributes to their corresponding style props:
|
|
1243
|
+
|
|
1244
|
+
- `className` → `style`
|
|
1245
|
+
- `contentContainerClassName` → `contentContainerStyle` (ScrollView, FlatList)
|
|
1246
|
+
- `columnWrapperClassName` → `columnWrapperStyle` (FlatList)
|
|
1247
|
+
- `ListHeaderComponentClassName` → `ListHeaderComponentStyle` (FlatList)
|
|
1248
|
+
- `ListFooterComponentClassName` → `ListFooterComponentStyle` (FlatList)
|
|
1249
|
+
|
|
1250
|
+
You can customize which attributes are transformed using the `attributes` plugin option:
|
|
1251
|
+
|
|
1252
|
+
**Exact Matches:**
|
|
1253
|
+
|
|
1254
|
+
```javascript
|
|
1255
|
+
// babel.config.js
|
|
1256
|
+
module.exports = {
|
|
1257
|
+
plugins: [
|
|
1258
|
+
[
|
|
1259
|
+
"@mgcrea/react-native-tailwind/babel",
|
|
1260
|
+
{
|
|
1261
|
+
attributes: ["className", "buttonClassName", "containerClassName"],
|
|
1262
|
+
},
|
|
1263
|
+
],
|
|
1264
|
+
],
|
|
1265
|
+
};
|
|
1266
|
+
```
|
|
1267
|
+
|
|
1268
|
+
**Pattern Matching:**
|
|
1269
|
+
|
|
1270
|
+
Use glob patterns to match multiple attributes:
|
|
1271
|
+
|
|
1272
|
+
```javascript
|
|
1273
|
+
// babel.config.js
|
|
1274
|
+
module.exports = {
|
|
1275
|
+
plugins: [
|
|
1276
|
+
[
|
|
1277
|
+
"@mgcrea/react-native-tailwind/babel",
|
|
1278
|
+
{
|
|
1279
|
+
// Matches any attribute ending in 'ClassName'
|
|
1280
|
+
attributes: ["*ClassName"],
|
|
1281
|
+
},
|
|
1282
|
+
],
|
|
1283
|
+
],
|
|
1284
|
+
};
|
|
1285
|
+
```
|
|
1286
|
+
|
|
1287
|
+
**Combined:**
|
|
1288
|
+
|
|
1289
|
+
```javascript
|
|
1290
|
+
// babel.config.js
|
|
1291
|
+
module.exports = {
|
|
1292
|
+
plugins: [
|
|
1293
|
+
[
|
|
1294
|
+
"@mgcrea/react-native-tailwind/babel",
|
|
1295
|
+
{
|
|
1296
|
+
// Mix exact matches and patterns
|
|
1297
|
+
attributes: [
|
|
1298
|
+
"className",
|
|
1299
|
+
"*ClassName", // containerClassName, buttonClassName, etc.
|
|
1300
|
+
"custom*", // customButton, customHeader, etc.
|
|
1301
|
+
],
|
|
1302
|
+
},
|
|
1303
|
+
],
|
|
1304
|
+
],
|
|
1305
|
+
};
|
|
1306
|
+
```
|
|
1307
|
+
|
|
1308
|
+
**Usage Example:**
|
|
1309
|
+
|
|
1310
|
+
```tsx
|
|
1311
|
+
// With custom attributes configured
|
|
1312
|
+
function Button({ title, onPress, buttonClassName, containerClassName }) {
|
|
1313
|
+
return (
|
|
1314
|
+
<View containerClassName="p-2 bg-gray-100">
|
|
1315
|
+
<Pressable buttonClassName="bg-blue-500 px-6 py-4 rounded-lg" onPress={onPress}>
|
|
1316
|
+
<Text className="text-white font-semibold">{title}</Text>
|
|
1317
|
+
</Pressable>
|
|
1318
|
+
</View>
|
|
1319
|
+
);
|
|
1320
|
+
}
|
|
1321
|
+
|
|
1322
|
+
// Transforms to:
|
|
1323
|
+
function Button({ title, onPress, buttonStyle, containerStyle }) {
|
|
1324
|
+
return (
|
|
1325
|
+
<View style={[_twStyles._bg_gray_100_p_2, containerStyle]}>
|
|
1326
|
+
<Pressable style={[_twStyles._bg_blue_500_px_6_py_4_rounded_lg, buttonStyle]} onPress={onPress}>
|
|
1327
|
+
<Text style={_twStyles._font_semibold_text_white}>{title}</Text>
|
|
1328
|
+
</Pressable>
|
|
1329
|
+
</View>
|
|
1330
|
+
);
|
|
1331
|
+
}
|
|
1332
|
+
```
|
|
1333
|
+
|
|
1334
|
+
**Naming Convention:**
|
|
1335
|
+
|
|
1336
|
+
Attributes ending in `ClassName` are automatically converted to their `Style` equivalent:
|
|
1337
|
+
|
|
1338
|
+
- `buttonClassName` → `buttonStyle`
|
|
1339
|
+
- `containerClassName` → `containerStyle`
|
|
1340
|
+
- `headerClassName` → `headerStyle`
|
|
1341
|
+
|
|
1342
|
+
For attributes not ending in `ClassName`, the `style` prop is used.
|
|
1343
|
+
|
|
1344
|
+
**TypeScript Support:**
|
|
1345
|
+
|
|
1346
|
+
When using custom attributes, you'll need to augment the component types to include your custom className props. See the [TypeScript section](#2-enable-typescript-support-typescript) for details on module augmentation.
|
|
1347
|
+
|
|
1348
|
+
### Custom Styles Identifier
|
|
1349
|
+
|
|
1350
|
+
By default, the Babel plugin generates a StyleSheet constant named `_twStyles`. You can customize this identifier to avoid conflicts or match your project's naming conventions:
|
|
1351
|
+
|
|
1352
|
+
```javascript
|
|
1353
|
+
// babel.config.js
|
|
1354
|
+
module.exports = {
|
|
1355
|
+
plugins: [
|
|
1356
|
+
[
|
|
1357
|
+
"@mgcrea/react-native-tailwind/babel",
|
|
1358
|
+
{
|
|
1359
|
+
stylesIdentifier: "styles", // or 'tw', 'tailwind', etc.
|
|
1360
|
+
},
|
|
1361
|
+
],
|
|
1362
|
+
],
|
|
1363
|
+
};
|
|
1364
|
+
```
|
|
1365
|
+
|
|
1366
|
+
**Default behavior:**
|
|
1367
|
+
|
|
1368
|
+
```tsx
|
|
1369
|
+
// Input
|
|
1370
|
+
<View className="p-4 bg-blue-500" />
|
|
1371
|
+
|
|
1372
|
+
// Output
|
|
1373
|
+
<View style={_twStyles._bg_blue_500_p_4} />
|
|
1374
|
+
|
|
1375
|
+
const _twStyles = StyleSheet.create({
|
|
1376
|
+
_bg_blue_500_p_4: { padding: 16, backgroundColor: '#3B82F6' }
|
|
1377
|
+
});
|
|
1378
|
+
```
|
|
1379
|
+
|
|
1380
|
+
**With custom identifier:**
|
|
1381
|
+
|
|
1382
|
+
```tsx
|
|
1383
|
+
// Input (with stylesIdentifier: "styles")
|
|
1384
|
+
<View className="p-4 bg-blue-500" />
|
|
1385
|
+
|
|
1386
|
+
// Output
|
|
1387
|
+
<View style={styles._bg_blue_500_p_4} />
|
|
1388
|
+
|
|
1389
|
+
const styles = StyleSheet.create({
|
|
1390
|
+
_bg_blue_500_p_4: { padding: 16, backgroundColor: '#3B82F6' }
|
|
1391
|
+
});
|
|
1392
|
+
```
|
|
1393
|
+
|
|
1394
|
+
**Use Cases:**
|
|
1395
|
+
|
|
1396
|
+
- **Avoid conflicts:** If you already have a `_twStyles` variable in your code
|
|
1397
|
+
- **Consistency:** Match your existing StyleSheet naming convention (`styles`, `styleSheet`, etc.)
|
|
1398
|
+
- **Shorter names:** Use a shorter identifier like `tw` or `s` for more compact code
|
|
1399
|
+
- **Team conventions:** Align with your team's coding standards
|
|
1400
|
+
|
|
1401
|
+
**Important Notes:**
|
|
1402
|
+
|
|
1403
|
+
- The identifier must be a valid JavaScript variable name
|
|
1404
|
+
- Choose a name that won't conflict with existing variables in your files
|
|
1405
|
+
- The same identifier is used across all files in your project
|
|
1406
|
+
|
|
1003
1407
|
### Arbitrary Values
|
|
1004
1408
|
|
|
1005
1409
|
Use arbitrary values for custom sizes, spacing, and borders not in the preset scales:
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
import * as fs from "fs";
|
|
9
9
|
import * as path from "path";
|
|
10
|
+
import { flattenColors } from "../utils/flattenColors";
|
|
10
11
|
|
|
11
12
|
export type TailwindConfig = {
|
|
12
13
|
theme?: {
|
|
@@ -79,29 +80,6 @@ export function loadTailwindConfig(configPath: string): TailwindConfig | null {
|
|
|
79
80
|
}
|
|
80
81
|
}
|
|
81
82
|
|
|
82
|
-
/**
|
|
83
|
-
* Flatten nested color objects into dot notation
|
|
84
|
-
* Example: { brand: { light: '#fff', dark: '#000' } } -> { 'brand-light': '#fff', 'brand-dark': '#000' }
|
|
85
|
-
*/
|
|
86
|
-
function flattenColors(
|
|
87
|
-
colors: Record<string, string | Record<string, string>>,
|
|
88
|
-
prefix = "",
|
|
89
|
-
): Record<string, string> {
|
|
90
|
-
const result: Record<string, string> = {};
|
|
91
|
-
|
|
92
|
-
for (const [key, value] of Object.entries(colors)) {
|
|
93
|
-
const newKey = prefix ? `${prefix}-${key}` : key;
|
|
94
|
-
|
|
95
|
-
if (typeof value === "string") {
|
|
96
|
-
result[newKey] = value;
|
|
97
|
-
} else if (typeof value === "object" && value !== null) {
|
|
98
|
-
Object.assign(result, flattenColors(value, newKey));
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
return result;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
83
|
/**
|
|
106
84
|
* Extract custom colors from tailwind config
|
|
107
85
|
* Prefers theme.extend.colors over theme.colors to avoid overriding defaults
|