UNPKG

react-divx

Version:
140 lines (121 loc) 4.92 kB
/* eslint-disable react/destructuring-assignment */ import React from 'react'; import PropTypes from 'prop-types'; const fullAreaStyle = { height: '100%', width: '100%' }; class DivX extends React.Component { constructor(props) { super(props); this.state = {}; this.clientHeight = 0; this.clientWidth = 0; this.dynamics = {}; } componentDidMount = () => { if (this.props.onOuterClick || this.props.onDocumentClick) document.addEventListener('click', this.onDocumentClick); if (this.props.onEscPress || this.props.onDocumentKeydown) document.addEventListener('keydown', this.onDocumentKeydown); if (this.props.onResize) this.onResize(); // dynamics handlers attach Object.keys(this.getDynamicProps()).forEach((dynamicProp) => { const key = dynamicProp.toLowerCase(); if (dynamicProp.indexOf('onWindow') === 0 && key.replace('onwindow', '').length > 0) { window.addEventListener(key.replace('onwindow', ''), this.createDynamicHandler(dynamicProp)); } if (dynamicProp.indexOf('onDocument') === 0 && key.replace('ondocument', '').length > 0) { document.addEventListener(key.replace('ondocument', ''), this.createDynamicHandler(dynamicProp)); } }); }; componentDidUpdate = () => { if (this.props.onResize) this.onResize(); }; componentWillUnmount = () => { if (this.props.onOuterClick || this.props.onDocumentClick) document.removeEventListener('click', this.onDocumentClick); if (this.props.onEscPress || this.props.onDocumentKeydown) document.removeEventListener('keydown', this.onDocumentKeydown); // dynamics handlers remove Object.keys(this.dynamics).forEach((dynamicProp) => { const key = dynamicProp.toLowerCase(); if (dynamicProp.indexOf('onWindow') === 0 && key.replace('onwindow', '').length > 0) { window.removeEventListener(key.replace('onwindow', ''), this.dynamics[dynamicProp]); } if (dynamicProp.indexOf('onDocument') === 0 && key.replace('ondocument', '').length > 0) { document.removeEventListener(key.replace('ondocument', ''), this.dynamics[dynamicProp]); } }); }; onDocumentKeydown = (event) => { if (event.keyCode === 27) { if (typeof this.props.onEscPress === 'function') this.props.onEscPress(event); } if (typeof this.props.onDocumentKeydown === 'function') this.props.onDocumentKeydown(event); }; onResize = () => { if (this.container) { const { clientHeight, clientWidth } = this.container; if (clientWidth !== this.clientWidth || clientHeight !== this.clientHeight) { this.clientHeight = clientHeight; this.clientWidth = clientWidth; if (typeof this.props.onResize === 'function') this.props.onResize(clientWidth, clientHeight); } } }; onDocumentClick = (e) => { if (this.container && !this.container.contains(e.target)) { if (typeof this.props.onOuterClick === 'function') this.props.onOuterClick(e); } if (typeof this.props.onDocumentClick === 'function') this.props.onDocumentClick(e); }; getDynamicProps = () => { // eslint-disable-next-line const { innerRef, onOuterClick, onResize, onEscPress, onDocumentKeydown, onDocumentClick, ...rest } = this.props; return rest; }; getRealDivProps = () => { const rest = this.getDynamicProps(); Object.keys(rest).forEach((dynamicProp) => { const key = dynamicProp.toLowerCase(); if (key.indexOf('onwindow') === 0 || key.indexOf('ondocument') === 0) { delete rest[dynamicProp]; } }); return rest; }; setRef = (ref) => { this.container = ref; if (this.props.innerRef) { this.props.innerRef(ref); } }; createDynamicHandler = (dynamicProp) => { this.dynamics[dynamicProp] = (...args) => { if (this.props[dynamicProp]) this.props[dynamicProp](...args); }; return this.dynamics[dynamicProp]; }; render() { const { fullArea, children, onOuterClick, onResize } = this.props; const realDivProps = this.getRealDivProps(); const needRealDiv = onOuterClick || onResize || Object.keys(realDivProps).length > 0; return needRealDiv ? ( // eslint-disable-next-line react/jsx-props-no-spreading <div ref={this.setRef} {...realDivProps} style={fullArea ? fullAreaStyle : undefined}> {children} </div> ) : children; } } DivX.propTypes = { innerRef: PropTypes.func, onOuterClick: PropTypes.func, onEscPress: PropTypes.func, onResize: PropTypes.func, onDocumentKeydown: PropTypes.func, onDocumentClick: PropTypes.func, children: PropTypes.any.isRequired, fullArea: PropTypes.bool }; export default DivX;