151 lines
4.1 KiB
Vue
151 lines
4.1 KiB
Vue
<script>
|
|
import PropTypes from '../../_util/vue-types'
|
|
import Trigger from '../../trigger'
|
|
import placements from './placements'
|
|
import { hasProp } from '../../_util/props-util'
|
|
import BaseMixin from '../../_util/BaseMixin'
|
|
import { cloneElement, getEvents, cloneVNode } from '../../_util/vnode'
|
|
|
|
export default {
|
|
mixins: [BaseMixin],
|
|
props: {
|
|
minOverlayWidthMatchTrigger: PropTypes.bool.def(true),
|
|
prefixCls: PropTypes.string.def('rc-dropdown'),
|
|
transitionName: PropTypes.string,
|
|
overlayClassName: PropTypes.string.def(''),
|
|
animation: PropTypes.any,
|
|
align: PropTypes.object,
|
|
overlayStyle: PropTypes.object.def({}),
|
|
placement: PropTypes.string.def('bottomLeft'),
|
|
trigger: PropTypes.array.def(['hover']),
|
|
showAction: PropTypes.array.def([]),
|
|
hideAction: PropTypes.array.def([]),
|
|
getPopupContainer: PropTypes.func,
|
|
visible: PropTypes.bool,
|
|
defaultVisible: PropTypes.bool.def(false),
|
|
mouseEnterDelay: PropTypes.number.def(0.15),
|
|
mouseLeaveDelay: PropTypes.number.def(0.1),
|
|
},
|
|
data () {
|
|
let sVisible = this.defaultVisible
|
|
if (hasProp(this, 'visible')) {
|
|
sVisible = this.visible
|
|
}
|
|
return {
|
|
sVisible,
|
|
}
|
|
},
|
|
watch: {
|
|
visible (val) {
|
|
if (val !== undefined) {
|
|
this.setState({
|
|
sVisible: val,
|
|
})
|
|
}
|
|
},
|
|
},
|
|
methods: {
|
|
onClick (e) {
|
|
// do no call onVisibleChange, if you need click to hide, use onClick and control visible
|
|
if (!hasProp(this, 'visible')) {
|
|
this.setState({
|
|
sVisible: false,
|
|
})
|
|
}
|
|
this.$emit('overlayClick', e)
|
|
if (this.childOriginEvents.click) {
|
|
this.childOriginEvents.click(e)
|
|
}
|
|
},
|
|
|
|
onVisibleChange (visible) {
|
|
if (!hasProp(this, 'visible')) {
|
|
this.setState({
|
|
sVisible: visible,
|
|
})
|
|
}
|
|
this.__emit('visibleChange', visible)
|
|
},
|
|
|
|
getMenuElement () {
|
|
const { onClick, prefixCls, $slots } = this
|
|
this.childOriginEvents = getEvents($slots.overlay[0])
|
|
return cloneElement(cloneVNode($slots.overlay[0]), {
|
|
props: {
|
|
prefixCls: `${prefixCls}-menu`,
|
|
},
|
|
on: {
|
|
click: onClick,
|
|
},
|
|
})
|
|
},
|
|
|
|
getPopupDomNode () {
|
|
return this.$refs.trigger.getPopupDomNode()
|
|
},
|
|
|
|
afterVisibleChange (visible) {
|
|
if (visible && this.$props.minOverlayWidthMatchTrigger) {
|
|
const overlayNode = this.getPopupDomNode()
|
|
const rootNode = this.$el
|
|
if (rootNode && overlayNode && rootNode.offsetWidth > overlayNode.offsetWidth) {
|
|
overlayNode.style.width = `${rootNode.offsetWidth}px`
|
|
if (this.$refs.trigger &&
|
|
this.$refs.trigger._component &&
|
|
this.$refs.trigger._component.alignInstance) {
|
|
this.$refs.trigger._component.alignInstance.forceAlign()
|
|
}
|
|
}
|
|
}
|
|
},
|
|
},
|
|
|
|
render () {
|
|
const {
|
|
prefixCls,
|
|
transitionName, animation,
|
|
align, placement, getPopupContainer,
|
|
showAction, hideAction,
|
|
overlayClassName, overlayStyle,
|
|
trigger, ...otherProps
|
|
} = this.$props
|
|
|
|
const triggerProps = {
|
|
props: {
|
|
...otherProps,
|
|
prefixCls,
|
|
popupClassName: overlayClassName,
|
|
popupStyle: overlayStyle,
|
|
builtinPlacements: placements,
|
|
action: trigger,
|
|
showAction,
|
|
hideAction,
|
|
popupPlacement: placement,
|
|
popupAlign: align,
|
|
popupTransitionName: transitionName,
|
|
popupAnimation: animation,
|
|
popupVisible: this.sVisible,
|
|
afterPopupVisibleChange: this.afterVisibleChange,
|
|
getPopupContainer: getPopupContainer,
|
|
},
|
|
on: {
|
|
popupVisibleChange: this.onVisibleChange,
|
|
},
|
|
ref: 'trigger',
|
|
}
|
|
const child = this.$slots.default && this.$slots.default[0]
|
|
return (
|
|
<Trigger {...triggerProps}>
|
|
{child && !child.tag
|
|
? <span>{child}</span>
|
|
: child}
|
|
<template slot='popup'>
|
|
{this.$slots.overlay && this.getMenuElement()}
|
|
</template>
|
|
</Trigger>
|
|
)
|
|
},
|
|
}
|
|
|
|
</script>
|