UNPKG

element-react-codish

Version:
146 lines (125 loc) 4.11 kB
/* @flow */ import React from 'react'; import { Component, View, PropTypes } from '../../libs'; type State = { bodyOverflow: string, } export default class Dialog extends Component { state: State; static defaultProps = { visible: false, title: '', size: 'small', top: '15%', modal: true, lockScroll: true, closeOnClickModal: true, closeOnPressEscape: true } constructor(props: Object) { super(props); this.state = { bodyOverflow: '' } } componentWillReceiveProps(nextProps: Object): void { if (this.willOpen(this.props, nextProps)){ if (this.props.lockScroll && document.body && document.body.style) { if (!this.state.bodyOverflow) { this.setState({ bodyOverflow: document.body.style.overflow }); } document.body.style.overflow = 'hidden'; } } if (this.willClose(this.props, nextProps) && this.props.lockScroll) { if (this.props.modal && this.state.bodyOverflow !== 'hidden' && document.body && document.body.style) { document.body.style.overflow = this.state.bodyOverflow; } } } componentDidUpdate(prevProps: Object): void { if (this.willOpen(prevProps, this.props)){ this.refs.wrap.focus(); } } componentWillUnmount(): void { if (document.body && document.body.style) document.body.style.removeProperty('overflow'); } onKeyDown(e: SyntheticKeyboardEvent): void { if (this.props.closeOnPressEscape && e.keyCode === 27) { this.close(e); } } handleWrapperClick(e: SyntheticEvent): void { if (e.target instanceof HTMLDivElement) { if (this.props.closeOnClickModal && e.target === e.currentTarget) { this.close(e); } } } close(e: SyntheticEvent | SyntheticKeyboardEvent): void { this.props.onCancel(e); } willOpen(prevProps: Object, nextProps: Object): boolean { return (!prevProps.visible && nextProps.visible); } willClose(prevProps: Object, nextProps: Object): boolean { return (prevProps.visible && !nextProps.visible); } render(): React.Element<any> { const { visible, title, size, top, modal, customClass } = this.props; return ( <View show={ visible }> <div style={{ zIndex: 1013 }} className={this.classNames('el-dialog__wrapper')} onClick={ e => this.handleWrapperClick(e) } ref="wrap" tabIndex={ -1 } onKeyDown={ e => this.onKeyDown(e) } > <div ref="dialog" style={this.style(size === 'full' ? {} : { 'marginBottom': '50px', 'top': top })} className={ this.className("el-dialog", `el-dialog--${ size }`, customClass) } > <div className="el-dialog__header"> <span className="el-dialog__title">{ title }</span> <div className="el-dialog__headerbtn"> <i className="el-dialog__close el-icon el-icon-close" onClick={ e => this.close(e) }></i> </div> </div> { this.props.children } </div> </div> <View show={ modal } transition="v-modal" transitionKey="dialog-v-modal"> <div className="v-modal" style={{ zIndex: 1012 }}></div> </View> </View> ); } } Dialog.propTypes = { // 控制对话框是否可见 visible: PropTypes.bool.isRequired, // 标题 title: PropTypes.string, // 大小 (tiny/small/large/full) size: PropTypes.string, // top 值(仅在 size 不为 full 时有效) top: PropTypes.string, // 控制遮罩层展示 modal: PropTypes.bool, // Dialog 的自定义类名 customClass: PropTypes.string, // 是否在 Dialog 出现时将 body 滚动锁定 lockScroll: PropTypes.bool, // 是否可以通过点击 modal 关闭 Dialog closeOnClickModal: PropTypes.bool, // 是否可以通过按下 ESC 关闭 Dialog closeOnPressEscape: PropTypes.bool, // 点击遮罩层或右上角叉或取消按钮的回调 onCancel: PropTypes.func.isRequired };