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<UsageProviderKind, UsageProviderPresentation>; /** 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));}
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<UsageProviderKind, UsageProviderPresentation>;
/** 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));
}