{"version":3,"file":"use-countdown.cjs","names":[],"sources":["../../src/hooks/use-countdown.ts"],"sourcesContent":["import { useCallback, useEffect, useState } from \"react\";\nimport { useInterval } from \"./use-interval\";\n\n/** Options for {@link useCountdown}. */\nexport interface UseCountdownOptions {\n    /**\n     * How often the remaining time is recomputed, in ms. Default `1000`, which\n     * suits a \"try again in 3s\" label; drop it to ~50 to drive a progress bar.\n     */\n    tickMs?: number;\n}\n\n/**\n * Counts down the time left on a window that started at a known instant.\n *\n * Written around a timestamp rather than a decrementing counter on purpose: the\n * remaining time is recomputed from `Date.now()` on every tick, so a throttled\n * background tab, a slow frame or a `setInterval` that drifts cannot make the\n * countdown disagree with the clock. Remounting recovers the correct value too,\n * which a counter held in state cannot do.\n *\n * The interval stops once it reaches zero instead of ticking forever behind a\n * clamp — `useInterval` pauses on a `null` delay, so reaching zero is what tears\n * the timer down.\n *\n * @param durationMs - Length of the window.\n * @param startedAt - Epoch ms the window opened (`Date.now()` when it started).\n * @param options - Tick cadence.\n * @returns Milliseconds remaining, never below `0`.\n *\n * @example\n * const remaining = useCountdown(60_000, lastSentAt);\n *\n * <button disabled={remaining > 0}>\n *   {remaining > 0 ? `Reenviar em ${Math.ceil(remaining / 1000)}s` : \"Reenviar código\"}\n * </button>\n */\nexport function useCountdown(\n    durationMs: number,\n    startedAt: number,\n    options: UseCountdownOptions = {},\n): number {\n    const { tickMs = 1000 } = options;\n\n    const compute = useCallback(\n        () => Math.max(0, durationMs - (Date.now() - startedAt)),\n        [durationMs, startedAt],\n    );\n\n    const [remaining, setRemaining] = useState(compute);\n\n    useEffect(() => {\n        setRemaining(compute());\n    }, [compute]);\n\n    useInterval(() => setRemaining(compute()), remaining > 0 ? tickMs : null);\n\n    return remaining;\n}\n"],"mappings":"6DAqCA,SAAgB,EACZ,EACA,EACA,EAA+B,CAAC,EAC1B,CACN,GAAM,CAAE,SAAS,KAAS,EAEpB,GAAA,EAAU,EAAA,YAAA,KACN,KAAK,IAAI,EAAG,GAAc,KAAK,IAAI,EAAI,EAAU,EACvD,CAAC,EAAY,CAAS,CAC1B,EAEM,CAAC,EAAW,IAAA,EAAgB,EAAA,SAAA,CAAS,CAAO,EAQlD,OANA,EAAA,EAAA,UAAA,KAAgB,CACZ,EAAa,EAAQ,CAAC,CAC1B,EAAG,CAAC,CAAO,CAAC,EAEZ,EAAA,gBAAkB,EAAa,EAAQ,CAAC,EAAG,EAAY,EAAI,EAAS,IAAI,EAEjE,CACX"}