@smileid/usesmileid 12.0.0 → 12.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (365) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +1 -1
  3. package/dist/camera/camera_defaults.d.ts +2 -0
  4. package/dist/camera/camera_defaults.d.ts.map +1 -1
  5. package/dist/camera/camera_defaults.js +2 -0
  6. package/dist/camera/camera_defaults.js.map +1 -1
  7. package/dist/core/exception/agent_mode_with_enhanced_liveness_exception.d.ts +11 -0
  8. package/dist/core/exception/agent_mode_with_enhanced_liveness_exception.d.ts.map +1 -0
  9. package/dist/core/exception/agent_mode_with_enhanced_liveness_exception.js +17 -0
  10. package/dist/core/exception/agent_mode_with_enhanced_liveness_exception.js.map +1 -0
  11. package/dist/core/exception/capture_validation_exceptions.d.ts +1 -0
  12. package/dist/core/exception/capture_validation_exceptions.d.ts.map +1 -1
  13. package/dist/core/exception/capture_validation_exceptions.js +1 -0
  14. package/dist/core/exception/capture_validation_exceptions.js.map +1 -1
  15. package/dist/core/exception/flow_exceptions.d.ts +4 -2
  16. package/dist/core/exception/flow_exceptions.d.ts.map +1 -1
  17. package/dist/core/exception/flow_exceptions.js +3 -2
  18. package/dist/core/exception/flow_exceptions.js.map +1 -1
  19. package/dist/core/exception/index.d.ts +1 -0
  20. package/dist/core/exception/index.d.ts.map +1 -1
  21. package/dist/core/exception/index.js +1 -0
  22. package/dist/core/exception/index.js.map +1 -1
  23. package/dist/core/exception/missing_job_type_exception.d.ts +1 -3
  24. package/dist/core/exception/missing_job_type_exception.d.ts.map +1 -1
  25. package/dist/core/exception/missing_job_type_exception.js +2 -4
  26. package/dist/core/exception/missing_job_type_exception.js.map +1 -1
  27. package/dist/core/exception/use_smile_id_error_code.d.ts +1 -0
  28. package/dist/core/exception/use_smile_id_error_code.d.ts.map +1 -1
  29. package/dist/core/exception/use_smile_id_error_code.js +1 -0
  30. package/dist/core/exception/use_smile_id_error_code.js.map +1 -1
  31. package/dist/core/models/config.d.ts +19 -0
  32. package/dist/core/models/config.d.ts.map +1 -1
  33. package/dist/core/models/document_type.d.ts +1 -1
  34. package/dist/core/models/document_type.d.ts.map +1 -1
  35. package/dist/core/models/document_type.js +2 -2
  36. package/dist/core/models/document_type.js.map +1 -1
  37. package/dist/core/models/global_privacy_control.d.ts +36 -0
  38. package/dist/core/models/global_privacy_control.d.ts.map +1 -0
  39. package/dist/core/models/global_privacy_control.js +39 -0
  40. package/dist/core/models/global_privacy_control.js.map +1 -0
  41. package/dist/core/models/network_config.d.ts +2 -2
  42. package/dist/core/models/network_config.js +2 -2
  43. package/dist/data/api/interceptors/smile_auth_interceptor.d.ts.map +1 -1
  44. package/dist/data/api/interceptors/smile_auth_interceptor.js +3 -17
  45. package/dist/data/api/interceptors/smile_auth_interceptor.js.map +1 -1
  46. package/dist/data/api/smile_id_api.d.ts +5 -1
  47. package/dist/data/api/smile_id_api.d.ts.map +1 -1
  48. package/dist/data/api/smile_id_api.js +30 -27
  49. package/dist/data/api/smile_id_api.js.map +1 -1
  50. package/dist/data/dsl/builder/retry_config_builder.d.ts +4 -4
  51. package/dist/data/dsl/builder/retry_config_builder.d.ts.map +1 -1
  52. package/dist/data/dsl/builder/retry_config_builder.js +6 -6
  53. package/dist/data/dsl/builder/retry_config_builder.js.map +1 -1
  54. package/dist/data/model/job_request.d.ts +28 -12
  55. package/dist/data/model/job_request.d.ts.map +1 -1
  56. package/dist/data/model/token_payload.d.ts +78 -0
  57. package/dist/data/model/token_payload.d.ts.map +1 -0
  58. package/dist/data/model/token_payload.js +132 -0
  59. package/dist/data/model/token_payload.js.map +1 -0
  60. package/dist/data/model/user_details_payload.d.ts +39 -0
  61. package/dist/data/model/user_details_payload.d.ts.map +1 -0
  62. package/dist/data/model/user_details_payload.js +53 -0
  63. package/dist/data/model/user_details_payload.js.map +1 -0
  64. package/dist/data/smile_id_urls.d.ts +1 -1
  65. package/dist/data/smile_id_urls.js +1 -1
  66. package/dist/data/smile_id_urls.js.map +1 -1
  67. package/dist/data/util/retry_util.d.ts +1 -1
  68. package/dist/data/util/retry_util.d.ts.map +1 -1
  69. package/dist/data/util/retry_util.js +5 -0
  70. package/dist/data/util/retry_util.js.map +1 -1
  71. package/dist/data/util/use_smile_id_token_decoder.d.ts +15 -3
  72. package/dist/data/util/use_smile_id_token_decoder.d.ts.map +1 -1
  73. package/dist/data/util/use_smile_id_token_decoder.js +20 -8
  74. package/dist/data/util/use_smile_id_token_decoder.js.map +1 -1
  75. package/dist/index.d.ts +2 -2
  76. package/dist/index.d.ts.map +1 -1
  77. package/dist/index.js +2 -2
  78. package/dist/index.js.map +1 -1
  79. package/dist/l10n/strings_en.d.ts +4 -1
  80. package/dist/l10n/strings_en.d.ts.map +1 -1
  81. package/dist/l10n/strings_en.js +4 -1
  82. package/dist/l10n/strings_en.js.map +1 -1
  83. package/dist/l10n/use_smile_id_localizations.d.ts +10 -0
  84. package/dist/l10n/use_smile_id_localizations.d.ts.map +1 -1
  85. package/dist/l10n/use_smile_id_localizations.js +59 -3
  86. package/dist/l10n/use_smile_id_localizations.js.map +1 -1
  87. package/dist/metadata/builder_configuration.d.ts +5 -0
  88. package/dist/metadata/builder_configuration.d.ts.map +1 -1
  89. package/dist/metadata/builder_configuration.js +1 -0
  90. package/dist/metadata/builder_configuration.js.map +1 -1
  91. package/dist/metadata/metadata_configuration_mappers.d.ts +2 -3
  92. package/dist/metadata/metadata_configuration_mappers.d.ts.map +1 -1
  93. package/dist/metadata/metadata_configuration_mappers.js +13 -6
  94. package/dist/metadata/metadata_configuration_mappers.js.map +1 -1
  95. package/dist/metadata/use_smile_id_metadata_factory.d.ts.map +1 -1
  96. package/dist/metadata/use_smile_id_metadata_factory.js +14 -5
  97. package/dist/metadata/use_smile_id_metadata_factory.js.map +1 -1
  98. package/dist/presentation/components/use_smile_id_button.d.ts.map +1 -1
  99. package/dist/presentation/components/use_smile_id_button.js +8 -2
  100. package/dist/presentation/components/use_smile_id_button.js.map +1 -1
  101. package/dist/presentation/components/use_smile_id_enhanced_smart_selfie_clip.d.ts +5 -2
  102. package/dist/presentation/components/use_smile_id_enhanced_smart_selfie_clip.d.ts.map +1 -1
  103. package/dist/presentation/components/use_smile_id_enhanced_smart_selfie_clip.js +8 -3
  104. package/dist/presentation/components/use_smile_id_enhanced_smart_selfie_clip.js.map +1 -1
  105. package/dist/presentation/components/use_smile_id_instructions_hero.d.ts.map +1 -1
  106. package/dist/presentation/components/use_smile_id_instructions_hero.js +8 -3
  107. package/dist/presentation/components/use_smile_id_instructions_hero.js.map +1 -1
  108. package/dist/presentation/flow/dsl/builder/config_builder.d.ts +16 -0
  109. package/dist/presentation/flow/dsl/builder/config_builder.d.ts.map +1 -1
  110. package/dist/presentation/flow/dsl/builder/config_builder.js +18 -0
  111. package/dist/presentation/flow/dsl/builder/config_builder.js.map +1 -1
  112. package/dist/presentation/flow/dsl/builder/screens_builder.d.ts +6 -12
  113. package/dist/presentation/flow/dsl/builder/screens_builder.d.ts.map +1 -1
  114. package/dist/presentation/flow/dsl/builder/screens_builder.js +7 -12
  115. package/dist/presentation/flow/dsl/builder/screens_builder.js.map +1 -1
  116. package/dist/presentation/flow/dsl/use_smile_id_flow_builder.d.ts.map +1 -1
  117. package/dist/presentation/flow/dsl/use_smile_id_flow_builder.js +23 -1
  118. package/dist/presentation/flow/dsl/use_smile_id_flow_builder.js.map +1 -1
  119. package/dist/presentation/flow/flow_navigation_manager.d.ts +22 -3
  120. package/dist/presentation/flow/flow_navigation_manager.d.ts.map +1 -1
  121. package/dist/presentation/flow/flow_navigation_manager.js +84 -46
  122. package/dist/presentation/flow/flow_navigation_manager.js.map +1 -1
  123. package/dist/presentation/flow/model/instructions_defaults.d.ts.map +1 -1
  124. package/dist/presentation/flow/model/instructions_defaults.js +1 -1
  125. package/dist/presentation/flow/model/instructions_defaults.js.map +1 -1
  126. package/dist/presentation/flow/screen/orchestrated_capture_screen.d.ts.map +1 -1
  127. package/dist/presentation/flow/screen/orchestrated_capture_screen.js +13 -3
  128. package/dist/presentation/flow/screen/orchestrated_capture_screen.js.map +1 -1
  129. package/dist/presentation/flow/screen/orchestrated_consent_screen.d.ts.map +1 -1
  130. package/dist/presentation/flow/screen/orchestrated_consent_screen.js +3 -1
  131. package/dist/presentation/flow/screen/orchestrated_consent_screen.js.map +1 -1
  132. package/dist/presentation/flow/screen/orchestrated_preview_screen.d.ts.map +1 -1
  133. package/dist/presentation/flow/screen/orchestrated_preview_screen.js +0 -8
  134. package/dist/presentation/flow/screen/orchestrated_preview_screen.js.map +1 -1
  135. package/dist/presentation/flow/screen/orchestrated_processing_screen.d.ts.map +1 -1
  136. package/dist/presentation/flow/screen/orchestrated_processing_screen.js +25 -5
  137. package/dist/presentation/flow/screen/orchestrated_processing_screen.js.map +1 -1
  138. package/dist/presentation/flow/use_smile_id_flow.d.ts.map +1 -1
  139. package/dist/presentation/flow/use_smile_id_flow.js +45 -12
  140. package/dist/presentation/flow/use_smile_id_flow.js.map +1 -1
  141. package/dist/presentation/flow/validation/flow_validator.d.ts +16 -2
  142. package/dist/presentation/flow/validation/flow_validator.d.ts.map +1 -1
  143. package/dist/presentation/flow/validation/flow_validator.js +61 -47
  144. package/dist/presentation/flow/validation/flow_validator.js.map +1 -1
  145. package/dist/presentation/flow/validation/job_type_validator.d.ts +7 -0
  146. package/dist/presentation/flow/validation/job_type_validator.d.ts.map +1 -1
  147. package/dist/presentation/flow/validation/job_type_validator.js +52 -27
  148. package/dist/presentation/flow/validation/job_type_validator.js.map +1 -1
  149. package/dist/presentation/flow/validation/user_details_validator.d.ts +9 -0
  150. package/dist/presentation/flow/validation/user_details_validator.d.ts.map +1 -0
  151. package/dist/presentation/flow/validation/user_details_validator.js +40 -0
  152. package/dist/presentation/flow/validation/user_details_validator.js.map +1 -0
  153. package/dist/presentation/screen/helpers/capture_screen_helpers.d.ts.map +1 -1
  154. package/dist/presentation/screen/helpers/capture_screen_helpers.js +1 -0
  155. package/dist/presentation/screen/helpers/capture_screen_helpers.js.map +1 -1
  156. package/dist/presentation/screen/helpers/capture_ui_state.d.ts +6 -6
  157. package/dist/presentation/screen/helpers/capture_ui_state.d.ts.map +1 -1
  158. package/dist/presentation/screen/helpers/capture_ui_state.js +19 -19
  159. package/dist/presentation/screen/helpers/capture_ui_state.js.map +1 -1
  160. package/dist/presentation/screen/helpers/ess_turn_haptics.d.ts +2 -2
  161. package/dist/presentation/screen/helpers/ess_turn_haptics.d.ts.map +1 -1
  162. package/dist/presentation/screen/helpers/ess_turn_haptics.js +6 -6
  163. package/dist/presentation/screen/helpers/ess_turn_haptics.js.map +1 -1
  164. package/dist/presentation/screen/helpers/scan_state_to_overlay_state.d.ts +5 -5
  165. package/dist/presentation/screen/helpers/scan_state_to_overlay_state.d.ts.map +1 -1
  166. package/dist/presentation/screen/helpers/scan_state_to_overlay_state.js +11 -11
  167. package/dist/presentation/screen/helpers/scan_state_to_overlay_state.js.map +1 -1
  168. package/dist/presentation/screen/helpers/use_capture_orientation_lock.d.ts +13 -3
  169. package/dist/presentation/screen/helpers/use_capture_orientation_lock.d.ts.map +1 -1
  170. package/dist/presentation/screen/helpers/use_capture_orientation_lock.js +48 -6
  171. package/dist/presentation/screen/helpers/use_capture_orientation_lock.js.map +1 -1
  172. package/dist/presentation/screen/use_smile_id_capture_screen.d.ts +4 -2
  173. package/dist/presentation/screen/use_smile_id_capture_screen.d.ts.map +1 -1
  174. package/dist/presentation/screen/use_smile_id_capture_screen.js +90 -23
  175. package/dist/presentation/screen/use_smile_id_capture_screen.js.map +1 -1
  176. package/dist/presentation/screen/use_smile_id_consent_screen.d.ts +7 -0
  177. package/dist/presentation/screen/use_smile_id_consent_screen.d.ts.map +1 -1
  178. package/dist/presentation/screen/use_smile_id_consent_screen.js +6 -5
  179. package/dist/presentation/screen/use_smile_id_consent_screen.js.map +1 -1
  180. package/dist/presentation/screen/use_smile_id_document_back_instructions.d.ts.map +1 -1
  181. package/dist/presentation/screen/use_smile_id_document_back_instructions.js +5 -13
  182. package/dist/presentation/screen/use_smile_id_document_back_instructions.js.map +1 -1
  183. package/dist/presentation/screen/use_smile_id_document_preview_screen.js +1 -1
  184. package/dist/presentation/screen/use_smile_id_document_preview_screen.js.map +1 -1
  185. package/dist/presentation/screen/use_smile_id_preview_screen.d.ts +1 -21
  186. package/dist/presentation/screen/use_smile_id_preview_screen.d.ts.map +1 -1
  187. package/dist/presentation/screen/use_smile_id_preview_screen.js +3 -14
  188. package/dist/presentation/screen/use_smile_id_preview_screen.js.map +1 -1
  189. package/dist/presentation/screen/use_smile_id_processing_screen.js +1 -1
  190. package/dist/presentation/screen/use_smile_id_processing_screen.js.map +1 -1
  191. package/dist/presentation/utils/locale_utils.d.ts +10 -4
  192. package/dist/presentation/utils/locale_utils.d.ts.map +1 -1
  193. package/dist/presentation/utils/locale_utils.js +13 -5
  194. package/dist/presentation/utils/locale_utils.js.map +1 -1
  195. package/dist/testing/fake_face_analyzer.d.ts +43 -0
  196. package/dist/testing/fake_face_analyzer.d.ts.map +1 -0
  197. package/dist/testing/fake_face_analyzer.js +52 -0
  198. package/dist/testing/fake_face_analyzer.js.map +1 -0
  199. package/dist/testing/index.d.ts +5 -0
  200. package/dist/testing/index.d.ts.map +1 -0
  201. package/dist/testing/index.js +7 -0
  202. package/dist/testing/index.js.map +1 -0
  203. package/dist/testing/scenario_expectations.d.ts +28 -0
  204. package/dist/testing/scenario_expectations.d.ts.map +1 -0
  205. package/dist/testing/scenario_expectations.js +65 -0
  206. package/dist/testing/scenario_expectations.js.map +1 -0
  207. package/dist/testing/scenario_loader.d.ts +11 -0
  208. package/dist/testing/scenario_loader.d.ts.map +1 -0
  209. package/dist/testing/scenario_loader.js +64 -0
  210. package/dist/testing/scenario_loader.js.map +1 -0
  211. package/dist/testing/scripted_scan_results.d.ts +17 -0
  212. package/dist/testing/scripted_scan_results.d.ts.map +1 -0
  213. package/dist/testing/scripted_scan_results.js +52 -0
  214. package/dist/testing/scripted_scan_results.js.map +1 -0
  215. package/package.json +11 -4
  216. package/src/__tests__/dsl.test.ts +51 -1
  217. package/src/__tests__/react_native_mock.tsx +22 -0
  218. package/src/__tests__/setup_react_native.ts +17 -2
  219. package/src/__tests__/snapshots/__snapshots__/screens_structural.test.tsx.snap +5267 -0
  220. package/src/__tests__/snapshots/screens_structural.test.tsx +230 -0
  221. package/src/camera/__tests__/camera_permissions.test.ts +72 -0
  222. package/src/camera/__tests__/camera_system_focus.test.ts +173 -0
  223. package/src/camera/__tests__/use_smile_id_camera_preview.test.tsx +461 -0
  224. package/src/camera/__tests__/use_smile_id_camera_system.test.ts +103 -0
  225. package/src/camera/__tests__/use_smile_id_frame_stream_hook.test.tsx +229 -0
  226. package/src/camera/camera_defaults.ts +3 -0
  227. package/src/core/exception/__tests__/builder_validation_exceptions.test.ts +81 -0
  228. package/src/core/exception/agent_mode_with_enhanced_liveness_exception.ts +20 -0
  229. package/src/core/exception/capture_validation_exceptions.ts +1 -0
  230. package/src/core/exception/flow_exceptions.test.ts +10 -0
  231. package/src/core/exception/flow_exceptions.ts +3 -2
  232. package/src/core/exception/index.ts +1 -0
  233. package/src/core/exception/missing_job_type_exception.ts +2 -4
  234. package/src/core/exception/use_smile_id_error_code.ts +1 -0
  235. package/src/core/models/__tests__/document_type.test.ts +2 -2
  236. package/src/core/models/__tests__/flow_models.test.ts +26 -0
  237. package/src/core/models/config.ts +22 -0
  238. package/src/core/models/document_type.ts +2 -2
  239. package/src/core/models/global_privacy_control.ts +45 -0
  240. package/src/core/models/network_config.ts +2 -2
  241. package/src/data/api/__tests__/smile_id_api.test.ts +275 -1
  242. package/src/data/api/interceptors/__tests__/credential_header_redaction.test.ts +144 -0
  243. package/src/data/api/interceptors/__tests__/gzip_interceptor.test.ts +83 -0
  244. package/src/data/api/interceptors/smile_auth_interceptor.ts +3 -18
  245. package/src/data/api/smile_id_api.ts +36 -49
  246. package/src/data/compression/__tests__/payload_compressor_real_jpeg.test.ts +6 -2
  247. package/src/data/dsl/__tests__/use_smile_id_network_builder.test.ts +157 -0
  248. package/src/data/dsl/builder/__tests__/config_builders.test.ts +62 -0
  249. package/src/data/dsl/builder/retry_config_builder.ts +6 -6
  250. package/src/data/factory/__tests__/retry_gzip_mac_composition.test.ts +163 -0
  251. package/src/data/factory/__tests__/signed_job_submission_headers.test.ts +1 -1
  252. package/src/data/model/__tests__/token_payload.test.ts +224 -0
  253. package/src/data/model/__tests__/user_details_payload.test.ts +100 -0
  254. package/src/data/model/job_request.ts +27 -12
  255. package/src/data/model/token_payload.ts +182 -0
  256. package/src/data/model/user_details_payload.ts +84 -0
  257. package/src/data/repository/__tests__/network_retries.test.ts +1 -1
  258. package/src/data/repository/__tests__/repository_dispatch.test.ts +366 -0
  259. package/src/data/repository/__tests__/use_smile_id_repository.test.ts +1 -1
  260. package/src/data/security/__tests__/request_canonicalizer.test.ts +132 -0
  261. package/src/data/security/__tests__/signing_crypto.test.ts +203 -0
  262. package/src/data/smile_id_urls.ts +1 -1
  263. package/src/data/util/__tests__/retry_util.test.ts +25 -0
  264. package/src/data/util/__tests__/use_smile_id_token_decoder.test.ts +179 -0
  265. package/src/data/util/retry_util.ts +9 -1
  266. package/src/data/util/use_smile_id_token_decoder.ts +29 -8
  267. package/src/index.ts +6 -4
  268. package/src/l10n/__tests__/use_smile_id_localizations.test.ts +122 -5
  269. package/src/l10n/__tests__/use_smile_id_localizations_provider.test.tsx +112 -0
  270. package/src/l10n/__tests__/use_smile_id_localizations_surface.test.ts +231 -0
  271. package/src/l10n/strings_en.ts +5 -1
  272. package/src/l10n/use_smile_id_localizations.ts +80 -3
  273. package/src/metadata/__tests__/device_orientation_sampling.test.ts +165 -0
  274. package/src/metadata/__tests__/geolocation.test.ts +150 -0
  275. package/src/metadata/__tests__/metadata_configuration_mappers.test.ts +39 -0
  276. package/src/metadata/__tests__/metadata_configuration_objects.test.ts +2 -1
  277. package/src/metadata/__tests__/metadata_device_context.test.ts +3 -3
  278. package/src/metadata/__tests__/metadata_device_os_android.test.ts +18 -0
  279. package/src/metadata/__tests__/metadata_golden_fixture.json +1 -1
  280. package/src/metadata/__tests__/metadata_payload_golden.test.ts +4 -4
  281. package/src/metadata/__tests__/optional_native_modules.test.ts +234 -0
  282. package/src/metadata/__tests__/use_smile_id_metadata.test.ts +1 -1
  283. package/src/metadata/__tests__/use_smile_id_metadata_factory.test.ts +615 -0
  284. package/src/metadata/builder_configuration.ts +6 -0
  285. package/src/metadata/metadata_configuration_mappers.ts +21 -7
  286. package/src/metadata/use_smile_id_metadata_factory.ts +17 -6
  287. package/src/presentation/assets/si_document_green_book_hero_animation.json +1 -4668
  288. package/src/presentation/assets/si_document_hero_animation.json +1 -4799
  289. package/src/presentation/assets/si_document_hero_back_animation.json +1 -2039
  290. package/src/presentation/assets/si_document_passport_hero_animation.json +1 -14491
  291. package/src/presentation/assets/si_ess_all_directions_hero_animation.json +1 -0
  292. package/src/presentation/assets/si_ess_animation_all_directions.json +1 -6589
  293. package/src/presentation/assets/si_selfie_hero_animation.json +1 -1439
  294. package/src/presentation/assets/si_smile_to_capture_animation.json +1 -1439
  295. package/src/presentation/components/__tests__/use_smile_id_content_card.test.tsx +112 -0
  296. package/src/presentation/components/__tests__/use_smile_id_enhanced_smart_selfie_clip.test.tsx +9 -4
  297. package/src/presentation/components/__tests__/use_smile_id_face_oval_image.test.tsx +190 -0
  298. package/src/presentation/components/__tests__/use_smile_id_instructions_hero.test.tsx +44 -0
  299. package/src/presentation/components/__tests__/use_smile_id_learn_more_content.test.tsx +159 -0
  300. package/src/presentation/components/__tests__/use_smile_id_processing_center_indicator.test.tsx +88 -0
  301. package/src/presentation/components/use_smile_id_button.tsx +7 -2
  302. package/src/presentation/components/use_smile_id_enhanced_smart_selfie_clip.tsx +9 -3
  303. package/src/presentation/components/use_smile_id_instructions_hero.tsx +10 -0
  304. package/src/presentation/flow/__tests__/document_flow_navigation.test.ts +3 -3
  305. package/src/presentation/flow/__tests__/flow_navigation_manager.test.ts +372 -1
  306. package/src/presentation/flow/__tests__/use_smile_id_flow.test.tsx +651 -0
  307. package/src/presentation/flow/dsl/__tests__/use_smile_id_builder_component.test.tsx +120 -0
  308. package/src/presentation/flow/dsl/builder/__tests__/config_builder.test.ts +25 -0
  309. package/src/presentation/flow/dsl/builder/config_builder.ts +21 -0
  310. package/src/presentation/flow/dsl/builder/screens_builder.ts +7 -12
  311. package/src/presentation/flow/dsl/use_smile_id_flow_builder.ts +27 -1
  312. package/src/presentation/flow/flow_navigation_manager.ts +108 -93
  313. package/src/presentation/flow/graph/__tests__/screen_renderer.test.tsx +102 -0
  314. package/src/presentation/flow/model/instructions_defaults.ts +1 -1
  315. package/src/presentation/flow/screen/__tests__/orchestrated_capture_screen.test.tsx +836 -0
  316. package/src/presentation/flow/screen/__tests__/orchestrated_consent_screen.test.tsx +165 -0
  317. package/src/presentation/flow/screen/__tests__/orchestrated_instructions_screen.test.tsx +163 -0
  318. package/src/presentation/flow/screen/__tests__/orchestrated_preview_screen.test.tsx +224 -0
  319. package/src/presentation/flow/screen/__tests__/orchestrated_processing_screen.test.tsx +338 -0
  320. package/src/presentation/flow/screen/orchestrated_capture_screen.tsx +18 -3
  321. package/src/presentation/flow/screen/orchestrated_consent_screen.tsx +5 -0
  322. package/src/presentation/flow/screen/orchestrated_preview_screen.tsx +0 -12
  323. package/src/presentation/flow/screen/orchestrated_processing_screen.tsx +42 -5
  324. package/src/presentation/flow/use_smile_id_flow.tsx +63 -12
  325. package/src/presentation/flow/validation/__tests__/flow_validator.test.ts +219 -1
  326. package/src/presentation/flow/validation/__tests__/job_type_validator.test.ts +200 -0
  327. package/src/presentation/flow/validation/flow_validator.ts +85 -57
  328. package/src/presentation/flow/validation/job_type_validator.ts +73 -39
  329. package/src/presentation/flow/validation/user_details_validator.ts +53 -0
  330. package/src/presentation/screen/__tests__/capture_ui_state.test.ts +66 -47
  331. package/src/presentation/screen/__tests__/ess_turn_haptics.test.ts +15 -11
  332. package/src/presentation/screen/__tests__/feedback_copy_table.test.ts +145 -0
  333. package/src/presentation/screen/__tests__/scan_state_to_overlay_state.test.ts +47 -27
  334. package/src/presentation/screen/__tests__/use_smile_id_capture_screen.test.tsx +524 -14
  335. package/src/presentation/screen/__tests__/use_smile_id_document_back_instructions.test.tsx +4 -2
  336. package/src/presentation/screen/__tests__/use_smile_id_permission_screen.test.tsx +68 -0
  337. package/src/presentation/screen/__tests__/use_smile_id_preview_screen.test.tsx +10 -40
  338. package/src/presentation/screen/helpers/__tests__/use_capture_orientation_lock.test.tsx +212 -0
  339. package/src/presentation/screen/helpers/capture_screen_helpers.ts +1 -0
  340. package/src/presentation/screen/helpers/capture_ui_state.ts +27 -27
  341. package/src/presentation/screen/helpers/ess_turn_haptics.ts +9 -9
  342. package/src/presentation/screen/helpers/scan_state_to_overlay_state.ts +13 -13
  343. package/src/presentation/screen/helpers/use_capture_orientation_lock.ts +69 -7
  344. package/src/presentation/screen/use_smile_id_capture_screen.tsx +107 -28
  345. package/src/presentation/screen/use_smile_id_consent_screen.tsx +16 -5
  346. package/src/presentation/screen/use_smile_id_document_back_instructions.tsx +14 -23
  347. package/src/presentation/screen/use_smile_id_document_preview_screen.tsx +1 -1
  348. package/src/presentation/screen/use_smile_id_preview_screen.tsx +13 -45
  349. package/src/presentation/screen/use_smile_id_processing_screen.tsx +1 -1
  350. package/src/presentation/theme/__tests__/use_use_smile_id_fonts.test.tsx +166 -0
  351. package/src/presentation/utils/__tests__/locale_utils.test.ts +46 -5
  352. package/src/presentation/utils/locale_utils.ts +13 -4
  353. package/src/testing/__tests__/fake_face_analyzer.test.ts +42 -0
  354. package/src/testing/__tests__/scenario_expectations.test.ts +110 -0
  355. package/src/testing/__tests__/scenario_loader.test.ts +64 -0
  356. package/src/testing/fake_face_analyzer.ts +82 -0
  357. package/src/testing/index.ts +15 -0
  358. package/src/testing/scenario_expectations.ts +87 -0
  359. package/src/testing/scenario_loader.ts +83 -0
  360. package/src/testing/scripted_scan_results.ts +66 -0
  361. package/dist/presentation/components/use_smile_id_face_silhouette_overlay.d.ts +0 -15
  362. package/dist/presentation/components/use_smile_id_face_silhouette_overlay.d.ts.map +0 -1
  363. package/dist/presentation/components/use_smile_id_face_silhouette_overlay.js +0 -19
  364. package/dist/presentation/components/use_smile_id_face_silhouette_overlay.js.map +0 -1
  365. package/src/presentation/components/use_smile_id_face_silhouette_overlay.tsx +0 -27
@@ -18,6 +18,12 @@ import {
18
18
  MissingCaptureForPreviewException,
19
19
  } from "../../../core/exception/screen_config_validation_exceptions";
20
20
  import { IssueSeverity } from "../../../core/exception/issue_severity";
21
+ import {
22
+ tokenConsentMissingSubfields,
23
+ bindsRequiredUserDetails,
24
+ type TokenPayload,
25
+ } from "../../../data/model/token_payload";
26
+ import { missingUserDetailsFieldIssues } from "./user_details_validator";
21
27
  import type { ValidationIssue } from "./validation_state";
22
28
 
23
29
  /**
@@ -66,6 +72,12 @@ export type JobTypeValidatorInput = {
66
72
  | EnhancedDocumentVerificationParams
67
73
  | undefined;
68
74
  readonly userDetails?: UserDetails | undefined;
75
+ /**
76
+ * User-detail/consent bindings decoded from the JWT `payload` claim.
77
+ * `undefined` (no token, offline mode, legacy token) keeps every rule
78
+ * exactly as strict as before token support existed.
79
+ */
80
+ readonly tokenPayload?: TokenPayload | undefined;
69
81
  };
70
82
 
71
83
  /**
@@ -93,9 +105,13 @@ function jobTypeName(jobType: JobType): string {
93
105
  }
94
106
 
95
107
  /**
96
- * Consent rule: exactly one form of consent is required — either a
97
- * Consent screen or pre-supplied `consentInformation`, never both and
98
- * never neither.
108
+ * Consent rule: token consent always wins. A token that carries a
109
+ * consent binding must carry all four subfields — the local sources
110
+ * are then ignored (the consent screen is skipped and any preset is
111
+ * not sent), so an incomplete binding is a build-time error rather
112
+ * than a silent fallback. Without a token binding, exactly one local
113
+ * form of consent is required — either a Consent screen or
114
+ * pre-supplied `consentInformation`, never both.
99
115
  */
100
116
  function appendConsentRule(
101
117
  jobType: JobType,
@@ -104,6 +120,33 @@ function appendConsentRule(
104
120
  ): void {
105
121
  const hasConsentScreen = input.steps.some((s) => s.kind === "consent");
106
122
  const hasConsentInformation = input.consentInformation !== undefined;
123
+ if (hasConsentScreen && hasConsentInformation) {
124
+ issues.push(
125
+ InvalidJobTypeScreenConfigException.forJob({
126
+ jobType,
127
+ reason:
128
+ "must not include both a Consent screen and a pre-supplied consentInformation — use one or the other",
129
+ suggestedFix:
130
+ "Remove the consent { } screen if supplying consentInformation, or clear consentInformation if using the consent screen",
131
+ }),
132
+ );
133
+ return;
134
+ }
135
+ const tokenConsent = input.tokenPayload?.consent;
136
+ if (tokenConsent !== undefined) {
137
+ const missing = tokenConsentMissingSubfields(tokenConsent);
138
+ if (missing.length > 0) {
139
+ issues.push(
140
+ InvalidJobTypeScreenConfigException.forJob({
141
+ jobType,
142
+ reason: `the token's consent binding is incomplete — missing: ${missing.join(", ")}`,
143
+ suggestedFix:
144
+ "Bind all four consent fields when minting the token at /v3/token, or bind none and collect consent in the app",
145
+ }),
146
+ );
147
+ }
148
+ return;
149
+ }
107
150
  if (!hasConsentScreen && !hasConsentInformation) {
108
151
  issues.push(
109
152
  InvalidJobTypeScreenConfigException.forJob({
@@ -114,17 +157,36 @@ function appendConsentRule(
114
157
  "Add a consent { } screen to your flow, or supply consentInformation via the builder",
115
158
  }),
116
159
  );
117
- } else if (hasConsentScreen && hasConsentInformation) {
160
+ }
161
+ }
162
+
163
+ /**
164
+ * userDetails rule: the token and the builder fill the requirement
165
+ * together — token-bound fields (see `bindsRequiredUserDetails`) count
166
+ * as supplied and the builder must cover the rest. With no token
167
+ * binding and no builder value the legacy blanket error fires; with a
168
+ * partial token binding the per-field errors name exactly what neither
169
+ * side provided.
170
+ */
171
+ function appendUserDetailsRequiredRule(
172
+ jobType: JobType,
173
+ input: JobTypeValidatorInput,
174
+ issues: ValidationIssue[],
175
+ ): void {
176
+ if (input.userDetails !== undefined) return;
177
+ if (bindsRequiredUserDetails(input.tokenPayload)) return;
178
+ if (input.tokenPayload === undefined) {
118
179
  issues.push(
119
180
  InvalidJobTypeScreenConfigException.forJob({
120
181
  jobType,
121
- reason:
122
- "must not include both a Consent screen and a pre-supplied consentInformation — use one or the other",
182
+ reason: `userDetails is required for ${jobTypeName(jobType)} jobs`,
123
183
  suggestedFix:
124
- "Remove the consent { } screen if supplying consentInformation, or clear consentInformation if using the consent screen",
184
+ "Set builder.userDetails with the end user PII before building",
125
185
  }),
126
186
  );
187
+ return;
127
188
  }
189
+ issues.push(...missingUserDetailsFieldIssues(undefined, input.tokenPayload));
128
190
  }
129
191
 
130
192
  /**
@@ -381,16 +443,7 @@ export class SelfieJobTypeValidator implements JobTypeValidator {
381
443
  );
382
444
  }
383
445
 
384
- if (input.userDetails === undefined) {
385
- issues.push(
386
- InvalidJobTypeScreenConfigException.forJob({
387
- jobType: this.jobType,
388
- reason: `userDetails is required for ${jobTypeName(this.jobType)} jobs`,
389
- suggestedFix:
390
- "Set builder.userDetails with the end user PII before building",
391
- }),
392
- );
393
- }
446
+ appendUserDetailsRequiredRule(this.jobType, input, issues);
394
447
  }
395
448
  }
396
449
 
@@ -477,16 +530,7 @@ export class DocumentJobTypeValidator implements JobTypeValidator {
477
530
  );
478
531
  }
479
532
 
480
- if (input.userDetails === undefined) {
481
- issues.push(
482
- InvalidJobTypeScreenConfigException.forJob({
483
- jobType: this.jobType,
484
- reason: `userDetails is required for ${jobTypeName(this.jobType)} jobs`,
485
- suggestedFix:
486
- "Set builder.userDetails with the end user PII before building",
487
- }),
488
- );
489
- }
533
+ appendUserDetailsRequiredRule(this.jobType, input, issues);
490
534
  }
491
535
 
492
536
  /**
@@ -578,18 +622,8 @@ export class NonCaptureJobTypeValidator implements JobTypeValidator {
578
622
  );
579
623
  }
580
624
 
581
- if (
582
- this.jobType === JobType.enhancedKyc &&
583
- input.userDetails === undefined
584
- ) {
585
- issues.push(
586
- InvalidJobTypeScreenConfigException.forJob({
587
- jobType: this.jobType,
588
- reason: "userDetails is required for EnhancedKyc jobs",
589
- suggestedFix:
590
- "Set builder.userDetails with the end user PII before building",
591
- }),
592
- );
625
+ if (this.jobType === JobType.enhancedKyc) {
626
+ appendUserDetailsRequiredRule(this.jobType, input, issues);
593
627
  }
594
628
  }
595
629
  }
@@ -0,0 +1,53 @@
1
+ import type { UserDetails } from "../../../core/models/params";
2
+ import { InvalidFieldValueException } from "../../../core/exception/job_validation_exceptions";
3
+ import type { TokenPayload } from "../../../data/model/token_payload";
4
+ import type { ValidationIssue } from "./validation_state";
5
+
6
+ /**
7
+ * Field-union rule shared by the content validator and the job-type required
8
+ * rule: a field is covered when the token binds it or the builder supplies it.
9
+ */
10
+ export function missingUserDetailsFieldIssues(
11
+ userDetails: UserDetails | undefined,
12
+ tokenPayload: TokenPayload | undefined,
13
+ ): ValidationIssue[] {
14
+ const issues: ValidationIssue[] = [];
15
+ const fieldReason =
16
+ tokenPayload === undefined
17
+ ? "must not be blank"
18
+ : "not bound by the token and not supplied on the builder";
19
+ const tokenBindsField = {
20
+ givenNames: tokenPayload?.hasGivenNames === true,
21
+ lastName: tokenPayload?.hasLastName === true,
22
+ } as const;
23
+ for (const field of ["givenNames", "lastName"] as const) {
24
+ if (tokenBindsField[field]) continue;
25
+ const value = userDetails?.[field];
26
+ if (!value || !value.trim()) {
27
+ issues.push(
28
+ new InvalidFieldValueException({
29
+ fieldName: `userDetails.${field}`,
30
+ reason: fieldReason,
31
+ }),
32
+ );
33
+ }
34
+ }
35
+ // email and phoneNumber are each optional, but one must come from the builder or the token.
36
+ const hasEmail = !!userDetails?.email && userDetails.email.trim().length > 0;
37
+ const hasPhone =
38
+ !!userDetails?.phoneNumber && userDetails.phoneNumber.trim().length > 0;
39
+ const tokenHasContact =
40
+ tokenPayload?.hasEmail === true || tokenPayload?.hasPhoneNumber === true;
41
+ if (!hasEmail && !hasPhone && !tokenHasContact) {
42
+ issues.push(
43
+ new InvalidFieldValueException({
44
+ fieldName: "userDetails",
45
+ reason:
46
+ tokenPayload === undefined
47
+ ? "at least one of email or phoneNumber must be non blank"
48
+ : "at least one contact field must be bound by the token or supplied on the builder",
49
+ }),
50
+ );
51
+ }
52
+ return issues;
53
+ }
@@ -1,6 +1,6 @@
1
1
  import { describe, expect, it } from "vitest";
2
- import type { ScanState } from "@smileid/usesmileid_bridge";
3
- import { ScanStateType } from "@smileid/usesmileid_bridge";
2
+ import type { UseSmileIDScanState } from "@smileid/usesmileid_bridge";
3
+ import { UseSmileIDScanStateType } from "@smileid/usesmileid_bridge";
4
4
  import { CaptureType } from "../../../core/models/ml_config";
5
5
  import { UseSmileIDOverlayState } from "../../state/use_smile_id_overlay_state";
6
6
  import {
@@ -16,7 +16,10 @@ import {
16
16
 
17
17
  describe("mapSelfieUiState — standard flow", () => {
18
18
  it("maps initial to the standard primer", () => {
19
- const ui = mapSelfieUiState({ type: ScanStateType.Initial }, false);
19
+ const ui = mapSelfieUiState(
20
+ { type: UseSmileIDScanStateType.Initial },
21
+ false,
22
+ );
20
23
  expect(ui.overlayState).toBe(UseSmileIDOverlayState.INSTRUCTION);
21
24
  expect(ui.feedbackKey).toBe("si_capture_initial_instruction");
22
25
  expect(ui.captureProgress).toBe(0);
@@ -26,7 +29,7 @@ describe("mapSelfieUiState — standard flow", () => {
26
29
  it("passes the analyzer feedback key through on found", () => {
27
30
  const ui = mapSelfieUiState(
28
31
  {
29
- type: ScanStateType.Found,
32
+ type: UseSmileIDScanStateType.Found,
30
33
  feedback: "si_capture_move_left",
31
34
  captureProgress: 0.4,
32
35
  },
@@ -40,10 +43,13 @@ describe("mapSelfieUiState — standard flow", () => {
40
43
  it("shows the in-capture copy on found-default and satisfied", () => {
41
44
  // All checks passing means frames are being collected — the
42
45
  // guidance reads "Capturing…", never the pre-start instruction.
43
- const found = mapSelfieUiState({ type: ScanStateType.Found }, false);
46
+ const found = mapSelfieUiState(
47
+ { type: UseSmileIDScanStateType.Found },
48
+ false,
49
+ );
44
50
  expect(found.feedbackKey).toBe("si_capturing");
45
51
  const satisfied = mapSelfieUiState(
46
- { type: ScanStateType.Satisfied },
52
+ { type: UseSmileIDScanStateType.Satisfied },
47
53
  false,
48
54
  );
49
55
  expect(satisfied.feedbackKey).toBe("si_capturing");
@@ -54,14 +60,20 @@ describe("mapSelfieUiState — standard flow", () => {
54
60
  });
55
61
 
56
62
  it("maps finished through the shared terminal snapshot", () => {
57
- const ui = mapSelfieUiState({ type: ScanStateType.Finished }, false);
63
+ const ui = mapSelfieUiState(
64
+ { type: UseSmileIDScanStateType.Finished },
65
+ false,
66
+ );
58
67
  expect(ui).toEqual(scannedUiState(false));
59
68
  expect(ui.feedbackKey).toBe("si_selfie_capture_complete");
60
69
  expect(ui.captureProgress).toBe(1);
61
70
  });
62
71
 
63
72
  it("maps timeout to idle with the timeout copy", () => {
64
- const ui = mapSelfieUiState({ type: ScanStateType.Timeout }, false);
73
+ const ui = mapSelfieUiState(
74
+ { type: UseSmileIDScanStateType.Timeout },
75
+ false,
76
+ );
65
77
  expect(ui.overlayState).toBe(UseSmileIDOverlayState.IDLE);
66
78
  expect(ui.feedbackKey).toBe("si_capture_timeout");
67
79
  });
@@ -69,15 +81,18 @@ describe("mapSelfieUiState — standard flow", () => {
69
81
 
70
82
  describe("mapSelfieUiState — Enhanced Smart Selfie", () => {
71
83
  it("swaps the initial primer for the head-turn instruction", () => {
72
- const ui = mapSelfieUiState({ type: ScanStateType.Initial }, true);
84
+ const ui = mapSelfieUiState(
85
+ { type: UseSmileIDScanStateType.Initial },
86
+ true,
87
+ );
73
88
  expect(ui.feedbackKey).toBe("si_ess_capture_initial_instruction");
74
89
  });
75
90
 
76
91
  it("shows hold-still through active capture (found-default / satisfied)", () => {
77
92
  for (const scanState of [
78
- { type: ScanStateType.Found },
79
- { type: ScanStateType.Satisfied },
80
- ] satisfies ScanState[]) {
93
+ { type: UseSmileIDScanStateType.Found },
94
+ { type: UseSmileIDScanStateType.Satisfied },
95
+ ] satisfies UseSmileIDScanState[]) {
81
96
  expect(mapSelfieUiState(scanState, true).feedbackKey).toBe(
82
97
  "si_ess_hold_still",
83
98
  );
@@ -85,24 +100,25 @@ describe("mapSelfieUiState — Enhanced Smart Selfie", () => {
85
100
  // Finished shows the completion copy in both modes; only the oval
86
101
  // fill differs under Enhanced Smart Selfie.
87
102
  expect(
88
- mapSelfieUiState({ type: ScanStateType.Finished }, true).feedbackKey,
103
+ mapSelfieUiState({ type: UseSmileIDScanStateType.Finished }, true)
104
+ .feedbackKey,
89
105
  ).toBe("si_selfie_capture_complete");
90
106
  });
91
107
 
92
108
  it("zeroes captureProgress everywhere — the oval never fills under ESS", () => {
93
109
  for (const scanState of [
94
- { type: ScanStateType.Found, captureProgress: 0.6 },
95
- { type: ScanStateType.Satisfied },
96
- { type: ScanStateType.Finished },
97
- { type: ScanStateType.HeadTurn, currentDirection: "left" },
98
- ] satisfies ScanState[]) {
110
+ { type: UseSmileIDScanStateType.Found, captureProgress: 0.6 },
111
+ { type: UseSmileIDScanStateType.Satisfied },
112
+ { type: UseSmileIDScanStateType.Finished },
113
+ { type: UseSmileIDScanStateType.HeadTurn, currentDirection: "left" },
114
+ ] satisfies UseSmileIDScanState[]) {
99
115
  expect(mapSelfieUiState(scanState, true).captureProgress).toBe(0);
100
116
  }
101
117
  });
102
118
 
103
119
  it("keeps explicit guidance keys ahead of hold-still during found", () => {
104
120
  const ui = mapSelfieUiState(
105
- { type: ScanStateType.Found, feedback: "si_capture_too_close" },
121
+ { type: UseSmileIDScanStateType.Found, feedback: "si_capture_too_close" },
106
122
  true,
107
123
  );
108
124
  expect(ui.feedbackKey).toBe("si_capture_too_close");
@@ -116,7 +132,7 @@ describe("mapSelfieUiState — Enhanced Smart Selfie", () => {
116
132
  ] as const;
117
133
  for (const [direction, expectedKey] of directions) {
118
134
  const ui = mapSelfieUiState(
119
- { type: ScanStateType.HeadTurn, currentDirection: direction },
135
+ { type: UseSmileIDScanStateType.HeadTurn, currentDirection: direction },
120
136
  true,
121
137
  );
122
138
  expect(ui.overlayState).toBe(UseSmileIDOverlayState.HEAD_TURN);
@@ -127,7 +143,10 @@ describe("mapSelfieUiState — Enhanced Smart Selfie", () => {
127
143
  });
128
144
 
129
145
  it("falls back to hold-steady when headTurn arrives without a direction", () => {
130
- const ui = mapSelfieUiState({ type: ScanStateType.HeadTurn }, true);
146
+ const ui = mapSelfieUiState(
147
+ { type: UseSmileIDScanStateType.HeadTurn },
148
+ true,
149
+ );
131
150
  expect(ui.feedbackKey).toBe("si_capture_hold_steady");
132
151
  expect(ui.animationDirection).toBeNull();
133
152
  });
@@ -135,7 +154,7 @@ describe("mapSelfieUiState — Enhanced Smart Selfie", () => {
135
154
  it("threads poseMatched into the head-turn state (drives grey→green)", () => {
136
155
  const matched = mapSelfieUiState(
137
156
  {
138
- type: ScanStateType.HeadTurn,
157
+ type: UseSmileIDScanStateType.HeadTurn,
139
158
  currentDirection: "left",
140
159
  poseMatched: true,
141
160
  },
@@ -145,7 +164,7 @@ describe("mapSelfieUiState — Enhanced Smart Selfie", () => {
145
164
  expect(matched.poseMatched).toBe(true);
146
165
 
147
166
  const pending = mapSelfieUiState(
148
- { type: ScanStateType.HeadTurn, currentDirection: "left" },
167
+ { type: UseSmileIDScanStateType.HeadTurn, currentDirection: "left" },
149
168
  true,
150
169
  );
151
170
  expect(pending.poseMatched).toBe(false);
@@ -159,7 +178,7 @@ describe("mapSelfieUiState — Enhanced Smart Selfie", () => {
159
178
  ] as const) {
160
179
  const ui = mapSelfieUiState(
161
180
  {
162
- type: ScanStateType.HeadTurn,
181
+ type: UseSmileIDScanStateType.HeadTurn,
163
182
  currentDirection: "left",
164
183
  feedback,
165
184
  poseMatched: true,
@@ -182,7 +201,7 @@ describe("mapSelfieUiState — Enhanced Smart Selfie", () => {
182
201
  ] as const) {
183
202
  const ui = mapSelfieUiState(
184
203
  {
185
- type: ScanStateType.HeadTurn,
204
+ type: UseSmileIDScanStateType.HeadTurn,
186
205
  currentDirection: "up",
187
206
  feedback,
188
207
  poseMatched: true,
@@ -203,7 +222,7 @@ describe("mapSelfieUiState — Enhanced Smart Selfie", () => {
203
222
  ] as const) {
204
223
  const ui = mapSelfieUiState(
205
224
  {
206
- type: ScanStateType.HeadTurn,
225
+ type: UseSmileIDScanStateType.HeadTurn,
207
226
  currentDirection: "right",
208
227
  feedback,
209
228
  poseMatched: true,
@@ -241,7 +260,7 @@ describe("withEnhancedLivenessPolicy", () => {
241
260
 
242
261
  describe("document mapping", () => {
243
262
  it("maps finished through the shared document terminal snapshot", () => {
244
- const ui = mapDocumentUiState({ type: ScanStateType.Finished });
263
+ const ui = mapDocumentUiState({ type: UseSmileIDScanStateType.Finished });
245
264
  expect(ui).toEqual(scannedDocumentUiState());
246
265
  expect(ui.feedbackKey).toBe("si_document_capture_complete");
247
266
  expect(ui.captureProgress).toBe(1);
@@ -249,7 +268,7 @@ describe("document mapping", () => {
249
268
 
250
269
  it("passes document feedback keys through on found", () => {
251
270
  const ui = mapDocumentUiState({
252
- type: ScanStateType.Found,
271
+ type: UseSmileIDScanStateType.Found,
253
272
  feedback: "si_document_too_far",
254
273
  });
255
274
  expect(ui.overlayState).toBe(UseSmileIDOverlayState.DOCUMENT_TOO_FAR);
@@ -257,7 +276,7 @@ describe("document mapping", () => {
257
276
  });
258
277
 
259
278
  it("treats a degenerate headTurn as the pre-capture instruction", () => {
260
- const ui = mapDocumentUiState({ type: ScanStateType.HeadTurn });
279
+ const ui = mapDocumentUiState({ type: UseSmileIDScanStateType.HeadTurn });
261
280
  expect(ui.overlayState).toBe(UseSmileIDOverlayState.INSTRUCTION);
262
281
  expect(ui.feedbackKey).toBe("si_document_initial_instruction");
263
282
  });
@@ -287,14 +306,14 @@ describe("mapCaptureUiState dispatch", () => {
287
306
  it("routes by capture type", () => {
288
307
  expect(
289
308
  mapCaptureUiState(
290
- { type: ScanStateType.Initial },
309
+ { type: UseSmileIDScanStateType.Initial },
291
310
  CaptureType.selfie,
292
311
  true,
293
312
  ).feedbackKey,
294
313
  ).toBe("si_ess_capture_initial_instruction");
295
314
  expect(
296
315
  mapCaptureUiState(
297
- { type: ScanStateType.Initial },
316
+ { type: UseSmileIDScanStateType.Initial },
298
317
  CaptureType.document,
299
318
  // ESS is a selfie-only concept; the flag must not leak into
300
319
  // the document mapping.
@@ -308,8 +327,8 @@ describe("isSessionBoundary", () => {
308
327
  it("returns true for unsatisfied → found (leaving unsatisfied is a boundary)", () => {
309
328
  expect(
310
329
  isSessionBoundary(
311
- { type: ScanStateType.Unsatisfied },
312
- { type: ScanStateType.Found },
330
+ { type: UseSmileIDScanStateType.Unsatisfied },
331
+ { type: UseSmileIDScanStateType.Found },
313
332
  ),
314
333
  ).toBe(true);
315
334
  });
@@ -317,8 +336,8 @@ describe("isSessionBoundary", () => {
317
336
  it("returns true for unsatisfied → initial", () => {
318
337
  expect(
319
338
  isSessionBoundary(
320
- { type: ScanStateType.Unsatisfied },
321
- { type: ScanStateType.Initial },
339
+ { type: UseSmileIDScanStateType.Unsatisfied },
340
+ { type: UseSmileIDScanStateType.Initial },
322
341
  ),
323
342
  ).toBe(true);
324
343
  });
@@ -326,8 +345,8 @@ describe("isSessionBoundary", () => {
326
345
  it("returns true for timeout → initial (session restart)", () => {
327
346
  expect(
328
347
  isSessionBoundary(
329
- { type: ScanStateType.Timeout },
330
- { type: ScanStateType.Initial },
348
+ { type: UseSmileIDScanStateType.Timeout },
349
+ { type: UseSmileIDScanStateType.Initial },
331
350
  ),
332
351
  ).toBe(true);
333
352
  });
@@ -335,8 +354,8 @@ describe("isSessionBoundary", () => {
335
354
  it("returns true for finished → initial (session restart)", () => {
336
355
  expect(
337
356
  isSessionBoundary(
338
- { type: ScanStateType.Finished },
339
- { type: ScanStateType.Initial },
357
+ { type: UseSmileIDScanStateType.Finished },
358
+ { type: UseSmileIDScanStateType.Initial },
340
359
  ),
341
360
  ).toBe(true);
342
361
  });
@@ -344,8 +363,8 @@ describe("isSessionBoundary", () => {
344
363
  it("returns false for found → unsatisfied (entering unsatisfied, not leaving)", () => {
345
364
  expect(
346
365
  isSessionBoundary(
347
- { type: ScanStateType.Found },
348
- { type: ScanStateType.Unsatisfied },
366
+ { type: UseSmileIDScanStateType.Found },
367
+ { type: UseSmileIDScanStateType.Unsatisfied },
349
368
  ),
350
369
  ).toBe(false);
351
370
  });
@@ -353,8 +372,8 @@ describe("isSessionBoundary", () => {
353
372
  it("returns false for same-type transition (found → found)", () => {
354
373
  expect(
355
374
  isSessionBoundary(
356
- { type: ScanStateType.Found },
357
- { type: ScanStateType.Found },
375
+ { type: UseSmileIDScanStateType.Found },
376
+ { type: UseSmileIDScanStateType.Found },
358
377
  ),
359
378
  ).toBe(false);
360
379
  });
@@ -362,8 +381,8 @@ describe("isSessionBoundary", () => {
362
381
  it("returns false for initial → found (normal forward progression)", () => {
363
382
  expect(
364
383
  isSessionBoundary(
365
- { type: ScanStateType.Initial },
366
- { type: ScanStateType.Found },
384
+ { type: UseSmileIDScanStateType.Initial },
385
+ { type: UseSmileIDScanStateType.Found },
367
386
  ),
368
387
  ).toBe(false);
369
388
  });
@@ -371,8 +390,8 @@ describe("isSessionBoundary", () => {
371
390
  it("returns false for timeout → found (only initial restarts after a terminal state)", () => {
372
391
  expect(
373
392
  isSessionBoundary(
374
- { type: ScanStateType.Timeout },
375
- { type: ScanStateType.Found },
393
+ { type: UseSmileIDScanStateType.Timeout },
394
+ { type: UseSmileIDScanStateType.Found },
376
395
  ),
377
396
  ).toBe(false);
378
397
  });
@@ -1,16 +1,16 @@
1
1
  import { describe, expect, it, vi, beforeEach } from "vitest";
2
2
  import * as Haptics from "expo-haptics";
3
- import type { ScanState } from "@smileid/usesmileid_bridge";
4
- import { ScanStateType } from "@smileid/usesmileid_bridge";
3
+ import type { UseSmileIDScanState } from "@smileid/usesmileid_bridge";
4
+ import { UseSmileIDScanStateType } from "@smileid/usesmileid_bridge";
5
5
  import {
6
6
  essTurnHaptic,
7
7
  triggerEssTurnHaptic,
8
8
  } from "../helpers/ess_turn_haptics";
9
9
 
10
- const headTurn = (direction?: "left" | "right" | "up"): ScanState =>
10
+ const headTurn = (direction?: "left" | "right" | "up"): UseSmileIDScanState =>
11
11
  direction === undefined
12
- ? { type: ScanStateType.HeadTurn }
13
- : { type: ScanStateType.HeadTurn, currentDirection: direction };
12
+ ? { type: UseSmileIDScanStateType.HeadTurn }
13
+ : { type: UseSmileIDScanStateType.HeadTurn, currentDirection: direction };
14
14
 
15
15
  describe("essTurnHaptic", () => {
16
16
  it("fires intermediate when the requested direction advances", () => {
@@ -24,9 +24,9 @@ describe("essTurnHaptic", () => {
24
24
 
25
25
  it("fires final when leaving the head-turn phase toward capture", () => {
26
26
  for (const next of [
27
- ScanStateType.Found,
28
- ScanStateType.Satisfied,
29
- ScanStateType.Finished,
27
+ UseSmileIDScanStateType.Found,
28
+ UseSmileIDScanStateType.Satisfied,
29
+ UseSmileIDScanStateType.Finished,
30
30
  ] as const) {
31
31
  expect(essTurnHaptic(headTurn("up"), { type: next })).toBe("final");
32
32
  }
@@ -34,10 +34,14 @@ describe("essTurnHaptic", () => {
34
34
 
35
35
  it("never fires on a reset (head turn abandoned to initial / timeout)", () => {
36
36
  expect(
37
- essTurnHaptic(headTurn("left"), { type: ScanStateType.Initial }),
37
+ essTurnHaptic(headTurn("left"), {
38
+ type: UseSmileIDScanStateType.Initial,
39
+ }),
38
40
  ).toBeNull();
39
41
  expect(
40
- essTurnHaptic(headTurn("left"), { type: ScanStateType.Timeout }),
42
+ essTurnHaptic(headTurn("left"), {
43
+ type: UseSmileIDScanStateType.Timeout,
44
+ }),
41
45
  ).toBeNull();
42
46
  });
43
47
 
@@ -48,7 +52,7 @@ describe("essTurnHaptic", () => {
48
52
  it("does not fire when the previous state was not a directed head turn", () => {
49
53
  // Entering a head turn is not completing one.
50
54
  expect(
51
- essTurnHaptic({ type: ScanStateType.Found }, headTurn("left")),
55
+ essTurnHaptic({ type: UseSmileIDScanStateType.Found }, headTurn("left")),
52
56
  ).toBeNull();
53
57
  // A head turn with no direction yet has nothing to complete.
54
58
  expect(essTurnHaptic(headTurn(), headTurn("left"))).toBeNull();