2020-03-31 13:47:59 +08:00

262 lines
6.7 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
import cx from 'classnames';
import ConfigProvider from '../config-provider';
import Message from '../message';
import zhCN from '../locale/zh-cn';
import dialog from './dialog';
const Dialog = ConfigProvider.config(dialog);
const noop = () => {};
const MESSAGE_TYPE = {
alert: 'warning',
confirm: 'help',
};
export const ModalInner = function({
type,
messageProps = {},
title,
rtl,
prefix = 'next-',
content,
}) {
return (
<Message
size="large"
shape="addon"
type={MESSAGE_TYPE[type]}
{...messageProps}
title={title}
rtl={rtl}
className={cx(`${prefix}dialog-message`, messageProps.className)}
>
{content}
</Message>
);
};
class Modal extends Component {
static propTypes = {
prefix: PropTypes.string,
pure: PropTypes.bool,
rtl: PropTypes.bool,
type: PropTypes.oneOf(['alert', 'confirm']),
title: PropTypes.node,
content: PropTypes.node,
messageProps: PropTypes.object,
footerActions: PropTypes.array,
/**
* Callback function triggered when Ok button is clicked
* @param {Object} event click event object
* @returns {Promise} Optionally handles a Promise return object
*/
onOk: PropTypes.func,
/**
* Callback function triggered when Cancel button is clicked
* @param {Object} event click event object
* @returns {Promise} Optionally handles a Promise return object
*/
onCancel: PropTypes.func,
/**
* Callback function triggered when Close button is clicked
* @param {Object} event click event object
* @returns {Promise} Optionally handles a Promise return object
*/
onClose: PropTypes.func,
okProps: PropTypes.object,
locale: PropTypes.object,
needWrapper: PropTypes.bool,
className: PropTypes.string,
};
static defaultProps = {
prefix: 'next-',
pure: false,
messageProps: {},
onOk: noop,
onCancel: noop,
onClose: noop,
okProps: {},
locale: zhCN.Dialog,
needWrapper: true,
};
state = {
visible: true,
loading: false,
};
close = () => {
this.setState({
visible: false,
});
};
loading = loading => {
this.setState({
loading,
});
};
wrapper(fn, callback) {
return (...args) => {
const res = fn(...args);
if (res && res.then) {
this.loading(true);
res.then(result => {
this.loading(false);
if (result !== false) {
return callback();
}
}).catch(e => {
this.loading(false);
throw e;
});
} else if (res !== false) {
return callback();
}
};
}
render() {
const {
prefix,
type,
title,
content,
messageProps,
footerActions,
onOk,
onCancel,
onClose,
okProps,
needWrapper,
rtl,
className,
...others
} = this.props;
const newTitle = needWrapper && type ? null : title;
const newContent =
needWrapper && type ? (
<ModalInner
type={type}
messageProps={messageProps}
title={title}
rtl={rtl}
prefix={prefix}
content={content}
/>
) : (
content
);
const newFooterActions =
footerActions ||
(type === 'alert'
? ['ok']
: type === 'confirm'
? ['ok', 'cancel']
: undefined);
const newOnOk = this.wrapper(onOk, this.close);
const newOnCancel = this.wrapper(onCancel, this.close);
const newOnClose = this.wrapper(onClose, this.close);
const { visible, loading } = this.state;
okProps.loading = loading;
const classNames = cx(`${prefix}dialog-quick`, className);
return (
<Dialog
prefix={prefix}
role="alertdialog"
{...others}
visible={visible}
title={newTitle}
rtl={rtl}
footerActions={newFooterActions}
onOk={this.state.loading ? noop : newOnOk}
onCancel={newOnCancel}
onClose={newOnClose}
okProps={okProps}
className={classNames}
>
{newContent}
</Dialog>
);
}
}
const ConfigModal = ConfigProvider.config(Modal, { componentName: 'Dialog' });
/**
* 创建对话框
* @exportName show
* @param {Object} config 配置项
* @returns {Object} 包含有 hide 方法,可用来关闭对话框
*/
export const show = (config = {}) => {
const container = document.createElement('div');
const unmount = () => {
if (config.afterClose) {
config.afterClose();
}
ReactDOM.unmountComponentAtNode(container);
container.parentNode.removeChild(container);
};
document.body.appendChild(container);
const newContext = ConfigProvider.getContext();
let instance, myRef;
ReactDOM.render(
<ConfigProvider {...newContext}>
<ConfigModal
{...config}
afterClose={unmount}
ref={ref => {
myRef = ref;
}}
/>
</ConfigProvider>,
container,
function() {
instance = myRef;
}
);
return {
hide: () => {
const inc = instance && instance.getInstance();
inc && inc.close();
},
};
};
const methodFactory = type => (config = {}) => {
config.type = type;
return show(config);
};
/**
* 创建警示对话框
* @exportName alert
* @param {Object} config 配置项
* @returns {Object} 包含有 hide 方法,可用来关闭对话框
*/
export const alert = methodFactory('alert');
/**
* 创建确认对话框
* @exportName confirm
* @param {Object} config 配置项
* @returns {Object} 包含有 hide 方法,可用来关闭对话框
*/
export const confirm = methodFactory('confirm');