@mgcrea/react-native-tailwind 0.12.1 → 0.14.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.
Files changed (104) hide show
  1. package/README.md +45 -2031
  2. package/dist/babel/index.cjs +1726 -1094
  3. package/dist/babel/plugin/componentScope.d.ts +26 -0
  4. package/dist/babel/plugin/componentScope.ts +87 -0
  5. package/dist/babel/plugin/state.d.ts +123 -0
  6. package/dist/babel/plugin/state.ts +185 -0
  7. package/dist/babel/plugin/visitors/className.d.ts +11 -0
  8. package/{src/babel/plugin.test.ts → dist/babel/plugin/visitors/className.test.ts} +285 -572
  9. package/dist/babel/plugin/visitors/className.ts +652 -0
  10. package/dist/babel/plugin/visitors/className.windowDimensions.test.ts +406 -0
  11. package/dist/babel/plugin/visitors/imports.d.ts +11 -0
  12. package/dist/babel/plugin/visitors/imports.test.ts +88 -0
  13. package/dist/babel/plugin/visitors/imports.ts +116 -0
  14. package/dist/babel/plugin/visitors/program.d.ts +15 -0
  15. package/dist/babel/plugin/visitors/program.test.ts +325 -0
  16. package/dist/babel/plugin/visitors/program.ts +116 -0
  17. package/dist/babel/plugin/visitors/tw.d.ts +16 -0
  18. package/dist/babel/plugin/visitors/tw.test.ts +771 -0
  19. package/dist/babel/plugin/visitors/tw.ts +148 -0
  20. package/dist/babel/plugin.d.ts +3 -96
  21. package/dist/babel/plugin.test.ts +470 -0
  22. package/dist/babel/plugin.ts +28 -963
  23. package/dist/babel/utils/colorSchemeModifierProcessing.ts +11 -0
  24. package/dist/babel/utils/componentSupport.test.ts +20 -7
  25. package/dist/babel/utils/componentSupport.ts +2 -0
  26. package/dist/babel/utils/directionalModifierProcessing.d.ts +34 -0
  27. package/dist/babel/utils/directionalModifierProcessing.ts +99 -0
  28. package/dist/babel/utils/modifierProcessing.ts +21 -0
  29. package/dist/babel/utils/platformModifierProcessing.ts +11 -0
  30. package/dist/babel/utils/styleInjection.d.ts +31 -0
  31. package/dist/babel/utils/styleInjection.ts +253 -7
  32. package/dist/babel/utils/twProcessing.d.ts +2 -0
  33. package/dist/babel/utils/twProcessing.ts +103 -3
  34. package/dist/babel/utils/windowDimensionsProcessing.d.ts +56 -0
  35. package/dist/babel/utils/windowDimensionsProcessing.ts +121 -0
  36. package/dist/components/TouchableOpacity.d.ts +35 -0
  37. package/dist/components/TouchableOpacity.js +1 -0
  38. package/dist/components/index.d.ts +3 -0
  39. package/dist/components/index.js +1 -0
  40. package/dist/config/markers.d.ts +5 -0
  41. package/dist/config/markers.js +1 -0
  42. package/dist/index.d.ts +2 -5
  43. package/dist/index.js +1 -1
  44. package/dist/parser/borders.d.ts +3 -1
  45. package/dist/parser/borders.js +1 -1
  46. package/dist/parser/borders.test.js +1 -1
  47. package/dist/parser/colors.js +1 -1
  48. package/dist/parser/colors.test.js +1 -1
  49. package/dist/parser/index.d.ts +2 -2
  50. package/dist/parser/index.js +1 -1
  51. package/dist/parser/layout.js +1 -1
  52. package/dist/parser/layout.test.js +1 -1
  53. package/dist/parser/modifiers.d.ts +32 -2
  54. package/dist/parser/modifiers.js +1 -1
  55. package/dist/parser/modifiers.test.js +1 -1
  56. package/dist/parser/sizing.js +1 -1
  57. package/dist/parser/spacing.d.ts +1 -1
  58. package/dist/parser/spacing.js +1 -1
  59. package/dist/parser/spacing.test.js +1 -1
  60. package/dist/parser/typography.test.js +1 -1
  61. package/dist/runtime.cjs +1 -1
  62. package/dist/runtime.cjs.map +4 -4
  63. package/dist/runtime.js +1 -1
  64. package/dist/runtime.js.map +4 -4
  65. package/package.json +6 -6
  66. package/src/babel/plugin/componentScope.ts +87 -0
  67. package/src/babel/plugin/state.ts +185 -0
  68. package/src/babel/plugin/visitors/className.test.ts +1625 -0
  69. package/src/babel/plugin/visitors/className.ts +652 -0
  70. package/src/babel/plugin/visitors/className.windowDimensions.test.ts +406 -0
  71. package/src/babel/plugin/visitors/imports.test.ts +88 -0
  72. package/src/babel/plugin/visitors/imports.ts +116 -0
  73. package/src/babel/plugin/visitors/program.test.ts +325 -0
  74. package/src/babel/plugin/visitors/program.ts +116 -0
  75. package/src/babel/plugin/visitors/tw.test.ts +771 -0
  76. package/src/babel/plugin/visitors/tw.ts +148 -0
  77. package/src/babel/plugin.ts +28 -963
  78. package/src/babel/utils/colorSchemeModifierProcessing.ts +11 -0
  79. package/src/babel/utils/componentSupport.test.ts +20 -7
  80. package/src/babel/utils/componentSupport.ts +2 -0
  81. package/src/babel/utils/directionalModifierProcessing.ts +99 -0
  82. package/src/babel/utils/modifierProcessing.ts +21 -0
  83. package/src/babel/utils/platformModifierProcessing.ts +11 -0
  84. package/src/babel/utils/styleInjection.ts +253 -7
  85. package/src/babel/utils/twProcessing.ts +103 -3
  86. package/src/babel/utils/windowDimensionsProcessing.ts +121 -0
  87. package/src/components/TouchableOpacity.tsx +71 -0
  88. package/src/components/index.ts +3 -0
  89. package/src/config/markers.ts +5 -0
  90. package/src/index.ts +4 -5
  91. package/src/parser/borders.test.ts +162 -0
  92. package/src/parser/borders.ts +67 -9
  93. package/src/parser/colors.test.ts +249 -0
  94. package/src/parser/colors.ts +38 -0
  95. package/src/parser/index.ts +4 -2
  96. package/src/parser/layout.test.ts +74 -0
  97. package/src/parser/layout.ts +94 -0
  98. package/src/parser/modifiers.test.ts +206 -0
  99. package/src/parser/modifiers.ts +62 -3
  100. package/src/parser/sizing.ts +11 -0
  101. package/src/parser/spacing.test.ts +66 -0
  102. package/src/parser/spacing.ts +15 -5
  103. package/src/parser/typography.test.ts +8 -0
  104. package/src/parser/typography.ts +4 -0
@@ -0,0 +1,148 @@
1
+ /**
2
+ * tw and twStyle visitors - handles compile-time tw tagged templates and twStyle calls
3
+ */
4
+
5
+ import type { NodePath } from "@babel/core";
6
+ import type * as BabelTypes from "@babel/types";
7
+ import { parseClassName, splitModifierClasses } from "../../../parser/index.js";
8
+ import { generateStyleKey } from "../../../utils/styleKey.js";
9
+ import { processTwCall } from "../../utils/twProcessing.js";
10
+ import { findComponentScope } from "../componentScope.js";
11
+ import type { PluginState } from "../state.js";
12
+
13
+ /**
14
+ * TaggedTemplateExpression visitor
15
+ * Handles tw`...` tagged template expressions
16
+ */
17
+ export function taggedTemplateVisitor(
18
+ path: NodePath<BabelTypes.TaggedTemplateExpression>,
19
+ state: PluginState,
20
+ t: typeof BabelTypes,
21
+ ): void {
22
+ const node = path.node;
23
+
24
+ // Check if the tag is a tracked tw import
25
+ if (!t.isIdentifier(node.tag)) {
26
+ return;
27
+ }
28
+
29
+ const tagName = node.tag.name;
30
+ if (!state.twImportNames.has(tagName)) {
31
+ return;
32
+ }
33
+
34
+ // Extract static className from template literal
35
+ const quasi = node.quasi;
36
+ if (!t.isTemplateLiteral(quasi)) {
37
+ return;
38
+ }
39
+
40
+ // Only support static strings (no interpolations)
41
+ if (quasi.expressions.length > 0) {
42
+ if (process.env.NODE_ENV !== "production") {
43
+ console.warn(
44
+ `[react-native-tailwind] Dynamic tw\`...\` with interpolations is not supported at ${state.file.opts.filename ?? "unknown"}. ` +
45
+ `Use style prop for dynamic values.`,
46
+ );
47
+ }
48
+ return;
49
+ }
50
+
51
+ // Get the static className string
52
+ const className = quasi.quasis[0]?.value.cooked?.trim() ?? "";
53
+ if (!className) {
54
+ // Replace with empty object
55
+ path.replaceWith(t.objectExpression([t.objectProperty(t.identifier("style"), t.objectExpression([]))]));
56
+ // Mark as successfully transformed (even if empty)
57
+ state.hasTwImport = true;
58
+ return;
59
+ }
60
+
61
+ state.hasClassNames = true;
62
+
63
+ // Process the className with modifiers
64
+ processTwCall(
65
+ className,
66
+ path,
67
+ state,
68
+ parseClassName,
69
+ generateStyleKey,
70
+ splitModifierClasses,
71
+ findComponentScope,
72
+ t,
73
+ );
74
+
75
+ // Mark as successfully transformed
76
+ state.hasTwImport = true;
77
+ }
78
+
79
+ /**
80
+ * CallExpression visitor
81
+ * Handles twStyle('...') call expressions
82
+ */
83
+ export function callExpressionVisitor(
84
+ path: NodePath<BabelTypes.CallExpression>,
85
+ state: PluginState,
86
+ t: typeof BabelTypes,
87
+ ): void {
88
+ const node = path.node;
89
+
90
+ // Check if the callee is a tracked twStyle import
91
+ if (!t.isIdentifier(node.callee)) {
92
+ return;
93
+ }
94
+
95
+ const calleeName = node.callee.name;
96
+ if (!state.twImportNames.has(calleeName)) {
97
+ return;
98
+ }
99
+
100
+ // Must have exactly one argument
101
+ if (node.arguments.length !== 1) {
102
+ if (process.env.NODE_ENV !== "production") {
103
+ console.warn(
104
+ `[react-native-tailwind] twStyle() expects exactly one argument at ${state.file.opts.filename ?? "unknown"}`,
105
+ );
106
+ }
107
+ return;
108
+ }
109
+
110
+ const arg = node.arguments[0];
111
+
112
+ // Only support static string literals
113
+ if (!t.isStringLiteral(arg)) {
114
+ if (process.env.NODE_ENV !== "production") {
115
+ console.warn(
116
+ `[react-native-tailwind] twStyle() only supports static string literals at ${state.file.opts.filename ?? "unknown"}. ` +
117
+ `Use style prop for dynamic values.`,
118
+ );
119
+ }
120
+ return;
121
+ }
122
+
123
+ const className = arg.value.trim();
124
+ if (!className) {
125
+ // Replace with undefined
126
+ path.replaceWith(t.identifier("undefined"));
127
+ // Mark as successfully transformed (even if empty)
128
+ state.hasTwImport = true;
129
+ return;
130
+ }
131
+
132
+ state.hasClassNames = true;
133
+
134
+ // Process the className with modifiers
135
+ processTwCall(
136
+ className,
137
+ path,
138
+ state,
139
+ parseClassName,
140
+ generateStyleKey,
141
+ splitModifierClasses,
142
+ findComponentScope,
143
+ t,
144
+ );
145
+
146
+ // Mark as successfully transformed
147
+ state.hasTwImport = true;
148
+ }
@@ -2,103 +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 { NodePath, PluginObj, PluginPass } from "@babel/core";
5
+ import type { PluginObj } from "@babel/core";
6
6
  import * as BabelTypes from "@babel/types";
7
- import type { StyleObject } from "../types/core.js";
8
- import type { CustomTheme } from "./config-loader.js";
9
- import type { SchemeModifierConfig } from "../types/config.js";
10
- /**
11
- * Plugin options
12
- */
13
- export type PluginOptions = {
14
- /**
15
- * List of JSX attribute names to transform (in addition to or instead of 'className')
16
- * Supports exact matches and glob patterns:
17
- * - Exact: 'className', 'containerClassName'
18
- * - Glob: '*ClassName' (matches any attribute ending in 'ClassName')
19
- *
20
- * @default ['className', 'contentContainerClassName', 'columnWrapperClassName', 'ListHeaderComponentClassName', 'ListFooterComponentClassName']
21
- */
22
- attributes?: string[];
23
- /**
24
- * Custom identifier name for the generated StyleSheet constant
25
- *
26
- * @default '_twStyles'
27
- */
28
- stylesIdentifier?: string;
29
- /**
30
- * Configuration for the scheme: modifier that expands to both dark: and light: modifiers
31
- *
32
- * @example
33
- * {
34
- * darkSuffix: '-dark', // scheme:bg-primary -> dark:bg-primary-dark
35
- * lightSuffix: '-light' // scheme:bg-primary -> light:bg-primary-light
36
- * }
37
- *
38
- * @default { darkSuffix: '-dark', lightSuffix: '-light' }
39
- */
40
- schemeModifier?: {
41
- darkSuffix?: string;
42
- lightSuffix?: string;
43
- };
44
- /**
45
- * Configuration for color scheme hook import (dark:/light: modifiers)
46
- *
47
- * Allows using custom color scheme hooks from theme providers instead of
48
- * React Native's built-in useColorScheme.
49
- *
50
- * @example
51
- * // Use custom hook from theme provider
52
- * {
53
- * importFrom: '@/hooks/useColorScheme',
54
- * importName: 'useColorScheme'
55
- * }
56
- *
57
- * @example
58
- * // Use React Navigation theme
59
- * {
60
- * importFrom: '@react-navigation/native',
61
- * importName: 'useTheme' // You'd wrap this to return ColorSchemeName
62
- * }
63
- *
64
- * @default { importFrom: 'react-native', importName: 'useColorScheme' }
65
- */
66
- colorScheme?: {
67
- /**
68
- * Module to import the color scheme hook from
69
- * @default 'react-native'
70
- */
71
- importFrom?: string;
72
- /**
73
- * Name of the hook to import
74
- * @default 'useColorScheme'
75
- */
76
- importName?: string;
77
- };
78
- };
79
- type PluginState = PluginPass & {
80
- styleRegistry: Map<string, StyleObject>;
81
- hasClassNames: boolean;
82
- hasStyleSheetImport: boolean;
83
- hasPlatformImport: boolean;
84
- needsPlatformImport: boolean;
85
- hasColorSchemeImport: boolean;
86
- needsColorSchemeImport: boolean;
87
- colorSchemeVariableName: string;
88
- colorSchemeImportSource: string;
89
- colorSchemeHookName: string;
90
- colorSchemeLocalIdentifier?: string;
91
- customTheme: CustomTheme;
92
- schemeModifierConfig: SchemeModifierConfig;
93
- supportedAttributes: Set<string>;
94
- attributePatterns: RegExp[];
95
- stylesIdentifier: string;
96
- twImportNames: Set<string>;
97
- hasTwImport: boolean;
98
- reactNativeImportPath?: NodePath<BabelTypes.ImportDeclaration>;
99
- functionComponentsNeedingColorScheme: Set<NodePath<BabelTypes.Function>>;
100
- };
7
+ import type { PluginOptions, PluginState } from "./plugin/state.js";
8
+ export type { PluginOptions };
101
9
  export default function reactNativeTailwindBabelPlugin({ types: t }: {
102
10
  types: typeof BabelTypes;
103
11
  }, options?: PluginOptions): PluginObj<PluginState>;
104
- export {};