@vertesia/ui 1.5.0-dev.20260807.073259Z → 1.5.0-dev.20260826.064249Z

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 (432) hide show
  1. package/README.md +1 -7
  2. package/lib/core/components/shadcn/filters/comboBox/DateCombobox.js +1 -1
  3. package/lib/core/components/shadcn/filters/comboBox/DateCombobox.js.map +1 -1
  4. package/lib/core/components/shadcn/filters/filter/dateFilter.d.ts.map +1 -1
  5. package/lib/core/components/shadcn/filters/filter/dateFilter.js +1 -1
  6. package/lib/core/components/shadcn/filters/filter/dateFilter.js.map +1 -1
  7. package/lib/core/components/shadcn/filters/filters.d.ts.map +1 -1
  8. package/lib/core/components/shadcn/filters/filters.js +1 -1
  9. package/lib/core/components/shadcn/filters/filters.js.map +1 -1
  10. package/lib/core/components/shadcn/index.d.ts +1 -0
  11. package/lib/core/components/shadcn/index.d.ts.map +1 -1
  12. package/lib/core/components/shadcn/index.js +1 -0
  13. package/lib/core/components/shadcn/index.js.map +1 -1
  14. package/lib/core/components/shadcn/modal/dialog.d.ts.map +1 -1
  15. package/lib/core/components/shadcn/modal/dialog.js +1 -3
  16. package/lib/core/components/shadcn/modal/dialog.js.map +1 -1
  17. package/lib/core/components/shadcn/overflowTabs.d.ts +59 -0
  18. package/lib/core/components/shadcn/overflowTabs.d.ts.map +1 -0
  19. package/lib/core/components/shadcn/overflowTabs.js +173 -0
  20. package/lib/core/components/shadcn/overflowTabs.js.map +1 -0
  21. package/lib/core/components/shadcn/selectBox.js +2 -2
  22. package/lib/core/components/shadcn/selectBox.js.map +1 -1
  23. package/lib/core/components/shadcn/theme/ThemeProvider.d.ts +3 -1
  24. package/lib/core/components/shadcn/theme/ThemeProvider.d.ts.map +1 -1
  25. package/lib/core/components/shadcn/theme/ThemeProvider.js +8 -9
  26. package/lib/core/components/shadcn/theme/ThemeProvider.js.map +1 -1
  27. package/lib/core/utils/dayjs.d.ts +12 -0
  28. package/lib/core/utils/dayjs.d.ts.map +1 -0
  29. package/lib/core/utils/dayjs.js +16 -0
  30. package/lib/core/utils/dayjs.js.map +1 -0
  31. package/lib/env/index.d.ts +17 -0
  32. package/lib/env/index.d.ts.map +1 -1
  33. package/lib/env/index.js +18 -1
  34. package/lib/env/index.js.map +1 -1
  35. package/lib/features/agent/PayloadBuilder.d.ts +1 -0
  36. package/lib/features/agent/PayloadBuilder.d.ts.map +1 -1
  37. package/lib/features/agent/PayloadBuilder.js +22 -5
  38. package/lib/features/agent/PayloadBuilder.js.map +1 -1
  39. package/lib/features/agent/chat/AgentRightPanel.d.ts.map +1 -1
  40. package/lib/features/agent/chat/AgentRightPanel.js +3 -135
  41. package/lib/features/agent/chat/AgentRightPanel.js.map +1 -1
  42. package/lib/features/agent/chat/ArtifactsTab.d.ts.map +1 -1
  43. package/lib/features/agent/chat/ArtifactsTab.js +1 -1
  44. package/lib/features/agent/chat/ArtifactsTab.js.map +1 -1
  45. package/lib/features/agent/chat/AskUserWidget.d.ts.map +1 -1
  46. package/lib/features/agent/chat/AskUserWidget.js +19 -4
  47. package/lib/features/agent/chat/AskUserWidget.js.map +1 -1
  48. package/lib/features/agent/chat/ModernAgentConversation.d.ts +6 -0
  49. package/lib/features/agent/chat/ModernAgentConversation.d.ts.map +1 -1
  50. package/lib/features/agent/chat/ModernAgentConversation.js +99 -29
  51. package/lib/features/agent/chat/ModernAgentConversation.js.map +1 -1
  52. package/lib/features/agent/chat/ModernAgentOutput/ActiveWorkstreamsSummary.d.ts.map +1 -1
  53. package/lib/features/agent/chat/ModernAgentOutput/ActiveWorkstreamsSummary.js +10 -9
  54. package/lib/features/agent/chat/ModernAgentOutput/ActiveWorkstreamsSummary.js.map +1 -1
  55. package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.d.ts.map +1 -1
  56. package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.js +5 -8
  57. package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.js.map +1 -1
  58. package/lib/features/agent/chat/ModernAgentOutput/AttachmentPreview.d.ts.map +1 -1
  59. package/lib/features/agent/chat/ModernAgentOutput/AttachmentPreview.js +45 -4
  60. package/lib/features/agent/chat/ModernAgentOutput/AttachmentPreview.js.map +1 -1
  61. package/lib/features/agent/chat/ModernAgentOutput/BatchProgressPanel.js +1 -1
  62. package/lib/features/agent/chat/ModernAgentOutput/BatchProgressPanel.js.map +1 -1
  63. package/lib/features/agent/chat/ModernAgentOutput/Header.d.ts.map +1 -1
  64. package/lib/features/agent/chat/ModernAgentOutput/Header.js +3 -3
  65. package/lib/features/agent/chat/ModernAgentOutput/Header.js.map +1 -1
  66. package/lib/features/agent/chat/ModernAgentOutput/MessageItem.d.ts.map +1 -1
  67. package/lib/features/agent/chat/ModernAgentOutput/MessageItem.js +1 -1
  68. package/lib/features/agent/chat/ModernAgentOutput/MessageItem.js.map +1 -1
  69. package/lib/features/agent/chat/ModernAgentOutput/StreamingMessage.d.ts.map +1 -1
  70. package/lib/features/agent/chat/ModernAgentOutput/StreamingMessage.js +1 -1
  71. package/lib/features/agent/chat/ModernAgentOutput/StreamingMessage.js.map +1 -1
  72. package/lib/features/agent/chat/ModernAgentOutput/ToolCallGroup.js +1 -1
  73. package/lib/features/agent/chat/ModernAgentOutput/ToolCallGroup.js.map +1 -1
  74. package/lib/features/agent/chat/ModernAgentOutput/WorkstreamTabs.d.ts.map +1 -1
  75. package/lib/features/agent/chat/ModernAgentOutput/WorkstreamTabs.js +9 -121
  76. package/lib/features/agent/chat/ModernAgentOutput/WorkstreamTabs.js.map +1 -1
  77. package/lib/features/agent/chat/ModernAgentOutput/utils.d.ts +6 -0
  78. package/lib/features/agent/chat/ModernAgentOutput/utils.d.ts.map +1 -1
  79. package/lib/features/agent/chat/ModernAgentOutput/utils.js +19 -11
  80. package/lib/features/agent/chat/ModernAgentOutput/utils.js.map +1 -1
  81. package/lib/features/agent/chat/VegaLiteChart.d.ts.map +1 -1
  82. package/lib/features/agent/chat/VegaLiteChart.js +11 -3
  83. package/lib/features/agent/chat/VegaLiteChart.js.map +1 -1
  84. package/lib/features/agent/chat/hooks/useAgentStream.d.ts.map +1 -1
  85. package/lib/features/agent/chat/hooks/useAgentStream.js +3 -0
  86. package/lib/features/agent/chat/hooks/useAgentStream.js.map +1 -1
  87. package/lib/features/document-viewer/UniversalDocumentViewer.d.ts.map +1 -1
  88. package/lib/features/document-viewer/UniversalDocumentViewer.js +1 -1
  89. package/lib/features/document-viewer/UniversalDocumentViewer.js.map +1 -1
  90. package/lib/features/facets/AgentRunnerFacetsNav.d.ts +14 -2
  91. package/lib/features/facets/AgentRunnerFacetsNav.d.ts.map +1 -1
  92. package/lib/features/facets/AgentRunnerFacetsNav.js +20 -2
  93. package/lib/features/facets/AgentRunnerFacetsNav.js.map +1 -1
  94. package/lib/features/facets/CollectionsFacetsNav.d.ts +3 -3
  95. package/lib/features/facets/CollectionsFacetsNav.d.ts.map +1 -1
  96. package/lib/features/facets/CollectionsFacetsNav.js +6 -1
  97. package/lib/features/facets/CollectionsFacetsNav.js.map +1 -1
  98. package/lib/features/facets/DocumentsFacetsNav.d.ts +3 -3
  99. package/lib/features/facets/DocumentsFacetsNav.d.ts.map +1 -1
  100. package/lib/features/facets/DocumentsFacetsNav.js +20 -8
  101. package/lib/features/facets/DocumentsFacetsNav.js.map +1 -1
  102. package/lib/features/facets/InteractionsFacetsNav.d.ts +3 -3
  103. package/lib/features/facets/InteractionsFacetsNav.d.ts.map +1 -1
  104. package/lib/features/facets/InteractionsFacetsNav.js +11 -1
  105. package/lib/features/facets/InteractionsFacetsNav.js.map +1 -1
  106. package/lib/features/facets/PromptsFacetsNav.d.ts +3 -3
  107. package/lib/features/facets/PromptsFacetsNav.d.ts.map +1 -1
  108. package/lib/features/facets/PromptsFacetsNav.js +6 -1
  109. package/lib/features/facets/PromptsFacetsNav.js.map +1 -1
  110. package/lib/features/facets/RunsFacetsNav.d.ts +4 -14
  111. package/lib/features/facets/RunsFacetsNav.d.ts.map +1 -1
  112. package/lib/features/facets/RunsFacetsNav.js +26 -15
  113. package/lib/features/facets/RunsFacetsNav.js.map +1 -1
  114. package/lib/features/facets/WorkflowExecutionsFacetsNav.d.ts +4 -3
  115. package/lib/features/facets/WorkflowExecutionsFacetsNav.d.ts.map +1 -1
  116. package/lib/features/facets/WorkflowExecutionsFacetsNav.js +18 -10
  117. package/lib/features/facets/WorkflowExecutionsFacetsNav.js.map +1 -1
  118. package/lib/features/facets/index.d.ts +1 -1
  119. package/lib/features/facets/index.d.ts.map +1 -1
  120. package/lib/features/facets/index.js.map +1 -1
  121. package/lib/features/facets/utils/SearchInterface.d.ts +4 -3
  122. package/lib/features/facets/utils/SearchInterface.d.ts.map +1 -1
  123. package/lib/features/facets/utils/SearchInterface.js +4 -0
  124. package/lib/features/facets/utils/SearchInterface.js.map +1 -1
  125. package/lib/features/layout/GenericPageNavHeader.d.ts +8 -1
  126. package/lib/features/layout/GenericPageNavHeader.d.ts.map +1 -1
  127. package/lib/features/layout/GenericPageNavHeader.js +9 -1
  128. package/lib/features/layout/GenericPageNavHeader.js.map +1 -1
  129. package/lib/features/magic-pdf/DownloadPopover.d.ts +3 -2
  130. package/lib/features/magic-pdf/DownloadPopover.d.ts.map +1 -1
  131. package/lib/features/magic-pdf/DownloadPopover.js.map +1 -1
  132. package/lib/features/magic-pdf/GroundedExtractionView.d.ts.map +1 -1
  133. package/lib/features/magic-pdf/GroundedExtractionView.js +51 -64
  134. package/lib/features/magic-pdf/GroundedExtractionView.js.map +1 -1
  135. package/lib/features/oauth/McpConnectionsButton.d.ts +1 -1
  136. package/lib/features/oauth/McpConnectionsButton.d.ts.map +1 -1
  137. package/lib/features/oauth/McpConnectionsButton.js +2 -2
  138. package/lib/features/oauth/McpConnectionsButton.js.map +1 -1
  139. package/lib/features/oauth/McpConnectionsDialog.d.ts +1 -1
  140. package/lib/features/oauth/McpConnectionsDialog.js +2 -2
  141. package/lib/features/oauth/McpConnectionsDialog.js.map +1 -1
  142. package/lib/features/oauth/useMcpConnections.d.ts +4 -5
  143. package/lib/features/oauth/useMcpConnections.d.ts.map +1 -1
  144. package/lib/features/oauth/useMcpConnections.js +20 -4
  145. package/lib/features/oauth/useMcpConnections.js.map +1 -1
  146. package/lib/features/pdf-viewer/PdfPageRenderer.d.ts.map +1 -1
  147. package/lib/features/pdf-viewer/PdfPageRenderer.js +9 -11
  148. package/lib/features/pdf-viewer/PdfPageRenderer.js.map +1 -1
  149. package/lib/features/pdf-viewer/lazyReactPdf.d.ts +10 -0
  150. package/lib/features/pdf-viewer/lazyReactPdf.d.ts.map +1 -0
  151. package/lib/features/pdf-viewer/lazyReactPdf.js +25 -0
  152. package/lib/features/pdf-viewer/lazyReactPdf.js.map +1 -0
  153. package/lib/features/store/collections/CollectionsTable.d.ts.map +1 -1
  154. package/lib/features/store/collections/CollectionsTable.js +1 -3
  155. package/lib/features/store/collections/CollectionsTable.js.map +1 -1
  156. package/lib/features/store/collections/EditCollectionView.js +1 -1
  157. package/lib/features/store/collections/EditCollectionView.js.map +1 -1
  158. package/lib/features/store/objects/ExportPropertiesModal.d.ts +3 -1
  159. package/lib/features/store/objects/ExportPropertiesModal.d.ts.map +1 -1
  160. package/lib/features/store/objects/ExportPropertiesModal.js +5 -5
  161. package/lib/features/store/objects/ExportPropertiesModal.js.map +1 -1
  162. package/lib/features/store/objects/components/ContentOverview.d.ts.map +1 -1
  163. package/lib/features/store/objects/components/ContentOverview.js +4 -10
  164. package/lib/features/store/objects/components/ContentOverview.js.map +1 -1
  165. package/lib/features/store/objects/components/TextEditorPanel.d.ts.map +1 -1
  166. package/lib/features/store/objects/components/TextEditorPanel.js +8 -3
  167. package/lib/features/store/objects/components/TextEditorPanel.js.map +1 -1
  168. package/lib/features/store/objects/layout/renderers.d.ts.map +1 -1
  169. package/lib/features/store/objects/layout/renderers.js +1 -5
  170. package/lib/features/store/objects/layout/renderers.js.map +1 -1
  171. package/lib/features/store/objects/search/DocumentSearchContext.d.ts +29 -62
  172. package/lib/features/store/objects/search/DocumentSearchContext.d.ts.map +1 -1
  173. package/lib/features/store/objects/search/DocumentSearchContext.js +2 -0
  174. package/lib/features/store/objects/search/DocumentSearchContext.js.map +1 -1
  175. package/lib/features/store/objects/upload/DocumentUploadModal.d.ts +6 -1
  176. package/lib/features/store/objects/upload/DocumentUploadModal.d.ts.map +1 -1
  177. package/lib/features/store/objects/upload/DocumentUploadModal.js +4 -3
  178. package/lib/features/store/objects/upload/DocumentUploadModal.js.map +1 -1
  179. package/lib/features/store/objects/upload/useSmartFileUploadProcessing.d.ts.map +1 -1
  180. package/lib/features/store/objects/upload/useSmartFileUploadProcessing.js +2 -2
  181. package/lib/features/store/objects/upload/useSmartFileUploadProcessing.js.map +1 -1
  182. package/lib/features/store/types/ContentObjectTypesTable.d.ts.map +1 -1
  183. package/lib/features/store/types/ContentObjectTypesTable.js +1 -3
  184. package/lib/features/store/types/ContentObjectTypesTable.js.map +1 -1
  185. package/lib/features/store/types/IntakePolicyEditor.d.ts.map +1 -1
  186. package/lib/features/store/types/IntakePolicyEditor.js +11 -1
  187. package/lib/features/store/types/IntakePolicyEditor.js.map +1 -1
  188. package/lib/features/store/types/ObjectSchemaEditor.d.ts.map +1 -1
  189. package/lib/features/store/types/ObjectSchemaEditor.js +6 -2
  190. package/lib/features/store/types/ObjectSchemaEditor.js.map +1 -1
  191. package/lib/features/store/types/TableLayoutEditor.d.ts.map +1 -1
  192. package/lib/features/store/types/TableLayoutEditor.js +2 -0
  193. package/lib/features/store/types/TableLayoutEditor.js.map +1 -1
  194. package/lib/features/store/types/TypeRegistry.d.ts +272 -0
  195. package/lib/features/store/types/TypeRegistry.d.ts.map +1 -1
  196. package/lib/features/store/types/search/ObjectTypeSearchContext.d.ts +271 -0
  197. package/lib/features/store/types/search/ObjectTypeSearchContext.d.ts.map +1 -1
  198. package/lib/features/user/UserInfo.d.ts.map +1 -1
  199. package/lib/features/user/UserInfo.js +2 -4
  200. package/lib/features/user/UserInfo.js.map +1 -1
  201. package/lib/features/views/ViewActions.d.ts +32 -0
  202. package/lib/features/views/ViewActions.d.ts.map +1 -0
  203. package/lib/features/views/ViewActions.js +186 -0
  204. package/lib/features/views/ViewActions.js.map +1 -0
  205. package/lib/features/views/ViewDropTarget.d.ts +15 -0
  206. package/lib/features/views/ViewDropTarget.d.ts.map +1 -0
  207. package/lib/features/views/ViewDropTarget.js +79 -0
  208. package/lib/features/views/ViewDropTarget.js.map +1 -0
  209. package/lib/features/views/ViewExperience.d.ts +3 -2
  210. package/lib/features/views/ViewExperience.d.ts.map +1 -1
  211. package/lib/features/views/ViewExperience.js +103 -12
  212. package/lib/features/views/ViewExperience.js.map +1 -1
  213. package/lib/features/views/ViewNavigation.d.ts +1 -1
  214. package/lib/features/views/ViewNavigation.d.ts.map +1 -1
  215. package/lib/features/views/ViewNavigation.js +14 -5
  216. package/lib/features/views/ViewNavigation.js.map +1 -1
  217. package/lib/features/views/ViewResults.d.ts +1 -1
  218. package/lib/features/views/ViewResults.d.ts.map +1 -1
  219. package/lib/features/views/ViewResults.js +124 -34
  220. package/lib/features/views/ViewResults.js.map +1 -1
  221. package/lib/features/views/index.d.ts +1 -0
  222. package/lib/features/views/index.d.ts.map +1 -1
  223. package/lib/features/views/index.js +1 -0
  224. package/lib/features/views/index.js.map +1 -1
  225. package/lib/features/views/types.d.ts +46 -1
  226. package/lib/features/views/types.d.ts.map +1 -1
  227. package/lib/features/views/viewState.d.ts.map +1 -1
  228. package/lib/features/views/viewState.js +34 -0
  229. package/lib/features/views/viewState.js.map +1 -1
  230. package/lib/i18n/LanguageProvider.d.ts +3 -1
  231. package/lib/i18n/LanguageProvider.d.ts.map +1 -1
  232. package/lib/i18n/LanguageProvider.js +9 -7
  233. package/lib/i18n/LanguageProvider.js.map +1 -1
  234. package/lib/i18n/instance.d.ts +2 -0
  235. package/lib/i18n/instance.d.ts.map +1 -1
  236. package/lib/i18n/instance.js +45 -26
  237. package/lib/i18n/instance.js.map +1 -1
  238. package/lib/i18n/locales/ar.json +261 -15
  239. package/lib/i18n/locales/de.json +259 -13
  240. package/lib/i18n/locales/en.json +30 -4
  241. package/lib/i18n/locales/es.json +260 -14
  242. package/lib/i18n/locales/fr.json +259 -13
  243. package/lib/i18n/locales/it.json +259 -13
  244. package/lib/i18n/locales/ja.json +257 -10
  245. package/lib/i18n/locales/ko.json +257 -10
  246. package/lib/i18n/locales/pt.json +259 -13
  247. package/lib/i18n/locales/ru.json +256 -10
  248. package/lib/i18n/locales/tr.json +256 -10
  249. package/lib/i18n/locales/zh-TW.json +257 -10
  250. package/lib/i18n/locales/zh.json +257 -10
  251. package/lib/session/UserSessionProvider.d.ts.map +1 -1
  252. package/lib/session/UserSessionProvider.js +8 -16
  253. package/lib/session/UserSessionProvider.js.map +1 -1
  254. package/lib/session/auth/composable.d.ts.map +1 -1
  255. package/lib/session/auth/composable.js +25 -19
  256. package/lib/session/auth/composable.js.map +1 -1
  257. package/lib/session/auth/firebase.js +1 -1
  258. package/lib/session/auth/firebase.js.map +1 -1
  259. package/lib/shell/VertesiaShell.d.ts.map +1 -1
  260. package/lib/shell/VertesiaShell.js +2 -1
  261. package/lib/shell/VertesiaShell.js.map +1 -1
  262. package/lib/shell/apps/AppInstallationProvider.d.ts +4 -2
  263. package/lib/shell/apps/AppInstallationProvider.d.ts.map +1 -1
  264. package/lib/shell/apps/IframeAppContextSync.d.ts +3 -0
  265. package/lib/shell/apps/IframeAppContextSync.d.ts.map +1 -0
  266. package/lib/shell/apps/IframeAppContextSync.js +95 -0
  267. package/lib/shell/apps/IframeAppContextSync.js.map +1 -0
  268. package/lib/shell/apps/iframe-auth.d.ts +55 -0
  269. package/lib/shell/apps/iframe-auth.d.ts.map +1 -0
  270. package/lib/shell/apps/iframe-auth.js +154 -0
  271. package/lib/shell/apps/iframe-auth.js.map +1 -0
  272. package/lib/shell/apps/index.d.ts +2 -0
  273. package/lib/shell/apps/index.d.ts.map +1 -1
  274. package/lib/shell/apps/index.js +2 -0
  275. package/lib/shell/apps/index.js.map +1 -1
  276. package/lib/vertesia-ui-core.js +4 -4
  277. package/lib/vertesia-ui-core.js.map +1 -1
  278. package/lib/vertesia-ui-env.js +1 -1
  279. package/lib/vertesia-ui-env.js.map +1 -1
  280. package/lib/vertesia-ui-features.js +32 -34
  281. package/lib/vertesia-ui-features.js.map +1 -1
  282. package/lib/vertesia-ui-i18n.js +16 -16
  283. package/lib/vertesia-ui-i18n.js.map +1 -1
  284. package/lib/vertesia-ui-rich-text.js +4 -4
  285. package/lib/vertesia-ui-rich-text.js.map +1 -1
  286. package/lib/vertesia-ui-router.js +1 -1
  287. package/lib/vertesia-ui-router.js.map +1 -1
  288. package/lib/vertesia-ui-session.js +1 -1
  289. package/lib/vertesia-ui-session.js.map +1 -1
  290. package/lib/vertesia-ui-shell.js +1 -1
  291. package/lib/vertesia-ui-shell.js.map +1 -1
  292. package/lib/vertesia-ui-widgets.js +20 -20
  293. package/lib/vertesia-ui-widgets.js.map +1 -1
  294. package/lib/widgets/markdown/MarkdownRenderer.d.ts.map +1 -1
  295. package/lib/widgets/markdown/MarkdownRenderer.js +43 -2
  296. package/lib/widgets/markdown/MarkdownRenderer.js.map +1 -1
  297. package/lib/widgets/markdown/MermaidDiagram.d.ts.map +1 -1
  298. package/lib/widgets/markdown/MermaidDiagram.js +35 -22
  299. package/lib/widgets/markdown/MermaidDiagram.js.map +1 -1
  300. package/lib/widgets/monacoEditor/MonacoEditor.d.ts.map +1 -1
  301. package/lib/widgets/monacoEditor/MonacoEditor.js +14 -10
  302. package/lib/widgets/monacoEditor/MonacoEditor.js.map +1 -1
  303. package/lib/widgets/xml-viewer/hooks/useCollapsible.d.ts +1 -1
  304. package/package.json +24 -29
  305. package/src/core/components/shadcn/filters/comboBox/DateCombobox.tsx +1 -1
  306. package/src/core/components/shadcn/filters/filter/dateFilter.tsx +1 -1
  307. package/src/core/components/shadcn/filters/filters.tsx +1 -1
  308. package/src/core/components/shadcn/index.ts +1 -0
  309. package/src/core/components/shadcn/modal/dialog.test.tsx +35 -0
  310. package/src/core/components/shadcn/modal/dialog.tsx +0 -4
  311. package/src/core/components/shadcn/overflowTabs.tsx +320 -0
  312. package/src/core/components/shadcn/selectBox.tsx +2 -2
  313. package/src/core/components/shadcn/theme/ThemeProvider.tsx +10 -9
  314. package/src/core/utils/dayjs.ts +17 -0
  315. package/src/css/base.css +78 -0
  316. package/src/env/index.test.ts +94 -0
  317. package/src/env/index.ts +36 -1
  318. package/src/features/agent/PayloadBuilder.test.ts +68 -0
  319. package/src/features/agent/PayloadBuilder.tsx +28 -4
  320. package/src/features/agent/chat/AgentRightPanel.tsx +2 -252
  321. package/src/features/agent/chat/ArtifactsTab.tsx +1 -0
  322. package/src/features/agent/chat/AskUserWidget.test.tsx +20 -1
  323. package/src/features/agent/chat/AskUserWidget.tsx +22 -6
  324. package/src/features/agent/chat/ModernAgentConversation.test.tsx +160 -0
  325. package/src/features/agent/chat/ModernAgentConversation.tsx +111 -31
  326. package/src/features/agent/chat/ModernAgentOutput/ActiveWorkstreamsSummary.tsx +86 -67
  327. package/src/features/agent/chat/ModernAgentOutput/AllMessagesMixed.test.tsx +90 -7
  328. package/src/features/agent/chat/ModernAgentOutput/AllMessagesMixed.tsx +4 -6
  329. package/src/features/agent/chat/ModernAgentOutput/AttachmentPreview.test.ts +103 -1
  330. package/src/features/agent/chat/ModernAgentOutput/AttachmentPreview.tsx +50 -4
  331. package/src/features/agent/chat/ModernAgentOutput/BatchProgressPanel.tsx +1 -1
  332. package/src/features/agent/chat/ModernAgentOutput/Header.tsx +18 -1
  333. package/src/features/agent/chat/ModernAgentOutput/MessageItem.tsx +1 -1
  334. package/src/features/agent/chat/ModernAgentOutput/StreamingMessage.tsx +1 -1
  335. package/src/features/agent/chat/ModernAgentOutput/ToolCallGroup.tsx +1 -1
  336. package/src/features/agent/chat/ModernAgentOutput/WorkstreamTabs.tsx +37 -167
  337. package/src/features/agent/chat/ModernAgentOutput/utils.test.ts +94 -0
  338. package/src/features/agent/chat/ModernAgentOutput/utils.ts +19 -10
  339. package/src/features/agent/chat/VegaLiteChart.tsx +32 -14
  340. package/src/features/agent/chat/hooks/useAgentStream.test.tsx +18 -0
  341. package/src/features/agent/chat/hooks/useAgentStream.ts +3 -0
  342. package/src/features/document-viewer/UniversalDocumentViewer.tsx +1 -1
  343. package/src/features/facets/AgentRunnerFacetsNav.tsx +44 -4
  344. package/src/features/facets/CollectionsFacetsNav.tsx +15 -4
  345. package/src/features/facets/DocumentsFacetsNav.tsx +25 -8
  346. package/src/features/facets/FacetQueryHandlers.test.ts +84 -0
  347. package/src/features/facets/InteractionsFacetsNav.tsx +20 -4
  348. package/src/features/facets/PromptsFacetsNav.tsx +15 -4
  349. package/src/features/facets/RunsFacetsNav.test.ts +59 -0
  350. package/src/features/facets/RunsFacetsNav.tsx +40 -30
  351. package/src/features/facets/WorkflowExecutionsFacetsNav.test.ts +57 -0
  352. package/src/features/facets/WorkflowExecutionsFacetsNav.tsx +36 -16
  353. package/src/features/facets/index.ts +1 -0
  354. package/src/features/facets/utils/SearchInterface.tsx +12 -3
  355. package/src/features/layout/GenericPageNavHeader.tsx +16 -0
  356. package/src/features/magic-pdf/DownloadPopover.tsx +1 -2
  357. package/src/features/magic-pdf/GroundedExtractionView.test.tsx +7 -1
  358. package/src/features/magic-pdf/GroundedExtractionView.tsx +162 -242
  359. package/src/features/oauth/McpConnectionsButton.test.tsx +18 -1
  360. package/src/features/oauth/McpConnectionsButton.tsx +6 -2
  361. package/src/features/oauth/McpConnectionsDialog.tsx +3 -3
  362. package/src/features/oauth/useMcpConnections.test.ts +1 -0
  363. package/src/features/oauth/useMcpConnections.ts +24 -7
  364. package/src/features/pdf-viewer/PdfPageRenderer.tsx +76 -71
  365. package/src/features/pdf-viewer/lazyReactPdf.ts +33 -0
  366. package/src/features/store/collections/CollectionsTable.tsx +1 -4
  367. package/src/features/store/collections/EditCollectionView.tsx +1 -1
  368. package/src/features/store/objects/ExportPropertiesModal.tsx +25 -16
  369. package/src/features/store/objects/components/ContentOverview.tsx +2 -28
  370. package/src/features/store/objects/components/TextEditorPanel.tsx +13 -3
  371. package/src/features/store/objects/layout/renderers.tsx +1 -6
  372. package/src/features/store/objects/search/DocumentSearchContext.ts +4 -2
  373. package/src/features/store/objects/upload/DocumentUploadModal.tsx +10 -3
  374. package/src/features/store/objects/upload/useSmartFileUploadProcessing.ts +15 -6
  375. package/src/features/store/types/ContentObjectTypesTable.tsx +1 -4
  376. package/src/features/store/types/IntakePolicyEditor.tsx +11 -1
  377. package/src/features/store/types/ObjectSchemaEditor.tsx +6 -2
  378. package/src/features/store/types/TableLayoutEditor.tsx +2 -0
  379. package/src/features/user/UserInfo.test.tsx +10 -0
  380. package/src/features/user/UserInfo.tsx +2 -7
  381. package/src/features/views/ViewActions.test.tsx +80 -0
  382. package/src/features/views/ViewActions.tsx +352 -0
  383. package/src/features/views/ViewDropTarget.test.tsx +150 -0
  384. package/src/features/views/ViewDropTarget.tsx +140 -0
  385. package/src/features/views/ViewExperience.test.tsx +72 -0
  386. package/src/features/views/ViewExperience.tsx +189 -22
  387. package/src/features/views/ViewMedia.test.tsx +180 -0
  388. package/src/features/views/ViewNavigation.test.tsx +42 -0
  389. package/src/features/views/ViewNavigation.tsx +43 -5
  390. package/src/features/views/ViewResults.tsx +243 -26
  391. package/src/features/views/index.ts +1 -0
  392. package/src/features/views/types.ts +50 -0
  393. package/src/features/views/viewState.test.ts +7 -1
  394. package/src/features/views/viewState.ts +32 -0
  395. package/src/i18n/LanguageProvider.tsx +15 -8
  396. package/src/i18n/instance.test.ts +30 -0
  397. package/src/i18n/instance.ts +67 -40
  398. package/src/i18n/locales/ar.json +1157 -911
  399. package/src/i18n/locales/de.json +1113 -867
  400. package/src/i18n/locales/en.json +30 -4
  401. package/src/i18n/locales/es.json +1124 -878
  402. package/src/i18n/locales/fr.json +1124 -878
  403. package/src/i18n/locales/it.json +1124 -878
  404. package/src/i18n/locales/ja.json +1113 -866
  405. package/src/i18n/locales/ko.json +1113 -866
  406. package/src/i18n/locales/pt.json +1124 -878
  407. package/src/i18n/locales/ru.json +1135 -889
  408. package/src/i18n/locales/tr.json +1113 -867
  409. package/src/i18n/locales/zh-TW.json +1113 -866
  410. package/src/i18n/locales/zh.json +1113 -866
  411. package/src/i18n/rtl.test.ts +16 -7
  412. package/src/rich-text/VertesiaRichTextEditor.test.tsx +33 -1
  413. package/src/session/UserSessionProvider.tsx +8 -20
  414. package/src/session/auth/composable.scope.test.ts +1 -1
  415. package/src/session/auth/composable.test.ts +61 -1
  416. package/src/session/auth/composable.ts +29 -23
  417. package/src/session/auth/firebase.ts +1 -1
  418. package/src/shell/VertesiaShell.tsx +2 -0
  419. package/src/shell/apps/IframeAppContextSync.test.tsx +196 -0
  420. package/src/shell/apps/IframeAppContextSync.tsx +101 -0
  421. package/src/shell/apps/iframe-auth.test.ts +118 -0
  422. package/src/shell/apps/iframe-auth.ts +193 -0
  423. package/src/shell/apps/index.ts +2 -0
  424. package/src/widgets/markdown/ArtifactEditingSurface.test.tsx +12 -3
  425. package/src/widgets/markdown/MarkdownRenderer.tsx +50 -2
  426. package/src/widgets/markdown/MermaidDiagram.tsx +38 -22
  427. package/src/widgets/monacoEditor/MonacoEditor.tsx +27 -20
  428. package/lib/features/magic-pdf/GroundedExtractionAssistantPanel.d.ts +0 -25
  429. package/lib/features/magic-pdf/GroundedExtractionAssistantPanel.d.ts.map +0 -1
  430. package/lib/features/magic-pdf/GroundedExtractionAssistantPanel.js +0 -42
  431. package/lib/features/magic-pdf/GroundedExtractionAssistantPanel.js.map +0 -1
  432. package/src/features/magic-pdf/GroundedExtractionAssistantPanel.tsx +0 -86
@@ -1,20 +1,31 @@
1
+ import type { VertesiaClient } from '@vertesia/client';
1
2
  import type {
2
3
  ExecuteViewRequest,
4
+ Permission,
3
5
  ViewDisplayConfiguration,
4
6
  ViewExecutionResult,
5
7
  ViewHit,
6
8
  ViewNavigationItem,
7
9
  ViewResultMedia,
8
10
  } from '@vertesia/common';
9
- import { ImageRenditionFormat } from '@vertesia/common';
11
+ import { ImageRenditionFormat, Permission as PermissionValue } from '@vertesia/common';
10
12
  import { Button, ErrorBox, MessageBox, SelectBox, Spinner } from '@vertesia/ui/core';
11
13
  import { useUITranslation } from '@vertesia/ui/i18n';
12
14
  import { FullHeightLayout } from '@vertesia/ui/layout';
13
15
  import { useUserSession } from '@vertesia/ui/session';
14
16
  import { ChevronLeft, ChevronRight } from 'lucide-react';
15
- import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
17
+ import { useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react';
16
18
  import { GenericPageNavHeader } from '../layout/GenericPageNavHeader.js';
17
- import type { ViewExecutor, ViewExperienceRenderers, ViewMediaResolver } from './types.js';
19
+ import { UserPermissionsContext } from '../permissions/UserPermissionsProvider.js';
20
+ import type {
21
+ ViewExecutor,
22
+ ViewExperienceContributions,
23
+ ViewExperienceRenderers,
24
+ ViewMediaResolver,
25
+ ViewSelectionController,
26
+ } from './types.js';
27
+ import { ViewActionsProvider, ViewActionsToolbar } from './ViewActions.js';
28
+ import { ViewDropTarget } from './ViewDropTarget.js';
18
29
  import { DefaultViewNavigation } from './ViewNavigation.js';
19
30
  import { DefaultViewResults } from './ViewResults.js';
20
31
  import { DefaultViewSearch } from './ViewSearch.js';
@@ -37,6 +48,7 @@ export interface ViewExperienceProps {
37
48
  /** Override execution for embedded apps or tests. Defaults to client.views.execute. */
38
49
  execute?: ViewExecutor;
39
50
  renderers?: ViewExperienceRenderers;
51
+ contributions?: ViewExperienceContributions;
40
52
  onOpenHit?: (hit: ViewHit) => void;
41
53
  /** Override media resolution for embedded apps or custom storage backends. */
42
54
  resolveMedia?: ViewMediaResolver;
@@ -55,8 +67,18 @@ function cleanRecord(values: Record<string, string[]>): Record<string, string[]>
55
67
  return Object.keys(filtered).length > 0 ? filtered : undefined;
56
68
  }
57
69
 
70
+ function cleanStringRecord(values: Record<string, string>): Record<string, string> | undefined {
71
+ const filtered = Object.fromEntries(
72
+ Object.entries(values)
73
+ .map(([key, value]) => [key, value.trim()] as const)
74
+ .filter(([, value]) => value.length > 0),
75
+ );
76
+ return Object.keys(filtered).length > 0 ? filtered : undefined;
77
+ }
78
+
58
79
  function ViewExperienceWithSession(props: Omit<ViewExperienceProps, 'execute'>) {
59
80
  const { client } = useUserSession();
81
+ const permissions = useContext(UserPermissionsContext);
60
82
  const execute = useCallback(
61
83
  (request: ExecuteViewRequest) => client.views.execute(props.viewId, request),
62
84
  [client, props.viewId],
@@ -88,11 +110,30 @@ function ViewExperienceWithSession(props: Omit<ViewExperienceProps, 'execute'>)
88
110
  },
89
111
  [client],
90
112
  );
91
- return <ViewExperienceRuntime {...props} execute={execute} resolveMedia={props.resolveMedia ?? resolveMedia} />;
113
+ const hasAnyPermission = (values: Permission[]) =>
114
+ permissions !== undefined && values.some((permission) => permissions.hasPermission(permission));
115
+ return (
116
+ <ViewExperienceRuntime
117
+ {...props}
118
+ execute={execute}
119
+ resolveMedia={props.resolveMedia ?? resolveMedia}
120
+ client={client}
121
+ canDelete={hasAnyPermission([
122
+ PermissionValue.content_delete,
123
+ PermissionValue.content_admin,
124
+ PermissionValue.content_superadmin,
125
+ ])}
126
+ canWrite={hasAnyPermission([
127
+ PermissionValue.content_write,
128
+ PermissionValue.content_admin,
129
+ PermissionValue.content_superadmin,
130
+ ])}
131
+ />
132
+ );
92
133
  }
93
134
 
94
135
  /**
95
- * Reusable renderer for stored and app-contributed View Experiences.
136
+ * Reusable renderer for stored, system, and app-contributed View Experiences.
96
137
  * Pass `execute` to use it outside Vertesia's session provider.
97
138
  */
98
139
  export function ViewExperience({ execute, ...props }: ViewExperienceProps) {
@@ -105,16 +146,23 @@ export function ViewExperience({ execute, ...props }: ViewExperienceProps) {
105
146
 
106
147
  interface ViewExperienceRuntimeProps extends Omit<ViewExperienceProps, 'execute'> {
107
148
  execute: ViewExecutor;
149
+ client?: VertesiaClient;
150
+ canDelete?: boolean;
151
+ canWrite?: boolean;
108
152
  }
109
153
 
110
154
  function ViewExperienceRuntime({
111
155
  execute,
112
156
  renderers,
157
+ contributions,
113
158
  onOpenHit,
114
159
  resolveMedia,
115
160
  syncUrl = true,
116
161
  showHeader = true,
117
162
  className,
163
+ client,
164
+ canDelete = false,
165
+ canWrite = false,
118
166
  }: ViewExperienceRuntimeProps) {
119
167
  const { t } = useUITranslation();
120
168
  const executeRef = useRef(execute);
@@ -126,10 +174,18 @@ function ViewExperienceRuntime({
126
174
  const [result, setResult] = useState<ViewExecutionResult>();
127
175
  const [isLoading, setIsLoading] = useState(true);
128
176
  const [error, setError] = useState<Error>();
177
+ const [selectedHits, setSelectedHits] = useState<Record<string, ViewHit>>({});
178
+ const selectionAnchorRef = useRef<string | undefined>(undefined);
179
+
180
+ const clearSelection = useCallback(() => {
181
+ selectionAnchorRef.current = undefined;
182
+ setSelectedHits({});
183
+ }, []);
129
184
 
130
185
  const runRequest = useCallback(
131
- (next: ExecuteViewRequest, updateUrl: boolean) => {
186
+ (next: ExecuteViewRequest, updateUrl: boolean, preserveSelection = false) => {
132
187
  const generation = ++generationRef.current;
188
+ if (!preserveSelection) clearSelection();
133
189
  setRequest(next);
134
190
  if (updateUrl && syncUrl) replaceViewStateInUrl(next);
135
191
  setIsLoading(true);
@@ -153,7 +209,7 @@ function ViewExperienceRuntime({
153
209
  if (generation === generationRef.current) setIsLoading(false);
154
210
  });
155
211
  },
156
- [syncUrl],
212
+ [clearSelection, syncUrl],
157
213
  );
158
214
 
159
215
  const loadUrlState = useCallback(() => {
@@ -183,6 +239,7 @@ function ViewExperienceRuntime({
183
239
  [definition?.navigation],
184
240
  );
185
241
  const resultsConfiguration = definition?.results;
242
+ const selectionConfiguration = resultsConfiguration?.selection;
186
243
  const effectiveDisplayId = result?.display ?? request.display ?? resultsConfiguration?.default_display;
187
244
  const display =
188
245
  resultsConfiguration?.displays.find((candidate) => candidate.id === effectiveDisplayId) ?? FALLBACK_DISPLAY;
@@ -199,6 +256,14 @@ function ViewExperienceRuntime({
199
256
  applyRequest({ ...request, navigation: nextNavigation, offset: undefined });
200
257
  };
201
258
 
259
+ const updateNavigationQuery = (item: ViewNavigationItem, query: string) => {
260
+ const navigation_queries = cleanStringRecord({
261
+ ...(request.navigation_queries ?? {}),
262
+ [item.id]: query,
263
+ });
264
+ applyRequest({ ...request, navigation_queries, offset: undefined });
265
+ };
266
+
202
267
  const submitSearch = () => {
203
268
  applyRequest({
204
269
  ...request,
@@ -208,6 +273,59 @@ function ViewExperienceRuntime({
208
273
  });
209
274
  };
210
275
 
276
+ const selection = useMemo<ViewSelectionController | undefined>(() => {
277
+ if (!selectionConfiguration) return undefined;
278
+ const selectedIds = Object.keys(selectedHits);
279
+ return {
280
+ mode: selectionConfiguration.mode,
281
+ selectAll: selectionConfiguration.mode === 'multiple' && selectionConfiguration.select_all === 'page',
282
+ selectedIds,
283
+ selectedHits: selectedIds.map((id) => selectedHits[id]).filter((hit): hit is ViewHit => hit !== undefined),
284
+ isSelected: (id) => selectedHits[id] !== undefined,
285
+ toggle: (hit, selected, options) => {
286
+ setSelectedHits((current) => {
287
+ if (!selected) {
288
+ const next = { ...current };
289
+ delete next[hit.id];
290
+ return next;
291
+ }
292
+ if (selectionConfiguration.mode === 'single') {
293
+ selectionAnchorRef.current = hit.id;
294
+ return { [hit.id]: hit };
295
+ }
296
+ const next = { ...current, [hit.id]: hit };
297
+ if (options?.range && options.page && selectionAnchorRef.current) {
298
+ const anchorIndex = options.page.findIndex(
299
+ (candidate) => candidate.id === selectionAnchorRef.current,
300
+ );
301
+ const hitIndex = options.page.findIndex((candidate) => candidate.id === hit.id);
302
+ if (anchorIndex >= 0 && hitIndex >= 0) {
303
+ const start = Math.min(anchorIndex, hitIndex);
304
+ const end = Math.max(anchorIndex, hitIndex);
305
+ for (const candidate of options.page.slice(start, end + 1)) {
306
+ next[candidate.id] = candidate;
307
+ }
308
+ }
309
+ }
310
+ selectionAnchorRef.current = hit.id;
311
+ return next;
312
+ });
313
+ },
314
+ togglePage: (hits, selected) => {
315
+ if (selectionConfiguration.mode !== 'multiple') return;
316
+ setSelectedHits((current) => {
317
+ const next = { ...current };
318
+ for (const hit of hits) {
319
+ if (selected) next[hit.id] = hit;
320
+ else delete next[hit.id];
321
+ }
322
+ return next;
323
+ });
324
+ },
325
+ clear: clearSelection,
326
+ };
327
+ }, [clearSelection, selectedHits, selectionConfiguration]);
328
+
211
329
  if (!result && isLoading) {
212
330
  return (
213
331
  <div className="flex h-full min-h-48 items-center justify-center">
@@ -255,11 +373,14 @@ function ViewExperienceRuntime({
255
373
  result={navigationResult}
256
374
  isLoading={isLoading}
257
375
  onChange={(values) => updateNavigation(item, values)}
376
+ onQueryChange={item.source === 'collection' ? (query) => updateNavigationQuery(item, query) : undefined}
258
377
  />
259
378
  );
260
379
  });
261
380
 
262
- return (
381
+ const refresh = () => runRequest(request, false, true);
382
+
383
+ const content = (
263
384
  <FullHeightLayout className={className}>
264
385
  {showHeader && <GenericPageNavHeader title={definition.name} description={definition.description} />}
265
386
  <FullHeightLayout.Fixed heightClass="h-auto" className="space-y-3 border-b p-3">
@@ -324,6 +445,11 @@ function ViewExperienceRuntime({
324
445
  {isLoading && <Spinner size="sm" />}
325
446
  </div>
326
447
  <div className="flex flex-wrap items-center gap-3">
448
+ <ViewActionsToolbar
449
+ selection={selection}
450
+ page={result.hits}
451
+ showSelectPage={display.type !== 'table'}
452
+ />
327
453
  {resultsConfiguration?.allow_display_switch &&
328
454
  resultsConfiguration.displays.length > 1 && (
329
455
  <div className="flex items-center gap-2">
@@ -332,7 +458,11 @@ function ViewExperienceRuntime({
332
458
  options={resultsConfiguration.displays}
333
459
  value={display}
334
460
  onChange={(option) =>
335
- applyRequest({ ...request, display: option.id, offset: undefined })
461
+ void runRequest(
462
+ { ...request, display: option.id, offset: undefined },
463
+ true,
464
+ true,
465
+ )
336
466
  }
337
467
  optionLabel={(option) => option.label}
338
468
  by="id"
@@ -351,7 +481,11 @@ function ViewExperienceRuntime({
351
481
  (option) => option.id === effectiveSortId,
352
482
  )}
353
483
  onChange={(option) =>
354
- applyRequest({ ...request, sort: option.id, offset: undefined })
484
+ void runRequest(
485
+ { ...request, sort: option.id, offset: undefined },
486
+ true,
487
+ true,
488
+ )
355
489
  }
356
490
  optionLabel={(option) => option.label}
357
491
  by="id"
@@ -363,16 +497,28 @@ function ViewExperienceRuntime({
363
497
  )}
364
498
  </div>
365
499
  </div>
366
- <ResultsRenderer
367
- configuration={display}
500
+ <ViewDropTarget
368
501
  definition={definition}
369
502
  request={request}
370
503
  result={result}
371
- isLoading={isLoading}
372
- onSortChange={(sort) => applyRequest({ ...request, sort, offset: undefined })}
373
- onOpenHit={onOpenHit}
374
- resolveMedia={resolveMedia}
375
- />
504
+ contribution={contributions?.drop}
505
+ canWrite={canWrite}
506
+ refresh={refresh}
507
+ >
508
+ <ResultsRenderer
509
+ configuration={display}
510
+ definition={definition}
511
+ request={request}
512
+ result={result}
513
+ isLoading={isLoading}
514
+ onSortChange={(sort) =>
515
+ void runRequest({ ...request, sort, offset: undefined }, true, true)
516
+ }
517
+ onOpenHit={onOpenHit}
518
+ resolveMedia={resolveMedia}
519
+ selection={selection}
520
+ />
521
+ </ViewDropTarget>
376
522
  {(hasPrevious || hasNext) && (
377
523
  <nav className="flex items-center justify-center gap-2" aria-label={t('view.pagination')}>
378
524
  <Button
@@ -380,10 +526,14 @@ function ViewExperienceRuntime({
380
526
  variant="outline"
381
527
  disabled={!hasPrevious || isLoading}
382
528
  onClick={() =>
383
- applyRequest({
384
- ...request,
385
- offset: Math.max(0, offset - pageStep) || undefined,
386
- })
529
+ void runRequest(
530
+ {
531
+ ...request,
532
+ offset: Math.max(0, offset - pageStep) || undefined,
533
+ },
534
+ true,
535
+ true,
536
+ )
387
537
  }
388
538
  >
389
539
  <ChevronLeft className="size-4 cn-rtl-flip" />
@@ -393,7 +543,9 @@ function ViewExperienceRuntime({
393
543
  type="button"
394
544
  variant="outline"
395
545
  disabled={!hasNext || isLoading}
396
- onClick={() => applyRequest({ ...request, offset: offset + pageStep })}
546
+ onClick={() =>
547
+ void runRequest({ ...request, offset: offset + pageStep }, true, true)
548
+ }
397
549
  >
398
550
  {t('grounded.nextPage')}
399
551
  <ChevronRight className="size-4 cn-rtl-flip" />
@@ -405,4 +557,19 @@ function ViewExperienceRuntime({
405
557
  </FullHeightLayout.Body>
406
558
  </FullHeightLayout>
407
559
  );
560
+
561
+ return (
562
+ <ViewActionsProvider
563
+ definition={definition}
564
+ request={request}
565
+ result={result}
566
+ selection={selection}
567
+ contributions={contributions}
568
+ client={client}
569
+ canDelete={canDelete}
570
+ refresh={refresh}
571
+ >
572
+ {content}
573
+ </ViewActionsProvider>
574
+ );
408
575
  }
@@ -0,0 +1,180 @@
1
+ import { cleanup, fireEvent, screen, waitFor } from '@testing-library/react';
2
+ import {
3
+ ContentObjectStatus,
4
+ type ExecuteViewRequest,
5
+ type ViewDisplayConfiguration,
6
+ type ViewExecutionDefinition,
7
+ type ViewExecutionResult,
8
+ } from '@vertesia/common';
9
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
10
+ import { renderWithProviders } from '../../__tests__/test-utils.js';
11
+ import type { ViewMediaResolver } from './types.js';
12
+ import { DefaultViewResults } from './ViewResults.js';
13
+
14
+ const display: ViewDisplayConfiguration = {
15
+ id: 'list',
16
+ label: 'List',
17
+ type: 'list',
18
+ title: { field: 'name', label: 'Name' },
19
+ media: { source: 'content_thumbnail' },
20
+ };
21
+
22
+ const definition: ViewExecutionDefinition = {
23
+ name: 'Document Library',
24
+ results: { default_display: 'list', displays: [display] },
25
+ };
26
+
27
+ const request: ExecuteViewRequest = { display: 'list' };
28
+
29
+ const result: ViewExecutionResult = {
30
+ view: 'document-lib',
31
+ revision: 1,
32
+ definition,
33
+ display: 'list',
34
+ search: { requested_mode: 'browse', applied_mode: 'browse', warnings: [] },
35
+ hits: [
36
+ {
37
+ id: 'document-1',
38
+ document: {
39
+ id: 'document-1',
40
+ name: 'Renewal Agreement',
41
+ created_at: '2026-01-01T00:00:00.000Z',
42
+ created_by: 'user-1',
43
+ updated_at: '2026-01-02T00:00:00.000Z',
44
+ updated_by: 'user-1',
45
+ location: '/Customers/Acme',
46
+ status: ContentObjectStatus.completed,
47
+ properties: {},
48
+ revision: { root: 'document-1', head: true },
49
+ },
50
+ },
51
+ ],
52
+ total: 1,
53
+ navigation: {},
54
+ took: 1,
55
+ };
56
+
57
+ function renderResults(resolveMedia: ViewMediaResolver) {
58
+ return renderWithProviders(
59
+ <DefaultViewResults
60
+ configuration={display}
61
+ definition={definition}
62
+ request={request}
63
+ result={result}
64
+ isLoading={false}
65
+ resolveMedia={resolveMedia}
66
+ />,
67
+ );
68
+ }
69
+
70
+ // Property-backed media: the URL comes straight off the hit, so no resolver runs and no mediaKey
71
+ // exists. Rendered through the same DefaultViewResults path with a `thumbnail` property.
72
+ const propertyDisplay: ViewDisplayConfiguration = {
73
+ ...display,
74
+ media: { source: 'property', field: 'properties.thumbnail' },
75
+ };
76
+
77
+ const propertyDefinition: ViewExecutionDefinition = {
78
+ name: 'Document Library',
79
+ results: { default_display: 'list', displays: [propertyDisplay] },
80
+ };
81
+
82
+ function propertyResults(thumbnail: string) {
83
+ const hit = result.hits[0];
84
+ const propertyResult: ViewExecutionResult = {
85
+ ...result,
86
+ definition: propertyDefinition,
87
+ hits: [{ ...hit, document: { ...hit.document, properties: { thumbnail } } }],
88
+ };
89
+ return (
90
+ <DefaultViewResults
91
+ configuration={propertyDisplay}
92
+ definition={propertyDefinition}
93
+ request={request}
94
+ result={propertyResult}
95
+ isLoading={false}
96
+ />
97
+ );
98
+ }
99
+
100
+ function renderPropertyResults(thumbnail: string) {
101
+ const rendered = renderWithProviders(propertyResults(thumbnail));
102
+ return {
103
+ container: rendered.container,
104
+ rerenderWith: (next: string) => rendered.rerender(propertyResults(next)),
105
+ };
106
+ }
107
+
108
+ describe('ViewMedia resolution', () => {
109
+ beforeEach(() => {
110
+ vi.useFakeTimers({ shouldAdvanceTime: true });
111
+ });
112
+
113
+ afterEach(() => {
114
+ vi.useRealTimers();
115
+ cleanup();
116
+ });
117
+
118
+ it('keeps concurrent resolutions of the same media separate per resolver', async () => {
119
+ const first = vi.fn<ViewMediaResolver>(async () => 'https://cdn.test/first.png');
120
+ const second = vi.fn<ViewMediaResolver>(async () => 'https://cdn.test/second.png');
121
+
122
+ const a = renderResults(first);
123
+ const b = renderResults(second);
124
+
125
+ await waitFor(() => {
126
+ expect(a.container.querySelector('img')?.getAttribute('src')).toBe('https://cdn.test/first.png');
127
+ expect(b.container.querySelector('img')?.getAttribute('src')).toBe('https://cdn.test/second.png');
128
+ });
129
+ expect(first).toHaveBeenCalledTimes(1);
130
+ expect(second).toHaveBeenCalledTimes(1);
131
+ });
132
+
133
+ it('retries a resolution that has no URL yet, then settles on the fallback', async () => {
134
+ const resolveMedia = vi.fn<ViewMediaResolver>(async () => undefined);
135
+ renderResults(resolveMedia);
136
+
137
+ await waitFor(() => expect(resolveMedia).toHaveBeenCalledTimes(1));
138
+ // Three backoff steps (2s, 4s, 8s), then the tile stops asking.
139
+ for (const [delay, expected] of [
140
+ [2_000, 2],
141
+ [4_000, 3],
142
+ [8_000, 4],
143
+ ]) {
144
+ await vi.advanceTimersByTimeAsync(delay);
145
+ await waitFor(() => expect(resolveMedia).toHaveBeenCalledTimes(expected));
146
+ }
147
+ await vi.advanceTimersByTimeAsync(30_000);
148
+ expect(resolveMedia).toHaveBeenCalledTimes(4);
149
+ expect(screen.queryByRole('img')).toBeNull();
150
+ });
151
+
152
+ it('does not retry a failed resolution', async () => {
153
+ const resolveMedia = vi.fn<ViewMediaResolver>(async () => {
154
+ throw new Error('Internal Server Error');
155
+ });
156
+ renderResults(resolveMedia);
157
+
158
+ await waitFor(() => expect(resolveMedia).toHaveBeenCalledTimes(1));
159
+ await vi.advanceTimersByTimeAsync(60_000);
160
+ expect(resolveMedia).toHaveBeenCalledTimes(1);
161
+ });
162
+
163
+ it('shows a refreshed direct URL after the previous one failed to load', async () => {
164
+ const { container, rerenderWith } = renderPropertyResults('https://cdn.test/stale.png');
165
+
166
+ const img = () => container.querySelector('img');
167
+ expect(img()?.getAttribute('src')).toBe('https://cdn.test/stale.png');
168
+
169
+ // The browser cannot fetch it — the tile falls back to the icon.
170
+ fireEvent.error(img() as HTMLImageElement);
171
+ await waitFor(() => expect(container.querySelector('img')).toBeNull());
172
+
173
+ // A refreshed URL arrives on the same hit. No mediaKey exists for property media, so only
174
+ // directUrl can tell the effect to clear the failure.
175
+ rerenderWith('https://cdn.test/fresh.png');
176
+ await waitFor(() =>
177
+ expect(container.querySelector('img')?.getAttribute('src')).toBe('https://cdn.test/fresh.png'),
178
+ );
179
+ });
180
+ });
@@ -83,4 +83,46 @@ describe('DefaultViewNavigation', () => {
83
83
  fireEvent.click(screen.getByRole('button', { name: 'FL' }));
84
84
  expect(onChange).toHaveBeenLastCalledWith(['h1:florida']);
85
85
  });
86
+
87
+ it('renders location breadcrumbs and navigates to an ancestor', () => {
88
+ const onChange = vi.fn();
89
+ renderWithProviders(
90
+ <DefaultViewNavigation
91
+ configuration={{ id: 'location', label: 'Location', source: 'location' }}
92
+ result={{
93
+ id: 'location',
94
+ selected: ['/Customers/Acme'],
95
+ breadcrumbs: [
96
+ { id: '/Customers', label: 'Customers', count: 12 },
97
+ { id: '/Customers/Acme', label: 'Acme', count: 8, selected: true },
98
+ ],
99
+ nodes: [{ id: '/Customers/Acme/Orders', label: 'Orders', count: 8 }],
100
+ }}
101
+ isLoading={false}
102
+ onChange={onChange}
103
+ />,
104
+ );
105
+
106
+ fireEvent.click(screen.getByRole('button', { name: 'Customers' }));
107
+ expect(onChange).toHaveBeenCalledWith(['/Customers']);
108
+ });
109
+
110
+ it('submits a collection navigation query', () => {
111
+ const onQueryChange = vi.fn();
112
+ renderWithProviders(
113
+ <DefaultViewNavigation
114
+ configuration={{ id: 'collections', label: 'Collections', source: 'collection' }}
115
+ result={{ id: 'collections', selected: [], nodes: [] }}
116
+ isLoading={false}
117
+ onChange={vi.fn()}
118
+ onQueryChange={onQueryChange}
119
+ />,
120
+ );
121
+
122
+ fireEvent.change(screen.getByRole('textbox', { name: 'Filter Collections' }), {
123
+ target: { value: ' legal ' },
124
+ });
125
+ fireEvent.click(screen.getByRole('button', { name: 'Search Collections' }));
126
+ expect(onQueryChange).toHaveBeenCalledWith('legal');
127
+ });
86
128
  });
@@ -1,8 +1,8 @@
1
1
  import type { ViewNavigationNode } from '@vertesia/common';
2
- import { Button, Checkbox, SelectBox } from '@vertesia/ui/core';
2
+ import { Button, Checkbox, Input, SelectBox } from '@vertesia/ui/core';
3
3
  import { useUITranslation } from '@vertesia/ui/i18n';
4
- import { ChevronRight, X } from 'lucide-react';
5
- import { useId } from 'react';
4
+ import { ChevronRight, Search, X } from 'lucide-react';
5
+ import { type SyntheticEvent, useEffect, useId, useState } from 'react';
6
6
  import type { ViewNavigationRendererProps } from './types.js';
7
7
 
8
8
  function nextSelection(current: string[], id: string, selected: boolean, multiSelect: boolean | undefined): string[] {
@@ -20,7 +20,13 @@ function NodeLabel({ node }: { node: ViewNavigationNode }) {
20
20
  );
21
21
  }
22
22
 
23
- export function DefaultViewNavigation({ configuration, result, isLoading, onChange }: ViewNavigationRendererProps) {
23
+ export function DefaultViewNavigation({
24
+ configuration,
25
+ result,
26
+ isLoading,
27
+ onChange,
28
+ onQueryChange,
29
+ }: ViewNavigationRendererProps) {
24
30
  const { t } = useUITranslation();
25
31
  const idPrefix = useId();
26
32
  const presentation =
@@ -28,11 +34,21 @@ export function DefaultViewNavigation({ configuration, result, isLoading, onChan
28
34
  (configuration.source === 'location' || configuration.source === 'hierarchy' ? 'tree' : 'list');
29
35
  const multiSelect = configuration.source === 'hierarchy' ? false : configuration.multi_select;
30
36
  const breadcrumbs = result.breadcrumbs ?? [];
37
+ const [draftQuery, setDraftQuery] = useState(result.query ?? '');
38
+
39
+ useEffect(() => {
40
+ setDraftQuery(result.query ?? '');
41
+ }, [result.query]);
31
42
 
32
43
  const toggle = (id: string, selected: boolean) => {
33
44
  onChange(nextSelection(result.selected, id, selected, multiSelect));
34
45
  };
35
46
 
47
+ const submitQuery = (event: SyntheticEvent<HTMLFormElement>) => {
48
+ event.preventDefault();
49
+ onQueryChange?.(draftQuery.trim());
50
+ };
51
+
36
52
  return (
37
53
  <section className="space-y-2" aria-labelledby={`${idPrefix}-label`}>
38
54
  <div className="flex items-center justify-between gap-2">
@@ -54,7 +70,28 @@ export function DefaultViewNavigation({ configuration, result, isLoading, onChan
54
70
  )}
55
71
  </div>
56
72
 
57
- {configuration.source === 'hierarchy' && breadcrumbs.length > 0 && (
73
+ {configuration.source === 'collection' && onQueryChange && (
74
+ <form className="flex items-center gap-1" onSubmit={submitQuery}>
75
+ <Input
76
+ value={draftQuery}
77
+ onChange={setDraftQuery}
78
+ disabled={isLoading}
79
+ placeholder={t('view.filterNavigation', { label: configuration.label })}
80
+ aria-label={t('view.filterNavigation', { label: configuration.label })}
81
+ />
82
+ <Button
83
+ type="submit"
84
+ variant="outline"
85
+ size="icon"
86
+ disabled={isLoading}
87
+ aria-label={t('view.searchNavigation', { label: configuration.label })}
88
+ >
89
+ <Search aria-hidden="true" className="size-4" />
90
+ </Button>
91
+ </form>
92
+ )}
93
+
94
+ {breadcrumbs.length > 0 && (
58
95
  <nav aria-label={`${configuration.label} path`}>
59
96
  <ol className="flex flex-wrap items-center gap-1 text-sm">
60
97
  {breadcrumbs.map((node, index) => (
@@ -77,6 +114,7 @@ export function DefaultViewNavigation({ configuration, result, isLoading, onChan
77
114
  )}
78
115
 
79
116
  {result.selected.length > 0 &&
117
+ breadcrumbs.length === 0 &&
80
118
  (configuration.source === 'location' || configuration.source === 'collection') && (
81
119
  <div className="flex flex-wrap gap-1">
82
120
  {result.selected.map((value) => {