{"version":3,"file":"focusManager.cjs","names":["Subscribable","#setup","#cleanup","#focused"],"sources":["../../src/focusManager.ts"],"sourcesContent":["import { Subscribable } from './subscribable'\n\ntype Listener = (focused: boolean) => void\n\ntype SetupFn = (\n  setFocused: (focused?: boolean) => void,\n) => (() => void) | undefined\n\nexport class FocusManager extends Subscribable<Listener> {\n  #focused?: boolean\n  #cleanup?: () => void\n\n  #setup: SetupFn\n\n  constructor() {\n    super()\n    this.#setup = (onFocus) => {\n      // addEventListener does not exist in React Native, but window does\n      // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n      if (typeof window !== 'undefined' && window.addEventListener) {\n        const listener = () => onFocus()\n        // Listen to visibilitychange\n        window.addEventListener('visibilitychange', listener, false)\n\n        return () => {\n          // Be sure to unsubscribe if a new handler is set\n          window.removeEventListener('visibilitychange', listener)\n        }\n      }\n      return\n    }\n  }\n\n  protected onSubscribe(): void {\n    if (!this.#cleanup) {\n      this.setEventListener(this.#setup)\n    }\n  }\n\n  protected onUnsubscribe() {\n    if (!this.hasListeners()) {\n      this.#cleanup?.()\n      this.#cleanup = undefined\n    }\n  }\n\n  setEventListener(setup: SetupFn): void {\n    this.#setup = setup\n    this.#cleanup?.()\n    this.#cleanup = setup((focused) => {\n      if (typeof focused === 'boolean') {\n        this.setFocused(focused)\n      } else {\n        this.onFocus()\n      }\n    })\n  }\n\n  setFocused(focused?: boolean): void {\n    const changed = this.#focused !== focused\n    if (changed) {\n      this.#focused = focused\n      this.onFocus()\n    }\n  }\n\n  onFocus(): void {\n    const isFocused = this.isFocused()\n    this.listeners.forEach((listener) => {\n      listener(isFocused)\n    })\n  }\n\n  isFocused(): boolean {\n    if (typeof this.#focused === 'boolean') {\n      return this.#focused\n    }\n\n    // document global can be unavailable in react native\n    // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n    return globalThis.document?.visibilityState !== 'hidden'\n  }\n}\n\nexport const focusManager = new FocusManager()\n"],"mappings":";;;AAQA,IAAa,eAAb,cAAkCA,qBAAAA,aAAuB;CACvD;CACA;CAEA;CAEA,cAAc;EACZ,MAAM;EACN,KAAKC,UAAU,YAAY;GAGzB,IAAI,OAAO,WAAW,eAAe,OAAO,kBAAkB;IAC5D,MAAM,iBAAiB,QAAQ;IAE/B,OAAO,iBAAiB,oBAAoB,UAAU,KAAK;IAE3D,aAAa;KAEX,OAAO,oBAAoB,oBAAoB,QAAQ;IACzD;GACF;EAEF;CACF;CAEA,cAA8B;EAC5B,IAAI,CAAC,KAAKC,UACR,KAAK,iBAAiB,KAAKD,MAAM;CAErC;CAEA,gBAA0B;EACxB,IAAI,CAAC,KAAK,aAAa,GAAG;GACxB,KAAKC,WAAW;GAChB,KAAKA,WAAW,KAAA;EAClB;CACF;CAEA,iBAAiB,OAAsB;EACrC,KAAKD,SAAS;EACd,KAAKC,WAAW;EAChB,KAAKA,WAAW,OAAO,YAAY;GACjC,IAAI,OAAO,YAAY,WACrB,KAAK,WAAW,OAAO;QAEvB,KAAK,QAAQ;EAEjB,CAAC;CACH;CAEA,WAAW,SAAyB;EAElC,IADgB,KAAKC,aAAa,SACrB;GACX,KAAKA,WAAW;GAChB,KAAK,QAAQ;EACf;CACF;CAEA,UAAgB;EACd,MAAM,YAAY,KAAK,UAAU;EACjC,KAAK,UAAU,SAAS,aAAa;GACnC,SAAS,SAAS;EACpB,CAAC;CACH;CAEA,YAAqB;EACnB,IAAI,OAAO,KAAKA,aAAa,WAC3B,OAAO,KAAKA;EAKd,OAAO,WAAW,UAAU,oBAAoB;CAClD;AACF;AAEA,MAAa,eAAe,IAAI,aAAa"}