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 ( {label} {value.toFixed(2)}× onChange(parseFloat(e.target.value))} className="w-full accent-cyan-400 cursor-pointer" aria-label={`${label} (${hint})`} /> {hint} ); } /* 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 ( setOpen((v) => !v)} aria-expanded={open} aria-haspopup="dialog" title="Contrast & brightness" > Display{!isDefault && •} {open && ( Contrast onChange(DEFAULT_DISPLAY_SETTINGS)} className="text-[10px] text-primary/70 hover:text-primary transition-colors disabled:opacity-30" disabled={isDefault} > Reset 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. )} ); }
{hint}
1.00× follows the automatic density compensation. Lower the edge/glow/bloom values when a large graph washes out to white.