Files
LogiFlow/client/src/hooks/use-toast-robust.ts
T
michaelschal 69c3d6805a Replace toast notifications and reconciliation module for improved stability
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
2025-08-12 11:11:10 +00:00

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,
};
}