UNPKG

@momentum-ui/react-collaboration

Version:

Cisco Momentum UI Framework for React Collaboration Applications

80 lines (66 loc) 2.88 kB
import { v4 as uuidV4 } from 'uuid'; /** * An event target to handle communication between instances of OverlayAlert and Popover. * This will enable us to keep track of Popover instances (specifically those with hideOnEsc = true) * which are opened while an OverlayAlert is rendered. While such Popover instances remain open, the OverlayAlert * will not close on Esc. * * This operates on the assumption that any Popover instance that is opened after an OverlayAlert is * rendered on the screen is part of the content of said OverlayAlert and should be closed before the OverlayAlert * itself. */ export enum EventType { TIPPY_INSTANCE_ADDED = 'tippyInstanceAdded', TIPPY_INSTANCE_REMOVED = 'tippyInstanceRemoved', } type CustomEventHandler = (event: CustomEvent) => void; type EventHandler = (data?: unknown) => void; const eventHandlers: Record<EventType, Record<string, CustomEventHandler>> = { [EventType.TIPPY_INSTANCE_ADDED]: {}, [EventType.TIPPY_INSTANCE_REMOVED]: {}, }; /** * Event target used for Popover instances with hideOnEsc = true */ const eventTarget = new EventTarget(); /** * Dispatch a custom event to the event target. * @param eventType The category, allowing for listeners to listen to specific events * @param data The data associated with the event (provided in the custom event detail) */ const dispatchEvent = (eventType: EventType, data?: unknown): void => { eventTarget.dispatchEvent(new CustomEvent(eventType, { detail: { data } })); }; /** * Add a listener for a specific type (category) of event. * This wraps the provided event handler to obfuscate the use of the custom event. * Due to this the event listener is stored against an ID which can be used to remove it later. * @param eventType The category of event * @param handler The handler function to call, expecting a type and data arguments * @returns The ID of the listener added */ const addListener = (eventType: EventType, handler: EventHandler): string => { const id = uuidV4(); const eventHandler = ({ detail: { data } }: CustomEvent) => { handler(data); }; eventTarget.addEventListener(eventType, eventHandler); eventHandlers[eventType][id] = eventHandler; return id; }; /** * Remove a listener for a specific type (category) of event. * Removes the stored listener based on the event type and handler ID provided. * @param eventType The category of event * @param id The ID of the listener to be removed */ const removeListener = (eventType: EventType, id: string): void => { const eventHandler = eventHandlers[eventType][id]; if (!eventHandler) { console.warn(`PopoverEvents:removeListener - No event handler found for ID: ${id}`); return; } eventTarget.removeEventListener(eventType, eventHandler); delete eventHandlers[eventType][id]; }; export { dispatchEvent, addListener, removeListener };