@arcfusionz/arc-analytic-ui 0.0.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/_virtual/_rolldown/runtime.js +13 -0
- package/dist/components/AnomalyCard/AnomalyCard.chart.d.ts +64 -0
- package/dist/components/AnomalyCard/AnomalyCard.chart.js +341 -0
- package/dist/components/AnomalyCard/AnomalyCard.d.ts +169 -0
- package/dist/components/AnomalyCard/AnomalyCard.js +1019 -0
- package/dist/components/AnomalyCard/AnomalyCard.model.d.ts +508 -0
- package/dist/components/AnomalyCard/AnomalyCard.model.js +553 -0
- package/dist/components/AnomalyCard/index.d.ts +4 -0
- package/dist/components/AnomalyCard/index.js +4 -0
- package/dist/components/ChartCard/ChartCard.chart.d.ts +72 -0
- package/dist/components/ChartCard/ChartCard.chart.js +1333 -0
- package/dist/components/ChartCard/ChartCard.d.ts +206 -0
- package/dist/components/ChartCard/ChartCard.js +718 -0
- package/dist/components/ChartCard/ChartCard.model.d.ts +452 -0
- package/dist/components/ChartCard/ChartCard.model.js +1223 -0
- package/dist/components/ChartCard/index.d.ts +4 -0
- package/dist/components/ChartCard/index.js +4 -0
- package/dist/components/ComparisonCard/ComparisonCard.chart.d.ts +80 -0
- package/dist/components/ComparisonCard/ComparisonCard.chart.js +337 -0
- package/dist/components/ComparisonCard/ComparisonCard.d.ts +200 -0
- package/dist/components/ComparisonCard/ComparisonCard.js +1325 -0
- package/dist/components/ComparisonCard/ComparisonCard.model.d.ts +309 -0
- package/dist/components/ComparisonCard/ComparisonCard.model.js +263 -0
- package/dist/components/ComparisonCard/index.d.ts +4 -0
- package/dist/components/ComparisonCard/index.js +4 -0
- package/dist/components/ForecastCard/ForecastCard.chart.d.ts +82 -0
- package/dist/components/ForecastCard/ForecastCard.chart.js +416 -0
- package/dist/components/ForecastCard/ForecastCard.d.ts +148 -0
- package/dist/components/ForecastCard/ForecastCard.js +1029 -0
- package/dist/components/ForecastCard/ForecastCard.model.d.ts +497 -0
- package/dist/components/ForecastCard/ForecastCard.model.js +554 -0
- package/dist/components/ForecastCard/index.d.ts +4 -0
- package/dist/components/ForecastCard/index.js +4 -0
- package/dist/components/HighlightCard/HighlightCard.chart.d.ts +122 -0
- package/dist/components/HighlightCard/HighlightCard.chart.js +660 -0
- package/dist/components/HighlightCard/HighlightCard.d.ts +202 -0
- package/dist/components/HighlightCard/HighlightCard.js +1286 -0
- package/dist/components/HighlightCard/HighlightCard.model.d.ts +692 -0
- package/dist/components/HighlightCard/HighlightCard.model.js +875 -0
- package/dist/components/HighlightCard/index.d.ts +4 -0
- package/dist/components/HighlightCard/index.js +4 -0
- package/dist/components/InsightCard/InsightCard.chart.d.ts +91 -0
- package/dist/components/InsightCard/InsightCard.chart.js +471 -0
- package/dist/components/InsightCard/InsightCard.d.ts +161 -0
- package/dist/components/InsightCard/InsightCard.js +961 -0
- package/dist/components/InsightCard/InsightCard.model.d.ts +405 -0
- package/dist/components/InsightCard/InsightCard.model.js +421 -0
- package/dist/components/InsightCard/index.d.ts +4 -0
- package/dist/components/InsightCard/index.js +4 -0
- package/dist/components/MetricCard/MetricCard.chart.d.ts +79 -0
- package/dist/components/MetricCard/MetricCard.chart.js +435 -0
- package/dist/components/MetricCard/MetricCard.d.ts +227 -0
- package/dist/components/MetricCard/MetricCard.js +1293 -0
- package/dist/components/MetricCard/MetricCard.model.d.ts +521 -0
- package/dist/components/MetricCard/MetricCard.model.js +627 -0
- package/dist/components/MetricCard/index.d.ts +4 -0
- package/dist/components/MetricCard/index.js +4 -0
- package/dist/components/ProfileCard/ProfileCard.chart.d.ts +64 -0
- package/dist/components/ProfileCard/ProfileCard.chart.js +427 -0
- package/dist/components/ProfileCard/ProfileCard.d.ts +140 -0
- package/dist/components/ProfileCard/ProfileCard.js +735 -0
- package/dist/components/ProfileCard/ProfileCard.model.d.ts +279 -0
- package/dist/components/ProfileCard/ProfileCard.model.js +244 -0
- package/dist/components/ProfileCard/index.d.ts +4 -0
- package/dist/components/ProfileCard/index.js +4 -0
- package/dist/components/ProgressCard/ProgressCard.chart.d.ts +73 -0
- package/dist/components/ProgressCard/ProgressCard.chart.js +373 -0
- package/dist/components/ProgressCard/ProgressCard.d.ts +137 -0
- package/dist/components/ProgressCard/ProgressCard.js +908 -0
- package/dist/components/ProgressCard/ProgressCard.model.d.ts +385 -0
- package/dist/components/ProgressCard/ProgressCard.model.js +389 -0
- package/dist/components/ProgressCard/index.d.ts +4 -0
- package/dist/components/ProgressCard/index.js +4 -0
- package/dist/components/ReportCard/ReportCard.chart.d.ts +45 -0
- package/dist/components/ReportCard/ReportCard.chart.js +231 -0
- package/dist/components/ReportCard/ReportCard.d.ts +153 -0
- package/dist/components/ReportCard/ReportCard.js +1118 -0
- package/dist/components/ReportCard/ReportCard.model.d.ts +392 -0
- package/dist/components/ReportCard/ReportCard.model.js +399 -0
- package/dist/components/ReportCard/index.d.ts +4 -0
- package/dist/components/ReportCard/index.js +4 -0
- package/dist/components/SankeyCard/SankeyCard.chart.d.ts +75 -0
- package/dist/components/SankeyCard/SankeyCard.chart.js +249 -0
- package/dist/components/SankeyCard/SankeyCard.d.ts +185 -0
- package/dist/components/SankeyCard/SankeyCard.js +788 -0
- package/dist/components/SankeyCard/SankeyCard.model.d.ts +501 -0
- package/dist/components/SankeyCard/SankeyCard.model.js +789 -0
- package/dist/components/SankeyCard/index.d.ts +4 -0
- package/dist/components/SankeyCard/index.js +4 -0
- package/dist/components/StatusCard/StatusCard.chart.d.ts +60 -0
- package/dist/components/StatusCard/StatusCard.chart.js +188 -0
- package/dist/components/StatusCard/StatusCard.d.ts +176 -0
- package/dist/components/StatusCard/StatusCard.js +989 -0
- package/dist/components/StatusCard/StatusCard.model.d.ts +555 -0
- package/dist/components/StatusCard/StatusCard.model.js +776 -0
- package/dist/components/StatusCard/index.d.ts +4 -0
- package/dist/components/StatusCard/index.js +4 -0
- package/dist/components/TableCard/TableCard.chart.d.ts +53 -0
- package/dist/components/TableCard/TableCard.chart.js +192 -0
- package/dist/components/TableCard/TableCard.d.ts +140 -0
- package/dist/components/TableCard/TableCard.js +811 -0
- package/dist/components/TableCard/TableCard.model.d.ts +381 -0
- package/dist/components/TableCard/TableCard.model.js +475 -0
- package/dist/components/TableCard/index.d.ts +4 -0
- package/dist/components/TableCard/index.js +4 -0
- package/dist/components/TargetCard/TargetCard.chart.d.ts +52 -0
- package/dist/components/TargetCard/TargetCard.chart.js +273 -0
- package/dist/components/TargetCard/TargetCard.d.ts +143 -0
- package/dist/components/TargetCard/TargetCard.js +910 -0
- package/dist/components/TargetCard/TargetCard.model.d.ts +468 -0
- package/dist/components/TargetCard/TargetCard.model.js +581 -0
- package/dist/components/TargetCard/index.d.ts +4 -0
- package/dist/components/TargetCard/index.js +4 -0
- package/dist/components/TreeCard/TreeCard.chart.d.ts +80 -0
- package/dist/components/TreeCard/TreeCard.chart.js +178 -0
- package/dist/components/TreeCard/TreeCard.d.ts +182 -0
- package/dist/components/TreeCard/TreeCard.js +1187 -0
- package/dist/components/TreeCard/TreeCard.model.d.ts +330 -0
- package/dist/components/TreeCard/TreeCard.model.js +401 -0
- package/dist/components/TreeCard/index.d.ts +4 -0
- package/dist/components/TreeCard/index.js +4 -0
- package/dist/components/TrendCard/TrendCard.chart.d.ts +75 -0
- package/dist/components/TrendCard/TrendCard.chart.js +393 -0
- package/dist/components/TrendCard/TrendCard.d.ts +224 -0
- package/dist/components/TrendCard/TrendCard.js +1053 -0
- package/dist/components/TrendCard/TrendCard.model.d.ts +545 -0
- package/dist/components/TrendCard/TrendCard.model.js +623 -0
- package/dist/components/TrendCard/index.d.ts +4 -0
- package/dist/components/TrendCard/index.js +4 -0
- package/dist/index.d.ts +76 -0
- package/dist/index.js +57 -0
- package/dist/lib/vega/ArcVegaChart.d.ts +24 -0
- package/dist/lib/vega/ArcVegaChart.js +42 -0
- package/dist/lib/vega/ArcVegaSurface.d.ts +13 -0
- package/dist/lib/vega/ArcVegaSurface.js +38 -0
- package/dist/lib/vega/axisTicks.js +156 -0
- package/dist/lib/vega/config.d.ts +29 -0
- package/dist/lib/vega/config.js +113 -0
- package/dist/lib/vega/embed.d.ts +29 -0
- package/dist/lib/vega/embed.js +29 -0
- package/dist/lib/vega/engine.d.ts +10 -0
- package/dist/lib/vega/engine.js +6 -0
- package/dist/lib/vega/formatters.d.ts +125 -0
- package/dist/lib/vega/formatters.js +277 -0
- package/dist/lib/vega/index.d.ts +11 -0
- package/dist/lib/vega/load.d.ts +13 -0
- package/dist/lib/vega/load.js +21 -0
- package/dist/lib/vega/time.d.ts +45 -0
- package/dist/lib/vega/time.js +105 -0
- package/dist/lib/vega/tokens.d.ts +73 -0
- package/dist/lib/vega/tokens.js +137 -0
- package/dist/lib/vega/tooltip.d.ts +45 -0
- package/dist/lib/vega/tooltip.js +124 -0
- package/dist/lib/vega/useArcVega.d.ts +43 -0
- package/dist/lib/vega/useArcVega.js +121 -0
- package/package.json +60 -0
|
@@ -0,0 +1,501 @@
|
|
|
1
|
+
//#region src/components/SankeyCard/SankeyCard.model.d.ts
|
|
2
|
+
/** What the consumer's transport reports. */
|
|
3
|
+
type SankeyCardStatus = "loading" | "ready" | "error";
|
|
4
|
+
/**
|
|
5
|
+
* What the card actually shows, derived from `status`, the links and
|
|
6
|
+
* `filtered`. Stamped on the root as `data-state`.
|
|
7
|
+
*/
|
|
8
|
+
type SankeyCardState = "loading" | "refreshing" | "ready" | "empty" | "no-match" | "insufficient" | "error";
|
|
9
|
+
type SankeyCardSize = "sm" | "md" | "lg";
|
|
10
|
+
/**
|
|
11
|
+
* Which column a node lands in.
|
|
12
|
+
*
|
|
13
|
+
* - `justify` (default): depth is the longest path from a source, but every
|
|
14
|
+
* node with no outgoing flow is pushed to the LAST column. The funnel
|
|
15
|
+
* reading — terminal buckets line up on the right however early they were
|
|
16
|
+
* reached, so "where did the volume end up" is one vertical scan.
|
|
17
|
+
* - `left`: depth is the longest path from a source, and a terminal bucket
|
|
18
|
+
* stays in the column it was reached in. The process reading — the x axis
|
|
19
|
+
* is elapsed stages, so an early exit is visibly early.
|
|
20
|
+
* - `right`: depth is counted back from the sinks, so sources spread out
|
|
21
|
+
* instead of terminals. Reach for it when the question is what FEEDS an
|
|
22
|
+
* outcome rather than what becomes of an input.
|
|
23
|
+
*
|
|
24
|
+
* Stamped as `data-align`.
|
|
25
|
+
*/
|
|
26
|
+
type SankeyAlign = "left" | "right" | "justify";
|
|
27
|
+
/**
|
|
28
|
+
* What colour means on the ribbons — one job per chart.
|
|
29
|
+
*
|
|
30
|
+
* - `none` (default): every ribbon takes the one emphasis hue. Thickness and
|
|
31
|
+
* position already carry the whole comparison, so this is the honest
|
|
32
|
+
* default: a hue per stage would only restate the x position, which is
|
|
33
|
+
* decoration, and decoration still costs attention.
|
|
34
|
+
* - `polarity`: the `tone` each link declares — retained, lost, neutral — on
|
|
35
|
+
* the diverging ends. The one licensed use of a good/bad hue on a mark,
|
|
36
|
+
* because here the value genuinely MEANS good or bad. The funnel answer.
|
|
37
|
+
* - `terminal`: identity by the outcome each flow ends in, from the fixed
|
|
38
|
+
* categorical slots. The allocation answer — where did the volume land.
|
|
39
|
+
* - `node`: identity by the flow's source node. The attribution answer —
|
|
40
|
+
* which input produced this.
|
|
41
|
+
*
|
|
42
|
+
* `terminal` and `node` are capped by the theme's identity budget
|
|
43
|
+
* (`SANKEY_MAX_IDENTITY`): past it the tail folds to the context gray and the
|
|
44
|
+
* card stamps `data-over-identity` rather than repeating a slot, because two
|
|
45
|
+
* entities in one hue is a lie a legend cannot fix. Stamped as `data-color`.
|
|
46
|
+
*/
|
|
47
|
+
type SankeyColor = "none" | "polarity" | "terminal" | "node";
|
|
48
|
+
/**
|
|
49
|
+
* How nodes are stacked inside their column.
|
|
50
|
+
*
|
|
51
|
+
* - `declared` (default when `nodes` is given): the consumer's own order. A
|
|
52
|
+
* node keeps its place — and its identity colour slot — when the data
|
|
53
|
+
* changes, so a filter cannot reshuffle the diagram under the reader.
|
|
54
|
+
* - `value`: largest first. The ranking read, and the default when `nodes` is
|
|
55
|
+
* omitted and there is no declared order to honour.
|
|
56
|
+
*/
|
|
57
|
+
type SankeyNodeOrder = "declared" | "value";
|
|
58
|
+
/** What a flow means, when it means anything: volume kept, volume lost, or neither. */
|
|
59
|
+
type SankeyTone = "positive" | "negative" | "neutral";
|
|
60
|
+
/**
|
|
61
|
+
* Which node names the plot draws.
|
|
62
|
+
*
|
|
63
|
+
* - `all` (default): every node. Interior names sit to the right of their
|
|
64
|
+
* node, over the ribbons, in the foreground text role.
|
|
65
|
+
* - `ends`: the first and last columns only — the two that carry the question
|
|
66
|
+
* — each in its own gutter, so no name ever sits over a ribbon. The right
|
|
67
|
+
* choice on a narrow panel.
|
|
68
|
+
* - `none`: no names on the plot; the table and the tooltip carry every one.
|
|
69
|
+
*
|
|
70
|
+
* Stamped as `data-labels`.
|
|
71
|
+
*/
|
|
72
|
+
type SankeyNodeLabels = "all" | "ends" | "none";
|
|
73
|
+
/**
|
|
74
|
+
* The theme ships three categorical identity slots (`chart-1…3`), because
|
|
75
|
+
* three of the brand's six hues are reserved for status. An identity encoding
|
|
76
|
+
* past that folds its tail to the context gray instead of repeating a slot.
|
|
77
|
+
*/
|
|
78
|
+
declare const SANKEY_MAX_IDENTITY = 3;
|
|
79
|
+
/** Below two columns there is no flow to draw — one column is a bar chart, and the card says so instead of drawing a sankey of nothing. */
|
|
80
|
+
declare const SANKEY_MIN_STAGES = 2;
|
|
81
|
+
/**
|
|
82
|
+
* Below two flows there is nothing to compare. A diagram of ONE ribbon is a
|
|
83
|
+
* picture of a single number: it has no sibling to weigh it against, no split
|
|
84
|
+
* to read a share at, and no chain — every reason this card exists is
|
|
85
|
+
* missing. The reader is better served by a number, so the card declines and
|
|
86
|
+
* says so rather than drawing a decoration.
|
|
87
|
+
*/
|
|
88
|
+
declare const SANKEY_MIN_FLOWS = 2;
|
|
89
|
+
/** Points sampled along each ribbon edge. Fixed, so a Chromatic baseline never drifts on it. */
|
|
90
|
+
declare const RIBBON_SAMPLES = 20;
|
|
91
|
+
/**
|
|
92
|
+
* One node, declared. `nodes` is optional — the card derives the set from the
|
|
93
|
+
* links — but declaring it fixes the ORDER, which fixes each node's place in
|
|
94
|
+
* its column and its identity colour slot, so the diagram does not reshuffle
|
|
95
|
+
* when the data moves.
|
|
96
|
+
*/
|
|
97
|
+
interface SankeyNode {
|
|
98
|
+
/** Stable id the links refer to. Defaults to `label`. */
|
|
99
|
+
key?: string;
|
|
100
|
+
label: string;
|
|
101
|
+
}
|
|
102
|
+
/** One flow, from one node to another. `source` and `target` are node keys. */
|
|
103
|
+
interface SankeyLink {
|
|
104
|
+
source: string;
|
|
105
|
+
target: string;
|
|
106
|
+
/** The quantity flowing. Must be finite and ≥ 0 — a negative flow has no thickness and is dropped, counted and reported. */
|
|
107
|
+
value: number;
|
|
108
|
+
/** Names this specific flow in the tooltip and the table, in place of `source → target`. */
|
|
109
|
+
label?: string;
|
|
110
|
+
/** What the flow means, for `color="polarity"`. Omitted reads as `neutral`. */
|
|
111
|
+
tone?: SankeyTone;
|
|
112
|
+
}
|
|
113
|
+
/** A node after normalisation: its column, its totals, and whether the two agree. */
|
|
114
|
+
interface SankeyNodeInfo {
|
|
115
|
+
key: string;
|
|
116
|
+
label: string;
|
|
117
|
+
/** Column index, 0-based, after `align`. */
|
|
118
|
+
depth: number;
|
|
119
|
+
/** Position in the consumer's declared order — the identity slot, never the rank, so a filter cannot repaint the survivors. */
|
|
120
|
+
index: number;
|
|
121
|
+
/** Position inside its own column, top to bottom. */
|
|
122
|
+
order: number;
|
|
123
|
+
/** `max(inValue, outValue)` — the d3-sankey convention, so an imbalance shows as unfilled node instead of being hidden. */
|
|
124
|
+
value: number;
|
|
125
|
+
inValue: number;
|
|
126
|
+
outValue: number;
|
|
127
|
+
/**
|
|
128
|
+
* `inValue - outValue`: volume that arrived and did not leave through any
|
|
129
|
+
* declared link. Never balanced away — an unmodelled leak is a finding, and
|
|
130
|
+
* the card reports it in the table, the caption and `data-imbalanced`.
|
|
131
|
+
*/
|
|
132
|
+
imbalance: number;
|
|
133
|
+
isSource: boolean;
|
|
134
|
+
isSink: boolean;
|
|
135
|
+
/** This node is the `Other` fold of its column. */
|
|
136
|
+
folded: boolean;
|
|
137
|
+
/** Labels folded into this node, so the table can still name every one. */
|
|
138
|
+
members: string[];
|
|
139
|
+
/** The paintable colour, baked in so the spec stays structural. */
|
|
140
|
+
color: string;
|
|
141
|
+
}
|
|
142
|
+
/** A flow after normalisation, with its share of the volume leaving its source. */
|
|
143
|
+
interface SankeyLinkInfo {
|
|
144
|
+
/** `source→target`, unique after aggregation. */
|
|
145
|
+
id: string;
|
|
146
|
+
source: string;
|
|
147
|
+
target: string;
|
|
148
|
+
sourceLabel: string;
|
|
149
|
+
targetLabel: string;
|
|
150
|
+
/** The consumer's own name for this flow, when it gave one. */
|
|
151
|
+
label?: string;
|
|
152
|
+
value: number;
|
|
153
|
+
/** `value / source.outValue` — the part-to-whole at this split. `null` when nothing leaves the source. */
|
|
154
|
+
share: number | null;
|
|
155
|
+
tone: SankeyTone;
|
|
156
|
+
color: string;
|
|
157
|
+
/** The source's column, so a flow can be read as "between stage n and n+1". */
|
|
158
|
+
depth: number;
|
|
159
|
+
/** The target's column. Greater than `depth` for every drawn flow. */
|
|
160
|
+
targetDepth: number;
|
|
161
|
+
}
|
|
162
|
+
/** A flow the graph could not keep, and why — reported, never silently dropped. */
|
|
163
|
+
interface SankeyRejectedLink {
|
|
164
|
+
source: string;
|
|
165
|
+
target: string;
|
|
166
|
+
value: number;
|
|
167
|
+
reason: "negative" | "self-loop" | "cycle" | "unknown-node";
|
|
168
|
+
}
|
|
169
|
+
interface SankeySummary {
|
|
170
|
+
nodes: SankeyNodeInfo[];
|
|
171
|
+
links: SankeyLinkInfo[];
|
|
172
|
+
/** Nodes grouped by column, each already in stacking order. */
|
|
173
|
+
columns: SankeyNodeInfo[][];
|
|
174
|
+
/** Number of columns. Below `SANKEY_MIN_STAGES` the card refuses to draw a sankey. */
|
|
175
|
+
stages: number;
|
|
176
|
+
/** Volume entering the diagram — the total leaving the first column's nodes. */
|
|
177
|
+
total: number;
|
|
178
|
+
/** Flows with a value greater than zero — what the plot can actually draw. */
|
|
179
|
+
count: number;
|
|
180
|
+
/** Flows the graph rejected, with the reason. */
|
|
181
|
+
rejected: SankeyRejectedLink[];
|
|
182
|
+
/** A cycle was broken to make the graph drawable. */
|
|
183
|
+
cycles: number;
|
|
184
|
+
/** Nodes whose inflow and outflow disagree. */
|
|
185
|
+
imbalanced: SankeyNodeInfo[];
|
|
186
|
+
/** A column exceeded `maxNodesPerStage` and its tail was folded into `Other`. */
|
|
187
|
+
folded: boolean;
|
|
188
|
+
/** An identity encoding ran past the theme's slot budget and its tail took the context gray. */
|
|
189
|
+
overIdentity: boolean;
|
|
190
|
+
}
|
|
191
|
+
/** Node geometry in normalised [0,1] coordinates — `y` measured DOWNWARD from the top, which the plot's reversed y scale undoes. */
|
|
192
|
+
interface SankeyNodeRow {
|
|
193
|
+
k: string;
|
|
194
|
+
/** The column's centre line. The node rect straddles it with a pixel `mark.width`, so the geometry carries no pixel width of its own. */
|
|
195
|
+
x: number;
|
|
196
|
+
y: number;
|
|
197
|
+
y2: number;
|
|
198
|
+
/** Vertical middle, where the name sits. */
|
|
199
|
+
mid: number;
|
|
200
|
+
/** Node height in PIXELS, so a name only prints its value line when the node is tall enough to hold one. */
|
|
201
|
+
h: number;
|
|
202
|
+
label: string;
|
|
203
|
+
/** Formatted total, for the value line. */
|
|
204
|
+
vt: string;
|
|
205
|
+
c: string;
|
|
206
|
+
/** Column position flags — the first and last columns label into their own gutters, the rest label over the ribbons. */
|
|
207
|
+
first: boolean;
|
|
208
|
+
last: boolean;
|
|
209
|
+
/** Draw this node's name. */
|
|
210
|
+
lab: boolean;
|
|
211
|
+
}
|
|
212
|
+
/** One sampled point along a ribbon. `y`/`y2` are its two edges at that x. */
|
|
213
|
+
interface SankeyRibbonRow {
|
|
214
|
+
id: string;
|
|
215
|
+
x: number;
|
|
216
|
+
y: number;
|
|
217
|
+
y2: number;
|
|
218
|
+
c: string;
|
|
219
|
+
/** Tooltip and highlight fields, carried on every sample so no lookup is needed at hover time. */
|
|
220
|
+
sl: string;
|
|
221
|
+
tl: string;
|
|
222
|
+
v: number;
|
|
223
|
+
/** Formatted share of the source's outflow, or the missing marker. */
|
|
224
|
+
sh: string;
|
|
225
|
+
s: string;
|
|
226
|
+
t: string;
|
|
227
|
+
}
|
|
228
|
+
interface SankeyLayout {
|
|
229
|
+
nodes: SankeyNodeRow[];
|
|
230
|
+
ribbons: SankeyRibbonRow[];
|
|
231
|
+
/** Normalised x centre per column, for the DOM stage headings above the plot. */
|
|
232
|
+
columnCenters: number[];
|
|
233
|
+
/**
|
|
234
|
+
* Drawable flows whose thickness lands under `HAIRLINE_PX` — real volume
|
|
235
|
+
* the plot cannot show at this scale.
|
|
236
|
+
*
|
|
237
|
+
* The card REPORTS these rather than widening them. A minimum ribbon width
|
|
238
|
+
* would make thickness stop meaning quantity, and it cannot be done
|
|
239
|
+
* honestly anyway: widening a ribbon past its share would overflow the node
|
|
240
|
+
* it leaves, so the sum of the ribbons at a node would no longer be the
|
|
241
|
+
* node. The proportions stay exact, the note says the smallest flows are
|
|
242
|
+
* below a pixel, and the table carries their values — which is how
|
|
243
|
+
* StatusCard handles the same problem with a 17-second outage.
|
|
244
|
+
*/
|
|
245
|
+
hairlines: number;
|
|
246
|
+
}
|
|
247
|
+
/** Below this many pixels a ribbon is not a shape a reader can see, whatever it means. */
|
|
248
|
+
declare const HAIRLINE_PX = 1.5;
|
|
249
|
+
/** Every string the card renders or announces, so a product can localise it. Sentences are functions. */
|
|
250
|
+
interface SankeyCardLabels {
|
|
251
|
+
noData: string;
|
|
252
|
+
noMatch: string;
|
|
253
|
+
clearFilters: string;
|
|
254
|
+
error: string;
|
|
255
|
+
retry: string;
|
|
256
|
+
stale: string;
|
|
257
|
+
asOf: string;
|
|
258
|
+
/** The card cannot draw a flow from a single column. */
|
|
259
|
+
insufficient: string;
|
|
260
|
+
/** Column headers of the flow table. */
|
|
261
|
+
tableFrom: string;
|
|
262
|
+
tableTo: string;
|
|
263
|
+
tableValue: string;
|
|
264
|
+
tableShare: string;
|
|
265
|
+
/** Column headers of the node table. */
|
|
266
|
+
tableNode: string;
|
|
267
|
+
tableStage: string;
|
|
268
|
+
tableIn: string;
|
|
269
|
+
tableOut: string;
|
|
270
|
+
tableUnaccounted: string;
|
|
271
|
+
/** The `Other` fold's name, and how the table lists what went into it. */
|
|
272
|
+
other: string;
|
|
273
|
+
otherMembers: (list: string) => string;
|
|
274
|
+
/** Tooltip row titles. */
|
|
275
|
+
flowTitle: string;
|
|
276
|
+
shareTitle: string;
|
|
277
|
+
/** Said once, politely, when the reader picks another node. */
|
|
278
|
+
selectedNode: (label: string) => string;
|
|
279
|
+
/** Clears the node selection. */
|
|
280
|
+
clearSelection: string;
|
|
281
|
+
/** Accessible name of a node's own button in the table — the keyboard path Vega does not provide. */
|
|
282
|
+
selectNode: (label: string) => string;
|
|
283
|
+
showTable: (name: string) => string;
|
|
284
|
+
hideTable: (name: string) => string;
|
|
285
|
+
about: (name: string) => string;
|
|
286
|
+
loading: (name: string) => string;
|
|
287
|
+
tableCaption: (name: string) => string;
|
|
288
|
+
flowsCaption: (name: string) => string;
|
|
289
|
+
nodesCaption: (name: string) => string;
|
|
290
|
+
/** Warns that a cycle was broken so the graph could be drawn at all. */
|
|
291
|
+
cyclesNote: (count: number) => string;
|
|
292
|
+
/** Warns that some volume arrived at a node and did not leave through any declared flow. */
|
|
293
|
+
imbalanceNote: (count: number, amount: string) => string;
|
|
294
|
+
/** Says a column's tail was folded, so a reader never mistakes `Other` for a real bucket. */
|
|
295
|
+
foldedNote: (label: string) => string;
|
|
296
|
+
/** Says the smallest flows are below a pixel at this scale, so the table is the only place to read them. */
|
|
297
|
+
hairlineNote: (count: number) => string;
|
|
298
|
+
/** Says an identity encoding ran out of slots and the tail went gray. */
|
|
299
|
+
overIdentityNote: (max: number) => string;
|
|
300
|
+
/** Names the flows the graph could not keep. */
|
|
301
|
+
rejectedNote: (count: number) => string;
|
|
302
|
+
/** The takeaway: the biggest flow out of the first stage, and the biggest loss. */
|
|
303
|
+
flowSentence: (input: {
|
|
304
|
+
value: string;
|
|
305
|
+
total: string;
|
|
306
|
+
share: string;
|
|
307
|
+
from: string;
|
|
308
|
+
to: string;
|
|
309
|
+
}) => string;
|
|
310
|
+
lossSentence: (input: {
|
|
311
|
+
value: string;
|
|
312
|
+
share: string;
|
|
313
|
+
to: string;
|
|
314
|
+
}) => string;
|
|
315
|
+
/** Lists the stages on the plot. */
|
|
316
|
+
stageSummary: (count: number, list: string) => string;
|
|
317
|
+
/** The plot's own `aria-label`. */
|
|
318
|
+
chartDescription: (input: {
|
|
319
|
+
name: string;
|
|
320
|
+
stages: number;
|
|
321
|
+
nodes: number;
|
|
322
|
+
flows: number;
|
|
323
|
+
total: string;
|
|
324
|
+
stageList: string;
|
|
325
|
+
}) => string;
|
|
326
|
+
/** Accessible name of the AI mark beside the insight sentence. */
|
|
327
|
+
insightMark: string;
|
|
328
|
+
/** The generated insight, as segments so the values render bold while the words stay plain. */
|
|
329
|
+
insight: (input: {
|
|
330
|
+
name: string;
|
|
331
|
+
total: string;
|
|
332
|
+
from: string;
|
|
333
|
+
to: string;
|
|
334
|
+
value: string;
|
|
335
|
+
share: string;
|
|
336
|
+
lossTo: string | null;
|
|
337
|
+
lossValue: string | null;
|
|
338
|
+
lossShare: string | null;
|
|
339
|
+
}) => SankeyInsightSegment[];
|
|
340
|
+
}
|
|
341
|
+
/** A piece of a generated insight: plain text, or a value the card sets in bold. */
|
|
342
|
+
type SankeyInsightSegment = string | {
|
|
343
|
+
value: string;
|
|
344
|
+
};
|
|
345
|
+
declare const DEFAULT_SANKEY_LABELS: SankeyCardLabels;
|
|
346
|
+
declare function resolveSankeyLabels(overrides?: Partial<SankeyCardLabels>): SankeyCardLabels;
|
|
347
|
+
interface DeriveSankeyStateInput {
|
|
348
|
+
status: SankeyCardStatus;
|
|
349
|
+
/** At least one flow with a value greater than zero survived normalisation. */
|
|
350
|
+
hasFlow: boolean;
|
|
351
|
+
/** Anything is on screen already, so a reload is a refresh rather than a first load. */
|
|
352
|
+
hasData: boolean;
|
|
353
|
+
filtered: boolean;
|
|
354
|
+
/** Columns the graph resolved to. */
|
|
355
|
+
stages: number;
|
|
356
|
+
/** Flows with a value greater than zero — what the plot can actually draw. */
|
|
357
|
+
count: number;
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* The state machine. Error wins; loading over existing data is a refresh (the
|
|
361
|
+
* previous render stays under the veil); no flow at all is `no-match` when the
|
|
362
|
+
* consumer's filter caused it and `empty` otherwise.
|
|
363
|
+
*
|
|
364
|
+
* `insufficient` is the honest refusal: a single flow is a picture of one
|
|
365
|
+
* number, with no sibling to compare it against and no chain to follow, so
|
|
366
|
+
* the card declines to draw a sankey of it. The column floor is checked
|
|
367
|
+
* alongside it — a valid flow always spans two columns, so that half is a
|
|
368
|
+
* guard rather than a case, and it keeps the rule true if the depth
|
|
369
|
+
* assignment ever changes.
|
|
370
|
+
*/
|
|
371
|
+
declare function deriveSankeyState({ status, hasFlow, hasData, filtered, stages, count }: DeriveSankeyStateInput): SankeyCardState;
|
|
372
|
+
interface NormalizeSankeyOptions {
|
|
373
|
+
align?: SankeyAlign;
|
|
374
|
+
nodeOrder?: SankeyNodeOrder;
|
|
375
|
+
color?: SankeyColor;
|
|
376
|
+
/** Nodes a column may hold before its smallest fold into `Other`. */
|
|
377
|
+
maxNodesPerStage?: number;
|
|
378
|
+
/** Identity slots in fixed order (`chart-1…N`). */
|
|
379
|
+
palette: readonly string[];
|
|
380
|
+
/** The one hue a `color="none"` diagram draws with. */
|
|
381
|
+
emphasis: string;
|
|
382
|
+
/** The gray a folded identity tail, and every node rect, takes. */
|
|
383
|
+
context: string;
|
|
384
|
+
/** The diverging ends, for `color="polarity"`. */
|
|
385
|
+
positive: string;
|
|
386
|
+
negative: string;
|
|
387
|
+
/** Localised name of the `Other` fold. */
|
|
388
|
+
otherLabel: string;
|
|
389
|
+
}
|
|
390
|
+
/**
|
|
391
|
+
* Normalises `nodes` and `links` into a drawable DAG plus everything the text
|
|
392
|
+
* surfaces read.
|
|
393
|
+
*
|
|
394
|
+
* The order of operations matters and each step is a decision:
|
|
395
|
+
* 1. Keys resolve (a repeat is suffixed), and a link naming a node that does
|
|
396
|
+
* not exist is rejected rather than inventing one.
|
|
397
|
+
* 2. Flows aggregate — two `A→B` rows are one ribbon — and a negative or
|
|
398
|
+
* self-looping flow is rejected. Each rejection is COUNTED and reported.
|
|
399
|
+
* 3. Cycles break, deterministically, and are reported.
|
|
400
|
+
* 4. Depths resolve through `align`.
|
|
401
|
+
* 5. A column past `maxNodesPerStage` folds its smallest into `Other`, links
|
|
402
|
+
* re-route onto the fold and aggregate again. The table still names every
|
|
403
|
+
* member, so the fold is honest rather than a disappearance.
|
|
404
|
+
* 6. Node values are `max(in, out)`, so an imbalance shows as unfilled node
|
|
405
|
+
* rather than being balanced away.
|
|
406
|
+
* 7. Colours are assigned by the node's declared POSITION, never its rank, so
|
|
407
|
+
* filtering cannot repaint the survivors.
|
|
408
|
+
*
|
|
409
|
+
* Returns `null` when there is nothing to speak of.
|
|
410
|
+
*/
|
|
411
|
+
declare function normalizeSankey(nodes: readonly SankeyNode[] | undefined, links: readonly SankeyLink[] | undefined, { align, nodeOrder, color, maxNodesPerStage, palette, emphasis, context, positive, negative, otherLabel }: NormalizeSankeyOptions): SankeySummary | null;
|
|
412
|
+
interface LayoutSankeyOptions {
|
|
413
|
+
/**
|
|
414
|
+
* Plot height in pixels. The only pixel the layout needs: the horizontal
|
|
415
|
+
* axis is normalised to [0,1] and the node rect takes a pixel `mark.width`,
|
|
416
|
+
* so a WIDTH change is `view.width()` and never a relayout.
|
|
417
|
+
*/
|
|
418
|
+
plotHeight: number;
|
|
419
|
+
/** Vertical pixels between stacked nodes. */
|
|
420
|
+
nodeGap: number;
|
|
421
|
+
/** Crossing-reduction passes. Fixed and small, so the result is deterministic. */
|
|
422
|
+
iterations?: number;
|
|
423
|
+
/** 0 draws straight ribbons, 1 the fully eased S. */
|
|
424
|
+
curvature?: number;
|
|
425
|
+
/** Which names the plot draws. */
|
|
426
|
+
labels?: SankeyNodeLabels;
|
|
427
|
+
/** A node shorter than this many pixels gets no name, because the name would collide with its neighbour's. */
|
|
428
|
+
minLabelHeight?: number;
|
|
429
|
+
formatValue: (value: number) => string;
|
|
430
|
+
formatShare: (share: number) => string;
|
|
431
|
+
missing: string;
|
|
432
|
+
}
|
|
433
|
+
/**
|
|
434
|
+
* Turns a summary into normalised geometry.
|
|
435
|
+
*
|
|
436
|
+
* Vertical: one value→pixel scale shared by every column (d3-sankey's `ky`),
|
|
437
|
+
* so a thickness means the same quantity wherever it appears — the whole
|
|
438
|
+
* point of the diagram. Nodes stack from the top with `nodeGap` between them,
|
|
439
|
+
* then a few relaxation passes slide each node toward the weighted centre of
|
|
440
|
+
* what it connects to and push overlaps apart again; that is what stops the
|
|
441
|
+
* ribbons knotting, and it is capped and deterministic so a baseline never
|
|
442
|
+
* drifts. Each node's flows are then stacked in the order of the partner's
|
|
443
|
+
* position, so ribbons run roughly parallel instead of crossing inside a node.
|
|
444
|
+
*
|
|
445
|
+
* Horizontal: a column is a normalised centre LINE. The node rect straddles
|
|
446
|
+
* it with a pixel width and the ribbons run line to line, passing under the
|
|
447
|
+
* opaque rects — so the geometry carries no pixel width at all and the same
|
|
448
|
+
* rows are correct at every panel width.
|
|
449
|
+
*/
|
|
450
|
+
declare function layoutSankey(summary: SankeySummary | null, { plotHeight, nodeGap, iterations, curvature, labels, minLabelHeight, formatValue, formatShare, missing }: LayoutSankeyOptions): SankeyLayout;
|
|
451
|
+
interface SankeyTextFormatters {
|
|
452
|
+
formatValue: (value: number | null | undefined) => string;
|
|
453
|
+
formatShare: (share: number | null | undefined) => string;
|
|
454
|
+
}
|
|
455
|
+
declare function createSankeyFormatters({ format, shareFormat, locale, formatValue }: {
|
|
456
|
+
format: string;
|
|
457
|
+
shareFormat: string;
|
|
458
|
+
locale?: string;
|
|
459
|
+
formatValue?: (value: number) => string;
|
|
460
|
+
}): SankeyTextFormatters;
|
|
461
|
+
interface SankeyHighlights {
|
|
462
|
+
/** The biggest flow out of the first stage — what most of the volume did. */
|
|
463
|
+
main: SankeyLinkInfo;
|
|
464
|
+
/** The biggest flow the data called a loss, when any link declared a tone. */
|
|
465
|
+
loss: SankeyLinkInfo | null;
|
|
466
|
+
}
|
|
467
|
+
/**
|
|
468
|
+
* What the diagram is about: the largest flow leaving the first stage, and
|
|
469
|
+
* the largest declared loss anywhere. Only a link the consumer TONED as
|
|
470
|
+
* negative counts as a loss — the card never decides on its own that an
|
|
471
|
+
* outcome is bad.
|
|
472
|
+
*/
|
|
473
|
+
declare function deriveSankeyHighlights(summary: SankeySummary | null): SankeyHighlights | null;
|
|
474
|
+
interface BuildSankeyDescriptionInput {
|
|
475
|
+
name: string;
|
|
476
|
+
state: SankeyCardState;
|
|
477
|
+
summary: SankeySummary | null;
|
|
478
|
+
formatters: SankeyTextFormatters;
|
|
479
|
+
asOfText?: string | null;
|
|
480
|
+
labels: SankeyCardLabels;
|
|
481
|
+
}
|
|
482
|
+
/** The figure's generated description: the volume, the stages, the main flow, the largest loss, the caveats and the as-of. */
|
|
483
|
+
declare function buildSankeyDescription({ name, state, summary, formatters, asOfText, labels }: BuildSankeyDescriptionInput): string;
|
|
484
|
+
/** The plot's own `aria-label` — the form, the volume, the stages. */
|
|
485
|
+
declare function buildSankeyChartDescription({ name, summary, formatters, labels }: {
|
|
486
|
+
name: string;
|
|
487
|
+
summary: SankeySummary;
|
|
488
|
+
formatters: SankeyTextFormatters;
|
|
489
|
+
labels: SankeyCardLabels;
|
|
490
|
+
}): string;
|
|
491
|
+
/** The generated insight, as segments so the values render bold and the words stay plain. */
|
|
492
|
+
declare function buildSankeyInsight({ name, summary, formatters, labels }: {
|
|
493
|
+
name: string;
|
|
494
|
+
summary: SankeySummary | null;
|
|
495
|
+
formatters: SankeyTextFormatters;
|
|
496
|
+
labels: SankeyCardLabels;
|
|
497
|
+
}): SankeyInsightSegment[] | null;
|
|
498
|
+
/** The plain-text reading of insight segments — for descriptions and tests. */
|
|
499
|
+
declare function sankeyInsightToText(segments: readonly SankeyInsightSegment[]): string;
|
|
500
|
+
//#endregion
|
|
501
|
+
export { BuildSankeyDescriptionInput, DEFAULT_SANKEY_LABELS, DeriveSankeyStateInput, HAIRLINE_PX, LayoutSankeyOptions, NormalizeSankeyOptions, RIBBON_SAMPLES, SANKEY_MAX_IDENTITY, SANKEY_MIN_FLOWS, SANKEY_MIN_STAGES, SankeyAlign, SankeyCardLabels, SankeyCardSize, SankeyCardState, SankeyCardStatus, SankeyColor, SankeyHighlights, SankeyInsightSegment, SankeyLayout, SankeyLink, SankeyLinkInfo, SankeyNode, SankeyNodeInfo, SankeyNodeLabels, SankeyNodeOrder, SankeyNodeRow, SankeyRejectedLink, SankeyRibbonRow, SankeySummary, SankeyTextFormatters, SankeyTone, buildSankeyChartDescription, buildSankeyDescription, buildSankeyInsight, createSankeyFormatters, deriveSankeyHighlights, deriveSankeyState, layoutSankey, normalizeSankey, resolveSankeyLabels, sankeyInsightToText };
|