@mastra/playground-ui 58.0.0 → 58.1.0-alpha.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 (176) hide show
  1. package/dist/{Badge-TD55_qZJ.js → Badge-Bzn8Z-_I.js} +2 -2
  2. package/dist/Badge-Bzn8Z-_I.js.map +1 -0
  3. package/dist/{Badge-BEeYtjmv.cjs → Badge-DFNxcz-r.cjs} +2 -2
  4. package/dist/Badge-DFNxcz-r.cjs.map +1 -0
  5. package/dist/{ask-user-jDUt7hgT.js → ask-user-DtF4a9Vr.js} +2 -2
  6. package/dist/{ask-user-jDUt7hgT.js.map → ask-user-DtF4a9Vr.js.map} +1 -1
  7. package/dist/{ask-user-BPpgiE7k.cjs → ask-user-pPTuoPKI.cjs} +2 -2
  8. package/dist/{ask-user-BPpgiE7k.cjs.map → ask-user-pPTuoPKI.cjs.map} +1 -1
  9. package/dist/{chat-notification-CmdRGO_D.js → chat-notification-C4P2InUX.js} +2 -2
  10. package/dist/{chat-notification-CmdRGO_D.js.map → chat-notification-C4P2InUX.js.map} +1 -1
  11. package/dist/{chat-notification-DJykWtoj.cjs → chat-notification-HP18KxlS.cjs} +2 -2
  12. package/dist/{chat-notification-DJykWtoj.cjs.map → chat-notification-HP18KxlS.cjs.map} +1 -1
  13. package/dist/{chat-signal-xs3FkPts.cjs → chat-signal-BP9RN6Rh.cjs} +2 -2
  14. package/dist/{chat-signal-xs3FkPts.cjs.map → chat-signal-BP9RN6Rh.cjs.map} +1 -1
  15. package/dist/{chat-signal-Vg8pGXwH.js → chat-signal-CQnmFp3V.js} +2 -2
  16. package/dist/{chat-signal-Vg8pGXwH.js.map → chat-signal-CQnmFp3V.js.map} +1 -1
  17. package/dist/components/Badge.cjs.js +1 -1
  18. package/dist/components/Badge.es.js +1 -1
  19. package/dist/components/DataList.cjs.js +1 -1
  20. package/dist/components/DataList.es.js +1 -1
  21. package/dist/components/ItemList.cjs.js +1 -1
  22. package/dist/components/ItemList.es.js +1 -1
  23. package/dist/components/LogsDataList.cjs.js +1 -1
  24. package/dist/components/LogsDataList.es.js +1 -1
  25. package/dist/components/MetricsCard.cjs.js +1 -1
  26. package/dist/components/MetricsCard.es.js +1 -1
  27. package/dist/components/MetricsCardGroup.cjs.js +2 -11
  28. package/dist/components/MetricsCardGroup.cjs.js.map +1 -1
  29. package/dist/components/MetricsCardGroup.es.js +2 -11
  30. package/dist/components/MetricsCardGroup.es.js.map +1 -1
  31. package/dist/components/MetricsKpiCard.cjs.js +1 -1
  32. package/dist/components/MetricsKpiCard.es.js +1 -1
  33. package/dist/components/MetricsLineChart.cjs.js +2 -1
  34. package/dist/components/MetricsLineChart.cjs.js.map +1 -1
  35. package/dist/components/MetricsLineChart.es.js +1 -1
  36. package/dist/components/PageHeader.cjs.js +1 -1
  37. package/dist/components/PageHeader.es.js +1 -1
  38. package/dist/components/Workflow.cjs.js +1 -1
  39. package/dist/components/Workflow.es.js +1 -1
  40. package/dist/components/ai/ask-user.cjs.js +1 -1
  41. package/dist/components/ai/ask-user.es.js +1 -1
  42. package/dist/components/ai/chat-event.cjs.js +2 -2
  43. package/dist/components/ai/chat-event.es.js +3 -3
  44. package/dist/components/ai/plan.cjs.js +1 -1
  45. package/dist/components/ai/plan.es.js +1 -1
  46. package/dist/components/ai/task-list.cjs.js +370 -55
  47. package/dist/components/ai/task-list.cjs.js.map +1 -1
  48. package/dist/components/ai/task-list.es.js +374 -58
  49. package/dist/components/ai/task-list.es.js.map +1 -1
  50. package/dist/domains/chat/messages/notification-signal-notice.cjs.js +1 -1
  51. package/dist/domains/chat/messages/notification-signal-notice.es.js +1 -1
  52. package/dist/domains/chat/messages/renderers/message-text.cjs.js +1 -1
  53. package/dist/domains/chat/messages/renderers/message-text.es.js +1 -1
  54. package/dist/domains/chat/messages/signal-badge.cjs.js +1 -1
  55. package/dist/domains/chat/messages/signal-badge.es.js +1 -1
  56. package/dist/domains/chat/messages/tripwire-notice.cjs.js +1 -1
  57. package/dist/domains/chat/messages/tripwire-notice.es.js +1 -1
  58. package/dist/domains/chat/tools/badges/ask-user-badge.cjs.js +1 -1
  59. package/dist/domains/chat/tools/badges/ask-user-badge.es.js +1 -1
  60. package/dist/domains/chat/tools/badges/observation-marker-badge.cjs.js +1 -1
  61. package/dist/domains/chat/tools/badges/observation-marker-badge.es.js +1 -1
  62. package/dist/domains/logs/components/logs-list-view.cjs.js +1 -1
  63. package/dist/domains/logs/components/logs-list-view.es.js +1 -1
  64. package/dist/domains/metrics/components/kpi-card-view.cjs.js +1 -1
  65. package/dist/domains/metrics/components/kpi-card-view.es.js +1 -1
  66. package/dist/domains/metrics/components/latency-card-view.cjs.js +33 -24
  67. package/dist/domains/metrics/components/latency-card-view.cjs.js.map +1 -1
  68. package/dist/domains/metrics/components/latency-card-view.es.js +34 -25
  69. package/dist/domains/metrics/components/latency-card-view.es.js.map +1 -1
  70. package/dist/domains/metrics/components/memory-card-view.cjs.js +3 -3
  71. package/dist/domains/metrics/components/memory-card-view.cjs.js.map +1 -1
  72. package/dist/domains/metrics/components/memory-card-view.es.js +3 -3
  73. package/dist/domains/metrics/components/memory-card-view.es.js.map +1 -1
  74. package/dist/domains/metrics/components/model-usage-cost-card-view.cjs.js +1 -1
  75. package/dist/domains/metrics/components/model-usage-cost-card-view.es.js +1 -1
  76. package/dist/domains/metrics/components/scores-card-view.cjs.js +4 -4
  77. package/dist/domains/metrics/components/scores-card-view.cjs.js.map +1 -1
  78. package/dist/domains/metrics/components/scores-card-view.es.js +4 -4
  79. package/dist/domains/metrics/components/scores-card-view.es.js.map +1 -1
  80. package/dist/domains/metrics/components/token-usage-by-agent-card-view.cjs.js +3 -3
  81. package/dist/domains/metrics/components/token-usage-by-agent-card-view.cjs.js.map +1 -1
  82. package/dist/domains/metrics/components/token-usage-by-agent-card-view.es.js +3 -3
  83. package/dist/domains/metrics/components/token-usage-by-agent-card-view.es.js.map +1 -1
  84. package/dist/domains/metrics/components/token-usage-timeline-card-view.cjs.js +10 -9
  85. package/dist/domains/metrics/components/token-usage-timeline-card-view.cjs.js.map +1 -1
  86. package/dist/domains/metrics/components/token-usage-timeline-card-view.es.js +10 -9
  87. package/dist/domains/metrics/components/token-usage-timeline-card-view.es.js.map +1 -1
  88. package/dist/domains/metrics/components/traces-volume-card-view.cjs.js +4 -4
  89. package/dist/domains/metrics/components/traces-volume-card-view.cjs.js.map +1 -1
  90. package/dist/domains/metrics/components/traces-volume-card-view.es.js +4 -4
  91. package/dist/domains/metrics/components/traces-volume-card-view.es.js.map +1 -1
  92. package/dist/domains/metrics/hooks/use-latency-metrics.cjs.js +11 -11
  93. package/dist/domains/metrics/hooks/use-latency-metrics.cjs.js.map +1 -1
  94. package/dist/domains/metrics/hooks/use-latency-metrics.es.js +12 -11
  95. package/dist/domains/metrics/hooks/use-latency-metrics.es.js.map +1 -1
  96. package/dist/domains/metrics/hooks/use-token-usage-timeseries.cjs.js +4 -12
  97. package/dist/domains/metrics/hooks/use-token-usage-timeseries.cjs.js.map +1 -1
  98. package/dist/domains/metrics/hooks/use-token-usage-timeseries.es.js +4 -12
  99. package/dist/domains/metrics/hooks/use-token-usage-timeseries.es.js.map +1 -1
  100. package/dist/domains/metrics/hooks.cjs.js +3 -0
  101. package/dist/domains/metrics/hooks.cjs.js.map +1 -1
  102. package/dist/domains/metrics/hooks.es.js +1 -0
  103. package/dist/domains/metrics/hooks.es.js.map +1 -1
  104. package/dist/domains/metrics/metrics-interval.cjs.js +18 -0
  105. package/dist/domains/metrics/metrics-interval.cjs.js.map +1 -0
  106. package/dist/domains/metrics/metrics-interval.d.ts +2 -0
  107. package/dist/domains/metrics/metrics-interval.es.js +13 -0
  108. package/dist/domains/metrics/metrics-interval.es.js.map +1 -0
  109. package/dist/domains/metrics.cjs.js +3 -0
  110. package/dist/domains/metrics.cjs.js.map +1 -1
  111. package/dist/domains/metrics.es.js +1 -0
  112. package/dist/domains/metrics.es.js.map +1 -1
  113. package/dist/domains/traces/components/span-type-legend.cjs.js +1 -1
  114. package/dist/domains/traces/components/span-type-legend.es.js +1 -1
  115. package/dist/domains/traces/components/traces-list-view.cjs.js +1 -1
  116. package/dist/domains/traces/components/traces-list-view.es.js +1 -1
  117. package/dist/ee/signals/components/entity-index-compact-grid.cjs.js +1 -1
  118. package/dist/ee/signals/components/entity-index-compact-grid.es.js +1 -1
  119. package/dist/ee/signals/components/entity-index-list.cjs.js +1 -1
  120. package/dist/ee/signals/components/entity-index-list.es.js +1 -1
  121. package/dist/ee/signals/settings/trace-signal-settings.cjs.js +1 -1
  122. package/dist/ee/signals/settings/trace-signal-settings.es.js +1 -1
  123. package/dist/{logs-data-list-YL9yLKF3.cjs → logs-data-list-BHvJOeec.cjs} +2 -2
  124. package/dist/{logs-data-list-YL9yLKF3.cjs.map → logs-data-list-BHvJOeec.cjs.map} +1 -1
  125. package/dist/{logs-data-list-5BAeLU57.js → logs-data-list-CgDcNIvS.js} +2 -2
  126. package/dist/{logs-data-list-5BAeLU57.js.map → logs-data-list-CgDcNIvS.js.map} +1 -1
  127. package/dist/{metrics-card-Bzm6m1dy.js → metrics-card-C2RTi5Ew.js} +7 -7
  128. package/dist/metrics-card-C2RTi5Ew.js.map +1 -0
  129. package/dist/{metrics-card-DCCHIG-z.cjs → metrics-card-DzcVJTAN.cjs} +7 -7
  130. package/dist/metrics-card-DzcVJTAN.cjs.map +1 -0
  131. package/dist/{metrics-kpi-card-BrnFhFQm.js → metrics-kpi-card-BVCuXeDa.js} +21 -10
  132. package/dist/metrics-kpi-card-BVCuXeDa.js.map +1 -0
  133. package/dist/{metrics-kpi-card-Bhb4R4z0.cjs → metrics-kpi-card-DoIeHfv6.cjs} +21 -10
  134. package/dist/metrics-kpi-card-DoIeHfv6.cjs.map +1 -0
  135. package/dist/{metrics-line-chart-0FR3SYSt.cjs → metrics-line-chart-BNNRRxM8.cjs} +61 -25
  136. package/dist/metrics-line-chart-BNNRRxM8.cjs.map +1 -0
  137. package/dist/{metrics-line-chart-knlgw8bV.js → metrics-line-chart-CT_pqJtC.js} +62 -27
  138. package/dist/metrics-line-chart-CT_pqJtC.js.map +1 -0
  139. package/dist/new/layout/page-header.cjs.js +1 -1
  140. package/dist/new/layout/page-header.es.js +1 -1
  141. package/dist/{page-header-CyXAezlZ.js → page-header-BGyZw13s.js} +2 -2
  142. package/dist/page-header-BGyZw13s.js.map +1 -0
  143. package/dist/{page-header-Dk3s3XtC.cjs → page-header-CqvBk1wE.cjs} +2 -2
  144. package/dist/page-header-CqvBk1wE.cjs.map +1 -0
  145. package/dist/src/domains/metrics/components/latency-card-view.d.ts +4 -1
  146. package/dist/src/domains/metrics/hooks/index.d.ts +1 -0
  147. package/dist/src/domains/metrics/hooks/use-latency-metrics.d.ts +2 -2
  148. package/dist/src/domains/metrics/hooks/use-token-usage-timeseries.d.ts +2 -1
  149. package/dist/src/domains/metrics/metrics-interval.d.ts +7 -0
  150. package/dist/src/ds/components/MetricsCardGroup/metrics-card-group.d.ts +3 -8
  151. package/dist/src/ds/components/MetricsLineChart/index.d.ts +1 -0
  152. package/dist/src/ds/components/MetricsLineChart/metrics-line-chart-legend.d.ts +6 -0
  153. package/dist/src/ds/components/MetricsLineChart/metrics-line-chart.d.ts +6 -4
  154. package/dist/src/ds/components/MetricsLineChart/metrics-line-chart.stories.d.ts +1 -0
  155. package/dist/src/ds/components/ai/task-list/task-graph-node.d.ts +8 -0
  156. package/dist/src/ds/components/ai/task-list/task-graph.d.ts +8 -0
  157. package/dist/src/ds/components/ai/task-list/task-list.d.ts +4 -8
  158. package/dist/src/ds/components/ai/task-list/task-list.stories.d.ts +1 -1
  159. package/dist/src/ds/components/ai/task-list/use-focused-row-scroll.d.ts +12 -0
  160. package/dist/src/ds/new/layout/page-header/page-header.stories.d.ts +1 -0
  161. package/dist/style.css +304 -14
  162. package/dist/{traces-data-list-Dvi0s56v.js → traces-data-list-B5MkMMBi.js} +2 -2
  163. package/dist/{traces-data-list-Dvi0s56v.js.map → traces-data-list-B5MkMMBi.js.map} +1 -1
  164. package/dist/{traces-data-list-Dam8-XW-.cjs → traces-data-list-D3k50j4n.cjs} +2 -2
  165. package/dist/{traces-data-list-Dam8-XW-.cjs.map → traces-data-list-D3k50j4n.cjs.map} +1 -1
  166. package/package.json +7 -7
  167. package/dist/Badge-BEeYtjmv.cjs.map +0 -1
  168. package/dist/Badge-TD55_qZJ.js.map +0 -1
  169. package/dist/metrics-card-Bzm6m1dy.js.map +0 -1
  170. package/dist/metrics-card-DCCHIG-z.cjs.map +0 -1
  171. package/dist/metrics-kpi-card-Bhb4R4z0.cjs.map +0 -1
  172. package/dist/metrics-kpi-card-BrnFhFQm.js.map +0 -1
  173. package/dist/metrics-line-chart-0FR3SYSt.cjs.map +0 -1
  174. package/dist/metrics-line-chart-knlgw8bV.js.map +0 -1
  175. package/dist/page-header-CyXAezlZ.js.map +0 -1
  176. package/dist/page-header-Dk3s3XtC.cjs.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics-kpi-card-DoIeHfv6.cjs","sources":["../src/ds/components/MetricsKpiCard/metrics-kpi-card-change.tsx","../src/ds/components/MetricsKpiCard/metrics-kpi-card-error.tsx","../src/ds/components/MetricsKpiCard/metrics-kpi-card-label.tsx","../src/ds/components/MetricsKpiCard/metrics-kpi-card-loading.tsx","../src/ds/components/MetricsKpiCard/metrics-kpi-card-no-change.tsx","../src/ds/components/MetricsKpiCard/metrics-kpi-card-no-data.tsx","../src/ds/components/MetricsKpiCard/metrics-kpi-card-root.tsx","../src/ds/components/MetricsKpiCard/metrics-kpi-card-value.tsx","../src/ds/components/MetricsKpiCard/metrics-kpi-card-value-row.tsx","../src/ds/components/MetricsKpiCard/metrics-kpi-card.tsx"],"sourcesContent":["import { ArrowDownRightIcon, ArrowUpRightIcon } from 'lucide-react';\nimport { Badge } from '@/ds/components/Badge';\nimport { cn } from '@/lib/utils';\n\nconst compact = new Intl.NumberFormat('en', { notation: 'compact', maximumFractionDigits: 1 });\n\n// Past +1000% a percentage is unreadable, so show how many times bigger the value got instead.\nfunction formatChange(changePct: number) {\n if (changePct >= 1000) return `×${compact.format(1 + changePct / 100)}`;\n const digits = Math.abs(changePct) < 10 ? 1 : 0;\n return `${changePct > 0 ? '+' : ''}${changePct.toFixed(digits)}%`;\n}\n\nexport function MetricsKpiCardChange({\n changePct,\n prevValue,\n lowerIsBetter,\n className,\n}: {\n changePct: number;\n prevValue?: string;\n lowerIsBetter?: boolean;\n className?: string;\n}) {\n const isGood = lowerIsBetter ? changePct < 0 : changePct >= 0;\n const Icon = changePct >= 0 ? ArrowUpRightIcon : ArrowDownRightIcon;\n const formattedChange = formatChange(changePct);\n\n return (\n <div className={cn('flex items-center gap-1.5', className)}>\n <Badge variant={isGood ? 'green' : 'red'} emphasis=\"muted\" size=\"xs\" icon={<Icon />} className=\"tabular-nums\">\n {formattedChange}\n </Badge>\n <span className=\"text-meta text-placeholder\">\n vs prior period\n {prevValue ? <span className=\"sr-only\">, previous value {prevValue}</span> : null}\n </span>\n </div>\n );\n}\n","import { cn } from '@/lib/utils';\n\nexport function MetricsKpiCardError({\n message = 'Failed to load data',\n className,\n}: {\n message?: string;\n className?: string;\n}) {\n return <span className={cn('text-meta text-accent2', className)}>{message}</span>;\n}\n","import { cn } from '@/lib/utils';\n\nexport function MetricsKpiCardLabel({ children, className }: { children: string; className?: string }) {\n return <span className={cn('text-body font-medium text-foreground', className)}>{children}</span>;\n}\n","import { Spinner } from '@/ds/components/Spinner/spinner';\nimport { cn } from '@/lib/utils';\n\nexport function MetricsKpiCardLoading({ className }: { className?: string }) {\n return (\n <span className={cn('text-body', className)}>\n <Spinner size=\"md\" variant=\"pulse\" className=\"text-placeholder\" />\n </span>\n );\n}\n","import { cn } from '@/lib/utils';\n\nexport function MetricsKpiCardNoChange({\n message = 'No previous value to compare',\n className,\n}: {\n message?: string;\n className?: string;\n}) {\n return <span className={cn('text-meta text-placeholder', className)}>{message}</span>;\n}\n","import { cn } from '@/lib/utils';\n\nexport function MetricsKpiCardNoData({ message = 'No data yet', className }: { message?: string; className?: string }) {\n return <span className={cn('text-meta text-placeholder', className)}>{message}</span>;\n}\n","import type { ReactNode } from 'react';\nimport { Card } from '@/ds/components/Card';\nimport { cn } from '@/lib/utils';\n\nexport function MetricsKpiCardRoot({ children, className }: { children: ReactNode; className?: string }) {\n return (\n <Card className={cn('min-w-72 flex-1 px-5 py-4', className)}>\n <div className=\"grid gap-1.5\">{children}</div>\n </Card>\n );\n}\n","import type { ReactNode } from 'react';\nimport { cn } from '@/lib/utils';\n\nexport function MetricsKpiCardValue({ children, className }: { children: ReactNode; className?: string }) {\n return (\n <strong\n className={cn(\n 'text-title font-semibold text-foreground tabular-nums [text-box:trim-both_cap_alphabetic]',\n className,\n )}\n >\n {children}\n </strong>\n );\n}\n","import type { ReactNode } from 'react';\nimport { cn } from '@/lib/utils';\n\nexport function MetricsKpiCardValueRow({ children, className }: { children: ReactNode; className?: string }) {\n return <div className={cn('flex min-h-6 flex-wrap items-center gap-x-2 gap-y-1', className)}>{children}</div>;\n}\n","import { MetricsKpiCardChange } from './metrics-kpi-card-change';\nimport { MetricsKpiCardError } from './metrics-kpi-card-error';\nimport { MetricsKpiCardLabel } from './metrics-kpi-card-label';\nimport { MetricsKpiCardLoading } from './metrics-kpi-card-loading';\nimport { MetricsKpiCardNoChange } from './metrics-kpi-card-no-change';\nimport { MetricsKpiCardNoData } from './metrics-kpi-card-no-data';\nimport { MetricsKpiCardRoot } from './metrics-kpi-card-root';\nimport { MetricsKpiCardValue } from './metrics-kpi-card-value';\nimport { MetricsKpiCardValueRow } from './metrics-kpi-card-value-row';\n\nexport const MetricsKpiCard = Object.assign(MetricsKpiCardRoot, {\n Label: MetricsKpiCardLabel,\n ValueRow: MetricsKpiCardValueRow,\n Value: MetricsKpiCardValue,\n Change: MetricsKpiCardChange,\n NoChange: MetricsKpiCardNoChange,\n NoData: MetricsKpiCardNoData,\n Error: MetricsKpiCardError,\n Loading: MetricsKpiCardLoading,\n});\n"],"names":["ArrowUpRightIcon","ArrowDownRightIcon","cn","jsx","Badge","jsxs","Spinner","Card"],"mappings":"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"}
@@ -2,9 +2,31 @@
2
2
 
3
3
  const jsxRuntime = require('react/jsx-runtime');
4
4
  const recharts = require('recharts');
5
+ const utils_cn = require('./cn-DG0X1KEP.cjs');
5
6
  const chartTooltip = require('./chart-tooltip-DX6vs_Tc.cjs');
6
7
  const tokens = require('./tokens.cjs.js');
7
8
 
9
+ function MetricsLineChartLegend({
10
+ data,
11
+ series,
12
+ className
13
+ }) {
14
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: utils_cn.cn("flex flex-wrap items-center gap-4 gap-y-1", className), children: series.map((s) => {
15
+ const aggregated = s.aggregate?.(data);
16
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "inline-flex items-center gap-2", children: [
17
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "size-2 shrink-0 rounded-full", style: { backgroundColor: s.color } }),
18
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "max-w-24 truncate text-caption text-muted-foreground", children: s.label }),
19
+ aggregated && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-caption text-muted-foreground", children: [
20
+ aggregated.value,
21
+ aggregated.suffix && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-caption text-placeholder", children: [
22
+ " ",
23
+ aggregated.suffix
24
+ ] })
25
+ ] })
26
+ ] }, s.dataKey);
27
+ }) });
28
+ }
29
+
8
30
  function MetricsLineChartTooltip({
9
31
  active,
10
32
  payload,
@@ -14,51 +36,59 @@ function MetricsLineChartTooltip({
14
36
  if (!active || !payload?.length) return null;
15
37
  return /* @__PURE__ */ jsxRuntime.jsxs(chartTooltip.ChartTooltip, { children: [
16
38
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-1 text-column text-foreground", children: label }),
17
- payload.map((entry) => /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-placeholder", children: [
39
+ payload.map((entry) => /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-foreground", children: [
18
40
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "mr-2 inline-block size-2 rounded-full", style: { backgroundColor: entry.color } }),
19
41
  entry.name,
20
42
  ":",
21
43
  " ",
22
44
  /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-mono", children: [
23
- entry.value,
45
+ typeof entry.value === "number" ? entry.value.toLocaleString("en-US") : entry.value,
24
46
  suffix
25
47
  ] })
26
48
  ] }, entry.name))
27
49
  ] });
28
50
  }
29
51
 
52
+ const compactNumber = new Intl.NumberFormat("en", { notation: "compact", maximumFractionDigits: 1 });
53
+ function SmoothCursor({ points }) {
54
+ const [top, bottom] = points ?? [];
55
+ if (!top || !bottom) return null;
56
+ return /* @__PURE__ */ jsxRuntime.jsx(
57
+ "line",
58
+ {
59
+ x1: 0,
60
+ x2: 0,
61
+ y1: top.y,
62
+ y2: bottom.y,
63
+ stroke: "currentColor",
64
+ strokeOpacity: 0.2,
65
+ strokeWidth: 1,
66
+ className: "pointer-events-none text-black transition-transform duration-150 ease-out dark:text-white",
67
+ style: { transform: `translateX(${top.x}px)` }
68
+ }
69
+ );
70
+ }
30
71
  function MetricsLineChart({
31
72
  data,
32
73
  series,
33
74
  height = 210,
34
75
  yDomain,
35
76
  onPointClick,
36
- xAxisInterval = 5,
37
- xAxisMinTickGap,
38
- showDots = false
77
+ xAxisInterval = "preserveStartEnd",
78
+ xAxisMinTickGap = 28,
79
+ showDots = false,
80
+ showLegend = true
39
81
  }) {
40
82
  const isClickable = typeof onPointClick === "function";
41
83
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
42
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-4 flex w-full flex-wrap items-end gap-4 gap-y-1", children: series.map((s) => {
43
- const aggregated = s.aggregate?.(data);
44
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "inline-flex items-baseline gap-2", children: [
45
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "size-2 shrink-0 -translate-y-px rounded-full", style: { backgroundColor: s.color } }),
46
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "max-w-24 truncate text-caption text-muted-foreground", children: s.label }),
47
- aggregated && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-caption text-muted-foreground", children: [
48
- aggregated.value,
49
- aggregated.suffix && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-caption text-placeholder", children: [
50
- " ",
51
- aggregated.suffix
52
- ] })
53
- ] })
54
- ] }, s.dataKey);
55
- }) }),
56
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { height }, children: /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(recharts.LineChart, { data, children: [
84
+ showLegend && /* @__PURE__ */ jsxRuntime.jsx(MetricsLineChartLegend, { data, series, className: "mb-4" }),
85
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { height }, children: /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(recharts.LineChart, { data, margin: { top: 5, right: 5, bottom: 5, left: 0 }, children: [
57
86
  /* @__PURE__ */ jsxRuntime.jsx(
58
87
  recharts.CartesianGrid,
59
88
  {
60
89
  stroke: "currentColor",
61
90
  strokeOpacity: 0.08,
91
+ strokeDasharray: "4 4",
62
92
  vertical: false,
63
93
  className: "text-black dark:text-white"
64
94
  }
@@ -80,11 +110,13 @@ function MetricsLineChart({
80
110
  tick: { fontSize: tokens.CHART_TICK_FONT_SIZE, fill: tokens.CHART_LABEL_COLOR, fontFamily: "var(--font-mono)" },
81
111
  tickLine: false,
82
112
  axisLine: false,
83
- width: 30,
84
- domain: yDomain
113
+ width: "auto",
114
+ tickFormatter: (value) => compactNumber.format(value),
115
+ domain: yDomain,
116
+ tickCount: 3
85
117
  }
86
118
  ),
87
- /* @__PURE__ */ jsxRuntime.jsx(recharts.Tooltip, { content: /* @__PURE__ */ jsxRuntime.jsx(MetricsLineChartTooltip, {}) }),
119
+ /* @__PURE__ */ jsxRuntime.jsx(recharts.Tooltip, { content: /* @__PURE__ */ jsxRuntime.jsx(MetricsLineChartTooltip, {}), cursor: /* @__PURE__ */ jsxRuntime.jsx(SmoothCursor, {}) }),
88
120
  series.map((s) => /* @__PURE__ */ jsxRuntime.jsx(
89
121
  recharts.Line,
90
122
  {
@@ -95,12 +127,15 @@ function MetricsLineChart({
95
127
  dot: showDots ? { r: 3, fill: s.color, strokeWidth: 0 } : false,
96
128
  activeDot: isClickable ? {
97
129
  r: 4,
130
+ stroke: s.color,
131
+ strokeOpacity: 0.3,
132
+ strokeWidth: 4,
98
133
  style: { cursor: "pointer" },
99
134
  onClick: (_, payload) => {
100
135
  const datum = payload?.payload;
101
136
  if (datum) onPointClick(datum, s.dataKey);
102
137
  }
103
- } : void 0,
138
+ } : { r: 4, stroke: s.color, strokeOpacity: 0.3, strokeWidth: 4 },
104
139
  name: s.label
105
140
  },
106
141
  s.dataKey
@@ -110,5 +145,6 @@ function MetricsLineChart({
110
145
  }
111
146
 
112
147
  exports.MetricsLineChart = MetricsLineChart;
148
+ exports.MetricsLineChartLegend = MetricsLineChartLegend;
113
149
  exports.MetricsLineChartTooltip = MetricsLineChartTooltip;
114
- //# sourceMappingURL=metrics-line-chart-0FR3SYSt.cjs.map
150
+ //# sourceMappingURL=metrics-line-chart-BNNRRxM8.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics-line-chart-BNNRRxM8.cjs","sources":["../src/ds/components/MetricsLineChart/metrics-line-chart-legend.tsx","../src/ds/components/MetricsLineChart/metrics-line-chart-tooltip.tsx","../src/ds/components/MetricsLineChart/metrics-line-chart.tsx"],"sourcesContent":["import type { MetricsLineChartSeries } from './metrics-line-chart';\nimport { cn } from '@/lib/utils';\n\nexport function MetricsLineChartLegend({\n data,\n series,\n className,\n}: {\n data: Record<string, unknown>[];\n series: MetricsLineChartSeries[];\n className?: string;\n}) {\n return (\n <div className={cn('flex flex-wrap items-center gap-4 gap-y-1', className)}>\n {series.map(s => {\n const aggregated = s.aggregate?.(data);\n return (\n <div key={s.dataKey} className=\"inline-flex items-center gap-2\">\n <div className=\"size-2 shrink-0 rounded-full\" style={{ backgroundColor: s.color }} />\n <span className=\"max-w-24 truncate text-caption text-muted-foreground\">{s.label}</span>\n {aggregated && (\n <span className=\"text-caption text-muted-foreground\">\n {aggregated.value}\n {aggregated.suffix && <span className=\"text-caption text-placeholder\"> {aggregated.suffix}</span>}\n </span>\n )}\n </div>\n );\n })}\n </div>\n );\n}\n","import { ChartTooltip } from '@/ds/components/ChartTooltip';\n\nexport function MetricsLineChartTooltip({\n active,\n payload,\n label,\n suffix,\n}: {\n active?: boolean;\n payload?: Array<{ name: string; value: number; color: string }>;\n label?: string;\n suffix?: string;\n}) {\n if (!active || !payload?.length) return null;\n return (\n <ChartTooltip>\n <p className=\"mb-1 text-column text-foreground\">{label}</p>\n {payload.map(entry => (\n <p key={entry.name} className=\"text-foreground\">\n <span className=\"mr-2 inline-block size-2 rounded-full\" style={{ backgroundColor: entry.color }} />\n {entry.name}:{' '}\n <span className=\"font-mono\">\n {typeof entry.value === 'number' ? entry.value.toLocaleString('en-US') : entry.value}\n {suffix}\n </span>\n </p>\n ))}\n </ChartTooltip>\n );\n}\n","import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer } from 'recharts';\nimport { MetricsLineChartLegend } from './metrics-line-chart-legend';\nimport { MetricsLineChartTooltip } from './metrics-line-chart-tooltip';\nimport { CHART_LABEL_COLOR, CHART_TICK_FONT_SIZE } from '@/ds/tokens';\n\nexport type MetricsLineChartSeries = {\n dataKey: string;\n label: string;\n color: string;\n aggregate?: (data: Record<string, unknown>[]) => { value: string; suffix?: string };\n};\n\nconst compactNumber = new Intl.NumberFormat('en', { notation: 'compact', maximumFractionDigits: 1 });\n\n// Positioned via transform so the hover line glides between points instead of jumping.\nfunction SmoothCursor({ points }: { points?: { x: number; y: number }[] }) {\n const [top, bottom] = points ?? [];\n if (!top || !bottom) return null;\n return (\n <line\n x1={0}\n x2={0}\n y1={top.y}\n y2={bottom.y}\n stroke=\"currentColor\"\n strokeOpacity={0.2}\n strokeWidth={1}\n className=\"pointer-events-none text-black transition-transform duration-150 ease-out dark:text-white\"\n style={{ transform: `translateX(${top.x}px)` }}\n />\n );\n}\n\nexport type MetricsLineChartPointClickHandler = (point: Record<string, unknown>, seriesKey: string) => void;\n\nexport function MetricsLineChart({\n data,\n series,\n height = 210,\n yDomain,\n onPointClick,\n xAxisInterval = 'preserveStartEnd',\n xAxisMinTickGap = 28,\n showDots = false,\n showLegend = true,\n}: {\n data: Record<string, unknown>[];\n series: MetricsLineChartSeries[];\n height?: number;\n yDomain?: [number, number];\n onPointClick?: MetricsLineChartPointClickHandler;\n /** X-axis tick density. Defaults to `\"preserveStartEnd\"`, which drops labels\n * to fit the chart width. Pass a number for a fixed step instead. */\n xAxisInterval?: number | 'preserveStart' | 'preserveEnd' | 'preserveStartEnd';\n /** Minimum px gap between rendered ticks; recharts drops labels to honor it. Default `28`. */\n xAxisMinTickGap?: number;\n /** Render a visible dot on every point (needed for single-point series). */\n showDots?: boolean;\n /** Set to `false` to render `MetricsLineChartLegend` elsewhere, e.g. next to tabs. */\n showLegend?: boolean;\n}) {\n const isClickable = typeof onPointClick === 'function';\n\n return (\n <div>\n {showLegend && <MetricsLineChartLegend data={data} series={series} className=\"mb-4\" />}\n <div style={{ height }}>\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <LineChart data={data} margin={{ top: 5, right: 5, bottom: 5, left: 0 }}>\n <CartesianGrid\n stroke=\"currentColor\"\n strokeOpacity={0.08}\n strokeDasharray=\"4 4\"\n vertical={false}\n className=\"text-black dark:text-white\"\n />\n <XAxis\n dataKey=\"time\"\n tick={{ fontSize: CHART_TICK_FONT_SIZE, fill: CHART_LABEL_COLOR, fontFamily: 'var(--font-mono)' }}\n tickLine={false}\n axisLine={false}\n interval={xAxisInterval}\n minTickGap={xAxisMinTickGap}\n />\n <YAxis\n tick={{ fontSize: CHART_TICK_FONT_SIZE, fill: CHART_LABEL_COLOR, fontFamily: 'var(--font-mono)' }}\n tickLine={false}\n axisLine={false}\n width=\"auto\"\n tickFormatter={(value: number) => compactNumber.format(value)}\n domain={yDomain}\n tickCount={3}\n />\n <Tooltip content={<MetricsLineChartTooltip />} cursor={<SmoothCursor />} />\n {series.map(s => (\n <Line\n key={s.dataKey}\n type=\"linear\"\n dataKey={s.dataKey}\n stroke={s.color}\n strokeWidth={2}\n dot={showDots ? { r: 3, fill: s.color, strokeWidth: 0 } : false}\n activeDot={\n isClickable\n ? {\n r: 4,\n stroke: s.color,\n strokeOpacity: 0.3,\n strokeWidth: 4,\n style: { cursor: 'pointer' },\n onClick: (_: unknown, payload: unknown) => {\n const datum = (payload as { payload?: Record<string, unknown> } | undefined)?.payload;\n if (datum) onPointClick(datum, s.dataKey);\n },\n }\n : { r: 4, stroke: s.color, strokeOpacity: 0.3, strokeWidth: 4 }\n }\n name={s.label}\n />\n ))}\n </LineChart>\n </ResponsiveContainer>\n </div>\n </div>\n );\n}\n"],"names":["jsx","cn","jsxs","ChartTooltip","ResponsiveContainer","LineChart","CartesianGrid","XAxis","CHART_TICK_FONT_SIZE","CHART_LABEL_COLOR","YAxis","Tooltip","Line"],"mappings":"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"}
@@ -1,8 +1,30 @@
1
- import { jsxs, jsx } from 'react/jsx-runtime';
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
2
  import { ResponsiveContainer, LineChart, CartesianGrid, XAxis, YAxis, Tooltip, Line } from 'recharts';
3
+ import { c as cn } from './cn-65Adrsfj.js';
3
4
  import { C as ChartTooltip } from './chart-tooltip-84fl_3Wc.js';
4
5
  import { CHART_LABEL_COLOR, CHART_TICK_FONT_SIZE } from './tokens.es.js';
5
6
 
7
+ function MetricsLineChartLegend({
8
+ data,
9
+ series,
10
+ className
11
+ }) {
12
+ return /* @__PURE__ */ jsx("div", { className: cn("flex flex-wrap items-center gap-4 gap-y-1", className), children: series.map((s) => {
13
+ const aggregated = s.aggregate?.(data);
14
+ return /* @__PURE__ */ jsxs("div", { className: "inline-flex items-center gap-2", children: [
15
+ /* @__PURE__ */ jsx("div", { className: "size-2 shrink-0 rounded-full", style: { backgroundColor: s.color } }),
16
+ /* @__PURE__ */ jsx("span", { className: "max-w-24 truncate text-caption text-muted-foreground", children: s.label }),
17
+ aggregated && /* @__PURE__ */ jsxs("span", { className: "text-caption text-muted-foreground", children: [
18
+ aggregated.value,
19
+ aggregated.suffix && /* @__PURE__ */ jsxs("span", { className: "text-caption text-placeholder", children: [
20
+ " ",
21
+ aggregated.suffix
22
+ ] })
23
+ ] })
24
+ ] }, s.dataKey);
25
+ }) });
26
+ }
27
+
6
28
  function MetricsLineChartTooltip({
7
29
  active,
8
30
  payload,
@@ -12,51 +34,59 @@ function MetricsLineChartTooltip({
12
34
  if (!active || !payload?.length) return null;
13
35
  return /* @__PURE__ */ jsxs(ChartTooltip, { children: [
14
36
  /* @__PURE__ */ jsx("p", { className: "mb-1 text-column text-foreground", children: label }),
15
- payload.map((entry) => /* @__PURE__ */ jsxs("p", { className: "text-placeholder", children: [
37
+ payload.map((entry) => /* @__PURE__ */ jsxs("p", { className: "text-foreground", children: [
16
38
  /* @__PURE__ */ jsx("span", { className: "mr-2 inline-block size-2 rounded-full", style: { backgroundColor: entry.color } }),
17
39
  entry.name,
18
40
  ":",
19
41
  " ",
20
42
  /* @__PURE__ */ jsxs("span", { className: "font-mono", children: [
21
- entry.value,
43
+ typeof entry.value === "number" ? entry.value.toLocaleString("en-US") : entry.value,
22
44
  suffix
23
45
  ] })
24
46
  ] }, entry.name))
25
47
  ] });
26
48
  }
27
49
 
50
+ const compactNumber = new Intl.NumberFormat("en", { notation: "compact", maximumFractionDigits: 1 });
51
+ function SmoothCursor({ points }) {
52
+ const [top, bottom] = points ?? [];
53
+ if (!top || !bottom) return null;
54
+ return /* @__PURE__ */ jsx(
55
+ "line",
56
+ {
57
+ x1: 0,
58
+ x2: 0,
59
+ y1: top.y,
60
+ y2: bottom.y,
61
+ stroke: "currentColor",
62
+ strokeOpacity: 0.2,
63
+ strokeWidth: 1,
64
+ className: "pointer-events-none text-black transition-transform duration-150 ease-out dark:text-white",
65
+ style: { transform: `translateX(${top.x}px)` }
66
+ }
67
+ );
68
+ }
28
69
  function MetricsLineChart({
29
70
  data,
30
71
  series,
31
72
  height = 210,
32
73
  yDomain,
33
74
  onPointClick,
34
- xAxisInterval = 5,
35
- xAxisMinTickGap,
36
- showDots = false
75
+ xAxisInterval = "preserveStartEnd",
76
+ xAxisMinTickGap = 28,
77
+ showDots = false,
78
+ showLegend = true
37
79
  }) {
38
80
  const isClickable = typeof onPointClick === "function";
39
81
  return /* @__PURE__ */ jsxs("div", { children: [
40
- /* @__PURE__ */ jsx("div", { className: "mb-4 flex w-full flex-wrap items-end gap-4 gap-y-1", children: series.map((s) => {
41
- const aggregated = s.aggregate?.(data);
42
- return /* @__PURE__ */ jsxs("div", { className: "inline-flex items-baseline gap-2", children: [
43
- /* @__PURE__ */ jsx("div", { className: "size-2 shrink-0 -translate-y-px rounded-full", style: { backgroundColor: s.color } }),
44
- /* @__PURE__ */ jsx("span", { className: "max-w-24 truncate text-caption text-muted-foreground", children: s.label }),
45
- aggregated && /* @__PURE__ */ jsxs("span", { className: "text-caption text-muted-foreground", children: [
46
- aggregated.value,
47
- aggregated.suffix && /* @__PURE__ */ jsxs("span", { className: "text-caption text-placeholder", children: [
48
- " ",
49
- aggregated.suffix
50
- ] })
51
- ] })
52
- ] }, s.dataKey);
53
- }) }),
54
- /* @__PURE__ */ jsx("div", { style: { height }, children: /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs(LineChart, { data, children: [
82
+ showLegend && /* @__PURE__ */ jsx(MetricsLineChartLegend, { data, series, className: "mb-4" }),
83
+ /* @__PURE__ */ jsx("div", { style: { height }, children: /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs(LineChart, { data, margin: { top: 5, right: 5, bottom: 5, left: 0 }, children: [
55
84
  /* @__PURE__ */ jsx(
56
85
  CartesianGrid,
57
86
  {
58
87
  stroke: "currentColor",
59
88
  strokeOpacity: 0.08,
89
+ strokeDasharray: "4 4",
60
90
  vertical: false,
61
91
  className: "text-black dark:text-white"
62
92
  }
@@ -78,11 +108,13 @@ function MetricsLineChart({
78
108
  tick: { fontSize: CHART_TICK_FONT_SIZE, fill: CHART_LABEL_COLOR, fontFamily: "var(--font-mono)" },
79
109
  tickLine: false,
80
110
  axisLine: false,
81
- width: 30,
82
- domain: yDomain
111
+ width: "auto",
112
+ tickFormatter: (value) => compactNumber.format(value),
113
+ domain: yDomain,
114
+ tickCount: 3
83
115
  }
84
116
  ),
85
- /* @__PURE__ */ jsx(Tooltip, { content: /* @__PURE__ */ jsx(MetricsLineChartTooltip, {}) }),
117
+ /* @__PURE__ */ jsx(Tooltip, { content: /* @__PURE__ */ jsx(MetricsLineChartTooltip, {}), cursor: /* @__PURE__ */ jsx(SmoothCursor, {}) }),
86
118
  series.map((s) => /* @__PURE__ */ jsx(
87
119
  Line,
88
120
  {
@@ -93,12 +125,15 @@ function MetricsLineChart({
93
125
  dot: showDots ? { r: 3, fill: s.color, strokeWidth: 0 } : false,
94
126
  activeDot: isClickable ? {
95
127
  r: 4,
128
+ stroke: s.color,
129
+ strokeOpacity: 0.3,
130
+ strokeWidth: 4,
96
131
  style: { cursor: "pointer" },
97
132
  onClick: (_, payload) => {
98
133
  const datum = payload?.payload;
99
134
  if (datum) onPointClick(datum, s.dataKey);
100
135
  }
101
- } : void 0,
136
+ } : { r: 4, stroke: s.color, strokeOpacity: 0.3, strokeWidth: 4 },
102
137
  name: s.label
103
138
  },
104
139
  s.dataKey
@@ -107,5 +142,5 @@ function MetricsLineChart({
107
142
  ] });
108
143
  }
109
144
 
110
- export { MetricsLineChart as M, MetricsLineChartTooltip as a };
111
- //# sourceMappingURL=metrics-line-chart-knlgw8bV.js.map
145
+ export { MetricsLineChart as M, MetricsLineChartLegend as a, MetricsLineChartTooltip as b };
146
+ //# sourceMappingURL=metrics-line-chart-CT_pqJtC.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics-line-chart-CT_pqJtC.js","sources":["../src/ds/components/MetricsLineChart/metrics-line-chart-legend.tsx","../src/ds/components/MetricsLineChart/metrics-line-chart-tooltip.tsx","../src/ds/components/MetricsLineChart/metrics-line-chart.tsx"],"sourcesContent":["import type { MetricsLineChartSeries } from './metrics-line-chart';\nimport { cn } from '@/lib/utils';\n\nexport function MetricsLineChartLegend({\n data,\n series,\n className,\n}: {\n data: Record<string, unknown>[];\n series: MetricsLineChartSeries[];\n className?: string;\n}) {\n return (\n <div className={cn('flex flex-wrap items-center gap-4 gap-y-1', className)}>\n {series.map(s => {\n const aggregated = s.aggregate?.(data);\n return (\n <div key={s.dataKey} className=\"inline-flex items-center gap-2\">\n <div className=\"size-2 shrink-0 rounded-full\" style={{ backgroundColor: s.color }} />\n <span className=\"max-w-24 truncate text-caption text-muted-foreground\">{s.label}</span>\n {aggregated && (\n <span className=\"text-caption text-muted-foreground\">\n {aggregated.value}\n {aggregated.suffix && <span className=\"text-caption text-placeholder\"> {aggregated.suffix}</span>}\n </span>\n )}\n </div>\n );\n })}\n </div>\n );\n}\n","import { ChartTooltip } from '@/ds/components/ChartTooltip';\n\nexport function MetricsLineChartTooltip({\n active,\n payload,\n label,\n suffix,\n}: {\n active?: boolean;\n payload?: Array<{ name: string; value: number; color: string }>;\n label?: string;\n suffix?: string;\n}) {\n if (!active || !payload?.length) return null;\n return (\n <ChartTooltip>\n <p className=\"mb-1 text-column text-foreground\">{label}</p>\n {payload.map(entry => (\n <p key={entry.name} className=\"text-foreground\">\n <span className=\"mr-2 inline-block size-2 rounded-full\" style={{ backgroundColor: entry.color }} />\n {entry.name}:{' '}\n <span className=\"font-mono\">\n {typeof entry.value === 'number' ? entry.value.toLocaleString('en-US') : entry.value}\n {suffix}\n </span>\n </p>\n ))}\n </ChartTooltip>\n );\n}\n","import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer } from 'recharts';\nimport { MetricsLineChartLegend } from './metrics-line-chart-legend';\nimport { MetricsLineChartTooltip } from './metrics-line-chart-tooltip';\nimport { CHART_LABEL_COLOR, CHART_TICK_FONT_SIZE } from '@/ds/tokens';\n\nexport type MetricsLineChartSeries = {\n dataKey: string;\n label: string;\n color: string;\n aggregate?: (data: Record<string, unknown>[]) => { value: string; suffix?: string };\n};\n\nconst compactNumber = new Intl.NumberFormat('en', { notation: 'compact', maximumFractionDigits: 1 });\n\n// Positioned via transform so the hover line glides between points instead of jumping.\nfunction SmoothCursor({ points }: { points?: { x: number; y: number }[] }) {\n const [top, bottom] = points ?? [];\n if (!top || !bottom) return null;\n return (\n <line\n x1={0}\n x2={0}\n y1={top.y}\n y2={bottom.y}\n stroke=\"currentColor\"\n strokeOpacity={0.2}\n strokeWidth={1}\n className=\"pointer-events-none text-black transition-transform duration-150 ease-out dark:text-white\"\n style={{ transform: `translateX(${top.x}px)` }}\n />\n );\n}\n\nexport type MetricsLineChartPointClickHandler = (point: Record<string, unknown>, seriesKey: string) => void;\n\nexport function MetricsLineChart({\n data,\n series,\n height = 210,\n yDomain,\n onPointClick,\n xAxisInterval = 'preserveStartEnd',\n xAxisMinTickGap = 28,\n showDots = false,\n showLegend = true,\n}: {\n data: Record<string, unknown>[];\n series: MetricsLineChartSeries[];\n height?: number;\n yDomain?: [number, number];\n onPointClick?: MetricsLineChartPointClickHandler;\n /** X-axis tick density. Defaults to `\"preserveStartEnd\"`, which drops labels\n * to fit the chart width. Pass a number for a fixed step instead. */\n xAxisInterval?: number | 'preserveStart' | 'preserveEnd' | 'preserveStartEnd';\n /** Minimum px gap between rendered ticks; recharts drops labels to honor it. Default `28`. */\n xAxisMinTickGap?: number;\n /** Render a visible dot on every point (needed for single-point series). */\n showDots?: boolean;\n /** Set to `false` to render `MetricsLineChartLegend` elsewhere, e.g. next to tabs. */\n showLegend?: boolean;\n}) {\n const isClickable = typeof onPointClick === 'function';\n\n return (\n <div>\n {showLegend && <MetricsLineChartLegend data={data} series={series} className=\"mb-4\" />}\n <div style={{ height }}>\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <LineChart data={data} margin={{ top: 5, right: 5, bottom: 5, left: 0 }}>\n <CartesianGrid\n stroke=\"currentColor\"\n strokeOpacity={0.08}\n strokeDasharray=\"4 4\"\n vertical={false}\n className=\"text-black dark:text-white\"\n />\n <XAxis\n dataKey=\"time\"\n tick={{ fontSize: CHART_TICK_FONT_SIZE, fill: CHART_LABEL_COLOR, fontFamily: 'var(--font-mono)' }}\n tickLine={false}\n axisLine={false}\n interval={xAxisInterval}\n minTickGap={xAxisMinTickGap}\n />\n <YAxis\n tick={{ fontSize: CHART_TICK_FONT_SIZE, fill: CHART_LABEL_COLOR, fontFamily: 'var(--font-mono)' }}\n tickLine={false}\n axisLine={false}\n width=\"auto\"\n tickFormatter={(value: number) => compactNumber.format(value)}\n domain={yDomain}\n tickCount={3}\n />\n <Tooltip content={<MetricsLineChartTooltip />} cursor={<SmoothCursor />} />\n {series.map(s => (\n <Line\n key={s.dataKey}\n type=\"linear\"\n dataKey={s.dataKey}\n stroke={s.color}\n strokeWidth={2}\n dot={showDots ? { r: 3, fill: s.color, strokeWidth: 0 } : false}\n activeDot={\n isClickable\n ? {\n r: 4,\n stroke: s.color,\n strokeOpacity: 0.3,\n strokeWidth: 4,\n style: { cursor: 'pointer' },\n onClick: (_: unknown, payload: unknown) => {\n const datum = (payload as { payload?: Record<string, unknown> } | undefined)?.payload;\n if (datum) onPointClick(datum, s.dataKey);\n },\n }\n : { r: 4, stroke: s.color, strokeOpacity: 0.3, strokeWidth: 4 }\n }\n name={s.label}\n />\n ))}\n </LineChart>\n </ResponsiveContainer>\n </div>\n </div>\n );\n}\n"],"names":[],"mappings":"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"}
@@ -2,7 +2,7 @@
2
2
 
3
3
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4
4
 
5
- const pageHeader = require('../../page-header-Dk3s3XtC.cjs');
5
+ const pageHeader = require('../../page-header-CqvBk1wE.cjs');
6
6
 
7
7
 
8
8
 
@@ -1,2 +1,2 @@
1
- export { P as PageHeader } from '../../page-header-CyXAezlZ.js';
1
+ export { P as PageHeader } from '../../page-header-BGyZw13s.js';
2
2
  //# sourceMappingURL=page-header.es.js.map
@@ -43,7 +43,7 @@ function PageHeaderMeta({ beside = false, className, ...props }) {
43
43
  "data-slot": "page-header-meta",
44
44
  "data-placement": beside ? "beside" : "below",
45
45
  className: cn(
46
- "flex min-w-0 flex-wrap items-center gap-2",
46
+ "flex min-w-0 flex-wrap items-center gap-2 text-meta text-muted-foreground",
47
47
  beside ? "col-start-[meta] row-start-1 self-center justify-self-start" : "col-[title/end]",
48
48
  className
49
49
  ),
@@ -112,4 +112,4 @@ const PageHeader = Object.assign(PageHeaderRoot, {
112
112
  });
113
113
 
114
114
  export { PageHeader as P };
115
- //# sourceMappingURL=page-header-CyXAezlZ.js.map
115
+ //# sourceMappingURL=page-header-BGyZw13s.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page-header-BGyZw13s.js","sources":["../src/ds/new/layout/page-header/page-header-action.tsx","../src/ds/new/layout/page-header/page-header-description.tsx","../src/ds/new/layout/page-header/page-header-icon.tsx","../src/ds/new/layout/page-header/page-header-meta.tsx","../src/ds/new/layout/page-header/page-header-title.tsx","../src/ds/new/layout/page-header/page-header-root.tsx","../src/ds/new/layout/page-header/page-header.tsx"],"sourcesContent":["import type { ComponentPropsWithoutRef } from 'react';\n\nimport { cn } from '@/lib/utils';\n\nexport type PageHeaderActionProps = ComponentPropsWithoutRef<'div'>;\n\nexport function PageHeaderAction({ className, ...props }: PageHeaderActionProps) {\n return (\n <div data-slot=\"page-header-action\" className={cn('ml-auto shrink-0 self-start pt-0.5', className)} {...props} />\n );\n}\n","import type { ComponentPropsWithoutRef } from 'react';\n\nimport { cn } from '@/lib/utils';\n\nexport interface PageHeaderDescriptionProps extends ComponentPropsWithoutRef<'p'> {\n isLoading?: boolean;\n}\n\nexport function PageHeaderDescription({ children, className, isLoading, ...props }: PageHeaderDescriptionProps) {\n return (\n <p\n data-slot=\"page-header-description\"\n className={cn(\n 'col-[title/end] flex max-w-140 flex-wrap gap-x-4 gap-y-1 text-caption text-muted-foreground',\n isLoading && 'w-160 max-w-[80%] animate-pulse rounded-md bg-muted',\n className,\n )}\n {...props}\n >\n {isLoading ? <>&nbsp;</> : children}\n </p>\n );\n}\n","import type { ComponentPropsWithoutRef } from 'react';\n\nimport { cn } from '@/lib/utils';\n\nexport type PageHeaderIconProps = ComponentPropsWithoutRef<'div'>;\n\nexport function PageHeaderIcon({ className, ...props }: PageHeaderIconProps) {\n return (\n <div\n data-slot=\"page-header-icon\"\n className={cn(\n 'col-start-[icon] row-start-1 flex items-center self-center text-muted-foreground [&>svg]:size-5',\n className,\n )}\n {...props}\n />\n );\n}\n","import type { ComponentPropsWithoutRef } from 'react';\n\nimport { cn } from '@/lib/utils';\n\nexport interface PageHeaderMetaProps extends ComponentPropsWithoutRef<'div'> {\n beside?: boolean;\n}\n\nexport function PageHeaderMeta({ beside = false, className, ...props }: PageHeaderMetaProps) {\n return (\n <div\n data-slot=\"page-header-meta\"\n data-placement={beside ? 'beside' : 'below'}\n className={cn(\n 'flex min-w-0 flex-wrap items-center gap-2 text-meta text-muted-foreground',\n beside ? 'col-start-[meta] row-start-1 self-center justify-self-start' : 'col-[title/end]',\n className,\n )}\n {...props}\n />\n );\n}\n","import type { ComponentPropsWithoutRef } from 'react';\n\nimport { cn } from '@/lib/utils';\n\nexport interface PageHeaderTitleProps extends ComponentPropsWithoutRef<'h1'> {\n isLoading?: boolean;\n}\n\nexport function PageHeaderTitle({ children, className, isLoading, ...props }: PageHeaderTitleProps) {\n return (\n <h1\n data-slot=\"page-header-title\"\n className={cn(\n 'col-start-[title] row-start-1 flex min-w-0 items-center gap-2 self-start',\n 'text-heading text-foreground',\n '[&>svg]:size-[1.25em] [&>svg]:opacity-50',\n isLoading && 'w-60 max-w-[50%] animate-pulse rounded-md bg-fill',\n className,\n )}\n {...props}\n >\n {isLoading ? <>&nbsp;</> : children}\n </h1>\n );\n}\n","import { Children, isValidElement } from 'react';\nimport type { ComponentPropsWithoutRef } from 'react';\n\nimport { PageHeaderAction } from './page-header-action';\nimport { PageHeaderDescription } from './page-header-description';\nimport { PageHeaderIcon } from './page-header-icon';\nimport { PageHeaderTitle } from './page-header-title';\nimport { cn } from '@/lib/utils';\n\nexport interface PageHeaderRootProps extends Omit<ComponentPropsWithoutRef<'header'>, 'title'> {\n title?: React.ReactNode;\n description?: React.ReactNode;\n icon?: React.ReactNode;\n isLoading?: boolean;\n}\n\nexport function PageHeaderRoot({\n children,\n className,\n title,\n description,\n icon,\n isLoading,\n ...props\n}: PageHeaderRootProps) {\n const useLegacyApi = children === undefined && title !== undefined;\n\n // Actions sit outside the title grid so their height never affects title/meta/description alignment.\n const items = Children.toArray(children);\n const actions = items.filter(child => isValidElement(child) && child.type === PageHeaderAction);\n const content = items.filter(child => !actions.includes(child));\n\n return (\n <header className={cn('relative flex w-full items-start gap-3', className)} {...props}>\n <div\n data-slot=\"page-header-grid\"\n className={cn(\n 'grid min-w-0 flex-1 grid-cols-[[title]_auto_[meta]_minmax(0,1fr)_[end]] gap-x-3 gap-y-1',\n 'has-[>[data-slot=page-header-icon]]:grid-cols-[[icon]_auto_[title]_auto_[meta]_minmax(0,1fr)_[end]]',\n )}\n >\n {useLegacyApi ? (\n <>\n {!isLoading && icon !== undefined && <PageHeaderIcon>{icon}</PageHeaderIcon>}\n <PageHeaderTitle isLoading={isLoading}>{title}</PageHeaderTitle>\n {description !== undefined && (\n <PageHeaderDescription isLoading={isLoading}>{description}</PageHeaderDescription>\n )}\n </>\n ) : (\n content\n )}\n </div>\n {actions}\n </header>\n );\n}\n","import { PageHeaderAction } from './page-header-action';\nimport { PageHeaderDescription } from './page-header-description';\nimport { PageHeaderIcon } from './page-header-icon';\nimport { PageHeaderMeta } from './page-header-meta';\nimport { PageHeaderRoot } from './page-header-root';\nimport { PageHeaderTitle } from './page-header-title';\n\nexport type { PageHeaderActionProps } from './page-header-action';\nexport type { PageHeaderDescriptionProps } from './page-header-description';\nexport type { PageHeaderIconProps } from './page-header-icon';\nexport type { PageHeaderMetaProps } from './page-header-meta';\nexport type { PageHeaderRootProps } from './page-header-root';\nexport type { PageHeaderTitleProps } from './page-header-title';\n\nexport const PageHeader = Object.assign(PageHeaderRoot, {\n Icon: PageHeaderIcon,\n Title: PageHeaderTitle,\n Meta: PageHeaderMeta,\n Description: PageHeaderDescription,\n Action: PageHeaderAction,\n});\n"],"names":[],"mappings":"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"}
@@ -45,7 +45,7 @@ function PageHeaderMeta({ beside = false, className, ...props }) {
45
45
  "data-slot": "page-header-meta",
46
46
  "data-placement": beside ? "beside" : "below",
47
47
  className: utils_cn.cn(
48
- "flex min-w-0 flex-wrap items-center gap-2",
48
+ "flex min-w-0 flex-wrap items-center gap-2 text-meta text-muted-foreground",
49
49
  beside ? "col-start-[meta] row-start-1 self-center justify-self-start" : "col-[title/end]",
50
50
  className
51
51
  ),
@@ -114,4 +114,4 @@ const PageHeader = Object.assign(PageHeaderRoot, {
114
114
  });
115
115
 
116
116
  exports.PageHeader = PageHeader;
117
- //# sourceMappingURL=page-header-Dk3s3XtC.cjs.map
117
+ //# sourceMappingURL=page-header-CqvBk1wE.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page-header-CqvBk1wE.cjs","sources":["../src/ds/new/layout/page-header/page-header-action.tsx","../src/ds/new/layout/page-header/page-header-description.tsx","../src/ds/new/layout/page-header/page-header-icon.tsx","../src/ds/new/layout/page-header/page-header-meta.tsx","../src/ds/new/layout/page-header/page-header-title.tsx","../src/ds/new/layout/page-header/page-header-root.tsx","../src/ds/new/layout/page-header/page-header.tsx"],"sourcesContent":["import type { ComponentPropsWithoutRef } from 'react';\n\nimport { cn } from '@/lib/utils';\n\nexport type PageHeaderActionProps = ComponentPropsWithoutRef<'div'>;\n\nexport function PageHeaderAction({ className, ...props }: PageHeaderActionProps) {\n return (\n <div data-slot=\"page-header-action\" className={cn('ml-auto shrink-0 self-start pt-0.5', className)} {...props} />\n );\n}\n","import type { ComponentPropsWithoutRef } from 'react';\n\nimport { cn } from '@/lib/utils';\n\nexport interface PageHeaderDescriptionProps extends ComponentPropsWithoutRef<'p'> {\n isLoading?: boolean;\n}\n\nexport function PageHeaderDescription({ children, className, isLoading, ...props }: PageHeaderDescriptionProps) {\n return (\n <p\n data-slot=\"page-header-description\"\n className={cn(\n 'col-[title/end] flex max-w-140 flex-wrap gap-x-4 gap-y-1 text-caption text-muted-foreground',\n isLoading && 'w-160 max-w-[80%] animate-pulse rounded-md bg-muted',\n className,\n )}\n {...props}\n >\n {isLoading ? <>&nbsp;</> : children}\n </p>\n );\n}\n","import type { ComponentPropsWithoutRef } from 'react';\n\nimport { cn } from '@/lib/utils';\n\nexport type PageHeaderIconProps = ComponentPropsWithoutRef<'div'>;\n\nexport function PageHeaderIcon({ className, ...props }: PageHeaderIconProps) {\n return (\n <div\n data-slot=\"page-header-icon\"\n className={cn(\n 'col-start-[icon] row-start-1 flex items-center self-center text-muted-foreground [&>svg]:size-5',\n className,\n )}\n {...props}\n />\n );\n}\n","import type { ComponentPropsWithoutRef } from 'react';\n\nimport { cn } from '@/lib/utils';\n\nexport interface PageHeaderMetaProps extends ComponentPropsWithoutRef<'div'> {\n beside?: boolean;\n}\n\nexport function PageHeaderMeta({ beside = false, className, ...props }: PageHeaderMetaProps) {\n return (\n <div\n data-slot=\"page-header-meta\"\n data-placement={beside ? 'beside' : 'below'}\n className={cn(\n 'flex min-w-0 flex-wrap items-center gap-2 text-meta text-muted-foreground',\n beside ? 'col-start-[meta] row-start-1 self-center justify-self-start' : 'col-[title/end]',\n className,\n )}\n {...props}\n />\n );\n}\n","import type { ComponentPropsWithoutRef } from 'react';\n\nimport { cn } from '@/lib/utils';\n\nexport interface PageHeaderTitleProps extends ComponentPropsWithoutRef<'h1'> {\n isLoading?: boolean;\n}\n\nexport function PageHeaderTitle({ children, className, isLoading, ...props }: PageHeaderTitleProps) {\n return (\n <h1\n data-slot=\"page-header-title\"\n className={cn(\n 'col-start-[title] row-start-1 flex min-w-0 items-center gap-2 self-start',\n 'text-heading text-foreground',\n '[&>svg]:size-[1.25em] [&>svg]:opacity-50',\n isLoading && 'w-60 max-w-[50%] animate-pulse rounded-md bg-fill',\n className,\n )}\n {...props}\n >\n {isLoading ? <>&nbsp;</> : children}\n </h1>\n );\n}\n","import { Children, isValidElement } from 'react';\nimport type { ComponentPropsWithoutRef } from 'react';\n\nimport { PageHeaderAction } from './page-header-action';\nimport { PageHeaderDescription } from './page-header-description';\nimport { PageHeaderIcon } from './page-header-icon';\nimport { PageHeaderTitle } from './page-header-title';\nimport { cn } from '@/lib/utils';\n\nexport interface PageHeaderRootProps extends Omit<ComponentPropsWithoutRef<'header'>, 'title'> {\n title?: React.ReactNode;\n description?: React.ReactNode;\n icon?: React.ReactNode;\n isLoading?: boolean;\n}\n\nexport function PageHeaderRoot({\n children,\n className,\n title,\n description,\n icon,\n isLoading,\n ...props\n}: PageHeaderRootProps) {\n const useLegacyApi = children === undefined && title !== undefined;\n\n // Actions sit outside the title grid so their height never affects title/meta/description alignment.\n const items = Children.toArray(children);\n const actions = items.filter(child => isValidElement(child) && child.type === PageHeaderAction);\n const content = items.filter(child => !actions.includes(child));\n\n return (\n <header className={cn('relative flex w-full items-start gap-3', className)} {...props}>\n <div\n data-slot=\"page-header-grid\"\n className={cn(\n 'grid min-w-0 flex-1 grid-cols-[[title]_auto_[meta]_minmax(0,1fr)_[end]] gap-x-3 gap-y-1',\n 'has-[>[data-slot=page-header-icon]]:grid-cols-[[icon]_auto_[title]_auto_[meta]_minmax(0,1fr)_[end]]',\n )}\n >\n {useLegacyApi ? (\n <>\n {!isLoading && icon !== undefined && <PageHeaderIcon>{icon}</PageHeaderIcon>}\n <PageHeaderTitle isLoading={isLoading}>{title}</PageHeaderTitle>\n {description !== undefined && (\n <PageHeaderDescription isLoading={isLoading}>{description}</PageHeaderDescription>\n )}\n </>\n ) : (\n content\n )}\n </div>\n {actions}\n </header>\n );\n}\n","import { PageHeaderAction } from './page-header-action';\nimport { PageHeaderDescription } from './page-header-description';\nimport { PageHeaderIcon } from './page-header-icon';\nimport { PageHeaderMeta } from './page-header-meta';\nimport { PageHeaderRoot } from './page-header-root';\nimport { PageHeaderTitle } from './page-header-title';\n\nexport type { PageHeaderActionProps } from './page-header-action';\nexport type { PageHeaderDescriptionProps } from './page-header-description';\nexport type { PageHeaderIconProps } from './page-header-icon';\nexport type { PageHeaderMetaProps } from './page-header-meta';\nexport type { PageHeaderRootProps } from './page-header-root';\nexport type { PageHeaderTitleProps } from './page-header-title';\n\nexport const PageHeader = Object.assign(PageHeaderRoot, {\n Icon: PageHeaderIcon,\n Title: PageHeaderTitle,\n Meta: PageHeaderMeta,\n Description: PageHeaderDescription,\n Action: PageHeaderAction,\n});\n"],"names":["jsx","cn","Fragment","Children","isValidElement","jsxs"],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  import { ReactNode } from 'react';
2
2
  import { LatencyPoint } from '../hooks/use-latency-metrics';
3
+ import { MetricsInterval } from '../metrics-interval';
3
4
  import { LatencyTab } from './latency-card-view.utils';
4
5
  export type { LatencyTab };
5
6
  export interface LatencyCardViewProps {
@@ -7,11 +8,13 @@ export interface LatencyCardViewProps {
7
8
  agentData: LatencyPoint[];
8
9
  workflowData: LatencyPoint[];
9
10
  toolData: LatencyPoint[];
11
+ /** Bucket size of the points. Defaults to `'1h'`. */
12
+ interval?: MetricsInterval;
10
13
  } | undefined;
11
14
  isLoading: boolean;
12
15
  isError: boolean;
13
16
  /** Optional drilldown: invoked when a chart node is clicked. Container provides the navigation. */
14
- onPointClick?: (tab: LatencyTab, point: LatencyPoint) => void;
17
+ onPointClick?: (tab: LatencyTab, point: LatencyPoint, interval: MetricsInterval) => void;
15
18
  /**
16
19
  * Optional slot for top-bar action buttons (e.g. "View in Traces").
17
20
  * Pass a function to receive the active tab so the action can scope itself to the current entity type.
@@ -16,4 +16,5 @@ export { useTopActiveThreadsMetrics, type ActiveThreadRow } from './use-top-acti
16
16
  export { useTopResourcesByThreadsMetrics, type ResourceThreadsRow } from './use-top-resources-by-threads-metrics';
17
17
  export { useDrilldown } from './use-drilldown';
18
18
  export { buildLogsDrilldownUrl, buildTracesDrilldownUrl, narrowWindowToBucket, type DrilldownScope, type DrilldownWindow, } from '../drilldown';
19
+ export { chooseMetricsInterval, formatMetricsBucketLabel, type MetricsInterval } from '../metrics-interval';
19
20
  export { applyMetricsPropertyFilterTokens, buildMetricsDimensionalFilter, clearSavedMetricsFilters, createMetricsPropertyFilterFields, getMetricsPropertyFilterTokens, hasAnyMetricsFilterParams, loadMetricsFiltersFromStorage, saveMetricsFiltersToStorage, type MetricsDimensionalFilter, type MetricsPropertyFilterFieldId, } from '../metrics-filters';
@@ -1,3 +1,4 @@
1
+ import { MetricsInterval } from '../metrics-interval';
1
2
  export interface LatencyPoint {
2
3
  [key: string]: unknown;
3
4
  time: string;
@@ -7,10 +8,9 @@ export interface LatencyPoint {
7
8
  p50: number;
8
9
  p95: number;
9
10
  }
10
- export declare const LATENCY_INTERVAL: '1h';
11
11
  export declare function useLatencyMetrics(): import('@tanstack/react-query').UseQueryResult<{
12
12
  agentData: LatencyPoint[];
13
13
  workflowData: LatencyPoint[];
14
14
  toolData: LatencyPoint[];
15
- interval: "1h";
15
+ interval: MetricsInterval;
16
16
  }, Error>;
@@ -1,4 +1,5 @@
1
- export type TokenUsageTimeSeriesInterval = '1h' | '1d';
1
+ import { MetricsInterval } from '../metrics-interval';
2
+ export type TokenUsageTimeSeriesInterval = MetricsInterval;
2
3
  export interface TokenTimelinePoint {
3
4
  time: string;
4
5
  tsMs: number;
@@ -0,0 +1,7 @@
1
+ export type MetricsInterval = '1h' | '1d';
2
+ /** Hourly buckets up to 48h, daily buckets beyond, so long ranges stay readable. */
3
+ export declare function chooseMetricsInterval({ start, end }: {
4
+ start: Date;
5
+ end: Date;
6
+ }): MetricsInterval;
7
+ export declare function formatMetricsBucketLabel(ts: Date, interval: MetricsInterval): string;
@@ -8,16 +8,11 @@ export type MetricsCardGroupProps = {
8
8
  * cards are flat wells cut into it, so the frame reads as a thick border.
9
9
  */
10
10
  variant?: MetricsCardGroupVariant;
11
- /**
12
- * Base width each card grows from; a card wraps once the row can't fit it.
13
- * Raise it for chart cards, which need more room than a KPI.
14
- */
15
- minItemWidth?: string;
16
11
  className?: string;
17
12
  };
18
13
  /**
19
14
  * A frame that holds a row of metrics cards (KPI, chart, …) as one unit.
20
- * Cards flex to fill each row and wrap responsively; the group owns their width,
21
- * so each card's own `min-w-*` is neutralised.
15
+ * One column below `md`, two below `lg`, then every card on a single row with
16
+ * equal widths. The group owns their width, so each card's own `min-w-*` is neutralised.
22
17
  */
23
- export declare function MetricsCardGroup({ children, variant, minItemWidth, className, }: MetricsCardGroupProps): import("react").JSX.Element;
18
+ export declare function MetricsCardGroup({ children, variant, className }: MetricsCardGroupProps): import("react").JSX.Element;
@@ -1,2 +1,3 @@
1
1
  export { MetricsLineChart, type MetricsLineChartSeries } from './metrics-line-chart';
2
2
  export { MetricsLineChartTooltip } from './metrics-line-chart-tooltip';
3
+ export { MetricsLineChartLegend } from './metrics-line-chart-legend';
@@ -0,0 +1,6 @@
1
+ import { MetricsLineChartSeries } from './metrics-line-chart';
2
+ export declare function MetricsLineChartLegend({ data, series, className, }: {
3
+ data: Record<string, unknown>[];
4
+ series: MetricsLineChartSeries[];
5
+ className?: string;
6
+ }): import("react").JSX.Element;
@@ -8,17 +8,19 @@ export type MetricsLineChartSeries = {
8
8
  };
9
9
  };
10
10
  export type MetricsLineChartPointClickHandler = (point: Record<string, unknown>, seriesKey: string) => void;
11
- export declare function MetricsLineChart({ data, series, height, yDomain, onPointClick, xAxisInterval, xAxisMinTickGap, showDots, }: {
11
+ export declare function MetricsLineChart({ data, series, height, yDomain, onPointClick, xAxisInterval, xAxisMinTickGap, showDots, showLegend, }: {
12
12
  data: Record<string, unknown>[];
13
13
  series: MetricsLineChartSeries[];
14
14
  height?: number;
15
15
  yDomain?: [number, number];
16
16
  onPointClick?: MetricsLineChartPointClickHandler;
17
- /** X-axis tick density. Default `5` (every 6th point). Pass
18
- * `"preserveStartEnd"` with `xAxisMinTickGap` for a width-responsive axis. */
17
+ /** X-axis tick density. Defaults to `"preserveStartEnd"`, which drops labels
18
+ * to fit the chart width. Pass a number for a fixed step instead. */
19
19
  xAxisInterval?: number | 'preserveStart' | 'preserveEnd' | 'preserveStartEnd';
20
- /** Minimum px gap between rendered ticks; recharts drops labels to honor it. */
20
+ /** Minimum px gap between rendered ticks; recharts drops labels to honor it. Default `28`. */
21
21
  xAxisMinTickGap?: number;
22
22
  /** Render a visible dot on every point (needed for single-point series). */
23
23
  showDots?: boolean;
24
+ /** Set to `false` to render `MetricsLineChartLegend` elsewhere, e.g. next to tabs. */
25
+ showLegend?: boolean;
24
26
  }): import("react").JSX.Element;
@@ -5,4 +5,5 @@ export default meta;
5
5
  type Story = StoryObj<typeof MetricsLineChart>;
6
6
  export declare const MultipleSeries: Story;
7
7
  export declare const SinglePoint: Story;
8
+ export declare const InMetricsCardWithTabs: Story;
8
9
  export declare const FixedDomain: Story;