UNPKG

@flanksource/clicky-ui

Version:

Flanksource Clicky UI — React component library built on shadcn/ui with light/dark and density theming.

147 lines (146 loc) 4.46 kB
import { jsx } from "react/jsx-runtime"; import { cn } from "../../lib/utils.js"; function parseTimestamp(value) { if (value == null) return null; if (value instanceof Date) return Number.isNaN(value.getTime()) ? null : value; if (typeof value === "number") { const ms = value < 1e12 ? value * 1e3 : value; const d = new Date(ms); return Number.isNaN(d.getTime()) ? null : d; } if (typeof value === "string") { const trimmed = value.trim(); if (!trimmed) return null; const d = new Date(trimmed); return Number.isNaN(d.getTime()) ? null : d; } return null; } const UNIT_MS = { s: 1e3, m: 6e4, h: 36e5, d: 864e5, w: 6048e5 }; const RELATIVE_PATTERN = /^now\s*([+-])\s*(\d+)\s*([smhdw])$/i; function resolveDateMath(value, now = /* @__PURE__ */ new Date()) { if (value == null) return null; if (typeof value === "string") { const trimmed = value.trim(); if (!trimmed) return null; if (trimmed.toLowerCase() === "now") return new Date(now.getTime()); const match = trimmed.match(RELATIVE_PATTERN); if (match) { const [, sign, amount, unit] = match; const unitMs = UNIT_MS[unit.toLowerCase()]; if (!unitMs) return null; const delta = Number(amount) * unitMs * (sign === "-" ? -1 : 1); return new Date(now.getTime() + delta); } } return parseTimestamp(value); } const MS_PER_MINUTE = 6e4; const MS_PER_DAY = 864e5; function chooseTimestampFormat(values) { if (values.length === 0) return "iso"; let min = Infinity; let max = -Infinity; for (const d of values) { const t = d.getTime(); if (t < min) min = t; if (t > max) max = t; } const span = max - min; if (span <= MS_PER_MINUTE) return "relative"; const minDate = new Date(min); const maxDate = new Date(max); if (minDate.getFullYear() === maxDate.getFullYear() && minDate.getMonth() === maxDate.getMonth() && minDate.getDate() === maxDate.getDate()) { return "time"; } if (minDate.getFullYear() === maxDate.getFullYear() && span <= MS_PER_DAY * 365) { return "short"; } return "iso"; } function formatTimestamp(date, format, now = /* @__PURE__ */ new Date()) { switch (format) { case "relative": return formatRelative(date, now); case "time": return date.toLocaleTimeString(void 0, { hour: "2-digit", minute: "2-digit", second: "2-digit" }); case "short": return date.toLocaleString(void 0, { month: "short", day: "numeric", hour: "2-digit", minute: "2-digit" }); case "iso": default: return formatIso(date); } } function formatIso(date) { const yyyy = date.getFullYear(); const mm = String(date.getMonth() + 1).padStart(2, "0"); const dd = String(date.getDate()).padStart(2, "0"); const hh = String(date.getHours()).padStart(2, "0"); const min = String(date.getMinutes()).padStart(2, "0"); return `${yyyy}-${mm}-${dd} ${hh}:${min}`; } function formatRelative(date, now) { const diffMs = now.getTime() - date.getTime(); const future = diffMs < 0; const abs = Math.abs(diffMs); const sec = Math.round(abs / 1e3); let value; if (sec < 1) value = "just now"; else if (sec < 60) value = `${sec}s`; else if (sec < 3600) value = `${Math.round(sec / 60)}m`; else if (sec < 86400) value = `${Math.round(sec / 3600)}h`; else value = `${Math.round(sec / 86400)}d`; if (value === "just now") return value; return future ? `in ${value}` : `${value} ago`; } function modeToFormat(mode, dataFormat) { switch (mode) { case "absolute": return "iso"; case "relative": return "relative"; case "time": return "time"; case "auto": default: return dataFormat; } } function Timestamp({ value, format, showTitleOnHover = true, className }) { const parsed = parseTimestamp(value); if (!parsed) return /* @__PURE__ */ jsx("span", { className: cn("text-muted-foreground", className), children: "—" }); const display = formatTimestamp(parsed, format); const title = showTitleOnHover ? parsed.toISOString() : void 0; return /* @__PURE__ */ jsx( "span", { className: cn("tabular-nums whitespace-nowrap text-muted-foreground", className), title, children: display } ); } export { Timestamp, chooseTimestampFormat, formatTimestamp, modeToFormat, parseTimestamp, resolveDateMath }; //# sourceMappingURL=Timestamp.js.map