From 3c8ca0dc11f94a5dbc9de559cc16be993fdaf0b3 Mon Sep 17 00:00:00 2001
From: Austin Wildgrube <40448411+AustinWildgrube@users.noreply.github.com>
Date: Wed, 8 May 2024 04:42:21 -0500
Subject: [PATCH] [@mantine/core] NumberInput: Fix incorrect `allowNegative`
handling with up/down arrows (#6170)
---
.../src/components/NumberInput/NumberInput.test.tsx | 13 +++++++++++++
.../core/src/components/NumberInput/NumberInput.tsx | 5 +++--
2 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/packages/@mantine/core/src/components/NumberInput/NumberInput.test.tsx b/packages/@mantine/core/src/components/NumberInput/NumberInput.test.tsx
index c5aefc450f..adf6430021 100644
--- a/packages/@mantine/core/src/components/NumberInput/NumberInput.test.tsx
+++ b/packages/@mantine/core/src/components/NumberInput/NumberInput.test.tsx
@@ -18,6 +18,9 @@ const defaultProps: NumberInputProps = {
const clickIncrement = (container: HTMLElement) =>
userEvent.click(container.querySelector('.mantine-NumberInput-control[data-direction="up"]')!);
+const clickDecrement = (container: HTMLElement) =>
+ userEvent.click(container.querySelector('.mantine-NumberInput-control[data-direction="down"]')!);
+
const getInput = () => screen.getByRole('textbox');
const enterText = (text: string) => userEvent.type(getInput(), text);
const expectValue = (value: string) => expect(getInput()).toHaveValue(value);
@@ -176,4 +179,14 @@ describe('@mantine/core/NumberInput', () => {
expect(spy).toHaveBeenLastCalledWith(0);
});
+
+ it('does not allow negative numbers if the allowNegative prop is false', async () => {
+ const spy = jest.fn();
+ const { container } = render();
+
+ await clickDecrement(container);
+
+ expectValue('0');
+ expect(spy).toHaveBeenLastCalledWith(0);
+ });
});
diff --git a/packages/@mantine/core/src/components/NumberInput/NumberInput.tsx b/packages/@mantine/core/src/components/NumberInput/NumberInput.tsx
index 94df3bba30..89d67f918a 100644
--- a/packages/@mantine/core/src/components/NumberInput/NumberInput.tsx
+++ b/packages/@mantine/core/src/components/NumberInput/NumberInput.tsx
@@ -290,16 +290,17 @@ export const NumberInput = factory((_props, ref) => {
const decrementRef = useRef<() => void>();
decrementRef.current = () => {
let val: number;
+ const minValue = min !== undefined ? min : !allowNegative ? 0 : Number.MIN_SAFE_INTEGER;
const currentValuePrecision = getDecimalPlaces(_value);
const stepPrecision = getDecimalPlaces(step!);
const maxPrecision = Math.max(currentValuePrecision, stepPrecision);
const factor = 10 ** maxPrecision;
if (typeof _value !== 'number' || Number.isNaN(_value)) {
- val = clamp(startValue!, min, max);
+ val = clamp(startValue!, minValue, max);
} else {
const decrementedValue = (Math.round(_value * factor) - Math.round(step! * factor)) / factor;
- val = min !== undefined && decrementedValue < min ? min : decrementedValue;
+ val = minValue !== undefined && decrementedValue < minValue ? minValue : decrementedValue;
}
const formattedValue = val.toFixed(maxPrecision);