@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
JavaScript
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