@tangle-network/charts 2.0.0 → 2.0.2
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.
- package/README.md +3 -0
- package/dist/react/flow-waterfall.css +13 -14
- package/dist/react/index.d.ts +6 -2
- package/dist/react/index.js +195 -157
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -6,6 +6,8 @@ The React entry also exports `DayBars`, `HBars`, `Histogram`, `Lines`, `Meter`,
|
|
|
6
6
|
|
|
7
7
|
`FlowWaterfall` from `@tangle-network/charts/react` is the shared live trace inspector: an agent timeline (one row per agent, elbow handoffs, hatched waiting) and a virtualized span waterfall over one clock. It owns hierarchy layout, folding, search, playback, zoom, span cards and running-span growth. Producers own identity, `parentId`, explicit `status` and observed totals. Import `@tangle-network/charts/react/flow-waterfall.css`; its `fw-*` classes and six-field summary support hosts without a Tailwind build. Every color, radius and shadow in it is a Brand role (text, card, hairline, well, chart grid, status inks, the categorical tones for agents), so the host loads `@tangle-network/brand` `tokens.css` (or `legacy-light.css`) and sets its theme; the stylesheet has no color of its own. The React-free root exports the `FlowSpan` and `FlowTrace` types.
|
|
8
8
|
|
|
9
|
+
`FlowWaterfall` accepts optional `graph` and `latestEvents` React nodes. Supplying `graph` adds Graph to its existing Agents/Steps view control, including `defaultView="graph"`. The trace clock and controlled selection survive switches. Graph hides waterfall-only controls; `latestEvents` stays mounted in the header across all views.
|
|
10
|
+
|
|
9
11
|
`WaterfallHeader`, `WaterfallTimeAxis`, `WaterfallBar` and `WaterfallRow` remain available for existing consumers that own their own hierarchy and selection. All use the same `waterfallSpanGeometry` and `waterfallTicks`. Existing fixed-width cells, tones, formatting, attribution slots and unordered-time `—` marks are preserved. Optional fluid tracks, inner-bar colour/class, overlay and clipping fields support the shared inspector without changing existing calls. The primitives were extracted from Intelligence under [brand #211](https://github.com/tangle-network/brand/pull/211); the shared inspector extends that presentation ownership while leaving failure interpretation with producers.
|
|
10
12
|
|
|
11
13
|
Five figures cover the decisions a benchmark reader makes:
|
|
@@ -350,3 +352,4 @@ CHARTS_REACT_VERSION=19 CHARTS_PROOF_DIR=/tmp/charts-react19 node scripts/charts
|
|
|
350
352
|
```
|
|
351
353
|
|
|
352
354
|
Consumers: agent-record adapts record provenance; agent-app supplies application trace producers; Creative consumes both. Intelligence already uses the row/axis primitives with its controlled virtualized tree. Tangle Website’s `RecordedRunWaterfall` uses the Header/Row primitives; Blueprint Agent’s execution timeline is a separately owned follow-up. Keep these existing primitives exported. Agent-record’s earlier agent-app dependency increased its installed graph from 134 to 256 package versions (tangle-tools #1674); adopting the lower chart owner removes that framework dependency, with the actual new graph measured by the deployment owner.
|
|
355
|
+
|
|
@@ -21,8 +21,8 @@
|
|
|
21
21
|
--fw-h1: light-dark(oklch(from var(--tone-blue-icon) .58 .11 calc(h + 39)), oklch(from var(--tone-blue-icon) .67 .11 calc(h + 39)));
|
|
22
22
|
--fw-h2: light-dark(oklch(from var(--tone-violet-icon) .55 .11 h), oklch(from var(--tone-violet-icon) .70 .11 h));
|
|
23
23
|
--fw-h3: light-dark(oklch(from var(--tone-pink-icon) .55 .11 h), oklch(from var(--tone-pink-icon) .67 .11 calc(h - 16)));
|
|
24
|
-
--fw-h4: light-dark(oklch(from var(--tone-cyan-icon) .
|
|
25
|
-
--fw-h5: light-dark(oklch(from var(--tone-blue-icon) .58 .
|
|
24
|
+
--fw-h4: light-dark(oklch(from var(--tone-cyan-icon) .578 .11 calc(h - 22.894)), oklch(from var(--tone-cyan-icon) .67 .11 calc(h - 26.148)));
|
|
25
|
+
--fw-h5: light-dark(oklch(from var(--tone-blue-icon) .58 .11 calc(h + 37.6)), oklch(from var(--tone-blue-icon) .67 .11 calc(h + 29.5)));
|
|
26
26
|
--fw-ease: var(--ease-standard, cubic-bezier(.2,.8,.2,1));
|
|
27
27
|
--fw-bar-h: 20px;
|
|
28
28
|
--fw-label-col: min(var(--fw-name-w), 42%);
|
|
@@ -83,11 +83,13 @@
|
|
|
83
83
|
.fw-root .fw-search-input::placeholder { color: var(--fw-muted); }
|
|
84
84
|
.fw-root .fw-search-input::-webkit-search-cancel-button { display: none; }
|
|
85
85
|
|
|
86
|
-
.fw-root .fw-summary { display:
|
|
86
|
+
.fw-root .fw-summary { display: flex; flex-wrap: wrap; align-items: center; border-bottom: 1px solid var(--fw-border); }
|
|
87
87
|
.fw-root .fw-summary > div { padding: 12px 16px; min-width: 0; }
|
|
88
|
-
.fw-root .fw-summary > div
|
|
89
|
-
.fw-root .fw-summary
|
|
90
|
-
.fw-root .fw-
|
|
88
|
+
.fw-root .fw-summary > div:nth-child(-n+2) { flex: 1; }
|
|
89
|
+
.fw-root .fw-summary > div:nth-child(n+3) { display: flex; align-items: baseline; gap: 4px; padding: 8px 6px; color: var(--fw-muted); }
|
|
90
|
+
.fw-root .fw-summary dt { font-size: 14px; line-height: 20px; color: var(--fw-muted); }
|
|
91
|
+
.fw-root .fw-value { margin-top: 4px; font-size: 28px; line-height: 34px; font-weight: 600; letter-spacing: -.02em; font-variant-numeric: tabular-nums; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
92
|
+
.fw-root .fw-summary > div:nth-child(n+3) .fw-value { margin: 0; font-size: 14px; line-height: 20px; font-weight: 500; letter-spacing: normal; }
|
|
91
93
|
.fw-root .fw-has-errors .fw-value { color: var(--fw-failed); }
|
|
92
94
|
|
|
93
95
|
.fw-root .fw-axis { display: grid; grid-template-columns: var(--fw-label-col) minmax(0, 1fr); height: 32px; color: var(--fw-muted); font-size: 14px; }
|
|
@@ -203,7 +205,7 @@
|
|
|
203
205
|
.fw-root :is(.fw-bar, .fw-seg):hover { filter: brightness(1.18); box-shadow: inset 0 0 0 1px var(--line), 0 0 0 2px color-mix(in oklab, var(--line) 55%, transparent); z-index: 1; }
|
|
204
206
|
.fw-root .fw-bar.fw-k-tool { background: var(--dim); box-shadow: inset 0 0 0 1px var(--dim-line); }
|
|
205
207
|
.fw-root .fw-bar.fw-k-handoff { background: var(--line); height: 8px; top: calc(50% + var(--fw-bar-shift) - 4px); box-shadow: none; }
|
|
206
|
-
.fw-root .fw-bar.fw-k-waiting { background: repeating-linear-gradient(-45deg, var(--fw-hatch) 0 1px, transparent 1px 5px); box-shadow: inset 0 0 0 1px var(--fw-hatch); }
|
|
208
|
+
.fw-root .fw-bar.fw-k-waiting, .fw-root .fw-kinds .fw-swatch-wait { background: repeating-linear-gradient(-45deg, var(--fw-hatch) 0 1px, transparent 1px 5px); box-shadow: inset 0 0 0 1px var(--fw-hatch); }
|
|
207
209
|
.fw-root .fw-bar.fw-k-failed { background: color-mix(in oklab, var(--fw-failed) 22%, var(--fw-surface)); box-shadow: inset 0 0 0 1px var(--fw-failed); color: var(--fw-failed); }
|
|
208
210
|
.fw-root .fw-bar.fw-k-pipeline { background: linear-gradient(90deg, var(--fw-neutral-bar), color-mix(in oklab, var(--fw-neutral-bar) 55%, var(--fw-surface))); box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--fw-text) 12%, transparent); }
|
|
209
211
|
.fw-root .fw-bar.fw-k-pipeline.fw-has-marks { background: repeating-linear-gradient(-45deg, var(--fw-hatch) 0 1px, transparent 1px 5px); box-shadow: inset 0 0 0 1px var(--fw-hatch); }
|
|
@@ -227,7 +229,7 @@
|
|
|
227
229
|
.fw-root.fw-fill-agent .fw-kinds .fw-swatch-model { background: var(--model-fill); }
|
|
228
230
|
.fw-root.fw-fill-agent .fw-kinds .fw-swatch-tool { background: var(--tool-fill); }
|
|
229
231
|
.fw-root .fw-kinds .fw-swatch-tool { width: 12px; height: 8px; border-radius: 2px; background: var(--fw-kind-tool); }
|
|
230
|
-
.fw-root .fw-kinds .fw-swatch-wait { width: 12px; height: 8px; border-radius: 2px;
|
|
232
|
+
.fw-root .fw-kinds .fw-swatch-wait { width: 12px; height: 8px; border-radius: 2px; }
|
|
231
233
|
.fw-root .fw-kinds .fw-swatch-event { width: 8px; height: 8px; border-radius: 50%; background: var(--fw-muted); box-shadow: 0 0 0 2px var(--fw-surface); }
|
|
232
234
|
.fw-root .fw-kinds .fw-swatch-handoff { width: 10px; height: 8px; border-left: 1.5px solid var(--fw-muted); border-bottom: 1.5px solid var(--fw-muted); border-bottom-left-radius: 3px; }
|
|
233
235
|
.fw-root .fw-description { margin: 0; color: var(--fw-muted); font-size: 14px; line-height: 20px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
@@ -266,11 +268,11 @@
|
|
|
266
268
|
.fw-root .fw-glyph svg { width: 11px; height: 11px; stroke-width: 2; }
|
|
267
269
|
.fw-root .fw-seg-model .fw-glyph, .fw-root .fw-k-model .fw-glyph { color: light-dark(var(--tone), var(--fw-text)); }
|
|
268
270
|
.fw-root .fw-end { z-index: 2; display: inline-flex; align-items: center; gap: 8px; top: calc(50% + var(--fw-bar-shift) - var(--fw-bar-h) / 2); height: var(--fw-bar-h);
|
|
269
|
-
left: min(calc(var(--x0) + max(var(--w), 3px) + 4px), calc(100% - var(--fw-end-w, 0px) -
|
|
271
|
+
left: min(calc(var(--x0) + max(var(--w), 3px) + 4px), calc(100% - var(--fw-end-w, 0px) - 4px)); padding: 0 4px; border-radius: var(--radius-tag);
|
|
270
272
|
background: linear-gradient(var(--fw-tint, transparent) 0 0), var(--fw-surface); white-space: nowrap; pointer-events: none; }
|
|
271
273
|
.fw-root .fw-duration { font-size: 14px; color: var(--fw-muted); font-variant-numeric: tabular-nums; }
|
|
272
274
|
.fw-root .fw-k-failed ~ .fw-end .fw-duration { color: var(--fw-failed); }
|
|
273
|
-
.fw-root .fw-badge { height:
|
|
275
|
+
.fw-root .fw-badge { display: inline-flex; flex: none; height: 18px; padding: 0 6px; border-radius: var(--radius-pill); font-size: 12px; line-height: 18px; font-weight: 500; color: var(--fw-muted); background: transparent; box-shadow: inset 0 0 0 1px var(--fw-border); }
|
|
274
276
|
|
|
275
277
|
.fw-root .fw-links { position: absolute; top: 0; bottom: 0; left: var(--fw-label-col); right: 0; overflow: hidden; pointer-events: none; z-index: 0; }
|
|
276
278
|
.fw-root .fw-link {
|
|
@@ -384,10 +386,7 @@
|
|
|
384
386
|
.fw-root .fw-card .fw-agent-dot:not([data-outcome]) { background: transparent; box-shadow: inset 0 0 0 1.5px var(--fw-muted); }
|
|
385
387
|
@container flow-waterfall (max-width: 599px) {
|
|
386
388
|
.fw-root > * { --fw-label-col: 0px; --fw-bar-shift: 8px; --fw-bar-h: 8px; --fw-row-h: 44px; }
|
|
387
|
-
.fw-root .fw-summary {
|
|
388
|
-
.fw-root .fw-summary > div { padding: 8px; }
|
|
389
|
-
.fw-root .fw-summary > div:nth-child(4) { border-left: 0; }
|
|
390
|
-
.fw-root .fw-summary > div:nth-child(n+4) { border-top: 1px solid var(--fw-border); }
|
|
389
|
+
.fw-root .fw-summary > div:nth-child(-n+2) { flex-basis: 50%; padding: 6px 8px; }
|
|
391
390
|
.fw-root :is(.fw-zoom, .fw-branch-controls, .fw-resize, .fw-links, .fw-gridlayer, .fw-marker-layer, .fw-subtitle, .fw-badge, .fw-icon-tile) { display: none; }
|
|
392
391
|
.fw-root .fw-row-state { display: inline; }
|
|
393
392
|
.fw-root .fw-key > summary { display: flex; align-items: center; min-height: 32px; cursor: pointer; }
|
package/dist/react/index.d.ts
CHANGED
|
@@ -459,7 +459,7 @@ export declare function flowWaterfallRows(trace: FlowTrace, resolutionMs?: numbe
|
|
|
459
459
|
export declare function criticalPathIds(rows: readonly FlowWaterfallRow[]): ReadonlySet<string>;
|
|
460
460
|
//#endregion
|
|
461
461
|
//#region src/react/flow-waterfall-row.d.ts
|
|
462
|
-
type FlowView = 'spans' | 'agents';
|
|
462
|
+
type FlowView = 'spans' | 'agents' | 'graph';
|
|
463
463
|
//#endregion
|
|
464
464
|
//#region src/react/flow-waterfall-time.d.ts
|
|
465
465
|
interface ViewWindow {
|
|
@@ -480,6 +480,10 @@ interface FlowWaterfallProps {
|
|
|
480
480
|
defaultCollapsed?: boolean;
|
|
481
481
|
/** `agents` shows one row per agent (the agent timeline); expanding a row opens the full span tree. */
|
|
482
482
|
defaultView?: FlowView;
|
|
483
|
+
/** Host graph rendered by the same view control, retaining the trace clock and selection. */
|
|
484
|
+
graph?: ReactNode;
|
|
485
|
+
/** Shared header feed, kept mounted across Agents, Steps and Graph. */
|
|
486
|
+
latestEvents?: ReactNode;
|
|
483
487
|
/** Host brand marks by span; the inspector draws kind glyphs without it. */
|
|
484
488
|
renderIcon?: (span: FlowSpan) => ReactNode;
|
|
485
489
|
/** Scroll height of the rows; the tree is virtualized beyond it. Defaults to 20 agent rows, or 640 px of steps. */
|
|
@@ -519,7 +523,7 @@ interface FlowWaterfallProps {
|
|
|
519
523
|
}
|
|
520
524
|
/** Shared trace inspector: the agent timeline and the span waterfall over one clock.
|
|
521
525
|
* Data remains producer-owned; playback, zoom and folding change presentation only. */
|
|
522
|
-
export declare function FlowWaterfall({ trace, live, startedAt, label, defaultCollapsed, defaultView, renderIcon, maxHeight, onSelect, markers, onTimeChange, agentFill: fillProp, selectedId, onDeselect, description, summary: showSummary, criticalPath, query: queryProp, onQueryChange, collapsed: collapsedProp, onCollapsedChange, zoom: zoomProp, onZoomChange, matchSpan }: FlowWaterfallProps): import("react").JSX.Element;
|
|
526
|
+
export declare function FlowWaterfall({ trace, live, startedAt, label, defaultCollapsed, defaultView, graph, latestEvents, renderIcon, maxHeight, onSelect, markers, onTimeChange, agentFill: fillProp, selectedId, onDeselect, description, summary: showSummary, criticalPath, query: queryProp, onQueryChange, collapsed: collapsedProp, onCollapsedChange, zoom: zoomProp, onZoomChange, matchSpan }: FlowWaterfallProps): import("react").JSX.Element;
|
|
523
527
|
//#endregion
|
|
524
528
|
//#region src/react/flow-waterfall-icons.d.ts
|
|
525
529
|
/** Kind glyphs drawn when the host supplies no `renderIcon`. Brand marks belong to the host. */
|
package/dist/react/index.js
CHANGED
|
@@ -6822,17 +6822,15 @@ function criticalPathIds(rows) {
|
|
|
6822
6822
|
function agentCallouts(agents, clockMs) {
|
|
6823
6823
|
let slowest, slowestMs = -1, costliest, top = -1, priced = 0, timed = 0;
|
|
6824
6824
|
for (const row of agents) {
|
|
6825
|
-
if (row.durationLabel === "—" || row.span.startMs > clockMs || row.kind !== "pipeline" || row.id.startsWith("family:") || row.id.startsWith("run:")) continue;
|
|
6826
|
-
|
|
6827
|
-
|
|
6828
|
-
|
|
6829
|
-
|
|
6830
|
-
|
|
6831
|
-
slowestMs = ms;
|
|
6832
|
-
}
|
|
6825
|
+
if (row.durationLabel === "—" || row.span.startMs > clockMs || row.kind !== "pipeline" || row.hasAgents || row.id.startsWith("family:") || row.id.startsWith("run:")) continue;
|
|
6826
|
+
const ms = (spanRunning(row.span) ? Math.max(row.span.endMs, clockMs) : Math.min(row.span.endMs, clockMs)) - row.span.startMs;
|
|
6827
|
+
timed += 1;
|
|
6828
|
+
if (ms > slowestMs) {
|
|
6829
|
+
slowest = row;
|
|
6830
|
+
slowestMs = ms;
|
|
6833
6831
|
}
|
|
6834
6832
|
const cost = row.span.costUsd ?? row.rollupCostUsd;
|
|
6835
|
-
if (cost
|
|
6833
|
+
if (typeof cost !== "number" || !Number.isFinite(cost)) continue;
|
|
6836
6834
|
priced += 1;
|
|
6837
6835
|
if (cost > top) {
|
|
6838
6836
|
costliest = row;
|
|
@@ -6934,10 +6932,15 @@ function agentFamilies(agents, open) {
|
|
|
6934
6932
|
const hue = (row) => row.tone <= 0 || ++next > 5 ? 0 : 1 + [...roleOf(row.name)].reduce((hash, c) => hash * 31 + c.charCodeAt(0) >>> 0, 0) % 5;
|
|
6935
6933
|
for (const [role, members] of groups) {
|
|
6936
6934
|
if (members.length < 2) {
|
|
6937
|
-
|
|
6935
|
+
const row = members[0], tone = hue(row);
|
|
6936
|
+
out.push({
|
|
6938
6937
|
...row,
|
|
6939
|
-
tone
|
|
6940
|
-
|
|
6938
|
+
tone,
|
|
6939
|
+
own: row.own.map((mark) => ({
|
|
6940
|
+
...mark,
|
|
6941
|
+
tone
|
|
6942
|
+
}))
|
|
6943
|
+
});
|
|
6941
6944
|
continue;
|
|
6942
6945
|
}
|
|
6943
6946
|
const tone = hue(members[0]);
|
|
@@ -7361,6 +7364,7 @@ function Table({ rows }) {
|
|
|
7361
7364
|
/** The span card: what ran, for how long, on what tokens and at what recorded cost, then its input and output. */
|
|
7362
7365
|
function SpanCard({ id, row, agent, clockMs, left, top, pinned, onClose, renderIcon, compact }) {
|
|
7363
7366
|
const span = row.span;
|
|
7367
|
+
const failure = span.facts?.find((fact) => fact.label.toLowerCase() === "failure")?.value;
|
|
7364
7368
|
const state = runStatus(span.status ?? "unknown");
|
|
7365
7369
|
const meta = statusMeta(state);
|
|
7366
7370
|
const status = meta.label;
|
|
@@ -7433,14 +7437,14 @@ function SpanCard({ id, row, agent, clockMs, left, top, pinned, onClose, renderI
|
|
|
7433
7437
|
close
|
|
7434
7438
|
]
|
|
7435
7439
|
}),
|
|
7436
|
-
/* @__PURE__ */ jsx(Table, { rows: metrics(who, clockMs, false) }),
|
|
7440
|
+
/* @__PURE__ */ jsx(Table, { rows: metrics(who, clockMs, false).filter(([label]) => label.toLowerCase() !== "failure") }),
|
|
7437
7441
|
step && /* @__PURE__ */ jsx("p", {
|
|
7438
7442
|
className: "fw-card-step",
|
|
7439
7443
|
children: step
|
|
7440
7444
|
}),
|
|
7441
|
-
!row.ok && /* @__PURE__ */
|
|
7445
|
+
!row.ok && /* @__PURE__ */ jsx("p", {
|
|
7442
7446
|
className: "fw-card-error",
|
|
7443
|
-
children:
|
|
7447
|
+
children: failure ? `Failure: ${failure}` : span.output ? `Recorded output: ${span.output}` : "Failure detail not reported"
|
|
7444
7448
|
}),
|
|
7445
7449
|
sentence && row.ok && /* @__PURE__ */ jsx("p", {
|
|
7446
7450
|
className: "fw-card-result",
|
|
@@ -7487,6 +7491,10 @@ function SpanCard({ id, row, agent, clockMs, left, top, pinned, onClose, renderI
|
|
|
7487
7491
|
]
|
|
7488
7492
|
}),
|
|
7489
7493
|
/* @__PURE__ */ jsx(Table, { rows: metrics(row, clockMs, true) }),
|
|
7494
|
+
!row.ok && !span.output && !failure && /* @__PURE__ */ jsx("p", {
|
|
7495
|
+
className: "fw-card-error",
|
|
7496
|
+
children: "Failure detail not reported"
|
|
7497
|
+
}),
|
|
7490
7498
|
span.input && /* @__PURE__ */ jsxs("div", {
|
|
7491
7499
|
className: "fw-card-text",
|
|
7492
7500
|
children: [/* @__PURE__ */ jsx("div", {
|
|
@@ -7498,7 +7506,7 @@ function SpanCard({ id, row, agent, clockMs, left, top, pinned, onClose, renderI
|
|
|
7498
7506
|
className: "fw-card-text",
|
|
7499
7507
|
children: [/* @__PURE__ */ jsx("div", {
|
|
7500
7508
|
className: "fw-card-label",
|
|
7501
|
-
children: row.ok ? "Output" : "
|
|
7509
|
+
children: row.ok ? "Output" : "Recorded output"
|
|
7502
7510
|
}), /* @__PURE__ */ jsx("p", { children: span.output })]
|
|
7503
7511
|
})
|
|
7504
7512
|
]
|
|
@@ -7597,6 +7605,15 @@ const FlowRow = memo(function FlowRow(props) {
|
|
|
7597
7605
|
const step = agentView && row.stepOf !== void 0;
|
|
7598
7606
|
const opens = family || agentView && isAgent && row.own.length > 0;
|
|
7599
7607
|
const outcomes = row.outcomes ?? (span.outcome ? [span.outcome] : []);
|
|
7608
|
+
const callouts = /* @__PURE__ */ jsxs(Fragment, { children: [slowest && /* @__PURE__ */ jsx("span", {
|
|
7609
|
+
className: "fw-badge",
|
|
7610
|
+
title: agentView ? "Longest elapsed leaf agent" : "Longest elapsed leaf step",
|
|
7611
|
+
children: agentView ? "Longest leaf" : "Longest step"
|
|
7612
|
+
}), costliest && /* @__PURE__ */ jsx("span", {
|
|
7613
|
+
className: "fw-badge",
|
|
7614
|
+
title: "Highest reported cost among priced leaf agents",
|
|
7615
|
+
children: "Costliest leaf"
|
|
7616
|
+
})] });
|
|
7600
7617
|
return /* @__PURE__ */ jsxs("div", {
|
|
7601
7618
|
role: "row",
|
|
7602
7619
|
"data-span-id": row.id,
|
|
@@ -7616,8 +7633,7 @@ const FlowRow = memo(function FlowRow(props) {
|
|
|
7616
7633
|
style: {
|
|
7617
7634
|
"--row-y": `${top}px`,
|
|
7618
7635
|
"--fw-enter-delay": `${motion?.enter ?? 0}ms`,
|
|
7619
|
-
"--fw-end-w": `${endLabelWidth(label)}px
|
|
7620
|
-
"--fw-badge-w": `${(slowest ? 80 : 0) + (costliest ? 90 : 0)}px`
|
|
7636
|
+
"--fw-end-w": `${endLabelWidth(label)}px`
|
|
7621
7637
|
},
|
|
7622
7638
|
onFocus: (event) => {
|
|
7623
7639
|
if (event.target === event.currentTarget) props.onActivate(row);
|
|
@@ -7708,7 +7724,8 @@ const FlowRow = memo(function FlowRow(props) {
|
|
|
7708
7724
|
className: "fw-name-text",
|
|
7709
7725
|
children: row.name
|
|
7710
7726
|
}),
|
|
7711
|
-
|
|
7727
|
+
!agentView && callouts,
|
|
7728
|
+
state !== "unknown" && !activity.quiet && /* @__PURE__ */ jsx("span", {
|
|
7712
7729
|
className: "fw-row-state",
|
|
7713
7730
|
style: { color: `var(${meta.token})` },
|
|
7714
7731
|
children: meta.label
|
|
@@ -7726,13 +7743,17 @@ const FlowRow = memo(function FlowRow(props) {
|
|
|
7726
7743
|
children: renderIcon(span)
|
|
7727
7744
|
}), /* @__PURE__ */ jsxs("span", {
|
|
7728
7745
|
className: "fw-subtitle-tail",
|
|
7729
|
-
children: [
|
|
7730
|
-
|
|
7731
|
-
|
|
7732
|
-
|
|
7733
|
-
|
|
7734
|
-
|
|
7735
|
-
|
|
7746
|
+
children: [
|
|
7747
|
+
callouts,
|
|
7748
|
+
/* @__PURE__ */ jsx("span", {
|
|
7749
|
+
className: "fw-subtitle-text",
|
|
7750
|
+
children: summary[0]
|
|
7751
|
+
}),
|
|
7752
|
+
summary.slice(1).map((part) => /* @__PURE__ */ jsxs("span", {
|
|
7753
|
+
className: "fw-subtitle-extra",
|
|
7754
|
+
children: ["· ", part]
|
|
7755
|
+
}, part))
|
|
7756
|
+
]
|
|
7736
7757
|
})]
|
|
7737
7758
|
})]
|
|
7738
7759
|
}),
|
|
@@ -7750,7 +7771,7 @@ const FlowRow = memo(function FlowRow(props) {
|
|
|
7750
7771
|
role: "gridcell",
|
|
7751
7772
|
className: "fw-lane",
|
|
7752
7773
|
"data-waterfall-track": true,
|
|
7753
|
-
"aria-label": `${KIND_LABEL[span.kind]}, ${label}${slowest ? `,
|
|
7774
|
+
"aria-label": `${KIND_LABEL[span.kind]}, ${label}${slowest ? `, longest leaf ${agentView ? "agent" : "step"}` : ""}${costliest ? ", highest reported leaf-agent cost" : ""}${critical ? ", critical path" : ""}`,
|
|
7754
7775
|
children: invalid ? /* @__PURE__ */ jsx("span", {
|
|
7755
7776
|
className: "fw-invalid",
|
|
7756
7777
|
children: "—"
|
|
@@ -7792,23 +7813,13 @@ const FlowRow = memo(function FlowRow(props) {
|
|
|
7792
7813
|
events: props,
|
|
7793
7814
|
agentView
|
|
7794
7815
|
}, `${mark.id}-${i}`)),
|
|
7795
|
-
/* @__PURE__ */
|
|
7816
|
+
/* @__PURE__ */ jsx("span", {
|
|
7796
7817
|
className: "fw-end",
|
|
7797
7818
|
style: at(span.startMs, running ? OPEN_END : span.endMs),
|
|
7798
|
-
children:
|
|
7799
|
-
|
|
7800
|
-
|
|
7801
|
-
|
|
7802
|
-
}),
|
|
7803
|
-
slowest && /* @__PURE__ */ jsx("span", {
|
|
7804
|
-
className: "fw-badge",
|
|
7805
|
-
children: "Slowest"
|
|
7806
|
-
}),
|
|
7807
|
-
costliest && /* @__PURE__ */ jsx("span", {
|
|
7808
|
-
className: "fw-badge",
|
|
7809
|
-
children: "Costliest"
|
|
7810
|
-
})
|
|
7811
|
-
]
|
|
7819
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
7820
|
+
className: "fw-duration",
|
|
7821
|
+
children: label
|
|
7822
|
+
})
|
|
7812
7823
|
})
|
|
7813
7824
|
] })
|
|
7814
7825
|
})]
|
|
@@ -7960,7 +7971,8 @@ function clampWindow(view, limitMs) {
|
|
|
7960
7971
|
//#region src/react/flow-waterfall-body.tsx
|
|
7961
7972
|
const ROW_HEIGHT = {
|
|
7962
7973
|
spans: 36,
|
|
7963
|
-
agents: 40
|
|
7974
|
+
agents: 40,
|
|
7975
|
+
graph: 40
|
|
7964
7976
|
};
|
|
7965
7977
|
const OVERSCAN = 8;
|
|
7966
7978
|
/** Rows re-render once per CHUNK rows scrolled; overscan covers the rows in between. */
|
|
@@ -8690,11 +8702,13 @@ const AGENT_ROWS = 20;
|
|
|
8690
8702
|
const UNFOLD_ROWS = 12;
|
|
8691
8703
|
const END_LABEL_GUTTER = {
|
|
8692
8704
|
spans: 120,
|
|
8693
|
-
agents: 176
|
|
8705
|
+
agents: 176,
|
|
8706
|
+
graph: 176
|
|
8694
8707
|
};
|
|
8695
8708
|
const NAME_WIDTH = {
|
|
8696
8709
|
spans: 320,
|
|
8697
|
-
agents: 240
|
|
8710
|
+
agents: 240,
|
|
8711
|
+
graph: 240
|
|
8698
8712
|
};
|
|
8699
8713
|
/** State the host may own: its value wins when given, and every change is reported either way. */
|
|
8700
8714
|
function useHostable(value, onChange, initial) {
|
|
@@ -8771,7 +8785,7 @@ const TONE_ORDER = [
|
|
|
8771
8785
|
"ok"
|
|
8772
8786
|
];
|
|
8773
8787
|
/** What each mark means, as the agent view draws it; a key only for kinds the run has. */
|
|
8774
|
-
function KindLegend({ rows }) {
|
|
8788
|
+
function KindLegend({ rows, fill }) {
|
|
8775
8789
|
const has = (kind) => rows.some((row) => row.own.some((mark) => mark.kind === kind) || row.span.kind === kind);
|
|
8776
8790
|
const shown = [
|
|
8777
8791
|
["model", "Model call"],
|
|
@@ -8780,13 +8794,19 @@ function KindLegend({ rows }) {
|
|
|
8780
8794
|
["handoff", "Handoff"]
|
|
8781
8795
|
].filter(([kind]) => kind === "waiting" ? rows.some((row) => row.kind === "pipeline") : kind === "handoff" ? rows.some((row) => row.span.handoffTo || row.hasAgents) : has(kind));
|
|
8782
8796
|
if (shown.length === 0) return null;
|
|
8783
|
-
|
|
8797
|
+
const example = rows.find((row) => toneKey(row.tone) > 0 && row.own.some((mark) => mark.kind === "model")) ?? rows.find((row) => row.own.length);
|
|
8798
|
+
return /* @__PURE__ */ jsxs("ul", {
|
|
8784
8799
|
className: "fw-legend fw-kinds",
|
|
8785
8800
|
"aria-label": "Key",
|
|
8786
|
-
|
|
8801
|
+
"data-tone": fill === "agent" ? toneKey(example?.tone ?? 0) : void 0,
|
|
8802
|
+
"data-example": example?.id,
|
|
8803
|
+
children: [shown.map(([kind, name]) => /* @__PURE__ */ jsxs("li", { children: [/* @__PURE__ */ jsx("span", {
|
|
8787
8804
|
className: `fw-swatch-${kind === "waiting" ? "wait" : kind}`,
|
|
8788
8805
|
"aria-hidden": true
|
|
8789
|
-
}), name] }, kind))
|
|
8806
|
+
}), name] }, kind)), /* @__PURE__ */ jsx("li", {
|
|
8807
|
+
className: "fw-kind-rule",
|
|
8808
|
+
children: fill === "agent" ? "Bar color identifies family; shade identifies work." : "Shade identifies work."
|
|
8809
|
+
})]
|
|
8790
8810
|
});
|
|
8791
8811
|
}
|
|
8792
8812
|
/** The axis dots and the dashed lines they drop: one key naming what they mark (a release, or the kinds the host gave). */
|
|
@@ -8886,17 +8906,37 @@ function OutcomeLegend({ agents, selected, onFilter, neutral }) {
|
|
|
8886
8906
|
]
|
|
8887
8907
|
});
|
|
8888
8908
|
}
|
|
8909
|
+
function ViewControl({ view, graph, onChange }) {
|
|
8910
|
+
return /* @__PURE__ */ jsx("div", {
|
|
8911
|
+
className: "fw-views",
|
|
8912
|
+
role: "radiogroup",
|
|
8913
|
+
"aria-label": "Trace view",
|
|
8914
|
+
children: [
|
|
8915
|
+
"agents",
|
|
8916
|
+
"spans",
|
|
8917
|
+
...graph ? ["graph"] : []
|
|
8918
|
+
].map((option) => /* @__PURE__ */ jsx("button", {
|
|
8919
|
+
type: "button",
|
|
8920
|
+
role: "radio",
|
|
8921
|
+
"aria-checked": view === option,
|
|
8922
|
+
disabled: view === option,
|
|
8923
|
+
className: "fw-view-button",
|
|
8924
|
+
onClick: () => onChange(option),
|
|
8925
|
+
children: option === "agents" ? "Agents" : option === "spans" ? "Steps" : "Graph"
|
|
8926
|
+
}, option))
|
|
8927
|
+
});
|
|
8928
|
+
}
|
|
8889
8929
|
/** Shared trace inspector: the agent timeline and the span waterfall over one clock.
|
|
8890
8930
|
* Data remains producer-owned; playback, zoom and folding change presentation only. */
|
|
8891
|
-
function FlowWaterfall({ trace, live, startedAt, label = "Trace waterfall", defaultCollapsed = false, defaultView = "spans", renderIcon, maxHeight, onSelect, markers, onTimeChange, agentFill: fillProp, selectedId, onDeselect, description, summary: showSummary = true, criticalPath = false, query: queryProp, onQueryChange, collapsed: collapsedProp, onCollapsedChange, zoom: zoomProp, onZoomChange, matchSpan }) {
|
|
8931
|
+
function FlowWaterfall({ trace, live, startedAt, label = "Trace waterfall", defaultCollapsed = false, defaultView = "spans", graph, latestEvents, renderIcon, maxHeight, onSelect, markers, onTimeChange, agentFill: fillProp, selectedId, onDeselect, description, summary: showSummary = true, criticalPath = false, query: queryProp, onQueryChange, collapsed: collapsedProp, onCollapsedChange, zoom: zoomProp, onZoomChange, matchSpan }) {
|
|
8892
8932
|
const root = useRef(null);
|
|
8893
8933
|
const search = useRef(null);
|
|
8894
8934
|
const slider = useRef(null);
|
|
8895
8935
|
const timeOutput = useRef(null);
|
|
8896
8936
|
const hideTimer = useRef(void 0);
|
|
8897
|
-
const searchId = useId();
|
|
8898
|
-
const
|
|
8899
|
-
const
|
|
8937
|
+
const searchId = useId(), cardId = useId();
|
|
8938
|
+
const [requestedView, setView] = useState(defaultView);
|
|
8939
|
+
const view = requestedView === "graph" && graph == null ? "agents" : requestedView;
|
|
8900
8940
|
const [query, setQuery] = useHostable(queryProp, onQueryChange, "");
|
|
8901
8941
|
const [collapsed, setCollapsed] = useHostable(collapsedProp, onCollapsedChange, () => new Set(defaultCollapsed ? trace.spans.flatMap((span) => span.parentId ? [span.parentId] : []) : []));
|
|
8902
8942
|
const [speed, setSpeed] = useState(1);
|
|
@@ -9012,6 +9052,7 @@ function FlowWaterfall({ trace, live, startedAt, label = "Trace waterfall", defa
|
|
|
9012
9052
|
}, [view, agents]);
|
|
9013
9053
|
useEffect(() => {
|
|
9014
9054
|
const keydown = (event) => {
|
|
9055
|
+
if (view === "graph") return;
|
|
9015
9056
|
const active = document.activeElement;
|
|
9016
9057
|
const ownsFocus = root.current?.contains(active);
|
|
9017
9058
|
if ((event.metaKey || event.ctrlKey) && event.key.toLowerCase() === "f") {
|
|
@@ -9326,7 +9367,7 @@ function FlowWaterfall({ trace, live, startedAt, label = "Trace waterfall", defa
|
|
|
9326
9367
|
done && speedup >= 1.05 ? ` · ${speedup.toFixed(1)}x parallel` : ""
|
|
9327
9368
|
]
|
|
9328
9369
|
}),
|
|
9329
|
-
failedAgents > 0 && /* @__PURE__ */ jsxs("button", {
|
|
9370
|
+
view !== "graph" && failedAgents > 0 && /* @__PURE__ */ jsxs("button", {
|
|
9330
9371
|
type: "button",
|
|
9331
9372
|
className: "fw-text-button fw-alert",
|
|
9332
9373
|
"aria-pressed": filter === "__errors",
|
|
@@ -9338,7 +9379,7 @@ function FlowWaterfall({ trace, live, startedAt, label = "Trace waterfall", defa
|
|
|
9338
9379
|
" failed"
|
|
9339
9380
|
]
|
|
9340
9381
|
}),
|
|
9341
|
-
quietAgents > 0 && /* @__PURE__ */ jsxs("button", {
|
|
9382
|
+
view !== "graph" && quietAgents > 0 && /* @__PURE__ */ jsxs("button", {
|
|
9342
9383
|
type: "button",
|
|
9343
9384
|
className: "fw-text-button fw-quiet",
|
|
9344
9385
|
"aria-pressed": filter === "__quiet",
|
|
@@ -9351,7 +9392,7 @@ function FlowWaterfall({ trace, live, startedAt, label = "Trace waterfall", defa
|
|
|
9351
9392
|
children: "Live"
|
|
9352
9393
|
})
|
|
9353
9394
|
]
|
|
9354
|
-
}), /* @__PURE__ */ jsxs("details", {
|
|
9395
|
+
}), view !== "graph" && /* @__PURE__ */ jsxs("details", {
|
|
9355
9396
|
className: "fw-key",
|
|
9356
9397
|
open: root.current ? root.current.clientWidth >= 600 : true,
|
|
9357
9398
|
children: [/* @__PURE__ */ jsxs("summary", { children: ["Key", /* @__PURE__ */ jsx(ChevronGlyph, {})] }), /* @__PURE__ */ jsxs("div", {
|
|
@@ -9363,30 +9404,24 @@ function FlowWaterfall({ trace, live, startedAt, label = "Trace waterfall", defa
|
|
|
9363
9404
|
selected: filter,
|
|
9364
9405
|
onFilter: applyFilter
|
|
9365
9406
|
}),
|
|
9366
|
-
view === "agents" && /* @__PURE__ */ jsx(KindLegend, {
|
|
9407
|
+
view === "agents" && /* @__PURE__ */ jsx(KindLegend, {
|
|
9408
|
+
rows: visible,
|
|
9409
|
+
fill: agentFill
|
|
9410
|
+
}),
|
|
9367
9411
|
/* @__PURE__ */ jsx(MarkerLegend, { markers })
|
|
9368
9412
|
]
|
|
9369
9413
|
})]
|
|
9370
9414
|
})]
|
|
9371
9415
|
}), /* @__PURE__ */ jsxs("div", {
|
|
9372
9416
|
className: "fw-tools",
|
|
9373
|
-
children: [/* @__PURE__ */ jsx(
|
|
9374
|
-
|
|
9375
|
-
|
|
9376
|
-
|
|
9377
|
-
|
|
9378
|
-
|
|
9379
|
-
|
|
9380
|
-
|
|
9381
|
-
disabled: view === option,
|
|
9382
|
-
className: "fw-view-button",
|
|
9383
|
-
onClick: () => {
|
|
9384
|
-
setView(option);
|
|
9385
|
-
setNameWidth(NAME_WIDTH[option]);
|
|
9386
|
-
setCard(null);
|
|
9387
|
-
},
|
|
9388
|
-
children: option === "agents" ? "Agents" : "Steps"
|
|
9389
|
-
}, option))
|
|
9417
|
+
children: [/* @__PURE__ */ jsx(ViewControl, {
|
|
9418
|
+
view,
|
|
9419
|
+
graph: graph != null,
|
|
9420
|
+
onChange: (option) => {
|
|
9421
|
+
setView(option);
|
|
9422
|
+
setNameWidth(NAME_WIDTH[option]);
|
|
9423
|
+
setCard(null);
|
|
9424
|
+
}
|
|
9390
9425
|
}), view === "spans" && /* @__PURE__ */ jsxs("div", {
|
|
9391
9426
|
className: "fw-search",
|
|
9392
9427
|
children: [
|
|
@@ -9420,91 +9455,94 @@ function FlowWaterfall({ trace, live, startedAt, label = "Trace waterfall", defa
|
|
|
9420
9455
|
})]
|
|
9421
9456
|
})]
|
|
9422
9457
|
}),
|
|
9423
|
-
|
|
9424
|
-
|
|
9425
|
-
|
|
9426
|
-
className:
|
|
9427
|
-
children: [
|
|
9428
|
-
className: "fw-
|
|
9429
|
-
|
|
9430
|
-
|
|
9431
|
-
|
|
9432
|
-
|
|
9433
|
-
|
|
9434
|
-
|
|
9435
|
-
|
|
9436
|
-
|
|
9437
|
-
|
|
9438
|
-
|
|
9439
|
-
|
|
9440
|
-
|
|
9441
|
-
|
|
9442
|
-
|
|
9443
|
-
|
|
9444
|
-
|
|
9445
|
-
|
|
9446
|
-
|
|
9447
|
-
|
|
9448
|
-
|
|
9449
|
-
|
|
9450
|
-
|
|
9451
|
-
|
|
9452
|
-
|
|
9453
|
-
|
|
9454
|
-
|
|
9455
|
-
|
|
9456
|
-
|
|
9457
|
-
|
|
9458
|
-
|
|
9459
|
-
|
|
9460
|
-
|
|
9461
|
-
|
|
9462
|
-
|
|
9463
|
-
|
|
9464
|
-
|
|
9465
|
-
trackPx,
|
|
9466
|
-
showCursor,
|
|
9467
|
-
markers,
|
|
9468
|
-
fillByAgent: agentFill !== "outcome",
|
|
9469
|
-
zoomed: zoom !== null,
|
|
9470
|
-
renderIcon,
|
|
9471
|
-
emptyText: rows.length === 0 ? "No spans yet. Waiting for trace events." : `No matching steps for “${query}”.`,
|
|
9472
|
-
onToggle: toggle,
|
|
9473
|
-
onInspect: inspect,
|
|
9474
|
-
onLeave: leave,
|
|
9475
|
-
onPin: pin,
|
|
9476
|
-
onActivate: (row) => setActiveId(row.id),
|
|
9477
|
-
onActiveChange: setActiveId,
|
|
9478
|
-
onScrub: scrubTo,
|
|
9479
|
-
onZoom: zoomBy,
|
|
9480
|
-
onPan: pan,
|
|
9481
|
-
nameWidth,
|
|
9482
|
-
onNameWidth: (px) => {
|
|
9483
|
-
resized.current = true;
|
|
9484
|
-
setNameWidth(Math.max(140, Math.min(560, px)));
|
|
9485
|
-
},
|
|
9486
|
-
onTrack: setLaneElement,
|
|
9487
|
-
onExpandAll: rows.some((row) => row.hasChildren) ? () => setCollapsed(/* @__PURE__ */ new Set()) : void 0,
|
|
9488
|
-
onCollapseAll: () => setCollapsed(new Set(rows.filter((row) => row.hasChildren).map((row) => row.id)))
|
|
9489
|
-
}),
|
|
9490
|
-
card && cardRow && /* @__PURE__ */ jsx("div", {
|
|
9491
|
-
className: `fw-card-anchor${card.above && card.top === void 0 ? " fw-card-above" : ""}`,
|
|
9492
|
-
onPointerEnter: () => clearTimeout(hideTimer.current),
|
|
9493
|
-
onPointerLeave: card.pinned ? void 0 : leave,
|
|
9494
|
-
children: /* @__PURE__ */ jsx(SpanCard, {
|
|
9495
|
-
id: cardId,
|
|
9496
|
-
row: cardRow,
|
|
9497
|
-
agent: cardAgent,
|
|
9458
|
+
latestEvents,
|
|
9459
|
+
view === "graph" ? graph : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
9460
|
+
showSummary && /* @__PURE__ */ jsx("dl", {
|
|
9461
|
+
className: "fw-summary",
|
|
9462
|
+
children: summary.map(([name, value, title]) => /* @__PURE__ */ jsxs("div", {
|
|
9463
|
+
className: name === "Errors" && errors !== void 0 && errors > 0 ? "fw-has-errors" : void 0,
|
|
9464
|
+
children: [/* @__PURE__ */ jsx("dt", { children: name }), /* @__PURE__ */ jsx("dd", {
|
|
9465
|
+
className: "fw-value",
|
|
9466
|
+
title,
|
|
9467
|
+
children: name === "Errors" ? /* @__PURE__ */ jsx("button", {
|
|
9468
|
+
type: "button",
|
|
9469
|
+
"aria-pressed": filter === "__errors",
|
|
9470
|
+
onClick: () => applyFilter("__errors"),
|
|
9471
|
+
children: value
|
|
9472
|
+
}) : value
|
|
9473
|
+
})]
|
|
9474
|
+
}, name))
|
|
9475
|
+
}),
|
|
9476
|
+
view === "agents" && playback,
|
|
9477
|
+
/* @__PURE__ */ jsx(FlowBody, {
|
|
9478
|
+
rows: visible,
|
|
9479
|
+
byId,
|
|
9480
|
+
totalRows: rows.length,
|
|
9481
|
+
view,
|
|
9482
|
+
maxHeight: rowsHeight,
|
|
9483
|
+
collapsed,
|
|
9484
|
+
searching: Boolean(query.trim()),
|
|
9485
|
+
query,
|
|
9486
|
+
matchSpan,
|
|
9487
|
+
pauses: trace.pauses,
|
|
9488
|
+
errorTimes,
|
|
9489
|
+
cursorLine: isLive || position !== null || playing,
|
|
9490
|
+
sharedDetail,
|
|
9491
|
+
sharedOutcome,
|
|
9492
|
+
expandedIds: view === "agents" ? /* @__PURE__ */ new Set([...openFamilies, ...openSteps]) : void 0,
|
|
9493
|
+
holdHeight: isLive,
|
|
9494
|
+
slowestId: slowest?.id ?? callouts.slowestId,
|
|
9495
|
+
costliestId: callouts.costliestId,
|
|
9496
|
+
criticalIds: criticalPath && view === "spans" ? critical : void 0,
|
|
9497
|
+
activeId,
|
|
9498
|
+
selectedId: selection,
|
|
9499
|
+
focusId: cardAgent?.id ?? (view === "agents" ? activeId : void 0),
|
|
9498
9500
|
clockMs,
|
|
9499
|
-
|
|
9500
|
-
|
|
9501
|
-
|
|
9502
|
-
|
|
9501
|
+
window: win,
|
|
9502
|
+
trackPx,
|
|
9503
|
+
showCursor,
|
|
9504
|
+
markers,
|
|
9505
|
+
fillByAgent: agentFill !== "outcome",
|
|
9506
|
+
zoomed: zoom !== null,
|
|
9503
9507
|
renderIcon,
|
|
9504
|
-
|
|
9505
|
-
|
|
9506
|
-
|
|
9507
|
-
|
|
9508
|
+
emptyText: rows.length === 0 ? "No spans yet. Waiting for trace events." : `No matching steps for “${query}”.`,
|
|
9509
|
+
onToggle: toggle,
|
|
9510
|
+
onInspect: inspect,
|
|
9511
|
+
onLeave: leave,
|
|
9512
|
+
onPin: pin,
|
|
9513
|
+
onActivate: (row) => setActiveId(row.id),
|
|
9514
|
+
onActiveChange: setActiveId,
|
|
9515
|
+
onScrub: scrubTo,
|
|
9516
|
+
onZoom: zoomBy,
|
|
9517
|
+
onPan: pan,
|
|
9518
|
+
nameWidth,
|
|
9519
|
+
onNameWidth: (px) => {
|
|
9520
|
+
resized.current = true;
|
|
9521
|
+
setNameWidth(Math.max(140, Math.min(560, px)));
|
|
9522
|
+
},
|
|
9523
|
+
onTrack: setLaneElement,
|
|
9524
|
+
onExpandAll: rows.some((row) => row.hasChildren) ? () => setCollapsed(/* @__PURE__ */ new Set()) : void 0,
|
|
9525
|
+
onCollapseAll: () => setCollapsed(new Set(rows.filter((row) => row.hasChildren).map((row) => row.id)))
|
|
9526
|
+
}),
|
|
9527
|
+
card && cardRow && /* @__PURE__ */ jsx("div", {
|
|
9528
|
+
className: `fw-card-anchor${card.above && card.top === void 0 ? " fw-card-above" : ""}`,
|
|
9529
|
+
onPointerEnter: () => clearTimeout(hideTimer.current),
|
|
9530
|
+
onPointerLeave: card.pinned ? void 0 : leave,
|
|
9531
|
+
children: /* @__PURE__ */ jsx(SpanCard, {
|
|
9532
|
+
id: cardId,
|
|
9533
|
+
row: cardRow,
|
|
9534
|
+
agent: cardAgent,
|
|
9535
|
+
clockMs,
|
|
9536
|
+
left: card.left,
|
|
9537
|
+
top: card.top ?? (card.above ? card.anchorTop - 8 : card.anchorBottom + 8),
|
|
9538
|
+
pinned: card.pinned,
|
|
9539
|
+
onClose: closeCard,
|
|
9540
|
+
renderIcon,
|
|
9541
|
+
compact: view === "agents"
|
|
9542
|
+
})
|
|
9543
|
+
}),
|
|
9544
|
+
view === "spans" && playback
|
|
9545
|
+
] })
|
|
9508
9546
|
]
|
|
9509
9547
|
});
|
|
9510
9548
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tangle-network/charts",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.2",
|
|
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",
|