"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = exports.STEPPER_KEY = 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 _number = require("../utils/validate/number");

var _interceptor = require("../utils/interceptor");

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

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

var _constant = require("../utils/constant");

var _useRefState = _interopRequireDefault(require("../hooks/use-ref-state"));

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 LONG_PRESS_INTERVAL = 200;
const LONG_PRESS_START_TIME = 600;

function equal(value1, value2) {
  return String(value1) === String(value2);
} // add num and avoid float number


function add(num1, num2) {
  const cardinal = Math.pow(10, 10);
  return Math.round((num1 + num2) * cardinal) / cardinal;
}

const Stepper = props => {
  const {
    prefixCls,
    createNamespace
  } = (0, _react().useContext)(_ConfigProviderContext.default);
  const [bem] = createNamespace('stepper', prefixCls);
  const format = (0, _react().useCallback)(value => {
    const {
      min,
      max,
      allowEmpty,
      decimalLength,
      integer
    } = props;

    if (allowEmpty && value === '') {
      return value;
    }

    value = (0, _utils.formatNumber)(String(value), !integer);
    value = value === '' ? 0 : +value;
    value = (0, _number.isNaN)(value) ? +min : value;
    value = Math.max(Math.min(+max, value), +min); // format decimal

    if ((0, _utils.isDef)(decimalLength)) {
      value = value.toFixed(+decimalLength);
    }

    return value;
  }, [props.min, props.max, props.allowEmpty, props.decimalLength, props.integer]);

  const getInitialValue = () => {
    var _a;

    const defaultValue = (_a = props.value) !== null && _a !== void 0 ? _a : props.defaultValue;
    const value = format(defaultValue);
    return value;
  };

  let actionType;
  const inputRef = (0, _react().useRef)(null);
  const innerEffectRef = (0, _react().useRef)(false);
  const [current, setCurrent, currentRef] = (0, _useRefState.default)(() => getInitialValue());
  const minusDisabled = (0, _react().useMemo)(() => props.disabled || props.disableMinus || current <= +props.min, [props.disabled, props.disableMinus, props.min, current]);
  const plusDisabled = (0, _react().useMemo)(() => props.disabled || props.disablePlus || current >= +props.max, [props.disabled, props.disablePlus, props.max, current]);
  const inputStyle = (0, _react().useMemo)(() => ({
    width: (0, _utils.addUnit)(props.inputWidth),
    height: (0, _utils.addUnit)(props.buttonSize)
  }), [props.inputWidth, props.buttonSize]);
  const buttonStyle = (0, _react().useMemo)(() => (0, _utils.getSizeStyle)(props.buttonSize), [props.buttonSize]);
  const innerChange = (0, _react().useCallback)(value => {
    var _a;

    innerEffectRef.current = true;
    setCurrent(value);
    (_a = props.onChange) === null || _a === void 0 ? void 0 : _a.call(props, value);
  }, [props, setCurrent]);
  const check = (0, _react().useCallback)(() => {
    const value = format(currentRef.current);

    if (!equal(value, currentRef.current)) {
      innerChange(value);
    }
  }, [format, currentRef.current]);

  const setValue = value => {
    if (props.beforeChange) {
      (0, _interceptor.callInterceptor)({
        args: [value],
        interceptor: props.beforeChange,

        done() {
          innerChange(value);
        }

      });
    } else {
      innerChange(value);
    }
  };

  const onChange = e => {
    var _a, _b, _c;

    const isMinus = actionType === 'minus';

    if (actionType === 'plus' && plusDisabled || isMinus && minusDisabled) {
      (_a = props.onOverlimit) === null || _a === void 0 ? void 0 : _a.call(props, actionType);
      return;
    }

    const diff = isMinus ? -props.step : +props.step;
    const value = format(add(+currentRef.current, diff));
    setValue(value);

    if (isMinus) {
      (_b = props.onMinus) === null || _b === void 0 ? void 0 : _b.call(props, e, value);
    } else {
      (_c = props.onPlus) === null || _c === void 0 ? void 0 : _c.call(props, e, value);
    }
  };

  const onInput = event => {
    const input = event.target;
    const {
      value
    } = input;
    const {
      decimalLength
    } = props;
    let formatted = (0, _utils.formatNumber)(String(value), !props.integer); // limit max decimal length

    if ((0, _utils.isDef)(decimalLength) && formatted.includes('.')) {
      const pair = formatted.split('.');
      formatted = `${pair[0]}.${pair[1].slice(0, +decimalLength)}`;
    } // prefer number type


    const isNumeric = formatted === String(+formatted);
    setValue(isNumeric ? +formatted : formatted);
  };

  const onFocus = (0, _react().useCallback)(event => {
    var _a; // readonly not work in lagacy mobile safari


    if (props.disableInput && inputRef.current) {
      inputRef.current.blur();
    } else {
      (_a = props.onFocus) === null || _a === void 0 ? void 0 : _a.call(props, event);
    }
  }, [props]);

  const onBlur = event => {
    var _a;

    const input = event.target;
    const value = format(input.value);

    if (!equal(value, currentRef.current)) {
      innerChange(value);
    }

    (_a = props.onBlur) === null || _a === void 0 ? void 0 : _a.call(props, event);
    (0, _utils.resetScroll)();
  };

  const isLongPress = (0, _react().useRef)(false);
  const longPressTimer = (0, _react().useRef)(null);

  const longPressStep = () => {
    longPressTimer.current = setTimeout(() => {
      onChange();
      longPressStep();
    }, LONG_PRESS_INTERVAL);
  };

  const onTouchStart = () => {
    if (props.longPress) {
      isLongPress.current = false;
      clearTimeout(longPressTimer.current);
      longPressTimer.current = setTimeout(() => {
        isLongPress.current = true;
        onChange();
        longPressStep();
      }, LONG_PRESS_START_TIME);
    }
  };

  const onTouchEnd = event => {
    if (props.longPress) {
      clearTimeout(longPressTimer.current);

      if (isLongPress.current) {
        (0, _utils.preventDefault)(event);
      }
    }
  };

  const onMousedown = event => {
    // fix mobile safari page scroll down issue
    // see: https://github.com/youzan/vant/issues/7690
    if (props.disableInput) {
      event.preventDefault();
    }
  };

  const createListeners = type => ({
    onClick: event => {
      // disable double tap scrolling on mobile safari
      event.preventDefault();
      actionType = type;
      onChange(event);
    },
    onTouchStart: () => {
      actionType = type;
      onTouchStart();
    },
    onTouchEnd,
    onTouchCancel: onTouchEnd
  });

  (0, _react().useEffect)(() => {
    if (innerEffectRef.current) {
      innerEffectRef.current = false;
      return;
    }

    setCurrent(props.value);
  }, [props.value, setCurrent]);
  (0, _react().useEffect)(() => check, [props.max, props.min, props.integer, props.decimalLength]);
  return (0, _jsxRuntime().jsxs)("div", Object.assign({
    className: (0, _clsx().default)(props.className, bem([props.theme])),
    style: props.style
  }, {
    children: [props.showMinus && (0, _jsxRuntime().jsx)("button", Object.assign({
      type: "button",
      "aria-label": "minus",
      style: buttonStyle,
      className: (0, _clsx().default)(bem('minus', {
        disabled: minusDisabled
      }))
    }, createListeners('minus'))), props.showInput && (0, _jsxRuntime().jsx)("input", {
      ref: inputRef,
      type: props.integer ? 'tel' : 'text',
      role: "spinbutton",
      className: (0, _clsx().default)(bem('input')),
      value: current !== null && current !== void 0 ? current : '',
      style: inputStyle,
      disabled: props.disabled,
      readOnly: props.disableInput,
      inputMode: props.integer ? 'numeric' : 'decimal',
      placeholder: props.placeholder,
      "aria-valuemax": +props.max,
      "aria-valuemin": +props.min,
      "aria-valuenow": +current,
      onChange: onInput,
      onBlur: onBlur,
      onFocus: onFocus,
      onMouseDown: onMousedown,
      onClick: props.onClick
    }), props.showPlus && (0, _jsxRuntime().jsx)("button", Object.assign({
      type: "button",
      "aria-label": "add",
      style: buttonStyle,
      className: (0, _clsx().default)(bem('plus', {
        disabled: plusDisabled
      }))
    }, createListeners('plus')))]
  }));
};

Stepper.defaultProps = {
  theme: 'default',
  max: Number.MAX_VALUE,
  min: 1,
  step: 1,
  defaultValue: 1,
  showPlus: true,
  showMinus: true,
  showInput: true,
  longPress: true
};
const STEPPER_KEY = Symbol('stepper');
exports.STEPPER_KEY = STEPPER_KEY;
const StepperNamespace = Object.assign(Stepper, {
  [_constant.COMPONENT_TYPE_KEY]: STEPPER_KEY
});
var _default = StepperNamespace;
exports.default = _default;