nifty-wallet/old-ui/app/components/menu-droppo.js

151 lines
4.0 KiB
JavaScript
Raw Normal View History

2019-06-18 10:57:36 -07:00
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import h from 'react-hyperscript'
import { findDOMNode } from 'react-dom'
import { CSSTransitionGroup } from 'react-transition-group'
2017-11-14 08:04:23 -08:00
2019-06-18 10:57:36 -07:00
export default class MenuDroppo extends Component {
2017-11-14 08:04:23 -08:00
2019-06-18 10:57:36 -07:00
constructor (props) {
super(props)
this.menuDroppoContainer = React.createRef()
}
2017-11-14 08:04:23 -08:00
2019-06-18 10:57:36 -07:00
static propTypes = {
speed: PropTypes.string,
useCssTransition: PropTypes.bool,
zIndex: PropTypes.number,
isOpen: PropTypes.bool,
innerStyle: PropTypes.object,
children: PropTypes.array,
onClickOutside: PropTypes.func,
style: PropTypes.object,
constOverflow: PropTypes.bool,
}
2017-11-14 08:04:23 -08:00
2019-06-18 10:57:36 -07:00
render () {
const speed = this.props.speed || '300ms'
const useCssTransition = this.props.useCssTransition
const zIndex = ('zIndex' in this.props) ? this.props.zIndex : 0
2017-11-14 08:04:23 -08:00
2019-06-18 10:57:36 -07:00
this.manageListeners()
2017-11-14 08:04:23 -08:00
2019-06-18 10:57:36 -07:00
const style = this.props.style || {}
if (!('position' in style)) {
style.position = 'fixed'
}
style.zIndex = zIndex
style.overflow = 'hidden'
return (
h('.menu-droppo-container', {
ref: this.menuDroppoContainer,
style,
}, [
// this.renderPrimary(),
useCssTransition
? h(CSSTransitionGroup, {
className: 'css-transition-group',
transitionName: 'menu-droppo',
transitionEnterTimeout: parseInt(speed),
transitionLeaveTimeout: parseInt(speed),
}, this.renderPrimary())
: this.renderPrimary(),
])
)
2018-08-29 05:54:01 -07:00
}
2017-11-14 08:04:23 -08:00
2019-06-18 10:57:36 -07:00
renderPrimary () {
const isOpen = this.props.isOpen
if (!isOpen) {
return null
}
2017-11-14 08:04:23 -08:00
2019-06-18 10:57:36 -07:00
const innerStyle = this.props.innerStyle || {}
2017-11-14 08:04:23 -08:00
2019-06-18 10:57:36 -07:00
return (
h('.menu-droppo', {
key: 'menu-droppo-drawer',
style: innerStyle,
},
[ this.props.children ])
)
}
2017-11-14 08:04:23 -08:00
2019-06-18 10:57:36 -07:00
manageListeners () {
const isOpen = this.props.isOpen
const onClickOutside = this.props.onClickOutside
2017-11-14 08:04:23 -08:00
2019-06-18 10:57:36 -07:00
if (isOpen) {
this.outsideClickHandler = onClickOutside
} else if (isOpen) {
this.outsideClickHandler = null
}
2017-11-14 08:04:23 -08:00
}
2019-06-18 10:57:36 -07:00
componentDidMount () {
if (this && document.body) {
this.globalClickHandler = this.globalClickOccurred.bind(this)
document.body.addEventListener('click', this.globalClickHandler)
// eslint-disable-next-line react/no-find-dom-node
2020-04-14 02:18:53 -07:00
const container = findDOMNode(this)
2019-06-18 10:57:36 -07:00
this.container = container
}
2018-09-10 02:14:04 -07:00
2019-06-18 10:57:36 -07:00
this.transitionStarted = this.transitionstartOccured.bind(this)
2018-10-26 10:30:51 -07:00
2019-06-18 10:57:36 -07:00
/*
* transitionstart event is not supported in Chrome yet. But it works for Firefox 53+.
* We need to handle this event only for FF because for Chrome we've hidden scrolls.
*/
this.menuDroppoContainer.current.addEventListener('transitionstart', this.transitionStarted)
2018-09-10 02:14:04 -07:00
2019-06-18 10:57:36 -07:00
this.transitionEnded = this.transitionendOccured.bind(this)
2018-10-26 10:30:51 -07:00
2019-06-18 10:57:36 -07:00
this.menuDroppoContainer.current.addEventListener('transitionend', this.transitionEnded)
}
2017-11-14 08:04:23 -08:00
2019-06-18 10:57:36 -07:00
componentWillUnmount () {
if (this && document.body) {
document.body.removeEventListener('click', this.globalClickHandler)
document.body.removeEventListener('transitionstart', this.transitionStarted)
document.body.removeEventListener('transitionend', this.transitionEnded)
}
2017-11-14 08:04:23 -08:00
}
2019-06-18 10:57:36 -07:00
globalClickOccurred (event) {
const target = event.target
// eslint-disable-next-line react/no-find-dom-node
const container = findDOMNode(this)
2017-11-14 08:04:23 -08:00
2019-06-18 10:57:36 -07:00
if (target !== container &&
!this.isDescendant(this.container, event.target) &&
this.outsideClickHandler) {
this.outsideClickHandler(event)
}
2017-11-14 08:04:23 -08:00
}
2019-06-18 10:57:36 -07:00
transitionstartOccured (event) {
this.menuDroppoContainer.current.style.overflow = 'hidden'
}
2018-10-26 10:30:51 -07:00
2019-06-18 10:57:36 -07:00
transitionendOccured (event) {
if (!this.props.constOverflow) {
this.menuDroppoContainer.current.style.overflow = 'auto'
}
2018-10-26 10:30:51 -07:00
}
2019-06-18 10:57:36 -07:00
isDescendant (parent, child) {
2020-04-14 02:18:53 -07:00
let node = child.parentNode
2019-06-18 10:57:36 -07:00
while (node !== null) {
if (node === parent) {
return true
}
node = node.parentNode
2017-11-14 08:04:23 -08:00
}
2019-06-18 10:57:36 -07:00
return false
2017-11-14 08:04:23 -08:00
}
}