"use strict";

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

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

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

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

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

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

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

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

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

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

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

var _propTypes = _interopRequireDefault(require("prop-types"));

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

var _TextField = _interopRequireDefault(require("@material-ui/core/TextField"));

var _classnames = _interopRequireDefault(require("classnames"));

var _styles = require("@material-ui/core/styles");

var _isFinite = _interopRequireDefault(require("lodash/isFinite"));

var _IconButton = _interopRequireDefault(require("@material-ui/core/IconButton"));

var _InputAdornment = _interopRequireDefault(require("@material-ui/core/InputAdornment"));

var _Remove = _interopRequireDefault(require("@material-ui/icons/Remove"));

var _Add = _interopRequireDefault(require("@material-ui/icons/Add"));

var math = _interopRequireWildcard(require("mathjs"));

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 _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = (0, _getPrototypeOf2["default"])(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = (0, _getPrototypeOf2["default"])(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return (0, _possibleConstructorReturn2["default"])(this, result); }; }

function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }

var styles = function styles() {
  return {
    input: {
      '& input[type=number]': {
        '-moz-appearance': 'textfield'
      },
      '& input[type=number]::-webkit-outer-spin-button': {
        '-webkit-appearance': 'none',
        margin: 0
      },
      '& input[type=number]::-webkit-inner-spin-button': {
        '-webkit-appearance': 'none',
        margin: 0
      }
    },
    iconButton: {
      padding: '2px'
    }
  };
};

var fallbackNumber = function fallbackNumber(min, max) {
  if (!(0, _isFinite["default"])(min) && !(0, _isFinite["default"])(max)) {
    return 0;
  }

  if (!(0, _isFinite["default"])(min) && (0, _isFinite["default"])(max)) {
    return max;
  }

  if ((0, _isFinite["default"])(min)) {
    return min;
  }
};

var NumberTextFieldCustom = /*#__PURE__*/function (_React$Component) {
  (0, _inherits2["default"])(NumberTextFieldCustom, _React$Component);

  var _super = _createSuper(NumberTextFieldCustom);

  function NumberTextFieldCustom(props) {
    var _this;

    (0, _classCallCheck2["default"])(this, NumberTextFieldCustom);
    _this = _super.call(this, props);
    (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "normalizeValueAndIndex", function (customValues, number, min, max) {
      var type = _this.props.type;

      var value = _this.clamp(number, min, max);

      var currentIndex = (customValues || []).findIndex(function (val) {
        return val === value;
      });

      if ((customValues || []).length > 0 && currentIndex === -1) {
        var closestValue = type === 'text' ? _this.getClosestFractionValue(customValues, value) : _this.getClosestValue(customValues, value);
        return {
          value: closestValue.value,
          currentIndex: closestValue.index
        };
      }

      return {
        value: value,
        currentIndex: currentIndex
      };
    });
    (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "getClosestValue", function (customValues, number) {
      return customValues.reduce(function (closest, value, index) {
        return Math.abs(value - number) < Math.abs(closest.value - number) ? {
          value: value,
          index: index
        } : closest;
      }, {
        value: customValues[0],
        index: 0
      });
    });
    (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "getClosestFractionValue", function (customValues, number) {
      return customValues.reduce(function (closest, value, index) {
        return Math.abs(math.number(math.fraction(value)) - math.number(math.fraction(number))) < Math.abs(math.number(math.fraction(closest.value)) - math.number(math.fraction(number))) ? {
          value: value,
          index: index
        } : closest;
      }, {
        value: customValues[0],
        index: 0
      });
    });
    (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "getValidFraction", function (value) {
      if (_this.isPositiveInteger(value.trim())) {
        return value.trim();
      }

      if (value.trim() === '' || value.trim().split('/').length !== 2) {
        return false;
      }

      var _value$trim$split = value.trim().split('/'),
          _value$trim$split2 = (0, _slicedToArray2["default"])(_value$trim$split, 2),
          numerator = _value$trim$split2[0],
          denominator = _value$trim$split2[1];

      if (isNaN(numerator) || isNaN(denominator)) {
        return false;
      }

      numerator = parseFloat(numerator);
      denominator = parseFloat(denominator);

      if (!Number.isInteger(numerator) || !Number.isInteger(denominator)) {
        return false;
      }

      if (numerator < 0 || denominator < 1) {
        return false;
      }

      return numerator + '/' + denominator;
    });
    (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "isPositiveInteger", function (n) {
      return n >>> 0 === parseFloat(n);
    });
    (0, _defineProperty2["default"])((0, _assertThisInitialized2["default"])(_this), "onBlur", function (event) {
      var _this$props = _this.props,
          customValues = _this$props.customValues,
          onlyIntegersAllowed = _this$props.onlyIntegersAllowed,
          type = _this$props.type;
      var value = event.target.value;

      if (type === 'text') {
        var tempValue = _this.getValidFraction(value);

        if (tempValue) {
          value = tempValue;
        } else {
          value = _this.props.value;
        }
      }

      var rawNumber = onlyIntegersAllowed ? Math.round(parseFloat(value)) : parseFloat(value);

      if (type === 'text') {
        rawNumber = value.trim();
      }

      var _this$normalizeValueA = _this.normalizeValueAndIndex(customValues, rawNumber),
          number = _this$normalizeValueA.value,
          currentIndex = _this$normalizeValueA.currentIndex;

      _this.setState({
        value: number.toString(),
        currentIndex: currentIndex
      }, function () {
        return _this.props.onChange(event, number);
      });
    });

    var _this$normalizeValueA2 = _this.normalizeValueAndIndex(props.customValues, props.value),
        _value = _this$normalizeValueA2.value,
        _currentIndex = _this$normalizeValueA2.currentIndex;

    _this.state = {
      value: _value,
      currentIndex: _currentIndex
    };

    if (_value !== props.value) {
      _this.props.onChange({}, _value);
    }

    _this.onChange = _this.onChange.bind((0, _assertThisInitialized2["default"])(_this));
    return _this;
  }

  (0, _createClass2["default"])(NumberTextFieldCustom, [{
    key: "UNSAFE_componentWillReceiveProps",
    value: function UNSAFE_componentWillReceiveProps(props) {
      var _this$normalizeValueA3 = this.normalizeValueAndIndex(props.customValues, props.value, props.min, props.max),
          value = _this$normalizeValueA3.value,
          currentIndex = _this$normalizeValueA3.currentIndex;

      this.setState({
        value: value,
        currentIndex: currentIndex
      });
    }
  }, {
    key: "clamp",
    value: function clamp(value) {
      var min = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.props.min;
      var max = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : this.props.max;
      var customValues = this.props.customValues;

      if ((customValues || []).length > 0) {
        return value;
      }

      if (!(0, _isFinite["default"])(value)) {
        return fallbackNumber(min, max);
      }

      if ((0, _isFinite["default"])(max)) {
        value = Math.min(value, max);
      }

      if ((0, _isFinite["default"])(min)) {
        value = Math.max(value, min);
      }

      return value;
    }
  }, {
    key: "onChange",
    value: function onChange(event) {
      var type = this.props.type;
      var value = event.target.value;

      if (type !== 'text' && typeof value === 'string' && value.trim() === '') {
        return;
      }

      this.setState({
        value: value
      });
    }
  }, {
    key: "changeValue",
    value: function changeValue(event) {
      var sign = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
      var shouldUpdate = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
      event.preventDefault();
      var _this$props2 = this.props,
          customValues = _this$props2.customValues,
          step = _this$props2.step,
          onlyIntegersAllowed = _this$props2.onlyIntegersAllowed,
          onChange = _this$props2.onChange;
      var _this$state = this.state,
          currentIndex = _this$state.currentIndex,
          value = _this$state.value;
      var updatedIndex = currentIndex + sign * 1;
      var number;

      if (customValues.length > 0) {
        if (updatedIndex < 0 || updatedIndex >= customValues.length) {
          return;
        }

        number = customValues[updatedIndex];
      } else {
        var rawNumber = onlyIntegersAllowed ? parseInt(value) : parseFloat(value);
        var updatedValue = (rawNumber * 10000 + step * sign * 10000) / 10000;
        number = this.clamp(updatedValue);
      }

      this.setState({
        value: number.toString(),
        currentIndex: updatedIndex
      }, function () {
        if (shouldUpdate) {
          onChange(event, number);
        }
      });
    }
  }, {
    key: "render",
    value: function render() {
      var _this2 = this;

      var _this$props3 = this.props,
          className = _this$props3.className,
          classes = _this$props3.classes,
          label = _this$props3.label,
          disabled = _this$props3.disabled,
          error = _this$props3.error,
          min = _this$props3.min,
          max = _this$props3.max,
          customValues = _this$props3.customValues,
          inputClassName = _this$props3.inputClassName,
          disableUnderline = _this$props3.disableUnderline,
          helperText = _this$props3.helperText,
          variant = _this$props3.variant,
          textAlign = _this$props3.textAlign,
          _this$props3$type = _this$props3.type,
          type = _this$props3$type === void 0 ? 'number' : _this$props3$type;
      var value = this.state.value;
      var names = (0, _classnames["default"])(className, classes.input); //Logic to disable the increment and decrement buttons

      var disabledStart = false;
      var disabledEnd = false;

      if (customValues.length > 0) {
        disabledStart = value === customValues[0];
        disabledEnd = value === customValues[customValues.length - 1];
      } else if ((0, _isFinite["default"])(min) && (0, _isFinite["default"])(max)) {
        disabledStart = value === min;
        disabledEnd = value === max;
      }

      return /*#__PURE__*/_react["default"].createElement(_TextField["default"], {
        variant: variant,
        inputRef: function inputRef(ref) {
          return _this2.inputRef = ref;
        },
        disabled: disabled,
        label: label,
        value: value,
        error: error,
        helperText: helperText,
        onChange: this.onChange,
        onBlur: this.onBlur,
        onKeyPress: function onKeyPress(e) {
          // once the Enter key is pressed, we force input blur
          if (e.key === 'Enter' && _this2.inputRef) {
            _this2.inputRef.blur();
          }
        },
        onKeyDown: function onKeyDown(e) {
          if (e.key === 'ArrowUp') {
            _this2.changeValue(e);
          }

          if (e.key === 'ArrowDown') {
            _this2.changeValue(e, -1);
          }
        },
        title: '',
        type: type,
        className: names,
        InputProps: {
          className: inputClassName,
          disableUnderline: disableUnderline,
          startAdornment: /*#__PURE__*/_react["default"].createElement(_InputAdornment["default"], {
            position: "start"
          }, /*#__PURE__*/_react["default"].createElement(_IconButton["default"], {
            className: classes.iconButton,
            disabled: disabled ? disabled : disabledStart,
            onClick: function onClick(e) {
              return _this2.changeValue(e, -1, true);
            }
          }, /*#__PURE__*/_react["default"].createElement(_Remove["default"], {
            fontSize: "small"
          }))),
          endAdornment: /*#__PURE__*/_react["default"].createElement(_InputAdornment["default"], {
            position: "end"
          }, /*#__PURE__*/_react["default"].createElement(_IconButton["default"], {
            className: classes.iconButton,
            disabled: disabled ? disabled : disabledEnd,
            onClick: function onClick(e) {
              return _this2.changeValue(e, 1, true);
            }
          }, /*#__PURE__*/_react["default"].createElement(_Add["default"], {
            fontSize: "small"
          })))
        },
        inputProps: {
          style: {
            textAlign: textAlign
          },
          min: min,
          max: max
        }
      });
    }
  }]);
  return NumberTextFieldCustom;
}(_react["default"].Component);

exports.NumberTextFieldCustom = NumberTextFieldCustom;
(0, _defineProperty2["default"])(NumberTextFieldCustom, "propTypes", {
  classes: _propTypes["default"].object.isRequired,
  className: _propTypes["default"].string,
  customValues: _propTypes["default"].array,
  disabled: _propTypes["default"].bool,
  error: _propTypes["default"].bool,
  inputClassName: _propTypes["default"].string,
  helperText: _propTypes["default"].string,
  onChange: _propTypes["default"].func.isRequired,
  onlyIntegersAllowed: _propTypes["default"].bool,
  value: _propTypes["default"].any,
  min: _propTypes["default"].number,
  max: _propTypes["default"].number,
  step: _propTypes["default"].number,
  label: _propTypes["default"].string,
  disableUnderline: _propTypes["default"].bool,
  textAlign: _propTypes["default"].string,
  variant: _propTypes["default"].string,
  type: _propTypes["default"].string
});
(0, _defineProperty2["default"])(NumberTextFieldCustom, "defaultProps", {
  step: 1,
  customValues: [],
  textAlign: 'center',
  variant: 'standard',
  onlyIntegersAllowed: false
});

var _default = (0, _styles.withStyles)(styles)(NumberTextFieldCustom);

exports["default"] = _default;
//# sourceMappingURL=number-text-field-custom.js.map