add popconfirm

pull/9/head
tangjinzhou 2018-01-15 17:33:34 +08:00
parent 5d4f905a2f
commit b1e17a0004
16 changed files with 377 additions and 63 deletions

View File

@ -2,6 +2,7 @@
import PropTypes from '../_util/vue-types'
import align from 'dom-align'
import clonedeep from 'lodash.clonedeep'
import isEqual from 'lodash.isequal'
import addEventListener from '../_util/Dom/addEventListener'
import { cloneElement } from '../_util/vnode.js'
import isWindow from './isWindow'
@ -37,48 +38,47 @@ export default {
monitorWindowResize: PropTypes.bool.def(false),
disabled: PropTypes.bool.def(false),
},
watch: {
'$props': {
handler: function (props) {
const prevProps = this.prevProps
this.$nextTick(() => {
let reAlign = false
if (!props.disabled) {
if (prevProps.disabled || prevProps.align !== props.align) {
reAlign = true
} else {
const lastTarget = prevProps.target()
const currentTarget = props.target()
if (isWindow(lastTarget) && isWindow(currentTarget)) {
reAlign = false
} else if (lastTarget !== currentTarget) {
reAlign = true
}
}
}
if (reAlign) {
this.forceAlign()
}
if (props.monitorWindowResize && !props.disabled) {
this.startMonitorWindowResize()
} else {
this.stopMonitorWindowResize()
}
})
},
deep: true,
},
data () {
return {
aligned: false,
}
},
mounted () {
const props = this.$props
// if parent ref not attached .... use document.getElementById
this.forceAlign()
!this.aligned && this.forceAlign()
if (!props.disabled && props.monitorWindowResize) {
this.startMonitorWindowResize()
}
},
updated () {
const prevProps = this.prevProps
const props = this.$props
let reAlign = false
if (!props.disabled) {
if (prevProps.disabled || !isEqual(prevProps.align, props.align)) {
reAlign = true
} else {
const lastTarget = prevProps.target()
const currentTarget = props.target()
if (isWindow(lastTarget) && isWindow(currentTarget)) {
reAlign = false
} else if (lastTarget !== currentTarget) {
reAlign = true
}
}
}
if (reAlign) {
this.forceAlign()
}
if (props.monitorWindowResize && !props.disabled) {
this.startMonitorWindowResize()
} else {
this.stopMonitorWindowResize()
}
},
beforeDestroy () {
this.stopMonitorWindowResize()
},
@ -102,6 +102,7 @@ export default {
const props = this.$props
if (!props.disabled) {
const source = this.$el
this.aligned = true
// this.$emit('align', source, align(source, props.target(), props.align))
this.$listeners.align && this.$listeners.align(source, align(source, props.target(), props.align))
}

View File

@ -3,12 +3,13 @@ import Icon from '../icon'
const rxTwoCNChar = /^[\u4e00-\u9fa5]{2}$/
const isTwoCNChar = rxTwoCNChar.test.bind(rxTwoCNChar)
import buttonTypes from './buttonTypes'
const props = buttonTypes()
export default {
name: 'Button',
__ANT_BUTTON: true,
components: { Icon },
props: {
...buttonTypes,
...props,
},
data () {
return {

View File

@ -1,5 +1,5 @@
import PropTypes from '../_util/vue-types'
export default {
export default () => ({
prefixCls: PropTypes.string.def('ant-btn'),
type: PropTypes.oneOf(['primary', 'danger', 'dashed', 'ghost', 'default']).def('default'),
htmlType: PropTypes.oneOf(['button', 'submit', 'reset']).def('button'),
@ -9,4 +9,4 @@ export default {
loading: PropTypes.oneOfType([PropTypes.bool, PropTypes.object]),
disabled: PropTypes.bool,
ghost: PropTypes.bool,
}
})

View File

@ -415,6 +415,7 @@ export default {
animProps.name = openTransitionName
} else if (typeof openAnimation === 'object') {
animProps = { ...animProps, ...openAnimation.props || {}}
animProps.on = openAnimation.on
if (!transitionAppear) {
animProps.appear = false
}

View File

@ -0,0 +1,62 @@
<template>
<div>
<md>
## 条件触发
可以判断是否需要弹出
</md>
<Popconfirm
title="Are you sure delete this task?"
:visible="visible"
@visibleChange="handleVisibleChange"
@confirm="confirm"
@cancel="cancel"
okText="Yes"
cancelText="No"
>
<a href="#">Delete a task</a>
</Popconfirm>
<br />
<br />
Whether directly execute<Checkbox defaultChecked @change="changeCondition" />
</div>
</template>
<script>
import { Popconfirm, Checkbox } from 'antd'
export default {
data () {
return {
visible: false,
condition: true,
}
},
methods: {
changeCondition (e) {
this.condition = e.target.checked
},
confirm () {
this.visible = false
},
cancel () {
this.visible = false
},
handleVisibleChange (visible) {
if (!visible) {
this.visible = false
return
}
// Determining condition before show the popconfirm.
console.log(this.condition)
if (this.condition) {
this.confirm() // next step
} else {
this.visible = true
}
},
},
components: {
Popconfirm,
Checkbox,
},
}
</script>

View File

@ -0,0 +1,26 @@
<template>
<div>
<h1>Basic</h1>
<Basic />
<h1>Dynamic Trigger</h1>
<Trigger />
<h1>Local</h1>
<Local />
<h1>Placement</h1>
<Placement />
</div>
</template>
<script>
import Basic from './basic'
import Trigger from './dynamic-trigger'
import Local from './local'
import Placement from './placement'
export default {
components: {
Basic,
Trigger,
Local,
Placement,
},
}
</script>

View File

@ -0,0 +1,20 @@
<template>
<div>
<md>
## 国际化
使用 `okText` `cancelText` 自定义按钮文字
</md>
<Popconfirm title="Are you sure" okText="Yes" cancelText="No">
<a href="#">Delete</a>
</Popconfirm>
</div>
</template>
<script>
import { Popconfirm } from 'antd'
export default {
components: {
Popconfirm,
},
}
</script>

View File

@ -0,0 +1,153 @@
<template>
<div id="components-popconfirm-demo-placement">
<md>
## 位置
位置有十二个方向如需箭头指向目标元素中心可以设置 `arrowPointAtCenter`
</md>
<div :style="{ marginLeft: `${buttonWidth}px`, whiteSpace: 'nowrap' }">
<Popconfirm placement="topLeft" okText="Yes" cancelText="No" @confirm="confirm">
<template slot="title">
<div>
<p>Are you sure delete this task?</p>
<p>Are you sure delete this task?</p>
</div>
</template>
<AntButton>TL</AntButton>
</Popconfirm>
<Popconfirm placement="top" okText="Yes" cancelText="No" @confirm="confirm">
<template slot="title">
<div>
<p>Are you sure delete this task?</p>
<p>Are you sure delete this task?</p>
</div>
</template>
<AntButton>Top</AntButton>
</Popconfirm>
<Popconfirm placement="topRight" okText="Yes" cancelText="No" @confirm="confirm">
<template slot="title">
<div>
<p>Are you sure delete this task?</p>
<p>Are you sure delete this task?</p>
</div>
</template>
<AntButton>TR</AntButton>
</Popconfirm>
</div>
<div :style="{ width: `${buttonWidth}px`, float: 'left' }">
<Popconfirm placement="leftTop" okText="Yes" cancelText="No" @confirm="confirm">
<template slot="title">
<div>
<p>Are you sure delete this task?</p>
<p>Are you sure delete this task?</p>
</div>
</template>
<AntButton>LT</AntButton>
</Popconfirm>
<Popconfirm placement="left" okText="Yes" cancelText="No" @confirm="confirm">
<template slot="title">
<div>
<p>Are you sure delete this task?</p>
<p>Are you sure delete this task?</p>
</div>
</template>
<AntButton>Left</AntButton>
</Popconfirm>
<Popconfirm placement="leftBottom" okText="Yes" cancelText="No" @confirm="confirm">
<template slot="title">
<div>
<p>Are you sure delete this task?</p>
<p>Are you sure delete this task?</p>
</div>
</template>
<AntButton>LB</AntButton>
</Popconfirm>
</div>
<div :style="{ width: `${buttonWidth}px`, marginLeft: `${buttonWidth * 4 + 24 }px`}">
<Popconfirm placement="rightTop" okText="Yes" cancelText="No" @confirm="confirm">
<template slot="title">
<div>
<p>Are you sure delete this task?</p>
<p>Are you sure delete this task?</p>
</div>
</template>
<AntButton>RT</AntButton>
</Popconfirm>
<Popconfirm placement="right" okText="Yes" cancelText="No" @confirm="confirm">
<template slot="title">
<div>
<p>Are you sure delete this task?</p>
<p>Are you sure delete this task?</p>
</div>
</template>
<AntButton>Right</AntButton>
</Popconfirm>
<Popconfirm placement="rightBottom" okText="Yes" cancelText="No" @confirm="confirm">
<template slot="title">
<div>
<p>Are you sure delete this task?</p>
<p>Are you sure delete this task?</p>
</div>
</template>
<AntButton>RB</AntButton>
</Popconfirm>
</div>
<div :style="{ marginLeft: `${buttonWidth}px`, clear: 'both', whiteSpace: 'nowrap' }">
<Popconfirm placement="bottomLeft" okText="Yes" cancelText="No" @confirm="confirm">
<template slot="title">
<div>
<p>Are you sure delete this task?</p>
<p>Are you sure delete this task?</p>
</div>
</template>
<AntButton>BL</AntButton>
</Popconfirm>
<Popconfirm placement="bottom" okText="Yes" cancelText="No" @confirm="confirm">
<template slot="title">
<div>
<p>Are you sure delete this task?</p>
<p>Are you sure delete this task?</p>
</div>
</template>
<AntButton>Bottom</AntButton>
</Popconfirm>
<Popconfirm placement="bottomRight" okText="Yes" cancelText="No" @confirm="confirm">
<template slot="title">
<div>
<p>Are you sure delete this task?</p>
<p>Are you sure delete this task?</p>
</div>
</template>
<AntButton>BR</AntButton>
</Popconfirm>
</div>
</div>
</template>
<script>
import { Popconfirm, Button } from 'antd'
export default {
data () {
return {
buttonWidth: 70,
}
},
methods: {
confirm () {
console.log('Click on Yes')
},
},
components: {
Popconfirm,
AntButton: Button,
},
}
</script>
<style>
#components-popconfirm-demo-placement .ant-btn {
width: 70px;
text-align: center;
padding: 0;
margin-right: 8px;
margin-bottom: 8px;
}
</style>

View File

@ -9,23 +9,30 @@ import buttonTypes from '../button/buttonTypes'
import Icon from '../icon'
import Button from '../button'
const tooltipProps = abstractTooltipProps()
const btnProps = buttonTypes()
export default {
name: 'popconfirm',
props: {
...abstractTooltipProps,
...tooltipProps,
prefixCls: PropTypes.string.def('ant-popover'),
transitionName: PropTypes.string.def('zoom-big'),
content: PropTypes.any,
title: PropTypes.any,
trigger: abstractTooltipProps.trigger.def('click'),
okType: buttonTypes.type.def('primary'),
trigger: tooltipProps.trigger.def('click'),
okType: btnProps.type.def('primary'),
okText: PropTypes.any,
cancelText: PropTypes.any,
},
mixins: [BaseMixin],
model: {
prop: 'visible',
event: 'change',
event: 'visibleChange',
},
watch: {
visible (val) {
this.sVisible = val
},
},
data () {
return {
@ -48,16 +55,10 @@ export default {
},
setVisible (sVisible) {
const props = this.$props
if (!hasProp(this, 'visible')) {
this.setState({ sVisible })
}
const { onVisibleChange } = props
if (onVisibleChange) {
onVisibleChange(sVisible)
}
this.$emit('change', sVisible)
this.$emit('visibleChange', sVisible)
},
getPopupDomNode () {
return this.$refs.tooltip.getPopupDomNode()

View File

@ -24,7 +24,7 @@ export default {
},
render (h) {
const { title, prefixCls, content, $slots } = this
const { title, prefixCls, $slots } = this
const props = getOptionProps(this)
delete props.title
delete props.content

View File

@ -1,5 +1,5 @@
import PropTypes from '../_util/vue-types'
export default {
export default () => ({
trigger: PropTypes.oneOf(['hover', 'focus', 'click']).def('hover'),
visible: PropTypes.bool,
placement: PropTypes.oneOf(['top', 'left', 'right', 'bottom',
@ -16,4 +16,4 @@ export default {
getPopupContainer: PropTypes.func,
arrowPointAtCenter: PropTypes.bool.def(false),
autoAdjustOverflow: PropTypes.oneOfType([PropTypes.bool, PropTypes.object]).def(true),
}
})

View File

@ -17,11 +17,11 @@ const splitObject = (obj, keys) => {
})
return { picked, omited }
}
const props = abstractTooltipProps()
export default {
name: 'Tooltip',
props: {
...abstractTooltipProps,
...props,
title: PropTypes.any,
},
model: {

View File

@ -4,6 +4,7 @@ import Align from '../align'
import PopupInner from './PopupInner'
import LazyRenderBox from './LazyRenderBox'
import { noop } from './utils'
import animate from 'css-animation'
export default {
props: {
@ -24,6 +25,7 @@ export default {
},
data () {
return {
aligned: false,
destroyPopup: false,
initAlign: false, // mountedalign,this.$el
}
@ -48,7 +50,8 @@ export default {
initAlign (val) {
if (val) {
this.$nextTick(() => {
this.$refs.alignInstance.forceAlign()
// console.log(this.$refs.alignInstance.$el)
// this.$refs.alignInstance.forceAlign()
})
}
},
@ -94,11 +97,6 @@ export default {
getClassName (currentAlignClassName) {
return `${this.$props.prefixCls} ${this.$props.popupClassName} ${currentAlignClassName}`
},
afterLeave (el) {
if (this.destroyPopupOnHide) {
this.destroyPopup = true
}
},
getPopupElement () {
const { $props: props, $slots, $listeners } = this
const { align, visible, prefixCls, animation } = props
@ -114,6 +112,7 @@ export default {
props: {
prefixCls,
visible,
// hiddenClassName,
},
class: `${className}`,
on: {
@ -126,11 +125,43 @@ export default {
const transitionProps = {
props: Object.assign({
appear: true,
}, typeof animation === 'object' ? animation : { name: this.getTransitionName() }),
css: false,
}),
}
let opacity = '1'
const transitionEvent = {
beforeEnter: (el) => {
opacity = el.style.opacity
el.style.opacity = '0'
!this.aligned && this.$refs.alignInstance.forceAlign()
this.aligned = true
},
enter: (el, done) => {
el.style.opacity = opacity
animate(el, 'zoom-big-enter', done)
},
leave: (el, done) => {
animate(el, 'zoom-big-leave', done)
},
afterLeave: (el) => {
if (this.destroyPopupOnHide) {
this.destroyPopup = true
}
},
}
if (typeof animation === 'object') {
const { on = {}, ...otherProps } = animation
transitionProps.props = { ...transitionProps.props, ...otherProps }
transitionProps.on = { ...on, afterLeave: (el) => {
transitionEvent.afterLeave(el)
on.afterLeave && on.afterLeave(el)
} }
} else {
transitionProps.on = transitionEvent
}
return (<transition
{...transitionProps}
onAfterLeave={this.afterLeave}
>
<Align
v-show={visible}

View File

@ -9,13 +9,14 @@ export default {
visible: PropTypes.bool,
},
render () {
const { prefixCls, visible } = this.$props
const { prefixCls, visible, hiddenClassName } = this.$props
const { $listeners } = this
const divProps = {
on: $listeners,
}
return (
<div {...divProps}>
<div {...divProps} class={!visible ? hiddenClassName : ''}>
<LazyRenderBox class={`${prefixCls}-content`} visible={visible}>
{this.$slots.default}
</LazyRenderBox>

View File

@ -0,0 +1,16 @@
<script>
export default {
props: {
transitionProps: Object,
},
render () {
return (
<transition
{...this.transitionProps}
>
{this.$slots.default}
</transition>
)
},
}
</script>

View File

@ -81,6 +81,7 @@
"eslint-plugin-vue": "^3.13.0",
"lodash.clonedeep": "^4.5.0",
"lodash.debounce": "^4.0.8",
"lodash.isequal": "^4.5.0",
"lodash.isplainobject": "^4.0.6",
"omit.js": "^1.0.0",
"vue": "^2.5.13",