399 lines
14 KiB
JavaScript
399 lines
14 KiB
JavaScript
'use strict';
|
|
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
|
|
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
|
|
|
|
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
|
|
|
|
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
|
|
|
|
var _react = require('react');
|
|
|
|
var _react2 = _interopRequireDefault(_react);
|
|
|
|
var _propTypes = require('prop-types');
|
|
|
|
var _propTypes2 = _interopRequireDefault(_propTypes);
|
|
|
|
var _glamor = require('glamor');
|
|
|
|
var _TransitionGroup = require('react-transition-group/TransitionGroup');
|
|
|
|
var _TransitionGroup2 = _interopRequireDefault(_TransitionGroup);
|
|
|
|
var _Toast = require('./Toast');
|
|
|
|
var _Toast2 = _interopRequireDefault(_Toast);
|
|
|
|
var _DefaultCloseButton = require('./DefaultCloseButton');
|
|
|
|
var _DefaultCloseButton2 = _interopRequireDefault(_DefaultCloseButton);
|
|
|
|
var _DefaultTransition = require('./DefaultTransition');
|
|
|
|
var _DefaultTransition2 = _interopRequireDefault(_DefaultTransition);
|
|
|
|
var _constant = require('./constant');
|
|
|
|
var _style = require('./style');
|
|
|
|
var _style2 = _interopRequireDefault(_style);
|
|
|
|
var _EventManager = require('./util/EventManager');
|
|
|
|
var _EventManager2 = _interopRequireDefault(_EventManager);
|
|
|
|
var _propValidator = require('./util/propValidator');
|
|
|
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
|
|
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
|
|
|
|
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
|
|
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
|
|
|
|
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
|
|
|
|
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
|
|
var toastPosition = function toastPosition(pos) {
|
|
var positionKey = pos.toUpperCase().replace('-', '_');
|
|
var positionRule = typeof _constant.POSITION[positionKey] !== 'undefined' ? _style2.default[positionKey] : _style2.default.TOP_RIGHT;
|
|
|
|
/** define margin for center toast based on toast witdh */
|
|
if (positionKey.indexOf('CENTER') !== -1 && typeof positionRule.marginLeft === 'undefined') {
|
|
positionRule.marginLeft = '-' + parseInt(_style2.default.width, 10) / 2 + 'px';
|
|
}
|
|
|
|
return (0, _glamor.css)(positionRule, (0, _glamor.css)(_defineProperty({}, '@media ' + _style2.default.mobile, _extends({
|
|
left: 0,
|
|
margin: 0,
|
|
position: 'fixed'
|
|
}, pos.substring(0, 3) === 'top' ? { top: 0 } : { bottom: 0 }))));
|
|
};
|
|
|
|
var container = function container(disablePointer, position) {
|
|
return (0, _glamor.css)(_extends({
|
|
zIndex: _style2.default.zIndex,
|
|
position: 'fixed',
|
|
padding: '4px',
|
|
width: _style2.default.width,
|
|
boxSizing: 'border-box',
|
|
color: '#fff'
|
|
}, disablePointer ? { pointerEvents: 'none' } : {}, _defineProperty({}, '@media ' + _style2.default.mobile, {
|
|
width: '100vw',
|
|
padding: 0
|
|
})), toastPosition(position));
|
|
};
|
|
|
|
var ToastContainer = function (_Component) {
|
|
_inherits(ToastContainer, _Component);
|
|
|
|
function ToastContainer() {
|
|
var _ref;
|
|
|
|
var _temp, _this, _ret;
|
|
|
|
_classCallCheck(this, ToastContainer);
|
|
|
|
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
|
|
args[_key] = arguments[_key];
|
|
}
|
|
|
|
return _ret = (_temp = (_this = _possibleConstructorReturn(this, (_ref = ToastContainer.__proto__ || Object.getPrototypeOf(ToastContainer)).call.apply(_ref, [this].concat(args))), _this), _this.state = {
|
|
toast: [],
|
|
isDocumentHidden: false
|
|
}, _this.collection = {}, _this.isDocumentHidden = function () {
|
|
return _this.setState({ isDocumentHidden: document.hidden });
|
|
}, _this.isToastActive = function (id) {
|
|
return _this.state.toast.indexOf(parseInt(id, 10)) !== -1;
|
|
}, _temp), _possibleConstructorReturn(_this, _ret);
|
|
}
|
|
|
|
/**
|
|
* Hold toast ids
|
|
*/
|
|
|
|
|
|
/**
|
|
* Hold toast's informations:
|
|
* - what to render
|
|
* - position
|
|
* - raw content
|
|
* - options
|
|
*/
|
|
|
|
|
|
_createClass(ToastContainer, [{
|
|
key: 'componentDidMount',
|
|
value: function componentDidMount() {
|
|
var _this2 = this;
|
|
|
|
var SHOW = _constant.ACTION.SHOW,
|
|
CLEAR = _constant.ACTION.CLEAR,
|
|
MOUNTED = _constant.ACTION.MOUNTED;
|
|
|
|
_EventManager2.default.on(SHOW, function (content, options) {
|
|
return _this2.show(content, options);
|
|
}).on(CLEAR, function (id) {
|
|
return id !== null ? _this2.removeToast(id) : _this2.clear();
|
|
}).emit(MOUNTED, this);
|
|
document.addEventListener('visibilitychange', this.isDocumentHidden);
|
|
}
|
|
}, {
|
|
key: 'componentWillUnmount',
|
|
value: function componentWillUnmount() {
|
|
_EventManager2.default.off(_constant.ACTION.SHOW);
|
|
_EventManager2.default.off(_constant.ACTION.CLEAR);
|
|
document.removeEventListener('visibilitychange', this.isDocumentHidden);
|
|
}
|
|
}, {
|
|
key: 'removeToast',
|
|
value: function removeToast(id) {
|
|
this.setState({
|
|
toast: this.state.toast.filter(function (v) {
|
|
return v !== parseInt(id, 10);
|
|
})
|
|
});
|
|
}
|
|
}, {
|
|
key: 'makeCloseButton',
|
|
value: function makeCloseButton(toastClose, toastId, type) {
|
|
var _this3 = this;
|
|
|
|
var closeButton = this.props.closeButton;
|
|
|
|
if ((0, _react.isValidElement)(toastClose) || toastClose === false) {
|
|
closeButton = toastClose;
|
|
}
|
|
|
|
return closeButton === false ? false : (0, _react.cloneElement)(closeButton, {
|
|
closeToast: function closeToast() {
|
|
return _this3.removeToast(toastId);
|
|
},
|
|
type: type
|
|
});
|
|
}
|
|
}, {
|
|
key: 'getAutoCloseDelay',
|
|
value: function getAutoCloseDelay(toastAutoClose) {
|
|
return toastAutoClose === false || (0, _propValidator.isValidDelay)(toastAutoClose) ? toastAutoClose : this.props.autoClose;
|
|
}
|
|
}, {
|
|
key: 'isFunction',
|
|
value: function isFunction(object) {
|
|
return !!(object && object.constructor && object.call && object.apply);
|
|
}
|
|
}, {
|
|
key: 'canBeRendered',
|
|
value: function canBeRendered(content) {
|
|
return (0, _react.isValidElement)(content) || typeof content === 'string' || typeof content === 'number' || this.isFunction(content);
|
|
}
|
|
}, {
|
|
key: 'show',
|
|
value: function show(content, options) {
|
|
var _this4 = this;
|
|
|
|
if (!this.canBeRendered(content)) {
|
|
throw new Error('The element you provided cannot be rendered. You provided an element of type ' + (typeof content === 'undefined' ? 'undefined' : _typeof(content)));
|
|
}
|
|
var toastId = options.toastId;
|
|
var closeToast = function closeToast() {
|
|
return _this4.removeToast(toastId);
|
|
};
|
|
var toastOptions = {
|
|
id: toastId,
|
|
type: options.type,
|
|
closeToast: closeToast,
|
|
updateId: options.updateId,
|
|
position: options.position || this.props.position,
|
|
transition: options.transition || this.props.transition,
|
|
className: options.className || this.props.toastClassName,
|
|
bodyClassName: options.bodyClassName || this.props.bodyClassName,
|
|
closeButton: this.makeCloseButton(options.closeButton, toastId, options.type),
|
|
pauseOnHover: options.pauseOnHover !== null ? options.pauseOnHover : this.props.pauseOnHover,
|
|
closeOnClick: options.closeOnClick !== null ? options.closeOnClick : this.props.closeOnClick,
|
|
progressClassName: options.progressClassName || this.props.progressClassName,
|
|
autoClose: this.getAutoCloseDelay(options.autoClose !== false ? parseInt(options.autoClose, 10) : options.autoClose),
|
|
hideProgressBar: typeof options.hideProgressBar === 'boolean' ? options.hideProgressBar : this.props.hideProgressBar
|
|
};
|
|
|
|
this.isFunction(options.onOpen) && (toastOptions.onOpen = options.onOpen);
|
|
|
|
this.isFunction(options.onClose) && (toastOptions.onClose = options.onClose);
|
|
|
|
/**
|
|
* add closeToast function to react component only
|
|
*/
|
|
if ((0, _react.isValidElement)(content) && typeof content.type !== 'string' && typeof content.type !== 'number') {
|
|
content = (0, _react.cloneElement)(content, {
|
|
closeToast: closeToast
|
|
});
|
|
} else if (this.isFunction(content)) {
|
|
content = content({ closeToast: closeToast });
|
|
}
|
|
|
|
this.collection = _extends({}, this.collection, _defineProperty({}, toastId, {
|
|
position: toastOptions.position,
|
|
options: toastOptions,
|
|
content: content
|
|
}));
|
|
|
|
this.setState({
|
|
toast: toastOptions.updateId !== null ? [].concat(_toConsumableArray(this.state.toast)) : [].concat(_toConsumableArray(this.state.toast), [toastId])
|
|
});
|
|
}
|
|
}, {
|
|
key: 'makeToast',
|
|
value: function makeToast(content, options) {
|
|
return _react2.default.createElement(
|
|
_Toast2.default,
|
|
_extends({}, options, {
|
|
isDocumentHidden: this.state.isDocumentHidden,
|
|
key: 'toast-' + options.id
|
|
}),
|
|
content
|
|
);
|
|
}
|
|
}, {
|
|
key: 'clear',
|
|
value: function clear() {
|
|
this.setState({ toast: [] });
|
|
}
|
|
}, {
|
|
key: 'renderToast',
|
|
value: function renderToast() {
|
|
var _this5 = this;
|
|
|
|
var toastToRender = {};
|
|
var _props = this.props,
|
|
className = _props.className,
|
|
style = _props.style,
|
|
newestOnTop = _props.newestOnTop;
|
|
|
|
var collection = newestOnTop ? Object.keys(this.collection).reverse() : Object.keys(this.collection);
|
|
|
|
collection.forEach(function (toastId) {
|
|
var item = _this5.collection[toastId];
|
|
toastToRender[item.position] || (toastToRender[item.position] = []);
|
|
|
|
if (_this5.state.toast.indexOf(parseInt(toastId, 10)) !== -1) {
|
|
toastToRender[item.position].push(_this5.makeToast(item.content, item.options));
|
|
} else {
|
|
toastToRender[item.position].push(null);
|
|
delete _this5.collection[toastId];
|
|
}
|
|
});
|
|
|
|
return Object.keys(toastToRender).map(function (position) {
|
|
var disablePointer = toastToRender[position].length === 1 && toastToRender[position][0] === null;
|
|
|
|
return _react2.default.createElement(
|
|
_TransitionGroup2.default,
|
|
_extends({}, typeof className !== 'string' ? (0, _glamor.css)(container(disablePointer, position), className) : container(disablePointer, position), typeof className === 'string' && { className: className }, style !== null && { style: style }, {
|
|
key: 'container-' + position
|
|
}),
|
|
toastToRender[position]
|
|
);
|
|
});
|
|
}
|
|
}, {
|
|
key: 'render',
|
|
value: function render() {
|
|
return _react2.default.createElement(
|
|
'div',
|
|
null,
|
|
this.renderToast()
|
|
);
|
|
}
|
|
}]);
|
|
|
|
return ToastContainer;
|
|
}(_react.Component);
|
|
|
|
ToastContainer.propTypes = {
|
|
/**
|
|
* Set toast position
|
|
*/
|
|
position: _propTypes2.default.oneOf((0, _propValidator.objectValues)(_constant.POSITION)),
|
|
|
|
/**
|
|
* Disable or set autoClose delay
|
|
*/
|
|
autoClose: _propValidator.falseOrDelay,
|
|
|
|
/**
|
|
* Disable or set a custom react element for the close button
|
|
*/
|
|
closeButton: _propValidator.falseOrElement,
|
|
|
|
/**
|
|
* Hide or not progress bar when autoClose is enabled
|
|
*/
|
|
hideProgressBar: _propTypes2.default.bool,
|
|
|
|
/**
|
|
* Pause toast duration on hover
|
|
*/
|
|
pauseOnHover: _propTypes2.default.bool,
|
|
|
|
/**
|
|
* Dismiss toast on click
|
|
*/
|
|
closeOnClick: _propTypes2.default.bool,
|
|
|
|
/**
|
|
* Newest on top
|
|
*/
|
|
newestOnTop: _propTypes2.default.bool,
|
|
|
|
/**
|
|
* An optional className
|
|
*/
|
|
className: _propTypes2.default.oneOfType([_propTypes2.default.string, _propTypes2.default.object]),
|
|
|
|
/**
|
|
* An optional style
|
|
*/
|
|
style: _propTypes2.default.object,
|
|
|
|
/**
|
|
* An optional className for the toast
|
|
*/
|
|
toastClassName: _propTypes2.default.oneOfType([_propTypes2.default.string, _propTypes2.default.object]),
|
|
|
|
/**
|
|
* An optional className for the toast body
|
|
*/
|
|
bodyClassName: _propTypes2.default.oneOfType([_propTypes2.default.string, _propTypes2.default.object]),
|
|
|
|
/**
|
|
* An optional className for the toast progress bar
|
|
*/
|
|
progressClassName: _propTypes2.default.oneOfType([_propTypes2.default.string, _propTypes2.default.object]),
|
|
|
|
/**
|
|
* Define enter and exit transition using react-transition-group
|
|
*/
|
|
transition: _propTypes2.default.func
|
|
};
|
|
ToastContainer.defaultProps = {
|
|
position: _constant.POSITION.TOP_RIGHT,
|
|
transition: _DefaultTransition2.default,
|
|
autoClose: 5000,
|
|
hideProgressBar: false,
|
|
closeButton: _react2.default.createElement(_DefaultCloseButton2.default, null),
|
|
pauseOnHover: true,
|
|
closeOnClick: true,
|
|
newestOnTop: false,
|
|
className: null,
|
|
style: null,
|
|
toastClassName: '',
|
|
bodyClassName: '',
|
|
progressClassName: ''
|
|
};
|
|
exports.default = ToastContainer; |