import * as T from '@radix-ui/react-toast' import * as React from 'react' import { AlertSeverity, TLUiToast, useToasts } from '../context/toasts' import { useTranslation } from '../hooks/useTranslation/useTranslation' import { TLUiIconType } from '../icon-types' import { TldrawUiButton } from './primitives/Button/TldrawUiButton' import { TldrawUiButtonLabel } from './primitives/Button/TldrawUiButtonLabel' import { TldrawUiIcon } from './primitives/TldrawUiIcon' const SEVERITY_TO_ICON: { [msg in AlertSeverity]: TLUiIconType } = { success: 'check-circle', warning: 'warning-triangle', error: 'cross-circle', info: 'info-circle', } function Toast({ toast }: { toast: TLUiToast }) { const { removeToast } = useToasts() const msg = useTranslation() const onOpenChange = (isOpen: boolean) => { if (!isOpen) { removeToast(toast.id) } } const hasActions = toast.actions && toast.actions.length > 0 const icon = toast.icon || (toast.severity && SEVERITY_TO_ICON[toast.severity]) return ( {icon && (
)}
{toast.title && {toast.title}} {toast.description && ( {toast.description} )}
{toast.actions && (
{toast.actions.map((action, i) => ( {action.label} ))} {toast.closeLabel ?? msg('toast.close')}
)}
{!hasActions && ( {toast.closeLabel ?? msg('toast.close')} )}
) } function _Toasts() { const { toasts } = useToasts() return ( <> {toasts.map((toast) => ( ))} ) } export const Toasts = React.memo(_Toasts) export function ToastViewport() { const { toasts } = useToasts() const [hasToasts, setHasToasts] = React.useState(false) React.useEffect(() => { let cancelled = false if (toasts.length) { setHasToasts(true) } else { setTimeout(() => { if (!cancelled) { setHasToasts(false) } }, 1000) } return () => { cancelled = true } }, [toasts.length, setHasToasts]) if (!hasToasts) return null return }