@tangle-network/charts 0.20.3 → 0.21.1
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.
|
@@ -323,6 +323,8 @@ interface FlowSpan {
|
|
|
323
323
|
icon?: string;
|
|
324
324
|
/** Recorded values only. Absent means unknown and is shown as Unknown, never as zero. */
|
|
325
325
|
costUsd?: number;
|
|
326
|
+
/** `lower`: `costUsd` is a floor and prints "≥". Spans inherit a trace's `costBound: 'lower'`. */
|
|
327
|
+
costBound?: 'lower' | 'upper';
|
|
326
328
|
promptTokens?: number;
|
|
327
329
|
completionTokens?: number;
|
|
328
330
|
/** Short producer summaries shown in the span card. */
|
|
@@ -354,7 +356,10 @@ interface FlowSpanMark {
|
|
|
354
356
|
interface FlowPause {
|
|
355
357
|
startMs: number;
|
|
356
358
|
endMs: number;
|
|
359
|
+
/** A few words on the band, such as 'Paused 4 h 40 m'. */
|
|
357
360
|
label: string;
|
|
361
|
+
/** The full reason, shown on hover and focus of the label rather than printed across the rows. */
|
|
362
|
+
detail?: string;
|
|
358
363
|
}
|
|
359
364
|
/** A host verdict: `label` is the legend text, `tone` the status color. */
|
|
360
365
|
interface FlowOutcome {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as BreakdownInput, B as Refusal, C as MarkKind, D as YScale, E as XCategory, F as Figure, H as Tier, I as Interval, L as IntervalMethod, M as CostBasis, N as Estimate, O as YTarget, P as Exclusion, R as MatrixCell, S as ChartMark, T as MarkerShape, U as TierCounts, V as Setup, W as isRefusal, _ as checkerColor, a as TimelineLane, b as BandKind, c as TimelineTick, d as ENDING_COLORS, f as ENDING_ORDER, g as TickOutcome, h as RunEnding, i as FlowTrace, j as ComparisonRow, k as YTick, l as timeline, m as OUTCOME_ORDER, n as FlowOutcome, o as TimelineOptions, p as OUTCOME_COLORS, r as FlowSpan, s as TimelineSpan, t as FlowMarker, u as CHECKER_HUES, v as PointFields, w as MarkVerdict, x as ChartBand, y as PointGlyph, z as RateRow } from "./flow-trace-
|
|
1
|
+
import { A as BreakdownInput, B as Refusal, C as MarkKind, D as YScale, E as XCategory, F as Figure, H as Tier, I as Interval, L as IntervalMethod, M as CostBasis, N as Estimate, O as YTarget, P as Exclusion, R as MatrixCell, S as ChartMark, T as MarkerShape, U as TierCounts, V as Setup, W as isRefusal, _ as checkerColor, a as TimelineLane, b as BandKind, c as TimelineTick, d as ENDING_COLORS, f as ENDING_ORDER, g as TickOutcome, h as RunEnding, i as FlowTrace, j as ComparisonRow, k as YTick, l as timeline, m as OUTCOME_ORDER, n as FlowOutcome, o as TimelineOptions, p as OUTCOME_COLORS, r as FlowSpan, s as TimelineSpan, t as FlowMarker, u as CHECKER_HUES, v as PointFields, w as MarkVerdict, x as ChartBand, y as PointGlyph, z as RateRow } from "./flow-trace-DBJY1YAA.js";
|
|
2
2
|
//#region src/block.d.ts
|
|
3
3
|
interface RenderFigureOptions {
|
|
4
4
|
/** Chart uses a closed data disclosure; plot keeps only the SVG and accessible data. */
|
|
@@ -132,6 +132,8 @@
|
|
|
132
132
|
border-inline: 1px dashed color-mix(in oklab, var(--fw-text) 24%, transparent); }
|
|
133
133
|
.fw-root .fw-pause-label { position: sticky; top: 4px; display: block; width: max-content; max-width: calc(100% - 8px); margin: 4px auto 0; padding: 0 8px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
|
134
134
|
border-radius: 4px; font-size: 12px; line-height: 20px; color: var(--fw-muted); background: var(--fw-surface); box-shadow: inset 0 0 0 1px var(--fw-border); }
|
|
135
|
+
/* The label alone takes the pointer, for its reason; the band stays click-through to the rows. */
|
|
136
|
+
.fw-root .fw-pause-label[title] { pointer-events: auto; cursor: help; }
|
|
135
137
|
.fw-root .fw-marker-label { position: absolute; top: 2px; left: 3px; max-width: 160px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; padding: 0 4px; border-radius: 4px; font-size: 12px; line-height: 16px; color: var(--fw-marker); background: var(--fw-surface); box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--fw-marker) 40%, transparent); }
|
|
136
138
|
.fw-root .fw-marker-label-left { left: auto; right: 3px; }
|
|
137
139
|
.fw-root .fw-marker[data-tone="warn"], .fw-root .fw-event[data-tone="warn"] { --fw-marker: var(--fw-amber); }
|
package/dist/react/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { B as Refusal, C as MarkKind, D as YScale, E as XCategory, F as Figure, O as YTarget, S as ChartMark, T as MarkerShape, a as TimelineLane, b as BandKind, c as TimelineTick, g as TickOutcome, i as FlowTrace, k as YTick, o as TimelineOptions, r as FlowSpan, s as TimelineSpan, t as FlowMarker, v as PointFields, w as MarkVerdict, x as ChartBand, y as PointGlyph } from "../flow-trace-
|
|
1
|
+
import { B as Refusal, C as MarkKind, D as YScale, E as XCategory, F as Figure, O as YTarget, S as ChartMark, T as MarkerShape, a as TimelineLane, b as BandKind, c as TimelineTick, g as TickOutcome, i as FlowTrace, k as YTick, o as TimelineOptions, r as FlowSpan, s as TimelineSpan, t as FlowMarker, v as PointFields, w as MarkVerdict, x as ChartBand, y as PointGlyph } from "../flow-trace-DBJY1YAA.js";
|
|
2
2
|
import { CSSProperties, ReactElement, ReactNode } from "react";
|
|
3
3
|
//#region src/react/sparkline.d.ts
|
|
4
4
|
type SparklineDirection = "rising" | "falling" | "flat";
|
|
@@ -277,6 +277,31 @@ export declare function Gantt({ rows, lanes: laneInput, colors, axis, span, mark
|
|
|
277
277
|
hatch?: string[];
|
|
278
278
|
}): import("react").JSX.Element;
|
|
279
279
|
//#endregion
|
|
280
|
+
//#region src/react/gap.d.ts
|
|
281
|
+
interface GapBand {
|
|
282
|
+
min: number;
|
|
283
|
+
max: number;
|
|
284
|
+
}
|
|
285
|
+
interface GapProps {
|
|
286
|
+
value: number;
|
|
287
|
+
/** A bound, not a measurement: the true value is at most (upper) or at least (lower) `value`; drawn as an open arrow. */
|
|
288
|
+
bound?: 'upper' | 'lower' | null;
|
|
289
|
+
target: GapBand;
|
|
290
|
+
stretch?: GapBand | null;
|
|
291
|
+
scale?: 'log' | 'linear';
|
|
292
|
+
format?: (value: number) => string;
|
|
293
|
+
/** The value mark's color; the caller's state color. */
|
|
294
|
+
tone?: string;
|
|
295
|
+
/** Hover text for each mark; defaults name the numbers. */
|
|
296
|
+
titles?: {
|
|
297
|
+
value?: string;
|
|
298
|
+
target?: string;
|
|
299
|
+
stretch?: string;
|
|
300
|
+
};
|
|
301
|
+
label?: string;
|
|
302
|
+
}
|
|
303
|
+
export declare function Gap({ value, bound, target, stretch, scale, format, tone, titles, label }: GapProps): import("react").JSX.Element;
|
|
304
|
+
//#endregion
|
|
280
305
|
//#region src/react/figure-view.d.ts
|
|
281
306
|
/** A figure drawn for a width: FigureView calls it with its container's measured width (at least 720 px). */
|
|
282
307
|
type FigureAtWidth = (width: number) => Figure | Refusal;
|
|
@@ -391,4 +416,4 @@ interface FlowWaterfallProps {
|
|
|
391
416
|
* Data remains producer-owned; playback, zoom and folding change presentation only. */
|
|
392
417
|
export declare function FlowWaterfall({ trace, live, startedAt, label, defaultCollapsed, defaultView, renderIcon, maxHeight, onSelect, markers, onTimeChange, agentFill, selectedId, onDeselect, description, summary: showSummary }: FlowWaterfallProps): import("react").JSX.Element;
|
|
393
418
|
//#endregion
|
|
394
|
-
export type { BandKind, ChartBand, ChartMark, DotMapLabel, DotMapProps, DotMapRect, Figure, FigureAtWidth, FigureViewProps, FlowWaterfallProps, LineSeries, MarkKind, MarkVerdict, MarkerShape, MeterSegment, PointFields, PointGlyph, Refusal, SparklineDirection, SparklineGeometry, SparklineGeometryOptions, SparklineLabelOptions, SparklinePoint, SparklineProps, SparklineValues, StackedBarBucket, StackedBarChartProps, StackedBarSegment, StackedBarSeries, TickOutcome, TimelineLane, TimelineOptions, TimelineSpan, TimelineTick, TimelineViewProps, WaterfallBarProps, WaterfallHeaderProps, WaterfallRowProps, WaterfallSpanGeometry, WaterfallTimeAxisProps, WaterfallWindow, XCategory, YScale, YTarget, YTick };
|
|
419
|
+
export type { BandKind, ChartBand, ChartMark, DotMapLabel, DotMapProps, DotMapRect, Figure, FigureAtWidth, FigureViewProps, FlowWaterfallProps, GapBand, GapProps, LineSeries, MarkKind, MarkVerdict, MarkerShape, MeterSegment, PointFields, PointGlyph, Refusal, SparklineDirection, SparklineGeometry, SparklineGeometryOptions, SparklineLabelOptions, SparklinePoint, SparklineProps, SparklineValues, StackedBarBucket, StackedBarChartProps, StackedBarSegment, StackedBarSeries, TickOutcome, TimelineLane, TimelineOptions, TimelineSpan, TimelineTick, TimelineViewProps, WaterfallBarProps, WaterfallHeaderProps, WaterfallRowProps, WaterfallSpanGeometry, WaterfallTimeAxisProps, WaterfallWindow, XCategory, YScale, YTarget, YTick };
|
package/dist/react/index.js
CHANGED
|
@@ -1765,6 +1765,118 @@ function Gantt({ rows, lanes: laneInput, colors, axis, span, marks = [], now, ha
|
|
|
1765
1765
|
});
|
|
1766
1766
|
}
|
|
1767
1767
|
//#endregion
|
|
1768
|
+
//#region src/react/gap.tsx
|
|
1769
|
+
/** One reading against its target band on one scale: how far a value sits from where it should be. Values, words and
|
|
1770
|
+
* colors belong to callers; the chart only places them. */
|
|
1771
|
+
const HEIGHT = 24;
|
|
1772
|
+
const MID = HEIGHT / 2;
|
|
1773
|
+
function Gap({ value, bound = null, target, stretch = null, scale = "log", format = formatCompact, tone = "var(--chart-live-accent, #8b7cf6)", titles = {}, label }) {
|
|
1774
|
+
const [ref, width] = useWidth();
|
|
1775
|
+
const log = scale === "log" && value > 0 && target.min > 0;
|
|
1776
|
+
const f = (v) => log ? Math.log10(v) : v;
|
|
1777
|
+
const ends = [
|
|
1778
|
+
value,
|
|
1779
|
+
target.min,
|
|
1780
|
+
target.max,
|
|
1781
|
+
...stretch ? [stretch.min, stretch.max] : []
|
|
1782
|
+
].map(f);
|
|
1783
|
+
const lo = Math.min(...ends);
|
|
1784
|
+
const hi = Math.max(...ends);
|
|
1785
|
+
const pad = Math.max((hi - lo) * .08, log ? .15 : Math.abs(hi) * .05 || 1);
|
|
1786
|
+
const x = (v) => width ? (f(v) - (lo - pad)) / (hi - lo + 2 * pad) * width : 0;
|
|
1787
|
+
const band = (b) => ({
|
|
1788
|
+
x: x(b.min),
|
|
1789
|
+
w: Math.max(4, x(b.max) - x(b.min))
|
|
1790
|
+
});
|
|
1791
|
+
const t = band(target);
|
|
1792
|
+
const s = stretch ? band(stretch) : null;
|
|
1793
|
+
const near = value < target.min ? x(target.min) : value > target.max ? x(target.max) : x(value);
|
|
1794
|
+
const vx = x(value);
|
|
1795
|
+
const range = (b) => b.min === b.max ? `≈${format(b.min)}` : `${format(b.min)}–${format(b.max)}`;
|
|
1796
|
+
const decades = log && width ? Array.from({ length: Math.floor(hi + pad) - Math.ceil(lo - pad) + 1 }, (_, i) => Math.ceil(lo - pad) + i) : [];
|
|
1797
|
+
const arrow = bound === "upper" ? `M${vx + 4},6 L${vx - 4},${MID} L${vx + 4},18` : `M${vx - 4},6 L${vx + 4},${MID} L${vx - 4},18`;
|
|
1798
|
+
return /* @__PURE__ */ jsx("div", {
|
|
1799
|
+
ref,
|
|
1800
|
+
className: "ov-gap",
|
|
1801
|
+
role: "img",
|
|
1802
|
+
"aria-label": label ?? `${bound === "upper" ? "≤" : bound === "lower" ? "≥" : ""}${format(value)} against ${range(target)}`,
|
|
1803
|
+
children: width > 0 && /* @__PURE__ */ jsxs("svg", {
|
|
1804
|
+
width,
|
|
1805
|
+
height: HEIGHT,
|
|
1806
|
+
viewBox: `0 0 ${width} ${HEIGHT}`,
|
|
1807
|
+
"aria-hidden": true,
|
|
1808
|
+
children: [
|
|
1809
|
+
/* @__PURE__ */ jsx("line", {
|
|
1810
|
+
className: "ov-gap-track",
|
|
1811
|
+
x1: 0,
|
|
1812
|
+
x2: width,
|
|
1813
|
+
y1: MID,
|
|
1814
|
+
y2: MID
|
|
1815
|
+
}),
|
|
1816
|
+
decades.map((d) => /* @__PURE__ */ jsx("line", {
|
|
1817
|
+
className: "ov-gap-tick",
|
|
1818
|
+
x1: x(10 ** d),
|
|
1819
|
+
x2: x(10 ** d),
|
|
1820
|
+
y1: 8,
|
|
1821
|
+
y2: 16
|
|
1822
|
+
}, d)),
|
|
1823
|
+
s && /* @__PURE__ */ jsx("rect", {
|
|
1824
|
+
className: "ov-gap-stretch",
|
|
1825
|
+
x: s.x,
|
|
1826
|
+
y: 4,
|
|
1827
|
+
width: s.w,
|
|
1828
|
+
height: 16,
|
|
1829
|
+
rx: 4,
|
|
1830
|
+
children: /* @__PURE__ */ jsx("title", { children: titles.stretch ?? `stretch ${range(stretch)}` })
|
|
1831
|
+
}),
|
|
1832
|
+
/* @__PURE__ */ jsx("rect", {
|
|
1833
|
+
className: "ov-gap-target",
|
|
1834
|
+
x: t.x,
|
|
1835
|
+
y: 4,
|
|
1836
|
+
width: t.w,
|
|
1837
|
+
height: 16,
|
|
1838
|
+
rx: 4,
|
|
1839
|
+
children: /* @__PURE__ */ jsx("title", { children: titles.target ?? `target ${range(target)}` })
|
|
1840
|
+
}),
|
|
1841
|
+
Math.abs(near - vx) > 1 && /* @__PURE__ */ jsx("line", {
|
|
1842
|
+
className: "ov-gap-span",
|
|
1843
|
+
x1: vx,
|
|
1844
|
+
x2: near,
|
|
1845
|
+
y1: MID,
|
|
1846
|
+
y2: MID,
|
|
1847
|
+
style: { stroke: tone }
|
|
1848
|
+
}),
|
|
1849
|
+
/* @__PURE__ */ jsxs("g", {
|
|
1850
|
+
className: "ov-gap-value",
|
|
1851
|
+
children: [
|
|
1852
|
+
/* @__PURE__ */ jsx("title", { children: titles.value ?? `${bound === "upper" ? "≤" : bound === "lower" ? "≥" : ""}${format(value)}` }),
|
|
1853
|
+
bound ? /* @__PURE__ */ jsx("path", {
|
|
1854
|
+
d: arrow,
|
|
1855
|
+
fill: "none",
|
|
1856
|
+
stroke: tone,
|
|
1857
|
+
strokeWidth: 2,
|
|
1858
|
+
strokeLinecap: "round",
|
|
1859
|
+
strokeLinejoin: "round"
|
|
1860
|
+
}) : /* @__PURE__ */ jsx("circle", {
|
|
1861
|
+
cx: vx,
|
|
1862
|
+
cy: MID,
|
|
1863
|
+
r: 5,
|
|
1864
|
+
fill: tone
|
|
1865
|
+
}),
|
|
1866
|
+
/* @__PURE__ */ jsx("rect", {
|
|
1867
|
+
x: vx - 8,
|
|
1868
|
+
y: 0,
|
|
1869
|
+
width: 16,
|
|
1870
|
+
height: HEIGHT,
|
|
1871
|
+
fill: "transparent"
|
|
1872
|
+
})
|
|
1873
|
+
]
|
|
1874
|
+
})
|
|
1875
|
+
]
|
|
1876
|
+
})
|
|
1877
|
+
});
|
|
1878
|
+
}
|
|
1879
|
+
//#endregion
|
|
1768
1880
|
//#region src/react/figure-view.tsx
|
|
1769
1881
|
/** Embeds a static Figure or Refusal in React: the wide or phone render chosen by the container's width, the data
|
|
1770
1882
|
* table in a disclosure. The SVG and table strings come from this library's figure functions, which escape input. */
|
|
@@ -2397,7 +2509,8 @@ function flowWaterfallRows(trace, resolutionMs) {
|
|
|
2397
2509
|
segments: [],
|
|
2398
2510
|
own: [],
|
|
2399
2511
|
retry: span.retryOf !== void 0,
|
|
2400
|
-
hasAgents: false
|
|
2512
|
+
hasAgents: false,
|
|
2513
|
+
...span.costBound === "lower" || span.costBound === void 0 && trace.costBound === "lower" ? { costFloor: true } : {}
|
|
2401
2514
|
};
|
|
2402
2515
|
});
|
|
2403
2516
|
const byId = new Map(rows.map((row) => [row.id, row]));
|
|
@@ -2633,6 +2746,7 @@ function agentFamilies(agents, open) {
|
|
|
2633
2746
|
const known = members.map((row) => row.span.costUsd ?? row.rollupCostUsd).filter((cost) => cost !== void 0);
|
|
2634
2747
|
const failed = members.filter((row) => !row.ok).length;
|
|
2635
2748
|
out.push({
|
|
2749
|
+
costFloor: known.length < members.length || members.some((row) => row.costFloor),
|
|
2636
2750
|
id,
|
|
2637
2751
|
parentId: members[0].parentId,
|
|
2638
2752
|
name: `${role} ×${members.length}`,
|
|
@@ -2791,6 +2905,8 @@ function drawnRow(row, visible) {
|
|
|
2791
2905
|
tone: family.tone
|
|
2792
2906
|
} : row;
|
|
2793
2907
|
}
|
|
2908
|
+
/** A row's cost as printed: "≥" when it is a floor. */
|
|
2909
|
+
const rowCostText = (row, cost) => `${row.costFloor ? "≥" : ""}${formatCost(cost)}`;
|
|
2794
2910
|
//#endregion
|
|
2795
2911
|
//#region src/react/flow-waterfall-icons.tsx
|
|
2796
2912
|
const svg = (children, label) => /* @__PURE__ */ jsx("svg", {
|
|
@@ -2974,7 +3090,7 @@ function SpanCard({ id, row, agent, clockMs, left, top, pinned, onClose, renderI
|
|
|
2974
3090
|
for (const fact of (subject.facts ?? []).slice(0, 3)) cells.push([fact.label, fact.value]);
|
|
2975
3091
|
cells.push(["Started", `+${formatSpanDuration(Math.max(0, subject.startMs))}`]);
|
|
2976
3092
|
if (tokenCount !== void 0) cells.push(["Tokens", count(tokenCount)]);
|
|
2977
|
-
if (cost !== void 0) cells.push(["Cost",
|
|
3093
|
+
if (cost !== void 0) cells.push(["Cost", rowCostText(who, cost)]);
|
|
2978
3094
|
cells.splice(6);
|
|
2979
3095
|
const kind = span.kind === "model" ? "Thinking" : KIND_LABEL[span.kind];
|
|
2980
3096
|
const step = owner && span.endMs > span.startMs ? `${kind}${span.name && span.name !== kind && span.name.toLowerCase() !== span.kind ? ` ${span.name}` : ""} · ${duration}${row.ok ? "" : " · failed"}` : void 0;
|
|
@@ -3121,7 +3237,7 @@ function SpanCard({ id, row, agent, clockMs, left, top, pinned, onClose, renderI
|
|
|
3121
3237
|
children: [
|
|
3122
3238
|
/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("dt", { children: "Duration" }), /* @__PURE__ */ jsx("dd", { children: duration })] }),
|
|
3123
3239
|
/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("dt", { children: "Started" }), /* @__PURE__ */ jsxs("dd", { children: ["+", formatSpanDuration(Math.max(0, span.startMs))] })] }),
|
|
3124
|
-
span.costUsd !== void 0 && /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("dt", { children: "Cost" }), /* @__PURE__ */ jsx("dd", { children:
|
|
3240
|
+
span.costUsd !== void 0 && /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("dt", { children: "Cost" }), /* @__PURE__ */ jsx("dd", { children: rowCostText(row, span.costUsd) })] }),
|
|
3125
3241
|
tokens && span.promptTokens !== void 0 && /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("dt", { children: "Tokens in" }), /* @__PURE__ */ jsx("dd", { children: count(span.promptTokens) })] }),
|
|
3126
3242
|
tokens && span.completionTokens !== void 0 && /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("dt", { children: "Tokens out" }), /* @__PURE__ */ jsx("dd", { children: count(span.completionTokens) })] }),
|
|
3127
3243
|
(span.facts ?? []).slice(0, 3).map((fact) => /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("dt", { children: fact.label }), /* @__PURE__ */ jsx("dd", { children: fact.value })] }, fact.label)),
|
|
@@ -3175,11 +3291,11 @@ const open = (row, clockMs) => spanRunning(row.span) || row.span.startMs <= cloc
|
|
|
3175
3291
|
function endLabel(row, clockMs) {
|
|
3176
3292
|
const span = row.span;
|
|
3177
3293
|
if (row.durationLabel === "—") return "—";
|
|
3178
|
-
if (row.approx && span.endMs === span.startMs && !spanRunning(span)) return span.costUsd === void 0 ? "" :
|
|
3294
|
+
if (row.approx && span.endMs === span.startMs && !spanRunning(span)) return span.costUsd === void 0 ? "" : rowCostText(row, span.costUsd);
|
|
3179
3295
|
if (!spanRunning(span) && clockMs < span.endMs) return `${formatSpanDuration(Math.max(0, clockMs - span.startMs))}${row.approx ? "~" : ""}`;
|
|
3180
3296
|
const duration = spanRunning(span) ? `${formatSpanDuration(Math.max(span.endMs, clockMs) - span.startMs)}${row.approx ? "~" : ""}` : row.durationLabel;
|
|
3181
3297
|
const cost = span.costUsd ?? (row.rollupCostUsd ? row.rollupCostUsd : void 0);
|
|
3182
|
-
return cost === void 0 ? duration : `${duration} · ${
|
|
3298
|
+
return cost === void 0 ? duration : `${duration} · ${rowCostText(row, cost)}`;
|
|
3183
3299
|
}
|
|
3184
3300
|
/** One trace row. Geometry comes from CSS variables, so a row re-renders only when its own state changes. */
|
|
3185
3301
|
const FlowRow = memo(function FlowRow(props) {
|
|
@@ -3781,6 +3897,10 @@ function FlowBody(props) {
|
|
|
3781
3897
|
"aria-pressed": jumped === marker,
|
|
3782
3898
|
onPointerDown: (event) => event.stopPropagation(),
|
|
3783
3899
|
onClick: () => {
|
|
3900
|
+
if (jumped === marker) {
|
|
3901
|
+
setJumped(void 0);
|
|
3902
|
+
return;
|
|
3903
|
+
}
|
|
3784
3904
|
setJumped(marker);
|
|
3785
3905
|
props.onScrub(marker.at);
|
|
3786
3906
|
}
|
|
@@ -3890,6 +4010,9 @@ function FlowBody(props) {
|
|
|
3890
4010
|
title: pause.label,
|
|
3891
4011
|
children: /* @__PURE__ */ jsx("span", {
|
|
3892
4012
|
className: "fw-pause-label",
|
|
4013
|
+
title: pause.detail,
|
|
4014
|
+
tabIndex: pause.detail ? 0 : void 0,
|
|
4015
|
+
"aria-label": pause.detail ? `${pause.label}: ${pause.detail}` : void 0,
|
|
3893
4016
|
children: pause.label
|
|
3894
4017
|
})
|
|
3895
4018
|
}, `p-${pause.startMs}`)), props.markers?.map((marker) => /* @__PURE__ */ jsx("span", {
|
|
@@ -4524,6 +4647,10 @@ function FlowWaterfall({ trace, live, startedAt, label = "Trace waterfall", defa
|
|
|
4524
4647
|
return () => document.removeEventListener("pointermove", move);
|
|
4525
4648
|
}, [card, leave]);
|
|
4526
4649
|
latest.current.pin = (target, element) => {
|
|
4650
|
+
if (card?.pinned && card.target === target) {
|
|
4651
|
+
closeCard();
|
|
4652
|
+
return;
|
|
4653
|
+
}
|
|
4527
4654
|
place(target, element, true);
|
|
4528
4655
|
const row = byId.get(target);
|
|
4529
4656
|
if (row) {
|
|
@@ -4792,4 +4919,4 @@ function FlowWaterfall({ trace, live, startedAt, label = "Trace waterfall", defa
|
|
|
4792
4919
|
});
|
|
4793
4920
|
}
|
|
4794
4921
|
//#endregion
|
|
4795
|
-
export { DEFAULT_SPARKLINE_EMPTY_LABEL, DEFAULT_SPARKLINE_HEIGHT, DEFAULT_SPARKLINE_LABEL, DEFAULT_SPARKLINE_UNAVAILABLE_LABEL, DEFAULT_SPARKLINE_WIDTH, DOT_MAP_CATEGORIES, DayBars, DotMap, Events, FigureView, FlowWaterfall, Gantt, HBars, Histogram, LIVE_SERIES, Lines, Meter, Spark, Sparkline, StackedBarChart, TimelineView, WaterfallBar, WaterfallHeader, WaterfallRow, WaterfallTimeAxis, formatCompact, formatSparklineValue, formatWaterfallDuration, sparklineGeometry, sparklineLabel, sparklinePointsAttribute, sparklineReadings, waterfallSpanGeometry, waterfallTicks };
|
|
4922
|
+
export { DEFAULT_SPARKLINE_EMPTY_LABEL, DEFAULT_SPARKLINE_HEIGHT, DEFAULT_SPARKLINE_LABEL, DEFAULT_SPARKLINE_UNAVAILABLE_LABEL, DEFAULT_SPARKLINE_WIDTH, DOT_MAP_CATEGORIES, DayBars, DotMap, Events, FigureView, FlowWaterfall, Gantt, Gap, HBars, Histogram, LIVE_SERIES, Lines, Meter, Spark, Sparkline, StackedBarChart, TimelineView, WaterfallBar, WaterfallHeader, WaterfallRow, WaterfallTimeAxis, formatCompact, formatSparklineValue, formatWaterfallDuration, sparklineGeometry, sparklineLabel, sparklinePointsAttribute, sparklineReadings, waterfallSpanGeometry, waterfallTicks };
|
package/dist/react/live.css
CHANGED
|
@@ -89,3 +89,11 @@ line.ov-gridline { stroke: color-mix(in srgb, var(--chart-live-faint, #777) 22%,
|
|
|
89
89
|
.tgc-dot-map { color: var(--chart-live-muted, #8a8a8a); }
|
|
90
90
|
.tgc-dot-map canvas:focus-visible { outline: 2px solid var(--chart-accent, #7760bd); outline-offset: 2px; }
|
|
91
91
|
.tgc-dot-map-tip { z-index: 2; max-width: 300px; padding: 6px 9px; border-radius: 6px; background: var(--chart-tip-bg, #262626); color: var(--chart-tip-ink, #eee); font: 12px/1.4 ui-sans-serif, system-ui, sans-serif; white-space: pre-line; box-shadow: 0 4px 14px rgb(0 0 0 / .3); }
|
|
92
|
+
.ov-gap { width: 100%; min-width: 96px; height: 24px; }
|
|
93
|
+
.ov-gap svg { display: block; overflow: visible; }
|
|
94
|
+
.ov-gap-track { stroke: color-mix(in srgb, var(--chart-live-faint, #777) 40%, transparent); stroke-width: 1; }
|
|
95
|
+
.ov-gap-tick { stroke: color-mix(in srgb, var(--chart-live-faint, #777) 60%, transparent); stroke-width: 1; }
|
|
96
|
+
.ov-gap-target { fill: color-mix(in srgb, var(--chart-live-pass, #2f9e6e) 28%, transparent); stroke: var(--chart-live-pass, #2f9e6e); stroke-width: 1; }
|
|
97
|
+
.ov-gap-stretch { fill: none; stroke: var(--chart-live-pass, #2f9e6e); stroke-width: 1; stroke-dasharray: 3 3; }
|
|
98
|
+
.ov-gap-span { stroke-width: 2; stroke-dasharray: 2 4; stroke-linecap: round; }
|
|
99
|
+
.ov-gap-value { cursor: default; }
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tangle-network/charts",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.21.1",
|
|
4
4
|
"description": "Static SVG and HTML figures for benchmarks and operational timing. Draws from producer data and refuses what it cannot draw honestly.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|