@afzalimdad9/react-alert
Version:
A simple react alert component
132 lines • 5.46 kB
JavaScript
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
import React, { Fragment, useState, useRef, useEffect, useCallback, } from 'react';
import PropTypes from 'prop-types';
import { TransitionGroup } from 'react-transition-group';
import { createPortal } from 'react-dom';
import DefaultContext from './Context';
import Wrapper from './Wrapper';
import Transition from './Transition';
import { positions, transitions, types } from './options';
import { groupBy } from './helpers';
const Provider = (_a) => {
var { children, offset, position, timeout, type, transition, containerStyle, template: AlertComponent, context: Context } = _a, props = __rest(_a, ["children", "offset", "position", "timeout", "type", "transition", "containerStyle", "template", "context"]);
const root = useRef(null);
const alertContext = useRef(null);
const timersId = useRef([]);
const [alerts, setAlerts] = useState([]);
useEffect(() => {
root.current = document.createElement('div');
root.current.id = '__react-alert__';
document.body.appendChild(root.current);
const timersIdRef = timersId.current;
return () => {
timersIdRef.forEach(clearTimeout);
if (root.current)
document.body.removeChild(root.current);
};
}, []);
const remove = useCallback((alert) => {
setAlerts((currentAlerts) => {
const lengthBeforeRemove = currentAlerts.length;
const filteredAlerts = currentAlerts.filter((a) => a.id !== alert.id);
if (lengthBeforeRemove > filteredAlerts.length && alert.options.onClose) {
alert.options.onClose();
}
return filteredAlerts;
});
}, []);
const removeAll = useCallback(() => {
alertContext.current.alerts.forEach(remove);
}, [remove]);
const show = useCallback((message = '', options = {}) => {
const id = Math.random().toString(36).substr(2, 9);
const alertOptions = Object.assign({ position: options.position || position, timeout,
type }, options);
const alert = {
id,
message,
options: alertOptions,
close: () => remove(alert),
};
if (alert.options.timeout) {
const timerId = setTimeout(() => {
remove(alert);
timersId.current.splice(timersId.current.indexOf(timerId), 1);
}, alert.options.timeout);
timersId.current.push(timerId);
}
setAlerts((state) => state.concat(alert));
if (alert.options.onOpen)
alert.options.onOpen();
return alert;
}, [position, remove, timeout, type]);
const success = useCallback((message = '', options = {}) => {
options.type = types.SUCCESS;
return show(message, options);
}, [show]);
const error = useCallback((message = '', options = {}) => {
options.type = types.ERROR;
return show(message, options);
}, [show]);
const info = useCallback((message = '', options = {}) => {
options.type = types.INFO;
return show(message, options);
}, [show]);
alertContext.current = {
alerts,
show,
remove,
removeAll,
success,
error,
info,
};
const alertsByPosition = groupBy(alerts, (alert) => alert.options.position);
return (React.createElement(Context.Provider, { value: alertContext.current },
children,
root.current &&
createPortal(React.createElement(Fragment, null, Object.values(positions).map((position) => {
return (React.createElement(TransitionGroup, Object.assign({ appear: true, key: position, options: { position, containerStyle }, component: Wrapper }, props), alertsByPosition[position] ? (alertsByPosition[position].map((alert) => (React.createElement(Transition, { type: transition, key: alert.id },
React.createElement(AlertComponent, Object.assign({ style: { margin: offset, pointerEvents: 'all' } }, alert)))))) : (React.createElement(React.Fragment, null))));
})), root.current)));
};
Provider.propTypes = {
offset: PropTypes.string,
position: PropTypes.oneOf(Object.values(positions)),
timeout: PropTypes.number,
type: PropTypes.oneOf(Object.values(types)),
transition: PropTypes.oneOf(Object.values(transitions)),
containerStyle: PropTypes.object,
template: PropTypes.oneOfType([
PropTypes.element,
PropTypes.func,
PropTypes.elementType,
]).isRequired,
context: PropTypes.shape({
Provider: PropTypes.object,
Consumer: PropTypes.object,
}),
};
Provider.defaultProps = {
offset: '10px',
position: positions.TOP_CENTER,
timeout: 0,
type: types.INFO,
transition: transitions.FADE,
containerStyle: {
zIndex: 100,
},
context: DefaultContext,
};
export default Provider;
//# sourceMappingURL=Provider.js.map