Skip to content

Commit 41cac30

Browse files
committed
fix: number is duplicate when input number by keyboard's numeric keypad in Chrome
1 parent 4470642 commit 41cac30

File tree

2 files changed

+78
-0
lines changed

2 files changed

+78
-0
lines changed

src/InputNumber.tsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ const InternalInputNumber = React.forwardRef(
160160
const userTypingRef = React.useRef(false);
161161
const compositionRef = React.useRef(false);
162162
const shiftKeyRef = React.useRef(false);
163+
const imeCompositionRef = React.useRef(false);
163164

164165
// ============================ Value =============================
165166
// Real value control
@@ -428,6 +429,9 @@ const InternalInputNumber = React.forwardRef(
428429

429430
// >>> Input
430431
const onInternalInput: React.ChangeEventHandler<HTMLInputElement> = (e) => {
432+
if (imeCompositionRef.current && !compositionRef.current) {
433+
return;
434+
}
431435
collectInputValue(e.target.value);
432436
};
433437

@@ -498,6 +502,12 @@ const InternalInputNumber = React.forwardRef(
498502

499503
shiftKeyRef.current = shiftKey;
500504

505+
if (event.key === 'Process' || compositionRef.current) {
506+
imeCompositionRef.current = true;
507+
} else {
508+
imeCompositionRef.current = false;
509+
}
510+
501511
if (key === 'Enter') {
502512
if (!compositionRef.current) {
503513
userTypingRef.current = false;
@@ -543,6 +553,8 @@ const InternalInputNumber = React.forwardRef(
543553

544554
// >>> Focus & Blur
545555
const onBlur = () => {
556+
imeCompositionRef.current = false;
557+
546558
if (changeOnBlur) {
547559
flushInputValue(false);
548560
}

tests/formatter.test.tsx

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,72 @@ describe('InputNumber.Formatter', () => {
6363
expect(onChange).toHaveBeenCalledWith(100);
6464
});
6565

66+
it('formatter on IME numeric keypad input', () => {
67+
const { container } = render(
68+
<InputNumber formatter={(value) => `${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')} />
69+
);
70+
const input = container.querySelector('input');
71+
fireEvent.focus(input);
72+
fireEvent.compositionStart(input);
73+
fireEvent.keyDown(input, {
74+
which: 229,
75+
key: 'Process',
76+
code: 'Numpad1',
77+
keyCode: 229,
78+
composed: true,
79+
});
80+
fireEvent.change(input, { target: { value: '1' } });
81+
fireEvent.keyDown(input, {
82+
which: 229,
83+
key: 'Process',
84+
code: 'Numpad2',
85+
keyCode: 229,
86+
composed: true,
87+
});
88+
fireEvent.change(input, { target: { value: '12' } });
89+
fireEvent.keyDown(input, {
90+
which: 229,
91+
key: 'Process',
92+
code: 'Numpad3',
93+
keyCode: 229,
94+
composed: true,
95+
});
96+
fireEvent.change(input, { target: { value: '123' } });
97+
fireEvent.keyDown(input, {
98+
which: 229,
99+
key: 'Process',
100+
code: 'Numpad4',
101+
keyCode: 229,
102+
composed: true,
103+
});
104+
fireEvent.change(input, { target: { value: '1234' } });
105+
fireEvent.keyDown(input, {
106+
which: 229,
107+
key: 'Process',
108+
code: 'Enter',
109+
keyCode: 229,
110+
composed: true,
111+
});
112+
fireEvent.compositionEnd(input);
113+
fireEvent.blur(input);
114+
expect(input.value).toEqual('1,234');
115+
116+
fireEvent.focus(input);
117+
fireEvent.compositionStart(input);
118+
fireEvent.keyDown(input, {
119+
which: 229,
120+
key: 'Process',
121+
code: 'Numpad5',
122+
keyCode: 229,
123+
composed: true,
124+
});
125+
fireEvent.change(input, { target: { value: '12345' } });
126+
fireEvent.compositionEnd(input);
127+
fireEvent.change(input, { target: { value: '1234' } });
128+
fireEvent.blur(input);
129+
expect(input.value).toEqual('12,345');
130+
});
131+
66132
it('formatter and parser', () => {
67133
const onChange = jest.fn();
68134
const { container } = render(

0 commit comments

Comments
 (0)