import * as React from 'react'; export type ToastType = 'success' | 'error'; export interface IToast { id: number; message: string; type: ToastType; /** Тост гаснет (анимация исчезновения) перед удалением. */ isLeaving: boolean; } /** Тост виден 3 секунды — как в старом web part. */ const TOAST_VISIBLE_MS = 3000; /** Длительность анимации исчезновения (совпадает с transition в стилях). */ const TOAST_FADE_MS = 250; interface IToastsState { toasts: IToast[]; showToast: (message: string, type: ToastType) => void; } /** Простые тосты раздела импорта (в ui-kit тостов нет). Таймеры снимаются при уходе со страницы. */ export function useToasts(): IToastsState { const [toasts, setToasts] = React.useState([]); const nextIdRef = React.useRef(1); const timersRef = React.useRef([]); React.useEffect( () => () => { timersRef.current.forEach((timer) => window.clearTimeout(timer)); }, [] ); const showToast = React.useCallback((message: string, type: ToastType): void => { const id = nextIdRef.current++; setToasts((prev) => [...prev, { id, message, type, isLeaving: false }]); const leaveTimer = window.setTimeout(() => { setToasts((prev) => prev.map((toast) => (toast.id === id ? { ...toast, isLeaving: true } : toast))); }, TOAST_VISIBLE_MS); const removeTimer = window.setTimeout(() => { setToasts((prev) => prev.filter((toast) => toast.id !== id)); }, TOAST_VISIBLE_MS + TOAST_FADE_MS); timersRef.current.push(leaveTimer, removeTimer); }, []); return { toasts, showToast }; }