{"version":3,"file":"focusManager.cjs","names":["Subscribable"],"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\n/**\n * The `FocusManager` manages the focus state within TanStack Query.\n *\n * It can be used to change the default event listeners or to manually change the focus state.\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      // oxlint-disable-next-line typescript/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 override onSubscribe(): void {\n    if (!this.#cleanup) {\n      this.setEventListener(this.#setup)\n    }\n  }\n\n  protected override onUnsubscribe() {\n    if (!this.hasListeners()) {\n      this.#cleanup?.()\n      this.#cleanup = undefined\n    }\n  }\n\n  /**\n   * `setEventListener` can be used to set a custom event listener that will\n   * be used to determine the focus state. The provided `setup` function\n   * receives a `setFocused` callback: call it with a `boolean` to manually\n   * set the focus state, or with no arguments to re-evaluate the current\n   * focus state and notify subscribers.\n   * @param setup - Receives the `setFocused` callback, registers the event listener, and may return\n   * a cleanup function that is called when the listener is replaced or no longer needed.\n   * @example\n   * ```ts\n   * import { focusManager } from '@tanstack/query-core'\n   *\n   * focusManager.setEventListener((handleFocus) => {\n   *   const listener = () => handleFocus()\n   *   // Listen to visibilitychange\n   *   if (typeof window !== 'undefined' && window.addEventListener) {\n   *     window.addEventListener('visibilitychange', listener, false)\n   *   }\n   *\n   *   return () => {\n   *     // Be sure to unsubscribe if a new handler is set\n   *     window.removeEventListener('visibilitychange', listener)\n   *   }\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  /**\n   * `setFocused` can be used to manually set the focus state. Set `undefined`\n   * to fall back to the default focus check.\n   * @param focused - The focus state, or `undefined` to use the default focus check.\n   * @example\n   * ```ts\n   * import { focusManager } from '@tanstack/query-core'\n   *\n   * // Set focused\n   * focusManager.setFocused(true)\n   *\n   * // Set unfocused\n   * focusManager.setFocused(false)\n   *\n   * // Fallback to the default focus check\n   * focusManager.setFocused(undefined)\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  /**\n   * `onFocus` notifies all subscribed listeners with the current focus state.\n   */\n  onFocus(): void {\n    const isFocused = this.isFocused()\n    this.listeners.forEach((listener) => {\n      listener(isFocused)\n    })\n  }\n\n  /**\n   * `isFocused` can be used to get the current focus state.\n   * @returns The focus state set with `setFocused`, or otherwise whether the document is visible.\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    // oxlint-disable-next-line typescript/no-unnecessary-condition\n    return globalThis.document?.visibilityState !== 'hidden'\n  }\n}\n\n/**\n * Singleton instance of {@link FocusManager}, used to manage and observe the focus state within TanStack Query.\n */\nexport const focusManager = new FocusManager()\n"],"mappings":";;;;;;;;AAaA,IAAa,eAAb,cAAkCA,qBAAAA,aAAuB;CACvD;CACA;CAEA;CAEA,cAAc;EACZ,MAAM;EACN,KAAK,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,cAAuC;EACrC,IAAI,CAAC,KAAK,UACR,KAAK,iBAAiB,KAAK,MAAM;CAErC;CAEA,gBAAmC;EACjC,IAAI,CAAC,KAAK,aAAa,GAAG;GACxB,KAAK,WAAW;GAChB,KAAK,WAAW,KAAA;EAClB;CACF;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4BA,iBAAiB,OAAsB;EACrC,KAAK,SAAS;EACd,KAAK,WAAW;EAChB,KAAK,WAAW,OAAO,YAAY;GACjC,IAAI,OAAO,YAAY,WACrB,KAAK,WAAW,OAAO;QAEvB,KAAK,QAAQ;EAEjB,CAAC;CACH;;;;;;;;;;;;;;;;;;;CAoBA,WAAW,SAAyB;EAElC,IADgB,KAAK,aAAa,SACrB;GACX,KAAK,WAAW;GAChB,KAAK,QAAQ;EACf;CACF;;;;CAKA,UAAgB;EACd,MAAM,YAAY,KAAK,UAAU;EACjC,KAAK,UAAU,SAAS,aAAa;GACnC,SAAS,SAAS;EACpB,CAAC;CACH;;;;;CAMA,YAAqB;EACnB,IAAI,OAAO,KAAK,aAAa,WAC3B,OAAO,KAAK;EAKd,OAAO,WAAW,UAAU,oBAAoB;CAClD;AACF;;;;AAKA,MAAa,eAAe,IAAI,aAAa"}