import { useEffect, useRef, useState } from "react"; import { Button } from "@/components/ui/button"; import { DEFAULT_DISPLAY_SETTINGS, DISPLAY_LIMITS, type DisplaySettings, } from "../lib/density"; interface DisplaySettingsMenuProps { settings: DisplaySettings; onChange: (next: DisplaySettings) => void; } interface SliderRowProps { label: string; hint: string; value: number; min: number; max: number; onChange: (value: number) => void; } function SliderRow({ label, hint, value, min, max, onChange }: SliderRowProps) { return ( ); } /* Contrast / brightness controls for the 3D graph. These ride on top of the * automatic density compensation — the defaults already adapt to graph size, * so 1.00× is "auto"; the sliders let the user push it. */ export function DisplaySettingsMenu({ settings, onChange, }: DisplaySettingsMenuProps) { const [open, setOpen] = useState(false); const rootRef = useRef(null); /* Close on outside click / Escape */ useEffect(() => { if (!open) return; const onDown = (e: MouseEvent) => { if (rootRef.current && !rootRef.current.contains(e.target as Node)) { setOpen(false); } }; const onKey = (e: KeyboardEvent) => { if (e.key === "Escape") setOpen(false); }; document.addEventListener("mousedown", onDown); document.addEventListener("keydown", onKey); return () => { document.removeEventListener("mousedown", onDown); document.removeEventListener("keydown", onKey); }; }, [open]); const set = (patch: Partial) => onChange({ ...settings, ...patch }); const isDefault = settings.edgeBrightness === DEFAULT_DISPLAY_SETTINGS.edgeBrightness && settings.nodeGlow === DEFAULT_DISPLAY_SETTINGS.nodeGlow && settings.bloom === DEFAULT_DISPLAY_SETTINGS.bloom; return (
{open && (
Contrast
set({ edgeBrightness })} /> set({ nodeGlow })} /> set({ bloom })} />

1.00× follows the automatic density compensation. Lower the edge/glow/bloom values when a large graph washes out to white.

)}
); }