"use client"; /** * EventRow — single row in the horizontal event-feed timeline. * * No card chrome. The row is a single typographic line: mono timestamp, * severity dot, actor mention, action verb, channel jump, excerpt. * * Hover reveals full excerpt and selection state; click toggles selection * so the right rail / command line can target the event. */ import { type ReactNode, useCallback } from "react"; import { cn } from "@/lib/utils"; export type EventSeverity = "neutral" | "signal" | "amber" | "vermilion"; export interface FeedEvent { /** Stable id from the upstream record. Used as React key. */ id: string; /** Unix epoch ms. */ ts: number; /** Severity tone — drives dot color and zebra fill. */ severity: EventSeverity; /** Display label for the actor ("alice", "@everyone", "Carl-bot"). */ actor: string; /** Verb describing the action ("sent", "flagged", "joined", "muted"). */ action: string; /** Channel reference (monogram display only — no chrome). */ channel?: string | null; /** Message excerpt or action payload text. Truncated when long. */ excerpt: string; /** Optional metadata tag (e.g. "ai:flag", "voice:join"). */ tag?: string | null; } interface EventRowProps { event: FeedEvent; selected?: boolean; onSelect?: (id: string) => void; } const SEVERITY_DOT: Record = { neutral: "oklch(0.46 0.02 70)", signal: "var(--color-signal)", amber: "var(--color-amber)", vermilion: "var(--color-vermilion)", }; const SEVERITY_FILL: Record = { neutral: "transparent", signal: "oklch(0.78 0.17 125 / 0.06)", amber: "oklch(0.80 0.15 70 / 0.07)", vermilion: "oklch(0.62 0.21 25 / 0.08)", }; function formatTimestamp(ts: number): string { const d = new Date(ts); const pad = (n: number) => String(n).padStart(2, "0"); return `${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`; } export function EventRow({ event, selected, onSelect }: EventRowProps) { const handleClick = useCallback(() => { onSelect?.(event.id); }, [event.id, onSelect]); const dot: ReactNode = ( ); return ( ); }