cx & time helpers

Small, dependency-free helpers the components use internally and that are handy in HUD apps: a class name joiner and formatters for clocks, ages and durations.

import { cx, formatTime, relativeTime, formatAge, formatDuration } from 'jarvis-react-ui';
import { useEffect, useState } from 'react';
import { cx, formatAge, formatDuration, formatTime, relativeTime, Table } from 'jarvis-react-ui';
import type { TableColumn } from 'jarvis-react-ui';

interface Row {
    call: string;
    result: string;
}

const COLUMNS: TableColumn<Row>[] = [
    { key: 'call', header: 'Call', render: (r) => <code className="text-accent">{r.call}</code> },
    { key: 'result', header: 'Result', render: (r) => <code>{r.result}</code> },
];

export default function TimeHelpers() {
    const [bootedAt] = useState(() => new Date().toISOString());
    const [now, setNow] = useState(() => new Date());

    useEffect(() => {
        const id = setInterval(() => setNow(new Date()), 1000);
        return () => clearInterval(id);
    }, []);

    const uptime = now.getTime() - new Date(bootedAt).getTime();
    const rows: Row[] = [
        { call: 'formatTime(bootedAt)', result: formatTime(bootedAt) },
        { call: 'relativeTime(bootedAt)', result: relativeTime(bootedAt) },
        { call: 'formatAge(bootedAt, now)', result: formatAge(bootedAt, now) },
        { call: 'formatDuration(uptime)', result: formatDuration(uptime) },
        { call: "cx('a', uptime > 5000 && 'b')", result: cx('a', uptime > 5000 && 'b') },
    ];

    return <Table columns={COLUMNS} rows={rows} getRowKey={(r) => r.call} dense />;
}

cx

cx('base', isActive && 'active', { muted: isMuted }, ['a', 'b']);

Joins strings, numbers, arrays and objects (keys with truthy values) into one class string and skips falsy values. It does not merge conflicting Tailwind classes; the last one in the generated stylesheet wins.

Time helpers

Function Example output Description
formatTime(iso) 14:30 24-hour clock time of an ISO timestamp.
relativeTime(iso) 1m Compact age: now, Xs, Xm, Xh, Xd.
formatAge(iso, now?) 3m ago Readable age; now defaults to the current time.
formatDuration(ms) 1m 30s Duration in the two largest units.

All of them take ISO 8601 strings (or milliseconds) and use the browser's local time zone.