@dudousxd/nestjs-telescope-ui 2.0.0 → 2.0.1

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 (263) hide show
  1. package/CHANGELOG.md +748 -0
  2. package/README.md +31 -0
  3. package/dist/client/console-url.d.ts +11 -0
  4. package/dist/client/console-url.d.ts.map +1 -0
  5. package/dist/client/console-url.js +21 -0
  6. package/dist/client/console-url.js.map +1 -0
  7. package/dist/client/index.d.ts +2 -1
  8. package/dist/client/index.d.ts.map +1 -1
  9. package/dist/client/index.js +3 -0
  10. package/dist/client/index.js.map +1 -1
  11. package/dist/client/telescope-client.d.ts +64 -11
  12. package/dist/client/telescope-client.d.ts.map +1 -1
  13. package/dist/client/telescope-client.js +59 -54
  14. package/dist/client/telescope-client.js.map +1 -1
  15. package/dist/client/types.d.ts +431 -30
  16. package/dist/client/types.d.ts.map +1 -1
  17. package/dist/react/components/batch-timeline.js +2 -2
  18. package/dist/react/components/batch-timeline.js.map +1 -1
  19. package/dist/react/components/cache-badge.d.ts +14 -6
  20. package/dist/react/components/cache-badge.d.ts.map +1 -1
  21. package/dist/react/components/cache-badge.js +26 -12
  22. package/dist/react/components/cache-badge.js.map +1 -1
  23. package/dist/react/components/charts/area-chart-card.d.ts +11 -3
  24. package/dist/react/components/charts/area-chart-card.d.ts.map +1 -1
  25. package/dist/react/components/charts/area-chart-card.js +33 -6
  26. package/dist/react/components/charts/area-chart-card.js.map +1 -1
  27. package/dist/react/components/charts/bar-chart-card.d.ts +18 -7
  28. package/dist/react/components/charts/bar-chart-card.d.ts.map +1 -1
  29. package/dist/react/components/charts/bar-chart-card.js +18 -9
  30. package/dist/react/components/charts/bar-chart-card.js.map +1 -1
  31. package/dist/react/components/charts/breakdown-card.d.ts +17 -0
  32. package/dist/react/components/charts/breakdown-card.d.ts.map +1 -0
  33. package/dist/react/components/charts/breakdown-card.js +43 -0
  34. package/dist/react/components/charts/breakdown-card.js.map +1 -0
  35. package/dist/react/components/charts/chart-card.d.ts +7 -0
  36. package/dist/react/components/charts/chart-card.d.ts.map +1 -1
  37. package/dist/react/components/charts/chart-card.js +10 -3
  38. package/dist/react/components/charts/chart-card.js.map +1 -1
  39. package/dist/react/components/charts/chart-selection.d.ts +44 -0
  40. package/dist/react/components/charts/chart-selection.d.ts.map +1 -0
  41. package/dist/react/components/charts/chart-selection.js +36 -0
  42. package/dist/react/components/charts/chart-selection.js.map +1 -0
  43. package/dist/react/components/charts/chart-theme.d.ts +62 -19
  44. package/dist/react/components/charts/chart-theme.d.ts.map +1 -1
  45. package/dist/react/components/charts/chart-theme.js +72 -13
  46. package/dist/react/components/charts/chart-theme.js.map +1 -1
  47. package/dist/react/components/charts/distribution-chart-card.d.ts +17 -0
  48. package/dist/react/components/charts/distribution-chart-card.d.ts.map +1 -0
  49. package/dist/react/components/charts/distribution-chart-card.js +46 -0
  50. package/dist/react/components/charts/distribution-chart-card.js.map +1 -0
  51. package/dist/react/components/charts/gauge-card.d.ts +12 -0
  52. package/dist/react/components/charts/gauge-card.d.ts.map +1 -0
  53. package/dist/react/components/charts/gauge-card.js +17 -0
  54. package/dist/react/components/charts/gauge-card.js.map +1 -0
  55. package/dist/react/components/charts/index.d.ts +1 -0
  56. package/dist/react/components/charts/index.d.ts.map +1 -1
  57. package/dist/react/components/charts/index.js +1 -0
  58. package/dist/react/components/charts/index.js.map +1 -1
  59. package/dist/react/components/charts/stacked-area-chart-card.d.ts +17 -3
  60. package/dist/react/components/charts/stacked-area-chart-card.d.ts.map +1 -1
  61. package/dist/react/components/charts/stacked-area-chart-card.js +31 -8
  62. package/dist/react/components/charts/stacked-area-chart-card.js.map +1 -1
  63. package/dist/react/components/entries-table.d.ts.map +1 -1
  64. package/dist/react/components/entries-table.js +17 -3
  65. package/dist/react/components/entries-table.js.map +1 -1
  66. package/dist/react/components/entry-detail.d.ts +2 -0
  67. package/dist/react/components/entry-detail.d.ts.map +1 -1
  68. package/dist/react/components/entry-detail.js +186 -20
  69. package/dist/react/components/entry-detail.js.map +1 -1
  70. package/dist/react/components/entry-insights.d.ts.map +1 -1
  71. package/dist/react/components/entry-insights.js +28 -17
  72. package/dist/react/components/entry-insights.js.map +1 -1
  73. package/dist/react/components/entry-types.d.ts +29 -0
  74. package/dist/react/components/entry-types.d.ts.map +1 -1
  75. package/dist/react/components/entry-types.js +60 -0
  76. package/dist/react/components/entry-types.js.map +1 -1
  77. package/dist/react/components/export-json-toolbar.js +2 -2
  78. package/dist/react/components/export-json-toolbar.js.map +1 -1
  79. package/dist/react/components/extensions/panel-column-menu.d.ts +19 -0
  80. package/dist/react/components/extensions/panel-column-menu.d.ts.map +1 -0
  81. package/dist/react/components/extensions/panel-column-menu.js +47 -0
  82. package/dist/react/components/extensions/panel-column-menu.js.map +1 -0
  83. package/dist/react/components/extensions/panel-renderer.d.ts +46 -0
  84. package/dist/react/components/extensions/panel-renderer.d.ts.map +1 -0
  85. package/dist/react/components/extensions/panel-renderer.js +122 -0
  86. package/dist/react/components/extensions/panel-renderer.js.map +1 -0
  87. package/dist/react/components/extensions/panel-table-header.d.ts +18 -0
  88. package/dist/react/components/extensions/panel-table-header.d.ts.map +1 -0
  89. package/dist/react/components/extensions/panel-table-header.js +82 -0
  90. package/dist/react/components/extensions/panel-table-header.js.map +1 -0
  91. package/dist/react/components/extensions/panel-table.d.ts +27 -0
  92. package/dist/react/components/extensions/panel-table.d.ts.map +1 -0
  93. package/dist/react/components/extensions/panel-table.js +87 -0
  94. package/dist/react/components/extensions/panel-table.js.map +1 -0
  95. package/dist/react/components/extensions/stat-card.d.ts +18 -0
  96. package/dist/react/components/extensions/stat-card.d.ts.map +1 -0
  97. package/dist/react/components/extensions/stat-card.js +44 -0
  98. package/dist/react/components/extensions/stat-card.js.map +1 -0
  99. package/dist/react/components/extensions/table-columns.d.ts +32 -0
  100. package/dist/react/components/extensions/table-columns.d.ts.map +1 -0
  101. package/dist/react/components/extensions/table-columns.js +51 -0
  102. package/dist/react/components/extensions/table-columns.js.map +1 -0
  103. package/dist/react/components/extensions/table-features.d.ts +47 -0
  104. package/dist/react/components/extensions/table-features.d.ts.map +1 -0
  105. package/dist/react/components/extensions/table-features.js +45 -0
  106. package/dist/react/components/extensions/table-features.js.map +1 -0
  107. package/dist/react/components/extensions/table-query.d.ts +53 -0
  108. package/dist/react/components/extensions/table-query.d.ts.map +1 -0
  109. package/dist/react/components/extensions/table-query.js +51 -0
  110. package/dist/react/components/extensions/table-query.js.map +1 -0
  111. package/dist/react/components/flamegraph-view.d.ts +18 -0
  112. package/dist/react/components/flamegraph-view.d.ts.map +1 -0
  113. package/dist/react/components/flamegraph-view.js +48 -0
  114. package/dist/react/components/flamegraph-view.js.map +1 -0
  115. package/dist/react/components/flamegraph.d.ts +34 -0
  116. package/dist/react/components/flamegraph.d.ts.map +1 -0
  117. package/dist/react/components/flamegraph.js +54 -0
  118. package/dist/react/components/flamegraph.js.map +1 -0
  119. package/dist/react/components/inertia-badge.d.ts +33 -0
  120. package/dist/react/components/inertia-badge.d.ts.map +1 -0
  121. package/dist/react/components/inertia-badge.js +72 -0
  122. package/dist/react/components/inertia-badge.js.map +1 -0
  123. package/dist/react/components/inertia-body.d.ts +11 -0
  124. package/dist/react/components/inertia-body.d.ts.map +1 -0
  125. package/dist/react/components/inertia-body.js +127 -0
  126. package/dist/react/components/inertia-body.js.map +1 -0
  127. package/dist/react/components/official-event.d.ts +16 -0
  128. package/dist/react/components/official-event.d.ts.map +1 -0
  129. package/dist/react/components/official-event.js +88 -0
  130. package/dist/react/components/official-event.js.map +1 -0
  131. package/dist/react/components/pulse-panel.d.ts.map +1 -1
  132. package/dist/react/components/pulse-panel.js +6 -6
  133. package/dist/react/components/pulse-panel.js.map +1 -1
  134. package/dist/react/components/queues/EnqueueJobForm.d.ts.map +1 -1
  135. package/dist/react/components/queues/EnqueueJobForm.js +2 -1
  136. package/dist/react/components/queues/EnqueueJobForm.js.map +1 -1
  137. package/dist/react/components/queues/JobActions.d.ts.map +1 -1
  138. package/dist/react/components/queues/JobActions.js +11 -9
  139. package/dist/react/components/queues/JobActions.js.map +1 -1
  140. package/dist/react/components/queues/JobDetailDrawer.d.ts.map +1 -1
  141. package/dist/react/components/queues/JobDetailDrawer.js +8 -13
  142. package/dist/react/components/queues/JobDetailDrawer.js.map +1 -1
  143. package/dist/react/components/queues/JobTable.d.ts.map +1 -1
  144. package/dist/react/components/queues/JobTable.js +0 -0
  145. package/dist/react/components/queues/JobTable.js.map +1 -1
  146. package/dist/react/components/queues/QueueList.d.ts.map +1 -1
  147. package/dist/react/components/queues/QueueList.js +6 -6
  148. package/dist/react/components/queues/QueueList.js.map +1 -1
  149. package/dist/react/components/queues/QueueStateTabs.d.ts.map +1 -1
  150. package/dist/react/components/queues/QueueStateTabs.js +9 -7
  151. package/dist/react/components/queues/QueueStateTabs.js.map +1 -1
  152. package/dist/react/components/queues/queue-format.d.ts +5 -1
  153. package/dist/react/components/queues/queue-format.d.ts.map +1 -1
  154. package/dist/react/components/queues/queue-format.js +11 -7
  155. package/dist/react/components/queues/queue-format.js.map +1 -1
  156. package/dist/react/components/queues-panel.js +1 -1
  157. package/dist/react/components/queues-panel.js.map +1 -1
  158. package/dist/react/components/request-timeline.d.ts.map +1 -1
  159. package/dist/react/components/request-timeline.js +2 -2
  160. package/dist/react/components/request-timeline.js.map +1 -1
  161. package/dist/react/components/retention-indicator.d.ts.map +1 -1
  162. package/dist/react/components/retention-indicator.js +1 -1
  163. package/dist/react/components/retention-indicator.js.map +1 -1
  164. package/dist/react/components/sparkline.d.ts.map +1 -1
  165. package/dist/react/components/sparkline.js +1 -1
  166. package/dist/react/components/sparkline.js.map +1 -1
  167. package/dist/react/components/tag-autocomplete.d.ts +21 -4
  168. package/dist/react/components/tag-autocomplete.d.ts.map +1 -1
  169. package/dist/react/components/tag-autocomplete.js +57 -29
  170. package/dist/react/components/tag-autocomplete.js.map +1 -1
  171. package/dist/react/components/to-csv.d.ts +25 -0
  172. package/dist/react/components/to-csv.d.ts.map +1 -0
  173. package/dist/react/components/to-csv.js +78 -0
  174. package/dist/react/components/to-csv.js.map +1 -0
  175. package/dist/react/components/user-tag.d.ts +15 -0
  176. package/dist/react/components/user-tag.d.ts.map +1 -1
  177. package/dist/react/components/user-tag.js +19 -0
  178. package/dist/react/components/user-tag.js.map +1 -1
  179. package/dist/react/components/waterfall-view.d.ts +13 -0
  180. package/dist/react/components/waterfall-view.d.ts.map +1 -0
  181. package/dist/react/components/waterfall-view.js +58 -0
  182. package/dist/react/components/waterfall-view.js.map +1 -0
  183. package/dist/react/components/window-select.d.ts.map +1 -1
  184. package/dist/react/components/window-select.js +6 -2
  185. package/dist/react/components/window-select.js.map +1 -1
  186. package/dist/react/index.d.ts +7 -1
  187. package/dist/react/index.d.ts.map +1 -1
  188. package/dist/react/index.js +11 -1
  189. package/dist/react/index.js.map +1 -1
  190. package/dist/react/ui/badge.d.ts +16 -0
  191. package/dist/react/ui/badge.d.ts.map +1 -0
  192. package/dist/react/ui/badge.js +28 -0
  193. package/dist/react/ui/badge.js.map +1 -0
  194. package/dist/react/ui/button.d.ts +17 -0
  195. package/dist/react/ui/button.d.ts.map +1 -0
  196. package/dist/react/ui/button.js +35 -0
  197. package/dist/react/ui/button.js.map +1 -0
  198. package/dist/react/ui/chart.d.ts +116 -0
  199. package/dist/react/ui/chart.d.ts.map +1 -0
  200. package/dist/react/ui/chart.js +191 -0
  201. package/dist/react/ui/chart.js.map +1 -0
  202. package/dist/react/ui/cn.d.ts +8 -0
  203. package/dist/react/ui/cn.d.ts.map +1 -0
  204. package/dist/react/ui/cn.js +11 -0
  205. package/dist/react/ui/cn.js.map +1 -0
  206. package/dist/react/ui/dialog.d.ts +26 -0
  207. package/dist/react/ui/dialog.d.ts.map +1 -0
  208. package/dist/react/ui/dialog.js +40 -0
  209. package/dist/react/ui/dialog.js.map +1 -0
  210. package/dist/react/ui/index.d.ts +24 -0
  211. package/dist/react/ui/index.d.ts.map +1 -0
  212. package/dist/react/ui/index.js +24 -0
  213. package/dist/react/ui/index.js.map +1 -0
  214. package/dist/react/ui/input.d.ts +3 -0
  215. package/dist/react/ui/input.d.ts.map +1 -0
  216. package/dist/react/ui/input.js +8 -0
  217. package/dist/react/ui/input.js.map +1 -0
  218. package/dist/react/ui/select.d.ts +20 -0
  219. package/dist/react/ui/select.d.ts.map +1 -0
  220. package/dist/react/ui/select.js +27 -0
  221. package/dist/react/ui/select.js.map +1 -0
  222. package/dist/react/ui/table.d.ts +27 -0
  223. package/dist/react/ui/table.d.ts.map +1 -0
  224. package/dist/react/ui/table.js +22 -0
  225. package/dist/react/ui/table.js.map +1 -0
  226. package/dist/react/ui/tabs.d.ts +12 -0
  227. package/dist/react/ui/tabs.d.ts.map +1 -0
  228. package/dist/react/ui/tabs.js +20 -0
  229. package/dist/react/ui/tabs.js.map +1 -0
  230. package/dist/react/ui/tooltip.d.ts +10 -0
  231. package/dist/react/ui/tooltip.d.ts.map +1 -0
  232. package/dist/react/ui/tooltip.js +12 -0
  233. package/dist/react/ui/tooltip.js.map +1 -0
  234. package/dist/react/use-telescope-queries.d.ts +129 -130
  235. package/dist/react/use-telescope-queries.d.ts.map +1 -1
  236. package/dist/react/use-telescope-queries.js +146 -1
  237. package/dist/react/use-telescope-queries.js.map +1 -1
  238. package/dist/react/use-telescope-stream.d.ts +10 -0
  239. package/dist/react/use-telescope-stream.d.ts.map +1 -0
  240. package/dist/react/use-telescope-stream.js +40 -0
  241. package/dist/react/use-telescope-stream.js.map +1 -0
  242. package/dist/server/index.d.ts +2 -1
  243. package/dist/server/index.d.ts.map +1 -1
  244. package/dist/server/index.js +2 -0
  245. package/dist/server/index.js.map +1 -1
  246. package/dist/server/telescope-ui.module.d.ts +28 -1
  247. package/dist/server/telescope-ui.module.d.ts.map +1 -1
  248. package/dist/server/telescope-ui.module.js +42 -4
  249. package/dist/server/telescope-ui.module.js.map +1 -1
  250. package/dist/server/telescope-ui.options.d.ts +47 -0
  251. package/dist/server/telescope-ui.options.d.ts.map +1 -1
  252. package/dist/server/telescope-ui.options.js.map +1 -1
  253. package/dist/spa/assets/index-BPSlup7m.js +159 -0
  254. package/dist/spa/assets/index-DmsmJrlA.css +1 -0
  255. package/dist/spa/index.html +2 -2
  256. package/package.json +75 -36
  257. package/skills/telescope-ui-dashboard/SKILL.md +198 -0
  258. package/dist/react/components/type-tabs.d.ts +0 -5
  259. package/dist/react/components/type-tabs.d.ts.map +0 -1
  260. package/dist/react/components/type-tabs.js +0 -8
  261. package/dist/react/components/type-tabs.js.map +0 -1
  262. package/dist/spa/assets/index-CCzTpxj3.css +0 -1
  263. package/dist/spa/assets/index-w0XTI5OM.js +0 -135
@@ -1,4 +1,12 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
+ /**
3
+ * Cache entries carry `content: { operation, hit, key, tier?, stale?, ... }`. This
4
+ * module derives a small status pill: `HIT` reads `--good`, `MISS` reads `--warn`,
5
+ * and `SET`/`DEL`/`CLEAR` are neutral. A grace-served (`stale`) hit reads warn to
6
+ * stand out from a fresh hit; a `tier` (e.g. l1/l2) is appended when present.
7
+ */
8
+ import { Badge, badgeVariants } from '../ui/index.js';
9
+ const OPERATIONS = new Set(['get', 'set', 'delete', 'clear']);
2
10
  /** Narrow unknown entry content to the cache shape without casts. */
3
11
  function isCacheContent(content) {
4
12
  if (typeof content !== 'object' || content === null)
@@ -6,30 +14,36 @@ function isCacheContent(content) {
6
14
  if (!('operation' in content) || !('hit' in content) || !('key' in content))
7
15
  return false;
8
16
  const { operation, hit, key } = content;
9
- if (operation !== 'get' && operation !== 'set')
17
+ if (typeof operation !== 'string' || !OPERATIONS.has(operation))
10
18
  return false;
11
19
  if (hit !== null && typeof hit !== 'boolean')
12
20
  return false;
13
21
  return typeof key === 'string';
14
22
  }
15
- const PILL_BASE = 'rounded border px-1.5 py-0.5 text-[10px] font-medium';
23
+ function info(label, variant) {
24
+ return { label, variant, className: badgeVariants({ variant }) };
25
+ }
16
26
  /**
17
27
  * Pure mapping from entry content to a cache pill descriptor; `null` for any
18
- * non-cache or unrecognized content. Mirrors the bordered-pill token style used
19
- * by the queue action buttons.
28
+ * non-cache or unrecognized content.
20
29
  */
21
30
  export function cacheBadge(content) {
22
31
  if (!isCacheContent(content))
23
32
  return null;
24
- if (content.operation === 'set') {
25
- return { label: 'SET', className: `${PILL_BASE} border-zinc-700 text-zinc-300` };
26
- }
33
+ const tierSuffix = typeof content.tier === 'string' ? ` ${content.tier.toUpperCase()}` : '';
34
+ if (content.operation === 'set')
35
+ return info(`SET${tierSuffix}`, 'muted');
36
+ if (content.operation === 'delete')
37
+ return info('DEL', 'muted');
38
+ if (content.operation === 'clear')
39
+ return info('CLEAR', 'muted');
27
40
  if (content.hit === true) {
28
- return { label: 'HIT', className: `${PILL_BASE} border-emerald-500/40 text-emerald-300` };
29
- }
30
- if (content.hit === false) {
31
- return { label: 'MISS', className: `${PILL_BASE} border-amber-500/40 text-amber-300` };
41
+ // A grace-period (stale) hit warns so it's distinguishable from a fresh hit.
42
+ const stale = content.stale === true;
43
+ return info(`${stale ? 'HIT·STALE' : 'HIT'}${tierSuffix}`, stale ? 'warn' : 'good');
32
44
  }
45
+ if (content.hit === false)
46
+ return info(`MISS${tierSuffix}`, 'warn');
33
47
  return null;
34
48
  }
35
49
  /** Small cache hit/miss/set status pill; renders nothing for non-cache content. */
@@ -37,6 +51,6 @@ export function CacheBadge({ content }) {
37
51
  const badge = cacheBadge(content);
38
52
  if (badge === null)
39
53
  return null;
40
- return _jsx("span", { className: badge.className, children: badge.label });
54
+ return _jsx(Badge, { variant: badge.variant, children: badge.label });
41
55
  }
42
56
  //# sourceMappingURL=cache-badge.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"cache-badge.js","sourceRoot":"","sources":["../../../src/react/components/cache-badge.tsx"],"names":[],"mappings":";AAYA,qEAAqE;AACrE,SAAS,cAAc,CAAC,OAAgB;IACtC,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAClE,IAAI,CAAC,CAAC,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,OAAO,CAAC;QAAE,OAAO,KAAK,CAAC;IAC1F,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC;IACxC,IAAI,SAAS,KAAK,KAAK,IAAI,SAAS,KAAK,KAAK;QAAE,OAAO,KAAK,CAAC;IAC7D,IAAI,GAAG,KAAK,IAAI,IAAI,OAAO,GAAG,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IAC3D,OAAO,OAAO,GAAG,KAAK,QAAQ,CAAC;AACjC,CAAC;AAOD,MAAM,SAAS,GAAG,sDAAsD,CAAC;AAEzE;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAC,OAAgB;IACzC,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAC;IAC1C,IAAI,OAAO,CAAC,SAAS,KAAK,KAAK,EAAE,CAAC;QAChC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,SAAS,gCAAgC,EAAE,CAAC;IACnF,CAAC;IACD,IAAI,OAAO,CAAC,GAAG,KAAK,IAAI,EAAE,CAAC;QACzB,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,SAAS,yCAAyC,EAAE,CAAC;IAC5F,CAAC;IACD,IAAI,OAAO,CAAC,GAAG,KAAK,KAAK,EAAE,CAAC;QAC1B,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,SAAS,qCAAqC,EAAE,CAAC;IACzF,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,UAAU,CAAC,EAAE,OAAO,EAAwB;IAC1D,MAAM,KAAK,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC;IAClC,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAChC,OAAO,eAAM,SAAS,EAAE,KAAK,CAAC,SAAS,YAAG,KAAK,CAAC,KAAK,GAAQ,CAAC;AAChE,CAAC"}
1
+ {"version":3,"file":"cache-badge.js","sourceRoot":"","sources":["../../../src/react/components/cache-badge.tsx"],"names":[],"mappings":";AAAA;;;;;GAKG;AACH,OAAO,EAAE,KAAK,EAAmB,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAUvE,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;AAE9D,qEAAqE;AACrE,SAAS,cAAc,CAAC,OAAgB;IACtC,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAClE,IAAI,CAAC,CAAC,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,OAAO,CAAC;QAAE,OAAO,KAAK,CAAC;IAC1F,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC;IACxC,IAAI,OAAO,SAAS,KAAK,QAAQ,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC;QAAE,OAAO,KAAK,CAAC;IAC9E,IAAI,GAAG,KAAK,IAAI,IAAI,OAAO,GAAG,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IAC3D,OAAO,OAAO,GAAG,KAAK,QAAQ,CAAC;AACjC,CAAC;AAcD,SAAS,IAAI,CAAC,KAAa,EAAE,OAA2C;IACtE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,aAAa,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;AACnE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,OAAgB;IACzC,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAC;IAC1C,MAAM,UAAU,GAAG,OAAO,OAAO,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAC5F,IAAI,OAAO,CAAC,SAAS,KAAK,KAAK;QAAE,OAAO,IAAI,CAAC,MAAM,UAAU,EAAE,EAAE,OAAO,CAAC,CAAC;IAC1E,IAAI,OAAO,CAAC,SAAS,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IAChE,IAAI,OAAO,CAAC,SAAS,KAAK,OAAO;QAAE,OAAO,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACjE,IAAI,OAAO,CAAC,GAAG,KAAK,IAAI,EAAE,CAAC;QACzB,6EAA6E;QAC7E,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,KAAK,IAAI,CAAC;QACrC,OAAO,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,GAAG,UAAU,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IACtF,CAAC;IACD,IAAI,OAAO,CAAC,GAAG,KAAK,KAAK;QAAE,OAAO,IAAI,CAAC,OAAO,UAAU,EAAE,EAAE,MAAM,CAAC,CAAC;IACpE,OAAO,IAAI,CAAC;AACd,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,UAAU,CAAC,EAAE,OAAO,EAAwB;IAC1D,MAAM,KAAK,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC;IAClC,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAChC,OAAO,KAAC,KAAK,IAAC,OAAO,EAAE,KAAK,CAAC,OAAO,YAAG,KAAK,CAAC,KAAK,GAAS,CAAC;AAC9D,CAAC"}
@@ -1,16 +1,24 @@
1
+ import type { JSX, ReactNode } from 'react';
2
+ import { type ChartSelection } from './chart-selection.js';
1
3
  export interface AreaChartPoint {
2
4
  /** X-axis label (e.g. formatted time). */
3
5
  label: string;
4
6
  /** Series value. */
5
7
  value: number;
6
8
  }
7
- /** Single-series time area chart with a subtle gradient fill and hover tooltip. */
8
- export declare function AreaChartCard({ title, data, right, color, valueLabel, height, }: {
9
+ /** Single-series time area chart with a gradient fill, a hover card and an optional brush. */
10
+ export declare function AreaChartCard({ title, data, right, color, valueLabel, height, brush, valueFormatter, onSelect, }: {
9
11
  title: string;
10
12
  data: AreaChartPoint[];
11
- right?: React.ReactNode;
13
+ right?: ReactNode;
12
14
  color?: string;
13
15
  valueLabel?: string;
14
16
  height?: number;
17
+ /** Force the range brush on or off. Defaults to on once the series is long. */
18
+ brush?: boolean;
19
+ /** Format the value in the hover card (the axis is left alone). */
20
+ valueFormatter?: (value: number) => ReactNode;
21
+ /** Drill-down: called with the point under a click. Omit and the chart is inert. */
22
+ onSelect?: (selection: ChartSelection) => void;
15
23
  }): JSX.Element;
16
24
  //# sourceMappingURL=area-chart-card.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"area-chart-card.d.ts","sourceRoot":"","sources":["../../../../src/react/components/charts/area-chart-card.tsx"],"names":[],"mappings":"AAoBA,MAAM,WAAW,cAAc;IAC7B,0CAA0C;IAC1C,KAAK,EAAE,MAAM,CAAC;IACd,oBAAoB;IACpB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,mFAAmF;AACnF,wBAAgB,aAAa,CAAC,EAC5B,KAAK,EACL,IAAI,EACJ,KAAK,EACL,KAAkB,EAClB,UAAoB,EACpB,MAAY,GACb,EAAE;IACD,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,cAAc,EAAE,CAAC;IACvB,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG,GAAG,CAAC,OAAO,CAqDd"}
1
+ {"version":3,"file":"area-chart-card.d.ts","sourceRoot":"","sources":["../../../../src/react/components/charts/area-chart-card.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAW5C,OAAO,EAAE,KAAK,cAAc,EAAoC,MAAM,sBAAsB,CAAC;AAG7F,MAAM,WAAW,cAAc;IAC7B,0CAA0C;IAC1C,KAAK,EAAE,MAAM,CAAC;IACd,oBAAoB;IACpB,KAAK,EAAE,MAAM,CAAC;CACf;AAWD,8FAA8F;AAC9F,wBAAgB,aAAa,CAAC,EAC5B,KAAK,EACL,IAAI,EACJ,KAAK,EACL,KAAkB,EAClB,UAAoB,EACpB,MAAY,EACZ,KAAK,EACL,cAAc,EACd,QAAQ,GACT,EAAE;IACD,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,cAAc,EAAE,CAAC;IACvB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,+EAA+E;IAC/E,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,mEAAmE;IACnE,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,SAAS,CAAC;IAC9C,oFAAoF;IACpF,QAAQ,CAAC,EAAE,CAAC,SAAS,EAAE,cAAc,KAAK,IAAI,CAAC;CAChD,GAAG,GAAG,CAAC,OAAO,CA0Ed"}
@@ -1,12 +1,39 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useId } from 'react';
3
- import { Area, AreaChart, CartesianGrid, ResponsiveContainer, Tooltip, XAxis, YAxis, } from 'recharts';
2
+ import { useId, useMemo } from 'react';
3
+ import { Area, AreaChart, Brush, CartesianGrid, XAxis, YAxis } from 'recharts';
4
+ import { ChartContainer, ChartTooltip, ChartTooltipContent, chartBrushProps, chartColorVar, } from '../../ui/chart.js';
4
5
  import { ChartCard, ChartEmptyState } from './chart-card.js';
5
- import { ACCENT_HEX, axisTickStyle, chartTheme, tooltipContentStyle, tooltipItemStyle, tooltipLabelStyle, } from './chart-theme.js';
6
- /** Single-series time area chart with a subtle gradient fill and hover tooltip. */
7
- export function AreaChartCard({ title, data, right, color = ACCENT_HEX, valueLabel = 'value', height = 220, }) {
6
+ import { activeChartLabel, chartSelection } from './chart-selection.js';
7
+ import { ACCENT_HEX, chartConfig } from './chart-theme.js';
8
+ /**
9
+ * Number of points past which the chart gets a range brush.
10
+ *
11
+ * A brush costs ~20px of an already short body and only earns it when the window
12
+ * is long enough that the interesting part is a slice of it; over a dozen buckets
13
+ * it is a scrollbar for a page that already fits.
14
+ */
15
+ const BRUSH_MIN_POINTS = 24;
16
+ /** Single-series time area chart with a gradient fill, a hover card and an optional brush. */
17
+ export function AreaChartCard({ title, data, right, color = ACCENT_HEX, valueLabel = 'value', height = 220, brush, valueFormatter, onSelect, }) {
8
18
  const gradientId = useId();
9
19
  const bodyHeight = height - 64;
10
- return (_jsx(ChartCard, { title: title, right: right, height: bodyHeight, children: data.length === 0 ? (_jsx(ChartEmptyState, { height: bodyHeight })) : (_jsx(ResponsiveContainer, { width: "100%", height: "100%", children: _jsxs(AreaChart, { data: data, margin: { top: 4, right: 8, bottom: 0, left: -16 }, children: [_jsx("defs", { children: _jsxs("linearGradient", { id: gradientId, x1: "0", y1: "0", x2: "0", y2: "1", children: [_jsx("stop", { offset: "0%", stopColor: color, stopOpacity: 0.35 }), _jsx("stop", { offset: "100%", stopColor: color, stopOpacity: 0 })] }) }), _jsx(CartesianGrid, { stroke: chartTheme.gridStroke, vertical: false }), _jsx(XAxis, { dataKey: "label", tick: axisTickStyle, stroke: chartTheme.axisStroke, tickLine: false, minTickGap: 24 }), _jsx(YAxis, { tick: axisTickStyle, stroke: chartTheme.axisStroke, tickLine: false, width: 40, allowDecimals: false }), _jsx(Tooltip, { contentStyle: tooltipContentStyle, labelStyle: tooltipLabelStyle, itemStyle: tooltipItemStyle, cursor: { stroke: chartTheme.axisStroke } }), _jsx(Area, { type: "monotone", dataKey: "value", name: valueLabel, stroke: color, strokeWidth: 2, fill: `url(#${gradientId})`, isAnimationActive: false, dot: false, activeDot: { r: 3 } })] }) })) }));
20
+ const config = useMemo(() => chartConfig(['value'], () => color, () => valueLabel), [color, valueLabel]);
21
+ const showBrush = brush ?? data.length >= BRUSH_MIN_POINTS;
22
+ // Interaction props are built conditionally: under `exactOptionalPropertyTypes`
23
+ // an explicit `undefined` is not assignable to Recharts' optional handlers, and
24
+ // a chart with no drill-down target must not advertise a pointer cursor.
25
+ const clickProps = onSelect
26
+ ? {
27
+ onClick: (state) => {
28
+ const label = activeChartLabel(state);
29
+ if (label === undefined)
30
+ return;
31
+ const point = data.find((p) => p.label === label);
32
+ onSelect(chartSelection({ label, series: 'value', value: point?.value }));
33
+ },
34
+ className: 'cursor-pointer',
35
+ }
36
+ : {};
37
+ return (_jsx(ChartCard, { title: title, right: right, height: bodyHeight, children: data.length === 0 ? (_jsx(ChartEmptyState, { height: bodyHeight })) : (_jsx(ChartContainer, { config: config, children: _jsxs(AreaChart, { data: data, margin: { top: 4, right: 8, bottom: 0, left: -16 }, ...clickProps, children: [_jsx("defs", { children: _jsxs("linearGradient", { id: gradientId, x1: "0", y1: "0", x2: "0", y2: "1", children: [_jsx("stop", { offset: "0%", stopColor: chartColorVar('value'), stopOpacity: 0.35 }), _jsx("stop", { offset: "100%", stopColor: chartColorVar('value'), stopOpacity: 0 })] }) }), _jsx(CartesianGrid, { vertical: false }), _jsx(XAxis, { dataKey: "label", tickLine: false, minTickGap: 24 }), _jsx(YAxis, { tickLine: false, width: 40, allowDecimals: false }), _jsx(ChartTooltip, { cursor: { stroke: 'var(--line)' }, content: _jsx(ChartTooltipContent, { ...(valueFormatter ? { valueFormatter: (v) => valueFormatter(v) } : {}) }) }), _jsx(Area, { type: "monotone", dataKey: "value", name: valueLabel, stroke: chartColorVar('value'), strokeWidth: 2, fill: `url(#${gradientId})`, isAnimationActive: false, dot: false, activeDot: { r: 3 } }), showBrush && _jsx(Brush, { ...chartBrushProps, dataKey: "label" })] }) })) }));
11
38
  }
12
39
  //# sourceMappingURL=area-chart-card.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"area-chart-card.js","sourceRoot":"","sources":["../../../../src/react/components/charts/area-chart-card.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAC9B,OAAO,EACL,IAAI,EACJ,SAAS,EACT,aAAa,EACb,mBAAmB,EACnB,OAAO,EACP,KAAK,EACL,KAAK,GACN,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAC7D,OAAO,EACL,UAAU,EACV,aAAa,EACb,UAAU,EACV,mBAAmB,EACnB,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,kBAAkB,CAAC;AAS1B,mFAAmF;AACnF,MAAM,UAAU,aAAa,CAAC,EAC5B,KAAK,EACL,IAAI,EACJ,KAAK,EACL,KAAK,GAAG,UAAU,EAClB,UAAU,GAAG,OAAO,EACpB,MAAM,GAAG,GAAG,GAQb;IACC,MAAM,UAAU,GAAG,KAAK,EAAE,CAAC;IAC3B,MAAM,UAAU,GAAG,MAAM,GAAG,EAAE,CAAC;IAC/B,OAAO,CACL,KAAC,SAAS,IAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,YACtD,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CACnB,KAAC,eAAe,IAAC,MAAM,EAAE,UAAU,GAAI,CACxC,CAAC,CAAC,CAAC,CACF,KAAC,mBAAmB,IAAC,KAAK,EAAC,MAAM,EAAC,MAAM,EAAC,MAAM,YAC7C,MAAC,SAAS,IAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,aACvE,yBACE,0BAAgB,EAAE,EAAE,UAAU,EAAE,EAAE,EAAC,GAAG,EAAC,EAAE,EAAC,GAAG,EAAC,EAAE,EAAC,GAAG,EAAC,EAAE,EAAC,GAAG,aACzD,eAAM,MAAM,EAAC,IAAI,EAAC,SAAS,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,GAAI,EACzD,eAAM,MAAM,EAAC,MAAM,EAAC,SAAS,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,GAAI,IACzC,GACZ,EACP,KAAC,aAAa,IAAC,MAAM,EAAE,UAAU,CAAC,UAAU,EAAE,QAAQ,EAAE,KAAK,GAAI,EACjE,KAAC,KAAK,IACJ,OAAO,EAAC,OAAO,EACf,IAAI,EAAE,aAAa,EACnB,MAAM,EAAE,UAAU,CAAC,UAAU,EAC7B,QAAQ,EAAE,KAAK,EACf,UAAU,EAAE,EAAE,GACd,EACF,KAAC,KAAK,IACJ,IAAI,EAAE,aAAa,EACnB,MAAM,EAAE,UAAU,CAAC,UAAU,EAC7B,QAAQ,EAAE,KAAK,EACf,KAAK,EAAE,EAAE,EACT,aAAa,EAAE,KAAK,GACpB,EACF,KAAC,OAAO,IACN,YAAY,EAAE,mBAAmB,EACjC,UAAU,EAAE,iBAAiB,EAC7B,SAAS,EAAE,gBAAgB,EAC3B,MAAM,EAAE,EAAE,MAAM,EAAE,UAAU,CAAC,UAAU,EAAE,GACzC,EACF,KAAC,IAAI,IACH,IAAI,EAAC,UAAU,EACf,OAAO,EAAC,OAAO,EACf,IAAI,EAAE,UAAU,EAChB,MAAM,EAAE,KAAK,EACb,WAAW,EAAE,CAAC,EACd,IAAI,EAAE,QAAQ,UAAU,GAAG,EAC3B,iBAAiB,EAAE,KAAK,EACxB,GAAG,EAAE,KAAK,EACV,SAAS,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,GACnB,IACQ,GACQ,CACvB,GACS,CACb,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"area-chart-card.js","sourceRoot":"","sources":["../../../../src/react/components/charts/area-chart-card.tsx"],"names":[],"mappings":"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"}
@@ -1,3 +1,5 @@
1
+ import type { JSX, ReactNode } from 'react';
2
+ import { type ChartSelection } from './chart-selection.js';
1
3
  export interface BarChartDatum {
2
4
  /** Category label on the x-axis (or y-axis when horizontal). */
3
5
  label: string;
@@ -5,22 +7,31 @@ export interface BarChartDatum {
5
7
  value: number;
6
8
  /** Optional per-bar color override. */
7
9
  color?: string;
8
- /** Optional stable identifier carried through to {@link onBarClick}. */
10
+ /** Optional stable identifier carried through to {@link BarChartCardProps.onSelect}. */
9
11
  id?: string;
10
12
  }
11
- /** Categorical bar chart (e.g. per-queue failure rate) with a hover tooltip. */
12
- export declare function BarChartCard({ title, data, right, color, valueLabel, height, horizontal, truncateLabel, onBarClick, }: {
13
+ export interface BarChartCardProps {
13
14
  title: string;
14
15
  data: BarChartDatum[];
15
- right?: React.ReactNode;
16
+ right?: ReactNode;
16
17
  color?: string;
17
18
  valueLabel?: string;
18
19
  height?: number;
19
20
  /** Render category labels down the Y axis so long labels read left-to-right. */
20
21
  horizontal?: boolean;
21
- /** Truncate tick labels to this many chars (full label stays in the tooltip). */
22
+ /** Truncate tick labels to this many chars (full label stays in the hover card). */
22
23
  truncateLabel?: number;
23
- /** Called with the datum behind a clicked bar. */
24
+ /** Format the value in the hover card (the axis is left alone). */
25
+ valueFormatter?: (value: number) => ReactNode;
26
+ /** Drill-down: called with the bar under a click. Omit and the chart is inert. */
27
+ onSelect?: (selection: ChartSelection) => void;
28
+ /**
29
+ * @deprecated Use {@link BarChartCardProps.onSelect}, which reports the same
30
+ * click in the shape every chart card uses. Still called, so existing callers
31
+ * keep working.
32
+ */
24
33
  onBarClick?: (datum: BarChartDatum) => void;
25
- }): JSX.Element;
34
+ }
35
+ /** Categorical bar chart (e.g. per-queue failure rate) with a hover card. */
36
+ export declare function BarChartCard({ title, data, right, color, valueLabel, height, horizontal, truncateLabel, valueFormatter, onSelect, onBarClick, }: BarChartCardProps): JSX.Element;
26
37
  //# sourceMappingURL=bar-chart-card.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"bar-chart-card.d.ts","sourceRoot":"","sources":["../../../../src/react/components/charts/bar-chart-card.tsx"],"names":[],"mappings":"AAoBA,MAAM,WAAW,aAAa;IAC5B,gEAAgE;IAChE,KAAK,EAAE,MAAM,CAAC;IACd,iBAAiB;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,uCAAuC;IACvC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,wEAAwE;IACxE,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAQD,gFAAgF;AAChF,wBAAgB,YAAY,CAAC,EAC3B,KAAK,EACL,IAAI,EACJ,KAAK,EACL,KAAkB,EAClB,UAAoB,EACpB,MAAY,EACZ,UAAkB,EAClB,aAAa,EACb,UAAU,GACX,EAAE;IACD,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,aAAa,EAAE,CAAC;IACtB,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gFAAgF;IAChF,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,iFAAiF;IACjF,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,kDAAkD;IAClD,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;CAC7C,GAAG,GAAG,CAAC,OAAO,CA0Gd"}
1
+ {"version":3,"file":"bar-chart-card.d.ts","sourceRoot":"","sources":["../../../../src/react/components/charts/bar-chart-card.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAU5C,OAAO,EAAE,KAAK,cAAc,EAAkB,MAAM,sBAAsB,CAAC;AAG3E,MAAM,WAAW,aAAa;IAC5B,gEAAgE;IAChE,KAAK,EAAE,MAAM,CAAC;IACd,iBAAiB;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,uCAAuC;IACvC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,wFAAwF;IACxF,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAQD,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,aAAa,EAAE,CAAC;IACtB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gFAAgF;IAChF,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,oFAAoF;IACpF,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,mEAAmE;IACnE,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,SAAS,CAAC;IAC9C,kFAAkF;IAClF,QAAQ,CAAC,EAAE,CAAC,SAAS,EAAE,cAAc,KAAK,IAAI,CAAC;IAC/C;;;;OAIG;IACH,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;CAC7C;AAED,6EAA6E;AAC7E,wBAAgB,YAAY,CAAC,EAC3B,KAAK,EACL,IAAI,EACJ,KAAK,EACL,KAAkB,EAClB,UAAoB,EACpB,MAAY,EACZ,UAAkB,EAClB,aAAa,EACb,cAAc,EACd,QAAQ,EACR,UAAU,GACX,EAAE,iBAAiB,GAAG,GAAG,CAAC,OAAO,CAsFjC"}
@@ -1,27 +1,36 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Bar, BarChart, CartesianGrid, Cell, ResponsiveContainer, Tooltip, XAxis, YAxis, } from 'recharts';
2
+ import { useMemo } from 'react';
3
+ import { Bar, BarChart, CartesianGrid, Cell, XAxis, YAxis } from 'recharts';
4
+ import { ChartContainer, ChartTooltip, ChartTooltipContent, chartColorVar, } from '../../ui/chart.js';
3
5
  import { ChartCard, ChartEmptyState } from './chart-card.js';
4
- import { ACCENT_HEX, axisTickStyle, chartTheme, tooltipContentStyle, tooltipItemStyle, tooltipLabelStyle, } from './chart-theme.js';
6
+ import { chartSelection } from './chart-selection.js';
7
+ import { ACCENT_HEX, chartConfig } from './chart-theme.js';
5
8
  /** Truncate a long category label to `max` chars with a trailing ellipsis. */
6
9
  function truncate(label, max) {
7
10
  if (label.length <= max)
8
11
  return label;
9
12
  return `${label.slice(0, Math.max(0, max - 1))}…`;
10
13
  }
11
- /** Categorical bar chart (e.g. per-queue failure rate) with a hover tooltip. */
12
- export function BarChartCard({ title, data, right, color = ACCENT_HEX, valueLabel = 'value', height = 220, horizontal = false, truncateLabel, onBarClick, }) {
14
+ /** Categorical bar chart (e.g. per-queue failure rate) with a hover card. */
15
+ export function BarChartCard({ title, data, right, color = ACCENT_HEX, valueLabel = 'value', height = 220, horizontal = false, truncateLabel, valueFormatter, onSelect, onBarClick, }) {
13
16
  const bodyHeight = height - 64;
17
+ const config = useMemo(() => chartConfig(['value'], () => color, () => valueLabel), [color, valueLabel]);
14
18
  function handleBarClick(_value, index) {
15
19
  const datum = data[index];
16
- if (datum && onBarClick)
17
- onBarClick(datum);
20
+ if (!datum)
21
+ return;
22
+ onBarClick?.(datum);
23
+ onSelect?.(chartSelection({ label: datum.label, id: datum.id, value: datum.value }));
18
24
  }
19
- // Build optional props conditionally: under `exactOptionalPropertyTypes` an
25
+ // Optional props are built conditionally: under `exactOptionalPropertyTypes` an
20
26
  // explicit `undefined` is not assignable to Recharts' optional handlers.
21
27
  const tickFormatterProps = truncateLabel !== undefined
22
28
  ? { tickFormatter: (value) => truncate(value, truncateLabel) }
23
29
  : {};
24
- const barInteractionProps = onBarClick !== undefined ? { onClick: handleBarClick, cursor: 'pointer' } : {};
25
- return (_jsx(ChartCard, { title: title, right: right, height: bodyHeight, children: data.length === 0 ? (_jsx(ChartEmptyState, { height: bodyHeight })) : (_jsx(ResponsiveContainer, { width: "100%", height: "100%", children: horizontal ? (_jsxs(BarChart, { data: data, layout: "vertical", margin: { top: 4, right: 8, bottom: 0, left: 8 }, children: [_jsx(CartesianGrid, { stroke: chartTheme.gridStroke, horizontal: false }), _jsx(XAxis, { type: "number", tick: axisTickStyle, stroke: chartTheme.axisStroke, tickLine: false, allowDecimals: false }), _jsx(YAxis, { type: "category", dataKey: "label", tick: axisTickStyle, ...tickFormatterProps, stroke: chartTheme.axisStroke, tickLine: false, width: 160, interval: 0 }), _jsx(Tooltip, { contentStyle: tooltipContentStyle, labelStyle: tooltipLabelStyle, itemStyle: tooltipItemStyle, cursor: { fill: '#ffffff08' } }), _jsx(Bar, { dataKey: "value", name: valueLabel, radius: [0, 3, 3, 0], isAnimationActive: false, ...barInteractionProps, children: data.map((datum) => (_jsx(Cell, { fill: datum.color ?? color }, datum.id ?? datum.label))) })] })) : (_jsxs(BarChart, { data: data, margin: { top: 4, right: 8, bottom: 0, left: -16 }, children: [_jsx(CartesianGrid, { stroke: chartTheme.gridStroke, vertical: false }), _jsx(XAxis, { dataKey: "label", tick: axisTickStyle, ...tickFormatterProps, stroke: chartTheme.axisStroke, tickLine: false, interval: 0 }), _jsx(YAxis, { tick: axisTickStyle, stroke: chartTheme.axisStroke, tickLine: false, width: 40, allowDecimals: false }), _jsx(Tooltip, { contentStyle: tooltipContentStyle, labelStyle: tooltipLabelStyle, itemStyle: tooltipItemStyle, cursor: { fill: '#ffffff08' } }), _jsx(Bar, { dataKey: "value", name: valueLabel, radius: [3, 3, 0, 0], isAnimationActive: false, ...barInteractionProps, children: data.map((datum) => (_jsx(Cell, { fill: datum.color ?? color }, datum.id ?? datum.label))) })] })) })) }));
30
+ const interactive = onSelect !== undefined || onBarClick !== undefined;
31
+ const barInteractionProps = interactive
32
+ ? { onClick: handleBarClick, cursor: 'pointer' }
33
+ : {};
34
+ return (_jsx(ChartCard, { title: title, right: right, height: bodyHeight, children: data.length === 0 ? (_jsx(ChartEmptyState, { height: bodyHeight })) : (_jsx(ChartContainer, { config: config, children: _jsxs(BarChart, { data: data, layout: horizontal ? 'vertical' : 'horizontal', margin: { top: 4, right: 8, bottom: 0, left: horizontal ? 8 : -16 }, children: [_jsx(CartesianGrid, { horizontal: !horizontal, vertical: horizontal }), horizontal ? (_jsx(XAxis, { type: "number", tickLine: false, allowDecimals: false })) : (_jsx(XAxis, { dataKey: "label", tickLine: false, interval: 0, ...tickFormatterProps })), horizontal ? (_jsx(YAxis, { type: "category", dataKey: "label", tickLine: false, width: 160, interval: 0, ...tickFormatterProps })) : (_jsx(YAxis, { tickLine: false, width: 40, allowDecimals: false })), _jsx(ChartTooltip, { cursor: { fill: 'color-mix(in srgb, var(--text) 5%, transparent)' }, content: _jsx(ChartTooltipContent, { ...(valueFormatter ? { valueFormatter: (v) => valueFormatter(v) } : {}) }) }), _jsx(Bar, { dataKey: "value", name: valueLabel, fill: chartColorVar('value'), radius: horizontal ? [0, 3, 3, 0] : [3, 3, 0, 0], isAnimationActive: false, ...barInteractionProps, children: data.map((datum) => (_jsx(Cell, { fill: datum.color ?? chartColorVar('value') }, datum.id ?? datum.label))) })] }) })) }));
26
35
  }
27
36
  //# sourceMappingURL=bar-chart-card.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"bar-chart-card.js","sourceRoot":"","sources":["../../../../src/react/components/charts/bar-chart-card.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"bar-chart-card.js","sourceRoot":"","sources":["../../../../src/react/components/charts/bar-chart-card.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAChC,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,aAAa,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAC5E,OAAO,EACL,cAAc,EACd,YAAY,EACZ,mBAAmB,EACnB,aAAa,GACd,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAC7D,OAAO,EAAuB,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3E,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAa3D,8EAA8E;AAC9E,SAAS,QAAQ,CAAC,KAAa,EAAE,GAAW;IAC1C,IAAI,KAAK,CAAC,MAAM,IAAI,GAAG;QAAE,OAAO,KAAK,CAAC;IACtC,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;AACpD,CAAC;AAyBD,6EAA6E;AAC7E,MAAM,UAAU,YAAY,CAAC,EAC3B,KAAK,EACL,IAAI,EACJ,KAAK,EACL,KAAK,GAAG,UAAU,EAClB,UAAU,GAAG,OAAO,EACpB,MAAM,GAAG,GAAG,EACZ,UAAU,GAAG,KAAK,EAClB,aAAa,EACb,cAAc,EACd,QAAQ,EACR,UAAU,GACQ;IAClB,MAAM,UAAU,GAAG,MAAM,GAAG,EAAE,CAAC;IAC/B,MAAM,MAAM,GAAG,OAAO,CACpB,GAAG,EAAE,CACH,WAAW,CACT,CAAC,OAAO,CAAC,EACT,GAAG,EAAE,CAAC,KAAK,EACX,GAAG,EAAE,CAAC,UAAU,CACjB,EACH,CAAC,KAAK,EAAE,UAAU,CAAC,CACpB,CAAC;IAEF,SAAS,cAAc,CAAC,MAAe,EAAE,KAAa;QACpD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;QAC1B,IAAI,CAAC,KAAK;YAAE,OAAO;QACnB,UAAU,EAAE,CAAC,KAAK,CAAC,CAAC;QACpB,QAAQ,EAAE,CAAC,cAAc,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IACvF,CAAC;IAED,gFAAgF;IAChF,yEAAyE;IACzE,MAAM,kBAAkB,GACtB,aAAa,KAAK,SAAS;QACzB,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC,KAAa,EAAE,EAAE,CAAC,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,EAAE;QACtE,CAAC,CAAC,EAAE,CAAC;IACT,MAAM,WAAW,GAAG,QAAQ,KAAK,SAAS,IAAI,UAAU,KAAK,SAAS,CAAC;IACvE,MAAM,mBAAmB,GAAG,WAAW;QACrC,CAAC,CAAC,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,SAAkB,EAAE;QACzD,CAAC,CAAC,EAAE,CAAC;IAEP,OAAO,CACL,KAAC,SAAS,IAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,YACtD,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CACnB,KAAC,eAAe,IAAC,MAAM,EAAE,UAAU,GAAI,CACxC,CAAC,CAAC,CAAC,CACF,KAAC,cAAc,IAAC,MAAM,EAAE,MAAM,YAG5B,MAAC,QAAQ,IACP,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,YAAY,EAC9C,MAAM,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,aAEnE,KAAC,aAAa,IAAC,UAAU,EAAE,CAAC,UAAU,EAAE,QAAQ,EAAE,UAAU,GAAI,EAC/D,UAAU,CAAC,CAAC,CAAC,CACZ,KAAC,KAAK,IAAC,IAAI,EAAC,QAAQ,EAAC,QAAQ,EAAE,KAAK,EAAE,aAAa,EAAE,KAAK,GAAI,CAC/D,CAAC,CAAC,CAAC,CACF,KAAC,KAAK,IAAC,OAAO,EAAC,OAAO,EAAC,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,KAAM,kBAAkB,GAAI,CAChF,EACA,UAAU,CAAC,CAAC,CAAC,CACZ,KAAC,KAAK,IACJ,IAAI,EAAC,UAAU,EACf,OAAO,EAAC,OAAO,EACf,QAAQ,EAAE,KAAK,EACf,KAAK,EAAE,GAAG,EACV,QAAQ,EAAE,CAAC,KACP,kBAAkB,GACtB,CACH,CAAC,CAAC,CAAC,CACF,KAAC,KAAK,IAAC,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,aAAa,EAAE,KAAK,GAAI,CAC5D,EACD,KAAC,YAAY,IACX,MAAM,EAAE,EAAE,IAAI,EAAE,iDAAiD,EAAE,EACnE,OAAO,EACL,KAAC,mBAAmB,OACd,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,CAAC,CAAS,EAAE,EAAE,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,GAChF,GAEJ,EACF,KAAC,GAAG,IACF,OAAO,EAAC,OAAO,EACf,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,aAAa,CAAC,OAAO,CAAC,EAC5B,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAChD,iBAAiB,EAAE,KAAK,KACpB,mBAAmB,YAEtB,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CACnB,KAAC,IAAI,IAA+B,IAAI,EAAE,KAAK,CAAC,KAAK,IAAI,aAAa,CAAC,OAAO,CAAC,IAApE,KAAK,CAAC,EAAE,IAAI,KAAK,CAAC,KAAK,CAAiD,CACpF,CAAC,GACE,IACG,GACI,CAClB,GACS,CACb,CAAC;AACJ,CAAC"}
@@ -0,0 +1,17 @@
1
+ import type { JSX } from 'react';
2
+ import { type ChartSelection } from './chart-selection.js';
3
+ export interface BreakdownSegment {
4
+ label: string;
5
+ value: number;
6
+ color?: string;
7
+ }
8
+ /** Donut (default) or single stacked bar showing how a total splits by category. */
9
+ export declare function BreakdownCard({ title, segments, style, height, onSelect, }: {
10
+ title: string;
11
+ segments: BreakdownSegment[];
12
+ style?: 'donut' | 'bar';
13
+ height?: number;
14
+ /** Drill-down: called with the segment under a click. Omit and the chart is inert. */
15
+ onSelect?: (selection: ChartSelection) => void;
16
+ }): JSX.Element;
17
+ //# sourceMappingURL=breakdown-card.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"breakdown-card.d.ts","sourceRoot":"","sources":["../../../../src/react/components/charts/breakdown-card.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAWjC,OAAO,EAAE,KAAK,cAAc,EAAkB,MAAM,sBAAsB,CAAC;AAG3E,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,oFAAoF;AACpF,wBAAgB,aAAa,CAAC,EAC5B,KAAK,EACL,QAAQ,EACR,KAAe,EACf,MAAY,EACZ,QAAQ,GACT,EAAE;IACD,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,gBAAgB,EAAE,CAAC;IAC7B,KAAK,CAAC,EAAE,OAAO,GAAG,KAAK,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,sFAAsF;IACtF,QAAQ,CAAC,EAAE,CAAC,SAAS,EAAE,cAAc,KAAK,IAAI,CAAC;CAChD,GAAG,GAAG,CAAC,OAAO,CA2Fd"}
@@ -0,0 +1,43 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useMemo } from 'react';
3
+ import { Bar, BarChart, Cell, Pie, PieChart } from 'recharts';
4
+ import { ChartContainer, ChartLegend, ChartLegendContent, ChartTooltip, ChartTooltipContent, } from '../../ui/chart.js';
5
+ import { ChartCard, ChartEmptyState } from './chart-card.js';
6
+ import { chartSelection } from './chart-selection.js';
7
+ import { chartConfig, hexForSegment } from './chart-theme.js';
8
+ /** Donut (default) or single stacked bar showing how a total splits by category. */
9
+ export function BreakdownCard({ title, segments, style = 'donut', height = 220, onSelect, }) {
10
+ const bodyHeight = height - 64;
11
+ const config = useMemo(() => chartConfig(segments.map((s) => s.label), (label, index) => hexForSegment(label, index, segments[index]?.color)), [segments]);
12
+ function select(index) {
13
+ const segment = segments[index];
14
+ if (segment && onSelect) {
15
+ onSelect(chartSelection({ label: segment.label, value: segment.value }));
16
+ }
17
+ }
18
+ // Recharts hands a click handler its own datum first; the index is what we
19
+ // actually key off, so the datum is deliberately ignored.
20
+ const clickProps = onSelect
21
+ ? { onClick: (_datum, index) => select(index), cursor: 'pointer' }
22
+ : {};
23
+ if (segments.length === 0) {
24
+ return (_jsx(ChartCard, { title: title, height: bodyHeight, children: _jsx(ChartEmptyState, { height: bodyHeight }) }));
25
+ }
26
+ if (style === 'bar') {
27
+ // One row, one stacked bar per segment: the chart is a single 100% bar, so
28
+ // every segment is its own series rather than a row in a shared one.
29
+ const row = [
30
+ { name: 'breakdown', ...Object.fromEntries(segments.map((s) => [s.label, s.value])) },
31
+ ];
32
+ return (_jsx(ChartCard, { title: title, height: bodyHeight, children: _jsx(ChartContainer, { config: config, children: _jsxs(BarChart, { data: row, layout: "vertical", children: [_jsx(ChartTooltip, { content: _jsx(ChartTooltipContent, { hideLabel: true }) }), _jsx(ChartLegend, { content: _jsx(ChartLegendContent, {}) }), segments.map((segment, index) => (_jsx(Bar, { dataKey: segment.label, stackId: "a", fill: hexForSegment(segment.label, index, segment.color), isAnimationActive: false, ...(onSelect ? { onClick: () => select(index), cursor: 'pointer' } : {}) }, segment.label)))] }) }) }));
33
+ }
34
+ const pieData = segments.map((segment, index) => ({
35
+ name: segment.label,
36
+ value: segment.value,
37
+ // `color` (not `fill`) so the hover card and the legend resolve the segment's
38
+ // own hue — see `seriesColor` in the vendored chart layer.
39
+ color: hexForSegment(segment.label, index, segment.color),
40
+ }));
41
+ return (_jsx(ChartCard, { title: title, height: bodyHeight, children: _jsx(ChartContainer, { config: config, children: _jsxs(PieChart, { children: [_jsx(ChartTooltip, { content: _jsx(ChartTooltipContent, { hideLabel: true }) }), _jsx(ChartLegend, { content: _jsx(ChartLegendContent, {}) }), _jsx(Pie, { data: pieData, dataKey: "value", nameKey: "name", innerRadius: "55%", outerRadius: "80%", isAnimationActive: false, ...clickProps, children: pieData.map((entry) => (_jsx(Cell, { fill: entry.color }, entry.name))) })] }) }) }));
42
+ }
43
+ //# sourceMappingURL=breakdown-card.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"breakdown-card.js","sourceRoot":"","sources":["../../../../src/react/components/charts/breakdown-card.tsx"],"names":[],"mappings":"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"}
@@ -5,6 +5,13 @@ export declare function ChartCard({ title, right, height, children, }: {
5
5
  height?: number;
6
6
  children: React.ReactNode;
7
7
  }): JSX.Element;
8
+ /**
9
+ * "Nothing in this window" body. `height` is optional: given one it reserves
10
+ * exactly the space the chart would have taken, and without one it fills its
11
+ * parent — which is what a card that puts something else (percentile chips) above
12
+ * the chart needs, since there the chart's share of the body is not the card's
13
+ * height.
14
+ */
8
15
  export declare function ChartEmptyState({ height }: {
9
16
  height?: number;
10
17
  }): JSX.Element;
@@ -1 +1 @@
1
- {"version":3,"file":"chart-card.d.ts","sourceRoot":"","sources":["../../../../src/react/components/charts/chart-card.tsx"],"names":[],"mappings":"AAAA,yFAAyF;AACzF,wBAAgB,SAAS,CAAC,EACxB,KAAK,EACL,KAAK,EACL,MAAY,EACZ,QAAQ,GACT,EAAE;IACD,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B,GAAG,GAAG,CAAC,OAAO,CAUd;AAED,wBAAgB,eAAe,CAAC,EAAE,MAAY,EAAE,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,GAAG,CAAC,OAAO,CAMlF"}
1
+ {"version":3,"file":"chart-card.d.ts","sourceRoot":"","sources":["../../../../src/react/components/charts/chart-card.tsx"],"names":[],"mappings":"AAAA,yFAAyF;AACzF,wBAAgB,SAAS,CAAC,EACxB,KAAK,EACL,KAAK,EACL,MAAY,EACZ,QAAQ,GACT,EAAE;IACD,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B,GAAG,GAAG,CAAC,OAAO,CAYd;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,GAAG,CAAC,OAAO,CAS5E"}
@@ -1,9 +1,16 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  /** Shared card chrome (title, optional right slot, framed body) for every chart card. */
3
3
  export function ChartCard({ title, right, height = 220, children, }) {
4
- return (_jsxs("section", { className: "rounded-lg border border-zinc-800 bg-zinc-900/40 p-4", children: [_jsxs("header", { className: "mb-3 flex items-center justify-between", children: [_jsx("h3", { className: "text-xs font-medium uppercase tracking-wide text-zinc-400", children: title }), right] }), _jsx("div", { style: { height }, children: children })] }));
4
+ return (_jsxs("section", { className: "rounded-lg border border-line bg-panel/40 p-4", children: [_jsxs("header", { className: "mb-3 flex items-center justify-between", children: [_jsx("h3", { className: "text-xs font-medium uppercase tracking-wide text-muted-foreground", children: title }), right] }), _jsx("div", { style: { height }, children: children })] }));
5
5
  }
6
- export function ChartEmptyState({ height = 220 }) {
7
- return (_jsx("div", { className: "flex items-center justify-center text-xs text-zinc-600", style: { height }, children: "No data in window." }));
6
+ /**
7
+ * "Nothing in this window" body. `height` is optional: given one it reserves
8
+ * exactly the space the chart would have taken, and without one it fills its
9
+ * parent — which is what a card that puts something else (percentile chips) above
10
+ * the chart needs, since there the chart's share of the body is not the card's
11
+ * height.
12
+ */
13
+ export function ChartEmptyState({ height }) {
14
+ return (_jsx("div", { className: "flex h-full items-center justify-center text-xs text-muted-foreground", style: height === undefined ? undefined : { height }, children: "No data in window." }));
8
15
  }
9
16
  //# sourceMappingURL=chart-card.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"chart-card.js","sourceRoot":"","sources":["../../../../src/react/components/charts/chart-card.tsx"],"names":[],"mappings":";AAAA,yFAAyF;AACzF,MAAM,UAAU,SAAS,CAAC,EACxB,KAAK,EACL,KAAK,EACL,MAAM,GAAG,GAAG,EACZ,QAAQ,GAMT;IACC,OAAO,CACL,mBAAS,SAAS,EAAC,sDAAsD,aACvE,kBAAQ,SAAS,EAAC,wCAAwC,aACxD,aAAI,SAAS,EAAC,2DAA2D,YAAE,KAAK,GAAM,EACrF,KAAK,IACC,EACT,cAAK,KAAK,EAAE,EAAE,MAAM,EAAE,YAAG,QAAQ,GAAO,IAChC,CACX,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,EAAE,MAAM,GAAG,GAAG,EAAuB;IACnE,OAAO,CACL,cAAK,SAAS,EAAC,wDAAwD,EAAC,KAAK,EAAE,EAAE,MAAM,EAAE,mCAEnF,CACP,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"chart-card.js","sourceRoot":"","sources":["../../../../src/react/components/charts/chart-card.tsx"],"names":[],"mappings":";AAAA,yFAAyF;AACzF,MAAM,UAAU,SAAS,CAAC,EACxB,KAAK,EACL,KAAK,EACL,MAAM,GAAG,GAAG,EACZ,QAAQ,GAMT;IACC,OAAO,CACL,mBAAS,SAAS,EAAC,+CAA+C,aAChE,kBAAQ,SAAS,EAAC,wCAAwC,aACxD,aAAI,SAAS,EAAC,mEAAmE,YAC9E,KAAK,GACH,EACJ,KAAK,IACC,EACT,cAAK,KAAK,EAAE,EAAE,MAAM,EAAE,YAAG,QAAQ,GAAO,IAChC,CACX,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAAC,EAAE,MAAM,EAAuB;IAC7D,OAAO,CACL,cACE,SAAS,EAAC,uEAAuE,EACjF,KAAK,EAAE,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,mCAGhD,CACP,CAAC;AACJ,CAAC"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * What a user clicked inside a chart, in the one shape every card reports it.
3
+ *
4
+ * This is the drill-down intent and nothing more: a card knows what was clicked,
5
+ * it does not know what that should filter. The caller decides — `PanelView`
6
+ * forwards the selection, the extension dashboard turns it into provider query
7
+ * state. Keeping the card ignorant is what lets the same `AreaChartCard` sit on
8
+ * the Overview page (where clicking means nothing and no callback is passed) and
9
+ * on an extension dashboard (where it filters the page).
10
+ */
11
+ export interface ChartSelection {
12
+ /** The category, bucket or x-axis label under the click. */
13
+ label: string;
14
+ /** Series key when the chart draws more than one; absent for single-series charts. */
15
+ series?: string;
16
+ /** Provider-supplied stable id, when the datum carried one (topN items do). */
17
+ id?: string;
18
+ /** The value at the click, when the click resolved to a single datum. */
19
+ value?: number;
20
+ }
21
+ /**
22
+ * Build a {@link ChartSelection} without tripping `exactOptionalPropertyTypes`,
23
+ * which rejects an explicit `undefined` for an optional field. Every card builds
24
+ * its selection here so "no id" is consistently an absent key rather than a
25
+ * present `undefined` — the difference shows up the moment a selection is spread
26
+ * into a query object.
27
+ */
28
+ export declare function chartSelection(input: {
29
+ label: string;
30
+ series?: string | undefined;
31
+ id?: string | undefined;
32
+ value?: number | undefined;
33
+ }): ChartSelection;
34
+ /**
35
+ * The x-axis label under a click on a cartesian chart.
36
+ *
37
+ * A click on an area or a line has no single datum — Recharts reports the whole
38
+ * hovered category in its chart-level event state instead, and types that state
39
+ * loosely enough that reading it is a runtime question, not a compile-time one.
40
+ * Returns undefined when the click landed on chrome (axis, legend, padding),
41
+ * which is the case a drill-down must ignore rather than fire an empty filter.
42
+ */
43
+ export declare function activeChartLabel(state: unknown): string | undefined;
44
+ //# sourceMappingURL=chart-selection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chart-selection.d.ts","sourceRoot":"","sources":["../../../../src/react/components/charts/chart-selection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,MAAM,WAAW,cAAc;IAC7B,4DAA4D;IAC5D,KAAK,EAAE,MAAM,CAAC;IACd,sFAAsF;IACtF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,+EAA+E;IAC/E,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,yEAAyE;IACzE,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,EAAE,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5B,GAAG,cAAc,CAOjB;AAMD;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAKnE"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Build a {@link ChartSelection} without tripping `exactOptionalPropertyTypes`,
3
+ * which rejects an explicit `undefined` for an optional field. Every card builds
4
+ * its selection here so "no id" is consistently an absent key rather than a
5
+ * present `undefined` — the difference shows up the moment a selection is spread
6
+ * into a query object.
7
+ */
8
+ export function chartSelection(input) {
9
+ return {
10
+ label: input.label,
11
+ ...(input.series !== undefined ? { series: input.series } : {}),
12
+ ...(input.id !== undefined ? { id: input.id } : {}),
13
+ ...(input.value !== undefined ? { value: input.value } : {}),
14
+ };
15
+ }
16
+ function isRecord(value) {
17
+ return typeof value === 'object' && value !== null;
18
+ }
19
+ /**
20
+ * The x-axis label under a click on a cartesian chart.
21
+ *
22
+ * A click on an area or a line has no single datum — Recharts reports the whole
23
+ * hovered category in its chart-level event state instead, and types that state
24
+ * loosely enough that reading it is a runtime question, not a compile-time one.
25
+ * Returns undefined when the click landed on chrome (axis, legend, padding),
26
+ * which is the case a drill-down must ignore rather than fire an empty filter.
27
+ */
28
+ export function activeChartLabel(state) {
29
+ if (!isRecord(state))
30
+ return undefined;
31
+ const label = state.activeLabel;
32
+ if (typeof label === 'string' && label.length > 0)
33
+ return label;
34
+ return typeof label === 'number' ? String(label) : undefined;
35
+ }
36
+ //# sourceMappingURL=chart-selection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chart-selection.js","sourceRoot":"","sources":["../../../../src/react/components/charts/chart-selection.ts"],"names":[],"mappings":"AAqBA;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAAC,KAK9B;IACC,OAAO;QACL,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,GAAG,CAAC,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/D,GAAG,CAAC,KAAK,CAAC,EAAE,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACnD,GAAG,CAAC,KAAK,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC7D,CAAC;AACJ,CAAC;AAED,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAC;AACrD,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAc;IAC7C,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IACvC,MAAM,KAAK,GAAG,KAAK,CAAC,WAAW,CAAC;IAChC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IAChE,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAC/D,CAAC"}