@kernaq/verify-react-native 2.0.0 → 2.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.d.ts +95 -50
- package/dist/index.esm.js +1171 -580
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +1169 -576
- package/dist/index.js.map +1 -1
- package/package.json +2 -9
- package/src/KernaqVerify.tsx +172 -176
- package/src/index.ts +9 -4
- package/src/locale.ts +32 -29
- package/src/quality.ts +180 -0
- package/src/steps/DocumentStep.tsx +214 -77
- package/src/steps/IntroStep.tsx +58 -37
- package/src/steps/LivenessStep.tsx +225 -125
- package/src/steps/ProcessingStep.tsx +10 -34
- package/src/steps/ResultStep.tsx +99 -35
- package/src/steps/SelfieStep.tsx +165 -96
- package/src/theme.ts +22 -14
- package/src/types.ts +27 -51
package/README.md
CHANGED
|
@@ -159,7 +159,7 @@ Never expose a live API key in your app. Instead, forward requests through your
|
|
|
159
159
|
/>
|
|
160
160
|
```
|
|
161
161
|
|
|
162
|
-
Your backend endpoint receives a `multipart/form-data` POST with `
|
|
162
|
+
Your backend endpoint receives a `multipart/form-data` POST with `doc_front`, `doc_back`, `selfie`, `video`, `document_type`, `country`, and `reference` fields. Forward it to `https://api.identity.kernaq.com/v1/verify` with your secret key.
|
|
163
163
|
|
|
164
164
|
## Result object
|
|
165
165
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* @kernaq/verify-react-native — public types
|
|
4
|
+
* @kernaq/verify-react-native — public types (v2)
|
|
5
5
|
*/
|
|
6
|
-
type VerifyStep = 'intro' | '
|
|
6
|
+
type VerifyStep = 'intro' | 'doc-front' | 'doc-back' | 'selfie' | 'liveness' | 'processing' | 'result';
|
|
7
|
+
/** Which capture steps to include. Default: all three. */
|
|
8
|
+
type VerifyStepName = 'document' | 'selfie' | 'liveness';
|
|
9
|
+
/** Liveness challenge tasks */
|
|
10
|
+
type LivenessTask = 'blink' | 'turn-left' | 'turn-right' | 'nod' | 'open-mouth';
|
|
7
11
|
type DocumentType = 'national_id' | 'passport' | 'driver_license' | 'alien_card';
|
|
8
12
|
type VerifyVerdict = 'pass' | 'fail' | 'review';
|
|
9
13
|
interface VerifyResult {
|
|
@@ -16,84 +20,64 @@ interface VerifyResult {
|
|
|
16
20
|
documentFields?: Record<string, string>;
|
|
17
21
|
}
|
|
18
22
|
interface VerifyTheme {
|
|
19
|
-
/** Primary accent colour. Default: #111827 */
|
|
20
23
|
accentColor?: string;
|
|
21
|
-
/** Modal background. Default: #ffffff */
|
|
22
24
|
backgroundColor?: string;
|
|
23
|
-
/** Primary text colour. Default: #111827 */
|
|
24
25
|
textColor?: string;
|
|
25
|
-
/** Subtle text colour. Default: #6b7280 */
|
|
26
26
|
subtextColor?: string;
|
|
27
|
-
/** Border/divider colour. Default: #e5e7eb */
|
|
28
27
|
borderColor?: string;
|
|
29
|
-
/** Card/surface colour. Default: #f9fafb */
|
|
30
28
|
cardColor?: string;
|
|
31
|
-
/** Border radius for buttons and cards. Default: 12 */
|
|
32
29
|
borderRadius?: number;
|
|
33
|
-
/** 'light' | 'dark'
|
|
30
|
+
/** 'light' | 'dark' */
|
|
34
31
|
mode?: 'light' | 'dark';
|
|
35
32
|
}
|
|
36
33
|
interface VerifyLocale {
|
|
37
34
|
intro_title: string;
|
|
38
35
|
intro_body: string;
|
|
39
36
|
intro_cta: string;
|
|
40
|
-
|
|
41
|
-
|
|
37
|
+
doc_front_title: string;
|
|
38
|
+
doc_front_instruction: string;
|
|
39
|
+
doc_back_title: string;
|
|
40
|
+
doc_back_instruction: string;
|
|
42
41
|
doc_capture_btn: string;
|
|
43
42
|
doc_retake_btn: string;
|
|
44
|
-
doc_next_btn: string;
|
|
45
43
|
selfie_title: string;
|
|
46
44
|
selfie_instruction: string;
|
|
47
|
-
selfie_capture_btn: string;
|
|
48
|
-
selfie_retake_btn: string;
|
|
49
|
-
selfie_next_btn: string;
|
|
50
45
|
liveness_title: string;
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
46
|
+
liveness_ready: string;
|
|
47
|
+
liveness_task_prefix: string;
|
|
48
|
+
liveness_complete: string;
|
|
54
49
|
processing_title: string;
|
|
55
|
-
processing_subtitle: string;
|
|
56
50
|
result_pass_title: string;
|
|
57
51
|
result_pass_body: string;
|
|
58
52
|
result_fail_title: string;
|
|
59
53
|
result_fail_body: string;
|
|
60
54
|
result_review_title: string;
|
|
61
55
|
result_review_body: string;
|
|
62
|
-
result_retry_btn: string;
|
|
63
56
|
error_camera_denied: string;
|
|
57
|
+
error_blur: string;
|
|
64
58
|
error_quality: string;
|
|
65
59
|
error_network: string;
|
|
66
60
|
}
|
|
67
61
|
interface VerifyConfig {
|
|
68
|
-
/**
|
|
69
|
-
* Your Kernaq publishable API key (k_test_... or k_live_...).
|
|
70
|
-
* For production use a backend proxy and pass backendUrl instead.
|
|
71
|
-
*/
|
|
72
62
|
apiKey?: string;
|
|
73
|
-
/**
|
|
74
|
-
* URL of your backend proxy that forwards to the Kernaq Identity API.
|
|
75
|
-
* POST /verify with multipart/form-data.
|
|
76
|
-
*/
|
|
77
63
|
backendUrl?: string;
|
|
78
|
-
/**
|
|
79
|
-
|
|
80
|
-
/** Country code (ISO 3166-1 alpha-3). Default: 'KEN' */
|
|
64
|
+
/** Single document type the developer specifies. Default: 'national_id' */
|
|
65
|
+
documentType?: DocumentType;
|
|
81
66
|
country?: string;
|
|
82
|
-
/** Your internal reference ID for this user/session */
|
|
83
67
|
reference?: string;
|
|
84
|
-
/** Use sandbox mode — no billing, test responses */
|
|
85
68
|
sandbox?: boolean;
|
|
86
|
-
/** Liveness recording duration in ms. Default: 3000 */
|
|
87
69
|
livenessDuration?: number;
|
|
88
|
-
/**
|
|
70
|
+
/** Number of liveness tasks. Default: 2 */
|
|
71
|
+
livenessTaskCount?: number;
|
|
72
|
+
/**
|
|
73
|
+
* Which steps to include. Default: all three.
|
|
74
|
+
* @example steps={['selfie', 'liveness']}
|
|
75
|
+
*/
|
|
76
|
+
steps?: VerifyStepName[];
|
|
89
77
|
theme?: VerifyTheme;
|
|
90
|
-
/** Override any displayed string */
|
|
91
78
|
locale?: Partial<VerifyLocale>;
|
|
92
|
-
/** Called when the user dismisses without completing */
|
|
93
79
|
onCancel?: () => void;
|
|
94
|
-
/** Called when verification is complete */
|
|
95
80
|
onComplete?: (result: VerifyResult) => void;
|
|
96
|
-
/** Called on unrecoverable error */
|
|
97
81
|
onError?: (error: {
|
|
98
82
|
code: string;
|
|
99
83
|
message: string;
|
|
@@ -101,25 +85,86 @@ interface VerifyConfig {
|
|
|
101
85
|
}
|
|
102
86
|
|
|
103
87
|
/**
|
|
104
|
-
* <KernaqVerify /> — drop-in identity verification modal for React Native.
|
|
88
|
+
* <KernaqVerify /> — drop-in identity verification modal for React Native (v2).
|
|
105
89
|
*
|
|
106
|
-
*
|
|
107
|
-
*
|
|
90
|
+
* Matches @kernaq/verify web v2.0.0:
|
|
91
|
+
* - No header / logo
|
|
92
|
+
* - No progress bar
|
|
93
|
+
* - No cancel/close button — user must complete the flow
|
|
94
|
+
* - Front + back document capture
|
|
95
|
+
* - Auto-capture selfie with guidance pill
|
|
96
|
+
* - Randomised liveness tasks with in-viewport overlay
|
|
97
|
+
* - Configurable steps prop
|
|
98
|
+
* - "Secured by Kernaq" footer only
|
|
108
99
|
*
|
|
100
|
+
* Usage:
|
|
109
101
|
* <KernaqVerify
|
|
110
|
-
* visible={
|
|
111
|
-
*
|
|
102
|
+
* visible={show}
|
|
103
|
+
* documentType="national_id"
|
|
112
104
|
* country="KEN"
|
|
113
105
|
* reference={userId}
|
|
114
|
-
*
|
|
115
|
-
*
|
|
106
|
+
* steps={['document', 'selfie', 'liveness']}
|
|
107
|
+
* onComplete={(r) => console.log(r.verdict)}
|
|
116
108
|
* />
|
|
117
109
|
*/
|
|
118
110
|
|
|
119
111
|
interface Props extends VerifyConfig {
|
|
120
112
|
visible: boolean;
|
|
121
113
|
}
|
|
122
|
-
declare function KernaqVerify({ visible, apiKey, backendUrl, country, reference, sandbox, livenessDuration,
|
|
114
|
+
declare function KernaqVerify({ visible, apiKey, backendUrl, country, reference, sandbox, livenessDuration, livenessTaskCount, documentType, steps: stepsProp, theme: themeProp, locale: localeProp, onComplete, onError, }: Props): React.JSX.Element;
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* quality.ts — Native port of @kernaq/capture-web analyseImage logic.
|
|
118
|
+
*
|
|
119
|
+
* React Native has no OffscreenCanvas or createImageBitmap, so we decode
|
|
120
|
+
* the JPEG manually from its base64 representation to extract a luminance
|
|
121
|
+
* sample, then run the same Laplacian variance + brightness + fill-ratio
|
|
122
|
+
* checks the web SDK uses.
|
|
123
|
+
*
|
|
124
|
+
* This is intentionally dependency-free — no expo-image-manipulator,
|
|
125
|
+
* no worklets, no native modules beyond what vision-camera already provides.
|
|
126
|
+
*
|
|
127
|
+
* The JPEG sampling approach:
|
|
128
|
+
* 1. takeSnapshot({ quality: 20 }) → tiny file (~5-15KB)
|
|
129
|
+
* 2. fetch as ArrayBuffer → raw bytes
|
|
130
|
+
* 3. Skip JPEG header bytes, sample raw DCT-domain luminance bytes
|
|
131
|
+
* as a brightness proxy (not exact, but sufficient for dark/overexposed detection)
|
|
132
|
+
* 4. For blur: compute variance of luminance differences between adjacent samples
|
|
133
|
+
*
|
|
134
|
+
* Limitations vs web SDK:
|
|
135
|
+
* - Fill ratio check is approximated via luminance variance spread
|
|
136
|
+
* - Glasses glare heuristic is the same eye-band brightness check
|
|
137
|
+
* - Blur detection is less precise but calibrated to the same thresholds
|
|
138
|
+
*/
|
|
139
|
+
interface QualityReport {
|
|
140
|
+
passed: boolean;
|
|
141
|
+
blurScore: number;
|
|
142
|
+
brightness: number;
|
|
143
|
+
fillRatio: number;
|
|
144
|
+
failures: QualityFailure[];
|
|
145
|
+
}
|
|
146
|
+
type QualityFailure = 'too_blurry' | 'too_dark' | 'too_bright' | 'too_small';
|
|
147
|
+
interface QualityConfig {
|
|
148
|
+
minBlurScore?: number;
|
|
149
|
+
minBrightness?: number;
|
|
150
|
+
maxBrightness?: number;
|
|
151
|
+
minFillRatio?: number;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Analyse an image from a file URI.
|
|
155
|
+
* Reads the raw bytes, samples luminance, returns a quality report.
|
|
156
|
+
*/
|
|
157
|
+
declare function analyseImageUri(uri: string, config?: QualityConfig): Promise<QualityReport>;
|
|
158
|
+
/**
|
|
159
|
+
* Selfie-specific quality check with glasses/glare heuristic.
|
|
160
|
+
* Takes snapshots from two regions: full frame and top-40% (eye area).
|
|
161
|
+
*
|
|
162
|
+
* Returns a guidance message (empty string = all good) and a passing flag.
|
|
163
|
+
*/
|
|
164
|
+
declare function analyseSelfieFrame(uri: string, config?: QualityConfig): Promise<{
|
|
165
|
+
passing: boolean;
|
|
166
|
+
message: string;
|
|
167
|
+
}>;
|
|
123
168
|
|
|
124
|
-
export { KernaqVerify };
|
|
125
|
-
export type { DocumentType, VerifyConfig, VerifyLocale, VerifyResult, VerifyStep, VerifyTheme, VerifyVerdict };
|
|
169
|
+
export { KernaqVerify, analyseImageUri, analyseSelfieFrame };
|
|
170
|
+
export type { DocumentType, LivenessTask, QualityConfig, QualityFailure, QualityReport, VerifyConfig, VerifyLocale, VerifyResult, VerifyStep, VerifyStepName, VerifyTheme, VerifyVerdict };
|