@mgcrea/react-native-tailwind 0.9.0 → 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 +575 -60
- package/dist/babel/plugin.d.ts +23 -1
- package/dist/babel/plugin.test.ts +417 -0
- package/dist/babel/plugin.ts +265 -32
- 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 +14 -1
- package/dist/babel/utils/styleInjection.ts +125 -7
- 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/aspectRatio.js +1 -1
- package/dist/parser/aspectRatio.test.js +1 -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/parser/spacing.d.ts +1 -1
- package/dist/parser/spacing.js +1 -1
- package/dist/parser/spacing.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/config.d.ts +7 -0
- package/dist/types/config.js +0 -0
- package/package.json +4 -4
- package/src/babel/config-loader.test.ts +152 -0
- package/src/babel/plugin.test.ts +417 -0
- package/src/babel/plugin.ts +265 -32
- package/src/babel/utils/colorSchemeModifierProcessing.ts +89 -0
- package/src/babel/utils/dynamicProcessing.ts +352 -33
- package/src/babel/utils/styleInjection.ts +125 -7
- package/src/babel/utils/styleTransforms.test.ts +56 -0
- package/src/babel/utils/twProcessing.ts +22 -1
- package/src/parser/aspectRatio.test.ts +25 -2
- package/src/parser/aspectRatio.ts +3 -3
- package/src/parser/index.ts +12 -1
- package/src/parser/modifiers.test.ts +151 -1
- package/src/parser/modifiers.ts +139 -4
- package/src/parser/spacing.test.ts +63 -0
- package/src/parser/spacing.ts +10 -6
- package/src/runtime.test.ts +27 -0
- package/src/runtime.ts +2 -1
- package/src/types/config.ts +7 -0
- package/dist/babel/index.test.ts +0 -481
- package/dist/config/palettes.d.ts +0 -302
- package/dist/config/palettes.js +0 -1
- package/dist/parser/__snapshots__/aspectRatio.test.js.snap +0 -9
- package/dist/parser/__snapshots__/borders.test.js.snap +0 -23
- package/dist/parser/__snapshots__/colors.test.js.snap +0 -251
- package/dist/parser/__snapshots__/shadows.test.js.snap +0 -76
- package/dist/parser/__snapshots__/sizing.test.js.snap +0 -61
- package/dist/parser/__snapshots__/spacing.test.js.snap +0 -40
- package/dist/parser/__snapshots__/transforms.test.js.snap +0 -58
- package/dist/parser/__snapshots__/typography.test.js.snap +0 -30
- package/dist/parser/aspectRatio.test.d.ts +0 -1
- package/dist/parser/borders.test.d.ts +0 -1
- package/dist/parser/colors.test.d.ts +0 -1
- package/dist/parser/layout.test.d.ts +0 -1
- package/dist/parser/modifiers.test.d.ts +0 -1
- package/dist/parser/shadows.test.d.ts +0 -1
- package/dist/parser/sizing.test.d.ts +0 -1
- package/dist/parser/spacing.test.d.ts +0 -1
- package/dist/parser/typography.test.d.ts +0 -1
- package/dist/types.d.ts +0 -42
- package/dist/types.js +0 -1
package/dist/babel/plugin.d.ts
CHANGED
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
* Babel plugin for react-native-tailwind
|
|
3
3
|
* Transforms className props to style props at compile time
|
|
4
4
|
*/
|
|
5
|
-
import type { PluginObj, PluginPass } from "@babel/core";
|
|
5
|
+
import type { NodePath, PluginObj, PluginPass } from "@babel/core";
|
|
6
6
|
import * as BabelTypes from "@babel/types";
|
|
7
7
|
import type { StyleObject } from "../types/core.js";
|
|
8
|
+
import type { SchemeModifierConfig } from "../types/config.js";
|
|
8
9
|
/**
|
|
9
10
|
* Plugin options
|
|
10
11
|
*/
|
|
@@ -24,6 +25,21 @@ export type PluginOptions = {
|
|
|
24
25
|
* @default '_twStyles'
|
|
25
26
|
*/
|
|
26
27
|
stylesIdentifier?: string;
|
|
28
|
+
/**
|
|
29
|
+
* Configuration for the scheme: modifier that expands to both dark: and light: modifiers
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* {
|
|
33
|
+
* darkSuffix: '-dark', // scheme:bg-primary -> dark:bg-primary-dark
|
|
34
|
+
* lightSuffix: '-light' // scheme:bg-primary -> light:bg-primary-light
|
|
35
|
+
* }
|
|
36
|
+
*
|
|
37
|
+
* @default { darkSuffix: '-dark', lightSuffix: '-light' }
|
|
38
|
+
*/
|
|
39
|
+
schemeModifier?: {
|
|
40
|
+
darkSuffix?: string;
|
|
41
|
+
lightSuffix?: string;
|
|
42
|
+
};
|
|
27
43
|
};
|
|
28
44
|
type PluginState = PluginPass & {
|
|
29
45
|
styleRegistry: Map<string, StyleObject>;
|
|
@@ -31,12 +47,18 @@ type PluginState = PluginPass & {
|
|
|
31
47
|
hasStyleSheetImport: boolean;
|
|
32
48
|
hasPlatformImport: boolean;
|
|
33
49
|
needsPlatformImport: boolean;
|
|
50
|
+
hasColorSchemeImport: boolean;
|
|
51
|
+
needsColorSchemeImport: boolean;
|
|
52
|
+
colorSchemeVariableName: string;
|
|
34
53
|
customColors: Record<string, string>;
|
|
54
|
+
schemeModifierConfig: SchemeModifierConfig;
|
|
35
55
|
supportedAttributes: Set<string>;
|
|
36
56
|
attributePatterns: RegExp[];
|
|
37
57
|
stylesIdentifier: string;
|
|
38
58
|
twImportNames: Set<string>;
|
|
39
59
|
hasTwImport: boolean;
|
|
60
|
+
reactNativeImportPath?: NodePath<BabelTypes.ImportDeclaration>;
|
|
61
|
+
functionComponentsNeedingColorScheme: Set<NodePath<BabelTypes.Function>>;
|
|
40
62
|
};
|
|
41
63
|
export default function reactNativeTailwindBabelPlugin({ types: t }: {
|
|
42
64
|
types: typeof BabelTypes;
|
|
@@ -721,3 +721,420 @@ describe("Babel plugin - platform modifier transformation", () => {
|
|
|
721
721
|
expect(output).not.toMatch(/(?<!_ios|_android|_web)_p_8:/);
|
|
722
722
|
});
|
|
723
723
|
});
|
|
724
|
+
|
|
725
|
+
describe("Babel plugin - color scheme modifier transformation", () => {
|
|
726
|
+
it("should transform dark: modifier to conditional expression", () => {
|
|
727
|
+
const input = `
|
|
728
|
+
import React from 'react';
|
|
729
|
+
import { View } from 'react-native';
|
|
730
|
+
|
|
731
|
+
export function Component() {
|
|
732
|
+
return (
|
|
733
|
+
<View className="bg-white dark:bg-gray-900" />
|
|
734
|
+
);
|
|
735
|
+
}
|
|
736
|
+
`;
|
|
737
|
+
|
|
738
|
+
const output = transform(input, undefined, true);
|
|
739
|
+
|
|
740
|
+
// Should import useColorScheme
|
|
741
|
+
expect(output).toContain("useColorScheme");
|
|
742
|
+
expect(output).toMatch(/import.*useColorScheme.*from ['"]react-native['"]/);
|
|
743
|
+
|
|
744
|
+
// Should inject colorScheme hook in component
|
|
745
|
+
expect(output).toContain("_twColorScheme");
|
|
746
|
+
expect(output).toContain("useColorScheme()");
|
|
747
|
+
|
|
748
|
+
// Should have base bg-white style
|
|
749
|
+
expect(output).toContain("_bg_white");
|
|
750
|
+
|
|
751
|
+
// Should have dark:bg-gray-900 style
|
|
752
|
+
expect(output).toContain("_dark_bg_gray_900");
|
|
753
|
+
|
|
754
|
+
// Should generate conditional: _twColorScheme === 'dark' && ...
|
|
755
|
+
expect(output).toMatch(/_twColorScheme\s*===\s*['"]dark['"]/);
|
|
756
|
+
});
|
|
757
|
+
|
|
758
|
+
it("should support both dark: and light: modifiers", () => {
|
|
759
|
+
const input = `
|
|
760
|
+
import React from 'react';
|
|
761
|
+
import { View } from 'react-native';
|
|
762
|
+
|
|
763
|
+
export function Component() {
|
|
764
|
+
return (
|
|
765
|
+
<View className="bg-gray-100 dark:bg-gray-900 light:bg-white" />
|
|
766
|
+
);
|
|
767
|
+
}
|
|
768
|
+
`;
|
|
769
|
+
|
|
770
|
+
const output = transform(input, undefined, true);
|
|
771
|
+
|
|
772
|
+
// Should have all three styles
|
|
773
|
+
expect(output).toContain("_bg_gray_100");
|
|
774
|
+
expect(output).toContain("_dark_bg_gray_900");
|
|
775
|
+
expect(output).toContain("_light_bg_white");
|
|
776
|
+
|
|
777
|
+
// Should have both conditionals
|
|
778
|
+
expect(output).toMatch(/_twColorScheme\s*===\s*['"]dark['"]/);
|
|
779
|
+
expect(output).toMatch(/_twColorScheme\s*===\s*['"]light['"]/);
|
|
780
|
+
});
|
|
781
|
+
|
|
782
|
+
it("should inject hook once for multiple elements with color scheme modifiers", () => {
|
|
783
|
+
const input = `
|
|
784
|
+
import React from 'react';
|
|
785
|
+
import { View, Text } from 'react-native';
|
|
786
|
+
|
|
787
|
+
export function Component() {
|
|
788
|
+
return (
|
|
789
|
+
<>
|
|
790
|
+
<View className="dark:bg-gray-900" />
|
|
791
|
+
<Text className="dark:text-white" />
|
|
792
|
+
<View className="light:bg-white" />
|
|
793
|
+
</>
|
|
794
|
+
);
|
|
795
|
+
}
|
|
796
|
+
`;
|
|
797
|
+
|
|
798
|
+
const output = transform(input, undefined, true);
|
|
799
|
+
|
|
800
|
+
// Count occurrences of useColorScheme() call - should be exactly 1
|
|
801
|
+
const hookCallMatches = output.match(/=\s*useColorScheme\(\)/g);
|
|
802
|
+
expect(hookCallMatches).toHaveLength(1);
|
|
803
|
+
|
|
804
|
+
// Should have color scheme variable
|
|
805
|
+
expect(output).toContain("_twColorScheme");
|
|
806
|
+
});
|
|
807
|
+
|
|
808
|
+
it("should work with color scheme and platform modifiers together", () => {
|
|
809
|
+
const input = `
|
|
810
|
+
import React from 'react';
|
|
811
|
+
import { View } from 'react-native';
|
|
812
|
+
|
|
813
|
+
export function Component() {
|
|
814
|
+
return (
|
|
815
|
+
<View className="p-4 ios:p-6 dark:bg-gray-900" />
|
|
816
|
+
);
|
|
817
|
+
}
|
|
818
|
+
`;
|
|
819
|
+
|
|
820
|
+
const output = transform(input, undefined, true);
|
|
821
|
+
|
|
822
|
+
// Should have Platform import
|
|
823
|
+
expect(output).toContain("Platform");
|
|
824
|
+
|
|
825
|
+
// Should have useColorScheme import
|
|
826
|
+
expect(output).toContain("useColorScheme");
|
|
827
|
+
|
|
828
|
+
// Should have Platform.select for ios:
|
|
829
|
+
expect(output).toContain("Platform.select");
|
|
830
|
+
expect(output).toContain("_ios_p_6");
|
|
831
|
+
|
|
832
|
+
// Should have color scheme conditional for dark:
|
|
833
|
+
expect(output).toMatch(/_twColorScheme\s*===\s*['"]dark['"]/);
|
|
834
|
+
expect(output).toContain("_dark_bg_gray_900");
|
|
835
|
+
});
|
|
836
|
+
|
|
837
|
+
it("should only add useColorScheme import once when needed", () => {
|
|
838
|
+
const input = `
|
|
839
|
+
import React from 'react';
|
|
840
|
+
import { View } from 'react-native';
|
|
841
|
+
|
|
842
|
+
export function Component() {
|
|
843
|
+
return (
|
|
844
|
+
<>
|
|
845
|
+
<View className="dark:bg-black" />
|
|
846
|
+
<View className="light:bg-white" />
|
|
847
|
+
</>
|
|
848
|
+
);
|
|
849
|
+
}
|
|
850
|
+
`;
|
|
851
|
+
|
|
852
|
+
const output = transform(input, undefined, true);
|
|
853
|
+
|
|
854
|
+
// Count useColorScheme imports
|
|
855
|
+
const importMatches = output.match(/import.*useColorScheme.*from ['"]react-native['"]/g);
|
|
856
|
+
expect(importMatches).toHaveLength(1);
|
|
857
|
+
});
|
|
858
|
+
|
|
859
|
+
it("should merge with existing useColorScheme import", () => {
|
|
860
|
+
const input = `
|
|
861
|
+
import React from 'react';
|
|
862
|
+
import { View, useColorScheme } from 'react-native';
|
|
863
|
+
|
|
864
|
+
export function Component() {
|
|
865
|
+
return <View className="dark:bg-gray-900" />;
|
|
866
|
+
}
|
|
867
|
+
`;
|
|
868
|
+
|
|
869
|
+
const output = transform(input, undefined, true);
|
|
870
|
+
|
|
871
|
+
// Should still use useColorScheme
|
|
872
|
+
expect(output).toContain("useColorScheme");
|
|
873
|
+
|
|
874
|
+
// Should inject hook call
|
|
875
|
+
expect(output).toContain("_twColorScheme");
|
|
876
|
+
expect(output).toContain("useColorScheme()");
|
|
877
|
+
});
|
|
878
|
+
|
|
879
|
+
it("should work with concise arrow functions", () => {
|
|
880
|
+
const input = `
|
|
881
|
+
import React from 'react';
|
|
882
|
+
import { View } from 'react-native';
|
|
883
|
+
|
|
884
|
+
const Component = () => <View className="dark:bg-gray-900" />;
|
|
885
|
+
`;
|
|
886
|
+
|
|
887
|
+
const output = transform(input, undefined, true);
|
|
888
|
+
|
|
889
|
+
// Should inject useColorScheme import
|
|
890
|
+
expect(output).toContain("useColorScheme");
|
|
891
|
+
|
|
892
|
+
// Should convert concise arrow to block statement and inject hook
|
|
893
|
+
expect(output).toContain("_twColorScheme");
|
|
894
|
+
expect(output).toContain("useColorScheme()");
|
|
895
|
+
expect(output).toContain("return");
|
|
896
|
+
|
|
897
|
+
// Should have the style
|
|
898
|
+
expect(output).toContain("_dark_bg_gray_900");
|
|
899
|
+
expect(output).toMatch(/_twColorScheme\s*===\s*['"]dark['"]/);
|
|
900
|
+
});
|
|
901
|
+
|
|
902
|
+
it("should inject hook at component level when dark: used in nested callback", () => {
|
|
903
|
+
const input = `
|
|
904
|
+
import React from 'react';
|
|
905
|
+
import { View } from 'react-native';
|
|
906
|
+
|
|
907
|
+
export function Component() {
|
|
908
|
+
const items = [1, 2, 3];
|
|
909
|
+
return (
|
|
910
|
+
<View>
|
|
911
|
+
{items.map(item => (
|
|
912
|
+
<View key={item} className="dark:bg-gray-900" />
|
|
913
|
+
))}
|
|
914
|
+
</View>
|
|
915
|
+
);
|
|
916
|
+
}
|
|
917
|
+
`;
|
|
918
|
+
|
|
919
|
+
const output = transform(input, undefined, true);
|
|
920
|
+
|
|
921
|
+
// Should inject hook at Component level (not in map callback)
|
|
922
|
+
expect(output).toContain("_twColorScheme");
|
|
923
|
+
expect(output).toContain("useColorScheme()");
|
|
924
|
+
|
|
925
|
+
// Hook should be injected in Component function, not in map callback
|
|
926
|
+
// Count occurrences - should be exactly 1 at Component level
|
|
927
|
+
const hookCallMatches = output.match(/=\s*useColorScheme\(\)/g);
|
|
928
|
+
expect(hookCallMatches).toHaveLength(1);
|
|
929
|
+
|
|
930
|
+
// Should still generate conditional expression
|
|
931
|
+
expect(output).toContain("_dark_bg_gray_900");
|
|
932
|
+
expect(output).toMatch(/_twColorScheme\s*===\s*['"]dark['"]/);
|
|
933
|
+
});
|
|
934
|
+
|
|
935
|
+
it("should handle dynamic expressions with dark:/light: modifiers", () => {
|
|
936
|
+
const input = `
|
|
937
|
+
import React from 'react';
|
|
938
|
+
import { View } from 'react-native';
|
|
939
|
+
|
|
940
|
+
export function Component({ isActive }) {
|
|
941
|
+
return (
|
|
942
|
+
<View className={\`p-4 \${isActive ? "dark:bg-blue-500" : "dark:bg-gray-900"}\`} />
|
|
943
|
+
);
|
|
944
|
+
}
|
|
945
|
+
`;
|
|
946
|
+
|
|
947
|
+
const output = transform(input, undefined, true);
|
|
948
|
+
|
|
949
|
+
// Should inject useColorScheme
|
|
950
|
+
expect(output).toContain("useColorScheme");
|
|
951
|
+
expect(output).toContain("_twColorScheme");
|
|
952
|
+
|
|
953
|
+
// Should have both dark styles
|
|
954
|
+
expect(output).toContain("_dark_bg_blue_500");
|
|
955
|
+
expect(output).toContain("_dark_bg_gray_900");
|
|
956
|
+
|
|
957
|
+
// Should have conditional expressions for color scheme
|
|
958
|
+
expect(output).toMatch(/_twColorScheme\s*===\s*['"]dark['"]/);
|
|
959
|
+
});
|
|
960
|
+
|
|
961
|
+
it("should handle dynamic expressions with platform modifiers", () => {
|
|
962
|
+
const input = `
|
|
963
|
+
import React from 'react';
|
|
964
|
+
import { View } from 'react-native';
|
|
965
|
+
|
|
966
|
+
export function Component({ isLarge }) {
|
|
967
|
+
return (
|
|
968
|
+
<View className={\`p-4 \${isLarge ? "ios:p-8" : "ios:p-6"}\`} />
|
|
969
|
+
);
|
|
970
|
+
}
|
|
971
|
+
`;
|
|
972
|
+
|
|
973
|
+
const output = transform(input, undefined, true);
|
|
974
|
+
|
|
975
|
+
// Should inject Platform import
|
|
976
|
+
expect(output).toContain("Platform");
|
|
977
|
+
|
|
978
|
+
// Should have both ios styles
|
|
979
|
+
expect(output).toContain("_ios_p_8");
|
|
980
|
+
expect(output).toContain("_ios_p_6");
|
|
981
|
+
|
|
982
|
+
// Should have Platform.select
|
|
983
|
+
expect(output).toContain("Platform.select");
|
|
984
|
+
});
|
|
985
|
+
|
|
986
|
+
it("should skip color scheme modifiers when used outside component scope", () => {
|
|
987
|
+
// Suppress console.warn for this test
|
|
988
|
+
const consoleWarnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
|
|
989
|
+
|
|
990
|
+
const input = `
|
|
991
|
+
import React from 'react';
|
|
992
|
+
import { View } from 'react-native';
|
|
993
|
+
|
|
994
|
+
// Class component - no function component scope
|
|
995
|
+
class MyComponent extends React.Component {
|
|
996
|
+
render() {
|
|
997
|
+
return <View className="p-4 dark:bg-gray-900" />;
|
|
998
|
+
}
|
|
999
|
+
}
|
|
1000
|
+
`;
|
|
1001
|
+
|
|
1002
|
+
const output = transform(input, undefined, true);
|
|
1003
|
+
|
|
1004
|
+
// Should warn about invalid context
|
|
1005
|
+
expect(consoleWarnSpy).toHaveBeenCalledWith(
|
|
1006
|
+
expect.stringContaining("dark:/light: modifiers require a function component scope"),
|
|
1007
|
+
);
|
|
1008
|
+
|
|
1009
|
+
// Should NOT inject useColorScheme import (no valid component scope)
|
|
1010
|
+
expect(output).not.toContain("useColorScheme");
|
|
1011
|
+
|
|
1012
|
+
// Should NOT have _twColorScheme variable reference (would cause ReferenceError)
|
|
1013
|
+
expect(output).not.toContain("_twColorScheme");
|
|
1014
|
+
|
|
1015
|
+
// Should NOT have dark: style conditional (skipped due to no component scope)
|
|
1016
|
+
expect(output).not.toContain("_dark_bg_gray_900");
|
|
1017
|
+
|
|
1018
|
+
// Should still transform base classes (p-4)
|
|
1019
|
+
expect(output).toContain("_p_4");
|
|
1020
|
+
|
|
1021
|
+
consoleWarnSpy.mockRestore();
|
|
1022
|
+
});
|
|
1023
|
+
});
|
|
1024
|
+
|
|
1025
|
+
describe("Babel plugin - import injection", () => {
|
|
1026
|
+
it("should not add StyleSheet import to files without className usage", () => {
|
|
1027
|
+
const input = `
|
|
1028
|
+
import { View, Text } from 'react-native';
|
|
1029
|
+
|
|
1030
|
+
function MyComponent() {
|
|
1031
|
+
return <View><Text>Hello</Text></View>;
|
|
1032
|
+
}
|
|
1033
|
+
`;
|
|
1034
|
+
|
|
1035
|
+
const output = transform(input, undefined, true);
|
|
1036
|
+
|
|
1037
|
+
// Should not mutate the import by adding StyleSheet
|
|
1038
|
+
// Count occurrences of "StyleSheet" in output
|
|
1039
|
+
const styleSheetCount = (output.match(/StyleSheet/g) ?? []).length;
|
|
1040
|
+
expect(styleSheetCount).toBe(0);
|
|
1041
|
+
|
|
1042
|
+
// Should not have _twStyles definition
|
|
1043
|
+
expect(output).not.toContain("_twStyles");
|
|
1044
|
+
expect(output).not.toContain("StyleSheet.create");
|
|
1045
|
+
|
|
1046
|
+
// Original imports should remain unchanged
|
|
1047
|
+
expect(output).toContain("View");
|
|
1048
|
+
expect(output).toContain("Text");
|
|
1049
|
+
});
|
|
1050
|
+
|
|
1051
|
+
it("should add StyleSheet import only when className is used", () => {
|
|
1052
|
+
const input = `
|
|
1053
|
+
import { View } from 'react-native';
|
|
1054
|
+
|
|
1055
|
+
function MyComponent() {
|
|
1056
|
+
return <View className="m-4 p-2" />;
|
|
1057
|
+
}
|
|
1058
|
+
`;
|
|
1059
|
+
|
|
1060
|
+
const output = transform(input, undefined, true);
|
|
1061
|
+
|
|
1062
|
+
// Should have StyleSheet import (both single and double quotes)
|
|
1063
|
+
expect(output).toMatch(/import.*StyleSheet.*from ['"]react-native['"]|require\(['"]react-native['"]\)/);
|
|
1064
|
+
|
|
1065
|
+
// Should have _twStyles definition
|
|
1066
|
+
expect(output).toContain("_twStyles");
|
|
1067
|
+
expect(output).toContain("StyleSheet.create");
|
|
1068
|
+
});
|
|
1069
|
+
|
|
1070
|
+
it("should add Platform import only when platform modifiers are used", () => {
|
|
1071
|
+
const input = `
|
|
1072
|
+
import { View } from 'react-native';
|
|
1073
|
+
|
|
1074
|
+
function MyComponent() {
|
|
1075
|
+
return <View className="ios:m-4 android:m-2" />;
|
|
1076
|
+
}
|
|
1077
|
+
`;
|
|
1078
|
+
|
|
1079
|
+
const output = transform(input, undefined, true);
|
|
1080
|
+
|
|
1081
|
+
// Should have Platform import
|
|
1082
|
+
expect(output).toContain("Platform");
|
|
1083
|
+
|
|
1084
|
+
// Should have StyleSheet import too
|
|
1085
|
+
expect(output).toContain("StyleSheet");
|
|
1086
|
+
|
|
1087
|
+
// Should use Platform.select
|
|
1088
|
+
expect(output).toContain("Platform.select");
|
|
1089
|
+
});
|
|
1090
|
+
|
|
1091
|
+
it("should not add Platform import without platform modifiers", () => {
|
|
1092
|
+
const input = `
|
|
1093
|
+
import { View } from 'react-native';
|
|
1094
|
+
|
|
1095
|
+
function MyComponent() {
|
|
1096
|
+
return <View className="m-4 p-2" />;
|
|
1097
|
+
}
|
|
1098
|
+
`;
|
|
1099
|
+
|
|
1100
|
+
const output = transform(input, undefined, true);
|
|
1101
|
+
|
|
1102
|
+
// Should not have Platform import
|
|
1103
|
+
const platformCount = (output.match(/Platform/g) ?? []).length;
|
|
1104
|
+
expect(platformCount).toBe(0);
|
|
1105
|
+
|
|
1106
|
+
// Should still have StyleSheet
|
|
1107
|
+
expect(output).toContain("StyleSheet");
|
|
1108
|
+
});
|
|
1109
|
+
});
|
|
1110
|
+
|
|
1111
|
+
describe("Babel plugin - scheme: modifier", () => {
|
|
1112
|
+
it.skip("should expand scheme: modifier into dark: and light: modifiers", () => {
|
|
1113
|
+
// Note: This test requires tailwind.config.js with custom colors defined
|
|
1114
|
+
// The scheme: modifier expands to dark: and light: modifiers which require
|
|
1115
|
+
// the color variants to exist in customColors (e.g., systemGray-dark, systemGray-light)
|
|
1116
|
+
//
|
|
1117
|
+
// Integration test should be done in a real project with tailwind.config.js
|
|
1118
|
+
const input = `
|
|
1119
|
+
import { View } from 'react-native';
|
|
1120
|
+
|
|
1121
|
+
function MyComponent() {
|
|
1122
|
+
return <View className="scheme:text-systemGray" />;
|
|
1123
|
+
}
|
|
1124
|
+
`;
|
|
1125
|
+
|
|
1126
|
+
const output = transform(input, undefined, true);
|
|
1127
|
+
|
|
1128
|
+
// Should generate both dark and light variants
|
|
1129
|
+
expect(output).toContain("_dark_text_systemGray_dark");
|
|
1130
|
+
expect(output).toContain("_light_text_systemGray_light");
|
|
1131
|
+
|
|
1132
|
+
// Should inject useColorScheme hook
|
|
1133
|
+
expect(output).toContain("useColorScheme");
|
|
1134
|
+
expect(output).toContain("_twColorScheme");
|
|
1135
|
+
|
|
1136
|
+
// Should have conditional expressions
|
|
1137
|
+
expect(output).toContain("_twColorScheme === 'dark'");
|
|
1138
|
+
expect(output).toContain("_twColorScheme === 'light'");
|
|
1139
|
+
});
|
|
1140
|
+
});
|