@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,13 @@
|
|
|
1
|
+
//#region \0rolldown/runtime.js
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __exportAll = (all, no_symbols) => {
|
|
4
|
+
let target = {};
|
|
5
|
+
for (var name in all) __defProp(target, name, {
|
|
6
|
+
get: all[name],
|
|
7
|
+
enumerable: true
|
|
8
|
+
});
|
|
9
|
+
if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
10
|
+
return target;
|
|
11
|
+
};
|
|
12
|
+
//#endregion
|
|
13
|
+
export { __exportAll };
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { ChartTokens } from "../../lib/vega/tokens.js";
|
|
2
|
+
import { AnomalyMark, AnomalyScale, AnomalyXType } from "./AnomalyCard.model.js";
|
|
3
|
+
import { TopLevelSpec } from "vega-lite";
|
|
4
|
+
//#region src/components/AnomalyCard/AnomalyCard.chart.d.ts
|
|
5
|
+
/** Every period `{ x, y, lo, hi, ex, d, a, dir, c, sh, e, sc }` per `AnomalyRow`. */
|
|
6
|
+
declare const ANOMALY_TABLE_DATASET = "table";
|
|
7
|
+
/** One row per period, `{ x }` — the crosshair, revealed by the hover selection. */
|
|
8
|
+
declare const ANOMALY_PERIODS_DATASET = "periods";
|
|
9
|
+
/** Zero or one row `{ start, end }` — the selected excursion's wash. */
|
|
10
|
+
declare const ANOMALY_SPAN_DATASET = "span";
|
|
11
|
+
/** The shared-x hover selection: projected onto `x`, so pointing anywhere in a column reads that period. */
|
|
12
|
+
declare const ANOMALY_HOVER_PARAM = "hover";
|
|
13
|
+
/** Responsive x tick values, recomputed by Vega when the domain or the width changes. */
|
|
14
|
+
declare const ANOMALY_X_TICKS_PARAM = "anomaly_x_ticks";
|
|
15
|
+
interface AnomalyPlotSpecOptions {
|
|
16
|
+
/** `line` reads shape; `area` fills from zero. */
|
|
17
|
+
mark: AnomalyMark;
|
|
18
|
+
/** `auto` lets a line crop to its data range; `zero` includes zero. An area always includes zero. */
|
|
19
|
+
scale: AnomalyScale;
|
|
20
|
+
xType: AnomalyXType;
|
|
21
|
+
/** Plot height in pixels, axes included. */
|
|
22
|
+
height: number;
|
|
23
|
+
/** Draw both axes. `false` shrinks the plot toward a sparkline; the table still carries every value. */
|
|
24
|
+
axes: boolean;
|
|
25
|
+
/** Number of y ticks — the caller scales it to the plot's height. */
|
|
26
|
+
yTicks: number;
|
|
27
|
+
/** Draw the expected range as a band. */
|
|
28
|
+
band: boolean;
|
|
29
|
+
/** Draw the model's expected value as a dashed hairline inside the band. */
|
|
30
|
+
expected: boolean;
|
|
31
|
+
/** Wash the selected excursion's span (the `span` dataset carries it). */
|
|
32
|
+
span: boolean;
|
|
33
|
+
/** Wire the shared-x hover selection, the crosshair and the tooltip channel. */
|
|
34
|
+
tooltip: boolean;
|
|
35
|
+
/** Tooltip titles. */
|
|
36
|
+
xTitle: string;
|
|
37
|
+
yTitle: string;
|
|
38
|
+
/** `arcNumber` grammar for the y axis and the tooltip. */
|
|
39
|
+
plotFormat: string;
|
|
40
|
+
/** `arcTime` grammar for temporal x in tooltips (`day@en-US@Asia/Bangkok`). */
|
|
41
|
+
timeFormat: string;
|
|
42
|
+
/** `arcTime` grammar for x-axis tick labels — the axis-length form (`day-short@en-US@Asia/Bangkok`). */
|
|
43
|
+
axisTimeFormat: string;
|
|
44
|
+
locale?: string;
|
|
45
|
+
timeZone?: string;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Builds the plot: the readings as a line or an area, the expected range as a
|
|
49
|
+
* quiet band behind them, the model's expectation as a dashed hairline, and
|
|
50
|
+
* every reading that broke out marked with a direction-shaped, polarity-hued
|
|
51
|
+
* flag — so the deviation is DIRECTLY visible as a mark outside a region
|
|
52
|
+
* rather than as two numbers to subtract.
|
|
53
|
+
*
|
|
54
|
+
* Gaps stay gaps — a `null` reading breaks the path rather than dropping it to
|
|
55
|
+
* zero, and a period with no bounds leaves a hole in the band rather than
|
|
56
|
+
* pretending the range continued. A line may crop (`scale: "auto"`); an area
|
|
57
|
+
* keeps a zero baseline whatever `scale` says, because proportional ink is not
|
|
58
|
+
* negotiable. Either way the extent the caller passes spans the band as well
|
|
59
|
+
* as the readings, so a cropped scale can never hide the range being judged
|
|
60
|
+
* against.
|
|
61
|
+
*/
|
|
62
|
+
declare function buildAnomalyPlotSpec(options: AnomalyPlotSpecOptions, tokens: ChartTokens): TopLevelSpec;
|
|
63
|
+
//#endregion
|
|
64
|
+
export { ANOMALY_HOVER_PARAM, ANOMALY_PERIODS_DATASET, ANOMALY_SPAN_DATASET, ANOMALY_TABLE_DATASET, ANOMALY_X_TICKS_PARAM, AnomalyPlotSpecOptions, buildAnomalyPlotSpec };
|
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
import { AXIS_LABEL_LIMIT_EXPR } from "../../lib/vega/axisTicks.js";
|
|
2
|
+
import { arcVegaConfig } from "../../lib/vega/config.js";
|
|
3
|
+
//#region src/components/AnomalyCard/AnomalyCard.chart.ts
|
|
4
|
+
/** Every period `{ x, y, lo, hi, ex, d, a, dir, c, sh, e, sc }` per `AnomalyRow`. */
|
|
5
|
+
const ANOMALY_TABLE_DATASET = "table";
|
|
6
|
+
/** One row per period, `{ x }` — the crosshair, revealed by the hover selection. */
|
|
7
|
+
const ANOMALY_PERIODS_DATASET = "periods";
|
|
8
|
+
/** Zero or one row `{ start, end }` — the selected excursion's wash. */
|
|
9
|
+
const ANOMALY_SPAN_DATASET = "span";
|
|
10
|
+
/** The shared-x hover selection: projected onto `x`, so pointing anywhere in a column reads that period. */
|
|
11
|
+
const ANOMALY_HOVER_PARAM = "hover";
|
|
12
|
+
/** Responsive x tick values, recomputed by Vega when the domain or the width changes. */
|
|
13
|
+
const ANOMALY_X_TICKS_PARAM = "anomaly_x_ticks";
|
|
14
|
+
const POINT_SIZE = 64;
|
|
15
|
+
const FLAG_SIZE = 120;
|
|
16
|
+
const PLOT_PADDING = 8;
|
|
17
|
+
const BAND_OPACITY = .22;
|
|
18
|
+
const EXPECTED_DASH = [4, 3];
|
|
19
|
+
const EXPECTED_OPACITY = .9;
|
|
20
|
+
const SPAN_OPACITY = .5;
|
|
21
|
+
const DISCRETE_DOMAIN_EXPR = `pluck(data('${ANOMALY_PERIODS_DATASET}'), 'x')`;
|
|
22
|
+
/**
|
|
23
|
+
* Builds the plot: the readings as a line or an area, the expected range as a
|
|
24
|
+
* quiet band behind them, the model's expectation as a dashed hairline, and
|
|
25
|
+
* every reading that broke out marked with a direction-shaped, polarity-hued
|
|
26
|
+
* flag — so the deviation is DIRECTLY visible as a mark outside a region
|
|
27
|
+
* rather than as two numbers to subtract.
|
|
28
|
+
*
|
|
29
|
+
* Gaps stay gaps — a `null` reading breaks the path rather than dropping it to
|
|
30
|
+
* zero, and a period with no bounds leaves a hole in the band rather than
|
|
31
|
+
* pretending the range continued. A line may crop (`scale: "auto"`); an area
|
|
32
|
+
* keeps a zero baseline whatever `scale` says, because proportional ink is not
|
|
33
|
+
* negotiable. Either way the extent the caller passes spans the band as well
|
|
34
|
+
* as the readings, so a cropped scale can never hide the range being judged
|
|
35
|
+
* against.
|
|
36
|
+
*/
|
|
37
|
+
function buildAnomalyPlotSpec(options, tokens) {
|
|
38
|
+
const { mark, scale, xType, height, axes, yTicks, band, expected, span, tooltip, xTitle, yTitle, plotFormat, timeFormat, axisTimeFormat } = options;
|
|
39
|
+
const zero = mark !== "line" || scale === "zero";
|
|
40
|
+
const discreteX = xType === "ordinal";
|
|
41
|
+
const xTickFormat = xType === "temporal" ? axisTimeFormat : "compact";
|
|
42
|
+
const xTickKind = xType === "temporal" ? "time" : xType === "quantitative" ? "number" : "text";
|
|
43
|
+
const axisArgs = `domain('x'), width, ${discreteX}, ${JSON.stringify(xTickFormat)}, ${JSON.stringify(xTickKind)}`;
|
|
44
|
+
const xAxisLabels = xType === "temporal" ? {
|
|
45
|
+
format: axisTimeFormat,
|
|
46
|
+
formatType: "arcTime"
|
|
47
|
+
} : xType === "quantitative" ? {
|
|
48
|
+
format: "compact",
|
|
49
|
+
formatType: "arcNumber"
|
|
50
|
+
} : {};
|
|
51
|
+
const xAxis = axes ? {
|
|
52
|
+
title: null,
|
|
53
|
+
orient: "bottom",
|
|
54
|
+
domain: true,
|
|
55
|
+
ticks: false,
|
|
56
|
+
grid: false,
|
|
57
|
+
values: { expr: ANOMALY_X_TICKS_PARAM },
|
|
58
|
+
labelAngle: 0,
|
|
59
|
+
labelAlign: { expr: `arcAxisLabelAlign(datum.value, ${axisArgs})` },
|
|
60
|
+
labelFlush: false,
|
|
61
|
+
labelOverlap: false,
|
|
62
|
+
labelLimit: { expr: AXIS_LABEL_LIMIT_EXPR },
|
|
63
|
+
labelPadding: 4,
|
|
64
|
+
...xAxisLabels
|
|
65
|
+
} : null;
|
|
66
|
+
const yAxis = axes ? {
|
|
67
|
+
title: null,
|
|
68
|
+
orient: "left",
|
|
69
|
+
domain: false,
|
|
70
|
+
ticks: false,
|
|
71
|
+
grid: true,
|
|
72
|
+
tickCount: yTicks,
|
|
73
|
+
labelOverlap: true,
|
|
74
|
+
labelPadding: 6,
|
|
75
|
+
format: plotFormat,
|
|
76
|
+
formatType: "arcNumber"
|
|
77
|
+
} : null;
|
|
78
|
+
const xField = discreteX ? {
|
|
79
|
+
field: "x",
|
|
80
|
+
type: "ordinal",
|
|
81
|
+
sort: null,
|
|
82
|
+
axis: xAxis,
|
|
83
|
+
...discreteX ? { scale: {
|
|
84
|
+
domain: { expr: DISCRETE_DOMAIN_EXPR },
|
|
85
|
+
paddingOuter: .05
|
|
86
|
+
} } : {}
|
|
87
|
+
} : {
|
|
88
|
+
field: "x",
|
|
89
|
+
type: xType,
|
|
90
|
+
axis: xAxis,
|
|
91
|
+
scale: {
|
|
92
|
+
nice: false,
|
|
93
|
+
...xType === "quantitative" ? { zero: false } : {}
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
const yField = {
|
|
97
|
+
field: "y",
|
|
98
|
+
type: "quantitative",
|
|
99
|
+
axis: yAxis,
|
|
100
|
+
scale: {
|
|
101
|
+
zero,
|
|
102
|
+
nice: axes
|
|
103
|
+
},
|
|
104
|
+
stack: null
|
|
105
|
+
};
|
|
106
|
+
const tooltipChannel = [xType === "temporal" ? {
|
|
107
|
+
field: "x",
|
|
108
|
+
type: "temporal",
|
|
109
|
+
title: xTitle,
|
|
110
|
+
format: timeFormat,
|
|
111
|
+
formatType: "arcTime"
|
|
112
|
+
} : xType === "quantitative" ? {
|
|
113
|
+
field: "x",
|
|
114
|
+
type: "quantitative",
|
|
115
|
+
title: xTitle,
|
|
116
|
+
format: "number",
|
|
117
|
+
formatType: "arcNumber"
|
|
118
|
+
} : {
|
|
119
|
+
field: "x",
|
|
120
|
+
type: "nominal",
|
|
121
|
+
title: xTitle
|
|
122
|
+
}, {
|
|
123
|
+
field: "y",
|
|
124
|
+
type: "quantitative",
|
|
125
|
+
title: yTitle,
|
|
126
|
+
format: plotFormat,
|
|
127
|
+
formatType: "arcNumber"
|
|
128
|
+
}];
|
|
129
|
+
const layers = [];
|
|
130
|
+
if (span) layers.push({
|
|
131
|
+
data: { name: ANOMALY_SPAN_DATASET },
|
|
132
|
+
mark: {
|
|
133
|
+
type: "rect",
|
|
134
|
+
fill: tokens.brush,
|
|
135
|
+
aria: false
|
|
136
|
+
},
|
|
137
|
+
encoding: {
|
|
138
|
+
x: {
|
|
139
|
+
...xField,
|
|
140
|
+
field: "start",
|
|
141
|
+
axis: xAxis,
|
|
142
|
+
...discreteX ? { bandPosition: 0 } : {}
|
|
143
|
+
},
|
|
144
|
+
x2: {
|
|
145
|
+
field: "end",
|
|
146
|
+
...discreteX ? { bandPosition: 1 } : {}
|
|
147
|
+
},
|
|
148
|
+
opacity: {
|
|
149
|
+
condition: {
|
|
150
|
+
test: "datum.on",
|
|
151
|
+
value: SPAN_OPACITY
|
|
152
|
+
},
|
|
153
|
+
value: 0
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
if (band) layers.push({
|
|
158
|
+
mark: {
|
|
159
|
+
type: "area",
|
|
160
|
+
line: false,
|
|
161
|
+
interpolate: "linear",
|
|
162
|
+
fill: tokens.context,
|
|
163
|
+
fillOpacity: BAND_OPACITY,
|
|
164
|
+
invalid: "break-paths-show-domains",
|
|
165
|
+
aria: false
|
|
166
|
+
},
|
|
167
|
+
encoding: {
|
|
168
|
+
x: xField,
|
|
169
|
+
y: {
|
|
170
|
+
...yField,
|
|
171
|
+
field: "lo"
|
|
172
|
+
},
|
|
173
|
+
y2: { field: "hi" }
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
if (expected) layers.push({
|
|
177
|
+
mark: {
|
|
178
|
+
type: "line",
|
|
179
|
+
interpolate: "linear",
|
|
180
|
+
stroke: tokens.context,
|
|
181
|
+
strokeWidth: 1,
|
|
182
|
+
strokeDash: EXPECTED_DASH,
|
|
183
|
+
opacity: EXPECTED_OPACITY,
|
|
184
|
+
invalid: "break-paths-show-domains",
|
|
185
|
+
aria: false
|
|
186
|
+
},
|
|
187
|
+
encoding: {
|
|
188
|
+
x: xField,
|
|
189
|
+
y: {
|
|
190
|
+
...yField,
|
|
191
|
+
field: "ex"
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
if (mark === "area") layers.push({
|
|
196
|
+
mark: {
|
|
197
|
+
type: "area",
|
|
198
|
+
line: false,
|
|
199
|
+
interpolate: "linear",
|
|
200
|
+
fill: tokens.emphasis,
|
|
201
|
+
fillOpacity: .12,
|
|
202
|
+
invalid: "break-paths-show-domains",
|
|
203
|
+
aria: false
|
|
204
|
+
},
|
|
205
|
+
encoding: {
|
|
206
|
+
x: xField,
|
|
207
|
+
y: yField
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
layers.push({
|
|
211
|
+
mark: {
|
|
212
|
+
type: "line",
|
|
213
|
+
stroke: tokens.emphasis,
|
|
214
|
+
strokeWidth: 2,
|
|
215
|
+
strokeCap: "round",
|
|
216
|
+
strokeJoin: "round",
|
|
217
|
+
interpolate: "linear",
|
|
218
|
+
invalid: "break-paths-show-domains"
|
|
219
|
+
},
|
|
220
|
+
encoding: {
|
|
221
|
+
x: xField,
|
|
222
|
+
y: yField
|
|
223
|
+
}
|
|
224
|
+
});
|
|
225
|
+
layers.push({
|
|
226
|
+
mark: {
|
|
227
|
+
type: "point",
|
|
228
|
+
filled: true,
|
|
229
|
+
size: FLAG_SIZE,
|
|
230
|
+
stroke: tokens.background,
|
|
231
|
+
strokeWidth: 1.5,
|
|
232
|
+
aria: false
|
|
233
|
+
},
|
|
234
|
+
encoding: {
|
|
235
|
+
x: xField,
|
|
236
|
+
y: yField,
|
|
237
|
+
fill: {
|
|
238
|
+
field: "c",
|
|
239
|
+
type: "nominal",
|
|
240
|
+
scale: null,
|
|
241
|
+
legend: null
|
|
242
|
+
},
|
|
243
|
+
shape: {
|
|
244
|
+
field: "sh",
|
|
245
|
+
type: "nominal",
|
|
246
|
+
scale: null,
|
|
247
|
+
legend: null
|
|
248
|
+
},
|
|
249
|
+
opacity: {
|
|
250
|
+
condition: {
|
|
251
|
+
test: "datum.a",
|
|
252
|
+
value: 1
|
|
253
|
+
},
|
|
254
|
+
value: 0
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
});
|
|
258
|
+
if (tooltip) {
|
|
259
|
+
layers.push({
|
|
260
|
+
data: { name: ANOMALY_PERIODS_DATASET },
|
|
261
|
+
mark: {
|
|
262
|
+
type: "rule",
|
|
263
|
+
stroke: tokens.axis,
|
|
264
|
+
strokeWidth: 1,
|
|
265
|
+
aria: false
|
|
266
|
+
},
|
|
267
|
+
encoding: {
|
|
268
|
+
x: xField,
|
|
269
|
+
opacity: {
|
|
270
|
+
condition: {
|
|
271
|
+
param: ANOMALY_HOVER_PARAM,
|
|
272
|
+
empty: false,
|
|
273
|
+
value: .6
|
|
274
|
+
},
|
|
275
|
+
value: 0
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
});
|
|
279
|
+
layers.push({
|
|
280
|
+
params: [{
|
|
281
|
+
name: ANOMALY_HOVER_PARAM,
|
|
282
|
+
select: {
|
|
283
|
+
type: "point",
|
|
284
|
+
on: "pointermove",
|
|
285
|
+
nearest: true,
|
|
286
|
+
clear: "pointerout",
|
|
287
|
+
encodings: ["x"]
|
|
288
|
+
}
|
|
289
|
+
}],
|
|
290
|
+
mark: {
|
|
291
|
+
type: "point",
|
|
292
|
+
filled: true,
|
|
293
|
+
size: POINT_SIZE,
|
|
294
|
+
fill: tokens.emphasis,
|
|
295
|
+
stroke: tokens.background,
|
|
296
|
+
strokeWidth: 1.5,
|
|
297
|
+
aria: false
|
|
298
|
+
},
|
|
299
|
+
encoding: {
|
|
300
|
+
x: xField,
|
|
301
|
+
y: yField,
|
|
302
|
+
opacity: {
|
|
303
|
+
condition: {
|
|
304
|
+
test: { and: [{
|
|
305
|
+
param: ANOMALY_HOVER_PARAM,
|
|
306
|
+
empty: false
|
|
307
|
+
}, "!datum.a"] },
|
|
308
|
+
value: 1
|
|
309
|
+
},
|
|
310
|
+
value: 0
|
|
311
|
+
},
|
|
312
|
+
tooltip: tooltipChannel
|
|
313
|
+
}
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
const params = [];
|
|
317
|
+
if (axes) params.push({
|
|
318
|
+
name: ANOMALY_X_TICKS_PARAM,
|
|
319
|
+
expr: `arcAxisTicks(${axisArgs})`
|
|
320
|
+
});
|
|
321
|
+
return {
|
|
322
|
+
$schema: "https://vega.github.io/schema/vega-lite/v6.json",
|
|
323
|
+
width: 320,
|
|
324
|
+
height,
|
|
325
|
+
autosize: {
|
|
326
|
+
type: "fit",
|
|
327
|
+
contains: "padding"
|
|
328
|
+
},
|
|
329
|
+
padding: PLOT_PADDING,
|
|
330
|
+
background: "transparent",
|
|
331
|
+
data: { name: ANOMALY_TABLE_DATASET },
|
|
332
|
+
...params.length > 0 ? { params } : {},
|
|
333
|
+
layer: layers,
|
|
334
|
+
config: arcVegaConfig(tokens, {
|
|
335
|
+
locale: options.locale,
|
|
336
|
+
timeZone: options.timeZone
|
|
337
|
+
})
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
//#endregion
|
|
341
|
+
export { ANOMALY_HOVER_PARAM, ANOMALY_PERIODS_DATASET, ANOMALY_SPAN_DATASET, ANOMALY_TABLE_DATASET, ANOMALY_X_TICKS_PARAM, buildAnomalyPlotSpec };
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { ArcTimeGranularity } from "../../lib/vega/formatters.js";
|
|
2
|
+
import { AnomalyBounds, AnomalyCardLabels, AnomalyCardSize, AnomalyCardStatus, AnomalyDeltaMode, AnomalyGoodDirection, AnomalyHeadline, AnomalyMark, AnomalyPoint, AnomalyScale } from "./AnomalyCard.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/AnomalyCard/AnomalyCard.d.ts
|
|
8
|
+
interface AnomalyCardProps extends Omit<BoxProps, "children" | "padding" | "title"> {
|
|
9
|
+
/** The measure's name — the panel's heading. Pass `name` too when this is not plain text. */
|
|
10
|
+
label: ReactNode;
|
|
11
|
+
/** Plain-text name used in the generated descriptions and control labels. Defaults to `label` when it is a string. */
|
|
12
|
+
name?: string;
|
|
13
|
+
/** 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. */
|
|
14
|
+
hint?: string;
|
|
15
|
+
/**
|
|
16
|
+
* The readings, oldest first: `{ x, y, lower?, upper?, expected?, anomaly?, score? }`.
|
|
17
|
+
* `x` is a `Date`, an ISO string, a number or a period label; `y` the
|
|
18
|
+
* reading, or `null` for a period with no measurement — drawn as a gap,
|
|
19
|
+
* never as zero, and never flagged. `lower`/`upper` are that period's own
|
|
20
|
+
* expected range and fall back to `bounds`; `expected` is the model's
|
|
21
|
+
* predicted value; `anomaly` is the detector's own verdict and overrides
|
|
22
|
+
* the range in BOTH directions; `score` is its own score, printed through
|
|
23
|
+
* `scoreFormat`. Pass `[]` while loading to reserve the plot's height.
|
|
24
|
+
*/
|
|
25
|
+
points: readonly AnomalyPoint[];
|
|
26
|
+
/**
|
|
27
|
+
* A flat expected range — a control limit or an SLO — applied to every
|
|
28
|
+
* period that carries no bounds of its own. Pass one side for a ceiling or
|
|
29
|
+
* a floor (`{ upper: 500 }` reads as `≤ 500`). A period with no bounds from
|
|
30
|
+
* either source is plotted but never judged, and the card says so.
|
|
31
|
+
*/
|
|
32
|
+
bounds?: AnomalyBounds;
|
|
33
|
+
/**
|
|
34
|
+
* Key of the excursion the reader has selected, controlled — pair with
|
|
35
|
+
* `onSelectedEpisodeChange`. Its span is washed in the plot and its row is
|
|
36
|
+
* pressed. Omit for the uncontrolled card (`defaultSelectedEpisode`, else
|
|
37
|
+
* none).
|
|
38
|
+
*/
|
|
39
|
+
selectedEpisode?: string | null;
|
|
40
|
+
/** The excursion selected on first render when `selectedEpisode` is uncontrolled. */
|
|
41
|
+
defaultSelectedEpisode?: string | null;
|
|
42
|
+
/**
|
|
43
|
+
* Called with an excursion's key when the reader selects it, and with `null`
|
|
44
|
+
* when they clear it — the drill-through hook: open a `HighlightCard` (or
|
|
45
|
+
* your own detail view) for that window from here.
|
|
46
|
+
*/
|
|
47
|
+
onSelectedEpisodeChange?: (key: string | null) => void;
|
|
48
|
+
/** `line` (default, may crop) or `area` (fills from zero). */
|
|
49
|
+
mark?: AnomalyMark;
|
|
50
|
+
/** Y-scale baseline for a `line` plot: `auto` (default) fits the readings and their range; `zero` includes zero. An `area` always includes zero. */
|
|
51
|
+
scale?: AnomalyScale;
|
|
52
|
+
/**
|
|
53
|
+
* The big number: `latest` (default) is the last reading with the expected
|
|
54
|
+
* range beneath it; `count` makes the number of excursions the headline;
|
|
55
|
+
* `worst` makes the largest deviation the headline; `none` leaves the plot
|
|
56
|
+
* to carry the panel. Stamped as `data-headline`.
|
|
57
|
+
*/
|
|
58
|
+
headline?: AnomalyHeadline;
|
|
59
|
+
/** `absolute` (default) states a deviation in the measure's own units — percentage points for a `percent` format; `percent` states it relative to the bound it broke. The other form rides along in the tooltip. */
|
|
60
|
+
deltaMode?: AnomalyDeltaMode;
|
|
61
|
+
/**
|
|
62
|
+
* Which direction is good, and therefore what colour means. `none`
|
|
63
|
+
* (default) is the honest answer for a detector — an excursion is
|
|
64
|
+
* UNEXPECTED, not bad — and both directions take the attention hue. `up`
|
|
65
|
+
* (revenue) and `down` (latency, cost, errors) split the excursions into
|
|
66
|
+
* the diverging ends. Direction itself is always carried by the mark's
|
|
67
|
+
* shape and by words, never by hue.
|
|
68
|
+
*/
|
|
69
|
+
goodDirection?: AnomalyGoodDirection;
|
|
70
|
+
/**
|
|
71
|
+
* Number format for the headline, the axis, the rows, the table and the
|
|
72
|
+
* tooltip — one grammar so nothing rounds two ways: `number[:digits]`,
|
|
73
|
+
* `integer`, `compact[:digits]`, `percent[:digits]`,
|
|
74
|
+
* `currency:CODE[:digits|compact]`. Default `compact`.
|
|
75
|
+
*/
|
|
76
|
+
format?: string;
|
|
77
|
+
/** Custom formatter for values. Takes precedence over `format` everywhere a reading is rendered. */
|
|
78
|
+
formatValue?: (value: number) => string;
|
|
79
|
+
/** Number format for the detector's `score`. Default `number:1`. */
|
|
80
|
+
scoreFormat?: string;
|
|
81
|
+
/** Unit shown after a `latest` headline in the muted role (`ms`, `req/s`). Prefer `format="currency:…"` for money. */
|
|
82
|
+
unit?: ReactNode;
|
|
83
|
+
/** Plot height in pixels, axes included. Defaults per `size` (120 / 160 / 200), plus 24 when `axes` draws the x labels. */
|
|
84
|
+
plotHeight?: number;
|
|
85
|
+
/** Draw both axes with grid lines and labels. Default `true`; `false` shrinks the plot toward a sparkline — the table still carries every value. */
|
|
86
|
+
axes?: boolean;
|
|
87
|
+
/** Draw the expected range as a band. Default `true`; ignored when no period carries bounds. */
|
|
88
|
+
band?: boolean;
|
|
89
|
+
/** Draw the model's `expected` value as a dashed hairline inside the band. Default `true`; ignored when no period carries one. */
|
|
90
|
+
expected?: boolean;
|
|
91
|
+
/** The key row under the plot — the readings, the expected range, the expected value and the anomaly mark. Default `true`. */
|
|
92
|
+
keys?: boolean;
|
|
93
|
+
/**
|
|
94
|
+
* The excursion rows — the ranked list of episodes, each a real button that
|
|
95
|
+
* selects it. Default `true`. The description and the table twin name every
|
|
96
|
+
* excursion regardless.
|
|
97
|
+
*/
|
|
98
|
+
episodes?: boolean;
|
|
99
|
+
/**
|
|
100
|
+
* How many excursion slots the rows reserve. The box is exactly this tall in
|
|
101
|
+
* every state, so a card in a grid never resizes when a window gains an
|
|
102
|
+
* excursion; when there are more, the last slot names the overflow. Default 3.
|
|
103
|
+
*/
|
|
104
|
+
maxEpisodes?: number;
|
|
105
|
+
/** Period granularity of temporal `x` values for the axis, tooltips and the table. Inferred from the spacing when omitted. */
|
|
106
|
+
granularity?: ArcTimeGranularity;
|
|
107
|
+
/**
|
|
108
|
+
* The takeaway in a sentence, rendered beside the AI mark under the rows —
|
|
109
|
+
* the insight slot. Wrap values in `<strong>` to set them in bold. Omitted,
|
|
110
|
+
* the card generates one from the window's excursions; pass `null` or
|
|
111
|
+
* `false` to render none.
|
|
112
|
+
*/
|
|
113
|
+
insight?: ReactNode;
|
|
114
|
+
/** The transport's status. `loading` with readings already present is a refresh: the previous render stays under the veil. Default `ready`. */
|
|
115
|
+
status?: AnomalyCardStatus;
|
|
116
|
+
/** The consumer's filter is active — no readings then reads as no-match rather than empty, with a clear-filters action when `onClearFilters` is set. */
|
|
117
|
+
filtered?: boolean;
|
|
118
|
+
/** The data is older than the product's freshness rule (TanStack Query's `isStale`). Shows a badge and stamps `data-stale`. */
|
|
119
|
+
stale?: boolean;
|
|
120
|
+
/** When the data was last true. Rendered as an "as of" line and included in the description. */
|
|
121
|
+
updatedAt?: Date | string | number;
|
|
122
|
+
/**
|
|
123
|
+
* How `updatedAt` is written, as a time-grammar granularity — `day`
|
|
124
|
+
* (default, `Sep 8, 2026`), `datetime`, `time`, `month`, `year` — or a
|
|
125
|
+
* formatter for a custom form. Applies to the as-of line and the
|
|
126
|
+
* description alike, in the card's `locale` and `timeZone`.
|
|
127
|
+
*/
|
|
128
|
+
updatedAtFormat?: ArcTimeGranularity | ((date: Date) => string);
|
|
129
|
+
/** Recovery action for the error state; renders a retry button when set. */
|
|
130
|
+
onRetry?: () => void;
|
|
131
|
+
/** Recovery action for the no-match state; renders a clear-filters button when set. */
|
|
132
|
+
onClearFilters?: () => void;
|
|
133
|
+
/** Density: `sm` for dense grids, `md` (default), `lg` for a hero panel. Scales type, padding and the default plot height. */
|
|
134
|
+
size?: AnomalyCardSize;
|
|
135
|
+
/** Heading level of the label for the document outline. Default 3 — panels usually sit under a page's h2. */
|
|
136
|
+
titleLevel?: 2 | 3 | 4 | 5 | 6;
|
|
137
|
+
/** 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`. */
|
|
138
|
+
locale?: string;
|
|
139
|
+
/** IANA time zone for dates. Defaults to the runtime's — pass it for deterministic output and single-business-zone reporting. */
|
|
140
|
+
timeZone?: string;
|
|
141
|
+
/** Overrides for every rendered or announced string. */
|
|
142
|
+
labels?: Partial<AnomalyCardLabels>;
|
|
143
|
+
/** Replaces the generated accessible description of the whole card (the figure's `aria-describedby` text). */
|
|
144
|
+
description?: string;
|
|
145
|
+
/** Trailing header slot — a ghost `Button` or `Menu` for drill-through, export, or settings. */
|
|
146
|
+
action?: ReactNode;
|
|
147
|
+
/** Open the data popover on first render, anchored to the card. */
|
|
148
|
+
defaultTableOpen?: boolean;
|
|
149
|
+
/** Hide the header info button for the data popover. Only when another surface exposes the same values to keyboard and screen-reader users. */
|
|
150
|
+
hideTableToggle?: boolean;
|
|
151
|
+
/** Called with vega-embed's result once the plot mounts — for `view` access in advanced compositions. */
|
|
152
|
+
onEmbed?: (result: Result) => void;
|
|
153
|
+
/** Escape hatch: transform the plot spec before it renders. Voids the token and accessibility guarantees for whatever it changes. */
|
|
154
|
+
patchSpec?: (spec: TopLevelSpec) => TopLevelSpec;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* An anomaly panel for dashboards: one measure plotted against the range it
|
|
158
|
+
* was expected to stay inside, every reading that broke out marked with a
|
|
159
|
+
* direction-shaped flag, the excursions grouped into episodes and ranked as
|
|
160
|
+
* rows the reader can select, a verdict that says whether it is happening
|
|
161
|
+
* now, and every loading, empty, error and stale state — layout-stable, with
|
|
162
|
+
* a generated text equivalent and a data table in an info popover.
|
|
163
|
+
*
|
|
164
|
+
* Where `HighlightCard` explains ONE window it was handed, AnomalyCard is the
|
|
165
|
+
* surface that finds them: select an excursion here and hand its window on.
|
|
166
|
+
*/
|
|
167
|
+
declare const AnomalyCard: import("react").ForwardRefExoticComponent<AnomalyCardProps & import("react").RefAttributes<HTMLElement>>;
|
|
168
|
+
//#endregion
|
|
169
|
+
export { AnomalyCard, AnomalyCardProps };
|