@usetheo/ui 0.28.2 → 0.30.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -39,6 +39,13 @@ export interface TrendChartProps extends HTMLAttributes<HTMLElement> {
39
39
  height?: number;
40
40
  /** Formats y-axis labels and table cells (tremor vocabulary). */
41
41
  valueFormatter?: (v: number) => string;
42
+ /**
43
+ * Pin the top of the y-axis. Pass a fixed bound (e.g. `1` for a 0–1 score) so the
44
+ * scale is stable and comparable across renders instead of auto-fitting to the data
45
+ * max via {@link niceMax} (which makes 0.68 look near the top of a [0, 0.7] axis).
46
+ * Ignored when ≤ 0. Default: auto (`niceMax`).
47
+ */
48
+ yMax?: number;
42
49
  }
43
50
  declare const TrendChart: import("react").ForwardRefExoticComponent<TrendChartProps & import("react").RefAttributes<HTMLElement>>;
44
51
  export { TrendChart };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export { cn } from "./lib/cn.js";
2
- export { aggregateCost, asChat, contentText, isRedactedThinking, buildLayeredGraph, computeBarLayout, computeTraceBounds, deriveSpanKind, durationMs, flattenAll, flattenVisible, GRAPH_NODE_CAP, isSpanError, KIND_LABEL, niceAxisTicks, packRows, prettyValue, spanCostUsd, toNs, alignSpanTrees, groupByNamespace, traceMetrics, toTranscriptRows, VIRTUALIZE_THRESHOLD, } from "./lib/trace/index.js";
2
+ export { aggregateCost, asChat, contentText, isRedactedThinking, buildLayeredGraph, computeBarLayout, computeTraceBounds, deriveSpanKind, durationMs, flattenAll, flattenVisible, GRAPH_NODE_CAP, isSpanError, KIND_LABEL, niceAxisTicks, packRows, prettyValue, spanCostUsd, spanOwnCostUsd, toNs, alignSpanTrees, groupByNamespace, traceMetrics, toTranscriptRows, VIRTUALIZE_THRESHOLD, } from "./lib/trace/index.js";
3
3
  export type { AlignDelta, AlignRow, AttributeGroup, AxisTick, BarLayout, ChatMessage, FlatSpan, GraphEdge, GraphNode, LayeredGraph, SpanKind, SpanStatus, ToolCall, TraceSpan, TranscriptRow, TranscriptRowStats, } from "./lib/trace/index.js";
4
4
  export { Button, buttonVariants, type ButtonProps } from "./components/primitives/button/index.js";
5
5
  export { Badge, badgeVariants, type BadgeProps } from "./components/primitives/badge/index.js";
package/dist/index.js CHANGED
@@ -153,6 +153,19 @@ function spanCostUsd(span) {
153
153
  }
154
154
  return 0;
155
155
  }
156
+ function spanOwnCostUsd(span) {
157
+ if (typeof span.costUsd === "number" && Number.isFinite(span.costUsd)) {
158
+ return span.costUsd > 0 ? span.costUsd : void 0;
159
+ }
160
+ const attrs = span.attributes ?? {};
161
+ for (const key of COST_ATTRIBUTE_KEYS) {
162
+ if (!(key in attrs)) continue;
163
+ const raw = attrs[key];
164
+ const n = typeof raw === "number" ? raw : typeof raw === "string" ? Number(raw) : Number.NaN;
165
+ if (Number.isFinite(n)) return n > 0 ? n : void 0;
166
+ }
167
+ return void 0;
168
+ }
156
169
  function aggregateCost(span) {
157
170
  const seen = /* @__PURE__ */ new Set();
158
171
  const walk = (s) => {
@@ -209,7 +222,7 @@ function toTranscriptRows(root) {
209
222
  stats: {
210
223
  inputTokens: span.inputTokens ?? 0,
211
224
  outputTokens: span.outputTokens ?? 0,
212
- costUsd: spanCostUsd(span),
225
+ costUsd: spanOwnCostUsd(span),
213
226
  durationMs: durationMs(span)
214
227
  }
215
228
  });
@@ -5074,7 +5087,7 @@ function niceMax(values) {
5074
5087
  const m = Math.max(0, ...values.filter((v) => Number.isFinite(v)));
5075
5088
  if (m <= 0) return 0;
5076
5089
  const pow = 10 ** Math.floor(Math.log10(m));
5077
- return Math.ceil(m / pow) * pow;
5090
+ return Number((Math.ceil(m / pow) * pow).toPrecision(12));
5078
5091
  }
5079
5092
  function seriesPath(points, xScale, yScale) {
5080
5093
  const finite = points.filter((p) => Number.isFinite(p.y));
@@ -5085,7 +5098,29 @@ var VIEW_W = 600;
5085
5098
  var PAD = { top: 8, right: 8, bottom: 4, left: 40 };
5086
5099
  var SPARSE_MARKER_MAX = 5;
5087
5100
  var TrendChart = forwardRef(
5088
- ({ title, series, height = 180, valueFormatter = (v) => String(v), className, ...props }, ref) => {
5101
+ ({
5102
+ title,
5103
+ series,
5104
+ height = 180,
5105
+ valueFormatter = (v) => String(v),
5106
+ yMax: yMaxProp,
5107
+ className,
5108
+ ...props
5109
+ }, ref) => {
5110
+ const [viewW, setViewW] = useState(VIEW_W);
5111
+ const roRef = useRef(null);
5112
+ const setSvgNode = useCallback((node) => {
5113
+ roRef.current?.disconnect();
5114
+ roRef.current = null;
5115
+ if (!node || typeof ResizeObserver === "undefined") return;
5116
+ const measure = () => {
5117
+ const w = node.clientWidth;
5118
+ if (w > 0) setViewW(w);
5119
+ };
5120
+ measure();
5121
+ roRef.current = new ResizeObserver(measure);
5122
+ roRef.current.observe(node);
5123
+ }, []);
5089
5124
  const allPoints = series.flatMap((s) => s.points);
5090
5125
  const hasData = allPoints.some((p) => Number.isFinite(p.y));
5091
5126
  if (!hasData) {
@@ -5115,17 +5150,18 @@ var TrendChart = forwardRef(
5115
5150
  const xs = allPoints.map((p) => p.x);
5116
5151
  const xMin = Math.min(...xs);
5117
5152
  const xMax = Math.max(...xs);
5118
- const yMax = niceMax(allPoints.map((p) => p.y)) || 1;
5153
+ const yMax = yMaxProp != null && yMaxProp > 0 ? yMaxProp : niceMax(allPoints.map((p) => p.y)) || 1;
5119
5154
  const axisXs = Array.from(new Set(allPoints.map((p) => p.x))).sort((a, b) => a - b);
5120
5155
  const yByX = series.map((s) => new Map(s.points.map((p) => [p.x, p.y])));
5121
- const xScale = linScale([xMin, xMax], [PAD.left, VIEW_W - PAD.right]);
5156
+ const xScale = linScale([xMin, xMax], [PAD.left, viewW - PAD.right]);
5122
5157
  const yScale = linScale([0, yMax], [height - PAD.bottom, PAD.top]);
5123
5158
  return /* @__PURE__ */ jsxs("figure", { "data-slot": "trend-chart", ref, className: cn("space-y-1", className), ...props, children: [
5124
5159
  /* @__PURE__ */ jsx("figcaption", { className: "font-semibold text-label-caps text-muted-foreground uppercase", children: title }),
5125
5160
  /* @__PURE__ */ jsxs(
5126
5161
  "svg",
5127
5162
  {
5128
- viewBox: `0 0 ${VIEW_W} ${height}`,
5163
+ ref: setSvgNode,
5164
+ viewBox: `0 0 ${viewW} ${height}`,
5129
5165
  preserveAspectRatio: "none",
5130
5166
  role: "img",
5131
5167
  "aria-label": `${title} trend`,
@@ -5137,7 +5173,7 @@ var TrendChart = forwardRef(
5137
5173
  {
5138
5174
  x1: PAD.left,
5139
5175
  y1: height - PAD.bottom,
5140
- x2: VIEW_W - PAD.right,
5176
+ x2: viewW - PAD.right,
5141
5177
  y2: height - PAD.bottom,
5142
5178
  className: "stroke-border",
5143
5179
  strokeWidth: 1
@@ -5148,7 +5184,7 @@ var TrendChart = forwardRef(
5148
5184
  {
5149
5185
  x1: PAD.left,
5150
5186
  y1: PAD.top,
5151
- x2: VIEW_W - PAD.right,
5187
+ x2: viewW - PAD.right,
5152
5188
  y2: PAD.top,
5153
5189
  className: "stroke-border/50",
5154
5190
  strokeWidth: 1,
@@ -7227,8 +7263,9 @@ function Row3({ row, ...ctx }) {
7227
7263
  stats.inputTokens,
7228
7264
  "\u2192",
7229
7265
  stats.outputTokens,
7230
- " \xB7 ",
7231
- ctx.formatCostUsd(stats.costUsd),
7266
+ " \xB7",
7267
+ " ",
7268
+ stats.costUsd === void 0 ? "\u2014" : ctx.formatCostUsd(stats.costUsd),
7232
7269
  " \xB7",
7233
7270
  " ",
7234
7271
  formatDurationMs(stats.durationMs)
@@ -9067,4 +9104,4 @@ var PromptTemplateEditor = forwardRef(
9067
9104
  );
9068
9105
  PromptTemplateEditor.displayName = "PromptTemplateEditor";
9069
9106
 
9070
- export { AccountMenu, ActionBar, Alert, AnnotationInput, AnnotationSummaryGroup, AttributesTable, Avatar, BadgeWithDot as Badge, Breadcrumb, Button, Card, ChatMessageCard, Checkbox, CodeBlock, Combobox, CommandPalette, CommentThread, ConfirmDialog, CopyButton, DangerZone, DataTable, DatasetItemDiff, DeploymentRow, DescriptionList, Dialog, DiffView, DomainConfig, DropdownMenu, EmptyState, EnvVarEditor, EvaluatorForm, FileDropzone, FormField, GRAPH_NODE_CAP, Histogram, IOCards, Input, JsonViewer, KIND_LABEL, Label, LoginSplit, MessageBranchSelector, MessageCard, MessageItem, MetricCard, MetricsPanel, PageShell, Pagination, PercentileChart, PinInput, PlanBadge, PreviewEnvCard, PriceBreakdown, Progress, ProjectCard, PromptTemplateEditor, PromptVersionDiff, RadioGroup, RollbackUI, ScrollArea, Select, SessionSummary, SessionTimeline, SeverityBadge, Sheet, Sidebar, Skeleton, Slider, SocialAuthRow, SpanGraph, SpanTree, SpanTreeRow, SpanWaterfall, StatTile, StatusDot, StatusIndicator, Stepper, Switch, Table, Tabs, TagInput, TaskHeader, Textarea, Timestamp, Toast, Toaster, TokenCostBreakdown, TooltipWithStatics as Tooltip, TopNav, TraceCompare, TraceTranscript, TrendChart, UpdateBanner, VIRTUALIZE_THRESHOLD, aggregateCost, aggregateSession, alignSpanTrees, asChat, avatarVariants, badgeVariants, buildLayeredGraph, buttonVariants, cn, computeBarLayout, computeHistogram, computePageRange, computeTraceBounds, configToText, contentText, defaultEvaluatorConfig, deriveSpanKind, deriveSteps, diffLines, durationMs, extractVars, fieldPresent, fieldToText, flattenAll, flattenVisible, groupByNamespace, isCategoricalConfig, isContinuousConfig, isFreeformConfig, isNearBottom, isRedactedThinking, isRegexEvaluator, isSpanError, isTargetEvaluator, isThresholdEvaluator, linScale, matchesAccept, niceAxisTicks, niceMax, packRows, prettyValue, seriesPath, sessionBounds, sheetVariants, spanCostUsd, templateToText, toNs, toTranscriptRows, traceMetrics, useStickToBottom, useToast, validateFiles };
9107
+ export { AccountMenu, ActionBar, Alert, AnnotationInput, AnnotationSummaryGroup, AttributesTable, Avatar, BadgeWithDot as Badge, Breadcrumb, Button, Card, ChatMessageCard, Checkbox, CodeBlock, Combobox, CommandPalette, CommentThread, ConfirmDialog, CopyButton, DangerZone, DataTable, DatasetItemDiff, DeploymentRow, DescriptionList, Dialog, DiffView, DomainConfig, DropdownMenu, EmptyState, EnvVarEditor, EvaluatorForm, FileDropzone, FormField, GRAPH_NODE_CAP, Histogram, IOCards, Input, JsonViewer, KIND_LABEL, Label, LoginSplit, MessageBranchSelector, MessageCard, MessageItem, MetricCard, MetricsPanel, PageShell, Pagination, PercentileChart, PinInput, PlanBadge, PreviewEnvCard, PriceBreakdown, Progress, ProjectCard, PromptTemplateEditor, PromptVersionDiff, RadioGroup, RollbackUI, ScrollArea, Select, SessionSummary, SessionTimeline, SeverityBadge, Sheet, Sidebar, Skeleton, Slider, SocialAuthRow, SpanGraph, SpanTree, SpanTreeRow, SpanWaterfall, StatTile, StatusDot, StatusIndicator, Stepper, Switch, Table, Tabs, TagInput, TaskHeader, Textarea, Timestamp, Toast, Toaster, TokenCostBreakdown, TooltipWithStatics as Tooltip, TopNav, TraceCompare, TraceTranscript, TrendChart, UpdateBanner, VIRTUALIZE_THRESHOLD, aggregateCost, aggregateSession, alignSpanTrees, asChat, avatarVariants, badgeVariants, buildLayeredGraph, buttonVariants, cn, computeBarLayout, computeHistogram, computePageRange, computeTraceBounds, configToText, contentText, defaultEvaluatorConfig, deriveSpanKind, deriveSteps, diffLines, durationMs, extractVars, fieldPresent, fieldToText, flattenAll, flattenVisible, groupByNamespace, isCategoricalConfig, isContinuousConfig, isFreeformConfig, isNearBottom, isRedactedThinking, isRegexEvaluator, isSpanError, isTargetEvaluator, isThresholdEvaluator, linScale, matchesAccept, niceAxisTicks, niceMax, packRows, prettyValue, seriesPath, sessionBounds, sheetVariants, spanCostUsd, spanOwnCostUsd, templateToText, toNs, toTranscriptRows, traceMetrics, useStickToBottom, useToast, validateFiles };
@@ -9,6 +9,14 @@ import type { TraceSpan } from "./types.js";
9
9
  * negative costs floor to 0.
10
10
  */
11
11
  export declare function spanCostUsd(span: TraceSpan): number;
12
+ /**
13
+ * A single span's own USD cost for PER-SPAN DISPLAY: the promoted `costUsd` field, else the first
14
+ * parseable cost attribute — but returns `undefined` when the span has no individually-computed
15
+ * cost (absent / non-numeric / ≤ 0). Distinct from `spanCostUsd` (which collapses to 0 for honest
16
+ * `∑` badges): a per-span cost is "exists or doesn't", not a sum, so the absent case renders `—`
17
+ * (em-dash) downstream instead of a fabricated `$0.0000` (M52 / theo-lens#71 Finding 3).
18
+ */
19
+ export declare function spanOwnCostUsd(span: TraceSpan): number | undefined;
12
20
  /**
13
21
  * Sum a span's own cost + all descendants' (`∑`). Total: missing cost counts as 0, never NaN.
14
22
  * Cycle-safe: a repeated/self-referential child is counted at most once (no stack overflow).
@@ -66,7 +66,12 @@ export interface FlatSpan {
66
66
  export interface TranscriptRowStats {
67
67
  inputTokens: number;
68
68
  outputTokens: number;
69
- costUsd: number;
69
+ /**
70
+ * Per-span own cost. `undefined` when the span has no individually-computed cost — the feed
71
+ * renders `—` then, never a fabricated `$0.0000` (M52 / theo-lens#71 Finding 3). A real computed
72
+ * cost is a positive number.
73
+ */
74
+ costUsd: number | undefined;
70
75
  durationMs: number | null;
71
76
  }
72
77
  /** One row in the reader-mode transcript feed. */
package/package.json CHANGED
@@ -1,12 +1,14 @@
1
1
  {
2
2
  "name": "@usetheo/ui",
3
- "version": "0.28.2",
3
+ "version": "0.30.0",
4
4
  "packageManager": "pnpm@10.32.1+sha512.a706938f0e89ac1456b6563eab4edf1d1faf3368d1191fc5c59790e96dc918e4456ab2e67d613de1043d2e8c81f87303e6b40d4ffeca9df15ef1ad567348f2be",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
7
7
  "description": "Violet Forge design system — generic React components + primitives (the non-AI foundation of @theokit/ui).",
8
8
  "sideEffects": false,
9
- "files": ["dist"],
9
+ "files": [
10
+ "dist"
11
+ ],
10
12
  "exports": {
11
13
  ".": {
12
14
  "types": "./dist/index.d.ts",