UNPKG

@tanstack/query-core

Version:

The framework agnostic core that powers TanStack Query

1 lines • 5.47 kB
{"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"}