mirror of
https://github.com/robonen/tools.git
synced 2026-03-20 10:54:44 +00:00
feat(packages/vue): init useEventListener composable
This commit is contained in:
136
packages/vue/src/composables/useEventListener/index.ts
Normal file
136
packages/vue/src/composables/useEventListener/index.ts
Normal file
@@ -0,0 +1,136 @@
|
||||
import { isArray, isString, noop, type Arrayable, type VoidFunction } from '@robonen/stdlib';
|
||||
import type { MaybeRefOrGetter } from 'vue';
|
||||
import { defaultWindow } from '../..';
|
||||
|
||||
// TODO: wip
|
||||
|
||||
interface InferEventTarget<Events> {
|
||||
addEventListener: (event: Events, listener?: any, options?: any) => any;
|
||||
removeEventListener: (event: Events, listener?: any, options?: any) => any;
|
||||
}
|
||||
|
||||
export interface GeneralEventListener<E = Event> {
|
||||
(evt: E): void;
|
||||
}
|
||||
|
||||
export type WindowEventName = keyof WindowEventMap;
|
||||
export type DocumentEventName = keyof DocumentEventMap;
|
||||
export type ElementEventName = keyof HTMLElementEventMap;
|
||||
|
||||
/**
|
||||
* @name useEventListener
|
||||
* @category Elements
|
||||
* @description Registers an event listener using the `addEventListener` on mounted and removes it automatically on unmounted
|
||||
*
|
||||
* Overload 1: Omitted window target
|
||||
*/
|
||||
export function useEventListener<E extends WindowEventName>(
|
||||
event: Arrayable<E>,
|
||||
listener: Arrayable<(this: Window, ev: WindowEventMap[E]) => any>,
|
||||
options?: MaybeRefOrGetter<boolean | AddEventListenerOptions>
|
||||
): VoidFunction;
|
||||
|
||||
/**
|
||||
* @name useEventListener
|
||||
* @category Elements
|
||||
* @description Registers an event listener using the `addEventListener` on mounted and removes it automatically on unmounted
|
||||
*
|
||||
* Overload 2: Explicit window target
|
||||
*/
|
||||
export function useEventListener<E extends WindowEventName>(
|
||||
target: Window,
|
||||
event: Arrayable<E>,
|
||||
listener: Arrayable<(this: Window, ev: WindowEventMap[E]) => any>,
|
||||
options?: MaybeRefOrGetter<boolean | AddEventListenerOptions>
|
||||
): VoidFunction;
|
||||
|
||||
/**
|
||||
* @name useEventListener
|
||||
* @category Elements
|
||||
* @description Registers an event listener using the `addEventListener` on mounted and removes it automatically on unmounted
|
||||
*
|
||||
* Overload 3: Explicit document target
|
||||
*/
|
||||
export function useEventListener<E extends DocumentEventName>(
|
||||
target: Document,
|
||||
event: Arrayable<E>,
|
||||
listener: Arrayable<(this: Document, ev: DocumentEventMap[E]) => any>,
|
||||
options?: MaybeRefOrGetter<boolean | AddEventListenerOptions>
|
||||
): VoidFunction;
|
||||
|
||||
/**
|
||||
* @name useEventListener
|
||||
* @category Elements
|
||||
* @description Registers an event listener using the `addEventListener` on mounted and removes it automatically on unmounted
|
||||
*
|
||||
* Overload 4: Explicit HTMLElement target
|
||||
*/
|
||||
export function useEventListener<E extends ElementEventName>(
|
||||
target: MaybeRefOrGetter<HTMLElement | null | undefined>,
|
||||
event: Arrayable<E>,
|
||||
listener: Arrayable<(this: HTMLElement, ev: HTMLElementEventMap[E]) => any>,
|
||||
options?: MaybeRefOrGetter<boolean | AddEventListenerOptions>
|
||||
): VoidFunction;
|
||||
|
||||
/**
|
||||
* @name useEventListener
|
||||
* @category Elements
|
||||
* @description Registers an event listener using the `addEventListener` on mounted and removes it automatically on unmounted
|
||||
*
|
||||
* Overload 5: Custom target with inferred event type
|
||||
*/
|
||||
export function useEventListener<Names extends string, EventType = Event>(
|
||||
target: MaybeRefOrGetter<InferEventTarget<Names> | null | undefined>,
|
||||
event: Arrayable<Names>,
|
||||
listener: Arrayable<GeneralEventListener<EventType>>,
|
||||
options?: MaybeRefOrGetter<boolean | AddEventListenerOptions>
|
||||
)
|
||||
|
||||
/**
|
||||
* @name useEventListener
|
||||
* @category Elements
|
||||
* @description Registers an event listener using the `addEventListener` on mounted and removes it automatically on unmounted
|
||||
*
|
||||
* Overload 6: Custom event target fallback
|
||||
*/
|
||||
export function useEventListener<EventType = Event>(
|
||||
target: MaybeRefOrGetter<EventTarget | null | undefined>,
|
||||
event: Arrayable<string>,
|
||||
listener: Arrayable<GeneralEventListener<EventType>>,
|
||||
options?: MaybeRefOrGetter<boolean | AddEventListenerOptions>
|
||||
): VoidFunction;
|
||||
|
||||
export function useEventListener(...args: any[]) {
|
||||
let target: MaybeRefOrGetter<EventTarget> | undefined;
|
||||
let events: Arrayable<string>;
|
||||
let listeners: Arrayable<Function>;
|
||||
let options: MaybeRefOrGetter<boolean | AddEventListenerOptions> | undefined;
|
||||
|
||||
if (isString(args[0]) || isArray(args[0])) {
|
||||
[events, listeners, options] = args;
|
||||
target = defaultWindow;
|
||||
} else {
|
||||
[target, events, listeners, options] = args;
|
||||
}
|
||||
|
||||
if (!target)
|
||||
return noop;
|
||||
|
||||
if (!isArray(events))
|
||||
events = [events];
|
||||
|
||||
if (!isArray(listeners))
|
||||
listeners = [listeners];
|
||||
|
||||
const cleanups: Function[] = [];
|
||||
|
||||
const cleanup = () => {
|
||||
cleanups.forEach(fn => fn());
|
||||
cleanups.length = 0;
|
||||
}
|
||||
|
||||
const register = (el: any, event: string, listener: any, options: any) => {
|
||||
el.addEventListener(event, listener, options);
|
||||
return () => el.removeEventListener(event, listener, options);
|
||||
}
|
||||
}
|
||||
3
packages/vue/src/types/window.ts
Normal file
3
packages/vue/src/types/window.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import { isClient } from '@robonen/platform';
|
||||
|
||||
export const defaultWindow = /* #__PURE__ */ isClient ? window : undefined
|
||||
Reference in New Issue
Block a user