blob: a5df36f520149d01178082dc52e3f9cbd30133e1 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
|
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { getHTMLElementOrNull } from '@/scripts/get-dom-node-or-null.js';
const focusTrapElements = new Set<HTMLElement>();
const ignoreElements = [
'script',
'style',
];
function containsFocusTrappedElements(el: HTMLElement): boolean {
return Array.from(focusTrapElements).some((focusTrapElement) => {
return el.contains(focusTrapElement);
});
}
function releaseFocusTrap(el: HTMLElement): void {
focusTrapElements.delete(el);
if (el.inert === true) {
el.inert = false;
}
if (el.parentElement != null && el !== document.body) {
el.parentElement.childNodes.forEach((siblingNode) => {
const siblingEl = getHTMLElementOrNull(siblingNode);
if (!siblingEl) return;
if (siblingEl !== el && (focusTrapElements.has(siblingEl) || containsFocusTrappedElements(siblingEl) || focusTrapElements.size === 0)) {
siblingEl.inert = false;
} else if (
focusTrapElements.size > 0 &&
!containsFocusTrappedElements(siblingEl) &&
!focusTrapElements.has(siblingEl) &&
!ignoreElements.includes(siblingEl.tagName.toLowerCase())
) {
siblingEl.inert = true;
} else {
siblingEl.inert = false;
}
});
releaseFocusTrap(el.parentElement);
}
}
export function focusTrap(el: HTMLElement, hasInteractionWithOtherFocusTrappedEls: boolean, parent: true): void;
export function focusTrap(el: HTMLElement, hasInteractionWithOtherFocusTrappedEls?: boolean, parent?: false): { release: () => void; };
export function focusTrap(el: HTMLElement, hasInteractionWithOtherFocusTrappedEls = false, parent = false): { release: () => void; } | void {
if (el.inert === true) {
el.inert = false;
}
if (el.parentElement != null && el !== document.body) {
el.parentElement.childNodes.forEach((siblingNode) => {
const siblingEl = getHTMLElementOrNull(siblingNode);
if (!siblingEl) return;
if (
siblingEl !== el &&
(
hasInteractionWithOtherFocusTrappedEls === false ||
(!focusTrapElements.has(siblingEl) && !containsFocusTrappedElements(siblingEl))
) &&
!ignoreElements.includes(siblingEl.tagName.toLowerCase())
) {
siblingEl.inert = true;
}
});
focusTrap(el.parentElement, hasInteractionWithOtherFocusTrappedEls, true);
}
if (!parent) {
focusTrapElements.add(el);
return {
release: () => {
releaseFocusTrap(el);
},
};
}
}
|