@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.
Files changed (156) hide show
  1. package/dist/_virtual/_rolldown/runtime.js +13 -0
  2. package/dist/components/AnomalyCard/AnomalyCard.chart.d.ts +64 -0
  3. package/dist/components/AnomalyCard/AnomalyCard.chart.js +341 -0
  4. package/dist/components/AnomalyCard/AnomalyCard.d.ts +169 -0
  5. package/dist/components/AnomalyCard/AnomalyCard.js +1019 -0
  6. package/dist/components/AnomalyCard/AnomalyCard.model.d.ts +508 -0
  7. package/dist/components/AnomalyCard/AnomalyCard.model.js +553 -0
  8. package/dist/components/AnomalyCard/index.d.ts +4 -0
  9. package/dist/components/AnomalyCard/index.js +4 -0
  10. package/dist/components/ChartCard/ChartCard.chart.d.ts +72 -0
  11. package/dist/components/ChartCard/ChartCard.chart.js +1333 -0
  12. package/dist/components/ChartCard/ChartCard.d.ts +206 -0
  13. package/dist/components/ChartCard/ChartCard.js +718 -0
  14. package/dist/components/ChartCard/ChartCard.model.d.ts +452 -0
  15. package/dist/components/ChartCard/ChartCard.model.js +1223 -0
  16. package/dist/components/ChartCard/index.d.ts +4 -0
  17. package/dist/components/ChartCard/index.js +4 -0
  18. package/dist/components/ComparisonCard/ComparisonCard.chart.d.ts +80 -0
  19. package/dist/components/ComparisonCard/ComparisonCard.chart.js +337 -0
  20. package/dist/components/ComparisonCard/ComparisonCard.d.ts +200 -0
  21. package/dist/components/ComparisonCard/ComparisonCard.js +1325 -0
  22. package/dist/components/ComparisonCard/ComparisonCard.model.d.ts +309 -0
  23. package/dist/components/ComparisonCard/ComparisonCard.model.js +263 -0
  24. package/dist/components/ComparisonCard/index.d.ts +4 -0
  25. package/dist/components/ComparisonCard/index.js +4 -0
  26. package/dist/components/ForecastCard/ForecastCard.chart.d.ts +82 -0
  27. package/dist/components/ForecastCard/ForecastCard.chart.js +416 -0
  28. package/dist/components/ForecastCard/ForecastCard.d.ts +148 -0
  29. package/dist/components/ForecastCard/ForecastCard.js +1029 -0
  30. package/dist/components/ForecastCard/ForecastCard.model.d.ts +497 -0
  31. package/dist/components/ForecastCard/ForecastCard.model.js +554 -0
  32. package/dist/components/ForecastCard/index.d.ts +4 -0
  33. package/dist/components/ForecastCard/index.js +4 -0
  34. package/dist/components/HighlightCard/HighlightCard.chart.d.ts +122 -0
  35. package/dist/components/HighlightCard/HighlightCard.chart.js +660 -0
  36. package/dist/components/HighlightCard/HighlightCard.d.ts +202 -0
  37. package/dist/components/HighlightCard/HighlightCard.js +1286 -0
  38. package/dist/components/HighlightCard/HighlightCard.model.d.ts +692 -0
  39. package/dist/components/HighlightCard/HighlightCard.model.js +875 -0
  40. package/dist/components/HighlightCard/index.d.ts +4 -0
  41. package/dist/components/HighlightCard/index.js +4 -0
  42. package/dist/components/InsightCard/InsightCard.chart.d.ts +91 -0
  43. package/dist/components/InsightCard/InsightCard.chart.js +471 -0
  44. package/dist/components/InsightCard/InsightCard.d.ts +161 -0
  45. package/dist/components/InsightCard/InsightCard.js +961 -0
  46. package/dist/components/InsightCard/InsightCard.model.d.ts +405 -0
  47. package/dist/components/InsightCard/InsightCard.model.js +421 -0
  48. package/dist/components/InsightCard/index.d.ts +4 -0
  49. package/dist/components/InsightCard/index.js +4 -0
  50. package/dist/components/MetricCard/MetricCard.chart.d.ts +79 -0
  51. package/dist/components/MetricCard/MetricCard.chart.js +435 -0
  52. package/dist/components/MetricCard/MetricCard.d.ts +227 -0
  53. package/dist/components/MetricCard/MetricCard.js +1293 -0
  54. package/dist/components/MetricCard/MetricCard.model.d.ts +521 -0
  55. package/dist/components/MetricCard/MetricCard.model.js +627 -0
  56. package/dist/components/MetricCard/index.d.ts +4 -0
  57. package/dist/components/MetricCard/index.js +4 -0
  58. package/dist/components/ProfileCard/ProfileCard.chart.d.ts +64 -0
  59. package/dist/components/ProfileCard/ProfileCard.chart.js +427 -0
  60. package/dist/components/ProfileCard/ProfileCard.d.ts +140 -0
  61. package/dist/components/ProfileCard/ProfileCard.js +735 -0
  62. package/dist/components/ProfileCard/ProfileCard.model.d.ts +279 -0
  63. package/dist/components/ProfileCard/ProfileCard.model.js +244 -0
  64. package/dist/components/ProfileCard/index.d.ts +4 -0
  65. package/dist/components/ProfileCard/index.js +4 -0
  66. package/dist/components/ProgressCard/ProgressCard.chart.d.ts +73 -0
  67. package/dist/components/ProgressCard/ProgressCard.chart.js +373 -0
  68. package/dist/components/ProgressCard/ProgressCard.d.ts +137 -0
  69. package/dist/components/ProgressCard/ProgressCard.js +908 -0
  70. package/dist/components/ProgressCard/ProgressCard.model.d.ts +385 -0
  71. package/dist/components/ProgressCard/ProgressCard.model.js +389 -0
  72. package/dist/components/ProgressCard/index.d.ts +4 -0
  73. package/dist/components/ProgressCard/index.js +4 -0
  74. package/dist/components/ReportCard/ReportCard.chart.d.ts +45 -0
  75. package/dist/components/ReportCard/ReportCard.chart.js +231 -0
  76. package/dist/components/ReportCard/ReportCard.d.ts +153 -0
  77. package/dist/components/ReportCard/ReportCard.js +1118 -0
  78. package/dist/components/ReportCard/ReportCard.model.d.ts +392 -0
  79. package/dist/components/ReportCard/ReportCard.model.js +399 -0
  80. package/dist/components/ReportCard/index.d.ts +4 -0
  81. package/dist/components/ReportCard/index.js +4 -0
  82. package/dist/components/SankeyCard/SankeyCard.chart.d.ts +75 -0
  83. package/dist/components/SankeyCard/SankeyCard.chart.js +249 -0
  84. package/dist/components/SankeyCard/SankeyCard.d.ts +185 -0
  85. package/dist/components/SankeyCard/SankeyCard.js +788 -0
  86. package/dist/components/SankeyCard/SankeyCard.model.d.ts +501 -0
  87. package/dist/components/SankeyCard/SankeyCard.model.js +789 -0
  88. package/dist/components/SankeyCard/index.d.ts +4 -0
  89. package/dist/components/SankeyCard/index.js +4 -0
  90. package/dist/components/StatusCard/StatusCard.chart.d.ts +60 -0
  91. package/dist/components/StatusCard/StatusCard.chart.js +188 -0
  92. package/dist/components/StatusCard/StatusCard.d.ts +176 -0
  93. package/dist/components/StatusCard/StatusCard.js +989 -0
  94. package/dist/components/StatusCard/StatusCard.model.d.ts +555 -0
  95. package/dist/components/StatusCard/StatusCard.model.js +776 -0
  96. package/dist/components/StatusCard/index.d.ts +4 -0
  97. package/dist/components/StatusCard/index.js +4 -0
  98. package/dist/components/TableCard/TableCard.chart.d.ts +53 -0
  99. package/dist/components/TableCard/TableCard.chart.js +192 -0
  100. package/dist/components/TableCard/TableCard.d.ts +140 -0
  101. package/dist/components/TableCard/TableCard.js +811 -0
  102. package/dist/components/TableCard/TableCard.model.d.ts +381 -0
  103. package/dist/components/TableCard/TableCard.model.js +475 -0
  104. package/dist/components/TableCard/index.d.ts +4 -0
  105. package/dist/components/TableCard/index.js +4 -0
  106. package/dist/components/TargetCard/TargetCard.chart.d.ts +52 -0
  107. package/dist/components/TargetCard/TargetCard.chart.js +273 -0
  108. package/dist/components/TargetCard/TargetCard.d.ts +143 -0
  109. package/dist/components/TargetCard/TargetCard.js +910 -0
  110. package/dist/components/TargetCard/TargetCard.model.d.ts +468 -0
  111. package/dist/components/TargetCard/TargetCard.model.js +581 -0
  112. package/dist/components/TargetCard/index.d.ts +4 -0
  113. package/dist/components/TargetCard/index.js +4 -0
  114. package/dist/components/TreeCard/TreeCard.chart.d.ts +80 -0
  115. package/dist/components/TreeCard/TreeCard.chart.js +178 -0
  116. package/dist/components/TreeCard/TreeCard.d.ts +182 -0
  117. package/dist/components/TreeCard/TreeCard.js +1187 -0
  118. package/dist/components/TreeCard/TreeCard.model.d.ts +330 -0
  119. package/dist/components/TreeCard/TreeCard.model.js +401 -0
  120. package/dist/components/TreeCard/index.d.ts +4 -0
  121. package/dist/components/TreeCard/index.js +4 -0
  122. package/dist/components/TrendCard/TrendCard.chart.d.ts +75 -0
  123. package/dist/components/TrendCard/TrendCard.chart.js +393 -0
  124. package/dist/components/TrendCard/TrendCard.d.ts +224 -0
  125. package/dist/components/TrendCard/TrendCard.js +1053 -0
  126. package/dist/components/TrendCard/TrendCard.model.d.ts +545 -0
  127. package/dist/components/TrendCard/TrendCard.model.js +623 -0
  128. package/dist/components/TrendCard/index.d.ts +4 -0
  129. package/dist/components/TrendCard/index.js +4 -0
  130. package/dist/index.d.ts +76 -0
  131. package/dist/index.js +57 -0
  132. package/dist/lib/vega/ArcVegaChart.d.ts +24 -0
  133. package/dist/lib/vega/ArcVegaChart.js +42 -0
  134. package/dist/lib/vega/ArcVegaSurface.d.ts +13 -0
  135. package/dist/lib/vega/ArcVegaSurface.js +38 -0
  136. package/dist/lib/vega/axisTicks.js +156 -0
  137. package/dist/lib/vega/config.d.ts +29 -0
  138. package/dist/lib/vega/config.js +113 -0
  139. package/dist/lib/vega/embed.d.ts +29 -0
  140. package/dist/lib/vega/embed.js +29 -0
  141. package/dist/lib/vega/engine.d.ts +10 -0
  142. package/dist/lib/vega/engine.js +6 -0
  143. package/dist/lib/vega/formatters.d.ts +125 -0
  144. package/dist/lib/vega/formatters.js +277 -0
  145. package/dist/lib/vega/index.d.ts +11 -0
  146. package/dist/lib/vega/load.d.ts +13 -0
  147. package/dist/lib/vega/load.js +21 -0
  148. package/dist/lib/vega/time.d.ts +45 -0
  149. package/dist/lib/vega/time.js +105 -0
  150. package/dist/lib/vega/tokens.d.ts +73 -0
  151. package/dist/lib/vega/tokens.js +137 -0
  152. package/dist/lib/vega/tooltip.d.ts +45 -0
  153. package/dist/lib/vega/tooltip.js +124 -0
  154. package/dist/lib/vega/useArcVega.d.ts +43 -0
  155. package/dist/lib/vega/useArcVega.js +121 -0
  156. package/package.json +60 -0
@@ -0,0 +1,989 @@
1
+ import { ArcVegaChart } from "../../lib/vega/ArcVegaChart.js";
2
+ import { arcEmbedOptions } from "../../lib/vega/embed.js";
3
+ import { formatDate } from "../../lib/vega/formatters.js";
4
+ import { useChartTokens } from "../../lib/vega/tokens.js";
5
+ import { ArcTooltipRows, useArcTooltipHandler } from "../../lib/vega/tooltip.js";
6
+ import { STATUS_CELL_GAP_RATIO, STATUS_TABLE_DATASET, STATUS_WINDOW_DATASET, buildStatusTimelineSpec } from "./StatusCard.chart.js";
7
+ import { STATUS_LEVELS, buildStatusChartDescription, buildStatusDescription, buildStatusDetailRows, buildStatusExplanation, buildStatusIncidentRows, buildStatusStrip, createStatusFormatters, deriveStatusRun, deriveStatusState, describeResolution, formatStripCell, resolveStatusHold, resolveStatusLabels, statusLevelBreakdown, statusStepKey } from "./StatusCard.model.js";
8
+ import { forwardRef, useCallback, useEffect, useId, useMemo, useRef, useState } from "react";
9
+ import { AILoader, Badge, Box, Button, Popover, PopoverPopup, PopoverTitle, PopoverTrigger, Skeleton, SkeletonGroup, SystemState, Table, TableBody, TableCaption, TableCell, TableContainer, TableHead, TableHeader, TableRow, Tooltip, TooltipPopup, TooltipTrigger, cn } from "@arcfusionz/arc-primitive-ui";
10
+ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
11
+ //#region src/components/StatusCard/StatusCard.tsx
12
+ const sizeStyles = {
13
+ sm: {
14
+ padding: "sm",
15
+ gap: "gap-2",
16
+ gapPx: 8,
17
+ label: "text-xs",
18
+ value: "text-xl leading-7",
19
+ valueLinePx: 28,
20
+ subLinePx: 20,
21
+ glyph: "size-4",
22
+ body: "text-xs",
23
+ badge: "sm",
24
+ deltaLinePx: 20,
25
+ comparisonLinePx: 16,
26
+ chip: "sm",
27
+ stripHeight: 16,
28
+ captionLinePx: 16,
29
+ keyLinePx: 16
30
+ },
31
+ md: {
32
+ padding: "md",
33
+ gap: "gap-2",
34
+ gapPx: 8,
35
+ label: "text-sm",
36
+ value: "text-2xl leading-8",
37
+ valueLinePx: 32,
38
+ subLinePx: 20,
39
+ glyph: "size-5",
40
+ body: "text-sm",
41
+ badge: "md",
42
+ deltaLinePx: 24,
43
+ comparisonLinePx: 20,
44
+ chip: "sm",
45
+ stripHeight: 22,
46
+ captionLinePx: 18,
47
+ keyLinePx: 18
48
+ },
49
+ lg: {
50
+ padding: "lg",
51
+ gap: "gap-2",
52
+ gapPx: 8,
53
+ label: "text-sm",
54
+ value: "text-3xl leading-9",
55
+ valueLinePx: 36,
56
+ subLinePx: 24,
57
+ glyph: "size-6",
58
+ body: "text-sm",
59
+ badge: "lg",
60
+ deltaLinePx: 28,
61
+ comparisonLinePx: 20,
62
+ chip: "md",
63
+ stripHeight: 28,
64
+ captionLinePx: 20,
65
+ keyLinePx: 18
66
+ }
67
+ };
68
+ const labelClasses = "min-w-0 font-sans font-medium text-muted-foreground";
69
+ const valueClasses = "font-heading font-semibold tracking-tight text-foreground";
70
+ const HEADLINE_GAP_PX = 4;
71
+ const STRIP_CAPTION_GAP_PX = 4;
72
+ const KEY_LINES = 2;
73
+ const captionClasses = "font-sans text-xs text-muted-foreground";
74
+ /**
75
+ * The headline state word wears its level's TEXT step — the same 700 steps
76
+ * `text-success-700` / `text-error-700` resolve to, which clear 4.5:1 as body
77
+ * text and far more at headline size. It is the one place a status hue reaches
78
+ * type, and it is allowed because the word IS the status: an operator scanning
79
+ * a wall must find the broken tile without reading it. Shape carries the same
80
+ * information beside it (`LevelGlyph`), so the colour is never load-bearing.
81
+ */
82
+ const levelTextClasses = {
83
+ operational: "text-success-700",
84
+ degraded: "text-warning-700",
85
+ down: "text-error-700",
86
+ maintenance: "text-primary-700",
87
+ unknown: "text-muted-foreground"
88
+ };
89
+ const levelBadgeVariant = {
90
+ operational: "success",
91
+ degraded: "warning",
92
+ down: "destructive",
93
+ maintenance: "primary",
94
+ unknown: "neutral"
95
+ };
96
+ const polarityBadgeVariant = {
97
+ positive: "success",
98
+ negative: "destructive",
99
+ neutral: "neutral"
100
+ };
101
+ const toneTextClasses = {
102
+ positive: "text-chart-positive",
103
+ negative: "text-chart-negative",
104
+ neutral: "text-foreground"
105
+ };
106
+ const deltaStackClasses = "ms-auto flex min-w-0 max-w-[56%] shrink-0 flex-col items-end gap-1 rounded-md text-right font-sans focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring";
107
+ const headlineValueClasses = "flex min-w-0 flex-1 flex-col items-start gap-1";
108
+ const headerControlClasses = "size-6 min-w-0 text-muted-foreground hover:text-foreground";
109
+ const tileStateClasses = "w-full max-w-none gap-1.5 px-2 py-1 [--artwork-box:2rem]";
110
+ function InfoIcon(props) {
111
+ return /* @__PURE__ */ jsxs("svg", {
112
+ viewBox: "0 0 24 24",
113
+ fill: "none",
114
+ stroke: "currentColor",
115
+ strokeWidth: 2,
116
+ strokeLinecap: "round",
117
+ strokeLinejoin: "round",
118
+ "aria-hidden": "true",
119
+ ...props,
120
+ children: [/* @__PURE__ */ jsx("circle", {
121
+ cx: "12",
122
+ cy: "12",
123
+ r: "9"
124
+ }), /* @__PURE__ */ jsx("path", { d: "M12 11v5M12 8h.01" })]
125
+ });
126
+ }
127
+ /**
128
+ * The level's own shape, beside its word wherever the word appears. Five
129
+ * distinct silhouettes, so a reader who cannot separate the hues still reads
130
+ * five different states (WCAG 1.4.1).
131
+ */
132
+ function LevelGlyph({ level, ...props }) {
133
+ return /* @__PURE__ */ jsxs("svg", {
134
+ viewBox: "0 0 24 24",
135
+ fill: "none",
136
+ stroke: "currentColor",
137
+ strokeWidth: 2.25,
138
+ strokeLinecap: "round",
139
+ strokeLinejoin: "round",
140
+ "aria-hidden": "true",
141
+ ...props,
142
+ children: [
143
+ level === "operational" && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("circle", {
144
+ cx: "12",
145
+ cy: "12",
146
+ r: "9"
147
+ }), /* @__PURE__ */ jsx("path", { d: "m8 12 2.5 2.5L16 9.5" })] }),
148
+ level === "degraded" && /* @__PURE__ */ jsx("path", { d: "M12 3.5 2.5 20.5h19L12 3.5ZM12 10v4.5m0 3h.01" }),
149
+ level === "down" && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("path", { d: "M8.4 2.5h7.2l5.9 5.9v7.2l-5.9 5.9H8.4L2.5 15.6V8.4L8.4 2.5Z" }), /* @__PURE__ */ jsx("path", { d: "m9 9 6 6m0-6-6 6" })] }),
150
+ level === "maintenance" && /* @__PURE__ */ jsx("path", { d: "M14.5 6.5a3.5 3.5 0 1 0 4.6 4.6l2.4 2.4a6 6 0 0 1-8.4 8.4L4.5 13.4a6 6 0 0 1 8.4-8.4l1.6 1.5Z" }),
151
+ level === "unknown" && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("circle", {
152
+ cx: "12",
153
+ cy: "12",
154
+ r: "9"
155
+ }), /* @__PURE__ */ jsx("path", { d: "M9.5 9.5a2.5 2.5 0 1 1 3.4 2.3c-.6.3-.9.8-.9 1.5v.4m0 3h.01" })] })
156
+ ]
157
+ });
158
+ }
159
+ /**
160
+ * The level's key mark — a compact shape in the level's own chart hue, used in
161
+ * the key line, the tooltip chip and the incident table, so a cell's colour is
162
+ * always tied to a shape and a word somewhere the reader can reach.
163
+ */
164
+ function StatusKey({ level, label, color, className }) {
165
+ return /* @__PURE__ */ jsxs("span", {
166
+ className: cn("inline-flex items-center gap-1.5", className),
167
+ children: [/* @__PURE__ */ jsxs("svg", {
168
+ width: "10",
169
+ height: "10",
170
+ viewBox: "0 0 10 10",
171
+ "aria-hidden": "true",
172
+ className: "shrink-0",
173
+ style: { color },
174
+ children: [
175
+ level === "operational" && /* @__PURE__ */ jsx("circle", {
176
+ cx: "5",
177
+ cy: "5",
178
+ r: "4.5",
179
+ fill: "currentColor"
180
+ }),
181
+ level === "degraded" && /* @__PURE__ */ jsx("path", {
182
+ d: "M5 0.5 9.7 9.2H0.3z",
183
+ fill: "currentColor"
184
+ }),
185
+ level === "down" && /* @__PURE__ */ jsx("rect", {
186
+ x: "0.5",
187
+ y: "0.5",
188
+ width: "9",
189
+ height: "9",
190
+ rx: "1.5",
191
+ fill: "currentColor"
192
+ }),
193
+ level === "maintenance" && /* @__PURE__ */ jsx("path", {
194
+ d: "M5 0.2 9.8 5 5 9.8 0.2 5z",
195
+ fill: "currentColor"
196
+ }),
197
+ level === "unknown" && /* @__PURE__ */ jsx("rect", {
198
+ x: "1.2",
199
+ y: "1.2",
200
+ width: "7.6",
201
+ height: "7.6",
202
+ rx: "1.5",
203
+ fill: "none",
204
+ stroke: "currentColor",
205
+ strokeWidth: "1.8"
206
+ })
207
+ ]
208
+ }), label]
209
+ });
210
+ }
211
+ function useMergedRef(forwarded) {
212
+ const inner = useRef(null);
213
+ return [inner, useCallback((node) => {
214
+ inner.current = node;
215
+ if (typeof forwarded === "function") forwarded(node);
216
+ else if (forwarded) forwarded.current = node;
217
+ }, [forwarded])];
218
+ }
219
+ function usePlotWidth(ref, enabled) {
220
+ const [width, setWidth] = useState(0);
221
+ useEffect(() => {
222
+ if (!enabled) return;
223
+ const el = ref.current;
224
+ if (!el) return;
225
+ let frame = 0;
226
+ const measure = () => {
227
+ const next = Math.round(el.getBoundingClientRect().width);
228
+ setWidth((prev) => prev === next ? prev : next);
229
+ };
230
+ measure();
231
+ if (typeof ResizeObserver === "undefined") return;
232
+ const observer = new ResizeObserver(() => {
233
+ cancelAnimationFrame(frame);
234
+ frame = requestAnimationFrame(measure);
235
+ });
236
+ observer.observe(el);
237
+ return () => {
238
+ cancelAnimationFrame(frame);
239
+ observer.disconnect();
240
+ };
241
+ }, [ref, enabled]);
242
+ return width;
243
+ }
244
+ /**
245
+ * An operational status tile for dashboard grids and status pages: the state
246
+ * right now as a word, how long it has held, availability over the window
247
+ * against its target, the incidents behind that number, and the error budget
248
+ * they leave — on a state timeline (each cell painted the worst level inside
249
+ * it, so no outage can vanish) with every loading, empty, error and stale
250
+ * state, layout-stable, with a generated text equivalent and both a details
251
+ * table and an incident list in an info popover.
252
+ */
253
+ const StatusCard = forwardRef(({ label, name: nameProp, hint, level, since, history, window: windowProp, uptimeTarget, uptimeMode = "monitored", uptimeFormat = "percent:2", formatUptime, headline = "level", resolution = "auto", axis = false, legend = false, insight, status = "ready", filtered = false, stale = false, updatedAt, updatedAtFormat = "datetime", onRetry, onClearFilters, size = "md", titleLevel = 3, locale, timeZone, labels: labelOverrides, description, action, defaultTableOpen = false, hideTableToggle = false, onEmbed, patchSpec, render, className, ...rest }, forwardedRef) => {
254
+ const labels = useMemo(() => resolveStatusLabels(labelOverrides), [labelOverrides]);
255
+ const sizes = sizeStyles[size];
256
+ const plotHeight = sizes.stripHeight + (axis ? 18 : 0);
257
+ const name = nameProp ?? (typeof label === "string" ? label : "");
258
+ const id = useId();
259
+ const headingId = `${id}-label`;
260
+ const descriptionId = `${id}-description`;
261
+ const hintId = `${id}-hint`;
262
+ const tableId = `${id}-table`;
263
+ const explanationId = `${id}-explanation`;
264
+ const [rootRef, setRootRef] = useMergedRef(forwardedRef);
265
+ const plotRef = useRef(null);
266
+ const [tableOpen, setTableOpen] = useState(defaultTableOpen);
267
+ const [popoverContainer, setPopoverContainer] = useState(null);
268
+ const asOfDate = updatedAt == null ? null : updatedAt instanceof Date ? updatedAt : new Date(updatedAt);
269
+ const asOfValid = asOfDate != null && !Number.isNaN(asOfDate.getTime());
270
+ const asOfMs = asOfValid ? asOfDate.getTime() : null;
271
+ const asOfText = asOfValid ? typeof updatedAtFormat === "function" ? updatedAtFormat(asOfDate) : formatDate(asOfDate, {
272
+ granularity: updatedAtFormat,
273
+ locale,
274
+ timeZone
275
+ }) : void 0;
276
+ const formatters = useMemo(() => createStatusFormatters({
277
+ uptimeFormat,
278
+ formatUptimeValue: formatUptime,
279
+ units: labels.durationUnits,
280
+ zeroDuration: labels.zeroDuration,
281
+ locale,
282
+ timeZone
283
+ }), [
284
+ uptimeFormat,
285
+ formatUptime,
286
+ labels.durationUnits,
287
+ labels.zeroDuration,
288
+ locale,
289
+ timeZone
290
+ ]);
291
+ const windowStart = windowProp?.start;
292
+ const windowEnd = windowProp?.end;
293
+ const run = useMemo(() => deriveStatusRun({
294
+ level,
295
+ since,
296
+ history,
297
+ window: windowStart != null && windowEnd != null ? {
298
+ start: windowStart,
299
+ end: windowEnd
300
+ } : void 0,
301
+ asOf: asOfMs,
302
+ uptimeTarget,
303
+ mode: uptimeMode,
304
+ timeZone
305
+ }), [
306
+ level,
307
+ since,
308
+ history,
309
+ windowStart,
310
+ windowEnd,
311
+ asOfMs,
312
+ uptimeTarget,
313
+ uptimeMode,
314
+ timeZone
315
+ ]);
316
+ const reported = run?.segments.some((segment) => !segment.gap) ?? false;
317
+ const currentLevel = level ?? (reported ? run?.level ?? null : null);
318
+ const hold = useMemo(() => resolveStatusHold({
319
+ run,
320
+ since,
321
+ asOf: asOfMs,
322
+ timeZone
323
+ }), [
324
+ run,
325
+ since,
326
+ asOfMs,
327
+ timeZone
328
+ ]);
329
+ const hasLevel = currentLevel != null;
330
+ const state = deriveStatusState({
331
+ status,
332
+ hasLevel,
333
+ hasHistory: run != null && reported,
334
+ hasData: hasLevel,
335
+ filtered
336
+ });
337
+ const showContent = state === "ready" || state === "refreshing" || state === "insufficient";
338
+ const noHistory = showContent && run == null;
339
+ const explanationRows = useMemo(() => run ? buildStatusExplanation({
340
+ run,
341
+ formatters,
342
+ labels
343
+ }) : [], [
344
+ run,
345
+ formatters,
346
+ labels
347
+ ]);
348
+ const explanation = explanationRows.map(([key, entry]) => `${key}: ${entry}`).join(". ");
349
+ const incidentRows = useMemo(() => run ? buildStatusIncidentRows({
350
+ run,
351
+ formatters,
352
+ labels
353
+ }) : [], [
354
+ run,
355
+ formatters,
356
+ labels
357
+ ]);
358
+ const tokens = useChartTokens(rootRef);
359
+ const plotWidth = usePlotWidth(plotRef, run != null);
360
+ const strip = useMemo(() => run && tokens ? buildStatusStrip({
361
+ run,
362
+ resolution,
363
+ tokens,
364
+ plotWidth,
365
+ minCellPx: 6,
366
+ gapRatio: STATUS_CELL_GAP_RATIO,
367
+ gapMinPx: 1,
368
+ gapMaxPx: 4,
369
+ timeZone
370
+ }) : null, [
371
+ run,
372
+ resolution,
373
+ tokens,
374
+ plotWidth,
375
+ timeZone
376
+ ]);
377
+ const detailRows = useMemo(() => run ? buildStatusDetailRows({
378
+ run,
379
+ strip,
380
+ formatters,
381
+ labels
382
+ }) : [], [
383
+ run,
384
+ strip,
385
+ formatters,
386
+ labels
387
+ ]);
388
+ const resolutionText = strip ? describeResolution(strip, formatters, labels) : null;
389
+ const breakdown = useMemo(() => run ? statusLevelBreakdown(run, formatters, labels) : [], [
390
+ run,
391
+ formatters,
392
+ labels
393
+ ]);
394
+ const cardDescription = description ?? buildStatusDescription({
395
+ name,
396
+ state,
397
+ run,
398
+ level: currentLevel,
399
+ hold,
400
+ formatters,
401
+ labels,
402
+ asOfText
403
+ });
404
+ const tooltipContent = useCallback(({ item }) => {
405
+ const datum = item.datum;
406
+ if (!datum || datum.level == null || !strip) return null;
407
+ const present = STATUS_LEVELS.filter((entry) => (datum.durations?.[entry] ?? 0) > 0);
408
+ const rows = (present.length > 0 ? present : [datum.level]).map((entry) => [/* @__PURE__ */ jsx(StatusKey, {
409
+ level: entry,
410
+ label: labels.levelNames[entry],
411
+ color: tokens?.status[entry]
412
+ }, entry), formatters.formatDuration(datum.durations?.[entry] ?? datum.to - datum.from)]);
413
+ return /* @__PURE__ */ jsxs("div", {
414
+ className: "flex flex-col gap-1",
415
+ children: [
416
+ /* @__PURE__ */ jsx("span", {
417
+ className: "font-medium",
418
+ children: formatStripCell(datum, strip, formatters)
419
+ }),
420
+ /* @__PURE__ */ jsx(ArcTooltipRows, { rows }),
421
+ datum.label && /* @__PURE__ */ jsx("span", {
422
+ className: "max-w-56 whitespace-normal text-background/70",
423
+ children: datum.label
424
+ })
425
+ ]
426
+ });
427
+ }, [
428
+ strip,
429
+ labels,
430
+ formatters,
431
+ tokens
432
+ ]);
433
+ const { handler: tooltipHandler, tooltip } = useArcTooltipHandler({ content: tooltipContent });
434
+ const embedOptions = useMemo(() => arcEmbedOptions({ tooltip: tooltipHandler }), [tooltipHandler]);
435
+ const axisTimeFormat = strip ? [
436
+ strip.axisGranularity,
437
+ locale ?? "",
438
+ timeZone ?? ""
439
+ ].join("@").replace(/@+$/, "") : "day-short";
440
+ const spec = useMemo(() => {
441
+ if (!tokens) return null;
442
+ const built = buildStatusTimelineSpec({
443
+ height: plotHeight,
444
+ axis,
445
+ tooltip: true,
446
+ axisTimeFormat,
447
+ locale,
448
+ timeZone
449
+ }, tokens);
450
+ return patchSpec ? patchSpec(built) : built;
451
+ }, [
452
+ tokens,
453
+ plotHeight,
454
+ axis,
455
+ axisTimeFormat,
456
+ locale,
457
+ timeZone,
458
+ patchSpec
459
+ ]);
460
+ const datasets = useMemo(() => {
461
+ if (!run || !strip) return void 0;
462
+ return {
463
+ [STATUS_TABLE_DATASET]: strip.rows,
464
+ [STATUS_WINDOW_DATASET]: [{
465
+ start: run.window.start,
466
+ end: run.window.end
467
+ }]
468
+ };
469
+ }, [run, strip]);
470
+ const chartDescription = run && strip ? buildStatusChartDescription({
471
+ name,
472
+ run,
473
+ strip,
474
+ formatters,
475
+ labels
476
+ }) : void 0;
477
+ const verdict = run?.sla?.verdict ?? null;
478
+ const showChip = headline === "uptime" ? currentLevel != null : hold != null;
479
+ const hasBadge = headline === "uptime" ? verdict != null : run != null;
480
+ const reserveInsight = insight != null && insight !== false;
481
+ const reserveKey = legend;
482
+ const headlineMinHeight = Math.max(sizes.valueLinePx + (HEADLINE_GAP_PX + sizes.subLinePx), sizes.deltaLinePx + 4 + sizes.comparisonLinePx);
483
+ const bodyMinHeight = headlineMinHeight + sizes.gapPx + plotHeight + STRIP_CAPTION_GAP_PX + sizes.captionLinePx + (reserveKey ? STRIP_CAPTION_GAP_PX + sizes.keyLinePx * KEY_LINES : 0) + (reserveInsight ? sizes.gapPx + sizes.comparisonLinePx : 0);
484
+ const HeadingTag = `h${titleLevel}`;
485
+ const busy = state === "loading" || state === "refreshing";
486
+ const uptimeText = formatters.formatUptime(run?.uptime);
487
+ const bigIsLevel = headline === "level";
488
+ const holdText = hold ? hold.atLeast ? labels.heldAtLeast(formatters.formatDuration(hold.duration)) : labels.heldFor(formatters.formatDuration(hold.duration)) : null;
489
+ const overBudget = run?.sla != null && run.sla.remaining <= 0 && run.sla.used > run.sla.allowed;
490
+ return /* @__PURE__ */ jsxs(Box, {
491
+ ref: setRootRef,
492
+ render: render ?? /* @__PURE__ */ jsx("figure", {}),
493
+ padding: sizes.padding,
494
+ "aria-labelledby": headingId,
495
+ "aria-describedby": descriptionId,
496
+ "aria-busy": busy || void 0,
497
+ "data-status": status,
498
+ "data-state": state,
499
+ "data-size": size,
500
+ "data-headline": headline,
501
+ "data-mode": uptimeMode,
502
+ "data-level": showContent && currentLevel ? currentLevel : void 0,
503
+ "data-worst": showContent && run ? run.worst : void 0,
504
+ "data-verdict": showContent && verdict ? verdict : void 0,
505
+ "data-polarity": showContent && run?.sla ? run.polarity : void 0,
506
+ "data-resolution": showContent && strip ? statusStepKey(strip.step) : void 0,
507
+ "data-empty": state === "empty" || state === "no-match" ? "" : void 0,
508
+ "data-stale": stale ? "" : void 0,
509
+ "data-insufficient": noHistory ? "" : void 0,
510
+ ...rest,
511
+ className: cn("relative flex min-w-0 flex-col", sizes.gap, className),
512
+ children: [
513
+ /* @__PURE__ */ jsxs("div", {
514
+ className: "flex min-h-6 items-center justify-between gap-2",
515
+ children: [/* @__PURE__ */ jsxs("div", {
516
+ className: "flex min-w-0 items-center gap-1",
517
+ children: [/* @__PURE__ */ jsx(HeadingTag, {
518
+ id: headingId,
519
+ className: cn(labelClasses, sizes.label, "line-clamp-2"),
520
+ children: label
521
+ }), hint && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs(Tooltip, { children: [/* @__PURE__ */ jsx(TooltipTrigger, {
522
+ render: /* @__PURE__ */ jsx(Button, {
523
+ variant: "ghost",
524
+ size: "sm",
525
+ iconOnly: true,
526
+ circular: true,
527
+ "aria-label": labels.about(name),
528
+ "aria-describedby": hintId,
529
+ className: headerControlClasses
530
+ }),
531
+ children: /* @__PURE__ */ jsx(InfoIcon, { className: "size-3.5" })
532
+ }), /* @__PURE__ */ jsx(TooltipPopup, { children: hint })] }), /* @__PURE__ */ jsx("span", {
533
+ id: hintId,
534
+ className: "sr-only",
535
+ children: hint
536
+ })] })]
537
+ }), /* @__PURE__ */ jsxs("div", {
538
+ className: "flex shrink-0 items-center gap-1",
539
+ children: [
540
+ stale && /* @__PURE__ */ jsx(Badge, {
541
+ variant: "warning",
542
+ appearance: "soft",
543
+ size: "sm",
544
+ children: labels.stale
545
+ }),
546
+ showContent && run && /* @__PURE__ */ jsxs(Popover, {
547
+ open: tableOpen,
548
+ onOpenChange: setTableOpen,
549
+ children: [!hideTableToggle && /* @__PURE__ */ jsx(PopoverTrigger, {
550
+ render: /* @__PURE__ */ jsx(Button, {
551
+ variant: "ghost",
552
+ size: "sm",
553
+ iconOnly: true,
554
+ circular: true,
555
+ "aria-label": tableOpen ? labels.hideTable(name) : labels.showTable(name),
556
+ className: headerControlClasses
557
+ }),
558
+ children: /* @__PURE__ */ jsx(InfoIcon, { className: "size-3.5" })
559
+ }), popoverContainer && /* @__PURE__ */ jsxs(PopoverPopup, {
560
+ id: tableId,
561
+ anchor: rootRef,
562
+ container: popoverContainer,
563
+ side: "right",
564
+ align: "start",
565
+ collisionPadding: 8,
566
+ className: "pointer-events-auto w-80",
567
+ "data-part": "data-popover",
568
+ children: [
569
+ /* @__PURE__ */ jsx(PopoverTitle, {
570
+ className: "mb-3",
571
+ children: name
572
+ }),
573
+ /* @__PURE__ */ jsx(TableContainer, {
574
+ variant: "plain",
575
+ tabIndex: 0,
576
+ role: "region",
577
+ "aria-label": labels.tableCaption(name),
578
+ className: "mb-3 max-h-[min(14rem,calc(var(--available-height)-12rem))] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring",
579
+ "data-part": "table",
580
+ children: /* @__PURE__ */ jsxs(Table, {
581
+ size: "sm",
582
+ stickyHeader: true,
583
+ hoverable: false,
584
+ children: [
585
+ /* @__PURE__ */ jsx(TableCaption, {
586
+ side: "top",
587
+ className: "sr-only",
588
+ children: labels.tableCaption(name)
589
+ }),
590
+ /* @__PURE__ */ jsx(TableHeader, { children: /* @__PURE__ */ jsxs(TableRow, { children: [/* @__PURE__ */ jsx(TableHead, { children: labels.tableItem }), /* @__PURE__ */ jsx(TableHead, {
591
+ className: "text-right",
592
+ children: labels.tableValue
593
+ })] }) }),
594
+ /* @__PURE__ */ jsx(TableBody, { children: detailRows.map((row) => /* @__PURE__ */ jsxs(TableRow, {
595
+ "data-row": row.key,
596
+ children: [/* @__PURE__ */ jsx(TableCell, { children: row.label }), /* @__PURE__ */ jsx(TableCell, {
597
+ className: cn("text-right tabular-nums", row.tone && row.tone !== "neutral" && cn("font-medium", toneTextClasses[row.tone])),
598
+ children: row.value
599
+ })]
600
+ }, row.key)) })
601
+ ]
602
+ })
603
+ }),
604
+ incidentRows.length > 0 ? /* @__PURE__ */ jsx(TableContainer, {
605
+ variant: "plain",
606
+ tabIndex: 0,
607
+ role: "region",
608
+ "aria-label": labels.incidentTableCaption(name),
609
+ className: "max-h-[min(12rem,calc(var(--available-height)-16rem))] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring",
610
+ "data-part": "incident-table",
611
+ children: /* @__PURE__ */ jsxs(Table, {
612
+ size: "sm",
613
+ stickyHeader: true,
614
+ hoverable: false,
615
+ children: [
616
+ /* @__PURE__ */ jsx(TableCaption, {
617
+ side: "top",
618
+ className: "sr-only",
619
+ children: labels.incidentTableCaption(name)
620
+ }),
621
+ /* @__PURE__ */ jsx(TableHeader, { children: /* @__PURE__ */ jsxs(TableRow, { children: [
622
+ /* @__PURE__ */ jsx(TableHead, { children: labels.incidentTableWhen }),
623
+ /* @__PURE__ */ jsx(TableHead, { children: labels.incidentTableLevel }),
624
+ /* @__PURE__ */ jsx(TableHead, {
625
+ className: "text-right",
626
+ children: labels.incidentTableFor
627
+ })
628
+ ] }) }),
629
+ /* @__PURE__ */ jsx(TableBody, { children: incidentRows.map((row) => /* @__PURE__ */ jsxs(TableRow, {
630
+ "data-row": row.key,
631
+ "data-level": row.level,
632
+ children: [
633
+ /* @__PURE__ */ jsxs(TableCell, { children: [/* @__PURE__ */ jsx("span", {
634
+ className: "tabular-nums",
635
+ children: row.when
636
+ }), row.label && /* @__PURE__ */ jsx("span", {
637
+ className: "block text-muted-foreground text-xs",
638
+ children: row.label
639
+ })] }),
640
+ /* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsx(StatusKey, {
641
+ level: row.level,
642
+ label: row.levelName,
643
+ color: tokens?.status[row.level],
644
+ className: "whitespace-nowrap"
645
+ }) }),
646
+ /* @__PURE__ */ jsx(TableCell, {
647
+ className: "text-right tabular-nums",
648
+ children: row.duration
649
+ })
650
+ ]
651
+ }, row.key)) })
652
+ ]
653
+ })
654
+ }) : /* @__PURE__ */ jsx("p", {
655
+ className: captionClasses,
656
+ children: labels.noIncidents
657
+ })
658
+ ]
659
+ })]
660
+ }),
661
+ action
662
+ ]
663
+ })]
664
+ }),
665
+ /* @__PURE__ */ jsx("p", {
666
+ id: descriptionId,
667
+ className: "sr-only",
668
+ children: cardDescription
669
+ }),
670
+ /* @__PURE__ */ jsxs("div", {
671
+ className: "relative flex min-w-0 flex-col",
672
+ style: { minHeight: bodyMinHeight },
673
+ children: [
674
+ state === "loading" && /* @__PURE__ */ jsxs(SkeletonGroup, {
675
+ className: "flex flex-col",
676
+ children: [
677
+ /* @__PURE__ */ jsxs("div", {
678
+ className: cn("flex min-w-0 items-start justify-between gap-2", "mb-2"),
679
+ style: { minHeight: headlineMinHeight },
680
+ children: [/* @__PURE__ */ jsxs("div", {
681
+ className: "flex w-3/5 flex-col gap-1",
682
+ children: [/* @__PURE__ */ jsx(Skeleton, {
683
+ variant: "rounded",
684
+ className: "w-2/3",
685
+ style: { height: sizes.valueLinePx }
686
+ }), /* @__PURE__ */ jsx(Skeleton, {
687
+ variant: "rounded",
688
+ className: "w-24 max-w-full",
689
+ style: { height: sizes.subLinePx }
690
+ })]
691
+ }), /* @__PURE__ */ jsxs("div", {
692
+ className: "flex w-2/5 flex-col items-end gap-1",
693
+ children: [/* @__PURE__ */ jsx(Skeleton, {
694
+ variant: "rounded",
695
+ className: "w-20 max-w-full",
696
+ style: { height: sizes.deltaLinePx }
697
+ }), /* @__PURE__ */ jsx(Skeleton, {
698
+ variant: "rounded",
699
+ className: "w-full",
700
+ style: { height: sizes.comparisonLinePx }
701
+ })]
702
+ })]
703
+ }),
704
+ /* @__PURE__ */ jsxs("div", {
705
+ className: "flex flex-col gap-1",
706
+ children: [
707
+ /* @__PURE__ */ jsx(Skeleton, {
708
+ variant: "rounded",
709
+ className: "w-full",
710
+ style: { height: plotHeight }
711
+ }),
712
+ /* @__PURE__ */ jsxs("div", {
713
+ className: "flex items-center justify-between",
714
+ style: { minHeight: sizes.captionLinePx },
715
+ children: [
716
+ /* @__PURE__ */ jsx(Skeleton, {
717
+ variant: "rounded",
718
+ className: "w-12",
719
+ style: { height: sizes.captionLinePx - 4 }
720
+ }),
721
+ /* @__PURE__ */ jsx(Skeleton, {
722
+ variant: "rounded",
723
+ className: "w-20",
724
+ style: { height: sizes.captionLinePx - 4 }
725
+ }),
726
+ /* @__PURE__ */ jsx(Skeleton, {
727
+ variant: "rounded",
728
+ className: "w-12",
729
+ style: { height: sizes.captionLinePx - 4 }
730
+ })
731
+ ]
732
+ }),
733
+ legend && /* @__PURE__ */ jsx(Skeleton, {
734
+ variant: "rounded",
735
+ className: "w-2/3",
736
+ style: { height: sizes.keyLinePx * KEY_LINES }
737
+ })
738
+ ]
739
+ }),
740
+ reserveInsight && /* @__PURE__ */ jsxs("div", {
741
+ className: "mt-2 flex items-start gap-2",
742
+ children: [/* @__PURE__ */ jsx(Skeleton, {
743
+ variant: "rounded",
744
+ className: "size-4 shrink-0"
745
+ }), /* @__PURE__ */ jsx(Skeleton, {
746
+ variant: "rounded",
747
+ className: "w-full",
748
+ style: { height: sizes.comparisonLinePx }
749
+ })]
750
+ })
751
+ ]
752
+ }),
753
+ state === "error" && /* @__PURE__ */ jsx(SystemState, {
754
+ variant: "server-error",
755
+ scope: "inline",
756
+ title: labels.error,
757
+ description: false,
758
+ action: onRetry ? /* @__PURE__ */ jsx(Button, {
759
+ size: "sm",
760
+ onClick: onRetry,
761
+ children: labels.retry
762
+ }) : void 0,
763
+ className: cn(tileStateClasses, "my-auto")
764
+ }),
765
+ state === "empty" && /* @__PURE__ */ jsx(SystemState, {
766
+ variant: "empty",
767
+ scope: "inline",
768
+ title: labels.noData,
769
+ description: false,
770
+ className: cn(tileStateClasses, "my-auto")
771
+ }),
772
+ state === "no-match" && /* @__PURE__ */ jsx(SystemState, {
773
+ variant: "no-results",
774
+ scope: "inline",
775
+ title: labels.noMatch,
776
+ description: false,
777
+ action: onClearFilters ? /* @__PURE__ */ jsx(Button, {
778
+ variant: "outline",
779
+ size: "sm",
780
+ onClick: onClearFilters,
781
+ children: labels.clearFilters
782
+ }) : void 0,
783
+ className: cn(tileStateClasses, "my-auto")
784
+ }),
785
+ showContent && currentLevel && /* @__PURE__ */ jsxs("div", {
786
+ className: "flex min-w-0 flex-col",
787
+ children: [
788
+ /* @__PURE__ */ jsxs("div", {
789
+ className: cn("flex min-w-0 items-start justify-between gap-2", showChip && "mb-2"),
790
+ style: { minHeight: headlineMinHeight },
791
+ "data-part": "headline",
792
+ children: [/* @__PURE__ */ jsxs("div", {
793
+ className: headlineValueClasses,
794
+ "data-part": "value",
795
+ children: [bigIsLevel ? /* @__PURE__ */ jsxs("span", {
796
+ className: "flex min-w-0 items-center gap-2",
797
+ role: "status",
798
+ "aria-label": `${labels.levelGroup(name)}: ${labels.levelNames[currentLevel]}`,
799
+ "data-part": "level",
800
+ "data-level": currentLevel,
801
+ children: [/* @__PURE__ */ jsx(LevelGlyph, {
802
+ level: currentLevel,
803
+ className: cn("shrink-0", sizes.glyph, levelTextClasses[currentLevel])
804
+ }), /* @__PURE__ */ jsx("span", {
805
+ className: cn(valueClasses, sizes.value, levelTextClasses[currentLevel], "min-w-0 wrap-break-word"),
806
+ children: labels.levelNames[currentLevel]
807
+ })]
808
+ }) : /* @__PURE__ */ jsx("span", {
809
+ className: cn(valueClasses, sizes.value, "min-w-0 tabular-nums wrap-break-word"),
810
+ "data-part": "uptime",
811
+ children: uptimeText
812
+ }), showChip && (bigIsLevel ? /* @__PURE__ */ jsx("span", {
813
+ className: "min-w-0 max-w-full truncate text-muted-foreground text-xs tabular-nums",
814
+ "data-part": "hold",
815
+ children: holdText
816
+ }) : /* @__PURE__ */ jsxs(Badge, {
817
+ variant: levelBadgeVariant[currentLevel],
818
+ appearance: "soft",
819
+ size: sizes.chip,
820
+ role: "status",
821
+ "aria-label": `${labels.levelGroup(name)}: ${labels.levelNames[currentLevel]}`,
822
+ "data-part": "level",
823
+ "data-level": currentLevel,
824
+ children: [/* @__PURE__ */ jsx(LevelGlyph, { level: currentLevel }), labels.levelNames[currentLevel]]
825
+ }))]
826
+ }), hasBadge && run && /* @__PURE__ */ jsxs(Tooltip, { children: [/* @__PURE__ */ jsxs(TooltipTrigger, {
827
+ delay: 150,
828
+ render: /* @__PURE__ */ jsx("p", {
829
+ tabIndex: 0,
830
+ role: "group",
831
+ "aria-label": labels.uptimeGroup(name),
832
+ "aria-describedby": explanationId,
833
+ className: cn(deltaStackClasses, sizes.body),
834
+ "data-part": "delta",
835
+ "data-kind": bigIsLevel ? "uptime" : "verdict"
836
+ }),
837
+ children: [
838
+ /* @__PURE__ */ jsx("span", {
839
+ id: explanationId,
840
+ className: "sr-only",
841
+ children: explanation
842
+ }),
843
+ /* @__PURE__ */ jsx(Badge, {
844
+ variant: polarityBadgeVariant[run.sla ? run.polarity : "neutral"],
845
+ appearance: "soft",
846
+ size: sizes.badge,
847
+ className: "tabular-nums",
848
+ children: bigIsLevel ? uptimeText : verdict ? labels.verdictNames[verdict] : uptimeText
849
+ }),
850
+ /* @__PURE__ */ jsx("span", {
851
+ className: "max-w-full truncate text-muted-foreground text-xs",
852
+ ...verdict ? {
853
+ role: "status",
854
+ "aria-label": `${labels.uptimeGroup(name)}: ${labels.verdictNames[verdict]}`,
855
+ "data-part": "verdict",
856
+ "data-verdict": verdict
857
+ } : {},
858
+ children: run.sla ? labels.vsTarget(formatters.formatUptime(run.sla.target), run.sla.verdict === "met") : labels.uptimeOver(formatters.formatDuration(run.window.span))
859
+ })
860
+ ]
861
+ }), /* @__PURE__ */ jsx(TooltipPopup, {
862
+ arrow: false,
863
+ side: "bottom",
864
+ align: "end",
865
+ sideOffset: 8,
866
+ collisionPadding: 8,
867
+ container: popoverContainer,
868
+ className: "text-left",
869
+ "data-part": "delta-tooltip",
870
+ children: /* @__PURE__ */ jsx(ArcTooltipRows, { rows: explanationRows })
871
+ })] })]
872
+ }),
873
+ /* @__PURE__ */ jsxs("div", {
874
+ className: "flex min-w-0 flex-col gap-1",
875
+ children: [
876
+ /* @__PURE__ */ jsx("div", {
877
+ ref: plotRef,
878
+ className: "relative w-full",
879
+ style: { height: plotHeight },
880
+ "data-part": "plot",
881
+ children: run ? plotWidth > 0 && spec && datasets ? /* @__PURE__ */ jsx(ArcVegaChart, {
882
+ spec,
883
+ options: embedOptions,
884
+ datasets,
885
+ description: chartDescription,
886
+ width: plotWidth,
887
+ height: plotHeight,
888
+ onEmbed,
889
+ className: "absolute inset-0 [&_svg]:block [&_.vega-bindings:empty]:hidden",
890
+ fallback: /* @__PURE__ */ jsx(Skeleton, {
891
+ variant: "rounded",
892
+ className: "size-full"
893
+ })
894
+ }) : /* @__PURE__ */ jsx(Skeleton, {
895
+ variant: "rounded",
896
+ className: "size-full"
897
+ }) : /* @__PURE__ */ jsx("p", {
898
+ className: cn(captionClasses, "flex h-full items-center"),
899
+ "data-part": "no-history",
900
+ children: labels.noHistory
901
+ })
902
+ }),
903
+ run && /* @__PURE__ */ jsxs("div", {
904
+ className: "flex min-w-0 items-baseline justify-between gap-2 text-muted-foreground text-xs tabular-nums",
905
+ style: { minHeight: sizes.captionLinePx },
906
+ "data-part": "caption",
907
+ children: [
908
+ /* @__PURE__ */ jsx("span", {
909
+ className: "shrink-0",
910
+ "data-part": "window-start",
911
+ children: formatters.formatInstant(run.window.start, strip?.axisGranularity ?? "day-short")
912
+ }),
913
+ /* @__PURE__ */ jsx("span", {
914
+ className: cn("min-w-0 truncate text-center", overBudget && "font-medium text-chart-negative"),
915
+ "data-part": "summary",
916
+ children: run.incidents.length > 0 ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("span", {
917
+ "data-part": "incidents",
918
+ children: labels.incidents(String(run.incidents.length), run.incidents.length)
919
+ }), size !== "sm" && run.downtime > 0 && /* @__PURE__ */ jsxs(Fragment$1, { children: [" · ", /* @__PURE__ */ jsx("span", {
920
+ "data-part": "downtime",
921
+ children: labels.downFor(formatters.formatDuration(run.downtime))
922
+ })] })] }) : labels.noIncidents
923
+ }),
924
+ /* @__PURE__ */ jsx("span", {
925
+ className: "shrink-0",
926
+ "data-part": "window-end",
927
+ children: formatters.formatInstant(run.window.end, strip?.axisGranularity ?? "day-short")
928
+ })
929
+ ]
930
+ }),
931
+ reserveKey && /* @__PURE__ */ jsxs("div", {
932
+ className: "flex min-w-0 flex-wrap items-center gap-x-3 gap-y-0.5 text-muted-foreground text-xs",
933
+ style: { minHeight: sizes.keyLinePx * KEY_LINES },
934
+ "data-part": "chart-legend",
935
+ children: [breakdown.map((entry) => /* @__PURE__ */ jsx(StatusKey, {
936
+ level: entry.level,
937
+ color: tokens?.status[entry.level],
938
+ label: entry.name
939
+ }, entry.level)), resolutionText && /* @__PURE__ */ jsx("span", {
940
+ "data-part": "resolution",
941
+ children: resolutionText
942
+ })]
943
+ })
944
+ ]
945
+ }),
946
+ reserveInsight && /* @__PURE__ */ jsxs("div", {
947
+ className: cn("mt-2 flex items-start gap-2 font-sans text-foreground", sizes.body),
948
+ "data-part": "insight",
949
+ children: [/* @__PURE__ */ jsx(AILoader, {
950
+ size: "sm",
951
+ state: "default",
952
+ label: labels.insightMark,
953
+ className: cn("shrink-0", size === "sm" ? "" : "mt-0.5")
954
+ }), /* @__PURE__ */ jsx("p", {
955
+ className: "min-w-0 flex-1 [&_strong]:font-semibold [&_strong]:text-foreground text-xs leading-[1.8]",
956
+ children: insight
957
+ })]
958
+ })
959
+ ]
960
+ }),
961
+ state === "refreshing" && /* @__PURE__ */ jsx("div", {
962
+ "aria-hidden": "true",
963
+ className: "absolute -inset-1 rounded-md bg-veil"
964
+ })
965
+ ]
966
+ }),
967
+ asOfValid && asOfDate && /* @__PURE__ */ jsx("p", {
968
+ className: cn(captionClasses, "mt-1 text-right"),
969
+ "data-part": "footer",
970
+ children: /* @__PURE__ */ jsx("span", {
971
+ "data-part": "as-of",
972
+ children: /* @__PURE__ */ jsx("time", {
973
+ dateTime: asOfDate.toISOString(),
974
+ children: asOfText
975
+ })
976
+ })
977
+ }),
978
+ /* @__PURE__ */ jsx("div", {
979
+ ref: setPopoverContainer,
980
+ className: "pointer-events-none absolute inset-0",
981
+ "data-part": "popover-host"
982
+ }),
983
+ tooltip
984
+ ]
985
+ });
986
+ });
987
+ StatusCard.displayName = "StatusCard";
988
+ //#endregion
989
+ export { StatusCard };