@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,961 @@
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 { INSIGHT_INTERVAL_DATASET, INSIGHT_POINTS_DATASET, INSIGHT_STRIP_DATASET, buildInsightSparkSpec, buildInsightStripSpec } from "./InsightCard.chart.js";
7
+ import { buildInsightChartDescription, buildInsightDescription, buildInsightProvenance, createInsightFormatters, deriveInsightState, formatInsightX, insightAxisGranularity, normalizeInsight, resolveInsightLabels } from "./InsightCard.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, Toggle, 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/InsightCard/InsightCard.tsx
12
+ const sizeStyles = {
13
+ sm: {
14
+ padding: "sm",
15
+ gap: "gap-2",
16
+ gapPx: 8,
17
+ label: "text-xs",
18
+ statement: "text-sm",
19
+ statementPx: 20,
20
+ body: "text-xs",
21
+ keyRowPx: 35,
22
+ keyColumns: 2,
23
+ spark: 44,
24
+ strip: 22,
25
+ yTicks: 2,
26
+ captionPx: 16
27
+ },
28
+ md: {
29
+ padding: "md",
30
+ gap: "gap-3",
31
+ gapPx: 12,
32
+ label: "text-sm",
33
+ statement: "text-base",
34
+ statementPx: 24,
35
+ body: "text-sm",
36
+ keyRowPx: 34,
37
+ keyColumns: 3,
38
+ spark: 56,
39
+ strip: 26,
40
+ yTicks: 3,
41
+ captionPx: 18
42
+ },
43
+ lg: {
44
+ padding: "lg",
45
+ gap: "gap-3",
46
+ gapPx: 12,
47
+ label: "text-sm",
48
+ statement: "text-lg",
49
+ statementPx: 28,
50
+ body: "text-sm",
51
+ keyRowPx: 38,
52
+ keyColumns: 3,
53
+ spark: 72,
54
+ strip: 30,
55
+ yTicks: 4,
56
+ captionPx: 18
57
+ }
58
+ };
59
+ const severityBadge = {
60
+ info: "neutral",
61
+ notable: "warning",
62
+ critical: "destructive"
63
+ };
64
+ const polarityTextClasses = {
65
+ positive: "text-chart-positive",
66
+ negative: "text-chart-negative",
67
+ neutral: "text-foreground"
68
+ };
69
+ const labelClasses = "min-w-0 font-sans font-medium text-muted-foreground";
70
+ const captionClasses = "font-sans text-xs text-muted-foreground";
71
+ const headerControlClasses = "size-6 min-w-0 text-muted-foreground hover:text-foreground";
72
+ const tileStateClasses = "w-full max-w-none gap-2 px-2 py-2 [--artwork-box:3rem]";
73
+ const MISSING_NAME = "Insight";
74
+ const EMPTY_POINTS = [];
75
+ const EMPTY_ROWS = [];
76
+ function KindGlyph({ kind, ...props }) {
77
+ return /* @__PURE__ */ jsxs("svg", {
78
+ viewBox: "0 0 24 24",
79
+ fill: "none",
80
+ stroke: "currentColor",
81
+ strokeWidth: 2,
82
+ strokeLinecap: "round",
83
+ strokeLinejoin: "round",
84
+ "aria-hidden": "true",
85
+ ...props,
86
+ children: [
87
+ kind === "anomaly" && /* @__PURE__ */ jsx("path", { d: "M3 16h4l3-9 4 13 3-8h4" }),
88
+ kind === "trend" && /* @__PURE__ */ jsx("path", { d: "M3 17l6-6 4 4 8-8M15 7h6v6" }),
89
+ kind === "threshold" && /* @__PURE__ */ jsx("path", { d: "M3 14h18M8 21V9m0 0-3 3m3-3 3 3" }),
90
+ kind === "outlier" && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("path", { d: "M5 18h.01M10 15h.01M15 17h.01M9 20h.01" }), /* @__PURE__ */ jsx("circle", {
91
+ cx: "18",
92
+ cy: "6",
93
+ r: "2.5"
94
+ })] }),
95
+ kind === "correlation" && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("path", { d: "M4 20 20 4" }), /* @__PURE__ */ jsx("path", { d: "M7 16h.01M12 11h.01M17 7h.01M9 13h.01" })] }),
96
+ kind === "forecast" && /* @__PURE__ */ jsx("path", {
97
+ d: "M3 15l5-5 3 3 4-5M15 8h4v4M14 19h7",
98
+ strokeDasharray: "0"
99
+ }),
100
+ kind === "milestone" && /* @__PURE__ */ jsx("path", { d: "M6 21V4m0 0h11l-2.5 4L17 12H6" }),
101
+ kind === "note" && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("circle", {
102
+ cx: "12",
103
+ cy: "12",
104
+ r: "9"
105
+ }), /* @__PURE__ */ jsx("path", { d: "M12 11v5M12 8h.01" })] })
106
+ ]
107
+ });
108
+ }
109
+ function DeltaGlyph({ direction, ...props }) {
110
+ return /* @__PURE__ */ jsxs("svg", {
111
+ viewBox: "0 0 24 24",
112
+ fill: "none",
113
+ stroke: "currentColor",
114
+ strokeWidth: 2.5,
115
+ strokeLinecap: "round",
116
+ strokeLinejoin: "round",
117
+ "aria-hidden": "true",
118
+ ...props,
119
+ children: [
120
+ direction === "up" && /* @__PURE__ */ jsx("path", { d: "M7 17 17 7M7 7h10v10" }),
121
+ direction === "down" && /* @__PURE__ */ jsx("path", { d: "M7 7 17 17M7 17h10V7" }),
122
+ direction === "flat" && /* @__PURE__ */ jsx("path", { d: "M5 12h14" })
123
+ ]
124
+ });
125
+ }
126
+ function InfoIcon(props) {
127
+ return /* @__PURE__ */ jsxs("svg", {
128
+ viewBox: "0 0 24 24",
129
+ fill: "none",
130
+ stroke: "currentColor",
131
+ strokeWidth: 2,
132
+ strokeLinecap: "round",
133
+ strokeLinejoin: "round",
134
+ "aria-hidden": "true",
135
+ ...props,
136
+ children: [/* @__PURE__ */ jsx("circle", {
137
+ cx: "12",
138
+ cy: "12",
139
+ r: "9"
140
+ }), /* @__PURE__ */ jsx("path", { d: "M12 11v5M12 8h.01" })]
141
+ });
142
+ }
143
+ function TableIcon(props) {
144
+ return /* @__PURE__ */ jsxs("svg", {
145
+ viewBox: "0 0 24 24",
146
+ fill: "none",
147
+ stroke: "currentColor",
148
+ strokeWidth: 2,
149
+ strokeLinecap: "round",
150
+ strokeLinejoin: "round",
151
+ "aria-hidden": "true",
152
+ ...props,
153
+ children: [/* @__PURE__ */ jsx("rect", {
154
+ x: "3",
155
+ y: "4",
156
+ width: "18",
157
+ height: "16",
158
+ rx: "2"
159
+ }), /* @__PURE__ */ jsx("path", { d: "M3 10h18M9 10v10" })]
160
+ });
161
+ }
162
+ function CloseIcon(props) {
163
+ return /* @__PURE__ */ jsx("svg", {
164
+ viewBox: "0 0 24 24",
165
+ fill: "none",
166
+ stroke: "currentColor",
167
+ strokeWidth: 2,
168
+ strokeLinecap: "round",
169
+ strokeLinejoin: "round",
170
+ "aria-hidden": "true",
171
+ ...props,
172
+ children: /* @__PURE__ */ jsx("path", { d: "M6 6l12 12M18 6 6 18" })
173
+ });
174
+ }
175
+ function ThumbIcon({ down, ...props }) {
176
+ return /* @__PURE__ */ jsxs("svg", {
177
+ viewBox: "0 0 24 24",
178
+ fill: "none",
179
+ stroke: "currentColor",
180
+ strokeWidth: 2,
181
+ strokeLinecap: "round",
182
+ strokeLinejoin: "round",
183
+ "aria-hidden": "true",
184
+ ...props,
185
+ style: down ? { transform: "rotate(180deg)" } : void 0,
186
+ children: [/* @__PURE__ */ jsx("path", { d: "M7 10v11H4a1 1 0 0 1-1-1v-9a1 1 0 0 1 1-1h3Z" }), /* @__PURE__ */ jsx("path", { d: "M7 10l4.5-7a2.5 2.5 0 0 1 3.7 3.2L14 10h5a2 2 0 0 1 2 2.4l-1.4 6A2 2 0 0 1 17.6 20H7" })]
187
+ });
188
+ }
189
+ function useMergedRef(forwarded) {
190
+ const inner = useRef(null);
191
+ return [inner, useCallback((node) => {
192
+ inner.current = node;
193
+ if (typeof forwarded === "function") forwarded(node);
194
+ else if (forwarded) forwarded.current = node;
195
+ }, [forwarded])];
196
+ }
197
+ function usePlotWidth(ref, enabled) {
198
+ const [width, setWidth] = useState(0);
199
+ useEffect(() => {
200
+ if (!enabled) return;
201
+ const node = ref.current;
202
+ if (!node) return;
203
+ let frame = 0;
204
+ const measure = () => setWidth((previous) => {
205
+ const next = Math.round(node.getBoundingClientRect().width);
206
+ return previous === next ? previous : next;
207
+ });
208
+ measure();
209
+ if (typeof ResizeObserver === "undefined") return;
210
+ const observer = new ResizeObserver(() => {
211
+ cancelAnimationFrame(frame);
212
+ frame = requestAnimationFrame(measure);
213
+ });
214
+ observer.observe(node);
215
+ return () => {
216
+ cancelAnimationFrame(frame);
217
+ observer.disconnect();
218
+ };
219
+ }, [ref, enabled]);
220
+ return width;
221
+ }
222
+ /**
223
+ * A finding, stated — the tenth member of the analytics card family, and the
224
+ * only one whose primary content is a **claim** rather than a reading.
225
+ * Everything else here takes data and computes something; this takes a finding
226
+ * a detector or a model already made and lays it out so a person can judge it:
227
+ * the statement, the observed reading against what was expected, the evidence
228
+ * plot, the provenance behind the claim, and the triage — act, dismiss, or say
229
+ * it was wrong.
230
+ *
231
+ * The evidence resolves itself: a `spark` when there is history to plot, a
232
+ * `range` strip when there is only a reading and an expectation, `none` when
233
+ * the finding is not a number on a scale. Severity is derived on whichever
234
+ * scale the detector's own data establishes and stamped with which one that
235
+ * was, polarity is separate and rides `goodDirection`, and every value the
236
+ * plot shows is also in the key row, the description and the popover table.
237
+ */
238
+ const InsightCard = forwardRef(({ label, name: nameProp, statement, statementText, hint, kind = "anomaly", observation, points = EMPTY_POINTS, xType, evidence = "auto", axes = "none", zeroScale = false, severity: severityProp, severityThresholds, goodDirection = "none", deltaMode = "percent", format = "compact", formatValue, granularity = "day", method, confidence, sampleSize, detectedAt, detectedAtFormat = "day", generated = true, status = "ready", filtered = false, stale = false, updatedAt, updatedAtFormat = "day", onRetry, onClearFilters, onDismiss, feedback, defaultFeedback, onFeedback, primaryAction, action, expectedLines = 2, size = "md", titleLevel = 3, locale, timeZone, labels: labelOverrides, description, defaultTableOpen = false, hideTableToggle = false, onEmbed, patchSpec, render, className, ...rest }, forwardedRef) => {
239
+ const labels = useMemo(() => resolveInsightLabels(labelOverrides), [labelOverrides]);
240
+ const sizes = sizeStyles[size];
241
+ const name = nameProp ?? (typeof label === "string" ? label : MISSING_NAME);
242
+ const claimText = statementText ?? (typeof statement === "string" ? statement : null);
243
+ const id = useId();
244
+ const headingId = `${id}-label`;
245
+ const descriptionId = `${id}-description`;
246
+ const hintId = `${id}-hint`;
247
+ const tableId = `${id}-table`;
248
+ const [rootRef, setRootRef] = useMergedRef(forwardedRef);
249
+ const plotRef = useRef(null);
250
+ const [popoverContainer, setPopoverContainer] = useState(null);
251
+ const [tableOpen, setTableOpen] = useState(defaultTableOpen);
252
+ const tokens = useChartTokens(rootRef);
253
+ const [feedbackState, setFeedbackState] = useState(defaultFeedback);
254
+ const chosen = feedback !== void 0 ? feedback : feedbackState ?? null;
255
+ const chooseFeedback = useCallback((next, pressed) => {
256
+ const value = pressed ? next : null;
257
+ if (feedback === void 0) setFeedbackState(value);
258
+ onFeedback?.(value);
259
+ }, [feedback, onFeedback]);
260
+ const summary = useMemo(() => normalizeInsight({
261
+ observation,
262
+ points,
263
+ xType,
264
+ goodDirection,
265
+ evidence,
266
+ severity: severityProp,
267
+ severityThresholds,
268
+ tokens
269
+ }), [
270
+ observation,
271
+ points,
272
+ xType,
273
+ goodDirection,
274
+ evidence,
275
+ severityProp,
276
+ severityThresholds,
277
+ tokens
278
+ ]);
279
+ const formatters = useMemo(() => createInsightFormatters({
280
+ format,
281
+ locale,
282
+ deltaMode,
283
+ formatValue,
284
+ labels
285
+ }), [
286
+ format,
287
+ locale,
288
+ deltaMode,
289
+ formatValue,
290
+ labels
291
+ ]);
292
+ const hasStatement = statement != null && statement !== false;
293
+ const hasFinding = hasStatement || (summary?.value ?? null) != null;
294
+ const hasData = hasStatement || (points?.length ?? 0) > 0 || observation != null;
295
+ const insufficient = (evidence === "auto" || evidence === "spark") && (points?.length ?? 0) > 0 && (summary?.insufficient ?? false);
296
+ const state = deriveInsightState({
297
+ status,
298
+ hasFinding,
299
+ hasData,
300
+ insufficient,
301
+ filtered
302
+ });
303
+ const showContent = state === "ready" || state === "refreshing" || state === "insufficient";
304
+ const severity = summary?.severity ?? severityProp ?? "info";
305
+ const polarity = summary?.polarity ?? "neutral";
306
+ const plotEvidence = showContent ? summary?.evidence ?? "none" : "none";
307
+ const asOfText = useMemo(() => {
308
+ if (updatedAt == null) return null;
309
+ return typeof updatedAtFormat === "function" ? updatedAtFormat(new Date(updatedAt)) : formatDate(updatedAt, {
310
+ granularity: updatedAtFormat,
311
+ locale,
312
+ timeZone
313
+ });
314
+ }, [
315
+ updatedAt,
316
+ updatedAtFormat,
317
+ locale,
318
+ timeZone
319
+ ]);
320
+ const detectedAtText = useMemo(() => {
321
+ if (detectedAt == null) return null;
322
+ return typeof detectedAtFormat === "function" ? detectedAtFormat(new Date(detectedAt)) : formatDate(detectedAt, {
323
+ granularity: detectedAtFormat,
324
+ locale,
325
+ timeZone
326
+ });
327
+ }, [
328
+ detectedAt,
329
+ detectedAtFormat,
330
+ locale,
331
+ timeZone
332
+ ]);
333
+ const atText = useMemo(() => summary?.at != null ? formatDate(summary.at, {
334
+ granularity,
335
+ locale,
336
+ timeZone
337
+ }) : null, [
338
+ summary,
339
+ granularity,
340
+ locale,
341
+ timeZone
342
+ ]);
343
+ const provenance = useMemo(() => buildInsightProvenance({
344
+ method,
345
+ confidence,
346
+ sampleSize,
347
+ detectedAtText,
348
+ locale,
349
+ labels
350
+ }), [
351
+ method,
352
+ confidence,
353
+ sampleSize,
354
+ detectedAtText,
355
+ locale,
356
+ labels
357
+ ]);
358
+ const cardDescription = description ?? buildInsightDescription({
359
+ name,
360
+ state,
361
+ statement: claimText,
362
+ kind,
363
+ severity,
364
+ summary,
365
+ formatters,
366
+ provenance,
367
+ asOfText,
368
+ labels
369
+ });
370
+ const datasets = useMemo(() => ({
371
+ [INSIGHT_POINTS_DATASET]: summary?.points ?? EMPTY_ROWS,
372
+ [INSIGHT_INTERVAL_DATASET]: summary?.interval ?? EMPTY_ROWS,
373
+ [INSIGHT_STRIP_DATASET]: summary?.strip ?? EMPTY_ROWS
374
+ }), [summary]);
375
+ const plotHeight = plotEvidence === "spark" ? sizes.spark : plotEvidence === "range" ? sizes.strip : 0;
376
+ const hasPlot = plotEvidence !== "none";
377
+ const plotWidth = usePlotWidth(plotRef, hasPlot);
378
+ const sparkBand = summary?.hasBand ?? false;
379
+ const sparkExpectedLine = summary?.hasExpectedLine ?? false;
380
+ const sparkInterval = (summary?.interval.length ?? 0) > 0;
381
+ const stripBand = summary?.strip[0]?.lo != null && summary?.strip[0]?.hi != null;
382
+ const stripExpected = summary?.strip[0]?.e != null;
383
+ const resolvedXType = summary?.xType ?? "temporal";
384
+ const timeFormat = [
385
+ granularity,
386
+ locale ?? "",
387
+ timeZone ?? ""
388
+ ].join("@").replace(/@+$/, "");
389
+ const spanMs = useMemo(() => {
390
+ const rows = summary?.points ?? [];
391
+ if (resolvedXType !== "temporal" || rows.length < 2) return null;
392
+ const first = rows[0]?.x;
393
+ const last = rows[rows.length - 1]?.x;
394
+ return typeof first === "number" && typeof last === "number" ? last - first : null;
395
+ }, [summary, resolvedXType]);
396
+ const axisTimeFormat = [
397
+ insightAxisGranularity(granularity, spanMs),
398
+ locale ?? "",
399
+ timeZone ?? ""
400
+ ].join("@").replace(/@+$/, "");
401
+ const valueFormat = locale ? `${format}@${locale}` : format;
402
+ const spec = useMemo(() => {
403
+ if (!tokens || plotEvidence === "none") return null;
404
+ const built = plotEvidence === "spark" ? buildInsightSparkSpec({
405
+ height: sizes.spark,
406
+ xType: resolvedXType,
407
+ axes,
408
+ zero: zeroScale,
409
+ band: sparkBand,
410
+ expectedLine: sparkExpectedLine,
411
+ interval: sparkInterval,
412
+ tooltip: true,
413
+ xTitle: labels.tablePeriod,
414
+ valueTitle: name,
415
+ expectedTitle: labels.expected,
416
+ valueFormat,
417
+ timeFormat,
418
+ axisTimeFormat,
419
+ yTicks: sizes.yTicks,
420
+ locale
421
+ }, tokens) : buildInsightStripSpec({
422
+ height: sizes.strip,
423
+ band: stripBand,
424
+ expected: stripExpected,
425
+ tooltip: true,
426
+ observedTitle: labels.observed,
427
+ expectedTitle: labels.expected,
428
+ lowerTitle: `${labels.expected} ↓`,
429
+ upperTitle: `${labels.expected} ↑`,
430
+ valueFormat,
431
+ locale
432
+ }, tokens);
433
+ return patchSpec ? patchSpec(built) : built;
434
+ }, [
435
+ tokens,
436
+ plotEvidence,
437
+ sizes.spark,
438
+ sizes.strip,
439
+ sizes.yTicks,
440
+ resolvedXType,
441
+ axes,
442
+ zeroScale,
443
+ sparkBand,
444
+ sparkExpectedLine,
445
+ sparkInterval,
446
+ stripBand,
447
+ stripExpected,
448
+ labels,
449
+ name,
450
+ valueFormat,
451
+ timeFormat,
452
+ axisTimeFormat,
453
+ locale,
454
+ patchSpec
455
+ ]);
456
+ const chartDescription = summary && hasPlot ? buildInsightChartDescription({
457
+ name,
458
+ summary,
459
+ formatters,
460
+ atText,
461
+ labels
462
+ }) : 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
+ if (!datum) return null;
467
+ const num = (key) => typeof datum[key] === "number" ? datum[key] : null;
468
+ const rows = [];
469
+ if (plotEvidence === "spark") {
470
+ const x = datum.x;
471
+ rows.push([labels.tablePeriod, formatInsightX(x ?? null, {
472
+ xType: resolvedXType,
473
+ granularity,
474
+ locale,
475
+ timeZone
476
+ })]);
477
+ rows.push([labels.observed, formatters.formatValue(num("y"))]);
478
+ const expected = num("e");
479
+ if (expected != null) rows.push([labels.expected, formatters.formatValue(expected)]);
480
+ const range = formatters.formatRange(num("lo"), num("hi"));
481
+ if (range) rows.push([labels.tableRange, range]);
482
+ } else {
483
+ rows.push([labels.observed, formatters.formatValue(num("v"))]);
484
+ const expected = num("e");
485
+ if (expected != null) rows.push([labels.expected, formatters.formatValue(expected)]);
486
+ const range = formatters.formatRange(num("lo"), num("hi"));
487
+ if (range) rows.push([labels.tableRange, range]);
488
+ }
489
+ return /* @__PURE__ */ jsx(ArcTooltipRows, { rows });
490
+ }, [
491
+ plotEvidence,
492
+ labels,
493
+ formatters,
494
+ resolvedXType,
495
+ granularity,
496
+ locale,
497
+ timeZone
498
+ ]);
499
+ const { handler: tooltipHandler, tooltip } = useArcTooltipHandler({ content: tooltipContent });
500
+ const embedOptions = useMemo(() => arcEmbedOptions({ tooltip: tooltipHandler }), [tooltipHandler]);
501
+ const observedText = summary?.value != null ? formatters.formatValue(summary.value) : null;
502
+ const rangeText = summary ? formatters.formatRange(summary.lower, summary.upper) : null;
503
+ const expectedText = rangeText ?? (summary?.expected != null ? formatters.formatValue(summary.expected) : null);
504
+ const deviationText = summary?.value != null && summary.expected != null ? formatters.formatDeviation(summary.value, summary.expected) : null;
505
+ const strengthText = summary ? formatters.formatStrength(summary.strength, summary.strengthKind) : null;
506
+ const keyCells = [
507
+ observedText ? {
508
+ key: "observed",
509
+ label: labels.observed,
510
+ value: observedText,
511
+ tone: "plain"
512
+ } : null,
513
+ expectedText ? {
514
+ key: "expected",
515
+ label: labels.expected,
516
+ value: expectedText,
517
+ tone: "muted"
518
+ } : null,
519
+ deviationText ? {
520
+ key: "deviation",
521
+ label: labels.deviation,
522
+ value: deviationText,
523
+ tone: "delta"
524
+ } : null
525
+ ].filter((cell) => cell != null);
526
+ const keyRows = keyCells.length > 0 ? Math.ceil(keyCells.length / sizes.keyColumns) : 0;
527
+ const statementLines = Math.max(1, expectedLines);
528
+ const loading = state === "loading";
529
+ const reservedKeyRows = loading ? Math.ceil(3 / sizes.keyColumns) : keyRows;
530
+ const provenanceLines = provenance.length >= 3 ? 2 : 1;
531
+ const bodyMinHeight = (hasStatement || loading ? statementLines * sizes.statementPx : 0) + (reservedKeyRows > 0 ? sizes.gapPx + reservedKeyRows * sizes.keyRowPx : 0) + (hasPlot || loading ? sizes.gapPx + (hasPlot ? plotHeight : sizes.spark) : 0) + (state === "insufficient" ? sizes.gapPx + sizes.captionPx : 0) + (provenance.length > 0 ? sizes.gapPx + provenanceLines * sizes.captionPx : 0);
532
+ const HeadingTag = `h${titleLevel}`;
533
+ const busy = state === "loading" || state === "refreshing";
534
+ const badgeText = labels.badge(labels.severityNames[severity], labels.kindNames[kind], severity);
535
+ const hasTable = showContent && summary != null && (summary.points.length > 0 || summary.value != null);
536
+ const showFeedback = onFeedback != null;
537
+ const showFooter = primaryAction != null || showFeedback;
538
+ return /* @__PURE__ */ jsxs(Box, {
539
+ ref: setRootRef,
540
+ render: render ?? /* @__PURE__ */ jsx("figure", {}),
541
+ padding: sizes.padding,
542
+ "aria-labelledby": headingId,
543
+ "aria-describedby": descriptionId,
544
+ "aria-busy": busy || void 0,
545
+ "data-status": status,
546
+ "data-state": state,
547
+ "data-size": size,
548
+ "data-kind": kind,
549
+ "data-severity": severity,
550
+ "data-polarity": polarity,
551
+ "data-evidence": plotEvidence,
552
+ "data-strength": summary?.strengthKind ?? void 0,
553
+ "data-outside": summary?.outside ? "" : void 0,
554
+ "data-feedback": chosen ?? void 0,
555
+ "data-stale": stale ? "" : void 0,
556
+ "data-empty": state === "empty" || state === "no-match" ? "" : void 0,
557
+ className: cn("relative flex min-w-0 flex-col", sizes.gap, className),
558
+ ...rest,
559
+ children: [
560
+ /* @__PURE__ */ jsx("div", {
561
+ ref: setPopoverContainer,
562
+ className: "contents"
563
+ }),
564
+ /* @__PURE__ */ jsxs("div", {
565
+ className: "flex min-w-0 items-start justify-between gap-2",
566
+ children: [/* @__PURE__ */ jsxs("div", {
567
+ className: "flex min-w-0 flex-wrap items-center gap-x-2 gap-y-1",
568
+ children: [
569
+ /* @__PURE__ */ jsxs(Badge, {
570
+ variant: severityBadge[severity],
571
+ appearance: "soft",
572
+ size: "sm",
573
+ "data-part": "badge",
574
+ children: [/* @__PURE__ */ jsx(KindGlyph, {
575
+ kind,
576
+ className: "size-3"
577
+ }), badgeText]
578
+ }),
579
+ /* @__PURE__ */ jsx(HeadingTag, {
580
+ id: headingId,
581
+ className: cn(labelClasses, sizes.label, "truncate"),
582
+ "data-part": "label",
583
+ children: label
584
+ }),
585
+ hint && /* @__PURE__ */ jsx("span", {
586
+ id: hintId,
587
+ className: "sr-only",
588
+ children: hint
589
+ })
590
+ ]
591
+ }), /* @__PURE__ */ jsxs("div", {
592
+ className: "flex shrink-0 items-center gap-1",
593
+ children: [
594
+ hint && /* @__PURE__ */ jsxs(Tooltip, { children: [/* @__PURE__ */ jsx(TooltipTrigger, {
595
+ delay: 150,
596
+ render: /* @__PURE__ */ jsx(Button, {
597
+ variant: "ghost",
598
+ size: "sm",
599
+ iconOnly: true,
600
+ circular: true,
601
+ "aria-label": labels.about(name),
602
+ "aria-describedby": hintId,
603
+ className: headerControlClasses
604
+ }),
605
+ children: /* @__PURE__ */ jsx(InfoIcon, { className: "size-3.5" })
606
+ }), /* @__PURE__ */ jsx(TooltipPopup, {
607
+ side: "top",
608
+ sideOffset: 6,
609
+ container: popoverContainer,
610
+ children: hint
611
+ })] }),
612
+ stale && /* @__PURE__ */ jsx(Badge, {
613
+ variant: "warning",
614
+ appearance: "soft",
615
+ size: "sm",
616
+ "data-part": "stale",
617
+ children: labels.stale
618
+ }),
619
+ hasTable && /* @__PURE__ */ jsxs(Popover, {
620
+ open: tableOpen,
621
+ onOpenChange: setTableOpen,
622
+ children: [!hideTableToggle && /* @__PURE__ */ jsx(PopoverTrigger, {
623
+ render: /* @__PURE__ */ jsx(Button, {
624
+ variant: "ghost",
625
+ size: "sm",
626
+ iconOnly: true,
627
+ circular: true,
628
+ "aria-label": tableOpen ? labels.hideTable(name) : labels.showTable(name),
629
+ className: headerControlClasses
630
+ }),
631
+ children: /* @__PURE__ */ jsx(TableIcon, { className: "size-3.5" })
632
+ }), popoverContainer && summary && /* @__PURE__ */ jsxs(PopoverPopup, {
633
+ id: tableId,
634
+ anchor: rootRef,
635
+ container: popoverContainer,
636
+ side: "right",
637
+ align: "start",
638
+ collisionPadding: 8,
639
+ className: "pointer-events-auto w-[min(30rem,var(--available-width))]",
640
+ "data-part": "data-popover",
641
+ children: [/* @__PURE__ */ jsx(PopoverTitle, {
642
+ className: "mb-3",
643
+ children: name
644
+ }), /* @__PURE__ */ jsx(TableContainer, {
645
+ variant: "plain",
646
+ tabIndex: 0,
647
+ role: "region",
648
+ "aria-label": labels.tableCaption(name),
649
+ className: "max-h-[min(18rem,calc(var(--available-height)-6rem))] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring",
650
+ "data-part": "table",
651
+ children: /* @__PURE__ */ jsxs(Table, {
652
+ size: "sm",
653
+ stickyHeader: true,
654
+ hoverable: false,
655
+ children: [/* @__PURE__ */ jsx(TableCaption, {
656
+ side: "top",
657
+ className: "sr-only",
658
+ children: labels.tableCaption(name)
659
+ }), summary.points.length > 0 ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(TableHeader, { children: /* @__PURE__ */ jsxs(TableRow, { children: [
660
+ /* @__PURE__ */ jsx(TableHead, { children: labels.tablePeriod }),
661
+ /* @__PURE__ */ jsx(TableHead, {
662
+ className: "text-right",
663
+ children: labels.tableValue
664
+ }),
665
+ /* @__PURE__ */ jsx(TableHead, {
666
+ className: "text-right",
667
+ children: labels.tableExpected
668
+ }),
669
+ /* @__PURE__ */ jsx(TableHead, {
670
+ className: "text-right",
671
+ children: labels.tableRange
672
+ })
673
+ ] }) }), /* @__PURE__ */ jsx(TableBody, { children: summary.points.map((row) => /* @__PURE__ */ jsxs(TableRow, {
674
+ "data-flagged": row.f ? "" : void 0,
675
+ children: [
676
+ /* @__PURE__ */ jsxs(TableCell, {
677
+ className: cn(row.f && "font-semibold text-foreground"),
678
+ children: [formatInsightX(row.x, {
679
+ xType: resolvedXType,
680
+ granularity,
681
+ locale,
682
+ timeZone
683
+ }), row.f && /* @__PURE__ */ jsxs("span", {
684
+ className: "sr-only",
685
+ children: [
686
+ " (",
687
+ labels.flagged,
688
+ ")"
689
+ ]
690
+ })]
691
+ }),
692
+ /* @__PURE__ */ jsx(TableCell, {
693
+ className: cn("text-right tabular-nums", row.f && "font-semibold text-foreground"),
694
+ children: formatters.formatValue(row.y)
695
+ }),
696
+ /* @__PURE__ */ jsx(TableCell, {
697
+ className: "text-right text-muted-foreground tabular-nums",
698
+ children: formatters.formatValue(row.e)
699
+ }),
700
+ /* @__PURE__ */ jsx(TableCell, {
701
+ className: "text-right text-muted-foreground tabular-nums",
702
+ children: formatters.formatRange(row.lo, row.hi) ?? "—"
703
+ })
704
+ ]
705
+ }, String(row.x))) })] }) : /* @__PURE__ */ jsxs(TableBody, { children: [
706
+ /* @__PURE__ */ jsxs(TableRow, { children: [/* @__PURE__ */ jsx(TableCell, { children: labels.observed }), /* @__PURE__ */ jsx(TableCell, {
707
+ className: "text-right font-semibold tabular-nums",
708
+ children: formatters.formatValue(summary.value)
709
+ })] }),
710
+ /* @__PURE__ */ jsxs(TableRow, { children: [/* @__PURE__ */ jsx(TableCell, { children: labels.tableExpected }), /* @__PURE__ */ jsx(TableCell, {
711
+ className: "text-right tabular-nums",
712
+ children: formatters.formatValue(summary.expected)
713
+ })] }),
714
+ /* @__PURE__ */ jsxs(TableRow, { children: [/* @__PURE__ */ jsx(TableCell, { children: labels.tableRange }), /* @__PURE__ */ jsx(TableCell, {
715
+ className: "text-right tabular-nums",
716
+ children: formatters.formatRange(summary.lower, summary.upper) ?? "—"
717
+ })] })
718
+ ] })]
719
+ })
720
+ })]
721
+ })]
722
+ }),
723
+ action,
724
+ onDismiss && /* @__PURE__ */ jsx(Button, {
725
+ variant: "ghost",
726
+ size: "sm",
727
+ iconOnly: true,
728
+ circular: true,
729
+ onClick: onDismiss,
730
+ "aria-label": labels.dismiss(name),
731
+ className: headerControlClasses,
732
+ "data-part": "dismiss",
733
+ children: /* @__PURE__ */ jsx(CloseIcon, { className: "size-3.5" })
734
+ })
735
+ ]
736
+ })]
737
+ }),
738
+ /* @__PURE__ */ jsx("p", {
739
+ id: descriptionId,
740
+ className: "sr-only",
741
+ children: cardDescription
742
+ }),
743
+ /* @__PURE__ */ jsxs("div", {
744
+ className: "relative flex min-w-0 flex-col",
745
+ style: { minHeight: bodyMinHeight },
746
+ children: [
747
+ loading && /* @__PURE__ */ jsxs(SkeletonGroup, {
748
+ className: cn("flex flex-col", sizes.gap),
749
+ children: [
750
+ /* @__PURE__ */ jsx("div", {
751
+ className: "flex flex-col gap-1",
752
+ children: Array.from({ length: statementLines }, (_, index) => /* @__PURE__ */ jsx(Skeleton, {
753
+ variant: "text",
754
+ className: index === statementLines - 1 ? "w-3/5" : "w-full",
755
+ style: { height: sizes.statementPx - 6 }
756
+ }, index))
757
+ }),
758
+ /* @__PURE__ */ jsx("div", {
759
+ className: cn("grid gap-x-4 gap-y-1", sizes.keyColumns === 2 ? "grid-cols-2" : "grid-cols-3"),
760
+ style: { minHeight: reservedKeyRows * sizes.keyRowPx },
761
+ children: Array.from({ length: 3 }, (_, index) => /* @__PURE__ */ jsxs("div", {
762
+ className: "flex flex-col gap-1",
763
+ children: [/* @__PURE__ */ jsx(Skeleton, {
764
+ variant: "text",
765
+ className: "w-3/5",
766
+ style: { height: sizes.captionPx - 6 }
767
+ }), /* @__PURE__ */ jsx(Skeleton, {
768
+ variant: "text",
769
+ className: "w-4/5",
770
+ style: { height: sizes.captionPx - 4 }
771
+ })]
772
+ }, index))
773
+ }),
774
+ /* @__PURE__ */ jsx(Skeleton, {
775
+ variant: "rounded",
776
+ className: "w-full",
777
+ style: { height: sizes.spark }
778
+ })
779
+ ]
780
+ }),
781
+ state === "error" && /* @__PURE__ */ jsx(SystemState, {
782
+ variant: "server-error",
783
+ scope: "inline",
784
+ title: labels.error,
785
+ description: false,
786
+ action: onRetry ? /* @__PURE__ */ jsx(Button, {
787
+ size: "sm",
788
+ onClick: onRetry,
789
+ children: labels.retry
790
+ }) : void 0,
791
+ className: cn(tileStateClasses, "my-auto")
792
+ }),
793
+ state === "empty" && /* @__PURE__ */ jsx(SystemState, {
794
+ variant: "empty",
795
+ scope: "inline",
796
+ title: labels.noData,
797
+ description: false,
798
+ className: cn(tileStateClasses, "my-auto")
799
+ }),
800
+ state === "no-match" && /* @__PURE__ */ jsx(SystemState, {
801
+ variant: "no-results",
802
+ scope: "inline",
803
+ title: labels.noMatch,
804
+ description: false,
805
+ action: onClearFilters ? /* @__PURE__ */ jsx(Button, {
806
+ size: "sm",
807
+ variant: "secondary",
808
+ onClick: onClearFilters,
809
+ children: labels.clearFilters
810
+ }) : void 0,
811
+ className: cn(tileStateClasses, "my-auto")
812
+ }),
813
+ showContent && /* @__PURE__ */ jsxs("div", {
814
+ className: cn("flex min-w-0 flex-col", sizes.gap, state === "refreshing" && "bg-veil"),
815
+ children: [
816
+ hasStatement && /* @__PURE__ */ jsxs("div", {
817
+ className: "flex min-w-0 items-start gap-2",
818
+ "data-part": "statement",
819
+ children: [generated && /* @__PURE__ */ jsx(AILoader, {
820
+ size: "sm",
821
+ state: "default",
822
+ label: labels.insightMark,
823
+ className: "mt-1 shrink-0"
824
+ }), /* @__PURE__ */ jsx("p", {
825
+ className: cn("min-w-0 flex-1 font-heading font-semibold text-foreground leading-snug", sizes.statement, "[&_strong]:font-semibold [&_strong]:text-foreground"),
826
+ style: {
827
+ display: "-webkit-box",
828
+ WebkitBoxOrient: "vertical",
829
+ WebkitLineClamp: statementLines,
830
+ overflow: "hidden"
831
+ },
832
+ children: statement
833
+ })]
834
+ }),
835
+ keyCells.length > 0 && /* @__PURE__ */ jsx("dl", {
836
+ className: cn("grid min-w-0 gap-x-4 gap-y-1", sizes.keyColumns === 2 ? "grid-cols-2" : "grid-cols-3"),
837
+ "data-part": "key-row",
838
+ children: keyCells.map((cell) => /* @__PURE__ */ jsxs("div", {
839
+ className: "flex min-w-0 flex-col",
840
+ "data-part": `key-${cell.key}`,
841
+ children: [/* @__PURE__ */ jsx("dt", {
842
+ className: cn(captionClasses, "truncate"),
843
+ children: cell.label
844
+ }), /* @__PURE__ */ jsx("dd", {
845
+ className: cn("truncate font-sans font-semibold tabular-nums", sizes.body, cell.tone === "muted" && "text-muted-foreground", cell.tone === "plain" && "text-foreground", cell.tone === "delta" && polarityTextClasses[polarity]),
846
+ children: cell.tone === "delta" && summary ? /* @__PURE__ */ jsxs("span", {
847
+ className: "inline-flex min-w-0 items-center gap-0.5",
848
+ children: [
849
+ /* @__PURE__ */ jsx(DeltaGlyph, {
850
+ direction: summary.direction,
851
+ className: "size-3 shrink-0"
852
+ }),
853
+ /* @__PURE__ */ jsxs("span", {
854
+ className: "sr-only",
855
+ children: [labels.directionWords[summary.direction], " "]
856
+ }),
857
+ /* @__PURE__ */ jsx("span", {
858
+ className: "truncate",
859
+ children: cell.value
860
+ })
861
+ ]
862
+ }) : cell.value
863
+ })]
864
+ }, cell.key))
865
+ }),
866
+ hasPlot && /* @__PURE__ */ jsx("div", {
867
+ ref: plotRef,
868
+ className: "relative w-full",
869
+ style: { height: plotHeight },
870
+ "data-part": "plot-block",
871
+ children: plotWidth > 0 && spec && /* @__PURE__ */ jsx(ArcVegaChart, {
872
+ spec,
873
+ options: embedOptions,
874
+ datasets,
875
+ description: chartDescription,
876
+ width: plotWidth,
877
+ height: plotHeight,
878
+ onEmbed,
879
+ className: "absolute inset-0 [&_svg]:block [&_.vega-bindings:empty]:hidden",
880
+ "data-part": "plot",
881
+ fallback: /* @__PURE__ */ jsx(Skeleton, {
882
+ variant: "rounded",
883
+ className: "absolute inset-0"
884
+ })
885
+ })
886
+ }),
887
+ state === "insufficient" && /* @__PURE__ */ jsx("p", {
888
+ className: cn(captionClasses, "min-w-0"),
889
+ "data-part": "insufficient",
890
+ children: labels.needsHistory
891
+ }),
892
+ (strengthText || rangeText) && /* @__PURE__ */ jsxs("p", {
893
+ className: "sr-only",
894
+ "data-part": "claim-text",
895
+ children: [rangeText ? summary?.outside ? labels.outsideRange(rangeText) : labels.insideRange(rangeText) : null, strengthText ? ` ${strengthText}.` : null]
896
+ }),
897
+ provenance.length > 0 && /* @__PURE__ */ jsx("p", {
898
+ className: cn(captionClasses, "min-w-0"),
899
+ "data-part": "provenance",
900
+ children: provenance.join(" · ")
901
+ })
902
+ ]
903
+ })
904
+ ]
905
+ }),
906
+ showFooter && showContent && /* @__PURE__ */ jsxs("div", {
907
+ className: "flex min-w-0 flex-wrap items-center justify-between gap-2",
908
+ "data-part": "footer",
909
+ children: [/* @__PURE__ */ jsx("div", {
910
+ className: "min-w-0",
911
+ children: primaryAction
912
+ }), showFeedback && /* @__PURE__ */ jsxs("div", {
913
+ role: "group",
914
+ "aria-label": labels.feedbackGroup(name),
915
+ className: "flex shrink-0 items-center gap-1",
916
+ "data-part": "feedback",
917
+ children: [/* @__PURE__ */ jsx(Toggle, {
918
+ variant: "ghost",
919
+ size: "sm",
920
+ pressed: chosen === "helpful",
921
+ onPressedChange: (pressed) => chooseFeedback("helpful", pressed),
922
+ "aria-label": labels.helpful,
923
+ className: "size-7 min-w-0 text-muted-foreground hover:text-foreground",
924
+ "data-part": "feedback-helpful",
925
+ children: /* @__PURE__ */ jsx(ThumbIcon, { className: "size-3.5" })
926
+ }), /* @__PURE__ */ jsx(Toggle, {
927
+ variant: "ghost",
928
+ size: "sm",
929
+ pressed: chosen === "not-helpful",
930
+ onPressedChange: (pressed) => chooseFeedback("not-helpful", pressed),
931
+ "aria-label": labels.notHelpful,
932
+ className: "size-7 min-w-0 text-muted-foreground hover:text-foreground",
933
+ "data-part": "feedback-not-helpful",
934
+ children: /* @__PURE__ */ jsx(ThumbIcon, {
935
+ down: true,
936
+ className: "size-3.5"
937
+ })
938
+ })]
939
+ })]
940
+ }),
941
+ /* @__PURE__ */ jsx("p", {
942
+ role: "status",
943
+ className: "sr-only",
944
+ children: chosen ? chosen === "helpful" ? labels.helpful : labels.notHelpful : ""
945
+ }),
946
+ asOfText && /* @__PURE__ */ jsxs("figcaption", {
947
+ className: cn(captionClasses, "text-right"),
948
+ "data-part": "as-of",
949
+ children: [
950
+ labels.asOf,
951
+ " ",
952
+ asOfText
953
+ ]
954
+ }),
955
+ tooltip
956
+ ]
957
+ });
958
+ });
959
+ InsightCard.displayName = "InsightCard";
960
+ //#endregion
961
+ export { InsightCard };