add modal
parent
0346b11868
commit
c67e4103f4
|
@ -60,12 +60,9 @@ export default {
|
|||
})
|
||||
},
|
||||
render () {
|
||||
console.log(props)
|
||||
return getComponent(props)
|
||||
},
|
||||
})
|
||||
} else {
|
||||
this._component.$forceUpdate()
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -111,7 +111,11 @@ export function getClass (ele) {
|
|||
} else if (ele.$vnode && ele.$vnode.data) {
|
||||
data = ele.$vnode.data
|
||||
}
|
||||
return data.class || data.staticClass
|
||||
let cls = data.class || data.staticClass || {}
|
||||
if (typeof cls === 'string') {
|
||||
cls = cls.split(' ').forEach(c => { cls[c.trim()] = true })
|
||||
}
|
||||
return cls
|
||||
}
|
||||
export function getStyle (ele) {
|
||||
let data = {}
|
||||
|
@ -138,6 +142,10 @@ export function isEmptyElement (ele) {
|
|||
export function filterEmpty (children = []) {
|
||||
return children.filter(c => c.tag || c.text.trim() !== '')
|
||||
}
|
||||
const initDefaultProps = (propTypes, defaultProps) => {
|
||||
Object.keys(defaultProps).forEach(k => { propTypes[k] = propTypes[k].def(defaultProps[k]) })
|
||||
return propTypes
|
||||
}
|
||||
export {
|
||||
hasProp,
|
||||
filterProps,
|
||||
|
@ -150,5 +158,6 @@ export {
|
|||
getAttrs,
|
||||
getValueByProp,
|
||||
parseStyleText,
|
||||
initDefaultProps,
|
||||
}
|
||||
export default hasProp
|
||||
|
|
|
@ -93,4 +93,5 @@ export { default as Affix } from './affix'
|
|||
|
||||
export { default as Cascader } from './cascader'
|
||||
export { default as BackTop } from './back-top'
|
||||
export { default as Modal } from './modal'
|
||||
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
<script>
|
||||
import PropTypes from '../_util/vue-types'
|
||||
import Button from '../button'
|
||||
import BaseMixin from '../_util/BaseMixin'
|
||||
import buttonTypes from '../button/buttonTypes'
|
||||
const ButtonType = buttonTypes().type
|
||||
const ActionButtonProps = {
|
||||
type: ButtonType,
|
||||
actionFn: PropTypes.func,
|
||||
closeModal: PropTypes.func,
|
||||
autoFocus: PropTypes.bool,
|
||||
}
|
||||
|
||||
export default {
|
||||
mixins: [BaseMixin],
|
||||
props: ActionButtonProps,
|
||||
data () {
|
||||
return {
|
||||
loading: false,
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
if (this.autoFocus) {
|
||||
this.timeoutId = setTimeout(() => this.$el.focus())
|
||||
}
|
||||
},
|
||||
beforeDestroy () {
|
||||
clearTimeout(this.timeoutId)
|
||||
},
|
||||
methods: {
|
||||
onClick () {
|
||||
const { actionFn, closeModal } = this
|
||||
if (actionFn) {
|
||||
let ret
|
||||
if (actionFn.length) {
|
||||
ret = actionFn(closeModal)
|
||||
} else {
|
||||
ret = actionFn()
|
||||
if (!ret) {
|
||||
closeModal()
|
||||
}
|
||||
}
|
||||
if (ret && ret.then) {
|
||||
this.setState({ loading: true })
|
||||
ret.then((...args) => {
|
||||
// It's unnecessary to set loading=false, for the Modal will be unmounted after close.
|
||||
// this.setState({ loading: false });
|
||||
closeModal(...args)
|
||||
}, () => {
|
||||
// See: https://github.com/ant-design/ant-design/issues/6183
|
||||
this.setState({ loading: false })
|
||||
})
|
||||
}
|
||||
} else {
|
||||
closeModal()
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
render () {
|
||||
const { type, $slots, loading } = this
|
||||
return (
|
||||
<Button type={type} onClick={this.onClick} loading={loading}>
|
||||
{$slots.default}
|
||||
</Button>
|
||||
)
|
||||
},
|
||||
}
|
||||
|
||||
</script>
|
|
@ -0,0 +1,71 @@
|
|||
<script>
|
||||
import classNames from 'classnames'
|
||||
import Icon from '../icon'
|
||||
import Dialog from './Modal'
|
||||
import ActionButton from './ActionButton'
|
||||
import { getConfirmLocale } from './locale'
|
||||
|
||||
export default {
|
||||
functional: true,
|
||||
render () {
|
||||
const { onCancel, onOk, close, zIndex, afterClose, visible } = this.$props
|
||||
const props = this.$props
|
||||
const iconType = props.iconType || 'question-circle'
|
||||
const okType = props.okType || 'primary'
|
||||
const prefixCls = props.prefixCls || 'ant-confirm'
|
||||
// 默认为 true,保持向下兼容
|
||||
const okCancel = ('okCancel' in props) ? props.okCancel : true
|
||||
const width = props.width || 416
|
||||
const style = props.style || {}
|
||||
// 默认为 false,保持旧版默认行为
|
||||
const maskClosable = props.maskClosable === undefined ? false : props.maskClosable
|
||||
const runtimeLocale = getConfirmLocale()
|
||||
const okText = props.okText ||
|
||||
(okCancel ? runtimeLocale.okText : runtimeLocale.justOkText)
|
||||
const cancelText = props.cancelText || runtimeLocale.cancelText
|
||||
|
||||
const classString = classNames(
|
||||
prefixCls,
|
||||
`${prefixCls}-${props.type}`,
|
||||
props.class,
|
||||
)
|
||||
|
||||
const cancelButton = okCancel && (
|
||||
<ActionButton actionFn={onCancel} closeModal={close}>
|
||||
{cancelText}
|
||||
</ActionButton>
|
||||
)
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
class={classString}
|
||||
onCancel={(e) => close({ triggerCancel: true }, e)}
|
||||
visible={visible}
|
||||
title=''
|
||||
transitionName='zoom'
|
||||
footer=''
|
||||
maskTransitionName='fade'
|
||||
maskClosable={maskClosable}
|
||||
style={style}
|
||||
width={width}
|
||||
zIndex={zIndex}
|
||||
afterClose={afterClose}
|
||||
>
|
||||
<div class={`${prefixCls}-body-wrapper`}>
|
||||
<div class={`${prefixCls}-body`}>
|
||||
<Icon type={iconType} />
|
||||
<span class={`${prefixCls}-title`}>{props.title}</span>
|
||||
<div class={`${prefixCls}-content`}>{props.content}</div>
|
||||
</div>
|
||||
<div class={`${prefixCls}-btns`}>
|
||||
{cancelButton}
|
||||
<ActionButton type={okType} actionFn={onOk} closeModal={close} autoFocus>
|
||||
{okText}
|
||||
</ActionButton>
|
||||
</div>
|
||||
</div>
|
||||
</Dialog>)
|
||||
},
|
||||
}
|
||||
|
||||
</script>
|
|
@ -0,0 +1,149 @@
|
|||
<script>
|
||||
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 } from '../_util/props-util'
|
||||
|
||||
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),
|
||||
/** 宽度*/
|
||||
width: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||
/** 底部内容*/
|
||||
footer: PropTypes.any,
|
||||
/** 确认按钮文字*/
|
||||
okText: PropTypes.string,
|
||||
/** 确认按钮类型*/
|
||||
okType: ButtonType,
|
||||
/** 取消按钮文字*/
|
||||
cancelText: PropTypes.string,
|
||||
/** 点击蒙层是否允许关闭*/
|
||||
maskClosable: PropTypes.bool,
|
||||
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,
|
||||
}
|
||||
return initDefaultProps(props, defaultProps)
|
||||
}
|
||||
|
||||
export default {
|
||||
props: modalProps({
|
||||
prefixCls: 'ant-modal',
|
||||
width: 520,
|
||||
transitionName: 'zoom',
|
||||
maskTransitionName: 'fade',
|
||||
confirmLoading: false,
|
||||
visible: false,
|
||||
okType: 'primary',
|
||||
}),
|
||||
// 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)
|
||||
},
|
||||
|
||||
handleOk (e) {
|
||||
this.$emit('ok', e)
|
||||
},
|
||||
renderFooter (locale) {
|
||||
const { okType, confirmLoading } = this
|
||||
return (
|
||||
<div>
|
||||
<Button
|
||||
onClick={this.handleCancel}
|
||||
>
|
||||
{getComponentFromProp(this, 'cancelText') || locale.cancelText}
|
||||
</Button>
|
||||
<Button
|
||||
type={okType}
|
||||
loading={confirmLoading}
|
||||
onClick={this.handleOk}
|
||||
>
|
||||
{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, $listeners, $slots } = this
|
||||
|
||||
const defaultFooter = (
|
||||
<LocaleReceiver
|
||||
componentName='Modal'
|
||||
defaultLocale={getConfirmLocale()}
|
||||
children={this.renderFooter}
|
||||
/>
|
||||
)
|
||||
const dialogProps = {
|
||||
props: {
|
||||
...this.$props,
|
||||
title: getComponentFromProp(this, 'title'),
|
||||
footer: getComponentFromProp(this, 'footer') || defaultFooter,
|
||||
visible: visible,
|
||||
mousePosition,
|
||||
},
|
||||
on: {
|
||||
...$listeners,
|
||||
close: this.handleCancel,
|
||||
},
|
||||
}
|
||||
return (
|
||||
<Dialog {...dialogProps}>
|
||||
{$slots.default}
|
||||
</Dialog>
|
||||
)
|
||||
},
|
||||
}
|
||||
|
||||
</script>
|
|
@ -0,0 +1,39 @@
|
|||
import Vue from 'vue'
|
||||
import ConfirmDialog from './ConfirmDialog'
|
||||
export default function confirm (config) {
|
||||
const div = document.createElement('div')
|
||||
document.body.appendChild(div)
|
||||
let confirmDialogInstance = null
|
||||
function close (...args) {
|
||||
destroy(...args)
|
||||
}
|
||||
|
||||
function destroy (...args) {
|
||||
if (confirmDialogInstance && div.parentNode) {
|
||||
confirmDialogInstance.$destroy()
|
||||
confirmDialogInstance = null
|
||||
div.parentNode.removeChild(div)
|
||||
}
|
||||
const triggerCancel = args && args.length &&
|
||||
args.some(param => param && param.triggerCancel)
|
||||
if (config.onCancel && triggerCancel) {
|
||||
config.onCancel(...args)
|
||||
}
|
||||
}
|
||||
|
||||
function render (props) {
|
||||
return new Vue({
|
||||
el: div,
|
||||
render () {
|
||||
return <ConfirmDialog {...props} />
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
confirmDialogInstance = render({ ...config, visible: true, close })
|
||||
|
||||
return {
|
||||
destroy: close,
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
|
||||
<cn>
|
||||
#### 基本
|
||||
第一个对话框。
|
||||
</cn>
|
||||
|
||||
<us>
|
||||
#### Basic
|
||||
Basic modal.
|
||||
</us>
|
||||
|
||||
```html
|
||||
<template>
|
||||
<div>
|
||||
<a-button type="primary" @click="showModal">Open</a-button>
|
||||
<a-modal
|
||||
title="Basic Modal"
|
||||
:visible="visible"
|
||||
@ok="handleOk"
|
||||
@cancel="handleCancel"
|
||||
>
|
||||
<p>Some contents...</p>
|
||||
<p>Some contents...</p>
|
||||
<p>Some contents...</p>
|
||||
</a-modal>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
visible: false,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
showModal() {
|
||||
this.visible = true
|
||||
},
|
||||
handleOk(e) {
|
||||
console.log(e);
|
||||
this.visible = false
|
||||
},
|
||||
handleCancel(e) {
|
||||
console.log(e);
|
||||
this.visible = false
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
import Modal from './Modal'
|
||||
import confirm from './confirm'
|
||||
|
||||
// export { ActionButtonProps } from './ActionButton'
|
||||
// export { ModalProps, ModalFuncProps } from './Modal'
|
||||
|
||||
Modal.info = function (props) {
|
||||
const config = {
|
||||
type: 'info',
|
||||
iconType: 'info-circle',
|
||||
okCancel: false,
|
||||
...props,
|
||||
}
|
||||
return confirm(config)
|
||||
}
|
||||
|
||||
Modal.success = function (props) {
|
||||
const config = {
|
||||
type: 'success',
|
||||
iconType: 'check-circle',
|
||||
okCancel: false,
|
||||
...props,
|
||||
}
|
||||
return confirm(config)
|
||||
}
|
||||
|
||||
Modal.error = function (props) {
|
||||
const config = {
|
||||
type: 'error',
|
||||
iconType: 'cross-circle',
|
||||
okCancel: false,
|
||||
...props,
|
||||
}
|
||||
return confirm(config)
|
||||
}
|
||||
|
||||
Modal.warning = Modal.warn = function (props) {
|
||||
const config = {
|
||||
type: 'warning',
|
||||
iconType: 'exclamation-circle',
|
||||
okCancel: false,
|
||||
...props,
|
||||
}
|
||||
return confirm(config)
|
||||
}
|
||||
|
||||
Modal.confirm = function (props) {
|
||||
const config = {
|
||||
type: 'confirm',
|
||||
okCancel: true,
|
||||
...props,
|
||||
}
|
||||
return confirm(config)
|
||||
}
|
||||
|
||||
export default Modal
|
|
@ -0,0 +1,28 @@
|
|||
import defaultLocale from '../locale-provider/default'
|
||||
|
||||
// export interface ModalLocale {
|
||||
// okText: string;
|
||||
// cancelText: string;
|
||||
// justOkText: string;
|
||||
// }
|
||||
|
||||
let runtimeLocale = {
|
||||
...defaultLocale.Modal,
|
||||
}
|
||||
|
||||
export function changeConfirmLocale (newLocale) {
|
||||
if (newLocale) {
|
||||
runtimeLocale = {
|
||||
...runtimeLocale,
|
||||
...newLocale,
|
||||
}
|
||||
} else {
|
||||
runtimeLocale = {
|
||||
...defaultLocale.Modal,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function getConfirmLocale () {
|
||||
return runtimeLocale
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
@import "../../style/mixins/index";
|
||||
|
||||
@confirm-prefix-cls: ~"@{ant-prefix}-confirm";
|
||||
|
||||
.@{confirm-prefix-cls} {
|
||||
.@{ant-prefix}-modal-header {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.@{ant-prefix}-modal-close {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.@{ant-prefix}-modal-body {
|
||||
padding: 32px 32px 24px;
|
||||
}
|
||||
|
||||
&-body-wrapper {
|
||||
.clearfix();
|
||||
}
|
||||
|
||||
&-body {
|
||||
.@{confirm-prefix-cls}-title {
|
||||
color: @heading-color;
|
||||
font-weight: 500;
|
||||
font-size: @font-size-lg;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.@{confirm-prefix-cls}-content {
|
||||
margin-left: 38px;
|
||||
font-size: @font-size-base;
|
||||
color: @text-color;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
> .@{iconfont-css-prefix} {
|
||||
font-size: 22px;
|
||||
margin-right: 16px;
|
||||
float: left;
|
||||
min-height: 48px;
|
||||
}
|
||||
}
|
||||
|
||||
.@{confirm-prefix-cls}-btns {
|
||||
margin-top: 24px;
|
||||
float: right;
|
||||
|
||||
button + button {
|
||||
margin-left: 8px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&-error &-body > .@{iconfont-css-prefix} {
|
||||
color: @error-color;
|
||||
}
|
||||
|
||||
&-warning &-body > .@{iconfont-css-prefix},
|
||||
&-confirm &-body > .@{iconfont-css-prefix} {
|
||||
color: @warning-color;
|
||||
}
|
||||
|
||||
&-info &-body > .@{iconfont-css-prefix} {
|
||||
color: @info-color;
|
||||
}
|
||||
|
||||
&-success &-body > .@{iconfont-css-prefix} {
|
||||
color: @success-color;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
import '../../style/index.less'
|
||||
import './index.less'
|
||||
|
||||
// style dependencies
|
||||
import '../../button/style'
|
|
@ -0,0 +1,4 @@
|
|||
@import "../../style/themes/default";
|
||||
@import "../../style/mixins/index";
|
||||
@import "./modal";
|
||||
@import "./confirm";
|
|
@ -0,0 +1,146 @@
|
|||
@dialog-prefix-cls: ~"@{ant-prefix}-modal";
|
||||
|
||||
.@{dialog-prefix-cls} {
|
||||
.reset-component;
|
||||
position: relative;
|
||||
width: auto;
|
||||
margin: 0 auto;
|
||||
top: 100px;
|
||||
padding-bottom: 24px;
|
||||
|
||||
&-wrap {
|
||||
position: fixed;
|
||||
overflow: auto;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: @zindex-modal;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
&-title {
|
||||
margin: 0;
|
||||
font-size: @font-size-lg;
|
||||
line-height: 22px;
|
||||
font-weight: 500;
|
||||
color: @heading-color;
|
||||
}
|
||||
|
||||
&-content {
|
||||
position: relative;
|
||||
background-color: @component-background;
|
||||
border: 0;
|
||||
border-radius: @border-radius-base;
|
||||
background-clip: padding-box;
|
||||
box-shadow: @shadow-2;
|
||||
}
|
||||
|
||||
&-close {
|
||||
cursor: pointer;
|
||||
border: 0;
|
||||
background: transparent;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
z-index: 10;
|
||||
font-weight: 700;
|
||||
line-height: 1;
|
||||
text-decoration: none;
|
||||
transition: color .3s;
|
||||
color: @text-color-secondary;
|
||||
outline: 0;
|
||||
padding: 0;
|
||||
|
||||
&-x {
|
||||
display: block;
|
||||
font-style: normal;
|
||||
vertical-align: baseline;
|
||||
text-align: center;
|
||||
text-transform: none;
|
||||
text-rendering: auto;
|
||||
width: 56px;
|
||||
height: 56px;
|
||||
line-height: 56px;
|
||||
font-size: @font-size-lg;
|
||||
|
||||
&:before {
|
||||
content: "\e633";
|
||||
display: block;
|
||||
font-family: "anticon" !important;
|
||||
}
|
||||
}
|
||||
|
||||
&:focus,
|
||||
&:hover {
|
||||
color: #444;
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
||||
&-header {
|
||||
padding: 16px 24px;
|
||||
border-radius: @border-radius-base @border-radius-base 0 0;
|
||||
background: @component-background;
|
||||
color: @text-color;
|
||||
border-bottom: @border-width-base @border-style-base @border-color-split;
|
||||
}
|
||||
|
||||
&-body {
|
||||
padding: 24px;
|
||||
font-size: @font-size-base;
|
||||
line-height: @line-height-base;
|
||||
}
|
||||
|
||||
&-footer {
|
||||
border-top: @border-width-base @border-style-base @border-color-split;
|
||||
padding: 10px 16px;
|
||||
text-align: right;
|
||||
border-radius: 0 0 @border-radius-base @border-radius-base;
|
||||
button + button {
|
||||
margin-left: 8px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&.zoom-enter,
|
||||
&.zoom-appear {
|
||||
animation-duration: @animation-duration-slow;
|
||||
transform: none; // reset scale avoid mousePosition bug
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
&-mask {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
background-color: #373737;
|
||||
background-color: @modal-mask-bg; // lesshint duplicateProperty: false
|
||||
height: 100%;
|
||||
z-index: @zindex-modal-mask;
|
||||
filter: ~"alpha(opacity=50)";
|
||||
|
||||
&-hidden {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
&-open {
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: @screen-md) {
|
||||
.@{dialog-prefix-cls} {
|
||||
width: auto !important;
|
||||
margin: 10px;
|
||||
}
|
||||
.vertical-center-modal {
|
||||
.@{dialog-prefix-cls} {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -27,3 +27,4 @@ import './auto-complete/style'
|
|||
import './affix/style'
|
||||
import './cascader/style'
|
||||
import './back-top/style'
|
||||
import './modal/style'
|
||||
|
|
|
@ -218,11 +218,11 @@ export default {
|
|||
},
|
||||
|
||||
render () {
|
||||
const { destroyPopup, getMaskElement, getPopupElement } = this
|
||||
const { destroyPopup, getMaskElement, getPopupElement, visible } = this
|
||||
return (
|
||||
<div>
|
||||
{getMaskElement()}
|
||||
{ destroyPopup ? null : getPopupElement()}
|
||||
{(visible || !destroyPopup) ? getPopupElement() : null}
|
||||
</div>
|
||||
)
|
||||
},
|
||||
|
|
|
@ -62,6 +62,11 @@ export default {
|
|||
prefixCls: 'rc-dialog',
|
||||
}),
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
destroyPopup: false,
|
||||
}
|
||||
},
|
||||
|
||||
// private inTransition: boolean;
|
||||
// private titleId: string;
|
||||
|
@ -88,10 +93,13 @@ export default {
|
|||
this.$nextTick(() => {
|
||||
this.updatedCallback(val)
|
||||
})
|
||||
if (val) {
|
||||
this.destroyPopup = false
|
||||
}
|
||||
},
|
||||
},
|
||||
beforeDestroy () {
|
||||
if (this.props.visible || this.inTransition) {
|
||||
if (this.visible || this.inTransition) {
|
||||
this.removeScrollingEffect()
|
||||
}
|
||||
},
|
||||
|
@ -127,12 +135,15 @@ export default {
|
|||
}
|
||||
},
|
||||
onAnimateLeave () {
|
||||
const { afterClose } = this
|
||||
const { afterClose, destroyOnClose } = this
|
||||
// need demo?
|
||||
// https://github.com/react-component/dialog/pull/28
|
||||
if (this.$refs.wrap) {
|
||||
this.$refs.wrap.style.display = 'none'
|
||||
}
|
||||
if (destroyOnClose) {
|
||||
this.destroyPopup = true
|
||||
}
|
||||
this.inTransition = false
|
||||
this.removeScrollingEffect()
|
||||
if (afterClose) {
|
||||
|
@ -149,6 +160,7 @@ export default {
|
|||
}
|
||||
},
|
||||
onKeydown (e) {
|
||||
console.log('keydown')
|
||||
const props = this.$props
|
||||
if (props.keyboard && e.keyCode === KeyCode.ESC) {
|
||||
this.close(e)
|
||||
|
@ -169,32 +181,31 @@ export default {
|
|||
}
|
||||
},
|
||||
getDialogElement () {
|
||||
const props = this.$props
|
||||
const closable = props.closable
|
||||
const prefixCls = props.prefixCls
|
||||
const { closable, prefixCls, width, height,
|
||||
title, footer: tempFooter, bodyStyle, visible, bodyProps } = this
|
||||
const dest = {}
|
||||
if (props.width !== undefined) {
|
||||
dest.width = props.width
|
||||
if (width !== undefined) {
|
||||
dest.width = typeof width === 'number' ? `${width}px` : width
|
||||
}
|
||||
if (props.height !== undefined) {
|
||||
dest.height = props.height
|
||||
if (height !== undefined) {
|
||||
dest.height = typeof height === 'number' ? `${height}px` : height
|
||||
}
|
||||
|
||||
let footer
|
||||
if (props.footer) {
|
||||
if (tempFooter) {
|
||||
footer = (
|
||||
<div class={`${prefixCls}-footer`} ref='footer'>
|
||||
{props.footer}
|
||||
{tempFooter}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
let header
|
||||
if (props.title) {
|
||||
if (title) {
|
||||
header = (
|
||||
<div class={`${prefixCls}-header`} ref='header'>
|
||||
<div class={`${prefixCls}-title`} id={this.titleId}>
|
||||
{props.title}
|
||||
{title}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
@ -213,25 +224,29 @@ export default {
|
|||
</button>)
|
||||
}
|
||||
|
||||
const style = { ...dest }
|
||||
const style = { ...this.dialogStyle, ...dest }
|
||||
const cls = {
|
||||
[prefixCls]: true,
|
||||
...this.dialogClass,
|
||||
}
|
||||
const transitionName = this.getTransitionName()
|
||||
const dialogElement = (
|
||||
<LazyRenderBox
|
||||
v-show={props.visible}
|
||||
v-show={visible}
|
||||
key='dialog-element'
|
||||
role='document'
|
||||
ref='dialog'
|
||||
style={style}
|
||||
class={prefixCls}
|
||||
class={cls}
|
||||
>
|
||||
<div class={`${prefixCls}-content`}>
|
||||
{closer}
|
||||
{header}
|
||||
<div
|
||||
class={`${prefixCls}-body`}
|
||||
style={props.bodyStyle}
|
||||
style={bodyStyle}
|
||||
ref='body'
|
||||
{...props.bodyProps}
|
||||
{...bodyProps}
|
||||
>
|
||||
{this.$slots.default}
|
||||
</div>
|
||||
|
@ -250,7 +265,7 @@ export default {
|
|||
key='dialog'
|
||||
{...dialogTransitionProps}
|
||||
>
|
||||
{(props.visible || !props.destroyOnClose) ? dialogElement : null}
|
||||
{(visible || !this.destroyPopup) ? dialogElement : null}
|
||||
</transition>
|
||||
)
|
||||
},
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
import Dialog from './Dialog'
|
||||
import ContainerRender from '../_util/ContainerRender'
|
||||
import getDialogPropTypes from './IDialogPropTypes'
|
||||
import { getStyle, getClass } from '../_util/props-util'
|
||||
const IDialogPropTypes = getDialogPropTypes()
|
||||
const DialogWrap = {
|
||||
props: {
|
||||
|
@ -29,16 +30,22 @@ const DialogWrap = {
|
|||
},
|
||||
methods: {
|
||||
getComponent (extra = {}) {
|
||||
const { $attrs, $listeners, $props, $slots } = this
|
||||
|
||||
const dialogProps = {
|
||||
props: {
|
||||
...this.$props,
|
||||
...$props,
|
||||
dialogClass: getClass(this),
|
||||
dialogStyle: getStyle(this),
|
||||
...extra,
|
||||
},
|
||||
attrs: $attrs,
|
||||
ref: '_component',
|
||||
key: 'dialog',
|
||||
on: $listeners,
|
||||
}
|
||||
return (
|
||||
<Dialog {...dialogProps}>{this.$slots.default}</Dialog>
|
||||
<Dialog {...dialogProps}>{$slots.default}</Dialog>
|
||||
)
|
||||
},
|
||||
|
||||
|
|
|
@ -25,13 +25,15 @@ function IDialogPropTypes () {
|
|||
maskStyle: PropTypes.object,
|
||||
prefixCls: PropTypes.string,
|
||||
wrapClassName: PropTypes.string,
|
||||
width: PropTypes.number,
|
||||
height: PropTypes.number,
|
||||
width: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||
height: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||
zIndex: PropTypes.number,
|
||||
bodyProps: PropTypes.any,
|
||||
maskProps: PropTypes.any,
|
||||
wrapProps: PropTypes.any,
|
||||
getContainer: PropTypes.func,
|
||||
dialogStyle: PropTypes.object.def({}),
|
||||
dialogClass: PropTypes.object.def({}),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
import '../assets/index.less'
|
||||
// use import Dialog from 'rc-dialog'
|
||||
import Dialog from '../DialogWrap'
|
||||
import Dialog from '../index'
|
||||
|
||||
export default {
|
||||
data () {
|
||||
|
@ -34,7 +34,6 @@ export default {
|
|||
},
|
||||
|
||||
changeWidth (e) {
|
||||
console.log(e)
|
||||
this.width = this.width === 600 ? 800 : 600
|
||||
},
|
||||
|
||||
|
@ -110,4 +109,4 @@ export default {
|
|||
)
|
||||
},
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
import DialogWrap from './DialogWrap'
|
||||
export default DialogWrap
|
|
@ -3,7 +3,7 @@ const AsyncComp = () => {
|
|||
const hashs = window.location.hash.split('/')
|
||||
const d = hashs[hashs.length - 1]
|
||||
return {
|
||||
component: import(`../components/vc-dialog/demo/${d}.vue`),
|
||||
component: import(`../components/modal/demo/${d}`),
|
||||
}
|
||||
}
|
||||
export default [
|
||||
|
|
Loading…
Reference in New Issue