"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");

var _typeof3 = require("@babel/runtime/helpers/typeof");

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

var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));

var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));

var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));

var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));

var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));

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

var _icon = _interopRequireDefault(require("../icon"));

var _uiIcons = require("@teamleader/ui-icons");

var _theme = _interopRequireDefault(require("./theme.css"));

var _SingleLineInputBase = _interopRequireDefault(require("./SingleLineInputBase"));

var _constants = require("../../constants");

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

var _button = _interopRequireDefault(require("../button"));

var _excluded = ["connectedLeft", "connectedRight", "inverse", "max", "min", "onBlur", "onChange", "onKeyDown", "size", "step", "stepper", "suffix", "value"];

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 || _typeof3(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 ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }

function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { (0, _defineProperty2.default)(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }

var StepperControls = function StepperControls(_ref) {
  var inverse = _ref.inverse,
      stepperUpProps = _ref.stepperUpProps,
      stepperDownProps = _ref.stepperDownProps;
  var iconProps = {
    color: inverse ? 'teal' : 'neutral',
    element: 'button',
    tabIndex: '-1',
    tint: inverse ? 'lightest' : 'darkest',
    type: 'button'
  };
  return /*#__PURE__*/_react.default.createElement("div", {
    className: _theme.default['stepper']
  }, /*#__PURE__*/_react.default.createElement(_icon.default, (0, _extends2.default)({
    className: _theme.default['stepper-up']
  }, stepperUpProps, iconProps), /*#__PURE__*/_react.default.createElement(_uiIcons.IconChevronUpSmallOutline, null)), /*#__PURE__*/_react.default.createElement(_icon.default, (0, _extends2.default)({
    className: _theme.default['stepper-down']
  }, stepperDownProps, iconProps), /*#__PURE__*/_react.default.createElement(_uiIcons.IconChevronDownSmallOutline, null)));
};

var NumericInput = /*#__PURE__*/(0, _react.forwardRef)(function (_ref2, forwardedRef) {
  var connectedLeft = _ref2.connectedLeft,
      connectedRight = _ref2.connectedRight,
      _ref2$inverse = _ref2.inverse,
      inverse = _ref2$inverse === void 0 ? false : _ref2$inverse,
      _ref2$max = _ref2.max,
      max = _ref2$max === void 0 ? Number.MAX_SAFE_INTEGER : _ref2$max,
      _ref2$min = _ref2.min,
      min = _ref2$min === void 0 ? Number.MIN_SAFE_INTEGER : _ref2$min,
      onBlur = _ref2.onBlur,
      onChange = _ref2.onChange,
      onKeyDown = _ref2.onKeyDown,
      size = _ref2.size,
      _ref2$step = _ref2.step,
      step = _ref2$step === void 0 ? 1 : _ref2$step,
      _ref2$stepper = _ref2.stepper,
      stepper = _ref2$stepper === void 0 ? 'suffix' : _ref2$stepper,
      _ref2$suffix = _ref2.suffix,
      suffix = _ref2$suffix === void 0 ? [] : _ref2$suffix,
      value = _ref2.value,
      others = (0, _objectWithoutProperties2.default)(_ref2, _excluded);
  var inputElementRef = (0, _react.useRef)(null);
  var timerRef = (0, _react.useRef)(null);
  var timeoutRef = (0, _react.useRef)(null);
  var valueRef = (0, _react.useRef)(value);
  (0, _react.useEffect)(function () {
    valueRef.current = value;
  }, [value]);

  var isMinReached = function isMinReached() {
    return (0, _utils.toNumber)(value || 0) <= min;
  };

  var isMaxReached = function isMaxReached() {
    return (0, _utils.toNumber)(value || 0) >= max;
  };

  var handleChange = function handleChange(event) {
    onChange && onChange(event, event.currentTarget.value);
  };

  var updateStep = function updateStep(n) {
    var _Object$getOwnPropert;

    var currentValue = (0, _utils.toNumber)(valueRef.current || 0);
    var stepN = step * n;
    var newValue = currentValue + stepN;

    if (newValue % step) {
      newValue = Math.ceil(currentValue / stepN) * stepN;
    }

    var newValueBoundToMinMax = (0, _utils.parseValue)(newValue, min, max);
    var currentInputElement = inputElementRef.current;

    if (!currentInputElement) {
      return;
    }

    var prototype = Object.getPrototypeOf(currentInputElement);
    var prototypeValueSetter = (_Object$getOwnPropert = Object.getOwnPropertyDescriptor(prototype, 'value')) === null || _Object$getOwnPropert === void 0 ? void 0 : _Object$getOwnPropert.set;

    if (!prototypeValueSetter) {
      return;
    }

    prototypeValueSetter.call(currentInputElement, newValueBoundToMinMax);
    currentInputElement.dispatchEvent(new Event('change', {
      bubbles: true
    }));
  };

  var handleIncreaseValue = function handleIncreaseValue() {
    updateStep(1);
  };

  var handleDecreaseValue = function handleDecreaseValue() {
    updateStep(-1);
  };

  var handleClearStepperTimer = function handleClearStepperTimer() {
    clearTimeout(timeoutRef.current);
    clearInterval(timerRef.current);
  };

  var handleDecreaseMouseDown = function handleDecreaseMouseDown() {
    handleDecreaseValue();
    timeoutRef.current = setTimeout(function () {
      timerRef.current = setInterval(function () {
        if (isMinReached()) {
          handleClearStepperTimer();
        } else {
          handleDecreaseValue();
        }
      }, 75);
    }, 300);
  };

  var handleIncreaseMouseDown = function handleIncreaseMouseDown() {
    handleIncreaseValue();
    timeoutRef.current = setTimeout(function () {
      timerRef.current = setInterval(function () {
        if (isMaxReached()) {
          handleClearStepperTimer();
        } else {
          handleIncreaseValue();
        }
      }, 75);
    }, 300);
  }; // Unlike mouse down events, key down events are "auto-repeated" while holding down the key
  // This means we don't need to use an interval and can directly rely on the handler
  // https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent#auto-repeat_handling


  var handleKeyDown = function handleKeyDown(event) {
    if (event.key === _constants.KEY.ArrowUp) {
      event.preventDefault();
      handleIncreaseValue();
    } else if (event.key === _constants.KEY.ArrowDown) {
      event.preventDefault();
      handleDecreaseValue();
    }

    onKeyDown && onKeyDown(event);
  };

  var handleBlur = function handleBlur(event) {
    onBlur && onBlur(event);
  };

  var getConnectedRight = function getConnectedRight() {
    if (stepper === 'connected') {
      return /*#__PURE__*/_react.default.createElement(_button.default, {
        disabled: isMaxReached(),
        icon: /*#__PURE__*/_react.default.createElement(_uiIcons.IconAddSmallOutline, null),
        onBlur: handleBlur,
        onMouseDown: handleIncreaseMouseDown,
        onMouseUp: handleClearStepperTimer,
        onMouseLeave: handleClearStepperTimer,
        size: size
      });
    }

    return connectedRight;
  };

  var getConnectedLeft = function getConnectedLeft() {
    if (stepper === 'connected') {
      return /*#__PURE__*/_react.default.createElement(_button.default, {
        disabled: isMinReached(),
        icon: /*#__PURE__*/_react.default.createElement(_uiIcons.IconMinusSmallOutline, null),
        onMouseDown: handleDecreaseMouseDown,
        onMouseUp: handleClearStepperTimer,
        onMouseLeave: handleClearStepperTimer,
        onBlur: handleBlur,
        size: size
      });
    }

    return connectedLeft;
  };

  var getSuffix = function getSuffix() {
    if (stepper === 'suffix') {
      return [].concat((0, _toConsumableArray2.default)(Array.isArray(suffix) ? suffix : [suffix]), [
      /*#__PURE__*/

      /* eslint-disable-next-line react/jsx-key */
      _react.default.createElement(StepperControls, {
        inverse: inverse,
        stepperUpProps: {
          disabled: isMaxReached(),
          onBlur: handleBlur,
          onMouseDown: handleIncreaseMouseDown,
          onMouseUp: handleClearStepperTimer,
          onMouseLeave: handleClearStepperTimer
        },
        stepperDownProps: {
          disabled: isMinReached(),
          onBlur: handleBlur,
          onMouseDown: handleDecreaseMouseDown,
          onMouseUp: handleClearStepperTimer,
          onMouseLeave: handleClearStepperTimer
        }
      })]);
    }

    return suffix;
  };

  var setRef = function setRef(ref) {
    inputElementRef.current = ref;

    if (typeof forwardedRef === 'function') {
      forwardedRef(ref);
    } else if ((0, _typeof2.default)(forwardedRef) === 'object' && forwardedRef !== null) {
      forwardedRef.current = ref;
    }
  };

  var restProps = _objectSpread({
    connectedLeft: connectedLeft,
    connectedRight: connectedRight,
    inverse: inverse,
    max: max,
    min: min,
    onBlur: onBlur,
    size: size,
    step: step,
    stepper: stepper
  }, others);

  return /*#__PURE__*/_react.default.createElement(_SingleLineInputBase.default, (0, _extends2.default)({
    ref: setRef,
    type: "number",
    value: value,
    onChange: handleChange,
    onKeyDown: handleKeyDown
  }, restProps, {
    connectedLeft: getConnectedLeft(),
    connectedRight: getConnectedRight(),
    suffix: getSuffix()
  }));
});
NumericInput.displayName = 'NumericInput';
var _default = NumericInput;
exports.default = _default;