import { useState, useEffect } from "react"; import type { StatusColorScheme } from "@/types/host-sidebar-preferences"; export type { StatusColorScheme }; const PREFS_KEY = "hostSidebarPreferences"; const PREFS_EVENT = "hostSidebarPreferencesChanged"; /** * Reads the scheme straight off the sidebar preferences cache that * useHostSidebarPreferences writes, so the toggle in Customize Sidebar takes * effect without a reload. Exported for imperative callers that build markup * outside React (the topology SVG). */ export function readStatusColorScheme(): StatusColorScheme { try { const raw = localStorage.getItem(PREFS_KEY); if (!raw) return "accent"; const parsed = JSON.parse(raw) as { display?: { statusColorScheme?: string }; }; return parsed?.display?.statusColorScheme === "status" ? "status" : "accent"; } catch { return "accent"; } } export function useStatusColorScheme(): StatusColorScheme { const [scheme, setScheme] = useState( readStatusColorScheme, ); useEffect(() => { const handler = () => setScheme(readStatusColorScheme()); handler(); window.addEventListener(PREFS_EVENT, handler); window.addEventListener("storage", handler); return () => { window.removeEventListener(PREFS_EVENT, handler); window.removeEventListener("storage", handler); }; }, []); return scheme; } /** Returns Tailwind class names for a status dot/stripe. */ export function getStatusClasses( status: boolean | "online" | "offline" | "unknown", scheme: StatusColorScheme, variant: "dot" | "stripe" | "badge", loading = false, ): string { const online = status === true || status === "online"; if (loading || status === "unknown") { if (scheme === "status") { if (variant === "dot") return "bg-warning animate-pulse"; if (variant === "stripe") return "bg-warning/40 animate-pulse"; return "border-warning/40 text-warning bg-warning/10 animate-pulse"; } if (variant === "dot") return "bg-muted-foreground/40 animate-pulse"; if (variant === "stripe") return "bg-muted-foreground/20 animate-pulse"; return "border-border/50 text-muted-foreground/50 bg-muted/20 animate-pulse"; } if (scheme === "status") { if (variant === "dot") return online ? "bg-emerald-500" : "bg-red-500"; if (variant === "stripe") return online ? "bg-emerald-500" : "bg-red-500/40"; // badge return online ? "border-emerald-500/40 text-emerald-500 bg-emerald-500/10" : "border-red-500/40 text-red-500 bg-red-500/10"; } // accent scheme if (variant === "dot") return online ? "bg-accent-brand" : "bg-muted-foreground/25"; // Offline keeps a faint neutral line rather than nothing, so the stripe // column stays visible instead of blending into the background. if (variant === "stripe") return online ? "bg-accent-brand" : "bg-muted-foreground/20"; // badge return online ? "border-accent-brand/40 text-accent-brand bg-accent-brand/10" : "border-border/50 text-muted-foreground/60 bg-muted/30"; }