@koraidv/react 1.7.7 → 1.7.9

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/dist/index.d.mts CHANGED
@@ -87,7 +87,7 @@ interface UseKoraIDVReturn {
87
87
  /**
88
88
  * Upload document image
89
89
  */
90
- uploadDocument: (imageData: Blob, side: 'front' | 'back') => Promise<boolean>;
90
+ uploadDocument: (imageData: Blob, side: 'front' | 'back', country?: string) => Promise<boolean>;
91
91
  /**
92
92
  * Upload selfie image
93
93
  */
package/dist/index.d.ts CHANGED
@@ -87,7 +87,7 @@ interface UseKoraIDVReturn {
87
87
  /**
88
88
  * Upload document image
89
89
  */
90
- uploadDocument: (imageData: Blob, side: 'front' | 'back') => Promise<boolean>;
90
+ uploadDocument: (imageData: Blob, side: 'front' | 'back', country?: string) => Promise<boolean>;
91
91
  /**
92
92
  * Upload selfie image
93
93
  */
package/dist/index.js CHANGED
@@ -191,11 +191,11 @@ function useKoraIDV() {
191
191
  [sdk, selectedDocumentType]
192
192
  );
193
193
  const uploadDocument = (0, import_react2.useCallback)(
194
- async (imageData, side) => {
194
+ async (imageData, side, country) => {
195
195
  if (!selectedDocumentType) return false;
196
196
  setState((prev) => ({ ...prev, isLoading: true, error: null }));
197
197
  try {
198
- const result = await sdk.uploadDocument(imageData, side, selectedDocumentType);
198
+ const result = await sdk.uploadDocument(imageData, side, selectedDocumentType, country);
199
199
  if (result.success) {
200
200
  if (side === "front") {
201
201
  setDocumentFrontCaptured(true);
@@ -2354,6 +2354,7 @@ function LivenessScreen({
2354
2354
  const canvasRef = (0, import_react8.useRef)(null);
2355
2355
  const [stream, setStream] = (0, import_react8.useState)(null);
2356
2356
  const [cameraError, setCameraError] = (0, import_react8.useState)(null);
2357
+ const [phase, setPhase] = (0, import_react8.useState)("preparing");
2357
2358
  const [countdown, setCountdown] = (0, import_react8.useState)(3);
2358
2359
  const [capturing, setCapturing] = (0, import_react8.useState)(false);
2359
2360
  (0, import_react8.useEffect)(() => {
@@ -2401,6 +2402,7 @@ function LivenessScreen({
2401
2402
  }, [stream]);
2402
2403
  (0, import_react8.useEffect)(() => {
2403
2404
  if (!currentChallenge) return;
2405
+ setPhase("preparing");
2404
2406
  setCountdown(3);
2405
2407
  }, [currentChallenge?.id]);
2406
2408
  const captureFrame = (0, import_react8.useCallback)(async () => {
@@ -2429,12 +2431,17 @@ function LivenessScreen({
2429
2431
  (0, import_react8.useEffect)(() => {
2430
2432
  if (!currentChallenge || capturing) return;
2431
2433
  if (countdown === 0) {
2432
- captureFrame();
2434
+ if (phase === "preparing") {
2435
+ setPhase("capturing");
2436
+ setCountdown(3);
2437
+ } else {
2438
+ captureFrame();
2439
+ }
2433
2440
  return;
2434
2441
  }
2435
2442
  const t = setTimeout(() => setCountdown((c) => c - 1), 1e3);
2436
2443
  return () => clearTimeout(t);
2437
- }, [countdown, currentChallenge?.id, capturing, captureFrame]);
2444
+ }, [countdown, currentChallenge?.id, capturing, captureFrame, phase]);
2438
2445
  (0, import_react8.useEffect)(() => {
2439
2446
  if (session && !currentChallenge && completedChallenges > 0) {
2440
2447
  onComplete();
@@ -2460,15 +2467,17 @@ function LivenessScreen({
2460
2467
  /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("h1", { style: styles.darkScreenTitle, children: "Liveness Check" }),
2461
2468
  /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { style: styles.glassCloseButton, onClick: onCancel, children: "\u2715" })
2462
2469
  ] }),
2463
- currentChallenge && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: { padding: "16px 0" }, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("h2", { style: styles.challengeTitle, children: currentChallenge.instruction }) }),
2464
2470
  /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
2465
2471
  "div",
2466
2472
  {
2467
2473
  style: {
2468
2474
  flex: 1,
2469
2475
  display: "flex",
2476
+ flexDirection: "column",
2470
2477
  alignItems: "center",
2471
- justifyContent: "center"
2478
+ justifyContent: "center",
2479
+ gap: "24px",
2480
+ padding: "16px 0"
2472
2481
  },
2473
2482
  children: [
2474
2483
  /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { position: "relative" }, children: [
@@ -2520,7 +2529,7 @@ function LivenessScreen({
2520
2529
  rx: "124",
2521
2530
  ry: "154",
2522
2531
  fill: "none",
2523
- stroke: colors.teal,
2532
+ stroke: phase === "capturing" ? colors.teal : "rgba(13,148,136,0.4)",
2524
2533
  strokeWidth: "5",
2525
2534
  strokeDasharray: `${completedChallenges / totalChallenges * 880} 880`,
2526
2535
  transform: "rotate(-90 128 158)",
@@ -2528,20 +2537,62 @@ function LivenessScreen({
2528
2537
  }
2529
2538
  )
2530
2539
  }
2531
- ),
2532
- currentChallenge && countdown > 0 && !capturing && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: styles.countdownBadge, children: countdown }),
2533
- capturing && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2534
- "div",
2535
- {
2536
- style: {
2537
- ...styles.countdownBadge,
2538
- fontSize: "14px",
2539
- padding: "8px 14px"
2540
- },
2541
- children: "Checking..."
2542
- }
2543
2540
  )
2544
2541
  ] }),
2542
+ currentChallenge && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
2543
+ "div",
2544
+ {
2545
+ style: {
2546
+ textAlign: "center",
2547
+ padding: "20px 24px",
2548
+ borderRadius: "16px",
2549
+ backgroundColor: phase === "capturing" ? "rgba(13,148,136,0.18)" : "rgba(255,255,255,0.06)",
2550
+ border: phase === "capturing" ? `1px solid ${colors.teal}` : "1px solid rgba(255,255,255,0.08)",
2551
+ minWidth: "260px",
2552
+ transition: "background-color 200ms, border-color 200ms"
2553
+ },
2554
+ children: [
2555
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2556
+ "p",
2557
+ {
2558
+ style: {
2559
+ margin: 0,
2560
+ fontSize: "12px",
2561
+ fontWeight: 600,
2562
+ letterSpacing: "0.08em",
2563
+ textTransform: "uppercase",
2564
+ color: phase === "capturing" ? colors.teal : "rgba(255,255,255,0.5)"
2565
+ },
2566
+ children: capturing ? "Checking..." : phase === "preparing" ? "Get ready" : "Now \u2014 hold the pose"
2567
+ }
2568
+ ),
2569
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2570
+ "h2",
2571
+ {
2572
+ style: {
2573
+ ...styles.challengeTitle,
2574
+ margin: "8px 0 0",
2575
+ fontSize: "26px"
2576
+ },
2577
+ children: currentChallenge.instruction
2578
+ }
2579
+ ),
2580
+ !capturing && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2581
+ "p",
2582
+ {
2583
+ style: {
2584
+ margin: "12px 0 0",
2585
+ fontSize: "32px",
2586
+ fontWeight: 700,
2587
+ color: phase === "capturing" ? colors.teal : "rgba(255,255,255,0.75)",
2588
+ lineHeight: 1
2589
+ },
2590
+ children: countdown
2591
+ }
2592
+ )
2593
+ ]
2594
+ }
2595
+ ),
2545
2596
  /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("canvas", { ref: canvasRef, style: { display: "none" } })
2546
2597
  ]
2547
2598
  }
@@ -2573,7 +2624,7 @@ function LivenessScreen({
2573
2624
  fontSize: "13px",
2574
2625
  margin: 0
2575
2626
  },
2576
- children: "Position your face inside the oval and follow the prompt."
2627
+ children: phase === "preparing" ? "Position your face inside the oval. Get ready for the next prompt." : "Hold the pose until the capture completes."
2577
2628
  }
2578
2629
  ) })
2579
2630
  ] });
@@ -3014,11 +3065,6 @@ function VerificationFlow({
3014
3065
  (0, import_react10.useEffect)(() => {
3015
3066
  startVerification(externalId, tier);
3016
3067
  }, [externalId, tier, startVerification]);
3017
- (0, import_react10.useEffect)(() => {
3018
- if (state.step === "complete" && state.verification && onComplete) {
3019
- onComplete(state.verification);
3020
- }
3021
- }, [state.step, state.verification, onComplete]);
3022
3068
  (0, import_react10.useEffect)(() => {
3023
3069
  if (state.error && onError) {
3024
3070
  onError(state.error);
@@ -3101,7 +3147,7 @@ function VerificationFlow({
3101
3147
  {
3102
3148
  side: "front",
3103
3149
  onQualityCheck: (blob) => checkDocumentQuality(blob),
3104
- onCapture: (imageData) => uploadDocument(imageData, "front"),
3150
+ onCapture: (imageData) => uploadDocument(imageData, "front", selectedCountry?.id),
3105
3151
  onCancel: handleCancel
3106
3152
  }
3107
3153
  ),
@@ -3116,7 +3162,7 @@ function VerificationFlow({
3116
3162
  DocumentCaptureScreen,
3117
3163
  {
3118
3164
  side: "back",
3119
- onCapture: (imageData) => uploadDocument(imageData, "back"),
3165
+ onCapture: (imageData) => uploadDocument(imageData, "back", selectedCountry?.id),
3120
3166
  onCancel: handleCancel
3121
3167
  }
3122
3168
  ),
package/dist/index.mjs CHANGED
@@ -142,11 +142,11 @@ function useKoraIDV() {
142
142
  [sdk, selectedDocumentType]
143
143
  );
144
144
  const uploadDocument = useCallback(
145
- async (imageData, side) => {
145
+ async (imageData, side, country) => {
146
146
  if (!selectedDocumentType) return false;
147
147
  setState((prev) => ({ ...prev, isLoading: true, error: null }));
148
148
  try {
149
- const result = await sdk.uploadDocument(imageData, side, selectedDocumentType);
149
+ const result = await sdk.uploadDocument(imageData, side, selectedDocumentType, country);
150
150
  if (result.success) {
151
151
  if (side === "front") {
152
152
  setDocumentFrontCaptured(true);
@@ -2305,6 +2305,7 @@ function LivenessScreen({
2305
2305
  const canvasRef = useRef4(null);
2306
2306
  const [stream, setStream] = useState5(null);
2307
2307
  const [cameraError, setCameraError] = useState5(null);
2308
+ const [phase, setPhase] = useState5("preparing");
2308
2309
  const [countdown, setCountdown] = useState5(3);
2309
2310
  const [capturing, setCapturing] = useState5(false);
2310
2311
  useEffect6(() => {
@@ -2352,6 +2353,7 @@ function LivenessScreen({
2352
2353
  }, [stream]);
2353
2354
  useEffect6(() => {
2354
2355
  if (!currentChallenge) return;
2356
+ setPhase("preparing");
2355
2357
  setCountdown(3);
2356
2358
  }, [currentChallenge?.id]);
2357
2359
  const captureFrame = useCallback4(async () => {
@@ -2380,12 +2382,17 @@ function LivenessScreen({
2380
2382
  useEffect6(() => {
2381
2383
  if (!currentChallenge || capturing) return;
2382
2384
  if (countdown === 0) {
2383
- captureFrame();
2385
+ if (phase === "preparing") {
2386
+ setPhase("capturing");
2387
+ setCountdown(3);
2388
+ } else {
2389
+ captureFrame();
2390
+ }
2384
2391
  return;
2385
2392
  }
2386
2393
  const t = setTimeout(() => setCountdown((c) => c - 1), 1e3);
2387
2394
  return () => clearTimeout(t);
2388
- }, [countdown, currentChallenge?.id, capturing, captureFrame]);
2395
+ }, [countdown, currentChallenge?.id, capturing, captureFrame, phase]);
2389
2396
  useEffect6(() => {
2390
2397
  if (session && !currentChallenge && completedChallenges > 0) {
2391
2398
  onComplete();
@@ -2411,15 +2418,17 @@ function LivenessScreen({
2411
2418
  /* @__PURE__ */ jsx9("h1", { style: styles.darkScreenTitle, children: "Liveness Check" }),
2412
2419
  /* @__PURE__ */ jsx9("button", { style: styles.glassCloseButton, onClick: onCancel, children: "\u2715" })
2413
2420
  ] }),
2414
- currentChallenge && /* @__PURE__ */ jsx9("div", { style: { padding: "16px 0" }, children: /* @__PURE__ */ jsx9("h2", { style: styles.challengeTitle, children: currentChallenge.instruction }) }),
2415
2421
  /* @__PURE__ */ jsxs8(
2416
2422
  "div",
2417
2423
  {
2418
2424
  style: {
2419
2425
  flex: 1,
2420
2426
  display: "flex",
2427
+ flexDirection: "column",
2421
2428
  alignItems: "center",
2422
- justifyContent: "center"
2429
+ justifyContent: "center",
2430
+ gap: "24px",
2431
+ padding: "16px 0"
2423
2432
  },
2424
2433
  children: [
2425
2434
  /* @__PURE__ */ jsxs8("div", { style: { position: "relative" }, children: [
@@ -2471,7 +2480,7 @@ function LivenessScreen({
2471
2480
  rx: "124",
2472
2481
  ry: "154",
2473
2482
  fill: "none",
2474
- stroke: colors.teal,
2483
+ stroke: phase === "capturing" ? colors.teal : "rgba(13,148,136,0.4)",
2475
2484
  strokeWidth: "5",
2476
2485
  strokeDasharray: `${completedChallenges / totalChallenges * 880} 880`,
2477
2486
  transform: "rotate(-90 128 158)",
@@ -2479,20 +2488,62 @@ function LivenessScreen({
2479
2488
  }
2480
2489
  )
2481
2490
  }
2482
- ),
2483
- currentChallenge && countdown > 0 && !capturing && /* @__PURE__ */ jsx9("div", { style: styles.countdownBadge, children: countdown }),
2484
- capturing && /* @__PURE__ */ jsx9(
2485
- "div",
2486
- {
2487
- style: {
2488
- ...styles.countdownBadge,
2489
- fontSize: "14px",
2490
- padding: "8px 14px"
2491
- },
2492
- children: "Checking..."
2493
- }
2494
2491
  )
2495
2492
  ] }),
2493
+ currentChallenge && /* @__PURE__ */ jsxs8(
2494
+ "div",
2495
+ {
2496
+ style: {
2497
+ textAlign: "center",
2498
+ padding: "20px 24px",
2499
+ borderRadius: "16px",
2500
+ backgroundColor: phase === "capturing" ? "rgba(13,148,136,0.18)" : "rgba(255,255,255,0.06)",
2501
+ border: phase === "capturing" ? `1px solid ${colors.teal}` : "1px solid rgba(255,255,255,0.08)",
2502
+ minWidth: "260px",
2503
+ transition: "background-color 200ms, border-color 200ms"
2504
+ },
2505
+ children: [
2506
+ /* @__PURE__ */ jsx9(
2507
+ "p",
2508
+ {
2509
+ style: {
2510
+ margin: 0,
2511
+ fontSize: "12px",
2512
+ fontWeight: 600,
2513
+ letterSpacing: "0.08em",
2514
+ textTransform: "uppercase",
2515
+ color: phase === "capturing" ? colors.teal : "rgba(255,255,255,0.5)"
2516
+ },
2517
+ children: capturing ? "Checking..." : phase === "preparing" ? "Get ready" : "Now \u2014 hold the pose"
2518
+ }
2519
+ ),
2520
+ /* @__PURE__ */ jsx9(
2521
+ "h2",
2522
+ {
2523
+ style: {
2524
+ ...styles.challengeTitle,
2525
+ margin: "8px 0 0",
2526
+ fontSize: "26px"
2527
+ },
2528
+ children: currentChallenge.instruction
2529
+ }
2530
+ ),
2531
+ !capturing && /* @__PURE__ */ jsx9(
2532
+ "p",
2533
+ {
2534
+ style: {
2535
+ margin: "12px 0 0",
2536
+ fontSize: "32px",
2537
+ fontWeight: 700,
2538
+ color: phase === "capturing" ? colors.teal : "rgba(255,255,255,0.75)",
2539
+ lineHeight: 1
2540
+ },
2541
+ children: countdown
2542
+ }
2543
+ )
2544
+ ]
2545
+ }
2546
+ ),
2496
2547
  /* @__PURE__ */ jsx9("canvas", { ref: canvasRef, style: { display: "none" } })
2497
2548
  ]
2498
2549
  }
@@ -2524,7 +2575,7 @@ function LivenessScreen({
2524
2575
  fontSize: "13px",
2525
2576
  margin: 0
2526
2577
  },
2527
- children: "Position your face inside the oval and follow the prompt."
2578
+ children: phase === "preparing" ? "Position your face inside the oval. Get ready for the next prompt." : "Hold the pose until the capture completes."
2528
2579
  }
2529
2580
  ) })
2530
2581
  ] });
@@ -2965,11 +3016,6 @@ function VerificationFlow({
2965
3016
  useEffect8(() => {
2966
3017
  startVerification(externalId, tier);
2967
3018
  }, [externalId, tier, startVerification]);
2968
- useEffect8(() => {
2969
- if (state.step === "complete" && state.verification && onComplete) {
2970
- onComplete(state.verification);
2971
- }
2972
- }, [state.step, state.verification, onComplete]);
2973
3019
  useEffect8(() => {
2974
3020
  if (state.error && onError) {
2975
3021
  onError(state.error);
@@ -3052,7 +3098,7 @@ function VerificationFlow({
3052
3098
  {
3053
3099
  side: "front",
3054
3100
  onQualityCheck: (blob) => checkDocumentQuality(blob),
3055
- onCapture: (imageData) => uploadDocument(imageData, "front"),
3101
+ onCapture: (imageData) => uploadDocument(imageData, "front", selectedCountry?.id),
3056
3102
  onCancel: handleCancel
3057
3103
  }
3058
3104
  ),
@@ -3067,7 +3113,7 @@ function VerificationFlow({
3067
3113
  DocumentCaptureScreen,
3068
3114
  {
3069
3115
  side: "back",
3070
- onCapture: (imageData) => uploadDocument(imageData, "back"),
3116
+ onCapture: (imageData) => uploadDocument(imageData, "back", selectedCountry?.id),
3071
3117
  onCancel: handleCancel
3072
3118
  }
3073
3119
  ),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@koraidv/react",
3
- "version": "1.7.7",
3
+ "version": "1.7.9",
4
4
  "description": "Kora IDV React Components for Identity Verification",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -21,7 +21,7 @@
21
21
  "test": "vitest run"
22
22
  },
23
23
  "dependencies": {
24
- "@koraidv/core": "^1.7.7"
24
+ "@koraidv/core": "^1.7.9"
25
25
  },
26
26
  "devDependencies": {
27
27
  "@types/react": "^18.2.0",