Skip to content

Commit 37f1ed2

Browse files
committed
store prev value and pass to parser/formatter callbacks
1 parent 121606e commit 37f1ed2

1 file changed

Lines changed: 14 additions & 37 deletions

File tree

src/InputNumber.tsx

Lines changed: 14 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -44,20 +44,6 @@ const getDecimalIfValidate = (value: ValueType) => {
4444
return decimal.isInvalidate() ? null : decimal;
4545
};
4646

47-
const inputDiff=(str1: string, str2: string) =>{
48-
const maxLength = Math.max(str1.length, str2.length);
49-
let diff = '';
50-
51-
for (let i = 0; i < maxLength; i++) {
52-
if (str1[i] !== str2[i]) {
53-
if (str1[i]) diff += str1[i];
54-
if (str2[i]) diff += str2[i];
55-
}
56-
}
57-
58-
return diff;
59-
}
60-
6147
export interface InputNumberProps<T extends ValueType = ValueType>
6248
extends Omit<
6349
React.InputHTMLAttributes<HTMLInputElement>,
@@ -100,9 +86,9 @@ export interface InputNumberProps<T extends ValueType = ValueType>
10086
wheel?: boolean;
10187

10288
/** Parse display value to validate number */
103-
parser?: (displayValue: string | undefined) => T;
89+
parser?: (displayValue: string | undefined, info: { prevValue: string }) => T;
10490
/** Transform `value` to display value show in input */
105-
formatter?: (value: T | undefined, info: { userTyping: boolean; input: string }) => string;
91+
formatter?: (value: T | undefined, info: { userTyping: boolean; input: string, prevValue: string }) => string;
10692
/** Syntactic sugar of `formatter`. Config precision of display. */
10793
precision?: number;
10894
/** Syntactic sugar of `formatter`. Config decimal separator of display. */
@@ -185,7 +171,10 @@ const InternalInputNumber = React.forwardRef(
185171
}
186172
}
187173

188-
// ====================== Parser & Formatter ======================
174+
175+
const prevValueRef = React.useRef<string | number>('');
176+
177+
// ====================== Formatter ======================
189178
/**
190179
* `precision` is used for formatter & onChange.
191180
* It will auto generate by `value` & `step`.
@@ -218,7 +207,7 @@ const InternalInputNumber = React.forwardRef(
218207
const numStr = String(num);
219208

220209
if (parser) {
221-
return parser(numStr);
210+
return parser(numStr, { prevValue: String(prevValueRef.current) });
222211
}
223212

224213
let parsedStr = numStr;
@@ -237,7 +226,7 @@ const InternalInputNumber = React.forwardRef(
237226
const mergedFormatter = React.useCallback(
238227
(number: string, userTyping: boolean) => {
239228
if (formatter) {
240-
return formatter(number, { userTyping, input: String(inputValueRef.current) });
229+
return formatter(number, { userTyping, input: String(inputValueRef.current), prevValue: String(prevValueRef.current) });
241230
}
242231

243232
let str = typeof number === 'number' ? num2str(number) : number;
@@ -276,7 +265,11 @@ const InternalInputNumber = React.forwardRef(
276265
}
277266
return mergedFormatter(decimalValue.toString(), false);
278267
});
279-
inputValueRef.current = inputValue;
268+
269+
React.useEffect(() => {
270+
prevValueRef.current = inputValueRef.current;
271+
inputValueRef.current = inputValue;
272+
}, [inputValue]);
280273

281274
// Should always be string
282275
function setInputValue(newValue: DecimalClass, userTyping: boolean) {
@@ -396,26 +389,10 @@ const InternalInputNumber = React.forwardRef(
396389
const collectInputValue = (inputStr: string) => {
397390
recordCursor();
398391

399-
// checks what are the diffs between the current state and the input value
400-
const diff = inputDiff(inputStr, String(inputValue));
401-
402-
// if only one change is present, check if it is a comma
403-
if (diff.length === 1) {
404-
// if it is a comma, do not update the input value
405-
if (diff[0] === ',') {
406-
return;
407-
}
408-
}
409-
410-
// Only allow input number characters and precision decimals if specified
411-
const precisionRegex = precision ? `{0,${precision}}` : '*';
412-
const regex = RegExp(`^-?\\d{1,3}(?:,\\d{3})*\.?\\d${precisionRegex}$`,'g');
413-
if (inputStr!== '' && !regex.test(inputStr)) {
414-
return;
415-
}
416392

417393
// Update inputValue in case input can not parse as number
418394
// Refresh ref value immediately since it may used by formatter
395+
prevValueRef.current = inputValueRef.current
419396
inputValueRef.current = inputStr;
420397
setInternalInputValue(inputStr);
421398

0 commit comments

Comments
 (0)