diff --git a/packages/studio/src/components/editor/propertyPanelFlatColorGradingSection.test.tsx b/packages/studio/src/components/editor/propertyPanelFlatColorGradingSection.test.tsx new file mode 100644 index 000000000..adfb8c40a --- /dev/null +++ b/packages/studio/src/components/editor/propertyPanelFlatColorGradingSection.test.tsx @@ -0,0 +1,73 @@ +// @vitest-environment happy-dom + +import React, { act } from "react"; +import { createRoot } from "react-dom/client"; +import { afterEach, describe, expect, it, vi } from "vitest"; +import { FlatColorGradingAccessory } from "./propertyPanelFlatColorGradingSection"; +import { normalizeHfColorGrading } from "@hyperframes/core/color-grading"; + +(globalThis as unknown as { IS_REACT_ACT_ENVIRONMENT: boolean }).IS_REACT_ACT_ENVIRONMENT = true; + +afterEach(() => { + document.body.innerHTML = ""; +}); + +function renderInto(node: React.ReactElement) { + const host = document.createElement("div"); + document.body.append(host); + const root = createRoot(host); + act(() => { + root.render(node); + }); + return { host, root }; +} + +function neutralGrading() { + const grading = normalizeHfColorGrading("neutral"); + if (!grading) throw new Error("expected a neutral grading"); + return grading; +} + +describe("FlatColorGradingAccessory", () => { + it("shows a 5px status dot colored by runtime status, with the message as its title", () => { + const { host, root } = renderInto( + , + ); + const dot = host.querySelector('[data-flat-grade-status-dot="true"]'); + expect(dot).not.toBeNull(); + expect(dot?.getAttribute("title")).toBe("Shader active"); + expect(dot?.className).toContain("bg-emerald-400"); + act(() => root.unmount()); + }); + + it("disables the compare hold button when grading is inactive, and fires resetGrading on click", () => { + const resetGrading = vi.fn(); + const { host, root } = renderInto( + , + ); + const compareButton = host.querySelector( + '[aria-label="Hold to show original"]', + ); + expect(compareButton?.disabled).toBe(true); + const resetButton = host.querySelector('[data-flat-grade-reset="true"]'); + act(() => resetButton?.dispatchEvent(new MouseEvent("click", { bubbles: true }))); + expect(resetGrading).toHaveBeenCalledTimes(1); + act(() => root.unmount()); + }); +}); diff --git a/packages/studio/src/components/editor/propertyPanelFlatColorGradingSection.tsx b/packages/studio/src/components/editor/propertyPanelFlatColorGradingSection.tsx new file mode 100644 index 000000000..2f9c6376d --- /dev/null +++ b/packages/studio/src/components/editor/propertyPanelFlatColorGradingSection.tsx @@ -0,0 +1,68 @@ +import { isHfColorGradingActive } from "@hyperframes/core/color-grading"; +import { Compare, RotateCcw } from "../../icons/SystemIcons"; +import type { ColorGradingControllerState } from "./useColorGradingController"; + +const STATUS_DOT_CLASS: Record = { + active: "bg-emerald-400", + pending: "bg-amber-300", + unavailable: "bg-red-400", + missing: "bg-panel-text-5", + inactive: "bg-panel-text-5", +}; + +export function FlatColorGradingAccessory({ + state, +}: { + state: Pick< + ColorGradingControllerState, + "grading" | "compareEnabled" | "runtimeStatus" | "commitCompare" | "resetGrading" + >; +}) { + const { grading, compareEnabled, runtimeStatus, commitCompare, resetGrading } = state; + const gradingActive = isHfColorGradingActive(grading); + + return ( + + + + + + ); +}