@flanksource/clicky-ui 0.3.59 → 0.3.60

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 (428) hide show
  1. package/NOTICE.md +58 -0
  2. package/dist/data/Clicky.cjs +2 -1
  3. package/dist/data/Clicky.cjs.map +1 -1
  4. package/dist/data/Clicky.d.ts +2 -0
  5. package/dist/data/Clicky.d.ts.map +1 -1
  6. package/dist/data/Clicky.js +2 -1
  7. package/dist/data/Clicky.js.map +1 -1
  8. package/dist/data/PromptBanner.model.cjs +10 -0
  9. package/dist/data/PromptBanner.model.cjs.map +1 -1
  10. package/dist/data/PromptBanner.model.d.ts +2 -0
  11. package/dist/data/PromptBanner.model.d.ts.map +1 -1
  12. package/dist/data/PromptBanner.model.js +10 -1
  13. package/dist/data/PromptBanner.model.js.map +1 -1
  14. package/dist/data/PromptDialog.cjs +16 -49
  15. package/dist/data/PromptDialog.cjs.map +1 -1
  16. package/dist/data/PromptDialog.d.ts +7 -1
  17. package/dist/data/PromptDialog.d.ts.map +1 -1
  18. package/dist/data/PromptDialog.js +17 -50
  19. package/dist/data/PromptDialog.js.map +1 -1
  20. package/dist/data/PromptForm.cjs +79 -0
  21. package/dist/data/PromptForm.cjs.map +1 -0
  22. package/dist/data/PromptForm.d.ts +26 -0
  23. package/dist/data/PromptForm.d.ts.map +1 -0
  24. package/dist/data/PromptForm.js +79 -0
  25. package/dist/data/PromptForm.js.map +1 -0
  26. package/dist/data/PromptIndicator.cjs +82 -0
  27. package/dist/data/PromptIndicator.cjs.map +1 -0
  28. package/dist/data/PromptIndicator.d.ts +19 -0
  29. package/dist/data/PromptIndicator.d.ts.map +1 -0
  30. package/dist/data/PromptIndicator.js +82 -0
  31. package/dist/data/PromptIndicator.js.map +1 -0
  32. package/dist/data/PromptList.cjs +67 -0
  33. package/dist/data/PromptList.cjs.map +1 -0
  34. package/dist/data/PromptList.d.ts +13 -0
  35. package/dist/data/PromptList.d.ts.map +1 -0
  36. package/dist/data/PromptList.js +67 -0
  37. package/dist/data/PromptList.js.map +1 -0
  38. package/dist/data/git/GitChangeList.cjs +11 -4
  39. package/dist/data/git/GitChangeList.cjs.map +1 -1
  40. package/dist/data/git/GitChangeList.d.ts +2 -35
  41. package/dist/data/git/GitChangeList.d.ts.map +1 -1
  42. package/dist/data/git/GitChangeList.js +11 -4
  43. package/dist/data/git/GitChangeList.js.map +1 -1
  44. package/dist/data/git/GitLink.cjs +13 -0
  45. package/dist/data/git/GitLink.cjs.map +1 -0
  46. package/dist/data/git/GitLink.d.ts +8 -0
  47. package/dist/data/git/GitLink.d.ts.map +1 -0
  48. package/dist/data/git/GitLink.js +13 -0
  49. package/dist/data/git/GitLink.js.map +1 -0
  50. package/dist/data/git/git-links.cjs +54 -0
  51. package/dist/data/git/git-links.cjs.map +1 -0
  52. package/dist/data/git/git-links.d.ts +4 -0
  53. package/dist/data/git/git-links.d.ts.map +1 -0
  54. package/dist/data/git/git-links.js +53 -0
  55. package/dist/data/git/git-links.js.map +1 -0
  56. package/dist/data/git/index.d.ts +3 -0
  57. package/dist/data/git/index.d.ts.map +1 -1
  58. package/dist/data/git/types.d.ts +54 -0
  59. package/dist/data/git/types.d.ts.map +1 -0
  60. package/dist/data/test-runner/MatrixMarks.cjs +4 -3
  61. package/dist/data/test-runner/MatrixMarks.cjs.map +1 -1
  62. package/dist/data/test-runner/MatrixMarks.d.ts +7 -4
  63. package/dist/data/test-runner/MatrixMarks.d.ts.map +1 -1
  64. package/dist/data/test-runner/MatrixMarks.js +4 -3
  65. package/dist/data/test-runner/MatrixMarks.js.map +1 -1
  66. package/dist/data/test-runner/TestRunSummary.cjs +1 -1
  67. package/dist/data/test-runner/TestRunSummary.cjs.map +1 -1
  68. package/dist/data/test-runner/TestRunSummary.js +1 -1
  69. package/dist/data/test-runner/TestRunSummary.js.map +1 -1
  70. package/dist/data/test-runner/TestTree.cjs +1 -1
  71. package/dist/data/test-runner/TestTree.cjs.map +1 -1
  72. package/dist/data/test-runner/TestTree.js +1 -1
  73. package/dist/data/test-runner/TestTree.js.map +1 -1
  74. package/dist/data/test-runner/TestTreeNode.cjs +2 -2
  75. package/dist/data/test-runner/TestTreeNode.cjs.map +1 -1
  76. package/dist/data/test-runner/TestTreeNode.js +2 -2
  77. package/dist/data/test-runner/TestTreeNode.js.map +1 -1
  78. package/dist/data/test-runner/adapter.cjs +7 -0
  79. package/dist/data/test-runner/adapter.cjs.map +1 -1
  80. package/dist/data/test-runner/adapter.d.ts +7 -0
  81. package/dist/data/test-runner/adapter.d.ts.map +1 -1
  82. package/dist/data/test-runner/adapter.js +7 -0
  83. package/dist/data/test-runner/adapter.js.map +1 -1
  84. package/dist/data/test-runner/index.d.ts +1 -1
  85. package/dist/data/test-runner/index.d.ts.map +1 -1
  86. package/dist/data/test-runner/marks.cjs +3 -3
  87. package/dist/data/test-runner/marks.cjs.map +1 -1
  88. package/dist/data/test-runner/marks.js +3 -3
  89. package/dist/data/test-runner/marks.js.map +1 -1
  90. package/dist/data/test-runner/matrix-marks.cjs +12 -3
  91. package/dist/data/test-runner/matrix-marks.cjs.map +1 -1
  92. package/dist/data/test-runner/matrix-marks.d.ts +13 -0
  93. package/dist/data/test-runner/matrix-marks.d.ts.map +1 -1
  94. package/dist/data/test-runner/matrix-marks.js +12 -3
  95. package/dist/data/test-runner/matrix-marks.js.map +1 -1
  96. package/dist/data/test-runner/status.cjs +1 -1
  97. package/dist/data/test-runner/status.cjs.map +1 -1
  98. package/dist/data/test-runner/status.js +1 -1
  99. package/dist/data/test-runner/status.js.map +1 -1
  100. package/dist/data/test-runner/types.d.ts +2 -0
  101. package/dist/data/test-runner/types.d.ts.map +1 -1
  102. package/dist/data/verification/adapterViews.cjs +3 -1
  103. package/dist/data/verification/adapterViews.cjs.map +1 -1
  104. package/dist/data/verification/adapterViews.d.ts +5 -2
  105. package/dist/data/verification/adapterViews.d.ts.map +1 -1
  106. package/dist/data/verification/adapterViews.js +4 -2
  107. package/dist/data/verification/adapterViews.js.map +1 -1
  108. package/dist/data/verification/adapters.cjs +28 -7
  109. package/dist/data/verification/adapters.cjs.map +1 -1
  110. package/dist/data/verification/adapters.d.ts +7 -1
  111. package/dist/data/verification/adapters.d.ts.map +1 -1
  112. package/dist/data/verification/adapters.js +28 -7
  113. package/dist/data/verification/adapters.js.map +1 -1
  114. package/dist/data/verification/stepKind.cjs +1 -0
  115. package/dist/data/verification/stepKind.cjs.map +1 -1
  116. package/dist/data/verification/stepKind.d.ts.map +1 -1
  117. package/dist/data/verification/stepKind.js +1 -0
  118. package/dist/data/verification/stepKind.js.map +1 -1
  119. package/dist/data/verification/stepKindViews.cjs +17 -0
  120. package/dist/data/verification/stepKindViews.cjs.map +1 -1
  121. package/dist/data/verification/stepKindViews.d.ts +4 -0
  122. package/dist/data/verification/stepKindViews.d.ts.map +1 -1
  123. package/dist/data/verification/stepKindViews.js +17 -1
  124. package/dist/data/verification/stepKindViews.js.map +1 -1
  125. package/dist/data/version-info.cjs +3 -3
  126. package/dist/data/version-info.js +3 -3
  127. package/dist/data.cjs +114 -0
  128. package/dist/data.d.ts +3 -0
  129. package/dist/data.d.ts.map +1 -1
  130. package/dist/data.js +51 -1
  131. package/dist/git.cjs +6 -0
  132. package/dist/git.d.ts +4 -0
  133. package/dist/git.d.ts.map +1 -0
  134. package/dist/git.js +3 -0
  135. package/dist/hooks/use-prompts.cjs +18 -11
  136. package/dist/hooks/use-prompts.cjs.map +1 -1
  137. package/dist/hooks/use-prompts.d.ts.map +1 -1
  138. package/dist/hooks/use-prompts.js +18 -11
  139. package/dist/hooks/use-prompts.js.map +1 -1
  140. package/dist/icons/components/UiApi.cjs +37 -0
  141. package/dist/icons/components/UiApi.cjs.map +1 -0
  142. package/dist/icons/components/UiApi.d.ts +9 -0
  143. package/dist/icons/components/UiApi.d.ts.map +1 -0
  144. package/dist/icons/components/UiApi.js +35 -0
  145. package/dist/icons/components/UiApi.js.map +1 -0
  146. package/dist/icons/components/UiApiBridge.cjs +38 -0
  147. package/dist/icons/components/UiApiBridge.cjs.map +1 -0
  148. package/dist/icons/components/UiApiBridge.d.ts +9 -0
  149. package/dist/icons/components/UiApiBridge.d.ts.map +1 -0
  150. package/dist/icons/components/UiApiBridge.js +36 -0
  151. package/dist/icons/components/UiApiBridge.js.map +1 -0
  152. package/dist/icons/components/UiApiGateway.cjs +33 -0
  153. package/dist/icons/components/UiApiGateway.cjs.map +1 -0
  154. package/dist/icons/components/UiApiGateway.d.ts +9 -0
  155. package/dist/icons/components/UiApiGateway.d.ts.map +1 -0
  156. package/dist/icons/components/UiApiGateway.js +31 -0
  157. package/dist/icons/components/UiApiGateway.js.map +1 -0
  158. package/dist/icons/components/UiApiRequest.cjs +37 -0
  159. package/dist/icons/components/UiApiRequest.cjs.map +1 -0
  160. package/dist/icons/components/UiApiRequest.d.ts +9 -0
  161. package/dist/icons/components/UiApiRequest.d.ts.map +1 -0
  162. package/dist/icons/components/UiApiRequest.js +35 -0
  163. package/dist/icons/components/UiApiRequest.js.map +1 -0
  164. package/dist/icons/components/UiArrowDecision.cjs +51 -0
  165. package/dist/icons/components/UiArrowDecision.cjs.map +1 -0
  166. package/dist/icons/components/UiArrowDecision.d.ts +15 -0
  167. package/dist/icons/components/UiArrowDecision.d.ts.map +1 -0
  168. package/dist/icons/components/UiArrowDecision.js +48 -0
  169. package/dist/icons/components/UiArrowDecision.js.map +1 -0
  170. package/dist/icons/components/UiArrowSquareIn.cjs +51 -0
  171. package/dist/icons/components/UiArrowSquareIn.cjs.map +1 -0
  172. package/dist/icons/components/UiArrowSquareIn.d.ts +15 -0
  173. package/dist/icons/components/UiArrowSquareIn.d.ts.map +1 -0
  174. package/dist/icons/components/UiArrowSquareIn.js +48 -0
  175. package/dist/icons/components/UiArrowSquareIn.js.map +1 -0
  176. package/dist/icons/components/UiBatchCheck.cjs +55 -0
  177. package/dist/icons/components/UiBatchCheck.cjs.map +1 -0
  178. package/dist/icons/components/UiBatchCheck.d.ts +15 -0
  179. package/dist/icons/components/UiBatchCheck.d.ts.map +1 -0
  180. package/dist/icons/components/UiBatchCheck.js +52 -0
  181. package/dist/icons/components/UiBatchCheck.js.map +1 -0
  182. package/dist/icons/components/UiBatchJob.cjs +39 -0
  183. package/dist/icons/components/UiBatchJob.cjs.map +1 -0
  184. package/dist/icons/components/UiBatchJob.d.ts +9 -0
  185. package/dist/icons/components/UiBatchJob.d.ts.map +1 -0
  186. package/dist/icons/components/UiBatchJob.js +37 -0
  187. package/dist/icons/components/UiBatchJob.js.map +1 -0
  188. package/dist/icons/components/UiBatchRequest.cjs +39 -0
  189. package/dist/icons/components/UiBatchRequest.cjs.map +1 -0
  190. package/dist/icons/components/UiBatchRequest.d.ts +9 -0
  191. package/dist/icons/components/UiBatchRequest.d.ts.map +1 -0
  192. package/dist/icons/components/UiBatchRequest.js +37 -0
  193. package/dist/icons/components/UiBatchRequest.js.map +1 -0
  194. package/dist/icons/components/UiBpmnConditional.cjs +29 -0
  195. package/dist/icons/components/UiBpmnConditional.cjs.map +1 -0
  196. package/dist/icons/components/UiBpmnConditional.d.ts +9 -0
  197. package/dist/icons/components/UiBpmnConditional.d.ts.map +1 -0
  198. package/dist/icons/components/UiBpmnConditional.js +27 -0
  199. package/dist/icons/components/UiBpmnConditional.js.map +1 -0
  200. package/dist/icons/components/UiBranchFlow.cjs +33 -0
  201. package/dist/icons/components/UiBranchFlow.cjs.map +1 -0
  202. package/dist/icons/components/UiBranchFlow.d.ts +9 -0
  203. package/dist/icons/components/UiBranchFlow.d.ts.map +1 -0
  204. package/dist/icons/components/UiBranchFlow.js +31 -0
  205. package/dist/icons/components/UiBranchFlow.js.map +1 -0
  206. package/dist/icons/components/UiClassicBatch.cjs +29 -0
  207. package/dist/icons/components/UiClassicBatch.cjs.map +1 -0
  208. package/dist/icons/components/UiClassicBatch.d.ts +9 -0
  209. package/dist/icons/components/UiClassicBatch.d.ts.map +1 -0
  210. package/dist/icons/components/UiClassicBatch.js +27 -0
  211. package/dist/icons/components/UiClassicBatch.js.map +1 -0
  212. package/dist/icons/components/UiCodeFile.cjs +29 -0
  213. package/dist/icons/components/UiCodeFile.cjs.map +1 -0
  214. package/dist/icons/components/UiCodeFile.d.ts +9 -0
  215. package/dist/icons/components/UiCodeFile.d.ts.map +1 -0
  216. package/dist/icons/components/UiCodeFile.js +27 -0
  217. package/dist/icons/components/UiCodeFile.js.map +1 -0
  218. package/dist/icons/components/UiColumnsLayout.cjs +29 -0
  219. package/dist/icons/components/UiColumnsLayout.cjs.map +1 -0
  220. package/dist/icons/components/UiColumnsLayout.d.ts +9 -0
  221. package/dist/icons/components/UiColumnsLayout.d.ts.map +1 -0
  222. package/dist/icons/components/UiColumnsLayout.js +27 -0
  223. package/dist/icons/components/UiColumnsLayout.js.map +1 -0
  224. package/dist/icons/components/UiCondition.cjs +37 -0
  225. package/dist/icons/components/UiCondition.cjs.map +1 -0
  226. package/dist/icons/components/UiCondition.d.ts +9 -0
  227. package/dist/icons/components/UiCondition.d.ts.map +1 -0
  228. package/dist/icons/components/UiCondition.js +35 -0
  229. package/dist/icons/components/UiCondition.js.map +1 -0
  230. package/dist/icons/components/UiConditions.cjs +29 -0
  231. package/dist/icons/components/UiConditions.cjs.map +1 -0
  232. package/dist/icons/components/UiConditions.d.ts +9 -0
  233. package/dist/icons/components/UiConditions.d.ts.map +1 -0
  234. package/dist/icons/components/UiConditions.js +27 -0
  235. package/dist/icons/components/UiConditions.js.map +1 -0
  236. package/dist/icons/components/UiDelayQueue.cjs +40 -0
  237. package/dist/icons/components/UiDelayQueue.cjs.map +1 -0
  238. package/dist/icons/components/UiDelayQueue.d.ts +9 -0
  239. package/dist/icons/components/UiDelayQueue.d.ts.map +1 -0
  240. package/dist/icons/components/UiDelayQueue.js +38 -0
  241. package/dist/icons/components/UiDelayQueue.js.map +1 -0
  242. package/dist/icons/components/UiDynamicForm.cjs +51 -0
  243. package/dist/icons/components/UiDynamicForm.cjs.map +1 -0
  244. package/dist/icons/components/UiDynamicForm.d.ts +15 -0
  245. package/dist/icons/components/UiDynamicForm.d.ts.map +1 -0
  246. package/dist/icons/components/UiDynamicForm.js +48 -0
  247. package/dist/icons/components/UiDynamicForm.js.map +1 -0
  248. package/dist/icons/components/UiFlowArrow.cjs +51 -0
  249. package/dist/icons/components/UiFlowArrow.cjs.map +1 -0
  250. package/dist/icons/components/UiFlowArrow.d.ts +15 -0
  251. package/dist/icons/components/UiFlowArrow.d.ts.map +1 -0
  252. package/dist/icons/components/UiFlowArrow.js +48 -0
  253. package/dist/icons/components/UiFlowArrow.js.map +1 -0
  254. package/dist/icons/components/UiFormFields.cjs +33 -0
  255. package/dist/icons/components/UiFormFields.cjs.map +1 -0
  256. package/dist/icons/components/UiFormFields.d.ts +9 -0
  257. package/dist/icons/components/UiFormFields.d.ts.map +1 -0
  258. package/dist/icons/components/UiFormFields.js +31 -0
  259. package/dist/icons/components/UiFormFields.js.map +1 -0
  260. package/dist/icons/components/UiFormStep.cjs +38 -0
  261. package/dist/icons/components/UiFormStep.cjs.map +1 -0
  262. package/dist/icons/components/UiFormStep.d.ts +9 -0
  263. package/dist/icons/components/UiFormStep.d.ts.map +1 -0
  264. package/dist/icons/components/UiFormStep.js +36 -0
  265. package/dist/icons/components/UiFormStep.js.map +1 -0
  266. package/dist/icons/components/UiGatewayApi.cjs +32 -0
  267. package/dist/icons/components/UiGatewayApi.cjs.map +1 -0
  268. package/dist/icons/components/UiGatewayApi.d.ts +9 -0
  269. package/dist/icons/components/UiGatewayApi.d.ts.map +1 -0
  270. package/dist/icons/components/UiGatewayApi.js +30 -0
  271. package/dist/icons/components/UiGatewayApi.js.map +1 -0
  272. package/dist/icons/components/UiImportArrow.cjs +29 -0
  273. package/dist/icons/components/UiImportArrow.cjs.map +1 -0
  274. package/dist/icons/components/UiImportArrow.d.ts +9 -0
  275. package/dist/icons/components/UiImportArrow.d.ts.map +1 -0
  276. package/dist/icons/components/UiImportArrow.js +27 -0
  277. package/dist/icons/components/UiImportArrow.js.map +1 -0
  278. package/dist/icons/components/UiInputField.cjs +33 -0
  279. package/dist/icons/components/UiInputField.cjs.map +1 -0
  280. package/dist/icons/components/UiInputField.d.ts +9 -0
  281. package/dist/icons/components/UiInputField.d.ts.map +1 -0
  282. package/dist/icons/components/UiInputField.js +31 -0
  283. package/dist/icons/components/UiInputField.js.map +1 -0
  284. package/dist/icons/components/UiInsertTable.cjs +29 -0
  285. package/dist/icons/components/UiInsertTable.cjs.map +1 -0
  286. package/dist/icons/components/UiInsertTable.d.ts +9 -0
  287. package/dist/icons/components/UiInsertTable.d.ts.map +1 -0
  288. package/dist/icons/components/UiInsertTable.js +27 -0
  289. package/dist/icons/components/UiInsertTable.js.map +1 -0
  290. package/dist/icons/components/UiLayoutTemplate.cjs +32 -0
  291. package/dist/icons/components/UiLayoutTemplate.cjs.map +1 -0
  292. package/dist/icons/components/UiLayoutTemplate.d.ts +9 -0
  293. package/dist/icons/components/UiLayoutTemplate.d.ts.map +1 -0
  294. package/dist/icons/components/UiLayoutTemplate.js +30 -0
  295. package/dist/icons/components/UiLayoutTemplate.js.map +1 -0
  296. package/dist/icons/components/UiLayoutWindow.cjs +56 -0
  297. package/dist/icons/components/UiLayoutWindow.cjs.map +1 -0
  298. package/dist/icons/components/UiLayoutWindow.d.ts +15 -0
  299. package/dist/icons/components/UiLayoutWindow.d.ts.map +1 -0
  300. package/dist/icons/components/UiLayoutWindow.js +53 -0
  301. package/dist/icons/components/UiLayoutWindow.js.map +1 -0
  302. package/dist/icons/components/UiListEnd.cjs +33 -0
  303. package/dist/icons/components/UiListEnd.cjs.map +1 -0
  304. package/dist/icons/components/UiListEnd.d.ts +9 -0
  305. package/dist/icons/components/UiListEnd.d.ts.map +1 -0
  306. package/dist/icons/components/UiListEnd.js +31 -0
  307. package/dist/icons/components/UiListEnd.js.map +1 -0
  308. package/dist/icons/components/UiListEndLine.cjs +51 -0
  309. package/dist/icons/components/UiListEndLine.cjs.map +1 -0
  310. package/dist/icons/components/UiListEndLine.d.ts +15 -0
  311. package/dist/icons/components/UiListEndLine.d.ts.map +1 -0
  312. package/dist/icons/components/UiListEndLine.js +48 -0
  313. package/dist/icons/components/UiListEndLine.js.map +1 -0
  314. package/dist/icons/components/UiListNumbers.cjs +51 -0
  315. package/dist/icons/components/UiListNumbers.cjs.map +1 -0
  316. package/dist/icons/components/UiListNumbers.d.ts +15 -0
  317. package/dist/icons/components/UiListNumbers.d.ts.map +1 -0
  318. package/dist/icons/components/UiListNumbers.js +48 -0
  319. package/dist/icons/components/UiListNumbers.js.map +1 -0
  320. package/dist/icons/components/UiLowPriority.cjs +29 -0
  321. package/dist/icons/components/UiLowPriority.cjs.map +1 -0
  322. package/dist/icons/components/UiLowPriority.d.ts +9 -0
  323. package/dist/icons/components/UiLowPriority.d.ts.map +1 -0
  324. package/dist/icons/components/UiLowPriority.js +27 -0
  325. package/dist/icons/components/UiLowPriority.js.map +1 -0
  326. package/dist/icons/components/UiMergeQueue.cjs +38 -0
  327. package/dist/icons/components/UiMergeQueue.cjs.map +1 -0
  328. package/dist/icons/components/UiMergeQueue.d.ts +9 -0
  329. package/dist/icons/components/UiMergeQueue.d.ts.map +1 -0
  330. package/dist/icons/components/UiMergeQueue.js +36 -0
  331. package/dist/icons/components/UiMergeQueue.js.map +1 -0
  332. package/dist/icons/components/UiPipelineStage.cjs +33 -0
  333. package/dist/icons/components/UiPipelineStage.cjs.map +1 -0
  334. package/dist/icons/components/UiPipelineStage.d.ts +9 -0
  335. package/dist/icons/components/UiPipelineStage.d.ts.map +1 -0
  336. package/dist/icons/components/UiPipelineStage.js +31 -0
  337. package/dist/icons/components/UiPipelineStage.js.map +1 -0
  338. package/dist/icons/components/UiPlaylistRemove.cjs +29 -0
  339. package/dist/icons/components/UiPlaylistRemove.cjs.map +1 -0
  340. package/dist/icons/components/UiPlaylistRemove.d.ts +9 -0
  341. package/dist/icons/components/UiPlaylistRemove.d.ts.map +1 -0
  342. package/dist/icons/components/UiPlaylistRemove.js +27 -0
  343. package/dist/icons/components/UiPlaylistRemove.js.map +1 -0
  344. package/dist/icons/components/UiReportForms.cjs +51 -0
  345. package/dist/icons/components/UiReportForms.cjs.map +1 -0
  346. package/dist/icons/components/UiReportForms.d.ts +15 -0
  347. package/dist/icons/components/UiReportForms.d.ts.map +1 -0
  348. package/dist/icons/components/UiReportForms.js +48 -0
  349. package/dist/icons/components/UiReportForms.js.map +1 -0
  350. package/dist/icons/components/UiScreenTemplate.cjs +29 -0
  351. package/dist/icons/components/UiScreenTemplate.cjs.map +1 -0
  352. package/dist/icons/components/UiScreenTemplate.d.ts +9 -0
  353. package/dist/icons/components/UiScreenTemplate.d.ts.map +1 -0
  354. package/dist/icons/components/UiScreenTemplate.js +27 -0
  355. package/dist/icons/components/UiScreenTemplate.js.map +1 -0
  356. package/dist/icons/components/UiServices.cjs +29 -0
  357. package/dist/icons/components/UiServices.cjs.map +1 -0
  358. package/dist/icons/components/UiServices.d.ts +9 -0
  359. package/dist/icons/components/UiServices.d.ts.map +1 -0
  360. package/dist/icons/components/UiServices.js +27 -0
  361. package/dist/icons/components/UiServices.js.map +1 -0
  362. package/dist/icons/components/UiSkipCircle.cjs +51 -0
  363. package/dist/icons/components/UiSkipCircle.cjs.map +1 -0
  364. package/dist/icons/components/UiSkipCircle.d.ts +15 -0
  365. package/dist/icons/components/UiSkipCircle.d.ts.map +1 -0
  366. package/dist/icons/components/UiSkipCircle.js +48 -0
  367. package/dist/icons/components/UiSkipCircle.js.map +1 -0
  368. package/dist/icons/components/UiTaskBatch.cjs +33 -0
  369. package/dist/icons/components/UiTaskBatch.cjs.map +1 -0
  370. package/dist/icons/components/UiTaskBatch.d.ts +9 -0
  371. package/dist/icons/components/UiTaskBatch.d.ts.map +1 -0
  372. package/dist/icons/components/UiTaskBatch.js +31 -0
  373. package/dist/icons/components/UiTaskBatch.js.map +1 -0
  374. package/dist/icons/components/UiTodoList.cjs +29 -0
  375. package/dist/icons/components/UiTodoList.cjs.map +1 -0
  376. package/dist/icons/components/UiTodoList.d.ts +9 -0
  377. package/dist/icons/components/UiTodoList.d.ts.map +1 -0
  378. package/dist/icons/components/UiTodoList.js +27 -0
  379. package/dist/icons/components/UiTodoList.js.map +1 -0
  380. package/dist/icons/components/UiTrayArrowDown.cjs +51 -0
  381. package/dist/icons/components/UiTrayArrowDown.cjs.map +1 -0
  382. package/dist/icons/components/UiTrayArrowDown.d.ts +15 -0
  383. package/dist/icons/components/UiTrayArrowDown.d.ts.map +1 -0
  384. package/dist/icons/components/UiTrayArrowDown.js +48 -0
  385. package/dist/icons/components/UiTrayArrowDown.js.map +1 -0
  386. package/dist/icons/components/UiVault.cjs +51 -0
  387. package/dist/icons/components/UiVault.cjs.map +1 -0
  388. package/dist/icons/components/UiVault.d.ts +15 -0
  389. package/dist/icons/components/UiVault.d.ts.map +1 -0
  390. package/dist/icons/components/UiVault.js +48 -0
  391. package/dist/icons/components/UiVault.js.map +1 -0
  392. package/dist/icons/components/UiWebServiceDefinition.cjs +39 -0
  393. package/dist/icons/components/UiWebServiceDefinition.cjs.map +1 -0
  394. package/dist/icons/components/UiWebServiceDefinition.d.ts +9 -0
  395. package/dist/icons/components/UiWebServiceDefinition.d.ts.map +1 -0
  396. package/dist/icons/components/UiWebServiceDefinition.js +37 -0
  397. package/dist/icons/components/UiWebServiceDefinition.js.map +1 -0
  398. package/dist/icons/components/UiWebhook.cjs +29 -0
  399. package/dist/icons/components/UiWebhook.cjs.map +1 -0
  400. package/dist/icons/components/UiWebhook.d.ts +9 -0
  401. package/dist/icons/components/UiWebhook.d.ts.map +1 -0
  402. package/dist/icons/components/UiWebhook.js +27 -0
  403. package/dist/icons/components/UiWebhook.js.map +1 -0
  404. package/dist/icons/components/UiWebhookLine.cjs +51 -0
  405. package/dist/icons/components/UiWebhookLine.cjs.map +1 -0
  406. package/dist/icons/components/UiWebhookLine.d.ts +15 -0
  407. package/dist/icons/components/UiWebhookLine.d.ts.map +1 -0
  408. package/dist/icons/components/UiWebhookLine.js +48 -0
  409. package/dist/icons/components/UiWebhookLine.js.map +1 -0
  410. package/dist/icons/index.d.ts +58 -0
  411. package/dist/icons/index.d.ts.map +1 -1
  412. package/dist/icons/registry.cjs +90 -0
  413. package/dist/icons/registry.cjs.map +1 -1
  414. package/dist/icons/registry.d.ts.map +1 -1
  415. package/dist/icons/registry.js +90 -0
  416. package/dist/icons/registry.js.map +1 -1
  417. package/dist/icons.cjs +103 -0
  418. package/dist/icons.js +46 -1
  419. package/dist/index.cjs +114 -0
  420. package/dist/index.js +51 -1
  421. package/dist/overlay/DropdownMenu.cjs +17 -14
  422. package/dist/overlay/DropdownMenu.cjs.map +1 -1
  423. package/dist/overlay/DropdownMenu.d.ts +1 -0
  424. package/dist/overlay/DropdownMenu.d.ts.map +1 -1
  425. package/dist/overlay/DropdownMenu.js +18 -15
  426. package/dist/overlay/DropdownMenu.js.map +1 -1
  427. package/dist/styles.css +1 -1
  428. package/package.json +6 -1
@@ -1 +1 @@
1
- {"version":3,"file":"TestTreeNode.cjs","names":["sum","Badge","useTestRunner","testStatus","outcomeFor","totalDuration","_Fragment","OutcomeIcon","Icon","UiClass","ToolIcon","toolKeyFor","cn","humanizeName","formatTestDuration","IconButton","UiStop","UiRefresh"],"sources":["../../../src/data/test-runner/TestTreeNode.tsx"],"sourcesContent":["import { Icon } from \"../Icon\";\nimport { Badge } from \"../Badge\";\nimport { IconButton } from \"../../components/IconButton\";\nimport { UiClass, UiRefresh, UiStop } from \"../../icons\";\nimport { cn } from \"../../lib/utils\";\nimport type { Test } from \"./types\";\nimport { useTestRunner } from \"./context\";\nimport {\n formatTestDuration,\n humanizeName,\n outcomeFor,\n sum,\n testStatus,\n totalDuration,\n} from \"./status\";\nimport { toolKeyFor } from \"./marks\";\nimport { OutcomeIcon, ToolIcon } from \"./MarkIcons\";\n\nconst NAME_TONE: Record<string, string> = {\n failed: \"text-red-600 dark:text-red-400\",\n timedout: \"text-amber-600 dark:text-amber-400\",\n warned: \"text-amber-600 dark:text-amber-400\",\n aborted: \"text-red-500 dark:text-red-300\",\n running: \"text-blue-600 dark:text-blue-400\",\n skipped: \"text-muted-foreground\",\n pending: \"text-muted-foreground\",\n passed: \"text-foreground\",\n};\n\nconst MESSAGE_STATUSES = new Set([\"failed\", \"timedout\", \"warned\", \"aborted\", \"skipped\"]);\n\n/** Per-status roll-up count badges shown on a container row. */\nfunction CountBadges({ node }: { node: Test }) {\n const s = sum(node);\n if (s.total === 0) return null;\n return (\n <span className=\"flex shrink-0 items-center gap-1\">\n {s.passed > 0 && <Badge tone=\"success\" variant=\"solid\" size=\"xxs\" count={s.passed} />}\n {s.failed > 0 && <Badge tone=\"danger\" variant=\"solid\" size=\"xxs\" count={s.failed} />}\n {s.warned > 0 && <Badge tone=\"warning\" variant=\"outline\" size=\"xxs\" count={s.warned} />}\n {s.timedout > 0 && <Badge tone=\"warning\" variant=\"solid\" size=\"xxs\" count={s.timedout} />}\n {s.aborted > 0 && <Badge tone=\"danger\" variant=\"soft\" size=\"xxs\" count={s.aborted} />}\n {s.skipped > 0 && <Badge tone=\"neutral\" variant=\"soft\" size=\"xxs\" count={s.skipped} />}\n {s.running > 0 && <Badge tone=\"info\" variant=\"solid\" size=\"xxs\" count={s.running} />}\n {s.pending > 0 && <Badge tone=\"neutral\" variant=\"soft\" size=\"xxs\" count={s.pending} />}\n </span>\n );\n}\n\n/**\n * Renders one test tree row: status icon, optional adapter decoration + framework\n * icon, status-colored name, duration, per-status count badges, and (when the\n * runner exposes the handlers) rerun/stop buttons. Designed as the `renderRow`\n * for the clicky `Tree`.\n */\nexport function TestTreeNode({ node, selected }: { node: Test; selected: boolean }) {\n const runner = useTestRunner();\n const hasChildren = (node.children?.length ?? 0) > 0;\n const status = testStatus(node);\n const outcome = outcomeFor(node);\n const fwAdapter = runner.adapters.resolveFrameworkIcon(node, runner);\n const fwNode = fwAdapter?.renderFrameworkIcon?.({ node, runner });\n const leadingAdapter = runner.adapters.resolveRowLeading(node, runner);\n const dur = node.duration || (hasChildren ? totalDuration(node) : 0);\n const canRerun = !!runner.onRerun && node.framework !== \"task\";\n const canStop = !!runner.onStop && !!node.can_stop && !!node.task_id;\n const showMessage = status && (MESSAGE_STATUSES.has(status) || (node.framework === \"task\" && (status === \"running\" || status === \"pending\")));\n const message = showMessage ? (node.message ?? \"\").trim() : \"\";\n\n return (\n <>\n {outcome ? (\n <OutcomeIcon outcome={outcome} />\n ) : (\n <Icon icon={UiClass} className=\"shrink-0 text-muted-foreground\" />\n )}\n\n {fwNode != null ? (\n <span className=\"flex shrink-0 items-center text-sm\">{fwNode}</span>\n ) : (\n <ToolIcon tool={toolKeyFor(node)} className=\"text-sm\" />\n )}\n\n {leadingAdapter?.renderRowLeading?.({ node, runner })}\n\n <span\n className={cn(\n \"min-w-0 truncate\",\n selected ? \"font-semibold\" : \"font-medium\",\n (status && NAME_TONE[status]) || \"text-foreground\",\n )}\n title={message || undefined}\n >\n {humanizeName(node.name, node.framework)}\n </span>\n {/* The verdict trails the name on the same line and gives way first. */}\n {message ? (\n <span\n className=\"min-w-0 flex-1 shrink-[100] truncate text-xs text-muted-foreground\"\n title={message}\n data-row-message=\"\"\n >\n {message}\n </span>\n ) : (\n <span className=\"flex-1\" />\n )}\n\n {node.progress && node.progress.total > 0 && !node.passed && !node.failed && (\n <span className=\"flex shrink-0 items-center gap-1 text-xs text-blue-600 dark:text-blue-400\">\n {node.progress.phase && <span>{node.progress.phase}</span>}\n <span className=\"tabular-nums\">\n {node.progress.done}/{node.progress.total}\n </span>\n </span>\n )}\n\n {dur > 0 && (\n <span className=\"shrink-0 text-xs text-muted-foreground\">{formatTestDuration(dur)}</span>\n )}\n\n {hasChildren && <CountBadges node={node} />}\n\n {canStop && (\n <IconButton\n icon={UiStop}\n label=\"Stop\"\n disabled={runner.busy.stop}\n onClick={(e) => {\n e.stopPropagation();\n runner.onStop!(node);\n }}\n />\n )}\n\n {canRerun && (\n <IconButton\n icon={UiRefresh}\n label=\"Rerun\"\n disabled={runner.busy.rerun}\n onClick={(e) => {\n e.stopPropagation();\n runner.onRerun!(node);\n }}\n />\n )}\n </>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"TestTreeNode.cjs","names":["sum","Badge","useTestRunner","testStatus","outcomeFor","totalDuration","_Fragment","OutcomeIcon","Icon","UiClass","ToolIcon","toolKeyFor","cn","humanizeName","formatTestDuration","IconButton","UiStop","UiRefresh"],"sources":["../../../src/data/test-runner/TestTreeNode.tsx"],"sourcesContent":["import { Icon } from \"../Icon\";\nimport { Badge } from \"../Badge\";\nimport { IconButton } from \"../../components/IconButton\";\nimport { UiClass, UiRefresh, UiStop } from \"../../icons\";\nimport { cn } from \"../../lib/utils\";\nimport type { Test } from \"./types\";\nimport { useTestRunner } from \"./context\";\nimport {\n formatTestDuration,\n humanizeName,\n outcomeFor,\n sum,\n testStatus,\n totalDuration,\n} from \"./status\";\nimport { toolKeyFor } from \"./marks\";\nimport { OutcomeIcon, ToolIcon } from \"./MarkIcons\";\n\nconst NAME_TONE: Record<string, string> = {\n failed: \"text-red-600 dark:text-red-400\",\n timedout: \"text-amber-600 dark:text-amber-400\",\n warned: \"text-amber-600 dark:text-amber-400\",\n aborted: \"text-muted-foreground\",\n running: \"text-blue-600 dark:text-blue-400\",\n skipped: \"text-muted-foreground\",\n pending: \"text-muted-foreground\",\n passed: \"text-foreground\",\n};\n\nconst MESSAGE_STATUSES = new Set([\"failed\", \"timedout\", \"warned\", \"aborted\", \"skipped\"]);\n\n/** Per-status roll-up count badges shown on a container row. */\nfunction CountBadges({ node }: { node: Test }) {\n const s = sum(node);\n if (s.total === 0) return null;\n return (\n <span className=\"flex shrink-0 items-center gap-1\">\n {s.passed > 0 && <Badge tone=\"success\" variant=\"solid\" size=\"xxs\" count={s.passed} />}\n {s.failed > 0 && <Badge tone=\"danger\" variant=\"solid\" size=\"xxs\" count={s.failed} />}\n {s.warned > 0 && <Badge tone=\"warning\" variant=\"outline\" size=\"xxs\" count={s.warned} />}\n {s.timedout > 0 && <Badge tone=\"warning\" variant=\"solid\" size=\"xxs\" count={s.timedout} />}\n {s.aborted > 0 && <Badge tone=\"neutral\" variant=\"soft\" size=\"xxs\" count={s.aborted} />}\n {s.skipped > 0 && <Badge tone=\"neutral\" variant=\"soft\" size=\"xxs\" count={s.skipped} />}\n {s.running > 0 && <Badge tone=\"info\" variant=\"solid\" size=\"xxs\" count={s.running} />}\n {s.pending > 0 && <Badge tone=\"neutral\" variant=\"soft\" size=\"xxs\" count={s.pending} />}\n </span>\n );\n}\n\n/**\n * Renders one test tree row: status icon, optional adapter decoration + framework\n * icon, status-colored name, duration, per-status count badges, and (when the\n * runner exposes the handlers) rerun/stop buttons. Designed as the `renderRow`\n * for the clicky `Tree`.\n */\nexport function TestTreeNode({ node, selected }: { node: Test; selected: boolean }) {\n const runner = useTestRunner();\n const hasChildren = (node.children?.length ?? 0) > 0;\n const status = testStatus(node);\n const outcome = outcomeFor(node);\n const fwAdapter = runner.adapters.resolveFrameworkIcon(node, runner);\n const fwNode = fwAdapter?.renderFrameworkIcon?.({ node, runner });\n const leadingAdapter = runner.adapters.resolveRowLeading(node, runner);\n const dur = node.duration || (hasChildren ? totalDuration(node) : 0);\n const canRerun = !!runner.onRerun && node.framework !== \"task\";\n const canStop = !!runner.onStop && !!node.can_stop && !!node.task_id;\n const showMessage = status && (MESSAGE_STATUSES.has(status) || (node.framework === \"task\" && (status === \"running\" || status === \"pending\")));\n const message = showMessage ? (node.message ?? \"\").trim() : \"\";\n\n return (\n <>\n {outcome ? (\n <OutcomeIcon outcome={outcome} />\n ) : (\n <Icon icon={UiClass} className=\"shrink-0 text-muted-foreground\" />\n )}\n\n {fwNode != null ? (\n <span className=\"flex shrink-0 items-center text-sm\">{fwNode}</span>\n ) : (\n <ToolIcon tool={toolKeyFor(node)} className=\"text-sm\" />\n )}\n\n {leadingAdapter?.renderRowLeading?.({ node, runner })}\n\n <span\n className={cn(\n \"min-w-0 truncate\",\n selected ? \"font-semibold\" : \"font-medium\",\n (status && NAME_TONE[status]) || \"text-foreground\",\n )}\n title={message || undefined}\n >\n {humanizeName(node.name, node.framework)}\n </span>\n {/* The verdict trails the name on the same line and gives way first. */}\n {message ? (\n <span\n className=\"min-w-0 flex-1 shrink-[100] truncate text-xs text-muted-foreground\"\n title={message}\n data-row-message=\"\"\n >\n {message}\n </span>\n ) : (\n <span className=\"flex-1\" />\n )}\n\n {node.progress && node.progress.total > 0 && !node.passed && !node.failed && (\n <span className=\"flex shrink-0 items-center gap-1 text-xs text-blue-600 dark:text-blue-400\">\n {node.progress.phase && <span>{node.progress.phase}</span>}\n <span className=\"tabular-nums\">\n {node.progress.done}/{node.progress.total}\n </span>\n </span>\n )}\n\n {dur > 0 && (\n <span className=\"shrink-0 text-xs text-muted-foreground\">{formatTestDuration(dur)}</span>\n )}\n\n {hasChildren && <CountBadges node={node} />}\n\n {canStop && (\n <IconButton\n icon={UiStop}\n label=\"Stop\"\n disabled={runner.busy.stop}\n onClick={(e) => {\n e.stopPropagation();\n runner.onStop!(node);\n }}\n />\n )}\n\n {canRerun && (\n <IconButton\n icon={UiRefresh}\n label=\"Rerun\"\n disabled={runner.busy.rerun}\n onClick={(e) => {\n e.stopPropagation();\n runner.onRerun!(node);\n }}\n />\n )}\n </>\n );\n}\n"],"mappings":";;;;;;;;;;;;;AAkBA,IAAM,YAAoC;CACxC,QAAQ;CACR,UAAU;CACV,QAAQ;CACR,SAAS;CACT,SAAS;CACT,SAAS;CACT,SAAS;CACT,QAAQ;AACV;AAEA,IAAM,mCAAmB,IAAI,IAAI;CAAC;CAAU;CAAY;CAAU;CAAW;AAAS,CAAC;;AAGvF,SAAS,YAAY,EAAE,QAAwB;CAC7C,MAAM,IAAIA,eAAAA,IAAI,IAAI;CAClB,IAAI,EAAE,UAAU,GAAG,OAAO;CAC1B,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,QAAD;EAAM,WAAU;EAAhB,UAAA;GACG,EAAE,SAAS,KAAK,iBAAA,GAAA,kBAAA,IAAA,CAACC,cAAAA,OAAD;IAAO,MAAK;IAAU,SAAQ;IAAQ,MAAK;IAAM,OAAO,EAAE;GAAS,CAAA;GACnF,EAAE,SAAS,KAAK,iBAAA,GAAA,kBAAA,IAAA,CAACA,cAAAA,OAAD;IAAO,MAAK;IAAS,SAAQ;IAAQ,MAAK;IAAM,OAAO,EAAE;GAAS,CAAA;GAClF,EAAE,SAAS,KAAK,iBAAA,GAAA,kBAAA,IAAA,CAACA,cAAAA,OAAD;IAAO,MAAK;IAAU,SAAQ;IAAU,MAAK;IAAM,OAAO,EAAE;GAAS,CAAA;GACrF,EAAE,WAAW,KAAK,iBAAA,GAAA,kBAAA,IAAA,CAACA,cAAAA,OAAD;IAAO,MAAK;IAAU,SAAQ;IAAQ,MAAK;IAAM,OAAO,EAAE;GAAW,CAAA;GACvF,EAAE,UAAU,KAAK,iBAAA,GAAA,kBAAA,IAAA,CAACA,cAAAA,OAAD;IAAO,MAAK;IAAU,SAAQ;IAAO,MAAK;IAAM,OAAO,EAAE;GAAU,CAAA;GACpF,EAAE,UAAU,KAAK,iBAAA,GAAA,kBAAA,IAAA,CAACA,cAAAA,OAAD;IAAO,MAAK;IAAU,SAAQ;IAAO,MAAK;IAAM,OAAO,EAAE;GAAU,CAAA;GACpF,EAAE,UAAU,KAAK,iBAAA,GAAA,kBAAA,IAAA,CAACA,cAAAA,OAAD;IAAO,MAAK;IAAO,SAAQ;IAAQ,MAAK;IAAM,OAAO,EAAE;GAAU,CAAA;GAClF,EAAE,UAAU,KAAK,iBAAA,GAAA,kBAAA,IAAA,CAACA,cAAAA,OAAD;IAAO,MAAK;IAAU,SAAQ;IAAO,MAAK;IAAM,OAAO,EAAE;GAAU,CAAA;EACjF;;AAEV;;;;;;;AAQA,SAAgB,aAAa,EAAE,MAAM,YAA+C;CAClF,MAAM,SAASC,gBAAAA,cAAc;CAC7B,MAAM,eAAe,KAAK,UAAU,UAAU,KAAK;CACnD,MAAM,SAASC,eAAAA,WAAW,IAAI;CAC9B,MAAM,UAAUC,eAAAA,WAAW,IAAI;CAE/B,MAAM,SADY,OAAO,SAAS,qBAAqB,MAAM,MAC9C,CAAA,EAAW,sBAAsB;EAAE;EAAM;CAAO,CAAC;CAChE,MAAM,iBAAiB,OAAO,SAAS,kBAAkB,MAAM,MAAM;CACrE,MAAM,MAAM,KAAK,aAAa,cAAcC,eAAAA,cAAc,IAAI,IAAI;CAClE,MAAM,WAAW,CAAC,CAAC,OAAO,WAAW,KAAK,cAAc;CACxD,MAAM,UAAU,CAAC,CAAC,OAAO,UAAU,CAAC,CAAC,KAAK,YAAY,CAAC,CAAC,KAAK;CAE7D,MAAM,UADc,WAAW,iBAAiB,IAAI,MAAM,KAAM,KAAK,cAAc,WAAW,WAAW,aAAa,WAAW,eAClG,KAAK,WAAW,GAAA,CAAI,KAAK,IAAI;CAE5D,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAAC,kBAAAA,UAAA,EAAA,UAAA;EACG,UACC,iBAAA,GAAA,kBAAA,IAAA,CAACC,kBAAAA,aAAD,EAAsB,QAAU,CAAA,IAEhC,iBAAA,GAAA,kBAAA,IAAA,CAACC,aAAAA,MAAD;GAAM,MAAMC,gBAAAA;GAAS,WAAU;EAAkC,CAAA;EAGlE,UAAU,OACT,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;GAAM,WAAU;GAAsC,UAAA;EAAa,CAAA,IAEnE,iBAAA,GAAA,kBAAA,IAAA,CAACC,kBAAAA,UAAD;GAAU,MAAMC,cAAAA,WAAW,IAAI;GAAG,WAAU;EAAW,CAAA;EAGxD,gBAAgB,mBAAmB;GAAE;GAAM;EAAO,CAAC;EAEpD,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;GACE,WAAWC,cAAAA,GACT,oBACA,WAAW,kBAAkB,eAC5B,UAAU,UAAU,WAAY,iBACnC;GACA,OAAO,WAAW,KAAA;GAEjB,UAAAC,eAAAA,aAAa,KAAK,MAAM,KAAK,SAAS;EACnC,CAAA;EAEL,UACC,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;GACE,WAAU;GACV,OAAO;GACP,oBAAiB;GAEhB,UAAA;EACG,CAAA,IAEN,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAM,WAAU,SAAU,CAAA;EAG3B,KAAK,YAAY,KAAK,SAAS,QAAQ,KAAK,CAAC,KAAK,UAAU,CAAC,KAAK,UACjE,iBAAA,GAAA,kBAAA,KAAA,CAAC,QAAD;GAAM,WAAU;GAAhB,UAAA,CACG,KAAK,SAAS,SAAS,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAA,UAAO,KAAK,SAAS,MAAY,CAAA,GACzD,iBAAA,GAAA,kBAAA,KAAA,CAAC,QAAD;IAAM,WAAU;IAAhB,UAAA;KACG,KAAK,SAAS;KAAK;KAAE,KAAK,SAAS;IAChC;GACF,CAAA,CAAA;;EAGP,MAAM,KACL,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;GAAM,WAAU;GAA0C,UAAAC,eAAAA,mBAAmB,GAAG;EAAQ,CAAA;EAGzF,eAAe,iBAAA,GAAA,kBAAA,IAAA,CAAC,aAAD,EAAmB,KAAO,CAAA;EAEzC,WACC,iBAAA,GAAA,kBAAA,IAAA,CAACC,mBAAAA,YAAD;GACE,MAAMC,eAAAA;GACN,OAAM;GACN,UAAU,OAAO,KAAK;GACtB,UAAU,MAAM;IACd,EAAE,gBAAgB;IAClB,OAAO,OAAQ,IAAI;GACrB;EACD,CAAA;EAGF,YACC,iBAAA,GAAA,kBAAA,IAAA,CAACD,mBAAAA,YAAD;GACE,MAAME,kBAAAA;GACN,OAAM;GACN,UAAU,OAAO,KAAK;GACtB,UAAU,MAAM;IACd,EAAE,gBAAgB;IAClB,OAAO,QAAS,IAAI;GACtB;EACD,CAAA;CAEH,EAAA,CAAA;AAEN"}
@@ -15,7 +15,7 @@ var NAME_TONE = {
15
15
  failed: "text-red-600 dark:text-red-400",
16
16
  timedout: "text-amber-600 dark:text-amber-400",
17
17
  warned: "text-amber-600 dark:text-amber-400",
18
- aborted: "text-red-500 dark:text-red-300",
18
+ aborted: "text-muted-foreground",
19
19
  running: "text-blue-600 dark:text-blue-400",
20
20
  skipped: "text-muted-foreground",
21
21
  pending: "text-muted-foreground",
@@ -60,7 +60,7 @@ function CountBadges({ node }) {
60
60
  count: s.timedout
61
61
  }),
62
62
  s.aborted > 0 && /* @__PURE__ */ jsx(Badge, {
63
- tone: "danger",
63
+ tone: "neutral",
64
64
  variant: "soft",
65
65
  size: "xxs",
66
66
  count: s.aborted
@@ -1 +1 @@
1
- {"version":3,"file":"TestTreeNode.js","names":["_Fragment"],"sources":["../../../src/data/test-runner/TestTreeNode.tsx"],"sourcesContent":["import { Icon } from \"../Icon\";\nimport { Badge } from \"../Badge\";\nimport { IconButton } from \"../../components/IconButton\";\nimport { UiClass, UiRefresh, UiStop } from \"../../icons\";\nimport { cn } from \"../../lib/utils\";\nimport type { Test } from \"./types\";\nimport { useTestRunner } from \"./context\";\nimport {\n formatTestDuration,\n humanizeName,\n outcomeFor,\n sum,\n testStatus,\n totalDuration,\n} from \"./status\";\nimport { toolKeyFor } from \"./marks\";\nimport { OutcomeIcon, ToolIcon } from \"./MarkIcons\";\n\nconst NAME_TONE: Record<string, string> = {\n failed: \"text-red-600 dark:text-red-400\",\n timedout: \"text-amber-600 dark:text-amber-400\",\n warned: \"text-amber-600 dark:text-amber-400\",\n aborted: \"text-red-500 dark:text-red-300\",\n running: \"text-blue-600 dark:text-blue-400\",\n skipped: \"text-muted-foreground\",\n pending: \"text-muted-foreground\",\n passed: \"text-foreground\",\n};\n\nconst MESSAGE_STATUSES = new Set([\"failed\", \"timedout\", \"warned\", \"aborted\", \"skipped\"]);\n\n/** Per-status roll-up count badges shown on a container row. */\nfunction CountBadges({ node }: { node: Test }) {\n const s = sum(node);\n if (s.total === 0) return null;\n return (\n <span className=\"flex shrink-0 items-center gap-1\">\n {s.passed > 0 && <Badge tone=\"success\" variant=\"solid\" size=\"xxs\" count={s.passed} />}\n {s.failed > 0 && <Badge tone=\"danger\" variant=\"solid\" size=\"xxs\" count={s.failed} />}\n {s.warned > 0 && <Badge tone=\"warning\" variant=\"outline\" size=\"xxs\" count={s.warned} />}\n {s.timedout > 0 && <Badge tone=\"warning\" variant=\"solid\" size=\"xxs\" count={s.timedout} />}\n {s.aborted > 0 && <Badge tone=\"danger\" variant=\"soft\" size=\"xxs\" count={s.aborted} />}\n {s.skipped > 0 && <Badge tone=\"neutral\" variant=\"soft\" size=\"xxs\" count={s.skipped} />}\n {s.running > 0 && <Badge tone=\"info\" variant=\"solid\" size=\"xxs\" count={s.running} />}\n {s.pending > 0 && <Badge tone=\"neutral\" variant=\"soft\" size=\"xxs\" count={s.pending} />}\n </span>\n );\n}\n\n/**\n * Renders one test tree row: status icon, optional adapter decoration + framework\n * icon, status-colored name, duration, per-status count badges, and (when the\n * runner exposes the handlers) rerun/stop buttons. Designed as the `renderRow`\n * for the clicky `Tree`.\n */\nexport function TestTreeNode({ node, selected }: { node: Test; selected: boolean }) {\n const runner = useTestRunner();\n const hasChildren = (node.children?.length ?? 0) > 0;\n const status = testStatus(node);\n const outcome = outcomeFor(node);\n const fwAdapter = runner.adapters.resolveFrameworkIcon(node, runner);\n const fwNode = fwAdapter?.renderFrameworkIcon?.({ node, runner });\n const leadingAdapter = runner.adapters.resolveRowLeading(node, runner);\n const dur = node.duration || (hasChildren ? totalDuration(node) : 0);\n const canRerun = !!runner.onRerun && node.framework !== \"task\";\n const canStop = !!runner.onStop && !!node.can_stop && !!node.task_id;\n const showMessage = status && (MESSAGE_STATUSES.has(status) || (node.framework === \"task\" && (status === \"running\" || status === \"pending\")));\n const message = showMessage ? (node.message ?? \"\").trim() : \"\";\n\n return (\n <>\n {outcome ? (\n <OutcomeIcon outcome={outcome} />\n ) : (\n <Icon icon={UiClass} className=\"shrink-0 text-muted-foreground\" />\n )}\n\n {fwNode != null ? (\n <span className=\"flex shrink-0 items-center text-sm\">{fwNode}</span>\n ) : (\n <ToolIcon tool={toolKeyFor(node)} className=\"text-sm\" />\n )}\n\n {leadingAdapter?.renderRowLeading?.({ node, runner })}\n\n <span\n className={cn(\n \"min-w-0 truncate\",\n selected ? \"font-semibold\" : \"font-medium\",\n (status && NAME_TONE[status]) || \"text-foreground\",\n )}\n title={message || undefined}\n >\n {humanizeName(node.name, node.framework)}\n </span>\n {/* The verdict trails the name on the same line and gives way first. */}\n {message ? (\n <span\n className=\"min-w-0 flex-1 shrink-[100] truncate text-xs text-muted-foreground\"\n title={message}\n data-row-message=\"\"\n >\n {message}\n </span>\n ) : (\n <span className=\"flex-1\" />\n )}\n\n {node.progress && node.progress.total > 0 && !node.passed && !node.failed && (\n <span className=\"flex shrink-0 items-center gap-1 text-xs text-blue-600 dark:text-blue-400\">\n {node.progress.phase && <span>{node.progress.phase}</span>}\n <span className=\"tabular-nums\">\n {node.progress.done}/{node.progress.total}\n </span>\n </span>\n )}\n\n {dur > 0 && (\n <span className=\"shrink-0 text-xs text-muted-foreground\">{formatTestDuration(dur)}</span>\n )}\n\n {hasChildren && <CountBadges node={node} />}\n\n {canStop && (\n <IconButton\n icon={UiStop}\n label=\"Stop\"\n disabled={runner.busy.stop}\n onClick={(e) => {\n e.stopPropagation();\n runner.onStop!(node);\n }}\n />\n )}\n\n {canRerun && (\n <IconButton\n icon={UiRefresh}\n label=\"Rerun\"\n disabled={runner.busy.rerun}\n onClick={(e) => {\n e.stopPropagation();\n runner.onRerun!(node);\n }}\n />\n )}\n </>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"TestTreeNode.js","names":["_Fragment"],"sources":["../../../src/data/test-runner/TestTreeNode.tsx"],"sourcesContent":["import { Icon } from \"../Icon\";\nimport { Badge } from \"../Badge\";\nimport { IconButton } from \"../../components/IconButton\";\nimport { UiClass, UiRefresh, UiStop } from \"../../icons\";\nimport { cn } from \"../../lib/utils\";\nimport type { Test } from \"./types\";\nimport { useTestRunner } from \"./context\";\nimport {\n formatTestDuration,\n humanizeName,\n outcomeFor,\n sum,\n testStatus,\n totalDuration,\n} from \"./status\";\nimport { toolKeyFor } from \"./marks\";\nimport { OutcomeIcon, ToolIcon } from \"./MarkIcons\";\n\nconst NAME_TONE: Record<string, string> = {\n failed: \"text-red-600 dark:text-red-400\",\n timedout: \"text-amber-600 dark:text-amber-400\",\n warned: \"text-amber-600 dark:text-amber-400\",\n aborted: \"text-muted-foreground\",\n running: \"text-blue-600 dark:text-blue-400\",\n skipped: \"text-muted-foreground\",\n pending: \"text-muted-foreground\",\n passed: \"text-foreground\",\n};\n\nconst MESSAGE_STATUSES = new Set([\"failed\", \"timedout\", \"warned\", \"aborted\", \"skipped\"]);\n\n/** Per-status roll-up count badges shown on a container row. */\nfunction CountBadges({ node }: { node: Test }) {\n const s = sum(node);\n if (s.total === 0) return null;\n return (\n <span className=\"flex shrink-0 items-center gap-1\">\n {s.passed > 0 && <Badge tone=\"success\" variant=\"solid\" size=\"xxs\" count={s.passed} />}\n {s.failed > 0 && <Badge tone=\"danger\" variant=\"solid\" size=\"xxs\" count={s.failed} />}\n {s.warned > 0 && <Badge tone=\"warning\" variant=\"outline\" size=\"xxs\" count={s.warned} />}\n {s.timedout > 0 && <Badge tone=\"warning\" variant=\"solid\" size=\"xxs\" count={s.timedout} />}\n {s.aborted > 0 && <Badge tone=\"neutral\" variant=\"soft\" size=\"xxs\" count={s.aborted} />}\n {s.skipped > 0 && <Badge tone=\"neutral\" variant=\"soft\" size=\"xxs\" count={s.skipped} />}\n {s.running > 0 && <Badge tone=\"info\" variant=\"solid\" size=\"xxs\" count={s.running} />}\n {s.pending > 0 && <Badge tone=\"neutral\" variant=\"soft\" size=\"xxs\" count={s.pending} />}\n </span>\n );\n}\n\n/**\n * Renders one test tree row: status icon, optional adapter decoration + framework\n * icon, status-colored name, duration, per-status count badges, and (when the\n * runner exposes the handlers) rerun/stop buttons. Designed as the `renderRow`\n * for the clicky `Tree`.\n */\nexport function TestTreeNode({ node, selected }: { node: Test; selected: boolean }) {\n const runner = useTestRunner();\n const hasChildren = (node.children?.length ?? 0) > 0;\n const status = testStatus(node);\n const outcome = outcomeFor(node);\n const fwAdapter = runner.adapters.resolveFrameworkIcon(node, runner);\n const fwNode = fwAdapter?.renderFrameworkIcon?.({ node, runner });\n const leadingAdapter = runner.adapters.resolveRowLeading(node, runner);\n const dur = node.duration || (hasChildren ? totalDuration(node) : 0);\n const canRerun = !!runner.onRerun && node.framework !== \"task\";\n const canStop = !!runner.onStop && !!node.can_stop && !!node.task_id;\n const showMessage = status && (MESSAGE_STATUSES.has(status) || (node.framework === \"task\" && (status === \"running\" || status === \"pending\")));\n const message = showMessage ? (node.message ?? \"\").trim() : \"\";\n\n return (\n <>\n {outcome ? (\n <OutcomeIcon outcome={outcome} />\n ) : (\n <Icon icon={UiClass} className=\"shrink-0 text-muted-foreground\" />\n )}\n\n {fwNode != null ? (\n <span className=\"flex shrink-0 items-center text-sm\">{fwNode}</span>\n ) : (\n <ToolIcon tool={toolKeyFor(node)} className=\"text-sm\" />\n )}\n\n {leadingAdapter?.renderRowLeading?.({ node, runner })}\n\n <span\n className={cn(\n \"min-w-0 truncate\",\n selected ? \"font-semibold\" : \"font-medium\",\n (status && NAME_TONE[status]) || \"text-foreground\",\n )}\n title={message || undefined}\n >\n {humanizeName(node.name, node.framework)}\n </span>\n {/* The verdict trails the name on the same line and gives way first. */}\n {message ? (\n <span\n className=\"min-w-0 flex-1 shrink-[100] truncate text-xs text-muted-foreground\"\n title={message}\n data-row-message=\"\"\n >\n {message}\n </span>\n ) : (\n <span className=\"flex-1\" />\n )}\n\n {node.progress && node.progress.total > 0 && !node.passed && !node.failed && (\n <span className=\"flex shrink-0 items-center gap-1 text-xs text-blue-600 dark:text-blue-400\">\n {node.progress.phase && <span>{node.progress.phase}</span>}\n <span className=\"tabular-nums\">\n {node.progress.done}/{node.progress.total}\n </span>\n </span>\n )}\n\n {dur > 0 && (\n <span className=\"shrink-0 text-xs text-muted-foreground\">{formatTestDuration(dur)}</span>\n )}\n\n {hasChildren && <CountBadges node={node} />}\n\n {canStop && (\n <IconButton\n icon={UiStop}\n label=\"Stop\"\n disabled={runner.busy.stop}\n onClick={(e) => {\n e.stopPropagation();\n runner.onStop!(node);\n }}\n />\n )}\n\n {canRerun && (\n <IconButton\n icon={UiRefresh}\n label=\"Rerun\"\n disabled={runner.busy.rerun}\n onClick={(e) => {\n e.stopPropagation();\n runner.onRerun!(node);\n }}\n />\n )}\n </>\n );\n}\n"],"mappings":"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"}
@@ -28,6 +28,13 @@ var TestNodeAdapterRegistry = class {
28
28
  resolveActions(node, runner) {
29
29
  return this.firstWith(node, runner, (a) => !!a.nodeActions);
30
30
  }
31
+ resolveTreeChildren(node, runner) {
32
+ const adapter = this.firstWith(node, runner, (a) => !!a.treeChildren);
33
+ return adapter?.treeChildren ? adapter.treeChildren({
34
+ node,
35
+ runner
36
+ }) : node.children;
37
+ }
31
38
  /**
32
39
  * Attempts for the header chooser: the first matching adapter's
33
40
  * `detailAttempts`, else the node's own `attempts` (the built-in default,
@@ -1 +1 @@
1
- {"version":3,"file":"adapter.cjs","names":["testAttemptViews","mergeCopySections"],"sources":["../../../src/data/test-runner/adapter.ts"],"sourcesContent":["// Node adapters let a host plug domain-specific rendering into the test runner\n// without forking it. An adapter claims nodes via `match` and contributes how\n// they render in each surface (tree row, detail body, detail tabs, header\n// actions). The registry resolves the first matching adapter per surface;\n// surfaces with no match fall back to the runner's built-in default rendering.\n//\n// This formalizes the wrapper-with-an-if-chain pattern hosts use today (e.g.\n// a ResultDetailPane fall-through over domain panels + tab providers + per-step\n// actions) into a registered, composable contract.\n\nimport type { ReactNode } from \"react\";\nimport type { Test } from \"./types\";\nimport type { TestRunnerContext } from \"./context\";\nimport { mergeCopySections, type CopySections } from \"./copy\";\nimport { testAttemptViews } from \"./attempts\";\n\nexport type AdapterContext = {\n node: Test;\n runner: TestRunnerContext;\n};\n\nexport type DetailTab = {\n id: string;\n label: string;\n render: () => ReactNode;\n};\n\nexport type DetailAttempt = { id: number; status: string; durationMs?: number; node: Test };\n\nexport type TestNodeAdapter = {\n /** Stable identifier, used as a React key and for debugging. */\n id: string;\n /** Claim the node. The first registered adapter to return true wins per surface. */\n match: (node: Test, runner: TestRunnerContext) => boolean;\n /**\n * Replace the framework icon for the node — return any node, or null to fall\n * back to the built-in tool mark (`TEST_TOOLS`). For a tool the catalog\n * lacks, prefer adding it to `TEST_TOOLS` so every surface shows it.\n */\n renderFrameworkIcon?: (c: AdapterContext) => ReactNode;\n /** Extra decoration rendered between the framework icon and the node name. */\n renderRowLeading?: (c: AdapterContext) => ReactNode;\n /** Primary detail body for the node, replacing the default panel body. */\n renderDetail?: (c: AdapterContext) => ReactNode;\n /** Extra detail tabs, merged (in registration order) across all matching adapters. */\n detailTabs?: (c: AdapterContext) => DetailTab[];\n /** Stored attempt views for the header chooser; tree and run totals remain step-level. */\n detailAttempts?: (c: AdapterContext) => DetailAttempt[];\n /** Node-scoped action buttons rendered in the detail header. */\n nodeActions?: (c: AdapterContext) => ReactNode;\n /**\n * Domain facts, brief sections and menu items for the header's \"Copy details\"\n * button, merged (in registration order) across all matching adapters on top\n * of the generic sections every node gets.\n */\n copy?: (c: AdapterContext) => CopySections;\n /**\n * Whether `renderDetail` owns its own full-height scroll container. When\n * false (the default for custom bodies), the panel wraps it in a scroll\n * region. The built-in default body owns its scroll.\n */\n ownsScroll?: (c: AdapterContext) => boolean;\n};\n\n/**\n * Ordered set of node adapters. First match wins per surface; `detailTabs` and\n * `copy` are the exceptions — they merge across every matching adapter so\n * independent adapters can each contribute a tab or a copy section.\n */\nexport class TestNodeAdapterRegistry {\n readonly adapters: TestNodeAdapter[];\n\n constructor(adapters: TestNodeAdapter[] = []) {\n this.adapters = adapters;\n }\n\n private firstWith(\n node: Test,\n runner: TestRunnerContext,\n has: (a: TestNodeAdapter) => boolean,\n ): TestNodeAdapter | null {\n for (const a of this.adapters) {\n if (has(a) && a.match(node, runner)) return a;\n }\n return null;\n }\n\n /** Adapter whose `renderDetail` should drive the body, or null for the default. */\n resolveDetail(node: Test, runner: TestRunnerContext): TestNodeAdapter | null {\n return this.firstWith(node, runner, (a) => !!a.renderDetail);\n }\n\n resolveRowLeading(node: Test, runner: TestRunnerContext): TestNodeAdapter | null {\n return this.firstWith(node, runner, (a) => !!a.renderRowLeading);\n }\n\n resolveFrameworkIcon(node: Test, runner: TestRunnerContext): TestNodeAdapter | null {\n return this.firstWith(node, runner, (a) => !!a.renderFrameworkIcon);\n }\n\n resolveActions(node: Test, runner: TestRunnerContext): TestNodeAdapter | null {\n return this.firstWith(node, runner, (a) => !!a.nodeActions);\n }\n\n /**\n * Attempts for the header chooser: the first matching adapter's\n * `detailAttempts`, else the node's own `attempts` (the built-in default,\n * which always sits behind the registered adapters).\n */\n resolveAttempts(node: Test, runner: TestRunnerContext): DetailAttempt[] {\n const adapted = this.firstWith(node, runner, (a) => !!a.detailAttempts)?.detailAttempts?.({ node, runner });\n if (adapted && adapted.length > 0) return adapted;\n return testAttemptViews(node);\n }\n\n /** Merge `detailTabs` from every matching adapter, de-duplicated by tab id. */\n resolveTabs(node: Test, runner: TestRunnerContext): DetailTab[] {\n const ctx: AdapterContext = { node, runner };\n const seen = new Set<string>();\n const tabs: DetailTab[] = [];\n for (const a of this.adapters) {\n if (!a.detailTabs || !a.match(node, runner)) continue;\n for (const tab of a.detailTabs(ctx)) {\n if (seen.has(tab.id)) continue;\n seen.add(tab.id);\n tabs.push(tab);\n }\n }\n return tabs;\n }\n\n /**\n * Merge `copy` sections from every matching adapter, de-duplicated by fact\n * label, section title and item label — the first contributor wins.\n */\n resolveCopy(node: Test, runner: TestRunnerContext): Required<CopySections> {\n const ctx: AdapterContext = { node, runner };\n return mergeCopySections(\n this.adapters.flatMap((a) => (a.copy && a.match(node, runner) ? [a.copy(ctx)] : [])),\n );\n }\n\n /** True when the resolved detail adapter owns its own scroll region. */\n ownsScroll(node: Test, runner: TestRunnerContext): boolean {\n const a = this.resolveDetail(node, runner);\n if (!a?.ownsScroll) return false;\n return a.ownsScroll({ node, runner });\n }\n}\n\nexport function createTestRunnerRegistry(\n adapters: TestNodeAdapter[] = [],\n): TestNodeAdapterRegistry {\n return new TestNodeAdapterRegistry(adapters);\n}\n"],"mappings":";;;;;;;;AAqEA,IAAa,0BAAb,MAAqC;CACnC;CAEA,YAAY,WAA8B,CAAC,GAAG;EAC5C,KAAK,WAAW;CAClB;CAEA,UACE,MACA,QACA,KACwB;EACxB,KAAK,MAAM,KAAK,KAAK,UACnB,IAAI,IAAI,CAAC,KAAK,EAAE,MAAM,MAAM,MAAM,GAAG,OAAO;EAE9C,OAAO;CACT;;CAGA,cAAc,MAAY,QAAmD;EAC3E,OAAO,KAAK,UAAU,MAAM,SAAS,MAAM,CAAC,CAAC,EAAE,YAAY;CAC7D;CAEA,kBAAkB,MAAY,QAAmD;EAC/E,OAAO,KAAK,UAAU,MAAM,SAAS,MAAM,CAAC,CAAC,EAAE,gBAAgB;CACjE;CAEA,qBAAqB,MAAY,QAAmD;EAClF,OAAO,KAAK,UAAU,MAAM,SAAS,MAAM,CAAC,CAAC,EAAE,mBAAmB;CACpE;CAEA,eAAe,MAAY,QAAmD;EAC5E,OAAO,KAAK,UAAU,MAAM,SAAS,MAAM,CAAC,CAAC,EAAE,WAAW;CAC5D;;;;;;CAOA,gBAAgB,MAAY,QAA4C;EACtE,MAAM,UAAU,KAAK,UAAU,MAAM,SAAS,MAAM,CAAC,CAAC,EAAE,cAAc,CAAC,EAAE,iBAAiB;GAAE;GAAM;EAAO,CAAC;EAC1G,IAAI,WAAW,QAAQ,SAAS,GAAG,OAAO;EAC1C,OAAOA,iBAAAA,iBAAiB,IAAI;CAC9B;;CAGA,YAAY,MAAY,QAAwC;EAC9D,MAAM,MAAsB;GAAE;GAAM;EAAO;EAC3C,MAAM,uBAAO,IAAI,IAAY;EAC7B,MAAM,OAAoB,CAAC;EAC3B,KAAK,MAAM,KAAK,KAAK,UAAU;GAC7B,IAAI,CAAC,EAAE,cAAc,CAAC,EAAE,MAAM,MAAM,MAAM,GAAG;GAC7C,KAAK,MAAM,OAAO,EAAE,WAAW,GAAG,GAAG;IACnC,IAAI,KAAK,IAAI,IAAI,EAAE,GAAG;IACtB,KAAK,IAAI,IAAI,EAAE;IACf,KAAK,KAAK,GAAG;GACf;EACF;EACA,OAAO;CACT;;;;;CAMA,YAAY,MAAY,QAAmD;EACzE,MAAM,MAAsB;GAAE;GAAM;EAAO;EAC3C,OAAOC,aAAAA,kBACL,KAAK,SAAS,SAAS,MAAO,EAAE,QAAQ,EAAE,MAAM,MAAM,MAAM,IAAI,CAAC,EAAE,KAAK,GAAG,CAAC,IAAI,CAAC,CAAE,CACrF;CACF;;CAGA,WAAW,MAAY,QAAoC;EACzD,MAAM,IAAI,KAAK,cAAc,MAAM,MAAM;EACzC,IAAI,CAAC,GAAG,YAAY,OAAO;EAC3B,OAAO,EAAE,WAAW;GAAE;GAAM;EAAO,CAAC;CACtC;AACF;AAEA,SAAgB,yBACd,WAA8B,CAAC,GACN;CACzB,OAAO,IAAI,wBAAwB,QAAQ;AAC7C"}
1
+ {"version":3,"file":"adapter.cjs","names":["testAttemptViews","mergeCopySections"],"sources":["../../../src/data/test-runner/adapter.ts"],"sourcesContent":["// Node adapters let a host plug domain-specific rendering into the test runner\n// without forking it. An adapter claims nodes via `match` and contributes how\n// they render in each surface (tree row, detail body, detail tabs, header\n// actions). The registry resolves the first matching adapter per surface;\n// surfaces with no match fall back to the runner's built-in default rendering.\n//\n// This formalizes the wrapper-with-an-if-chain pattern hosts use today (e.g.\n// a ResultDetailPane fall-through over domain panels + tab providers + per-step\n// actions) into a registered, composable contract.\n\nimport type { ReactNode } from \"react\";\nimport type { Test } from \"./types\";\nimport type { TestRunnerContext } from \"./context\";\nimport { mergeCopySections, type CopySections } from \"./copy\";\nimport { testAttemptViews } from \"./attempts\";\n\nexport type AdapterContext = {\n node: Test;\n runner: TestRunnerContext;\n};\n\nexport type DetailTab = {\n id: string;\n label: string;\n render: () => ReactNode;\n};\n\nexport type DetailAttempt = { id: number; status: string; durationMs?: number; node: Test };\n\nexport type TestNodeAdapter = {\n /** Stable identifier, used as a React key and for debugging. */\n id: string;\n /** Claim the node. The first registered adapter to return true wins per surface. */\n match: (node: Test, runner: TestRunnerContext) => boolean;\n /**\n * Children shown in the navigation tree; results and status rollups stay intact.\n * Return [] to render a node as a leaf. Without a matching hook, uses node.children.\n * @example { id: \"setup-leaf\", match: node => node.name === \"setup\", treeChildren: () => [] }\n */\n treeChildren?: (c: AdapterContext) => Test[] | undefined;\n /**\n * Replace the framework icon for the node — return any node, or null to fall\n * back to the built-in tool mark (`TEST_TOOLS`). For a tool the catalog\n * lacks, prefer adding it to `TEST_TOOLS` so every surface shows it.\n */\n renderFrameworkIcon?: (c: AdapterContext) => ReactNode;\n /** Extra decoration rendered between the framework icon and the node name. */\n renderRowLeading?: (c: AdapterContext) => ReactNode;\n /** Primary detail body for the node, replacing the default panel body. */\n renderDetail?: (c: AdapterContext) => ReactNode;\n /** Extra detail tabs, merged (in registration order) across all matching adapters. */\n detailTabs?: (c: AdapterContext) => DetailTab[];\n /** Stored attempt views for the header chooser; tree and run totals remain step-level. */\n detailAttempts?: (c: AdapterContext) => DetailAttempt[];\n /** Node-scoped action buttons rendered in the detail header. */\n nodeActions?: (c: AdapterContext) => ReactNode;\n /**\n * Domain facts, brief sections and menu items for the header's \"Copy details\"\n * button, merged (in registration order) across all matching adapters on top\n * of the generic sections every node gets.\n */\n copy?: (c: AdapterContext) => CopySections;\n /**\n * Whether `renderDetail` owns its own full-height scroll container. When\n * false (the default for custom bodies), the panel wraps it in a scroll\n * region. The built-in default body owns its scroll.\n */\n ownsScroll?: (c: AdapterContext) => boolean;\n};\n\n/**\n * Ordered set of node adapters. First match wins per surface; `detailTabs` and\n * `copy` are the exceptions — they merge across every matching adapter so\n * independent adapters can each contribute a tab or a copy section.\n */\nexport class TestNodeAdapterRegistry {\n readonly adapters: TestNodeAdapter[];\n\n constructor(adapters: TestNodeAdapter[] = []) {\n this.adapters = adapters;\n }\n\n private firstWith(\n node: Test,\n runner: TestRunnerContext,\n has: (a: TestNodeAdapter) => boolean,\n ): TestNodeAdapter | null {\n for (const a of this.adapters) {\n if (has(a) && a.match(node, runner)) return a;\n }\n return null;\n }\n\n /** Adapter whose `renderDetail` should drive the body, or null for the default. */\n resolveDetail(node: Test, runner: TestRunnerContext): TestNodeAdapter | null {\n return this.firstWith(node, runner, (a) => !!a.renderDetail);\n }\n\n resolveRowLeading(node: Test, runner: TestRunnerContext): TestNodeAdapter | null {\n return this.firstWith(node, runner, (a) => !!a.renderRowLeading);\n }\n\n resolveFrameworkIcon(node: Test, runner: TestRunnerContext): TestNodeAdapter | null {\n return this.firstWith(node, runner, (a) => !!a.renderFrameworkIcon);\n }\n\n resolveActions(node: Test, runner: TestRunnerContext): TestNodeAdapter | null {\n return this.firstWith(node, runner, (a) => !!a.nodeActions);\n }\n\n resolveTreeChildren(node: Test, runner: TestRunnerContext): Test[] | undefined {\n const adapter = this.firstWith(node, runner, (a) => !!a.treeChildren);\n return adapter?.treeChildren ? adapter.treeChildren({ node, runner }) : node.children;\n }\n\n /**\n * Attempts for the header chooser: the first matching adapter's\n * `detailAttempts`, else the node's own `attempts` (the built-in default,\n * which always sits behind the registered adapters).\n */\n resolveAttempts(node: Test, runner: TestRunnerContext): DetailAttempt[] {\n const adapted = this.firstWith(node, runner, (a) => !!a.detailAttempts)?.detailAttempts?.({ node, runner });\n if (adapted && adapted.length > 0) return adapted;\n return testAttemptViews(node);\n }\n\n /** Merge `detailTabs` from every matching adapter, de-duplicated by tab id. */\n resolveTabs(node: Test, runner: TestRunnerContext): DetailTab[] {\n const ctx: AdapterContext = { node, runner };\n const seen = new Set<string>();\n const tabs: DetailTab[] = [];\n for (const a of this.adapters) {\n if (!a.detailTabs || !a.match(node, runner)) continue;\n for (const tab of a.detailTabs(ctx)) {\n if (seen.has(tab.id)) continue;\n seen.add(tab.id);\n tabs.push(tab);\n }\n }\n return tabs;\n }\n\n /**\n * Merge `copy` sections from every matching adapter, de-duplicated by fact\n * label, section title and item label — the first contributor wins.\n */\n resolveCopy(node: Test, runner: TestRunnerContext): Required<CopySections> {\n const ctx: AdapterContext = { node, runner };\n return mergeCopySections(\n this.adapters.flatMap((a) => (a.copy && a.match(node, runner) ? [a.copy(ctx)] : [])),\n );\n }\n\n /** True when the resolved detail adapter owns its own scroll region. */\n ownsScroll(node: Test, runner: TestRunnerContext): boolean {\n const a = this.resolveDetail(node, runner);\n if (!a?.ownsScroll) return false;\n return a.ownsScroll({ node, runner });\n }\n}\n\nexport function createTestRunnerRegistry(\n adapters: TestNodeAdapter[] = [],\n): TestNodeAdapterRegistry {\n return new TestNodeAdapterRegistry(adapters);\n}\n"],"mappings":";;;;;;;;AA2EA,IAAa,0BAAb,MAAqC;CACnC;CAEA,YAAY,WAA8B,CAAC,GAAG;EAC5C,KAAK,WAAW;CAClB;CAEA,UACE,MACA,QACA,KACwB;EACxB,KAAK,MAAM,KAAK,KAAK,UACnB,IAAI,IAAI,CAAC,KAAK,EAAE,MAAM,MAAM,MAAM,GAAG,OAAO;EAE9C,OAAO;CACT;;CAGA,cAAc,MAAY,QAAmD;EAC3E,OAAO,KAAK,UAAU,MAAM,SAAS,MAAM,CAAC,CAAC,EAAE,YAAY;CAC7D;CAEA,kBAAkB,MAAY,QAAmD;EAC/E,OAAO,KAAK,UAAU,MAAM,SAAS,MAAM,CAAC,CAAC,EAAE,gBAAgB;CACjE;CAEA,qBAAqB,MAAY,QAAmD;EAClF,OAAO,KAAK,UAAU,MAAM,SAAS,MAAM,CAAC,CAAC,EAAE,mBAAmB;CACpE;CAEA,eAAe,MAAY,QAAmD;EAC5E,OAAO,KAAK,UAAU,MAAM,SAAS,MAAM,CAAC,CAAC,EAAE,WAAW;CAC5D;CAEA,oBAAoB,MAAY,QAA+C;EAC7E,MAAM,UAAU,KAAK,UAAU,MAAM,SAAS,MAAM,CAAC,CAAC,EAAE,YAAY;EACpE,OAAO,SAAS,eAAe,QAAQ,aAAa;GAAE;GAAM;EAAO,CAAC,IAAI,KAAK;CAC/E;;;;;;CAOA,gBAAgB,MAAY,QAA4C;EACtE,MAAM,UAAU,KAAK,UAAU,MAAM,SAAS,MAAM,CAAC,CAAC,EAAE,cAAc,CAAC,EAAE,iBAAiB;GAAE;GAAM;EAAO,CAAC;EAC1G,IAAI,WAAW,QAAQ,SAAS,GAAG,OAAO;EAC1C,OAAOA,iBAAAA,iBAAiB,IAAI;CAC9B;;CAGA,YAAY,MAAY,QAAwC;EAC9D,MAAM,MAAsB;GAAE;GAAM;EAAO;EAC3C,MAAM,uBAAO,IAAI,IAAY;EAC7B,MAAM,OAAoB,CAAC;EAC3B,KAAK,MAAM,KAAK,KAAK,UAAU;GAC7B,IAAI,CAAC,EAAE,cAAc,CAAC,EAAE,MAAM,MAAM,MAAM,GAAG;GAC7C,KAAK,MAAM,OAAO,EAAE,WAAW,GAAG,GAAG;IACnC,IAAI,KAAK,IAAI,IAAI,EAAE,GAAG;IACtB,KAAK,IAAI,IAAI,EAAE;IACf,KAAK,KAAK,GAAG;GACf;EACF;EACA,OAAO;CACT;;;;;CAMA,YAAY,MAAY,QAAmD;EACzE,MAAM,MAAsB;GAAE;GAAM;EAAO;EAC3C,OAAOC,aAAAA,kBACL,KAAK,SAAS,SAAS,MAAO,EAAE,QAAQ,EAAE,MAAM,MAAM,MAAM,IAAI,CAAC,EAAE,KAAK,GAAG,CAAC,IAAI,CAAC,CAAE,CACrF;CACF;;CAGA,WAAW,MAAY,QAAoC;EACzD,MAAM,IAAI,KAAK,cAAc,MAAM,MAAM;EACzC,IAAI,CAAC,GAAG,YAAY,OAAO;EAC3B,OAAO,EAAE,WAAW;GAAE;GAAM;EAAO,CAAC;CACtC;AACF;AAEA,SAAgB,yBACd,WAA8B,CAAC,GACN;CACzB,OAAO,IAAI,wBAAwB,QAAQ;AAC7C"}
@@ -22,6 +22,12 @@ export type TestNodeAdapter = {
22
22
  id: string;
23
23
  /** Claim the node. The first registered adapter to return true wins per surface. */
24
24
  match: (node: Test, runner: TestRunnerContext) => boolean;
25
+ /**
26
+ * Children shown in the navigation tree; results and status rollups stay intact.
27
+ * Return [] to render a node as a leaf. Without a matching hook, uses node.children.
28
+ * @example { id: "setup-leaf", match: node => node.name === "setup", treeChildren: () => [] }
29
+ */
30
+ treeChildren?: (c: AdapterContext) => Test[] | undefined;
25
31
  /**
26
32
  * Replace the framework icon for the node — return any node, or null to fall
27
33
  * back to the built-in tool mark (`TEST_TOOLS`). For a tool the catalog
@@ -65,6 +71,7 @@ export declare class TestNodeAdapterRegistry {
65
71
  resolveRowLeading(node: Test, runner: TestRunnerContext): TestNodeAdapter | null;
66
72
  resolveFrameworkIcon(node: Test, runner: TestRunnerContext): TestNodeAdapter | null;
67
73
  resolveActions(node: Test, runner: TestRunnerContext): TestNodeAdapter | null;
74
+ resolveTreeChildren(node: Test, runner: TestRunnerContext): Test[] | undefined;
68
75
  /**
69
76
  * Attempts for the header chooser: the first matching adapter's
70
77
  * `detailAttempts`, else the node's own `attempts` (the built-in default,
@@ -1 +1 @@
1
- {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../src/data/test-runner/adapter.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAqB,KAAK,YAAY,EAAE,MAAM,QAAQ,CAAC;AAG9D,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,IAAI,CAAC;IACX,MAAM,EAAE,iBAAiB,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,SAAS,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,IAAI,CAAA;CAAE,CAAC;AAE5F,MAAM,MAAM,eAAe,GAAG;IAC5B,gEAAgE;IAChE,EAAE,EAAE,MAAM,CAAC;IACX,oFAAoF;IACpF,KAAK,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,iBAAiB,KAAK,OAAO,CAAC;IAC1D;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,CAAC,CAAC,EAAE,cAAc,KAAK,SAAS,CAAC;IACvD,8EAA8E;IAC9E,gBAAgB,CAAC,EAAE,CAAC,CAAC,EAAE,cAAc,KAAK,SAAS,CAAC;IACpD,0EAA0E;IAC1E,YAAY,CAAC,EAAE,CAAC,CAAC,EAAE,cAAc,KAAK,SAAS,CAAC;IAChD,sFAAsF;IACtF,UAAU,CAAC,EAAE,CAAC,CAAC,EAAE,cAAc,KAAK,SAAS,EAAE,CAAC;IAChD,0FAA0F;IAC1F,cAAc,CAAC,EAAE,CAAC,CAAC,EAAE,cAAc,KAAK,aAAa,EAAE,CAAC;IACxD,gEAAgE;IAChE,WAAW,CAAC,EAAE,CAAC,CAAC,EAAE,cAAc,KAAK,SAAS,CAAC;IAC/C;;;;OAIG;IACH,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,cAAc,KAAK,YAAY,CAAC;IAC3C;;;;OAIG;IACH,UAAU,CAAC,EAAE,CAAC,CAAC,EAAE,cAAc,KAAK,OAAO,CAAC;CAC7C,CAAC;AAEF;;;;GAIG;AACH,qBAAa,uBAAuB;IAClC,QAAQ,CAAC,QAAQ,EAAE,eAAe,EAAE,CAAC;gBAEzB,QAAQ,GAAE,eAAe,EAAO;IAI5C,OAAO,CAAC,SAAS;IAWjB,mFAAmF;IACnF,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,iBAAiB,GAAG,eAAe,GAAG,IAAI;IAI5E,iBAAiB,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,iBAAiB,GAAG,eAAe,GAAG,IAAI;IAIhF,oBAAoB,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,iBAAiB,GAAG,eAAe,GAAG,IAAI;IAInF,cAAc,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,iBAAiB,GAAG,eAAe,GAAG,IAAI;IAI7E;;;;OAIG;IACH,eAAe,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,iBAAiB,GAAG,aAAa,EAAE;IAMvE,+EAA+E;IAC/E,WAAW,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,iBAAiB,GAAG,SAAS,EAAE;IAe/D;;;OAGG;IACH,WAAW,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,iBAAiB,GAAG,QAAQ,CAAC,YAAY,CAAC;IAO1E,wEAAwE;IACxE,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,iBAAiB,GAAG,OAAO;CAK3D;AAED,wBAAgB,wBAAwB,CACtC,QAAQ,GAAE,eAAe,EAAO,GAC/B,uBAAuB,CAEzB"}
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../src/data/test-runner/adapter.ts"],"names":[],"mappings":"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"}
@@ -28,6 +28,13 @@ var TestNodeAdapterRegistry = class {
28
28
  resolveActions(node, runner) {
29
29
  return this.firstWith(node, runner, (a) => !!a.nodeActions);
30
30
  }
31
+ resolveTreeChildren(node, runner) {
32
+ const adapter = this.firstWith(node, runner, (a) => !!a.treeChildren);
33
+ return adapter?.treeChildren ? adapter.treeChildren({
34
+ node,
35
+ runner
36
+ }) : node.children;
37
+ }
31
38
  /**
32
39
  * Attempts for the header chooser: the first matching adapter's
33
40
  * `detailAttempts`, else the node's own `attempts` (the built-in default,
@@ -1 +1 @@
1
- {"version":3,"file":"adapter.js","names":[],"sources":["../../../src/data/test-runner/adapter.ts"],"sourcesContent":["// Node adapters let a host plug domain-specific rendering into the test runner\n// without forking it. An adapter claims nodes via `match` and contributes how\n// they render in each surface (tree row, detail body, detail tabs, header\n// actions). The registry resolves the first matching adapter per surface;\n// surfaces with no match fall back to the runner's built-in default rendering.\n//\n// This formalizes the wrapper-with-an-if-chain pattern hosts use today (e.g.\n// a ResultDetailPane fall-through over domain panels + tab providers + per-step\n// actions) into a registered, composable contract.\n\nimport type { ReactNode } from \"react\";\nimport type { Test } from \"./types\";\nimport type { TestRunnerContext } from \"./context\";\nimport { mergeCopySections, type CopySections } from \"./copy\";\nimport { testAttemptViews } from \"./attempts\";\n\nexport type AdapterContext = {\n node: Test;\n runner: TestRunnerContext;\n};\n\nexport type DetailTab = {\n id: string;\n label: string;\n render: () => ReactNode;\n};\n\nexport type DetailAttempt = { id: number; status: string; durationMs?: number; node: Test };\n\nexport type TestNodeAdapter = {\n /** Stable identifier, used as a React key and for debugging. */\n id: string;\n /** Claim the node. The first registered adapter to return true wins per surface. */\n match: (node: Test, runner: TestRunnerContext) => boolean;\n /**\n * Replace the framework icon for the node — return any node, or null to fall\n * back to the built-in tool mark (`TEST_TOOLS`). For a tool the catalog\n * lacks, prefer adding it to `TEST_TOOLS` so every surface shows it.\n */\n renderFrameworkIcon?: (c: AdapterContext) => ReactNode;\n /** Extra decoration rendered between the framework icon and the node name. */\n renderRowLeading?: (c: AdapterContext) => ReactNode;\n /** Primary detail body for the node, replacing the default panel body. */\n renderDetail?: (c: AdapterContext) => ReactNode;\n /** Extra detail tabs, merged (in registration order) across all matching adapters. */\n detailTabs?: (c: AdapterContext) => DetailTab[];\n /** Stored attempt views for the header chooser; tree and run totals remain step-level. */\n detailAttempts?: (c: AdapterContext) => DetailAttempt[];\n /** Node-scoped action buttons rendered in the detail header. */\n nodeActions?: (c: AdapterContext) => ReactNode;\n /**\n * Domain facts, brief sections and menu items for the header's \"Copy details\"\n * button, merged (in registration order) across all matching adapters on top\n * of the generic sections every node gets.\n */\n copy?: (c: AdapterContext) => CopySections;\n /**\n * Whether `renderDetail` owns its own full-height scroll container. When\n * false (the default for custom bodies), the panel wraps it in a scroll\n * region. The built-in default body owns its scroll.\n */\n ownsScroll?: (c: AdapterContext) => boolean;\n};\n\n/**\n * Ordered set of node adapters. First match wins per surface; `detailTabs` and\n * `copy` are the exceptions — they merge across every matching adapter so\n * independent adapters can each contribute a tab or a copy section.\n */\nexport class TestNodeAdapterRegistry {\n readonly adapters: TestNodeAdapter[];\n\n constructor(adapters: TestNodeAdapter[] = []) {\n this.adapters = adapters;\n }\n\n private firstWith(\n node: Test,\n runner: TestRunnerContext,\n has: (a: TestNodeAdapter) => boolean,\n ): TestNodeAdapter | null {\n for (const a of this.adapters) {\n if (has(a) && a.match(node, runner)) return a;\n }\n return null;\n }\n\n /** Adapter whose `renderDetail` should drive the body, or null for the default. */\n resolveDetail(node: Test, runner: TestRunnerContext): TestNodeAdapter | null {\n return this.firstWith(node, runner, (a) => !!a.renderDetail);\n }\n\n resolveRowLeading(node: Test, runner: TestRunnerContext): TestNodeAdapter | null {\n return this.firstWith(node, runner, (a) => !!a.renderRowLeading);\n }\n\n resolveFrameworkIcon(node: Test, runner: TestRunnerContext): TestNodeAdapter | null {\n return this.firstWith(node, runner, (a) => !!a.renderFrameworkIcon);\n }\n\n resolveActions(node: Test, runner: TestRunnerContext): TestNodeAdapter | null {\n return this.firstWith(node, runner, (a) => !!a.nodeActions);\n }\n\n /**\n * Attempts for the header chooser: the first matching adapter's\n * `detailAttempts`, else the node's own `attempts` (the built-in default,\n * which always sits behind the registered adapters).\n */\n resolveAttempts(node: Test, runner: TestRunnerContext): DetailAttempt[] {\n const adapted = this.firstWith(node, runner, (a) => !!a.detailAttempts)?.detailAttempts?.({ node, runner });\n if (adapted && adapted.length > 0) return adapted;\n return testAttemptViews(node);\n }\n\n /** Merge `detailTabs` from every matching adapter, de-duplicated by tab id. */\n resolveTabs(node: Test, runner: TestRunnerContext): DetailTab[] {\n const ctx: AdapterContext = { node, runner };\n const seen = new Set<string>();\n const tabs: DetailTab[] = [];\n for (const a of this.adapters) {\n if (!a.detailTabs || !a.match(node, runner)) continue;\n for (const tab of a.detailTabs(ctx)) {\n if (seen.has(tab.id)) continue;\n seen.add(tab.id);\n tabs.push(tab);\n }\n }\n return tabs;\n }\n\n /**\n * Merge `copy` sections from every matching adapter, de-duplicated by fact\n * label, section title and item label — the first contributor wins.\n */\n resolveCopy(node: Test, runner: TestRunnerContext): Required<CopySections> {\n const ctx: AdapterContext = { node, runner };\n return mergeCopySections(\n this.adapters.flatMap((a) => (a.copy && a.match(node, runner) ? [a.copy(ctx)] : [])),\n );\n }\n\n /** True when the resolved detail adapter owns its own scroll region. */\n ownsScroll(node: Test, runner: TestRunnerContext): boolean {\n const a = this.resolveDetail(node, runner);\n if (!a?.ownsScroll) return false;\n return a.ownsScroll({ node, runner });\n }\n}\n\nexport function createTestRunnerRegistry(\n adapters: TestNodeAdapter[] = [],\n): TestNodeAdapterRegistry {\n return new TestNodeAdapterRegistry(adapters);\n}\n"],"mappings":";;;;;;;;AAqEA,IAAa,0BAAb,MAAqC;CACnC;CAEA,YAAY,WAA8B,CAAC,GAAG;EAC5C,KAAK,WAAW;CAClB;CAEA,UACE,MACA,QACA,KACwB;EACxB,KAAK,MAAM,KAAK,KAAK,UACnB,IAAI,IAAI,CAAC,KAAK,EAAE,MAAM,MAAM,MAAM,GAAG,OAAO;EAE9C,OAAO;CACT;;CAGA,cAAc,MAAY,QAAmD;EAC3E,OAAO,KAAK,UAAU,MAAM,SAAS,MAAM,CAAC,CAAC,EAAE,YAAY;CAC7D;CAEA,kBAAkB,MAAY,QAAmD;EAC/E,OAAO,KAAK,UAAU,MAAM,SAAS,MAAM,CAAC,CAAC,EAAE,gBAAgB;CACjE;CAEA,qBAAqB,MAAY,QAAmD;EAClF,OAAO,KAAK,UAAU,MAAM,SAAS,MAAM,CAAC,CAAC,EAAE,mBAAmB;CACpE;CAEA,eAAe,MAAY,QAAmD;EAC5E,OAAO,KAAK,UAAU,MAAM,SAAS,MAAM,CAAC,CAAC,EAAE,WAAW;CAC5D;;;;;;CAOA,gBAAgB,MAAY,QAA4C;EACtE,MAAM,UAAU,KAAK,UAAU,MAAM,SAAS,MAAM,CAAC,CAAC,EAAE,cAAc,CAAC,EAAE,iBAAiB;GAAE;GAAM;EAAO,CAAC;EAC1G,IAAI,WAAW,QAAQ,SAAS,GAAG,OAAO;EAC1C,OAAO,iBAAiB,IAAI;CAC9B;;CAGA,YAAY,MAAY,QAAwC;EAC9D,MAAM,MAAsB;GAAE;GAAM;EAAO;EAC3C,MAAM,uBAAO,IAAI,IAAY;EAC7B,MAAM,OAAoB,CAAC;EAC3B,KAAK,MAAM,KAAK,KAAK,UAAU;GAC7B,IAAI,CAAC,EAAE,cAAc,CAAC,EAAE,MAAM,MAAM,MAAM,GAAG;GAC7C,KAAK,MAAM,OAAO,EAAE,WAAW,GAAG,GAAG;IACnC,IAAI,KAAK,IAAI,IAAI,EAAE,GAAG;IACtB,KAAK,IAAI,IAAI,EAAE;IACf,KAAK,KAAK,GAAG;GACf;EACF;EACA,OAAO;CACT;;;;;CAMA,YAAY,MAAY,QAAmD;EACzE,MAAM,MAAsB;GAAE;GAAM;EAAO;EAC3C,OAAO,kBACL,KAAK,SAAS,SAAS,MAAO,EAAE,QAAQ,EAAE,MAAM,MAAM,MAAM,IAAI,CAAC,EAAE,KAAK,GAAG,CAAC,IAAI,CAAC,CAAE,CACrF;CACF;;CAGA,WAAW,MAAY,QAAoC;EACzD,MAAM,IAAI,KAAK,cAAc,MAAM,MAAM;EACzC,IAAI,CAAC,GAAG,YAAY,OAAO;EAC3B,OAAO,EAAE,WAAW;GAAE;GAAM;EAAO,CAAC;CACtC;AACF;AAEA,SAAgB,yBACd,WAA8B,CAAC,GACN;CACzB,OAAO,IAAI,wBAAwB,QAAQ;AAC7C"}
1
+ {"version":3,"file":"adapter.js","names":[],"sources":["../../../src/data/test-runner/adapter.ts"],"sourcesContent":["// Node adapters let a host plug domain-specific rendering into the test runner\n// without forking it. An adapter claims nodes via `match` and contributes how\n// they render in each surface (tree row, detail body, detail tabs, header\n// actions). The registry resolves the first matching adapter per surface;\n// surfaces with no match fall back to the runner's built-in default rendering.\n//\n// This formalizes the wrapper-with-an-if-chain pattern hosts use today (e.g.\n// a ResultDetailPane fall-through over domain panels + tab providers + per-step\n// actions) into a registered, composable contract.\n\nimport type { ReactNode } from \"react\";\nimport type { Test } from \"./types\";\nimport type { TestRunnerContext } from \"./context\";\nimport { mergeCopySections, type CopySections } from \"./copy\";\nimport { testAttemptViews } from \"./attempts\";\n\nexport type AdapterContext = {\n node: Test;\n runner: TestRunnerContext;\n};\n\nexport type DetailTab = {\n id: string;\n label: string;\n render: () => ReactNode;\n};\n\nexport type DetailAttempt = { id: number; status: string; durationMs?: number; node: Test };\n\nexport type TestNodeAdapter = {\n /** Stable identifier, used as a React key and for debugging. */\n id: string;\n /** Claim the node. The first registered adapter to return true wins per surface. */\n match: (node: Test, runner: TestRunnerContext) => boolean;\n /**\n * Children shown in the navigation tree; results and status rollups stay intact.\n * Return [] to render a node as a leaf. Without a matching hook, uses node.children.\n * @example { id: \"setup-leaf\", match: node => node.name === \"setup\", treeChildren: () => [] }\n */\n treeChildren?: (c: AdapterContext) => Test[] | undefined;\n /**\n * Replace the framework icon for the node — return any node, or null to fall\n * back to the built-in tool mark (`TEST_TOOLS`). For a tool the catalog\n * lacks, prefer adding it to `TEST_TOOLS` so every surface shows it.\n */\n renderFrameworkIcon?: (c: AdapterContext) => ReactNode;\n /** Extra decoration rendered between the framework icon and the node name. */\n renderRowLeading?: (c: AdapterContext) => ReactNode;\n /** Primary detail body for the node, replacing the default panel body. */\n renderDetail?: (c: AdapterContext) => ReactNode;\n /** Extra detail tabs, merged (in registration order) across all matching adapters. */\n detailTabs?: (c: AdapterContext) => DetailTab[];\n /** Stored attempt views for the header chooser; tree and run totals remain step-level. */\n detailAttempts?: (c: AdapterContext) => DetailAttempt[];\n /** Node-scoped action buttons rendered in the detail header. */\n nodeActions?: (c: AdapterContext) => ReactNode;\n /**\n * Domain facts, brief sections and menu items for the header's \"Copy details\"\n * button, merged (in registration order) across all matching adapters on top\n * of the generic sections every node gets.\n */\n copy?: (c: AdapterContext) => CopySections;\n /**\n * Whether `renderDetail` owns its own full-height scroll container. When\n * false (the default for custom bodies), the panel wraps it in a scroll\n * region. The built-in default body owns its scroll.\n */\n ownsScroll?: (c: AdapterContext) => boolean;\n};\n\n/**\n * Ordered set of node adapters. First match wins per surface; `detailTabs` and\n * `copy` are the exceptions — they merge across every matching adapter so\n * independent adapters can each contribute a tab or a copy section.\n */\nexport class TestNodeAdapterRegistry {\n readonly adapters: TestNodeAdapter[];\n\n constructor(adapters: TestNodeAdapter[] = []) {\n this.adapters = adapters;\n }\n\n private firstWith(\n node: Test,\n runner: TestRunnerContext,\n has: (a: TestNodeAdapter) => boolean,\n ): TestNodeAdapter | null {\n for (const a of this.adapters) {\n if (has(a) && a.match(node, runner)) return a;\n }\n return null;\n }\n\n /** Adapter whose `renderDetail` should drive the body, or null for the default. */\n resolveDetail(node: Test, runner: TestRunnerContext): TestNodeAdapter | null {\n return this.firstWith(node, runner, (a) => !!a.renderDetail);\n }\n\n resolveRowLeading(node: Test, runner: TestRunnerContext): TestNodeAdapter | null {\n return this.firstWith(node, runner, (a) => !!a.renderRowLeading);\n }\n\n resolveFrameworkIcon(node: Test, runner: TestRunnerContext): TestNodeAdapter | null {\n return this.firstWith(node, runner, (a) => !!a.renderFrameworkIcon);\n }\n\n resolveActions(node: Test, runner: TestRunnerContext): TestNodeAdapter | null {\n return this.firstWith(node, runner, (a) => !!a.nodeActions);\n }\n\n resolveTreeChildren(node: Test, runner: TestRunnerContext): Test[] | undefined {\n const adapter = this.firstWith(node, runner, (a) => !!a.treeChildren);\n return adapter?.treeChildren ? adapter.treeChildren({ node, runner }) : node.children;\n }\n\n /**\n * Attempts for the header chooser: the first matching adapter's\n * `detailAttempts`, else the node's own `attempts` (the built-in default,\n * which always sits behind the registered adapters).\n */\n resolveAttempts(node: Test, runner: TestRunnerContext): DetailAttempt[] {\n const adapted = this.firstWith(node, runner, (a) => !!a.detailAttempts)?.detailAttempts?.({ node, runner });\n if (adapted && adapted.length > 0) return adapted;\n return testAttemptViews(node);\n }\n\n /** Merge `detailTabs` from every matching adapter, de-duplicated by tab id. */\n resolveTabs(node: Test, runner: TestRunnerContext): DetailTab[] {\n const ctx: AdapterContext = { node, runner };\n const seen = new Set<string>();\n const tabs: DetailTab[] = [];\n for (const a of this.adapters) {\n if (!a.detailTabs || !a.match(node, runner)) continue;\n for (const tab of a.detailTabs(ctx)) {\n if (seen.has(tab.id)) continue;\n seen.add(tab.id);\n tabs.push(tab);\n }\n }\n return tabs;\n }\n\n /**\n * Merge `copy` sections from every matching adapter, de-duplicated by fact\n * label, section title and item label — the first contributor wins.\n */\n resolveCopy(node: Test, runner: TestRunnerContext): Required<CopySections> {\n const ctx: AdapterContext = { node, runner };\n return mergeCopySections(\n this.adapters.flatMap((a) => (a.copy && a.match(node, runner) ? [a.copy(ctx)] : [])),\n );\n }\n\n /** True when the resolved detail adapter owns its own scroll region. */\n ownsScroll(node: Test, runner: TestRunnerContext): boolean {\n const a = this.resolveDetail(node, runner);\n if (!a?.ownsScroll) return false;\n return a.ownsScroll({ node, runner });\n }\n}\n\nexport function createTestRunnerRegistry(\n adapters: TestNodeAdapter[] = [],\n): TestNodeAdapterRegistry {\n return new TestNodeAdapterRegistry(adapters);\n}\n"],"mappings":";;;;;;;;AA2EA,IAAa,0BAAb,MAAqC;CACnC;CAEA,YAAY,WAA8B,CAAC,GAAG;EAC5C,KAAK,WAAW;CAClB;CAEA,UACE,MACA,QACA,KACwB;EACxB,KAAK,MAAM,KAAK,KAAK,UACnB,IAAI,IAAI,CAAC,KAAK,EAAE,MAAM,MAAM,MAAM,GAAG,OAAO;EAE9C,OAAO;CACT;;CAGA,cAAc,MAAY,QAAmD;EAC3E,OAAO,KAAK,UAAU,MAAM,SAAS,MAAM,CAAC,CAAC,EAAE,YAAY;CAC7D;CAEA,kBAAkB,MAAY,QAAmD;EAC/E,OAAO,KAAK,UAAU,MAAM,SAAS,MAAM,CAAC,CAAC,EAAE,gBAAgB;CACjE;CAEA,qBAAqB,MAAY,QAAmD;EAClF,OAAO,KAAK,UAAU,MAAM,SAAS,MAAM,CAAC,CAAC,EAAE,mBAAmB;CACpE;CAEA,eAAe,MAAY,QAAmD;EAC5E,OAAO,KAAK,UAAU,MAAM,SAAS,MAAM,CAAC,CAAC,EAAE,WAAW;CAC5D;CAEA,oBAAoB,MAAY,QAA+C;EAC7E,MAAM,UAAU,KAAK,UAAU,MAAM,SAAS,MAAM,CAAC,CAAC,EAAE,YAAY;EACpE,OAAO,SAAS,eAAe,QAAQ,aAAa;GAAE;GAAM;EAAO,CAAC,IAAI,KAAK;CAC/E;;;;;;CAOA,gBAAgB,MAAY,QAA4C;EACtE,MAAM,UAAU,KAAK,UAAU,MAAM,SAAS,MAAM,CAAC,CAAC,EAAE,cAAc,CAAC,EAAE,iBAAiB;GAAE;GAAM;EAAO,CAAC;EAC1G,IAAI,WAAW,QAAQ,SAAS,GAAG,OAAO;EAC1C,OAAO,iBAAiB,IAAI;CAC9B;;CAGA,YAAY,MAAY,QAAwC;EAC9D,MAAM,MAAsB;GAAE;GAAM;EAAO;EAC3C,MAAM,uBAAO,IAAI,IAAY;EAC7B,MAAM,OAAoB,CAAC;EAC3B,KAAK,MAAM,KAAK,KAAK,UAAU;GAC7B,IAAI,CAAC,EAAE,cAAc,CAAC,EAAE,MAAM,MAAM,MAAM,GAAG;GAC7C,KAAK,MAAM,OAAO,EAAE,WAAW,GAAG,GAAG;IACnC,IAAI,KAAK,IAAI,IAAI,EAAE,GAAG;IACtB,KAAK,IAAI,IAAI,EAAE;IACf,KAAK,KAAK,GAAG;GACf;EACF;EACA,OAAO;CACT;;;;;CAMA,YAAY,MAAY,QAAmD;EACzE,MAAM,MAAsB;GAAE;GAAM;EAAO;EAC3C,OAAO,kBACL,KAAK,SAAS,SAAS,MAAO,EAAE,QAAQ,EAAE,MAAM,MAAM,MAAM,IAAI,CAAC,EAAE,KAAK,GAAG,CAAC,IAAI,CAAC,CAAE,CACrF;CACF;;CAGA,WAAW,MAAY,QAAoC;EACzD,MAAM,IAAI,KAAK,cAAc,MAAM,MAAM;EACzC,IAAI,CAAC,GAAG,YAAY,OAAO;EAC3B,OAAO,EAAE,WAAW;GAAE;GAAM;EAAO,CAAC;CACtC;AACF;AAEA,SAAgB,yBACd,WAA8B,CAAC,GACN;CACzB,OAAO,IAAI,wBAAwB,QAAQ;AAC7C"}
@@ -18,7 +18,7 @@ export { type StatusCounts, type TestStatus, sum, sumNonTaskTests, aggregateStat
18
18
  export { TEST_OUTCOMES, LINT_SEVERITIES, TEST_TOOLS, toolMark, toolKeyFor, type ResultMark, type LintSeverity, type ToolKind, type ToolMark, } from './marks.js';
19
19
  export { OutcomeIcon, LintSeverityIcon, ToolIcon } from './MarkIcons.js';
20
20
  export { MATRIX_MARKS, MATRIX_ORDER, matrixMarkKey, repeatsMark, matrixBarClass, formatMatrixDuration, type MatrixMarkToken, type MatrixMarkKey, type MatrixCounts, type MatrixEnvCounts, } from './matrix-marks.js';
21
- export { MatrixMark, MatrixMix, MatrixElapsed, MatrixHeatmap, EmptyMatrixCell, MatrixLegend, EnvChip, MatrixEnvHeader, MatrixUnavailableEnvHeader, type MatrixMarkProps, type MatrixMixProps, type MatrixElapsedProps, type MatrixHeatmapProps, type MatrixTick, type EmptyMatrixCellProps, type MatrixLegendProps, type EnvChipProps, type MatrixEnvHeaderProps, type MatrixUnavailableEnvHeaderProps, } from './MatrixMarks.js';
21
+ export { MatrixMark, MatrixMix, MatrixElapsed, MatrixHeatmap, EmptyMatrixCell, MatrixLegend, EnvChip, MatrixEnvHeader, MatrixUnavailableEnvHeader, type MatrixMarkProps, type MatrixMixProps, type MatrixUnit, type MatrixElapsedProps, type MatrixHeatmapProps, type MatrixTick, type EmptyMatrixCellProps, type MatrixLegendProps, type EnvChipProps, type MatrixEnvHeaderProps, type MatrixUnavailableEnvHeaderProps, } from './MatrixMarks.js';
22
22
  export { slugify, annotateRoutePaths, findNodeByRoutePath } from './routePath.js';
23
23
  export { type FilterMode, type FilterState, type TestFilters, emptyTestFilters, decodeFilterState, encodeFilterState, cycleFilterState, matchesFilterState, filterStateToRecord, recordToFilterState, } from './filterState.js';
24
24
  export type { Test, TestSummary, TestAttempt, FailureDetail, FailureKind, GoTestContext, GinkgoContext, FixtureContext, TaskContext, RunMeta, Snapshot, SnapshotGit, SnapshotStatus, } from './types.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/data/test-runner/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/data/test-runner/index.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,3 @@
1
- const require_UiDebugStop = require("../../icons/components/UiDebugStop.cjs");
2
1
  const require_UiTimer = require("../../icons/components/UiTimer.cjs");
3
2
  const require_UiGlobe = require("../../icons/components/UiGlobe.cjs");
4
3
  const require_UiWarningTriangle = require("../../icons/components/UiWarningTriangle.cjs");
@@ -10,6 +9,7 @@ const require_UiPass = require("../../icons/components/UiPass.cjs");
10
9
  const require_UiSealCheck = require("../../icons/components/UiSealCheck.cjs");
11
10
  const require_UiKey = require("../../icons/components/UiKey.cjs");
12
11
  const require_UiSkipForward = require("../../icons/components/UiSkipForward.cjs");
12
+ const require_UiSkipCircle = require("../../icons/components/UiSkipCircle.cjs");
13
13
  const require_UiCopy = require("../../icons/components/UiCopy.cjs");
14
14
  const require_UiTerminal = require("../../icons/components/UiTerminal.cjs");
15
15
  const require_UiSparkles = require("../../icons/components/UiSparkles.cjs");
@@ -60,9 +60,9 @@ var TEST_OUTCOMES = {
60
60
  className: AMBER
61
61
  },
62
62
  aborted: {
63
- icon: require_UiDebugStop.UiDebugStop,
63
+ icon: require_UiSkipCircle.UiSkipCircle,
64
64
  label: LABEL.aborted,
65
- className: "text-red-400 dark:text-red-300"
65
+ className: "text-muted-foreground"
66
66
  },
67
67
  passed: {
68
68
  icon: require_UiPass.UiPass,
@@ -1 +1 @@
1
- {"version":3,"file":"marks.cjs","names":["STATUS_LABELS","UiCircleX","UiProhibit","UiTimer","UiWarningTriangle","UiDebugStop","UiPass","UiSkipForward","UiCircleOutline","UiLoader","UiInfo","UiLogoGo","UiLogoVitest","UiLogoJest","UiLogoPlaywright","UiLogoMarkdown","UiTerminal","UiBeaker","UiListChecks","UiSparkles","UiDatabase","UiServer","UiClipboardText","UiChatDots","UiRobotAi","UiGlobe","UiCursorClick","UiSealCheck","UiLogoEslint","UiLogoOxc","UiLogoTypescript","UiLogoPython","UiLogoRuff","UiKey","UiCopy","UiLogoReact"],"sources":["../../../src/data/test-runner/marks.ts"],"sourcesContent":["// The shared iconography for test and lint results: what happened (outcome),\n// how bad a finding is (lint severity), and what produced it (tool).\n//\n// Every outcome has its own outline glyph, so a result never reads by colour\n// alone.\n// Tool marks are bundled Simple Icons brand glyphs (offline, no runtime icon\n// names), coloured per theme here because one brand hex can't hold up on both\n// light and dark surfaces.\n\nimport type { StaticIconComponent } from \"../Icon\";\nimport {\n UiCircleOutline,\n UiCircleX,\n UiBeaker,\n UiChatDots,\n UiClipboardText,\n UiCopy,\n UiCursorClick,\n UiDebugStop,\n UiDatabase,\n UiGlobe,\n UiInfo,\n UiKey,\n UiListChecks,\n UiLoader,\n UiLogoEslint,\n UiLogoGo,\n UiLogoJest,\n UiLogoMarkdown,\n UiLogoOxc,\n UiLogoPlaywright,\n UiLogoPython,\n UiLogoReact,\n UiLogoRuff,\n UiLogoTypescript,\n UiLogoVitest,\n UiPass,\n UiProhibit,\n UiRobotAi,\n UiSealCheck,\n UiServer,\n UiSkipForward,\n UiSparkles,\n UiTerminal,\n UiTimer,\n UiWarningTriangle,\n} from \"../../icons\";\nimport { STATUS_LABELS, type TestOutcome } from \"./status\";\n\nexport type { TestOutcome } from \"./status\";\n\nexport type ResultMark = {\n icon: StaticIconComponent;\n label: string;\n /** Text colour classes for light and dark themes. */\n className: string;\n spin?: boolean;\n};\n\nconst LABEL = Object.fromEntries(STATUS_LABELS.map((s) => [s.key, s.label]));\n\nconst RED = \"text-red-600 dark:text-red-400\";\nconst AMBER = \"text-amber-600 dark:text-amber-400\";\n\nexport const TEST_OUTCOMES: Record<TestOutcome, ResultMark> = {\n failed: { icon: UiCircleX, label: LABEL.failed!, className: RED },\n errored: { icon: UiProhibit, label: \"Could not run\", className: RED },\n timedout: { icon: UiTimer, label: LABEL.timedout!, className: AMBER },\n warned: { icon: UiWarningTriangle, label: LABEL.warned!, className: AMBER },\n aborted: { icon: UiDebugStop, label: LABEL.aborted!, className: \"text-red-400 dark:text-red-300\" },\n passed: {\n icon: UiPass,\n label: LABEL.passed!,\n className: \"text-emerald-600 dark:text-emerald-400\",\n },\n skipped: { icon: UiSkipForward, label: LABEL.skipped!, className: \"text-slate-500\" },\n pending: {\n icon: UiCircleOutline,\n label: LABEL.pending!,\n className: \"text-slate-400 dark:text-slate-500\",\n },\n running: {\n icon: UiLoader,\n label: LABEL.running!,\n className: \"text-blue-600 dark:text-blue-400\",\n spin: true,\n },\n};\n\nexport type LintSeverity = \"error\" | \"warning\" | \"info\";\n\n/** An error-severity finding fails the verdict and a warning warns it, so they share those outcomes' marks. */\nexport const LINT_SEVERITIES: Record<LintSeverity, ResultMark> = {\n error: { ...TEST_OUTCOMES.failed, label: \"Error\" },\n warning: { ...TEST_OUTCOMES.warned, label: \"Warning\" },\n info: { icon: UiInfo, label: \"Info\", className: \"text-sky-600 dark:text-sky-400\" },\n};\n\nexport type ToolKind = \"test\" | \"lint\" | \"fixture\" | \"runner\";\n\nexport type ToolMark = {\n icon: StaticIconComponent;\n label: string;\n kind: ToolKind;\n className: string;\n};\n\nconst GO = \"text-[#00add8]\";\nconst MARKDOWN = \"text-foreground\";\nconst MUTED = \"text-muted-foreground\";\n\n/**\n * Keyed by the identifiers gavel reports: testrunner/parsers Framework values\n * and each linter's Name(). A tool without a mark of its own takes its\n * language's (golangci-lint → Go, pyright → Python).\n */\nexport const TEST_TOOLS: Record<string, ToolMark> = {\n \"go test\": { icon: UiLogoGo, label: \"go test\", kind: \"test\", className: GO },\n ginkgo: { icon: UiLogoGo, label: \"Ginkgo\", kind: \"test\", className: GO },\n vitest: { icon: UiLogoVitest, label: \"Vitest\", kind: \"test\", className: \"text-[#6e9f18]\" },\n jest: { icon: UiLogoJest, label: \"Jest\", kind: \"test\", className: \"text-[#c21325] dark:text-[#e5576a]\" },\n playwright: {\n icon: UiLogoPlaywright,\n label: \"Playwright\",\n kind: \"test\",\n className: \"text-[#2ead33]\",\n },\n fixture: { icon: UiLogoMarkdown, label: \"Markdown fixture\", kind: \"test\", className: MARKDOWN },\n task: { icon: UiTerminal, label: \"Task\", kind: \"runner\", className: MUTED },\n // Fixture step types (gavel fixtures FixtureResult.Type) and the\n // \"checklist\" node verifyReportTests synthesizes for acceptance criteria.\n exec: { icon: UiTerminal, label: \"Command\", kind: \"fixture\", className: MUTED },\n test: { icon: UiBeaker, label: \"Test step\", kind: \"fixture\", className: MUTED },\n lint: { icon: UiListChecks, label: \"Lint step\", kind: \"fixture\", className: MUTED },\n verify: {\n icon: UiSparkles,\n label: \"AI review\",\n kind: \"fixture\",\n className: \"text-violet-600 dark:text-violet-400\",\n },\n query: { icon: UiDatabase, label: \"Query\", kind: \"fixture\", className: MUTED },\n // Typed step kinds (gavel fixtures/kind registry): the node's `framework`\n // is the kind name. `ai` is the runner behind `verify` but is a prompt/CEL\n // round-trip rather than an acceptance-criteria review, so it takes the\n // same violet family with its own glyph and label.\n services: { icon: UiServer, label: \"Services\", kind: \"fixture\", className: MUTED },\n todo: { icon: UiClipboardText, label: \"TODO step\", kind: \"fixture\", className: MUTED },\n todo_prompt: { icon: UiChatDots, label: \"TODO prompt run\", kind: \"fixture\", className: MUTED },\n ai: {\n icon: UiRobotAi,\n label: \"AI step\",\n kind: \"fixture\",\n className: \"text-violet-600 dark:text-violet-400\",\n },\n browser: { icon: UiGlobe, label: \"Browser\", kind: \"fixture\", className: MUTED },\n // The fixture-step twin of the `playwright` test framework above; both\n // arrive as framework \"playwright\", so toolKeyFor() picks this key when the\n // node carries `detail.step`. Muted like every other fixture step, so the\n // brand green stays on the spec results the framework reports.\n \"playwright-step\": {\n icon: UiLogoPlaywright,\n label: \"Playwright step\",\n kind: \"fixture\",\n className: MUTED,\n },\n \"agent-browser\": { icon: UiCursorClick, label: \"Agent browser\", kind: \"fixture\", className: MUTED },\n criterion: { icon: UiSealCheck, label: \"Acceptance criterion\", kind: \"fixture\", className: MUTED },\n checklist: { icon: UiSealCheck, label: \"Acceptance criteria\", kind: \"fixture\", className: MUTED },\n \"golangci-lint\": { icon: UiLogoGo, label: \"golangci-lint\", kind: \"lint\", className: GO },\n eslint: {\n icon: UiLogoEslint,\n label: \"ESLint\",\n kind: \"lint\",\n className: \"text-[#4b32c3] dark:text-[#8080f2]\",\n },\n oxlint: {\n icon: UiLogoOxc,\n label: \"oxlint\",\n kind: \"lint\",\n className: \"text-[#0891b2] dark:text-[#00f7f1]\",\n },\n tsc: {\n icon: UiLogoTypescript,\n label: \"TypeScript compiler\",\n kind: \"lint\",\n className: \"text-[#3178c6]\",\n },\n markdownlint: { icon: UiLogoMarkdown, label: \"markdownlint\", kind: \"lint\", className: MARKDOWN },\n vale: { icon: UiLogoMarkdown, label: \"Vale (prose)\", kind: \"lint\", className: MARKDOWN },\n pyright: {\n icon: UiLogoPython,\n label: \"Pyright\",\n kind: \"lint\",\n className: \"text-[#3776ab] dark:text-[#ffd43b]\",\n },\n ruff: {\n icon: UiLogoRuff,\n label: \"Ruff\",\n kind: \"lint\",\n className: \"text-[#261230] dark:text-[#d7ff64]\",\n },\n // A secret scanner's finding is about a credential, not a language.\n betterleaks: { icon: UiKey, label: \"betterleaks (secrets)\", kind: \"lint\", className: MUTED },\n jscpd: { icon: UiCopy, label: \"jscpd (duplicate code)\", kind: \"lint\", className: MUTED },\n reactdoctor: {\n icon: UiLogoReact,\n label: \"React Doctor\",\n kind: \"lint\",\n className: \"text-[#0e7490] dark:text-[#61dafb]\",\n },\n};\n\n/** The tool's mark, or null for a tool the catalog doesn't know (render its name alone). */\nexport function toolMark(tool: string | undefined): ToolMark | null {\n return (tool && TEST_TOOLS[tool]) || null;\n}\n\nfunction hasStepInfo(detail: unknown): boolean {\n if (detail === null || typeof detail !== \"object\" || Array.isArray(detail)) return false;\n const step = (detail as Record<string, unknown>).step;\n return step !== null && typeof step === \"object\" && !Array.isArray(step);\n}\n\n/**\n * The TEST_TOOLS key for a node. A node's `framework` is the key, except that\n * \"playwright\" names both the test framework and the `playwright` fixture-step\n * kind: a node carrying `detail.step` (the fixture verifier's step id and\n * kind) is the step.\n */\nexport function toolKeyFor(node: { framework?: string | undefined; detail?: unknown }): string | undefined {\n if (node.framework === \"playwright\" && hasStepInfo(node.detail)) return \"playwright-step\";\n return node.framework;\n}\n\n"],"mappings":"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"}
1
+ {"version":3,"file":"marks.cjs","names":["STATUS_LABELS","UiCircleX","UiProhibit","UiTimer","UiWarningTriangle","UiSkipCircle","UiPass","UiSkipForward","UiCircleOutline","UiLoader","UiInfo","UiLogoGo","UiLogoVitest","UiLogoJest","UiLogoPlaywright","UiLogoMarkdown","UiTerminal","UiBeaker","UiListChecks","UiSparkles","UiDatabase","UiServer","UiClipboardText","UiChatDots","UiRobotAi","UiGlobe","UiCursorClick","UiSealCheck","UiLogoEslint","UiLogoOxc","UiLogoTypescript","UiLogoPython","UiLogoRuff","UiKey","UiCopy","UiLogoReact"],"sources":["../../../src/data/test-runner/marks.ts"],"sourcesContent":["// The shared iconography for test and lint results: what happened (outcome),\n// how bad a finding is (lint severity), and what produced it (tool).\n//\n// Every outcome has its own outline glyph, so a result never reads by colour\n// alone.\n// Tool marks are bundled Simple Icons brand glyphs (offline, no runtime icon\n// names), coloured per theme here because one brand hex can't hold up on both\n// light and dark surfaces.\n\nimport type { StaticIconComponent } from \"../Icon\";\nimport {\n UiCircleOutline,\n UiCircleX,\n UiBeaker,\n UiChatDots,\n UiClipboardText,\n UiCopy,\n UiCursorClick,\n UiDatabase,\n UiGlobe,\n UiInfo,\n UiKey,\n UiListChecks,\n UiLoader,\n UiLogoEslint,\n UiLogoGo,\n UiLogoJest,\n UiLogoMarkdown,\n UiLogoOxc,\n UiLogoPlaywright,\n UiLogoPython,\n UiLogoReact,\n UiLogoRuff,\n UiLogoTypescript,\n UiLogoVitest,\n UiPass,\n UiProhibit,\n UiRobotAi,\n UiSealCheck,\n UiServer,\n UiSkipForward,\n UiSkipCircle,\n UiSparkles,\n UiTerminal,\n UiTimer,\n UiWarningTriangle,\n} from \"../../icons\";\nimport { STATUS_LABELS, type TestOutcome } from \"./status\";\n\nexport type { TestOutcome } from \"./status\";\n\nexport type ResultMark = {\n icon: StaticIconComponent;\n label: string;\n /** Text colour classes for light and dark themes. */\n className: string;\n spin?: boolean;\n};\n\nconst LABEL = Object.fromEntries(STATUS_LABELS.map((s) => [s.key, s.label]));\n\nconst RED = \"text-red-600 dark:text-red-400\";\nconst AMBER = \"text-amber-600 dark:text-amber-400\";\n\nexport const TEST_OUTCOMES: Record<TestOutcome, ResultMark> = {\n failed: { icon: UiCircleX, label: LABEL.failed!, className: RED },\n errored: { icon: UiProhibit, label: \"Could not run\", className: RED },\n timedout: { icon: UiTimer, label: LABEL.timedout!, className: AMBER },\n warned: { icon: UiWarningTriangle, label: LABEL.warned!, className: AMBER },\n aborted: { icon: UiSkipCircle, label: LABEL.aborted!, className: \"text-muted-foreground\" },\n passed: {\n icon: UiPass,\n label: LABEL.passed!,\n className: \"text-emerald-600 dark:text-emerald-400\",\n },\n skipped: { icon: UiSkipForward, label: LABEL.skipped!, className: \"text-slate-500\" },\n pending: {\n icon: UiCircleOutline,\n label: LABEL.pending!,\n className: \"text-slate-400 dark:text-slate-500\",\n },\n running: {\n icon: UiLoader,\n label: LABEL.running!,\n className: \"text-blue-600 dark:text-blue-400\",\n spin: true,\n },\n};\n\nexport type LintSeverity = \"error\" | \"warning\" | \"info\";\n\n/** An error-severity finding fails the verdict and a warning warns it, so they share those outcomes' marks. */\nexport const LINT_SEVERITIES: Record<LintSeverity, ResultMark> = {\n error: { ...TEST_OUTCOMES.failed, label: \"Error\" },\n warning: { ...TEST_OUTCOMES.warned, label: \"Warning\" },\n info: { icon: UiInfo, label: \"Info\", className: \"text-sky-600 dark:text-sky-400\" },\n};\n\nexport type ToolKind = \"test\" | \"lint\" | \"fixture\" | \"runner\";\n\nexport type ToolMark = {\n icon: StaticIconComponent;\n label: string;\n kind: ToolKind;\n className: string;\n};\n\nconst GO = \"text-[#00add8]\";\nconst MARKDOWN = \"text-foreground\";\nconst MUTED = \"text-muted-foreground\";\n\n/**\n * Keyed by the identifiers gavel reports: testrunner/parsers Framework values\n * and each linter's Name(). A tool without a mark of its own takes its\n * language's (golangci-lint → Go, pyright → Python).\n */\nexport const TEST_TOOLS: Record<string, ToolMark> = {\n \"go test\": { icon: UiLogoGo, label: \"go test\", kind: \"test\", className: GO },\n ginkgo: { icon: UiLogoGo, label: \"Ginkgo\", kind: \"test\", className: GO },\n vitest: { icon: UiLogoVitest, label: \"Vitest\", kind: \"test\", className: \"text-[#6e9f18]\" },\n jest: { icon: UiLogoJest, label: \"Jest\", kind: \"test\", className: \"text-[#c21325] dark:text-[#e5576a]\" },\n playwright: {\n icon: UiLogoPlaywright,\n label: \"Playwright\",\n kind: \"test\",\n className: \"text-[#2ead33]\",\n },\n fixture: { icon: UiLogoMarkdown, label: \"Markdown fixture\", kind: \"test\", className: MARKDOWN },\n task: { icon: UiTerminal, label: \"Task\", kind: \"runner\", className: MUTED },\n // Fixture step types (gavel fixtures FixtureResult.Type) and the\n // \"checklist\" node verifyReportTests synthesizes for acceptance criteria.\n exec: { icon: UiTerminal, label: \"Command\", kind: \"fixture\", className: MUTED },\n test: { icon: UiBeaker, label: \"Test step\", kind: \"fixture\", className: MUTED },\n lint: { icon: UiListChecks, label: \"Lint step\", kind: \"fixture\", className: MUTED },\n verify: {\n icon: UiSparkles,\n label: \"AI review\",\n kind: \"fixture\",\n className: \"text-violet-600 dark:text-violet-400\",\n },\n query: { icon: UiDatabase, label: \"Query\", kind: \"fixture\", className: MUTED },\n // Typed step kinds (gavel fixtures/kind registry): the node's `framework`\n // is the kind name. `ai` is the runner behind `verify` but is a prompt/CEL\n // round-trip rather than an acceptance-criteria review, so it takes the\n // same violet family with its own glyph and label.\n services: { icon: UiServer, label: \"Services\", kind: \"fixture\", className: MUTED },\n todo: { icon: UiClipboardText, label: \"TODO step\", kind: \"fixture\", className: MUTED },\n todo_prompt: { icon: UiChatDots, label: \"TODO prompt run\", kind: \"fixture\", className: MUTED },\n ai: {\n icon: UiRobotAi,\n label: \"AI step\",\n kind: \"fixture\",\n className: \"text-violet-600 dark:text-violet-400\",\n },\n browser: { icon: UiGlobe, label: \"Browser\", kind: \"fixture\", className: MUTED },\n // The fixture-step twin of the `playwright` test framework above; both\n // arrive as framework \"playwright\", so toolKeyFor() picks this key when the\n // node carries `detail.step`. Muted like every other fixture step, so the\n // brand green stays on the spec results the framework reports.\n \"playwright-step\": {\n icon: UiLogoPlaywright,\n label: \"Playwright step\",\n kind: \"fixture\",\n className: MUTED,\n },\n \"agent-browser\": { icon: UiCursorClick, label: \"Agent browser\", kind: \"fixture\", className: MUTED },\n criterion: { icon: UiSealCheck, label: \"Acceptance criterion\", kind: \"fixture\", className: MUTED },\n checklist: { icon: UiSealCheck, label: \"Acceptance criteria\", kind: \"fixture\", className: MUTED },\n \"golangci-lint\": { icon: UiLogoGo, label: \"golangci-lint\", kind: \"lint\", className: GO },\n eslint: {\n icon: UiLogoEslint,\n label: \"ESLint\",\n kind: \"lint\",\n className: \"text-[#4b32c3] dark:text-[#8080f2]\",\n },\n oxlint: {\n icon: UiLogoOxc,\n label: \"oxlint\",\n kind: \"lint\",\n className: \"text-[#0891b2] dark:text-[#00f7f1]\",\n },\n tsc: {\n icon: UiLogoTypescript,\n label: \"TypeScript compiler\",\n kind: \"lint\",\n className: \"text-[#3178c6]\",\n },\n markdownlint: { icon: UiLogoMarkdown, label: \"markdownlint\", kind: \"lint\", className: MARKDOWN },\n vale: { icon: UiLogoMarkdown, label: \"Vale (prose)\", kind: \"lint\", className: MARKDOWN },\n pyright: {\n icon: UiLogoPython,\n label: \"Pyright\",\n kind: \"lint\",\n className: \"text-[#3776ab] dark:text-[#ffd43b]\",\n },\n ruff: {\n icon: UiLogoRuff,\n label: \"Ruff\",\n kind: \"lint\",\n className: \"text-[#261230] dark:text-[#d7ff64]\",\n },\n // A secret scanner's finding is about a credential, not a language.\n betterleaks: { icon: UiKey, label: \"betterleaks (secrets)\", kind: \"lint\", className: MUTED },\n jscpd: { icon: UiCopy, label: \"jscpd (duplicate code)\", kind: \"lint\", className: MUTED },\n reactdoctor: {\n icon: UiLogoReact,\n label: \"React Doctor\",\n kind: \"lint\",\n className: \"text-[#0e7490] dark:text-[#61dafb]\",\n },\n};\n\n/** The tool's mark, or null for a tool the catalog doesn't know (render its name alone). */\nexport function toolMark(tool: string | undefined): ToolMark | null {\n return (tool && TEST_TOOLS[tool]) || null;\n}\n\nfunction hasStepInfo(detail: unknown): boolean {\n if (detail === null || typeof detail !== \"object\" || Array.isArray(detail)) return false;\n const step = (detail as Record<string, unknown>).step;\n return step !== null && typeof step === \"object\" && !Array.isArray(step);\n}\n\n/**\n * The TEST_TOOLS key for a node. A node's `framework` is the key, except that\n * \"playwright\" names both the test framework and the `playwright` fixture-step\n * kind: a node carrying `detail.step` (the fixture verifier's step id and\n * kind) is the step.\n */\nexport function toolKeyFor(node: { framework?: string | undefined; detail?: unknown }): string | undefined {\n if (node.framework === \"playwright\" && hasStepInfo(node.detail)) return \"playwright-step\";\n return node.framework;\n}\n\n"],"mappings":"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"}
@@ -1,4 +1,3 @@
1
- import { UiDebugStop } from "../../icons/components/UiDebugStop.js";
2
1
  import { UiTimer } from "../../icons/components/UiTimer.js";
3
2
  import { UiGlobe } from "../../icons/components/UiGlobe.js";
4
3
  import { UiWarningTriangle } from "../../icons/components/UiWarningTriangle.js";
@@ -10,6 +9,7 @@ import { UiPass } from "../../icons/components/UiPass.js";
10
9
  import { UiSealCheck } from "../../icons/components/UiSealCheck.js";
11
10
  import { UiKey } from "../../icons/components/UiKey.js";
12
11
  import { UiSkipForward } from "../../icons/components/UiSkipForward.js";
12
+ import { UiSkipCircle } from "../../icons/components/UiSkipCircle.js";
13
13
  import { UiCopy } from "../../icons/components/UiCopy.js";
14
14
  import { UiTerminal } from "../../icons/components/UiTerminal.js";
15
15
  import { UiSparkles } from "../../icons/components/UiSparkles.js";
@@ -60,9 +60,9 @@ var TEST_OUTCOMES = {
60
60
  className: AMBER
61
61
  },
62
62
  aborted: {
63
- icon: UiDebugStop,
63
+ icon: UiSkipCircle,
64
64
  label: LABEL.aborted,
65
- className: "text-red-400 dark:text-red-300"
65
+ className: "text-muted-foreground"
66
66
  },
67
67
  passed: {
68
68
  icon: UiPass,
@@ -1 +1 @@
1
- {"version":3,"file":"marks.js","names":[],"sources":["../../../src/data/test-runner/marks.ts"],"sourcesContent":["// The shared iconography for test and lint results: what happened (outcome),\n// how bad a finding is (lint severity), and what produced it (tool).\n//\n// Every outcome has its own outline glyph, so a result never reads by colour\n// alone.\n// Tool marks are bundled Simple Icons brand glyphs (offline, no runtime icon\n// names), coloured per theme here because one brand hex can't hold up on both\n// light and dark surfaces.\n\nimport type { StaticIconComponent } from \"../Icon\";\nimport {\n UiCircleOutline,\n UiCircleX,\n UiBeaker,\n UiChatDots,\n UiClipboardText,\n UiCopy,\n UiCursorClick,\n UiDebugStop,\n UiDatabase,\n UiGlobe,\n UiInfo,\n UiKey,\n UiListChecks,\n UiLoader,\n UiLogoEslint,\n UiLogoGo,\n UiLogoJest,\n UiLogoMarkdown,\n UiLogoOxc,\n UiLogoPlaywright,\n UiLogoPython,\n UiLogoReact,\n UiLogoRuff,\n UiLogoTypescript,\n UiLogoVitest,\n UiPass,\n UiProhibit,\n UiRobotAi,\n UiSealCheck,\n UiServer,\n UiSkipForward,\n UiSparkles,\n UiTerminal,\n UiTimer,\n UiWarningTriangle,\n} from \"../../icons\";\nimport { STATUS_LABELS, type TestOutcome } from \"./status\";\n\nexport type { TestOutcome } from \"./status\";\n\nexport type ResultMark = {\n icon: StaticIconComponent;\n label: string;\n /** Text colour classes for light and dark themes. */\n className: string;\n spin?: boolean;\n};\n\nconst LABEL = Object.fromEntries(STATUS_LABELS.map((s) => [s.key, s.label]));\n\nconst RED = \"text-red-600 dark:text-red-400\";\nconst AMBER = \"text-amber-600 dark:text-amber-400\";\n\nexport const TEST_OUTCOMES: Record<TestOutcome, ResultMark> = {\n failed: { icon: UiCircleX, label: LABEL.failed!, className: RED },\n errored: { icon: UiProhibit, label: \"Could not run\", className: RED },\n timedout: { icon: UiTimer, label: LABEL.timedout!, className: AMBER },\n warned: { icon: UiWarningTriangle, label: LABEL.warned!, className: AMBER },\n aborted: { icon: UiDebugStop, label: LABEL.aborted!, className: \"text-red-400 dark:text-red-300\" },\n passed: {\n icon: UiPass,\n label: LABEL.passed!,\n className: \"text-emerald-600 dark:text-emerald-400\",\n },\n skipped: { icon: UiSkipForward, label: LABEL.skipped!, className: \"text-slate-500\" },\n pending: {\n icon: UiCircleOutline,\n label: LABEL.pending!,\n className: \"text-slate-400 dark:text-slate-500\",\n },\n running: {\n icon: UiLoader,\n label: LABEL.running!,\n className: \"text-blue-600 dark:text-blue-400\",\n spin: true,\n },\n};\n\nexport type LintSeverity = \"error\" | \"warning\" | \"info\";\n\n/** An error-severity finding fails the verdict and a warning warns it, so they share those outcomes' marks. */\nexport const LINT_SEVERITIES: Record<LintSeverity, ResultMark> = {\n error: { ...TEST_OUTCOMES.failed, label: \"Error\" },\n warning: { ...TEST_OUTCOMES.warned, label: \"Warning\" },\n info: { icon: UiInfo, label: \"Info\", className: \"text-sky-600 dark:text-sky-400\" },\n};\n\nexport type ToolKind = \"test\" | \"lint\" | \"fixture\" | \"runner\";\n\nexport type ToolMark = {\n icon: StaticIconComponent;\n label: string;\n kind: ToolKind;\n className: string;\n};\n\nconst GO = \"text-[#00add8]\";\nconst MARKDOWN = \"text-foreground\";\nconst MUTED = \"text-muted-foreground\";\n\n/**\n * Keyed by the identifiers gavel reports: testrunner/parsers Framework values\n * and each linter's Name(). A tool without a mark of its own takes its\n * language's (golangci-lint → Go, pyright → Python).\n */\nexport const TEST_TOOLS: Record<string, ToolMark> = {\n \"go test\": { icon: UiLogoGo, label: \"go test\", kind: \"test\", className: GO },\n ginkgo: { icon: UiLogoGo, label: \"Ginkgo\", kind: \"test\", className: GO },\n vitest: { icon: UiLogoVitest, label: \"Vitest\", kind: \"test\", className: \"text-[#6e9f18]\" },\n jest: { icon: UiLogoJest, label: \"Jest\", kind: \"test\", className: \"text-[#c21325] dark:text-[#e5576a]\" },\n playwright: {\n icon: UiLogoPlaywright,\n label: \"Playwright\",\n kind: \"test\",\n className: \"text-[#2ead33]\",\n },\n fixture: { icon: UiLogoMarkdown, label: \"Markdown fixture\", kind: \"test\", className: MARKDOWN },\n task: { icon: UiTerminal, label: \"Task\", kind: \"runner\", className: MUTED },\n // Fixture step types (gavel fixtures FixtureResult.Type) and the\n // \"checklist\" node verifyReportTests synthesizes for acceptance criteria.\n exec: { icon: UiTerminal, label: \"Command\", kind: \"fixture\", className: MUTED },\n test: { icon: UiBeaker, label: \"Test step\", kind: \"fixture\", className: MUTED },\n lint: { icon: UiListChecks, label: \"Lint step\", kind: \"fixture\", className: MUTED },\n verify: {\n icon: UiSparkles,\n label: \"AI review\",\n kind: \"fixture\",\n className: \"text-violet-600 dark:text-violet-400\",\n },\n query: { icon: UiDatabase, label: \"Query\", kind: \"fixture\", className: MUTED },\n // Typed step kinds (gavel fixtures/kind registry): the node's `framework`\n // is the kind name. `ai` is the runner behind `verify` but is a prompt/CEL\n // round-trip rather than an acceptance-criteria review, so it takes the\n // same violet family with its own glyph and label.\n services: { icon: UiServer, label: \"Services\", kind: \"fixture\", className: MUTED },\n todo: { icon: UiClipboardText, label: \"TODO step\", kind: \"fixture\", className: MUTED },\n todo_prompt: { icon: UiChatDots, label: \"TODO prompt run\", kind: \"fixture\", className: MUTED },\n ai: {\n icon: UiRobotAi,\n label: \"AI step\",\n kind: \"fixture\",\n className: \"text-violet-600 dark:text-violet-400\",\n },\n browser: { icon: UiGlobe, label: \"Browser\", kind: \"fixture\", className: MUTED },\n // The fixture-step twin of the `playwright` test framework above; both\n // arrive as framework \"playwright\", so toolKeyFor() picks this key when the\n // node carries `detail.step`. Muted like every other fixture step, so the\n // brand green stays on the spec results the framework reports.\n \"playwright-step\": {\n icon: UiLogoPlaywright,\n label: \"Playwright step\",\n kind: \"fixture\",\n className: MUTED,\n },\n \"agent-browser\": { icon: UiCursorClick, label: \"Agent browser\", kind: \"fixture\", className: MUTED },\n criterion: { icon: UiSealCheck, label: \"Acceptance criterion\", kind: \"fixture\", className: MUTED },\n checklist: { icon: UiSealCheck, label: \"Acceptance criteria\", kind: \"fixture\", className: MUTED },\n \"golangci-lint\": { icon: UiLogoGo, label: \"golangci-lint\", kind: \"lint\", className: GO },\n eslint: {\n icon: UiLogoEslint,\n label: \"ESLint\",\n kind: \"lint\",\n className: \"text-[#4b32c3] dark:text-[#8080f2]\",\n },\n oxlint: {\n icon: UiLogoOxc,\n label: \"oxlint\",\n kind: \"lint\",\n className: \"text-[#0891b2] dark:text-[#00f7f1]\",\n },\n tsc: {\n icon: UiLogoTypescript,\n label: \"TypeScript compiler\",\n kind: \"lint\",\n className: \"text-[#3178c6]\",\n },\n markdownlint: { icon: UiLogoMarkdown, label: \"markdownlint\", kind: \"lint\", className: MARKDOWN },\n vale: { icon: UiLogoMarkdown, label: \"Vale (prose)\", kind: \"lint\", className: MARKDOWN },\n pyright: {\n icon: UiLogoPython,\n label: \"Pyright\",\n kind: \"lint\",\n className: \"text-[#3776ab] dark:text-[#ffd43b]\",\n },\n ruff: {\n icon: UiLogoRuff,\n label: \"Ruff\",\n kind: \"lint\",\n className: \"text-[#261230] dark:text-[#d7ff64]\",\n },\n // A secret scanner's finding is about a credential, not a language.\n betterleaks: { icon: UiKey, label: \"betterleaks (secrets)\", kind: \"lint\", className: MUTED },\n jscpd: { icon: UiCopy, label: \"jscpd (duplicate code)\", kind: \"lint\", className: MUTED },\n reactdoctor: {\n icon: UiLogoReact,\n label: \"React Doctor\",\n kind: \"lint\",\n className: \"text-[#0e7490] dark:text-[#61dafb]\",\n },\n};\n\n/** The tool's mark, or null for a tool the catalog doesn't know (render its name alone). */\nexport function toolMark(tool: string | undefined): ToolMark | null {\n return (tool && TEST_TOOLS[tool]) || null;\n}\n\nfunction hasStepInfo(detail: unknown): boolean {\n if (detail === null || typeof detail !== \"object\" || Array.isArray(detail)) return false;\n const step = (detail as Record<string, unknown>).step;\n return step !== null && typeof step === \"object\" && !Array.isArray(step);\n}\n\n/**\n * The TEST_TOOLS key for a node. A node's `framework` is the key, except that\n * \"playwright\" names both the test framework and the `playwright` fixture-step\n * kind: a node carrying `detail.step` (the fixture verifier's step id and\n * kind) is the step.\n */\nexport function toolKeyFor(node: { framework?: string | undefined; detail?: unknown }): string | undefined {\n if (node.framework === \"playwright\" && hasStepInfo(node.detail)) return \"playwright-step\";\n return node.framework;\n}\n\n"],"mappings":"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"}
1
+ {"version":3,"file":"marks.js","names":[],"sources":["../../../src/data/test-runner/marks.ts"],"sourcesContent":["// The shared iconography for test and lint results: what happened (outcome),\n// how bad a finding is (lint severity), and what produced it (tool).\n//\n// Every outcome has its own outline glyph, so a result never reads by colour\n// alone.\n// Tool marks are bundled Simple Icons brand glyphs (offline, no runtime icon\n// names), coloured per theme here because one brand hex can't hold up on both\n// light and dark surfaces.\n\nimport type { StaticIconComponent } from \"../Icon\";\nimport {\n UiCircleOutline,\n UiCircleX,\n UiBeaker,\n UiChatDots,\n UiClipboardText,\n UiCopy,\n UiCursorClick,\n UiDatabase,\n UiGlobe,\n UiInfo,\n UiKey,\n UiListChecks,\n UiLoader,\n UiLogoEslint,\n UiLogoGo,\n UiLogoJest,\n UiLogoMarkdown,\n UiLogoOxc,\n UiLogoPlaywright,\n UiLogoPython,\n UiLogoReact,\n UiLogoRuff,\n UiLogoTypescript,\n UiLogoVitest,\n UiPass,\n UiProhibit,\n UiRobotAi,\n UiSealCheck,\n UiServer,\n UiSkipForward,\n UiSkipCircle,\n UiSparkles,\n UiTerminal,\n UiTimer,\n UiWarningTriangle,\n} from \"../../icons\";\nimport { STATUS_LABELS, type TestOutcome } from \"./status\";\n\nexport type { TestOutcome } from \"./status\";\n\nexport type ResultMark = {\n icon: StaticIconComponent;\n label: string;\n /** Text colour classes for light and dark themes. */\n className: string;\n spin?: boolean;\n};\n\nconst LABEL = Object.fromEntries(STATUS_LABELS.map((s) => [s.key, s.label]));\n\nconst RED = \"text-red-600 dark:text-red-400\";\nconst AMBER = \"text-amber-600 dark:text-amber-400\";\n\nexport const TEST_OUTCOMES: Record<TestOutcome, ResultMark> = {\n failed: { icon: UiCircleX, label: LABEL.failed!, className: RED },\n errored: { icon: UiProhibit, label: \"Could not run\", className: RED },\n timedout: { icon: UiTimer, label: LABEL.timedout!, className: AMBER },\n warned: { icon: UiWarningTriangle, label: LABEL.warned!, className: AMBER },\n aborted: { icon: UiSkipCircle, label: LABEL.aborted!, className: \"text-muted-foreground\" },\n passed: {\n icon: UiPass,\n label: LABEL.passed!,\n className: \"text-emerald-600 dark:text-emerald-400\",\n },\n skipped: { icon: UiSkipForward, label: LABEL.skipped!, className: \"text-slate-500\" },\n pending: {\n icon: UiCircleOutline,\n label: LABEL.pending!,\n className: \"text-slate-400 dark:text-slate-500\",\n },\n running: {\n icon: UiLoader,\n label: LABEL.running!,\n className: \"text-blue-600 dark:text-blue-400\",\n spin: true,\n },\n};\n\nexport type LintSeverity = \"error\" | \"warning\" | \"info\";\n\n/** An error-severity finding fails the verdict and a warning warns it, so they share those outcomes' marks. */\nexport const LINT_SEVERITIES: Record<LintSeverity, ResultMark> = {\n error: { ...TEST_OUTCOMES.failed, label: \"Error\" },\n warning: { ...TEST_OUTCOMES.warned, label: \"Warning\" },\n info: { icon: UiInfo, label: \"Info\", className: \"text-sky-600 dark:text-sky-400\" },\n};\n\nexport type ToolKind = \"test\" | \"lint\" | \"fixture\" | \"runner\";\n\nexport type ToolMark = {\n icon: StaticIconComponent;\n label: string;\n kind: ToolKind;\n className: string;\n};\n\nconst GO = \"text-[#00add8]\";\nconst MARKDOWN = \"text-foreground\";\nconst MUTED = \"text-muted-foreground\";\n\n/**\n * Keyed by the identifiers gavel reports: testrunner/parsers Framework values\n * and each linter's Name(). A tool without a mark of its own takes its\n * language's (golangci-lint → Go, pyright → Python).\n */\nexport const TEST_TOOLS: Record<string, ToolMark> = {\n \"go test\": { icon: UiLogoGo, label: \"go test\", kind: \"test\", className: GO },\n ginkgo: { icon: UiLogoGo, label: \"Ginkgo\", kind: \"test\", className: GO },\n vitest: { icon: UiLogoVitest, label: \"Vitest\", kind: \"test\", className: \"text-[#6e9f18]\" },\n jest: { icon: UiLogoJest, label: \"Jest\", kind: \"test\", className: \"text-[#c21325] dark:text-[#e5576a]\" },\n playwright: {\n icon: UiLogoPlaywright,\n label: \"Playwright\",\n kind: \"test\",\n className: \"text-[#2ead33]\",\n },\n fixture: { icon: UiLogoMarkdown, label: \"Markdown fixture\", kind: \"test\", className: MARKDOWN },\n task: { icon: UiTerminal, label: \"Task\", kind: \"runner\", className: MUTED },\n // Fixture step types (gavel fixtures FixtureResult.Type) and the\n // \"checklist\" node verifyReportTests synthesizes for acceptance criteria.\n exec: { icon: UiTerminal, label: \"Command\", kind: \"fixture\", className: MUTED },\n test: { icon: UiBeaker, label: \"Test step\", kind: \"fixture\", className: MUTED },\n lint: { icon: UiListChecks, label: \"Lint step\", kind: \"fixture\", className: MUTED },\n verify: {\n icon: UiSparkles,\n label: \"AI review\",\n kind: \"fixture\",\n className: \"text-violet-600 dark:text-violet-400\",\n },\n query: { icon: UiDatabase, label: \"Query\", kind: \"fixture\", className: MUTED },\n // Typed step kinds (gavel fixtures/kind registry): the node's `framework`\n // is the kind name. `ai` is the runner behind `verify` but is a prompt/CEL\n // round-trip rather than an acceptance-criteria review, so it takes the\n // same violet family with its own glyph and label.\n services: { icon: UiServer, label: \"Services\", kind: \"fixture\", className: MUTED },\n todo: { icon: UiClipboardText, label: \"TODO step\", kind: \"fixture\", className: MUTED },\n todo_prompt: { icon: UiChatDots, label: \"TODO prompt run\", kind: \"fixture\", className: MUTED },\n ai: {\n icon: UiRobotAi,\n label: \"AI step\",\n kind: \"fixture\",\n className: \"text-violet-600 dark:text-violet-400\",\n },\n browser: { icon: UiGlobe, label: \"Browser\", kind: \"fixture\", className: MUTED },\n // The fixture-step twin of the `playwright` test framework above; both\n // arrive as framework \"playwright\", so toolKeyFor() picks this key when the\n // node carries `detail.step`. Muted like every other fixture step, so the\n // brand green stays on the spec results the framework reports.\n \"playwright-step\": {\n icon: UiLogoPlaywright,\n label: \"Playwright step\",\n kind: \"fixture\",\n className: MUTED,\n },\n \"agent-browser\": { icon: UiCursorClick, label: \"Agent browser\", kind: \"fixture\", className: MUTED },\n criterion: { icon: UiSealCheck, label: \"Acceptance criterion\", kind: \"fixture\", className: MUTED },\n checklist: { icon: UiSealCheck, label: \"Acceptance criteria\", kind: \"fixture\", className: MUTED },\n \"golangci-lint\": { icon: UiLogoGo, label: \"golangci-lint\", kind: \"lint\", className: GO },\n eslint: {\n icon: UiLogoEslint,\n label: \"ESLint\",\n kind: \"lint\",\n className: \"text-[#4b32c3] dark:text-[#8080f2]\",\n },\n oxlint: {\n icon: UiLogoOxc,\n label: \"oxlint\",\n kind: \"lint\",\n className: \"text-[#0891b2] dark:text-[#00f7f1]\",\n },\n tsc: {\n icon: UiLogoTypescript,\n label: \"TypeScript compiler\",\n kind: \"lint\",\n className: \"text-[#3178c6]\",\n },\n markdownlint: { icon: UiLogoMarkdown, label: \"markdownlint\", kind: \"lint\", className: MARKDOWN },\n vale: { icon: UiLogoMarkdown, label: \"Vale (prose)\", kind: \"lint\", className: MARKDOWN },\n pyright: {\n icon: UiLogoPython,\n label: \"Pyright\",\n kind: \"lint\",\n className: \"text-[#3776ab] dark:text-[#ffd43b]\",\n },\n ruff: {\n icon: UiLogoRuff,\n label: \"Ruff\",\n kind: \"lint\",\n className: \"text-[#261230] dark:text-[#d7ff64]\",\n },\n // A secret scanner's finding is about a credential, not a language.\n betterleaks: { icon: UiKey, label: \"betterleaks (secrets)\", kind: \"lint\", className: MUTED },\n jscpd: { icon: UiCopy, label: \"jscpd (duplicate code)\", kind: \"lint\", className: MUTED },\n reactdoctor: {\n icon: UiLogoReact,\n label: \"React Doctor\",\n kind: \"lint\",\n className: \"text-[#0e7490] dark:text-[#61dafb]\",\n },\n};\n\n/** The tool's mark, or null for a tool the catalog doesn't know (render its name alone). */\nexport function toolMark(tool: string | undefined): ToolMark | null {\n return (tool && TEST_TOOLS[tool]) || null;\n}\n\nfunction hasStepInfo(detail: unknown): boolean {\n if (detail === null || typeof detail !== \"object\" || Array.isArray(detail)) return false;\n const step = (detail as Record<string, unknown>).step;\n return step !== null && typeof step === \"object\" && !Array.isArray(step);\n}\n\n/**\n * The TEST_TOOLS key for a node. A node's `framework` is the key, except that\n * \"playwright\" names both the test framework and the `playwright` fixture-step\n * kind: a node carrying `detail.step` (the fixture verifier's step id and\n * kind) is the step.\n */\nexport function toolKeyFor(node: { framework?: string | undefined; detail?: unknown }): string | undefined {\n if (node.framework === \"playwright\" && hasStepInfo(node.detail)) return \"playwright-step\";\n return node.framework;\n}\n\n"],"mappings":"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"}
@@ -5,6 +5,7 @@ const require_UiCircleOutline = require("../../icons/components/UiCircleOutline.
5
5
  const require_UiLoader = require("../../icons/components/UiLoader.cjs");
6
6
  const require_UiPass = require("../../icons/components/UiPass.cjs");
7
7
  const require_UiSkipForward = require("../../icons/components/UiSkipForward.cjs");
8
+ const require_UiSkipCircle = require("../../icons/components/UiSkipCircle.cjs");
8
9
  const require_UiHourglass = require("../../icons/components/UiHourglass.cjs");
9
10
  const require_UiProhibit = require("../../icons/components/UiProhibit.cjs");
10
11
  // src/data/test-runner/matrix-marks.ts
@@ -39,9 +40,9 @@ var MATRIX_MARKS = {
39
40
  spin: true
40
41
  },
41
42
  aborted: {
42
- icon: require_UiProhibit.UiProhibit,
43
- tone: "text-red-400 dark:text-red-300",
44
- bar: "bg-red-300 dark:bg-red-800",
43
+ icon: require_UiSkipCircle.UiSkipCircle,
44
+ tone: "text-muted-foreground",
45
+ bar: "bg-slate-300 dark:bg-slate-600",
45
46
  label: "aborted",
46
47
  attention: true
47
48
  },
@@ -72,6 +73,14 @@ var MATRIX_MARKS = {
72
73
  tone: "text-muted-foreground/60",
73
74
  label: "not in this run",
74
75
  attention: false
76
+ },
77
+ /** A plan or case its country does not apply to: not run here, by design. */
78
+ na: {
79
+ icon: require_UiProhibit.UiProhibit,
80
+ tone: "text-muted-foreground/60",
81
+ label: "N/A",
82
+ legend: "N/A · not for this country",
83
+ attention: false
75
84
  }
76
85
  };
77
86
  var MATRIX_ORDER = Object.keys(MATRIX_MARKS);
@@ -1 +1 @@
1
- {"version":3,"file":"matrix-marks.cjs","names":["UiPass","UiWarningCircle","UiSkipForward","UiLoader","UiProhibit","UiCircleX","UiWarningTriangleFilled","UiHourglass","UiCircleOutline"],"sources":["../../../src/data/test-runner/matrix-marks.ts"],"sourcesContent":["// The glyph vocabulary of a bulk test matrix (plans × environments): plan\n// cells, sub-steps, the environment header's verdict row and the legend all\n// read MATRIX_MARKS, in this order. The live web matrix and its printed report\n// draw from this one table. MatrixMarks.tsx renders it; this file holds only\n// the tokens and pure helpers (react/only-export-components).\n\nimport {\n UiCircleOutline,\n UiCircleX,\n UiHourglass,\n UiLoader,\n UiPass,\n UiProhibit,\n UiSkipForward,\n UiWarningCircle,\n UiWarningTriangleFilled,\n type IconComponent,\n} from \"../../icons\";\n\nexport type MatrixMarkToken = {\n icon: IconComponent;\n tone: string;\n /** Progress-bar fill; absent for states a bar leaves as its track. */\n bar?: string;\n label: string;\n legend?: string;\n /** Whether a sub-step spells the outcome out beside its glyph. */\n attention: boolean;\n spin?: boolean;\n};\n\nexport const MATRIX_MARKS = {\n passed: { icon: UiPass, tone: \"text-emerald-600 dark:text-emerald-400\", bar: \"bg-emerald-500\", label: \"passed\", attention: false },\n warned: { icon: UiWarningCircle, tone: \"text-amber-600 dark:text-amber-400\", bar: \"bg-amber-400\", label: \"warned\", attention: true },\n skipped: { icon: UiSkipForward, tone: \"text-slate-400 dark:text-slate-500\", bar: \"bg-slate-300 dark:bg-slate-600\", label: \"skipped\", attention: false },\n running: { icon: UiLoader, tone: \"text-blue-600 dark:text-blue-400\", bar: \"bg-blue-500 animate-pulse\", label: \"running\", attention: true, spin: true },\n aborted: { icon: UiProhibit, tone: \"text-red-400 dark:text-red-300\", bar: \"bg-red-300 dark:bg-red-800\", label: \"aborted\", attention: true },\n failed: { icon: UiCircleX, tone: \"text-red-600 dark:text-red-400\", bar: \"bg-red-600\", label: \"failed\", attention: true },\n error: { icon: UiWarningTriangleFilled, tone: \"text-red-600 dark:text-red-400\", bar: \"bg-red-800\", label: \"error\", legend: \"error · never started\", attention: true },\n pending: { icon: UiHourglass, tone: \"text-muted-foreground\", label: \"pending\", legend: \"pending · queued\", attention: false },\n absent: { icon: UiCircleOutline, tone: \"text-muted-foreground/60\", label: \"not in this run\", attention: false },\n} satisfies Record<string, MatrixMarkToken>;\n\nexport type MatrixMarkKey = keyof typeof MATRIX_MARKS;\nexport type MatrixCounts = Partial<Record<MatrixMarkKey, number>>;\n\nexport const MATRIX_ORDER = Object.keys(MATRIX_MARKS) as readonly MatrixMarkKey[];\n\n/** One environment's plan totals, as its matrix column header reads them. */\nexport type MatrixEnvCounts = {\n passed: number;\n warned: number;\n failed: number;\n error: number;\n running: number;\n queued: number;\n total: number;\n};\n\nexport function matrixMarkKey(outcome: string): MatrixMarkKey {\n if (!Object.hasOwn(MATRIX_MARKS, outcome)) throw new Error(`matrix has no mark for outcome \"${outcome}\"`);\n return outcome as MatrixMarkKey;\n}\n\n/**\n * Whether a mix holds only the outcome a mark beside it already shows, so\n * drawing both would repeat the glyph.\n */\nexport function repeatsMark(counts: MatrixCounts, mark: MatrixMarkKey): boolean {\n const nonZero = MATRIX_ORDER.filter((key) => (counts[key] ?? 0) > 0);\n return nonZero.length === 1 && nonZero[0] === mark;\n}\n\n/** A mark's progress-bar fill, the muted track for one with none; static (print) drops its animate-* classes. */\nexport function matrixBarClass(mark: MatrixMarkKey, isStatic: boolean): string {\n const bar: string = (MATRIX_MARKS[mark] as MatrixMarkToken).bar ?? \"bg-muted\";\n return isStatic ? bar.split(\" \").filter((c) => !c.startsWith(\"animate-\")).join(\" \") : bar;\n}\n\n/** The matrix's one duration format: 42s, 4m 12s, 1h 03m. */\nexport function formatMatrixDuration(ms: number): string {\n const s = Math.round(ms / 1000);\n if (s < 60) return `${s}s`;\n const m = Math.floor(s / 60);\n if (m < 60) return `${m}m ${String(s % 60).padStart(2, \"0\")}s`;\n return `${Math.floor(m / 60)}h ${String(m % 60).padStart(2, \"0\")}m`;\n}\n"],"mappings":";;;;;;;;;;AA+BA,IAAa,eAAe;CAC1B,QAAQ;EAAE,MAAMA,eAAAA;EAAQ,MAAM;EAA0C,KAAK;EAAkB,OAAO;EAAU,WAAW;CAAM;CACjI,QAAQ;EAAE,MAAMC,wBAAAA;EAAiB,MAAM;EAAsC,KAAK;EAAgB,OAAO;EAAU,WAAW;CAAK;CACnI,SAAS;EAAE,MAAMC,sBAAAA;EAAe,MAAM;EAAsC,KAAK;EAAkC,OAAO;EAAW,WAAW;CAAM;CACtJ,SAAS;EAAE,MAAMC,iBAAAA;EAAU,MAAM;EAAoC,KAAK;EAA6B,OAAO;EAAW,WAAW;EAAM,MAAM;CAAK;CACrJ,SAAS;EAAE,MAAMC,mBAAAA;EAAY,MAAM;EAAkC,KAAK;EAA8B,OAAO;EAAW,WAAW;CAAK;CAC1I,QAAQ;EAAE,MAAMC,kBAAAA;EAAW,MAAM;EAAkC,KAAK;EAAc,OAAO;EAAU,WAAW;CAAK;CACvH,OAAO;EAAE,MAAMC,0BAAAA;EAAyB,MAAM;EAAkC,KAAK;EAAc,OAAO;EAAS,QAAQ;EAAyB,WAAW;CAAK;CACpK,SAAS;EAAE,MAAMC,oBAAAA;EAAa,MAAM;EAAyB,OAAO;EAAW,QAAQ;EAAoB,WAAW;CAAM;CAC5H,QAAQ;EAAE,MAAMC,wBAAAA;EAAiB,MAAM;EAA4B,OAAO;EAAmB,WAAW;CAAM;AAChH;AAKA,IAAa,eAAe,OAAO,KAAK,YAAY;AAapD,SAAgB,cAAc,SAAgC;CAC5D,IAAI,CAAC,OAAO,OAAO,cAAc,OAAO,GAAG,MAAM,IAAI,MAAM,mCAAmC,QAAQ,EAAE;CACxG,OAAO;AACT;;;;;AAMA,SAAgB,YAAY,QAAsB,MAA8B;CAC9E,MAAM,UAAU,aAAa,QAAQ,SAAS,OAAO,QAAQ,KAAK,CAAC;CACnE,OAAO,QAAQ,WAAW,KAAK,QAAQ,OAAO;AAChD;;AAGA,SAAgB,eAAe,MAAqB,UAA2B;CAC7E,MAAM,MAAe,aAAa,KAAK,CAAqB,OAAO;CACnE,OAAO,WAAW,IAAI,MAAM,GAAG,CAAC,CAAC,QAAQ,MAAM,CAAC,EAAE,WAAW,UAAU,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI;AACxF;;AAGA,SAAgB,qBAAqB,IAAoB;CACvD,MAAM,IAAI,KAAK,MAAM,KAAK,GAAI;CAC9B,IAAI,IAAI,IAAI,OAAO,GAAG,EAAE;CACxB,MAAM,IAAI,KAAK,MAAM,IAAI,EAAE;CAC3B,IAAI,IAAI,IAAI,OAAO,GAAG,EAAE,IAAI,OAAO,IAAI,EAAE,CAAC,CAAC,SAAS,GAAG,GAAG,EAAE;CAC5D,OAAO,GAAG,KAAK,MAAM,IAAI,EAAE,EAAE,IAAI,OAAO,IAAI,EAAE,CAAC,CAAC,SAAS,GAAG,GAAG,EAAE;AACnE"}
1
+ {"version":3,"file":"matrix-marks.cjs","names":["UiPass","UiWarningCircle","UiSkipForward","UiLoader","UiSkipCircle","UiCircleX","UiWarningTriangleFilled","UiHourglass","UiCircleOutline","UiProhibit"],"sources":["../../../src/data/test-runner/matrix-marks.ts"],"sourcesContent":["// The glyph vocabulary of a bulk test matrix (plans × environments): plan\n// cells, sub-steps, the environment header's verdict row and the legend all\n// read MATRIX_MARKS, in this order. The live web matrix and its printed report\n// draw from this one table. MatrixMarks.tsx renders it; this file holds only\n// the tokens and pure helpers (react/only-export-components).\n\nimport {\n UiCircleOutline,\n UiCircleX,\n UiHourglass,\n UiLoader,\n UiPass,\n UiProhibit,\n UiSkipCircle,\n UiSkipForward,\n UiWarningCircle,\n UiWarningTriangleFilled,\n type IconComponent,\n} from \"../../icons\";\n\nexport type MatrixMarkToken = {\n icon: IconComponent;\n tone: string;\n /** Progress-bar fill; absent for states a bar leaves as its track. */\n bar?: string;\n label: string;\n legend?: string;\n /** Whether a sub-step spells the outcome out beside its glyph. */\n attention: boolean;\n spin?: boolean;\n};\n\nexport const MATRIX_MARKS = {\n passed: { icon: UiPass, tone: \"text-emerald-600 dark:text-emerald-400\", bar: \"bg-emerald-500\", label: \"passed\", attention: false },\n warned: { icon: UiWarningCircle, tone: \"text-amber-600 dark:text-amber-400\", bar: \"bg-amber-400\", label: \"warned\", attention: true },\n skipped: { icon: UiSkipForward, tone: \"text-slate-400 dark:text-slate-500\", bar: \"bg-slate-300 dark:bg-slate-600\", label: \"skipped\", attention: false },\n running: { icon: UiLoader, tone: \"text-blue-600 dark:text-blue-400\", bar: \"bg-blue-500 animate-pulse\", label: \"running\", attention: true, spin: true },\n aborted: { icon: UiSkipCircle, tone: \"text-muted-foreground\", bar: \"bg-slate-300 dark:bg-slate-600\", label: \"aborted\", attention: true },\n failed: { icon: UiCircleX, tone: \"text-red-600 dark:text-red-400\", bar: \"bg-red-600\", label: \"failed\", attention: true },\n error: { icon: UiWarningTriangleFilled, tone: \"text-red-600 dark:text-red-400\", bar: \"bg-red-800\", label: \"error\", legend: \"error · never started\", attention: true },\n pending: { icon: UiHourglass, tone: \"text-muted-foreground\", label: \"pending\", legend: \"pending · queued\", attention: false },\n absent: { icon: UiCircleOutline, tone: \"text-muted-foreground/60\", label: \"not in this run\", attention: false },\n /** A plan or case its country does not apply to: not run here, by design. */\n na: { icon: UiProhibit, tone: \"text-muted-foreground/60\", label: \"N/A\", legend: \"N/A · not for this country\", attention: false },\n} satisfies Record<string, MatrixMarkToken>;\n\nexport type MatrixMarkKey = keyof typeof MATRIX_MARKS;\nexport type MatrixCounts = Partial<Record<MatrixMarkKey, number>>;\n\nexport const MATRIX_ORDER = Object.keys(MATRIX_MARKS) as readonly MatrixMarkKey[];\n\n/** One environment's plan totals, as its matrix column header reads them. */\nexport type MatrixEnvCounts = {\n passed: number;\n warned: number;\n failed: number;\n error: number;\n running: number;\n queued: number;\n total: number;\n};\n\nexport function matrixMarkKey(outcome: string): MatrixMarkKey {\n if (!Object.hasOwn(MATRIX_MARKS, outcome)) throw new Error(`matrix has no mark for outcome \"${outcome}\"`);\n return outcome as MatrixMarkKey;\n}\n\n/**\n * Whether a mix holds only the outcome a mark beside it already shows, so\n * drawing both would repeat the glyph.\n */\nexport function repeatsMark(counts: MatrixCounts, mark: MatrixMarkKey): boolean {\n const nonZero = MATRIX_ORDER.filter((key) => (counts[key] ?? 0) > 0);\n return nonZero.length === 1 && nonZero[0] === mark;\n}\n\n/** A mark's progress-bar fill, the muted track for one with none; static (print) drops its animate-* classes. */\nexport function matrixBarClass(mark: MatrixMarkKey, isStatic: boolean): string {\n const bar: string = (MATRIX_MARKS[mark] as MatrixMarkToken).bar ?? \"bg-muted\";\n return isStatic ? bar.split(\" \").filter((c) => !c.startsWith(\"animate-\")).join(\" \") : bar;\n}\n\n/** The matrix's one duration format: 42s, 4m 12s, 1h 03m. */\nexport function formatMatrixDuration(ms: number): string {\n const s = Math.round(ms / 1000);\n if (s < 60) return `${s}s`;\n const m = Math.floor(s / 60);\n if (m < 60) return `${m}m ${String(s % 60).padStart(2, \"0\")}s`;\n return `${Math.floor(m / 60)}h ${String(m % 60).padStart(2, \"0\")}m`;\n}\n"],"mappings":";;;;;;;;;;;AAgCA,IAAa,eAAe;CAC1B,QAAQ;EAAE,MAAMA,eAAAA;EAAQ,MAAM;EAA0C,KAAK;EAAkB,OAAO;EAAU,WAAW;CAAM;CACjI,QAAQ;EAAE,MAAMC,wBAAAA;EAAiB,MAAM;EAAsC,KAAK;EAAgB,OAAO;EAAU,WAAW;CAAK;CACnI,SAAS;EAAE,MAAMC,sBAAAA;EAAe,MAAM;EAAsC,KAAK;EAAkC,OAAO;EAAW,WAAW;CAAM;CACtJ,SAAS;EAAE,MAAMC,iBAAAA;EAAU,MAAM;EAAoC,KAAK;EAA6B,OAAO;EAAW,WAAW;EAAM,MAAM;CAAK;CACrJ,SAAS;EAAE,MAAMC,qBAAAA;EAAc,MAAM;EAAyB,KAAK;EAAkC,OAAO;EAAW,WAAW;CAAK;CACvI,QAAQ;EAAE,MAAMC,kBAAAA;EAAW,MAAM;EAAkC,KAAK;EAAc,OAAO;EAAU,WAAW;CAAK;CACvH,OAAO;EAAE,MAAMC,0BAAAA;EAAyB,MAAM;EAAkC,KAAK;EAAc,OAAO;EAAS,QAAQ;EAAyB,WAAW;CAAK;CACpK,SAAS;EAAE,MAAMC,oBAAAA;EAAa,MAAM;EAAyB,OAAO;EAAW,QAAQ;EAAoB,WAAW;CAAM;CAC5H,QAAQ;EAAE,MAAMC,wBAAAA;EAAiB,MAAM;EAA4B,OAAO;EAAmB,WAAW;CAAM;;CAE9G,IAAI;EAAE,MAAMC,mBAAAA;EAAY,MAAM;EAA4B,OAAO;EAAO,QAAQ;EAA8B,WAAW;CAAM;AACjI;AAKA,IAAa,eAAe,OAAO,KAAK,YAAY;AAapD,SAAgB,cAAc,SAAgC;CAC5D,IAAI,CAAC,OAAO,OAAO,cAAc,OAAO,GAAG,MAAM,IAAI,MAAM,mCAAmC,QAAQ,EAAE;CACxG,OAAO;AACT;;;;;AAMA,SAAgB,YAAY,QAAsB,MAA8B;CAC9E,MAAM,UAAU,aAAa,QAAQ,SAAS,OAAO,QAAQ,KAAK,CAAC;CACnE,OAAO,QAAQ,WAAW,KAAK,QAAQ,OAAO;AAChD;;AAGA,SAAgB,eAAe,MAAqB,UAA2B;CAC7E,MAAM,MAAe,aAAa,KAAK,CAAqB,OAAO;CACnE,OAAO,WAAW,IAAI,MAAM,GAAG,CAAC,CAAC,QAAQ,MAAM,CAAC,EAAE,WAAW,UAAU,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI;AACxF;;AAGA,SAAgB,qBAAqB,IAAoB;CACvD,MAAM,IAAI,KAAK,MAAM,KAAK,GAAI;CAC9B,IAAI,IAAI,IAAI,OAAO,GAAG,EAAE;CACxB,MAAM,IAAI,KAAK,MAAM,IAAI,EAAE;CAC3B,IAAI,IAAI,IAAI,OAAO,GAAG,EAAE,IAAI,OAAO,IAAI,EAAE,CAAC,CAAC,SAAS,GAAG,GAAG,EAAE;CAC5D,OAAO,GAAG,KAAK,MAAM,IAAI,EAAE,EAAE,IAAI,OAAO,IAAI,EAAE,CAAC,CAAC,SAAS,GAAG,GAAG,EAAE;AACnE"}
@@ -125,6 +125,19 @@ export declare const MATRIX_MARKS: {
125
125
  label: string;
126
126
  attention: false;
127
127
  };
128
+ /** A plan or case its country does not apply to: not run here, by design. */
129
+ na: {
130
+ icon: import('react').FC<import('../../icons.js').IconProps> & {
131
+ __source: string;
132
+ __viewBox: string;
133
+ __group: string;
134
+ __consumerName: string;
135
+ };
136
+ tone: string;
137
+ label: string;
138
+ legend: string;
139
+ attention: false;
140
+ };
128
141
  };
129
142
  export type MatrixMarkKey = keyof typeof MATRIX_MARKS;
130
143
  export type MatrixCounts = Partial<Record<MatrixMarkKey, number>>;
@@ -1 +1 @@
1
- {"version":3,"file":"matrix-marks.d.ts","sourceRoot":"","sources":["../../../src/data/test-runner/matrix-marks.ts"],"names":[],"mappings":"AAMA,OAAO,EAUL,KAAK,aAAa,EACnB,MAAM,aAAa,CAAC;AAErB,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,aAAa,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,sEAAsE;IACtE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kEAAkE;IAClE,SAAS,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAUkB,CAAC;AAE5C,MAAM,MAAM,aAAa,GAAG,MAAM,OAAO,YAAY,CAAC;AACtD,MAAM,MAAM,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC,CAAC;AAElE,eAAO,MAAM,YAAY,EAAgC,SAAS,aAAa,EAAE,CAAC;AAElF,6EAA6E;AAC7E,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,CAG5D;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO,CAG9E;AAED,iHAAiH;AACjH,wBAAgB,cAAc,CAAC,IAAI,EAAE,aAAa,EAAE,QAAQ,EAAE,OAAO,GAAG,MAAM,CAG7E;AAED,6DAA6D;AAC7D,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAMvD"}
1
+ {"version":3,"file":"matrix-marks.d.ts","sourceRoot":"","sources":["../../../src/data/test-runner/matrix-marks.ts"],"names":[],"mappings":"AAMA,OAAO,EAWL,KAAK,aAAa,EACnB,MAAM,aAAa,CAAC;AAErB,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,aAAa,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,sEAAsE;IACtE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kEAAkE;IAClE,SAAS,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAUvB,6EAA6E;;;;;;;;;;;;;CAEpC,CAAC;AAE5C,MAAM,MAAM,aAAa,GAAG,MAAM,OAAO,YAAY,CAAC;AACtD,MAAM,MAAM,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC,CAAC;AAElE,eAAO,MAAM,YAAY,EAAgC,SAAS,aAAa,EAAE,CAAC;AAElF,6EAA6E;AAC7E,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,CAG5D;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO,CAG9E;AAED,iHAAiH;AACjH,wBAAgB,cAAc,CAAC,IAAI,EAAE,aAAa,EAAE,QAAQ,EAAE,OAAO,GAAG,MAAM,CAG7E;AAED,6DAA6D;AAC7D,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAMvD"}