@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.
377 lines (376 loc) • 15.1 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.destroyFns = exports.default = void 0;
var _noop2 = _interopRequireDefault(require("lodash/noop"));
var _constants = require("@douyinfe/semi-foundation/lib/cjs/modal/constants");
require("@douyinfe/semi-foundation/lib/cjs/modal/modal.css");
var _modalFoundation = _interopRequireDefault(require("@douyinfe/semi-foundation/lib/cjs/modal/modalFoundation"));
var _classnames = _interopRequireDefault(require("classnames"));
var _propTypes = _interopRequireDefault(require("prop-types"));
var _react = _interopRequireDefault(require("react"));
var _baseComponent = _interopRequireDefault(require("../_base/baseComponent"));
var _cssAnimation = _interopRequireDefault(require("../_cssAnimation"));
var _portal = _interopRequireDefault(require("../_portal"));
var _utils = require("../_utils");
var _button = _interopRequireDefault(require("../button"));
var _localeConsumer = _interopRequireDefault(require("../locale/localeConsumer"));
var _ModalContent = _interopRequireDefault(require("./ModalContent"));
var _confirm = _interopRequireWildcard(require("./confirm"));
var _useModal = _interopRequireDefault(require("./useModal"));
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
var __rest = void 0 && (void 0).__rest || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]];
}
return t;
};
let destroyFns = exports.destroyFns = [];
class Modal extends _baseComponent.default {
constructor(props) {
super(props);
this.bodyOverflow = null;
this.handleCancel = e => {
this.foundation.handleCancel(e);
};
this.handleOk = e => {
this.foundation.handleOk(e);
};
this.updateState = () => {
const {
visible
} = this.props;
this.foundation.toggleDisplayNone(!visible);
};
this.renderFooter = () => {
const {
okText,
okType,
cancelText,
confirmLoading,
cancelLoading,
hasCancel,
footerFill
} = this.props;
const getCancelButton = locale => {
var _a;
if (!hasCancel) {
return null;
} else {
return /*#__PURE__*/_react.default.createElement(_button.default, Object.assign({
"aria-label": "cancel",
onClick: this.handleCancel,
loading: cancelLoading === undefined ? this.state.onCancelReturnPromiseStatus === "pending" : cancelLoading,
type: "tertiary",
block: footerFill,
autoFocus: true
}, this.props.cancelButtonProps, {
style: Object.assign(Object.assign({}, footerFill ? {
marginLeft: "unset"
} : {}), (_a = this.props.cancelButtonProps) === null || _a === void 0 ? void 0 : _a.style),
"x-semi-children-alias": "cancelText"
}), cancelText || locale.cancel);
}
};
return /*#__PURE__*/_react.default.createElement(_localeConsumer.default, {
componentName: "Modal"
}, (locale, localeCode) => ( /*#__PURE__*/_react.default.createElement("div", {
className: (0, _classnames.default)({
[`${_constants.cssClasses.DIALOG}-footerfill`]: footerFill
})
}, getCancelButton(locale), /*#__PURE__*/_react.default.createElement(_button.default, Object.assign({
"aria-label": "confirm",
type: okType,
theme: "solid",
block: footerFill,
loading: confirmLoading === undefined ? this.state.onOKReturnPromiseStatus === "pending" : confirmLoading,
onClick: this.handleOk
}, this.props.okButtonProps, {
"x-semi-children-alias": "okText"
}), okText || locale.confirm))));
};
// getDialog = () => {
// const {
// footer,
// ...restProps
// } = this.props;
// const renderFooter = 'footer' in this.props ? footer : this.renderFooter();
// return <ModalContent {...restProps} footer={renderFooter} onClose={this.handleCancel}/>;
// };
this.renderDialog = () => {
var _a;
let _b = this.props,
{
footer,
className,
motion,
maskStyle: maskStyleFromProps,
keepDOM,
style: styleFromProps,
zIndex,
getPopupContainer,
visible,
modalContentClass
} = _b,
restProps = __rest(_b, ["footer", "className", "motion", "maskStyle", "keepDOM", "style", "zIndex", "getPopupContainer", "visible", "modalContentClass"]);
let style = styleFromProps;
const maskStyle = maskStyleFromProps;
const renderFooter = 'footer' in this.props ? footer : this.renderFooter();
let wrapperStyle = {
zIndex
};
if (getPopupContainer && getPopupContainer() !== ((_a = globalThis === null || globalThis === void 0 ? void 0 : globalThis.document) === null || _a === void 0 ? void 0 : _a.body)) {
wrapperStyle = {
zIndex,
position: 'static'
};
}
const classList = (0, _classnames.default)(className, {
[`${_constants.cssClasses.DIALOG}-displayNone`]: keepDOM && this.state.displayNone
});
const shouldRender = this.props.visible || this.props.keepDOM && (!this.props.lazyRender || this._haveRendered) || this.props.motion && !this.state.displayNone /* When there is animation, we use displayNone to judge whether animation is ended and judge whether to unmount content */;
if (shouldRender) {
this._haveRendered = true;
}
return /*#__PURE__*/_react.default.createElement(_cssAnimation.default, {
motion: this.props.motion,
animationState: visible ? 'enter' : 'leave',
startClassName: visible ? `${_constants.cssClasses.DIALOG}-content-animate-show` : `${_constants.cssClasses.DIALOG}-content-animate-hide`,
onAnimationEnd: () => {
this.updateState();
}
}, _ref => {
let {
animationClassName,
animationEventsNeedBind
} = _ref;
return /*#__PURE__*/_react.default.createElement(_cssAnimation.default, {
motion: this.props.motion,
animationState: visible ? 'enter' : 'leave',
startClassName: visible ? `${_constants.cssClasses.DIALOG}-mask-animate-show` : `${_constants.cssClasses.DIALOG}-mask-animate-hide`,
onAnimationEnd: () => {
this.updateState();
}
}, _ref2 => {
let {
animationClassName: maskAnimationClassName,
animationEventsNeedBind: maskAnimationEventsNeedBind
} = _ref2;
return shouldRender ? /*#__PURE__*/_react.default.createElement(_portal.default, {
style: wrapperStyle,
getPopupContainer: getPopupContainer
}, " ", /*#__PURE__*/_react.default.createElement(_ModalContent.default, Object.assign({}, restProps, {
contentExtraProps: animationEventsNeedBind,
maskExtraProps: maskAnimationEventsNeedBind,
isFullScreen: this.state.isFullScreen,
contentClassName: `${animationClassName} ${modalContentClass}`,
maskClassName: maskAnimationClassName,
className: classList,
getPopupContainer: getPopupContainer,
maskStyle: maskStyle,
style: style,
ref: this.modalRef,
footer: renderFooter,
onClose: this.handleCancel
}))) : /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null);
});
});
};
this.state = {
displayNone: !props.visible,
isFullScreen: props.fullScreen
};
this.foundation = new _modalFoundation.default(this.adapter);
this.modalRef = /*#__PURE__*/_react.default.createRef();
this.scrollBarWidth = 0;
this.originBodyWidth = '100%';
}
get adapter() {
return Object.assign(Object.assign({}, super.adapter), {
getProps: () => this.props,
disabledBodyScroll: () => {
var _a;
const {
getPopupContainer
} = this.props;
this.bodyOverflow = document.body.style.overflow || '';
if ((!getPopupContainer || getPopupContainer() === ((_a = globalThis === null || globalThis === void 0 ? void 0 : globalThis.document) === null || _a === void 0 ? void 0 : _a.body)) && this.bodyOverflow !== 'hidden') {
document.body.style.overflow = 'hidden';
document.body.style.width = `calc(${this.originBodyWidth || '100%'} - ${this.scrollBarWidth}px)`;
}
},
enabledBodyScroll: () => {
var _a;
const {
getPopupContainer
} = this.props;
if ((!getPopupContainer || getPopupContainer() === ((_a = globalThis === null || globalThis === void 0 ? void 0 : globalThis.document) === null || _a === void 0 ? void 0 : _a.body)) && this.bodyOverflow !== null && this.bodyOverflow !== 'hidden') {
document.body.style.overflow = this.bodyOverflow;
document.body.style.width = this.originBodyWidth;
}
},
notifyCancel: e => {
return this.props.onCancel(e);
},
notifyOk: e => {
return this.props.onOk(e);
},
notifyClose: () => {
this.props.afterClose();
},
toggleDisplayNone: (displayNone, callback) => {
if (displayNone !== this.state.displayNone) {
this.setState({
displayNone: displayNone
}, callback || _noop2.default);
}
},
notifyFullScreen: isFullScreen => {
if (isFullScreen !== this.state.isFullScreen) {
this.setState({
isFullScreen
});
}
}
});
}
static getDerivedStateFromProps(props, prevState) {
const newState = {};
if (props.fullScreen !== prevState.isFullScreen) {
newState.isFullScreen = props.fullScreen;
}
if (props.visible && prevState.displayNone) {
newState.displayNone = false;
}
//
// if (!props.visible && !props.motion && !prevState.displayNone) {
// newState.displayNone = true;
// }
return newState;
}
componentDidMount() {
this.scrollBarWidth = (0, _utils.getScrollbarWidth)();
this.originBodyWidth = document.body.style.width;
if (this.props.visible) {
this.foundation.beforeShow();
}
}
componentDidUpdate(prevProps, prevState, snapshot) {
// hide => show
if (!prevProps.visible && this.props.visible) {
this.foundation.beforeShow();
}
if (!prevState.displayNone && this.state.displayNone) {
this.foundation.afterHide();
}
}
componentWillUnmount() {
if (this.props.visible) {
this.foundation.destroy();
} else {
this.foundation.enabledBodyScroll();
}
}
render() {
const {
visible,
keepDOM,
lazyRender
} = this.props;
return this.renderDialog();
}
}
Modal.propTypes = {
mask: _propTypes.default.bool,
closable: _propTypes.default.bool,
centered: _propTypes.default.bool,
visible: _propTypes.default.bool,
width: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.number]),
height: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.number]),
confirmLoading: _propTypes.default.bool,
cancelLoading: _propTypes.default.bool,
okText: _propTypes.default.string,
okType: _propTypes.default.string,
cancelText: _propTypes.default.string,
maskClosable: _propTypes.default.bool,
onCancel: _propTypes.default.func,
onOk: _propTypes.default.func,
afterClose: _propTypes.default.func,
okButtonProps: _propTypes.default.object,
cancelButtonProps: _propTypes.default.object,
style: _propTypes.default.object,
className: _propTypes.default.string,
maskStyle: _propTypes.default.object,
bodyStyle: _propTypes.default.object,
zIndex: _propTypes.default.number,
title: _propTypes.default.node,
icon: _propTypes.default.node,
header: _propTypes.default.node,
footer: _propTypes.default.node,
hasCancel: _propTypes.default.bool,
motion: _propTypes.default.bool,
children: _propTypes.default.node,
getPopupContainer: _propTypes.default.func,
getContainerContext: _propTypes.default.func,
maskFixed: _propTypes.default.bool,
closeIcon: _propTypes.default.node,
closeOnEsc: _propTypes.default.bool,
size: _propTypes.default.oneOf(_constants.strings.SIZE),
keepDOM: _propTypes.default.bool,
lazyRender: _propTypes.default.bool,
direction: _propTypes.default.oneOf(_constants.strings.directions),
fullScreen: _propTypes.default.bool,
footerFill: _propTypes.default.bool
};
Modal.__SemiComponentName__ = "Modal";
Modal.defaultProps = (0, _utils.getDefaultPropsFromGlobalConfig)(Modal.__SemiComponentName__, {
zIndex: 1000,
motion: true,
mask: true,
centered: false,
closable: true,
visible: false,
okType: 'primary',
maskClosable: true,
hasCancel: true,
onCancel: _noop2.default,
onOk: _noop2.default,
afterClose: _noop2.default,
maskFixed: false,
closeOnEsc: true,
size: 'small',
keepDOM: false,
lazyRender: true,
fullScreen: false
});
Modal.useModal = _useModal.default;
Modal.info = function (props) {
return (0, _confirm.default)((0, _confirm.withInfo)(props));
};
Modal.success = function (props) {
return (0, _confirm.default)((0, _confirm.withSuccess)(props));
};
Modal.error = function (props) {
return (0, _confirm.default)((0, _confirm.withError)(props));
};
Modal.warning = function (props) {
return (0, _confirm.default)((0, _confirm.withWarning)(props));
};
Modal.confirm = function (props) {
return (0, _confirm.default)((0, _confirm.withConfirm)(props));
};
Modal.destroyAll = function destroyAllFn() {
for (let i = 0, len = destroyFns.length; i < len; i++) {
const close = destroyFns[i];
if (close) {
close();
}
}
exports.destroyFns = destroyFns = [];
};
var _default = exports.default = Modal;