@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
JavaScript
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;
;