{"version":3,"file":"use-poll.cjs","names":[],"sources":["../../src/http/use-poll.ts"],"sourcesContent":["import { useEffect, useRef, useState } from \"react\";\n\nexport interface UsePollOptions<T> {\n    /** Polling interval in ms. */\n    interval: number;\n    /** Disable polling without unmounting. Default: false. */\n    disabled?: boolean;\n    /** Stop polling once the predicate returns true. */\n    stopWhen?: (data: T) => boolean;\n    /** Called on each error. */\n    onError?: (error: unknown) => void;\n}\n\nexport interface UsePollResult<T> {\n    data: T | null;\n    error: unknown;\n    loading: boolean;\n    stop: () => void;\n    start: () => void;\n}\n\n/**\n * Poll an async factory on a fixed interval. Skips overlapping requests if a\n * prior call has not finished. Pause via `disabled` or `stopWhen`.\n */\nexport function usePoll<T>(\n    factory: () => Promise<T>,\n    options: UsePollOptions<T>,\n): UsePollResult<T> {\n    const { interval, disabled = false, stopWhen, onError } = options;\n    const [data, setData] = useState<T | null>(null);\n    const [error, setError] = useState<unknown>(null);\n    const [loading, setLoading] = useState<boolean>(!disabled);\n    const stopped = useRef<boolean>(disabled);\n    const inFlight = useRef<boolean>(false);\n    const timer = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n    async function tick(): Promise<void> {\n        if (stopped.current || inFlight.current) return;\n        inFlight.current = true;\n        try {\n            const next = await factory();\n            if (stopped.current) return;\n            setData(next);\n            setError(null);\n            if (stopWhen?.(next)) stopped.current = true;\n        } catch (err) {\n            if (!stopped.current) {\n                setError(err);\n                onError?.(err);\n            }\n        } finally {\n            inFlight.current = false;\n            setLoading(false);\n            if (!stopped.current) {\n                timer.current = setTimeout(tick, interval);\n            }\n        }\n    }\n\n    useEffect(() => {\n        stopped.current = disabled;\n        if (disabled) {\n            if (timer.current) clearTimeout(timer.current);\n            return;\n        }\n        setLoading(true);\n        void tick();\n        return () => {\n            stopped.current = true;\n            if (timer.current) clearTimeout(timer.current);\n        };\n        // eslint-disable-next-line react-hooks/exhaustive-deps\n    }, [interval, disabled]);\n\n    return {\n        data,\n        error,\n        loading,\n        stop: () => {\n            stopped.current = true;\n            if (timer.current) clearTimeout(timer.current);\n        },\n        start: () => {\n            if (!stopped.current) return;\n            stopped.current = false;\n            void tick();\n        },\n    };\n}\n"],"mappings":"uBAyBA,SAAgB,EACZ,EACA,EACgB,CAChB,GAAM,CAAE,WAAU,WAAW,GAAO,WAAU,WAAY,EACpD,CAAC,EAAM,IAAA,EAAW,EAAA,SAAA,CAAmB,IAAI,EACzC,CAAC,EAAO,IAAA,EAAY,EAAA,SAAA,CAAkB,IAAI,EAC1C,CAAC,EAAS,IAAA,EAAc,EAAA,SAAA,CAAkB,CAAC,CAAQ,EACnD,GAAA,EAAU,EAAA,OAAA,CAAgB,CAAQ,EAClC,GAAA,EAAW,EAAA,OAAA,CAAgB,EAAK,EAChC,GAAA,EAAQ,EAAA,OAAA,CAA6C,IAAI,EAE/D,eAAe,GAAsB,CAC7B,OAAQ,SAAW,EAAS,SAChC,GAAS,QAAU,GACnB,GAAI,CACA,IAAM,EAAO,MAAM,EAAQ,EAC3B,GAAI,EAAQ,QAAS,OACrB,EAAQ,CAAI,EACZ,EAAS,IAAI,EACT,IAAW,CAAI,IAAG,EAAQ,QAAU,GAC5C,OAAS,EAAK,CACL,EAAQ,UACT,EAAS,CAAG,EACZ,IAAU,CAAG,EAErB,QAAU,CACN,EAAS,QAAU,GACnB,EAAW,EAAK,EACX,EAAQ,UACT,EAAM,QAAU,WAAW,EAAM,CAAQ,EAEjD,CAlBmB,CAmBvB,CAiBA,OAfA,EAAA,EAAA,UAAA,KAAgB,CAEZ,GADA,EAAQ,QAAU,EACd,EAAU,CACN,EAAM,SAAS,aAAa,EAAM,OAAO,EAC7C,MACJ,CAGA,OAFA,EAAW,EAAI,EACf,EAAU,MACG,CACT,EAAQ,QAAU,GACd,EAAM,SAAS,aAAa,EAAM,OAAO,CACjD,CAEJ,EAAG,CAAC,EAAU,CAAQ,CAAC,EAEhB,CACH,OACA,QACA,UACA,SAAY,CACR,EAAQ,QAAU,GACd,EAAM,SAAS,aAAa,EAAM,OAAO,CACjD,EACA,UAAa,CACJ,EAAQ,UACb,EAAQ,QAAU,GAClB,EAAU,EACd,CACJ,CACJ"}