import { Dispatch , SetStateAction } from 'react' ; import { NotificationOptions , CreateNotificationOptions } from './interfaces' ; function createNotificationManager ( setNotifications ) { let idx = 1 ; const intervalIds = new Map < number , any > ( ) ; const removeInterval = ( id ) => { const intervalId = intervalIds . get ( id ) ; if ( ! intervalId ) { return ; } if ( intervalId !== - 1 ) { clearTimeout ( intervalId ) ; } intervalIds . delete ( id ) ; } ; const removeNotification = ( id ) => { const intervalId = intervalIds . get ( id ) ; if ( ! intervalId ) { return ; } removeInterval ( id ) ; return setNotifications ( ( oldNotifications ) => { return oldNotifications . filter ( ( { id : otherId } ) => id !== otherId ) ; } ) ; } ; const hideNotification = ( id ) => { if ( document . hidden ) { return removeNotification ( id ) ; } return setNotifications ( ( oldNotifications ) => { return oldNotifications . map ( ( oldNotification ) => { if ( oldNotification . id !== id ) { return oldNotification ; } return { ... oldNotification , isClosing : true , } ; } ) ; } ) ; } ; const createNotification = ( { id = idx ++ , expiration = 3500 , type = 'success' , ... rest } ) => { if ( intervalIds . has ( id ) ) { throw new Error ( 'notification already exists' ) ; } if ( idx >= 1000 ) { idx = 0 ; } setNotifications ( ( oldNotifications ) => { const newNotification = { id , key : id , expiration , type , ... rest , isClosing : false , } ; if ( typeof rest . text === 'string' && type !== 'success' ) { const duplicateOldNotification = oldNotifications . find ( ( oldNotification ) => oldNotification . text === rest . text ) ; if ( duplicateOldNotification ) { removeInterval ( duplicateOldNotification . id ) ; return oldNotifications . map ( ( oldNotification ) => { if ( oldNotification === duplicateOldNotification ) { return { ... newNotification , key : duplicateOldNotification . key , } ; } return oldNotification ; } ) ; } } return [ ... oldNotifications , newNotification ] ; } ) ; intervalIds . set ( id , expiration === - 1 ? - 1 : setTimeout ( ( ) => hideNotification ( id ) , expiration ) ) ; return id ; } ; const clearNotifications = ( ) => { intervalIds . forEach ( ( intervalId ) => { clearTimeout ( intervalId ) ; } ) ; intervalIds . clear ( ) ; return setNotifications ( [ ] ) ; } ; return { createNotification , removeNotification , hideNotification , clearNotifications , } ; } export type NotificationsManager = ReturnType < typeof createNotificationManager > ; export default createNotificationManager ;