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