@smileid/usesmileid 12.2.0 → 12.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +5 -1
- package/README.md +57 -18
- package/dist/camera/bounding_box_metering_region.d.ts +10 -0
- package/dist/camera/bounding_box_metering_region.js +1 -0
- package/dist/camera/camera_defaults.d.ts +0 -2
- package/dist/camera/camera_defaults.js +1 -1
- package/dist/camera/document_image_pipeline.d.ts +9 -0
- package/dist/camera/document_image_pipeline.js +1 -1
- package/dist/camera/imported_document_folder.d.ts +15 -0
- package/dist/camera/imported_document_folder.js +1 -0
- package/dist/camera/kamera_config_factory.d.ts +11 -1
- package/dist/camera/kamera_config_factory.js +1 -1
- package/dist/camera/use_smile_id_frame_stream.js +1 -1
- package/dist/camera/use_smile_id_kamera_camera_system.d.ts +46 -2
- package/dist/camera/use_smile_id_kamera_camera_system.js +1 -1
- package/dist/core/exception/use_smile_id_error_code.js +1 -1
- package/dist/core/exception/use_smile_id_network_exception.d.ts +10 -3
- package/dist/core/exception/use_smile_id_network_exception.js +1 -1
- package/dist/core/is_development_build.d.ts +6 -0
- package/dist/core/is_development_build.js +1 -0
- package/dist/core/models/config.d.ts +6 -0
- package/dist/core/models/ml_config.d.ts +1 -1
- package/dist/core/models/network_config.d.ts +4 -1
- package/dist/core/models/params.d.ts +8 -6
- package/dist/core/models/result.d.ts +11 -0
- package/dist/core/models/result.js +1 -1
- package/dist/core/perf/capture_perf_trace.d.ts +90 -0
- package/dist/core/perf/capture_perf_trace.js +1 -0
- package/dist/data/api/interceptors/logging_interceptor.js +1 -1
- package/dist/data/api/interceptors/smile_auth_interceptor.js +1 -1
- package/dist/data/api/request_capture.d.ts +16 -0
- package/dist/data/api/request_capture.js +1 -0
- package/dist/data/api/smile_id_api.d.ts +1 -1
- package/dist/data/api/smile_id_api.js +1 -1
- package/dist/data/factory/networking_factory.d.ts +3 -1
- package/dist/data/factory/networking_factory.js +1 -1
- package/dist/data/model/captured_job.d.ts +49 -0
- package/dist/data/model/captured_job.js +1 -0
- package/dist/data/model/job_request.d.ts +1 -1
- package/dist/data/model/sealed_job_request.d.ts +15 -0
- package/dist/data/model/sealed_job_request.js +1 -0
- package/dist/data/model/token_payload.d.ts +5 -7
- package/dist/data/model/token_payload.js +1 -1
- package/dist/data/model/user_details_payload.d.ts +6 -4
- package/dist/data/repository/use_smile_id_repository.d.ts +7 -0
- package/dist/data/repository/use_smile_id_repository_impl.d.ts +29 -2
- package/dist/data/repository/use_smile_id_repository_impl.js +1 -1
- package/dist/data/security/job_package_crypto.d.ts +41 -0
- package/dist/data/security/job_package_crypto.js +1 -0
- package/dist/data/security/job_package_sealer.d.ts +35 -0
- package/dist/data/security/job_package_sealer.js +1 -0
- package/dist/data/security/signing_crypto.d.ts +34 -0
- package/dist/data/security/signing_crypto.js +1 -1
- package/dist/data/util/retry_util.d.ts +9 -6
- package/dist/data/util/retry_util.js +1 -1
- package/dist/debug/selfie_preview_debug_geometry.d.ts +13 -13
- package/dist/debug/selfie_preview_debug_geometry.js +1 -1
- package/dist/debug/use_smile_id_debug.d.ts +25 -2
- package/dist/debug/use_smile_id_debug.js +1 -1
- package/dist/debug/use_smile_id_document_preview_debug_overlay.js +1 -1
- package/dist/debug/use_smile_id_selfie_preview_debug_overlay.d.ts +5 -1
- package/dist/debug/use_smile_id_selfie_preview_debug_overlay.js +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +1 -1
- package/dist/l10n/strings_en.d.ts +3 -3
- package/dist/l10n/strings_en.js +2 -2
- package/dist/l10n/use_smile_id_localizations.d.ts +5 -7
- package/dist/l10n/use_smile_id_localizations.js +1 -1
- package/dist/metadata/metadata_configuration_mappers.d.ts +3 -5
- package/dist/metadata/metadata_configuration_mappers.js +1 -1
- package/dist/metadata/use_smile_id_metadata_factory.js +1 -1
- package/dist/presentation/assets/si_dark_lighting_animation.json +1 -927
- package/dist/presentation/assets/si_device_orientation_animation.json +1 -850
- package/dist/presentation/assets/si_document_green_book_hero_animation.json +1 -4740
- package/dist/presentation/assets/si_document_hero_animation.json +1 -4870
- package/dist/presentation/assets/si_document_hero_back_animation.json +1 -2122
- package/dist/presentation/assets/si_document_passport_hero_animation.json +1 -14540
- package/dist/presentation/assets/si_ess_all_directions_hero_animation.json +1 -5906
- package/dist/presentation/assets/si_ess_animation_all_directions.json +1 -5906
- package/dist/presentation/assets/si_selfie_hero_animation.json +1 -1468
- package/dist/presentation/assets/si_smile_to_capture_animation.json +1 -1412
- package/dist/presentation/components/helpers/captured_image_uri.d.ts +11 -0
- package/dist/presentation/components/helpers/captured_image_uri.js +1 -0
- package/dist/presentation/components/helpers/captured_oval_region.d.ts +40 -0
- package/dist/presentation/components/helpers/captured_oval_region.js +1 -0
- package/dist/presentation/components/helpers/document_interior_crop.d.ts +13 -2
- package/dist/presentation/components/helpers/document_interior_crop.js +1 -1
- package/dist/presentation/components/helpers/enhanced_smart_selfie_animation_frames.d.ts +35 -29
- package/dist/presentation/components/helpers/enhanced_smart_selfie_animation_frames.js +1 -1
- package/dist/presentation/components/helpers/selfie_interior_crop.js +1 -1
- package/dist/presentation/components/use_smile_id_capture_content.d.ts +5 -2
- package/dist/presentation/components/use_smile_id_capture_content.js +1 -1
- package/dist/presentation/components/use_smile_id_captured_document_image.d.ts +8 -4
- package/dist/presentation/components/use_smile_id_captured_document_image.js +1 -1
- package/dist/presentation/components/use_smile_id_captured_image_oval.d.ts +6 -0
- package/dist/presentation/components/use_smile_id_captured_image_oval.js +1 -1
- package/dist/presentation/components/use_smile_id_enhanced_smart_selfie_clip.d.ts +17 -7
- package/dist/presentation/components/use_smile_id_enhanced_smart_selfie_clip.js +1 -1
- package/dist/presentation/components/use_smile_id_enhanced_smart_selfie_direction_animation.d.ts +13 -14
- package/dist/presentation/components/use_smile_id_enhanced_smart_selfie_direction_animation.js +1 -1
- package/dist/presentation/components/use_smile_id_enhanced_smart_selfie_full_animation.js +1 -1
- package/dist/presentation/components/use_smile_id_face_oval_image.js +1 -1
- package/dist/presentation/flow/analytics/unsatisfied_reasons.d.ts +14 -0
- package/dist/presentation/flow/analytics/unsatisfied_reasons.js +1 -0
- package/dist/presentation/flow/analytics/use_smile_id_analytics_event.d.ts +8 -7
- package/dist/presentation/flow/analytics/use_smile_id_analytics_event.js +1 -1
- package/dist/presentation/flow/analytics/use_smile_id_analytics_event_kind.d.ts +9 -0
- package/dist/presentation/flow/analytics/use_smile_id_analytics_event_kind.js +1 -1
- package/dist/presentation/flow/config/flow_configuration_camera.d.ts +9 -0
- package/dist/presentation/flow/config/flow_configuration_camera.js +1 -0
- package/dist/presentation/flow/dsl/builder/config_builder.d.ts +6 -0
- package/dist/presentation/flow/dsl/builder/config_builder.js +1 -1
- package/dist/presentation/flow/dsl/builder/ml_builder.d.ts +1 -7
- package/dist/presentation/flow/dsl/builder/ml_builder.js +1 -1
- package/dist/presentation/flow/dsl/use_smile_id_flow_builder.d.ts +0 -9
- package/dist/presentation/flow/dsl/use_smile_id_flow_builder.js +1 -1
- package/dist/presentation/flow/flow_navigation_manager.d.ts +39 -70
- package/dist/presentation/flow/flow_navigation_manager.js +1 -1
- package/dist/presentation/flow/flow_navigation_manager_analytics.d.ts +23 -0
- package/dist/presentation/flow/flow_navigation_manager_analytics.js +1 -0
- package/dist/presentation/flow/flow_navigation_manager_documents.d.ts +18 -0
- package/dist/presentation/flow/flow_navigation_manager_documents.js +1 -0
- package/dist/presentation/flow/flow_navigation_manager_job_request.d.ts +7 -0
- package/dist/presentation/flow/flow_navigation_manager_job_request.js +1 -0
- package/dist/presentation/flow/flow_navigation_manager_routing.d.ts +12 -0
- package/dist/presentation/flow/flow_navigation_manager_routing.js +1 -0
- package/dist/presentation/flow/flow_navigation_manager_submission.d.ts +17 -0
- package/dist/presentation/flow/flow_navigation_manager_submission.js +1 -0
- package/dist/presentation/flow/job_submission_state.d.ts +4 -0
- package/dist/presentation/flow/screen/helpers/face_session_config.d.ts +1 -1
- package/dist/presentation/flow/screen/helpers/failure_message.js +1 -1
- package/dist/presentation/flow/screen/orchestrated_capture_screen.js +1 -1
- package/dist/presentation/flow/screen/orchestrated_instructions_screen.js +1 -1
- package/dist/presentation/flow/screen/orchestrated_preview_screen.js +1 -1
- package/dist/presentation/flow/screen/orchestrated_processing_screen.js +1 -1
- package/dist/presentation/flow/use_smile_id_flow.js +1 -1
- package/dist/presentation/flow/validation/flow_validator.d.ts +0 -19
- package/dist/presentation/flow/validation/flow_validator.js +1 -1
- package/dist/presentation/flow/validation/job_type_validator.js +1 -1
- package/dist/presentation/screen/helpers/capture_screen_helpers.d.ts +0 -12
- package/dist/presentation/screen/helpers/capture_screen_helpers.js +1 -1
- package/dist/presentation/screen/helpers/capture_ui_state.d.ts +33 -6
- package/dist/presentation/screen/helpers/capture_ui_state.js +1 -1
- package/dist/presentation/screen/helpers/dropped_frames.d.ts +6 -0
- package/dist/presentation/screen/helpers/dropped_frames.js +1 -0
- package/dist/presentation/screen/helpers/ess_turn_haptics.d.ts +2 -0
- package/dist/presentation/screen/helpers/ess_turn_haptics.js +1 -1
- package/dist/presentation/screen/helpers/instructions_screen_helpers.d.ts +5 -1
- package/dist/presentation/screen/helpers/instructions_screen_helpers.js +1 -1
- package/dist/presentation/screen/helpers/use_capture_orientation_lock.d.ts +23 -1
- package/dist/presentation/screen/helpers/use_capture_orientation_lock.js +1 -1
- package/dist/presentation/screen/helpers/use_debounced_feedback_key.d.ts +1 -1
- package/dist/presentation/screen/helpers/use_debounced_feedback_key.js +1 -1
- package/dist/presentation/screen/use_smile_id_capture_screen.d.ts +4 -1
- package/dist/presentation/screen/use_smile_id_capture_screen.js +1 -1
- package/dist/presentation/screen/use_smile_id_consent_screen.js +1 -1
- package/dist/presentation/screen/use_smile_id_preview_screen.d.ts +3 -0
- package/dist/presentation/screen/use_smile_id_preview_screen.js +1 -1
- package/dist/presentation/screen/use_smile_id_processing_screen.d.ts +3 -0
- package/dist/presentation/screen/use_smile_id_processing_screen.js +1 -1
- package/dist/presentation/utils/locale_utils.d.ts +3 -6
- package/dist/presentation/utils/locale_utils.js +1 -1
- package/dist/testing/scenario_expectations.d.ts +7 -2
- package/dist/testing/scenario_expectations.js +1 -1
- package/dist/testing/scripted_scan_results.d.ts +2 -1
- package/dist/testing/scripted_scan_results.js +1 -1
- package/package.json +7 -7
- package/dist/presentation/flow/validation/user_details_validator.d.ts +0 -8
- package/dist/presentation/flow/validation/user_details_validator.js +0 -1
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** Records that a new take was just written to `uri`; call it as the capture is recorded. */
|
|
2
|
+
export declare function markCapturedTake(uri: string): void;
|
|
3
|
+
/**
|
|
4
|
+
* `uri` tagged with the take it holds, so every screen showing one take shares
|
|
5
|
+
* one cache entry and a retake gets its own. The image loaders read a `file://`
|
|
6
|
+
* URI's path, so the query only changes the cache key. A URI with no recorded
|
|
7
|
+
* take, one that is not a file, or one already tagged comes back unchanged.
|
|
8
|
+
*/
|
|
9
|
+
export declare function capturedImageUri(uri: string): string;
|
|
10
|
+
/** Test seam: forgets every recorded take. */
|
|
11
|
+
export declare function resetCapturedTakesForTesting(): void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";const t=new Map;let a=Date.now();const r="take=";export function markCapturedTake(e){a+=1,t.set(e,a)}export function capturedImageUri(e){const n=t.get(e);return n===void 0||!e.startsWith("file://")?e:`${e}${e.includes("?")?"&":"?"}${r}${n}`}export function resetCapturedTakesForTesting(){t.clear()}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { type SelfieSize } from "./selfie_interior_crop";
|
|
2
|
+
/** A rectangle in layout units, or image pixels. */
|
|
3
|
+
export type RegionRect = {
|
|
4
|
+
readonly x: number;
|
|
5
|
+
readonly y: number;
|
|
6
|
+
readonly width: number;
|
|
7
|
+
readonly height: number;
|
|
8
|
+
};
|
|
9
|
+
/** Width over height of the upright selfie camera frame: a 4:3 stream held in portrait. */
|
|
10
|
+
export declare const SELFIE_FRAME_ASPECT: number;
|
|
11
|
+
/**
|
|
12
|
+
* What a selfie capture screen laid out, so the review screens show what its oval showed: the size
|
|
13
|
+
* its camera covered and the shape (width over height) of the upright frames the camera showed.
|
|
14
|
+
*/
|
|
15
|
+
export type SelfieCaptureGeometry = {
|
|
16
|
+
readonly viewport: SelfieSize;
|
|
17
|
+
readonly frameAspect: number;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* How a captured selfie is placed in a review screen's oval so it shows what the capture screen's
|
|
21
|
+
* oval showed.
|
|
22
|
+
*
|
|
23
|
+
* The capture screen fills its `viewport` with the camera frame (`frameAspect`, width over
|
|
24
|
+
* height), covered and centred, and draws the oval where `FaceOvalDefaults` puts it: above the
|
|
25
|
+
* screen's centre. The selfie is saved from that frame, centre-cropped to its configured size, so
|
|
26
|
+
* centring it in the review oval would show a region lower than the one the user framed their face
|
|
27
|
+
* in (their neck) and smaller. Instead the region the capture oval covered fills the review oval.
|
|
28
|
+
*
|
|
29
|
+
* The frame's border ring stays out of view as before (`SelfieInteriorCrop`): the scale is never
|
|
30
|
+
* below the interior's cover scale, and the image is never moved so far that the ring shows.
|
|
31
|
+
*/
|
|
32
|
+
export declare function capturedOvalRegion(viewport: SelfieSize, frameAspect?: number): {
|
|
33
|
+
regionIn: (image: SelfieSize) => RegionRect;
|
|
34
|
+
scale: (image: SelfieSize, box: SelfieSize) => number;
|
|
35
|
+
offset: (drawn: SelfieSize, box: SelfieSize) => {
|
|
36
|
+
readonly x: number;
|
|
37
|
+
readonly y: number;
|
|
38
|
+
};
|
|
39
|
+
imageRect: (image: SelfieSize, box: SelfieSize) => RegionRect;
|
|
40
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";import{FaceOvalDefaults as l}from"../face_oval_defaults";import{SelfieInteriorCrop as w}from"./selfie_interior_crop";export const SELFIE_FRAME_ASPECT=3/4;export function capturedOvalRegion(i,c=SELFIE_FRAME_ASPECT){function d(t){if(r(t)||r(i)||!Number.isFinite(c)||c<=0)return{x:0,y:0,width:t.width,height:t.height};const h=t.width/t.height>=c?{width:t.width,height:t.width/c}:{width:t.height*c,height:t.height},n=(h.width-t.width)/2,o=(h.height-t.height)/2,e=Math.max(i.width/h.width,i.height/h.height),y=(i.width-h.width*e)/2,M=(i.height-h.height*e)/2,f=i.width*l.ovalWidthRatio,R=i.height*l.ovalHeightRatio,F=(i.width-f)/2,S=i.height*l.ovalTopRatio;return{x:(F-y)/e-n,y:(S-M)/e-o,width:f/e,height:R/e}}function g(t,h){if(r(t)||r(h))return 1;const n=d(t),o=n.width>0&&n.height>0?Math.max(h.width/n.width,h.height/n.height):0;return Math.max(o,w.coverScale(t,h))}function s(t,h){if(r(t)||r(h))return{x:0,y:0};const n=d(t),o=w.borderFraction*Math.min(t.width,t.height);return{x:a(h.width/2-(n.x+n.width/2),h.width,t.width,o),y:a(h.height/2-(n.y+n.height/2),h.height,t.height,o)}}function u(t,h){const n=g(t,h),o={width:t.width*n,height:t.height*n},e=s(o,h);return{x:e.x,y:e.y,...o}}return{regionIn:d,scale:g,offset:s,imageRect:u}}function a(i,c,d,g){const s=c-(d-g),u=-g;return s>u?(c-d)/2:Math.min(Math.max(i,s),u)}function r(i){return i.width<=0||i.height<=0}
|
|
@@ -20,7 +20,8 @@ export type DocumentImageRect = {
|
|
|
20
20
|
* each edge, so showing the outline alone could cut a captured document off; the
|
|
21
21
|
* screens that show the document fit the outline grown by that slack into their
|
|
22
22
|
* card instead (`shownSize`). A manual-shutter still or a gallery import is saved
|
|
23
|
-
* without a border, so its border fraction is 0 and it is shown whole
|
|
23
|
+
* without a border, so its border fraction is 0 and it is shown whole, in a card
|
|
24
|
+
* of its own shape (`cardAspectRatio`).
|
|
24
25
|
*/
|
|
25
26
|
export declare const DocumentInteriorCrop: {
|
|
26
27
|
/** The full border, as a fraction of the saved document's short side on every edge. */
|
|
@@ -39,10 +40,20 @@ export declare const DocumentInteriorCrop: {
|
|
|
39
40
|
* edge, and held to the image. The whole image when `borderFraction` is 0.
|
|
40
41
|
*/
|
|
41
42
|
readonly shownSize: (imageSize: SelfieSize, borderFraction: number) => SelfieSize;
|
|
43
|
+
/**
|
|
44
|
+
* Aspect ratio of the card a document is drawn in: `documentAspectRatio`, the
|
|
45
|
+
* shape of the outline the user framed, for a document saved with a border.
|
|
46
|
+
* One saved with none takes the shape of its `imageSize` once that is known,
|
|
47
|
+
* so the whole image fills the card with nothing beside it; a portrait photo
|
|
48
|
+
* of a passport would otherwise be a strip down the middle of a wide card.
|
|
49
|
+
*/
|
|
50
|
+
readonly cardAspectRatio: (imageSize: SelfieSize | null, documentAspectRatio: number, borderFraction: number) => number;
|
|
42
51
|
/**
|
|
43
52
|
* Uniform scale at which an `imageSize` document is drawn in a `boxSize` card,
|
|
44
53
|
* centred: its `shownSize` part fitted to the card, or, with no border, the
|
|
45
|
-
* whole image
|
|
54
|
+
* whole image fitted to it: a gallery import keeps the shape it was picked
|
|
55
|
+
* in, and covering the card with it would cut the document off. Returns 1
|
|
56
|
+
* when either size is degenerate.
|
|
46
57
|
*/
|
|
47
58
|
readonly cardScale: (imageSize: SelfieSize, boxSize: SelfieSize, borderFraction: number) => number;
|
|
48
59
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";export const DocumentInteriorCrop={fullBorderFraction:.15,guideEdgeSlack:.1,shownSize(t,h){const n=Math.min(Math.max(h,0),DocumentInteriorCrop.fullBorderFraction)*Math.min(t.width,t.height),
|
|
1
|
+
"use strict";export const DocumentInteriorCrop={fullBorderFraction:.15,guideEdgeSlack:.1,shownSize(t,h){const n=Math.min(Math.max(h,0),DocumentInteriorCrop.fullBorderFraction)*Math.min(t.width,t.height),d=1+2*DocumentInteriorCrop.guideEdgeSlack;return{width:Math.min(t.width,(t.width-2*n)*d),height:Math.min(t.height,(t.height-2*n)*d)}},cardAspectRatio(t,h,r){return r>0||t===null||t.width<=0||t.height<=0?h:t.width/t.height},cardScale(t,h,r){if(t.width<=0||t.height<=0||h.width<=0||h.height<=0)return 1;if(r<=0)return Math.min(h.width/t.width,h.height/t.height);const n=DocumentInteriorCrop.shownSize(t,r);return Math.min(h.width/n.width,h.height/n.height)},imageRect(t,h,r){const n=DocumentInteriorCrop.cardScale(t,h,r),d=t.width*n,c=t.height*n;return{left:(h.width-d)/2,top:(h.height-c)/2,width:d,height:c}}};
|
|
@@ -6,59 +6,65 @@ export type EnhancedSmartSelfieFrameRange = {
|
|
|
6
6
|
};
|
|
7
7
|
/**
|
|
8
8
|
* Per-direction keyframe sub-ranges within the
|
|
9
|
-
* `si_ess_animation_all_directions` composition (419 frames @ 30 fps)
|
|
10
|
-
* Each direction
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
9
|
+
* `si_ess_animation_all_directions` composition (419 frames @ 30 fps),
|
|
10
|
+
* scrubbed by a turn's progress. Each direction has a grey `turning` span,
|
|
11
|
+
* where the drawn head turns and the grey chevrons slide out, and a green
|
|
12
|
+
* `holding` span, where the head holds the turn and the green chevron slides
|
|
13
|
+
* further out. The spans skip the frames where the chevrons are not drawn yet
|
|
14
|
+
* or have faded. Pinned against the asset's layer in/out points — it carries
|
|
15
|
+
* no named markers — so this is a cross-platform contract: change only in
|
|
16
|
+
* lockstep with the sibling SDKs and re-derive when the asset changes.
|
|
16
17
|
*/
|
|
17
18
|
export declare const EnhancedSmartSelfieAnimationFrames: {
|
|
18
19
|
readonly left: {
|
|
19
|
-
readonly
|
|
20
|
-
readonly startFrame:
|
|
21
|
-
readonly endFrame:
|
|
20
|
+
readonly turning: {
|
|
21
|
+
readonly startFrame: 8;
|
|
22
|
+
readonly endFrame: 38;
|
|
22
23
|
};
|
|
23
|
-
readonly
|
|
24
|
+
readonly holding: {
|
|
24
25
|
readonly startFrame: 42;
|
|
25
|
-
readonly endFrame:
|
|
26
|
+
readonly endFrame: 90;
|
|
26
27
|
};
|
|
27
28
|
};
|
|
28
29
|
readonly right: {
|
|
29
|
-
readonly
|
|
30
|
-
readonly startFrame:
|
|
31
|
-
readonly endFrame:
|
|
30
|
+
readonly turning: {
|
|
31
|
+
readonly startFrame: 146;
|
|
32
|
+
readonly endFrame: 176;
|
|
32
33
|
};
|
|
33
|
-
readonly
|
|
34
|
+
readonly holding: {
|
|
34
35
|
readonly startFrame: 180;
|
|
35
|
-
readonly endFrame:
|
|
36
|
+
readonly endFrame: 225;
|
|
36
37
|
};
|
|
37
38
|
};
|
|
38
39
|
readonly up: {
|
|
39
|
-
readonly
|
|
40
|
-
readonly startFrame:
|
|
41
|
-
readonly endFrame:
|
|
40
|
+
readonly turning: {
|
|
41
|
+
readonly startFrame: 284;
|
|
42
|
+
readonly endFrame: 314;
|
|
42
43
|
};
|
|
43
|
-
readonly
|
|
44
|
+
readonly holding: {
|
|
44
45
|
readonly startFrame: 318;
|
|
45
|
-
readonly endFrame:
|
|
46
|
+
readonly endFrame: 365;
|
|
46
47
|
};
|
|
47
48
|
};
|
|
48
49
|
};
|
|
50
|
+
/**
|
|
51
|
+
* Share of a turn's progress taken by the turn toward the pose; the hold at
|
|
52
|
+
* the pose takes the rest. Matches the native `TURN_SHARE_OF_OVAL`.
|
|
53
|
+
*/
|
|
54
|
+
export declare const ENHANCED_SMART_SELFIE_TURN_SHARE = 0.8;
|
|
49
55
|
/** Total frame count of the all-directions composition. */
|
|
50
56
|
export declare const ENHANCED_SMART_SELFIE_TOTAL_FRAMES = 419;
|
|
51
57
|
/** Composition frame rate (frames per second). */
|
|
52
58
|
export declare const ENHANCED_SMART_SELFIE_FRAME_RATE = 30;
|
|
53
59
|
/**
|
|
54
|
-
* Playback rate for the ESS
|
|
55
|
-
* hectic
|
|
56
|
-
* followed.
|
|
60
|
+
* Playback rate for the ESS demo loop. At native speed the arrows read as
|
|
61
|
+
* hectic; 0.6× lets the motion be followed.
|
|
57
62
|
*/
|
|
58
63
|
export declare const ENHANCED_SMART_SELFIE_ANIMATION_SPEED = 0.6;
|
|
59
64
|
/**
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
65
|
+
* The keyframe that shows [turnProgress] of a turn toward [direction]. The
|
|
66
|
+
* turn toward the pose, the first {@link ENHANCED_SMART_SELFIE_TURN_SHARE} of
|
|
67
|
+
* the progress, scrubs the grey turning span; the hold at the pose, the rest,
|
|
68
|
+
* scrubs the green holding span. Pure, and the same in every SDK.
|
|
63
69
|
*/
|
|
64
|
-
export declare function
|
|
70
|
+
export declare function enhancedSmartSelfieTurnFrame(direction: ScanHeadTurnDirection, turnProgress: number): number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";export const EnhancedSmartSelfieAnimationFrames={left:{
|
|
1
|
+
"use strict";export const EnhancedSmartSelfieAnimationFrames={left:{turning:{startFrame:8,endFrame:38},holding:{startFrame:42,endFrame:90}},right:{turning:{startFrame:146,endFrame:176},holding:{startFrame:180,endFrame:225}},up:{turning:{startFrame:284,endFrame:314},holding:{startFrame:318,endFrame:365}}},ENHANCED_SMART_SELFIE_TURN_SHARE=.8,ENHANCED_SMART_SELFIE_TOTAL_FRAMES=419,ENHANCED_SMART_SELFIE_FRAME_RATE=30,ENHANCED_SMART_SELFIE_ANIMATION_SPEED=.6;export function enhancedSmartSelfieTurnFrame(e,a){const{turning:o,holding:s}=EnhancedSmartSelfieAnimationFrames[e],r=Math.min(Math.max(a,0),1),t=ENHANCED_SMART_SELFIE_TURN_SHARE,n=r<t?o:s,E=r<t?r/t:(r-t)/(1-t);return n.startFrame+(n.endFrame-n.startFrame)*E}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{useEffect as o,useState as d}from"react";import{Image as
|
|
1
|
+
"use strict";import{useEffect as o,useState as d}from"react";import{Image as h}from"react-native";import{capturedImageUri as u}from"./captured_image_uri";export const SelfieInteriorCrop={borderFraction:.15,coverScale(t,e){if(t.width<=0||t.height<=0||e.width<=0||e.height<=0)return 1;const n=SelfieInteriorCrop.borderFraction*Math.min(t.width,t.height);return Math.max(e.width/(t.width-2*n),e.height/(t.height-2*n))},unknownSizeRect(t){const e=1/(1-2*SelfieInteriorCrop.borderFraction),n=t.width*e,r=t.height*e;return{x:(t.width-n)/2,y:(t.height-r)/2,width:n,height:r}}};export function decodeUprightImageSize(t){return new Promise(e=>{if(typeof h.getSize!="function"){e(null);return}h.getSize(u(t),(n,r)=>e(n>0&&r>0?{width:n,height:r}:null),()=>e(null))})}export function useImageSize(t){const[e,n]=d({uri:t,result:{kind:"pending"}});return o(()=>{if(!t)return;let r=!0;return decodeUprightImageSize(t).then(i=>{r&&n({uri:t,result:i?{kind:"read",size:i}:{kind:"unreadable"}})}),()=>{r=!1}},[t]),e.uri===t?e.result:{kind:"pending"}}
|
|
@@ -13,8 +13,6 @@ export type UseSmileIDCaptureContentState = {
|
|
|
13
13
|
readonly enableEnhancedLiveness: boolean;
|
|
14
14
|
/** Active ESS head-turn direction, null outside a turn. */
|
|
15
15
|
readonly animationDirection: ScanHeadTurnDirection | null;
|
|
16
|
-
/** `true` while the head pose holds {@link animationDirection} — switches the cue grey→green. */
|
|
17
|
-
readonly poseMatched: boolean;
|
|
18
16
|
/** Settled (debounced) si_* feedback key; null hides the feedback bubble. */
|
|
19
17
|
readonly feedbackKey: SiKey | null;
|
|
20
18
|
/** Show the Start Capture control (pre-flight instruction state only). */
|
|
@@ -38,6 +36,11 @@ export type UseSmileIDCaptureContentProps = {
|
|
|
38
36
|
readonly state: UseSmileIDCaptureContentState;
|
|
39
37
|
/** 0..1 — bottom-to-top oval fill; always 0 under Enhanced Smart Selfie. */
|
|
40
38
|
readonly captureProgress: number;
|
|
39
|
+
/**
|
|
40
|
+
* 0..1 through the active ESS head turn, in 1/40 steps; scrubs the direction
|
|
41
|
+
* arrow. Kept off the state snapshot, like {@link captureProgress}.
|
|
42
|
+
*/
|
|
43
|
+
readonly turnProgress?: number;
|
|
41
44
|
/** Camera preview slot — previews/tests inject an inert placeholder. */
|
|
42
45
|
readonly cameraPreview: ReactNode;
|
|
43
46
|
readonly onStartCapture: () => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{jsx as i,Fragment as v,jsxs as c}from"react/jsx-runtime";import{memo as B,useState as A}from"react";import{Pressable as L,StyleSheet as T,Text as _,View as f}from"react-native";import{SafeAreaView as g}from"react-native-safe-area-context";import{CaptureType as U}from"../../core/models/ml_config";import{AttributionResolver as x}from"../flow/config/attribution_resolver";import{defaultLightTheme as b}from"../theme/theme";import{useUseSmileIDTheme as E}from"../theme/theme_context";import{isDocumentCaptureActive as y,UseSmileIDOverlayState as
|
|
1
|
+
"use strict";import{jsx as i,Fragment as v,jsxs as c}from"react/jsx-runtime";import{memo as B,useState as A}from"react";import{Pressable as L,StyleSheet as T,Text as _,View as f}from"react-native";import{SafeAreaView as g}from"react-native-safe-area-context";import{CaptureType as U}from"../../core/models/ml_config";import{AttributionResolver as x}from"../flow/config/attribution_resolver";import{defaultLightTheme as b}from"../theme/theme";import{useUseSmileIDTheme as E}from"../theme/theme_context";import{isDocumentCaptureActive as y,UseSmileIDOverlayState as K}from"../state/use_smile_id_overlay_state";import{SiOutlineClose as M}from"./icons";import{useUseSmileIDLocalizations as F}from"../../l10n/use_smile_id_localizations_provider";import{resolveFeedbackCopy as H}from"../screen/helpers/capture_screen_helpers";import{ATTRIBUTION_TEST_ID as R,UseSmileIDAttribution as W}from"./use_smile_id_attribution";import{UseSmileIDBackButton as j}from"./use_smile_id_back_button";import{UseSmileIDButton as G}from"./use_smile_id_button";import{UseSmileIDDocumentOverlay as O,resolveDocumentSide as P}from"./use_smile_id_document_overlay";import{UseSmileIDDocumentCaptureControls as z}from"./use_smile_id_document_capture_controls";import{UseSmileIDFaceOverlay as V}from"./use_smile_id_face_overlay";import{UseSmileIDCaptureInstructionAnimation as N}from"./use_smile_id_capture_instruction_animation";import{enhancedSmartSelfieInstructionAnimationKey as $}from"./helpers/capture_instruction_animation_spec";import{UseSmileIDEnhancedSmartSelfieDirectionAnimation as q}from"./use_smile_id_enhanced_smart_selfie_direction_animation";import{UseSmileIDEnhancedSmartSelfieFullAnimation as J}from"./use_smile_id_enhanced_smart_selfie_full_animation";import{FaceOvalDefaults as Q}from"./face_oval_defaults";const S=()=>{};function X(t){const C=E(),n=t.theme??C,a=F(),{state:e}=t,[o,D]=A({width:0,height:0}),I=m=>{const{width:d,height:u}=m.nativeEvent.layout;D(h=>h.width===d&&h.height===u?h:{width:d,height:u}),t.onViewportLayout?.({width:d,height:u})},r=e.captureType===U.selfie,w=x.resolveForCapture({captureType:e.captureType,showAttribution:t.showAttribution}),k=!r&&o.width>o.height,s=e.feedbackKey?H(e.feedbackKey,a):null,p=t.startButton;return c(f,{style:[l.root,{backgroundColor:n.colors.offBlack}],testID:"si_capture_screen",onLayout:I,children:[t.cameraPreview,o.width>0&&o.height>0?c(v,{children:[r?i(V,{state:e.overlayState,progress:t.captureProgress,containerWidth:o.width,containerHeight:o.height,enableEnhancedLiveness:e.enableEnhancedLiveness,theme:n}):i(O,{state:e.overlayState,containerWidth:o.width,containerHeight:o.height,theme:n,documentSide:P(e.documentSide,e.isBackSide),...e.documentTypeKind!==void 0?{documentTypeKind:e.documentTypeKind}:{},...e.knownIdAspectRatio!==void 0?{knownIdAspectRatio:e.knownIdAspectRatio}:{},...s!==null?{feedbackText:s}:{}}),r?i(N,{feedbackKey:e.enableEnhancedLiveness?$(e.feedbackKey):e.feedbackKey,containerWidth:o.width,containerHeight:o.height}):null,r&&e.enableEnhancedLiveness?e.animationDirection!==null?i(q,{direction:e.animationDirection,turnProgress:t.turnProgress??0,containerWidth:o.width,containerHeight:o.height}):e.overlayState===K.IDLE?i(J,{containerWidth:o.width,containerHeight:o.height}):null:null,r?null:i(z,{showManualShutter:(e.showManualShutter??!1)&&t.onManualShutter!==void 0&&!y(e.overlayState),showGallery:(e.showGalleryUpload??!1)&&t.onGalleryUpload!==void 0&&!y(e.overlayState),isLandscape:o.width>o.height,enabled:t.documentControlsEnabled??!0,onManualShutter:t.onManualShutter??S,onGallery:t.onGalleryUpload??S,shutterAccessibilityLabel:a.siCdDocumentCaptureShutter,galleryAccessibilityLabel:a.siCdDocumentGallery,closeAccessibilityLabel:a.siCdClose,onClose:t.onClose})]}):null,c(g,{edges:["top","left","right"],style:[l.topBar,{paddingHorizontal:n.spacing.medium,paddingTop:n.spacing.medium}],pointerEvents:"box-none",children:[t.onBack?i(j,{onClick:t.onBack,forceLightMode:!0,theme:n,testID:"si_capture_back_button"}):i(f,{style:l.chromeSpacer}),t.onClose&&!k?i(L,{onPress:t.onClose,accessibilityRole:"button",accessibilityLabel:a.siCdClose,testID:"si_capture_close_button",style:({pressed:m})=>[l.closeButton,{backgroundColor:b.colors.offBlack,borderColor:b.colors.backButtonBorder,opacity:m?.7:1}],children:i(M,{size:20,color:b.colors.offWhite})}):null]}),s!==null&&r?i(f,{style:[l.feedbackBubble,{paddingHorizontal:n.spacing.medium,paddingVertical:n.spacing.small}],pointerEvents:"none",children:i(_,{style:{...n.typography.cardTitle,color:n.colors.primary,textAlign:"center"},testID:"si_capture_feedback_text",children:s})}):null,c(g,{edges:["bottom","left","right"],style:[l.bottom,{paddingHorizontal:n.spacing.medium,paddingBottom:n.spacing.large,gap:n.spacing.small}],pointerEvents:"box-none",children:[e.showCaptureButton?p?p({onClick:t.onStartCapture,enabled:t.startCaptureEnabled}):i(G,{label:a.siCaptureStartButton,onClick:t.onStartCapture,variant:"primary",enabled:t.startCaptureEnabled,forceLightMode:!0,theme:n,testID:"si_capture_start_button"}):null,w?i(W,{forceLightMode:!0,theme:n,testID:R}):null]})]})}export const UseSmileIDCaptureContent=B(X);const l=T.create({root:{flex:1},topBar:{position:"absolute",top:0,start:0,end:0,flexDirection:"row",justifyContent:"space-between",alignItems:"flex-start"},closeButton:{width:40,height:40,borderRadius:20,borderWidth:1,alignItems:"center",justifyContent:"center"},chromeSpacer:{width:40,height:40},feedbackBubble:{position:"absolute",top:`${Math.round(Q.feedbackTopRatio*100)}%`,alignSelf:"center",maxWidth:"85%"},bottom:{position:"absolute",bottom:0,start:0,end:0,alignItems:"center"}});
|
|
@@ -3,7 +3,10 @@ import type { UseSmileIDTheme } from "../theme/theme";
|
|
|
3
3
|
export type UseSmileIDCapturedDocumentImageProps = {
|
|
4
4
|
/** Local file URI (`file:///…`) of the captured document side. */
|
|
5
5
|
readonly uri?: string;
|
|
6
|
-
/**
|
|
6
|
+
/**
|
|
7
|
+
* Capture-frame aspect ratio (width / height) the box keeps while fitting the region; a document
|
|
8
|
+
* saved with no border keeps its image's own instead.
|
|
9
|
+
*/
|
|
7
10
|
readonly aspectRatio: number;
|
|
8
11
|
/**
|
|
9
12
|
* The hidden border `uri` was saved with, as a fraction of its short side on every edge. The
|
|
@@ -30,8 +33,9 @@ export type UseSmileIDCapturedDocumentImageProps = {
|
|
|
30
33
|
readonly theme?: UseSmileIDTheme;
|
|
31
34
|
};
|
|
32
35
|
/**
|
|
33
|
-
* Captured document image at its capture aspect,
|
|
34
|
-
* to the largest box that fits the padded region —
|
|
35
|
-
* {@link UseSmileIDCapturedImageOval}. Shared by the document
|
|
36
|
+
* Captured document image at its capture aspect, or a document saved with no border at its own,
|
|
37
|
+
* clipped to an 8dp rounded rectangle and sized to the largest box that fits the padded region —
|
|
38
|
+
* the rectangular counterpart to {@link UseSmileIDCapturedImageOval}. Shared by the document
|
|
39
|
+
* preview and the processing screen.
|
|
36
40
|
*/
|
|
37
41
|
export declare function UseSmileIDCapturedDocumentImage(props: UseSmileIDCapturedDocumentImageProps): import("react").JSX.Element;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{jsx as l,jsxs as
|
|
1
|
+
"use strict";import{jsx as l,jsxs as E}from"react/jsx-runtime";import{useState as b}from"react";import{Image as k,StyleSheet as f,View as c}from"react-native";import{useUseSmileIDTheme as F}from"../theme/theme_context";import{fitCapturedDocumentImage as A}from"./helpers/captured_document_image_fit";import{DocumentInteriorCrop as I}from"./helpers/document_interior_crop";import{useImageSize as B}from"./helpers/selfie_interior_crop";import{useDocumentPreviewOverlayEnabled as O}from"../../debug/use_smile_id_debug";import{DocumentPreviewHiddenRegionsInPlace as U}from"../../debug/use_smile_id_document_preview_debug_overlay";import{capturedImageUri as P}from"./helpers/captured_image_uri";const w=8;export function UseSmileIDCapturedDocumentImage(e){const d=e.uri===void 0?void 0:P(e.uri),x=F(),R=e.theme??x,n=e.borderFraction??0,t=B(d),g=I.cardAspectRatio(t.kind==="read"?t.size:null,e.aspectRatio,n),h=R.spacing.large,[y,v]=b({width:0,height:0}),D=u=>{const{width:o,height:a}=u.nativeEvent.layout;v(i=>i.width===o&&i.height===a?i:{width:o,height:a})},S=A(g,y.width-2*h,y.height)??{...r.fillWidth,aspectRatio:g},z=O()&&e.showDebugOverlay===!0,[s,C]=b(null),L=u=>{const{width:o,height:a}=u.nativeEvent.layout;C(i=>i?.width===o&&i.height===a?i:{width:o,height:a}),e.onCardLayout?.({width:o,height:a})},m=n>0&&s!==null&&t.kind==="read"?I.imageRect(t.size,s,n):null,j=!!d&&(m!==null||t.kind==="unreadable"||n<=0&&t.kind==="read");return l(c,{style:[r.region,{paddingHorizontal:h}],onLayout:D,testID:e.testID,children:E(c,{style:[r.imageBox,S],onLayout:L,children:[j?l(k,{source:{uri:d},resizeMode:n>0?"cover":"contain",style:m?[r.interiorImage,m]:r.image,testID:e.imageTestID,...e.imageAccessibilityLabel?{accessible:!0,accessibilityRole:"image",accessibilityLabel:e.imageAccessibilityLabel}:{}}):null,z&&s!==null&&t.kind==="read"?l(c,{pointerEvents:"none",style:f.absoluteFill,children:l(U,{imageSize:t.size,cardSize:s,borderFraction:n})}):null,e.overlayChild?l(c,{pointerEvents:"box-none",style:r.overlay,children:e.overlayChild}):null]})})}const r=f.create({region:{flex:1,alignItems:"center",justifyContent:"center"},imageBox:{borderRadius:w,overflow:"hidden"},fillWidth:{width:"100%"},image:{width:"100%",height:"100%",borderRadius:w},interiorImage:{position:"absolute"},overlay:{position:"absolute",top:0,bottom:0,start:0,end:0,alignItems:"center",justifyContent:"center"}});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type ReactNode } from "react";
|
|
2
2
|
import type { UseSmileIDTheme } from "../theme/theme";
|
|
3
|
+
import { type SelfieCaptureGeometry } from "./helpers/captured_oval_region";
|
|
3
4
|
export type UseSmileIDCapturedImageOvalProps = {
|
|
4
5
|
/**
|
|
5
6
|
* Full screen width. The oval proportions are sized against the
|
|
@@ -29,6 +30,11 @@ export type UseSmileIDCapturedImageOvalProps = {
|
|
|
29
30
|
* Only the preview screen sets it; inert in release builds.
|
|
30
31
|
*/
|
|
31
32
|
readonly showDebugOverlay?: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* @internal What the flow's selfie capture screen laid out; omitted maps through this screen's
|
|
35
|
+
* size and the 4:3 selfie stream.
|
|
36
|
+
*/
|
|
37
|
+
readonly captureGeometry?: SelfieCaptureGeometry;
|
|
32
38
|
readonly testID?: string;
|
|
33
39
|
readonly theme?: UseSmileIDTheme;
|
|
34
40
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{jsx as i,jsxs as
|
|
1
|
+
"use strict";import{jsx as i,jsxs as u}from"react/jsx-runtime";import{useId as x,useState as S}from"react";import{StyleSheet as w,View as s}from"react-native";import D,{ClipPath as H,Defs as R,Ellipse as W,Image as C}from"react-native-svg";import{useSelfiePreviewOverlayEnabled as O}from"../../debug/use_smile_id_debug";import{UseSmileIDSelfiePreviewDebugOverlay as p}from"../../debug/use_smile_id_selfie_preview_debug_overlay";import{useUseSmileIDTheme as E}from"../theme/theme_context";import{computeScaledOvalGeometry as L}from"./helpers/scaled_oval_geometry";import{SelfieInteriorCrop as j,useImageSize as _}from"./helpers/selfie_interior_crop";import{capturedImageUri as z}from"./helpers/captured_image_uri";import{capturedOvalRegion as A}from"./helpers/captured_oval_region";export function UseSmileIDCapturedImageOval(e){const l=e.uri===void 0?void 0:z(e.uri),v=E(),y=e.theme??v,[m,f]=S(0),d=`si_oval_clip_${x().replace(/:/g,"")}`,b=O(),a=_(l),I=n=>{f(n.nativeEvent.layout.height)},t=e.screenWidth>0&&e.screenHeight>0&&m>0?L(e.screenWidth,e.screenHeight,m,y.spacing.medium):null,r=t!==null&&t.scale>0,g=A(e.captureGeometry?.viewport??{width:e.screenWidth,height:e.screenHeight},e.captureGeometry?.frameAspect),o=(()=>{if(!t||a.kind==="pending")return null;const n={width:t.ovalWidth,height:t.ovalHeight};return a.kind==="unreadable"?j.unknownSizeRect(n):g.imageRect(a.size,n)})(),c=t?{width:t.ovalWidth,height:t.ovalHeight,left:t.ovalLeft,top:t.ovalTop}:{width:0,height:0,left:0,top:0};return u(s,{style:h.region,onLayout:I,testID:e.testID,children:[l?i(s,{pointerEvents:"none",style:[h.oval,c],testID:e.imageTestID,...e.imageAccessibilityLabel?{accessible:!0,accessibilityRole:"image",accessibilityLabel:e.imageAccessibilityLabel}:{},children:r&&t&&o?u(D,{width:"100%",height:"100%",viewBox:`0 0 ${t.ovalWidth} ${t.ovalHeight}`,children:[i(R,{children:i(H,{id:d,children:i(W,{cx:t.ovalWidth/2,cy:t.ovalHeight/2,rx:t.ovalWidth/2,ry:t.ovalHeight/2})})}),i(C,{href:{uri:l},x:o.x,y:o.y,width:o.width,height:o.height,preserveAspectRatio:"xMidYMid slice",clipPath:`url(#${d})`})]}):null}):null,e.overlayChild&&r?i(s,{pointerEvents:"box-none",style:[h.overlay,c],children:e.overlayChild}):null,e.showDebugOverlay&&b&&l&&r?i(p,{uri:l,ovalRect:c,placement:g}):null]})}const h=w.create({region:{flex:1},oval:{position:"absolute"},overlay:{position:"absolute",alignItems:"center",justifyContent:"center"}});
|
|
@@ -7,20 +7,30 @@ export declare const ESS_ALL_DIRECTIONS_ANIMATION: AnimationObject;
|
|
|
7
7
|
export declare const ENHANCED_SMART_SELFIE_ARROW_FIT = 1.15;
|
|
8
8
|
/** Nudge so the composition's face lands on the oval centre. */
|
|
9
9
|
export declare const VERTICAL_ALIGNMENT_OFFSET = -15;
|
|
10
|
+
/**
|
|
11
|
+
* The square box both ESS cues draw in, centred on the face oval: the oval's
|
|
12
|
+
* width times {@link ENHANCED_SMART_SELFIE_ARROW_FIT}, nudged by
|
|
13
|
+
* {@link VERTICAL_ALIGNMENT_OFFSET}. One source, so the demo and the
|
|
14
|
+
* direction arrow always line up.
|
|
15
|
+
*/
|
|
16
|
+
export declare function essAnimationBoxStyle(containerWidth: number, containerHeight: number): {
|
|
17
|
+
position: "absolute";
|
|
18
|
+
left: number;
|
|
19
|
+
top: number;
|
|
20
|
+
width: number;
|
|
21
|
+
height: number;
|
|
22
|
+
};
|
|
10
23
|
export type UseSmileIDEnhancedSmartSelfieClipProps = {
|
|
11
|
-
readonly startFrame: number;
|
|
12
24
|
readonly endFrame: number;
|
|
13
|
-
/** Play forward-then-back instead of restarting from the first frame. */
|
|
14
|
-
readonly pingPong: boolean;
|
|
15
25
|
readonly containerWidth: number;
|
|
16
26
|
readonly containerHeight: number;
|
|
17
27
|
readonly testID: string;
|
|
18
28
|
};
|
|
19
29
|
/**
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
30
|
+
* Renderer for the Enhanced Smart Selfie demo — loops the all-directions
|
|
31
|
+
* composition, centred on the face oval. Reduced motion holds the clip's
|
|
32
|
+
* final frame.
|
|
23
33
|
*
|
|
24
|
-
* @internal Used by the full
|
|
34
|
+
* @internal Used by the full ESS animation component.
|
|
25
35
|
*/
|
|
26
36
|
export declare function UseSmileIDEnhancedSmartSelfieClip(props: UseSmileIDEnhancedSmartSelfieClipProps): import("react").JSX.Element | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{jsx as
|
|
1
|
+
"use strict";import{jsx as i}from"react/jsx-runtime";import{View as l}from"react-native";import a from"lottie-react-native";import{useReducedMotion as _}from"../utils/use_reduced_motion";import{FaceOvalDefaults as E}from"./face_oval_defaults";import{ENHANCED_SMART_SELFIE_ANIMATION_SPEED as c,ENHANCED_SMART_SELFIE_TOTAL_FRAMES as u}from"./helpers/enhanced_smart_selfie_animation_frames";export const ESS_ALL_DIRECTIONS_ANIMATION=require("../assets/si_ess_animation_all_directions.json"),ENHANCED_SMART_SELFIE_ARROW_FIT=1.15,VERTICAL_ALIGNMENT_OFFSET=-15;export function essAnimationBoxStyle(t,n){const e=t*E.ovalWidthRatio*ENHANCED_SMART_SELFIE_ARROW_FIT,o=n*E.ovalCenterYRatio;return{position:"absolute",left:(t-e)/2,top:o-e/2+VERTICAL_ALIGNMENT_OFFSET,width:e,height:e}}export function UseSmileIDEnhancedSmartSelfieClip(t){const n=_(),{endFrame:e,containerWidth:o,containerHeight:r}=t;if(o<=0||r<=0)return null;const s=essAnimationBoxStyle(o,r);return n?i(l,{pointerEvents:"none",style:s,testID:t.testID,children:i(a,{source:ESS_ALL_DIRECTIONS_ANIMATION,progress:e/u,autoPlay:!1,loop:!1,style:{width:"100%",height:"100%"}})}):i(l,{pointerEvents:"none",style:s,testID:t.testID,children:i(a,{source:ESS_ALL_DIRECTIONS_ANIMATION,autoPlay:!0,loop:!0,speed:c,style:{width:"100%",height:"100%"}})})}
|
package/dist/presentation/components/use_smile_id_enhanced_smart_selfie_direction_animation.d.ts
CHANGED
|
@@ -1,24 +1,23 @@
|
|
|
1
1
|
import type { ScanHeadTurnDirection } from "@smileid/usesmileid_bridge";
|
|
2
|
+
/**
|
|
3
|
+
* How long the arrow takes to reach a new progress: short, so it stays with
|
|
4
|
+
* the head. The same as the other SDKs.
|
|
5
|
+
*/
|
|
6
|
+
export declare const ENHANCED_SMART_SELFIE_TURN_FOLLOW_MS = 100;
|
|
2
7
|
export type UseSmileIDEnhancedSmartSelfieDirectionAnimationProps = {
|
|
3
8
|
/** Active head-turn direction from the scan state; null renders nothing. */
|
|
4
9
|
readonly direction: ScanHeadTurnDirection | null;
|
|
5
|
-
/**
|
|
6
|
-
|
|
7
|
-
* from the grey "pending" keyframe span to the green "matched" span.
|
|
8
|
-
*/
|
|
9
|
-
readonly poseMatched: boolean;
|
|
10
|
+
/** How much of the turn is done, 0–1; scrubs the cue. */
|
|
11
|
+
readonly turnProgress: number;
|
|
10
12
|
readonly containerWidth: number;
|
|
11
13
|
readonly containerHeight: number;
|
|
12
14
|
};
|
|
13
15
|
/**
|
|
14
|
-
* Enhanced Smart Selfie head-turn cue
|
|
15
|
-
*
|
|
16
|
-
* the
|
|
17
|
-
*
|
|
18
|
-
* the
|
|
19
|
-
*
|
|
20
|
-
* Reduced motion holds the clip's final (turned-head) frame. Never
|
|
21
|
-
* mirrored in RTL so the analyzer sees identical expected head-turn
|
|
22
|
-
* directions in every locale.
|
|
16
|
+
* Enhanced Smart Selfie head-turn cue, moved by the turn itself rather than
|
|
17
|
+
* looped: as the head turns toward {@link direction} the drawn head turns and
|
|
18
|
+
* the grey chevrons slide out; as it holds there the chevron turns green and
|
|
19
|
+
* slides further. Turning back moves it back, so the cue stays in step with
|
|
20
|
+
* the head. Never mirrored in RTL so the analyzer sees identical expected
|
|
21
|
+
* head-turn directions in every locale.
|
|
23
22
|
*/
|
|
24
23
|
export declare function UseSmileIDEnhancedSmartSelfieDirectionAnimation(props: UseSmileIDEnhancedSmartSelfieDirectionAnimationProps): import("react").JSX.Element | null;
|
package/dist/presentation/components/use_smile_id_enhanced_smart_selfie_direction_animation.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{jsx as
|
|
1
|
+
"use strict";import{jsx as m}from"react/jsx-runtime";import{useEffect as l,useRef as c}from"react";import{Animated as u,Easing as f,View as d}from"react-native";import{AnimatedLottieView as _}from"./helpers/animated_lottie_view";import{useReducedMotion as E}from"../utils/use_reduced_motion";import{ENHANCED_SMART_SELFIE_TOTAL_FRAMES as S,enhancedSmartSelfieTurnFrame as A}from"./helpers/enhanced_smart_selfie_animation_frames";import{ESS_ALL_DIRECTIONS_ANIMATION as p,essAnimationBoxStyle as g}from"./use_smile_id_enhanced_smart_selfie_clip";export const ENHANCED_SMART_SELFIE_TURN_FOLLOW_MS=100;export function UseSmileIDEnhancedSmartSelfieDirectionAnimation(i){const{direction:n,containerWidth:r,containerHeight:o}=i,s=E(),e=n===null?0:A(n,i.turnProgress)/S,t=c(new u.Value(e)).current;return l(()=>{if(s){t.setValue(e);return}const a=u.timing(t,{toValue:e,duration:ENHANCED_SMART_SELFIE_TURN_FOLLOW_MS,easing:f.linear,useNativeDriver:!1});return a.start(),()=>a.stop()},[e,s,t]),n===null||r<=0||o<=0?null:m(d,{pointerEvents:"none",style:g(r,o),testID:"si_ess_direction_animation",children:m(_,{source:p,progress:t,autoPlay:!1,loop:!1,style:{width:"100%",height:"100%"}})})}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{jsx as i}from"react/jsx-runtime";import{ENHANCED_SMART_SELFIE_TOTAL_FRAMES as n}from"./helpers/enhanced_smart_selfie_animation_frames";import{UseSmileIDEnhancedSmartSelfieClip as t}from"./use_smile_id_enhanced_smart_selfie_clip";export function UseSmileIDEnhancedSmartSelfieFullAnimation(e){return i(t,{
|
|
1
|
+
"use strict";import{jsx as i}from"react/jsx-runtime";import{ENHANCED_SMART_SELFIE_TOTAL_FRAMES as n}from"./helpers/enhanced_smart_selfie_animation_frames";import{UseSmileIDEnhancedSmartSelfieClip as t}from"./use_smile_id_enhanced_smart_selfie_clip";export function UseSmileIDEnhancedSmartSelfieFullAnimation(e){return i(t,{endFrame:n,containerWidth:e.containerWidth,containerHeight:e.containerHeight,testID:"si_ess_full_animation"})}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{jsx as
|
|
1
|
+
"use strict";import{jsx as r,jsxs as c}from"react/jsx-runtime";import h,{ClipPath as s,Defs as m,Ellipse as d,Image as g}from"react-native-svg";import{StyleSheet as f,View as u}from"react-native";import{computeFaceOvalGeometry as v}from"./face_oval_defaults";import{capturedImageUri as x}from"./helpers/captured_image_uri";export function UseSmileIDFaceOvalImage(e){const n=x(e.uri);if(e.containerWidth<=0||e.containerHeight<=0||n.length===0)return null;const{ovalWidth:t,ovalHeight:i,ovalLeft:a,ovalTop:l}=v(e.containerWidth,e.containerHeight),o="si_face_oval_image_clip";return r(u,{pointerEvents:"none",style:[p.container,{width:t,height:i,left:a,top:l}],testID:e.testID,children:c(h,{width:"100%",height:"100%",viewBox:`0 0 ${t} ${i}`,children:[r(m,{children:r(s,{id:o,children:r(d,{cx:t/2,cy:i/2,rx:t/2,ry:i/2})})}),r(g,{href:{uri:n},x:0,y:0,width:t,height:i,preserveAspectRatio:"xMidYMid slice",clipPath:`url(#${o})`})]})})}const p=f.create({container:{position:"absolute"}});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `selfie_session_restarted` reasons this SDK builds itself, as the
|
|
3
|
+
* shared `analytics-contract.json` lists them. The native capture reports
|
|
4
|
+
* the rest. @internal
|
|
5
|
+
*/
|
|
6
|
+
export declare const UnsatisfiedReasons: {
|
|
7
|
+
/** The reason sent when the native capture restarts without one. */
|
|
8
|
+
readonly fallback: "unknown";
|
|
9
|
+
/**
|
|
10
|
+
* The prefix of every reason the selfie upload check reports
|
|
11
|
+
* (`upload_check_` plus the problem), which the native bridge builds.
|
|
12
|
+
*/
|
|
13
|
+
readonly uploadCheckPrefix: "upload_check_";
|
|
14
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";export const UnsatisfiedReasons={fallback:"unknown",uploadCheckPrefix:"upload_check_"};
|
|
@@ -16,6 +16,8 @@ export declare const UseSmileIDAnalyticsEventTypes: {
|
|
|
16
16
|
readonly documentCaptured: "document_captured";
|
|
17
17
|
readonly retakeRequested: "retake_requested";
|
|
18
18
|
readonly jobSubmitted: "job_submitted";
|
|
19
|
+
/** Fired instead of `jobSubmitted` when `skipApiSubmission` hands the assembled job to the partner. Extras: `job_type`. */
|
|
20
|
+
readonly jobCaptured: "job_captured";
|
|
19
21
|
readonly flowCompleted: "flow_completed";
|
|
20
22
|
/**
|
|
21
23
|
* Selfie capture session restarts after Unsatisfied. Extras:
|
|
@@ -60,16 +62,15 @@ export declare const UseSmileIDAnalyticsScreenNames: {
|
|
|
60
62
|
readonly processing: "processing";
|
|
61
63
|
};
|
|
62
64
|
/**
|
|
63
|
-
* Stable wire-identifier strings for
|
|
64
|
-
*
|
|
65
|
-
*
|
|
65
|
+
* Stable wire-identifier strings for `selfie_frame_rejected`'s `reason`
|
|
66
|
+
* extras key, and `qualityDropTimeout`, one of `selfie_session_restarted`'s
|
|
67
|
+
* (all of which the shared analytics contract lists as `restartReasons`).
|
|
68
|
+
* Partner dashboards aggregate on these — never change a value here without
|
|
69
|
+
* bumping the wire format.
|
|
66
70
|
*/
|
|
67
71
|
export declare const UseSmileIDAnalyticsReasons: {
|
|
68
|
-
readonly outOfFrame: "out_of_frame";
|
|
69
|
-
readonly timeout: "timeout";
|
|
70
|
-
readonly qualityDropTimeout: "quality_drop_timeout";
|
|
71
72
|
readonly motionBlur: "motion_blur";
|
|
72
|
-
readonly
|
|
73
|
+
readonly qualityDropTimeout: "quality_drop_timeout";
|
|
73
74
|
};
|
|
74
75
|
/** Read an event back as a typed `UseSmileIDAnalyticsEventKind` with `analyticsEventKind(event)`. */
|
|
75
76
|
export type UseSmileIDAnalyticsEvent = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";export const UseSmileIDAnalyticsEventTypes={flowStarted:"flow_started",screenViewed:"screen_viewed",consentCaptured:"consent_captured",selfieCaptured:"selfie_captured",documentCaptured:"document_captured",retakeRequested:"retake_requested",jobSubmitted:"job_submitted",flowCompleted:"flow_completed",selfieSessionRestarted:"selfie_session_restarted",selfieFrameRejected:"selfie_frame_rejected"},UseSmileIDAnalyticsParamKeys={jobType:"job_type",jobTypeId:"job_type_id",screenName:"screen_name",sessionId:"session_id",timestamp:"timestamp",documentSide:"document_side",decision:"decision",livenessImageCount:"liveness_image_count",attempt:"attempt",jobId:"job_id",result:"result",errorMessage:"error_message",reason:"reason",framesDiscarded:"frames_discarded",durationMs:"duration_ms",iou:"iou",probability:"probability"},UseSmileIDAnalyticsScreenNames={consent:"consent",instructions:"instructions",capture:"capture",preview:"preview",processing:"processing"},UseSmileIDAnalyticsReasons={
|
|
1
|
+
"use strict";export const UseSmileIDAnalyticsEventTypes={flowStarted:"flow_started",screenViewed:"screen_viewed",consentCaptured:"consent_captured",selfieCaptured:"selfie_captured",documentCaptured:"document_captured",retakeRequested:"retake_requested",jobSubmitted:"job_submitted",jobCaptured:"job_captured",flowCompleted:"flow_completed",selfieSessionRestarted:"selfie_session_restarted",selfieFrameRejected:"selfie_frame_rejected"},UseSmileIDAnalyticsParamKeys={jobType:"job_type",jobTypeId:"job_type_id",screenName:"screen_name",sessionId:"session_id",timestamp:"timestamp",documentSide:"document_side",decision:"decision",livenessImageCount:"liveness_image_count",attempt:"attempt",jobId:"job_id",result:"result",errorMessage:"error_message",reason:"reason",framesDiscarded:"frames_discarded",durationMs:"duration_ms",iou:"iou",probability:"probability"},UseSmileIDAnalyticsScreenNames={consent:"consent",instructions:"instructions",capture:"capture",preview:"preview",processing:"processing"},UseSmileIDAnalyticsReasons={motionBlur:"motion_blur",qualityDropTimeout:"quality_drop_timeout"};
|
|
@@ -49,6 +49,11 @@ export type UseSmileIDAnalyticsEventKind =
|
|
|
49
49
|
readonly jobType: JobType;
|
|
50
50
|
readonly attempt: number;
|
|
51
51
|
}
|
|
52
|
+
/** `skipApiSubmission` handed the assembled job to the partner instead of submitting it. */
|
|
53
|
+
| {
|
|
54
|
+
readonly kind: "jobCaptured";
|
|
55
|
+
readonly jobType: JobType;
|
|
56
|
+
}
|
|
52
57
|
/** Smile ID accepted the submission; `jobId` is sent when it is known. */
|
|
53
58
|
| {
|
|
54
59
|
readonly kind: "flowCompletedSuccess";
|
|
@@ -59,6 +64,10 @@ export type UseSmileIDAnalyticsEventKind =
|
|
|
59
64
|
readonly kind: "flowCompletedFailure";
|
|
60
65
|
readonly errorMessage: string;
|
|
61
66
|
}
|
|
67
|
+
/** `skipApiSubmission` handed the job to the partner; nothing was submitted. */
|
|
68
|
+
| {
|
|
69
|
+
readonly kind: "flowCompletedCaptured";
|
|
70
|
+
}
|
|
62
71
|
/** The selfie session restarted after its requirements stopped being met. */
|
|
63
72
|
| {
|
|
64
73
|
readonly kind: "selfieSessionRestarted";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{DocumentSide as
|
|
1
|
+
"use strict";import{DocumentSide as m}from"@smileid/usesmileid_bridge";import{JobType as S}from"../../../core/models/job_type";import{UseSmileIDAnalyticsEventTypes as r,UseSmileIDAnalyticsParamKeys as n,UseSmileIDAnalyticsScreenNames as y}from"./use_smile_id_analytics_event";const a="granted",c="success",f="failure",p="captured";function o(e){return{[n.jobType]:String(e),[n.jobTypeId]:String(e)}}export function encodeAnalyticsEventKind(e){const t=r;switch(e.kind){case"flowStarted":return{type:t.flowStarted,extras:o(e.jobType)};case"screenViewed":return{type:t.screenViewed,extras:{[n.screenName]:e.screen}};case"consentCaptured":return{type:t.consentCaptured,extras:{[n.decision]:a}};case"selfieCaptured":return{type:t.selfieCaptured,extras:{[n.livenessImageCount]:String(e.livenessImageCount)}};case"documentCaptured":return{type:t.documentCaptured,extras:{[n.documentSide]:e.side}};case"retakeRequested":return{type:t.retakeRequested,extras:{}};case"jobSubmitted":return{type:t.jobSubmitted,extras:{...o(e.jobType),[n.attempt]:String(e.attempt)}};case"jobCaptured":return{type:t.jobCaptured,extras:o(e.jobType)};case"flowCompletedSuccess":return{type:t.flowCompleted,extras:{[n.result]:c,...e.jobId?{[n.jobId]:e.jobId}:{}}};case"flowCompletedFailure":return{type:t.flowCompleted,extras:{[n.result]:f,[n.errorMessage]:e.errorMessage}};case"flowCompletedCaptured":return{type:t.flowCompleted,extras:{[n.result]:p}};case"selfieSessionRestarted":return{type:t.selfieSessionRestarted,extras:{[n.reason]:e.reason,[n.framesDiscarded]:String(e.framesDiscarded),[n.durationMs]:String(e.durationMs)}};case"selfieFrameRejected":return{type:t.selfieFrameRejected,extras:{[n.reason]:e.reason}}}}function s(e){if(!(e===void 0||!/^-?\d+$/.test(e)))return Number(e)}function i(e){const t=s(e[n.jobTypeId])??s(e[n.jobType]);return Object.values(S).find(d=>d===t)}const C=Object.values(y),b=Object.values(m),l={[r.flowStarted]:e=>{const t=i(e);return t===void 0?void 0:{kind:"flowStarted",jobType:t}},[r.screenViewed]:e=>{const t=e[n.screenName];return t!==void 0&&C.includes(t)?{kind:"screenViewed",screen:t}:void 0},[r.consentCaptured]:e=>e[n.decision]===a?{kind:"consentCaptured"}:void 0,[r.selfieCaptured]:e=>{const t=s(e[n.livenessImageCount]);return t===void 0?void 0:{kind:"selfieCaptured",livenessImageCount:t}},[r.documentCaptured]:e=>{const t=e[n.documentSide];return t!==void 0&&b.includes(t)?{kind:"documentCaptured",side:t}:void 0},[r.retakeRequested]:()=>({kind:"retakeRequested"}),[r.jobSubmitted]:e=>{const t=i(e),d=s(e[n.attempt]);return t===void 0||d===void 0?void 0:{kind:"jobSubmitted",jobType:t,attempt:d}},[r.jobCaptured]:e=>{const t=i(e);return t===void 0?void 0:{kind:"jobCaptured",jobType:t}},[r.flowCompleted]:e=>{switch(e[n.result]){case c:{const t=e[n.jobId];return t?{kind:"flowCompletedSuccess",jobId:t}:{kind:"flowCompletedSuccess"}}case f:{const t=e[n.errorMessage];return t===void 0?void 0:{kind:"flowCompletedFailure",errorMessage:t}}case p:return{kind:"flowCompletedCaptured"};default:return}},[r.selfieSessionRestarted]:e=>{const t=e[n.reason],d=s(e[n.framesDiscarded]),u=s(e[n.durationMs]);return t===void 0||d===void 0||u===void 0?void 0:{kind:"selfieSessionRestarted",reason:t,framesDiscarded:d,durationMs:u}},[r.selfieFrameRejected]:e=>{const t=e[n.reason];return t===void 0?void 0:{kind:"selfieFrameRejected",reason:t}}};export function analyticsEventKind(e){return Object.prototype.hasOwnProperty.call(l,e.type)?l[e.type]?.(e.extras):void 0}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { FlowConfiguration } from "./flow_configuration";
|
|
2
|
+
/** Whether a step of `configuration` captures with the camera, selfie or document. */
|
|
3
|
+
export declare function opensCamera(configuration: FlowConfiguration): boolean;
|
|
4
|
+
/**
|
|
5
|
+
* Starts the camera stack's one-off set-up now when a step of `configuration` captures, so the
|
|
6
|
+
* capture screen's camera doesn't wait for it. Opens no camera, needs no permission, and kamera's
|
|
7
|
+
* `prewarm` never rejects.
|
|
8
|
+
*/
|
|
9
|
+
export declare function prewarmCameraIfNeeded(configuration: FlowConfiguration, prewarm?: () => Promise<void>): void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";import{KameraSession as n}from"@smileid/kamera";export function opensCamera(e){return e.screens.steps.some(r=>r.kind==="capture")}export function prewarmCameraIfNeeded(e,r=()=>n.prewarm()){opensCamera(e)&&r()}
|