UNPKG

react-customized-notifications

Version:

A React Notification System forked from https://github.com/igorprado/react-notification-system

285 lines (230 loc) 7.94 kB
var React = require('react'); var createReactClass = require('create-react-class'); var PropTypes = require('prop-types'); var merge = require('object-assign'); var NotificationContainer = require('./NotificationContainer'); var Constants = require('./constants'); var Styles = require('./styles'); var NotificationSystem = createReactClass({ uid: 3400, _isMounted: false, _getStyles: { overrideStyle: {}, overrideWidth: null, elements: { notification: 'NotificationItem', title: 'Title', messageWrapper: 'MessageWrapper', dismiss: 'Dismiss', action: 'Action', actionWrapper: 'ActionWrapper' }, setOverrideStyle: function(style) { this.overrideStyle = style; }, wrapper: function() { if (!this.overrideStyle) return {}; return merge({}, Styles.Wrapper, this.overrideStyle.Wrapper); }, container: function(position) { var override = this.overrideStyle.Containers || {}; if (!this.overrideStyle) return {}; this.overrideWidth = Styles.Containers.DefaultStyle.width; if (override.DefaultStyle && override.DefaultStyle.width) { this.overrideWidth = override.DefaultStyle.width; } if (override[position] && override[position].width) { this.overrideWidth = override[position].width; } return merge({}, Styles.Containers.DefaultStyle, Styles.Containers[position], override.DefaultStyle, override[position]); }, byElement: function(element) { var self = this; return function(level) { var _element = self.elements[element]; var override = self.overrideStyle[_element] || {}; if (!self.overrideStyle) return {}; return merge({}, Styles[_element].DefaultStyle, Styles[_element][level], override.DefaultStyle, override[level]); }; } }, _didNotificationRemoved: function(uid) { var notification; var notifications = this.state.notifications.filter(function(toCheck) { if (toCheck.uid === uid) { notification = toCheck; return false; } return true; }); if (this._isMounted) { this.setState({ notifications: notifications }); } if (notification && notification.onRemove) { notification.onRemove(notification); } }, getInitialState: function() { return { notifications: [] }; }, propTypes: { style: PropTypes.oneOfType([ PropTypes.bool, PropTypes.object ]), noAnimation: PropTypes.bool, allowHTML: PropTypes.bool, itemClassName: PropTypes.string, containerClassName: PropTypes.string, itemOnClick: PropTypes.func }, getDefaultProps: function() { return { style: {}, noAnimation: false, allowHTML: false, itemClassName: '', containerClassName: '' }; }, addNotification: function(notification) { var _notification = merge({}, Constants.notification, notification); var notifications = this.state.notifications; var i; _notification.itemClassName = this.props.itemClassName; if (!_notification.level) { throw new Error('notification level is required.'); } if (Object.keys(Constants.levels).indexOf(_notification.level) === -1) { throw new Error('\'' + _notification.level + '\' is not a valid level.'); } // eslint-disable-next-line if (isNaN(_notification.autoDismiss)) { throw new Error('\'autoDismiss\' must be a number.'); } if (Object.keys(Constants.positions).indexOf(_notification.position) === -1) { throw new Error('\'' + _notification.position + '\' is not a valid position.'); } // Some preparations _notification.position = _notification.position.toLowerCase(); _notification.level = _notification.level.toLowerCase(); _notification.autoDismiss = parseInt(_notification.autoDismiss, 10); _notification.uid = _notification.uid || this.uid; _notification.ref = 'notification-' + _notification.uid; this.uid += 1; // do not add if the notification already exists based on supplied uid for (i = 0; i < notifications.length; i += 1) { if (notifications[i].uid === _notification.uid) { return false; } } notifications.push(_notification); if (typeof _notification.onAdd === 'function') { notification.onAdd(_notification); } this.setState({ notifications: notifications }); return _notification; }, getNotificationRef: function(notification) { var self = this; var foundNotification = null; Object.keys(this.refs).forEach(function(container) { if (container.indexOf('container') > -1) { Object.keys(self.refs[container].refs).forEach(function(_notification) { var uid = notification.uid ? notification.uid : notification; if (_notification === 'notification-' + uid) { // NOTE: Stop iterating further and return the found notification. // Since UIDs are uniques and there won't be another notification found. foundNotification = self.refs[container].refs[_notification]; } }); } }); return foundNotification; }, removeNotification: function(notification) { var foundNotification = this.getNotificationRef(notification); return foundNotification && foundNotification._hideNotification(); }, editNotification: function(notification, newNotification) { var foundNotification = null; // NOTE: Find state notification to update by using // `setState` and forcing React to re-render the component. var uid = notification.uid ? notification.uid : notification; var newNotifications = this.state.notifications.filter(function(stateNotification) { if (uid === stateNotification.uid) { foundNotification = stateNotification; return false; } return true; }); if (!foundNotification) { return; } newNotifications.push(merge( {}, foundNotification, newNotification )); this.setState({ notifications: newNotifications }); }, clearNotifications: function() { var self = this; Object.keys(this.refs).forEach(function(container) { if (container.indexOf('container') > -1) { Object.keys(self.refs[container].refs).forEach(function(_notification) { self.refs[container].refs[_notification]._hideNotification(); }); } }); }, componentDidMount: function() { this._getStyles.setOverrideStyle(this.props.style); this._isMounted = true; }, componentWillUnmount: function() { this._isMounted = false; }, render: function() { var self = this; var containers = null; var notifications = this.state.notifications; var itemOnClick = self.props.itemOnClick; if (notifications.length) { containers = Object.keys(Constants.positions).map(function(position) { var _notifications = notifications.filter(function(notification) { return position === notification.position; }); if (!_notifications.length) { return null; } return ( <NotificationContainer containerClassName={ self.props.containerClassName || '' } ref={ 'container-' + position } key={ position } position={ position } notifications={ _notifications } getStyles={ self._getStyles } onRemove={ self._didNotificationRemoved } noAnimation={ self.props.noAnimation } allowHTML={ self.props.allowHTML } itemOnClick={ itemOnClick } /> ); }); } return ( <div className="notifications-wrapper" style={ this._getStyles.wrapper() }> { containers } </div> ); } }); module.exports = NotificationSystem;