| 1 | const EDITABLE_SELECTOR = [ |
| 2 | "input", |
| 3 | "textarea", |
| 4 | "select", |
| 5 | '[contenteditable=""]', |
| 6 | '[contenteditable="true"]', |
| 7 | '[contenteditable="plaintext-only"]', |
| 8 | '[role="textbox"]', |
| 9 | ].join(","); |
| 10 | |
| 11 | /** |
| 12 | * Whether a text-editing element owns the keyboard. Shortcuts that share |
| 13 | * their chord with native editing (mod+z) must yield when this is true. |
| 14 | * Focus inside an open shadow root counts: a key event's target is retargeted |
| 15 | * to the shadow host, so the host's focused descendant is what is typed into. |
| 16 | */ |
| 17 | export function isEditableFocused(target: EventTarget | null = document.activeElement): boolean { |
| 18 | let element = target instanceof Element ? target : null; |
| 19 | while (element?.shadowRoot?.activeElement) element = element.shadowRoot.activeElement; |
| 20 | return element !== null && element.closest(EDITABLE_SELECTOR) !== null; |
| 21 | } |