@kensoni/react-input-number
Version:
Handle input number with React. Support Material UI (MUI)
149 lines (148 loc) • 7.05 kB
JavaScript
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
import { jsx as _jsx } from "react/jsx-runtime";
import { forwardRef, useEffect, useRef, useState } from "react";
import { isCommandKey, isWhiteKeys, revertByChange } from "./utils";
import BigNumber from "@kensoni/big-number";
import useEmitControl from "@kensoni/react-hooks/useEmitControl";
import useForceUpdate from "@kensoni/react-hooks/useForceUpdate";
var InputNumber = forwardRef(function InputNumber(props, ref) {
var value = props.value, format = props.format, comma = props.comma, disableNegative = props.disableNegative, defaultValue = props.defaultValue, formatOnlyBlur = props.formatOnlyBlur, integer = props.integer, onKeyDown = props.onKeyDown, onPaste = props.onPaste, onChange = props.onChange, onFocus = props.onFocus, onBlur = props.onBlur, renderInput = props.renderInput, rest = __rest(props, ["value", "format", "comma", "disableNegative", "defaultValue", "formatOnlyBlur", "integer", "onKeyDown", "onPaste", "onChange", "onFocus", "onBlur", "renderInput"]);
var opt = useRef({ comma: comma });
var focus = useRef(false);
var cursor = useRef(null);
var inputRef = useRef(null);
var shouldUpdate = useRef(false);
var emitChangeInput = useEmitControl(inputRef);
var forceUpdate = useForceUpdate();
var _a = useState(new BigNumber(value !== null && value !== void 0 ? value : '', opt.current)), currentValue = _a[0], setCurrentValue = _a[1];
useEffect(function () {
var newBig = new BigNumber(value !== null && value !== void 0 ? value : '', opt.current);
newBig.value === currentValue.value || setCurrentValue(newBig);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [value]);
useEffect(function () {
if (ref) {
if (typeof ref === 'function') {
ref(inputRef.current);
}
else {
ref.current = inputRef.current;
}
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
useEffect(function () {
var input = inputRef.current;
input && input.setSelectionRange(cursor.current, cursor.current);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [currentValue, value, inputRef, cursor]);
var onKeyDownInput = function (e) {
var _a;
var key = e.key, isNotCommand = !isCommandKey(e);
if (!isWhiteKeys(key, currentValue, comma, disableNegative, integer) && isNotCommand) {
e.preventDefault();
return;
}
if (key === 'ArrowDown' || key === 'ArrowUp') {
e.preventDefault();
var newValue = currentValue.add(new BigNumber(key === 'ArrowDown' ? -1 : 1));
onKeyDown && onKeyDown(e);
emitChangeInput('change', newValue.formatValue);
return;
}
cursor.current = ((_a = e.target.selectionStart) !== null && _a !== void 0 ? _a : 0);
if (isNotCommand)
cursor.current = cursor.current + 1;
shouldUpdate.current = true;
onKeyDown && onKeyDown(e);
};
var onPasteInput = function (e) {
var _a;
var clipboardValue = BigNumber.from(e.clipboardData.getData('text').trim(), opt.current).abs();
var _b = e.target, value = _b.value, selectionStart = _b.selectionStart, selectionEnd = _b.selectionEnd;
var first = value.substring(0, selectionStart !== null && selectionStart !== void 0 ? selectionStart : 0);
var last = value.substring(selectionEnd !== null && selectionEnd !== void 0 ? selectionEnd : 0);
var valClip = clipboardValue.toString();
if (value.includes(format && comma ? ',' : '.')) {
valClip = "".concat(clipboardValue.int).concat(clipboardValue.dec);
}
var val = "".concat(first).concat(valClip).concat(last);
if (val === '') {
e.preventDefault();
return;
}
var sepLenth = Math.floor(BigNumber.from(valClip).int.length / 3);
cursor.current = ((_a = cursor.current) !== null && _a !== void 0 ? _a : 0) + valClip.length + sepLenth - 1;
e.clipboardData.setData('text/plain', valClip);
onPaste && onPaste(e);
};
var onChangeInput = function (e) {
var _a;
var originVal = e.target.value, val = revertByChange(originVal, comma), newValue = new BigNumber(val, opt.current);
e.target.value = newValue.toString();
if (((_a = cursor.current) !== null && _a !== void 0 ? _a : 0) === originVal.length) {
cursor.current = newValue.formatValue.length;
}
if (format && !formatOnlyBlur) {
var dec = comma ? ',' : '.', sep = RegExp("\\".concat(comma ? '.' : ','), 'g');
var oldLength = BigNumber.from(currentValue.toString().split(dec)[0]).formatValue.split(',').length;
var newLength = BigNumber.from(originVal.split(dec)[0].replace(sep, '')).formatValue.split(',').length;
var current = cursor.current;
if (typeof current === 'number' && current > 0 && oldLength < newLength) {
cursor.current = current + 1;
}
}
setCurrentValue(newValue);
onChange && onChange(e);
};
var onFocusInput = function (e) {
focus.current = true;
onFocus && onFocus(e);
format && forceUpdate();
};
var onBlurInput = function (e) {
focus.current = false;
onBlur && onBlur(e);
if (format && formatOnlyBlur && shouldUpdate.current) {
shouldUpdate.current = false;
forceUpdate();
}
};
var inputValue = currentValue.value;
if (format && (!formatOnlyBlur || !focus.current))
inputValue = currentValue.formatValue;
var renderProps = {
onKeyDown: onKeyDownInput,
onPaste: onPasteInput,
onChange: onChangeInput,
onFocus: onFocusInput,
onBlur: onBlurInput,
value: inputValue,
type: 'text',
};
if (renderInput)
return renderInput(renderProps, inputRef);
return _jsx("input", __assign({}, rest, renderProps, { ref: inputRef }));
});
export default InputNumber;