@flanksource/clicky-ui 0.3.46 → 0.3.48

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 (474) hide show
  1. package/NOTICE.md +11 -0
  2. package/README.md +49 -0
  3. package/dist/ai.cjs +13 -8
  4. package/dist/ai.cjs.map +1 -1
  5. package/dist/ai.js +7 -2
  6. package/dist/ai.js.map +1 -1
  7. package/dist/comments/CommentSidePanel.cjs +10 -4
  8. package/dist/comments/CommentSidePanel.cjs.map +1 -1
  9. package/dist/comments/CommentSidePanel.d.ts +2 -0
  10. package/dist/comments/CommentSidePanel.d.ts.map +1 -1
  11. package/dist/comments/CommentSidePanel.js +10 -4
  12. package/dist/comments/CommentSidePanel.js.map +1 -1
  13. package/dist/comments/CommentThread.cjs +2 -0
  14. package/dist/comments/CommentThread.cjs.map +1 -1
  15. package/dist/comments/CommentThread.d.ts +2 -1
  16. package/dist/comments/CommentThread.d.ts.map +1 -1
  17. package/dist/comments/CommentThread.js +2 -0
  18. package/dist/comments/CommentThread.js.map +1 -1
  19. package/dist/comments/CommentThreadList.cjs +3 -0
  20. package/dist/comments/CommentThreadList.cjs.map +1 -1
  21. package/dist/comments/CommentThreadList.d.ts +3 -1
  22. package/dist/comments/CommentThreadList.d.ts.map +1 -1
  23. package/dist/comments/CommentThreadList.js +3 -0
  24. package/dist/comments/CommentThreadList.js.map +1 -1
  25. package/dist/components/ErrorWrapper.cjs +2 -3
  26. package/dist/components/ErrorWrapper.cjs.map +1 -1
  27. package/dist/components/ErrorWrapper.d.ts.map +1 -1
  28. package/dist/components/ErrorWrapper.js +3 -4
  29. package/dist/components/ErrorWrapper.js.map +1 -1
  30. package/dist/data/Clicky.cjs +3 -0
  31. package/dist/data/Clicky.cjs.map +1 -1
  32. package/dist/data/Clicky.js +3 -0
  33. package/dist/data/Clicky.js.map +1 -1
  34. package/dist/data/CodeLine.cjs +4 -2
  35. package/dist/data/CodeLine.cjs.map +1 -1
  36. package/dist/data/CodeLine.d.ts.map +1 -1
  37. package/dist/data/CodeLine.js +4 -2
  38. package/dist/data/CodeLine.js.map +1 -1
  39. package/dist/data/FilterPill.cjs +15 -2
  40. package/dist/data/FilterPill.cjs.map +1 -1
  41. package/dist/data/FilterPill.d.ts +1 -1
  42. package/dist/data/FilterPill.d.ts.map +1 -1
  43. package/dist/data/FilterPill.js +15 -2
  44. package/dist/data/FilterPill.js.map +1 -1
  45. package/dist/data/LogViewer.cjs +27 -8
  46. package/dist/data/LogViewer.cjs.map +1 -1
  47. package/dist/data/LogViewer.d.ts +11 -3
  48. package/dist/data/LogViewer.d.ts.map +1 -1
  49. package/dist/data/LogViewer.js +27 -8
  50. package/dist/data/LogViewer.js.map +1 -1
  51. package/dist/data/Properties.cjs +2 -15
  52. package/dist/data/Properties.cjs.map +1 -1
  53. package/dist/data/Properties.d.ts +4 -0
  54. package/dist/data/Properties.d.ts.map +1 -1
  55. package/dist/data/Properties.js +2 -15
  56. package/dist/data/Properties.js.map +1 -1
  57. package/dist/data/PropertyValue.cjs +37 -0
  58. package/dist/data/PropertyValue.cjs.map +1 -0
  59. package/dist/data/PropertyValue.d.ts +6 -0
  60. package/dist/data/PropertyValue.d.ts.map +1 -0
  61. package/dist/data/PropertyValue.js +37 -0
  62. package/dist/data/PropertyValue.js.map +1 -0
  63. package/dist/data/SymbolBadge.cjs +61 -0
  64. package/dist/data/SymbolBadge.cjs.map +1 -0
  65. package/dist/data/SymbolBadge.d.ts +21 -0
  66. package/dist/data/SymbolBadge.d.ts.map +1 -0
  67. package/dist/data/SymbolBadge.js +61 -0
  68. package/dist/data/SymbolBadge.js.map +1 -0
  69. package/dist/data/Tree.cjs +4 -3
  70. package/dist/data/Tree.cjs.map +1 -1
  71. package/dist/data/Tree.d.ts +3 -1
  72. package/dist/data/Tree.d.ts.map +1 -1
  73. package/dist/data/Tree.js +4 -3
  74. package/dist/data/Tree.js.map +1 -1
  75. package/dist/data/ai/ChatFab.cjs +1 -1
  76. package/dist/data/ai/ChatFab.cjs.map +1 -1
  77. package/dist/data/ai/ChatFab.js +1 -1
  78. package/dist/data/ai/ChatFab.js.map +1 -1
  79. package/dist/data/ai/ChatWindow.cjs +106 -171
  80. package/dist/data/ai/ChatWindow.cjs.map +1 -1
  81. package/dist/data/ai/ChatWindow.d.ts +6 -2
  82. package/dist/data/ai/ChatWindow.d.ts.map +1 -1
  83. package/dist/data/ai/ChatWindow.header.cjs +104 -0
  84. package/dist/data/ai/ChatWindow.header.cjs.map +1 -0
  85. package/dist/data/ai/ChatWindow.header.d.ts +29 -0
  86. package/dist/data/ai/ChatWindow.header.d.ts.map +1 -0
  87. package/dist/data/ai/ChatWindow.header.js +104 -0
  88. package/dist/data/ai/ChatWindow.header.js.map +1 -0
  89. package/dist/data/ai/ChatWindow.js +107 -172
  90. package/dist/data/ai/ChatWindow.js.map +1 -1
  91. package/dist/data/ai/ChatWindow.placement.cjs +95 -0
  92. package/dist/data/ai/ChatWindow.placement.cjs.map +1 -0
  93. package/dist/data/ai/ChatWindow.placement.d.ts +32 -0
  94. package/dist/data/ai/ChatWindow.placement.d.ts.map +1 -0
  95. package/dist/data/ai/ChatWindow.placement.js +95 -0
  96. package/dist/data/ai/ChatWindow.placement.js.map +1 -0
  97. package/dist/data/ai/SessionChatComposer.cjs +3 -1
  98. package/dist/data/ai/SessionChatComposer.cjs.map +1 -1
  99. package/dist/data/ai/SessionChatComposer.d.ts +4 -1
  100. package/dist/data/ai/SessionChatComposer.d.ts.map +1 -1
  101. package/dist/data/ai/SessionChatComposer.js +3 -1
  102. package/dist/data/ai/SessionChatComposer.js.map +1 -1
  103. package/dist/data/ai/SessionInspector.cjs +68 -72
  104. package/dist/data/ai/SessionInspector.cjs.map +1 -1
  105. package/dist/data/ai/SessionInspector.composer-slot.cjs +8 -0
  106. package/dist/data/ai/SessionInspector.composer-slot.cjs.map +1 -0
  107. package/dist/data/ai/SessionInspector.composer-slot.d.ts +9 -0
  108. package/dist/data/ai/SessionInspector.composer-slot.d.ts.map +1 -0
  109. package/dist/data/ai/SessionInspector.composer-slot.js +8 -0
  110. package/dist/data/ai/SessionInspector.composer-slot.js.map +1 -0
  111. package/dist/data/ai/SessionInspector.d.ts +6 -1
  112. package/dist/data/ai/SessionInspector.d.ts.map +1 -1
  113. package/dist/data/ai/SessionInspector.js +69 -73
  114. package/dist/data/ai/SessionInspector.js.map +1 -1
  115. package/dist/data/ai/SessionInspector.legacy.cjs +41 -42
  116. package/dist/data/ai/SessionInspector.legacy.cjs.map +1 -1
  117. package/dist/data/ai/SessionInspector.legacy.d.ts.map +1 -1
  118. package/dist/data/ai/SessionInspector.legacy.js +41 -42
  119. package/dist/data/ai/SessionInspector.legacy.js.map +1 -1
  120. package/dist/data/ai/SessionInspector.remote-view.cjs +14 -9
  121. package/dist/data/ai/SessionInspector.remote-view.cjs.map +1 -1
  122. package/dist/data/ai/SessionInspector.remote-view.d.ts +6 -2
  123. package/dist/data/ai/SessionInspector.remote-view.d.ts.map +1 -1
  124. package/dist/data/ai/SessionInspector.remote-view.js +14 -9
  125. package/dist/data/ai/SessionInspector.remote-view.js.map +1 -1
  126. package/dist/data/ai/SessionInspector.remote.cjs +84 -16
  127. package/dist/data/ai/SessionInspector.remote.cjs.map +1 -1
  128. package/dist/data/ai/SessionInspector.remote.d.ts +42 -7
  129. package/dist/data/ai/SessionInspector.remote.d.ts.map +1 -1
  130. package/dist/data/ai/SessionInspector.remote.js +86 -18
  131. package/dist/data/ai/SessionInspector.remote.js.map +1 -1
  132. package/dist/data/ai/SessionInspector.transcript.cjs +5 -0
  133. package/dist/data/ai/SessionInspector.transcript.cjs.map +1 -1
  134. package/dist/data/ai/SessionInspector.transcript.d.ts.map +1 -1
  135. package/dist/data/ai/SessionInspector.transcript.js +5 -0
  136. package/dist/data/ai/SessionInspector.transcript.js.map +1 -1
  137. package/dist/data/ai/SessionTail.cjs +63 -0
  138. package/dist/data/ai/SessionTail.cjs.map +1 -0
  139. package/dist/data/ai/SessionTail.d.ts +14 -0
  140. package/dist/data/ai/SessionTail.d.ts.map +1 -0
  141. package/dist/data/ai/SessionTail.js +63 -0
  142. package/dist/data/ai/SessionTail.js.map +1 -0
  143. package/dist/data/ai/SessionViewer.cjs +10 -3
  144. package/dist/data/ai/SessionViewer.cjs.map +1 -1
  145. package/dist/data/ai/SessionViewer.d.ts +7 -1
  146. package/dist/data/ai/SessionViewer.d.ts.map +1 -1
  147. package/dist/data/ai/SessionViewer.js +10 -3
  148. package/dist/data/ai/SessionViewer.js.map +1 -1
  149. package/dist/data/ai/SessionViewer.unified.d.ts +14 -0
  150. package/dist/data/ai/SessionViewer.unified.d.ts.map +1 -1
  151. package/dist/data/ai/index.d.ts +4 -3
  152. package/dist/data/ai/index.d.ts.map +1 -1
  153. package/dist/data/ai/use-session-scroll.cjs +30 -6
  154. package/dist/data/ai/use-session-scroll.cjs.map +1 -1
  155. package/dist/data/ai/use-session-scroll.d.ts +7 -0
  156. package/dist/data/ai/use-session-scroll.d.ts.map +1 -1
  157. package/dist/data/ai/use-session-scroll.js +30 -6
  158. package/dist/data/ai/use-session-scroll.js.map +1 -1
  159. package/dist/data/chat/Chat.cjs +1 -1
  160. package/dist/data/chat/Chat.cjs.map +1 -1
  161. package/dist/data/chat/Chat.js +1 -1
  162. package/dist/data/chat/Chat.js.map +1 -1
  163. package/dist/data/chat/ChatRuntimeToolbar.cjs +4 -4
  164. package/dist/data/chat/ChatRuntimeToolbar.cjs.map +1 -1
  165. package/dist/data/chat/ChatRuntimeToolbar.d.ts.map +1 -1
  166. package/dist/data/chat/ChatRuntimeToolbar.js +4 -4
  167. package/dist/data/chat/ChatRuntimeToolbar.js.map +1 -1
  168. package/dist/data/chat/PromptInput.cjs +4 -2
  169. package/dist/data/chat/PromptInput.cjs.map +1 -1
  170. package/dist/data/chat/PromptInput.d.ts +5 -1
  171. package/dist/data/chat/PromptInput.d.ts.map +1 -1
  172. package/dist/data/chat/PromptInput.js +4 -2
  173. package/dist/data/chat/PromptInput.js.map +1 -1
  174. package/dist/data/diagnostics/ErrorDetails.cjs +13 -2
  175. package/dist/data/diagnostics/ErrorDetails.cjs.map +1 -1
  176. package/dist/data/diagnostics/ErrorDetails.d.ts +3 -1
  177. package/dist/data/diagnostics/ErrorDetails.d.ts.map +1 -1
  178. package/dist/data/diagnostics/ErrorDetails.js +14 -3
  179. package/dist/data/diagnostics/ErrorDetails.js.map +1 -1
  180. package/dist/data/diagnostics/FrameSourceWindow.cjs +3 -2
  181. package/dist/data/diagnostics/FrameSourceWindow.cjs.map +1 -1
  182. package/dist/data/diagnostics/FrameSourceWindow.d.ts.map +1 -1
  183. package/dist/data/diagnostics/FrameSourceWindow.js +3 -2
  184. package/dist/data/diagnostics/FrameSourceWindow.js.map +1 -1
  185. package/dist/data/diagnostics/error-diagnostics.cjs +5 -0
  186. package/dist/data/diagnostics/error-diagnostics.cjs.map +1 -1
  187. package/dist/data/diagnostics/error-diagnostics.d.ts +1 -0
  188. package/dist/data/diagnostics/error-diagnostics.d.ts.map +1 -1
  189. package/dist/data/diagnostics/error-diagnostics.js +6 -1
  190. package/dist/data/diagnostics/error-diagnostics.js.map +1 -1
  191. package/dist/data/har/HarPanel.cjs +3 -1
  192. package/dist/data/har/HarPanel.cjs.map +1 -1
  193. package/dist/data/har/HarPanel.d.ts +4 -1
  194. package/dist/data/har/HarPanel.d.ts.map +1 -1
  195. package/dist/data/har/HarPanel.js +3 -1
  196. package/dist/data/har/HarPanel.js.map +1 -1
  197. package/dist/data/test-runner/Expectation.cjs +57 -0
  198. package/dist/data/test-runner/Expectation.cjs.map +1 -0
  199. package/dist/data/test-runner/Expectation.d.ts +19 -0
  200. package/dist/data/test-runner/Expectation.d.ts.map +1 -0
  201. package/dist/data/test-runner/Expectation.js +57 -0
  202. package/dist/data/test-runner/Expectation.js.map +1 -0
  203. package/dist/data/test-runner/MarkIcons.cjs +38 -0
  204. package/dist/data/test-runner/MarkIcons.cjs.map +1 -0
  205. package/dist/data/test-runner/MarkIcons.d.ts +15 -0
  206. package/dist/data/test-runner/MarkIcons.d.ts.map +1 -0
  207. package/dist/data/test-runner/MarkIcons.js +38 -0
  208. package/dist/data/test-runner/MarkIcons.js.map +1 -0
  209. package/dist/data/test-runner/TestDetailPanel.cjs +99 -53
  210. package/dist/data/test-runner/TestDetailPanel.cjs.map +1 -1
  211. package/dist/data/test-runner/TestDetailPanel.d.ts.map +1 -1
  212. package/dist/data/test-runner/TestDetailPanel.js +101 -55
  213. package/dist/data/test-runner/TestDetailPanel.js.map +1 -1
  214. package/dist/data/test-runner/TestFailureDetail.cjs +23 -27
  215. package/dist/data/test-runner/TestFailureDetail.cjs.map +1 -1
  216. package/dist/data/test-runner/TestFailureDetail.d.ts +2 -2
  217. package/dist/data/test-runner/TestFailureDetail.d.ts.map +1 -1
  218. package/dist/data/test-runner/TestFailureDetail.js +23 -27
  219. package/dist/data/test-runner/TestFailureDetail.js.map +1 -1
  220. package/dist/data/test-runner/TestFilterBar.cjs +87 -93
  221. package/dist/data/test-runner/TestFilterBar.cjs.map +1 -1
  222. package/dist/data/test-runner/TestFilterBar.d.ts +3 -2
  223. package/dist/data/test-runner/TestFilterBar.d.ts.map +1 -1
  224. package/dist/data/test-runner/TestFilterBar.js +89 -95
  225. package/dist/data/test-runner/TestFilterBar.js.map +1 -1
  226. package/dist/data/test-runner/TestRunSummary.cjs +35 -21
  227. package/dist/data/test-runner/TestRunSummary.cjs.map +1 -1
  228. package/dist/data/test-runner/TestRunSummary.d.ts.map +1 -1
  229. package/dist/data/test-runner/TestRunSummary.js +35 -21
  230. package/dist/data/test-runner/TestRunSummary.js.map +1 -1
  231. package/dist/data/test-runner/TestRunner.cjs +58 -30
  232. package/dist/data/test-runner/TestRunner.cjs.map +1 -1
  233. package/dist/data/test-runner/TestRunner.d.ts +6 -3
  234. package/dist/data/test-runner/TestRunner.d.ts.map +1 -1
  235. package/dist/data/test-runner/TestRunner.js +58 -30
  236. package/dist/data/test-runner/TestRunner.js.map +1 -1
  237. package/dist/data/test-runner/TestTree.cjs +5 -2
  238. package/dist/data/test-runner/TestTree.cjs.map +1 -1
  239. package/dist/data/test-runner/TestTree.d.ts +5 -2
  240. package/dist/data/test-runner/TestTree.d.ts.map +1 -1
  241. package/dist/data/test-runner/TestTree.js +5 -2
  242. package/dist/data/test-runner/TestTree.js.map +1 -1
  243. package/dist/data/test-runner/TestTreeNode.cjs +28 -19
  244. package/dist/data/test-runner/TestTreeNode.cjs.map +1 -1
  245. package/dist/data/test-runner/TestTreeNode.d.ts.map +1 -1
  246. package/dist/data/test-runner/TestTreeNode.js +29 -20
  247. package/dist/data/test-runner/TestTreeNode.js.map +1 -1
  248. package/dist/data/test-runner/adapter.cjs +15 -0
  249. package/dist/data/test-runner/adapter.cjs.map +1 -1
  250. package/dist/data/test-runner/adapter.d.ts +27 -7
  251. package/dist/data/test-runner/adapter.d.ts.map +1 -1
  252. package/dist/data/test-runner/adapter.js +15 -0
  253. package/dist/data/test-runner/adapter.js.map +1 -1
  254. package/dist/data/test-runner/context.cjs.map +1 -1
  255. package/dist/data/test-runner/context.d.ts +2 -0
  256. package/dist/data/test-runner/context.d.ts.map +1 -1
  257. package/dist/data/test-runner/context.js.map +1 -1
  258. package/dist/data/test-runner/copy.cjs +114 -0
  259. package/dist/data/test-runner/copy.cjs.map +1 -0
  260. package/dist/data/test-runner/copy.d.ts +47 -0
  261. package/dist/data/test-runner/copy.d.ts.map +1 -0
  262. package/dist/data/test-runner/copy.js +114 -0
  263. package/dist/data/test-runner/copy.js.map +1 -0
  264. package/dist/data/test-runner/index.d.ts +6 -3
  265. package/dist/data/test-runner/index.d.ts.map +1 -1
  266. package/dist/data/test-runner/marks.cjs +184 -0
  267. package/dist/data/test-runner/marks.cjs.map +1 -0
  268. package/dist/data/test-runner/marks.d.ts +40 -0
  269. package/dist/data/test-runner/marks.d.ts.map +1 -0
  270. package/dist/data/test-runner/marks.js +184 -0
  271. package/dist/data/test-runner/marks.js.map +1 -0
  272. package/dist/data/test-runner/status.cjs +27 -44
  273. package/dist/data/test-runner/status.cjs.map +1 -1
  274. package/dist/data/test-runner/status.d.ts +12 -3
  275. package/dist/data/test-runner/status.d.ts.map +1 -1
  276. package/dist/data/test-runner/status.js +27 -44
  277. package/dist/data/test-runner/status.js.map +1 -1
  278. package/dist/data/traces/TerminalCastPlayer.d.ts +21 -0
  279. package/dist/data/traces/TerminalCastPlayer.d.ts.map +1 -0
  280. package/dist/data/traces/TraceHarView.d.ts +13 -0
  281. package/dist/data/traces/TraceHarView.d.ts.map +1 -0
  282. package/dist/data/traces/cast.d.ts +9 -0
  283. package/dist/data/traces/cast.d.ts.map +1 -0
  284. package/dist/data/traces/fixtures.d.ts +8 -0
  285. package/dist/data/traces/fixtures.d.ts.map +1 -0
  286. package/dist/data/traces/har-adapter.d.ts +13 -0
  287. package/dist/data/traces/har-adapter.d.ts.map +1 -0
  288. package/dist/data/traces/terminal-screen.d.ts +45 -0
  289. package/dist/data/traces/terminal-screen.d.ts.map +1 -0
  290. package/dist/data/traces/terminal-timeline.d.ts +26 -0
  291. package/dist/data/traces/terminal-timeline.d.ts.map +1 -0
  292. package/dist/data/traces/types.d.ts +141 -0
  293. package/dist/data/traces/types.d.ts.map +1 -0
  294. package/dist/data/verification/VerificationResults.cjs +4 -0
  295. package/dist/data/verification/VerificationResults.cjs.map +1 -1
  296. package/dist/data/verification/VerificationResults.d.ts +3 -1
  297. package/dist/data/verification/VerificationResults.d.ts.map +1 -1
  298. package/dist/data/verification/VerificationResults.js +4 -0
  299. package/dist/data/verification/VerificationResults.js.map +1 -1
  300. package/dist/data/verification/adapterViews.cjs +28 -44
  301. package/dist/data/verification/adapterViews.cjs.map +1 -1
  302. package/dist/data/verification/adapterViews.d.ts +4 -1
  303. package/dist/data/verification/adapterViews.d.ts.map +1 -1
  304. package/dist/data/verification/adapterViews.js +28 -44
  305. package/dist/data/verification/adapterViews.js.map +1 -1
  306. package/dist/data/verification/adapters.cjs +163 -8
  307. package/dist/data/verification/adapters.cjs.map +1 -1
  308. package/dist/data/verification/adapters.d.ts +7 -1
  309. package/dist/data/verification/adapters.d.ts.map +1 -1
  310. package/dist/data/verification/adapters.js +163 -8
  311. package/dist/data/verification/adapters.js.map +1 -1
  312. package/dist/data/verification/index.d.ts +4 -2
  313. package/dist/data/verification/index.d.ts.map +1 -1
  314. package/dist/data/verification/stepKind.cjs +217 -0
  315. package/dist/data/verification/stepKind.cjs.map +1 -0
  316. package/dist/data/verification/stepKind.d.ts +87 -0
  317. package/dist/data/verification/stepKind.d.ts.map +1 -0
  318. package/dist/data/verification/stepKind.js +217 -0
  319. package/dist/data/verification/stepKind.js.map +1 -0
  320. package/dist/data/verification/stepKindViews.cjs +111 -0
  321. package/dist/data/verification/stepKindViews.cjs.map +1 -0
  322. package/dist/data/verification/stepKindViews.d.ts +18 -0
  323. package/dist/data/verification/stepKindViews.d.ts.map +1 -0
  324. package/dist/data/verification/stepKindViews.js +111 -0
  325. package/dist/data/verification/stepKindViews.js.map +1 -0
  326. package/dist/data/verification/verifyReportTests.cjs +1 -0
  327. package/dist/data/verification/verifyReportTests.cjs.map +1 -1
  328. package/dist/data/verification/verifyReportTests.d.ts +2 -1
  329. package/dist/data/verification/verifyReportTests.d.ts.map +1 -1
  330. package/dist/data/verification/verifyReportTests.js +1 -0
  331. package/dist/data/verification/verifyReportTests.js.map +1 -1
  332. package/dist/data/version-info.cjs +3 -3
  333. package/dist/data/version-info.js +3 -3
  334. package/dist/data.cjs +58 -3
  335. package/dist/data.cjs.map +1 -1
  336. package/dist/data.d.ts +3 -0
  337. package/dist/data.d.ts.map +1 -1
  338. package/dist/data.js +60 -5
  339. package/dist/data.js.map +1 -1
  340. package/dist/icons/components/UiLogoEslint.cjs +10 -0
  341. package/dist/icons/components/UiLogoEslint.cjs.map +1 -0
  342. package/dist/icons/components/UiLogoEslint.d.ts +9 -0
  343. package/dist/icons/components/UiLogoEslint.d.ts.map +1 -0
  344. package/dist/icons/components/UiLogoEslint.js +10 -0
  345. package/dist/icons/components/UiLogoEslint.js.map +1 -0
  346. package/dist/icons/components/UiLogoGo.cjs +10 -0
  347. package/dist/icons/components/UiLogoGo.cjs.map +1 -0
  348. package/dist/icons/components/UiLogoGo.d.ts +9 -0
  349. package/dist/icons/components/UiLogoGo.d.ts.map +1 -0
  350. package/dist/icons/components/UiLogoGo.js +10 -0
  351. package/dist/icons/components/UiLogoGo.js.map +1 -0
  352. package/dist/icons/components/UiLogoJest.cjs +10 -0
  353. package/dist/icons/components/UiLogoJest.cjs.map +1 -0
  354. package/dist/icons/components/UiLogoJest.d.ts +9 -0
  355. package/dist/icons/components/UiLogoJest.d.ts.map +1 -0
  356. package/dist/icons/components/UiLogoJest.js +10 -0
  357. package/dist/icons/components/UiLogoJest.js.map +1 -0
  358. package/dist/icons/components/UiLogoMarkdown.cjs +10 -0
  359. package/dist/icons/components/UiLogoMarkdown.cjs.map +1 -0
  360. package/dist/icons/components/UiLogoMarkdown.d.ts +9 -0
  361. package/dist/icons/components/UiLogoMarkdown.d.ts.map +1 -0
  362. package/dist/icons/components/UiLogoMarkdown.js +10 -0
  363. package/dist/icons/components/UiLogoMarkdown.js.map +1 -0
  364. package/dist/icons/components/UiLogoOxc.cjs +10 -0
  365. package/dist/icons/components/UiLogoOxc.cjs.map +1 -0
  366. package/dist/icons/components/UiLogoOxc.d.ts +9 -0
  367. package/dist/icons/components/UiLogoOxc.d.ts.map +1 -0
  368. package/dist/icons/components/UiLogoOxc.js +10 -0
  369. package/dist/icons/components/UiLogoOxc.js.map +1 -0
  370. package/dist/icons/components/UiLogoPlaywright.cjs +10 -0
  371. package/dist/icons/components/UiLogoPlaywright.cjs.map +1 -0
  372. package/dist/icons/components/UiLogoPlaywright.d.ts +9 -0
  373. package/dist/icons/components/UiLogoPlaywright.d.ts.map +1 -0
  374. package/dist/icons/components/UiLogoPlaywright.js +10 -0
  375. package/dist/icons/components/UiLogoPlaywright.js.map +1 -0
  376. package/dist/icons/components/UiLogoPython.cjs +10 -0
  377. package/dist/icons/components/UiLogoPython.cjs.map +1 -0
  378. package/dist/icons/components/UiLogoPython.d.ts +9 -0
  379. package/dist/icons/components/UiLogoPython.d.ts.map +1 -0
  380. package/dist/icons/components/UiLogoPython.js +10 -0
  381. package/dist/icons/components/UiLogoPython.js.map +1 -0
  382. package/dist/icons/components/UiLogoReact.cjs +10 -0
  383. package/dist/icons/components/UiLogoReact.cjs.map +1 -0
  384. package/dist/icons/components/UiLogoReact.d.ts +9 -0
  385. package/dist/icons/components/UiLogoReact.d.ts.map +1 -0
  386. package/dist/icons/components/UiLogoReact.js +10 -0
  387. package/dist/icons/components/UiLogoReact.js.map +1 -0
  388. package/dist/icons/components/UiLogoRuff.cjs +10 -0
  389. package/dist/icons/components/UiLogoRuff.cjs.map +1 -0
  390. package/dist/icons/components/UiLogoRuff.d.ts +9 -0
  391. package/dist/icons/components/UiLogoRuff.d.ts.map +1 -0
  392. package/dist/icons/components/UiLogoRuff.js +10 -0
  393. package/dist/icons/components/UiLogoRuff.js.map +1 -0
  394. package/dist/icons/components/UiLogoTypescript.cjs +10 -0
  395. package/dist/icons/components/UiLogoTypescript.cjs.map +1 -0
  396. package/dist/icons/components/UiLogoTypescript.d.ts +9 -0
  397. package/dist/icons/components/UiLogoTypescript.d.ts.map +1 -0
  398. package/dist/icons/components/UiLogoTypescript.js +10 -0
  399. package/dist/icons/components/UiLogoTypescript.js.map +1 -0
  400. package/dist/icons/components/UiLogoVitest.cjs +10 -0
  401. package/dist/icons/components/UiLogoVitest.cjs.map +1 -0
  402. package/dist/icons/components/UiLogoVitest.d.ts +9 -0
  403. package/dist/icons/components/UiLogoVitest.d.ts.map +1 -0
  404. package/dist/icons/components/UiLogoVitest.js +10 -0
  405. package/dist/icons/components/UiLogoVitest.js.map +1 -0
  406. package/dist/icons/index.d.ts +11 -0
  407. package/dist/icons/index.d.ts.map +1 -1
  408. package/dist/icons/registry.cjs +22 -0
  409. package/dist/icons/registry.cjs.map +1 -1
  410. package/dist/icons/registry.d.ts.map +1 -1
  411. package/dist/icons/registry.js +22 -0
  412. package/dist/icons/registry.js.map +1 -1
  413. package/dist/icons.cjs +22 -0
  414. package/dist/icons.cjs.map +1 -1
  415. package/dist/icons.js +22 -0
  416. package/dist/icons.js.map +1 -1
  417. package/dist/index.cjs +60 -3
  418. package/dist/index.cjs.map +1 -1
  419. package/dist/index.js +62 -5
  420. package/dist/index.js.map +1 -1
  421. package/dist/overlay/DropdownMenuSubmenu.cjs +4 -4
  422. package/dist/overlay/DropdownMenuSubmenu.cjs.map +1 -1
  423. package/dist/overlay/DropdownMenuSubmenu.js +4 -4
  424. package/dist/overlay/DropdownMenuSubmenu.js.map +1 -1
  425. package/dist/rpc/FilterForm.cjs +9 -0
  426. package/dist/rpc/FilterForm.cjs.map +1 -1
  427. package/dist/rpc/FilterForm.d.ts +5 -1
  428. package/dist/rpc/FilterForm.d.ts.map +1 -1
  429. package/dist/rpc/FilterForm.js +9 -0
  430. package/dist/rpc/FilterForm.js.map +1 -1
  431. package/dist/rpc/InlineError.cjs +12 -43
  432. package/dist/rpc/InlineError.cjs.map +1 -1
  433. package/dist/rpc/InlineError.d.ts.map +1 -1
  434. package/dist/rpc/InlineError.js +13 -44
  435. package/dist/rpc/InlineError.js.map +1 -1
  436. package/dist/rpc/OperationArgsForm.cjs +153 -0
  437. package/dist/rpc/OperationArgsForm.cjs.map +1 -0
  438. package/dist/rpc/OperationArgsForm.d.ts +16 -0
  439. package/dist/rpc/OperationArgsForm.d.ts.map +1 -0
  440. package/dist/rpc/OperationArgsForm.js +153 -0
  441. package/dist/rpc/OperationArgsForm.js.map +1 -0
  442. package/dist/rpc/OperationScheduleDialog.cjs +119 -22
  443. package/dist/rpc/OperationScheduleDialog.cjs.map +1 -1
  444. package/dist/rpc/OperationScheduleDialog.d.ts +7 -0
  445. package/dist/rpc/OperationScheduleDialog.d.ts.map +1 -1
  446. package/dist/rpc/OperationScheduleDialog.js +120 -23
  447. package/dist/rpc/OperationScheduleDialog.js.map +1 -1
  448. package/dist/rpc/OperationSchedules.cjs +17 -2
  449. package/dist/rpc/OperationSchedules.cjs.map +1 -1
  450. package/dist/rpc/OperationSchedules.d.ts.map +1 -1
  451. package/dist/rpc/OperationSchedules.js +17 -2
  452. package/dist/rpc/OperationSchedules.js.map +1 -1
  453. package/dist/rpc/operation-schedule-model.cjs +2 -7
  454. package/dist/rpc/operation-schedule-model.cjs.map +1 -1
  455. package/dist/rpc/operation-schedule-model.d.ts +0 -2
  456. package/dist/rpc/operation-schedule-model.d.ts.map +1 -1
  457. package/dist/rpc/operation-schedule-model.js +2 -7
  458. package/dist/rpc/operation-schedule-model.js.map +1 -1
  459. package/dist/rpc/operation-schedule-types.d.ts +12 -1
  460. package/dist/rpc/operation-schedule-types.d.ts.map +1 -1
  461. package/dist/rpc.cjs +2 -0
  462. package/dist/rpc.cjs.map +1 -1
  463. package/dist/rpc.d.ts +1 -0
  464. package/dist/rpc.d.ts.map +1 -1
  465. package/dist/rpc.js +2 -0
  466. package/dist/rpc.js.map +1 -1
  467. package/dist/styles.css +1 -1
  468. package/package.json +1 -1
  469. package/dist/data/test-runner/frameworkIcon.cjs +0 -27
  470. package/dist/data/test-runner/frameworkIcon.cjs.map +0 -1
  471. package/dist/data/test-runner/frameworkIcon.d.ts +0 -3
  472. package/dist/data/test-runner/frameworkIcon.d.ts.map +0 -1
  473. package/dist/data/test-runner/frameworkIcon.js +0 -27
  474. package/dist/data/test-runner/frameworkIcon.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"TestDetailPanel.js","sources":["../../../src/data/test-runner/TestDetailPanel.tsx"],"sourcesContent":["import { useState, type ReactNode } from \"react\";\nimport { Icon } from \"../Icon\";\nimport { Button } from \"../../components/button\";\nimport { JsonView } from \"../JsonView\";\nimport { TabButton } from \"../TabButton\";\nimport { cn } from \"../../lib/utils\";\nimport { UiClass, UiClock, UiRefresh, UiStop } from \"../../icons\";\nimport type { Test } from \"./types\";\nimport { useTestRunner } from \"./context\";\nimport { formatTestDuration, statusIconFor, statusToneFor, sum } from \"./status\";\nimport { frameworkIcon } from \"./frameworkIcon\";\nimport { TestAttempts, TestFailureDetail, TestOutput } from \"./TestFailureDetail\";\n\nconst ICON_TONE = {\n danger: \"rose\",\n warning: \"amber\",\n success: \"emerald\",\n info: \"sky\",\n neutral: \"neutral\",\n} as const;\n\n/** Built-in detail body — used when no adapter contributes `renderDetail`. */\nfunction DefaultDetailBody({ node }: { node: Test }) {\n const hasChildren = (node.children?.length ?? 0) > 0;\n const counts = hasChildren ? sum(node) : null;\n return (\n <div className=\"space-y-4 p-density-4\">\n {node.message && !node.failure_detail && (\n <p className=\"whitespace-pre-wrap break-words text-sm\">{node.message}</p>\n )}\n {node.failure_detail && <TestFailureDetail failure={node.failure_detail} />}\n <TestOutput node={node} />\n {node.attempts && node.attempts.length > 0 && <TestAttempts attempts={node.attempts} />}\n {counts && counts.total > 0 && (\n <div className=\"flex flex-wrap gap-3 text-xs text-muted-foreground\">\n <span>{counts.total} total</span>\n {counts.passed > 0 && <span>{counts.passed} passed</span>}\n {counts.failed > 0 && <span>{counts.failed} failed</span>}\n {counts.skipped > 0 && <span>{counts.skipped} skipped</span>}\n </div>\n )}\n {node.detail != null && (\n <div className=\"space-y-1\">\n <div className=\"text-[10px] uppercase tracking-wide text-muted-foreground\">Detail</div>\n <JsonView data={node.detail} />\n </div>\n )}\n </div>\n );\n}\n\nfunction DetailHeader({ node, actions }: { node: Test; actions?: ReactNode }) {\n const runner = useTestRunner();\n const fwIcon = frameworkIcon(node.framework);\n const canRerun = !!runner.onRerun && node.framework !== \"task\";\n const canStop = !!runner.onStop && !!node.can_stop && !!node.task_id;\n return (\n <div className=\"flex items-start gap-2 border-b border-border p-density-4\">\n <Icon\n icon={statusIconFor(node)}\n className={cn(\"mt-0.5 shrink-0 text-2xl\", node.running && \"animate-spin\")}\n tone={ICON_TONE[statusToneFor(node)]}\n />\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-start justify-between gap-2\">\n <h2 className=\"break-words text-base font-semibold\">{node.name}</h2>\n <div className=\"flex shrink-0 items-center gap-1\">\n {actions}\n {canRerun && (\n <Button\n size=\"sm\"\n disabled={runner.busy.rerun}\n onClick={() => runner.onRerun!(node)}\n title=\"Rerun this test or subtree\"\n >\n <Icon icon={UiRefresh} className=\"mr-1 text-sm\" />\n {runner.busy.rerun ? \"Running...\" : \"Rerun\"}\n </Button>\n )}\n {canStop && (\n <Button\n size=\"sm\"\n variant=\"destructive\"\n disabled={runner.busy.stop}\n onClick={() => runner.onStop!(node)}\n title=\"Stop this running task\"\n >\n <Icon icon={UiStop} className=\"mr-1 text-sm\" />\n {runner.busy.stop ? \"Stopping...\" : \"Stop\"}\n </Button>\n )}\n </div>\n </div>\n <div className=\"mt-1 flex flex-wrap items-center gap-2 text-xs text-muted-foreground\">\n {fwIcon && (\n <span className=\"inline-flex items-center gap-1 rounded bg-muted px-1.5 py-0.5\">\n <Icon icon={fwIcon} className=\"text-sm\" />\n {node.framework}\n </span>\n )}\n {node.duration ? (\n <span className=\"inline-flex items-center gap-1\">\n <Icon icon={UiClock} className=\"text-xs\" />\n {formatTestDuration(node.duration)}\n </span>\n ) : null}\n {node.file && (\n <span className=\"font-mono\">\n {node.file}\n {node.line ? `:${node.line}` : \"\"}\n </span>\n )}\n </div>\n </div>\n </div>\n );\n}\n\n/**\n * The right pane. Resolves the node's adapter for body / tabs / header actions,\n * falling back to the built-in default body. Shows an empty state when nothing\n * is selected.\n */\nexport function TestDetailPanel() {\n const runner = useTestRunner();\n const node = runner.selected;\n // Tab state is controlled when the host supplies activeTab (e.g. to mirror it\n // into the URL); otherwise the panel owns it. The render below tolerates an\n // unknown id by falling back to the built-in \"detail\" tab.\n const controlled = runner.activeTab !== undefined;\n const [internalTab, setInternalTab] = useState<string>(\"detail\");\n const activeTab = controlled ? runner.activeTab! : internalTab;\n const setActiveTab = (id: string) => {\n if (controlled) runner.onTabChange?.(id);\n else setInternalTab(id);\n };\n\n if (!node) {\n return (\n <div className=\"flex h-full items-center justify-center text-sm text-muted-foreground\">\n <div className=\"text-center\">\n <Icon icon={UiClass} className=\"mb-2 block text-4xl\" />\n Select a test to view its details.\n </div>\n </div>\n );\n }\n\n const detailAdapter = runner.adapters.resolveDetail(node, runner);\n const actionAdapter = runner.adapters.resolveActions(node, runner);\n const tabs = runner.adapters.resolveTabs(node, runner);\n const ownsScroll = runner.adapters.ownsScroll(node, runner);\n\n const body = detailAdapter?.renderDetail\n ? detailAdapter.renderDetail({ node, runner })\n : <DefaultDetailBody node={node} />;\n const actions = actionAdapter?.nodeActions?.({ node, runner });\n\n const detailRegion = ownsScroll ? \"min-h-0 flex-1\" : \"min-h-0 flex-1 overflow-y-auto\";\n\n // No extra tabs → just the body under the header.\n if (tabs.length === 0) {\n return (\n <div className=\"flex h-full min-h-0 flex-col\">\n <DetailHeader node={node} actions={actions} />\n <div className={detailRegion}>{body}</div>\n </div>\n );\n }\n\n const detailTab = { id: \"detail\", label: \"Detail\", render: () => body };\n const allTabs = [detailTab, ...tabs];\n const active = allTabs.find((t) => t.id === activeTab) ?? detailTab;\n\n return (\n <div className=\"flex h-full min-h-0 flex-col\">\n <DetailHeader node={node} actions={actions} />\n <div className=\"flex shrink-0 items-center gap-1 border-b border-border px-density-2 py-density-1\">\n {allTabs.map((t) => (\n <TabButton\n key={t.id}\n active={active.id === t.id}\n onClick={() => setActiveTab(t.id)}\n label={t.label}\n />\n ))}\n </div>\n <div className={detailRegion}>{active.render()}</div>\n </div>\n );\n}\n"],"names":["_a"],"mappings":"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"}
1
+ {"version":3,"file":"TestDetailPanel.js","sources":["../../../src/data/test-runner/TestDetailPanel.tsx"],"sourcesContent":["import { useMemo, useState, type ReactNode } from \"react\";\nimport { Icon } from \"../Icon\";\nimport { Button } from \"../../components/button\";\nimport { Select } from \"../../components/select\";\nimport { SplitButton } from \"../../components/SplitButton\";\nimport { useCopyFlash } from \"../../components/clipboard\";\nimport type { DropdownMenuItem } from \"../../overlay/DropdownMenu\";\nimport { cn } from \"../../lib/utils\";\nimport { JsonView } from \"../JsonView\";\nimport { TabButton } from \"../TabButton\";\nimport {\n UiCheck,\n UiClass,\n UiClock,\n UiCopy,\n UiJson,\n UiRefresh,\n UiStop,\n UiWarningCircle,\n} from \"../../icons\";\nimport type { Test } from \"./types\";\nimport { useTestRunner } from \"./context\";\nimport { buildNodeBrief, buildNodeJson, type CopyItem } from \"./copy\";\nimport { formatTestDuration, outcomeFor, sum } from \"./status\";\nimport { toolKeyFor } from \"./marks\";\nimport { OutcomeIcon, ToolIcon } from \"./MarkIcons\";\nimport { TestAttempts, TestFailureDetail, TestOutput } from \"./TestFailureDetail\";\n\n/** Built-in detail body — used when no adapter contributes `renderDetail`. */\nfunction DefaultDetailBody({ node }: { node: Test }) {\n const hasChildren = (node.children?.length ?? 0) > 0;\n const counts = hasChildren ? sum(node) : null;\n return (\n <div className=\"space-y-4 p-density-4\">\n {node.message && !node.failure_detail && (\n <p className=\"whitespace-pre-wrap break-words text-sm\">{node.message}</p>\n )}\n {node.failure_detail && <TestFailureDetail failure={node.failure_detail} />}\n <TestOutput node={node} />\n {node.attempts && node.attempts.length > 0 && <TestAttempts attempts={node.attempts} />}\n {counts && counts.total > 0 && (\n <div className=\"flex flex-wrap gap-3 text-xs text-muted-foreground\">\n <span>{counts.total} total</span>\n {counts.passed > 0 && <span>{counts.passed} passed</span>}\n {counts.failed > 0 && <span>{counts.failed} failed</span>}\n {counts.skipped > 0 && <span>{counts.skipped} skipped</span>}\n </div>\n )}\n {node.detail != null && (\n <div className=\"space-y-1\">\n <div className=\"text-[10px] uppercase tracking-wide text-muted-foreground\">Detail</div>\n <JsonView data={node.detail} />\n </div>\n )}\n </div>\n );\n}\n\nfunction copyMenuItem(item: CopyItem, copy: (text: string) => void): DropdownMenuItem {\n const icon = item.icon ? { icon: item.icon } : {};\n if (\"reason\" in item) {\n return { label: item.label, ...icon, disabled: true, title: item.reason, onSelect: () => {} };\n }\n return { label: item.label, ...icon, onSelect: () => copy(item.value) };\n}\n\nconst COPY_LABEL = { idle: \"Copy details\", copied: \"Copied\", error: \"Copy failed\" } as const;\nconst COPY_ICON = { idle: UiCopy, copied: UiCheck, error: UiWarningCircle } as const;\n\n/**\n * \"Copy details\" split button: the primary action copies a Markdown brief of\n * the generic sections plus every matching adapter's `copy` sections; the menu\n * offers the node as JSON and the adapters' items, disabled with a reason when\n * they have nothing to copy. The label flips to \"Copied\" or \"Copy failed\".\n */\nfunction CopyDetailsButton({ node }: { node: Test }) {\n const runner = useTestRunner();\n const { state, copy } = useCopyFlash();\n const sections = useMemo(() => runner.adapters.resolveCopy(node, runner), [node, runner]);\n const items: DropdownMenuItem[] = [\n { label: \"Copy as JSON\", icon: UiJson, onSelect: () => copy(buildNodeJson(node)) },\n ...sections.items.map((item) => copyMenuItem(item, copy)),\n ];\n return (\n <SplitButton\n label={COPY_LABEL[state]}\n icon={COPY_ICON[state]}\n variant=\"outline\"\n size=\"sm\"\n align=\"right\"\n title=\"More copy options\"\n onClick={() => copy(buildNodeBrief(node, sections))}\n items={items}\n />\n );\n}\n\nfunction DetailHeader({ node, actionNode, actions, attemptChooser }: { node: Test; actionNode: Test; actions?: ReactNode; attemptChooser?: ReactNode }) {\n const runner = useTestRunner();\n const outcome = outcomeFor(node);\n const canRerun = !!runner.onRerun && actionNode.framework !== \"task\";\n const canStop = !!runner.onStop && !!actionNode.can_stop && !!actionNode.task_id;\n const location = node.file ? `${node.file}${node.line ? `:${node.line}` : \"\"}` : undefined;\n return (\n <div\n className=\"flex min-w-0 items-center gap-2 border-b border-border px-density-4 py-density-2\"\n data-detail-header=\"\"\n >\n {outcome ? (\n <OutcomeIcon outcome={outcome} className=\"text-lg\" />\n ) : (\n <Icon icon={UiClass} className=\"shrink-0 text-lg text-muted-foreground\" />\n )}\n <h2 className=\"min-w-0 shrink truncate text-base font-semibold\" title={node.name}>\n {node.name}\n </h2>\n {node.framework && (\n <span className=\"inline-flex shrink-0 items-center gap-1 rounded bg-muted px-1.5 py-0.5 text-xs text-muted-foreground\">\n <ToolIcon tool={toolKeyFor(node)} className=\"text-sm\" />\n {node.framework}\n </span>\n )}\n {node.duration ? (\n <span className=\"inline-flex shrink-0 items-center gap-1 text-xs text-muted-foreground\">\n <Icon icon={UiClock} className=\"text-xs\" />\n {formatTestDuration(node.duration)}\n </span>\n ) : null}\n {location && (\n <span\n className=\"min-w-0 shrink-[100] truncate font-mono text-xs text-muted-foreground\"\n title={location}\n >\n {location}\n </span>\n )}\n <div className=\"ml-auto flex shrink-0 items-center gap-1\">\n {attemptChooser}\n {actions}\n <CopyDetailsButton node={node} />\n {canRerun && (\n <Button\n size=\"sm\"\n disabled={runner.busy.rerun}\n onClick={() => runner.onRerun!(actionNode)}\n title=\"Rerun this test or subtree\"\n >\n <Icon icon={UiRefresh} className=\"mr-1 text-sm\" />\n {runner.busy.rerun ? \"Running...\" : \"Rerun\"}\n </Button>\n )}\n {canStop && (\n <Button\n size=\"sm\"\n variant=\"destructive\"\n disabled={runner.busy.stop}\n onClick={() => runner.onStop!(actionNode)}\n title=\"Stop this running task\"\n >\n <Icon icon={UiStop} className=\"mr-1 text-sm\" />\n {runner.busy.stop ? \"Stopping...\" : \"Stop\"}\n </Button>\n )}\n </div>\n </div>\n );\n}\n\n/**\n * The right pane. Resolves the node's adapter for body / tabs / header actions,\n * falling back to the built-in default body. Shows an empty state when nothing\n * is selected.\n */\nexport function TestDetailPanel() {\n const runner = useTestRunner();\n const selected = runner.selected;\n const [attemptSelection, setAttemptSelection] = useState<{ key: string; id: number } | null>(null);\n // Tab state is controlled when the host supplies activeTab (e.g. to mirror it\n // into the URL); otherwise the panel owns it. The render below tolerates an\n // unknown id by falling back to the built-in \"detail\" tab.\n const controlled = runner.activeTab !== undefined;\n const [internalTab, setInternalTab] = useState<string>(\"detail\");\n const activeTab = controlled ? runner.activeTab! : internalTab;\n const setActiveTab = (id: string) => {\n if (controlled) runner.onTabChange?.(id);\n else setInternalTab(id);\n };\n\n if (!selected) {\n return (\n <div className=\"flex h-full items-center justify-center text-sm text-muted-foreground\">\n <div className=\"text-center\">\n <Icon icon={UiClass} className=\"mb-2 block text-4xl\" />\n Select a test to view its details.\n </div>\n </div>\n );\n }\n\n const attempts = runner.adapters.resolveAttempts(selected, runner);\n const key = selected.task_id ?? selected.name;\n const attemptId = runner.activeAttempt ?? (attemptSelection?.key === key ? attemptSelection.id : undefined);\n const attempt = attempts.find((a) => a.id === attemptId) ?? attempts.at(-1);\n const node = attempts.length > 1 && attempt ? attempt.node : selected;\n const attemptChooser = attempts.length > 1 && attempt ? (\n <div className=\"w-44 shrink-0\">\n <Select aria-label=\"Attempt\" value={String(attempt.id)} className=\"h-7 text-xs\" onChange={(event) => {\n const id = Number(event.target.value);\n if (runner.onAttemptChange) runner.onAttemptChange(id);\n else setAttemptSelection({ key, id });\n }} options={attempts.map((a) => ({ value: String(a.id), label: `Attempt ${a.id}/${attempts.length} · ${a.status}${a.durationMs !== undefined ? ` · ${formatTestDuration(a.durationMs * 1e6)}` : \"\"}` }))} />\n </div>\n ) : null;\n\n const detailAdapter = runner.adapters.resolveDetail(node, runner);\n const actionAdapter = runner.adapters.resolveActions(selected, runner);\n const tabs = runner.adapters.resolveTabs(node, runner);\n const ownsScroll = runner.adapters.ownsScroll(node, runner);\n\n const body = detailAdapter?.renderDetail\n ? detailAdapter.renderDetail({ node, runner })\n : <DefaultDetailBody node={node} />;\n const actions = actionAdapter?.nodeActions?.({ node: selected, runner });\n\n // A size container, so log blocks can cap themselves at a share of the pane (cqh).\n const detailRegion = cn(\"min-h-0 flex-1 [container-type:size]\", !ownsScroll && \"overflow-y-auto\");\n\n // No extra tabs → just the body under the header.\n if (tabs.length === 0) {\n return (\n <div className=\"flex h-full min-h-0 flex-col\">\n <DetailHeader node={node} actionNode={selected} actions={actions} attemptChooser={attemptChooser} />\n <div className={detailRegion}>{body}</div>\n </div>\n );\n }\n\n const detailTab = { id: \"detail\", label: \"Detail\", render: () => body };\n const allTabs = [detailTab, ...tabs];\n const active = allTabs.find((t) => t.id === activeTab) ?? detailTab;\n\n return (\n <div className=\"flex h-full min-h-0 flex-col\">\n <DetailHeader node={node} actionNode={selected} actions={actions} attemptChooser={attemptChooser} />\n <div className=\"flex shrink-0 items-center gap-1 border-b border-border px-density-2 py-density-1\">\n {allTabs.map((t) => (\n <TabButton\n key={t.id}\n active={active.id === t.id}\n onClick={() => setActiveTab(t.id)}\n label={t.label}\n />\n ))}\n </div>\n <div className={detailRegion}>{active.render()}</div>\n </div>\n );\n}\n"],"names":["_a"],"mappings":"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"}
@@ -3,47 +3,43 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const jsxRuntime = require("react/jsx-runtime");
4
4
  const LogViewer = require("../LogViewer.cjs");
5
5
  const utils = require("../../lib/utils.cjs");
6
+ const Expectation = require("./Expectation.cjs");
6
7
  const status = require("./status.cjs");
7
- function Field({
8
- label,
9
- value,
10
- mono
11
- }) {
12
- if (!value) return null;
13
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
14
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-[10px] uppercase tracking-wide text-muted-foreground", children: label }),
15
- /* @__PURE__ */ jsxRuntime.jsx(
16
- "pre",
17
- {
18
- className: utils.cn(
19
- "whitespace-pre-wrap break-words rounded-md bg-muted p-2 text-xs",
20
- mono && "font-mono"
21
- ),
22
- children: value
23
- }
24
- )
25
- ] });
26
- }
27
8
  function TestFailureDetail({ failure }) {
28
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3 rounded-md border border-red-200 bg-red-50/50 p-3 dark:border-red-900 dark:bg-red-950/30", children: [
9
+ const hasExpectation = !!(failure.matcher || failure.expected || failure.actual || failure.location);
10
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
29
11
  failure.summary && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-red-700 dark:text-red-300", children: failure.summary }),
30
- /* @__PURE__ */ jsxRuntime.jsx(Field, { label: "Matcher", value: failure.matcher, mono: true }),
31
- /* @__PURE__ */ jsxRuntime.jsx(Field, { label: "Expected", value: failure.expected, mono: true }),
32
- /* @__PURE__ */ jsxRuntime.jsx(Field, { label: "Actual", value: failure.actual, mono: true }),
33
- /* @__PURE__ */ jsxRuntime.jsx(Field, { label: "Location", value: failure.location, mono: true }),
12
+ hasExpectation && /* @__PURE__ */ jsxRuntime.jsx(
13
+ Expectation.Expectation,
14
+ {
15
+ check: failure.matcher,
16
+ expected: failure.expected || void 0,
17
+ actual: failure.actual || void 0,
18
+ location: failure.location
19
+ }
20
+ ),
34
21
  failure.stack && /* @__PURE__ */ jsxRuntime.jsx(LogViewer.LogViewer, { logs: failure.stack, collapsedLines: 6 })
35
22
  ] });
36
23
  }
24
+ const OUTPUT_MAX_HEIGHT = "25cqh";
37
25
  function TestOutput({ node }) {
38
26
  if (!node.stdout && !node.stderr) return null;
39
27
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
40
28
  node.stdout && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
41
29
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-[10px] uppercase tracking-wide text-muted-foreground", children: "stdout" }),
42
- /* @__PURE__ */ jsxRuntime.jsx(LogViewer.LogViewer, { logs: node.stdout })
30
+ /* @__PURE__ */ jsxRuntime.jsx(LogViewer.LogViewer, { logs: node.stdout, variant: "terminal", maxHeight: OUTPUT_MAX_HEIGHT })
43
31
  ] }),
44
32
  node.stderr && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
45
33
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-[10px] uppercase tracking-wide text-muted-foreground", children: "stderr" }),
46
- /* @__PURE__ */ jsxRuntime.jsx(LogViewer.LogViewer, { logs: node.stderr, borderClass: "border-red-300 dark:border-red-900" })
34
+ /* @__PURE__ */ jsxRuntime.jsx(
35
+ LogViewer.LogViewer,
36
+ {
37
+ logs: node.stderr,
38
+ variant: "terminal",
39
+ maxHeight: OUTPUT_MAX_HEIGHT,
40
+ borderClass: "border-red-500/70"
41
+ }
42
+ )
47
43
  ] })
48
44
  ] });
49
45
  }
@@ -1 +1 @@
1
- {"version":3,"file":"TestFailureDetail.cjs","sources":["../../../src/data/test-runner/TestFailureDetail.tsx"],"sourcesContent":["import { LogViewer } from \"../LogViewer\";\nimport { cn } from \"../../lib/utils\";\nimport type { FailureDetail, Test, TestAttempt } from \"./types\";\nimport { formatTestDuration } from \"./status\";\n\nfunction Field({\n label,\n value,\n mono,\n}: {\n label: string;\n value: string | undefined;\n mono?: boolean;\n}) {\n if (!value) return null;\n return (\n <div className=\"space-y-1\">\n <div className=\"text-[10px] uppercase tracking-wide text-muted-foreground\">{label}</div>\n <pre\n className={cn(\n \"whitespace-pre-wrap break-words rounded-md bg-muted p-2 text-xs\",\n mono && \"font-mono\",\n )}\n >\n {value}\n </pre>\n </div>\n );\n}\n\n/** Renders a structured failure (expected/actual/matcher/location/stack). */\nexport function TestFailureDetail({ failure }: { failure: FailureDetail }) {\n return (\n <div className=\"space-y-3 rounded-md border border-red-200 bg-red-50/50 p-3 dark:border-red-900 dark:bg-red-950/30\">\n {failure.summary && (\n <p className=\"text-sm font-medium text-red-700 dark:text-red-300\">{failure.summary}</p>\n )}\n <Field label=\"Matcher\" value={failure.matcher} mono />\n <Field label=\"Expected\" value={failure.expected} mono />\n <Field label=\"Actual\" value={failure.actual} mono />\n <Field label=\"Location\" value={failure.location} mono />\n {failure.stack && <LogViewer logs={failure.stack} collapsedLines={6} />}\n </div>\n );\n}\n\n/** stdout / stderr blocks, each via the collapsible LogViewer. */\nexport function TestOutput({ node }: { node: Test }) {\n if (!node.stdout && !node.stderr) return null;\n return (\n <div className=\"space-y-3\">\n {node.stdout && (\n <div className=\"space-y-1\">\n <div className=\"text-[10px] uppercase tracking-wide text-muted-foreground\">stdout</div>\n <LogViewer logs={node.stdout} />\n </div>\n )}\n {node.stderr && (\n <div className=\"space-y-1\">\n <div className=\"text-[10px] uppercase tracking-wide text-muted-foreground\">stderr</div>\n <LogViewer logs={node.stderr} borderClass=\"border-red-300 dark:border-red-900\" />\n </div>\n )}\n </div>\n );\n}\n\nfunction attemptTone(a: TestAttempt): string {\n if (a.failed || a.timed_out) return \"text-red-600 dark:text-red-400\";\n if (a.passed) return \"text-green-600 dark:text-green-400\";\n return \"text-muted-foreground\";\n}\n\n/** Prior attempts list for flaky/reran tests. */\nexport function TestAttempts({ attempts }: { attempts: TestAttempt[] }) {\n if (attempts.length === 0) return null;\n return (\n <div className=\"space-y-1\">\n <div className=\"text-[10px] uppercase tracking-wide text-muted-foreground\">\n Attempts ({attempts.length})\n </div>\n <ul className=\"divide-y divide-border rounded-md border border-border text-xs\">\n {attempts.map((a) => (\n <li key={a.sequence} className=\"flex items-center justify-between gap-2 px-2 py-1\">\n <span className={cn(\"font-medium\", attemptTone(a))}>\n #{a.sequence} {a.run_kind ?? \"\"}\n </span>\n <span className=\"truncate text-muted-foreground\">{a.message}</span>\n {a.duration ? (\n <span className=\"shrink-0 text-muted-foreground\">{formatTestDuration(a.duration)}</span>\n ) : null}\n </li>\n ))}\n </ul>\n </div>\n );\n}\n"],"names":["jsxs","jsx","cn","LogViewer","formatTestDuration"],"mappings":"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"}
1
+ {"version":3,"file":"TestFailureDetail.cjs","sources":["../../../src/data/test-runner/TestFailureDetail.tsx"],"sourcesContent":["import { LogViewer } from \"../LogViewer\";\nimport { cn } from \"../../lib/utils\";\nimport { Expectation } from \"./Expectation\";\nimport type { FailureDetail, Test, TestAttempt } from \"./types\";\nimport { formatTestDuration } from \"./status\";\n\n/** Renders a structured failure: its summary, the expectation, and the stack. */\nexport function TestFailureDetail({ failure }: { failure: FailureDetail }) {\n const hasExpectation = !!(\n failure.matcher ||\n failure.expected ||\n failure.actual ||\n failure.location\n );\n return (\n <div className=\"space-y-2\">\n {failure.summary && (\n <p className=\"text-sm font-medium text-red-700 dark:text-red-300\">{failure.summary}</p>\n )}\n {hasExpectation && (\n <Expectation\n check={failure.matcher}\n expected={failure.expected || undefined}\n actual={failure.actual || undefined}\n location={failure.location}\n />\n )}\n {failure.stack && <LogViewer logs={failure.stack} collapsedLines={6} />}\n </div>\n );\n}\n\n// A quarter of the detail pane, which TestDetailPanel makes a size container.\nconst OUTPUT_MAX_HEIGHT = \"25cqh\";\n\n/** stdout / stderr as terminal blocks, each scrolling within a quarter of the detail pane. */\nexport function TestOutput({ node }: { node: Test }) {\n if (!node.stdout && !node.stderr) return null;\n return (\n <div className=\"space-y-3\">\n {node.stdout && (\n <div className=\"space-y-1\">\n <div className=\"text-[10px] uppercase tracking-wide text-muted-foreground\">stdout</div>\n <LogViewer logs={node.stdout} variant=\"terminal\" maxHeight={OUTPUT_MAX_HEIGHT} />\n </div>\n )}\n {node.stderr && (\n <div className=\"space-y-1\">\n <div className=\"text-[10px] uppercase tracking-wide text-muted-foreground\">stderr</div>\n <LogViewer\n logs={node.stderr}\n variant=\"terminal\"\n maxHeight={OUTPUT_MAX_HEIGHT}\n borderClass=\"border-red-500/70\"\n />\n </div>\n )}\n </div>\n );\n}\n\nfunction attemptTone(a: TestAttempt): string {\n if (a.failed || a.timed_out) return \"text-red-600 dark:text-red-400\";\n if (a.passed) return \"text-green-600 dark:text-green-400\";\n return \"text-muted-foreground\";\n}\n\n/** Prior attempts list for flaky/reran tests. */\nexport function TestAttempts({ attempts }: { attempts: TestAttempt[] }) {\n if (attempts.length === 0) return null;\n return (\n <div className=\"space-y-1\">\n <div className=\"text-[10px] uppercase tracking-wide text-muted-foreground\">\n Attempts ({attempts.length})\n </div>\n <ul className=\"divide-y divide-border rounded-md border border-border text-xs\">\n {attempts.map((a) => (\n <li key={a.sequence} className=\"flex items-center justify-between gap-2 px-2 py-1\">\n <span className={cn(\"font-medium\", attemptTone(a))}>\n #{a.sequence} {a.run_kind ?? \"\"}\n </span>\n <span className=\"truncate text-muted-foreground\">{a.message}</span>\n {a.duration ? (\n <span className=\"shrink-0 text-muted-foreground\">{formatTestDuration(a.duration)}</span>\n ) : null}\n </li>\n ))}\n </ul>\n </div>\n );\n}\n"],"names":["jsxs","jsx","Expectation","LogViewer","cn","formatTestDuration"],"mappings":";;;;;;;AAOO,SAAS,kBAAkB,EAAE,WAAuC;AACzE,QAAM,iBAAiB,CAAC,EACtB,QAAQ,WACR,QAAQ,YACR,QAAQ,UACR,QAAQ;AAEV,SACEA,2BAAAA,KAAC,OAAA,EAAI,WAAU,aACZ,UAAA;AAAA,IAAA,QAAQ,WACPC,2BAAAA,IAAC,KAAA,EAAE,WAAU,sDAAsD,kBAAQ,SAAQ;AAAA,IAEpF,kBACCA,2BAAAA;AAAAA,MAACC,YAAAA;AAAAA,MAAA;AAAA,QACC,OAAO,QAAQ;AAAA,QACf,UAAU,QAAQ,YAAY;AAAA,QAC9B,QAAQ,QAAQ,UAAU;AAAA,QAC1B,UAAU,QAAQ;AAAA,MAAA;AAAA,IAAA;AAAA,IAGrB,QAAQ,SAASD,2BAAAA,IAACE,qBAAA,EAAU,MAAM,QAAQ,OAAO,gBAAgB,EAAA,CAAG;AAAA,EAAA,GACvE;AAEJ;AAGA,MAAM,oBAAoB;AAGnB,SAAS,WAAW,EAAE,QAAwB;AACnD,MAAI,CAAC,KAAK,UAAU,CAAC,KAAK,OAAQ,QAAO;AACzC,SACEH,2BAAAA,KAAC,OAAA,EAAI,WAAU,aACZ,UAAA;AAAA,IAAA,KAAK,UACJA,gCAAC,OAAA,EAAI,WAAU,aACb,UAAA;AAAA,MAAAC,2BAAAA,IAAC,OAAA,EAAI,WAAU,6DAA4D,UAAA,UAAM;AAAA,MACjFA,+BAACE,UAAAA,aAAU,MAAM,KAAK,QAAQ,SAAQ,YAAW,WAAW,kBAAA,CAAmB;AAAA,IAAA,GACjF;AAAA,IAED,KAAK,UACJH,gCAAC,OAAA,EAAI,WAAU,aACb,UAAA;AAAA,MAAAC,2BAAAA,IAAC,OAAA,EAAI,WAAU,6DAA4D,UAAA,UAAM;AAAA,MACjFA,2BAAAA;AAAAA,QAACE,UAAAA;AAAAA,QAAA;AAAA,UACC,MAAM,KAAK;AAAA,UACX,SAAQ;AAAA,UACR,WAAW;AAAA,UACX,aAAY;AAAA,QAAA;AAAA,MAAA;AAAA,IACd,EAAA,CACF;AAAA,EAAA,GAEJ;AAEJ;AAEA,SAAS,YAAY,GAAwB;AAC3C,MAAI,EAAE,UAAU,EAAE,UAAW,QAAO;AACpC,MAAI,EAAE,OAAQ,QAAO;AACrB,SAAO;AACT;AAGO,SAAS,aAAa,EAAE,YAAyC;AACtE,MAAI,SAAS,WAAW,EAAG,QAAO;AAClC,SACEH,2BAAAA,KAAC,OAAA,EAAI,WAAU,aACb,UAAA;AAAA,IAAAA,2BAAAA,KAAC,OAAA,EAAI,WAAU,6DAA4D,UAAA;AAAA,MAAA;AAAA,MAC9D,SAAS;AAAA,MAAO;AAAA,IAAA,GAC7B;AAAA,IACAC,2BAAAA,IAAC,MAAA,EAAG,WAAU,kEACX,UAAA,SAAS,IAAI,CAAC,MACbD,2BAAAA,KAAC,MAAA,EAAoB,WAAU,qDAC7B,UAAA;AAAA,MAAAA,gCAAC,UAAK,WAAWI,MAAAA,GAAG,eAAe,YAAY,CAAC,CAAC,GAAG,UAAA;AAAA,QAAA;AAAA,QAChD,EAAE;AAAA,QAAS;AAAA,QAAE,EAAE,YAAY;AAAA,MAAA,GAC/B;AAAA,MACAH,2BAAAA,IAAC,QAAA,EAAK,WAAU,kCAAkC,YAAE,SAAQ;AAAA,MAC3D,EAAE,WACDA,+BAAC,QAAA,EAAK,WAAU,kCAAkC,UAAAI,OAAAA,mBAAmB,EAAE,QAAQ,EAAA,CAAE,IAC/E;AAAA,IAAA,KAPG,EAAE,QAQX,CACD,EAAA,CACH;AAAA,EAAA,GACF;AAEJ;;;;"}
@@ -1,9 +1,9 @@
1
1
  import { FailureDetail, Test, TestAttempt } from './types.js';
2
- /** Renders a structured failure (expected/actual/matcher/location/stack). */
2
+ /** Renders a structured failure: its summary, the expectation, and the stack. */
3
3
  export declare function TestFailureDetail({ failure }: {
4
4
  failure: FailureDetail;
5
5
  }): import("react").JSX.Element;
6
- /** stdout / stderr blocks, each via the collapsible LogViewer. */
6
+ /** stdout / stderr as terminal blocks, each scrolling within a quarter of the detail pane. */
7
7
  export declare function TestOutput({ node }: {
8
8
  node: Test;
9
9
  }): import("react").JSX.Element | null;
@@ -1 +1 @@
1
- {"version":3,"file":"TestFailureDetail.d.ts","sourceRoot":"","sources":["../../../src/data/test-runner/TestFailureDetail.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AA4BhE,6EAA6E;AAC7E,wBAAgB,iBAAiB,CAAC,EAAE,OAAO,EAAE,EAAE;IAAE,OAAO,EAAE,aAAa,CAAA;CAAE,+BAaxE;AAED,kEAAkE;AAClE,wBAAgB,UAAU,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,IAAI,CAAA;CAAE,sCAkBlD;AAQD,iDAAiD;AACjD,wBAAgB,YAAY,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,EAAE,WAAW,EAAE,CAAA;CAAE,sCAsBrE"}
1
+ {"version":3,"file":"TestFailureDetail.d.ts","sourceRoot":"","sources":["../../../src/data/test-runner/TestFailureDetail.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAGhE,iFAAiF;AACjF,wBAAgB,iBAAiB,CAAC,EAAE,OAAO,EAAE,EAAE;IAAE,OAAO,EAAE,aAAa,CAAA;CAAE,+BAuBxE;AAKD,8FAA8F;AAC9F,wBAAgB,UAAU,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,IAAI,CAAA;CAAE,sCAuBlD;AAQD,iDAAiD;AACjD,wBAAgB,YAAY,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,EAAE,WAAW,EAAE,CAAA;CAAE,sCAsBrE"}
@@ -1,47 +1,43 @@
1
1
  import { jsxs, jsx } from "react/jsx-runtime";
2
2
  import { LogViewer } from "../LogViewer.js";
3
3
  import { cn } from "../../lib/utils.js";
4
+ import { Expectation } from "./Expectation.js";
4
5
  import { formatTestDuration } from "./status.js";
5
- function Field({
6
- label,
7
- value,
8
- mono
9
- }) {
10
- if (!value) return null;
11
- return /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
12
- /* @__PURE__ */ jsx("div", { className: "text-[10px] uppercase tracking-wide text-muted-foreground", children: label }),
13
- /* @__PURE__ */ jsx(
14
- "pre",
15
- {
16
- className: cn(
17
- "whitespace-pre-wrap break-words rounded-md bg-muted p-2 text-xs",
18
- mono && "font-mono"
19
- ),
20
- children: value
21
- }
22
- )
23
- ] });
24
- }
25
6
  function TestFailureDetail({ failure }) {
26
- return /* @__PURE__ */ jsxs("div", { className: "space-y-3 rounded-md border border-red-200 bg-red-50/50 p-3 dark:border-red-900 dark:bg-red-950/30", children: [
7
+ const hasExpectation = !!(failure.matcher || failure.expected || failure.actual || failure.location);
8
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
27
9
  failure.summary && /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-red-700 dark:text-red-300", children: failure.summary }),
28
- /* @__PURE__ */ jsx(Field, { label: "Matcher", value: failure.matcher, mono: true }),
29
- /* @__PURE__ */ jsx(Field, { label: "Expected", value: failure.expected, mono: true }),
30
- /* @__PURE__ */ jsx(Field, { label: "Actual", value: failure.actual, mono: true }),
31
- /* @__PURE__ */ jsx(Field, { label: "Location", value: failure.location, mono: true }),
10
+ hasExpectation && /* @__PURE__ */ jsx(
11
+ Expectation,
12
+ {
13
+ check: failure.matcher,
14
+ expected: failure.expected || void 0,
15
+ actual: failure.actual || void 0,
16
+ location: failure.location
17
+ }
18
+ ),
32
19
  failure.stack && /* @__PURE__ */ jsx(LogViewer, { logs: failure.stack, collapsedLines: 6 })
33
20
  ] });
34
21
  }
22
+ const OUTPUT_MAX_HEIGHT = "25cqh";
35
23
  function TestOutput({ node }) {
36
24
  if (!node.stdout && !node.stderr) return null;
37
25
  return /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
38
26
  node.stdout && /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
39
27
  /* @__PURE__ */ jsx("div", { className: "text-[10px] uppercase tracking-wide text-muted-foreground", children: "stdout" }),
40
- /* @__PURE__ */ jsx(LogViewer, { logs: node.stdout })
28
+ /* @__PURE__ */ jsx(LogViewer, { logs: node.stdout, variant: "terminal", maxHeight: OUTPUT_MAX_HEIGHT })
41
29
  ] }),
42
30
  node.stderr && /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
43
31
  /* @__PURE__ */ jsx("div", { className: "text-[10px] uppercase tracking-wide text-muted-foreground", children: "stderr" }),
44
- /* @__PURE__ */ jsx(LogViewer, { logs: node.stderr, borderClass: "border-red-300 dark:border-red-900" })
32
+ /* @__PURE__ */ jsx(
33
+ LogViewer,
34
+ {
35
+ logs: node.stderr,
36
+ variant: "terminal",
37
+ maxHeight: OUTPUT_MAX_HEIGHT,
38
+ borderClass: "border-red-500/70"
39
+ }
40
+ )
45
41
  ] })
46
42
  ] });
47
43
  }
@@ -1 +1 @@
1
- {"version":3,"file":"TestFailureDetail.js","sources":["../../../src/data/test-runner/TestFailureDetail.tsx"],"sourcesContent":["import { LogViewer } from \"../LogViewer\";\nimport { cn } from \"../../lib/utils\";\nimport type { FailureDetail, Test, TestAttempt } from \"./types\";\nimport { formatTestDuration } from \"./status\";\n\nfunction Field({\n label,\n value,\n mono,\n}: {\n label: string;\n value: string | undefined;\n mono?: boolean;\n}) {\n if (!value) return null;\n return (\n <div className=\"space-y-1\">\n <div className=\"text-[10px] uppercase tracking-wide text-muted-foreground\">{label}</div>\n <pre\n className={cn(\n \"whitespace-pre-wrap break-words rounded-md bg-muted p-2 text-xs\",\n mono && \"font-mono\",\n )}\n >\n {value}\n </pre>\n </div>\n );\n}\n\n/** Renders a structured failure (expected/actual/matcher/location/stack). */\nexport function TestFailureDetail({ failure }: { failure: FailureDetail }) {\n return (\n <div className=\"space-y-3 rounded-md border border-red-200 bg-red-50/50 p-3 dark:border-red-900 dark:bg-red-950/30\">\n {failure.summary && (\n <p className=\"text-sm font-medium text-red-700 dark:text-red-300\">{failure.summary}</p>\n )}\n <Field label=\"Matcher\" value={failure.matcher} mono />\n <Field label=\"Expected\" value={failure.expected} mono />\n <Field label=\"Actual\" value={failure.actual} mono />\n <Field label=\"Location\" value={failure.location} mono />\n {failure.stack && <LogViewer logs={failure.stack} collapsedLines={6} />}\n </div>\n );\n}\n\n/** stdout / stderr blocks, each via the collapsible LogViewer. */\nexport function TestOutput({ node }: { node: Test }) {\n if (!node.stdout && !node.stderr) return null;\n return (\n <div className=\"space-y-3\">\n {node.stdout && (\n <div className=\"space-y-1\">\n <div className=\"text-[10px] uppercase tracking-wide text-muted-foreground\">stdout</div>\n <LogViewer logs={node.stdout} />\n </div>\n )}\n {node.stderr && (\n <div className=\"space-y-1\">\n <div className=\"text-[10px] uppercase tracking-wide text-muted-foreground\">stderr</div>\n <LogViewer logs={node.stderr} borderClass=\"border-red-300 dark:border-red-900\" />\n </div>\n )}\n </div>\n );\n}\n\nfunction attemptTone(a: TestAttempt): string {\n if (a.failed || a.timed_out) return \"text-red-600 dark:text-red-400\";\n if (a.passed) return \"text-green-600 dark:text-green-400\";\n return \"text-muted-foreground\";\n}\n\n/** Prior attempts list for flaky/reran tests. */\nexport function TestAttempts({ attempts }: { attempts: TestAttempt[] }) {\n if (attempts.length === 0) return null;\n return (\n <div className=\"space-y-1\">\n <div className=\"text-[10px] uppercase tracking-wide text-muted-foreground\">\n Attempts ({attempts.length})\n </div>\n <ul className=\"divide-y divide-border rounded-md border border-border text-xs\">\n {attempts.map((a) => (\n <li key={a.sequence} className=\"flex items-center justify-between gap-2 px-2 py-1\">\n <span className={cn(\"font-medium\", attemptTone(a))}>\n #{a.sequence} {a.run_kind ?? \"\"}\n </span>\n <span className=\"truncate text-muted-foreground\">{a.message}</span>\n {a.duration ? (\n <span className=\"shrink-0 text-muted-foreground\">{formatTestDuration(a.duration)}</span>\n ) : null}\n </li>\n ))}\n </ul>\n </div>\n );\n}\n"],"names":[],"mappings":";;;;AAKA,SAAS,MAAM;AAAA,EACb;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,MAAI,CAAC,MAAO,QAAO;AACnB,SACE,qBAAC,OAAA,EAAI,WAAU,aACb,UAAA;AAAA,IAAA,oBAAC,OAAA,EAAI,WAAU,6DAA6D,UAAA,OAAM;AAAA,IAClF;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAW;AAAA,UACT;AAAA,UACA,QAAQ;AAAA,QAAA;AAAA,QAGT,UAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EACH,GACF;AAEJ;AAGO,SAAS,kBAAkB,EAAE,WAAuC;AACzE,SACE,qBAAC,OAAA,EAAI,WAAU,sGACZ,UAAA;AAAA,IAAA,QAAQ,WACP,oBAAC,KAAA,EAAE,WAAU,sDAAsD,kBAAQ,SAAQ;AAAA,IAErF,oBAAC,SAAM,OAAM,WAAU,OAAO,QAAQ,SAAS,MAAI,MAAC;AAAA,IACpD,oBAAC,SAAM,OAAM,YAAW,OAAO,QAAQ,UAAU,MAAI,MAAC;AAAA,IACtD,oBAAC,SAAM,OAAM,UAAS,OAAO,QAAQ,QAAQ,MAAI,MAAC;AAAA,IAClD,oBAAC,SAAM,OAAM,YAAW,OAAO,QAAQ,UAAU,MAAI,MAAC;AAAA,IACrD,QAAQ,SAAS,oBAAC,WAAA,EAAU,MAAM,QAAQ,OAAO,gBAAgB,EAAA,CAAG;AAAA,EAAA,GACvE;AAEJ;AAGO,SAAS,WAAW,EAAE,QAAwB;AACnD,MAAI,CAAC,KAAK,UAAU,CAAC,KAAK,OAAQ,QAAO;AACzC,SACE,qBAAC,OAAA,EAAI,WAAU,aACZ,UAAA;AAAA,IAAA,KAAK,UACJ,qBAAC,OAAA,EAAI,WAAU,aACb,UAAA;AAAA,MAAA,oBAAC,OAAA,EAAI,WAAU,6DAA4D,UAAA,UAAM;AAAA,MACjF,oBAAC,WAAA,EAAU,MAAM,KAAK,OAAA,CAAQ;AAAA,IAAA,GAChC;AAAA,IAED,KAAK,UACJ,qBAAC,OAAA,EAAI,WAAU,aACb,UAAA;AAAA,MAAA,oBAAC,OAAA,EAAI,WAAU,6DAA4D,UAAA,UAAM;AAAA,0BAChF,WAAA,EAAU,MAAM,KAAK,QAAQ,aAAY,qCAAA,CAAqC;AAAA,IAAA,EAAA,CACjF;AAAA,EAAA,GAEJ;AAEJ;AAEA,SAAS,YAAY,GAAwB;AAC3C,MAAI,EAAE,UAAU,EAAE,UAAW,QAAO;AACpC,MAAI,EAAE,OAAQ,QAAO;AACrB,SAAO;AACT;AAGO,SAAS,aAAa,EAAE,YAAyC;AACtE,MAAI,SAAS,WAAW,EAAG,QAAO;AAClC,SACE,qBAAC,OAAA,EAAI,WAAU,aACb,UAAA;AAAA,IAAA,qBAAC,OAAA,EAAI,WAAU,6DAA4D,UAAA;AAAA,MAAA;AAAA,MAC9D,SAAS;AAAA,MAAO;AAAA,IAAA,GAC7B;AAAA,IACA,oBAAC,MAAA,EAAG,WAAU,kEACX,UAAA,SAAS,IAAI,CAAC,MACb,qBAAC,MAAA,EAAoB,WAAU,qDAC7B,UAAA;AAAA,MAAA,qBAAC,UAAK,WAAW,GAAG,eAAe,YAAY,CAAC,CAAC,GAAG,UAAA;AAAA,QAAA;AAAA,QAChD,EAAE;AAAA,QAAS;AAAA,QAAE,EAAE,YAAY;AAAA,MAAA,GAC/B;AAAA,MACA,oBAAC,QAAA,EAAK,WAAU,kCAAkC,YAAE,SAAQ;AAAA,MAC3D,EAAE,WACD,oBAAC,QAAA,EAAK,WAAU,kCAAkC,UAAA,mBAAmB,EAAE,QAAQ,EAAA,CAAE,IAC/E;AAAA,IAAA,KAPG,EAAE,QAQX,CACD,EAAA,CACH;AAAA,EAAA,GACF;AAEJ;"}
1
+ {"version":3,"file":"TestFailureDetail.js","sources":["../../../src/data/test-runner/TestFailureDetail.tsx"],"sourcesContent":["import { LogViewer } from \"../LogViewer\";\nimport { cn } from \"../../lib/utils\";\nimport { Expectation } from \"./Expectation\";\nimport type { FailureDetail, Test, TestAttempt } from \"./types\";\nimport { formatTestDuration } from \"./status\";\n\n/** Renders a structured failure: its summary, the expectation, and the stack. */\nexport function TestFailureDetail({ failure }: { failure: FailureDetail }) {\n const hasExpectation = !!(\n failure.matcher ||\n failure.expected ||\n failure.actual ||\n failure.location\n );\n return (\n <div className=\"space-y-2\">\n {failure.summary && (\n <p className=\"text-sm font-medium text-red-700 dark:text-red-300\">{failure.summary}</p>\n )}\n {hasExpectation && (\n <Expectation\n check={failure.matcher}\n expected={failure.expected || undefined}\n actual={failure.actual || undefined}\n location={failure.location}\n />\n )}\n {failure.stack && <LogViewer logs={failure.stack} collapsedLines={6} />}\n </div>\n );\n}\n\n// A quarter of the detail pane, which TestDetailPanel makes a size container.\nconst OUTPUT_MAX_HEIGHT = \"25cqh\";\n\n/** stdout / stderr as terminal blocks, each scrolling within a quarter of the detail pane. */\nexport function TestOutput({ node }: { node: Test }) {\n if (!node.stdout && !node.stderr) return null;\n return (\n <div className=\"space-y-3\">\n {node.stdout && (\n <div className=\"space-y-1\">\n <div className=\"text-[10px] uppercase tracking-wide text-muted-foreground\">stdout</div>\n <LogViewer logs={node.stdout} variant=\"terminal\" maxHeight={OUTPUT_MAX_HEIGHT} />\n </div>\n )}\n {node.stderr && (\n <div className=\"space-y-1\">\n <div className=\"text-[10px] uppercase tracking-wide text-muted-foreground\">stderr</div>\n <LogViewer\n logs={node.stderr}\n variant=\"terminal\"\n maxHeight={OUTPUT_MAX_HEIGHT}\n borderClass=\"border-red-500/70\"\n />\n </div>\n )}\n </div>\n );\n}\n\nfunction attemptTone(a: TestAttempt): string {\n if (a.failed || a.timed_out) return \"text-red-600 dark:text-red-400\";\n if (a.passed) return \"text-green-600 dark:text-green-400\";\n return \"text-muted-foreground\";\n}\n\n/** Prior attempts list for flaky/reran tests. */\nexport function TestAttempts({ attempts }: { attempts: TestAttempt[] }) {\n if (attempts.length === 0) return null;\n return (\n <div className=\"space-y-1\">\n <div className=\"text-[10px] uppercase tracking-wide text-muted-foreground\">\n Attempts ({attempts.length})\n </div>\n <ul className=\"divide-y divide-border rounded-md border border-border text-xs\">\n {attempts.map((a) => (\n <li key={a.sequence} className=\"flex items-center justify-between gap-2 px-2 py-1\">\n <span className={cn(\"font-medium\", attemptTone(a))}>\n #{a.sequence} {a.run_kind ?? \"\"}\n </span>\n <span className=\"truncate text-muted-foreground\">{a.message}</span>\n {a.duration ? (\n <span className=\"shrink-0 text-muted-foreground\">{formatTestDuration(a.duration)}</span>\n ) : null}\n </li>\n ))}\n </ul>\n </div>\n );\n}\n"],"names":[],"mappings":";;;;;AAOO,SAAS,kBAAkB,EAAE,WAAuC;AACzE,QAAM,iBAAiB,CAAC,EACtB,QAAQ,WACR,QAAQ,YACR,QAAQ,UACR,QAAQ;AAEV,SACE,qBAAC,OAAA,EAAI,WAAU,aACZ,UAAA;AAAA,IAAA,QAAQ,WACP,oBAAC,KAAA,EAAE,WAAU,sDAAsD,kBAAQ,SAAQ;AAAA,IAEpF,kBACC;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,OAAO,QAAQ;AAAA,QACf,UAAU,QAAQ,YAAY;AAAA,QAC9B,QAAQ,QAAQ,UAAU;AAAA,QAC1B,UAAU,QAAQ;AAAA,MAAA;AAAA,IAAA;AAAA,IAGrB,QAAQ,SAAS,oBAAC,WAAA,EAAU,MAAM,QAAQ,OAAO,gBAAgB,EAAA,CAAG;AAAA,EAAA,GACvE;AAEJ;AAGA,MAAM,oBAAoB;AAGnB,SAAS,WAAW,EAAE,QAAwB;AACnD,MAAI,CAAC,KAAK,UAAU,CAAC,KAAK,OAAQ,QAAO;AACzC,SACE,qBAAC,OAAA,EAAI,WAAU,aACZ,UAAA;AAAA,IAAA,KAAK,UACJ,qBAAC,OAAA,EAAI,WAAU,aACb,UAAA;AAAA,MAAA,oBAAC,OAAA,EAAI,WAAU,6DAA4D,UAAA,UAAM;AAAA,MACjF,oBAAC,aAAU,MAAM,KAAK,QAAQ,SAAQ,YAAW,WAAW,kBAAA,CAAmB;AAAA,IAAA,GACjF;AAAA,IAED,KAAK,UACJ,qBAAC,OAAA,EAAI,WAAU,aACb,UAAA;AAAA,MAAA,oBAAC,OAAA,EAAI,WAAU,6DAA4D,UAAA,UAAM;AAAA,MACjF;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,MAAM,KAAK;AAAA,UACX,SAAQ;AAAA,UACR,WAAW;AAAA,UACX,aAAY;AAAA,QAAA;AAAA,MAAA;AAAA,IACd,EAAA,CACF;AAAA,EAAA,GAEJ;AAEJ;AAEA,SAAS,YAAY,GAAwB;AAC3C,MAAI,EAAE,UAAU,EAAE,UAAW,QAAO;AACpC,MAAI,EAAE,OAAQ,QAAO;AACrB,SAAO;AACT;AAGO,SAAS,aAAa,EAAE,YAAyC;AACtE,MAAI,SAAS,WAAW,EAAG,QAAO;AAClC,SACE,qBAAC,OAAA,EAAI,WAAU,aACb,UAAA;AAAA,IAAA,qBAAC,OAAA,EAAI,WAAU,6DAA4D,UAAA;AAAA,MAAA;AAAA,MAC9D,SAAS;AAAA,MAAO;AAAA,IAAA,GAC7B;AAAA,IACA,oBAAC,MAAA,EAAG,WAAU,kEACX,UAAA,SAAS,IAAI,CAAC,MACb,qBAAC,MAAA,EAAoB,WAAU,qDAC7B,UAAA;AAAA,MAAA,qBAAC,UAAK,WAAW,GAAG,eAAe,YAAY,CAAC,CAAC,GAAG,UAAA;AAAA,QAAA;AAAA,QAChD,EAAE;AAAA,QAAS;AAAA,QAAE,EAAE,YAAY;AAAA,MAAA,GAC/B;AAAA,MACA,oBAAC,QAAA,EAAK,WAAU,kCAAkC,YAAE,SAAQ;AAAA,MAC3D,EAAE,WACD,oBAAC,QAAA,EAAK,WAAU,kCAAkC,UAAA,mBAAmB,EAAE,QAAQ,EAAA,CAAE,IAC/E;AAAA,IAAA,KAPG,EAAE,QAQX,CACD,EAAA,CACH;AAAA,EAAA,GACF;AAEJ;"}
@@ -1,36 +1,62 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const jsxRuntime = require("react/jsx-runtime");
4
- const Icon = require("../Icon.cjs");
5
4
  const utils = require("../../lib/utils.cjs");
6
- const frameworkIcon = require("./frameworkIcon.cjs");
5
+ const Icon = require("../Icon.cjs");
6
+ const DropdownMenu = require("../../overlay/DropdownMenu.cjs");
7
+ const filterBarContext = require("../../components/filter-bar-context.cjs");
8
+ const filterBarMulti = require("../../components/filter-bar-multi.cjs");
9
+ const filterBarFieldUtils = require("../../components/filter-bar-field-utils.cjs");
10
+ const MarkIcons = require("./MarkIcons.cjs");
11
+ const marks = require("./marks.cjs");
7
12
  const status = require("./status.cjs");
8
- const filterState = require("./filterState.cjs");
9
- const UiAdd = require("../../icons/components/UiAdd.cjs");
10
- const UiRemove = require("../../icons/components/UiRemove.cjs");
11
- const STATUS_BADGES = {
12
- failed: "bg-red-500",
13
- warned: "bg-amber-400",
14
- timedout: "bg-amber-500",
15
- passed: "bg-green-500",
16
- skipped: "bg-yellow-400",
17
- running: "bg-blue-500",
18
- pending: "bg-muted-foreground",
19
- total: "bg-muted-foreground"
20
- };
21
- const STATUS_DEFS = status.STATUS_LABELS.map((d) => ({
22
- ...d,
23
- badge: STATUS_BADGES[d.key]
24
- }));
25
- function pillClass(mode) {
26
- if (mode === "include") return "bg-accent border-border font-medium text-foreground";
27
- if (mode === "exclude") return "bg-foreground text-background border-foreground font-medium";
28
- return "border-border text-muted-foreground hover:bg-accent";
29
- }
30
- function StateMarker({ mode }) {
31
- if (mode === "include") return /* @__PURE__ */ jsxRuntime.jsx(Icon.Icon, { icon: UiAdd.UiAdd, className: "text-xs" });
32
- if (mode === "exclude") return /* @__PURE__ */ jsxRuntime.jsx(Icon.Icon, { icon: UiRemove.UiRemove, className: "text-xs" });
33
- return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "h-2 w-2 rounded-full bg-current opacity-30", "aria-hidden": true });
13
+ const UiChevronDown = require("../../icons/components/UiChevronDown.cjs");
14
+ const COMMIT_IMMEDIATELY = { autoSubmit: false, compact: false };
15
+ function Facet({
16
+ label,
17
+ options,
18
+ state,
19
+ onChange
20
+ }) {
21
+ const value = Object.fromEntries(state);
22
+ const active = state.size > 0;
23
+ return /* @__PURE__ */ jsxRuntime.jsx(
24
+ DropdownMenu.DropdownMenu,
25
+ {
26
+ align: "right",
27
+ menuLabel: label,
28
+ menuClassName: "p-2",
29
+ trigger: /* @__PURE__ */ jsxRuntime.jsxs(
30
+ "span",
31
+ {
32
+ role: "button",
33
+ tabIndex: 0,
34
+ className: utils.cn(
35
+ "inline-flex h-6 items-center gap-0.5 rounded px-1.5 text-xs transition-colors",
36
+ active ? "bg-muted font-medium text-foreground" : "text-muted-foreground hover:bg-muted/60 hover:text-foreground"
37
+ ),
38
+ children: [
39
+ filterBarFieldUtils.summarizeMultiFilter(label, value),
40
+ /* @__PURE__ */ jsxRuntime.jsx(Icon.Icon, { icon: UiChevronDown.UiChevronDown, className: "text-[10px] opacity-60" })
41
+ ]
42
+ }
43
+ ),
44
+ children: () => /* @__PURE__ */ jsxRuntime.jsx(filterBarContext.FilterBarContext.Provider, { value: COMMIT_IMMEDIATELY, children: /* @__PURE__ */ jsxRuntime.jsx(
45
+ filterBarMulti.MultiFilterPanel,
46
+ {
47
+ chrome: "embedded",
48
+ filter: {
49
+ key: label,
50
+ kind: "multi",
51
+ label,
52
+ options,
53
+ value,
54
+ onChange: (v) => onChange(new Map(Object.entries(v)))
55
+ }
56
+ }
57
+ ) })
58
+ }
59
+ );
34
60
  }
35
61
  function TestFilterBar({
36
62
  filters,
@@ -39,72 +65,40 @@ function TestFilterBar({
39
65
  frameworks,
40
66
  className
41
67
  }) {
42
- const hasActive = filters.status.size > 0 || filters.framework.size > 0;
43
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: utils.cn("flex flex-wrap items-center gap-1.5", className), children: [
44
- STATUS_DEFS.map((sf) => {
45
- const count = counts[sf.key];
46
- if (count === 0) return null;
47
- const mode = filters.status.get(sf.key);
48
- return /* @__PURE__ */ jsxRuntime.jsxs(
49
- "button",
50
- {
51
- type: "button",
52
- className: utils.cn(
53
- "inline-flex items-center gap-1.5 rounded-full border px-2 py-0.5 text-xs transition-colors",
54
- pillClass(mode)
55
- ),
56
- onClick: () => onChange({ ...filters, status: filterState.cycleFilterState(filters.status, sf.key) }),
57
- title: `${sf.label}: ${mode ?? "neutral"}`,
58
- children: [
59
- /* @__PURE__ */ jsxRuntime.jsx(
60
- "span",
61
- {
62
- className: utils.cn(
63
- "inline-flex h-4 min-w-4 items-center justify-center rounded-full px-1 text-[10px] font-bold text-white",
64
- sf.badge
65
- ),
66
- children: status.formatCount(count)
67
- }
68
- ),
69
- /* @__PURE__ */ jsxRuntime.jsx(StateMarker, { mode }),
70
- sf.label
71
- ]
72
- },
73
- sf.key
74
- );
75
- }),
76
- frameworks.length > 1 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
77
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "mx-0.5 text-border", children: "|" }),
78
- frameworks.map((fw) => {
79
- const icon = frameworkIcon.frameworkIcon(fw);
80
- const mode = filters.framework.get(fw);
81
- return /* @__PURE__ */ jsxRuntime.jsxs(
82
- "button",
83
- {
84
- type: "button",
85
- className: utils.cn(
86
- "inline-flex items-center gap-1 rounded-full border px-2 py-0.5 text-xs transition-colors",
87
- pillClass(mode)
88
- ),
89
- onClick: () => onChange({ ...filters, framework: filterState.cycleFilterState(filters.framework, fw) }),
90
- title: `${fw}: ${mode ?? "neutral"}`,
91
- children: [
92
- /* @__PURE__ */ jsxRuntime.jsx(StateMarker, { mode }),
93
- icon && /* @__PURE__ */ jsxRuntime.jsx(Icon.Icon, { icon, className: "text-sm" }),
94
- fw
95
- ]
96
- },
97
- fw
98
- );
99
- })
100
- ] }),
101
- hasActive && /* @__PURE__ */ jsxRuntime.jsx(
102
- "button",
68
+ const statusOptions = status.STATUS_LABELS.filter((d) => counts[d.key] > 0).map(
69
+ (d) => ({
70
+ value: d.key,
71
+ label: d.label,
72
+ icon: /* @__PURE__ */ jsxRuntime.jsx(MarkIcons.OutcomeIcon, { outcome: d.key }),
73
+ count: counts[d.key]
74
+ })
75
+ );
76
+ const toolOptions = frameworks.map((fw) => {
77
+ var _a;
78
+ return {
79
+ value: fw,
80
+ label: ((_a = marks.toolMark(fw)) == null ? void 0 : _a.label) ?? fw,
81
+ title: fw,
82
+ icon: /* @__PURE__ */ jsxRuntime.jsx(MarkIcons.ToolIcon, { tool: fw })
83
+ };
84
+ });
85
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: utils.cn("flex items-center gap-0.5", className), children: [
86
+ /* @__PURE__ */ jsxRuntime.jsx(
87
+ Facet,
88
+ {
89
+ label: "Status",
90
+ options: statusOptions,
91
+ state: filters.status,
92
+ onChange: (status2) => onChange({ ...filters, status: status2 })
93
+ }
94
+ ),
95
+ frameworks.length > 1 && /* @__PURE__ */ jsxRuntime.jsx(
96
+ Facet,
103
97
  {
104
- type: "button",
105
- className: "ml-1 text-xs text-muted-foreground hover:text-foreground",
106
- onClick: () => onChange({ status: /* @__PURE__ */ new Map(), framework: /* @__PURE__ */ new Map() }),
107
- children: "Clear"
98
+ label: "Tool",
99
+ options: toolOptions,
100
+ state: filters.framework,
101
+ onChange: (framework) => onChange({ ...filters, framework })
108
102
  }
109
103
  )
110
104
  ] });
@@ -1 +1 @@
1
- {"version":3,"file":"TestFilterBar.cjs","sources":["../../../src/data/test-runner/TestFilterBar.tsx"],"sourcesContent":["import { Icon } from \"../Icon\";\nimport { cn } from \"../../lib/utils\";\nimport { UiAdd, UiRemove } from \"../../icons\";\nimport { frameworkIcon } from \"./frameworkIcon\";\nimport { formatCount, STATUS_LABELS, type StatusCounts } from \"./status\";\nimport { cycleFilterState, type FilterMode, type TestFilters } from \"./filterState\";\n\nexport type TestFilterBarProps = {\n filters: TestFilters;\n onChange: (next: TestFilters) => void;\n counts: StatusCounts;\n frameworks: string[];\n className?: string;\n};\n\ntype StatusDef = { key: keyof StatusCounts; label: string; badge: string };\n\nconst STATUS_BADGES: Record<keyof StatusCounts, string> = {\n failed: \"bg-red-500\",\n warned: \"bg-amber-400\",\n timedout: \"bg-amber-500\",\n passed: \"bg-green-500\",\n skipped: \"bg-yellow-400\",\n running: \"bg-blue-500\",\n pending: \"bg-muted-foreground\",\n total: \"bg-muted-foreground\",\n};\n\nconst STATUS_DEFS: StatusDef[] = STATUS_LABELS.map((d) => ({\n ...d,\n badge: STATUS_BADGES[d.key],\n}));\n\nfunction pillClass(mode: FilterMode | undefined): string {\n if (mode === \"include\") return \"bg-accent border-border font-medium text-foreground\";\n if (mode === \"exclude\") return \"bg-foreground text-background border-foreground font-medium\";\n return \"border-border text-muted-foreground hover:bg-accent\";\n}\n\nfunction StateMarker({ mode }: { mode: FilterMode | undefined }) {\n if (mode === \"include\") return <Icon icon={UiAdd} className=\"text-xs\" />;\n if (mode === \"exclude\") return <Icon icon={UiRemove} className=\"text-xs\" />;\n return <span className=\"h-2 w-2 rounded-full bg-current opacity-30\" aria-hidden />;\n}\n\n/**\n * Tri-state status + framework filter pills. Named TestFilterBar to avoid the\n * pre-existing generic `FilterBar` export in clicky-ui/components.\n */\nexport function TestFilterBar({\n filters,\n onChange,\n counts,\n frameworks,\n className,\n}: TestFilterBarProps) {\n const hasActive = filters.status.size > 0 || filters.framework.size > 0;\n\n return (\n <div className={cn(\"flex flex-wrap items-center gap-1.5\", className)}>\n {STATUS_DEFS.map((sf) => {\n const count = counts[sf.key];\n if (count === 0) return null;\n const mode = filters.status.get(sf.key);\n return (\n <button\n key={sf.key}\n type=\"button\"\n className={cn(\n \"inline-flex items-center gap-1.5 rounded-full border px-2 py-0.5 text-xs transition-colors\",\n pillClass(mode),\n )}\n onClick={() => onChange({ ...filters, status: cycleFilterState(filters.status, sf.key) })}\n title={`${sf.label}: ${mode ?? \"neutral\"}`}\n >\n <span\n className={cn(\n \"inline-flex h-4 min-w-4 items-center justify-center rounded-full px-1 text-[10px] font-bold text-white\",\n sf.badge,\n )}\n >\n {formatCount(count)}\n </span>\n <StateMarker mode={mode} />\n {sf.label}\n </button>\n );\n })}\n\n {frameworks.length > 1 && (\n <>\n <span className=\"mx-0.5 text-border\">|</span>\n {frameworks.map((fw) => {\n const icon = frameworkIcon(fw);\n const mode = filters.framework.get(fw);\n return (\n <button\n key={fw}\n type=\"button\"\n className={cn(\n \"inline-flex items-center gap-1 rounded-full border px-2 py-0.5 text-xs transition-colors\",\n pillClass(mode),\n )}\n onClick={() =>\n onChange({ ...filters, framework: cycleFilterState(filters.framework, fw) })\n }\n title={`${fw}: ${mode ?? \"neutral\"}`}\n >\n <StateMarker mode={mode} />\n {icon && <Icon icon={icon} className=\"text-sm\" />}\n {fw}\n </button>\n );\n })}\n </>\n )}\n\n {hasActive && (\n <button\n type=\"button\"\n className=\"ml-1 text-xs text-muted-foreground hover:text-foreground\"\n onClick={() => onChange({ status: new Map(), framework: new Map() })}\n >\n Clear\n </button>\n )}\n </div>\n );\n}\n"],"names":["STATUS_LABELS","jsx","Icon","UiAdd","UiRemove","cn","jsxs","cycleFilterState","Fragment","frameworkIcon"],"mappings":"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"}
1
+ {"version":3,"file":"TestFilterBar.cjs","sources":["../../../src/data/test-runner/TestFilterBar.tsx"],"sourcesContent":["import { cn } from \"../../lib/utils\";\nimport { Icon } from \"../Icon\";\nimport { UiChevronDown } from \"../../icons\";\nimport { DropdownMenu } from \"../../overlay/DropdownMenu\";\nimport { FilterBarContext } from \"../../components/filter-bar-context\";\nimport { MultiFilterPanel } from \"../../components/filter-bar-multi\";\nimport { summarizeMultiFilter } from \"../../components/filter-bar-field-utils\";\nimport type { MultiSelectOption } from \"../../components/MultiSelect\";\nimport { OutcomeIcon, ToolIcon } from \"./MarkIcons\";\nimport { toolMark } from \"./marks\";\nimport { STATUS_LABELS, type StatusCounts, type TestOutcome } from \"./status\";\nimport type { FilterMode, FilterState, TestFilters } from \"./filterState\";\n\nexport type TestFilterBarProps = {\n filters: TestFilters;\n onChange: (next: TestFilters) => void;\n counts: StatusCounts;\n frameworks: string[];\n className?: string;\n};\n\n// Picks commit straight away: the runner, not a form, owns the filter state.\nconst COMMIT_IMMEDIATELY = { autoSubmit: false, compact: false };\n\nfunction Facet({\n label,\n options,\n state,\n onChange,\n}: {\n label: string;\n options: MultiSelectOption[];\n state: FilterState<string>;\n onChange: (next: FilterState<string>) => void;\n}) {\n const value: Record<string, FilterMode> = Object.fromEntries(state);\n const active = state.size > 0;\n return (\n <DropdownMenu\n align=\"right\"\n menuLabel={label}\n menuClassName=\"p-2\"\n trigger={\n <span\n role=\"button\"\n tabIndex={0}\n className={cn(\n \"inline-flex h-6 items-center gap-0.5 rounded px-1.5 text-xs transition-colors\",\n active\n ? \"bg-muted font-medium text-foreground\"\n : \"text-muted-foreground hover:bg-muted/60 hover:text-foreground\",\n )}\n >\n {summarizeMultiFilter(label, value)}\n <Icon icon={UiChevronDown} className=\"text-[10px] opacity-60\" />\n </span>\n }\n >\n {() => (\n <FilterBarContext.Provider value={COMMIT_IMMEDIATELY}>\n <MultiFilterPanel\n chrome=\"embedded\"\n filter={{\n key: label,\n kind: \"multi\",\n label,\n options,\n value,\n onChange: (v) => onChange(new Map(Object.entries(v))),\n }}\n />\n </FilterBarContext.Provider>\n )}\n </DropdownMenu>\n );\n}\n\n/**\n * Status and tool facets as compact, muted menu triggers sized for the tree\n * toolbar; each opens a tri-state (include / exclude) option list. Named\n * TestFilterBar to avoid the generic `FilterBar` export in clicky-ui/components.\n */\nexport function TestFilterBar({\n filters,\n onChange,\n counts,\n frameworks,\n className,\n}: TestFilterBarProps) {\n const statusOptions: MultiSelectOption[] = STATUS_LABELS.filter((d) => counts[d.key] > 0).map(\n (d) => ({\n value: d.key,\n label: d.label,\n icon: <OutcomeIcon outcome={d.key as TestOutcome} />,\n count: counts[d.key],\n }),\n );\n const toolOptions: MultiSelectOption[] = frameworks.map((fw) => ({\n value: fw,\n label: toolMark(fw)?.label ?? fw,\n title: fw,\n icon: <ToolIcon tool={fw} />,\n }));\n\n return (\n <div className={cn(\"flex items-center gap-0.5\", className)}>\n <Facet\n label=\"Status\"\n options={statusOptions}\n state={filters.status}\n onChange={(status) => onChange({ ...filters, status })}\n />\n {frameworks.length > 1 && (\n <Facet\n label=\"Tool\"\n options={toolOptions}\n state={filters.framework}\n onChange={(framework) => onChange({ ...filters, framework })}\n />\n )}\n </div>\n );\n}\n"],"names":["jsx","DropdownMenu","jsxs","cn","summarizeMultiFilter","Icon","UiChevronDown","FilterBarContext","MultiFilterPanel","STATUS_LABELS","OutcomeIcon","toolMark","ToolIcon","status"],"mappings":";;;;;;;;;;;;;AAsBA,MAAM,qBAAqB,EAAE,YAAY,OAAO,SAAS,MAAA;AAEzD,SAAS,MAAM;AAAA,EACb;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAKG;AACD,QAAM,QAAoC,OAAO,YAAY,KAAK;AAClE,QAAM,SAAS,MAAM,OAAO;AAC5B,SACEA,2BAAAA;AAAAA,IAACC,aAAAA;AAAAA,IAAA;AAAA,MACC,OAAM;AAAA,MACN,WAAW;AAAA,MACX,eAAc;AAAA,MACd,SACEC,2BAAAA;AAAAA,QAAC;AAAA,QAAA;AAAA,UACC,MAAK;AAAA,UACL,UAAU;AAAA,UACV,WAAWC,MAAAA;AAAAA,YACT;AAAA,YACA,SACI,yCACA;AAAA,UAAA;AAAA,UAGL,UAAA;AAAA,YAAAC,oBAAAA,qBAAqB,OAAO,KAAK;AAAA,YAClCJ,2BAAAA,IAACK,KAAAA,MAAA,EAAK,MAAMC,cAAAA,eAAe,WAAU,yBAAA,CAAyB;AAAA,UAAA;AAAA,QAAA;AAAA,MAAA;AAAA,MAIjE,gBACCN,2BAAAA,IAACO,kCAAiB,UAAjB,EAA0B,OAAO,oBAChC,UAAAP,2BAAAA;AAAAA,QAACQ,eAAAA;AAAAA,QAAA;AAAA,UACC,QAAO;AAAA,UACP,QAAQ;AAAA,YACN,KAAK;AAAA,YACL,MAAM;AAAA,YACN;AAAA,YACA;AAAA,YACA;AAAA,YACA,UAAU,CAAC,MAAM,SAAS,IAAI,IAAI,OAAO,QAAQ,CAAC,CAAC,CAAC;AAAA,UAAA;AAAA,QACtD;AAAA,MAAA,EACF,CACF;AAAA,IAAA;AAAA,EAAA;AAIR;AAOO,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAuB;AACrB,QAAM,gBAAqCC,OAAAA,cAAc,OAAO,CAAC,MAAM,OAAO,EAAE,GAAG,IAAI,CAAC,EAAE;AAAA,IACxF,CAAC,OAAO;AAAA,MACN,OAAO,EAAE;AAAA,MACT,OAAO,EAAE;AAAA,MACT,MAAMT,2BAAAA,IAACU,UAAAA,aAAA,EAAY,SAAS,EAAE,KAAoB;AAAA,MAClD,OAAO,OAAO,EAAE,GAAG;AAAA,IAAA;AAAA,EACrB;AAEF,QAAM,cAAmC,WAAW,IAAI,CAAC,OAAA;;AAAQ;AAAA,MAC/D,OAAO;AAAA,MACP,SAAOC,WAAAA,SAAS,EAAE,MAAXA,mBAAc,UAAS;AAAA,MAC9B,OAAO;AAAA,MACP,MAAMX,2BAAAA,IAACY,UAAAA,UAAA,EAAS,MAAM,GAAA,CAAI;AAAA,IAAA;AAAA,GAC1B;AAEF,yCACG,OAAA,EAAI,WAAWT,MAAAA,GAAG,6BAA6B,SAAS,GACvD,UAAA;AAAA,IAAAH,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC,OAAM;AAAA,QACN,SAAS;AAAA,QACT,OAAO,QAAQ;AAAA,QACf,UAAU,CAACa,YAAW,SAAS,EAAE,GAAG,SAAS,QAAAA,SAAQ;AAAA,MAAA;AAAA,IAAA;AAAA,IAEtD,WAAW,SAAS,KACnBb,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC,OAAM;AAAA,QACN,SAAS;AAAA,QACT,OAAO,QAAQ;AAAA,QACf,UAAU,CAAC,cAAc,SAAS,EAAE,GAAG,SAAS,WAAW;AAAA,MAAA;AAAA,IAAA;AAAA,EAC7D,GAEJ;AAEJ;;"}
@@ -8,8 +8,9 @@ export type TestFilterBarProps = {
8
8
  className?: string;
9
9
  };
10
10
  /**
11
- * Tri-state status + framework filter pills. Named TestFilterBar to avoid the
12
- * pre-existing generic `FilterBar` export in clicky-ui/components.
11
+ * Status and tool facets as compact, muted menu triggers sized for the tree
12
+ * toolbar; each opens a tri-state (include / exclude) option list. Named
13
+ * TestFilterBar to avoid the generic `FilterBar` export in clicky-ui/components.
13
14
  */
14
15
  export declare function TestFilterBar({ filters, onChange, counts, frameworks, className, }: TestFilterBarProps): import("react").JSX.Element;
15
16
  //# sourceMappingURL=TestFilterBar.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"TestFilterBar.d.ts","sourceRoot":"","sources":["../../../src/data/test-runner/TestFilterBar.tsx"],"names":[],"mappings":"AAIA,OAAO,EAA8B,KAAK,YAAY,EAAE,MAAM,UAAU,CAAC;AACzE,OAAO,EAAqC,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AAEpF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,OAAO,EAAE,WAAW,CAAC;IACrB,QAAQ,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,CAAC;IACtC,MAAM,EAAE,YAAY,CAAC;IACrB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAgCF;;;GAGG;AACH,wBAAgB,aAAa,CAAC,EAC5B,OAAO,EACP,QAAQ,EACR,MAAM,EACN,UAAU,EACV,SAAS,GACV,EAAE,kBAAkB,+BAyEpB"}
1
+ {"version":3,"file":"TestFilterBar.d.ts","sourceRoot":"","sources":["../../../src/data/test-runner/TestFilterBar.tsx"],"names":[],"mappings":"AAUA,OAAO,EAAiB,KAAK,YAAY,EAAoB,MAAM,UAAU,CAAC;AAC9E,OAAO,KAAK,EAA2B,WAAW,EAAE,MAAM,eAAe,CAAC;AAE1E,MAAM,MAAM,kBAAkB,GAAG;IAC/B,OAAO,EAAE,WAAW,CAAC;IACrB,QAAQ,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,CAAC;IACtC,MAAM,EAAE,YAAY,CAAC;IACrB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AA0DF;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,EAC5B,OAAO,EACP,QAAQ,EACR,MAAM,EACN,UAAU,EACV,SAAS,GACV,EAAE,kBAAkB,+BAkCpB"}