import EventEmitter from "eventemitter3"; import { atom, useAtom } from "jotai"; import type { DependencyList } from "react"; import { useCallback, useEffect } from "react"; type EventDataMap = { "request_params.focus_value": string; "request_pane.focus_tab": undefined; }; export function useRequestEditorEvent< Event extends keyof EventDataMap, Data extends EventDataMap[Event], >(event: Event, fn: (data: Data) => void, deps?: DependencyList) { useEffect(() => { emitter.on(event, fn); return () => { emitter.off(event, fn); }; // oxlint-disable-next-line react-hooks/exhaustive-deps -- We're handing deps manually }, deps); } export const urlKeyAtom = atom(Math.random().toString()); export const urlParamsKeyAtom = atom(Math.random().toString()); export function useRequestEditor() { const [urlParametersKey, setUrlParametersKey] = useAtom(urlParamsKeyAtom); const [urlKey, setUrlKey] = useAtom(urlKeyAtom); const focusParamsTab = useCallback(() => { emitter.emit("request_pane.focus_tab", undefined); }, []); const focusParamValue = useCallback( (name: string) => { focusParamsTab(); requestAnimationFrame(() => emitter.emit("request_params.focus_value", name)); }, [focusParamsTab], ); const forceUrlRefresh = useCallback(() => setUrlKey(Math.random().toString()), [setUrlKey]); const forceParamsRefresh = useCallback( () => setUrlParametersKey(Math.random().toString()), [setUrlParametersKey], ); return [ { urlParametersKey, urlKey, }, { focusParamValue, focusParamsTab, forceParamsRefresh, forceUrlRefresh, }, ] as const; } const emitter = new (class RequestEditorEventEmitter { #emitter: EventEmitter = new EventEmitter(); emit( event: Event, data: Data, ) { this.#emitter.emit(event, data); } on( event: Event, fn: (data: Data) => void, ) { this.#emitter.on(event, fn); } off( event: Event, fn: (data: Data) => void, ) { this.#emitter.off(event, fn); } })();