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 (
);
};