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

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 (299) hide show
  1. package/lib/core/components/ComboBox.d.ts.map +1 -1
  2. package/lib/core/components/ComboBox.js +4 -4
  3. package/lib/core/components/ComboBox.js.map +1 -1
  4. package/lib/core/components/FileUpload.js.map +1 -1
  5. package/lib/core/components/MenuList.d.ts +2 -1
  6. package/lib/core/components/MenuList.d.ts.map +1 -1
  7. package/lib/core/components/TagsInput.js +1 -1
  8. package/lib/core/components/popup/PopupController.d.ts.map +1 -1
  9. package/lib/core/components/popup/PopupController.js.map +1 -1
  10. package/lib/core/components/popup/position.js.map +1 -1
  11. package/lib/core/components/popup/utils.js.map +1 -1
  12. package/lib/core/components/shadcn/LanguageSwitcher.js.map +1 -1
  13. package/lib/core/components/shadcn/MessageBox.js.map +1 -1
  14. package/lib/core/components/shadcn/Panel.js +1 -1
  15. package/lib/core/components/shadcn/badge.d.ts +2 -2
  16. package/lib/core/components/shadcn/button.d.ts +2 -2
  17. package/lib/core/components/shadcn/button.js +1 -1
  18. package/lib/core/components/shadcn/command.d.ts +4 -4
  19. package/lib/core/components/shadcn/command.d.ts.map +1 -1
  20. package/lib/core/components/shadcn/filters/DynamicLabel.js +1 -1
  21. package/lib/core/components/shadcn/filters/comboBox/DateCombobox.d.ts.map +1 -1
  22. package/lib/core/components/shadcn/filters/comboBox/DateCombobox.js +1 -1
  23. package/lib/core/components/shadcn/filters/comboBox/SelectCombobox.d.ts.map +1 -1
  24. package/lib/core/components/shadcn/filters/comboBox/SelectCombobox.js +1 -1
  25. package/lib/core/components/shadcn/filters/comboBox/StringListCombobox.d.ts.map +1 -1
  26. package/lib/core/components/shadcn/filters/comboBox/TextCombobox.d.ts.map +1 -1
  27. package/lib/core/components/shadcn/filters/filter/dateFilter.js +1 -1
  28. package/lib/core/components/shadcn/filters/filterBar.d.ts.map +1 -1
  29. package/lib/core/components/shadcn/filters/filters.js.map +1 -1
  30. package/lib/core/components/shadcn/input.d.ts +2 -2
  31. package/lib/core/components/shadcn/modal/dialog.d.ts.map +1 -1
  32. package/lib/core/components/shadcn/popover.d.ts +1 -1
  33. package/lib/core/components/shadcn/popover.d.ts.map +1 -1
  34. package/lib/core/components/shadcn/popover.js.map +1 -1
  35. package/lib/core/components/shadcn/radioGroup.d.ts.map +1 -1
  36. package/lib/core/components/shadcn/selectBox.js +1 -1
  37. package/lib/core/components/shadcn/tabs.d.ts.map +1 -1
  38. package/lib/core/components/shadcn/tabs.js +1 -1
  39. package/lib/core/components/shadcn/text.d.ts +2 -2
  40. package/lib/core/components/shadcn/theme/ThemeSwitcher.js.map +1 -1
  41. package/lib/core/components/toast/ToastProvider.js +1 -1
  42. package/lib/core/hooks/CompositeState.d.ts +1 -1
  43. package/lib/core/hooks/CompositeState.d.ts.map +1 -1
  44. package/lib/core/hooks/CompositeState.js.map +1 -1
  45. package/lib/core/hooks/SharedState.d.ts.map +1 -1
  46. package/lib/core/hooks/useFetch.d.ts.map +1 -1
  47. package/lib/core/hooks/useFetch.js +2 -1
  48. package/lib/core/hooks/useFetch.js.map +1 -1
  49. package/lib/core/hooks/useFlag.d.ts.map +1 -1
  50. package/lib/core/hooks/useIntersectionObserver.js.map +1 -1
  51. package/lib/core/hooks/useSafeLayoutEffect.d.ts +2 -2
  52. package/lib/core/hooks/useSafeLayoutEffect.d.ts.map +1 -1
  53. package/lib/core/hooks/useScrollableSearch.js.map +1 -1
  54. package/lib/core/hooks/useSharedValue.d.ts.map +1 -1
  55. package/lib/core/hooks/useSharedValue.js.map +1 -1
  56. package/lib/core/utils/a11y.d.ts.map +1 -1
  57. package/lib/env/index.d.ts.map +1 -1
  58. package/lib/env/index.js.map +1 -1
  59. package/lib/features/agent/PayloadBuilder.d.ts +1 -1
  60. package/lib/features/agent/PayloadBuilder.d.ts.map +1 -1
  61. package/lib/features/agent/PayloadBuilder.js.map +1 -1
  62. package/lib/features/agent/chat/ArtifactsTab.js +1 -1
  63. package/lib/features/agent/chat/AskUserWidget.js +1 -1
  64. package/lib/features/agent/chat/DocumentEditingActionCard.js +1 -1
  65. package/lib/features/agent/chat/ModernAgentConversation.d.ts.map +1 -1
  66. package/lib/features/agent/chat/ModernAgentConversation.js +26 -3
  67. package/lib/features/agent/chat/ModernAgentConversation.js.map +1 -1
  68. package/lib/features/agent/chat/ModernAgentOutput/ActiveWorkstreamsSummary.js +1 -1
  69. package/lib/features/agent/chat/ModernAgentOutput/AgentMarkdownAnchor.d.ts.map +1 -1
  70. package/lib/features/agent/chat/ModernAgentOutput/AgentMarkdownAnchor.js.map +1 -1
  71. package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.d.ts.map +1 -1
  72. package/lib/features/agent/chat/ModernAgentOutput/AllMessagesMixed.js +1 -1
  73. package/lib/features/agent/chat/ModernAgentOutput/AttachmentPreview.d.ts +7 -0
  74. package/lib/features/agent/chat/ModernAgentOutput/AttachmentPreview.d.ts.map +1 -1
  75. package/lib/features/agent/chat/ModernAgentOutput/AttachmentPreview.js +25 -0
  76. package/lib/features/agent/chat/ModernAgentOutput/AttachmentPreview.js.map +1 -1
  77. package/lib/features/agent/chat/ModernAgentOutput/BatchProgressPanel.d.ts.map +1 -1
  78. package/lib/features/agent/chat/ModernAgentOutput/InlineSlidingPlanPanel.d.ts.map +1 -1
  79. package/lib/features/agent/chat/ModernAgentOutput/MessageItem.d.ts.map +1 -1
  80. package/lib/features/agent/chat/ModernAgentOutput/ResourceChip.js +1 -1
  81. package/lib/features/agent/chat/ModernAgentOutput/SlideInPanel.js +1 -1
  82. package/lib/features/agent/chat/ModernAgentOutput/StreamingMessage.d.ts.map +1 -1
  83. package/lib/features/agent/chat/ModernAgentOutput/SummaryConversation.d.ts.map +1 -1
  84. package/lib/features/agent/chat/ModernAgentOutput/SummaryConversation.js +8 -0
  85. package/lib/features/agent/chat/ModernAgentOutput/SummaryConversation.js.map +1 -1
  86. package/lib/features/agent/chat/ModernAgentOutput/ToolCallGroup.d.ts.map +1 -1
  87. package/lib/features/agent/chat/ModernAgentOutput/ToolCallGroup.js +1 -1
  88. package/lib/features/agent/chat/ModernAgentOutput/WorkstreamTabs.js +1 -1
  89. package/lib/features/agent/chat/ModernAgentOutput/utils.d.ts.map +1 -1
  90. package/lib/features/agent/chat/SlidingThinkingIndicator.js +1 -1
  91. package/lib/features/agent/chat/VegaLiteChart.js +1 -1
  92. package/lib/features/agent/chat/VegaLiteChart.js.map +1 -1
  93. package/lib/features/agent/chat/hooks/useAgentStream.d.ts.map +1 -1
  94. package/lib/features/agent/chat/hooks/useAgentStream.js +26 -0
  95. package/lib/features/agent/chat/hooks/useAgentStream.js.map +1 -1
  96. package/lib/features/agent/chat/hooks/useFileProcessing.d.ts +8 -1
  97. package/lib/features/agent/chat/hooks/useFileProcessing.d.ts.map +1 -1
  98. package/lib/features/agent/chat/hooks/useFileProcessing.js +31 -2
  99. package/lib/features/agent/chat/hooks/useFileProcessing.js.map +1 -1
  100. package/lib/features/agent/chat/useArtifactUrlCache.js.map +1 -1
  101. package/lib/features/agent/chat/workstreams.d.ts +1 -1
  102. package/lib/features/facets/AgentRunnerFacetsNav.d.ts.map +1 -1
  103. package/lib/features/facets/CollectionsFacetsNav.d.ts.map +1 -1
  104. package/lib/features/facets/DocumentsFacetsNav.d.ts.map +1 -1
  105. package/lib/features/facets/InteractionsFacetsNav.d.ts.map +1 -1
  106. package/lib/features/facets/PromptsFacetsNav.d.ts.map +1 -1
  107. package/lib/features/facets/RunsFacetsNav.d.ts.map +1 -1
  108. package/lib/features/facets/WorkflowExecutionsFacetsNav.d.ts.map +1 -1
  109. package/lib/features/magic-pdf/GroundedExtractionView.js +1 -1
  110. package/lib/features/magic-pdf/MagicPdfProvider.d.ts.map +1 -1
  111. package/lib/features/magic-pdf/MagicPdfProvider.js.map +1 -1
  112. package/lib/features/oauth/McpConnectionsButton.js +1 -1
  113. package/lib/features/oauth/OAuthProviderConnectButton.js +1 -1
  114. package/lib/features/oauth/RemoteMcpConnectionButton.js +1 -1
  115. package/lib/features/pdf-viewer/PdfPageRenderer.js +1 -1
  116. package/lib/features/pdf-viewer/PdfPageSlider.js +1 -1
  117. package/lib/features/permissions/UserPermissionsProvider.d.ts.map +1 -1
  118. package/lib/features/permissions/UserPermissionsProvider.js.map +1 -1
  119. package/lib/features/store/collections/CollectionsTable.js +2 -2
  120. package/lib/features/store/collections/CollectionsTable.js.map +1 -1
  121. package/lib/features/store/collections/CreateCollection.js +1 -1
  122. package/lib/features/store/collections/EditCollectionView.js +1 -1
  123. package/lib/features/store/objects/DocumentQuickFilter.js +1 -1
  124. package/lib/features/store/objects/DocumentSelectionProvider.d.ts.map +1 -1
  125. package/lib/features/store/objects/DocumentSelectionProvider.js.map +1 -1
  126. package/lib/features/store/objects/components/ContentDispositionButton.d.ts +2 -1
  127. package/lib/features/store/objects/components/ContentDispositionButton.d.ts.map +1 -1
  128. package/lib/features/store/objects/components/ContentOverview.js +1 -1
  129. package/lib/features/store/objects/components/DocumentEditingPanel.js +1 -1
  130. package/lib/features/store/objects/components/PropertiesEditorModal.js +1 -1
  131. package/lib/features/store/objects/components/TextEditorPanel.js +1 -1
  132. package/lib/features/store/objects/components/documentEditingTarget.d.ts.map +1 -1
  133. package/lib/features/store/objects/components/useContentPanelHooks.d.ts +2 -2
  134. package/lib/features/store/objects/components/useContentPanelHooks.d.ts.map +1 -1
  135. package/lib/features/store/objects/layout/DocumentTableColumn.d.ts +1 -1
  136. package/lib/features/store/objects/layout/DocumentTableColumn.d.ts.map +1 -1
  137. package/lib/features/store/objects/layout/DocumentTableColumn.js.map +1 -1
  138. package/lib/features/store/objects/layout/documentLayout.js +1 -1
  139. package/lib/features/store/objects/layout/renderers.d.ts.map +1 -1
  140. package/lib/features/store/objects/search/DocumentSearchContext.d.ts +25 -25
  141. package/lib/features/store/objects/search/DocumentSearchContext.d.ts.map +1 -1
  142. package/lib/features/store/objects/search/DocumentSearchContext.js.map +1 -1
  143. package/lib/features/store/objects/selection/ObjectsActionContextClass.d.ts.map +1 -1
  144. package/lib/features/store/objects/selection/ObjectsActionContextClass.js.map +1 -1
  145. package/lib/features/store/objects/selection/SelectionActions.js +1 -1
  146. package/lib/features/store/objects/selection/actions/ConfirmAction.js +1 -1
  147. package/lib/features/store/objects/selection/actions/DeleteObjectsAction.js +1 -1
  148. package/lib/features/store/objects/selection/actions/StartWorkflowButton.js +1 -1
  149. package/lib/features/store/objects/upload/DocumentUploadModal.js +1 -1
  150. package/lib/features/store/objects/upload/useSmartFileUploadProcessing.d.ts.map +1 -1
  151. package/lib/features/store/objects/upload/useUploadHandler.d.ts.map +1 -1
  152. package/lib/features/store/types/ContentObjectTypesSearch.js +1 -1
  153. package/lib/features/store/types/IntakePolicyEditor.js +1 -1
  154. package/lib/features/store/types/TypeRegistry.d.ts +240 -180
  155. package/lib/features/store/types/TypeRegistry.d.ts.map +1 -1
  156. package/lib/features/store/types/TypeRegistry.js.map +1 -1
  157. package/lib/features/store/types/search/ObjectTypeSearchContext.d.ts +239 -179
  158. package/lib/features/store/types/search/ObjectTypeSearchContext.d.ts.map +1 -1
  159. package/lib/features/store/types/search/ObjectTypeSearchContext.js.map +1 -1
  160. package/lib/features/user/UserInfo.d.ts +14 -14
  161. package/lib/features/user/UserInfo.js +1 -1
  162. package/lib/features/user/UserInfo.js.map +1 -1
  163. package/lib/features/utils/mimeType.d.ts.map +1 -1
  164. package/lib/features/utils/rendition.js.map +1 -1
  165. package/lib/features/utils/text.js.map +1 -1
  166. package/lib/i18n/locales/ar.json +25 -0
  167. package/lib/i18n/locales/de.json +25 -0
  168. package/lib/i18n/locales/en.json +25 -0
  169. package/lib/i18n/locales/es.json +25 -0
  170. package/lib/i18n/locales/fr.json +25 -0
  171. package/lib/i18n/locales/it.json +25 -0
  172. package/lib/i18n/locales/ja.json +25 -0
  173. package/lib/i18n/locales/ko.json +25 -0
  174. package/lib/i18n/locales/pt.json +25 -0
  175. package/lib/i18n/locales/ru.json +25 -0
  176. package/lib/i18n/locales/tr.json +25 -0
  177. package/lib/i18n/locales/zh-TW.json +25 -0
  178. package/lib/i18n/locales/zh.json +25 -0
  179. package/lib/i18n/rtl.d.ts +1 -1
  180. package/lib/i18n/rtl.d.ts.map +1 -1
  181. package/lib/layout/FullHeightLayout.d.ts +7 -6
  182. package/lib/layout/FullHeightLayout.d.ts.map +1 -1
  183. package/lib/layout/Sidebar.d.ts +1 -1
  184. package/lib/layout/Sidebar.js +1 -1
  185. package/lib/rich-text/EditorToolbar.js +1 -1
  186. package/lib/router/HistoryNavigator.d.ts +2 -2
  187. package/lib/router/HistoryNavigator.d.ts.map +1 -1
  188. package/lib/router/HistoryNavigator.js.map +1 -1
  189. package/lib/router/PathMatcher.d.ts.map +1 -1
  190. package/lib/router/PathMatcher.js.map +1 -1
  191. package/lib/router/PathWithParams.d.ts.map +1 -1
  192. package/lib/router/Redirect.js.map +1 -1
  193. package/lib/router/Route404.js +1 -1
  194. package/lib/router/Router.d.ts.map +1 -1
  195. package/lib/router/Router.js.map +1 -1
  196. package/lib/session/UserSession.d.ts +1 -1
  197. package/lib/session/UserSession.d.ts.map +1 -1
  198. package/lib/session/UserSession.js.map +1 -1
  199. package/lib/session/UserSessionProvider.d.ts +2 -0
  200. package/lib/session/UserSessionProvider.d.ts.map +1 -1
  201. package/lib/session/UserSessionProvider.js +81 -53
  202. package/lib/session/UserSessionProvider.js.map +1 -1
  203. package/lib/session/auth/composable.d.ts +49 -1
  204. package/lib/session/auth/composable.d.ts.map +1 -1
  205. package/lib/session/auth/composable.js +179 -53
  206. package/lib/session/auth/composable.js.map +1 -1
  207. package/lib/shell/VertesiaShell.js +1 -1
  208. package/lib/shell/apps/AppInstallationProvider.d.ts +58 -50
  209. package/lib/shell/apps/AppInstallationProvider.d.ts.map +1 -1
  210. package/lib/shell/apps/AppProjectSelector.js +1 -1
  211. package/lib/shell/login/SignInEmailStep.js +1 -1
  212. package/lib/shell/login/SignInPrimitives.d.ts +21 -20
  213. package/lib/shell/login/SignInPrimitives.d.ts.map +1 -1
  214. package/lib/shell/login/SignInPrimitives.js.map +1 -1
  215. package/lib/shell/login/SignInRecoveryStep.d.ts +22 -0
  216. package/lib/shell/login/SignInRecoveryStep.d.ts.map +1 -0
  217. package/lib/shell/login/SignInRecoveryStep.js +59 -0
  218. package/lib/shell/login/SignInRecoveryStep.js.map +1 -0
  219. package/lib/shell/login/SigninScreen.d.ts.map +1 -1
  220. package/lib/shell/login/SigninScreen.js +84 -11
  221. package/lib/shell/login/SigninScreen.js.map +1 -1
  222. package/lib/shell/login/SignupForm.js +1 -1
  223. package/lib/shell/login/TerminalLogin.js +1 -1
  224. package/lib/shell/login/UserSessionMenu.js +1 -1
  225. package/lib/vertesia-ui-core.js.map +1 -1
  226. package/lib/vertesia-ui-features.js +26 -26
  227. package/lib/vertesia-ui-features.js.map +1 -1
  228. package/lib/vertesia-ui-i18n.js +13 -13
  229. package/lib/vertesia-ui-layout.js.map +1 -1
  230. package/lib/vertesia-ui-rich-text.js.map +1 -1
  231. package/lib/vertesia-ui-router.js.map +1 -1
  232. package/lib/vertesia-ui-session.js +1 -1
  233. package/lib/vertesia-ui-session.js.map +1 -1
  234. package/lib/vertesia-ui-shell.js +1 -1
  235. package/lib/vertesia-ui-shell.js.map +1 -1
  236. package/lib/vertesia-ui-widgets.js.map +1 -1
  237. package/lib/widgets/form/FormContext.d.ts.map +1 -1
  238. package/lib/widgets/form/FormContext.js.map +1 -1
  239. package/lib/widgets/form/ManagedObject.d.ts +2 -2
  240. package/lib/widgets/form/ManagedObject.d.ts.map +1 -1
  241. package/lib/widgets/form/ManagedObject.js.map +1 -1
  242. package/lib/widgets/form/schema.d.ts.map +1 -1
  243. package/lib/widgets/form/schema.js.map +1 -1
  244. package/lib/widgets/json-view/JSONCode.js +1 -1
  245. package/lib/widgets/json-view/JSONTable.js +1 -1
  246. package/lib/widgets/markdown/ArtifactContentRenderer.js.map +1 -1
  247. package/lib/widgets/markdown/CodeBlockPlaceholder.d.ts +1 -1
  248. package/lib/widgets/markdown/CodeBlockPlaceholder.d.ts.map +1 -1
  249. package/lib/widgets/markdown/CodeBlockPlaceholder.js +1 -1
  250. package/lib/widgets/markdown/CodeBlockRendering.d.ts.map +1 -1
  251. package/lib/widgets/markdown/CollaborativeMarkdownRenderer.js +1 -1
  252. package/lib/widgets/markdown/remarkDirectiveHandler.d.ts.map +1 -1
  253. package/lib/widgets/markdown/textDiff.js.map +1 -1
  254. package/lib/widgets/monacoEditor/MonacoEditor.d.ts.map +1 -1
  255. package/lib/widgets/monacoEditor/MonacoEditor.js.map +1 -1
  256. package/lib/widgets/schema-editor/ManagedSchema.d.ts.map +1 -1
  257. package/lib/widgets/schema-editor/editor/PropertyEditor.js +1 -1
  258. package/lib/widgets/schema-editor/json-schema4-utils.js.map +1 -1
  259. package/lib/widgets/xml-viewer/components/Elements/index.js +1 -1
  260. package/lib/widgets/xml-viewer/components/Tag/index.js +1 -1
  261. package/lib/widgets/xml-viewer/constants/index.d.ts.map +1 -1
  262. package/lib/widgets/xml-viewer/helpers/index.d.ts +1 -1
  263. package/lib/widgets/xml-viewer/hooks/useCollapsible.d.ts +1 -1
  264. package/lib/widgets/xml-viewer/hooks/useCollapsible.d.ts.map +1 -1
  265. package/package.json +11 -11
  266. package/src/core/hooks/useFetch.ts +2 -1
  267. package/src/features/agent/chat/ModernAgentConversation.test.tsx +13 -0
  268. package/src/features/agent/chat/ModernAgentConversation.tsx +24 -3
  269. package/src/features/agent/chat/ModernAgentOutput/AttachmentPreview.test.ts +38 -0
  270. package/src/features/agent/chat/ModernAgentOutput/AttachmentPreview.tsx +26 -0
  271. package/src/features/agent/chat/ModernAgentOutput/SummaryConversation.ts +9 -0
  272. package/src/features/agent/chat/ModernAgentOutput/utils.test.ts +21 -0
  273. package/src/features/agent/chat/hooks/useAgentStream.test.tsx +116 -1
  274. package/src/features/agent/chat/hooks/useAgentStream.ts +26 -0
  275. package/src/features/agent/chat/hooks/useFileProcessing.test.tsx +87 -0
  276. package/src/features/agent/chat/hooks/useFileProcessing.ts +32 -1
  277. package/src/features/store/collections/CollectionsTable.tsx +1 -1
  278. package/src/i18n/locales/ar.json +25 -0
  279. package/src/i18n/locales/de.json +25 -0
  280. package/src/i18n/locales/en.json +25 -0
  281. package/src/i18n/locales/es.json +25 -0
  282. package/src/i18n/locales/fr.json +25 -0
  283. package/src/i18n/locales/it.json +25 -0
  284. package/src/i18n/locales/ja.json +25 -0
  285. package/src/i18n/locales/ko.json +25 -0
  286. package/src/i18n/locales/pt.json +25 -0
  287. package/src/i18n/locales/ru.json +25 -0
  288. package/src/i18n/locales/tr.json +25 -0
  289. package/src/i18n/locales/zh-TW.json +25 -0
  290. package/src/i18n/locales/zh.json +25 -0
  291. package/src/session/UserSessionProvider.test.ts +69 -0
  292. package/src/session/UserSessionProvider.tsx +96 -60
  293. package/src/session/auth/composable.scope.test.ts +88 -0
  294. package/src/session/auth/composable.test.ts +205 -0
  295. package/src/session/auth/composable.ts +227 -58
  296. package/src/shell/login/SignInPrimitives.tsx +1 -0
  297. package/src/shell/login/SignInRecoveryStep.test.tsx +112 -0
  298. package/src/shell/login/SignInRecoveryStep.tsx +177 -0
  299. package/src/shell/login/SigninScreen.tsx +145 -27
@@ -0,0 +1,177 @@
1
+ import { useUITranslation } from '@vertesia/ui/i18n';
2
+ import { AlertTriangle } from 'lucide-react';
3
+ import { useEffect, useRef, useState } from 'react';
4
+ import {
5
+ SignInAccountRow,
6
+ SignInIconBadge,
7
+ SignInInitialsBadge,
8
+ SignInStepButton,
9
+ SignInStepHeader,
10
+ SignInStepLayout,
11
+ } from './SignInPrimitives';
12
+ import { emailInitial, firstNameFromEmail } from './signInUtils';
13
+
14
+ export type SignInRecoveryKind = 'scopeProject' | 'scopeAccount' | 'noAccessibleAccount' | 'credential' | 'service';
15
+
16
+ export interface SignInRecoveryDetails {
17
+ accountId?: string;
18
+ errorCode?: string;
19
+ message: string;
20
+ projectId?: string;
21
+ status?: number;
22
+ }
23
+
24
+ export interface SignInRecoveryIdentity {
25
+ email: string;
26
+ name?: string;
27
+ }
28
+
29
+ interface SignInRecoveryStepProps {
30
+ details?: SignInRecoveryDetails;
31
+ identity?: SignInRecoveryIdentity;
32
+ kind: SignInRecoveryKind;
33
+ onContinue?: () => void;
34
+ onUseDifferentAccount: () => void;
35
+ }
36
+
37
+ export default function SignInRecoveryStep({
38
+ details,
39
+ identity,
40
+ kind,
41
+ onContinue,
42
+ onUseDifferentAccount,
43
+ }: SignInRecoveryStepProps) {
44
+ const { t } = useUITranslation();
45
+ const [submitting, setSubmitting] = useState(false);
46
+ const initialButtonRef = useRef<HTMLButtonElement>(null);
47
+
48
+ useEffect(() => {
49
+ initialButtonRef.current?.focus();
50
+ }, []);
51
+
52
+ const isScopeFailure = kind === 'scopeProject' || kind === 'scopeAccount';
53
+ let copy: { eyebrow: string; title: string; body: string };
54
+ if (kind === 'scopeProject') {
55
+ copy = {
56
+ eyebrow: t('auth.recovery.scopeProject.eyebrow'),
57
+ title: t('auth.recovery.scopeProject.title'),
58
+ body: t('auth.recovery.scopeProject.body'),
59
+ };
60
+ } else if (kind === 'scopeAccount') {
61
+ copy = {
62
+ eyebrow: t('auth.recovery.scopeAccount.eyebrow'),
63
+ title: t('auth.recovery.scopeAccount.title'),
64
+ body: t('auth.recovery.scopeAccount.body'),
65
+ };
66
+ } else if (kind === 'noAccessibleAccount') {
67
+ copy = {
68
+ eyebrow: t('auth.recovery.noAccessibleAccount.eyebrow'),
69
+ title: t('auth.recovery.noAccessibleAccount.title'),
70
+ body: t('auth.recovery.noAccessibleAccount.body'),
71
+ };
72
+ } else if (kind === 'credential') {
73
+ copy = {
74
+ eyebrow: t('auth.recovery.credential.eyebrow'),
75
+ title: t('auth.recovery.credential.title'),
76
+ body: t('auth.recovery.credential.body'),
77
+ };
78
+ } else {
79
+ copy = {
80
+ eyebrow: t('auth.recovery.service.eyebrow'),
81
+ title: t('auth.recovery.service.title'),
82
+ body: t('auth.recovery.service.body'),
83
+ };
84
+ }
85
+
86
+ const runAction = (action: () => void) => {
87
+ if (submitting) return;
88
+ setSubmitting(true);
89
+ action();
90
+ };
91
+
92
+ return (
93
+ <SignInStepLayout>
94
+ <div role="alert" aria-live="assertive">
95
+ <SignInIconBadge>
96
+ <AlertTriangle className="size-7 text-attention" aria-hidden="true" />
97
+ </SignInIconBadge>
98
+ <SignInStepHeader eyebrow={copy.eyebrow} title={copy.title} body={copy.body} />
99
+ </div>
100
+
101
+ {identity && (
102
+ <SignInAccountRow
103
+ badge={<SignInInitialsBadge initials={emailInitial(identity.email)} />}
104
+ title={identity.name || firstNameFromEmail(identity.email)}
105
+ subtitle={identity.email}
106
+ actionLabel={t('auth.returning.notYou')}
107
+ onAction={onUseDifferentAccount}
108
+ />
109
+ )}
110
+
111
+ <div className="flex flex-col gap-2">
112
+ {onContinue && (
113
+ <SignInStepButton
114
+ ref={initialButtonRef}
115
+ className="w-full"
116
+ disabled={submitting}
117
+ onClick={() => runAction(onContinue)}
118
+ >
119
+ {isScopeFailure ? t('auth.recovery.continue') : t('auth.recovery.tryAgain')}
120
+ </SignInStepButton>
121
+ )}
122
+ <SignInStepButton
123
+ ref={onContinue ? undefined : initialButtonRef}
124
+ variant={onContinue ? 'ghost' : 'primary'}
125
+ disabled={submitting}
126
+ onClick={() => runAction(onUseDifferentAccount)}
127
+ >
128
+ {t('auth.recovery.useDifferentAccount')}
129
+ </SignInStepButton>
130
+ {(kind === 'noAccessibleAccount' || kind === 'service') && (
131
+ <p className="text-center text-xs text-muted">
132
+ {t('auth.recovery.supportPrefix')}{' '}
133
+ <a className="text-info" href="mailto:support@vertesiahq.com">
134
+ support@vertesiahq.com
135
+ </a>
136
+ </p>
137
+ )}
138
+ </div>
139
+
140
+ {details && (
141
+ <details className="rounded-lg border border-mixer-muted/30 bg-mixer-muted/10 px-4 py-3 text-sm">
142
+ <summary className="cursor-pointer font-medium text-muted marker:text-muted focus-visible:outline-2 focus-visible:outline-offset-2">
143
+ {t('auth.recovery.technicalDetails')}
144
+ </summary>
145
+ <dl className="mt-3 grid grid-cols-[max-content_minmax(0,1fr)] gap-x-3 gap-y-2 text-xs">
146
+ {details.errorCode && (
147
+ <>
148
+ <dt className="text-muted">{t('auth.recovery.errorCode')}</dt>
149
+ <dd className="wrap-break-word font-mono">{details.errorCode}</dd>
150
+ </>
151
+ )}
152
+ {details.status && (
153
+ <>
154
+ <dt className="text-muted">{t('auth.recovery.httpStatus')}</dt>
155
+ <dd className="font-mono">{details.status}</dd>
156
+ </>
157
+ )}
158
+ {details.accountId && (
159
+ <>
160
+ <dt className="text-muted">{t('auth.recovery.requestedAccount')}</dt>
161
+ <dd className="wrap-break-word font-mono">{details.accountId}</dd>
162
+ </>
163
+ )}
164
+ {details.projectId && (
165
+ <>
166
+ <dt className="text-muted">{t('auth.recovery.requestedProject')}</dt>
167
+ <dd className="wrap-break-word font-mono">{details.projectId}</dd>
168
+ </>
169
+ )}
170
+ <dt className="text-muted">{t('auth.recovery.errorMessage')}</dt>
171
+ <dd className="wrap-break-word font-mono">{details.message}</dd>
172
+ </dl>
173
+ </details>
174
+ )}
175
+ </SignInStepLayout>
176
+ );
177
+ }
@@ -1,12 +1,22 @@
1
- import type { SignupData, SignupPayload } from '@vertesia/common';
1
+ import { REQUESTED_SCOPE_UNAVAILABLE_ERROR_CODE, type SignupData, type SignupPayload } from '@vertesia/common';
2
2
  import { Env } from '@vertesia/ui/env';
3
3
  import { useUITranslation } from '@vertesia/ui/i18n';
4
4
  import { RegionTag } from '@vertesia/ui/layout';
5
- import { RestrictedEnvironmentError, UserNotFoundError, useUserSession, useUXTracking } from '@vertesia/ui/session';
5
+ import {
6
+ AuthenticationServiceError,
7
+ CredentialError,
8
+ NoAccessibleAccountError,
9
+ RequestedScopeUnavailableError,
10
+ RestrictedEnvironmentError,
11
+ UserNotFoundError,
12
+ useUserSession,
13
+ useUXTracking,
14
+ } from '@vertesia/ui/session';
6
15
  import { useCallback, useEffect, useState } from 'react';
7
16
  import SignInAuthPending from './SignInAuthPending';
8
17
  import SignInEmailStep, { type TenantInfo } from './SignInEmailStep';
9
18
  import SignInProvidersStep from './SignInProvidersStep';
19
+ import SignInRecoveryStep, { type SignInRecoveryKind } from './SignInRecoveryStep';
10
20
  import SignInRestrictedEnvStep from './SignInRestrictedEnvStep';
11
21
  import SignInReturningStep from './SignInReturningStep';
12
22
  import SignInTenantBlockedStep from './SignInTenantBlockedStep';
@@ -65,7 +75,30 @@ function matchesPathPrefix(pathname: string, prefix?: string | string[]) {
65
75
  });
66
76
  }
67
77
 
68
- type Mode = 'email' | 'providers' | 'tenant' | 'blocked' | 'returning' | 'pending' | 'signup' | 'restricted';
78
+ type Mode =
79
+ | 'email'
80
+ | 'providers'
81
+ | 'tenant'
82
+ | 'blocked'
83
+ | 'returning'
84
+ | 'pending'
85
+ | 'signup'
86
+ | 'restricted'
87
+ | 'scopeUnavailable'
88
+ | 'noAccessibleAccount'
89
+ | 'credentialFailure'
90
+ | 'serviceFailure';
91
+
92
+ function isDedicatedAuthError(error: Error): boolean {
93
+ return (
94
+ error instanceof UserNotFoundError ||
95
+ error instanceof RestrictedEnvironmentError ||
96
+ error instanceof RequestedScopeUnavailableError ||
97
+ error instanceof NoAccessibleAccountError ||
98
+ error instanceof CredentialError ||
99
+ error instanceof AuthenticationServiceError
100
+ );
101
+ }
69
102
 
70
103
  function SigninScreenImpl({
71
104
  isNested = false,
@@ -87,8 +120,20 @@ function SigninScreenImpl({
87
120
  const [tenant, setTenant] = useState<TenantInfo | undefined>(undefined);
88
121
  const [pendingProvider, setPendingProvider] = useState<ProviderId | null>(null);
89
122
 
123
+ const recoveryIdentity =
124
+ authError instanceof RequestedScopeUnavailableError || authError instanceof NoAccessibleAccountError
125
+ ? authError.identity
126
+ : undefined;
127
+ const matchingStoredIdentity =
128
+ recoveryIdentity && storedSession?.email.toLowerCase() === recoveryIdentity.email.toLowerCase()
129
+ ? storedSession
130
+ : undefined;
131
+ const displayedRecoveryIdentity = recoveryIdentity
132
+ ? { email: recoveryIdentity.email, name: recoveryIdentity.name ?? matchingStoredIdentity?.name }
133
+ : undefined;
134
+
90
135
  useEffect(() => {
91
- if (!preservePath) {
136
+ if (!preservePath && !isLoading && !authError) {
92
137
  // Reset to the app's mount root, not the bare origin. A gateway-mounted app carries a
93
138
  // served `<base href>` deep mount; collapsing to '/' drops the app off that mount (the
94
139
  // bare origin serves no app) and the address bar can no longer be reloaded. This effect
@@ -99,7 +144,7 @@ function SigninScreenImpl({
99
144
  const mountRoot = new URL(document.baseURI).pathname || '/';
100
145
  history.replaceState({}, '', mountRoot);
101
146
  }
102
- }, [preservePath]);
147
+ }, [authError, isLoading, preservePath]);
103
148
 
104
149
  // Route based on authError surfaced by the session.
105
150
  useEffect(() => {
@@ -108,6 +153,14 @@ function SigninScreenImpl({
108
153
  setMode('signup');
109
154
  } else if (authError instanceof RestrictedEnvironmentError) {
110
155
  setMode('restricted');
156
+ } else if (authError instanceof RequestedScopeUnavailableError) {
157
+ setMode('scopeUnavailable');
158
+ } else if (authError instanceof NoAccessibleAccountError) {
159
+ setMode('noAccessibleAccount');
160
+ } else if (authError instanceof CredentialError) {
161
+ setMode('credentialFailure');
162
+ } else if (authError instanceof AuthenticationServiceError) {
163
+ setMode('serviceFailure');
111
164
  } else if (isInviteRequiredError(authError)) {
112
165
  const pending = readPendingSignin();
113
166
  if (pending) setEmail(pending.email);
@@ -176,6 +229,37 @@ function SigninScreenImpl({
176
229
  void resetSignInState();
177
230
  }, []);
178
231
 
232
+ const useDifferentAccount = useCallback(() => {
233
+ Env.logger.info('Authentication recovery action selected', {
234
+ vertesia: { recovery_action: 'use_different_account' },
235
+ });
236
+ setStoredSession(null);
237
+ setEmail('');
238
+ setTenant(undefined);
239
+ setMode('email');
240
+ void resetSignInState().finally(() => signOut());
241
+ }, [signOut]);
242
+
243
+ const continueWithSanitizedScope = useCallback(() => {
244
+ if (!(authError instanceof RequestedScopeUnavailableError)) return;
245
+ Env.logger.info('Authentication recovery action selected', {
246
+ vertesia: {
247
+ error_code: REQUESTED_SCOPE_UNAVAILABLE_ERROR_CODE,
248
+ selector_source: authError.selectorSource,
249
+ requested_scope: authError.requestedScope,
250
+ recovery_action: 'continue_sanitized',
251
+ },
252
+ });
253
+ window.location.replace(authError.recoveryUrl ?? window.location.href);
254
+ }, [authError]);
255
+
256
+ const retryAuthentication = useCallback(() => {
257
+ Env.logger.info('Authentication recovery action selected', {
258
+ vertesia: { recovery_action: 'retry' },
259
+ });
260
+ window.location.reload();
261
+ }, []);
262
+
179
263
  // Submits the signup form to /auth/signup, then redirects into the app.
180
264
  const onSignup = (data: SignupData, fbToken: string) => {
181
265
  const payload: SignupPayload = { signupData: data, firebaseToken: fbToken };
@@ -190,10 +274,7 @@ function SigninScreenImpl({
190
274
  };
191
275
 
192
276
  const shouldHideTransientAuthError =
193
- suppressAuthError &&
194
- authError !== undefined &&
195
- !(authError instanceof UserNotFoundError) &&
196
- !(authError instanceof RestrictedEnvironmentError);
277
+ suppressAuthError && authError !== undefined && !isDedicatedAuthError(authError);
197
278
 
198
279
  if (isLoading || user || shouldHideTransientAuthError) return null;
199
280
 
@@ -210,6 +291,49 @@ function SigninScreenImpl({
210
291
  );
211
292
  } else if (mode === 'restricted') {
212
293
  content = <SignInRestrictedEnvStep onUseDifferentEmail={startOver} />;
294
+ } else if (mode === 'scopeUnavailable' && authError instanceof RequestedScopeUnavailableError) {
295
+ const kind: SignInRecoveryKind = authError.requestedScope === 'project' ? 'scopeProject' : 'scopeAccount';
296
+ content = (
297
+ <SignInRecoveryStep
298
+ details={{
299
+ accountId: authError.accountId,
300
+ errorCode: authError.errorCode,
301
+ message: authError.message,
302
+ projectId: authError.projectId,
303
+ status: authError.status,
304
+ }}
305
+ identity={displayedRecoveryIdentity}
306
+ kind={kind}
307
+ onContinue={continueWithSanitizedScope}
308
+ onUseDifferentAccount={useDifferentAccount}
309
+ />
310
+ );
311
+ } else if (mode === 'noAccessibleAccount' && authError instanceof NoAccessibleAccountError) {
312
+ content = (
313
+ <SignInRecoveryStep
314
+ details={{ errorCode: authError.errorCode, message: authError.message, status: authError.status }}
315
+ identity={displayedRecoveryIdentity}
316
+ kind="noAccessibleAccount"
317
+ onUseDifferentAccount={useDifferentAccount}
318
+ />
319
+ );
320
+ } else if (mode === 'credentialFailure' && authError instanceof CredentialError) {
321
+ content = (
322
+ <SignInRecoveryStep
323
+ details={{ errorCode: authError.errorCode, message: authError.message, status: authError.status }}
324
+ kind="credential"
325
+ onUseDifferentAccount={useDifferentAccount}
326
+ />
327
+ );
328
+ } else if (mode === 'serviceFailure' && authError instanceof AuthenticationServiceError) {
329
+ content = (
330
+ <SignInRecoveryStep
331
+ details={{ errorCode: authError.errorCode, message: authError.message, status: authError.status }}
332
+ kind="service"
333
+ onContinue={retryAuthentication}
334
+ onUseDifferentAccount={useDifferentAccount}
335
+ />
336
+ );
213
337
  } else if (mode === 'signup' && !localStorage.getItem('tenantName')) {
214
338
  content = <SignupForm onSignup={onSignup} goBack={startOver} />;
215
339
  } else if (mode === 'tenant' && tenant) {
@@ -247,25 +371,19 @@ function SigninScreenImpl({
247
371
 
248
372
  {content}
249
373
 
250
- {authError &&
251
- !(authError instanceof UserNotFoundError) &&
252
- !(authError instanceof RestrictedEnvironmentError) &&
253
- !isInviteRequiredError(authError) && (
254
- <div className="mt-6 max-w-[420px] text-center text-sm text-muted">
255
- <div>
256
- {t('auth.signInError')}
257
- <br />
258
- {t('auth.signInErrorContact')}
259
- <a className="text-info mx-1" href="mailto:support@vertesiahq.com">
260
- support@vertesiahq.com
261
- </a>
262
- {t('auth.signInErrorPersists')}
263
- <pre className="mt-2 text-xs">
264
- {t('auth.error', { message: authError.message })}
265
- </pre>
266
- </div>
374
+ {authError && !isDedicatedAuthError(authError) && !isInviteRequiredError(authError) && (
375
+ <div className="mt-6 max-w-[420px] text-center text-sm text-muted">
376
+ <div>
377
+ {t('auth.signInError')}
378
+ <br />
379
+ {t('auth.signInErrorContact')}
380
+ <a className="text-info mx-1" href="mailto:support@vertesiahq.com">
381
+ support@vertesiahq.com
382
+ </a>
383
+ {t('auth.signInErrorPersists')}
267
384
  </div>
268
- )}
385
+ </div>
386
+ )}
269
387
 
270
388
  <div className="flex items-center gap-5 mt-10 text-xs text-muted-foreground">
271
389
  <a href="https://vertesiahq.com/privacy" className="hover:text-foreground transition">