@mgcrea/react-native-tailwind 0.9.1 → 0.11.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 +386 -43
- package/dist/babel/config-loader.d.ts +12 -3
- package/dist/babel/config-loader.test.ts +154 -0
- package/dist/babel/config-loader.ts +41 -9
- package/dist/babel/index.cjs +592 -69
- package/dist/babel/plugin.d.ts +23 -1
- package/dist/babel/plugin.test.ts +331 -0
- package/dist/babel/plugin.ts +268 -37
- package/dist/babel/utils/colorSchemeModifierProcessing.d.ts +34 -0
- package/dist/babel/utils/colorSchemeModifierProcessing.ts +89 -0
- package/dist/babel/utils/dynamicProcessing.d.ts +34 -3
- package/dist/babel/utils/dynamicProcessing.ts +358 -39
- package/dist/babel/utils/modifierProcessing.d.ts +3 -3
- package/dist/babel/utils/modifierProcessing.ts +5 -5
- package/dist/babel/utils/platformModifierProcessing.d.ts +3 -3
- package/dist/babel/utils/platformModifierProcessing.ts +4 -4
- package/dist/babel/utils/styleInjection.d.ts +13 -0
- package/dist/babel/utils/styleInjection.ts +101 -0
- package/dist/babel/utils/styleTransforms.test.ts +56 -0
- package/dist/babel/utils/twProcessing.d.ts +5 -3
- package/dist/babel/utils/twProcessing.ts +27 -6
- package/dist/parser/index.d.ts +13 -6
- 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/typography.d.ts +3 -1
- package/dist/parser/typography.js +1 -1
- package/dist/runtime.cjs +1 -1
- package/dist/runtime.cjs.map +3 -3
- package/dist/runtime.d.ts +8 -1
- 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 +3 -2
- package/src/babel/config-loader.test.ts +154 -0
- package/src/babel/config-loader.ts +41 -9
- package/src/babel/plugin.test.ts +331 -0
- package/src/babel/plugin.ts +268 -37
- package/src/babel/utils/colorSchemeModifierProcessing.ts +89 -0
- package/src/babel/utils/dynamicProcessing.ts +358 -39
- package/src/babel/utils/modifierProcessing.ts +5 -5
- package/src/babel/utils/platformModifierProcessing.ts +4 -4
- package/src/babel/utils/styleInjection.ts +101 -0
- package/src/babel/utils/styleTransforms.test.ts +56 -0
- package/src/babel/utils/twProcessing.ts +27 -6
- package/src/parser/index.ts +28 -9
- package/src/parser/modifiers.test.ts +151 -1
- package/src/parser/modifiers.ts +139 -4
- package/src/parser/typography.ts +14 -2
- package/src/runtime.test.ts +7 -7
- package/src/runtime.ts +37 -14
- package/src/types/config.ts +7 -0
|
@@ -2,7 +2,10 @@
|
|
|
2
2
|
* Utility functions for processing dynamic className expressions
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
+
import type { NodePath } from "@babel/core";
|
|
5
6
|
import type * as BabelTypes from "@babel/types";
|
|
7
|
+
import type { CustomTheme, ParsedModifier } from "../../parser/index.js";
|
|
8
|
+
import type { SchemeModifierConfig } from "../../types/config.js";
|
|
6
9
|
import type { StyleObject } from "../../types/core.js";
|
|
7
10
|
|
|
8
11
|
/**
|
|
@@ -11,10 +14,60 @@ import type { StyleObject } from "../../types/core.js";
|
|
|
11
14
|
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
|
|
12
15
|
export interface DynamicProcessingState {
|
|
13
16
|
styleRegistry: Map<string, StyleObject>;
|
|
14
|
-
|
|
17
|
+
customTheme: CustomTheme;
|
|
18
|
+
schemeModifierConfig: SchemeModifierConfig;
|
|
15
19
|
stylesIdentifier: string;
|
|
20
|
+
needsPlatformImport: boolean;
|
|
21
|
+
needsColorSchemeImport: boolean;
|
|
22
|
+
colorSchemeVariableName: string;
|
|
23
|
+
functionComponentsNeedingColorScheme: Set<NodePath<BabelTypes.Function>>;
|
|
16
24
|
}
|
|
17
25
|
|
|
26
|
+
/**
|
|
27
|
+
* Type for the splitModifierClasses function
|
|
28
|
+
*/
|
|
29
|
+
export type SplitModifierClassesFn = (className: string) => {
|
|
30
|
+
baseClasses: string[];
|
|
31
|
+
modifierClasses: ParsedModifier[];
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Type for the processPlatformModifiers function
|
|
36
|
+
*/
|
|
37
|
+
export type ProcessPlatformModifiersFn = (
|
|
38
|
+
modifiers: ParsedModifier[],
|
|
39
|
+
state: DynamicProcessingState,
|
|
40
|
+
parseClassName: (className: string, customTheme?: CustomTheme) => StyleObject,
|
|
41
|
+
generateStyleKey: (className: string) => string,
|
|
42
|
+
t: typeof BabelTypes,
|
|
43
|
+
) => BabelTypes.Expression;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Type for the processColorSchemeModifiers function
|
|
47
|
+
*/
|
|
48
|
+
export type ProcessColorSchemeModifiersFn = (
|
|
49
|
+
modifiers: ParsedModifier[],
|
|
50
|
+
state: DynamicProcessingState,
|
|
51
|
+
parseClassName: (className: string, customTheme?: CustomTheme) => StyleObject,
|
|
52
|
+
generateStyleKey: (className: string) => string,
|
|
53
|
+
t: typeof BabelTypes,
|
|
54
|
+
) => BabelTypes.Expression[];
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Type for modifier type guard functions
|
|
58
|
+
*/
|
|
59
|
+
export type ModifierTypeGuardFn = (modifier: unknown) => boolean;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Type for the expandSchemeModifier function
|
|
63
|
+
*/
|
|
64
|
+
export type ExpandSchemeModifierFn = (
|
|
65
|
+
modifier: ParsedModifier,
|
|
66
|
+
customColors: Record<string, string>,
|
|
67
|
+
darkSuffix: string,
|
|
68
|
+
lightSuffix: string,
|
|
69
|
+
) => ParsedModifier[];
|
|
70
|
+
|
|
18
71
|
/**
|
|
19
72
|
* Result of processing a dynamic expression
|
|
20
73
|
*/
|
|
@@ -32,23 +85,73 @@ export type DynamicExpressionResult = {
|
|
|
32
85
|
export function processDynamicExpression(
|
|
33
86
|
expression: BabelTypes.Expression,
|
|
34
87
|
state: DynamicProcessingState,
|
|
35
|
-
parseClassName: (className: string,
|
|
88
|
+
parseClassName: (className: string, customTheme?: CustomTheme) => StyleObject,
|
|
36
89
|
generateStyleKey: (className: string) => string,
|
|
90
|
+
splitModifierClasses: SplitModifierClassesFn,
|
|
91
|
+
processPlatformModifiers: ProcessPlatformModifiersFn,
|
|
92
|
+
processColorSchemeModifiers: ProcessColorSchemeModifiersFn,
|
|
93
|
+
componentScope: NodePath<BabelTypes.Function> | null,
|
|
94
|
+
isPlatformModifier: ModifierTypeGuardFn,
|
|
95
|
+
isColorSchemeModifier: ModifierTypeGuardFn,
|
|
96
|
+
isSchemeModifier: ModifierTypeGuardFn,
|
|
97
|
+
expandSchemeModifier: ExpandSchemeModifierFn,
|
|
37
98
|
t: typeof BabelTypes,
|
|
38
99
|
) {
|
|
39
100
|
// Handle template literals: `m-4 ${condition ? "p-4" : "p-2"}`
|
|
40
101
|
if (t.isTemplateLiteral(expression)) {
|
|
41
|
-
return processTemplateLiteral(
|
|
102
|
+
return processTemplateLiteral(
|
|
103
|
+
expression,
|
|
104
|
+
state,
|
|
105
|
+
parseClassName,
|
|
106
|
+
generateStyleKey,
|
|
107
|
+
splitModifierClasses,
|
|
108
|
+
processPlatformModifiers,
|
|
109
|
+
processColorSchemeModifiers,
|
|
110
|
+
componentScope,
|
|
111
|
+
isPlatformModifier,
|
|
112
|
+
isColorSchemeModifier,
|
|
113
|
+
isSchemeModifier,
|
|
114
|
+
expandSchemeModifier,
|
|
115
|
+
t,
|
|
116
|
+
);
|
|
42
117
|
}
|
|
43
118
|
|
|
44
119
|
// Handle conditional expressions: condition ? "m-4" : "p-2"
|
|
45
120
|
if (t.isConditionalExpression(expression)) {
|
|
46
|
-
return processConditionalExpression(
|
|
121
|
+
return processConditionalExpression(
|
|
122
|
+
expression,
|
|
123
|
+
state,
|
|
124
|
+
parseClassName,
|
|
125
|
+
generateStyleKey,
|
|
126
|
+
splitModifierClasses,
|
|
127
|
+
processPlatformModifiers,
|
|
128
|
+
processColorSchemeModifiers,
|
|
129
|
+
componentScope,
|
|
130
|
+
isPlatformModifier,
|
|
131
|
+
isColorSchemeModifier,
|
|
132
|
+
isSchemeModifier,
|
|
133
|
+
expandSchemeModifier,
|
|
134
|
+
t,
|
|
135
|
+
);
|
|
47
136
|
}
|
|
48
137
|
|
|
49
138
|
// Handle logical expressions: condition && "m-4"
|
|
50
139
|
if (t.isLogicalExpression(expression)) {
|
|
51
|
-
return processLogicalExpression(
|
|
140
|
+
return processLogicalExpression(
|
|
141
|
+
expression,
|
|
142
|
+
state,
|
|
143
|
+
parseClassName,
|
|
144
|
+
generateStyleKey,
|
|
145
|
+
splitModifierClasses,
|
|
146
|
+
processPlatformModifiers,
|
|
147
|
+
processColorSchemeModifiers,
|
|
148
|
+
componentScope,
|
|
149
|
+
isPlatformModifier,
|
|
150
|
+
isColorSchemeModifier,
|
|
151
|
+
isSchemeModifier,
|
|
152
|
+
expandSchemeModifier,
|
|
153
|
+
t,
|
|
154
|
+
);
|
|
52
155
|
}
|
|
53
156
|
|
|
54
157
|
// Unsupported expression type
|
|
@@ -61,11 +164,19 @@ export function processDynamicExpression(
|
|
|
61
164
|
function processTemplateLiteral(
|
|
62
165
|
node: BabelTypes.TemplateLiteral,
|
|
63
166
|
state: DynamicProcessingState,
|
|
64
|
-
parseClassName: (className: string,
|
|
167
|
+
parseClassName: (className: string, customTheme?: CustomTheme) => StyleObject,
|
|
65
168
|
generateStyleKey: (className: string) => string,
|
|
169
|
+
splitModifierClasses: SplitModifierClassesFn,
|
|
170
|
+
processPlatformModifiers: ProcessPlatformModifiersFn,
|
|
171
|
+
processColorSchemeModifiers: ProcessColorSchemeModifiersFn,
|
|
172
|
+
componentScope: NodePath<BabelTypes.Function> | null,
|
|
173
|
+
isPlatformModifier: ModifierTypeGuardFn,
|
|
174
|
+
isColorSchemeModifier: ModifierTypeGuardFn,
|
|
175
|
+
isSchemeModifier: ModifierTypeGuardFn,
|
|
176
|
+
expandSchemeModifier: ExpandSchemeModifierFn,
|
|
66
177
|
t: typeof BabelTypes,
|
|
67
178
|
) {
|
|
68
|
-
const parts: BabelTypes.
|
|
179
|
+
const parts: BabelTypes.Expression[] = [];
|
|
69
180
|
const staticParts: string[] = [];
|
|
70
181
|
|
|
71
182
|
// Process quasis (static parts) and expressions (dynamic parts)
|
|
@@ -75,16 +186,31 @@ function processTemplateLiteral(
|
|
|
75
186
|
|
|
76
187
|
// Add static part if not empty
|
|
77
188
|
if (staticText) {
|
|
78
|
-
// Parse static classes
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
189
|
+
// Parse static classes with modifier support
|
|
190
|
+
const processedExpression = processStringOrExpressionHelper(
|
|
191
|
+
t.stringLiteral(staticText),
|
|
192
|
+
state,
|
|
193
|
+
parseClassName,
|
|
194
|
+
generateStyleKey,
|
|
195
|
+
splitModifierClasses,
|
|
196
|
+
processPlatformModifiers,
|
|
197
|
+
processColorSchemeModifiers,
|
|
198
|
+
componentScope,
|
|
199
|
+
isPlatformModifier,
|
|
200
|
+
isColorSchemeModifier,
|
|
201
|
+
isSchemeModifier,
|
|
202
|
+
expandSchemeModifier,
|
|
203
|
+
t,
|
|
204
|
+
);
|
|
205
|
+
|
|
206
|
+
if (processedExpression) {
|
|
207
|
+
staticParts.push(staticText);
|
|
208
|
+
// Handle array or single expression
|
|
209
|
+
if (t.isArrayExpression(processedExpression)) {
|
|
210
|
+
parts.push(...(processedExpression.elements as BabelTypes.Expression[]));
|
|
211
|
+
} else {
|
|
212
|
+
parts.push(processedExpression);
|
|
213
|
+
}
|
|
88
214
|
}
|
|
89
215
|
}
|
|
90
216
|
|
|
@@ -98,14 +224,21 @@ function processTemplateLiteral(
|
|
|
98
224
|
state,
|
|
99
225
|
parseClassName,
|
|
100
226
|
generateStyleKey,
|
|
227
|
+
splitModifierClasses,
|
|
228
|
+
processPlatformModifiers,
|
|
229
|
+
processColorSchemeModifiers,
|
|
230
|
+
componentScope,
|
|
231
|
+
isPlatformModifier,
|
|
232
|
+
isColorSchemeModifier,
|
|
233
|
+
isSchemeModifier,
|
|
234
|
+
expandSchemeModifier,
|
|
101
235
|
t,
|
|
102
236
|
);
|
|
103
237
|
if (result) {
|
|
104
|
-
parts.push(result.expression
|
|
238
|
+
parts.push(result.expression);
|
|
105
239
|
} else {
|
|
106
240
|
// For unsupported expressions, keep them as-is
|
|
107
|
-
|
|
108
|
-
parts.push(expr as BabelTypes.MemberExpression);
|
|
241
|
+
parts.push(expr as BabelTypes.Expression);
|
|
109
242
|
}
|
|
110
243
|
}
|
|
111
244
|
}
|
|
@@ -129,12 +262,48 @@ function processTemplateLiteral(
|
|
|
129
262
|
function processConditionalExpression(
|
|
130
263
|
node: BabelTypes.ConditionalExpression,
|
|
131
264
|
state: DynamicProcessingState,
|
|
132
|
-
parseClassName: (className: string,
|
|
265
|
+
parseClassName: (className: string, customTheme?: CustomTheme) => StyleObject,
|
|
133
266
|
generateStyleKey: (className: string) => string,
|
|
267
|
+
splitModifierClasses: SplitModifierClassesFn,
|
|
268
|
+
processPlatformModifiers: ProcessPlatformModifiersFn,
|
|
269
|
+
processColorSchemeModifiers: ProcessColorSchemeModifiersFn,
|
|
270
|
+
componentScope: NodePath<BabelTypes.Function> | null,
|
|
271
|
+
isPlatformModifier: ModifierTypeGuardFn,
|
|
272
|
+
isColorSchemeModifier: ModifierTypeGuardFn,
|
|
273
|
+
isSchemeModifier: ModifierTypeGuardFn,
|
|
274
|
+
expandSchemeModifier: ExpandSchemeModifierFn,
|
|
134
275
|
t: typeof BabelTypes,
|
|
135
276
|
) {
|
|
136
|
-
const consequent =
|
|
137
|
-
|
|
277
|
+
const consequent = processStringOrExpressionHelper(
|
|
278
|
+
node.consequent,
|
|
279
|
+
state,
|
|
280
|
+
parseClassName,
|
|
281
|
+
generateStyleKey,
|
|
282
|
+
splitModifierClasses,
|
|
283
|
+
processPlatformModifiers,
|
|
284
|
+
processColorSchemeModifiers,
|
|
285
|
+
componentScope,
|
|
286
|
+
isPlatformModifier,
|
|
287
|
+
isColorSchemeModifier,
|
|
288
|
+
isSchemeModifier,
|
|
289
|
+
expandSchemeModifier,
|
|
290
|
+
t,
|
|
291
|
+
);
|
|
292
|
+
const alternate = processStringOrExpressionHelper(
|
|
293
|
+
node.alternate,
|
|
294
|
+
state,
|
|
295
|
+
parseClassName,
|
|
296
|
+
generateStyleKey,
|
|
297
|
+
splitModifierClasses,
|
|
298
|
+
processPlatformModifiers,
|
|
299
|
+
processColorSchemeModifiers,
|
|
300
|
+
componentScope,
|
|
301
|
+
isPlatformModifier,
|
|
302
|
+
isColorSchemeModifier,
|
|
303
|
+
isSchemeModifier,
|
|
304
|
+
expandSchemeModifier,
|
|
305
|
+
t,
|
|
306
|
+
);
|
|
138
307
|
|
|
139
308
|
if (!consequent && !alternate) {
|
|
140
309
|
return null;
|
|
@@ -143,8 +312,8 @@ function processConditionalExpression(
|
|
|
143
312
|
// Build conditional: condition ? consequentStyle : alternateStyle
|
|
144
313
|
const expression = t.conditionalExpression(
|
|
145
314
|
node.test,
|
|
146
|
-
|
|
147
|
-
|
|
315
|
+
consequent ?? t.nullLiteral(),
|
|
316
|
+
alternate ?? t.nullLiteral(),
|
|
148
317
|
);
|
|
149
318
|
|
|
150
319
|
return { expression };
|
|
@@ -156,8 +325,16 @@ function processConditionalExpression(
|
|
|
156
325
|
function processLogicalExpression(
|
|
157
326
|
node: BabelTypes.LogicalExpression,
|
|
158
327
|
state: DynamicProcessingState,
|
|
159
|
-
parseClassName: (className: string,
|
|
328
|
+
parseClassName: (className: string, customTheme?: CustomTheme) => StyleObject,
|
|
160
329
|
generateStyleKey: (className: string) => string,
|
|
330
|
+
splitModifierClasses: SplitModifierClassesFn,
|
|
331
|
+
processPlatformModifiers: ProcessPlatformModifiersFn,
|
|
332
|
+
processColorSchemeModifiers: ProcessColorSchemeModifiersFn,
|
|
333
|
+
componentScope: NodePath<BabelTypes.Function> | null,
|
|
334
|
+
isPlatformModifier: ModifierTypeGuardFn,
|
|
335
|
+
isColorSchemeModifier: ModifierTypeGuardFn,
|
|
336
|
+
isSchemeModifier: ModifierTypeGuardFn,
|
|
337
|
+
expandSchemeModifier: ExpandSchemeModifierFn,
|
|
161
338
|
t: typeof BabelTypes,
|
|
162
339
|
) {
|
|
163
340
|
// Only handle AND (&&) expressions
|
|
@@ -165,28 +342,52 @@ function processLogicalExpression(
|
|
|
165
342
|
return null;
|
|
166
343
|
}
|
|
167
344
|
|
|
168
|
-
const right =
|
|
345
|
+
const right = processStringOrExpressionHelper(
|
|
346
|
+
node.right,
|
|
347
|
+
state,
|
|
348
|
+
parseClassName,
|
|
349
|
+
generateStyleKey,
|
|
350
|
+
splitModifierClasses,
|
|
351
|
+
processPlatformModifiers,
|
|
352
|
+
processColorSchemeModifiers,
|
|
353
|
+
componentScope,
|
|
354
|
+
isPlatformModifier,
|
|
355
|
+
isColorSchemeModifier,
|
|
356
|
+
isSchemeModifier,
|
|
357
|
+
expandSchemeModifier,
|
|
358
|
+
t,
|
|
359
|
+
);
|
|
169
360
|
|
|
170
361
|
if (!right) {
|
|
171
362
|
return null;
|
|
172
363
|
}
|
|
173
364
|
|
|
174
365
|
// Build logical: condition && style
|
|
175
|
-
const expression = t.logicalExpression("&&", node.left, right
|
|
366
|
+
const expression = t.logicalExpression("&&", node.left, right);
|
|
176
367
|
|
|
177
368
|
return { expression };
|
|
178
369
|
}
|
|
179
370
|
|
|
180
371
|
/**
|
|
181
372
|
* Process a node that might be a string literal or another expression
|
|
373
|
+
*
|
|
374
|
+
* This helper is called by processStringOrExpression below
|
|
182
375
|
*/
|
|
183
|
-
function
|
|
376
|
+
function processStringOrExpressionHelper(
|
|
184
377
|
node: BabelTypes.StringLiteral | BabelTypes.Expression,
|
|
185
378
|
state: DynamicProcessingState,
|
|
186
|
-
parseClassName: (className: string,
|
|
379
|
+
parseClassName: (className: string, customTheme?: CustomTheme) => StyleObject,
|
|
187
380
|
generateStyleKey: (className: string) => string,
|
|
381
|
+
splitModifierClasses: SplitModifierClassesFn,
|
|
382
|
+
processPlatformModifiers: ProcessPlatformModifiersFn,
|
|
383
|
+
processColorSchemeModifiers: ProcessColorSchemeModifiersFn,
|
|
384
|
+
componentScope: NodePath<BabelTypes.Function> | null,
|
|
385
|
+
isPlatformModifier: ModifierTypeGuardFn,
|
|
386
|
+
isColorSchemeModifier: ModifierTypeGuardFn,
|
|
387
|
+
isSchemeModifier: ModifierTypeGuardFn,
|
|
388
|
+
expandSchemeModifier: ExpandSchemeModifierFn,
|
|
188
389
|
t: typeof BabelTypes,
|
|
189
|
-
) {
|
|
390
|
+
): BabelTypes.Expression | BabelTypes.ArrayExpression | null {
|
|
190
391
|
// Handle string literals
|
|
191
392
|
if (t.isStringLiteral(node)) {
|
|
192
393
|
const className = node.value.trim();
|
|
@@ -194,27 +395,145 @@ function processStringOrExpression(
|
|
|
194
395
|
return null;
|
|
195
396
|
}
|
|
196
397
|
|
|
197
|
-
//
|
|
198
|
-
const
|
|
199
|
-
|
|
200
|
-
|
|
398
|
+
// Split into base and modifier classes
|
|
399
|
+
const { baseClasses, modifierClasses: rawModifierClasses } = splitModifierClasses(className);
|
|
400
|
+
|
|
401
|
+
// Expand scheme: modifiers into dark: and light: modifiers
|
|
402
|
+
const modifierClasses: Array<import("../../parser/index.js").ParsedModifier> = [];
|
|
403
|
+
for (const modifier of rawModifierClasses) {
|
|
404
|
+
if (isSchemeModifier(modifier.modifier)) {
|
|
405
|
+
// Expand scheme: into dark: and light:
|
|
406
|
+
const expanded = expandSchemeModifier(
|
|
407
|
+
modifier,
|
|
408
|
+
state.customTheme.colors ?? {},
|
|
409
|
+
state.schemeModifierConfig.darkSuffix ?? "-dark",
|
|
410
|
+
state.schemeModifierConfig.lightSuffix ?? "-light",
|
|
411
|
+
);
|
|
412
|
+
modifierClasses.push(...expanded);
|
|
413
|
+
} else {
|
|
414
|
+
// Keep other modifiers as-is
|
|
415
|
+
modifierClasses.push(modifier);
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
// Separate modifiers by type
|
|
420
|
+
const platformModifiers = modifierClasses.filter((m) => isPlatformModifier(m.modifier));
|
|
421
|
+
const colorSchemeModifiers = modifierClasses.filter((m) => isColorSchemeModifier(m.modifier));
|
|
422
|
+
|
|
423
|
+
const styleElements: BabelTypes.Expression[] = [];
|
|
424
|
+
|
|
425
|
+
// Process base classes
|
|
426
|
+
if (baseClasses.length > 0) {
|
|
427
|
+
const baseClassName = baseClasses.join(" ");
|
|
428
|
+
const styleObject = parseClassName(baseClassName, state.customTheme);
|
|
429
|
+
const styleKey = generateStyleKey(baseClassName);
|
|
430
|
+
state.styleRegistry.set(styleKey, styleObject);
|
|
431
|
+
styleElements.push(t.memberExpression(t.identifier(state.stylesIdentifier), t.identifier(styleKey)));
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
// Process platform modifiers
|
|
435
|
+
if (platformModifiers.length > 0) {
|
|
436
|
+
state.needsPlatformImport = true;
|
|
437
|
+
const platformExpression = processPlatformModifiers(
|
|
438
|
+
platformModifiers,
|
|
439
|
+
state,
|
|
440
|
+
parseClassName,
|
|
441
|
+
generateStyleKey,
|
|
442
|
+
t,
|
|
443
|
+
);
|
|
444
|
+
styleElements.push(platformExpression);
|
|
445
|
+
}
|
|
201
446
|
|
|
202
|
-
|
|
447
|
+
// Process color scheme modifiers (only if component scope exists)
|
|
448
|
+
if (colorSchemeModifiers.length > 0) {
|
|
449
|
+
if (componentScope) {
|
|
450
|
+
state.needsColorSchemeImport = true;
|
|
451
|
+
state.functionComponentsNeedingColorScheme.add(componentScope);
|
|
452
|
+
const colorSchemeExpressions = processColorSchemeModifiers(
|
|
453
|
+
colorSchemeModifiers,
|
|
454
|
+
state,
|
|
455
|
+
parseClassName,
|
|
456
|
+
generateStyleKey,
|
|
457
|
+
t,
|
|
458
|
+
);
|
|
459
|
+
styleElements.push(...colorSchemeExpressions);
|
|
460
|
+
} else {
|
|
461
|
+
// Warn in development: color scheme modifiers without valid component scope
|
|
462
|
+
// Skip transformation - these modifiers will be ignored
|
|
463
|
+
if (process.env.NODE_ENV !== "production") {
|
|
464
|
+
console.warn(
|
|
465
|
+
"[react-native-tailwind] dark:/light: modifiers in dynamic expressions require a function component scope. " +
|
|
466
|
+
"These modifiers will be ignored.",
|
|
467
|
+
);
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
// Return single element or array
|
|
473
|
+
if (styleElements.length === 0) {
|
|
474
|
+
return null;
|
|
475
|
+
}
|
|
476
|
+
if (styleElements.length === 1) {
|
|
477
|
+
return styleElements[0];
|
|
478
|
+
}
|
|
479
|
+
return t.arrayExpression(styleElements);
|
|
203
480
|
}
|
|
204
481
|
|
|
205
482
|
// Handle nested expressions recursively
|
|
206
483
|
if (t.isConditionalExpression(node)) {
|
|
207
|
-
const result = processConditionalExpression(
|
|
484
|
+
const result = processConditionalExpression(
|
|
485
|
+
node,
|
|
486
|
+
state,
|
|
487
|
+
parseClassName,
|
|
488
|
+
generateStyleKey,
|
|
489
|
+
splitModifierClasses,
|
|
490
|
+
processPlatformModifiers,
|
|
491
|
+
processColorSchemeModifiers,
|
|
492
|
+
componentScope,
|
|
493
|
+
isPlatformModifier,
|
|
494
|
+
isColorSchemeModifier,
|
|
495
|
+
isSchemeModifier,
|
|
496
|
+
expandSchemeModifier,
|
|
497
|
+
t,
|
|
498
|
+
);
|
|
208
499
|
return result?.expression ?? null;
|
|
209
500
|
}
|
|
210
501
|
|
|
211
502
|
if (t.isLogicalExpression(node)) {
|
|
212
|
-
const result = processLogicalExpression(
|
|
503
|
+
const result = processLogicalExpression(
|
|
504
|
+
node,
|
|
505
|
+
state,
|
|
506
|
+
parseClassName,
|
|
507
|
+
generateStyleKey,
|
|
508
|
+
splitModifierClasses,
|
|
509
|
+
processPlatformModifiers,
|
|
510
|
+
processColorSchemeModifiers,
|
|
511
|
+
componentScope,
|
|
512
|
+
isPlatformModifier,
|
|
513
|
+
isColorSchemeModifier,
|
|
514
|
+
isSchemeModifier,
|
|
515
|
+
expandSchemeModifier,
|
|
516
|
+
t,
|
|
517
|
+
);
|
|
213
518
|
return result?.expression ?? null;
|
|
214
519
|
}
|
|
215
520
|
|
|
216
521
|
if (t.isTemplateLiteral(node)) {
|
|
217
|
-
const result = processTemplateLiteral(
|
|
522
|
+
const result = processTemplateLiteral(
|
|
523
|
+
node,
|
|
524
|
+
state,
|
|
525
|
+
parseClassName,
|
|
526
|
+
generateStyleKey,
|
|
527
|
+
splitModifierClasses,
|
|
528
|
+
processPlatformModifiers,
|
|
529
|
+
processColorSchemeModifiers,
|
|
530
|
+
componentScope,
|
|
531
|
+
isPlatformModifier,
|
|
532
|
+
isColorSchemeModifier,
|
|
533
|
+
isSchemeModifier,
|
|
534
|
+
expandSchemeModifier,
|
|
535
|
+
t,
|
|
536
|
+
);
|
|
218
537
|
return result?.expression ?? null;
|
|
219
538
|
}
|
|
220
539
|
|
|
@@ -2,21 +2,21 @@
|
|
|
2
2
|
* Utility functions for processing class modifiers (active:, hover:, focus:, etc.)
|
|
3
3
|
*/
|
|
4
4
|
import type * as BabelTypes from "@babel/types";
|
|
5
|
-
import type { ModifierType, ParsedModifier } from "../../parser/index.js";
|
|
5
|
+
import type { CustomTheme, ModifierType, ParsedModifier } from "../../parser/index.js";
|
|
6
6
|
import type { StyleObject } from "../../types/core.js";
|
|
7
7
|
/**
|
|
8
8
|
* Plugin state interface (subset needed for modifier processing)
|
|
9
9
|
*/
|
|
10
10
|
export interface ModifierProcessingState {
|
|
11
11
|
styleRegistry: Map<string, StyleObject>;
|
|
12
|
-
|
|
12
|
+
customTheme: CustomTheme;
|
|
13
13
|
stylesIdentifier: string;
|
|
14
14
|
}
|
|
15
15
|
/**
|
|
16
16
|
* Process a static className string that contains modifiers
|
|
17
17
|
* Returns a style function expression for Pressable components
|
|
18
18
|
*/
|
|
19
|
-
export declare function processStaticClassNameWithModifiers(className: string, state: ModifierProcessingState, parseClassName: (className: string,
|
|
19
|
+
export declare function processStaticClassNameWithModifiers(className: string, state: ModifierProcessingState, parseClassName: (className: string, customTheme?: CustomTheme) => StyleObject, generateStyleKey: (className: string) => string, splitModifierClasses: (className: string) => {
|
|
20
20
|
baseClasses: string[];
|
|
21
21
|
modifierClasses: ParsedModifier[];
|
|
22
22
|
}, t: typeof BabelTypes): BabelTypes.Expression;
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import type * as BabelTypes from "@babel/types";
|
|
6
|
-
import type { ModifierType, ParsedModifier } from "../../parser/index.js";
|
|
6
|
+
import type { CustomTheme, ModifierType, ParsedModifier } from "../../parser/index.js";
|
|
7
7
|
import type { StyleObject } from "../../types/core.js";
|
|
8
8
|
import { getStatePropertyForModifier } from "./componentSupport.js";
|
|
9
9
|
|
|
@@ -13,7 +13,7 @@ import { getStatePropertyForModifier } from "./componentSupport.js";
|
|
|
13
13
|
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
|
|
14
14
|
export interface ModifierProcessingState {
|
|
15
15
|
styleRegistry: Map<string, StyleObject>;
|
|
16
|
-
|
|
16
|
+
customTheme: CustomTheme;
|
|
17
17
|
stylesIdentifier: string;
|
|
18
18
|
}
|
|
19
19
|
|
|
@@ -24,7 +24,7 @@ export interface ModifierProcessingState {
|
|
|
24
24
|
export function processStaticClassNameWithModifiers(
|
|
25
25
|
className: string,
|
|
26
26
|
state: ModifierProcessingState,
|
|
27
|
-
parseClassName: (className: string,
|
|
27
|
+
parseClassName: (className: string, customTheme?: CustomTheme) => StyleObject,
|
|
28
28
|
generateStyleKey: (className: string) => string,
|
|
29
29
|
splitModifierClasses: (className: string) => { baseClasses: string[]; modifierClasses: ParsedModifier[] },
|
|
30
30
|
t: typeof BabelTypes,
|
|
@@ -35,7 +35,7 @@ export function processStaticClassNameWithModifiers(
|
|
|
35
35
|
let baseStyleExpression: BabelTypes.Node | null = null;
|
|
36
36
|
if (baseClasses.length > 0) {
|
|
37
37
|
const baseClassName = baseClasses.join(" ");
|
|
38
|
-
const baseStyleObject = parseClassName(baseClassName, state.
|
|
38
|
+
const baseStyleObject = parseClassName(baseClassName, state.customTheme);
|
|
39
39
|
const baseStyleKey = generateStyleKey(baseClassName);
|
|
40
40
|
state.styleRegistry.set(baseStyleKey, baseStyleObject);
|
|
41
41
|
baseStyleExpression = t.memberExpression(t.identifier(state.stylesIdentifier), t.identifier(baseStyleKey));
|
|
@@ -66,7 +66,7 @@ export function processStaticClassNameWithModifiers(
|
|
|
66
66
|
for (const [modifierType, modifiers] of modifiersByType) {
|
|
67
67
|
// Parse all modifier classes together
|
|
68
68
|
const modifierClassNames = modifiers.map((m) => m.baseClass).join(" ");
|
|
69
|
-
const modifierStyleObject = parseClassName(modifierClassNames, state.
|
|
69
|
+
const modifierStyleObject = parseClassName(modifierClassNames, state.customTheme);
|
|
70
70
|
const modifierStyleKey = generateStyleKey(`${modifierType}_${modifierClassNames}`);
|
|
71
71
|
state.styleRegistry.set(modifierStyleKey, modifierStyleObject);
|
|
72
72
|
|
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
* Utility functions for processing platform modifiers (ios:, android:, web:)
|
|
3
3
|
*/
|
|
4
4
|
import type * as BabelTypes from "@babel/types";
|
|
5
|
-
import type { ParsedModifier } from "../../parser/index.js";
|
|
5
|
+
import type { CustomTheme, ParsedModifier } from "../../parser/index.js";
|
|
6
6
|
import type { StyleObject } from "../../types/core.js";
|
|
7
7
|
/**
|
|
8
8
|
* Plugin state interface (subset needed for platform modifier processing)
|
|
9
9
|
*/
|
|
10
10
|
export interface PlatformModifierProcessingState {
|
|
11
11
|
styleRegistry: Map<string, StyleObject>;
|
|
12
|
-
|
|
12
|
+
customTheme: CustomTheme;
|
|
13
13
|
stylesIdentifier: string;
|
|
14
14
|
needsPlatformImport: boolean;
|
|
15
15
|
}
|
|
@@ -27,4 +27,4 @@ export interface PlatformModifierProcessingState {
|
|
|
27
27
|
* Input: [{ modifier: "ios", baseClass: "shadow-lg" }, { modifier: "android", baseClass: "elevation-4" }]
|
|
28
28
|
* Output: Platform.select({ ios: styles._ios_shadow_lg, android: styles._android_elevation_4 })
|
|
29
29
|
*/
|
|
30
|
-
export declare function processPlatformModifiers(platformModifiers: ParsedModifier[], state: PlatformModifierProcessingState, parseClassName: (className: string,
|
|
30
|
+
export declare function processPlatformModifiers(platformModifiers: ParsedModifier[], state: PlatformModifierProcessingState, parseClassName: (className: string, customTheme?: CustomTheme) => StyleObject, generateStyleKey: (className: string) => string, t: typeof BabelTypes): BabelTypes.Expression;
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import type * as BabelTypes from "@babel/types";
|
|
6
|
-
import type { ParsedModifier, PlatformModifierType } from "../../parser/index.js";
|
|
6
|
+
import type { CustomTheme, ParsedModifier, PlatformModifierType } from "../../parser/index.js";
|
|
7
7
|
import type { StyleObject } from "../../types/core.js";
|
|
8
8
|
|
|
9
9
|
/**
|
|
@@ -12,7 +12,7 @@ import type { StyleObject } from "../../types/core.js";
|
|
|
12
12
|
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
|
|
13
13
|
export interface PlatformModifierProcessingState {
|
|
14
14
|
styleRegistry: Map<string, StyleObject>;
|
|
15
|
-
|
|
15
|
+
customTheme: CustomTheme;
|
|
16
16
|
stylesIdentifier: string;
|
|
17
17
|
needsPlatformImport: boolean;
|
|
18
18
|
}
|
|
@@ -34,7 +34,7 @@ export interface PlatformModifierProcessingState {
|
|
|
34
34
|
export function processPlatformModifiers(
|
|
35
35
|
platformModifiers: ParsedModifier[],
|
|
36
36
|
state: PlatformModifierProcessingState,
|
|
37
|
-
parseClassName: (className: string,
|
|
37
|
+
parseClassName: (className: string, customTheme?: CustomTheme) => StyleObject,
|
|
38
38
|
generateStyleKey: (className: string) => string,
|
|
39
39
|
t: typeof BabelTypes,
|
|
40
40
|
): BabelTypes.Expression {
|
|
@@ -61,7 +61,7 @@ export function processPlatformModifiers(
|
|
|
61
61
|
for (const [platform, modifiers] of modifiersByPlatform) {
|
|
62
62
|
// Parse all classes for this platform together
|
|
63
63
|
const classNames = modifiers.map((m) => m.baseClass).join(" ");
|
|
64
|
-
const styleObject = parseClassName(classNames, state.
|
|
64
|
+
const styleObject = parseClassName(classNames, state.customTheme);
|
|
65
65
|
const styleKey = generateStyleKey(`${platform}_${classNames}`);
|
|
66
66
|
|
|
67
67
|
// Register style in the registry
|
|
@@ -12,6 +12,19 @@ export declare function addStyleSheetImport(path: NodePath<BabelTypes.Program>,
|
|
|
12
12
|
* Add Platform import to the file or merge with existing react-native import
|
|
13
13
|
*/
|
|
14
14
|
export declare function addPlatformImport(path: NodePath<BabelTypes.Program>, t: typeof BabelTypes): void;
|
|
15
|
+
/**
|
|
16
|
+
* Add useColorScheme import to the file or merge with existing react-native import
|
|
17
|
+
*/
|
|
18
|
+
export declare function addColorSchemeImport(path: NodePath<BabelTypes.Program>, t: typeof BabelTypes): void;
|
|
19
|
+
/**
|
|
20
|
+
* Inject useColorScheme hook call at the top of a function component
|
|
21
|
+
*
|
|
22
|
+
* @param functionPath - Path to the function component
|
|
23
|
+
* @param colorSchemeVariableName - Name for the color scheme variable
|
|
24
|
+
* @param t - Babel types
|
|
25
|
+
* @returns true if hook was injected, false if already exists
|
|
26
|
+
*/
|
|
27
|
+
export declare function injectColorSchemeHook(functionPath: NodePath<BabelTypes.Function>, colorSchemeVariableName: string, t: typeof BabelTypes): boolean;
|
|
15
28
|
/**
|
|
16
29
|
* Inject StyleSheet.create with all collected styles at the top of the file
|
|
17
30
|
* This ensures the styles object is defined before any code that references it
|