ant-design-vue/components/modal/Modal.jsx

181 lines
5.2 KiB
Vue

import classNames from 'classnames'
import Dialog from '../vc-dialog'
import PropTypes from '../_util/vue-types'
import addEventListener from '../_util/Dom/addEventListener'
import Button from '../button'
import buttonTypes from '../button/buttonTypes'
const ButtonType = buttonTypes().type
import LocaleReceiver from '../locale-provider/LocaleReceiver'
import { getConfirmLocale } from './locale'
import { initDefaultProps, getComponentFromProp, getClass, getStyle, mergeProps } from '../_util/props-util'
import Icon from '../icon'
let mousePosition = null
let mousePositionEventBinded = false
function noop () {}
const modalProps = (defaultProps = {}) => {
const props = {
prefixCls: PropTypes.string,
/** 对话框是否可见*/
visible: PropTypes.bool,
/** 确定按钮 loading*/
confirmLoading: PropTypes.bool,
/** 标题*/
title: PropTypes.any,
/** 是否显示右上角的关闭按钮*/
closable: PropTypes.bool,
/** 点击确定回调*/
// onOk: (e: React.MouseEvent<any>) => void,
/** 点击模态框右上角叉、取消按钮、Props.maskClosable 值为 true 时的遮罩层或键盘按下 Esc 时的回调*/
// onCancel: (e: React.MouseEvent<any>) => void,
afterClose: PropTypes.func.def(noop),
/** 居中 */
centered: PropTypes.bool,
/** 宽度*/
width: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
/** 底部内容*/
footer: PropTypes.any,
/** 确认按钮文字*/
okText: PropTypes.string,
/** 确认按钮类型*/
okType: ButtonType,
/** 取消按钮文字*/
cancelText: PropTypes.string,
/** 点击蒙层是否允许关闭*/
maskClosable: PropTypes.bool,
okButtonProps: PropTypes.object,
cancelButtonProps: PropTypes.object,
destroyOnClose: PropTypes.bool,
wrapClassName: PropTypes.string,
maskTransitionName: PropTypes.string,
transitionName: PropTypes.string,
getContainer: PropTypes.func,
zIndex: PropTypes.number,
bodyStyle: PropTypes.object,
maskStyle: PropTypes.object,
mask: PropTypes.bool,
keyboard: PropTypes.bool,
wrapProps: PropTypes.object,
}
return initDefaultProps(props, defaultProps)
}
export default {
name: 'AModal',
props: modalProps({
prefixCls: 'ant-modal',
width: 520,
transitionName: 'zoom',
maskTransitionName: 'fade',
confirmLoading: false,
visible: false,
okType: 'primary',
// okButtonDisabled: false,
// cancelButtonDisabled: false,
}),
model: {
prop: 'visible',
event: 'change',
},
// static info: ModalFunc;
// static success: ModalFunc;
// static error: ModalFunc;
// static warn: ModalFunc;
// static warning: ModalFunc;
// static confirm: ModalFunc;
methods: {
handleCancel (e) {
this.$emit('cancel', e)
this.$emit('change', false)
},
handleOk (e) {
this.$emit('ok', e)
},
renderFooter (locale) {
const { okType, confirmLoading } = this
const cancelBtnProps = mergeProps({ on: { click: this.handleCancel }}, this.cancelButtonProps || {})
const okBtnProps = mergeProps({
on: { click: this.handleOk },
props: {
type: okType,
loading: confirmLoading,
},
},
this.okButtonProps || {})
return (
<div>
<Button {...cancelBtnProps}>
{getComponentFromProp(this, 'cancelText') || locale.cancelText}
</Button>
<Button {...okBtnProps}>
{getComponentFromProp(this, 'okText') || locale.okText}
</Button>
</div>
)
},
},
mounted () {
if (mousePositionEventBinded) {
return
}
// 只有点击事件支持从鼠标位置动画展开
addEventListener(document.documentElement, 'click', (e) => {
mousePosition = {
x: e.pageX,
y: e.pageY,
}
// 100ms 内发生过点击事件,则从点击位置动画展示
// 否则直接 zoom 展示
// 这样可以兼容非点击方式展开
setTimeout(() => { mousePosition = null }, 100)
})
mousePositionEventBinded = true
},
render () {
const { visible, wrapClassName, centered, prefixCls, $listeners, $slots } = this
const defaultFooter = (
<LocaleReceiver
componentName='Modal'
defaultLocale={getConfirmLocale()}
scopedSlots={
{ default: this.renderFooter }
}
/>
)
const closeIcon = (
<span class={`${prefixCls}-close-x`}>
<Icon class={`${prefixCls}-close-icon`} type={'close'}/>
</span>
)
const footer = getComponentFromProp(this, 'footer')
const title = getComponentFromProp(this, 'title')
const dialogProps = {
props: {
...this.$props,
prefixCls,
wrapClassName: classNames({ [`${prefixCls}-centered`]: !!centered }, wrapClassName),
title,
footer: footer === undefined ? defaultFooter : footer,
visible: visible,
mousePosition,
closeIcon,
},
on: {
...$listeners,
close: this.handleCancel,
},
class: getClass(this),
style: getStyle(this),
}
return (
<Dialog {...dialogProps}>
{$slots.default}
</Dialog>
)
},
}