@velion-la/onboarding-sdk-react-native 1.0.0-beta.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.
- package/CHANGELOG.md +66 -0
- package/LICENSE +12 -0
- package/README.md +803 -0
- package/lib/commonjs/camera/AddressSearchBar.js +304 -0
- package/lib/commonjs/camera/AddressSearchBar.js.map +1 -0
- package/lib/commonjs/camera/DocumentCapture.js +505 -0
- package/lib/commonjs/camera/DocumentCapture.js.map +1 -0
- package/lib/commonjs/camera/LivenessCamera.js +534 -0
- package/lib/commonjs/camera/LivenessCamera.js.map +1 -0
- package/lib/commonjs/camera/MapAddressPicker.js +341 -0
- package/lib/commonjs/camera/MapAddressPicker.js.map +1 -0
- package/lib/commonjs/core/VelionOnboarding.js +815 -0
- package/lib/commonjs/core/VelionOnboarding.js.map +1 -0
- package/lib/commonjs/core/sessionDeclinedCopy.js +56 -0
- package/lib/commonjs/core/sessionDeclinedCopy.js.map +1 -0
- package/lib/commonjs/core/sessionStateMapper.js +137 -0
- package/lib/commonjs/core/sessionStateMapper.js.map +1 -0
- package/lib/commonjs/core/sseReasonMessages.js +450 -0
- package/lib/commonjs/core/sseReasonMessages.js.map +1 -0
- package/lib/commonjs/data/iso3166Alpha2Codes.json +1 -0
- package/lib/commonjs/data/iso3166CountryNames.json +251 -0
- package/lib/commonjs/i18n/index.js +30 -0
- package/lib/commonjs/i18n/index.js.map +1 -0
- package/lib/commonjs/i18n/strings/en.js +261 -0
- package/lib/commonjs/i18n/strings/en.js.map +1 -0
- package/lib/commonjs/i18n/strings/es.js +266 -0
- package/lib/commonjs/i18n/strings/es.js.map +1 -0
- package/lib/commonjs/index.js +213 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/package.json +1 -0
- package/lib/commonjs/steps/AddressInfoStep.js +650 -0
- package/lib/commonjs/steps/AddressInfoStep.js.map +1 -0
- package/lib/commonjs/steps/DocumentsOcrStep.js +397 -0
- package/lib/commonjs/steps/DocumentsOcrStep.js.map +1 -0
- package/lib/commonjs/steps/EmailContactStep.js +145 -0
- package/lib/commonjs/steps/EmailContactStep.js.map +1 -0
- package/lib/commonjs/steps/EmailOtpStep.js +220 -0
- package/lib/commonjs/steps/EmailOtpStep.js.map +1 -0
- package/lib/commonjs/steps/FaceMatchStep.js +166 -0
- package/lib/commonjs/steps/FaceMatchStep.js.map +1 -0
- package/lib/commonjs/steps/FingerprintStep.js +92 -0
- package/lib/commonjs/steps/FingerprintStep.js.map +1 -0
- package/lib/commonjs/steps/HumanBasicInfoStep.js +243 -0
- package/lib/commonjs/steps/HumanBasicInfoStep.js.map +1 -0
- package/lib/commonjs/steps/HumanExtendedInfoStep.js +268 -0
- package/lib/commonjs/steps/HumanExtendedInfoStep.js.map +1 -0
- package/lib/commonjs/steps/LegalBasicInfoStep.js +188 -0
- package/lib/commonjs/steps/LegalBasicInfoStep.js.map +1 -0
- package/lib/commonjs/steps/LegalExtendedInfoStep.js +166 -0
- package/lib/commonjs/steps/LegalExtendedInfoStep.js.map +1 -0
- package/lib/commonjs/steps/LivenessMatchStep.js +707 -0
- package/lib/commonjs/steps/LivenessMatchStep.js.map +1 -0
- package/lib/commonjs/steps/PhoneContactStep.js +146 -0
- package/lib/commonjs/steps/PhoneContactStep.js.map +1 -0
- package/lib/commonjs/steps/PhoneOtpStep.js +219 -0
- package/lib/commonjs/steps/PhoneOtpStep.js.map +1 -0
- package/lib/commonjs/steps/SwornDeclarationStep.js +196 -0
- package/lib/commonjs/steps/SwornDeclarationStep.js.map +1 -0
- package/lib/commonjs/steps/TaxInfoStep.js +244 -0
- package/lib/commonjs/steps/TaxInfoStep.js.map +1 -0
- package/lib/commonjs/steps/TermsAndConditionsStep.js +238 -0
- package/lib/commonjs/steps/TermsAndConditionsStep.js.map +1 -0
- package/lib/commonjs/steps/_shared.js +40 -0
- package/lib/commonjs/steps/_shared.js.map +1 -0
- package/lib/commonjs/steps/types.js +6 -0
- package/lib/commonjs/steps/types.js.map +1 -0
- package/lib/commonjs/transport/api.js +176 -0
- package/lib/commonjs/transport/api.js.map +1 -0
- package/lib/commonjs/transport/irisWebSocket.js +121 -0
- package/lib/commonjs/transport/irisWebSocket.js.map +1 -0
- package/lib/commonjs/transport/secureUrl.js +50 -0
- package/lib/commonjs/transport/secureUrl.js.map +1 -0
- package/lib/commonjs/transport/sse.js +248 -0
- package/lib/commonjs/transport/sse.js.map +1 -0
- package/lib/commonjs/types/index.js +391 -0
- package/lib/commonjs/types/index.js.map +1 -0
- package/lib/commonjs/ui/MapFallbackBoundary.js +42 -0
- package/lib/commonjs/ui/MapFallbackBoundary.js.map +1 -0
- package/lib/commonjs/ui/StepShell.js +118 -0
- package/lib/commonjs/ui/StepShell.js.map +1 -0
- package/lib/commonjs/ui/VelionOnboardingScreen.js +217 -0
- package/lib/commonjs/ui/VelionOnboardingScreen.js.map +1 -0
- package/lib/commonjs/ui/forms/index.js +38 -0
- package/lib/commonjs/ui/forms/index.js.map +1 -0
- package/lib/commonjs/ui/forms/useInlineValidation.js +88 -0
- package/lib/commonjs/ui/forms/useInlineValidation.js.map +1 -0
- package/lib/commonjs/ui/forms/validators.js +34 -0
- package/lib/commonjs/ui/forms/validators.js.map +1 -0
- package/lib/commonjs/ui/icons/HomeHeartIcon.js +38 -0
- package/lib/commonjs/ui/icons/HomeHeartIcon.js.map +1 -0
- package/lib/commonjs/ui/icons/StepIcon.js +59 -0
- package/lib/commonjs/ui/icons/StepIcon.js.map +1 -0
- package/lib/commonjs/ui/overlays/AnalyzingOverlay.js +284 -0
- package/lib/commonjs/ui/overlays/AnalyzingOverlay.js.map +1 -0
- package/lib/commonjs/ui/overlays/LoadingOverlay.js +108 -0
- package/lib/commonjs/ui/overlays/LoadingOverlay.js.map +1 -0
- package/lib/commonjs/ui/overlays/ProgressBar.js +95 -0
- package/lib/commonjs/ui/overlays/ProgressBar.js.map +1 -0
- package/lib/commonjs/ui/overlays/RetryDialog.js +125 -0
- package/lib/commonjs/ui/overlays/RetryDialog.js.map +1 -0
- package/lib/commonjs/ui/overlays/index.js +33 -0
- package/lib/commonjs/ui/overlays/index.js.map +1 -0
- package/lib/commonjs/ui/primitives/Banner.js +81 -0
- package/lib/commonjs/ui/primitives/Banner.js.map +1 -0
- package/lib/commonjs/ui/primitives/Button.js +142 -0
- package/lib/commonjs/ui/primitives/Button.js.map +1 -0
- package/lib/commonjs/ui/primitives/Card.js +50 -0
- package/lib/commonjs/ui/primitives/Card.js.map +1 -0
- package/lib/commonjs/ui/primitives/Checkbox.js +139 -0
- package/lib/commonjs/ui/primitives/Checkbox.js.map +1 -0
- package/lib/commonjs/ui/primitives/CountrySelect.js +288 -0
- package/lib/commonjs/ui/primitives/CountrySelect.js.map +1 -0
- package/lib/commonjs/ui/primitives/DatePicker.js +245 -0
- package/lib/commonjs/ui/primitives/DatePicker.js.map +1 -0
- package/lib/commonjs/ui/primitives/Input.js +101 -0
- package/lib/commonjs/ui/primitives/Input.js.map +1 -0
- package/lib/commonjs/ui/primitives/Select.js +209 -0
- package/lib/commonjs/ui/primitives/Select.js.map +1 -0
- package/lib/commonjs/ui/primitives/Spinner.js +25 -0
- package/lib/commonjs/ui/primitives/Spinner.js.map +1 -0
- package/lib/commonjs/ui/primitives/index.js +69 -0
- package/lib/commonjs/ui/primitives/index.js.map +1 -0
- package/lib/commonjs/ui/theme/ThemeProvider.js +74 -0
- package/lib/commonjs/ui/theme/ThemeProvider.js.map +1 -0
- package/lib/commonjs/ui/theme/index.js +68 -0
- package/lib/commonjs/ui/theme/index.js.map +1 -0
- package/lib/commonjs/ui/theme/tokens.js +154 -0
- package/lib/commonjs/ui/theme/tokens.js.map +1 -0
- package/lib/commonjs/utils/EventEmitter.js +144 -0
- package/lib/commonjs/utils/EventEmitter.js.map +1 -0
- package/lib/commonjs/utils/base64.js +53 -0
- package/lib/commonjs/utils/base64.js.map +1 -0
- package/lib/commonjs/utils/deviceFingerprint.js +132 -0
- package/lib/commonjs/utils/deviceFingerprint.js.map +1 -0
- package/lib/commonjs/utils/documentTypeOptions.js +35 -0
- package/lib/commonjs/utils/documentTypeOptions.js.map +1 -0
- package/lib/commonjs/utils/googleMapsPreflight.js +77 -0
- package/lib/commonjs/utils/googleMapsPreflight.js.map +1 -0
- package/lib/commonjs/utils/hmac.js +58 -0
- package/lib/commonjs/utils/hmac.js.map +1 -0
- package/lib/commonjs/utils/iso3166Countries.js +98 -0
- package/lib/commonjs/utils/iso3166Countries.js.map +1 -0
- package/lib/commonjs/utils/jpegFromUri.js +44 -0
- package/lib/commonjs/utils/jpegFromUri.js.map +1 -0
- package/lib/commonjs/utils/keepAwake.js +58 -0
- package/lib/commonjs/utils/keepAwake.js.map +1 -0
- package/lib/commonjs/utils/log.js +42 -0
- package/lib/commonjs/utils/log.js.map +1 -0
- package/lib/commonjs/utils/osGeocoder.js +70 -0
- package/lib/commonjs/utils/osGeocoder.js.map +1 -0
- package/lib/commonjs/utils/parseGoogleAddressComponents.js +74 -0
- package/lib/commonjs/utils/parseGoogleAddressComponents.js.map +1 -0
- package/lib/commonjs/utils/personNameNormalize.js +24 -0
- package/lib/commonjs/utils/personNameNormalize.js.map +1 -0
- package/lib/commonjs/utils/sdkError.js +34 -0
- package/lib/commonjs/utils/sdkError.js.map +1 -0
- package/lib/commonjs/utils/sdkVersion.js +13 -0
- package/lib/commonjs/utils/sdkVersion.js.map +1 -0
- package/lib/commonjs/utils/stepConfig.js +65 -0
- package/lib/commonjs/utils/stepConfig.js.map +1 -0
- package/lib/commonjs/utils/taxInfoConfig.js +19 -0
- package/lib/commonjs/utils/taxInfoConfig.js.map +1 -0
- package/lib/module/camera/AddressSearchBar.js +299 -0
- package/lib/module/camera/AddressSearchBar.js.map +1 -0
- package/lib/module/camera/DocumentCapture.js +500 -0
- package/lib/module/camera/DocumentCapture.js.map +1 -0
- package/lib/module/camera/LivenessCamera.js +529 -0
- package/lib/module/camera/LivenessCamera.js.map +1 -0
- package/lib/module/camera/MapAddressPicker.js +337 -0
- package/lib/module/camera/MapAddressPicker.js.map +1 -0
- package/lib/module/core/VelionOnboarding.js +811 -0
- package/lib/module/core/VelionOnboarding.js.map +1 -0
- package/lib/module/core/sessionDeclinedCopy.js +52 -0
- package/lib/module/core/sessionDeclinedCopy.js.map +1 -0
- package/lib/module/core/sessionStateMapper.js +128 -0
- package/lib/module/core/sessionStateMapper.js.map +1 -0
- package/lib/module/core/sseReasonMessages.js +446 -0
- package/lib/module/core/sseReasonMessages.js.map +1 -0
- package/lib/module/data/iso3166Alpha2Codes.json +1 -0
- package/lib/module/data/iso3166CountryNames.json +251 -0
- package/lib/module/i18n/index.js +25 -0
- package/lib/module/i18n/index.js.map +1 -0
- package/lib/module/i18n/strings/en.js +257 -0
- package/lib/module/i18n/strings/en.js.map +1 -0
- package/lib/module/i18n/strings/es.js +262 -0
- package/lib/module/i18n/strings/es.js.map +1 -0
- package/lib/module/index.js +36 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/steps/AddressInfoStep.js +646 -0
- package/lib/module/steps/AddressInfoStep.js.map +1 -0
- package/lib/module/steps/DocumentsOcrStep.js +391 -0
- package/lib/module/steps/DocumentsOcrStep.js.map +1 -0
- package/lib/module/steps/EmailContactStep.js +140 -0
- package/lib/module/steps/EmailContactStep.js.map +1 -0
- package/lib/module/steps/EmailOtpStep.js +215 -0
- package/lib/module/steps/EmailOtpStep.js.map +1 -0
- package/lib/module/steps/FaceMatchStep.js +161 -0
- package/lib/module/steps/FaceMatchStep.js.map +1 -0
- package/lib/module/steps/FingerprintStep.js +87 -0
- package/lib/module/steps/FingerprintStep.js.map +1 -0
- package/lib/module/steps/HumanBasicInfoStep.js +238 -0
- package/lib/module/steps/HumanBasicInfoStep.js.map +1 -0
- package/lib/module/steps/HumanExtendedInfoStep.js +263 -0
- package/lib/module/steps/HumanExtendedInfoStep.js.map +1 -0
- package/lib/module/steps/LegalBasicInfoStep.js +183 -0
- package/lib/module/steps/LegalBasicInfoStep.js.map +1 -0
- package/lib/module/steps/LegalExtendedInfoStep.js +161 -0
- package/lib/module/steps/LegalExtendedInfoStep.js.map +1 -0
- package/lib/module/steps/LivenessMatchStep.js +701 -0
- package/lib/module/steps/LivenessMatchStep.js.map +1 -0
- package/lib/module/steps/PhoneContactStep.js +141 -0
- package/lib/module/steps/PhoneContactStep.js.map +1 -0
- package/lib/module/steps/PhoneOtpStep.js +214 -0
- package/lib/module/steps/PhoneOtpStep.js.map +1 -0
- package/lib/module/steps/SwornDeclarationStep.js +191 -0
- package/lib/module/steps/SwornDeclarationStep.js.map +1 -0
- package/lib/module/steps/TaxInfoStep.js +239 -0
- package/lib/module/steps/TaxInfoStep.js.map +1 -0
- package/lib/module/steps/TermsAndConditionsStep.js +233 -0
- package/lib/module/steps/TermsAndConditionsStep.js.map +1 -0
- package/lib/module/steps/_shared.js +33 -0
- package/lib/module/steps/_shared.js.map +1 -0
- package/lib/module/steps/types.js +4 -0
- package/lib/module/steps/types.js.map +1 -0
- package/lib/module/transport/api.js +173 -0
- package/lib/module/transport/api.js.map +1 -0
- package/lib/module/transport/irisWebSocket.js +115 -0
- package/lib/module/transport/irisWebSocket.js.map +1 -0
- package/lib/module/transport/secureUrl.js +45 -0
- package/lib/module/transport/secureUrl.js.map +1 -0
- package/lib/module/transport/sse.js +242 -0
- package/lib/module/transport/sse.js.map +1 -0
- package/lib/module/types/index.js +457 -0
- package/lib/module/types/index.js.map +1 -0
- package/lib/module/ui/MapFallbackBoundary.js +37 -0
- package/lib/module/ui/MapFallbackBoundary.js.map +1 -0
- package/lib/module/ui/StepShell.js +114 -0
- package/lib/module/ui/StepShell.js.map +1 -0
- package/lib/module/ui/VelionOnboardingScreen.js +212 -0
- package/lib/module/ui/VelionOnboardingScreen.js.map +1 -0
- package/lib/module/ui/forms/index.js +5 -0
- package/lib/module/ui/forms/index.js.map +1 -0
- package/lib/module/ui/forms/useInlineValidation.js +84 -0
- package/lib/module/ui/forms/useInlineValidation.js.map +1 -0
- package/lib/module/ui/forms/validators.js +27 -0
- package/lib/module/ui/forms/validators.js.map +1 -0
- package/lib/module/ui/icons/HomeHeartIcon.js +33 -0
- package/lib/module/ui/icons/HomeHeartIcon.js.map +1 -0
- package/lib/module/ui/icons/StepIcon.js +55 -0
- package/lib/module/ui/icons/StepIcon.js.map +1 -0
- package/lib/module/ui/overlays/AnalyzingOverlay.js +279 -0
- package/lib/module/ui/overlays/AnalyzingOverlay.js.map +1 -0
- package/lib/module/ui/overlays/LoadingOverlay.js +104 -0
- package/lib/module/ui/overlays/LoadingOverlay.js.map +1 -0
- package/lib/module/ui/overlays/ProgressBar.js +90 -0
- package/lib/module/ui/overlays/ProgressBar.js.map +1 -0
- package/lib/module/ui/overlays/RetryDialog.js +121 -0
- package/lib/module/ui/overlays/RetryDialog.js.map +1 -0
- package/lib/module/ui/overlays/index.js +6 -0
- package/lib/module/ui/overlays/index.js.map +1 -0
- package/lib/module/ui/primitives/Banner.js +77 -0
- package/lib/module/ui/primitives/Banner.js.map +1 -0
- package/lib/module/ui/primitives/Button.js +138 -0
- package/lib/module/ui/primitives/Button.js.map +1 -0
- package/lib/module/ui/primitives/Card.js +46 -0
- package/lib/module/ui/primitives/Card.js.map +1 -0
- package/lib/module/ui/primitives/Checkbox.js +136 -0
- package/lib/module/ui/primitives/Checkbox.js.map +1 -0
- package/lib/module/ui/primitives/CountrySelect.js +284 -0
- package/lib/module/ui/primitives/CountrySelect.js.map +1 -0
- package/lib/module/ui/primitives/DatePicker.js +241 -0
- package/lib/module/ui/primitives/DatePicker.js.map +1 -0
- package/lib/module/ui/primitives/Input.js +97 -0
- package/lib/module/ui/primitives/Input.js.map +1 -0
- package/lib/module/ui/primitives/Select.js +205 -0
- package/lib/module/ui/primitives/Select.js.map +1 -0
- package/lib/module/ui/primitives/Spinner.js +21 -0
- package/lib/module/ui/primitives/Spinner.js.map +1 -0
- package/lib/module/ui/primitives/index.js +12 -0
- package/lib/module/ui/primitives/index.js.map +1 -0
- package/lib/module/ui/theme/ThemeProvider.js +67 -0
- package/lib/module/ui/theme/ThemeProvider.js.map +1 -0
- package/lib/module/ui/theme/index.js +5 -0
- package/lib/module/ui/theme/index.js.map +1 -0
- package/lib/module/ui/theme/tokens.js +145 -0
- package/lib/module/ui/theme/tokens.js.map +1 -0
- package/lib/module/utils/EventEmitter.js +139 -0
- package/lib/module/utils/EventEmitter.js.map +1 -0
- package/lib/module/utils/base64.js +47 -0
- package/lib/module/utils/base64.js.map +1 -0
- package/lib/module/utils/deviceFingerprint.js +129 -0
- package/lib/module/utils/deviceFingerprint.js.map +1 -0
- package/lib/module/utils/documentTypeOptions.js +31 -0
- package/lib/module/utils/documentTypeOptions.js.map +1 -0
- package/lib/module/utils/googleMapsPreflight.js +73 -0
- package/lib/module/utils/googleMapsPreflight.js.map +1 -0
- package/lib/module/utils/hmac.js +53 -0
- package/lib/module/utils/hmac.js.map +1 -0
- package/lib/module/utils/iso3166Countries.js +92 -0
- package/lib/module/utils/iso3166Countries.js.map +1 -0
- package/lib/module/utils/jpegFromUri.js +40 -0
- package/lib/module/utils/jpegFromUri.js.map +1 -0
- package/lib/module/utils/keepAwake.js +53 -0
- package/lib/module/utils/keepAwake.js.map +1 -0
- package/lib/module/utils/log.js +37 -0
- package/lib/module/utils/log.js.map +1 -0
- package/lib/module/utils/osGeocoder.js +65 -0
- package/lib/module/utils/osGeocoder.js.map +1 -0
- package/lib/module/utils/parseGoogleAddressComponents.js +69 -0
- package/lib/module/utils/parseGoogleAddressComponents.js.map +1 -0
- package/lib/module/utils/personNameNormalize.js +20 -0
- package/lib/module/utils/personNameNormalize.js.map +1 -0
- package/lib/module/utils/sdkError.js +29 -0
- package/lib/module/utils/sdkError.js.map +1 -0
- package/lib/module/utils/sdkVersion.js +9 -0
- package/lib/module/utils/sdkVersion.js.map +1 -0
- package/lib/module/utils/stepConfig.js +59 -0
- package/lib/module/utils/stepConfig.js.map +1 -0
- package/lib/module/utils/taxInfoConfig.js +15 -0
- package/lib/module/utils/taxInfoConfig.js.map +1 -0
- package/lib/typescript/camera/AddressSearchBar.d.ts +37 -0
- package/lib/typescript/camera/AddressSearchBar.d.ts.map +1 -0
- package/lib/typescript/camera/DocumentCapture.d.ts +34 -0
- package/lib/typescript/camera/DocumentCapture.d.ts.map +1 -0
- package/lib/typescript/camera/LivenessCamera.d.ts +50 -0
- package/lib/typescript/camera/LivenessCamera.d.ts.map +1 -0
- package/lib/typescript/camera/MapAddressPicker.d.ts +57 -0
- package/lib/typescript/camera/MapAddressPicker.d.ts.map +1 -0
- package/lib/typescript/core/VelionOnboarding.d.ts +115 -0
- package/lib/typescript/core/VelionOnboarding.d.ts.map +1 -0
- package/lib/typescript/core/sessionDeclinedCopy.d.ts +16 -0
- package/lib/typescript/core/sessionDeclinedCopy.d.ts.map +1 -0
- package/lib/typescript/core/sessionStateMapper.d.ts +33 -0
- package/lib/typescript/core/sessionStateMapper.d.ts.map +1 -0
- package/lib/typescript/core/sseReasonMessages.d.ts +20 -0
- package/lib/typescript/core/sseReasonMessages.d.ts.map +1 -0
- package/lib/typescript/i18n/index.d.ts +13 -0
- package/lib/typescript/i18n/index.d.ts.map +1 -0
- package/lib/typescript/i18n/strings/en.d.ts +3 -0
- package/lib/typescript/i18n/strings/en.d.ts.map +1 -0
- package/lib/typescript/i18n/strings/es.d.ts +260 -0
- package/lib/typescript/i18n/strings/es.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +26 -0
- package/lib/typescript/index.d.ts.map +1 -0
- package/lib/typescript/steps/AddressInfoStep.d.ts +26 -0
- package/lib/typescript/steps/AddressInfoStep.d.ts.map +1 -0
- package/lib/typescript/steps/DocumentsOcrStep.d.ts +26 -0
- package/lib/typescript/steps/DocumentsOcrStep.d.ts.map +1 -0
- package/lib/typescript/steps/EmailContactStep.d.ts +15 -0
- package/lib/typescript/steps/EmailContactStep.d.ts.map +1 -0
- package/lib/typescript/steps/EmailOtpStep.d.ts +21 -0
- package/lib/typescript/steps/EmailOtpStep.d.ts.map +1 -0
- package/lib/typescript/steps/FaceMatchStep.d.ts +27 -0
- package/lib/typescript/steps/FaceMatchStep.d.ts.map +1 -0
- package/lib/typescript/steps/FingerprintStep.d.ts +25 -0
- package/lib/typescript/steps/FingerprintStep.d.ts.map +1 -0
- package/lib/typescript/steps/HumanBasicInfoStep.d.ts +25 -0
- package/lib/typescript/steps/HumanBasicInfoStep.d.ts.map +1 -0
- package/lib/typescript/steps/HumanExtendedInfoStep.d.ts +23 -0
- package/lib/typescript/steps/HumanExtendedInfoStep.d.ts.map +1 -0
- package/lib/typescript/steps/LegalBasicInfoStep.d.ts +17 -0
- package/lib/typescript/steps/LegalBasicInfoStep.d.ts.map +1 -0
- package/lib/typescript/steps/LegalExtendedInfoStep.d.ts +17 -0
- package/lib/typescript/steps/LegalExtendedInfoStep.d.ts.map +1 -0
- package/lib/typescript/steps/LivenessMatchStep.d.ts +26 -0
- package/lib/typescript/steps/LivenessMatchStep.d.ts.map +1 -0
- package/lib/typescript/steps/PhoneContactStep.d.ts +15 -0
- package/lib/typescript/steps/PhoneContactStep.d.ts.map +1 -0
- package/lib/typescript/steps/PhoneOtpStep.d.ts +19 -0
- package/lib/typescript/steps/PhoneOtpStep.d.ts.map +1 -0
- package/lib/typescript/steps/SwornDeclarationStep.d.ts +20 -0
- package/lib/typescript/steps/SwornDeclarationStep.d.ts.map +1 -0
- package/lib/typescript/steps/TaxInfoStep.d.ts +19 -0
- package/lib/typescript/steps/TaxInfoStep.d.ts.map +1 -0
- package/lib/typescript/steps/TermsAndConditionsStep.d.ts +21 -0
- package/lib/typescript/steps/TermsAndConditionsStep.d.ts.map +1 -0
- package/lib/typescript/steps/_shared.d.ts +11 -0
- package/lib/typescript/steps/_shared.d.ts.map +1 -0
- package/lib/typescript/steps/types.d.ts +68 -0
- package/lib/typescript/steps/types.d.ts.map +1 -0
- package/lib/typescript/transport/api.d.ts +35 -0
- package/lib/typescript/transport/api.d.ts.map +1 -0
- package/lib/typescript/transport/irisWebSocket.d.ts +72 -0
- package/lib/typescript/transport/irisWebSocket.d.ts.map +1 -0
- package/lib/typescript/transport/secureUrl.d.ts +14 -0
- package/lib/typescript/transport/secureUrl.d.ts.map +1 -0
- package/lib/typescript/transport/sse.d.ts +54 -0
- package/lib/typescript/transport/sse.d.ts.map +1 -0
- package/lib/typescript/types/index.d.ts +1010 -0
- package/lib/typescript/types/index.d.ts.map +1 -0
- package/lib/typescript/ui/MapFallbackBoundary.d.ts +28 -0
- package/lib/typescript/ui/MapFallbackBoundary.d.ts.map +1 -0
- package/lib/typescript/ui/StepShell.d.ts +19 -0
- package/lib/typescript/ui/StepShell.d.ts.map +1 -0
- package/lib/typescript/ui/VelionOnboardingScreen.d.ts +19 -0
- package/lib/typescript/ui/VelionOnboardingScreen.d.ts.map +1 -0
- package/lib/typescript/ui/forms/index.d.ts +3 -0
- package/lib/typescript/ui/forms/index.d.ts.map +1 -0
- package/lib/typescript/ui/forms/useInlineValidation.d.ts +30 -0
- package/lib/typescript/ui/forms/useInlineValidation.d.ts.map +1 -0
- package/lib/typescript/ui/forms/validators.d.ts +11 -0
- package/lib/typescript/ui/forms/validators.d.ts.map +1 -0
- package/lib/typescript/ui/icons/HomeHeartIcon.d.ts +14 -0
- package/lib/typescript/ui/icons/HomeHeartIcon.d.ts.map +1 -0
- package/lib/typescript/ui/icons/StepIcon.d.ts +26 -0
- package/lib/typescript/ui/icons/StepIcon.d.ts.map +1 -0
- package/lib/typescript/ui/overlays/AnalyzingOverlay.d.ts +24 -0
- package/lib/typescript/ui/overlays/AnalyzingOverlay.d.ts.map +1 -0
- package/lib/typescript/ui/overlays/LoadingOverlay.d.ts +19 -0
- package/lib/typescript/ui/overlays/LoadingOverlay.d.ts.map +1 -0
- package/lib/typescript/ui/overlays/ProgressBar.d.ts +26 -0
- package/lib/typescript/ui/overlays/ProgressBar.d.ts.map +1 -0
- package/lib/typescript/ui/overlays/RetryDialog.d.ts +17 -0
- package/lib/typescript/ui/overlays/RetryDialog.d.ts.map +1 -0
- package/lib/typescript/ui/overlays/index.d.ts +4 -0
- package/lib/typescript/ui/overlays/index.d.ts.map +1 -0
- package/lib/typescript/ui/primitives/Banner.d.ts +11 -0
- package/lib/typescript/ui/primitives/Banner.d.ts.map +1 -0
- package/lib/typescript/ui/primitives/Button.d.ts +27 -0
- package/lib/typescript/ui/primitives/Button.d.ts.map +1 -0
- package/lib/typescript/ui/primitives/Card.d.ts +10 -0
- package/lib/typescript/ui/primitives/Card.d.ts.map +1 -0
- package/lib/typescript/ui/primitives/Checkbox.d.ts +25 -0
- package/lib/typescript/ui/primitives/Checkbox.d.ts.map +1 -0
- package/lib/typescript/ui/primitives/CountrySelect.d.ts +31 -0
- package/lib/typescript/ui/primitives/CountrySelect.d.ts.map +1 -0
- package/lib/typescript/ui/primitives/DatePicker.d.ts +42 -0
- package/lib/typescript/ui/primitives/DatePicker.d.ts.map +1 -0
- package/lib/typescript/ui/primitives/Input.d.ts +17 -0
- package/lib/typescript/ui/primitives/Input.d.ts.map +1 -0
- package/lib/typescript/ui/primitives/Select.d.ts +26 -0
- package/lib/typescript/ui/primitives/Select.d.ts.map +1 -0
- package/lib/typescript/ui/primitives/Spinner.d.ts +10 -0
- package/lib/typescript/ui/primitives/Spinner.d.ts.map +1 -0
- package/lib/typescript/ui/primitives/index.d.ts +10 -0
- package/lib/typescript/ui/primitives/index.d.ts.map +1 -0
- package/lib/typescript/ui/theme/ThemeProvider.d.ts +23 -0
- package/lib/typescript/ui/theme/ThemeProvider.d.ts.map +1 -0
- package/lib/typescript/ui/theme/index.d.ts +3 -0
- package/lib/typescript/ui/theme/index.d.ts.map +1 -0
- package/lib/typescript/ui/theme/tokens.d.ts +42 -0
- package/lib/typescript/ui/theme/tokens.d.ts.map +1 -0
- package/lib/typescript/utils/EventEmitter.d.ts +98 -0
- package/lib/typescript/utils/EventEmitter.d.ts.map +1 -0
- package/lib/typescript/utils/base64.d.ts +19 -0
- package/lib/typescript/utils/base64.d.ts.map +1 -0
- package/lib/typescript/utils/deviceFingerprint.d.ts +42 -0
- package/lib/typescript/utils/deviceFingerprint.d.ts.map +1 -0
- package/lib/typescript/utils/documentTypeOptions.d.ts +13 -0
- package/lib/typescript/utils/documentTypeOptions.d.ts.map +1 -0
- package/lib/typescript/utils/googleMapsPreflight.d.ts +44 -0
- package/lib/typescript/utils/googleMapsPreflight.d.ts.map +1 -0
- package/lib/typescript/utils/hmac.d.ts +39 -0
- package/lib/typescript/utils/hmac.d.ts.map +1 -0
- package/lib/typescript/utils/iso3166Countries.d.ts +27 -0
- package/lib/typescript/utils/iso3166Countries.d.ts.map +1 -0
- package/lib/typescript/utils/jpegFromUri.d.ts +29 -0
- package/lib/typescript/utils/jpegFromUri.d.ts.map +1 -0
- package/lib/typescript/utils/keepAwake.d.ts +16 -0
- package/lib/typescript/utils/keepAwake.d.ts.map +1 -0
- package/lib/typescript/utils/log.d.ts +18 -0
- package/lib/typescript/utils/log.d.ts.map +1 -0
- package/lib/typescript/utils/osGeocoder.d.ts +38 -0
- package/lib/typescript/utils/osGeocoder.d.ts.map +1 -0
- package/lib/typescript/utils/parseGoogleAddressComponents.d.ts +43 -0
- package/lib/typescript/utils/parseGoogleAddressComponents.d.ts.map +1 -0
- package/lib/typescript/utils/personNameNormalize.d.ts +10 -0
- package/lib/typescript/utils/personNameNormalize.d.ts.map +1 -0
- package/lib/typescript/utils/sdkError.d.ts +14 -0
- package/lib/typescript/utils/sdkError.d.ts.map +1 -0
- package/lib/typescript/utils/sdkVersion.d.ts +7 -0
- package/lib/typescript/utils/sdkVersion.d.ts.map +1 -0
- package/lib/typescript/utils/stepConfig.d.ts +8 -0
- package/lib/typescript/utils/stepConfig.d.ts.map +1 -0
- package/lib/typescript/utils/taxInfoConfig.d.ts +7 -0
- package/lib/typescript/utils/taxInfoConfig.d.ts.map +1 -0
- package/package.json +99 -0
- package/src/camera/AddressSearchBar.tsx +363 -0
- package/src/camera/DocumentCapture.tsx +505 -0
- package/src/camera/LivenessCamera.tsx +602 -0
- package/src/camera/MapAddressPicker.tsx +397 -0
- package/src/core/VelionOnboarding.ts +974 -0
- package/src/core/sessionDeclinedCopy.ts +76 -0
- package/src/core/sessionStateMapper.ts +167 -0
- package/src/core/sseReasonMessages.ts +531 -0
- package/src/data/iso3166Alpha2Codes.json +1 -0
- package/src/data/iso3166CountryNames.json +251 -0
- package/src/i18n/index.ts +26 -0
- package/src/i18n/strings/en.ts +289 -0
- package/src/i18n/strings/es.ts +291 -0
- package/src/index.ts +137 -0
- package/src/steps/AddressInfoStep.tsx +726 -0
- package/src/steps/DocumentsOcrStep.tsx +472 -0
- package/src/steps/EmailContactStep.tsx +159 -0
- package/src/steps/EmailOtpStep.tsx +250 -0
- package/src/steps/FaceMatchStep.tsx +177 -0
- package/src/steps/FingerprintStep.tsx +99 -0
- package/src/steps/HumanBasicInfoStep.tsx +274 -0
- package/src/steps/HumanExtendedInfoStep.tsx +353 -0
- package/src/steps/LegalBasicInfoStep.tsx +205 -0
- package/src/steps/LegalExtendedInfoStep.tsx +171 -0
- package/src/steps/LivenessMatchStep.tsx +846 -0
- package/src/steps/PhoneContactStep.tsx +160 -0
- package/src/steps/PhoneOtpStep.tsx +249 -0
- package/src/steps/SwornDeclarationStep.tsx +220 -0
- package/src/steps/TaxInfoStep.tsx +277 -0
- package/src/steps/TermsAndConditionsStep.tsx +261 -0
- package/src/steps/_shared.ts +44 -0
- package/src/steps/types.ts +72 -0
- package/src/transport/api.ts +257 -0
- package/src/transport/irisWebSocket.ts +186 -0
- package/src/transport/secureUrl.ts +47 -0
- package/src/transport/sse.ts +310 -0
- package/src/types/index.ts +1198 -0
- package/src/ui/MapFallbackBoundary.tsx +46 -0
- package/src/ui/StepShell.tsx +137 -0
- package/src/ui/VelionOnboardingScreen.tsx +223 -0
- package/src/ui/forms/index.ts +12 -0
- package/src/ui/forms/useInlineValidation.ts +115 -0
- package/src/ui/forms/validators.ts +29 -0
- package/src/ui/icons/HomeHeartIcon.tsx +34 -0
- package/src/ui/icons/StepIcon.tsx +77 -0
- package/src/ui/overlays/AnalyzingOverlay.tsx +323 -0
- package/src/ui/overlays/LoadingOverlay.tsx +115 -0
- package/src/ui/overlays/ProgressBar.tsx +99 -0
- package/src/ui/overlays/RetryDialog.tsx +128 -0
- package/src/ui/overlays/index.ts +3 -0
- package/src/ui/primitives/Banner.tsx +81 -0
- package/src/ui/primitives/Button.tsx +164 -0
- package/src/ui/primitives/Card.tsx +55 -0
- package/src/ui/primitives/Checkbox.tsx +153 -0
- package/src/ui/primitives/CountrySelect.tsx +356 -0
- package/src/ui/primitives/DatePicker.tsx +266 -0
- package/src/ui/primitives/Input.tsx +110 -0
- package/src/ui/primitives/Select.tsx +259 -0
- package/src/ui/primitives/Spinner.tsx +17 -0
- package/src/ui/primitives/index.ts +9 -0
- package/src/ui/theme/ThemeProvider.tsx +102 -0
- package/src/ui/theme/index.ts +17 -0
- package/src/ui/theme/tokens.ts +159 -0
- package/src/utils/EventEmitter.ts +155 -0
- package/src/utils/base64.ts +44 -0
- package/src/utils/deviceFingerprint.ts +184 -0
- package/src/utils/documentTypeOptions.ts +31 -0
- package/src/utils/googleMapsPreflight.ts +72 -0
- package/src/utils/hmac.ts +61 -0
- package/src/utils/iso3166Countries.ts +111 -0
- package/src/utils/jpegFromUri.ts +42 -0
- package/src/utils/keepAwake.ts +62 -0
- package/src/utils/log.ts +37 -0
- package/src/utils/osGeocoder.ts +75 -0
- package/src/utils/parseGoogleAddressComponents.ts +123 -0
- package/src/utils/personNameNormalize.ts +17 -0
- package/src/utils/sdkError.ts +40 -0
- package/src/utils/sdkVersion.ts +6 -0
- package/src/utils/stepConfig.ts +75 -0
- package/src/utils/taxInfoConfig.ts +14 -0
|
@@ -0,0 +1,602 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Liveness camera surface — front-facing vision-camera with an
|
|
3
|
+
* oval mask, status pill, and capture loop driven by the parent step.
|
|
4
|
+
*
|
|
5
|
+
* Capture strategy: vision-camera v4 frame processors run on a worklet thread
|
|
6
|
+
* and don't expose the JPEG bytes back to JS without a custom native plugin.
|
|
7
|
+
* We avoid that complication by using `takePhoto({ qualityPrioritization:
|
|
8
|
+
* 'speed' })` on a JS-level interval (matches the `setInterval` pattern in
|
|
9
|
+
* `web/LivenessModule.ts`). Real-world FPS lands around 3–8 fps which is
|
|
10
|
+
* sufficient for Iris's challenge cadence.
|
|
11
|
+
*
|
|
12
|
+
* The parent owns the loop and the WebSocket — this component just exposes a
|
|
13
|
+
* `captureFrame` ref so the step can drive the timing while the camera stays
|
|
14
|
+
* mounted across challenges.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import {
|
|
18
|
+
forwardRef,
|
|
19
|
+
useCallback,
|
|
20
|
+
useEffect,
|
|
21
|
+
useImperativeHandle,
|
|
22
|
+
useRef,
|
|
23
|
+
useState,
|
|
24
|
+
} from 'react';
|
|
25
|
+
import {
|
|
26
|
+
ActivityIndicator,
|
|
27
|
+
Animated,
|
|
28
|
+
Easing,
|
|
29
|
+
StyleSheet,
|
|
30
|
+
Text,
|
|
31
|
+
useWindowDimensions,
|
|
32
|
+
View,
|
|
33
|
+
} from 'react-native';
|
|
34
|
+
import Svg, { Defs, Ellipse, Mask, Rect } from 'react-native-svg';
|
|
35
|
+
import {
|
|
36
|
+
Camera,
|
|
37
|
+
useCameraDevice,
|
|
38
|
+
useCameraPermission,
|
|
39
|
+
type PhotoFile,
|
|
40
|
+
} from 'react-native-vision-camera';
|
|
41
|
+
import { Button } from '../ui/primitives/Button';
|
|
42
|
+
import { useTheme, withAlpha } from '../ui/theme';
|
|
43
|
+
|
|
44
|
+
export interface LivenessCameraHandle {
|
|
45
|
+
takeFrame: () => Promise<PhotoFile | null>;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Visual cue applied to the oval guide. The parent maps the current Iris
|
|
50
|
+
* challenge to one of these so the oval animates in a way that reinforces
|
|
51
|
+
* the instruction (oval grows for MOVE_CLOSER, shrinks back for MOVE_FARTHER,
|
|
52
|
+
* stays neutral otherwise).
|
|
53
|
+
*/
|
|
54
|
+
export type LivenessOvalCue = 'NEUTRAL' | 'MOVE_CLOSER' | 'MOVE_FARTHER';
|
|
55
|
+
|
|
56
|
+
export interface LivenessCameraProps {
|
|
57
|
+
/** Status text rendered in the centred pill. Pass `null` to hide it. */
|
|
58
|
+
statusText: string | null;
|
|
59
|
+
/** Active challenge instruction (rendered above the oval). Optional. */
|
|
60
|
+
challengeText?: string | null | undefined;
|
|
61
|
+
/** Visual cue for the oval shape (size animation). Defaults to NEUTRAL. */
|
|
62
|
+
ovalCue?: LivenessOvalCue | undefined;
|
|
63
|
+
/** Toast text — passed in as a `{ kind, message }` so the parent owns timing. */
|
|
64
|
+
toast?: { kind: 'success' | 'warning'; message: string } | null | undefined;
|
|
65
|
+
/** Linear progress 0–1 shown under the oval (CHALLENGE_PROGRESS). */
|
|
66
|
+
progress?: number | null | undefined;
|
|
67
|
+
/** Localized permission denied copy. */
|
|
68
|
+
permissionDeniedLabel: string;
|
|
69
|
+
/** Localized retry label for the permission CTA. */
|
|
70
|
+
retryLabel: string;
|
|
71
|
+
/** Localized cancel / back label. */
|
|
72
|
+
cancelLabel: string;
|
|
73
|
+
onCancel?: (() => void) | undefined;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export const LivenessCamera = forwardRef<LivenessCameraHandle, LivenessCameraProps>(
|
|
77
|
+
function LivenessCamera(props, ref) {
|
|
78
|
+
const theme = useTheme();
|
|
79
|
+
const cameraRef = useRef<Camera>(null);
|
|
80
|
+
const device = useCameraDevice('front');
|
|
81
|
+
const { hasPermission, requestPermission } = useCameraPermission();
|
|
82
|
+
const requestedRef = useRef(false);
|
|
83
|
+
const inFlightRef = useRef(false);
|
|
84
|
+
// Same simulator-friendly timeout as DocumentCapture: bail out of the
|
|
85
|
+
// infinite spinner after 4s without a device.
|
|
86
|
+
const [deviceTimeout, setDeviceTimeout] = useState(false);
|
|
87
|
+
|
|
88
|
+
useEffect(() => {
|
|
89
|
+
if (!hasPermission && !requestedRef.current) {
|
|
90
|
+
requestedRef.current = true;
|
|
91
|
+
void requestPermission();
|
|
92
|
+
}
|
|
93
|
+
}, [hasPermission, requestPermission]);
|
|
94
|
+
|
|
95
|
+
useEffect(() => {
|
|
96
|
+
if (device || !hasPermission) {
|
|
97
|
+
setDeviceTimeout(false);
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
const t = setTimeout(() => setDeviceTimeout(true), 4000);
|
|
101
|
+
return () => clearTimeout(t);
|
|
102
|
+
}, [device, hasPermission]);
|
|
103
|
+
|
|
104
|
+
const takeFrame = useCallback(async (): Promise<PhotoFile | null> => {
|
|
105
|
+
if (inFlightRef.current) return null;
|
|
106
|
+
const camera = cameraRef.current;
|
|
107
|
+
if (!camera) return null;
|
|
108
|
+
inFlightRef.current = true;
|
|
109
|
+
try {
|
|
110
|
+
return await camera.takePhoto({
|
|
111
|
+
flash: 'off',
|
|
112
|
+
enableShutterSound: false,
|
|
113
|
+
});
|
|
114
|
+
} catch {
|
|
115
|
+
// Frame failures are non-fatal — the parent loop just retries on the
|
|
116
|
+
// next tick. Keep the camera mounted.
|
|
117
|
+
return null;
|
|
118
|
+
} finally {
|
|
119
|
+
inFlightRef.current = false;
|
|
120
|
+
}
|
|
121
|
+
}, []);
|
|
122
|
+
|
|
123
|
+
useImperativeHandle(ref, () => ({ takeFrame }), [takeFrame]);
|
|
124
|
+
|
|
125
|
+
if (!hasPermission) {
|
|
126
|
+
return (
|
|
127
|
+
<View style={[styles.permission, { backgroundColor: theme.backgroundColor }]}>
|
|
128
|
+
<Text style={[styles.permissionText, { color: theme.textColor }]}>
|
|
129
|
+
{props.permissionDeniedLabel}
|
|
130
|
+
</Text>
|
|
131
|
+
<View style={styles.row}>
|
|
132
|
+
{props.onCancel ? (
|
|
133
|
+
<Button
|
|
134
|
+
variant="ghost"
|
|
135
|
+
label={props.cancelLabel}
|
|
136
|
+
onPress={props.onCancel}
|
|
137
|
+
fullWidth={false}
|
|
138
|
+
style={styles.actionBtn}
|
|
139
|
+
/>
|
|
140
|
+
) : null}
|
|
141
|
+
<Button
|
|
142
|
+
label={props.retryLabel}
|
|
143
|
+
onPress={() => {
|
|
144
|
+
void requestPermission();
|
|
145
|
+
}}
|
|
146
|
+
fullWidth={false}
|
|
147
|
+
style={styles.actionBtn}
|
|
148
|
+
/>
|
|
149
|
+
</View>
|
|
150
|
+
</View>
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (!device) {
|
|
155
|
+
if (deviceTimeout) {
|
|
156
|
+
return (
|
|
157
|
+
<View style={[styles.permission, { backgroundColor: theme.backgroundColor }]}>
|
|
158
|
+
<Text style={[styles.permissionText, { color: theme.textColor }]}>
|
|
159
|
+
No camera detected. The iOS Simulator does not provide a real
|
|
160
|
+
camera — please run on a physical device to perform the
|
|
161
|
+
liveness check.
|
|
162
|
+
</Text>
|
|
163
|
+
{props.onCancel ? (
|
|
164
|
+
<View style={styles.row}>
|
|
165
|
+
<Button
|
|
166
|
+
variant="ghost"
|
|
167
|
+
label={props.cancelLabel}
|
|
168
|
+
onPress={props.onCancel}
|
|
169
|
+
fullWidth={false}
|
|
170
|
+
style={styles.actionBtn}
|
|
171
|
+
/>
|
|
172
|
+
</View>
|
|
173
|
+
) : null}
|
|
174
|
+
</View>
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
return (
|
|
178
|
+
<View style={[styles.permission, { backgroundColor: theme.backgroundColor }]}>
|
|
179
|
+
<ActivityIndicator color={theme.primaryColor} />
|
|
180
|
+
</View>
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
return (
|
|
185
|
+
<View style={styles.root}>
|
|
186
|
+
<Camera
|
|
187
|
+
ref={cameraRef}
|
|
188
|
+
style={StyleSheet.absoluteFill}
|
|
189
|
+
device={device}
|
|
190
|
+
photo
|
|
191
|
+
photoQualityBalance="speed"
|
|
192
|
+
// Sin espejo en el output: el preview sigue mirrored, pero el JPEG enviado a Iris mantiene el yaw real (TURN_LEFT/RIGHT).
|
|
193
|
+
isMirrored={false}
|
|
194
|
+
isActive
|
|
195
|
+
/>
|
|
196
|
+
<OvalOverlay
|
|
197
|
+
primaryColor={theme.primaryColor}
|
|
198
|
+
cue={props.ovalCue ?? 'NEUTRAL'}
|
|
199
|
+
/>
|
|
200
|
+
{props.challengeText ? (
|
|
201
|
+
<ChallengeBanner
|
|
202
|
+
text={props.challengeText}
|
|
203
|
+
tint={theme.primaryColor}
|
|
204
|
+
/>
|
|
205
|
+
) : null}
|
|
206
|
+
{props.statusText ? (
|
|
207
|
+
<View style={styles.statusPill}>
|
|
208
|
+
<ActivityIndicator color="#FFFFFF" size="small" />
|
|
209
|
+
<Text style={styles.statusText}>{props.statusText}</Text>
|
|
210
|
+
</View>
|
|
211
|
+
) : null}
|
|
212
|
+
{props.toast ? (
|
|
213
|
+
<View
|
|
214
|
+
style={[
|
|
215
|
+
styles.toast,
|
|
216
|
+
{
|
|
217
|
+
backgroundColor:
|
|
218
|
+
props.toast.kind === 'success'
|
|
219
|
+
? withAlpha(theme.successColor, 0.92)
|
|
220
|
+
: withAlpha(theme.warningColor, 0.92),
|
|
221
|
+
},
|
|
222
|
+
]}
|
|
223
|
+
>
|
|
224
|
+
<Text style={styles.toastText}>{props.toast.message}</Text>
|
|
225
|
+
</View>
|
|
226
|
+
) : null}
|
|
227
|
+
{props.progress != null ? (
|
|
228
|
+
<ProgressBar
|
|
229
|
+
progress={props.progress}
|
|
230
|
+
color={theme.primaryColor}
|
|
231
|
+
/>
|
|
232
|
+
) : null}
|
|
233
|
+
</View>
|
|
234
|
+
);
|
|
235
|
+
},
|
|
236
|
+
);
|
|
237
|
+
|
|
238
|
+
interface ProgressBarProps {
|
|
239
|
+
progress: number;
|
|
240
|
+
color: string;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Challenge progress bar with an indeterminate fallback.
|
|
245
|
+
*
|
|
246
|
+
* When the orchestrator hasn't sent any CHALLENGE_PROGRESS yet (still
|
|
247
|
+
* collecting baseline, user hasn't started moving, etc.) `progress` is 0
|
|
248
|
+
* and a static empty bar looks broken. We treat the [0, 0.05) range as
|
|
249
|
+
* "no measurable progress yet" and run a left-to-right shimmer instead,
|
|
250
|
+
* so the user can tell the system is still listening.
|
|
251
|
+
*/
|
|
252
|
+
function ProgressBar({ progress, color }: ProgressBarProps) {
|
|
253
|
+
const clamped = Math.max(0, Math.min(1, progress));
|
|
254
|
+
const isIndeterminate = clamped < 0.05;
|
|
255
|
+
|
|
256
|
+
const shimmer = useRef(new Animated.Value(0)).current;
|
|
257
|
+
useEffect(() => {
|
|
258
|
+
if (!isIndeterminate) {
|
|
259
|
+
shimmer.stopAnimation();
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
shimmer.setValue(0);
|
|
263
|
+
const loop = Animated.loop(
|
|
264
|
+
Animated.timing(shimmer, {
|
|
265
|
+
toValue: 1,
|
|
266
|
+
duration: 1200,
|
|
267
|
+
easing: Easing.inOut(Easing.ease),
|
|
268
|
+
useNativeDriver: false,
|
|
269
|
+
}),
|
|
270
|
+
);
|
|
271
|
+
loop.start();
|
|
272
|
+
return () => loop.stop();
|
|
273
|
+
}, [isIndeterminate, shimmer]);
|
|
274
|
+
|
|
275
|
+
if (isIndeterminate) {
|
|
276
|
+
// 30 % wide segment sliding from -30 % to +100 % of the track.
|
|
277
|
+
const left = shimmer.interpolate({
|
|
278
|
+
inputRange: [0, 1],
|
|
279
|
+
outputRange: ['-30%', '100%'],
|
|
280
|
+
});
|
|
281
|
+
return (
|
|
282
|
+
<View style={styles.progressTrack}>
|
|
283
|
+
<Animated.View
|
|
284
|
+
style={[
|
|
285
|
+
styles.progressShimmer,
|
|
286
|
+
{ backgroundColor: color, left },
|
|
287
|
+
]}
|
|
288
|
+
/>
|
|
289
|
+
</View>
|
|
290
|
+
);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
return (
|
|
294
|
+
<View style={styles.progressTrack}>
|
|
295
|
+
<View
|
|
296
|
+
style={[
|
|
297
|
+
styles.progressBar,
|
|
298
|
+
{
|
|
299
|
+
width: `${clamped * 100}%`,
|
|
300
|
+
backgroundColor: color,
|
|
301
|
+
},
|
|
302
|
+
]}
|
|
303
|
+
/>
|
|
304
|
+
</View>
|
|
305
|
+
);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
interface ChallengeBannerProps {
|
|
309
|
+
text: string;
|
|
310
|
+
tint: string;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* Attention-grabbing challenge instruction.
|
|
315
|
+
*
|
|
316
|
+
* The previous small grey pill was easy to miss — users sat confused
|
|
317
|
+
* while Iris's 800-8000 ms BLINK window closed. This banner is bold,
|
|
318
|
+
* sits on a dark translucent surface (less visually heavy than a full
|
|
319
|
+
* primary-tinted fill), and runs a fade-in + scale-up animation every
|
|
320
|
+
* time the `text` prop changes so the eye snaps to the new instruction.
|
|
321
|
+
*
|
|
322
|
+
* The `tint` prop is no longer used for the background (too saturated);
|
|
323
|
+
* it's kept in the signature for future re-introduction of an accent
|
|
324
|
+
* line / icon if needed without changing the call site.
|
|
325
|
+
*/
|
|
326
|
+
function ChallengeBanner({ text, tint: _tint }: ChallengeBannerProps) {
|
|
327
|
+
const opacity = useRef(new Animated.Value(0)).current;
|
|
328
|
+
const scale = useRef(new Animated.Value(0.85)).current;
|
|
329
|
+
|
|
330
|
+
useEffect(() => {
|
|
331
|
+
// Reset to invisible/shrunk, then animate in. `text` in deps means each
|
|
332
|
+
// new challenge re-triggers the entrance animation.
|
|
333
|
+
opacity.setValue(0);
|
|
334
|
+
scale.setValue(0.85);
|
|
335
|
+
Animated.parallel([
|
|
336
|
+
Animated.timing(opacity, {
|
|
337
|
+
toValue: 1,
|
|
338
|
+
duration: 240,
|
|
339
|
+
easing: Easing.out(Easing.cubic),
|
|
340
|
+
useNativeDriver: true,
|
|
341
|
+
}),
|
|
342
|
+
Animated.spring(scale, {
|
|
343
|
+
toValue: 1,
|
|
344
|
+
damping: 12,
|
|
345
|
+
stiffness: 180,
|
|
346
|
+
mass: 0.7,
|
|
347
|
+
useNativeDriver: true,
|
|
348
|
+
}),
|
|
349
|
+
]).start();
|
|
350
|
+
}, [text, opacity, scale]);
|
|
351
|
+
|
|
352
|
+
return (
|
|
353
|
+
<Animated.View
|
|
354
|
+
pointerEvents="none"
|
|
355
|
+
style={[
|
|
356
|
+
styles.challengeBanner,
|
|
357
|
+
{
|
|
358
|
+
opacity,
|
|
359
|
+
transform: [{ scale }],
|
|
360
|
+
},
|
|
361
|
+
]}
|
|
362
|
+
>
|
|
363
|
+
<Text style={styles.challengeBannerText} numberOfLines={2}>
|
|
364
|
+
{text}
|
|
365
|
+
</Text>
|
|
366
|
+
</Animated.View>
|
|
367
|
+
);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
interface OvalOverlayProps {
|
|
371
|
+
primaryColor: string;
|
|
372
|
+
cue: LivenessOvalCue;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
// Face-shaped oval: real human heads have a width-to-height ratio close to
|
|
376
|
+
// ~0.72 (slightly taller than a circle). Sized explicitly from
|
|
377
|
+
// `useWindowDimensions` and rendered as a true ellipse via SVG (NOT a
|
|
378
|
+
// rounded View) so the dim mask can follow the actual curve.
|
|
379
|
+
const OVAL_WIDTH_RATIO = 0.78; // 78 % of screen width
|
|
380
|
+
const OVAL_MAX_HEIGHT_RATIO = 0.62; // never taller than 62 % of screen height
|
|
381
|
+
const OVAL_ASPECT = 0.78; // width / height — face proportion
|
|
382
|
+
// Visual nudge: dim the screen symmetrically around the geometric centre
|
|
383
|
+
// looks slightly low because of the status bar / Dynamic Island at the
|
|
384
|
+
// top. Lift the oval by this many points so the user's natural framing
|
|
385
|
+
// (eyes near the top third of the oval) aligns with the screen's optical
|
|
386
|
+
// centre.
|
|
387
|
+
const OVAL_OPTICAL_OFFSET_UP = 24;
|
|
388
|
+
const OVAL_BORDER_WIDTH = 4;
|
|
389
|
+
// Secondary halo drawn outside the main stroke. Gives the user a clearer
|
|
390
|
+
// "your face should fill this" target without being so heavy that it
|
|
391
|
+
// distracts during the challenges.
|
|
392
|
+
const OVAL_HALO_WIDTH = 2;
|
|
393
|
+
const OVAL_HALO_OFFSET = 6; // px outside the primary stroke
|
|
394
|
+
const DIM_FILL = 'rgba(0, 0, 0, 0.55)';
|
|
395
|
+
// Scale targets per oval cue. The oval visually invites the user to bring
|
|
396
|
+
// their face closer (it grows) on MOVE_CLOSER, and to back away (it shrinks
|
|
397
|
+
// back to neutral size) on MOVE_FARTHER. NEUTRAL is the default oval size.
|
|
398
|
+
const OVAL_SCALE_BY_CUE: Record<LivenessOvalCue, number> = {
|
|
399
|
+
NEUTRAL: 1.0,
|
|
400
|
+
MOVE_CLOSER: 1.25,
|
|
401
|
+
MOVE_FARTHER: 1.0,
|
|
402
|
+
};
|
|
403
|
+
const OVAL_SCALE_ANIM_MS = 600;
|
|
404
|
+
|
|
405
|
+
function OvalOverlay({ primaryColor, cue }: OvalOverlayProps) {
|
|
406
|
+
const { width: screenW, height: screenH } = useWindowDimensions();
|
|
407
|
+
|
|
408
|
+
// Compute width first, then derive height to keep the face aspect ratio.
|
|
409
|
+
// If that height would dominate the screen, clip from the height side
|
|
410
|
+
// instead so the oval stays well within the visible area on tall phones.
|
|
411
|
+
let ovalW = screenW * OVAL_WIDTH_RATIO;
|
|
412
|
+
let ovalH = ovalW / OVAL_ASPECT;
|
|
413
|
+
const maxH = screenH * OVAL_MAX_HEIGHT_RATIO;
|
|
414
|
+
if (ovalH > maxH) {
|
|
415
|
+
ovalH = maxH;
|
|
416
|
+
ovalW = ovalH * OVAL_ASPECT;
|
|
417
|
+
}
|
|
418
|
+
const rx = ovalW / 2;
|
|
419
|
+
const ry = ovalH / 2;
|
|
420
|
+
const cx = screenW / 2;
|
|
421
|
+
const cy = Math.max(ry + 20, screenH / 2 - OVAL_OPTICAL_OFFSET_UP);
|
|
422
|
+
|
|
423
|
+
// Animate the oval scale on cue changes. We scale the entire Svg via an
|
|
424
|
+
// Animated.View transform — that keeps the mask + stroke perfectly
|
|
425
|
+
// aligned (no need to animate every SVG attribute individually). Scaling
|
|
426
|
+
// the dim rectangle past the screen edge is harmless: the user only sees
|
|
427
|
+
// the on-screen portion, which is exactly what we want.
|
|
428
|
+
const ovalScale = useRef(new Animated.Value(OVAL_SCALE_BY_CUE[cue])).current;
|
|
429
|
+
useEffect(() => {
|
|
430
|
+
Animated.timing(ovalScale, {
|
|
431
|
+
toValue: OVAL_SCALE_BY_CUE[cue],
|
|
432
|
+
duration: OVAL_SCALE_ANIM_MS,
|
|
433
|
+
easing: Easing.out(Easing.cubic),
|
|
434
|
+
useNativeDriver: true,
|
|
435
|
+
}).start();
|
|
436
|
+
}, [cue, ovalScale]);
|
|
437
|
+
|
|
438
|
+
// SVG mask trick:
|
|
439
|
+
// - The Mask defines a black/white image where white = "show the masked
|
|
440
|
+
// element" and black = "hide it (transparent)".
|
|
441
|
+
// - We mask a full-screen dim rectangle so the dim shows EVERYWHERE
|
|
442
|
+
// except inside the ellipse (where the mask is black).
|
|
443
|
+
// - On top of the dim, we draw the ellipse stroke as the visual
|
|
444
|
+
// viewfinder. Stroke is inset half its width so it stays exactly on
|
|
445
|
+
// the dim/transparent boundary.
|
|
446
|
+
return (
|
|
447
|
+
<Animated.View
|
|
448
|
+
pointerEvents="none"
|
|
449
|
+
style={[StyleSheet.absoluteFill, { transform: [{ scale: ovalScale }] }]}
|
|
450
|
+
>
|
|
451
|
+
<Svg
|
|
452
|
+
width={screenW}
|
|
453
|
+
height={screenH}
|
|
454
|
+
style={StyleSheet.absoluteFill}
|
|
455
|
+
>
|
|
456
|
+
<Defs>
|
|
457
|
+
<Mask id="ovalCutout">
|
|
458
|
+
<Rect x={0} y={0} width={screenW} height={screenH} fill="white" />
|
|
459
|
+
<Ellipse cx={cx} cy={cy} rx={rx} ry={ry} fill="black" />
|
|
460
|
+
</Mask>
|
|
461
|
+
</Defs>
|
|
462
|
+
<Rect
|
|
463
|
+
x={0}
|
|
464
|
+
y={0}
|
|
465
|
+
width={screenW}
|
|
466
|
+
height={screenH}
|
|
467
|
+
fill={DIM_FILL}
|
|
468
|
+
mask="url(#ovalCutout)"
|
|
469
|
+
/>
|
|
470
|
+
{/* Outer halo: lower-opacity white ring that frames the primary
|
|
471
|
+
stroke. The pair reads as "here's the target shape" much more
|
|
472
|
+
clearly than a single 3 px stroke against the live camera feed,
|
|
473
|
+
especially on Android phones with low-contrast OLED panels. */}
|
|
474
|
+
<Ellipse
|
|
475
|
+
cx={cx}
|
|
476
|
+
cy={cy}
|
|
477
|
+
rx={rx + OVAL_HALO_OFFSET}
|
|
478
|
+
ry={ry + OVAL_HALO_OFFSET}
|
|
479
|
+
stroke="rgba(255, 255, 255, 0.45)"
|
|
480
|
+
strokeWidth={OVAL_HALO_WIDTH}
|
|
481
|
+
fill="none"
|
|
482
|
+
/>
|
|
483
|
+
<Ellipse
|
|
484
|
+
cx={cx}
|
|
485
|
+
cy={cy}
|
|
486
|
+
rx={rx - OVAL_BORDER_WIDTH / 2}
|
|
487
|
+
ry={ry - OVAL_BORDER_WIDTH / 2}
|
|
488
|
+
stroke={primaryColor}
|
|
489
|
+
strokeWidth={OVAL_BORDER_WIDTH}
|
|
490
|
+
fill="none"
|
|
491
|
+
/>
|
|
492
|
+
</Svg>
|
|
493
|
+
</Animated.View>
|
|
494
|
+
);
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
const styles = StyleSheet.create({
|
|
498
|
+
root: {
|
|
499
|
+
flex: 1,
|
|
500
|
+
backgroundColor: '#000',
|
|
501
|
+
},
|
|
502
|
+
permission: {
|
|
503
|
+
flex: 1,
|
|
504
|
+
alignItems: 'center',
|
|
505
|
+
justifyContent: 'center',
|
|
506
|
+
padding: 32,
|
|
507
|
+
gap: 16,
|
|
508
|
+
},
|
|
509
|
+
permissionText: {
|
|
510
|
+
textAlign: 'center',
|
|
511
|
+
fontSize: 15,
|
|
512
|
+
lineHeight: 22,
|
|
513
|
+
},
|
|
514
|
+
row: {
|
|
515
|
+
flexDirection: 'row',
|
|
516
|
+
gap: 12,
|
|
517
|
+
width: '100%',
|
|
518
|
+
maxWidth: 380,
|
|
519
|
+
},
|
|
520
|
+
actionBtn: {
|
|
521
|
+
flex: 1,
|
|
522
|
+
},
|
|
523
|
+
challengeBanner: {
|
|
524
|
+
position: 'absolute',
|
|
525
|
+
top: 76,
|
|
526
|
+
left: 24,
|
|
527
|
+
right: 24,
|
|
528
|
+
paddingHorizontal: 16,
|
|
529
|
+
paddingVertical: 10,
|
|
530
|
+
borderRadius: 18,
|
|
531
|
+
alignItems: 'center',
|
|
532
|
+
justifyContent: 'center',
|
|
533
|
+
backgroundColor: 'rgba(0, 0, 0, 0.62)',
|
|
534
|
+
},
|
|
535
|
+
challengeBannerText: {
|
|
536
|
+
color: '#FFFFFF',
|
|
537
|
+
fontSize: 19,
|
|
538
|
+
fontWeight: '700',
|
|
539
|
+
textAlign: 'center',
|
|
540
|
+
letterSpacing: 0.1,
|
|
541
|
+
lineHeight: 24,
|
|
542
|
+
},
|
|
543
|
+
statusPill: {
|
|
544
|
+
position: 'absolute',
|
|
545
|
+
top: 130,
|
|
546
|
+
left: 0,
|
|
547
|
+
right: 0,
|
|
548
|
+
alignSelf: 'center',
|
|
549
|
+
flexDirection: 'row',
|
|
550
|
+
alignItems: 'center',
|
|
551
|
+
justifyContent: 'center',
|
|
552
|
+
gap: 8,
|
|
553
|
+
backgroundColor: 'rgba(0,0,0,0.55)',
|
|
554
|
+
paddingHorizontal: 14,
|
|
555
|
+
paddingVertical: 8,
|
|
556
|
+
borderRadius: 16,
|
|
557
|
+
marginHorizontal: 60,
|
|
558
|
+
overflow: 'hidden',
|
|
559
|
+
},
|
|
560
|
+
statusText: {
|
|
561
|
+
color: '#FFFFFF',
|
|
562
|
+
fontSize: 13,
|
|
563
|
+
fontWeight: '500',
|
|
564
|
+
},
|
|
565
|
+
toast: {
|
|
566
|
+
position: 'absolute',
|
|
567
|
+
bottom: 100,
|
|
568
|
+
left: 24,
|
|
569
|
+
right: 24,
|
|
570
|
+
paddingVertical: 10,
|
|
571
|
+
paddingHorizontal: 14,
|
|
572
|
+
borderRadius: 14,
|
|
573
|
+
alignItems: 'center',
|
|
574
|
+
},
|
|
575
|
+
toastText: {
|
|
576
|
+
color: '#FFFFFF',
|
|
577
|
+
fontWeight: '600',
|
|
578
|
+
fontSize: 14,
|
|
579
|
+
textAlign: 'center',
|
|
580
|
+
},
|
|
581
|
+
progressTrack: {
|
|
582
|
+
position: 'absolute',
|
|
583
|
+
bottom: 60,
|
|
584
|
+
left: 24,
|
|
585
|
+
right: 24,
|
|
586
|
+
height: 6,
|
|
587
|
+
borderRadius: 3,
|
|
588
|
+
backgroundColor: 'rgba(255,255,255,0.25)',
|
|
589
|
+
overflow: 'hidden',
|
|
590
|
+
},
|
|
591
|
+
progressBar: {
|
|
592
|
+
height: '100%',
|
|
593
|
+
},
|
|
594
|
+
progressShimmer: {
|
|
595
|
+
position: 'absolute',
|
|
596
|
+
top: 0,
|
|
597
|
+
bottom: 0,
|
|
598
|
+
width: '30%',
|
|
599
|
+
opacity: 0.85,
|
|
600
|
+
borderRadius: 3,
|
|
601
|
+
},
|
|
602
|
+
});
|