import type { DsProps } from './props'; import * as React from 'react'; import { ArrowDownRight, ArrowUpRight, Minus } from 'lucide-react'; import { cn } from '@/lib/utils'; /** * MetricStrip — modern executive operational metric card strip. * * `items: [{ label, value, delta?, deltaLabel?, invertTrend?, sub?, icon?, tone? }]` */ const TONE = { default: 'text-ink-1', brand: 'text-blue-600 dark:text-blue-400', success: 'text-emerald-600 dark:text-emerald-400', warning: 'text-amber-600 dark:text-amber-400', risk: 'text-red-600 dark:text-red-400', }; const ICON_BG = { default: 'bg-surface-subtle text-ink-3', brand: 'bg-blue-50 text-blue-600 dark:bg-blue-950/60 dark:text-blue-400', success: 'bg-emerald-50 text-emerald-600 dark:bg-emerald-950/60 dark:text-emerald-400', warning: 'bg-amber-50 text-amber-600 dark:bg-amber-950/60 dark:text-amber-400', risk: 'bg-red-50 text-red-600 dark:bg-red-950/60 dark:text-red-400', }; const ACCENT_BAR = { default: 'from-gray-400 to-gray-600', brand: 'from-blue-500 to-indigo-500', success: 'from-emerald-500 to-teal-500', warning: 'from-amber-500 to-orange-500', risk: 'from-red-500 to-rose-500', }; function Delta({ delta, label, invert }) { if (typeof delta !== 'number') return null; const flat = delta === 0; const good = invert ? delta < 0 : delta > 0; const Icon = flat ? Minus : delta > 0 ? ArrowUpRight : ArrowDownRight; return ( {flat ? '0%' : `${Math.abs(delta)}%`} {label && {label}} ); } /** @param {any} props */ export function MetricStrip({ items = [], columns, className, loading = false }: DsProps) { const count = columns ?? Math.min(items.length, 6); const gridCols = { 2: 'sm:grid-cols-2', 3: 'sm:grid-cols-3', 4: 'grid-cols-2 sm:grid-cols-4', 5: 'grid-cols-2 sm:grid-cols-3 xl:grid-cols-5', 6: 'grid-cols-2 sm:grid-cols-3 xl:grid-cols-6', }[count] || 'grid-cols-2 sm:grid-cols-4'; return (
{item.label}
{IconComponent && (