Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
Size: Mime:
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 }