@vnmfify/core
Version:
```shell npm i @vnmfify/core -S ```
120 lines (108 loc) • 3.19 kB
JavaScript
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