import type { UsageProviderKind } from "@t3tools/contracts"; import { ClaudeAI, GrokIcon, type Icon, OpenAI } from "../Icons"; type UsageProviderPresentation = { readonly label: string; readonly color: string; readonly mark: Icon; }; /** * Exhaustive presentation for providers supported by the usage contract. * Declaration order is reused by every chart and table, so adding a provider * only requires its contract support and one entry here. */ export const PROVIDER_PRESENTATION = { codex: { label: "Codex", color: "var(--contrast-foreground)", mark: OpenAI, }, claude: { label: "Claude Code", color: "#d97757", mark: ClaudeAI, }, grok: { label: "Grok Build", // Contrast-aware neutral between the Codex series and muted chart chrome. color: "color-mix(in oklab, var(--contrast-foreground) 72%, var(--background))", mark: GrokIcon, }, } satisfies Record; /** Stable provider reading order across charts, summaries, tables, and hover rows. */ export const PROVIDER_ORDER = Object.keys(PROVIDER_PRESENTATION) as UsageProviderKind[]; /** Providers with real activity, independent of the metric currently displayed. */ export function providersWithUsage( totals: readonly { readonly provider: UsageProviderKind; readonly costUsd: number; readonly totalTokens: number; }[], ): readonly UsageProviderKind[] { const active = new Set( totals .filter((entry) => entry.totalTokens > 0 || entry.costUsd > 0) .map((entry) => entry.provider), ); return PROVIDER_ORDER.filter((provider) => active.has(provider)); }