UNPKG

@vnmfify/core

Version:

```shell npm i @vnmfify/core -S ```

120 lines (108 loc) 3.19 kB
import { useCallback, useEffect, useMemo, useRef } from "react"; import { useUpdate } from "../hooks"; import { cancelRaf, raf } from "../utils/raf"; import { useToRef } from "../utils/state"; var SECOND = 1000; var MINUTE = 60 * SECOND; var HOUR = 60 * MINUTE; var DAY = 24 * HOUR; function parseTime(time) { var days = Math.floor(time / DAY); var hours = Math.floor(time % DAY / HOUR); var minutes = Math.floor(time % HOUR / MINUTE); var seconds = Math.floor(time % MINUTE / SECOND); var milliseconds = Math.floor(time % SECOND); return { total: time, days, hours, minutes, seconds, milliseconds }; } function isSameTime(time1, time2, interval) { return Math.floor(time1 / interval) === Math.floor(time2 / interval); } export default function useCountdown(options) { var { value: valueProp, autostart: autostartProp, interval: intervalOption = 1000, onChange, onComplete } = options; var update = useUpdate(); var intervalRef = useToRef(Math.max(intervalOption, 1)); var valueRef = useToRef(valueProp); var rafIdRef = useRef(); var statusRef = useRef(); var endTimeRef = useRef(0); var remainRef = useRef(valueProp); var current = parseTime(remainRef.current); var currentRef = useToRef(current); var pause = useCallback(() => { statusRef.current = "paused"; if (rafIdRef.current) { cancelRaf(rafIdRef.current); } }, []); var getCurrentRemain = () => Math.max(endTimeRef.current - Date.now(), 0); var nextRemain = nextValue => { remainRef.current = nextValue; update(); onChange === null || onChange === void 0 ? void 0 : onChange(currentRef.current); if (nextValue === 0) { pause(); onComplete === null || onComplete === void 0 ? void 0 : onComplete(); } }; function macroTick() { rafIdRef.current = raf(() => { if (statusRef.current === "started") { var remainRemain = getCurrentRemain(); if (!isSameTime(remainRemain, remainRef.current, intervalRef.current) || remainRemain === 0) { nextRemain(remainRemain); } if (remainRef.current > 0) { macroTick(); } } }); } var start = useCallback(() => { if (statusRef.current !== "started") { endTimeRef.current = Date.now() + (statusRef.current === "paused" ? remainRef.current : valueRef.current); statusRef.current = "started"; macroTick(); } }, []); var stop = useCallback(() => { pause(); statusRef.current = "stopped"; }, []); var autostart = useCallback(() => { if (autostartProp) { start(); } }, []); var reset = useCallback(() => { stop(); autostart(); }, []); var restart = useCallback(() => { stop(); start(); }, []); useEffect(() => autostart(), []); useEffect(() => restart(), [valueProp]); return useMemo(() => ({ current, start, reset, restart, pause, stop }), [current, pause, reset, restart, start, stop]); } //# sourceMappingURL=use-countdown.js.map