@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,435 @@
|
|
|
1
|
+
import { AXIS_LABEL_LIMIT_EXPR } from "../../lib/vega/axisTicks.js";
|
|
2
|
+
import { arcVegaConfig } from "../../lib/vega/config.js";
|
|
3
|
+
//#region src/components/MetricCard/MetricCard.chart.ts
|
|
4
|
+
/** The trend rows: `{ x, y }` per `MetricTrendRow` (plus `hl` and `tone` in the highlight variant). */
|
|
5
|
+
const METRIC_TREND_DATASET = "table";
|
|
6
|
+
/** Zero or one row `{ value }` — the target reference line. */
|
|
7
|
+
const METRIC_REFERENCE_DATASET = "reference";
|
|
8
|
+
/** Zero or one row — the latest valid reading, marked with a dot. */
|
|
9
|
+
const METRIC_LATEST_DATASET = "latest";
|
|
10
|
+
/** Highlight variant: the readings outside the window with a `seg` of `before` or `after` — the gray context runs. */
|
|
11
|
+
const METRIC_CONTEXT_DATASET = "context";
|
|
12
|
+
/** Highlight variant: the readings inside the window — the coloured segment. */
|
|
13
|
+
const METRIC_HIGHLIGHT_ROWS_DATASET = "highlightRows";
|
|
14
|
+
/** Highlight variant: the window's start and end readings — the two dots. */
|
|
15
|
+
const METRIC_HIGHLIGHT_POINTS_DATASET = "highlightPoints";
|
|
16
|
+
/** Highlight variant: one row `{ start, end, startY, endY, tone }` — the band behind a line and the axis anchors. */
|
|
17
|
+
const METRIC_HIGHLIGHT_DATASET = "highlight";
|
|
18
|
+
/** The nearest-point hover selection. */
|
|
19
|
+
const METRIC_HOVER_PARAM = "hover";
|
|
20
|
+
/** Responsive x tick values, recomputed by Vega when the domain or width changes. */
|
|
21
|
+
const METRIC_X_TICKS_PARAM = "metric_x_ticks";
|
|
22
|
+
/** Highlight variant: the window's snapped bounds, read from the `highlight` dataset — the x axis labels them. */
|
|
23
|
+
const METRIC_HIGHLIGHT_START_PARAM = "metric_hl_start";
|
|
24
|
+
const METRIC_HIGHLIGHT_END_PARAM = "metric_hl_end";
|
|
25
|
+
const POINT_SIZE = 64;
|
|
26
|
+
const BAR_WIDTH_EXPR = "min(24, bandwidth('x') * 0.7)";
|
|
27
|
+
const PLOT_PADDING = 6;
|
|
28
|
+
const BAND_OPACITY = .08;
|
|
29
|
+
const DISCRETE_DOMAIN_EXPR = `pluck(data('${METRIC_TREND_DATASET}'), 'x')`;
|
|
30
|
+
const Y_AXIS_TICKS = 3;
|
|
31
|
+
/**
|
|
32
|
+
* A mark colour that follows the window's polarity through the row's `tone`
|
|
33
|
+
* field — the diverging ends when the move means good or bad (lightness-matched,
|
|
34
|
+
* ≥ 3:1 on both surfaces), the emphasis hue when it is neutral — and
|
|
35
|
+
* `fallback` for rows outside the window (`tone: null`). Kept in the spec as
|
|
36
|
+
* three token values, so the spec stays structural while the data decides.
|
|
37
|
+
*/
|
|
38
|
+
function toneColor(tokens, fallback) {
|
|
39
|
+
return {
|
|
40
|
+
condition: [
|
|
41
|
+
{
|
|
42
|
+
test: "datum.tone === 'positive'",
|
|
43
|
+
value: tokens.divergingPositive
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
test: "datum.tone === 'negative'",
|
|
47
|
+
value: tokens.divergingNegative
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
test: "datum.tone === 'neutral'",
|
|
51
|
+
value: tokens.emphasis
|
|
52
|
+
}
|
|
53
|
+
],
|
|
54
|
+
value: fallback
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Builds the sparkline: a line (or an area with a crisp line on top, or bars),
|
|
59
|
+
* an optional hairline target rule that joins the y-domain, the latest reading
|
|
60
|
+
* as a dot, a nearest-point hover layer carrying the tooltip, and — when
|
|
61
|
+
* `axes` asks for them — quiet x and/or y axes labelled through the card's own
|
|
62
|
+
* formats. Lines may crop (`scale: "auto"`); areas and bars keep a zero
|
|
63
|
+
* baseline whatever `scale` says — proportional ink is not negotiable. Gaps
|
|
64
|
+
* stay gaps: Vega-Lite's default `invalid` handling breaks the path at a null
|
|
65
|
+
* reading.
|
|
66
|
+
*
|
|
67
|
+
* With `highlight`, the series recedes to the context gray and the window is
|
|
68
|
+
* the subject: a quiet band washes its extent, its readings draw in the
|
|
69
|
+
* polarity hue (bars inside it take the hue), its start and end are dotted,
|
|
70
|
+
* and the x axis labels the window's bounds (flanking the band) before the
|
|
71
|
+
* domain ends.
|
|
72
|
+
*/
|
|
73
|
+
function buildMetricTrendSpec(options, tokens) {
|
|
74
|
+
const { mark, scale, xType, axes = "x", height, reference, tooltip, highlight = false, xTitle, yTitle, valueFormat, timeFormat, axisTimeFormat } = options;
|
|
75
|
+
const zero = mark !== "line" || scale === "zero";
|
|
76
|
+
const showX = axes === "x" || axes === "both";
|
|
77
|
+
const showY = axes === "y" || axes === "both";
|
|
78
|
+
const discreteX = mark === "bar" || xType === "ordinal";
|
|
79
|
+
const xTickFormat = xType === "temporal" ? axisTimeFormat : "compact";
|
|
80
|
+
const xTickKind = xType === "temporal" ? "time" : xType === "quantitative" ? "number" : "text";
|
|
81
|
+
const axisArgs = `domain('x'), width, ${discreteX}, ${JSON.stringify(xTickFormat)}, ${JSON.stringify(xTickKind)}`;
|
|
82
|
+
const anchorsArg = highlight ? `, [${METRIC_HIGHLIGHT_START_PARAM}, ${METRIC_HIGHLIGHT_END_PARAM}]` : "";
|
|
83
|
+
const xAxisLabels = xType === "temporal" ? {
|
|
84
|
+
format: axisTimeFormat,
|
|
85
|
+
formatType: "arcTime"
|
|
86
|
+
} : xType === "quantitative" ? {
|
|
87
|
+
format: "compact",
|
|
88
|
+
formatType: "arcNumber"
|
|
89
|
+
} : {};
|
|
90
|
+
const xAxis = showX ? {
|
|
91
|
+
title: null,
|
|
92
|
+
orient: "bottom",
|
|
93
|
+
domain: true,
|
|
94
|
+
ticks: false,
|
|
95
|
+
grid: false,
|
|
96
|
+
values: { expr: METRIC_X_TICKS_PARAM },
|
|
97
|
+
labelAngle: 0,
|
|
98
|
+
labelAlign: { expr: highlight ? `arcAxisLabelAlign(datum.value, ${axisArgs}${anchorsArg})` : "scale('x', datum.value) === scale('x', domain('x')[0]) ? 'left' : scale('x', datum.value) === scale('x', peek(domain('x'))) ? 'right' : 'center'" },
|
|
99
|
+
labelFlush: false,
|
|
100
|
+
labelOverlap: false,
|
|
101
|
+
labelLimit: { expr: AXIS_LABEL_LIMIT_EXPR },
|
|
102
|
+
labelPadding: 4,
|
|
103
|
+
...xAxisLabels
|
|
104
|
+
} : null;
|
|
105
|
+
const yAxis = showY ? {
|
|
106
|
+
title: null,
|
|
107
|
+
orient: "left",
|
|
108
|
+
domain: false,
|
|
109
|
+
ticks: false,
|
|
110
|
+
grid: true,
|
|
111
|
+
tickCount: Y_AXIS_TICKS,
|
|
112
|
+
labelOverlap: true,
|
|
113
|
+
labelPadding: 6,
|
|
114
|
+
format: valueFormat,
|
|
115
|
+
formatType: "arcNumber"
|
|
116
|
+
} : null;
|
|
117
|
+
const discreteScale = highlight ? { scale: { domain: { expr: DISCRETE_DOMAIN_EXPR } } } : {};
|
|
118
|
+
const xField = mark === "bar" ? {
|
|
119
|
+
field: "x",
|
|
120
|
+
type: "ordinal",
|
|
121
|
+
sort: null,
|
|
122
|
+
axis: xAxis,
|
|
123
|
+
...discreteScale
|
|
124
|
+
} : {
|
|
125
|
+
field: "x",
|
|
126
|
+
type: xType,
|
|
127
|
+
axis: xAxis,
|
|
128
|
+
...xType === "ordinal" ? {
|
|
129
|
+
sort: null,
|
|
130
|
+
...discreteScale
|
|
131
|
+
} : { scale: {
|
|
132
|
+
nice: false,
|
|
133
|
+
...xType === "quantitative" ? { zero: false } : {}
|
|
134
|
+
} }
|
|
135
|
+
};
|
|
136
|
+
const yField = {
|
|
137
|
+
field: "y",
|
|
138
|
+
type: "quantitative",
|
|
139
|
+
axis: yAxis,
|
|
140
|
+
scale: {
|
|
141
|
+
zero,
|
|
142
|
+
nice: showY
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
const tooltipChannel = [xType === "temporal" ? {
|
|
146
|
+
field: "x",
|
|
147
|
+
type: "temporal",
|
|
148
|
+
title: xTitle,
|
|
149
|
+
format: timeFormat,
|
|
150
|
+
formatType: "arcTime"
|
|
151
|
+
} : xType === "quantitative" ? {
|
|
152
|
+
field: "x",
|
|
153
|
+
type: "quantitative",
|
|
154
|
+
title: xTitle,
|
|
155
|
+
format: "number",
|
|
156
|
+
formatType: "arcNumber"
|
|
157
|
+
} : {
|
|
158
|
+
field: "x",
|
|
159
|
+
type: "nominal",
|
|
160
|
+
title: xTitle
|
|
161
|
+
}, {
|
|
162
|
+
field: "y",
|
|
163
|
+
type: "quantitative",
|
|
164
|
+
title: yTitle,
|
|
165
|
+
format: valueFormat,
|
|
166
|
+
formatType: "arcNumber"
|
|
167
|
+
}];
|
|
168
|
+
const layers = [];
|
|
169
|
+
if (highlight) layers.push({
|
|
170
|
+
data: { name: METRIC_HIGHLIGHT_DATASET },
|
|
171
|
+
mark: {
|
|
172
|
+
type: "rect",
|
|
173
|
+
opacity: BAND_OPACITY,
|
|
174
|
+
aria: false
|
|
175
|
+
},
|
|
176
|
+
encoding: {
|
|
177
|
+
x: {
|
|
178
|
+
...xField,
|
|
179
|
+
field: "start",
|
|
180
|
+
...discreteX ? { bandPosition: 0 } : {}
|
|
181
|
+
},
|
|
182
|
+
x2: {
|
|
183
|
+
field: "end",
|
|
184
|
+
...discreteX ? { bandPosition: 1 } : {}
|
|
185
|
+
},
|
|
186
|
+
fill: toneColor(tokens, tokens.emphasis)
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
if (mark === "bar") layers.push({
|
|
190
|
+
...tooltip ? { params: [{
|
|
191
|
+
name: METRIC_HOVER_PARAM,
|
|
192
|
+
select: {
|
|
193
|
+
type: "point",
|
|
194
|
+
on: "pointerover",
|
|
195
|
+
clear: "pointerout",
|
|
196
|
+
encodings: ["x"]
|
|
197
|
+
}
|
|
198
|
+
}] } : {},
|
|
199
|
+
mark: {
|
|
200
|
+
type: "bar",
|
|
201
|
+
...highlight ? {} : { fill: tokens.emphasis },
|
|
202
|
+
cornerRadiusEnd: 2,
|
|
203
|
+
width: { expr: BAR_WIDTH_EXPR }
|
|
204
|
+
},
|
|
205
|
+
encoding: {
|
|
206
|
+
x: xField,
|
|
207
|
+
y: yField,
|
|
208
|
+
...highlight ? { fill: toneColor(tokens, tokens.context) } : {},
|
|
209
|
+
...tooltip ? {
|
|
210
|
+
opacity: {
|
|
211
|
+
condition: {
|
|
212
|
+
param: METRIC_HOVER_PARAM,
|
|
213
|
+
empty: false,
|
|
214
|
+
value: 1
|
|
215
|
+
},
|
|
216
|
+
value: .75
|
|
217
|
+
},
|
|
218
|
+
tooltip: tooltipChannel
|
|
219
|
+
} : {}
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
else if (highlight) {
|
|
223
|
+
const contextEncoding = {
|
|
224
|
+
x: xField,
|
|
225
|
+
y: yField,
|
|
226
|
+
detail: {
|
|
227
|
+
field: "seg",
|
|
228
|
+
type: "nominal"
|
|
229
|
+
}
|
|
230
|
+
};
|
|
231
|
+
if (mark === "area") layers.push({
|
|
232
|
+
data: { name: METRIC_CONTEXT_DATASET },
|
|
233
|
+
mark: {
|
|
234
|
+
type: "area",
|
|
235
|
+
fill: tokens.context,
|
|
236
|
+
fillOpacity: .12,
|
|
237
|
+
line: false,
|
|
238
|
+
interpolate: "linear"
|
|
239
|
+
},
|
|
240
|
+
encoding: contextEncoding
|
|
241
|
+
});
|
|
242
|
+
layers.push({
|
|
243
|
+
data: { name: METRIC_CONTEXT_DATASET },
|
|
244
|
+
mark: {
|
|
245
|
+
type: "line",
|
|
246
|
+
stroke: tokens.context,
|
|
247
|
+
strokeWidth: 2,
|
|
248
|
+
strokeCap: "round",
|
|
249
|
+
strokeJoin: "round",
|
|
250
|
+
interpolate: "linear"
|
|
251
|
+
},
|
|
252
|
+
encoding: contextEncoding
|
|
253
|
+
});
|
|
254
|
+
if (mark === "area") layers.push({
|
|
255
|
+
data: { name: METRIC_HIGHLIGHT_ROWS_DATASET },
|
|
256
|
+
mark: {
|
|
257
|
+
type: "area",
|
|
258
|
+
fillOpacity: .12,
|
|
259
|
+
line: false,
|
|
260
|
+
interpolate: "linear"
|
|
261
|
+
},
|
|
262
|
+
encoding: {
|
|
263
|
+
x: xField,
|
|
264
|
+
y: yField,
|
|
265
|
+
fill: toneColor(tokens, tokens.emphasis)
|
|
266
|
+
}
|
|
267
|
+
});
|
|
268
|
+
layers.push({
|
|
269
|
+
data: { name: METRIC_HIGHLIGHT_ROWS_DATASET },
|
|
270
|
+
mark: {
|
|
271
|
+
type: "line",
|
|
272
|
+
strokeWidth: 2,
|
|
273
|
+
strokeCap: "round",
|
|
274
|
+
strokeJoin: "round",
|
|
275
|
+
interpolate: "linear"
|
|
276
|
+
},
|
|
277
|
+
encoding: {
|
|
278
|
+
x: xField,
|
|
279
|
+
y: yField,
|
|
280
|
+
stroke: toneColor(tokens, tokens.emphasis)
|
|
281
|
+
}
|
|
282
|
+
});
|
|
283
|
+
} else {
|
|
284
|
+
if (mark === "area") layers.push({
|
|
285
|
+
mark: {
|
|
286
|
+
type: "area",
|
|
287
|
+
fill: tokens.emphasis,
|
|
288
|
+
fillOpacity: .12,
|
|
289
|
+
line: false,
|
|
290
|
+
interpolate: "linear"
|
|
291
|
+
},
|
|
292
|
+
encoding: {
|
|
293
|
+
x: xField,
|
|
294
|
+
y: yField
|
|
295
|
+
}
|
|
296
|
+
});
|
|
297
|
+
layers.push({
|
|
298
|
+
mark: {
|
|
299
|
+
type: "line",
|
|
300
|
+
stroke: tokens.emphasis,
|
|
301
|
+
strokeWidth: 2,
|
|
302
|
+
strokeCap: "round",
|
|
303
|
+
strokeJoin: "round",
|
|
304
|
+
interpolate: "linear"
|
|
305
|
+
},
|
|
306
|
+
encoding: {
|
|
307
|
+
x: xField,
|
|
308
|
+
y: yField
|
|
309
|
+
}
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
if (reference) layers.push({
|
|
313
|
+
data: { name: METRIC_REFERENCE_DATASET },
|
|
314
|
+
mark: {
|
|
315
|
+
type: "rule",
|
|
316
|
+
stroke: tokens.reference,
|
|
317
|
+
strokeWidth: 1.5,
|
|
318
|
+
strokeDash: [0, 4],
|
|
319
|
+
strokeCap: "round",
|
|
320
|
+
opacity: .9,
|
|
321
|
+
aria: false
|
|
322
|
+
},
|
|
323
|
+
encoding: {
|
|
324
|
+
y: {
|
|
325
|
+
...yField,
|
|
326
|
+
field: "value"
|
|
327
|
+
},
|
|
328
|
+
...tooltip ? { tooltip: [{
|
|
329
|
+
field: "value",
|
|
330
|
+
type: "quantitative",
|
|
331
|
+
title: options.targetTitle ?? "Target",
|
|
332
|
+
format: valueFormat,
|
|
333
|
+
formatType: "arcNumber"
|
|
334
|
+
}] } : {}
|
|
335
|
+
}
|
|
336
|
+
});
|
|
337
|
+
if (mark !== "bar") {
|
|
338
|
+
const dot = {
|
|
339
|
+
type: "point",
|
|
340
|
+
filled: true,
|
|
341
|
+
size: POINT_SIZE,
|
|
342
|
+
stroke: tokens.background,
|
|
343
|
+
strokeWidth: 1.5,
|
|
344
|
+
opacity: 1,
|
|
345
|
+
aria: false
|
|
346
|
+
};
|
|
347
|
+
if (highlight) layers.push({
|
|
348
|
+
data: { name: METRIC_HIGHLIGHT_POINTS_DATASET },
|
|
349
|
+
mark: dot,
|
|
350
|
+
encoding: {
|
|
351
|
+
x: xField,
|
|
352
|
+
y: yField,
|
|
353
|
+
fill: toneColor(tokens, tokens.emphasis)
|
|
354
|
+
}
|
|
355
|
+
});
|
|
356
|
+
else layers.push({
|
|
357
|
+
data: { name: METRIC_LATEST_DATASET },
|
|
358
|
+
mark: {
|
|
359
|
+
...dot,
|
|
360
|
+
fill: tokens.emphasis
|
|
361
|
+
},
|
|
362
|
+
encoding: {
|
|
363
|
+
x: xField,
|
|
364
|
+
y: yField
|
|
365
|
+
}
|
|
366
|
+
});
|
|
367
|
+
if (tooltip) layers.push({
|
|
368
|
+
params: [{
|
|
369
|
+
name: METRIC_HOVER_PARAM,
|
|
370
|
+
select: {
|
|
371
|
+
type: "point",
|
|
372
|
+
on: "pointermove",
|
|
373
|
+
nearest: true,
|
|
374
|
+
clear: "pointerout",
|
|
375
|
+
encodings: ["x"]
|
|
376
|
+
}
|
|
377
|
+
}],
|
|
378
|
+
mark: {
|
|
379
|
+
type: "point",
|
|
380
|
+
filled: true,
|
|
381
|
+
size: POINT_SIZE,
|
|
382
|
+
...highlight ? {} : { fill: tokens.emphasis },
|
|
383
|
+
stroke: tokens.background,
|
|
384
|
+
strokeWidth: 1.5,
|
|
385
|
+
aria: false
|
|
386
|
+
},
|
|
387
|
+
encoding: {
|
|
388
|
+
x: xField,
|
|
389
|
+
y: yField,
|
|
390
|
+
...highlight ? { fill: toneColor(tokens, tokens.context) } : {},
|
|
391
|
+
opacity: {
|
|
392
|
+
condition: {
|
|
393
|
+
param: METRIC_HOVER_PARAM,
|
|
394
|
+
empty: false,
|
|
395
|
+
value: 1
|
|
396
|
+
},
|
|
397
|
+
value: 0
|
|
398
|
+
},
|
|
399
|
+
tooltip: tooltipChannel
|
|
400
|
+
}
|
|
401
|
+
});
|
|
402
|
+
}
|
|
403
|
+
const params = [];
|
|
404
|
+
if (highlight) params.push({
|
|
405
|
+
name: METRIC_HIGHLIGHT_START_PARAM,
|
|
406
|
+
expr: `length(data('${METRIC_HIGHLIGHT_DATASET}')) ? data('${METRIC_HIGHLIGHT_DATASET}')[0].start : null`
|
|
407
|
+
}, {
|
|
408
|
+
name: METRIC_HIGHLIGHT_END_PARAM,
|
|
409
|
+
expr: `length(data('${METRIC_HIGHLIGHT_DATASET}')) ? data('${METRIC_HIGHLIGHT_DATASET}')[0].end : null`
|
|
410
|
+
});
|
|
411
|
+
if (showX) params.push({
|
|
412
|
+
name: METRIC_X_TICKS_PARAM,
|
|
413
|
+
expr: `arcAxisTicks(${axisArgs}${anchorsArg})`
|
|
414
|
+
});
|
|
415
|
+
return {
|
|
416
|
+
$schema: "https://vega.github.io/schema/vega-lite/v6.json",
|
|
417
|
+
width: 240,
|
|
418
|
+
height,
|
|
419
|
+
autosize: {
|
|
420
|
+
type: "fit",
|
|
421
|
+
contains: "padding"
|
|
422
|
+
},
|
|
423
|
+
padding: PLOT_PADDING,
|
|
424
|
+
background: "transparent",
|
|
425
|
+
data: { name: METRIC_TREND_DATASET },
|
|
426
|
+
...params.length > 0 ? { params } : {},
|
|
427
|
+
layer: layers,
|
|
428
|
+
config: arcVegaConfig(tokens, {
|
|
429
|
+
locale: options.locale,
|
|
430
|
+
timeZone: options.timeZone
|
|
431
|
+
})
|
|
432
|
+
};
|
|
433
|
+
}
|
|
434
|
+
//#endregion
|
|
435
|
+
export { METRIC_CONTEXT_DATASET, METRIC_HIGHLIGHT_DATASET, METRIC_HIGHLIGHT_END_PARAM, METRIC_HIGHLIGHT_POINTS_DATASET, METRIC_HIGHLIGHT_ROWS_DATASET, METRIC_HIGHLIGHT_START_PARAM, METRIC_HOVER_PARAM, METRIC_LATEST_DATASET, METRIC_REFERENCE_DATASET, METRIC_TREND_DATASET, METRIC_X_TICKS_PARAM, buildMetricTrendSpec };
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import { ArcTimeGranularity } from "../../lib/vega/formatters.js";
|
|
2
|
+
import { MetricCardLabels, MetricCardSize, MetricCardStatus, MetricCardVariant, MetricComparison, MetricDeltaMode, MetricGoodDirection, MetricHighlightRange, MetricTrendAxes, MetricTrendMark, MetricTrendPoint, MetricTrendScale } from "./MetricCard.model.js";
|
|
3
|
+
import { ReactNode } from "react";
|
|
4
|
+
import { BoxProps } from "@arcfusionz/arc-primitive-ui";
|
|
5
|
+
import { TopLevelSpec } from "vega-lite";
|
|
6
|
+
import { Result } from "vega-embed";
|
|
7
|
+
//#region src/components/MetricCard/MetricCard.d.ts
|
|
8
|
+
interface MetricCardBaseProps extends Omit<BoxProps, "children" | "padding" | "title"> {
|
|
9
|
+
/**
|
|
10
|
+
* `default` (the metric tile) or `highlight` — a card about one window of
|
|
11
|
+
* the trend. A highlight card requires `highlight` and `trend` and derives
|
|
12
|
+
* its headline from them: the value is the reading at the window's end, the
|
|
13
|
+
* badge is the change across the window, the comparison line is the window's
|
|
14
|
+
* label or period. `value`, `previousValue` and `comparisonLabel` are not
|
|
15
|
+
* accepted with it. The sparkline paints the window in the polarity hue on a
|
|
16
|
+
* gray context, dots its start and end, washes a band behind it and labels
|
|
17
|
+
* its bounds on the x axis; hovering inside it adds the window's start, end
|
|
18
|
+
* and change to the tooltip. Default `default`. Stamped as `data-variant`.
|
|
19
|
+
*/
|
|
20
|
+
variant?: MetricCardVariant;
|
|
21
|
+
/**
|
|
22
|
+
* The window a `highlight` card is about: `{ start, end, label? }` in the
|
|
23
|
+
* trend's own `x` type (Dates or ISO strings, numbers, or category labels).
|
|
24
|
+
* Each bound snaps inward to the nearest finite reading. A window without
|
|
25
|
+
* two distinct readings is unresolved — plain sparkline, no badge,
|
|
26
|
+
* `data-highlight="unresolved"`. Pass stable values (ISO strings or memoized
|
|
27
|
+
* Dates): the window is re-resolved when they change.
|
|
28
|
+
*/
|
|
29
|
+
highlight?: MetricHighlightRange;
|
|
30
|
+
/**
|
|
31
|
+
* `highlight` variant: clicking the delta stack opens a popover detailing
|
|
32
|
+
* the window — its start and end readings, the change in both forms, every
|
|
33
|
+
* reading inside it with its step from the previous one, and how the trend
|
|
34
|
+
* moved before the window and since it. Default `true`; `false` keeps the
|
|
35
|
+
* hover tooltip, for a static tile.
|
|
36
|
+
*/
|
|
37
|
+
highlightDetails?: boolean;
|
|
38
|
+
/** Open the highlight details popover on first render. */
|
|
39
|
+
defaultHighlightDetailsOpen?: boolean;
|
|
40
|
+
/** The metric's name — the tile's heading. Pass `name` too when this is not plain text. */
|
|
41
|
+
label: ReactNode;
|
|
42
|
+
/** Plain-text name used in the generated descriptions and control labels. Defaults to `label` when it is a string. */
|
|
43
|
+
name?: string;
|
|
44
|
+
/** Definition of the metric, shown in a tooltip behind an info control beside the label and exposed to assistive technology as the control's description. */
|
|
45
|
+
hint?: string;
|
|
46
|
+
/** The headline reading. `null`/`undefined` renders the empty (or no-match) state. Not accepted by the `highlight` variant, which reads the window's end value from `trend`. */
|
|
47
|
+
value?: number | null;
|
|
48
|
+
/**
|
|
49
|
+
* Number format for the value, delta, target, table and tooltip — one
|
|
50
|
+
* grammar so nothing rounds two ways: `number[:digits]`, `integer`,
|
|
51
|
+
* `compact[:digits]`, `percent[:digits]`, `currency:CODE[:digits|compact]`.
|
|
52
|
+
* Default `compact` (`3.8M`); pass `percent` for ratio metrics.
|
|
53
|
+
*/
|
|
54
|
+
format?: string;
|
|
55
|
+
/** Custom formatter for values. Takes precedence over `format` everywhere a value is rendered. */
|
|
56
|
+
formatValue?: (value: number) => string;
|
|
57
|
+
/** Unit shown after the value in the muted role (`ms`, `req/s`). Prefer `format="currency:…"` for money. */
|
|
58
|
+
unit?: ReactNode;
|
|
59
|
+
/** The reading one period ago. Renders the delta above its label to the right of the value; pass `null` while unknown to reserve the stack's height. Not accepted by the `highlight` variant, whose delta is the change across the window. */
|
|
60
|
+
previousValue?: number | null;
|
|
61
|
+
/** What the delta is against — `vs last month`. Default: `labels.previousPeriod`. Not accepted by the `highlight` variant, which shows `highlight.label` or the window's period, nor with `comparisons`, whose selected baseline names the line. */
|
|
62
|
+
comparisonLabel?: ReactNode;
|
|
63
|
+
/**
|
|
64
|
+
* The baselines the headline can be compared with — yesterday, last week,
|
|
65
|
+
* last month, last year — as `{ key?, label, value }` records in the order
|
|
66
|
+
* they should be offered. The selected one supplies the delta and the
|
|
67
|
+
* comparison line (`vs last month`, through `labels.versus`), and the delta
|
|
68
|
+
* stack becomes a compare-with menu listing every baseline with its reading
|
|
69
|
+
* and the change the headline would show against it. Replaces
|
|
70
|
+
* `previousValue` and `comparisonLabel`; a baseline with `value: null` is
|
|
71
|
+
* listed but cannot be chosen. Pass `[]` while loading to reserve the
|
|
72
|
+
* stack's height. Not accepted by the `highlight` variant.
|
|
73
|
+
*/
|
|
74
|
+
comparisons?: readonly MetricComparison[];
|
|
75
|
+
/**
|
|
76
|
+
* Key of the selected baseline, controlled. Pair with `onComparisonChange`
|
|
77
|
+
* to follow the reader's pick; omit it for the uncontrolled card
|
|
78
|
+
* (`defaultComparison`, else the first baseline with a value). `null`
|
|
79
|
+
* selects none — no delta, and the line invites a choice. A controlled key
|
|
80
|
+
* without its change handler is pinned: the stack renders no menu.
|
|
81
|
+
*/
|
|
82
|
+
comparison?: string | null;
|
|
83
|
+
/** The selected baseline on first render when `comparison` is uncontrolled. Default: the first baseline with a value. */
|
|
84
|
+
defaultComparison?: string;
|
|
85
|
+
/** Called with the chosen baseline's key when the reader picks another one from the compare-with menu. */
|
|
86
|
+
onComparisonChange?: (key: string) => void;
|
|
87
|
+
/**
|
|
88
|
+
* The delta stack is a menu button: click, Enter, Space or an arrow key
|
|
89
|
+
* opens the compare-with menu listing every baseline — the `comparisons`,
|
|
90
|
+
* or the one `previousValue` as a single row — with its reading and the
|
|
91
|
+
* change against it in both forms. Default `true`; `false` for a static
|
|
92
|
+
* tile, where the stack is a focusable group with the hover tooltip.
|
|
93
|
+
* Stamped as `data-selectable` while the menu exists. Not accepted by the
|
|
94
|
+
* `highlight` variant, whose switch is `highlightDetails`.
|
|
95
|
+
*/
|
|
96
|
+
selectable?: boolean;
|
|
97
|
+
/** `percent` (default) is relative change; `absolute` is the difference in the value's units — percentage points for a `percent` format. */
|
|
98
|
+
deltaMode?: MetricDeltaMode;
|
|
99
|
+
/**
|
|
100
|
+
* Which direction is good. Drives the delta's polarity color and the
|
|
101
|
+
* target meter's status: `up` (revenue), `down` (churn, latency, cost) or
|
|
102
|
+
* `none` (headcount — the delta stays neutral). Default `up`.
|
|
103
|
+
*/
|
|
104
|
+
goodDirection?: MetricGoodDirection;
|
|
105
|
+
/** The goal. Renders a `Meter` of progress and the variance against it; pass `null` while unknown to reserve the block's height. */
|
|
106
|
+
target?: number | null;
|
|
107
|
+
/**
|
|
108
|
+
* Recent readings as `{ x, y }` points: `x` a `Date`, ISO string, number or
|
|
109
|
+
* category label; `y` the value or `null` for a gap. Two or more finite
|
|
110
|
+
* readings draw the sparkline; fewer show the insufficient-data caption in
|
|
111
|
+
* the same space. Pass `[]` while loading to reserve the sparkline's height.
|
|
112
|
+
* Required by the `highlight` variant.
|
|
113
|
+
*/
|
|
114
|
+
trend?: readonly MetricTrendPoint[];
|
|
115
|
+
/** `line` (default, may crop to the data range), `area` (zero baseline, filled to it) or `bar` (zero baseline, for a few periods). */
|
|
116
|
+
trendMark?: MetricTrendMark;
|
|
117
|
+
/** Y-scale baseline for a `line` sparkline: `auto` (default) fits the data range and reads for shape; `zero` includes zero. Areas and bars always start at zero. */
|
|
118
|
+
trendScale?: MetricTrendScale;
|
|
119
|
+
/**
|
|
120
|
+
* Which axes the sparkline draws: `x` (default — period labels under the plot,
|
|
121
|
+
* always including the first and last values), `none` (no axes), `y` (value labels with hairline grid
|
|
122
|
+
* lines, ticks rounded to readable numbers) or `both`. Labels use the card's
|
|
123
|
+
* `format`, `locale` and `timeZone`. Interior x labels adapt to the plot width;
|
|
124
|
+
* a `highlight` card labels the window's bounds instead.
|
|
125
|
+
* An x axis adds 24px to the default
|
|
126
|
+
* `trendHeight` so the plot keeps its size.
|
|
127
|
+
*/
|
|
128
|
+
trendAxes?: MetricTrendAxes;
|
|
129
|
+
/** Sparkline height in pixels, axes included. Defaults per `size` (32 / 40 / 56), plus 24 when `trendAxes` shows the x axis. */
|
|
130
|
+
trendHeight?: number;
|
|
131
|
+
/** Period granularity of temporal `x` values for tooltips and the table. Inferred from the spacing when omitted. */
|
|
132
|
+
trendGranularity?: ArcTimeGranularity;
|
|
133
|
+
/**
|
|
134
|
+
* The takeaway in a sentence, rendered beside the AI mark under the chart —
|
|
135
|
+
* the insight slot. Wrap values in `<strong>` to set them in bold. A
|
|
136
|
+
* `highlight` card with no `insight` generates one from the window, with the
|
|
137
|
+
* start and end readings and the change in bold; pass `null` or `false` to
|
|
138
|
+
* render no insight.
|
|
139
|
+
*/
|
|
140
|
+
insight?: ReactNode;
|
|
141
|
+
/** The transport's status. `loading` with data already present is a refresh: the previous render stays under the veil. Default `ready`. */
|
|
142
|
+
status?: MetricCardStatus;
|
|
143
|
+
/** The consumer's filter is active — a missing value then reads as no-match rather than empty, with a clear-filters action when `onClearFilters` is set. */
|
|
144
|
+
filtered?: boolean;
|
|
145
|
+
/** The data is older than the product's freshness rule (TanStack Query's `isStale`). Shows a badge and stamps `data-stale`. */
|
|
146
|
+
stale?: boolean;
|
|
147
|
+
/** When the data was last true. Rendered as an "as of" line (the date by default — see `updatedAtFormat`) and included in the description. */
|
|
148
|
+
updatedAt?: Date | string | number;
|
|
149
|
+
/**
|
|
150
|
+
* How `updatedAt` is written, as a time-grammar granularity — `day`
|
|
151
|
+
* (default, `Sep 8, 2026`), `datetime` (`Sep 8, 2026, 04:30 PM`), `time`
|
|
152
|
+
* (`04:30 PM`), `month` (`Sep 2026`), `year` — or a formatter for a custom
|
|
153
|
+
* form. Applies to the as-of line and the description alike, in the card's
|
|
154
|
+
* `locale` and `timeZone`.
|
|
155
|
+
*/
|
|
156
|
+
updatedAtFormat?: ArcTimeGranularity | ((date: Date) => string);
|
|
157
|
+
/** Recovery action for the error state; renders a retry button when set. */
|
|
158
|
+
onRetry?: () => void;
|
|
159
|
+
/** Recovery action for the no-match state; renders a clear-filters button when set. */
|
|
160
|
+
onClearFilters?: () => void;
|
|
161
|
+
/** Density: `sm` for dense grids, `md` (default), `lg` for a hero metric. Scales type, padding and the default sparkline height. */
|
|
162
|
+
size?: MetricCardSize;
|
|
163
|
+
/** Heading level of the label for the document outline. Default 3 — tiles usually sit under a page's h2. */
|
|
164
|
+
titleLevel?: 2 | 3 | 4 | 5 | 6;
|
|
165
|
+
/** BCP 47 locale for every number and date. Defaults to the runtime's. Thai products on the Gregorian calendar pass `th-TH-u-ca-gregory`. */
|
|
166
|
+
locale?: string;
|
|
167
|
+
/** IANA time zone for dates. Defaults to the runtime's — pass it for deterministic output and single-business-zone reporting. */
|
|
168
|
+
timeZone?: string;
|
|
169
|
+
/** Overrides for every rendered or announced string. */
|
|
170
|
+
labels?: Partial<MetricCardLabels>;
|
|
171
|
+
/** Replaces the generated accessible description of the whole card (the figure's `aria-describedby` text). */
|
|
172
|
+
description?: string;
|
|
173
|
+
/** Trailing header slot — a ghost `Button` or `Menu` for drill-through, export, or settings. */
|
|
174
|
+
action?: ReactNode;
|
|
175
|
+
/** Open the data popover on first render, anchored to the card. */
|
|
176
|
+
defaultTableOpen?: boolean;
|
|
177
|
+
/** Hide the header info button for the data popover. Only when another surface exposes the same values to keyboard and screen-reader users. */
|
|
178
|
+
hideTableToggle?: boolean;
|
|
179
|
+
/** Called with vega-embed's result once the sparkline mounts — for `view` access in advanced compositions. */
|
|
180
|
+
onEmbed?: (result: Result) => void;
|
|
181
|
+
/** Escape hatch: transform the sparkline spec before it renders. Voids the token and accessibility guarantees for whatever it changes. */
|
|
182
|
+
patchSpec?: (spec: TopLevelSpec) => TopLevelSpec;
|
|
183
|
+
}
|
|
184
|
+
type MetricCardComparisonProps = {
|
|
185
|
+
comparisons?: never;
|
|
186
|
+
comparison?: never;
|
|
187
|
+
defaultComparison?: never;
|
|
188
|
+
onComparisonChange?: never;
|
|
189
|
+
} | {
|
|
190
|
+
comparisons: readonly MetricComparison[];
|
|
191
|
+
comparison?: string | null;
|
|
192
|
+
defaultComparison?: string;
|
|
193
|
+
onComparisonChange?: (key: string) => void;
|
|
194
|
+
previousValue?: never;
|
|
195
|
+
comparisonLabel?: never;
|
|
196
|
+
};
|
|
197
|
+
type MetricCardVariantProps = ({
|
|
198
|
+
variant?: "default";
|
|
199
|
+
highlight?: never;
|
|
200
|
+
highlightDetails?: never;
|
|
201
|
+
defaultHighlightDetailsOpen?: never;
|
|
202
|
+
} & MetricCardComparisonProps) | {
|
|
203
|
+
variant: "highlight";
|
|
204
|
+
highlight: MetricHighlightRange;
|
|
205
|
+
trend: readonly MetricTrendPoint[];
|
|
206
|
+
value?: never;
|
|
207
|
+
previousValue?: never;
|
|
208
|
+
comparisonLabel?: never;
|
|
209
|
+
comparisons?: never;
|
|
210
|
+
comparison?: never;
|
|
211
|
+
defaultComparison?: never;
|
|
212
|
+
onComparisonChange?: never;
|
|
213
|
+
selectable?: never;
|
|
214
|
+
};
|
|
215
|
+
type MetricCardProps = MetricCardBaseProps & MetricCardVariantProps;
|
|
216
|
+
/**
|
|
217
|
+
* A metric tile for dashboard grids: the headline value, its comparison
|
|
218
|
+
* against the previous period and/or a target, a sparkline of the recent
|
|
219
|
+
* readings, and every loading, empty, error and stale state — layout-stable,
|
|
220
|
+
* with a generated text equivalent and a data table in an info popover. The
|
|
221
|
+
* `highlight` variant makes one window of the trend the subject: the headline
|
|
222
|
+
* and delta derive from the window's readings and the sparkline paints it in
|
|
223
|
+
* the polarity hue on a gray context.
|
|
224
|
+
*/
|
|
225
|
+
declare const MetricCard: import("react").ForwardRefExoticComponent<MetricCardProps & import("react").RefAttributes<HTMLElement>>;
|
|
226
|
+
//#endregion
|
|
227
|
+
export { MetricCard, MetricCardBaseProps, MetricCardComparisonProps, MetricCardProps, MetricCardVariantProps };
|