@vertesia/ui 1.5.0-dev.20260722.120446Z → 1.5.0-dev.20260725.083715Z

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 (307) hide show
  1. package/lib/core/components/shadcn/filters/filterBar.d.ts.map +1 -1
  2. package/lib/core/components/shadcn/filters/filterBar.js +1 -1
  3. package/lib/core/components/shadcn/filters/filterBar.js.map +1 -1
  4. package/lib/core/components/shadcn/modal/dialog.d.ts +1 -1
  5. package/lib/core/components/shadcn/modal/dialog.d.ts.map +1 -1
  6. package/lib/core/components/shadcn/modal/dialog.js +2 -0
  7. package/lib/core/components/shadcn/modal/dialog.js.map +1 -1
  8. package/lib/core/components/shadcn/tabs.d.ts +12 -1
  9. package/lib/core/components/shadcn/tabs.d.ts.map +1 -1
  10. package/lib/core/components/shadcn/tabs.js +12 -4
  11. package/lib/core/components/shadcn/tabs.js.map +1 -1
  12. package/lib/features/agent/chat/AgentRightPanel.d.ts +5 -1
  13. package/lib/features/agent/chat/AgentRightPanel.d.ts.map +1 -1
  14. package/lib/features/agent/chat/AgentRightPanel.js +2 -2
  15. package/lib/features/agent/chat/AgentRightPanel.js.map +1 -1
  16. package/lib/features/agent/chat/ArtifactsTab.d.ts +5 -1
  17. package/lib/features/agent/chat/ArtifactsTab.d.ts.map +1 -1
  18. package/lib/features/agent/chat/ArtifactsTab.js +48 -11
  19. package/lib/features/agent/chat/ArtifactsTab.js.map +1 -1
  20. package/lib/features/agent/chat/DocumentEditingActionCard.d.ts +6 -0
  21. package/lib/features/agent/chat/DocumentEditingActionCard.d.ts.map +1 -0
  22. package/lib/features/agent/chat/DocumentEditingActionCard.js +129 -0
  23. package/lib/features/agent/chat/DocumentEditingActionCard.js.map +1 -0
  24. package/lib/features/agent/chat/ModernAgentConversation.d.ts +19 -1
  25. package/lib/features/agent/chat/ModernAgentConversation.d.ts.map +1 -1
  26. package/lib/features/agent/chat/ModernAgentConversation.js +125 -27
  27. package/lib/features/agent/chat/ModernAgentConversation.js.map +1 -1
  28. package/lib/features/agent/chat/ModernAgentOutput/AgentMarkdownAnchor.d.ts +45 -0
  29. package/lib/features/agent/chat/ModernAgentOutput/AgentMarkdownAnchor.d.ts.map +1 -0
  30. package/lib/features/agent/chat/ModernAgentOutput/AgentMarkdownAnchor.js +40 -0
  31. package/lib/features/agent/chat/ModernAgentOutput/AgentMarkdownAnchor.js.map +1 -0
  32. package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.d.ts +3 -1
  33. package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.d.ts.map +1 -1
  34. package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.js +94 -49
  35. package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.js.map +1 -1
  36. package/lib/features/agent/chat/ModernAgentOutput/AttachmentPreview.d.ts +2 -1
  37. package/lib/features/agent/chat/ModernAgentOutput/AttachmentPreview.d.ts.map +1 -1
  38. package/lib/features/agent/chat/ModernAgentOutput/AttachmentPreview.js +9 -5
  39. package/lib/features/agent/chat/ModernAgentOutput/AttachmentPreview.js.map +1 -1
  40. package/lib/features/agent/chat/ModernAgentOutput/CollapsibleAgentMarkdown.d.ts +25 -0
  41. package/lib/features/agent/chat/ModernAgentOutput/CollapsibleAgentMarkdown.d.ts.map +1 -0
  42. package/lib/features/agent/chat/ModernAgentOutput/CollapsibleAgentMarkdown.js +33 -0
  43. package/lib/features/agent/chat/ModernAgentOutput/CollapsibleAgentMarkdown.js.map +1 -0
  44. package/lib/features/agent/chat/ModernAgentOutput/MessageItem.d.ts +3 -1
  45. package/lib/features/agent/chat/ModernAgentOutput/MessageItem.d.ts.map +1 -1
  46. package/lib/features/agent/chat/ModernAgentOutput/MessageItem.js +22 -24
  47. package/lib/features/agent/chat/ModernAgentOutput/MessageItem.js.map +1 -1
  48. package/lib/features/agent/chat/ModernAgentOutput/ResourceChangeSummary.d.ts +14 -0
  49. package/lib/features/agent/chat/ModernAgentOutput/ResourceChangeSummary.d.ts.map +1 -0
  50. package/lib/features/agent/chat/ModernAgentOutput/ResourceChangeSummary.js +21 -0
  51. package/lib/features/agent/chat/ModernAgentOutput/ResourceChangeSummary.js.map +1 -0
  52. package/lib/features/agent/chat/ModernAgentOutput/ResourceChip.d.ts +30 -0
  53. package/lib/features/agent/chat/ModernAgentOutput/ResourceChip.d.ts.map +1 -0
  54. package/lib/features/agent/chat/ModernAgentOutput/ResourceChip.js +53 -0
  55. package/lib/features/agent/chat/ModernAgentOutput/ResourceChip.js.map +1 -0
  56. package/lib/features/agent/chat/ModernAgentOutput/ToolCallGroup.d.ts.map +1 -1
  57. package/lib/features/agent/chat/ModernAgentOutput/ToolCallGroup.js +21 -2
  58. package/lib/features/agent/chat/ModernAgentOutput/ToolCallGroup.js.map +1 -1
  59. package/lib/features/agent/chat/ModernAgentOutput/resourceLinks.d.ts +6 -0
  60. package/lib/features/agent/chat/ModernAgentOutput/resourceLinks.d.ts.map +1 -0
  61. package/lib/features/agent/chat/ModernAgentOutput/resourceLinks.js +29 -0
  62. package/lib/features/agent/chat/ModernAgentOutput/resourceLinks.js.map +1 -0
  63. package/lib/features/agent/chat/ModernAgentOutput/resourceSummary.d.ts +33 -0
  64. package/lib/features/agent/chat/ModernAgentOutput/resourceSummary.d.ts.map +1 -0
  65. package/lib/features/agent/chat/ModernAgentOutput/resourceSummary.js +129 -0
  66. package/lib/features/agent/chat/ModernAgentOutput/resourceSummary.js.map +1 -0
  67. package/lib/features/agent/chat/ModernAgentOutput/utils.d.ts +7 -0
  68. package/lib/features/agent/chat/ModernAgentOutput/utils.d.ts.map +1 -1
  69. package/lib/features/agent/chat/ModernAgentOutput/utils.js +11 -1
  70. package/lib/features/agent/chat/ModernAgentOutput/utils.js.map +1 -1
  71. package/lib/features/agent/chat/hooks/useAgentStream.d.ts +1 -1
  72. package/lib/features/agent/chat/hooks/useAgentStream.d.ts.map +1 -1
  73. package/lib/features/agent/chat/hooks/useAgentStream.js +24 -9
  74. package/lib/features/agent/chat/hooks/useAgentStream.js.map +1 -1
  75. package/lib/features/agent/chat/index.d.ts +2 -1
  76. package/lib/features/agent/chat/index.d.ts.map +1 -1
  77. package/lib/features/agent/chat/index.js +3 -0
  78. package/lib/features/agent/chat/index.js.map +1 -1
  79. package/lib/features/store/objects/DocumentSearchResults.js +2 -2
  80. package/lib/features/store/objects/DocumentSearchResults.js.map +1 -1
  81. package/lib/features/store/objects/components/ContentOverview.d.ts +2 -1
  82. package/lib/features/store/objects/components/ContentOverview.d.ts.map +1 -1
  83. package/lib/features/store/objects/components/ContentOverview.js +86 -15
  84. package/lib/features/store/objects/components/ContentOverview.js.map +1 -1
  85. package/lib/features/store/objects/components/DocumentEditingConfigurationSelector.d.ts +16 -0
  86. package/lib/features/store/objects/components/DocumentEditingConfigurationSelector.d.ts.map +1 -0
  87. package/lib/features/store/objects/components/DocumentEditingConfigurationSelector.js +116 -0
  88. package/lib/features/store/objects/components/DocumentEditingConfigurationSelector.js.map +1 -0
  89. package/lib/features/store/objects/components/DocumentEditingLockStatus.d.ts +7 -0
  90. package/lib/features/store/objects/components/DocumentEditingLockStatus.d.ts.map +1 -0
  91. package/lib/features/store/objects/components/DocumentEditingLockStatus.js +13 -0
  92. package/lib/features/store/objects/components/DocumentEditingLockStatus.js.map +1 -0
  93. package/lib/features/store/objects/components/DocumentEditingPanel.d.ts +48 -0
  94. package/lib/features/store/objects/components/DocumentEditingPanel.d.ts.map +1 -0
  95. package/lib/features/store/objects/components/DocumentEditingPanel.js +720 -0
  96. package/lib/features/store/objects/components/DocumentEditingPanel.js.map +1 -0
  97. package/lib/features/store/objects/components/TextEditorPanel.d.ts.map +1 -1
  98. package/lib/features/store/objects/components/TextEditorPanel.js +22 -9
  99. package/lib/features/store/objects/components/TextEditorPanel.js.map +1 -1
  100. package/lib/features/store/objects/components/documentArtifactRefs.d.ts +26 -0
  101. package/lib/features/store/objects/components/documentArtifactRefs.d.ts.map +1 -0
  102. package/lib/features/store/objects/components/documentArtifactRefs.js +52 -0
  103. package/lib/features/store/objects/components/documentArtifactRefs.js.map +1 -0
  104. package/lib/features/store/objects/components/documentEditingAgentConfig.d.ts +4 -0
  105. package/lib/features/store/objects/components/documentEditingAgentConfig.d.ts.map +1 -0
  106. package/lib/features/store/objects/components/documentEditingAgentConfig.js +40 -0
  107. package/lib/features/store/objects/components/documentEditingAgentConfig.js.map +1 -0
  108. package/lib/features/store/objects/components/documentEditingPrompts.d.ts +3 -0
  109. package/lib/features/store/objects/components/documentEditingPrompts.d.ts.map +1 -0
  110. package/lib/features/store/objects/components/documentEditingPrompts.js +13 -0
  111. package/lib/features/store/objects/components/documentEditingPrompts.js.map +1 -0
  112. package/lib/features/store/objects/components/documentEditingRun.d.ts +27 -0
  113. package/lib/features/store/objects/components/documentEditingRun.d.ts.map +1 -0
  114. package/lib/features/store/objects/components/documentEditingRun.js +126 -0
  115. package/lib/features/store/objects/components/documentEditingRun.js.map +1 -0
  116. package/lib/features/store/objects/components/documentEditingTarget.d.ts +20 -0
  117. package/lib/features/store/objects/components/documentEditingTarget.d.ts.map +1 -0
  118. package/lib/features/store/objects/components/documentEditingTarget.js +40 -0
  119. package/lib/features/store/objects/components/documentEditingTarget.js.map +1 -0
  120. package/lib/features/store/objects/components/index.d.ts +1 -0
  121. package/lib/features/store/objects/components/index.d.ts.map +1 -1
  122. package/lib/features/store/objects/components/index.js +1 -0
  123. package/lib/features/store/objects/components/index.js.map +1 -1
  124. package/lib/features/store/objects/components/useContentPanelHooks.d.ts +5 -1
  125. package/lib/features/store/objects/components/useContentPanelHooks.d.ts.map +1 -1
  126. package/lib/features/store/objects/components/useContentPanelHooks.js +53 -29
  127. package/lib/features/store/objects/components/useContentPanelHooks.js.map +1 -1
  128. package/lib/features/store/objects/components/useDownloadFile.d.ts +2 -1
  129. package/lib/features/store/objects/components/useDownloadFile.d.ts.map +1 -1
  130. package/lib/features/store/objects/components/useDownloadFile.js +3 -0
  131. package/lib/features/store/objects/components/useDownloadFile.js.map +1 -1
  132. package/lib/features/store/objects/selection/actions/StartWorkflowButton.js +1 -1
  133. package/lib/features/store/objects/selection/actions/StartWorkflowButton.js.map +1 -1
  134. package/lib/i18n/locales/ar.json +118 -1
  135. package/lib/i18n/locales/de.json +118 -1
  136. package/lib/i18n/locales/en.json +118 -0
  137. package/lib/i18n/locales/es.json +118 -1
  138. package/lib/i18n/locales/fr.json +118 -1
  139. package/lib/i18n/locales/it.json +118 -1
  140. package/lib/i18n/locales/ja.json +118 -1
  141. package/lib/i18n/locales/ko.json +118 -1
  142. package/lib/i18n/locales/pt.json +118 -1
  143. package/lib/i18n/locales/ru.json +118 -1
  144. package/lib/i18n/locales/tr.json +118 -1
  145. package/lib/i18n/locales/zh-TW.json +118 -1
  146. package/lib/i18n/locales/zh.json +118 -1
  147. package/lib/rich-text/EditorToolbar.d.ts +37 -0
  148. package/lib/rich-text/EditorToolbar.d.ts.map +1 -0
  149. package/lib/rich-text/EditorToolbar.js +215 -0
  150. package/lib/rich-text/EditorToolbar.js.map +1 -0
  151. package/lib/rich-text/VertesiaRichTextEditor.d.ts +26 -0
  152. package/lib/rich-text/VertesiaRichTextEditor.d.ts.map +1 -0
  153. package/lib/rich-text/VertesiaRichTextEditor.js +67 -0
  154. package/lib/rich-text/VertesiaRichTextEditor.js.map +1 -0
  155. package/lib/rich-text/index.d.ts +2 -0
  156. package/lib/rich-text/index.d.ts.map +1 -0
  157. package/lib/rich-text/index.js +2 -0
  158. package/lib/rich-text/index.js.map +1 -0
  159. package/lib/vertesia-ui-core.js +2 -2
  160. package/lib/vertesia-ui-core.js.map +1 -1
  161. package/lib/vertesia-ui-features.js +35 -30
  162. package/lib/vertesia-ui-features.js.map +1 -1
  163. package/lib/vertesia-ui-i18n.js +14 -14
  164. package/lib/vertesia-ui-i18n.js.map +1 -1
  165. package/lib/vertesia-ui-rich-text.js +5 -0
  166. package/lib/vertesia-ui-rich-text.js.map +1 -0
  167. package/lib/vertesia-ui-widgets.js +25 -7
  168. package/lib/vertesia-ui-widgets.js.map +1 -1
  169. package/lib/widgets/markdown/AgentResourceResolver.d.ts +31 -0
  170. package/lib/widgets/markdown/AgentResourceResolver.d.ts.map +1 -0
  171. package/lib/widgets/markdown/AgentResourceResolver.js +39 -0
  172. package/lib/widgets/markdown/AgentResourceResolver.js.map +1 -0
  173. package/lib/widgets/markdown/ArtifactEditingSurface.d.ts +63 -0
  174. package/lib/widgets/markdown/ArtifactEditingSurface.d.ts.map +1 -0
  175. package/lib/widgets/markdown/ArtifactEditingSurface.js +582 -0
  176. package/lib/widgets/markdown/ArtifactEditingSurface.js.map +1 -0
  177. package/lib/widgets/markdown/CollaborativeMarkdownRenderer.d.ts +69 -0
  178. package/lib/widgets/markdown/CollaborativeMarkdownRenderer.d.ts.map +1 -0
  179. package/lib/widgets/markdown/CollaborativeMarkdownRenderer.js +374 -0
  180. package/lib/widgets/markdown/CollaborativeMarkdownRenderer.js.map +1 -0
  181. package/lib/widgets/markdown/MarkdownLink.d.ts +3 -1
  182. package/lib/widgets/markdown/MarkdownLink.d.ts.map +1 -1
  183. package/lib/widgets/markdown/MarkdownLink.js +41 -14
  184. package/lib/widgets/markdown/MarkdownLink.js.map +1 -1
  185. package/lib/widgets/markdown/MarkdownRenderer.d.ts +8 -1
  186. package/lib/widgets/markdown/MarkdownRenderer.d.ts.map +1 -1
  187. package/lib/widgets/markdown/MarkdownRenderer.js +20 -4
  188. package/lib/widgets/markdown/MarkdownRenderer.js.map +1 -1
  189. package/lib/widgets/markdown/index.d.ts +5 -1
  190. package/lib/widgets/markdown/index.d.ts.map +1 -1
  191. package/lib/widgets/markdown/index.js +5 -1
  192. package/lib/widgets/markdown/index.js.map +1 -1
  193. package/lib/widgets/markdown/normalizeCustomSchemeLinks.d.ts.map +1 -1
  194. package/lib/widgets/markdown/normalizeCustomSchemeLinks.js +14 -2
  195. package/lib/widgets/markdown/normalizeCustomSchemeLinks.js.map +1 -1
  196. package/lib/widgets/markdown/textDiff.d.ts +52 -0
  197. package/lib/widgets/markdown/textDiff.d.ts.map +1 -0
  198. package/lib/widgets/markdown/textDiff.js +362 -0
  199. package/lib/widgets/markdown/textDiff.js.map +1 -0
  200. package/lib/widgets/markdown/useArtifactContent.d.ts +5 -3
  201. package/lib/widgets/markdown/useArtifactContent.d.ts.map +1 -1
  202. package/lib/widgets/markdown/useArtifactContent.js +6 -3
  203. package/lib/widgets/markdown/useArtifactContent.js.map +1 -1
  204. package/lib/widgets/markdown/useResolvedUrl.d.ts +1 -5
  205. package/lib/widgets/markdown/useResolvedUrl.d.ts.map +1 -1
  206. package/lib/widgets/markdown/useResolvedUrl.js +19 -31
  207. package/lib/widgets/markdown/useResolvedUrl.js.map +1 -1
  208. package/lib/widgets/xml-viewer/hooks/useXMLViewer.d.ts +9 -0
  209. package/lib/widgets/xml-viewer/hooks/useXMLViewer.d.ts.map +1 -1
  210. package/lib/widgets/xml-viewer/hooks/useXMLViewer.js +20 -17
  211. package/lib/widgets/xml-viewer/hooks/useXMLViewer.js.map +1 -1
  212. package/package.json +13 -9
  213. package/src/__tests__/a11y.test.tsx +4 -1
  214. package/src/__tests__/axe-helper.ts +17 -7
  215. package/src/__tests__/setup.ts +25 -0
  216. package/src/core/components/shadcn/filters/filterBar.tsx +1 -0
  217. package/src/core/components/shadcn/modal/dialog.tsx +3 -1
  218. package/src/core/components/shadcn/tabs.test.tsx +65 -0
  219. package/src/core/components/shadcn/tabs.tsx +25 -3
  220. package/src/features/agent/chat/AgentRightPanel.tsx +16 -1
  221. package/src/features/agent/chat/ArtifactsTab.test.tsx +55 -0
  222. package/src/features/agent/chat/ArtifactsTab.tsx +203 -52
  223. package/src/features/agent/chat/DocumentEditingActionCard.test.tsx +105 -0
  224. package/src/features/agent/chat/DocumentEditingActionCard.tsx +210 -0
  225. package/src/features/agent/chat/ModernAgentConversation.test.tsx +237 -40
  226. package/src/features/agent/chat/ModernAgentConversation.tsx +247 -75
  227. package/src/features/agent/chat/ModernAgentOutput/AgentMarkdownAnchor.test.tsx +79 -0
  228. package/src/features/agent/chat/ModernAgentOutput/AgentMarkdownAnchor.tsx +94 -0
  229. package/src/features/agent/chat/ModernAgentOutput/AllMessagesMixed.test.tsx +257 -34
  230. package/src/features/agent/chat/ModernAgentOutput/AllMessagesMixed.tsx +217 -105
  231. package/src/features/agent/chat/ModernAgentOutput/AttachmentPreview.tsx +17 -0
  232. package/src/features/agent/chat/ModernAgentOutput/CollapsibleAgentMarkdown.test.tsx +44 -0
  233. package/src/features/agent/chat/ModernAgentOutput/CollapsibleAgentMarkdown.tsx +88 -0
  234. package/src/features/agent/chat/ModernAgentOutput/MessageItem.tsx +30 -46
  235. package/src/features/agent/chat/ModernAgentOutput/ResourceChangeSummary.tsx +40 -0
  236. package/src/features/agent/chat/ModernAgentOutput/ResourceChip.test.tsx +148 -0
  237. package/src/features/agent/chat/ModernAgentOutput/ResourceChip.tsx +141 -0
  238. package/src/features/agent/chat/ModernAgentOutput/ToolCallGroup.tsx +33 -1
  239. package/src/features/agent/chat/ModernAgentOutput/resourceLinks.tsx +43 -0
  240. package/src/features/agent/chat/ModernAgentOutput/resourceSummary.test.ts +229 -0
  241. package/src/features/agent/chat/ModernAgentOutput/resourceSummary.ts +152 -0
  242. package/src/features/agent/chat/ModernAgentOutput/utils.test.ts +17 -0
  243. package/src/features/agent/chat/ModernAgentOutput/utils.ts +14 -1
  244. package/src/features/agent/chat/hooks/useAgentStream.test.tsx +188 -0
  245. package/src/features/agent/chat/hooks/useAgentStream.ts +28 -8
  246. package/src/features/agent/chat/index.ts +11 -0
  247. package/src/features/store/objects/DocumentSearchResults.tsx +2 -2
  248. package/src/features/store/objects/components/ContentOverview.tsx +216 -65
  249. package/src/features/store/objects/components/DocumentEditingConfigurationSelector.test.ts +34 -0
  250. package/src/features/store/objects/components/DocumentEditingConfigurationSelector.tsx +211 -0
  251. package/src/features/store/objects/components/DocumentEditingLockStatus.test.tsx +32 -0
  252. package/src/features/store/objects/components/DocumentEditingLockStatus.tsx +45 -0
  253. package/src/features/store/objects/components/DocumentEditingPanel.test.tsx +336 -0
  254. package/src/features/store/objects/components/DocumentEditingPanel.tsx +1236 -0
  255. package/src/features/store/objects/components/TextEditorPanel.test.tsx +48 -0
  256. package/src/features/store/objects/components/TextEditorPanel.tsx +41 -20
  257. package/src/features/store/objects/components/documentArtifactRefs.test.ts +65 -0
  258. package/src/features/store/objects/components/documentArtifactRefs.ts +72 -0
  259. package/src/features/store/objects/components/documentEditingAgentConfig.test.ts +28 -0
  260. package/src/features/store/objects/components/documentEditingAgentConfig.ts +41 -0
  261. package/src/features/store/objects/components/documentEditingPrompts.test.ts +26 -0
  262. package/src/features/store/objects/components/documentEditingPrompts.ts +12 -0
  263. package/src/features/store/objects/components/documentEditingRun.test.ts +176 -0
  264. package/src/features/store/objects/components/documentEditingRun.ts +184 -0
  265. package/src/features/store/objects/components/documentEditingTarget.test.ts +96 -0
  266. package/src/features/store/objects/components/documentEditingTarget.ts +63 -0
  267. package/src/features/store/objects/components/index.ts +1 -0
  268. package/src/features/store/objects/components/useContentPanelHooks.ts +52 -27
  269. package/src/features/store/objects/components/useDownloadFile.test.ts +20 -0
  270. package/src/features/store/objects/components/useDownloadFile.ts +5 -1
  271. package/src/features/store/objects/selection/actions/StartWorkflowButton.tsx +2 -2
  272. package/src/i18n/locales/ar.json +118 -1
  273. package/src/i18n/locales/de.json +118 -1
  274. package/src/i18n/locales/en.json +118 -0
  275. package/src/i18n/locales/es.json +118 -1
  276. package/src/i18n/locales/fr.json +118 -1
  277. package/src/i18n/locales/it.json +118 -1
  278. package/src/i18n/locales/ja.json +118 -1
  279. package/src/i18n/locales/ko.json +118 -1
  280. package/src/i18n/locales/pt.json +118 -1
  281. package/src/i18n/locales/ru.json +118 -1
  282. package/src/i18n/locales/tr.json +118 -1
  283. package/src/i18n/locales/zh-TW.json +118 -1
  284. package/src/i18n/locales/zh.json +118 -1
  285. package/src/rich-text/EditorToolbar.tsx +708 -0
  286. package/src/rich-text/VertesiaRichTextEditor.test.tsx +211 -0
  287. package/src/rich-text/VertesiaRichTextEditor.tsx +241 -0
  288. package/src/rich-text/index.ts +9 -0
  289. package/src/session/UserSession.test.ts +11 -11
  290. package/src/widgets/markdown/AgentResourceResolver.test.ts +24 -0
  291. package/src/widgets/markdown/AgentResourceResolver.tsx +70 -0
  292. package/src/widgets/markdown/ArtifactEditingSurface.test.tsx +537 -0
  293. package/src/widgets/markdown/ArtifactEditingSurface.tsx +878 -0
  294. package/src/widgets/markdown/CollaborativeMarkdownRenderer.test.tsx +484 -0
  295. package/src/widgets/markdown/CollaborativeMarkdownRenderer.tsx +825 -0
  296. package/src/widgets/markdown/MarkdownLink.test.tsx +122 -0
  297. package/src/widgets/markdown/MarkdownLink.tsx +102 -17
  298. package/src/widgets/markdown/MarkdownRenderer.tsx +30 -3
  299. package/src/widgets/markdown/index.ts +39 -1
  300. package/src/widgets/markdown/normalizeCustomSchemeLinks.ts +15 -2
  301. package/src/widgets/markdown/textDiff.test.ts +156 -0
  302. package/src/widgets/markdown/textDiff.ts +399 -0
  303. package/src/widgets/markdown/useArtifactContent.ts +9 -3
  304. package/src/widgets/markdown/useResolvedUrl.test.ts +29 -40
  305. package/src/widgets/markdown/useResolvedUrl.ts +33 -35
  306. package/src/widgets/xml-viewer/hooks/useXMLViewer.test.ts +26 -0
  307. package/src/widgets/xml-viewer/hooks/useXMLViewer.ts +23 -18
@@ -0,0 +1,484 @@
1
+ /** @vitest-environment jsdom */
2
+
3
+ import { cleanup, fireEvent, render, screen, waitFor, within } from '@testing-library/react';
4
+ import userEvent from '@testing-library/user-event';
5
+ import type { Element } from 'hast';
6
+ import { afterEach, describe, expect, it, vi } from 'vitest';
7
+ import { I18nProvider } from '../../i18n/index.js';
8
+ import {
9
+ applyMarkdownEditingChange,
10
+ CollaborativeMarkdownRenderer,
11
+ createMarkdownBlockAnchor,
12
+ formatMarkdownEditingAction,
13
+ type MarkdownEditingAction,
14
+ } from './CollaborativeMarkdownRenderer.js';
15
+
16
+ afterEach(() => {
17
+ cleanup();
18
+ });
19
+
20
+ function elementAt(start: number, end: number): Element {
21
+ return {
22
+ type: 'element',
23
+ tagName: 'p',
24
+ properties: {},
25
+ children: [],
26
+ position: {
27
+ start: { line: 1, column: start + 1, offset: start },
28
+ end: { line: 1, column: end + 1, offset: end },
29
+ },
30
+ };
31
+ }
32
+
33
+ describe('collaborative Markdown actions', () => {
34
+ it('anchors a block with its range and surrounding source context', () => {
35
+ const markdown = 'Before\n\nSelected paragraph\n\nAfter';
36
+ const start = markdown.indexOf('Selected');
37
+ const end = start + 'Selected paragraph'.length;
38
+
39
+ expect(createMarkdownBlockAnchor(markdown, elementAt(start, end), 'paragraph')).toEqual({
40
+ block_id: `paragraph:${start}:${end}`,
41
+ block_type: 'paragraph',
42
+ source_range: { start, end },
43
+ exact_text: 'Selected paragraph',
44
+ prefix: 'Before\n\n',
45
+ suffix: '\n\nAfter',
46
+ occurrence_index: 0,
47
+ });
48
+ });
49
+
50
+ it('disambiguates repeated blocks under the same heading', () => {
51
+ const markdown = '# Section\n\nRepeated\n\nRepeated';
52
+ const start = markdown.lastIndexOf('Repeated');
53
+ const end = start + 'Repeated'.length;
54
+
55
+ expect(createMarkdownBlockAnchor(markdown, elementAt(start, end), 'paragraph')).toEqual(
56
+ expect.objectContaining({
57
+ heading_path: ['Section'],
58
+ exact_text: 'Repeated',
59
+ occurrence_index: 1,
60
+ }),
61
+ );
62
+ });
63
+
64
+ it('formats a direct artifact edit as an actionable agent message', () => {
65
+ const action: MarkdownEditingAction = {
66
+ operation_id: 'operation-1',
67
+ resource: { kind: 'agent_artifact', run_id: 'run-1', path: 'draft.md' },
68
+ base_version: 'etag-1',
69
+ action: 'edit',
70
+ anchor: {
71
+ block_id: 'paragraph:0:3',
72
+ block_type: 'paragraph',
73
+ exact_text: 'Old',
74
+ },
75
+ user_change: { before: 'Old', after: 'New' },
76
+ };
77
+
78
+ expect(formatMarkdownEditingAction(action)).toContain('artifact:draft.md (run run-1)');
79
+ expect(formatMarkdownEditingAction(action)).toContain('Before:\n```markdown\nOld');
80
+ expect(formatMarkdownEditingAction(action)).toContain('After:\n```markdown\nNew');
81
+ });
82
+
83
+ it('uses a longer message fence when selected source contains a fenced code block', () => {
84
+ const action: MarkdownEditingAction = {
85
+ operation_id: 'operation-1',
86
+ resource: { kind: 'agent_artifact', run_id: 'run-1', path: 'draft.md' },
87
+ action: 'comment',
88
+ anchor: {
89
+ block_id: 'code_block:0:21',
90
+ block_type: 'code_block',
91
+ exact_text: '```ts\nconst n = 1;\n```',
92
+ },
93
+ comment: 'Rename this variable.',
94
+ };
95
+
96
+ expect(formatMarkdownEditingAction(action)).toContain(
97
+ 'Selected content:\n````markdown\n```ts\nconst n = 1;\n```\n````',
98
+ );
99
+ });
100
+
101
+ it('submits a comment with the selected source block and version', async () => {
102
+ const onAction = vi.fn();
103
+ render(
104
+ <I18nProvider lng="en">
105
+ <CollaborativeMarkdownRenderer
106
+ resource={{ kind: 'store_document', document_id: 'document-1' }}
107
+ baseVersion="etag-1"
108
+ onAction={onAction}
109
+ >
110
+ {'First paragraph.\n\nSecond paragraph.'}
111
+ </CollaborativeMarkdownRenderer>
112
+ </I18nProvider>,
113
+ );
114
+
115
+ const selectedBlock = screen.getByText('Second paragraph.').parentElement;
116
+ if (!selectedBlock) throw new Error('Expected the paragraph to have a collaborative block parent');
117
+ fireEvent.click(within(selectedBlock).getByRole('button', { name: 'Comment on selection' }));
118
+ fireEvent.change(within(selectedBlock).getByRole('textbox'), {
119
+ target: { value: 'Make this more specific.' },
120
+ });
121
+ fireEvent.click(screen.getByRole('button', { name: 'Send' }));
122
+
123
+ await waitFor(() => expect(onAction).toHaveBeenCalledTimes(1));
124
+ expect(onAction).toHaveBeenCalledWith(
125
+ expect.objectContaining({
126
+ resource: { kind: 'store_document', document_id: 'document-1' },
127
+ base_version: 'etag-1',
128
+ action: 'comment',
129
+ comment: 'Make this more specific.',
130
+ anchor: expect.objectContaining({
131
+ block_type: 'paragraph',
132
+ exact_text: 'Second paragraph.',
133
+ }),
134
+ }),
135
+ );
136
+ });
137
+
138
+ it('briefly highlights blocks that changed between document revisions', async () => {
139
+ const onAction = vi.fn();
140
+ const { rerender } = render(
141
+ <I18nProvider lng="en">
142
+ <CollaborativeMarkdownRenderer
143
+ resource={{ kind: 'store_document', document_id: 'document-1' }}
144
+ onAction={onAction}
145
+ >
146
+ {'Original paragraph.'}
147
+ </CollaborativeMarkdownRenderer>
148
+ </I18nProvider>,
149
+ );
150
+
151
+ rerender(
152
+ <I18nProvider lng="en">
153
+ <CollaborativeMarkdownRenderer
154
+ resource={{ kind: 'store_document', document_id: 'document-2' }}
155
+ highlightChangesFrom="Original paragraph."
156
+ highlightVersion={1}
157
+ onAction={onAction}
158
+ >
159
+ {'Updated paragraph.'}
160
+ </CollaborativeMarkdownRenderer>
161
+ </I18nProvider>,
162
+ );
163
+
164
+ await waitFor(() => {
165
+ expect(screen.getByText('Updated paragraph.').parentElement?.className).toContain('bg-mixer-success/15');
166
+ });
167
+ });
168
+
169
+ it('preserves a typed draft when a document refresh invalidates its block anchor', async () => {
170
+ const onAction = vi.fn();
171
+ const { rerender } = render(
172
+ <I18nProvider lng="en">
173
+ <CollaborativeMarkdownRenderer
174
+ resource={{ kind: 'store_document', document_id: 'document-1' }}
175
+ onAction={onAction}
176
+ >
177
+ {'Original paragraph.'}
178
+ </CollaborativeMarkdownRenderer>
179
+ </I18nProvider>,
180
+ );
181
+
182
+ const selectedBlock = screen.getByText('Original paragraph.').parentElement;
183
+ if (!selectedBlock) throw new Error('Expected a collaborative block parent');
184
+ fireEvent.click(within(selectedBlock).getByRole('button', { name: 'Comment on selection' }));
185
+ fireEvent.change(within(selectedBlock).getByRole('textbox'), {
186
+ target: { value: 'Keep this draft recoverable.' },
187
+ });
188
+
189
+ rerender(
190
+ <I18nProvider lng="en">
191
+ <CollaborativeMarkdownRenderer
192
+ resource={{ kind: 'store_document', document_id: 'document-2' }}
193
+ onAction={onAction}
194
+ >
195
+ {'Inserted paragraph.\n\nOriginal paragraph.'}
196
+ </CollaborativeMarkdownRenderer>
197
+ </I18nProvider>,
198
+ );
199
+
200
+ await waitFor(() => {
201
+ expect(screen.getByText('Your draft was preserved')).not.toBeNull();
202
+ expect(screen.getByDisplayValue('Keep this draft recoverable.')).not.toBeNull();
203
+ });
204
+ });
205
+
206
+ it('keeps source anchors aligned when normal rendering would rewrite earlier Markdown', async () => {
207
+ const onAction = vi.fn();
208
+ render(
209
+ <I18nProvider lng="en">
210
+ <CollaborativeMarkdownRenderer
211
+ resource={{ kind: 'store_document', document_id: 'document-1' }}
212
+ onAction={onAction}
213
+ >
214
+ {'Revenue was between $100M and $500M.\n\nKeep this exact.'}
215
+ </CollaborativeMarkdownRenderer>
216
+ </I18nProvider>,
217
+ );
218
+
219
+ const selectedBlock = screen.getByText('Keep this exact.').parentElement;
220
+ if (!selectedBlock) throw new Error('Expected the paragraph to have a collaborative block parent');
221
+ fireEvent.click(within(selectedBlock).getByRole('button', { name: 'Comment on selection' }));
222
+ fireEvent.change(within(selectedBlock).getByRole('textbox'), {
223
+ target: { value: 'Add evidence.' },
224
+ });
225
+ fireEvent.click(screen.getByRole('button', { name: 'Send' }));
226
+
227
+ await waitFor(() => expect(onAction).toHaveBeenCalledTimes(1));
228
+ expect(onAction).toHaveBeenCalledWith(
229
+ expect.objectContaining({
230
+ anchor: expect.objectContaining({
231
+ exact_text: 'Keep this exact.',
232
+ source_range: {
233
+ start: 'Revenue was between $100M and $500M.\n\n'.length,
234
+ end: 'Revenue was between $100M and $500M.\n\nKeep this exact.'.length,
235
+ },
236
+ }),
237
+ }),
238
+ );
239
+ });
240
+
241
+ it('hides editing controls on a read-only surface', () => {
242
+ render(
243
+ <I18nProvider lng="en">
244
+ <CollaborativeMarkdownRenderer
245
+ resource={{ kind: 'agent_artifact', run_id: 'run-1', path: 'draft.md' }}
246
+ readOnly
247
+ onAction={vi.fn()}
248
+ >
249
+ {'Read only paragraph.'}
250
+ </CollaborativeMarkdownRenderer>
251
+ </I18nProvider>,
252
+ );
253
+
254
+ expect(screen.queryByRole('button', { name: 'Comment on selection' })).toBeNull();
255
+ expect(screen.queryByRole('button', { name: 'Edit selection' })).toBeNull();
256
+ });
257
+
258
+ it('keeps comments enabled while content mutations are locked', async () => {
259
+ const onAction = vi.fn();
260
+ render(
261
+ <I18nProvider lng="en">
262
+ <CollaborativeMarkdownRenderer
263
+ resource={{ kind: 'agent_artifact', run_id: 'run-1', path: 'draft.md' }}
264
+ readOnly
265
+ allowComments
266
+ onAction={onAction}
267
+ >
268
+ {'Locked paragraph.'}
269
+ </CollaborativeMarkdownRenderer>
270
+ </I18nProvider>,
271
+ );
272
+
273
+ expect(screen.queryByRole('button', { name: 'Edit selection' })).toBeNull();
274
+ fireEvent.click(screen.getByRole('button', { name: 'Comment on selection' }));
275
+ fireEvent.change(screen.getByRole('textbox'), { target: { value: 'Add supporting evidence.' } });
276
+ fireEvent.click(screen.getByRole('button', { name: 'Send' }));
277
+
278
+ await waitFor(() => expect(onAction).toHaveBeenCalledTimes(1));
279
+ expect(onAction).toHaveBeenCalledWith(
280
+ expect.objectContaining({
281
+ action: 'comment',
282
+ comment: 'Add supporting evidence.',
283
+ anchor: expect.objectContaining({ exact_text: 'Locked paragraph.' }),
284
+ }),
285
+ );
286
+ });
287
+
288
+ it('prevents an open component editor from submitting after the surface becomes read-only', () => {
289
+ const onAction = vi.fn();
290
+ const view = render(
291
+ <I18nProvider lng="en">
292
+ <CollaborativeMarkdownRenderer
293
+ resource={{ kind: 'agent_artifact', run_id: 'run-1', path: 'draft.md' }}
294
+ onAction={onAction}
295
+ >
296
+ {'Editable paragraph.'}
297
+ </CollaborativeMarkdownRenderer>
298
+ </I18nProvider>,
299
+ );
300
+
301
+ fireEvent.click(screen.getByRole('button', { name: 'Comment on selection' }));
302
+ fireEvent.change(screen.getByRole('textbox'), { target: { value: 'Keep this draft.' } });
303
+
304
+ view.rerender(
305
+ <I18nProvider lng="en">
306
+ <CollaborativeMarkdownRenderer
307
+ resource={{ kind: 'agent_artifact', run_id: 'run-1', path: 'draft.md' }}
308
+ readOnly
309
+ onAction={onAction}
310
+ >
311
+ {'Editable paragraph.'}
312
+ </CollaborativeMarkdownRenderer>
313
+ </I18nProvider>,
314
+ );
315
+
316
+ expect(screen.getByRole('textbox')).toHaveProperty('disabled', true);
317
+ const sendButton = screen.getByRole('button', { name: 'Send' });
318
+ expect(sendButton).toHaveProperty('disabled', true);
319
+ fireEvent.click(sendButton);
320
+ expect(onAction).not.toHaveBeenCalled();
321
+ });
322
+
323
+ it('selects a list as one group instead of individual bullets', async () => {
324
+ const onAction = vi.fn();
325
+ const markdown = '- First bullet\n- Second bullet';
326
+ render(
327
+ <I18nProvider lng="en">
328
+ <CollaborativeMarkdownRenderer
329
+ resource={{ kind: 'store_document', document_id: 'document-1' }}
330
+ onAction={onAction}
331
+ >
332
+ {markdown}
333
+ </CollaborativeMarkdownRenderer>
334
+ </I18nProvider>,
335
+ );
336
+
337
+ // One control set for the whole list, none per bullet.
338
+ expect(screen.getAllByRole('button', { name: 'Comment on selection' })).toHaveLength(1);
339
+
340
+ fireEvent.click(screen.getByRole('button', { name: 'Edit selection' }));
341
+ fireEvent.change(screen.getByRole('textbox'), {
342
+ target: { value: '- First bullet\n- Second bullet\n- Third bullet' },
343
+ });
344
+ fireEvent.click(screen.getByRole('button', { name: 'Send' }));
345
+
346
+ await waitFor(() => expect(onAction).toHaveBeenCalledTimes(1));
347
+ expect(onAction).toHaveBeenCalledWith(
348
+ expect.objectContaining({
349
+ action: 'edit',
350
+ anchor: expect.objectContaining({
351
+ block_type: 'list',
352
+ exact_text: '- First bullet\n- Second bullet',
353
+ }),
354
+ user_change: {
355
+ before: '- First bullet\n- Second bullet',
356
+ after: '- First bullet\n- Second bullet\n- Third bullet',
357
+ },
358
+ }),
359
+ );
360
+ });
361
+
362
+ it('uses the rich component editor for a selected block', async () => {
363
+ // delay:null types synchronously so ProseMirror doesn't drop characters between renders.
364
+ const user = userEvent.setup({ delay: null });
365
+ const onAction = vi.fn();
366
+ render(
367
+ <I18nProvider lng="en">
368
+ <CollaborativeMarkdownRenderer
369
+ resource={{ kind: 'store_document', document_id: 'document-1' }}
370
+ onAction={onAction}
371
+ >
372
+ {'Original paragraph.'}
373
+ </CollaborativeMarkdownRenderer>
374
+ </I18nProvider>,
375
+ );
376
+
377
+ fireEvent.click(screen.getByRole('button', { name: 'Edit selection' }));
378
+ const editor = await screen.findByRole('textbox');
379
+ // Wait for the draft to hydrate, then select the whole paragraph and paste the replacement
380
+ // in one operation — char-by-char typing races ProseMirror in jsdom and drops chars.
381
+ await waitFor(() => expect(editor.textContent ?? '').toContain('Original paragraph.'));
382
+ await user.tripleClick(editor);
383
+ await user.paste('Revised paragraph.');
384
+ fireEvent.click(screen.getByRole('button', { name: 'Send' }));
385
+
386
+ await waitFor(() => expect(onAction).toHaveBeenCalledTimes(1));
387
+ expect(onAction).toHaveBeenCalledWith(
388
+ expect.objectContaining({
389
+ action: 'edit',
390
+ user_change: {
391
+ before: 'Original paragraph.',
392
+ after: expect.stringContaining('Revised paragraph.'),
393
+ },
394
+ }),
395
+ );
396
+ });
397
+
398
+ it('inserts a new component after a selected block as an already-applicable edit', async () => {
399
+ const user = userEvent.setup({ delay: null });
400
+ const onAction = vi.fn();
401
+ render(
402
+ <I18nProvider lng="en">
403
+ <CollaborativeMarkdownRenderer
404
+ resource={{ kind: 'agent_artifact', run_id: 'run-1', path: 'draft.md' }}
405
+ onAction={onAction}
406
+ >
407
+ {'Original paragraph.'}
408
+ </CollaborativeMarkdownRenderer>
409
+ </I18nProvider>,
410
+ );
411
+
412
+ await user.click(screen.getByRole('button', { name: 'Insert component after this block' }));
413
+ await user.click(await screen.findByRole('menuitem', { name: 'Paragraph' }));
414
+
415
+ const editor = await screen.findByRole('textbox');
416
+ await user.click(editor);
417
+ // Paste in one operation — char-by-char typing races ProseMirror in jsdom and drops chars.
418
+ await user.paste('Inserted paragraph.');
419
+ await waitFor(() => expect(editor.textContent ?? '').toContain('Inserted paragraph.'));
420
+ fireEvent.click(screen.getByRole('button', { name: 'Send' }));
421
+
422
+ await waitFor(() => expect(onAction).toHaveBeenCalledTimes(1));
423
+ expect(onAction).toHaveBeenCalledWith(
424
+ expect.objectContaining({
425
+ action: 'edit',
426
+ user_change: {
427
+ before: 'Original paragraph.',
428
+ after: expect.stringMatching(/^Original paragraph\.\n\n.*Inserted paragraph\.$/),
429
+ },
430
+ }),
431
+ );
432
+ });
433
+
434
+ it('applies an anchored edit to the markdown source', () => {
435
+ const markdown = '# Title\n\n- First bullet\n- Second bullet\n\nTail paragraph.';
436
+ const start = markdown.indexOf('- First');
437
+ const end = markdown.indexOf('\n\nTail');
438
+ const action: MarkdownEditingAction = {
439
+ operation_id: 'operation-1',
440
+ resource: { kind: 'store_document', document_id: 'document-1' },
441
+ action: 'edit',
442
+ anchor: {
443
+ block_id: `list:${start}:${end}`,
444
+ block_type: 'list',
445
+ source_range: { start, end },
446
+ exact_text: markdown.slice(start, end),
447
+ },
448
+ user_change: {
449
+ before: markdown.slice(start, end),
450
+ after: '- First bullet\n- Second bullet\n- Third bullet',
451
+ },
452
+ };
453
+
454
+ expect(applyMarkdownEditingChange(markdown, action)).toBe(
455
+ '# Title\n\n- First bullet\n- Second bullet\n- Third bullet\n\nTail paragraph.',
456
+ );
457
+ });
458
+
459
+ it('recovers a shifted anchor through its prefix context and rejects ambiguity', () => {
460
+ const shifted: MarkdownEditingAction = {
461
+ operation_id: 'operation-2',
462
+ resource: { kind: 'store_document', document_id: 'document-1' },
463
+ action: 'edit',
464
+ anchor: {
465
+ block_id: 'paragraph:0:0',
466
+ block_type: 'paragraph',
467
+ source_range: { start: 0, end: 6 },
468
+ exact_text: 'Target',
469
+ prefix: 'Intro.\n\n',
470
+ },
471
+ user_change: { before: 'Target', after: 'Changed' },
472
+ };
473
+
474
+ // The range no longer matches, but the prefix disambiguates the occurrence.
475
+ expect(applyMarkdownEditingChange('Header.\n\nIntro.\n\nTarget', shifted)).toBe('Header.\n\nIntro.\n\nChanged');
476
+ // Range mismatch, two occurrences, and no usable prefix: refuse to guess.
477
+ expect(
478
+ applyMarkdownEditingChange('Intro.\n\nTarget\n\nTarget', {
479
+ ...shifted,
480
+ anchor: { ...shifted.anchor, prefix: undefined },
481
+ }),
482
+ ).toBeUndefined();
483
+ });
484
+ });