"use client"; import { useEffect, useState } from "react"; import {getJSON, type Stats} from "@/lib/api"; import { DIMS, type View } from "@/lib/api"; import { VIEW_INFO, VIEW_ORDER } from "@/lib/views"; export function Segmented({ value, options, onChange, render, label, ariaLabel, }: { value: T; options: readonly T[]; onChange: (v: T) => void; render?: (v: T) => React.ReactNode; label: string; ariaLabel?: string; }) { return (
{label && {label}}
{options.map((o) => ( ))}
); } export function ViewSwatch({ view }: { view: View }) { return ; } export function ViewPicker({ value, onChange, views = VIEW_ORDER }: { value: View; onChange: (v: View) => void; views?: View[] }) { const [available,setAvailable]=useState(views); useEffect(()=>{void getJSON("/api/stats").then(s=>{setAvailable(s.views);if(s.views.length&&!s.views.includes(value))onChange(s.views[0]);}).catch(()=>{}); // Initial capabilities are a server snapshot; manual selection remains local. // eslint-disable-next-line react-hooks/exhaustive-deps },[]); return ( views.includes(v))} onChange={onChange} render={(v) => ( {VIEW_INFO[v].label} )} /> ); } export function DimPicker({ value, onChange }: { value: number; onChange: (d: number) => void }) { const [dims,setDims]=useState(DIMS); useEffect(()=>{void getJSON("/api/stats").then(s=>{setDims(s.dims);if(s.dims.length&&!s.dims.includes(value))onChange(s.dims[0]);}).catch(()=>{}); // eslint-disable-next-line react-hooks/exhaustive-deps },[]); return `${d}d`} />; }