Skip to content

Instantly share code, notes, and snippets.

@chrisabrams
Created January 31, 2019 19:28
Show Gist options
  • Save chrisabrams/7945c4500f043c04b1e3a60c0d815fb2 to your computer and use it in GitHub Desktop.
Save chrisabrams/7945c4500f043c04b1e3a60c0d815fb2 to your computer and use it in GitHub Desktop.
import React from 'react'
import { addEventListener } from 'consolidated-events'
interface Props {
onOutsideClick: any
}
export default class OutsideClickHandler extends React.Component<Props> {
childNode: any
removeMouseDown: any
removeMouseUp: any
constructor(props) {
super(props)
}
componentWillMount() {
this.addMouseDownEventListener()
}
componentWillUnmount() {
this.removeEventListeners()
}
// Use mousedown/mouseup to enforce that clicks remain outside the root's
// descendant tree, even when dragged. This should also get triggered on
// touch devices.
onMouseDown = (e) => {
const isDescendantOfRoot = this.childNode && this.childNode.contains(e.target)
if (!isDescendantOfRoot) {
this.removeMouseUp = addEventListener(
document,
'mouseup',
this.onMouseUp
);
}
}
// Use mousedown/mouseup to enforce that clicks remain outside the root's
// descendant tree, even when dragged. This should also get triggered on
// touch devices.
onMouseUp = (e) => {
const { onOutsideClick } = this.props
const isDescendantOfRoot = this.childNode && this.childNode.contains(e.target)
if (this.removeMouseUp) this.removeMouseUp()
this.removeMouseUp = null
if (!isDescendantOfRoot) {
onOutsideClick(e)
}
}
setChildNodeRef = (ref) => {
this.childNode = ref
}
addMouseDownEventListener() {
this.removeMouseDown = addEventListener(
document,
'mousedown',
this.onMouseDown
)
}
removeEventListeners() {
if (this.removeMouseDown) this.removeMouseDown()
if (this.removeMouseUp) this.removeMouseUp()
}
render() {
const { children } = this.props
return (
<div ref={this.setChildNodeRef}>
{children}
</div>
)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment