@tangle-network/charts 2.0.16 → 2.0.17
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 +2 -0
- package/dist/react/index.d.ts +62 -1
- package/dist/react/index.js +238 -3
- package/dist/react/live.css +39 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,6 +4,8 @@ Benchmark figures as static SVG and HTML tables, plus optional React timing prim
|
|
|
4
4
|
|
|
5
5
|
The React entry also exports `DayBars`, `HBars`, `Histogram`, `Lines`, `Meter`, `Spark`, and `Gantt` for live operational pages. Import `@tangle-network/charts/react/live.css` for their layout and set `--chart-live-*` theme tokens on an ancestor. Data, state colors, destination links, labels, and interpretation remain with the caller. `DayBars` accepts an `onOpen(index)` action with keyboard activation.
|
|
6
6
|
|
|
7
|
+
`VersionGraph` and `layoutVersionGraph` from `@tangle-network/charts/react` render version histories with lane and merge geometry, controlled selection, filtering, keyboard navigation and bounded rows. Import `react/live.css` and Brand tokens as above. Producers supply commit identities, parents, lane labels and scored chips; Charts preserves those facts and owns drawing, arrival motion and reduced-motion behavior.
|
|
8
|
+
|
|
7
9
|
`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
10
|
|
|
9
11
|
`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.
|
package/dist/react/index.d.ts
CHANGED
|
@@ -538,4 +538,65 @@ export declare function FlowWaterfall({ trace, live, startedAt, label, defaultCo
|
|
|
538
538
|
/** Generic tool identity by name: a terminal, a file, a pencil, a lens, a globe or a branch, never a vendor mark. */
|
|
539
539
|
export declare function toolGlyph(name: string | undefined): import("react").JSX.Element | undefined;
|
|
540
540
|
//#endregion
|
|
541
|
-
|
|
541
|
+
//#region src/react/version-graph.d.ts
|
|
542
|
+
/** `muted` chips sit beside the title; any other tone gets the second line. */
|
|
543
|
+
/** A status tone from `statusOf`, or a non-status chip: `accent` for a series, `info` and `muted` for plain facts. */
|
|
544
|
+
type VersionGraphTone = 'pass' | 'live' | 'attention' | 'fail' | 'neutral' | 'accent' | 'info' | 'muted';
|
|
545
|
+
interface VersionGraphChip {
|
|
546
|
+
readonly label: string;
|
|
547
|
+
readonly tone?: VersionGraphTone;
|
|
548
|
+
readonly title?: string;
|
|
549
|
+
}
|
|
550
|
+
interface VersionGraphNode {
|
|
551
|
+
readonly id: string;
|
|
552
|
+
/** Parents in the model; one that is not in it (or is hidden) is skipped, and a hidden one passes its own on. */
|
|
553
|
+
readonly parents: readonly string[];
|
|
554
|
+
readonly lane: string;
|
|
555
|
+
readonly at: string | null;
|
|
556
|
+
readonly title: string;
|
|
557
|
+
readonly detail?: string | null;
|
|
558
|
+
/** A style hook and a filter key: `write`, `integrate`, `profile`, `version`, `authored`, `ghost`. */
|
|
559
|
+
readonly kind: string;
|
|
560
|
+
readonly chips?: readonly VersionGraphChip[];
|
|
561
|
+
}
|
|
562
|
+
interface VersionGraphLane {
|
|
563
|
+
readonly id: string;
|
|
564
|
+
readonly label: string;
|
|
565
|
+
readonly detail?: string | null;
|
|
566
|
+
}
|
|
567
|
+
/** Nodes newest first, every child above its parents. */
|
|
568
|
+
interface VersionGraphModel {
|
|
569
|
+
readonly lanes: readonly VersionGraphLane[];
|
|
570
|
+
readonly nodes: readonly VersionGraphNode[];
|
|
571
|
+
}
|
|
572
|
+
/**
|
|
573
|
+
* Rows in model order, one column per lane that holds a shown node, and one edge from each shown node to each nearest
|
|
574
|
+
* shown ancestor: a hidden node (an integration when integrations are hidden, a commit of a lane filtered out) passes
|
|
575
|
+
* its parents on, so a lane's line stays connected.
|
|
576
|
+
*/
|
|
577
|
+
export declare function layoutVersionGraph(model: VersionGraphModel, shown?: (node: VersionGraphNode) => boolean): {
|
|
578
|
+
rows: {
|
|
579
|
+
node: VersionGraphNode;
|
|
580
|
+
row: number;
|
|
581
|
+
column: number;
|
|
582
|
+
}[];
|
|
583
|
+
edges: {
|
|
584
|
+
from: string;
|
|
585
|
+
to: string;
|
|
586
|
+
fromRow: number;
|
|
587
|
+
fromColumn: number;
|
|
588
|
+
toRow: number;
|
|
589
|
+
toColumn: number;
|
|
590
|
+
}[];
|
|
591
|
+
lanes: VersionGraphLane[];
|
|
592
|
+
};
|
|
593
|
+
export declare function VersionGraph({ model, selected, onSelect, label, shown, maxHeight }: {
|
|
594
|
+
model: VersionGraphModel;
|
|
595
|
+
selected: string | null;
|
|
596
|
+
onSelect: (id: string) => void;
|
|
597
|
+
label: string;
|
|
598
|
+
shown?: (node: VersionGraphNode) => boolean;
|
|
599
|
+
maxHeight?: number;
|
|
600
|
+
}): import("react").JSX.Element;
|
|
601
|
+
//#endregion
|
|
602
|
+
export type { BandKind, ChartBand, ChartMark, DotMapLabel, DotMapProps, DotMapRect, Figure, FigureAtWidth, FigureViewProps, FlowWaterfallProps, FlowWaterfallRow, ViewWindow as FlowWaterfallWindow, 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, VersionGraphChip, VersionGraphLane, VersionGraphModel, VersionGraphNode, VersionGraphTone, WaterfallBarProps, WaterfallHeaderProps, WaterfallRowProps, WaterfallSpanGeometry, WaterfallTimeAxisProps, WaterfallWindow, XCategory, YScale, YTarget, YTick };
|
package/dist/react/index.js
CHANGED
|
@@ -3354,7 +3354,7 @@ function useRowMotion(rows, element) {
|
|
|
3354
3354
|
const previous = known.current;
|
|
3355
3355
|
let order = 0;
|
|
3356
3356
|
for (const row of rows) {
|
|
3357
|
-
const isRunning = spanRunning(row.span);
|
|
3357
|
+
const isRunning = !!row.span && spanRunning(row.span);
|
|
3358
3358
|
if (!previous || !previous.has(row.id)) active.current.set(row.id, {
|
|
3359
3359
|
enter: Math.min(order++ * stagger, cap),
|
|
3360
3360
|
until: now + hold + cap
|
|
@@ -3365,7 +3365,7 @@ function useRowMotion(rows, element) {
|
|
|
3365
3365
|
});
|
|
3366
3366
|
}
|
|
3367
3367
|
known.current = new Set(rows.map((row) => row.id));
|
|
3368
|
-
running.current = new Set(rows.filter((row) => spanRunning(row.span)).map((row) => row.id));
|
|
3368
|
+
running.current = new Set(rows.filter((row) => row.span && spanRunning(row.span)).map((row) => row.id));
|
|
3369
3369
|
return new Map(active.current);
|
|
3370
3370
|
}, [
|
|
3371
3371
|
rows,
|
|
@@ -5062,4 +5062,239 @@ function FlowWaterfall({ trace, live, startedAt, label = "Trace waterfall", defa
|
|
|
5062
5062
|
});
|
|
5063
5063
|
}
|
|
5064
5064
|
//#endregion
|
|
5065
|
-
|
|
5065
|
+
//#region src/react/version-graph.tsx
|
|
5066
|
+
/** Recorded version lanes; callers supply their domain model, filters and selection. */
|
|
5067
|
+
/**
|
|
5068
|
+
* Rows in model order, one column per lane that holds a shown node, and one edge from each shown node to each nearest
|
|
5069
|
+
* shown ancestor: a hidden node (an integration when integrations are hidden, a commit of a lane filtered out) passes
|
|
5070
|
+
* its parents on, so a lane's line stays connected.
|
|
5071
|
+
*/
|
|
5072
|
+
function layoutVersionGraph(model, shown = () => true) {
|
|
5073
|
+
const byId = new Map(model.nodes.map((node) => [node.id, node]));
|
|
5074
|
+
const visible = model.nodes.filter(shown);
|
|
5075
|
+
const visibleIds = new Set(visible.map((node) => node.id));
|
|
5076
|
+
const lanes = model.lanes.filter((lane) => visible.some((node) => node.lane === lane.id));
|
|
5077
|
+
for (const node of visible) if (!lanes.some((lane) => lane.id === node.lane)) lanes.push({
|
|
5078
|
+
id: node.lane,
|
|
5079
|
+
label: node.lane
|
|
5080
|
+
});
|
|
5081
|
+
const column = new Map(lanes.map((lane, i) => [lane.id, i]));
|
|
5082
|
+
const rowOf = new Map(visible.map((node, i) => [node.id, i]));
|
|
5083
|
+
const nearest = (id, seen) => {
|
|
5084
|
+
if (seen.has(id)) return [];
|
|
5085
|
+
seen.add(id);
|
|
5086
|
+
if (visibleIds.has(id)) return [id];
|
|
5087
|
+
const node = byId.get(id);
|
|
5088
|
+
return node ? node.parents.flatMap((parent) => nearest(parent, seen)) : [];
|
|
5089
|
+
};
|
|
5090
|
+
const edges = [];
|
|
5091
|
+
for (const node of visible) {
|
|
5092
|
+
const seen = /* @__PURE__ */ new Set([node.id]);
|
|
5093
|
+
const targets = [...new Set(node.parents.flatMap((parent) => nearest(parent, seen)))];
|
|
5094
|
+
for (const target of targets) {
|
|
5095
|
+
const toRow = rowOf.get(target);
|
|
5096
|
+
if (toRow <= rowOf.get(node.id)) continue;
|
|
5097
|
+
edges.push({
|
|
5098
|
+
from: node.id,
|
|
5099
|
+
to: target,
|
|
5100
|
+
fromRow: rowOf.get(node.id),
|
|
5101
|
+
fromColumn: column.get(node.lane),
|
|
5102
|
+
toRow,
|
|
5103
|
+
toColumn: column.get(byId.get(target).lane)
|
|
5104
|
+
});
|
|
5105
|
+
}
|
|
5106
|
+
}
|
|
5107
|
+
return {
|
|
5108
|
+
rows: visible.map((node, i) => ({
|
|
5109
|
+
node,
|
|
5110
|
+
row: i,
|
|
5111
|
+
column: column.get(node.lane)
|
|
5112
|
+
})),
|
|
5113
|
+
edges,
|
|
5114
|
+
lanes
|
|
5115
|
+
};
|
|
5116
|
+
}
|
|
5117
|
+
const WIDE = {
|
|
5118
|
+
column: 16,
|
|
5119
|
+
gutter: 14
|
|
5120
|
+
};
|
|
5121
|
+
const NARROW = {
|
|
5122
|
+
column: 5,
|
|
5123
|
+
gutter: 4
|
|
5124
|
+
};
|
|
5125
|
+
const LINE = 30;
|
|
5126
|
+
const TALL = 54;
|
|
5127
|
+
const BEND = 22;
|
|
5128
|
+
const COLORS = 8;
|
|
5129
|
+
const tall = (node) => (node.chips ?? []).some((chip) => chip.tone && chip.tone !== "muted");
|
|
5130
|
+
function VersionGraph({ model, selected, onSelect, label, shown, maxHeight = 600 }) {
|
|
5131
|
+
const laid = useMemo(() => layoutVersionGraph(model, shown), [model, shown]);
|
|
5132
|
+
const tops = useMemo(() => {
|
|
5133
|
+
const out = [];
|
|
5134
|
+
let y = 0;
|
|
5135
|
+
for (const row of laid.rows) {
|
|
5136
|
+
out.push(y);
|
|
5137
|
+
y += tall(row.node) ? TALL : LINE;
|
|
5138
|
+
}
|
|
5139
|
+
out.push(y);
|
|
5140
|
+
return out;
|
|
5141
|
+
}, [laid]);
|
|
5142
|
+
const height = tops.at(-1) ?? 0;
|
|
5143
|
+
const [measure, measuredWidth] = useWidth();
|
|
5144
|
+
const { column: COLUMN, gutter: GUTTER } = measuredWidth < 700 ? NARROW : WIDE;
|
|
5145
|
+
const width = GUTTER + laid.lanes.length * COLUMN;
|
|
5146
|
+
const x = (column) => GUTTER / 2 + column * COLUMN + COLUMN / 2;
|
|
5147
|
+
const y = (row) => tops[row] + LINE / 2;
|
|
5148
|
+
const path = (fromRow, fromColumn, toRow, toColumn) => {
|
|
5149
|
+
const [x1, y1, x2, y2] = [
|
|
5150
|
+
x(fromColumn),
|
|
5151
|
+
y(fromRow),
|
|
5152
|
+
x(toColumn),
|
|
5153
|
+
y(toRow)
|
|
5154
|
+
];
|
|
5155
|
+
if (x1 === x2) return `M${x1},${y1} V${y2}`;
|
|
5156
|
+
const bend = Math.min(BEND, y2 - y1);
|
|
5157
|
+
return `M${x1},${y1} C${x1},${y1 + bend * .7} ${x2},${y1 + bend * .3} ${x2},${y1 + bend} V${y2}`;
|
|
5158
|
+
};
|
|
5159
|
+
const pane = useRef(null);
|
|
5160
|
+
const focusTarget = useRef(null);
|
|
5161
|
+
const arrived = useRef(/* @__PURE__ */ new Set());
|
|
5162
|
+
const motion = useRowMotion(model.nodes, pane.current);
|
|
5163
|
+
const [scrollTop, setScrollTop] = useState(0);
|
|
5164
|
+
const first = Math.max(0, tops.findIndex((top) => top >= scrollTop) - 7);
|
|
5165
|
+
const after = tops.findIndex((top) => top > scrollTop + maxHeight);
|
|
5166
|
+
const end = after < 0 ? laid.rows.length : Math.min(laid.rows.length, after + 7);
|
|
5167
|
+
const visible = laid.rows.slice(first, end);
|
|
5168
|
+
const focusRow = (index) => {
|
|
5169
|
+
const at = Math.max(0, Math.min(laid.rows.length - 1, index)), top = tops[at] ?? 0;
|
|
5170
|
+
focusTarget.current = laid.rows[at]?.node.id ?? null;
|
|
5171
|
+
if (pane.current) pane.current.scrollTop = top;
|
|
5172
|
+
setScrollTop(top);
|
|
5173
|
+
const target = pane.current?.querySelector(`[data-row="${at}"]`);
|
|
5174
|
+
if (target) {
|
|
5175
|
+
focusTarget.current = null;
|
|
5176
|
+
target.focus();
|
|
5177
|
+
}
|
|
5178
|
+
};
|
|
5179
|
+
useEffect(() => {
|
|
5180
|
+
const at = laid.rows.findIndex((row) => row.node.id === selected), element = pane.current;
|
|
5181
|
+
if (at < 0 || !element) return;
|
|
5182
|
+
const top = tops[at], bottom = tops[at + 1];
|
|
5183
|
+
if (top < element.scrollTop) element.scrollTop = Math.max(0, top - 8);
|
|
5184
|
+
else if (bottom > element.scrollTop + element.clientHeight) element.scrollTop = bottom - element.clientHeight + 8;
|
|
5185
|
+
setScrollTop(element.scrollTop);
|
|
5186
|
+
}, [selected]);
|
|
5187
|
+
const allLanes = useMemo(() => layoutVersionGraph(model).lanes, [model]);
|
|
5188
|
+
const colorOf = new Map(allLanes.map((item, i) => [item.id, i % COLORS]));
|
|
5189
|
+
return /* @__PURE__ */ jsx("div", {
|
|
5190
|
+
ref: measure,
|
|
5191
|
+
className: "tgc-version-graph",
|
|
5192
|
+
"data-version-graph": label,
|
|
5193
|
+
children: laid.rows.length === 0 ? /* @__PURE__ */ jsx("p", {
|
|
5194
|
+
className: "ov-empty",
|
|
5195
|
+
children: "Nothing to show with these filters."
|
|
5196
|
+
}) : /* @__PURE__ */ jsx("div", {
|
|
5197
|
+
ref: pane,
|
|
5198
|
+
className: "vg-scroll",
|
|
5199
|
+
style: {
|
|
5200
|
+
maxHeight,
|
|
5201
|
+
overflow: "auto"
|
|
5202
|
+
},
|
|
5203
|
+
onScroll: (event) => setScrollTop(event.currentTarget.scrollTop),
|
|
5204
|
+
onKeyDown: (event) => {
|
|
5205
|
+
const at = Number(event.target.closest("[data-row]")?.getAttribute("data-row"));
|
|
5206
|
+
const next = event.key === "Home" ? 0 : event.key === "End" ? laid.rows.length - 1 : event.key === "ArrowDown" ? at + 1 : event.key === "ArrowUp" ? at - 1 : null;
|
|
5207
|
+
if (next !== null) {
|
|
5208
|
+
event.preventDefault();
|
|
5209
|
+
focusRow(next);
|
|
5210
|
+
}
|
|
5211
|
+
},
|
|
5212
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
5213
|
+
className: "vg-host",
|
|
5214
|
+
style: { height },
|
|
5215
|
+
children: [/* @__PURE__ */ jsxs("svg", {
|
|
5216
|
+
className: "vg-lines",
|
|
5217
|
+
width,
|
|
5218
|
+
height,
|
|
5219
|
+
"aria-hidden": "true",
|
|
5220
|
+
children: [laid.edges.filter((edge) => y(edge.fromRow) <= scrollTop + maxHeight + TALL && y(edge.toRow) >= scrollTop - TALL).map((edge) => /* @__PURE__ */ jsx("path", {
|
|
5221
|
+
"data-from": edge.from,
|
|
5222
|
+
"data-to": edge.to,
|
|
5223
|
+
className: `vg-c${colorOf.get(laid.lanes[edge.toColumn].id)} ${selected === edge.from || selected === edge.to ? "hot" : ""}`,
|
|
5224
|
+
d: path(edge.fromRow, edge.fromColumn, edge.toRow, edge.toColumn)
|
|
5225
|
+
}, `${edge.from}>${edge.to}`)), visible.map((row) => /* @__PURE__ */ jsx("circle", {
|
|
5226
|
+
className: `vg-dot vg-c${colorOf.get(row.node.lane)} kind-${row.node.kind} ${selected === row.node.id ? "on" : ""}`,
|
|
5227
|
+
cx: x(row.column),
|
|
5228
|
+
cy: y(row.row),
|
|
5229
|
+
r: row.node.kind === "integrate" ? 3 : 5
|
|
5230
|
+
}, row.node.id))]
|
|
5231
|
+
}), /* @__PURE__ */ jsx("ol", {
|
|
5232
|
+
className: "vg-rows",
|
|
5233
|
+
"aria-label": label,
|
|
5234
|
+
style: {
|
|
5235
|
+
paddingLeft: width,
|
|
5236
|
+
paddingTop: tops[first]
|
|
5237
|
+
},
|
|
5238
|
+
children: visible.map((row) => {
|
|
5239
|
+
const node = row.node;
|
|
5240
|
+
const on = selected === node.id;
|
|
5241
|
+
const arriving = motion.get(node.id)?.enter !== void 0 && !arrived.current.has(node.id);
|
|
5242
|
+
const loud = (node.chips ?? []).filter((chip) => chip.tone && chip.tone !== "muted");
|
|
5243
|
+
const quiet = (node.chips ?? []).filter((chip) => !chip.tone || chip.tone === "muted");
|
|
5244
|
+
return /* @__PURE__ */ jsx("li", {
|
|
5245
|
+
"aria-posinset": row.row + 1,
|
|
5246
|
+
"aria-setsize": laid.rows.length,
|
|
5247
|
+
style: { height: tops[row.row + 1] - tops[row.row] },
|
|
5248
|
+
children: /* @__PURE__ */ jsxs("button", {
|
|
5249
|
+
ref: (element) => {
|
|
5250
|
+
if (!element) return;
|
|
5251
|
+
if (arriving) arrived.current.add(node.id);
|
|
5252
|
+
if (focusTarget.current === node.id) {
|
|
5253
|
+
focusTarget.current = null;
|
|
5254
|
+
element.focus();
|
|
5255
|
+
}
|
|
5256
|
+
},
|
|
5257
|
+
type: "button",
|
|
5258
|
+
className: `vg-row kind-${node.kind} ${on ? "on" : ""}`,
|
|
5259
|
+
"aria-pressed": on,
|
|
5260
|
+
disabled: node.kind === "ghost",
|
|
5261
|
+
"data-node": node.id,
|
|
5262
|
+
"data-row": row.row,
|
|
5263
|
+
"data-arriving": arriving || void 0,
|
|
5264
|
+
onClick: () => onSelect(node.id),
|
|
5265
|
+
children: [/* @__PURE__ */ jsxs("span", {
|
|
5266
|
+
className: "vg-line",
|
|
5267
|
+
children: [
|
|
5268
|
+
/* @__PURE__ */ jsx("b", {
|
|
5269
|
+
className: "vg-title",
|
|
5270
|
+
title: node.title,
|
|
5271
|
+
children: node.title
|
|
5272
|
+
}),
|
|
5273
|
+
node.detail && /* @__PURE__ */ jsx("span", {
|
|
5274
|
+
className: "vg-detail",
|
|
5275
|
+
children: node.detail
|
|
5276
|
+
}),
|
|
5277
|
+
quiet.map((chip, i) => /* @__PURE__ */ jsx("span", {
|
|
5278
|
+
className: "vg-chip tone-muted",
|
|
5279
|
+
title: chip.title,
|
|
5280
|
+
children: chip.label
|
|
5281
|
+
}, i))
|
|
5282
|
+
]
|
|
5283
|
+
}), loud.length > 0 && /* @__PURE__ */ jsx("span", {
|
|
5284
|
+
className: "vg-line vg-tags",
|
|
5285
|
+
children: loud.map((chip, i) => /* @__PURE__ */ jsx("span", {
|
|
5286
|
+
className: `vg-chip tone-${chip.tone}`,
|
|
5287
|
+
title: chip.title,
|
|
5288
|
+
children: chip.label
|
|
5289
|
+
}, i))
|
|
5290
|
+
})]
|
|
5291
|
+
})
|
|
5292
|
+
}, node.id);
|
|
5293
|
+
})
|
|
5294
|
+
})]
|
|
5295
|
+
})
|
|
5296
|
+
})
|
|
5297
|
+
});
|
|
5298
|
+
}
|
|
5299
|
+
//#endregion
|
|
5300
|
+
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, VersionGraph, WaterfallBar, WaterfallHeader, WaterfallRow, WaterfallTimeAxis, criticalPathIds, flowWaterfallRows, formatCompact, formatSparklineValue, formatWaterfallDuration, layoutVersionGraph, sparklineGeometry, sparklineLabel, sparklinePointsAttribute, sparklineReadings, toolGlyph, waterfallSpanGeometry, waterfallTicks };
|
package/dist/react/live.css
CHANGED
|
@@ -129,3 +129,42 @@ line.ov-gridline { stroke: color-mix(in srgb, var(--chart-live-faint, #777) 22%,
|
|
|
129
129
|
|
|
130
130
|
.ov-meter-steps span { overflow-wrap: anywhere; }
|
|
131
131
|
@media (max-width: 720px) { .ov-meter-steps { grid-template-columns: repeat(3, minmax(0, 1fr)); } .ov-meter-steps li { padding: 12px; min-height: 94px; } }
|
|
132
|
+
|
|
133
|
+
/* Recorded version history shares chart/Brand roles with the live timeline. */
|
|
134
|
+
.tgc-version-graph { min-width: 0; font: 14px/1.4 var(--font-sans, sans-serif); color: var(--chart-live-fg, var(--text-primary));
|
|
135
|
+
--vg-c0: var(--chart-live-accent, var(--accent-text)); --vg-c1: light-dark(#2a7fa8, #6cc0e8); --vg-c2: light-dark(#7b4fc0, #b99af0); --vg-c3: light-dark(#1f7f88, #5fc2c9); --vg-c4: light-dark(#a8418f, #e58ccf); --vg-c5: light-dark(#5a6ad8, #8fa4ff); --vg-c6: light-dark(#45507a, #c0c4dc); --vg-c7: var(--chart-live-muted, var(--text-muted));
|
|
136
|
+
}
|
|
137
|
+
.tgc-version-graph .vg-host { position: relative; min-width: max-content; }
|
|
138
|
+
.tgc-version-graph .vg-lines { position: absolute; left: 0; top: 0; pointer-events: none; overflow: visible; }
|
|
139
|
+
.tgc-version-graph .vg-lines path { fill: none; stroke: currentColor; stroke-width: 2; opacity: .55; }
|
|
140
|
+
.tgc-version-graph .vg-lines path.hot { opacity: 1; stroke-width: 2.5; }
|
|
141
|
+
.tgc-version-graph .vg-lines .vg-dot { fill: currentColor; stroke: var(--chart-live-surface, var(--bg-surface)); stroke-width: 2; }
|
|
142
|
+
.tgc-version-graph .vg-lines .vg-dot.kind-profile, .tgc-version-graph .vg-lines .vg-dot.kind-authored { fill: var(--chart-live-surface, var(--bg-surface)); stroke: currentColor; stroke-width: 2.5; }
|
|
143
|
+
.tgc-version-graph .vg-lines .vg-dot.kind-ghost { fill: var(--chart-live-surface, var(--bg-surface)); stroke: var(--chart-live-faint, var(--text-muted)); stroke-dasharray: 2 2; }
|
|
144
|
+
.tgc-version-graph .vg-lines .vg-dot.on { stroke: var(--chart-live-fg, var(--text-primary)); stroke-width: 3; }
|
|
145
|
+
.tgc-version-graph .vg-c0 { color: var(--vg-c0); } .tgc-version-graph .vg-c1 { color: var(--vg-c1); } .tgc-version-graph .vg-c2 { color: var(--vg-c2); } .tgc-version-graph .vg-c3 { color: var(--vg-c3); }
|
|
146
|
+
.tgc-version-graph .vg-c4 { color: var(--vg-c4); } .tgc-version-graph .vg-c5 { color: var(--vg-c5); } .tgc-version-graph .vg-c6 { color: var(--vg-c6); } .tgc-version-graph .vg-c7 { color: var(--vg-c7); }
|
|
147
|
+
.tgc-version-graph .vg-rows { list-style: none; margin: 0; padding-right: 8px; }
|
|
148
|
+
.tgc-version-graph .vg-rows > li { display: flex; }
|
|
149
|
+
.tgc-version-graph .vg-row { display: flex; flex-direction: column; justify-content: flex-start; gap: 4px; width: 100%; min-width: 0; padding: 0 8px; border: 0; border-radius: 6px; background: none; color: var(--chart-live-fg, var(--text-primary)); font: inherit; text-align: left; cursor: pointer; }
|
|
150
|
+
.tgc-version-graph .vg-row:hover, .tgc-version-graph .vg-row:focus-visible { background: var(--chart-live-raised, var(--bg-elevated)); }
|
|
151
|
+
.tgc-version-graph .vg-row:focus-visible { outline: 2px solid var(--chart-live-accent, var(--accent-text)); outline-offset: -2px; }
|
|
152
|
+
.tgc-version-graph .vg-row.on { background: color-mix(in srgb, var(--chart-live-accent, var(--accent-text)) 13%, var(--chart-live-surface, var(--bg-surface))); box-shadow: inset 2px 0 var(--chart-live-border, var(--border-color)); }
|
|
153
|
+
.tgc-version-graph .vg-row:disabled { cursor: default; opacity: .8; }
|
|
154
|
+
.tgc-version-graph .vg-line { display: flex; align-items: center; gap: 8px; min-width: 0; height: 30px; flex: none; }
|
|
155
|
+
.tgc-version-graph .vg-line.vg-tags { height: 22px; flex-wrap: nowrap; overflow: hidden; }
|
|
156
|
+
.tgc-version-graph .vg-title { font-weight: 600; max-width: 46ch; }
|
|
157
|
+
.tgc-version-graph .vg-row.kind-integrate .vg-title { font-weight: 400; color: var(--chart-live-muted, var(--text-muted)); }
|
|
158
|
+
.tgc-version-graph .vg-row.kind-ghost .vg-title { font-weight: 400; color: var(--chart-live-faint, var(--text-muted)); }
|
|
159
|
+
.tgc-version-graph .vg-detail { font-size: var(--font-size-sm, 13px); color: var(--chart-live-muted, var(--text-muted)); }
|
|
160
|
+
.tgc-version-graph .vg-chip { display: inline-block; flex: none; margin-left: 4px; padding: 0 8px; border-radius: 4px; font: 600 var(--font-size-sm, 13px)/1.6 var(--font-sans); white-space: nowrap; background: var(--chart-live-raised, var(--bg-elevated)); color: var(--chart-live-muted, var(--text-muted)); }
|
|
161
|
+
.tgc-version-graph .vg-chip.tone-neutral { background: none; box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--chart-live-muted, var(--text-muted)) 55%, transparent); }
|
|
162
|
+
.tgc-version-graph .vg-chip.tone-accent { color: var(--chart-live-accent, var(--accent-text)); background: color-mix(in srgb, var(--chart-live-accent, var(--accent-text)) 14%, transparent); }
|
|
163
|
+
.tgc-version-graph .vg-chip.tone-info { color: var(--chart-live-fg, var(--text-primary)); background: var(--chart-live-raised, var(--bg-elevated)); font-weight: 400; }
|
|
164
|
+
|
|
165
|
+
.tgc-version-graph :is(.vg-title,.vg-detail) { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
166
|
+
@media (forced-colors: active) { .tgc-version-graph .vg-chip { forced-color-adjust: none; border: 1px solid CanvasText; } }
|
|
167
|
+
|
|
168
|
+
.tgc-version-graph .vg-row[data-arriving] { transition: opacity var(--motion-arrive); }
|
|
169
|
+
@starting-style { .tgc-version-graph .vg-row[data-arriving] { opacity: 0; } }
|
|
170
|
+
@media (prefers-reduced-motion: reduce) { .tgc-version-graph .vg-row[data-arriving] { transition: none; } }
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tangle-network/charts",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.17",
|
|
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",
|