Skip to content

Commit 081a47a

Browse files
authored
[@mantine/core] NumberInput: Fix incorrect increment/decrement functions logic when step is a float value (#5926)
* [@mantine/core] fix numberinput increment bug * fix stype bug
1 parent 1e84a97 commit 081a47a

File tree

1 file changed

+27
-32
lines changed

1 file changed

+27
-32
lines changed

packages/@mantine/core/src/components/NumberInput/NumberInput.tsx

+27-32
Original file line numberDiff line numberDiff line change
@@ -38,31 +38,6 @@ function isValidNumber(value: number | string | undefined): value is number {
3838
);
3939
}
4040

41-
interface GetDecrementedValueInput {
42-
value: number;
43-
min: number | undefined;
44-
step: number | undefined;
45-
allowNegative: boolean | undefined;
46-
}
47-
48-
function getDecrementedValue({ value, min, step = 1, allowNegative }: GetDecrementedValueInput) {
49-
const nextValue = value - step;
50-
51-
if (min !== undefined && nextValue < min) {
52-
return min;
53-
}
54-
55-
if (!allowNegative && nextValue < 0 && min === undefined) {
56-
return value;
57-
}
58-
59-
if (min !== undefined && min >= 0 && nextValue <= min) {
60-
return nextValue;
61-
}
62-
63-
return nextValue;
64-
}
65-
6641
function isInRange(value: number | undefined, min: number | undefined, max: number | undefined) {
6742
if (value === undefined) {
6843
return true;
@@ -266,38 +241,58 @@ export const NumberInput = factory<NumberInputFactory>((_props, ref) => {
266241
onValueChange?.(payload, event);
267242
};
268243

244+
const getDecimalPlaces = (inputValue: number | string): number => {
245+
const match = String(inputValue).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);
246+
if (!match) {
247+
return 0;
248+
}
249+
return Math.max(0, (match[1] ? match[1].length : 0) - (match[2] ? +match[2] : 0));
250+
};
251+
269252
const incrementRef = useRef<() => void>();
270253
incrementRef.current = () => {
271254
let val: number;
255+
const currentValuePrecision = getDecimalPlaces(_value);
256+
const stepPrecision = getDecimalPlaces(step!);
257+
const maxPrecision = Math.max(currentValuePrecision, stepPrecision);
258+
const factor = 10 ** maxPrecision;
272259

273260
if (typeof _value !== 'number' || Number.isNaN(_value)) {
274261
val = clamp(startValue!, min, max);
275262
} else if (max !== undefined) {
276-
val = _value + step! <= max ? _value + step! : max;
263+
const incrementedValue = (Math.round(_value * factor) + Math.round(step! * factor)) / factor;
264+
val = incrementedValue <= max ? incrementedValue : max;
277265
} else {
278-
val = _value + step!;
266+
val = (Math.round(_value * factor) + Math.round(step! * factor)) / factor;
279267
}
280268

281-
setValue(val);
269+
const formattedValue = val.toFixed(maxPrecision);
270+
setValue(parseFloat(formattedValue));
282271
onValueChange?.(
283-
{ floatValue: val, formattedValue: val.toString(), value: val.toString() },
272+
{ floatValue: parseFloat(formattedValue), formattedValue, value: formattedValue },
284273
{ source: 'increment' as any }
285274
);
286275
};
287276

288277
const decrementRef = useRef<() => void>();
289278
decrementRef.current = () => {
290279
let val: number;
280+
const currentValuePrecision = getDecimalPlaces(_value);
281+
const stepPrecision = getDecimalPlaces(step!);
282+
const maxPrecision = Math.max(currentValuePrecision, stepPrecision);
283+
const factor = 10 ** maxPrecision;
291284

292285
if (typeof _value !== 'number' || Number.isNaN(_value)) {
293286
val = clamp(startValue!, min, max);
294287
} else {
295-
val = getDecrementedValue({ value: _value, min, step, allowNegative });
288+
const decrementedValue = (Math.round(_value * factor) - Math.round(step! * factor)) / factor;
289+
val = min !== undefined && decrementedValue < min ? min : decrementedValue;
296290
}
297291

298-
setValue(val);
292+
const formattedValue = val.toFixed(maxPrecision);
293+
setValue(parseFloat(formattedValue));
299294
onValueChange?.(
300-
{ floatValue: val, formattedValue: val.toString(), value: val.toString() },
295+
{ floatValue: parseFloat(formattedValue), formattedValue, value: formattedValue },
301296
{ source: 'decrement' as any }
302297
);
303298
};

0 commit comments

Comments
 (0)