import warning from 'warning' import classnames from 'classnames' import VcDrawer from '../vc-drawer/src' import PropTypes from '../_util/vue-types' import BaseMixin from '../_util/BaseMixin' import Icon from '../icon' import { getComponentFromProp, getOptionProps } from '../_util/props-util' const Drawer = { name: 'ADrawer', props: { closable: PropTypes.bool.def(true), destroyOnClose: PropTypes.bool, getContainer: PropTypes.any, maskClosable: PropTypes.bool.def(true), mask: PropTypes.bool.def(true), maskStyle: PropTypes.object, title: PropTypes.any, visible: PropTypes.bool, width: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).def(256), height: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).def(256), zIndex: PropTypes.number, prefixCls: PropTypes.string.def('ant-drawer'), placement: PropTypes.oneOf(['top', 'right', 'bottom', 'left']).def('right'), level: PropTypes.any.def(null), wrapClassName: PropTypes.string, // not use class like react, vue will add class to root dom }, mixins: [BaseMixin], data () { this.destoryClose = false this.preVisible = this.$props.visible return { _push: false, } }, inject: { parentDrawer: { default: null, }, }, provide () { return { parentDrawer: this, } }, updated () { this.$nextTick(() => { if (this.preVisible !== this.visible && this.parentDrawer) { if (this.visible) { this.parentDrawer.push() } else { this.parentDrawer.pull() } } this.preVisible = this.visible }) }, methods: { close (e) { if (this.visible !== undefined) { this.$emit('close', e) return } }, onMaskClick (e) { if (!this.maskClosable) { return } this.close(e) }, push () { this.setState({ _push: true, }) }, pull () { this.setState({ _push: false, }) }, onDestoryTransitionEnd () { const isDestroyOnClose = this.getDestoryOnClose() if (!isDestroyOnClose) { return } if (!this.visible) { this.destoryClose = true this.$forceUpdate() } }, getDestoryOnClose () { return this.destroyOnClose && !this.visible }, // get drawar push width or height getPushTransform (placement) { if (placement === 'left' || placement === 'right') { return `translateX(${placement === 'left' ? 180 : -180}px)` } if (placement === 'top' || placement === 'bottom') { return `translateY(${placement === 'top' ? 180 : -180}px)` } }, // render drawer body dom renderBody () { if (this.destoryClose && !this.visible) { return null } this.destoryClose = false const { placement, bodyStyle } = this.$props const containerStyle = placement === 'left' || placement === 'right' ? { overflow: 'auto', height: '100%', } : {} const isDestroyOnClose = this.getDestoryOnClose() if (isDestroyOnClose) { // Increase the opacity transition, delete children after closing. containerStyle.opacity = 0 containerStyle.transition = 'opacity .3s' } const { prefixCls, closable } = this.$props const title = getComponentFromProp(this, 'title') // is have header dom let header if (title) { header = (
{title}
) } // is have closer button let closer if (closable) { closer = ( ) } return (
{header} {closer}
{this.$slots.default}
) }, getRcDrawerStyle () { const { zIndex, placement, maskStyle } = this.$props return this.$data._push ? { ...maskStyle, zIndex, transform: this.getPushTransform(placement), } : { ...maskStyle, zIndex, } }, }, render () { const props = getOptionProps(this) const { width, height, visible, placement, wrapClassName, ...rest } = props const haveMask = rest.mask ? '' : 'no-mask' const offsetStyle = {} if (placement === 'left' || placement === 'right') { offsetStyle.width = typeof width === 'number' ? `${width}px` : width } else { offsetStyle.height = typeof height === 'number' ? `${height}px` : height } const vcDrawerProps = { props: { handler: false, ...rest, ...offsetStyle, open: visible, showMask: props.mask, placement, className: classnames({ [wrapClassName]: !!wrapClassName, [haveMask]: !!haveMask, }), }, on: { maskClick: this.onMaskClick, ...this.$listeners, }, style: this.getRcDrawerStyle(), } return ( {this.renderBody()} ) }, } /* istanbul ignore next */ Drawer.install = function (Vue) { Vue.component(Drawer.name, Drawer) } export default Drawer