@oxyhq/services 5.13.0 → 5.13.2

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 (353) hide show
  1. package/README.md +71 -0
  2. package/lib/commonjs/core/HttpClient.js +238 -0
  3. package/lib/commonjs/core/HttpClient.js.map +1 -0
  4. package/lib/commonjs/core/OxyServices.js +530 -332
  5. package/lib/commonjs/core/OxyServices.js.map +1 -1
  6. package/lib/commonjs/core/RequestManager.js +199 -0
  7. package/lib/commonjs/core/RequestManager.js.map +1 -0
  8. package/lib/commonjs/core/index.js +38 -1
  9. package/lib/commonjs/core/index.js.map +1 -1
  10. package/lib/commonjs/i18n/index.js +37 -1
  11. package/lib/commonjs/i18n/index.js.map +1 -1
  12. package/lib/commonjs/i18n/locales/ar-SA.json +128 -0
  13. package/lib/commonjs/i18n/locales/ca-ES.json +128 -0
  14. package/lib/commonjs/i18n/locales/de-DE.json +128 -0
  15. package/lib/commonjs/i18n/locales/en-US.json +85 -12
  16. package/lib/commonjs/i18n/locales/es-ES.json +58 -6
  17. package/lib/commonjs/i18n/locales/fr-FR.json +128 -0
  18. package/lib/commonjs/i18n/locales/it-IT.json +128 -0
  19. package/lib/commonjs/i18n/locales/ja-JP.json +127 -0
  20. package/lib/commonjs/i18n/locales/ko-KR.json +128 -0
  21. package/lib/commonjs/i18n/locales/pt-PT.json +128 -0
  22. package/lib/commonjs/i18n/locales/zh-CN.json +128 -0
  23. package/lib/commonjs/index.js +36 -0
  24. package/lib/commonjs/index.js.map +1 -1
  25. package/lib/commonjs/ui/components/Avatar.js +94 -27
  26. package/lib/commonjs/ui/components/Avatar.js.map +1 -1
  27. package/lib/commonjs/ui/components/FollowButton.js +1 -0
  28. package/lib/commonjs/ui/components/FollowButton.js.map +1 -1
  29. package/lib/commonjs/ui/components/FontLoader.js +22 -42
  30. package/lib/commonjs/ui/components/FontLoader.js.map +1 -1
  31. package/lib/commonjs/ui/components/OxyProvider.js +5 -8
  32. package/lib/commonjs/ui/components/OxyProvider.js.map +1 -1
  33. package/lib/commonjs/ui/components/StepBasedScreen.js +64 -44
  34. package/lib/commonjs/ui/components/StepBasedScreen.js.map +1 -1
  35. package/lib/commonjs/ui/components/internal/GroupedPillButtons.js +14 -35
  36. package/lib/commonjs/ui/components/internal/GroupedPillButtons.js.map +1 -1
  37. package/lib/commonjs/ui/components/internal/PinInput.js +2 -2
  38. package/lib/commonjs/ui/components/internal/PinInput.js.map +1 -1
  39. package/lib/commonjs/ui/components/internal/TextField.js +13 -8
  40. package/lib/commonjs/ui/components/internal/TextField.js.map +1 -1
  41. package/lib/commonjs/ui/context/OxyContext.js +443 -371
  42. package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
  43. package/lib/commonjs/ui/hooks/useSessionSocket.js +80 -22
  44. package/lib/commonjs/ui/hooks/useSessionSocket.js.map +1 -1
  45. package/lib/commonjs/ui/index.js +4 -1
  46. package/lib/commonjs/ui/index.js.map +1 -1
  47. package/lib/commonjs/ui/screens/AccountSettingsScreen.js +32 -2
  48. package/lib/commonjs/ui/screens/AccountSettingsScreen.js.map +1 -1
  49. package/lib/commonjs/ui/screens/AccountSwitcherScreen.js +101 -59
  50. package/lib/commonjs/ui/screens/AccountSwitcherScreen.js.map +1 -1
  51. package/lib/commonjs/ui/screens/FileManagementScreen.js +3 -2
  52. package/lib/commonjs/ui/screens/FileManagementScreen.js.map +1 -1
  53. package/lib/commonjs/ui/screens/LanguageSelectorScreen.js +75 -117
  54. package/lib/commonjs/ui/screens/LanguageSelectorScreen.js.map +1 -1
  55. package/lib/commonjs/ui/screens/SignInScreen.js +43 -50
  56. package/lib/commonjs/ui/screens/SignInScreen.js.map +1 -1
  57. package/lib/commonjs/ui/screens/SignUpScreen.js +14 -16
  58. package/lib/commonjs/ui/screens/SignUpScreen.js.map +1 -1
  59. package/lib/commonjs/ui/screens/WelcomeNewUserScreen.js +188 -142
  60. package/lib/commonjs/ui/screens/WelcomeNewUserScreen.js.map +1 -1
  61. package/lib/commonjs/ui/screens/internal/SignInPasswordStep.js +10 -10
  62. package/lib/commonjs/ui/screens/internal/SignInPasswordStep.js.map +1 -1
  63. package/lib/commonjs/ui/screens/internal/SignInUsernameStep.js +2 -4
  64. package/lib/commonjs/ui/screens/internal/SignInUsernameStep.js.map +1 -1
  65. package/lib/commonjs/ui/screens/steps/RecoverRequestStep.js +45 -25
  66. package/lib/commonjs/ui/screens/steps/RecoverRequestStep.js.map +1 -1
  67. package/lib/commonjs/ui/screens/steps/RecoverResetPasswordStep.js +88 -53
  68. package/lib/commonjs/ui/screens/steps/RecoverResetPasswordStep.js.map +1 -1
  69. package/lib/commonjs/ui/screens/steps/RecoverSuccessStep.js +79 -58
  70. package/lib/commonjs/ui/screens/steps/RecoverSuccessStep.js.map +1 -1
  71. package/lib/commonjs/ui/screens/steps/RecoverVerifyStep.js +61 -52
  72. package/lib/commonjs/ui/screens/steps/RecoverVerifyStep.js.map +1 -1
  73. package/lib/commonjs/ui/screens/steps/SignInPasswordStep.js +218 -39
  74. package/lib/commonjs/ui/screens/steps/SignInPasswordStep.js.map +1 -1
  75. package/lib/commonjs/ui/screens/steps/SignInTotpStep.js +77 -50
  76. package/lib/commonjs/ui/screens/steps/SignInTotpStep.js.map +1 -1
  77. package/lib/commonjs/ui/screens/steps/SignInUsernameStep.js +424 -71
  78. package/lib/commonjs/ui/screens/steps/SignInUsernameStep.js.map +1 -1
  79. package/lib/commonjs/ui/screens/steps/SignUpIdentityStep.js +55 -30
  80. package/lib/commonjs/ui/screens/steps/SignUpIdentityStep.js.map +1 -1
  81. package/lib/commonjs/ui/screens/steps/SignUpSecurityStep.js +64 -46
  82. package/lib/commonjs/ui/screens/steps/SignUpSecurityStep.js.map +1 -1
  83. package/lib/commonjs/ui/screens/steps/SignUpSummaryStep.js +84 -146
  84. package/lib/commonjs/ui/screens/steps/SignUpSummaryStep.js.map +1 -1
  85. package/lib/commonjs/ui/screens/steps/SignUpWelcomeStep.js +113 -34
  86. package/lib/commonjs/ui/screens/steps/SignUpWelcomeStep.js.map +1 -1
  87. package/lib/commonjs/ui/stores/accountStore.js +237 -0
  88. package/lib/commonjs/ui/stores/accountStore.js.map +1 -0
  89. package/lib/commonjs/ui/stores/authStore.js +17 -20
  90. package/lib/commonjs/ui/stores/authStore.js.map +1 -1
  91. package/lib/commonjs/ui/styles/authStyles.js +16 -8
  92. package/lib/commonjs/ui/styles/authStyles.js.map +1 -1
  93. package/lib/commonjs/ui/styles/index.js +11 -0
  94. package/lib/commonjs/ui/styles/index.js.map +1 -1
  95. package/lib/commonjs/ui/styles/spacing.js +51 -0
  96. package/lib/commonjs/ui/styles/spacing.js.map +1 -0
  97. package/lib/commonjs/utils/asyncUtils.js +9 -22
  98. package/lib/commonjs/utils/asyncUtils.js.map +1 -1
  99. package/lib/commonjs/utils/cache.js +259 -0
  100. package/lib/commonjs/utils/cache.js.map +1 -0
  101. package/lib/commonjs/utils/index.js +99 -0
  102. package/lib/commonjs/utils/index.js.map +1 -1
  103. package/lib/commonjs/utils/languageUtils.js +159 -0
  104. package/lib/commonjs/utils/languageUtils.js.map +1 -0
  105. package/lib/commonjs/utils/requestUtils.js +217 -0
  106. package/lib/commonjs/utils/requestUtils.js.map +1 -0
  107. package/lib/commonjs/utils/sessionUtils.js +191 -0
  108. package/lib/commonjs/utils/sessionUtils.js.map +1 -0
  109. package/lib/commonjs/utils/validationUtils.js +1 -1
  110. package/lib/module/core/HttpClient.js +232 -0
  111. package/lib/module/core/HttpClient.js.map +1 -0
  112. package/lib/module/core/OxyServices.js +528 -326
  113. package/lib/module/core/OxyServices.js.map +1 -1
  114. package/lib/module/core/RequestManager.js +194 -0
  115. package/lib/module/core/RequestManager.js.map +1 -0
  116. package/lib/module/core/index.js +2 -0
  117. package/lib/module/core/index.js.map +1 -1
  118. package/lib/module/i18n/index.js +37 -1
  119. package/lib/module/i18n/index.js.map +1 -1
  120. package/lib/module/i18n/locales/ar-SA.json +128 -0
  121. package/lib/module/i18n/locales/ca-ES.json +128 -0
  122. package/lib/module/i18n/locales/de-DE.json +128 -0
  123. package/lib/module/i18n/locales/en-US.json +85 -12
  124. package/lib/module/i18n/locales/es-ES.json +58 -6
  125. package/lib/module/i18n/locales/fr-FR.json +128 -0
  126. package/lib/module/i18n/locales/it-IT.json +128 -0
  127. package/lib/module/i18n/locales/ja-JP.json +127 -0
  128. package/lib/module/i18n/locales/ko-KR.json +128 -0
  129. package/lib/module/i18n/locales/pt-PT.json +128 -0
  130. package/lib/module/i18n/locales/zh-CN.json +128 -0
  131. package/lib/module/index.js +2 -0
  132. package/lib/module/index.js.map +1 -1
  133. package/lib/module/ui/components/Avatar.js +94 -27
  134. package/lib/module/ui/components/Avatar.js.map +1 -1
  135. package/lib/module/ui/components/FollowButton.js +1 -0
  136. package/lib/module/ui/components/FollowButton.js.map +1 -1
  137. package/lib/module/ui/components/FontLoader.js +23 -43
  138. package/lib/module/ui/components/FontLoader.js.map +1 -1
  139. package/lib/module/ui/components/OxyProvider.js +6 -8
  140. package/lib/module/ui/components/OxyProvider.js.map +1 -1
  141. package/lib/module/ui/components/StepBasedScreen.js +65 -45
  142. package/lib/module/ui/components/StepBasedScreen.js.map +1 -1
  143. package/lib/module/ui/components/internal/GroupedPillButtons.js +14 -35
  144. package/lib/module/ui/components/internal/GroupedPillButtons.js.map +1 -1
  145. package/lib/module/ui/components/internal/PinInput.js +2 -2
  146. package/lib/module/ui/components/internal/PinInput.js.map +1 -1
  147. package/lib/module/ui/components/internal/TextField.js +13 -8
  148. package/lib/module/ui/components/internal/TextField.js.map +1 -1
  149. package/lib/module/ui/context/OxyContext.js +442 -370
  150. package/lib/module/ui/context/OxyContext.js.map +1 -1
  151. package/lib/module/ui/hooks/useSessionSocket.js +80 -22
  152. package/lib/module/ui/hooks/useSessionSocket.js.map +1 -1
  153. package/lib/module/ui/index.js +4 -2
  154. package/lib/module/ui/index.js.map +1 -1
  155. package/lib/module/ui/screens/AccountSettingsScreen.js +33 -2
  156. package/lib/module/ui/screens/AccountSettingsScreen.js.map +1 -1
  157. package/lib/module/ui/screens/AccountSwitcherScreen.js +102 -60
  158. package/lib/module/ui/screens/AccountSwitcherScreen.js.map +1 -1
  159. package/lib/module/ui/screens/FileManagementScreen.js +3 -2
  160. package/lib/module/ui/screens/FileManagementScreen.js.map +1 -1
  161. package/lib/module/ui/screens/LanguageSelectorScreen.js +73 -117
  162. package/lib/module/ui/screens/LanguageSelectorScreen.js.map +1 -1
  163. package/lib/module/ui/screens/SignInScreen.js +44 -51
  164. package/lib/module/ui/screens/SignInScreen.js.map +1 -1
  165. package/lib/module/ui/screens/SignUpScreen.js +14 -16
  166. package/lib/module/ui/screens/SignUpScreen.js.map +1 -1
  167. package/lib/module/ui/screens/WelcomeNewUserScreen.js +187 -143
  168. package/lib/module/ui/screens/WelcomeNewUserScreen.js.map +1 -1
  169. package/lib/module/ui/screens/internal/SignInPasswordStep.js +10 -10
  170. package/lib/module/ui/screens/internal/SignInPasswordStep.js.map +1 -1
  171. package/lib/module/ui/screens/internal/SignInUsernameStep.js +2 -4
  172. package/lib/module/ui/screens/internal/SignInUsernameStep.js.map +1 -1
  173. package/lib/module/ui/screens/steps/RecoverRequestStep.js +45 -25
  174. package/lib/module/ui/screens/steps/RecoverRequestStep.js.map +1 -1
  175. package/lib/module/ui/screens/steps/RecoverResetPasswordStep.js +89 -54
  176. package/lib/module/ui/screens/steps/RecoverResetPasswordStep.js.map +1 -1
  177. package/lib/module/ui/screens/steps/RecoverSuccessStep.js +80 -59
  178. package/lib/module/ui/screens/steps/RecoverSuccessStep.js.map +1 -1
  179. package/lib/module/ui/screens/steps/RecoverVerifyStep.js +62 -53
  180. package/lib/module/ui/screens/steps/RecoverVerifyStep.js.map +1 -1
  181. package/lib/module/ui/screens/steps/SignInPasswordStep.js +219 -40
  182. package/lib/module/ui/screens/steps/SignInPasswordStep.js.map +1 -1
  183. package/lib/module/ui/screens/steps/SignInTotpStep.js +78 -51
  184. package/lib/module/ui/screens/steps/SignInTotpStep.js.map +1 -1
  185. package/lib/module/ui/screens/steps/SignInUsernameStep.js +426 -73
  186. package/lib/module/ui/screens/steps/SignInUsernameStep.js.map +1 -1
  187. package/lib/module/ui/screens/steps/SignUpIdentityStep.js +55 -30
  188. package/lib/module/ui/screens/steps/SignUpIdentityStep.js.map +1 -1
  189. package/lib/module/ui/screens/steps/SignUpSecurityStep.js +65 -47
  190. package/lib/module/ui/screens/steps/SignUpSecurityStep.js.map +1 -1
  191. package/lib/module/ui/screens/steps/SignUpSummaryStep.js +84 -146
  192. package/lib/module/ui/screens/steps/SignUpSummaryStep.js.map +1 -1
  193. package/lib/module/ui/screens/steps/SignUpWelcomeStep.js +114 -35
  194. package/lib/module/ui/screens/steps/SignUpWelcomeStep.js.map +1 -1
  195. package/lib/module/ui/stores/accountStore.js +229 -0
  196. package/lib/module/ui/stores/accountStore.js.map +1 -0
  197. package/lib/module/ui/stores/authStore.js +17 -20
  198. package/lib/module/ui/stores/authStore.js.map +1 -1
  199. package/lib/module/ui/styles/authStyles.js +16 -8
  200. package/lib/module/ui/styles/authStyles.js.map +1 -1
  201. package/lib/module/ui/styles/index.js +1 -0
  202. package/lib/module/ui/styles/index.js.map +1 -1
  203. package/lib/module/ui/styles/spacing.js +48 -0
  204. package/lib/module/ui/styles/spacing.js.map +1 -0
  205. package/lib/module/utils/asyncUtils.js +10 -22
  206. package/lib/module/utils/asyncUtils.js.map +1 -1
  207. package/lib/module/utils/cache.js +250 -0
  208. package/lib/module/utils/cache.js.map +1 -0
  209. package/lib/module/utils/index.js +7 -0
  210. package/lib/module/utils/index.js.map +1 -1
  211. package/lib/module/utils/languageUtils.js +151 -0
  212. package/lib/module/utils/languageUtils.js.map +1 -0
  213. package/lib/module/utils/requestUtils.js +210 -0
  214. package/lib/module/utils/requestUtils.js.map +1 -0
  215. package/lib/module/utils/sessionUtils.js +180 -0
  216. package/lib/module/utils/sessionUtils.js.map +1 -0
  217. package/lib/module/utils/validationUtils.js +1 -1
  218. package/lib/typescript/core/HttpClient.d.ts +64 -0
  219. package/lib/typescript/core/HttpClient.d.ts.map +1 -0
  220. package/lib/typescript/core/OxyServices.d.ts +86 -73
  221. package/lib/typescript/core/OxyServices.d.ts.map +1 -1
  222. package/lib/typescript/core/RequestManager.d.ts +67 -0
  223. package/lib/typescript/core/RequestManager.d.ts.map +1 -0
  224. package/lib/typescript/core/index.d.ts +2 -0
  225. package/lib/typescript/core/index.d.ts.map +1 -1
  226. package/lib/typescript/i18n/index.d.ts.map +1 -1
  227. package/lib/typescript/index.d.ts +2 -0
  228. package/lib/typescript/index.d.ts.map +1 -1
  229. package/lib/typescript/models/interfaces.d.ts +15 -0
  230. package/lib/typescript/models/interfaces.d.ts.map +1 -1
  231. package/lib/typescript/models/session.d.ts +1 -0
  232. package/lib/typescript/models/session.d.ts.map +1 -1
  233. package/lib/typescript/ui/components/Avatar.d.ts +6 -7
  234. package/lib/typescript/ui/components/Avatar.d.ts.map +1 -1
  235. package/lib/typescript/ui/components/FollowButton.d.ts.map +1 -1
  236. package/lib/typescript/ui/components/FontLoader.d.ts +3 -3
  237. package/lib/typescript/ui/components/FontLoader.d.ts.map +1 -1
  238. package/lib/typescript/ui/components/OxyProvider.d.ts +2 -2
  239. package/lib/typescript/ui/components/OxyProvider.d.ts.map +1 -1
  240. package/lib/typescript/ui/components/StepBasedScreen.d.ts.map +1 -1
  241. package/lib/typescript/ui/components/internal/GroupedPillButtons.d.ts.map +1 -1
  242. package/lib/typescript/ui/components/internal/TextField.d.ts.map +1 -1
  243. package/lib/typescript/ui/context/OxyContext.d.ts +5 -0
  244. package/lib/typescript/ui/context/OxyContext.d.ts.map +1 -1
  245. package/lib/typescript/ui/hooks/useSessionSocket.d.ts.map +1 -1
  246. package/lib/typescript/ui/index.d.ts +2 -2
  247. package/lib/typescript/ui/index.d.ts.map +1 -1
  248. package/lib/typescript/ui/screens/AccountSettingsScreen.d.ts.map +1 -1
  249. package/lib/typescript/ui/screens/AccountSwitcherScreen.d.ts.map +1 -1
  250. package/lib/typescript/ui/screens/LanguageSelectorScreen.d.ts +3 -3
  251. package/lib/typescript/ui/screens/LanguageSelectorScreen.d.ts.map +1 -1
  252. package/lib/typescript/ui/screens/SignInScreen.d.ts.map +1 -1
  253. package/lib/typescript/ui/screens/SignUpScreen.d.ts.map +1 -1
  254. package/lib/typescript/ui/screens/WelcomeNewUserScreen.d.ts.map +1 -1
  255. package/lib/typescript/ui/screens/internal/SignInPasswordStep.d.ts.map +1 -1
  256. package/lib/typescript/ui/screens/steps/RecoverRequestStep.d.ts.map +1 -1
  257. package/lib/typescript/ui/screens/steps/RecoverResetPasswordStep.d.ts.map +1 -1
  258. package/lib/typescript/ui/screens/steps/RecoverSuccessStep.d.ts.map +1 -1
  259. package/lib/typescript/ui/screens/steps/RecoverVerifyStep.d.ts.map +1 -1
  260. package/lib/typescript/ui/screens/steps/SignInPasswordStep.d.ts +2 -0
  261. package/lib/typescript/ui/screens/steps/SignInPasswordStep.d.ts.map +1 -1
  262. package/lib/typescript/ui/screens/steps/SignInTotpStep.d.ts.map +1 -1
  263. package/lib/typescript/ui/screens/steps/SignInUsernameStep.d.ts.map +1 -1
  264. package/lib/typescript/ui/screens/steps/SignUpIdentityStep.d.ts.map +1 -1
  265. package/lib/typescript/ui/screens/steps/SignUpSecurityStep.d.ts.map +1 -1
  266. package/lib/typescript/ui/screens/steps/SignUpSummaryStep.d.ts.map +1 -1
  267. package/lib/typescript/ui/screens/steps/SignUpWelcomeStep.d.ts.map +1 -1
  268. package/lib/typescript/ui/stores/accountStore.d.ts +34 -0
  269. package/lib/typescript/ui/stores/accountStore.d.ts.map +1 -0
  270. package/lib/typescript/ui/stores/authStore.d.ts +7 -3
  271. package/lib/typescript/ui/stores/authStore.d.ts.map +1 -1
  272. package/lib/typescript/ui/styles/authStyles.d.ts +19 -2
  273. package/lib/typescript/ui/styles/authStyles.d.ts.map +1 -1
  274. package/lib/typescript/ui/styles/index.d.ts +1 -0
  275. package/lib/typescript/ui/styles/index.d.ts.map +1 -1
  276. package/lib/typescript/ui/styles/spacing.d.ts +43 -0
  277. package/lib/typescript/ui/styles/spacing.d.ts.map +1 -0
  278. package/lib/typescript/utils/asyncUtils.d.ts +2 -0
  279. package/lib/typescript/utils/asyncUtils.d.ts.map +1 -1
  280. package/lib/typescript/utils/cache.d.ts +128 -0
  281. package/lib/typescript/utils/cache.d.ts.map +1 -0
  282. package/lib/typescript/utils/index.d.ts +4 -0
  283. package/lib/typescript/utils/index.d.ts.map +1 -1
  284. package/lib/typescript/utils/languageUtils.d.ts +38 -0
  285. package/lib/typescript/utils/languageUtils.d.ts.map +1 -0
  286. package/lib/typescript/utils/requestUtils.d.ts +122 -0
  287. package/lib/typescript/utils/requestUtils.d.ts.map +1 -0
  288. package/lib/typescript/utils/sessionUtils.d.ts +55 -0
  289. package/lib/typescript/utils/sessionUtils.d.ts.map +1 -0
  290. package/lib/typescript/utils/validationUtils.d.ts +1 -1
  291. package/package.json +1 -1
  292. package/src/core/HttpClient.ts +277 -0
  293. package/src/core/OxyServices.ts +461 -352
  294. package/src/core/RequestManager.ts +240 -0
  295. package/src/core/index.ts +10 -0
  296. package/src/i18n/index.ts +36 -0
  297. package/src/i18n/locales/ar-SA.json +128 -0
  298. package/src/i18n/locales/ca-ES.json +128 -0
  299. package/src/i18n/locales/de-DE.json +128 -0
  300. package/src/i18n/locales/en-US.json +85 -12
  301. package/src/i18n/locales/es-ES.json +58 -6
  302. package/src/i18n/locales/fr-FR.json +128 -0
  303. package/src/i18n/locales/it-IT.json +128 -0
  304. package/src/i18n/locales/ja-JP.json +127 -0
  305. package/src/i18n/locales/ko-KR.json +128 -0
  306. package/src/i18n/locales/pt-PT.json +128 -0
  307. package/src/i18n/locales/zh-CN.json +128 -0
  308. package/src/index.ts +10 -0
  309. package/src/models/interfaces.ts +19 -0
  310. package/src/models/session.ts +1 -1
  311. package/src/ui/components/Avatar.tsx +151 -35
  312. package/src/ui/components/FollowButton.tsx +1 -0
  313. package/src/ui/components/FontLoader.tsx +17 -37
  314. package/src/ui/components/OxyProvider.tsx +14 -13
  315. package/src/ui/components/StepBasedScreen.tsx +66 -43
  316. package/src/ui/components/internal/GroupedPillButtons.tsx +15 -31
  317. package/src/ui/components/internal/PinInput.tsx +2 -2
  318. package/src/ui/components/internal/TextField.tsx +7 -6
  319. package/src/ui/context/OxyContext.tsx +441 -326
  320. package/src/ui/hooks/useSessionSocket.ts +72 -18
  321. package/src/ui/index.ts +4 -1
  322. package/src/ui/screens/AccountSettingsScreen.tsx +34 -2
  323. package/src/ui/screens/AccountSwitcherScreen.tsx +102 -68
  324. package/src/ui/screens/FileManagementScreen.tsx +16 -16
  325. package/src/ui/screens/LanguageSelectorScreen.tsx +86 -143
  326. package/src/ui/screens/SignInScreen.tsx +59 -43
  327. package/src/ui/screens/SignUpScreen.tsx +14 -15
  328. package/src/ui/screens/WelcomeNewUserScreen.tsx +153 -105
  329. package/src/ui/screens/internal/SignInPasswordStep.tsx +4 -6
  330. package/src/ui/screens/internal/SignInUsernameStep.tsx +1 -1
  331. package/src/ui/screens/steps/RecoverRequestStep.tsx +34 -24
  332. package/src/ui/screens/steps/RecoverResetPasswordStep.tsx +65 -36
  333. package/src/ui/screens/steps/RecoverSuccessStep.tsx +71 -47
  334. package/src/ui/screens/steps/RecoverVerifyStep.tsx +60 -50
  335. package/src/ui/screens/steps/SignInPasswordStep.tsx +190 -32
  336. package/src/ui/screens/steps/SignInTotpStep.tsx +68 -34
  337. package/src/ui/screens/steps/SignInUsernameStep.tsx +446 -63
  338. package/src/ui/screens/steps/SignUpIdentityStep.tsx +49 -35
  339. package/src/ui/screens/steps/SignUpSecurityStep.tsx +56 -39
  340. package/src/ui/screens/steps/SignUpSummaryStep.tsx +99 -89
  341. package/src/ui/screens/steps/SignUpWelcomeStep.tsx +88 -20
  342. package/src/ui/stores/accountStore.ts +285 -0
  343. package/src/ui/stores/authStore.ts +16 -19
  344. package/src/ui/styles/authStyles.ts +16 -8
  345. package/src/ui/styles/index.ts +1 -0
  346. package/src/ui/styles/spacing.ts +46 -0
  347. package/src/utils/asyncUtils.ts +10 -24
  348. package/src/utils/cache.ts +264 -0
  349. package/src/utils/index.ts +19 -0
  350. package/src/utils/languageUtils.ts +174 -0
  351. package/src/utils/requestUtils.ts +234 -0
  352. package/src/utils/sessionUtils.ts +206 -0
  353. package/src/utils/validationUtils.ts +1 -1
@@ -1,4 +1,5 @@
1
1
  import type React from 'react';
2
+ import { memo, useMemo } from 'react';
2
3
  import { View, Text, Image, StyleSheet, type StyleProp, type ViewStyle, type ImageStyle, type TextStyle, ActivityIndicator, Platform } from 'react-native';
3
4
  import { useThemeColors } from '../styles';
4
5
  import { fontFamilies } from '../styles/fonts';
@@ -16,7 +17,10 @@ export interface AvatarProps {
16
17
  text?: string;
17
18
 
18
19
  /**
19
- * Full name to derive the initials from (takes first letter)
20
+ * Full name to derive the initials from
21
+ * For single word: takes first letter
22
+ * For multiple words: takes first letter of first and last word (e.g., "John Doe" -> "JD")
23
+ * For usernames starting with @: takes first two letters after @
20
24
  */
21
25
  name?: string;
22
26
 
@@ -67,9 +71,68 @@ export interface AvatarProps {
67
71
  isLoading?: boolean;
68
72
  }
69
73
 
74
+ /**
75
+ * Extracts initials from a name string
76
+ * - Single word: first letter (e.g., "John" -> "J")
77
+ * - Multiple words: first letter of first and last word (e.g., "John Doe" -> "JD")
78
+ * - Username starting with @: first two letters after @ (e.g., "@johndoe" -> "JO")
79
+ */
80
+ const getInitials = (nameStr: string): string => {
81
+ if (!nameStr?.trim()) return '';
82
+
83
+ const trimmed = nameStr.trim();
84
+ const parts = trimmed.split(/\s+/).filter(part => part.length > 0);
85
+
86
+ if (parts.length === 0) return '';
87
+
88
+ if (parts.length === 1) {
89
+ const firstPart = parts[0];
90
+ // Handle username format (@username)
91
+ if (firstPart.length >= 2 && firstPart.startsWith('@')) {
92
+ return firstPart.substring(1, 3).toUpperCase();
93
+ }
94
+ return firstPart.charAt(0).toUpperCase();
95
+ }
96
+
97
+ // Multiple words: first letter of first and last word
98
+ return (parts[0].charAt(0) + parts[parts.length - 1].charAt(0)).toUpperCase();
99
+ };
100
+
101
+ /**
102
+ * Generates a consistent color from a string (name)
103
+ * Uses a simple hash function to create a deterministic color
104
+ */
105
+ const generateColorFromString = (str: string): string => {
106
+ let hash = 0;
107
+ for (let i = 0; i < str.length; i++) {
108
+ hash = str.charCodeAt(i) + ((hash << 5) - hash);
109
+ }
110
+
111
+ // Generate a vibrant color with good contrast
112
+ const hue = Math.abs(hash) % 360;
113
+ // Use high saturation and medium lightness for vibrant, readable colors
114
+ return `hsl(${hue}, 65%, 55%)`;
115
+ };
116
+
117
+ /**
118
+ * Calculates font size based on avatar size for letter avatars
119
+ * Uses a larger ratio for better visibility
120
+ */
121
+ const calculateFontSize = (size: number): number => {
122
+ // Use larger font size for letter avatars (50-55% of size)
123
+ return size <= 40
124
+ ? Math.floor(size * 0.5)
125
+ : Math.floor(size * 0.45);
126
+ };
127
+
70
128
  /**
71
129
  * Avatar component that displays either an image or text avatar
72
- * Falls back to displaying the first letter of the name if no image is provided
130
+ * Falls back to displaying initials (1-2 letters) derived from the name if no image is provided
131
+ * Supports flexible sizing via the size prop (default: 40px)
132
+ *
133
+ * @example
134
+ * <Avatar name="John Doe" size={100} theme="light" />
135
+ * <Avatar uri="https://example.com/avatar.jpg" size={50} />
73
136
  */
74
137
  const Avatar: React.FC<AvatarProps> = ({
75
138
  uri,
@@ -84,58 +147,111 @@ const Avatar: React.FC<AvatarProps> = ({
84
147
  textStyle,
85
148
  isLoading = false,
86
149
  }) => {
87
- // Get theme colors
88
150
  const colors = useThemeColors(theme);
89
151
 
90
- // Use the primary color from theme as default background if not specified
91
- const bgColor = backgroundColor || colors.primary;
152
+ const displayText = useMemo(
153
+ () => text || (name ? getInitials(name) : ''),
154
+ [text, name]
155
+ );
156
+
157
+ // Generate a color from the name for letter avatars (only when no backgroundColor is provided and no uri)
158
+ const generatedBgColor = useMemo(
159
+ () => {
160
+ if (backgroundColor) return backgroundColor;
161
+ if (uri) return colors.primary; // Use primary for image avatars as fallback
162
+ // Generate color from name for letter avatars
163
+ const nameForColor = name || text || 'User';
164
+ return generateColorFromString(nameForColor);
165
+ },
166
+ [backgroundColor, uri, name, text, colors.primary]
167
+ );
92
168
 
93
- // Calculate font size based on avatar size
94
- const fontSize = Math.floor(size * 0.4);
169
+ // Memoize computed values to avoid recalculation on every render
170
+ const bgColor = useMemo(
171
+ () => generatedBgColor,
172
+ [generatedBgColor]
173
+ );
95
174
 
96
- // Determine what text to display for fallback
97
- const displayText = text ||
98
- (name ? name.charAt(0).toUpperCase() : '');
175
+ const fontSize = useMemo(
176
+ () => calculateFontSize(size),
177
+ [size]
178
+ );
99
179
 
100
- // Style for container based on size
101
- const containerStyle = {
102
- width: size,
103
- height: size,
104
- borderRadius: size / 2, // Make it circular
105
- };
180
+ const containerStyle = useMemo(
181
+ () => ({
182
+ width: size,
183
+ height: size,
184
+ borderRadius: size / 2,
185
+ }),
186
+ [size]
187
+ );
106
188
 
189
+ const textStyleComputed = useMemo(
190
+ () => [
191
+ styles.text,
192
+ {
193
+ fontSize,
194
+ fontFamily: fontFamilies.phuduBold,
195
+ color: textColor,
196
+ textAlign: 'center' as const,
197
+ lineHeight: size, // Match line height to size for perfect vertical centering
198
+ ...(Platform.OS === 'android' && { includeFontPadding: false }), // Remove extra padding for better centering (Android only)
199
+ },
200
+ textStyle,
201
+ ],
202
+ [fontSize, textColor, textStyle, size]
203
+ );
204
+
205
+ // Early return for loading state
107
206
  if (isLoading) {
108
207
  return (
109
- <View style={[styles.container, containerStyle, { backgroundColor: colors.inputBackground }, style]}>
110
- <ActivityIndicator color={colors.primary} size={size > 50 ? 'large' : 'small'} />
208
+ <View
209
+ style={[
210
+ styles.container,
211
+ containerStyle,
212
+ { backgroundColor: colors.inputBackground },
213
+ style
214
+ ]}
215
+ >
216
+ <ActivityIndicator
217
+ color={colors.primary}
218
+ size={size > 50 ? 'large' : 'small'}
219
+ />
111
220
  </View>
112
221
  );
113
222
  }
114
223
 
115
- // If an image URL is provided, use Image component with optional background
224
+ // Image avatar
116
225
  if (uri) {
117
226
  return (
118
- <View style={[styles.container, containerStyle, { backgroundColor: bgColor }, style]}>
227
+ <View
228
+ style={[
229
+ styles.container,
230
+ containerStyle,
231
+ { backgroundColor: bgColor },
232
+ style
233
+ ]}
234
+ >
119
235
  <Image
120
- source={{ uri: uri }}
236
+ source={{ uri }}
121
237
  style={[styles.image, containerStyle, imageStyle]}
238
+ resizeMode="cover"
122
239
  />
123
240
  </View>
124
241
  );
125
242
  }
126
243
 
127
- // Otherwise show text avatar
244
+ // Text avatar with initials
128
245
  return (
129
- <View style={[styles.container, containerStyle, { backgroundColor: bgColor }, style]}>
130
- <Text style={[
131
- styles.text,
132
- {
133
- fontSize,
134
- fontFamily: fontFamilies.phuduBold,
135
- },
136
- { color: textColor },
137
- textStyle
138
- ]}>
246
+ <View
247
+ style={[
248
+ styles.container,
249
+ containerStyle,
250
+ { backgroundColor: bgColor },
251
+ style
252
+ ]}
253
+ >
254
+ <Text style={textStyleComputed}>
139
255
  {displayText}
140
256
  </Text>
141
257
  </View>
@@ -153,9 +269,9 @@ const styles = StyleSheet.create({
153
269
  height: '100%',
154
270
  },
155
271
  text: {
156
- // Font family is applied directly in the component to use the constants
157
- fontWeight: Platform.OS === 'web' ? 'bold' : undefined, // Only apply fontWeight on web
272
+ fontWeight: Platform.OS === 'web' ? 'bold' : undefined,
158
273
  },
159
274
  });
160
275
 
161
- export default Avatar;
276
+ // Memoize component to prevent unnecessary re-renders when props haven't changed
277
+ export default memo(Avatar);
@@ -153,6 +153,7 @@ const FollowButton: React.FC<FollowButtonProps> = ({
153
153
  boxShadow: '0 2px 4px rgba(0,0,0,0.1)',
154
154
  },
155
155
  default: {
156
+ shadowColor: '#000',
156
157
  shadowOffset: { width: 0, height: 2 },
157
158
  shadowOpacity: 0.1,
158
159
  shadowRadius: 4,
@@ -1,6 +1,6 @@
1
1
  import type React from 'react';
2
2
  import { useState, useEffect } from 'react';
3
- import { Text, View, ActivityIndicator, StyleSheet, Platform } from 'react-native';
3
+ import { Platform } from 'react-native';
4
4
  import * as Font from 'expo-font';
5
5
 
6
6
  /**
@@ -21,21 +21,22 @@ const getPhuduFonts = () => {
21
21
  'Phudu-Black': require('../../assets/fonts/Phudu/Phudu-Black.ttf'),
22
22
  };
23
23
  } catch (error) {
24
+ if (__DEV__) {
24
25
  console.warn('Failed to load Phudu fonts:', error);
26
+ }
25
27
  return null;
26
28
  }
27
29
  };
28
30
 
29
31
  /**
30
- * FontLoader component that loads custom fonts before rendering children
32
+ * FontLoader component that loads custom fonts in the background while rendering children immediately
31
33
  * This works in both the package development and when consumed as an npm package
34
+ * Children render immediately with system fonts as fallback until custom fonts are loaded
32
35
  */
33
36
  export const FontLoader = ({
34
37
  children,
35
- fallbackContent,
36
38
  }: {
37
39
  children: React.ReactNode;
38
- fallbackContent?: React.ReactNode;
39
40
  }) => {
40
41
  const [fontState, setFontState] = useState<'loading' | 'loaded' | 'error'>('loading');
41
42
 
@@ -54,8 +55,9 @@ export const FontLoader = ({
54
55
 
55
56
  setFontState('loaded');
56
57
  } catch (error) {
58
+ if (__DEV__) {
57
59
  console.error('Error loading fonts:', error);
58
- // Fallback to render without custom fonts
60
+ }
59
61
  setFontState('error');
60
62
  }
61
63
  };
@@ -63,23 +65,14 @@ export const FontLoader = ({
63
65
  loadFonts();
64
66
  }, []);
65
67
 
66
- if (fontState === 'loading') {
67
- // Render a loading placeholder while fonts are loading
68
- if (fallbackContent) {
69
- return <>{fallbackContent}</>;
70
- }
71
- return (
72
- <View style={styles.loaderContainer}>
73
- <ActivityIndicator size="small" color="#d169e5" />
74
- </View>
75
- );
76
- }
77
-
78
- if (fontState === 'error') {
68
+ // Always render children immediately - fonts will load in background
69
+ // If fonts aren't loaded yet, the app will use system fonts as fallback
70
+ if (fontState === 'error' && __DEV__) {
79
71
  console.warn('Fonts failed to load. Using system fonts instead.');
80
72
  }
81
73
 
82
- // Return children even on error - the app will use system fonts as fallback
74
+ // Render children immediately, even while fonts are loading
75
+ // Fonts will apply when they're ready, otherwise system fonts are used
83
76
  return <>{children}</>;
84
77
  };
85
78
 
@@ -148,35 +141,22 @@ export const setupFonts = async () => {
148
141
  `;
149
142
 
150
143
  style.textContent = fontFaceRules;
151
- // Append to the document head
152
144
  document.head.appendChild(style);
145
+ if (__DEV__) {
153
146
  console.info('All Phudu web fonts have been dynamically loaded');
147
+ }
154
148
  }
155
149
  } else {
156
- // For native platforms, guidance for the package users
157
- console.info('Fonts should be linked in native projects to use Phudu fonts');
158
-
159
150
  // Attempt to load the fonts anyway (this works if the consumer has linked the assets)
160
151
  await Font.loadAsync(phuduFonts);
161
152
  }
162
153
 
163
154
  return true;
164
155
  } catch (error: unknown) {
156
+ if (__DEV__) {
165
157
  const errorMessage = error instanceof Error ? error.message : String(error);
166
158
  console.warn('Error setting up fonts:', errorMessage);
159
+ }
167
160
  return false;
168
161
  }
169
- };
170
-
171
- const styles = StyleSheet.create({
172
- loaderContainer: {
173
- position: 'absolute',
174
- top: 0,
175
- left: 0,
176
- right: 0,
177
- bottom: 0,
178
- justifyContent: 'center',
179
- alignItems: 'center',
180
- backgroundColor: 'transparent',
181
- },
182
- });
162
+ };
@@ -1,4 +1,4 @@
1
- import React, { useCallback, useRef, useState, useEffect, useMemo, forwardRef, useImperativeHandle } from 'react';
1
+ import { useCallback, useRef, useState, useEffect, useMemo, forwardRef, useImperativeHandle, type FC } from 'react';
2
2
  import { View, Text, StyleSheet, Platform, Animated, StatusBar, Keyboard, KeyboardEvent, AppState } from 'react-native';
3
3
  import { SafeAreaProvider, useSafeAreaInsets } from 'react-native-safe-area-context';
4
4
  import { GestureHandlerRootView } from 'react-native-gesture-handler';
@@ -10,7 +10,7 @@ import { Toaster } from '../../lib/sonner';
10
10
  import { QueryClient, QueryClientProvider, focusManager } from '@tanstack/react-query';
11
11
 
12
12
  // Import bottom sheet components directly - no longer a peer dependency
13
- import { BottomSheetModal, BottomSheetBackdrop, type BottomSheetBackdropProps, BottomSheetModalProvider, BottomSheetView, BottomSheetScrollView } from '@gorhom/bottom-sheet';
13
+ import { BottomSheetModal, BottomSheetBackdrop, type BottomSheetBackdropProps, BottomSheetModalProvider, BottomSheetView } from '@gorhom/bottom-sheet';
14
14
  import type { BottomSheetModalMethods as BottomSheetModalRef } from '@gorhom/bottom-sheet/lib/typescript/types';
15
15
 
16
16
  // Initialize fonts automatically
@@ -23,7 +23,7 @@ setupFonts();
23
23
  * 1. As a context provider for authentication and session management across the app
24
24
  * 2. As a UI component for authentication and account management using a bottom sheet
25
25
  */
26
- const OxyProvider: React.FC<OxyProviderProps> = (props) => {
26
+ const OxyProvider: FC<OxyProviderProps> = (props) => {
27
27
  const {
28
28
  oxyServices,
29
29
  children,
@@ -335,18 +335,19 @@ const OxyBottomSheet = forwardRef<BottomSheetController, OxyBottomSheetProps>(({
335
335
  onChange={(index) => { isOpenRef.current = index !== -1; }}
336
336
  onDismiss={() => { isOpenRef.current = false; }}
337
337
  >
338
- <BottomSheetScrollView
339
- style={[styles.contentContainer]}
340
- keyboardShouldPersistTaps="handled"
341
- contentContainerStyle={{ paddingBottom: (insets?.bottom ?? 0) + (appInsets?.bottom ?? 0) }}
342
- >
343
- <View style={styles.centeredContentWrapper}>
338
+ <BottomSheetView style={[styles.contentContainer]}>
339
+ <View
340
+ style={[
341
+ styles.centeredContentWrapper,
342
+ { paddingBottom: (insets?.bottom ?? 0) + (appInsets?.bottom ?? 0) }
343
+ ]}
344
+ >
344
345
  <Animated.View
345
346
  style={[
346
347
  styles.animatedContent,
347
- Platform.OS === 'android' ?
348
- { opacity: 1 } :
349
- { opacity: fadeAnim, transform: [{ translateY: slideAnim }] }
348
+ Platform.OS === 'android'
349
+ ? { opacity: 1 }
350
+ : { opacity: fadeAnim, transform: [{ translateY: slideAnim }] }
350
351
  ]}
351
352
  >
352
353
  {oxyServices ? (
@@ -366,7 +367,7 @@ const OxyBottomSheet = forwardRef<BottomSheetController, OxyBottomSheetProps>(({
366
367
  )}
367
368
  </Animated.View>
368
369
  </View>
369
- </BottomSheetScrollView>
370
+ </BottomSheetView>
370
371
  {showInternalToaster && (
371
372
  <View style={styles.toasterContainer}>
372
373
  <Toaster position="top-center" swipeToDismissDirection="left" />
@@ -13,11 +13,7 @@ import Animated, {
13
13
  useSharedValue,
14
14
  useAnimatedStyle,
15
15
  withTiming,
16
- withSequence,
17
- withDelay,
18
- withSpring,
19
16
  runOnJS,
20
- interpolate,
21
17
  type SharedValue,
22
18
  } from 'react-native-reanimated';
23
19
  import { useThemeColors, createAuthStyles } from '../styles';
@@ -51,6 +47,38 @@ interface StepBasedScreenState {
51
47
  isTransitioning: boolean;
52
48
  }
53
49
 
50
+ // Individual animated progress dot
51
+ const AnimatedProgressDot: React.FC<{
52
+ isActive: boolean;
53
+ colors: any;
54
+ styles: any;
55
+ }> = ({ isActive, colors, styles }) => {
56
+ const width = useSharedValue(isActive ? 12 : 6);
57
+ const backgroundColor = useSharedValue(isActive ? colors.primary : colors.border);
58
+
59
+ useEffect(() => {
60
+ width.value = withTiming(isActive ? 12 : 6, { duration: 300 });
61
+ backgroundColor.value = withTiming(
62
+ isActive ? colors.primary : colors.border,
63
+ { duration: 300 }
64
+ );
65
+ }, [isActive, colors.primary, colors.border, width, backgroundColor]);
66
+
67
+ const animatedStyle = useAnimatedStyle(() => ({
68
+ width: width.value,
69
+ backgroundColor: backgroundColor.value,
70
+ }));
71
+
72
+ return (
73
+ <Animated.View
74
+ style={[
75
+ styles.progressDot,
76
+ animatedStyle,
77
+ ]}
78
+ />
79
+ );
80
+ };
81
+
54
82
  // Progress indicator component
55
83
  const ProgressIndicator: React.FC<{
56
84
  currentStep: number;
@@ -60,14 +88,11 @@ const ProgressIndicator: React.FC<{
60
88
  }> = ({ currentStep, totalSteps, colors, styles }) => (
61
89
  <View style={styles.progressContainer}>
62
90
  {Array.from({ length: totalSteps }, (_, index) => (
63
- <View
91
+ <AnimatedProgressDot
64
92
  key={index}
65
- style={[
66
- styles.progressDot,
67
- currentStep === index
68
- ? { backgroundColor: colors.primary, width: 24 }
69
- : { backgroundColor: colors.border }
70
- ]}
93
+ isActive={currentStep === index}
94
+ colors={colors}
95
+ styles={styles}
71
96
  />
72
97
  ))}
73
98
  </View>
@@ -183,6 +208,20 @@ const StepBasedScreen: React.FC<StepBasedScreenProps> = ({
183
208
  fontWeight: '600' as const,
184
209
  textDecorationLine: 'underline' as const,
185
210
  },
211
+ progressContainer: {
212
+ flexDirection: 'row' as const,
213
+ width: '100%',
214
+ justifyContent: 'center' as const,
215
+ marginTop: 24, // Space for bottom sheet handle (~20px) + small buffer
216
+ marginBottom: 24, // Equal spacing below dots
217
+ },
218
+ progressDot: {
219
+ height: 6,
220
+ width: 6,
221
+ borderRadius: 3,
222
+ marginHorizontal: 3,
223
+ backgroundColor: colors.border,
224
+ },
186
225
  }), [colors, theme]);
187
226
 
188
227
  // State management
@@ -231,13 +270,6 @@ const StepBasedScreen: React.FC<StepBasedScreenProps> = ({
231
270
 
232
271
  setState(prev => ({ ...prev, isTransitioning: true }));
233
272
 
234
- // Scale down current content
235
- scaleAnim.value = withSequence(
236
- withTiming(0.95, { duration: 150 }),
237
- withTiming(0.95, { duration: 50 })
238
- );
239
-
240
- // Define a JS function for runOnJS to avoid inline closures
241
273
  const applyStepChange = (targetStep: number, totalSteps: number) => {
242
274
  setState(prev => ({
243
275
  ...prev,
@@ -245,33 +277,24 @@ const StepBasedScreen: React.FC<StepBasedScreenProps> = ({
245
277
  isTransitioning: false,
246
278
  }));
247
279
  onStepChangeRef.current?.(targetStep, totalSteps);
280
+
281
+ // Prepare next step animation
282
+ fadeAnim.value = 0;
283
+ scaleAnim.value = 0.98;
284
+ slideAnim.value = 0;
285
+
286
+ fadeAnim.value = withTiming(1, { duration: 220 });
287
+ scaleAnim.value = withTiming(1, { duration: 220 });
248
288
  };
249
289
 
250
- fadeAnim.value = withSequence(
251
- withTiming(0, { duration: 200 }),
252
- withTiming(0, { duration: 50 }, (finished) => {
253
- if (finished) {
254
- // Call back to JS thread correctly
255
- runOnJS(applyStepChange)(nextStep, steps.length);
256
-
257
- // Reset animations with proper timing
258
- slideAnim.value = withDelay(16, withTiming(-50, { duration: 0 }));
259
- scaleAnim.value = withDelay(16, withTiming(0.95, { duration: 0 }));
260
-
261
- // Animate in new content
262
- fadeAnim.value = withDelay(16, withTiming(1, { duration: 300 }));
263
- slideAnim.value = withDelay(16, withSpring(0, {
264
- damping: 15,
265
- stiffness: 200,
266
- }));
267
- scaleAnim.value = withDelay(16, withSpring(1, {
268
- damping: 15,
269
- stiffness: 200,
270
- }));
271
- }
272
- })
273
- );
274
- }, [enableAnimations, steps.length]);
290
+ // Animate current step out
291
+ scaleAnim.value = withTiming(0.98, { duration: 180 });
292
+ fadeAnim.value = withTiming(0, { duration: 180 }, (finished) => {
293
+ if (finished) {
294
+ runOnJS(applyStepChange)(nextStep, steps.length);
295
+ }
296
+ });
297
+ }, [enableAnimations, steps.length, fadeAnim, scaleAnim, slideAnim]);
275
298
 
276
299
  // Navigation functions
277
300
  const nextStep = useCallback(() => {