{"version":3,"file":"use-before-install-prompt.cjs","names":[],"sources":["../../src/hooks/use-before-install-prompt.ts"],"sourcesContent":["import { useCallback, useEffect, useState } from \"react\";\n\ninterface BeforeInstallPromptEvent extends Event {\n    readonly platforms: readonly string[];\n    readonly userChoice: Promise<{ outcome: \"accepted\" | \"dismissed\"; platform: string }>;\n    prompt(): Promise<void>;\n}\n\nexport interface UseBeforeInstallPromptResult {\n    /** True when the browser fired `beforeinstallprompt` and the user has not yet decided. */\n    installable: boolean;\n    /** True after the user accepts the install prompt. */\n    installed: boolean;\n    /**\n     * True when the app is already running as an installed PWA (display-mode\n     * `standalone`/`fullscreen`/`minimal-ui`, or iOS `navigator.standalone`).\n     * Use it to hide install affordances for users who already installed.\n     */\n    isStandalone: boolean;\n    /** Show the install prompt. Resolves with the user's choice. */\n    prompt: () => Promise<\"accepted\" | \"dismissed\" | \"unsupported\">;\n}\n\n/** Detect whether the document is running inside an installed PWA window. */\nfunction detectStandalone(): boolean {\n    if (typeof window === \"undefined\") return false;\n    const displayModes = [\"standalone\", \"fullscreen\", \"minimal-ui\"];\n    const matchesDisplayMode = displayModes.some(\n        (mode) => window.matchMedia?.(`(display-mode: ${mode})`)?.matches,\n    );\n    // iOS Safari exposes the legacy non-standard `navigator.standalone`.\n    const iosStandalone =\n        (window.navigator as Navigator & { standalone?: boolean }).standalone === true;\n    return matchesDisplayMode || iosStandalone;\n}\n\n/**\n * React hook for the PWA install prompt. Captures the `beforeinstallprompt`\n * event so you can defer the install UI to a moment that fits your UX.\n */\nexport function useBeforeInstallPrompt(): UseBeforeInstallPromptResult {\n    const [deferred, setDeferred] = useState<BeforeInstallPromptEvent | null>(null);\n    const [installed, setInstalled] = useState<boolean>(false);\n    const [isStandalone, setIsStandalone] = useState<boolean>(detectStandalone);\n\n    useEffect(() => {\n        if (typeof window === \"undefined\") return;\n        const handler = (event: Event): void => {\n            event.preventDefault();\n            setDeferred(event as BeforeInstallPromptEvent);\n        };\n        const installedHandler = (): void => {\n            setDeferred(null);\n            setInstalled(true);\n            setIsStandalone(true);\n        };\n        const displayModeQuery = window.matchMedia?.(\"(display-mode: standalone)\");\n        const displayModeHandler = (): void => setIsStandalone(detectStandalone());\n        window.addEventListener(\"beforeinstallprompt\", handler);\n        window.addEventListener(\"appinstalled\", installedHandler);\n        displayModeQuery?.addEventListener(\"change\", displayModeHandler);\n        return () => {\n            window.removeEventListener(\"beforeinstallprompt\", handler);\n            window.removeEventListener(\"appinstalled\", installedHandler);\n            displayModeQuery?.removeEventListener(\"change\", displayModeHandler);\n        };\n    }, []);\n\n    const prompt = useCallback(async (): Promise<\"accepted\" | \"dismissed\" | \"unsupported\"> => {\n        if (!deferred) return \"unsupported\";\n        await deferred.prompt();\n        const result = await deferred.userChoice;\n        setDeferred(null);\n        if (result.outcome === \"accepted\") setInstalled(true);\n        return result.outcome;\n    }, [deferred]);\n\n    return {\n        installable: !!deferred,\n        installed,\n        isStandalone,\n        prompt,\n    };\n}\n"],"mappings":"uBAwBA,SAAS,GAA4B,CACjC,GAAI,OAAO,OAAW,IAAa,MAAO,GAE1C,IAAM,EAAqB,CADL,aAAc,aAAc,YACvB,CAAA,CAAa,KACnC,GAAS,OAAO,aAAa,kBAAkB,EAAK,EAAE,CAAC,EAAE,OAC9D,EAEM,EACD,OAAO,UAAmD,aAAe,GAC9E,OAAO,GAAsB,CACjC,CAMA,SAAgB,GAAuD,CACnE,GAAM,CAAC,EAAU,IAAA,EAAe,EAAA,SAAA,CAA0C,IAAI,EACxE,CAAC,EAAW,IAAA,EAAgB,EAAA,SAAA,CAAkB,EAAK,EACnD,CAAC,EAAc,IAAA,EAAmB,EAAA,SAAA,CAAkB,CAAgB,GAE1E,EAAA,EAAA,UAAA,KAAgB,CACZ,GAAI,OAAO,OAAW,IAAa,OACnC,IAAM,EAAW,GAAuB,CACpC,EAAM,eAAe,EACrB,EAAY,CAAiC,CACjD,EACM,MAA+B,CACjC,EAAY,IAAI,EAChB,EAAa,EAAI,EACjB,EAAgB,EAAI,CACxB,EACM,EAAmB,OAAO,aAAa,4BAA4B,EACnE,MAAiC,EAAgB,EAAiB,CAAC,EAIzE,OAHA,OAAO,iBAAiB,sBAAuB,CAAO,EACtD,OAAO,iBAAiB,eAAgB,CAAgB,EACxD,GAAkB,iBAAiB,SAAU,CAAkB,MAClD,CACT,OAAO,oBAAoB,sBAAuB,CAAO,EACzD,OAAO,oBAAoB,eAAgB,CAAgB,EAC3D,GAAkB,oBAAoB,SAAU,CAAkB,CACtE,CACJ,EAAG,CAAC,CAAC,EAEL,IAAM,GAAA,EAAS,EAAA,YAAA,CAAY,SAA+D,CACtF,GAAI,CAAC,EAAU,MAAO,cACtB,MAAM,EAAS,OAAO,EACtB,IAAM,EAAS,MAAM,EAAS,WAG9B,OAFA,EAAY,IAAI,EACZ,EAAO,UAAY,YAAY,EAAa,EAAI,EAC7C,EAAO,OAClB,EAAG,CAAC,CAAQ,CAAC,EAEb,MAAO,CACH,YAAa,CAAC,CAAC,EACf,YACA,eACA,QACJ,CACJ"}