@colorye/react-native-css 0.3.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 +198 -0
- package/crates/transformer/index.js +105 -0
- package/crates/transformer/transformer.darwin-arm64.node +0 -0
- package/crates/transformer/transformer.node +0 -0
- package/dist/babel.js +208 -0
- package/dist/exported-stylesheet.json +1 -0
- package/dist/features/build-transform.js +575 -0
- package/dist/features/css-calc.js +539 -0
- package/dist/features/css-media.js +77 -0
- package/dist/features/css-transform.js +426 -0
- package/dist/features/css-vars.js +153 -0
- package/dist/features/stylesheet.js +45 -0
- package/dist/index.d.ts +89 -0
- package/dist/index.js +60 -0
- package/dist/interop.js +260 -0
- package/dist/transformer-runtime.js +274 -0
- package/dist/transformer.js +100 -0
- package/dist/utils/babel.js +363 -0
- package/dist/utils/css.js +263 -0
- package/dist/utils/helper.js +11 -0
- package/package.json +51 -0
- package/src/babel.js +271 -0
- package/src/exported-stylesheet.json +1 -0
- package/src/features/build-transform.js +536 -0
- package/src/features/css-calc.js +490 -0
- package/src/features/css-media.js +78 -0
- package/src/features/css-transform.js +446 -0
- package/src/features/css-vars.js +138 -0
- package/src/features/stylesheet.js +29 -0
- package/src/index.d.ts +89 -0
- package/src/index.js +29 -0
- package/src/interop.js +269 -0
- package/src/transformer-runtime.js +241 -0
- package/src/transformer.js +87 -0
- package/src/utils/babel.js +425 -0
- package/src/utils/css.js +221 -0
- package/src/utils/helper.js +3 -0
- package/types.d.ts +47 -0
package/src/index.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export {
|
|
2
|
+
GroupContext,
|
|
3
|
+
InheritContext,
|
|
4
|
+
cssInterop,
|
|
5
|
+
getGlobalStylesheet,
|
|
6
|
+
remapProps,
|
|
7
|
+
setGlobalStylesheet,
|
|
8
|
+
} from "./interop.js";
|
|
9
|
+
export { default as Runtime } from "./transformer-runtime.js";
|
|
10
|
+
|
|
11
|
+
import {
|
|
12
|
+
GroupContext,
|
|
13
|
+
InheritContext,
|
|
14
|
+
cssInterop,
|
|
15
|
+
getGlobalStylesheet,
|
|
16
|
+
remapProps,
|
|
17
|
+
setGlobalStylesheet,
|
|
18
|
+
} from "./interop.js";
|
|
19
|
+
import Runtime from "./transformer-runtime.js";
|
|
20
|
+
|
|
21
|
+
export default {
|
|
22
|
+
cssInterop,
|
|
23
|
+
remapProps,
|
|
24
|
+
setGlobalStylesheet,
|
|
25
|
+
getGlobalStylesheet,
|
|
26
|
+
GroupContext,
|
|
27
|
+
InheritContext,
|
|
28
|
+
Runtime,
|
|
29
|
+
};
|
package/src/interop.js
ADDED
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
import React, { createContext, forwardRef, useContext } from "react";
|
|
2
|
+
import Runtime from "./transformer-runtime.js";
|
|
3
|
+
|
|
4
|
+
export const InheritContext = createContext(undefined);
|
|
5
|
+
export const GroupContext = createContext({ pressed: false, hovered: false, focus: false });
|
|
6
|
+
|
|
7
|
+
let globalStylesheet = {};
|
|
8
|
+
|
|
9
|
+
try {
|
|
10
|
+
const raw = require("./exported-stylesheet.json");
|
|
11
|
+
let current = raw;
|
|
12
|
+
while (current?.default && typeof current.default === "object" && !current[":root"]) {
|
|
13
|
+
current = current.default;
|
|
14
|
+
}
|
|
15
|
+
globalStylesheet = current || {};
|
|
16
|
+
} catch {
|
|
17
|
+
// Fallback to empty if not yet compiled
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function setGlobalStylesheet(sheet) {
|
|
21
|
+
if (sheet && typeof sheet === "object") {
|
|
22
|
+
let current = sheet;
|
|
23
|
+
while (current?.default && typeof current.default === "object" && !current[":root"]) {
|
|
24
|
+
current = current.default;
|
|
25
|
+
}
|
|
26
|
+
globalStylesheet = current;
|
|
27
|
+
Runtime.clearCache?.();
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function getGlobalStylesheet() {
|
|
32
|
+
return globalStylesheet;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* cssInterop(Component, mapping)
|
|
37
|
+
*
|
|
38
|
+
* Wraps any React Native or third-party component to support className mapping.
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* cssInterop(FlashList, {
|
|
42
|
+
* className: "style",
|
|
43
|
+
* contentContainerClassName: "contentContainerStyle",
|
|
44
|
+
* });
|
|
45
|
+
*
|
|
46
|
+
* @param {React.ComponentType} Component
|
|
47
|
+
* @param {Record<string, string>} mapping Mapping of class props to style props
|
|
48
|
+
* @returns {React.ForwardRefExoticComponent}
|
|
49
|
+
*/
|
|
50
|
+
export function cssInterop(Component, mapping = { className: "style" }) {
|
|
51
|
+
const InteropComponent = forwardRef((props, ref) => {
|
|
52
|
+
const parentInherit = useContext(InheritContext);
|
|
53
|
+
const parentGroup = useContext(GroupContext);
|
|
54
|
+
const inheritStyle = props.inheritStyle || parentInherit;
|
|
55
|
+
const [groupPressed, setGroupPressed] = React.useState(false);
|
|
56
|
+
|
|
57
|
+
const nextProps = { ...props };
|
|
58
|
+
if (ref) {
|
|
59
|
+
nextProps.ref = ref;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const sheet = getGlobalStylesheet();
|
|
63
|
+
let currentInherit = parentInherit;
|
|
64
|
+
let isGroupProvider = false;
|
|
65
|
+
|
|
66
|
+
// Check if this component acts as a group container
|
|
67
|
+
for (const classProp of Object.keys(mapping)) {
|
|
68
|
+
const val = props[classProp];
|
|
69
|
+
if (typeof val === "string" && (val === "group" || val.split(/\s+/).includes("group"))) {
|
|
70
|
+
isGroupProvider = true;
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (isGroupProvider) {
|
|
76
|
+
const originalOnPressIn = props.onPressIn;
|
|
77
|
+
const originalOnPressOut = props.onPressOut;
|
|
78
|
+
nextProps.onPressIn = (e) => {
|
|
79
|
+
setGroupPressed(true);
|
|
80
|
+
originalOnPressIn?.(e);
|
|
81
|
+
};
|
|
82
|
+
nextProps.onPressOut = (e) => {
|
|
83
|
+
setGroupPressed(false);
|
|
84
|
+
originalOnPressOut?.(e);
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
for (const [classProp, styleProp] of Object.entries(mapping)) {
|
|
89
|
+
const classValue = props[classProp];
|
|
90
|
+
const hasClass = typeof classValue === "string" && classValue.length > 0;
|
|
91
|
+
const isPrimaryStyle = styleProp === "style";
|
|
92
|
+
const hasInherit = isPrimaryStyle && Boolean(inheritStyle);
|
|
93
|
+
|
|
94
|
+
if (hasClass) {
|
|
95
|
+
const hasActiveVariants = /(^|\s)(active|pressed):/.test(classValue);
|
|
96
|
+
const hasDisabledVariants = /(^|\s)disabled:/.test(classValue);
|
|
97
|
+
const hasGroupActiveVariants = /(^|\s)group-(active|pressed):/.test(classValue);
|
|
98
|
+
|
|
99
|
+
const isDisabled = Boolean(props.disabled || props.accessibilityState?.disabled);
|
|
100
|
+
|
|
101
|
+
if ((hasActiveVariants || hasDisabledVariants || hasGroupActiveVariants) && isPrimaryStyle) {
|
|
102
|
+
const classes = classValue.trim().split(/\s+/);
|
|
103
|
+
const normalClasses = [];
|
|
104
|
+
const activeClasses = [];
|
|
105
|
+
const disabledClasses = [];
|
|
106
|
+
const groupActiveClasses = [];
|
|
107
|
+
|
|
108
|
+
for (const cls of classes) {
|
|
109
|
+
if (cls.startsWith("active:") || cls.startsWith("pressed:")) {
|
|
110
|
+
const baseCls = cls.replace(/^(active|pressed):/, "");
|
|
111
|
+
activeClasses.push(baseCls);
|
|
112
|
+
} else if (cls.startsWith("disabled:")) {
|
|
113
|
+
const baseCls = cls.replace(/^disabled:/, "");
|
|
114
|
+
disabledClasses.push(baseCls);
|
|
115
|
+
} else if (cls.startsWith("group-active:") || cls.startsWith("group-pressed:")) {
|
|
116
|
+
const baseCls = cls.replace(/^group-(active|pressed):/, "");
|
|
117
|
+
groupActiveClasses.push(baseCls);
|
|
118
|
+
} else {
|
|
119
|
+
normalClasses.push(cls);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const normalStyle = Runtime.getStyle(sheet, [
|
|
124
|
+
hasInherit ? inheritStyle : undefined,
|
|
125
|
+
normalClasses.join(" "),
|
|
126
|
+
typeof props[styleProp] === "object" ? props[styleProp] : undefined,
|
|
127
|
+
]);
|
|
128
|
+
|
|
129
|
+
const activeStyle = activeClasses.length > 0
|
|
130
|
+
? Runtime.getStyle(sheet, [undefined, activeClasses.join(" "), undefined])
|
|
131
|
+
: undefined;
|
|
132
|
+
|
|
133
|
+
const disabledStyle = disabledClasses.length > 0
|
|
134
|
+
? Runtime.getStyle(sheet, [undefined, disabledClasses.join(" "), undefined])
|
|
135
|
+
: undefined;
|
|
136
|
+
|
|
137
|
+
const groupActiveStyle = (hasGroupActiveVariants && parentGroup.pressed && groupActiveClasses.length > 0)
|
|
138
|
+
? Runtime.getStyle(sheet, [undefined, groupActiveClasses.join(" "), undefined])
|
|
139
|
+
: undefined;
|
|
140
|
+
|
|
141
|
+
if (hasActiveVariants || typeof props[styleProp] === "function") {
|
|
142
|
+
nextProps[styleProp] = (state) => {
|
|
143
|
+
const isPressed = (state && state.pressed) || false;
|
|
144
|
+
const userStyle = typeof props[styleProp] === "function" ? props[styleProp](state) : null;
|
|
145
|
+
const currentStyles = [normalStyle, groupActiveStyle];
|
|
146
|
+
|
|
147
|
+
if (isPressed && !isDisabled && activeStyle) {
|
|
148
|
+
currentStyles.push(activeStyle);
|
|
149
|
+
}
|
|
150
|
+
if (isDisabled && disabledStyle) {
|
|
151
|
+
currentStyles.push(disabledStyle);
|
|
152
|
+
}
|
|
153
|
+
if (userStyle) {
|
|
154
|
+
currentStyles.push(userStyle);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return currentStyles.filter(Boolean);
|
|
158
|
+
};
|
|
159
|
+
} else {
|
|
160
|
+
const currentStyles = [
|
|
161
|
+
normalStyle,
|
|
162
|
+
groupActiveStyle,
|
|
163
|
+
isDisabled ? disabledStyle : undefined,
|
|
164
|
+
typeof props[styleProp] === "object" ? props[styleProp] : undefined,
|
|
165
|
+
].filter(Boolean);
|
|
166
|
+
nextProps[styleProp] =
|
|
167
|
+
currentStyles.length === 1
|
|
168
|
+
? currentStyles[0]
|
|
169
|
+
: currentStyles.length > 1
|
|
170
|
+
? currentStyles
|
|
171
|
+
: undefined;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const inheritable = Runtime.getInheritStyle(normalStyle);
|
|
175
|
+
if (inheritable) {
|
|
176
|
+
currentInherit = parentInherit
|
|
177
|
+
? { ...parentInherit, ...inheritable }
|
|
178
|
+
: inheritable;
|
|
179
|
+
}
|
|
180
|
+
} else {
|
|
181
|
+
// Dynamic className present - runtime resolution
|
|
182
|
+
const computedStyle = Runtime.getStyle(sheet, [
|
|
183
|
+
hasInherit ? inheritStyle : undefined,
|
|
184
|
+
classValue,
|
|
185
|
+
props[styleProp],
|
|
186
|
+
]);
|
|
187
|
+
|
|
188
|
+
if (computedStyle !== undefined) {
|
|
189
|
+
nextProps[styleProp] = computedStyle;
|
|
190
|
+
|
|
191
|
+
if (isPrimaryStyle) {
|
|
192
|
+
const inheritable = Runtime.getInheritStyle(computedStyle);
|
|
193
|
+
if (inheritable) {
|
|
194
|
+
currentInherit = parentInherit
|
|
195
|
+
? { ...parentInherit, ...inheritable }
|
|
196
|
+
: inheritable;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
delete nextProps[classProp];
|
|
202
|
+
} else if (isPrimaryStyle) {
|
|
203
|
+
// Static inlined style or plain style prop with inheritance
|
|
204
|
+
const ownStyle = props[styleProp];
|
|
205
|
+
|
|
206
|
+
if (typeof ownStyle === "function") {
|
|
207
|
+
if (hasInherit) {
|
|
208
|
+
nextProps[styleProp] = (state) => {
|
|
209
|
+
const res = ownStyle(state);
|
|
210
|
+
return [inheritStyle, res];
|
|
211
|
+
};
|
|
212
|
+
} else {
|
|
213
|
+
nextProps[styleProp] = ownStyle;
|
|
214
|
+
}
|
|
215
|
+
} else {
|
|
216
|
+
const flatOwnStyle = ownStyle ? Runtime.getFlattenStyle(ownStyle) : undefined;
|
|
217
|
+
|
|
218
|
+
if (hasInherit) {
|
|
219
|
+
const merged = Runtime.mergeStyles(inheritStyle, flatOwnStyle, undefined);
|
|
220
|
+
if (merged !== undefined) {
|
|
221
|
+
nextProps[styleProp] = merged;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Inheritable styles come from either the component's own style or inherited from parent
|
|
226
|
+
const combinedForInherit = hasInherit
|
|
227
|
+
? Runtime.mergeStyles(inheritStyle, flatOwnStyle, undefined)
|
|
228
|
+
: flatOwnStyle;
|
|
229
|
+
const ownInheritable = Runtime.getInheritStyle(combinedForInherit);
|
|
230
|
+
|
|
231
|
+
if (ownInheritable) {
|
|
232
|
+
currentInherit = parentInherit
|
|
233
|
+
? { ...parentInherit, ...ownInheritable }
|
|
234
|
+
: ownInheritable;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
delete nextProps.inheritStyle;
|
|
241
|
+
|
|
242
|
+
let element = React.createElement(Component, nextProps);
|
|
243
|
+
|
|
244
|
+
if (isGroupProvider) {
|
|
245
|
+
element = React.createElement(
|
|
246
|
+
GroupContext.Provider,
|
|
247
|
+
{ value: { ...parentGroup, pressed: groupPressed } },
|
|
248
|
+
element,
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
if (currentInherit && currentInherit !== parentInherit) {
|
|
253
|
+
return React.createElement(InheritContext.Provider, { value: currentInherit }, element);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
return element;
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
const name = Component.displayName || Component.name || "Component";
|
|
260
|
+
InteropComponent.displayName = `CssInterop(${name})`;
|
|
261
|
+
|
|
262
|
+
return InteropComponent;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
export function remapProps(Component, mapping) {
|
|
266
|
+
return cssInterop(Component, mapping);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
export default cssInterop;
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
let RN = {};
|
|
2
|
+
try {
|
|
3
|
+
RN = require("react-native");
|
|
4
|
+
} catch {
|
|
5
|
+
// Safe in Node/Babel build environment
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const Appearance = RN.Appearance || { getColorScheme: () => "light" };
|
|
9
|
+
const Dimensions = RN.Dimensions || { get: () => ({ width: 375, height: 812 }) };
|
|
10
|
+
|
|
11
|
+
// ============================================================================
|
|
12
|
+
// Constants
|
|
13
|
+
// ============================================================================
|
|
14
|
+
const INHERIT_PROPERTIES = [
|
|
15
|
+
"color",
|
|
16
|
+
"fontFamily",
|
|
17
|
+
"fontSize",
|
|
18
|
+
"fontStyle",
|
|
19
|
+
"fontWeight",
|
|
20
|
+
"fontVariant",
|
|
21
|
+
"letterSpacing",
|
|
22
|
+
"lineHeight",
|
|
23
|
+
"textAlign",
|
|
24
|
+
"textTransform",
|
|
25
|
+
];
|
|
26
|
+
|
|
27
|
+
// ============================================================================
|
|
28
|
+
// Cached Dimensions and Appearance
|
|
29
|
+
// ============================================================================
|
|
30
|
+
let cachedDimensions = null;
|
|
31
|
+
let cachedColorScheme = null;
|
|
32
|
+
let TRANSFORM_CACHE = {};
|
|
33
|
+
let currentCacheKey = null;
|
|
34
|
+
|
|
35
|
+
function getDimensions() {
|
|
36
|
+
if (!cachedDimensions) {
|
|
37
|
+
try {
|
|
38
|
+
cachedDimensions = Dimensions?.get?.("window") || { width: 375, height: 812 };
|
|
39
|
+
} catch {
|
|
40
|
+
cachedDimensions = { width: 375, height: 812 };
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return cachedDimensions;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function getColorScheme() {
|
|
47
|
+
if (cachedColorScheme === null) {
|
|
48
|
+
try {
|
|
49
|
+
cachedColorScheme = Appearance?.getColorScheme?.() || "light";
|
|
50
|
+
} catch {
|
|
51
|
+
cachedColorScheme = "light";
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return cachedColorScheme;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function getCacheKey() {
|
|
58
|
+
const { width, height } = getDimensions();
|
|
59
|
+
const colorScheme = getColorScheme();
|
|
60
|
+
return `${width}x${height}:${colorScheme}`;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function invalidateCache() {
|
|
64
|
+
cachedDimensions = null;
|
|
65
|
+
cachedColorScheme = null;
|
|
66
|
+
TRANSFORM_CACHE = {};
|
|
67
|
+
currentCacheKey = null;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function clearCache() {
|
|
71
|
+
TRANSFORM_CACHE = {};
|
|
72
|
+
currentCacheKey = null;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
try {
|
|
76
|
+
Dimensions?.addEventListener?.("change", invalidateCache);
|
|
77
|
+
Appearance?.addChangeListener?.(invalidateCache);
|
|
78
|
+
} catch {}
|
|
79
|
+
|
|
80
|
+
// ============================================================================
|
|
81
|
+
// Flatten Style
|
|
82
|
+
// ============================================================================
|
|
83
|
+
function getFlattenStyle(declarations) {
|
|
84
|
+
if (!Array.isArray(declarations)) {
|
|
85
|
+
return declarations;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const result = {};
|
|
89
|
+
|
|
90
|
+
function merge(item) {
|
|
91
|
+
if (!item) return;
|
|
92
|
+
if (Array.isArray(item)) {
|
|
93
|
+
for (let i = 0; i < item.length; i++) {
|
|
94
|
+
merge(item[i]);
|
|
95
|
+
}
|
|
96
|
+
} else {
|
|
97
|
+
Object.assign(result, item);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
for (let i = 0; i < declarations.length; i++) {
|
|
102
|
+
merge(declarations[i]);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const borderStyles = ["borderBottomStyle", "borderTopStyle", "borderLeftStyle", "borderRightStyle"];
|
|
106
|
+
for (const bs of borderStyles) {
|
|
107
|
+
if (result[bs] !== undefined) {
|
|
108
|
+
if (result.borderStyle === undefined) {
|
|
109
|
+
result.borderStyle = ["solid", "dotted", "dashed"].includes(result[bs]) ? result[bs] : "solid";
|
|
110
|
+
}
|
|
111
|
+
delete result[bs];
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
if (result.borderStyle !== undefined) {
|
|
115
|
+
if (typeof result.borderStyle !== "string" || !["solid", "dotted", "dashed"].includes(result.borderStyle)) {
|
|
116
|
+
delete result.borderStyle;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return Object.keys(result).length > 0 ? result : undefined;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// ============================================================================
|
|
124
|
+
// Main Native Rust Stylesheet Transform
|
|
125
|
+
// ============================================================================
|
|
126
|
+
function transformStyles(stylesheet, classNames) {
|
|
127
|
+
if (!stylesheet || !classNames) return undefined;
|
|
128
|
+
if (stylesheet.default && typeof stylesheet.default === "object" && !stylesheet[":root"]) {
|
|
129
|
+
stylesheet = stylesheet.default;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const { width, height } = getDimensions();
|
|
133
|
+
const colorScheme = getColorScheme();
|
|
134
|
+
|
|
135
|
+
const cacheKey = getCacheKey();
|
|
136
|
+
if (cacheKey !== currentCacheKey) {
|
|
137
|
+
TRANSFORM_CACHE = {};
|
|
138
|
+
currentCacheKey = cacheKey;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (TRANSFORM_CACHE[classNames] !== undefined) {
|
|
142
|
+
return TRANSFORM_CACHE[classNames];
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const classes = classNames.trim().split(/\s+/);
|
|
146
|
+
const resolved = {};
|
|
147
|
+
|
|
148
|
+
for (const cls of classes) {
|
|
149
|
+
if (!cls) continue;
|
|
150
|
+
const entry = stylesheet[cls];
|
|
151
|
+
if (!entry) continue;
|
|
152
|
+
|
|
153
|
+
if (entry._static) {
|
|
154
|
+
Object.assign(resolved, entry._static);
|
|
155
|
+
} else if (entry._dynamic) {
|
|
156
|
+
Object.assign(resolved, entry._dynamic);
|
|
157
|
+
} else if (typeof entry === "object") {
|
|
158
|
+
Object.assign(resolved, entry);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const result = Object.keys(resolved).length > 0 ? resolved : undefined;
|
|
163
|
+
TRANSFORM_CACHE[classNames] = result;
|
|
164
|
+
return result;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// ============================================================================
|
|
168
|
+
// Inherit Style
|
|
169
|
+
// ============================================================================
|
|
170
|
+
function getInheritStyle(declarations) {
|
|
171
|
+
if (!declarations) return undefined;
|
|
172
|
+
|
|
173
|
+
const inheritDeclarations = {};
|
|
174
|
+
for (const key of INHERIT_PROPERTIES) {
|
|
175
|
+
if (declarations[key] !== undefined) {
|
|
176
|
+
inheritDeclarations[key] = declarations[key];
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
return Object.keys(inheritDeclarations).length > 0 ? inheritDeclarations : undefined;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// ============================================================================
|
|
184
|
+
// Main Entry Point
|
|
185
|
+
// ============================================================================
|
|
186
|
+
function getStyle(stylesheet, [inheritStyle, className, style]) {
|
|
187
|
+
const inherited = getInheritStyle(getFlattenStyle(inheritStyle));
|
|
188
|
+
const transformed = transformStyles(stylesheet, className);
|
|
189
|
+
const result = getFlattenStyle([inherited, transformed, style]);
|
|
190
|
+
return result;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// ============================================================================
|
|
194
|
+
// Lightweight Merge for Static Styles
|
|
195
|
+
// ============================================================================
|
|
196
|
+
function mergeStyles(inheritStyle, staticStyles, inlineStyle) {
|
|
197
|
+
if (!inheritStyle && !inlineStyle) {
|
|
198
|
+
return staticStyles;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
let inherited;
|
|
202
|
+
if (inheritStyle) {
|
|
203
|
+
const flatInherit = getFlattenStyle(inheritStyle);
|
|
204
|
+
if (flatInherit) {
|
|
205
|
+
inherited = {};
|
|
206
|
+
for (const key of INHERIT_PROPERTIES) {
|
|
207
|
+
if (flatInherit[key] !== undefined) {
|
|
208
|
+
inherited[key] = flatInherit[key];
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
if (Object.keys(inherited).length === 0) {
|
|
212
|
+
inherited = undefined;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
if (!inherited && !inlineStyle) {
|
|
218
|
+
return staticStyles;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
const result = {};
|
|
222
|
+
if (inherited) Object.assign(result, inherited);
|
|
223
|
+
if (staticStyles) {
|
|
224
|
+
for (const key in staticStyles) {
|
|
225
|
+
if (!key.startsWith("--")) {
|
|
226
|
+
result[key] = staticStyles[key];
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
if (inlineStyle) Object.assign(result, inlineStyle);
|
|
231
|
+
|
|
232
|
+
return Object.keys(result).length > 0 ? result : undefined;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
export default {
|
|
236
|
+
getFlattenStyle,
|
|
237
|
+
getStyle,
|
|
238
|
+
getInheritStyle,
|
|
239
|
+
mergeStyles,
|
|
240
|
+
clearCache,
|
|
241
|
+
};
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import Stylesheet from "./features/stylesheet";
|
|
4
|
+
import { parseStylesheetWithLightning } from "./utils/css";
|
|
5
|
+
|
|
6
|
+
export function getStylesheet(css, filename) {
|
|
7
|
+
const rawStylesheet = parseStylesheetWithLightning(css);
|
|
8
|
+
const stylesheet = new Stylesheet();
|
|
9
|
+
stylesheet.setRawStylesheet(rawStylesheet);
|
|
10
|
+
|
|
11
|
+
const jsonContent = stylesheet.toJSON();
|
|
12
|
+
writeStylesheetJSON(jsonContent, filename);
|
|
13
|
+
|
|
14
|
+
return jsonContent;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function writeStylesheetJSON(content, filename) {
|
|
18
|
+
try {
|
|
19
|
+
const distPath = path.join(__dirname, "exported-stylesheet.json");
|
|
20
|
+
fs.writeFileSync(distPath, content, { mode: 0o755 });
|
|
21
|
+
|
|
22
|
+
const srcPath = path.resolve(__dirname, "../src/exported-stylesheet.json");
|
|
23
|
+
if (fs.existsSync(path.dirname(srcPath))) {
|
|
24
|
+
fs.writeFileSync(srcPath, content, { mode: 0o755 });
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (filename) {
|
|
28
|
+
fs.writeFileSync(`${filename}.json`, content, { mode: 0o755 });
|
|
29
|
+
}
|
|
30
|
+
} catch {
|
|
31
|
+
// Silently fail - Babel will fall back to runtime
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function transform({ src, filename, options }) {
|
|
36
|
+
const projectRoot = options && options.projectRoot ? options.projectRoot : process.cwd();
|
|
37
|
+
|
|
38
|
+
const resolveTransformer = (() => {
|
|
39
|
+
try {
|
|
40
|
+
return require("@expo/metro-config/babel-transformer");
|
|
41
|
+
} catch {
|
|
42
|
+
try {
|
|
43
|
+
return require("@react-native/metro-babel-transformer");
|
|
44
|
+
} catch {
|
|
45
|
+
try {
|
|
46
|
+
return require("metro-react-native-babel-transformer");
|
|
47
|
+
} catch {
|
|
48
|
+
const resolveOptions = { paths: [projectRoot] };
|
|
49
|
+
try {
|
|
50
|
+
const resolved = require.resolve("@expo/metro-config/babel-transformer", resolveOptions);
|
|
51
|
+
return eval("require")(resolved);
|
|
52
|
+
} catch {
|
|
53
|
+
try {
|
|
54
|
+
const resolved = require.resolve("@react-native/metro-babel-transformer", resolveOptions);
|
|
55
|
+
return eval("require")(resolved);
|
|
56
|
+
} catch {
|
|
57
|
+
try {
|
|
58
|
+
const resolved = require.resolve("metro-react-native-babel-transformer", resolveOptions);
|
|
59
|
+
return eval("require")(resolved);
|
|
60
|
+
} catch {
|
|
61
|
+
throw new Error(
|
|
62
|
+
"Failed to load any upstream babel-transformer. Please ensure either '@expo/metro-config', '@react-native/metro-babel-transformer', or 'metro-react-native-babel-transformer' is installed.",
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
})();
|
|
71
|
+
|
|
72
|
+
if (filename.endsWith(".css")) {
|
|
73
|
+
const jsonContent = getStylesheet(src, filename);
|
|
74
|
+
return resolveTransformer.transform({
|
|
75
|
+
src: `const sheet = ${jsonContent};\nmodule.exports = sheet;\nmodule.exports.default = sheet;\nmodule.exports.__esModule = true;`,
|
|
76
|
+
filename,
|
|
77
|
+
options,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
return resolveTransformer.transform({ src, filename, options });
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export default {
|
|
84
|
+
transform,
|
|
85
|
+
getStylesheet,
|
|
86
|
+
writeStylesheetJSON,
|
|
87
|
+
};
|