export type BannerSeverity = "error" | "warning" | "notice" | "success"; export interface BannerEntry { id: number; severity: BannerSeverity; message: string; } const DISMISS_AFTER_MS = 8000; let banners: BannerEntry[] = []; let nextId = 1; const listeners = new Set<() => void>(); function notify() { for (const listener of listeners) listener(); } function show(severity: BannerSeverity, message: string): void { const isDuplicate = banners.some( (b) => b.severity === severity && b.message === message, ); if (isDuplicate) return; const id = nextId++; banners = [{ id, severity, message }, ...banners]; notify(); setTimeout(() => dismiss(id), DISMISS_AFTER_MS); } export function showError(message: string): void { show("error", message); } export function showWarning(message: string): void { show("warning", message); } export function showNotice(message: string): void { show("notice", message); } export function showSuccess(message: string): void { show("success", message); } export function dismiss(id: number): void { banners = banners.filter((b) => b.id !== id); notify(); } export function subscribe(listener: () => void): () => void { listeners.add(listener); return () => listeners.delete(listener); } export function getSnapshot(): BannerEntry[] { return banners; }