UNPKG

@douyinfe/semi-ui

Version:

A modern, comprehensive, flexible design system and UI library. Connect DesignOps & DevOps. Quickly build beautiful React apps. Maintained by Douyin-fe team.

266 lines (265 loc) 9.31 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _react = _interopRequireDefault(require("react")); var _reactDom = _interopRequireDefault(require("react-dom")); var _classnames = _interopRequireDefault(require("classnames")); var _propTypes = _interopRequireDefault(require("prop-types")); var _context = _interopRequireDefault(require("../configProvider/context")); var _notificationListFoundation = _interopRequireDefault(require("@douyinfe/semi-foundation/lib/cjs/notification/notificationListFoundation")); var _constants = require("@douyinfe/semi-foundation/lib/cjs/notification/constants"); var _notice = _interopRequireDefault(require("./notice")); var _baseComponent = _interopRequireDefault(require("../_base/baseComponent")); require("@douyinfe/semi-foundation/lib/cjs/notification/notification.css"); var _uuid = _interopRequireDefault(require("@douyinfe/semi-foundation/lib/cjs/utils/uuid")); var _useNotification = _interopRequireDefault(require("./useNotification")); var _cssAnimation = _interopRequireDefault(require("../_cssAnimation")); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } let ref = null; const defaultConfig = { duration: 3, position: 'topRight', motion: true, content: '', title: '', zIndex: 1010 }; class NotificationList extends _baseComponent.default { constructor(props) { var _this; super(props); _this = this; this.add = noticeOpts => this.foundation.addNotice(noticeOpts); this.has = id => this.foundation.has(id); this.remove = id => { this.foundation.removeNotice(String(id)); }; this.update = (id, opts) => { return this.foundation.update(id, opts); }; this.destroyAll = () => this.foundation.destroyAll(); this.renderNoticeInPosition = function (notices, position) { let removedItems = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : []; let updatedItems = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : []; const className = (0, _classnames.default)(_constants.cssClasses.LIST); // TODO notifyOnClose if (notices.length) { const style = _this.setPosInStyle(notices[0]); return ( /*#__PURE__*/ // @ts-ignore _react.default.createElement("div", { placement: position, key: position, className: className, style: style }, notices.map((notice, index) => { const isRemoved = removedItems.find(removedItem => removedItem.id === notice.id) !== undefined; return /*#__PURE__*/_react.default.createElement(_cssAnimation.default, { key: notice.id, animationState: isRemoved ? "leave" : "enter", startClassName: `${_constants.cssClasses.NOTICE}-animation-${isRemoved ? "hide" : "show"}_${position}` }, _ref => { let { animationClassName, animationEventsNeedBind, isAnimating } = _ref; return isRemoved && !isAnimating ? null : /*#__PURE__*/_react.default.createElement(_notice.default, Object.assign({}, notice, { ref: notice => { if (notice && updatedItems.some(item => item.id === notice.props.id)) { notice.foundation.restartCloseTimer(); } }, className: (0, _classnames.default)({ [notice.className]: Boolean(notice.className), [animationClassName]: true }) }, animationEventsNeedBind, { style: Object.assign({}, notice.style), close: _this.remove })); }); })) ); } return null; }; this.state = { notices: [], removedItems: [], updatedItems: [] }; this.noticeStorage = []; this.removeItemStorage = []; this.foundation = new _notificationListFoundation.default(this.adapter); } get adapter() { var _this2 = this; return Object.assign(Object.assign({}, super.adapter), { updateNotices: function (notices) { let removedItems = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; let updatedItems = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : []; _this2.noticeStorage = [...notices]; _this2.removeItemStorage = [...removedItems]; // setState is async sometimes and react often merges state, so use "this" , make sure other code always get right data. _this2.setState({ notices, removedItems, updatedItems }); }, getNotices: () => this.noticeStorage }); } static addNotice(notice) { var _a; notice = Object.assign(Object.assign({}, defaultConfig), notice); const id = (_a = notice.id) !== null && _a !== void 0 ? _a : (0, _uuid.default)('notification'); if (!ref) { const { getPopupContainer } = notice; const div = document.createElement('div'); if (!this.wrapperId) { this.wrapperId = (0, _uuid.default)('notification-wrapper').slice(0, 32); } div.className = _constants.cssClasses.WRAPPER; div.id = this.wrapperId; div.style.zIndex = String(typeof notice.zIndex === 'number' ? notice.zIndex : defaultConfig.zIndex); if (getPopupContainer) { const container = getPopupContainer(); container.appendChild(div); } else { document.body.appendChild(div); } _reactDom.default.render(/*#__PURE__*/_react.default.createElement(NotificationList, { ref: instance => ref = instance }), div, () => { ref.add(Object.assign(Object.assign({}, notice), { id })); }); } else { if (ref.has(`${id}`)) { ref.update(id, notice); } else { ref.add(Object.assign(Object.assign({}, notice), { id })); } } return id; } static removeNotice(id) { if (ref) { ref.remove(id); } return id; } static info(opts) { return this.addNotice(Object.assign(Object.assign({}, opts), { type: 'info' })); } static success(opts) { return this.addNotice(Object.assign(Object.assign({}, opts), { type: 'success' })); } static error(opts) { return this.addNotice(Object.assign(Object.assign({}, opts), { type: 'error' })); } static warning(opts) { return this.addNotice(Object.assign(Object.assign({}, opts), { type: 'warning' })); } static open(opts) { return this.addNotice(Object.assign(Object.assign({}, opts), { type: 'default' })); } static close(id) { return this.removeNotice(id); } static destroyAll() { if (ref) { ref.destroyAll(); const wrapper = document.querySelector(`#${this.wrapperId}`); _reactDom.default.unmountComponentAtNode(wrapper); wrapper && wrapper.parentNode.removeChild(wrapper); ref = null; this.wrapperId = null; } } static config(opts) { ['top', 'left', 'bottom', 'right'].map(pos => { if (pos in opts) { defaultConfig[pos] = opts[pos]; } }); if (typeof opts.zIndex === 'number') { defaultConfig.zIndex = opts.zIndex; } if (typeof opts.duration === 'number') { defaultConfig.duration = opts.duration; } if (typeof opts.position === 'string') { defaultConfig.position = opts.position; } } setPosInStyle(noticeInstance) { const style = {}; ['top', 'left', 'bottom', 'right'].forEach(pos => { if (pos in noticeInstance) { const val = noticeInstance[pos]; style[pos] = typeof val === 'number' ? `${val}px` : val; } }); return style; } render() { let { notices } = this.state; const { removedItems, updatedItems } = this.state; notices = Array.from(new Set([...notices, ...removedItems])); const noticesInPosition = { top: [], topLeft: [], topRight: [], bottom: [], bottomLeft: [], bottomRight: [] }; notices.forEach(notice => { const direction = notice.direction || this.context.direction; const defaultPosition = direction === 'rtl' ? 'topLeft' : 'topRight'; const position = notice.position || defaultPosition; noticesInPosition[position].push(notice); }); const noticesList = Object.entries(noticesInPosition).map(obj => { const pos = obj[0]; const noticesInPos = obj[1]; return this.renderNoticeInPosition(noticesInPos, pos, removedItems, updatedItems); }); return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, noticesList); } } NotificationList.contextType = _context.default; NotificationList.propTypes = { style: _propTypes.default.object, className: _propTypes.default.string, direction: _propTypes.default.oneOf(_constants.strings.directions) }; NotificationList.defaultProps = {}; NotificationList.useNotification = _useNotification.default; var _default = exports.default = NotificationList;