| 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"); |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| 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); |
| }; |
|
|
| |
| const useCapture = true; |
|
|
| |
| document.addEventListener("pointerdown", listenerWrapper, useCapture); |
| document.addEventListener("mousedown", listenerWrapper, useCapture); |
| document.addEventListener("pointerup", listenerWrapper, useCapture); |
| document.addEventListener("mouseup", listenerWrapper, useCapture); |
|
|
| |
| 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); |
| } |
|
|