@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,1293 @@
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 { METRIC_CONTEXT_DATASET, METRIC_HIGHLIGHT_DATASET, METRIC_HIGHLIGHT_POINTS_DATASET, METRIC_HIGHLIGHT_ROWS_DATASET, METRIC_LATEST_DATASET, METRIC_REFERENCE_DATASET, METRIC_TREND_DATASET, buildMetricTrendSpec } from "./MetricCard.chart.js";
7
+ import { METRIC_PREVIOUS_KEY, axisGranularity, buildHighlightDatasets, buildHighlightDetails, buildHighlightInsight, buildMetricChartDescription, buildMetricDescription, createMetricFormatters, deriveDelta, deriveMetricState, deriveTarget, describeComparisons, normalizeComparisons, normalizeTrend, resolveComparison, resolveHighlight, resolveMetricLabels } from "./MetricCard.model.js";
8
+ import { Fragment, forwardRef, useCallback, useEffect, useId, useMemo, useRef, useState } from "react";
9
+ import { AILoader, Badge, Box, Button, Menu, MenuGroupLabel, MenuPopup, MenuRadioGroup, MenuRadioItem, MenuSeparator, MenuTrigger, Meter, Popover, PopoverDescription, 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/MetricCard/MetricCard.tsx
12
+ const sizeStyles = {
13
+ sm: {
14
+ padding: "sm",
15
+ gap: "gap-2",
16
+ gapPx: 8,
17
+ label: "text-xs",
18
+ value: "text-2xl leading-8",
19
+ valueLinePx: 32,
20
+ unit: "text-xs",
21
+ body: "text-xs",
22
+ badge: "sm",
23
+ deltaLinePx: 20,
24
+ comparisonLinePx: 16,
25
+ trendHeight: 32
26
+ },
27
+ md: {
28
+ padding: "md",
29
+ gap: "gap-2",
30
+ gapPx: 8,
31
+ label: "text-sm",
32
+ value: "text-3xl leading-9",
33
+ valueLinePx: 36,
34
+ unit: "text-sm",
35
+ body: "text-sm",
36
+ badge: "md",
37
+ deltaLinePx: 24,
38
+ comparisonLinePx: 20,
39
+ trendHeight: 40
40
+ },
41
+ lg: {
42
+ padding: "lg",
43
+ gap: "gap-2",
44
+ gapPx: 8,
45
+ label: "text-sm",
46
+ value: "text-4xl leading-10",
47
+ valueLinePx: 40,
48
+ unit: "text-base",
49
+ body: "text-sm",
50
+ badge: "lg",
51
+ deltaLinePx: 28,
52
+ comparisonLinePx: 20,
53
+ trendHeight: 56
54
+ }
55
+ };
56
+ const polarityTextClasses = {
57
+ positive: "text-chart-positive",
58
+ negative: "text-chart-negative",
59
+ neutral: "text-muted-foreground"
60
+ };
61
+ const TARGET_BLOCK_PX = 52;
62
+ const labelClasses = "min-w-0 font-sans font-medium text-muted-foreground";
63
+ const valueClasses = "font-heading font-semibold tracking-tight text-foreground";
64
+ const captionClasses = "font-sans text-xs text-muted-foreground mt-1";
65
+ const polarityBadgeVariant = {
66
+ positive: "success",
67
+ negative: "destructive",
68
+ neutral: "neutral"
69
+ };
70
+ const deltaStackClasses = "ms-auto flex min-w-0 max-w-1/2 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";
71
+ const deltaButtonClasses = "group cursor-pointer";
72
+ const menuGridClasses = "grid grid-cols-[minmax(0,1fr)_auto_auto_auto] gap-x-2";
73
+ const menuRowClasses = "col-span-4 grid grid-cols-subgrid items-center";
74
+ const menuFigureClasses = "text-right tabular-nums whitespace-nowrap";
75
+ const changeTextClasses = {
76
+ positive: "text-chart-positive",
77
+ negative: "text-chart-negative",
78
+ neutral: "text-foreground"
79
+ };
80
+ const headerControlClasses = "size-6 min-w-0 text-muted-foreground hover:text-foreground";
81
+ /** Match the plot's mark shape so its meaning never depends on color alone. */
82
+ function MetricTrendKey({ label, mark, color }) {
83
+ return /* @__PURE__ */ jsxs("span", {
84
+ className: "inline-flex items-center gap-2",
85
+ children: [/* @__PURE__ */ jsx("svg", {
86
+ width: "24",
87
+ height: "12",
88
+ viewBox: "0 0 24 12",
89
+ fill: "none",
90
+ "aria-hidden": "true",
91
+ className: "shrink-0",
92
+ style: { color },
93
+ children: mark === "bar" ? /* @__PURE__ */ jsx("rect", {
94
+ x: "7",
95
+ y: "1",
96
+ width: "10",
97
+ height: "10",
98
+ rx: "1",
99
+ fill: "currentColor"
100
+ }) : /* @__PURE__ */ jsxs(Fragment$1, { children: [mark === "area" && /* @__PURE__ */ jsx("rect", {
101
+ x: "1",
102
+ y: "6",
103
+ width: "22",
104
+ height: "5",
105
+ fill: "currentColor",
106
+ opacity: "0.12"
107
+ }), /* @__PURE__ */ jsx("line", {
108
+ x1: "2",
109
+ y1: "6",
110
+ x2: "22",
111
+ y2: "6",
112
+ stroke: "currentColor",
113
+ strokeWidth: mark === "target" ? 1.5 : 2,
114
+ strokeLinecap: "round",
115
+ strokeDasharray: mark === "target" ? "0 4" : void 0
116
+ })] })
117
+ }), label]
118
+ });
119
+ }
120
+ /** A generated insight: words as text, values in bold. */
121
+ function InsightText({ segments }) {
122
+ return /* @__PURE__ */ jsx(Fragment$1, { children: segments.map((segment, index) => typeof segment === "string" ? /* @__PURE__ */ jsx(Fragment, { children: segment }, index) : /* @__PURE__ */ jsx("strong", { children: segment.value }, index)) });
123
+ }
124
+ /**
125
+ * Label → value rows on the popover surface — the light-surface counterpart
126
+ * of `ArcTooltipRows`: muted keys, tabular values, an optional class per
127
+ * value for a change's polarity tone.
128
+ */
129
+ function DetailRows({ rows, className, ...rest }) {
130
+ return /* @__PURE__ */ jsx("dl", {
131
+ className: cn("m-0 flex flex-col gap-1 font-sans text-xs", className),
132
+ ...rest,
133
+ children: rows.map(([label, value, valueClassName], index) => /* @__PURE__ */ jsxs("div", {
134
+ className: "flex items-baseline justify-between gap-3",
135
+ children: [/* @__PURE__ */ jsx("dt", {
136
+ className: "min-w-0 text-muted-foreground",
137
+ children: label
138
+ }), /* @__PURE__ */ jsx("dd", {
139
+ className: cn("m-0 shrink-0 font-medium text-foreground tabular-nums", valueClassName),
140
+ children: value
141
+ })]
142
+ }, index))
143
+ });
144
+ }
145
+ function highlightHue(tokens, polarity) {
146
+ return polarity === "positive" ? tokens.divergingPositive : polarity === "negative" ? tokens.divergingNegative : tokens.emphasis;
147
+ }
148
+ const tileStateClasses = "w-full max-w-none gap-2 px-2 py-2 [--artwork-box:3rem]";
149
+ const X_AXIS_HEIGHT_PX = 24;
150
+ const MISSING_NAME = "Metric";
151
+ function InfoIcon(props) {
152
+ return /* @__PURE__ */ jsxs("svg", {
153
+ viewBox: "0 0 24 24",
154
+ fill: "none",
155
+ stroke: "currentColor",
156
+ strokeWidth: 2,
157
+ strokeLinecap: "round",
158
+ strokeLinejoin: "round",
159
+ "aria-hidden": "true",
160
+ ...props,
161
+ children: [/* @__PURE__ */ jsx("circle", {
162
+ cx: "12",
163
+ cy: "12",
164
+ r: "9"
165
+ }), /* @__PURE__ */ jsx("path", { d: "M12 11v5M12 8h.01" })]
166
+ });
167
+ }
168
+ function DeltaGlyph({ direction, ...props }) {
169
+ return /* @__PURE__ */ jsxs("svg", {
170
+ viewBox: "0 0 24 24",
171
+ fill: "none",
172
+ stroke: "currentColor",
173
+ strokeWidth: 2.5,
174
+ strokeLinecap: "round",
175
+ strokeLinejoin: "round",
176
+ "aria-hidden": "true",
177
+ ...props,
178
+ children: [
179
+ direction === "up" && /* @__PURE__ */ jsx("path", { d: "M7 17 17 7M7 7h10v10" }),
180
+ direction === "down" && /* @__PURE__ */ jsx("path", { d: "M7 7 17 17M7 17h10V7" }),
181
+ direction === "flat" && /* @__PURE__ */ jsx("path", { d: "M5 12h14M13 6l6 6-6 6" })
182
+ ]
183
+ });
184
+ }
185
+ function ChevronDownIcon(props) {
186
+ return /* @__PURE__ */ jsx("svg", {
187
+ viewBox: "0 0 24 24",
188
+ fill: "none",
189
+ stroke: "currentColor",
190
+ strokeWidth: 2,
191
+ strokeLinecap: "round",
192
+ strokeLinejoin: "round",
193
+ "aria-hidden": "true",
194
+ ...props,
195
+ children: /* @__PURE__ */ jsx("path", { d: "m6 9 6 6 6-6" })
196
+ });
197
+ }
198
+ function useMergedRef(forwarded) {
199
+ const inner = useRef(null);
200
+ return [inner, useCallback((node) => {
201
+ inner.current = node;
202
+ if (typeof forwarded === "function") forwarded(node);
203
+ else if (forwarded) forwarded.current = node;
204
+ }, [forwarded])];
205
+ }
206
+ function usePlotWidth(ref, enabled) {
207
+ const [width, setWidth] = useState(0);
208
+ useEffect(() => {
209
+ if (!enabled) return;
210
+ const el = ref.current;
211
+ if (!el) return;
212
+ let frame = 0;
213
+ const measure = () => {
214
+ const next = Math.round(el.getBoundingClientRect().width);
215
+ setWidth((prev) => prev === next ? prev : next);
216
+ };
217
+ measure();
218
+ if (typeof ResizeObserver === "undefined") return;
219
+ const observer = new ResizeObserver(() => {
220
+ cancelAnimationFrame(frame);
221
+ frame = requestAnimationFrame(measure);
222
+ });
223
+ observer.observe(el);
224
+ return () => {
225
+ cancelAnimationFrame(frame);
226
+ observer.disconnect();
227
+ };
228
+ }, [ref, enabled]);
229
+ return width;
230
+ }
231
+ /**
232
+ * A metric tile for dashboard grids: the headline value, its comparison
233
+ * against the previous period and/or a target, a sparkline of the recent
234
+ * readings, and every loading, empty, error and stale state — layout-stable,
235
+ * with a generated text equivalent and a data table in an info popover. The
236
+ * `highlight` variant makes one window of the trend the subject: the headline
237
+ * and delta derive from the window's readings and the sparkline paints it in
238
+ * the polarity hue on a gray context.
239
+ */
240
+ const MetricCard = forwardRef(({ variant = "default", highlight, highlightDetails = true, defaultHighlightDetailsOpen = false, label, name: nameProp, hint, value, format = "compact", formatValue, unit, previousValue, comparisonLabel, comparisons, comparison, defaultComparison, onComparisonChange, selectable = true, deltaMode = "percent", goodDirection = "up", target, trend, trendMark = "line", trendScale = "auto", trendAxes = "x", trendHeight: trendHeightProp, trendGranularity, insight, status = "ready", filtered = false, stale = false, updatedAt, updatedAtFormat = "day", onRetry, onClearFilters, size = "md", titleLevel = 3, locale, timeZone, labels: labelOverrides, description, action, defaultTableOpen = false, hideTableToggle = false, onEmbed, patchSpec, render, className, ...rest }, forwardedRef) => {
241
+ const labels = useMemo(() => resolveMetricLabels(labelOverrides), [labelOverrides]);
242
+ const sizes = sizeStyles[size];
243
+ const showXAxis = trendAxes === "x" || trendAxes === "both";
244
+ const trendHeight = trendHeightProp ?? sizes.trendHeight + (showXAxis ? X_AXIS_HEIGHT_PX : 0);
245
+ const name = nameProp ?? (typeof label === "string" ? label : MISSING_NAME);
246
+ const isHighlight = variant === "highlight";
247
+ const id = useId();
248
+ const headingId = `${id}-label`;
249
+ const descriptionId = `${id}-description`;
250
+ const hintId = `${id}-hint`;
251
+ const tableId = `${id}-table`;
252
+ const targetExplanationId = `${id}-target-explanation`;
253
+ const deltaExplanationId = `${id}-delta-explanation`;
254
+ const [rootRef, setRootRef] = useMergedRef(forwardedRef);
255
+ const plotRef = useRef(null);
256
+ const [tableOpen, setTableOpen] = useState(defaultTableOpen);
257
+ const [highlightDetailsOpen, setHighlightDetailsOpen] = useState(defaultHighlightDetailsOpen);
258
+ const [popoverContainer, setPopoverContainer] = useState(null);
259
+ const hasComparisons = comparisons !== void 0;
260
+ const comparisonRows = useMemo(() => normalizeComparisons(comparisons), [comparisons]);
261
+ const isComparisonControlled = comparison !== void 0;
262
+ const [innerComparison, setInnerComparison] = useState(defaultComparison);
263
+ const comparisonKey = isComparisonControlled ? comparison : innerComparison;
264
+ const selectedComparison = useMemo(() => hasComparisons ? resolveComparison(comparisonRows, comparisonKey) : null, [
265
+ hasComparisons,
266
+ comparisonRows,
267
+ comparisonKey
268
+ ]);
269
+ const baselineValue = hasComparisons ? selectedComparison?.value : previousValue;
270
+ const pendingAnnounce = useRef(false);
271
+ const [announcement, setAnnouncement] = useState("");
272
+ const selectComparison = useCallback((key) => {
273
+ pendingAnnounce.current = true;
274
+ if (!isComparisonControlled) setInnerComparison(key);
275
+ onComparisonChange?.(key);
276
+ }, [isComparisonControlled, onComparisonChange]);
277
+ const summary = useMemo(() => normalizeTrend(trend, trendGranularity), [trend, trendGranularity]);
278
+ const formatters = useMemo(() => createMetricFormatters({
279
+ format,
280
+ locale,
281
+ timeZone,
282
+ formatValue,
283
+ xType: summary?.xType ?? "temporal",
284
+ granularity: summary?.granularity ?? trendGranularity ?? "day"
285
+ }), [
286
+ format,
287
+ locale,
288
+ timeZone,
289
+ formatValue,
290
+ summary,
291
+ trendGranularity
292
+ ]);
293
+ const highlightStart = highlight?.start;
294
+ const highlightEnd = highlight?.end;
295
+ const highlightLabel = highlight?.label;
296
+ const highlightInfo = useMemo(() => isHighlight && highlightStart != null && highlightEnd != null ? resolveHighlight(summary, {
297
+ start: highlightStart,
298
+ end: highlightEnd,
299
+ label: highlightLabel
300
+ }, {
301
+ deltaMode,
302
+ goodDirection,
303
+ format,
304
+ locale,
305
+ percentagePoints: labels.percentagePoints,
306
+ formatters
307
+ }) : null, [
308
+ isHighlight,
309
+ summary,
310
+ highlightStart,
311
+ highlightEnd,
312
+ highlightLabel,
313
+ deltaMode,
314
+ goodDirection,
315
+ format,
316
+ locale,
317
+ labels.percentagePoints,
318
+ formatters
319
+ ]);
320
+ const highlightActive = isHighlight && highlightInfo != null;
321
+ const headlineValue = isHighlight ? highlightInfo?.end.y ?? summary?.latest?.y ?? null : value;
322
+ const hasValue = typeof headlineValue === "number" && Number.isFinite(headlineValue);
323
+ const hasData = hasValue || (summary?.count ?? 0) > 0;
324
+ const state = deriveMetricState({
325
+ status,
326
+ hasValue,
327
+ hasData,
328
+ filtered
329
+ });
330
+ const showContent = state === "ready" || state === "refreshing";
331
+ const hasTable = showContent && summary != null && summary.rows.length > 0;
332
+ const delta = useMemo(() => isHighlight ? highlightInfo?.delta ?? null : deriveDelta(headlineValue, baselineValue, {
333
+ deltaMode,
334
+ goodDirection,
335
+ format,
336
+ locale,
337
+ percentagePoints: labels.percentagePoints
338
+ }), [
339
+ isHighlight,
340
+ highlightInfo,
341
+ headlineValue,
342
+ baselineValue,
343
+ deltaMode,
344
+ goodDirection,
345
+ format,
346
+ locale,
347
+ labels.percentagePoints
348
+ ]);
349
+ const targetInfo = useMemo(() => deriveTarget(headlineValue, target, {
350
+ goodDirection,
351
+ format,
352
+ locale,
353
+ formatValue
354
+ }), [
355
+ headlineValue,
356
+ target,
357
+ goodDirection,
358
+ format,
359
+ locale,
360
+ formatValue
361
+ ]);
362
+ const targetExplanationRows = targetInfo ? labels.targetExplanation(targetInfo) : [];
363
+ const targetExplanation = targetExplanationRows.map(([key, value]) => `${key}: ${value}`).join(". ");
364
+ const valueText = formatters.formatY(headlineValue);
365
+ const comparisonText = isHighlight ? highlightInfo?.label ?? highlightInfo?.rangeText ?? "" : hasComparisons ? selectedComparison ? labels.versus(selectedComparison.label) : labels.compareWith : typeof comparisonLabel === "string" ? comparisonLabel : labels.previousPeriod;
366
+ const comparisonNode = !isHighlight && !hasComparisons && comparisonLabel != null ? comparisonLabel : comparisonText || null;
367
+ const deltaExplanationRows = delta ? labels.deltaExplanation({
368
+ kind: isHighlight ? "window" : "period",
369
+ previousText: formatters.formatY(isHighlight ? highlightInfo?.start.y : baselineValue),
370
+ previousLabel: !isHighlight && hasComparisons ? selectedComparison?.label ?? null : null,
371
+ currentText: valueText,
372
+ changeText: delta.text,
373
+ secondaryText: delta.secondaryText,
374
+ renderedMode: delta.renderedMode,
375
+ direction: delta.direction,
376
+ comparisonText,
377
+ periodText: isHighlight ? highlightInfo?.rangeText ?? null : null
378
+ }) : [];
379
+ const deltaExplanation = deltaExplanationRows.map(([key, value]) => `${key}: ${value}`).join(". ");
380
+ const asOfDate = updatedAt == null ? null : updatedAt instanceof Date ? updatedAt : new Date(updatedAt);
381
+ const asOfValid = asOfDate != null && !Number.isNaN(asOfDate.getTime());
382
+ const asOfText = asOfValid ? typeof updatedAtFormat === "function" ? updatedAtFormat(asOfDate) : formatDate(asOfDate, {
383
+ granularity: updatedAtFormat,
384
+ locale,
385
+ timeZone
386
+ }) : void 0;
387
+ const hasChart = summary != null && summary.count >= 2;
388
+ const insufficient = showContent && summary != null && !hasChart;
389
+ const cardDescription = description ?? buildMetricDescription({
390
+ name,
391
+ state,
392
+ valueText,
393
+ unit: typeof unit === "string" ? unit : void 0,
394
+ delta,
395
+ comparisonText,
396
+ target: targetInfo,
397
+ trend: summary,
398
+ formatters,
399
+ asOfText,
400
+ labels,
401
+ highlight: highlightActive ? highlightInfo : null
402
+ });
403
+ useEffect(() => {
404
+ if (!pendingAnnounce.current) return;
405
+ pendingAnnounce.current = false;
406
+ setAnnouncement(cardDescription);
407
+ }, [cardDescription]);
408
+ const hasPreviousValue = typeof previousValue === "number" && Number.isFinite(previousValue);
409
+ const previousLabel = labels.previous;
410
+ const menuRows = useMemo(() => hasComparisons ? comparisonRows : hasPreviousValue ? [{
411
+ key: METRIC_PREVIOUS_KEY,
412
+ label: previousLabel,
413
+ value: previousValue
414
+ }] : [], [
415
+ hasComparisons,
416
+ comparisonRows,
417
+ hasPreviousValue,
418
+ previousLabel,
419
+ previousValue
420
+ ]);
421
+ const showComparisonMenu = !isHighlight && selectable && (!isComparisonControlled || onComparisonChange != null) && menuRows.length > 0;
422
+ const comparisonCandidates = useMemo(() => showComparisonMenu ? describeComparisons(menuRows, headlineValue, {
423
+ deltaMode,
424
+ goodDirection,
425
+ format,
426
+ locale,
427
+ percentagePoints: labels.percentagePoints,
428
+ formatters
429
+ }) : [], [
430
+ showComparisonMenu,
431
+ menuRows,
432
+ headlineValue,
433
+ deltaMode,
434
+ goodDirection,
435
+ format,
436
+ locale,
437
+ labels.percentagePoints,
438
+ formatters
439
+ ]);
440
+ const showHighlightDetails = highlightActive && highlightDetails;
441
+ const highlightDetailsInfo = useMemo(() => showHighlightDetails && summary && highlightInfo ? buildHighlightDetails(summary, highlightInfo, {
442
+ deltaMode,
443
+ goodDirection,
444
+ format,
445
+ locale,
446
+ percentagePoints: labels.percentagePoints,
447
+ formatters
448
+ }) : null, [
449
+ showHighlightDetails,
450
+ summary,
451
+ highlightInfo,
452
+ deltaMode,
453
+ goodDirection,
454
+ format,
455
+ locale,
456
+ labels.percentagePoints,
457
+ formatters
458
+ ]);
459
+ const tokens = useChartTokens(rootRef);
460
+ const plotWidth = usePlotWidth(plotRef, showContent && hasChart);
461
+ const highlightColor = tokens && highlightActive && highlightInfo ? highlightHue(tokens, highlightInfo.delta.polarity) : void 0;
462
+ const seriesColor = tokens ? highlightActive ? tokens.context : tokens.emphasis : void 0;
463
+ const tooltipContent = useCallback(({ item }) => {
464
+ const raw = item.datum;
465
+ const datum = raw && "datum" in raw && raw.datum ? raw.datum : raw;
466
+ const row = datum && "x" in datum ? datum : null;
467
+ if (!row && !(datum && "value" in datum)) return null;
468
+ const inWindow = highlightActive && highlightInfo != null && row?.hl === true;
469
+ const rows = [];
470
+ if (row) rows.push([labels.tablePeriod, formatters.formatX(row.x)], [/* @__PURE__ */ jsx(MetricTrendKey, {
471
+ label: name,
472
+ mark: trendMark,
473
+ color: inWindow ? highlightColor : seriesColor
474
+ }, "actual"), formatters.formatY(row.y)]);
475
+ if (target != null) rows.push([/* @__PURE__ */ jsx(MetricTrendKey, {
476
+ label: labels.target,
477
+ mark: "target",
478
+ color: tokens?.reference
479
+ }, "target"), formatters.formatY(target)]);
480
+ if (!inWindow || !highlightInfo) return /* @__PURE__ */ jsx(ArcTooltipRows, { rows });
481
+ const windowRows = [];
482
+ if (highlightInfo.label) windowRows.push([labels.highlightRange, highlightInfo.rangeText]);
483
+ windowRows.push([`${labels.highlightStart} · ${formatters.formatX(highlightInfo.start.x)}`, formatters.formatY(highlightInfo.start.y)], [`${labels.highlightEnd} · ${formatters.formatX(highlightInfo.end.x)}`, formatters.formatY(highlightInfo.end.y)], [labels.highlightChange, highlightInfo.absoluteText], [labels.highlightChangePercent, highlightInfo.percentText]);
484
+ return /* @__PURE__ */ jsxs("div", {
485
+ className: "flex flex-col gap-1.5",
486
+ children: [
487
+ /* @__PURE__ */ jsx(ArcTooltipRows, { rows }),
488
+ /* @__PURE__ */ jsx("div", {
489
+ role: "presentation",
490
+ className: "border-t border-background/20"
491
+ }),
492
+ /* @__PURE__ */ jsx("div", {
493
+ className: "font-medium",
494
+ "data-part": "highlight-key",
495
+ children: /* @__PURE__ */ jsx(MetricTrendKey, {
496
+ label: highlightInfo.label ?? highlightInfo.rangeText,
497
+ mark: trendMark,
498
+ color: highlightColor
499
+ })
500
+ }),
501
+ /* @__PURE__ */ jsx(ArcTooltipRows, { rows: windowRows })
502
+ ]
503
+ });
504
+ }, [
505
+ labels,
506
+ formatters,
507
+ name,
508
+ trendMark,
509
+ tokens,
510
+ target,
511
+ highlightActive,
512
+ highlightInfo,
513
+ highlightColor,
514
+ seriesColor
515
+ ]);
516
+ const { handler: tooltipHandler, tooltip } = useArcTooltipHandler({ content: tooltipContent });
517
+ const embedOptions = useMemo(() => arcEmbedOptions({ tooltip: tooltipHandler }), [tooltipHandler]);
518
+ const xType = summary?.xType;
519
+ const granularity = summary?.granularity;
520
+ const hasReference = target != null;
521
+ const periodTitle = labels.tablePeriod;
522
+ const spec = useMemo(() => {
523
+ if (!tokens || !xType || !granularity) return null;
524
+ const timeGrammar = (kind) => [
525
+ kind,
526
+ locale ?? "",
527
+ timeZone ?? ""
528
+ ].join("@").replace(/@+$/, "");
529
+ const built = buildMetricTrendSpec({
530
+ mark: trendMark,
531
+ scale: trendScale,
532
+ xType,
533
+ axes: trendAxes,
534
+ height: trendHeight,
535
+ reference: hasReference,
536
+ tooltip: true,
537
+ highlight: highlightActive,
538
+ xTitle: periodTitle,
539
+ yTitle: name,
540
+ targetTitle: labels.target,
541
+ valueFormat: locale ? `${format}@${locale}` : format,
542
+ timeFormat: timeGrammar(granularity),
543
+ axisTimeFormat: timeGrammar(axisGranularity(granularity)),
544
+ locale,
545
+ timeZone
546
+ }, tokens);
547
+ return patchSpec ? patchSpec(built) : built;
548
+ }, [
549
+ tokens,
550
+ xType,
551
+ granularity,
552
+ trendMark,
553
+ trendScale,
554
+ trendAxes,
555
+ trendHeight,
556
+ hasReference,
557
+ highlightActive,
558
+ periodTitle,
559
+ labels.target,
560
+ name,
561
+ format,
562
+ locale,
563
+ timeZone,
564
+ patchSpec
565
+ ]);
566
+ const trendRows = summary?.rows;
567
+ const latest = summary?.latest;
568
+ const referenceRows = useMemo(() => target != null ? [{ value: target }] : [], [target]);
569
+ const latestRows = useMemo(() => latest ? [latest] : [], [latest]);
570
+ const highlightDatasets = useMemo(() => highlightActive && summary && highlightInfo ? buildHighlightDatasets(summary, highlightInfo) : null, [
571
+ highlightActive,
572
+ summary,
573
+ highlightInfo
574
+ ]);
575
+ const datasets = useMemo(() => {
576
+ if (highlightDatasets) return {
577
+ [METRIC_TREND_DATASET]: highlightDatasets.table,
578
+ [METRIC_CONTEXT_DATASET]: highlightDatasets.context,
579
+ [METRIC_HIGHLIGHT_ROWS_DATASET]: highlightDatasets.highlightRows,
580
+ [METRIC_HIGHLIGHT_POINTS_DATASET]: highlightDatasets.highlightPoints,
581
+ [METRIC_HIGHLIGHT_DATASET]: highlightDatasets.highlight,
582
+ [METRIC_REFERENCE_DATASET]: referenceRows
583
+ };
584
+ return {
585
+ [METRIC_TREND_DATASET]: trendRows ?? [],
586
+ [METRIC_REFERENCE_DATASET]: referenceRows,
587
+ [METRIC_LATEST_DATASET]: latestRows
588
+ };
589
+ }, [
590
+ highlightDatasets,
591
+ trendRows,
592
+ referenceRows,
593
+ latestRows
594
+ ]);
595
+ const chartDescription = summary && hasChart ? buildMetricChartDescription({
596
+ name,
597
+ mark: trendMark,
598
+ trend: summary,
599
+ target: targetInfo,
600
+ formatters,
601
+ labels,
602
+ highlight: highlightActive ? highlightInfo : null
603
+ }) : void 0;
604
+ const insightContent = insight === void 0 ? highlightActive && highlightInfo ? /* @__PURE__ */ jsx(InsightText, { segments: buildHighlightInsight({
605
+ name,
606
+ highlight: highlightInfo,
607
+ formatters,
608
+ labels
609
+ }) }) : null : insight;
610
+ const showInsight = insightContent != null && insightContent !== false;
611
+ const reserveDelta = isHighlight || previousValue !== void 0 || hasComparisons;
612
+ const reserveTrend = trend !== void 0;
613
+ const reserveTarget = target !== void 0;
614
+ const reserveInsight = insight === void 0 ? isHighlight : insight != null && insight !== false;
615
+ const headlineMinHeight = Math.max(sizes.valueLinePx, reserveDelta ? sizes.deltaLinePx + 4 + sizes.comparisonLinePx : 0);
616
+ const bodyMinHeight = headlineMinHeight + (reserveTrend ? sizes.gapPx + trendHeight : 0) + (reserveTarget ? sizes.gapPx + TARGET_BLOCK_PX : 0) + (reserveInsight ? sizes.gapPx + sizes.comparisonLinePx : 0);
617
+ const HeadingTag = `h${titleLevel}`;
618
+ const busy = state === "loading" || state === "refreshing";
619
+ const directionWordFor = (direction) => direction === "up" ? labels.increase : direction === "down" ? labels.decrease : labels.unchanged;
620
+ const targetTone = goodDirection === "none" ? "neutral" : targetInfo?.variant ?? "primary";
621
+ const targetPolarity = !targetInfo || goodDirection === "none" || targetInfo.direction === "flat" ? "neutral" : targetInfo.met ? "positive" : "negative";
622
+ const deltaStack = (chevron) => /* @__PURE__ */ jsxs(Fragment$1, { children: [
623
+ delta && /* @__PURE__ */ jsx("span", {
624
+ id: deltaExplanationId,
625
+ className: "sr-only",
626
+ children: deltaExplanation
627
+ }),
628
+ delta && /* @__PURE__ */ jsxs(Badge, {
629
+ variant: polarityBadgeVariant[delta.polarity],
630
+ appearance: "soft",
631
+ size: sizes.badge,
632
+ "data-direction": delta.direction,
633
+ children: [
634
+ /* @__PURE__ */ jsx(DeltaGlyph, { direction: delta.direction }),
635
+ /* @__PURE__ */ jsxs("span", {
636
+ className: "sr-only",
637
+ children: [directionWordFor(delta.direction), " "]
638
+ }),
639
+ delta.text
640
+ ]
641
+ }),
642
+ chevron ? /* @__PURE__ */ jsxs("span", {
643
+ className: "inline-flex max-w-full items-center gap-0.5 text-muted-foreground text-xs transition-colors group-hover:text-foreground group-data-popup-open:text-foreground",
644
+ children: [/* @__PURE__ */ jsx("span", {
645
+ className: "min-w-0 wrap-break-word",
646
+ children: comparisonNode
647
+ }), /* @__PURE__ */ jsx(ChevronDownIcon, { className: "size-3 shrink-0" })]
648
+ }) : /* @__PURE__ */ jsx("span", {
649
+ className: "max-w-full text-muted-foreground wrap-break-word text-xs",
650
+ children: comparisonNode
651
+ })
652
+ ] });
653
+ return /* @__PURE__ */ jsxs(Box, {
654
+ ref: setRootRef,
655
+ render: render ?? /* @__PURE__ */ jsx("figure", {}),
656
+ padding: sizes.padding,
657
+ "aria-labelledby": headingId,
658
+ "aria-describedby": descriptionId,
659
+ "aria-busy": busy || void 0,
660
+ "data-status": status,
661
+ "data-state": state,
662
+ "data-size": size,
663
+ "data-variant": variant,
664
+ "data-highlight": isHighlight && showContent ? highlightActive ? "resolved" : "unresolved" : void 0,
665
+ "data-empty": state === "empty" || state === "no-match" ? "" : void 0,
666
+ "data-stale": stale ? "" : void 0,
667
+ "data-insufficient": insufficient ? "" : void 0,
668
+ "data-trend-axes": summary ? trendAxes : void 0,
669
+ "data-polarity": showContent && delta ? delta.polarity : void 0,
670
+ "data-selectable": showContent && showComparisonMenu ? "" : void 0,
671
+ "data-comparison": showContent && hasComparisons ? selectedComparison?.key : void 0,
672
+ ...rest,
673
+ className: cn("relative flex min-w-0 flex-col", sizes.gap, className),
674
+ children: [
675
+ /* @__PURE__ */ jsxs("div", {
676
+ className: "flex items-center justify-between gap-2",
677
+ children: [/* @__PURE__ */ jsxs("div", {
678
+ className: "flex min-w-0 items-center gap-1",
679
+ children: [/* @__PURE__ */ jsx(HeadingTag, {
680
+ id: headingId,
681
+ className: cn(labelClasses, sizes.label, "line-clamp-2"),
682
+ children: label
683
+ }), hint && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs(Tooltip, { children: [/* @__PURE__ */ jsx(TooltipTrigger, {
684
+ render: /* @__PURE__ */ jsx(Button, {
685
+ variant: "ghost",
686
+ size: "sm",
687
+ iconOnly: true,
688
+ circular: true,
689
+ "aria-label": labels.about(name),
690
+ "aria-describedby": hintId,
691
+ className: headerControlClasses
692
+ }),
693
+ children: /* @__PURE__ */ jsx(InfoIcon, { className: "size-3.5" })
694
+ }), /* @__PURE__ */ jsx(TooltipPopup, { children: hint })] }), /* @__PURE__ */ jsx("span", {
695
+ id: hintId,
696
+ className: "sr-only",
697
+ children: hint
698
+ })] })]
699
+ }), /* @__PURE__ */ jsxs("div", {
700
+ className: "flex shrink-0 items-center gap-1",
701
+ children: [
702
+ stale && /* @__PURE__ */ jsx(Badge, {
703
+ variant: "warning",
704
+ appearance: "soft",
705
+ size: "sm",
706
+ children: labels.stale
707
+ }),
708
+ hasTable && /* @__PURE__ */ jsxs(Popover, {
709
+ open: tableOpen,
710
+ onOpenChange: setTableOpen,
711
+ children: [hasChart && !hideTableToggle && /* @__PURE__ */ jsx(PopoverTrigger, {
712
+ render: /* @__PURE__ */ jsx(Button, {
713
+ variant: "ghost",
714
+ size: "sm",
715
+ iconOnly: true,
716
+ circular: true,
717
+ "aria-label": tableOpen ? labels.hideTable(name) : labels.showTable(name),
718
+ className: headerControlClasses
719
+ }),
720
+ children: /* @__PURE__ */ jsx(InfoIcon, { className: "size-3.5" })
721
+ }), popoverContainer && /* @__PURE__ */ jsxs(PopoverPopup, {
722
+ id: tableId,
723
+ anchor: rootRef,
724
+ container: popoverContainer,
725
+ side: "right",
726
+ align: "start",
727
+ collisionPadding: 8,
728
+ className: "pointer-events-auto w-80",
729
+ "data-part": "data-popover",
730
+ children: [
731
+ /* @__PURE__ */ jsx(PopoverTitle, {
732
+ className: "mb-3",
733
+ children: name
734
+ }),
735
+ /* @__PURE__ */ jsxs("div", {
736
+ className: "mb-3 flex flex-wrap gap-x-3 gap-y-1 text-xs text-muted-foreground",
737
+ "data-part": "chart-legend",
738
+ children: [
739
+ /* @__PURE__ */ jsx(MetricTrendKey, {
740
+ label: name,
741
+ mark: trendMark,
742
+ color: seriesColor
743
+ }),
744
+ highlightActive && highlightInfo && /* @__PURE__ */ jsx(MetricTrendKey, {
745
+ label: `${highlightInfo.label ?? highlightInfo.rangeText} · ${highlightInfo.delta.text}`,
746
+ mark: trendMark,
747
+ color: highlightColor
748
+ }),
749
+ target != null && /* @__PURE__ */ jsx(MetricTrendKey, {
750
+ label: `${labels.target} ${formatters.formatY(target)}`,
751
+ mark: "target",
752
+ color: tokens?.reference
753
+ })
754
+ ]
755
+ }),
756
+ /* @__PURE__ */ jsx(TableContainer, {
757
+ variant: "plain",
758
+ tabIndex: 0,
759
+ role: "region",
760
+ "aria-label": labels.tableCaption(name),
761
+ className: "max-h-[min(16rem,calc(var(--available-height)-4.5rem))] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring",
762
+ "data-part": "table",
763
+ children: /* @__PURE__ */ jsxs(Table, {
764
+ size: "sm",
765
+ stickyHeader: true,
766
+ hoverable: false,
767
+ children: [
768
+ /* @__PURE__ */ jsx(TableCaption, {
769
+ side: "top",
770
+ className: "sr-only",
771
+ children: labels.tableCaption(name)
772
+ }),
773
+ /* @__PURE__ */ jsx(TableHeader, { children: /* @__PURE__ */ jsxs(TableRow, { children: [/* @__PURE__ */ jsx(TableHead, { children: labels.tablePeriod }), /* @__PURE__ */ jsx(TableHead, {
774
+ className: "text-right",
775
+ children: labels.tableValue
776
+ })] }) }),
777
+ /* @__PURE__ */ jsx(TableBody, { children: summary.rows.map((row, index) => {
778
+ const inWindow = highlightDatasets?.table[index]?.hl === true;
779
+ return /* @__PURE__ */ jsxs(TableRow, {
780
+ "data-highlight": inWindow ? "" : void 0,
781
+ children: [/* @__PURE__ */ jsxs(TableCell, { children: [
782
+ inWindow && /* @__PURE__ */ jsx("span", {
783
+ "aria-hidden": "true",
784
+ className: "me-1.5 inline-block size-1.5 rounded-full align-middle",
785
+ style: { background: highlightColor }
786
+ }),
787
+ formatters.formatX(row.x),
788
+ inWindow && /* @__PURE__ */ jsxs("span", {
789
+ className: "sr-only",
790
+ children: [
791
+ " (",
792
+ labels.highlighted,
793
+ ")"
794
+ ]
795
+ })
796
+ ] }), /* @__PURE__ */ jsx(TableCell, {
797
+ className: "text-right tabular-nums",
798
+ children: formatters.formatY(row.y)
799
+ })]
800
+ }, index);
801
+ }) })
802
+ ]
803
+ })
804
+ })
805
+ ]
806
+ })]
807
+ }),
808
+ action
809
+ ]
810
+ })]
811
+ }),
812
+ /* @__PURE__ */ jsx("p", {
813
+ id: descriptionId,
814
+ className: "sr-only",
815
+ children: cardDescription
816
+ }),
817
+ hasComparisons && /* @__PURE__ */ jsx("p", {
818
+ role: "status",
819
+ "aria-live": "polite",
820
+ className: "sr-only",
821
+ "data-part": "announcement",
822
+ children: announcement
823
+ }),
824
+ /* @__PURE__ */ jsxs("div", {
825
+ className: "relative flex min-w-0 flex-col",
826
+ style: { minHeight: bodyMinHeight },
827
+ children: [
828
+ state === "loading" && /* @__PURE__ */ jsxs(SkeletonGroup, {
829
+ className: cn("flex flex-col", sizes.gap),
830
+ children: [
831
+ /* @__PURE__ */ jsxs("div", {
832
+ className: "flex min-w-0 items-center justify-between gap-2",
833
+ style: { minHeight: headlineMinHeight },
834
+ children: [/* @__PURE__ */ jsx(Skeleton, {
835
+ variant: "rounded",
836
+ className: "w-2/5",
837
+ style: { height: sizes.valueLinePx }
838
+ }), reserveDelta && /* @__PURE__ */ jsxs("div", {
839
+ className: "flex w-2/5 flex-col items-end gap-1",
840
+ children: [/* @__PURE__ */ jsx(Skeleton, {
841
+ variant: "rounded",
842
+ className: "w-20 max-w-full",
843
+ style: { height: sizes.deltaLinePx }
844
+ }), /* @__PURE__ */ jsx(Skeleton, {
845
+ variant: "rounded",
846
+ className: "w-full",
847
+ style: { height: sizes.comparisonLinePx }
848
+ })]
849
+ })]
850
+ }),
851
+ reserveTrend && /* @__PURE__ */ jsx(Skeleton, {
852
+ variant: "rounded",
853
+ className: "w-full",
854
+ style: { height: trendHeight }
855
+ }),
856
+ reserveTarget && /* @__PURE__ */ jsx(Skeleton, {
857
+ variant: "rounded",
858
+ className: "w-full",
859
+ style: { height: TARGET_BLOCK_PX }
860
+ }),
861
+ reserveInsight && /* @__PURE__ */ jsxs("div", {
862
+ className: "flex items-start gap-2",
863
+ children: [/* @__PURE__ */ jsx(Skeleton, {
864
+ variant: "rounded",
865
+ className: "size-4 shrink-0"
866
+ }), /* @__PURE__ */ jsx(Skeleton, {
867
+ variant: "rounded",
868
+ className: "w-full",
869
+ style: { height: sizes.comparisonLinePx }
870
+ })]
871
+ })
872
+ ]
873
+ }),
874
+ state === "error" && /* @__PURE__ */ jsx(SystemState, {
875
+ variant: "server-error",
876
+ scope: "inline",
877
+ title: labels.error,
878
+ description: false,
879
+ action: onRetry ? /* @__PURE__ */ jsx(Button, {
880
+ size: "sm",
881
+ onClick: onRetry,
882
+ children: labels.retry
883
+ }) : void 0,
884
+ className: cn(tileStateClasses, "my-auto")
885
+ }),
886
+ state === "empty" && /* @__PURE__ */ jsx(SystemState, {
887
+ variant: "empty",
888
+ scope: "inline",
889
+ title: labels.noData,
890
+ description: false,
891
+ className: cn(tileStateClasses, "my-auto")
892
+ }),
893
+ state === "no-match" && /* @__PURE__ */ jsx(SystemState, {
894
+ variant: "no-results",
895
+ scope: "inline",
896
+ title: labels.noMatch,
897
+ description: false,
898
+ action: onClearFilters ? /* @__PURE__ */ jsx(Button, {
899
+ variant: "outline",
900
+ size: "sm",
901
+ onClick: onClearFilters,
902
+ children: labels.clearFilters
903
+ }) : void 0,
904
+ className: cn(tileStateClasses, "my-auto")
905
+ }),
906
+ showContent && /* @__PURE__ */ jsxs("div", {
907
+ className: cn("flex min-w-0 flex-col", sizes.gap),
908
+ children: [
909
+ /* @__PURE__ */ jsxs("div", {
910
+ className: "flex min-w-0 items-center justify-between gap-2",
911
+ style: { minHeight: headlineMinHeight },
912
+ "data-part": "headline",
913
+ children: [/* @__PURE__ */ jsxs("div", {
914
+ className: "flex min-w-0 flex-wrap items-baseline gap-x-1.5",
915
+ "data-part": "value",
916
+ children: [/* @__PURE__ */ jsx("span", {
917
+ className: cn(valueClasses, sizes.value, "min-w-0 wrap-break-word"),
918
+ children: valueText
919
+ }), unit != null && /* @__PURE__ */ jsx("span", {
920
+ className: cn("font-sans text-muted-foreground", sizes.unit),
921
+ children: unit
922
+ })]
923
+ }), showComparisonMenu ? /* @__PURE__ */ jsxs(Menu, { children: [/* @__PURE__ */ jsx(MenuTrigger, {
924
+ render: /* @__PURE__ */ jsx("button", {
925
+ type: "button",
926
+ "aria-label": hasComparisons ? labels.chooseComparison(name) : labels.deltaComparison(name),
927
+ "aria-describedby": delta ? deltaExplanationId : void 0,
928
+ className: cn(deltaStackClasses, deltaButtonClasses, sizes.body),
929
+ "data-part": "delta"
930
+ }),
931
+ children: deltaStack(true)
932
+ }), /* @__PURE__ */ jsxs(MenuPopup, {
933
+ side: "right",
934
+ align: "start",
935
+ sideOffset: 8,
936
+ collisionPadding: 8,
937
+ container: popoverContainer,
938
+ className: "pointer-events-auto w-[26rem] max-w-[min(26rem,var(--available-width))]",
939
+ "data-part": "comparison-menu",
940
+ children: [
941
+ /* @__PURE__ */ jsxs("div", {
942
+ className: "flex items-center justify-between gap-3 px-2 py-1.5 font-sans text-xs",
943
+ "data-part": "comparison-menu-subject",
944
+ children: [/* @__PURE__ */ jsx("span", {
945
+ className: "min-w-0 truncate font-medium text-foreground",
946
+ children: name
947
+ }), /* @__PURE__ */ jsx("span", {
948
+ className: "shrink-0 font-medium text-foreground tabular-nums",
949
+ children: valueText
950
+ })]
951
+ }),
952
+ /* @__PURE__ */ jsx(MenuSeparator, {}),
953
+ /* @__PURE__ */ jsxs(MenuRadioGroup, {
954
+ className: menuGridClasses,
955
+ value: hasComparisons ? selectedComparison?.key ?? "" : "__previous__",
956
+ onValueChange: hasComparisons ? (value) => selectComparison(String(value)) : void 0,
957
+ children: [/* @__PURE__ */ jsxs(MenuGroupLabel, {
958
+ inset: true,
959
+ className: menuRowClasses,
960
+ "data-part": "comparison-menu-header",
961
+ children: [
962
+ /* @__PURE__ */ jsx("span", {
963
+ className: "min-w-0 truncate",
964
+ children: labels.compareWith
965
+ }),
966
+ /* @__PURE__ */ jsx("span", {
967
+ className: menuFigureClasses,
968
+ children: labels.tableValue
969
+ }),
970
+ /* @__PURE__ */ jsx("span", {
971
+ className: menuFigureClasses,
972
+ children: labels.changePercent
973
+ }),
974
+ /* @__PURE__ */ jsx("span", {
975
+ className: menuFigureClasses,
976
+ children: labels.changeAmount
977
+ })
978
+ ]
979
+ }), comparisonCandidates.map(({ row, polarity, valueText: baselineText, percentText, amountText }) => /* @__PURE__ */ jsxs(MenuRadioItem, {
980
+ value: row.key,
981
+ closeOnClick: true,
982
+ disabled: row.value == null,
983
+ className: menuRowClasses,
984
+ "data-polarity": polarity,
985
+ children: [
986
+ /* @__PURE__ */ jsx("span", {
987
+ className: "min-w-0 truncate",
988
+ children: row.label
989
+ }),
990
+ /* @__PURE__ */ jsx("span", {
991
+ className: cn(menuFigureClasses, "text-muted-foreground"),
992
+ children: baselineText
993
+ }),
994
+ /* @__PURE__ */ jsx("span", {
995
+ className: cn(menuFigureClasses, "font-medium", changeTextClasses[polarity]),
996
+ children: percentText
997
+ }),
998
+ /* @__PURE__ */ jsx("span", {
999
+ className: cn(menuFigureClasses, "font-medium", changeTextClasses[polarity]),
1000
+ children: amountText
1001
+ })
1002
+ ]
1003
+ }, row.key))]
1004
+ })
1005
+ ]
1006
+ })] }) : delta && showHighlightDetails && highlightInfo && highlightDetailsInfo ? /* @__PURE__ */ jsxs(Popover, {
1007
+ open: highlightDetailsOpen,
1008
+ onOpenChange: setHighlightDetailsOpen,
1009
+ children: [/* @__PURE__ */ jsx(PopoverTrigger, {
1010
+ render: /* @__PURE__ */ jsx("button", {
1011
+ type: "button",
1012
+ "aria-label": labels.highlightDetails(name),
1013
+ "aria-describedby": deltaExplanationId,
1014
+ className: cn(deltaStackClasses, deltaButtonClasses, sizes.body),
1015
+ "data-part": "delta"
1016
+ }),
1017
+ children: deltaStack(true)
1018
+ }), popoverContainer && /* @__PURE__ */ jsxs(PopoverPopup, {
1019
+ side: "right",
1020
+ align: "start",
1021
+ sideOffset: 8,
1022
+ collisionPadding: 8,
1023
+ container: popoverContainer,
1024
+ className: "pointer-events-auto w-80",
1025
+ "data-part": "highlight-popover",
1026
+ children: [
1027
+ /* @__PURE__ */ jsx(PopoverTitle, {
1028
+ className: highlightInfo.label ? "mb-0.5" : "mb-3",
1029
+ children: highlightInfo.label ?? highlightInfo.rangeText
1030
+ }),
1031
+ highlightInfo.label && /* @__PURE__ */ jsx(PopoverDescription, {
1032
+ className: "mb-3",
1033
+ children: highlightInfo.rangeText
1034
+ }),
1035
+ /* @__PURE__ */ jsx(DetailRows, {
1036
+ rows: [
1037
+ [`${labels.highlightStart} · ${formatters.formatX(highlightInfo.start.x)}`, formatters.formatY(highlightInfo.start.y)],
1038
+ [`${labels.highlightEnd} · ${formatters.formatX(highlightInfo.end.x)}`, formatters.formatY(highlightInfo.end.y)],
1039
+ [
1040
+ labels.highlightChange,
1041
+ highlightInfo.absoluteText,
1042
+ changeTextClasses[delta.polarity]
1043
+ ],
1044
+ [
1045
+ labels.highlightChangePercent,
1046
+ highlightInfo.percentText,
1047
+ changeTextClasses[delta.polarity]
1048
+ ]
1049
+ ],
1050
+ "data-part": "highlight-summary"
1051
+ }),
1052
+ /* @__PURE__ */ jsx(TableContainer, {
1053
+ variant: "plain",
1054
+ tabIndex: 0,
1055
+ role: "region",
1056
+ "aria-label": labels.highlightReadings(name),
1057
+ className: "mt-3 max-h-40 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring",
1058
+ "data-part": "highlight-steps",
1059
+ children: /* @__PURE__ */ jsxs(Table, {
1060
+ size: "sm",
1061
+ stickyHeader: true,
1062
+ hoverable: false,
1063
+ children: [
1064
+ /* @__PURE__ */ jsx(TableCaption, {
1065
+ side: "top",
1066
+ className: "sr-only",
1067
+ children: labels.highlightReadings(name)
1068
+ }),
1069
+ /* @__PURE__ */ jsx(TableHeader, { children: /* @__PURE__ */ jsxs(TableRow, { children: [
1070
+ /* @__PURE__ */ jsx(TableHead, { children: labels.tablePeriod }),
1071
+ /* @__PURE__ */ jsx(TableHead, {
1072
+ className: "text-right",
1073
+ children: labels.tableValue
1074
+ }),
1075
+ /* @__PURE__ */ jsx(TableHead, {
1076
+ className: "text-right",
1077
+ children: delta.renderedMode === "percent" ? labels.highlightChangePercent : labels.highlightChange
1078
+ })
1079
+ ] }) }),
1080
+ /* @__PURE__ */ jsx(TableBody, { children: highlightDetailsInfo.steps.map((step, index) => /* @__PURE__ */ jsxs(TableRow, {
1081
+ "data-role": step.role,
1082
+ children: [
1083
+ /* @__PURE__ */ jsx(TableCell, { children: step.xText }),
1084
+ /* @__PURE__ */ jsx(TableCell, {
1085
+ className: "text-right tabular-nums",
1086
+ children: step.yText
1087
+ }),
1088
+ /* @__PURE__ */ jsx(TableCell, {
1089
+ className: cn("text-right tabular-nums", step.changeText ? cn("font-medium", changeTextClasses[step.polarity]) : "text-muted-foreground"),
1090
+ children: step.changeText ?? "—"
1091
+ })
1092
+ ]
1093
+ }, index)) })
1094
+ ]
1095
+ })
1096
+ }),
1097
+ (highlightDetailsInfo.before || highlightDetailsInfo.since) && /* @__PURE__ */ jsx(DetailRows, {
1098
+ className: "mt-3 border-t border-border pt-3",
1099
+ rows: [...highlightDetailsInfo.before ? [[
1100
+ `${labels.highlightBefore} · ${highlightDetailsInfo.before.rangeText}`,
1101
+ highlightDetailsInfo.before.changeText,
1102
+ changeTextClasses[highlightDetailsInfo.before.polarity]
1103
+ ]] : [], ...highlightDetailsInfo.since ? [[
1104
+ `${labels.highlightSince} · ${highlightDetailsInfo.since.rangeText}`,
1105
+ highlightDetailsInfo.since.changeText,
1106
+ changeTextClasses[highlightDetailsInfo.since.polarity]
1107
+ ], [`${labels.highlightLatest} · ${highlightDetailsInfo.since.to.xText}`, highlightDetailsInfo.since.to.yText]] : []],
1108
+ "data-part": "highlight-context"
1109
+ })
1110
+ ]
1111
+ })]
1112
+ }) : delta ? /* @__PURE__ */ jsxs(Tooltip, { children: [/* @__PURE__ */ jsx(TooltipTrigger, {
1113
+ delay: 150,
1114
+ render: /* @__PURE__ */ jsx("p", {
1115
+ tabIndex: 0,
1116
+ role: "group",
1117
+ "aria-label": labels.deltaComparison(name),
1118
+ "aria-describedby": deltaExplanationId,
1119
+ className: cn(deltaStackClasses, sizes.body),
1120
+ "data-part": "delta"
1121
+ }),
1122
+ children: deltaStack(false)
1123
+ }), /* @__PURE__ */ jsx(TooltipPopup, {
1124
+ arrow: false,
1125
+ side: "bottom",
1126
+ align: "end",
1127
+ sideOffset: 8,
1128
+ collisionPadding: 8,
1129
+ container: popoverContainer,
1130
+ className: "text-left",
1131
+ "data-part": "delta-tooltip",
1132
+ children: /* @__PURE__ */ jsx(ArcTooltipRows, { rows: deltaExplanationRows })
1133
+ })] }) : null]
1134
+ }),
1135
+ summary && /* @__PURE__ */ jsx("div", {
1136
+ ref: plotRef,
1137
+ className: "relative w-full",
1138
+ style: { height: trendHeight },
1139
+ "data-part": "trend",
1140
+ children: hasChart ? plotWidth > 0 && spec ? /* @__PURE__ */ jsx(ArcVegaChart, {
1141
+ spec,
1142
+ options: embedOptions,
1143
+ datasets,
1144
+ description: chartDescription,
1145
+ width: plotWidth,
1146
+ height: trendHeight,
1147
+ onEmbed,
1148
+ className: "absolute inset-0 [&_svg]:block [&_.vega-bindings:empty]:hidden",
1149
+ fallback: /* @__PURE__ */ jsx(Skeleton, {
1150
+ variant: "rounded",
1151
+ className: "size-full"
1152
+ })
1153
+ }) : /* @__PURE__ */ jsx(Skeleton, {
1154
+ variant: "rounded",
1155
+ className: "size-full"
1156
+ }) : /* @__PURE__ */ jsx("p", {
1157
+ className: cn(captionClasses, "flex h-full items-center"),
1158
+ children: labels.insufficientTrend
1159
+ })
1160
+ }),
1161
+ targetInfo && /* @__PURE__ */ jsxs(Tooltip, {
1162
+ trackCursorAxis: "both",
1163
+ children: [/* @__PURE__ */ jsxs(TooltipTrigger, {
1164
+ delay: 150,
1165
+ render: /* @__PURE__ */ jsx(Box, {
1166
+ background: "transparent",
1167
+ shadow: "none",
1168
+ border: true,
1169
+ radius: "md",
1170
+ padding: "sm",
1171
+ tabIndex: 0,
1172
+ role: "group",
1173
+ "aria-label": labels.targetProgress(name),
1174
+ "aria-describedby": targetExplanationId,
1175
+ className: "flex w-full min-w-0 flex-col gap-1.5 bg-slate-50 text-xs focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring",
1176
+ "data-part": "target",
1177
+ "data-tone": targetTone,
1178
+ "data-direction": targetInfo.direction
1179
+ }),
1180
+ children: [
1181
+ /* @__PURE__ */ jsx("span", {
1182
+ id: targetExplanationId,
1183
+ className: "sr-only",
1184
+ children: targetExplanation
1185
+ }),
1186
+ /* @__PURE__ */ jsxs("p", {
1187
+ className: "flex min-w-0 flex-wrap items-center justify-between gap-2",
1188
+ children: [/* @__PURE__ */ jsxs("span", {
1189
+ className: "flex min-w-0 flex-wrap items-center gap-1.5",
1190
+ children: [/* @__PURE__ */ jsxs("span", {
1191
+ className: "shrink-0 font-semibold text-foreground tabular-nums",
1192
+ children: [targetInfo.percentText, /* @__PURE__ */ jsxs("span", {
1193
+ className: "sr-only",
1194
+ children: [" ", labels.ofTarget]
1195
+ })]
1196
+ }), /* @__PURE__ */ jsxs("span", {
1197
+ className: "text-muted-foreground tabular-nums",
1198
+ "data-part": "target-amount",
1199
+ children: [
1200
+ "(",
1201
+ targetInfo.progressAmountText,
1202
+ ")"
1203
+ ]
1204
+ })]
1205
+ }), /* @__PURE__ */ jsxs("span", {
1206
+ className: "ms-auto flex min-w-0 items-center gap-1.5",
1207
+ children: [/* @__PURE__ */ jsx("span", {
1208
+ className: "min-w-0 font-semibold text-foreground tabular-nums wrap-break-word",
1209
+ "data-part": "target-goal",
1210
+ children: targetInfo.targetText
1211
+ }), /* @__PURE__ */ jsxs("span", {
1212
+ className: cn("inline-flex shrink-0 items-center gap-x-1", polarityTextClasses[targetPolarity]),
1213
+ "data-part": "target-variance",
1214
+ "data-polarity": targetPolarity,
1215
+ children: [
1216
+ /* @__PURE__ */ jsxs("span", {
1217
+ className: "sr-only",
1218
+ children: [directionWordFor(targetInfo.direction), " "]
1219
+ }),
1220
+ /* @__PURE__ */ jsx("span", {
1221
+ className: "font-medium tabular-nums",
1222
+ children: targetInfo.varianceText
1223
+ }),
1224
+ /* @__PURE__ */ jsxs("span", {
1225
+ className: "sr-only",
1226
+ children: [" ", labels.vsTarget]
1227
+ })
1228
+ ]
1229
+ })]
1230
+ })]
1231
+ }),
1232
+ /* @__PURE__ */ jsx(Meter, {
1233
+ value: Math.min(100, Math.max(0, targetInfo.ratio * 100)),
1234
+ size: "sm",
1235
+ variant: targetInfo.variant,
1236
+ "aria-label": labels.targetProgress(name),
1237
+ getAriaValueText: () => `${targetInfo.percentText} ${labels.ofTarget}`
1238
+ })
1239
+ ]
1240
+ }), /* @__PURE__ */ jsx(TooltipPopup, {
1241
+ arrow: false,
1242
+ side: "bottom",
1243
+ align: "start",
1244
+ sideOffset: 12,
1245
+ alignOffset: 12,
1246
+ collisionPadding: 8,
1247
+ container: popoverContainer,
1248
+ className: "text-left",
1249
+ "data-part": "target-tooltip",
1250
+ children: /* @__PURE__ */ jsx(ArcTooltipRows, { rows: targetExplanationRows })
1251
+ })]
1252
+ }),
1253
+ showInsight && /* @__PURE__ */ jsxs("div", {
1254
+ className: cn("flex items-start gap-2 font-sans text-foreground", sizes.body),
1255
+ "data-part": "insight",
1256
+ children: [/* @__PURE__ */ jsx(AILoader, {
1257
+ size: "sm",
1258
+ state: "default",
1259
+ label: labels.insightMark,
1260
+ className: cn("shrink-0", size === "sm" ? "" : "mt-0.5")
1261
+ }), /* @__PURE__ */ jsx("p", {
1262
+ className: "min-w-0 flex-1 [&_strong]:font-semibold [&_strong]:text-foreground text-xs leading-[1.8]",
1263
+ children: insightContent
1264
+ })]
1265
+ })
1266
+ ]
1267
+ }),
1268
+ state === "refreshing" && /* @__PURE__ */ jsx("div", {
1269
+ "aria-hidden": "true",
1270
+ className: "absolute -inset-1 rounded-md bg-veil"
1271
+ })
1272
+ ]
1273
+ }),
1274
+ asOfValid && asOfDate && /* @__PURE__ */ jsx("p", {
1275
+ className: cn(captionClasses, "text-right"),
1276
+ "data-part": "as-of",
1277
+ children: /* @__PURE__ */ jsx("time", {
1278
+ dateTime: asOfDate.toISOString(),
1279
+ children: asOfText
1280
+ })
1281
+ }),
1282
+ /* @__PURE__ */ jsx("div", {
1283
+ ref: setPopoverContainer,
1284
+ className: "pointer-events-none absolute inset-0",
1285
+ "data-part": "popover-host"
1286
+ }),
1287
+ tooltip
1288
+ ]
1289
+ });
1290
+ });
1291
+ MetricCard.displayName = "MetricCard";
1292
+ //#endregion
1293
+ export { MetricCard };