@mgcrea/react-native-tailwind 0.9.1 → 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 +386 -43
- package/dist/babel/config-loader.d.ts +12 -3
- package/dist/babel/config-loader.test.ts +154 -0
- package/dist/babel/config-loader.ts +41 -9
- package/dist/babel/index.cjs +592 -69
- package/dist/babel/plugin.d.ts +23 -1
- package/dist/babel/plugin.test.ts +331 -0
- package/dist/babel/plugin.ts +268 -37
- package/dist/babel/utils/colorSchemeModifierProcessing.d.ts +34 -0
- package/dist/babel/utils/colorSchemeModifierProcessing.ts +89 -0
- package/dist/babel/utils/dynamicProcessing.d.ts +34 -3
- package/dist/babel/utils/dynamicProcessing.ts +358 -39
- 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/styleInjection.d.ts +13 -0
- package/dist/babel/utils/styleInjection.ts +101 -0
- package/dist/babel/utils/styleTransforms.test.ts +56 -0
- package/dist/babel/utils/twProcessing.d.ts +5 -3
- package/dist/babel/utils/twProcessing.ts +27 -6
- package/dist/parser/index.d.ts +13 -6
- package/dist/parser/index.js +1 -1
- package/dist/parser/modifiers.d.ts +48 -2
- package/dist/parser/modifiers.js +1 -1
- package/dist/parser/modifiers.test.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/dist/types/config.d.ts +7 -0
- package/dist/types/config.js +0 -0
- package/package.json +3 -2
- package/src/babel/config-loader.test.ts +154 -0
- package/src/babel/config-loader.ts +41 -9
- package/src/babel/plugin.test.ts +331 -0
- package/src/babel/plugin.ts +268 -37
- package/src/babel/utils/colorSchemeModifierProcessing.ts +89 -0
- package/src/babel/utils/dynamicProcessing.ts +358 -39
- package/src/babel/utils/modifierProcessing.ts +5 -5
- package/src/babel/utils/platformModifierProcessing.ts +4 -4
- package/src/babel/utils/styleInjection.ts +101 -0
- package/src/babel/utils/styleTransforms.test.ts +56 -0
- package/src/babel/utils/twProcessing.ts +27 -6
- package/src/parser/index.ts +28 -9
- package/src/parser/modifiers.test.ts +151 -1
- package/src/parser/modifiers.ts +139 -4
- package/src/parser/typography.ts +14 -2
- package/src/runtime.test.ts +7 -7
- package/src/runtime.ts +37 -14
- package/src/types/config.ts +7 -0
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
|
|
@@ -1741,7 +1747,14 @@ var STATE_MODIFIERS = [
|
|
|
1741
1747
|
"placeholder"
|
|
1742
1748
|
];
|
|
1743
1749
|
var PLATFORM_MODIFIERS = ["ios", "android", "web"];
|
|
1744
|
-
var
|
|
1750
|
+
var COLOR_SCHEME_MODIFIERS = ["dark", "light"];
|
|
1751
|
+
var SCHEME_MODIFIERS = ["scheme"];
|
|
1752
|
+
var SUPPORTED_MODIFIERS = [
|
|
1753
|
+
...STATE_MODIFIERS,
|
|
1754
|
+
...PLATFORM_MODIFIERS,
|
|
1755
|
+
...COLOR_SCHEME_MODIFIERS,
|
|
1756
|
+
...SCHEME_MODIFIERS
|
|
1757
|
+
];
|
|
1745
1758
|
function parseModifier(cls) {
|
|
1746
1759
|
const colonIndex = cls.indexOf(":");
|
|
1747
1760
|
if (colonIndex === -1) {
|
|
@@ -1769,6 +1782,56 @@ function isStateModifier(modifier) {
|
|
|
1769
1782
|
function isPlatformModifier(modifier) {
|
|
1770
1783
|
return PLATFORM_MODIFIERS.includes(modifier);
|
|
1771
1784
|
}
|
|
1785
|
+
function isColorSchemeModifier(modifier) {
|
|
1786
|
+
return COLOR_SCHEME_MODIFIERS.includes(modifier);
|
|
1787
|
+
}
|
|
1788
|
+
function isSchemeModifier(modifier) {
|
|
1789
|
+
return SCHEME_MODIFIERS.includes(modifier);
|
|
1790
|
+
}
|
|
1791
|
+
function isColorClass(className) {
|
|
1792
|
+
return className.startsWith("text-") || className.startsWith("bg-") || className.startsWith("border-");
|
|
1793
|
+
}
|
|
1794
|
+
function expandSchemeModifier(schemeModifier, customColors, darkSuffix = "-dark", lightSuffix = "-light") {
|
|
1795
|
+
const { baseClass } = schemeModifier;
|
|
1796
|
+
if (!isColorClass(baseClass)) {
|
|
1797
|
+
if (process.env.NODE_ENV !== "production") {
|
|
1798
|
+
console.warn(
|
|
1799
|
+
`[react-native-tailwind] scheme: modifier only supports color classes (text-*, bg-*, border-*). Found: "${baseClass}". This modifier will be ignored.`
|
|
1800
|
+
);
|
|
1801
|
+
}
|
|
1802
|
+
return [];
|
|
1803
|
+
}
|
|
1804
|
+
const match = baseClass.match(/^(text|bg|border)-(.+)$/);
|
|
1805
|
+
if (!match) {
|
|
1806
|
+
return [];
|
|
1807
|
+
}
|
|
1808
|
+
const [, prefix, colorName] = match;
|
|
1809
|
+
const darkColorName = `${colorName}${darkSuffix}`;
|
|
1810
|
+
const lightColorName = `${colorName}${lightSuffix}`;
|
|
1811
|
+
const darkColorExists = customColors[darkColorName] !== void 0;
|
|
1812
|
+
const lightColorExists = customColors[lightColorName] !== void 0;
|
|
1813
|
+
if (!darkColorExists || !lightColorExists) {
|
|
1814
|
+
if (process.env.NODE_ENV !== "production") {
|
|
1815
|
+
const missing = [];
|
|
1816
|
+
if (!darkColorExists) missing.push(`${colorName}${darkSuffix}`);
|
|
1817
|
+
if (!lightColorExists) missing.push(`${colorName}${lightSuffix}`);
|
|
1818
|
+
console.warn(
|
|
1819
|
+
`[react-native-tailwind] scheme:${baseClass} requires both color variants to exist. Missing: ${missing.join(", ")}. This modifier will be ignored.`
|
|
1820
|
+
);
|
|
1821
|
+
}
|
|
1822
|
+
return [];
|
|
1823
|
+
}
|
|
1824
|
+
return [
|
|
1825
|
+
{
|
|
1826
|
+
modifier: "dark",
|
|
1827
|
+
baseClass: `${prefix}-${darkColorName}`
|
|
1828
|
+
},
|
|
1829
|
+
{
|
|
1830
|
+
modifier: "light",
|
|
1831
|
+
baseClass: `${prefix}-${lightColorName}`
|
|
1832
|
+
}
|
|
1833
|
+
];
|
|
1834
|
+
}
|
|
1772
1835
|
function splitModifierClasses(className) {
|
|
1773
1836
|
const classes = className.trim().split(/\s+/).filter(Boolean);
|
|
1774
1837
|
const baseClasses = [];
|
|
@@ -1785,22 +1848,22 @@ function splitModifierClasses(className) {
|
|
|
1785
1848
|
}
|
|
1786
1849
|
|
|
1787
1850
|
// src/parser/index.ts
|
|
1788
|
-
function parseClassName(className,
|
|
1851
|
+
function parseClassName(className, customTheme) {
|
|
1789
1852
|
const classes = className.split(/\s+/).filter(Boolean);
|
|
1790
1853
|
const style = {};
|
|
1791
1854
|
for (const cls of classes) {
|
|
1792
|
-
const parsedStyle = parseClass(cls,
|
|
1855
|
+
const parsedStyle = parseClass(cls, customTheme);
|
|
1793
1856
|
Object.assign(style, parsedStyle);
|
|
1794
1857
|
}
|
|
1795
1858
|
return style;
|
|
1796
1859
|
}
|
|
1797
|
-
function parseClass(cls,
|
|
1860
|
+
function parseClass(cls, customTheme) {
|
|
1798
1861
|
const parsers = [
|
|
1799
1862
|
parseSpacing,
|
|
1800
1863
|
parseBorder,
|
|
1801
|
-
(cls2) => parseColor(cls2,
|
|
1864
|
+
(cls2) => parseColor(cls2, customTheme?.colors),
|
|
1802
1865
|
parseLayout,
|
|
1803
|
-
parseTypography,
|
|
1866
|
+
(cls2) => parseTypography(cls2, customTheme?.fontFamily),
|
|
1804
1867
|
parseSizing,
|
|
1805
1868
|
parseShadow,
|
|
1806
1869
|
parseAspectRatio,
|
|
@@ -1868,15 +1931,15 @@ function loadTailwindConfig(configPath) {
|
|
|
1868
1931
|
return null;
|
|
1869
1932
|
}
|
|
1870
1933
|
}
|
|
1871
|
-
function
|
|
1934
|
+
function extractCustomTheme(filename) {
|
|
1872
1935
|
const projectDir = path.dirname(filename);
|
|
1873
1936
|
const configPath = findTailwindConfig(projectDir);
|
|
1874
1937
|
if (!configPath) {
|
|
1875
|
-
return {};
|
|
1938
|
+
return { colors: {}, fontFamily: {} };
|
|
1876
1939
|
}
|
|
1877
1940
|
const config = loadTailwindConfig(configPath);
|
|
1878
1941
|
if (!config?.theme) {
|
|
1879
|
-
return {};
|
|
1942
|
+
return { colors: {}, fontFamily: {} };
|
|
1880
1943
|
}
|
|
1881
1944
|
if (config.theme.colors && !config.theme.extend?.colors && process.env.NODE_ENV !== "production") {
|
|
1882
1945
|
console.warn(
|
|
@@ -1884,7 +1947,24 @@ function extractCustomColors(filename) {
|
|
|
1884
1947
|
);
|
|
1885
1948
|
}
|
|
1886
1949
|
const colors = config.theme.extend?.colors ?? config.theme.colors ?? {};
|
|
1887
|
-
|
|
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
|
+
};
|
|
1888
1968
|
}
|
|
1889
1969
|
|
|
1890
1970
|
// src/babel/utils/attributeMatchers.ts
|
|
@@ -1923,6 +2003,38 @@ function getTargetStyleProp(attributeName) {
|
|
|
1923
2003
|
return attributeName.endsWith("ClassName") ? attributeName.replace("ClassName", "Style") : "style";
|
|
1924
2004
|
}
|
|
1925
2005
|
|
|
2006
|
+
// src/babel/utils/colorSchemeModifierProcessing.ts
|
|
2007
|
+
function processColorSchemeModifiers(colorSchemeModifiers, state, parseClassName2, generateStyleKey2, t) {
|
|
2008
|
+
state.needsColorSchemeImport = true;
|
|
2009
|
+
const modifiersByScheme = /* @__PURE__ */ new Map();
|
|
2010
|
+
for (const mod of colorSchemeModifiers) {
|
|
2011
|
+
const scheme = mod.modifier;
|
|
2012
|
+
if (!modifiersByScheme.has(scheme)) {
|
|
2013
|
+
modifiersByScheme.set(scheme, []);
|
|
2014
|
+
}
|
|
2015
|
+
const schemeGroup = modifiersByScheme.get(scheme);
|
|
2016
|
+
if (schemeGroup) {
|
|
2017
|
+
schemeGroup.push(mod);
|
|
2018
|
+
}
|
|
2019
|
+
}
|
|
2020
|
+
const conditionalExpressions = [];
|
|
2021
|
+
for (const [scheme, modifiers] of modifiersByScheme) {
|
|
2022
|
+
const classNames = modifiers.map((m) => m.baseClass).join(" ");
|
|
2023
|
+
const styleObject = parseClassName2(classNames, state.customTheme);
|
|
2024
|
+
const styleKey = generateStyleKey2(`${scheme}_${classNames}`);
|
|
2025
|
+
state.styleRegistry.set(styleKey, styleObject);
|
|
2026
|
+
const colorSchemeCheck = t.binaryExpression(
|
|
2027
|
+
"===",
|
|
2028
|
+
t.identifier(state.colorSchemeVariableName),
|
|
2029
|
+
t.stringLiteral(scheme)
|
|
2030
|
+
);
|
|
2031
|
+
const styleReference = t.memberExpression(t.identifier(state.stylesIdentifier), t.identifier(styleKey));
|
|
2032
|
+
const conditionalExpression = t.logicalExpression("&&", colorSchemeCheck, styleReference);
|
|
2033
|
+
conditionalExpressions.push(conditionalExpression);
|
|
2034
|
+
}
|
|
2035
|
+
return conditionalExpressions;
|
|
2036
|
+
}
|
|
2037
|
+
|
|
1926
2038
|
// src/babel/utils/componentSupport.ts
|
|
1927
2039
|
function getComponentModifierSupport(jsxElement, t) {
|
|
1928
2040
|
if (!t.isJSXOpeningElement(jsxElement)) {
|
|
@@ -1967,32 +2079,89 @@ function getStatePropertyForModifier(modifier) {
|
|
|
1967
2079
|
}
|
|
1968
2080
|
|
|
1969
2081
|
// src/babel/utils/dynamicProcessing.ts
|
|
1970
|
-
function processDynamicExpression(expression, state, parseClassName2, generateStyleKey2, t) {
|
|
2082
|
+
function processDynamicExpression(expression, state, parseClassName2, generateStyleKey2, splitModifierClasses2, processPlatformModifiers2, processColorSchemeModifiers2, componentScope, isPlatformModifier2, isColorSchemeModifier2, isSchemeModifier2, expandSchemeModifier2, t) {
|
|
1971
2083
|
if (t.isTemplateLiteral(expression)) {
|
|
1972
|
-
return processTemplateLiteral(
|
|
2084
|
+
return processTemplateLiteral(
|
|
2085
|
+
expression,
|
|
2086
|
+
state,
|
|
2087
|
+
parseClassName2,
|
|
2088
|
+
generateStyleKey2,
|
|
2089
|
+
splitModifierClasses2,
|
|
2090
|
+
processPlatformModifiers2,
|
|
2091
|
+
processColorSchemeModifiers2,
|
|
2092
|
+
componentScope,
|
|
2093
|
+
isPlatformModifier2,
|
|
2094
|
+
isColorSchemeModifier2,
|
|
2095
|
+
isSchemeModifier2,
|
|
2096
|
+
expandSchemeModifier2,
|
|
2097
|
+
t
|
|
2098
|
+
);
|
|
1973
2099
|
}
|
|
1974
2100
|
if (t.isConditionalExpression(expression)) {
|
|
1975
|
-
return processConditionalExpression(
|
|
2101
|
+
return processConditionalExpression(
|
|
2102
|
+
expression,
|
|
2103
|
+
state,
|
|
2104
|
+
parseClassName2,
|
|
2105
|
+
generateStyleKey2,
|
|
2106
|
+
splitModifierClasses2,
|
|
2107
|
+
processPlatformModifiers2,
|
|
2108
|
+
processColorSchemeModifiers2,
|
|
2109
|
+
componentScope,
|
|
2110
|
+
isPlatformModifier2,
|
|
2111
|
+
isColorSchemeModifier2,
|
|
2112
|
+
isSchemeModifier2,
|
|
2113
|
+
expandSchemeModifier2,
|
|
2114
|
+
t
|
|
2115
|
+
);
|
|
1976
2116
|
}
|
|
1977
2117
|
if (t.isLogicalExpression(expression)) {
|
|
1978
|
-
return processLogicalExpression(
|
|
2118
|
+
return processLogicalExpression(
|
|
2119
|
+
expression,
|
|
2120
|
+
state,
|
|
2121
|
+
parseClassName2,
|
|
2122
|
+
generateStyleKey2,
|
|
2123
|
+
splitModifierClasses2,
|
|
2124
|
+
processPlatformModifiers2,
|
|
2125
|
+
processColorSchemeModifiers2,
|
|
2126
|
+
componentScope,
|
|
2127
|
+
isPlatformModifier2,
|
|
2128
|
+
isColorSchemeModifier2,
|
|
2129
|
+
isSchemeModifier2,
|
|
2130
|
+
expandSchemeModifier2,
|
|
2131
|
+
t
|
|
2132
|
+
);
|
|
1979
2133
|
}
|
|
1980
2134
|
return null;
|
|
1981
2135
|
}
|
|
1982
|
-
function processTemplateLiteral(node, state, parseClassName2, generateStyleKey2, t) {
|
|
2136
|
+
function processTemplateLiteral(node, state, parseClassName2, generateStyleKey2, splitModifierClasses2, processPlatformModifiers2, processColorSchemeModifiers2, componentScope, isPlatformModifier2, isColorSchemeModifier2, isSchemeModifier2, expandSchemeModifier2, t) {
|
|
1983
2137
|
const parts = [];
|
|
1984
2138
|
const staticParts = [];
|
|
1985
2139
|
for (let i = 0; i < node.quasis.length; i++) {
|
|
1986
2140
|
const quasi = node.quasis[i];
|
|
1987
2141
|
const staticText = quasi.value.cooked?.trim();
|
|
1988
2142
|
if (staticText) {
|
|
1989
|
-
const
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
2143
|
+
const processedExpression = processStringOrExpressionHelper(
|
|
2144
|
+
t.stringLiteral(staticText),
|
|
2145
|
+
state,
|
|
2146
|
+
parseClassName2,
|
|
2147
|
+
generateStyleKey2,
|
|
2148
|
+
splitModifierClasses2,
|
|
2149
|
+
processPlatformModifiers2,
|
|
2150
|
+
processColorSchemeModifiers2,
|
|
2151
|
+
componentScope,
|
|
2152
|
+
isPlatformModifier2,
|
|
2153
|
+
isColorSchemeModifier2,
|
|
2154
|
+
isSchemeModifier2,
|
|
2155
|
+
expandSchemeModifier2,
|
|
2156
|
+
t
|
|
2157
|
+
);
|
|
2158
|
+
if (processedExpression) {
|
|
2159
|
+
staticParts.push(staticText);
|
|
2160
|
+
if (t.isArrayExpression(processedExpression)) {
|
|
2161
|
+
parts.push(...processedExpression.elements);
|
|
2162
|
+
} else {
|
|
2163
|
+
parts.push(processedExpression);
|
|
2164
|
+
}
|
|
1996
2165
|
}
|
|
1997
2166
|
}
|
|
1998
2167
|
if (i < node.expressions.length) {
|
|
@@ -2002,6 +2171,14 @@ function processTemplateLiteral(node, state, parseClassName2, generateStyleKey2,
|
|
|
2002
2171
|
state,
|
|
2003
2172
|
parseClassName2,
|
|
2004
2173
|
generateStyleKey2,
|
|
2174
|
+
splitModifierClasses2,
|
|
2175
|
+
processPlatformModifiers2,
|
|
2176
|
+
processColorSchemeModifiers2,
|
|
2177
|
+
componentScope,
|
|
2178
|
+
isPlatformModifier2,
|
|
2179
|
+
isColorSchemeModifier2,
|
|
2180
|
+
isSchemeModifier2,
|
|
2181
|
+
expandSchemeModifier2,
|
|
2005
2182
|
t
|
|
2006
2183
|
);
|
|
2007
2184
|
if (result) {
|
|
@@ -2020,9 +2197,37 @@ function processTemplateLiteral(node, state, parseClassName2, generateStyleKey2,
|
|
|
2020
2197
|
staticParts: staticParts.length > 0 ? staticParts : void 0
|
|
2021
2198
|
};
|
|
2022
2199
|
}
|
|
2023
|
-
function processConditionalExpression(node, state, parseClassName2, generateStyleKey2, t) {
|
|
2024
|
-
const consequent =
|
|
2025
|
-
|
|
2200
|
+
function processConditionalExpression(node, state, parseClassName2, generateStyleKey2, splitModifierClasses2, processPlatformModifiers2, processColorSchemeModifiers2, componentScope, isPlatformModifier2, isColorSchemeModifier2, isSchemeModifier2, expandSchemeModifier2, t) {
|
|
2201
|
+
const consequent = processStringOrExpressionHelper(
|
|
2202
|
+
node.consequent,
|
|
2203
|
+
state,
|
|
2204
|
+
parseClassName2,
|
|
2205
|
+
generateStyleKey2,
|
|
2206
|
+
splitModifierClasses2,
|
|
2207
|
+
processPlatformModifiers2,
|
|
2208
|
+
processColorSchemeModifiers2,
|
|
2209
|
+
componentScope,
|
|
2210
|
+
isPlatformModifier2,
|
|
2211
|
+
isColorSchemeModifier2,
|
|
2212
|
+
isSchemeModifier2,
|
|
2213
|
+
expandSchemeModifier2,
|
|
2214
|
+
t
|
|
2215
|
+
);
|
|
2216
|
+
const alternate = processStringOrExpressionHelper(
|
|
2217
|
+
node.alternate,
|
|
2218
|
+
state,
|
|
2219
|
+
parseClassName2,
|
|
2220
|
+
generateStyleKey2,
|
|
2221
|
+
splitModifierClasses2,
|
|
2222
|
+
processPlatformModifiers2,
|
|
2223
|
+
processColorSchemeModifiers2,
|
|
2224
|
+
componentScope,
|
|
2225
|
+
isPlatformModifier2,
|
|
2226
|
+
isColorSchemeModifier2,
|
|
2227
|
+
isSchemeModifier2,
|
|
2228
|
+
expandSchemeModifier2,
|
|
2229
|
+
t
|
|
2230
|
+
);
|
|
2026
2231
|
if (!consequent && !alternate) {
|
|
2027
2232
|
return null;
|
|
2028
2233
|
}
|
|
@@ -2033,38 +2238,153 @@ function processConditionalExpression(node, state, parseClassName2, generateStyl
|
|
|
2033
2238
|
);
|
|
2034
2239
|
return { expression };
|
|
2035
2240
|
}
|
|
2036
|
-
function processLogicalExpression(node, state, parseClassName2, generateStyleKey2, t) {
|
|
2241
|
+
function processLogicalExpression(node, state, parseClassName2, generateStyleKey2, splitModifierClasses2, processPlatformModifiers2, processColorSchemeModifiers2, componentScope, isPlatformModifier2, isColorSchemeModifier2, isSchemeModifier2, expandSchemeModifier2, t) {
|
|
2037
2242
|
if (node.operator !== "&&") {
|
|
2038
2243
|
return null;
|
|
2039
2244
|
}
|
|
2040
|
-
const right =
|
|
2245
|
+
const right = processStringOrExpressionHelper(
|
|
2246
|
+
node.right,
|
|
2247
|
+
state,
|
|
2248
|
+
parseClassName2,
|
|
2249
|
+
generateStyleKey2,
|
|
2250
|
+
splitModifierClasses2,
|
|
2251
|
+
processPlatformModifiers2,
|
|
2252
|
+
processColorSchemeModifiers2,
|
|
2253
|
+
componentScope,
|
|
2254
|
+
isPlatformModifier2,
|
|
2255
|
+
isColorSchemeModifier2,
|
|
2256
|
+
isSchemeModifier2,
|
|
2257
|
+
expandSchemeModifier2,
|
|
2258
|
+
t
|
|
2259
|
+
);
|
|
2041
2260
|
if (!right) {
|
|
2042
2261
|
return null;
|
|
2043
2262
|
}
|
|
2044
2263
|
const expression = t.logicalExpression("&&", node.left, right);
|
|
2045
2264
|
return { expression };
|
|
2046
2265
|
}
|
|
2047
|
-
function
|
|
2266
|
+
function processStringOrExpressionHelper(node, state, parseClassName2, generateStyleKey2, splitModifierClasses2, processPlatformModifiers2, processColorSchemeModifiers2, componentScope, isPlatformModifier2, isColorSchemeModifier2, isSchemeModifier2, expandSchemeModifier2, t) {
|
|
2048
2267
|
if (t.isStringLiteral(node)) {
|
|
2049
2268
|
const className = node.value.trim();
|
|
2050
2269
|
if (!className) {
|
|
2051
2270
|
return null;
|
|
2052
2271
|
}
|
|
2053
|
-
const
|
|
2054
|
-
const
|
|
2055
|
-
|
|
2056
|
-
|
|
2272
|
+
const { baseClasses, modifierClasses: rawModifierClasses } = splitModifierClasses2(className);
|
|
2273
|
+
const modifierClasses = [];
|
|
2274
|
+
for (const modifier of rawModifierClasses) {
|
|
2275
|
+
if (isSchemeModifier2(modifier.modifier)) {
|
|
2276
|
+
const expanded = expandSchemeModifier2(
|
|
2277
|
+
modifier,
|
|
2278
|
+
state.customTheme.colors ?? {},
|
|
2279
|
+
state.schemeModifierConfig.darkSuffix ?? "-dark",
|
|
2280
|
+
state.schemeModifierConfig.lightSuffix ?? "-light"
|
|
2281
|
+
);
|
|
2282
|
+
modifierClasses.push(...expanded);
|
|
2283
|
+
} else {
|
|
2284
|
+
modifierClasses.push(modifier);
|
|
2285
|
+
}
|
|
2286
|
+
}
|
|
2287
|
+
const platformModifiers = modifierClasses.filter((m) => isPlatformModifier2(m.modifier));
|
|
2288
|
+
const colorSchemeModifiers = modifierClasses.filter((m) => isColorSchemeModifier2(m.modifier));
|
|
2289
|
+
const styleElements = [];
|
|
2290
|
+
if (baseClasses.length > 0) {
|
|
2291
|
+
const baseClassName = baseClasses.join(" ");
|
|
2292
|
+
const styleObject = parseClassName2(baseClassName, state.customTheme);
|
|
2293
|
+
const styleKey = generateStyleKey2(baseClassName);
|
|
2294
|
+
state.styleRegistry.set(styleKey, styleObject);
|
|
2295
|
+
styleElements.push(t.memberExpression(t.identifier(state.stylesIdentifier), t.identifier(styleKey)));
|
|
2296
|
+
}
|
|
2297
|
+
if (platformModifiers.length > 0) {
|
|
2298
|
+
state.needsPlatformImport = true;
|
|
2299
|
+
const platformExpression = processPlatformModifiers2(
|
|
2300
|
+
platformModifiers,
|
|
2301
|
+
state,
|
|
2302
|
+
parseClassName2,
|
|
2303
|
+
generateStyleKey2,
|
|
2304
|
+
t
|
|
2305
|
+
);
|
|
2306
|
+
styleElements.push(platformExpression);
|
|
2307
|
+
}
|
|
2308
|
+
if (colorSchemeModifiers.length > 0) {
|
|
2309
|
+
if (componentScope) {
|
|
2310
|
+
state.needsColorSchemeImport = true;
|
|
2311
|
+
state.functionComponentsNeedingColorScheme.add(componentScope);
|
|
2312
|
+
const colorSchemeExpressions = processColorSchemeModifiers2(
|
|
2313
|
+
colorSchemeModifiers,
|
|
2314
|
+
state,
|
|
2315
|
+
parseClassName2,
|
|
2316
|
+
generateStyleKey2,
|
|
2317
|
+
t
|
|
2318
|
+
);
|
|
2319
|
+
styleElements.push(...colorSchemeExpressions);
|
|
2320
|
+
} else {
|
|
2321
|
+
if (process.env.NODE_ENV !== "production") {
|
|
2322
|
+
console.warn(
|
|
2323
|
+
"[react-native-tailwind] dark:/light: modifiers in dynamic expressions require a function component scope. These modifiers will be ignored."
|
|
2324
|
+
);
|
|
2325
|
+
}
|
|
2326
|
+
}
|
|
2327
|
+
}
|
|
2328
|
+
if (styleElements.length === 0) {
|
|
2329
|
+
return null;
|
|
2330
|
+
}
|
|
2331
|
+
if (styleElements.length === 1) {
|
|
2332
|
+
return styleElements[0];
|
|
2333
|
+
}
|
|
2334
|
+
return t.arrayExpression(styleElements);
|
|
2057
2335
|
}
|
|
2058
2336
|
if (t.isConditionalExpression(node)) {
|
|
2059
|
-
const result = processConditionalExpression(
|
|
2337
|
+
const result = processConditionalExpression(
|
|
2338
|
+
node,
|
|
2339
|
+
state,
|
|
2340
|
+
parseClassName2,
|
|
2341
|
+
generateStyleKey2,
|
|
2342
|
+
splitModifierClasses2,
|
|
2343
|
+
processPlatformModifiers2,
|
|
2344
|
+
processColorSchemeModifiers2,
|
|
2345
|
+
componentScope,
|
|
2346
|
+
isPlatformModifier2,
|
|
2347
|
+
isColorSchemeModifier2,
|
|
2348
|
+
isSchemeModifier2,
|
|
2349
|
+
expandSchemeModifier2,
|
|
2350
|
+
t
|
|
2351
|
+
);
|
|
2060
2352
|
return result?.expression ?? null;
|
|
2061
2353
|
}
|
|
2062
2354
|
if (t.isLogicalExpression(node)) {
|
|
2063
|
-
const result = processLogicalExpression(
|
|
2355
|
+
const result = processLogicalExpression(
|
|
2356
|
+
node,
|
|
2357
|
+
state,
|
|
2358
|
+
parseClassName2,
|
|
2359
|
+
generateStyleKey2,
|
|
2360
|
+
splitModifierClasses2,
|
|
2361
|
+
processPlatformModifiers2,
|
|
2362
|
+
processColorSchemeModifiers2,
|
|
2363
|
+
componentScope,
|
|
2364
|
+
isPlatformModifier2,
|
|
2365
|
+
isColorSchemeModifier2,
|
|
2366
|
+
isSchemeModifier2,
|
|
2367
|
+
expandSchemeModifier2,
|
|
2368
|
+
t
|
|
2369
|
+
);
|
|
2064
2370
|
return result?.expression ?? null;
|
|
2065
2371
|
}
|
|
2066
2372
|
if (t.isTemplateLiteral(node)) {
|
|
2067
|
-
const result = processTemplateLiteral(
|
|
2373
|
+
const result = processTemplateLiteral(
|
|
2374
|
+
node,
|
|
2375
|
+
state,
|
|
2376
|
+
parseClassName2,
|
|
2377
|
+
generateStyleKey2,
|
|
2378
|
+
splitModifierClasses2,
|
|
2379
|
+
processPlatformModifiers2,
|
|
2380
|
+
processColorSchemeModifiers2,
|
|
2381
|
+
componentScope,
|
|
2382
|
+
isPlatformModifier2,
|
|
2383
|
+
isColorSchemeModifier2,
|
|
2384
|
+
isSchemeModifier2,
|
|
2385
|
+
expandSchemeModifier2,
|
|
2386
|
+
t
|
|
2387
|
+
);
|
|
2068
2388
|
return result?.expression ?? null;
|
|
2069
2389
|
}
|
|
2070
2390
|
return null;
|
|
@@ -2076,7 +2396,7 @@ function processStaticClassNameWithModifiers(className, state, parseClassName2,
|
|
|
2076
2396
|
let baseStyleExpression = null;
|
|
2077
2397
|
if (baseClasses.length > 0) {
|
|
2078
2398
|
const baseClassName = baseClasses.join(" ");
|
|
2079
|
-
const baseStyleObject = parseClassName2(baseClassName, state.
|
|
2399
|
+
const baseStyleObject = parseClassName2(baseClassName, state.customTheme);
|
|
2080
2400
|
const baseStyleKey = generateStyleKey2(baseClassName);
|
|
2081
2401
|
state.styleRegistry.set(baseStyleKey, baseStyleObject);
|
|
2082
2402
|
baseStyleExpression = t.memberExpression(t.identifier(state.stylesIdentifier), t.identifier(baseStyleKey));
|
|
@@ -2097,7 +2417,7 @@ function processStaticClassNameWithModifiers(className, state, parseClassName2,
|
|
|
2097
2417
|
}
|
|
2098
2418
|
for (const [modifierType, modifiers] of modifiersByType) {
|
|
2099
2419
|
const modifierClassNames = modifiers.map((m) => m.baseClass).join(" ");
|
|
2100
|
-
const modifierStyleObject = parseClassName2(modifierClassNames, state.
|
|
2420
|
+
const modifierStyleObject = parseClassName2(modifierClassNames, state.customTheme);
|
|
2101
2421
|
const modifierStyleKey = generateStyleKey2(`${modifierType}_${modifierClassNames}`);
|
|
2102
2422
|
state.styleRegistry.set(modifierStyleKey, modifierStyleObject);
|
|
2103
2423
|
const stateProperty = getStatePropertyForModifier(modifierType);
|
|
@@ -2146,7 +2466,7 @@ function processPlatformModifiers(platformModifiers, state, parseClassName2, gen
|
|
|
2146
2466
|
const selectProperties = [];
|
|
2147
2467
|
for (const [platform, modifiers] of modifiersByPlatform) {
|
|
2148
2468
|
const classNames = modifiers.map((m) => m.baseClass).join(" ");
|
|
2149
|
-
const styleObject = parseClassName2(classNames, state.
|
|
2469
|
+
const styleObject = parseClassName2(classNames, state.customTheme);
|
|
2150
2470
|
const styleKey = generateStyleKey2(`${platform}_${classNames}`);
|
|
2151
2471
|
state.styleRegistry.set(styleKey, styleObject);
|
|
2152
2472
|
const styleReference = t.memberExpression(t.identifier(state.stylesIdentifier), t.identifier(styleKey));
|
|
@@ -2198,6 +2518,63 @@ function addPlatformImport(path2, t) {
|
|
|
2198
2518
|
path2.unshiftContainer("body", importDeclaration);
|
|
2199
2519
|
}
|
|
2200
2520
|
}
|
|
2521
|
+
function addColorSchemeImport(path2, t) {
|
|
2522
|
+
const body = path2.node.body;
|
|
2523
|
+
let reactNativeImport = null;
|
|
2524
|
+
for (const statement of body) {
|
|
2525
|
+
if (t.isImportDeclaration(statement) && statement.source.value === "react-native") {
|
|
2526
|
+
reactNativeImport = statement;
|
|
2527
|
+
break;
|
|
2528
|
+
}
|
|
2529
|
+
}
|
|
2530
|
+
if (reactNativeImport) {
|
|
2531
|
+
const hasUseColorScheme = reactNativeImport.specifiers.some(
|
|
2532
|
+
(spec) => t.isImportSpecifier(spec) && spec.imported.type === "Identifier" && spec.imported.name === "useColorScheme"
|
|
2533
|
+
);
|
|
2534
|
+
if (!hasUseColorScheme) {
|
|
2535
|
+
reactNativeImport.specifiers.push(
|
|
2536
|
+
t.importSpecifier(t.identifier("useColorScheme"), t.identifier("useColorScheme"))
|
|
2537
|
+
);
|
|
2538
|
+
}
|
|
2539
|
+
} else {
|
|
2540
|
+
const importDeclaration = t.importDeclaration(
|
|
2541
|
+
[t.importSpecifier(t.identifier("useColorScheme"), t.identifier("useColorScheme"))],
|
|
2542
|
+
t.stringLiteral("react-native")
|
|
2543
|
+
);
|
|
2544
|
+
path2.unshiftContainer("body", importDeclaration);
|
|
2545
|
+
}
|
|
2546
|
+
}
|
|
2547
|
+
function injectColorSchemeHook(functionPath, colorSchemeVariableName, t) {
|
|
2548
|
+
let body = functionPath.node.body;
|
|
2549
|
+
if (!t.isBlockStatement(body)) {
|
|
2550
|
+
if (t.isArrowFunctionExpression(functionPath.node) && t.isExpression(body)) {
|
|
2551
|
+
const returnStatement = t.returnStatement(body);
|
|
2552
|
+
const blockStatement = t.blockStatement([returnStatement]);
|
|
2553
|
+
functionPath.node.body = blockStatement;
|
|
2554
|
+
body = blockStatement;
|
|
2555
|
+
} else {
|
|
2556
|
+
return false;
|
|
2557
|
+
}
|
|
2558
|
+
}
|
|
2559
|
+
const hasHook = body.body.some((statement) => {
|
|
2560
|
+
if (t.isVariableDeclaration(statement) && statement.declarations.length > 0 && t.isVariableDeclarator(statement.declarations[0])) {
|
|
2561
|
+
const declarator = statement.declarations[0];
|
|
2562
|
+
return t.isIdentifier(declarator.id) && declarator.id.name === colorSchemeVariableName;
|
|
2563
|
+
}
|
|
2564
|
+
return false;
|
|
2565
|
+
});
|
|
2566
|
+
if (hasHook) {
|
|
2567
|
+
return false;
|
|
2568
|
+
}
|
|
2569
|
+
const hookCall = t.variableDeclaration("const", [
|
|
2570
|
+
t.variableDeclarator(
|
|
2571
|
+
t.identifier(colorSchemeVariableName),
|
|
2572
|
+
t.callExpression(t.identifier("useColorScheme"), [])
|
|
2573
|
+
)
|
|
2574
|
+
]);
|
|
2575
|
+
body.body.unshift(hookCall);
|
|
2576
|
+
return true;
|
|
2577
|
+
}
|
|
2201
2578
|
function injectStylesAtTop(path2, styleRegistry, stylesIdentifier, t) {
|
|
2202
2579
|
const styleProperties = [];
|
|
2203
2580
|
for (const [key, styleObject] of styleRegistry) {
|
|
@@ -2348,11 +2725,25 @@ function addOrMergePlaceholderTextColorProp(jsxOpeningElement, color, t) {
|
|
|
2348
2725
|
|
|
2349
2726
|
// src/babel/utils/twProcessing.ts
|
|
2350
2727
|
function processTwCall(className, path2, state, parseClassName2, generateStyleKey2, splitModifierClasses2, t) {
|
|
2351
|
-
const { baseClasses, modifierClasses } = splitModifierClasses2(className);
|
|
2728
|
+
const { baseClasses, modifierClasses: rawModifierClasses } = splitModifierClasses2(className);
|
|
2729
|
+
const modifierClasses = [];
|
|
2730
|
+
for (const modifier of rawModifierClasses) {
|
|
2731
|
+
if (isSchemeModifier(modifier.modifier)) {
|
|
2732
|
+
const expanded = expandSchemeModifier(
|
|
2733
|
+
modifier,
|
|
2734
|
+
state.customTheme.colors ?? {},
|
|
2735
|
+
state.schemeModifierConfig.darkSuffix ?? "-dark",
|
|
2736
|
+
state.schemeModifierConfig.lightSuffix ?? "-light"
|
|
2737
|
+
);
|
|
2738
|
+
modifierClasses.push(...expanded);
|
|
2739
|
+
} else {
|
|
2740
|
+
modifierClasses.push(modifier);
|
|
2741
|
+
}
|
|
2742
|
+
}
|
|
2352
2743
|
const objectProperties = [];
|
|
2353
2744
|
if (baseClasses.length > 0) {
|
|
2354
2745
|
const baseClassName = baseClasses.join(" ");
|
|
2355
|
-
const baseStyleObject = parseClassName2(baseClassName, state.
|
|
2746
|
+
const baseStyleObject = parseClassName2(baseClassName, state.customTheme);
|
|
2356
2747
|
const baseStyleKey = generateStyleKey2(baseClassName);
|
|
2357
2748
|
state.styleRegistry.set(baseStyleKey, baseStyleObject);
|
|
2358
2749
|
objectProperties.push(
|
|
@@ -2376,7 +2767,7 @@ function processTwCall(className, path2, state, parseClassName2, generateStyleKe
|
|
|
2376
2767
|
}
|
|
2377
2768
|
for (const [modifierType, modifiers] of modifiersByType) {
|
|
2378
2769
|
const modifierClassNames = modifiers.map((m) => m.baseClass).join(" ");
|
|
2379
|
-
const modifierStyleObject = parseClassName2(modifierClassNames, state.
|
|
2770
|
+
const modifierStyleObject = parseClassName2(modifierClassNames, state.customTheme);
|
|
2380
2771
|
const modifierStyleKey = generateStyleKey2(`${modifierType}_${modifierClassNames}`);
|
|
2381
2772
|
state.styleRegistry.set(modifierStyleKey, modifierStyleObject);
|
|
2382
2773
|
const propertyName = `${modifierType}Style`;
|
|
@@ -2415,10 +2806,52 @@ function removeTwImports(path2, t) {
|
|
|
2415
2806
|
|
|
2416
2807
|
// src/babel/plugin.ts
|
|
2417
2808
|
var DEFAULT_STYLES_IDENTIFIER = "_twStyles";
|
|
2809
|
+
function isComponentScope(functionPath, t) {
|
|
2810
|
+
const node = functionPath.node;
|
|
2811
|
+
const parent = functionPath.parent;
|
|
2812
|
+
const parentPath = functionPath.parentPath;
|
|
2813
|
+
if (t.isClassMethod(parent)) {
|
|
2814
|
+
return false;
|
|
2815
|
+
}
|
|
2816
|
+
if (functionPath.findParent((p) => t.isClassBody(p.node))) {
|
|
2817
|
+
return false;
|
|
2818
|
+
}
|
|
2819
|
+
if (t.isFunctionDeclaration(node)) {
|
|
2820
|
+
if (t.isProgram(parent) || t.isExportNamedDeclaration(parent) || t.isExportDefaultDeclaration(parent)) {
|
|
2821
|
+
return true;
|
|
2822
|
+
}
|
|
2823
|
+
}
|
|
2824
|
+
if (t.isFunctionExpression(node) || t.isArrowFunctionExpression(node)) {
|
|
2825
|
+
if (t.isVariableDeclarator(parent)) {
|
|
2826
|
+
const varDeclarationPath = parentPath?.parentPath;
|
|
2827
|
+
if (varDeclarationPath && t.isVariableDeclaration(varDeclarationPath.node) && (t.isProgram(varDeclarationPath.parent) || t.isExportNamedDeclaration(varDeclarationPath.parent))) {
|
|
2828
|
+
if (t.isIdentifier(parent.id)) {
|
|
2829
|
+
const name = parent.id.name;
|
|
2830
|
+
return /^[A-Z]/.test(name);
|
|
2831
|
+
}
|
|
2832
|
+
}
|
|
2833
|
+
}
|
|
2834
|
+
}
|
|
2835
|
+
return false;
|
|
2836
|
+
}
|
|
2837
|
+
function findComponentScope(path2, t) {
|
|
2838
|
+
let current = path2.getFunctionParent();
|
|
2839
|
+
while (current) {
|
|
2840
|
+
if (t.isFunction(current.node) && isComponentScope(current, t)) {
|
|
2841
|
+
return current;
|
|
2842
|
+
}
|
|
2843
|
+
current = current.getFunctionParent();
|
|
2844
|
+
}
|
|
2845
|
+
return null;
|
|
2846
|
+
}
|
|
2418
2847
|
function reactNativeTailwindBabelPlugin({ types: t }, options) {
|
|
2419
2848
|
const attributes = options?.attributes ?? [...DEFAULT_CLASS_ATTRIBUTES];
|
|
2420
2849
|
const { exactMatches, patterns } = buildAttributeMatchers(attributes);
|
|
2421
2850
|
const stylesIdentifier = options?.stylesIdentifier ?? DEFAULT_STYLES_IDENTIFIER;
|
|
2851
|
+
const schemeModifierConfig = {
|
|
2852
|
+
darkSuffix: options?.schemeModifier?.darkSuffix ?? "-dark",
|
|
2853
|
+
lightSuffix: options?.schemeModifier?.lightSuffix ?? "-light"
|
|
2854
|
+
};
|
|
2422
2855
|
return {
|
|
2423
2856
|
name: "react-native-tailwind",
|
|
2424
2857
|
visitor: {
|
|
@@ -2429,12 +2862,17 @@ function reactNativeTailwindBabelPlugin({ types: t }, options) {
|
|
|
2429
2862
|
state.hasStyleSheetImport = false;
|
|
2430
2863
|
state.hasPlatformImport = false;
|
|
2431
2864
|
state.needsPlatformImport = false;
|
|
2865
|
+
state.hasColorSchemeImport = false;
|
|
2866
|
+
state.needsColorSchemeImport = false;
|
|
2867
|
+
state.colorSchemeVariableName = "_twColorScheme";
|
|
2432
2868
|
state.supportedAttributes = exactMatches;
|
|
2433
2869
|
state.attributePatterns = patterns;
|
|
2434
2870
|
state.stylesIdentifier = stylesIdentifier;
|
|
2435
2871
|
state.twImportNames = /* @__PURE__ */ new Set();
|
|
2436
2872
|
state.hasTwImport = false;
|
|
2437
|
-
state.
|
|
2873
|
+
state.functionComponentsNeedingColorScheme = /* @__PURE__ */ new Set();
|
|
2874
|
+
state.customTheme = extractCustomTheme(state.file.opts.filename ?? "");
|
|
2875
|
+
state.schemeModifierConfig = schemeModifierConfig;
|
|
2438
2876
|
},
|
|
2439
2877
|
exit(path2, state) {
|
|
2440
2878
|
if (state.hasTwImport) {
|
|
@@ -2449,6 +2887,14 @@ function reactNativeTailwindBabelPlugin({ types: t }, options) {
|
|
|
2449
2887
|
if (state.needsPlatformImport && !state.hasPlatformImport) {
|
|
2450
2888
|
addPlatformImport(path2, t);
|
|
2451
2889
|
}
|
|
2890
|
+
if (state.needsColorSchemeImport && !state.hasColorSchemeImport) {
|
|
2891
|
+
addColorSchemeImport(path2, t);
|
|
2892
|
+
}
|
|
2893
|
+
if (state.needsColorSchemeImport) {
|
|
2894
|
+
for (const functionPath of state.functionComponentsNeedingColorScheme) {
|
|
2895
|
+
injectColorSchemeHook(functionPath, state.colorSchemeVariableName, t);
|
|
2896
|
+
}
|
|
2897
|
+
}
|
|
2452
2898
|
injectStylesAtTop(path2, state.styleRegistry, state.stylesIdentifier, t);
|
|
2453
2899
|
}
|
|
2454
2900
|
},
|
|
@@ -2469,12 +2915,21 @@ function reactNativeTailwindBabelPlugin({ types: t }, options) {
|
|
|
2469
2915
|
}
|
|
2470
2916
|
return false;
|
|
2471
2917
|
});
|
|
2918
|
+
const hasUseColorScheme = specifiers.some((spec) => {
|
|
2919
|
+
if (t.isImportSpecifier(spec) && t.isIdentifier(spec.imported)) {
|
|
2920
|
+
return spec.imported.name === "useColorScheme";
|
|
2921
|
+
}
|
|
2922
|
+
return false;
|
|
2923
|
+
});
|
|
2472
2924
|
if (hasStyleSheet) {
|
|
2473
2925
|
state.hasStyleSheetImport = true;
|
|
2474
2926
|
}
|
|
2475
2927
|
if (hasPlatform) {
|
|
2476
2928
|
state.hasPlatformImport = true;
|
|
2477
2929
|
}
|
|
2930
|
+
if (hasUseColorScheme) {
|
|
2931
|
+
state.hasColorSchemeImport = true;
|
|
2932
|
+
}
|
|
2478
2933
|
state.reactNativeImportPath = path2;
|
|
2479
2934
|
}
|
|
2480
2935
|
if (node.source.value === "@mgcrea/react-native-tailwind") {
|
|
@@ -2576,9 +3031,24 @@ function reactNativeTailwindBabelPlugin({ types: t }, options) {
|
|
|
2576
3031
|
return;
|
|
2577
3032
|
}
|
|
2578
3033
|
state.hasClassNames = true;
|
|
2579
|
-
const { baseClasses, modifierClasses } = splitModifierClasses(className);
|
|
3034
|
+
const { baseClasses, modifierClasses: rawModifierClasses } = splitModifierClasses(className);
|
|
3035
|
+
const modifierClasses = [];
|
|
3036
|
+
for (const modifier of rawModifierClasses) {
|
|
3037
|
+
if (isSchemeModifier(modifier.modifier)) {
|
|
3038
|
+
const expanded = expandSchemeModifier(
|
|
3039
|
+
modifier,
|
|
3040
|
+
state.customTheme.colors ?? {},
|
|
3041
|
+
state.schemeModifierConfig.darkSuffix,
|
|
3042
|
+
state.schemeModifierConfig.lightSuffix
|
|
3043
|
+
);
|
|
3044
|
+
modifierClasses.push(...expanded);
|
|
3045
|
+
} else {
|
|
3046
|
+
modifierClasses.push(modifier);
|
|
3047
|
+
}
|
|
3048
|
+
}
|
|
2580
3049
|
const placeholderModifiers = modifierClasses.filter((m) => m.modifier === "placeholder");
|
|
2581
3050
|
const platformModifiers = modifierClasses.filter((m) => isPlatformModifier(m.modifier));
|
|
3051
|
+
const colorSchemeModifiers = modifierClasses.filter((m) => isColorSchemeModifier(m.modifier));
|
|
2582
3052
|
const stateModifiers = modifierClasses.filter(
|
|
2583
3053
|
(m) => isStateModifier(m.modifier) && m.modifier !== "placeholder"
|
|
2584
3054
|
);
|
|
@@ -2587,7 +3057,7 @@ function reactNativeTailwindBabelPlugin({ types: t }, options) {
|
|
|
2587
3057
|
const componentSupport = getComponentModifierSupport(jsxOpeningElement, t);
|
|
2588
3058
|
if (componentSupport?.supportedModifiers.includes("placeholder")) {
|
|
2589
3059
|
const placeholderClasses = placeholderModifiers.map((m) => m.baseClass).join(" ");
|
|
2590
|
-
const placeholderColor = parsePlaceholderClasses(placeholderClasses, state.
|
|
3060
|
+
const placeholderColor = parsePlaceholderClasses(placeholderClasses, state.customTheme.colors);
|
|
2591
3061
|
if (placeholderColor) {
|
|
2592
3062
|
addOrMergePlaceholderTextColorProp(jsxOpeningElement, placeholderColor, t);
|
|
2593
3063
|
}
|
|
@@ -2600,30 +3070,56 @@ function reactNativeTailwindBabelPlugin({ types: t }, options) {
|
|
|
2600
3070
|
}
|
|
2601
3071
|
}
|
|
2602
3072
|
const hasPlatformModifiers = platformModifiers.length > 0;
|
|
3073
|
+
const hasColorSchemeModifiers = colorSchemeModifiers.length > 0;
|
|
2603
3074
|
const hasStateModifiers = stateModifiers.length > 0;
|
|
2604
3075
|
const hasBaseClasses = baseClasses.length > 0;
|
|
2605
|
-
|
|
3076
|
+
let componentScope = null;
|
|
3077
|
+
if (hasColorSchemeModifiers) {
|
|
3078
|
+
componentScope = findComponentScope(path2, t);
|
|
3079
|
+
if (componentScope) {
|
|
3080
|
+
state.functionComponentsNeedingColorScheme.add(componentScope);
|
|
3081
|
+
} else {
|
|
3082
|
+
if (process.env.NODE_ENV !== "production") {
|
|
3083
|
+
console.warn(
|
|
3084
|
+
`[react-native-tailwind] dark:/light: modifiers require a function component scope. Found in non-component context at ${state.file.opts.filename ?? "unknown"}. These modifiers are not supported in class components or nested callbacks.`
|
|
3085
|
+
);
|
|
3086
|
+
}
|
|
3087
|
+
}
|
|
3088
|
+
}
|
|
3089
|
+
if (hasStateModifiers && (hasPlatformModifiers || hasColorSchemeModifiers)) {
|
|
2606
3090
|
const jsxOpeningElement = path2.parent;
|
|
2607
3091
|
const componentSupport = getComponentModifierSupport(jsxOpeningElement, t);
|
|
2608
3092
|
if (componentSupport) {
|
|
2609
3093
|
const styleArrayElements = [];
|
|
2610
3094
|
if (hasBaseClasses) {
|
|
2611
3095
|
const baseClassName = baseClasses.join(" ");
|
|
2612
|
-
const baseStyleObject = parseClassName(baseClassName, state.
|
|
3096
|
+
const baseStyleObject = parseClassName(baseClassName, state.customTheme);
|
|
2613
3097
|
const baseStyleKey = generateStyleKey(baseClassName);
|
|
2614
3098
|
state.styleRegistry.set(baseStyleKey, baseStyleObject);
|
|
2615
3099
|
styleArrayElements.push(
|
|
2616
3100
|
t.memberExpression(t.identifier(state.stylesIdentifier), t.identifier(baseStyleKey))
|
|
2617
3101
|
);
|
|
2618
3102
|
}
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
3103
|
+
if (hasPlatformModifiers) {
|
|
3104
|
+
const platformSelectExpression = processPlatformModifiers(
|
|
3105
|
+
platformModifiers,
|
|
3106
|
+
state,
|
|
3107
|
+
parseClassName,
|
|
3108
|
+
generateStyleKey,
|
|
3109
|
+
t
|
|
3110
|
+
);
|
|
3111
|
+
styleArrayElements.push(platformSelectExpression);
|
|
3112
|
+
}
|
|
3113
|
+
if (hasColorSchemeModifiers && componentScope) {
|
|
3114
|
+
const colorSchemeConditionals = processColorSchemeModifiers(
|
|
3115
|
+
colorSchemeModifiers,
|
|
3116
|
+
state,
|
|
3117
|
+
parseClassName,
|
|
3118
|
+
generateStyleKey,
|
|
3119
|
+
t
|
|
3120
|
+
);
|
|
3121
|
+
styleArrayElements.push(...colorSchemeConditionals);
|
|
3122
|
+
}
|
|
2627
3123
|
const modifiersByType = /* @__PURE__ */ new Map();
|
|
2628
3124
|
for (const mod of stateModifiers) {
|
|
2629
3125
|
const modType = mod.modifier;
|
|
@@ -2637,7 +3133,7 @@ function reactNativeTailwindBabelPlugin({ types: t }, options) {
|
|
|
2637
3133
|
continue;
|
|
2638
3134
|
}
|
|
2639
3135
|
const modifierClassNames = modifiers.map((m) => m.baseClass).join(" ");
|
|
2640
|
-
const modifierStyleObject = parseClassName(modifierClassNames, state.
|
|
3136
|
+
const modifierStyleObject = parseClassName(modifierClassNames, state.customTheme);
|
|
2641
3137
|
const modifierStyleKey = generateStyleKey(`${modifierType}_${modifierClassNames}`);
|
|
2642
3138
|
state.styleRegistry.set(modifierStyleKey, modifierStyleObject);
|
|
2643
3139
|
const stateProperty = getStatePropertyForModifier(modifierType);
|
|
@@ -2663,25 +3159,37 @@ function reactNativeTailwindBabelPlugin({ types: t }, options) {
|
|
|
2663
3159
|
} else {
|
|
2664
3160
|
}
|
|
2665
3161
|
}
|
|
2666
|
-
if (hasPlatformModifiers && !hasStateModifiers) {
|
|
3162
|
+
if ((hasPlatformModifiers || hasColorSchemeModifiers) && !hasStateModifiers) {
|
|
2667
3163
|
const styleExpressions = [];
|
|
2668
3164
|
if (hasBaseClasses) {
|
|
2669
3165
|
const baseClassName = baseClasses.join(" ");
|
|
2670
|
-
const baseStyleObject = parseClassName(baseClassName, state.
|
|
3166
|
+
const baseStyleObject = parseClassName(baseClassName, state.customTheme);
|
|
2671
3167
|
const baseStyleKey = generateStyleKey(baseClassName);
|
|
2672
3168
|
state.styleRegistry.set(baseStyleKey, baseStyleObject);
|
|
2673
3169
|
styleExpressions.push(
|
|
2674
3170
|
t.memberExpression(t.identifier(state.stylesIdentifier), t.identifier(baseStyleKey))
|
|
2675
3171
|
);
|
|
2676
3172
|
}
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
3173
|
+
if (hasPlatformModifiers) {
|
|
3174
|
+
const platformSelectExpression = processPlatformModifiers(
|
|
3175
|
+
platformModifiers,
|
|
3176
|
+
state,
|
|
3177
|
+
parseClassName,
|
|
3178
|
+
generateStyleKey,
|
|
3179
|
+
t
|
|
3180
|
+
);
|
|
3181
|
+
styleExpressions.push(platformSelectExpression);
|
|
3182
|
+
}
|
|
3183
|
+
if (hasColorSchemeModifiers && componentScope) {
|
|
3184
|
+
const colorSchemeConditionals = processColorSchemeModifiers(
|
|
3185
|
+
colorSchemeModifiers,
|
|
3186
|
+
state,
|
|
3187
|
+
parseClassName,
|
|
3188
|
+
generateStyleKey,
|
|
3189
|
+
t
|
|
3190
|
+
);
|
|
3191
|
+
styleExpressions.push(...colorSchemeConditionals);
|
|
3192
|
+
}
|
|
2685
3193
|
const styleExpression = styleExpressions.length === 1 ? styleExpressions[0] : t.arrayExpression(styleExpressions);
|
|
2686
3194
|
const styleAttribute2 = findStyleAttribute(path2, targetStyleProp, t);
|
|
2687
3195
|
if (styleAttribute2) {
|
|
@@ -2771,7 +3279,7 @@ function reactNativeTailwindBabelPlugin({ types: t }, options) {
|
|
|
2771
3279
|
path2.remove();
|
|
2772
3280
|
return;
|
|
2773
3281
|
}
|
|
2774
|
-
const styleObject = parseClassName(classNameForStyle, state.
|
|
3282
|
+
const styleObject = parseClassName(classNameForStyle, state.customTheme);
|
|
2775
3283
|
const styleKey = generateStyleKey(classNameForStyle);
|
|
2776
3284
|
state.styleRegistry.set(styleKey, styleObject);
|
|
2777
3285
|
const styleAttribute = findStyleAttribute(path2, targetStyleProp, t);
|
|
@@ -2788,7 +3296,22 @@ function reactNativeTailwindBabelPlugin({ types: t }, options) {
|
|
|
2788
3296
|
return;
|
|
2789
3297
|
}
|
|
2790
3298
|
try {
|
|
2791
|
-
const
|
|
3299
|
+
const componentScope = findComponentScope(path2, t);
|
|
3300
|
+
const result = processDynamicExpression(
|
|
3301
|
+
expression,
|
|
3302
|
+
state,
|
|
3303
|
+
parseClassName,
|
|
3304
|
+
generateStyleKey,
|
|
3305
|
+
splitModifierClasses,
|
|
3306
|
+
processPlatformModifiers,
|
|
3307
|
+
processColorSchemeModifiers,
|
|
3308
|
+
componentScope,
|
|
3309
|
+
isPlatformModifier,
|
|
3310
|
+
isColorSchemeModifier,
|
|
3311
|
+
isSchemeModifier,
|
|
3312
|
+
expandSchemeModifier,
|
|
3313
|
+
t
|
|
3314
|
+
);
|
|
2792
3315
|
if (result) {
|
|
2793
3316
|
state.hasClassNames = true;
|
|
2794
3317
|
const styleAttribute = findStyleAttribute(path2, targetStyleProp, t);
|