UNPKG

react-toastify

Version:
1,185 lines (1,003 loc) 34.2 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } var _extends = _interopDefault(require('@babel/runtime/helpers/extends')); var _objectWithoutPropertiesLoose = _interopDefault(require('@babel/runtime/helpers/objectWithoutPropertiesLoose')); var _inheritsLoose = _interopDefault(require('@babel/runtime/helpers/inheritsLoose')); var React = require('react'); var React__default = _interopDefault(React); var PropTypes = _interopDefault(require('prop-types')); var cx = _interopDefault(require('classnames')); var TransitionGroup = _interopDefault(require('react-transition-group/TransitionGroup')); var Transition = _interopDefault(require('react-transition-group/Transition')); var reactDom = require('react-dom'); var POSITION = { TOP_LEFT: 'top-left', TOP_RIGHT: 'top-right', TOP_CENTER: 'top-center', BOTTOM_LEFT: 'bottom-left', BOTTOM_RIGHT: 'bottom-right', BOTTOM_CENTER: 'bottom-center' }; var TYPE = { INFO: 'info', SUCCESS: 'success', WARNING: 'warning', ERROR: 'error', DEFAULT: 'default' }; var ACTION = { SHOW: 0, CLEAR: 1, DID_MOUNT: 2, WILL_UNMOUNT: 3, ON_CHANGE: 4 }; var NOOP = function NOOP() {}; function isValidDelay(val) { return typeof val === 'number' && !isNaN(val) && val > 0; } function objectValues(obj) { return Object.keys(obj).map(function (key) { return obj[key]; }); } var canUseDom = !!(typeof window !== 'undefined' && window.document && window.document.createElement); function withRequired(fn) { fn.isRequired = function (props, propName, componentName) { var prop = props[propName]; if (typeof prop === 'undefined') { return new Error("The prop " + propName + " is marked as required in \n " + componentName + ", but its value is undefined."); } fn(props, propName, componentName); }; return fn; } var falseOrDelay = withRequired(function (props, propName, componentName) { var prop = props[propName]; if (prop !== false && !isValidDelay(prop)) { return new Error(componentName + " expect " + propName + " \n to be a valid Number > 0 or equal to false. " + prop + " given."); } return null; }); function ProgressBar(_ref) { var _animationEvent; var delay = _ref.delay, isRunning = _ref.isRunning, closeToast = _ref.closeToast, type = _ref.type, hide = _ref.hide, className = _ref.className, userStyle = _ref.style, controlledProgress = _ref.controlledProgress, progress = _ref.progress, isProgressDone = _ref.isProgressDone, rtl = _ref.rtl; var style = _extends({}, userStyle, { animationDuration: delay + "ms", animationPlayState: isRunning ? 'running' : 'paused', opacity: hide ? 0 : 1, transform: controlledProgress ? "scaleX(" + progress + ")" : null }); var classNames = cx('Toastify__progress-bar', controlledProgress ? 'Toastify__progress-bar--controlled' : 'Toastify__progress-bar--animated', "Toastify__progress-bar--" + type, { 'Toastify__progress-bar--rtl': rtl }, className); var animationEvent = (_animationEvent = {}, _animationEvent[controlledProgress && isProgressDone ? 'onTransitionEnd' : 'onAnimationEnd'] = controlledProgress && !isProgressDone ? null : closeToast, _animationEvent); return React__default.createElement("div", _extends({ className: classNames, style: style }, animationEvent)); } ProgressBar.propTypes = { /** * The animation delay which determine when to close the toast */ delay: falseOrDelay.isRequired, /** * Whether or not the animation is running or paused */ isRunning: PropTypes.bool.isRequired, /** * Func to close the current toast */ closeToast: PropTypes.func.isRequired, /** * Support rtl content */ rtl: PropTypes.bool.isRequired, /** * Optional type : info, success ... */ type: PropTypes.string, /** * Hide or not the progress bar */ hide: PropTypes.bool, /** * Optionnal className */ className: PropTypes.oneOfType([PropTypes.string, PropTypes.object]), /** * Controlled progress value */ progress: PropTypes.number, /** * Tell wether or not controlled progress bar is used */ controlledProgress: PropTypes.bool, /** * Helper to close the toast when using controlled progress value */ isProgressDone: PropTypes.bool }; ProgressBar.defaultProps = { type: TYPE.DEFAULT, hide: false }; function getX(e) { return e.targetTouches && e.targetTouches.length >= 1 ? e.targetTouches[0].clientX : e.clientX; } function getY(e) { return e.targetTouches && e.targetTouches.length >= 1 ? e.targetTouches[0].clientY : e.clientY; } var iLoveInternetExplorer = canUseDom && /(msie|trident)/i.test(navigator.userAgent); var Toast = /*#__PURE__*/ function (_Component) { _inheritsLoose(Toast, _Component); function Toast() { var _this; for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _this = _Component.call.apply(_Component, [this].concat(args)) || this; _this.state = { isRunning: true, preventExitTransition: false }; _this.flag = { canCloseOnClick: true, canDrag: false }; _this.drag = { start: 0, x: 0, y: 0, deltaX: 0, removalDistance: 0 }; _this.boundingRect = null; _this.ref = null; _this.pauseToast = function () { if (_this.props.autoClose) { _this.setState({ isRunning: false }); } }; _this.playToast = function () { if (_this.props.autoClose) { _this.setState({ isRunning: true }); } }; _this.onDragStart = function (e) { _this.flag.canCloseOnClick = true; _this.flag.canDrag = true; _this.boundingRect = _this.ref.getBoundingClientRect(); _this.ref.style.transition = ''; _this.drag.start = _this.drag.x = getX(e.nativeEvent); _this.drag.removalDistance = _this.ref.offsetWidth * (_this.props.draggablePercent / 100); }; _this.onDragMove = function (e) { if (_this.flag.canDrag) { if (_this.state.isRunning) { _this.pauseToast(); } _this.drag.x = getX(e); _this.drag.deltaX = _this.drag.x - _this.drag.start; _this.drag.y = getY(e); // prevent false positif during a toast click _this.drag.start !== _this.drag.x && (_this.flag.canCloseOnClick = false); _this.ref.style.transform = "translateX(" + _this.drag.deltaX + "px)"; _this.ref.style.opacity = 1 - Math.abs(_this.drag.deltaX / _this.drag.removalDistance); } }; _this.onDragEnd = function (e) { if (_this.flag.canDrag) { _this.flag.canDrag = false; if (Math.abs(_this.drag.deltaX) > _this.drag.removalDistance) { _this.setState({ preventExitTransition: true }, _this.props.closeToast); return; } _this.ref.style.transition = 'transform 0.2s, opacity 0.2s'; _this.ref.style.transform = 'translateX(0)'; _this.ref.style.opacity = 1; } }; _this.onDragTransitionEnd = function () { if (_this.boundingRect) { var _this$boundingRect = _this.boundingRect, top = _this$boundingRect.top, bottom = _this$boundingRect.bottom, left = _this$boundingRect.left, right = _this$boundingRect.right; if (_this.props.pauseOnHover && _this.drag.x >= left && _this.drag.x <= right && _this.drag.y >= top && _this.drag.y <= bottom) { _this.pauseToast(); } else { _this.playToast(); } } }; _this.onExitTransitionEnd = function () { if (iLoveInternetExplorer) { _this.props.onExited(); return; } var height = _this.ref.scrollHeight; var style = _this.ref.style; requestAnimationFrame(function () { style.minHeight = 'initial'; style.height = height + 'px'; style.transition = 'all 0.4s '; requestAnimationFrame(function () { style.height = 0; style.padding = 0; style.margin = 0; }); setTimeout(function () { return _this.props.onExited(); }, 400); }); }; return _this; } var _proto = Toast.prototype; _proto.componentDidMount = function componentDidMount() { this.props.onOpen(this.props.children.props); if (this.props.draggable) { this.bindDragEvents(); } // Maybe I could bind the event in the ToastContainer and rely on delegation if (this.props.pauseOnFocusLoss) { this.bindFocusEvents(); } }; _proto.componentDidUpdate = function componentDidUpdate(prevProps) { if (prevProps.draggable !== this.props.draggable) { if (this.props.draggable) { this.bindDragEvents(); } else { this.unbindDragEvents(); } } if (prevProps.pauseOnFocusLoss !== this.props.pauseOnFocusLoss) { if (this.props.pauseOnFocusLoss) { this.bindFocusEvents(); } else { this.unbindFocusEvents(); } } }; _proto.componentWillUnmount = function componentWillUnmount() { this.props.onClose(this.props.children.props); if (this.props.draggable) { this.unbindDragEvents(); } if (this.props.pauseOnFocusLoss) { this.unbindFocusEvents(); } }; _proto.bindFocusEvents = function bindFocusEvents() { window.addEventListener('focus', this.playToast); window.addEventListener('blur', this.pauseToast); }; _proto.unbindFocusEvents = function unbindFocusEvents() { window.removeEventListener('focus', this.playToast); window.removeEventListener('blur', this.pauseToast); }; _proto.bindDragEvents = function bindDragEvents() { document.addEventListener('mousemove', this.onDragMove); document.addEventListener('mouseup', this.onDragEnd); document.addEventListener('touchmove', this.onDragMove); document.addEventListener('touchend', this.onDragEnd); }; _proto.unbindDragEvents = function unbindDragEvents() { document.removeEventListener('mousemove', this.onDragMove); document.removeEventListener('mouseup', this.onDragEnd); document.removeEventListener('touchmove', this.onDragMove); document.removeEventListener('touchend', this.onDragEnd); }; _proto.render = function render() { var _this2 = this; var _this$props = this.props, closeButton = _this$props.closeButton, children = _this$props.children, autoClose = _this$props.autoClose, pauseOnHover = _this$props.pauseOnHover, closeOnClick = _this$props.closeOnClick, type = _this$props.type, hideProgressBar = _this$props.hideProgressBar, closeToast = _this$props.closeToast, Transition = _this$props.transition, position = _this$props.position, className = _this$props.className, bodyClassName = _this$props.bodyClassName, progressClassName = _this$props.progressClassName, progressStyle = _this$props.progressStyle, updateId = _this$props.updateId, role = _this$props.role, progress = _this$props.progress, isProgressDone = _this$props.isProgressDone, rtl = _this$props.rtl; var toastProps = { className: cx('Toastify__toast', "Toastify__toast--" + type, { 'Toastify__toast--rtl': rtl }, className) }; if (autoClose && pauseOnHover) { toastProps.onMouseEnter = this.pauseToast; toastProps.onMouseLeave = this.playToast; } // prevent toast from closing when user drags the toast if (closeOnClick) { toastProps.onClick = function () { return _this2.flag.canCloseOnClick && closeToast(); }; } var controlledProgress = parseFloat(progress) === progress; return React__default.createElement(Transition, { in: this.props.in, appear: true, onExited: this.onExitTransitionEnd, position: position, preventExitTransition: this.state.preventExitTransition }, React__default.createElement("div", _extends({}, toastProps, { ref: function ref(_ref) { return _this2.ref = _ref; }, onMouseDown: this.onDragStart, onTouchStart: this.onDragStart, onMouseUp: this.onDragTransitionEnd, onTouchEnd: this.onDragTransitionEnd }), React__default.createElement("div", _extends({}, this.props.in && { role: role }, { className: cx('Toastify__toast-body', bodyClassName) }), children), closeButton && closeButton, (autoClose || controlledProgress) && React__default.createElement(ProgressBar, _extends({}, updateId && !controlledProgress ? { key: "pb-" + updateId } : {}, { rtl: rtl, delay: autoClose, isRunning: this.state.isRunning, closeToast: closeToast, hide: hideProgressBar, type: type, style: progressStyle, className: progressClassName, controlledProgress: controlledProgress, isProgressDone: isProgressDone, progress: progress })))); }; return Toast; }(React.Component); Toast.propTypes = { closeButton: PropTypes.oneOfType([PropTypes.node, PropTypes.bool]).isRequired, autoClose: falseOrDelay.isRequired, children: PropTypes.node.isRequired, closeToast: PropTypes.func.isRequired, position: PropTypes.oneOf(objectValues(POSITION)).isRequired, pauseOnHover: PropTypes.bool.isRequired, pauseOnFocusLoss: PropTypes.bool.isRequired, closeOnClick: PropTypes.bool.isRequired, transition: PropTypes.func.isRequired, rtl: PropTypes.bool.isRequired, hideProgressBar: PropTypes.bool.isRequired, draggable: PropTypes.bool.isRequired, draggablePercent: PropTypes.number.isRequired, in: PropTypes.bool, onExited: PropTypes.func, onOpen: PropTypes.func, onClose: PropTypes.func, type: PropTypes.oneOf(objectValues(TYPE)), className: PropTypes.oneOfType([PropTypes.string, PropTypes.object]), bodyClassName: PropTypes.oneOfType([PropTypes.string, PropTypes.object]), progressClassName: PropTypes.oneOfType([PropTypes.string, PropTypes.object]), progressStyle: PropTypes.object, progress: PropTypes.number, isProgressDone: PropTypes.bool, updateId: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), ariaLabel: PropTypes.string, containerId: PropTypes.oneOfType([PropTypes.string, PropTypes.number]) }; Toast.defaultProps = { type: TYPE.DEFAULT, in: true, onOpen: NOOP, onClose: NOOP, className: null, bodyClassName: null, progressClassName: null, updateId: null, role: 'alert' }; function CloseButton(_ref) { var closeToast = _ref.closeToast, type = _ref.type, ariaLabel = _ref.ariaLabel; return React__default.createElement("button", { className: "Toastify__close-button Toastify__close-button--" + type, type: "button", onClick: closeToast, "aria-label": ariaLabel }, "\u2716"); } CloseButton.propTypes = { closeToast: PropTypes.func, arialLabel: PropTypes.string }; CloseButton.defaultProps = { ariaLabel: 'close' }; function cssTransition (_ref) { var enter = _ref.enter, exit = _ref.exit, _ref$duration = _ref.duration, duration = _ref$duration === void 0 ? 750 : _ref$duration, _ref$appendPosition = _ref.appendPosition, appendPosition = _ref$appendPosition === void 0 ? false : _ref$appendPosition; return function Animation(_ref2) { var children = _ref2.children, position = _ref2.position, preventExitTransition = _ref2.preventExitTransition, props = _objectWithoutPropertiesLoose(_ref2, ["children", "position", "preventExitTransition"]); var enterClassName = appendPosition ? enter + "--" + position : enter; var exitClassName = appendPosition ? exit + "--" + position : exit; var enterDuration, exitDuration; if (Array.isArray(duration) && duration.length === 2) { enterDuration = duration[0]; exitDuration = duration[1]; } else { enterDuration = exitDuration = duration; } var onEnter = function onEnter(node) { node.classList.add(enterClassName); node.style.animationFillMode = 'forwards'; node.style.animationDuration = enterDuration * 0.001 + "s"; }; var onEntered = function onEntered(node) { node.classList.remove(enterClassName); node.style.cssText = ''; }; var onExit = function onExit(node) { node.classList.add(exitClassName); node.style.animationFillMode = 'forwards'; node.style.animationDuration = exitDuration * 0.001 + "s"; }; return React__default.createElement(Transition, _extends({}, props, { timeout: preventExitTransition ? 0 : { enter: enterDuration, exit: exitDuration }, onEnter: onEnter, onEntered: onEntered, onExit: preventExitTransition ? NOOP : onExit }), children); }; } var Bounce = cssTransition({ enter: 'Toastify__bounce-enter', exit: 'Toastify__bounce-exit', appendPosition: true }); var Slide = cssTransition({ enter: 'Toastify__slide-enter', exit: 'Toastify__slide-exit', duration: [450, 750], appendPosition: true }); var Zoom = cssTransition({ enter: 'Toastify__zoom-enter', exit: 'Toastify__zoom-exit' }); var Flip = cssTransition({ enter: 'Toastify__flip-enter', exit: 'Toastify__flip-exit' }); var eventManager = { list: new Map(), on: function on(event, callback) { this.list.has(event) || this.list.set(event, []); this.list.get(event).push(callback); return this; }, off: function off(event) { this.list.delete(event); return this; }, /** * Enqueue the event at the end of the call stack * Doing so let the user call toast as follow: * toast('1') * toast('2') * toast('3') * Without setTimemout the code above will not work */ emit: function emit(event) { for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { args[_key - 1] = arguments[_key]; } this.list.has(event) && this.list.get(event).forEach(function (callback) { return setTimeout(function () { callback.apply(void 0, args); }, 0); }); } }; var ToastContainer = /*#__PURE__*/ function (_Component) { _inheritsLoose(ToastContainer, _Component); function ToastContainer() { var _this; for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _this = _Component.call.apply(_Component, [this].concat(args)) || this; _this.state = { toast: [] }; _this.toastKey = 1; _this.collection = {}; _this.isToastActive = function (id) { return _this.state.toast.indexOf(id) !== -1; }; return _this; } var _proto = ToastContainer.prototype; _proto.componentDidMount = function componentDidMount() { var _this2 = this; eventManager.on(ACTION.SHOW, function (content, options) { return _this2.buildToast(content, options); }).on(ACTION.CLEAR, function (id) { return id == null ? _this2.clear() : _this2.removeToast(id); }).emit(ACTION.DID_MOUNT, this); }; _proto.componentWillUnmount = function componentWillUnmount() { eventManager.off(ACTION.SHOW).off(ACTION.CLEAR).emit(ACTION.WILL_UNMOUNT); }; _proto.removeToast = function removeToast(id) { this.setState({ toast: this.state.toast.filter(function (v) { return v !== id; }) }, this.dispatchChange); }; _proto.dispatchChange = function dispatchChange() { eventManager.emit(ACTION.ON_CHANGE, this.state.toast.length); }; _proto.makeCloseButton = function makeCloseButton(toastClose, toastId, type) { var _this3 = this; var closeButton = this.props.closeButton; if (React.isValidElement(toastClose) || toastClose === false) { closeButton = toastClose; } else if (toastClose === true) { closeButton = React__default.createElement(CloseButton, null); } return closeButton === false ? false : React.cloneElement(closeButton, { closeToast: function closeToast() { return _this3.removeToast(toastId); }, type: type }); }; _proto.getAutoCloseDelay = function getAutoCloseDelay(toastAutoClose) { return toastAutoClose === false || isValidDelay(toastAutoClose) ? toastAutoClose : this.props.autoClose; }; _proto.canBeRendered = function canBeRendered(content) { return React.isValidElement(content) || typeof content === 'string' || typeof content === 'number' || typeof content === 'function'; }; _proto.parseClassName = function parseClassName(prop) { if (typeof prop === 'string') { return prop; } else if (prop !== null && typeof prop === 'object' && 'toString' in prop) { return prop.toString(); } return null; }; _proto.belongToContainer = function belongToContainer(_ref) { var containerId = _ref.containerId; return containerId === this.props.containerId; }; _proto.buildToast = function buildToast(content, _ref2) { var _this4 = this; var delay = _ref2.delay, options = _objectWithoutPropertiesLoose(_ref2, ["delay"]); if (!this.canBeRendered(content)) { throw new Error("The element you provided cannot be rendered. You provided an element of type " + typeof content); } if (this.props.enableMultiContainer) { if (!this.belongToContainer(options)) { return null; } } var toastId = options.toastId; var closeToast = function closeToast() { return _this4.removeToast(toastId); }; var toastOptions = { id: toastId, // ⚠️ if no options.key, this.toastKey - 1 is assigned key: options.key || this.toastKey++, type: options.type, closeToast: closeToast, updateId: options.updateId, rtl: this.props.rtl, position: options.position || this.props.position, transition: options.transition || this.props.transition, className: this.parseClassName(options.className || this.props.toastClassName), bodyClassName: this.parseClassName(options.bodyClassName || this.props.bodyClassName), closeButton: this.makeCloseButton(options.closeButton, toastId, options.type), pauseOnHover: typeof options.pauseOnHover === 'boolean' ? options.pauseOnHover : this.props.pauseOnHover, pauseOnFocusLoss: typeof options.pauseOnFocusLoss === 'boolean' ? options.pauseOnFocusLoss : this.props.pauseOnFocusLoss, draggable: typeof options.draggable === 'boolean' ? options.draggable : this.props.draggable, draggablePercent: typeof options.draggablePercent === 'number' && !isNaN(options.draggablePercent) ? options.draggablePercent : this.props.draggablePercent, closeOnClick: typeof options.closeOnClick === 'boolean' ? options.closeOnClick : this.props.closeOnClick, progressClassName: this.parseClassName(options.progressClassName || this.props.progressClassName), progressStyle: this.props.progressStyle, autoClose: this.getAutoCloseDelay(options.autoClose), hideProgressBar: typeof options.hideProgressBar === 'boolean' ? options.hideProgressBar : this.props.hideProgressBar, progress: parseFloat(options.progress), isProgressDone: options.isProgressDone }; typeof options.onOpen === 'function' && (toastOptions.onOpen = options.onOpen); typeof options.onClose === 'function' && (toastOptions.onClose = options.onClose); // add closeToast function to react component only if (React.isValidElement(content) && typeof content.type !== 'string' && typeof content.type !== 'number') { content = React.cloneElement(content, { closeToast: closeToast }); } else if (typeof content === 'function') { content = content({ closeToast: closeToast }); } if (isValidDelay(delay)) { setTimeout(function () { _this4.appendToast(toastOptions, content, options.staleToastId); }, delay); } else { this.appendToast(toastOptions, content, options.staleToastId); } }; _proto.appendToast = function appendToast(options, content, staleToastId) { var _extends2; var id = options.id, updateId = options.updateId; this.collection = _extends({}, this.collection, (_extends2 = {}, _extends2[id] = { options: options, content: content, position: options.position }, _extends2)); this.setState({ toast: (updateId ? [].concat(this.state.toast) : [].concat(this.state.toast, [id])).filter(function (id) { return id !== staleToastId; }) }, this.dispatchChange); }; _proto.clear = function clear() { this.setState({ toast: [] }); }; _proto.renderToast = function renderToast() { var _this5 = this; var toastToRender = {}; var _this$props = this.props, className = _this$props.className, style = _this$props.style, newestOnTop = _this$props.newestOnTop; var collection = newestOnTop ? Object.keys(this.collection).reverse() : Object.keys(this.collection); // group toast by position collection.forEach(function (toastId) { var _this5$collection$toa = _this5.collection[toastId], position = _this5$collection$toa.position, options = _this5$collection$toa.options, content = _this5$collection$toa.content; toastToRender[position] || (toastToRender[position] = []); if (_this5.state.toast.indexOf(options.id) !== -1) { toastToRender[position].push(React__default.createElement(Toast, _extends({}, options, { isDocumentHidden: _this5.state.isDocumentHidden, key: "toast-" + options.key }), content)); } else { toastToRender[position].push(null); delete _this5.collection[toastId]; } }); return Object.keys(toastToRender).map(function (position) { var disablePointer = toastToRender[position].length === 1 && toastToRender[position][0] === null; var props = { className: cx('Toastify__toast-container', "Toastify__toast-container--" + position, { 'Toastify__toast-container--rtl': _this5.props.rtl }, _this5.parseClassName(className)), style: disablePointer ? _extends({}, style, { pointerEvents: 'none' }) : _extends({}, style) }; return React__default.createElement(TransitionGroup, _extends({}, props, { key: "container-" + position }), toastToRender[position]); }); }; _proto.render = function render() { return React__default.createElement("div", { className: "Toastify" }, this.renderToast()); }; return ToastContainer; }(React.Component); ToastContainer.propTypes = { /** * Set toast position */ position: PropTypes.oneOf(objectValues(POSITION)), /** * Disable or set autoClose delay */ autoClose: falseOrDelay, /** * Disable or set a custom react element for the close button */ closeButton: PropTypes.oneOfType([PropTypes.node, PropTypes.bool]), /** * Hide or not progress bar when autoClose is enabled */ hideProgressBar: PropTypes.bool, /** * Pause toast duration on hover */ pauseOnHover: PropTypes.bool, /** * Dismiss toast on click */ closeOnClick: PropTypes.bool, /** * Newest on top */ newestOnTop: PropTypes.bool, /** * An optional className */ className: PropTypes.oneOfType([PropTypes.string, PropTypes.object]), /** * An optional style */ style: PropTypes.object, /** * An optional className for the toast */ toastClassName: PropTypes.oneOfType([PropTypes.string, PropTypes.object]), /** * An optional className for the toast body */ bodyClassName: PropTypes.oneOfType([PropTypes.string, PropTypes.object]), /** * An optional className for the toast progress bar */ progressClassName: PropTypes.oneOfType([PropTypes.string, PropTypes.object]), /** * An optional style for the toast progress bar */ progressStyle: PropTypes.object, /** * Define enter and exit transition using react-transition-group */ transition: PropTypes.func, /** * Support rtl display */ rtl: PropTypes.bool, /** * Allow toast to be draggable */ draggable: PropTypes.bool, /** * The percentage of the toast's width it takes for a drag to dismiss a toast */ draggablePercent: PropTypes.number, /** * Pause the toast on focus loss */ pauseOnFocusLoss: PropTypes.bool, /** * Show the toast only if it includes containerId and it's the same as containerId */ enableMultiContainer: PropTypes.bool, /** * Set id to handle multiple container */ containerId: PropTypes.oneOfType([PropTypes.string, PropTypes.number]) }; ToastContainer.defaultProps = { position: POSITION.TOP_RIGHT, transition: Bounce, rtl: false, autoClose: 5000, hideProgressBar: false, closeButton: React__default.createElement(CloseButton, null), pauseOnHover: true, pauseOnFocusLoss: true, closeOnClick: true, newestOnTop: false, draggable: true, draggablePercent: 80, className: null, style: null, toastClassName: null, bodyClassName: null, progressClassName: null, progressStyle: null }; var container = null; var containerDomNode = null; var containerConfig = {}; var queue = []; var lazy = false; /** * Merge provided options with the defaults settings and generate the toastId */ function mergeOptions(options, type) { return _extends({}, options, { type: type, toastId: getToastId(options) }); } /** * Generate a random toastId */ function generateToastId() { return (Math.random().toString(36) + Date.now().toString(36)).substr(2, 10); } /** * Generate a toastId or use the one provided */ function getToastId(options) { if (options && (typeof options.toastId === 'string' || typeof options.toastId === 'number' && !isNaN(options.toastId))) { return options.toastId; } return generateToastId(); } /** * If the container is not mounted, the toast is enqueued and * the container lazy mounted */ function dispatchToast(content, options) { if (container) { eventManager.emit(ACTION.SHOW, content, options); } else { queue.push({ action: ACTION.SHOW, content: content, options: options }); if (lazy && canUseDom) { containerDomNode = document.createElement('div'); document.body.appendChild(containerDomNode); reactDom.render(React__default.createElement(ToastContainer, containerConfig), containerDomNode); } } return options.toastId; } var toast = function toast(content, options) { return dispatchToast(content, mergeOptions(options, options && options.type || TYPE.DEFAULT)); }; /** * For each available position create a shortcut */ var _loop = function _loop(pos) { if (TYPE[pos] !== TYPE.DEFAULT) { toast[TYPE[pos].toLowerCase()] = function (content, options) { return dispatchToast(content, mergeOptions(options, options && options.type || TYPE[pos])); }; } }; for (var pos in TYPE) { _loop(pos); } /** * Maybe I should remove warning in favor of warn, I don't know */ toast.warn = toast.warning; /** * Remove toast programmaticaly */ toast.dismiss = function (id) { if (id === void 0) { id = null; } return container && eventManager.emit(ACTION.CLEAR, id); }; /** * Do nothing until the container is mounted. Reassigned later */ toast.isActive = NOOP; toast.update = function (toastId, options) { // if you call toast and toast.update directly nothing will be displayed // this is way I defered the update setTimeout(function () { if (container && typeof container.collection[toastId] !== 'undefined') { var _container$collection = container.collection[toastId], oldOptions = _container$collection.options, oldContent = _container$collection.content; var nextOptions = _extends({}, oldOptions, options, { toastId: options.toastId || toastId }); if (!options.toastId || options.toastId === toastId) { nextOptions.updateId = generateToastId(); } else { nextOptions.staleToastId = toastId; } var content = typeof nextOptions.render !== 'undefined' ? nextOptions.render : oldContent; delete nextOptions.render; dispatchToast(content, nextOptions); } }, 0); }; /** * Used for controlled progress bar. */ toast.done = function (id, progress) { if (progress === void 0) { progress = 1; } toast.update(id, { progress: progress, isProgressDone: true }); }; /** * Track changes. The callback get the number of toast displayed */ toast.onChange = function (callback) { if (typeof callback === 'function') { eventManager.on(ACTION.ON_CHANGE, callback); } }; /** * Configure the ToastContainer when lazy mounted */ toast.configure = function (config) { lazy = true; containerConfig = config; }; toast.POSITION = POSITION; toast.TYPE = TYPE; /** * Wait until the ToastContainer is mounted to dispatch the toast * and attach isActive method */ eventManager.on(ACTION.DID_MOUNT, function (containerInstance) { container = containerInstance; toast.isActive = function (id) { return container.isToastActive(id); }; queue.forEach(function (item) { eventManager.emit(item.action, item.content, item.options); }); queue = []; }).on(ACTION.WILL_UNMOUNT, function () { container = null; toast.isActive = NOOP; if (canUseDom && containerDomNode) { document.body.removeChild(containerDomNode); } }); exports.Bounce = Bounce; exports.Flip = Flip; exports.Slide = Slide; exports.ToastContainer = ToastContainer; exports.ToastPosition = POSITION; exports.ToastType = TYPE; exports.Zoom = Zoom; exports.cssTransition = cssTransition; exports.toast = toast;