From 38921f48068bf902675a1c5250d00878c3698814 Mon Sep 17 00:00:00 2001 From: Edoardo Cavazza Date: Thu, 18 Jul 2024 19:00:40 +0200 Subject: [PATCH] Do not store node's ownerDocument since it can change for imported nodes --- .changeset/purple-bees-yell.md | 5 +++++ src/focusEnterBehavior.ts | 5 ++--- src/focusFirstChildBehavior.ts | 5 ++--- src/focusTrapBehavior.ts | 9 ++++----- src/keyboardNavigationBehavior.ts | 5 +++-- 5 files changed, 16 insertions(+), 13 deletions(-) create mode 100644 .changeset/purple-bees-yell.md diff --git a/.changeset/purple-bees-yell.md b/.changeset/purple-bees-yell.md new file mode 100644 index 0000000..04beb98 --- /dev/null +++ b/.changeset/purple-bees-yell.md @@ -0,0 +1,5 @@ +--- +'@chialab/loock': minor +--- + +Do not store node's ownerDocument since it can change for imported nodes. diff --git a/src/focusEnterBehavior.ts b/src/focusEnterBehavior.ts index 4798bc6..395124a 100644 --- a/src/focusEnterBehavior.ts +++ b/src/focusEnterBehavior.ts @@ -21,13 +21,12 @@ export interface FocusEnterOptions extends FocusManagerOptions { * @returns The behavior controller. */ export function focusEnterBehavior(node: HTMLElement, options: FocusEnterOptions = {}) { - const document = node.ownerDocument; const { onEnter, onExit } = options; let focused = false; let connected = false; const onFocusIn = () => { - const activeElement = document.activeElement; + const activeElement = node.ownerDocument.activeElement; if (focused || !activeElement) { return; } @@ -57,7 +56,7 @@ export function focusEnterBehavior(node: HTMLElement, options: FocusEnterOptions } connected = true; focused = false; - if (document.activeElement && node.contains(document.activeElement)) { + if (node.ownerDocument.activeElement && node.contains(node.ownerDocument.activeElement)) { onFocusIn(); } node.addEventListener('focusin', onFocusIn); diff --git a/src/focusFirstChildBehavior.ts b/src/focusFirstChildBehavior.ts index e510360..1d28f6b 100644 --- a/src/focusFirstChildBehavior.ts +++ b/src/focusFirstChildBehavior.ts @@ -9,7 +9,6 @@ import { restoreAttribute } from './helpers'; * @returns The behavior controller. */ export function focusFirstChildBehavior(node: HTMLElement, options: FocusManagerOptions = {}) { - const document = node.ownerDocument; let activeElement: HTMLElement | null = null; let connected = false; let tabIndex: string | null = null; @@ -28,7 +27,7 @@ export function focusFirstChildBehavior(node: HTMLElement, options: FocusManager const onFocus = () => { const elements = manager.findFocusable(); - const target = document.activeElement as HTMLElement; + const target = node.ownerDocument.activeElement as HTMLElement; if (target === node) { if (activeElement && node.contains(activeElement)) { activeElement.focus(); @@ -53,7 +52,7 @@ export function focusFirstChildBehavior(node: HTMLElement, options: FocusManager enterBehavior.connect(); connected = true; activeElement = null; - if (document.activeElement && node.contains(document.activeElement)) { + if (node.ownerDocument.activeElement && node.contains(node.ownerDocument.activeElement)) { onFocus(); } node.addEventListener('focus', onFocus, true); diff --git a/src/focusTrapBehavior.ts b/src/focusTrapBehavior.ts index 35082ac..4378b7c 100644 --- a/src/focusTrapBehavior.ts +++ b/src/focusTrapBehavior.ts @@ -122,8 +122,7 @@ export function focusTrapBehavior(node: HTMLElement, options: FocusTrapOptions = node.setAttribute('tabindex', '0'); } - const document = node.ownerDocument; - trapStart = startHelper || createTrapHelper(document); + trapStart = startHelper || createTrapHelper(node.ownerDocument); trapStart.addEventListener( 'focus', (event) => { @@ -143,7 +142,7 @@ export function focusTrapBehavior(node: HTMLElement, options: FocusTrapOptions = true ); - trapEnd = endHelper || createTrapHelper(document); + trapEnd = endHelper || createTrapHelper(node.ownerDocument); trapEnd.addEventListener( 'focus', (event) => { @@ -169,7 +168,7 @@ export function focusTrapBehavior(node: HTMLElement, options: FocusTrapOptions = root = node.shadowRoot; } else { root = node.attachShadow({ mode: 'open' }); - root.append(document.createElement('slot')); + root.append(node.ownerDocument.createElement('slot')); } } if (root.firstChild !== trapStart) { @@ -189,7 +188,7 @@ export function focusTrapBehavior(node: HTMLElement, options: FocusTrapOptions = if (trapEnd) { trapEnd.tabIndex = 0; } - restoreFocusNode = document.activeElement as HTMLElement; + restoreFocusNode = node.ownerDocument.activeElement as HTMLElement; if (node.contains(restoreFocusNode) && restoreFocusNode !== node) { restoreFocusNode = node; } else if (focusContainer) { diff --git a/src/keyboardNavigationBehavior.ts b/src/keyboardNavigationBehavior.ts index 4393809..da0444e 100644 --- a/src/keyboardNavigationBehavior.ts +++ b/src/keyboardNavigationBehavior.ts @@ -29,7 +29,6 @@ export interface KeyboardNavigationOptions extends FocusManagerOptions { * @returns The behavior controller. */ export function keyboardNavigationBehavior(node: HTMLElement, options: KeyboardNavigationOptions) { - const document = node.ownerDocument; let connected = false; const manager = focusManager(node, options); @@ -38,7 +37,9 @@ export function keyboardNavigationBehavior(node: HTMLElement, options: KeyboardN return; } - const current = node.contains(document.activeElement) ? (document.activeElement as HTMLElement) : null; + const current = node.contains(node.ownerDocument.activeElement) + ? (node.ownerDocument.activeElement as HTMLElement) + : null; if (!current) { return; }