返回 JoyAI-Echo
toast.ts
1 export type ToastType = "error" | "success";
2
3 export interface ToastOptions {
4 message: string;
5 type?: ToastType;
6 duration?: number;
7 }
8
9 export interface ToastState {
10 message: string;
11 type: ToastType;
12 visible: boolean;
13 }
14
15 type ToastListener = (state: ToastState | null) => void;
16
17 const DEFAULT_DURATION = 3000;
18
19 let listener: ToastListener | null = null;
20 let timer: number | null = null;
21 let currentToast: ToastState | null = null;
22
23 function clearTimer() {
24 if (timer !== null) {
25 window.clearTimeout(timer);
26 timer = null;
27 }
28 }
29
30 function emit(state: ToastState | null) {
31 listener?.(state);
32 }
33
34 function normalizeOptions(
35 options: ToastOptions | string,
36 type?: ToastType,
37 duration?: number,
38 ): Required<Pick<ToastOptions, "message" | "type" | "duration">> {
39 if (typeof options === "string") {
40 return {
41 message: options,
42 type: type ?? "error",
43 duration: duration ?? DEFAULT_DURATION,
44 };
45 }
46 return {
47 message: options.message,
48 type: options.type ?? "error",
49 duration: options.duration ?? DEFAULT_DURATION,
50 };
51 }
52
53 function showToast(options: ToastOptions | string) {
54 const { message, type, duration } = normalizeOptions(options);
55
56 clearTimer();
57 currentToast = { message, type, visible: true };
58 emit(currentToast);
59
60 timer = window.setTimeout(() => {
61 if (currentToast) {
62 currentToast = { ...currentToast, visible: false };
63 emit(currentToast);
64 }
65 timer = null;
66 }, duration);
67 }
68
69 export function registerToastListener(fn: ToastListener): () => void {
70 listener = fn;
71 return () => {
72 if (listener === fn) {
73 listener = null;
74 }
75 };
76 }
77
78 export const toast = {
79 show(options: ToastOptions | string) {
80 showToast(options);
81 },
82 error(message: string, duration?: number) {
83 showToast({ message, type: "error", duration });
84 },
85 success(message: string, duration?: number) {
86 showToast({ message, type: "success", duration });
87 },
88 };
89
89 lines TYPESCRIPT