2025-07-07 22:30:33 -04:00
|
|
|
import { useEffect, useState } from "react";
|
|
|
|
|
|
|
|
|
|
interface HMS {
|
|
|
|
|
hour: number;
|
|
|
|
|
minute: number;
|
|
|
|
|
second: number;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
interface Props {
|
2025-08-15 07:25:04 -04:00
|
|
|
override?: number;
|
2025-07-07 22:30:33 -04:00
|
|
|
startAt?: HMS;
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-15 07:25:04 -04:00
|
|
|
const formatMs = (elapsed: number) => {
|
|
|
|
|
let seconds = Math.floor(elapsed / 1000);
|
|
|
|
|
let minutes = Math.floor(seconds / 60);
|
|
|
|
|
let hours = Math.floor(minutes / 60);
|
|
|
|
|
seconds = seconds % 60;
|
|
|
|
|
minutes = minutes % 60;
|
|
|
|
|
hours = hours % 24;
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
hour: hours,
|
|
|
|
|
minute: minutes,
|
|
|
|
|
second: seconds,
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
function Timer({ override, startAt }: Props) {
|
2025-07-07 22:30:33 -04:00
|
|
|
const [time, setTime] = useState<HMS>({
|
|
|
|
|
hour: 0,
|
|
|
|
|
minute: 0,
|
|
|
|
|
second: 0,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
2025-08-15 07:25:04 -04:00
|
|
|
if (override) {
|
|
|
|
|
const formatted = formatMs(override);
|
|
|
|
|
setTime(() => formatted);
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-07 22:30:33 -04:00
|
|
|
const start = performance.now();
|
|
|
|
|
|
|
|
|
|
const loop = () => {
|
|
|
|
|
const elapsed = performance.now() - start;
|
2025-08-15 07:25:04 -04:00
|
|
|
const formatted = formatMs(elapsed);
|
2025-07-07 22:30:33 -04:00
|
|
|
setTime(() => ({
|
2025-08-15 07:25:04 -04:00
|
|
|
hour: formatted.hour + (startAt?.hour ?? 0),
|
|
|
|
|
minute: formatted.minute + (startAt?.minute ?? 0),
|
|
|
|
|
second: formatted.second + (startAt?.second ?? 0),
|
2025-07-07 22:30:33 -04:00
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
rAF = requestAnimationFrame(loop);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let rAF = requestAnimationFrame(loop);
|
|
|
|
|
|
|
|
|
|
return () => cancelAnimationFrame(rAF);
|
2025-08-15 07:25:04 -04:00
|
|
|
}, [override, startAt]);
|
2025-07-07 22:30:33 -04:00
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div>
|
|
|
|
|
{String(time.hour).padStart(2, "0")}:
|
|
|
|
|
{String(time.minute).padStart(2, "0")}:
|
|
|
|
|
{String(time.second).padStart(2, "0")}
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export { Timer };
|