import { useEffect, useState, type ReactNode } from "react"; import { createPortal } from "react-dom"; import { X } from "lucide-react"; type AlertTone = "success" | "info" | "warning" | "danger"; type DismissibleAlertProps = { tone?: AlertTone; children: ReactNode; dismissible?: boolean; className?: string; compact?: boolean; floating?: boolean; resetKey?: string | number; dismissStorageKey?: string; }; let floatingAlertRoot: HTMLElement | null = null; function getFloatingAlertRoot(): HTMLElement | null { if (typeof document === "undefined") return null; if (floatingAlertRoot?.isConnected) return floatingAlertRoot; const existing = document.getElementById("app-floating-alerts"); if (existing) { floatingAlertRoot = existing; return floatingAlertRoot; } floatingAlertRoot = document.createElement("div"); floatingAlertRoot.id = "app-floating-alerts"; floatingAlertRoot.className = "alert-floating-stack"; floatingAlertRoot.setAttribute("aria-label", "Application notices"); document.body.appendChild(floatingAlertRoot); return floatingAlertRoot; } function resolveDismissStorageKey(dismissStorageKey: string | undefined, resetKey: string | number | undefined): string | null { if (!dismissStorageKey) return null; return `govoplan.alert.dismissed:${dismissStorageKey}:${resetKey ?? "default"}`; } function readDismissed(storageKey: string | null): boolean { if (!storageKey || typeof window === "undefined") return false; try { return window.localStorage.getItem(storageKey) === "1"; } catch { return false; } } function writeDismissed(storageKey: string | null): void { if (!storageKey || typeof window === "undefined") return; try { window.localStorage.setItem(storageKey, "1"); } catch { // localStorage may be unavailable in private or restricted contexts. } } export default function DismissibleAlert({ tone = "info", children, dismissible = true, className = "", compact = false, floating = false, resetKey, dismissStorageKey }: DismissibleAlertProps) { const storageKey = resolveDismissStorageKey(dismissStorageKey, resetKey); const [alertState, setAlertState] = useState(() => ({ storageKey, visible: !readDismissed(storageKey) })); const visible = alertState.storageKey === storageKey ? alertState.visible : !readDismissed(storageKey); useEffect(() => { setAlertState({ storageKey, visible: !readDismissed(storageKey) }); }, [storageKey, resetKey, children]); if (!visible) return null; function dismiss() { writeDismissed(storageKey); setAlertState({ storageKey, visible: false }); } const role = tone === "danger" || tone === "warning" ? "alert" : "status"; const alert = (