@mgcrea/react-native-tailwind 0.9.1 → 0.10.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 +356 -30
- package/dist/babel/config-loader.test.ts +152 -0
- package/dist/babel/index.cjs +547 -47
- package/dist/babel/plugin.d.ts +21 -0
- package/dist/babel/plugin.test.ts +331 -0
- package/dist/babel/plugin.ts +258 -28
- package/dist/babel/utils/colorSchemeModifierProcessing.d.ts +34 -0
- package/dist/babel/utils/colorSchemeModifierProcessing.ts +89 -0
- package/dist/babel/utils/dynamicProcessing.d.ts +33 -2
- package/dist/babel/utils/dynamicProcessing.ts +352 -33
- 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 +2 -0
- package/dist/babel/utils/twProcessing.ts +22 -1
- package/dist/parser/index.d.ts +2 -2
- 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/runtime.cjs +1 -1
- package/dist/runtime.cjs.map +3 -3
- package/dist/runtime.js +1 -1
- package/dist/runtime.js.map +3 -3
- 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 +152 -0
- package/src/babel/plugin.test.ts +331 -0
- package/src/babel/plugin.ts +258 -28
- package/src/babel/utils/colorSchemeModifierProcessing.ts +89 -0
- package/src/babel/utils/dynamicProcessing.ts +352 -33
- package/src/babel/utils/styleInjection.ts +101 -0
- package/src/babel/utils/styleTransforms.test.ts +56 -0
- package/src/babel/utils/twProcessing.ts +22 -1
- package/src/parser/index.ts +12 -1
- package/src/parser/modifiers.test.ts +151 -1
- package/src/parser/modifiers.ts +139 -4
- package/src/types/config.ts +7 -0
package/dist/babel/index.cjs
CHANGED
|
@@ -1741,7 +1741,14 @@ var STATE_MODIFIERS = [
|
|
|
1741
1741
|
"placeholder"
|
|
1742
1742
|
];
|
|
1743
1743
|
var PLATFORM_MODIFIERS = ["ios", "android", "web"];
|
|
1744
|
-
var
|
|
1744
|
+
var COLOR_SCHEME_MODIFIERS = ["dark", "light"];
|
|
1745
|
+
var SCHEME_MODIFIERS = ["scheme"];
|
|
1746
|
+
var SUPPORTED_MODIFIERS = [
|
|
1747
|
+
...STATE_MODIFIERS,
|
|
1748
|
+
...PLATFORM_MODIFIERS,
|
|
1749
|
+
...COLOR_SCHEME_MODIFIERS,
|
|
1750
|
+
...SCHEME_MODIFIERS
|
|
1751
|
+
];
|
|
1745
1752
|
function parseModifier(cls) {
|
|
1746
1753
|
const colonIndex = cls.indexOf(":");
|
|
1747
1754
|
if (colonIndex === -1) {
|
|
@@ -1769,6 +1776,56 @@ function isStateModifier(modifier) {
|
|
|
1769
1776
|
function isPlatformModifier(modifier) {
|
|
1770
1777
|
return PLATFORM_MODIFIERS.includes(modifier);
|
|
1771
1778
|
}
|
|
1779
|
+
function isColorSchemeModifier(modifier) {
|
|
1780
|
+
return COLOR_SCHEME_MODIFIERS.includes(modifier);
|
|
1781
|
+
}
|
|
1782
|
+
function isSchemeModifier(modifier) {
|
|
1783
|
+
return SCHEME_MODIFIERS.includes(modifier);
|
|
1784
|
+
}
|
|
1785
|
+
function isColorClass(className) {
|
|
1786
|
+
return className.startsWith("text-") || className.startsWith("bg-") || className.startsWith("border-");
|
|
1787
|
+
}
|
|
1788
|
+
function expandSchemeModifier(schemeModifier, customColors, darkSuffix = "-dark", lightSuffix = "-light") {
|
|
1789
|
+
const { baseClass } = schemeModifier;
|
|
1790
|
+
if (!isColorClass(baseClass)) {
|
|
1791
|
+
if (process.env.NODE_ENV !== "production") {
|
|
1792
|
+
console.warn(
|
|
1793
|
+
`[react-native-tailwind] scheme: modifier only supports color classes (text-*, bg-*, border-*). Found: "${baseClass}". This modifier will be ignored.`
|
|
1794
|
+
);
|
|
1795
|
+
}
|
|
1796
|
+
return [];
|
|
1797
|
+
}
|
|
1798
|
+
const match = baseClass.match(/^(text|bg|border)-(.+)$/);
|
|
1799
|
+
if (!match) {
|
|
1800
|
+
return [];
|
|
1801
|
+
}
|
|
1802
|
+
const [, prefix, colorName] = match;
|
|
1803
|
+
const darkColorName = `${colorName}${darkSuffix}`;
|
|
1804
|
+
const lightColorName = `${colorName}${lightSuffix}`;
|
|
1805
|
+
const darkColorExists = customColors[darkColorName] !== void 0;
|
|
1806
|
+
const lightColorExists = customColors[lightColorName] !== void 0;
|
|
1807
|
+
if (!darkColorExists || !lightColorExists) {
|
|
1808
|
+
if (process.env.NODE_ENV !== "production") {
|
|
1809
|
+
const missing = [];
|
|
1810
|
+
if (!darkColorExists) missing.push(`${colorName}${darkSuffix}`);
|
|
1811
|
+
if (!lightColorExists) missing.push(`${colorName}${lightSuffix}`);
|
|
1812
|
+
console.warn(
|
|
1813
|
+
`[react-native-tailwind] scheme:${baseClass} requires both color variants to exist. Missing: ${missing.join(", ")}. This modifier will be ignored.`
|
|
1814
|
+
);
|
|
1815
|
+
}
|
|
1816
|
+
return [];
|
|
1817
|
+
}
|
|
1818
|
+
return [
|
|
1819
|
+
{
|
|
1820
|
+
modifier: "dark",
|
|
1821
|
+
baseClass: `${prefix}-${darkColorName}`
|
|
1822
|
+
},
|
|
1823
|
+
{
|
|
1824
|
+
modifier: "light",
|
|
1825
|
+
baseClass: `${prefix}-${lightColorName}`
|
|
1826
|
+
}
|
|
1827
|
+
];
|
|
1828
|
+
}
|
|
1772
1829
|
function splitModifierClasses(className) {
|
|
1773
1830
|
const classes = className.trim().split(/\s+/).filter(Boolean);
|
|
1774
1831
|
const baseClasses = [];
|
|
@@ -1923,6 +1980,38 @@ function getTargetStyleProp(attributeName) {
|
|
|
1923
1980
|
return attributeName.endsWith("ClassName") ? attributeName.replace("ClassName", "Style") : "style";
|
|
1924
1981
|
}
|
|
1925
1982
|
|
|
1983
|
+
// src/babel/utils/colorSchemeModifierProcessing.ts
|
|
1984
|
+
function processColorSchemeModifiers(colorSchemeModifiers, state, parseClassName2, generateStyleKey2, t) {
|
|
1985
|
+
state.needsColorSchemeImport = true;
|
|
1986
|
+
const modifiersByScheme = /* @__PURE__ */ new Map();
|
|
1987
|
+
for (const mod of colorSchemeModifiers) {
|
|
1988
|
+
const scheme = mod.modifier;
|
|
1989
|
+
if (!modifiersByScheme.has(scheme)) {
|
|
1990
|
+
modifiersByScheme.set(scheme, []);
|
|
1991
|
+
}
|
|
1992
|
+
const schemeGroup = modifiersByScheme.get(scheme);
|
|
1993
|
+
if (schemeGroup) {
|
|
1994
|
+
schemeGroup.push(mod);
|
|
1995
|
+
}
|
|
1996
|
+
}
|
|
1997
|
+
const conditionalExpressions = [];
|
|
1998
|
+
for (const [scheme, modifiers] of modifiersByScheme) {
|
|
1999
|
+
const classNames = modifiers.map((m) => m.baseClass).join(" ");
|
|
2000
|
+
const styleObject = parseClassName2(classNames, state.customColors);
|
|
2001
|
+
const styleKey = generateStyleKey2(`${scheme}_${classNames}`);
|
|
2002
|
+
state.styleRegistry.set(styleKey, styleObject);
|
|
2003
|
+
const colorSchemeCheck = t.binaryExpression(
|
|
2004
|
+
"===",
|
|
2005
|
+
t.identifier(state.colorSchemeVariableName),
|
|
2006
|
+
t.stringLiteral(scheme)
|
|
2007
|
+
);
|
|
2008
|
+
const styleReference = t.memberExpression(t.identifier(state.stylesIdentifier), t.identifier(styleKey));
|
|
2009
|
+
const conditionalExpression = t.logicalExpression("&&", colorSchemeCheck, styleReference);
|
|
2010
|
+
conditionalExpressions.push(conditionalExpression);
|
|
2011
|
+
}
|
|
2012
|
+
return conditionalExpressions;
|
|
2013
|
+
}
|
|
2014
|
+
|
|
1926
2015
|
// src/babel/utils/componentSupport.ts
|
|
1927
2016
|
function getComponentModifierSupport(jsxElement, t) {
|
|
1928
2017
|
if (!t.isJSXOpeningElement(jsxElement)) {
|
|
@@ -1967,32 +2056,89 @@ function getStatePropertyForModifier(modifier) {
|
|
|
1967
2056
|
}
|
|
1968
2057
|
|
|
1969
2058
|
// src/babel/utils/dynamicProcessing.ts
|
|
1970
|
-
function processDynamicExpression(expression, state, parseClassName2, generateStyleKey2, t) {
|
|
2059
|
+
function processDynamicExpression(expression, state, parseClassName2, generateStyleKey2, splitModifierClasses2, processPlatformModifiers2, processColorSchemeModifiers2, componentScope, isPlatformModifier2, isColorSchemeModifier2, isSchemeModifier2, expandSchemeModifier2, t) {
|
|
1971
2060
|
if (t.isTemplateLiteral(expression)) {
|
|
1972
|
-
return processTemplateLiteral(
|
|
2061
|
+
return processTemplateLiteral(
|
|
2062
|
+
expression,
|
|
2063
|
+
state,
|
|
2064
|
+
parseClassName2,
|
|
2065
|
+
generateStyleKey2,
|
|
2066
|
+
splitModifierClasses2,
|
|
2067
|
+
processPlatformModifiers2,
|
|
2068
|
+
processColorSchemeModifiers2,
|
|
2069
|
+
componentScope,
|
|
2070
|
+
isPlatformModifier2,
|
|
2071
|
+
isColorSchemeModifier2,
|
|
2072
|
+
isSchemeModifier2,
|
|
2073
|
+
expandSchemeModifier2,
|
|
2074
|
+
t
|
|
2075
|
+
);
|
|
1973
2076
|
}
|
|
1974
2077
|
if (t.isConditionalExpression(expression)) {
|
|
1975
|
-
return processConditionalExpression(
|
|
2078
|
+
return processConditionalExpression(
|
|
2079
|
+
expression,
|
|
2080
|
+
state,
|
|
2081
|
+
parseClassName2,
|
|
2082
|
+
generateStyleKey2,
|
|
2083
|
+
splitModifierClasses2,
|
|
2084
|
+
processPlatformModifiers2,
|
|
2085
|
+
processColorSchemeModifiers2,
|
|
2086
|
+
componentScope,
|
|
2087
|
+
isPlatformModifier2,
|
|
2088
|
+
isColorSchemeModifier2,
|
|
2089
|
+
isSchemeModifier2,
|
|
2090
|
+
expandSchemeModifier2,
|
|
2091
|
+
t
|
|
2092
|
+
);
|
|
1976
2093
|
}
|
|
1977
2094
|
if (t.isLogicalExpression(expression)) {
|
|
1978
|
-
return processLogicalExpression(
|
|
2095
|
+
return processLogicalExpression(
|
|
2096
|
+
expression,
|
|
2097
|
+
state,
|
|
2098
|
+
parseClassName2,
|
|
2099
|
+
generateStyleKey2,
|
|
2100
|
+
splitModifierClasses2,
|
|
2101
|
+
processPlatformModifiers2,
|
|
2102
|
+
processColorSchemeModifiers2,
|
|
2103
|
+
componentScope,
|
|
2104
|
+
isPlatformModifier2,
|
|
2105
|
+
isColorSchemeModifier2,
|
|
2106
|
+
isSchemeModifier2,
|
|
2107
|
+
expandSchemeModifier2,
|
|
2108
|
+
t
|
|
2109
|
+
);
|
|
1979
2110
|
}
|
|
1980
2111
|
return null;
|
|
1981
2112
|
}
|
|
1982
|
-
function processTemplateLiteral(node, state, parseClassName2, generateStyleKey2, t) {
|
|
2113
|
+
function processTemplateLiteral(node, state, parseClassName2, generateStyleKey2, splitModifierClasses2, processPlatformModifiers2, processColorSchemeModifiers2, componentScope, isPlatformModifier2, isColorSchemeModifier2, isSchemeModifier2, expandSchemeModifier2, t) {
|
|
1983
2114
|
const parts = [];
|
|
1984
2115
|
const staticParts = [];
|
|
1985
2116
|
for (let i = 0; i < node.quasis.length; i++) {
|
|
1986
2117
|
const quasi = node.quasis[i];
|
|
1987
2118
|
const staticText = quasi.value.cooked?.trim();
|
|
1988
2119
|
if (staticText) {
|
|
1989
|
-
const
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
2120
|
+
const processedExpression = processStringOrExpressionHelper(
|
|
2121
|
+
t.stringLiteral(staticText),
|
|
2122
|
+
state,
|
|
2123
|
+
parseClassName2,
|
|
2124
|
+
generateStyleKey2,
|
|
2125
|
+
splitModifierClasses2,
|
|
2126
|
+
processPlatformModifiers2,
|
|
2127
|
+
processColorSchemeModifiers2,
|
|
2128
|
+
componentScope,
|
|
2129
|
+
isPlatformModifier2,
|
|
2130
|
+
isColorSchemeModifier2,
|
|
2131
|
+
isSchemeModifier2,
|
|
2132
|
+
expandSchemeModifier2,
|
|
2133
|
+
t
|
|
2134
|
+
);
|
|
2135
|
+
if (processedExpression) {
|
|
2136
|
+
staticParts.push(staticText);
|
|
2137
|
+
if (t.isArrayExpression(processedExpression)) {
|
|
2138
|
+
parts.push(...processedExpression.elements);
|
|
2139
|
+
} else {
|
|
2140
|
+
parts.push(processedExpression);
|
|
2141
|
+
}
|
|
1996
2142
|
}
|
|
1997
2143
|
}
|
|
1998
2144
|
if (i < node.expressions.length) {
|
|
@@ -2002,6 +2148,14 @@ function processTemplateLiteral(node, state, parseClassName2, generateStyleKey2,
|
|
|
2002
2148
|
state,
|
|
2003
2149
|
parseClassName2,
|
|
2004
2150
|
generateStyleKey2,
|
|
2151
|
+
splitModifierClasses2,
|
|
2152
|
+
processPlatformModifiers2,
|
|
2153
|
+
processColorSchemeModifiers2,
|
|
2154
|
+
componentScope,
|
|
2155
|
+
isPlatformModifier2,
|
|
2156
|
+
isColorSchemeModifier2,
|
|
2157
|
+
isSchemeModifier2,
|
|
2158
|
+
expandSchemeModifier2,
|
|
2005
2159
|
t
|
|
2006
2160
|
);
|
|
2007
2161
|
if (result) {
|
|
@@ -2020,9 +2174,37 @@ function processTemplateLiteral(node, state, parseClassName2, generateStyleKey2,
|
|
|
2020
2174
|
staticParts: staticParts.length > 0 ? staticParts : void 0
|
|
2021
2175
|
};
|
|
2022
2176
|
}
|
|
2023
|
-
function processConditionalExpression(node, state, parseClassName2, generateStyleKey2, t) {
|
|
2024
|
-
const consequent =
|
|
2025
|
-
|
|
2177
|
+
function processConditionalExpression(node, state, parseClassName2, generateStyleKey2, splitModifierClasses2, processPlatformModifiers2, processColorSchemeModifiers2, componentScope, isPlatformModifier2, isColorSchemeModifier2, isSchemeModifier2, expandSchemeModifier2, t) {
|
|
2178
|
+
const consequent = processStringOrExpressionHelper(
|
|
2179
|
+
node.consequent,
|
|
2180
|
+
state,
|
|
2181
|
+
parseClassName2,
|
|
2182
|
+
generateStyleKey2,
|
|
2183
|
+
splitModifierClasses2,
|
|
2184
|
+
processPlatformModifiers2,
|
|
2185
|
+
processColorSchemeModifiers2,
|
|
2186
|
+
componentScope,
|
|
2187
|
+
isPlatformModifier2,
|
|
2188
|
+
isColorSchemeModifier2,
|
|
2189
|
+
isSchemeModifier2,
|
|
2190
|
+
expandSchemeModifier2,
|
|
2191
|
+
t
|
|
2192
|
+
);
|
|
2193
|
+
const alternate = processStringOrExpressionHelper(
|
|
2194
|
+
node.alternate,
|
|
2195
|
+
state,
|
|
2196
|
+
parseClassName2,
|
|
2197
|
+
generateStyleKey2,
|
|
2198
|
+
splitModifierClasses2,
|
|
2199
|
+
processPlatformModifiers2,
|
|
2200
|
+
processColorSchemeModifiers2,
|
|
2201
|
+
componentScope,
|
|
2202
|
+
isPlatformModifier2,
|
|
2203
|
+
isColorSchemeModifier2,
|
|
2204
|
+
isSchemeModifier2,
|
|
2205
|
+
expandSchemeModifier2,
|
|
2206
|
+
t
|
|
2207
|
+
);
|
|
2026
2208
|
if (!consequent && !alternate) {
|
|
2027
2209
|
return null;
|
|
2028
2210
|
}
|
|
@@ -2033,38 +2215,153 @@ function processConditionalExpression(node, state, parseClassName2, generateStyl
|
|
|
2033
2215
|
);
|
|
2034
2216
|
return { expression };
|
|
2035
2217
|
}
|
|
2036
|
-
function processLogicalExpression(node, state, parseClassName2, generateStyleKey2, t) {
|
|
2218
|
+
function processLogicalExpression(node, state, parseClassName2, generateStyleKey2, splitModifierClasses2, processPlatformModifiers2, processColorSchemeModifiers2, componentScope, isPlatformModifier2, isColorSchemeModifier2, isSchemeModifier2, expandSchemeModifier2, t) {
|
|
2037
2219
|
if (node.operator !== "&&") {
|
|
2038
2220
|
return null;
|
|
2039
2221
|
}
|
|
2040
|
-
const right =
|
|
2222
|
+
const right = processStringOrExpressionHelper(
|
|
2223
|
+
node.right,
|
|
2224
|
+
state,
|
|
2225
|
+
parseClassName2,
|
|
2226
|
+
generateStyleKey2,
|
|
2227
|
+
splitModifierClasses2,
|
|
2228
|
+
processPlatformModifiers2,
|
|
2229
|
+
processColorSchemeModifiers2,
|
|
2230
|
+
componentScope,
|
|
2231
|
+
isPlatformModifier2,
|
|
2232
|
+
isColorSchemeModifier2,
|
|
2233
|
+
isSchemeModifier2,
|
|
2234
|
+
expandSchemeModifier2,
|
|
2235
|
+
t
|
|
2236
|
+
);
|
|
2041
2237
|
if (!right) {
|
|
2042
2238
|
return null;
|
|
2043
2239
|
}
|
|
2044
2240
|
const expression = t.logicalExpression("&&", node.left, right);
|
|
2045
2241
|
return { expression };
|
|
2046
2242
|
}
|
|
2047
|
-
function
|
|
2243
|
+
function processStringOrExpressionHelper(node, state, parseClassName2, generateStyleKey2, splitModifierClasses2, processPlatformModifiers2, processColorSchemeModifiers2, componentScope, isPlatformModifier2, isColorSchemeModifier2, isSchemeModifier2, expandSchemeModifier2, t) {
|
|
2048
2244
|
if (t.isStringLiteral(node)) {
|
|
2049
2245
|
const className = node.value.trim();
|
|
2050
2246
|
if (!className) {
|
|
2051
2247
|
return null;
|
|
2052
2248
|
}
|
|
2053
|
-
const
|
|
2054
|
-
const
|
|
2055
|
-
|
|
2056
|
-
|
|
2249
|
+
const { baseClasses, modifierClasses: rawModifierClasses } = splitModifierClasses2(className);
|
|
2250
|
+
const modifierClasses = [];
|
|
2251
|
+
for (const modifier of rawModifierClasses) {
|
|
2252
|
+
if (isSchemeModifier2(modifier.modifier)) {
|
|
2253
|
+
const expanded = expandSchemeModifier2(
|
|
2254
|
+
modifier,
|
|
2255
|
+
state.customColors,
|
|
2256
|
+
state.schemeModifierConfig.darkSuffix ?? "-dark",
|
|
2257
|
+
state.schemeModifierConfig.lightSuffix ?? "-light"
|
|
2258
|
+
);
|
|
2259
|
+
modifierClasses.push(...expanded);
|
|
2260
|
+
} else {
|
|
2261
|
+
modifierClasses.push(modifier);
|
|
2262
|
+
}
|
|
2263
|
+
}
|
|
2264
|
+
const platformModifiers = modifierClasses.filter((m) => isPlatformModifier2(m.modifier));
|
|
2265
|
+
const colorSchemeModifiers = modifierClasses.filter((m) => isColorSchemeModifier2(m.modifier));
|
|
2266
|
+
const styleElements = [];
|
|
2267
|
+
if (baseClasses.length > 0) {
|
|
2268
|
+
const baseClassName = baseClasses.join(" ");
|
|
2269
|
+
const styleObject = parseClassName2(baseClassName, state.customColors);
|
|
2270
|
+
const styleKey = generateStyleKey2(baseClassName);
|
|
2271
|
+
state.styleRegistry.set(styleKey, styleObject);
|
|
2272
|
+
styleElements.push(t.memberExpression(t.identifier(state.stylesIdentifier), t.identifier(styleKey)));
|
|
2273
|
+
}
|
|
2274
|
+
if (platformModifiers.length > 0) {
|
|
2275
|
+
state.needsPlatformImport = true;
|
|
2276
|
+
const platformExpression = processPlatformModifiers2(
|
|
2277
|
+
platformModifiers,
|
|
2278
|
+
state,
|
|
2279
|
+
parseClassName2,
|
|
2280
|
+
generateStyleKey2,
|
|
2281
|
+
t
|
|
2282
|
+
);
|
|
2283
|
+
styleElements.push(platformExpression);
|
|
2284
|
+
}
|
|
2285
|
+
if (colorSchemeModifiers.length > 0) {
|
|
2286
|
+
if (componentScope) {
|
|
2287
|
+
state.needsColorSchemeImport = true;
|
|
2288
|
+
state.functionComponentsNeedingColorScheme.add(componentScope);
|
|
2289
|
+
const colorSchemeExpressions = processColorSchemeModifiers2(
|
|
2290
|
+
colorSchemeModifiers,
|
|
2291
|
+
state,
|
|
2292
|
+
parseClassName2,
|
|
2293
|
+
generateStyleKey2,
|
|
2294
|
+
t
|
|
2295
|
+
);
|
|
2296
|
+
styleElements.push(...colorSchemeExpressions);
|
|
2297
|
+
} else {
|
|
2298
|
+
if (process.env.NODE_ENV !== "production") {
|
|
2299
|
+
console.warn(
|
|
2300
|
+
"[react-native-tailwind] dark:/light: modifiers in dynamic expressions require a function component scope. These modifiers will be ignored."
|
|
2301
|
+
);
|
|
2302
|
+
}
|
|
2303
|
+
}
|
|
2304
|
+
}
|
|
2305
|
+
if (styleElements.length === 0) {
|
|
2306
|
+
return null;
|
|
2307
|
+
}
|
|
2308
|
+
if (styleElements.length === 1) {
|
|
2309
|
+
return styleElements[0];
|
|
2310
|
+
}
|
|
2311
|
+
return t.arrayExpression(styleElements);
|
|
2057
2312
|
}
|
|
2058
2313
|
if (t.isConditionalExpression(node)) {
|
|
2059
|
-
const result = processConditionalExpression(
|
|
2314
|
+
const result = processConditionalExpression(
|
|
2315
|
+
node,
|
|
2316
|
+
state,
|
|
2317
|
+
parseClassName2,
|
|
2318
|
+
generateStyleKey2,
|
|
2319
|
+
splitModifierClasses2,
|
|
2320
|
+
processPlatformModifiers2,
|
|
2321
|
+
processColorSchemeModifiers2,
|
|
2322
|
+
componentScope,
|
|
2323
|
+
isPlatformModifier2,
|
|
2324
|
+
isColorSchemeModifier2,
|
|
2325
|
+
isSchemeModifier2,
|
|
2326
|
+
expandSchemeModifier2,
|
|
2327
|
+
t
|
|
2328
|
+
);
|
|
2060
2329
|
return result?.expression ?? null;
|
|
2061
2330
|
}
|
|
2062
2331
|
if (t.isLogicalExpression(node)) {
|
|
2063
|
-
const result = processLogicalExpression(
|
|
2332
|
+
const result = processLogicalExpression(
|
|
2333
|
+
node,
|
|
2334
|
+
state,
|
|
2335
|
+
parseClassName2,
|
|
2336
|
+
generateStyleKey2,
|
|
2337
|
+
splitModifierClasses2,
|
|
2338
|
+
processPlatformModifiers2,
|
|
2339
|
+
processColorSchemeModifiers2,
|
|
2340
|
+
componentScope,
|
|
2341
|
+
isPlatformModifier2,
|
|
2342
|
+
isColorSchemeModifier2,
|
|
2343
|
+
isSchemeModifier2,
|
|
2344
|
+
expandSchemeModifier2,
|
|
2345
|
+
t
|
|
2346
|
+
);
|
|
2064
2347
|
return result?.expression ?? null;
|
|
2065
2348
|
}
|
|
2066
2349
|
if (t.isTemplateLiteral(node)) {
|
|
2067
|
-
const result = processTemplateLiteral(
|
|
2350
|
+
const result = processTemplateLiteral(
|
|
2351
|
+
node,
|
|
2352
|
+
state,
|
|
2353
|
+
parseClassName2,
|
|
2354
|
+
generateStyleKey2,
|
|
2355
|
+
splitModifierClasses2,
|
|
2356
|
+
processPlatformModifiers2,
|
|
2357
|
+
processColorSchemeModifiers2,
|
|
2358
|
+
componentScope,
|
|
2359
|
+
isPlatformModifier2,
|
|
2360
|
+
isColorSchemeModifier2,
|
|
2361
|
+
isSchemeModifier2,
|
|
2362
|
+
expandSchemeModifier2,
|
|
2363
|
+
t
|
|
2364
|
+
);
|
|
2068
2365
|
return result?.expression ?? null;
|
|
2069
2366
|
}
|
|
2070
2367
|
return null;
|
|
@@ -2198,6 +2495,63 @@ function addPlatformImport(path2, t) {
|
|
|
2198
2495
|
path2.unshiftContainer("body", importDeclaration);
|
|
2199
2496
|
}
|
|
2200
2497
|
}
|
|
2498
|
+
function addColorSchemeImport(path2, t) {
|
|
2499
|
+
const body = path2.node.body;
|
|
2500
|
+
let reactNativeImport = null;
|
|
2501
|
+
for (const statement of body) {
|
|
2502
|
+
if (t.isImportDeclaration(statement) && statement.source.value === "react-native") {
|
|
2503
|
+
reactNativeImport = statement;
|
|
2504
|
+
break;
|
|
2505
|
+
}
|
|
2506
|
+
}
|
|
2507
|
+
if (reactNativeImport) {
|
|
2508
|
+
const hasUseColorScheme = reactNativeImport.specifiers.some(
|
|
2509
|
+
(spec) => t.isImportSpecifier(spec) && spec.imported.type === "Identifier" && spec.imported.name === "useColorScheme"
|
|
2510
|
+
);
|
|
2511
|
+
if (!hasUseColorScheme) {
|
|
2512
|
+
reactNativeImport.specifiers.push(
|
|
2513
|
+
t.importSpecifier(t.identifier("useColorScheme"), t.identifier("useColorScheme"))
|
|
2514
|
+
);
|
|
2515
|
+
}
|
|
2516
|
+
} else {
|
|
2517
|
+
const importDeclaration = t.importDeclaration(
|
|
2518
|
+
[t.importSpecifier(t.identifier("useColorScheme"), t.identifier("useColorScheme"))],
|
|
2519
|
+
t.stringLiteral("react-native")
|
|
2520
|
+
);
|
|
2521
|
+
path2.unshiftContainer("body", importDeclaration);
|
|
2522
|
+
}
|
|
2523
|
+
}
|
|
2524
|
+
function injectColorSchemeHook(functionPath, colorSchemeVariableName, t) {
|
|
2525
|
+
let body = functionPath.node.body;
|
|
2526
|
+
if (!t.isBlockStatement(body)) {
|
|
2527
|
+
if (t.isArrowFunctionExpression(functionPath.node) && t.isExpression(body)) {
|
|
2528
|
+
const returnStatement = t.returnStatement(body);
|
|
2529
|
+
const blockStatement = t.blockStatement([returnStatement]);
|
|
2530
|
+
functionPath.node.body = blockStatement;
|
|
2531
|
+
body = blockStatement;
|
|
2532
|
+
} else {
|
|
2533
|
+
return false;
|
|
2534
|
+
}
|
|
2535
|
+
}
|
|
2536
|
+
const hasHook = body.body.some((statement) => {
|
|
2537
|
+
if (t.isVariableDeclaration(statement) && statement.declarations.length > 0 && t.isVariableDeclarator(statement.declarations[0])) {
|
|
2538
|
+
const declarator = statement.declarations[0];
|
|
2539
|
+
return t.isIdentifier(declarator.id) && declarator.id.name === colorSchemeVariableName;
|
|
2540
|
+
}
|
|
2541
|
+
return false;
|
|
2542
|
+
});
|
|
2543
|
+
if (hasHook) {
|
|
2544
|
+
return false;
|
|
2545
|
+
}
|
|
2546
|
+
const hookCall = t.variableDeclaration("const", [
|
|
2547
|
+
t.variableDeclarator(
|
|
2548
|
+
t.identifier(colorSchemeVariableName),
|
|
2549
|
+
t.callExpression(t.identifier("useColorScheme"), [])
|
|
2550
|
+
)
|
|
2551
|
+
]);
|
|
2552
|
+
body.body.unshift(hookCall);
|
|
2553
|
+
return true;
|
|
2554
|
+
}
|
|
2201
2555
|
function injectStylesAtTop(path2, styleRegistry, stylesIdentifier, t) {
|
|
2202
2556
|
const styleProperties = [];
|
|
2203
2557
|
for (const [key, styleObject] of styleRegistry) {
|
|
@@ -2348,7 +2702,21 @@ function addOrMergePlaceholderTextColorProp(jsxOpeningElement, color, t) {
|
|
|
2348
2702
|
|
|
2349
2703
|
// src/babel/utils/twProcessing.ts
|
|
2350
2704
|
function processTwCall(className, path2, state, parseClassName2, generateStyleKey2, splitModifierClasses2, t) {
|
|
2351
|
-
const { baseClasses, modifierClasses } = splitModifierClasses2(className);
|
|
2705
|
+
const { baseClasses, modifierClasses: rawModifierClasses } = splitModifierClasses2(className);
|
|
2706
|
+
const modifierClasses = [];
|
|
2707
|
+
for (const modifier of rawModifierClasses) {
|
|
2708
|
+
if (isSchemeModifier(modifier.modifier)) {
|
|
2709
|
+
const expanded = expandSchemeModifier(
|
|
2710
|
+
modifier,
|
|
2711
|
+
state.customColors,
|
|
2712
|
+
state.schemeModifierConfig.darkSuffix ?? "-dark",
|
|
2713
|
+
state.schemeModifierConfig.lightSuffix ?? "-light"
|
|
2714
|
+
);
|
|
2715
|
+
modifierClasses.push(...expanded);
|
|
2716
|
+
} else {
|
|
2717
|
+
modifierClasses.push(modifier);
|
|
2718
|
+
}
|
|
2719
|
+
}
|
|
2352
2720
|
const objectProperties = [];
|
|
2353
2721
|
if (baseClasses.length > 0) {
|
|
2354
2722
|
const baseClassName = baseClasses.join(" ");
|
|
@@ -2415,10 +2783,52 @@ function removeTwImports(path2, t) {
|
|
|
2415
2783
|
|
|
2416
2784
|
// src/babel/plugin.ts
|
|
2417
2785
|
var DEFAULT_STYLES_IDENTIFIER = "_twStyles";
|
|
2786
|
+
function isComponentScope(functionPath, t) {
|
|
2787
|
+
const node = functionPath.node;
|
|
2788
|
+
const parent = functionPath.parent;
|
|
2789
|
+
const parentPath = functionPath.parentPath;
|
|
2790
|
+
if (t.isClassMethod(parent)) {
|
|
2791
|
+
return false;
|
|
2792
|
+
}
|
|
2793
|
+
if (functionPath.findParent((p) => t.isClassBody(p.node))) {
|
|
2794
|
+
return false;
|
|
2795
|
+
}
|
|
2796
|
+
if (t.isFunctionDeclaration(node)) {
|
|
2797
|
+
if (t.isProgram(parent) || t.isExportNamedDeclaration(parent) || t.isExportDefaultDeclaration(parent)) {
|
|
2798
|
+
return true;
|
|
2799
|
+
}
|
|
2800
|
+
}
|
|
2801
|
+
if (t.isFunctionExpression(node) || t.isArrowFunctionExpression(node)) {
|
|
2802
|
+
if (t.isVariableDeclarator(parent)) {
|
|
2803
|
+
const varDeclarationPath = parentPath?.parentPath;
|
|
2804
|
+
if (varDeclarationPath && t.isVariableDeclaration(varDeclarationPath.node) && (t.isProgram(varDeclarationPath.parent) || t.isExportNamedDeclaration(varDeclarationPath.parent))) {
|
|
2805
|
+
if (t.isIdentifier(parent.id)) {
|
|
2806
|
+
const name = parent.id.name;
|
|
2807
|
+
return /^[A-Z]/.test(name);
|
|
2808
|
+
}
|
|
2809
|
+
}
|
|
2810
|
+
}
|
|
2811
|
+
}
|
|
2812
|
+
return false;
|
|
2813
|
+
}
|
|
2814
|
+
function findComponentScope(path2, t) {
|
|
2815
|
+
let current = path2.getFunctionParent();
|
|
2816
|
+
while (current) {
|
|
2817
|
+
if (t.isFunction(current.node) && isComponentScope(current, t)) {
|
|
2818
|
+
return current;
|
|
2819
|
+
}
|
|
2820
|
+
current = current.getFunctionParent();
|
|
2821
|
+
}
|
|
2822
|
+
return null;
|
|
2823
|
+
}
|
|
2418
2824
|
function reactNativeTailwindBabelPlugin({ types: t }, options) {
|
|
2419
2825
|
const attributes = options?.attributes ?? [...DEFAULT_CLASS_ATTRIBUTES];
|
|
2420
2826
|
const { exactMatches, patterns } = buildAttributeMatchers(attributes);
|
|
2421
2827
|
const stylesIdentifier = options?.stylesIdentifier ?? DEFAULT_STYLES_IDENTIFIER;
|
|
2828
|
+
const schemeModifierConfig = {
|
|
2829
|
+
darkSuffix: options?.schemeModifier?.darkSuffix ?? "-dark",
|
|
2830
|
+
lightSuffix: options?.schemeModifier?.lightSuffix ?? "-light"
|
|
2831
|
+
};
|
|
2422
2832
|
return {
|
|
2423
2833
|
name: "react-native-tailwind",
|
|
2424
2834
|
visitor: {
|
|
@@ -2429,12 +2839,17 @@ function reactNativeTailwindBabelPlugin({ types: t }, options) {
|
|
|
2429
2839
|
state.hasStyleSheetImport = false;
|
|
2430
2840
|
state.hasPlatformImport = false;
|
|
2431
2841
|
state.needsPlatformImport = false;
|
|
2842
|
+
state.hasColorSchemeImport = false;
|
|
2843
|
+
state.needsColorSchemeImport = false;
|
|
2844
|
+
state.colorSchemeVariableName = "_twColorScheme";
|
|
2432
2845
|
state.supportedAttributes = exactMatches;
|
|
2433
2846
|
state.attributePatterns = patterns;
|
|
2434
2847
|
state.stylesIdentifier = stylesIdentifier;
|
|
2435
2848
|
state.twImportNames = /* @__PURE__ */ new Set();
|
|
2436
2849
|
state.hasTwImport = false;
|
|
2850
|
+
state.functionComponentsNeedingColorScheme = /* @__PURE__ */ new Set();
|
|
2437
2851
|
state.customColors = extractCustomColors(state.file.opts.filename ?? "");
|
|
2852
|
+
state.schemeModifierConfig = schemeModifierConfig;
|
|
2438
2853
|
},
|
|
2439
2854
|
exit(path2, state) {
|
|
2440
2855
|
if (state.hasTwImport) {
|
|
@@ -2449,6 +2864,14 @@ function reactNativeTailwindBabelPlugin({ types: t }, options) {
|
|
|
2449
2864
|
if (state.needsPlatformImport && !state.hasPlatformImport) {
|
|
2450
2865
|
addPlatformImport(path2, t);
|
|
2451
2866
|
}
|
|
2867
|
+
if (state.needsColorSchemeImport && !state.hasColorSchemeImport) {
|
|
2868
|
+
addColorSchemeImport(path2, t);
|
|
2869
|
+
}
|
|
2870
|
+
if (state.needsColorSchemeImport) {
|
|
2871
|
+
for (const functionPath of state.functionComponentsNeedingColorScheme) {
|
|
2872
|
+
injectColorSchemeHook(functionPath, state.colorSchemeVariableName, t);
|
|
2873
|
+
}
|
|
2874
|
+
}
|
|
2452
2875
|
injectStylesAtTop(path2, state.styleRegistry, state.stylesIdentifier, t);
|
|
2453
2876
|
}
|
|
2454
2877
|
},
|
|
@@ -2469,12 +2892,21 @@ function reactNativeTailwindBabelPlugin({ types: t }, options) {
|
|
|
2469
2892
|
}
|
|
2470
2893
|
return false;
|
|
2471
2894
|
});
|
|
2895
|
+
const hasUseColorScheme = specifiers.some((spec) => {
|
|
2896
|
+
if (t.isImportSpecifier(spec) && t.isIdentifier(spec.imported)) {
|
|
2897
|
+
return spec.imported.name === "useColorScheme";
|
|
2898
|
+
}
|
|
2899
|
+
return false;
|
|
2900
|
+
});
|
|
2472
2901
|
if (hasStyleSheet) {
|
|
2473
2902
|
state.hasStyleSheetImport = true;
|
|
2474
2903
|
}
|
|
2475
2904
|
if (hasPlatform) {
|
|
2476
2905
|
state.hasPlatformImport = true;
|
|
2477
2906
|
}
|
|
2907
|
+
if (hasUseColorScheme) {
|
|
2908
|
+
state.hasColorSchemeImport = true;
|
|
2909
|
+
}
|
|
2478
2910
|
state.reactNativeImportPath = path2;
|
|
2479
2911
|
}
|
|
2480
2912
|
if (node.source.value === "@mgcrea/react-native-tailwind") {
|
|
@@ -2576,9 +3008,24 @@ function reactNativeTailwindBabelPlugin({ types: t }, options) {
|
|
|
2576
3008
|
return;
|
|
2577
3009
|
}
|
|
2578
3010
|
state.hasClassNames = true;
|
|
2579
|
-
const { baseClasses, modifierClasses } = splitModifierClasses(className);
|
|
3011
|
+
const { baseClasses, modifierClasses: rawModifierClasses } = splitModifierClasses(className);
|
|
3012
|
+
const modifierClasses = [];
|
|
3013
|
+
for (const modifier of rawModifierClasses) {
|
|
3014
|
+
if (isSchemeModifier(modifier.modifier)) {
|
|
3015
|
+
const expanded = expandSchemeModifier(
|
|
3016
|
+
modifier,
|
|
3017
|
+
state.customColors,
|
|
3018
|
+
state.schemeModifierConfig.darkSuffix,
|
|
3019
|
+
state.schemeModifierConfig.lightSuffix
|
|
3020
|
+
);
|
|
3021
|
+
modifierClasses.push(...expanded);
|
|
3022
|
+
} else {
|
|
3023
|
+
modifierClasses.push(modifier);
|
|
3024
|
+
}
|
|
3025
|
+
}
|
|
2580
3026
|
const placeholderModifiers = modifierClasses.filter((m) => m.modifier === "placeholder");
|
|
2581
3027
|
const platformModifiers = modifierClasses.filter((m) => isPlatformModifier(m.modifier));
|
|
3028
|
+
const colorSchemeModifiers = modifierClasses.filter((m) => isColorSchemeModifier(m.modifier));
|
|
2582
3029
|
const stateModifiers = modifierClasses.filter(
|
|
2583
3030
|
(m) => isStateModifier(m.modifier) && m.modifier !== "placeholder"
|
|
2584
3031
|
);
|
|
@@ -2600,9 +3047,23 @@ function reactNativeTailwindBabelPlugin({ types: t }, options) {
|
|
|
2600
3047
|
}
|
|
2601
3048
|
}
|
|
2602
3049
|
const hasPlatformModifiers = platformModifiers.length > 0;
|
|
3050
|
+
const hasColorSchemeModifiers = colorSchemeModifiers.length > 0;
|
|
2603
3051
|
const hasStateModifiers = stateModifiers.length > 0;
|
|
2604
3052
|
const hasBaseClasses = baseClasses.length > 0;
|
|
2605
|
-
|
|
3053
|
+
let componentScope = null;
|
|
3054
|
+
if (hasColorSchemeModifiers) {
|
|
3055
|
+
componentScope = findComponentScope(path2, t);
|
|
3056
|
+
if (componentScope) {
|
|
3057
|
+
state.functionComponentsNeedingColorScheme.add(componentScope);
|
|
3058
|
+
} else {
|
|
3059
|
+
if (process.env.NODE_ENV !== "production") {
|
|
3060
|
+
console.warn(
|
|
3061
|
+
`[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.`
|
|
3062
|
+
);
|
|
3063
|
+
}
|
|
3064
|
+
}
|
|
3065
|
+
}
|
|
3066
|
+
if (hasStateModifiers && (hasPlatformModifiers || hasColorSchemeModifiers)) {
|
|
2606
3067
|
const jsxOpeningElement = path2.parent;
|
|
2607
3068
|
const componentSupport = getComponentModifierSupport(jsxOpeningElement, t);
|
|
2608
3069
|
if (componentSupport) {
|
|
@@ -2616,14 +3077,26 @@ function reactNativeTailwindBabelPlugin({ types: t }, options) {
|
|
|
2616
3077
|
t.memberExpression(t.identifier(state.stylesIdentifier), t.identifier(baseStyleKey))
|
|
2617
3078
|
);
|
|
2618
3079
|
}
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
3080
|
+
if (hasPlatformModifiers) {
|
|
3081
|
+
const platformSelectExpression = processPlatformModifiers(
|
|
3082
|
+
platformModifiers,
|
|
3083
|
+
state,
|
|
3084
|
+
parseClassName,
|
|
3085
|
+
generateStyleKey,
|
|
3086
|
+
t
|
|
3087
|
+
);
|
|
3088
|
+
styleArrayElements.push(platformSelectExpression);
|
|
3089
|
+
}
|
|
3090
|
+
if (hasColorSchemeModifiers && componentScope) {
|
|
3091
|
+
const colorSchemeConditionals = processColorSchemeModifiers(
|
|
3092
|
+
colorSchemeModifiers,
|
|
3093
|
+
state,
|
|
3094
|
+
parseClassName,
|
|
3095
|
+
generateStyleKey,
|
|
3096
|
+
t
|
|
3097
|
+
);
|
|
3098
|
+
styleArrayElements.push(...colorSchemeConditionals);
|
|
3099
|
+
}
|
|
2627
3100
|
const modifiersByType = /* @__PURE__ */ new Map();
|
|
2628
3101
|
for (const mod of stateModifiers) {
|
|
2629
3102
|
const modType = mod.modifier;
|
|
@@ -2663,7 +3136,7 @@ function reactNativeTailwindBabelPlugin({ types: t }, options) {
|
|
|
2663
3136
|
} else {
|
|
2664
3137
|
}
|
|
2665
3138
|
}
|
|
2666
|
-
if (hasPlatformModifiers && !hasStateModifiers) {
|
|
3139
|
+
if ((hasPlatformModifiers || hasColorSchemeModifiers) && !hasStateModifiers) {
|
|
2667
3140
|
const styleExpressions = [];
|
|
2668
3141
|
if (hasBaseClasses) {
|
|
2669
3142
|
const baseClassName = baseClasses.join(" ");
|
|
@@ -2674,14 +3147,26 @@ function reactNativeTailwindBabelPlugin({ types: t }, options) {
|
|
|
2674
3147
|
t.memberExpression(t.identifier(state.stylesIdentifier), t.identifier(baseStyleKey))
|
|
2675
3148
|
);
|
|
2676
3149
|
}
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
3150
|
+
if (hasPlatformModifiers) {
|
|
3151
|
+
const platformSelectExpression = processPlatformModifiers(
|
|
3152
|
+
platformModifiers,
|
|
3153
|
+
state,
|
|
3154
|
+
parseClassName,
|
|
3155
|
+
generateStyleKey,
|
|
3156
|
+
t
|
|
3157
|
+
);
|
|
3158
|
+
styleExpressions.push(platformSelectExpression);
|
|
3159
|
+
}
|
|
3160
|
+
if (hasColorSchemeModifiers && componentScope) {
|
|
3161
|
+
const colorSchemeConditionals = processColorSchemeModifiers(
|
|
3162
|
+
colorSchemeModifiers,
|
|
3163
|
+
state,
|
|
3164
|
+
parseClassName,
|
|
3165
|
+
generateStyleKey,
|
|
3166
|
+
t
|
|
3167
|
+
);
|
|
3168
|
+
styleExpressions.push(...colorSchemeConditionals);
|
|
3169
|
+
}
|
|
2685
3170
|
const styleExpression = styleExpressions.length === 1 ? styleExpressions[0] : t.arrayExpression(styleExpressions);
|
|
2686
3171
|
const styleAttribute2 = findStyleAttribute(path2, targetStyleProp, t);
|
|
2687
3172
|
if (styleAttribute2) {
|
|
@@ -2788,7 +3273,22 @@ function reactNativeTailwindBabelPlugin({ types: t }, options) {
|
|
|
2788
3273
|
return;
|
|
2789
3274
|
}
|
|
2790
3275
|
try {
|
|
2791
|
-
const
|
|
3276
|
+
const componentScope = findComponentScope(path2, t);
|
|
3277
|
+
const result = processDynamicExpression(
|
|
3278
|
+
expression,
|
|
3279
|
+
state,
|
|
3280
|
+
parseClassName,
|
|
3281
|
+
generateStyleKey,
|
|
3282
|
+
splitModifierClasses,
|
|
3283
|
+
processPlatformModifiers,
|
|
3284
|
+
processColorSchemeModifiers,
|
|
3285
|
+
componentScope,
|
|
3286
|
+
isPlatformModifier,
|
|
3287
|
+
isColorSchemeModifier,
|
|
3288
|
+
isSchemeModifier,
|
|
3289
|
+
expandSchemeModifier,
|
|
3290
|
+
t
|
|
3291
|
+
);
|
|
2792
3292
|
if (result) {
|
|
2793
3293
|
state.hasClassNames = true;
|
|
2794
3294
|
const styleAttribute = findStyleAttribute(path2, targetStyleProp, t);
|