Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[@mantine/core] NumberInput: implement parsePrecision function #2638

Merged
merged 2 commits into from Oct 11, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
24 changes: 24 additions & 0 deletions src/mantine-core/src/NumberInput/NumberInput.test.tsx
Expand Up @@ -141,6 +141,30 @@ describe('@mantine/core/NumberInput', () => {
expect(spy).toHaveBeenLastCalledWith(6.123);
});

it('supports removing trailing zero with increment/decrement', async () => {
const spy = jest.fn();
const { container } = render(
<NumberInput
defaultValue={0.05}
removeTrailingZeros
precision={2}
min={-1}
step={0.05}
max={1}
onChange={spy}
/>
);
await clickIncrement(container);
expectValue('0.1');
expect(spy).toHaveBeenLastCalledWith(0.1);
await clickDecrement(container);
expectValue('0.05');
expect(spy).toHaveBeenLastCalledWith(0.05);
await clickDecrement(container);
expectValue('0');
expect(spy).toHaveBeenLastCalledWith(0);
});

it('supports removing trailing zeros and decimal separator with precision', async () => {
const spy = jest.fn();
render(<NumberInput precision={8} removeTrailingZeros onChange={spy} />);
Expand Down
46 changes: 23 additions & 23 deletions src/mantine-core/src/NumberInput/NumberInput.tsx
Expand Up @@ -165,13 +165,27 @@ export const NumberInput = forwardRef<HTMLInputElement, NumberInputProps>((props
{ classNames, styles, unstyled, name: 'NumberInput' }
);

const parsePrecision = (val: number | undefined) => {
if (val === undefined) return undefined;

let result = val.toFixed(precision);
if (removeTrailingZeros && precision > 0) {
result = result.replace(new RegExp(`[0]{0,${precision}}$`), '');
if (result.endsWith('.') || result.endsWith(decimalSeparator)) {
result = result.slice(0, -1);
}
}

return result;
};

const [focused, setFocused] = useState(false);
const [_value, setValue] = useState(
typeof value === 'number' ? value : typeof defaultValue === 'number' ? defaultValue : undefined
);
const finalValue = typeof value === 'number' ? value : _value;
const [tempValue, setTempValue] = useState(
typeof finalValue === 'number' ? finalValue.toFixed(precision) : ''
typeof finalValue === 'number' ? parsePrecision(finalValue) : ''
);
const inputRef = useRef<HTMLInputElement>();
const handleValueChange = (val: number | undefined) => {
Expand Down Expand Up @@ -208,9 +222,9 @@ export const NumberInput = forwardRef<HTMLInputElement, NumberInputProps>((props
incrementRef.current = () => {
if (_value === undefined) {
handleValueChange(startValue ?? min ?? 0);
setTempValue(startValue?.toFixed(precision) ?? min?.toFixed(precision) ?? '0');
setTempValue(parsePrecision(startValue) ?? parsePrecision(min) ?? '0');
} else {
const result = clamp(_value + step, _min, _max).toFixed(precision);
const result = parsePrecision(clamp(_value + step, _min, _max));

handleValueChange(parseFloat(result));
setTempValue(result);
Expand All @@ -221,9 +235,9 @@ export const NumberInput = forwardRef<HTMLInputElement, NumberInputProps>((props
decrementRef.current = () => {
if (_value === undefined) {
handleValueChange(startValue ?? min ?? 0);
setTempValue(startValue?.toFixed(precision) ?? min?.toFixed(precision) ?? '0');
setTempValue(parsePrecision(startValue) ?? parsePrecision(min) ?? '0');
} else {
const result = clamp(_value - step, _min, _max).toFixed(precision);
const result = parsePrecision(clamp(_value - step, _min, _max));
handleValueChange(parseFloat(result));
setTempValue(result);
}
Expand All @@ -234,7 +248,7 @@ export const NumberInput = forwardRef<HTMLInputElement, NumberInputProps>((props
useEffect(() => {
if (typeof value === 'number' && !focused) {
setValue(value);
setTempValue(value.toFixed(precision));
setTempValue(parsePrecision(value));
}
if (defaultValue === undefined && value === undefined && !focused) {
setValue(value);
Expand Down Expand Up @@ -359,25 +373,11 @@ export const NumberInput = forwardRef<HTMLInputElement, NumberInputProps>((props

if (!Number.isNaN(val)) {
if (!noClampOnBlur) {
if (removeTrailingZeros) {
const valNoZeros = val
.toFixed(precision)
.replace(new RegExp(`[0]{0,${precision}}$`), '');

if (valNoZeros.endsWith(decimalSeparator) || valNoZeros.endsWith('.')) {
setTempValue(valNoZeros.slice(0, -1));
handleValueChange(parseFloat(valNoZeros.slice(0, -1)));
} else {
setTempValue(valNoZeros);
handleValueChange(parseFloat(valNoZeros));
}
} else {
setTempValue(val.toFixed(precision));
handleValueChange(parseFloat(val.toFixed(precision)));
}
setTempValue(parsePrecision(val));
handleValueChange(parseFloat(parsePrecision(val)));
}
} else {
setTempValue(finalValue?.toFixed(precision) ?? '');
setTempValue(parsePrecision(finalValue) ?? '');
}
}

Expand Down