@vertesia/ui 1.5.0-dev.20260905.011013Z → 1.5.0-dev.20260910.052912Z

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 (508) hide show
  1. package/lib/core/components/Avatar.d.ts.map +1 -1
  2. package/lib/core/components/Avatar.js +3 -3
  3. package/lib/core/components/Avatar.js.map +1 -1
  4. package/lib/core/components/ComboBox.js +1 -1
  5. package/lib/core/components/ComboBox.js.map +1 -1
  6. package/lib/core/components/FileUpload.js +1 -1
  7. package/lib/core/components/FileUpload.js.map +1 -1
  8. package/lib/core/components/Link.js +1 -1
  9. package/lib/core/components/Link.js.map +1 -1
  10. package/lib/core/components/SelectList.js +1 -1
  11. package/lib/core/components/SelectList.js.map +1 -1
  12. package/lib/core/components/SidePanel.js +1 -1
  13. package/lib/core/components/SidePanel.js.map +1 -1
  14. package/lib/core/components/Spinner.js +1 -1
  15. package/lib/core/components/Spinner.js.map +1 -1
  16. package/lib/core/components/TagsInput.js +8 -8
  17. package/lib/core/components/TagsInput.js.map +1 -1
  18. package/lib/core/components/shadcn/MessageBox.js +1 -1
  19. package/lib/core/components/shadcn/MessageBox.js.map +1 -1
  20. package/lib/core/components/shadcn/button.js +1 -1
  21. package/lib/core/components/shadcn/button.js.map +1 -1
  22. package/lib/core/components/shadcn/card.d.ts.map +1 -1
  23. package/lib/core/components/shadcn/card.js +1 -1
  24. package/lib/core/components/shadcn/card.js.map +1 -1
  25. package/lib/core/components/shadcn/command.js +5 -5
  26. package/lib/core/components/shadcn/command.js.map +1 -1
  27. package/lib/core/components/shadcn/filters/DynamicLabel.js +1 -1
  28. package/lib/core/components/shadcn/filters/DynamicLabel.js.map +1 -1
  29. package/lib/core/components/shadcn/filters/comboBox/DateCombobox.js +3 -3
  30. package/lib/core/components/shadcn/filters/comboBox/DateCombobox.js.map +1 -1
  31. package/lib/core/components/shadcn/input.js +3 -3
  32. package/lib/core/components/shadcn/input.js.map +1 -1
  33. package/lib/core/components/shadcn/modal/ConfirmModal.js +1 -1
  34. package/lib/core/components/shadcn/modal/ConfirmModal.js.map +1 -1
  35. package/lib/core/components/shadcn/modal/dialog.d.ts.map +1 -1
  36. package/lib/core/components/shadcn/modal/dialog.js +2 -2
  37. package/lib/core/components/shadcn/modal/dialog.js.map +1 -1
  38. package/lib/core/components/shadcn/overflowTabs.js +2 -2
  39. package/lib/core/components/shadcn/overflowTabs.js.map +1 -1
  40. package/lib/core/components/shadcn/popover.js +1 -1
  41. package/lib/core/components/shadcn/popover.js.map +1 -1
  42. package/lib/core/components/shadcn/radioGroup.d.ts.map +1 -1
  43. package/lib/core/components/shadcn/radioGroup.js +3 -3
  44. package/lib/core/components/shadcn/radioGroup.js.map +1 -1
  45. package/lib/core/components/shadcn/selectBox.js +1 -1
  46. package/lib/core/components/shadcn/selectBox.js.map +1 -1
  47. package/lib/core/components/shadcn/tabs.d.ts.map +1 -1
  48. package/lib/core/components/shadcn/tabs.js +5 -2
  49. package/lib/core/components/shadcn/tabs.js.map +1 -1
  50. package/lib/core/components/styles.js +1 -1
  51. package/lib/core/components/styles.js.map +1 -1
  52. package/lib/core/components/table/index.js +1 -1
  53. package/lib/core/hooks/useFetch.d.ts.map +1 -1
  54. package/lib/core/hooks/useFetch.js +2 -0
  55. package/lib/core/hooks/useFetch.js.map +1 -1
  56. package/lib/features/activity-doc/ActivityDoc.js +8 -8
  57. package/lib/features/activity-doc/ActivityDoc.js.map +1 -1
  58. package/lib/features/agent/chat/AgentChart.js +1 -1
  59. package/lib/features/agent/chat/AgentChart.js.map +1 -1
  60. package/lib/features/agent/chat/AskUserWidget.d.ts.map +1 -1
  61. package/lib/features/agent/chat/AskUserWidget.js +13 -13
  62. package/lib/features/agent/chat/AskUserWidget.js.map +1 -1
  63. package/lib/features/agent/chat/JumpingDots.js +1 -1
  64. package/lib/features/agent/chat/JumpingDots.js.map +1 -1
  65. package/lib/features/agent/chat/ModernAgentConversation.js +1 -1
  66. package/lib/features/agent/chat/ModernAgentConversation.js.map +1 -1
  67. package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.d.ts.map +1 -1
  68. package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.js +22 -9
  69. package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.js.map +1 -1
  70. package/lib/features/agent/chat/ModernAgentOutput/BatchProgressPanel.js +5 -5
  71. package/lib/features/agent/chat/ModernAgentOutput/BatchProgressPanel.js.map +1 -1
  72. package/lib/features/agent/chat/ModernAgentOutput/Header.js +1 -1
  73. package/lib/features/agent/chat/ModernAgentOutput/Header.js.map +1 -1
  74. package/lib/features/agent/chat/ModernAgentOutput/InlineSlideInPanel.js +1 -1
  75. package/lib/features/agent/chat/ModernAgentOutput/InlineSlideInPanel.js.map +1 -1
  76. package/lib/features/agent/chat/ModernAgentOutput/MessageInput.js +1 -1
  77. package/lib/features/agent/chat/ModernAgentOutput/MessageInput.js.map +1 -1
  78. package/lib/features/agent/chat/ModernAgentOutput/MessageItem.d.ts.map +1 -1
  79. package/lib/features/agent/chat/ModernAgentOutput/MessageItem.js +7 -7
  80. package/lib/features/agent/chat/ModernAgentOutput/MessageItem.js.map +1 -1
  81. package/lib/features/agent/chat/ModernAgentOutput/MessagesContainer.js +1 -1
  82. package/lib/features/agent/chat/ModernAgentOutput/MessagesContainer.js.map +1 -1
  83. package/lib/features/agent/chat/ModernAgentOutput/PlanPanel.d.ts.map +1 -1
  84. package/lib/features/agent/chat/ModernAgentOutput/PlanPanel.js +10 -10
  85. package/lib/features/agent/chat/ModernAgentOutput/PlanPanel.js.map +1 -1
  86. package/lib/features/agent/chat/ModernAgentOutput/SlideInPanel.js +1 -1
  87. package/lib/features/agent/chat/ModernAgentOutput/SlideInPanel.js.map +1 -1
  88. package/lib/features/agent/chat/ModernAgentOutput/SlidingMessages.d.ts.map +1 -1
  89. package/lib/features/agent/chat/ModernAgentOutput/SlidingMessages.js +1 -1
  90. package/lib/features/agent/chat/ModernAgentOutput/SlidingMessages.js.map +1 -1
  91. package/lib/features/agent/chat/ModernAgentOutput/SlidingPlanPanel.js +17 -17
  92. package/lib/features/agent/chat/ModernAgentOutput/SlidingPlanPanel.js.map +1 -1
  93. package/lib/features/agent/chat/ModernAgentOutput/StreamingMessage.js +1 -1
  94. package/lib/features/agent/chat/ModernAgentOutput/StreamingMessage.js.map +1 -1
  95. package/lib/features/agent/chat/ModernAgentOutput/SummaryConversation.d.ts.map +1 -1
  96. package/lib/features/agent/chat/ModernAgentOutput/SummaryConversation.js +14 -2
  97. package/lib/features/agent/chat/ModernAgentOutput/SummaryConversation.js.map +1 -1
  98. package/lib/features/agent/chat/ModernAgentOutput/ToolCallGroup.d.ts.map +1 -1
  99. package/lib/features/agent/chat/ModernAgentOutput/ToolCallGroup.js +15 -15
  100. package/lib/features/agent/chat/ModernAgentOutput/ToolCallGroup.js.map +1 -1
  101. package/lib/features/agent/chat/ModernAgentOutput/requestInputMessages.d.ts.map +1 -1
  102. package/lib/features/agent/chat/ModernAgentOutput/requestInputMessages.js +18 -0
  103. package/lib/features/agent/chat/ModernAgentOutput/requestInputMessages.js.map +1 -1
  104. package/lib/features/agent/chat/SlidingThinkingIndicator.d.ts.map +1 -1
  105. package/lib/features/agent/chat/SlidingThinkingIndicator.js +5 -2
  106. package/lib/features/agent/chat/SlidingThinkingIndicator.js.map +1 -1
  107. package/lib/features/agent/chat/VegaLiteChart.d.ts.map +1 -1
  108. package/lib/features/agent/chat/VegaLiteChart.js +6 -2
  109. package/lib/features/agent/chat/VegaLiteChart.js.map +1 -1
  110. package/lib/features/errors/RowErrorBoundary.js +1 -1
  111. package/lib/features/errors/RowErrorBoundary.js.map +1 -1
  112. package/lib/features/facets/AgentRunnerFacetsNav.js +1 -1
  113. package/lib/features/facets/AgentRunnerFacetsNav.js.map +1 -1
  114. package/lib/features/facets/utils/VInteractionFacet.d.ts +3 -5
  115. package/lib/features/facets/utils/VInteractionFacet.d.ts.map +1 -1
  116. package/lib/features/facets/utils/VInteractionFacet.js +10 -23
  117. package/lib/features/facets/utils/VInteractionFacet.js.map +1 -1
  118. package/lib/features/facets/utils/VUserFacet.js +1 -1
  119. package/lib/features/facets/utils/VUserFacet.js.map +1 -1
  120. package/lib/features/layout/GenericPageNavHeader.d.ts.map +1 -1
  121. package/lib/features/layout/GenericPageNavHeader.js +4 -1
  122. package/lib/features/layout/GenericPageNavHeader.js.map +1 -1
  123. package/lib/features/layout/NotFoundView.js +1 -1
  124. package/lib/features/layout/NotFoundView.js.map +1 -1
  125. package/lib/features/magic-pdf/AnnotatedImageSlider.js +4 -12
  126. package/lib/features/magic-pdf/AnnotatedImageSlider.js.map +1 -1
  127. package/lib/features/magic-pdf/ExtractedContentView.js +4 -4
  128. package/lib/features/magic-pdf/ExtractedContentView.js.map +1 -1
  129. package/lib/features/magic-pdf/MagicPdfView.js +1 -1
  130. package/lib/features/magic-pdf/MagicPdfView.js.map +1 -1
  131. package/lib/features/pdf-viewer/PdfPageRenderer.js +2 -2
  132. package/lib/features/pdf-viewer/PdfPageRenderer.js.map +1 -1
  133. package/lib/features/pdf-viewer/PdfPageSlider.js +3 -3
  134. package/lib/features/pdf-viewer/PdfPageSlider.js.map +1 -1
  135. package/lib/features/pdf-viewer/SimplePdfViewer.js +1 -1
  136. package/lib/features/pdf-viewer/SimplePdfViewer.js.map +1 -1
  137. package/lib/features/permissions/UserPermissionsProvider.d.ts +2 -1
  138. package/lib/features/permissions/UserPermissionsProvider.d.ts.map +1 -1
  139. package/lib/features/permissions/UserPermissionsProvider.js +35 -22
  140. package/lib/features/permissions/UserPermissionsProvider.js.map +1 -1
  141. package/lib/features/permissions/useRoleMappings.d.ts +19 -0
  142. package/lib/features/permissions/useRoleMappings.d.ts.map +1 -0
  143. package/lib/features/permissions/useRoleMappings.js +87 -0
  144. package/lib/features/permissions/useRoleMappings.js.map +1 -0
  145. package/lib/features/store/collections/SelectCollection.js +1 -1
  146. package/lib/features/store/collections/SelectCollection.js.map +1 -1
  147. package/lib/features/store/objects/DocumentPreviewPanel.d.ts.map +1 -1
  148. package/lib/features/store/objects/DocumentPreviewPanel.js +9 -9
  149. package/lib/features/store/objects/DocumentPreviewPanel.js.map +1 -1
  150. package/lib/features/store/objects/DocumentTable.js +1 -1
  151. package/lib/features/store/objects/DocumentTable.js.map +1 -1
  152. package/lib/features/store/objects/components/DocumentIcon.js +2 -2
  153. package/lib/features/store/objects/components/DocumentIcon.js.map +1 -1
  154. package/lib/features/store/objects/components/DocumentInput.js +1 -1
  155. package/lib/features/store/objects/components/DocumentInput.js.map +1 -1
  156. package/lib/features/store/objects/components/PropertiesEditorModal.js +1 -1
  157. package/lib/features/store/objects/components/PropertiesEditorModal.js.map +1 -1
  158. package/lib/features/store/objects/components/SaveVersionConfirmModal.js +1 -1
  159. package/lib/features/store/objects/components/SaveVersionConfirmModal.js.map +1 -1
  160. package/lib/features/store/objects/layout/documentLayout.d.ts.map +1 -1
  161. package/lib/features/store/objects/layout/documentLayout.js +2 -2
  162. package/lib/features/store/objects/layout/documentLayout.js.map +1 -1
  163. package/lib/features/store/objects/selection/SelectionActions.js +1 -1
  164. package/lib/features/store/objects/selection/SelectionActions.js.map +1 -1
  165. package/lib/features/store/types/IntakePolicyEditor.d.ts +10 -1
  166. package/lib/features/store/types/IntakePolicyEditor.d.ts.map +1 -1
  167. package/lib/features/store/types/IntakePolicyEditor.js +29 -19
  168. package/lib/features/store/types/IntakePolicyEditor.js.map +1 -1
  169. package/lib/features/store/types/IntakePolicyForm.d.ts +1 -1
  170. package/lib/features/store/types/IntakePolicyForm.d.ts.map +1 -1
  171. package/lib/features/store/types/IntakePolicyForm.js +5 -3
  172. package/lib/features/store/types/IntakePolicyForm.js.map +1 -1
  173. package/lib/features/store/types/SelectContentTypeModal.js +1 -1
  174. package/lib/features/store/types/SelectContentTypeModal.js.map +1 -1
  175. package/lib/features/user/UserAvatar.js +2 -2
  176. package/lib/features/user/UserAvatar.js.map +1 -1
  177. package/lib/features/user/UserInfo.d.ts.map +1 -1
  178. package/lib/features/user/UserInfo.js +7 -7
  179. package/lib/features/user/UserInfo.js.map +1 -1
  180. package/lib/features/utils/index.d.ts +1 -0
  181. package/lib/features/utils/index.d.ts.map +1 -1
  182. package/lib/features/utils/index.js +1 -0
  183. package/lib/features/utils/index.js.map +1 -1
  184. package/lib/features/utils/interaction.d.ts +55 -0
  185. package/lib/features/utils/interaction.d.ts.map +1 -0
  186. package/lib/features/utils/interaction.js +77 -0
  187. package/lib/features/utils/interaction.js.map +1 -0
  188. package/lib/features/views/ViewResults.js +2 -2
  189. package/lib/features/views/ViewResults.js.map +1 -1
  190. package/lib/i18n/locales/ar.json +7 -1
  191. package/lib/i18n/locales/de.json +7 -1
  192. package/lib/i18n/locales/en.json +7 -1
  193. package/lib/i18n/locales/es.json +7 -1
  194. package/lib/i18n/locales/fr.json +7 -1
  195. package/lib/i18n/locales/it.json +7 -1
  196. package/lib/i18n/locales/ja.json +7 -1
  197. package/lib/i18n/locales/ko.json +7 -1
  198. package/lib/i18n/locales/pt.json +7 -1
  199. package/lib/i18n/locales/ru.json +7 -1
  200. package/lib/i18n/locales/tr.json +7 -1
  201. package/lib/i18n/locales/zh-TW.json +7 -1
  202. package/lib/i18n/locales/zh.json +7 -1
  203. package/lib/layout/FullHeightLayout.js +2 -2
  204. package/lib/layout/FullHeightLayout.js.map +1 -1
  205. package/lib/layout/Navbar.js +4 -4
  206. package/lib/layout/Navbar.js.map +1 -1
  207. package/lib/layout/Sidebar.js +1 -1
  208. package/lib/layout/Sidebar.js.map +1 -1
  209. package/lib/session/UserSessionProvider.d.ts.map +1 -1
  210. package/lib/session/UserSessionProvider.js +2 -13
  211. package/lib/session/UserSessionProvider.js.map +1 -1
  212. package/lib/session/auth/authState.d.ts +13 -0
  213. package/lib/session/auth/authState.d.ts.map +1 -0
  214. package/lib/session/auth/authState.js +37 -0
  215. package/lib/session/auth/authState.js.map +1 -0
  216. package/lib/session/auth/domainRouting.d.ts +39 -0
  217. package/lib/session/auth/domainRouting.d.ts.map +1 -1
  218. package/lib/session/auth/domainRouting.js +85 -0
  219. package/lib/session/auth/domainRouting.js.map +1 -1
  220. package/lib/session/auth/useAuthState.d.ts +4 -7
  221. package/lib/session/auth/useAuthState.d.ts.map +1 -1
  222. package/lib/session/auth/useAuthState.js +5 -41
  223. package/lib/session/auth/useAuthState.js.map +1 -1
  224. package/lib/session/index.d.ts +1 -0
  225. package/lib/session/index.d.ts.map +1 -1
  226. package/lib/session/index.js +2 -0
  227. package/lib/session/index.js.map +1 -1
  228. package/lib/shell/SplashScreen.d.ts +1 -1
  229. package/lib/shell/SplashScreen.d.ts.map +1 -1
  230. package/lib/shell/SplashScreen.js +6 -2
  231. package/lib/shell/SplashScreen.js.map +1 -1
  232. package/lib/shell/VertesiaShell.js +1 -1
  233. package/lib/shell/VertesiaShell.js.map +1 -1
  234. package/lib/shell/apps/AppProjectSelector.js +1 -1
  235. package/lib/shell/apps/AppProjectSelector.js.map +1 -1
  236. package/lib/shell/apps/StandaloneApp.js +2 -2
  237. package/lib/shell/apps/StandaloneApp.js.map +1 -1
  238. package/lib/shell/login/SignInPrimitives.js +2 -2
  239. package/lib/shell/login/SignInPrimitives.js.map +1 -1
  240. package/lib/shell/login/SigninScreen.js +1 -1
  241. package/lib/shell/login/SigninScreen.js.map +1 -1
  242. package/lib/shell/login/SignupForm.js +1 -1
  243. package/lib/shell/login/SignupForm.js.map +1 -1
  244. package/lib/shell/login/TerminalLogin.js +2 -2
  245. package/lib/shell/login/TerminalLogin.js.map +1 -1
  246. package/lib/shell/login/UserInfo.d.ts.map +1 -1
  247. package/lib/shell/login/UserInfo.js +1 -1
  248. package/lib/shell/login/UserInfo.js.map +1 -1
  249. package/lib/shell/login/UserSessionMenu.js +1 -1
  250. package/lib/shell/login/UserSessionMenu.js.map +1 -1
  251. package/lib/vertesia-ui-core.js +7 -7
  252. package/lib/vertesia-ui-core.js.map +1 -1
  253. package/lib/vertesia-ui-features.js +179 -182
  254. package/lib/vertesia-ui-features.js.map +1 -1
  255. package/lib/vertesia-ui-i18n.BfN7iOHb.chunk.js +5 -0
  256. package/lib/vertesia-ui-i18n.BfN7iOHb.chunk.js.map +1 -0
  257. package/lib/vertesia-ui-i18n.BjH2zEZw.chunk.js +5 -0
  258. package/lib/vertesia-ui-i18n.BjH2zEZw.chunk.js.map +1 -0
  259. package/lib/vertesia-ui-i18n.BjSwAZXl.chunk.js +5 -0
  260. package/lib/vertesia-ui-i18n.BjSwAZXl.chunk.js.map +1 -0
  261. package/lib/vertesia-ui-i18n.C7PUm5Au.chunk.js +5 -0
  262. package/lib/vertesia-ui-i18n.C7PUm5Au.chunk.js.map +1 -0
  263. package/lib/vertesia-ui-i18n.CF_1mUS5.chunk.js +5 -0
  264. package/lib/vertesia-ui-i18n.CF_1mUS5.chunk.js.map +1 -0
  265. package/lib/vertesia-ui-i18n.ChfUl3_-.chunk.js +5 -0
  266. package/lib/vertesia-ui-i18n.ChfUl3_-.chunk.js.map +1 -0
  267. package/lib/vertesia-ui-i18n.D-Sk-5d1.chunk.js +5 -0
  268. package/lib/vertesia-ui-i18n.D-Sk-5d1.chunk.js.map +1 -0
  269. package/lib/vertesia-ui-i18n.D4rnu1_S.chunk.js +5 -0
  270. package/lib/vertesia-ui-i18n.D4rnu1_S.chunk.js.map +1 -0
  271. package/lib/vertesia-ui-i18n.DDf0-laK.chunk.js +5 -0
  272. package/lib/vertesia-ui-i18n.DDf0-laK.chunk.js.map +1 -0
  273. package/lib/vertesia-ui-i18n.DN79y06J.chunk.js +5 -0
  274. package/lib/vertesia-ui-i18n.DN79y06J.chunk.js.map +1 -0
  275. package/lib/vertesia-ui-i18n.DWLIciYQ.chunk.js +5 -0
  276. package/lib/vertesia-ui-i18n.DWLIciYQ.chunk.js.map +1 -0
  277. package/lib/vertesia-ui-i18n.DvF_YaAJ.chunk.js +5 -0
  278. package/lib/vertesia-ui-i18n.DvF_YaAJ.chunk.js.map +1 -0
  279. package/lib/vertesia-ui-i18n.js +2 -2
  280. package/lib/vertesia-ui-layout.js +1 -1
  281. package/lib/vertesia-ui-layout.js.map +1 -1
  282. package/lib/vertesia-ui-rich-text.js +24 -24
  283. package/lib/vertesia-ui-rich-text.js.map +1 -1
  284. package/lib/vertesia-ui-session.js +1 -1
  285. package/lib/vertesia-ui-session.js.map +1 -1
  286. package/lib/vertesia-ui-shell.js +3 -3
  287. package/lib/vertesia-ui-shell.js.map +1 -1
  288. package/lib/vertesia-ui-widgets.js +54 -54
  289. package/lib/vertesia-ui-widgets.js.map +1 -1
  290. package/lib/widgets/Progress.js +1 -1
  291. package/lib/widgets/Progress.js.map +1 -1
  292. package/lib/widgets/form/Form.js +2 -2
  293. package/lib/widgets/form/Form.js.map +1 -1
  294. package/lib/widgets/form/fields.js +2 -2
  295. package/lib/widgets/form/fields.js.map +1 -1
  296. package/lib/widgets/json-view/JSONView.js +1 -1
  297. package/lib/widgets/json-view/JSONView.js.map +1 -1
  298. package/lib/widgets/markdown/MermaidDiagram.js +1 -1
  299. package/lib/widgets/markdown/MermaidDiagram.js.map +1 -1
  300. package/lib/widgets/markdown/remarkDirectiveHandler.d.ts +7 -2
  301. package/lib/widgets/markdown/remarkDirectiveHandler.d.ts.map +1 -1
  302. package/lib/widgets/markdown/remarkDirectiveHandler.js +19 -4
  303. package/lib/widgets/markdown/remarkDirectiveHandler.js.map +1 -1
  304. package/lib/widgets/monacoEditor/MonacoEditor.d.ts.map +1 -1
  305. package/lib/widgets/monacoEditor/MonacoEditor.js +4 -2
  306. package/lib/widgets/monacoEditor/MonacoEditor.js.map +1 -1
  307. package/lib/widgets/monacoEditor/index.d.ts +1 -0
  308. package/lib/widgets/monacoEditor/index.d.ts.map +1 -1
  309. package/lib/widgets/monacoEditor/index.js +1 -0
  310. package/lib/widgets/monacoEditor/index.js.map +1 -1
  311. package/lib/widgets/monacoEditor/loadMonaco.d.ts +45 -0
  312. package/lib/widgets/monacoEditor/loadMonaco.d.ts.map +1 -0
  313. package/lib/widgets/monacoEditor/loadMonaco.js +62 -0
  314. package/lib/widgets/monacoEditor/loadMonaco.js.map +1 -0
  315. package/lib/widgets/properties/PropertiesView.js +1 -1
  316. package/lib/widgets/properties/PropertiesView.js.map +1 -1
  317. package/lib/widgets/schema-editor/editor/Editable.js +2 -2
  318. package/lib/widgets/schema-editor/editor/Editable.js.map +1 -1
  319. package/lib/widgets/schema-editor/editor/PropertyEditor.js +1 -1
  320. package/lib/widgets/schema-editor/editor/PropertyEditor.js.map +1 -1
  321. package/lib/widgets/schema-editor/editor/SchemaEditor.js +2 -2
  322. package/lib/widgets/schema-editor/editor/SchemaEditor.js.map +1 -1
  323. package/lib/widgets/upload/DropZone.js +1 -1
  324. package/lib/widgets/upload/DropZone.js.map +1 -1
  325. package/lib/widgets/upload/UploadResultCategory.d.ts +1 -1
  326. package/lib/widgets/upload/UploadResultCategory.d.ts.map +1 -1
  327. package/lib/widgets/upload/UploadResultCategory.js +3 -3
  328. package/lib/widgets/upload/UploadResultCategory.js.map +1 -1
  329. package/lib/widgets/upload/UploadSummary.js +1 -1
  330. package/lib/widgets/upload/UploadSummary.js.map +1 -1
  331. package/lib/widgets/xml-viewer/components/XMLViewer.d.ts.map +1 -1
  332. package/lib/widgets/xml-viewer/components/XMLViewer.js +7 -3
  333. package/lib/widgets/xml-viewer/components/XMLViewer.js.map +1 -1
  334. package/lib/widgets/xml-viewer/hooks/useCollapsible.d.ts +1 -1
  335. package/lib/widgets/xml-viewer/hooks/useXMLViewer.d.ts +11 -13
  336. package/lib/widgets/xml-viewer/hooks/useXMLViewer.d.ts.map +1 -1
  337. package/lib/widgets/xml-viewer/hooks/useXMLViewer.js +41 -14
  338. package/lib/widgets/xml-viewer/hooks/useXMLViewer.js.map +1 -1
  339. package/package.json +7 -7
  340. package/src/__tests__/contrast.test.ts +1 -0
  341. package/src/core/components/Avatar.tsx +3 -3
  342. package/src/core/components/ComboBox.tsx +1 -1
  343. package/src/core/components/FileUpload.tsx +4 -4
  344. package/src/core/components/Link.tsx +1 -1
  345. package/src/core/components/SelectList.tsx +1 -1
  346. package/src/core/components/SidePanel.tsx +1 -1
  347. package/src/core/components/Spinner.tsx +1 -1
  348. package/src/core/components/TagsInput.tsx +8 -8
  349. package/src/core/components/shadcn/MessageBox.tsx +1 -1
  350. package/src/core/components/shadcn/button.tsx +1 -1
  351. package/src/core/components/shadcn/card.tsx +1 -3
  352. package/src/core/components/shadcn/command.tsx +5 -5
  353. package/src/core/components/shadcn/filters/DynamicLabel.tsx +1 -1
  354. package/src/core/components/shadcn/filters/comboBox/DateCombobox.tsx +3 -3
  355. package/src/core/components/shadcn/input.tsx +3 -3
  356. package/src/core/components/shadcn/modal/ConfirmModal.tsx +3 -3
  357. package/src/core/components/shadcn/modal/dialog.tsx +2 -4
  358. package/src/core/components/shadcn/overflowTabs.tsx +2 -2
  359. package/src/core/components/shadcn/popover.tsx +1 -1
  360. package/src/core/components/shadcn/radioGroup.tsx +5 -7
  361. package/src/core/components/shadcn/selectBox.tsx +1 -1
  362. package/src/core/components/shadcn/tabs.tsx +4 -2
  363. package/src/core/components/styles.ts +1 -1
  364. package/src/core/components/table/index.tsx +1 -1
  365. package/src/core/hooks/useFetch.test.ts +20 -0
  366. package/src/core/hooks/useFetch.ts +2 -0
  367. package/src/css/base.css +1 -1
  368. package/src/css/color.css +4 -0
  369. package/src/css/theme.css +1 -0
  370. package/src/css/typography.css +2 -2
  371. package/src/features/activity-doc/ActivityDoc.tsx +11 -11
  372. package/src/features/agent/chat/AgentChart.tsx +1 -1
  373. package/src/features/agent/chat/AskUserWidget.tsx +19 -23
  374. package/src/features/agent/chat/JumpingDots.tsx +3 -3
  375. package/src/features/agent/chat/ModernAgentConversation.tsx +3 -3
  376. package/src/features/agent/chat/ModernAgentOutput/AllMessagesMixed.test.tsx +60 -1
  377. package/src/features/agent/chat/ModernAgentOutput/AllMessagesMixed.tsx +44 -24
  378. package/src/features/agent/chat/ModernAgentOutput/BatchProgressPanel.tsx +12 -12
  379. package/src/features/agent/chat/ModernAgentOutput/Header.tsx +1 -1
  380. package/src/features/agent/chat/ModernAgentOutput/InlineSlideInPanel.tsx +4 -4
  381. package/src/features/agent/chat/ModernAgentOutput/MessageInput.tsx +2 -2
  382. package/src/features/agent/chat/ModernAgentOutput/MessageItem.tsx +7 -12
  383. package/src/features/agent/chat/ModernAgentOutput/MessagesContainer.tsx +1 -1
  384. package/src/features/agent/chat/ModernAgentOutput/PlanPanel.tsx +16 -22
  385. package/src/features/agent/chat/ModernAgentOutput/SlideInPanel.tsx +4 -4
  386. package/src/features/agent/chat/ModernAgentOutput/SlidingMessages.tsx +2 -4
  387. package/src/features/agent/chat/ModernAgentOutput/SlidingPlanPanel.tsx +21 -21
  388. package/src/features/agent/chat/ModernAgentOutput/StreamingMessage.tsx +4 -4
  389. package/src/features/agent/chat/ModernAgentOutput/SummaryConversation.ts +16 -1
  390. package/src/features/agent/chat/ModernAgentOutput/ToolCallGroup.tsx +19 -40
  391. package/src/features/agent/chat/ModernAgentOutput/requestInputMessages.test.ts +41 -0
  392. package/src/features/agent/chat/ModernAgentOutput/requestInputMessages.ts +19 -0
  393. package/src/features/agent/chat/ModernAgentOutput/utils.test.ts +93 -0
  394. package/src/features/agent/chat/SlidingThinkingIndicator.tsx +5 -2
  395. package/src/features/agent/chat/VegaLiteChart.tsx +6 -2
  396. package/src/features/errors/RowErrorBoundary.tsx +1 -1
  397. package/src/features/facets/AgentRunnerFacetsNav.tsx +1 -1
  398. package/src/features/facets/utils/VInteractionFacet.tsx +22 -34
  399. package/src/features/facets/utils/VUserFacet.tsx +1 -1
  400. package/src/features/layout/GenericPageNavHeader.tsx +9 -1
  401. package/src/features/layout/NotFoundView.tsx +1 -1
  402. package/src/features/magic-pdf/AnnotatedImageSlider.tsx +8 -16
  403. package/src/features/magic-pdf/ExtractedContentView.tsx +4 -4
  404. package/src/features/magic-pdf/MagicPdfView.tsx +1 -1
  405. package/src/features/pdf-viewer/PdfPageRenderer.tsx +2 -2
  406. package/src/features/pdf-viewer/PdfPageSlider.tsx +4 -4
  407. package/src/features/pdf-viewer/SimplePdfViewer.tsx +1 -1
  408. package/src/features/permissions/UserPermissionsProvider.test.tsx +172 -0
  409. package/src/features/permissions/UserPermissionsProvider.tsx +68 -21
  410. package/src/features/permissions/useRoleMappings.ts +105 -0
  411. package/src/features/store/collections/SelectCollection.tsx +1 -1
  412. package/src/features/store/objects/DocumentPreviewPanel.tsx +43 -53
  413. package/src/features/store/objects/DocumentTable.tsx +2 -2
  414. package/src/features/store/objects/components/DocumentIcon.tsx +4 -4
  415. package/src/features/store/objects/components/DocumentInput.tsx +3 -3
  416. package/src/features/store/objects/components/PropertiesEditorModal.tsx +2 -2
  417. package/src/features/store/objects/components/SaveVersionConfirmModal.tsx +2 -2
  418. package/src/features/store/objects/layout/documentLayout.tsx +2 -4
  419. package/src/features/store/objects/selection/SelectionActions.tsx +1 -1
  420. package/src/features/store/types/IntakePolicyEditor.tsx +70 -36
  421. package/src/features/store/types/IntakePolicyForm.tsx +11 -3
  422. package/src/features/store/types/SelectContentTypeModal.tsx +1 -1
  423. package/src/features/user/UserAvatar.tsx +3 -3
  424. package/src/features/user/UserInfo.tsx +11 -16
  425. package/src/features/utils/index.ts +1 -0
  426. package/src/features/utils/interaction.test.tsx +93 -0
  427. package/src/features/utils/interaction.tsx +125 -0
  428. package/src/features/views/ViewResults.tsx +3 -3
  429. package/src/i18n/locales/ar.json +7 -1
  430. package/src/i18n/locales/de.json +7 -1
  431. package/src/i18n/locales/en.json +7 -1
  432. package/src/i18n/locales/es.json +7 -1
  433. package/src/i18n/locales/fr.json +7 -1
  434. package/src/i18n/locales/it.json +7 -1
  435. package/src/i18n/locales/ja.json +7 -1
  436. package/src/i18n/locales/ko.json +7 -1
  437. package/src/i18n/locales/pt.json +7 -1
  438. package/src/i18n/locales/ru.json +7 -1
  439. package/src/i18n/locales/tr.json +7 -1
  440. package/src/i18n/locales/zh-TW.json +7 -1
  441. package/src/i18n/locales/zh.json +7 -1
  442. package/src/layout/FullHeightLayout.tsx +2 -2
  443. package/src/layout/Navbar.tsx +5 -5
  444. package/src/layout/Sidebar.tsx +1 -1
  445. package/src/session/UserSessionProvider.tsx +2 -15
  446. package/src/session/auth/authState.test.ts +35 -0
  447. package/src/session/auth/authState.ts +42 -0
  448. package/src/session/auth/domainRouting.test.ts +169 -1
  449. package/src/session/auth/domainRouting.ts +89 -0
  450. package/src/session/auth/useAuthState.ts +5 -49
  451. package/src/session/index.ts +6 -0
  452. package/src/shell/SplashScreen.test.tsx +22 -0
  453. package/src/shell/SplashScreen.tsx +6 -2
  454. package/src/shell/VertesiaShell.tsx +1 -1
  455. package/src/shell/apps/AppProjectSelector.tsx +1 -1
  456. package/src/shell/apps/StandaloneApp.tsx +9 -9
  457. package/src/shell/login/SignInPrimitives.tsx +2 -2
  458. package/src/shell/login/SigninScreen.tsx +1 -1
  459. package/src/shell/login/SignupForm.tsx +2 -2
  460. package/src/shell/login/TerminalLogin.tsx +5 -5
  461. package/src/shell/login/UserInfo.tsx +2 -5
  462. package/src/shell/login/UserSessionMenu.tsx +2 -2
  463. package/src/widgets/Progress.tsx +2 -2
  464. package/src/widgets/form/Form.tsx +4 -4
  465. package/src/widgets/form/fields.tsx +2 -2
  466. package/src/widgets/json-view/JSONView.tsx +1 -6
  467. package/src/widgets/markdown/ArtifactEditingSurface.test.tsx +33 -29
  468. package/src/widgets/markdown/MarkdownRenderer.test.tsx +52 -0
  469. package/src/widgets/markdown/MermaidDiagram.tsx +2 -2
  470. package/src/widgets/markdown/remarkDirectiveHandler.ts +21 -5
  471. package/src/widgets/monacoEditor/MonacoEditor.tsx +4 -2
  472. package/src/widgets/monacoEditor/index.ts +1 -0
  473. package/src/widgets/monacoEditor/loadMonaco.test.ts +63 -0
  474. package/src/widgets/monacoEditor/loadMonaco.ts +70 -0
  475. package/src/widgets/properties/PropertiesView.tsx +1 -1
  476. package/src/widgets/schema-editor/editor/Editable.tsx +2 -2
  477. package/src/widgets/schema-editor/editor/PropertyEditor.tsx +1 -1
  478. package/src/widgets/schema-editor/editor/SchemaEditor.tsx +2 -2
  479. package/src/widgets/upload/DropZone.tsx +1 -1
  480. package/src/widgets/upload/UploadResultCategory.tsx +7 -7
  481. package/src/widgets/upload/UploadSummary.tsx +4 -4
  482. package/src/widgets/xml-viewer/components/XMLViewer.tsx +7 -3
  483. package/src/widgets/xml-viewer/hooks/useXMLViewer.test.ts +60 -7
  484. package/src/widgets/xml-viewer/hooks/useXMLViewer.ts +70 -16
  485. package/lib/vertesia-ui-i18n.3yHWompP.chunk.js +0 -5
  486. package/lib/vertesia-ui-i18n.3yHWompP.chunk.js.map +0 -1
  487. package/lib/vertesia-ui-i18n.4XKCcnL0.chunk.js +0 -5
  488. package/lib/vertesia-ui-i18n.4XKCcnL0.chunk.js.map +0 -1
  489. package/lib/vertesia-ui-i18n.78KG4J25.chunk.js +0 -5
  490. package/lib/vertesia-ui-i18n.78KG4J25.chunk.js.map +0 -1
  491. package/lib/vertesia-ui-i18n.BN06mpp1.chunk.js +0 -5
  492. package/lib/vertesia-ui-i18n.BN06mpp1.chunk.js.map +0 -1
  493. package/lib/vertesia-ui-i18n.CSzKLlHJ.chunk.js +0 -5
  494. package/lib/vertesia-ui-i18n.CSzKLlHJ.chunk.js.map +0 -1
  495. package/lib/vertesia-ui-i18n.Ccus7aRh.chunk.js +0 -5
  496. package/lib/vertesia-ui-i18n.Ccus7aRh.chunk.js.map +0 -1
  497. package/lib/vertesia-ui-i18n.D9j3c6gI.chunk.js +0 -5
  498. package/lib/vertesia-ui-i18n.D9j3c6gI.chunk.js.map +0 -1
  499. package/lib/vertesia-ui-i18n.DAUg4rrI.chunk.js +0 -5
  500. package/lib/vertesia-ui-i18n.DAUg4rrI.chunk.js.map +0 -1
  501. package/lib/vertesia-ui-i18n.DSxVZKXy.chunk.js +0 -5
  502. package/lib/vertesia-ui-i18n.DSxVZKXy.chunk.js.map +0 -1
  503. package/lib/vertesia-ui-i18n.aahVhHvR.chunk.js +0 -5
  504. package/lib/vertesia-ui-i18n.aahVhHvR.chunk.js.map +0 -1
  505. package/lib/vertesia-ui-i18n.nZ3xJ26v.chunk.js +0 -5
  506. package/lib/vertesia-ui-i18n.nZ3xJ26v.chunk.js.map +0 -1
  507. package/lib/vertesia-ui-i18n.xPYbuFzT.chunk.js +0 -5
  508. package/lib/vertesia-ui-i18n.xPYbuFzT.chunk.js.map +0 -1
@@ -1,11 +1,13 @@
1
- import { type FacetBucket, InteractionStatus } from '@vertesia/common';
1
+ import type { FacetBucket } from '@vertesia/common';
2
2
  import { Badge, type FilterGroup } from '@vertesia/ui/core';
3
+ import {
4
+ type InteractionDisplayRef,
5
+ InteractionStatusBadge,
6
+ resolveInteractionName,
7
+ splitInteractionType,
8
+ } from '../../utils/interaction.js';
3
9
 
4
- export interface EnrichedFacetBucket extends FacetBucket {
5
- name?: string;
6
- status?: string;
7
- version?: number;
8
- }
10
+ export interface EnrichedFacetBucket extends FacetBucket, InteractionDisplayRef {}
9
11
 
10
12
  interface InteractionFacetProps {
11
13
  buckets: EnrichedFacetBucket[];
@@ -13,6 +15,11 @@ interface InteractionFacetProps {
13
15
  placeholder?: string;
14
16
  }
15
17
 
18
+ /** The name this facet displays for a bucket — the same one the runs table shows for the run. */
19
+ function bucketName(bucket: EnrichedFacetBucket | undefined, interactionId: string): string {
20
+ return resolveInteractionName(bucket, interactionId) ?? interactionId;
21
+ }
22
+
16
23
  export function VInteractionFacet({ buckets, name, placeholder }: InteractionFacetProps): FilterGroup {
17
24
  const options = buckets.map((bucket) => ({
18
25
  label: `(${bucket.count})`,
@@ -26,38 +33,20 @@ export function VInteractionFacet({ buckets, name, placeholder }: InteractionFac
26
33
  type: 'select',
27
34
  labelRenderer: (interactionId: string) => {
28
35
  const bucket = buckets.find((b) => b._id === interactionId);
29
- const displayName = bucket?.name || interactionId;
30
-
31
- // Determine badge variant based on status
32
- let badgeVariant: 'success' | 'info' | 'destructive' | 'default' = 'success';
33
- if (bucket?.status) {
34
- switch (bucket.status) {
35
- case InteractionStatus.published:
36
- badgeVariant = 'success';
37
- break;
38
- case InteractionStatus.archived:
39
- badgeVariant = 'destructive';
40
- break;
41
- case InteractionStatus.code:
42
- badgeVariant = 'info';
43
- break;
44
- }
45
- }
46
-
47
- const badgeText =
48
- bucket?.version && bucket?.status
49
- ? `v${bucket.version} ${bucket.status !== InteractionStatus.unknown ? bucket.status : ''}`
50
- : bucket?.status || (bucket?.version ? `v${bucket.version}` : '');
36
+ // Same split as the runs table: the `sys`/`app`/`tmp` namespace becomes its own badge
37
+ // instead of staying glued to the name.
38
+ const { type, label } = splitInteractionType(bucketName(bucket, interactionId));
51
39
 
52
40
  return (
53
41
  <div className="w-full flex items-center justify-between">
54
42
  <div className="flex flex-row flex-wrap items-center gap-2 min-w-0 flex-1">
55
- <span className="text-sm truncate">{displayName}</span>
56
- {badgeText && (
57
- <Badge variant={badgeVariant} className="text-xs w-fit">
58
- {badgeText}
43
+ <span className="text-sm truncate">{label}</span>
44
+ {type && (
45
+ <Badge variant="secondary" className="text-xs w-fit">
46
+ {type}
59
47
  </Badge>
60
48
  )}
49
+ {bucket && <InteractionStatusBadge interaction={bucket} className="text-xs w-fit" />}
61
50
  </div>
62
51
  {(bucket?.count ?? 0) > 0 && <span className="ms-2 text-xs shrink-0">({bucket?.count})</span>}
63
52
  </div>
@@ -65,8 +54,7 @@ export function VInteractionFacet({ buckets, name, placeholder }: InteractionFac
65
54
  },
66
55
  filterBy: (optionValue: string, searchText: string) => {
67
56
  const bucket = buckets.find((b) => b._id === optionValue);
68
- const searchName = bucket?.name || optionValue;
69
- return searchName.toLowerCase().includes(searchText.toLowerCase());
57
+ return bucketName(bucket, optionValue).toLowerCase().includes(searchText.toLowerCase());
70
58
  },
71
59
  };
72
60
 
@@ -36,7 +36,7 @@ export function createUserFilterGroup({ buckets, name, placeholder }: UserFacetP
36
36
  <div className="flex-1 min-w-0 flex items-center truncate">
37
37
  <UserInfo userRef={userRef} showTitle={true} size="sm" />
38
38
  </div>
39
- <span className="text-muted-foreground flex-shrink-0">({bucket?.count || 0})</span>
39
+ <span className="text-muted flex-shrink-0">({bucket?.count || 0})</span>
40
40
  </div>
41
41
  );
42
42
  },
@@ -148,6 +148,9 @@ export function GenericPageNavHeader({
148
148
  };
149
149
 
150
150
  const breadcrumbItems = buildBreadcrumbItems();
151
+ // The description tooltip trails the last element of the header: the breadcrumbs when there
152
+ // are any, otherwise the title.
153
+ const showDescriptionWithTitle = !!title && breadcrumbItems.length === 0;
151
154
 
152
155
  return (
153
156
  <div className={clsx('pb-0 ps-4 pe-2 py-2 flex flex-col', className)}>
@@ -161,7 +164,7 @@ export function GenericPageNavHeader({
161
164
  maxItems={4}
162
165
  />
163
166
  )}
164
- {description && (
167
+ {description && !showDescriptionWithTitle && (
165
168
  <VTooltip description={description}>
166
169
  <Info className="size-4 text-muted ms-4" />
167
170
  </VTooltip>
@@ -170,6 +173,11 @@ export function GenericPageNavHeader({
170
173
  {title && (
171
174
  <div className="flex gap-2 items-center">
172
175
  <h1 className="text-xl font-semibold break-all">{title}</h1>
176
+ {description && showDescriptionWithTitle && (
177
+ <VTooltip description={description}>
178
+ <Info className="size-4 text-muted" />
179
+ </VTooltip>
180
+ )}
173
181
  </div>
174
182
  )}
175
183
  </div>
@@ -4,7 +4,7 @@ export function NotFoundView() {
4
4
  const { t } = useUITranslation();
5
5
  return (
6
6
  <div className="text-center pt-32">
7
- <h1 className="text-3xl font-bold text-red-500">404</h1>
7
+ <h1 className="text-3xl font-bold text-destructive">404</h1>
8
8
  <p className="text-2xl">{t('layout.pageNotFound')}</p>
9
9
  </div>
10
10
  );
@@ -326,9 +326,7 @@ function ImageTypeButton({ type, currentType, onClick, icon, tooltip }: ImageTyp
326
326
  aria-pressed={isSelected}
327
327
  className={clsx(
328
328
  'p-1 rounded cursor-pointer transition-colors',
329
- isSelected
330
- ? 'text-primary bg-primary/10'
331
- : 'text-muted-foreground hover:text-foreground hover:bg-muted',
329
+ isSelected ? 'text-primary bg-primary/10' : 'text-muted hover:text-foreground hover:bg-muted',
332
330
  )}
333
331
  onClick={onClick}
334
332
  >
@@ -355,25 +353,21 @@ function ZoomControls({ zoom, onZoomIn, onZoomOut, onFitToView, canZoomIn, canZo
355
353
  variant="unstyled"
356
354
  className={clsx(
357
355
  'p-1 rounded cursor-pointer transition-colors',
358
- canZoomOut
359
- ? 'text-muted-foreground hover:text-foreground hover:bg-muted'
360
- : 'text-muted-foreground/40 cursor-not-allowed',
356
+ canZoomOut ? 'text-muted hover:text-foreground hover:bg-muted' : 'text-muted/40 cursor-not-allowed',
361
357
  )}
362
358
  onClick={onZoomOut}
363
359
  disabled={!canZoomOut}
364
360
  >
365
361
  <Minus className="size-4" />
366
362
  </Button>
367
- <span className="text-xs text-muted-foreground min-w-[32px] text-center">{zoom}%</span>
363
+ <span className="text-xs text-muted min-w-[32px] text-center">{zoom}%</span>
368
364
  <Button
369
365
  title={t('pdf.zoomIn')}
370
366
  tooltipPlacement="bottom"
371
367
  variant="unstyled"
372
368
  className={clsx(
373
369
  'p-1 rounded cursor-pointer transition-colors',
374
- canZoomIn
375
- ? 'text-muted-foreground hover:text-foreground hover:bg-muted'
376
- : 'text-muted-foreground/40 cursor-not-allowed',
370
+ canZoomIn ? 'text-muted hover:text-foreground hover:bg-muted' : 'text-muted/40 cursor-not-allowed',
377
371
  )}
378
372
  onClick={onZoomIn}
379
373
  disabled={!canZoomIn}
@@ -386,9 +380,7 @@ function ZoomControls({ zoom, onZoomIn, onZoomOut, onFitToView, canZoomIn, canZo
386
380
  variant="unstyled"
387
381
  className={clsx(
388
382
  'p-1 rounded cursor-pointer transition-colors',
389
- zoom !== DEFAULT_ZOOM
390
- ? 'text-muted-foreground hover:text-foreground hover:bg-muted'
391
- : 'text-muted-foreground/40',
383
+ zoom !== DEFAULT_ZOOM ? 'text-muted hover:text-foreground hover:bg-muted' : 'text-muted/40',
392
384
  )}
393
385
  onClick={onFitToView}
394
386
  >
@@ -431,10 +423,10 @@ function PageThumbnail({ pageNumber, currentPage, aspectRatio, zoom, url, onSele
431
423
  {url ? (
432
424
  <img src={url} alt={`Page ${pageNumber}`} className="w-full" />
433
425
  ) : (
434
- <Loader2 className="w-6 h-6 animate-spin text-muted-foreground" />
426
+ <Loader2 className="w-6 h-6 animate-spin text-muted" />
435
427
  )}
436
428
  </Button>
437
- <Center className="text-sm text-muted-foreground pt-1 font-semibold">{pageNumber}</Center>
429
+ <Center className="text-sm text-muted pt-1 font-semibold">{pageNumber}</Center>
438
430
  </div>
439
431
  );
440
432
  }
@@ -479,7 +471,7 @@ function PageNavigator({ currentPage, totalPages, onChange }: PageNavigatorProps
479
471
  };
480
472
 
481
473
  return (
482
- <div className="flex items-center gap-1 text-xs text-muted-foreground">
474
+ <div className="flex items-center gap-1 text-xs text-muted">
483
475
  <span>{t('pdf.page')}</span>
484
476
  <input
485
477
  ref={inputRef}
@@ -7,7 +7,7 @@ import type { ViewType } from './types';
7
7
  function LoadingSpinner({ className }: { className?: string }) {
8
8
  return (
9
9
  <div className={`flex items-center justify-center ${className || ''}`}>
10
- <Loader2 className="w-6 h-6 animate-spin text-gray-400" />
10
+ <Loader2 className="w-6 h-6 animate-spin text-muted" />
11
11
  </div>
12
12
  );
13
13
  }
@@ -61,7 +61,7 @@ function JsonPageLayoutView({ pageNumber }: JsonPageLayoutViewProps) {
61
61
  }
62
62
 
63
63
  if (error) {
64
- return <div className="px-4 py-2 text-red-500 text-sm">{error}</div>;
64
+ return <div className="px-4 py-2 text-destructive text-sm">{error}</div>;
65
65
  }
66
66
 
67
67
  return content ? <JSONCode className="w-full" data={content} /> : null;
@@ -96,13 +96,13 @@ function MarkdownPageView({ pageNumber }: MarkdownPageViewProps) {
96
96
  return (
97
97
  <div className="h-full flex flex-col items-center justify-center gap-2">
98
98
  <LoadingSpinner />
99
- <span className="text-sm text-muted-foreground">Loading...</span>
99
+ <span className="text-sm text-muted">Loading...</span>
100
100
  </div>
101
101
  );
102
102
  }
103
103
 
104
104
  if (error) {
105
- return <div className="px-4 py-2 text-red-500 text-sm">{error}</div>;
105
+ return <div className="px-4 py-2 text-destructive text-sm">{error}</div>;
106
106
  }
107
107
 
108
108
  return (
@@ -144,7 +144,7 @@ function MagicPdfViewImpl({ object, onClose }: _MagicPdfViewProps) {
144
144
  <div className="flex items-center gap-x-2">
145
145
  <DownloadPopover object={object} />
146
146
  </div>
147
- <span className="text-xs text-muted-foreground">{t('pdf.pageOf', { pageNumber, totalPages })}</span>
147
+ <span className="text-xs text-muted">{t('pdf.pageOf', { pageNumber, totalPages })}</span>
148
148
  <div className="flex items-center gap-x-2">
149
149
  {!!onClose && (
150
150
  <Button variant="ghost" size="xs" onClick={onClose} title={t('pdf.close')}>
@@ -11,7 +11,7 @@ function LoadingSpinner({ className, size = 'md' }: { className?: string; size?:
11
11
  };
12
12
  return (
13
13
  <div className={`flex items-center justify-center ${className || ''}`}>
14
- <Loader2 className={`${sizeClasses[size]} animate-spin text-muted-foreground`} />
14
+ <Loader2 className={`${sizeClasses[size]} animate-spin text-muted`} />
15
15
  </div>
16
16
  );
17
17
  }
@@ -327,7 +327,7 @@ function VirtualizedThumbnail({
327
327
  className="flex items-center justify-center bg-muted"
328
328
  style={{ height: placeholderHeight, width: width || '100%' }}
329
329
  >
330
- <span className="text-muted-foreground text-xs">{pageNumber}</span>
330
+ <span className="text-muted text-xs">{pageNumber}</span>
331
331
  </div>
332
332
  );
333
333
 
@@ -367,7 +367,7 @@ export function PdfPageSlider({
367
367
  </Button>
368
368
  <Center
369
369
  className={clsx(
370
- 'text-muted-foreground font-semibold',
370
+ 'text-muted font-semibold',
371
371
  compact ? 'text-xs pt-0.5' : 'text-sm pt-1',
372
372
  )}
373
373
  >
@@ -426,7 +426,7 @@ function PageNavigator({ currentPage, totalPages, onChange }: PageNavigatorProps
426
426
  };
427
427
 
428
428
  return (
429
- <div className="flex items-center gap-1 text-xs text-muted-foreground">
429
+ <div className="flex items-center gap-1 text-xs text-muted">
430
430
  <span>{t('pdf.page')}</span>
431
431
  <input
432
432
  ref={inputRef}
@@ -457,7 +457,7 @@ function ZoomControls({ zoom, onZoomIn, onZoomOut, onFitToView, canZoomIn, canZo
457
457
  <Button variant="ghost" size="xs" onClick={onZoomOut} isDisabled={!canZoomOut} title={t('pdf.zoomOut')}>
458
458
  <Minus />
459
459
  </Button>
460
- <span className="text-xs text-muted-foreground min-w-[32px] text-center">{zoom}%</span>
460
+ <span className="text-xs text-muted min-w-[32px] text-center">{zoom}%</span>
461
461
  <Button variant="ghost" size="xs" onClick={onZoomIn} isDisabled={!canZoomIn} title={t('pdf.zoomIn')}>
462
462
  <Plus />
463
463
  </Button>
@@ -466,7 +466,7 @@ function ZoomControls({ zoom, onZoomIn, onZoomOut, onFitToView, canZoomIn, canZo
466
466
  size="xs"
467
467
  onClick={onFitToView}
468
468
  title={t('pdf.fitToWidth')}
469
- className={zoom === DEFAULT_ZOOM ? 'text-muted-foreground/40' : undefined}
469
+ className={zoom === DEFAULT_ZOOM ? 'text-muted/40' : undefined}
470
470
  >
471
471
  <Maximize />
472
472
  </Button>
@@ -135,7 +135,7 @@ export function SimplePdfViewer({ object, url, source, className }: SimplePdfVie
135
135
  title={t('pdf.fullscreen')}
136
136
  tooltipPlacement="bottom"
137
137
  variant="unstyled"
138
- className="p-1 rounded cursor-pointer transition-colors text-muted-foreground hover:text-foreground hover:bg-muted"
138
+ className="p-1 rounded cursor-pointer transition-colors text-muted hover:text-foreground hover:bg-muted"
139
139
  onClick={() => setIsFullscreen(true)}
140
140
  >
141
141
  <Maximize2 className="size-4" />
@@ -0,0 +1,172 @@
1
+ import { act, fireEvent, render, screen } from '@testing-library/react';
2
+ import { VertesiaClient } from '@vertesia/client';
3
+ import type { AuthTokenPayload, SystemRoleDefinition } from '@vertesia/common';
4
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
5
+ import { UserPermissionProvider } from './UserPermissionsProvider';
6
+
7
+ const session = {
8
+ client: new VertesiaClient({ serverUrl: 'https://studio.example.test', storeUrl: 'https://store.example.test' }),
9
+ authToken: { sub: 'user-a', account_roles: [] } as unknown as AuthTokenPayload,
10
+ signOut: vi.fn(),
11
+ };
12
+ vi.mock('@vertesia/ui/session', () => ({ useUserSession: () => session }));
13
+
14
+ function renderProvider() {
15
+ return render(
16
+ <UserPermissionProvider>
17
+ <div>Protected workspace</div>
18
+ </UserPermissionProvider>,
19
+ );
20
+ }
21
+
22
+ async function advance(ms: number) {
23
+ await act(async () => {
24
+ await vi.advanceTimersByTimeAsync(ms);
25
+ });
26
+ }
27
+
28
+ describe('role mapping recovery', () => {
29
+ beforeEach(() => {
30
+ vi.useFakeTimers();
31
+ vi.spyOn(Math, 'random').mockReturnValue(1);
32
+ session.authToken = { sub: 'user-a', account_roles: [] } as unknown as AuthTokenPayload;
33
+ session.signOut.mockClear();
34
+ });
35
+ afterEach(() => {
36
+ vi.useRealTimers();
37
+ vi.restoreAllMocks();
38
+ });
39
+
40
+ it.each([0, 502, 503, 504])(
41
+ 'recovers automatically from status %s without rendering protected content early',
42
+ async (status) => {
43
+ const fetch = vi
44
+ .spyOn(session.client.iam.roles, 'listSystem')
45
+ .mockRejectedValueOnce(Object.assign(new Error('JWKSTimeout'), { status }))
46
+ .mockResolvedValue([]);
47
+ renderProvider();
48
+ expect(screen.queryByText('Protected workspace')).toBeNull();
49
+ await advance(0);
50
+ expect(screen.getByRole('status').textContent).toContain('automatically');
51
+ expect(screen.queryByText('JWKSTimeout')).toBeNull();
52
+ await advance(1_000);
53
+ expect(screen.getByText('Protected workspace')).toBeTruthy();
54
+ expect(fetch).toHaveBeenCalledTimes(2);
55
+ expect(screen.queryByRole('alert')).toBeNull();
56
+ },
57
+ );
58
+
59
+ it('stops after one minute and lets a manual retry recover without navigating', async () => {
60
+ const fetch = vi
61
+ .spyOn(session.client.iam.roles, 'listSystem')
62
+ .mockRejectedValue(Object.assign(new Error('JWKSTimeout'), { status: 503 }));
63
+ const location = window.location.href;
64
+ renderProvider();
65
+ await advance(60_000);
66
+ expect(screen.getByRole('alert').textContent).toContain('couldn’t connect');
67
+ const calls = fetch.mock.calls.length;
68
+ await advance(60_000);
69
+ expect(fetch).toHaveBeenCalledTimes(calls);
70
+ fetch.mockResolvedValue([]);
71
+ fireEvent.click(screen.getByRole('button', { name: 'Try again' }));
72
+ await advance(0);
73
+ expect(screen.getByText('Protected workspace')).toBeTruthy();
74
+ expect(window.location.href).toBe(location);
75
+ });
76
+
77
+ it('does not restart recovery when authentication re-decodes the same JWT', async () => {
78
+ const fetch = vi.spyOn(session.client.iam.roles, 'listSystem').mockImplementation(async () => {
79
+ session.authToken = { ...session.authToken };
80
+ throw Object.assign(new Error('Unavailable'), { status: 503 });
81
+ });
82
+ renderProvider();
83
+ await advance(60_000);
84
+ expect(screen.getByRole('button', { name: 'Try again' })).toBeTruthy();
85
+ const calls = fetch.mock.calls.length;
86
+ await advance(10_000);
87
+ expect(fetch).toHaveBeenCalledTimes(calls);
88
+ fetch.mockImplementation(async () => {
89
+ session.authToken = { ...session.authToken };
90
+ return [];
91
+ });
92
+ fireEvent.click(screen.getByRole('button', { name: 'Try again' }));
93
+ await advance(0);
94
+ expect(screen.getByText('Protected workspace')).toBeTruthy();
95
+ expect(fetch).toHaveBeenCalledTimes(calls + 1);
96
+ });
97
+
98
+ it('bounds a hung request and ignores its late success', async () => {
99
+ let resolve!: (roles: SystemRoleDefinition[]) => void;
100
+ const fetch = vi.spyOn(session.client.iam.roles, 'listSystem').mockImplementation(
101
+ () =>
102
+ new Promise((done) => {
103
+ resolve = done;
104
+ }),
105
+ );
106
+ renderProvider();
107
+ await advance(60_000);
108
+ expect(fetch.mock.calls[0][0]?.signal?.aborted).toBe(true);
109
+ await act(async () => resolve([]));
110
+ expect(screen.queryByText('Protected workspace')).toBeNull();
111
+ expect(screen.getByRole('button', { name: 'Try again' })).toBeTruthy();
112
+ });
113
+
114
+ it.each([401, 403, 400, 500])('does not automatically retry status %s', async (status) => {
115
+ const fetch = vi
116
+ .spyOn(session.client.iam.roles, 'listSystem')
117
+ .mockRejectedValue(Object.assign(new Error('Request failed'), { status }));
118
+ renderProvider();
119
+ await advance(60_000);
120
+ expect(fetch).toHaveBeenCalledTimes(1);
121
+ expect(screen.queryByText('Protected workspace')).toBeNull();
122
+ if (status === 401 || status === 403) {
123
+ fireEvent.click(screen.getByRole('button', { name: 'Use a different account' }));
124
+ expect(session.signOut).toHaveBeenCalledOnce();
125
+ }
126
+ });
127
+
128
+ it('cancels retries on unmount', async () => {
129
+ const fetch = vi
130
+ .spyOn(session.client.iam.roles, 'listSystem')
131
+ .mockRejectedValue(Object.assign(new Error('Unavailable'), { status: 503 }));
132
+ const view = renderProvider();
133
+ await advance(0);
134
+ view.unmount();
135
+ await advance(60_000);
136
+ expect(fetch).toHaveBeenCalledTimes(1);
137
+ expect(fetch.mock.calls[0][0]?.signal?.aborted).toBe(true);
138
+ });
139
+
140
+ it('ignores the previous session’s pending response after a token change', async () => {
141
+ let resolveOld!: (roles: SystemRoleDefinition[]) => void;
142
+ const fetch = vi
143
+ .spyOn(session.client.iam.roles, 'listSystem')
144
+ .mockImplementationOnce(
145
+ () =>
146
+ new Promise((done) => {
147
+ resolveOld = done;
148
+ }),
149
+ )
150
+ .mockRejectedValue(Object.assign(new Error('Forbidden'), { status: 403 }));
151
+ const view = renderProvider();
152
+ session.authToken = { sub: 'user-b', account_roles: [] } as unknown as AuthTokenPayload;
153
+ view.rerender(
154
+ <UserPermissionProvider>
155
+ <div>Protected workspace</div>
156
+ </UserPermissionProvider>,
157
+ );
158
+ await advance(0);
159
+ await act(async () => resolveOld([]));
160
+ expect(fetch.mock.calls[0][0]?.signal?.aborted).toBe(true);
161
+ expect(screen.queryByText('Protected workspace')).toBeNull();
162
+ expect(screen.getByRole('alert').textContent).toContain('Access Denied');
163
+ });
164
+
165
+ it('uses permissions embedded in the token without fetching mappings', () => {
166
+ session.authToken = { ...session.authToken, permissions: [] };
167
+ const fetch = vi.spyOn(session.client.iam.roles, 'listSystem');
168
+ renderProvider();
169
+ expect(screen.getByText('Protected workspace')).toBeTruthy();
170
+ expect(fetch).not.toHaveBeenCalled();
171
+ });
172
+ });
@@ -1,9 +1,10 @@
1
1
  import { type AuthTokenPayload, type Permission, PrincipalType, type SystemRoleDefinition } from '@vertesia/common';
2
- import { ErrorBox, errorMessage, useFetch } from '@vertesia/ui/core';
2
+ import { Button, errorMessage, Spinner } from '@vertesia/ui/core';
3
3
  import { useUITranslation } from '@vertesia/ui/i18n';
4
4
  import { useUserSession } from '@vertesia/ui/session';
5
5
  import { createContext, useContext, useMemo } from 'react';
6
6
  import { isAnyOf } from './helpers';
7
+ import { roleMappingsErrorStatus, useRoleMappings } from './useRoleMappings';
7
8
 
8
9
  type ListRolesResponse = SystemRoleDefinition[];
9
10
 
@@ -68,35 +69,81 @@ export function useUserPermissions() {
68
69
 
69
70
  interface UserPermissionProviderProps {
70
71
  children: React.ReactNode;
72
+ loadingIcon?: React.ReactNode;
71
73
  }
72
- export function UserPermissionProvider({ children }: UserPermissionProviderProps) {
74
+ export function UserPermissionProvider({ children, loadingIcon }: UserPermissionProviderProps) {
73
75
  const { t } = useUITranslation();
74
76
  const session = useUserSession();
75
77
  const authToken = session.authToken;
76
- const shouldFetchRoleMappings = Boolean(authToken && !authToken.permissions);
77
- const { data, error, isLoading } = useFetch<ListRolesResponse | undefined>(() => {
78
- if (shouldFetchRoleMappings) {
79
- return session.client.iam.roles.listSystem();
80
- }
81
- return Promise.resolve(undefined);
82
- }, [session.client, authToken, shouldFetchRoleMappings]);
78
+ const { state, retry } = useRoleMappings(session.client, authToken);
83
79
 
84
80
  const perms = useMemo(() => {
85
- if (authToken) {
86
- if (authToken.permissions || !shouldFetchRoleMappings) {
87
- return new UserPermissions(authToken);
88
- }
89
- if (data && !isLoading) {
90
- return new UserPermissions(authToken, data);
91
- }
92
- } else {
93
- return undefined;
81
+ if (!authToken) return undefined;
82
+ if (authToken.permissions) {
83
+ return new UserPermissions(authToken);
84
+ }
85
+ if (state.status === 'ready') {
86
+ return new UserPermissions(authToken, state.roles);
94
87
  }
95
88
  return undefined;
96
- }, [authToken, data, isLoading, shouldFetchRoleMappings]);
89
+ }, [authToken, state]);
97
90
 
98
- if (error) {
99
- return <ErrorBox title={t('store.failedToFetchRoleMappings')}>{errorMessage(error)}</ErrorBox>;
91
+ if (authToken && !perms) {
92
+ const failed = state.status === 'error';
93
+ const status = failed ? roleMappingsErrorStatus(state.error) : undefined;
94
+ const needsSignIn = status === 401;
95
+ const denied = status === 403;
96
+ const title = needsSignIn
97
+ ? t('auth.recovery.credential.title')
98
+ : denied
99
+ ? t('shell.accessDenied')
100
+ : failed
101
+ ? t('permissions.connectionFailed')
102
+ : t('permissions.connecting');
103
+ return (
104
+ <div className="flex min-h-dvh items-center justify-center bg-background px-6 text-foreground">
105
+ <div className="w-full max-w-md space-y-6 text-center">
106
+ <div aria-hidden="true" className="flex justify-center">
107
+ {loadingIcon || (!failed && <Spinner size="2xl" className="text-primary" />)}
108
+ </div>
109
+ <div
110
+ role={failed ? 'alert' : 'status'}
111
+ aria-live={failed ? 'assertive' : 'polite'}
112
+ className="space-y-2"
113
+ >
114
+ <h1 className="text-xl font-semibold">{title}</h1>
115
+ <p className="text-muted">
116
+ {needsSignIn
117
+ ? t('auth.recovery.credential.body')
118
+ : denied
119
+ ? t('permissions.accessDenied')
120
+ : failed
121
+ ? t('permissions.tryAgainLater')
122
+ : state.status === 'retrying'
123
+ ? t('permissions.retrying')
124
+ : t('permissions.loadingPermissions')}
125
+ </p>
126
+ </div>
127
+ {failed && (
128
+ <>
129
+ <Button variant="outline" onClick={needsSignIn || denied ? () => session.signOut() : retry}>
130
+ {needsSignIn || denied
131
+ ? t('auth.recovery.useDifferentAccount')
132
+ : t('auth.recovery.tryAgain')}
133
+ </Button>
134
+ {state.error != null && (
135
+ <details className="text-start text-sm text-muted">
136
+ <summary className="cursor-pointer">{t('auth.recovery.technicalDetails')}</summary>
137
+ <pre className="mt-2 max-h-48 overflow-auto whitespace-pre-wrap wrap-break-word">
138
+ {errorMessage(state.error)}
139
+ </pre>
140
+ </details>
141
+ )}
142
+ </>
143
+ )}
144
+ </div>
145
+ </div>
146
+ );
100
147
  }
101
148
 
102
149
  return perms && <UserPermissionsContext.Provider value={perms}>{children}</UserPermissionsContext.Provider>;