Skip to content
File

Blob: src/client/components/toast-store.ts

typescript46 lines
1export type ToastVariant = "success" | "error" | "info";
2 
3export interface Toast {
4 id: number;
5 message: string;
6 variant: ToastVariant;
7 exiting?: boolean;
8}
9 
10let nextId = 0;
11let toasts: Toast[] = [];
12const listeners = new Set<() => void>();
13 
14function emit() {
15 for (const listener of listeners) listener();
16}
17 
18function add(message: string, variant: ToastVariant) {
19 const id = ++nextId;
20 toasts = [{ id, message, variant }, ...toasts].slice(0, 3);
21 emit();
22 setTimeout(() => {
23 toasts = toasts.map((toast) => (toast.id === id ? { ...toast, exiting: true } : toast));
24 emit();
25 }, 3800);
26 setTimeout(() => {
27 toasts = toasts.filter((toast) => toast.id !== id);
28 emit();
29 }, 4000);
30}
31 
32export function subscribeToast(listener: () => void) {
33 listeners.add(listener);
34 return () => listeners.delete(listener);
35}
36 
37export function getToastSnapshot() {
38 return toasts;
39}
40 
41export const toast = {
42 success: (message: string) => add(message, "success"),
43 error: (message: string) => add(message, "error"),
44 info: (message: string) => add(message, "info"),
45};