You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
132 lines
3.4 KiB
132 lines
3.4 KiB
4 years ago
|
import PropTypes from 'prop-types';
|
||
|
import React, { Component } from 'react';
|
||
|
import { findDOMNode } from 'react-dom';
|
||
|
import ReactCSSTransitionGroup from 'react-transition-group/CSSTransitionGroup';
|
||
7 years ago
|
|
||
5 years ago
|
export default class MenuDroppoComponent extends Component {
|
||
|
static propTypes = {
|
||
|
isOpen: PropTypes.bool.isRequired,
|
||
|
innerStyle: PropTypes.object,
|
||
|
children: PropTypes.node.isRequired,
|
||
5 years ago
|
onClickOutside: PropTypes.func,
|
||
5 years ago
|
containerClassName: PropTypes.string,
|
||
|
zIndex: PropTypes.number,
|
||
|
style: PropTypes.object.isRequired,
|
||
|
useCssTransition: PropTypes.bool,
|
||
|
speed: PropTypes.string,
|
||
4 years ago
|
};
|
||
7 years ago
|
|
||
4 years ago
|
renderPrimary() {
|
||
4 years ago
|
const { isOpen } = this.props;
|
||
5 years ago
|
if (!isOpen) {
|
||
4 years ago
|
return null;
|
||
5 years ago
|
}
|
||
7 years ago
|
|
||
4 years ago
|
const innerStyle = this.props.innerStyle || {};
|
||
5 years ago
|
|
||
|
return (
|
||
|
<div className="menu-droppo" key="menu-droppo-drawer" style={innerStyle}>
|
||
|
{this.props.children}
|
||
|
</div>
|
||
4 years ago
|
);
|
||
5 years ago
|
}
|
||
|
|
||
|
globalClickOccurred = (event) => {
|
||
4 years ago
|
const { target } = event;
|
||
5 years ago
|
// eslint-disable-next-line react/no-find-dom-node
|
||
4 years ago
|
const container = findDOMNode(this);
|
||
5 years ago
|
|
||
4 years ago
|
if (
|
||
4 years ago
|
this.props.isOpen &&
|
||
4 years ago
|
target !== container &&
|
||
5 years ago
|
!isDescendant(this.container, event.target) &&
|
||
4 years ago
|
this.props.onClickOutside
|
||
4 years ago
|
) {
|
||
4 years ago
|
this.props.onClickOutside(event);
|
||
5 years ago
|
}
|
||
4 years ago
|
};
|
||
5 years ago
|
|
||
4 years ago
|
componentDidMount() {
|
||
5 years ago
|
if (this && document.body) {
|
||
4 years ago
|
document.body.addEventListener('click', this.globalClickOccurred);
|
||
5 years ago
|
// eslint-disable-next-line react/no-find-dom-node
|
||
4 years ago
|
const container = findDOMNode(this);
|
||
|
this.container = container;
|
||
5 years ago
|
}
|
||
|
}
|
||
|
|
||
4 years ago
|
componentWillUnmount() {
|
||
5 years ago
|
if (this && document.body) {
|
||
4 years ago
|
document.body.removeEventListener('click', this.globalClickOccurred);
|
||
5 years ago
|
}
|
||
|
}
|
||
7 years ago
|
|
||
4 years ago
|
render() {
|
||
4 years ago
|
const { containerClassName = '', style } = this.props;
|
||
|
const speed = this.props.speed || '300ms';
|
||
|
const { useCssTransition } = this.props;
|
||
|
const zIndex = 'zIndex' in this.props ? this.props.zIndex : 0;
|
||
7 years ago
|
|
||
4 years ago
|
const baseStyle = {
|
||
|
position: 'fixed',
|
||
|
...style,
|
||
|
zIndex,
|
||
4 years ago
|
};
|
||
7 years ago
|
|
||
5 years ago
|
return (
|
||
4 years ago
|
<div
|
||
|
style={baseStyle}
|
||
|
className={`menu-droppo-container ${containerClassName}`}
|
||
|
>
|
||
|
<style>
|
||
|
{`
|
||
5 years ago
|
.menu-droppo-enter {
|
||
|
transition: transform ${speed} ease-in-out;
|
||
|
transform: translateY(-200%);
|
||
|
}
|
||
|
|
||
|
.menu-droppo-enter.menu-droppo-enter-active {
|
||
|
transition: transform ${speed} ease-in-out;
|
||
|
transform: translateY(0%);
|
||
|
}
|
||
|
|
||
|
.menu-droppo-leave {
|
||
|
transition: transform ${speed} ease-in-out;
|
||
|
transform: translateY(0%);
|
||
|
}
|
||
|
|
||
|
.menu-droppo-leave.menu-droppo-leave-active {
|
||
|
transition: transform ${speed} ease-in-out;
|
||
|
transform: translateY(-200%);
|
||
|
}
|
||
|
`}
|
||
5 years ago
|
</style>
|
||
4 years ago
|
{useCssTransition ? (
|
||
|
<ReactCSSTransitionGroup
|
||
|
className="css-transition-group"
|
||
|
transitionName="menu-droppo"
|
||
|
transitionEnterTimeout={parseInt(speed, 10)}
|
||
|
transitionLeaveTimeout={parseInt(speed, 10)}
|
||
|
>
|
||
|
{this.renderPrimary()}
|
||
|
</ReactCSSTransitionGroup>
|
||
|
) : (
|
||
|
this.renderPrimary()
|
||
|
)}
|
||
5 years ago
|
</div>
|
||
4 years ago
|
);
|
||
7 years ago
|
}
|
||
|
}
|
||
|
|
||
4 years ago
|
function isDescendant(parent, child) {
|
||
4 years ago
|
let node = child.parentNode;
|
||
7 years ago
|
while (node !== null) {
|
||
|
if (node === parent) {
|
||
4 years ago
|
return true;
|
||
7 years ago
|
}
|
||
4 years ago
|
node = node.parentNode;
|
||
7 years ago
|
}
|
||
|
|
||
4 years ago
|
return false;
|
||
7 years ago
|
}
|