Skip to content

Commit

Permalink
Cleanup addEventListener (#16)
Browse files Browse the repository at this point in the history
* tidy up addEventListener implementation

* shut up prettier

* restore array behavior

* add jsdoc

* Create olive-rivers-try.md

---------

Co-authored-by: Thomas G. Lopes <[email protected]>
  • Loading branch information
Abdelrahman and TGlide authored Apr 27, 2024
1 parent 3e1f45e commit 22de8ae
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 25 deletions.
5 changes: 5 additions & 0 deletions .changeset/olive-rivers-try.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"runed": patch
---

Fix addEventListener overloads
Original file line number Diff line number Diff line change
@@ -1,43 +1,65 @@
import { box } from "../box/box.svelte.js";
import type { MaybeBoxOrGetter } from "$lib/internal/types.js";
import { addEventListener } from "$lib/internal/utils/event.js";

/**
* Adds an event listener to the specified target element for the given event(s), and returns a function to remove it.
* @param target The target element to add the event listener to.
* @param event The event(s) to listen for.
* @param handler The function to be called when the event is triggered.
* @param options An optional object that specifies characteristics about the event listener.
*/
export function useEventListener<TEvent extends keyof WindowEventMap>(
target: MaybeBoxOrGetter<Window | null | undefined>,
event: TEvent,
event: TEvent | TEvent[],
handler: (this: Window, event: WindowEventMap[TEvent]) => unknown,
options?: boolean | AddEventListenerOptions
): void;

export function useEventListener<TEvent extends keyof DocumentEventMap>(
target: MaybeBoxOrGetter<Document | null | undefined>,
event: TEvent,
event: TEvent | TEvent[],
handler: (this: Document, event: DocumentEventMap[TEvent]) => unknown,
options?: boolean | AddEventListenerOptions
): void;

/**
* Adds an event listener to the specified target element for the given event(s), and returns a function to remove it.
* @param target The target element to add the event listener to.
* @param event The event(s) to listen for.
* @param handler The function to be called when the event is triggered.
* @param options An optional object that specifies characteristics about the event listener.
*/
export function useEventListener<
TElement extends HTMLElement,
TEvent extends keyof HTMLElementEventMap,
>(
target: MaybeBoxOrGetter<TElement | null | undefined>,
event: TEvent,
event: TEvent | TEvent[],
handler: (this: TElement, event: HTMLElementEventMap[TEvent]) => unknown,
options?: boolean | AddEventListenerOptions
): void;

/**
* Adds an event listener to the specified target element for the given event(s), and returns a function to remove it.
* @param target The target element to add the event listener to.
* @param event The event(s) to listen for.
* @param handler The function to be called when the event is triggered.
* @param options An optional object that specifies characteristics about the event listener.
*/
export function useEventListener(
target: MaybeBoxOrGetter<EventTarget | null | undefined>,
event: string,
event: string | string[],
handler: EventListenerOrEventListenerObject,
options?: boolean | AddEventListenerOptions
): void;

export function useEventListener(
_target: MaybeBoxOrGetter<EventTarget | null | undefined>,
event: string,
event: string | string[],
handler: EventListenerOrEventListenerObject,
options?: boolean | AddEventListenerOptions
) {
): void {
const target = box.from(_target);

$effect(() => {
Expand Down
61 changes: 42 additions & 19 deletions packages/runed/src/lib/internal/utils/event.ts
Original file line number Diff line number Diff line change
@@ -1,58 +1,81 @@
/**
* Overloaded function signatures for addEventListener
* Adds an event listener to the specified target element for the given event(s), and returns a function to remove it.
* @param target The target element to add the event listener to.
* @param event The event(s) to listen for.
* @param handler The function to be called when the event is triggered.
* @param options An optional object that specifies characteristics about the event listener.
* @returns A function that removes the event listener(s) from the target element.
*/
export function addEventListener<TEvent extends keyof WindowEventMap>(
target: Window,
event: TEvent,
event: TEvent | TEvent[],
handler: (this: Window, event: WindowEventMap[TEvent]) => unknown,
options?: boolean | AddEventListenerOptions
): VoidFunction;

/**
* Adds an event listener to the specified target element for the given event(s), and returns a function to remove it.
* @param target The target element to add the event listener to.
* @param event The event(s) to listen for.
* @param handler The function to be called when the event is triggered.
* @param options An optional object that specifies characteristics about the event listener.
* @returns A function that removes the event listener(s) from the target element.
*/
export function addEventListener<TEvent extends keyof DocumentEventMap>(
target: Document,
event: TEvent,
event: TEvent | TEvent[],
handler: (this: Document, event: DocumentEventMap[TEvent]) => unknown,
options?: boolean | AddEventListenerOptions
): VoidFunction;

/**
* Adds an event listener to the specified target element for the given event(s), and returns a function to remove it.
* @param target The target element to add the event listener to.
* @param event The event(s) to listen for.
* @param handler The function to be called when the event is triggered.
* @param options An optional object that specifies characteristics about the event listener.
* @returns A function that removes the event listener(s) from the target element.
*/
export function addEventListener<
TElement extends HTMLElement,
TEvent extends keyof HTMLElementEventMap,
>(
target: TElement,
event: TEvent,
event: TEvent | TEvent[],
handler: (this: TElement, event: HTMLElementEventMap[TEvent]) => unknown,
options?: boolean | AddEventListenerOptions
): VoidFunction;

/**
* Adds an event listener to the specified target element for the given event(s), and returns a function to remove it.
* @param target The target element to add the event listener to.
* @param event The event(s) to listen for.
* @param handler The function to be called when the event is triggered.
* @param options An optional object that specifies characteristics about the event listener.
* @returns A function that removes the event listener(s) from the target element.
*/
export function addEventListener(
target: EventTarget,
event: string,
event: string | string[],
handler: EventListenerOrEventListenerObject,
options?: boolean | AddEventListenerOptions
): VoidFunction;

/**
* Adds an event listener to the specified target element(s) for the given event(s), and returns a function to remove it.
* @param target The target element(s) to add the event listener to.
* @param event The event(s) to listen for.
* @param handler The function to be called when the event is triggered.
* @param options An optional object that specifies characteristics about the event listener.
* @returns A function that removes the event listener from the target element(s).
*/
export function addEventListener(
target: Window | Document | EventTarget,
target: EventTarget,
event: string | string[],
handler: EventListenerOrEventListenerObject,
options?: boolean | AddEventListenerOptions
) {
): VoidFunction {
const events = Array.isArray(event) ? event : [event];

// Add the event listener to each specified event for the target element(s).
events.forEach((_event) => target.addEventListener(_event, handler, options));
for (const event of events) {
target.addEventListener(event, handler, options);
}

// Return a function that removes the event listener from the target element(s).
return () => {
events.forEach((_event) => target.removeEventListener(_event, handler, options));
for (const event of events) {
target.removeEventListener(event, handler, options);
}
};
}

0 comments on commit 22de8ae

Please sign in to comment.