@mgcrea/react-native-tailwind 0.7.0 → 0.8.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 +2 -1
- package/dist/babel/index.cjs +333 -195
- package/dist/babel/index.d.ts +4 -40
- package/dist/babel/index.test.ts +214 -1
- package/dist/babel/index.ts +4 -1169
- package/dist/babel/plugin.d.ts +42 -0
- package/{src/babel/index.test.ts → dist/babel/plugin.test.ts} +216 -2
- package/dist/babel/plugin.ts +491 -0
- package/dist/babel/utils/attributeMatchers.d.ts +23 -0
- package/dist/babel/utils/attributeMatchers.ts +71 -0
- package/dist/babel/utils/componentSupport.d.ts +18 -0
- package/dist/babel/utils/componentSupport.ts +68 -0
- package/dist/babel/utils/dynamicProcessing.d.ts +32 -0
- package/dist/babel/utils/dynamicProcessing.ts +223 -0
- package/dist/babel/utils/modifierProcessing.d.ts +26 -0
- package/dist/babel/utils/modifierProcessing.ts +118 -0
- package/dist/babel/utils/styleInjection.d.ts +15 -0
- package/dist/babel/utils/styleInjection.ts +80 -0
- package/dist/babel/utils/styleTransforms.d.ts +39 -0
- package/dist/babel/utils/styleTransforms.test.ts +349 -0
- package/dist/babel/utils/styleTransforms.ts +258 -0
- package/dist/babel/utils/twProcessing.d.ts +28 -0
- package/dist/babel/utils/twProcessing.ts +124 -0
- package/dist/components/TextInput.d.ts +171 -14
- package/dist/config/tailwind.d.ts +302 -0
- package/dist/config/tailwind.js +1 -0
- package/dist/index.d.ts +5 -4
- package/dist/index.js +1 -1
- package/dist/parser/colors.js +1 -1
- package/dist/parser/index.d.ts +1 -0
- package/dist/parser/index.js +1 -1
- package/dist/parser/modifiers.d.ts +2 -2
- package/dist/parser/modifiers.js +1 -1
- package/dist/parser/placeholder.d.ts +36 -0
- package/dist/parser/placeholder.js +1 -0
- package/dist/parser/placeholder.test.js +1 -0
- package/dist/parser/typography.d.ts +1 -0
- 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 +4 -4
- package/dist/runtime.d.ts +1 -14
- package/dist/runtime.js +1 -1
- package/dist/runtime.js.map +4 -4
- package/dist/stubs/tw.d.ts +1 -14
- package/dist/types/core.d.ts +40 -0
- package/dist/types/core.js +0 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.js +1 -0
- package/dist/types/runtime.d.ts +15 -0
- package/dist/types/runtime.js +1 -0
- package/dist/types/util.d.ts +3 -0
- package/dist/types/util.js +0 -0
- package/package.json +1 -1
- package/src/babel/index.ts +4 -1169
- package/src/babel/plugin.test.ts +482 -0
- package/src/babel/plugin.ts +491 -0
- package/src/babel/utils/attributeMatchers.ts +71 -0
- package/src/babel/utils/componentSupport.ts +68 -0
- package/src/babel/utils/dynamicProcessing.ts +223 -0
- package/src/babel/utils/modifierProcessing.ts +118 -0
- package/src/babel/utils/styleInjection.ts +80 -0
- package/src/babel/utils/styleTransforms.test.ts +349 -0
- package/src/babel/utils/styleTransforms.ts +258 -0
- package/src/babel/utils/twProcessing.ts +124 -0
- package/src/components/TextInput.tsx +17 -14
- package/src/config/{palettes.ts → tailwind.ts} +2 -2
- package/src/index.ts +6 -3
- package/src/parser/colors.ts +2 -2
- package/src/parser/index.ts +1 -0
- package/src/parser/modifiers.ts +10 -4
- package/src/parser/placeholder.test.ts +105 -0
- package/src/parser/placeholder.ts +78 -0
- package/src/parser/typography.test.ts +11 -0
- package/src/parser/typography.ts +20 -2
- package/src/runtime.ts +1 -16
- package/src/stubs/tw.ts +1 -16
- package/src/{types.ts → types/core.ts} +0 -4
- package/src/types/index.ts +2 -0
- package/src/types/runtime.ts +17 -0
- package/src/types/util.ts +1 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility functions for processing dynamic className expressions
|
|
3
|
+
*/
|
|
4
|
+
import type * as BabelTypes from "@babel/types";
|
|
5
|
+
import type { StyleObject } from "../../types/core.js";
|
|
6
|
+
/**
|
|
7
|
+
* Plugin state interface (subset needed for dynamic processing)
|
|
8
|
+
*/
|
|
9
|
+
export interface DynamicProcessingState {
|
|
10
|
+
styleRegistry: Map<string, StyleObject>;
|
|
11
|
+
customColors: Record<string, string>;
|
|
12
|
+
stylesIdentifier: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Result of processing a dynamic expression
|
|
16
|
+
*/
|
|
17
|
+
export type DynamicExpressionResult = {
|
|
18
|
+
expression: BabelTypes.Expression;
|
|
19
|
+
staticParts?: string[];
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Process a dynamic className expression
|
|
23
|
+
* Extracts static strings and transforms the expression to use pre-compiled styles
|
|
24
|
+
*/
|
|
25
|
+
export declare function processDynamicExpression(expression: BabelTypes.Expression, state: DynamicProcessingState, parseClassName: (className: string, customColors: Record<string, string>) => StyleObject, generateStyleKey: (className: string) => string, t: typeof BabelTypes): {
|
|
26
|
+
expression: BabelTypes.ArrayExpression | BabelTypes.MemberExpression;
|
|
27
|
+
staticParts: string[] | undefined;
|
|
28
|
+
} | {
|
|
29
|
+
expression: BabelTypes.ConditionalExpression;
|
|
30
|
+
} | {
|
|
31
|
+
expression: BabelTypes.LogicalExpression;
|
|
32
|
+
} | null;
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility functions for processing dynamic className expressions
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type * as BabelTypes from "@babel/types";
|
|
6
|
+
import type { StyleObject } from "../../types/core.js";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Plugin state interface (subset needed for dynamic processing)
|
|
10
|
+
*/
|
|
11
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
|
|
12
|
+
export interface DynamicProcessingState {
|
|
13
|
+
styleRegistry: Map<string, StyleObject>;
|
|
14
|
+
customColors: Record<string, string>;
|
|
15
|
+
stylesIdentifier: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Result of processing a dynamic expression
|
|
20
|
+
*/
|
|
21
|
+
export type DynamicExpressionResult = {
|
|
22
|
+
// The transformed expression to use in the style prop
|
|
23
|
+
expression: BabelTypes.Expression;
|
|
24
|
+
// Static parts that can be parsed at compile time (if any)
|
|
25
|
+
staticParts?: string[];
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Process a dynamic className expression
|
|
30
|
+
* Extracts static strings and transforms the expression to use pre-compiled styles
|
|
31
|
+
*/
|
|
32
|
+
export function processDynamicExpression(
|
|
33
|
+
expression: BabelTypes.Expression,
|
|
34
|
+
state: DynamicProcessingState,
|
|
35
|
+
parseClassName: (className: string, customColors: Record<string, string>) => StyleObject,
|
|
36
|
+
generateStyleKey: (className: string) => string,
|
|
37
|
+
t: typeof BabelTypes,
|
|
38
|
+
) {
|
|
39
|
+
// Handle template literals: `m-4 ${condition ? "p-4" : "p-2"}`
|
|
40
|
+
if (t.isTemplateLiteral(expression)) {
|
|
41
|
+
return processTemplateLiteral(expression, state, parseClassName, generateStyleKey, t);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Handle conditional expressions: condition ? "m-4" : "p-2"
|
|
45
|
+
if (t.isConditionalExpression(expression)) {
|
|
46
|
+
return processConditionalExpression(expression, state, parseClassName, generateStyleKey, t);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Handle logical expressions: condition && "m-4"
|
|
50
|
+
if (t.isLogicalExpression(expression)) {
|
|
51
|
+
return processLogicalExpression(expression, state, parseClassName, generateStyleKey, t);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Unsupported expression type
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Process template literal: `static ${dynamic} more-static`
|
|
60
|
+
*/
|
|
61
|
+
function processTemplateLiteral(
|
|
62
|
+
node: BabelTypes.TemplateLiteral,
|
|
63
|
+
state: DynamicProcessingState,
|
|
64
|
+
parseClassName: (className: string, customColors: Record<string, string>) => StyleObject,
|
|
65
|
+
generateStyleKey: (className: string) => string,
|
|
66
|
+
t: typeof BabelTypes,
|
|
67
|
+
) {
|
|
68
|
+
const parts: BabelTypes.MemberExpression[] = [];
|
|
69
|
+
const staticParts: string[] = [];
|
|
70
|
+
|
|
71
|
+
// Process quasis (static parts) and expressions (dynamic parts)
|
|
72
|
+
for (let i = 0; i < node.quasis.length; i++) {
|
|
73
|
+
const quasi = node.quasis[i];
|
|
74
|
+
const staticText = quasi.value.cooked?.trim();
|
|
75
|
+
|
|
76
|
+
// Add static part if not empty
|
|
77
|
+
if (staticText) {
|
|
78
|
+
// Parse static classes and add to registry
|
|
79
|
+
const classes = staticText.split(/\s+/).filter(Boolean);
|
|
80
|
+
for (const cls of classes) {
|
|
81
|
+
const styleObject = parseClassName(cls, state.customColors);
|
|
82
|
+
const styleKey = generateStyleKey(cls);
|
|
83
|
+
state.styleRegistry.set(styleKey, styleObject);
|
|
84
|
+
staticParts.push(cls);
|
|
85
|
+
|
|
86
|
+
// Add to parts array
|
|
87
|
+
parts.push(t.memberExpression(t.identifier(state.stylesIdentifier), t.identifier(styleKey)));
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Add dynamic expression if exists
|
|
92
|
+
if (i < node.expressions.length) {
|
|
93
|
+
const expr = node.expressions[i];
|
|
94
|
+
|
|
95
|
+
// Recursively process nested dynamic expressions
|
|
96
|
+
const result = processDynamicExpression(
|
|
97
|
+
expr as BabelTypes.Expression,
|
|
98
|
+
state,
|
|
99
|
+
parseClassName,
|
|
100
|
+
generateStyleKey,
|
|
101
|
+
t,
|
|
102
|
+
);
|
|
103
|
+
if (result) {
|
|
104
|
+
parts.push(result.expression as BabelTypes.MemberExpression);
|
|
105
|
+
} else {
|
|
106
|
+
// For unsupported expressions, keep them as-is
|
|
107
|
+
// This won't work at runtime but maintains the structure
|
|
108
|
+
parts.push(expr as BabelTypes.MemberExpression);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (parts.length === 0) {
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// If single part, return it directly; otherwise return array
|
|
118
|
+
const expression = parts.length === 1 ? parts[0] : t.arrayExpression(parts);
|
|
119
|
+
|
|
120
|
+
return {
|
|
121
|
+
expression,
|
|
122
|
+
staticParts: staticParts.length > 0 ? staticParts : undefined,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Process conditional expression: condition ? "class-a" : "class-b"
|
|
128
|
+
*/
|
|
129
|
+
function processConditionalExpression(
|
|
130
|
+
node: BabelTypes.ConditionalExpression,
|
|
131
|
+
state: DynamicProcessingState,
|
|
132
|
+
parseClassName: (className: string, customColors: Record<string, string>) => StyleObject,
|
|
133
|
+
generateStyleKey: (className: string) => string,
|
|
134
|
+
t: typeof BabelTypes,
|
|
135
|
+
) {
|
|
136
|
+
const consequent = processStringOrExpression(node.consequent, state, parseClassName, generateStyleKey, t);
|
|
137
|
+
const alternate = processStringOrExpression(node.alternate, state, parseClassName, generateStyleKey, t);
|
|
138
|
+
|
|
139
|
+
if (!consequent && !alternate) {
|
|
140
|
+
return null;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Build conditional: condition ? consequentStyle : alternateStyle
|
|
144
|
+
const expression = t.conditionalExpression(
|
|
145
|
+
node.test,
|
|
146
|
+
(consequent as BabelTypes.Expression) ?? t.nullLiteral(),
|
|
147
|
+
(alternate as BabelTypes.Expression) ?? t.nullLiteral(),
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
return { expression };
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Process logical expression: condition && "class-a"
|
|
155
|
+
*/
|
|
156
|
+
function processLogicalExpression(
|
|
157
|
+
node: BabelTypes.LogicalExpression,
|
|
158
|
+
state: DynamicProcessingState,
|
|
159
|
+
parseClassName: (className: string, customColors: Record<string, string>) => StyleObject,
|
|
160
|
+
generateStyleKey: (className: string) => string,
|
|
161
|
+
t: typeof BabelTypes,
|
|
162
|
+
) {
|
|
163
|
+
// Only handle AND (&&) expressions
|
|
164
|
+
if (node.operator !== "&&") {
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
const right = processStringOrExpression(node.right, state, parseClassName, generateStyleKey, t);
|
|
169
|
+
|
|
170
|
+
if (!right) {
|
|
171
|
+
return null;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Build logical: condition && style
|
|
175
|
+
const expression = t.logicalExpression("&&", node.left, right as BabelTypes.Expression);
|
|
176
|
+
|
|
177
|
+
return { expression };
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Process a node that might be a string literal or another expression
|
|
182
|
+
*/
|
|
183
|
+
function processStringOrExpression(
|
|
184
|
+
node: BabelTypes.StringLiteral | BabelTypes.Expression,
|
|
185
|
+
state: DynamicProcessingState,
|
|
186
|
+
parseClassName: (className: string, customColors: Record<string, string>) => StyleObject,
|
|
187
|
+
generateStyleKey: (className: string) => string,
|
|
188
|
+
t: typeof BabelTypes,
|
|
189
|
+
) {
|
|
190
|
+
// Handle string literals
|
|
191
|
+
if (t.isStringLiteral(node)) {
|
|
192
|
+
const className = node.value.trim();
|
|
193
|
+
if (!className) {
|
|
194
|
+
return null;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// Parse and register styles
|
|
198
|
+
const styleObject = parseClassName(className, state.customColors);
|
|
199
|
+
const styleKey = generateStyleKey(className);
|
|
200
|
+
state.styleRegistry.set(styleKey, styleObject);
|
|
201
|
+
|
|
202
|
+
return t.memberExpression(t.identifier(state.stylesIdentifier), t.identifier(styleKey));
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// Handle nested expressions recursively
|
|
206
|
+
if (t.isConditionalExpression(node)) {
|
|
207
|
+
const result = processConditionalExpression(node, state, parseClassName, generateStyleKey, t);
|
|
208
|
+
return result?.expression ?? null;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
if (t.isLogicalExpression(node)) {
|
|
212
|
+
const result = processLogicalExpression(node, state, parseClassName, generateStyleKey, t);
|
|
213
|
+
return result?.expression ?? null;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
if (t.isTemplateLiteral(node)) {
|
|
217
|
+
const result = processTemplateLiteral(node, state, parseClassName, generateStyleKey, t);
|
|
218
|
+
return result?.expression ?? null;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// Unsupported - return null
|
|
222
|
+
return null;
|
|
223
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility functions for processing class modifiers (active:, hover:, focus:, etc.)
|
|
3
|
+
*/
|
|
4
|
+
import type * as BabelTypes from "@babel/types";
|
|
5
|
+
import type { ModifierType, ParsedModifier } from "../../parser/index.js";
|
|
6
|
+
import type { StyleObject } from "../../types/core.js";
|
|
7
|
+
/**
|
|
8
|
+
* Plugin state interface (subset needed for modifier processing)
|
|
9
|
+
*/
|
|
10
|
+
export interface ModifierProcessingState {
|
|
11
|
+
styleRegistry: Map<string, StyleObject>;
|
|
12
|
+
customColors: Record<string, string>;
|
|
13
|
+
stylesIdentifier: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Process a static className string that contains modifiers
|
|
17
|
+
* Returns a style function expression for Pressable components
|
|
18
|
+
*/
|
|
19
|
+
export declare function processStaticClassNameWithModifiers(className: string, state: ModifierProcessingState, parseClassName: (className: string, customColors: Record<string, string>) => StyleObject, generateStyleKey: (className: string) => string, splitModifierClasses: (className: string) => {
|
|
20
|
+
baseClasses: string[];
|
|
21
|
+
modifierClasses: ParsedModifier[];
|
|
22
|
+
}, t: typeof BabelTypes): BabelTypes.Expression;
|
|
23
|
+
/**
|
|
24
|
+
* Create a style function for Pressable: ({ pressed }) => styleExpression
|
|
25
|
+
*/
|
|
26
|
+
export declare function createStyleFunction(styleExpression: BabelTypes.Expression, modifierTypes: ModifierType[], t: typeof BabelTypes): BabelTypes.ArrowFunctionExpression;
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility functions for processing class modifiers (active:, hover:, focus:, etc.)
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type * as BabelTypes from "@babel/types";
|
|
6
|
+
import type { ModifierType, ParsedModifier } from "../../parser/index.js";
|
|
7
|
+
import type { StyleObject } from "../../types/core.js";
|
|
8
|
+
import { getStatePropertyForModifier } from "./componentSupport.js";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Plugin state interface (subset needed for modifier processing)
|
|
12
|
+
*/
|
|
13
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
|
|
14
|
+
export interface ModifierProcessingState {
|
|
15
|
+
styleRegistry: Map<string, StyleObject>;
|
|
16
|
+
customColors: Record<string, string>;
|
|
17
|
+
stylesIdentifier: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Process a static className string that contains modifiers
|
|
22
|
+
* Returns a style function expression for Pressable components
|
|
23
|
+
*/
|
|
24
|
+
export function processStaticClassNameWithModifiers(
|
|
25
|
+
className: string,
|
|
26
|
+
state: ModifierProcessingState,
|
|
27
|
+
parseClassName: (className: string, customColors: Record<string, string>) => StyleObject,
|
|
28
|
+
generateStyleKey: (className: string) => string,
|
|
29
|
+
splitModifierClasses: (className: string) => { baseClasses: string[]; modifierClasses: ParsedModifier[] },
|
|
30
|
+
t: typeof BabelTypes,
|
|
31
|
+
) {
|
|
32
|
+
const { baseClasses, modifierClasses } = splitModifierClasses(className);
|
|
33
|
+
|
|
34
|
+
// Parse and register base classes
|
|
35
|
+
let baseStyleExpression: BabelTypes.Node | null = null;
|
|
36
|
+
if (baseClasses.length > 0) {
|
|
37
|
+
const baseClassName = baseClasses.join(" ");
|
|
38
|
+
const baseStyleObject = parseClassName(baseClassName, state.customColors);
|
|
39
|
+
const baseStyleKey = generateStyleKey(baseClassName);
|
|
40
|
+
state.styleRegistry.set(baseStyleKey, baseStyleObject);
|
|
41
|
+
baseStyleExpression = t.memberExpression(t.identifier(state.stylesIdentifier), t.identifier(baseStyleKey));
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Parse and register modifier classes
|
|
45
|
+
// Group by modifier type for better organization
|
|
46
|
+
const modifiersByType = new Map<ModifierType, ParsedModifier[]>();
|
|
47
|
+
for (const mod of modifierClasses) {
|
|
48
|
+
if (!modifiersByType.has(mod.modifier)) {
|
|
49
|
+
modifiersByType.set(mod.modifier, []);
|
|
50
|
+
}
|
|
51
|
+
const modGroup = modifiersByType.get(mod.modifier);
|
|
52
|
+
if (modGroup) {
|
|
53
|
+
modGroup.push(mod);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Build style function: ({ pressed }) => [baseStyle, pressed && modifierStyle]
|
|
58
|
+
const styleArrayElements: BabelTypes.Expression[] = [];
|
|
59
|
+
|
|
60
|
+
// Add base style first
|
|
61
|
+
if (baseStyleExpression) {
|
|
62
|
+
styleArrayElements.push(baseStyleExpression);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Add conditional styles for each modifier type
|
|
66
|
+
for (const [modifierType, modifiers] of modifiersByType) {
|
|
67
|
+
// Parse all modifier classes together
|
|
68
|
+
const modifierClassNames = modifiers.map((m) => m.baseClass).join(" ");
|
|
69
|
+
const modifierStyleObject = parseClassName(modifierClassNames, state.customColors);
|
|
70
|
+
const modifierStyleKey = generateStyleKey(`${modifierType}_${modifierClassNames}`);
|
|
71
|
+
state.styleRegistry.set(modifierStyleKey, modifierStyleObject);
|
|
72
|
+
|
|
73
|
+
// Create conditional: pressed && styles._active_bg_blue_700
|
|
74
|
+
const stateProperty = getStatePropertyForModifier(modifierType);
|
|
75
|
+
const conditionalExpression = t.logicalExpression(
|
|
76
|
+
"&&",
|
|
77
|
+
t.identifier(stateProperty),
|
|
78
|
+
t.memberExpression(t.identifier(state.stylesIdentifier), t.identifier(modifierStyleKey)),
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
styleArrayElements.push(conditionalExpression);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// If only base style, return it directly; otherwise return array
|
|
85
|
+
if (styleArrayElements.length === 1) {
|
|
86
|
+
return styleArrayElements[0];
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return t.arrayExpression(styleArrayElements);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Create a style function for Pressable: ({ pressed }) => styleExpression
|
|
94
|
+
*/
|
|
95
|
+
export function createStyleFunction(
|
|
96
|
+
styleExpression: BabelTypes.Expression,
|
|
97
|
+
modifierTypes: ModifierType[],
|
|
98
|
+
t: typeof BabelTypes,
|
|
99
|
+
) {
|
|
100
|
+
// Build parameter object: { pressed, hovered, focused }
|
|
101
|
+
const paramProperties: BabelTypes.ObjectProperty[] = [];
|
|
102
|
+
const usedStateProps = new Set<string>();
|
|
103
|
+
|
|
104
|
+
for (const modifierType of modifierTypes) {
|
|
105
|
+
const stateProperty = getStatePropertyForModifier(modifierType);
|
|
106
|
+
if (!usedStateProps.has(stateProperty)) {
|
|
107
|
+
usedStateProps.add(stateProperty);
|
|
108
|
+
paramProperties.push(
|
|
109
|
+
t.objectProperty(t.identifier(stateProperty), t.identifier(stateProperty), false, true),
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const param = t.objectPattern(paramProperties);
|
|
115
|
+
|
|
116
|
+
// Create arrow function: ({ pressed }) => styleExpression
|
|
117
|
+
return t.arrowFunctionExpression([param], styleExpression);
|
|
118
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility functions for injecting StyleSheet imports and style definitions
|
|
3
|
+
*/
|
|
4
|
+
import type { NodePath } from "@babel/core";
|
|
5
|
+
import type * as BabelTypes from "@babel/types";
|
|
6
|
+
import type { StyleObject } from "../../types/core.js";
|
|
7
|
+
/**
|
|
8
|
+
* Add StyleSheet import to the file
|
|
9
|
+
*/
|
|
10
|
+
export declare function addStyleSheetImport(path: NodePath<BabelTypes.Program>, t: typeof BabelTypes): void;
|
|
11
|
+
/**
|
|
12
|
+
* Inject StyleSheet.create with all collected styles at the top of the file
|
|
13
|
+
* This ensures the styles object is defined before any code that references it
|
|
14
|
+
*/
|
|
15
|
+
export declare function injectStylesAtTop(path: NodePath<BabelTypes.Program>, styleRegistry: Map<string, StyleObject>, stylesIdentifier: string, t: typeof BabelTypes): void;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility functions for injecting StyleSheet imports and style definitions
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { NodePath } from "@babel/core";
|
|
6
|
+
import type * as BabelTypes from "@babel/types";
|
|
7
|
+
import type { StyleObject } from "../../types/core.js";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Add StyleSheet import to the file
|
|
11
|
+
*/
|
|
12
|
+
export function addStyleSheetImport(path: NodePath<BabelTypes.Program>, t: typeof BabelTypes): void {
|
|
13
|
+
const importDeclaration = t.importDeclaration(
|
|
14
|
+
[t.importSpecifier(t.identifier("StyleSheet"), t.identifier("StyleSheet"))],
|
|
15
|
+
t.stringLiteral("react-native"),
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
// Add import at the top of the file
|
|
19
|
+
path.unshiftContainer("body", importDeclaration);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Inject StyleSheet.create with all collected styles at the top of the file
|
|
24
|
+
* This ensures the styles object is defined before any code that references it
|
|
25
|
+
*/
|
|
26
|
+
export function injectStylesAtTop(
|
|
27
|
+
path: NodePath<BabelTypes.Program>,
|
|
28
|
+
styleRegistry: Map<string, StyleObject>,
|
|
29
|
+
stylesIdentifier: string,
|
|
30
|
+
t: typeof BabelTypes,
|
|
31
|
+
): void {
|
|
32
|
+
// Build style object properties
|
|
33
|
+
const styleProperties: BabelTypes.ObjectProperty[] = [];
|
|
34
|
+
|
|
35
|
+
for (const [key, styleObject] of styleRegistry) {
|
|
36
|
+
const properties = Object.entries(styleObject).map(([styleProp, styleValue]) => {
|
|
37
|
+
let valueNode;
|
|
38
|
+
|
|
39
|
+
if (typeof styleValue === "number") {
|
|
40
|
+
valueNode = t.numericLiteral(styleValue);
|
|
41
|
+
} else if (typeof styleValue === "string") {
|
|
42
|
+
valueNode = t.stringLiteral(styleValue);
|
|
43
|
+
} else {
|
|
44
|
+
// Fallback for other types
|
|
45
|
+
valueNode = t.valueToNode(styleValue);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return t.objectProperty(t.identifier(styleProp), valueNode);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
styleProperties.push(t.objectProperty(t.identifier(key), t.objectExpression(properties)));
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Create: const _twStyles = StyleSheet.create({ ... })
|
|
55
|
+
const styleSheet = t.variableDeclaration("const", [
|
|
56
|
+
t.variableDeclarator(
|
|
57
|
+
t.identifier(stylesIdentifier),
|
|
58
|
+
t.callExpression(t.memberExpression(t.identifier("StyleSheet"), t.identifier("create")), [
|
|
59
|
+
t.objectExpression(styleProperties),
|
|
60
|
+
]),
|
|
61
|
+
),
|
|
62
|
+
]);
|
|
63
|
+
|
|
64
|
+
// Find the index to insert after all imports
|
|
65
|
+
const body = path.node.body;
|
|
66
|
+
let insertIndex = 0;
|
|
67
|
+
|
|
68
|
+
// Find the last import statement
|
|
69
|
+
for (let i = 0; i < body.length; i++) {
|
|
70
|
+
if (t.isImportDeclaration(body[i])) {
|
|
71
|
+
insertIndex = i + 1;
|
|
72
|
+
} else {
|
|
73
|
+
// Stop at the first non-import statement
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Insert StyleSheet.create after imports
|
|
79
|
+
body.splice(insertIndex, 0, styleSheet);
|
|
80
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility functions for transforming and merging style attributes
|
|
3
|
+
*/
|
|
4
|
+
import type { NodePath } from "@babel/core";
|
|
5
|
+
import type * as BabelTypes from "@babel/types";
|
|
6
|
+
import type { DynamicExpressionResult } from "./dynamicProcessing.js";
|
|
7
|
+
/**
|
|
8
|
+
* Helper to find existing style attribute on parent JSX element
|
|
9
|
+
*/
|
|
10
|
+
export declare function findStyleAttribute(path: NodePath, targetStyleProp: string, t: typeof BabelTypes): BabelTypes.JSXAttribute | undefined;
|
|
11
|
+
/**
|
|
12
|
+
* Replace className with style attribute
|
|
13
|
+
*/
|
|
14
|
+
export declare function replaceWithStyleAttribute(classNamePath: NodePath, styleKey: string, targetStyleProp: string, stylesIdentifier: string, t: typeof BabelTypes): void;
|
|
15
|
+
/**
|
|
16
|
+
* Merge className styles with existing style prop
|
|
17
|
+
*/
|
|
18
|
+
export declare function mergeStyleAttribute(classNamePath: NodePath, styleAttribute: BabelTypes.JSXAttribute, styleKey: string, stylesIdentifier: string, t: typeof BabelTypes): void;
|
|
19
|
+
/**
|
|
20
|
+
* Replace className with dynamic style attribute
|
|
21
|
+
*/
|
|
22
|
+
export declare function replaceDynamicWithStyleAttribute(classNamePath: NodePath, result: DynamicExpressionResult, targetStyleProp: string, t: typeof BabelTypes): void;
|
|
23
|
+
/**
|
|
24
|
+
* Merge dynamic className styles with existing style prop
|
|
25
|
+
*/
|
|
26
|
+
export declare function mergeDynamicStyleAttribute(classNamePath: NodePath, styleAttribute: BabelTypes.JSXAttribute, result: DynamicExpressionResult, t: typeof BabelTypes): void;
|
|
27
|
+
/**
|
|
28
|
+
* Replace className with style function attribute (for Pressable with modifiers)
|
|
29
|
+
*/
|
|
30
|
+
export declare function replaceWithStyleFunctionAttribute(classNamePath: NodePath, styleFunctionExpression: BabelTypes.Expression, targetStyleProp: string, t: typeof BabelTypes): void;
|
|
31
|
+
/**
|
|
32
|
+
* Merge className style function with existing style prop (for Pressable with modifiers)
|
|
33
|
+
*/
|
|
34
|
+
export declare function mergeStyleFunctionAttribute(classNamePath: NodePath, styleAttribute: BabelTypes.JSXAttribute, styleFunctionExpression: BabelTypes.Expression, t: typeof BabelTypes): void;
|
|
35
|
+
/**
|
|
36
|
+
* Add or merge placeholderTextColor prop on a JSX element
|
|
37
|
+
* Handles merging with existing placeholderTextColor if present
|
|
38
|
+
*/
|
|
39
|
+
export declare function addOrMergePlaceholderTextColorProp(jsxOpeningElement: BabelTypes.JSXOpeningElement, color: string, t: typeof BabelTypes): void;
|