@daimo/pay
Version:
Seamless crypto payments. Onboard users from any chain, any coin into your app with one click.
49 lines (46 loc) • 2.66 kB
JavaScript
import { jsxs, jsx } from 'react/jsx-runtime';
import { useState, useEffect } from 'react';
const CircleTimer = ({ total, size = 24, stroke = 3, currentTime, onTimeChange, children, }) => {
// timestamp (ms) when timer ends
const [target, setTarget] = useState(Date.now() + (currentTime ?? total) * 1000);
const [left, setLeft] = useState(currentTime ?? total);
// react to external currentTime updates
useEffect(() => {
if (currentTime !== undefined) {
setTarget(Date.now() + currentTime * 1000);
setLeft(currentTime);
}
}, [currentTime]);
// interval tick
useEffect(() => {
const id = setInterval(() => {
const secs = Math.max(0, Math.ceil((target - Date.now()) / 1000));
setLeft(secs);
onTimeChange?.(secs);
if (secs === 0)
clearInterval(id);
}, 1000);
return () => clearInterval(id);
}, [target, onTimeChange]);
const ratio = Math.round((left * 100) / total); // 0-100
// Ensure stroke stays within viewBox: use floor to be conservative
const radius = Math.floor((size - stroke) / 2);
const circumference = Math.round((2 * 314 * radius) / 100); // 2πr, π≈3.14
const dashoffset = Math.round((circumference * (100 - ratio)) / 100);
// colour transition: green → orange → red
const color = ratio <= 10
? "var(--timer-red, #D92D20)"
: ratio <= 40
? "var(--timer-orange, #F79009)"
: "var(--timer-green, #12D18E)";
const center = Math.round(size / 2);
return (jsxs("svg", { viewBox: `0 0 ${size} ${size}`, width: size, height: size, role: "img", "aria-label": `Timer: ${left}s left of ${total}s`, children: [jsx("circle", { cx: center, cy: center, r: radius, fill: "transparent", stroke: "var(--ck-body-background-secondary, #EEE)", strokeWidth: stroke }), jsx("circle", { cx: center, cy: center, r: radius, fill: "transparent", stroke: color, strokeWidth: stroke, strokeDasharray: circumference, strokeDashoffset: dashoffset, strokeLinecap: "round", style: { transition: "stroke-dashoffset 1s linear" }, transform: `rotate(-90 ${center} ${center})` }), children && (jsx("foreignObject", { x: "0", y: "0", width: size, height: size, children: jsx("div", { style: {
display: "flex",
alignItems: "center",
justifyContent: "center",
width: "100%",
height: "100%",
}, children: children }) }))] }));
};
export { CircleTimer as default };
//# sourceMappingURL=CircleTimer.js.map