mirror of
https://github.com/R0m1k3/LogiFlow.git
synced 2026-10-18 20:57:40 +02:00
Replace the existing toast notification system and the BL Reconciliation module with robust, independent implementations to resolve React errors and improve performance. Replit-Commit-Author: Agent Replit-Commit-Session-Id: b163d4c0-de5e-4f4e-a9c0-aed4c7049718 Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/1957c339-2757-4d1f-8e92-e9f71a1ce58e/b163d4c0-de5e-4f4e-a9c0-aed4c7049718/l61v0JT
110 lines
2.2 KiB
TypeScript
110 lines
2.2 KiB
TypeScript
import { useState, useCallback, useEffect } from "react";
|
|
|
|
export interface Toast {
|
|
id: string;
|
|
title?: string;
|
|
description?: string;
|
|
variant?: "default" | "destructive" | "success";
|
|
duration?: number;
|
|
}
|
|
|
|
interface ToastState {
|
|
toasts: Toast[];
|
|
}
|
|
|
|
let listeners: Array<(state: ToastState) => void> = [];
|
|
let state: ToastState = { toasts: [] };
|
|
let count = 0;
|
|
|
|
function genId() {
|
|
count = (count + 1) % Number.MAX_SAFE_INTEGER;
|
|
return count.toString();
|
|
}
|
|
|
|
function dispatch(action: { type: string; toast?: any; toastId?: string }) {
|
|
switch (action.type) {
|
|
case "ADD_TOAST":
|
|
state.toasts = [action.toast, ...state.toasts].slice(0, 3); // Max 3 toasts
|
|
break;
|
|
case "DISMISS_TOAST":
|
|
if (action.toastId) {
|
|
state.toasts = state.toasts.filter(t => t.id !== action.toastId);
|
|
} else {
|
|
state.toasts = [];
|
|
}
|
|
break;
|
|
case "REMOVE_TOAST":
|
|
state.toasts = state.toasts.filter(t => t.id !== action.toastId);
|
|
break;
|
|
}
|
|
|
|
listeners.forEach(listener => listener(state));
|
|
}
|
|
|
|
function toast({
|
|
title,
|
|
description,
|
|
variant = "default",
|
|
duration = 5000,
|
|
...props
|
|
}: Omit<Toast, "id"> & { duration?: number }) {
|
|
const id = genId();
|
|
|
|
const newToast: Toast = {
|
|
id,
|
|
title,
|
|
description,
|
|
variant,
|
|
duration,
|
|
...props,
|
|
};
|
|
|
|
dispatch({
|
|
type: "ADD_TOAST",
|
|
toast: newToast,
|
|
});
|
|
|
|
// Auto remove after duration
|
|
if (duration > 0) {
|
|
setTimeout(() => {
|
|
dispatch({
|
|
type: "REMOVE_TOAST",
|
|
toastId: id,
|
|
});
|
|
}, duration);
|
|
}
|
|
|
|
return {
|
|
id,
|
|
dismiss: () => dispatch({ type: "DISMISS_TOAST", toastId: id }),
|
|
update: (updates: Partial<Toast>) =>
|
|
dispatch({ type: "ADD_TOAST", toast: { ...newToast, ...updates } }),
|
|
};
|
|
}
|
|
|
|
function dismiss(toastId?: string) {
|
|
dispatch({
|
|
type: "DISMISS_TOAST",
|
|
toastId,
|
|
});
|
|
}
|
|
|
|
export function useToast() {
|
|
const [toastState, setToastState] = useState<ToastState>(state);
|
|
|
|
useEffect(() => {
|
|
listeners.push(setToastState);
|
|
return () => {
|
|
const index = listeners.indexOf(setToastState);
|
|
if (index > -1) {
|
|
listeners.splice(index, 1);
|
|
}
|
|
};
|
|
}, []);
|
|
|
|
return {
|
|
toast,
|
|
dismiss,
|
|
toasts: toastState.toasts,
|
|
};
|
|
} |