"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;

function _react() {
  const data = _interopRequireWildcard(require("react"));

  _react = function () {
    return data;
  };

  return data;
}

function _jsxRuntime() {
  const data = require("react/jsx-runtime");

  _jsxRuntime = function () {
    return data;
  };

  return data;
}

function _clsx() {
  const data = _interopRequireDefault(require("clsx"));

  _clsx = function () {
    return data;
  };

  return data;
}

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

var _useRect = require("../hooks/use-rect");

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

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

var _hooks = require("../hooks");

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 (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; }

const Slider = props => {
  const {
    prefixCls,
    createNamespace
  } = (0, _react().useContext)(_ConfigProviderContext.default);
  const [bem] = createNamespace('slider', prefixCls);
  const [buttonRef1, setButtonRef1] = (0, _react().useState)(null);
  const [buttonRef2, setButtonRef2] = (0, _react().useState)(null);
  const buttonIndex = (0, _react().useRef)();
  const startValue = (0, _react().useRef)();
  const currentValue = (0, _react().useRef)(props.value);
  const root = (0, _react().useRef)();
  const dragStatus = (0, _react().useRef)();
  const touch = (0, _hooks.useTouch)();
  const scope = (0, _react().useMemo)(() => Number(props.max) - Number(props.min), [props.max, props.min]);
  const wrapperStyle = (0, _react().useMemo)(() => {
    const crossAxis = props.vertical ? 'width' : 'height';
    return Object.assign({
      background: props.inactiveColor,
      [crossAxis]: (0, _utils.addUnit)(props.barHeight)
    }, props.style);
  }, [props.vertical, props.barHeight, props.inactiveColor, props.style]);

  const isRange = val => props.range && Array.isArray(val); // 计算选中条的长度百分比


  const calcMainAxis = () => {
    const {
      value,
      min
    } = props;

    if (isRange(value)) {
      return `${(value[1] - value[0]) * 100 / scope}%`;
    }

    return `${(+value - Number(min)) * 100 / scope}%`;
  }; // 计算选中条的开始位置的偏移量


  const calcOffset = () => {
    const {
      value,
      min
    } = props;

    if (isRange(value)) {
      return `${(value[0] - Number(min)) * 100 / scope}%`;
    }

    return '0%';
  };

  const barStyle = (0, _react().useMemo)(() => {
    const mainAxis = props.vertical ? 'height' : 'width';
    const style = {
      [mainAxis]: calcMainAxis(),
      background: props.activeColor
    };

    if (dragStatus.current) {
      style.transition = 'none';
    }

    const getPositionKey = () => {
      if (props.vertical) {
        return props.reverse ? 'bottom' : 'top';
      }

      return props.reverse ? 'right' : 'left';
    };

    style[getPositionKey()] = calcOffset();
    return style; // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [calcOffset]);

  const format = value => {
    const min = +props.min;
    const max = +props.max;
    const step = +props.step;
    value = (0, _utils.range)(value, min, max);
    const diff = Math.round((value - min) / step) * step;
    return (0, _utils.addNumber)(min, diff);
  };

  const isSameValue = (newValue, oldValue) => JSON.stringify(newValue) === JSON.stringify(oldValue);

  const handleRangeValue = value => {
    var _a, _b; // 设置默认值


    const left = (_a = value[0]) !== null && _a !== void 0 ? _a : Number(props.min);
    const right = (_b = value[1]) !== null && _b !== void 0 ? _b : Number(props.max); // 处理两个滑块重叠之后的情况

    return left > right ? [right, left] : [left, right];
  };

  const updateValue = (value, end) => {
    var _a, _b;

    if (isRange(value)) {
      value = handleRangeValue(value).map(format);
    } else {
      value = format(value);
    }

    if (!isSameValue(value, props.value)) {
      (_a = props.onChange) === null || _a === void 0 ? void 0 : _a.call(props, value);
    }

    if (end && !isSameValue(value, startValue.current)) {
      (_b = props.onChangeAfter) === null || _b === void 0 ? void 0 : _b.call(props, value);
    }

    return value;
  };

  const onClick = event => {
    event.stopPropagation();

    if (props.disabled || props.readonly) {
      return;
    }

    const {
      min,
      reverse,
      vertical,
      value: modelValue
    } = props;
    const rect = (0, _useRect.getRect)(root.current);

    const getDelta = () => {
      if (vertical) {
        if (reverse) {
          return rect.bottom - event.clientY;
        }

        return event.clientY - rect.top;
      }

      if (reverse) {
        return rect.right - event.clientX;
      }

      return event.clientX - rect.left;
    };

    const total = vertical ? rect.height : rect.width;
    const value = Number(min) + getDelta() / total * scope;

    if (isRange(modelValue)) {
      const [left, right] = modelValue;
      const middle = (left + right) / 2;

      if (value <= middle) {
        updateValue([value, right], true);
      } else {
        updateValue([left, value], true);
      }
    } else {
      updateValue(value, true);
    }
  };

  const onTouchStart = event => {
    if (props.disabled || props.readonly) {
      return;
    }

    touch.start(event);
    currentValue.current = JSON.parse(JSON.stringify(props.value));

    if (isRange(currentValue.current)) {
      startValue.current = currentValue.current.map(format);
    } else {
      startValue.current = format(currentValue.current);
    }

    dragStatus.current = 'start';
  };

  const onTouchMove = event => {
    var _a;

    if (props.disabled || props.readonly) {
      return;
    }

    if (dragStatus.current === 'start') {
      (_a = props.onDragStart) === null || _a === void 0 ? void 0 : _a.call(props, event, startValue.current);
    }

    (0, _utils.preventDefault)(event, true);
    touch.move(event);
    dragStatus.current = 'dragging';
    const rect = (0, _useRect.getRect)(root.current);
    const delta = props.vertical ? touch.deltaY.current : touch.deltaX.current;
    const total = props.vertical ? rect.height : rect.width;
    let diff = delta / total * scope;

    if (props.reverse) {
      diff = -diff;
    }

    if (isRange(startValue.current)) {
      const index = props.reverse ? 1 - buttonIndex.current : buttonIndex.current;
      currentValue.current[index] = startValue.current[index] + diff;
    } else {
      currentValue.current = +startValue.current + diff;
    }

    updateValue(currentValue.current);
  };

  const onTouchEnd = event => {
    var _a;

    if (props.disabled || props.readonly) {
      return;
    }

    if (dragStatus.current === 'dragging') {
      const value = updateValue(currentValue.current, true);
      (_a = props.onDragEnd) === null || _a === void 0 ? void 0 : _a.call(props, event, value);
    }

    dragStatus.current = '';
  };

  const getButtonClassName = index => {
    if (typeof index === 'number') {
      const position = ['left', 'right'];
      return bem('button-wrapper', position[index]);
    }

    return bem('button-wrapper', props.reverse ? 'left' : 'right');
  };

  const renderButtonContent = (value, index) => {
    if (typeof index === 'number') {
      const slot = props[index === 0 ? 'leftButton' : 'rightButton'];

      if (slot) {
        return slot;
      }
    }

    if (typeof props.button === 'function') {
      return props.button({
        value
      });
    }

    if (props.button) {
      return props.button;
    }

    return (0, _jsxRuntime().jsx)("div", {
      className: (0, _clsx().default)(bem('button')),
      style: (0, _utils.getSizeStyle)(props.buttonSize)
    });
  };

  const renderButton = (buttounRef, index) => {
    const value = typeof index === 'number' ? props.value[index] : props.value;
    return (0, _jsxRuntime().jsx)("div", Object.assign({
      ref: buttounRef,
      role: "slider",
      className: (0, _clsx().default)(getButtonClassName(index)),
      tabIndex: props.disabled || props.readonly ? -1 : 0,
      "aria-valuemin": props.min,
      "aria-valuenow": value,
      "aria-valuemax": props.max,
      "aria-orientation": props.vertical ? 'vertical' : 'horizontal',
      onTouchStart: event => {
        if (typeof index === 'number') {
          // save index of current button
          buttonIndex.current = index;
        }

        onTouchStart(event);
      },
      onTouchEnd: onTouchEnd,
      onTouchCancel: onTouchEnd,
      onClick: _utils.stopPropagation
    }, {
      children: renderButtonContent(currentValue.current, index)
    }), index);
  };

  (0, _useEventListener.default)('touchmove', onTouchMove, {
    target: buttonRef1,
    depends: [touch.deltaX.current, touch.deltaY.current, props.disabled, props.readonly]
  });
  (0, _useEventListener.default)('touchmove', onTouchMove, {
    target: buttonRef2,
    depends: [touch.deltaX.current, touch.deltaY.current, props.disabled, props.readonly]
  });
  return (0, _jsxRuntime().jsx)("div", Object.assign({
    ref: root,
    style: wrapperStyle,
    className: (0, _clsx().default)(props.className, bem({
      vertical: props.vertical,
      disabled: props.disabled
    })),
    onClick: onClick
  }, {
    children: (0, _jsxRuntime().jsx)("div", Object.assign({
      className: (0, _clsx().default)(bem('bar')),
      style: barStyle
    }, {
      children: props.range ? [renderButton(setButtonRef1, 0), renderButton(setButtonRef2, 1)] : renderButton(setButtonRef1)
    }))
  }));
};

Slider.defaultProps = {
  min: 0,
  max: 100,
  step: 1
};
var _default = Slider;
exports.default = _default;