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);