@vertesia/ui 1.4.0-dev.20260615.042549Z → 1.4.0-dev.20260629.130134Z

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 (337) hide show
  1. package/lib/core/components/shadcn/dropdown.d.ts.map +1 -1
  2. package/lib/core/components/shadcn/dropdown.js +6 -2
  3. package/lib/core/components/shadcn/dropdown.js.map +1 -1
  4. package/lib/core/components/shadcn/filters/filterBar.d.ts.map +1 -1
  5. package/lib/core/components/shadcn/filters/filterBar.js +9 -2
  6. package/lib/core/components/shadcn/filters/filterBar.js.map +1 -1
  7. package/lib/core/components/shadcn/modal/ConfirmModal.d.ts +16 -1
  8. package/lib/core/components/shadcn/modal/ConfirmModal.d.ts.map +1 -1
  9. package/lib/core/components/shadcn/modal/ConfirmModal.js +25 -3
  10. package/lib/core/components/shadcn/modal/ConfirmModal.js.map +1 -1
  11. package/lib/core/components/shadcn/modal/dialog.js +1 -1
  12. package/lib/core/components/shadcn/modal/dialog.js.map +1 -1
  13. package/lib/core/components/shadcn/popover.d.ts.map +1 -1
  14. package/lib/core/components/shadcn/popover.js +3 -1
  15. package/lib/core/components/shadcn/popover.js.map +1 -1
  16. package/lib/core/components/shadcn/switch.js +3 -3
  17. package/lib/core/components/shadcn/switch.js.map +1 -1
  18. package/lib/core/components/shadcn/tabs.js +1 -1
  19. package/lib/core/components/shadcn/tabs.js.map +1 -1
  20. package/lib/core/components/shadcn/tooltip.d.ts.map +1 -1
  21. package/lib/core/components/shadcn/tooltip.js +3 -1
  22. package/lib/core/components/shadcn/tooltip.js.map +1 -1
  23. package/lib/env/index.d.ts +0 -19
  24. package/lib/env/index.d.ts.map +1 -1
  25. package/lib/env/index.js +0 -6
  26. package/lib/env/index.js.map +1 -1
  27. package/lib/features/agent/PayloadBuilder.d.ts +4 -0
  28. package/lib/features/agent/PayloadBuilder.d.ts.map +1 -1
  29. package/lib/features/agent/PayloadBuilder.js +16 -0
  30. package/lib/features/agent/PayloadBuilder.js.map +1 -1
  31. package/lib/features/agent/chat/AgentApprovalModeSelector.d.ts +10 -0
  32. package/lib/features/agent/chat/AgentApprovalModeSelector.d.ts.map +1 -0
  33. package/lib/features/agent/chat/AgentApprovalModeSelector.js +50 -0
  34. package/lib/features/agent/chat/AgentApprovalModeSelector.js.map +1 -0
  35. package/lib/features/agent/chat/AgentChatFixtureReplay.d.ts +2 -1
  36. package/lib/features/agent/chat/AgentChatFixtureReplay.d.ts.map +1 -1
  37. package/lib/features/agent/chat/AgentChatFixtureReplay.js +3 -3
  38. package/lib/features/agent/chat/AgentChatFixtureReplay.js.map +1 -1
  39. package/lib/features/agent/chat/AgentRequestInputOverlay.d.ts +5 -2
  40. package/lib/features/agent/chat/AgentRequestInputOverlay.d.ts.map +1 -1
  41. package/lib/features/agent/chat/AgentRequestInputOverlay.js +41 -7
  42. package/lib/features/agent/chat/AgentRequestInputOverlay.js.map +1 -1
  43. package/lib/features/agent/chat/AgentRightPanel.d.ts.map +1 -1
  44. package/lib/features/agent/chat/AgentRightPanel.js +133 -12
  45. package/lib/features/agent/chat/AgentRightPanel.js.map +1 -1
  46. package/lib/features/agent/chat/AnimatedThinkingDots.js +1 -1
  47. package/lib/features/agent/chat/AnimatedThinkingDots.js.map +1 -1
  48. package/lib/features/agent/chat/ArtifactsTab.d.ts.map +1 -1
  49. package/lib/features/agent/chat/ArtifactsTab.js +11 -65
  50. package/lib/features/agent/chat/ArtifactsTab.js.map +1 -1
  51. package/lib/features/agent/chat/AskUserWidget.d.ts +3 -1
  52. package/lib/features/agent/chat/AskUserWidget.d.ts.map +1 -1
  53. package/lib/features/agent/chat/AskUserWidget.js +4 -3
  54. package/lib/features/agent/chat/AskUserWidget.js.map +1 -1
  55. package/lib/features/agent/chat/ModernAgentConversation.d.ts +10 -2
  56. package/lib/features/agent/chat/ModernAgentConversation.d.ts.map +1 -1
  57. package/lib/features/agent/chat/ModernAgentConversation.js +526 -117
  58. package/lib/features/agent/chat/ModernAgentConversation.js.map +1 -1
  59. package/lib/features/agent/chat/ModernAgentOutput/ActiveWorkstreamsSummary.d.ts +8 -0
  60. package/lib/features/agent/chat/ModernAgentOutput/ActiveWorkstreamsSummary.d.ts.map +1 -0
  61. package/lib/features/agent/chat/ModernAgentOutput/ActiveWorkstreamsSummary.js +19 -0
  62. package/lib/features/agent/chat/ModernAgentOutput/ActiveWorkstreamsSummary.js.map +1 -0
  63. package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.d.ts +8 -2
  64. package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.d.ts.map +1 -1
  65. package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.js +551 -92
  66. package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.js.map +1 -1
  67. package/lib/features/agent/chat/ModernAgentOutput/AttachmentPreview.d.ts.map +1 -1
  68. package/lib/features/agent/chat/ModernAgentOutput/AttachmentPreview.js +7 -6
  69. package/lib/features/agent/chat/ModernAgentOutput/AttachmentPreview.js.map +1 -1
  70. package/lib/features/agent/chat/ModernAgentOutput/Header.js +2 -2
  71. package/lib/features/agent/chat/ModernAgentOutput/Header.js.map +1 -1
  72. package/lib/features/agent/chat/ModernAgentOutput/MessageDeliveryStatus.d.ts +8 -0
  73. package/lib/features/agent/chat/ModernAgentOutput/MessageDeliveryStatus.d.ts.map +1 -0
  74. package/lib/features/agent/chat/ModernAgentOutput/MessageDeliveryStatus.js +61 -0
  75. package/lib/features/agent/chat/ModernAgentOutput/MessageDeliveryStatus.js.map +1 -0
  76. package/lib/features/agent/chat/ModernAgentOutput/MessageInput.d.ts +15 -2
  77. package/lib/features/agent/chat/ModernAgentOutput/MessageInput.d.ts.map +1 -1
  78. package/lib/features/agent/chat/ModernAgentOutput/MessageInput.js +28 -38
  79. package/lib/features/agent/chat/ModernAgentOutput/MessageInput.js.map +1 -1
  80. package/lib/features/agent/chat/ModernAgentOutput/MessageItem.d.ts +1 -1
  81. package/lib/features/agent/chat/ModernAgentOutput/MessageItem.d.ts.map +1 -1
  82. package/lib/features/agent/chat/ModernAgentOutput/MessageItem.js +3 -2
  83. package/lib/features/agent/chat/ModernAgentOutput/MessageItem.js.map +1 -1
  84. package/lib/features/agent/chat/ModernAgentOutput/SlideInPanel.js +2 -1
  85. package/lib/features/agent/chat/ModernAgentOutput/SlideInPanel.js.map +1 -1
  86. package/lib/features/agent/chat/ModernAgentOutput/SlidingMessages.js +1 -1
  87. package/lib/features/agent/chat/ModernAgentOutput/SlidingMessages.js.map +1 -1
  88. package/lib/features/agent/chat/ModernAgentOutput/SummaryConversation.d.ts +5 -0
  89. package/lib/features/agent/chat/ModernAgentOutput/SummaryConversation.d.ts.map +1 -1
  90. package/lib/features/agent/chat/ModernAgentOutput/SummaryConversation.js +59 -4
  91. package/lib/features/agent/chat/ModernAgentOutput/SummaryConversation.js.map +1 -1
  92. package/lib/features/agent/chat/ModernAgentOutput/WorkstreamTabs.js +2 -2
  93. package/lib/features/agent/chat/ModernAgentOutput/WorkstreamTabs.js.map +1 -1
  94. package/lib/features/agent/chat/ModernAgentOutput/requestInputMessages.d.ts +9 -0
  95. package/lib/features/agent/chat/ModernAgentOutput/requestInputMessages.d.ts.map +1 -1
  96. package/lib/features/agent/chat/ModernAgentOutput/requestInputMessages.js +180 -0
  97. package/lib/features/agent/chat/ModernAgentOutput/requestInputMessages.js.map +1 -1
  98. package/lib/features/agent/chat/ModernAgentOutput/utils.d.ts +6 -0
  99. package/lib/features/agent/chat/ModernAgentOutput/utils.d.ts.map +1 -1
  100. package/lib/features/agent/chat/ModernAgentOutput/utils.js +92 -2
  101. package/lib/features/agent/chat/ModernAgentOutput/utils.js.map +1 -1
  102. package/lib/features/agent/chat/clipboardFiles.d.ts +15 -0
  103. package/lib/features/agent/chat/clipboardFiles.d.ts.map +1 -0
  104. package/lib/features/agent/chat/clipboardFiles.js +35 -0
  105. package/lib/features/agent/chat/clipboardFiles.js.map +1 -0
  106. package/lib/features/agent/chat/hooks/useAgentStream.d.ts +6 -0
  107. package/lib/features/agent/chat/hooks/useAgentStream.d.ts.map +1 -1
  108. package/lib/features/agent/chat/hooks/useAgentStream.js +218 -37
  109. package/lib/features/agent/chat/hooks/useAgentStream.js.map +1 -1
  110. package/lib/features/agent/chat/hooks/useArtifacts.d.ts +1 -8
  111. package/lib/features/agent/chat/hooks/useArtifacts.d.ts.map +1 -1
  112. package/lib/features/agent/chat/hooks/useArtifacts.js +10 -28
  113. package/lib/features/agent/chat/hooks/useArtifacts.js.map +1 -1
  114. package/lib/features/agent/chat/index.d.ts +2 -1
  115. package/lib/features/agent/chat/index.d.ts.map +1 -1
  116. package/lib/features/agent/chat/index.js +2 -1
  117. package/lib/features/agent/chat/index.js.map +1 -1
  118. package/lib/features/agent/chat/workstreams.d.ts +1 -0
  119. package/lib/features/agent/chat/workstreams.d.ts.map +1 -1
  120. package/lib/features/agent/chat/workstreams.js +28 -0
  121. package/lib/features/agent/chat/workstreams.js.map +1 -1
  122. package/lib/features/facets/AgentRunnerFacetsNav.d.ts +10 -1
  123. package/lib/features/facets/AgentRunnerFacetsNav.d.ts.map +1 -1
  124. package/lib/features/facets/AgentRunnerFacetsNav.js +6 -3
  125. package/lib/features/facets/AgentRunnerFacetsNav.js.map +1 -1
  126. package/lib/features/facets/CollectionsFacetsNav.d.ts +10 -1
  127. package/lib/features/facets/CollectionsFacetsNav.d.ts.map +1 -1
  128. package/lib/features/facets/CollectionsFacetsNav.js +14 -5
  129. package/lib/features/facets/CollectionsFacetsNav.js.map +1 -1
  130. package/lib/features/facets/PromptsFacetsNav.d.ts +10 -1
  131. package/lib/features/facets/PromptsFacetsNav.d.ts.map +1 -1
  132. package/lib/features/facets/PromptsFacetsNav.js +14 -5
  133. package/lib/features/facets/PromptsFacetsNav.js.map +1 -1
  134. package/lib/features/facets/RunsFacetsNav.d.ts +10 -1
  135. package/lib/features/facets/RunsFacetsNav.d.ts.map +1 -1
  136. package/lib/features/facets/RunsFacetsNav.js +14 -5
  137. package/lib/features/facets/RunsFacetsNav.js.map +1 -1
  138. package/lib/features/index.d.ts +0 -1
  139. package/lib/features/index.d.ts.map +1 -1
  140. package/lib/features/index.js +0 -1
  141. package/lib/features/index.js.map +1 -1
  142. package/lib/features/oauth/McpConnectionsButton.d.ts +30 -0
  143. package/lib/features/oauth/McpConnectionsButton.d.ts.map +1 -0
  144. package/lib/features/oauth/McpConnectionsButton.js +70 -0
  145. package/lib/features/oauth/McpConnectionsButton.js.map +1 -0
  146. package/lib/features/oauth/McpConnectionsDialog.d.ts +25 -0
  147. package/lib/features/oauth/McpConnectionsDialog.d.ts.map +1 -0
  148. package/lib/features/oauth/McpConnectionsDialog.js +26 -0
  149. package/lib/features/oauth/McpConnectionsDialog.js.map +1 -0
  150. package/lib/features/oauth/RemoteMcpConnectionButton.d.ts.map +1 -1
  151. package/lib/features/oauth/RemoteMcpConnectionButton.js +14 -6
  152. package/lib/features/oauth/RemoteMcpConnectionButton.js.map +1 -1
  153. package/lib/features/oauth/index.d.ts +3 -0
  154. package/lib/features/oauth/index.d.ts.map +1 -1
  155. package/lib/features/oauth/index.js +3 -0
  156. package/lib/features/oauth/index.js.map +1 -1
  157. package/lib/features/oauth/useMcpConnections.d.ts +44 -0
  158. package/lib/features/oauth/useMcpConnections.d.ts.map +1 -0
  159. package/lib/features/oauth/useMcpConnections.js +168 -0
  160. package/lib/features/oauth/useMcpConnections.js.map +1 -0
  161. package/lib/features/permissions/UserPermissionsProvider.d.ts +4 -6
  162. package/lib/features/permissions/UserPermissionsProvider.d.ts.map +1 -1
  163. package/lib/features/permissions/UserPermissionsProvider.js +40 -42
  164. package/lib/features/permissions/UserPermissionsProvider.js.map +1 -1
  165. package/lib/features/store/objects/DocumentPreviewPanel.d.ts.map +1 -1
  166. package/lib/features/store/objects/DocumentPreviewPanel.js +2 -1
  167. package/lib/features/store/objects/DocumentPreviewPanel.js.map +1 -1
  168. package/lib/features/store/objects/DocumentQuickFilter.d.ts +23 -0
  169. package/lib/features/store/objects/DocumentQuickFilter.d.ts.map +1 -0
  170. package/lib/features/store/objects/DocumentQuickFilter.js +30 -0
  171. package/lib/features/store/objects/DocumentQuickFilter.js.map +1 -0
  172. package/lib/features/store/objects/DocumentSearchResults.d.ts.map +1 -1
  173. package/lib/features/store/objects/DocumentSearchResults.js +17 -1
  174. package/lib/features/store/objects/DocumentSearchResults.js.map +1 -1
  175. package/lib/features/store/objects/components/ContentOverview.d.ts.map +1 -1
  176. package/lib/features/store/objects/components/ContentOverview.js +17 -74
  177. package/lib/features/store/objects/components/ContentOverview.js.map +1 -1
  178. package/lib/features/store/objects/layout/DocumentTableColumn.d.ts +7 -1
  179. package/lib/features/store/objects/layout/DocumentTableColumn.d.ts.map +1 -1
  180. package/lib/features/store/objects/layout/DocumentTableColumn.js +27 -3
  181. package/lib/features/store/objects/layout/DocumentTableColumn.js.map +1 -1
  182. package/lib/features/store/objects/layout/documentLayout.js +1 -1
  183. package/lib/features/store/objects/layout/renderers.d.ts +2 -1
  184. package/lib/features/store/objects/layout/renderers.d.ts.map +1 -1
  185. package/lib/features/store/objects/layout/renderers.js +27 -20
  186. package/lib/features/store/objects/layout/renderers.js.map +1 -1
  187. package/lib/features/store/types/ContentObjectTypesSearch.d.ts.map +1 -1
  188. package/lib/features/store/types/ContentObjectTypesSearch.js +4 -1
  189. package/lib/features/store/types/ContentObjectTypesSearch.js.map +1 -1
  190. package/lib/features/store/types/ContentObjectTypesTable.d.ts +2 -1
  191. package/lib/features/store/types/ContentObjectTypesTable.d.ts.map +1 -1
  192. package/lib/features/store/types/ContentObjectTypesTable.js +8 -3
  193. package/lib/features/store/types/ContentObjectTypesTable.js.map +1 -1
  194. package/lib/i18n/instance.d.ts.map +1 -1
  195. package/lib/i18n/instance.js +1 -0
  196. package/lib/i18n/instance.js.map +1 -1
  197. package/lib/i18n/locales/ar.json +72 -45
  198. package/lib/i18n/locales/de.json +65 -34
  199. package/lib/i18n/locales/en.json +63 -47
  200. package/lib/i18n/locales/es.json +65 -35
  201. package/lib/i18n/locales/fr.json +65 -35
  202. package/lib/i18n/locales/it.json +72 -42
  203. package/lib/i18n/locales/ja.json +72 -41
  204. package/lib/i18n/locales/ko.json +72 -41
  205. package/lib/i18n/locales/pt.json +72 -42
  206. package/lib/i18n/locales/ru.json +72 -43
  207. package/lib/i18n/locales/tr.json +72 -41
  208. package/lib/i18n/locales/zh-TW.json +72 -41
  209. package/lib/i18n/locales/zh.json +72 -41
  210. package/lib/session/UserSession.d.ts +0 -6
  211. package/lib/session/UserSession.d.ts.map +1 -1
  212. package/lib/session/UserSession.js +0 -15
  213. package/lib/session/UserSession.js.map +1 -1
  214. package/lib/session/UserSessionProvider.d.ts.map +1 -1
  215. package/lib/session/UserSessionProvider.js +39 -98
  216. package/lib/session/UserSessionProvider.js.map +1 -1
  217. package/lib/session/auth/composable.d.ts.map +1 -1
  218. package/lib/session/auth/composable.js +3 -33
  219. package/lib/session/auth/composable.js.map +1 -1
  220. package/lib/shell/login/SignInPrimitives.d.ts.map +1 -1
  221. package/lib/shell/login/SignInPrimitives.js +3 -2
  222. package/lib/shell/login/SignInPrimitives.js.map +1 -1
  223. package/lib/vertesia-ui-core.js +1 -1
  224. package/lib/vertesia-ui-core.js.map +1 -1
  225. package/lib/vertesia-ui-env.js +1 -1
  226. package/lib/vertesia-ui-env.js.map +1 -1
  227. package/lib/vertesia-ui-features.js +1 -1
  228. package/lib/vertesia-ui-features.js.map +1 -1
  229. package/lib/vertesia-ui-i18n.js +1 -1
  230. package/lib/vertesia-ui-i18n.js.map +1 -1
  231. package/lib/vertesia-ui-session.js +1 -1
  232. package/lib/vertesia-ui-session.js.map +1 -1
  233. package/lib/vertesia-ui-shell.js +1 -1
  234. package/lib/vertesia-ui-shell.js.map +1 -1
  235. package/lib/vertesia-ui-widgets.js +1 -1
  236. package/lib/vertesia-ui-widgets.js.map +1 -1
  237. package/lib/widgets/schema-editor/editor/Editable.js +1 -1
  238. package/lib/widgets/schema-editor/editor/Editable.js.map +1 -1
  239. package/llms.txt +70 -70
  240. package/package.json +35 -32
  241. package/src/core/components/shadcn/dropdown.tsx +2 -0
  242. package/src/core/components/shadcn/filters/filterBar.tsx +9 -2
  243. package/src/core/components/shadcn/modal/ConfirmModal.tsx +65 -3
  244. package/src/core/components/shadcn/modal/dialog.tsx +1 -1
  245. package/src/core/components/shadcn/popover.tsx +1 -0
  246. package/src/core/components/shadcn/switch.tsx +4 -4
  247. package/src/core/components/shadcn/tabs.tsx +1 -1
  248. package/src/core/components/shadcn/tooltip.tsx +1 -0
  249. package/src/env/index.ts +0 -24
  250. package/src/features/agent/PayloadBuilder.tsx +18 -0
  251. package/src/features/agent/chat/AgentApprovalModeSelector.tsx +130 -0
  252. package/src/features/agent/chat/AgentChatFixtureReplay.test.tsx +22 -2
  253. package/src/features/agent/chat/AgentChatFixtureReplay.tsx +33 -27
  254. package/src/features/agent/chat/AgentRequestInputOverlay.test.tsx +122 -0
  255. package/src/features/agent/chat/AgentRequestInputOverlay.tsx +91 -17
  256. package/src/features/agent/chat/AgentRightPanel.tsx +238 -50
  257. package/src/features/agent/chat/AnimatedThinkingDots.tsx +1 -1
  258. package/src/features/agent/chat/ArtifactsTab.tsx +21 -155
  259. package/src/features/agent/chat/AskUserWidget.tsx +6 -2
  260. package/src/features/agent/chat/ModernAgentConversation.test.tsx +1157 -47
  261. package/src/features/agent/chat/ModernAgentConversation.tsx +703 -136
  262. package/src/features/agent/chat/ModernAgentOutput/ActiveWorkstreamsSummary.tsx +74 -0
  263. package/src/features/agent/chat/ModernAgentOutput/AllMessagesMixed.test.tsx +1420 -126
  264. package/src/features/agent/chat/ModernAgentOutput/AllMessagesMixed.tsx +934 -111
  265. package/src/features/agent/chat/ModernAgentOutput/AttachmentPreview.tsx +31 -40
  266. package/src/features/agent/chat/ModernAgentOutput/Header.tsx +28 -28
  267. package/src/features/agent/chat/ModernAgentOutput/MessageDeliveryStatus.tsx +83 -0
  268. package/src/features/agent/chat/ModernAgentOutput/MessageInput.test.tsx +38 -2
  269. package/src/features/agent/chat/ModernAgentOutput/MessageInput.tsx +121 -98
  270. package/src/features/agent/chat/ModernAgentOutput/MessageItem.tsx +7 -1
  271. package/src/features/agent/chat/ModernAgentOutput/SlideInPanel.tsx +3 -3
  272. package/src/features/agent/chat/ModernAgentOutput/SlidingMessages.tsx +1 -1
  273. package/src/features/agent/chat/ModernAgentOutput/SummaryConversation.ts +82 -2
  274. package/src/features/agent/chat/ModernAgentOutput/WorkstreamTabs.tsx +2 -2
  275. package/src/features/agent/chat/ModernAgentOutput/requestInputMessages.ts +216 -0
  276. package/src/features/agent/chat/ModernAgentOutput/utils.test.ts +149 -0
  277. package/src/features/agent/chat/ModernAgentOutput/utils.ts +103 -2
  278. package/src/features/agent/chat/clipboardFiles.ts +33 -0
  279. package/src/features/agent/chat/hooks/useAgentStream.test.tsx +355 -4
  280. package/src/features/agent/chat/hooks/useAgentStream.ts +270 -43
  281. package/src/features/agent/chat/hooks/useArtifacts.ts +11 -44
  282. package/src/features/agent/chat/index.ts +10 -1
  283. package/src/features/agent/chat/workstreams.ts +42 -0
  284. package/src/features/facets/AgentRunnerFacetsNav.tsx +23 -3
  285. package/src/features/facets/CollectionsFacetsNav.tsx +30 -5
  286. package/src/features/facets/PromptsFacetsNav.tsx +30 -5
  287. package/src/features/facets/RunsFacetsNav.tsx +32 -5
  288. package/src/features/index.ts +0 -1
  289. package/src/features/oauth/McpConnectionsButton.test.tsx +248 -0
  290. package/src/features/oauth/McpConnectionsButton.tsx +269 -0
  291. package/src/features/oauth/McpConnectionsDialog.tsx +142 -0
  292. package/src/features/oauth/RemoteMcpConnectionButton.tsx +37 -14
  293. package/src/features/oauth/index.ts +3 -0
  294. package/src/features/oauth/useMcpConnections.test.ts +94 -0
  295. package/src/features/oauth/useMcpConnections.ts +210 -0
  296. package/src/features/permissions/UserPermissionsProvider.tsx +41 -59
  297. package/src/features/store/objects/DocumentPreviewPanel.tsx +4 -2
  298. package/src/features/store/objects/DocumentQuickFilter.tsx +72 -0
  299. package/src/features/store/objects/DocumentSearchResults.tsx +30 -11
  300. package/src/features/store/objects/components/ContentOverview.tsx +30 -99
  301. package/src/features/store/objects/layout/DocumentTableColumn.tsx +29 -4
  302. package/src/features/store/objects/layout/documentLayout.tsx +1 -1
  303. package/src/features/store/objects/layout/renderers.tsx +80 -20
  304. package/src/features/store/types/ContentObjectTypesSearch.tsx +7 -1
  305. package/src/features/store/types/ContentObjectTypesTable.tsx +34 -4
  306. package/src/i18n/instance.ts +1 -0
  307. package/src/i18n/locales/ar.json +72 -45
  308. package/src/i18n/locales/de.json +65 -34
  309. package/src/i18n/locales/en.json +63 -47
  310. package/src/i18n/locales/es.json +65 -35
  311. package/src/i18n/locales/fr.json +65 -35
  312. package/src/i18n/locales/it.json +72 -42
  313. package/src/i18n/locales/ja.json +72 -41
  314. package/src/i18n/locales/ko.json +72 -41
  315. package/src/i18n/locales/pt.json +72 -42
  316. package/src/i18n/locales/ru.json +72 -43
  317. package/src/i18n/locales/tr.json +72 -41
  318. package/src/i18n/locales/zh-TW.json +72 -41
  319. package/src/i18n/locales/zh.json +72 -41
  320. package/src/i18n/rtl.test.ts +57 -1
  321. package/src/session/UserSession.ts +0 -16
  322. package/src/session/UserSessionProvider.tsx +51 -123
  323. package/src/session/auth/composable.ts +3 -34
  324. package/src/shell/login/SignInPrimitives.tsx +3 -2
  325. package/src/widgets/schema-editor/editor/Editable.tsx +1 -1
  326. package/lib/features/document-viewer/UniversalDocumentViewer.d.ts +0 -73
  327. package/lib/features/document-viewer/UniversalDocumentViewer.d.ts.map +0 -1
  328. package/lib/features/document-viewer/UniversalDocumentViewer.js +0 -415
  329. package/lib/features/document-viewer/UniversalDocumentViewer.js.map +0 -1
  330. package/lib/features/document-viewer/index.d.ts +0 -2
  331. package/lib/features/document-viewer/index.d.ts.map +0 -1
  332. package/lib/features/document-viewer/index.js +0 -2
  333. package/lib/features/document-viewer/index.js.map +0 -1
  334. package/src/features/document-viewer/UniversalDocumentViewer.test.tsx +0 -123
  335. package/src/features/document-viewer/UniversalDocumentViewer.tsx +0 -746
  336. package/src/features/document-viewer/index.ts +0 -1
  337. package/src/session/auth/composable.test.ts +0 -79
@@ -1,39 +1,50 @@
1
- import {
2
- type AuthTokenPayload,
3
- getPermissionsForRoles,
4
- listRoles,
5
- type Permission,
6
- PrincipalType,
7
- type ProjectRoles,
8
- } from '@vertesia/common';
1
+ import { type Permission, PrincipalType, type SystemRoleDefinition } from '@vertesia/common';
9
2
  import { ErrorBox, errorMessage, useFetch } from '@vertesia/ui/core';
10
3
  import { useUITranslation } from '@vertesia/ui/i18n';
11
- import { useUserSession } from '@vertesia/ui/session';
4
+ import { type UserSession, useUserSession } from '@vertesia/ui/session';
12
5
  import { createContext, useContext, useMemo } from 'react';
13
6
  import { isAnyOf } from './helpers';
14
7
 
15
- type ListRolesResponse = {
16
- name: ProjectRoles;
17
- permissions: Permission[];
18
- }[];
8
+ type ListRolesResponse = SystemRoleDefinition[];
19
9
 
20
10
  export class UserPermissions {
21
11
  system_roles: ListRolesResponse; // all roles defined in the system
22
12
  roles: Set<string>; // all roles of the current user
23
13
  permissions: Set<string>; // all permissions of the current user
24
14
 
25
- constructor(authToken: AuthTokenPayload, roles: ListRolesResponse = listSystemRoles()) {
15
+ constructor(session: UserSession, roles: ListRolesResponse) {
16
+ if (!session.authToken) {
17
+ throw new Error('No auth token found in user session');
18
+ }
26
19
  this.system_roles = roles;
27
- const roleNames = [...(authToken.account_roles || []), ...(authToken.project_roles || [])];
28
- const userRoles = new Set<string>(roleNames);
20
+ const userRoles = new Set<string>(session.authToken.account_roles || []);
21
+ if (session.authToken.project_roles) {
22
+ for (const role of session.authToken.project_roles) {
23
+ userRoles.add(role);
24
+ }
25
+ }
29
26
  this.roles = userRoles;
30
- const rolePermissions = authToken.permissions ?? getPermissionsForRolesFromMappings(roleNames, roles);
31
- // OAuth access tokens are capped to the permissions granted to the token (its scopes).
27
+ // build a temporary role to permissions map
28
+ const map: Record<string, Permission[]> = {};
29
+ for (const role of roles) {
30
+ map[role.name] = role.permissions;
31
+ }
32
32
  const permissionCap =
33
- authToken.type === PrincipalType.OAuthAccess ? new Set<string>(authToken.permissions ?? []) : undefined;
34
- this.permissions = new Set(
35
- permissionCap ? rolePermissions.filter((permission) => permissionCap.has(permission)) : rolePermissions,
36
- );
33
+ session.authToken.type === PrincipalType.OAuthAccess
34
+ ? new Set<string>(session.authToken.permissions ?? [])
35
+ : undefined;
36
+ const permissions = new Set<string>();
37
+ for (const role of userRoles) {
38
+ const rolePermissions = map[role];
39
+ if (rolePermissions) {
40
+ for (const permission of rolePermissions) {
41
+ if (!permissionCap || permissionCap.has(permission)) {
42
+ permissions.add(permission);
43
+ }
44
+ }
45
+ }
46
+ }
47
+ this.permissions = permissions;
37
48
  }
38
49
 
39
50
  hasPermission(permission: string | string[]) {
@@ -53,28 +64,6 @@ export class UserPermissions {
53
64
  }
54
65
  }
55
66
 
56
- function listSystemRoles(): ListRolesResponse {
57
- return listRoles().map((role) => ({
58
- name: role.name,
59
- permissions: Array.from(role.permissions),
60
- }));
61
- }
62
-
63
- function getPermissionsForRolesFromMappings(roleNames: Iterable<ProjectRoles>, roles: ListRolesResponse): Permission[] {
64
- if (roles.length === 0) {
65
- return getPermissionsForRoles(roleNames);
66
- }
67
-
68
- const permissionsByRole = new Map(roles.map((role) => [role.name, role.permissions]));
69
- const permissions = new Set<Permission>();
70
- for (const role of roleNames) {
71
- for (const permission of permissionsByRole.get(role) ?? []) {
72
- permissions.add(permission);
73
- }
74
- }
75
- return Array.from(permissions);
76
- }
77
-
78
67
  const UserPermissionsContext = createContext<UserPermissions | undefined>(undefined);
79
68
 
80
69
  export { UserPermissionsContext };
@@ -93,28 +82,21 @@ interface UserPermissionProviderProps {
93
82
  export function UserPermissionProvider({ children }: UserPermissionProviderProps) {
94
83
  const { t } = useUITranslation();
95
84
  const session = useUserSession();
96
- const authToken = session.authToken;
97
- const shouldFetchRoleMappings = Boolean(authToken && !authToken.permissions);
98
85
  const { data, error, isLoading } = useFetch<ListRolesResponse | undefined>(() => {
99
- if (shouldFetchRoleMappings) {
100
- return session.client.iam.roles.list();
86
+ if (session.user) {
87
+ return session.client.iam.roles.listSystem();
88
+ } else {
89
+ return Promise.resolve(undefined);
101
90
  }
102
- return Promise.resolve(undefined);
103
- }, [session, shouldFetchRoleMappings]);
91
+ }, [session.user]);
104
92
 
105
93
  const perms = useMemo(() => {
106
- if (authToken) {
107
- if (authToken.permissions || !shouldFetchRoleMappings) {
108
- return new UserPermissions(authToken);
109
- }
110
- if (data && !isLoading) {
111
- return new UserPermissions(authToken, data);
112
- }
94
+ if (session.authToken && data && !isLoading) {
95
+ return new UserPermissions(session, data);
113
96
  } else {
114
97
  return undefined;
115
98
  }
116
- return undefined;
117
- }, [authToken, data, isLoading, shouldFetchRoleMappings]);
99
+ }, [session, data, isLoading]);
118
100
 
119
101
  if (error) {
120
102
  return <ErrorBox title={t('store.failedToFetchRoleMappings')}>{errorMessage(error)}</ErrorBox>;
@@ -123,9 +123,11 @@ export function DocumentPreviewPanel({ objectId, isOpen, onClose }: DocumentPrev
123
123
 
124
124
  if (!isOpen) return null;
125
125
 
126
+ const panelTranslateClass = isOpen ? 'translate-x-0' : 'translate-x-full rtl:-translate-x-full'; // rtl-ok: mirrored inline-end transform
127
+
126
128
  return (
127
129
  <div
128
- className={`fixed inset-y-0 end-0 w-2/5 dark:bg-slate-900 shadow-xl z-50 flex flex-col transition-transform duration-300 transform ${isOpen ? 'translate-x-0' : 'translate-x-full rtl:-translate-x-full'}`}
130
+ className={`fixed inset-y-0 end-0 w-2/5 dark:bg-slate-900 shadow-xl z-50 flex flex-col transition-transform duration-300 transform ${panelTranslateClass}`}
129
131
  >
130
132
  {/* Header */}
131
133
  <div className="flex items-center justify-between px-4 py-3 border-b dark:border-gray-700 bg-gradient-to-r from-indigo-50 to-gray-50 dark:from-gray-800 dark:to-gray-900">
@@ -135,7 +137,7 @@ export function DocumentPreviewPanel({ objectId, isOpen, onClose }: DocumentPrev
135
137
  {isLoading ? t('store.loadingDocument') : object?.name || t('store.documentPreview')}
136
138
  </h2>
137
139
  </div>
138
- <div className="flex items-center space-x-2">
140
+ <div className="flex items-center gap-2">
139
141
  <Button
140
142
  variant="ghost"
141
143
  size="sm"
@@ -0,0 +1,72 @@
1
+ import { Button, CopyButton, VTooltip } from '@vertesia/ui/core';
2
+ import { Filter } from 'lucide-react';
3
+ import { createContext, type ReactNode, useContext } from 'react';
4
+
5
+ export type DocumentQuickFilter = (field: string, value: string | string[]) => void;
6
+
7
+ const DocumentQuickFilterContext = createContext<DocumentQuickFilter | undefined>(undefined);
8
+
9
+ /**
10
+ * Provides a quick-filter handler to the document table cells below it (read via
11
+ * {@link useDocumentQuickFilter}). Only surfaces that own a filter bar — e.g. DocumentSearchResults —
12
+ * need to supply one; everywhere else the per-cell filter buttons stay inert.
13
+ */
14
+ export function DocumentQuickFilterProvider({
15
+ onFilter,
16
+ children,
17
+ }: {
18
+ onFilter?: DocumentQuickFilter;
19
+ children: ReactNode;
20
+ }) {
21
+ return <DocumentQuickFilterContext.Provider value={onFilter}>{children}</DocumentQuickFilterContext.Provider>;
22
+ }
23
+
24
+ export function useDocumentQuickFilter() {
25
+ return useContext(DocumentQuickFilterContext);
26
+ }
27
+
28
+ const ACTION_BTN_CLASS =
29
+ 'h-6 w-6 p-0 opacity-0 group-hover/field:opacity-100 text-muted hover:text-foreground transition-opacity shrink-0';
30
+
31
+ /**
32
+ * Hover-revealed per-cell actions for the document table: an optional copy button (for id-valued
33
+ * fields) and a "Filter by ..." button wired to the {@link DocumentQuickFilterProvider} handler.
34
+ */
35
+ export function DocumentCellActions({
36
+ field,
37
+ value,
38
+ label,
39
+ copyContent,
40
+ }: {
41
+ field: string;
42
+ value?: string | string[];
43
+ label: string;
44
+ copyContent?: string;
45
+ }) {
46
+ const onFilter = useDocumentQuickFilter();
47
+ const hasValue = Array.isArray(value) ? value.length > 0 : value !== undefined && value !== '';
48
+
49
+ return (
50
+ <>
51
+ {copyContent !== undefined && copyContent !== '' && (
52
+ <CopyButton content={copyContent} className={ACTION_BTN_CLASS} />
53
+ )}
54
+ {hasValue && value !== undefined && (
55
+ <VTooltip description={`Filter by ${label}`} asChild size="xs">
56
+ <Button
57
+ variant="ghost"
58
+ size="sm"
59
+ aria-label={`Filter by ${label}`}
60
+ className={ACTION_BTN_CLASS}
61
+ onClick={(e) => {
62
+ e.stopPropagation();
63
+ onFilter?.(field, value);
64
+ }}
65
+ >
66
+ <Filter className="size-3" />
67
+ </Button>
68
+ </VTooltip>
69
+ )}
70
+ </>
71
+ );
72
+ }
@@ -26,6 +26,7 @@ import { ContentDispositionButton } from './components/ContentDispositionButton'
26
26
  import { ContentOverview } from './components/ContentOverview';
27
27
  import { useDownloadFile } from './components/useDownloadFile';
28
28
  import { VectorSearchWidget } from './components/VectorSearchWidget';
29
+ import { DocumentQuickFilterProvider } from './DocumentQuickFilter';
29
30
  import { DocumentTable } from './DocumentTable';
30
31
  import type { ExtendedColumnLayout } from './layout/DocumentTableColumn';
31
32
  import {
@@ -278,6 +279,22 @@ export function DocumentSearchResults({
278
279
  handleFilterLogic(newFilters);
279
280
  };
280
281
 
282
+ // Per-row quick filters from the table cells: merge into the same filter list (so a chip shows in
283
+ // the bar) and re-run the search via handleFilterChange.
284
+ const addQuickFilter = (name: string, value: string | string[]) => {
285
+ const group = filterGroups.find((g) => g.name === name);
286
+ const base = { name, type: group?.type, placeholder: group?.placeholder, multiple: group?.multiple };
287
+ handleFilterChange((prev) => {
288
+ const others = prev.filter((f) => f.name !== name);
289
+ if (group?.type === 'stringList' || Array.isArray(value)) {
290
+ const incoming = Array.isArray(value) ? value : [value];
291
+ const current = (prev.find((f) => f.name === name)?.value as string[] | undefined) ?? [];
292
+ return [...others, { ...base, value: Array.from(new Set([...current, ...incoming])) }];
293
+ }
294
+ return [...others, { ...base, value: [{ value, label: value }] }];
295
+ });
296
+ };
297
+
281
298
  const url = new URL(window.location.href);
282
299
  const filtersParam = url.searchParams.get('filters');
283
300
 
@@ -332,17 +349,19 @@ export function DocumentSearchResults({
332
349
  />
333
350
  <div className="flex flex-col w-full flex-1 min-h-0 border rounded-md mb-2">
334
351
  <div ref={scrollRef} className="flex-1 min-h-0 overflow-y-auto">
335
- <DocumentTable
336
- objects={objects}
337
- isLoading={!objects.length && isLoading}
338
- layout={actualLayout}
339
- onRowClick={onRowClick}
340
- previewObject={previewObject}
341
- selectedObject={selectedObject}
342
- onUpload={onUpload}
343
- isGridView={isGridView}
344
- collectionId={searchContext.collectionId}
345
- />
352
+ <DocumentQuickFilterProvider onFilter={addQuickFilter}>
353
+ <DocumentTable
354
+ objects={objects}
355
+ isLoading={!objects.length && isLoading}
356
+ layout={actualLayout}
357
+ onRowClick={onRowClick}
358
+ previewObject={previewObject}
359
+ selectedObject={selectedObject}
360
+ onUpload={onUpload}
361
+ isGridView={isGridView}
362
+ collectionId={searchContext.collectionId}
363
+ />
364
+ </DocumentQuickFilterProvider>
346
365
  {hasMore ? (
347
366
  <div ref={loadMoreRef} className="w-full flex justify-center">
348
367
  <Spinner size="xl" />
@@ -25,16 +25,12 @@ import {
25
25
  import { useUITranslation } from '@vertesia/ui/i18n';
26
26
  import { NavLink } from '@vertesia/ui/router';
27
27
  import { useUserSession } from '@vertesia/ui/session';
28
- import { JSONDisplay, Progress } from '@vertesia/ui/widgets';
28
+ import { JSONDisplay, MarkdownRenderer, Progress, XMLViewer } from '@vertesia/ui/widgets';
29
29
  import { AlertTriangle, Copy, Download, FileSearch, SquarePen } from 'lucide-react';
30
- import { memo, type RefObject, useEffect, useMemo, useRef, useState } from 'react';
31
- import {
32
- type UniversalDocumentConverter,
33
- type UniversalDocumentSource,
34
- UniversalDocumentViewer,
35
- } from '../../../document-viewer/UniversalDocumentViewer.js';
30
+ import { memo, type RefObject, useEffect, useRef, useState } from 'react';
36
31
  import { MagicPdfView } from '../../../magic-pdf';
37
32
  import { AudioPanel, ImagePanel, VideoPanel } from '../../../media-viewer';
33
+ import { SimplePdfViewer } from '../../../pdf-viewer';
38
34
  import { SecureButton } from '../../../permissions/SecureButton.js';
39
35
  import { getWorkflowStatusColor, getWorkflowStatusName, isPreviewableAsPdf } from '../../../utils/index.js';
40
36
  import { PropertiesEditorModal } from './PropertiesEditorModal';
@@ -63,12 +59,11 @@ interface TextPanelProps {
63
59
  }
64
60
 
65
61
  interface OfficePdfPreviewPanelProps {
66
- object: ContentObject;
67
62
  pdfRendition?: { content?: { source?: string } };
68
63
  officePdfUrl?: string;
69
- converters: UniversalDocumentConverter[];
70
64
  officePdfConverting: boolean;
71
65
  officePdfError?: string;
66
+ onConvert: () => void;
72
67
  }
73
68
 
74
69
  interface OfficePdfActionsProps {
@@ -325,7 +320,6 @@ function DataPanel({
325
320
  handleCopyContent: (content: string, type: 'text' | 'properties') => Promise<void>;
326
321
  refetch?: () => Promise<unknown>;
327
322
  }) {
328
- const { client } = useUserSession();
329
323
  const { t } = useUITranslation();
330
324
  const isImage = object?.metadata?.type === ContentNature.Image;
331
325
  const isVideo = object?.metadata?.type === ContentNature.Video;
@@ -395,40 +389,9 @@ function DataPanel({
395
389
  pdfUrl: officePdfUrl,
396
390
  isConverting: officePdfConverting,
397
391
  error: officePdfError,
392
+ triggerConversion: triggerOfficePdfConversion,
398
393
  } = useOfficePdfConversion(object.id, isPreviewableAsPdfDoc);
399
394
 
400
- const officePdfConverters = useMemo<UniversalDocumentConverter[]>(
401
- () => [
402
- {
403
- id: 'office-pdf-rendition',
404
- target: 'pdf',
405
- canConvert: ({ contentType, extension }) =>
406
- isPreviewableAsPdfDoc ||
407
- (contentType ? isPreviewableAsPdf(contentType) : false) ||
408
- ['doc', 'docx', 'ppt', 'pptx'].includes(extension),
409
- convert: async () => {
410
- const response = await client.objects.getRendition(object.id, {
411
- format: MarkdownRenditionFormat.pdf,
412
- generate_if_missing: true,
413
- sign_url: true,
414
- block_on_generation: true,
415
- });
416
-
417
- if (response.status === 'found' && response.renditions?.length) {
418
- return {
419
- url: response.renditions[0],
420
- contentType: 'application/pdf',
421
- fileName: `${object.name || 'document'}.pdf`,
422
- };
423
- }
424
-
425
- return null;
426
- },
427
- },
428
- ],
429
- [client, isPreviewableAsPdfDoc, object.id, object.name],
430
- );
431
-
432
395
  // Load text once processing completes without triggering a full object refetch
433
396
  // (which would flash the page-level loading spinner).
434
397
  useEffect(() => {
@@ -520,6 +483,9 @@ function DataPanel({
520
483
  alt={t('store.viewAsPdf')}
521
484
  onClick={() => {
522
485
  setCurrentPanel(PanelView.Pdf);
486
+ if (!pdfRendition && !officePdfUrl && !officePdfConverting) {
487
+ void triggerOfficePdfConversion();
488
+ }
523
489
  }}
524
490
  disabled={officePdfConverting}
525
491
  >
@@ -573,12 +539,11 @@ function DataPanel({
573
539
  {isPreviewableAsPdfDoc && keepPdfPreviewMounted && (
574
540
  <div className={getPanelVisibility(showPdfPreviewPanel)}>
575
541
  <OfficePdfPreviewPanel
576
- object={object}
577
542
  pdfRendition={pdfRendition}
578
543
  officePdfUrl={officePdfUrl}
579
- converters={officePdfConverters}
580
544
  officePdfConverting={officePdfConverting}
581
545
  officePdfError={officePdfError}
546
+ onConvert={triggerOfficePdfConversion}
582
547
  />
583
548
  </div>
584
549
  )}
@@ -778,24 +743,18 @@ function TextActions({ object, text, fullText, handleCopyContent, onToggleEdit,
778
743
 
779
744
  const TextPanel = memo(({ object, text, isTextCropped, textContainerRef }: TextPanelProps) => {
780
745
  const { t } = useUITranslation();
746
+ const content = object.content;
781
747
  const isCreatedOrProcessing = isCreatedOrProcessingStatus(object?.status);
748
+
749
+ // Check content processor type for XML
782
750
  const contentProcessorType = getContentProcessorType(object);
783
751
  const isXml = contentProcessorType === 'xml';
784
752
 
785
753
  // Check if content type is markdown or plain text
786
- const isMarkdownOrText =
787
- object.content?.type && (object.content.type === 'text/markdown' || object.content.type === 'text/plain');
754
+ const isMarkdownOrText = content?.type && (content.type === 'text/markdown' || content.type === 'text/plain');
788
755
 
789
756
  // Render as markdown if it's markdown/text type OR if text looks like markdown (but not if XML)
790
757
  const shouldRenderAsMarkdown = !isXml && (isMarkdownOrText || looksLikeMarkdown(text));
791
- const source: UniversalDocumentSource = {
792
- id: object.id,
793
- title: object.name,
794
- fileName: object.content?.name || object.name,
795
- contentType: isXml ? 'text/xml' : shouldRenderAsMarkdown ? 'text/markdown' : object.content?.type,
796
- content: text,
797
- sourcePath: object.content?.source,
798
- };
799
758
 
800
759
  return text ? (
801
760
  <>
@@ -808,12 +767,17 @@ const TextPanel = memo(({ object, text, isTextCropped, textContainerRef }: TextP
808
767
  </div>
809
768
  )}
810
769
  <div className={`max-w-7xl px-2 h-full overflow-auto`} ref={textContainerRef}>
811
- <UniversalDocumentViewer
812
- source={source}
813
- className="h-full"
814
- bodyClassName="overflow-auto"
815
- markdownComponents={createMarkdownComponents()}
816
- />
770
+ {isXml ? (
771
+ <div className="px-4 py-2">
772
+ <XMLViewer xml={text} collapsible />
773
+ </div>
774
+ ) : shouldRenderAsMarkdown ? (
775
+ <div className="vprose prose-sm p-1">
776
+ <MarkdownRenderer components={createMarkdownComponents()}>{text}</MarkdownRenderer>
777
+ </div>
778
+ ) : (
779
+ <pre className="text-wrap bg-muted text-muted p-2">{text}</pre>
780
+ )}
817
781
  </div>
818
782
  </>
819
783
  ) : (
@@ -958,17 +922,9 @@ function OfficePdfActions({ object, pdfRendition, officePdfUrl }: OfficePdfActio
958
922
  }
959
923
 
960
924
  function PdfPreviewPanel({ object }: { object: ContentObject }) {
961
- const source: UniversalDocumentSource = {
962
- id: object.id,
963
- title: object.name,
964
- fileName: object.content?.name || object.name,
965
- contentType: object.content?.type,
966
- sourcePath: object.content?.source,
967
- };
968
-
969
925
  return (
970
926
  <div className="h-full">
971
- <UniversalDocumentViewer source={source} className="h-full" />
927
+ <SimplePdfViewer object={object} className="h-full" />
972
928
  </div>
973
929
  );
974
930
  }
@@ -978,12 +934,11 @@ function PdfPreviewPanel({ object }: { object: ContentObject }) {
978
934
  * Handles the various states: converting, error, showing PDF.
979
935
  */
980
936
  function OfficePdfPreviewPanel({
981
- object,
982
937
  pdfRendition,
983
938
  officePdfUrl,
984
- converters,
985
939
  officePdfConverting,
986
940
  officePdfError,
941
+ onConvert,
987
942
  }: OfficePdfPreviewPanelProps) {
988
943
  const { t } = useUITranslation();
989
944
  if (officePdfConverting) {
@@ -1005,48 +960,24 @@ function OfficePdfPreviewPanel({
1005
960
  }
1006
961
 
1007
962
  if (pdfRendition?.content?.source) {
1008
- const source: UniversalDocumentSource = {
1009
- id: object.id,
1010
- title: object.name,
1011
- fileName: `${object.name || 'document'}.pdf`,
1012
- contentType: 'application/pdf',
1013
- sourcePath: pdfRendition.content.source,
1014
- };
1015
-
1016
963
  return (
1017
964
  <div className="h-full">
1018
- <UniversalDocumentViewer source={source} className="h-full" />
965
+ <SimplePdfViewer source={pdfRendition.content.source} className="h-full" />
1019
966
  </div>
1020
967
  );
1021
968
  }
1022
969
 
1023
970
  if (officePdfUrl) {
1024
- const source: UniversalDocumentSource = {
1025
- id: object.id,
1026
- title: object.name,
1027
- fileName: `${object.name || 'document'}.pdf`,
1028
- contentType: 'application/pdf',
1029
- url: officePdfUrl,
1030
- };
1031
-
1032
971
  return (
1033
972
  <div className="h-full">
1034
- <UniversalDocumentViewer source={source} className="h-full" />
973
+ <SimplePdfViewer url={officePdfUrl} className="h-full" />
1035
974
  </div>
1036
975
  );
1037
976
  }
1038
977
 
1039
- const source: UniversalDocumentSource = {
1040
- id: object.id,
1041
- title: object.name,
1042
- fileName: object.content?.name || object.name,
1043
- contentType: object.content?.type,
1044
- sourcePath: object.content?.source,
1045
- };
1046
-
1047
978
  return (
1048
- <div className="h-full">
1049
- <UniversalDocumentViewer source={source} converters={converters} className="h-full" />
979
+ <div className="flex flex-col justify-center items-center flex-1 gap-2">
980
+ <Button onClick={onConvert}>Convert to PDF</Button>
1050
981
  </div>
1051
982
  );
1052
983
  }
@@ -1,6 +1,7 @@
1
1
  import type { ColumnLayout, ContentObjectItem } from '@vertesia/common';
2
2
  import type React from 'react';
3
3
 
4
+ import { DocumentCellActions } from '../DocumentQuickFilter';
4
5
  import renderers from './renderers';
5
6
 
6
7
  const defaultRenderer = renderers.string();
@@ -43,7 +44,7 @@ export interface ExtendedColumnLayout extends Omit<ColumnLayout, 'field'> {
43
44
  }
44
45
 
45
46
  export class DocumentTableColumn {
46
- renderer: (value: unknown, index: number) => React.ReactNode = defaultRenderer;
47
+ renderer: (value: unknown, index: number, actions?: React.ReactNode) => React.ReactNode = defaultRenderer;
47
48
  path: string[];
48
49
  fallbackPath?: string[];
49
50
  previewObject?: (objectId: string) => void;
@@ -91,7 +92,7 @@ export class DocumentTableColumn {
91
92
  // If there's a custom render function, wrap its result in a td
92
93
  if (this.layout.render) {
93
94
  return (
94
- <td key={index} className="whitespace-nowrap px-3 py-4 text-sm">
95
+ <td key={index} className="whitespace-nowrap px-3 py-4 text-sm group">
95
96
  {this.layout.render(object)}
96
97
  </td>
97
98
  );
@@ -99,6 +100,7 @@ export class DocumentTableColumn {
99
100
 
100
101
  const type = this.layout.type || 'string';
101
102
  const baseType = type.indexOf('?') > 0 ? type.substring(0, type.indexOf('?')) : type;
103
+ const actions = this.buildActions(object, baseType);
102
104
 
103
105
  if ((baseType === 'objectId' || baseType === 'objectLink') && this.previewObject) {
104
106
  const i = type.indexOf('?');
@@ -106,10 +108,33 @@ export class DocumentTableColumn {
106
108
  const renderer = renderers[baseType](params, (_id: string) => {
107
109
  this.previewObject?.(object.id);
108
110
  });
109
- return renderer(object, index);
111
+ return renderer(object, index, actions);
110
112
  }
111
113
 
112
114
  // Otherwise use the type-based renderer with the resolved value
113
- return this.renderer(this.resolveValue(object), index);
115
+ return this.renderer(this.resolveValue(object), index, actions);
116
+ }
117
+
118
+ /**
119
+ * Per-cell quick-filter/copy actions, derived from the column's field/type. Returns undefined for
120
+ * columns that aren't backed by a filterable facet field. The filter handler itself is read from
121
+ * {@link DocumentQuickFilterProvider} context by {@link DocumentCellActions}.
122
+ */
123
+ private buildActions(object: ContentObjectItem, baseType: string): React.ReactNode {
124
+ const field = this.layout.field;
125
+ if (baseType === 'objectId' || baseType === 'objectLink' || field === 'id') {
126
+ return <DocumentCellActions field="id" value={object.id} label={object.id} copyContent={object.id} />;
127
+ }
128
+ if (baseType === 'objectName' || field === 'name') {
129
+ return <DocumentCellActions field="name" value={object.name} label={object.name ?? object.id} />;
130
+ }
131
+ if (baseType === 'typeLink' || field === 'type.name' || field === 'type') {
132
+ const typeId = object.type?.id;
133
+ return <DocumentCellActions field="type" value={typeId} label={object.type?.name ?? typeId ?? 'type'} />;
134
+ }
135
+ if (field === 'status') {
136
+ return <DocumentCellActions field="status" value={object.status} label={object.status} />;
137
+ }
138
+ return undefined;
114
139
  }
115
140
  }
@@ -53,7 +53,7 @@ export function DocumentTableView({
53
53
  return (
54
54
  <tr
55
55
  key={obj.id}
56
- className={`cursor-pointer hover:bg-muted group ${selectedObject?.id === obj.id ? 'bg-muted' : ''} ${isHighlighted ? 'bg-blue-50 dark:bg-blue-900/20' : ''}`}
56
+ className={`group cursor-pointer hover:bg-muted ${selectedObject?.id === obj.id ? 'bg-muted' : ''} ${isHighlighted ? 'bg-blue-50 dark:bg-blue-900/20' : ''}`}
57
57
  onClick={() => {
58
58
  onRowClick?.(obj);
59
59
  }}