Skip to content

Commit 04839bc

Browse files
JirakLumarklawlor
andauthored
fix: runtime box shadows from nested css variables (#145)
* fix: box shadow from css variables * chore: move tests into seperate file --------- Co-authored-by: Mark Lawlor <mwlawlor@gmail.com>
1 parent 330e81c commit 04839bc

File tree

3 files changed

+119
-22
lines changed

3 files changed

+119
-22
lines changed
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
import { render, screen } from "@testing-library/react-native";
2+
import { View } from "react-native-css/components/View";
3+
import { registerCSS, testID } from "react-native-css/jest";
4+
5+
test("shadow values - single nested variables", () => {
6+
registerCSS(`
7+
:root {
8+
--color: #fb2c36;
9+
--my-var: 0 20px 25px -5px var(--color);
10+
}
11+
12+
.test { box-shadow: var(--my-var); }
13+
`);
14+
15+
render(<View testID={testID} className="test" />);
16+
const component = screen.getByTestId(testID);
17+
18+
expect(component.props.style).toStrictEqual({
19+
boxShadow: [
20+
{
21+
blurRadius: 25,
22+
color: "#fb2c36",
23+
offsetX: 0,
24+
offsetY: 20,
25+
spreadDistance: -5,
26+
},
27+
],
28+
});
29+
});
30+
31+
test("shadow values - multiple nested variables", () => {
32+
registerCSS(`
33+
:root {
34+
--my-var: 0 20px 0 0 red, 0 30px 0 0 green;
35+
--my-var-2: var(--my-var), 0 40px 0 0 purple;
36+
--my-var-3: 0 50px 0 0 yellow, 0 60px 0 0 orange;
37+
--my-var-4: var(--my-var-3), 0 70px 0 0 gray;
38+
}
39+
40+
.test {
41+
box-shadow: var(--my-var-2), var(--my-var-4);
42+
}
43+
`);
44+
45+
render(<View testID={testID} className="test" />);
46+
const component = screen.getByTestId(testID);
47+
48+
expect(component.props.style).toStrictEqual({
49+
boxShadow: [
50+
{
51+
blurRadius: 0,
52+
color: "red",
53+
offsetX: 0,
54+
offsetY: 20,
55+
spreadDistance: 0,
56+
},
57+
58+
{
59+
blurRadius: 0,
60+
color: "green",
61+
offsetX: 0,
62+
offsetY: 30,
63+
spreadDistance: 0,
64+
},
65+
{
66+
blurRadius: 0,
67+
color: "purple",
68+
offsetX: 0,
69+
offsetY: 40,
70+
spreadDistance: 0,
71+
},
72+
{
73+
blurRadius: 0,
74+
color: "yellow",
75+
offsetX: 0,
76+
offsetY: 50,
77+
spreadDistance: 0,
78+
},
79+
{
80+
blurRadius: 0,
81+
color: "orange",
82+
offsetX: 0,
83+
offsetY: 60,
84+
spreadDistance: 0,
85+
},
86+
{
87+
blurRadius: 0,
88+
color: "gray",
89+
offsetX: 0,
90+
offsetY: 70,
91+
spreadDistance: 0,
92+
},
93+
],
94+
});
95+
});

src/__tests__/native/variables.test.tsx

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -209,8 +209,6 @@ test("useUnsafeVariable", () => {
209209
.test { color: var(--my-var); }
210210
`);
211211

212-
// Since we can't directly test the hook in isolation with the render approach,
213-
// we'll test that a component using the variable gets the correct value
214212
render(<View testID={testID} className="test" />);
215213
const component = screen.getByTestId(testID);
216214

@@ -223,8 +221,6 @@ test("ratio values", () => {
223221
.test { aspect-ratio: var(--my-var); }
224222
`);
225223

226-
// Since we can't directly test the hook in isolation with the render approach,
227-
// we'll test that a component using the variable gets the correct value
228224
render(<View testID={testID} className="test" />);
229225
const component = screen.getByTestId(testID);
230226

src/runtime/native/styles/shorthands/box-shadow.ts

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import type { StyleDescriptor } from "../../../../compiler";
12
import { isStyleDescriptorArray } from "../../../utils";
23
import type { StyleFunctionResolver } from "../resolve";
34
import { shorthandHandler } from "./_handler";
@@ -9,6 +10,27 @@ const blurRadius = ["blurRadius", "number"] as const;
910
const spreadDistance = ["spreadDistance", "number"] as const;
1011
// const inset = ["inset", "string"] as const;
1112

13+
function deepFlattenToArrayOfStyleDescriptors(
14+
arr: StyleDescriptor[],
15+
): StyleDescriptor[] {
16+
const result: StyleDescriptor[] = [];
17+
const stack = [arr];
18+
while (stack.length > 0) {
19+
const current = stack.pop();
20+
if (Array.isArray(current)) {
21+
if (current.length > 0 && Array.isArray(current[0])) {
22+
for (let i = current.length - 1; i >= 0; i--) {
23+
const elem = current[i];
24+
if (isStyleDescriptorArray(elem)) stack.push(elem);
25+
}
26+
} else {
27+
result.push(current);
28+
}
29+
}
30+
}
31+
return result;
32+
}
33+
1234
const handler = shorthandHandler(
1335
[
1436
[offsetX, offsetY, blurRadius, spreadDistance, color],
@@ -33,26 +55,10 @@ export const boxShadow: StyleFunctionResolver = (
3355
if (!isStyleDescriptorArray(args)) {
3456
return args;
3557
} else {
36-
return args
37-
.flatMap((shadows) => {
58+
return deepFlattenToArrayOfStyleDescriptors(args)
59+
.map((shadows) => {
3860
if (shadows === undefined) {
3961
return [];
40-
} else if (isStyleDescriptorArray(shadows)) {
41-
if (shadows.length === 0) {
42-
return [];
43-
} else if (Array.isArray(shadows[0])) {
44-
return shadows
45-
.map((shadow) => {
46-
return omitTransparentShadows(
47-
handler(resolveValue, shadow, get, options),
48-
);
49-
})
50-
.filter((v) => v !== undefined);
51-
} else {
52-
return omitTransparentShadows(
53-
handler(resolveValue, shadows, get, options),
54-
);
55-
}
5662
} else {
5763
return omitTransparentShadows(
5864
handler(resolveValue, shadows, get, options),

0 commit comments

Comments
 (0)