UNPKG

saagie-ui

Version:

Saagie UI from Saagie Design System

140 lines (124 loc) 3.75 kB
import React, { useEffect, useState, useRef } from 'react'; import PropTypes from 'prop-types'; import classnames from 'classnames'; import { NotificationActions } from './NotificationActions'; import { modifierCSS } from '../../../helpers'; const propTypes = { /** * The content of the cancel duration end action button. */ cancelLabel: PropTypes.node, /** * The content of the NotificationItem. The simple use case is just a message * in the notification. */ children: PropTypes.node.isRequired, /** * The component used for the root node. * Either a string to use a DOM element or a component. */ tag: PropTypes.elementType, defaultClassName: PropTypes.oneOfType([PropTypes.string, PropTypes.arrayOf(PropTypes.string)]), color: PropTypes.oneOf(['', 'primary', 'success', 'warning', 'danger']), duration: PropTypes.oneOf([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 12, 14, 16, 18, 20]), /** * The function that will be called on close. * Used by NotificationProvider to release memory. */ onClose: PropTypes.func, /** * The function that will be called when the notification hide itself and * was not cancelled. */ onDurationEndAction: PropTypes.func, /** * The function that will be called when the user clicks on the undo button. * The button only appears when the `onDurationEndAction` prop is given. */ onCancelDurationEndAction: PropTypes.func, }; const defaultProps = { cancelLabel: 'Undo', tag: 'div', defaultClassName: 'sui-o-notification__item', color: '', duration: 0, /** Callback function that will be executed on close */ onClose: () => {}, /** Callback function that will be executed when the duration end */ onDurationEndAction: undefined, onCancelDurationEndAction: () => {}, }; /** * The NotificationItem represents the notification that we see on the interface. * * Behavior : * - If onDurationEndAction is present, the NotificationItem will add a button to * cancel this action. */ export const NotificationItem = ({ cancelLabel, children, color, defaultClassName, duration, onClose, onCancelDurationEndAction, onDurationEndAction, tag: Tag, ...attributes }) => { const [isClosed, setIsClosed] = useState(false); const onDurationEndTimeoutRef = useRef(null); const close = () => { if (onDurationEndAction) { onDurationEndAction(); clearTimeout(onDurationEndTimeoutRef.current); } setIsClosed(true); onClose(); }; useEffect(() => { if (duration > 0) { const timeout = setTimeout(() => { close(); }, duration * 1000); if (onDurationEndAction) { onDurationEndTimeoutRef.current = setTimeout(() => { onDurationEndAction(); }, duration * 1000); } return () => { clearTimeout(timeout); }; } return () => {}; }, []); const cancelOnDurationEndAction = () => { clearTimeout(onDurationEndTimeoutRef.current); setIsClosed(true); onClose(); onCancelDurationEndAction(); }; const classes = classnames( defaultClassName, modifierCSS(color), isClosed ? 'as--hidden' : 'as--toggle', ); if (!isClosed) { return ( <Tag className={classes} data-delay={duration} {...attributes}> {children} <button type="button" aria-label="Close" className="sui-o-notification__clear" onClick={close} /> {onDurationEndAction && ( <NotificationActions> <button type="button" onClick={cancelOnDurationEndAction}>{cancelLabel}</button> </NotificationActions> )} </Tag> ); } return ''; }; NotificationItem.propTypes = propTypes; NotificationItem.defaultProps = defaultProps;