UNPKG

saagie-ui

Version:

Saagie UI from Saagie Design System

124 lines (107 loc) 3.56 kB
import React, { useMemo } from 'react'; import ReactDOM from 'react-dom'; import PropTypes from 'prop-types'; import { Notification } from './Notification'; import { NotificationItem } from './NotificationItem'; import { NotificationActions } from './NotificationActions'; const propTypes = { /** * The children that will be rendered by the NotificationProvider. */ children: PropTypes.any.isRequired, /** * Render the Notification root element in the current DOM hierarchy. */ isPortalDisabled: PropTypes.bool, /** * The target where the Notification node should render when the portal is * enabled */ portalTarget: PropTypes.instanceOf(Element), }; const defaultProps = { isPortalDisabled: false, portalTarget: document.body, }; export const NotificationContext = React.createContext(); export const NotificationProvider = ({ children, isPortalDisabled, portalTarget, ...attributes }) => { const [notifications, setNotifications] = React.useState([]); /** * Remove a notification from the notification context. * @param {string} key The previously set key on the notification object. */ const clearNotification = (key) => { setNotifications((notifs) => notifs.filter((notfication) => notfication.key !== key)); }; const throwNotifcation = (color = '') => (content, actions = '', { cancelLabel = 'Undo', duration = 0, key = undefined, onDurationEndAction = undefined, onCancelDurationEndAction = () => {}, } = {}) => { const notificationKey = key || Math.random().toString(36).substr(2, 9); setNotifications((notifs) => [...notifs.filter((notfication) => notfication.key !== key), { actions, cancelLabel, color, content, key: notificationKey, duration, onDurationEndAction, onCancelDurationEndAction, }]); return notificationKey; }; const clearAllNotifications = () => { setNotifications([]); }; const value = useMemo(() => ({ clearAllNotifications, throwError: throwNotifcation('danger'), throwSuccess: throwNotifcation('success'), throwWarning: throwNotifcation('warning'), throwImportant: throwNotifcation('primary'), throwMessage: throwNotifcation(), clearNotification, }), []); const notificationNode = ( <Notification {...attributes}> {notifications.map((notification) => ( <NotificationItem cancelLabel={notification.cancelLabel} color={notification.color} key={notification.key} onClose={() => clearNotification(notification.key)} duration={notification.duration} onDurationEndAction={notification.onDurationEndAction} onCancelDurationEndAction={notification.onCancelDurationEndAction} > {notification.content} {notification.actions && ( <NotificationActions> {notification.actions} </NotificationActions> )} </NotificationItem> ))} </Notification> ); const mountNotificationNode = () => { if (isPortalDisabled) { return notificationNode; } return ReactDOM.createPortal(notificationNode, portalTarget); }; return ( <NotificationContext.Provider value={value}> { children } { mountNotificationNode() } </NotificationContext.Provider> ); }; export const useNotification = () => React.useContext(NotificationContext); NotificationProvider.propTypes = propTypes; NotificationProvider.defaultProps = defaultProps;