import type { ReactNode } from "react"; import { Button, Tooltip } from "@cloudflare/kumo"; import type { ViewModel } from "./model.ts"; import { relativeTime } from "./time.ts"; export function snapshotAge(view: ViewModel, now = Date.now()): string { const age = view.updatedAt && relativeTime(view.updatedAt, now); return age === "Just now" ? "just now" : age || "an unknown time"; } export function staleReason(view: ViewModel): string | undefined { return view.stale ? `Refresh first. This data is from ${snapshotAge(view)}.` : undefined; } /** Disabled controls still have a focusable tooltip target, including in open dialogs. */ export function WriteHint({ reason, children }: { reason?: string; children: ReactNode }) { return reason ? ( }> {children} ) : <>{children}; } export function FreshnessStamp({ view, retry }: { view: ViewModel; retry?: () => Promise }) { if (!view.state || !view.updatedAt) return null; const time = }> {snapshotAge(view)} ; // A retry of a failed read stays stale, with its time visible, until it succeeds. return
{view.stale ? <> Couldn't refresh. Last updated {time}. {retry && } : view.refreshing ? }> Refreshing… : Updated {time}}
; }