diff --git a/src/InputNumber.tsx b/src/InputNumber.tsx index 969e97e2..73e2643f 100644 --- a/src/InputNumber.tsx +++ b/src/InputNumber.tsx @@ -160,6 +160,7 @@ const InternalInputNumber = React.forwardRef( const userTypingRef = React.useRef(false); const compositionRef = React.useRef(false); const shiftKeyRef = React.useRef(false); + const imeCompositionRef = React.useRef(false); // ============================ Value ============================= // Real value control @@ -428,6 +429,9 @@ const InternalInputNumber = React.forwardRef( // >>> Input const onInternalInput: React.ChangeEventHandler = (e) => { + if (imeCompositionRef.current && !compositionRef.current) { + return; + } collectInputValue(e.target.value); }; @@ -498,6 +502,12 @@ const InternalInputNumber = React.forwardRef( shiftKeyRef.current = shiftKey; + if (event.key === 'Process' || compositionRef.current) { + imeCompositionRef.current = true; + } else { + imeCompositionRef.current = false; + } + if (key === 'Enter') { if (!compositionRef.current) { userTypingRef.current = false; @@ -543,6 +553,8 @@ const InternalInputNumber = React.forwardRef( // >>> Focus & Blur const onBlur = () => { + imeCompositionRef.current = false; + if (changeOnBlur) { flushInputValue(false); } diff --git a/tests/formatter.test.tsx b/tests/formatter.test.tsx index 1947de7d..456fd054 100644 --- a/tests/formatter.test.tsx +++ b/tests/formatter.test.tsx @@ -63,6 +63,72 @@ describe('InputNumber.Formatter', () => { expect(onChange).toHaveBeenCalledWith(100); }); + it('formatter on IME numeric keypad input', () => { + const { container } = render( + `${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')} /> + ); + const input = container.querySelector('input'); + fireEvent.focus(input); + fireEvent.compositionStart(input); + fireEvent.keyDown(input, { + which: 229, + key: 'Process', + code: 'Numpad1', + keyCode: 229, + composed: true, + }); + fireEvent.change(input, { target: { value: '1' } }); + fireEvent.keyDown(input, { + which: 229, + key: 'Process', + code: 'Numpad2', + keyCode: 229, + composed: true, + }); + fireEvent.change(input, { target: { value: '12' } }); + fireEvent.keyDown(input, { + which: 229, + key: 'Process', + code: 'Numpad3', + keyCode: 229, + composed: true, + }); + fireEvent.change(input, { target: { value: '123' } }); + fireEvent.keyDown(input, { + which: 229, + key: 'Process', + code: 'Numpad4', + keyCode: 229, + composed: true, + }); + fireEvent.change(input, { target: { value: '1234' } }); + fireEvent.keyDown(input, { + which: 229, + key: 'Process', + code: 'Enter', + keyCode: 229, + composed: true, + }); + fireEvent.compositionEnd(input); + fireEvent.blur(input); + expect(input.value).toEqual('1,234'); + + fireEvent.focus(input); + fireEvent.compositionStart(input); + fireEvent.keyDown(input, { + which: 229, + key: 'Process', + code: 'Numpad5', + keyCode: 229, + composed: true, + }); + fireEvent.change(input, { target: { value: '12345' } }); + fireEvent.compositionEnd(input); + fireEvent.change(input, { target: { value: '1234' } }); + fireEvent.blur(input); + expect(input.value).toEqual('12,345'); + }); + it('formatter and parser', () => { const onChange = jest.fn(); const { container } = render(