diff --git a/src/__tests__/native/filters.test.tsx b/src/__tests__/native/filters.test.tsx new file mode 100644 index 00000000..9ff55e48 --- /dev/null +++ b/src/__tests__/native/filters.test.tsx @@ -0,0 +1,181 @@ +import { render, screen } from "@testing-library/react-native"; +import { View } from "react-native-css/components/View"; +import { registerCSS, testID } from "react-native-css/jest"; + +describe("filter: drop-shadow()", () => { + test("basic drop-shadow", () => { + registerCSS(` + .test { filter: drop-shadow(0 4px 6px #000); } + `); + + render(); + const component = screen.getByTestId(testID); + + // drop-shadow uses standardDeviation (not blurRadius) to match + // React Native's DropShadowValue type + expect(component.props.style.filter).toStrictEqual([ + { + dropShadow: { + offsetX: 0, + offsetY: 4, + standardDeviation: 6, + color: "#000", + }, + }, + ]); + }); + + test("drop-shadow with color first", () => { + registerCSS(` + .test { filter: drop-shadow(#fb2c36 0 0 24px); } + `); + + render(); + const component = screen.getByTestId(testID); + + expect(component.props.style.filter).toStrictEqual([ + { + dropShadow: { + color: "#fb2c36", + offsetX: 0, + offsetY: 0, + standardDeviation: 24, + }, + }, + ]); + }); + + test("drop-shadow without blur", () => { + registerCSS(` + .test { filter: drop-shadow(2px 4px #000); } + `); + + render(); + const component = screen.getByTestId(testID); + + expect(component.props.style.filter).toStrictEqual([ + { + dropShadow: { + offsetX: 2, + offsetY: 4, + standardDeviation: 0, + color: "#000", + }, + }, + ]); + }); + + test("drop-shadow from CSS variable", () => { + registerCSS(` + :root { --my-shadow: 0 4px 6px #000; } + .test { filter: drop-shadow(var(--my-shadow)); } + `); + + render(); + const component = screen.getByTestId(testID); + + expect(component.props.style.filter).toStrictEqual([ + { + dropShadow: { + offsetX: 0, + offsetY: 4, + standardDeviation: 6, + color: "#000", + }, + }, + ]); + }); + + test("drop-shadow from runtime variable", () => { + registerCSS( + `.test { + --my-shadow: 0 4px 6px #000; + filter: drop-shadow(var(--my-shadow)); + }`, + { inlineVariables: false }, + ); + + render(); + const component = screen.getByTestId(testID); + + expect(component.props.style.filter).toStrictEqual([ + { + dropShadow: { + offsetX: 0, + offsetY: 4, + standardDeviation: 6, + color: "#000", + }, + }, + ]); + }); + + test("drop-shadow with currentcolor resolves to PlatformColor", () => { + registerCSS( + `.test { + --my-shadow: 0 4px 6px currentcolor; + filter: drop-shadow(var(--my-shadow)); + }`, + { inlineVariables: false }, + ); + + render(); + const component = screen.getByTestId(testID); + + // currentcolor resolves to a PlatformColor object — requires + // "color" type (not "string") in the shorthand handler pattern + expect(component.props.style.filter).toStrictEqual([ + { + dropShadow: { + offsetX: 0, + offsetY: 4, + standardDeviation: 6, + color: { semantic: ["label", "labelColor"] }, + }, + }, + ]); + }); + + test("Tailwind v4 drop-shadow pattern with @property", () => { + registerCSS(` + @property --tw-drop-shadow { syntax: "*"; inherits: false; } + :root { --drop-shadow-md: 0 3px 3px rgb(0 0 0 / 0.12); } + .test { + --tw-drop-shadow: drop-shadow(var(--drop-shadow-md)); + filter: var(--tw-drop-shadow); + } + `); + + render(); + const component = screen.getByTestId(testID); + + expect(component.props.style.filter).toStrictEqual([ + { + dropShadow: { + offsetX: 0, + offsetY: 3, + standardDeviation: 3, + color: "#0000001f", + }, + }, + ]); + }); +}); + +describe("filter: opacity()", () => { + test("opacity function produces correct key", () => { + registerCSS(` + @property --tw-opacity { syntax: "*"; inherits: false; } + .test { + --tw-opacity: opacity(0.5); + filter: var(--tw-opacity); + } + `); + + render(); + const component = screen.getByTestId(testID); + + // Must produce { opacity: 0.5 }, not { hueRotate: 0.5 } + expect(component.props.style.filter).toStrictEqual([{ opacity: 0.5 }]); + }); +}); diff --git a/src/__tests__/vendor/tailwind/filters.test.tsx b/src/__tests__/vendor/tailwind/filters.test.tsx index 24833fed..c7bbb4a6 100644 --- a/src/__tests__/vendor/tailwind/filters.test.tsx +++ b/src/__tests__/vendor/tailwind/filters.test.tsx @@ -63,7 +63,7 @@ describe("Filters - Drop Shadow", () => { [ { dropShadow: { - blurRadius: 2, + standardDeviation: 2, color: "#0000001a", offsetX: 0, offsetY: 1, @@ -71,7 +71,7 @@ describe("Filters - Drop Shadow", () => { }, { dropShadow: { - blurRadius: 1, + standardDeviation: 1, color: "#0000000f", offsetX: 0, offsetY: 1, diff --git a/src/native/styles/functions/filters.ts b/src/native/styles/functions/filters.ts index 17def28e..98cf8fff 100644 --- a/src/native/styles/functions/filters.ts +++ b/src/native/styles/functions/filters.ts @@ -62,22 +62,22 @@ export const saturate: StyleFunctionResolver = (resolveValue, value) => { export const opacity: StyleFunctionResolver = (resolveValue, value) => { const args = resolveValue(value[2]); return { - hueRotate: (Array.isArray(args) ? args[0] : args) as unknown, + opacity: (Array.isArray(args) ? args[0] : args) as unknown, }; }; -const color = ["color", "string"] as const; +const color = ["color", "color"] as const; const offsetX = ["offsetX", "number"] as const; const offsetY = ["offsetY", "number"] as const; -const blurRadius = ["blurRadius", "number"] as const; +const standardDeviation = ["standardDeviation", "number"] as const; const handler = shorthandHandler( [ - [offsetX, offsetY, blurRadius, color], + [offsetX, offsetY, standardDeviation, color], [color, offsetX, offsetY], - [color, offsetX, offsetY, blurRadius], + [color, offsetX, offsetY, standardDeviation], [offsetX, offsetY, color], - [offsetX, offsetY, blurRadius, color], + [offsetX, offsetY, standardDeviation, color], ], [], "object",