{"version":3,"file":"event-bus-CqrIUE24.mjs","names":[],"sources":["../src/core/event-bus.ts"],"sourcesContent":["import type { Attrs } from '@tiptap/pm/model';\nimport { useEffect } from 'react';\n\nconst EVENT_PREFIX = '@react-email/editor:';\n\n/**\n * Base event map interface for the editor event bus.\n *\n * Components extend this via TypeScript module augmentation:\n * ```ts\n * declare module '@react-email/editor' {\n *   interface EditorEventMap {\n *     'my-component:custom-event': { data: string };\n *   }\n * }\n * ```\n */\nexport interface EditorEventMap {\n  'bubble-menu:add-link': undefined;\n  'node-clicked': NodeClickedEvent;\n}\n\nexport type NodeClickedEvent = {\n  nodeType: string;\n  nodeAttrs: Attrs;\n  nodePos: { pos: number; inside: number };\n};\n\nexport type EditorEventName = keyof EditorEventMap;\n\nexport type EditorEventHandler<T extends EditorEventName> = (\n  payload: EditorEventMap[T],\n) => void | Promise<void>;\n\nexport interface EditorEventSubscription {\n  unsubscribe: () => void;\n}\n\nclass EditorEventBus {\n  private prefixEventName(eventName: EditorEventName): string {\n    return `${EVENT_PREFIX}${String(eventName)}`;\n  }\n\n  dispatch<T extends EditorEventName>(\n    eventName: T,\n    payload: EditorEventMap[T],\n    options?: { target?: EventTarget },\n  ): void {\n    const target = options?.target ?? window;\n    const prefixedEventName = this.prefixEventName(eventName);\n    const event = new CustomEvent(prefixedEventName, {\n      detail: payload,\n      bubbles: false,\n      cancelable: false,\n    });\n    target.dispatchEvent(event);\n  }\n\n  on<T extends EditorEventName>(\n    eventName: T,\n    handler: EditorEventHandler<T>,\n    options?: AddEventListenerOptions & { target?: EventTarget },\n  ): EditorEventSubscription {\n    const target = options?.target ?? window;\n    const prefixedEventName = this.prefixEventName(eventName);\n    const abortController = new AbortController();\n\n    const wrappedHandler = (event: Event) => {\n      const customEvent = event as CustomEvent<EditorEventMap[T]>;\n      const result = handler(customEvent.detail);\n\n      if (result instanceof Promise) {\n        result.catch((error) => {\n          console.error(\n            `Error in async event handler for ${prefixedEventName}:`,\n            { event: customEvent.detail, error },\n          );\n        });\n      }\n    };\n\n    target.addEventListener(prefixedEventName, wrappedHandler, {\n      ...options,\n      signal: abortController.signal,\n    });\n\n    return {\n      unsubscribe: () => {\n        abortController.abort();\n      },\n    };\n  }\n}\n\nexport const editorEventBus = new EditorEventBus();\n\nexport function useEditorEvent<T extends EditorEventName>(\n  eventName: T,\n  handler: EditorEventHandler<T>,\n  options?: AddEventListenerOptions & { target?: EventTarget },\n) {\n  useEffect(() => {\n    const subscription = editorEventBus.on(eventName, handler, options);\n\n    return () => subscription.unsubscribe();\n  }, [eventName, handler, options]);\n}\n"],"mappings":";;AAGA,MAAM,eAAe;AAmCrB,IAAM,iBAAN,MAAqB;CACnB,gBAAwB,WAAoC;AAC1D,SAAO,GAAG,eAAe,OAAO,UAAU;;CAG5C,SACE,WACA,SACA,SACM;EACN,MAAM,SAAS,SAAS,UAAU;EAClC,MAAM,oBAAoB,KAAK,gBAAgB,UAAU;EACzD,MAAM,QAAQ,IAAI,YAAY,mBAAmB;GAC/C,QAAQ;GACR,SAAS;GACT,YAAY;GACb,CAAC;AACF,SAAO,cAAc,MAAM;;CAG7B,GACE,WACA,SACA,SACyB;EACzB,MAAM,SAAS,SAAS,UAAU;EAClC,MAAM,oBAAoB,KAAK,gBAAgB,UAAU;EACzD,MAAM,kBAAkB,IAAI,iBAAiB;EAE7C,MAAM,kBAAkB,UAAiB;GACvC,MAAM,cAAc;GACpB,MAAM,SAAS,QAAQ,YAAY,OAAO;AAE1C,OAAI,kBAAkB,QACpB,QAAO,OAAO,UAAU;AACtB,YAAQ,MACN,oCAAoC,kBAAkB,IACtD;KAAE,OAAO,YAAY;KAAQ;KAAO,CACrC;KACD;;AAIN,SAAO,iBAAiB,mBAAmB,gBAAgB;GACzD,GAAG;GACH,QAAQ,gBAAgB;GACzB,CAAC;AAEF,SAAO,EACL,mBAAmB;AACjB,mBAAgB,OAAO;KAE1B;;;AAIL,MAAa,iBAAiB,IAAI,gBAAgB;AAElD,SAAgB,eACd,WACA,SACA,SACA;AACA,iBAAgB;EACd,MAAM,eAAe,eAAe,GAAG,WAAW,SAAS,QAAQ;AAEnE,eAAa,aAAa,aAAa;IACtC;EAAC;EAAW;EAAS;EAAQ,CAAC"}