{"version":3,"file":"Observable.min.mjs","names":[],"sources":["../../src/Observable.ts"],"sourcesContent":["export type TEventCallback<T = any> = (options: T) => any;\n\ntype EventRegistryObject<E> = {\n  [K in keyof E]?: TEventCallback<E[K]>;\n};\n\n/**\n * @see {@link http://fabric5.fabricjs.com/fabric-intro-part-2#events}\n * @see {@link http://fabric5.fabricjs.com/events|Events demo}\n */\nexport class Observable<EventSpec> {\n  private __eventListeners: Record<keyof EventSpec, TEventCallback[]> =\n    {} as Record<keyof EventSpec, TEventCallback[]>;\n\n  /**\n   * Observes specified event\n   * @alias on\n   * @param {string} eventName Event name (eg. 'after:render')\n   * @param {EventRegistryObject} handlers key/value pairs (eg. {'after:render': handler, 'selection:cleared': handler})\n   * @param {Function} handler Function that receives a notification when an event of the specified type occurs\n   * @return {Function} disposer\n   */\n  on<K extends keyof EventSpec, E extends EventSpec[K]>(\n    eventName: K,\n    handler: TEventCallback<E>,\n  ): VoidFunction;\n  on(handlers: EventRegistryObject<EventSpec>): VoidFunction;\n  on<K extends keyof EventSpec, E extends EventSpec[K]>(\n    arg0: K | EventRegistryObject<EventSpec>,\n    handler?: TEventCallback<E>,\n  ): VoidFunction {\n    if (!this.__eventListeners) {\n      this.__eventListeners = {} as Record<keyof EventSpec, TEventCallback[]>;\n    }\n    if (typeof arg0 === 'object') {\n      // one object with key/value pairs was passed\n      Object.entries(arg0).forEach(([eventName, handler]) => {\n        this.on(eventName as K, handler as TEventCallback);\n      });\n      return () => this.off(arg0);\n    } else if (handler) {\n      const eventName = arg0;\n      if (!this.__eventListeners[eventName]) {\n        this.__eventListeners[eventName] = [];\n      }\n      this.__eventListeners[eventName].push(handler);\n      return () => this.off(eventName, handler);\n    } else {\n      // noop\n      return () => false;\n    }\n  }\n\n  /**\n   * Observes specified event **once**\n   * @alias once\n   * @param {string} eventName Event name (eg. 'after:render')\n   * @param {EventRegistryObject} handlers key/value pairs (eg. {'after:render': handler, 'selection:cleared': handler})\n   * @param {Function} handler Function that receives a notification when an event of the specified type occurs\n   * @return {Function} disposer\n   */\n  once<K extends keyof EventSpec, E extends EventSpec[K]>(\n    eventName: K,\n    handler: TEventCallback<E>,\n  ): VoidFunction;\n  once(handlers: EventRegistryObject<EventSpec>): VoidFunction;\n  once<K extends keyof EventSpec, E extends EventSpec[K]>(\n    arg0: K | EventRegistryObject<EventSpec>,\n    handler?: TEventCallback<E>,\n  ): VoidFunction {\n    if (typeof arg0 === 'object') {\n      // one object with key/value pairs was passed\n      const disposers: VoidFunction[] = [];\n      Object.entries(arg0).forEach(([eventName, handler]) => {\n        disposers.push(this.once(eventName as K, handler as TEventCallback));\n      });\n      return () => disposers.forEach((d) => d());\n    } else if (handler) {\n      const disposer = this.on<K, E>(\n        arg0,\n        function onceHandler(this: Observable<EventSpec>, ...args) {\n          handler.call(this, ...args);\n          disposer();\n        },\n      );\n      return disposer;\n    } else {\n      // noop\n      return () => false;\n    }\n  }\n\n  /**\n   * @private\n   * @param {string} eventName\n   * @param {Function} [handler]\n   */\n  private _removeEventListener<K extends keyof EventSpec>(\n    eventName: K,\n    handler?: TEventCallback,\n  ) {\n    if (!this.__eventListeners[eventName]) {\n      return;\n    }\n\n    if (handler) {\n      const eventListener = this.__eventListeners[eventName];\n      const index = eventListener.indexOf(handler);\n      index > -1 && eventListener.splice(index, 1);\n    } else {\n      this.__eventListeners[eventName] = [];\n    }\n  }\n\n  /**\n   * Unsubscribe all event listeners for eventname.\n   * Do not use this pattern. You could kill internal fabricJS events.\n   * We know we should have protected events for internal flows, but we don't have yet\n   * @deprecated\n   * @param {string} eventName event name (eg. 'after:render')\n   */\n  off<K extends keyof EventSpec>(eventName: K): void;\n  /**\n   * unsubscribe an event listener\n   * @param {string} eventName event name (eg. 'after:render')\n   * @param {TEventCallback} handler event listener to unsubscribe\n   */\n  off<K extends keyof EventSpec>(eventName: K, handler: TEventCallback): void;\n  /**\n   * unsubscribe event listeners\n   * @param handlers handlers key/value pairs (eg. {'after:render': handler, 'selection:cleared': handler})\n   */\n  off(handlers: EventRegistryObject<EventSpec>): void;\n  /**\n   * unsubscribe all event listeners\n   */\n  off(): void;\n  off<K extends keyof EventSpec>(\n    arg0?: K | EventRegistryObject<EventSpec>,\n    handler?: TEventCallback,\n  ) {\n    if (!this.__eventListeners) {\n      return;\n    }\n\n    // remove all key/value pairs (event name -> event handler)\n    if (typeof arg0 === 'undefined') {\n      for (const eventName in this.__eventListeners) {\n        this._removeEventListener(eventName);\n      }\n    }\n    // one object with key/value pairs was passed\n    else if (typeof arg0 === 'object') {\n      Object.entries(arg0).forEach(([eventName, handler]) => {\n        this._removeEventListener(eventName as K, handler as TEventCallback);\n      });\n    } else {\n      this._removeEventListener(arg0, handler);\n    }\n  }\n\n  /**\n   * Fires event with an optional options object\n   * @param {String} eventName Event name to fire\n   * @param {Object} [options] Options object\n   */\n  fire<K extends keyof EventSpec>(eventName: K, options?: EventSpec[K]) {\n    if (!this.__eventListeners) {\n      return;\n    }\n\n    const listenersForEvent = this.__eventListeners[eventName]?.concat();\n    if (listenersForEvent) {\n      for (let i = 0; i < listenersForEvent.length; i++) {\n        listenersForEvent[i].call(this, options || {});\n      }\n    }\n  }\n}\n"],"mappings":"2GAUA,IAAa,EAAb,KAAA,CAAA,aAAA,CAAA,EAAA,KACU,mBACN,EAAA,CAAA,CAeF,GACE,EACA,EAAA,CAKA,GAHK,KAAK,mBACR,KAAK,iBAAmB,EAAA,EAEN,OAAT,GAAS,SAKlB,OAHA,OAAO,QAAQ,EAAA,CAAM,SAAA,CAAU,EAAW,KAAA,CACxC,KAAK,GAAG,EAAgB,EAAA,EAAA,KAEb,KAAK,IAAI,EAAA,CAAA,GACb,EAAS,CAClB,IAAM,EAAY,EAKlB,OAJK,KAAK,iBAAiB,KACzB,KAAK,iBAAiB,GAAa,EAAA,EAErC,KAAK,iBAAiB,GAAW,KAAK,EAAA,KACzB,KAAK,IAAI,EAAW,EAAA,CAGjC,UAAA,CAAa,EAiBjB,KACE,EACA,EAAA,CAEA,GAAoB,OAAT,GAAS,SAAU,CAE5B,IAAM,EAA4B,EAAA,CAIlC,OAHA,OAAO,QAAQ,EAAA,CAAM,SAAA,CAAU,EAAW,KAAA,CACxC,EAAU,KAAK,KAAK,KAAK,EAAgB,EAAA,CAAA,EAAA,KAE9B,EAAU,QAAS,GAAM,GAAA,CAAA,CAAA,GAC7B,EAAS,CAClB,IAAM,EAAW,KAAK,GACpB,EACA,SAAA,GAAqD,EAAA,CACnD,EAAQ,KAAK,KAAA,GAAS,EAAA,CACtB,GAAA,EAAA,CAGJ,OAAO,EAGP,UAAA,CAAa,EASjB,qBACE,EACA,EAAA,CAEA,GAAK,KAAK,iBAAiB,GAI3B,GAAI,EAAS,CACX,IAAM,EAAgB,KAAK,iBAAiB,GACtC,EAAQ,EAAc,QAAQ,EAAA,CACpC,EAAA,IAAc,EAAc,OAAO,EAAO,EAAA,MAE1C,KAAK,iBAAiB,GAAa,EAAA,CA2BvC,IACE,EACA,EAAA,CAEA,GAAK,KAAK,iBAKV,GAAW,IAAX,IAAoB,GAClB,IAAK,IAAM,KAAa,KAAK,iBAC3B,KAAK,qBAAqB,EAAA,MAIL,OAAT,GAAS,SACvB,OAAO,QAAQ,EAAA,CAAM,SAAA,CAAU,EAAW,KAAA,CACxC,KAAK,qBAAqB,EAAgB,EAAA,EAAA,CAG5C,KAAK,qBAAqB,EAAM,EAAA,CASpC,KAAgC,EAAc,EAAA,CAAA,IAAA,EAC5C,GAAA,CAAK,KAAK,iBACR,OAGF,IAAM,GAAA,EAAoB,KAAK,iBAAiB,KAAA,KAAA,IAAA,GAAA,EAAY,QAAA,CAC5D,GAAI,EACF,IAAK,IAAI,EAAI,EAAG,EAAI,EAAkB,OAAQ,IAC5C,EAAkB,GAAG,KAAK,KAAM,GAAW,EAAA,CAAA,GAAA,OAAA,KAAA"}