improve event listener types and add scroll event listener to public interface

This commit is contained in:
Rene Haas
2022-10-25 22:17:53 +02:00
parent addd976f3b
commit 983f95d2ec
4 changed files with 58 additions and 39 deletions
@@ -4,6 +4,9 @@ import type { Options } from '~/options';
import type {
EventListeners as GeneralEventListeners,
EventListener as GeneralEventListener,
AddEvent as GeneralAddEvent,
RemoveEvent as GeneralRemoveEvent,
TriggerEvent as GeneralTriggerEvent,
} from '~/support/eventListeners';
/**
@@ -45,6 +48,8 @@ export type EventListenerMap = {
updated: [instance: OverlayScrollbars, onUpdatedArgs: OnUpdatedEventListenerArgs];
/** Triggered after all elements, observers and events are destroyed. */
destroyed: [instance: OverlayScrollbars, canceled: boolean];
/** Triggered on scroll. */
scroll: [instance: OverlayScrollbars, event: Event];
};
/**
@@ -61,3 +66,12 @@ export type EventListener<N extends keyof EventListenerMap> = GeneralEventListen
EventListenerMap,
N
>;
/** A function which adds event listeners. */
export type AddEvent = GeneralAddEvent<EventListenerMap>;
/** A function which removes event listeners. */
export type RemoveEvent = GeneralRemoveEvent<EventListenerMap>;
/** A function which triggers event listeners. */
export type TriggerEvent = GeneralTriggerEvent<EventListenerMap>;
@@ -262,7 +262,9 @@ export const OverlayScrollbars: OverlayScrollbarsStatic = (
const [updateScrollbars, scrollbarsState, destroyScrollbars] = createScrollbarsSetup(
target,
currentOptions,
structureState
structureState,
// eslint-disable-next-line @typescript-eslint/no-use-before-define
(scrollEvent) => triggerEvent('scroll', [instance, scrollEvent])
);
const update = (changedOptions: DeepPartial<Options>, force?: boolean): boolean =>
updateStructure(changedOptions, !!force);
@@ -36,7 +36,8 @@ export interface ScrollbarsSetupStaticState {
export const createScrollbarsSetup = (
target: InitializationTarget,
options: ReadonlyOptions,
structureSetupState: (() => StructureSetupState) & StructureSetupStaticState
structureSetupState: (() => StructureSetupState) & StructureSetupStaticState,
onScroll: (event: Event) => void
): Setup<
ScrollbarsSetupState,
ScrollbarsSetupStaticState,
@@ -132,7 +133,7 @@ export const createScrollbarsSetup = (
});
});
}),
on(_scrollEventElement, 'scroll', () => {
on(_scrollEventElement, 'scroll', (event) => {
requestScrollAnimationFrame(() => {
_refreshScrollbarsHandleOffset(structureSetupState());
@@ -142,6 +143,8 @@ export const createScrollbarsSetup = (
});
});
onScroll(event);
_viewportIsTarget && styleHorizontal(styleScrollbarPosition);
_viewportIsTarget && styleVertical(styleScrollbarPosition);
}),
@@ -10,6 +10,35 @@ export type EventListeners<EventMap extends Record<string, any[]>> = {
[K in keyof EventMap]?: EventListener<EventMap, K> | EventListener<EventMap, K>[];
};
export type RemoveEvent<EventMap extends Record<string, any[]>> = {
<N extends keyof EventMap>(name?: N, listener?: EventListener<EventMap, N>): void;
<N extends keyof EventMap>(name?: N, listener?: EventListener<EventMap, N>[]): void;
<N extends keyof EventMap>(
name?: N,
listener?: EventListener<EventMap, N> | EventListener<EventMap, N>[]
): void;
};
export type AddEvent<EventMap extends Record<string, any[]>> = {
(eventListeners: EventListeners<EventMap>): () => void;
<N extends keyof EventMap>(name: N, listener: EventListener<EventMap, N>): () => void;
<N extends keyof EventMap>(name: N, listener: EventListener<EventMap, N>[]): () => void;
<N extends keyof EventMap>(
nameOrEventListeners: N | EventListeners<EventMap>,
listener?: EventListener<EventMap, N> | EventListener<EventMap, N>[]
): () => void;
};
export type TriggerEvent<EventMap extends Record<string, any[]>> = {
<N extends keyof EventMap>(name: N, args?: EventMap[N]): void;
};
export type EventListenerHub<EventMap extends Record<string, any[]>> = [
AddEvent<EventMap>,
RemoveEvent<EventMap>,
TriggerEvent<EventMap>
];
const manageListener = <EventMap extends Record<string, any[]>, N extends keyof EventMap>(
callback: (listener?: EventListener<EventMap, N>) => void,
listener?: EventListener<EventMap, N> | EventListener<EventMap, N>[]
@@ -19,33 +48,10 @@ const manageListener = <EventMap extends Record<string, any[]>, N extends keyof
export const createEventListenerHub = <EventMap extends Record<string, any[]>>(
initialEventListeners?: EventListeners<EventMap>
) => {
// eslint-disable-next-line @typescript-eslint/no-shadow
type EventListener<N extends keyof EventMap> = (...args: EventMap[N]) => void;
type RemoveEvent = {
<N extends keyof EventMap>(name?: N, listener?: EventListener<N>): void;
<N extends keyof EventMap>(name?: N, listener?: EventListener<N>[]): void;
<N extends keyof EventMap>(name?: N, listener?: EventListener<N> | EventListener<N>[]): void;
};
type AddEvent = {
(eventListeners: EventListeners<EventMap>): () => void;
<N extends keyof EventMap>(name: N, listener: EventListener<N>): () => void;
<N extends keyof EventMap>(name: N, listener: EventListener<N>[]): () => void;
<N extends keyof EventMap>(
nameOrEventListeners: N | EventListeners<EventMap>,
listener?: EventListener<N> | EventListener<N>[]
): () => void;
};
type TriggerEvent = {
<N extends keyof EventMap>(name: N, args?: EventMap[N]): void;
};
): EventListenerHub<EventMap> => {
const events = new Map<keyof EventMap, Set<EventListener<EventMap, keyof EventMap>>>();
const events = new Map<keyof EventMap, Set<EventListener<keyof EventMap>>>();
const removeEvent: RemoveEvent = <N extends keyof EventMap>(
name?: N,
listener?: EventListener<N> | EventListener<N>[]
): void => {
const removeEvent: RemoveEvent<EventMap> = (name, listener) => {
if (name) {
const eventSet = events.get(name);
manageListener((currListener) => {
@@ -61,10 +67,7 @@ export const createEventListenerHub = <EventMap extends Record<string, any[]>>(
}
};
const addEvent: AddEvent = <N extends keyof EventMap>(
nameOrEventListeners: N | EventListeners<EventMap>,
listener?: EventListener<N> | EventListener<N>[]
): (() => void) => {
const addEvent: AddEvent<EventMap> = ((nameOrEventListeners, listener) => {
if (isString(nameOrEventListeners)) {
const eventSet = events.get(nameOrEventListeners) || new Set();
events.set(nameOrEventListeners, eventSet);
@@ -83,12 +86,9 @@ export const createEventListenerHub = <EventMap extends Record<string, any[]>>(
});
return runEachAndClear.bind(0, offFns);
};
}) as AddEvent<EventMap>; // sorry!
const triggerEvent: TriggerEvent = <N extends keyof EventMap>(
name: N,
args?: EventMap[N]
): void => {
const triggerEvent: TriggerEvent<EventMap> = (name, args) => {
const eventSet = events.get(name);
each(from(eventSet), (event) => {
@@ -102,5 +102,5 @@ export const createEventListenerHub = <EventMap extends Record<string, any[]>>(
addEvent(initialEventListeners || {});
return [addEvent, removeEvent, triggerEvent] as [AddEvent, RemoveEvent, TriggerEvent];
return [addEvent, removeEvent, triggerEvent];
};