@trellixio/roaster-coffee
Version:
Beans' product component library
57 lines (56 loc) • 2.38 kB
JavaScript
import { useIsomorphicEffect } from '../useIsomorphicEffect';
/**
* Dispatches a custom event with the given type and detail.
*
* @typeParam T - The type of the detail property.
* @param type - The type of the custom event.
* @param detail - The optional detail property of the custom event.
*/
function dispatchEvent(type, detail) {
window.dispatchEvent(new CustomEvent(type, { detail }));
}
/**
* Creates a custom React hook and event creator function for managing external events with a specified prefix.
*
* @typeParam Handlers - A record containing event handlers keyed by event type.
* @param prefix - The prefix for the event types.
* @returns A tuple containing the custom hook `useExternalEvents` and the event creator function `createEvent`.
*
* @example
* ```typescript
* const [useExternalEvents, createExternalEvent] = createUseExternalEvents<MyEventHandlers>('myPrefix');
* ```
*/
export function createUseExternalEvents(prefix) {
/**
* A custom React hook that listens to external events with the specified prefix and calls the corresponding handlers.
*
* @param events - The event handlers to be called when an external event with the specified prefix is dispatched.
*/
function useExternalEvents(events) {
const handlers = Object.keys(events).reduce((acc, eventKey) => {
acc[`${prefix}:${eventKey}`] = (event) => 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]);
}
/**
* Creates a function that dispatches an event with the specified prefix and event type.
*
* @typeParam EventKey - A key of the Handlers type.
* @param event - The event type.
* @returns A function that takes the payload and dispatches the event.
*/
function createEvent(event) {
return (...payload) => dispatchEvent(`${prefix}:${String(event)}`, payload[0]);
}
return [useExternalEvents, createEvent];
}