@sanctum-key/react-native-sdk 1.0.6 → 1.0.8

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 (206) hide show
  1. package/README.md +3 -3
  2. package/android/build/.transforms/{f62cb96b2d1f78ca96ab35932dd530dc → c9d62bb333688ab562f51958998d5a48}/transformed/classes/classes_dex/classes.dex +0 -0
  3. package/android/build/generated/source/buildConfig/debug/kyc/{transfergratis → SanctumKey}/com/BuildConfig.java +2 -2
  4. package/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/AndroidManifest.xml +1 -1
  5. package/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/output-metadata.json +1 -1
  6. package/android/build/intermediates/compile_library_classes_jar/debug/bundleLibCompileToJarDebug/classes.jar +0 -0
  7. package/android/build/intermediates/compile_r_class_jar/debug/generateDebugRFile/R.jar +0 -0
  8. package/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties +2 -2
  9. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/kyc/SanctumKey/com/BuildConfig.class +0 -0
  10. package/android/build/intermediates/manifest_merge_blame_file/debug/processDebugManifest/manifest-merger-blame-debug-report.txt +1 -1
  11. package/android/build/intermediates/merged_manifest/debug/processDebugManifest/AndroidManifest.xml +1 -1
  12. package/android/build/intermediates/runtime_library_classes_jar/debug/bundleLibRuntimeToJarDebug/classes.jar +0 -0
  13. package/android/build/intermediates/symbol_list_with_package_name/debug/generateDebugRFile/package-aware-r.txt +1 -1
  14. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab +0 -0
  15. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.values.at +0 -0
  16. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab +0 -0
  17. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream +0 -0
  18. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream.len +0 -0
  19. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab_i +0 -0
  20. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab +0 -0
  21. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream +0 -0
  22. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream.len +0 -0
  23. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i +0 -0
  24. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab +0 -0
  25. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream +0 -0
  26. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream.len +0 -0
  27. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i +0 -0
  28. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab +0 -0
  29. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream +0 -0
  30. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream.len +0 -0
  31. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values.at +0 -0
  32. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab_i +0 -0
  33. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab +0 -0
  34. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.values.at +0 -0
  35. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab +0 -0
  36. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.values.at +0 -0
  37. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab +0 -0
  38. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream +0 -0
  39. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream.len +0 -0
  40. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab_i +0 -0
  41. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab +0 -0
  42. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream +0 -0
  43. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream.len +0 -0
  44. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.values.at +0 -0
  45. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab_i +0 -0
  46. package/android/build/kotlin/compileDebugKotlin/cacheable/last-build.bin +0 -0
  47. package/android/build/kotlin/compileDebugKotlin/local-state/build-history.bin +0 -0
  48. package/android/build/outputs/logs/manifest-merger-debug-report.txt +1 -1
  49. package/android/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin +0 -0
  50. package/android/build/tmp/kotlin-classes/debug/kyc/SanctumKey/com/SanctumKeySdkModule$definition$1$5$1.class +0 -0
  51. package/android/build/tmp/kotlin-classes/debug/kyc/SanctumKey/com/SanctumKeySdkModule$definition$1$5$2.class +0 -0
  52. package/android/build/tmp/kotlin-classes/debug/kyc/{transfergratis/com/TransfergratisSdkModule$definition$lambda$5$$inlined$AsyncFunction$1.class → SanctumKey/com/SanctumKeySdkModule$definition$lambda$5$$inlined$AsyncFunction$1.class} +0 -0
  53. package/android/build/tmp/kotlin-classes/debug/kyc/{transfergratis/com/TransfergratisSdkModule$definition$lambda$5$$inlined$AsyncFunction$2.class → SanctumKey/com/SanctumKeySdkModule$definition$lambda$5$$inlined$AsyncFunction$2.class} +0 -0
  54. package/android/build/tmp/kotlin-classes/debug/kyc/{transfergratis/com/TransfergratisSdkModule$definition$lambda$5$$inlined$AsyncFunction$3.class → SanctumKey/com/SanctumKeySdkModule$definition$lambda$5$$inlined$AsyncFunction$3.class} +0 -0
  55. package/android/build/tmp/kotlin-classes/debug/kyc/{transfergratis/com/TransfergratisSdkModule$definition$lambda$5$$inlined$AsyncFunction$4.class → SanctumKey/com/SanctumKeySdkModule$definition$lambda$5$$inlined$AsyncFunction$4.class} +0 -0
  56. package/android/build/tmp/kotlin-classes/debug/kyc/{transfergratis/com/TransfergratisSdkModule$definition$lambda$5$$inlined$AsyncFunction$5.class → SanctumKey/com/SanctumKeySdkModule$definition$lambda$5$$inlined$AsyncFunction$5.class} +0 -0
  57. package/android/build/tmp/kotlin-classes/debug/kyc/{transfergratis/com/TransfergratisSdkModule$definition$lambda$5$$inlined$AsyncFunction$6.class → SanctumKey/com/SanctumKeySdkModule$definition$lambda$5$$inlined$AsyncFunction$6.class} +0 -0
  58. package/android/build/tmp/kotlin-classes/debug/kyc/{transfergratis/com/TransfergratisSdkModule$definition$lambda$5$$inlined$AsyncFunctionWithPromise$1.class → SanctumKey/com/SanctumKeySdkModule$definition$lambda$5$$inlined$AsyncFunctionWithPromise$1.class} +0 -0
  59. package/android/build/tmp/kotlin-classes/debug/kyc/{transfergratis/com/TransfergratisSdkModule$definition$lambda$5$$inlined$AsyncFunctionWithPromise$2.class → SanctumKey/com/SanctumKeySdkModule$definition$lambda$5$$inlined$AsyncFunctionWithPromise$2.class} +0 -0
  60. package/android/build/tmp/kotlin-classes/debug/kyc/{transfergratis/com/TransfergratisSdkModule$definition$lambda$5$$inlined$AsyncFunctionWithPromise$3.class → SanctumKey/com/SanctumKeySdkModule$definition$lambda$5$$inlined$AsyncFunctionWithPromise$3.class} +0 -0
  61. package/android/build/tmp/kotlin-classes/debug/kyc/{transfergratis/com/TransfergratisSdkModule$definition$lambda$5$$inlined$AsyncFunctionWithPromise$4.class → SanctumKey/com/SanctumKeySdkModule$definition$lambda$5$$inlined$AsyncFunctionWithPromise$4.class} +0 -0
  62. package/android/build/tmp/kotlin-classes/debug/kyc/SanctumKey/com/SanctumKeySdkModule$definition$lambda$5$$inlined$View$1.class +0 -0
  63. package/android/build/tmp/kotlin-classes/debug/kyc/{transfergratis/com/TransfergratisSdkModule$definition$lambda$5$lambda$4$$inlined$Prop$1.class → SanctumKey/com/SanctumKeySdkModule$definition$lambda$5$lambda$4$$inlined$Prop$1.class} +0 -0
  64. package/android/build/tmp/kotlin-classes/debug/kyc/{transfergratis/com/TransfergratisSdkModule$definition$lambda$5$lambda$4$$inlined$Prop$2.class → SanctumKey/com/SanctumKeySdkModule$definition$lambda$5$lambda$4$$inlined$Prop$2.class} +0 -0
  65. package/android/build/tmp/kotlin-classes/debug/kyc/{transfergratis/com/TransfergratisSdkModule.class → SanctumKey/com/SanctumKeySdkModule.class} +0 -0
  66. package/android/build/tmp/kotlin-classes/debug/kyc/{transfergratis/com/TransfergratisSdkView.class → SanctumKey/com/SanctumKeySdkView.class} +0 -0
  67. package/android/build.gradle +2 -2
  68. package/android/src/main/AndroidManifest.xml +1 -1
  69. package/android/src/main/java/kyc/transfergratis/com/TransfergratisSdkModule.kt +6 -6
  70. package/android/src/main/java/kyc/transfergratis/com/TransfergratisSdkView.kt +2 -2
  71. package/build/package.json +9 -7
  72. package/build/src/App.d.ts +2 -2
  73. package/build/src/App.d.ts.map +1 -1
  74. package/build/src/App.js +2 -2
  75. package/build/src/App.js.map +1 -1
  76. package/build/src/{TransfergratisSdk.types.d.ts → SanctumKeySdk.types.d.ts} +3 -3
  77. package/build/src/SanctumKeySdk.types.d.ts.map +1 -0
  78. package/build/src/SanctumKeySdk.types.js +2 -0
  79. package/build/src/SanctumKeySdk.types.js.map +1 -0
  80. package/build/src/{TransfergratisSdkModule.d.ts → SanctumKeySdkModule.d.ts} +4 -4
  81. package/build/src/SanctumKeySdkModule.d.ts.map +1 -0
  82. package/build/src/{TransfergratisSdkModule.js → SanctumKeySdkModule.js} +2 -2
  83. package/build/src/SanctumKeySdkModule.js.map +1 -0
  84. package/build/src/{TransfergratisSdkModule.web.d.ts → SanctumKeySdkModule.web.d.ts} +4 -4
  85. package/build/src/SanctumKeySdkModule.web.d.ts.map +1 -0
  86. package/build/src/{TransfergratisSdkModule.web.js → SanctumKeySdkModule.web.js} +3 -3
  87. package/build/src/SanctumKeySdkModule.web.js.map +1 -0
  88. package/build/src/SanctumKeySdkView.d.ts +4 -0
  89. package/build/src/SanctumKeySdkView.d.ts.map +1 -0
  90. package/build/src/SanctumKeySdkView.js +7 -0
  91. package/build/src/SanctumKeySdkView.js.map +1 -0
  92. package/build/src/SanctumKeySdkView.web.d.ts +4 -0
  93. package/build/src/SanctumKeySdkView.web.d.ts.map +1 -0
  94. package/build/src/{TransfergratisSdkView.web.js → SanctumKeySdkView.web.js} +2 -2
  95. package/build/src/SanctumKeySdkView.web.js.map +1 -0
  96. package/build/src/api/axios.js +2 -2
  97. package/build/src/api/axios.js.map +1 -1
  98. package/build/src/components/EnhancedCameraView.d.ts.map +1 -1
  99. package/build/src/components/EnhancedCameraView.js +107 -330
  100. package/build/src/components/EnhancedCameraView.js.map +1 -1
  101. package/build/src/components/KYCElements/EmailVerificationTemplate.d.ts.map +1 -1
  102. package/build/src/components/KYCElements/EmailVerificationTemplate.js +114 -15
  103. package/build/src/components/KYCElements/EmailVerificationTemplate.js.map +1 -1
  104. package/build/src/components/KYCElements/IDCardCapture.d.ts.map +1 -1
  105. package/build/src/components/KYCElements/IDCardCapture.js +166 -695
  106. package/build/src/components/KYCElements/IDCardCapture.js.map +1 -1
  107. package/build/src/components/KYCElements/PhoneVerificationTemplate.d.ts.map +1 -1
  108. package/build/src/components/KYCElements/PhoneVerificationTemplate.js +282 -40
  109. package/build/src/components/KYCElements/PhoneVerificationTemplate.js.map +1 -1
  110. package/build/src/components/KYCElements/SelfieCapture.d.ts +1 -1
  111. package/build/src/components/KYCElements/SelfieCapture.d.ts.map +1 -1
  112. package/build/src/components/KYCElements/SelfieCapture.js +130 -192
  113. package/build/src/components/KYCElements/SelfieCapture.js.map +1 -1
  114. package/build/src/components/KYCElements/SelfieCaptureTemplate.d.ts.map +1 -1
  115. package/build/src/components/KYCElements/SelfieCaptureTemplate.js +131 -433
  116. package/build/src/components/KYCElements/SelfieCaptureTemplate.js.map +1 -1
  117. package/build/src/components/NativeCameraView.js +1 -1
  118. package/build/src/components/NativeCameraView.js.map +1 -1
  119. package/build/src/components/OverLay/IdCard.d.ts +3 -2
  120. package/build/src/components/OverLay/IdCard.d.ts.map +1 -1
  121. package/build/src/components/OverLay/IdCard.js +149 -141
  122. package/build/src/components/OverLay/IdCard.js.map +1 -1
  123. package/build/src/components/OverLay/SelfieOverlay.d.ts +2 -1
  124. package/build/src/components/OverLay/SelfieOverlay.d.ts.map +1 -1
  125. package/build/src/components/OverLay/SelfieOverlay.js +37 -95
  126. package/build/src/components/OverLay/SelfieOverlay.js.map +1 -1
  127. package/build/src/components/OverLay/type.d.ts +1 -0
  128. package/build/src/components/OverLay/type.d.ts.map +1 -1
  129. package/build/src/components/OverLay/type.js.map +1 -1
  130. package/build/src/components/Svgs/scanningLine.d.ts +2 -1
  131. package/build/src/components/Svgs/scanningLine.d.ts.map +1 -1
  132. package/build/src/components/Svgs/scanningLine.js +55 -51
  133. package/build/src/components/Svgs/scanningLine.js.map +1 -1
  134. package/build/src/config/KYCConfig.js +1 -1
  135. package/build/src/config/KYCConfig.js.map +1 -1
  136. package/build/src/config/allowedDomains.js +6 -6
  137. package/build/src/config/allowedDomains.js.map +1 -1
  138. package/build/src/hooks/useTemplateKYCFlow.d.ts.map +1 -1
  139. package/build/src/hooks/useTemplateKYCFlow.js +37 -38
  140. package/build/src/hooks/useTemplateKYCFlow.js.map +1 -1
  141. package/build/src/index.d.ts +3 -3
  142. package/build/src/index.d.ts.map +1 -1
  143. package/build/src/index.js +3 -3
  144. package/build/src/index.js.map +1 -1
  145. package/build/src/modules/api/CardAuthentification.d.ts +0 -5
  146. package/build/src/modules/api/CardAuthentification.d.ts.map +1 -1
  147. package/build/src/modules/api/CardAuthentification.js +114 -116
  148. package/build/src/modules/api/CardAuthentification.js.map +1 -1
  149. package/build/src/modules/api/KYCService.d.ts +12 -1
  150. package/build/src/modules/api/KYCService.d.ts.map +1 -1
  151. package/build/src/modules/api/KYCService.js +102 -38
  152. package/build/src/modules/api/KYCService.js.map +1 -1
  153. package/build/src/modules/camera/NativeCameraModule.js +17 -17
  154. package/build/src/modules/camera/NativeCameraModule.js.map +1 -1
  155. package/expo-module.config.json +2 -2
  156. package/ios/TransfergratisSdk.podspec +2 -2
  157. package/ios/TransfergratisSdkModule.swift +12 -12
  158. package/package.json +9 -7
  159. package/src/App.tsx +2 -2
  160. package/src/{TransfergratisSdk.types.ts → SanctumKeySdk.types.ts} +2 -2
  161. package/src/{TransfergratisSdkModule.ts → SanctumKeySdkModule.ts} +3 -3
  162. package/src/{TransfergratisSdkModule.web.ts → SanctumKeySdkModule.web.ts} +3 -3
  163. package/src/SanctumKeySdkView.tsx +11 -0
  164. package/src/{TransfergratisSdkView.web.tsx → SanctumKeySdkView.web.tsx} +2 -2
  165. package/src/api/axios.ts +2 -2
  166. package/src/components/EnhancedCameraView.tsx +131 -385
  167. package/src/components/KYCElements/EmailVerificationTemplate.tsx +141 -26
  168. package/src/components/KYCElements/IDCardCapture.tsx +228 -868
  169. package/src/components/KYCElements/PhoneVerificationTemplate.tsx +342 -60
  170. package/src/components/KYCElements/SelfieCapture.tsx +184 -213
  171. package/src/components/KYCElements/SelfieCaptureTemplate.tsx +330 -662
  172. package/src/components/NativeCameraView.tsx +1 -1
  173. package/src/components/OverLay/IdCard.tsx +218 -217
  174. package/src/components/OverLay/SelfieOverlay.tsx +56 -134
  175. package/src/components/OverLay/type.ts +1 -0
  176. package/src/components/Svgs/scanningLine.tsx +71 -72
  177. package/src/config/KYCConfig.ts +1 -1
  178. package/src/config/allowedDomains.ts +6 -6
  179. package/src/hooks/useTemplateKYCFlow.tsx +45 -39
  180. package/src/i18n/README.md +1 -1
  181. package/src/index.ts +3 -3
  182. package/src/modules/api/CardAuthentification.ts +202 -200
  183. package/src/modules/api/KYCService.ts +169 -53
  184. package/src/modules/camera/NativeCameraModule.ts +17 -17
  185. package/android/build/tmp/kotlin-classes/debug/kyc/transfergratis/com/TransfergratisSdkModule$definition$1$5$1.class +0 -0
  186. package/android/build/tmp/kotlin-classes/debug/kyc/transfergratis/com/TransfergratisSdkModule$definition$1$5$2.class +0 -0
  187. package/android/build/tmp/kotlin-classes/debug/kyc/transfergratis/com/TransfergratisSdkModule$definition$lambda$5$$inlined$View$1.class +0 -0
  188. package/build/src/TransfergratisSdk.types.d.ts.map +0 -1
  189. package/build/src/TransfergratisSdk.types.js +0 -2
  190. package/build/src/TransfergratisSdk.types.js.map +0 -1
  191. package/build/src/TransfergratisSdkModule.d.ts.map +0 -1
  192. package/build/src/TransfergratisSdkModule.js.map +0 -1
  193. package/build/src/TransfergratisSdkModule.web.d.ts.map +0 -1
  194. package/build/src/TransfergratisSdkModule.web.js.map +0 -1
  195. package/build/src/TransfergratisSdkView.d.ts +0 -4
  196. package/build/src/TransfergratisSdkView.d.ts.map +0 -1
  197. package/build/src/TransfergratisSdkView.js +0 -7
  198. package/build/src/TransfergratisSdkView.js.map +0 -1
  199. package/build/src/TransfergratisSdkView.web.d.ts +0 -4
  200. package/build/src/TransfergratisSdkView.web.d.ts.map +0 -1
  201. package/build/src/TransfergratisSdkView.web.js.map +0 -1
  202. package/src/TransfergratisSdkView.tsx +0 -11
  203. /package/android/build/.transforms/{532c0e65d82f446633d0a7dab2772198 → ab90740579f5bd05b27b4343ada2d1c9}/results.bin +0 -0
  204. /package/android/build/.transforms/{532c0e65d82f446633d0a7dab2772198 → ab90740579f5bd05b27b4343ada2d1c9}/transformed/classes/classes_dex/classes.dex +0 -0
  205. /package/android/build/.transforms/{f62cb96b2d1f78ca96ab35932dd530dc → c9d62bb333688ab562f51958998d5a48}/results.bin +0 -0
  206. /package/android/build/{intermediates/javac/debug/compileDebugJavaWithJavac/classes/kyc/transfergratis/com/BuildConfig.class → tmp/compileDebugJavaWithJavac/compileTransaction/stash-dir/BuildConfig.class.uniqueId0} +0 -0
@@ -1,5 +1,5 @@
1
- import React, { useState } from 'react';
2
- import { View, Text, StyleSheet, TextInput, TouchableOpacity, Alert } from 'react-native';
1
+ import React, { useState, useRef, useEffect } from 'react';
2
+ import { View, Text, StyleSheet, TextInput, TouchableOpacity, Alert, Pressable } from 'react-native';
3
3
  import { TemplateComponent, LocalizedText } from '../../types/KYC.types';
4
4
  import { useTemplateKYCFlowContext } from '../../hooks/useTemplateKYCFlow';
5
5
  import { useI18n } from '../../hooks/useI18n';
@@ -15,10 +15,10 @@ interface EmailVerificationTemplateProps {
15
15
  }
16
16
 
17
17
  type VerificationStep = 'email' | 'otp';
18
+ const CODE_LENGTH = 6;
18
19
 
19
20
  /** RFC-style email validation: local@domain.tld */
20
21
  const EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
21
-
22
22
  const isValidEmail = (value: string): boolean => EMAIL_REGEX.test((value || '').trim());
23
23
 
24
24
  export const EmailVerificationTemplate: React.FC<EmailVerificationTemplateProps> = ({
@@ -31,7 +31,6 @@ export const EmailVerificationTemplate: React.FC<EmailVerificationTemplateProps>
31
31
  const { t } = useI18n();
32
32
 
33
33
  const auth = apiKey ? { apiKey } : (state.session.token ? { token: state.session.token } : undefined);
34
- // const config = component.config as EmailVerificationConfig; // Keep for future use
35
34
 
36
35
  // State
37
36
  const [step, setStep] = useState<VerificationStep>('email');
@@ -39,6 +38,11 @@ export const EmailVerificationTemplate: React.FC<EmailVerificationTemplateProps>
39
38
  const [otp, setOtp] = useState('');
40
39
  const [localError, setLocalError] = useState<string | null>(null);
41
40
  const [isSimulating, setIsSimulating] = useState(false);
41
+
42
+ // 🚨 NEW: Track actual focus state for visual feedback
43
+ const [isInputFocused, setIsInputFocused] = useState(false);
44
+
45
+ const inputRef = useRef<TextInput>(null);
42
46
 
43
47
  const title = getLocalizedText(component.labels as LocalizedText);
44
48
  const instructions = getLocalizedText(component.instructions as LocalizedText);
@@ -48,6 +52,29 @@ export const EmailVerificationTemplate: React.FC<EmailVerificationTemplateProps>
48
52
  const sendButtonText = t('common.sendCode') || 'Send Verification Code';
49
53
  const buttonText = step === 'email' ? sendButtonText : verifyButtonText;
50
54
 
55
+ // --- AUTO SUBMIT LOGIC ---
56
+ useEffect(() => {
57
+ if (otp.length === CODE_LENGTH && step === 'otp' && !isSimulating) {
58
+ handleVerifyCode();
59
+ }
60
+ }, [otp]);
61
+
62
+ // --- AUTO FOCUS LOGIC ---
63
+ useEffect(() => {
64
+ let focusTimer: ReturnType<typeof setTimeout>;
65
+
66
+ // Only attempt focus when we are on the OTP step AND the loading state is completely finished
67
+ if (step === 'otp' && !isSimulating) {
68
+ focusTimer = setTimeout(() => {
69
+ inputRef.current?.focus();
70
+ }, 100);
71
+ }
72
+
73
+ return () => {
74
+ if (focusTimer) clearTimeout(focusTimer);
75
+ };
76
+ }, [step, isSimulating]);
77
+
51
78
  const handleSendCode = async () => {
52
79
  const trimmed = email.trim();
53
80
  if (!trimmed || !isValidEmail(trimmed)) {
@@ -61,6 +88,7 @@ export const EmailVerificationTemplate: React.FC<EmailVerificationTemplateProps>
61
88
  try {
62
89
  await kycService.sendEmailVerificationCode(trimmed, auth);
63
90
  setStep('otp');
91
+ // Note: Removed the buggy setTimeout from here. The useEffect handles it now!
64
92
  } catch (err: any) {
65
93
  const msg = errorMessage(err) ?? err?.message ?? (t('errors.sendCodeFailed') || 'Failed to send verification code');
66
94
  setLocalError(typeof msg === 'string' ? msg : JSON.stringify(msg));
@@ -70,7 +98,7 @@ export const EmailVerificationTemplate: React.FC<EmailVerificationTemplateProps>
70
98
  };
71
99
 
72
100
  const handleVerifyCode = async () => {
73
- if (!otp || otp.length < 4) {
101
+ if (!otp || otp.length < CODE_LENGTH) {
74
102
  setLocalError(t('errors.invalidCode') || 'Please enter the 6-digit code');
75
103
  return;
76
104
  }
@@ -86,6 +114,8 @@ export const EmailVerificationTemplate: React.FC<EmailVerificationTemplateProps>
86
114
  } catch (err: any) {
87
115
  const msg = errorMessage(err) ?? err?.message ?? (t('errors.wrongCode') || 'Invalid verification code');
88
116
  setLocalError(typeof msg === 'string' ? msg : JSON.stringify(msg));
117
+ setOtp('');
118
+ inputRef.current?.focus(); // Refocus on error
89
119
  } finally {
90
120
  setIsSimulating(false);
91
121
  }
@@ -97,7 +127,9 @@ export const EmailVerificationTemplate: React.FC<EmailVerificationTemplateProps>
97
127
  };
98
128
 
99
129
  const onChangeOtp = (text: string) => {
100
- setOtp(text);
130
+ // Only allow numbers
131
+ const cleaned = text.replace(/[^0-9]/g, '');
132
+ setOtp(cleaned);
101
133
  if (localError) setLocalError(null);
102
134
  };
103
135
 
@@ -107,6 +139,35 @@ export const EmailVerificationTemplate: React.FC<EmailVerificationTemplateProps>
107
139
  setLocalError(null);
108
140
  };
109
141
 
142
+ const renderOtpBoxes = () => {
143
+ const boxes = new Array(CODE_LENGTH).fill(0);
144
+ return (
145
+ <Pressable style={styles.otpBoxesContainer} onPress={() => inputRef.current?.focus()}>
146
+ {boxes.map((_, index) => {
147
+ const digit = otp[index] || '';
148
+ const isFilled = index < otp.length;
149
+
150
+ // 🚨 NEW: Only highlight if the input is ACTUALLY focused.
151
+ const isActiveIndex = index === otp.length || (index === CODE_LENGTH - 1 && otp.length === CODE_LENGTH);
152
+ const isCurrent = isInputFocused && isActiveIndex;
153
+
154
+ return (
155
+ <View
156
+ key={index}
157
+ style={[
158
+ styles.otpBox,
159
+ isFilled && styles.otpBoxFilled,
160
+ isCurrent && styles.otpBoxActive // Active overrides filled
161
+ ]}
162
+ >
163
+ <Text style={styles.otpBoxText}>{digit}</Text>
164
+ </View>
165
+ );
166
+ })}
167
+ </Pressable>
168
+ );
169
+ };
170
+
110
171
  return (
111
172
  <View style={styles.container}>
112
173
  <Text style={styles.title}>{title}</Text>
@@ -132,16 +193,27 @@ export const EmailVerificationTemplate: React.FC<EmailVerificationTemplateProps>
132
193
  ) : (
133
194
  <View style={styles.inputContainer}>
134
195
  <Text style={styles.label}>{t('common.verificationCode') || 'Verification Code'}</Text>
135
- <TextInput
136
- style={styles.input}
137
- placeholder="123456"
138
- value={otp}
139
- onChangeText={onChangeOtp}
140
- keyboardType="number-pad"
141
- maxLength={6}
142
- editable={!isSimulating}
143
- />
144
- <TouchableOpacity onPress={handleBackToEmail} style={styles.changeEmailLink}>
196
+
197
+ <View style={styles.otpWrapper}>
198
+ {renderOtpBoxes()}
199
+
200
+ <TextInput
201
+ ref={inputRef}
202
+ style={styles.hiddenInput}
203
+ value={otp}
204
+ onChangeText={onChangeOtp}
205
+ keyboardType="number-pad"
206
+ maxLength={CODE_LENGTH}
207
+ editable={!isSimulating}
208
+ textContentType="oneTimeCode"
209
+ caretHidden={true}
210
+ // 🚨 NEW: Track focus state
211
+ onFocus={() => setIsInputFocused(true)}
212
+ onBlur={() => setIsInputFocused(false)}
213
+ />
214
+ </View>
215
+
216
+ <TouchableOpacity onPress={handleBackToEmail} style={styles.changeEmailLink} disabled={isSimulating}>
145
217
  <Text style={styles.changeEmailText}>{t('common.changeEmail') || 'Change email'}</Text>
146
218
  </TouchableOpacity>
147
219
  </View>
@@ -154,11 +226,10 @@ export const EmailVerificationTemplate: React.FC<EmailVerificationTemplateProps>
154
226
  <Button
155
227
  title={isSimulating ? (t('common.processing') || 'Processing...') : buttonText}
156
228
  onPress={step === 'email' ? handleSendCode : handleVerifyCode}
157
-
158
-
229
+ style={styles.button}
159
230
  disabled={
160
231
  isSimulating ||
161
- (step === 'email' ? !email : !otp)
232
+ (step === 'email' ? !email : otp.length < CODE_LENGTH)
162
233
  }
163
234
  />
164
235
 
@@ -174,6 +245,8 @@ export const EmailVerificationTemplate: React.FC<EmailVerificationTemplateProps>
174
245
  t('common.codeResent') || 'Code Resent',
175
246
  t('common.codeResentMessage', { email }) || 'Code resent to ' + email
176
247
  );
248
+ // Refocus after resending
249
+ inputRef.current?.focus();
177
250
  } catch (err: any) {
178
251
  const msg = errorMessage(err) ?? err?.message ?? (t('errors.sendCodeFailed') || 'Failed to send code');
179
252
  setLocalError(typeof msg === 'string' ? msg : JSON.stringify(msg));
@@ -219,9 +292,7 @@ const styles = StyleSheet.create({
219
292
  lineHeight: 24,
220
293
  textAlign: 'center',
221
294
  },
222
- contentContainer: {
223
- // width: '100%',
224
- },
295
+ contentContainer: {},
225
296
  inputContainer: {
226
297
  marginBottom: 24,
227
298
  },
@@ -241,6 +312,50 @@ const styles = StyleSheet.create({
241
312
  backgroundColor: '#f8f9fa',
242
313
  color: '#333',
243
314
  },
315
+ otpWrapper: {
316
+ position: 'relative',
317
+ width: '100%',
318
+ height: 60,
319
+ },
320
+ otpBoxesContainer: {
321
+ flexDirection: 'row',
322
+ justifyContent: 'space-between',
323
+ alignItems: 'center',
324
+ width: '100%',
325
+ height: '100%',
326
+ },
327
+ otpBox: {
328
+ width: '14%',
329
+ aspectRatio: 1, // keeps it perfectly square
330
+ borderWidth: 1,
331
+ borderColor: '#e0e0e0',
332
+ borderRadius: 12,
333
+ backgroundColor: '#f8f9fa',
334
+ justifyContent: 'center',
335
+ alignItems: 'center',
336
+ },
337
+ otpBoxFilled: {
338
+ borderColor: '#9ca3af',
339
+ backgroundColor: '#ffffff',
340
+ },
341
+ otpBoxActive: {
342
+ borderColor: '#2DBD60',
343
+ borderWidth: 2,
344
+ backgroundColor: '#ffffff',
345
+ },
346
+ otpBoxText: {
347
+ fontSize: 24,
348
+ fontWeight: '700',
349
+ color: '#1a1a1a',
350
+ },
351
+ hiddenInput: {
352
+ position: 'absolute',
353
+ top: 0,
354
+ left: 0,
355
+ width: '100%',
356
+ height: '100%',
357
+ opacity: 0, // completely invisible but handles native keyboard interactions perfectly
358
+ },
244
359
  errorText: {
245
360
  color: '#dc2626',
246
361
  marginBottom: 16,
@@ -254,11 +369,11 @@ const styles = StyleSheet.create({
254
369
  button: {
255
370
  height: 50,
256
371
  borderRadius: 12,
257
- width: "100%"
372
+ width: "100%",
258
373
  },
259
374
  changeEmailLink: {
260
375
  alignSelf: 'flex-end',
261
- marginTop: 8,
376
+ marginTop: 12,
262
377
  },
263
378
  changeEmailText: {
264
379
  color: '#2DBD60',
@@ -268,11 +383,11 @@ const styles = StyleSheet.create({
268
383
  resendButton: {
269
384
  marginTop: 16,
270
385
  alignItems: 'center',
271
- width: "100%"
386
+ width: "100%",
272
387
  },
273
388
  resendText: {
274
389
  color: '#666',
275
390
  fontSize: 14,
276
391
  textDecorationLine: 'underline',
277
392
  },
278
- });
393
+ });