UNPKG

rsuite

Version:

A suite of react components

319 lines (262 loc) 10.8 kB
"use strict"; var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard"); var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); exports.__esModule = true; exports.default = void 0; var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); var _objectWithoutPropertiesLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutPropertiesLoose")); var _react = _interopRequireWildcard(require("react")); var _propTypes = _interopRequireDefault(require("prop-types")); var _isNil = _interopRequireDefault(require("lodash/isNil")); var _AngleUp = _interopRequireDefault(require("@rsuite/icons/legacy/AngleUp")); var _AngleDown = _interopRequireDefault(require("@rsuite/icons/legacy/AngleDown")); var _on = _interopRequireDefault(require("dom-lib/on")); var _InputGroup = _interopRequireDefault(require("../InputGroup/InputGroup")); var _InputGroupAddon = _interopRequireDefault(require("../InputGroup/InputGroupAddon")); var _Input = _interopRequireDefault(require("../Input")); var _Button = _interopRequireDefault(require("../Button")); var _utils = require("../utils"); /** * Check if the value is a number. * @param value */ var isNumber = function isNumber(value) { return /(^-?|^\+?|^\d?)\d*\.\d+$/.test(value + ''); }; /** * Get the length of the decimal. * @param value */ function getDecimalLength(value) { if (isNumber(value)) { return value.toString().split('.')[1].length; } return 0; } /** * Get the value after the decimal point. * @param values */ function decimals() { for (var _len = arguments.length, values = new Array(_len), _key = 0; _key < _len; _key++) { values[_key] = arguments[_key]; } var lengths = values.map(getDecimalLength); return Math.max.apply(Math, lengths); } /** * Disable the upper limit of the number. * @param value * @param max */ function valueReachesMax(value, max) { if (!(0, _isNil.default)(value)) { return +value >= max; } return false; } /** * Disable the lower limit of the number. * @param value * @param min */ function valueReachesMin(value, min) { if (!(0, _isNil.default)(value)) { return +value <= min; } return false; } var InputNumber = /*#__PURE__*/_react.default.forwardRef(function (props, ref) { var _props$as = props.as, Component = _props$as === void 0 ? _InputGroup.default : _props$as, className = props.className, _props$classPrefix = props.classPrefix, classPrefix = _props$classPrefix === void 0 ? 'input-number' : _props$classPrefix, disabled = props.disabled, readOnly = props.readOnly, plaintext = props.plaintext, valueProp = props.value, defaultValue = props.defaultValue, size = props.size, prefixElement = props.prefix, postfix = props.postfix, _props$step = props.step, step = _props$step === void 0 ? 1 : _props$step, _props$buttonAppearan = props.buttonAppearance, buttonAppearance = _props$buttonAppearan === void 0 ? 'subtle' : _props$buttonAppearan, minProp = props.min, maxProp = props.max, _props$scrollable = props.scrollable, scrollable = _props$scrollable === void 0 ? true : _props$scrollable, onChange = props.onChange, onWheel = props.onWheel, restProps = (0, _objectWithoutPropertiesLoose2.default)(props, ["as", "className", "classPrefix", "disabled", "readOnly", "plaintext", "value", "defaultValue", "size", "prefix", "postfix", "step", "buttonAppearance", "min", "max", "scrollable", "onChange", "onWheel"]); var min = minProp !== null && minProp !== void 0 ? minProp : -Infinity; var max = maxProp !== null && maxProp !== void 0 ? maxProp : Infinity; var _useControlled = (0, _utils.useControlled)(valueProp, defaultValue), value = _useControlled[0], setValue = _useControlled[1]; var _useClassNames = (0, _utils.useClassNames)(classPrefix), withClassPrefix = _useClassNames.withClassPrefix, merge = _useClassNames.merge, prefix = _useClassNames.prefix; var classes = merge(className, withClassPrefix()); var _partitionHTMLProps = (0, _utils.partitionHTMLProps)(restProps), htmlInputProps = _partitionHTMLProps[0], rest = _partitionHTMLProps[1]; var inputRef = (0, _react.useRef)(); var handleChangeValue = (0, _react.useCallback)(function (currentValue, event) { if (currentValue !== value) { setValue(currentValue); onChange === null || onChange === void 0 ? void 0 : onChange(currentValue, event); } }, [onChange, setValue, value]); var getSafeValue = (0, _react.useCallback)(function (value) { if (!Number.isNaN(value)) { if (+value > max) { value = max; } if (+value < min) { value = min; } } else { value = ''; } return value.toString(); }, [max, min]); // Increment value by step var handleStepUp = (0, _react.useCallback)(function (event) { var val = +(value || 0); var bit = decimals(val, step); handleChangeValue(getSafeValue((val + step).toFixed(bit)), event); }, [getSafeValue, handleChangeValue, step, value]); // Decrement value by step var handleStepDown = (0, _react.useCallback)(function (event) { var val = +(value || 0); var bit = decimals(val, step); handleChangeValue(getSafeValue((val - step).toFixed(bit)), event); }, [getSafeValue, handleChangeValue, step, value]); // Disables step up/down button when // - InputNumber is disabled/readonly // - value reaches max/min limits var stepUpDisabled = disabled || readOnly || valueReachesMax(value, max); var stepDownDisabled = disabled || readOnly || valueReachesMin(value, min); var handleKeyDown = (0, _react.useCallback)(function (event) { switch (event.key) { case _utils.KEY_VALUES.UP: event.preventDefault(); handleStepUp(event); break; case _utils.KEY_VALUES.DOWN: event.preventDefault(); handleStepDown(event); break; case _utils.KEY_VALUES.HOME: if (typeof minProp !== 'undefined') { event.preventDefault(); handleChangeValue(getSafeValue(minProp), event); } break; case _utils.KEY_VALUES.END: if (typeof maxProp !== 'undefined') { event.preventDefault(); handleChangeValue(getSafeValue(maxProp), event); } break; } }, [handleStepUp, handleStepDown, minProp, maxProp, handleChangeValue, getSafeValue]); var handleWheel = (0, _react.useCallback)(function (event) { if (!disabled && !readOnly && event.target === document.activeElement) { event.preventDefault(); var delta = event['wheelDelta'] || -event.deltaY || -(event === null || event === void 0 ? void 0 : event.detail); if (delta > 0) { handleStepDown(event); } if (delta < 0) { handleStepUp(event); } } onWheel === null || onWheel === void 0 ? void 0 : onWheel(event); }, [disabled, handleStepDown, handleStepUp, onWheel, readOnly]); var handleChange = (0, _react.useCallback)(function (value, event) { if (!/^-?(?:\d+)?(\.)?\d*$/.test(value) && value !== '') { return; } handleChangeValue(value, event); }, [handleChangeValue]); var handleBlur = (0, _react.useCallback)(function (event) { var _event$target; var targetValue = Number.parseFloat((_event$target = event.target) === null || _event$target === void 0 ? void 0 : _event$target.value); handleChangeValue(getSafeValue(targetValue), event); }, [getSafeValue, handleChangeValue]); (0, _react.useEffect)(function () { var wheelListener; if (inputRef.current && scrollable) { wheelListener = (0, _on.default)(inputRef.current, 'wheel', handleWheel, { passive: false }); } return function () { var _wheelListener; (_wheelListener = wheelListener) === null || _wheelListener === void 0 ? void 0 : _wheelListener.off(); }; }, [handleWheel, scrollable]); var input = /*#__PURE__*/_react.default.createElement(_Input.default, (0, _extends2.default)({}, htmlInputProps, { type: "number", autoComplete: "off", step: step, inputRef: inputRef, onChange: handleChange, onBlur: (0, _utils.createChainedFunction)(handleBlur, htmlInputProps === null || htmlInputProps === void 0 ? void 0 : htmlInputProps.onBlur), value: (0, _isNil.default)(value) ? '' : "" + value, disabled: disabled, readOnly: readOnly, plaintext: plaintext, ref: plaintext ? ref : undefined, onKeyDown: handleKeyDown })); if (plaintext) { return input; } return /*#__PURE__*/_react.default.createElement(Component, (0, _extends2.default)({}, rest, { ref: ref, className: classes, disabled: disabled, size: size }), prefixElement && /*#__PURE__*/_react.default.createElement(_InputGroupAddon.default, null, prefixElement), input, /*#__PURE__*/_react.default.createElement("span", { className: prefix('btn-group-vertical') }, /*#__PURE__*/_react.default.createElement(_Button.default, { tabIndex: -1, appearance: buttonAppearance, className: prefix('touchspin-up'), onClick: handleStepUp, disabled: stepUpDisabled, "aria-label": "Increment" }, /*#__PURE__*/_react.default.createElement(_AngleUp.default, null)), /*#__PURE__*/_react.default.createElement(_Button.default, { tabIndex: -1, appearance: buttonAppearance, className: prefix('touchspin-down'), onClick: handleStepDown, disabled: stepDownDisabled, "aria-label": "Decrement" }, /*#__PURE__*/_react.default.createElement(_AngleDown.default, null))), postfix && /*#__PURE__*/_react.default.createElement(_InputGroupAddon.default, null, postfix)); }); InputNumber.displayName = 'InputNumber'; InputNumber.propTypes = { className: _propTypes.default.string, classPrefix: _propTypes.default.string, min: _propTypes.default.number, max: _propTypes.default.number, step: _propTypes.default.number, value: _propTypes.default.oneOfType([_propTypes.default.number, _propTypes.default.string]), defaultValue: _propTypes.default.oneOfType([_propTypes.default.number, _propTypes.default.string]), prefix: _propTypes.default.node, postfix: _propTypes.default.node, disabled: _propTypes.default.bool, readOnly: _propTypes.default.bool, plaintext: _propTypes.default.bool, scrollable: _propTypes.default.bool, size: _propTypes.default.oneOf(['lg', 'md', 'sm', 'xs']), buttonAppearance: _propTypes.default.oneOf(['default', 'primary', 'link', 'subtle', 'ghost']), onWheel: _propTypes.default.func, onChange: _propTypes.default.func }; var _default = InputNumber; exports.default = _default;