@mgcrea/react-native-tailwind 0.6.1 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +404 -0
- package/dist/babel/config-loader.ts +1 -23
- package/dist/babel/index.cjs +227 -60
- package/dist/babel/index.d.ts +27 -2
- package/dist/babel/index.test.ts +268 -0
- package/dist/babel/index.ts +352 -44
- package/dist/index.d.ts +3 -0
- package/dist/index.js +1 -1
- package/dist/parser/__snapshots__/colors.test.js.snap +242 -90
- package/dist/parser/__snapshots__/transforms.test.js.snap +58 -0
- package/dist/parser/colors.js +1 -1
- package/dist/runtime.cjs +2 -0
- package/dist/runtime.cjs.map +7 -0
- package/dist/runtime.d.ts +139 -0
- package/dist/runtime.js +2 -0
- package/dist/runtime.js.map +7 -0
- package/dist/runtime.test.js +1 -0
- package/dist/stubs/tw.d.ts +60 -0
- package/dist/stubs/tw.js +1 -0
- package/dist/utils/flattenColors.d.ts +16 -0
- package/dist/utils/flattenColors.js +1 -0
- package/dist/utils/flattenColors.test.js +1 -0
- package/dist/utils/modifiers.d.ts +29 -0
- package/dist/utils/modifiers.js +1 -0
- package/dist/utils/modifiers.test.js +1 -0
- package/dist/utils/styleKey.test.js +1 -0
- package/package.json +15 -3
- package/src/babel/config-loader.ts +1 -23
- package/src/babel/index.test.ts +268 -0
- package/src/babel/index.ts +352 -44
- package/src/index.ts +5 -0
- package/src/parser/colors.ts +8 -22
- package/src/runtime.test.ts +325 -0
- package/src/runtime.ts +280 -0
- package/src/stubs/tw.ts +80 -0
- package/src/utils/flattenColors.test.ts +361 -0
- package/src/utils/flattenColors.ts +32 -0
- package/src/utils/modifiers.test.ts +286 -0
- package/src/utils/modifiers.ts +63 -0
- package/src/utils/styleKey.test.ts +168 -0
package/dist/babel/index.cjs
CHANGED
|
@@ -548,20 +548,28 @@ var TAILWIND_PALETTES = {
|
|
|
548
548
|
}
|
|
549
549
|
};
|
|
550
550
|
|
|
551
|
-
// src/
|
|
552
|
-
function flattenColors() {
|
|
553
|
-
const
|
|
554
|
-
for (const [
|
|
555
|
-
|
|
556
|
-
|
|
551
|
+
// src/utils/flattenColors.ts
|
|
552
|
+
function flattenColors(colors, prefix = "") {
|
|
553
|
+
const result = {};
|
|
554
|
+
for (const [key, value] of Object.entries(colors)) {
|
|
555
|
+
const newKey = prefix ? `${prefix}-${key}` : key;
|
|
556
|
+
if (typeof value === "string") {
|
|
557
|
+
result[newKey] = value;
|
|
558
|
+
} else if (typeof value === "object" && value !== null) {
|
|
559
|
+
Object.assign(result, flattenColors(value, newKey));
|
|
557
560
|
}
|
|
558
561
|
}
|
|
559
|
-
|
|
560
|
-
flat.black = "#000000";
|
|
561
|
-
flat.transparent = "transparent";
|
|
562
|
-
return flat;
|
|
562
|
+
return result;
|
|
563
563
|
}
|
|
564
|
-
|
|
564
|
+
|
|
565
|
+
// src/parser/colors.ts
|
|
566
|
+
var COLORS = {
|
|
567
|
+
...flattenColors(TAILWIND_PALETTES),
|
|
568
|
+
// Add basic colors
|
|
569
|
+
white: "#FFFFFF",
|
|
570
|
+
black: "#000000",
|
|
571
|
+
transparent: "transparent"
|
|
572
|
+
};
|
|
565
573
|
function applyOpacity(hex, opacity) {
|
|
566
574
|
if (hex === "transparent") {
|
|
567
575
|
return "transparent";
|
|
@@ -1801,18 +1809,6 @@ function loadTailwindConfig(configPath) {
|
|
|
1801
1809
|
return null;
|
|
1802
1810
|
}
|
|
1803
1811
|
}
|
|
1804
|
-
function flattenColors2(colors, prefix = "") {
|
|
1805
|
-
const result = {};
|
|
1806
|
-
for (const [key, value] of Object.entries(colors)) {
|
|
1807
|
-
const newKey = prefix ? `${prefix}-${key}` : key;
|
|
1808
|
-
if (typeof value === "string") {
|
|
1809
|
-
result[newKey] = value;
|
|
1810
|
-
} else if (typeof value === "object" && value !== null) {
|
|
1811
|
-
Object.assign(result, flattenColors2(value, newKey));
|
|
1812
|
-
}
|
|
1813
|
-
}
|
|
1814
|
-
return result;
|
|
1815
|
-
}
|
|
1816
1812
|
function extractCustomColors(filename) {
|
|
1817
1813
|
const projectDir = path.dirname(filename);
|
|
1818
1814
|
const configPath = findTailwindConfig(projectDir);
|
|
@@ -1829,36 +1825,44 @@ function extractCustomColors(filename) {
|
|
|
1829
1825
|
);
|
|
1830
1826
|
}
|
|
1831
1827
|
const colors = config.theme.extend?.colors ?? config.theme.colors ?? {};
|
|
1832
|
-
return
|
|
1828
|
+
return flattenColors(colors);
|
|
1833
1829
|
}
|
|
1834
1830
|
|
|
1835
1831
|
// src/babel/index.ts
|
|
1836
|
-
var
|
|
1837
|
-
var
|
|
1832
|
+
var DEFAULT_STYLES_IDENTIFIER = "_twStyles";
|
|
1833
|
+
var DEFAULT_CLASS_ATTRIBUTES = [
|
|
1838
1834
|
"className",
|
|
1839
|
-
"containerClassName",
|
|
1840
1835
|
"contentContainerClassName",
|
|
1841
1836
|
"columnWrapperClassName",
|
|
1842
1837
|
"ListHeaderComponentClassName",
|
|
1843
1838
|
"ListFooterComponentClassName"
|
|
1844
1839
|
];
|
|
1845
|
-
function
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1840
|
+
function buildAttributeMatchers(attributes) {
|
|
1841
|
+
const exactMatches = /* @__PURE__ */ new Set();
|
|
1842
|
+
const patterns = [];
|
|
1843
|
+
for (const attr of attributes) {
|
|
1844
|
+
if (attr.includes("*")) {
|
|
1845
|
+
const regexPattern = "^" + attr.replace(/\*/g, ".*") + "$";
|
|
1846
|
+
patterns.push(new RegExp(regexPattern));
|
|
1847
|
+
} else {
|
|
1848
|
+
exactMatches.add(attr);
|
|
1849
|
+
}
|
|
1854
1850
|
}
|
|
1855
|
-
|
|
1856
|
-
|
|
1851
|
+
return { exactMatches, patterns };
|
|
1852
|
+
}
|
|
1853
|
+
function isAttributeSupported(attributeName, exactMatches, patterns) {
|
|
1854
|
+
if (exactMatches.has(attributeName)) {
|
|
1855
|
+
return true;
|
|
1857
1856
|
}
|
|
1858
|
-
|
|
1859
|
-
|
|
1857
|
+
for (const pattern of patterns) {
|
|
1858
|
+
if (pattern.test(attributeName)) {
|
|
1859
|
+
return true;
|
|
1860
|
+
}
|
|
1860
1861
|
}
|
|
1861
|
-
return
|
|
1862
|
+
return false;
|
|
1863
|
+
}
|
|
1864
|
+
function getTargetStyleProp(attributeName) {
|
|
1865
|
+
return attributeName.endsWith("ClassName") ? attributeName.replace("ClassName", "Style") : "style";
|
|
1862
1866
|
}
|
|
1863
1867
|
function getComponentModifierSupport(jsxElement, t) {
|
|
1864
1868
|
if (!t.isJSXOpeningElement(jsxElement)) {
|
|
@@ -1912,7 +1916,7 @@ function processTemplateLiteral(node, state, t) {
|
|
|
1912
1916
|
const styleKey = generateStyleKey2(cls);
|
|
1913
1917
|
state.styleRegistry.set(styleKey, styleObject);
|
|
1914
1918
|
staticParts.push(cls);
|
|
1915
|
-
parts.push(t.memberExpression(t.identifier(
|
|
1919
|
+
parts.push(t.memberExpression(t.identifier(state.stylesIdentifier), t.identifier(styleKey)));
|
|
1916
1920
|
}
|
|
1917
1921
|
}
|
|
1918
1922
|
if (i < node.expressions.length) {
|
|
@@ -1967,7 +1971,7 @@ function processStringOrExpression(node, state, t) {
|
|
|
1967
1971
|
const styleObject = parseClassName2(className, state.customColors);
|
|
1968
1972
|
const styleKey = generateStyleKey2(className);
|
|
1969
1973
|
state.styleRegistry.set(styleKey, styleObject);
|
|
1970
|
-
return t.memberExpression(t.identifier(
|
|
1974
|
+
return t.memberExpression(t.identifier(state.stylesIdentifier), t.identifier(styleKey));
|
|
1971
1975
|
}
|
|
1972
1976
|
if (t.isConditionalExpression(node)) {
|
|
1973
1977
|
const result = processConditionalExpression(node, state, t);
|
|
@@ -1991,7 +1995,7 @@ function processStaticClassNameWithModifiers(className, state, t) {
|
|
|
1991
1995
|
const baseStyleObject = parseClassName2(baseClassName, state.customColors);
|
|
1992
1996
|
const baseStyleKey = generateStyleKey2(baseClassName);
|
|
1993
1997
|
state.styleRegistry.set(baseStyleKey, baseStyleObject);
|
|
1994
|
-
baseStyleExpression = t.memberExpression(t.identifier(
|
|
1998
|
+
baseStyleExpression = t.memberExpression(t.identifier(state.stylesIdentifier), t.identifier(baseStyleKey));
|
|
1995
1999
|
}
|
|
1996
2000
|
const modifiersByType = /* @__PURE__ */ new Map();
|
|
1997
2001
|
for (const mod of modifierClasses) {
|
|
@@ -2016,7 +2020,7 @@ function processStaticClassNameWithModifiers(className, state, t) {
|
|
|
2016
2020
|
const conditionalExpression = t.logicalExpression(
|
|
2017
2021
|
"&&",
|
|
2018
2022
|
t.identifier(stateProperty),
|
|
2019
|
-
t.memberExpression(t.identifier(
|
|
2023
|
+
t.memberExpression(t.identifier(state.stylesIdentifier), t.identifier(modifierStyleKey))
|
|
2020
2024
|
);
|
|
2021
2025
|
styleArrayElements.push(conditionalExpression);
|
|
2022
2026
|
}
|
|
@@ -2054,9 +2058,53 @@ function createStyleFunction(styleExpression, modifierTypes, t) {
|
|
|
2054
2058
|
const param = t.objectPattern(paramProperties);
|
|
2055
2059
|
return t.arrowFunctionExpression([param], styleExpression);
|
|
2056
2060
|
}
|
|
2057
|
-
function
|
|
2058
|
-
|
|
2059
|
-
|
|
2061
|
+
function processTwCall(className, path2, state, t) {
|
|
2062
|
+
const { baseClasses, modifierClasses } = splitModifierClasses(className);
|
|
2063
|
+
const objectProperties = [];
|
|
2064
|
+
if (baseClasses.length > 0) {
|
|
2065
|
+
const baseClassName = baseClasses.join(" ");
|
|
2066
|
+
const baseStyleObject = parseClassName2(baseClassName, state.customColors);
|
|
2067
|
+
const baseStyleKey = generateStyleKey2(baseClassName);
|
|
2068
|
+
state.styleRegistry.set(baseStyleKey, baseStyleObject);
|
|
2069
|
+
objectProperties.push(
|
|
2070
|
+
t.objectProperty(
|
|
2071
|
+
t.identifier("style"),
|
|
2072
|
+
t.memberExpression(t.identifier(state.stylesIdentifier), t.identifier(baseStyleKey))
|
|
2073
|
+
)
|
|
2074
|
+
);
|
|
2075
|
+
} else {
|
|
2076
|
+
objectProperties.push(t.objectProperty(t.identifier("style"), t.objectExpression([])));
|
|
2077
|
+
}
|
|
2078
|
+
const modifiersByType = /* @__PURE__ */ new Map();
|
|
2079
|
+
for (const mod of modifierClasses) {
|
|
2080
|
+
if (!modifiersByType.has(mod.modifier)) {
|
|
2081
|
+
modifiersByType.set(mod.modifier, []);
|
|
2082
|
+
}
|
|
2083
|
+
const modGroup = modifiersByType.get(mod.modifier);
|
|
2084
|
+
if (modGroup) {
|
|
2085
|
+
modGroup.push(mod);
|
|
2086
|
+
}
|
|
2087
|
+
}
|
|
2088
|
+
for (const [modifierType, modifiers] of modifiersByType) {
|
|
2089
|
+
const modifierClassNames = modifiers.map((m) => m.baseClass).join(" ");
|
|
2090
|
+
const modifierStyleObject = parseClassName2(modifierClassNames, state.customColors);
|
|
2091
|
+
const modifierStyleKey = generateStyleKey2(`${modifierType}_${modifierClassNames}`);
|
|
2092
|
+
state.styleRegistry.set(modifierStyleKey, modifierStyleObject);
|
|
2093
|
+
const propertyName = `${modifierType}Style`;
|
|
2094
|
+
objectProperties.push(
|
|
2095
|
+
t.objectProperty(
|
|
2096
|
+
t.identifier(propertyName),
|
|
2097
|
+
t.memberExpression(t.identifier(state.stylesIdentifier), t.identifier(modifierStyleKey))
|
|
2098
|
+
)
|
|
2099
|
+
);
|
|
2100
|
+
}
|
|
2101
|
+
const twStyleObject = t.objectExpression(objectProperties);
|
|
2102
|
+
path2.replaceWith(twStyleObject);
|
|
2103
|
+
}
|
|
2104
|
+
function reactNativeTailwindBabelPlugin({ types: t }, options) {
|
|
2105
|
+
const attributes = options?.attributes ?? [...DEFAULT_CLASS_ATTRIBUTES];
|
|
2106
|
+
const { exactMatches, patterns } = buildAttributeMatchers(attributes);
|
|
2107
|
+
const stylesIdentifier = options?.stylesIdentifier ?? DEFAULT_STYLES_IDENTIFIER;
|
|
2060
2108
|
return {
|
|
2061
2109
|
name: "react-native-tailwind",
|
|
2062
2110
|
visitor: {
|
|
@@ -2065,19 +2113,27 @@ function reactNativeTailwindBabelPlugin({
|
|
|
2065
2113
|
state.styleRegistry = /* @__PURE__ */ new Map();
|
|
2066
2114
|
state.hasClassNames = false;
|
|
2067
2115
|
state.hasStyleSheetImport = false;
|
|
2116
|
+
state.supportedAttributes = exactMatches;
|
|
2117
|
+
state.attributePatterns = patterns;
|
|
2118
|
+
state.stylesIdentifier = stylesIdentifier;
|
|
2119
|
+
state.twImportNames = /* @__PURE__ */ new Set();
|
|
2120
|
+
state.hasTwImport = false;
|
|
2068
2121
|
state.customColors = extractCustomColors(state.file.opts.filename ?? "");
|
|
2069
2122
|
},
|
|
2070
2123
|
exit(path2, state) {
|
|
2124
|
+
if (state.hasTwImport) {
|
|
2125
|
+
removeTwImports(path2, t);
|
|
2126
|
+
}
|
|
2071
2127
|
if (!state.hasClassNames || state.styleRegistry.size === 0) {
|
|
2072
2128
|
return;
|
|
2073
2129
|
}
|
|
2074
2130
|
if (!state.hasStyleSheetImport) {
|
|
2075
2131
|
addStyleSheetImport(path2, t);
|
|
2076
2132
|
}
|
|
2077
|
-
|
|
2133
|
+
injectStylesAtTop(path2, state.styleRegistry, state.stylesIdentifier, t);
|
|
2078
2134
|
}
|
|
2079
2135
|
},
|
|
2080
|
-
// Check if StyleSheet is already imported
|
|
2136
|
+
// Check if StyleSheet is already imported and track tw/twStyle imports
|
|
2081
2137
|
ImportDeclaration(path2, state) {
|
|
2082
2138
|
const node = path2.node;
|
|
2083
2139
|
if (node.source.value === "react-native") {
|
|
@@ -2095,11 +2151,91 @@ function reactNativeTailwindBabelPlugin({
|
|
|
2095
2151
|
state.hasStyleSheetImport = true;
|
|
2096
2152
|
}
|
|
2097
2153
|
}
|
|
2154
|
+
if (node.source.value === "@mgcrea/react-native-tailwind") {
|
|
2155
|
+
const specifiers = node.specifiers;
|
|
2156
|
+
specifiers.forEach((spec) => {
|
|
2157
|
+
if (t.isImportSpecifier(spec) && t.isIdentifier(spec.imported)) {
|
|
2158
|
+
const importedName = spec.imported.name;
|
|
2159
|
+
if (importedName === "tw" || importedName === "twStyle") {
|
|
2160
|
+
const localName = spec.local.name;
|
|
2161
|
+
state.twImportNames.add(localName);
|
|
2162
|
+
state.hasTwImport = true;
|
|
2163
|
+
}
|
|
2164
|
+
}
|
|
2165
|
+
});
|
|
2166
|
+
}
|
|
2167
|
+
},
|
|
2168
|
+
// Handle tw`...` tagged template expressions
|
|
2169
|
+
TaggedTemplateExpression(path2, state) {
|
|
2170
|
+
const node = path2.node;
|
|
2171
|
+
if (!t.isIdentifier(node.tag)) {
|
|
2172
|
+
return;
|
|
2173
|
+
}
|
|
2174
|
+
const tagName = node.tag.name;
|
|
2175
|
+
if (!state.twImportNames.has(tagName)) {
|
|
2176
|
+
return;
|
|
2177
|
+
}
|
|
2178
|
+
const quasi = node.quasi;
|
|
2179
|
+
if (!t.isTemplateLiteral(quasi)) {
|
|
2180
|
+
return;
|
|
2181
|
+
}
|
|
2182
|
+
if (quasi.expressions.length > 0) {
|
|
2183
|
+
if (process.env.NODE_ENV !== "production") {
|
|
2184
|
+
console.warn(
|
|
2185
|
+
`[react-native-tailwind] Dynamic tw\`...\` with interpolations is not supported at ${state.file.opts.filename ?? "unknown"}. Use style prop for dynamic values.`
|
|
2186
|
+
);
|
|
2187
|
+
}
|
|
2188
|
+
return;
|
|
2189
|
+
}
|
|
2190
|
+
const className = quasi.quasis[0]?.value.cooked?.trim() ?? "";
|
|
2191
|
+
if (!className) {
|
|
2192
|
+
path2.replaceWith(
|
|
2193
|
+
t.objectExpression([t.objectProperty(t.identifier("style"), t.objectExpression([]))])
|
|
2194
|
+
);
|
|
2195
|
+
return;
|
|
2196
|
+
}
|
|
2197
|
+
state.hasClassNames = true;
|
|
2198
|
+
processTwCall(className, path2, state, t);
|
|
2199
|
+
},
|
|
2200
|
+
// Handle twStyle('...') call expressions
|
|
2201
|
+
CallExpression(path2, state) {
|
|
2202
|
+
const node = path2.node;
|
|
2203
|
+
if (!t.isIdentifier(node.callee)) {
|
|
2204
|
+
return;
|
|
2205
|
+
}
|
|
2206
|
+
const calleeName = node.callee.name;
|
|
2207
|
+
if (!state.twImportNames.has(calleeName)) {
|
|
2208
|
+
return;
|
|
2209
|
+
}
|
|
2210
|
+
if (node.arguments.length !== 1) {
|
|
2211
|
+
if (process.env.NODE_ENV !== "production") {
|
|
2212
|
+
console.warn(
|
|
2213
|
+
`[react-native-tailwind] twStyle() expects exactly one argument at ${state.file.opts.filename ?? "unknown"}`
|
|
2214
|
+
);
|
|
2215
|
+
}
|
|
2216
|
+
return;
|
|
2217
|
+
}
|
|
2218
|
+
const arg = node.arguments[0];
|
|
2219
|
+
if (!t.isStringLiteral(arg)) {
|
|
2220
|
+
if (process.env.NODE_ENV !== "production") {
|
|
2221
|
+
console.warn(
|
|
2222
|
+
`[react-native-tailwind] twStyle() only supports static string literals at ${state.file.opts.filename ?? "unknown"}. Use style prop for dynamic values.`
|
|
2223
|
+
);
|
|
2224
|
+
}
|
|
2225
|
+
return;
|
|
2226
|
+
}
|
|
2227
|
+
const className = arg.value.trim();
|
|
2228
|
+
if (!className) {
|
|
2229
|
+
path2.replaceWith(t.identifier("undefined"));
|
|
2230
|
+
return;
|
|
2231
|
+
}
|
|
2232
|
+
state.hasClassNames = true;
|
|
2233
|
+
processTwCall(className, path2, state, t);
|
|
2098
2234
|
},
|
|
2099
2235
|
JSXAttribute(path2, state) {
|
|
2100
2236
|
const node = path2.node;
|
|
2101
2237
|
const attributeName = node.name.name;
|
|
2102
|
-
if (!
|
|
2238
|
+
if (!isAttributeSupported(attributeName, state.supportedAttributes, state.attributePatterns)) {
|
|
2103
2239
|
return;
|
|
2104
2240
|
}
|
|
2105
2241
|
const value = node.value;
|
|
@@ -2182,9 +2318,9 @@ function reactNativeTailwindBabelPlugin({
|
|
|
2182
2318
|
(attr) => t.isJSXAttribute(attr) && attr.name.name === targetStyleProp
|
|
2183
2319
|
);
|
|
2184
2320
|
if (styleAttribute) {
|
|
2185
|
-
mergeStyleAttribute(path2, styleAttribute, styleKey, t);
|
|
2321
|
+
mergeStyleAttribute(path2, styleAttribute, styleKey, state.stylesIdentifier, t);
|
|
2186
2322
|
} else {
|
|
2187
|
-
replaceWithStyleAttribute(path2, styleKey, targetStyleProp, t);
|
|
2323
|
+
replaceWithStyleAttribute(path2, styleKey, targetStyleProp, state.stylesIdentifier, t);
|
|
2188
2324
|
}
|
|
2189
2325
|
return;
|
|
2190
2326
|
}
|
|
@@ -2233,17 +2369,39 @@ function addStyleSheetImport(path2, t) {
|
|
|
2233
2369
|
);
|
|
2234
2370
|
path2.unshiftContainer("body", importDeclaration);
|
|
2235
2371
|
}
|
|
2236
|
-
function
|
|
2372
|
+
function removeTwImports(path2, t) {
|
|
2373
|
+
path2.traverse({
|
|
2374
|
+
ImportDeclaration(importPath) {
|
|
2375
|
+
const node = importPath.node;
|
|
2376
|
+
if (node.source.value !== "@mgcrea/react-native-tailwind") {
|
|
2377
|
+
return;
|
|
2378
|
+
}
|
|
2379
|
+
const remainingSpecifiers = node.specifiers.filter((spec) => {
|
|
2380
|
+
if (t.isImportSpecifier(spec) && t.isIdentifier(spec.imported)) {
|
|
2381
|
+
const importedName = spec.imported.name;
|
|
2382
|
+
return importedName !== "tw" && importedName !== "twStyle";
|
|
2383
|
+
}
|
|
2384
|
+
return true;
|
|
2385
|
+
});
|
|
2386
|
+
if (remainingSpecifiers.length === 0) {
|
|
2387
|
+
importPath.remove();
|
|
2388
|
+
} else if (remainingSpecifiers.length < node.specifiers.length) {
|
|
2389
|
+
node.specifiers = remainingSpecifiers;
|
|
2390
|
+
}
|
|
2391
|
+
}
|
|
2392
|
+
});
|
|
2393
|
+
}
|
|
2394
|
+
function replaceWithStyleAttribute(classNamePath, styleKey, targetStyleProp, stylesIdentifier, t) {
|
|
2237
2395
|
const styleAttribute = t.jsxAttribute(
|
|
2238
2396
|
t.jsxIdentifier(targetStyleProp),
|
|
2239
|
-
t.jsxExpressionContainer(t.memberExpression(t.identifier(
|
|
2397
|
+
t.jsxExpressionContainer(t.memberExpression(t.identifier(stylesIdentifier), t.identifier(styleKey)))
|
|
2240
2398
|
);
|
|
2241
2399
|
classNamePath.replaceWith(styleAttribute);
|
|
2242
2400
|
}
|
|
2243
|
-
function mergeStyleAttribute(classNamePath, styleAttribute, styleKey, t) {
|
|
2401
|
+
function mergeStyleAttribute(classNamePath, styleAttribute, styleKey, stylesIdentifier, t) {
|
|
2244
2402
|
const existingStyle = styleAttribute.value.expression;
|
|
2245
2403
|
const styleArray = t.arrayExpression([
|
|
2246
|
-
t.memberExpression(t.identifier(
|
|
2404
|
+
t.memberExpression(t.identifier(stylesIdentifier), t.identifier(styleKey)),
|
|
2247
2405
|
existingStyle
|
|
2248
2406
|
]);
|
|
2249
2407
|
styleAttribute.value = t.jsxExpressionContainer(styleArray);
|
|
@@ -2292,7 +2450,7 @@ function mergeStyleFunctionAttribute(classNamePath, styleAttribute, styleFunctio
|
|
|
2292
2450
|
}
|
|
2293
2451
|
classNamePath.remove();
|
|
2294
2452
|
}
|
|
2295
|
-
function
|
|
2453
|
+
function injectStylesAtTop(path2, styleRegistry, stylesIdentifier, t) {
|
|
2296
2454
|
const styleProperties = [];
|
|
2297
2455
|
for (const [key, styleObject] of styleRegistry) {
|
|
2298
2456
|
const properties = Object.entries(styleObject).map(([styleProp, styleValue]) => {
|
|
@@ -2310,13 +2468,22 @@ function injectStyles(path2, styleRegistry, t) {
|
|
|
2310
2468
|
}
|
|
2311
2469
|
const styleSheet = t.variableDeclaration("const", [
|
|
2312
2470
|
t.variableDeclarator(
|
|
2313
|
-
t.identifier(
|
|
2471
|
+
t.identifier(stylesIdentifier),
|
|
2314
2472
|
t.callExpression(t.memberExpression(t.identifier("StyleSheet"), t.identifier("create")), [
|
|
2315
2473
|
t.objectExpression(styleProperties)
|
|
2316
2474
|
])
|
|
2317
2475
|
)
|
|
2318
2476
|
]);
|
|
2319
|
-
path2.
|
|
2477
|
+
const body = path2.node.body;
|
|
2478
|
+
let insertIndex = 0;
|
|
2479
|
+
for (let i = 0; i < body.length; i++) {
|
|
2480
|
+
if (t.isImportDeclaration(body[i])) {
|
|
2481
|
+
insertIndex = i + 1;
|
|
2482
|
+
} else {
|
|
2483
|
+
break;
|
|
2484
|
+
}
|
|
2485
|
+
}
|
|
2486
|
+
body.splice(insertIndex, 0, styleSheet);
|
|
2320
2487
|
}
|
|
2321
2488
|
function parseClassName2(className, customColors) {
|
|
2322
2489
|
return parseClassName(className, customColors);
|
package/dist/babel/index.d.ts
CHANGED
|
@@ -5,13 +5,38 @@
|
|
|
5
5
|
import type { PluginObj, PluginPass } from "@babel/core";
|
|
6
6
|
import * as BabelTypes from "@babel/types";
|
|
7
7
|
import { StyleObject } from "src/types.js";
|
|
8
|
+
/**
|
|
9
|
+
* Plugin options
|
|
10
|
+
*/
|
|
11
|
+
export type PluginOptions = {
|
|
12
|
+
/**
|
|
13
|
+
* List of JSX attribute names to transform (in addition to or instead of 'className')
|
|
14
|
+
* Supports exact matches and glob patterns:
|
|
15
|
+
* - Exact: 'className', 'containerClassName'
|
|
16
|
+
* - Glob: '*ClassName' (matches any attribute ending in 'ClassName')
|
|
17
|
+
*
|
|
18
|
+
* @default ['className', 'contentContainerClassName', 'columnWrapperClassName', 'ListHeaderComponentClassName', 'ListFooterComponentClassName']
|
|
19
|
+
*/
|
|
20
|
+
attributes?: string[];
|
|
21
|
+
/**
|
|
22
|
+
* Custom identifier name for the generated StyleSheet constant
|
|
23
|
+
*
|
|
24
|
+
* @default '_twStyles'
|
|
25
|
+
*/
|
|
26
|
+
stylesIdentifier?: string;
|
|
27
|
+
};
|
|
8
28
|
type PluginState = PluginPass & {
|
|
9
29
|
styleRegistry: Map<string, StyleObject>;
|
|
10
30
|
hasClassNames: boolean;
|
|
11
31
|
hasStyleSheetImport: boolean;
|
|
12
32
|
customColors: Record<string, string>;
|
|
33
|
+
supportedAttributes: Set<string>;
|
|
34
|
+
attributePatterns: RegExp[];
|
|
35
|
+
stylesIdentifier: string;
|
|
36
|
+
twImportNames: Set<string>;
|
|
37
|
+
hasTwImport: boolean;
|
|
13
38
|
};
|
|
14
|
-
export default function reactNativeTailwindBabelPlugin({ types: t
|
|
39
|
+
export default function reactNativeTailwindBabelPlugin({ types: t }: {
|
|
15
40
|
types: typeof BabelTypes;
|
|
16
|
-
}): PluginObj<PluginState>;
|
|
41
|
+
}, options?: PluginOptions): PluginObj<PluginState>;
|
|
17
42
|
export {};
|