import { useState } from "react"; import { Clock } from "lucide-react"; import { registerWidget } from "./WidgetRegistry"; import { GRID_SIZE, type ClockConfig, type WidgetComponentProps, } from "../types.js"; import { usePageVisibleInterval } from "../use-page-visible-interval.js"; import { isValidTimezone } from "../clock-timezone"; import { WidgetTitle } from "@termix/plugin-sdk/ui"; function ClockWidget({ widget, config }: WidgetComponentProps) { const { showSeconds, format } = config; // Configs saved before the edit dialog validated timezones can still hold an // unusable one (e.g. "America/New York"), which makes toLocaleTimeString throw. const timezone = config.timezone && isValidTimezone(config.timezone) ? config.timezone : undefined; const [now, setNow] = useState(new Date()); // Minute-level is enough without seconds; pause when the tab is backgrounded. usePageVisibleInterval( () => setNow(new Date()), showSeconds ? 1_000 : 30_000, ); const opts: Intl.DateTimeFormatOptions = { hour: "2-digit", minute: "2-digit", ...(showSeconds ? { second: "2-digit" } : {}), hour12: format === "12h", ...(timezone ? { timeZone: timezone } : {}), }; const dateOpts: Intl.DateTimeFormatOptions = { weekday: "long", month: "short", day: "numeric", ...(timezone ? { timeZone: timezone } : {}), }; const timeStr = now.toLocaleTimeString(undefined, opts); const dateStr = now.toLocaleDateString(undefined, dateOpts); return (
} />
{timeStr} {dateStr} {timezone && ( {timezone} )}
); } registerWidget({ id: "clock", name: "Clock", description: "A live clock with configurable timezone", category: "info", icon: , defaultConfig: { showSeconds: true, format: "24h" }, defaultSize: { w: GRID_SIZE * 8, h: GRID_SIZE * 5 }, minSize: { w: GRID_SIZE * 2, h: GRID_SIZE * 2 }, component: ClockWidget, }); export { ClockWidget };