@koraidv/react 1.7.10 → 1.8.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/dist/index.d.mts +71 -7
- package/dist/index.d.ts +71 -7
- package/dist/index.js +830 -381
- package/dist/index.mjs +833 -384
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -96,16 +96,22 @@ function useKoraIDV() {
|
|
|
96
96
|
currentChallenge: null,
|
|
97
97
|
completedChallenges: 0,
|
|
98
98
|
isLoading: false,
|
|
99
|
-
error: null
|
|
99
|
+
error: null,
|
|
100
|
+
lastChallengeError: null
|
|
100
101
|
});
|
|
101
102
|
const [selectedDocumentType, setSelectedDocumentType] = (0, import_react2.useState)(null);
|
|
102
103
|
const [documentFrontCaptured, setDocumentFrontCaptured] = (0, import_react2.useState)(false);
|
|
103
104
|
const startVerification = (0, import_react2.useCallback)(
|
|
104
|
-
async (externalId, tier = "standard") => {
|
|
105
|
+
async (externalId, tier = "standard", expectedFirstName, expectedLastName) => {
|
|
105
106
|
setState((prev) => ({ ...prev, isLoading: true, error: null }));
|
|
106
107
|
try {
|
|
107
108
|
await sdk.startVerification(
|
|
108
|
-
{
|
|
109
|
+
{
|
|
110
|
+
externalId,
|
|
111
|
+
tier,
|
|
112
|
+
expectedFirstName,
|
|
113
|
+
expectedLastName
|
|
114
|
+
},
|
|
109
115
|
{
|
|
110
116
|
onStepChange: (step) => {
|
|
111
117
|
setState((prev) => ({ ...prev, step }));
|
|
@@ -290,14 +296,20 @@ function useKoraIDV() {
|
|
|
290
296
|
...prev,
|
|
291
297
|
completedChallenges: nextIndex,
|
|
292
298
|
currentChallenge: nextChallenge,
|
|
293
|
-
isLoading: false
|
|
299
|
+
isLoading: false,
|
|
300
|
+
// Clear any prior retake message — the user just succeeded.
|
|
301
|
+
lastChallengeError: null
|
|
294
302
|
}));
|
|
295
303
|
if (!nextChallenge) {
|
|
296
304
|
setState((prev) => ({ ...prev, step: "processing" }));
|
|
297
305
|
}
|
|
298
306
|
return true;
|
|
299
307
|
}
|
|
300
|
-
setState((prev) => ({
|
|
308
|
+
setState((prev) => ({
|
|
309
|
+
...prev,
|
|
310
|
+
isLoading: false,
|
|
311
|
+
lastChallengeError: retakeMessageForChallenge(currentChallenge.type)
|
|
312
|
+
}));
|
|
301
313
|
return false;
|
|
302
314
|
} catch (error) {
|
|
303
315
|
setState((prev) => ({
|
|
@@ -348,7 +360,8 @@ function useKoraIDV() {
|
|
|
348
360
|
currentChallenge: null,
|
|
349
361
|
completedChallenges: 0,
|
|
350
362
|
isLoading: false,
|
|
351
|
-
error: null
|
|
363
|
+
error: null,
|
|
364
|
+
lastChallengeError: null
|
|
352
365
|
});
|
|
353
366
|
}, [sdk]);
|
|
354
367
|
const retry = (0, import_react2.useCallback)(() => {
|
|
@@ -375,9 +388,27 @@ function useKoraIDV() {
|
|
|
375
388
|
sdk
|
|
376
389
|
};
|
|
377
390
|
}
|
|
391
|
+
function retakeMessageForChallenge(type) {
|
|
392
|
+
switch (type) {
|
|
393
|
+
case "blink":
|
|
394
|
+
return "We didn't catch the blink \u2014 close both eyes briefly and try again.";
|
|
395
|
+
case "smile":
|
|
396
|
+
return "We didn't catch the smile \u2014 show your teeth and try again.";
|
|
397
|
+
case "turn_left":
|
|
398
|
+
return "Turn your head a bit further to the left and try again.";
|
|
399
|
+
case "turn_right":
|
|
400
|
+
return "Turn your head a bit further to the right and try again.";
|
|
401
|
+
case "nod_up":
|
|
402
|
+
return "Tilt your head a bit higher and try again.";
|
|
403
|
+
case "nod_down":
|
|
404
|
+
return "Tilt your head a bit lower and try again.";
|
|
405
|
+
default:
|
|
406
|
+
return "That attempt didn't pass \u2014 follow the prompt and try again.";
|
|
407
|
+
}
|
|
408
|
+
}
|
|
378
409
|
|
|
379
410
|
// src/components/VerificationFlow.tsx
|
|
380
|
-
var
|
|
411
|
+
var import_react13 = require("react");
|
|
381
412
|
var import_core4 = require("@koraidv/core");
|
|
382
413
|
|
|
383
414
|
// src/components/styles.ts
|
|
@@ -444,6 +475,36 @@ function injectKeyframes() {
|
|
|
444
475
|
from { opacity: 0; transform: translateY(8px); }
|
|
445
476
|
to { opacity: 1; transform: translateY(0); }
|
|
446
477
|
}
|
|
478
|
+
/* \u2500\u2500\u2500 VisualGuides motion (v1.8.0) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
|
|
479
|
+
@keyframes kora-head-turn-right {
|
|
480
|
+
0%, 100% { transform: rotate(0deg); }
|
|
481
|
+
50% { transform: rotate(22deg); }
|
|
482
|
+
}
|
|
483
|
+
@keyframes kora-head-turn-left {
|
|
484
|
+
0%, 100% { transform: rotate(0deg); }
|
|
485
|
+
50% { transform: rotate(-22deg); }
|
|
486
|
+
}
|
|
487
|
+
@keyframes kora-head-tilt-up {
|
|
488
|
+
0%, 100% { transform: translateY(0); }
|
|
489
|
+
50% { transform: translateY(-6px) rotate(-6deg); }
|
|
490
|
+
}
|
|
491
|
+
@keyframes kora-head-tilt-down {
|
|
492
|
+
0%, 100% { transform: translateY(0); }
|
|
493
|
+
50% { transform: translateY(6px) rotate(6deg); }
|
|
494
|
+
}
|
|
495
|
+
@keyframes kora-smile {
|
|
496
|
+
0%, 100% { transform: scaleY(0.5); }
|
|
497
|
+
50% { transform: scaleY(1.2); }
|
|
498
|
+
}
|
|
499
|
+
@keyframes kora-blink {
|
|
500
|
+
0%, 80%, 100% { transform: scaleY(1); }
|
|
501
|
+
88% { transform: scaleY(0.05); }
|
|
502
|
+
}
|
|
503
|
+
@keyframes kora-nfc-wave {
|
|
504
|
+
0% { opacity: 0; transform: translateX(-4px); }
|
|
505
|
+
40% { opacity: 1; }
|
|
506
|
+
100% { opacity: 0; transform: translateX(6px); }
|
|
507
|
+
}
|
|
447
508
|
`;
|
|
448
509
|
document.head.appendChild(style);
|
|
449
510
|
}
|
|
@@ -1430,10 +1491,26 @@ function ScoreMetricRow({ label, score, icon, status, message }) {
|
|
|
1430
1491
|
}
|
|
1431
1492
|
);
|
|
1432
1493
|
}
|
|
1433
|
-
|
|
1494
|
+
var DEFAULT_AUTO_STEPS = [
|
|
1495
|
+
"Document analyzed",
|
|
1496
|
+
"Checking face match",
|
|
1497
|
+
"Finalizing results"
|
|
1498
|
+
];
|
|
1499
|
+
function ProcessingScreen({ steps, autoAdvance = true }) {
|
|
1434
1500
|
(0, import_react3.useEffect)(() => {
|
|
1435
1501
|
injectKeyframes();
|
|
1436
1502
|
}, []);
|
|
1503
|
+
const [autoIndex, setAutoIndex] = (0, import_react3.useState)(0);
|
|
1504
|
+
(0, import_react3.useEffect)(() => {
|
|
1505
|
+
if (steps || !autoAdvance) return;
|
|
1506
|
+
if (autoIndex >= DEFAULT_AUTO_STEPS.length - 1) return;
|
|
1507
|
+
const t = setTimeout(() => setAutoIndex((i) => i + 1), 1400);
|
|
1508
|
+
return () => clearTimeout(t);
|
|
1509
|
+
}, [autoIndex, steps, autoAdvance]);
|
|
1510
|
+
const renderedSteps = steps ? steps : DEFAULT_AUTO_STEPS.map((label, i) => ({
|
|
1511
|
+
label,
|
|
1512
|
+
status: i < autoIndex ? "done" : i === autoIndex ? "active" : "pending"
|
|
1513
|
+
}));
|
|
1437
1514
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles.processingContainer, children: [
|
|
1438
1515
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles.spinnerContainer, children: [
|
|
1439
1516
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
@@ -1484,7 +1561,7 @@ function ProcessingScreen({ steps }) {
|
|
|
1484
1561
|
}
|
|
1485
1562
|
)
|
|
1486
1563
|
] }),
|
|
1487
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: styles.processingSteps, children:
|
|
1564
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: styles.processingSteps, children: renderedSteps.map((step, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles.processingStep, children: [
|
|
1488
1565
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1489
1566
|
"div",
|
|
1490
1567
|
{
|
|
@@ -1806,8 +1883,243 @@ function getIcon(type) {
|
|
|
1806
1883
|
}
|
|
1807
1884
|
|
|
1808
1885
|
// src/components/DocumentCaptureScreen.tsx
|
|
1886
|
+
var import_react7 = require("react");
|
|
1887
|
+
|
|
1888
|
+
// src/components/VisualGuides.tsx
|
|
1809
1889
|
var import_react5 = require("react");
|
|
1810
1890
|
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
1891
|
+
function visualGuideForChallenge(challengeType) {
|
|
1892
|
+
switch (challengeType) {
|
|
1893
|
+
case "turn_left":
|
|
1894
|
+
return "livenessTurnLeft";
|
|
1895
|
+
case "turn_right":
|
|
1896
|
+
return "livenessTurnRight";
|
|
1897
|
+
case "nod_up":
|
|
1898
|
+
return "livenessLookUp";
|
|
1899
|
+
case "nod_down":
|
|
1900
|
+
return "livenessLookDown";
|
|
1901
|
+
case "smile":
|
|
1902
|
+
return "livenessSmile";
|
|
1903
|
+
case "blink":
|
|
1904
|
+
return "livenessBlink";
|
|
1905
|
+
default:
|
|
1906
|
+
return null;
|
|
1907
|
+
}
|
|
1908
|
+
}
|
|
1909
|
+
function VisualGuide({ kind, size = 96 }) {
|
|
1910
|
+
(0, import_react5.useEffect)(() => {
|
|
1911
|
+
injectKeyframes();
|
|
1912
|
+
}, []);
|
|
1913
|
+
const common = { width: size, height: size, viewBox: "0 0 100 100" };
|
|
1914
|
+
const fg = colors.teal;
|
|
1915
|
+
const dim = "rgba(255,255,255,0.3)";
|
|
1916
|
+
switch (kind) {
|
|
1917
|
+
case "docFront":
|
|
1918
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(DocFront, { ...common, fg, dim });
|
|
1919
|
+
case "docBack":
|
|
1920
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(DocBack, { ...common, fg, dim });
|
|
1921
|
+
case "selfie":
|
|
1922
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Selfie, { ...common, fg, dim });
|
|
1923
|
+
case "nfcScan":
|
|
1924
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(NfcScan, { ...common, fg, dim });
|
|
1925
|
+
case "livenessTurnLeft":
|
|
1926
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(HeadTurn, { ...common, fg, dim, right: false });
|
|
1927
|
+
case "livenessTurnRight":
|
|
1928
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(HeadTurn, { ...common, fg, dim, right: true });
|
|
1929
|
+
case "livenessLookUp":
|
|
1930
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(HeadTilt, { ...common, fg, dim, up: true });
|
|
1931
|
+
case "livenessLookDown":
|
|
1932
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(HeadTilt, { ...common, fg, dim, up: false });
|
|
1933
|
+
case "livenessSmile":
|
|
1934
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Smile, { ...common, fg, dim });
|
|
1935
|
+
case "livenessBlink":
|
|
1936
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Blink, { ...common, fg, dim });
|
|
1937
|
+
}
|
|
1938
|
+
}
|
|
1939
|
+
function DocFront({ width, height, viewBox, fg, dim }) {
|
|
1940
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("svg", { width, height, viewBox, fill: "none", children: [
|
|
1941
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("rect", { x: "8", y: "26", width: "84", height: "48", rx: "5", stroke: fg, strokeWidth: "2.5" }),
|
|
1942
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("rect", { x: "14", y: "34", width: "22", height: "28", rx: "2", fill: dim }),
|
|
1943
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("rect", { x: "42", y: "36", width: "44", height: "3", rx: "1.5", fill: fg }),
|
|
1944
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("rect", { x: "42", y: "44", width: "36", height: "2.5", rx: "1.25", fill: dim }),
|
|
1945
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("rect", { x: "42", y: "50", width: "40", height: "2.5", rx: "1.25", fill: dim }),
|
|
1946
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("rect", { x: "42", y: "56", width: "30", height: "2.5", rx: "1.25", fill: dim })
|
|
1947
|
+
] });
|
|
1948
|
+
}
|
|
1949
|
+
function DocBack({ width, height, viewBox, fg, dim }) {
|
|
1950
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("svg", { width, height, viewBox, fill: "none", children: [
|
|
1951
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("rect", { x: "8", y: "26", width: "84", height: "48", rx: "5", stroke: fg, strokeWidth: "2.5" }),
|
|
1952
|
+
[16, 19, 22, 26, 28, 32, 35, 39, 42, 46, 49, 53, 56, 60].map((x, i) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1953
|
+
"rect",
|
|
1954
|
+
{
|
|
1955
|
+
x,
|
|
1956
|
+
y: "34",
|
|
1957
|
+
width: i % 3 === 0 ? 2 : 1.2,
|
|
1958
|
+
height: "20",
|
|
1959
|
+
fill: fg
|
|
1960
|
+
},
|
|
1961
|
+
i
|
|
1962
|
+
)),
|
|
1963
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("line", { x1: "14", y1: "64", x2: "58", y2: "64", stroke: dim, strokeWidth: "1.5" }),
|
|
1964
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("rect", { x: "66", y: "34", width: "20", height: "20", rx: "1", fill: dim })
|
|
1965
|
+
] });
|
|
1966
|
+
}
|
|
1967
|
+
function Selfie({ width, height, viewBox, fg, dim }) {
|
|
1968
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("svg", { width, height, viewBox, fill: "none", children: [
|
|
1969
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("ellipse", { cx: "50", cy: "42", rx: "22", ry: "28", stroke: fg, strokeWidth: "2.5" }),
|
|
1970
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("circle", { cx: "42", cy: "38", r: "2.5", fill: fg }),
|
|
1971
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("circle", { cx: "58", cy: "38", r: "2.5", fill: fg }),
|
|
1972
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M 40 50 Q 50 56 60 50", stroke: fg, strokeWidth: "2", strokeLinecap: "round", fill: "none" }),
|
|
1973
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M 18 92 Q 18 76 36 70 L 64 70 Q 82 76 82 92", stroke: dim, strokeWidth: "2", fill: "none" })
|
|
1974
|
+
] });
|
|
1975
|
+
}
|
|
1976
|
+
function NfcScan({ width, height, viewBox, fg, dim }) {
|
|
1977
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("svg", { width, height, viewBox, fill: "none", children: [
|
|
1978
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("rect", { x: "14", y: "40", width: "40", height: "50", rx: "3", stroke: dim, strokeWidth: "2" }),
|
|
1979
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("circle", { cx: "34", cy: "60", r: "6", stroke: dim, strokeWidth: "1.5" }),
|
|
1980
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("rect", { x: "62", y: "22", width: "26", height: "52", rx: "4", stroke: fg, strokeWidth: "2.5" }),
|
|
1981
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("rect", { x: "66", y: "26", width: "18", height: "38", rx: "1.5", fill: dim, opacity: "0.5" }),
|
|
1982
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M 58 48 Q 52 48 50 56", stroke: fg, strokeWidth: "2", fill: "none", style: { animation: "kora-nfc-wave 1.6s ease-out infinite" } }),
|
|
1983
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M 58 44 Q 50 44 46 56", stroke: fg, strokeWidth: "2", fill: "none", opacity: "0.7", style: { animation: "kora-nfc-wave 1.6s ease-out infinite 0.3s" } })
|
|
1984
|
+
] });
|
|
1985
|
+
}
|
|
1986
|
+
function HeadTurn({ width, height, viewBox, fg, dim, right }) {
|
|
1987
|
+
const arrowPath = right ? "M 30 12 L 70 12 L 64 6 M 70 12 L 64 18" : "M 70 12 L 30 12 L 36 6 M 30 12 L 36 18";
|
|
1988
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("svg", { width, height, viewBox, fill: "none", children: [
|
|
1989
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: arrowPath, stroke: fg, strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", fill: "none" }),
|
|
1990
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
1991
|
+
"g",
|
|
1992
|
+
{
|
|
1993
|
+
style: {
|
|
1994
|
+
transformOrigin: "50px 56px",
|
|
1995
|
+
animation: right ? "kora-head-turn-right 2s ease-in-out infinite" : "kora-head-turn-left 2s ease-in-out infinite"
|
|
1996
|
+
},
|
|
1997
|
+
children: [
|
|
1998
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("ellipse", { cx: "50", cy: "55", rx: "20", ry: "26", stroke: fg, strokeWidth: "2.5" }),
|
|
1999
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("circle", { cx: "42", cy: "50", r: "2", fill: fg }),
|
|
2000
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("circle", { cx: "58", cy: "50", r: "2", fill: fg }),
|
|
2001
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M 50 54 L 50 62", stroke: dim, strokeWidth: "1.5", strokeLinecap: "round" })
|
|
2002
|
+
]
|
|
2003
|
+
}
|
|
2004
|
+
)
|
|
2005
|
+
] });
|
|
2006
|
+
}
|
|
2007
|
+
function HeadTilt({ width, height, viewBox, fg, dim, up }) {
|
|
2008
|
+
const arrowPath = up ? "M 50 92 L 50 14 M 44 22 L 50 14 L 56 22" : "M 50 14 L 50 92 M 44 84 L 50 92 L 56 84";
|
|
2009
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("svg", { width, height, viewBox, fill: "none", children: [
|
|
2010
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: arrowPath, stroke: fg, strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", opacity: "0.4", fill: "none" }),
|
|
2011
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
2012
|
+
"g",
|
|
2013
|
+
{
|
|
2014
|
+
style: {
|
|
2015
|
+
transformOrigin: "50px 56px",
|
|
2016
|
+
animation: up ? "kora-head-tilt-up 2s ease-in-out infinite" : "kora-head-tilt-down 2s ease-in-out infinite"
|
|
2017
|
+
},
|
|
2018
|
+
children: [
|
|
2019
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("ellipse", { cx: "50", cy: "55", rx: "20", ry: "26", stroke: fg, strokeWidth: "2.5" }),
|
|
2020
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("circle", { cx: "42", cy: "50", r: "2", fill: fg }),
|
|
2021
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("circle", { cx: "58", cy: "50", r: "2", fill: fg }),
|
|
2022
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M 50 54 L 50 62", stroke: dim, strokeWidth: "1.5", strokeLinecap: "round" })
|
|
2023
|
+
]
|
|
2024
|
+
}
|
|
2025
|
+
)
|
|
2026
|
+
] });
|
|
2027
|
+
}
|
|
2028
|
+
function Smile({ width, height, viewBox, fg, dim }) {
|
|
2029
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("svg", { width, height, viewBox, fill: "none", children: [
|
|
2030
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("ellipse", { cx: "50", cy: "50", rx: "24", ry: "30", stroke: fg, strokeWidth: "2.5" }),
|
|
2031
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("circle", { cx: "40", cy: "44", r: "2.5", fill: fg }),
|
|
2032
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("circle", { cx: "60", cy: "44", r: "2.5", fill: fg }),
|
|
2033
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2034
|
+
"path",
|
|
2035
|
+
{
|
|
2036
|
+
d: "M 38 60 Q 50 68 62 60",
|
|
2037
|
+
stroke: fg,
|
|
2038
|
+
strokeWidth: "2.5",
|
|
2039
|
+
strokeLinecap: "round",
|
|
2040
|
+
fill: "none",
|
|
2041
|
+
style: { animation: "kora-smile 2s ease-in-out infinite", transformOrigin: "50px 60px" }
|
|
2042
|
+
}
|
|
2043
|
+
),
|
|
2044
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("line", { x1: "40", y1: "60", x2: "60", y2: "60", stroke: dim, strokeWidth: "1.5", opacity: "0.3" })
|
|
2045
|
+
] });
|
|
2046
|
+
}
|
|
2047
|
+
function Blink({ width, height, viewBox, fg, dim }) {
|
|
2048
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("svg", { width, height, viewBox, fill: "none", children: [
|
|
2049
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("ellipse", { cx: "50", cy: "50", rx: "24", ry: "30", stroke: fg, strokeWidth: "2.5" }),
|
|
2050
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("g", { style: { animation: "kora-blink 1.6s ease-in-out infinite" }, children: [
|
|
2051
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("circle", { cx: "40", cy: "44", r: "3", fill: fg }),
|
|
2052
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("circle", { cx: "60", cy: "44", r: "3", fill: fg })
|
|
2053
|
+
] }),
|
|
2054
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M 42 60 Q 50 64 58 60", stroke: dim, strokeWidth: "2", strokeLinecap: "round", fill: "none" })
|
|
2055
|
+
] });
|
|
2056
|
+
}
|
|
2057
|
+
|
|
2058
|
+
// src/hooks/useDocumentDetection.ts
|
|
2059
|
+
var import_react6 = require("react");
|
|
2060
|
+
var FRAME_INTERVAL_MS = 300;
|
|
2061
|
+
function useDocumentDetection(videoRef, side) {
|
|
2062
|
+
const [signals, setSignals] = (0, import_react6.useState)({
|
|
2063
|
+
documentDetected: false,
|
|
2064
|
+
detectorActive: false
|
|
2065
|
+
});
|
|
2066
|
+
const detectorRef = (0, import_react6.useRef)(null);
|
|
2067
|
+
const intervalRef = (0, import_react6.useRef)(null);
|
|
2068
|
+
(0, import_react6.useEffect)(() => {
|
|
2069
|
+
let cancelled = false;
|
|
2070
|
+
async function setup() {
|
|
2071
|
+
const win = typeof window !== "undefined" ? window : null;
|
|
2072
|
+
if (!win) return;
|
|
2073
|
+
let DetectorCtor = null;
|
|
2074
|
+
if (side === "front" && "FaceDetector" in win) {
|
|
2075
|
+
DetectorCtor = win["FaceDetector"];
|
|
2076
|
+
} else if (side === "back" && "BarcodeDetector" in win) {
|
|
2077
|
+
DetectorCtor = win["BarcodeDetector"];
|
|
2078
|
+
}
|
|
2079
|
+
if (!DetectorCtor) {
|
|
2080
|
+
return;
|
|
2081
|
+
}
|
|
2082
|
+
try {
|
|
2083
|
+
const detector = new DetectorCtor(
|
|
2084
|
+
side === "front" ? { fastMode: true, maxDetectedFaces: 1 } : { formats: ["pdf417", "qr_code", "data_matrix", "code_128"] }
|
|
2085
|
+
);
|
|
2086
|
+
if (cancelled) return;
|
|
2087
|
+
detectorRef.current = detector;
|
|
2088
|
+
setSignals((prev) => ({ ...prev, detectorActive: true }));
|
|
2089
|
+
} catch {
|
|
2090
|
+
return;
|
|
2091
|
+
}
|
|
2092
|
+
intervalRef.current = setInterval(async () => {
|
|
2093
|
+
const detector = detectorRef.current;
|
|
2094
|
+
const video = videoRef.current;
|
|
2095
|
+
if (!detector || !video || video.readyState < 2) return;
|
|
2096
|
+
try {
|
|
2097
|
+
const results = await detector.detect(video);
|
|
2098
|
+
if (cancelled) return;
|
|
2099
|
+
setSignals((prev) => {
|
|
2100
|
+
const next = results.length > 0;
|
|
2101
|
+
if (prev.documentDetected === next) return prev;
|
|
2102
|
+
return { ...prev, documentDetected: next };
|
|
2103
|
+
});
|
|
2104
|
+
} catch {
|
|
2105
|
+
}
|
|
2106
|
+
}, FRAME_INTERVAL_MS);
|
|
2107
|
+
}
|
|
2108
|
+
setup();
|
|
2109
|
+
return () => {
|
|
2110
|
+
cancelled = true;
|
|
2111
|
+
if (intervalRef.current) {
|
|
2112
|
+
clearInterval(intervalRef.current);
|
|
2113
|
+
intervalRef.current = null;
|
|
2114
|
+
}
|
|
2115
|
+
detectorRef.current = null;
|
|
2116
|
+
};
|
|
2117
|
+
}, [videoRef, side]);
|
|
2118
|
+
return signals;
|
|
2119
|
+
}
|
|
2120
|
+
|
|
2121
|
+
// src/components/DocumentCaptureScreen.tsx
|
|
2122
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
1811
2123
|
var qualityIssueMessages = {
|
|
1812
2124
|
face_blurred: "Photo on document is blurry. Retake in better lighting.",
|
|
1813
2125
|
low_resolution: "Image quality too low. Move closer to document.",
|
|
@@ -1824,23 +2136,25 @@ function DocumentCaptureScreen({
|
|
|
1824
2136
|
requiresBack = true,
|
|
1825
2137
|
onQualityCheck,
|
|
1826
2138
|
onCapture,
|
|
1827
|
-
onCancel
|
|
2139
|
+
onCancel,
|
|
2140
|
+
showVisualGuides = true
|
|
1828
2141
|
}) {
|
|
1829
|
-
const videoRef = (0,
|
|
1830
|
-
const canvasRef = (0,
|
|
1831
|
-
const guideRef = (0,
|
|
1832
|
-
const [stream, setStream] = (0,
|
|
1833
|
-
const
|
|
1834
|
-
const [
|
|
1835
|
-
const [
|
|
1836
|
-
const [
|
|
1837
|
-
const [
|
|
1838
|
-
const [
|
|
1839
|
-
const [
|
|
1840
|
-
(0,
|
|
2142
|
+
const videoRef = (0, import_react7.useRef)(null);
|
|
2143
|
+
const canvasRef = (0, import_react7.useRef)(null);
|
|
2144
|
+
const guideRef = (0, import_react7.useRef)(null);
|
|
2145
|
+
const [stream, setStream] = (0, import_react7.useState)(null);
|
|
2146
|
+
const documentSignals = useDocumentDetection(videoRef, side);
|
|
2147
|
+
const [isCapturing, setIsCapturing] = (0, import_react7.useState)(false);
|
|
2148
|
+
const [error, setError] = (0, import_react7.useState)(null);
|
|
2149
|
+
const [capturedImage, setCapturedImage] = (0, import_react7.useState)(null);
|
|
2150
|
+
const [capturedBlob, setCapturedBlob] = (0, import_react7.useState)(null);
|
|
2151
|
+
const [qualityResult, setQualityResult] = (0, import_react7.useState)(null);
|
|
2152
|
+
const [isCheckingQuality, setIsCheckingQuality] = (0, import_react7.useState)(false);
|
|
2153
|
+
const [retakeCount, setRetakeCount] = (0, import_react7.useState)(0);
|
|
2154
|
+
(0, import_react7.useEffect)(() => {
|
|
1841
2155
|
injectKeyframes();
|
|
1842
2156
|
}, []);
|
|
1843
|
-
(0,
|
|
2157
|
+
(0, import_react7.useEffect)(() => {
|
|
1844
2158
|
let mounted = true;
|
|
1845
2159
|
async function startCamera() {
|
|
1846
2160
|
try {
|
|
@@ -1862,12 +2176,12 @@ function DocumentCaptureScreen({
|
|
|
1862
2176
|
mounted = false;
|
|
1863
2177
|
};
|
|
1864
2178
|
}, [capturedImage]);
|
|
1865
|
-
(0,
|
|
2179
|
+
(0, import_react7.useEffect)(() => {
|
|
1866
2180
|
return () => {
|
|
1867
2181
|
stream?.getTracks().forEach((t) => t.stop());
|
|
1868
2182
|
};
|
|
1869
2183
|
}, [stream]);
|
|
1870
|
-
const handleCapture = (0,
|
|
2184
|
+
const handleCapture = (0, import_react7.useCallback)(() => {
|
|
1871
2185
|
if (!videoRef.current || !canvasRef.current || isCapturing) return;
|
|
1872
2186
|
setIsCapturing(true);
|
|
1873
2187
|
const video = videoRef.current;
|
|
@@ -1955,24 +2269,24 @@ function DocumentCaptureScreen({
|
|
|
1955
2269
|
}
|
|
1956
2270
|
};
|
|
1957
2271
|
if (error) {
|
|
1958
|
-
return /* @__PURE__ */ (0,
|
|
1959
|
-
/* @__PURE__ */ (0,
|
|
1960
|
-
/* @__PURE__ */ (0,
|
|
2272
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: styles.container, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: styles.errorContainer, children: [
|
|
2273
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { style: styles.errorText, children: error }),
|
|
2274
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { style: styles.primaryButton, onClick: onCancel, children: "Go Back" })
|
|
1961
2275
|
] }) });
|
|
1962
2276
|
}
|
|
1963
2277
|
if (capturedImage) {
|
|
1964
2278
|
const qualityPassed = qualityResult && qualityResult.qualityScore >= 60;
|
|
1965
2279
|
const qualityFailed = qualityResult && qualityResult.qualityScore < 60;
|
|
1966
2280
|
const canContinueAnyway = qualityFailed && retakeCount >= 2;
|
|
1967
|
-
return /* @__PURE__ */ (0,
|
|
1968
|
-
/* @__PURE__ */ (0,
|
|
1969
|
-
/* @__PURE__ */ (0,
|
|
1970
|
-
/* @__PURE__ */ (0,
|
|
1971
|
-
/* @__PURE__ */ (0,
|
|
1972
|
-
/* @__PURE__ */ (0,
|
|
2281
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: styles.darkContainer, children: [
|
|
2282
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(StepProgressBar, { total: 5, current: 3, isDark: true }),
|
|
2283
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: styles.darkScreenHeader, children: [
|
|
2284
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { width: 40 } }),
|
|
2285
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("h1", { style: styles.darkScreenTitle, children: "Review your photo" }),
|
|
2286
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { style: styles.glassCloseButton, onClick: onCancel, children: "\u2715" })
|
|
1973
2287
|
] }),
|
|
1974
|
-
/* @__PURE__ */ (0,
|
|
1975
|
-
/* @__PURE__ */ (0,
|
|
2288
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { flex: 1, display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", padding: "24px" }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: styles.reviewCard, children: [
|
|
2289
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1976
2290
|
"img",
|
|
1977
2291
|
{
|
|
1978
2292
|
src: capturedImage,
|
|
@@ -1980,42 +2294,42 @@ function DocumentCaptureScreen({
|
|
|
1980
2294
|
style: { width: "100%", maxWidth: "300px", borderRadius: "16px", display: "block", margin: "0 auto" }
|
|
1981
2295
|
}
|
|
1982
2296
|
),
|
|
1983
|
-
isCheckingQuality && /* @__PURE__ */ (0,
|
|
1984
|
-
qualityPassed && /* @__PURE__ */ (0,
|
|
1985
|
-
/* @__PURE__ */ (0,
|
|
2297
|
+
isCheckingQuality && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { textAlign: "center", marginTop: "16px" }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: { ...styles.reviewBadge, backgroundColor: "rgba(255,255,255,0.1)" }, children: "Checking quality..." }) }),
|
|
2298
|
+
qualityPassed && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
|
|
2299
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { textAlign: "center", marginTop: "16px" }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { style: styles.reviewBadge, children: [
|
|
1986
2300
|
"\u2713 Quality score: ",
|
|
1987
2301
|
Math.round(qualityResult.qualityScore),
|
|
1988
2302
|
"%"
|
|
1989
2303
|
] }) }),
|
|
1990
|
-
/* @__PURE__ */ (0,
|
|
1991
|
-
/* @__PURE__ */ (0,
|
|
1992
|
-
/* @__PURE__ */ (0,
|
|
1993
|
-
/* @__PURE__ */ (0,
|
|
2304
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: styles.qualityChecks, children: [
|
|
2305
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(QualityCheck, { label: "Sharp" }),
|
|
2306
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(QualityCheck, { label: "Well-lit" }),
|
|
2307
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(QualityCheck, { label: "Readable" })
|
|
1994
2308
|
] })
|
|
1995
2309
|
] }),
|
|
1996
|
-
qualityFailed && /* @__PURE__ */ (0,
|
|
1997
|
-
/* @__PURE__ */ (0,
|
|
2310
|
+
qualityFailed && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
|
|
2311
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { textAlign: "center", marginTop: "16px" }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { style: { ...styles.reviewBadge, backgroundColor: "rgba(239,68,68,0.15)", color: "#ef4444" }, children: [
|
|
1998
2312
|
"\u26A0 Quality score: ",
|
|
1999
2313
|
Math.round(qualityResult.qualityScore),
|
|
2000
2314
|
"%"
|
|
2001
2315
|
] }) }),
|
|
2002
|
-
/* @__PURE__ */ (0,
|
|
2316
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { padding: "12px 0" }, children: qualityResult.qualityIssues.map((issue, i) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { style: { color: "rgba(255,255,255,0.7)", fontSize: "13px", margin: "4px 0", textAlign: "center" }, children: qualityIssueMessages[issue] || issue }, i)) })
|
|
2003
2317
|
] }),
|
|
2004
|
-
!qualityResult && !isCheckingQuality && /* @__PURE__ */ (0,
|
|
2005
|
-
/* @__PURE__ */ (0,
|
|
2006
|
-
/* @__PURE__ */ (0,
|
|
2007
|
-
/* @__PURE__ */ (0,
|
|
2008
|
-
/* @__PURE__ */ (0,
|
|
2009
|
-
/* @__PURE__ */ (0,
|
|
2318
|
+
!qualityResult && !isCheckingQuality && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
|
|
2319
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { textAlign: "center", marginTop: "16px" }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: styles.reviewBadge, children: "\u2713 Good quality" }) }),
|
|
2320
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: styles.qualityChecks, children: [
|
|
2321
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(QualityCheck, { label: "Sharp" }),
|
|
2322
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(QualityCheck, { label: "Well-lit" }),
|
|
2323
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(QualityCheck, { label: "No glare" })
|
|
2010
2324
|
] })
|
|
2011
2325
|
] })
|
|
2012
2326
|
] }) }),
|
|
2013
|
-
/* @__PURE__ */ (0,
|
|
2014
|
-
/* @__PURE__ */ (0,
|
|
2015
|
-
canContinueAnyway && /* @__PURE__ */ (0,
|
|
2016
|
-
] }) : /* @__PURE__ */ (0,
|
|
2017
|
-
/* @__PURE__ */ (0,
|
|
2018
|
-
/* @__PURE__ */ (0,
|
|
2327
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: styles.reviewButtonsRow, children: qualityFailed ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
|
|
2328
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { style: { ...styles.darkOutlineButton, flex: 1 }, onClick: handleRetake, children: "Retake" }),
|
|
2329
|
+
canContinueAnyway && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { style: { ...styles.primaryButton, flex: 1 }, onClick: handleContinueAnyway, children: "Continue anyway" })
|
|
2330
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
|
|
2331
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { style: { ...styles.darkOutlineButton, flex: 1 }, onClick: handleRetake, children: "Retake" }),
|
|
2332
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
2019
2333
|
"button",
|
|
2020
2334
|
{
|
|
2021
2335
|
style: { ...styles.primaryButton, flex: 1, opacity: isCheckingQuality ? 0.5 : 1 },
|
|
@@ -2027,29 +2341,54 @@ function DocumentCaptureScreen({
|
|
|
2027
2341
|
] }) })
|
|
2028
2342
|
] });
|
|
2029
2343
|
}
|
|
2030
|
-
return /* @__PURE__ */ (0,
|
|
2031
|
-
/* @__PURE__ */ (0,
|
|
2032
|
-
/* @__PURE__ */ (0,
|
|
2033
|
-
/* @__PURE__ */ (0,
|
|
2034
|
-
/* @__PURE__ */ (0,
|
|
2035
|
-
/* @__PURE__ */ (0,
|
|
2036
|
-
documentType && /* @__PURE__ */ (0,
|
|
2344
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: styles.captureContainer, children: [
|
|
2345
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(StepProgressBar, { total: 5, current: 3, isDark: true }),
|
|
2346
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: styles.darkScreenHeader, children: [
|
|
2347
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { width: 40 } }),
|
|
2348
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { flex: 1, textAlign: "center" }, children: [
|
|
2349
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("h1", { style: { ...styles.darkScreenTitle, margin: 0 }, children: side === "front" ? "Front of ID" : "Back of ID" }),
|
|
2350
|
+
documentType && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { style: styles.darkScreenSubtitle, children: documentType })
|
|
2037
2351
|
] }),
|
|
2038
|
-
/* @__PURE__ */ (0,
|
|
2352
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { style: styles.glassCloseButton, onClick: onCancel, children: "\u2715" })
|
|
2039
2353
|
] }),
|
|
2040
|
-
/* @__PURE__ */ (0,
|
|
2041
|
-
|
|
2042
|
-
/* @__PURE__ */ (0,
|
|
2043
|
-
|
|
2044
|
-
/* @__PURE__ */ (0,
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2354
|
+
showVisualGuides && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { display: "flex", justifyContent: "center", padding: "6px 0 0" }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(VisualGuide, { kind: side === "front" ? "docFront" : "docBack", size: 56 }) }),
|
|
2355
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: styles.cameraContainer, children: [
|
|
2356
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("video", { ref: videoRef, autoPlay: true, playsInline: true, muted: true, style: styles.cameraVideo }),
|
|
2357
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: styles.documentOverlay, children: [
|
|
2358
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { ref: guideRef, style: styles.documentFrame, children: [
|
|
2359
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { ...styles.corner, top: 0, left: 0 } }),
|
|
2360
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { ...styles.corner, top: 0, right: 0, transform: "rotate(90deg)" } }),
|
|
2361
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { ...styles.corner, bottom: 0, right: 0, transform: "rotate(180deg)" } }),
|
|
2362
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { ...styles.corner, bottom: 0, left: 0, transform: "rotate(270deg)" } }),
|
|
2363
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: styles.scanLine })
|
|
2364
|
+
] }),
|
|
2365
|
+
documentSignals.detectorActive && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
2366
|
+
"div",
|
|
2367
|
+
{
|
|
2368
|
+
style: {
|
|
2369
|
+
position: "absolute",
|
|
2370
|
+
bottom: "24px",
|
|
2371
|
+
left: "50%",
|
|
2372
|
+
transform: "translateX(-50%)",
|
|
2373
|
+
padding: "6px 14px",
|
|
2374
|
+
borderRadius: "999px",
|
|
2375
|
+
fontSize: "12px",
|
|
2376
|
+
fontWeight: 600,
|
|
2377
|
+
color: documentSignals.documentDetected ? colors.success : "rgba(255,255,255,0.55)",
|
|
2378
|
+
backgroundColor: documentSignals.documentDetected ? "rgba(16,185,129,0.15)" : "rgba(0,0,0,0.35)",
|
|
2379
|
+
border: documentSignals.documentDetected ? "1px solid rgba(16,185,129,0.4)" : "1px solid rgba(255,255,255,0.12)",
|
|
2380
|
+
transition: "all 200ms",
|
|
2381
|
+
pointerEvents: "none",
|
|
2382
|
+
whiteSpace: "nowrap"
|
|
2383
|
+
},
|
|
2384
|
+
children: documentSignals.documentDetected ? "\u2713 Document detected \u2014 fill the frame" : "Position your ID inside the guide"
|
|
2385
|
+
}
|
|
2386
|
+
)
|
|
2387
|
+
] }),
|
|
2388
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("canvas", { ref: canvasRef, style: { display: "none" } })
|
|
2050
2389
|
] }),
|
|
2051
|
-
/* @__PURE__ */ (0,
|
|
2052
|
-
/* @__PURE__ */ (0,
|
|
2390
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: styles.stepPillsRow, children: [
|
|
2391
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
2053
2392
|
"span",
|
|
2054
2393
|
{
|
|
2055
2394
|
style: {
|
|
@@ -2060,7 +2399,7 @@ function DocumentCaptureScreen({
|
|
|
2060
2399
|
children: "Front"
|
|
2061
2400
|
}
|
|
2062
2401
|
),
|
|
2063
|
-
requiresBack && /* @__PURE__ */ (0,
|
|
2402
|
+
requiresBack && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
2064
2403
|
"span",
|
|
2065
2404
|
{
|
|
2066
2405
|
style: {
|
|
@@ -2072,7 +2411,7 @@ function DocumentCaptureScreen({
|
|
|
2072
2411
|
}
|
|
2073
2412
|
)
|
|
2074
2413
|
] }),
|
|
2075
|
-
/* @__PURE__ */ (0,
|
|
2414
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { textAlign: "center", padding: "8px 0" }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
2076
2415
|
"span",
|
|
2077
2416
|
{
|
|
2078
2417
|
style: {
|
|
@@ -2081,44 +2420,44 @@ function DocumentCaptureScreen({
|
|
|
2081
2420
|
color: colors.teal
|
|
2082
2421
|
},
|
|
2083
2422
|
children: [
|
|
2084
|
-
/* @__PURE__ */ (0,
|
|
2423
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: { ...styles.pulsingDot, backgroundColor: colors.teal } }),
|
|
2085
2424
|
"Scanning document..."
|
|
2086
2425
|
]
|
|
2087
2426
|
}
|
|
2088
2427
|
) }),
|
|
2089
|
-
/* @__PURE__ */ (0,
|
|
2428
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: styles.captureFooter, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
2090
2429
|
"button",
|
|
2091
2430
|
{
|
|
2092
2431
|
style: { ...styles.captureButton, opacity: isCapturing ? 0.5 : 1 },
|
|
2093
2432
|
onClick: handleCapture,
|
|
2094
2433
|
disabled: isCapturing,
|
|
2095
|
-
children: /* @__PURE__ */ (0,
|
|
2434
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: styles.captureButtonInner })
|
|
2096
2435
|
}
|
|
2097
2436
|
) })
|
|
2098
2437
|
] });
|
|
2099
2438
|
}
|
|
2100
2439
|
function QualityCheck({ label }) {
|
|
2101
|
-
return /* @__PURE__ */ (0,
|
|
2102
|
-
/* @__PURE__ */ (0,
|
|
2103
|
-
/* @__PURE__ */ (0,
|
|
2440
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: styles.qualityCheck, children: [
|
|
2441
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: styles.qualityCheckIcon, children: "\u2713" }),
|
|
2442
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: styles.qualityCheckLabel, children: label })
|
|
2104
2443
|
] });
|
|
2105
2444
|
}
|
|
2106
2445
|
|
|
2107
2446
|
// src/components/FlipDocumentScreen.tsx
|
|
2108
|
-
var
|
|
2109
|
-
var
|
|
2447
|
+
var import_react8 = require("react");
|
|
2448
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
2110
2449
|
function FlipDocumentScreen({ onContinue, onCancel }) {
|
|
2111
|
-
(0,
|
|
2450
|
+
(0, import_react8.useEffect)(() => {
|
|
2112
2451
|
injectKeyframes();
|
|
2113
2452
|
}, []);
|
|
2114
|
-
return /* @__PURE__ */ (0,
|
|
2115
|
-
/* @__PURE__ */ (0,
|
|
2116
|
-
/* @__PURE__ */ (0,
|
|
2117
|
-
/* @__PURE__ */ (0,
|
|
2118
|
-
/* @__PURE__ */ (0,
|
|
2119
|
-
/* @__PURE__ */ (0,
|
|
2453
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: styles.darkContainer, children: [
|
|
2454
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(StepProgressBar, { total: 5, current: 3, isDark: true }),
|
|
2455
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: styles.darkScreenHeader, children: [
|
|
2456
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { width: 40 } }),
|
|
2457
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h1", { style: styles.darkScreenTitle, children: "Flip your document" }),
|
|
2458
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { style: styles.glassCloseButton, onClick: onCancel, children: "\u2715" })
|
|
2120
2459
|
] }),
|
|
2121
|
-
/* @__PURE__ */ (0,
|
|
2460
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: {
|
|
2122
2461
|
flex: 1,
|
|
2123
2462
|
display: "flex",
|
|
2124
2463
|
flexDirection: "column",
|
|
@@ -2127,7 +2466,7 @@ function FlipDocumentScreen({ onContinue, onCancel }) {
|
|
|
2127
2466
|
padding: "24px",
|
|
2128
2467
|
gap: "32px"
|
|
2129
2468
|
}, children: [
|
|
2130
|
-
/* @__PURE__ */ (0,
|
|
2469
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
|
|
2131
2470
|
width: "120px",
|
|
2132
2471
|
height: "120px",
|
|
2133
2472
|
borderRadius: "50%",
|
|
@@ -2135,18 +2474,18 @@ function FlipDocumentScreen({ onContinue, onCancel }) {
|
|
|
2135
2474
|
display: "flex",
|
|
2136
2475
|
alignItems: "center",
|
|
2137
2476
|
justifyContent: "center"
|
|
2138
|
-
}, children: /* @__PURE__ */ (0,
|
|
2139
|
-
/* @__PURE__ */ (0,
|
|
2140
|
-
/* @__PURE__ */ (0,
|
|
2477
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("svg", { width: "56", height: "56", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
|
|
2478
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M9 3L5 6.99H8V14H10V6.99H13L9 3Z", fill: colors.teal }),
|
|
2479
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("path", { d: "M16 17.01V10H14V17.01H11L15 21L19 17.01H16Z", fill: colors.teal })
|
|
2141
2480
|
] }) }),
|
|
2142
|
-
/* @__PURE__ */ (0,
|
|
2143
|
-
/* @__PURE__ */ (0,
|
|
2481
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { textAlign: "center" }, children: [
|
|
2482
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h2", { style: {
|
|
2144
2483
|
fontSize: "22px",
|
|
2145
2484
|
fontWeight: 700,
|
|
2146
2485
|
color: colors.white,
|
|
2147
2486
|
margin: "0 0 12px 0"
|
|
2148
2487
|
}, children: "Now capture the back" }),
|
|
2149
|
-
/* @__PURE__ */ (0,
|
|
2488
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { style: {
|
|
2150
2489
|
fontSize: "15px",
|
|
2151
2490
|
color: "rgba(255,255,255,0.6)",
|
|
2152
2491
|
margin: 0,
|
|
@@ -2154,38 +2493,38 @@ function FlipDocumentScreen({ onContinue, onCancel }) {
|
|
|
2154
2493
|
maxWidth: "280px"
|
|
2155
2494
|
}, children: "Turn your document over to the back side, then tap continue to take a photo." })
|
|
2156
2495
|
] }),
|
|
2157
|
-
/* @__PURE__ */ (0,
|
|
2158
|
-
/* @__PURE__ */ (0,
|
|
2496
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: styles.stepPillsRow, children: [
|
|
2497
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: {
|
|
2159
2498
|
...styles.stepPill,
|
|
2160
2499
|
backgroundColor: "rgba(16,185,129,0.15)",
|
|
2161
2500
|
color: colors.success
|
|
2162
2501
|
}, children: "\u2713 Front" }),
|
|
2163
|
-
/* @__PURE__ */ (0,
|
|
2502
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: {
|
|
2164
2503
|
...styles.stepPill,
|
|
2165
2504
|
backgroundColor: colors.teal,
|
|
2166
2505
|
color: colors.white
|
|
2167
2506
|
}, children: "Back" })
|
|
2168
2507
|
] })
|
|
2169
2508
|
] }),
|
|
2170
|
-
/* @__PURE__ */ (0,
|
|
2509
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { padding: "24px" }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { style: styles.primaryButton, onClick: onContinue, children: "Continue" }) })
|
|
2171
2510
|
] });
|
|
2172
2511
|
}
|
|
2173
2512
|
|
|
2174
2513
|
// src/components/SelfieCaptureScreen.tsx
|
|
2175
|
-
var
|
|
2176
|
-
var
|
|
2177
|
-
function SelfieCaptureScreen({ onCapture, onCancel }) {
|
|
2178
|
-
const videoRef = (0,
|
|
2179
|
-
const canvasRef = (0,
|
|
2180
|
-
const [stream, setStream] = (0,
|
|
2181
|
-
const [isCapturing, setIsCapturing] = (0,
|
|
2182
|
-
const [error, setError] = (0,
|
|
2183
|
-
const [capturedImage, setCapturedImage] = (0,
|
|
2184
|
-
const [capturedBlob, setCapturedBlob] = (0,
|
|
2185
|
-
(0,
|
|
2514
|
+
var import_react9 = require("react");
|
|
2515
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
2516
|
+
function SelfieCaptureScreen({ onCapture, onCancel, showVisualGuides = true }) {
|
|
2517
|
+
const videoRef = (0, import_react9.useRef)(null);
|
|
2518
|
+
const canvasRef = (0, import_react9.useRef)(null);
|
|
2519
|
+
const [stream, setStream] = (0, import_react9.useState)(null);
|
|
2520
|
+
const [isCapturing, setIsCapturing] = (0, import_react9.useState)(false);
|
|
2521
|
+
const [error, setError] = (0, import_react9.useState)(null);
|
|
2522
|
+
const [capturedImage, setCapturedImage] = (0, import_react9.useState)(null);
|
|
2523
|
+
const [capturedBlob, setCapturedBlob] = (0, import_react9.useState)(null);
|
|
2524
|
+
(0, import_react9.useEffect)(() => {
|
|
2186
2525
|
injectKeyframes();
|
|
2187
2526
|
}, []);
|
|
2188
|
-
(0,
|
|
2527
|
+
(0, import_react9.useEffect)(() => {
|
|
2189
2528
|
let mounted = true;
|
|
2190
2529
|
async function startCamera() {
|
|
2191
2530
|
try {
|
|
@@ -2207,12 +2546,12 @@ function SelfieCaptureScreen({ onCapture, onCancel }) {
|
|
|
2207
2546
|
mounted = false;
|
|
2208
2547
|
};
|
|
2209
2548
|
}, [capturedImage]);
|
|
2210
|
-
(0,
|
|
2549
|
+
(0, import_react9.useEffect)(() => {
|
|
2211
2550
|
return () => {
|
|
2212
2551
|
stream?.getTracks().forEach((t) => t.stop());
|
|
2213
2552
|
};
|
|
2214
2553
|
}, [stream]);
|
|
2215
|
-
const handleCapture = (0,
|
|
2554
|
+
const handleCapture = (0, import_react9.useCallback)(() => {
|
|
2216
2555
|
if (!videoRef.current || !canvasRef.current || isCapturing) return;
|
|
2217
2556
|
setIsCapturing(true);
|
|
2218
2557
|
const video = videoRef.current;
|
|
@@ -2251,22 +2590,22 @@ function SelfieCaptureScreen({ onCapture, onCancel }) {
|
|
|
2251
2590
|
}
|
|
2252
2591
|
};
|
|
2253
2592
|
if (error) {
|
|
2254
|
-
return /* @__PURE__ */ (0,
|
|
2255
|
-
/* @__PURE__ */ (0,
|
|
2256
|
-
/* @__PURE__ */ (0,
|
|
2593
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: styles.container, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: styles.errorContainer, children: [
|
|
2594
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { style: styles.errorText, children: error }),
|
|
2595
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { style: styles.primaryButton, onClick: onCancel, children: "Go Back" })
|
|
2257
2596
|
] }) });
|
|
2258
2597
|
}
|
|
2259
2598
|
if (capturedImage) {
|
|
2260
|
-
return /* @__PURE__ */ (0,
|
|
2261
|
-
/* @__PURE__ */ (0,
|
|
2262
|
-
/* @__PURE__ */ (0,
|
|
2263
|
-
/* @__PURE__ */ (0,
|
|
2264
|
-
/* @__PURE__ */ (0,
|
|
2265
|
-
/* @__PURE__ */ (0,
|
|
2599
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: styles.darkContainer, children: [
|
|
2600
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(StepProgressBar, { total: 5, current: 4, isDark: true }),
|
|
2601
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: styles.darkScreenHeader, children: [
|
|
2602
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: { width: 40 } }),
|
|
2603
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("h1", { style: styles.darkScreenTitle, children: "Does this look like you?" }),
|
|
2604
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { style: styles.glassCloseButton, onClick: onCancel, children: "\u2715" })
|
|
2266
2605
|
] }),
|
|
2267
|
-
/* @__PURE__ */ (0,
|
|
2268
|
-
/* @__PURE__ */ (0,
|
|
2269
|
-
/* @__PURE__ */ (0,
|
|
2606
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { style: styles.darkScreenSubtitle, children: "Check clarity and lighting" }),
|
|
2607
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: { flex: 1, display: "flex", alignItems: "center", justifyContent: "center", padding: "24px" }, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { position: "relative" }, children: [
|
|
2608
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: { width: "240px", height: "300px", borderRadius: "50%", overflow: "hidden", border: `3px solid ${colors.teal}` }, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
2270
2609
|
"img",
|
|
2271
2610
|
{
|
|
2272
2611
|
src: capturedImage,
|
|
@@ -2274,31 +2613,32 @@ function SelfieCaptureScreen({ onCapture, onCancel }) {
|
|
|
2274
2613
|
style: { width: "100%", height: "100%", objectFit: "cover" }
|
|
2275
2614
|
}
|
|
2276
2615
|
) }),
|
|
2277
|
-
/* @__PURE__ */ (0,
|
|
2278
|
-
/* @__PURE__ */ (0,
|
|
2279
|
-
/* @__PURE__ */ (0,
|
|
2280
|
-
/* @__PURE__ */ (0,
|
|
2281
|
-
/* @__PURE__ */ (0,
|
|
2616
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: { textAlign: "center", marginTop: "16px" }, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { style: styles.reviewBadge, children: "\u2713 Face detected" }) }),
|
|
2617
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: styles.qualityChecks, children: [
|
|
2618
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(QualityCheck2, { label: "Clear" }),
|
|
2619
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(QualityCheck2, { label: "Centered" }),
|
|
2620
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(QualityCheck2, { label: "Well-lit" })
|
|
2282
2621
|
] })
|
|
2283
2622
|
] }) }),
|
|
2284
|
-
/* @__PURE__ */ (0,
|
|
2285
|
-
/* @__PURE__ */ (0,
|
|
2286
|
-
/* @__PURE__ */ (0,
|
|
2623
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: styles.reviewButtonsRow, children: [
|
|
2624
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { style: { ...styles.darkOutlineButton, flex: 1 }, onClick: handleRetake, children: "Retake" }),
|
|
2625
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { style: { ...styles.primaryButton, flex: 1 }, onClick: handleAccept, children: "Use this" })
|
|
2287
2626
|
] })
|
|
2288
2627
|
] });
|
|
2289
2628
|
}
|
|
2290
|
-
return /* @__PURE__ */ (0,
|
|
2291
|
-
/* @__PURE__ */ (0,
|
|
2292
|
-
/* @__PURE__ */ (0,
|
|
2293
|
-
/* @__PURE__ */ (0,
|
|
2294
|
-
/* @__PURE__ */ (0,
|
|
2295
|
-
/* @__PURE__ */ (0,
|
|
2296
|
-
/* @__PURE__ */ (0,
|
|
2629
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: styles.captureContainer, children: [
|
|
2630
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(StepProgressBar, { total: 5, current: 4, isDark: true }),
|
|
2631
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: styles.darkScreenHeader, children: [
|
|
2632
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: { width: 40 } }),
|
|
2633
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { flex: 1, textAlign: "center" }, children: [
|
|
2634
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("h1", { style: { ...styles.darkScreenTitle, margin: 0, fontSize: "24px", fontWeight: 700 }, children: "Face the camera" }),
|
|
2635
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { style: styles.darkScreenSubtitle, children: "Keep a neutral expression" })
|
|
2297
2636
|
] }),
|
|
2298
|
-
/* @__PURE__ */ (0,
|
|
2637
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { style: styles.glassCloseButton, onClick: onCancel, children: "\u2715" })
|
|
2299
2638
|
] }),
|
|
2300
|
-
/* @__PURE__ */ (0,
|
|
2301
|
-
|
|
2639
|
+
showVisualGuides && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: { display: "flex", justifyContent: "center", padding: "6px 0 0" }, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(VisualGuide, { kind: "selfie", size: 56 }) }),
|
|
2640
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: styles.cameraContainer, children: [
|
|
2641
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
2302
2642
|
"video",
|
|
2303
2643
|
{
|
|
2304
2644
|
ref: videoRef,
|
|
@@ -2308,10 +2648,10 @@ function SelfieCaptureScreen({ onCapture, onCancel }) {
|
|
|
2308
2648
|
style: { ...styles.cameraVideo, transform: "scaleX(-1)" }
|
|
2309
2649
|
}
|
|
2310
2650
|
),
|
|
2311
|
-
/* @__PURE__ */ (0,
|
|
2312
|
-
/* @__PURE__ */ (0,
|
|
2651
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: styles.selfieOverlay, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: styles.faceGuide, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: styles.rotatingRing }) }) }),
|
|
2652
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("canvas", { ref: canvasRef, style: { display: "none" } })
|
|
2313
2653
|
] }),
|
|
2314
|
-
/* @__PURE__ */ (0,
|
|
2654
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: { textAlign: "center", padding: "8px 0" }, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
2315
2655
|
"span",
|
|
2316
2656
|
{
|
|
2317
2657
|
style: {
|
|
@@ -2320,32 +2660,88 @@ function SelfieCaptureScreen({ onCapture, onCancel }) {
|
|
|
2320
2660
|
color: colors.teal
|
|
2321
2661
|
},
|
|
2322
2662
|
children: [
|
|
2323
|
-
/* @__PURE__ */ (0,
|
|
2663
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { style: { ...styles.pulsingDot, backgroundColor: colors.teal } }),
|
|
2324
2664
|
"Position your face in the oval"
|
|
2325
2665
|
]
|
|
2326
2666
|
}
|
|
2327
2667
|
) }),
|
|
2328
|
-
/* @__PURE__ */ (0,
|
|
2668
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: styles.captureFooter, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
2329
2669
|
"button",
|
|
2330
2670
|
{
|
|
2331
2671
|
style: { ...styles.captureButton, opacity: isCapturing ? 0.5 : 1 },
|
|
2332
2672
|
onClick: handleCapture,
|
|
2333
2673
|
disabled: isCapturing,
|
|
2334
|
-
children: /* @__PURE__ */ (0,
|
|
2674
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: styles.captureButtonInner })
|
|
2335
2675
|
}
|
|
2336
2676
|
) })
|
|
2337
2677
|
] });
|
|
2338
2678
|
}
|
|
2339
2679
|
function QualityCheck2({ label }) {
|
|
2340
|
-
return /* @__PURE__ */ (0,
|
|
2341
|
-
/* @__PURE__ */ (0,
|
|
2342
|
-
/* @__PURE__ */ (0,
|
|
2680
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: styles.qualityCheck, children: [
|
|
2681
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: styles.qualityCheckIcon, children: "\u2713" }),
|
|
2682
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { style: styles.qualityCheckLabel, children: label })
|
|
2343
2683
|
] });
|
|
2344
2684
|
}
|
|
2345
2685
|
|
|
2346
2686
|
// src/components/LivenessScreen.tsx
|
|
2347
|
-
var
|
|
2348
|
-
|
|
2687
|
+
var import_react11 = require("react");
|
|
2688
|
+
|
|
2689
|
+
// src/hooks/useLivenessSignals.ts
|
|
2690
|
+
var import_react10 = require("react");
|
|
2691
|
+
var FRAME_INTERVAL_MS2 = 250;
|
|
2692
|
+
function useLivenessSignals(videoRef) {
|
|
2693
|
+
const [signals, setSignals] = (0, import_react10.useState)({
|
|
2694
|
+
faceDetected: false,
|
|
2695
|
+
detectorActive: false
|
|
2696
|
+
});
|
|
2697
|
+
const detectorRef = (0, import_react10.useRef)(null);
|
|
2698
|
+
const intervalRef = (0, import_react10.useRef)(null);
|
|
2699
|
+
(0, import_react10.useEffect)(() => {
|
|
2700
|
+
let cancelled = false;
|
|
2701
|
+
async function setupDetector() {
|
|
2702
|
+
const NativeFaceDetector = typeof window !== "undefined" && "FaceDetector" in window ? window.FaceDetector : null;
|
|
2703
|
+
if (!NativeFaceDetector) {
|
|
2704
|
+
return;
|
|
2705
|
+
}
|
|
2706
|
+
try {
|
|
2707
|
+
const detector = new NativeFaceDetector({ fastMode: true, maxDetectedFaces: 1 });
|
|
2708
|
+
if (cancelled) return;
|
|
2709
|
+
detectorRef.current = detector;
|
|
2710
|
+
setSignals((prev) => ({ ...prev, detectorActive: true }));
|
|
2711
|
+
} catch {
|
|
2712
|
+
return;
|
|
2713
|
+
}
|
|
2714
|
+
intervalRef.current = setInterval(async () => {
|
|
2715
|
+
const detector = detectorRef.current;
|
|
2716
|
+
const video = videoRef.current;
|
|
2717
|
+
if (!detector || !video || video.readyState < 2) return;
|
|
2718
|
+
try {
|
|
2719
|
+
const faces = await detector.detect(video);
|
|
2720
|
+
if (cancelled) return;
|
|
2721
|
+
setSignals((prev) => {
|
|
2722
|
+
const next = faces.length > 0;
|
|
2723
|
+
if (prev.faceDetected === next) return prev;
|
|
2724
|
+
return { ...prev, faceDetected: next };
|
|
2725
|
+
});
|
|
2726
|
+
} catch {
|
|
2727
|
+
}
|
|
2728
|
+
}, FRAME_INTERVAL_MS2);
|
|
2729
|
+
}
|
|
2730
|
+
setupDetector();
|
|
2731
|
+
return () => {
|
|
2732
|
+
cancelled = true;
|
|
2733
|
+
if (intervalRef.current) {
|
|
2734
|
+
clearInterval(intervalRef.current);
|
|
2735
|
+
intervalRef.current = null;
|
|
2736
|
+
}
|
|
2737
|
+
detectorRef.current = null;
|
|
2738
|
+
};
|
|
2739
|
+
}, [videoRef]);
|
|
2740
|
+
return signals;
|
|
2741
|
+
}
|
|
2742
|
+
|
|
2743
|
+
// src/components/LivenessScreen.tsx
|
|
2744
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
2349
2745
|
function LivenessScreen({
|
|
2350
2746
|
session,
|
|
2351
2747
|
currentChallenge,
|
|
@@ -2353,22 +2749,25 @@ function LivenessScreen({
|
|
|
2353
2749
|
onChallengeComplete,
|
|
2354
2750
|
onStart,
|
|
2355
2751
|
onComplete,
|
|
2356
|
-
onCancel
|
|
2752
|
+
onCancel,
|
|
2753
|
+
lastChallengeError,
|
|
2754
|
+
showVisualGuides = true
|
|
2357
2755
|
}) {
|
|
2358
|
-
const videoRef = (0,
|
|
2359
|
-
const canvasRef = (0,
|
|
2360
|
-
const [stream, setStream] = (0,
|
|
2361
|
-
const
|
|
2362
|
-
const [
|
|
2363
|
-
const [
|
|
2364
|
-
const [
|
|
2365
|
-
(0,
|
|
2756
|
+
const videoRef = (0, import_react11.useRef)(null);
|
|
2757
|
+
const canvasRef = (0, import_react11.useRef)(null);
|
|
2758
|
+
const [stream, setStream] = (0, import_react11.useState)(null);
|
|
2759
|
+
const livenessSignals = useLivenessSignals(videoRef);
|
|
2760
|
+
const [cameraError, setCameraError] = (0, import_react11.useState)(null);
|
|
2761
|
+
const [phase, setPhase] = (0, import_react11.useState)("preparing");
|
|
2762
|
+
const [countdown, setCountdown] = (0, import_react11.useState)(3);
|
|
2763
|
+
const [capturing, setCapturing] = (0, import_react11.useState)(false);
|
|
2764
|
+
(0, import_react11.useEffect)(() => {
|
|
2366
2765
|
injectKeyframes();
|
|
2367
2766
|
}, []);
|
|
2368
|
-
(0,
|
|
2767
|
+
(0, import_react11.useEffect)(() => {
|
|
2369
2768
|
if (!session) onStart();
|
|
2370
2769
|
}, [session, onStart]);
|
|
2371
|
-
(0,
|
|
2770
|
+
(0, import_react11.useEffect)(() => {
|
|
2372
2771
|
let mounted = true;
|
|
2373
2772
|
async function startCamera() {
|
|
2374
2773
|
try {
|
|
@@ -2400,17 +2799,17 @@ function LivenessScreen({
|
|
|
2400
2799
|
mounted = false;
|
|
2401
2800
|
};
|
|
2402
2801
|
}, []);
|
|
2403
|
-
(0,
|
|
2802
|
+
(0, import_react11.useEffect)(() => {
|
|
2404
2803
|
return () => {
|
|
2405
2804
|
stream?.getTracks().forEach((t) => t.stop());
|
|
2406
2805
|
};
|
|
2407
2806
|
}, [stream]);
|
|
2408
|
-
(0,
|
|
2807
|
+
(0, import_react11.useEffect)(() => {
|
|
2409
2808
|
if (!currentChallenge) return;
|
|
2410
2809
|
setPhase("preparing");
|
|
2411
2810
|
setCountdown(3);
|
|
2412
2811
|
}, [currentChallenge?.id]);
|
|
2413
|
-
const captureFrame = (0,
|
|
2812
|
+
const captureFrame = (0, import_react11.useCallback)(async () => {
|
|
2414
2813
|
if (!currentChallenge || !videoRef.current || !canvasRef.current || capturing) {
|
|
2415
2814
|
return;
|
|
2416
2815
|
}
|
|
@@ -2433,7 +2832,7 @@ function LivenessScreen({
|
|
|
2433
2832
|
0.85
|
|
2434
2833
|
);
|
|
2435
2834
|
}, [currentChallenge, capturing, onChallengeComplete]);
|
|
2436
|
-
(0,
|
|
2835
|
+
(0, import_react11.useEffect)(() => {
|
|
2437
2836
|
if (!currentChallenge || capturing) return;
|
|
2438
2837
|
if (countdown === 0) {
|
|
2439
2838
|
if (phase === "preparing") {
|
|
@@ -2447,32 +2846,32 @@ function LivenessScreen({
|
|
|
2447
2846
|
const t = setTimeout(() => setCountdown((c) => c - 1), 1e3);
|
|
2448
2847
|
return () => clearTimeout(t);
|
|
2449
2848
|
}, [countdown, currentChallenge?.id, capturing, captureFrame, phase]);
|
|
2450
|
-
(0,
|
|
2849
|
+
(0, import_react11.useEffect)(() => {
|
|
2451
2850
|
if (session && !currentChallenge && completedChallenges > 0) {
|
|
2452
2851
|
onComplete();
|
|
2453
2852
|
}
|
|
2454
2853
|
}, [session, currentChallenge, completedChallenges, onComplete]);
|
|
2455
2854
|
if (cameraError) {
|
|
2456
|
-
return /* @__PURE__ */ (0,
|
|
2457
|
-
/* @__PURE__ */ (0,
|
|
2458
|
-
/* @__PURE__ */ (0,
|
|
2855
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: styles.darkContainer, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: styles.errorContainer, children: [
|
|
2856
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { style: styles.errorText, children: cameraError }),
|
|
2857
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { style: styles.primaryButton, onClick: onCancel, children: "Go back" })
|
|
2459
2858
|
] }) });
|
|
2460
2859
|
}
|
|
2461
2860
|
if (!session) {
|
|
2462
|
-
return /* @__PURE__ */ (0,
|
|
2463
|
-
/* @__PURE__ */ (0,
|
|
2464
|
-
/* @__PURE__ */ (0,
|
|
2861
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: styles.darkContainer, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: styles.loadingContainer, children: [
|
|
2862
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: styles.spinner }),
|
|
2863
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { style: { ...styles.loadingText, color: "rgba(255,255,255,0.6)" }, children: "Starting liveness check..." })
|
|
2465
2864
|
] }) });
|
|
2466
2865
|
}
|
|
2467
2866
|
const totalChallenges = session.challenges.length;
|
|
2468
|
-
return /* @__PURE__ */ (0,
|
|
2469
|
-
/* @__PURE__ */ (0,
|
|
2470
|
-
/* @__PURE__ */ (0,
|
|
2471
|
-
/* @__PURE__ */ (0,
|
|
2472
|
-
/* @__PURE__ */ (0,
|
|
2473
|
-
/* @__PURE__ */ (0,
|
|
2867
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: styles.captureContainer, children: [
|
|
2868
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(StepProgressBar, { total: 5, current: 5, isDark: true }),
|
|
2869
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: styles.darkScreenHeader, children: [
|
|
2870
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: { width: 40 } }),
|
|
2871
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("h1", { style: styles.darkScreenTitle, children: "Liveness Check" }),
|
|
2872
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { style: styles.glassCloseButton, onClick: onCancel, children: "\u2715" })
|
|
2474
2873
|
] }),
|
|
2475
|
-
/* @__PURE__ */ (0,
|
|
2874
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
2476
2875
|
"div",
|
|
2477
2876
|
{
|
|
2478
2877
|
style: {
|
|
@@ -2485,8 +2884,8 @@ function LivenessScreen({
|
|
|
2485
2884
|
padding: "16px 0"
|
|
2486
2885
|
},
|
|
2487
2886
|
children: [
|
|
2488
|
-
/* @__PURE__ */ (0,
|
|
2489
|
-
/* @__PURE__ */ (0,
|
|
2887
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: { position: "relative" }, children: [
|
|
2888
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2490
2889
|
"div",
|
|
2491
2890
|
{
|
|
2492
2891
|
style: {
|
|
@@ -2497,7 +2896,7 @@ function LivenessScreen({
|
|
|
2497
2896
|
backgroundColor: "#000",
|
|
2498
2897
|
border: "3px solid rgba(255,255,255,0.2)"
|
|
2499
2898
|
},
|
|
2500
|
-
children: /* @__PURE__ */ (0,
|
|
2899
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2501
2900
|
"video",
|
|
2502
2901
|
{
|
|
2503
2902
|
ref: videoRef,
|
|
@@ -2514,7 +2913,7 @@ function LivenessScreen({
|
|
|
2514
2913
|
)
|
|
2515
2914
|
}
|
|
2516
2915
|
),
|
|
2517
|
-
/* @__PURE__ */ (0,
|
|
2916
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2518
2917
|
"svg",
|
|
2519
2918
|
{
|
|
2520
2919
|
style: {
|
|
@@ -2526,7 +2925,7 @@ function LivenessScreen({
|
|
|
2526
2925
|
width: "256",
|
|
2527
2926
|
height: "316",
|
|
2528
2927
|
viewBox: "0 0 256 316",
|
|
2529
|
-
children: /* @__PURE__ */ (0,
|
|
2928
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2530
2929
|
"ellipse",
|
|
2531
2930
|
{
|
|
2532
2931
|
cx: "128",
|
|
@@ -2542,9 +2941,30 @@ function LivenessScreen({
|
|
|
2542
2941
|
}
|
|
2543
2942
|
)
|
|
2544
2943
|
}
|
|
2944
|
+
),
|
|
2945
|
+
livenessSignals.detectorActive && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2946
|
+
"div",
|
|
2947
|
+
{
|
|
2948
|
+
style: {
|
|
2949
|
+
position: "absolute",
|
|
2950
|
+
bottom: "-32px",
|
|
2951
|
+
left: "50%",
|
|
2952
|
+
transform: "translateX(-50%)",
|
|
2953
|
+
padding: "6px 14px",
|
|
2954
|
+
borderRadius: "999px",
|
|
2955
|
+
fontSize: "12px",
|
|
2956
|
+
fontWeight: 600,
|
|
2957
|
+
color: livenessSignals.faceDetected ? colors.success : "rgba(255,255,255,0.55)",
|
|
2958
|
+
backgroundColor: livenessSignals.faceDetected ? "rgba(16,185,129,0.15)" : "rgba(255,255,255,0.06)",
|
|
2959
|
+
border: livenessSignals.faceDetected ? "1px solid rgba(16,185,129,0.4)" : "1px solid rgba(255,255,255,0.12)",
|
|
2960
|
+
transition: "all 200ms",
|
|
2961
|
+
whiteSpace: "nowrap"
|
|
2962
|
+
},
|
|
2963
|
+
children: livenessSignals.faceDetected ? "\u2713 Face detected" : "Position your face in the oval"
|
|
2964
|
+
}
|
|
2545
2965
|
)
|
|
2546
2966
|
] }),
|
|
2547
|
-
currentChallenge && /* @__PURE__ */ (0,
|
|
2967
|
+
currentChallenge && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
2548
2968
|
"div",
|
|
2549
2969
|
{
|
|
2550
2970
|
style: {
|
|
@@ -2557,7 +2977,14 @@ function LivenessScreen({
|
|
|
2557
2977
|
transition: "background-color 200ms, border-color 200ms"
|
|
2558
2978
|
},
|
|
2559
2979
|
children: [
|
|
2560
|
-
/* @__PURE__ */ (0,
|
|
2980
|
+
showVisualGuides && visualGuideForChallenge(currentChallenge.type) && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: { display: "flex", justifyContent: "center", marginBottom: "12px" }, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2981
|
+
VisualGuide,
|
|
2982
|
+
{
|
|
2983
|
+
kind: visualGuideForChallenge(currentChallenge.type),
|
|
2984
|
+
size: 64
|
|
2985
|
+
}
|
|
2986
|
+
) }),
|
|
2987
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2561
2988
|
"p",
|
|
2562
2989
|
{
|
|
2563
2990
|
style: {
|
|
@@ -2571,7 +2998,7 @@ function LivenessScreen({
|
|
|
2571
2998
|
children: capturing ? "Checking..." : phase === "preparing" ? "Get ready" : "Now \u2014 hold the pose"
|
|
2572
2999
|
}
|
|
2573
3000
|
),
|
|
2574
|
-
/* @__PURE__ */ (0,
|
|
3001
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2575
3002
|
"h2",
|
|
2576
3003
|
{
|
|
2577
3004
|
style: {
|
|
@@ -2582,7 +3009,7 @@ function LivenessScreen({
|
|
|
2582
3009
|
children: currentChallenge.instruction
|
|
2583
3010
|
}
|
|
2584
3011
|
),
|
|
2585
|
-
!capturing && /* @__PURE__ */ (0,
|
|
3012
|
+
!capturing && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2586
3013
|
"p",
|
|
2587
3014
|
{
|
|
2588
3015
|
style: {
|
|
@@ -2594,16 +3021,33 @@ function LivenessScreen({
|
|
|
2594
3021
|
},
|
|
2595
3022
|
children: countdown
|
|
2596
3023
|
}
|
|
3024
|
+
),
|
|
3025
|
+
lastChallengeError && phase === "preparing" && !capturing && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
3026
|
+
"p",
|
|
3027
|
+
{
|
|
3028
|
+
style: {
|
|
3029
|
+
margin: "14px 0 0",
|
|
3030
|
+
padding: "10px 12px",
|
|
3031
|
+
borderRadius: "10px",
|
|
3032
|
+
fontSize: "13px",
|
|
3033
|
+
fontWeight: 500,
|
|
3034
|
+
color: "#fca5a5",
|
|
3035
|
+
backgroundColor: "rgba(239,68,68,0.10)",
|
|
3036
|
+
border: "1px solid rgba(239,68,68,0.25)",
|
|
3037
|
+
lineHeight: 1.35
|
|
3038
|
+
},
|
|
3039
|
+
children: lastChallengeError
|
|
3040
|
+
}
|
|
2597
3041
|
)
|
|
2598
3042
|
]
|
|
2599
3043
|
}
|
|
2600
3044
|
),
|
|
2601
|
-
/* @__PURE__ */ (0,
|
|
3045
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("canvas", { ref: canvasRef, style: { display: "none" } })
|
|
2602
3046
|
]
|
|
2603
3047
|
}
|
|
2604
3048
|
),
|
|
2605
|
-
/* @__PURE__ */ (0,
|
|
2606
|
-
/* @__PURE__ */ (0,
|
|
3049
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: { padding: "16px 0" }, children: [
|
|
3050
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: styles.progressDots, children: session.challenges.map((_, index) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2607
3051
|
"div",
|
|
2608
3052
|
{
|
|
2609
3053
|
style: {
|
|
@@ -2613,7 +3057,7 @@ function LivenessScreen({
|
|
|
2613
3057
|
},
|
|
2614
3058
|
index
|
|
2615
3059
|
)) }),
|
|
2616
|
-
/* @__PURE__ */ (0,
|
|
3060
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("p", { style: styles.progressText, children: [
|
|
2617
3061
|
"Challenge ",
|
|
2618
3062
|
Math.min(completedChallenges + 1, totalChallenges),
|
|
2619
3063
|
" of",
|
|
@@ -2621,7 +3065,7 @@ function LivenessScreen({
|
|
|
2621
3065
|
totalChallenges
|
|
2622
3066
|
] })
|
|
2623
3067
|
] }),
|
|
2624
|
-
/* @__PURE__ */ (0,
|
|
3068
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: { padding: "0 24px 24px", textAlign: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2625
3069
|
"p",
|
|
2626
3070
|
{
|
|
2627
3071
|
style: {
|
|
@@ -2636,35 +3080,35 @@ function LivenessScreen({
|
|
|
2636
3080
|
}
|
|
2637
3081
|
|
|
2638
3082
|
// src/components/ResultScreen.tsx
|
|
2639
|
-
var
|
|
3083
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
2640
3084
|
function ResultScreen({ verification, onDone, onRetry, resultPageMode, simplified, customMessages }) {
|
|
2641
3085
|
const { status } = verification;
|
|
2642
3086
|
const effectiveMode = resultPageMode ?? (simplified ? "simplified" : "detailed");
|
|
2643
3087
|
if (effectiveMode === "simplified") {
|
|
2644
3088
|
switch (status) {
|
|
2645
3089
|
case "approved":
|
|
2646
|
-
return /* @__PURE__ */ (0,
|
|
3090
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SimplifiedSuccess, { onDone, customMessages });
|
|
2647
3091
|
case "rejected":
|
|
2648
|
-
return /* @__PURE__ */ (0,
|
|
3092
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SimplifiedFailed, { onRetry: onRetry || onDone, customMessages });
|
|
2649
3093
|
case "review_required":
|
|
2650
|
-
return /* @__PURE__ */ (0,
|
|
3094
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SimplifiedReview, { verification, onDone, customMessages });
|
|
2651
3095
|
case "expired":
|
|
2652
|
-
return /* @__PURE__ */ (0,
|
|
3096
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SimplifiedFailed, { onRetry: onRetry || onDone, customMessages: { failedTitle: "Document Expired", failedMessage: "The document you submitted has expired. Please use a valid document." } });
|
|
2653
3097
|
default:
|
|
2654
|
-
return /* @__PURE__ */ (0,
|
|
3098
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SimplifiedSuccess, { onDone, customMessages });
|
|
2655
3099
|
}
|
|
2656
3100
|
}
|
|
2657
3101
|
switch (status) {
|
|
2658
3102
|
case "approved":
|
|
2659
|
-
return /* @__PURE__ */ (0,
|
|
3103
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SuccessResult, { verification, onDone });
|
|
2660
3104
|
case "rejected":
|
|
2661
|
-
return /* @__PURE__ */ (0,
|
|
3105
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(RejectedResult, { verification, onRetry: onRetry || onDone });
|
|
2662
3106
|
case "expired":
|
|
2663
|
-
return /* @__PURE__ */ (0,
|
|
3107
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ExpiredResult, { verification, onRetry: onRetry || onDone });
|
|
2664
3108
|
case "review_required":
|
|
2665
|
-
return /* @__PURE__ */ (0,
|
|
3109
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ManualReviewResult, { verification, onDone });
|
|
2666
3110
|
default:
|
|
2667
|
-
return /* @__PURE__ */ (0,
|
|
3111
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SuccessResult, { verification, onDone });
|
|
2668
3112
|
}
|
|
2669
3113
|
}
|
|
2670
3114
|
function SuccessResult({ verification, onDone }) {
|
|
@@ -2672,16 +3116,16 @@ function SuccessResult({ verification, onDone }) {
|
|
|
2672
3116
|
verification.scores?.overall ?? 100 - (verification.riskScore ?? 16)
|
|
2673
3117
|
);
|
|
2674
3118
|
const metrics = computeScoreBreakdown(verification);
|
|
2675
|
-
return /* @__PURE__ */ (0,
|
|
2676
|
-
/* @__PURE__ */ (0,
|
|
2677
|
-
/* @__PURE__ */ (0,
|
|
3119
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: styles.resultContainer, children: [
|
|
3120
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: styles.resultContent, children: [
|
|
3121
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
2678
3122
|
"div",
|
|
2679
3123
|
{
|
|
2680
3124
|
style: {
|
|
2681
3125
|
...styles.resultIconOuterRing,
|
|
2682
3126
|
backgroundColor: `${colors.success}15`
|
|
2683
3127
|
},
|
|
2684
|
-
children: /* @__PURE__ */ (0,
|
|
3128
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
2685
3129
|
"div",
|
|
2686
3130
|
{
|
|
2687
3131
|
style: {
|
|
@@ -2695,9 +3139,9 @@ function SuccessResult({ verification, onDone }) {
|
|
|
2695
3139
|
)
|
|
2696
3140
|
}
|
|
2697
3141
|
),
|
|
2698
|
-
/* @__PURE__ */ (0,
|
|
2699
|
-
/* @__PURE__ */ (0,
|
|
2700
|
-
/* @__PURE__ */ (0,
|
|
3142
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("h1", { style: styles.resultTitle, children: "Verification approved" }),
|
|
3143
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { style: styles.resultSubtitle, children: "Your identity has been successfully verified." }),
|
|
3144
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
2701
3145
|
ScoreCard,
|
|
2702
3146
|
{
|
|
2703
3147
|
score,
|
|
@@ -2705,9 +3149,9 @@ function SuccessResult({ verification, onDone }) {
|
|
|
2705
3149
|
gradient: `linear-gradient(135deg, ${colors.teal}, ${colors.tealDark})`
|
|
2706
3150
|
}
|
|
2707
3151
|
),
|
|
2708
|
-
metrics.map((m, i) => /* @__PURE__ */ (0,
|
|
3152
|
+
metrics.map((m, i) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ScoreMetricRow, { ...m }, i))
|
|
2709
3153
|
] }),
|
|
2710
|
-
/* @__PURE__ */ (0,
|
|
3154
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { style: styles.footer, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { style: styles.primaryButton, onClick: onDone, children: "Done" }) })
|
|
2711
3155
|
] });
|
|
2712
3156
|
}
|
|
2713
3157
|
function RejectedResult({ verification, onRetry }) {
|
|
@@ -2715,16 +3159,16 @@ function RejectedResult({ verification, onRetry }) {
|
|
|
2715
3159
|
verification.scores?.overall ?? 100 - (verification.riskScore ?? 58)
|
|
2716
3160
|
);
|
|
2717
3161
|
const metrics = computeScoreBreakdown(verification);
|
|
2718
|
-
return /* @__PURE__ */ (0,
|
|
2719
|
-
/* @__PURE__ */ (0,
|
|
2720
|
-
/* @__PURE__ */ (0,
|
|
3162
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: styles.resultContainer, children: [
|
|
3163
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: styles.resultContent, children: [
|
|
3164
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
2721
3165
|
"div",
|
|
2722
3166
|
{
|
|
2723
3167
|
style: {
|
|
2724
3168
|
...styles.resultIconOuterRing,
|
|
2725
3169
|
backgroundColor: `${colors.error}15`
|
|
2726
3170
|
},
|
|
2727
|
-
children: /* @__PURE__ */ (0,
|
|
3171
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
2728
3172
|
"div",
|
|
2729
3173
|
{
|
|
2730
3174
|
style: {
|
|
@@ -2738,9 +3182,9 @@ function RejectedResult({ verification, onRetry }) {
|
|
|
2738
3182
|
)
|
|
2739
3183
|
}
|
|
2740
3184
|
),
|
|
2741
|
-
/* @__PURE__ */ (0,
|
|
2742
|
-
/* @__PURE__ */ (0,
|
|
2743
|
-
/* @__PURE__ */ (0,
|
|
3185
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("h1", { style: styles.resultTitle, children: "Verification rejected" }),
|
|
3186
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { style: styles.resultSubtitle, children: "We could not verify your identity. Please try again with a valid document." }),
|
|
3187
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
2744
3188
|
ScoreCard,
|
|
2745
3189
|
{
|
|
2746
3190
|
score,
|
|
@@ -2748,15 +3192,15 @@ function RejectedResult({ verification, onRetry }) {
|
|
|
2748
3192
|
gradient: `linear-gradient(135deg, ${colors.error}, #B91C1C)`
|
|
2749
3193
|
}
|
|
2750
3194
|
),
|
|
2751
|
-
metrics.map((m, i) => /* @__PURE__ */ (0,
|
|
3195
|
+
metrics.map((m, i) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ScoreMetricRow, { ...m }, i))
|
|
2752
3196
|
] }),
|
|
2753
|
-
/* @__PURE__ */ (0,
|
|
3197
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { style: styles.footer, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { style: styles.primaryButton, onClick: onRetry, children: "Try again" }) })
|
|
2754
3198
|
] });
|
|
2755
3199
|
}
|
|
2756
3200
|
function ExpiredResult({ verification, onRetry }) {
|
|
2757
|
-
return /* @__PURE__ */ (0,
|
|
2758
|
-
/* @__PURE__ */ (0,
|
|
2759
|
-
/* @__PURE__ */ (0,
|
|
3201
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: styles.resultContainer, children: [
|
|
3202
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: styles.resultContent, children: [
|
|
3203
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
2760
3204
|
"div",
|
|
2761
3205
|
{
|
|
2762
3206
|
style: {
|
|
@@ -2764,7 +3208,7 @@ function ExpiredResult({ verification, onRetry }) {
|
|
|
2764
3208
|
backgroundColor: `${colors.warning}15`,
|
|
2765
3209
|
border: `2px solid ${colors.warning}30`
|
|
2766
3210
|
},
|
|
2767
|
-
children: /* @__PURE__ */ (0,
|
|
3211
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
2768
3212
|
"div",
|
|
2769
3213
|
{
|
|
2770
3214
|
style: {
|
|
@@ -2778,29 +3222,29 @@ function ExpiredResult({ verification, onRetry }) {
|
|
|
2778
3222
|
)
|
|
2779
3223
|
}
|
|
2780
3224
|
),
|
|
2781
|
-
/* @__PURE__ */ (0,
|
|
2782
|
-
/* @__PURE__ */ (0,
|
|
2783
|
-
verification.documentVerification && /* @__PURE__ */ (0,
|
|
2784
|
-
/* @__PURE__ */ (0,
|
|
2785
|
-
/* @__PURE__ */ (0,
|
|
2786
|
-
/* @__PURE__ */ (0,
|
|
3225
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("h1", { style: styles.resultTitle, children: "Document expired" }),
|
|
3226
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { style: styles.resultSubtitle, children: "The document you submitted has expired. Please use a valid, non-expired document." }),
|
|
3227
|
+
verification.documentVerification && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: styles.expiryCard, children: [
|
|
3228
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: styles.expiryRow, children: [
|
|
3229
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { style: styles.expiryLabel, children: "Document type" }),
|
|
3230
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { style: styles.expiryValue, children: verification.documentVerification.documentType || "ID Card" })
|
|
2787
3231
|
] }),
|
|
2788
|
-
verification.documentVerification.issuingCountry && /* @__PURE__ */ (0,
|
|
2789
|
-
/* @__PURE__ */ (0,
|
|
2790
|
-
/* @__PURE__ */ (0,
|
|
3232
|
+
verification.documentVerification.issuingCountry && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: styles.expiryRow, children: [
|
|
3233
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { style: styles.expiryLabel, children: "Country" }),
|
|
3234
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { style: styles.expiryValue, children: verification.documentVerification.issuingCountry })
|
|
2791
3235
|
] }),
|
|
2792
|
-
verification.documentVerification.expirationDate && /* @__PURE__ */ (0,
|
|
2793
|
-
/* @__PURE__ */ (0,
|
|
2794
|
-
/* @__PURE__ */ (0,
|
|
3236
|
+
verification.documentVerification.expirationDate && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: styles.expiryRow, children: [
|
|
3237
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { style: styles.expiryLabel, children: "Expired on" }),
|
|
3238
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { style: styles.expiryBadge, children: verification.documentVerification.expirationDate })
|
|
2795
3239
|
] })
|
|
2796
3240
|
] }),
|
|
2797
|
-
/* @__PURE__ */ (0,
|
|
2798
|
-
/* @__PURE__ */ (0,
|
|
2799
|
-
/* @__PURE__ */ (0,
|
|
2800
|
-
/* @__PURE__ */ (0,
|
|
3241
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: { textAlign: "left" }, children: [
|
|
3242
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(GuidanceTip, { number: 1, text: "Check the expiration date on your document" }),
|
|
3243
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(GuidanceTip, { number: 2, text: "Use a different document that is currently valid" }),
|
|
3244
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(GuidanceTip, { number: 3, text: "Ensure the document details are clearly visible" })
|
|
2801
3245
|
] })
|
|
2802
3246
|
] }),
|
|
2803
|
-
/* @__PURE__ */ (0,
|
|
3247
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { style: styles.footer, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { style: styles.primaryButton, onClick: onRetry, children: "Try with a valid document" }) })
|
|
2804
3248
|
] });
|
|
2805
3249
|
}
|
|
2806
3250
|
function ManualReviewResult({ verification, onDone }) {
|
|
@@ -2808,9 +3252,9 @@ function ManualReviewResult({ verification, onDone }) {
|
|
|
2808
3252
|
verification.scores?.overall ?? 100 - (verification.riskScore ?? 32)
|
|
2809
3253
|
);
|
|
2810
3254
|
const metrics = computeScoreBreakdown(verification);
|
|
2811
|
-
return /* @__PURE__ */ (0,
|
|
2812
|
-
/* @__PURE__ */ (0,
|
|
2813
|
-
/* @__PURE__ */ (0,
|
|
3255
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: styles.resultContainer, children: [
|
|
3256
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: styles.resultContent, children: [
|
|
3257
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
2814
3258
|
"div",
|
|
2815
3259
|
{
|
|
2816
3260
|
style: {
|
|
@@ -2818,7 +3262,7 @@ function ManualReviewResult({ verification, onDone }) {
|
|
|
2818
3262
|
backgroundColor: `${colors.info}15`,
|
|
2819
3263
|
border: `2px solid ${colors.info}30`
|
|
2820
3264
|
},
|
|
2821
|
-
children: /* @__PURE__ */ (0,
|
|
3265
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
2822
3266
|
"div",
|
|
2823
3267
|
{
|
|
2824
3268
|
style: {
|
|
@@ -2832,9 +3276,9 @@ function ManualReviewResult({ verification, onDone }) {
|
|
|
2832
3276
|
)
|
|
2833
3277
|
}
|
|
2834
3278
|
),
|
|
2835
|
-
/* @__PURE__ */ (0,
|
|
2836
|
-
/* @__PURE__ */ (0,
|
|
2837
|
-
/* @__PURE__ */ (0,
|
|
3279
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("h1", { style: styles.resultTitle, children: "Under review" }),
|
|
3280
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { style: styles.resultSubtitle, children: "Your verification requires manual review. We'll notify you of the result." }),
|
|
3281
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
2838
3282
|
ScoreCard,
|
|
2839
3283
|
{
|
|
2840
3284
|
score,
|
|
@@ -2842,21 +3286,21 @@ function ManualReviewResult({ verification, onDone }) {
|
|
|
2842
3286
|
gradient: `linear-gradient(135deg, ${colors.info}, #0369A1)`
|
|
2843
3287
|
}
|
|
2844
3288
|
),
|
|
2845
|
-
metrics.map((m, i) => /* @__PURE__ */ (0,
|
|
3289
|
+
metrics.map((m, i) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ScoreMetricRow, { ...m }, i))
|
|
2846
3290
|
] }),
|
|
2847
|
-
/* @__PURE__ */ (0,
|
|
3291
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { style: styles.footer, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { style: styles.primaryButton, onClick: onDone, children: "Got it" }) })
|
|
2848
3292
|
] });
|
|
2849
3293
|
}
|
|
2850
3294
|
function GuidanceTip({ number, text }) {
|
|
2851
|
-
return /* @__PURE__ */ (0,
|
|
2852
|
-
/* @__PURE__ */ (0,
|
|
2853
|
-
/* @__PURE__ */ (0,
|
|
3295
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: styles.guidanceTip, children: [
|
|
3296
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { style: styles.guidanceTipNumber, children: number }),
|
|
3297
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { style: styles.guidanceTipText, children: text })
|
|
2854
3298
|
] });
|
|
2855
3299
|
}
|
|
2856
3300
|
function SimplifiedSuccess({ onDone, customMessages }) {
|
|
2857
|
-
return /* @__PURE__ */ (0,
|
|
2858
|
-
/* @__PURE__ */ (0,
|
|
2859
|
-
/* @__PURE__ */ (0,
|
|
3301
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: styles.resultContainer, children: [
|
|
3302
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: { ...styles.resultContent, textAlign: "center" }, children: [
|
|
3303
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
2860
3304
|
"div",
|
|
2861
3305
|
{
|
|
2862
3306
|
style: {
|
|
@@ -2865,7 +3309,7 @@ function SimplifiedSuccess({ onDone, customMessages }) {
|
|
|
2865
3309
|
width: 96,
|
|
2866
3310
|
height: 96
|
|
2867
3311
|
},
|
|
2868
|
-
children: /* @__PURE__ */ (0,
|
|
3312
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
2869
3313
|
"div",
|
|
2870
3314
|
{
|
|
2871
3315
|
style: {
|
|
@@ -2882,16 +3326,16 @@ function SimplifiedSuccess({ onDone, customMessages }) {
|
|
|
2882
3326
|
)
|
|
2883
3327
|
}
|
|
2884
3328
|
),
|
|
2885
|
-
/* @__PURE__ */ (0,
|
|
2886
|
-
/* @__PURE__ */ (0,
|
|
3329
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("h1", { style: { ...styles.resultTitle, fontSize: 24, marginTop: 16 }, children: customMessages?.successTitle || "Verification Successful" }),
|
|
3330
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { style: { ...styles.resultSubtitle, fontSize: 16, maxWidth: 320, margin: "8px auto 0" }, children: customMessages?.successMessage || "Your identity has been successfully verified. You can now proceed." })
|
|
2887
3331
|
] }),
|
|
2888
|
-
/* @__PURE__ */ (0,
|
|
3332
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { style: styles.footer, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { style: styles.primaryButton, onClick: onDone, children: "Continue" }) })
|
|
2889
3333
|
] });
|
|
2890
3334
|
}
|
|
2891
3335
|
function SimplifiedFailed({ onRetry, customMessages }) {
|
|
2892
|
-
return /* @__PURE__ */ (0,
|
|
2893
|
-
/* @__PURE__ */ (0,
|
|
2894
|
-
/* @__PURE__ */ (0,
|
|
3336
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: styles.resultContainer, children: [
|
|
3337
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: { ...styles.resultContent, textAlign: "center" }, children: [
|
|
3338
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
2895
3339
|
"div",
|
|
2896
3340
|
{
|
|
2897
3341
|
style: {
|
|
@@ -2900,7 +3344,7 @@ function SimplifiedFailed({ onRetry, customMessages }) {
|
|
|
2900
3344
|
width: 96,
|
|
2901
3345
|
height: 96
|
|
2902
3346
|
},
|
|
2903
|
-
children: /* @__PURE__ */ (0,
|
|
3347
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
2904
3348
|
"div",
|
|
2905
3349
|
{
|
|
2906
3350
|
style: {
|
|
@@ -2917,16 +3361,16 @@ function SimplifiedFailed({ onRetry, customMessages }) {
|
|
|
2917
3361
|
)
|
|
2918
3362
|
}
|
|
2919
3363
|
),
|
|
2920
|
-
/* @__PURE__ */ (0,
|
|
2921
|
-
/* @__PURE__ */ (0,
|
|
3364
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("h1", { style: { ...styles.resultTitle, fontSize: 24, marginTop: 16 }, children: customMessages?.failedTitle || "Verification Failed" }),
|
|
3365
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { style: { ...styles.resultSubtitle, fontSize: 16, maxWidth: 320, margin: "8px auto 0" }, children: customMessages?.failedMessage || "We could not verify your identity. Please try again with a valid document." })
|
|
2922
3366
|
] }),
|
|
2923
|
-
/* @__PURE__ */ (0,
|
|
3367
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { style: styles.footer, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { style: styles.primaryButton, onClick: onRetry, children: "Try Again" }) })
|
|
2924
3368
|
] });
|
|
2925
3369
|
}
|
|
2926
3370
|
function SimplifiedReview({ verification, onDone, customMessages }) {
|
|
2927
|
-
return /* @__PURE__ */ (0,
|
|
2928
|
-
/* @__PURE__ */ (0,
|
|
2929
|
-
/* @__PURE__ */ (0,
|
|
3371
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: styles.resultContainer, children: [
|
|
3372
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: { ...styles.resultContent, textAlign: "center" }, children: [
|
|
3373
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
2930
3374
|
"div",
|
|
2931
3375
|
{
|
|
2932
3376
|
style: {
|
|
@@ -2935,7 +3379,7 @@ function SimplifiedReview({ verification, onDone, customMessages }) {
|
|
|
2935
3379
|
width: 96,
|
|
2936
3380
|
height: 96
|
|
2937
3381
|
},
|
|
2938
|
-
children: /* @__PURE__ */ (0,
|
|
3382
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
2939
3383
|
"div",
|
|
2940
3384
|
{
|
|
2941
3385
|
style: {
|
|
@@ -2952,9 +3396,9 @@ function SimplifiedReview({ verification, onDone, customMessages }) {
|
|
|
2952
3396
|
)
|
|
2953
3397
|
}
|
|
2954
3398
|
),
|
|
2955
|
-
/* @__PURE__ */ (0,
|
|
2956
|
-
/* @__PURE__ */ (0,
|
|
2957
|
-
/* @__PURE__ */ (0,
|
|
3399
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("h1", { style: { ...styles.resultTitle, fontSize: 24, marginTop: 16 }, children: customMessages?.reviewTitle || "Verification Under Review" }),
|
|
3400
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { style: { ...styles.resultSubtitle, fontSize: 16, maxWidth: 320, margin: "8px auto 0" }, children: customMessages?.reviewMessage || "Your verification requires additional review. We will notify you of the result." }),
|
|
3401
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: {
|
|
2958
3402
|
marginTop: 24,
|
|
2959
3403
|
padding: "12px 24px",
|
|
2960
3404
|
backgroundColor: `${colors.info}10`,
|
|
@@ -2962,27 +3406,27 @@ function SimplifiedReview({ verification, onDone, customMessages }) {
|
|
|
2962
3406
|
border: `1px solid ${colors.info}30`,
|
|
2963
3407
|
display: "inline-block"
|
|
2964
3408
|
}, children: [
|
|
2965
|
-
/* @__PURE__ */ (0,
|
|
2966
|
-
/* @__PURE__ */ (0,
|
|
3409
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { style: { fontSize: 12, color: colors.textSecondary }, children: "Reference: " }),
|
|
3410
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { style: { fontSize: 14, fontWeight: 600, fontFamily: "monospace" }, children: verification.id.slice(0, 8) })
|
|
2967
3411
|
] })
|
|
2968
3412
|
] }),
|
|
2969
|
-
/* @__PURE__ */ (0,
|
|
3413
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { style: styles.footer, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { style: styles.primaryButton, onClick: onDone, children: "Got It" }) })
|
|
2970
3414
|
] });
|
|
2971
3415
|
}
|
|
2972
3416
|
|
|
2973
3417
|
// src/components/ErrorScreen.tsx
|
|
2974
|
-
var
|
|
3418
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
2975
3419
|
function ErrorScreen({ error, onRetry, onCancel }) {
|
|
2976
|
-
return /* @__PURE__ */ (0,
|
|
2977
|
-
/* @__PURE__ */ (0,
|
|
2978
|
-
/* @__PURE__ */ (0,
|
|
3420
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { style: styles.resultContainer, children: [
|
|
3421
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { style: styles.resultContent, children: [
|
|
3422
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2979
3423
|
"div",
|
|
2980
3424
|
{
|
|
2981
3425
|
style: {
|
|
2982
3426
|
...styles.resultIconOuterRing,
|
|
2983
3427
|
backgroundColor: colors.errorBg
|
|
2984
3428
|
},
|
|
2985
|
-
children: /* @__PURE__ */ (0,
|
|
3429
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2986
3430
|
"div",
|
|
2987
3431
|
{
|
|
2988
3432
|
style: {
|
|
@@ -2996,26 +3440,26 @@ function ErrorScreen({ error, onRetry, onCancel }) {
|
|
|
2996
3440
|
)
|
|
2997
3441
|
}
|
|
2998
3442
|
),
|
|
2999
|
-
/* @__PURE__ */ (0,
|
|
3000
|
-
/* @__PURE__ */ (0,
|
|
3001
|
-
error.recoverySuggestion && /* @__PURE__ */ (0,
|
|
3443
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("h1", { style: styles.resultTitle, children: "Something went wrong" }),
|
|
3444
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { style: styles.resultSubtitle, children: error.message }),
|
|
3445
|
+
error.recoverySuggestion && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { style: { ...styles.bodyText, marginTop: "12px" }, children: error.recoverySuggestion })
|
|
3002
3446
|
] }),
|
|
3003
|
-
/* @__PURE__ */ (0,
|
|
3004
|
-
error.isRetryable && /* @__PURE__ */ (0,
|
|
3005
|
-
/* @__PURE__ */ (0,
|
|
3447
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { style: styles.footer, children: [
|
|
3448
|
+
error.isRetryable && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("button", { style: styles.primaryButton, onClick: onRetry, children: "Try Again" }),
|
|
3449
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("button", { style: styles.textButton, onClick: onCancel, children: "Cancel" })
|
|
3006
3450
|
] })
|
|
3007
3451
|
] });
|
|
3008
3452
|
}
|
|
3009
3453
|
|
|
3010
3454
|
// src/components/LoadingScreen.tsx
|
|
3011
|
-
var
|
|
3012
|
-
var
|
|
3455
|
+
var import_react12 = require("react");
|
|
3456
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
3013
3457
|
function LoadingScreen({ message = "Loading..." }) {
|
|
3014
|
-
(0,
|
|
3458
|
+
(0, import_react12.useEffect)(() => {
|
|
3015
3459
|
injectKeyframes();
|
|
3016
3460
|
}, []);
|
|
3017
|
-
return /* @__PURE__ */ (0,
|
|
3018
|
-
/* @__PURE__ */ (0,
|
|
3461
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: styles.container, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: styles.loadingContainer, children: [
|
|
3462
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
3019
3463
|
"div",
|
|
3020
3464
|
{
|
|
3021
3465
|
style: {
|
|
@@ -3032,16 +3476,19 @@ function LoadingScreen({ message = "Loading..." }) {
|
|
|
3032
3476
|
children: "\u{1F6E1}\uFE0F"
|
|
3033
3477
|
}
|
|
3034
3478
|
),
|
|
3035
|
-
/* @__PURE__ */ (0,
|
|
3479
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { style: styles.loadingText, children: message })
|
|
3036
3480
|
] }) });
|
|
3037
3481
|
}
|
|
3038
3482
|
|
|
3039
3483
|
// src/components/VerificationFlow.tsx
|
|
3040
|
-
var
|
|
3484
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
3041
3485
|
function VerificationFlow({
|
|
3042
3486
|
externalId,
|
|
3043
3487
|
tier = "standard",
|
|
3044
3488
|
documentTypes,
|
|
3489
|
+
expectedFirstName,
|
|
3490
|
+
expectedLastName,
|
|
3491
|
+
showVisualGuides = true,
|
|
3045
3492
|
onComplete,
|
|
3046
3493
|
onError,
|
|
3047
3494
|
onCancel,
|
|
@@ -3063,20 +3510,20 @@ function VerificationFlow({
|
|
|
3063
3510
|
retry,
|
|
3064
3511
|
sdk
|
|
3065
3512
|
} = useKoraIDV();
|
|
3066
|
-
const [selectedCountry, setSelectedCountry] = (0,
|
|
3067
|
-
const [flowStep, setFlowStep] = (0,
|
|
3068
|
-
const [showFlipInstruction, setShowFlipInstruction] = (0,
|
|
3069
|
-
const [supportedCountries, setSupportedCountries] = (0,
|
|
3070
|
-
const [countriesLoading, setCountriesLoading] = (0,
|
|
3071
|
-
(0,
|
|
3513
|
+
const [selectedCountry, setSelectedCountry] = (0, import_react13.useState)(null);
|
|
3514
|
+
const [flowStep, setFlowStep] = (0, import_react13.useState)("consent");
|
|
3515
|
+
const [showFlipInstruction, setShowFlipInstruction] = (0, import_react13.useState)(true);
|
|
3516
|
+
const [supportedCountries, setSupportedCountries] = (0, import_react13.useState)([]);
|
|
3517
|
+
const [countriesLoading, setCountriesLoading] = (0, import_react13.useState)(false);
|
|
3518
|
+
(0, import_react13.useEffect)(() => {
|
|
3072
3519
|
if (state.step === "document_front") {
|
|
3073
3520
|
setShowFlipInstruction(true);
|
|
3074
3521
|
}
|
|
3075
3522
|
}, [state.step]);
|
|
3076
|
-
(0,
|
|
3077
|
-
startVerification(externalId, tier);
|
|
3078
|
-
}, [externalId, tier, startVerification]);
|
|
3079
|
-
(0,
|
|
3523
|
+
(0, import_react13.useEffect)(() => {
|
|
3524
|
+
startVerification(externalId, tier, expectedFirstName, expectedLastName);
|
|
3525
|
+
}, [externalId, tier, expectedFirstName, expectedLastName, startVerification]);
|
|
3526
|
+
(0, import_react13.useEffect)(() => {
|
|
3080
3527
|
if (state.error && onError) {
|
|
3081
3528
|
onError(state.error);
|
|
3082
3529
|
}
|
|
@@ -3122,19 +3569,19 @@ function VerificationFlow({
|
|
|
3122
3569
|
...style
|
|
3123
3570
|
};
|
|
3124
3571
|
if (state.error) {
|
|
3125
|
-
return /* @__PURE__ */ (0,
|
|
3572
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className, style: containerStyle, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ErrorScreen, { error: state.error, onRetry: retry, onCancel: handleCancel }) });
|
|
3126
3573
|
}
|
|
3127
3574
|
if (state.isLoading && state.step !== "processing") {
|
|
3128
|
-
return /* @__PURE__ */ (0,
|
|
3575
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className, style: containerStyle, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(LoadingScreen, {}) });
|
|
3129
3576
|
}
|
|
3130
3577
|
if (flowStep === "consent" && state.step === "consent") {
|
|
3131
|
-
return /* @__PURE__ */ (0,
|
|
3578
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className, style: containerStyle, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ConsentScreen, { onAccept: handleAcceptConsent, onDecline: handleCancel }) });
|
|
3132
3579
|
}
|
|
3133
3580
|
if (flowStep === "country_selection") {
|
|
3134
3581
|
if (countriesLoading) {
|
|
3135
|
-
return /* @__PURE__ */ (0,
|
|
3582
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className, style: containerStyle, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(LoadingScreen, {}) });
|
|
3136
3583
|
}
|
|
3137
|
-
return /* @__PURE__ */ (0,
|
|
3584
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className, style: containerStyle, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
3138
3585
|
CountrySelectionScreen,
|
|
3139
3586
|
{
|
|
3140
3587
|
countries: supportedCountries,
|
|
@@ -3143,8 +3590,8 @@ function VerificationFlow({
|
|
|
3143
3590
|
}
|
|
3144
3591
|
) });
|
|
3145
3592
|
}
|
|
3146
|
-
return /* @__PURE__ */ (0,
|
|
3147
|
-
state.step === "document_selection" && /* @__PURE__ */ (0,
|
|
3593
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className, style: containerStyle, children: [
|
|
3594
|
+
state.step === "document_selection" && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
3148
3595
|
DocumentSelectionScreen,
|
|
3149
3596
|
{
|
|
3150
3597
|
documentTypes,
|
|
@@ -3153,32 +3600,41 @@ function VerificationFlow({
|
|
|
3153
3600
|
onCancel: handleCancel
|
|
3154
3601
|
}
|
|
3155
3602
|
),
|
|
3156
|
-
state.step === "document_front" && /* @__PURE__ */ (0,
|
|
3603
|
+
state.step === "document_front" && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
3157
3604
|
DocumentCaptureScreen,
|
|
3158
3605
|
{
|
|
3159
3606
|
side: "front",
|
|
3160
3607
|
onQualityCheck: (blob) => checkDocumentQuality(blob),
|
|
3161
3608
|
onCapture: (imageData) => uploadDocument(imageData, "front", selectedCountry?.id),
|
|
3162
|
-
onCancel: handleCancel
|
|
3609
|
+
onCancel: handleCancel,
|
|
3610
|
+
showVisualGuides
|
|
3163
3611
|
}
|
|
3164
3612
|
),
|
|
3165
|
-
state.step === "document_back" && showFlipInstruction && /* @__PURE__ */ (0,
|
|
3613
|
+
state.step === "document_back" && showFlipInstruction && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
3166
3614
|
FlipDocumentScreen,
|
|
3167
3615
|
{
|
|
3168
3616
|
onContinue: () => setShowFlipInstruction(false),
|
|
3169
3617
|
onCancel: handleCancel
|
|
3170
3618
|
}
|
|
3171
3619
|
),
|
|
3172
|
-
state.step === "document_back" && !showFlipInstruction && /* @__PURE__ */ (0,
|
|
3620
|
+
state.step === "document_back" && !showFlipInstruction && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
3173
3621
|
DocumentCaptureScreen,
|
|
3174
3622
|
{
|
|
3175
3623
|
side: "back",
|
|
3176
3624
|
onCapture: (imageData) => uploadDocument(imageData, "back", selectedCountry?.id),
|
|
3177
|
-
onCancel: handleCancel
|
|
3625
|
+
onCancel: handleCancel,
|
|
3626
|
+
showVisualGuides
|
|
3178
3627
|
}
|
|
3179
3628
|
),
|
|
3180
|
-
state.step === "selfie" && /* @__PURE__ */ (0,
|
|
3181
|
-
|
|
3629
|
+
state.step === "selfie" && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
3630
|
+
SelfieCaptureScreen,
|
|
3631
|
+
{
|
|
3632
|
+
onCapture: uploadSelfie,
|
|
3633
|
+
onCancel: handleCancel,
|
|
3634
|
+
showVisualGuides
|
|
3635
|
+
}
|
|
3636
|
+
),
|
|
3637
|
+
state.step === "liveness" && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
3182
3638
|
LivenessScreen,
|
|
3183
3639
|
{
|
|
3184
3640
|
session: state.livenessSession,
|
|
@@ -3187,20 +3643,13 @@ function VerificationFlow({
|
|
|
3187
3643
|
onChallengeComplete: submitChallenge,
|
|
3188
3644
|
onStart: startLiveness,
|
|
3189
3645
|
onComplete: complete,
|
|
3190
|
-
onCancel: handleCancel
|
|
3646
|
+
onCancel: handleCancel,
|
|
3647
|
+
lastChallengeError: state.lastChallengeError,
|
|
3648
|
+
showVisualGuides
|
|
3191
3649
|
}
|
|
3192
3650
|
),
|
|
3193
|
-
state.step === "processing" && /* @__PURE__ */ (0,
|
|
3194
|
-
|
|
3195
|
-
{
|
|
3196
|
-
steps: [
|
|
3197
|
-
{ label: "Document analyzed", status: "done" },
|
|
3198
|
-
{ label: "Checking face match", status: "active" },
|
|
3199
|
-
{ label: "Finalizing results", status: "pending" }
|
|
3200
|
-
]
|
|
3201
|
-
}
|
|
3202
|
-
),
|
|
3203
|
-
state.step === "complete" && state.verification && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
3651
|
+
state.step === "processing" && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ProcessingScreen, {}),
|
|
3652
|
+
state.step === "complete" && state.verification && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
3204
3653
|
ResultScreen,
|
|
3205
3654
|
{
|
|
3206
3655
|
verification: state.verification,
|
|
@@ -3212,8 +3661,8 @@ function VerificationFlow({
|
|
|
3212
3661
|
}
|
|
3213
3662
|
|
|
3214
3663
|
// src/components/QrHandoffScreen.tsx
|
|
3215
|
-
var
|
|
3216
|
-
var
|
|
3664
|
+
var import_react14 = require("react");
|
|
3665
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
3217
3666
|
function QrHandoffScreen({
|
|
3218
3667
|
session,
|
|
3219
3668
|
onMobileCaptureComplete,
|
|
@@ -3222,11 +3671,11 @@ function QrHandoffScreen({
|
|
|
3222
3671
|
onRefresh,
|
|
3223
3672
|
eventSource
|
|
3224
3673
|
}) {
|
|
3225
|
-
const [timeLeft, setTimeLeft] = (0,
|
|
3226
|
-
const [scanned, setScanned] = (0,
|
|
3227
|
-
const [expired, setExpired] = (0,
|
|
3228
|
-
const timerRef = (0,
|
|
3229
|
-
(0,
|
|
3674
|
+
const [timeLeft, setTimeLeft] = (0, import_react14.useState)(session.expiresIn);
|
|
3675
|
+
const [scanned, setScanned] = (0, import_react14.useState)(false);
|
|
3676
|
+
const [expired, setExpired] = (0, import_react14.useState)(false);
|
|
3677
|
+
const timerRef = (0, import_react14.useRef)();
|
|
3678
|
+
(0, import_react14.useEffect)(() => {
|
|
3230
3679
|
setTimeLeft(session.expiresIn);
|
|
3231
3680
|
setExpired(false);
|
|
3232
3681
|
setScanned(false);
|
|
@@ -3243,7 +3692,7 @@ function QrHandoffScreen({
|
|
|
3243
3692
|
}, 1e3);
|
|
3244
3693
|
return () => clearInterval(timerRef.current);
|
|
3245
3694
|
}, [session.token]);
|
|
3246
|
-
(0,
|
|
3695
|
+
(0, import_react14.useEffect)(() => {
|
|
3247
3696
|
if (!eventSource) return;
|
|
3248
3697
|
const handleStatus = (event) => {
|
|
3249
3698
|
try {
|
|
@@ -3269,34 +3718,34 @@ function QrHandoffScreen({
|
|
|
3269
3718
|
const seconds = timeLeft % 60;
|
|
3270
3719
|
const qrSize = 200;
|
|
3271
3720
|
if (expired) {
|
|
3272
|
-
return /* @__PURE__ */ (0,
|
|
3273
|
-
/* @__PURE__ */ (0,
|
|
3274
|
-
/* @__PURE__ */ (0,
|
|
3275
|
-
/* @__PURE__ */ (0,
|
|
3276
|
-
/* @__PURE__ */ (0,
|
|
3277
|
-
/* @__PURE__ */ (0,
|
|
3721
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: qrStyles.container, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { style: qrStyles.content, children: [
|
|
3722
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: qrStyles.expiredIcon, children: "\u23F1" }),
|
|
3723
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("h2", { style: qrStyles.title, children: "QR Code Expired" }),
|
|
3724
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { style: qrStyles.subtitle, children: "The QR code has expired. Generate a new one to continue." }),
|
|
3725
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("button", { style: qrStyles.primaryButton, onClick: onRefresh, children: "Generate New QR Code" }),
|
|
3726
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("button", { style: qrStyles.secondaryButton, onClick: onContinueOnDevice, children: "Continue on this device instead" })
|
|
3278
3727
|
] }) });
|
|
3279
3728
|
}
|
|
3280
3729
|
if (scanned) {
|
|
3281
|
-
return /* @__PURE__ */ (0,
|
|
3282
|
-
/* @__PURE__ */ (0,
|
|
3283
|
-
/* @__PURE__ */ (0,
|
|
3284
|
-
/* @__PURE__ */ (0,
|
|
3285
|
-
/* @__PURE__ */ (0,
|
|
3286
|
-
/* @__PURE__ */ (0,
|
|
3730
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: qrStyles.container, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { style: qrStyles.content, children: [
|
|
3731
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: qrStyles.spinnerContainer, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: qrStyles.spinner }) }),
|
|
3732
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("h2", { style: qrStyles.title, children: "Capturing on your phone..." }),
|
|
3733
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { style: qrStyles.subtitle, children: "Complete the document scan and selfie on your mobile device. This page will update automatically when done." }),
|
|
3734
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { style: qrStyles.statusBadge, children: [
|
|
3735
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { style: qrStyles.statusDot }),
|
|
3287
3736
|
"Connected \u2014 waiting for capture"
|
|
3288
3737
|
] })
|
|
3289
3738
|
] }) });
|
|
3290
3739
|
}
|
|
3291
|
-
return /* @__PURE__ */ (0,
|
|
3292
|
-
/* @__PURE__ */ (0,
|
|
3293
|
-
/* @__PURE__ */ (0,
|
|
3294
|
-
/* @__PURE__ */ (0,
|
|
3295
|
-
/* @__PURE__ */ (0,
|
|
3740
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: qrStyles.container, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { style: qrStyles.content, children: [
|
|
3741
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("h2", { style: qrStyles.title, children: "Scan with your phone" }),
|
|
3742
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { style: qrStyles.subtitle, children: "Use your phone's camera for a better capture experience. Scan the QR code below to continue on your mobile device." }),
|
|
3743
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { style: qrStyles.qrContainer, children: [
|
|
3744
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: {
|
|
3296
3745
|
...qrStyles.qrBox,
|
|
3297
3746
|
width: qrSize,
|
|
3298
3747
|
height: qrSize
|
|
3299
|
-
}, children: /* @__PURE__ */ (0,
|
|
3748
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
3300
3749
|
"img",
|
|
3301
3750
|
{
|
|
3302
3751
|
src: `https://api.qrserver.com/v1/create-qr-code/?size=${qrSize}x${qrSize}&data=${encodeURIComponent(session.captureUrl)}&margin=8`,
|
|
@@ -3306,26 +3755,26 @@ function QrHandoffScreen({
|
|
|
3306
3755
|
style: { borderRadius: 12 }
|
|
3307
3756
|
}
|
|
3308
3757
|
) }),
|
|
3309
|
-
/* @__PURE__ */ (0,
|
|
3758
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { style: qrStyles.timer, children: [
|
|
3310
3759
|
minutes,
|
|
3311
3760
|
":",
|
|
3312
3761
|
seconds.toString().padStart(2, "0"),
|
|
3313
3762
|
" remaining"
|
|
3314
3763
|
] })
|
|
3315
3764
|
] }),
|
|
3316
|
-
/* @__PURE__ */ (0,
|
|
3317
|
-
/* @__PURE__ */ (0,
|
|
3318
|
-
/* @__PURE__ */ (0,
|
|
3319
|
-
/* @__PURE__ */ (0,
|
|
3765
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { style: qrStyles.steps, children: [
|
|
3766
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Step, { number: 1, text: "Open your phone's camera" }),
|
|
3767
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Step, { number: 2, text: "Point at the QR code" }),
|
|
3768
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Step, { number: 3, text: "Complete the capture on your phone" })
|
|
3320
3769
|
] }),
|
|
3321
|
-
/* @__PURE__ */ (0,
|
|
3322
|
-
/* @__PURE__ */ (0,
|
|
3770
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: qrStyles.divider, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { style: qrStyles.dividerText, children: "or" }) }),
|
|
3771
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("button", { style: qrStyles.secondaryButton, onClick: onContinueOnDevice, children: "Continue on this device" })
|
|
3323
3772
|
] }) });
|
|
3324
3773
|
}
|
|
3325
3774
|
function Step({ number, text }) {
|
|
3326
|
-
return /* @__PURE__ */ (0,
|
|
3327
|
-
/* @__PURE__ */ (0,
|
|
3328
|
-
/* @__PURE__ */ (0,
|
|
3775
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { style: qrStyles.step, children: [
|
|
3776
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: qrStyles.stepNumber, children: number }),
|
|
3777
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { style: qrStyles.stepText, children: text })
|
|
3329
3778
|
] });
|
|
3330
3779
|
}
|
|
3331
3780
|
var qrStyles = {
|