@smileid/usesmileid 12.0.0-beta01 → 12.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 (403) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/README.md +701 -89
  3. package/dist/camera/camera_defaults.d.ts +14 -9
  4. package/dist/camera/camera_defaults.d.ts.map +1 -1
  5. package/dist/camera/camera_defaults.js +11 -9
  6. package/dist/camera/camera_defaults.js.map +1 -1
  7. package/dist/camera/orientation_degrees.d.ts +5 -6
  8. package/dist/camera/orientation_degrees.d.ts.map +1 -1
  9. package/dist/camera/orientation_degrees.js +5 -6
  10. package/dist/camera/orientation_degrees.js.map +1 -1
  11. package/dist/core/models/document_capture_mode.d.ts +8 -0
  12. package/dist/core/models/document_capture_mode.d.ts.map +1 -1
  13. package/dist/core/models/document_capture_mode.js +24 -0
  14. package/dist/core/models/document_capture_mode.js.map +1 -1
  15. package/dist/core/models/document_type.d.ts +2 -2
  16. package/dist/core/models/document_type.d.ts.map +1 -1
  17. package/dist/core/models/document_type.js +6 -4
  18. package/dist/core/models/document_type.js.map +1 -1
  19. package/dist/core/models/result.d.ts +9 -8
  20. package/dist/core/models/result.d.ts.map +1 -1
  21. package/dist/core/models/result.js +5 -6
  22. package/dist/core/models/result.js.map +1 -1
  23. package/dist/data/api/interceptors/smile_auth_interceptor.js +1 -1
  24. package/dist/data/api/interceptors/smile_auth_interceptor.js.map +1 -1
  25. package/dist/data/api/interceptors/smile_integrity_interceptor.d.ts +11 -0
  26. package/dist/data/api/interceptors/smile_integrity_interceptor.d.ts.map +1 -1
  27. package/dist/data/api/interceptors/smile_integrity_interceptor.js +13 -0
  28. package/dist/data/api/interceptors/smile_integrity_interceptor.js.map +1 -1
  29. package/dist/data/api/interceptors/smile_request_mac_interceptor.d.ts +8 -0
  30. package/dist/data/api/interceptors/smile_request_mac_interceptor.d.ts.map +1 -1
  31. package/dist/data/api/interceptors/smile_request_mac_interceptor.js +11 -0
  32. package/dist/data/api/interceptors/smile_request_mac_interceptor.js.map +1 -1
  33. package/dist/data/compression/compressible_asset.d.ts +41 -0
  34. package/dist/data/compression/compressible_asset.d.ts.map +1 -0
  35. package/dist/data/compression/compressible_asset.js +34 -0
  36. package/dist/data/compression/compressible_asset.js.map +1 -0
  37. package/dist/data/compression/payload_compression_config.d.ts +36 -0
  38. package/dist/data/compression/payload_compression_config.d.ts.map +1 -0
  39. package/dist/data/compression/payload_compression_config.js +52 -0
  40. package/dist/data/compression/payload_compression_config.js.map +1 -0
  41. package/dist/data/compression/payload_compression_runner.d.ts +29 -0
  42. package/dist/data/compression/payload_compression_runner.d.ts.map +1 -0
  43. package/dist/data/compression/payload_compression_runner.js +55 -0
  44. package/dist/data/compression/payload_compression_runner.js.map +1 -0
  45. package/dist/data/compression/payload_compressor.d.ts +40 -0
  46. package/dist/data/compression/payload_compressor.d.ts.map +1 -0
  47. package/dist/data/compression/payload_compressor.js +126 -0
  48. package/dist/data/compression/payload_compressor.js.map +1 -0
  49. package/dist/data/compression/uri_compressible_asset.d.ts +23 -0
  50. package/dist/data/compression/uri_compressible_asset.d.ts.map +1 -0
  51. package/dist/data/compression/uri_compressible_asset.js +77 -0
  52. package/dist/data/compression/uri_compressible_asset.js.map +1 -0
  53. package/dist/data/dsl/builder/cache_config_builder.d.ts +2 -1
  54. package/dist/data/dsl/builder/cache_config_builder.d.ts.map +1 -1
  55. package/dist/data/dsl/builder/cache_config_builder.js +2 -1
  56. package/dist/data/dsl/builder/cache_config_builder.js.map +1 -1
  57. package/dist/data/dsl/builder/config_builder.d.ts +40 -14
  58. package/dist/data/dsl/builder/config_builder.d.ts.map +1 -1
  59. package/dist/data/dsl/builder/config_builder.js +40 -14
  60. package/dist/data/dsl/builder/config_builder.js.map +1 -1
  61. package/dist/data/dsl/builder/interceptor_config_builder.d.ts +9 -7
  62. package/dist/data/dsl/builder/interceptor_config_builder.d.ts.map +1 -1
  63. package/dist/data/dsl/builder/interceptor_config_builder.js +9 -7
  64. package/dist/data/dsl/builder/interceptor_config_builder.js.map +1 -1
  65. package/dist/data/dsl/builder/retry_config_builder.d.ts +16 -1
  66. package/dist/data/dsl/builder/retry_config_builder.d.ts.map +1 -1
  67. package/dist/data/dsl/builder/retry_config_builder.js +16 -1
  68. package/dist/data/dsl/builder/retry_config_builder.js.map +1 -1
  69. package/dist/data/dsl/builder/timeout_config_builder.d.ts +4 -0
  70. package/dist/data/dsl/builder/timeout_config_builder.d.ts.map +1 -1
  71. package/dist/data/dsl/builder/timeout_config_builder.js +4 -0
  72. package/dist/data/dsl/builder/timeout_config_builder.js.map +1 -1
  73. package/dist/data/dsl/use_smile_id_network_builder.d.ts +17 -0
  74. package/dist/data/dsl/use_smile_id_network_builder.d.ts.map +1 -1
  75. package/dist/data/dsl/use_smile_id_network_builder.js +17 -0
  76. package/dist/data/dsl/use_smile_id_network_builder.js.map +1 -1
  77. package/dist/data/factory/networking_factory.d.ts.map +1 -1
  78. package/dist/data/factory/networking_factory.js +11 -1
  79. package/dist/data/factory/networking_factory.js.map +1 -1
  80. package/dist/data/repository/use_smile_id_repository_impl.d.ts +6 -0
  81. package/dist/data/repository/use_smile_id_repository_impl.d.ts.map +1 -1
  82. package/dist/data/repository/use_smile_id_repository_impl.js +82 -8
  83. package/dist/data/repository/use_smile_id_repository_impl.js.map +1 -1
  84. package/dist/data/security/request_canonicalizer.d.ts.map +1 -1
  85. package/dist/data/security/request_canonicalizer.js +14 -2
  86. package/dist/data/security/request_canonicalizer.js.map +1 -1
  87. package/dist/data/security/security_policy.d.ts +43 -0
  88. package/dist/data/security/security_policy.d.ts.map +1 -0
  89. package/dist/data/security/security_policy.js +61 -0
  90. package/dist/data/security/security_policy.js.map +1 -0
  91. package/dist/data/util/retry_util.d.ts +1 -1
  92. package/dist/data/util/retry_util.d.ts.map +1 -1
  93. package/dist/data/util/retry_util.js +2 -1
  94. package/dist/data/util/retry_util.js.map +1 -1
  95. package/dist/data/util/use_smile_id_token_decoder.d.ts +22 -0
  96. package/dist/data/util/use_smile_id_token_decoder.d.ts.map +1 -1
  97. package/dist/data/util/use_smile_id_token_decoder.js +58 -24
  98. package/dist/data/util/use_smile_id_token_decoder.js.map +1 -1
  99. package/dist/l10n/strings_en.d.ts +2 -1
  100. package/dist/l10n/strings_en.d.ts.map +1 -1
  101. package/dist/l10n/strings_en.js +2 -1
  102. package/dist/l10n/strings_en.js.map +1 -1
  103. package/dist/l10n/use_smile_id_localizations.d.ts +1 -0
  104. package/dist/l10n/use_smile_id_localizations.d.ts.map +1 -1
  105. package/dist/l10n/use_smile_id_localizations.js +3 -0
  106. package/dist/l10n/use_smile_id_localizations.js.map +1 -1
  107. package/dist/metadata/builder_configuration.d.ts +39 -0
  108. package/dist/metadata/builder_configuration.d.ts.map +1 -0
  109. package/dist/metadata/builder_configuration.js +34 -0
  110. package/dist/metadata/builder_configuration.js.map +1 -0
  111. package/dist/metadata/captured_image_properties.d.ts +11 -0
  112. package/dist/metadata/captured_image_properties.d.ts.map +1 -0
  113. package/dist/metadata/captured_image_properties.js +11 -0
  114. package/dist/metadata/captured_image_properties.js.map +1 -0
  115. package/dist/metadata/device_orientation_collector.d.ts +17 -0
  116. package/dist/metadata/device_orientation_collector.d.ts.map +1 -0
  117. package/dist/metadata/device_orientation_collector.js +66 -0
  118. package/dist/metadata/device_orientation_collector.js.map +1 -0
  119. package/dist/metadata/geolocation.d.ts +20 -0
  120. package/dist/metadata/geolocation.d.ts.map +1 -0
  121. package/dist/metadata/geolocation.js +40 -0
  122. package/dist/metadata/geolocation.js.map +1 -0
  123. package/dist/metadata/metadata_configuration_mappers.d.ts +48 -0
  124. package/dist/metadata/metadata_configuration_mappers.d.ts.map +1 -0
  125. package/dist/metadata/metadata_configuration_mappers.js +171 -0
  126. package/dist/metadata/metadata_configuration_mappers.js.map +1 -0
  127. package/dist/metadata/model_configuration.d.ts +41 -0
  128. package/dist/metadata/model_configuration.d.ts.map +1 -0
  129. package/dist/metadata/model_configuration.js +44 -0
  130. package/dist/metadata/model_configuration.js.map +1 -0
  131. package/dist/metadata/optional_native_modules.d.ts +79 -3
  132. package/dist/metadata/optional_native_modules.d.ts.map +1 -1
  133. package/dist/metadata/optional_native_modules.js +108 -3
  134. package/dist/metadata/optional_native_modules.js.map +1 -1
  135. package/dist/metadata/use_smile_id_metadata.d.ts +45 -7
  136. package/dist/metadata/use_smile_id_metadata.d.ts.map +1 -1
  137. package/dist/metadata/use_smile_id_metadata.js +85 -13
  138. package/dist/metadata/use_smile_id_metadata.js.map +1 -1
  139. package/dist/metadata/use_smile_id_metadata_factory.d.ts +37 -0
  140. package/dist/metadata/use_smile_id_metadata_factory.d.ts.map +1 -1
  141. package/dist/metadata/use_smile_id_metadata_factory.js +184 -12
  142. package/dist/metadata/use_smile_id_metadata_factory.js.map +1 -1
  143. package/dist/presentation/assets/svg/document_shimmer_strings.d.ts +14 -0
  144. package/dist/presentation/assets/svg/document_shimmer_strings.d.ts.map +1 -0
  145. package/dist/presentation/assets/svg/document_shimmer_strings.js +14 -0
  146. package/dist/presentation/assets/svg/document_shimmer_strings.js.map +1 -0
  147. package/dist/presentation/assets/svg/instruction_svg_strings.d.ts +12 -4
  148. package/dist/presentation/assets/svg/instruction_svg_strings.d.ts.map +1 -1
  149. package/dist/presentation/assets/svg/instruction_svg_strings.js +19 -8
  150. package/dist/presentation/assets/svg/instruction_svg_strings.js.map +1 -1
  151. package/dist/presentation/components/helpers/enhanced_smart_selfie_animation_frames.d.ts +0 -5
  152. package/dist/presentation/components/helpers/enhanced_smart_selfie_animation_frames.d.ts.map +1 -1
  153. package/dist/presentation/components/helpers/enhanced_smart_selfie_animation_frames.js +0 -5
  154. package/dist/presentation/components/helpers/enhanced_smart_selfie_animation_frames.js.map +1 -1
  155. package/dist/presentation/components/icons/index.d.ts +24 -8
  156. package/dist/presentation/components/icons/index.d.ts.map +1 -1
  157. package/dist/presentation/components/icons/index.js +31 -11
  158. package/dist/presentation/components/icons/index.js.map +1 -1
  159. package/dist/presentation/components/use_smile_id_attribution.d.ts +1 -1
  160. package/dist/presentation/components/use_smile_id_button.d.ts +2 -2
  161. package/dist/presentation/components/use_smile_id_button.js +4 -4
  162. package/dist/presentation/components/use_smile_id_button.js.map +1 -1
  163. package/dist/presentation/components/use_smile_id_capture_content.d.ts +13 -0
  164. package/dist/presentation/components/use_smile_id_capture_content.d.ts.map +1 -1
  165. package/dist/presentation/components/use_smile_id_capture_content.js +15 -9
  166. package/dist/presentation/components/use_smile_id_capture_content.js.map +1 -1
  167. package/dist/presentation/components/use_smile_id_captured_document_image.d.ts +2 -3
  168. package/dist/presentation/components/use_smile_id_captured_document_image.d.ts.map +1 -1
  169. package/dist/presentation/components/use_smile_id_captured_document_image.js +1 -3
  170. package/dist/presentation/components/use_smile_id_captured_document_image.js.map +1 -1
  171. package/dist/presentation/components/use_smile_id_document_capture_controls.d.ts +12 -6
  172. package/dist/presentation/components/use_smile_id_document_capture_controls.d.ts.map +1 -1
  173. package/dist/presentation/components/use_smile_id_document_capture_controls.js +59 -16
  174. package/dist/presentation/components/use_smile_id_document_capture_controls.js.map +1 -1
  175. package/dist/presentation/components/use_smile_id_document_overlay.d.ts +22 -5
  176. package/dist/presentation/components/use_smile_id_document_overlay.d.ts.map +1 -1
  177. package/dist/presentation/components/use_smile_id_document_overlay.js +80 -40
  178. package/dist/presentation/components/use_smile_id_document_overlay.js.map +1 -1
  179. package/dist/presentation/components/use_smile_id_document_shimmer.d.ts +15 -0
  180. package/dist/presentation/components/use_smile_id_document_shimmer.d.ts.map +1 -0
  181. package/dist/presentation/components/use_smile_id_document_shimmer.js +23 -0
  182. package/dist/presentation/components/use_smile_id_document_shimmer.js.map +1 -0
  183. package/dist/presentation/components/use_smile_id_enhanced_smart_selfie_clip.d.ts.map +1 -1
  184. package/dist/presentation/components/use_smile_id_enhanced_smart_selfie_clip.js +1 -3
  185. package/dist/presentation/components/use_smile_id_enhanced_smart_selfie_clip.js.map +1 -1
  186. package/dist/presentation/components/use_smile_id_guideline_thumbnail.d.ts.map +1 -1
  187. package/dist/presentation/components/use_smile_id_guideline_thumbnail.js +84 -1
  188. package/dist/presentation/components/use_smile_id_guideline_thumbnail.js.map +1 -1
  189. package/dist/presentation/components/use_smile_id_instructions_hero.d.ts +3 -1
  190. package/dist/presentation/components/use_smile_id_instructions_hero.d.ts.map +1 -1
  191. package/dist/presentation/components/use_smile_id_instructions_hero.js +18 -3
  192. package/dist/presentation/components/use_smile_id_instructions_hero.js.map +1 -1
  193. package/dist/presentation/components/use_smile_id_oval_border_palette.d.ts.map +1 -1
  194. package/dist/presentation/components/use_smile_id_oval_border_palette.js +7 -3
  195. package/dist/presentation/components/use_smile_id_oval_border_palette.js.map +1 -1
  196. package/dist/presentation/flow/dsl/builder/config_builder.d.ts +12 -0
  197. package/dist/presentation/flow/dsl/builder/config_builder.d.ts.map +1 -1
  198. package/dist/presentation/flow/dsl/builder/config_builder.js +12 -0
  199. package/dist/presentation/flow/dsl/builder/config_builder.js.map +1 -1
  200. package/dist/presentation/flow/dsl/builder/ml_builder.d.ts +13 -4
  201. package/dist/presentation/flow/dsl/builder/ml_builder.d.ts.map +1 -1
  202. package/dist/presentation/flow/dsl/builder/ml_builder.js +3 -2
  203. package/dist/presentation/flow/dsl/builder/ml_builder.js.map +1 -1
  204. package/dist/presentation/flow/dsl/builder/screens_builder.d.ts +111 -10
  205. package/dist/presentation/flow/dsl/builder/screens_builder.d.ts.map +1 -1
  206. package/dist/presentation/flow/dsl/builder/screens_builder.js +111 -10
  207. package/dist/presentation/flow/dsl/builder/screens_builder.js.map +1 -1
  208. package/dist/presentation/flow/dsl/builder/theme_builder.d.ts +15 -2
  209. package/dist/presentation/flow/dsl/builder/theme_builder.d.ts.map +1 -1
  210. package/dist/presentation/flow/dsl/builder/theme_builder.js +15 -2
  211. package/dist/presentation/flow/dsl/builder/theme_builder.js.map +1 -1
  212. package/dist/presentation/flow/dsl/use_smile_id_builder.d.ts +6 -4
  213. package/dist/presentation/flow/dsl/use_smile_id_builder.d.ts.map +1 -1
  214. package/dist/presentation/flow/dsl/use_smile_id_builder.js.map +1 -1
  215. package/dist/presentation/flow/dsl/use_smile_id_flow_builder.d.ts +62 -36
  216. package/dist/presentation/flow/dsl/use_smile_id_flow_builder.d.ts.map +1 -1
  217. package/dist/presentation/flow/dsl/use_smile_id_flow_builder.js +62 -36
  218. package/dist/presentation/flow/dsl/use_smile_id_flow_builder.js.map +1 -1
  219. package/dist/presentation/flow/flow_navigation_manager.d.ts +39 -4
  220. package/dist/presentation/flow/flow_navigation_manager.d.ts.map +1 -1
  221. package/dist/presentation/flow/flow_navigation_manager.js +141 -10
  222. package/dist/presentation/flow/flow_navigation_manager.js.map +1 -1
  223. package/dist/presentation/flow/model/instruction_guideline.d.ts +9 -0
  224. package/dist/presentation/flow/model/instruction_guideline.d.ts.map +1 -1
  225. package/dist/presentation/flow/model/instructions_defaults.d.ts +11 -2
  226. package/dist/presentation/flow/model/instructions_defaults.d.ts.map +1 -1
  227. package/dist/presentation/flow/model/instructions_defaults.js +73 -25
  228. package/dist/presentation/flow/model/instructions_defaults.js.map +1 -1
  229. package/dist/presentation/flow/screen/orchestrated_capture_screen.d.ts.map +1 -1
  230. package/dist/presentation/flow/screen/orchestrated_capture_screen.js +36 -12
  231. package/dist/presentation/flow/screen/orchestrated_capture_screen.js.map +1 -1
  232. package/dist/presentation/flow/screen/orchestrated_instructions_screen.js +1 -1
  233. package/dist/presentation/flow/screen/orchestrated_instructions_screen.js.map +1 -1
  234. package/dist/presentation/flow/screen/orchestrated_preview_screen.d.ts.map +1 -1
  235. package/dist/presentation/flow/screen/orchestrated_preview_screen.js +3 -1
  236. package/dist/presentation/flow/screen/orchestrated_preview_screen.js.map +1 -1
  237. package/dist/presentation/flow/screen/orchestrated_processing_screen.js +3 -3
  238. package/dist/presentation/flow/screen/orchestrated_processing_screen.js.map +1 -1
  239. package/dist/presentation/flow/validation/job_type_validator.d.ts.map +1 -1
  240. package/dist/presentation/flow/validation/job_type_validator.js +14 -0
  241. package/dist/presentation/flow/validation/job_type_validator.js.map +1 -1
  242. package/dist/presentation/screen/helpers/capture_screen_helpers.d.ts.map +1 -1
  243. package/dist/presentation/screen/helpers/capture_screen_helpers.js +1 -0
  244. package/dist/presentation/screen/helpers/capture_screen_helpers.js.map +1 -1
  245. package/dist/presentation/screen/helpers/instructions_screen_helpers.d.ts +1 -0
  246. package/dist/presentation/screen/helpers/instructions_screen_helpers.d.ts.map +1 -1
  247. package/dist/presentation/screen/helpers/instructions_screen_helpers.js +6 -2
  248. package/dist/presentation/screen/helpers/instructions_screen_helpers.js.map +1 -1
  249. package/dist/presentation/screen/helpers/scan_state_to_overlay_state.js +3 -0
  250. package/dist/presentation/screen/helpers/scan_state_to_overlay_state.js.map +1 -1
  251. package/dist/presentation/screen/use_smile_id_capture_screen.d.ts +17 -1
  252. package/dist/presentation/screen/use_smile_id_capture_screen.d.ts.map +1 -1
  253. package/dist/presentation/screen/use_smile_id_capture_screen.js +153 -18
  254. package/dist/presentation/screen/use_smile_id_capture_screen.js.map +1 -1
  255. package/dist/presentation/screen/use_smile_id_document_preview_screen.d.ts +2 -3
  256. package/dist/presentation/screen/use_smile_id_document_preview_screen.d.ts.map +1 -1
  257. package/dist/presentation/screen/use_smile_id_document_preview_screen.js +16 -11
  258. package/dist/presentation/screen/use_smile_id_document_preview_screen.js.map +1 -1
  259. package/dist/presentation/screen/use_smile_id_instructions_screen.d.ts +2 -0
  260. package/dist/presentation/screen/use_smile_id_instructions_screen.d.ts.map +1 -1
  261. package/dist/presentation/screen/use_smile_id_instructions_screen.js +2 -1
  262. package/dist/presentation/screen/use_smile_id_instructions_screen.js.map +1 -1
  263. package/dist/presentation/screen/use_smile_id_preview_screen.d.ts +7 -6
  264. package/dist/presentation/screen/use_smile_id_preview_screen.d.ts.map +1 -1
  265. package/dist/presentation/screen/use_smile_id_preview_screen.js +9 -8
  266. package/dist/presentation/screen/use_smile_id_preview_screen.js.map +1 -1
  267. package/dist/presentation/screen/use_smile_id_processing_screen.d.ts +2 -3
  268. package/dist/presentation/screen/use_smile_id_processing_screen.d.ts.map +1 -1
  269. package/dist/presentation/screen/use_smile_id_processing_screen.js +3 -2
  270. package/dist/presentation/screen/use_smile_id_processing_screen.js.map +1 -1
  271. package/dist/presentation/theme/theme.d.ts +1 -1
  272. package/dist/presentation/theme/theme.d.ts.map +1 -1
  273. package/dist/presentation/theme/theme.js +20 -18
  274. package/dist/presentation/theme/theme.js.map +1 -1
  275. package/dist/presentation/utils/force_max_brightness.d.ts +4 -4
  276. package/package.json +26 -6
  277. package/src/__tests__/react_native_mock.tsx +8 -0
  278. package/src/camera/camera_defaults.ts +11 -9
  279. package/src/camera/orientation_degrees.ts +5 -6
  280. package/src/core/models/__tests__/document_type.test.ts +6 -4
  281. package/src/core/models/document_capture_mode.ts +27 -0
  282. package/src/core/models/document_type.ts +6 -4
  283. package/src/core/models/result.ts +9 -8
  284. package/src/data/api/interceptors/__tests__/smile_integrity_interceptor.test.ts +37 -1
  285. package/src/data/api/interceptors/__tests__/smile_request_mac_interceptor.test.ts +59 -1
  286. package/src/data/api/interceptors/smile_auth_interceptor.ts +1 -1
  287. package/src/data/api/interceptors/smile_integrity_interceptor.ts +20 -0
  288. package/src/data/api/interceptors/smile_request_mac_interceptor.ts +13 -0
  289. package/src/data/compression/__tests__/payload_compressor.test.ts +200 -0
  290. package/src/data/compression/__tests__/payload_compressor_real_jpeg.test.ts +222 -0
  291. package/src/data/compression/compressible_asset.ts +62 -0
  292. package/src/data/compression/payload_compression_config.ts +53 -0
  293. package/src/data/compression/payload_compression_runner.ts +102 -0
  294. package/src/data/compression/payload_compressor.ts +164 -0
  295. package/src/data/compression/uri_compressible_asset.ts +85 -0
  296. package/src/data/dsl/builder/cache_config_builder.ts +3 -1
  297. package/src/data/dsl/builder/config_builder.ts +45 -14
  298. package/src/data/dsl/builder/interceptor_config_builder.ts +9 -7
  299. package/src/data/dsl/builder/retry_config_builder.ts +22 -1
  300. package/src/data/dsl/builder/timeout_config_builder.ts +7 -0
  301. package/src/data/dsl/use_smile_id_network_builder.ts +17 -0
  302. package/src/data/factory/networking_factory.ts +14 -1
  303. package/src/data/repository/__tests__/network_retries.test.ts +117 -0
  304. package/src/data/repository/use_smile_id_repository_impl.ts +96 -9
  305. package/src/data/security/__tests__/security_policy.test.ts +96 -0
  306. package/src/data/security/__tests__/smile_id_crypto_manager.test.ts +18 -0
  307. package/src/data/security/request_canonicalizer.ts +15 -2
  308. package/src/data/security/security_policy.ts +70 -0
  309. package/src/data/util/__tests__/use_smile_id_token_decoder.test.ts +57 -1
  310. package/src/data/util/retry_util.ts +3 -2
  311. package/src/data/util/use_smile_id_token_decoder.ts +76 -28
  312. package/src/l10n/strings_en.ts +2 -1
  313. package/src/l10n/use_smile_id_localizations.ts +3 -0
  314. package/src/metadata/__tests__/device_orientation_collector.test.ts +15 -0
  315. package/src/metadata/__tests__/metadata_configuration_mappers.test.ts +215 -0
  316. package/src/metadata/__tests__/metadata_configuration_objects.test.ts +85 -0
  317. package/src/metadata/__tests__/metadata_device_context.test.ts +147 -0
  318. package/src/metadata/__tests__/metadata_golden_fixture.json +13 -0
  319. package/src/metadata/__tests__/metadata_payload_golden.test.ts +193 -0
  320. package/src/metadata/__tests__/use_smile_id_metadata.test.ts +18 -24
  321. package/src/metadata/builder_configuration.ts +63 -0
  322. package/src/metadata/captured_image_properties.ts +10 -0
  323. package/src/metadata/device_orientation_collector.ts +75 -0
  324. package/src/metadata/geolocation.ts +46 -0
  325. package/src/metadata/metadata_configuration_mappers.ts +234 -0
  326. package/src/metadata/model_configuration.ts +68 -0
  327. package/src/metadata/optional_native_modules.ts +157 -3
  328. package/src/metadata/use_smile_id_metadata.ts +140 -17
  329. package/src/metadata/use_smile_id_metadata_factory.ts +195 -11
  330. package/src/presentation/assets/si_ess_animation_all_directions.json +1300 -286
  331. package/src/presentation/assets/svg/document_shimmer_strings.ts +17 -0
  332. package/src/presentation/assets/svg/instruction_svg_strings.ts +34 -12
  333. package/src/presentation/components/__tests__/enhanced_smart_selfie_animation_frames.test.ts +1 -3
  334. package/src/presentation/components/__tests__/use_smile_id_enhanced_smart_selfie_clip.test.tsx +3 -4
  335. package/src/presentation/components/__tests__/use_smile_id_guideline_thumbnail.test.tsx +34 -1
  336. package/src/presentation/components/__tests__/use_smile_id_instructions_hero.test.tsx +27 -0
  337. package/src/presentation/components/__tests__/use_smile_id_oval_border_palette.test.ts +7 -5
  338. package/src/presentation/components/helpers/enhanced_smart_selfie_animation_frames.ts +0 -6
  339. package/src/presentation/components/icons/index.tsx +65 -18
  340. package/src/presentation/components/use_smile_id_attribution.tsx +1 -1
  341. package/src/presentation/components/use_smile_id_button.tsx +4 -4
  342. package/src/presentation/components/use_smile_id_capture_content.tsx +36 -12
  343. package/src/presentation/components/use_smile_id_captured_document_image.tsx +3 -8
  344. package/src/presentation/components/use_smile_id_document_capture_controls.tsx +103 -39
  345. package/src/presentation/components/use_smile_id_document_overlay.tsx +134 -44
  346. package/src/presentation/components/use_smile_id_document_shimmer.tsx +51 -0
  347. package/src/presentation/components/use_smile_id_enhanced_smart_selfie_clip.tsx +0 -3
  348. package/src/presentation/components/use_smile_id_guideline_thumbnail.tsx +131 -2
  349. package/src/presentation/components/use_smile_id_instructions_hero.tsx +100 -59
  350. package/src/presentation/components/use_smile_id_oval_border_palette.ts +7 -3
  351. package/src/presentation/flow/__tests__/document_flow_navigation.test.ts +200 -1
  352. package/src/presentation/flow/dsl/builder/config_builder.ts +14 -0
  353. package/src/presentation/flow/dsl/builder/ml_builder.ts +13 -4
  354. package/src/presentation/flow/dsl/builder/screens_builder.ts +111 -10
  355. package/src/presentation/flow/dsl/builder/theme_builder.ts +19 -2
  356. package/src/presentation/flow/dsl/use_smile_id_builder.tsx +6 -4
  357. package/src/presentation/flow/dsl/use_smile_id_flow_builder.ts +62 -36
  358. package/src/presentation/flow/flow_navigation_manager.ts +179 -13
  359. package/src/presentation/flow/model/instruction_guideline.ts +6 -0
  360. package/src/presentation/flow/model/instructions_defaults.ts +103 -25
  361. package/src/presentation/flow/screen/orchestrated_capture_screen.tsx +43 -10
  362. package/src/presentation/flow/screen/orchestrated_instructions_screen.tsx +1 -0
  363. package/src/presentation/flow/screen/orchestrated_preview_screen.tsx +4 -2
  364. package/src/presentation/flow/screen/orchestrated_processing_screen.tsx +3 -3
  365. package/src/presentation/flow/validation/__tests__/job_type_validator.test.ts +64 -0
  366. package/src/presentation/flow/validation/job_type_validator.ts +24 -0
  367. package/src/presentation/screen/__tests__/instructions_screen_helpers.test.ts +15 -3
  368. package/src/presentation/screen/__tests__/use_smile_id_capture_screen.test.tsx +6 -4
  369. package/src/presentation/screen/helpers/capture_screen_helpers.ts +1 -0
  370. package/src/presentation/screen/helpers/instructions_screen_helpers.ts +7 -2
  371. package/src/presentation/screen/helpers/scan_state_to_overlay_state.ts +3 -0
  372. package/src/presentation/screen/use_smile_id_capture_screen.tsx +234 -36
  373. package/src/presentation/screen/use_smile_id_document_preview_screen.tsx +32 -22
  374. package/src/presentation/screen/use_smile_id_instructions_screen.tsx +4 -0
  375. package/src/presentation/screen/use_smile_id_preview_screen.tsx +9 -9
  376. package/src/presentation/screen/use_smile_id_processing_screen.tsx +7 -7
  377. package/src/presentation/theme/theme.ts +21 -19
  378. package/src/presentation/utils/force_max_brightness.tsx +4 -4
  379. package/dist/camera/frame_processor_plugin.d.ts +0 -28
  380. package/dist/camera/frame_processor_plugin.d.ts.map +0 -1
  381. package/dist/camera/frame_processor_plugin.js +0 -21
  382. package/dist/camera/frame_processor_plugin.js.map +0 -1
  383. package/dist/camera/use_smile_id_frame_processor.d.ts +0 -38
  384. package/dist/camera/use_smile_id_frame_processor.d.ts.map +0 -1
  385. package/dist/camera/use_smile_id_frame_processor.js +0 -2
  386. package/dist/camera/use_smile_id_frame_processor.js.map +0 -1
  387. package/dist/presentation/components/use_smile_id_document_frame_glyph.d.ts +0 -17
  388. package/dist/presentation/components/use_smile_id_document_frame_glyph.d.ts.map +0 -1
  389. package/dist/presentation/components/use_smile_id_document_frame_glyph.js +0 -17
  390. package/dist/presentation/components/use_smile_id_document_frame_glyph.js.map +0 -1
  391. package/dist/presentation/components/use_smile_id_enhanced_smart_selfie_animation.d.ts +0 -24
  392. package/dist/presentation/components/use_smile_id_enhanced_smart_selfie_animation.d.ts.map +0 -1
  393. package/dist/presentation/components/use_smile_id_enhanced_smart_selfie_animation.js +0 -91
  394. package/dist/presentation/components/use_smile_id_enhanced_smart_selfie_animation.js.map +0 -1
  395. package/dist/presentation/components/use_smile_id_instruction_card.d.ts +0 -31
  396. package/dist/presentation/components/use_smile_id_instruction_card.d.ts.map +0 -1
  397. package/dist/presentation/components/use_smile_id_instruction_card.js +0 -43
  398. package/dist/presentation/components/use_smile_id_instruction_card.js.map +0 -1
  399. package/dist/presentation/screen/helpers/use_document_orientation_lock.d.ts +0 -24
  400. package/dist/presentation/screen/helpers/use_document_orientation_lock.d.ts.map +0 -1
  401. package/dist/presentation/screen/helpers/use_document_orientation_lock.js +0 -47
  402. package/dist/presentation/screen/helpers/use_document_orientation_lock.js.map +0 -1
  403. package/src/presentation/components/use_smile_id_document_frame_glyph.tsx +0 -162
package/README.md CHANGED
@@ -1,130 +1,742 @@
1
- # `@smileid/usesmileid`
1
+ # Smile ID React Native (Expo) SDK
2
2
 
3
- UseSmileID v12 — public-facing React Native (Expo) SDK. ML processing
4
- lives in the federated provider packages
5
- (`@smileid/usesmileid_{mlkit,vision,huawei}_{face,document}`); this package
6
- owns configuration, state observation, and UI.
3
+ The UseSmileID React Native SDK lets you embed identity verification flows into your Expo or bare React Native app using a type-safe DSL builder. Compose screens like LEGO bricks — no predefined product flows, no inheritance.
7
4
 
8
- ## Architecture
5
+ ## SDK Size
9
6
 
10
- The SDK is one of nine workspace packages — see
11
- [`docs/Architecture.md`](../../docs/Architecture.md) for the full
12
- picture. This package contributes:
7
+ Sizes are measured on every push to `main` and updated automatically by CI.
13
8
 
14
- - **DSL builder** (`useSmileIDBuilder`) — declarative flow
15
- configuration.
16
- - **Theme tokens** (`UseSmileIDTheme`, `defaultLightTheme`,
17
- `defaultDarkTheme`) — colours, typography, spacing, shapes.
18
- - **Flow types** (`FlowConfiguration`, `JobType`, `FlowStep`,
19
- `UseSmileIDResult`) — discriminated unions partner code can exhaust.
20
- - **Screen surface** (`UseSmileID*Screen`) — public components, one
21
- per `FlowStep`. **Currently stubs** — visual implementation rolling
22
- out per `docs/Architecture.md § Rollout`.
9
+ <!-- SDK_SIZE_TABLE_START -->
23
10
 
24
- No ML logic lives in this package. Partners pick the analyzer
25
- implementation that matches their target platform / device fleet from
26
- the federated providers and inject it via `analyzers`.
11
+ | Package | Download Size | Install Size |
12
+ | ---------------------------------------- | ------------- | ------------ |
13
+ | `@smileid/usesmileid` | — | — |
14
+ | `@smileid/usesmileid_bridge` | — | — |
15
+ | `@smileid/usesmileid_platform_interface` | — | — |
16
+ | `@smileid/usesmileid_mlkit_face` | — | — |
17
+ | `@smileid/usesmileid_mlkit_document` | — | — |
18
+ | `@smileid/usesmileid_huawei_face` | — | — |
19
+ | `@smileid/usesmileid_huawei_document` | — | — |
20
+ | `@smileid/usesmileid_vision_face` | — | — |
21
+ | `@smileid/usesmileid_vision_document` | — | — |
22
+ | **Sample app (iOS)** | — | — |
23
+ | **Sample app (Android)** | — | — |
24
+
25
+ <!-- SDK_SIZE_TABLE_END -->
26
+
27
+ ## Requirements
28
+
29
+ - React Native 0.83+ or Expo SDK 55+
30
+ - Node 20.18+
31
+ - React 19.2+
32
+ - Xcode (latest stable) — iOS 15.0+ deployment target
33
+ - Android Gradle Plugin 8.x — `compileSdk` 37, `minSdk` 26 (the
34
+ `com.usesmileid:*` 12.0.0 AARs are built with compileSdk 37 and
35
+ enforce it as the consumer minimum — set `android.compileSdkVersion=37` in
36
+ `gradle.properties` if your project pins a lower level. `minSdk` 26 is
37
+ required because VisionCamera's `Frame.toArrayBuffer()`, which the SDK's
38
+ frame streaming depends on, is compiled out below it — set
39
+ `android.minSdkVersion=26`)
27
40
 
28
41
  ## Installation
29
42
 
43
+ Add the SDK, its native peer dependencies, and the analyzer providers that match your target platforms:
44
+
30
45
  ```sh
31
46
  pnpm add @smileid/usesmileid \
47
+ react-native-quick-crypto react-native-quick-base64 react-native-nitro-modules \
32
48
  @smileid/usesmileid_mlkit_face @smileid/usesmileid_mlkit_document \
33
49
  @smileid/usesmileid_vision_face @smileid/usesmileid_vision_document
34
50
  ```
35
51
 
36
- (Add `@smileid/usesmileid_huawei_{face,document}` instead of mlkit on
37
- no-GMS Android targets.)
52
+ (Use `@smileid/usesmileid_huawei_{face,document}` instead of mlkit on no-GMS Android targets.)
53
+
54
+ `react-native-quick-crypto`, `react-native-quick-base64`, and `react-native-nitro-modules` are **required peer dependencies** — the SDK uses them for native request signing (PBKDF2/HMAC). They must be installed in your app directly: React Native autolinking only links native modules declared in the app's own `package.json`, not a library's transitive ones, so the SDK cannot pull them in for you.
55
+
56
+ The provider packages each have native code (Android AAR / iOS SPM). Expo prebuild picks them up automatically via `expo-module.config.json`. For bare React Native, run `npx pod-install` after adding the packages and let Gradle resolve the AARs on the next Android build.
38
57
 
39
- ## Usage
58
+ ---
59
+
60
+ ## Quick Start
61
+
62
+ Mount `<UseSmileIDBuilder>` anywhere in your component tree. It is a regular React component — use it like any other.
40
63
 
41
64
  ```tsx
42
- import { Platform } from "react-native";
43
- import { JobType, UseSmileIDFlow, useSmileIDBuilder } from "@smileid/usesmileid";
44
- import { useSmileIDMlkitFace } from "@smileid/usesmileid_mlkit_face";
65
+ import { CaptureType, JobType, UseSmileIDBuilder } from "@smileid/usesmileid";
66
+ import { faceAnalyzer } from "./src/providers";
67
+
68
+ export default function VerificationScreen() {
69
+ return (
70
+ <UseSmileIDBuilder
71
+ builder={(b) => {
72
+ b.network((n) => {
73
+ n.config((c) => {
74
+ c.jobType = JobType.smartSelfieEnrollment;
75
+ c.token = "your-v3-token";
76
+ c.partnerConfig((p) => {
77
+ p.partnerId = "your-partner-id";
78
+ });
79
+ });
80
+ });
81
+
82
+ b.ml((m) => {
83
+ m.analyzers((a) => {
84
+ a.forCaptureType(CaptureType.selfie, (face) =>
85
+ face.add(faceAnalyzer),
86
+ );
87
+ });
88
+ });
89
+
90
+ b.screens((screens) => {
91
+ screens.instructions();
92
+ screens.capture((c) => {
93
+ c.captureType = CaptureType.selfie;
94
+ });
95
+ screens.preview();
96
+ screens.processing();
97
+ });
98
+
99
+ b.onResult = (result) => {
100
+ switch (result.status) {
101
+ case "success":
102
+ console.log("Captured:", result.value);
103
+ break;
104
+ case "failure":
105
+ console.error("Error:", result.error);
106
+ break;
107
+ }
108
+ };
109
+ }}
110
+ />
111
+ );
112
+ }
113
+ ```
114
+
115
+ `./src/providers` is a pair of platform-suffix files (`providers.ios.ts` and `providers.android.ts`) that select the right native analyzer per platform. See [Federated providers](#ml--federated-machine-learning-analyzers) below.
116
+
117
+ ---
118
+
119
+ ## Full Builder Reference
120
+
121
+ `useSmileIDBuilder` takes a callback that receives a mutable builder. Top-level mutable properties (`consentInformation`, `enhancedKYCParams`, `biometricKYCParams`, `documentVerificationParams`, `enhancedDocumentVerificationParams`, `userDetails`, `localizations`, `onResult`, `onAnalyticsEvent`) are property-assigned. Nested blocks (`config`, `theme`, `network`, `ml`, `screens`) take closures.
122
+
123
+ The server issues `userId` and `jobId` and returns them in the submission response — partners receive both via `onResult`. Don't construct them client-side.
124
+
125
+ ### `config` — Global settings
126
+
127
+ ```ts
128
+ b.config((c) => {
129
+ c.enableDebugMode = false;
130
+ c.allowOfflineMode = false;
131
+ c.enableCrashReporting = true;
132
+ });
133
+ ```
134
+
135
+ | Property | Type | Default | Description |
136
+ | ---------------------- | --------- | ------- | ------------------------------------------------------------------------------------------ |
137
+ | `enableDebugMode` | `boolean` | `false` | Shows a validation error screen on build failure |
138
+ | `allowOfflineMode` | `boolean` | `false` | Allows the flow to run without a network connection |
139
+ | `enableCrashReporting` | `boolean` | `true` | Enables Sentry crash reporting for the SDK. Set to `false` if your app runs its own Sentry |
140
+
141
+ ---
142
+
143
+ ### `theme` — UI customisation
144
+
145
+ Each color slot accepts an `AdaptiveColor` `{light, dark}` pair via the `color({...})` helper. The SDK resolves the active variant at mount time using the device's color scheme — partners supply both values up front.
146
+
147
+ ```ts
148
+ b.theme((t) => {
149
+ t.primaryColor = t.color("#1A73E8", "#4DA3FF");
150
+ t.primaryForeground = t.color("#FFFFFF", "#000000");
151
+ t.secondaryColor = t.color("#5F6368", "#9AA0A6");
152
+ t.accentColor = t.color("#34A853", "#81C995");
153
+ t.fontFamily = "Inter";
154
+ t.buttonShape = 12;
155
+ t.cardShape = 16;
156
+ });
157
+ ```
158
+
159
+ | Property | Type | Default | Description |
160
+ | ------------------- | --------------- | ----------- | ------------------------------------------------------ |
161
+ | `primaryColor` | `AdaptiveColor` | SDK default | Main action colour (buttons, highlights) |
162
+ | `primaryForeground` | `AdaptiveColor` | SDK default | Text/icons on primary colour |
163
+ | `secondaryColor` | `AdaptiveColor` | SDK default | Secondary surface colour |
164
+ | `accentColor` | `AdaptiveColor` | SDK default | Accent highlights |
165
+ | `fontFamily` | `string` | SDK default | Font family loaded via `expo-font` or RN's font system |
166
+ | `buttonShape` | `number` (dp) | SDK default | Corner radius for buttons |
167
+ | `cardShape` | `number` (dp) | SDK default | Corner radius for cards |
168
+
169
+ Both `defaultLightTheme` and `defaultDarkTheme` are exported. They share `typography` / `spacing` / `shapes` and differ only in `colors` — partners can mix-and-match.
170
+
171
+ ### Localization
172
+
173
+ Every string rendered by the SDK can be overridden at the app level. Drop one translation JSON per locale, register once at app startup, and the SDK auto-resolves the device locale at flow mount.
174
+
175
+ ```ts
176
+ import { UseSmileIDLocalizations } from "@smileid/usesmileid";
177
+ import frOverrides from "./l10n/fr.json";
178
+ import arOverrides from "./l10n/ar.json";
179
+
180
+ UseSmileIDLocalizations.register("fr", frOverrides);
181
+ UseSmileIDLocalizations.register("ar", arOverrides);
182
+ ```
183
+
184
+ ```jsonc
185
+ // l10n/fr.json
186
+ {
187
+ "si_consent_allow": "Accepter",
188
+ "si_consent_consent": "Je teste juste des trucs au hasard",
189
+ }
190
+ ```
191
+
192
+ Match strategy: exact match (`'pt-BR'`) → language-only fallback (`'pt'`) → English defaults.
193
+
194
+ Override the device-locale resolver to plug in your own resolution (e.g. `expo-localization`):
195
+
196
+ ```ts
197
+ import { getLocales } from "expo-localization";
198
+ UseSmileIDLocalizations.localeResolver = () =>
199
+ getLocales()[0]?.languageCode ?? "en";
200
+ ```
201
+
202
+ Per-flow override (wins over the registry) is still available via `b.localizations = UseSmileIDLocalizations.fromOverrides(map)`.
203
+
204
+ ---
205
+
206
+ ### `network` — API configuration
207
+
208
+ All fields are optional. Omit the `network` block entirely to use SDK defaults.
209
+
210
+ ```ts
211
+ import { JobType, LogLevel } from "@smileid/usesmileid";
212
+
213
+ b.network((n) => {
214
+ n.config((c) => {
215
+ c.jobType = JobType.documentVerification;
216
+ c.token = "your-v3-token";
217
+ // Optional: refresh on 401 mid-flow. Invoked when the server returns
218
+ // 401; return a fresh token and the SDK retries once.
219
+ c.onTokenExpired = async (previous) => fetchFreshToken();
220
+ c.partnerConfig((p) => {
221
+ p.partnerId = "your-partner-id";
222
+ p.callbackUrl = "https://example.com/callback";
223
+ p.useSandbox = false;
224
+ });
225
+ c.logging((l) => {
226
+ l.enabled = true;
227
+ l.level = LogLevel.basic;
228
+ });
229
+ });
230
+ n.timeouts((t) => {
231
+ t.connect = 30;
232
+ t.read = 60;
233
+ t.write = 60;
234
+ t.call = 120;
235
+ });
236
+ n.cache((c) => {
237
+ c.enabled = true;
238
+ c.maxSize = 100 * 1024 * 1024; // 100 MB
239
+ });
240
+ n.interceptors((i) => {
241
+ i.add(i.gzip());
242
+ i.add(
243
+ i.logging((l) => {
244
+ l.level = LogLevel.body;
245
+ }),
246
+ );
247
+ i.add(myCustomInterceptor); // partner-supplied
248
+ });
249
+ });
250
+ ```
251
+
252
+ #### `config` block
253
+
254
+ | Property | Type | Default | Description |
255
+ | ---------------- | ----------------------------------------------------------- | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
256
+ | `jobType` | `JobType` | `JobType.unknown` | Job type sent with every request |
257
+ | `token` | `string` | `""` | Short-lived v3 auth token. Exchange your long-lived API key for one from your own backend (`POST /v3/token`) and supply it here. The SDK stamps it on every authed request. |
258
+ | `onTokenExpired` | `((previousToken: string) => Promise<string>) \| undefined` | `undefined` | Optional refresh callback. Invoked on a `401 Unauthorized` response on an authed request. The SDK calls it with the token it was using, expects a fresh token back, and retries the failed request once. Concurrent 401s collapse to a single callback invocation. If the callback throws or the retry also returns 401, the original 401 surfaces unchanged. |
259
+
260
+ #### `partnerConfig` block
261
+
262
+ | Property | Type | Default | Description |
263
+ | --------------- | ------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------ |
264
+ | `partnerId` | `string` | `""` | Your Smile ID partner ID |
265
+ | `callbackUrl` | `string` | `""` | Webhook URL for job results |
266
+ | `useSandbox` | `boolean` | `false` | Route requests to the sandbox environment |
267
+ | `partnerParams` | `Record<string, string>?` | `undefined` | Optional partner-defined key/value pairs forwarded as the `partner_params` JSON multipart part on Enhanced/Biometric KYC submissions |
268
+
269
+ #### `logging` block
270
+
271
+ | Property | Type | Default | Description |
272
+ | --------- | ---------- | ---------------- | ------------------------------------- |
273
+ | `enabled` | `boolean` | `true` | Enable network logging |
274
+ | `level` | `LogLevel` | `LogLevel.basic` | `none` / `basic` / `headers` / `body` |
275
+
276
+ #### `timeouts` block (seconds)
277
+
278
+ | Property | Default |
279
+ | --------- | ------- |
280
+ | `connect` | `60` |
281
+ | `read` | `60` |
282
+ | `write` | `60` |
283
+ | `call` | `120` |
284
+
285
+ #### `cache` block
286
+
287
+ | Property | Type | Default |
288
+ | --------- | ---------------- | -------------------- |
289
+ | `enabled` | `boolean` | `true` |
290
+ | `maxSize` | `number` (bytes) | `52_428_800` (50 MB) |
291
+
292
+ ---
293
+
294
+ ### `ml` — Federated machine-learning analyzers
295
+
296
+ Pick the analyzer that matches your platform / device fleet:
297
+
298
+ | Platform | Face | Document | Native dep |
299
+ | ---------------- | --------------------------------- | ------------------------------------- | --------------------- |
300
+ | iOS | `@smileid/usesmileid_vision_face` | `@smileid/usesmileid_vision_document` | Apple Vision (SPM) |
301
+ | Android (GMS) | `@smileid/usesmileid_mlkit_face` | `@smileid/usesmileid_mlkit_document` | Google ML Kit (Maven) |
302
+ | Android (no GMS) | `@smileid/usesmileid_huawei_face` | `@smileid/usesmileid_huawei_document` | Huawei HMS (Maven) |
303
+
304
+ ```ts
305
+ import { CaptureType } from "@smileid/usesmileid";
306
+ import { faceAnalyzer, documentAnalyzer } from "./src/providers";
307
+
308
+ b.ml((m) => {
309
+ m.analyzers((a) => {
310
+ a.forCaptureType(CaptureType.selfie, (face) => face.add(faceAnalyzer));
311
+ a.forCaptureType(CaptureType.document, (doc) => doc.add(documentAnalyzer));
312
+ });
313
+ });
314
+ ```
315
+
316
+ **Important:** each provider package's TS index calls `requireNativeModule` at module-load. Importing `@smileid/usesmileid_mlkit_face` on iOS (or `@smileid/usesmileid_vision_face` on Android) crashes the bundle at evaluation time. Use platform-suffix files so Metro picks the right one and the wrong-platform package never loads:
317
+
318
+ ```ts
319
+ // providers.ios.ts
45
320
  import { useSmileIDVisionFace } from "@smileid/usesmileid_vision_face";
321
+ import { useSmileIDVisionDocument } from "@smileid/usesmileid_vision_document";
322
+ export const faceAnalyzer = useSmileIDVisionFace;
323
+ export const documentAnalyzer = useSmileIDVisionDocument;
324
+
325
+ // providers.android.ts
326
+ import { useSmileIDMlkitFace } from "@smileid/usesmileid_mlkit_face";
327
+ import { useSmileIDMlkitDocument } from "@smileid/usesmileid_mlkit_document";
328
+ export const faceAnalyzer = useSmileIDMlkitFace;
329
+ export const documentAnalyzer = useSmileIDMlkitDocument;
330
+ ```
331
+
332
+ Add `"moduleSuffixes": [".ios", ".android", ""]` to your `tsconfig.json` so `tsc` resolves `./src/providers` correctly. See `sample-expo/` for a complete reference.
333
+
334
+ ---
46
335
 
47
- const config = useSmileIDBuilder((b) => {
48
- b.userId("user-123");
49
- b.jobId(`job-${Date.now()}`);
50
- b.jobType(JobType.smartSelfieEnrollment);
51
- b.analyzers({
52
- face: Platform.OS === "ios" ? useSmileIDVisionFace : useSmileIDMlkitFace,
336
+ ### `screens` — Flow composition
337
+
338
+ Call screen functions directly inside the `screens` closure. The flow navigates through them in the order they are declared.
339
+
340
+ ```ts
341
+ import { CaptureType } from "@smileid/usesmileid";
342
+
343
+ b.screens((screens) => {
344
+ screens.consent((c) => {
345
+ c.partnerName = "Acme Corp";
346
+ c.partnerIcon = <Image source={require("./assets/logo.png")} style={{ width: 36, height: 36 }} />;
347
+ c.partnerPrivacyPolicyUrl = "https://acme.com/privacy";
348
+ c.showAttribution = true;
349
+ c.onConsentGranted = (info) => console.log("Consent:", info);
350
+ });
351
+ screens.instructions((i) => {
352
+ i.title = "Verify your identity";
353
+ i.description = "You will need a selfie and a document.";
354
+ i.showAttribution = true;
53
355
  });
54
- b.screens({
55
- instructions: { showAttribution: true },
56
- capture: { captureType: "selfie" },
57
- preview: { allowRetake: true },
356
+ screens.permission((p) => {
357
+ p.cameraRationale = "Camera access required.";
358
+ });
359
+ screens.capture((cap) => {
360
+ cap.captureType = CaptureType.selfie;
361
+ cap.selfie((sel) => {
362
+ sel.allowAgentMode = false;
363
+ sel.enableEnhancedLiveness = true;
364
+ });
365
+ });
366
+ screens.capture((cap) => {
367
+ cap.captureType = CaptureType.document;
368
+ cap.document((doc) => {
369
+ doc.autoCapture = true;
370
+ doc.autoCaptureTimeout = 10;
371
+ doc.allowGalleryUpload = false;
372
+ doc.captureBothSides = true;
373
+ doc.allowSkipBack = false;
374
+ doc.knownIdAspectRatio = 1.586; // CR-80 card ratio (optional)
375
+ });
376
+ });
377
+ screens.preview((p) => {
378
+ p.allowRetake = true;
379
+ });
380
+ screens.processing((p) => {
381
+ p.showProgressPercentage = true;
58
382
  });
59
- b.onResult = (result) => {
60
- // `UseSmileIDResult<T>` is a discriminated union; switch on
61
- // `status` to narrow each branch — analogous to Kotlin's
62
- // exhaustive `when` on a sealed class.
63
- switch (result.status) {
64
- case "success":
65
- // `result.value: JobSubmissionResponse` carries `jobId`,
66
- // `userId`, `status`, `message`, and optional `createdAt`.
67
- console.log("jobId:", result.value.jobId);
68
- console.log("status:", result.value.status);
69
- console.log("message:", result.value.message);
70
- break;
71
- case "failure":
72
- console.error("flow failed:", result.error);
73
- break;
74
- }
75
- };
76
383
  });
384
+ ```
385
+
386
+ #### Screen types
387
+
388
+ | Screen | How to add | Key properties |
389
+ | ---------------- | ------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
390
+ | Consent | `screens.consent((c) => ...)` | `partnerName`, `partnerIcon`, `partnerPrivacyPolicyUrl`, `showAttribution`, `onConsentGranted`, `allowButton`, `denyButton` (`partnerIcon` and `partnerPrivacyPolicyUrl` are required) |
391
+ | Instructions | `screens.instructions((i) => ...)` | `title`, `description`, `showAttribution`, `continueButton` |
392
+ | Permission | `screens.permission((p) => ...)` | `cameraRationale`, `continueButton` |
393
+ | Selfie capture | `screens.capture((cap) => { cap.captureType = CaptureType.selfie; cap.selfie(...); })` | `allowAgentMode`, `enableEnhancedLiveness` |
394
+ | Document capture | `screens.capture((cap) => { cap.captureType = CaptureType.document; cap.document(...); })` | `autoCapture`, `allowGalleryUpload`, `captureBothSides`, `allowSkipBack`, `knownIdAspectRatio` |
395
+ | Preview | `screens.preview((p) => ...)` | `allowRetake`, `continueButton`, `cancelButton` |
396
+ | Processing | `screens.processing((p) => ...)` | `showProgressPercentage`, `continueButton`, `retryButton`, `exitButton` |
397
+
398
+ Button slots receive `{ onPress: () => void; isEnabled: boolean }` and return any React node, so partners can ship fully custom buttons without losing the orchestrator's wiring.
399
+
400
+ #### Custom screens & button slots — `useFlowNavigation()`
401
+
402
+ Inside any partner component rendered under `<UseSmileIDBuilder>` (custom button slot, fully replaced screen, partner widget), call `useFlowNavigation()` to drive the flow without prop-drilling.
77
403
 
78
- export default () => <UseSmileIDFlow configuration={config} />;
404
+ ```tsx
405
+ import { useFlowNavigation } from "@smileid/usesmileid";
406
+ import { Pressable, Text } from "react-native";
407
+
408
+ function ExitButton() {
409
+ const nav = useFlowNavigation();
410
+ return (
411
+ <Pressable onPress={() => nav.exit()}>
412
+ <Text>Cancel</Text>
413
+ </Pressable>
414
+ );
415
+ }
416
+ ```
417
+
418
+ The hook returns the active `FlowNavigationManager`:
419
+
420
+ | Method | Behaviour |
421
+ | --------------- | --------------------------------------------------------------------------------------------------------------- |
422
+ | `next()` | Advance to the next screen. From the last step, calls `onResult({ status: 'success', ... })`. |
423
+ | `back()` | Decrement. From the first step, calls `onResult({ status: 'failure', error: ... })` with `cancelled` semantics. |
424
+ | `exit(reason?)` | Exit immediately — useful for "abort" buttons. Defaults to `cancelled`. |
425
+ | `captured` | Snapshot of artifacts collected so far (`selfiePath`, `livenessPaths`, `frontDocumentPath`, etc). |
426
+
427
+ Calling `useFlowNavigation()` outside `<UseSmileIDBuilder>` throws — the misuse is loud at first render rather than silently no-op-ing.
428
+
429
+ ---
430
+
431
+ ## Top-level builder callbacks
432
+
433
+ | Property | Type | Description |
434
+ | ------------------ | ----------------------------------------------------------- | --------------------------------------------------------- |
435
+ | `onResult` | `(result: UseSmileIDResult<JobSubmissionResponse>) => void` | Called once when the flow finishes (success or failure) |
436
+ | `onAnalyticsEvent` | `((event: UseSmileIDAnalyticsEvent) => void) \| undefined` | Optional. Called for each analytics event during the flow |
437
+
438
+ ---
439
+
440
+ ## Job-specific parameters
441
+
442
+ Each job type that needs identity fields reads them from a top-level builder property. The shared `user_details` part (`b.userDetails`) is required by every KYC and document job; `country` is the ISO 3166-1 alpha-2 code.
443
+
444
+ | Job type | Builder property | Required fields | Notes |
445
+ | -------------------------------------- | -------------------------------------- | ------------------------------- | ------------------------------------------------------------------------ |
446
+ | `JobType.enhancedKyc` | `b.enhancedKYCParams` | `idType`, `idNumber`, `country` | Optional `bankCode`, `mobileOperator` |
447
+ | `JobType.biometricKyc` | `b.biometricKYCParams` | `idType`, `idNumber`, `country` | `useEnrolledImage` toggles the enrolled-image path |
448
+ | `JobType.documentVerification` | `b.documentVerificationParams` | `country` | `idType` **optional** — omit it to let the backend classify the document |
449
+ | `JobType.enhancedDocumentVerification` | `b.enhancedDocumentVerificationParams` | `country`, `idType` | `idType` **required** — drives the ID-authority cross-check |
450
+
451
+ ```ts
452
+ // Document Verification — idType optional
453
+ b.documentVerificationParams = { country: "KE" };
454
+ b.userDetails = {
455
+ givenNames: "Jane",
456
+ lastName: "Doe",
457
+ email: "jane@example.com",
458
+ };
459
+
460
+ // Enhanced Document Verification — idType required
461
+ b.enhancedDocumentVerificationParams = { country: "KE", idType: "NATIONAL_ID" };
462
+ b.userDetails = {
463
+ givenNames: "Jane",
464
+ lastName: "Doe",
465
+ phoneNumber: "+254700000000",
466
+ };
79
467
  ```
80
468
 
469
+ `user_details` requires non-blank `givenNames` and `lastName` plus at least one of `email` / `phoneNumber`. Pre-flight any payload with `b.validateDocumentVerificationParams(...)`, `b.validateEnhancedDocumentVerificationParams(...)`, or `b.validateUserDetails(...)` before assigning.
470
+
471
+ ---
472
+
81
473
  ## Handling results
82
474
 
83
- Assign `b.onResult` inside the builder callback. It is called once when the flow finishes.
475
+ Set `b.onResult` before (or during) the builder block. It is called once when the flow finishes.
84
476
 
85
477
  ```ts
86
- <UseSmileIDBuilder builder={(smile) => {
87
- smile.onResult = (result) => {
88
- if (result.status === "success") {
478
+ b.onResult = (result) => {
479
+ switch (result.status) {
480
+ case "success":
89
481
  console.log(`Job ${result.value.jobId} status=${result.value.status}`);
90
- } else {
91
- console.log(`Failed: ${result.error}`);
92
- }
93
- };
94
- // ... configure flow
95
- }} />
482
+ break;
483
+ case "failure":
484
+ console.error("flow failed:", result.error);
485
+ break;
486
+ }
487
+ };
488
+ ```
489
+
490
+ The success branch carries a `JobSubmissionResponse` with `jobId`, `userId`, `status`, `message`, and an optional `createdAt`. Partner-supplied inputs (captured frames, identity fields, consent) are not echoed back — keep references at the call site if you need them after the flow.
491
+
492
+ `UseSmileIDResult<T>` is a discriminated union — `result.status` narrows it, no `try` / `catch` needed.
493
+
494
+ ### Forwarding failures to a crash reporter
495
+
496
+ Every exception the SDK surfaces extends `UseSmileIDException`, which carries:
497
+
498
+ - `errorCode` — a stable UPPER_SNAKE_CASE string (e.g. `"NETWORK_TIMEOUT"`, `"BUILDER_VALIDATION_ERROR"`) suitable for grouping. Stable across SDK releases, so Sentry pivots and analytics dashboards keyed on it keep working after upgrades.
499
+ - `message` — partner-safe message; never contains PII.
500
+ - `suggestedFix` — concrete remediation hint for triage.
501
+ - `cause` — the wrapped underlying error (`AxiosError` / `Error`) for stack trace forwarding.
502
+
503
+ Forward failures to Sentry, Bugsnag, or Crashlytics from inside the failure branch of `onResult`:
504
+
505
+ ```ts
506
+ import * as Sentry from "@sentry/react-native";
507
+ import { UseSmileIDException } from "@smileid/usesmileid";
508
+
509
+ b.onResult = (result) => {
510
+ if (result.status === "success") {
511
+ myAnalytics.recordSuccess(result.value.jobId);
512
+ return;
513
+ }
514
+ const error = result.error;
515
+ if (error instanceof UseSmileIDException) {
516
+ Sentry.captureException(error.cause ?? error, {
517
+ tags: { "smileid.error_code": error.errorCode ?? "unknown" },
518
+ extra: { "smileid.suggested_fix": error.suggestedFix },
519
+ });
520
+ }
521
+ };
96
522
  ```
97
523
 
98
- ### Payload
524
+ The wrapped `cause` carries the original stack trace so crash-reporter grouping keys off the underlying transport / IO failure, not the SDK's wrapper class. `errorCode` rides as a tag so you can filter the crash board by failure category.
99
525
 
100
- `UseSmileIDResult<JobSubmissionResponse>` is a discriminated union; switch on `status` to narrow each branch. The success branch carries the server's submission acknowledgement:
526
+ ---
101
527
 
102
- | Field | Type | Description |
103
- | ----------- | ------------------- | ------------------------------------------------------- |
104
- | `jobId` | `string` | Server-issued job identifier |
105
- | `userId` | `string` | Server-issued user identifier |
106
- | `status` | `string` | Submission status (e.g. `"submitted"`) |
107
- | `message` | `string` | Human-readable status message |
108
- | `createdAt` | `string` (optional) | ISO 8601 timestamp at which the server accepted the job |
528
+ ## Analytics
109
529
 
110
- The result does not echo back partner-supplied inputs (captured frames, identity fields, consent). Keep references at the call site if you need them after the flow.
530
+ Set `b.onAnalyticsEvent` to receive a stream of events fired at key moments in the flow. Each event carries a flat `Record<string, string>` that you can forward directly to any analytics backend.
111
531
 
112
- ## Status
532
+ ```ts
533
+ import * as Analytics from "expo-firebase-analytics";
113
534
 
114
- | Area | Status |
115
- | --------------------------------- | ------------------------------------------ |
116
- | Public DSL surface | implemented |
117
- | Theme tokens | implemented |
118
- | Flow types & discriminated unions | implemented |
119
- | Screen visuals | stub (returns placeholder views) |
120
- | Orchestrator state machine | stub (renders job summary, no transitions) |
121
- | Network / job submission | not yet wired |
535
+ b.onAnalyticsEvent = (event) => {
536
+ // Forward to Firebase, Mixpanel, Segment, or your own backend
537
+ Analytics.logEvent(event.type, event.extras);
538
+ };
539
+ ```
122
540
 
123
- See [`docs/Architecture.md § Rollout`](../../docs/Architecture.md) for
124
- the next milestones.
541
+ Every event automatically includes `session_id` and `timestamp` (epoch milliseconds) so you can correlate events across a single flow run without any extra bookkeeping.
125
542
 
126
- ## Testing
543
+ ### Event reference
127
544
 
128
- ```sh
129
- pnpm --filter @smileid/usesmileid test
545
+ | Event | When fired | Key extras |
546
+ | ------------------- | ---------------------------------- | --------------------------------------------------------------------------------- |
547
+ | `flow_started` | Flow initialises | `job_type` |
548
+ | `screen_viewed` | Each screen becomes active | `screen_name` |
549
+ | `consent_captured` | User grants consent | `decision: "granted"` |
550
+ | `selfie_captured` | Selfie + liveness captured | `liveness_image_count` |
551
+ | `document_captured` | Document image captured | `document_side: "front"` or `"both"` |
552
+ | `retake_requested` | User navigates back to redo a step | — |
553
+ | `job_submitted` | API submission begins | `job_type`, `attempt` |
554
+ | `flow_completed` | Flow finishes | `result: "success"` or `"failure"`, `job_id` (success), `error_message` (failure) |
555
+
556
+ `onAnalyticsEvent` is `undefined` by default — omit it and no events are delivered.
557
+
558
+ ---
559
+
560
+ ## Pre-supplied consent
561
+
562
+ If the user already consented in a previous session, skip the consent screen by supplying `consentInformation` before building:
563
+
564
+ ```tsx
565
+ import {
566
+ UseSmileIDBuilder,
567
+ type ConsentInformation,
568
+ } from "@smileid/usesmileid";
569
+
570
+ <UseSmileIDBuilder
571
+ builder={(b) => {
572
+ const consentInfo: ConsentInformation = {
573
+ /* … */
574
+ };
575
+ b.consentInformation = consentInfo;
576
+ b.screens((screens) => {
577
+ // do not add a consent screen when consentInformation is set —
578
+ // the builder will reject it
579
+ screens.instructions();
580
+ screens.capture((c) => {
581
+ c.captureType = CaptureType.selfie;
582
+ });
583
+ });
584
+ }}
585
+ />;
586
+ ```
587
+
588
+ If `consentInformation` is malformed (missing required fields, invalid timestamps), `<UseSmileIDBuilder>` routes the failure through `onResult.failure` carrying a typed `BuilderValidationException` — see [Validation](#validation) below.
589
+
590
+ ---
591
+
592
+ ## Validation
593
+
594
+ `<UseSmileIDBuilder>` validates eagerly: it surfaces every missing or invalid field the moment the closure returns. Partners receive a typed `BuilderValidationException` via `onResult.failure` — `error.validationState.issues` carries every rule that failed, not just the first.
595
+
596
+ ```tsx
597
+ <UseSmileIDBuilder
598
+ builder={(b) => {
599
+ // …
600
+ b.onResult = (result) => {
601
+ if (
602
+ result.status === "failure" &&
603
+ result.error instanceof BuilderValidationException
604
+ ) {
605
+ for (const issue of result.error.validationState.issues) {
606
+ console.error("[SmileID]", issue.errorCode, issue.message);
607
+ }
608
+ }
609
+ };
610
+ }}
611
+ />
612
+ ```
613
+
614
+ Triggers cover the validation rules — empty screens, ordering invariants, duplicate non-capture screens, capture without ML config, processing without network config, unknown job type at processing time, double-source consent, malformed `consentInformation`, blank KYC params. Set `b.config((c) => { c.enableDebugMode = true; })` to additionally render `ValidationErrorScreen` on-device with every failed rule during development. In production the screen does not mount — partners only see the failure via `onResult.failure`.
615
+
616
+ ---
617
+
618
+ ## Full example — Document verification
619
+
620
+ ```tsx
621
+ import { Alert, StyleSheet } from "react-native";
622
+ import { SafeAreaView } from "react-native-safe-area-context";
623
+ import {
624
+ CaptureType,
625
+ JobType,
626
+ LogLevel,
627
+ UseSmileIDBuilder,
628
+ } from "@smileid/usesmileid";
629
+ import { faceAnalyzer, documentAnalyzer } from "./src/providers";
630
+
631
+ export function DocumentVerificationScreen({
632
+ onComplete,
633
+ }: {
634
+ onComplete: () => void;
635
+ }) {
636
+ return (
637
+ <SafeAreaView style={styles.container} edges={["top", "bottom"]}>
638
+ <UseSmileIDBuilder
639
+ builder={(b) => {
640
+ // Document Verification requires its params + userDetails.
641
+ b.documentVerificationParams = {
642
+ country: "KE",
643
+ idType: "NATIONAL_ID",
644
+ };
645
+ b.userDetails = {
646
+ givenNames: "Jane",
647
+ lastName: "Doe",
648
+ email: "jane@example.com",
649
+ };
650
+
651
+ b.config((c) => {
652
+ c.enableDebugMode = false;
653
+ c.enableCrashReporting = true;
654
+ });
655
+
656
+ b.theme((t) => {
657
+ t.primaryColor = t.color("#1A73E8", "#4DA3FF");
658
+ t.buttonShape = 12;
659
+ });
660
+
661
+ b.network((n) => {
662
+ n.config((c) => {
663
+ c.jobType = JobType.documentVerification;
664
+ c.token = "your-v3-token";
665
+ c.partnerConfig((p) => {
666
+ p.partnerId = "your-partner-id";
667
+ p.callbackUrl = "https://example.com/callback";
668
+ p.useSandbox = true;
669
+ });
670
+ c.logging((l) => {
671
+ l.enabled = true;
672
+ l.level = LogLevel.basic;
673
+ });
674
+ });
675
+ n.timeouts((t) => {
676
+ t.connect = 30;
677
+ t.call = 120;
678
+ });
679
+ });
680
+
681
+ b.ml((m) => {
682
+ m.analyzers((a) => {
683
+ a.forCaptureType(CaptureType.selfie, (face) =>
684
+ face.add(faceAnalyzer),
685
+ );
686
+ a.forCaptureType(CaptureType.document, (doc) =>
687
+ doc.add(documentAnalyzer),
688
+ );
689
+ });
690
+ });
691
+
692
+ b.screens((screens) => {
693
+ screens.consent((c) => {
694
+ c.partnerName = "Acme Corp";
695
+ c.partnerPrivacyPolicyUrl = "https://acme.com/privacy";
696
+ });
697
+ screens.instructions((i) => {
698
+ i.title = "Verify your identity";
699
+ i.description = "You will need a selfie and a document.";
700
+ });
701
+ screens.capture((cap) => {
702
+ cap.captureType = CaptureType.document;
703
+ cap.document((doc) => {
704
+ doc.autoCapture = true;
705
+ doc.captureBothSides = true;
706
+ doc.allowGalleryUpload = false;
707
+ });
708
+ });
709
+ screens.preview((p) => {
710
+ p.allowRetake = true;
711
+ });
712
+ screens.processing();
713
+ });
714
+
715
+ b.onResult = (result) => {
716
+ switch (result.status) {
717
+ case "success":
718
+ Alert.alert("Done", JSON.stringify(result.value));
719
+ break;
720
+ case "failure":
721
+ Alert.alert("Failed", String(result.error));
722
+ break;
723
+ }
724
+ onComplete();
725
+ };
726
+
727
+ b.onAnalyticsEvent = (event) => {
728
+ console.log(
729
+ `[SmileID] ${event.type} — session: ${event.extras["session_id"]}`,
730
+ event.extras,
731
+ );
732
+ };
733
+ }}
734
+ />
735
+ </SafeAreaView>
736
+ );
737
+ }
738
+
739
+ const styles = StyleSheet.create({
740
+ container: { flex: 1, backgroundColor: "#FFFFFF" },
741
+ });
130
742
  ```