Skip to content

Instantly share code, notes, and snippets.

@etyp
Last active November 17, 2018 20:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save etyp/0c75e73bfb2efe74eb4cd91c62c54d3a to your computer and use it in GitHub Desktop.
Save etyp/0c75e73bfb2efe74eb4cd91c62c54d3a to your computer and use it in GitHub Desktop.
React on escape outside with mousedown support
import EscapeOutside from "react-escape-outside"
class MyComponent extends Component {
constructor() {
super()
this.state = {
isOpen: false,
}
this.handleEscapeOutside = this.handleEscapeOutside.bind(this)
}
//… more of your own code, e.g to open your modal
handleEscapeOutside() {
this.setState({ isOpen: false })
}
render() {
return (
<EscapeOutside mouseEvent="mousedown" touchEvent="touchstart" onEscapeOutside={ this.handleEscapeOutside }>
<div>Some content that will be closed</div>
</EscapeOutside>
)
}
}
import React, { Component } from "react"
import PropTypes from "prop-types"
export default class EscapeOutside extends Component {
static propTypes = {
children: PropTypes.element.isRequired,
onEscapeOutside: PropTypes.func.isRequired,
mouseEvent: PropTypes.string,
touchEvent: PropTypes.string,
}
constructor() {
super()
this.onEscape = this.onEscape.bind(this)
this.onClick = this.onClick.bind(this)
this.getRef = this.getRef.bind(this)
}
componentDidMount() {
document.addEventListener("keydown", this.onEscape)
document.addEventListener(this.props.mouseEvent, this.onClick, true)
document.addEventListener(this.props.touchEvent, this.onClick, true)
}
componentWillUnmount() {
document.removeEventListener("keydown", this.onEscape)
document.removeEventListener(this.props.mouseEvent, this.onClick, true)
document.removeEventListener(this.props.touchEvent, this.onClick, true)
}
onEscape(e) {
if (e.keyCode === 27) this.props.onEscapeOutside()
}
onClick(e) {
if (!this.ref.contains(e.target)) this.props.onEscapeOutside(e)
}
getRef(ref) {
this.ref = ref
}
render() {
const props = Object.assign({}, this.props)
const { children } = props
delete props.onEscapeOutside
delete props.children
return (
<div
{ ...props }
ref={ this.getRef }
>
{ children }
</div>
)
}
}
EscapeOutside.defaultProps = {
mouseEvent: "click",
touchEvent: "touchend",
};
@etyp
Copy link
Author

etyp commented Nov 17, 2018

Based on https://github.com/amytych/react-escape-outside this allows users to specify the click and touch events for escape if they want to use mousedown instead of click or touchstart instead of touchend.

Passing a mouseEvent and/or touchEvent prop like so is how you use:

<EscapeOutside mouseEvent="mousedown" touchEvent="touchstart">

Not passing these props defaults to click and touchend.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment