UNPKG

light-toast

Version:

A light-weight react toast component built for mobile web app

267 lines (245 loc) 13 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var React = require('react'); var ReactDOM = require('react-dom'); function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } var React__default = /*#__PURE__*/_interopDefaultLegacy(React); var ReactDOM__default = /*#__PURE__*/_interopDefaultLegacy(ReactDOM); function styleInject(css, ref) { if ( ref === void 0 ) ref = {}; var insertAt = ref.insertAt; if (!css || typeof document === 'undefined') { return; } var head = document.head || document.getElementsByTagName('head')[0]; var style = document.createElement('style'); style.type = 'text/css'; if (insertAt === 'top') { if (head.firstChild) { head.insertBefore(style, head.firstChild); } else { head.appendChild(style); } } else { head.appendChild(style); } if (style.styleSheet) { style.styleSheet.cssText = css; } else { style.appendChild(document.createTextNode(css)); } } var css_248z = ".style_mask__9zmSN{position:fixed;top:0;right:0;bottom:0;left:0;display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;background:transparent;z-index:1999}.style_box__2iia4{display:inline-block;max-width:85%;min-width:95px;padding:9px 15px;box-sizing:border-box;text-align:center;word-break:break-all;white-space:pre-wrap;font-size:0;color:#fff;background-color:rgba(58,58,58,.9);border-radius:3px;opacity:0;-webkit-transform:scale(.9);transform:scale(.9);-webkit-backface-visibility:hidden;backface-visibility:hidden;transition:opacity .3s,-webkit-transform .3s;transition:opacity .3s,transform .3s;transition:opacity .3s,transform .3s,-webkit-transform .3s}.style_enter__29LyQ{opacity:1;-webkit-transform:scale(1);transform:scale(1)}.style_exit__3WYmp{opacity:0;-webkit-transform:scale(.9);transform:scale(.9)}.style_message__1DUXc{line-height:1.5;font-size:14px}.style_wrapper__cQFyX{margin:0 auto 7px;width:36px;height:36px}.style_loading__2pb7J{-webkit-animation:style_loading__2pb7J 1s linear infinite;animation:style_loading__2pb7J 1s linear infinite}@-webkit-keyframes style_loading__2pb7J{to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes style_loading__2pb7J{to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}"; var styles = {"mask":"style_mask__9zmSN","box":"style_box__2iia4","enter":"style_enter__29LyQ","exit":"style_exit__3WYmp","message":"style_message__1DUXc","wrapper":"style_wrapper__cQFyX","loading":"style_loading__2pb7J"}; styleInject(css_248z); var Icon = function (_a) { var type = _a.type; switch (type) { case 'success': return (React__default['default'].createElement("svg", { viewBox: "0 0 1024 1024", fill: "#fff" }, React__default['default'].createElement("path", { d: "M699 353h-46.9c-10.2 0-19.9 4.9-25.9 13.3L469 584.3l-71.2-98.8c-6-8.3-15.6-13.3-25.9-13.3H325c-6.5 0-10.3 7.4-6.5 12.7l124.6 172.8a31.8 31.8 0 0 0 51.7 0l210.6-292c3.9-5.3.1-12.7-6.4-12.7z" }), React__default['default'].createElement("path", { d: "M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z" }))); case 'fail': return (React__default['default'].createElement("svg", { viewBox: "0 0 1024 1024", fill: "#fff" }, React__default['default'].createElement("path", { d: "M685.4 354.8c0-4.4-3.6-8-8-8l-66 .3L512 465.6l-99.3-118.4-66.1-.3c-4.4 0-8 3.5-8 8 0 1.9.7 3.7 1.9 5.2l130.1 155L340.5 670a8.32 8.32 0 0 0-1.9 5.2c0 4.4 3.6 8 8 8l66.1-.3L512 564.4l99.3 118.4 66 .3c4.4 0 8-3.5 8-8 0-1.9-.7-3.7-1.9-5.2L553.5 515l130.1-155c1.2-1.4 1.8-3.3 1.8-5.2z" }), React__default['default'].createElement("path", { d: "M512 65C264.6 65 64 265.6 64 513s200.6 448 448 448 448-200.6 448-448S759.4 65 512 65zm0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z" }))); case 'loading': return (React__default['default'].createElement("svg", { viewBox: "0 0 1024 1024", fill: "#fff", className: styles.loading }, React__default['default'].createElement("path", { d: "M988 548c-19.9 0-36-16.1-36-36 0-59.4-11.6-117-34.6-171.3a440.45 440.45 0 0 0-94.3-139.9 437.71 437.71 0 0 0-139.9-94.3C629 83.6 571.4 72 512 72c-19.9 0-36-16.1-36-36s16.1-36 36-36c69.1 0 136.2 13.5 199.3 40.3C772.3 66 827 103 874 150c47 47 83.9 101.8 109.7 162.7 26.7 63.1 40.2 130.2 40.2 199.3.1 19.9-16 36-35.9 36z" }))); } }; var EventManager = /** @class */ (function () { function EventManager() { this._events = {}; this._publishedEvents = []; this._uniqueId = 0; // use self increasing number to guarantee global uniqueness } EventManager.prototype.subscribe = function (name, callback) { if (!this._events[name]) { this._events[name] = []; } var event = { key: this._uniqueId++, callback: callback }; this._events[name].push(event); return event.key; }; EventManager.prototype.publish = function (name, data) { this._publishedEvents.push({ name: name, data: data }); if (this._events[name]) { this._events[name].forEach(function (_a) { var callback = _a.callback; callback(data); }); } }; EventManager.prototype.unSubscribe = function (name, key) { if (this._events[name]) { for (var i = 0; i < this._events[name].length; i++) { if (key === this._events[name][i].key) { this._events[name].splice(i, 1); break; } } } }; // Make sure published events can be triggered when subscribed EventManager.prototype.ensureTriggeredAndSubscribe = function (name, callback) { var event = this._publishedEvents .slice() .reverse() .find(function (item) { return item.name === name; }); if (event) { callback(event.data); } return this.subscribe(name, callback); }; return EventManager; }()); var eventManager = new EventManager(); var Toast = function (_a) { var id = _a.id, type = _a.type, content = _a.content, _b = _a.duration, duration = _b === void 0 ? 3000 : _b, onClose = _a.onClose; var _c = React.useState(styles.box), classes = _c[0], setClasses = _c[1]; var _d = React.useState(false), entered = _d[0], setEntered = _d[1]; var ref = React.useRef(null); function exit() { setClasses(function () { return styles.box + " " + styles.exit; }); } React.useEffect(function () { // force a repaint // eslint-disable-next-line ref.current && ref.current.scrollTop; setClasses(function (prev) { return prev + " " + styles.enter; }); }, []); React.useEffect(function () { var key = -1; var timerId = -1; if (entered) { // component mounting is async, there might be an exit command before a toast mounts // so we should make sure to trigger the published exit event key = eventManager.ensureTriggeredAndSubscribe('lt#exit', function (messageId) { if (messageId === id) { exit(); } }); if (duration !== 0) { timerId = window.setTimeout(exit, duration); } } return function () { eventManager.unSubscribe('lt#exit', key); window.clearTimeout(timerId); }; }, [id, duration, entered]); return (React__default['default'].createElement("div", { className: styles.mask }, React__default['default'].createElement("div", { className: classes, style: type === 'info' ? undefined : { padding: 15, borderRadius: 5 }, onTransitionEnd: function () { // enter phase if (~classes.indexOf(styles.enter)) { setEntered(true); } // exit phase if (~classes.indexOf(styles.exit)) { onClose(); } }, ref: ref }, type !== 'info' && (React__default['default'].createElement("div", { className: styles.wrapper, style: type === 'loading' ? { marginBottom: 10 } : undefined }, React__default['default'].createElement(Icon, { type: type }))), React__default['default'].createElement("span", { className: styles.message }, content)))); }; /*! ***************************************************************************** Copyright (c) Microsoft Corporation. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ***************************************************************************** */ var __assign = function() { __assign = Object.assign || function __assign(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; /** * Message queue. * Save messages in a queue, only remove it when component lifecycle ends. */ var Queue = /** @class */ (function () { function Queue() { this._messages = []; this._uniqueId = 0; } Queue.prototype.push = function (message) { this._messages.push(__assign({ id: this._uniqueId++ }, message)); }; Object.defineProperty(Queue.prototype, "length", { get: function () { return this._messages.length; }, enumerable: false, configurable: true }); Queue.prototype.getFirstMessage = function () { return this._messages[0]; }; Queue.prototype.shift = function () { return this._messages.shift(); }; return Queue; }()); var queue = new Queue(); eventManager.subscribe('lt#popmessage', function (_a) { var id = _a.id, type = _a.type, content = _a.content, duration = _a.duration, onClose = _a.onClose; var container = document.createElement('div'); document.body.appendChild(container); ReactDOM__default['default'].render(React__default['default'].createElement(Toast, { id: id, type: type, content: content, duration: duration, onClose: function () { ReactDOM__default['default'].unmountComponentAtNode(container); document.body.removeChild(container); onClose && onClose(); queue.shift(); if (queue.length > 0) { eventManager.publish('lt#popmessage', queue.getFirstMessage()); } } }), container); }); function notice(type, content, duration, onClose) { queue.push({ type: type, content: content, duration: duration, onClose: onClose }); // toast right now if there is only one message in queue if (queue.length === 1) { eventManager.publish('lt#popmessage', queue.getFirstMessage()); return; } // if current message is loading, then we should unmount it to proceed if (queue.length > 1) { var message = queue.getFirstMessage(); if (message.type === 'loading') { eventManager.publish('lt#exit', message.id); } } } var index = { info: function (content, duration, onClose) { notice('info', content, duration, onClose); }, success: function (content, duration, onClose) { notice('success', content, duration, onClose); }, fail: function (content, duration, onClose) { notice('fail', content, duration, onClose); }, loading: function (content, onClose) { notice('loading', content, 0, onClose); }, hide: function () { // hide the first toast in the queue when executing the command if (queue.length > 0) { eventManager.publish('lt#exit', queue.getFirstMessage().id); } }, }; exports.default = index; //# sourceMappingURL=index.js.map