@flanksource/clicky-ui 0.3.41 → 0.3.43

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 (487) hide show
  1. package/dist/ai.cjs +4 -0
  2. package/dist/ai.cjs.map +1 -1
  3. package/dist/ai.js +4 -0
  4. package/dist/ai.js.map +1 -1
  5. package/dist/comments/CommentCard.cjs +3 -1
  6. package/dist/comments/CommentCard.cjs.map +1 -1
  7. package/dist/comments/CommentCard.d.ts.map +1 -1
  8. package/dist/comments/CommentCard.js +4 -2
  9. package/dist/comments/CommentCard.js.map +1 -1
  10. package/dist/comments/CommentCardParts.cjs +16 -0
  11. package/dist/comments/CommentCardParts.cjs.map +1 -1
  12. package/dist/comments/CommentCardParts.d.ts +4 -1
  13. package/dist/comments/CommentCardParts.d.ts.map +1 -1
  14. package/dist/comments/CommentCardParts.js +16 -0
  15. package/dist/comments/CommentCardParts.js.map +1 -1
  16. package/dist/comments/comment-types.cjs.map +1 -1
  17. package/dist/comments/comment-types.d.ts +4 -0
  18. package/dist/comments/comment-types.d.ts.map +1 -1
  19. package/dist/comments/comment-types.js.map +1 -1
  20. package/dist/components/Combobox.cjs +54 -8
  21. package/dist/components/Combobox.cjs.map +1 -1
  22. package/dist/components/Combobox.d.ts.map +1 -1
  23. package/dist/components/Combobox.js +56 -10
  24. package/dist/components/Combobox.js.map +1 -1
  25. package/dist/components/ComboboxMenu.cjs +139 -113
  26. package/dist/components/ComboboxMenu.cjs.map +1 -1
  27. package/dist/components/ComboboxMenu.d.ts +3 -1
  28. package/dist/components/ComboboxMenu.d.ts.map +1 -1
  29. package/dist/components/ComboboxMenu.js +139 -113
  30. package/dist/components/ComboboxMenu.js.map +1 -1
  31. package/dist/components/ComboboxMenuTrigger.cjs +87 -0
  32. package/dist/components/ComboboxMenuTrigger.cjs.map +1 -0
  33. package/dist/components/ComboboxMenuTrigger.d.ts +23 -0
  34. package/dist/components/ComboboxMenuTrigger.d.ts.map +1 -0
  35. package/dist/components/ComboboxMenuTrigger.js +87 -0
  36. package/dist/components/ComboboxMenuTrigger.js.map +1 -0
  37. package/dist/components/JsonSchemaForm.cjs +30 -7
  38. package/dist/components/JsonSchemaForm.cjs.map +1 -1
  39. package/dist/components/JsonSchemaForm.d.ts.map +1 -1
  40. package/dist/components/JsonSchemaForm.js +30 -7
  41. package/dist/components/JsonSchemaForm.js.map +1 -1
  42. package/dist/components/SegmentedControl.cjs +20 -3
  43. package/dist/components/SegmentedControl.cjs.map +1 -1
  44. package/dist/components/SegmentedControl.d.ts +11 -0
  45. package/dist/components/SegmentedControl.d.ts.map +1 -1
  46. package/dist/components/SegmentedControl.js +21 -4
  47. package/dist/components/SegmentedControl.js.map +1 -1
  48. package/dist/components/combobox-types.d.ts +8 -0
  49. package/dist/components/combobox-types.d.ts.map +1 -1
  50. package/dist/components/json-schema-form-debug-badge.cjs +108 -0
  51. package/dist/components/json-schema-form-debug-badge.cjs.map +1 -0
  52. package/dist/components/json-schema-form-debug-badge.d.ts +10 -0
  53. package/dist/components/json-schema-form-debug-badge.d.ts.map +1 -0
  54. package/dist/components/json-schema-form-debug-badge.js +108 -0
  55. package/dist/components/json-schema-form-debug-badge.js.map +1 -0
  56. package/dist/components/json-schema-form-debug-glyph-map.cjs +129 -0
  57. package/dist/components/json-schema-form-debug-glyph-map.cjs.map +1 -0
  58. package/dist/components/json-schema-form-debug-glyph-map.d.ts +20 -0
  59. package/dist/components/json-schema-form-debug-glyph-map.d.ts.map +1 -0
  60. package/dist/components/json-schema-form-debug-glyph-map.js +129 -0
  61. package/dist/components/json-schema-form-debug-glyph-map.js.map +1 -0
  62. package/dist/components/json-schema-form-debug-glyph.cjs +13 -0
  63. package/dist/components/json-schema-form-debug-glyph.cjs.map +1 -0
  64. package/dist/components/json-schema-form-debug-glyph.d.ts +6 -0
  65. package/dist/components/json-schema-form-debug-glyph.d.ts.map +1 -0
  66. package/dist/components/json-schema-form-debug-glyph.js +13 -0
  67. package/dist/components/json-schema-form-debug-glyph.js.map +1 -0
  68. package/dist/components/json-schema-form-debug-groups.cjs +56 -0
  69. package/dist/components/json-schema-form-debug-groups.cjs.map +1 -0
  70. package/dist/components/json-schema-form-debug-groups.d.ts +8 -0
  71. package/dist/components/json-schema-form-debug-groups.d.ts.map +1 -0
  72. package/dist/components/json-schema-form-debug-groups.js +56 -0
  73. package/dist/components/json-schema-form-debug-groups.js.map +1 -0
  74. package/dist/components/json-schema-form-debug-keywords.cjs +159 -0
  75. package/dist/components/json-schema-form-debug-keywords.cjs.map +1 -0
  76. package/dist/components/json-schema-form-debug-keywords.d.ts +6 -0
  77. package/dist/components/json-schema-form-debug-keywords.d.ts.map +1 -0
  78. package/dist/components/json-schema-form-debug-keywords.js +159 -0
  79. package/dist/components/json-schema-form-debug-keywords.js.map +1 -0
  80. package/dist/components/json-schema-form-debug-listeners.cjs +102 -0
  81. package/dist/components/json-schema-form-debug-listeners.cjs.map +1 -0
  82. package/dist/components/json-schema-form-debug-listeners.d.ts +6 -0
  83. package/dist/components/json-schema-form-debug-listeners.d.ts.map +1 -0
  84. package/dist/components/json-schema-form-debug-listeners.js +102 -0
  85. package/dist/components/json-schema-form-debug-listeners.js.map +1 -0
  86. package/dist/components/json-schema-form-debug.cjs +31 -0
  87. package/dist/components/json-schema-form-debug.cjs.map +1 -0
  88. package/dist/components/json-schema-form-debug.d.ts +11 -0
  89. package/dist/components/json-schema-form-debug.d.ts.map +1 -0
  90. package/dist/components/json-schema-form-debug.js +31 -0
  91. package/dist/components/json-schema-form-debug.js.map +1 -0
  92. package/dist/components/json-schema-form-enum-choice.cjs +114 -0
  93. package/dist/components/json-schema-form-enum-choice.cjs.map +1 -0
  94. package/dist/components/json-schema-form-enum-choice.d.ts +14 -0
  95. package/dist/components/json-schema-form-enum-choice.d.ts.map +1 -0
  96. package/dist/components/json-schema-form-enum-choice.js +114 -0
  97. package/dist/components/json-schema-form-enum-choice.js.map +1 -0
  98. package/dist/components/json-schema-form-fields.cjs +3 -93
  99. package/dist/components/json-schema-form-fields.cjs.map +1 -1
  100. package/dist/components/json-schema-form-fields.d.ts.map +1 -1
  101. package/dist/components/json-schema-form-fields.js +1 -91
  102. package/dist/components/json-schema-form-fields.js.map +1 -1
  103. package/dist/components/json-schema-form-listeners.cjs +7 -1
  104. package/dist/components/json-schema-form-listeners.cjs.map +1 -1
  105. package/dist/components/json-schema-form-listeners.d.ts.map +1 -1
  106. package/dist/components/json-schema-form-listeners.js +7 -1
  107. package/dist/components/json-schema-form-listeners.js.map +1 -1
  108. package/dist/components/json-schema-form-preferences.cjs +1 -0
  109. package/dist/components/json-schema-form-preferences.cjs.map +1 -1
  110. package/dist/components/json-schema-form-preferences.d.ts +1 -0
  111. package/dist/components/json-schema-form-preferences.d.ts.map +1 -1
  112. package/dist/components/json-schema-form-preferences.js +1 -0
  113. package/dist/components/json-schema-form-preferences.js.map +1 -1
  114. package/dist/components/json-schema-form-render.cjs +21 -5
  115. package/dist/components/json-schema-form-render.cjs.map +1 -1
  116. package/dist/components/json-schema-form-render.d.ts.map +1 -1
  117. package/dist/components/json-schema-form-render.js +21 -5
  118. package/dist/components/json-schema-form-render.js.map +1 -1
  119. package/dist/components/json-schema-form-runtime-types.d.ts +1 -0
  120. package/dist/components/json-schema-form-runtime-types.d.ts.map +1 -1
  121. package/dist/components/json-schema-form-tone.cjs +12 -0
  122. package/dist/components/json-schema-form-tone.cjs.map +1 -1
  123. package/dist/components/json-schema-form-tone.js +12 -0
  124. package/dist/components/json-schema-form-tone.js.map +1 -1
  125. package/dist/components/json-schema-form-types.d.ts +1 -0
  126. package/dist/components/json-schema-form-types.d.ts.map +1 -1
  127. package/dist/data/GraphDiagram.cjs +125 -138
  128. package/dist/data/GraphDiagram.cjs.map +1 -1
  129. package/dist/data/GraphDiagram.d.ts +30 -23
  130. package/dist/data/GraphDiagram.d.ts.map +1 -1
  131. package/dist/data/GraphDiagram.js +128 -141
  132. package/dist/data/GraphDiagram.js.map +1 -1
  133. package/dist/data/GraphDiagramEdges.cjs +208 -0
  134. package/dist/data/GraphDiagramEdges.cjs.map +1 -0
  135. package/dist/data/GraphDiagramEdges.d.ts +40 -0
  136. package/dist/data/GraphDiagramEdges.d.ts.map +1 -0
  137. package/dist/data/GraphDiagramEdges.js +208 -0
  138. package/dist/data/GraphDiagramEdges.js.map +1 -0
  139. package/dist/data/GraphDiagramNodes.cjs +142 -0
  140. package/dist/data/GraphDiagramNodes.cjs.map +1 -0
  141. package/dist/data/GraphDiagramNodes.d.ts +22 -0
  142. package/dist/data/GraphDiagramNodes.d.ts.map +1 -0
  143. package/dist/data/GraphDiagramNodes.js +142 -0
  144. package/dist/data/GraphDiagramNodes.js.map +1 -0
  145. package/dist/data/ai/PromptRunEditor/RuntimeRows.cjs +8 -3
  146. package/dist/data/ai/PromptRunEditor/RuntimeRows.cjs.map +1 -1
  147. package/dist/data/ai/PromptRunEditor/RuntimeRows.d.ts.map +1 -1
  148. package/dist/data/ai/PromptRunEditor/RuntimeRows.js +8 -3
  149. package/dist/data/ai/PromptRunEditor/RuntimeRows.js.map +1 -1
  150. package/dist/data/ai/PromptRunEditor/index.cjs +37 -43
  151. package/dist/data/ai/PromptRunEditor/index.cjs.map +1 -1
  152. package/dist/data/ai/PromptRunEditor/index.d.ts +3 -1
  153. package/dist/data/ai/PromptRunEditor/index.d.ts.map +1 -1
  154. package/dist/data/ai/PromptRunEditor/index.js +38 -44
  155. package/dist/data/ai/PromptRunEditor/index.js.map +1 -1
  156. package/dist/data/ai/PromptRunEditor/runtimeActions.cjs +16 -5
  157. package/dist/data/ai/PromptRunEditor/runtimeActions.cjs.map +1 -1
  158. package/dist/data/ai/PromptRunEditor/runtimeActions.d.ts +4 -1
  159. package/dist/data/ai/PromptRunEditor/runtimeActions.d.ts.map +1 -1
  160. package/dist/data/ai/PromptRunEditor/runtimeActions.js +17 -6
  161. package/dist/data/ai/PromptRunEditor/runtimeActions.js.map +1 -1
  162. package/dist/data/ai/SessionInspector.approvals-model.cjs +12 -0
  163. package/dist/data/ai/SessionInspector.approvals-model.cjs.map +1 -1
  164. package/dist/data/ai/SessionInspector.approvals-model.d.ts +11 -2
  165. package/dist/data/ai/SessionInspector.approvals-model.d.ts.map +1 -1
  166. package/dist/data/ai/SessionInspector.approvals-model.js +12 -0
  167. package/dist/data/ai/SessionInspector.approvals-model.js.map +1 -1
  168. package/dist/data/ai/SessionInspector.approvals.cjs +25 -1
  169. package/dist/data/ai/SessionInspector.approvals.cjs.map +1 -1
  170. package/dist/data/ai/SessionInspector.approvals.d.ts.map +1 -1
  171. package/dist/data/ai/SessionInspector.approvals.js +26 -2
  172. package/dist/data/ai/SessionInspector.approvals.js.map +1 -1
  173. package/dist/data/ai/SessionInspector.summary.cjs +9 -3
  174. package/dist/data/ai/SessionInspector.summary.cjs.map +1 -1
  175. package/dist/data/ai/SessionInspector.summary.d.ts.map +1 -1
  176. package/dist/data/ai/SessionInspector.summary.js +9 -3
  177. package/dist/data/ai/SessionInspector.summary.js.map +1 -1
  178. package/dist/data/ai/SessionInspector.transcript.cjs +4 -0
  179. package/dist/data/ai/SessionInspector.transcript.cjs.map +1 -1
  180. package/dist/data/ai/SessionInspector.transcript.d.ts.map +1 -1
  181. package/dist/data/ai/SessionInspector.transcript.js +4 -0
  182. package/dist/data/ai/SessionInspector.transcript.js.map +1 -1
  183. package/dist/data/ai/SessionViewer.approval-body.cjs +146 -0
  184. package/dist/data/ai/SessionViewer.approval-body.cjs.map +1 -0
  185. package/dist/data/ai/SessionViewer.approval-body.d.ts +11 -0
  186. package/dist/data/ai/SessionViewer.approval-body.d.ts.map +1 -0
  187. package/dist/data/ai/SessionViewer.approval-body.js +146 -0
  188. package/dist/data/ai/SessionViewer.approval-body.js.map +1 -0
  189. package/dist/data/ai/SessionViewer.approval-forms.cjs +150 -0
  190. package/dist/data/ai/SessionViewer.approval-forms.cjs.map +1 -0
  191. package/dist/data/ai/SessionViewer.approval-forms.d.ts +23 -0
  192. package/dist/data/ai/SessionViewer.approval-forms.d.ts.map +1 -0
  193. package/dist/data/ai/SessionViewer.approval-forms.js +150 -0
  194. package/dist/data/ai/SessionViewer.approval-forms.js.map +1 -0
  195. package/dist/data/ai/SessionViewer.cjs +57 -20
  196. package/dist/data/ai/SessionViewer.cjs.map +1 -1
  197. package/dist/data/ai/SessionViewer.d.ts +13 -3
  198. package/dist/data/ai/SessionViewer.d.ts.map +1 -1
  199. package/dist/data/ai/SessionViewer.decision-controls.cjs +313 -0
  200. package/dist/data/ai/SessionViewer.decision-controls.cjs.map +1 -0
  201. package/dist/data/ai/SessionViewer.decision-controls.d.ts +43 -0
  202. package/dist/data/ai/SessionViewer.decision-controls.d.ts.map +1 -0
  203. package/dist/data/ai/SessionViewer.decision-controls.js +313 -0
  204. package/dist/data/ai/SessionViewer.decision-controls.js.map +1 -0
  205. package/dist/data/ai/SessionViewer.decision.cjs +21 -0
  206. package/dist/data/ai/SessionViewer.decision.cjs.map +1 -0
  207. package/dist/data/ai/SessionViewer.decision.d.ts +12 -0
  208. package/dist/data/ai/SessionViewer.decision.d.ts.map +1 -0
  209. package/dist/data/ai/SessionViewer.decision.js +21 -0
  210. package/dist/data/ai/SessionViewer.decision.js.map +1 -0
  211. package/dist/data/ai/SessionViewer.input.cjs +14 -0
  212. package/dist/data/ai/SessionViewer.input.cjs.map +1 -1
  213. package/dist/data/ai/SessionViewer.input.d.ts +5 -0
  214. package/dist/data/ai/SessionViewer.input.d.ts.map +1 -1
  215. package/dist/data/ai/SessionViewer.input.js +14 -0
  216. package/dist/data/ai/SessionViewer.input.js.map +1 -1
  217. package/dist/data/ai/SessionViewer.js +58 -21
  218. package/dist/data/ai/SessionViewer.js.map +1 -1
  219. package/dist/data/ai/SessionViewer.model.cjs.map +1 -1
  220. package/dist/data/ai/SessionViewer.model.d.ts +4 -0
  221. package/dist/data/ai/SessionViewer.model.d.ts.map +1 -1
  222. package/dist/data/ai/SessionViewer.model.js.map +1 -1
  223. package/dist/data/ai/SessionViewer.rows.cjs +6 -3
  224. package/dist/data/ai/SessionViewer.rows.cjs.map +1 -1
  225. package/dist/data/ai/SessionViewer.rows.d.ts +2 -1
  226. package/dist/data/ai/SessionViewer.rows.d.ts.map +1 -1
  227. package/dist/data/ai/SessionViewer.rows.js +6 -3
  228. package/dist/data/ai/SessionViewer.rows.js.map +1 -1
  229. package/dist/data/ai/SessionViewer.tool-row.cjs +29 -237
  230. package/dist/data/ai/SessionViewer.tool-row.cjs.map +1 -1
  231. package/dist/data/ai/SessionViewer.tool-row.d.ts.map +1 -1
  232. package/dist/data/ai/SessionViewer.tool-row.js +27 -235
  233. package/dist/data/ai/SessionViewer.tool-row.js.map +1 -1
  234. package/dist/data/ai/SessionViewer.unified.d.ts +4 -0
  235. package/dist/data/ai/SessionViewer.unified.d.ts.map +1 -1
  236. package/dist/data/ai/SessionViewerMenu.cjs +8 -2
  237. package/dist/data/ai/SessionViewerMenu.cjs.map +1 -1
  238. package/dist/data/ai/SessionViewerMenu.d.ts +4 -1
  239. package/dist/data/ai/SessionViewerMenu.d.ts.map +1 -1
  240. package/dist/data/ai/SessionViewerMenu.js +8 -2
  241. package/dist/data/ai/SessionViewerMenu.js.map +1 -1
  242. package/dist/data/ai/SpecRuntimeEditor/CommitSection.cjs +28 -17
  243. package/dist/data/ai/SpecRuntimeEditor/CommitSection.cjs.map +1 -1
  244. package/dist/data/ai/SpecRuntimeEditor/CommitSection.d.ts +10 -2
  245. package/dist/data/ai/SpecRuntimeEditor/CommitSection.d.ts.map +1 -1
  246. package/dist/data/ai/SpecRuntimeEditor/CommitSection.js +29 -18
  247. package/dist/data/ai/SpecRuntimeEditor/CommitSection.js.map +1 -1
  248. package/dist/data/ai/SpecRuntimeEditor/index.cjs +9 -1
  249. package/dist/data/ai/SpecRuntimeEditor/index.cjs.map +1 -1
  250. package/dist/data/ai/SpecRuntimeEditor/index.d.ts +9 -2
  251. package/dist/data/ai/SpecRuntimeEditor/index.d.ts.map +1 -1
  252. package/dist/data/ai/SpecRuntimeEditor/index.js +9 -1
  253. package/dist/data/ai/SpecRuntimeEditor/index.js.map +1 -1
  254. package/dist/data/ai/SpecRuntimeEditor/permission-mode-visuals.cjs +1 -1
  255. package/dist/data/ai/SpecRuntimeEditor/permission-mode-visuals.js +1 -1
  256. package/dist/data/ai/SpecRuntimeEditor/summaries.cjs.map +1 -1
  257. package/dist/data/ai/SpecRuntimeEditor/summaries.d.ts +8 -2
  258. package/dist/data/ai/SpecRuntimeEditor/summaries.d.ts.map +1 -1
  259. package/dist/data/ai/SpecRuntimeEditor/summaries.js.map +1 -1
  260. package/dist/data/ai/SpecRuntimeEditor/update.cjs +14 -6
  261. package/dist/data/ai/SpecRuntimeEditor/update.cjs.map +1 -1
  262. package/dist/data/ai/SpecRuntimeEditor/update.d.ts +1 -0
  263. package/dist/data/ai/SpecRuntimeEditor/update.d.ts.map +1 -1
  264. package/dist/data/ai/SpecRuntimeEditor/update.js +14 -6
  265. package/dist/data/ai/SpecRuntimeEditor/update.js.map +1 -1
  266. package/dist/data/ai/approval-request.cjs +75 -0
  267. package/dist/data/ai/approval-request.cjs.map +1 -0
  268. package/dist/data/ai/approval-request.d.ts +155 -0
  269. package/dist/data/ai/approval-request.d.ts.map +1 -0
  270. package/dist/data/ai/approval-request.js +75 -0
  271. package/dist/data/ai/approval-request.js.map +1 -0
  272. package/dist/data/ai/index.d.ts +3 -0
  273. package/dist/data/ai/index.d.ts.map +1 -1
  274. package/dist/data/ai/runtime-preset-menu/SavePresetDialog.cjs +125 -0
  275. package/dist/data/ai/runtime-preset-menu/SavePresetDialog.cjs.map +1 -0
  276. package/dist/data/ai/runtime-preset-menu/SavePresetDialog.d.ts +11 -0
  277. package/dist/data/ai/runtime-preset-menu/SavePresetDialog.d.ts.map +1 -0
  278. package/dist/data/ai/runtime-preset-menu/SavePresetDialog.js +125 -0
  279. package/dist/data/ai/runtime-preset-menu/SavePresetDialog.js.map +1 -0
  280. package/dist/data/ai/runtime-preset-menu/index.d.ts +3 -0
  281. package/dist/data/ai/runtime-preset-menu/index.d.ts.map +1 -0
  282. package/dist/data/ai/runtime-preset-menu/model.cjs +73 -0
  283. package/dist/data/ai/runtime-preset-menu/model.cjs.map +1 -0
  284. package/dist/data/ai/runtime-preset-menu/model.d.ts +13 -0
  285. package/dist/data/ai/runtime-preset-menu/model.d.ts.map +1 -0
  286. package/dist/data/ai/runtime-preset-menu/model.js +73 -0
  287. package/dist/data/ai/runtime-preset-menu/model.js.map +1 -0
  288. package/dist/data/ai/runtime-preset-menu/use-runtime-preset-menu.cjs +149 -0
  289. package/dist/data/ai/runtime-preset-menu/use-runtime-preset-menu.cjs.map +1 -0
  290. package/dist/data/ai/runtime-preset-menu/use-runtime-preset-menu.d.ts +15 -0
  291. package/dist/data/ai/runtime-preset-menu/use-runtime-preset-menu.d.ts.map +1 -0
  292. package/dist/data/ai/runtime-preset-menu/use-runtime-preset-menu.js +149 -0
  293. package/dist/data/ai/runtime-preset-menu/use-runtime-preset-menu.js.map +1 -0
  294. package/dist/data/ai/runtime-spec-fields.cjs +166 -0
  295. package/dist/data/ai/runtime-spec-fields.cjs.map +1 -0
  296. package/dist/data/ai/runtime-spec-fields.d.ts +13 -0
  297. package/dist/data/ai/runtime-spec-fields.d.ts.map +1 -0
  298. package/dist/data/ai/runtime-spec-fields.js +166 -0
  299. package/dist/data/ai/runtime-spec-fields.js.map +1 -0
  300. package/dist/data/ai/session-categories.cjs +4 -0
  301. package/dist/data/ai/session-categories.cjs.map +1 -1
  302. package/dist/data/ai/session-categories.d.ts +1 -0
  303. package/dist/data/ai/session-categories.d.ts.map +1 -1
  304. package/dist/data/ai/session-categories.js +4 -0
  305. package/dist/data/ai/session-categories.js.map +1 -1
  306. package/dist/data/ai/use-session-scroll.cjs +49 -21
  307. package/dist/data/ai/use-session-scroll.cjs.map +1 -1
  308. package/dist/data/ai/use-session-scroll.d.ts +2 -0
  309. package/dist/data/ai/use-session-scroll.d.ts.map +1 -1
  310. package/dist/data/ai/use-session-scroll.js +49 -21
  311. package/dist/data/ai/use-session-scroll.js.map +1 -1
  312. package/dist/data/chat/Chat.runtime.cjs +1 -1
  313. package/dist/data/chat/Chat.runtime.cjs.map +1 -1
  314. package/dist/data/chat/Chat.runtime.d.ts.map +1 -1
  315. package/dist/data/chat/Chat.runtime.js +1 -1
  316. package/dist/data/chat/Chat.runtime.js.map +1 -1
  317. package/dist/data/graph-columns-layout.cjs +216 -0
  318. package/dist/data/graph-columns-layout.cjs.map +1 -0
  319. package/dist/data/graph-columns-layout.d.ts +56 -0
  320. package/dist/data/graph-columns-layout.d.ts.map +1 -0
  321. package/dist/data/graph-columns-layout.js +216 -0
  322. package/dist/data/graph-columns-layout.js.map +1 -0
  323. package/dist/data/graph-diagram-model.cjs +73 -0
  324. package/dist/data/graph-diagram-model.cjs.map +1 -0
  325. package/dist/data/graph-diagram-model.d.ts +90 -0
  326. package/dist/data/graph-diagram-model.d.ts.map +1 -0
  327. package/dist/data/graph-diagram-model.js +73 -0
  328. package/dist/data/graph-diagram-model.js.map +1 -0
  329. package/dist/data/graph-edge-routing.cjs +235 -0
  330. package/dist/data/graph-edge-routing.cjs.map +1 -0
  331. package/dist/data/graph-edge-routing.d.ts +73 -0
  332. package/dist/data/graph-edge-routing.d.ts.map +1 -0
  333. package/dist/data/graph-edge-routing.js +235 -0
  334. package/dist/data/graph-edge-routing.js.map +1 -0
  335. package/dist/data/graph-layout.cjs +0 -82
  336. package/dist/data/graph-layout.cjs.map +1 -1
  337. package/dist/data/graph-layout.d.ts +1 -28
  338. package/dist/data/graph-layout.d.ts.map +1 -1
  339. package/dist/data/graph-layout.js +1 -83
  340. package/dist/data/graph-layout.js.map +1 -1
  341. package/dist/data/har/HarPanel.cjs +129 -33
  342. package/dist/data/har/HarPanel.cjs.map +1 -1
  343. package/dist/data/har/HarPanel.d.ts +13 -1
  344. package/dist/data/har/HarPanel.d.ts.map +1 -1
  345. package/dist/data/har/HarPanel.js +130 -34
  346. package/dist/data/har/HarPanel.js.map +1 -1
  347. package/dist/data/har/fixtures.d.ts +12 -0
  348. package/dist/data/har/fixtures.d.ts.map +1 -1
  349. package/dist/data/har/types.d.ts +12 -0
  350. package/dist/data/har/types.d.ts.map +1 -1
  351. package/dist/data/runtime/RuntimeBar.cjs +67 -84
  352. package/dist/data/runtime/RuntimeBar.cjs.map +1 -1
  353. package/dist/data/runtime/RuntimeBar.d.ts +4 -5
  354. package/dist/data/runtime/RuntimeBar.d.ts.map +1 -1
  355. package/dist/data/runtime/RuntimeBar.fields.cjs +170 -0
  356. package/dist/data/runtime/RuntimeBar.fields.cjs.map +1 -0
  357. package/dist/data/runtime/RuntimeBar.fields.d.ts +16 -0
  358. package/dist/data/runtime/RuntimeBar.fields.d.ts.map +1 -0
  359. package/dist/data/runtime/RuntimeBar.fields.js +170 -0
  360. package/dist/data/runtime/RuntimeBar.fields.js.map +1 -0
  361. package/dist/data/runtime/RuntimeBar.js +70 -87
  362. package/dist/data/runtime/RuntimeBar.js.map +1 -1
  363. package/dist/data/runtime/RuntimeBar.selection.cjs +56 -0
  364. package/dist/data/runtime/RuntimeBar.selection.cjs.map +1 -0
  365. package/dist/data/runtime/RuntimeBar.selection.d.ts +20 -0
  366. package/dist/data/runtime/RuntimeBar.selection.d.ts.map +1 -0
  367. package/dist/data/runtime/RuntimeBar.selection.js +56 -0
  368. package/dist/data/runtime/RuntimeBar.selection.js.map +1 -0
  369. package/dist/data/runtime/RuntimeBarActions.cjs +10 -6
  370. package/dist/data/runtime/RuntimeBarActions.cjs.map +1 -1
  371. package/dist/data/runtime/RuntimeBarActions.d.ts +8 -1
  372. package/dist/data/runtime/RuntimeBarActions.d.ts.map +1 -1
  373. package/dist/data/runtime/RuntimeBarActions.js +10 -6
  374. package/dist/data/runtime/RuntimeBarActions.js.map +1 -1
  375. package/dist/data/runtime/RuntimeBarIdentity.cjs +166 -0
  376. package/dist/data/runtime/RuntimeBarIdentity.cjs.map +1 -0
  377. package/dist/data/runtime/RuntimeBarIdentity.d.ts +25 -0
  378. package/dist/data/runtime/RuntimeBarIdentity.d.ts.map +1 -0
  379. package/dist/data/runtime/RuntimeBarIdentity.js +166 -0
  380. package/dist/data/runtime/RuntimeBarIdentity.js.map +1 -0
  381. package/dist/data/runtime/RuntimeBarLayout.cjs +95 -0
  382. package/dist/data/runtime/RuntimeBarLayout.cjs.map +1 -0
  383. package/dist/data/runtime/RuntimeBarLayout.d.ts +9 -0
  384. package/dist/data/runtime/RuntimeBarLayout.d.ts.map +1 -0
  385. package/dist/data/runtime/RuntimeBarLayout.js +95 -0
  386. package/dist/data/runtime/RuntimeBarLayout.js.map +1 -0
  387. package/dist/data/runtime/RuntimeBarSegment.cjs +25 -14
  388. package/dist/data/runtime/RuntimeBarSegment.cjs.map +1 -1
  389. package/dist/data/runtime/RuntimeBarSegment.d.ts +4 -0
  390. package/dist/data/runtime/RuntimeBarSegment.d.ts.map +1 -1
  391. package/dist/data/runtime/RuntimeBarSegment.js +25 -14
  392. package/dist/data/runtime/RuntimeBarSegment.js.map +1 -1
  393. package/dist/data/runtime/RuntimeLimitInput.cjs +41 -0
  394. package/dist/data/runtime/RuntimeLimitInput.cjs.map +1 -0
  395. package/dist/data/runtime/RuntimeLimitInput.d.ts +9 -0
  396. package/dist/data/runtime/RuntimeLimitInput.d.ts.map +1 -0
  397. package/dist/data/runtime/RuntimeLimitInput.js +41 -0
  398. package/dist/data/runtime/RuntimeLimitInput.js.map +1 -0
  399. package/dist/data/runtime/use-runtime-bar-overflow.cjs +70 -0
  400. package/dist/data/runtime/use-runtime-bar-overflow.cjs.map +1 -0
  401. package/dist/data/runtime/use-runtime-bar-overflow.d.ts +13 -0
  402. package/dist/data/runtime/use-runtime-bar-overflow.d.ts.map +1 -0
  403. package/dist/data/runtime/use-runtime-bar-overflow.js +70 -0
  404. package/dist/data/runtime/use-runtime-bar-overflow.js.map +1 -0
  405. package/dist/data/use-edge-focus.cjs +20 -0
  406. package/dist/data/use-edge-focus.cjs.map +1 -0
  407. package/dist/data/use-edge-focus.d.ts +23 -0
  408. package/dist/data/use-edge-focus.d.ts.map +1 -0
  409. package/dist/data/use-edge-focus.js +20 -0
  410. package/dist/data/use-edge-focus.js.map +1 -0
  411. package/dist/data/use-pan-zoom.cjs +159 -0
  412. package/dist/data/use-pan-zoom.cjs.map +1 -0
  413. package/dist/data/use-pan-zoom.d.ts +79 -0
  414. package/dist/data/use-pan-zoom.d.ts.map +1 -0
  415. package/dist/data/use-pan-zoom.js +159 -0
  416. package/dist/data/use-pan-zoom.js.map +1 -0
  417. package/dist/data/version-info.cjs +3 -3
  418. package/dist/data/version-info.js +3 -3
  419. package/dist/data.cjs +5 -1
  420. package/dist/data.cjs.map +1 -1
  421. package/dist/data.d.ts +4 -3
  422. package/dist/data.d.ts.map +1 -1
  423. package/dist/data.js +6 -2
  424. package/dist/data.js.map +1 -1
  425. package/dist/index.cjs +5 -1
  426. package/dist/index.cjs.map +1 -1
  427. package/dist/index.js +6 -2
  428. package/dist/index.js.map +1 -1
  429. package/dist/overlay/DropdownMenu.cjs +1 -0
  430. package/dist/overlay/DropdownMenu.cjs.map +1 -1
  431. package/dist/overlay/DropdownMenu.d.ts +4 -0
  432. package/dist/overlay/DropdownMenu.d.ts.map +1 -1
  433. package/dist/overlay/DropdownMenu.js +1 -0
  434. package/dist/overlay/DropdownMenu.js.map +1 -1
  435. package/dist/overlay/DropdownMenuSubmenu.cjs +31 -15
  436. package/dist/overlay/DropdownMenuSubmenu.cjs.map +1 -1
  437. package/dist/overlay/DropdownMenuSubmenu.d.ts.map +1 -1
  438. package/dist/overlay/DropdownMenuSubmenu.js +31 -15
  439. package/dist/overlay/DropdownMenuSubmenu.js.map +1 -1
  440. package/dist/profiles/fields/profileFieldFilterEditor.cjs +5 -2
  441. package/dist/profiles/fields/profileFieldFilterEditor.cjs.map +1 -1
  442. package/dist/profiles/fields/profileFieldFilterEditor.js +5 -2
  443. package/dist/profiles/fields/profileFieldFilterEditor.js.map +1 -1
  444. package/dist/profiles/fields/profileFieldIcons.cjs +2 -0
  445. package/dist/profiles/fields/profileFieldIcons.cjs.map +1 -1
  446. package/dist/profiles/fields/profileFieldIcons.d.ts.map +1 -1
  447. package/dist/profiles/fields/profileFieldIcons.js +2 -0
  448. package/dist/profiles/fields/profileFieldIcons.js.map +1 -1
  449. package/dist/profiles/wizard/profileWizardModel.cjs +1 -0
  450. package/dist/profiles/wizard/profileWizardModel.cjs.map +1 -1
  451. package/dist/profiles/wizard/profileWizardModel.d.ts +3 -0
  452. package/dist/profiles/wizard/profileWizardModel.d.ts.map +1 -1
  453. package/dist/profiles/wizard/profileWizardModel.js +1 -0
  454. package/dist/profiles/wizard/profileWizardModel.js.map +1 -1
  455. package/dist/rpc/OperationCatalog.cjs +3 -1
  456. package/dist/rpc/OperationCatalog.cjs.map +1 -1
  457. package/dist/rpc/OperationCatalog.d.ts +3 -1
  458. package/dist/rpc/OperationCatalog.d.ts.map +1 -1
  459. package/dist/rpc/OperationCatalog.js +3 -1
  460. package/dist/rpc/OperationCatalog.js.map +1 -1
  461. package/dist/rpc/useOperationPages.cjs +6 -1
  462. package/dist/rpc/useOperationPages.cjs.map +1 -1
  463. package/dist/rpc/useOperationPages.d.ts +3 -1
  464. package/dist/rpc/useOperationPages.d.ts.map +1 -1
  465. package/dist/rpc/useOperationPages.js +6 -1
  466. package/dist/rpc/useOperationPages.js.map +1 -1
  467. package/dist/styles.css +1 -1
  468. package/package.json +1 -1
  469. package/schemas/json-schema-form.schema.json +5 -0
  470. package/dist/data/runtime/RuntimeBarCombo.cjs +0 -423
  471. package/dist/data/runtime/RuntimeBarCombo.cjs.map +0 -1
  472. package/dist/data/runtime/RuntimeBarCombo.d.ts +0 -33
  473. package/dist/data/runtime/RuntimeBarCombo.d.ts.map +0 -1
  474. package/dist/data/runtime/RuntimeBarCombo.js +0 -423
  475. package/dist/data/runtime/RuntimeBarCombo.js.map +0 -1
  476. package/dist/data/runtime/RuntimeBarLimits.cjs +0 -262
  477. package/dist/data/runtime/RuntimeBarLimits.cjs.map +0 -1
  478. package/dist/data/runtime/RuntimeBarLimits.d.ts +0 -17
  479. package/dist/data/runtime/RuntimeBarLimits.d.ts.map +0 -1
  480. package/dist/data/runtime/RuntimeBarLimits.js +0 -262
  481. package/dist/data/runtime/RuntimeBarLimits.js.map +0 -1
  482. package/dist/data/runtime/RuntimeBarSegments.cjs +0 -346
  483. package/dist/data/runtime/RuntimeBarSegments.cjs.map +0 -1
  484. package/dist/data/runtime/RuntimeBarSegments.d.ts +0 -37
  485. package/dist/data/runtime/RuntimeBarSegments.d.ts.map +0 -1
  486. package/dist/data/runtime/RuntimeBarSegments.js +0 -346
  487. package/dist/data/runtime/RuntimeBarSegments.js.map +0 -1
package/dist/ai.cjs CHANGED
@@ -79,8 +79,10 @@ const yaml = require("./data/ai/PromptRunEditor/yaml.cjs");
79
79
  const SessionInspector_approvalsModel = require("./data/ai/SessionInspector.approvals-model.cjs");
80
80
  const promptRuntime = require("./data/ai/PromptPicker/prompt-runtime.cjs");
81
81
  const SessionViewer_input = require("./data/ai/SessionViewer.input.cjs");
82
+ const runtimeSpecFields = require("./data/ai/runtime-spec-fields.cjs");
82
83
  const useRuntimeFamilies = require("./data/ai/runtime-profiles/use-runtime-families.cjs");
83
84
  const usePermissionCatalog = require("./data/ai/runtime-profiles/use-permission-catalog.cjs");
85
+ const useRuntimePresetMenu = require("./data/ai/runtime-preset-menu/use-runtime-preset-menu.cjs");
84
86
  const useResolution = require("./data/ai/runtime-profiles/use-resolution.cjs");
85
87
  const useRuntimeProfilePicker = require("./data/ai/runtime-profiles/use-runtime-profile-picker.cjs");
86
88
  exports.AGENT_RUNTIME_ICONS = agentActionIcons.AGENT_RUNTIME_ICONS;
@@ -273,8 +275,10 @@ exports.questionsFromToolInput = SessionViewer_input.questionsFromToolInput;
273
275
  exports.summarizeToolInput = SessionViewer_input.summarizeToolInput;
274
276
  exports.toolDiff = SessionViewer_input.toolDiff;
275
277
  exports.toolInputParams = SessionViewer_input.toolInputParams;
278
+ exports.runtimeSpecFields = runtimeSpecFields.runtimeSpecFields;
276
279
  exports.useRuntimeFamilies = useRuntimeFamilies.useRuntimeFamilies;
277
280
  exports.useRuntimePermissionCatalog = usePermissionCatalog.useRuntimePermissionCatalog;
281
+ exports.useRuntimePresetMenu = useRuntimePresetMenu.useRuntimePresetMenu;
278
282
  exports.useRuntimePresetResolution = useResolution.useRuntimePresetResolution;
279
283
  exports.useRuntimeProfileResolution = useResolution.useRuntimeProfileResolution;
280
284
  exports.useRuntimeProfilePicker = useRuntimeProfilePicker.useRuntimeProfilePicker;
package/dist/ai.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"ai.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"ai.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
package/dist/ai.js CHANGED
@@ -77,8 +77,10 @@ import { parsePromptRunYaml, promptRunYaml } from "./data/ai/PromptRunEditor/yam
77
77
  import { pendingApprovalRequests } from "./data/ai/SessionInspector.approvals-model.js";
78
78
  import { promptPreviewText, promptRuntimeValueToPayload, specToPromptRuntimeValue } from "./data/ai/PromptPicker/prompt-runtime.js";
79
79
  import { questionsFromToolInput, summarizeToolInput, toolDiff, toolInputParams } from "./data/ai/SessionViewer.input.js";
80
+ import { runtimeSpecFields } from "./data/ai/runtime-spec-fields.js";
80
81
  import { useRuntimeFamilies } from "./data/ai/runtime-profiles/use-runtime-families.js";
81
82
  import { useRuntimePermissionCatalog } from "./data/ai/runtime-profiles/use-permission-catalog.js";
83
+ import { useRuntimePresetMenu } from "./data/ai/runtime-preset-menu/use-runtime-preset-menu.js";
82
84
  import { useRuntimePresetResolution, useRuntimeProfileResolution } from "./data/ai/runtime-profiles/use-resolution.js";
83
85
  import { useRuntimeProfilePicker } from "./data/ai/runtime-profiles/use-runtime-profile-picker.js";
84
86
  export {
@@ -250,6 +252,7 @@ export {
250
252
  runtimeModeOptions,
251
253
  runtimeModelError,
252
254
  runtimeRows,
255
+ runtimeSpecFields,
253
256
  runtimeSummary,
254
257
  selectionForMode,
255
258
  selectionForRuntime,
@@ -273,6 +276,7 @@ export {
273
276
  useRemoteSession,
274
277
  useRuntimeFamilies,
275
278
  useRuntimePermissionCatalog,
279
+ useRuntimePresetMenu,
276
280
  useRuntimePresetResolution,
277
281
  useRuntimeProfilePicker,
278
282
  useRuntimeProfileResolution,
package/dist/ai.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"ai.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"ai.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -131,6 +131,7 @@ function CommentBody({
131
131
  !isReply && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-1 flex flex-wrap gap-1", children: [
132
132
  /* @__PURE__ */ jsxRuntime.jsx(CommentCardParts.StatusChip, { comment, config }),
133
133
  /* @__PURE__ */ jsxRuntime.jsx(CommentCardParts.RatingChip, { rating: comment.rating }),
134
+ /* @__PURE__ */ jsxRuntime.jsx(CommentCardParts.ReviewDecisionChip, { decision: comment.reviewDecision }),
134
135
  /* @__PURE__ */ jsxRuntime.jsx(CommentCardParts.FacetBadges, { comment, config })
135
136
  ] })
136
137
  ] }),
@@ -245,9 +246,10 @@ function CommentCard(props) {
245
246
  !isReply && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
246
247
  /* @__PURE__ */ jsxRuntime.jsx(CommentCardParts.StatusChip, { comment, config }),
247
248
  /* @__PURE__ */ jsxRuntime.jsx(CommentCardParts.RatingChip, { rating: comment.rating }),
249
+ /* @__PURE__ */ jsxRuntime.jsx(CommentCardParts.ReviewDecisionChip, { decision: comment.reviewDecision }),
248
250
  /* @__PURE__ */ jsxRuntime.jsx(CommentCardParts.FacetBadges, { comment, config, compact: true })
249
251
  ] }),
250
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 flex-1 truncate text-[12px] text-foreground/80", children: comment.body.trim() ? commentUtils.truncatePlain(comment.body) : comment.rating === "positive" ? "Positive rating" : comment.rating === "negative" ? "Negative rating" : "Empty comment" }),
252
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 flex-1 truncate text-[12px] text-foreground/80", children: comment.body.trim() ? commentUtils.truncatePlain(comment.body) : comment.rating === "positive" ? "Positive rating" : comment.rating === "negative" ? "Negative rating" : comment.reviewDecision === "approved" ? "Approved" : "Empty comment" }),
251
253
  /* @__PURE__ */ jsxRuntime.jsx(
252
254
  "span",
253
255
  {
@@ -1 +1 @@
1
- {"version":3,"file":"CommentCard.cjs","sources":["../../src/comments/CommentCard.tsx"],"sourcesContent":["import { useState, type ReactNode } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { Icon } from \"../data/Icon\";\nimport { DropdownMenu, type DropdownMenuItem } from \"../overlay/DropdownMenu\";\nimport {\n parseTimestamp,\n formatRelativeTime,\n} from \"../data/cells/timestamp-format\";\nimport {\n UiCheck,\n UiCopy,\n UiDotsVertical,\n UiFullscreen,\n UiLock,\n UiRestart,\n UiTrash,\n} from \"../icons\";\nimport { CommentAuthorAvatar } from \"./CommentAuthor\";\nimport {\n ChecklistChips,\n FacetBadges,\n RatingChip,\n RefChips,\n StatusChip,\n} from \"./CommentCardParts\";\nimport { CommentMarkdown } from \"./CommentMarkdown\";\nimport { authorDisplayName, truncatePlain } from \"./comment-utils\";\nimport {\n resolveCommentStage,\n statusForCommentStage,\n} from \"../lib/comment-stage\";\nimport type { Comment, CommentConfig } from \"./comment-types\";\n\nexport type CommentCardProps = {\n comment: Comment;\n config: CommentConfig;\n /** Tighter padding for dense rails. */\n compact?: boolean;\n /** Render expanded on first mount. */\n defaultExpanded?: boolean;\n /** Custom body renderer; defaults to the lightweight CommentMarkdown. */\n renderBody?: (body: string) => ReactNode;\n /** Change this comment's status (roots only). */\n onUpdateStatus?: (status: string) => void | Promise<void>;\n /** Close a resolved root comment. */\n onClose?: () => void | Promise<void>;\n /** Delete this comment. */\n onDelete?: () => void;\n /** Copy this comment's whole thread in the caller's canonical format. */\n onCopy?: () => void | Promise<void>;\n /** Begin a reply to this comment. */\n onReply?: () => void;\n /** Advance the checklist item at `index` to its next status. */\n onChecklistToggle?: (index: number) => void;\n /**\n * Open this card's thread in a larger view. Owned by the caller because a\n * card knows only itself, while maximizing shows the root and its replies.\n * Omit to drop the action (e.g. inside an already-maximized thread).\n */\n onMaximize?: () => void;\n};\n\nfunction actionMenuItems(\n isReply: boolean,\n opts: {\n onDelete?: () => void;\n statusActions?: DropdownMenuItem[];\n onCopy?: () => void;\n onMaximize?: () => void;\n },\n): DropdownMenuItem[] {\n const items: DropdownMenuItem[] = [];\n if (opts.onDelete) {\n items.push({ label: \"Delete\", icon: UiTrash, onSelect: opts.onDelete });\n }\n if (!isReply) items.push(...(opts.statusActions ?? []));\n if (opts.onCopy) {\n items.push({ label: \"Copy\", icon: UiCopy, onSelect: opts.onCopy });\n }\n if (opts.onMaximize) {\n items.push({\n label: \"Maximise\",\n icon: UiFullscreen,\n onSelect: opts.onMaximize,\n });\n }\n return items;\n}\n\nfunction CommentBody({\n comment,\n config,\n renderBody,\n onUpdateStatus,\n onClose,\n onDelete,\n onCopy,\n onReply,\n onChecklistToggle,\n onMaximize,\n}: CommentCardProps) {\n const [actionError, setActionError] = useState(\"\");\n const isReply = Boolean(comment.parentId);\n const date = parseTimestamp(comment.createdAt);\n const resolved = statusForCommentStage(config, \"resolved\");\n const active = statusForCommentStage(config, \"active\");\n const closed = statusForCommentStage(config, \"closed\");\n const stage = resolveCommentStage(config, comment.status);\n const updateStatus = async (status: string) => {\n setActionError(\"\");\n try {\n await onUpdateStatus?.(status);\n } catch (error) {\n setActionError(\n `Couldn't update comment: ${error instanceof Error ? error.message : \"Unexpected error\"}`,\n );\n }\n };\n const close = async () => {\n setActionError(\"\");\n try {\n await onClose?.();\n } catch (error) {\n setActionError(\n `Couldn't close comment: ${error instanceof Error ? error.message : \"Unexpected error\"}`,\n );\n }\n };\n const copy = async () => {\n setActionError(\"\");\n try {\n await onCopy?.();\n } catch (error) {\n setActionError(\n `Couldn't copy comment: ${error instanceof Error ? error.message : \"Unexpected error\"}`,\n );\n }\n };\n const menuItems = actionMenuItems(isReply, {\n ...(onDelete ? { onDelete } : {}),\n statusActions: [\n ...(stage === \"active\" && onUpdateStatus && resolved\n ? [\n {\n label: \"Resolve\",\n icon: UiCheck,\n onSelect: () => void updateStatus(resolved.value),\n },\n ]\n : []),\n ...(stage === \"resolved\" && onClose && closed\n ? [\n {\n label: \"Close\",\n icon: UiLock,\n onSelect: () => void close(),\n },\n ]\n : []),\n ...((stage === \"resolved\" || stage === \"closed\") &&\n onUpdateStatus &&\n active\n ? [\n {\n label: \"Reopen\",\n icon: UiRestart,\n onSelect: () => void updateStatus(active.value),\n },\n ]\n : []),\n ],\n ...(onCopy ? { onCopy: () => void copy() } : {}),\n ...(onMaximize ? { onMaximize } : {}),\n });\n\n return (\n <div className=\"space-y-2.5\">\n <div className=\"flex items-start gap-2.5\">\n <CommentAuthorAvatar author={comment.author} />\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex min-w-0 items-baseline gap-1.5\">\n <span className=\"truncate text-xs font-semibold text-foreground\">\n {authorDisplayName(comment.author)}\n </span>\n {date && (\n <span\n title={date.toLocaleString()}\n className=\"shrink-0 text-[10px] text-muted-foreground\"\n >\n {formatRelativeTime(date)}\n </span>\n )}\n </div>\n {!isReply && (\n <div className=\"mt-1 flex flex-wrap gap-1\">\n <StatusChip comment={comment} config={config} />\n <RatingChip rating={comment.rating} />\n <FacetBadges comment={comment} config={config} />\n </div>\n )}\n </div>\n <div className=\"flex shrink-0 items-center gap-0.5\">\n {menuItems.length > 0 && (\n <DropdownMenu\n align=\"right\"\n menuClassName=\"min-w-[150px]\"\n trigger={\n <span\n role=\"button\"\n tabIndex={0}\n aria-label=\"Comment actions\"\n className=\"inline-flex rounded-full p-1.5 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground\"\n >\n <Icon icon={UiDotsVertical} className=\"text-sm\" />\n </span>\n }\n items={menuItems}\n />\n )}\n </div>\n </div>\n {comment.body.trim() && (\n <div className=\"text-[13px] leading-5 text-foreground\">\n {renderBody ? (\n renderBody(comment.body)\n ) : (\n <CommentMarkdown text={comment.body} />\n )}\n </div>\n )}\n {actionError && (\n <div\n role=\"alert\"\n className=\"rounded-md border border-destructive/30 bg-destructive/5 px-2.5 py-2 text-xs text-destructive\"\n >\n {actionError}\n </div>\n )}\n {!isReply && (\n <ChecklistChips\n comment={comment}\n {...(onChecklistToggle ? { onChecklistToggle } : {})}\n />\n )}\n {!isReply && <RefChips comment={comment} />}\n {onReply && (\n <button\n type=\"button\"\n onClick={onReply}\n className=\"-ml-2 rounded px-2 py-1 text-xs font-medium text-primary transition-colors hover:bg-primary/10\"\n >\n Reply\n </button>\n )}\n </div>\n );\n}\n\n/**\n * A single comment, collapsible between a compact one-line preview and a full\n * card. Offers a Maximise action when `onMaximize` is supplied — the owner\n * enlarges the whole thread. Fully controlled — all mutations are delegated to\n * the supplied callbacks.\n */\nexport function CommentCard(props: CommentCardProps) {\n const { comment, config, compact, defaultExpanded } = props;\n const [expanded, setExpanded] = useState(defaultExpanded ?? false);\n const [collapsedActionError, setCollapsedActionError] = useState(\"\");\n const isReply = Boolean(comment.parentId);\n const body = <CommentBody {...props} />;\n\n async function runCollapsedAction(action: \"resolve\" | \"close\" | \"reopen\") {\n setCollapsedActionError(\"\");\n try {\n if (action === \"close\") {\n await props.onClose?.();\n return;\n }\n const next = statusForCommentStage(\n config,\n action === \"resolve\" ? \"resolved\" : \"active\",\n );\n if (next) await props.onUpdateStatus?.(next.value);\n } catch (error) {\n setCollapsedActionError(\n `${action === \"close\" ? \"Couldn't close comment\" : \"Couldn't update comment\"}: ${error instanceof Error ? error.message : \"Unexpected error\"}`,\n );\n }\n }\n\n async function copyCollapsed() {\n setCollapsedActionError(\"\");\n try {\n await props.onCopy?.();\n } catch (error) {\n setCollapsedActionError(\n `Couldn't copy comment: ${error instanceof Error ? error.message : \"Unexpected error\"}`,\n );\n }\n }\n\n if (!expanded) {\n return (\n <>\n <div\n role=\"button\"\n tabIndex={0}\n onClick={() => setExpanded(true)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n setExpanded(true);\n }\n }}\n data-testid=\"comment-card\"\n data-comment-kind={isReply ? \"reply\" : \"root\"}\n data-comment-id={comment.id}\n className={cn(\n \"group/comment flex cursor-pointer items-center gap-2 rounded-lg px-2.5 py-1.5 text-xs transition-colors hover:bg-muted/50\",\n !isReply && \"border border-border bg-background shadow-sm\",\n isReply && \"ml-4 border-l-2 border-l-border bg-muted/30\",\n )}\n >\n <CommentAuthorAvatar author={comment.author} bare />\n <span className=\"shrink-0 text-[11px] font-semibold text-foreground\">\n {authorDisplayName(comment.author)}\n </span>\n {!isReply && (\n <>\n <StatusChip comment={comment} config={config} />\n <RatingChip rating={comment.rating} />\n <FacetBadges comment={comment} config={config} compact />\n </>\n )}\n <span className=\"min-w-0 flex-1 truncate text-[12px] text-foreground/80\">\n {comment.body.trim()\n ? truncatePlain(comment.body)\n : comment.rating === \"positive\"\n ? \"Positive rating\"\n : comment.rating === \"negative\"\n ? \"Negative rating\"\n : \"Empty comment\"}\n </span>\n <span\n role=\"presentation\"\n onClick={(e) => e.stopPropagation()}\n onKeyDown={(e) => e.stopPropagation()}\n >\n <DropdownMenu\n align=\"right\"\n trigger={\n <span\n role=\"button\"\n tabIndex={0}\n aria-label=\"Comment actions\"\n className=\"rounded p-0.5 text-muted-foreground opacity-0 transition-opacity hover:bg-muted hover:opacity-100 group-hover/comment:opacity-70\"\n >\n <Icon icon={UiDotsVertical} className=\"text-sm\" />\n </span>\n }\n items={actionMenuItems(isReply, {\n ...(props.onDelete ? { onDelete: props.onDelete } : {}),\n statusActions: [\n ...(resolveCommentStage(config, comment.status) ===\n \"active\" &&\n props.onUpdateStatus &&\n statusForCommentStage(config, \"resolved\")\n ? [\n {\n label: \"Resolve\",\n icon: UiCheck,\n onSelect: () => void runCollapsedAction(\"resolve\"),\n },\n ]\n : []),\n ...(resolveCommentStage(config, comment.status) ===\n \"resolved\" &&\n props.onClose &&\n statusForCommentStage(config, \"closed\")\n ? [\n {\n label: \"Close\",\n icon: UiLock,\n onSelect: () => void runCollapsedAction(\"close\"),\n },\n ]\n : []),\n ...((resolveCommentStage(config, comment.status) ===\n \"resolved\" ||\n resolveCommentStage(config, comment.status) === \"closed\") &&\n props.onUpdateStatus &&\n statusForCommentStage(config, \"active\")\n ? [\n {\n label: \"Reopen\",\n icon: UiRestart,\n onSelect: () => void runCollapsedAction(\"reopen\"),\n },\n ]\n : []),\n ],\n ...(props.onCopy ? { onCopy: () => void copyCollapsed() } : {}),\n ...(props.onMaximize ? { onMaximize: props.onMaximize } : {}),\n })}\n />\n </span>\n </div>\n {collapsedActionError && (\n <div\n role=\"alert\"\n className=\"rounded-md border border-destructive/30 bg-destructive/5 px-2.5 py-2 text-xs text-destructive\"\n >\n {collapsedActionError}\n </div>\n )}\n </>\n );\n }\n\n return (\n <>\n <div\n data-testid=\"comment-card\"\n data-comment-kind={isReply ? \"reply\" : \"root\"}\n data-comment-id={comment.id}\n className={cn(\n \"group/comment rounded-xl bg-background px-3.5 py-3 text-xs\",\n !isReply &&\n \"border border-border/80 shadow-sm transition-shadow hover:shadow-md\",\n compact && \"px-2.5 py-2.5\",\n isReply && \"ml-4 border-l-2 border-l-border bg-muted/20 shadow-none\",\n )}\n >\n {body}\n </div>\n </>\n );\n}\n"],"names":["UiTrash","UiCopy","UiFullscreen","useState","parseTimestamp","statusForCommentStage","resolveCommentStage","UiCheck","UiLock","UiRestart","jsxs","jsx","CommentAuthorAvatar","authorDisplayName","StatusChip","RatingChip","FacetBadges","DropdownMenu","Icon","UiDotsVertical","CommentMarkdown","ChecklistChips","RefChips","Fragment","cn","truncatePlain"],"mappings":"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"}
1
+ {"version":3,"file":"CommentCard.cjs","sources":["../../src/comments/CommentCard.tsx"],"sourcesContent":["import { useState, type ReactNode } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { Icon } from \"../data/Icon\";\nimport { DropdownMenu, type DropdownMenuItem } from \"../overlay/DropdownMenu\";\nimport {\n parseTimestamp,\n formatRelativeTime,\n} from \"../data/cells/timestamp-format\";\nimport {\n UiCheck,\n UiCopy,\n UiDotsVertical,\n UiFullscreen,\n UiLock,\n UiRestart,\n UiTrash,\n} from \"../icons\";\nimport { CommentAuthorAvatar } from \"./CommentAuthor\";\nimport {\n ChecklistChips,\n FacetBadges,\n RatingChip,\n ReviewDecisionChip,\n RefChips,\n StatusChip,\n} from \"./CommentCardParts\";\nimport { CommentMarkdown } from \"./CommentMarkdown\";\nimport { authorDisplayName, truncatePlain } from \"./comment-utils\";\nimport {\n resolveCommentStage,\n statusForCommentStage,\n} from \"../lib/comment-stage\";\nimport type { Comment, CommentConfig } from \"./comment-types\";\n\nexport type CommentCardProps = {\n comment: Comment;\n config: CommentConfig;\n /** Tighter padding for dense rails. */\n compact?: boolean;\n /** Render expanded on first mount. */\n defaultExpanded?: boolean;\n /** Custom body renderer; defaults to the lightweight CommentMarkdown. */\n renderBody?: (body: string) => ReactNode;\n /** Change this comment's status (roots only). */\n onUpdateStatus?: (status: string) => void | Promise<void>;\n /** Close a resolved root comment. */\n onClose?: () => void | Promise<void>;\n /** Delete this comment. */\n onDelete?: () => void;\n /** Copy this comment's whole thread in the caller's canonical format. */\n onCopy?: () => void | Promise<void>;\n /** Begin a reply to this comment. */\n onReply?: () => void;\n /** Advance the checklist item at `index` to its next status. */\n onChecklistToggle?: (index: number) => void;\n /**\n * Open this card's thread in a larger view. Owned by the caller because a\n * card knows only itself, while maximizing shows the root and its replies.\n * Omit to drop the action (e.g. inside an already-maximized thread).\n */\n onMaximize?: () => void;\n};\n\nfunction actionMenuItems(\n isReply: boolean,\n opts: {\n onDelete?: () => void;\n statusActions?: DropdownMenuItem[];\n onCopy?: () => void;\n onMaximize?: () => void;\n },\n): DropdownMenuItem[] {\n const items: DropdownMenuItem[] = [];\n if (opts.onDelete) {\n items.push({ label: \"Delete\", icon: UiTrash, onSelect: opts.onDelete });\n }\n if (!isReply) items.push(...(opts.statusActions ?? []));\n if (opts.onCopy) {\n items.push({ label: \"Copy\", icon: UiCopy, onSelect: opts.onCopy });\n }\n if (opts.onMaximize) {\n items.push({\n label: \"Maximise\",\n icon: UiFullscreen,\n onSelect: opts.onMaximize,\n });\n }\n return items;\n}\n\nfunction CommentBody({\n comment,\n config,\n renderBody,\n onUpdateStatus,\n onClose,\n onDelete,\n onCopy,\n onReply,\n onChecklistToggle,\n onMaximize,\n}: CommentCardProps) {\n const [actionError, setActionError] = useState(\"\");\n const isReply = Boolean(comment.parentId);\n const date = parseTimestamp(comment.createdAt);\n const resolved = statusForCommentStage(config, \"resolved\");\n const active = statusForCommentStage(config, \"active\");\n const closed = statusForCommentStage(config, \"closed\");\n const stage = resolveCommentStage(config, comment.status);\n const updateStatus = async (status: string) => {\n setActionError(\"\");\n try {\n await onUpdateStatus?.(status);\n } catch (error) {\n setActionError(\n `Couldn't update comment: ${error instanceof Error ? error.message : \"Unexpected error\"}`,\n );\n }\n };\n const close = async () => {\n setActionError(\"\");\n try {\n await onClose?.();\n } catch (error) {\n setActionError(\n `Couldn't close comment: ${error instanceof Error ? error.message : \"Unexpected error\"}`,\n );\n }\n };\n const copy = async () => {\n setActionError(\"\");\n try {\n await onCopy?.();\n } catch (error) {\n setActionError(\n `Couldn't copy comment: ${error instanceof Error ? error.message : \"Unexpected error\"}`,\n );\n }\n };\n const menuItems = actionMenuItems(isReply, {\n ...(onDelete ? { onDelete } : {}),\n statusActions: [\n ...(stage === \"active\" && onUpdateStatus && resolved\n ? [\n {\n label: \"Resolve\",\n icon: UiCheck,\n onSelect: () => void updateStatus(resolved.value),\n },\n ]\n : []),\n ...(stage === \"resolved\" && onClose && closed\n ? [\n {\n label: \"Close\",\n icon: UiLock,\n onSelect: () => void close(),\n },\n ]\n : []),\n ...((stage === \"resolved\" || stage === \"closed\") &&\n onUpdateStatus &&\n active\n ? [\n {\n label: \"Reopen\",\n icon: UiRestart,\n onSelect: () => void updateStatus(active.value),\n },\n ]\n : []),\n ],\n ...(onCopy ? { onCopy: () => void copy() } : {}),\n ...(onMaximize ? { onMaximize } : {}),\n });\n\n return (\n <div className=\"space-y-2.5\">\n <div className=\"flex items-start gap-2.5\">\n <CommentAuthorAvatar author={comment.author} />\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex min-w-0 items-baseline gap-1.5\">\n <span className=\"truncate text-xs font-semibold text-foreground\">\n {authorDisplayName(comment.author)}\n </span>\n {date && (\n <span\n title={date.toLocaleString()}\n className=\"shrink-0 text-[10px] text-muted-foreground\"\n >\n {formatRelativeTime(date)}\n </span>\n )}\n </div>\n {!isReply && (\n <div className=\"mt-1 flex flex-wrap gap-1\">\n <StatusChip comment={comment} config={config} />\n <RatingChip rating={comment.rating} />\n <ReviewDecisionChip decision={comment.reviewDecision} />\n <FacetBadges comment={comment} config={config} />\n </div>\n )}\n </div>\n <div className=\"flex shrink-0 items-center gap-0.5\">\n {menuItems.length > 0 && (\n <DropdownMenu\n align=\"right\"\n menuClassName=\"min-w-[150px]\"\n trigger={\n <span\n role=\"button\"\n tabIndex={0}\n aria-label=\"Comment actions\"\n className=\"inline-flex rounded-full p-1.5 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground\"\n >\n <Icon icon={UiDotsVertical} className=\"text-sm\" />\n </span>\n }\n items={menuItems}\n />\n )}\n </div>\n </div>\n {comment.body.trim() && (\n <div className=\"text-[13px] leading-5 text-foreground\">\n {renderBody ? (\n renderBody(comment.body)\n ) : (\n <CommentMarkdown text={comment.body} />\n )}\n </div>\n )}\n {actionError && (\n <div\n role=\"alert\"\n className=\"rounded-md border border-destructive/30 bg-destructive/5 px-2.5 py-2 text-xs text-destructive\"\n >\n {actionError}\n </div>\n )}\n {!isReply && (\n <ChecklistChips\n comment={comment}\n {...(onChecklistToggle ? { onChecklistToggle } : {})}\n />\n )}\n {!isReply && <RefChips comment={comment} />}\n {onReply && (\n <button\n type=\"button\"\n onClick={onReply}\n className=\"-ml-2 rounded px-2 py-1 text-xs font-medium text-primary transition-colors hover:bg-primary/10\"\n >\n Reply\n </button>\n )}\n </div>\n );\n}\n\n/**\n * A single comment, collapsible between a compact one-line preview and a full\n * card. Offers a Maximise action when `onMaximize` is supplied — the owner\n * enlarges the whole thread. Fully controlled — all mutations are delegated to\n * the supplied callbacks.\n */\nexport function CommentCard(props: CommentCardProps) {\n const { comment, config, compact, defaultExpanded } = props;\n const [expanded, setExpanded] = useState(defaultExpanded ?? false);\n const [collapsedActionError, setCollapsedActionError] = useState(\"\");\n const isReply = Boolean(comment.parentId);\n const body = <CommentBody {...props} />;\n\n async function runCollapsedAction(action: \"resolve\" | \"close\" | \"reopen\") {\n setCollapsedActionError(\"\");\n try {\n if (action === \"close\") {\n await props.onClose?.();\n return;\n }\n const next = statusForCommentStage(\n config,\n action === \"resolve\" ? \"resolved\" : \"active\",\n );\n if (next) await props.onUpdateStatus?.(next.value);\n } catch (error) {\n setCollapsedActionError(\n `${action === \"close\" ? \"Couldn't close comment\" : \"Couldn't update comment\"}: ${error instanceof Error ? error.message : \"Unexpected error\"}`,\n );\n }\n }\n\n async function copyCollapsed() {\n setCollapsedActionError(\"\");\n try {\n await props.onCopy?.();\n } catch (error) {\n setCollapsedActionError(\n `Couldn't copy comment: ${error instanceof Error ? error.message : \"Unexpected error\"}`,\n );\n }\n }\n\n if (!expanded) {\n return (\n <>\n <div\n role=\"button\"\n tabIndex={0}\n onClick={() => setExpanded(true)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n setExpanded(true);\n }\n }}\n data-testid=\"comment-card\"\n data-comment-kind={isReply ? \"reply\" : \"root\"}\n data-comment-id={comment.id}\n className={cn(\n \"group/comment flex cursor-pointer items-center gap-2 rounded-lg px-2.5 py-1.5 text-xs transition-colors hover:bg-muted/50\",\n !isReply && \"border border-border bg-background shadow-sm\",\n isReply && \"ml-4 border-l-2 border-l-border bg-muted/30\",\n )}\n >\n <CommentAuthorAvatar author={comment.author} bare />\n <span className=\"shrink-0 text-[11px] font-semibold text-foreground\">\n {authorDisplayName(comment.author)}\n </span>\n {!isReply && (\n <>\n <StatusChip comment={comment} config={config} />\n <RatingChip rating={comment.rating} />\n <ReviewDecisionChip decision={comment.reviewDecision} />\n <FacetBadges comment={comment} config={config} compact />\n </>\n )}\n <span className=\"min-w-0 flex-1 truncate text-[12px] text-foreground/80\">\n {comment.body.trim()\n ? truncatePlain(comment.body)\n : comment.rating === \"positive\"\n ? \"Positive rating\"\n : comment.rating === \"negative\"\n ? \"Negative rating\"\n : comment.reviewDecision === \"approved\"\n ? \"Approved\"\n : \"Empty comment\"}\n </span>\n <span\n role=\"presentation\"\n onClick={(e) => e.stopPropagation()}\n onKeyDown={(e) => e.stopPropagation()}\n >\n <DropdownMenu\n align=\"right\"\n trigger={\n <span\n role=\"button\"\n tabIndex={0}\n aria-label=\"Comment actions\"\n className=\"rounded p-0.5 text-muted-foreground opacity-0 transition-opacity hover:bg-muted hover:opacity-100 group-hover/comment:opacity-70\"\n >\n <Icon icon={UiDotsVertical} className=\"text-sm\" />\n </span>\n }\n items={actionMenuItems(isReply, {\n ...(props.onDelete ? { onDelete: props.onDelete } : {}),\n statusActions: [\n ...(resolveCommentStage(config, comment.status) ===\n \"active\" &&\n props.onUpdateStatus &&\n statusForCommentStage(config, \"resolved\")\n ? [\n {\n label: \"Resolve\",\n icon: UiCheck,\n onSelect: () => void runCollapsedAction(\"resolve\"),\n },\n ]\n : []),\n ...(resolveCommentStage(config, comment.status) ===\n \"resolved\" &&\n props.onClose &&\n statusForCommentStage(config, \"closed\")\n ? [\n {\n label: \"Close\",\n icon: UiLock,\n onSelect: () => void runCollapsedAction(\"close\"),\n },\n ]\n : []),\n ...((resolveCommentStage(config, comment.status) ===\n \"resolved\" ||\n resolveCommentStage(config, comment.status) === \"closed\") &&\n props.onUpdateStatus &&\n statusForCommentStage(config, \"active\")\n ? [\n {\n label: \"Reopen\",\n icon: UiRestart,\n onSelect: () => void runCollapsedAction(\"reopen\"),\n },\n ]\n : []),\n ],\n ...(props.onCopy ? { onCopy: () => void copyCollapsed() } : {}),\n ...(props.onMaximize ? { onMaximize: props.onMaximize } : {}),\n })}\n />\n </span>\n </div>\n {collapsedActionError && (\n <div\n role=\"alert\"\n className=\"rounded-md border border-destructive/30 bg-destructive/5 px-2.5 py-2 text-xs text-destructive\"\n >\n {collapsedActionError}\n </div>\n )}\n </>\n );\n }\n\n return (\n <>\n <div\n data-testid=\"comment-card\"\n data-comment-kind={isReply ? \"reply\" : \"root\"}\n data-comment-id={comment.id}\n className={cn(\n \"group/comment rounded-xl bg-background px-3.5 py-3 text-xs\",\n !isReply &&\n \"border border-border/80 shadow-sm transition-shadow hover:shadow-md\",\n compact && \"px-2.5 py-2.5\",\n isReply && \"ml-4 border-l-2 border-l-border bg-muted/20 shadow-none\",\n )}\n >\n {body}\n </div>\n </>\n );\n}\n"],"names":["UiTrash","UiCopy","UiFullscreen","useState","parseTimestamp","statusForCommentStage","resolveCommentStage","UiCheck","UiLock","UiRestart","jsxs","jsx","CommentAuthorAvatar","authorDisplayName","StatusChip","RatingChip","ReviewDecisionChip","FacetBadges","DropdownMenu","Icon","UiDotsVertical","CommentMarkdown","ChecklistChips","RefChips","Fragment","cn","truncatePlain"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"CommentCard.d.ts","sourceRoot":"","sources":["../../src/comments/CommentCard.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AA+BjD,OAAO,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAE9D,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,aAAa,CAAC;IACtB,uCAAuC;IACvC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,sCAAsC;IACtC,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,yEAAyE;IACzE,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,SAAS,CAAC;IACzC,iDAAiD;IACjD,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1D,qCAAqC;IACrC,OAAO,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,2BAA2B;IAC3B,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,yEAAyE;IACzE,MAAM,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpC,qCAAqC;IACrC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,gEAAgE;IAChE,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;CACzB,CAAC;AAsMF;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,+BA6KlD"}
1
+ {"version":3,"file":"CommentCard.d.ts","sourceRoot":"","sources":["../../src/comments/CommentCard.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAgCjD,OAAO,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAE9D,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,aAAa,CAAC;IACtB,uCAAuC;IACvC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,sCAAsC;IACtC,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,yEAAyE;IACzE,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,SAAS,CAAC;IACzC,iDAAiD;IACjD,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1D,qCAAqC;IACrC,OAAO,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,2BAA2B;IAC3B,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,yEAAyE;IACzE,MAAM,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpC,qCAAqC;IACrC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,gEAAgE;IAChE,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;CACzB,CAAC;AAuMF;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,+BAgLlD"}
@@ -5,7 +5,7 @@ import { Icon } from "../data/Icon.js";
5
5
  import { DropdownMenu } from "../overlay/DropdownMenu.js";
6
6
  import { parseTimestamp, formatRelativeTime } from "../data/cells/timestamp-format.js";
7
7
  import { CommentAuthorAvatar } from "./CommentAuthor.js";
8
- import { StatusChip, RatingChip, FacetBadges, ChecklistChips, RefChips } from "./CommentCardParts.js";
8
+ import { StatusChip, RatingChip, ReviewDecisionChip, FacetBadges, ChecklistChips, RefChips } from "./CommentCardParts.js";
9
9
  import { CommentMarkdown } from "./CommentMarkdown.js";
10
10
  import { authorDisplayName, truncatePlain } from "./comment-utils.js";
11
11
  import { resolveCommentStage, statusForCommentStage } from "../lib/comment-stage.js";
@@ -129,6 +129,7 @@ function CommentBody({
129
129
  !isReply && /* @__PURE__ */ jsxs("div", { className: "mt-1 flex flex-wrap gap-1", children: [
130
130
  /* @__PURE__ */ jsx(StatusChip, { comment, config }),
131
131
  /* @__PURE__ */ jsx(RatingChip, { rating: comment.rating }),
132
+ /* @__PURE__ */ jsx(ReviewDecisionChip, { decision: comment.reviewDecision }),
132
133
  /* @__PURE__ */ jsx(FacetBadges, { comment, config })
133
134
  ] })
134
135
  ] }),
@@ -243,9 +244,10 @@ function CommentCard(props) {
243
244
  !isReply && /* @__PURE__ */ jsxs(Fragment, { children: [
244
245
  /* @__PURE__ */ jsx(StatusChip, { comment, config }),
245
246
  /* @__PURE__ */ jsx(RatingChip, { rating: comment.rating }),
247
+ /* @__PURE__ */ jsx(ReviewDecisionChip, { decision: comment.reviewDecision }),
246
248
  /* @__PURE__ */ jsx(FacetBadges, { comment, config, compact: true })
247
249
  ] }),
248
- /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate text-[12px] text-foreground/80", children: comment.body.trim() ? truncatePlain(comment.body) : comment.rating === "positive" ? "Positive rating" : comment.rating === "negative" ? "Negative rating" : "Empty comment" }),
250
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate text-[12px] text-foreground/80", children: comment.body.trim() ? truncatePlain(comment.body) : comment.rating === "positive" ? "Positive rating" : comment.rating === "negative" ? "Negative rating" : comment.reviewDecision === "approved" ? "Approved" : "Empty comment" }),
249
251
  /* @__PURE__ */ jsx(
250
252
  "span",
251
253
  {
@@ -1 +1 @@
1
- {"version":3,"file":"CommentCard.js","sources":["../../src/comments/CommentCard.tsx"],"sourcesContent":["import { useState, type ReactNode } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { Icon } from \"../data/Icon\";\nimport { DropdownMenu, type DropdownMenuItem } from \"../overlay/DropdownMenu\";\nimport {\n parseTimestamp,\n formatRelativeTime,\n} from \"../data/cells/timestamp-format\";\nimport {\n UiCheck,\n UiCopy,\n UiDotsVertical,\n UiFullscreen,\n UiLock,\n UiRestart,\n UiTrash,\n} from \"../icons\";\nimport { CommentAuthorAvatar } from \"./CommentAuthor\";\nimport {\n ChecklistChips,\n FacetBadges,\n RatingChip,\n RefChips,\n StatusChip,\n} from \"./CommentCardParts\";\nimport { CommentMarkdown } from \"./CommentMarkdown\";\nimport { authorDisplayName, truncatePlain } from \"./comment-utils\";\nimport {\n resolveCommentStage,\n statusForCommentStage,\n} from \"../lib/comment-stage\";\nimport type { Comment, CommentConfig } from \"./comment-types\";\n\nexport type CommentCardProps = {\n comment: Comment;\n config: CommentConfig;\n /** Tighter padding for dense rails. */\n compact?: boolean;\n /** Render expanded on first mount. */\n defaultExpanded?: boolean;\n /** Custom body renderer; defaults to the lightweight CommentMarkdown. */\n renderBody?: (body: string) => ReactNode;\n /** Change this comment's status (roots only). */\n onUpdateStatus?: (status: string) => void | Promise<void>;\n /** Close a resolved root comment. */\n onClose?: () => void | Promise<void>;\n /** Delete this comment. */\n onDelete?: () => void;\n /** Copy this comment's whole thread in the caller's canonical format. */\n onCopy?: () => void | Promise<void>;\n /** Begin a reply to this comment. */\n onReply?: () => void;\n /** Advance the checklist item at `index` to its next status. */\n onChecklistToggle?: (index: number) => void;\n /**\n * Open this card's thread in a larger view. Owned by the caller because a\n * card knows only itself, while maximizing shows the root and its replies.\n * Omit to drop the action (e.g. inside an already-maximized thread).\n */\n onMaximize?: () => void;\n};\n\nfunction actionMenuItems(\n isReply: boolean,\n opts: {\n onDelete?: () => void;\n statusActions?: DropdownMenuItem[];\n onCopy?: () => void;\n onMaximize?: () => void;\n },\n): DropdownMenuItem[] {\n const items: DropdownMenuItem[] = [];\n if (opts.onDelete) {\n items.push({ label: \"Delete\", icon: UiTrash, onSelect: opts.onDelete });\n }\n if (!isReply) items.push(...(opts.statusActions ?? []));\n if (opts.onCopy) {\n items.push({ label: \"Copy\", icon: UiCopy, onSelect: opts.onCopy });\n }\n if (opts.onMaximize) {\n items.push({\n label: \"Maximise\",\n icon: UiFullscreen,\n onSelect: opts.onMaximize,\n });\n }\n return items;\n}\n\nfunction CommentBody({\n comment,\n config,\n renderBody,\n onUpdateStatus,\n onClose,\n onDelete,\n onCopy,\n onReply,\n onChecklistToggle,\n onMaximize,\n}: CommentCardProps) {\n const [actionError, setActionError] = useState(\"\");\n const isReply = Boolean(comment.parentId);\n const date = parseTimestamp(comment.createdAt);\n const resolved = statusForCommentStage(config, \"resolved\");\n const active = statusForCommentStage(config, \"active\");\n const closed = statusForCommentStage(config, \"closed\");\n const stage = resolveCommentStage(config, comment.status);\n const updateStatus = async (status: string) => {\n setActionError(\"\");\n try {\n await onUpdateStatus?.(status);\n } catch (error) {\n setActionError(\n `Couldn't update comment: ${error instanceof Error ? error.message : \"Unexpected error\"}`,\n );\n }\n };\n const close = async () => {\n setActionError(\"\");\n try {\n await onClose?.();\n } catch (error) {\n setActionError(\n `Couldn't close comment: ${error instanceof Error ? error.message : \"Unexpected error\"}`,\n );\n }\n };\n const copy = async () => {\n setActionError(\"\");\n try {\n await onCopy?.();\n } catch (error) {\n setActionError(\n `Couldn't copy comment: ${error instanceof Error ? error.message : \"Unexpected error\"}`,\n );\n }\n };\n const menuItems = actionMenuItems(isReply, {\n ...(onDelete ? { onDelete } : {}),\n statusActions: [\n ...(stage === \"active\" && onUpdateStatus && resolved\n ? [\n {\n label: \"Resolve\",\n icon: UiCheck,\n onSelect: () => void updateStatus(resolved.value),\n },\n ]\n : []),\n ...(stage === \"resolved\" && onClose && closed\n ? [\n {\n label: \"Close\",\n icon: UiLock,\n onSelect: () => void close(),\n },\n ]\n : []),\n ...((stage === \"resolved\" || stage === \"closed\") &&\n onUpdateStatus &&\n active\n ? [\n {\n label: \"Reopen\",\n icon: UiRestart,\n onSelect: () => void updateStatus(active.value),\n },\n ]\n : []),\n ],\n ...(onCopy ? { onCopy: () => void copy() } : {}),\n ...(onMaximize ? { onMaximize } : {}),\n });\n\n return (\n <div className=\"space-y-2.5\">\n <div className=\"flex items-start gap-2.5\">\n <CommentAuthorAvatar author={comment.author} />\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex min-w-0 items-baseline gap-1.5\">\n <span className=\"truncate text-xs font-semibold text-foreground\">\n {authorDisplayName(comment.author)}\n </span>\n {date && (\n <span\n title={date.toLocaleString()}\n className=\"shrink-0 text-[10px] text-muted-foreground\"\n >\n {formatRelativeTime(date)}\n </span>\n )}\n </div>\n {!isReply && (\n <div className=\"mt-1 flex flex-wrap gap-1\">\n <StatusChip comment={comment} config={config} />\n <RatingChip rating={comment.rating} />\n <FacetBadges comment={comment} config={config} />\n </div>\n )}\n </div>\n <div className=\"flex shrink-0 items-center gap-0.5\">\n {menuItems.length > 0 && (\n <DropdownMenu\n align=\"right\"\n menuClassName=\"min-w-[150px]\"\n trigger={\n <span\n role=\"button\"\n tabIndex={0}\n aria-label=\"Comment actions\"\n className=\"inline-flex rounded-full p-1.5 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground\"\n >\n <Icon icon={UiDotsVertical} className=\"text-sm\" />\n </span>\n }\n items={menuItems}\n />\n )}\n </div>\n </div>\n {comment.body.trim() && (\n <div className=\"text-[13px] leading-5 text-foreground\">\n {renderBody ? (\n renderBody(comment.body)\n ) : (\n <CommentMarkdown text={comment.body} />\n )}\n </div>\n )}\n {actionError && (\n <div\n role=\"alert\"\n className=\"rounded-md border border-destructive/30 bg-destructive/5 px-2.5 py-2 text-xs text-destructive\"\n >\n {actionError}\n </div>\n )}\n {!isReply && (\n <ChecklistChips\n comment={comment}\n {...(onChecklistToggle ? { onChecklistToggle } : {})}\n />\n )}\n {!isReply && <RefChips comment={comment} />}\n {onReply && (\n <button\n type=\"button\"\n onClick={onReply}\n className=\"-ml-2 rounded px-2 py-1 text-xs font-medium text-primary transition-colors hover:bg-primary/10\"\n >\n Reply\n </button>\n )}\n </div>\n );\n}\n\n/**\n * A single comment, collapsible between a compact one-line preview and a full\n * card. Offers a Maximise action when `onMaximize` is supplied — the owner\n * enlarges the whole thread. Fully controlled — all mutations are delegated to\n * the supplied callbacks.\n */\nexport function CommentCard(props: CommentCardProps) {\n const { comment, config, compact, defaultExpanded } = props;\n const [expanded, setExpanded] = useState(defaultExpanded ?? false);\n const [collapsedActionError, setCollapsedActionError] = useState(\"\");\n const isReply = Boolean(comment.parentId);\n const body = <CommentBody {...props} />;\n\n async function runCollapsedAction(action: \"resolve\" | \"close\" | \"reopen\") {\n setCollapsedActionError(\"\");\n try {\n if (action === \"close\") {\n await props.onClose?.();\n return;\n }\n const next = statusForCommentStage(\n config,\n action === \"resolve\" ? \"resolved\" : \"active\",\n );\n if (next) await props.onUpdateStatus?.(next.value);\n } catch (error) {\n setCollapsedActionError(\n `${action === \"close\" ? \"Couldn't close comment\" : \"Couldn't update comment\"}: ${error instanceof Error ? error.message : \"Unexpected error\"}`,\n );\n }\n }\n\n async function copyCollapsed() {\n setCollapsedActionError(\"\");\n try {\n await props.onCopy?.();\n } catch (error) {\n setCollapsedActionError(\n `Couldn't copy comment: ${error instanceof Error ? error.message : \"Unexpected error\"}`,\n );\n }\n }\n\n if (!expanded) {\n return (\n <>\n <div\n role=\"button\"\n tabIndex={0}\n onClick={() => setExpanded(true)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n setExpanded(true);\n }\n }}\n data-testid=\"comment-card\"\n data-comment-kind={isReply ? \"reply\" : \"root\"}\n data-comment-id={comment.id}\n className={cn(\n \"group/comment flex cursor-pointer items-center gap-2 rounded-lg px-2.5 py-1.5 text-xs transition-colors hover:bg-muted/50\",\n !isReply && \"border border-border bg-background shadow-sm\",\n isReply && \"ml-4 border-l-2 border-l-border bg-muted/30\",\n )}\n >\n <CommentAuthorAvatar author={comment.author} bare />\n <span className=\"shrink-0 text-[11px] font-semibold text-foreground\">\n {authorDisplayName(comment.author)}\n </span>\n {!isReply && (\n <>\n <StatusChip comment={comment} config={config} />\n <RatingChip rating={comment.rating} />\n <FacetBadges comment={comment} config={config} compact />\n </>\n )}\n <span className=\"min-w-0 flex-1 truncate text-[12px] text-foreground/80\">\n {comment.body.trim()\n ? truncatePlain(comment.body)\n : comment.rating === \"positive\"\n ? \"Positive rating\"\n : comment.rating === \"negative\"\n ? \"Negative rating\"\n : \"Empty comment\"}\n </span>\n <span\n role=\"presentation\"\n onClick={(e) => e.stopPropagation()}\n onKeyDown={(e) => e.stopPropagation()}\n >\n <DropdownMenu\n align=\"right\"\n trigger={\n <span\n role=\"button\"\n tabIndex={0}\n aria-label=\"Comment actions\"\n className=\"rounded p-0.5 text-muted-foreground opacity-0 transition-opacity hover:bg-muted hover:opacity-100 group-hover/comment:opacity-70\"\n >\n <Icon icon={UiDotsVertical} className=\"text-sm\" />\n </span>\n }\n items={actionMenuItems(isReply, {\n ...(props.onDelete ? { onDelete: props.onDelete } : {}),\n statusActions: [\n ...(resolveCommentStage(config, comment.status) ===\n \"active\" &&\n props.onUpdateStatus &&\n statusForCommentStage(config, \"resolved\")\n ? [\n {\n label: \"Resolve\",\n icon: UiCheck,\n onSelect: () => void runCollapsedAction(\"resolve\"),\n },\n ]\n : []),\n ...(resolveCommentStage(config, comment.status) ===\n \"resolved\" &&\n props.onClose &&\n statusForCommentStage(config, \"closed\")\n ? [\n {\n label: \"Close\",\n icon: UiLock,\n onSelect: () => void runCollapsedAction(\"close\"),\n },\n ]\n : []),\n ...((resolveCommentStage(config, comment.status) ===\n \"resolved\" ||\n resolveCommentStage(config, comment.status) === \"closed\") &&\n props.onUpdateStatus &&\n statusForCommentStage(config, \"active\")\n ? [\n {\n label: \"Reopen\",\n icon: UiRestart,\n onSelect: () => void runCollapsedAction(\"reopen\"),\n },\n ]\n : []),\n ],\n ...(props.onCopy ? { onCopy: () => void copyCollapsed() } : {}),\n ...(props.onMaximize ? { onMaximize: props.onMaximize } : {}),\n })}\n />\n </span>\n </div>\n {collapsedActionError && (\n <div\n role=\"alert\"\n className=\"rounded-md border border-destructive/30 bg-destructive/5 px-2.5 py-2 text-xs text-destructive\"\n >\n {collapsedActionError}\n </div>\n )}\n </>\n );\n }\n\n return (\n <>\n <div\n data-testid=\"comment-card\"\n data-comment-kind={isReply ? \"reply\" : \"root\"}\n data-comment-id={comment.id}\n className={cn(\n \"group/comment rounded-xl bg-background px-3.5 py-3 text-xs\",\n !isReply &&\n \"border border-border/80 shadow-sm transition-shadow hover:shadow-md\",\n compact && \"px-2.5 py-2.5\",\n isReply && \"ml-4 border-l-2 border-l-border bg-muted/20 shadow-none\",\n )}\n >\n {body}\n </div>\n </>\n );\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;AA8DA,SAAS,gBACP,SACA,MAMoB;AACpB,QAAM,QAA4B,CAAA;AAClC,MAAI,KAAK,UAAU;AACjB,UAAM,KAAK,EAAE,OAAO,UAAU,MAAM,SAAS,UAAU,KAAK,UAAU;AAAA,EACxE;AACA,MAAI,CAAC,QAAS,OAAM,KAAK,GAAI,KAAK,iBAAiB,EAAG;AACtD,MAAI,KAAK,QAAQ;AACf,UAAM,KAAK,EAAE,OAAO,QAAQ,MAAM,QAAQ,UAAU,KAAK,QAAQ;AAAA,EACnE;AACA,MAAI,KAAK,YAAY;AACnB,UAAM,KAAK;AAAA,MACT,OAAO;AAAA,MACP,MAAM;AAAA,MACN,UAAU,KAAK;AAAA,IAAA,CAChB;AAAA,EACH;AACA,SAAO;AACT;AAEA,SAAS,YAAY;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAqB;AACnB,QAAM,CAAC,aAAa,cAAc,IAAI,SAAS,EAAE;AACjD,QAAM,UAAU,QAAQ,QAAQ,QAAQ;AACxC,QAAM,OAAO,eAAe,QAAQ,SAAS;AAC7C,QAAM,WAAW,sBAAsB,QAAQ,UAAU;AACzD,QAAM,SAAS,sBAAsB,QAAQ,QAAQ;AACrD,QAAM,SAAS,sBAAsB,QAAQ,QAAQ;AACrD,QAAM,QAAQ,oBAAoB,QAAQ,QAAQ,MAAM;AACxD,QAAM,eAAe,OAAO,WAAmB;AAC7C,mBAAe,EAAE;AACjB,QAAI;AACF,aAAM,iDAAiB;AAAA,IACzB,SAAS,OAAO;AACd;AAAA,QACE,4BAA4B,iBAAiB,QAAQ,MAAM,UAAU,kBAAkB;AAAA,MAAA;AAAA,IAE3F;AAAA,EACF;AACA,QAAM,QAAQ,YAAY;AACxB,mBAAe,EAAE;AACjB,QAAI;AACF,aAAM;AAAA,IACR,SAAS,OAAO;AACd;AAAA,QACE,2BAA2B,iBAAiB,QAAQ,MAAM,UAAU,kBAAkB;AAAA,MAAA;AAAA,IAE1F;AAAA,EACF;AACA,QAAM,OAAO,YAAY;AACvB,mBAAe,EAAE;AACjB,QAAI;AACF,aAAM;AAAA,IACR,SAAS,OAAO;AACd;AAAA,QACE,0BAA0B,iBAAiB,QAAQ,MAAM,UAAU,kBAAkB;AAAA,MAAA;AAAA,IAEzF;AAAA,EACF;AACA,QAAM,YAAY,gBAAgB,SAAS;AAAA,IACzC,GAAI,WAAW,EAAE,SAAA,IAAa,CAAA;AAAA,IAC9B,eAAe;AAAA,MACb,GAAI,UAAU,YAAY,kBAAkB,WACxC;AAAA,QACE;AAAA,UACE,OAAO;AAAA,UACP,MAAM;AAAA,UACN,UAAU,MAAM,KAAK,aAAa,SAAS,KAAK;AAAA,QAAA;AAAA,MAClD,IAEF,CAAA;AAAA,MACJ,GAAI,UAAU,cAAc,WAAW,SACnC;AAAA,QACE;AAAA,UACE,OAAO;AAAA,UACP,MAAM;AAAA,UACN,UAAU,MAAM,KAAK,MAAA;AAAA,QAAM;AAAA,MAC7B,IAEF,CAAA;AAAA,MACJ,IAAK,UAAU,cAAc,UAAU,aACvC,kBACA,SACI;AAAA,QACE;AAAA,UACE,OAAO;AAAA,UACP,MAAM;AAAA,UACN,UAAU,MAAM,KAAK,aAAa,OAAO,KAAK;AAAA,QAAA;AAAA,MAChD,IAEF,CAAA;AAAA,IAAC;AAAA,IAEP,GAAI,SAAS,EAAE,QAAQ,MAAM,KAAK,KAAA,EAAK,IAAM,CAAA;AAAA,IAC7C,GAAI,aAAa,EAAE,eAAe,CAAA;AAAA,EAAC,CACpC;AAED,SACE,qBAAC,OAAA,EAAI,WAAU,eACb,UAAA;AAAA,IAAA,qBAAC,OAAA,EAAI,WAAU,4BACb,UAAA;AAAA,MAAA,oBAAC,qBAAA,EAAoB,QAAQ,QAAQ,OAAA,CAAQ;AAAA,MAC7C,qBAAC,OAAA,EAAI,WAAU,kBACb,UAAA;AAAA,QAAA,qBAAC,OAAA,EAAI,WAAU,uCACb,UAAA;AAAA,UAAA,oBAAC,UAAK,WAAU,kDACb,UAAA,kBAAkB,QAAQ,MAAM,GACnC;AAAA,UACC,QACC;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,OAAO,KAAK,eAAA;AAAA,cACZ,WAAU;AAAA,cAET,6BAAmB,IAAI;AAAA,YAAA;AAAA,UAAA;AAAA,QAC1B,GAEJ;AAAA,QACC,CAAC,WACA,qBAAC,OAAA,EAAI,WAAU,6BACb,UAAA;AAAA,UAAA,oBAAC,YAAA,EAAW,SAAkB,OAAA,CAAgB;AAAA,UAC9C,oBAAC,YAAA,EAAW,QAAQ,QAAQ,OAAA,CAAQ;AAAA,UACpC,oBAAC,aAAA,EAAY,SAAkB,OAAA,CAAgB;AAAA,QAAA,EAAA,CACjD;AAAA,MAAA,GAEJ;AAAA,0BACC,OAAA,EAAI,WAAU,sCACZ,UAAA,UAAU,SAAS,KAClB;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,OAAM;AAAA,UACN,eAAc;AAAA,UACd,SACE;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,UAAU;AAAA,cACV,cAAW;AAAA,cACX,WAAU;AAAA,cAEV,UAAA,oBAAC,MAAA,EAAK,MAAM,gBAAgB,WAAU,UAAA,CAAU;AAAA,YAAA;AAAA,UAAA;AAAA,UAGpD,OAAO;AAAA,QAAA;AAAA,MAAA,EACT,CAEJ;AAAA,IAAA,GACF;AAAA,IACC,QAAQ,KAAK,KAAA,KACZ,oBAAC,OAAA,EAAI,WAAU,yCACZ,UAAA,aACC,WAAW,QAAQ,IAAI,IAEvB,oBAAC,mBAAgB,MAAM,QAAQ,MAAM,GAEzC;AAAA,IAED,eACC;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,WAAU;AAAA,QAET,UAAA;AAAA,MAAA;AAAA,IAAA;AAAA,IAGJ,CAAC,WACA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACC,GAAI,oBAAoB,EAAE,sBAAsB,CAAA;AAAA,MAAC;AAAA,IAAA;AAAA,IAGrD,CAAC,WAAW,oBAAC,UAAA,EAAS,QAAA,CAAkB;AAAA,IACxC,WACC;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS;AAAA,QACT,WAAU;AAAA,QACX,UAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAED,GAEJ;AAEJ;AAQO,SAAS,YAAY,OAAyB;AACnD,QAAM,EAAE,SAAS,QAAQ,SAAS,oBAAoB;AACtD,QAAM,CAAC,UAAU,WAAW,IAAI,SAAS,mBAAmB,KAAK;AACjE,QAAM,CAAC,sBAAsB,uBAAuB,IAAI,SAAS,EAAE;AACnE,QAAM,UAAU,QAAQ,QAAQ,QAAQ;AACxC,QAAM,OAAO,oBAAC,aAAA,EAAa,GAAG,MAAA,CAAO;AAErC,iBAAe,mBAAmB,QAAwC;;AACxE,4BAAwB,EAAE;AAC1B,QAAI;AACF,UAAI,WAAW,SAAS;AACtB,gBAAM,WAAM,YAAN;AACN;AAAA,MACF;AACA,YAAM,OAAO;AAAA,QACX;AAAA,QACA,WAAW,YAAY,aAAa;AAAA,MAAA;AAEtC,UAAI,KAAM,SAAM,WAAM,mBAAN,+BAAuB,KAAK;AAAA,IAC9C,SAAS,OAAO;AACd;AAAA,QACE,GAAG,WAAW,UAAU,2BAA2B,yBAAyB,KAAK,iBAAiB,QAAQ,MAAM,UAAU,kBAAkB;AAAA,MAAA;AAAA,IAEhJ;AAAA,EACF;AAEA,iBAAe,gBAAgB;;AAC7B,4BAAwB,EAAE;AAC1B,QAAI;AACF,cAAM,WAAM,WAAN;AAAA,IACR,SAAS,OAAO;AACd;AAAA,QACE,0BAA0B,iBAAiB,QAAQ,MAAM,UAAU,kBAAkB;AAAA,MAAA;AAAA,IAEzF;AAAA,EACF;AAEA,MAAI,CAAC,UAAU;AACb,WACE,qBAAA,UAAA,EACE,UAAA;AAAA,MAAA;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,MAAK;AAAA,UACL,UAAU;AAAA,UACV,SAAS,MAAM,YAAY,IAAI;AAAA,UAC/B,WAAW,CAAC,MAAM;AAChB,gBAAI,EAAE,QAAQ,WAAW,EAAE,QAAQ,KAAK;AACtC,gBAAE,eAAA;AACF,0BAAY,IAAI;AAAA,YAClB;AAAA,UACF;AAAA,UACA,eAAY;AAAA,UACZ,qBAAmB,UAAU,UAAU;AAAA,UACvC,mBAAiB,QAAQ;AAAA,UACzB,WAAW;AAAA,YACT;AAAA,YACA,CAAC,WAAW;AAAA,YACZ,WAAW;AAAA,UAAA;AAAA,UAGb,UAAA;AAAA,YAAA,oBAAC,qBAAA,EAAoB,QAAQ,QAAQ,QAAQ,MAAI,MAAC;AAAA,gCACjD,QAAA,EAAK,WAAU,sDACb,UAAA,kBAAkB,QAAQ,MAAM,GACnC;AAAA,YACC,CAAC,WACA,qBAAA,UAAA,EACE,UAAA;AAAA,cAAA,oBAAC,YAAA,EAAW,SAAkB,OAAA,CAAgB;AAAA,cAC9C,oBAAC,YAAA,EAAW,QAAQ,QAAQ,OAAA,CAAQ;AAAA,cACpC,oBAAC,aAAA,EAAY,SAAkB,QAAgB,SAAO,KAAA,CAAC;AAAA,YAAA,GACzD;AAAA,YAEF,oBAAC,UAAK,WAAU,0DACb,kBAAQ,KAAK,KAAA,IACV,cAAc,QAAQ,IAAI,IAC1B,QAAQ,WAAW,aACjB,oBACA,QAAQ,WAAW,aACjB,oBACA,iBACV;AAAA,YACA;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,MAAK;AAAA,gBACL,SAAS,CAAC,MAAM,EAAE,gBAAA;AAAA,gBAClB,WAAW,CAAC,MAAM,EAAE,gBAAA;AAAA,gBAEpB,UAAA;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,OAAM;AAAA,oBACN,SACE;AAAA,sBAAC;AAAA,sBAAA;AAAA,wBACC,MAAK;AAAA,wBACL,UAAU;AAAA,wBACV,cAAW;AAAA,wBACX,WAAU;AAAA,wBAEV,UAAA,oBAAC,MAAA,EAAK,MAAM,gBAAgB,WAAU,UAAA,CAAU;AAAA,sBAAA;AAAA,oBAAA;AAAA,oBAGpD,OAAO,gBAAgB,SAAS;AAAA,sBAC9B,GAAI,MAAM,WAAW,EAAE,UAAU,MAAM,SAAA,IAAa,CAAA;AAAA,sBACpD,eAAe;AAAA,wBACb,GAAI,oBAAoB,QAAQ,QAAQ,MAAM,MAC5C,YACF,MAAM,kBACN,sBAAsB,QAAQ,UAAU,IACpC;AAAA,0BACE;AAAA,4BACE,OAAO;AAAA,4BACP,MAAM;AAAA,4BACN,UAAU,MAAM,KAAK,mBAAmB,SAAS;AAAA,0BAAA;AAAA,wBACnD,IAEF,CAAA;AAAA,wBACJ,GAAI,oBAAoB,QAAQ,QAAQ,MAAM,MAC5C,cACF,MAAM,WACN,sBAAsB,QAAQ,QAAQ,IAClC;AAAA,0BACE;AAAA,4BACE,OAAO;AAAA,4BACP,MAAM;AAAA,4BACN,UAAU,MAAM,KAAK,mBAAmB,OAAO;AAAA,0BAAA;AAAA,wBACjD,IAEF,CAAA;AAAA,wBACJ,IAAK,oBAAoB,QAAQ,QAAQ,MAAM,MAC7C,cACA,oBAAoB,QAAQ,QAAQ,MAAM,MAAM,aAClD,MAAM,kBACN,sBAAsB,QAAQ,QAAQ,IAClC;AAAA,0BACE;AAAA,4BACE,OAAO;AAAA,4BACP,MAAM;AAAA,4BACN,UAAU,MAAM,KAAK,mBAAmB,QAAQ;AAAA,0BAAA;AAAA,wBAClD,IAEF,CAAA;AAAA,sBAAC;AAAA,sBAEP,GAAI,MAAM,SAAS,EAAE,QAAQ,MAAM,KAAK,cAAA,EAAc,IAAM,CAAA;AAAA,sBAC5D,GAAI,MAAM,aAAa,EAAE,YAAY,MAAM,WAAA,IAAe,CAAA;AAAA,oBAAC,CAC5D;AAAA,kBAAA;AAAA,gBAAA;AAAA,cACH;AAAA,YAAA;AAAA,UACF;AAAA,QAAA;AAAA,MAAA;AAAA,MAED,wBACC;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,MAAK;AAAA,UACL,WAAU;AAAA,UAET,UAAA;AAAA,QAAA;AAAA,MAAA;AAAA,IACH,GAEJ;AAAA,EAEJ;AAEA,SACE,oBAAA,UAAA,EACE,UAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,eAAY;AAAA,MACZ,qBAAmB,UAAU,UAAU;AAAA,MACvC,mBAAiB,QAAQ;AAAA,MACzB,WAAW;AAAA,QACT;AAAA,QACA,CAAC,WACC;AAAA,QACF,WAAW;AAAA,QACX,WAAW;AAAA,MAAA;AAAA,MAGZ,UAAA;AAAA,IAAA;AAAA,EAAA,GAEL;AAEJ;"}
1
+ {"version":3,"file":"CommentCard.js","sources":["../../src/comments/CommentCard.tsx"],"sourcesContent":["import { useState, type ReactNode } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { Icon } from \"../data/Icon\";\nimport { DropdownMenu, type DropdownMenuItem } from \"../overlay/DropdownMenu\";\nimport {\n parseTimestamp,\n formatRelativeTime,\n} from \"../data/cells/timestamp-format\";\nimport {\n UiCheck,\n UiCopy,\n UiDotsVertical,\n UiFullscreen,\n UiLock,\n UiRestart,\n UiTrash,\n} from \"../icons\";\nimport { CommentAuthorAvatar } from \"./CommentAuthor\";\nimport {\n ChecklistChips,\n FacetBadges,\n RatingChip,\n ReviewDecisionChip,\n RefChips,\n StatusChip,\n} from \"./CommentCardParts\";\nimport { CommentMarkdown } from \"./CommentMarkdown\";\nimport { authorDisplayName, truncatePlain } from \"./comment-utils\";\nimport {\n resolveCommentStage,\n statusForCommentStage,\n} from \"../lib/comment-stage\";\nimport type { Comment, CommentConfig } from \"./comment-types\";\n\nexport type CommentCardProps = {\n comment: Comment;\n config: CommentConfig;\n /** Tighter padding for dense rails. */\n compact?: boolean;\n /** Render expanded on first mount. */\n defaultExpanded?: boolean;\n /** Custom body renderer; defaults to the lightweight CommentMarkdown. */\n renderBody?: (body: string) => ReactNode;\n /** Change this comment's status (roots only). */\n onUpdateStatus?: (status: string) => void | Promise<void>;\n /** Close a resolved root comment. */\n onClose?: () => void | Promise<void>;\n /** Delete this comment. */\n onDelete?: () => void;\n /** Copy this comment's whole thread in the caller's canonical format. */\n onCopy?: () => void | Promise<void>;\n /** Begin a reply to this comment. */\n onReply?: () => void;\n /** Advance the checklist item at `index` to its next status. */\n onChecklistToggle?: (index: number) => void;\n /**\n * Open this card's thread in a larger view. Owned by the caller because a\n * card knows only itself, while maximizing shows the root and its replies.\n * Omit to drop the action (e.g. inside an already-maximized thread).\n */\n onMaximize?: () => void;\n};\n\nfunction actionMenuItems(\n isReply: boolean,\n opts: {\n onDelete?: () => void;\n statusActions?: DropdownMenuItem[];\n onCopy?: () => void;\n onMaximize?: () => void;\n },\n): DropdownMenuItem[] {\n const items: DropdownMenuItem[] = [];\n if (opts.onDelete) {\n items.push({ label: \"Delete\", icon: UiTrash, onSelect: opts.onDelete });\n }\n if (!isReply) items.push(...(opts.statusActions ?? []));\n if (opts.onCopy) {\n items.push({ label: \"Copy\", icon: UiCopy, onSelect: opts.onCopy });\n }\n if (opts.onMaximize) {\n items.push({\n label: \"Maximise\",\n icon: UiFullscreen,\n onSelect: opts.onMaximize,\n });\n }\n return items;\n}\n\nfunction CommentBody({\n comment,\n config,\n renderBody,\n onUpdateStatus,\n onClose,\n onDelete,\n onCopy,\n onReply,\n onChecklistToggle,\n onMaximize,\n}: CommentCardProps) {\n const [actionError, setActionError] = useState(\"\");\n const isReply = Boolean(comment.parentId);\n const date = parseTimestamp(comment.createdAt);\n const resolved = statusForCommentStage(config, \"resolved\");\n const active = statusForCommentStage(config, \"active\");\n const closed = statusForCommentStage(config, \"closed\");\n const stage = resolveCommentStage(config, comment.status);\n const updateStatus = async (status: string) => {\n setActionError(\"\");\n try {\n await onUpdateStatus?.(status);\n } catch (error) {\n setActionError(\n `Couldn't update comment: ${error instanceof Error ? error.message : \"Unexpected error\"}`,\n );\n }\n };\n const close = async () => {\n setActionError(\"\");\n try {\n await onClose?.();\n } catch (error) {\n setActionError(\n `Couldn't close comment: ${error instanceof Error ? error.message : \"Unexpected error\"}`,\n );\n }\n };\n const copy = async () => {\n setActionError(\"\");\n try {\n await onCopy?.();\n } catch (error) {\n setActionError(\n `Couldn't copy comment: ${error instanceof Error ? error.message : \"Unexpected error\"}`,\n );\n }\n };\n const menuItems = actionMenuItems(isReply, {\n ...(onDelete ? { onDelete } : {}),\n statusActions: [\n ...(stage === \"active\" && onUpdateStatus && resolved\n ? [\n {\n label: \"Resolve\",\n icon: UiCheck,\n onSelect: () => void updateStatus(resolved.value),\n },\n ]\n : []),\n ...(stage === \"resolved\" && onClose && closed\n ? [\n {\n label: \"Close\",\n icon: UiLock,\n onSelect: () => void close(),\n },\n ]\n : []),\n ...((stage === \"resolved\" || stage === \"closed\") &&\n onUpdateStatus &&\n active\n ? [\n {\n label: \"Reopen\",\n icon: UiRestart,\n onSelect: () => void updateStatus(active.value),\n },\n ]\n : []),\n ],\n ...(onCopy ? { onCopy: () => void copy() } : {}),\n ...(onMaximize ? { onMaximize } : {}),\n });\n\n return (\n <div className=\"space-y-2.5\">\n <div className=\"flex items-start gap-2.5\">\n <CommentAuthorAvatar author={comment.author} />\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex min-w-0 items-baseline gap-1.5\">\n <span className=\"truncate text-xs font-semibold text-foreground\">\n {authorDisplayName(comment.author)}\n </span>\n {date && (\n <span\n title={date.toLocaleString()}\n className=\"shrink-0 text-[10px] text-muted-foreground\"\n >\n {formatRelativeTime(date)}\n </span>\n )}\n </div>\n {!isReply && (\n <div className=\"mt-1 flex flex-wrap gap-1\">\n <StatusChip comment={comment} config={config} />\n <RatingChip rating={comment.rating} />\n <ReviewDecisionChip decision={comment.reviewDecision} />\n <FacetBadges comment={comment} config={config} />\n </div>\n )}\n </div>\n <div className=\"flex shrink-0 items-center gap-0.5\">\n {menuItems.length > 0 && (\n <DropdownMenu\n align=\"right\"\n menuClassName=\"min-w-[150px]\"\n trigger={\n <span\n role=\"button\"\n tabIndex={0}\n aria-label=\"Comment actions\"\n className=\"inline-flex rounded-full p-1.5 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground\"\n >\n <Icon icon={UiDotsVertical} className=\"text-sm\" />\n </span>\n }\n items={menuItems}\n />\n )}\n </div>\n </div>\n {comment.body.trim() && (\n <div className=\"text-[13px] leading-5 text-foreground\">\n {renderBody ? (\n renderBody(comment.body)\n ) : (\n <CommentMarkdown text={comment.body} />\n )}\n </div>\n )}\n {actionError && (\n <div\n role=\"alert\"\n className=\"rounded-md border border-destructive/30 bg-destructive/5 px-2.5 py-2 text-xs text-destructive\"\n >\n {actionError}\n </div>\n )}\n {!isReply && (\n <ChecklistChips\n comment={comment}\n {...(onChecklistToggle ? { onChecklistToggle } : {})}\n />\n )}\n {!isReply && <RefChips comment={comment} />}\n {onReply && (\n <button\n type=\"button\"\n onClick={onReply}\n className=\"-ml-2 rounded px-2 py-1 text-xs font-medium text-primary transition-colors hover:bg-primary/10\"\n >\n Reply\n </button>\n )}\n </div>\n );\n}\n\n/**\n * A single comment, collapsible between a compact one-line preview and a full\n * card. Offers a Maximise action when `onMaximize` is supplied — the owner\n * enlarges the whole thread. Fully controlled — all mutations are delegated to\n * the supplied callbacks.\n */\nexport function CommentCard(props: CommentCardProps) {\n const { comment, config, compact, defaultExpanded } = props;\n const [expanded, setExpanded] = useState(defaultExpanded ?? false);\n const [collapsedActionError, setCollapsedActionError] = useState(\"\");\n const isReply = Boolean(comment.parentId);\n const body = <CommentBody {...props} />;\n\n async function runCollapsedAction(action: \"resolve\" | \"close\" | \"reopen\") {\n setCollapsedActionError(\"\");\n try {\n if (action === \"close\") {\n await props.onClose?.();\n return;\n }\n const next = statusForCommentStage(\n config,\n action === \"resolve\" ? \"resolved\" : \"active\",\n );\n if (next) await props.onUpdateStatus?.(next.value);\n } catch (error) {\n setCollapsedActionError(\n `${action === \"close\" ? \"Couldn't close comment\" : \"Couldn't update comment\"}: ${error instanceof Error ? error.message : \"Unexpected error\"}`,\n );\n }\n }\n\n async function copyCollapsed() {\n setCollapsedActionError(\"\");\n try {\n await props.onCopy?.();\n } catch (error) {\n setCollapsedActionError(\n `Couldn't copy comment: ${error instanceof Error ? error.message : \"Unexpected error\"}`,\n );\n }\n }\n\n if (!expanded) {\n return (\n <>\n <div\n role=\"button\"\n tabIndex={0}\n onClick={() => setExpanded(true)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n setExpanded(true);\n }\n }}\n data-testid=\"comment-card\"\n data-comment-kind={isReply ? \"reply\" : \"root\"}\n data-comment-id={comment.id}\n className={cn(\n \"group/comment flex cursor-pointer items-center gap-2 rounded-lg px-2.5 py-1.5 text-xs transition-colors hover:bg-muted/50\",\n !isReply && \"border border-border bg-background shadow-sm\",\n isReply && \"ml-4 border-l-2 border-l-border bg-muted/30\",\n )}\n >\n <CommentAuthorAvatar author={comment.author} bare />\n <span className=\"shrink-0 text-[11px] font-semibold text-foreground\">\n {authorDisplayName(comment.author)}\n </span>\n {!isReply && (\n <>\n <StatusChip comment={comment} config={config} />\n <RatingChip rating={comment.rating} />\n <ReviewDecisionChip decision={comment.reviewDecision} />\n <FacetBadges comment={comment} config={config} compact />\n </>\n )}\n <span className=\"min-w-0 flex-1 truncate text-[12px] text-foreground/80\">\n {comment.body.trim()\n ? truncatePlain(comment.body)\n : comment.rating === \"positive\"\n ? \"Positive rating\"\n : comment.rating === \"negative\"\n ? \"Negative rating\"\n : comment.reviewDecision === \"approved\"\n ? \"Approved\"\n : \"Empty comment\"}\n </span>\n <span\n role=\"presentation\"\n onClick={(e) => e.stopPropagation()}\n onKeyDown={(e) => e.stopPropagation()}\n >\n <DropdownMenu\n align=\"right\"\n trigger={\n <span\n role=\"button\"\n tabIndex={0}\n aria-label=\"Comment actions\"\n className=\"rounded p-0.5 text-muted-foreground opacity-0 transition-opacity hover:bg-muted hover:opacity-100 group-hover/comment:opacity-70\"\n >\n <Icon icon={UiDotsVertical} className=\"text-sm\" />\n </span>\n }\n items={actionMenuItems(isReply, {\n ...(props.onDelete ? { onDelete: props.onDelete } : {}),\n statusActions: [\n ...(resolveCommentStage(config, comment.status) ===\n \"active\" &&\n props.onUpdateStatus &&\n statusForCommentStage(config, \"resolved\")\n ? [\n {\n label: \"Resolve\",\n icon: UiCheck,\n onSelect: () => void runCollapsedAction(\"resolve\"),\n },\n ]\n : []),\n ...(resolveCommentStage(config, comment.status) ===\n \"resolved\" &&\n props.onClose &&\n statusForCommentStage(config, \"closed\")\n ? [\n {\n label: \"Close\",\n icon: UiLock,\n onSelect: () => void runCollapsedAction(\"close\"),\n },\n ]\n : []),\n ...((resolveCommentStage(config, comment.status) ===\n \"resolved\" ||\n resolveCommentStage(config, comment.status) === \"closed\") &&\n props.onUpdateStatus &&\n statusForCommentStage(config, \"active\")\n ? [\n {\n label: \"Reopen\",\n icon: UiRestart,\n onSelect: () => void runCollapsedAction(\"reopen\"),\n },\n ]\n : []),\n ],\n ...(props.onCopy ? { onCopy: () => void copyCollapsed() } : {}),\n ...(props.onMaximize ? { onMaximize: props.onMaximize } : {}),\n })}\n />\n </span>\n </div>\n {collapsedActionError && (\n <div\n role=\"alert\"\n className=\"rounded-md border border-destructive/30 bg-destructive/5 px-2.5 py-2 text-xs text-destructive\"\n >\n {collapsedActionError}\n </div>\n )}\n </>\n );\n }\n\n return (\n <>\n <div\n data-testid=\"comment-card\"\n data-comment-kind={isReply ? \"reply\" : \"root\"}\n data-comment-id={comment.id}\n className={cn(\n \"group/comment rounded-xl bg-background px-3.5 py-3 text-xs\",\n !isReply &&\n \"border border-border/80 shadow-sm transition-shadow hover:shadow-md\",\n compact && \"px-2.5 py-2.5\",\n isReply && \"ml-4 border-l-2 border-l-border bg-muted/20 shadow-none\",\n )}\n >\n {body}\n </div>\n </>\n );\n}\n"],"names":[],"mappings":"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"}
@@ -7,6 +7,21 @@ const commentUtils = require("./comment-utils.cjs");
7
7
  const commentStage = require("../lib/comment-stage.cjs");
8
8
  const UiThumbsUp = require("../icons/components/UiThumbsUp.cjs");
9
9
  const UiThumbsDown = require("../icons/components/UiThumbsDown.cjs");
10
+ function ReviewDecisionChip({
11
+ decision
12
+ }) {
13
+ if (!decision) return null;
14
+ const label = decision === "approved" ? "Approved" : decision === "rejected" ? "Rejected" : "Revision requested";
15
+ return /* @__PURE__ */ jsxRuntime.jsx(
16
+ Badge.Badge,
17
+ {
18
+ variant: "soft",
19
+ tone: decision === "approved" ? "success" : decision === "rejected" ? "danger" : "warning",
20
+ size: "xs",
21
+ children: label
22
+ }
23
+ );
24
+ }
10
25
  function RatingChip({ rating }) {
11
26
  if (!rating) return null;
12
27
  const positive = rating === "positive";
@@ -112,5 +127,6 @@ exports.ChecklistChips = ChecklistChips;
112
127
  exports.FacetBadges = FacetBadges;
113
128
  exports.RatingChip = RatingChip;
114
129
  exports.RefChips = RefChips;
130
+ exports.ReviewDecisionChip = ReviewDecisionChip;
115
131
  exports.StatusChip = StatusChip;
116
132
  //# sourceMappingURL=CommentCardParts.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"CommentCardParts.cjs","sources":["../../src/comments/CommentCardParts.tsx"],"sourcesContent":["import { Badge } from \"../data/Badge\";\nimport { cn } from \"../lib/utils\";\nimport { UiThumbsDown, UiThumbsUp } from \"../icons\";\nimport {\n resolveFacetOption,\n resolveStatusConfig,\n toneToBadgeTone,\n} from \"./comment-utils\";\nimport { resolveCommentStage } from \"../lib/comment-stage\";\nimport type { Comment, CommentConfig, CommentRating } from \"./comment-types\";\n\nexport function RatingChip({ rating }: { rating: CommentRating | undefined }) {\n if (!rating) return null;\n const positive = rating === \"positive\";\n return (\n <Badge\n variant=\"soft\"\n tone={positive ? \"success\" : \"danger\"}\n size=\"xs\"\n icon={positive ? UiThumbsUp : UiThumbsDown}\n >\n {positive ? \"Positive rating\" : \"Negative rating\"}\n </Badge>\n );\n}\n\nexport function StatusChip({\n comment,\n config,\n}: {\n comment: Comment;\n config: CommentConfig;\n}) {\n const status = resolveStatusConfig(config, comment.status);\n if (!status) return null;\n const closedBy =\n resolveCommentStage(config, comment.status) === \"closed\"\n ? comment.closedBy\n : undefined;\n return (\n <Badge\n variant=\"soft\"\n tone={toneToBadgeTone(status.tone)}\n size=\"xs\"\n {...(status.icon ? { icon: status.icon } : {})}\n {...(comment.closedAt\n ? { title: new Date(comment.closedAt).toLocaleString() }\n : {})}\n >\n {closedBy ? `Closed by ${closedBy.name}` : status.label}\n </Badge>\n );\n}\n\nexport function FacetBadges({\n comment,\n config,\n compact,\n}: {\n comment: Comment;\n config: CommentConfig;\n compact?: boolean;\n}) {\n const chips = (config.facets ?? []).flatMap((facet) => {\n const option = resolveFacetOption(facet, comment.facets?.[facet.key]);\n if (!option) return [];\n return [\n <Badge\n key={facet.key}\n variant=\"soft\"\n tone={toneToBadgeTone(option.tone)}\n size=\"xs\"\n >\n {compact ? (option.short ?? option.label) : option.label}\n </Badge>,\n ];\n });\n return chips.length > 0 ? <>{chips}</> : null;\n}\n\nexport function ChecklistChips({\n comment,\n onChecklistToggle,\n}: {\n comment: Comment;\n onChecklistToggle?: (index: number) => void;\n}) {\n if (!comment.checklist?.length) return null;\n return (\n <div className=\"flex flex-wrap gap-1\">\n {comment.checklist.map((item, index) => {\n const done = /done|complete|resolved/i.test(item.status);\n const active = /progress|doing/i.test(item.status);\n return (\n <button\n key={index}\n type=\"button\"\n onClick={() => onChecklistToggle?.(index)}\n disabled={!onChecklistToggle}\n className={cn(\n \"inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-[10px] transition-opacity\",\n onChecklistToggle && \"cursor-pointer hover:opacity-80\",\n done\n ? \"bg-green-100 text-green-800 line-through dark:bg-green-500/20 dark:text-green-300\"\n : active\n ? \"bg-yellow-100 text-yellow-800 dark:bg-yellow-500/20 dark:text-yellow-300\"\n : \"bg-muted text-muted-foreground\",\n )}\n >\n {item.label}\n </button>\n );\n })}\n </div>\n );\n}\n\nexport function RefChips({ comment }: { comment: Comment }) {\n if (!comment.refs?.length) return null;\n return (\n <div className=\"flex flex-wrap gap-1.5\">\n {comment.refs.map((group, index) => (\n <span\n key={index}\n className=\"inline-flex items-center gap-1 rounded bg-muted px-1.5 py-0.5 text-[10px] text-muted-foreground\"\n >\n <span className=\"font-medium\">{group.label}:</span>\n <span className={group.mono ? \"font-mono\" : undefined}>\n {group.items.join(\", \")}\n </span>\n </span>\n ))}\n </div>\n );\n}\n"],"names":["jsx","Badge","UiThumbsUp","UiThumbsDown","resolveStatusConfig","resolveCommentStage","toneToBadgeTone","resolveFacetOption","Fragment","cn","jsxs"],"mappings":"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"}
1
+ {"version":3,"file":"CommentCardParts.cjs","sources":["../../src/comments/CommentCardParts.tsx"],"sourcesContent":["import { Badge } from \"../data/Badge\";\nimport { cn } from \"../lib/utils\";\nimport { UiThumbsDown, UiThumbsUp } from \"../icons\";\nimport {\n resolveFacetOption,\n resolveStatusConfig,\n toneToBadgeTone,\n} from \"./comment-utils\";\nimport { resolveCommentStage } from \"../lib/comment-stage\";\nimport type {\n Comment,\n CommentConfig,\n CommentRating,\n CommentReviewDecision,\n} from \"./comment-types\";\n\nexport function ReviewDecisionChip({\n decision,\n}: {\n decision: CommentReviewDecision | undefined;\n}) {\n if (!decision) return null;\n const label =\n decision === \"approved\"\n ? \"Approved\"\n : decision === \"rejected\"\n ? \"Rejected\"\n : \"Revision requested\";\n return (\n <Badge\n variant=\"soft\"\n tone={\n decision === \"approved\"\n ? \"success\"\n : decision === \"rejected\"\n ? \"danger\"\n : \"warning\"\n }\n size=\"xs\"\n >\n {label}\n </Badge>\n );\n}\n\nexport function RatingChip({ rating }: { rating: CommentRating | undefined }) {\n if (!rating) return null;\n const positive = rating === \"positive\";\n return (\n <Badge\n variant=\"soft\"\n tone={positive ? \"success\" : \"danger\"}\n size=\"xs\"\n icon={positive ? UiThumbsUp : UiThumbsDown}\n >\n {positive ? \"Positive rating\" : \"Negative rating\"}\n </Badge>\n );\n}\n\nexport function StatusChip({\n comment,\n config,\n}: {\n comment: Comment;\n config: CommentConfig;\n}) {\n const status = resolveStatusConfig(config, comment.status);\n if (!status) return null;\n const closedBy =\n resolveCommentStage(config, comment.status) === \"closed\"\n ? comment.closedBy\n : undefined;\n return (\n <Badge\n variant=\"soft\"\n tone={toneToBadgeTone(status.tone)}\n size=\"xs\"\n {...(status.icon ? { icon: status.icon } : {})}\n {...(comment.closedAt\n ? { title: new Date(comment.closedAt).toLocaleString() }\n : {})}\n >\n {closedBy ? `Closed by ${closedBy.name}` : status.label}\n </Badge>\n );\n}\n\nexport function FacetBadges({\n comment,\n config,\n compact,\n}: {\n comment: Comment;\n config: CommentConfig;\n compact?: boolean;\n}) {\n const chips = (config.facets ?? []).flatMap((facet) => {\n const option = resolveFacetOption(facet, comment.facets?.[facet.key]);\n if (!option) return [];\n return [\n <Badge\n key={facet.key}\n variant=\"soft\"\n tone={toneToBadgeTone(option.tone)}\n size=\"xs\"\n >\n {compact ? (option.short ?? option.label) : option.label}\n </Badge>,\n ];\n });\n return chips.length > 0 ? <>{chips}</> : null;\n}\n\nexport function ChecklistChips({\n comment,\n onChecklistToggle,\n}: {\n comment: Comment;\n onChecklistToggle?: (index: number) => void;\n}) {\n if (!comment.checklist?.length) return null;\n return (\n <div className=\"flex flex-wrap gap-1\">\n {comment.checklist.map((item, index) => {\n const done = /done|complete|resolved/i.test(item.status);\n const active = /progress|doing/i.test(item.status);\n return (\n <button\n key={index}\n type=\"button\"\n onClick={() => onChecklistToggle?.(index)}\n disabled={!onChecklistToggle}\n className={cn(\n \"inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-[10px] transition-opacity\",\n onChecklistToggle && \"cursor-pointer hover:opacity-80\",\n done\n ? \"bg-green-100 text-green-800 line-through dark:bg-green-500/20 dark:text-green-300\"\n : active\n ? \"bg-yellow-100 text-yellow-800 dark:bg-yellow-500/20 dark:text-yellow-300\"\n : \"bg-muted text-muted-foreground\",\n )}\n >\n {item.label}\n </button>\n );\n })}\n </div>\n );\n}\n\nexport function RefChips({ comment }: { comment: Comment }) {\n if (!comment.refs?.length) return null;\n return (\n <div className=\"flex flex-wrap gap-1.5\">\n {comment.refs.map((group, index) => (\n <span\n key={index}\n className=\"inline-flex items-center gap-1 rounded bg-muted px-1.5 py-0.5 text-[10px] text-muted-foreground\"\n >\n <span className=\"font-medium\">{group.label}:</span>\n <span className={group.mono ? \"font-mono\" : undefined}>\n {group.items.join(\", \")}\n </span>\n </span>\n ))}\n </div>\n );\n}\n"],"names":["jsx","Badge","UiThumbsUp","UiThumbsDown","resolveStatusConfig","resolveCommentStage","toneToBadgeTone","resolveFacetOption","Fragment","cn","jsxs"],"mappings":"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"}
@@ -1,4 +1,7 @@
1
- import { Comment, CommentConfig, CommentRating } from './comment-types.js';
1
+ import { Comment, CommentConfig, CommentRating, CommentReviewDecision } from './comment-types.js';
2
+ export declare function ReviewDecisionChip({ decision, }: {
3
+ decision: CommentReviewDecision | undefined;
4
+ }): import("react").JSX.Element | null;
2
5
  export declare function RatingChip({ rating }: {
3
6
  rating: CommentRating | undefined;
4
7
  }): import("react").JSX.Element | null;
@@ -1 +1 @@
1
- {"version":3,"file":"CommentCardParts.d.ts","sourceRoot":"","sources":["../../src/comments/CommentCardParts.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAE7E,wBAAgB,UAAU,CAAC,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,EAAE,aAAa,GAAG,SAAS,CAAA;CAAE,sCAa3E;AAED,wBAAgB,UAAU,CAAC,EACzB,OAAO,EACP,MAAM,GACP,EAAE;IACD,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,aAAa,CAAC;CACvB,sCAoBA;AAED,wBAAgB,WAAW,CAAC,EAC1B,OAAO,EACP,MAAM,EACN,OAAO,GACR,EAAE;IACD,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,aAAa,CAAC;IACtB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,sCAgBA;AAED,wBAAgB,cAAc,CAAC,EAC7B,OAAO,EACP,iBAAiB,GAClB,EAAE;IACD,OAAO,EAAE,OAAO,CAAC;IACjB,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7C,sCA6BA;AAED,wBAAgB,QAAQ,CAAC,EAAE,OAAO,EAAE,EAAE;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,sCAiBzD"}
1
+ {"version":3,"file":"CommentCardParts.d.ts","sourceRoot":"","sources":["../../src/comments/CommentCardParts.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EACV,OAAO,EACP,aAAa,EACb,aAAa,EACb,qBAAqB,EACtB,MAAM,iBAAiB,CAAC;AAEzB,wBAAgB,kBAAkB,CAAC,EACjC,QAAQ,GACT,EAAE;IACD,QAAQ,EAAE,qBAAqB,GAAG,SAAS,CAAC;CAC7C,sCAuBA;AAED,wBAAgB,UAAU,CAAC,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,EAAE,aAAa,GAAG,SAAS,CAAA;CAAE,sCAa3E;AAED,wBAAgB,UAAU,CAAC,EACzB,OAAO,EACP,MAAM,GACP,EAAE;IACD,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,aAAa,CAAC;CACvB,sCAoBA;AAED,wBAAgB,WAAW,CAAC,EAC1B,OAAO,EACP,MAAM,EACN,OAAO,GACR,EAAE;IACD,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,aAAa,CAAC;IACtB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,sCAgBA;AAED,wBAAgB,cAAc,CAAC,EAC7B,OAAO,EACP,iBAAiB,GAClB,EAAE;IACD,OAAO,EAAE,OAAO,CAAC;IACjB,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7C,sCA6BA;AAED,wBAAgB,QAAQ,CAAC,EAAE,OAAO,EAAE,EAAE;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,sCAiBzD"}
@@ -5,6 +5,21 @@ import { resolveStatusConfig, toneToBadgeTone, resolveFacetOption } from "./comm
5
5
  import { resolveCommentStage } from "../lib/comment-stage.js";
6
6
  import { UiThumbsUp } from "../icons/components/UiThumbsUp.js";
7
7
  import { UiThumbsDown } from "../icons/components/UiThumbsDown.js";
8
+ function ReviewDecisionChip({
9
+ decision
10
+ }) {
11
+ if (!decision) return null;
12
+ const label = decision === "approved" ? "Approved" : decision === "rejected" ? "Rejected" : "Revision requested";
13
+ return /* @__PURE__ */ jsx(
14
+ Badge,
15
+ {
16
+ variant: "soft",
17
+ tone: decision === "approved" ? "success" : decision === "rejected" ? "danger" : "warning",
18
+ size: "xs",
19
+ children: label
20
+ }
21
+ );
22
+ }
8
23
  function RatingChip({ rating }) {
9
24
  if (!rating) return null;
10
25
  const positive = rating === "positive";
@@ -111,6 +126,7 @@ export {
111
126
  FacetBadges,
112
127
  RatingChip,
113
128
  RefChips,
129
+ ReviewDecisionChip,
114
130
  StatusChip
115
131
  };
116
132
  //# sourceMappingURL=CommentCardParts.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"CommentCardParts.js","sources":["../../src/comments/CommentCardParts.tsx"],"sourcesContent":["import { Badge } from \"../data/Badge\";\nimport { cn } from \"../lib/utils\";\nimport { UiThumbsDown, UiThumbsUp } from \"../icons\";\nimport {\n resolveFacetOption,\n resolveStatusConfig,\n toneToBadgeTone,\n} from \"./comment-utils\";\nimport { resolveCommentStage } from \"../lib/comment-stage\";\nimport type { Comment, CommentConfig, CommentRating } from \"./comment-types\";\n\nexport function RatingChip({ rating }: { rating: CommentRating | undefined }) {\n if (!rating) return null;\n const positive = rating === \"positive\";\n return (\n <Badge\n variant=\"soft\"\n tone={positive ? \"success\" : \"danger\"}\n size=\"xs\"\n icon={positive ? UiThumbsUp : UiThumbsDown}\n >\n {positive ? \"Positive rating\" : \"Negative rating\"}\n </Badge>\n );\n}\n\nexport function StatusChip({\n comment,\n config,\n}: {\n comment: Comment;\n config: CommentConfig;\n}) {\n const status = resolveStatusConfig(config, comment.status);\n if (!status) return null;\n const closedBy =\n resolveCommentStage(config, comment.status) === \"closed\"\n ? comment.closedBy\n : undefined;\n return (\n <Badge\n variant=\"soft\"\n tone={toneToBadgeTone(status.tone)}\n size=\"xs\"\n {...(status.icon ? { icon: status.icon } : {})}\n {...(comment.closedAt\n ? { title: new Date(comment.closedAt).toLocaleString() }\n : {})}\n >\n {closedBy ? `Closed by ${closedBy.name}` : status.label}\n </Badge>\n );\n}\n\nexport function FacetBadges({\n comment,\n config,\n compact,\n}: {\n comment: Comment;\n config: CommentConfig;\n compact?: boolean;\n}) {\n const chips = (config.facets ?? []).flatMap((facet) => {\n const option = resolveFacetOption(facet, comment.facets?.[facet.key]);\n if (!option) return [];\n return [\n <Badge\n key={facet.key}\n variant=\"soft\"\n tone={toneToBadgeTone(option.tone)}\n size=\"xs\"\n >\n {compact ? (option.short ?? option.label) : option.label}\n </Badge>,\n ];\n });\n return chips.length > 0 ? <>{chips}</> : null;\n}\n\nexport function ChecklistChips({\n comment,\n onChecklistToggle,\n}: {\n comment: Comment;\n onChecklistToggle?: (index: number) => void;\n}) {\n if (!comment.checklist?.length) return null;\n return (\n <div className=\"flex flex-wrap gap-1\">\n {comment.checklist.map((item, index) => {\n const done = /done|complete|resolved/i.test(item.status);\n const active = /progress|doing/i.test(item.status);\n return (\n <button\n key={index}\n type=\"button\"\n onClick={() => onChecklistToggle?.(index)}\n disabled={!onChecklistToggle}\n className={cn(\n \"inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-[10px] transition-opacity\",\n onChecklistToggle && \"cursor-pointer hover:opacity-80\",\n done\n ? \"bg-green-100 text-green-800 line-through dark:bg-green-500/20 dark:text-green-300\"\n : active\n ? \"bg-yellow-100 text-yellow-800 dark:bg-yellow-500/20 dark:text-yellow-300\"\n : \"bg-muted text-muted-foreground\",\n )}\n >\n {item.label}\n </button>\n );\n })}\n </div>\n );\n}\n\nexport function RefChips({ comment }: { comment: Comment }) {\n if (!comment.refs?.length) return null;\n return (\n <div className=\"flex flex-wrap gap-1.5\">\n {comment.refs.map((group, index) => (\n <span\n key={index}\n className=\"inline-flex items-center gap-1 rounded bg-muted px-1.5 py-0.5 text-[10px] text-muted-foreground\"\n >\n <span className=\"font-medium\">{group.label}:</span>\n <span className={group.mono ? \"font-mono\" : undefined}>\n {group.items.join(\", \")}\n </span>\n </span>\n ))}\n </div>\n );\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"CommentCardParts.js","sources":["../../src/comments/CommentCardParts.tsx"],"sourcesContent":["import { Badge } from \"../data/Badge\";\nimport { cn } from \"../lib/utils\";\nimport { UiThumbsDown, UiThumbsUp } from \"../icons\";\nimport {\n resolveFacetOption,\n resolveStatusConfig,\n toneToBadgeTone,\n} from \"./comment-utils\";\nimport { resolveCommentStage } from \"../lib/comment-stage\";\nimport type {\n Comment,\n CommentConfig,\n CommentRating,\n CommentReviewDecision,\n} from \"./comment-types\";\n\nexport function ReviewDecisionChip({\n decision,\n}: {\n decision: CommentReviewDecision | undefined;\n}) {\n if (!decision) return null;\n const label =\n decision === \"approved\"\n ? \"Approved\"\n : decision === \"rejected\"\n ? \"Rejected\"\n : \"Revision requested\";\n return (\n <Badge\n variant=\"soft\"\n tone={\n decision === \"approved\"\n ? \"success\"\n : decision === \"rejected\"\n ? \"danger\"\n : \"warning\"\n }\n size=\"xs\"\n >\n {label}\n </Badge>\n );\n}\n\nexport function RatingChip({ rating }: { rating: CommentRating | undefined }) {\n if (!rating) return null;\n const positive = rating === \"positive\";\n return (\n <Badge\n variant=\"soft\"\n tone={positive ? \"success\" : \"danger\"}\n size=\"xs\"\n icon={positive ? UiThumbsUp : UiThumbsDown}\n >\n {positive ? \"Positive rating\" : \"Negative rating\"}\n </Badge>\n );\n}\n\nexport function StatusChip({\n comment,\n config,\n}: {\n comment: Comment;\n config: CommentConfig;\n}) {\n const status = resolveStatusConfig(config, comment.status);\n if (!status) return null;\n const closedBy =\n resolveCommentStage(config, comment.status) === \"closed\"\n ? comment.closedBy\n : undefined;\n return (\n <Badge\n variant=\"soft\"\n tone={toneToBadgeTone(status.tone)}\n size=\"xs\"\n {...(status.icon ? { icon: status.icon } : {})}\n {...(comment.closedAt\n ? { title: new Date(comment.closedAt).toLocaleString() }\n : {})}\n >\n {closedBy ? `Closed by ${closedBy.name}` : status.label}\n </Badge>\n );\n}\n\nexport function FacetBadges({\n comment,\n config,\n compact,\n}: {\n comment: Comment;\n config: CommentConfig;\n compact?: boolean;\n}) {\n const chips = (config.facets ?? []).flatMap((facet) => {\n const option = resolveFacetOption(facet, comment.facets?.[facet.key]);\n if (!option) return [];\n return [\n <Badge\n key={facet.key}\n variant=\"soft\"\n tone={toneToBadgeTone(option.tone)}\n size=\"xs\"\n >\n {compact ? (option.short ?? option.label) : option.label}\n </Badge>,\n ];\n });\n return chips.length > 0 ? <>{chips}</> : null;\n}\n\nexport function ChecklistChips({\n comment,\n onChecklistToggle,\n}: {\n comment: Comment;\n onChecklistToggle?: (index: number) => void;\n}) {\n if (!comment.checklist?.length) return null;\n return (\n <div className=\"flex flex-wrap gap-1\">\n {comment.checklist.map((item, index) => {\n const done = /done|complete|resolved/i.test(item.status);\n const active = /progress|doing/i.test(item.status);\n return (\n <button\n key={index}\n type=\"button\"\n onClick={() => onChecklistToggle?.(index)}\n disabled={!onChecklistToggle}\n className={cn(\n \"inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-[10px] transition-opacity\",\n onChecklistToggle && \"cursor-pointer hover:opacity-80\",\n done\n ? \"bg-green-100 text-green-800 line-through dark:bg-green-500/20 dark:text-green-300\"\n : active\n ? \"bg-yellow-100 text-yellow-800 dark:bg-yellow-500/20 dark:text-yellow-300\"\n : \"bg-muted text-muted-foreground\",\n )}\n >\n {item.label}\n </button>\n );\n })}\n </div>\n );\n}\n\nexport function RefChips({ comment }: { comment: Comment }) {\n if (!comment.refs?.length) return null;\n return (\n <div className=\"flex flex-wrap gap-1.5\">\n {comment.refs.map((group, index) => (\n <span\n key={index}\n className=\"inline-flex items-center gap-1 rounded bg-muted px-1.5 py-0.5 text-[10px] text-muted-foreground\"\n >\n <span className=\"font-medium\">{group.label}:</span>\n <span className={group.mono ? \"font-mono\" : undefined}>\n {group.items.join(\", \")}\n </span>\n </span>\n ))}\n </div>\n );\n}\n"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"comment-types.cjs","sources":["../../src/comments/comment-types.ts"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport type { StaticIconComponent } from \"../data/Icon\";\n\n/** Semantic tone driving a status/facet color (maps onto Badge tones). */\nexport type CommentTone =\n | \"default\"\n | \"info\"\n | \"success\"\n | \"warning\"\n | \"danger\"\n | \"neutral\";\n\n/** Product lifecycle stage represented by one or more stored statuses. */\nexport type CommentStatusStage = \"active\" | \"resolved\" | \"closed\";\n\n/** A single selectable status (e.g. \"open\", \"resolved\"). Consumer-defined. */\nexport type CommentStatusConfig = {\n /** Stable value stored on a comment's `status`. */\n value: string;\n /** Human label shown in menus and badges. */\n label: string;\n /** Color tone for the status chip. */\n tone?: CommentTone;\n /** Optional leading glyph. */\n icon?: string | StaticIconComponent;\n /** Lifecycle stage used by review queues and status actions. */\n stage?: CommentStatusStage;\n /**\n * Whether this status counts as \"unresolved/open\" — drives progress tallies\n * and which groups start expanded. Defaults to false.\n */\n unresolved?: boolean;\n};\n\n/** One option of a generic facet (e.g. a \"category\" value). */\nexport type CommentFacetOption = {\n value: string;\n label: string;\n tone?: CommentTone;\n /** Compact glyph for the collapsed card (e.g. \"BS\" for a category). */\n short?: string;\n};\n\n/**\n * A generic, consumer-supplied classification axis. Replaces the financial\n * category/severity vocabulary — any app declares its own facets.\n */\nexport type CommentFacet = {\n /** Key into `Comment.facets`. */\n key: string;\n label: string;\n options: CommentFacetOption[];\n /** Allow several values to be selected at once in the filter bar. */\n multiple?: boolean;\n};\n\nexport type CommentMentionKind = \"user\" | \"agent\";\n\n/** A person or agent that can be @-mentioned in the composer. */\nexport type CommentMentionable = {\n id: string;\n name: string;\n /** Image URL for `kind: \"user\"`. */\n avatar?: string;\n kind: CommentMentionKind;\n /** Glyph override for `kind: \"agent\"`. */\n icon?: string | StaticIconComponent;\n};\n\n/** A resolved mention emitted when a comment referencing a mentionable is posted. */\nexport type CommentMention = {\n id: string;\n name: string;\n kind: CommentMentionKind;\n};\n\n/** A labelled group of reference chips (e.g. linked ids). */\nexport type CommentRefGroup = {\n label: string;\n items: string[];\n /** Render items in a monospace font. */\n mono?: boolean;\n};\n\n/** One item of a generic checklist; `status` cycles through `checklistStatusCycle`. */\nexport type CommentChecklistItem = {\n label: string;\n status: string;\n};\n\nexport type CommentAuthor = {\n id?: string;\n name: string;\n kind?: CommentMentionKind;\n avatar?: string;\n /** Glyph override for `kind: \"agent\"` authors. */\n icon?: string | StaticIconComponent;\n};\n\n/**\n * An opaque anchor key locating a comment within a document. Not a JSON path —\n * any stable string a consumer registers via the provider. `null`/absent means\n * document-level.\n */\nexport type CommentAnchor = string;\n\n/** Binary review signal attached to a root comment. */\nexport type CommentRating = \"positive\" | \"negative\";\n\n/** Anchor key reserved for document-level (un-anchored) comments. */\nexport const DOCUMENT_ANCHOR = \"__document__\";\n\n/** A single comment. Replies set `parentId`; roots leave it null. */\nexport type Comment = {\n id: string;\n body: string;\n /** ISO-8601 creation time. */\n createdAt: string;\n /** ISO-8601 last-update time. */\n updatedAt?: string;\n author: CommentAuthor | null;\n /** Key into the configured statuses; roots only. */\n status?: string;\n /** Parent comment id when this is a reply. */\n parentId?: string | null;\n /** Where the comment is anchored; null/absent = document-level. */\n anchor?: CommentAnchor | null;\n /** Optional positive/negative review signal; roots only. */\n rating?: CommentRating;\n /** ISO-8601 time when a human closed the resolved comment. */\n closedAt?: string;\n /** Human who closed the comment. */\n closedBy?: CommentAuthor;\n /** facet.key → selected option value. */\n facets?: Record<string, string>;\n refs?: CommentRefGroup[];\n checklist?: CommentChecklistItem[];\n};\n\n/** Payload for creating a new root comment. */\nexport type CommentCreateInput = {\n body: string;\n anchor?: CommentAnchor | null;\n rating?: CommentRating;\n facets?: Record<string, string>;\n mentions?: CommentMention[];\n};\n\nexport type CommentCreateAction = { id: string; label: string };\n\n/** Payload for replying to a comment. */\nexport type CommentReplyInput = {\n parentId: string;\n body: string;\n anchor?: CommentAnchor | null;\n mentions?: CommentMention[];\n};\n\n/**\n * Controlled callbacks. The components own no data fetching; the consumer\n * performs the mutation and feeds the updated `comments` back in.\n */\nexport type CommentCallbacks = {\n onCreate?: (input: CommentCreateInput, actionId?: string) => void | Promise<void>;\n onReply?: (input: CommentReplyInput) => void | Promise<void>;\n onUpdateStatus?: (id: string, status: string) => void | Promise<void>;\n /** Human-only transition from resolved to closed. */\n onClose?: (id: string) => void | Promise<void>;\n onUpdateRating?: (id: string, rating: CommentRating) => void | Promise<void>;\n onDelete?: (id: string) => void | Promise<void>;\n onChecklistToggle?: (\n id: string,\n index: number,\n next: string,\n ) => void | Promise<void>;\n /** Fired when a posted comment references a mentionable. */\n onMention?: (mention: CommentMention, context: { body: string }) => void;\n};\n\n/** Static configuration shared across the comment components. */\nexport type CommentConfig = {\n /** Selectable statuses; the first `unresolved` one is the default for new comments. */\n statuses: CommentStatusConfig[];\n /** Classification axes (category/severity/etc.). */\n facets?: CommentFacet[];\n /** People/agents available for @-mention. */\n mentionables?: CommentMentionable[];\n /** Status values a checklist item cycles through on click. */\n checklistStatusCycle?: string[];\n};\n\n/** Aggregate metadata for one anchor, derived from the comment list. */\nexport type CommentAnchorMeta = {\n count: number;\n authors: string[];\n latestStatus?: string;\n};\n\n/** Selected filter state for the filter bar / `applyCommentFilters`. */\nexport type CommentFilters = {\n /** Selected status values; empty = all statuses. */\n statuses: Set<string>;\n /** facet.key → selected option values; empty set = all values for that facet. */\n facets: Record<string, Set<string>>;\n /** Restrict to an author kind, or \"all\". */\n authorKind?: CommentMentionKind | \"all\";\n};\n\n/** Optional renderers passed down to a card. */\nexport type CommentRenderOptions = {\n /** Custom comment-body renderer (e.g. full Markdown). Defaults to CommentMarkdown. */\n renderBody?: (body: string) => ReactNode;\n};\n\n/** A domain-free default status set: open / in progress / resolved / closed. */\nexport const DEFAULT_COMMENT_STATUSES: CommentStatusConfig[] = [\n {\n value: \"open\",\n label: \"Open\",\n tone: \"info\",\n unresolved: true,\n stage: \"active\",\n },\n {\n value: \"in_progress\",\n label: \"In progress\",\n tone: \"warning\",\n unresolved: true,\n stage: \"active\",\n },\n {\n value: \"resolved\",\n label: \"Resolved\",\n tone: \"success\",\n stage: \"resolved\",\n },\n { value: \"closed\", label: \"Closed\", tone: \"neutral\", stage: \"closed\" },\n];\n\n/** Default checklist status cycle used when a consumer omits one. */\nexport const DEFAULT_CHECKLIST_CYCLE = [\"open\", \"in_progress\", \"done\"];\n"],"names":[],"mappings":";;AA8GO,MAAM,kBAAkB;AAyGxB,MAAM,2BAAkD;AAAA,EAC7D;AAAA,IACE,OAAO;AAAA,IACP,OAAO;AAAA,IACP,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,OAAO;AAAA,EAAA;AAAA,EAET;AAAA,IACE,OAAO;AAAA,IACP,OAAO;AAAA,IACP,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,OAAO;AAAA,EAAA;AAAA,EAET;AAAA,IACE,OAAO;AAAA,IACP,OAAO;AAAA,IACP,MAAM;AAAA,IACN,OAAO;AAAA,EAAA;AAAA,EAET,EAAE,OAAO,UAAU,OAAO,UAAU,MAAM,WAAW,OAAO,SAAA;AAC9D;AAGO,MAAM,0BAA0B,CAAC,QAAQ,eAAe,MAAM;;;;"}
1
+ {"version":3,"file":"comment-types.cjs","sources":["../../src/comments/comment-types.ts"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport type { StaticIconComponent } from \"../data/Icon\";\n\n/** Semantic tone driving a status/facet color (maps onto Badge tones). */\nexport type CommentTone =\n | \"default\"\n | \"info\"\n | \"success\"\n | \"warning\"\n | \"danger\"\n | \"neutral\";\n\n/** Product lifecycle stage represented by one or more stored statuses. */\nexport type CommentStatusStage = \"active\" | \"resolved\" | \"closed\";\n\n/** A single selectable status (e.g. \"open\", \"resolved\"). Consumer-defined. */\nexport type CommentStatusConfig = {\n /** Stable value stored on a comment's `status`. */\n value: string;\n /** Human label shown in menus and badges. */\n label: string;\n /** Color tone for the status chip. */\n tone?: CommentTone;\n /** Optional leading glyph. */\n icon?: string | StaticIconComponent;\n /** Lifecycle stage used by review queues and status actions. */\n stage?: CommentStatusStage;\n /**\n * Whether this status counts as \"unresolved/open\" — drives progress tallies\n * and which groups start expanded. Defaults to false.\n */\n unresolved?: boolean;\n};\n\n/** One option of a generic facet (e.g. a \"category\" value). */\nexport type CommentFacetOption = {\n value: string;\n label: string;\n tone?: CommentTone;\n /** Compact glyph for the collapsed card (e.g. \"BS\" for a category). */\n short?: string;\n};\n\n/**\n * A generic, consumer-supplied classification axis. Replaces the financial\n * category/severity vocabulary — any app declares its own facets.\n */\nexport type CommentFacet = {\n /** Key into `Comment.facets`. */\n key: string;\n label: string;\n options: CommentFacetOption[];\n /** Allow several values to be selected at once in the filter bar. */\n multiple?: boolean;\n};\n\nexport type CommentMentionKind = \"user\" | \"agent\";\n\n/** A person or agent that can be @-mentioned in the composer. */\nexport type CommentMentionable = {\n id: string;\n name: string;\n /** Image URL for `kind: \"user\"`. */\n avatar?: string;\n kind: CommentMentionKind;\n /** Glyph override for `kind: \"agent\"`. */\n icon?: string | StaticIconComponent;\n};\n\n/** A resolved mention emitted when a comment referencing a mentionable is posted. */\nexport type CommentMention = {\n id: string;\n name: string;\n kind: CommentMentionKind;\n};\n\n/** A labelled group of reference chips (e.g. linked ids). */\nexport type CommentRefGroup = {\n label: string;\n items: string[];\n /** Render items in a monospace font. */\n mono?: boolean;\n};\n\n/** One item of a generic checklist; `status` cycles through `checklistStatusCycle`. */\nexport type CommentChecklistItem = {\n label: string;\n status: string;\n};\n\nexport type CommentAuthor = {\n id?: string;\n name: string;\n kind?: CommentMentionKind;\n avatar?: string;\n /** Glyph override for `kind: \"agent\"` authors. */\n icon?: string | StaticIconComponent;\n};\n\n/**\n * An opaque anchor key locating a comment within a document. Not a JSON path —\n * any stable string a consumer registers via the provider. `null`/absent means\n * document-level.\n */\nexport type CommentAnchor = string;\n\n/** Binary review signal attached to a root comment. */\nexport type CommentRating = \"positive\" | \"negative\";\nexport type CommentReviewDecision =\n | \"approved\"\n | \"rejected\"\n | \"revision_requested\";\n\n/** Anchor key reserved for document-level (un-anchored) comments. */\nexport const DOCUMENT_ANCHOR = \"__document__\";\n\n/** A single comment. Replies set `parentId`; roots leave it null. */\nexport type Comment = {\n id: string;\n body: string;\n /** ISO-8601 creation time. */\n createdAt: string;\n /** ISO-8601 last-update time. */\n updatedAt?: string;\n author: CommentAuthor | null;\n /** Key into the configured statuses; roots only. */\n status?: string;\n /** Parent comment id when this is a reply. */\n parentId?: string | null;\n /** Where the comment is anchored; null/absent = document-level. */\n anchor?: CommentAnchor | null;\n /** Optional positive/negative review signal; roots only. */\n rating?: CommentRating;\n /** Human decision on an opted-in playground review element; roots only. */\n reviewDecision?: CommentReviewDecision;\n /** ISO-8601 time when a human closed the resolved comment. */\n closedAt?: string;\n /** Human who closed the comment. */\n closedBy?: CommentAuthor;\n /** facet.key → selected option value. */\n facets?: Record<string, string>;\n refs?: CommentRefGroup[];\n checklist?: CommentChecklistItem[];\n};\n\n/** Payload for creating a new root comment. */\nexport type CommentCreateInput = {\n body: string;\n anchor?: CommentAnchor | null;\n rating?: CommentRating;\n reviewDecision?: CommentReviewDecision;\n facets?: Record<string, string>;\n mentions?: CommentMention[];\n};\n\nexport type CommentCreateAction = { id: string; label: string };\n\n/** Payload for replying to a comment. */\nexport type CommentReplyInput = {\n parentId: string;\n body: string;\n anchor?: CommentAnchor | null;\n mentions?: CommentMention[];\n};\n\n/**\n * Controlled callbacks. The components own no data fetching; the consumer\n * performs the mutation and feeds the updated `comments` back in.\n */\nexport type CommentCallbacks = {\n onCreate?: (\n input: CommentCreateInput,\n actionId?: string,\n ) => void | Promise<void>;\n onReply?: (input: CommentReplyInput) => void | Promise<void>;\n onUpdateStatus?: (id: string, status: string) => void | Promise<void>;\n /** Human-only transition from resolved to closed. */\n onClose?: (id: string) => void | Promise<void>;\n onUpdateRating?: (id: string, rating: CommentRating) => void | Promise<void>;\n onDelete?: (id: string) => void | Promise<void>;\n onChecklistToggle?: (\n id: string,\n index: number,\n next: string,\n ) => void | Promise<void>;\n /** Fired when a posted comment references a mentionable. */\n onMention?: (mention: CommentMention, context: { body: string }) => void;\n};\n\n/** Static configuration shared across the comment components. */\nexport type CommentConfig = {\n /** Selectable statuses; the first `unresolved` one is the default for new comments. */\n statuses: CommentStatusConfig[];\n /** Classification axes (category/severity/etc.). */\n facets?: CommentFacet[];\n /** People/agents available for @-mention. */\n mentionables?: CommentMentionable[];\n /** Status values a checklist item cycles through on click. */\n checklistStatusCycle?: string[];\n};\n\n/** Aggregate metadata for one anchor, derived from the comment list. */\nexport type CommentAnchorMeta = {\n count: number;\n authors: string[];\n latestStatus?: string;\n};\n\n/** Selected filter state for the filter bar / `applyCommentFilters`. */\nexport type CommentFilters = {\n /** Selected status values; empty = all statuses. */\n statuses: Set<string>;\n /** facet.key → selected option values; empty set = all values for that facet. */\n facets: Record<string, Set<string>>;\n /** Restrict to an author kind, or \"all\". */\n authorKind?: CommentMentionKind | \"all\";\n};\n\n/** Optional renderers passed down to a card. */\nexport type CommentRenderOptions = {\n /** Custom comment-body renderer (e.g. full Markdown). Defaults to CommentMarkdown. */\n renderBody?: (body: string) => ReactNode;\n};\n\n/** A domain-free default status set: open / in progress / resolved / closed. */\nexport const DEFAULT_COMMENT_STATUSES: CommentStatusConfig[] = [\n {\n value: \"open\",\n label: \"Open\",\n tone: \"info\",\n unresolved: true,\n stage: \"active\",\n },\n {\n value: \"in_progress\",\n label: \"In progress\",\n tone: \"warning\",\n unresolved: true,\n stage: \"active\",\n },\n {\n value: \"resolved\",\n label: \"Resolved\",\n tone: \"success\",\n stage: \"resolved\",\n },\n { value: \"closed\", label: \"Closed\", tone: \"neutral\", stage: \"closed\" },\n];\n\n/** Default checklist status cycle used when a consumer omits one. */\nexport const DEFAULT_CHECKLIST_CYCLE = [\"open\", \"in_progress\", \"done\"];\n"],"names":[],"mappings":";;AAkHO,MAAM,kBAAkB;AA+GxB,MAAM,2BAAkD;AAAA,EAC7D;AAAA,IACE,OAAO;AAAA,IACP,OAAO;AAAA,IACP,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,OAAO;AAAA,EAAA;AAAA,EAET;AAAA,IACE,OAAO;AAAA,IACP,OAAO;AAAA,IACP,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,OAAO;AAAA,EAAA;AAAA,EAET;AAAA,IACE,OAAO;AAAA,IACP,OAAO;AAAA,IACP,MAAM;AAAA,IACN,OAAO;AAAA,EAAA;AAAA,EAET,EAAE,OAAO,UAAU,OAAO,UAAU,MAAM,WAAW,OAAO,SAAA;AAC9D;AAGO,MAAM,0BAA0B,CAAC,QAAQ,eAAe,MAAM;;;;"}
@@ -87,6 +87,7 @@ export type CommentAuthor = {
87
87
  export type CommentAnchor = string;
88
88
  /** Binary review signal attached to a root comment. */
89
89
  export type CommentRating = "positive" | "negative";
90
+ export type CommentReviewDecision = "approved" | "rejected" | "revision_requested";
90
91
  /** Anchor key reserved for document-level (un-anchored) comments. */
91
92
  export declare const DOCUMENT_ANCHOR = "__document__";
92
93
  /** A single comment. Replies set `parentId`; roots leave it null. */
@@ -106,6 +107,8 @@ export type Comment = {
106
107
  anchor?: CommentAnchor | null;
107
108
  /** Optional positive/negative review signal; roots only. */
108
109
  rating?: CommentRating;
110
+ /** Human decision on an opted-in playground review element; roots only. */
111
+ reviewDecision?: CommentReviewDecision;
109
112
  /** ISO-8601 time when a human closed the resolved comment. */
110
113
  closedAt?: string;
111
114
  /** Human who closed the comment. */
@@ -120,6 +123,7 @@ export type CommentCreateInput = {
120
123
  body: string;
121
124
  anchor?: CommentAnchor | null;
122
125
  rating?: CommentRating;
126
+ reviewDecision?: CommentReviewDecision;
123
127
  facets?: Record<string, string>;
124
128
  mentions?: CommentMention[];
125
129
  };