UNPKG

bee-drawer

Version:
221 lines (210 loc) 5.25 kB
import React, { Component } from 'react'; import ReactDOM from 'react-dom'; import PropTypes from 'prop-types'; import classNames from 'classnames'; import {bindAll,isNumber} from './common'; import {CSSTransition, TransitionGroup} from 'react-transition-group'; import Icon from 'bee-icon'; const propTypes = { placement: PropTypes.oneOf(['left','right','top','bottom']), hasHeader: PropTypes.bool, show: PropTypes.bool, title: PropTypes.string, className: PropTypes.string, showMask: PropTypes.bool, maskClosable: PropTypes.bool, zIndex: PropTypes.number, showClose: PropTypes.bool, width: PropTypes.oneOfType([PropTypes.string,PropTypes.number]), height: PropTypes.oneOfType([PropTypes.string,PropTypes.number]), destroyOnClose: PropTypes.bool, container: PropTypes.string, closeIcon: PropTypes.node } const defaultProps = { placement: 'left', hasHeader: true, show: false, showMask: true, maskClosable: true, zIndex: 100000, showClose: false, width: 'auto', height: 'auto', destroyOnClose: false, container: 'body', closeIcon: null } const DrawerContext = React.createContext&&React.createContext(null); class Drawer extends Component{ constructor(props){ super(props); this.state = { showDrawer: true, width: '0', push: false }; this.drawer = null; this.parentDrawer = null; bindAll(this,['fMaskClick','fDrawerTransitionEnd','renderMask','renderClose','fCloseClick','renderBody','renderAll']); } componentDidUpdate(preProps){ //在有父级抽屉时候,子级触发父级向外移动一段距离 if(preProps.show != this.props.show && this.parentDrawer){ if(this.props.show){ this.parentDrawer.push(); } else{ this.parentDrawer.pull(); } } } push(){ this.setState({ push: true }) } pull(){ this.setState({ push: false }) } fMaskClick(){ const {maskClosable} = this.props; if(maskClosable){ const {onClose} = this.props; onClose && onClose(); } } fCloseClick(){ const {onClose} = this.props; onClose && onClose(); } fDrawerTransitionEnd(e){ } renderMask(){ const {show,showMask,fMaskClick} = this.props; //mask样式 let maskStyle; if(show){ maskStyle = { opacity: 1, width: '100%' } } else{ maskStyle = { opacity: 0, width: 0 } } return ( showMask ? <div className="drawer-mask" style={maskStyle} onClick={this.fMaskClick}></div> : null ) } renderClose(){ const {showClose,closeIcon} = this.props; let closeDom = closeIcon || <Icon type="uf-close"/>; return ( showClose ? <span className="drawer-close" onClick={this.fCloseClick}>{closeDom}</span> : null ) } renderBody(){ const {destroyOnClose,show} = this.props; if(destroyOnClose && !show){ return null; } let {hasHeader,title,children,width,height,placement} = this.props; let {push} = this.state; //抽屉类 const drawerClass = classNames('drawer',`drawer-${placement}`); //根据位置获取抽屉样式 const translateHideMap = { left: 'translateX(-100%)', right: 'translateX(100%)', top: 'translateY(-100%)', bottom: 'translateY(100%)' }; let translateShow = 'translate(0,0)'; if(push){ const pushNum = 50; const translateShowMap = { left: `translate(${pushNum}px,0)`, right: `translate(-${pushNum}px,0)`, top: `translate(0,${pushNum}px)`, bottom: `translate(0,-${pushNum}px)` } translateShow = translateShowMap[placement]; } const translate = show ? translateShow : translateHideMap[placement]; //抽屉面板样式 if(isNumber(width)){ width = width + 'px'; } if(isNumber(height)){ height = height + 'px'; } if(placement == 'top' || placement == 'bottom'){ if(width == 'auto'){ width = '100%'; } } if(placement == 'left' || placement == 'right'){ if(height == 'auto'){ height = '100%'; } } const drawerStyle = { transform: translate, WebkitTransform: translate, width: width, height: height } const closer = this.renderClose(); const header = ( hasHeader ? (<div className="drawer-header"><div className="drawer-header-title">{title}</div></div>) : '' ) return ( <DrawerContext.Provider value={this}> <div ref={(drawer) => {this.drawer = drawer}} onTransitionEnd={this.fDrawerTransitionEnd} className={drawerClass} style={drawerStyle}> {closer} {header} <div className="drawer-body"> {children} </div> </div> </DrawerContext.Provider> ) } renderAll(value){ let {show,className,zIndex} = this.props; //容器类 const drawercClass = classNames('drawerc',className); //容器样式 let drawercStyle = {zIndex:zIndex} if(show){ drawercStyle.width = '100%'; } else{ drawercStyle.width = 0; } //获取父级抽屉 this.parentDrawer = value; return ( <div className={drawercClass} style={drawercStyle}> {this.renderMask()} {this.renderBody()} </div> ) } render(){ const {container} = this.props; const conDom = document.querySelector(container); return ( ReactDOM.createPortal(<DrawerContext.Consumer>{this.renderAll}</DrawerContext.Consumer>,conDom) ) } } Drawer.propTypes = propTypes; Drawer.defaultProps = defaultProps; export default Drawer;