All files / src/components/HorizontalSelect index.jsx

69.7% Statements 23/33
42.86% Branches 9/21
70% Functions 7/10
71.88% Lines 23/32
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 107 108 109 110 111 112 113 114 115                    1x         1x       3x 3x 3x             3x       3x 1x 1x         1x   3x 1x                     3x 3x     4x     4x 4x   4x                           3x                       3x 3x     3x           1x                              
import styles from './style.postcss';
 
import React, { PureComponent } from 'react';
import { Link } from 'react-router';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import is from 'is_js';
import HorizontalScroll from '../HorizontalScroll';
import ExpandableAnimationItem from '../ExpandableAnimationItem';
 
const wasLeftMouseButtonPressed = (e = window.event) => {
  const button = e.which || e.button;
  return button === 1;
};
 
const movementLimit = 20;
 
class HorizontalSelect extends PureComponent {
  constructor(props) {
    super();
    this.state = { value: props.value };
    this.scrollToElement = {
      selector: `.${styles.HorizontalSelect_option_active}`,
      duration: 300,
      easing: { style: 'ease-in-out' },
    };
 
    // this collection of goodies will prevent `onclick` firing after an x-axis drag
    this._onMouseDown = (e) => {
      if (! wasLeftMouseButtonPressed(e.nativeEvent)) return;
      this._startMouseX = e.screenX;
    };
    this._onClick = (option, e) => {
      const movement = Math.abs(this._startMouseX - e.screenX);
      Iif (this._startMouseX && movement > movementLimit) {
        // x-axis drag happened; block click
        e.preventDefault();
        return false;
      }
      this._onOptionSelect(option.value);
    };
    this._onOptionSelect = (value) => {
      this.props.onSelect && this.props.onSelect(value);
    };
  }
 
  componentWillReceiveProps(nextProps) {
    if (this.props.value !== nextProps.value) {
      this.setState({ value: nextProps.value });
    }
  }
 
  _renderOptions() {
    const { getLinkHrefForValue } = this.props;
    return <ul className={styles.HorizontalSelect_options}>
      {
        this.props.options.map((option) => {
          const optionClassName = classnames(styles.HorizontalSelect_option, {
            [styles.HorizontalSelect_option_active]: option.value === this.state.value,
          }, option.className);
          Eif (! option._onClick) {
            option._onClick = this._onClick.bind(null, option);  // eslint-disable-line
          }
          return <li key={option.value} className={optionClassName}>
            <Link to={getLinkHrefForValue && getLinkHrefForValue(option.value)}
                draggable={false}
                onMouseDown={this._onMouseDown}
                onClick={option._onClick}>
              {option.html}
            </Link>
          </li>;
        })
      }
    </ul>;
  }
 
  _renderHorizontalSelect() {
    return <ExpandableAnimationItem isExpand={! this.props.isHide} height={150}>
      <HorizontalScroll className={styles.HorizontalSelect}
          innerClassName={styles.HorizontalSelect_scroller}
          scrollToElement={this.scrollToElement}>
        <div className={styles.HorizontalSelect_options_wrap}>
          {this._renderOptions()}
        </div>
      </HorizontalScroll>
    </ExpandableAnimationItem>;
  }
 
  render() {
    const { options } = this.props;
    Iif (! is.existy(options) || options.length === 0) {
      return null;
    }
    return <div className={styles.HorizontalSelect_wrap}>
      {this._renderHorizontalSelect()}
    </div>;
  }
}
 
HorizontalSelect.propTypes = {
  options: PropTypes.arrayOf(
    PropTypes.shape({
      html: PropTypes.node,
      value: PropTypes.string,
      className: PropTypes.string,
    })).isRequired,
  value: PropTypes.string,
  getLinkHrefForValue: PropTypes.func.isRequired,
  onSelect: PropTypes.func,
  optionClassName: PropTypes.string,
  isHide: PropTypes.bool,
};
 
export default HorizontalSelect;