{"version":3,"file":"use-service-worker-update.cjs","names":[],"sources":["../../src/hooks/use-service-worker-update.ts"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from \"react\";\nimport { useLatestRef } from \"./use-latest-ref\";\nimport {\n    registerServiceWorker,\n    skipWaiting,\n    type RegisterServiceWorkerOptions,\n} from \"../sw/register-service-worker\";\n\n/**\n * Options for {@link useServiceWorkerUpdate}. Mirrors the registration options\n * minus the callbacks the hook owns internally (`onUpdate`); `onReady` and\n * `onError` still pass through for host-side logging.\n *\n * Leave `autoUpdate` off (the default): this hook exists to hand the reload\n * decision to the user, so a silent auto-reload would defeat the prompt.\n */\nexport type UseServiceWorkerUpdateOptions = Omit<RegisterServiceWorkerOptions, \"onUpdate\">;\n\n/** Reactive service-worker update state plus the apply action. */\nexport interface UseServiceWorkerUpdateResult {\n    /** `true` once a new worker has installed and is waiting to activate. */\n    updateAvailable: boolean;\n    /**\n     * Activate the waiting worker and reload the page once it takes control.\n     * No-op when no update is waiting.\n     */\n    applyUpdate: () => void;\n    /** The active registration, or `null` before it resolves / when unsupported. */\n    registration: ServiceWorkerRegistration | null;\n}\n\n/**\n * Register a service worker and expose a user-driven update flow.\n *\n * Wraps {@link registerServiceWorker}: when a fresh worker finishes installing\n * while the page is still controlled by the old one, `updateAvailable` flips to\n * `true`. Call `applyUpdate` — typically from an \"atualizar\" toast — to tell the\n * waiting worker to activate and reload the page once it takes control.\n *\n * Skips cleanly when the runtime has no service-worker support (`registration`\n * stays `null`, `updateAvailable` stays `false`).\n *\n * @param options - Registration options (`url` required); `autoUpdate` should\n *   stay off so the reload is user-confirmed.\n * @returns The update state and `applyUpdate` action.\n *\n * @example\n * const { updateAvailable, applyUpdate } = useServiceWorkerUpdate({ url: \"/sw.js\" });\n * return (\n *     <UpdatePrompt open={updateAvailable} onUpdate={applyUpdate} />\n * );\n */\nexport function useServiceWorkerUpdate(\n    options: UseServiceWorkerUpdateOptions,\n): UseServiceWorkerUpdateResult {\n    const [updateAvailable, setUpdateAvailable] = useState<boolean>(false);\n    const [registration, setRegistration] = useState<ServiceWorkerRegistration | null>(null);\n    const waitingRef = useRef<ServiceWorker | null>(null);\n\n    const optionsRef = useLatestRef(options);\n\n    useEffect(() => {\n        let cancelled = false;\n        void registerServiceWorker({\n            ...optionsRef.current,\n            onUpdate: (waiting, reg) => {\n                waitingRef.current = waiting;\n                setRegistration(reg);\n                setUpdateAvailable(true);\n            },\n            onReady: (reg) => {\n                if (cancelled) return;\n                setRegistration(reg);\n                if (reg.waiting && navigator.serviceWorker.controller) {\n                    waitingRef.current = reg.waiting;\n                    setUpdateAvailable(true);\n                }\n                optionsRef.current.onReady?.(reg);\n            },\n        }).then((reg) => {\n            if (!cancelled && reg) setRegistration(reg);\n        });\n        return () => {\n            cancelled = true;\n        };\n    }, [options.url, optionsRef]);\n\n    const applyUpdate = useCallback(() => {\n        const waiting = waitingRef.current;\n        if (!waiting || typeof navigator === \"undefined\") return;\n        let reloading = false;\n        navigator.serviceWorker.addEventListener(\"controllerchange\", () => {\n            if (reloading) return;\n            reloading = true;\n            window.location.reload();\n        });\n        skipWaiting(waiting);\n    }, []);\n\n    return { updateAvailable, applyUpdate, registration };\n}\n"],"mappings":"8GAoDA,SAAgB,EACZ,EAC4B,CAC5B,GAAM,CAAC,EAAiB,IAAA,EAAsB,EAAA,SAAA,CAAkB,EAAK,EAC/D,CAAC,EAAc,IAAA,EAAmB,EAAA,SAAA,CAA2C,IAAI,EACjF,GAAA,EAAa,EAAA,OAAA,CAA6B,IAAI,EAE9C,EAAa,EAAA,aAAa,CAAO,EAwCvC,OAtCA,EAAA,EAAA,UAAA,KAAgB,CACZ,IAAI,EAAY,GAoBhB,OAnBA,EAAK,sBAAsB,CACvB,GAAG,EAAW,QACd,UAAW,EAAS,IAAQ,CACxB,EAAW,QAAU,EACrB,EAAgB,CAAG,EACnB,EAAmB,EAAI,CAC3B,EACA,QAAU,GAAQ,CACV,IACJ,EAAgB,CAAG,EACf,EAAI,SAAW,UAAU,cAAc,aACvC,EAAW,QAAU,EAAI,QACzB,EAAmB,EAAI,GAE3B,EAAW,QAAQ,UAAU,CAAG,EACpC,CACJ,CAAC,CAAC,CAAC,KAAM,GAAQ,CACT,CAAC,GAAa,GAAK,EAAgB,CAAG,CAC9C,CAAC,MACY,CACT,EAAY,EAChB,CACJ,EAAG,CAAC,EAAQ,IAAK,CAAU,CAAC,EAcrB,CAAE,kBAAiB,aAAA,EAZN,EAAA,YAAA,KAAkB,CAClC,IAAM,EAAU,EAAW,QAC3B,GAAI,CAAC,GAAW,OAAO,UAAc,IAAa,OAClD,IAAI,EAAY,GAChB,UAAU,cAAc,iBAAiB,uBAA0B,CAC3D,IACJ,EAAY,GACZ,OAAO,SAAS,OAAO,EAC3B,CAAC,EACD,EAAA,YAAY,CAAO,CACvB,EAAG,CAAC,CAEsB,EAAa,cAAa,CACxD"}