// Importing necessary components, hooks, and types from related files import React, { useState, useCallback, useEffect } from 'react'; import { Notification } from "./components"; import { IConfig, INotification, NotificationCard, NotificationProviderProps } from "./types"; import { styles as defaultStyles, positionStyles } from './utils'; //classnames, import { NotificationContext } from "./context"; // Defining a functional component for the Notification Provider export const NotificationProvider: React.FC = (props) => { // Destructuring props const { config, overrideStyles, children } = props; // Default configuration values for notifications const configDefault: Required = { isCloseable: false, showTitle: true, position: 'top-right', duration: 10, errorColor: 'red', successColor: 'green', infoColor: 'blue', closeIcon: null, successIcon: null, errorIcon: null, infoIcon: null, showIcon: true, animationDuration: 500, }; // Merging default configuration with provided configuration const configData = { ...configDefault, ...config, }; // Merging default styles with provided override styles const styling = { ...positionStyles, container: { ...defaultStyles.container, ...overrideStyles?.container }, cardContainer: { ...defaultStyles.cardContainer, ...overrideStyles?.cardContainer, }, cardContent: { ...defaultStyles.cardContent, ...overrideStyles?.cardContent, }, cardIcon: { ...defaultStyles.cardIcon, ...overrideStyles?.cardIcon }, cardMessage: { ...defaultStyles.cardMessage, ...overrideStyles?.cardMessage, }, cardTitle: { ...defaultStyles.cardTitle, ...overrideStyles?.cardTitle }, closeButton: { ...defaultStyles.closeButton, ...overrideStyles?.closeButton, }, icon: { ...defaultStyles.icon, ...overrideStyles?.icon }, animateIn: { ...defaultStyles.animateIn, ...overrideStyles?.animateIn }, animateOut: { ...defaultStyles.animateOut, ...overrideStyles?.icon }, }; // State to manage notifications const [notifications, setNotifications] = useState([]); // Function to show a notification const show = useCallback((data: INotification) => { // Default values for notification data const defaultData: Required = { variant: 'info', duration: config?.duration || 5, message: '', title: '', }; // Merging default notification data with provided data const value = { ...defaultData, ...data, }; // Generating a unique id for the notification const id = Math.random(); const expiresAt = new Date(); const secondsToAdd = value.duration; expiresAt.setSeconds(expiresAt.getSeconds() + secondsToAdd); // Creating a new notification object const notification: NotificationCard = { ...value, id, animate: true, expiresAt: value.duration ? expiresAt : undefined, }; // Adding the new notification to the notifications state setNotifications((current) => [ ...current.map((c) => ({ ...c, })), notification, ]); return id; // Returning the id of the new notification }, []); // Function to remove a notification const remove = useCallback((id: number) => { // Updating the animate property of the notification to trigger exit animation setNotifications((current) => [ ...current.map((c) => { if (c.id === id) { return { ...c, animate: false, }; } return c; }), ]); // Removing the notification from state after animation duration setTimeout(() => { setNotifications((current) => [ ...current.filter((c) => { return c.id !== id; }), ]); }, configData.animationDuration); }, []); // Effect hook to manage notification expiration and removal useEffect(() => { // Set up an interval to check for expired notifications const intervalId = setInterval(() => { setNotifications((current) => current.map((c) => { if (!c.expiresAt || c.expiresAt > new Date()) { return c; } else { // If notification has expired, trigger removal remove(c.id); return { ...c, animate: false }; } }) ); }, 10); // Check interval // Cleanup function to clear the interval return () => { clearInterval(intervalId); }; }, []); // Rendering the Notification Provider component return ( <>{children} {/* Render children components */}
{/* Render notifications */} {notifications.map((notification) => ( ))}
); };