Skip to content

Commit 30be362

Browse files
committed
fix(input-number): implement precision prop to fix floating point errors
The precision prop was defined in types but never used. Arithmetic like 3.14 + 0.1 produced 3.2400000000000002. Now rounds results to the specified decimal precision.
1 parent 25a7652 commit 30be362

3 files changed

Lines changed: 31 additions & 4 deletions

File tree

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<demo>
2+
3+
### Precision
4+
5+
Set decimal precision with `precision`, and use `controls` to always show step buttons.
6+
7+
```jsx live
8+
() => {
9+
return (
10+
<div style={{ display: 'flex', gap: '16px' }}>
11+
<InputNumber defaultValue={3.14} precision={2} step={0.1} min={0} max={10} controls />
12+
<InputNumber defaultValue={100} precision={0} step={10} min={0} max={1000} controls />
13+
</div>
14+
);
15+
}
16+
```
17+
18+
</demo>

components/input-number/index.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import Basic from './demo/basic.md'
22
import Size from './demo/size.md'
33
import Disabled from './demo/disabled.md'
4+
import Precision from './demo/precision.md'
45

56
# Input Number
67

@@ -25,6 +26,7 @@ import { InputNumber } from 'tiny-ui';
2526
</column>
2627
<column>
2728
<Size/>
29+
<Precision/>
2830
</column>
2931
</layout>
3032

components/input-number/index.tsx

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,18 @@ const isValid = (val: string | number): boolean => {
1313
return !isNaN(+val);
1414
};
1515

16+
const toPrecision = (val: number, precision?: number): number => {
17+
if (precision === undefined) return val;
18+
return parseFloat(val.toFixed(precision));
19+
};
20+
1621
const InputNumber = React.forwardRef<HTMLDivElement, InputNumberProps>((props, ref) => {
1722
const {
1823
size = 'md',
1924
disabled = false,
2025
defaultValue = 0,
2126
step = 1,
27+
precision,
2228
controls = false,
2329
min = Number.NEGATIVE_INFINITY,
2430
max = Number.POSITIVE_INFINITY,
@@ -39,15 +45,16 @@ const InputNumber = React.forwardRef<HTMLDivElement, InputNumberProps>((props, r
3945
);
4046

4147
const inputOnChange = (e: React.ChangeEvent<HTMLInputElement>): void => {
42-
const val = Number(e.target.value.trim());
48+
const raw = Number(e.target.value.trim());
49+
const val = toPrecision(raw, precision);
4350
!('value' in props) && setValue(val);
4451
onChange && isValid(val) && onChange(val, e);
4552
};
4653

4754
const plusOnClick = (e: MouseEvent<HTMLSpanElement>): void => {
4855
e.stopPropagation();
4956
if (!disabled && isValid(step)) {
50-
const val = +value + +step;
57+
const val = toPrecision(+value + +step, precision);
5158
if (val <= max) {
5259
!('value' in props) && setValue(val);
5360
onChange && onChange(val, e);
@@ -58,7 +65,7 @@ const InputNumber = React.forwardRef<HTMLDivElement, InputNumberProps>((props, r
5865
const minusOnClick = (e: MouseEvent<HTMLSpanElement>): void => {
5966
e.stopPropagation();
6067
if (!disabled && isValid(step)) {
61-
const val = +value - +step;
68+
const val = toPrecision(+value - +step, precision);
6269
if (val >= min) {
6370
!('value' in props) && setValue(val);
6471
onChange && onChange(val, e);
@@ -75,7 +82,7 @@ const InputNumber = React.forwardRef<HTMLDivElement, InputNumberProps>((props, r
7582
<input
7683
autoComplete="off"
7784
disabled={disabled}
78-
value={value}
85+
value={precision !== undefined ? value.toFixed(precision) : value}
7986
type="number"
8087
className={`${prefixCls}__input`}
8188
max={max}

0 commit comments

Comments
 (0)