From 91c77695abad90e19d71150bb677505e0b20c80e Mon Sep 17 00:00:00 2001 From: aojunhao123 <1844749591@qq.com> Date: Mon, 29 Dec 2025 23:03:05 +0800 Subject: [PATCH 1/6] feat: add util function for better keyboard event handling --- src/KeyCode.ts | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/KeyCode.ts b/src/KeyCode.ts index 2746f9e9..4cfb6b1a 100644 --- a/src/KeyCode.ts +++ b/src/KeyCode.ts @@ -517,6 +517,29 @@ const KeyCode = { return false; } }, + + shouldIgnoreKeyboardEvent: function shouldIgnoreKeyboardEvent( + e: KeyboardEvent, + ) { + const target = e.target; + + if (!(target instanceof HTMLElement)) { + return false; + } + + const tagName = target.tagName; + if ( + e.isComposing || + tagName === 'INPUT' || + tagName === 'TEXTAREA' || + tagName === 'SELECT' || + target.isContentEditable + ) { + return true; + } + + return false; + }, }; export default KeyCode; From db5b908285124e72ac35f01ccf77a6f5d95f0b03 Mon Sep 17 00:00:00 2001 From: aojunhao123 <1844749591@qq.com> Date: Tue, 30 Dec 2025 10:45:27 +0800 Subject: [PATCH 2/6] chore: adjust --- src/KeyCode.ts | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/KeyCode.ts b/src/KeyCode.ts index 4cfb6b1a..6082b9ab 100644 --- a/src/KeyCode.ts +++ b/src/KeyCode.ts @@ -520,8 +520,13 @@ const KeyCode = { shouldIgnoreKeyboardEvent: function shouldIgnoreKeyboardEvent( e: KeyboardEvent, + options?: { + checkEditable?: boolean; + checkComposing?: boolean; + }, ) { const target = e.target; + const { checkEditable = true, checkComposing = true } = options || {}; if (!(target instanceof HTMLElement)) { return false; @@ -529,15 +534,19 @@ const KeyCode = { const tagName = target.tagName; if ( - e.isComposing || - tagName === 'INPUT' || - tagName === 'TEXTAREA' || - tagName === 'SELECT' || - target.isContentEditable + checkEditable && + (tagName === 'INPUT' || + tagName === 'TEXTAREA' || + tagName === 'SELECT' || + target.isContentEditable) ) { return true; } + if (checkComposing && e.isComposing) { + return true; + } + return false; }, }; From 12a1346180b922da4083a3cff2a727bdb419b656 Mon Sep 17 00:00:00 2001 From: aojunhao123 <1844749591@qq.com> Date: Tue, 30 Dec 2025 11:24:36 +0800 Subject: [PATCH 3/6] chore: adjust --- src/KeyCode.ts | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/src/KeyCode.ts b/src/KeyCode.ts index 6082b9ab..7c964fa9 100644 --- a/src/KeyCode.ts +++ b/src/KeyCode.ts @@ -518,15 +518,8 @@ const KeyCode = { } }, - shouldIgnoreKeyboardEvent: function shouldIgnoreKeyboardEvent( - e: KeyboardEvent, - options?: { - checkEditable?: boolean; - checkComposing?: boolean; - }, - ) { + isEditableTarget: function isEditableTarget(e: KeyboardEvent) { const target = e.target; - const { checkEditable = true, checkComposing = true } = options || {}; if (!(target instanceof HTMLElement)) { return false; @@ -534,19 +527,15 @@ const KeyCode = { const tagName = target.tagName; if ( - checkEditable && - (tagName === 'INPUT' || - tagName === 'TEXTAREA' || - tagName === 'SELECT' || - target.isContentEditable) + e.isComposing || + tagName === 'INPUT' || + tagName === 'TEXTAREA' || + tagName === 'SELECT' || + target.isContentEditable ) { return true; } - if (checkComposing && e.isComposing) { - return true; - } - return false; }, }; From d07a2081a7ba8060fa29f3cadc87fb1ab07dcf0f Mon Sep 17 00:00:00 2001 From: aojunhao123 <1844749591@qq.com> Date: Tue, 30 Dec 2025 11:47:14 +0800 Subject: [PATCH 4/6] add test case --- tests/KeyCode.test.ts | 54 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 tests/KeyCode.test.ts diff --git a/tests/KeyCode.test.ts b/tests/KeyCode.test.ts new file mode 100644 index 00000000..acca7513 --- /dev/null +++ b/tests/KeyCode.test.ts @@ -0,0 +1,54 @@ +import KeyCode from '../src/KeyCode'; + +describe('KeyCode.isEditableTarget', () => { + function testIsEditableTarget( + listenTarget: EventTarget, + dispatchTarget: EventTarget, + init?: KeyboardEventInit, + ) { + let result: boolean | undefined; + + const handler = (e: KeyboardEvent) => { + result = KeyCode.isEditableTarget(e); + }; + + listenTarget.addEventListener('keydown', handler); + dispatchTarget.dispatchEvent(new KeyboardEvent('keydown', init)); + listenTarget.removeEventListener('keydown', handler); + + return result; + } + + it('check non-editable target', () => { + const result = testIsEditableTarget(window, window); + + expect(result).toBe(false); + }); + + it('IME composing', () => { + const input = document.createElement('input'); + const result = testIsEditableTarget(input, input, { isComposing: true }); + + expect(result).toBe(true); + }); + + it('check input target', () => { + const input = document.createElement('input'); + document.body.appendChild(input); + + const result = testIsEditableTarget(window, input, { bubbles: true }); + + document.body.removeChild(input); + + expect(result).toBe(true); + }); + + it('check contentEditable target', () => { + const editable = document.createElement('div'); + // mock isContentEditable cause JSDOM don't support it + Object.defineProperty(editable, 'isContentEditable', { value: true }); + const result = testIsEditableTarget(editable, editable); + + expect(result).toBe(true); + }); +}); From 88d5bbb3045a560418b297a9bbab7f958617d87b Mon Sep 17 00:00:00 2001 From: aojunhao123 <1844749591@qq.com> Date: Tue, 30 Dec 2025 12:00:01 +0800 Subject: [PATCH 5/6] test case --- tests/KeyCode.test.ts | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/tests/KeyCode.test.ts b/tests/KeyCode.test.ts index acca7513..ad1a211c 100644 --- a/tests/KeyCode.test.ts +++ b/tests/KeyCode.test.ts @@ -20,9 +20,12 @@ describe('KeyCode.isEditableTarget', () => { } it('check non-editable target', () => { - const result = testIsEditableTarget(window, window); + const div = document.createElement('div'); + const result1 = testIsEditableTarget(window, window); + const result2 = testIsEditableTarget(div, div); - expect(result).toBe(false); + expect(result1).toBe(false); + expect(result2).toBe(false); }); it('IME composing', () => { @@ -32,23 +35,19 @@ describe('KeyCode.isEditableTarget', () => { expect(result).toBe(true); }); - it('check input target', () => { + it('check editable target', () => { const input = document.createElement('input'); document.body.appendChild(input); - - const result = testIsEditableTarget(window, input, { bubbles: true }); - - document.body.removeChild(input); - - expect(result).toBe(true); - }); - - it('check contentEditable target', () => { const editable = document.createElement('div'); // mock isContentEditable cause JSDOM don't support it Object.defineProperty(editable, 'isContentEditable', { value: true }); - const result = testIsEditableTarget(editable, editable); - expect(result).toBe(true); + const result1 = testIsEditableTarget(window, input, { bubbles: true }); + const result2 = testIsEditableTarget(editable, editable); + + document.body.removeChild(input); + + expect(result1).toBe(true); + expect(result2).toBe(true); }); }); From 2bda4bce27c05cd02017826ea5ce3c5e4e9b1030 Mon Sep 17 00:00:00 2001 From: aojunhao123 <1844749591@qq.com> Date: Tue, 30 Dec 2025 12:36:29 +0800 Subject: [PATCH 6/6] chore: adjust --- src/KeyCode.ts | 1 - tests/KeyCode.test.ts | 89 ++++++++++++++++++++----------------------- 2 files changed, 42 insertions(+), 48 deletions(-) diff --git a/src/KeyCode.ts b/src/KeyCode.ts index 7c964fa9..2f1dd427 100644 --- a/src/KeyCode.ts +++ b/src/KeyCode.ts @@ -527,7 +527,6 @@ const KeyCode = { const tagName = target.tagName; if ( - e.isComposing || tagName === 'INPUT' || tagName === 'TEXTAREA' || tagName === 'SELECT' || diff --git a/tests/KeyCode.test.ts b/tests/KeyCode.test.ts index ad1a211c..25f00ac3 100644 --- a/tests/KeyCode.test.ts +++ b/tests/KeyCode.test.ts @@ -1,53 +1,48 @@ import KeyCode from '../src/KeyCode'; +import { createEvent } from '@testing-library/react'; describe('KeyCode.isEditableTarget', () => { - function testIsEditableTarget( - listenTarget: EventTarget, - dispatchTarget: EventTarget, - init?: KeyboardEventInit, - ) { - let result: boolean | undefined; - - const handler = (e: KeyboardEvent) => { - result = KeyCode.isEditableTarget(e); - }; - - listenTarget.addEventListener('keydown', handler); - dispatchTarget.dispatchEvent(new KeyboardEvent('keydown', init)); - listenTarget.removeEventListener('keydown', handler); - - return result; - } - - it('check non-editable target', () => { - const div = document.createElement('div'); - const result1 = testIsEditableTarget(window, window); - const result2 = testIsEditableTarget(div, div); - - expect(result1).toBe(false); - expect(result2).toBe(false); - }); - - it('IME composing', () => { - const input = document.createElement('input'); - const result = testIsEditableTarget(input, input, { isComposing: true }); - - expect(result).toBe(true); - }); - it('check editable target', () => { - const input = document.createElement('input'); - document.body.appendChild(input); - const editable = document.createElement('div'); - // mock isContentEditable cause JSDOM don't support it - Object.defineProperty(editable, 'isContentEditable', { value: true }); - - const result1 = testIsEditableTarget(window, input, { bubbles: true }); - const result2 = testIsEditableTarget(editable, editable); - - document.body.removeChild(input); - - expect(result1).toBe(true); - expect(result2).toBe(true); + const eleList = [ + { + element: 'window', + expected: false, + }, + { + element: 'div', + expected: false, + }, + { + element: 'input', + expected: true, + }, + { + element: 'textarea', + expected: true, + }, + { + element: 'select', + expected: true, + }, + { + element: 'div', + isContentEditable: true, + expected: true, + }, + ]; + + eleList.forEach(({ element, isContentEditable, expected }) => { + const target = + element === 'window' ? window : document.createElement(element); + if (isContentEditable) { + // mock isContentEditable cause JSDOM don't support it + Object.defineProperty(target, 'isContentEditable', { value: true }); + } + const event = createEvent.keyDown(target) as KeyboardEvent; + target.dispatchEvent(event); + const result = KeyCode.isEditableTarget(event); + + expect(result).toBe(expected); + }); }); });