{"version":3,"file":"use-storage-estimate.cjs","names":[],"sources":["../../src/hooks/use-storage-estimate.ts"],"sourcesContent":["import { useCallback, useEffect, useState } from \"react\";\n\n/** Raw usage/quota reading from the Storage API, in bytes. */\nexport interface StorageEstimate {\n    /** Bytes currently used by this origin, or `null` when unknown. */\n    usage: number | null;\n    /** Total bytes available to this origin, or `null` when unknown. */\n    quota: number | null;\n}\n\n/**\n * `true` when `navigator.storage` exposes the estimate/persist APIs. Guards\n * every call so the helpers stay safe under SSR and older browsers.\n */\nfunction storageManagerAvailable(): boolean {\n    return (\n        typeof navigator !== \"undefined\" &&\n        \"storage\" in navigator &&\n        typeof navigator.storage?.estimate === \"function\"\n    );\n}\n\n/**\n * Read the origin's current storage usage and quota.\n *\n * @returns The estimate, or `{ usage: null, quota: null }` when unsupported.\n */\nexport async function estimateStorage(): Promise<StorageEstimate> {\n    if (!storageManagerAvailable()) return { usage: null, quota: null };\n    const estimate = await navigator.storage.estimate();\n    return { usage: estimate.usage ?? null, quota: estimate.quota ?? null };\n}\n\n/**\n * Ask the browser to make this origin's storage persistent, so IndexedDB and\n * the Cache Storage are not silently evicted under disk pressure — essential\n * for durable offline-first data.\n *\n * The browser may grant silently, prompt, or deny based on engagement heuristics.\n *\n * @returns `true` when storage is (now or already) persisted, else `false`.\n */\nexport async function requestPersistentStorage(): Promise<boolean> {\n    if (\n        typeof navigator === \"undefined\" ||\n        !(\"storage\" in navigator) ||\n        typeof navigator.storage?.persist !== \"function\"\n    ) {\n        return false;\n    }\n    if (typeof navigator.storage.persisted === \"function\") {\n        const already = await navigator.storage.persisted();\n        if (already) return true;\n    }\n    return navigator.storage.persist();\n}\n\n/** Reactive storage-quota state exposed by {@link useStorageEstimate}. */\nexport interface UseStorageEstimateResult extends StorageEstimate {\n    /** `true` when the Storage API is available. */\n    supported: boolean;\n    /** `usage / quota` in `[0, 1]`, or `null` when either value is unknown. */\n    ratio: number | null;\n    /** Whether storage is persisted, `null` before the first read / unsupported. */\n    persisted: boolean | null;\n    /** `true` during the initial read or a `refresh`. */\n    loading: boolean;\n    /** Re-read usage/quota and the persisted flag from the browser. */\n    refresh: () => Promise<void>;\n    /** Request persistent storage; refreshes state and returns the outcome. */\n    requestPersist: () => Promise<boolean>;\n}\n\n/**\n * Track the origin's storage usage, quota and persistence flag, refreshing on\n * demand. Pair with {@link requestPersistentStorage} to surface a \"usando X de\n * Y MB\" meter and a \"tornar armazenamento permanente\" action.\n *\n * @param options - `pollMs` re-reads the estimate on an interval (`0` = off,\n *   the default).\n * @returns The reactive storage state and actions.\n *\n * @example\n * const { usage, quota, ratio, persisted, requestPersist } = useStorageEstimate();\n * return <Meter value={ratio ?? 0} onClick={requestPersist} />;\n */\nexport function useStorageEstimate(options: { pollMs?: number } = {}): UseStorageEstimateResult {\n    const { pollMs = 0 } = options;\n    const [supported] = useState<boolean>(() => storageManagerAvailable());\n    const [usage, setUsage] = useState<number | null>(null);\n    const [quota, setQuota] = useState<number | null>(null);\n    const [persisted, setPersisted] = useState<boolean | null>(null);\n    const [loading, setLoading] = useState<boolean>(supported);\n\n    const refresh = useCallback(async () => {\n        if (!supported) return;\n        setLoading(true);\n        try {\n            const estimate = await estimateStorage();\n            setUsage(estimate.usage);\n            setQuota(estimate.quota);\n            if (typeof navigator.storage?.persisted === \"function\") {\n                setPersisted(await navigator.storage.persisted());\n            }\n        } finally {\n            setLoading(false);\n        }\n    }, [supported]);\n\n    const requestPersist = useCallback(async () => {\n        const granted = await requestPersistentStorage();\n        await refresh();\n        setPersisted(granted);\n        return granted;\n    }, [refresh]);\n\n    useEffect(() => {\n        void refresh();\n    }, [refresh]);\n\n    useEffect(() => {\n        if (pollMs <= 0 || !supported || typeof window === \"undefined\") return;\n        const id = window.setInterval(() => {\n            void refresh();\n        }, pollMs);\n        return () => window.clearInterval(id);\n    }, [pollMs, supported, refresh]);\n\n    const ratio = usage !== null && quota !== null && quota > 0 ? usage / quota : null;\n\n    return {\n        supported,\n        usage,\n        quota,\n        ratio,\n        persisted,\n        loading,\n        refresh,\n        requestPersist,\n    };\n}\n"],"mappings":"uBAcA,SAAS,GAAmC,CACxC,OACI,OAAO,UAAc,KACrB,YAAa,WACb,OAAO,UAAU,SAAS,UAAa,UAE/C,CAOA,eAAsB,GAA4C,CAC9D,GAAI,CAAC,EAAwB,EAAG,MAAO,CAAE,MAAO,KAAM,MAAO,IAAK,EAClE,IAAM,EAAW,MAAM,UAAU,QAAQ,SAAS,EAClD,MAAO,CAAE,MAAO,EAAS,OAAS,KAAM,MAAO,EAAS,OAAS,IAAK,CAC1E,CAWA,eAAsB,GAA6C,CAY/D,OAVI,OAAO,UAAc,KACrB,EAAE,YAAa,YACf,OAAO,UAAU,SAAS,SAAY,WAE/B,GAEP,OAAO,UAAU,QAAQ,WAAc,YAEnC,MADkB,UAAU,QAAQ,UAAU,EAC9B,GAEjB,UAAU,QAAQ,QAAQ,CACrC,CA+BA,SAAgB,EAAmB,EAA+B,CAAC,EAA6B,CAC5F,GAAM,CAAE,SAAS,GAAM,EACjB,CAAC,IAAA,EAAa,EAAA,SAAA,KAAwB,EAAwB,CAAC,EAC/D,CAAC,EAAO,IAAA,EAAY,EAAA,SAAA,CAAwB,IAAI,EAChD,CAAC,EAAO,IAAA,EAAY,EAAA,SAAA,CAAwB,IAAI,EAChD,CAAC,EAAW,IAAA,EAAgB,EAAA,SAAA,CAAyB,IAAI,EACzD,CAAC,EAAS,IAAA,EAAc,EAAA,SAAA,CAAkB,CAAS,EAEnD,GAAA,EAAU,EAAA,YAAA,CAAY,SAAY,CAC/B,KACL,GAAW,EAAI,EACf,GAAI,CACA,IAAM,EAAW,MAAM,EAAgB,EACvC,EAAS,EAAS,KAAK,EACvB,EAAS,EAAS,KAAK,EACnB,OAAO,UAAU,SAAS,WAAc,YACxC,EAAa,MAAM,UAAU,QAAQ,UAAU,CAAC,CAExD,QAAU,CACN,EAAW,EAAK,CACpB,CAVe,CAWnB,EAAG,CAAC,CAAS,CAAC,EAER,GAAA,EAAiB,EAAA,YAAA,CAAY,SAAY,CAC3C,IAAM,EAAU,MAAM,EAAyB,EAG/C,OAFA,MAAM,EAAQ,EACd,EAAa,CAAO,EACb,CACX,EAAG,CAAC,CAAO,CAAC,EAgBZ,OAdA,EAAA,EAAA,UAAA,KAAgB,CACZ,EAAa,CACjB,EAAG,CAAC,CAAO,CAAC,GAEZ,EAAA,EAAA,UAAA,KAAgB,CACZ,GAAI,GAAU,GAAK,CAAC,GAAa,OAAO,OAAW,IAAa,OAChE,IAAM,EAAK,OAAO,gBAAkB,CAChC,EAAa,CACjB,EAAG,CAAM,EACT,UAAa,OAAO,cAAc,CAAE,CACxC,EAAG,CAAC,EAAQ,EAAW,CAAO,CAAC,EAIxB,CACH,YACA,QACA,QACA,MANU,IAAU,MAAQ,IAAU,MAAQ,EAAQ,EAAI,EAAQ,EAAQ,KAO1E,YACA,UACA,UACA,gBACJ,CACJ"}