"use client"; import * as React from "react"; import { Check, ChevronDown, Minus } from "lucide-react"; import { ProviderIcon } from "@/components/brand/provider-icon"; import { Badge } from "@/components/ui/badge"; import { BadgeChips, LifecycleChip } from "@/components/models/badge-chips"; import type { Lifecycle, ModelBadge } from "@/lib/models/badges"; import type { ProviderId } from "@/lib/ai/core/types"; import { cn } from "@/lib/utils"; /** * Compact, pre-formatted row for the public catalog. The server sends only these strings/booleans * (≈ 200 B per model instead of the full PolyModel) and renders the first rows; the rest expands client-side. */ export interface CatalogRow { key: string; provider: ProviderId; name: string; id: string; inPrice: string; outPrice: string; context: string; maxOut: string; reasoning: boolean; vision: boolean; tools: boolean; json: boolean; lifecycle: Lifecycle; badges: ModelBadge[]; } const INITIAL = 8; function Mark({ on }: { on: boolean }) { return on ? : ; } export function PublicCatalogGroup({ rows, provider }: { rows: CatalogRow[]; provider: ProviderId }) { const [expanded, setExpanded] = React.useState(false); const shown = expanded ? rows : rows.slice(0, INITIAL); const hidden = rows.length - shown.length; return ( <> {/* Desktop table */}
{shown.map((m) => ( ))}
Model Input $/1M Output $/1M Context Max out Reasoning Vision Tools Status
{m.name}
{m.id}
{m.inPrice} {m.outPrice} {m.context} {m.maxOut}
{/* Mobile rows */} {hidden > 0 || expanded ? ( ) : null} ); }