@oxyhq/services 15.0.0 → 17.0.0

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 (280) hide show
  1. package/lib/commonjs/index.js +25 -55
  2. package/lib/commonjs/index.js.map +1 -1
  3. package/lib/commonjs/ui/client.js +0 -14
  4. package/lib/commonjs/ui/client.js.map +1 -1
  5. package/lib/commonjs/ui/components/OxyAccountDialog.js +764 -0
  6. package/lib/commonjs/ui/components/OxyAccountDialog.js.map +1 -0
  7. package/lib/commonjs/ui/components/OxyProvider.js +11 -6
  8. package/lib/commonjs/ui/components/OxyProvider.js.map +1 -1
  9. package/lib/commonjs/ui/components/OxySignInButton.js +10 -21
  10. package/lib/commonjs/ui/components/OxySignInButton.js.map +1 -1
  11. package/lib/commonjs/ui/components/ProfileButton.js +25 -112
  12. package/lib/commonjs/ui/components/ProfileButton.js.map +1 -1
  13. package/lib/commonjs/ui/components/RequireOxyAuth.js +299 -0
  14. package/lib/commonjs/ui/components/RequireOxyAuth.js.map +1 -0
  15. package/lib/commonjs/ui/context/OxyContext.js +106 -2
  16. package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
  17. package/lib/commonjs/ui/hooks/mutations/mutationKeys.js +1 -1
  18. package/lib/commonjs/ui/hooks/mutations/useAccountMutations.js +10 -10
  19. package/lib/commonjs/ui/hooks/mutations/useAccountMutations.js.map +1 -1
  20. package/lib/commonjs/ui/hooks/queries/queryKeys.js +1 -1
  21. package/lib/commonjs/ui/hooks/queries/useAccountQueries.js +7 -8
  22. package/lib/commonjs/ui/hooks/queries/useAccountQueries.js.map +1 -1
  23. package/lib/commonjs/ui/hooks/useAuth.js +19 -30
  24. package/lib/commonjs/ui/hooks/useAuth.js.map +1 -1
  25. package/lib/commonjs/ui/hooks/useSwitchableAccounts.js +37 -267
  26. package/lib/commonjs/ui/hooks/useSwitchableAccounts.js.map +1 -1
  27. package/lib/commonjs/ui/index.js +5 -40
  28. package/lib/commonjs/ui/index.js.map +1 -1
  29. package/lib/commonjs/ui/navigation/accountDialogManager.js +91 -0
  30. package/lib/commonjs/ui/navigation/accountDialogManager.js.map +1 -0
  31. package/lib/commonjs/ui/navigation/routes.js +0 -2
  32. package/lib/commonjs/ui/navigation/routes.js.map +1 -1
  33. package/lib/commonjs/ui/screens/ConnectedAppsScreen.js +17 -18
  34. package/lib/commonjs/ui/screens/ConnectedAppsScreen.js.map +1 -1
  35. package/lib/commonjs/ui/screens/ManageAccountScreen.js +4 -3
  36. package/lib/commonjs/ui/screens/ManageAccountScreen.js.map +1 -1
  37. package/lib/commonjs/ui/session/createSessionClient.js +10 -2
  38. package/lib/commonjs/ui/session/createSessionClient.js.map +1 -1
  39. package/lib/module/index.js +20 -17
  40. package/lib/module/index.js.map +1 -1
  41. package/lib/module/ui/client.js +1 -2
  42. package/lib/module/ui/client.js.map +1 -1
  43. package/lib/module/ui/components/OxyAccountDialog.js +761 -0
  44. package/lib/module/ui/components/OxyAccountDialog.js.map +1 -0
  45. package/lib/module/ui/components/OxyProvider.js +11 -6
  46. package/lib/module/ui/components/OxyProvider.js.map +1 -1
  47. package/lib/module/ui/components/OxySignInButton.js +10 -21
  48. package/lib/module/ui/components/OxySignInButton.js.map +1 -1
  49. package/lib/module/ui/components/ProfileButton.js +26 -112
  50. package/lib/module/ui/components/ProfileButton.js.map +1 -1
  51. package/lib/module/ui/components/RequireOxyAuth.js +294 -0
  52. package/lib/module/ui/components/RequireOxyAuth.js.map +1 -0
  53. package/lib/module/ui/context/OxyContext.js +107 -3
  54. package/lib/module/ui/context/OxyContext.js.map +1 -1
  55. package/lib/module/ui/hooks/mutations/mutationKeys.js +1 -1
  56. package/lib/module/ui/hooks/mutations/useAccountMutations.js +8 -8
  57. package/lib/module/ui/hooks/mutations/useAccountMutations.js.map +1 -1
  58. package/lib/module/ui/hooks/queries/queryKeys.js +1 -1
  59. package/lib/module/ui/hooks/queries/useAccountQueries.js +5 -6
  60. package/lib/module/ui/hooks/queries/useAccountQueries.js.map +1 -1
  61. package/lib/module/ui/hooks/useAuth.js +19 -30
  62. package/lib/module/ui/hooks/useAuth.js.map +1 -1
  63. package/lib/module/ui/hooks/useSwitchableAccounts.js +38 -267
  64. package/lib/module/ui/hooks/useSwitchableAccounts.js.map +1 -1
  65. package/lib/module/ui/index.js +1 -5
  66. package/lib/module/ui/index.js.map +1 -1
  67. package/lib/module/ui/navigation/accountDialogManager.js +81 -0
  68. package/lib/module/ui/navigation/accountDialogManager.js.map +1 -0
  69. package/lib/module/ui/navigation/routes.js +0 -2
  70. package/lib/module/ui/navigation/routes.js.map +1 -1
  71. package/lib/module/ui/screens/ConnectedAppsScreen.js +19 -20
  72. package/lib/module/ui/screens/ConnectedAppsScreen.js.map +1 -1
  73. package/lib/module/ui/screens/ManageAccountScreen.js +4 -3
  74. package/lib/module/ui/screens/ManageAccountScreen.js.map +1 -1
  75. package/lib/module/ui/session/createSessionClient.js +10 -2
  76. package/lib/module/ui/session/createSessionClient.js.map +1 -1
  77. package/lib/typescript/commonjs/index.d.ts +6 -13
  78. package/lib/typescript/commonjs/index.d.ts.map +1 -1
  79. package/lib/typescript/commonjs/ui/client.d.ts +0 -4
  80. package/lib/typescript/commonjs/ui/client.d.ts.map +1 -1
  81. package/lib/typescript/commonjs/ui/components/OxyAccountDialog.d.ts +35 -0
  82. package/lib/typescript/commonjs/ui/components/OxyAccountDialog.d.ts.map +1 -0
  83. package/lib/typescript/commonjs/ui/components/OxyProvider.d.ts +2 -2
  84. package/lib/typescript/commonjs/ui/components/OxyProvider.d.ts.map +1 -1
  85. package/lib/typescript/commonjs/ui/components/OxySignInButton.d.ts.map +1 -1
  86. package/lib/typescript/commonjs/ui/components/ProfileButton.d.ts +11 -23
  87. package/lib/typescript/commonjs/ui/components/ProfileButton.d.ts.map +1 -1
  88. package/lib/typescript/commonjs/ui/components/RequireOxyAuth.d.ts +55 -0
  89. package/lib/typescript/commonjs/ui/components/RequireOxyAuth.d.ts.map +1 -0
  90. package/lib/typescript/commonjs/ui/context/OxyContext.d.ts +13 -1
  91. package/lib/typescript/commonjs/ui/context/OxyContext.d.ts.map +1 -1
  92. package/lib/typescript/commonjs/ui/hooks/mutations/useAccountMutations.d.ts +4 -4
  93. package/lib/typescript/commonjs/ui/hooks/mutations/useAccountMutations.d.ts.map +1 -1
  94. package/lib/typescript/commonjs/ui/hooks/queries/useAccountQueries.d.ts +6 -7
  95. package/lib/typescript/commonjs/ui/hooks/queries/useAccountQueries.d.ts.map +1 -1
  96. package/lib/typescript/commonjs/ui/hooks/useAuth.d.ts.map +1 -1
  97. package/lib/typescript/commonjs/ui/hooks/useSwitchableAccounts.d.ts +13 -152
  98. package/lib/typescript/commonjs/ui/hooks/useSwitchableAccounts.d.ts.map +1 -1
  99. package/lib/typescript/commonjs/ui/index.d.ts +2 -5
  100. package/lib/typescript/commonjs/ui/index.d.ts.map +1 -1
  101. package/lib/typescript/commonjs/ui/navigation/accountDialogManager.d.ts +49 -0
  102. package/lib/typescript/commonjs/ui/navigation/accountDialogManager.d.ts.map +1 -0
  103. package/lib/typescript/commonjs/ui/navigation/routes.d.ts +1 -1
  104. package/lib/typescript/commonjs/ui/navigation/routes.d.ts.map +1 -1
  105. package/lib/typescript/commonjs/ui/screens/ConnectedAppsScreen.d.ts.map +1 -1
  106. package/lib/typescript/commonjs/ui/screens/ManageAccountScreen.d.ts +1 -1
  107. package/lib/typescript/commonjs/ui/screens/ManageAccountScreen.d.ts.map +1 -1
  108. package/lib/typescript/commonjs/ui/session/createSessionClient.d.ts +9 -2
  109. package/lib/typescript/commonjs/ui/session/createSessionClient.d.ts.map +1 -1
  110. package/lib/typescript/commonjs/ui/types/navigation.d.ts +9 -0
  111. package/lib/typescript/commonjs/ui/types/navigation.d.ts.map +1 -1
  112. package/lib/typescript/commonjs/ui/utils/storageHelpers.d.ts +7 -7
  113. package/lib/typescript/module/index.d.ts +6 -13
  114. package/lib/typescript/module/index.d.ts.map +1 -1
  115. package/lib/typescript/module/ui/client.d.ts +0 -4
  116. package/lib/typescript/module/ui/client.d.ts.map +1 -1
  117. package/lib/typescript/module/ui/components/OxyAccountDialog.d.ts +35 -0
  118. package/lib/typescript/module/ui/components/OxyAccountDialog.d.ts.map +1 -0
  119. package/lib/typescript/module/ui/components/OxyProvider.d.ts +2 -2
  120. package/lib/typescript/module/ui/components/OxyProvider.d.ts.map +1 -1
  121. package/lib/typescript/module/ui/components/OxySignInButton.d.ts.map +1 -1
  122. package/lib/typescript/module/ui/components/ProfileButton.d.ts +11 -23
  123. package/lib/typescript/module/ui/components/ProfileButton.d.ts.map +1 -1
  124. package/lib/typescript/module/ui/components/RequireOxyAuth.d.ts +55 -0
  125. package/lib/typescript/module/ui/components/RequireOxyAuth.d.ts.map +1 -0
  126. package/lib/typescript/module/ui/context/OxyContext.d.ts +13 -1
  127. package/lib/typescript/module/ui/context/OxyContext.d.ts.map +1 -1
  128. package/lib/typescript/module/ui/hooks/mutations/useAccountMutations.d.ts +4 -4
  129. package/lib/typescript/module/ui/hooks/mutations/useAccountMutations.d.ts.map +1 -1
  130. package/lib/typescript/module/ui/hooks/queries/useAccountQueries.d.ts +6 -7
  131. package/lib/typescript/module/ui/hooks/queries/useAccountQueries.d.ts.map +1 -1
  132. package/lib/typescript/module/ui/hooks/useAuth.d.ts.map +1 -1
  133. package/lib/typescript/module/ui/hooks/useSwitchableAccounts.d.ts +13 -152
  134. package/lib/typescript/module/ui/hooks/useSwitchableAccounts.d.ts.map +1 -1
  135. package/lib/typescript/module/ui/index.d.ts +2 -5
  136. package/lib/typescript/module/ui/index.d.ts.map +1 -1
  137. package/lib/typescript/module/ui/navigation/accountDialogManager.d.ts +49 -0
  138. package/lib/typescript/module/ui/navigation/accountDialogManager.d.ts.map +1 -0
  139. package/lib/typescript/module/ui/navigation/routes.d.ts +1 -1
  140. package/lib/typescript/module/ui/navigation/routes.d.ts.map +1 -1
  141. package/lib/typescript/module/ui/screens/ConnectedAppsScreen.d.ts.map +1 -1
  142. package/lib/typescript/module/ui/screens/ManageAccountScreen.d.ts +1 -1
  143. package/lib/typescript/module/ui/screens/ManageAccountScreen.d.ts.map +1 -1
  144. package/lib/typescript/module/ui/session/createSessionClient.d.ts +9 -2
  145. package/lib/typescript/module/ui/session/createSessionClient.d.ts.map +1 -1
  146. package/lib/typescript/module/ui/types/navigation.d.ts +9 -0
  147. package/lib/typescript/module/ui/types/navigation.d.ts.map +1 -1
  148. package/lib/typescript/module/ui/utils/storageHelpers.d.ts +7 -7
  149. package/package.json +4 -4
  150. package/src/index.ts +23 -28
  151. package/src/ui/client.ts +0 -4
  152. package/src/ui/components/OxyAccountDialog.tsx +760 -0
  153. package/src/ui/components/OxyProvider.tsx +12 -6
  154. package/src/ui/components/OxySignInButton.tsx +10 -21
  155. package/src/ui/components/ProfileButton.tsx +23 -126
  156. package/src/ui/components/RequireOxyAuth.tsx +266 -0
  157. package/src/ui/context/OxyContext.tsx +146 -7
  158. package/src/ui/hooks/mutations/mutationKeys.ts +1 -1
  159. package/src/ui/hooks/mutations/useAccountMutations.ts +8 -8
  160. package/src/ui/hooks/queries/queryKeys.ts +1 -1
  161. package/src/ui/hooks/queries/useAccountQueries.ts +8 -9
  162. package/src/ui/hooks/useAuth.ts +19 -31
  163. package/src/ui/hooks/useSwitchableAccounts.ts +42 -376
  164. package/src/ui/index.ts +2 -5
  165. package/src/ui/navigation/accountDialogManager.ts +84 -0
  166. package/src/ui/navigation/routes.ts +1 -5
  167. package/src/ui/screens/ConnectedAppsScreen.tsx +23 -24
  168. package/src/ui/screens/ManageAccountScreen.tsx +3 -2
  169. package/src/ui/session/createSessionClient.ts +9 -1
  170. package/src/ui/types/navigation.ts +9 -0
  171. package/src/ui/utils/storageHelpers.ts +7 -7
  172. package/lib/commonjs/ui/components/AccountMenu.js +0 -598
  173. package/lib/commonjs/ui/components/AccountMenu.js.map +0 -1
  174. package/lib/commonjs/ui/components/AccountMenuButton.js +0 -135
  175. package/lib/commonjs/ui/components/AccountMenuButton.js.map +0 -1
  176. package/lib/commonjs/ui/components/AccountSwitcher.js +0 -780
  177. package/lib/commonjs/ui/components/AccountSwitcher.js.map +0 -1
  178. package/lib/commonjs/ui/components/AnotherDeviceQR.js +0 -116
  179. package/lib/commonjs/ui/components/AnotherDeviceQR.js.map +0 -1
  180. package/lib/commonjs/ui/components/ProfileMenu.js +0 -518
  181. package/lib/commonjs/ui/components/ProfileMenu.js.map +0 -1
  182. package/lib/commonjs/ui/components/SignInAccountChooser.js +0 -189
  183. package/lib/commonjs/ui/components/SignInAccountChooser.js.map +0 -1
  184. package/lib/commonjs/ui/components/SignInModal.js +0 -600
  185. package/lib/commonjs/ui/components/SignInModal.js.map +0 -1
  186. package/lib/commonjs/ui/hooks/useOxyAuthSession.js +0 -501
  187. package/lib/commonjs/ui/hooks/useOxyAuthSession.js.map +0 -1
  188. package/lib/commonjs/ui/hooks/usePasswordSignIn.js +0 -170
  189. package/lib/commonjs/ui/hooks/usePasswordSignIn.js.map +0 -1
  190. package/lib/commonjs/ui/screens/AccountSwitcherScreen.js +0 -51
  191. package/lib/commonjs/ui/screens/AccountSwitcherScreen.js.map +0 -1
  192. package/lib/commonjs/ui/screens/OxyAuthScreen.js +0 -312
  193. package/lib/commonjs/ui/screens/OxyAuthScreen.js.map +0 -1
  194. package/lib/commonjs/utils/deviceFlowSignIn.js +0 -109
  195. package/lib/commonjs/utils/deviceFlowSignIn.js.map +0 -1
  196. package/lib/module/ui/components/AccountMenu.js +0 -593
  197. package/lib/module/ui/components/AccountMenu.js.map +0 -1
  198. package/lib/module/ui/components/AccountMenuButton.js +0 -130
  199. package/lib/module/ui/components/AccountMenuButton.js.map +0 -1
  200. package/lib/module/ui/components/AccountSwitcher.js +0 -774
  201. package/lib/module/ui/components/AccountSwitcher.js.map +0 -1
  202. package/lib/module/ui/components/AnotherDeviceQR.js +0 -110
  203. package/lib/module/ui/components/AnotherDeviceQR.js.map +0 -1
  204. package/lib/module/ui/components/ProfileMenu.js +0 -514
  205. package/lib/module/ui/components/ProfileMenu.js.map +0 -1
  206. package/lib/module/ui/components/SignInAccountChooser.js +0 -183
  207. package/lib/module/ui/components/SignInAccountChooser.js.map +0 -1
  208. package/lib/module/ui/components/SignInModal.js +0 -591
  209. package/lib/module/ui/components/SignInModal.js.map +0 -1
  210. package/lib/module/ui/hooks/useOxyAuthSession.js +0 -495
  211. package/lib/module/ui/hooks/useOxyAuthSession.js.map +0 -1
  212. package/lib/module/ui/hooks/usePasswordSignIn.js +0 -165
  213. package/lib/module/ui/hooks/usePasswordSignIn.js.map +0 -1
  214. package/lib/module/ui/screens/AccountSwitcherScreen.js +0 -48
  215. package/lib/module/ui/screens/AccountSwitcherScreen.js.map +0 -1
  216. package/lib/module/ui/screens/OxyAuthScreen.js +0 -306
  217. package/lib/module/ui/screens/OxyAuthScreen.js.map +0 -1
  218. package/lib/module/utils/deviceFlowSignIn.js +0 -106
  219. package/lib/module/utils/deviceFlowSignIn.js.map +0 -1
  220. package/lib/typescript/commonjs/ui/components/AccountMenu.d.ts +0 -47
  221. package/lib/typescript/commonjs/ui/components/AccountMenu.d.ts.map +0 -1
  222. package/lib/typescript/commonjs/ui/components/AccountMenuButton.d.ts +0 -26
  223. package/lib/typescript/commonjs/ui/components/AccountMenuButton.d.ts.map +0 -1
  224. package/lib/typescript/commonjs/ui/components/AccountSwitcher.d.ts +0 -46
  225. package/lib/typescript/commonjs/ui/components/AccountSwitcher.d.ts.map +0 -1
  226. package/lib/typescript/commonjs/ui/components/AnotherDeviceQR.d.ts +0 -34
  227. package/lib/typescript/commonjs/ui/components/AnotherDeviceQR.d.ts.map +0 -1
  228. package/lib/typescript/commonjs/ui/components/ProfileMenu.d.ts +0 -49
  229. package/lib/typescript/commonjs/ui/components/ProfileMenu.d.ts.map +0 -1
  230. package/lib/typescript/commonjs/ui/components/SignInAccountChooser.d.ts +0 -29
  231. package/lib/typescript/commonjs/ui/components/SignInAccountChooser.d.ts.map +0 -1
  232. package/lib/typescript/commonjs/ui/components/SignInModal.d.ts +0 -28
  233. package/lib/typescript/commonjs/ui/components/SignInModal.d.ts.map +0 -1
  234. package/lib/typescript/commonjs/ui/hooks/useOxyAuthSession.d.ts +0 -105
  235. package/lib/typescript/commonjs/ui/hooks/useOxyAuthSession.d.ts.map +0 -1
  236. package/lib/typescript/commonjs/ui/hooks/usePasswordSignIn.d.ts +0 -31
  237. package/lib/typescript/commonjs/ui/hooks/usePasswordSignIn.d.ts.map +0 -1
  238. package/lib/typescript/commonjs/ui/screens/AccountSwitcherScreen.d.ts +0 -11
  239. package/lib/typescript/commonjs/ui/screens/AccountSwitcherScreen.d.ts.map +0 -1
  240. package/lib/typescript/commonjs/ui/screens/OxyAuthScreen.d.ts +0 -22
  241. package/lib/typescript/commonjs/ui/screens/OxyAuthScreen.d.ts.map +0 -1
  242. package/lib/typescript/commonjs/utils/deviceFlowSignIn.d.ts +0 -97
  243. package/lib/typescript/commonjs/utils/deviceFlowSignIn.d.ts.map +0 -1
  244. package/lib/typescript/module/ui/components/AccountMenu.d.ts +0 -47
  245. package/lib/typescript/module/ui/components/AccountMenu.d.ts.map +0 -1
  246. package/lib/typescript/module/ui/components/AccountMenuButton.d.ts +0 -26
  247. package/lib/typescript/module/ui/components/AccountMenuButton.d.ts.map +0 -1
  248. package/lib/typescript/module/ui/components/AccountSwitcher.d.ts +0 -46
  249. package/lib/typescript/module/ui/components/AccountSwitcher.d.ts.map +0 -1
  250. package/lib/typescript/module/ui/components/AnotherDeviceQR.d.ts +0 -34
  251. package/lib/typescript/module/ui/components/AnotherDeviceQR.d.ts.map +0 -1
  252. package/lib/typescript/module/ui/components/ProfileMenu.d.ts +0 -49
  253. package/lib/typescript/module/ui/components/ProfileMenu.d.ts.map +0 -1
  254. package/lib/typescript/module/ui/components/SignInAccountChooser.d.ts +0 -29
  255. package/lib/typescript/module/ui/components/SignInAccountChooser.d.ts.map +0 -1
  256. package/lib/typescript/module/ui/components/SignInModal.d.ts +0 -28
  257. package/lib/typescript/module/ui/components/SignInModal.d.ts.map +0 -1
  258. package/lib/typescript/module/ui/hooks/useOxyAuthSession.d.ts +0 -105
  259. package/lib/typescript/module/ui/hooks/useOxyAuthSession.d.ts.map +0 -1
  260. package/lib/typescript/module/ui/hooks/usePasswordSignIn.d.ts +0 -31
  261. package/lib/typescript/module/ui/hooks/usePasswordSignIn.d.ts.map +0 -1
  262. package/lib/typescript/module/ui/screens/AccountSwitcherScreen.d.ts +0 -11
  263. package/lib/typescript/module/ui/screens/AccountSwitcherScreen.d.ts.map +0 -1
  264. package/lib/typescript/module/ui/screens/OxyAuthScreen.d.ts +0 -22
  265. package/lib/typescript/module/ui/screens/OxyAuthScreen.d.ts.map +0 -1
  266. package/lib/typescript/module/utils/deviceFlowSignIn.d.ts +0 -97
  267. package/lib/typescript/module/utils/deviceFlowSignIn.d.ts.map +0 -1
  268. package/src/ui/components/AccountMenu.tsx +0 -645
  269. package/src/ui/components/AccountMenuButton.tsx +0 -126
  270. package/src/ui/components/AccountSwitcher.tsx +0 -751
  271. package/src/ui/components/AnotherDeviceQR.tsx +0 -119
  272. package/src/ui/components/ProfileMenu.tsx +0 -564
  273. package/src/ui/components/SignInAccountChooser.tsx +0 -162
  274. package/src/ui/components/SignInModal.tsx +0 -530
  275. package/src/ui/hooks/useOxyAuthSession.ts +0 -635
  276. package/src/ui/hooks/usePasswordSignIn.ts +0 -207
  277. package/src/ui/screens/AccountSwitcherScreen.tsx +0 -43
  278. package/src/ui/screens/OxyAuthScreen.tsx +0 -324
  279. package/src/utils/__tests__/deviceFlowSignIn.test.ts +0 -231
  280. package/src/utils/deviceFlowSignIn.ts +0 -152
@@ -0,0 +1,760 @@
1
+ /**
2
+ * OxyAccountDialog — the ONE unified account dialog for `@oxyhq/services`.
3
+ *
4
+ * A thin React Native binding over the headless `AccountDialogController` in
5
+ * `@oxyhq/core` (bound via `useSyncExternalStore`), presented as a bottom-sheet
6
+ * modal. It REPLACES the five drifting device/account surfaces the SDK shipped
7
+ * before (`ProfileMenu`, `AccountMenu`, `AccountSwitcher`, `SignInAccountChooser`,
8
+ * and `SignInModal`) with a single implementation whose data + state machine live
9
+ * in core, so the RN and web (auth-sdk) bindings render the SAME list from the
10
+ * SAME logic and cannot diverge.
11
+ *
12
+ * Views (from `snapshot.view`):
13
+ * - `accounts` — the unified `SwitchableAccount[]` list (device sign-ins ∪ graph
14
+ * accounts). Tapping a row switches through `controller.switchTo(accountId)`
15
+ * (the uniform switch), the active row is flagged, and a "+ Add account" row
16
+ * opens the sign-in entry. This is what `ProfileButton` opens.
17
+ * - `add` / `signin` — the sign-in entry: primary "Sign in with Oxy" (device
18
+ * flow), "Scan a QR", and a secondary "Use a password" hand-off that opens
19
+ * auth.oxy.so (password + 2FA are NOT in the SDK).
20
+ * - `qr` — the cross-device QR handoff + its waiting state.
21
+ *
22
+ * Per-account color re-theming uses Bloom's `APP_COLOR_PRESETS` + `BloomColorScope`
23
+ * (same visual language auth.oxy.so uses). Base theming is `useTheme()` + a
24
+ * `StyleSheet`, so the dialog renders correctly in EVERY consumer — including apps
25
+ * that do not use NativeWind (e.g. the accounts app). Modal contents are wrapped
26
+ * in `<GestureHandlerRootView>` because RN's `Modal` renders into its own window.
27
+ */
28
+
29
+ import type React from 'react';
30
+ import { useCallback, useMemo, useState, useSyncExternalStore } from 'react';
31
+ import {
32
+ Modal,
33
+ Platform,
34
+ Pressable,
35
+ ScrollView,
36
+ StyleSheet,
37
+ View,
38
+ type StyleProp,
39
+ type ViewStyle,
40
+ } from 'react-native';
41
+ import { GestureHandlerRootView } from 'react-native-gesture-handler';
42
+ import { MaterialCommunityIcons } from '@expo/vector-icons';
43
+ import QRCode from 'react-native-qrcode-svg';
44
+ import { Avatar } from '@oxyhq/bloom/avatar';
45
+ import { Button } from '@oxyhq/bloom/button';
46
+ import { Text } from '@oxyhq/bloom/typography';
47
+ import {
48
+ useTheme,
49
+ BloomColorScope,
50
+ APP_COLOR_NAMES,
51
+ APP_COLOR_PRESETS,
52
+ type AppColorName,
53
+ } from '@oxyhq/bloom/theme';
54
+ import type { SwitchableAccount, AccountDialogSnapshot } from '@oxyhq/core';
55
+ import { useQueryClient } from '@tanstack/react-query';
56
+ import { useOxy } from '../context/OxyContext';
57
+ import { useI18n } from '../hooks/useI18n';
58
+ import OxyLogo from './OxyLogo';
59
+
60
+ /** Diameter of a row avatar. */
61
+ const ROW_AVATAR_SIZE = 40;
62
+ /** High-contrast QR colors — intentionally fixed (NOT themed) for scan reliability. */
63
+ const QR_PLATE_BG = '#FFFFFF';
64
+ const QR_FOREGROUND = '#000000';
65
+ const QR_SIZE = 196;
66
+
67
+ const isWeb = Platform.OS === 'web';
68
+
69
+ /**
70
+ * Resolve an account's stored color (a named Bloom preset, e.g. `'purple'`) to
71
+ * a concrete brand hex for the row accent. Falls back to the theme primary when
72
+ * the account has no color or the value is not a recognized preset, so the accent
73
+ * renders in EVERY consumer regardless of NativeWind availability.
74
+ */
75
+ function resolveAccentHex(color: string | null, fallback: string): string {
76
+ const preset = toPreset(color);
77
+ return preset ? APP_COLOR_PRESETS[preset].hex : fallback;
78
+ }
79
+
80
+ /** Narrow a stored color string to a known `AppColorName`, or `undefined`. */
81
+ function toPreset(color: string | null): AppColorName | undefined {
82
+ if (!color) return undefined;
83
+ return (APP_COLOR_NAMES as readonly string[]).includes(color)
84
+ ? (color as AppColorName)
85
+ : undefined;
86
+ }
87
+
88
+ interface OxyAccountDialogHandlers {
89
+ onSwitch: (accountId: string) => void;
90
+ onAdd: () => void;
91
+ onManage: () => void;
92
+ onClose: () => void;
93
+ }
94
+
95
+ /**
96
+ * The unified account dialog. Mounted once by `OxyProvider`; opened imperatively
97
+ * via `useOxy().openAccountDialog(view?)` (or the back-compat `showSignInModal`).
98
+ */
99
+ const OxyAccountDialog: React.FC = () => {
100
+ const {
101
+ accountDialogController: controller,
102
+ isAccountDialogOpen,
103
+ closeAccountDialog,
104
+ showBottomSheet,
105
+ logoutAll,
106
+ refreshAccounts,
107
+ } = useOxy();
108
+ const theme = useTheme();
109
+ const { t } = useI18n();
110
+ const queryClient = useQueryClient();
111
+
112
+ // Bind the headless controller. `getSnapshot` returns a stable reference
113
+ // between changes, so it is `useSyncExternalStore`-safe. Guard the no-provider
114
+ // loading state (`controller` is `null`) with an inert store.
115
+ const subscribe = useCallback(
116
+ (listener: () => void) => (controller ? controller.subscribe(listener) : () => undefined),
117
+ [controller],
118
+ );
119
+ const getSnapshot = useCallback(
120
+ () => (controller ? controller.getSnapshot() : EMPTY_SNAPSHOT),
121
+ [controller],
122
+ );
123
+ const snapshot = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
124
+
125
+ const [switching, setSwitching] = useState(false);
126
+
127
+ const handleSwitch = useCallback(
128
+ async (accountId: string) => {
129
+ if (!controller || switching) return;
130
+ if (accountId === snapshot.activeAccountId) {
131
+ closeAccountDialog();
132
+ return;
133
+ }
134
+ setSwitching(true);
135
+ try {
136
+ await controller.switchTo(accountId);
137
+ // A switch succeeds unless the controller recorded an error. On success
138
+ // reload the app's account graph and drop cached account-scoped data so
139
+ // the new active identity re-fetches — the same side effects the
140
+ // context's own `switchToAccount` performs.
141
+ if (!controller.getSnapshot().error) {
142
+ void refreshAccounts();
143
+ queryClient.invalidateQueries();
144
+ closeAccountDialog();
145
+ }
146
+ } finally {
147
+ setSwitching(false);
148
+ }
149
+ },
150
+ [controller, switching, snapshot.activeAccountId, closeAccountDialog, refreshAccounts, queryClient],
151
+ );
152
+
153
+ const handleManage = useCallback(() => {
154
+ closeAccountDialog();
155
+ showBottomSheet?.('ManageAccount');
156
+ }, [closeAccountDialog, showBottomSheet]);
157
+
158
+ const handleSignOutAll = useCallback(() => {
159
+ closeAccountDialog();
160
+ void logoutAll();
161
+ }, [closeAccountDialog, logoutAll]);
162
+
163
+ const handlers = useMemo<OxyAccountDialogHandlers>(
164
+ () => ({
165
+ onSwitch: (accountId) => {
166
+ void handleSwitch(accountId);
167
+ },
168
+ onAdd: () => controller?.add(),
169
+ onManage: handleManage,
170
+ onClose: closeAccountDialog,
171
+ }),
172
+ [handleSwitch, controller, handleManage, closeAccountDialog],
173
+ );
174
+
175
+ if (!isAccountDialogOpen || !controller) {
176
+ return null;
177
+ }
178
+
179
+ const { view } = snapshot;
180
+ const showBack = view === 'qr' || (view === 'add' && snapshot.accounts.length > 0);
181
+
182
+ return (
183
+ <Modal
184
+ visible
185
+ transparent
186
+ animationType={isWeb ? 'fade' : 'slide'}
187
+ statusBarTranslucent
188
+ onRequestClose={closeAccountDialog}
189
+ >
190
+ <GestureHandlerRootView style={styles.root}>
191
+ <View style={[styles.backdrop, { backgroundColor: theme.colors.overlay }]}>
192
+ <Pressable
193
+ style={StyleSheet.absoluteFill}
194
+ onPress={closeAccountDialog}
195
+ accessibilityLabel={t('common.actions.close') || 'Close'}
196
+ accessibilityRole="button"
197
+ />
198
+ <View
199
+ style={[
200
+ styles.card,
201
+ isWeb ? styles.cardCentered : styles.cardSheet,
202
+ { backgroundColor: theme.colors.card, borderColor: theme.colors.border },
203
+ ]}
204
+ >
205
+ <DialogHeader
206
+ snapshot={snapshot}
207
+ theme={theme}
208
+ t={t}
209
+ showBack={showBack}
210
+ onBack={() => controller.setView('accounts')}
211
+ onClose={closeAccountDialog}
212
+ />
213
+ <ScrollView
214
+ style={styles.body}
215
+ contentContainerStyle={styles.bodyContent}
216
+ showsVerticalScrollIndicator={false}
217
+ >
218
+ {view === 'accounts' ? (
219
+ <AccountsView snapshot={snapshot} theme={theme} t={t} handlers={handlers} />
220
+ ) : view === 'qr' ? (
221
+ <QrView snapshot={snapshot} theme={theme} t={t} onRetry={() => void controller.showQr()} />
222
+ ) : (
223
+ <SignInView
224
+ snapshot={snapshot}
225
+ theme={theme}
226
+ t={t}
227
+ handlers={handlers}
228
+ onSignInWithOxy={() => void controller.signInWithOxy()}
229
+ onScanQr={() => void controller.showQr()}
230
+ onUsePassword={() =>
231
+ controller.openPasswordAtOxyAuth({
232
+ returnUrl: isWeb ? currentHref() : undefined,
233
+ })
234
+ }
235
+ />
236
+ )}
237
+ </ScrollView>
238
+ </View>
239
+ </View>
240
+ </GestureHandlerRootView>
241
+ </Modal>
242
+ );
243
+ };
244
+
245
+ // ---------------------------------------------------------------------------
246
+ // Header
247
+ // ---------------------------------------------------------------------------
248
+
249
+ type Theme = ReturnType<typeof useTheme>;
250
+ type Translate = ReturnType<typeof useI18n>['t'];
251
+
252
+ interface HeaderProps {
253
+ snapshot: AccountDialogSnapshot;
254
+ theme: Theme;
255
+ t: Translate;
256
+ showBack: boolean;
257
+ onBack: () => void;
258
+ onClose: () => void;
259
+ }
260
+
261
+ const DialogHeader: React.FC<HeaderProps> = ({ snapshot, theme, t, showBack, onBack, onClose }) => {
262
+ const { title, subtitle } = headerCopy(snapshot.view, snapshot.accounts.length, t);
263
+ return (
264
+ <View style={styles.header}>
265
+ <View style={styles.headerBar}>
266
+ {showBack ? (
267
+ <Pressable
268
+ onPress={onBack}
269
+ style={[styles.iconButton, { backgroundColor: theme.colors.backgroundSecondary }]}
270
+ accessibilityRole="button"
271
+ accessibilityLabel={t('common.actions.back') || 'Back'}
272
+ >
273
+ <MaterialCommunityIcons name="chevron-left" size={22} color={theme.colors.textSecondary} />
274
+ </Pressable>
275
+ ) : (
276
+ <View style={styles.iconButton} />
277
+ )}
278
+ <OxyLogo variant="icon" size={34} fillColor={theme.colors.primary} />
279
+ <Pressable
280
+ onPress={onClose}
281
+ style={[styles.iconButton, { backgroundColor: theme.colors.backgroundSecondary }]}
282
+ accessibilityRole="button"
283
+ accessibilityLabel={t('common.actions.close') || 'Close'}
284
+ >
285
+ <MaterialCommunityIcons name="close" size={20} color={theme.colors.textSecondary} />
286
+ </Pressable>
287
+ </View>
288
+ <Text style={[styles.title, { color: theme.colors.text }]} numberOfLines={1}>
289
+ {title}
290
+ </Text>
291
+ {subtitle ? (
292
+ <Text style={[styles.subtitle, { color: theme.colors.textSecondary }]} numberOfLines={2}>
293
+ {subtitle}
294
+ </Text>
295
+ ) : null}
296
+ </View>
297
+ );
298
+ };
299
+
300
+ // ---------------------------------------------------------------------------
301
+ // Accounts view
302
+ // ---------------------------------------------------------------------------
303
+
304
+ interface AccountsViewProps {
305
+ snapshot: AccountDialogSnapshot;
306
+ theme: Theme;
307
+ t: Translate;
308
+ handlers: OxyAccountDialogHandlers;
309
+ }
310
+
311
+ const AccountsView: React.FC<AccountsViewProps> = ({ snapshot, theme, t, handlers }) => {
312
+ if (snapshot.loading && snapshot.accounts.length === 0) {
313
+ return (
314
+ <View style={styles.centeredBlock}>
315
+ <MaterialCommunityIcons name="loading" size={24} color={theme.colors.textSecondary} />
316
+ <Text style={[styles.mutedText, { color: theme.colors.textSecondary }]}>
317
+ {t('accountSwitcher.loading') || 'Loading accounts…'}
318
+ </Text>
319
+ </View>
320
+ );
321
+ }
322
+
323
+ return (
324
+ <View style={styles.rows}>
325
+ {snapshot.accounts.map((account) => (
326
+ <AccountRow
327
+ key={account.accountId}
328
+ account={account}
329
+ theme={theme}
330
+ switching={snapshot.switchingAccountId === account.accountId}
331
+ disabled={snapshot.switchingAccountId !== null}
332
+ onPress={() => handlers.onSwitch(account.accountId)}
333
+ />
334
+ ))}
335
+
336
+ <Pressable
337
+ style={[styles.addRow, { borderColor: theme.colors.border }]}
338
+ onPress={handlers.onAdd}
339
+ accessibilityRole="button"
340
+ accessibilityLabel={t('signin.addAccountTitle') || 'Add another account'}
341
+ >
342
+ <View style={[styles.addBadge, { borderColor: theme.colors.border }]}>
343
+ <MaterialCommunityIcons name="plus" size={20} color={theme.colors.textSecondary} />
344
+ </View>
345
+ <Text style={[styles.rowName, { color: theme.colors.textSecondary }]}>
346
+ {t('signin.addAccountTitle') || 'Add another account'}
347
+ </Text>
348
+ </Pressable>
349
+
350
+ <View style={styles.footerLinks}>
351
+ <Pressable onPress={handlers.onManage} accessibilityRole="button">
352
+ <Text style={[styles.linkText, { color: theme.colors.primary }]}>
353
+ {t('accountMenu.manage') || 'Manage accounts'}
354
+ </Text>
355
+ </Pressable>
356
+ </View>
357
+ </View>
358
+ );
359
+ };
360
+
361
+ interface AccountRowProps {
362
+ account: SwitchableAccount;
363
+ theme: Theme;
364
+ switching: boolean;
365
+ disabled: boolean;
366
+ onPress: () => void;
367
+ }
368
+
369
+ const AccountRow: React.FC<AccountRowProps> = ({ account, theme, switching, disabled, onPress }) => {
370
+ const accent = resolveAccentHex(account.color, theme.colors.primary);
371
+ const rowStyle: StyleProp<ViewStyle> = [
372
+ styles.accountRow,
373
+ {
374
+ borderColor: account.isCurrent ? accent : theme.colors.border,
375
+ backgroundColor: theme.colors.card,
376
+ },
377
+ disabled && !switching ? styles.rowDisabled : null,
378
+ ];
379
+
380
+ return (
381
+ <BloomColorScope colorPreset={toPreset(account.color)} asChild>
382
+ <Pressable
383
+ style={rowStyle}
384
+ onPress={onPress}
385
+ disabled={disabled}
386
+ accessibilityRole="button"
387
+ accessibilityState={{ selected: account.isCurrent, disabled }}
388
+ accessibilityLabel={account.displayName}
389
+ >
390
+ <View style={[styles.avatarRing, { borderColor: account.isCurrent ? accent : 'transparent' }]}>
391
+ <Avatar
392
+ source={account.user.avatar ?? undefined}
393
+ variant="thumb"
394
+ name={account.displayName}
395
+ size={ROW_AVATAR_SIZE}
396
+ />
397
+ </View>
398
+ <View style={styles.rowMeta}>
399
+ <Text style={[styles.rowName, { color: theme.colors.text }]} numberOfLines={1}>
400
+ {account.displayName}
401
+ </Text>
402
+ {account.email ? (
403
+ <Text style={[styles.rowHandle, { color: theme.colors.textSecondary }]} numberOfLines={1}>
404
+ {account.email}
405
+ </Text>
406
+ ) : null}
407
+ </View>
408
+ {switching ? (
409
+ <MaterialCommunityIcons name="loading" size={20} color={accent} />
410
+ ) : account.isCurrent ? (
411
+ <MaterialCommunityIcons name="check-circle" size={20} color={accent} />
412
+ ) : (
413
+ <MaterialCommunityIcons name="chevron-right" size={20} color={theme.colors.textSecondary} />
414
+ )}
415
+ </Pressable>
416
+ </BloomColorScope>
417
+ );
418
+ };
419
+
420
+ // ---------------------------------------------------------------------------
421
+ // Sign-in view (add / signin)
422
+ // ---------------------------------------------------------------------------
423
+
424
+ interface SignInViewProps {
425
+ snapshot: AccountDialogSnapshot;
426
+ theme: Theme;
427
+ t: Translate;
428
+ handlers: OxyAccountDialogHandlers;
429
+ onSignInWithOxy: () => void;
430
+ onScanQr: () => void;
431
+ onUsePassword: () => void;
432
+ }
433
+
434
+ const SignInView: React.FC<SignInViewProps> = ({
435
+ snapshot,
436
+ theme,
437
+ t,
438
+ handlers,
439
+ onSignInWithOxy,
440
+ onScanQr,
441
+ onUsePassword,
442
+ }) => (
443
+ <View style={styles.signInBlock}>
444
+ {snapshot.accounts.length > 0 ? (
445
+ <View style={styles.rows}>
446
+ {snapshot.accounts.map((account) => (
447
+ <AccountRow
448
+ key={account.accountId}
449
+ account={account}
450
+ theme={theme}
451
+ switching={snapshot.switchingAccountId === account.accountId}
452
+ disabled={snapshot.switchingAccountId !== null}
453
+ onPress={() => handlers.onSwitch(account.accountId)}
454
+ />
455
+ ))}
456
+ <Dividerish theme={theme} label={t('signin.or') || 'or'} />
457
+ </View>
458
+ ) : null}
459
+
460
+ <Button variant="primary" onPress={onSignInWithOxy} style={styles.primaryButton}>
461
+ Sign in with Oxy
462
+ </Button>
463
+
464
+ <Button variant="secondary" onPress={onScanQr} style={styles.secondaryButton}>
465
+ {t('accountSwitcher.scanQr') || 'Scan a QR from another device'}
466
+ </Button>
467
+
468
+ <Pressable onPress={onUsePassword} accessibilityRole="button" style={styles.passwordLink}>
469
+ <Text style={[styles.linkText, { color: theme.colors.textSecondary }]}>
470
+ Use a password instead
471
+ </Text>
472
+ </Pressable>
473
+ </View>
474
+ );
475
+
476
+ const Dividerish: React.FC<{ theme: Theme; label: string }> = ({ theme, label }) => (
477
+ <View style={styles.dividerRow}>
478
+ <View style={[styles.dividerLine, { backgroundColor: theme.colors.border }]} />
479
+ <Text style={[styles.dividerText, { color: theme.colors.textSecondary }]}>{label}</Text>
480
+ <View style={[styles.dividerLine, { backgroundColor: theme.colors.border }]} />
481
+ </View>
482
+ );
483
+
484
+ // ---------------------------------------------------------------------------
485
+ // QR view
486
+ // ---------------------------------------------------------------------------
487
+
488
+ interface QrViewProps {
489
+ snapshot: AccountDialogSnapshot;
490
+ theme: Theme;
491
+ t: Translate;
492
+ onRetry: () => void;
493
+ }
494
+
495
+ const QrView: React.FC<QrViewProps> = ({ snapshot, theme, t, onRetry }) => {
496
+ const { signIn } = snapshot;
497
+
498
+ if (signIn.phase === 'error') {
499
+ return (
500
+ <View style={styles.centeredBlock}>
501
+ <Text style={[styles.errorText, { color: theme.colors.error }]}>
502
+ {signIn.error || 'Sign-in failed. Please try again.'}
503
+ </Text>
504
+ <Button variant="secondary" onPress={onRetry} style={styles.secondaryButton}>
505
+ {t('common.actions.tryAgain') || 'Try again'}
506
+ </Button>
507
+ </View>
508
+ );
509
+ }
510
+
511
+ if (signIn.phase === 'starting' || signIn.phase === 'authorized' || !signIn.qrPayload) {
512
+ const label =
513
+ signIn.phase === 'authorized'
514
+ ? t('signin.status.signingIn') || 'Signing in…'
515
+ : t('accountSwitcher.loading') || 'Preparing sign-in…';
516
+ return (
517
+ <View style={styles.centeredBlock}>
518
+ <MaterialCommunityIcons name="loading" size={26} color={theme.colors.primary} />
519
+ <Text style={[styles.mutedText, { color: theme.colors.textSecondary }]}>{label}</Text>
520
+ </View>
521
+ );
522
+ }
523
+
524
+ return (
525
+ <View style={styles.centeredBlock}>
526
+ <View style={styles.qrPlate}>
527
+ <QRCode value={signIn.qrPayload} size={QR_SIZE} backgroundColor={QR_PLATE_BG} color={QR_FOREGROUND} />
528
+ </View>
529
+ <Text style={[styles.mutedText, { color: theme.colors.textSecondary }]}>
530
+ {t('accountSwitcher.scanWithOxy') || 'Scan with any Oxy app and approve.'}
531
+ </Text>
532
+ </View>
533
+ );
534
+ };
535
+
536
+ // ---------------------------------------------------------------------------
537
+ // Copy + helpers
538
+ // ---------------------------------------------------------------------------
539
+
540
+ function headerCopy(
541
+ view: AccountDialogSnapshot['view'],
542
+ accountCount: number,
543
+ t: Translate,
544
+ ): { title: string; subtitle: string | null } {
545
+ switch (view) {
546
+ case 'accounts':
547
+ return {
548
+ title: t('accountSwitcher.sections.yourAccounts') || 'Your accounts',
549
+ subtitle: t('signin.chooser.subtitle') || 'Choose which account to continue with.',
550
+ };
551
+ case 'qr':
552
+ return {
553
+ title: t('accountSwitcher.scanTitle') || 'Scan with Oxy',
554
+ subtitle: t('accountSwitcher.scanSubtitle') || 'Approve from your phone.',
555
+ };
556
+ default:
557
+ return accountCount > 0
558
+ ? {
559
+ title: t('signin.addAccountTitle') || 'Add another account',
560
+ subtitle: t('signin.addAccountSubtitle') || 'Sign in with another account.',
561
+ }
562
+ : {
563
+ title: t('signin.title') || 'Sign in',
564
+ subtitle: t('signin.subtitle') || 'One identity for the whole ecosystem.',
565
+ };
566
+ }
567
+ }
568
+
569
+ /** Current document URL on web; `undefined` where `location` is absent. */
570
+ function currentHref(): string | undefined {
571
+ const location = (globalThis as { location?: { href?: string } }).location;
572
+ return typeof location?.href === 'string' ? location.href : undefined;
573
+ }
574
+
575
+ const EMPTY_SNAPSHOT: AccountDialogSnapshot = {
576
+ view: 'accounts',
577
+ accounts: [],
578
+ activeAccountId: null,
579
+ loading: false,
580
+ error: null,
581
+ switchingAccountId: null,
582
+ signIn: { phase: 'idle', authorizeCode: null, qrPayload: null, expiresAt: null, error: null },
583
+ };
584
+
585
+ const styles = StyleSheet.create({
586
+ root: {
587
+ flex: 1,
588
+ },
589
+ backdrop: {
590
+ flex: 1,
591
+ justifyContent: isWeb ? 'center' : 'flex-end',
592
+ alignItems: 'center',
593
+ },
594
+ card: {
595
+ width: '100%',
596
+ maxWidth: 420,
597
+ borderWidth: StyleSheet.hairlineWidth,
598
+ paddingHorizontal: 20,
599
+ paddingTop: 16,
600
+ paddingBottom: 24,
601
+ },
602
+ cardCentered: {
603
+ borderRadius: 28,
604
+ },
605
+ cardSheet: {
606
+ borderTopLeftRadius: 28,
607
+ borderTopRightRadius: 28,
608
+ },
609
+ header: {
610
+ alignItems: 'center',
611
+ marginBottom: 12,
612
+ },
613
+ headerBar: {
614
+ width: '100%',
615
+ flexDirection: 'row',
616
+ alignItems: 'center',
617
+ justifyContent: 'space-between',
618
+ marginBottom: 8,
619
+ },
620
+ iconButton: {
621
+ width: 32,
622
+ height: 32,
623
+ borderRadius: 16,
624
+ alignItems: 'center',
625
+ justifyContent: 'center',
626
+ },
627
+ title: {
628
+ fontSize: 22,
629
+ fontWeight: '800',
630
+ letterSpacing: -0.4,
631
+ textAlign: 'center',
632
+ marginTop: 6,
633
+ },
634
+ subtitle: {
635
+ fontSize: 14,
636
+ lineHeight: 19,
637
+ textAlign: 'center',
638
+ marginTop: 4,
639
+ },
640
+ body: {
641
+ width: '100%',
642
+ },
643
+ bodyContent: {
644
+ paddingTop: 4,
645
+ paddingBottom: 4,
646
+ },
647
+ rows: {
648
+ width: '100%',
649
+ gap: 8,
650
+ },
651
+ accountRow: {
652
+ flexDirection: 'row',
653
+ alignItems: 'center',
654
+ gap: 12,
655
+ borderWidth: StyleSheet.hairlineWidth,
656
+ borderRadius: 16,
657
+ paddingVertical: 10,
658
+ paddingHorizontal: 12,
659
+ },
660
+ rowDisabled: {
661
+ opacity: 0.6,
662
+ },
663
+ avatarRing: {
664
+ borderRadius: 9999,
665
+ borderWidth: 2,
666
+ padding: 1,
667
+ },
668
+ rowMeta: {
669
+ flex: 1,
670
+ minWidth: 0,
671
+ },
672
+ rowName: {
673
+ fontSize: 15,
674
+ fontWeight: '600',
675
+ },
676
+ rowHandle: {
677
+ fontSize: 12.5,
678
+ marginTop: 1,
679
+ },
680
+ addRow: {
681
+ flexDirection: 'row',
682
+ alignItems: 'center',
683
+ gap: 12,
684
+ borderWidth: StyleSheet.hairlineWidth,
685
+ borderStyle: 'dashed',
686
+ borderRadius: 16,
687
+ paddingVertical: 10,
688
+ paddingHorizontal: 12,
689
+ marginTop: 8,
690
+ },
691
+ addBadge: {
692
+ width: ROW_AVATAR_SIZE,
693
+ height: ROW_AVATAR_SIZE,
694
+ borderRadius: 9999,
695
+ borderWidth: StyleSheet.hairlineWidth,
696
+ alignItems: 'center',
697
+ justifyContent: 'center',
698
+ },
699
+ footerLinks: {
700
+ alignItems: 'center',
701
+ marginTop: 16,
702
+ },
703
+ linkText: {
704
+ fontSize: 14,
705
+ fontWeight: '600',
706
+ },
707
+ signInBlock: {
708
+ width: '100%',
709
+ },
710
+ primaryButton: {
711
+ width: '100%',
712
+ borderRadius: 14,
713
+ marginTop: 8,
714
+ },
715
+ secondaryButton: {
716
+ width: '100%',
717
+ borderRadius: 14,
718
+ marginTop: 10,
719
+ },
720
+ passwordLink: {
721
+ alignSelf: 'center',
722
+ paddingVertical: 10,
723
+ marginTop: 12,
724
+ },
725
+ dividerRow: {
726
+ flexDirection: 'row',
727
+ alignItems: 'center',
728
+ width: '100%',
729
+ marginVertical: 14,
730
+ },
731
+ dividerLine: {
732
+ flex: 1,
733
+ height: StyleSheet.hairlineWidth,
734
+ },
735
+ dividerText: {
736
+ marginHorizontal: 12,
737
+ fontSize: 13,
738
+ },
739
+ centeredBlock: {
740
+ alignItems: 'center',
741
+ justifyContent: 'center',
742
+ gap: 12,
743
+ paddingVertical: 24,
744
+ },
745
+ mutedText: {
746
+ fontSize: 14,
747
+ textAlign: 'center',
748
+ },
749
+ errorText: {
750
+ fontSize: 14,
751
+ textAlign: 'center',
752
+ },
753
+ qrPlate: {
754
+ padding: 16,
755
+ borderRadius: 16,
756
+ backgroundColor: QR_PLATE_BG,
757
+ },
758
+ });
759
+
760
+ export default OxyAccountDialog;