function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }

function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }

function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }

function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }

function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }

function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }

function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import Icon from '../icon';
import { func, KEYCODE, obj } from '../util';
import zhCN from '../locale/zh-cn';
var noop = func.noop,
    bindCtx = func.bindCtx;
var ENTER = KEYCODE.ENTER,
    LEFT = KEYCODE.LEFT,
    UP = KEYCODE.UP,
    RIGHT = KEYCODE.RIGHT,
    DOWN = KEYCODE.DOWN;
var supportKeys = [ENTER, LEFT, UP, RIGHT, DOWN]; // 评分组件的大小与icon的大小映射关系

var ICON_SIZE_MAP = {
  small: 'xs',
  medium: 'small',
  large: 'medium'
};
/** Rating */

var Rating =
/*#__PURE__*/
function (_Component) {
  _inherits(Rating, _Component);

  _createClass(Rating, null, [{
    key: "currentValue",
    value: function currentValue(min, max, hoverValue, stateValue) {
      var value = hoverValue || stateValue;
      value = value >= max ? max : value;
      value = value <= min ? min : value;
      return value || 0;
    }
  }]);

  function Rating(props) {
    var _this;

    _classCallCheck(this, Rating);

    _this = _possibleConstructorReturn(this, _getPrototypeOf(Rating).call(this, props));
    _this.state = {
      value: 'value' in props ? props.value : props.defaultValue,
      hoverValue: 0,
      iconSpace: 0,
      iconSize: 0,
      clicked: false // 标记组件是否被点击过

    };
    _this.timer = null;
    bindCtx(_assertThisInitialized(_this), ['handleClick', 'handleHover', 'handleLeave', 'onKeyDown']);
    return _this;
  }

  _createClass(Rating, [{
    key: "componentDidMount",
    value: function componentDidMount() {
      this.getRenderResult();
    }
  }, {
    key: "UNSAFE_componentWillReceiveProps",
    value: function UNSAFE_componentWillReceiveProps(nextProps) {
      if ('value' in nextProps) {
        this.setState({
          value: nextProps.value || 0
        });
      }
    }
  }, {
    key: "componentWillUnmount",
    value: function componentWillUnmount() {
      this.clearTimer();
    } // 清除延时

  }, {
    key: "clearTimer",
    value: function clearTimer() {
      if (this.timer) {
        clearTimeout(this.timer);
        this.timer = null;
      }
    }
  }, {
    key: "getRenderResult",
    value: function getRenderResult() {
      var count = this.props.count;
      var _this$state = this.state,
          iconSpace = _this$state.iconSpace,
          iconSize = _this$state.iconSize;
      var icon = this.refs['rating-icon-0'];

      if (icon && this.underlayNode) {
        var newIconSize = icon.offsetWidth;
        var newIconSpace = (this.underlayNode.offsetWidth - count * newIconSize) / (count + 1);

        if (newIconSize !== iconSize || newIconSpace !== iconSpace) {
          this.setState({
            iconSpace: newIconSpace,
            iconSize: newIconSize
          });
        }
      }
    }
  }, {
    key: "getValue",
    value: function getValue(e) {
      // 如定位不准，优先纠正定位
      this.getRenderResult();
      var _this$props = this.props,
          allowHalf = _this$props.allowHalf,
          count = _this$props.count,
          rtl = _this$props.rtl;
      var _this$state2 = this.state,
          iconSpace = _this$state2.iconSpace,
          iconSize = _this$state2.iconSize;
      var pos = e.pageX - this.underlayNode.getBoundingClientRect().left;
      var fullNum = Math.floor(pos / (iconSpace + iconSize));
      var surplusNum = (pos - fullNum * (iconSpace + iconSize)) / iconSize;
      var value = Number(fullNum) + Number(surplusNum.toFixed(1));

      if (value >= count) {
        value = count;
      } else if (allowHalf) {
        var floorValue = Math.floor(value);
        value = value - 0.5 >= floorValue ? floorValue + 1 : floorValue + 0.5;
      } else {
        value = Math.floor(value) + 1;
      }

      return rtl ? count - value + 1 : value;
    }
  }, {
    key: "handleHover",
    value: function handleHover(e) {
      var _this2 = this;

      var value = this.getValue(e);
      var onHoverChange = this.props.onHoverChange;

      if (value !== this.state.hoverValue) {
        this.clearTimer();
        this.timer = setTimeout(function () {
          _this2.setState({
            hoverValue: value
          }, function () {
            onHoverChange(value);
          });
        }, 0);
      }
    }
  }, {
    key: "handleLeave",
    value: function handleLeave() {
      this.clearTimer();
      this.setState({
        hoverValue: 0
      });
    }
  }, {
    key: "onKeyDown",
    value: function onKeyDown(e) {
      var _this$props2 = this.props,
          disabled = _this$props2.disabled,
          onKeyDown = _this$props2.onKeyDown,
          count = _this$props2.count;

      if (disabled || supportKeys.indexOf(e.keyCode) < 0) {
        return !onKeyDown || onKeyDown(e);
      }

      var _this$state3 = this.state,
          hoverValue = _this$state3.hoverValue,
          value = _this$state3.value;
      var changingValue = hoverValue;

      if (changingValue === 0) {
        changingValue = value;
      }

      switch (e.keyCode) {
        case DOWN:
        case RIGHT:
          if (changingValue < count) {
            changingValue += 1;
          } else {
            changingValue = 1;
          }

          this.handleChecked(changingValue);
          break;

        case UP:
        case LEFT:
          if (changingValue > 1) {
            changingValue -= 1;
          } else {
            changingValue = count;
          }

          this.handleChecked(changingValue);
          break;

        case ENTER:
          this.props.onChange(changingValue);
          this.setState({
            value: changingValue,
            hoverValue: changingValue
          });
          break;
      }

      return !onKeyDown || onKeyDown(e);
    }
  }, {
    key: "handleChecked",
    value: function handleChecked(index) {
      this.setState({
        hoverValue: index
      });
    }
  }, {
    key: "handleClick",
    value: function handleClick(e) {
      var _this3 = this;

      var value = this.getValue(e);

      if (value < 0) {
        return;
      }

      if (!('value' in this.props)) {
        this.setState({
          value: value,
          clicked: true
        });
      }

      this.props.onChange(value);
      setTimeout(function () {
        _this3.setState({
          clicked: false
        });
      }, 100);
    }
  }, {
    key: "getOverlayWidth",
    value: function getOverlayWidth() {
      var _this$state4 = this.state,
          hoverValue = _this$state4.hoverValue,
          iconSpace = _this$state4.iconSpace,
          iconSize = _this$state4.iconSize;

      if (!iconSpace || !iconSize) {
        return 'auto';
      }

      var value = Rating.currentValue(0, this.props.count, hoverValue, this.state.value);
      var floorValue = Math.floor(value);
      return iconSize * value + (floorValue + 1) * iconSpace;
    }
  }, {
    key: "getInfoLeft",
    value: function getInfoLeft() {
      var _this$state5 = this.state,
          value = _this$state5.value,
          hoverValue = _this$state5.hoverValue,
          iconSpace = _this$state5.iconSpace,
          iconSize = _this$state5.iconSize;
      var infoValue = hoverValue || value;
      var ceilValue = Math.ceil(infoValue);
      return iconSize * (ceilValue - 1) + ceilValue * iconSpace;
    }
  }, {
    key: "render",
    value: function render() {
      var _classNames,
          _this4 = this;

      var _this$props3 = this.props,
          id = _this$props3.id,
          prefix = _this$props3.prefix,
          className = _this$props3.className,
          showGrade = _this$props3.showGrade,
          count = _this$props3.count,
          size = _this$props3.size,
          iconType = _this$props3.iconType,
          strokeMode = _this$props3.strokeMode,
          disabled = _this$props3.disabled,
          readAs = _this$props3.readAs,
          rtl = _this$props3.rtl,
          locale = _this$props3.locale;
      var others = obj.pickOthers(Rating.propTypes, this.props);
      var _this$state6 = this.state,
          hoverValue = _this$state6.hoverValue,
          clicked = _this$state6.clicked;
      var underlay = [];
      var overlay = [];
      var enableA11y = !!id; // 获得Value

      var value = Rating.currentValue(0, count, hoverValue, this.state.value); // icon的sizeMap

      var sizeMap = ICON_SIZE_MAP[size];

      for (var i = 0; i < count; i++) {
        var isCurrent = Math.ceil(value - 1) === i;
        var iconCls = classNames({
          hover: hoverValue > 0 && isCurrent,
          clicked: clicked && isCurrent
        });
        var iconNode = React.createElement(Icon, {
          type: iconType,
          size: sizeMap,
          className: iconCls
        });
        underlay.push(React.createElement("span", {
          ref: "rating-icon-".concat(i),
          key: "underlay-".concat(i),
          className: "".concat(prefix, "rating-icon")
        }, iconNode));

        if (enableA11y) {
          overlay.push(React.createElement("input", {
            id: "".concat(id, "-").concat(prefix, "star").concat(i + 1),
            key: "input-".concat(i),
            className: "".concat(prefix, "sr-only"),
            "aria-checked": i + 1 === parseInt(hoverValue),
            checked: i + 1 === parseInt(hoverValue),
            onChange: this.handleChecked.bind(this, i + 1),
            type: "radio",
            name: "rating"
          }));
        }

        overlay.push(React.createElement("label", {
          key: "overlay-".concat(i),
          htmlFor: enableA11y ? "".concat(id, "-").concat(prefix, "star").concat(i + 1) : null,
          className: "".concat(prefix, "rating-icon")
        }, iconNode, enableA11y ? React.createElement("span", {
          className: "".concat(prefix, "sr-only")
        }, readAs(i + 1)) : null));
      }

      var ratingCls = classNames(["".concat(prefix, "rating"), "".concat(prefix, "rating-").concat(size)], (_classNames = {}, _defineProperty(_classNames, "".concat(prefix, "rating-grade-low"), value <= count * 0.4), _defineProperty(_classNames, "".concat(prefix, "rating-grade-high"), value > count * 0.4), _defineProperty(_classNames, "".concat(prefix, "rating-stroke-mode"), strokeMode), _defineProperty(_classNames, "hover", hoverValue > 0), _classNames), className);
      var baseCls = classNames("".concat(prefix, "rating-base"), _defineProperty({}, "".concat(prefix, "rating-base-disabled"), disabled));
      var overlayStyle = {
        width: this.getOverlayWidth()
      };
      var infoStyle = {
        left: this.getInfoLeft(),
        display: hoverValue ? 'block' : 'none'
      };
      var finalProps = disabled ? {} : {
        onClick: this.handleClick,
        onMouseOver: this.handleHover,
        onMouseMove: this.handleHover,
        onMouseLeave: this.handleLeave
      };

      if (rtl) {
        others.dir = 'rtl';
      }

      return React.createElement("div", _extends({
        id: id || null
      }, others, {
        className: ratingCls,
        onKeyDown: this.onKeyDown,
        tabIndex: "0",
        role: "group",
        "aria-label": locale.description
      }), React.createElement("div", _extends({
        className: baseCls
      }, finalProps), React.createElement("div", {
        className: "".concat(prefix, "rating-underlay"),
        ref: function ref(n) {
          return _this4.underlayNode = n;
        },
        "aria-hidden": true
      }, underlay), React.createElement("div", {
        className: "".concat(prefix, "rating-overlay"),
        style: overlayStyle
      }, overlay)), showGrade ? React.createElement("div", {
        className: "".concat(prefix, "rating-info"),
        style: infoStyle
      }, readAs(value)) : null);
    }
  }]);

  return Rating;
}(Component);

_defineProperty(Rating, "displayName", 'Rating');

_defineProperty(Rating, "propTypes", {
  prefix: PropTypes.string,

  /**
   * 默认值
   */
  defaultValue: PropTypes.number,

  /**
   * 值
   */
  value: PropTypes.number,

  /**
   * 评分的总数
   */
  count: PropTypes.number,

  /**
   * 是否显示 grade
   */
  showGrade: PropTypes.bool,

  /**
   * 尺寸
   */
  size: PropTypes.oneOf(['small', 'medium', 'large']),

  /**
   * 是否允许半星评分
   */
  allowHalf: PropTypes.bool,

  /**
   * 用户点击评分时触发的回调
   * @param {String} value 评分值
   */
  onChange: PropTypes.func,

  /**
   * 用户hover评分时触发的回调
   * @param {String} value 评分值
   */
  onHoverChange: PropTypes.func,

  /**
   * 是否禁用
   */
  disabled: PropTypes.bool,

  /**
   * 评分文案生成方法，传入id支持无障碍时，读屏软件可读
   */
  readAs: PropTypes.func,
  // 实验属性: 自定义评分icon
  iconType: PropTypes.string,
  // 实验属性: 开启 `-webkit-text-stroke` 显示边框颜色，在IE中无效
  strokeMode: PropTypes.bool,
  className: PropTypes.string,
  id: PropTypes.string,
  rtl: PropTypes.bool,

  /**
   * 自定义国际化文案对象
   */
  locale: PropTypes.object
});

_defineProperty(Rating, "defaultProps", {
  prefix: 'next-',
  size: 'medium',
  disabled: false,
  count: 5,
  showGrade: false,
  defaultValue: 0,
  readAs: function readAs(val) {
    return val;
  },
  allowHalf: false,
  iconType: 'star-fill',
  onChange: noop,
  onHoverChange: noop,
  locale: zhCN.Rating
});

export { Rating as default };