import * as React from "react"; import { useCallback, useEffect } from "react"; import type { ToasterProps } from "sonner"; import { Toaster, toast } from "sonner"; import { useTheme } from "@/components/admin/theme-provider"; import { CloseNotificationContext, useNotificationContext, useTakeUndoableMutation, useTranslate, } from "ra-core"; /** * Displays notifications triggered with the useNotify hook. * * Supports different notification types (info, success, warning, error) and undoable mutations. * Automatically adapts to the current theme (light/dark). * * @see {@link https://marmelab.com/shadcn-admin-kit/docs/notification Notification documentation} * @see {@link https://marmelab.com/ra-core/usenotify/ useNotify hook} * * @example * // Trigger a notification * import { useNotify } from 'ra-core'; * * const NotifyButton = () => { * const notify = useNotify(); * const handleClick = () => { * notify('Comment approved', { type: 'success' }); * }; * return ; * }; */ export const Notification = (props: ToasterProps) => { const translate = useTranslate(); const { notifications, takeNotification } = useNotificationContext(); const takeMutation = useTakeUndoableMutation(); const { theme } = useTheme(); useEffect(() => { if (notifications.length) { const notification = takeNotification(); if (notification) { const { message, type = "info", notificationOptions } = notification; const { messageArgs, undoable } = notificationOptions || {}; const beforeunload = (e: BeforeUnloadEvent) => { e.preventDefault(); const confirmationMessage = ""; e.returnValue = confirmationMessage; return confirmationMessage; }; if (undoable) { window.addEventListener("beforeunload", beforeunload); } const handleExited = () => { if (undoable) { const mutation = takeMutation(); if (mutation) { mutation({ isUndo: false }); } window.removeEventListener("beforeunload", beforeunload); } }; const handleUndo = () => { const mutation = takeMutation(); if (mutation) { mutation({ isUndo: true }); } window.removeEventListener("beforeunload", beforeunload); }; const finalMessage = message ? typeof message === "string" ? translate(message, messageArgs) : React.isValidElement(message) ? message : undefined : undefined; toast[type](finalMessage, { action: undoable ? { label: translate("ra.action.undo"), onClick: handleUndo, } : undefined, onDismiss: handleExited, onAutoClose: handleExited, }); } } }, [notifications, takeMutation, takeNotification, translate]); const handleRequestClose = useCallback(() => { // Dismiss all toasts toast.dismiss(); }, []); return ( ); };