File size: 3,884 Bytes
aa3b624 63b089b 9bde4cc c7a3398 6bf3ab4 aa3b624 7fbff02 e5cb552 aa3b624 e5cb552 aa3b624 0f198fd 0b494ac 0f198fd 2d82059 0f198fd 63b089b 529f19a c7a3398 63b089b d0e0b03 aafd6df 63b089b 66a740c 9bde4cc 66a740c 4b04f2c 66a740c aa3b624 63b089b 0f198fd 8480986 aa3b624 4b04f2c 8480986 aa3b624 |
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 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
import { refreshActiveHighlight } from "./highlight";
import { emit } from "./emitter";
import { getState, setState } from "./state";
import { getConfig } from "./config";
import { getFocusableElements } from "./utils";
export function requireRefresh() {
const resizeTimeout = getState("__resizeTimeout");
if (resizeTimeout) {
window.cancelAnimationFrame(resizeTimeout);
}
setState("__resizeTimeout", window.requestAnimationFrame(refreshActiveHighlight));
}
function trapFocus(e: KeyboardEvent) {
const isActivated = getState("isInitialized");
if (!isActivated) {
return;
}
const isTabKey = e.key === "Tab" || e.keyCode === 9;
if (!isTabKey) {
return;
}
const activeElement = getState("__activeElement");
const popoverEl = getState("popover")?.wrapper;
const focusableEls = getFocusableElements([
...(popoverEl ? [popoverEl] : []),
...(activeElement ? [activeElement] : []),
]);
const firstFocusableEl = focusableEls[0];
const lastFocusableEl = focusableEls[focusableEls.length - 1];
e.preventDefault();
if (e.shiftKey) {
const previousFocusableEl =
focusableEls[focusableEls.indexOf(document.activeElement as HTMLElement) - 1] || lastFocusableEl;
previousFocusableEl?.focus();
} else {
const nextFocusableEl =
focusableEls[focusableEls.indexOf(document.activeElement as HTMLElement) + 1] || firstFocusableEl;
nextFocusableEl?.focus();
}
}
function onKeyup(e: KeyboardEvent) {
const allowKeyboardControl = getConfig("allowKeyboardControl") ?? true;
if (!allowKeyboardControl) {
return;
}
if (e.key === "Escape") {
emit("escapePress");
} else if (e.key === "ArrowRight") {
emit("arrowRightPress");
} else if (e.key === "ArrowLeft") {
emit("arrowLeftPress");
}
}
/**
* Attaches click handler to the elements created by driver.js. It makes
* sure to give the listener the first chance to handle the event, and
* prevents all other pointer-events to make sure no external-library
* ever knows the click happened.
*
* @param {Element} element Element to listen for click events
* @param {(pointer: MouseEvent | PointerEvent) => void} listener Click handler
* @param {(target: HTMLElement) => boolean} shouldPreventDefault Whether to prevent default action i.e. link clicks etc
*/
export function onDriverClick(
element: Element,
listener: (pointer: MouseEvent | PointerEvent) => void,
shouldPreventDefault?: (target: HTMLElement) => boolean
) {
const listenerWrapper = (e: MouseEvent | PointerEvent, listener?: (pointer: MouseEvent | PointerEvent) => void) => {
const target = e.target as HTMLElement;
if (!element.contains(target)) {
return;
}
if (!shouldPreventDefault || shouldPreventDefault(target)) {
e.preventDefault();
e.stopPropagation();
e.stopImmediatePropagation();
}
listener?.(e);
};
// We want to be the absolute first one to hear about the event
const useCapture = true;
// Events to disable
document.addEventListener("pointerdown", listenerWrapper, useCapture);
document.addEventListener("mousedown", listenerWrapper, useCapture);
document.addEventListener("pointerup", listenerWrapper, useCapture);
document.addEventListener("mouseup", listenerWrapper, useCapture);
// Actual click handler
document.addEventListener(
"click",
e => {
listenerWrapper(e, listener);
},
useCapture
);
}
export function initEvents() {
window.addEventListener("keyup", onKeyup, false);
window.addEventListener("keydown", trapFocus, false);
window.addEventListener("resize", requireRefresh);
window.addEventListener("scroll", requireRefresh);
}
export function destroyEvents() {
window.removeEventListener("keyup", onKeyup);
window.removeEventListener("resize", requireRefresh);
window.removeEventListener("scroll", requireRefresh);
}
|