@mgcrea/react-native-tailwind 0.10.0 → 0.11.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 +30 -13
- package/dist/babel/config-loader.d.ts +12 -3
- package/dist/babel/config-loader.test.ts +14 -12
- package/dist/babel/config-loader.ts +41 -9
- package/dist/babel/index.cjs +50 -27
- package/dist/babel/plugin.d.ts +2 -1
- package/dist/babel/plugin.ts +11 -10
- package/dist/babel/utils/colorSchemeModifierProcessing.d.ts +3 -3
- package/dist/babel/utils/colorSchemeModifierProcessing.ts +4 -4
- package/dist/babel/utils/dynamicProcessing.d.ts +5 -5
- package/dist/babel/utils/dynamicProcessing.ts +11 -11
- package/dist/babel/utils/modifierProcessing.d.ts +3 -3
- package/dist/babel/utils/modifierProcessing.ts +5 -5
- package/dist/babel/utils/platformModifierProcessing.d.ts +3 -3
- package/dist/babel/utils/platformModifierProcessing.ts +4 -4
- package/dist/babel/utils/twProcessing.d.ts +3 -3
- package/dist/babel/utils/twProcessing.ts +6 -6
- package/dist/parser/index.d.ts +11 -4
- package/dist/parser/index.js +1 -1
- package/dist/parser/typography.d.ts +3 -1
- package/dist/parser/typography.js +1 -1
- package/dist/runtime.cjs +1 -1
- package/dist/runtime.cjs.map +3 -3
- package/dist/runtime.d.ts +8 -1
- package/dist/runtime.js +1 -1
- package/dist/runtime.js.map +3 -3
- package/dist/runtime.test.js +1 -1
- package/package.json +1 -1
- package/src/babel/config-loader.test.ts +14 -12
- package/src/babel/config-loader.ts +41 -9
- package/src/babel/plugin.ts +11 -10
- package/src/babel/utils/colorSchemeModifierProcessing.ts +4 -4
- package/src/babel/utils/dynamicProcessing.ts +11 -11
- package/src/babel/utils/modifierProcessing.ts +5 -5
- package/src/babel/utils/platformModifierProcessing.ts +4 -4
- package/src/babel/utils/twProcessing.ts +6 -6
- package/src/parser/index.ts +16 -8
- package/src/parser/typography.ts +14 -2
- package/src/runtime.test.ts +7 -7
- package/src/runtime.ts +37 -14
package/README.md
CHANGED
|
@@ -425,7 +425,7 @@ export function RuntimeExample() {
|
|
|
425
425
|
|
|
426
426
|
#### Configuration
|
|
427
427
|
|
|
428
|
-
Configure custom colors and
|
|
428
|
+
Configure custom colors and font families using `setConfig()`:
|
|
429
429
|
|
|
430
430
|
```typescript
|
|
431
431
|
import { setConfig } from '@mgcrea/react-native-tailwind/runtime';
|
|
@@ -442,13 +442,17 @@ setConfig({
|
|
|
442
442
|
dark: '#CC0000',
|
|
443
443
|
},
|
|
444
444
|
},
|
|
445
|
+
fontFamily: {
|
|
446
|
+
sans: ['"SF Pro Rounded"'],
|
|
447
|
+
custom: ['"My Custom Font"'],
|
|
448
|
+
},
|
|
445
449
|
},
|
|
446
450
|
},
|
|
447
451
|
});
|
|
448
452
|
|
|
449
|
-
// Now you can use custom
|
|
453
|
+
// Now you can use custom theme
|
|
450
454
|
<View style={tw`bg-primary p-4`} />
|
|
451
|
-
<Text style={tw`text-brand-light`}>Custom
|
|
455
|
+
<Text style={tw`text-brand-light font-custom`}>Custom styling</Text>
|
|
452
456
|
```
|
|
453
457
|
|
|
454
458
|
#### API Reference
|
|
@@ -1365,7 +1369,7 @@ This pattern allows you to build component libraries with optimized default styl
|
|
|
1365
1369
|
|
|
1366
1370
|
**Available shades:** `50`, `100`, `200`, `300`, `400`, `500`, `600`, `700`, `800`, `900`
|
|
1367
1371
|
|
|
1368
|
-
> **Note:** You can extend the color palette with custom colors via `tailwind.config.*` — see [Custom
|
|
1372
|
+
> **Note:** You can extend the color palette with custom colors via `tailwind.config.*` — see [Custom Theme Extensions](#custom-theme-extensions)
|
|
1369
1373
|
|
|
1370
1374
|
**Opacity Modifiers:**
|
|
1371
1375
|
|
|
@@ -1911,9 +1915,9 @@ Use arbitrary values for custom sizes, spacing, and borders not in the preset sc
|
|
|
1911
1915
|
|
|
1912
1916
|
> **Note:** CSS units (`rem`, `em`, `vh`, `vw`) are not supported by React Native.
|
|
1913
1917
|
|
|
1914
|
-
### Custom
|
|
1918
|
+
### Custom Theme Extensions
|
|
1915
1919
|
|
|
1916
|
-
Extend the default color palette via `tailwind.config.*` in your project root:
|
|
1920
|
+
Extend the default color palette and font families via `tailwind.config.*` in your project root:
|
|
1917
1921
|
|
|
1918
1922
|
```javascript
|
|
1919
1923
|
// tailwind.config.mjs
|
|
@@ -1929,16 +1933,21 @@ export default {
|
|
|
1929
1933
|
dark: "#0c4a6e",
|
|
1930
1934
|
},
|
|
1931
1935
|
},
|
|
1936
|
+
fontFamily: {
|
|
1937
|
+
sans: ['"SF Pro Rounded"'],
|
|
1938
|
+
custom: ['"My Custom Font"'],
|
|
1939
|
+
},
|
|
1932
1940
|
},
|
|
1933
1941
|
},
|
|
1934
1942
|
};
|
|
1935
1943
|
```
|
|
1936
1944
|
|
|
1937
|
-
Then use your custom
|
|
1945
|
+
Then use your custom theme:
|
|
1938
1946
|
|
|
1939
1947
|
```tsx
|
|
1940
1948
|
<View className="bg-primary p-4">
|
|
1941
|
-
<Text className="text-brand">Custom branded text</Text>
|
|
1949
|
+
<Text className="text-brand font-custom">Custom branded text</Text>
|
|
1950
|
+
<Text className="font-sans">SF Pro Rounded text</Text>
|
|
1942
1951
|
<View className="bg-brand-light rounded-lg" />
|
|
1943
1952
|
</View>
|
|
1944
1953
|
```
|
|
@@ -1946,13 +1955,14 @@ Then use your custom colors:
|
|
|
1946
1955
|
**How it works:**
|
|
1947
1956
|
|
|
1948
1957
|
- Babel plugin discovers config by traversing up from source files
|
|
1949
|
-
- Custom
|
|
1950
|
-
- Nested objects flattened with dash notation: `brand.light` → `brand-light`
|
|
1958
|
+
- Custom theme merged with defaults at build time (custom takes precedence)
|
|
1959
|
+
- Nested color objects flattened with dash notation: `brand.light` → `brand-light`
|
|
1960
|
+
- Font families use first font in array (React Native doesn't support font stacks)
|
|
1951
1961
|
- Zero runtime overhead — all loading happens during compilation
|
|
1952
1962
|
|
|
1953
1963
|
**Supported formats:** `.js`, `.mjs`, `.cjs`, `.ts`
|
|
1954
1964
|
|
|
1955
|
-
> **Tip:** Use `theme.extend
|
|
1965
|
+
> **Tip:** Use `theme.extend.*` to keep defaults. Using `theme.colors` or `theme.fontFamily` directly will override all defaults.
|
|
1956
1966
|
|
|
1957
1967
|
### Programmatic API
|
|
1958
1968
|
|
|
@@ -1961,10 +1971,17 @@ Access the parser and constants programmatically:
|
|
|
1961
1971
|
```typescript
|
|
1962
1972
|
import { parseClassName, COLORS, SPACING_SCALE } from "@mgcrea/react-native-tailwind";
|
|
1963
1973
|
|
|
1964
|
-
// Parse className strings
|
|
1965
|
-
const
|
|
1974
|
+
// Parse className strings (no custom theme)
|
|
1975
|
+
const styles = parseClassName("m-4 p-2 bg-blue-500");
|
|
1966
1976
|
// Returns: { margin: 16, padding: 8, backgroundColor: '#3B82F6' }
|
|
1967
1977
|
|
|
1978
|
+
// Parse with custom theme
|
|
1979
|
+
const customStyles = parseClassName("m-4 bg-primary font-custom", {
|
|
1980
|
+
colors: { primary: "#1d4ed8" },
|
|
1981
|
+
fontFamily: { custom: "My Custom Font" },
|
|
1982
|
+
});
|
|
1983
|
+
// Returns: { margin: 16, backgroundColor: '#1d4ed8', fontFamily: 'My Custom Font' }
|
|
1984
|
+
|
|
1968
1985
|
// Access default scales
|
|
1969
1986
|
const blueColor = COLORS["blue-500"]; // '#3B82F6'
|
|
1970
1987
|
const spacing = SPACING_SCALE[4]; // 16
|
|
@@ -6,8 +6,10 @@ export type TailwindConfig = {
|
|
|
6
6
|
theme?: {
|
|
7
7
|
extend?: {
|
|
8
8
|
colors?: Record<string, string | Record<string, string>>;
|
|
9
|
+
fontFamily?: Record<string, string | string[]>;
|
|
9
10
|
};
|
|
10
11
|
colors?: Record<string, string | Record<string, string>>;
|
|
12
|
+
fontFamily?: Record<string, string | string[]>;
|
|
11
13
|
};
|
|
12
14
|
};
|
|
13
15
|
/**
|
|
@@ -19,7 +21,14 @@ export declare function findTailwindConfig(startDir: string): string | null;
|
|
|
19
21
|
*/
|
|
20
22
|
export declare function loadTailwindConfig(configPath: string): TailwindConfig | null;
|
|
21
23
|
/**
|
|
22
|
-
*
|
|
23
|
-
* Prefers theme.extend.colors over theme.colors to avoid overriding defaults
|
|
24
|
+
* Custom theme configuration extracted from tailwind.config
|
|
24
25
|
*/
|
|
25
|
-
export
|
|
26
|
+
export type CustomTheme = {
|
|
27
|
+
colors: Record<string, string>;
|
|
28
|
+
fontFamily: Record<string, string>;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Extract all custom theme extensions from tailwind config
|
|
32
|
+
* Prefers theme.extend.* over theme.* to avoid overriding defaults
|
|
33
|
+
*/
|
|
34
|
+
export declare function extractCustomTheme(filename: string): CustomTheme;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as fs from "fs";
|
|
2
2
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
3
|
-
import {
|
|
3
|
+
import { extractCustomTheme, findTailwindConfig, loadTailwindConfig } from "./config-loader";
|
|
4
4
|
|
|
5
5
|
// Mock fs
|
|
6
6
|
vi.mock("fs");
|
|
@@ -115,15 +115,15 @@ describe("config-loader", () => {
|
|
|
115
115
|
});
|
|
116
116
|
});
|
|
117
117
|
|
|
118
|
-
describe("
|
|
119
|
-
it("should return empty
|
|
118
|
+
describe("extractCustomTheme", () => {
|
|
119
|
+
it("should return empty theme when no config found", () => {
|
|
120
120
|
vi.spyOn(fs, "existsSync").mockReturnValue(false);
|
|
121
121
|
|
|
122
|
-
const result =
|
|
123
|
-
expect(result).toEqual({});
|
|
122
|
+
const result = extractCustomTheme("/project/src/file.ts");
|
|
123
|
+
expect(result).toEqual({ colors: {}, fontFamily: {} });
|
|
124
124
|
});
|
|
125
125
|
|
|
126
|
-
it("should return empty
|
|
126
|
+
it("should return empty theme when config has no theme", () => {
|
|
127
127
|
const configPath = "/project/tailwind.config.js";
|
|
128
128
|
|
|
129
129
|
vi.spyOn(fs, "existsSync").mockImplementation((filepath) => filepath === configPath);
|
|
@@ -131,22 +131,24 @@ describe("config-loader", () => {
|
|
|
131
131
|
|
|
132
132
|
// loadTailwindConfig will be called, but we've already tested it
|
|
133
133
|
// For integration, we'd need to mock the entire flow
|
|
134
|
-
const result =
|
|
134
|
+
const result = extractCustomTheme("/project/src/file.ts");
|
|
135
135
|
|
|
136
136
|
// Without actual config loading, this returns empty
|
|
137
|
-
expect(result).toEqual({});
|
|
137
|
+
expect(result).toEqual({ colors: {}, fontFamily: {} });
|
|
138
138
|
});
|
|
139
139
|
|
|
140
|
-
it("should extract colors from theme.extend
|
|
140
|
+
it("should extract colors and fontFamily from theme.extend", () => {
|
|
141
141
|
// This would require complex mocking of the entire require flow
|
|
142
|
-
// Testing the logic: theme.extend
|
|
142
|
+
// Testing the logic: theme.extend is preferred
|
|
143
143
|
const colors = { brand: { light: "#fff", dark: "#000" } };
|
|
144
|
+
const fontFamily = { sans: ['"SF Pro"'], custom: ['"Custom Font"'] };
|
|
144
145
|
const theme = {
|
|
145
|
-
extend: { colors },
|
|
146
|
+
extend: { colors, fontFamily },
|
|
146
147
|
};
|
|
147
148
|
|
|
148
|
-
// If we had the config, we'd flatten the colors
|
|
149
|
+
// If we had the config, we'd flatten the colors and convert fontFamily
|
|
149
150
|
expect(theme.extend.colors).toEqual(colors);
|
|
151
|
+
expect(theme.extend.fontFamily).toEqual(fontFamily);
|
|
150
152
|
});
|
|
151
153
|
});
|
|
152
154
|
});
|
|
@@ -13,8 +13,10 @@ export type TailwindConfig = {
|
|
|
13
13
|
theme?: {
|
|
14
14
|
extend?: {
|
|
15
15
|
colors?: Record<string, string | Record<string, string>>;
|
|
16
|
+
fontFamily?: Record<string, string | string[]>;
|
|
16
17
|
};
|
|
17
18
|
colors?: Record<string, string | Record<string, string>>;
|
|
19
|
+
fontFamily?: Record<string, string | string[]>;
|
|
18
20
|
};
|
|
19
21
|
};
|
|
20
22
|
|
|
@@ -82,23 +84,31 @@ export function loadTailwindConfig(configPath: string): TailwindConfig | null {
|
|
|
82
84
|
}
|
|
83
85
|
|
|
84
86
|
/**
|
|
85
|
-
*
|
|
86
|
-
* Prefers theme.extend.colors over theme.colors to avoid overriding defaults
|
|
87
|
+
* Custom theme configuration extracted from tailwind.config
|
|
87
88
|
*/
|
|
88
|
-
export
|
|
89
|
+
export type CustomTheme = {
|
|
90
|
+
colors: Record<string, string>;
|
|
91
|
+
fontFamily: Record<string, string>;
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Extract all custom theme extensions from tailwind config
|
|
96
|
+
* Prefers theme.extend.* over theme.* to avoid overriding defaults
|
|
97
|
+
*/
|
|
98
|
+
export function extractCustomTheme(filename: string): CustomTheme {
|
|
89
99
|
const projectDir = path.dirname(filename);
|
|
90
100
|
const configPath = findTailwindConfig(projectDir);
|
|
91
101
|
|
|
92
102
|
if (!configPath) {
|
|
93
|
-
return {};
|
|
103
|
+
return { colors: {}, fontFamily: {} };
|
|
94
104
|
}
|
|
95
105
|
|
|
96
106
|
const config = loadTailwindConfig(configPath);
|
|
97
107
|
if (!config?.theme) {
|
|
98
|
-
return {};
|
|
108
|
+
return { colors: {}, fontFamily: {} };
|
|
99
109
|
}
|
|
100
110
|
|
|
101
|
-
//
|
|
111
|
+
// Extract colors
|
|
102
112
|
/* v8 ignore next 5 */
|
|
103
113
|
if (config.theme.colors && !config.theme.extend?.colors && process.env.NODE_ENV !== "production") {
|
|
104
114
|
console.warn(
|
|
@@ -106,9 +116,31 @@ export function extractCustomColors(filename: string): Record<string, string> {
|
|
|
106
116
|
"Use theme.extend.colors to add custom colors while keeping defaults.",
|
|
107
117
|
);
|
|
108
118
|
}
|
|
109
|
-
|
|
110
|
-
// Prefer theme.extend.colors
|
|
111
119
|
const colors = config.theme.extend?.colors ?? config.theme.colors ?? {};
|
|
112
120
|
|
|
113
|
-
|
|
121
|
+
// Extract fontFamily
|
|
122
|
+
/* v8 ignore next 5 */
|
|
123
|
+
if (config.theme.fontFamily && !config.theme.extend?.fontFamily && process.env.NODE_ENV !== "production") {
|
|
124
|
+
console.warn(
|
|
125
|
+
"[react-native-tailwind] Using theme.fontFamily will override all default font families. " +
|
|
126
|
+
"Use theme.extend.fontFamily to add custom fonts while keeping defaults.",
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
const fontFamily = config.theme.extend?.fontFamily ?? config.theme.fontFamily ?? {};
|
|
130
|
+
|
|
131
|
+
// Convert fontFamily values to strings (take first value if array)
|
|
132
|
+
const fontFamilyResult: Record<string, string> = {};
|
|
133
|
+
for (const [key, value] of Object.entries(fontFamily)) {
|
|
134
|
+
if (Array.isArray(value)) {
|
|
135
|
+
// Take first font in the array (React Native doesn't support font stacks)
|
|
136
|
+
fontFamilyResult[key] = value[0];
|
|
137
|
+
} else {
|
|
138
|
+
fontFamilyResult[key] = value;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return {
|
|
143
|
+
colors: flattenColors(colors),
|
|
144
|
+
fontFamily: fontFamilyResult,
|
|
145
|
+
};
|
|
114
146
|
}
|
package/dist/babel/index.cjs
CHANGED
|
@@ -1678,7 +1678,13 @@ function parseArbitraryLineHeight(value) {
|
|
|
1678
1678
|
}
|
|
1679
1679
|
return null;
|
|
1680
1680
|
}
|
|
1681
|
-
function parseTypography(cls) {
|
|
1681
|
+
function parseTypography(cls, customFontFamily) {
|
|
1682
|
+
const fontFamilyMap = customFontFamily ? {
|
|
1683
|
+
...FONT_FAMILY_MAP,
|
|
1684
|
+
...Object.fromEntries(
|
|
1685
|
+
Object.entries(customFontFamily).map(([key, value]) => [`font-${key}`, { fontFamily: value }])
|
|
1686
|
+
)
|
|
1687
|
+
} : FONT_FAMILY_MAP;
|
|
1682
1688
|
if (cls.startsWith("text-")) {
|
|
1683
1689
|
const sizeKey = cls.substring(5);
|
|
1684
1690
|
const arbitraryValue = parseArbitraryFontSize(sizeKey);
|
|
@@ -1701,7 +1707,7 @@ function parseTypography(cls) {
|
|
|
1701
1707
|
return { lineHeight };
|
|
1702
1708
|
}
|
|
1703
1709
|
}
|
|
1704
|
-
return
|
|
1710
|
+
return fontFamilyMap[cls] ?? FONT_WEIGHT_MAP[cls] ?? FONT_STYLE_MAP[cls] ?? TEXT_ALIGN_MAP[cls] ?? TEXT_DECORATION_MAP[cls] ?? TEXT_TRANSFORM_MAP[cls] ?? LINE_HEIGHT_MAP[cls] ?? TRACKING_MAP[cls] ?? null;
|
|
1705
1711
|
}
|
|
1706
1712
|
|
|
1707
1713
|
// src/parser/placeholder.ts
|
|
@@ -1842,22 +1848,22 @@ function splitModifierClasses(className) {
|
|
|
1842
1848
|
}
|
|
1843
1849
|
|
|
1844
1850
|
// src/parser/index.ts
|
|
1845
|
-
function parseClassName(className,
|
|
1851
|
+
function parseClassName(className, customTheme) {
|
|
1846
1852
|
const classes = className.split(/\s+/).filter(Boolean);
|
|
1847
1853
|
const style = {};
|
|
1848
1854
|
for (const cls of classes) {
|
|
1849
|
-
const parsedStyle = parseClass(cls,
|
|
1855
|
+
const parsedStyle = parseClass(cls, customTheme);
|
|
1850
1856
|
Object.assign(style, parsedStyle);
|
|
1851
1857
|
}
|
|
1852
1858
|
return style;
|
|
1853
1859
|
}
|
|
1854
|
-
function parseClass(cls,
|
|
1860
|
+
function parseClass(cls, customTheme) {
|
|
1855
1861
|
const parsers = [
|
|
1856
1862
|
parseSpacing,
|
|
1857
1863
|
parseBorder,
|
|
1858
|
-
(cls2) => parseColor(cls2,
|
|
1864
|
+
(cls2) => parseColor(cls2, customTheme?.colors),
|
|
1859
1865
|
parseLayout,
|
|
1860
|
-
parseTypography,
|
|
1866
|
+
(cls2) => parseTypography(cls2, customTheme?.fontFamily),
|
|
1861
1867
|
parseSizing,
|
|
1862
1868
|
parseShadow,
|
|
1863
1869
|
parseAspectRatio,
|
|
@@ -1925,15 +1931,15 @@ function loadTailwindConfig(configPath) {
|
|
|
1925
1931
|
return null;
|
|
1926
1932
|
}
|
|
1927
1933
|
}
|
|
1928
|
-
function
|
|
1934
|
+
function extractCustomTheme(filename) {
|
|
1929
1935
|
const projectDir = path.dirname(filename);
|
|
1930
1936
|
const configPath = findTailwindConfig(projectDir);
|
|
1931
1937
|
if (!configPath) {
|
|
1932
|
-
return {};
|
|
1938
|
+
return { colors: {}, fontFamily: {} };
|
|
1933
1939
|
}
|
|
1934
1940
|
const config = loadTailwindConfig(configPath);
|
|
1935
1941
|
if (!config?.theme) {
|
|
1936
|
-
return {};
|
|
1942
|
+
return { colors: {}, fontFamily: {} };
|
|
1937
1943
|
}
|
|
1938
1944
|
if (config.theme.colors && !config.theme.extend?.colors && process.env.NODE_ENV !== "production") {
|
|
1939
1945
|
console.warn(
|
|
@@ -1941,7 +1947,24 @@ function extractCustomColors(filename) {
|
|
|
1941
1947
|
);
|
|
1942
1948
|
}
|
|
1943
1949
|
const colors = config.theme.extend?.colors ?? config.theme.colors ?? {};
|
|
1944
|
-
|
|
1950
|
+
if (config.theme.fontFamily && !config.theme.extend?.fontFamily && process.env.NODE_ENV !== "production") {
|
|
1951
|
+
console.warn(
|
|
1952
|
+
"[react-native-tailwind] Using theme.fontFamily will override all default font families. Use theme.extend.fontFamily to add custom fonts while keeping defaults."
|
|
1953
|
+
);
|
|
1954
|
+
}
|
|
1955
|
+
const fontFamily = config.theme.extend?.fontFamily ?? config.theme.fontFamily ?? {};
|
|
1956
|
+
const fontFamilyResult = {};
|
|
1957
|
+
for (const [key, value] of Object.entries(fontFamily)) {
|
|
1958
|
+
if (Array.isArray(value)) {
|
|
1959
|
+
fontFamilyResult[key] = value[0];
|
|
1960
|
+
} else {
|
|
1961
|
+
fontFamilyResult[key] = value;
|
|
1962
|
+
}
|
|
1963
|
+
}
|
|
1964
|
+
return {
|
|
1965
|
+
colors: flattenColors(colors),
|
|
1966
|
+
fontFamily: fontFamilyResult
|
|
1967
|
+
};
|
|
1945
1968
|
}
|
|
1946
1969
|
|
|
1947
1970
|
// src/babel/utils/attributeMatchers.ts
|
|
@@ -1997,7 +2020,7 @@ function processColorSchemeModifiers(colorSchemeModifiers, state, parseClassName
|
|
|
1997
2020
|
const conditionalExpressions = [];
|
|
1998
2021
|
for (const [scheme, modifiers] of modifiersByScheme) {
|
|
1999
2022
|
const classNames = modifiers.map((m) => m.baseClass).join(" ");
|
|
2000
|
-
const styleObject = parseClassName2(classNames, state.
|
|
2023
|
+
const styleObject = parseClassName2(classNames, state.customTheme);
|
|
2001
2024
|
const styleKey = generateStyleKey2(`${scheme}_${classNames}`);
|
|
2002
2025
|
state.styleRegistry.set(styleKey, styleObject);
|
|
2003
2026
|
const colorSchemeCheck = t.binaryExpression(
|
|
@@ -2252,7 +2275,7 @@ function processStringOrExpressionHelper(node, state, parseClassName2, generateS
|
|
|
2252
2275
|
if (isSchemeModifier2(modifier.modifier)) {
|
|
2253
2276
|
const expanded = expandSchemeModifier2(
|
|
2254
2277
|
modifier,
|
|
2255
|
-
state.
|
|
2278
|
+
state.customTheme.colors ?? {},
|
|
2256
2279
|
state.schemeModifierConfig.darkSuffix ?? "-dark",
|
|
2257
2280
|
state.schemeModifierConfig.lightSuffix ?? "-light"
|
|
2258
2281
|
);
|
|
@@ -2266,7 +2289,7 @@ function processStringOrExpressionHelper(node, state, parseClassName2, generateS
|
|
|
2266
2289
|
const styleElements = [];
|
|
2267
2290
|
if (baseClasses.length > 0) {
|
|
2268
2291
|
const baseClassName = baseClasses.join(" ");
|
|
2269
|
-
const styleObject = parseClassName2(baseClassName, state.
|
|
2292
|
+
const styleObject = parseClassName2(baseClassName, state.customTheme);
|
|
2270
2293
|
const styleKey = generateStyleKey2(baseClassName);
|
|
2271
2294
|
state.styleRegistry.set(styleKey, styleObject);
|
|
2272
2295
|
styleElements.push(t.memberExpression(t.identifier(state.stylesIdentifier), t.identifier(styleKey)));
|
|
@@ -2373,7 +2396,7 @@ function processStaticClassNameWithModifiers(className, state, parseClassName2,
|
|
|
2373
2396
|
let baseStyleExpression = null;
|
|
2374
2397
|
if (baseClasses.length > 0) {
|
|
2375
2398
|
const baseClassName = baseClasses.join(" ");
|
|
2376
|
-
const baseStyleObject = parseClassName2(baseClassName, state.
|
|
2399
|
+
const baseStyleObject = parseClassName2(baseClassName, state.customTheme);
|
|
2377
2400
|
const baseStyleKey = generateStyleKey2(baseClassName);
|
|
2378
2401
|
state.styleRegistry.set(baseStyleKey, baseStyleObject);
|
|
2379
2402
|
baseStyleExpression = t.memberExpression(t.identifier(state.stylesIdentifier), t.identifier(baseStyleKey));
|
|
@@ -2394,7 +2417,7 @@ function processStaticClassNameWithModifiers(className, state, parseClassName2,
|
|
|
2394
2417
|
}
|
|
2395
2418
|
for (const [modifierType, modifiers] of modifiersByType) {
|
|
2396
2419
|
const modifierClassNames = modifiers.map((m) => m.baseClass).join(" ");
|
|
2397
|
-
const modifierStyleObject = parseClassName2(modifierClassNames, state.
|
|
2420
|
+
const modifierStyleObject = parseClassName2(modifierClassNames, state.customTheme);
|
|
2398
2421
|
const modifierStyleKey = generateStyleKey2(`${modifierType}_${modifierClassNames}`);
|
|
2399
2422
|
state.styleRegistry.set(modifierStyleKey, modifierStyleObject);
|
|
2400
2423
|
const stateProperty = getStatePropertyForModifier(modifierType);
|
|
@@ -2443,7 +2466,7 @@ function processPlatformModifiers(platformModifiers, state, parseClassName2, gen
|
|
|
2443
2466
|
const selectProperties = [];
|
|
2444
2467
|
for (const [platform, modifiers] of modifiersByPlatform) {
|
|
2445
2468
|
const classNames = modifiers.map((m) => m.baseClass).join(" ");
|
|
2446
|
-
const styleObject = parseClassName2(classNames, state.
|
|
2469
|
+
const styleObject = parseClassName2(classNames, state.customTheme);
|
|
2447
2470
|
const styleKey = generateStyleKey2(`${platform}_${classNames}`);
|
|
2448
2471
|
state.styleRegistry.set(styleKey, styleObject);
|
|
2449
2472
|
const styleReference = t.memberExpression(t.identifier(state.stylesIdentifier), t.identifier(styleKey));
|
|
@@ -2708,7 +2731,7 @@ function processTwCall(className, path2, state, parseClassName2, generateStyleKe
|
|
|
2708
2731
|
if (isSchemeModifier(modifier.modifier)) {
|
|
2709
2732
|
const expanded = expandSchemeModifier(
|
|
2710
2733
|
modifier,
|
|
2711
|
-
state.
|
|
2734
|
+
state.customTheme.colors ?? {},
|
|
2712
2735
|
state.schemeModifierConfig.darkSuffix ?? "-dark",
|
|
2713
2736
|
state.schemeModifierConfig.lightSuffix ?? "-light"
|
|
2714
2737
|
);
|
|
@@ -2720,7 +2743,7 @@ function processTwCall(className, path2, state, parseClassName2, generateStyleKe
|
|
|
2720
2743
|
const objectProperties = [];
|
|
2721
2744
|
if (baseClasses.length > 0) {
|
|
2722
2745
|
const baseClassName = baseClasses.join(" ");
|
|
2723
|
-
const baseStyleObject = parseClassName2(baseClassName, state.
|
|
2746
|
+
const baseStyleObject = parseClassName2(baseClassName, state.customTheme);
|
|
2724
2747
|
const baseStyleKey = generateStyleKey2(baseClassName);
|
|
2725
2748
|
state.styleRegistry.set(baseStyleKey, baseStyleObject);
|
|
2726
2749
|
objectProperties.push(
|
|
@@ -2744,7 +2767,7 @@ function processTwCall(className, path2, state, parseClassName2, generateStyleKe
|
|
|
2744
2767
|
}
|
|
2745
2768
|
for (const [modifierType, modifiers] of modifiersByType) {
|
|
2746
2769
|
const modifierClassNames = modifiers.map((m) => m.baseClass).join(" ");
|
|
2747
|
-
const modifierStyleObject = parseClassName2(modifierClassNames, state.
|
|
2770
|
+
const modifierStyleObject = parseClassName2(modifierClassNames, state.customTheme);
|
|
2748
2771
|
const modifierStyleKey = generateStyleKey2(`${modifierType}_${modifierClassNames}`);
|
|
2749
2772
|
state.styleRegistry.set(modifierStyleKey, modifierStyleObject);
|
|
2750
2773
|
const propertyName = `${modifierType}Style`;
|
|
@@ -2848,7 +2871,7 @@ function reactNativeTailwindBabelPlugin({ types: t }, options) {
|
|
|
2848
2871
|
state.twImportNames = /* @__PURE__ */ new Set();
|
|
2849
2872
|
state.hasTwImport = false;
|
|
2850
2873
|
state.functionComponentsNeedingColorScheme = /* @__PURE__ */ new Set();
|
|
2851
|
-
state.
|
|
2874
|
+
state.customTheme = extractCustomTheme(state.file.opts.filename ?? "");
|
|
2852
2875
|
state.schemeModifierConfig = schemeModifierConfig;
|
|
2853
2876
|
},
|
|
2854
2877
|
exit(path2, state) {
|
|
@@ -3014,7 +3037,7 @@ function reactNativeTailwindBabelPlugin({ types: t }, options) {
|
|
|
3014
3037
|
if (isSchemeModifier(modifier.modifier)) {
|
|
3015
3038
|
const expanded = expandSchemeModifier(
|
|
3016
3039
|
modifier,
|
|
3017
|
-
state.
|
|
3040
|
+
state.customTheme.colors ?? {},
|
|
3018
3041
|
state.schemeModifierConfig.darkSuffix,
|
|
3019
3042
|
state.schemeModifierConfig.lightSuffix
|
|
3020
3043
|
);
|
|
@@ -3034,7 +3057,7 @@ function reactNativeTailwindBabelPlugin({ types: t }, options) {
|
|
|
3034
3057
|
const componentSupport = getComponentModifierSupport(jsxOpeningElement, t);
|
|
3035
3058
|
if (componentSupport?.supportedModifiers.includes("placeholder")) {
|
|
3036
3059
|
const placeholderClasses = placeholderModifiers.map((m) => m.baseClass).join(" ");
|
|
3037
|
-
const placeholderColor = parsePlaceholderClasses(placeholderClasses, state.
|
|
3060
|
+
const placeholderColor = parsePlaceholderClasses(placeholderClasses, state.customTheme.colors);
|
|
3038
3061
|
if (placeholderColor) {
|
|
3039
3062
|
addOrMergePlaceholderTextColorProp(jsxOpeningElement, placeholderColor, t);
|
|
3040
3063
|
}
|
|
@@ -3070,7 +3093,7 @@ function reactNativeTailwindBabelPlugin({ types: t }, options) {
|
|
|
3070
3093
|
const styleArrayElements = [];
|
|
3071
3094
|
if (hasBaseClasses) {
|
|
3072
3095
|
const baseClassName = baseClasses.join(" ");
|
|
3073
|
-
const baseStyleObject = parseClassName(baseClassName, state.
|
|
3096
|
+
const baseStyleObject = parseClassName(baseClassName, state.customTheme);
|
|
3074
3097
|
const baseStyleKey = generateStyleKey(baseClassName);
|
|
3075
3098
|
state.styleRegistry.set(baseStyleKey, baseStyleObject);
|
|
3076
3099
|
styleArrayElements.push(
|
|
@@ -3110,7 +3133,7 @@ function reactNativeTailwindBabelPlugin({ types: t }, options) {
|
|
|
3110
3133
|
continue;
|
|
3111
3134
|
}
|
|
3112
3135
|
const modifierClassNames = modifiers.map((m) => m.baseClass).join(" ");
|
|
3113
|
-
const modifierStyleObject = parseClassName(modifierClassNames, state.
|
|
3136
|
+
const modifierStyleObject = parseClassName(modifierClassNames, state.customTheme);
|
|
3114
3137
|
const modifierStyleKey = generateStyleKey(`${modifierType}_${modifierClassNames}`);
|
|
3115
3138
|
state.styleRegistry.set(modifierStyleKey, modifierStyleObject);
|
|
3116
3139
|
const stateProperty = getStatePropertyForModifier(modifierType);
|
|
@@ -3140,7 +3163,7 @@ function reactNativeTailwindBabelPlugin({ types: t }, options) {
|
|
|
3140
3163
|
const styleExpressions = [];
|
|
3141
3164
|
if (hasBaseClasses) {
|
|
3142
3165
|
const baseClassName = baseClasses.join(" ");
|
|
3143
|
-
const baseStyleObject = parseClassName(baseClassName, state.
|
|
3166
|
+
const baseStyleObject = parseClassName(baseClassName, state.customTheme);
|
|
3144
3167
|
const baseStyleKey = generateStyleKey(baseClassName);
|
|
3145
3168
|
state.styleRegistry.set(baseStyleKey, baseStyleObject);
|
|
3146
3169
|
styleExpressions.push(
|
|
@@ -3256,7 +3279,7 @@ function reactNativeTailwindBabelPlugin({ types: t }, options) {
|
|
|
3256
3279
|
path2.remove();
|
|
3257
3280
|
return;
|
|
3258
3281
|
}
|
|
3259
|
-
const styleObject = parseClassName(classNameForStyle, state.
|
|
3282
|
+
const styleObject = parseClassName(classNameForStyle, state.customTheme);
|
|
3260
3283
|
const styleKey = generateStyleKey(classNameForStyle);
|
|
3261
3284
|
state.styleRegistry.set(styleKey, styleObject);
|
|
3262
3285
|
const styleAttribute = findStyleAttribute(path2, targetStyleProp, t);
|
package/dist/babel/plugin.d.ts
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import type { NodePath, PluginObj, PluginPass } from "@babel/core";
|
|
6
6
|
import * as BabelTypes from "@babel/types";
|
|
7
7
|
import type { StyleObject } from "../types/core.js";
|
|
8
|
+
import type { CustomTheme } from "./config-loader.js";
|
|
8
9
|
import type { SchemeModifierConfig } from "../types/config.js";
|
|
9
10
|
/**
|
|
10
11
|
* Plugin options
|
|
@@ -50,7 +51,7 @@ type PluginState = PluginPass & {
|
|
|
50
51
|
hasColorSchemeImport: boolean;
|
|
51
52
|
needsColorSchemeImport: boolean;
|
|
52
53
|
colorSchemeVariableName: string;
|
|
53
|
-
|
|
54
|
+
customTheme: CustomTheme;
|
|
54
55
|
schemeModifierConfig: SchemeModifierConfig;
|
|
55
56
|
supportedAttributes: Set<string>;
|
|
56
57
|
attributePatterns: RegExp[];
|
package/dist/babel/plugin.ts
CHANGED
|
@@ -18,7 +18,8 @@ import {
|
|
|
18
18
|
} from "../parser/index.js";
|
|
19
19
|
import type { StyleObject } from "../types/core.js";
|
|
20
20
|
import { generateStyleKey } from "../utils/styleKey.js";
|
|
21
|
-
import {
|
|
21
|
+
import type { CustomTheme } from "./config-loader.js";
|
|
22
|
+
import { extractCustomTheme } from "./config-loader.js";
|
|
22
23
|
|
|
23
24
|
// Import utility functions
|
|
24
25
|
import type { SchemeModifierConfig } from "../types/config.js";
|
|
@@ -99,7 +100,7 @@ type PluginState = PluginPass & {
|
|
|
99
100
|
hasColorSchemeImport: boolean;
|
|
100
101
|
needsColorSchemeImport: boolean;
|
|
101
102
|
colorSchemeVariableName: string;
|
|
102
|
-
|
|
103
|
+
customTheme: CustomTheme;
|
|
103
104
|
schemeModifierConfig: SchemeModifierConfig;
|
|
104
105
|
supportedAttributes: Set<string>;
|
|
105
106
|
attributePatterns: RegExp[];
|
|
@@ -231,8 +232,8 @@ export default function reactNativeTailwindBabelPlugin(
|
|
|
231
232
|
state.hasTwImport = false;
|
|
232
233
|
state.functionComponentsNeedingColorScheme = new Set();
|
|
233
234
|
|
|
234
|
-
// Load custom
|
|
235
|
-
state.
|
|
235
|
+
// Load custom theme from tailwind.config.*
|
|
236
|
+
state.customTheme = extractCustomTheme(state.file.opts.filename ?? "");
|
|
236
237
|
|
|
237
238
|
// Use scheme modifier config from plugin options
|
|
238
239
|
state.schemeModifierConfig = schemeModifierConfig;
|
|
@@ -480,7 +481,7 @@ export default function reactNativeTailwindBabelPlugin(
|
|
|
480
481
|
// Expand scheme: into dark: and light:
|
|
481
482
|
const expanded = expandSchemeModifier(
|
|
482
483
|
modifier,
|
|
483
|
-
state.
|
|
484
|
+
state.customTheme.colors ?? {},
|
|
484
485
|
state.schemeModifierConfig.darkSuffix,
|
|
485
486
|
state.schemeModifierConfig.lightSuffix,
|
|
486
487
|
);
|
|
@@ -507,7 +508,7 @@ export default function reactNativeTailwindBabelPlugin(
|
|
|
507
508
|
|
|
508
509
|
if (componentSupport?.supportedModifiers.includes("placeholder")) {
|
|
509
510
|
const placeholderClasses = placeholderModifiers.map((m) => m.baseClass).join(" ");
|
|
510
|
-
const placeholderColor = parsePlaceholderClasses(placeholderClasses, state.
|
|
511
|
+
const placeholderColor = parsePlaceholderClasses(placeholderClasses, state.customTheme.colors);
|
|
511
512
|
|
|
512
513
|
if (placeholderColor) {
|
|
513
514
|
// Add or merge placeholderTextColor prop
|
|
@@ -561,7 +562,7 @@ export default function reactNativeTailwindBabelPlugin(
|
|
|
561
562
|
// Add base classes
|
|
562
563
|
if (hasBaseClasses) {
|
|
563
564
|
const baseClassName = baseClasses.join(" ");
|
|
564
|
-
const baseStyleObject = parseClassName(baseClassName, state.
|
|
565
|
+
const baseStyleObject = parseClassName(baseClassName, state.customTheme);
|
|
565
566
|
const baseStyleKey = generateStyleKey(baseClassName);
|
|
566
567
|
state.styleRegistry.set(baseStyleKey, baseStyleObject);
|
|
567
568
|
styleArrayElements.push(
|
|
@@ -611,7 +612,7 @@ export default function reactNativeTailwindBabelPlugin(
|
|
|
611
612
|
}
|
|
612
613
|
|
|
613
614
|
const modifierClassNames = modifiers.map((m) => m.baseClass).join(" ");
|
|
614
|
-
const modifierStyleObject = parseClassName(modifierClassNames, state.
|
|
615
|
+
const modifierStyleObject = parseClassName(modifierClassNames, state.customTheme);
|
|
615
616
|
const modifierStyleKey = generateStyleKey(`${modifierType}_${modifierClassNames}`);
|
|
616
617
|
state.styleRegistry.set(modifierStyleKey, modifierStyleObject);
|
|
617
618
|
|
|
@@ -653,7 +654,7 @@ export default function reactNativeTailwindBabelPlugin(
|
|
|
653
654
|
// Add base classes
|
|
654
655
|
if (hasBaseClasses) {
|
|
655
656
|
const baseClassName = baseClasses.join(" ");
|
|
656
|
-
const baseStyleObject = parseClassName(baseClassName, state.
|
|
657
|
+
const baseStyleObject = parseClassName(baseClassName, state.customTheme);
|
|
657
658
|
const baseStyleKey = generateStyleKey(baseClassName);
|
|
658
659
|
state.styleRegistry.set(baseStyleKey, baseStyleObject);
|
|
659
660
|
styleExpressions.push(
|
|
@@ -815,7 +816,7 @@ export default function reactNativeTailwindBabelPlugin(
|
|
|
815
816
|
return;
|
|
816
817
|
}
|
|
817
818
|
|
|
818
|
-
const styleObject = parseClassName(classNameForStyle, state.
|
|
819
|
+
const styleObject = parseClassName(classNameForStyle, state.customTheme);
|
|
819
820
|
const styleKey = generateStyleKey(classNameForStyle);
|
|
820
821
|
state.styleRegistry.set(styleKey, styleObject);
|
|
821
822
|
|
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
* Utility functions for processing color scheme modifiers (dark:, light:)
|
|
3
3
|
*/
|
|
4
4
|
import type * as BabelTypes from "@babel/types";
|
|
5
|
-
import type { ParsedModifier } from "../../parser/index.js";
|
|
5
|
+
import type { CustomTheme, ParsedModifier } from "../../parser/index.js";
|
|
6
6
|
import type { StyleObject } from "../../types/core.js";
|
|
7
7
|
/**
|
|
8
8
|
* Plugin state interface (subset needed for color scheme modifier processing)
|
|
9
9
|
*/
|
|
10
10
|
export interface ColorSchemeModifierProcessingState {
|
|
11
11
|
styleRegistry: Map<string, StyleObject>;
|
|
12
|
-
|
|
12
|
+
customTheme: CustomTheme;
|
|
13
13
|
stylesIdentifier: string;
|
|
14
14
|
needsColorSchemeImport: boolean;
|
|
15
15
|
colorSchemeVariableName: string;
|
|
@@ -31,4 +31,4 @@ export interface ColorSchemeModifierProcessingState {
|
|
|
31
31
|
* _twColorScheme === 'light' && styles._light_bg_white
|
|
32
32
|
* ]
|
|
33
33
|
*/
|
|
34
|
-
export declare function processColorSchemeModifiers(colorSchemeModifiers: ParsedModifier[], state: ColorSchemeModifierProcessingState, parseClassName: (className: string,
|
|
34
|
+
export declare function processColorSchemeModifiers(colorSchemeModifiers: ParsedModifier[], state: ColorSchemeModifierProcessingState, parseClassName: (className: string, customTheme?: CustomTheme) => StyleObject, generateStyleKey: (className: string) => string, t: typeof BabelTypes): BabelTypes.Expression[];
|