Repository URL to install this package:
|
Version:
1.3.2 ▾
|
import React from 'react'
import toClassName from 'classnames'
import { isFunction, isNil, isObj } from 'exotic'
import { func, node, string } from '@skava/modules/___dist/view-container/types'
import { isClickOutsideElement, isClickInsideElement } from './deps'
class ClickBoundary extends React.PureComponent {
dom: HTMLElement
// static isClickOutsideElement = isClickOutsideElement
static propTypes = {
// @todo @name onClickOutside
onClickOutside: func,
className: string,
children: node,
/**
* @todo @name @example
* maybe aria has a standard one too
* [provide] | [consume]
*
* parentRef | childrenRef
* | childRef
* | innerRef
*
* wrapRef | boxWrap
* giveRef | getRef
* provideRef |
*/
parentRef: func,
}
// only happens in browser, `willMount` in server
componentDidMount() {
if (IS_BROWSER) {
document.body.addEventListener('click', this.handleClick)
document.body.addEventListener('ontouchstart', this.handleClick)
}
}
// only happens browser
componentWillUnmount() {
if (IS_BROWSER) {
// remember to remove all events to avoid memory leaks
document.body.removeEventListener('click', this.handleClick)
document.body.removeEventListener('ontouchstart', this.handleClick)
}
}
setRef = dom => {
this.dom = dom
}
handleClick = event => {
// if (event.persist) event.persist()
// console.log('onClickBoundary', event)
// get click outside callback
const { onClickOutside } = this.props
// if there is no proper callback - no point of checking
if (isFunction(onClickOutside) === false) {
return
}
if (isClickOutsideElement(event, this.dom) === true) {
onClickOutside(event)
}
}
get className(): string {
return toClassName('click-boundary', this.props.className)
}
render() {
// why a diff dom?
// if (IS_BROWSER === false) {
// return React.Children.only(this.props.children)
// } else {
const children = isFunction(this.props.children)
? this.props.children(this)
: this.props.children
/**
* @todo - should use a ref to this.props.children to avoid pollouting the dom
* @todo - should maybe pass in `getParentRef` if it's inside...
*/
if (isFunction(this.props.parentRef) === true) {
this.setRef(this.props.parentRef)
return children
} else {
return (
<div ref={this.setRef} className={this.className}>
{this.props.children}
</div>
)
}
}
}
export default ClickBoundary
export { ClickBoundary }
export { isClickInsideElement }