import { CheckIcon, CopyIcon } from 'lucide-react'; import { DateTime } from 'luxon'; import { useCallback, useMemo, useRef, useState } from 'react'; import { cn } from '../../lib/utils'; import { Popover, PopoverContent, PopoverTrigger } from '../../primitives/popover'; const HOVER_DELAY_MS = 500; export type LocalTimeProps = { date: Date | string; className?: string; }; export const LocalTime = ({ date, className }: LocalTimeProps) => { const [open, setOpen] = useState(false); const [copiedField, setCopiedField] = useState(null); const hoverTimeout = useRef | null>(null); const isMouseOver = useRef(false); const dt = useMemo(() => DateTime.fromJSDate(new Date(date)), [date]); const relative = dt.toRelative() ?? ''; const local = dt.toFormat('yyyy-MM-dd HH:mm:ss ZZZZ'); const utc = dt.toUTC().toFormat('yyyy-MM-dd HH:mm:ss') + ' UTC'; const unix = Math.floor(dt.toSeconds()).toString(); const onMouseEnter = useCallback(() => { isMouseOver.current = true; hoverTimeout.current = setTimeout(() => { if (isMouseOver.current) { setOpen(true); } }, HOVER_DELAY_MS); }, []); const onMouseLeave = useCallback(() => { isMouseOver.current = false; if (hoverTimeout.current) { clearTimeout(hoverTimeout.current); hoverTimeout.current = null; } setTimeout(() => { if (!isMouseOver.current) { setOpen(false); } }, 200); }, []); const onCopy = async (label: string, value: string) => { await navigator.clipboard.writeText(value); setCopiedField(label); setTimeout(() => setCopiedField(null), 1500); }; return ( {relative} { isMouseOver.current = true; }} onMouseLeave={onMouseLeave} >
void onCopy('Local', local)} /> void onCopy('UTC', utc)} /> void onCopy('Unix', unix)} />
); }; type TimeRowProps = { label: string; value: string; isCopied: boolean; onCopy: () => void; }; const TimeRow = ({ label, value, isCopied, onCopy }: TimeRowProps) => (
{label}: {value}
);