@mastra/playground-ui 68.0.0-alpha.1 → 68.0.0-alpha.3

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 (536) hide show
  1. package/dist/{DataCodeSection-CcPmJPTp.cjs → DataCodeSection-CFxXsQWH.cjs} +3 -3
  2. package/dist/DataCodeSection-CFxXsQWH.cjs.map +1 -0
  3. package/dist/{DataCodeSection-KJRyRD1Q.js → DataCodeSection-PY9XEg2C.js} +3 -3
  4. package/dist/DataCodeSection-PY9XEg2C.js.map +1 -0
  5. package/dist/{DataPanel-BwB1Oifd.cjs → DataPanel-Coc9h35I.cjs} +2 -2
  6. package/dist/{DataPanel-BwB1Oifd.cjs.map → DataPanel-Coc9h35I.cjs.map} +1 -1
  7. package/dist/{DataPanel-Bv4M17xO.js → DataPanel-IgB9D5PO.js} +2 -2
  8. package/dist/{DataPanel-Bv4M17xO.js.map → DataPanel-IgB9D5PO.js.map} +1 -1
  9. package/dist/{FilterBar-BO-vvvyq.js → FilterBar-BgW2dqRQ.js} +7 -7
  10. package/dist/FilterBar-BgW2dqRQ.js.map +1 -0
  11. package/dist/{FilterBar-Buw0tv51.cjs → FilterBar-CQl04O6t.cjs} +7 -7
  12. package/dist/FilterBar-CQl04O6t.cjs.map +1 -0
  13. package/dist/KnowledgePageGraph.css +55 -0
  14. package/dist/{MarkdownRenderer-2GOXQJEv.js → MarkdownRenderer-CI30RqdB.js} +19 -6
  15. package/dist/MarkdownRenderer-CI30RqdB.js.map +1 -0
  16. package/dist/{MarkdownRenderer-CB8Z_CHc.cjs → MarkdownRenderer-y65WGBhC.cjs} +19 -6
  17. package/dist/MarkdownRenderer-y65WGBhC.cjs.map +1 -0
  18. package/dist/{MetricsTable-D-aZf3dk.cjs → MetricsTable-BSl81oNe.cjs} +44 -9
  19. package/dist/MetricsTable-BSl81oNe.cjs.map +1 -0
  20. package/dist/{MetricsTable-CRPeLHe1.js → MetricsTable-DID6LRoP.js} +44 -9
  21. package/dist/MetricsTable-DID6LRoP.js.map +1 -0
  22. package/dist/{activity-rJ1NQl_2.js → activity-C8Ql81WM.js} +2 -2
  23. package/dist/{activity-rJ1NQl_2.js.map → activity-C8Ql81WM.js.map} +1 -1
  24. package/dist/{activity-DyB5H3gF.cjs → activity-CcQZeDYi.cjs} +2 -2
  25. package/dist/{activity-DyB5H3gF.cjs.map → activity-CcQZeDYi.cjs.map} +1 -1
  26. package/dist/{ask-user-DdYz56qH.cjs → ask-user-C1p2PEYe.cjs} +2 -2
  27. package/dist/ask-user-C1p2PEYe.cjs.map +1 -0
  28. package/dist/{ask-user-B225wzWc.js → ask-user-DPznrqGO.js} +2 -2
  29. package/dist/ask-user-DPznrqGO.js.map +1 -0
  30. package/dist/chart-plot.css +5 -4
  31. package/dist/{combobox-CtCK0mNx.js → combobox-D21no8t5.js} +4 -4
  32. package/dist/{combobox-CtCK0mNx.js.map → combobox-D21no8t5.js.map} +1 -1
  33. package/dist/{combobox-CMx2ayFN.cjs → combobox-DIT_6xiG.cjs} +4 -4
  34. package/dist/combobox-DIT_6xiG.cjs.map +1 -0
  35. package/dist/{combobox-parts-ScKcYjMR.cjs → combobox-parts-C4phOq4t.cjs} +2 -2
  36. package/dist/combobox-parts-C4phOq4t.cjs.map +1 -0
  37. package/dist/{combobox-parts-C1CugUAU.js → combobox-parts-D90ir0Py.js} +3 -3
  38. package/dist/combobox-parts-D90ir0Py.js.map +1 -0
  39. package/dist/components/Combobox.cjs.js +2 -2
  40. package/dist/components/Combobox.es.js +2 -2
  41. package/dist/components/Command.cjs.js +1 -1
  42. package/dist/components/Command.cjs.js.map +1 -1
  43. package/dist/components/Command.es.js +1 -1
  44. package/dist/components/Command.es.js.map +1 -1
  45. package/dist/components/DataCodeSection.cjs.js +1 -1
  46. package/dist/components/DataCodeSection.es.js +1 -1
  47. package/dist/components/DataList.cjs.js +1 -1
  48. package/dist/components/DataList.es.js +1 -1
  49. package/dist/components/DataPanel.cjs.js +1 -1
  50. package/dist/components/DataPanel.es.js +1 -1
  51. package/dist/components/DateTimePicker.cjs.js +1 -1
  52. package/dist/components/DateTimePicker.cjs.js.map +1 -1
  53. package/dist/components/DateTimePicker.es.js +1 -1
  54. package/dist/components/DateTimePicker.es.js.map +1 -1
  55. package/dist/components/FilterBar.cjs.js +3 -3
  56. package/dist/components/FilterBar.es.js +3 -3
  57. package/dist/components/FormFieldBlocks.cjs.js +1 -1
  58. package/dist/components/FormFieldBlocks.cjs.js.map +1 -1
  59. package/dist/components/FormFieldBlocks.es.js +1 -1
  60. package/dist/components/FormFieldBlocks.es.js.map +1 -1
  61. package/dist/components/MarkdownRenderer.cjs.js +1 -1
  62. package/dist/components/MarkdownRenderer.es.js +1 -1
  63. package/dist/components/MetricsTable.cjs.js +1 -1
  64. package/dist/components/MetricsTable.es.js +1 -1
  65. package/dist/components/PropertyFilter.cjs.js +3 -3
  66. package/dist/components/PropertyFilter.cjs.js.map +1 -1
  67. package/dist/components/PropertyFilter.es.js +3 -3
  68. package/dist/components/PropertyFilter.es.js.map +1 -1
  69. package/dist/components/SavedViews.cjs.js +2 -2
  70. package/dist/components/SavedViews.es.js +2 -2
  71. package/dist/components/Sidebar.cjs.js +8 -8
  72. package/dist/components/Sidebar.cjs.js.map +1 -1
  73. package/dist/components/Sidebar.es.js +9 -9
  74. package/dist/components/Sidebar.es.js.map +1 -1
  75. package/dist/components/ai/activity.cjs.js +1 -1
  76. package/dist/components/ai/activity.es.js +1 -1
  77. package/dist/components/ai/ask-user.cjs.js +1 -1
  78. package/dist/components/ai/ask-user.es.js +1 -1
  79. package/dist/components/ai/plan.cjs.js +1 -1
  80. package/dist/components/ai/plan.es.js +1 -1
  81. package/dist/components/ai/tool-approval.cjs.js +1 -1
  82. package/dist/components/ai/tool-approval.es.js +1 -1
  83. package/dist/components/ai/tool-call.cjs.js +2 -2
  84. package/dist/components/ai/tool-call.es.js +2 -2
  85. package/dist/domains/chat/activity/activity-stretch-line.cjs.js +1 -1
  86. package/dist/domains/chat/activity/activity-stretch-line.es.js +1 -1
  87. package/dist/domains/chat/activity/components/activity-fold.cjs.js +1 -1
  88. package/dist/domains/chat/activity/components/activity-fold.es.js +1 -1
  89. package/dist/domains/chat/activity/components/activity-timed-trigger.cjs.js +1 -1
  90. package/dist/domains/chat/activity/components/activity-timed-trigger.es.js +1 -1
  91. package/dist/domains/chat/activity/components/calls-panel.cjs.js +1 -1
  92. package/dist/domains/chat/activity/components/calls-panel.es.js +1 -1
  93. package/dist/domains/chat/activity/components/stretch-content.cjs.js +1 -1
  94. package/dist/domains/chat/activity/components/stretch-content.es.js +1 -1
  95. package/dist/domains/chat/activity/components/stretch-thought.cjs.js +1 -1
  96. package/dist/domains/chat/activity/components/stretch-thought.es.js +1 -1
  97. package/dist/domains/chat/activity/model/activity-segments.cjs.js +1 -1
  98. package/dist/domains/chat/activity/model/activity-segments.es.js +1 -1
  99. package/dist/domains/chat/activity/model/activity-words.cjs.js +2 -2
  100. package/dist/domains/chat/activity/model/activity-words.es.js +2 -2
  101. package/dist/domains/chat/components/badge-wrapper.cjs.js +1 -1
  102. package/dist/domains/chat/components/badge-wrapper.es.js +1 -1
  103. package/dist/domains/chat/knowledge/knowledge-links.cjs.js +52 -6
  104. package/dist/domains/chat/knowledge/knowledge-links.cjs.js.map +1 -1
  105. package/dist/domains/chat/knowledge/knowledge-links.es.js +53 -9
  106. package/dist/domains/chat/knowledge/knowledge-links.es.js.map +1 -1
  107. package/dist/domains/chat/knowledge/pinned-knowledge-data.cjs.js +10 -3
  108. package/dist/domains/chat/knowledge/pinned-knowledge-data.cjs.js.map +1 -1
  109. package/dist/domains/chat/knowledge/pinned-knowledge-data.es.js +10 -3
  110. package/dist/domains/chat/knowledge/pinned-knowledge-data.es.js.map +1 -1
  111. package/dist/domains/chat/knowledge/pinned-knowledge.cjs.js +8 -3
  112. package/dist/domains/chat/knowledge/pinned-knowledge.cjs.js.map +1 -1
  113. package/dist/domains/chat/knowledge/pinned-knowledge.es.js +8 -3
  114. package/dist/domains/chat/knowledge/pinned-knowledge.es.js.map +1 -1
  115. package/dist/domains/chat/knowledge.cjs.js +2 -0
  116. package/dist/domains/chat/knowledge.es.js +2 -2
  117. package/dist/domains/chat/messages/message-row.cjs.js +3 -3
  118. package/dist/domains/chat/messages/message-row.es.js +3 -3
  119. package/dist/domains/chat/messages/notification-signal-notice.cjs.js +1 -1
  120. package/dist/domains/chat/messages/notification-signal-notice.es.js +1 -1
  121. package/dist/domains/chat/messages/reasoning-content.cjs.js +1 -1
  122. package/dist/domains/chat/messages/reasoning-content.es.js +1 -1
  123. package/dist/domains/chat/messages/renderers/message-text.cjs.js +35 -1
  124. package/dist/domains/chat/messages/renderers/message-text.cjs.js.map +1 -1
  125. package/dist/domains/chat/messages/renderers/message-text.es.js +36 -2
  126. package/dist/domains/chat/messages/renderers/message-text.es.js.map +1 -1
  127. package/dist/domains/chat/messages/renderers/reasoning-part-renderer.cjs.js +1 -1
  128. package/dist/domains/chat/messages/renderers/reasoning-part-renderer.es.js +1 -1
  129. package/dist/domains/chat/messages/signal-badge.cjs.js +1 -1
  130. package/dist/domains/chat/messages/signal-badge.es.js +1 -1
  131. package/dist/domains/chat/messages/skill-message.cjs.js +2 -2
  132. package/dist/domains/chat/messages/skill-message.es.js +2 -2
  133. package/dist/domains/chat/messages/system-reminder-badge.cjs.js +1 -1
  134. package/dist/domains/chat/messages/system-reminder-badge.es.js +1 -1
  135. package/dist/domains/chat/tools/badges/agent-badge-wrapper.cjs.js +1 -1
  136. package/dist/domains/chat/tools/badges/agent-badge-wrapper.es.js +1 -1
  137. package/dist/domains/chat/tools/badges/agent-badge.cjs.js +1 -1
  138. package/dist/domains/chat/tools/badges/agent-badge.es.js +1 -1
  139. package/dist/domains/chat/tools/badges/ask-user-badge.cjs.js +1 -1
  140. package/dist/domains/chat/tools/badges/ask-user-badge.es.js +1 -1
  141. package/dist/domains/chat/tools/badges/file-tree-badge.cjs.js +2 -2
  142. package/dist/domains/chat/tools/badges/file-tree-badge.es.js +2 -2
  143. package/dist/domains/chat/tools/badges/knowledge-body-range.cjs.js +80 -0
  144. package/dist/domains/chat/tools/badges/knowledge-body-range.cjs.js.map +1 -0
  145. package/dist/domains/chat/tools/badges/knowledge-body-range.d.ts +1 -0
  146. package/dist/domains/chat/tools/badges/knowledge-body-range.es.js +78 -0
  147. package/dist/domains/chat/tools/badges/knowledge-body-range.es.js.map +1 -0
  148. package/dist/domains/chat/tools/badges/knowledge-tool-badge.cjs.js +163 -13
  149. package/dist/domains/chat/tools/badges/knowledge-tool-badge.cjs.js.map +1 -1
  150. package/dist/domains/chat/tools/badges/knowledge-tool-badge.es.js +165 -15
  151. package/dist/domains/chat/tools/badges/knowledge-tool-badge.es.js.map +1 -1
  152. package/dist/domains/chat/tools/badges/mcp-input-request-badge.cjs.js +51 -0
  153. package/dist/domains/chat/tools/badges/mcp-input-request-badge.cjs.js.map +1 -0
  154. package/dist/domains/chat/tools/badges/mcp-input-request-badge.d.ts +1 -0
  155. package/dist/domains/chat/tools/badges/mcp-input-request-badge.es.js +49 -0
  156. package/dist/domains/chat/tools/badges/mcp-input-request-badge.es.js.map +1 -0
  157. package/dist/domains/chat/tools/badges/mcp-task-chip.cjs.js +7 -2
  158. package/dist/domains/chat/tools/badges/mcp-task-chip.cjs.js.map +1 -1
  159. package/dist/domains/chat/tools/badges/mcp-task-chip.es.js +7 -2
  160. package/dist/domains/chat/tools/badges/mcp-task-chip.es.js.map +1 -1
  161. package/dist/domains/chat/tools/badges/observation-marker-badge.cjs.js +2 -2
  162. package/dist/domains/chat/tools/badges/observation-marker-badge.es.js +2 -2
  163. package/dist/domains/chat/tools/badges/observation-marker-details.cjs.js +2 -2
  164. package/dist/domains/chat/tools/badges/observation-marker-details.es.js +2 -2
  165. package/dist/domains/chat/tools/badges/observation-renderer.cjs.js +1 -1
  166. package/dist/domains/chat/tools/badges/observation-renderer.es.js +1 -1
  167. package/dist/domains/chat/tools/badges/sandbox-execution-badge.cjs.js +2 -2
  168. package/dist/domains/chat/tools/badges/sandbox-execution-badge.es.js +2 -2
  169. package/dist/domains/chat/tools/badges/tool-approval-badge.cjs.js +1 -1
  170. package/dist/domains/chat/tools/badges/tool-approval-badge.es.js +1 -1
  171. package/dist/domains/chat/tools/badges/tool-badge.cjs.js +9 -4
  172. package/dist/domains/chat/tools/badges/tool-badge.cjs.js.map +1 -1
  173. package/dist/domains/chat/tools/badges/tool-badge.es.js +9 -4
  174. package/dist/domains/chat/tools/badges/tool-badge.es.js.map +1 -1
  175. package/dist/domains/chat/tools/badges/use-deferred-input-request.cjs.js +81 -0
  176. package/dist/domains/chat/tools/badges/use-deferred-input-request.cjs.js.map +1 -0
  177. package/dist/domains/chat/tools/badges/use-deferred-input-request.d.ts +1 -0
  178. package/dist/domains/chat/tools/badges/use-deferred-input-request.es.js +77 -0
  179. package/dist/domains/chat/tools/badges/use-deferred-input-request.es.js.map +1 -0
  180. package/dist/domains/chat/tools/badges/use-mcp-task-progress.cjs.js +11 -2
  181. package/dist/domains/chat/tools/badges/use-mcp-task-progress.cjs.js.map +1 -1
  182. package/dist/domains/chat/tools/badges/use-mcp-task-progress.es.js +11 -2
  183. package/dist/domains/chat/tools/badges/use-mcp-task-progress.es.js.map +1 -1
  184. package/dist/domains/chat/tools/badges/workflow-badge.cjs.js +1 -1
  185. package/dist/domains/chat/tools/badges/workflow-badge.es.js +1 -1
  186. package/dist/domains/chat/tools/mcp-input-request-tool.cjs.js +240 -0
  187. package/dist/domains/chat/tools/mcp-input-request-tool.cjs.js.map +1 -0
  188. package/dist/domains/chat/tools/mcp-input-request-tool.d.ts +1 -0
  189. package/dist/domains/chat/tools/mcp-input-request-tool.es.js +239 -0
  190. package/dist/domains/chat/tools/mcp-input-request-tool.es.js.map +1 -0
  191. package/dist/domains/chat/tools/mcp-input-request.cjs.js +40 -0
  192. package/dist/domains/chat/tools/mcp-input-request.cjs.js.map +1 -0
  193. package/dist/domains/chat/tools/mcp-input-request.d.ts +1 -0
  194. package/dist/domains/chat/tools/mcp-input-request.es.js +33 -0
  195. package/dist/domains/chat/tools/mcp-input-request.es.js.map +1 -0
  196. package/dist/domains/chat/tools/tool-card-kind.cjs.js +8 -3
  197. package/dist/domains/chat/tools/tool-card-kind.cjs.js.map +1 -1
  198. package/dist/domains/chat/tools/tool-card-kind.es.js +8 -4
  199. package/dist/domains/chat/tools/tool-card-kind.es.js.map +1 -1
  200. package/dist/domains/chat/tools/tool-card.cjs.js +1 -1
  201. package/dist/domains/chat/tools/tool-card.es.js +1 -1
  202. package/dist/domains/chat/tools/tool-groups.cjs.js +1 -1
  203. package/dist/domains/chat/tools/tool-groups.es.js +1 -1
  204. package/dist/domains/chat.cjs.js +5 -3
  205. package/dist/domains/chat.es.js +4 -4
  206. package/dist/domains/dashboards/kinds/table/table-view.cjs.js +1 -1
  207. package/dist/domains/dashboards/kinds/table/table-view.es.js +1 -1
  208. package/dist/domains/dashboards/metrics-dashboard.cjs.js +1 -1
  209. package/dist/domains/dashboards/metrics-dashboard.cjs.js.map +1 -1
  210. package/dist/domains/dashboards/metrics-dashboard.es.js +1 -1
  211. package/dist/domains/dashboards/metrics-dashboard.es.js.map +1 -1
  212. package/dist/domains/datasets/components/save-as-dataset-item-dialog.cjs.js +1 -1
  213. package/dist/domains/datasets/components/save-as-dataset-item-dialog.es.js +1 -1
  214. package/dist/domains/knowledge/components/KnowledgePageCard.cjs.js +48 -0
  215. package/dist/domains/knowledge/components/KnowledgePageCard.cjs.js.map +1 -0
  216. package/dist/domains/knowledge/components/KnowledgePageCard.d.ts +1 -0
  217. package/dist/domains/knowledge/components/KnowledgePageCard.es.js +47 -0
  218. package/dist/domains/knowledge/components/KnowledgePageCard.es.js.map +1 -0
  219. package/dist/domains/knowledge/components/KnowledgePageDetail.cjs.js +63 -5
  220. package/dist/domains/knowledge/components/KnowledgePageDetail.cjs.js.map +1 -1
  221. package/dist/domains/knowledge/components/KnowledgePageDetail.es.js +64 -6
  222. package/dist/domains/knowledge/components/KnowledgePageDetail.es.js.map +1 -1
  223. package/dist/domains/knowledge/components/KnowledgePageExplorer.cjs.js +485 -47
  224. package/dist/domains/knowledge/components/KnowledgePageExplorer.cjs.js.map +1 -1
  225. package/dist/domains/knowledge/components/KnowledgePageExplorer.es.js +487 -50
  226. package/dist/domains/knowledge/components/KnowledgePageExplorer.es.js.map +1 -1
  227. package/dist/domains/knowledge/components/KnowledgePageGraph.cjs.js +1051 -123
  228. package/dist/domains/knowledge/components/KnowledgePageGraph.cjs.js.map +1 -1
  229. package/dist/domains/knowledge/components/KnowledgePageGraph.es.js +1054 -126
  230. package/dist/domains/knowledge/components/KnowledgePageGraph.es.js.map +1 -1
  231. package/dist/domains/knowledge/components/KnowledgePageTree.cjs.js +75 -3
  232. package/dist/domains/knowledge/components/KnowledgePageTree.cjs.js.map +1 -1
  233. package/dist/domains/knowledge/components/KnowledgePageTree.es.js +76 -4
  234. package/dist/domains/knowledge/components/KnowledgePageTree.es.js.map +1 -1
  235. package/dist/domains/knowledge/lib/circleText.cjs.js +9 -0
  236. package/dist/domains/knowledge/lib/circleText.cjs.js.map +1 -0
  237. package/dist/domains/knowledge/lib/circleText.d.ts +1 -0
  238. package/dist/domains/knowledge/lib/circleText.es.js +8 -0
  239. package/dist/domains/knowledge/lib/circleText.es.js.map +1 -0
  240. package/dist/domains/knowledge/lib/fitViewport.cjs.js +82 -0
  241. package/dist/domains/knowledge/lib/fitViewport.cjs.js.map +1 -0
  242. package/dist/domains/knowledge/lib/fitViewport.d.ts +1 -0
  243. package/dist/domains/knowledge/lib/fitViewport.es.js +73 -0
  244. package/dist/domains/knowledge/lib/fitViewport.es.js.map +1 -0
  245. package/dist/domains/knowledge/lib/graphShape.cjs.js +524 -0
  246. package/dist/domains/knowledge/lib/graphShape.cjs.js.map +1 -0
  247. package/dist/domains/knowledge/lib/graphShape.d.ts +1 -0
  248. package/dist/domains/knowledge/lib/graphShape.es.js +499 -0
  249. package/dist/domains/knowledge/lib/graphShape.es.js.map +1 -0
  250. package/dist/domains/knowledge/lib/linkCountsText.cjs.js +11 -0
  251. package/dist/domains/knowledge/lib/linkCountsText.cjs.js.map +1 -0
  252. package/dist/domains/knowledge/lib/linkCountsText.d.ts +1 -0
  253. package/dist/domains/knowledge/lib/linkCountsText.es.js +10 -0
  254. package/dist/domains/knowledge/lib/linkCountsText.es.js.map +1 -0
  255. package/dist/domains/knowledge/lib/pageAddress.cjs.js +29 -0
  256. package/dist/domains/knowledge/lib/pageAddress.cjs.js.map +1 -0
  257. package/dist/domains/knowledge/lib/pageAddress.d.ts +1 -0
  258. package/dist/domains/knowledge/lib/pageAddress.es.js +27 -0
  259. package/dist/domains/knowledge/lib/pageAddress.es.js.map +1 -0
  260. package/dist/domains/knowledge/lib/pageGraph.cjs.js +11 -11
  261. package/dist/domains/knowledge/lib/pageGraph.cjs.js.map +1 -1
  262. package/dist/domains/knowledge/lib/pageGraph.es.js +11 -11
  263. package/dist/domains/knowledge/lib/pageGraph.es.js.map +1 -1
  264. package/dist/domains/knowledge/lib/pageRefs.cjs.js +69 -0
  265. package/dist/domains/knowledge/lib/pageRefs.cjs.js.map +1 -0
  266. package/dist/domains/knowledge/lib/pageRefs.d.ts +1 -0
  267. package/dist/domains/knowledge/lib/pageRefs.es.js +66 -0
  268. package/dist/domains/knowledge/lib/pageRefs.es.js.map +1 -0
  269. package/dist/domains/knowledge/lib/pageTree.cjs.js +5 -0
  270. package/dist/domains/knowledge/lib/pageTree.cjs.js.map +1 -1
  271. package/dist/domains/knowledge/lib/pageTree.es.js +5 -1
  272. package/dist/domains/knowledge/lib/pageTree.es.js.map +1 -1
  273. package/dist/domains/knowledge/lib/remarkKnowledgeLinks.cjs.js +82 -0
  274. package/dist/domains/knowledge/lib/remarkKnowledgeLinks.cjs.js.map +1 -0
  275. package/dist/domains/knowledge/lib/remarkKnowledgeLinks.d.ts +1 -0
  276. package/dist/domains/knowledge/lib/remarkKnowledgeLinks.es.js +78 -0
  277. package/dist/domains/knowledge/lib/remarkKnowledgeLinks.es.js.map +1 -0
  278. package/dist/domains/knowledge/lib/tooltipSide.cjs.js +77 -0
  279. package/dist/domains/knowledge/lib/tooltipSide.cjs.js.map +1 -0
  280. package/dist/domains/knowledge/lib/tooltipSide.d.ts +1 -0
  281. package/dist/domains/knowledge/lib/tooltipSide.es.js +75 -0
  282. package/dist/domains/knowledge/lib/tooltipSide.es.js.map +1 -0
  283. package/dist/domains/knowledge/lib/useLeavingNodes.cjs.js +65 -0
  284. package/dist/domains/knowledge/lib/useLeavingNodes.cjs.js.map +1 -0
  285. package/dist/domains/knowledge/lib/useLeavingNodes.d.ts +1 -0
  286. package/dist/domains/knowledge/lib/useLeavingNodes.es.js +62 -0
  287. package/dist/domains/knowledge/lib/useLeavingNodes.es.js.map +1 -0
  288. package/dist/domains/knowledge/lib/useStableWhile.cjs.js +15 -0
  289. package/dist/domains/knowledge/lib/useStableWhile.cjs.js.map +1 -0
  290. package/dist/domains/knowledge/lib/useStableWhile.d.ts +1 -0
  291. package/dist/domains/knowledge/lib/useStableWhile.es.js +14 -0
  292. package/dist/domains/knowledge/lib/useStableWhile.es.js.map +1 -0
  293. package/dist/domains/logs/components/log-data-panel.cjs.js +1 -1
  294. package/dist/domains/logs/components/log-data-panel.es.js +1 -1
  295. package/dist/domains/logs/components/logs-saved-views.cjs.js +1 -1
  296. package/dist/domains/logs/components/logs-saved-views.es.js +1 -1
  297. package/dist/domains/logs/components/logs-toolbar.cjs.js +1 -1
  298. package/dist/domains/logs/components/logs-toolbar.es.js +1 -1
  299. package/dist/domains/metrics/components/breakdown/breakdown-table.cjs.js +2 -2
  300. package/dist/domains/metrics/components/breakdown/breakdown-table.cjs.js.map +1 -1
  301. package/dist/domains/metrics/components/breakdown/breakdown-table.es.js +2 -2
  302. package/dist/domains/metrics/components/breakdown/breakdown-table.es.js.map +1 -1
  303. package/dist/domains/metrics/components/metrics-time-range-chip.cjs.js +1 -1
  304. package/dist/domains/metrics/components/metrics-time-range-chip.es.js +1 -1
  305. package/dist/domains/observability/saved-views/observability-saved-views.cjs.js +1 -1
  306. package/dist/domains/observability/saved-views/observability-saved-views.es.js +1 -1
  307. package/dist/domains/observability/saved-views.cjs.js +1 -1
  308. package/dist/domains/observability/saved-views.es.js +1 -1
  309. package/dist/domains/observability.cjs.js +1 -1
  310. package/dist/domains/observability.es.js +1 -1
  311. package/dist/domains/scores/components/score-data-panel.cjs.js +1 -1
  312. package/dist/domains/scores/components/score-data-panel.es.js +1 -1
  313. package/dist/domains/scores/components/span-scoring.cjs.js +3 -3
  314. package/dist/domains/scores/components/span-scoring.cjs.js.map +1 -1
  315. package/dist/domains/scores/components/span-scoring.es.js +3 -3
  316. package/dist/domains/scores/components/span-scoring.es.js.map +1 -1
  317. package/dist/domains/scores/components/trace-scores-list.cjs.js +2 -2
  318. package/dist/domains/scores/components/trace-scores-list.es.js +2 -2
  319. package/dist/domains/skills/skill-simple-form.cjs.js +2 -2
  320. package/dist/domains/skills/skill-simple-form.cjs.js.map +1 -1
  321. package/dist/domains/skills/skill-simple-form.es.js +2 -2
  322. package/dist/domains/skills/skill-simple-form.es.js.map +1 -1
  323. package/dist/domains/spans/components/spans-explorer-body.cjs.js +1 -1
  324. package/dist/domains/spans/components/spans-explorer-body.es.js +1 -1
  325. package/dist/domains/spans/components/spans-filter-bar.cjs.js +3 -3
  326. package/dist/domains/spans/components/spans-filter-bar.cjs.js.map +1 -1
  327. package/dist/domains/spans/components/spans-filter-bar.es.js +3 -3
  328. package/dist/domains/spans/components/spans-filter-bar.es.js.map +1 -1
  329. package/dist/domains/spans/hooks/use-spans-filter-bar.cjs.js +1 -1
  330. package/dist/domains/spans/hooks/use-spans-filter-bar.es.js +1 -1
  331. package/dist/domains/threads/components/threads-explorer-body.cjs.js +1 -1
  332. package/dist/domains/threads/components/threads-explorer-body.es.js +1 -1
  333. package/dist/domains/threads/components/threads-filter-bar.cjs.js +3 -3
  334. package/dist/domains/threads/components/threads-filter-bar.cjs.js.map +1 -1
  335. package/dist/domains/threads/components/threads-filter-bar.es.js +3 -3
  336. package/dist/domains/threads/components/threads-filter-bar.es.js.map +1 -1
  337. package/dist/domains/threads/hooks/use-threads-filter-bar.cjs.js +1 -1
  338. package/dist/domains/threads/hooks/use-threads-filter-bar.es.js +1 -1
  339. package/dist/domains/traces/components/feedback-thread.cjs.js +1 -1
  340. package/dist/domains/traces/components/feedback-thread.cjs.js.map +1 -1
  341. package/dist/domains/traces/components/feedback-thread.es.js +1 -1
  342. package/dist/domains/traces/components/feedback-thread.es.js.map +1 -1
  343. package/dist/domains/traces/components/span-data-panel-view.cjs.js +1 -1
  344. package/dist/domains/traces/components/span-data-panel-view.es.js +1 -1
  345. package/dist/domains/traces/components/span-payload/span-error-renderer.cjs.js +1 -1
  346. package/dist/domains/traces/components/span-payload/span-error-renderer.es.js +1 -1
  347. package/dist/domains/traces/components/span-payload/span-input-renderers.cjs.js +1 -1
  348. package/dist/domains/traces/components/span-payload/span-input-renderers.es.js +1 -1
  349. package/dist/domains/traces/components/span-payload/span-output-renderers.cjs.js +2 -2
  350. package/dist/domains/traces/components/span-payload/span-output-renderers.es.js +2 -2
  351. package/dist/domains/traces/components/span-payload/span-payload-messages.cjs.js +2 -2
  352. package/dist/domains/traces/components/span-payload/span-payload-messages.es.js +2 -2
  353. package/dist/domains/traces/components/span-payload/span-payload-primitives.cjs.js +1 -1
  354. package/dist/domains/traces/components/span-payload/span-payload-primitives.es.js +1 -1
  355. package/dist/domains/traces/components/span-payload/span-payload-processor.cjs.js +1 -1
  356. package/dist/domains/traces/components/span-payload/span-payload-processor.es.js +1 -1
  357. package/dist/domains/traces/components/span-payload/span-payload-tool.cjs.js +1 -1
  358. package/dist/domains/traces/components/span-payload/span-payload-tool.es.js +1 -1
  359. package/dist/domains/traces/components/span-payload/span-processor-mutations.cjs.js +1 -1
  360. package/dist/domains/traces/components/span-payload/span-processor-mutations.es.js +1 -1
  361. package/dist/domains/traces/components/span-payload/span-tools-section.cjs.js +1 -1
  362. package/dist/domains/traces/components/span-payload/span-tools-section.es.js +1 -1
  363. package/dist/domains/traces/components/span-summary-description.cjs.js +1 -1
  364. package/dist/domains/traces/components/span-summary-description.es.js +1 -1
  365. package/dist/domains/traces/components/span-timeline-row.cjs.js +1 -1
  366. package/dist/domains/traces/components/span-timeline-row.es.js +1 -1
  367. package/dist/domains/traces/components/span-timing-hover-card.cjs.js +1 -1
  368. package/dist/domains/traces/components/span-timing-hover-card.es.js +1 -1
  369. package/dist/domains/traces/components/thread-trace/thread-trace-details.cjs.js +1 -1
  370. package/dist/domains/traces/components/thread-trace/thread-trace-details.es.js +1 -1
  371. package/dist/domains/traces/components/trace-columns-menu.cjs.js +3 -3
  372. package/dist/domains/traces/components/trace-columns-menu.cjs.js.map +1 -1
  373. package/dist/domains/traces/components/trace-columns-menu.es.js +3 -3
  374. package/dist/domains/traces/components/trace-columns-menu.es.js.map +1 -1
  375. package/dist/domains/traces/components/trace-data-panel-view.cjs.js +10 -4
  376. package/dist/domains/traces/components/trace-data-panel-view.cjs.js.map +1 -1
  377. package/dist/domains/traces/components/trace-data-panel-view.es.js +10 -4
  378. package/dist/domains/traces/components/trace-data-panel-view.es.js.map +1 -1
  379. package/dist/domains/traces/components/trace-error-cell.cjs.js +1 -1
  380. package/dist/domains/traces/components/trace-error-cell.es.js +1 -1
  381. package/dist/domains/traces/components/trace-id-button.cjs.js +1 -1
  382. package/dist/domains/traces/components/trace-id-button.es.js +1 -1
  383. package/dist/domains/traces/components/trace-summary-description.cjs.js +1 -1
  384. package/dist/domains/traces/components/trace-summary-description.es.js +1 -1
  385. package/dist/domains/traces/components/trace-thread-panel.cjs.js +1 -1
  386. package/dist/domains/traces/components/trace-thread-panel.es.js +1 -1
  387. package/dist/domains/traces/components/traces-explorer/traces-explorer-filter-bar.cjs.js +3 -3
  388. package/dist/domains/traces/components/traces-explorer/traces-explorer-filter-bar.cjs.js.map +1 -1
  389. package/dist/domains/traces/components/traces-explorer/traces-explorer-filter-bar.es.js +3 -3
  390. package/dist/domains/traces/components/traces-explorer/traces-explorer-filter-bar.es.js.map +1 -1
  391. package/dist/domains/traces/components/traces-explorer/traces-explorer-saved-views.cjs.js +1 -1
  392. package/dist/domains/traces/components/traces-explorer/traces-explorer-saved-views.es.js +1 -1
  393. package/dist/domains/traces/components/traces-explorer/use-traces-filter-bar.cjs.js +1 -1
  394. package/dist/domains/traces/components/traces-explorer/use-traces-filter-bar.es.js +1 -1
  395. package/dist/domains/workflows/components/workflow-combobox.cjs.js +2 -2
  396. package/dist/domains/workflows/components/workflow-combobox.cjs.js.map +1 -1
  397. package/dist/domains/workflows/components/workflow-combobox.es.js +2 -2
  398. package/dist/domains/workflows/components/workflow-combobox.es.js.map +1 -1
  399. package/dist/domains/workflows/runs/workflow-run-list.cjs.js +1 -1
  400. package/dist/domains/workflows/runs/workflow-run-list.es.js +1 -1
  401. package/dist/domains/workflows/workflow/input/workflow-processor-input.cjs.js +3 -3
  402. package/dist/domains/workflows/workflow/input/workflow-processor-input.cjs.js.map +1 -1
  403. package/dist/domains/workflows/workflow/input/workflow-processor-input.es.js +3 -3
  404. package/dist/domains/workflows/workflow/input/workflow-processor-input.es.js.map +1 -1
  405. package/dist/domains/workflows/workflow/use-workflow-trigger.cjs.js +3 -3
  406. package/dist/domains/workflows/workflow/use-workflow-trigger.es.js +3 -3
  407. package/dist/domains/workflows/workflow/workflow-input-data.cjs.js +1 -1
  408. package/dist/domains/workflows/workflow/workflow-input-data.es.js +1 -1
  409. package/dist/domains/workflows/workflow/workflow-suspended-steps.cjs.js +2 -2
  410. package/dist/domains/workflows/workflow/workflow-suspended-steps.es.js +2 -2
  411. package/dist/domains/workflows/workflow/workflow-time-travel-form.cjs.js +2 -2
  412. package/dist/domains/workflows/workflow/workflow-time-travel-form.es.js +2 -2
  413. package/dist/domains/workspace/components/workspace-add-skill-dialog.cjs.js +2 -2
  414. package/dist/domains/workspace/components/workspace-add-skill-dialog.cjs.js.map +1 -1
  415. package/dist/domains/workspace/components/workspace-add-skill-dialog.es.js +2 -2
  416. package/dist/domains/workspace/components/workspace-add-skill-dialog.es.js.map +1 -1
  417. package/dist/domains/workspace/components/workspace-markdown-preview.cjs.js +1 -1
  418. package/dist/domains/workspace/components/workspace-markdown-preview.es.js +1 -1
  419. package/dist/{filter-bar-chip-B4sV4gDm.js → filter-bar-chip-CABeKrtf.js} +4 -4
  420. package/dist/{filter-bar-chip-B4sV4gDm.js.map → filter-bar-chip-CABeKrtf.js.map} +1 -1
  421. package/dist/{filter-bar-chip-CIEsWcEw.cjs → filter-bar-chip-Cg-UbIwP.cjs} +4 -4
  422. package/dist/{filter-bar-chip-CIEsWcEw.cjs.map → filter-bar-chip-Cg-UbIwP.cjs.map} +1 -1
  423. package/dist/{filter-bar-time-range-DvuaFnkI.cjs → filter-bar-time-range-BA-pXMlo.cjs} +2 -2
  424. package/dist/{filter-bar-time-range-DvuaFnkI.cjs.map → filter-bar-time-range-BA-pXMlo.cjs.map} +1 -1
  425. package/dist/{filter-bar-time-range-CXQMBgpz.js → filter-bar-time-range-mg9JeYue.js} +2 -2
  426. package/dist/{filter-bar-time-range-CXQMBgpz.js.map → filter-bar-time-range-mg9JeYue.js.map} +1 -1
  427. package/dist/layout/tabbed-container.cjs.js +1 -1
  428. package/dist/layout/tabbed-container.es.js +1 -1
  429. package/dist/lib/form/dynamic-form.cjs.js +2 -2
  430. package/dist/lib/form/dynamic-form.es.js +2 -2
  431. package/dist/lib/form/json-draft.cjs.js +1 -1
  432. package/dist/lib/form/json-draft.es.js +1 -1
  433. package/dist/lib/form/zod-provider.cjs.js +1 -1
  434. package/dist/lib/form/zod-provider.es.js +1 -1
  435. package/dist/{observability-saved-views-BBam8Fr5.js → observability-saved-views-CjKTEp1V.js} +3 -3
  436. package/dist/observability-saved-views-CjKTEp1V.js.map +1 -0
  437. package/dist/{observability-saved-views-BAzxxoAr.cjs → observability-saved-views-Daizz4tU.cjs} +3 -3
  438. package/dist/observability-saved-views-Daizz4tU.cjs.map +1 -0
  439. package/dist/primitives/chart-plot.cjs.js +8 -6
  440. package/dist/primitives/chart-plot.cjs.js.map +1 -1
  441. package/dist/primitives/chart-plot.es.js +8 -6
  442. package/dist/primitives/chart-plot.es.js.map +1 -1
  443. package/dist/primitives/control-icon.cjs.js.map +1 -1
  444. package/dist/primitives/control-icon.es.js.map +1 -1
  445. package/dist/{property-filter-applied-p3dTTDdb.js → property-filter-applied--U5EZdaA.js} +2 -2
  446. package/dist/property-filter-applied--U5EZdaA.js.map +1 -0
  447. package/dist/{property-filter-applied-BCeRLcXb.cjs → property-filter-applied-BkkIObRq.cjs} +2 -2
  448. package/dist/property-filter-applied-BkkIObRq.cjs.map +1 -0
  449. package/dist/{span-payload-primitives-B3RdahsC.js → span-payload-primitives-CKKIAVPJ.js} +4 -4
  450. package/dist/{span-payload-primitives-B3RdahsC.js.map → span-payload-primitives-CKKIAVPJ.js.map} +1 -1
  451. package/dist/{span-payload-primitives-_2d-pAOD.cjs → span-payload-primitives-D4tHWN2W.cjs} +4 -4
  452. package/dist/{span-payload-primitives-_2d-pAOD.cjs.map → span-payload-primitives-D4tHWN2W.cjs.map} +1 -1
  453. package/dist/src/domains/chat/knowledge/knowledge-links.d.ts +32 -4
  454. package/dist/src/domains/chat/knowledge/pinned-knowledge-data.d.ts +2 -0
  455. package/dist/src/domains/chat/tools/badges/knowledge-body-range.d.ts +12 -0
  456. package/dist/src/domains/chat/tools/badges/knowledge-tool-badge.d.ts +5 -2
  457. package/dist/src/domains/chat/tools/badges/mcp-input-request-badge.d.ts +18 -0
  458. package/dist/src/domains/chat/tools/badges/tool-badge.d.ts +4 -1
  459. package/dist/src/domains/chat/tools/badges/use-deferred-input-request.d.ts +44 -0
  460. package/dist/src/domains/chat/tools/badges/use-mcp-task-progress.d.ts +6 -1
  461. package/dist/src/domains/chat/tools/mcp-input-request-tool.d.ts +18 -0
  462. package/dist/src/domains/chat/tools/mcp-input-request.d.ts +40 -0
  463. package/dist/src/domains/chat/tools/tool-card-kind.d.ts +4 -2
  464. package/dist/src/domains/chat/tools/tool-card.d.ts +1 -1
  465. package/dist/src/domains/knowledge/components/KnowledgePageCard.d.ts +23 -0
  466. package/dist/src/domains/knowledge/components/KnowledgePageExplorer.d.ts +29 -0
  467. package/dist/src/domains/knowledge/components/KnowledgePageGraph.d.ts +27 -1
  468. package/dist/src/domains/knowledge/components/KnowledgePageTree.d.ts +2 -1
  469. package/dist/src/domains/knowledge/lib/circleText.d.ts +2 -0
  470. package/dist/src/domains/knowledge/lib/fitViewport.d.ts +67 -0
  471. package/dist/src/domains/knowledge/lib/graphShape.d.ts +131 -0
  472. package/dist/src/domains/knowledge/lib/linkCountsText.d.ts +5 -0
  473. package/dist/src/domains/knowledge/lib/pageAddress.d.ts +5 -0
  474. package/dist/src/domains/knowledge/lib/pageGraph.d.ts +4 -4
  475. package/dist/src/domains/knowledge/lib/pageRefs.d.ts +15 -0
  476. package/dist/src/domains/knowledge/lib/pageTree.d.ts +2 -0
  477. package/dist/src/domains/knowledge/lib/remarkKnowledgeLinks.d.ts +13 -0
  478. package/dist/src/domains/knowledge/lib/tooltipSide.d.ts +40 -0
  479. package/dist/src/domains/knowledge/lib/useLeavingNodes.d.ts +14 -0
  480. package/dist/src/domains/knowledge/lib/useStableWhile.d.ts +5 -0
  481. package/dist/src/domains/knowledge/pageTypes.d.ts +6 -1
  482. package/dist/src/ds/components/MarkdownRenderer/markdown-renderer.d.ts +8 -1
  483. package/dist/src/ds/components/MetricsTable/metrics-table-rows.d.ts +10 -3
  484. package/dist/src/ds/components/MetricsTable/metrics-table.d.ts +1 -1
  485. package/dist/src/ds/components/ai/tool-call/tool-phrases.d.ts +6 -0
  486. package/dist/style.css +83 -3
  487. package/dist/{tabbed-container-DQU7pVio.cjs → tabbed-container-B4lCBgRP.cjs} +2 -2
  488. package/dist/{tabbed-container-DQU7pVio.cjs.map → tabbed-container-B4lCBgRP.cjs.map} +1 -1
  489. package/dist/{tabbed-container-5j6dhoRX.js → tabbed-container-DI1GI1Qv.js} +2 -2
  490. package/dist/{tabbed-container-5j6dhoRX.js.map → tabbed-container-DI1GI1Qv.js.map} +1 -1
  491. package/dist/{tool-approval-1qiB4hhG.cjs → tool-approval-CJvPDL7D.cjs} +4 -4
  492. package/dist/{tool-approval-1qiB4hhG.cjs.map → tool-approval-CJvPDL7D.cjs.map} +1 -1
  493. package/dist/{tool-approval-B6MFcaKV.js → tool-approval-DyN11vFA.js} +4 -4
  494. package/dist/{tool-approval-B6MFcaKV.js.map → tool-approval-DyN11vFA.js.map} +1 -1
  495. package/dist/{tool-call-Bu66PkD-.cjs → tool-call-DBn14X-3.cjs} +9 -3
  496. package/dist/{tool-call-Bu66PkD-.cjs.map → tool-call-DBn14X-3.cjs.map} +1 -1
  497. package/dist/{tool-call-Ch9-jjXU.js → tool-call-Dsj43lvJ.js} +9 -3
  498. package/dist/{tool-call-Ch9-jjXU.js.map → tool-call-Dsj43lvJ.js.map} +1 -1
  499. package/dist/{tool-card-DrqPZfPQ.cjs → tool-card-rxhTDpk_.cjs} +164 -126
  500. package/dist/tool-card-rxhTDpk_.cjs.map +1 -0
  501. package/dist/{tool-card-sO6P2Qj4.js → tool-card-toDgoZzJ.js} +165 -127
  502. package/dist/tool-card-toDgoZzJ.js.map +1 -0
  503. package/dist/{tool-presentation-DvCsb_kz.js → tool-presentation-CvibOP1J.js} +6 -1
  504. package/dist/tool-presentation-CvibOP1J.js.map +1 -0
  505. package/dist/{tool-presentation-CQlDEwgS.cjs → tool-presentation-D6nzVruN.cjs} +6 -1
  506. package/dist/tool-presentation-D6nzVruN.cjs.map +1 -0
  507. package/oxlint/index.js +90 -0
  508. package/package.json +9 -9
  509. package/theme.css +4 -3
  510. package/dist/DataCodeSection-CcPmJPTp.cjs.map +0 -1
  511. package/dist/DataCodeSection-KJRyRD1Q.js.map +0 -1
  512. package/dist/FilterBar-BO-vvvyq.js.map +0 -1
  513. package/dist/FilterBar-Buw0tv51.cjs.map +0 -1
  514. package/dist/MarkdownRenderer-2GOXQJEv.js.map +0 -1
  515. package/dist/MarkdownRenderer-CB8Z_CHc.cjs.map +0 -1
  516. package/dist/MetricsTable-CRPeLHe1.js.map +0 -1
  517. package/dist/MetricsTable-D-aZf3dk.cjs.map +0 -1
  518. package/dist/ask-user-B225wzWc.js.map +0 -1
  519. package/dist/ask-user-DdYz56qH.cjs.map +0 -1
  520. package/dist/combobox-CMx2ayFN.cjs.map +0 -1
  521. package/dist/combobox-parts-C1CugUAU.js.map +0 -1
  522. package/dist/combobox-parts-ScKcYjMR.cjs.map +0 -1
  523. package/dist/domains/knowledge/lib/pageLayout.cjs.js +0 -49
  524. package/dist/domains/knowledge/lib/pageLayout.cjs.js.map +0 -1
  525. package/dist/domains/knowledge/lib/pageLayout.d.ts +0 -1
  526. package/dist/domains/knowledge/lib/pageLayout.es.js +0 -48
  527. package/dist/domains/knowledge/lib/pageLayout.es.js.map +0 -1
  528. package/dist/observability-saved-views-BAzxxoAr.cjs.map +0 -1
  529. package/dist/observability-saved-views-BBam8Fr5.js.map +0 -1
  530. package/dist/property-filter-applied-BCeRLcXb.cjs.map +0 -1
  531. package/dist/property-filter-applied-p3dTTDdb.js.map +0 -1
  532. package/dist/src/domains/knowledge/lib/pageLayout.d.ts +0 -24
  533. package/dist/tool-card-DrqPZfPQ.cjs.map +0 -1
  534. package/dist/tool-card-sO6P2Qj4.js.map +0 -1
  535. package/dist/tool-presentation-CQlDEwgS.cjs.map +0 -1
  536. package/dist/tool-presentation-DvCsb_kz.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MarkdownRenderer-y65WGBhC.cjs","names":["ARRIVING_CLASS","useCopyToClipboard","ButtonsGroup","Button","CheckIcon","CopyIcon","DropdownMenu","ChevronDownIcon","DownloadIcon","gfmToMarkdown","toMarkdown","useWatched","useState","useRef","memo","useMemo","cn","Markdown","CodeBlock","remarkGfm"],"sources":["../src/ds/components/MarkdownRenderer/arriving.ts","../src/ds/components/MarkdownRenderer/blocks.ts","../src/ds/components/MarkdownRenderer/table-csv.ts","../src/ds/components/MarkdownRenderer/markdown-table.tsx","../src/ds/components/MarkdownRenderer/table-markdown.ts","../src/ds/components/MarkdownRenderer/use-settled.ts","../src/ds/components/MarkdownRenderer/markdown-renderer.tsx"],"sourcesContent":["import type { ExtraProps } from 'react-markdown';\n\nimport { ARRIVING_CLASS } from '@/ds/tokens';\n\nimport '@/ds/components/Arrival/arrival.css';\n\ntype MarkdownElement = NonNullable<ExtraProps['node']>;\ntype MarkdownChild = MarkdownElement['children'][number];\n\n/** Fades whole: a fence renders through `CodeBlock`, and inline code carries a background. */\nconst UNBROKEN = new Set(['pre', 'code']);\n\nconst wrap = (value: string, arriving: boolean): MarkdownChild => ({\n type: 'element',\n tagName: 'span',\n properties: arriving ? { className: [ARRIVING_CLASS] } : {},\n children: [{ type: 'text', value }],\n});\n\nfunction markArriving(node: MarkdownElement): void {\n const classes = node.properties.className;\n\n node.properties.className = Array.isArray(classes) ? [...classes, ARRIVING_CLASS] : [ARRIVING_CLASS];\n}\n\nfunction rebuild(nodes: MarkdownChild[], arriving: () => boolean): MarkdownChild[] {\n const out: MarkdownChild[] = [];\n\n for (const node of nodes) {\n if (node.type === 'text') {\n for (const piece of node.value.match(/\\S+|\\s+/g) ?? []) {\n if (/\\S/.test(piece)) out.push(wrap(piece, arriving()));\n else out.push({ type: 'text', value: piece });\n }\n\n continue;\n }\n\n out.push(node);\n\n if (node.type !== 'element') continue;\n\n if (!UNBROKEN.has(node.tagName)) node.children = rebuild(node.children, arriving);\n else if (arriving()) markArriving(node);\n }\n\n return out;\n}\n\n/**\n * Gives every word of a block an element of its own, and the entrance class to\n * those past the first `settled` — the words that were not on screen yet when\n * the reader joined this reply.\n *\n * Every word, not just the arriving ones: react-markdown parses afresh on each\n * landing and React matches the children it already mounted by position, so a\n * wrapper that came and went would land where a bare text node used to be and\n * remount half the paragraph, replaying entrances that had long finished.\n * Wrapping the lot keeps every position fixed — a new word only ever appends —\n * and a word never gains the class it did not mount with, so nothing replays.\n */\nexport function rehypeArriving(settled: number) {\n return function attach() {\n return (tree: { children: MarkdownChild[] }) => {\n let word = 0;\n\n tree.children = rebuild(tree.children, () => word++ >= settled);\n };\n };\n}\n","const FENCE_OPEN = /^ {0,3}(`{3,}|~{3,})/;\nconst FENCE_CLOSE = /^ {0,3}(`{3,}|~{3,})[ \\t]*$/;\nconst LIST_ITEM = /^ {0,3}(?:[-*+]|\\d{1,9}[.)])(?:[ \\t]|$)/;\nconst INDENTED = /^(?:\\t| {2,})/;\nconst DEFINITION = /^ {0,3}\\[[^\\]]+\\]:/;\n\nfunction fenceOpenedBy(line: string): string | undefined {\n return FENCE_OPEN.exec(line)?.[1];\n}\n\n// Both are runs of one character, so `startsWith` is \"same marker, at least as long\".\nfunction closesFence(line: string, marker: string): boolean {\n return FENCE_CLOSE.exec(line)?.[1]?.startsWith(marker) ?? false;\n}\n\nfunction startsBlock(line: string, inList: boolean): boolean {\n if (INDENTED.test(line)) return false;\n\n return !(inList && LIST_ITEM.test(line));\n}\n\n/**\n * Cuts markdown into top-level blocks so a growing reply re-parses its last\n * block instead of all of them. Rejoining the result returns the input, and\n * every block renders as it would have inside the whole.\n *\n * Each rule only ever merges: over-merging costs a re-parse, while cutting a\n * construct in two changes what it renders as. Link reference and footnote\n * definitions resolve across blank lines, which no line-level rule can see, so\n * reaching one outside a fence abandons the split for the whole text.\n */\nexport function splitBlocks(markdown: string): string[] {\n const lines = markdown.split('\\n');\n const starts = [0];\n let fence: string | undefined;\n let started = false;\n let broken = false;\n let inList = false;\n\n for (const [index, line] of lines.entries()) {\n if (fence) {\n if (closesFence(line, fence)) fence = undefined;\n continue;\n }\n\n if (line.trim() === '') {\n broken = started;\n continue;\n }\n\n if (DEFINITION.test(line)) return [markdown];\n\n if (broken && startsBlock(line, inList)) {\n starts.push(index);\n started = false;\n }\n\n if (!started) inList = LIST_ITEM.test(line);\n\n started = true;\n broken = false;\n fence = fenceOpenedBy(line);\n }\n\n return starts.map((start, position) => {\n const end = starts[position + 1];\n const block = lines.slice(start, end ?? lines.length).join('\\n');\n\n return end === undefined ? block : `${block}\\n`;\n });\n}\n","function spreadsheetCell(value: string): string {\n // Quoting alone does not stop spreadsheet apps from evaluating formulas.\n const numeric = /^[+-]?(?:\\d+(?:\\.\\d*)?|\\.\\d+)(?:e[+-]?\\d+)?$/i.test(value.trim());\n const formula = /^[\\s\\uFEFF]*[=+\\-@=+-@]/u.test(value);\n const controlPrefix = /^[\\t\\r\\n]/.test(value);\n const safe = controlPrefix || (formula && !numeric) ? `'${value}` : value;\n return `\"${safe.replaceAll('\"', '\"\"')}\"`;\n}\n\nexport function tableToCsv(rows: string[][]): string {\n return rows.map(row => row.map(spreadsheetCell).join(',')).join('\\r\\n');\n}\n\nexport function downloadTableCsv(csv: string): void {\n const blob = new Blob(['\\uFEFF', csv], { type: 'text/csv;charset=utf-8' });\n const url = URL.createObjectURL(blob);\n const anchor = document.createElement('a');\n anchor.href = url;\n anchor.download = 'table.csv';\n document.body.appendChild(anchor);\n anchor.click();\n anchor.remove();\n URL.revokeObjectURL(url);\n}\n","import { CheckIcon, ChevronDownIcon, CopyIcon, DownloadIcon } from 'lucide-react';\nimport type { ComponentProps } from 'react';\nimport type { ExtraProps } from 'react-markdown';\nimport { downloadTableCsv } from './table-csv';\nimport { Button } from '@/ds/components/Button';\nimport { ButtonsGroup } from '@/ds/components/ButtonsGroup';\nimport { DropdownMenu } from '@/ds/components/DropdownMenu';\nimport { useCopyToClipboard } from '@/hooks/use-copy-to-clipboard';\n\nexport function MarkdownTable({ node, children }: ComponentProps<'table'> & ExtraProps) {\n const markdown = node?.properties.tableMarkdown;\n const csv = node?.properties.tableCsv;\n const { isCopied, copyToClipboard } = useCopyToClipboard({ copyMessage: 'Copied table markdown' });\n\n return (\n <div className=\"my-3 w-fit max-w-full min-w-0\">\n <div className=\"flex justify-end\">\n <ButtonsGroup size=\"sm\" aria-label=\"Table actions\">\n <Button\n type=\"button\"\n variant=\"ghost\"\n disabled={typeof markdown !== 'string'}\n onClick={() => {\n if (typeof markdown === 'string') copyToClipboard(markdown);\n }}\n aria-label=\"Copy table as markdown\"\n >\n {isCopied ? <CheckIcon /> : <CopyIcon />}\n {isCopied ? 'Copied!' : 'Copy table as markdown'}\n </Button>\n <DropdownMenu>\n <DropdownMenu.Trigger\n disabled={typeof csv !== 'string'}\n render={\n <Button type=\"button\" size=\"icon-sm\" variant=\"ghost\" aria-label=\"More table options\">\n <ChevronDownIcon />\n </Button>\n }\n />\n <DropdownMenu.Content align=\"end\" size=\"sm\" className=\"w-max min-w-0\">\n <DropdownMenu.Item\n size=\"sm\"\n onClick={() => {\n if (typeof csv === 'string') downloadTableCsv(csv);\n }}\n >\n <DownloadIcon />\n Download CSV\n </DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu>\n </ButtonsGroup>\n </div>\n <div className=\"max-w-full overflow-x-auto\">\n <table className=\"table min-w-full\">{children}</table>\n </div>\n </div>\n );\n}\n","import type { Definition, FootnoteDefinition, Nodes, Root, Table } from 'mdast';\nimport { gfmToMarkdown } from 'mdast-util-gfm';\nimport { toMarkdown } from 'mdast-util-to-markdown';\nimport { tableToCsv } from './table-csv';\n\nfunction cellText(node: Nodes): string {\n if (node.type === 'footnoteReference') return `[^${node.label ?? node.identifier}]`;\n if ('value' in node) return node.value;\n if (node.type === 'image' || node.type === 'imageReference') return node.alt ?? '';\n return 'children' in node ? node.children.map(cellText).join('') : '';\n}\n\nfunction walk(node: Nodes, visit: (node: Nodes) => void): void {\n visit(node);\n if ('children' in node) node.children.forEach(child => walk(child, visit));\n}\n\nconst SERIALIZE_OPTIONS = { extensions: [gfmToMarkdown()] };\n\n/** Capture table exports before rehype replaces text with animation spans. */\nexport function remarkTableMarkdown() {\n return (tree: Root, file: { value: unknown }) => {\n const source = String(file.value);\n const definitions = new Map<string, Definition | FootnoteDefinition>();\n const tables: Table[] = [];\n walk(tree, node => {\n if (node.type === 'definition' || node.type === 'footnoteDefinition') {\n const key = `${node.type}:${node.identifier}`;\n if (!definitions.has(key)) definitions.set(key, node);\n }\n if (node.type === 'table') tables.push(node);\n });\n\n const lines = source.split(/\\r\\n|\\r|\\n/);\n for (const table of tables) {\n const header = table.children[0];\n if (!header?.position) continue;\n const rows = table.children.map(row => {\n const start = row.position?.start.offset;\n const end = row.position?.end.offset;\n return start === undefined || end === undefined ? undefined : source.slice(start, end);\n });\n // Only offer exports when the parser supplied the original row locations.\n if (!rows.every(row => row !== undefined)) continue;\n // Row positions exclude list/blockquote prefixes. The delimiter has no AST node.\n const delimiter = lines[header.position.start.line]?.replace(/^[\\t >]*/, '');\n if (delimiter === undefined) continue;\n const markdown = [rows[0], delimiter, ...rows.slice(1)];\n const used = new Set<string>();\n const collectReference = (node: Nodes) => {\n if (node.type === 'linkReference' || node.type === 'imageReference') {\n used.add(`definition:${node.identifier}`);\n } else if (node.type === 'footnoteReference') {\n used.add(`footnoteDefinition:${node.identifier}`);\n }\n };\n walk(table, collectReference);\n // Visiting appended definitions also collects links/footnotes they depend on.\n // The set prevents duplicates and cycles, including self-referencing footnotes.\n for (const key of used) {\n const definition = definitions.get(key);\n if (!definition) continue;\n markdown.push('', toMarkdown(definition, SERIALIZE_OPTIONS).trimEnd());\n walk(definition, collectReference);\n }\n const cells = table.children.map(row =>\n Array.from({ length: header.children.length }, (_, index) => {\n const cell = row.children[index];\n return cell ? cellText(cell) : '';\n }),\n );\n table.data = {\n ...table.data,\n hProperties: {\n ...table.data?.hProperties,\n tableMarkdown: markdown.join('\\n'),\n tableCsv: tableToCsv(cells),\n },\n };\n }\n };\n}\n","import { useEffect, useRef, useState } from 'react';\n\nimport { useWatched } from '@/ds/components/Arrival';\nimport { ARRIVING_MS } from '@/ds/tokens';\n\ninterface Landing {\n words: number;\n at: number;\n}\n\n/**\n * How many of a reply's words have been on screen long enough that their entrance is over.\n *\n * The entrance plays on whatever mounts carrying the class, so it replays every time a\n * word's element is rebuilt — and markdown rebuilds a growing tail constantly: a `-`\n * turns a paragraph into a list item, a closing `**` splits it around a `<strong>`, the\n * stream ends and the mend comes off. Each of those swaps the element a settled word\n * lives in, which is what makes a word already read fade in again.\n *\n * Ageing them out is the whole answer: a word carries the class only while it is new,\n * so however often the tail is rebuilt, only what is genuinely arriving animates.\n *\n * What counts as new at mount is not this hook's call. A reply the reader was handed\n * is already there, and a block that mounts complete — a card's output, an expanded\n * body — enters with its container. Only a passage born streaming under the reader's\n * eyes is new from its first word: the reveal often lands several words in its first\n * commit, and they enter like every word after them.\n */\nexport function useSettledWords(words: number, streaming: boolean): number {\n const watched = useWatched();\n const [settled, setSettled] = useState(() => (watched && streaming ? 0 : words));\n const landings = useRef<Landing[]>([]);\n const recorded = useRef(settled);\n\n useEffect(() => {\n if (recorded.current !== words) {\n landings.current.push({ words, at: performance.now() });\n recorded.current = words;\n }\n\n const waiting = landings.current[0];\n if (!waiting) return;\n\n const timer = setTimeout(\n () => {\n landings.current.shift();\n setSettled(waiting.words);\n },\n Math.max(0, waiting.at + ARRIVING_MS - performance.now()),\n );\n\n return () => clearTimeout(timer);\n }, [settled, words]);\n\n // A shorter reply replacing the one on screen settles at once: nothing of it is new.\n return Math.min(settled, words);\n}\n","import { memo, useMemo } from 'react';\nimport type { MouseEvent, MouseEventHandler, ReactNode } from 'react';\nimport Markdown from 'react-markdown';\nimport type { Components, ExtraProps, Options } from 'react-markdown';\nimport remarkGfm from 'remark-gfm';\nimport remend from 'remend';\n\nimport { rehypeArriving } from './arriving';\nimport { splitBlocks } from './blocks';\nimport { MarkdownTable } from './markdown-table';\nimport { remarkTableMarkdown } from './table-markdown';\nimport { useSettledWords } from './use-settled';\nimport { CodeBlock } from '@/ds/components/CodeBlock';\nimport { cn } from '@/lib/utils';\n\nimport './markdown-renderer.css';\n\nexport type MarkdownExternalLinkTarget = 'tab' | 'window';\n\ntype RemarkPlugins = NonNullable<Options['remarkPlugins']>;\n\nexport interface MarkdownRendererProps {\n children: string;\n className?: string;\n externalLinkTarget?: MarkdownExternalLinkTarget;\n /** The text is a prefix of one still being written: close the markers the stream has not reached. */\n streaming?: boolean;\n /** Opt in to table copy/download controls; disabled while this text is streaming. */\n tableActions?: boolean;\n /** Remark plugins run after the built-in ones, e.g. to turn a syntax of the host's into elements. Keep it stable. */\n remarkPlugins?: RemarkPlugins;\n /** Element overrides merged over the built-in ones. Keep it stable: a new object re-renders every block. */\n components?: Components;\n}\n\n/**\n * Renders a markdown string. Agent output can carry attacker-influenced text\n * (file contents, tool output, web pages): react-markdown escapes raw HTML and\n * drops dangerous link schemes, so nothing here reaches the DOM as markup.\n *\n * react-markdown re-parses on every render, and a streaming reply re-renders\n * its whole transcript on every delta. Memoizing spares the settled messages;\n * rendering block by block — streaming or not — spares every block of the live\n * one but the last, and lets a reply settle without remounting what is already\n * on screen.\n *\n * The text is drawn as given: pacing a stream is `useRevealedText`, and belongs to\n * whoever owns the whole of what is being laid down — a reply is prose, tool rows\n * and cards, and they have to arrive in the order they were written. Only what\n * lands after the reader joined plays an entrance, and only while it is still new:\n * a reply opened part-written is already there, and fading in what someone is\n * halfway through reading would be both a lie and a screenful of animations at\n * once.\n */\nexport const MarkdownRenderer = memo(function MarkdownRenderer({\n children,\n className,\n externalLinkTarget = 'tab',\n streaming = false,\n tableActions = false,\n remarkPlugins: extraRemarkPlugins,\n components: extraComponents,\n}: MarkdownRendererProps) {\n const shown = decodeEscapedNewlines(children);\n const blocks = useMemo(() => splitBlocks(shown), [shown]);\n const last = blocks.length - 1;\n const baseComponents = (tableActions ? TABLE_COMPONENTS : DEFAULT_COMPONENTS)[externalLinkTarget];\n const components = useMemo(\n () => (extraComponents ? { ...baseComponents, ...extraComponents } : baseComponents),\n [baseComponents, extraComponents],\n );\n\n const spans = wordSpans(blocks);\n const settled = useSettledWords(spans.at(-1)?.end ?? 0, streaming);\n\n // A block whose words have all finished their entrance has nothing left to play,\n // which is what `undefined` says: leave it as plain text, no spans at all.\n const settledWords = (span: WordSpan | undefined): number | undefined =>\n !span || settled >= span.end ? undefined : Math.max(0, settled - span.start);\n\n const tail = blocks[last] ?? '';\n const mended = useMemo(() => (streaming ? remend(tail, REMEND_OPTIONS) : tail), [streaming, tail]);\n\n return (\n <div className={cn('mastra-markdown', className)}>\n {blocks.map((block, index) => (\n <MarkdownBlock\n key={index}\n content={index === last ? mended : block}\n settledWords={settledWords(spans[index])}\n components={components}\n streaming={streaming}\n tableActions={tableActions}\n extraRemarkPlugins={extraRemarkPlugins}\n />\n ))}\n </div>\n );\n});\n\n/** Keyed by position at the call site: a content key remounts on every character. */\nconst MarkdownBlock = memo(function MarkdownBlock({\n components,\n content,\n settledWords,\n streaming,\n tableActions,\n extraRemarkPlugins,\n}: {\n components: Components;\n content: string;\n settledWords?: number;\n streaming: boolean;\n tableActions: boolean;\n extraRemarkPlugins?: RemarkPlugins;\n}) {\n const remarkPlugins = useMemo(() => {\n const builtIn = tableActions && !streaming ? COPYABLE_REMARK_PLUGINS : REMARK_PLUGINS;\n return extraRemarkPlugins ? [...builtIn, ...extraRemarkPlugins] : builtIn;\n }, [tableActions, streaming, extraRemarkPlugins]);\n const rehypePlugins = useMemo(\n () => (settledWords === undefined ? SETTLED : [rehypeArriving(settledWords)]),\n [settledWords],\n );\n\n return (\n <Markdown remarkPlugins={remarkPlugins} rehypePlugins={rehypePlugins} components={components}>\n {content}\n </Markdown>\n );\n});\n\nconst SETTLED: Options['rehypePlugins'] = [];\n\ninterface WordSpan {\n start: number;\n end: number;\n}\n\n/**\n * Where each block's words fall in the reply's own count, so one settled count covers\n * them all. Counting the source counts its markers too, so the boundary only ever errs\n * towards leaving a word unanimated.\n */\nfunction wordSpans(blocks: string[]): WordSpan[] {\n let read = 0;\n\n return blocks.map(block => {\n const span = { start: read, end: read + countWords(block) };\n read = span.end;\n\n return span;\n });\n}\n\nfunction countWords(text: string): number {\n return text.match(/\\S+/g)?.length ?? 0;\n}\n\n// Agent networks emit their text with literal `\\n`. Only unescape when the text\n// has no real newline, otherwise a `\"a\\nb\"` inside a code fence gets shredded.\nfunction decodeEscapedNewlines(text: string): string {\n return text.includes('\\n') ? text : text.replace(/\\\\n/g, '\\n');\n}\n\ntype MarkdownNode = NonNullable<ExtraProps['node']>;\n\nfunction languageOf(node: MarkdownNode): string | undefined {\n const classNames = node.properties.className;\n if (!Array.isArray(classNames)) return undefined;\n\n const language = classNames.find(entry => typeof entry === 'string' && entry.startsWith('language-'));\n return typeof language === 'string' ? language.slice('language-'.length) : undefined;\n}\n\nfunction fencedCode(node: MarkdownNode | undefined): { code: string; language?: string } | undefined {\n const child = node?.children.find(entry => entry.type === 'element' && entry.tagName === 'code');\n if (child?.type !== 'element') return undefined;\n\n const code = child.children.map(entry => (entry.type === 'text' ? entry.value : '')).join('');\n return { code: code.replace(/\\n$/, ''), language: languageOf(child) };\n}\n\nfunction MarkdownCodeBlock({\n node,\n children,\n className,\n}: {\n node?: MarkdownNode;\n children?: ReactNode;\n className?: string;\n}) {\n const fenced = fencedCode(node);\n if (!fenced) return <pre className={className}>{children}</pre>;\n\n return (\n <CodeBlock\n code={fenced.code}\n lang={fenced.language}\n overflow=\"scroll\"\n className={cn('my-3 bg-sidebar', className)}\n copyMessage=\"Copied code to clipboard\"\n />\n );\n}\n\nconst POPUP_WINDOW_FEATURES = 'popup=yes,width=720,height=800,resizable=yes,scrollbars=yes';\n\nfunction isPlainLeftClick(event: MouseEvent): boolean {\n return event.button === 0 && !event.metaKey && !event.ctrlKey && !event.shiftKey && !event.altKey;\n}\n\nfunction markdownLink(externalLinkTarget: MarkdownExternalLinkTarget): NonNullable<Components['a']> {\n return function MarkdownLink({ href, title, children }) {\n const isExternal = /^https?:\\/\\//i.test(href ?? '');\n\n const openInPopup: MouseEventHandler<HTMLAnchorElement> = event => {\n if (!isExternal || externalLinkTarget !== 'window' || !isPlainLeftClick(event)) return;\n\n const popup = window.open(href, '_blank', POPUP_WINDOW_FEATURES);\n if (!popup) return;\n\n popup.opener = null;\n event.preventDefault();\n };\n\n return (\n <a\n href={href}\n title={title}\n onClick={openInPopup}\n target={isExternal ? '_blank' : undefined}\n rel={isExternal ? 'noopener noreferrer' : undefined}\n >\n {children}\n </a>\n );\n };\n}\n\nconst REMARK_PLUGINS = [remarkGfm];\nconst COPYABLE_REMARK_PLUGINS = [remarkGfm, remarkTableMarkdown];\n\n// Links stay text until their URL lands: remend's placeholder href would render\n// a live anchor to nowhere. No math is rendered here, so pairing `$$` would only\n// turn one literal into another.\nconst REMEND_OPTIONS = { katex: false, linkMode: 'text-only' } as const;\n\n// Elements are listed one by one: react-markdown also passes its `node`, which\n// React would forward to the DOM as a stray attribute. Everything else is\n// styled from markdown-renderer.css.\nconst COMPONENTS: Components = {\n pre: MarkdownCodeBlock,\n a: markdownLink('tab'),\n};\n\nconst WINDOW_COMPONENTS: Components = {\n ...COMPONENTS,\n a: markdownLink('window'),\n};\n\nconst DEFAULT_COMPONENTS = { tab: COMPONENTS, window: WINDOW_COMPONENTS };\nconst TABLE_COMPONENTS = {\n tab: { ...COMPONENTS, table: MarkdownTable },\n window: { ...WINDOW_COMPONENTS, table: MarkdownTable },\n};\n"],"mappings":"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"}
@@ -76,10 +76,17 @@ function MetricsTableHeaderLabel({ header, description, sorted, onSort }) {
76
76
  }
77
77
  // src/ds/components/MetricsTable/metrics-table-rows.tsx
78
78
  /**
79
+ * Full-width lines that fade over their last 6px. A hovered row covers the lines above and below
80
+ * it, which then fade over 24px so they read as part of the hover. Written out in full so Tailwind
81
+ * finds every class.
82
+ */
83
+ var ROW_LINE = "isolate before:absolute before:inset-x-0 before:-top-px before:bottom-0 before:-z-10 before:rounded hover:before:bg-fill-subtle after:absolute after:inset-x-0 after:bottom-0 after:h-px after:bg-border last:after:hidden after:[mask-image:linear-gradient(to_right,transparent,black_6px,black_calc(100%-6px),transparent)] hover:after:[mask-image:linear-gradient(to_right,transparent,black_24px,black_calc(100%-24px),transparent)] [&:has(+:hover)]:after:[mask-image:linear-gradient(to_right,transparent,black_24px,black_calc(100%-24px),transparent)]";
84
+ /**
79
85
  * Rows are 34.5px: 7px above 13px text (a 19.5px line) and 8px below, one more pixel for the
80
86
  * separator drawn in the row's last pixel, so text sits centered between the lines.
81
87
  */
82
- var ROW = require_utils.cn("relative col-span-full grid grid-cols-subgrid items-center px-3 pt-1.75 pb-2 text-body-sm", "isolate before:absolute before:inset-x-0 before:-top-px before:bottom-0 before:-z-10 before:rounded hover:before:bg-fill-subtle after:absolute after:inset-x-0 after:bottom-0 after:h-px after:bg-border last:after:hidden after:[mask-image:linear-gradient(to_right,transparent,black_6px,black_calc(100%-6px),transparent)] hover:after:[mask-image:linear-gradient(to_right,transparent,black_24px,black_calc(100%-24px),transparent)] [&:has(+:hover)]:after:[mask-image:linear-gradient(to_right,transparent,black_24px,black_calc(100%-24px),transparent)]");
88
+ var ROW_BOX = "pt-1.75 pb-2 text-body-sm";
89
+ var ROW = require_utils.cn("relative col-span-full grid grid-cols-subgrid items-center px-3", ROW_BOX, ROW_LINE);
83
90
  /** Skeleton widths for the first column's names, so loading rows don't look stamped. */
84
91
  var SKELETON_NAMES = [
85
92
  "w-32",
@@ -103,12 +110,24 @@ function skeletonBar(column, columnIndex, rowIndex) {
103
110
  return require_utils.cn("left-0", SKELETON_NAMES[rowIndex % SKELETON_NAMES.length]);
104
111
  }
105
112
  /** Skeleton rows while loading, the empty message without rows, else the page's rows. */
106
- function MetricsTableBody({ columns, rows, getRowKey, empty, skeletonRows, isLoading, ...behavior }) {
107
- if (isLoading) return Array.from({ length: skeletonRows }, (_, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MetricsTableSkeletonRow, {
113
+ function MetricsTableBody({ columns, rows, getRowKey, empty, pageSize, isLoading, ...behavior }) {
114
+ if (isLoading) return Array.from({ length: pageSize ?? 5 }, (_, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MetricsTableSkeletonRow, {
108
115
  columns,
109
116
  rowIndex: i
110
117
  }, i));
111
118
  if (rows.length === 0) {
119
+ if (pageSize) {
120
+ if (empty === void 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MetricsTableFiller, { count: pageSize });
121
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
122
+ role: "row",
123
+ className: "col-span-full grid *:col-start-1 *:row-start-1",
124
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MetricsTableFiller, { count: pageSize }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
125
+ role: "cell",
126
+ className: "flex items-center justify-center px-3 py-4 text-center text-body-sm text-muted-foreground",
127
+ children: empty
128
+ })]
129
+ });
130
+ }
112
131
  if (empty === void 0) return null;
113
132
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
114
133
  role: "row",
@@ -126,6 +145,22 @@ function MetricsTableBody({ columns, rows, getRowKey, empty, skeletonRows, isLoa
126
145
  ...behavior
127
146
  }, getRowKey(row)));
128
147
  }
148
+ /**
149
+ * Blank space as tall as `count` rows, so a paged table is a full page tall however many rows it
150
+ * shows. Rows of the same box, not a fixed height, so it follows the row's text size.
151
+ */
152
+ function MetricsTableFiller({ count }) {
153
+ if (count <= 0) return null;
154
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
155
+ "aria-hidden": true,
156
+ "data-slot": "metrics-table-filler",
157
+ className: "col-span-full",
158
+ children: Array.from({ length: count }, (_, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
159
+ className: ROW_BOX,
160
+ children: "​"
161
+ }, i))
162
+ });
163
+ }
129
164
  /** A loading row: the real row's markup with a bar in each cell, so it has the same height. */
130
165
  function MetricsTableSkeletonRow({ columns, rowIndex }) {
131
166
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
@@ -222,7 +257,7 @@ var columnWidth = (column) => column.width ?? (column.align === "end" ? "minmax(
222
257
  * A table for the numbers behind a chart: one row per series or group, columns for its figures,
223
258
  * separated by lines that fade at the ends. With `SeriesMark` and `Sparkline` cells and the row
224
259
  * hover and click hooks it doubles as the chart's legend; without them it's a plain data table.
225
- * With `pageSize` it pages long lists. For a share of a total, a compact `ShareBar` fits better.
260
+ * With `pageSize` it pages long lists, and is always a full page tall. For a share of a total, a compact `ShareBar` fits better.
226
261
  */
227
262
  function MetricsTable({ columns, rows, getRowKey, sort, defaultSort, onSortChange, onRowClick, onRowHover, isRowDimmed, isRowActive, rowTitle, empty, pageSize, isLoading = false, "aria-label": ariaLabel, className }) {
228
263
  const [ownSort, setOwnSort] = (0, react.useState)(defaultSort);
@@ -242,9 +277,9 @@ function MetricsTable({ columns, rows, getRowKey, sort, defaultSort, onSortChang
242
277
  };
243
278
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
244
279
  className: require_utils.cn("grid min-w-0 gap-3", className),
245
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_scroll_area.ScrollArea, {
280
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_scroll_area.ScrollArea, {
246
281
  orientation: "horizontal",
247
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
282
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
248
283
  role: "table",
249
284
  "aria-label": ariaLabel,
250
285
  className: "grid min-w-min gap-x-4",
@@ -276,10 +311,10 @@ function MetricsTable({ columns, rows, getRowKey, sort, defaultSort, onSortChang
276
311
  isRowActive,
277
312
  rowTitle,
278
313
  empty,
279
- skeletonRows: pageSize ?? 5,
314
+ pageSize,
280
315
  isLoading
281
316
  })]
282
- })
317
+ }), pageSize !== void 0 && !isLoading && shown.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MetricsTableFiller, { count: pageSize - shown.length })]
283
318
  }), showsPagination && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_table_pagination.TablePagination, {
284
319
  page: safePage,
285
320
  pageCount,
@@ -294,4 +329,4 @@ Object.defineProperty(exports, "MetricsTable", {
294
329
  }
295
330
  });
296
331
 
297
- //# sourceMappingURL=MetricsTable-D-aZf3dk.cjs.map
332
+ //# sourceMappingURL=MetricsTable-BSl81oNe.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MetricsTable-BSl81oNe.cjs","names":["ArrowUpIcon","ArrowDownIcon","cn","useId","Tooltip","TooltipTrigger","TooltipContent","cn","Skeleton","useState","cn","ScrollArea","TablePagination"],"sources":["../src/ds/components/MetricsTable/metrics-table-header.tsx","../src/ds/components/MetricsTable/metrics-table-rows.tsx","../src/ds/components/MetricsTable/metrics-table.tsx"],"sourcesContent":["import { ArrowDownIcon, ArrowUpIcon } from 'lucide-react';\nimport { useId } from 'react';\nimport type { ComponentProps, ReactNode } from 'react';\nimport type { MetricsTableSortDirection } from './metrics-table-types';\nimport { Tooltip, TooltipContent, TooltipTrigger } from '@/ds/components/Tooltip';\nimport { cn } from '@/lib/utils';\n\nconst SORT_ICON = { asc: ArrowUpIcon, desc: ArrowDownIcon };\n\nexport const FOCUS =\n 'focus-visible:outline-1 focus-visible:outline-solid focus-visible:outline-border-focus focus-visible:-outline-offset-1';\n\n/**\n * A faint dotted underline under the label: the header explains itself on hover or focus. It\n * brightens while the header is hovered or focused, so it hints without pulling the eye at rest.\n */\nconst EXPLAINED =\n 'cursor-help underline decoration-dotted decoration-placeholder/45 underline-offset-4 transition-[text-decoration-color] duration-150 group-hover/header:decoration-placeholder group-focus-visible/header:decoration-placeholder';\n\ntype HeaderTextProps = {\n header: string;\n /** Underlines the label: the header has a tooltip. */\n explained: boolean;\n};\n\n/** The header's label, as a sort button with the sorted direction's arrow. Takes a tooltip's trigger props. */\nfunction SortButton({\n header,\n explained,\n sorted,\n className,\n ...props\n}: HeaderTextProps & { sorted?: MetricsTableSortDirection } & ComponentProps<'button'>) {\n const SortIcon = sorted && SORT_ICON[sorted];\n return (\n <button\n type=\"button\"\n {...props}\n className={cn(\n 'group/header flex items-center gap-1 rounded whitespace-nowrap hover:text-muted-foreground',\n FOCUS,\n className,\n )}\n >\n <span className={cn(explained && EXPLAINED)}>{header}</span>\n {SortIcon && <SortIcon aria-hidden className=\"size-3\" />}\n </button>\n );\n}\n\n/** The header's label as text; focusable when it has a tooltip, so the keyboard reaches it. */\nfunction HeaderText({ header, explained, className, ...props }: HeaderTextProps & ComponentProps<'span'>) {\n return (\n <span\n tabIndex={explained ? 0 : undefined}\n {...props}\n className={cn('group/header rounded whitespace-nowrap', FOCUS, className)}\n >\n <span className={cn(explained && EXPLAINED)}>{header}</span>\n </span>\n );\n}\n\n/**\n * A column's header: a sort button when the column sorts, plain text otherwise. With a\n * `description`, the label itself shows it in a tooltip (no separate info icon), marked by a\n * dotted underline, and screen readers get it as the header's description.\n */\nexport function MetricsTableHeaderLabel({\n header,\n description,\n sorted,\n onSort,\n}: {\n header: string;\n description?: ReactNode;\n sorted?: MetricsTableSortDirection;\n /** Makes the header a sort button. */\n onSort?: () => void;\n}) {\n const descriptionId = useId();\n const explained = Boolean(description);\n const describedBy = explained ? descriptionId : undefined;\n const trigger = onSort ? (\n <SortButton header={header} explained={explained} sorted={sorted} onClick={onSort} aria-describedby={describedBy} />\n ) : (\n <HeaderText header={header} explained={explained} aria-describedby={describedBy} />\n );\n\n if (!explained) return trigger;\n return (\n <Tooltip>\n <TooltipTrigger render={trigger} />\n {/* Kept mounted (hidden) while closed, so screen readers always get the text. */}\n <TooltipContent id={descriptionId} keepMounted side=\"top\" className=\"max-w-72\">\n {description}\n </TooltipContent>\n </Tooltip>\n );\n}\n","import type { KeyboardEvent, MouseEvent } from 'react';\nimport { FOCUS } from './metrics-table-header';\nimport type { MetricsTableColumn, MetricsTableProps } from './metrics-table-types';\nimport { Skeleton } from '@/ds/components/Skeleton';\nimport { cn } from '@/lib/utils';\n\n/**\n * Full-width lines that fade over their last 6px. A hovered row covers the lines above and below\n * it, which then fade over 24px so they read as part of the hover. Written out in full so Tailwind\n * finds every class.\n */\nconst ROW_LINE =\n 'isolate before:absolute before:inset-x-0 before:-top-px before:bottom-0 before:-z-10 before:rounded hover:before:bg-fill-subtle after:absolute after:inset-x-0 after:bottom-0 after:h-px after:bg-border last:after:hidden after:[mask-image:linear-gradient(to_right,transparent,black_6px,black_calc(100%-6px),transparent)] hover:after:[mask-image:linear-gradient(to_right,transparent,black_24px,black_calc(100%-24px),transparent)] [&:has(+:hover)]:after:[mask-image:linear-gradient(to_right,transparent,black_24px,black_calc(100%-24px),transparent)]';\n\n/**\n * Rows are 34.5px: 7px above 13px text (a 19.5px line) and 8px below, one more pixel for the\n * separator drawn in the row's last pixel, so text sits centered between the lines.\n */\nconst ROW_BOX = 'pt-1.75 pb-2 text-body-sm';\n\nconst ROW = cn('relative col-span-full grid grid-cols-subgrid items-center px-3', ROW_BOX, ROW_LINE);\n\n/** Skeleton widths for the first column's names, so loading rows don't look stamped. */\nconst SKELETON_NAMES = ['w-32', 'w-24', 'w-36', 'w-20', 'w-28'];\n\n/** Controls a cell can hold; their own clicks and keys don't count as the row's. */\nconst CONTROLS = 'a, button, input, select, textarea, label, [role=\"button\"], [role=\"link\"], [contenteditable]';\n\n/** Whether an event started on a control inside the row rather than on the row itself. */\nfunction fromControl(event: MouseEvent | KeyboardEvent) {\n if (!(event.target instanceof Element)) return false;\n const control = event.target.closest(CONTROLS);\n return Boolean(control && event.currentTarget.contains(control));\n}\n\n/** Where a loading cell's bar sits and how wide it is: figures right, the name in varied widths. */\nfunction skeletonBar<Row>(column: MetricsTableColumn<Row>, columnIndex: number, rowIndex: number) {\n if (column.align === 'end') return 'right-0 w-10';\n if (columnIndex > 0) return 'left-0 w-16';\n return cn('left-0', SKELETON_NAMES[rowIndex % SKELETON_NAMES.length]);\n}\n\ntype RowBehavior<Row> = Pick<\n MetricsTableProps<Row>,\n 'onRowClick' | 'onRowHover' | 'isRowDimmed' | 'isRowActive' | 'rowTitle'\n>;\n\nexport type MetricsTableBodyProps<Row> = RowBehavior<Row> & {\n columns: MetricsTableColumn<Row>[];\n /** The rows on the current page, sorted. */\n rows: Row[];\n getRowKey: (row: Row) => string;\n empty: MetricsTableProps<Row>['empty'];\n /** A paged table's rows per page: drawn while loading, and kept as the empty table's height. */\n pageSize: number | undefined;\n isLoading: boolean;\n};\n\n/** Skeleton rows while loading, the empty message without rows, else the page's rows. */\nexport function MetricsTableBody<Row>({\n columns,\n rows,\n getRowKey,\n empty,\n pageSize,\n isLoading,\n ...behavior\n}: MetricsTableBodyProps<Row>) {\n if (isLoading) {\n return Array.from({ length: pageSize ?? 5 }, (_, i) => (\n <MetricsTableSkeletonRow key={i} columns={columns} rowIndex={i} />\n ));\n }\n if (rows.length === 0) {\n if (pageSize) {\n if (empty === undefined) return <MetricsTableFiller count={pageSize} />;\n // Empty, a paged table keeps at least a full page's height, with the message in its middle.\n // Both share one grid cell, so a message taller than the page still grows the row.\n return (\n <div role=\"row\" className=\"col-span-full grid *:col-start-1 *:row-start-1\">\n <MetricsTableFiller count={pageSize} />\n <p\n role=\"cell\"\n className=\"flex items-center justify-center px-3 py-4 text-center text-body-sm text-muted-foreground\"\n >\n {empty}\n </p>\n </div>\n );\n }\n if (empty === undefined) return null;\n return (\n <div role=\"row\" className=\"col-span-full\">\n <p role=\"cell\" className=\"py-8 text-center text-body-sm text-muted-foreground\">\n {empty}\n </p>\n </div>\n );\n }\n return rows.map(row => <MetricsTableRow key={getRowKey(row)} row={row} columns={columns} {...behavior} />);\n}\n\n/**\n * Blank space as tall as `count` rows, so a paged table is a full page tall however many rows it\n * shows. Rows of the same box, not a fixed height, so it follows the row's text size.\n */\nexport function MetricsTableFiller({ count }: { count: number }) {\n if (count <= 0) return null;\n return (\n <div aria-hidden data-slot=\"metrics-table-filler\" className=\"col-span-full\">\n {Array.from({ length: count }, (_, i) => (\n <div key={i} className={ROW_BOX}>\n {'\\u200b'}\n </div>\n ))}\n </div>\n );\n}\n\n/** A loading row: the real row's markup with a bar in each cell, so it has the same height. */\nfunction MetricsTableSkeletonRow<Row>({ columns, rowIndex }: { columns: MetricsTableColumn<Row>[]; rowIndex: number }) {\n return (\n <div role=\"row\" aria-busy className={ROW}>\n {columns.map((column, columnIndex) => (\n <div\n key={column.id}\n role=\"cell\"\n className={cn('relative flex min-w-0', column.align === 'end' && 'justify-end')}\n >\n {/* A zero-width space gives the cell a real line box, so loading rows match loaded ones. */}\n {'​'}\n <Skeleton\n className={cn('absolute top-1/2 h-3.5 -translate-y-1/2', skeletonBar(column, columnIndex, rowIndex))}\n />\n </div>\n ))}\n </div>\n );\n}\n\n/** One row: its cells, and with `onRowClick` a focusable row that Enter and Space also click. */\nfunction MetricsTableRow<Row>({\n row,\n columns,\n onRowClick,\n onRowHover,\n isRowDimmed,\n isRowActive,\n rowTitle,\n}: RowBehavior<Row> & { row: Row; columns: MetricsTableColumn<Row>[] }) {\n const active = isRowActive?.(row) ?? false;\n const dimmed = isRowDimmed?.(row) ?? false;\n\n const handleClick = (event: MouseEvent) => {\n if (!fromControl(event)) onRowClick?.(row);\n };\n const handleKeyDown = (event: KeyboardEvent) => {\n // Only while the row itself has focus, so a cell's link or input keeps its keys.\n if (event.target !== event.currentTarget) return;\n if (event.key !== 'Enter' && event.key !== ' ') return;\n // Space would also scroll the page.\n event.preventDefault();\n onRowClick?.(row);\n };\n\n return (\n <div\n role=\"row\"\n aria-current={active || undefined}\n tabIndex={onRowClick ? 0 : undefined}\n title={rowTitle?.(row)}\n onClick={onRowClick ? handleClick : undefined}\n onKeyDown={onRowClick ? handleKeyDown : undefined}\n onMouseEnter={onRowHover ? () => onRowHover(row) : undefined}\n onMouseLeave={onRowHover ? () => onRowHover(undefined) : undefined}\n className={cn(\n ROW,\n 'rounded text-foreground transition-opacity duration-150',\n onRowClick && cn('cursor-pointer', FOCUS),\n active && 'before:bg-fill-subtle',\n dimmed && 'opacity-40',\n )}\n >\n {columns.map(column => (\n <div\n key={column.id}\n role=\"cell\"\n className={cn('flex min-w-0 items-center', column.align === 'end' && 'justify-end text-right')}\n >\n {column.cell(row)}\n </div>\n ))}\n </div>\n );\n}\n","import { useState } from 'react';\nimport { MetricsTableHeaderLabel } from './metrics-table-header';\nimport { MetricsTableBody, MetricsTableFiller } from './metrics-table-rows';\nimport type { MetricsTableColumn, MetricsTableProps, MetricsTableSort } from './metrics-table-types';\nimport { ScrollArea } from '@/ds/components/ScrollArea/scroll-area';\nimport { TablePagination } from '@/ds/components/Table/table-pagination';\nimport { cn } from '@/lib/utils';\n\n/**\n * A full-width line that fades over its last 6px; over 24px when the first row is hovered, so it\n * reads as part of the hover. Written out in full so Tailwind finds every class.\n */\nconst HEADER_LINE =\n 'after:absolute after:inset-x-0 after:bottom-0 after:h-px after:bg-border after:[mask-image:linear-gradient(to_right,transparent,black_6px,black_calc(100%-6px),transparent)] [&:has(+:hover)]:after:[mask-image:linear-gradient(to_right,transparent,black_24px,black_calc(100%-24px),transparent)]';\n\nconst ARIA_SORT = { asc: 'ascending', desc: 'descending' } as const;\n\n/**\n * Clicks on a column cycle its first direction, the other one, then off: off goes back to the\n * table's default order. Another column starts at its own first direction.\n */\nfunction nextSort<Row>(\n current: MetricsTableSort | undefined,\n column: MetricsTableColumn<Row>,\n): MetricsTableSort | undefined {\n const first = column.firstDirection ?? 'desc';\n if (current?.column !== column.id) return { column: column.id, direction: first };\n if (current.direction !== first) return undefined;\n return { column: column.id, direction: first === 'desc' ? 'asc' : 'desc' };\n}\n\n/** Ascending order of two present sort values. */\nfunction compareAscending(x: number | string, y: number | string) {\n if (typeof x === 'number' && typeof y === 'number') return x - y;\n return String(x).localeCompare(String(y));\n}\n\nfunction sortRows<Row>(rows: Row[], columns: MetricsTableColumn<Row>[], sort: MetricsTableSort | undefined) {\n const by = columns.find(c => c.id === sort?.column)?.sortValue;\n if (!sort || !by) return rows;\n const sign = sort.direction === 'desc' ? -1 : 1;\n // A row without a value goes last whichever way the column sorts.\n return rows.toSorted((a, b) => {\n const x = by(a);\n const y = by(b);\n if (x === undefined && y === undefined) return 0;\n if (x === undefined) return 1;\n if (y === undefined) return -1;\n return sign * compareAscending(x, y);\n });\n}\n\n/**\n * A column's grid track. Figures take a share of the spare width, like an HTML table's auto\n * layout: never narrower than their values, wider when the card has room.\n */\nconst columnWidth = <Row,>(column: MetricsTableColumn<Row>) =>\n column.width ?? (column.align === 'end' ? 'minmax(max-content,1fr)' : 'max-content');\n\n/**\n * A table for the numbers behind a chart: one row per series or group, columns for its figures,\n * separated by lines that fade at the ends. With `SeriesMark` and `Sparkline` cells and the row\n * hover and click hooks it doubles as the chart's legend; without them it's a plain data table.\n * With `pageSize` it pages long lists, and is always a full page tall. For a share of a total, a compact `ShareBar` fits better.\n */\nexport function MetricsTable<Row>({\n columns,\n rows,\n getRowKey,\n sort,\n defaultSort,\n onSortChange,\n onRowClick,\n onRowHover,\n isRowDimmed,\n isRowActive,\n rowTitle,\n empty,\n pageSize,\n isLoading = false,\n 'aria-label': ariaLabel,\n className,\n}: MetricsTableProps<Row>) {\n const [ownSort, setOwnSort] = useState(defaultSort);\n const [page, setPage] = useState(0);\n const current = sort ?? ownSort;\n const sorted = sortRows(rows, columns, current);\n const pageCount = pageSize ? Math.ceil(sorted.length / pageSize) : 1;\n // Fewer rows than before (a narrower filter) keeps the last page rather than an empty one.\n const safePage = Math.min(page, Math.max(0, pageCount - 1));\n const shown = pageSize ? sorted.slice(safePage * pageSize, (safePage + 1) * pageSize) : sorted;\n const template = { gridTemplateColumns: columns.map(columnWidth).join(' ') };\n const showsPagination = !isLoading && pageCount > 1;\n\n const sortBy = (column: MetricsTableColumn<Row>) => {\n const next = nextSort(current, column) ?? defaultSort;\n setOwnSort(next);\n setPage(0);\n onSortChange?.(next);\n };\n\n return (\n <div className={cn('grid min-w-0 gap-3', className)}>\n {/* Narrower than its content (a phone), the table scrolls sideways instead of squeezing columns or the page. */}\n <ScrollArea orientation=\"horizontal\">\n {/* One set of column tracks for the header and every row (each row is a subgrid), so a column's\n width follows its widest cell in the whole table and headers sit over their cells. */}\n <div\n role=\"table\"\n aria-label={ariaLabel}\n // min-content, not max-content: a long name would otherwise grow every `fr` column with it.\n className=\"grid min-w-min gap-x-4\"\n style={template}\n >\n <div\n role=\"row\"\n className={cn(\n 'relative col-span-full grid grid-cols-subgrid items-end px-3 pb-1.5 text-body-sm font-medium text-placeholder',\n HEADER_LINE,\n )}\n >\n {columns.map(column => {\n const direction = current?.column === column.id ? current.direction : undefined;\n return (\n <div\n key={column.id}\n role=\"columnheader\"\n aria-sort={direction && ARIA_SORT[direction]}\n className={cn('flex min-w-0 items-center gap-1', column.align === 'end' && 'justify-end text-right')}\n >\n <MetricsTableHeaderLabel\n header={column.header}\n description={column.description}\n sorted={direction}\n onSort={column.sortValue ? () => sortBy(column) : undefined}\n />\n </div>\n );\n })}\n </div>\n <MetricsTableBody\n columns={columns}\n rows={shown}\n getRowKey={getRowKey}\n onRowClick={onRowClick}\n onRowHover={onRowHover}\n isRowDimmed={isRowDimmed}\n isRowActive={isRowActive}\n rowTitle={rowTitle}\n empty={empty}\n pageSize={pageSize}\n isLoading={isLoading}\n />\n </div>\n {/* Always a full page tall, so loading, paging and switching data don't move what's below. */}\n {pageSize !== undefined && !isLoading && shown.length > 0 && (\n <MetricsTableFiller count={pageSize - shown.length} />\n )}\n </ScrollArea>\n {showsPagination && <TablePagination page={safePage} pageCount={pageCount} onPageChange={setPage} />}\n </div>\n );\n}\n"],"mappings":"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"}
@@ -76,10 +76,17 @@ function MetricsTableHeaderLabel({ header, description, sorted, onSort }) {
76
76
  }
77
77
  // src/ds/components/MetricsTable/metrics-table-rows.tsx
78
78
  /**
79
+ * Full-width lines that fade over their last 6px. A hovered row covers the lines above and below
80
+ * it, which then fade over 24px so they read as part of the hover. Written out in full so Tailwind
81
+ * finds every class.
82
+ */
83
+ var ROW_LINE = "isolate before:absolute before:inset-x-0 before:-top-px before:bottom-0 before:-z-10 before:rounded hover:before:bg-fill-subtle after:absolute after:inset-x-0 after:bottom-0 after:h-px after:bg-border last:after:hidden after:[mask-image:linear-gradient(to_right,transparent,black_6px,black_calc(100%-6px),transparent)] hover:after:[mask-image:linear-gradient(to_right,transparent,black_24px,black_calc(100%-24px),transparent)] [&:has(+:hover)]:after:[mask-image:linear-gradient(to_right,transparent,black_24px,black_calc(100%-24px),transparent)]";
84
+ /**
79
85
  * Rows are 34.5px: 7px above 13px text (a 19.5px line) and 8px below, one more pixel for the
80
86
  * separator drawn in the row's last pixel, so text sits centered between the lines.
81
87
  */
82
- var ROW = cn("relative col-span-full grid grid-cols-subgrid items-center px-3 pt-1.75 pb-2 text-body-sm", "isolate before:absolute before:inset-x-0 before:-top-px before:bottom-0 before:-z-10 before:rounded hover:before:bg-fill-subtle after:absolute after:inset-x-0 after:bottom-0 after:h-px after:bg-border last:after:hidden after:[mask-image:linear-gradient(to_right,transparent,black_6px,black_calc(100%-6px),transparent)] hover:after:[mask-image:linear-gradient(to_right,transparent,black_24px,black_calc(100%-24px),transparent)] [&:has(+:hover)]:after:[mask-image:linear-gradient(to_right,transparent,black_24px,black_calc(100%-24px),transparent)]");
88
+ var ROW_BOX = "pt-1.75 pb-2 text-body-sm";
89
+ var ROW = cn("relative col-span-full grid grid-cols-subgrid items-center px-3", ROW_BOX, ROW_LINE);
83
90
  /** Skeleton widths for the first column's names, so loading rows don't look stamped. */
84
91
  var SKELETON_NAMES = [
85
92
  "w-32",
@@ -103,12 +110,24 @@ function skeletonBar(column, columnIndex, rowIndex) {
103
110
  return cn("left-0", SKELETON_NAMES[rowIndex % SKELETON_NAMES.length]);
104
111
  }
105
112
  /** Skeleton rows while loading, the empty message without rows, else the page's rows. */
106
- function MetricsTableBody({ columns, rows, getRowKey, empty, skeletonRows, isLoading, ...behavior }) {
107
- if (isLoading) return Array.from({ length: skeletonRows }, (_, i) => /* @__PURE__ */ jsx(MetricsTableSkeletonRow, {
113
+ function MetricsTableBody({ columns, rows, getRowKey, empty, pageSize, isLoading, ...behavior }) {
114
+ if (isLoading) return Array.from({ length: pageSize ?? 5 }, (_, i) => /* @__PURE__ */ jsx(MetricsTableSkeletonRow, {
108
115
  columns,
109
116
  rowIndex: i
110
117
  }, i));
111
118
  if (rows.length === 0) {
119
+ if (pageSize) {
120
+ if (empty === void 0) return /* @__PURE__ */ jsx(MetricsTableFiller, { count: pageSize });
121
+ return /* @__PURE__ */ jsxs("div", {
122
+ role: "row",
123
+ className: "col-span-full grid *:col-start-1 *:row-start-1",
124
+ children: [/* @__PURE__ */ jsx(MetricsTableFiller, { count: pageSize }), /* @__PURE__ */ jsx("p", {
125
+ role: "cell",
126
+ className: "flex items-center justify-center px-3 py-4 text-center text-body-sm text-muted-foreground",
127
+ children: empty
128
+ })]
129
+ });
130
+ }
112
131
  if (empty === void 0) return null;
113
132
  return /* @__PURE__ */ jsx("div", {
114
133
  role: "row",
@@ -126,6 +145,22 @@ function MetricsTableBody({ columns, rows, getRowKey, empty, skeletonRows, isLoa
126
145
  ...behavior
127
146
  }, getRowKey(row)));
128
147
  }
148
+ /**
149
+ * Blank space as tall as `count` rows, so a paged table is a full page tall however many rows it
150
+ * shows. Rows of the same box, not a fixed height, so it follows the row's text size.
151
+ */
152
+ function MetricsTableFiller({ count }) {
153
+ if (count <= 0) return null;
154
+ return /* @__PURE__ */ jsx("div", {
155
+ "aria-hidden": true,
156
+ "data-slot": "metrics-table-filler",
157
+ className: "col-span-full",
158
+ children: Array.from({ length: count }, (_, i) => /* @__PURE__ */ jsx("div", {
159
+ className: ROW_BOX,
160
+ children: "​"
161
+ }, i))
162
+ });
163
+ }
129
164
  /** A loading row: the real row's markup with a bar in each cell, so it has the same height. */
130
165
  function MetricsTableSkeletonRow({ columns, rowIndex }) {
131
166
  return /* @__PURE__ */ jsx("div", {
@@ -222,7 +257,7 @@ var columnWidth = (column) => column.width ?? (column.align === "end" ? "minmax(
222
257
  * A table for the numbers behind a chart: one row per series or group, columns for its figures,
223
258
  * separated by lines that fade at the ends. With `SeriesMark` and `Sparkline` cells and the row
224
259
  * hover and click hooks it doubles as the chart's legend; without them it's a plain data table.
225
- * With `pageSize` it pages long lists. For a share of a total, a compact `ShareBar` fits better.
260
+ * With `pageSize` it pages long lists, and is always a full page tall. For a share of a total, a compact `ShareBar` fits better.
226
261
  */
227
262
  function MetricsTable({ columns, rows, getRowKey, sort, defaultSort, onSortChange, onRowClick, onRowHover, isRowDimmed, isRowActive, rowTitle, empty, pageSize, isLoading = false, "aria-label": ariaLabel, className }) {
228
263
  const [ownSort, setOwnSort] = useState(defaultSort);
@@ -242,9 +277,9 @@ function MetricsTable({ columns, rows, getRowKey, sort, defaultSort, onSortChang
242
277
  };
243
278
  return /* @__PURE__ */ jsxs("div", {
244
279
  className: cn("grid min-w-0 gap-3", className),
245
- children: [/* @__PURE__ */ jsx(ScrollArea, {
280
+ children: [/* @__PURE__ */ jsxs(ScrollArea, {
246
281
  orientation: "horizontal",
247
- children: /* @__PURE__ */ jsxs("div", {
282
+ children: [/* @__PURE__ */ jsxs("div", {
248
283
  role: "table",
249
284
  "aria-label": ariaLabel,
250
285
  className: "grid min-w-min gap-x-4",
@@ -276,10 +311,10 @@ function MetricsTable({ columns, rows, getRowKey, sort, defaultSort, onSortChang
276
311
  isRowActive,
277
312
  rowTitle,
278
313
  empty,
279
- skeletonRows: pageSize ?? 5,
314
+ pageSize,
280
315
  isLoading
281
316
  })]
282
- })
317
+ }), pageSize !== void 0 && !isLoading && shown.length > 0 && /* @__PURE__ */ jsx(MetricsTableFiller, { count: pageSize - shown.length })]
283
318
  }), showsPagination && /* @__PURE__ */ jsx(TablePagination, {
284
319
  page: safePage,
285
320
  pageCount,
@@ -289,4 +324,4 @@ function MetricsTable({ columns, rows, getRowKey, sort, defaultSort, onSortChang
289
324
  }
290
325
  export { MetricsTable as t };
291
326
 
292
- //# sourceMappingURL=MetricsTable-CRPeLHe1.js.map
327
+ //# sourceMappingURL=MetricsTable-DID6LRoP.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MetricsTable-DID6LRoP.js","names":[],"sources":["../src/ds/components/MetricsTable/metrics-table-header.tsx","../src/ds/components/MetricsTable/metrics-table-rows.tsx","../src/ds/components/MetricsTable/metrics-table.tsx"],"sourcesContent":["import { ArrowDownIcon, ArrowUpIcon } from 'lucide-react';\nimport { useId } from 'react';\nimport type { ComponentProps, ReactNode } from 'react';\nimport type { MetricsTableSortDirection } from './metrics-table-types';\nimport { Tooltip, TooltipContent, TooltipTrigger } from '@/ds/components/Tooltip';\nimport { cn } from '@/lib/utils';\n\nconst SORT_ICON = { asc: ArrowUpIcon, desc: ArrowDownIcon };\n\nexport const FOCUS =\n 'focus-visible:outline-1 focus-visible:outline-solid focus-visible:outline-border-focus focus-visible:-outline-offset-1';\n\n/**\n * A faint dotted underline under the label: the header explains itself on hover or focus. It\n * brightens while the header is hovered or focused, so it hints without pulling the eye at rest.\n */\nconst EXPLAINED =\n 'cursor-help underline decoration-dotted decoration-placeholder/45 underline-offset-4 transition-[text-decoration-color] duration-150 group-hover/header:decoration-placeholder group-focus-visible/header:decoration-placeholder';\n\ntype HeaderTextProps = {\n header: string;\n /** Underlines the label: the header has a tooltip. */\n explained: boolean;\n};\n\n/** The header's label, as a sort button with the sorted direction's arrow. Takes a tooltip's trigger props. */\nfunction SortButton({\n header,\n explained,\n sorted,\n className,\n ...props\n}: HeaderTextProps & { sorted?: MetricsTableSortDirection } & ComponentProps<'button'>) {\n const SortIcon = sorted && SORT_ICON[sorted];\n return (\n <button\n type=\"button\"\n {...props}\n className={cn(\n 'group/header flex items-center gap-1 rounded whitespace-nowrap hover:text-muted-foreground',\n FOCUS,\n className,\n )}\n >\n <span className={cn(explained && EXPLAINED)}>{header}</span>\n {SortIcon && <SortIcon aria-hidden className=\"size-3\" />}\n </button>\n );\n}\n\n/** The header's label as text; focusable when it has a tooltip, so the keyboard reaches it. */\nfunction HeaderText({ header, explained, className, ...props }: HeaderTextProps & ComponentProps<'span'>) {\n return (\n <span\n tabIndex={explained ? 0 : undefined}\n {...props}\n className={cn('group/header rounded whitespace-nowrap', FOCUS, className)}\n >\n <span className={cn(explained && EXPLAINED)}>{header}</span>\n </span>\n );\n}\n\n/**\n * A column's header: a sort button when the column sorts, plain text otherwise. With a\n * `description`, the label itself shows it in a tooltip (no separate info icon), marked by a\n * dotted underline, and screen readers get it as the header's description.\n */\nexport function MetricsTableHeaderLabel({\n header,\n description,\n sorted,\n onSort,\n}: {\n header: string;\n description?: ReactNode;\n sorted?: MetricsTableSortDirection;\n /** Makes the header a sort button. */\n onSort?: () => void;\n}) {\n const descriptionId = useId();\n const explained = Boolean(description);\n const describedBy = explained ? descriptionId : undefined;\n const trigger = onSort ? (\n <SortButton header={header} explained={explained} sorted={sorted} onClick={onSort} aria-describedby={describedBy} />\n ) : (\n <HeaderText header={header} explained={explained} aria-describedby={describedBy} />\n );\n\n if (!explained) return trigger;\n return (\n <Tooltip>\n <TooltipTrigger render={trigger} />\n {/* Kept mounted (hidden) while closed, so screen readers always get the text. */}\n <TooltipContent id={descriptionId} keepMounted side=\"top\" className=\"max-w-72\">\n {description}\n </TooltipContent>\n </Tooltip>\n );\n}\n","import type { KeyboardEvent, MouseEvent } from 'react';\nimport { FOCUS } from './metrics-table-header';\nimport type { MetricsTableColumn, MetricsTableProps } from './metrics-table-types';\nimport { Skeleton } from '@/ds/components/Skeleton';\nimport { cn } from '@/lib/utils';\n\n/**\n * Full-width lines that fade over their last 6px. A hovered row covers the lines above and below\n * it, which then fade over 24px so they read as part of the hover. Written out in full so Tailwind\n * finds every class.\n */\nconst ROW_LINE =\n 'isolate before:absolute before:inset-x-0 before:-top-px before:bottom-0 before:-z-10 before:rounded hover:before:bg-fill-subtle after:absolute after:inset-x-0 after:bottom-0 after:h-px after:bg-border last:after:hidden after:[mask-image:linear-gradient(to_right,transparent,black_6px,black_calc(100%-6px),transparent)] hover:after:[mask-image:linear-gradient(to_right,transparent,black_24px,black_calc(100%-24px),transparent)] [&:has(+:hover)]:after:[mask-image:linear-gradient(to_right,transparent,black_24px,black_calc(100%-24px),transparent)]';\n\n/**\n * Rows are 34.5px: 7px above 13px text (a 19.5px line) and 8px below, one more pixel for the\n * separator drawn in the row's last pixel, so text sits centered between the lines.\n */\nconst ROW_BOX = 'pt-1.75 pb-2 text-body-sm';\n\nconst ROW = cn('relative col-span-full grid grid-cols-subgrid items-center px-3', ROW_BOX, ROW_LINE);\n\n/** Skeleton widths for the first column's names, so loading rows don't look stamped. */\nconst SKELETON_NAMES = ['w-32', 'w-24', 'w-36', 'w-20', 'w-28'];\n\n/** Controls a cell can hold; their own clicks and keys don't count as the row's. */\nconst CONTROLS = 'a, button, input, select, textarea, label, [role=\"button\"], [role=\"link\"], [contenteditable]';\n\n/** Whether an event started on a control inside the row rather than on the row itself. */\nfunction fromControl(event: MouseEvent | KeyboardEvent) {\n if (!(event.target instanceof Element)) return false;\n const control = event.target.closest(CONTROLS);\n return Boolean(control && event.currentTarget.contains(control));\n}\n\n/** Where a loading cell's bar sits and how wide it is: figures right, the name in varied widths. */\nfunction skeletonBar<Row>(column: MetricsTableColumn<Row>, columnIndex: number, rowIndex: number) {\n if (column.align === 'end') return 'right-0 w-10';\n if (columnIndex > 0) return 'left-0 w-16';\n return cn('left-0', SKELETON_NAMES[rowIndex % SKELETON_NAMES.length]);\n}\n\ntype RowBehavior<Row> = Pick<\n MetricsTableProps<Row>,\n 'onRowClick' | 'onRowHover' | 'isRowDimmed' | 'isRowActive' | 'rowTitle'\n>;\n\nexport type MetricsTableBodyProps<Row> = RowBehavior<Row> & {\n columns: MetricsTableColumn<Row>[];\n /** The rows on the current page, sorted. */\n rows: Row[];\n getRowKey: (row: Row) => string;\n empty: MetricsTableProps<Row>['empty'];\n /** A paged table's rows per page: drawn while loading, and kept as the empty table's height. */\n pageSize: number | undefined;\n isLoading: boolean;\n};\n\n/** Skeleton rows while loading, the empty message without rows, else the page's rows. */\nexport function MetricsTableBody<Row>({\n columns,\n rows,\n getRowKey,\n empty,\n pageSize,\n isLoading,\n ...behavior\n}: MetricsTableBodyProps<Row>) {\n if (isLoading) {\n return Array.from({ length: pageSize ?? 5 }, (_, i) => (\n <MetricsTableSkeletonRow key={i} columns={columns} rowIndex={i} />\n ));\n }\n if (rows.length === 0) {\n if (pageSize) {\n if (empty === undefined) return <MetricsTableFiller count={pageSize} />;\n // Empty, a paged table keeps at least a full page's height, with the message in its middle.\n // Both share one grid cell, so a message taller than the page still grows the row.\n return (\n <div role=\"row\" className=\"col-span-full grid *:col-start-1 *:row-start-1\">\n <MetricsTableFiller count={pageSize} />\n <p\n role=\"cell\"\n className=\"flex items-center justify-center px-3 py-4 text-center text-body-sm text-muted-foreground\"\n >\n {empty}\n </p>\n </div>\n );\n }\n if (empty === undefined) return null;\n return (\n <div role=\"row\" className=\"col-span-full\">\n <p role=\"cell\" className=\"py-8 text-center text-body-sm text-muted-foreground\">\n {empty}\n </p>\n </div>\n );\n }\n return rows.map(row => <MetricsTableRow key={getRowKey(row)} row={row} columns={columns} {...behavior} />);\n}\n\n/**\n * Blank space as tall as `count` rows, so a paged table is a full page tall however many rows it\n * shows. Rows of the same box, not a fixed height, so it follows the row's text size.\n */\nexport function MetricsTableFiller({ count }: { count: number }) {\n if (count <= 0) return null;\n return (\n <div aria-hidden data-slot=\"metrics-table-filler\" className=\"col-span-full\">\n {Array.from({ length: count }, (_, i) => (\n <div key={i} className={ROW_BOX}>\n {'\\u200b'}\n </div>\n ))}\n </div>\n );\n}\n\n/** A loading row: the real row's markup with a bar in each cell, so it has the same height. */\nfunction MetricsTableSkeletonRow<Row>({ columns, rowIndex }: { columns: MetricsTableColumn<Row>[]; rowIndex: number }) {\n return (\n <div role=\"row\" aria-busy className={ROW}>\n {columns.map((column, columnIndex) => (\n <div\n key={column.id}\n role=\"cell\"\n className={cn('relative flex min-w-0', column.align === 'end' && 'justify-end')}\n >\n {/* A zero-width space gives the cell a real line box, so loading rows match loaded ones. */}\n {'​'}\n <Skeleton\n className={cn('absolute top-1/2 h-3.5 -translate-y-1/2', skeletonBar(column, columnIndex, rowIndex))}\n />\n </div>\n ))}\n </div>\n );\n}\n\n/** One row: its cells, and with `onRowClick` a focusable row that Enter and Space also click. */\nfunction MetricsTableRow<Row>({\n row,\n columns,\n onRowClick,\n onRowHover,\n isRowDimmed,\n isRowActive,\n rowTitle,\n}: RowBehavior<Row> & { row: Row; columns: MetricsTableColumn<Row>[] }) {\n const active = isRowActive?.(row) ?? false;\n const dimmed = isRowDimmed?.(row) ?? false;\n\n const handleClick = (event: MouseEvent) => {\n if (!fromControl(event)) onRowClick?.(row);\n };\n const handleKeyDown = (event: KeyboardEvent) => {\n // Only while the row itself has focus, so a cell's link or input keeps its keys.\n if (event.target !== event.currentTarget) return;\n if (event.key !== 'Enter' && event.key !== ' ') return;\n // Space would also scroll the page.\n event.preventDefault();\n onRowClick?.(row);\n };\n\n return (\n <div\n role=\"row\"\n aria-current={active || undefined}\n tabIndex={onRowClick ? 0 : undefined}\n title={rowTitle?.(row)}\n onClick={onRowClick ? handleClick : undefined}\n onKeyDown={onRowClick ? handleKeyDown : undefined}\n onMouseEnter={onRowHover ? () => onRowHover(row) : undefined}\n onMouseLeave={onRowHover ? () => onRowHover(undefined) : undefined}\n className={cn(\n ROW,\n 'rounded text-foreground transition-opacity duration-150',\n onRowClick && cn('cursor-pointer', FOCUS),\n active && 'before:bg-fill-subtle',\n dimmed && 'opacity-40',\n )}\n >\n {columns.map(column => (\n <div\n key={column.id}\n role=\"cell\"\n className={cn('flex min-w-0 items-center', column.align === 'end' && 'justify-end text-right')}\n >\n {column.cell(row)}\n </div>\n ))}\n </div>\n );\n}\n","import { useState } from 'react';\nimport { MetricsTableHeaderLabel } from './metrics-table-header';\nimport { MetricsTableBody, MetricsTableFiller } from './metrics-table-rows';\nimport type { MetricsTableColumn, MetricsTableProps, MetricsTableSort } from './metrics-table-types';\nimport { ScrollArea } from '@/ds/components/ScrollArea/scroll-area';\nimport { TablePagination } from '@/ds/components/Table/table-pagination';\nimport { cn } from '@/lib/utils';\n\n/**\n * A full-width line that fades over its last 6px; over 24px when the first row is hovered, so it\n * reads as part of the hover. Written out in full so Tailwind finds every class.\n */\nconst HEADER_LINE =\n 'after:absolute after:inset-x-0 after:bottom-0 after:h-px after:bg-border after:[mask-image:linear-gradient(to_right,transparent,black_6px,black_calc(100%-6px),transparent)] [&:has(+:hover)]:after:[mask-image:linear-gradient(to_right,transparent,black_24px,black_calc(100%-24px),transparent)]';\n\nconst ARIA_SORT = { asc: 'ascending', desc: 'descending' } as const;\n\n/**\n * Clicks on a column cycle its first direction, the other one, then off: off goes back to the\n * table's default order. Another column starts at its own first direction.\n */\nfunction nextSort<Row>(\n current: MetricsTableSort | undefined,\n column: MetricsTableColumn<Row>,\n): MetricsTableSort | undefined {\n const first = column.firstDirection ?? 'desc';\n if (current?.column !== column.id) return { column: column.id, direction: first };\n if (current.direction !== first) return undefined;\n return { column: column.id, direction: first === 'desc' ? 'asc' : 'desc' };\n}\n\n/** Ascending order of two present sort values. */\nfunction compareAscending(x: number | string, y: number | string) {\n if (typeof x === 'number' && typeof y === 'number') return x - y;\n return String(x).localeCompare(String(y));\n}\n\nfunction sortRows<Row>(rows: Row[], columns: MetricsTableColumn<Row>[], sort: MetricsTableSort | undefined) {\n const by = columns.find(c => c.id === sort?.column)?.sortValue;\n if (!sort || !by) return rows;\n const sign = sort.direction === 'desc' ? -1 : 1;\n // A row without a value goes last whichever way the column sorts.\n return rows.toSorted((a, b) => {\n const x = by(a);\n const y = by(b);\n if (x === undefined && y === undefined) return 0;\n if (x === undefined) return 1;\n if (y === undefined) return -1;\n return sign * compareAscending(x, y);\n });\n}\n\n/**\n * A column's grid track. Figures take a share of the spare width, like an HTML table's auto\n * layout: never narrower than their values, wider when the card has room.\n */\nconst columnWidth = <Row,>(column: MetricsTableColumn<Row>) =>\n column.width ?? (column.align === 'end' ? 'minmax(max-content,1fr)' : 'max-content');\n\n/**\n * A table for the numbers behind a chart: one row per series or group, columns for its figures,\n * separated by lines that fade at the ends. With `SeriesMark` and `Sparkline` cells and the row\n * hover and click hooks it doubles as the chart's legend; without them it's a plain data table.\n * With `pageSize` it pages long lists, and is always a full page tall. For a share of a total, a compact `ShareBar` fits better.\n */\nexport function MetricsTable<Row>({\n columns,\n rows,\n getRowKey,\n sort,\n defaultSort,\n onSortChange,\n onRowClick,\n onRowHover,\n isRowDimmed,\n isRowActive,\n rowTitle,\n empty,\n pageSize,\n isLoading = false,\n 'aria-label': ariaLabel,\n className,\n}: MetricsTableProps<Row>) {\n const [ownSort, setOwnSort] = useState(defaultSort);\n const [page, setPage] = useState(0);\n const current = sort ?? ownSort;\n const sorted = sortRows(rows, columns, current);\n const pageCount = pageSize ? Math.ceil(sorted.length / pageSize) : 1;\n // Fewer rows than before (a narrower filter) keeps the last page rather than an empty one.\n const safePage = Math.min(page, Math.max(0, pageCount - 1));\n const shown = pageSize ? sorted.slice(safePage * pageSize, (safePage + 1) * pageSize) : sorted;\n const template = { gridTemplateColumns: columns.map(columnWidth).join(' ') };\n const showsPagination = !isLoading && pageCount > 1;\n\n const sortBy = (column: MetricsTableColumn<Row>) => {\n const next = nextSort(current, column) ?? defaultSort;\n setOwnSort(next);\n setPage(0);\n onSortChange?.(next);\n };\n\n return (\n <div className={cn('grid min-w-0 gap-3', className)}>\n {/* Narrower than its content (a phone), the table scrolls sideways instead of squeezing columns or the page. */}\n <ScrollArea orientation=\"horizontal\">\n {/* One set of column tracks for the header and every row (each row is a subgrid), so a column's\n width follows its widest cell in the whole table and headers sit over their cells. */}\n <div\n role=\"table\"\n aria-label={ariaLabel}\n // min-content, not max-content: a long name would otherwise grow every `fr` column with it.\n className=\"grid min-w-min gap-x-4\"\n style={template}\n >\n <div\n role=\"row\"\n className={cn(\n 'relative col-span-full grid grid-cols-subgrid items-end px-3 pb-1.5 text-body-sm font-medium text-placeholder',\n HEADER_LINE,\n )}\n >\n {columns.map(column => {\n const direction = current?.column === column.id ? current.direction : undefined;\n return (\n <div\n key={column.id}\n role=\"columnheader\"\n aria-sort={direction && ARIA_SORT[direction]}\n className={cn('flex min-w-0 items-center gap-1', column.align === 'end' && 'justify-end text-right')}\n >\n <MetricsTableHeaderLabel\n header={column.header}\n description={column.description}\n sorted={direction}\n onSort={column.sortValue ? () => sortBy(column) : undefined}\n />\n </div>\n );\n })}\n </div>\n <MetricsTableBody\n columns={columns}\n rows={shown}\n getRowKey={getRowKey}\n onRowClick={onRowClick}\n onRowHover={onRowHover}\n isRowDimmed={isRowDimmed}\n isRowActive={isRowActive}\n rowTitle={rowTitle}\n empty={empty}\n pageSize={pageSize}\n isLoading={isLoading}\n />\n </div>\n {/* Always a full page tall, so loading, paging and switching data don't move what's below. */}\n {pageSize !== undefined && !isLoading && shown.length > 0 && (\n <MetricsTableFiller count={pageSize - shown.length} />\n )}\n </ScrollArea>\n {showsPagination && <TablePagination page={safePage} pageCount={pageCount} onPageChange={setPage} />}\n </div>\n );\n}\n"],"mappings":"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"}
@@ -8,7 +8,7 @@ import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "./component
8
8
  import { DisclosureChevron } from "./components/DisclosureChevron.es.js";
9
9
  import { Shimmer } from "./components/Shimmer.es.js";
10
10
  import { t as Badge } from "./Badge-aVu5iGAF.js";
11
- import { t as MarkdownRenderer } from "./MarkdownRenderer-2GOXQJEv.js";
11
+ import { t as MarkdownRenderer } from "./MarkdownRenderer-CI30RqdB.js";
12
12
  import { createContext, useContext, useId, useState } from "react";
13
13
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
14
14
  import { Bell, ExternalLink, X } from "lucide-react";
@@ -447,4 +447,4 @@ function SignalActivity({ appearance = "row", ...signal }) {
447
447
  }
448
448
  export { useRelativePaths as S, ActivitySpacer as _, ReasoningText as a, ActivityTrigger as b, ActivityContent as c, ActivityHeader as d, ActivityHeadline as f, ActivityLeading as g, ActivityLabel as h, hasVisibleReasoning as i, ActivityDetail as l, ActivityItem as m, ReasoningActivity as n, NotificationActivity as o, ActivityIcon$1 as p, hasReasoningText as r, Activity as s, SignalActivity as t, ActivityDisclosure as u, ActivitySummary as v, ActivityWorkingDirectory as x, ActivityTrailing as y };
449
449
 
450
- //# sourceMappingURL=activity-rJ1NQl_2.js.map
450
+ //# sourceMappingURL=activity-C8Ql81WM.js.map