Skip to content

Commit 99859a4

Browse files
fix: correct drop-shadow output format and filter function bugs (#309)
1 parent d53b870 commit 99859a4

File tree

3 files changed

+189
-8
lines changed

3 files changed

+189
-8
lines changed
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
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+
describe("filter: drop-shadow()", () => {
6+
test("basic drop-shadow", () => {
7+
registerCSS(`
8+
.test { filter: drop-shadow(0 4px 6px #000); }
9+
`);
10+
11+
render(<View testID={testID} className="test" />);
12+
const component = screen.getByTestId(testID);
13+
14+
// drop-shadow uses standardDeviation (not blurRadius) to match
15+
// React Native's DropShadowValue type
16+
expect(component.props.style.filter).toStrictEqual([
17+
{
18+
dropShadow: {
19+
offsetX: 0,
20+
offsetY: 4,
21+
standardDeviation: 6,
22+
color: "#000",
23+
},
24+
},
25+
]);
26+
});
27+
28+
test("drop-shadow with color first", () => {
29+
registerCSS(`
30+
.test { filter: drop-shadow(#fb2c36 0 0 24px); }
31+
`);
32+
33+
render(<View testID={testID} className="test" />);
34+
const component = screen.getByTestId(testID);
35+
36+
expect(component.props.style.filter).toStrictEqual([
37+
{
38+
dropShadow: {
39+
color: "#fb2c36",
40+
offsetX: 0,
41+
offsetY: 0,
42+
standardDeviation: 24,
43+
},
44+
},
45+
]);
46+
});
47+
48+
test("drop-shadow without blur", () => {
49+
registerCSS(`
50+
.test { filter: drop-shadow(2px 4px #000); }
51+
`);
52+
53+
render(<View testID={testID} className="test" />);
54+
const component = screen.getByTestId(testID);
55+
56+
expect(component.props.style.filter).toStrictEqual([
57+
{
58+
dropShadow: {
59+
offsetX: 2,
60+
offsetY: 4,
61+
standardDeviation: 0,
62+
color: "#000",
63+
},
64+
},
65+
]);
66+
});
67+
68+
test("drop-shadow from CSS variable", () => {
69+
registerCSS(`
70+
:root { --my-shadow: 0 4px 6px #000; }
71+
.test { filter: drop-shadow(var(--my-shadow)); }
72+
`);
73+
74+
render(<View testID={testID} className="test" />);
75+
const component = screen.getByTestId(testID);
76+
77+
expect(component.props.style.filter).toStrictEqual([
78+
{
79+
dropShadow: {
80+
offsetX: 0,
81+
offsetY: 4,
82+
standardDeviation: 6,
83+
color: "#000",
84+
},
85+
},
86+
]);
87+
});
88+
89+
test("drop-shadow from runtime variable", () => {
90+
registerCSS(
91+
`.test {
92+
--my-shadow: 0 4px 6px #000;
93+
filter: drop-shadow(var(--my-shadow));
94+
}`,
95+
{ inlineVariables: false },
96+
);
97+
98+
render(<View testID={testID} className="test" />);
99+
const component = screen.getByTestId(testID);
100+
101+
expect(component.props.style.filter).toStrictEqual([
102+
{
103+
dropShadow: {
104+
offsetX: 0,
105+
offsetY: 4,
106+
standardDeviation: 6,
107+
color: "#000",
108+
},
109+
},
110+
]);
111+
});
112+
113+
test("drop-shadow with currentcolor resolves to PlatformColor", () => {
114+
registerCSS(
115+
`.test {
116+
--my-shadow: 0 4px 6px currentcolor;
117+
filter: drop-shadow(var(--my-shadow));
118+
}`,
119+
{ inlineVariables: false },
120+
);
121+
122+
render(<View testID={testID} className="test" />);
123+
const component = screen.getByTestId(testID);
124+
125+
// currentcolor resolves to a PlatformColor object — requires
126+
// "color" type (not "string") in the shorthand handler pattern
127+
expect(component.props.style.filter).toStrictEqual([
128+
{
129+
dropShadow: {
130+
offsetX: 0,
131+
offsetY: 4,
132+
standardDeviation: 6,
133+
color: { semantic: ["label", "labelColor"] },
134+
},
135+
},
136+
]);
137+
});
138+
139+
test("Tailwind v4 drop-shadow pattern with @property", () => {
140+
registerCSS(`
141+
@property --tw-drop-shadow { syntax: "*"; inherits: false; }
142+
:root { --drop-shadow-md: 0 3px 3px rgb(0 0 0 / 0.12); }
143+
.test {
144+
--tw-drop-shadow: drop-shadow(var(--drop-shadow-md));
145+
filter: var(--tw-drop-shadow);
146+
}
147+
`);
148+
149+
render(<View testID={testID} className="test" />);
150+
const component = screen.getByTestId(testID);
151+
152+
expect(component.props.style.filter).toStrictEqual([
153+
{
154+
dropShadow: {
155+
offsetX: 0,
156+
offsetY: 3,
157+
standardDeviation: 3,
158+
color: "#0000001f",
159+
},
160+
},
161+
]);
162+
});
163+
});
164+
165+
describe("filter: opacity()", () => {
166+
test("opacity function produces correct key", () => {
167+
registerCSS(`
168+
@property --tw-opacity { syntax: "*"; inherits: false; }
169+
.test {
170+
--tw-opacity: opacity(0.5);
171+
filter: var(--tw-opacity);
172+
}
173+
`);
174+
175+
render(<View testID={testID} className="test" />);
176+
const component = screen.getByTestId(testID);
177+
178+
// Must produce { opacity: 0.5 }, not { hueRotate: 0.5 }
179+
expect(component.props.style.filter).toStrictEqual([{ opacity: 0.5 }]);
180+
});
181+
});

src/__tests__/vendor/tailwind/filters.test.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,15 +63,15 @@ describe("Filters - Drop Shadow", () => {
6363
[
6464
{
6565
dropShadow: {
66-
blurRadius: 2,
66+
standardDeviation: 2,
6767
color: "#0000001a",
6868
offsetX: 0,
6969
offsetY: 1,
7070
},
7171
},
7272
{
7373
dropShadow: {
74-
blurRadius: 1,
74+
standardDeviation: 1,
7575
color: "#0000000f",
7676
offsetX: 0,
7777
offsetY: 1,

src/native/styles/functions/filters.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,22 +62,22 @@ export const saturate: StyleFunctionResolver = (resolveValue, value) => {
6262
export const opacity: StyleFunctionResolver = (resolveValue, value) => {
6363
const args = resolveValue(value[2]);
6464
return {
65-
hueRotate: (Array.isArray(args) ? args[0] : args) as unknown,
65+
opacity: (Array.isArray(args) ? args[0] : args) as unknown,
6666
};
6767
};
6868

69-
const color = ["color", "string"] as const;
69+
const color = ["color", "color"] as const;
7070
const offsetX = ["offsetX", "number"] as const;
7171
const offsetY = ["offsetY", "number"] as const;
72-
const blurRadius = ["blurRadius", "number"] as const;
72+
const standardDeviation = ["standardDeviation", "number"] as const;
7373

7474
const handler = shorthandHandler(
7575
[
76-
[offsetX, offsetY, blurRadius, color],
76+
[offsetX, offsetY, standardDeviation, color],
7777
[color, offsetX, offsetY],
78-
[color, offsetX, offsetY, blurRadius],
78+
[color, offsetX, offsetY, standardDeviation],
7979
[offsetX, offsetY, color],
80-
[offsetX, offsetY, blurRadius, color],
80+
[offsetX, offsetY, standardDeviation, color],
8181
],
8282
[],
8383
"object",

0 commit comments

Comments
 (0)