import { useCallback } from 'react'; import * as Events from '../utils/events'; import { emitter } from '../EditorEvent'; import type { EditorEvents, ToolbarEvents } from '../constants'; type SubscribableEvent = ToolbarEvents | EditorEvents; type EventData = { [EditorEvents.UpsertLink]: { text: string; url: string; }; [EditorEvents.EditorChange]: { value: string; toolbarState: Record; }; [ToolbarEvents.ApplyLink]: { text: string; url: string; }; }; type EventDataByEventName = T extends keyof EventData ? EventData[T] : void; /** * Hook to subscribe to events for a rich text editor * @param editorName - The name of the editor to subscribe to events for * @returns An object with two functions: emitEvent and subscribeToEvents * @example * const { emitEvent, subscribeToEvents } = useRichTextEditorEvents('editorName'); * subscribeToEvents(EditorEvents.EditorFocus, () => { * console.log('Editor focused'); * }); * emitEvent({ type: EditorEvents.EditorFocus, data: null }); */ const useRichTextEditorEvents = (editorName: string) => { const normalizeEventName = useCallback( (event: string) => `${editorName}/${event}`, [editorName] ); const subscribeToEvents = useCallback( ( eventName: TEventName, onEvent: (data: EventDataByEventName) => void ) => Events.on( emitter, normalizeEventName(eventName), (eventData: EventDataByEventName) => { onEvent(eventData); } ), [normalizeEventName] ); const emitEvent = useCallback( ({ type, data, }: { type: TEventName; data: TEventName extends keyof EventData ? EventData[TEventName] : unknown; }) => { Events.emit(emitter, normalizeEventName(type), data); }, [normalizeEventName] ); return { emitEvent, subscribeToEvents, }; }; export default useRichTextEditorEvents;