/
create-use-external-events.ts
39 lines (31 loc) · 1.33 KB
/
create-use-external-events.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import { useEffect, useLayoutEffect } from 'react';
function dispatchEvent<T>(type: string, detail?: T) {
window.dispatchEvent(new CustomEvent(type, { detail }));
}
const useIsomorphicEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect;
export function createUseExternalEvents<Handlers extends Record<string, (detail: any) => void>>(
prefix: string
) {
function _useExternalEvents(events: Handlers) {
const handlers = Object.keys(events).reduce((acc, eventKey) => {
acc[`${prefix}:${eventKey}`] = (event: CustomEvent) => events[eventKey](event.detail);
return acc;
}, {});
useIsomorphicEffect(() => {
Object.keys(handlers).forEach((eventKey) => {
window.removeEventListener(eventKey, handlers[eventKey]);
window.addEventListener(eventKey, handlers[eventKey]);
});
return () =>
Object.keys(handlers).forEach((eventKey) => {
window.removeEventListener(eventKey, handlers[eventKey]);
});
}, [handlers]);
}
function createEvent<EventKey extends keyof Handlers>(event: EventKey) {
type Parameter = Parameters<Handlers[EventKey]>[0];
return (...payload: Parameter extends undefined ? [undefined?] : [Parameter]) =>
dispatchEvent(`${prefix}:${String(event)}`, payload[0]);
}
return [_useExternalEvents, createEvent] as const;
}