saagie-ui
Version:
Saagie UI from Saagie Design System
124 lines (107 loc) • 3.56 kB
JavaScript
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;