Repository URL to install this package:
Version:
0.14.1 ▾
|
import React from 'react'
import toClassName from 'classnames'
import { isFunction } from 'exotic'
import { toCommonState } from 'src/state/common'
import { ClickBoundaryProps, ClickBoundaryRef } from './typings'
import { onClick, IS_BROWSER, toChildren } from './_deps'
class ClickBoundary extends React.Component<ClickBoundaryProps> {
// @todo does not need to be state
// we don't need to do any updates, should be pure
state = toCommonState(this.props)
isListening: boolean = false
dom: ClickBoundaryRef
/**
* only happens in browser, `willMount` in server
*/
subscribeListener() {
if (this.state.isActive && !this.isListening) {
// console.debug('[click boundary] subscribing')
// @note - document.body
window.addEventListener('click', this.handleClick)
window.addEventListener('ontouchstart', this.handleClick)
this.isListening = true
}
}
/**
* only happens browser
*/
unSubscribeListener() {
if (this.isListening) {
// console.debug('[click boundary] unsubscribing')
// remember to remove all events to avoid memory leaks
window.removeEventListener('click', this.handleClick)
window.removeEventListener('ontouchstart', this.handleClick)
this.isListening = false
}
}
setRef = dom => {
this.dom = dom
if (isFunction(this.props.innerRef) === true) {
this.props.innerRef(dom)
}
}
handleMouseEnter = event => {
this.state.focus()
// console.log(
// 'handleMouseEnter event:',
// 'isActive:',
// this.state.isActive,
// 'isFocused:',
// this.state.isFocused
// )
}
handleMouseLeave = event => {
this.state.blur()
this.state.setActive(true)
// console.debug(
// '[ClickBoundary] handleMouseLeave',
// 'isActive',
// this.state.isActive,
// 'isFocused:',
// this.state.isFocused
// )
this.subscribeListener()
}
handleClick = event => {
// console.debug('[ClickBoundary] handleClick ' + this.props.className)
onClick(event, this.props, this.dom)
this.state.setActive(false)
this.unSubscribeListener()
}
// @todo remove
get className(): string {
return toClassName('click-boundary', this.props.className)
}
get attributes() {
// omit(this.props, ['className', 'children', 'onClickOutside'])
const {
className,
children,
onClickOutside,
...remainingProps
} = this.props
return {
...remainingProps,
className: this.className,
}
}
render() {
const props = { ...this.props, setRef: this.setRef }
const children = toChildren(props, this.dom)
if (isFunction(props.parentRef) === true) {
this.setRef(props.parentRef)
return children
} else {
return (
<div
{...this.attributes}
ref={this.setRef}
className={this.className}
onMouseEnter={this.handleMouseEnter}
onMouseLeave={this.handleMouseLeave}
>
{this.props.children}
</div>
)
}
}
}
export default ClickBoundary
export { ClickBoundary }