@tangle-network/charts 0.20.2 → 0.21.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.
- package/dist/react/flow-waterfall.css +2 -1
- package/dist/react/index.d.ts +26 -1
- package/dist/react/index.js +126 -3
- package/dist/react/live.css +8 -0
- package/package.json +1 -1
|
@@ -262,7 +262,8 @@
|
|
|
262
262
|
.fw-root .fw-badge { height: 18px; padding: 0 8px; border-radius: 999px; font-size: 12px; line-height: 16px; font-weight: 600; color: var(--fw-amber); background: color-mix(in oklab, var(--fw-amber) 13%, transparent); border: 1px solid color-mix(in oklab, var(--fw-amber) 28%, transparent); }
|
|
263
263
|
|
|
264
264
|
/* Handoff elbows: 1.5 px stroke, 6 px radius, a 5 px dot where the handoff leaves its sender. */
|
|
265
|
-
|
|
265
|
+
/* Under the rows (which follow it), so end labels and badges always sit above the connectors. */
|
|
266
|
+
.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; }
|
|
266
267
|
.fw-root .fw-link {
|
|
267
268
|
--x: calc(var(--fw-pad) + (var(--s) - var(--fw-v0)) * var(--fw-k) * 1px);
|
|
268
269
|
position: absolute; width: 8px; border: 0 solid var(--line); border-bottom-width: 1.5px; translate: 0 var(--fw-bar-shift);
|
package/dist/react/index.d.ts
CHANGED
|
@@ -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. */
|
|
@@ -2663,7 +2775,8 @@ function agentFamilies(agents, open) {
|
|
|
2663
2775
|
detail: members[0].span.detail,
|
|
2664
2776
|
meta: {
|
|
2665
2777
|
failedAgents: failed,
|
|
2666
|
-
costPartial: known.length < members.length
|
|
2778
|
+
costPartial: known.length < members.length,
|
|
2779
|
+
members: members.map((row) => row.id)
|
|
2667
2780
|
}
|
|
2668
2781
|
}
|
|
2669
2782
|
});
|
|
@@ -2780,6 +2893,16 @@ function stepRuns(steps) {
|
|
|
2780
2893
|
}
|
|
2781
2894
|
return out;
|
|
2782
2895
|
}
|
|
2896
|
+
/** A row as the view draws it: its drawn copy, or for a member of a folded family, itself in the family's hue. */
|
|
2897
|
+
function drawnRow(row, visible) {
|
|
2898
|
+
const drawn = visible.find((item) => item.id === row.id);
|
|
2899
|
+
if (drawn) return drawn;
|
|
2900
|
+
const family = visible.find((item) => (item.span.meta?.members)?.includes(row.id));
|
|
2901
|
+
return family ? {
|
|
2902
|
+
...row,
|
|
2903
|
+
tone: family.tone
|
|
2904
|
+
} : row;
|
|
2905
|
+
}
|
|
2783
2906
|
//#endregion
|
|
2784
2907
|
//#region src/react/flow-waterfall-icons.tsx
|
|
2785
2908
|
const svg = (children, label) => /* @__PURE__ */ jsx("svg", {
|
|
@@ -4550,7 +4673,7 @@ function FlowWaterfall({ trace, live, startedAt, label = "Trace waterfall", defa
|
|
|
4550
4673
|
const busy = agents.reduce((sum, row) => sum + busyMs(row, limit), 0);
|
|
4551
4674
|
const speedup = limit > 0 ? busy / limit : 0;
|
|
4552
4675
|
const done = !isLive && !trace.spans.some(spanRunning);
|
|
4553
|
-
const shown = (row) => row && (
|
|
4676
|
+
const shown = (row) => row && drawnRow(row, visible);
|
|
4554
4677
|
const cardRow = shown(card ? byId.get(card.target) : void 0);
|
|
4555
4678
|
const cardAgent = cardRow && (() => {
|
|
4556
4679
|
for (let cursor = cardRow; cursor; cursor = cursor.parentId ? byId.get(cursor.parentId) : void 0) if (cursor.kind === "pipeline") return shown(cursor);
|
|
@@ -4781,4 +4904,4 @@ function FlowWaterfall({ trace, live, startedAt, label = "Trace waterfall", defa
|
|
|
4781
4904
|
});
|
|
4782
4905
|
}
|
|
4783
4906
|
//#endregion
|
|
4784
|
-
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 };
|
|
4907
|
+
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.0",
|
|
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",
|