From b240a56bedd98ee14bca40cee5fdcbbd43662095 Mon Sep 17 00:00:00 2001 From: chenyang Date: Thu, 5 Mar 2026 16:14:56 +0800 Subject: [PATCH] fix(hotkeys): recognize contenteditable=plaintext-only in isInputElement Use element.isContentEditable instead of checking contentEditable string values. This covers plaintext-only and inherited contenteditable, which were previously missed causing hotkeys to fire in editable elements. Closes #50 Made-with: Cursor --- .../fix-is-input-element-plaintext-only.md | 5 +++++ packages/hotkeys/src/manager.utils.ts | 10 ++++------ packages/hotkeys/tests/manager.utils.test.ts | 17 +++++++++++++++++ 3 files changed, 26 insertions(+), 6 deletions(-) create mode 100644 .changeset/fix-is-input-element-plaintext-only.md diff --git a/.changeset/fix-is-input-element-plaintext-only.md b/.changeset/fix-is-input-element-plaintext-only.md new file mode 100644 index 0000000..2ac350e --- /dev/null +++ b/.changeset/fix-is-input-element-plaintext-only.md @@ -0,0 +1,5 @@ +--- +'@tanstack/hotkeys': patch +--- + +fix(isInputElement): recognize contenteditable="plaintext-only" and inherited contenteditable diff --git a/packages/hotkeys/src/manager.utils.ts b/packages/hotkeys/src/manager.utils.ts index ec8790f..dc084fc 100644 --- a/packages/hotkeys/src/manager.utils.ts +++ b/packages/hotkeys/src/manager.utils.ts @@ -65,12 +65,10 @@ export function isInputElement(element: EventTarget | null): boolean { return true } - // Check for contenteditable elements - if (element instanceof HTMLElement) { - const contentEditable = element.contentEditable - if (contentEditable === 'true' || contentEditable === '') { - return true - } + // Check for contenteditable elements (includes "true", "", "plaintext-only", + // and inherited contenteditable from ancestor elements) + if (element instanceof HTMLElement && element.isContentEditable) { + return true } return false diff --git a/packages/hotkeys/tests/manager.utils.test.ts b/packages/hotkeys/tests/manager.utils.test.ts index 11b74f7..b929367 100644 --- a/packages/hotkeys/tests/manager.utils.test.ts +++ b/packages/hotkeys/tests/manager.utils.test.ts @@ -1,4 +1,5 @@ import { beforeEach, describe, expect, it, vi } from 'vitest' + import { defaultHotkeyOptions, getDefaultIgnoreInputs, @@ -53,6 +54,22 @@ describe('manager.utils', () => { expect(isInputElement(div)).toBe(true) }) + it('should return true for contenteditable plaintext-only elements', () => { + const div = document.createElement('div') + div.contentEditable = 'plaintext-only' + expect(isInputElement(div)).toBe(true) + }) + + it('should return true for inherited contenteditable', () => { + const parent = document.createElement('div') + parent.contentEditable = 'true' + const child = document.createElement('span') + parent.appendChild(child) + document.body.appendChild(parent) + expect(isInputElement(child)).toBe(true) + document.body.removeChild(parent) + }) + it('should return false for contenteditable false', () => { const div = document.createElement('div') div.contentEditable = 'false'