All files / components/dropdown index.js

0% Statements 0/92
0% Branches 0/47
0% Functions 0/16
0% Lines 0/2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106                                                                                                                                                                                                                   
import React, { Component } from 'react'
import cx from 'classnames'
import PropTypes from 'prop-types'
import DropDownStyled from './dropdown.styled'
import DropdownIcon from './dropdown-icon'
 
class DropDown extends Component {
  constructor () {
    super()
    this.state = {
      visible: false,
      arrowPosition: 0
    }
  }
 
  open = (e) => {
    e.stopPropagation()
    if (this.state.visible) {
      this.close();
      return;
    }
 
    const { offsetX } = e.nativeEvent
    const { clientWidth } = e.nativeEvent.target
 
    this.focusElement.focus()
    this.setState({
      visible: true,
      arrowPosition: offsetX,
      referenceSize: clientWidth
    })
  }
 
  close = () => {
    this.setState({
      visible: false
    })
  }
 
  definePositionArrow = () => {
    const { arrowPosition, referenceSize } = this.state
    const minValue = 10
    const arrowSize = 14
 
    let position = 0
    if (arrowPosition < minValue) { position = minValue } else if ((arrowPosition + arrowSize) > referenceSize) {
      position = referenceSize - arrowSize
    } else { position = parseInt(referenceSize / 2) }
 
    return position
  }
 
  render () {
    const { visible, referenceSize } = this.state
    const { className, reference, direction = 'bottom-right', children } = this.props
    let element = <DropdownIcon onClick={this.open} />
 
    if (reference) {
      element = React.cloneElement(reference, { onClick: this.open })
    }
 
    const dropdownArrowClass = {
      'arrow-top': (direction.indexOf('top') > -1),
      'arrow-left': (direction.indexOf('left') > -1),
      'arrow-bottom': (direction.indexOf('bottom') > -1),
      'arrow-right': (direction.indexOf('right') > -1)
    }
 
    const dropdownItemsContainerClass = {
      'top': (direction.indexOf('top') > -1),
      'bottom': (direction.indexOf('bottom') > -1),
      'left': (direction.indexOf('left') > -1),
      'right': (direction.indexOf('right') > -1)
    }
 
    return (
      <DropDownStyled className={className} arrowPosition={this.definePositionArrow()} referenceSize={referenceSize}>
        <input className='input-focus' ref={(input) => { this.focusElement = input }} onBlur={() => { setTimeout(this.close, 200) }} />
        {direction.indexOf('bottom') > -1 && element}
        <div className={cx({ 'show': visible }, 'dropdown-container')}>
          <div className={cx(dropdownArrowClass, 'dropdown-arrow')} />
          <div className={cx(dropdownItemsContainerClass, 'dropdown-items-container')}>
            {children}
          </div>
        </div>
        {direction.indexOf('top') > -1 && element}
      </DropDownStyled>
    )
  }
}
 
DropDown.propTypes = {
  className: PropTypes.string,
  reference: PropTypes.node,
  children: PropTypes.node,
  direction: PropTypes.oneOf([
    'top-left',
    'top-right',
    'bottom-left',
    'bottom-right'
  ])
}
 
export { DropDownItem } from './dropdown-item'
export { DropDown }