// DOM events import '../../types/ujs'; export interface PhilomenaAvailableEventsMap { dragstart: DragEvent; dragover: DragEvent; dragenter: DragEvent; dragleave: DragEvent; dragend: DragEvent; drop: DragEvent; click: MouseEvent; submit: Event; reset: Event; fetchcomplete: FetchcompleteEvent; } export interface PhilomenaEventElement { addEventListener( type: K, // eslint-disable-next-line @typescript-eslint/no-explicit-any listener: (this: Document | HTMLElement, ev: PhilomenaAvailableEventsMap[K]) => any, options?: boolean | AddEventListenerOptions | undefined, ): void; } export function fire(el: El, event: string, detail: D) { el.dispatchEvent(new CustomEvent(event, { detail, bubbles: true, cancelable: true })); } export function on( node: PhilomenaEventElement, event: K, selector: string, func: (e: PhilomenaAvailableEventsMap[K], target: Element) => boolean, ) { delegate(node, event, { [selector]: func }); } export function leftClick(func: (e: E, t: Target) => void) { return (event: E, target: Target) => { if (event.button === 0) return func(event, target); }; } export function mouseMoveThenOver(element: El, func: (e: MouseEvent) => void) { element.addEventListener( 'mousemove', (event: MouseEvent) => { func(event); element.addEventListener('mouseover', func); }, { once: true }, ); } export function delegate( node: PhilomenaEventElement, event: K, selectors: Record void | boolean>, ) { node.addEventListener(event, e => { for (const selector in selectors) { const evtTarget = e.target as EventTarget | Target | null; if (evtTarget && 'closest' in evtTarget && typeof evtTarget.closest === 'function') { const target = evtTarget.closest(selector) as Target; if (target && selectors[selector](e, target) === false) break; } } }); }