UNPKG

@kensoni/react-input-number

Version:

Handle input number with React. Support Material UI (MUI)

149 lines (148 loc) 7.05 kB
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;