"use strict";

exports.__esModule = true;
exports.default = void 0;

var _react = _interopRequireWildcard(require("react"));

var _icons = require("@react-vant/icons");

var _clsx = _interopRequireDefault(require("clsx"));

var _utils = require("../utils");

var _useTouch = _interopRequireDefault(require("../hooks/use-touch"));

var _useRefs2 = _interopRequireDefault(require("../hooks/use-refs"));

var _useMergedState2 = _interopRequireDefault(require("../hooks/use-merged-state"));

var _ConfigProviderContext = _interopRequireDefault(require("../config-provider/ConfigProviderContext"));

var _useEventListener = _interopRequireDefault(require("../hooks/use-event-listener"));

var _excluded = ["count", "touchable", "onChange"];

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }

function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }

function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }

function getRateStatus(value, index, allowHalf, readonly) {
  if (value >= index) {
    return {
      status: 'full',
      value: 1
    };
  }

  if (value + 0.5 >= index && allowHalf && !readonly) {
    return {
      status: 'half',
      value: 0.5
    };
  }

  if (value + 1 >= index && allowHalf && readonly) {
    var cardinal = Math.pow(10, 10);
    return {
      status: 'half',
      value: Math.round((value - index + 1) * cardinal) / cardinal
    };
  }

  return {
    status: 'void',
    value: 0
  };
}

var Rate = function Rate(_ref) {
  var count = _ref.count,
      touchable = _ref.touchable,
      onChange = _ref.onChange,
      props = _objectWithoutPropertiesLoose(_ref, _excluded);

  var _useContext = (0, _react.useContext)(_ConfigProviderContext.default),
      prefixCls = _useContext.prefixCls,
      createNamespace = _useContext.createNamespace;

  var _createNamespace = createNamespace('rate', prefixCls),
      bem = _createNamespace[0];

  var _useMergedState = (0, _useMergedState2.default)({
    value: props.value,
    defaultValue: props.defaultValue
  }),
      value = _useMergedState[0],
      setValue = _useMergedState[1];

  var root = (0, _react.useRef)(null);
  var touch = (0, _useTouch.default)(true);

  var _useRefs = (0, _useRefs2.default)(),
      itemRefs = _useRefs[0],
      setItemRefs = _useRefs[1];

  var untouchable = function untouchable() {
    return props.readonly || props.disabled || !touchable;
  };

  var list = (0, _react.useMemo)(function () {
    return Array(count).fill('').map(function (_, i) {
      return getRateStatus(value, i + 1, props.allowHalf, props.readonly);
    });
  }, [count, value, props.allowHalf, props.readonly]);
  var ranges = (0, _react.useRef)();

  var updateRanges = function updateRanges() {
    var rects = itemRefs.map(function (item) {
      return item.getBoundingClientRect();
    });
    ranges.current = [];
    rects.forEach(function (rect, index) {
      if (props.allowHalf) {
        ranges.current.push({
          score: index + 0.5,
          left: rect.left
        }, {
          score: index + 1,
          left: rect.left + rect.width / 2
        });
      } else {
        ranges.current.push({
          score: index + 1,
          left: rect.left
        });
      }
    });
  };

  var getScoreByPosition = function getScoreByPosition(x) {
    // eslint-disable-next-line no-plusplus
    for (var i = ranges.current.length - 1; i > 0; i--) {
      if (x > ranges.current[i].left) {
        return ranges.current[i].score;
      }
    }

    return props.allowHalf ? 0.5 : 1;
  };

  var select = function select(index) {
    if (!props.disabled && !props.readonly && index !== value) {
      setValue(index);
      onChange == null ? void 0 : onChange(index);
    }
  };

  var onTouchStart = function onTouchStart(event) {
    if (untouchable()) {
      return;
    }

    touch.start(event.nativeEvent);
    updateRanges();
  };

  var onTouchMove = function onTouchMove(event) {
    if (untouchable()) {
      return;
    }

    touch.move(event);

    if (touch.isHorizontal()) {
      var clientX = event.touches[0].clientX;
      (0, _utils.preventDefault)(event);
      select(getScoreByPosition(clientX));
    }
  };

  var renderStar = function renderStar(item, index) {
    var icon = props.icon,
        size = props.size,
        color = props.color,
        gutter = props.gutter,
        voidIcon = props.voidIcon,
        disabled = props.disabled,
        voidColor = props.voidColor,
        allowHalf = props.allowHalf,
        disabledColor = props.disabledColor;
    var score = index + 1;
    var isFull = item.status === 'full';
    var isVoid = item.status === 'void';
    var renderHalf = allowHalf && item.value > 0 && item.value < 1;
    var style;

    if (gutter && score !== +count) {
      style = {
        paddingRight: (0, _utils.addUnit)(gutter)
      };
    }

    var onClickItem = function onClickItem(event) {
      updateRanges();
      select(allowHalf ? getScoreByPosition(event.clientX) : score);
    };

    return /*#__PURE__*/_react.default.createElement("div", {
      key: index,
      ref: setItemRefs(index),
      role: "radio",
      style: style,
      className: (0, _clsx.default)(bem('item')),
      tabIndex: 0,
      "aria-setsize": parseInt(count == null ? void 0 : count.toString(), 10),
      "aria-posinset": score,
      "aria-checked": !isVoid,
      onClick: onClickItem
    }, /*#__PURE__*/_react.default.cloneElement(isFull ? icon : voidIcon, {
      className: (0, _clsx.default)(bem('icon', {
        disabled: disabled,
        full: isFull
      })),
      style: {
        color: disabled ? disabledColor : isFull ? color : voidColor,
        fontSize: size
      }
    }), renderHalf && /*#__PURE__*/_react.default.createElement("div", {
      className: (0, _clsx.default)(bem('icon', ['half'])),
      style: {
        width: item.value + "em"
      }
    }, /*#__PURE__*/_react.default.cloneElement(isVoid ? voidIcon : icon, {
      className: (0, _clsx.default)(bem('icon', [{
        disabled: disabled,
        full: !isVoid
      }])),
      style: {
        color: disabled ? disabledColor : isVoid ? voidColor : color,
        fontSize: size
      }
    })));
  };

  (0, _useEventListener.default)('touchmove', onTouchMove, {
    target: root.current,
    depends: [touch.deltaY]
  });
  return /*#__PURE__*/_react.default.createElement("div", {
    ref: root,
    role: "radiogroup",
    className: (0, _clsx.default)(bem({
      readonly: props.readonly,
      disabled: props.disabled
    })),
    tabIndex: 0,
    onTouchStart: onTouchStart
  }, list.map(renderStar));
};

Rate.defaultProps = {
  size: 20,
  count: 5,
  gutter: 4,
  icon: /*#__PURE__*/_react.default.createElement(_icons.Star, null),
  voidIcon: /*#__PURE__*/_react.default.createElement(_icons.StarO, null),
  touchable: true
};
var _default = Rate;
exports.default = _default;