@koraidv/react 1.7.11 → 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 +55 -6
- package/dist/index.d.ts +55 -6
- package/dist/index.js +819 -377
- package/dist/index.mjs +822 -380
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -96,7 +96,8 @@ 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);
|
|
@@ -295,14 +296,20 @@ function useKoraIDV() {
|
|
|
295
296
|
...prev,
|
|
296
297
|
completedChallenges: nextIndex,
|
|
297
298
|
currentChallenge: nextChallenge,
|
|
298
|
-
isLoading: false
|
|
299
|
+
isLoading: false,
|
|
300
|
+
// Clear any prior retake message — the user just succeeded.
|
|
301
|
+
lastChallengeError: null
|
|
299
302
|
}));
|
|
300
303
|
if (!nextChallenge) {
|
|
301
304
|
setState((prev) => ({ ...prev, step: "processing" }));
|
|
302
305
|
}
|
|
303
306
|
return true;
|
|
304
307
|
}
|
|
305
|
-
setState((prev) => ({
|
|
308
|
+
setState((prev) => ({
|
|
309
|
+
...prev,
|
|
310
|
+
isLoading: false,
|
|
311
|
+
lastChallengeError: retakeMessageForChallenge(currentChallenge.type)
|
|
312
|
+
}));
|
|
306
313
|
return false;
|
|
307
314
|
} catch (error) {
|
|
308
315
|
setState((prev) => ({
|
|
@@ -353,7 +360,8 @@ function useKoraIDV() {
|
|
|
353
360
|
currentChallenge: null,
|
|
354
361
|
completedChallenges: 0,
|
|
355
362
|
isLoading: false,
|
|
356
|
-
error: null
|
|
363
|
+
error: null,
|
|
364
|
+
lastChallengeError: null
|
|
357
365
|
});
|
|
358
366
|
}, [sdk]);
|
|
359
367
|
const retry = (0, import_react2.useCallback)(() => {
|
|
@@ -380,9 +388,27 @@ function useKoraIDV() {
|
|
|
380
388
|
sdk
|
|
381
389
|
};
|
|
382
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
|
+
}
|
|
383
409
|
|
|
384
410
|
// src/components/VerificationFlow.tsx
|
|
385
|
-
var
|
|
411
|
+
var import_react13 = require("react");
|
|
386
412
|
var import_core4 = require("@koraidv/core");
|
|
387
413
|
|
|
388
414
|
// src/components/styles.ts
|
|
@@ -449,6 +475,36 @@ function injectKeyframes() {
|
|
|
449
475
|
from { opacity: 0; transform: translateY(8px); }
|
|
450
476
|
to { opacity: 1; transform: translateY(0); }
|
|
451
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
|
+
}
|
|
452
508
|
`;
|
|
453
509
|
document.head.appendChild(style);
|
|
454
510
|
}
|
|
@@ -1435,10 +1491,26 @@ function ScoreMetricRow({ label, score, icon, status, message }) {
|
|
|
1435
1491
|
}
|
|
1436
1492
|
);
|
|
1437
1493
|
}
|
|
1438
|
-
|
|
1494
|
+
var DEFAULT_AUTO_STEPS = [
|
|
1495
|
+
"Document analyzed",
|
|
1496
|
+
"Checking face match",
|
|
1497
|
+
"Finalizing results"
|
|
1498
|
+
];
|
|
1499
|
+
function ProcessingScreen({ steps, autoAdvance = true }) {
|
|
1439
1500
|
(0, import_react3.useEffect)(() => {
|
|
1440
1501
|
injectKeyframes();
|
|
1441
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
|
+
}));
|
|
1442
1514
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles.processingContainer, children: [
|
|
1443
1515
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles.spinnerContainer, children: [
|
|
1444
1516
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
@@ -1489,7 +1561,7 @@ function ProcessingScreen({ steps }) {
|
|
|
1489
1561
|
}
|
|
1490
1562
|
)
|
|
1491
1563
|
] }),
|
|
1492
|
-
/* @__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: [
|
|
1493
1565
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1494
1566
|
"div",
|
|
1495
1567
|
{
|
|
@@ -1811,8 +1883,243 @@ function getIcon(type) {
|
|
|
1811
1883
|
}
|
|
1812
1884
|
|
|
1813
1885
|
// src/components/DocumentCaptureScreen.tsx
|
|
1886
|
+
var import_react7 = require("react");
|
|
1887
|
+
|
|
1888
|
+
// src/components/VisualGuides.tsx
|
|
1814
1889
|
var import_react5 = require("react");
|
|
1815
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");
|
|
1816
2123
|
var qualityIssueMessages = {
|
|
1817
2124
|
face_blurred: "Photo on document is blurry. Retake in better lighting.",
|
|
1818
2125
|
low_resolution: "Image quality too low. Move closer to document.",
|
|
@@ -1829,23 +2136,25 @@ function DocumentCaptureScreen({
|
|
|
1829
2136
|
requiresBack = true,
|
|
1830
2137
|
onQualityCheck,
|
|
1831
2138
|
onCapture,
|
|
1832
|
-
onCancel
|
|
2139
|
+
onCancel,
|
|
2140
|
+
showVisualGuides = true
|
|
1833
2141
|
}) {
|
|
1834
|
-
const videoRef = (0,
|
|
1835
|
-
const canvasRef = (0,
|
|
1836
|
-
const guideRef = (0,
|
|
1837
|
-
const [stream, setStream] = (0,
|
|
1838
|
-
const
|
|
1839
|
-
const [
|
|
1840
|
-
const [
|
|
1841
|
-
const [
|
|
1842
|
-
const [
|
|
1843
|
-
const [
|
|
1844
|
-
const [
|
|
1845
|
-
(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)(() => {
|
|
1846
2155
|
injectKeyframes();
|
|
1847
2156
|
}, []);
|
|
1848
|
-
(0,
|
|
2157
|
+
(0, import_react7.useEffect)(() => {
|
|
1849
2158
|
let mounted = true;
|
|
1850
2159
|
async function startCamera() {
|
|
1851
2160
|
try {
|
|
@@ -1867,12 +2176,12 @@ function DocumentCaptureScreen({
|
|
|
1867
2176
|
mounted = false;
|
|
1868
2177
|
};
|
|
1869
2178
|
}, [capturedImage]);
|
|
1870
|
-
(0,
|
|
2179
|
+
(0, import_react7.useEffect)(() => {
|
|
1871
2180
|
return () => {
|
|
1872
2181
|
stream?.getTracks().forEach((t) => t.stop());
|
|
1873
2182
|
};
|
|
1874
2183
|
}, [stream]);
|
|
1875
|
-
const handleCapture = (0,
|
|
2184
|
+
const handleCapture = (0, import_react7.useCallback)(() => {
|
|
1876
2185
|
if (!videoRef.current || !canvasRef.current || isCapturing) return;
|
|
1877
2186
|
setIsCapturing(true);
|
|
1878
2187
|
const video = videoRef.current;
|
|
@@ -1960,24 +2269,24 @@ function DocumentCaptureScreen({
|
|
|
1960
2269
|
}
|
|
1961
2270
|
};
|
|
1962
2271
|
if (error) {
|
|
1963
|
-
return /* @__PURE__ */ (0,
|
|
1964
|
-
/* @__PURE__ */ (0,
|
|
1965
|
-
/* @__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" })
|
|
1966
2275
|
] }) });
|
|
1967
2276
|
}
|
|
1968
2277
|
if (capturedImage) {
|
|
1969
2278
|
const qualityPassed = qualityResult && qualityResult.qualityScore >= 60;
|
|
1970
2279
|
const qualityFailed = qualityResult && qualityResult.qualityScore < 60;
|
|
1971
2280
|
const canContinueAnyway = qualityFailed && retakeCount >= 2;
|
|
1972
|
-
return /* @__PURE__ */ (0,
|
|
1973
|
-
/* @__PURE__ */ (0,
|
|
1974
|
-
/* @__PURE__ */ (0,
|
|
1975
|
-
/* @__PURE__ */ (0,
|
|
1976
|
-
/* @__PURE__ */ (0,
|
|
1977
|
-
/* @__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" })
|
|
1978
2287
|
] }),
|
|
1979
|
-
/* @__PURE__ */ (0,
|
|
1980
|
-
/* @__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)(
|
|
1981
2290
|
"img",
|
|
1982
2291
|
{
|
|
1983
2292
|
src: capturedImage,
|
|
@@ -1985,42 +2294,42 @@ function DocumentCaptureScreen({
|
|
|
1985
2294
|
style: { width: "100%", maxWidth: "300px", borderRadius: "16px", display: "block", margin: "0 auto" }
|
|
1986
2295
|
}
|
|
1987
2296
|
),
|
|
1988
|
-
isCheckingQuality && /* @__PURE__ */ (0,
|
|
1989
|
-
qualityPassed && /* @__PURE__ */ (0,
|
|
1990
|
-
/* @__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: [
|
|
1991
2300
|
"\u2713 Quality score: ",
|
|
1992
2301
|
Math.round(qualityResult.qualityScore),
|
|
1993
2302
|
"%"
|
|
1994
2303
|
] }) }),
|
|
1995
|
-
/* @__PURE__ */ (0,
|
|
1996
|
-
/* @__PURE__ */ (0,
|
|
1997
|
-
/* @__PURE__ */ (0,
|
|
1998
|
-
/* @__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" })
|
|
1999
2308
|
] })
|
|
2000
2309
|
] }),
|
|
2001
|
-
qualityFailed && /* @__PURE__ */ (0,
|
|
2002
|
-
/* @__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: [
|
|
2003
2312
|
"\u26A0 Quality score: ",
|
|
2004
2313
|
Math.round(qualityResult.qualityScore),
|
|
2005
2314
|
"%"
|
|
2006
2315
|
] }) }),
|
|
2007
|
-
/* @__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)) })
|
|
2008
2317
|
] }),
|
|
2009
|
-
!qualityResult && !isCheckingQuality && /* @__PURE__ */ (0,
|
|
2010
|
-
/* @__PURE__ */ (0,
|
|
2011
|
-
/* @__PURE__ */ (0,
|
|
2012
|
-
/* @__PURE__ */ (0,
|
|
2013
|
-
/* @__PURE__ */ (0,
|
|
2014
|
-
/* @__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" })
|
|
2015
2324
|
] })
|
|
2016
2325
|
] })
|
|
2017
2326
|
] }) }),
|
|
2018
|
-
/* @__PURE__ */ (0,
|
|
2019
|
-
/* @__PURE__ */ (0,
|
|
2020
|
-
canContinueAnyway && /* @__PURE__ */ (0,
|
|
2021
|
-
] }) : /* @__PURE__ */ (0,
|
|
2022
|
-
/* @__PURE__ */ (0,
|
|
2023
|
-
/* @__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)(
|
|
2024
2333
|
"button",
|
|
2025
2334
|
{
|
|
2026
2335
|
style: { ...styles.primaryButton, flex: 1, opacity: isCheckingQuality ? 0.5 : 1 },
|
|
@@ -2032,29 +2341,54 @@ function DocumentCaptureScreen({
|
|
|
2032
2341
|
] }) })
|
|
2033
2342
|
] });
|
|
2034
2343
|
}
|
|
2035
|
-
return /* @__PURE__ */ (0,
|
|
2036
|
-
/* @__PURE__ */ (0,
|
|
2037
|
-
/* @__PURE__ */ (0,
|
|
2038
|
-
/* @__PURE__ */ (0,
|
|
2039
|
-
/* @__PURE__ */ (0,
|
|
2040
|
-
/* @__PURE__ */ (0,
|
|
2041
|
-
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 })
|
|
2042
2351
|
] }),
|
|
2043
|
-
/* @__PURE__ */ (0,
|
|
2352
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { style: styles.glassCloseButton, onClick: onCancel, children: "\u2715" })
|
|
2044
2353
|
] }),
|
|
2045
|
-
/* @__PURE__ */ (0,
|
|
2046
|
-
|
|
2047
|
-
/* @__PURE__ */ (0,
|
|
2048
|
-
|
|
2049
|
-
/* @__PURE__ */ (0,
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
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" } })
|
|
2055
2389
|
] }),
|
|
2056
|
-
/* @__PURE__ */ (0,
|
|
2057
|
-
/* @__PURE__ */ (0,
|
|
2390
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: styles.stepPillsRow, children: [
|
|
2391
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
2058
2392
|
"span",
|
|
2059
2393
|
{
|
|
2060
2394
|
style: {
|
|
@@ -2065,7 +2399,7 @@ function DocumentCaptureScreen({
|
|
|
2065
2399
|
children: "Front"
|
|
2066
2400
|
}
|
|
2067
2401
|
),
|
|
2068
|
-
requiresBack && /* @__PURE__ */ (0,
|
|
2402
|
+
requiresBack && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
2069
2403
|
"span",
|
|
2070
2404
|
{
|
|
2071
2405
|
style: {
|
|
@@ -2077,7 +2411,7 @@ function DocumentCaptureScreen({
|
|
|
2077
2411
|
}
|
|
2078
2412
|
)
|
|
2079
2413
|
] }),
|
|
2080
|
-
/* @__PURE__ */ (0,
|
|
2414
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { textAlign: "center", padding: "8px 0" }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
2081
2415
|
"span",
|
|
2082
2416
|
{
|
|
2083
2417
|
style: {
|
|
@@ -2086,44 +2420,44 @@ function DocumentCaptureScreen({
|
|
|
2086
2420
|
color: colors.teal
|
|
2087
2421
|
},
|
|
2088
2422
|
children: [
|
|
2089
|
-
/* @__PURE__ */ (0,
|
|
2423
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: { ...styles.pulsingDot, backgroundColor: colors.teal } }),
|
|
2090
2424
|
"Scanning document..."
|
|
2091
2425
|
]
|
|
2092
2426
|
}
|
|
2093
2427
|
) }),
|
|
2094
|
-
/* @__PURE__ */ (0,
|
|
2428
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: styles.captureFooter, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
2095
2429
|
"button",
|
|
2096
2430
|
{
|
|
2097
2431
|
style: { ...styles.captureButton, opacity: isCapturing ? 0.5 : 1 },
|
|
2098
2432
|
onClick: handleCapture,
|
|
2099
2433
|
disabled: isCapturing,
|
|
2100
|
-
children: /* @__PURE__ */ (0,
|
|
2434
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: styles.captureButtonInner })
|
|
2101
2435
|
}
|
|
2102
2436
|
) })
|
|
2103
2437
|
] });
|
|
2104
2438
|
}
|
|
2105
2439
|
function QualityCheck({ label }) {
|
|
2106
|
-
return /* @__PURE__ */ (0,
|
|
2107
|
-
/* @__PURE__ */ (0,
|
|
2108
|
-
/* @__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 })
|
|
2109
2443
|
] });
|
|
2110
2444
|
}
|
|
2111
2445
|
|
|
2112
2446
|
// src/components/FlipDocumentScreen.tsx
|
|
2113
|
-
var
|
|
2114
|
-
var
|
|
2447
|
+
var import_react8 = require("react");
|
|
2448
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
2115
2449
|
function FlipDocumentScreen({ onContinue, onCancel }) {
|
|
2116
|
-
(0,
|
|
2450
|
+
(0, import_react8.useEffect)(() => {
|
|
2117
2451
|
injectKeyframes();
|
|
2118
2452
|
}, []);
|
|
2119
|
-
return /* @__PURE__ */ (0,
|
|
2120
|
-
/* @__PURE__ */ (0,
|
|
2121
|
-
/* @__PURE__ */ (0,
|
|
2122
|
-
/* @__PURE__ */ (0,
|
|
2123
|
-
/* @__PURE__ */ (0,
|
|
2124
|
-
/* @__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" })
|
|
2125
2459
|
] }),
|
|
2126
|
-
/* @__PURE__ */ (0,
|
|
2460
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: {
|
|
2127
2461
|
flex: 1,
|
|
2128
2462
|
display: "flex",
|
|
2129
2463
|
flexDirection: "column",
|
|
@@ -2132,7 +2466,7 @@ function FlipDocumentScreen({ onContinue, onCancel }) {
|
|
|
2132
2466
|
padding: "24px",
|
|
2133
2467
|
gap: "32px"
|
|
2134
2468
|
}, children: [
|
|
2135
|
-
/* @__PURE__ */ (0,
|
|
2469
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: {
|
|
2136
2470
|
width: "120px",
|
|
2137
2471
|
height: "120px",
|
|
2138
2472
|
borderRadius: "50%",
|
|
@@ -2140,18 +2474,18 @@ function FlipDocumentScreen({ onContinue, onCancel }) {
|
|
|
2140
2474
|
display: "flex",
|
|
2141
2475
|
alignItems: "center",
|
|
2142
2476
|
justifyContent: "center"
|
|
2143
|
-
}, children: /* @__PURE__ */ (0,
|
|
2144
|
-
/* @__PURE__ */ (0,
|
|
2145
|
-
/* @__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 })
|
|
2146
2480
|
] }) }),
|
|
2147
|
-
/* @__PURE__ */ (0,
|
|
2148
|
-
/* @__PURE__ */ (0,
|
|
2481
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { textAlign: "center" }, children: [
|
|
2482
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h2", { style: {
|
|
2149
2483
|
fontSize: "22px",
|
|
2150
2484
|
fontWeight: 700,
|
|
2151
2485
|
color: colors.white,
|
|
2152
2486
|
margin: "0 0 12px 0"
|
|
2153
2487
|
}, children: "Now capture the back" }),
|
|
2154
|
-
/* @__PURE__ */ (0,
|
|
2488
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { style: {
|
|
2155
2489
|
fontSize: "15px",
|
|
2156
2490
|
color: "rgba(255,255,255,0.6)",
|
|
2157
2491
|
margin: 0,
|
|
@@ -2159,38 +2493,38 @@ function FlipDocumentScreen({ onContinue, onCancel }) {
|
|
|
2159
2493
|
maxWidth: "280px"
|
|
2160
2494
|
}, children: "Turn your document over to the back side, then tap continue to take a photo." })
|
|
2161
2495
|
] }),
|
|
2162
|
-
/* @__PURE__ */ (0,
|
|
2163
|
-
/* @__PURE__ */ (0,
|
|
2496
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: styles.stepPillsRow, children: [
|
|
2497
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: {
|
|
2164
2498
|
...styles.stepPill,
|
|
2165
2499
|
backgroundColor: "rgba(16,185,129,0.15)",
|
|
2166
2500
|
color: colors.success
|
|
2167
2501
|
}, children: "\u2713 Front" }),
|
|
2168
|
-
/* @__PURE__ */ (0,
|
|
2502
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: {
|
|
2169
2503
|
...styles.stepPill,
|
|
2170
2504
|
backgroundColor: colors.teal,
|
|
2171
2505
|
color: colors.white
|
|
2172
2506
|
}, children: "Back" })
|
|
2173
2507
|
] })
|
|
2174
2508
|
] }),
|
|
2175
|
-
/* @__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" }) })
|
|
2176
2510
|
] });
|
|
2177
2511
|
}
|
|
2178
2512
|
|
|
2179
2513
|
// src/components/SelfieCaptureScreen.tsx
|
|
2180
|
-
var
|
|
2181
|
-
var
|
|
2182
|
-
function SelfieCaptureScreen({ onCapture, onCancel }) {
|
|
2183
|
-
const videoRef = (0,
|
|
2184
|
-
const canvasRef = (0,
|
|
2185
|
-
const [stream, setStream] = (0,
|
|
2186
|
-
const [isCapturing, setIsCapturing] = (0,
|
|
2187
|
-
const [error, setError] = (0,
|
|
2188
|
-
const [capturedImage, setCapturedImage] = (0,
|
|
2189
|
-
const [capturedBlob, setCapturedBlob] = (0,
|
|
2190
|
-
(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)(() => {
|
|
2191
2525
|
injectKeyframes();
|
|
2192
2526
|
}, []);
|
|
2193
|
-
(0,
|
|
2527
|
+
(0, import_react9.useEffect)(() => {
|
|
2194
2528
|
let mounted = true;
|
|
2195
2529
|
async function startCamera() {
|
|
2196
2530
|
try {
|
|
@@ -2212,12 +2546,12 @@ function SelfieCaptureScreen({ onCapture, onCancel }) {
|
|
|
2212
2546
|
mounted = false;
|
|
2213
2547
|
};
|
|
2214
2548
|
}, [capturedImage]);
|
|
2215
|
-
(0,
|
|
2549
|
+
(0, import_react9.useEffect)(() => {
|
|
2216
2550
|
return () => {
|
|
2217
2551
|
stream?.getTracks().forEach((t) => t.stop());
|
|
2218
2552
|
};
|
|
2219
2553
|
}, [stream]);
|
|
2220
|
-
const handleCapture = (0,
|
|
2554
|
+
const handleCapture = (0, import_react9.useCallback)(() => {
|
|
2221
2555
|
if (!videoRef.current || !canvasRef.current || isCapturing) return;
|
|
2222
2556
|
setIsCapturing(true);
|
|
2223
2557
|
const video = videoRef.current;
|
|
@@ -2256,22 +2590,22 @@ function SelfieCaptureScreen({ onCapture, onCancel }) {
|
|
|
2256
2590
|
}
|
|
2257
2591
|
};
|
|
2258
2592
|
if (error) {
|
|
2259
|
-
return /* @__PURE__ */ (0,
|
|
2260
|
-
/* @__PURE__ */ (0,
|
|
2261
|
-
/* @__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" })
|
|
2262
2596
|
] }) });
|
|
2263
2597
|
}
|
|
2264
2598
|
if (capturedImage) {
|
|
2265
|
-
return /* @__PURE__ */ (0,
|
|
2266
|
-
/* @__PURE__ */ (0,
|
|
2267
|
-
/* @__PURE__ */ (0,
|
|
2268
|
-
/* @__PURE__ */ (0,
|
|
2269
|
-
/* @__PURE__ */ (0,
|
|
2270
|
-
/* @__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" })
|
|
2271
2605
|
] }),
|
|
2272
|
-
/* @__PURE__ */ (0,
|
|
2273
|
-
/* @__PURE__ */ (0,
|
|
2274
|
-
/* @__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)(
|
|
2275
2609
|
"img",
|
|
2276
2610
|
{
|
|
2277
2611
|
src: capturedImage,
|
|
@@ -2279,31 +2613,32 @@ function SelfieCaptureScreen({ onCapture, onCancel }) {
|
|
|
2279
2613
|
style: { width: "100%", height: "100%", objectFit: "cover" }
|
|
2280
2614
|
}
|
|
2281
2615
|
) }),
|
|
2282
|
-
/* @__PURE__ */ (0,
|
|
2283
|
-
/* @__PURE__ */ (0,
|
|
2284
|
-
/* @__PURE__ */ (0,
|
|
2285
|
-
/* @__PURE__ */ (0,
|
|
2286
|
-
/* @__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" })
|
|
2287
2621
|
] })
|
|
2288
2622
|
] }) }),
|
|
2289
|
-
/* @__PURE__ */ (0,
|
|
2290
|
-
/* @__PURE__ */ (0,
|
|
2291
|
-
/* @__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" })
|
|
2292
2626
|
] })
|
|
2293
2627
|
] });
|
|
2294
2628
|
}
|
|
2295
|
-
return /* @__PURE__ */ (0,
|
|
2296
|
-
/* @__PURE__ */ (0,
|
|
2297
|
-
/* @__PURE__ */ (0,
|
|
2298
|
-
/* @__PURE__ */ (0,
|
|
2299
|
-
/* @__PURE__ */ (0,
|
|
2300
|
-
/* @__PURE__ */ (0,
|
|
2301
|
-
/* @__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" })
|
|
2302
2636
|
] }),
|
|
2303
|
-
/* @__PURE__ */ (0,
|
|
2637
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { style: styles.glassCloseButton, onClick: onCancel, children: "\u2715" })
|
|
2304
2638
|
] }),
|
|
2305
|
-
/* @__PURE__ */ (0,
|
|
2306
|
-
|
|
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)(
|
|
2307
2642
|
"video",
|
|
2308
2643
|
{
|
|
2309
2644
|
ref: videoRef,
|
|
@@ -2313,10 +2648,10 @@ function SelfieCaptureScreen({ onCapture, onCancel }) {
|
|
|
2313
2648
|
style: { ...styles.cameraVideo, transform: "scaleX(-1)" }
|
|
2314
2649
|
}
|
|
2315
2650
|
),
|
|
2316
|
-
/* @__PURE__ */ (0,
|
|
2317
|
-
/* @__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" } })
|
|
2318
2653
|
] }),
|
|
2319
|
-
/* @__PURE__ */ (0,
|
|
2654
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: { textAlign: "center", padding: "8px 0" }, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
2320
2655
|
"span",
|
|
2321
2656
|
{
|
|
2322
2657
|
style: {
|
|
@@ -2325,32 +2660,88 @@ function SelfieCaptureScreen({ onCapture, onCancel }) {
|
|
|
2325
2660
|
color: colors.teal
|
|
2326
2661
|
},
|
|
2327
2662
|
children: [
|
|
2328
|
-
/* @__PURE__ */ (0,
|
|
2663
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { style: { ...styles.pulsingDot, backgroundColor: colors.teal } }),
|
|
2329
2664
|
"Position your face in the oval"
|
|
2330
2665
|
]
|
|
2331
2666
|
}
|
|
2332
2667
|
) }),
|
|
2333
|
-
/* @__PURE__ */ (0,
|
|
2668
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: styles.captureFooter, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
2334
2669
|
"button",
|
|
2335
2670
|
{
|
|
2336
2671
|
style: { ...styles.captureButton, opacity: isCapturing ? 0.5 : 1 },
|
|
2337
2672
|
onClick: handleCapture,
|
|
2338
2673
|
disabled: isCapturing,
|
|
2339
|
-
children: /* @__PURE__ */ (0,
|
|
2674
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: styles.captureButtonInner })
|
|
2340
2675
|
}
|
|
2341
2676
|
) })
|
|
2342
2677
|
] });
|
|
2343
2678
|
}
|
|
2344
2679
|
function QualityCheck2({ label }) {
|
|
2345
|
-
return /* @__PURE__ */ (0,
|
|
2346
|
-
/* @__PURE__ */ (0,
|
|
2347
|
-
/* @__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 })
|
|
2348
2683
|
] });
|
|
2349
2684
|
}
|
|
2350
2685
|
|
|
2351
2686
|
// src/components/LivenessScreen.tsx
|
|
2352
|
-
var
|
|
2353
|
-
|
|
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");
|
|
2354
2745
|
function LivenessScreen({
|
|
2355
2746
|
session,
|
|
2356
2747
|
currentChallenge,
|
|
@@ -2358,22 +2749,25 @@ function LivenessScreen({
|
|
|
2358
2749
|
onChallengeComplete,
|
|
2359
2750
|
onStart,
|
|
2360
2751
|
onComplete,
|
|
2361
|
-
onCancel
|
|
2752
|
+
onCancel,
|
|
2753
|
+
lastChallengeError,
|
|
2754
|
+
showVisualGuides = true
|
|
2362
2755
|
}) {
|
|
2363
|
-
const videoRef = (0,
|
|
2364
|
-
const canvasRef = (0,
|
|
2365
|
-
const [stream, setStream] = (0,
|
|
2366
|
-
const
|
|
2367
|
-
const [
|
|
2368
|
-
const [
|
|
2369
|
-
const [
|
|
2370
|
-
(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)(() => {
|
|
2371
2765
|
injectKeyframes();
|
|
2372
2766
|
}, []);
|
|
2373
|
-
(0,
|
|
2767
|
+
(0, import_react11.useEffect)(() => {
|
|
2374
2768
|
if (!session) onStart();
|
|
2375
2769
|
}, [session, onStart]);
|
|
2376
|
-
(0,
|
|
2770
|
+
(0, import_react11.useEffect)(() => {
|
|
2377
2771
|
let mounted = true;
|
|
2378
2772
|
async function startCamera() {
|
|
2379
2773
|
try {
|
|
@@ -2405,17 +2799,17 @@ function LivenessScreen({
|
|
|
2405
2799
|
mounted = false;
|
|
2406
2800
|
};
|
|
2407
2801
|
}, []);
|
|
2408
|
-
(0,
|
|
2802
|
+
(0, import_react11.useEffect)(() => {
|
|
2409
2803
|
return () => {
|
|
2410
2804
|
stream?.getTracks().forEach((t) => t.stop());
|
|
2411
2805
|
};
|
|
2412
2806
|
}, [stream]);
|
|
2413
|
-
(0,
|
|
2807
|
+
(0, import_react11.useEffect)(() => {
|
|
2414
2808
|
if (!currentChallenge) return;
|
|
2415
2809
|
setPhase("preparing");
|
|
2416
2810
|
setCountdown(3);
|
|
2417
2811
|
}, [currentChallenge?.id]);
|
|
2418
|
-
const captureFrame = (0,
|
|
2812
|
+
const captureFrame = (0, import_react11.useCallback)(async () => {
|
|
2419
2813
|
if (!currentChallenge || !videoRef.current || !canvasRef.current || capturing) {
|
|
2420
2814
|
return;
|
|
2421
2815
|
}
|
|
@@ -2438,7 +2832,7 @@ function LivenessScreen({
|
|
|
2438
2832
|
0.85
|
|
2439
2833
|
);
|
|
2440
2834
|
}, [currentChallenge, capturing, onChallengeComplete]);
|
|
2441
|
-
(0,
|
|
2835
|
+
(0, import_react11.useEffect)(() => {
|
|
2442
2836
|
if (!currentChallenge || capturing) return;
|
|
2443
2837
|
if (countdown === 0) {
|
|
2444
2838
|
if (phase === "preparing") {
|
|
@@ -2452,32 +2846,32 @@ function LivenessScreen({
|
|
|
2452
2846
|
const t = setTimeout(() => setCountdown((c) => c - 1), 1e3);
|
|
2453
2847
|
return () => clearTimeout(t);
|
|
2454
2848
|
}, [countdown, currentChallenge?.id, capturing, captureFrame, phase]);
|
|
2455
|
-
(0,
|
|
2849
|
+
(0, import_react11.useEffect)(() => {
|
|
2456
2850
|
if (session && !currentChallenge && completedChallenges > 0) {
|
|
2457
2851
|
onComplete();
|
|
2458
2852
|
}
|
|
2459
2853
|
}, [session, currentChallenge, completedChallenges, onComplete]);
|
|
2460
2854
|
if (cameraError) {
|
|
2461
|
-
return /* @__PURE__ */ (0,
|
|
2462
|
-
/* @__PURE__ */ (0,
|
|
2463
|
-
/* @__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" })
|
|
2464
2858
|
] }) });
|
|
2465
2859
|
}
|
|
2466
2860
|
if (!session) {
|
|
2467
|
-
return /* @__PURE__ */ (0,
|
|
2468
|
-
/* @__PURE__ */ (0,
|
|
2469
|
-
/* @__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..." })
|
|
2470
2864
|
] }) });
|
|
2471
2865
|
}
|
|
2472
2866
|
const totalChallenges = session.challenges.length;
|
|
2473
|
-
return /* @__PURE__ */ (0,
|
|
2474
|
-
/* @__PURE__ */ (0,
|
|
2475
|
-
/* @__PURE__ */ (0,
|
|
2476
|
-
/* @__PURE__ */ (0,
|
|
2477
|
-
/* @__PURE__ */ (0,
|
|
2478
|
-
/* @__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" })
|
|
2479
2873
|
] }),
|
|
2480
|
-
/* @__PURE__ */ (0,
|
|
2874
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
2481
2875
|
"div",
|
|
2482
2876
|
{
|
|
2483
2877
|
style: {
|
|
@@ -2490,8 +2884,8 @@ function LivenessScreen({
|
|
|
2490
2884
|
padding: "16px 0"
|
|
2491
2885
|
},
|
|
2492
2886
|
children: [
|
|
2493
|
-
/* @__PURE__ */ (0,
|
|
2494
|
-
/* @__PURE__ */ (0,
|
|
2887
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: { position: "relative" }, children: [
|
|
2888
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2495
2889
|
"div",
|
|
2496
2890
|
{
|
|
2497
2891
|
style: {
|
|
@@ -2502,7 +2896,7 @@ function LivenessScreen({
|
|
|
2502
2896
|
backgroundColor: "#000",
|
|
2503
2897
|
border: "3px solid rgba(255,255,255,0.2)"
|
|
2504
2898
|
},
|
|
2505
|
-
children: /* @__PURE__ */ (0,
|
|
2899
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2506
2900
|
"video",
|
|
2507
2901
|
{
|
|
2508
2902
|
ref: videoRef,
|
|
@@ -2519,7 +2913,7 @@ function LivenessScreen({
|
|
|
2519
2913
|
)
|
|
2520
2914
|
}
|
|
2521
2915
|
),
|
|
2522
|
-
/* @__PURE__ */ (0,
|
|
2916
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2523
2917
|
"svg",
|
|
2524
2918
|
{
|
|
2525
2919
|
style: {
|
|
@@ -2531,7 +2925,7 @@ function LivenessScreen({
|
|
|
2531
2925
|
width: "256",
|
|
2532
2926
|
height: "316",
|
|
2533
2927
|
viewBox: "0 0 256 316",
|
|
2534
|
-
children: /* @__PURE__ */ (0,
|
|
2928
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2535
2929
|
"ellipse",
|
|
2536
2930
|
{
|
|
2537
2931
|
cx: "128",
|
|
@@ -2547,9 +2941,30 @@ function LivenessScreen({
|
|
|
2547
2941
|
}
|
|
2548
2942
|
)
|
|
2549
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
|
+
}
|
|
2550
2965
|
)
|
|
2551
2966
|
] }),
|
|
2552
|
-
currentChallenge && /* @__PURE__ */ (0,
|
|
2967
|
+
currentChallenge && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
2553
2968
|
"div",
|
|
2554
2969
|
{
|
|
2555
2970
|
style: {
|
|
@@ -2562,7 +2977,14 @@ function LivenessScreen({
|
|
|
2562
2977
|
transition: "background-color 200ms, border-color 200ms"
|
|
2563
2978
|
},
|
|
2564
2979
|
children: [
|
|
2565
|
-
/* @__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)(
|
|
2566
2988
|
"p",
|
|
2567
2989
|
{
|
|
2568
2990
|
style: {
|
|
@@ -2576,7 +2998,7 @@ function LivenessScreen({
|
|
|
2576
2998
|
children: capturing ? "Checking..." : phase === "preparing" ? "Get ready" : "Now \u2014 hold the pose"
|
|
2577
2999
|
}
|
|
2578
3000
|
),
|
|
2579
|
-
/* @__PURE__ */ (0,
|
|
3001
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2580
3002
|
"h2",
|
|
2581
3003
|
{
|
|
2582
3004
|
style: {
|
|
@@ -2587,7 +3009,7 @@ function LivenessScreen({
|
|
|
2587
3009
|
children: currentChallenge.instruction
|
|
2588
3010
|
}
|
|
2589
3011
|
),
|
|
2590
|
-
!capturing && /* @__PURE__ */ (0,
|
|
3012
|
+
!capturing && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2591
3013
|
"p",
|
|
2592
3014
|
{
|
|
2593
3015
|
style: {
|
|
@@ -2599,16 +3021,33 @@ function LivenessScreen({
|
|
|
2599
3021
|
},
|
|
2600
3022
|
children: countdown
|
|
2601
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
|
+
}
|
|
2602
3041
|
)
|
|
2603
3042
|
]
|
|
2604
3043
|
}
|
|
2605
3044
|
),
|
|
2606
|
-
/* @__PURE__ */ (0,
|
|
3045
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("canvas", { ref: canvasRef, style: { display: "none" } })
|
|
2607
3046
|
]
|
|
2608
3047
|
}
|
|
2609
3048
|
),
|
|
2610
|
-
/* @__PURE__ */ (0,
|
|
2611
|
-
/* @__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)(
|
|
2612
3051
|
"div",
|
|
2613
3052
|
{
|
|
2614
3053
|
style: {
|
|
@@ -2618,7 +3057,7 @@ function LivenessScreen({
|
|
|
2618
3057
|
},
|
|
2619
3058
|
index
|
|
2620
3059
|
)) }),
|
|
2621
|
-
/* @__PURE__ */ (0,
|
|
3060
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("p", { style: styles.progressText, children: [
|
|
2622
3061
|
"Challenge ",
|
|
2623
3062
|
Math.min(completedChallenges + 1, totalChallenges),
|
|
2624
3063
|
" of",
|
|
@@ -2626,7 +3065,7 @@ function LivenessScreen({
|
|
|
2626
3065
|
totalChallenges
|
|
2627
3066
|
] })
|
|
2628
3067
|
] }),
|
|
2629
|
-
/* @__PURE__ */ (0,
|
|
3068
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: { padding: "0 24px 24px", textAlign: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2630
3069
|
"p",
|
|
2631
3070
|
{
|
|
2632
3071
|
style: {
|
|
@@ -2641,35 +3080,35 @@ function LivenessScreen({
|
|
|
2641
3080
|
}
|
|
2642
3081
|
|
|
2643
3082
|
// src/components/ResultScreen.tsx
|
|
2644
|
-
var
|
|
3083
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
2645
3084
|
function ResultScreen({ verification, onDone, onRetry, resultPageMode, simplified, customMessages }) {
|
|
2646
3085
|
const { status } = verification;
|
|
2647
3086
|
const effectiveMode = resultPageMode ?? (simplified ? "simplified" : "detailed");
|
|
2648
3087
|
if (effectiveMode === "simplified") {
|
|
2649
3088
|
switch (status) {
|
|
2650
3089
|
case "approved":
|
|
2651
|
-
return /* @__PURE__ */ (0,
|
|
3090
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SimplifiedSuccess, { onDone, customMessages });
|
|
2652
3091
|
case "rejected":
|
|
2653
|
-
return /* @__PURE__ */ (0,
|
|
3092
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SimplifiedFailed, { onRetry: onRetry || onDone, customMessages });
|
|
2654
3093
|
case "review_required":
|
|
2655
|
-
return /* @__PURE__ */ (0,
|
|
3094
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SimplifiedReview, { verification, onDone, customMessages });
|
|
2656
3095
|
case "expired":
|
|
2657
|
-
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." } });
|
|
2658
3097
|
default:
|
|
2659
|
-
return /* @__PURE__ */ (0,
|
|
3098
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SimplifiedSuccess, { onDone, customMessages });
|
|
2660
3099
|
}
|
|
2661
3100
|
}
|
|
2662
3101
|
switch (status) {
|
|
2663
3102
|
case "approved":
|
|
2664
|
-
return /* @__PURE__ */ (0,
|
|
3103
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SuccessResult, { verification, onDone });
|
|
2665
3104
|
case "rejected":
|
|
2666
|
-
return /* @__PURE__ */ (0,
|
|
3105
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(RejectedResult, { verification, onRetry: onRetry || onDone });
|
|
2667
3106
|
case "expired":
|
|
2668
|
-
return /* @__PURE__ */ (0,
|
|
3107
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ExpiredResult, { verification, onRetry: onRetry || onDone });
|
|
2669
3108
|
case "review_required":
|
|
2670
|
-
return /* @__PURE__ */ (0,
|
|
3109
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ManualReviewResult, { verification, onDone });
|
|
2671
3110
|
default:
|
|
2672
|
-
return /* @__PURE__ */ (0,
|
|
3111
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SuccessResult, { verification, onDone });
|
|
2673
3112
|
}
|
|
2674
3113
|
}
|
|
2675
3114
|
function SuccessResult({ verification, onDone }) {
|
|
@@ -2677,16 +3116,16 @@ function SuccessResult({ verification, onDone }) {
|
|
|
2677
3116
|
verification.scores?.overall ?? 100 - (verification.riskScore ?? 16)
|
|
2678
3117
|
);
|
|
2679
3118
|
const metrics = computeScoreBreakdown(verification);
|
|
2680
|
-
return /* @__PURE__ */ (0,
|
|
2681
|
-
/* @__PURE__ */ (0,
|
|
2682
|
-
/* @__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)(
|
|
2683
3122
|
"div",
|
|
2684
3123
|
{
|
|
2685
3124
|
style: {
|
|
2686
3125
|
...styles.resultIconOuterRing,
|
|
2687
3126
|
backgroundColor: `${colors.success}15`
|
|
2688
3127
|
},
|
|
2689
|
-
children: /* @__PURE__ */ (0,
|
|
3128
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
2690
3129
|
"div",
|
|
2691
3130
|
{
|
|
2692
3131
|
style: {
|
|
@@ -2700,9 +3139,9 @@ function SuccessResult({ verification, onDone }) {
|
|
|
2700
3139
|
)
|
|
2701
3140
|
}
|
|
2702
3141
|
),
|
|
2703
|
-
/* @__PURE__ */ (0,
|
|
2704
|
-
/* @__PURE__ */ (0,
|
|
2705
|
-
/* @__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)(
|
|
2706
3145
|
ScoreCard,
|
|
2707
3146
|
{
|
|
2708
3147
|
score,
|
|
@@ -2710,9 +3149,9 @@ function SuccessResult({ verification, onDone }) {
|
|
|
2710
3149
|
gradient: `linear-gradient(135deg, ${colors.teal}, ${colors.tealDark})`
|
|
2711
3150
|
}
|
|
2712
3151
|
),
|
|
2713
|
-
metrics.map((m, i) => /* @__PURE__ */ (0,
|
|
3152
|
+
metrics.map((m, i) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ScoreMetricRow, { ...m }, i))
|
|
2714
3153
|
] }),
|
|
2715
|
-
/* @__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" }) })
|
|
2716
3155
|
] });
|
|
2717
3156
|
}
|
|
2718
3157
|
function RejectedResult({ verification, onRetry }) {
|
|
@@ -2720,16 +3159,16 @@ function RejectedResult({ verification, onRetry }) {
|
|
|
2720
3159
|
verification.scores?.overall ?? 100 - (verification.riskScore ?? 58)
|
|
2721
3160
|
);
|
|
2722
3161
|
const metrics = computeScoreBreakdown(verification);
|
|
2723
|
-
return /* @__PURE__ */ (0,
|
|
2724
|
-
/* @__PURE__ */ (0,
|
|
2725
|
-
/* @__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)(
|
|
2726
3165
|
"div",
|
|
2727
3166
|
{
|
|
2728
3167
|
style: {
|
|
2729
3168
|
...styles.resultIconOuterRing,
|
|
2730
3169
|
backgroundColor: `${colors.error}15`
|
|
2731
3170
|
},
|
|
2732
|
-
children: /* @__PURE__ */ (0,
|
|
3171
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
2733
3172
|
"div",
|
|
2734
3173
|
{
|
|
2735
3174
|
style: {
|
|
@@ -2743,9 +3182,9 @@ function RejectedResult({ verification, onRetry }) {
|
|
|
2743
3182
|
)
|
|
2744
3183
|
}
|
|
2745
3184
|
),
|
|
2746
|
-
/* @__PURE__ */ (0,
|
|
2747
|
-
/* @__PURE__ */ (0,
|
|
2748
|
-
/* @__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)(
|
|
2749
3188
|
ScoreCard,
|
|
2750
3189
|
{
|
|
2751
3190
|
score,
|
|
@@ -2753,15 +3192,15 @@ function RejectedResult({ verification, onRetry }) {
|
|
|
2753
3192
|
gradient: `linear-gradient(135deg, ${colors.error}, #B91C1C)`
|
|
2754
3193
|
}
|
|
2755
3194
|
),
|
|
2756
|
-
metrics.map((m, i) => /* @__PURE__ */ (0,
|
|
3195
|
+
metrics.map((m, i) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ScoreMetricRow, { ...m }, i))
|
|
2757
3196
|
] }),
|
|
2758
|
-
/* @__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" }) })
|
|
2759
3198
|
] });
|
|
2760
3199
|
}
|
|
2761
3200
|
function ExpiredResult({ verification, onRetry }) {
|
|
2762
|
-
return /* @__PURE__ */ (0,
|
|
2763
|
-
/* @__PURE__ */ (0,
|
|
2764
|
-
/* @__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)(
|
|
2765
3204
|
"div",
|
|
2766
3205
|
{
|
|
2767
3206
|
style: {
|
|
@@ -2769,7 +3208,7 @@ function ExpiredResult({ verification, onRetry }) {
|
|
|
2769
3208
|
backgroundColor: `${colors.warning}15`,
|
|
2770
3209
|
border: `2px solid ${colors.warning}30`
|
|
2771
3210
|
},
|
|
2772
|
-
children: /* @__PURE__ */ (0,
|
|
3211
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
2773
3212
|
"div",
|
|
2774
3213
|
{
|
|
2775
3214
|
style: {
|
|
@@ -2783,29 +3222,29 @@ function ExpiredResult({ verification, onRetry }) {
|
|
|
2783
3222
|
)
|
|
2784
3223
|
}
|
|
2785
3224
|
),
|
|
2786
|
-
/* @__PURE__ */ (0,
|
|
2787
|
-
/* @__PURE__ */ (0,
|
|
2788
|
-
verification.documentVerification && /* @__PURE__ */ (0,
|
|
2789
|
-
/* @__PURE__ */ (0,
|
|
2790
|
-
/* @__PURE__ */ (0,
|
|
2791
|
-
/* @__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" })
|
|
2792
3231
|
] }),
|
|
2793
|
-
verification.documentVerification.issuingCountry && /* @__PURE__ */ (0,
|
|
2794
|
-
/* @__PURE__ */ (0,
|
|
2795
|
-
/* @__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 })
|
|
2796
3235
|
] }),
|
|
2797
|
-
verification.documentVerification.expirationDate && /* @__PURE__ */ (0,
|
|
2798
|
-
/* @__PURE__ */ (0,
|
|
2799
|
-
/* @__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 })
|
|
2800
3239
|
] })
|
|
2801
3240
|
] }),
|
|
2802
|
-
/* @__PURE__ */ (0,
|
|
2803
|
-
/* @__PURE__ */ (0,
|
|
2804
|
-
/* @__PURE__ */ (0,
|
|
2805
|
-
/* @__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" })
|
|
2806
3245
|
] })
|
|
2807
3246
|
] }),
|
|
2808
|
-
/* @__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" }) })
|
|
2809
3248
|
] });
|
|
2810
3249
|
}
|
|
2811
3250
|
function ManualReviewResult({ verification, onDone }) {
|
|
@@ -2813,9 +3252,9 @@ function ManualReviewResult({ verification, onDone }) {
|
|
|
2813
3252
|
verification.scores?.overall ?? 100 - (verification.riskScore ?? 32)
|
|
2814
3253
|
);
|
|
2815
3254
|
const metrics = computeScoreBreakdown(verification);
|
|
2816
|
-
return /* @__PURE__ */ (0,
|
|
2817
|
-
/* @__PURE__ */ (0,
|
|
2818
|
-
/* @__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)(
|
|
2819
3258
|
"div",
|
|
2820
3259
|
{
|
|
2821
3260
|
style: {
|
|
@@ -2823,7 +3262,7 @@ function ManualReviewResult({ verification, onDone }) {
|
|
|
2823
3262
|
backgroundColor: `${colors.info}15`,
|
|
2824
3263
|
border: `2px solid ${colors.info}30`
|
|
2825
3264
|
},
|
|
2826
|
-
children: /* @__PURE__ */ (0,
|
|
3265
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
2827
3266
|
"div",
|
|
2828
3267
|
{
|
|
2829
3268
|
style: {
|
|
@@ -2837,9 +3276,9 @@ function ManualReviewResult({ verification, onDone }) {
|
|
|
2837
3276
|
)
|
|
2838
3277
|
}
|
|
2839
3278
|
),
|
|
2840
|
-
/* @__PURE__ */ (0,
|
|
2841
|
-
/* @__PURE__ */ (0,
|
|
2842
|
-
/* @__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)(
|
|
2843
3282
|
ScoreCard,
|
|
2844
3283
|
{
|
|
2845
3284
|
score,
|
|
@@ -2847,21 +3286,21 @@ function ManualReviewResult({ verification, onDone }) {
|
|
|
2847
3286
|
gradient: `linear-gradient(135deg, ${colors.info}, #0369A1)`
|
|
2848
3287
|
}
|
|
2849
3288
|
),
|
|
2850
|
-
metrics.map((m, i) => /* @__PURE__ */ (0,
|
|
3289
|
+
metrics.map((m, i) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(ScoreMetricRow, { ...m }, i))
|
|
2851
3290
|
] }),
|
|
2852
|
-
/* @__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" }) })
|
|
2853
3292
|
] });
|
|
2854
3293
|
}
|
|
2855
3294
|
function GuidanceTip({ number, text }) {
|
|
2856
|
-
return /* @__PURE__ */ (0,
|
|
2857
|
-
/* @__PURE__ */ (0,
|
|
2858
|
-
/* @__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 })
|
|
2859
3298
|
] });
|
|
2860
3299
|
}
|
|
2861
3300
|
function SimplifiedSuccess({ onDone, customMessages }) {
|
|
2862
|
-
return /* @__PURE__ */ (0,
|
|
2863
|
-
/* @__PURE__ */ (0,
|
|
2864
|
-
/* @__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)(
|
|
2865
3304
|
"div",
|
|
2866
3305
|
{
|
|
2867
3306
|
style: {
|
|
@@ -2870,7 +3309,7 @@ function SimplifiedSuccess({ onDone, customMessages }) {
|
|
|
2870
3309
|
width: 96,
|
|
2871
3310
|
height: 96
|
|
2872
3311
|
},
|
|
2873
|
-
children: /* @__PURE__ */ (0,
|
|
3312
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
2874
3313
|
"div",
|
|
2875
3314
|
{
|
|
2876
3315
|
style: {
|
|
@@ -2887,16 +3326,16 @@ function SimplifiedSuccess({ onDone, customMessages }) {
|
|
|
2887
3326
|
)
|
|
2888
3327
|
}
|
|
2889
3328
|
),
|
|
2890
|
-
/* @__PURE__ */ (0,
|
|
2891
|
-
/* @__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." })
|
|
2892
3331
|
] }),
|
|
2893
|
-
/* @__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" }) })
|
|
2894
3333
|
] });
|
|
2895
3334
|
}
|
|
2896
3335
|
function SimplifiedFailed({ onRetry, customMessages }) {
|
|
2897
|
-
return /* @__PURE__ */ (0,
|
|
2898
|
-
/* @__PURE__ */ (0,
|
|
2899
|
-
/* @__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)(
|
|
2900
3339
|
"div",
|
|
2901
3340
|
{
|
|
2902
3341
|
style: {
|
|
@@ -2905,7 +3344,7 @@ function SimplifiedFailed({ onRetry, customMessages }) {
|
|
|
2905
3344
|
width: 96,
|
|
2906
3345
|
height: 96
|
|
2907
3346
|
},
|
|
2908
|
-
children: /* @__PURE__ */ (0,
|
|
3347
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
2909
3348
|
"div",
|
|
2910
3349
|
{
|
|
2911
3350
|
style: {
|
|
@@ -2922,16 +3361,16 @@ function SimplifiedFailed({ onRetry, customMessages }) {
|
|
|
2922
3361
|
)
|
|
2923
3362
|
}
|
|
2924
3363
|
),
|
|
2925
|
-
/* @__PURE__ */ (0,
|
|
2926
|
-
/* @__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." })
|
|
2927
3366
|
] }),
|
|
2928
|
-
/* @__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" }) })
|
|
2929
3368
|
] });
|
|
2930
3369
|
}
|
|
2931
3370
|
function SimplifiedReview({ verification, onDone, customMessages }) {
|
|
2932
|
-
return /* @__PURE__ */ (0,
|
|
2933
|
-
/* @__PURE__ */ (0,
|
|
2934
|
-
/* @__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)(
|
|
2935
3374
|
"div",
|
|
2936
3375
|
{
|
|
2937
3376
|
style: {
|
|
@@ -2940,7 +3379,7 @@ function SimplifiedReview({ verification, onDone, customMessages }) {
|
|
|
2940
3379
|
width: 96,
|
|
2941
3380
|
height: 96
|
|
2942
3381
|
},
|
|
2943
|
-
children: /* @__PURE__ */ (0,
|
|
3382
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
2944
3383
|
"div",
|
|
2945
3384
|
{
|
|
2946
3385
|
style: {
|
|
@@ -2957,9 +3396,9 @@ function SimplifiedReview({ verification, onDone, customMessages }) {
|
|
|
2957
3396
|
)
|
|
2958
3397
|
}
|
|
2959
3398
|
),
|
|
2960
|
-
/* @__PURE__ */ (0,
|
|
2961
|
-
/* @__PURE__ */ (0,
|
|
2962
|
-
/* @__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: {
|
|
2963
3402
|
marginTop: 24,
|
|
2964
3403
|
padding: "12px 24px",
|
|
2965
3404
|
backgroundColor: `${colors.info}10`,
|
|
@@ -2967,27 +3406,27 @@ function SimplifiedReview({ verification, onDone, customMessages }) {
|
|
|
2967
3406
|
border: `1px solid ${colors.info}30`,
|
|
2968
3407
|
display: "inline-block"
|
|
2969
3408
|
}, children: [
|
|
2970
|
-
/* @__PURE__ */ (0,
|
|
2971
|
-
/* @__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) })
|
|
2972
3411
|
] })
|
|
2973
3412
|
] }),
|
|
2974
|
-
/* @__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" }) })
|
|
2975
3414
|
] });
|
|
2976
3415
|
}
|
|
2977
3416
|
|
|
2978
3417
|
// src/components/ErrorScreen.tsx
|
|
2979
|
-
var
|
|
3418
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
2980
3419
|
function ErrorScreen({ error, onRetry, onCancel }) {
|
|
2981
|
-
return /* @__PURE__ */ (0,
|
|
2982
|
-
/* @__PURE__ */ (0,
|
|
2983
|
-
/* @__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)(
|
|
2984
3423
|
"div",
|
|
2985
3424
|
{
|
|
2986
3425
|
style: {
|
|
2987
3426
|
...styles.resultIconOuterRing,
|
|
2988
3427
|
backgroundColor: colors.errorBg
|
|
2989
3428
|
},
|
|
2990
|
-
children: /* @__PURE__ */ (0,
|
|
3429
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2991
3430
|
"div",
|
|
2992
3431
|
{
|
|
2993
3432
|
style: {
|
|
@@ -3001,26 +3440,26 @@ function ErrorScreen({ error, onRetry, onCancel }) {
|
|
|
3001
3440
|
)
|
|
3002
3441
|
}
|
|
3003
3442
|
),
|
|
3004
|
-
/* @__PURE__ */ (0,
|
|
3005
|
-
/* @__PURE__ */ (0,
|
|
3006
|
-
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 })
|
|
3007
3446
|
] }),
|
|
3008
|
-
/* @__PURE__ */ (0,
|
|
3009
|
-
error.isRetryable && /* @__PURE__ */ (0,
|
|
3010
|
-
/* @__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" })
|
|
3011
3450
|
] })
|
|
3012
3451
|
] });
|
|
3013
3452
|
}
|
|
3014
3453
|
|
|
3015
3454
|
// src/components/LoadingScreen.tsx
|
|
3016
|
-
var
|
|
3017
|
-
var
|
|
3455
|
+
var import_react12 = require("react");
|
|
3456
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
3018
3457
|
function LoadingScreen({ message = "Loading..." }) {
|
|
3019
|
-
(0,
|
|
3458
|
+
(0, import_react12.useEffect)(() => {
|
|
3020
3459
|
injectKeyframes();
|
|
3021
3460
|
}, []);
|
|
3022
|
-
return /* @__PURE__ */ (0,
|
|
3023
|
-
/* @__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)(
|
|
3024
3463
|
"div",
|
|
3025
3464
|
{
|
|
3026
3465
|
style: {
|
|
@@ -3037,18 +3476,19 @@ function LoadingScreen({ message = "Loading..." }) {
|
|
|
3037
3476
|
children: "\u{1F6E1}\uFE0F"
|
|
3038
3477
|
}
|
|
3039
3478
|
),
|
|
3040
|
-
/* @__PURE__ */ (0,
|
|
3479
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { style: styles.loadingText, children: message })
|
|
3041
3480
|
] }) });
|
|
3042
3481
|
}
|
|
3043
3482
|
|
|
3044
3483
|
// src/components/VerificationFlow.tsx
|
|
3045
|
-
var
|
|
3484
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
3046
3485
|
function VerificationFlow({
|
|
3047
3486
|
externalId,
|
|
3048
3487
|
tier = "standard",
|
|
3049
3488
|
documentTypes,
|
|
3050
3489
|
expectedFirstName,
|
|
3051
3490
|
expectedLastName,
|
|
3491
|
+
showVisualGuides = true,
|
|
3052
3492
|
onComplete,
|
|
3053
3493
|
onError,
|
|
3054
3494
|
onCancel,
|
|
@@ -3070,20 +3510,20 @@ function VerificationFlow({
|
|
|
3070
3510
|
retry,
|
|
3071
3511
|
sdk
|
|
3072
3512
|
} = useKoraIDV();
|
|
3073
|
-
const [selectedCountry, setSelectedCountry] = (0,
|
|
3074
|
-
const [flowStep, setFlowStep] = (0,
|
|
3075
|
-
const [showFlipInstruction, setShowFlipInstruction] = (0,
|
|
3076
|
-
const [supportedCountries, setSupportedCountries] = (0,
|
|
3077
|
-
const [countriesLoading, setCountriesLoading] = (0,
|
|
3078
|
-
(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)(() => {
|
|
3079
3519
|
if (state.step === "document_front") {
|
|
3080
3520
|
setShowFlipInstruction(true);
|
|
3081
3521
|
}
|
|
3082
3522
|
}, [state.step]);
|
|
3083
|
-
(0,
|
|
3523
|
+
(0, import_react13.useEffect)(() => {
|
|
3084
3524
|
startVerification(externalId, tier, expectedFirstName, expectedLastName);
|
|
3085
3525
|
}, [externalId, tier, expectedFirstName, expectedLastName, startVerification]);
|
|
3086
|
-
(0,
|
|
3526
|
+
(0, import_react13.useEffect)(() => {
|
|
3087
3527
|
if (state.error && onError) {
|
|
3088
3528
|
onError(state.error);
|
|
3089
3529
|
}
|
|
@@ -3129,19 +3569,19 @@ function VerificationFlow({
|
|
|
3129
3569
|
...style
|
|
3130
3570
|
};
|
|
3131
3571
|
if (state.error) {
|
|
3132
|
-
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 }) });
|
|
3133
3573
|
}
|
|
3134
3574
|
if (state.isLoading && state.step !== "processing") {
|
|
3135
|
-
return /* @__PURE__ */ (0,
|
|
3575
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className, style: containerStyle, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(LoadingScreen, {}) });
|
|
3136
3576
|
}
|
|
3137
3577
|
if (flowStep === "consent" && state.step === "consent") {
|
|
3138
|
-
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 }) });
|
|
3139
3579
|
}
|
|
3140
3580
|
if (flowStep === "country_selection") {
|
|
3141
3581
|
if (countriesLoading) {
|
|
3142
|
-
return /* @__PURE__ */ (0,
|
|
3582
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className, style: containerStyle, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(LoadingScreen, {}) });
|
|
3143
3583
|
}
|
|
3144
|
-
return /* @__PURE__ */ (0,
|
|
3584
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className, style: containerStyle, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
3145
3585
|
CountrySelectionScreen,
|
|
3146
3586
|
{
|
|
3147
3587
|
countries: supportedCountries,
|
|
@@ -3150,8 +3590,8 @@ function VerificationFlow({
|
|
|
3150
3590
|
}
|
|
3151
3591
|
) });
|
|
3152
3592
|
}
|
|
3153
|
-
return /* @__PURE__ */ (0,
|
|
3154
|
-
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)(
|
|
3155
3595
|
DocumentSelectionScreen,
|
|
3156
3596
|
{
|
|
3157
3597
|
documentTypes,
|
|
@@ -3160,32 +3600,41 @@ function VerificationFlow({
|
|
|
3160
3600
|
onCancel: handleCancel
|
|
3161
3601
|
}
|
|
3162
3602
|
),
|
|
3163
|
-
state.step === "document_front" && /* @__PURE__ */ (0,
|
|
3603
|
+
state.step === "document_front" && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
3164
3604
|
DocumentCaptureScreen,
|
|
3165
3605
|
{
|
|
3166
3606
|
side: "front",
|
|
3167
3607
|
onQualityCheck: (blob) => checkDocumentQuality(blob),
|
|
3168
3608
|
onCapture: (imageData) => uploadDocument(imageData, "front", selectedCountry?.id),
|
|
3169
|
-
onCancel: handleCancel
|
|
3609
|
+
onCancel: handleCancel,
|
|
3610
|
+
showVisualGuides
|
|
3170
3611
|
}
|
|
3171
3612
|
),
|
|
3172
|
-
state.step === "document_back" && showFlipInstruction && /* @__PURE__ */ (0,
|
|
3613
|
+
state.step === "document_back" && showFlipInstruction && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
3173
3614
|
FlipDocumentScreen,
|
|
3174
3615
|
{
|
|
3175
3616
|
onContinue: () => setShowFlipInstruction(false),
|
|
3176
3617
|
onCancel: handleCancel
|
|
3177
3618
|
}
|
|
3178
3619
|
),
|
|
3179
|
-
state.step === "document_back" && !showFlipInstruction && /* @__PURE__ */ (0,
|
|
3620
|
+
state.step === "document_back" && !showFlipInstruction && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
3180
3621
|
DocumentCaptureScreen,
|
|
3181
3622
|
{
|
|
3182
3623
|
side: "back",
|
|
3183
3624
|
onCapture: (imageData) => uploadDocument(imageData, "back", selectedCountry?.id),
|
|
3184
|
-
onCancel: handleCancel
|
|
3625
|
+
onCancel: handleCancel,
|
|
3626
|
+
showVisualGuides
|
|
3185
3627
|
}
|
|
3186
3628
|
),
|
|
3187
|
-
state.step === "selfie" && /* @__PURE__ */ (0,
|
|
3188
|
-
|
|
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)(
|
|
3189
3638
|
LivenessScreen,
|
|
3190
3639
|
{
|
|
3191
3640
|
session: state.livenessSession,
|
|
@@ -3194,20 +3643,13 @@ function VerificationFlow({
|
|
|
3194
3643
|
onChallengeComplete: submitChallenge,
|
|
3195
3644
|
onStart: startLiveness,
|
|
3196
3645
|
onComplete: complete,
|
|
3197
|
-
onCancel: handleCancel
|
|
3646
|
+
onCancel: handleCancel,
|
|
3647
|
+
lastChallengeError: state.lastChallengeError,
|
|
3648
|
+
showVisualGuides
|
|
3198
3649
|
}
|
|
3199
3650
|
),
|
|
3200
|
-
state.step === "processing" && /* @__PURE__ */ (0,
|
|
3201
|
-
|
|
3202
|
-
{
|
|
3203
|
-
steps: [
|
|
3204
|
-
{ label: "Document analyzed", status: "done" },
|
|
3205
|
-
{ label: "Checking face match", status: "active" },
|
|
3206
|
-
{ label: "Finalizing results", status: "pending" }
|
|
3207
|
-
]
|
|
3208
|
-
}
|
|
3209
|
-
),
|
|
3210
|
-
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)(
|
|
3211
3653
|
ResultScreen,
|
|
3212
3654
|
{
|
|
3213
3655
|
verification: state.verification,
|
|
@@ -3219,8 +3661,8 @@ function VerificationFlow({
|
|
|
3219
3661
|
}
|
|
3220
3662
|
|
|
3221
3663
|
// src/components/QrHandoffScreen.tsx
|
|
3222
|
-
var
|
|
3223
|
-
var
|
|
3664
|
+
var import_react14 = require("react");
|
|
3665
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
3224
3666
|
function QrHandoffScreen({
|
|
3225
3667
|
session,
|
|
3226
3668
|
onMobileCaptureComplete,
|
|
@@ -3229,11 +3671,11 @@ function QrHandoffScreen({
|
|
|
3229
3671
|
onRefresh,
|
|
3230
3672
|
eventSource
|
|
3231
3673
|
}) {
|
|
3232
|
-
const [timeLeft, setTimeLeft] = (0,
|
|
3233
|
-
const [scanned, setScanned] = (0,
|
|
3234
|
-
const [expired, setExpired] = (0,
|
|
3235
|
-
const timerRef = (0,
|
|
3236
|
-
(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)(() => {
|
|
3237
3679
|
setTimeLeft(session.expiresIn);
|
|
3238
3680
|
setExpired(false);
|
|
3239
3681
|
setScanned(false);
|
|
@@ -3250,7 +3692,7 @@ function QrHandoffScreen({
|
|
|
3250
3692
|
}, 1e3);
|
|
3251
3693
|
return () => clearInterval(timerRef.current);
|
|
3252
3694
|
}, [session.token]);
|
|
3253
|
-
(0,
|
|
3695
|
+
(0, import_react14.useEffect)(() => {
|
|
3254
3696
|
if (!eventSource) return;
|
|
3255
3697
|
const handleStatus = (event) => {
|
|
3256
3698
|
try {
|
|
@@ -3276,34 +3718,34 @@ function QrHandoffScreen({
|
|
|
3276
3718
|
const seconds = timeLeft % 60;
|
|
3277
3719
|
const qrSize = 200;
|
|
3278
3720
|
if (expired) {
|
|
3279
|
-
return /* @__PURE__ */ (0,
|
|
3280
|
-
/* @__PURE__ */ (0,
|
|
3281
|
-
/* @__PURE__ */ (0,
|
|
3282
|
-
/* @__PURE__ */ (0,
|
|
3283
|
-
/* @__PURE__ */ (0,
|
|
3284
|
-
/* @__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" })
|
|
3285
3727
|
] }) });
|
|
3286
3728
|
}
|
|
3287
3729
|
if (scanned) {
|
|
3288
|
-
return /* @__PURE__ */ (0,
|
|
3289
|
-
/* @__PURE__ */ (0,
|
|
3290
|
-
/* @__PURE__ */ (0,
|
|
3291
|
-
/* @__PURE__ */ (0,
|
|
3292
|
-
/* @__PURE__ */ (0,
|
|
3293
|
-
/* @__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 }),
|
|
3294
3736
|
"Connected \u2014 waiting for capture"
|
|
3295
3737
|
] })
|
|
3296
3738
|
] }) });
|
|
3297
3739
|
}
|
|
3298
|
-
return /* @__PURE__ */ (0,
|
|
3299
|
-
/* @__PURE__ */ (0,
|
|
3300
|
-
/* @__PURE__ */ (0,
|
|
3301
|
-
/* @__PURE__ */ (0,
|
|
3302
|
-
/* @__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: {
|
|
3303
3745
|
...qrStyles.qrBox,
|
|
3304
3746
|
width: qrSize,
|
|
3305
3747
|
height: qrSize
|
|
3306
|
-
}, children: /* @__PURE__ */ (0,
|
|
3748
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
3307
3749
|
"img",
|
|
3308
3750
|
{
|
|
3309
3751
|
src: `https://api.qrserver.com/v1/create-qr-code/?size=${qrSize}x${qrSize}&data=${encodeURIComponent(session.captureUrl)}&margin=8`,
|
|
@@ -3313,26 +3755,26 @@ function QrHandoffScreen({
|
|
|
3313
3755
|
style: { borderRadius: 12 }
|
|
3314
3756
|
}
|
|
3315
3757
|
) }),
|
|
3316
|
-
/* @__PURE__ */ (0,
|
|
3758
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { style: qrStyles.timer, children: [
|
|
3317
3759
|
minutes,
|
|
3318
3760
|
":",
|
|
3319
3761
|
seconds.toString().padStart(2, "0"),
|
|
3320
3762
|
" remaining"
|
|
3321
3763
|
] })
|
|
3322
3764
|
] }),
|
|
3323
|
-
/* @__PURE__ */ (0,
|
|
3324
|
-
/* @__PURE__ */ (0,
|
|
3325
|
-
/* @__PURE__ */ (0,
|
|
3326
|
-
/* @__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" })
|
|
3327
3769
|
] }),
|
|
3328
|
-
/* @__PURE__ */ (0,
|
|
3329
|
-
/* @__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" })
|
|
3330
3772
|
] }) });
|
|
3331
3773
|
}
|
|
3332
3774
|
function Step({ number, text }) {
|
|
3333
|
-
return /* @__PURE__ */ (0,
|
|
3334
|
-
/* @__PURE__ */ (0,
|
|
3335
|
-
/* @__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 })
|
|
3336
3778
|
] });
|
|
3337
3779
|
}
|
|
3338
3780
|
var qrStyles = {
|