27 lines
855 B
TypeScript
27 lines
855 B
TypeScript
const focusableSelector = [
|
|
"a[href]",
|
|
"button:not([disabled])",
|
|
"input:not([disabled])",
|
|
"select:not([disabled])",
|
|
"textarea:not([disabled])",
|
|
"[tabindex]:not([tabindex='-1'])",
|
|
].join(",");
|
|
|
|
export function keepFocusWithin(event: KeyboardEvent, container: HTMLElement) {
|
|
if (event.key !== "Tab") return;
|
|
|
|
const focusable = Array.from(container.querySelectorAll<HTMLElement>(focusableSelector))
|
|
.filter((element) => element.getAttribute("aria-hidden") !== "true" && element.offsetParent !== null);
|
|
const first = focusable[0];
|
|
const last = focusable[focusable.length - 1];
|
|
if (!first || !last) return;
|
|
|
|
if (event.shiftKey && document.activeElement === first) {
|
|
event.preventDefault();
|
|
last.focus();
|
|
} else if (!event.shiftKey && document.activeElement === last) {
|
|
event.preventDefault();
|
|
first.focus();
|
|
}
|
|
}
|