import Link from 'next/link'; import { Sparkline } from '@/components/charts/sparkline'; import { CompanyTierBadge, CountryChip } from '@/components/ui/badges'; import { LiveAgo } from '@/components/ui/live'; import { cn } from '@/lib/cn'; import { fmtInt, fmtPctSigned, fmtScore, num } from '@/lib/format'; import { descriptionOf, logoCandidates } from '@/lib/profile'; import { routes } from '@/lib/site'; import type { CompanyCard } from '@/lib/types'; import { CompanyLogo } from './company-logo'; /** * Directory rows: dense table on ≥ md (logo · name + domain + one-line description · country · industry · activity · * hiring 30d · AI · events · sensors · sparkline · last event) and stacked cards below. Missing metrics render as a dash, * never 0. Logos are lazy with a monogram fallback; the description is the attributed profile paragraph when present. */ export function CompanyTable({ items, className, rank = false, showSparkline = true, showDescription = true, valueLabel, formatValue, formatDelta }: { items: (CompanyCard & { rank?: number; value?: number; delta?: number | null })[]; className?: string; rank?: boolean; showSparkline?: boolean; showDescription?: boolean; valueLabel?: string; formatValue?: (c: CompanyCard & { value?: number }) => string; formatDelta?: (c: CompanyCard & { delta?: number | null }) => string | null }) { if (!items.length) return
No companies match these filters yet.
; return (| # | }Company | Country | Industry | {valueLabel &&{valueLabel} | } {valueLabel && formatDelta &&Δ | }Activity | Hiring 30d | AI | Events | Sensors | {showSparkline &&30 d | }Last event |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| {c.rank} | }
|
|
{c.industry_primary ? {c.industry_primary.replace(/-/g, ' ')} : '—'} | {valueLabel &&{formatValue ? formatValue(c) : fmtScore(c.value)} | } {valueLabel && formatDelta &&{d ?? '—'} | }{fmtScore(c.metrics.activity_score)} | 0 ? 'text-positive' : h < 0 ? 'text-danger' : ''))}>{h === null ? '—' : fmtPctSigned(h)} | {fmtScore(c.metrics.ai_adoption)} | {fmtInt(c.counts.events)} | {fmtInt(c.counts.sensors)} | {showSparkline && (
|
)}
|
{c.display_name}
{c.canonical_domain} {c.industry_primary ? ` · ${c.industry_primary.replace(/-/g, ' ')}` : ''}
No monitored evidence available yet.
; const fmt = format ?? ((v: number | null) => (v === null ? '—' : metric.startsWith('hiring') ? fmtPctSigned(v) : fmtScore(v))); return (