Skip to content

Commit b6a94a9

Browse files
authored
Merge branch 'main' into 10-02-feat_add_runtime_color-mix_
2 parents 85e0210 + 7cd11a8 commit b6a94a9

8 files changed

Lines changed: 124 additions & 39 deletions

File tree

example/src/App.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Text, View } from "react-native";
1+
import { Button, Text, View } from "react-native";
22

33
import { StatusBar } from "expo-status-bar";
44

@@ -10,6 +10,7 @@ export default function App() {
1010
<Text className="text-red-800 text-2xl font-bold animate-bounce">
1111
Hello world!!!
1212
</Text>
13+
<Button title="test2" className="text-red-500" />
1314
<StatusBar style="auto" />
1415
</View>
1516
);

src/__tests__/native/container-queries.test.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ test("container query width", () => {
107107
},
108108
});
109109

110-
expect(parent.props.style).toStrictEqual([{ width: 200 }, { width: 500 }]);
110+
expect(parent.props.style).toStrictEqual({ width: 500 });
111111

112112
expect(child.props.style).toStrictEqual({
113113
color: "#00f",

src/__tests__/native/specificity.test.tsx

Lines changed: 5 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,7 @@ test("inline styles", () => {
1616
/>,
1717
).getByTestId(testID);
1818

19-
expect(component.props.style).toStrictEqual([
20-
{ backgroundColor: "#f00" },
21-
{ backgroundColor: "blue" },
22-
]);
19+
expect(component.props.style).toStrictEqual({ backgroundColor: "blue" });
2320
});
2421

2522
test("specificity order", () => {
@@ -60,10 +57,7 @@ test("important - requires sorting", () => {
6057
<Text testID={testID} className="blue red" />,
6158
).getByTestId(testID);
6259

63-
expect(component.props.style).toStrictEqual([
64-
{ color: "#f00" },
65-
{ color: "#00f" },
66-
]);
60+
expect(component.props.style).toStrictEqual({ color: "#00f" });
6761
});
6862

6963
test("important - inline", () => {
@@ -79,10 +73,7 @@ test("important - inline", () => {
7973
/>,
8074
).getByTestId(testID);
8175

82-
expect(component.props.style).toStrictEqual([
83-
{ backgroundColor: "red" },
84-
{ backgroundColor: "#00f" },
85-
]);
76+
expect(component.props.style).toStrictEqual({ backgroundColor: "#00f" });
8677
});
8778

8879
test("important - modifiers", () => {
@@ -96,17 +87,11 @@ test("important - modifiers", () => {
9687
<Text testID={testID} className="blue red" />,
9788
).getByTestId(testID);
9889

99-
expect(component.props.style).toStrictEqual([
100-
{ color: "#f00" },
101-
{ color: "#00f" },
102-
]);
90+
expect(component.props.style).toStrictEqual({ color: "#00f" });
10391

10492
fireEvent(component, "hoverIn");
10593

106-
expect(component.props.style).toStrictEqual([
107-
{ color: "#008000" },
108-
{ color: "#00f" },
109-
]);
94+
expect(component.props.style).toStrictEqual({ color: "#00f" });
11095
});
11196

11297
test("passThrough - inline", () => {

src/compiler/lightningcss-loader.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/* eslint-disable @typescript-eslint/no-require-imports */
12
export function lightningcssLoader() {
23
let lightningcssPath: string | undefined;
34

@@ -28,11 +29,29 @@ export function lightningcssLoader() {
2829
);
2930
}
3031

31-
// eslint-disable-next-line @typescript-eslint/no-require-imports
3232
const { transform: lightningcss, Features } = require(
3333
lightningcssPath,
3434
) as typeof import("lightningcss");
3535

36+
try {
37+
const lightningcssPackageJSONPath = require.resolve("../../package.json", {
38+
paths: [lightningcssPath],
39+
});
40+
41+
const packageJSON = require(lightningcssPackageJSONPath) as Record<
42+
string,
43+
unknown
44+
>;
45+
46+
if (packageJSON.version === "1.30.2") {
47+
throw new Error(
48+
"[react-native-css] lightningcss version 1.30.2 has a critical bug that breaks compilation. Please pin the version of lightningcss to 1.30.1; or try upgrading.",
49+
);
50+
}
51+
} catch {
52+
// Intentionally left empty
53+
}
54+
3655
return {
3756
lightningcss,
3857
Features,

src/native/react/useNativeCss.ts

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -172,29 +172,36 @@ export function useNativeCss(
172172
export function mappingToConfig(mapping: StyledConfiguration<any>) {
173173
return Object.entries(mapping).flatMap(([key, value]): Config => {
174174
if (value === true) {
175-
return { source: key, target: key };
175+
return {
176+
source: key,
177+
target: key,
178+
};
176179
} else if (value === false) {
177180
return { source: key, target: false };
178181
} else if (typeof value === "string") {
179182
return { source: key, target: value.split(".") };
180183
} else if (typeof value === "object") {
184+
const nativeStyleMapping = value.nativeStyleMapping as
185+
| Record<string, string>
186+
| undefined;
187+
181188
if (Array.isArray(value)) {
182-
return { source: key, target: value };
189+
return { source: key, target: value, nativeStyleMapping };
183190
}
184191

185192
if ("target" in value) {
186193
if (value.target === false) {
187-
return { source: key, target: false };
194+
return { source: key, target: false, nativeStyleMapping };
188195
} else if (typeof value.target === "string") {
189196
const target = value.target.split(".");
190197

191198
if (target.length === 1) {
192-
return { source: key, target: target[0]! };
199+
return { source: key, target: target[0]!, nativeStyleMapping };
193200
} else {
194-
return { source: key, target };
201+
return { source: key, target, nativeStyleMapping };
195202
}
196203
} else if (Array.isArray(value.target)) {
197-
return { source: key, target: value.target };
204+
return { source: key, target: value.target, nativeStyleMapping };
198205
}
199206
}
200207
}

src/native/styles/index.ts

Lines changed: 72 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,19 @@ export function getStyledProps(
4949
const styledProps = state.stylesObs?.get(state.styleEffect);
5050

5151
for (const config of state.configs) {
52-
result = deepMergeConfig(config, styledProps?.normal, inline, true);
52+
result = deepMergeConfig(
53+
config,
54+
nativeStyleMapping(config, styledProps?.normal),
55+
inline,
56+
true,
57+
);
5358

5459
if (styledProps?.important) {
55-
result = deepMergeConfig(config, result, styledProps.important);
60+
result = deepMergeConfig(
61+
config,
62+
result,
63+
nativeStyleMapping(config, styledProps.important),
64+
);
5665
}
5766

5867
// Apply the handlers
@@ -122,11 +131,11 @@ function deepMergeConfig(
122131
right: Record<string, any> | undefined | null,
123132
rightIsInline = false,
124133
) {
125-
if (!config.target || !right) {
134+
if (!right) {
126135
return { ...left };
127136
}
128137

129-
let result = Object.assign({}, left, right);
138+
let result = config.target ? Object.assign({}, left, right) : { ...left };
130139

131140
if (
132141
right &&
@@ -140,7 +149,7 @@ function deepMergeConfig(
140149
/**
141150
* If target is a path, deep merge until we get to the last key
142151
*/
143-
if (Array.isArray(config.target) && config.target.length > 1) {
152+
if (Array.isArray(config.target)) {
144153
for (let i = 0; i < config.target.length - 1; i++) {
145154
const key = config.target[i];
146155

@@ -159,11 +168,9 @@ function deepMergeConfig(
159168
return result;
160169
}
161170

162-
const target = Array.isArray(config.target)
163-
? config.target[0]
164-
: config.target;
171+
const target = config.target;
165172

166-
if (target === undefined) {
173+
if (target === undefined || target === false) {
167174
return result;
168175
}
169176

@@ -196,3 +203,59 @@ function deepMergeConfig(
196203

197204
return result;
198205
}
206+
207+
function nativeStyleMapping(
208+
config: Config,
209+
props: Record<string, any> | undefined,
210+
) {
211+
if (!config.nativeStyleMapping || !props) {
212+
return props;
213+
}
214+
215+
let source: Record<string, any> | undefined;
216+
217+
if (typeof config.target === "string") {
218+
source = props[config.target];
219+
} else if (config.target === false) {
220+
source = props["style"];
221+
} else {
222+
const tokens = [...config.target];
223+
const lastToken = tokens.pop()!;
224+
225+
source = props;
226+
for (const token of tokens) {
227+
source = source[token];
228+
if (!source) {
229+
return props;
230+
}
231+
}
232+
233+
source = source[lastToken];
234+
}
235+
236+
if (!source) {
237+
return props;
238+
}
239+
240+
for (const [key, path] of Object.entries(config.nativeStyleMapping)) {
241+
const styleValue = source[key];
242+
243+
delete source[key];
244+
245+
if (styleValue === undefined) {
246+
continue;
247+
}
248+
249+
let target = props;
250+
const tokens = path.split(".");
251+
const lastToken = tokens.pop();
252+
for (const token of tokens) {
253+
target[token] ??= {};
254+
target = target[token];
255+
}
256+
257+
target[lastToken!] = styleValue;
258+
}
259+
260+
return props;
261+
}

types.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ declare module "@react-native/virtualized-lists" {
1616
}
1717

1818
declare module "react-native" {
19+
interface ButtonProps {
20+
className?: string;
21+
}
1922
interface ScrollViewProps
2023
extends ViewProps,
2124
ScrollViewPropsIOS,

yarn.lock

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1895,13 +1895,20 @@ __metadata:
18951895
languageName: node
18961896
linkType: hard
18971897

1898-
"@eslint/js@npm:9.36.0, @eslint/js@npm:^9.30.1":
1898+
"@eslint/js@npm:9.36.0":
18991899
version: 9.36.0
19001900
resolution: "@eslint/js@npm:9.36.0"
19011901
checksum: 10c0/e3f6fb7d6f117d79615574f7bef4f238bcfed6ece0465d28226c3a75d2b6fac9cc189121e8673562796ca8ccea2bf9861715ee5cf4a3dbef87d17811c0dac22c
19021902
languageName: node
19031903
linkType: hard
19041904

1905+
"@eslint/js@npm:^9.30.1":
1906+
version: 9.37.0
1907+
resolution: "@eslint/js@npm:9.37.0"
1908+
checksum: 10c0/84f98a6213522fc76ea104bd910f606136200bd918544e056a7a22442d3f9d5c3c5cd7f4cdf2499d49b1fa140155b87d597a1f16d01644920f05c228e9ca0378
1909+
languageName: node
1910+
linkType: hard
1911+
19051912
"@eslint/object-schema@npm:^2.1.6":
19061913
version: 2.1.6
19071914
resolution: "@eslint/object-schema@npm:2.1.6"

0 commit comments

Comments
 (0)