@mgcrea/react-native-tailwind 0.11.1 → 0.12.1
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/dist/babel/config-loader.d.ts +3 -0
- package/dist/babel/config-loader.test.ts +2 -2
- package/dist/babel/config-loader.ts +37 -2
- package/dist/babel/index.cjs +325 -42
- package/dist/babel/plugin.test.ts +498 -0
- package/dist/babel/plugin.ts +66 -17
- package/dist/babel/utils/styleInjection.ts +57 -17
- package/dist/babel/utils/twProcessing.d.ts +8 -1
- package/dist/babel/utils/twProcessing.ts +212 -4
- package/dist/parser/index.d.ts +1 -0
- package/dist/parser/index.js +1 -1
- package/dist/parser/layout.js +1 -1
- package/dist/parser/layout.test.js +1 -1
- package/dist/parser/spacing.d.ts +1 -1
- package/dist/parser/spacing.js +1 -1
- package/dist/parser/spacing.test.js +1 -1
- package/dist/parser/typography.d.ts +2 -1
- package/dist/parser/typography.js +1 -1
- package/dist/parser/typography.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/runtime.test.js +1 -1
- package/dist/types/runtime.d.ts +8 -1
- package/package.json +1 -1
- package/src/babel/config-loader.test.ts +2 -2
- package/src/babel/config-loader.ts +37 -2
- package/src/babel/plugin.test.ts +498 -0
- package/src/babel/plugin.ts +66 -17
- package/src/babel/utils/styleInjection.ts +57 -17
- package/src/babel/utils/twProcessing.ts +212 -4
- package/src/parser/index.ts +2 -1
- package/src/parser/layout.test.ts +61 -0
- package/src/parser/layout.ts +55 -1
- package/src/parser/spacing.test.ts +62 -0
- package/src/parser/spacing.ts +7 -7
- package/src/parser/typography.test.ts +102 -0
- package/src/parser/typography.ts +61 -15
- package/src/runtime.test.ts +4 -1
- package/src/types/runtime.ts +8 -1
package/dist/babel/index.cjs
CHANGED
|
@@ -701,6 +701,21 @@ function parseArbitraryZIndex(value) {
|
|
|
701
701
|
}
|
|
702
702
|
return null;
|
|
703
703
|
}
|
|
704
|
+
function parseArbitraryGrowShrink(value) {
|
|
705
|
+
const match = value.match(/^\[(\d+(?:\.\d+)?|\.\d+)\]$/);
|
|
706
|
+
if (match) {
|
|
707
|
+
return parseFloat(match[1]);
|
|
708
|
+
}
|
|
709
|
+
if (value.startsWith("[") && value.endsWith("]")) {
|
|
710
|
+
if (process.env.NODE_ENV !== "production") {
|
|
711
|
+
console.warn(
|
|
712
|
+
`[react-native-tailwind] Invalid arbitrary grow/shrink value: ${value}. Only non-negative numbers are supported (e.g., [1.5], [2], [0.5], [.5]).`
|
|
713
|
+
);
|
|
714
|
+
}
|
|
715
|
+
return null;
|
|
716
|
+
}
|
|
717
|
+
return null;
|
|
718
|
+
}
|
|
704
719
|
var DISPLAY_MAP = {
|
|
705
720
|
flex: { display: "flex" },
|
|
706
721
|
hidden: { display: "none" }
|
|
@@ -725,7 +740,12 @@ var GROW_SHRINK_MAP = {
|
|
|
725
740
|
grow: { flexGrow: 1 },
|
|
726
741
|
"grow-0": { flexGrow: 0 },
|
|
727
742
|
shrink: { flexShrink: 1 },
|
|
728
|
-
"shrink-0": { flexShrink: 0 }
|
|
743
|
+
"shrink-0": { flexShrink: 0 },
|
|
744
|
+
// CSS-style aliases
|
|
745
|
+
"flex-grow": { flexGrow: 1 },
|
|
746
|
+
"flex-grow-0": { flexGrow: 0 },
|
|
747
|
+
"flex-shrink": { flexShrink: 1 },
|
|
748
|
+
"flex-shrink-0": { flexShrink: 0 }
|
|
729
749
|
};
|
|
730
750
|
var JUSTIFY_CONTENT_MAP = {
|
|
731
751
|
"justify-start": { justifyContent: "flex-start" },
|
|
@@ -920,6 +940,22 @@ function parseLayout(cls) {
|
|
|
920
940
|
return { top: insetValue, right: insetValue, bottom: insetValue, left: insetValue };
|
|
921
941
|
}
|
|
922
942
|
}
|
|
943
|
+
if (cls.startsWith("grow-") || cls.startsWith("flex-grow-")) {
|
|
944
|
+
const prefix = cls.startsWith("flex-grow-") ? "flex-grow-" : "grow-";
|
|
945
|
+
const growKey = cls.substring(prefix.length);
|
|
946
|
+
const arbitraryGrow = parseArbitraryGrowShrink(growKey);
|
|
947
|
+
if (arbitraryGrow !== null) {
|
|
948
|
+
return { flexGrow: arbitraryGrow };
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
if (cls.startsWith("shrink-") || cls.startsWith("flex-shrink-")) {
|
|
952
|
+
const prefix = cls.startsWith("flex-shrink-") ? "flex-shrink-" : "shrink-";
|
|
953
|
+
const shrinkKey = cls.substring(prefix.length);
|
|
954
|
+
const arbitraryShrink = parseArbitraryGrowShrink(shrinkKey);
|
|
955
|
+
if (arbitraryShrink !== null) {
|
|
956
|
+
return { flexShrink: arbitraryShrink };
|
|
957
|
+
}
|
|
958
|
+
}
|
|
923
959
|
return DISPLAY_MAP[cls] ?? FLEX_DIRECTION_MAP[cls] ?? FLEX_WRAP_MAP[cls] ?? FLEX_MAP[cls] ?? GROW_SHRINK_MAP[cls] ?? JUSTIFY_CONTENT_MAP[cls] ?? ALIGN_ITEMS_MAP[cls] ?? ALIGN_SELF_MAP[cls] ?? ALIGN_CONTENT_MAP[cls] ?? POSITION_MAP[cls] ?? OVERFLOW_MAP[cls] ?? OPACITY_MAP[cls] ?? null;
|
|
924
960
|
}
|
|
925
961
|
|
|
@@ -1194,14 +1230,14 @@ var SPACING_SCALE = {
|
|
|
1194
1230
|
96: 384
|
|
1195
1231
|
};
|
|
1196
1232
|
function parseArbitrarySpacing(value) {
|
|
1197
|
-
const pxMatch = value.match(/^\[(
|
|
1233
|
+
const pxMatch = value.match(/^\[(-?\d+(?:\.\d+)?)(?:px)?\]$/);
|
|
1198
1234
|
if (pxMatch) {
|
|
1199
|
-
return
|
|
1235
|
+
return parseFloat(pxMatch[1]);
|
|
1200
1236
|
}
|
|
1201
1237
|
if (value.startsWith("[") && value.endsWith("]")) {
|
|
1202
1238
|
if (process.env.NODE_ENV !== "production") {
|
|
1203
1239
|
console.warn(
|
|
1204
|
-
`[react-native-tailwind] Unsupported arbitrary spacing value: ${value}. Only px values are supported (e.g., [16px]
|
|
1240
|
+
`[react-native-tailwind] Unsupported arbitrary spacing value: ${value}. Only px values are supported (e.g., [16px], [16], [4.5px], [4.5]).`
|
|
1205
1241
|
);
|
|
1206
1242
|
}
|
|
1207
1243
|
return null;
|
|
@@ -1649,14 +1685,14 @@ var TRACKING_MAP = {
|
|
|
1649
1685
|
"tracking-widest": { letterSpacing: 1.6 }
|
|
1650
1686
|
};
|
|
1651
1687
|
function parseArbitraryFontSize(value) {
|
|
1652
|
-
const pxMatch = value.match(/^\[(
|
|
1688
|
+
const pxMatch = value.match(/^\[(-?\d+(?:\.\d+)?|-?\.\d+)(?:px)?\]$/);
|
|
1653
1689
|
if (pxMatch) {
|
|
1654
|
-
return
|
|
1690
|
+
return parseFloat(pxMatch[1]);
|
|
1655
1691
|
}
|
|
1656
1692
|
if (value.startsWith("[") && value.endsWith("]")) {
|
|
1657
1693
|
if (process.env.NODE_ENV !== "production") {
|
|
1658
1694
|
console.warn(
|
|
1659
|
-
`[react-native-tailwind] Unsupported arbitrary font size value: ${value}. Only px values are supported (e.g., [18px]
|
|
1695
|
+
`[react-native-tailwind] Unsupported arbitrary font size value: ${value}. Only px values are supported (e.g., [18px], [13.5px], [.5]).`
|
|
1660
1696
|
);
|
|
1661
1697
|
}
|
|
1662
1698
|
return null;
|
|
@@ -1664,21 +1700,36 @@ function parseArbitraryFontSize(value) {
|
|
|
1664
1700
|
return null;
|
|
1665
1701
|
}
|
|
1666
1702
|
function parseArbitraryLineHeight(value) {
|
|
1667
|
-
const pxMatch = value.match(/^\[(
|
|
1703
|
+
const pxMatch = value.match(/^\[(-?\d+(?:\.\d+)?|-?\.\d+)(?:px)?\]$/);
|
|
1668
1704
|
if (pxMatch) {
|
|
1669
|
-
return
|
|
1705
|
+
return parseFloat(pxMatch[1]);
|
|
1670
1706
|
}
|
|
1671
1707
|
if (value.startsWith("[") && value.endsWith("]")) {
|
|
1672
1708
|
if (process.env.NODE_ENV !== "production") {
|
|
1673
1709
|
console.warn(
|
|
1674
|
-
`[react-native-tailwind] Unsupported arbitrary line height value: ${value}. Only px values are supported (e.g., [24px]
|
|
1710
|
+
`[react-native-tailwind] Unsupported arbitrary line height value: ${value}. Only px values are supported (e.g., [24px], [21.5px], [.5]).`
|
|
1675
1711
|
);
|
|
1676
1712
|
}
|
|
1677
1713
|
return null;
|
|
1678
1714
|
}
|
|
1679
1715
|
return null;
|
|
1680
1716
|
}
|
|
1681
|
-
function
|
|
1717
|
+
function parseArbitraryLetterSpacing(value) {
|
|
1718
|
+
const pxMatch = value.match(/^\[(-?\d+(?:\.\d+)?|-?\.\d+)(?:px)?\]$/);
|
|
1719
|
+
if (pxMatch) {
|
|
1720
|
+
return parseFloat(pxMatch[1]);
|
|
1721
|
+
}
|
|
1722
|
+
if (value.startsWith("[") && value.endsWith("]")) {
|
|
1723
|
+
if (process.env.NODE_ENV !== "production") {
|
|
1724
|
+
console.warn(
|
|
1725
|
+
`[react-native-tailwind] Unsupported arbitrary letter spacing value: ${value}. Only px values are supported (e.g., [0.5px], [0.3], [.5], [-0.4]).`
|
|
1726
|
+
);
|
|
1727
|
+
}
|
|
1728
|
+
return null;
|
|
1729
|
+
}
|
|
1730
|
+
return null;
|
|
1731
|
+
}
|
|
1732
|
+
function parseTypography(cls, customFontFamily, customFontSize) {
|
|
1682
1733
|
const fontFamilyMap = customFontFamily ? {
|
|
1683
1734
|
...FONT_FAMILY_MAP,
|
|
1684
1735
|
...Object.fromEntries(
|
|
@@ -1691,6 +1742,9 @@ function parseTypography(cls, customFontFamily) {
|
|
|
1691
1742
|
if (arbitraryValue !== null) {
|
|
1692
1743
|
return { fontSize: arbitraryValue };
|
|
1693
1744
|
}
|
|
1745
|
+
if (customFontSize?.[sizeKey] !== void 0) {
|
|
1746
|
+
return { fontSize: customFontSize[sizeKey] };
|
|
1747
|
+
}
|
|
1694
1748
|
const fontSize = FONT_SIZES[sizeKey];
|
|
1695
1749
|
if (fontSize !== void 0) {
|
|
1696
1750
|
return { fontSize };
|
|
@@ -1707,6 +1761,13 @@ function parseTypography(cls, customFontFamily) {
|
|
|
1707
1761
|
return { lineHeight };
|
|
1708
1762
|
}
|
|
1709
1763
|
}
|
|
1764
|
+
if (cls.startsWith("tracking-")) {
|
|
1765
|
+
const trackingKey = cls.substring(9);
|
|
1766
|
+
const arbitraryValue = parseArbitraryLetterSpacing(trackingKey);
|
|
1767
|
+
if (arbitraryValue !== null) {
|
|
1768
|
+
return { letterSpacing: arbitraryValue };
|
|
1769
|
+
}
|
|
1770
|
+
}
|
|
1710
1771
|
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;
|
|
1711
1772
|
}
|
|
1712
1773
|
|
|
@@ -1863,7 +1924,7 @@ function parseClass(cls, customTheme) {
|
|
|
1863
1924
|
parseBorder,
|
|
1864
1925
|
(cls2) => parseColor(cls2, customTheme?.colors),
|
|
1865
1926
|
parseLayout,
|
|
1866
|
-
(cls2) => parseTypography(cls2, customTheme?.fontFamily),
|
|
1927
|
+
(cls2) => parseTypography(cls2, customTheme?.fontFamily, customTheme?.fontSize),
|
|
1867
1928
|
parseSizing,
|
|
1868
1929
|
parseShadow,
|
|
1869
1930
|
parseAspectRatio,
|
|
@@ -1935,11 +1996,11 @@ function extractCustomTheme(filename) {
|
|
|
1935
1996
|
const projectDir = path.dirname(filename);
|
|
1936
1997
|
const configPath = findTailwindConfig(projectDir);
|
|
1937
1998
|
if (!configPath) {
|
|
1938
|
-
return { colors: {}, fontFamily: {} };
|
|
1999
|
+
return { colors: {}, fontFamily: {}, fontSize: {} };
|
|
1939
2000
|
}
|
|
1940
2001
|
const config = loadTailwindConfig(configPath);
|
|
1941
2002
|
if (!config?.theme) {
|
|
1942
|
-
return { colors: {}, fontFamily: {} };
|
|
2003
|
+
return { colors: {}, fontFamily: {}, fontSize: {} };
|
|
1943
2004
|
}
|
|
1944
2005
|
if (config.theme.colors && !config.theme.extend?.colors && process.env.NODE_ENV !== "production") {
|
|
1945
2006
|
console.warn(
|
|
@@ -1961,9 +2022,33 @@ function extractCustomTheme(filename) {
|
|
|
1961
2022
|
fontFamilyResult[key] = value;
|
|
1962
2023
|
}
|
|
1963
2024
|
}
|
|
2025
|
+
if (config.theme.fontSize && !config.theme.extend?.fontSize && process.env.NODE_ENV !== "production") {
|
|
2026
|
+
console.warn(
|
|
2027
|
+
"[react-native-tailwind] Using theme.fontSize will override all default font sizes. Use theme.extend.fontSize to add custom font sizes while keeping defaults."
|
|
2028
|
+
);
|
|
2029
|
+
}
|
|
2030
|
+
const fontSize = config.theme.extend?.fontSize ?? config.theme.fontSize ?? {};
|
|
2031
|
+
const fontSizeResult = {};
|
|
2032
|
+
for (const [key, value] of Object.entries(fontSize)) {
|
|
2033
|
+
if (typeof value === "number") {
|
|
2034
|
+
fontSizeResult[key] = value;
|
|
2035
|
+
} else if (typeof value === "string") {
|
|
2036
|
+
const parsed = parseFloat(value.replace(/px$/, ""));
|
|
2037
|
+
if (!isNaN(parsed)) {
|
|
2038
|
+
fontSizeResult[key] = parsed;
|
|
2039
|
+
} else {
|
|
2040
|
+
if (process.env.NODE_ENV !== "production") {
|
|
2041
|
+
console.warn(
|
|
2042
|
+
`[react-native-tailwind] Invalid fontSize value for "${key}": ${value}. Expected number or string like "18px".`
|
|
2043
|
+
);
|
|
2044
|
+
}
|
|
2045
|
+
}
|
|
2046
|
+
}
|
|
2047
|
+
}
|
|
1964
2048
|
return {
|
|
1965
2049
|
colors: flattenColors(colors),
|
|
1966
|
-
fontFamily: fontFamilyResult
|
|
2050
|
+
fontFamily: fontFamilyResult,
|
|
2051
|
+
fontSize: fontSizeResult
|
|
1967
2052
|
};
|
|
1968
2053
|
}
|
|
1969
2054
|
|
|
@@ -2480,17 +2565,29 @@ function processPlatformModifiers(platformModifiers, state, parseClassName2, gen
|
|
|
2480
2565
|
// src/babel/utils/styleInjection.ts
|
|
2481
2566
|
function addStyleSheetImport(path2, t) {
|
|
2482
2567
|
const body = path2.node.body;
|
|
2483
|
-
let
|
|
2568
|
+
let existingValueImport = null;
|
|
2484
2569
|
for (const statement of body) {
|
|
2485
2570
|
if (t.isImportDeclaration(statement) && statement.source.value === "react-native") {
|
|
2486
|
-
|
|
2571
|
+
if (statement.importKind === "type") {
|
|
2572
|
+
continue;
|
|
2573
|
+
}
|
|
2574
|
+
const hasNamespaceImport = statement.specifiers.some((spec) => t.isImportNamespaceSpecifier(spec));
|
|
2575
|
+
if (hasNamespaceImport) {
|
|
2576
|
+
continue;
|
|
2577
|
+
}
|
|
2578
|
+
existingValueImport = statement;
|
|
2487
2579
|
break;
|
|
2488
2580
|
}
|
|
2489
2581
|
}
|
|
2490
|
-
if (
|
|
2491
|
-
|
|
2492
|
-
t.
|
|
2582
|
+
if (existingValueImport) {
|
|
2583
|
+
const hasStyleSheet = existingValueImport.specifiers.some(
|
|
2584
|
+
(spec) => t.isImportSpecifier(spec) && spec.imported.type === "Identifier" && spec.imported.name === "StyleSheet"
|
|
2493
2585
|
);
|
|
2586
|
+
if (!hasStyleSheet) {
|
|
2587
|
+
existingValueImport.specifiers.push(
|
|
2588
|
+
t.importSpecifier(t.identifier("StyleSheet"), t.identifier("StyleSheet"))
|
|
2589
|
+
);
|
|
2590
|
+
}
|
|
2494
2591
|
} else {
|
|
2495
2592
|
const importDeclaration = t.importDeclaration(
|
|
2496
2593
|
[t.importSpecifier(t.identifier("StyleSheet"), t.identifier("StyleSheet"))],
|
|
@@ -2501,15 +2598,29 @@ function addStyleSheetImport(path2, t) {
|
|
|
2501
2598
|
}
|
|
2502
2599
|
function addPlatformImport(path2, t) {
|
|
2503
2600
|
const body = path2.node.body;
|
|
2504
|
-
let
|
|
2601
|
+
let existingValueImport = null;
|
|
2505
2602
|
for (const statement of body) {
|
|
2506
2603
|
if (t.isImportDeclaration(statement) && statement.source.value === "react-native") {
|
|
2507
|
-
|
|
2604
|
+
if (statement.importKind === "type") {
|
|
2605
|
+
continue;
|
|
2606
|
+
}
|
|
2607
|
+
const hasNamespaceImport = statement.specifiers.some((spec) => t.isImportNamespaceSpecifier(spec));
|
|
2608
|
+
if (hasNamespaceImport) {
|
|
2609
|
+
continue;
|
|
2610
|
+
}
|
|
2611
|
+
existingValueImport = statement;
|
|
2508
2612
|
break;
|
|
2509
2613
|
}
|
|
2510
2614
|
}
|
|
2511
|
-
if (
|
|
2512
|
-
|
|
2615
|
+
if (existingValueImport) {
|
|
2616
|
+
const hasPlatform = existingValueImport.specifiers.some(
|
|
2617
|
+
(spec) => t.isImportSpecifier(spec) && spec.imported.type === "Identifier" && spec.imported.name === "Platform"
|
|
2618
|
+
);
|
|
2619
|
+
if (!hasPlatform) {
|
|
2620
|
+
existingValueImport.specifiers.push(
|
|
2621
|
+
t.importSpecifier(t.identifier("Platform"), t.identifier("Platform"))
|
|
2622
|
+
);
|
|
2623
|
+
}
|
|
2513
2624
|
} else {
|
|
2514
2625
|
const importDeclaration = t.importDeclaration(
|
|
2515
2626
|
[t.importSpecifier(t.identifier("Platform"), t.identifier("Platform"))],
|
|
@@ -2725,7 +2836,7 @@ function addOrMergePlaceholderTextColorProp(jsxOpeningElement, color, t) {
|
|
|
2725
2836
|
}
|
|
2726
2837
|
|
|
2727
2838
|
// src/babel/utils/twProcessing.ts
|
|
2728
|
-
function processTwCall(className, path2, state, parseClassName2, generateStyleKey2, splitModifierClasses2, t) {
|
|
2839
|
+
function processTwCall(className, path2, state, parseClassName2, generateStyleKey2, splitModifierClasses2, findComponentScope2, t) {
|
|
2729
2840
|
const { baseClasses, modifierClasses: rawModifierClasses } = splitModifierClasses2(className);
|
|
2730
2841
|
const modifierClasses = [];
|
|
2731
2842
|
for (const modifier of rawModifierClasses) {
|
|
@@ -2756,8 +2867,145 @@ function processTwCall(className, path2, state, parseClassName2, generateStyleKe
|
|
|
2756
2867
|
} else {
|
|
2757
2868
|
objectProperties.push(t.objectProperty(t.identifier("style"), t.objectExpression([])));
|
|
2758
2869
|
}
|
|
2870
|
+
const colorSchemeModifiers = modifierClasses.filter((m) => isColorSchemeModifier(m.modifier));
|
|
2871
|
+
const platformModifiers = modifierClasses.filter((m) => isPlatformModifier(m.modifier));
|
|
2872
|
+
const otherModifiers = modifierClasses.filter(
|
|
2873
|
+
(m) => !isColorSchemeModifier(m.modifier) && !isPlatformModifier(m.modifier)
|
|
2874
|
+
);
|
|
2875
|
+
const hasColorSchemeModifiers = colorSchemeModifiers.length > 0;
|
|
2876
|
+
let componentScope = null;
|
|
2877
|
+
if (hasColorSchemeModifiers) {
|
|
2878
|
+
componentScope = findComponentScope2(path2, t);
|
|
2879
|
+
if (!componentScope) {
|
|
2880
|
+
if (process.env.NODE_ENV !== "production") {
|
|
2881
|
+
console.warn(
|
|
2882
|
+
`[react-native-tailwind] Color scheme modifiers (dark:, light:) in tw/twStyle calls must be used inside a React component. Modifiers will be ignored.`
|
|
2883
|
+
);
|
|
2884
|
+
}
|
|
2885
|
+
} else {
|
|
2886
|
+
state.functionComponentsNeedingColorScheme.add(componentScope);
|
|
2887
|
+
}
|
|
2888
|
+
}
|
|
2889
|
+
if (hasColorSchemeModifiers && componentScope) {
|
|
2890
|
+
const colorSchemeConditionals = processColorSchemeModifiers(
|
|
2891
|
+
colorSchemeModifiers,
|
|
2892
|
+
state,
|
|
2893
|
+
parseClassName2,
|
|
2894
|
+
generateStyleKey2,
|
|
2895
|
+
t
|
|
2896
|
+
);
|
|
2897
|
+
const styleArrayElements = [];
|
|
2898
|
+
if (baseClasses.length > 0) {
|
|
2899
|
+
const baseClassName = baseClasses.join(" ");
|
|
2900
|
+
const baseStyleObject = parseClassName2(baseClassName, state.customTheme);
|
|
2901
|
+
const baseStyleKey = generateStyleKey2(baseClassName);
|
|
2902
|
+
state.styleRegistry.set(baseStyleKey, baseStyleObject);
|
|
2903
|
+
styleArrayElements.push(
|
|
2904
|
+
t.memberExpression(t.identifier(state.stylesIdentifier), t.identifier(baseStyleKey))
|
|
2905
|
+
);
|
|
2906
|
+
}
|
|
2907
|
+
styleArrayElements.push(...colorSchemeConditionals);
|
|
2908
|
+
objectProperties[0] = t.objectProperty(t.identifier("style"), t.arrayExpression(styleArrayElements));
|
|
2909
|
+
const darkModifiers = colorSchemeModifiers.filter((m) => m.modifier === "dark");
|
|
2910
|
+
const lightModifiers = colorSchemeModifiers.filter((m) => m.modifier === "light");
|
|
2911
|
+
if (darkModifiers.length > 0) {
|
|
2912
|
+
const darkClassNames = darkModifiers.map((m) => m.baseClass).join(" ");
|
|
2913
|
+
const darkStyleObject = parseClassName2(darkClassNames, state.customTheme);
|
|
2914
|
+
const darkStyleKey = generateStyleKey2(`dark_${darkClassNames}`);
|
|
2915
|
+
state.styleRegistry.set(darkStyleKey, darkStyleObject);
|
|
2916
|
+
objectProperties.push(
|
|
2917
|
+
t.objectProperty(
|
|
2918
|
+
t.identifier("darkStyle"),
|
|
2919
|
+
t.memberExpression(t.identifier(state.stylesIdentifier), t.identifier(darkStyleKey))
|
|
2920
|
+
)
|
|
2921
|
+
);
|
|
2922
|
+
}
|
|
2923
|
+
if (lightModifiers.length > 0) {
|
|
2924
|
+
const lightClassNames = lightModifiers.map((m) => m.baseClass).join(" ");
|
|
2925
|
+
const lightStyleObject = parseClassName2(lightClassNames, state.customTheme);
|
|
2926
|
+
const lightStyleKey = generateStyleKey2(`light_${lightClassNames}`);
|
|
2927
|
+
state.styleRegistry.set(lightStyleKey, lightStyleObject);
|
|
2928
|
+
objectProperties.push(
|
|
2929
|
+
t.objectProperty(
|
|
2930
|
+
t.identifier("lightStyle"),
|
|
2931
|
+
t.memberExpression(t.identifier(state.stylesIdentifier), t.identifier(lightStyleKey))
|
|
2932
|
+
)
|
|
2933
|
+
);
|
|
2934
|
+
}
|
|
2935
|
+
}
|
|
2936
|
+
const hasPlatformModifiers = platformModifiers.length > 0;
|
|
2937
|
+
if (hasPlatformModifiers) {
|
|
2938
|
+
state.needsPlatformImport = true;
|
|
2939
|
+
const platformSelectExpression = processPlatformModifiers(
|
|
2940
|
+
platformModifiers,
|
|
2941
|
+
state,
|
|
2942
|
+
parseClassName2,
|
|
2943
|
+
generateStyleKey2,
|
|
2944
|
+
t
|
|
2945
|
+
);
|
|
2946
|
+
if (hasColorSchemeModifiers && componentScope) {
|
|
2947
|
+
const styleProperty = objectProperties.find(
|
|
2948
|
+
(prop) => t.isIdentifier(prop.key) && prop.key.name === "style"
|
|
2949
|
+
);
|
|
2950
|
+
if (styleProperty && t.isArrayExpression(styleProperty.value)) {
|
|
2951
|
+
styleProperty.value.elements.push(platformSelectExpression);
|
|
2952
|
+
}
|
|
2953
|
+
} else {
|
|
2954
|
+
const styleArrayElements = [];
|
|
2955
|
+
if (baseClasses.length > 0) {
|
|
2956
|
+
const baseClassName = baseClasses.join(" ");
|
|
2957
|
+
const baseStyleObject = parseClassName2(baseClassName, state.customTheme);
|
|
2958
|
+
const baseStyleKey = generateStyleKey2(baseClassName);
|
|
2959
|
+
state.styleRegistry.set(baseStyleKey, baseStyleObject);
|
|
2960
|
+
styleArrayElements.push(
|
|
2961
|
+
t.memberExpression(t.identifier(state.stylesIdentifier), t.identifier(baseStyleKey))
|
|
2962
|
+
);
|
|
2963
|
+
}
|
|
2964
|
+
styleArrayElements.push(platformSelectExpression);
|
|
2965
|
+
objectProperties[0] = t.objectProperty(t.identifier("style"), t.arrayExpression(styleArrayElements));
|
|
2966
|
+
}
|
|
2967
|
+
const iosModifiers = platformModifiers.filter((m) => m.modifier === "ios");
|
|
2968
|
+
const androidModifiers = platformModifiers.filter((m) => m.modifier === "android");
|
|
2969
|
+
const webModifiers = platformModifiers.filter((m) => m.modifier === "web");
|
|
2970
|
+
if (iosModifiers.length > 0) {
|
|
2971
|
+
const iosClassNames = iosModifiers.map((m) => m.baseClass).join(" ");
|
|
2972
|
+
const iosStyleObject = parseClassName2(iosClassNames, state.customTheme);
|
|
2973
|
+
const iosStyleKey = generateStyleKey2(`ios_${iosClassNames}`);
|
|
2974
|
+
state.styleRegistry.set(iosStyleKey, iosStyleObject);
|
|
2975
|
+
objectProperties.push(
|
|
2976
|
+
t.objectProperty(
|
|
2977
|
+
t.identifier("iosStyle"),
|
|
2978
|
+
t.memberExpression(t.identifier(state.stylesIdentifier), t.identifier(iosStyleKey))
|
|
2979
|
+
)
|
|
2980
|
+
);
|
|
2981
|
+
}
|
|
2982
|
+
if (androidModifiers.length > 0) {
|
|
2983
|
+
const androidClassNames = androidModifiers.map((m) => m.baseClass).join(" ");
|
|
2984
|
+
const androidStyleObject = parseClassName2(androidClassNames, state.customTheme);
|
|
2985
|
+
const androidStyleKey = generateStyleKey2(`android_${androidClassNames}`);
|
|
2986
|
+
state.styleRegistry.set(androidStyleKey, androidStyleObject);
|
|
2987
|
+
objectProperties.push(
|
|
2988
|
+
t.objectProperty(
|
|
2989
|
+
t.identifier("androidStyle"),
|
|
2990
|
+
t.memberExpression(t.identifier(state.stylesIdentifier), t.identifier(androidStyleKey))
|
|
2991
|
+
)
|
|
2992
|
+
);
|
|
2993
|
+
}
|
|
2994
|
+
if (webModifiers.length > 0) {
|
|
2995
|
+
const webClassNames = webModifiers.map((m) => m.baseClass).join(" ");
|
|
2996
|
+
const webStyleObject = parseClassName2(webClassNames, state.customTheme);
|
|
2997
|
+
const webStyleKey = generateStyleKey2(`web_${webClassNames}`);
|
|
2998
|
+
state.styleRegistry.set(webStyleKey, webStyleObject);
|
|
2999
|
+
objectProperties.push(
|
|
3000
|
+
t.objectProperty(
|
|
3001
|
+
t.identifier("webStyle"),
|
|
3002
|
+
t.memberExpression(t.identifier(state.stylesIdentifier), t.identifier(webStyleKey))
|
|
3003
|
+
)
|
|
3004
|
+
);
|
|
3005
|
+
}
|
|
3006
|
+
}
|
|
2759
3007
|
const modifiersByType = /* @__PURE__ */ new Map();
|
|
2760
|
-
for (const mod of
|
|
3008
|
+
for (const mod of otherModifiers) {
|
|
2761
3009
|
if (!modifiersByType.has(mod.modifier)) {
|
|
2762
3010
|
modifiersByType.set(mod.modifier, []);
|
|
2763
3011
|
}
|
|
@@ -2876,6 +3124,10 @@ function reactNativeTailwindBabelPlugin({ types: t }, options) {
|
|
|
2876
3124
|
state.twImportNames = /* @__PURE__ */ new Set();
|
|
2877
3125
|
state.hasTwImport = false;
|
|
2878
3126
|
state.functionComponentsNeedingColorScheme = /* @__PURE__ */ new Set();
|
|
3127
|
+
state.hasColorSchemeImport = false;
|
|
3128
|
+
state.colorSchemeLocalIdentifier = void 0;
|
|
3129
|
+
state.needsPlatformImport = false;
|
|
3130
|
+
state.hasPlatformImport = false;
|
|
2879
3131
|
state.customTheme = extractCustomTheme(state.file.opts.filename ?? "");
|
|
2880
3132
|
state.schemeModifierConfig = schemeModifierConfig;
|
|
2881
3133
|
},
|
|
@@ -2934,7 +3186,7 @@ function reactNativeTailwindBabelPlugin({ types: t }, options) {
|
|
|
2934
3186
|
}
|
|
2935
3187
|
state.reactNativeImportPath = path2;
|
|
2936
3188
|
}
|
|
2937
|
-
if (node.source.value === state.colorSchemeImportSource) {
|
|
3189
|
+
if (node.source.value === state.colorSchemeImportSource && node.importKind !== "type") {
|
|
2938
3190
|
const specifiers = node.specifiers;
|
|
2939
3191
|
for (const spec of specifiers) {
|
|
2940
3192
|
if (t.isImportSpecifier(spec) && t.isIdentifier(spec.imported)) {
|
|
@@ -2954,7 +3206,6 @@ function reactNativeTailwindBabelPlugin({ types: t }, options) {
|
|
|
2954
3206
|
if (importedName === "tw" || importedName === "twStyle") {
|
|
2955
3207
|
const localName = spec.local.name;
|
|
2956
3208
|
state.twImportNames.add(localName);
|
|
2957
|
-
state.hasTwImport = true;
|
|
2958
3209
|
}
|
|
2959
3210
|
}
|
|
2960
3211
|
});
|
|
@@ -2987,10 +3238,21 @@ function reactNativeTailwindBabelPlugin({ types: t }, options) {
|
|
|
2987
3238
|
path2.replaceWith(
|
|
2988
3239
|
t.objectExpression([t.objectProperty(t.identifier("style"), t.objectExpression([]))])
|
|
2989
3240
|
);
|
|
3241
|
+
state.hasTwImport = true;
|
|
2990
3242
|
return;
|
|
2991
3243
|
}
|
|
2992
3244
|
state.hasClassNames = true;
|
|
2993
|
-
processTwCall(
|
|
3245
|
+
processTwCall(
|
|
3246
|
+
className,
|
|
3247
|
+
path2,
|
|
3248
|
+
state,
|
|
3249
|
+
parseClassName,
|
|
3250
|
+
generateStyleKey,
|
|
3251
|
+
splitModifierClasses,
|
|
3252
|
+
findComponentScope,
|
|
3253
|
+
t
|
|
3254
|
+
);
|
|
3255
|
+
state.hasTwImport = true;
|
|
2994
3256
|
},
|
|
2995
3257
|
// Handle twStyle('...') call expressions
|
|
2996
3258
|
CallExpression(path2, state) {
|
|
@@ -3022,10 +3284,21 @@ function reactNativeTailwindBabelPlugin({ types: t }, options) {
|
|
|
3022
3284
|
const className = arg.value.trim();
|
|
3023
3285
|
if (!className) {
|
|
3024
3286
|
path2.replaceWith(t.identifier("undefined"));
|
|
3287
|
+
state.hasTwImport = true;
|
|
3025
3288
|
return;
|
|
3026
3289
|
}
|
|
3027
3290
|
state.hasClassNames = true;
|
|
3028
|
-
processTwCall(
|
|
3291
|
+
processTwCall(
|
|
3292
|
+
className,
|
|
3293
|
+
path2,
|
|
3294
|
+
state,
|
|
3295
|
+
parseClassName,
|
|
3296
|
+
generateStyleKey,
|
|
3297
|
+
splitModifierClasses,
|
|
3298
|
+
findComponentScope,
|
|
3299
|
+
t
|
|
3300
|
+
);
|
|
3301
|
+
state.hasTwImport = true;
|
|
3029
3302
|
},
|
|
3030
3303
|
JSXAttribute(path2, state) {
|
|
3031
3304
|
const node = path2.node;
|
|
@@ -3038,14 +3311,14 @@ function reactNativeTailwindBabelPlugin({ types: t }, options) {
|
|
|
3038
3311
|
}
|
|
3039
3312
|
const value = node.value;
|
|
3040
3313
|
const targetStyleProp = getTargetStyleProp(attributeName);
|
|
3041
|
-
|
|
3042
|
-
const
|
|
3043
|
-
if (!
|
|
3314
|
+
const processStaticClassName = (className) => {
|
|
3315
|
+
const trimmedClassName = className.trim();
|
|
3316
|
+
if (!trimmedClassName) {
|
|
3044
3317
|
path2.remove();
|
|
3045
|
-
return;
|
|
3318
|
+
return true;
|
|
3046
3319
|
}
|
|
3047
3320
|
state.hasClassNames = true;
|
|
3048
|
-
const { baseClasses, modifierClasses: rawModifierClasses } = splitModifierClasses(
|
|
3321
|
+
const { baseClasses, modifierClasses: rawModifierClasses } = splitModifierClasses(trimmedClassName);
|
|
3049
3322
|
const modifierClasses = [];
|
|
3050
3323
|
for (const modifier of rawModifierClasses) {
|
|
3051
3324
|
if (isSchemeModifier(modifier.modifier)) {
|
|
@@ -3169,7 +3442,7 @@ function reactNativeTailwindBabelPlugin({ types: t }, options) {
|
|
|
3169
3442
|
} else {
|
|
3170
3443
|
replaceWithStyleFunctionAttribute(path2, styleFunctionExpression, targetStyleProp, t);
|
|
3171
3444
|
}
|
|
3172
|
-
return;
|
|
3445
|
+
return true;
|
|
3173
3446
|
} else {
|
|
3174
3447
|
}
|
|
3175
3448
|
}
|
|
@@ -3220,7 +3493,7 @@ function reactNativeTailwindBabelPlugin({ types: t }, options) {
|
|
|
3220
3493
|
path2.node.name = t.jsxIdentifier(targetStyleProp);
|
|
3221
3494
|
path2.node.value = t.jsxExpressionContainer(styleExpression);
|
|
3222
3495
|
}
|
|
3223
|
-
return;
|
|
3496
|
+
return true;
|
|
3224
3497
|
}
|
|
3225
3498
|
if (hasStateModifiers) {
|
|
3226
3499
|
const jsxOpeningElement = path2.parent;
|
|
@@ -3258,11 +3531,11 @@ function reactNativeTailwindBabelPlugin({ types: t }, options) {
|
|
|
3258
3531
|
} else {
|
|
3259
3532
|
replaceWithStyleFunctionAttribute(path2, styleFunctionExpression, targetStyleProp, t);
|
|
3260
3533
|
}
|
|
3261
|
-
return;
|
|
3534
|
+
return true;
|
|
3262
3535
|
}
|
|
3263
3536
|
} else {
|
|
3264
3537
|
const styleExpression = processStaticClassNameWithModifiers(
|
|
3265
|
-
|
|
3538
|
+
trimmedClassName,
|
|
3266
3539
|
state,
|
|
3267
3540
|
parseClassName,
|
|
3268
3541
|
generateStyleKey,
|
|
@@ -3277,7 +3550,7 @@ function reactNativeTailwindBabelPlugin({ types: t }, options) {
|
|
|
3277
3550
|
} else {
|
|
3278
3551
|
replaceWithStyleFunctionAttribute(path2, styleFunctionExpression, targetStyleProp, t);
|
|
3279
3552
|
}
|
|
3280
|
-
return;
|
|
3553
|
+
return true;
|
|
3281
3554
|
}
|
|
3282
3555
|
} else {
|
|
3283
3556
|
if (process.env.NODE_ENV !== "production") {
|
|
@@ -3291,7 +3564,7 @@ function reactNativeTailwindBabelPlugin({ types: t }, options) {
|
|
|
3291
3564
|
const classNameForStyle = baseClasses.join(" ");
|
|
3292
3565
|
if (!classNameForStyle) {
|
|
3293
3566
|
path2.remove();
|
|
3294
|
-
return;
|
|
3567
|
+
return true;
|
|
3295
3568
|
}
|
|
3296
3569
|
const styleObject = parseClassName(classNameForStyle, state.customTheme);
|
|
3297
3570
|
const styleKey = generateStyleKey(classNameForStyle);
|
|
@@ -3302,13 +3575,23 @@ function reactNativeTailwindBabelPlugin({ types: t }, options) {
|
|
|
3302
3575
|
} else {
|
|
3303
3576
|
replaceWithStyleAttribute(path2, styleKey, targetStyleProp, state.stylesIdentifier, t);
|
|
3304
3577
|
}
|
|
3305
|
-
return;
|
|
3578
|
+
return true;
|
|
3579
|
+
};
|
|
3580
|
+
if (t.isStringLiteral(value)) {
|
|
3581
|
+
if (processStaticClassName(value.value)) {
|
|
3582
|
+
return;
|
|
3583
|
+
}
|
|
3306
3584
|
}
|
|
3307
3585
|
if (t.isJSXExpressionContainer(value)) {
|
|
3308
3586
|
const expression = value.expression;
|
|
3309
3587
|
if (t.isJSXEmptyExpression(expression)) {
|
|
3310
3588
|
return;
|
|
3311
3589
|
}
|
|
3590
|
+
if (t.isStringLiteral(expression)) {
|
|
3591
|
+
if (processStaticClassName(expression.value)) {
|
|
3592
|
+
return;
|
|
3593
|
+
}
|
|
3594
|
+
}
|
|
3312
3595
|
try {
|
|
3313
3596
|
const componentScope = findComponentScope(path2, t);
|
|
3314
3597
|
const result = processDynamicExpression(
|