@colorye/react-native-css 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.babelrc +3 -0
- package/.yarnrc.yml +8 -0
- package/dist/babel.js +201 -0
- package/dist/features/build-transform.js +562 -0
- package/dist/features/css-calc.js +378 -0
- package/dist/features/css-media.js +77 -0
- package/dist/features/css-transform.js +398 -0
- package/dist/features/css-vars.js +107 -0
- package/dist/features/stylesheet.js +94 -0
- package/dist/index.js +158 -0
- package/dist/transformer-runtime.js +310 -0
- package/dist/utils/babel.js +336 -0
- package/dist/utils/css.js +239 -0
- package/dist/utils/helper.js +11 -0
- package/package.json +26 -0
- package/src/babel.js +274 -0
- package/src/features/build-transform.js +524 -0
- package/src/features/css-calc.js +326 -0
- package/src/features/css-media.js +78 -0
- package/src/features/css-transform.js +419 -0
- package/src/features/css-vars.js +93 -0
- package/src/features/stylesheet.js +82 -0
- package/src/index.js +123 -0
- package/src/transformer-runtime.js +287 -0
- package/src/utils/babel.js +354 -0
- package/src/utils/css.js +254 -0
- package/src/utils/helper.js +3 -0
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
import { Appearance, Dimensions, PixelRatio } from "react-native";
|
|
2
|
+
import CssCalc from "./features/css-calc";
|
|
3
|
+
import CssMedia from "./features/css-media";
|
|
4
|
+
import CssTransform from "./features/css-transform";
|
|
5
|
+
import CssVars from "./features/css-vars";
|
|
6
|
+
|
|
7
|
+
// ============================================================================
|
|
8
|
+
// Constants
|
|
9
|
+
// ============================================================================
|
|
10
|
+
const INHERIT_PROPERTIES = [
|
|
11
|
+
"color",
|
|
12
|
+
"fontFamily",
|
|
13
|
+
"fontSize",
|
|
14
|
+
"fontStyle",
|
|
15
|
+
"fontWeight",
|
|
16
|
+
"fontVariant",
|
|
17
|
+
"letterSpacing",
|
|
18
|
+
"lineHeight",
|
|
19
|
+
"textAlign",
|
|
20
|
+
"textTransform",
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
// ============================================================================
|
|
24
|
+
// Singleton Helper Instances
|
|
25
|
+
// ============================================================================
|
|
26
|
+
const vars = new CssVars();
|
|
27
|
+
const transform = new CssTransform();
|
|
28
|
+
const calc = new CssCalc();
|
|
29
|
+
const media = new CssMedia();
|
|
30
|
+
|
|
31
|
+
// ============================================================================
|
|
32
|
+
// Cached Dimensions and Appearance
|
|
33
|
+
// ============================================================================
|
|
34
|
+
let cachedDimensions = null;
|
|
35
|
+
let cachedColorScheme = null;
|
|
36
|
+
let TRANSFORM_CACHE = {};
|
|
37
|
+
let currentCacheKey = null;
|
|
38
|
+
|
|
39
|
+
function getDimensions() {
|
|
40
|
+
if (!cachedDimensions) {
|
|
41
|
+
cachedDimensions = Dimensions.get("window");
|
|
42
|
+
}
|
|
43
|
+
return cachedDimensions;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function getColorScheme() {
|
|
47
|
+
if (cachedColorScheme === null) {
|
|
48
|
+
cachedColorScheme = Appearance.getColorScheme();
|
|
49
|
+
}
|
|
50
|
+
return cachedColorScheme;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function getCacheKey() {
|
|
54
|
+
const { width, height } = getDimensions();
|
|
55
|
+
const colorScheme = getColorScheme();
|
|
56
|
+
return `${width}x${height}:${colorScheme}`;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function invalidateCache() {
|
|
60
|
+
cachedDimensions = null;
|
|
61
|
+
cachedColorScheme = null;
|
|
62
|
+
TRANSFORM_CACHE = {};
|
|
63
|
+
currentCacheKey = null;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Event listeners for cache invalidation
|
|
67
|
+
Dimensions.addEventListener("change", invalidateCache);
|
|
68
|
+
Appearance.addChangeListener(invalidateCache);
|
|
69
|
+
|
|
70
|
+
// ============================================================================
|
|
71
|
+
// Flatten Style
|
|
72
|
+
// ============================================================================
|
|
73
|
+
function getFlattenStyle(declarations) {
|
|
74
|
+
if (!Array.isArray(declarations)) {
|
|
75
|
+
return declarations;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const result = {};
|
|
79
|
+
|
|
80
|
+
function merge(item) {
|
|
81
|
+
if (!item) return;
|
|
82
|
+
if (Array.isArray(item)) {
|
|
83
|
+
for (let i = 0; i < item.length; i++) {
|
|
84
|
+
merge(item[i]);
|
|
85
|
+
}
|
|
86
|
+
} else {
|
|
87
|
+
Object.assign(result, item);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
for (let i = 0; i < declarations.length; i++) {
|
|
92
|
+
merge(declarations[i]);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return Object.keys(result).length > 0 ? result : undefined;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// ============================================================================
|
|
99
|
+
// Main Transform Function
|
|
100
|
+
// ============================================================================
|
|
101
|
+
function transformStyles(stylesheet, classNames) {
|
|
102
|
+
if (!stylesheet || !classNames) return undefined;
|
|
103
|
+
|
|
104
|
+
const { width, height } = getDimensions();
|
|
105
|
+
const colorScheme = getColorScheme();
|
|
106
|
+
|
|
107
|
+
// Check cache validity
|
|
108
|
+
const cacheKey = getCacheKey();
|
|
109
|
+
if (cacheKey !== currentCacheKey) {
|
|
110
|
+
TRANSFORM_CACHE = {};
|
|
111
|
+
currentCacheKey = cacheKey;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const transformedDeclarations = classNames.split(" ").map((className) => {
|
|
115
|
+
if (!className) return null;
|
|
116
|
+
|
|
117
|
+
// Check cache
|
|
118
|
+
if (TRANSFORM_CACHE[className] !== undefined) {
|
|
119
|
+
return TRANSFORM_CACHE[className];
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const declaration = stylesheet[className];
|
|
123
|
+
const globalDeclaration = stylesheet[":root"];
|
|
124
|
+
|
|
125
|
+
if (!declaration && !globalDeclaration) {
|
|
126
|
+
TRANSFORM_CACHE[className] = null;
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Reset vars helper
|
|
131
|
+
vars.global = {};
|
|
132
|
+
vars.data = {};
|
|
133
|
+
|
|
134
|
+
if (globalDeclaration) {
|
|
135
|
+
// Handle global with potential _static/_dynamic format
|
|
136
|
+
const globalRaw = globalDeclaration._static
|
|
137
|
+
? { ...globalDeclaration._static, ...globalDeclaration._dynamic }
|
|
138
|
+
: globalDeclaration;
|
|
139
|
+
vars.setGlobal(globalRaw, { width, height });
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if (declaration) {
|
|
143
|
+
// Handle declaration with potential _static/_dynamic format
|
|
144
|
+
const declRaw = declaration._static
|
|
145
|
+
? { ...declaration._static, ...declaration._dynamic }
|
|
146
|
+
: declaration;
|
|
147
|
+
vars.set(className, declRaw, { width, height });
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Get static and dynamic parts
|
|
151
|
+
const staticPart = declaration?._static || {};
|
|
152
|
+
const dynamicPart = declaration?._dynamic || (declaration?._static ? {} : declaration) || {};
|
|
153
|
+
|
|
154
|
+
// Start with pre-computed static styles
|
|
155
|
+
let results = { ...staticPart };
|
|
156
|
+
|
|
157
|
+
// Process dynamic properties
|
|
158
|
+
const transformDynamic = (currentSelector, decl) => {
|
|
159
|
+
for (let property in decl) {
|
|
160
|
+
if (vars.isVar(property)) continue;
|
|
161
|
+
|
|
162
|
+
let value = decl[property];
|
|
163
|
+
|
|
164
|
+
// Handle media queries
|
|
165
|
+
const [isMedia, matchedMedia] = media.match(property, { width, height, colorScheme });
|
|
166
|
+
if (isMedia) {
|
|
167
|
+
if (matchedMedia) {
|
|
168
|
+
vars.set(property, value);
|
|
169
|
+
// Media query value might have _static/_dynamic too
|
|
170
|
+
const mediaStatic = value?._static || {};
|
|
171
|
+
const mediaDynamic = value?._dynamic || (value?._static ? {} : value) || {};
|
|
172
|
+
Object.assign(results, mediaStatic);
|
|
173
|
+
transformDynamic(property, mediaDynamic);
|
|
174
|
+
}
|
|
175
|
+
continue;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Transform the value
|
|
179
|
+
[property, value] = transform.transformUnsafeValue(property, value);
|
|
180
|
+
if (!property) continue;
|
|
181
|
+
|
|
182
|
+
value = vars.injectVar(currentSelector, value);
|
|
183
|
+
value = transform.transformUnsupportedUnit(value);
|
|
184
|
+
value = transform.transformViewportUnit(value, { width, height });
|
|
185
|
+
value = transform.removeUnit(value);
|
|
186
|
+
value = calc.calc(value);
|
|
187
|
+
value = calc.calcColor(value);
|
|
188
|
+
value = transform.transformFontScaling(property, value, {
|
|
189
|
+
width,
|
|
190
|
+
height,
|
|
191
|
+
roundFn: PixelRatio.roundToNearestPixel,
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
if (value === undefined) continue;
|
|
195
|
+
|
|
196
|
+
const transformed = transform.transform(property, value, { width, height });
|
|
197
|
+
if (transformed) {
|
|
198
|
+
Object.assign(results, transformed);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
transformDynamic(className, dynamicPart);
|
|
204
|
+
|
|
205
|
+
TRANSFORM_CACHE[className] = results;
|
|
206
|
+
return results;
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
return getFlattenStyle(transformedDeclarations);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// ============================================================================
|
|
213
|
+
// Inherit Style
|
|
214
|
+
// ============================================================================
|
|
215
|
+
function getInheritStyle(declarations) {
|
|
216
|
+
if (!declarations) return undefined;
|
|
217
|
+
|
|
218
|
+
const inheritDeclarations = {};
|
|
219
|
+
for (const key of INHERIT_PROPERTIES) {
|
|
220
|
+
if (declarations[key] !== undefined) {
|
|
221
|
+
inheritDeclarations[key] = declarations[key];
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
return Object.keys(inheritDeclarations).length > 0 ? inheritDeclarations : undefined;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// ============================================================================
|
|
229
|
+
// Main Entry Point
|
|
230
|
+
// ============================================================================
|
|
231
|
+
function getStyle(stylesheet, [inheritStyle, className, style]) {
|
|
232
|
+
return getFlattenStyle([
|
|
233
|
+
getInheritStyle(getFlattenStyle(inheritStyle)),
|
|
234
|
+
transformStyles(stylesheet, className),
|
|
235
|
+
style,
|
|
236
|
+
]);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// ============================================================================
|
|
240
|
+
// Lightweight Merge for Static Styles
|
|
241
|
+
// ============================================================================
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Lightweight merge function for static styles with inheritStyle
|
|
245
|
+
* Much cheaper than full getStyle() - just extracts inherited props and merges
|
|
246
|
+
*/
|
|
247
|
+
function mergeStyles(inheritStyle, staticStyles, inlineStyle) {
|
|
248
|
+
// Fast path: no inheritStyle
|
|
249
|
+
if (!inheritStyle && !inlineStyle) {
|
|
250
|
+
return staticStyles;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// Extract inherited properties from inheritStyle
|
|
254
|
+
let inherited;
|
|
255
|
+
if (inheritStyle) {
|
|
256
|
+
const flatInherit = getFlattenStyle(inheritStyle);
|
|
257
|
+
if (flatInherit) {
|
|
258
|
+
inherited = {};
|
|
259
|
+
for (const key of INHERIT_PROPERTIES) {
|
|
260
|
+
if (flatInherit[key] !== undefined) {
|
|
261
|
+
inherited[key] = flatInherit[key];
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
if (Object.keys(inherited).length === 0) {
|
|
265
|
+
inherited = undefined;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// Merge: inheritStyle (lowest) -> staticStyles -> inlineStyle (highest)
|
|
271
|
+
if (!inherited && !inlineStyle) {
|
|
272
|
+
return staticStyles;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
const result = {};
|
|
276
|
+
if (inherited) Object.assign(result, inherited);
|
|
277
|
+
if (staticStyles) Object.assign(result, staticStyles);
|
|
278
|
+
if (inlineStyle) Object.assign(result, inlineStyle);
|
|
279
|
+
|
|
280
|
+
return Object.keys(result).length > 0 ? result : undefined;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
export default {
|
|
284
|
+
getStyle,
|
|
285
|
+
getInheritStyle,
|
|
286
|
+
mergeStyles,
|
|
287
|
+
};
|
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
export function isImportOrRequire(statement) {
|
|
2
|
+
return (
|
|
3
|
+
statement.isImportDeclaration() ||
|
|
4
|
+
statement.node?.declarations?.[0]?.init?.callee?.name === "require"
|
|
5
|
+
);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function isFragmentElement(t, elementName) {
|
|
9
|
+
return (
|
|
10
|
+
(t.isJSXIdentifier(elementName) &&
|
|
11
|
+
(elementName.name === "Fragment" || elementName.name === "React.Fragment")) ||
|
|
12
|
+
(t.isJSXMemberExpression(elementName) &&
|
|
13
|
+
elementName.object.name === "React" &&
|
|
14
|
+
elementName.property.name === "Fragment") ||
|
|
15
|
+
t.isJSXIdentifier(elementName, { name: "" }) // JSX shorthand fragment
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function isRootLevelJSXElement(path) {
|
|
20
|
+
let currentPath = path;
|
|
21
|
+
|
|
22
|
+
while (currentPath.parentPath) {
|
|
23
|
+
const parent = currentPath.parentPath;
|
|
24
|
+
|
|
25
|
+
if (parent.isReturnStatement()) return true;
|
|
26
|
+
if (parent.isArrowFunctionExpression() && parent.node.body === currentPath.node) return true;
|
|
27
|
+
if (parent.isJSXElement() && parent !== path) return false;
|
|
28
|
+
|
|
29
|
+
if (
|
|
30
|
+
parent.isConditionalExpression() ||
|
|
31
|
+
parent.isLogicalExpression() ||
|
|
32
|
+
parent.isParenthesizedExpression()
|
|
33
|
+
) {
|
|
34
|
+
currentPath = parent;
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
currentPath = parent;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// ============================================================================
|
|
45
|
+
// Static style detection helpers
|
|
46
|
+
// ============================================================================
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Check if className is a static string literal
|
|
50
|
+
*/
|
|
51
|
+
export function isStaticClassName(t, classNameAttr) {
|
|
52
|
+
if (!classNameAttr) return false;
|
|
53
|
+
if (t.isStringLiteral(classNameAttr.value)) return true;
|
|
54
|
+
if (
|
|
55
|
+
t.isJSXExpressionContainer(classNameAttr.value) &&
|
|
56
|
+
t.isStringLiteral(classNameAttr.value.expression)
|
|
57
|
+
) {
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Get static className string value
|
|
65
|
+
*/
|
|
66
|
+
export function getStaticClassNameValue(t, classNameAttr) {
|
|
67
|
+
if (!classNameAttr) return null;
|
|
68
|
+
if (t.isStringLiteral(classNameAttr.value)) return classNameAttr.value.value;
|
|
69
|
+
if (
|
|
70
|
+
t.isJSXExpressionContainer(classNameAttr.value) &&
|
|
71
|
+
t.isStringLiteral(classNameAttr.value.expression)
|
|
72
|
+
) {
|
|
73
|
+
return classNameAttr.value.expression.value;
|
|
74
|
+
}
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Check if a class is fully static (no _dynamic property)
|
|
80
|
+
*/
|
|
81
|
+
export function isClassStatic(stylesheet, className) {
|
|
82
|
+
const decl = stylesheet[className];
|
|
83
|
+
if (!decl) return true; // Non-existent class is "static" (no-op)
|
|
84
|
+
if (decl._dynamic && Object.keys(decl._dynamic).length > 0) return false;
|
|
85
|
+
if (decl._static) return true; // Has _static wrapper
|
|
86
|
+
// Check if it's a plain object (fully static, no wrapper)
|
|
87
|
+
return typeof decl === "object" && !decl._dynamic;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Get static styles from a class declaration
|
|
92
|
+
*/
|
|
93
|
+
export function getStaticStylesFromClass(stylesheet, className) {
|
|
94
|
+
const decl = stylesheet[className];
|
|
95
|
+
if (!decl) return {};
|
|
96
|
+
|
|
97
|
+
// If has _static wrapper, use that
|
|
98
|
+
if (decl._static) return { ...decl._static };
|
|
99
|
+
|
|
100
|
+
// If plain object (fully static), use directly
|
|
101
|
+
if (typeof decl === "object" && !decl._dynamic) {
|
|
102
|
+
// Filter out any metadata keys
|
|
103
|
+
const result = {};
|
|
104
|
+
for (const [key, value] of Object.entries(decl)) {
|
|
105
|
+
if (!key.startsWith("_") && !key.startsWith("@media")) {
|
|
106
|
+
result[key] = value;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return result;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return {};
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Check if all classes in className string are static
|
|
117
|
+
*/
|
|
118
|
+
export function areAllClassesStatic(stylesheet, classNameValue) {
|
|
119
|
+
if (!classNameValue || !stylesheet) return false;
|
|
120
|
+
const classes = classNameValue.trim().split(/\s+/).filter(Boolean);
|
|
121
|
+
return classes.every((cls) => isClassStatic(stylesheet, cls));
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Compute merged static styles from className string
|
|
126
|
+
*/
|
|
127
|
+
export function computeStaticStyles(stylesheet, classNameValue) {
|
|
128
|
+
if (!classNameValue || !stylesheet) return {};
|
|
129
|
+
|
|
130
|
+
const classes = classNameValue.trim().split(/\s+/).filter(Boolean);
|
|
131
|
+
let result = {};
|
|
132
|
+
|
|
133
|
+
for (const cls of classes) {
|
|
134
|
+
const styles = getStaticStylesFromClass(stylesheet, cls);
|
|
135
|
+
result = { ...result, ...styles };
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return result;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Convert JavaScript object to Babel AST
|
|
143
|
+
*/
|
|
144
|
+
export function objectToAST(t, obj) {
|
|
145
|
+
if (obj === null || obj === undefined) return t.nullLiteral();
|
|
146
|
+
|
|
147
|
+
if (Array.isArray(obj)) {
|
|
148
|
+
return t.arrayExpression(obj.map((item) => objectToAST(t, item)));
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (typeof obj === "object") {
|
|
152
|
+
return t.objectExpression(
|
|
153
|
+
Object.entries(obj).map(([key, value]) =>
|
|
154
|
+
t.objectProperty(
|
|
155
|
+
/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(key) ? t.identifier(key) : t.stringLiteral(key),
|
|
156
|
+
objectToAST(t, value),
|
|
157
|
+
),
|
|
158
|
+
),
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (typeof obj === "string") return t.stringLiteral(obj);
|
|
163
|
+
if (typeof obj === "number") return t.numericLiteral(obj);
|
|
164
|
+
if (typeof obj === "boolean") return t.booleanLiteral(obj);
|
|
165
|
+
|
|
166
|
+
return t.nullLiteral();
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Try to get static style info for an element
|
|
171
|
+
* Returns { staticStyles, hasInheritStyle, inlineStyleExpr } or null if not static
|
|
172
|
+
*/
|
|
173
|
+
export function tryGetStaticStyleInfo(path, state, t) {
|
|
174
|
+
const openingElement = path.node.openingElement;
|
|
175
|
+
|
|
176
|
+
const classNameAttr = openingElement.attributes.find(
|
|
177
|
+
(attr) => t.isJSXAttribute(attr) && attr.name?.name === "className",
|
|
178
|
+
);
|
|
179
|
+
|
|
180
|
+
// Check if className is static
|
|
181
|
+
if (!isStaticClassName(t, classNameAttr)) return null;
|
|
182
|
+
|
|
183
|
+
// Get stylesheet
|
|
184
|
+
const stylesheet = state.stylesheetData;
|
|
185
|
+
if (!stylesheet) return null;
|
|
186
|
+
|
|
187
|
+
const classNameValue = getStaticClassNameValue(t, classNameAttr);
|
|
188
|
+
if (!classNameValue) return null;
|
|
189
|
+
|
|
190
|
+
// Check if all classes are fully static
|
|
191
|
+
if (!areAllClassesStatic(stylesheet, classNameValue)) return null;
|
|
192
|
+
|
|
193
|
+
// Compute static styles from className
|
|
194
|
+
const staticStyles = computeStaticStyles(stylesheet, classNameValue);
|
|
195
|
+
|
|
196
|
+
// Get inheritStyle attribute (for mergeStyles call)
|
|
197
|
+
const inheritStyleAttr = openingElement.attributes.find(
|
|
198
|
+
(attr) => t.isJSXAttribute(attr) && attr.name?.name === "inheritStyle",
|
|
199
|
+
);
|
|
200
|
+
|
|
201
|
+
// Get style attribute
|
|
202
|
+
const styleAttr = openingElement.attributes.find(
|
|
203
|
+
(attr) => t.isJSXAttribute(attr) && attr.name?.name === "style",
|
|
204
|
+
);
|
|
205
|
+
|
|
206
|
+
return {
|
|
207
|
+
staticStyles,
|
|
208
|
+
inheritStyleAttr,
|
|
209
|
+
styleAttr,
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Generate mergeStyles(inheritStyle, staticStyles, inlineStyle) expression
|
|
215
|
+
*/
|
|
216
|
+
export function getStaticMergeExpression(path, state, t, staticInfo) {
|
|
217
|
+
const { staticStyles, inheritStyleAttr, styleAttr } = staticInfo;
|
|
218
|
+
|
|
219
|
+
// Get inheritStyle expression
|
|
220
|
+
const propInheritStyle = getMemoizedInheritStyleExpression(path, t);
|
|
221
|
+
const inheritStyleExpr = inheritStyleAttr?.value?.expression;
|
|
222
|
+
|
|
223
|
+
// Build inheritStyle array: [props.inheritStyle, explicitInheritStyle]
|
|
224
|
+
let inheritArg;
|
|
225
|
+
if (propInheritStyle || inheritStyleExpr) {
|
|
226
|
+
inheritArg = t.arrayExpression([
|
|
227
|
+
propInheritStyle || t.nullLiteral(),
|
|
228
|
+
inheritStyleExpr || t.nullLiteral(),
|
|
229
|
+
]);
|
|
230
|
+
} else {
|
|
231
|
+
inheritArg = t.nullLiteral();
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// Static styles as inline object
|
|
235
|
+
const staticArg =
|
|
236
|
+
Object.keys(staticStyles).length > 0 ? objectToAST(t, staticStyles) : t.nullLiteral();
|
|
237
|
+
|
|
238
|
+
// Inline style expression
|
|
239
|
+
const inlineArg = styleAttr?.value?.expression || t.nullLiteral();
|
|
240
|
+
|
|
241
|
+
// mergeStyles(inheritStyle, staticStyles, inlineStyle)
|
|
242
|
+
return t.callExpression(state.mergeStylesId, [inheritArg, staticArg, inlineArg]);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// ============================================================================
|
|
246
|
+
// InheritStyle helpers
|
|
247
|
+
// ============================================================================
|
|
248
|
+
|
|
249
|
+
const inheritStyleMemo = new WeakMap();
|
|
250
|
+
|
|
251
|
+
function getMemoizedInheritStyleExpression(path, t) {
|
|
252
|
+
let currentPath = path;
|
|
253
|
+
let funcPath = null;
|
|
254
|
+
while (currentPath && !funcPath) {
|
|
255
|
+
if (currentPath.isFunction()) {
|
|
256
|
+
funcPath = currentPath;
|
|
257
|
+
break;
|
|
258
|
+
}
|
|
259
|
+
currentPath = currentPath.parentPath;
|
|
260
|
+
}
|
|
261
|
+
if (!funcPath) return undefined;
|
|
262
|
+
|
|
263
|
+
if (inheritStyleMemo.has(funcPath.node)) {
|
|
264
|
+
return inheritStyleMemo.get(funcPath.node);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
let result;
|
|
268
|
+
const params = funcPath.node.params;
|
|
269
|
+
let parentPath = funcPath.parentPath;
|
|
270
|
+
|
|
271
|
+
if (
|
|
272
|
+
parentPath &&
|
|
273
|
+
parentPath.isCallExpression() &&
|
|
274
|
+
parentPath.node.callee &&
|
|
275
|
+
parentPath.node.callee.type === "Identifier" &&
|
|
276
|
+
["useMemo", "useCallback"].includes(parentPath.node.callee.name)
|
|
277
|
+
) {
|
|
278
|
+
result = undefined;
|
|
279
|
+
} else if (params.length === 0) {
|
|
280
|
+
funcPath.node.params = [t.identifier("props")];
|
|
281
|
+
result = t.memberExpression(t.identifier("props"), t.identifier("inheritStyle"), false, false);
|
|
282
|
+
} else if (params.length > 0) {
|
|
283
|
+
const firstParam = params[0];
|
|
284
|
+
if (t.isIdentifier(firstParam)) {
|
|
285
|
+
result = t.memberExpression(firstParam, t.identifier("inheritStyle"), false, false);
|
|
286
|
+
} else if (t.isObjectPattern(firstParam)) {
|
|
287
|
+
const restElement = firstParam.properties.find((p) => t.isRestElement(p));
|
|
288
|
+
if (restElement) {
|
|
289
|
+
result = t.memberExpression(
|
|
290
|
+
restElement.argument,
|
|
291
|
+
t.identifier("inheritStyle"),
|
|
292
|
+
false,
|
|
293
|
+
false,
|
|
294
|
+
);
|
|
295
|
+
} else {
|
|
296
|
+
const restProp = t.restElement(t.identifier("rest"));
|
|
297
|
+
firstParam.properties.push(restProp);
|
|
298
|
+
result = t.memberExpression(
|
|
299
|
+
t.identifier("rest"),
|
|
300
|
+
t.identifier("inheritStyle"),
|
|
301
|
+
false,
|
|
302
|
+
false,
|
|
303
|
+
);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
inheritStyleMemo.set(funcPath.node, result);
|
|
309
|
+
return result;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// ============================================================================
|
|
313
|
+
// Style expression generators (for dynamic/fallback cases)
|
|
314
|
+
// ============================================================================
|
|
315
|
+
|
|
316
|
+
export function getStyleExpression(path, state, t) {
|
|
317
|
+
const openingElement = path.node.openingElement;
|
|
318
|
+
const elementName = openingElement.name;
|
|
319
|
+
|
|
320
|
+
const propInheritStyle = getMemoizedInheritStyleExpression(path, t);
|
|
321
|
+
const inheritStyle = openingElement.attributes.find((attr) => attr.name?.name === "inheritStyle");
|
|
322
|
+
const className = openingElement.attributes.find((attr) => attr.name?.name === "className");
|
|
323
|
+
const style = openingElement.attributes.find((attr) => attr.name?.name === "style");
|
|
324
|
+
|
|
325
|
+
return t.callExpression(state.getStyleId, [
|
|
326
|
+
state.stylesheetId,
|
|
327
|
+
t.arrayExpression([
|
|
328
|
+
t.arrayExpression([
|
|
329
|
+
propInheritStyle || t.nullLiteral(),
|
|
330
|
+
(inheritStyle && inheritStyle.value.expression) || t.nullLiteral(),
|
|
331
|
+
]),
|
|
332
|
+
(className &&
|
|
333
|
+
(t.isStringLiteral(className.value)
|
|
334
|
+
? t.stringLiteral(className.value.value)
|
|
335
|
+
: className.value.expression)) ||
|
|
336
|
+
t.nullLiteral(),
|
|
337
|
+
(style && style.value.expression) || t.nullLiteral(),
|
|
338
|
+
t.isJSXIdentifier(elementName)
|
|
339
|
+
? t.stringLiteral(elementName.name)
|
|
340
|
+
: t.isJSXMemberExpression(elementName)
|
|
341
|
+
? t.stringLiteral(`${elementName.object.name}.${elementName.property.name}`)
|
|
342
|
+
: t.stringLiteral("Unknown"),
|
|
343
|
+
]),
|
|
344
|
+
]);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
export function getInheritStyleExpression(path, state, t) {
|
|
348
|
+
return t.callExpression(state.getInheritStyleId, [getStyleExpression(path, state, t)]);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
export function getRootInheritStyleExpression(path, t) {
|
|
352
|
+
const propInheritStyle = getMemoizedInheritStyleExpression(path, t);
|
|
353
|
+
return propInheritStyle || t.identifier("undefined");
|
|
354
|
+
}
|