"use client"; import { useEffect, useMemo, useRef, useState } from "react"; import { Flex, Stack, Text } from "@mantine/core"; import dayjs from "dayjs"; import advancedFormat from "dayjs/plugin/advancedFormat"; import timezones from "dayjs/plugin/timezone"; import utc from "dayjs/plugin/utc"; import type { WidgetComponentProps } from "../definition"; dayjs.extend(advancedFormat); dayjs.extend(utc); dayjs.extend(timezones); export default function ClockWidget({ options }: WidgetComponentProps<"clock">) { const secondsFormat = options.showSeconds ? ":ss" : ""; const timeFormat = options.is24HourFormat ? `HH:mm${secondsFormat}` : `h:mm${secondsFormat} A`; const dateFormat = options.dateFormat; const timezone = options.useCustomTimezone ? options.timezone : Intl.DateTimeFormat().resolvedOptions().timeZone; const time = useCurrentTime(options); return ( {options.customTitleToggle && ( {options.customTitle} )} {dayjs(time).tz(timezone).format(timeFormat)} {options.showDate && ( {dayjs(time).tz(timezone).format(dateFormat)} )} ); } interface UseCurrentTimeProps { showSeconds: boolean; } const useCurrentTime = ({ showSeconds }: UseCurrentTimeProps) => { const [time, setTime] = useState(new Date()); const timeoutRef = useRef(); const intervalRef = useRef(); const intervalMultiplier = useMemo(() => (showSeconds ? 1 : 60), [showSeconds]); useEffect(() => { setTime(new Date()); timeoutRef.current = setTimeout( () => { setTime(new Date()); intervalRef.current = setInterval(() => { setTime(new Date()); }, intervalMultiplier * 1000); }, intervalMultiplier * 1000 - (1000 * (showSeconds ? 0 : dayjs().second()) + dayjs().millisecond()), ); return () => { clearTimeout(timeoutRef.current); clearInterval(intervalRef.current); }; }, [intervalMultiplier, showSeconds]); return time; };