import * as React from 'react'; import { asyncTask } from '../utils'; import type { DispatchApi, DispatchInit, Listener } from './types'; /** * Context of the dispatch. */ export const DispatchContext = React.createContext( undefined ); DispatchContext.displayName = 'UIKitDispatchContext'; /** * Properties of the dispatch context. */ type DispatchContextProps = React.PropsWithChildren<{ value?: DispatchInit }>; /** * The dispatch context's provider. * @param param0 {@link DispatchContextProps} * @returns The Dispatch Provider */ export function DispatchContextProvider({ children }: DispatchContextProps) { const map = new Map>(); const v = { addListener: (key, listener) => { if (map.has(key)) { const s = map.get(key)!; s.add(listener); } else { const s = new Set(); s.add(listener); map.set(key, s); } }, removeListener: (key, listener) => { if (map.has(key)) { const s = map.get(key); if (s?.has(listener)) { s.delete(listener); } } }, emit: (key, ...args: any[]) => { const s = map.get(key); asyncTask(() => { s?.forEach((v) => { v?.(...args); // v.apply(null, [...args]); // v.call(null, ...args); }); }); }, emitSync: (key, ...args: any[]) => { const s = map.get(key); s?.forEach((v) => { v?.(...args); // v.apply(null, [...args]); // v.call(null, ...args); }); }, } as DispatchApi; return ( {children} ); } /** * The dispatch context's hook. * @returns dispatch {@link DispatchApi} */ export function useDispatchContext(): DispatchApi { const dis = React.useContext(DispatchContext); if (!dis) throw Error(`${DispatchContext.displayName} is not provided`); return dis; }