import { useEffect, useId, useRef, useState } from "react"; import { DecisionIcon } from "@chopin/icons"; import { Provenance, SidecarCard } from "../card"; import { useVisualDecision } from "../use-visual-decision"; import type { ComponentType } from "react"; import type { VisualDecision } from "@chopin/protocol"; import type { Transport } from "@chopin/question/react"; export type VisualPreviewProps = { definition: VisualDecision.Definition; values: VisualDecision.Values; }; export type VisualPreviewComponent = ComponentType; export function VisualDecisionCard( { canEdit = false, connected = false, id, preview: Preview, wire }: { canEdit?: boolean; connected?: boolean; id: string; preview?: VisualPreviewComponent; wire?: Transport; }, ) { let draft = useVisualDecision(id, wire, connected); let state = draft.state; let [peek, setPeek] = useState(false); let [padding, setPadding] = useState<4 | 6 | 8>(); let [color, setColor] = useState(); let paddingId = useId(); let colorId = useId(); let colorHelpId = useId(); let held = useRef<"pointer" | "keyboard" | undefined>(undefined); let saved = state?.saved; let editable = canEdit && connected && !!wire && !!state && !saved && !draft.syncing && !draft.saving; let displayedColor = color ?? state?.values.selectedColor ?? ""; let validColor = /^#[0-9a-fA-F]{6}$/.test(displayedColor); useEffect(() => { // Native inputs advance locally while acknowledgements catch up; the preview stays accepted. if (draft.pending > 0 && !state?.saved) return; setPadding(state?.values.optionPadding); }, [draft.pending, state?.values.optionPadding, state?.saved]); useEffect(() => { if (draft.pending > 0 && !state?.saved) return; if (color !== undefined && !/^#[0-9a-fA-F]{6}$/.test(color) && !state?.saved) return; setColor(state?.values.selectedColor); }, [color, draft.pending, state?.values.selectedColor, state?.saved]); useEffect(() => { let release = () => { held.current = undefined; setPeek(false); }; let onVisibility = () => { if (document.visibilityState !== "visible") release(); }; window.addEventListener("blur", release); document.addEventListener("visibilitychange", onVisibility); return () => { window.removeEventListener("blur", release); document.removeEventListener("visibilitychange", onVisibility); }; }, []); return (
{saved ? Saved : ( )}
{state ? ( <>
{peek ? "Current" : saved ? "Saved values" : "Adjusted"}
{Preview ? ( ) :

Preview unavailable.

}
{saved && (
)} ) : (

Loading shared draft…

)} {draft.error && (
{draft.error} {(draft.pending > 0 || draft.syncing) && !saved && ( )}
)}
); }