UNPKG

@seontechnologies/seon-id-verification

Version:

An advanced SDK featuring web components for natural person identification through document scanning, facial recognition, hand gesture, and face turning detection, designed for secure and efficient user verification.

311 lines (310 loc) 17.5 kB
var Me = Object.defineProperty; var Te = (e, t, i) => t in e ? Me(e, t, { enumerable: !0, configurable: !0, writable: !0, value: i }) : e[t] = i; var xe = (e, t, i) => Te(e, typeof t != "symbol" ? t + "" : t, i); import { j as h, l as a, a as M, t as U } from "./index-oGnhSncZ.mjs"; import * as x from "react"; import { useState as A, useRef as ee, useMemo as He, useCallback as P, useEffect as ce } from "react"; import { C as Se, a as ye } from "./CameraCard-DCtEAYmX.mjs"; import { s as Pe, S as Ee, L as be, a as Ve } from "./UploadLivenessVideo-ia7J-Ak0.mjs"; import { M as Oe } from "./MediaPipeVideo-BLVUgMdB.mjs"; import { I as ke, a as Ie } from "./InitLivenessCheck-skpuLOln.mjs"; import { R as je } from "./RetryLimitHandler-Bj2Rrg3E.mjs"; const ze = (e) => /* @__PURE__ */ x.createElement("svg", { width: 57, height: 56, viewBox: "0 0 57 56", fill: "none", xmlns: "http://www.w3.org/2000/svg", ...e }, /* @__PURE__ */ x.createElement("path", { d: "M28.1973 48.188C28.9783 48.188 29.6623 47.895 30.2483 47.309L44.7993 32.856C45.0923 32.465 45.3853 31.977 45.3853 31.489C45.3853 30.415 44.4083 29.438 43.3343 29.438H33.6663C33.1783 29.438 32.8853 29.145 32.8853 28.657V9.906C32.8853 8.636 31.8113 7.562 30.5413 7.562H25.8533C24.4863 7.562 23.5093 8.636 23.5093 9.906V28.656C23.5093 29.144 23.1183 29.437 22.7283 29.437H12.9633C11.8893 29.437 11.0103 30.413 11.0103 31.488C11.0103 31.976 11.2053 32.464 11.4983 32.855L26.0493 47.308C26.6353 47.894 27.3183 48.188 28.1973 48.188ZM46.9473 31.488C46.9473 32.367 46.5563 33.343 45.8733 33.929L31.4203 48.48C30.5413 49.359 29.3693 49.847 28.1973 49.847C26.9273 49.847 25.7563 49.359 24.9743 48.48L10.4243 33.93C9.74027 33.344 9.44727 32.368 9.44727 31.489C9.44727 29.536 11.0093 27.876 12.9633 27.876H21.9473V9.906C21.9473 7.758 23.6073 6 25.8533 6H30.5413C32.6893 6 34.4473 7.758 34.4473 9.906V27.875H43.3343C45.2873 27.875 46.9473 29.535 46.9473 31.488Z", fill: "currentColor" })), Ue = (e) => /* @__PURE__ */ x.createElement("svg", { width: 57, height: 56, viewBox: "0 0 57 56", fill: "none", xmlns: "http://www.w3.org/2000/svg", ...e }, /* @__PURE__ */ x.createElement("path", { d: "M28.1973 7.563C27.3183 7.563 26.6353 7.954 26.0493 8.442L11.4983 22.992C11.2053 23.383 11.0103 23.871 11.0103 24.359C11.0103 25.433 11.8893 26.312 12.9633 26.312H22.7293C23.1203 26.312 23.5103 26.703 23.5103 27.093V45.843C23.5103 47.21 24.4873 48.187 25.8543 48.187H30.5423C31.8123 48.187 32.8863 47.21 32.8863 45.843V27.093C32.8863 26.702 33.1793 26.312 33.6673 26.312H43.3353C44.4093 26.312 45.3863 25.433 45.3863 24.359C45.3863 23.871 45.0933 23.382 44.8003 22.992L30.2483 8.441C29.6623 7.953 28.9783 7.563 28.1973 7.563ZM46.9473 24.359C46.9473 26.312 45.2873 27.875 43.3343 27.875H34.4473V45.844C34.4473 48.09 32.6893 49.75 30.5413 49.75H25.8533C23.6073 49.75 21.9473 48.09 21.9473 45.844V27.875H12.9633C11.0103 27.875 9.44727 26.313 9.44727 24.359C9.44727 23.48 9.74027 22.504 10.4243 21.918L24.9743 7.367C25.7553 6.488 26.9273 6 28.1973 6C29.3693 6 30.5413 6.488 31.4203 7.367L45.8733 21.82C46.5573 22.504 46.9473 23.48 46.9473 24.359Z", fill: "currentColor" })), Ne = (e) => /* @__PURE__ */ x.createElement("svg", { width: 57, height: 56, viewBox: "0 0 57 56", fill: "none", xmlns: "http://www.w3.org/2000/svg", ...e }, /* @__PURE__ */ x.createElement("path", { d: "M8.00927 27.75C8.00927 28.629 8.30227 29.312 8.88827 29.898L23.3413 44.449C23.7323 44.742 24.2203 44.937 24.7083 44.937C25.7823 44.937 26.7593 44.058 26.7593 42.984V33.218C26.7593 32.827 27.0523 32.437 27.5403 32.437H46.2903C47.5603 32.437 48.6343 31.46 48.6343 30.093V25.405C48.6343 24.135 47.5603 23.061 46.2903 23.061H27.5403C27.0523 23.061 26.7593 22.768 26.7593 22.28V12.613C26.7593 11.539 25.7823 10.562 24.7083 10.562C24.2203 10.562 23.7323 10.855 23.3413 11.148L8.88827 25.699C8.30227 26.285 8.00927 26.969 8.00927 27.75ZM24.7093 9C26.6623 9 28.3223 10.66 28.3223 12.613V21.5H46.2913C48.4393 21.5 50.1973 23.258 50.1973 25.406V30.094C50.1973 32.34 48.4393 34 46.2913 34H28.3223V42.984C28.3223 44.937 26.6623 46.5 24.7093 46.5C23.8303 46.5 22.8543 46.207 22.2683 45.523L7.71727 30.973C6.83827 30.192 6.44727 29.02 6.44727 27.75C6.44727 26.578 6.83827 25.406 7.71727 24.527L22.2673 10.074C22.8533 9.39 23.8303 9 24.7093 9Z", fill: "currentColor" })), Ze = (e) => /* @__PURE__ */ x.createElement("svg", { width: 57, height: 56, viewBox: "0 0 57 56", fill: "none", xmlns: "http://www.w3.org/2000/svg", ...e }, /* @__PURE__ */ x.createElement("path", { d: "M48.6353 27.75C48.6353 26.969 48.2443 26.188 47.7563 25.699L33.2053 11.148C32.8143 10.855 32.3263 10.562 31.8383 10.562C30.7643 10.562 29.8853 11.539 29.8853 12.613V22.281C29.8853 22.769 29.4943 23.062 29.1043 23.062H10.3533C8.98627 23.062 8.00927 24.136 8.00927 25.406V30.094C8.00927 31.461 8.98627 32.438 10.3533 32.438H29.1033C29.4943 32.438 29.8843 32.829 29.8843 33.219V42.985C29.8843 44.059 30.7633 44.938 31.8373 44.938C32.3253 44.938 32.8143 44.743 33.2043 44.45L47.7553 29.899C48.2433 29.313 48.6343 28.63 48.6343 27.751L48.6353 27.75ZM31.8383 46.5C29.8853 46.5 28.3223 44.938 28.3223 42.984V34H10.3533C8.10727 34 6.44727 32.34 6.44727 30.094V25.406C6.44727 23.258 8.10727 21.5 10.3533 21.5H28.2243V12.613C28.2243 10.66 29.8843 9 31.8373 9C32.7163 9 33.6923 9.391 34.2783 10.074L48.8293 24.527C49.7083 25.406 50.1963 26.578 50.1963 27.75C50.1963 29.019 49.7083 30.191 48.8293 30.973L34.3763 45.524C33.6923 46.208 32.7163 46.501 31.8373 46.501L31.8383 46.5Z", fill: "currentColor" })), Fe = (e) => e.map((t, i) => { let c = null; switch (t) { case "DOWN": c = h.jsx(ze, { width: 48, hanging: 48 }); break; case "LEFT": c = h.jsx(Ne, { width: 48, hanging: 48 }); break; case "RIGHT": c = h.jsx(Ze, { width: 48, hanging: 48 }); break; case "UP": c = h.jsx(Ue, { width: 48, hanging: 48 }); break; } const w = a[`liveness_check_action_turn_${t.toLowerCase()}${i === 0 ? "_first" : ""}`]; return { direction: t, instruction: { icon: c, text: w }, outline: "indicator", dimension: "interactive-face" }; }), De = () => { const e = navigator.userAgent || navigator.vendor || window.opera; return /iPad|iPhone|iPod/.test(e) && !window.MSStream ? "iOS" : /Android/.test(e) ? "Android" : "Desktop"; }; var d; (function(e) { e.UP = "up", e.DOWN = "down", e.LEFT = "left", e.RIGHT = "right"; })(d || (d = {})); const T = []; class We { constructor(t) { xe(this, "delegate"); this.delegate = t; } analyzeHeadMovement(t) { var g; if (t.length < 6) { (g = this.delegate) == null || g.didFailDetectingFaceRotation(); return; } const i = { x: t[4].x, y: t[4].y }, c = { x: t[5].x, y: t[5].y }, w = { x: t[2].x, y: t[2].y }, m = c.x - i.x, r = 0.18, R = { x: (i.x + c.x) / 2, y: (i.y + c.y) / 2 }, W = w.x - R.x, ie = w.y - R.y, B = W * (r / m), C = ie * (r / m) - 0.02; let F = 0.18, b = 0.07, V = 0.1; const H = De(); H === "iOS" ? (F = 0.13, b = 0.035, V = 0.02) : H === "Android" && (F = 0.2, b = 0.07, V = 0.06); const S = -C * (100 / b), q = C * (100 / V), y = -B * (100 / F), G = B * (100 / F), oe = [ y, G, S, q ]; setTimeout(() => { var l, O, $, J, K; const o = Math.max(...oe); o >= 30 ? o === S ? (this.pushPrevDetections(d.UP, Math.min(o, 100)), (l = this.delegate) == null || l.didDetectFaceRotation(d.UP, Math.min(o, 100))) : o === q ? (this.pushPrevDetections(d.DOWN, Math.min(o, 100)), (O = this.delegate) == null || O.didDetectFaceRotation(d.DOWN, Math.min(o, 100))) : o === y ? (this.pushPrevDetections(d.RIGHT, Math.min(o, 100)), ($ = this.delegate) == null || $.didDetectFaceRotation( d.RIGHT, //NOTE: Because of the camera mirroring, we call the LEFT callback for RIGHT turn Math.min(o, 100) )) : o === G && (this.pushPrevDetections(d.LEFT, Math.min(o, 100)), (J = this.delegate) == null || J.didDetectFaceRotation( d.LEFT, //NOTE: Because of the camera mirroring, we call the RIGHT callback for LEFT turn Math.min(o, 100) )) : ((K = this.delegate) == null || K.didDetectNeutralFacePosition(), this.pushPrevDetections("none", 0)); }, 0); } pushPrevDetections(t, i) { T.push({ direction: t, percentage: i }), T.length > 10 && T.shift(); } } let u = 0, N = 0, f = 0, Re = Fe(M.config.livenessCheckSettings.steps || []), Z = 0, te = -1, E = !1, v = []; const ne = new je("error_code_6", "liveness"), Be = () => { switch (De()) { case "iOS": return 20; case "Android": return 15; default: return 15; } }, tt = (e) => { var le, ue, me; const { onNext: t, onBack: i } = e, [c, w] = A(0), m = ee(null), r = ee(null), [R, W] = A(!1), [ie, B] = A(!1), [C, F] = A(!1), [b, V] = A(((le = M.config.livenessCheckSettings) == null ? void 0 : le.steps) || []), [H, S] = A(!1), [q, y] = A(1), G = He(() => M.config.promptLength, []), oe = 24, g = ee(new Array(((me = (ue = M.config.livenessCheckSettings) == null ? void 0 : ue.steps) == null ? void 0 : me.length) || 0).fill(0)), o = 1400, l = ee(!1), O = P(() => { const s = new ke(); s.fetchInitLivenessCheck().then(() => { s.getInitLivenessCheck().then((n) => { var ae; if (!(n != null && n.ok)) { U({ ERROR: n }); return; } v = (n == null ? void 0 : n.directions) || [], V((n == null ? void 0 : n.directions) || []), Re = Fe((n == null ? void 0 : n.directions) || []), g.current = new Array(((ae = n == null ? void 0 : n.directions) == null ? void 0 : ae.length) || 0).fill(0); }); }); }, []); ce(() => { M.config.livenessCheckSettings.steps || O(); }, [O]), ce(() => { const s = setTimeout(() => { C || (U({ logo: "general-error", title: a.error_timeout_title, description: a.error_timeout_description, btnText: a.restart_button, ERROR: { cause: "timeout", prevDetections: T }, btnAction() { ne.handleRetry(() => i()); } }), cancelAnimationFrame(f)); }, (M.config.livenessCheckSettings.recordingLength || 20) * 1e3); return () => { clearTimeout(s); }; }, [C, i]); const $ = P((s) => { F(s); }, []), J = P(() => { }, []), K = P(async () => { await Ie(r); }, []), k = P(async ({ capturedInRow: s, videoDetectedChunkStartingTime: n, isDurationCompleted: ae, mediaRecorder: I, capturedVideo: D, minFaceCapturedInRow: X, videoDurationS: Y, setIsRecordingStopped: j, uploadVideo: z }) => { var fe, he, de, Ce, ge; if (C) { cancelAnimationFrame(f); return; } if (!((fe = m.current) != null && fe.srcObject) || !r.current || !(r.current instanceof Pe) || l.current || !v || v.length === 0 || ((he = m.current) == null ? void 0 : he.videoWidth) === 0 || ((de = m.current) == null ? void 0 : de.videoHeight) === 0) { f = window.requestAnimationFrame(() => k({ capturedInRow: s, videoDetectedChunkStartingTime: n, isDurationCompleted: l, mediaRecorder: I, capturedVideo: D, minFaceCapturedInRow: X, videoDurationS: Y, setIsRecordingStopped: j, uploadVideo: z })); return; } const _e = m.current.currentTime * 1e3 - te * 1e3; if (m.current.currentTime !== te && _e >= Be()) { const Ae = performance.now(); let p = []; const we = 24; N === 0 && (N = (/* @__PURE__ */ new Date()).getTime()), te = m.current.currentTime, p = ((ge = (Ce = r.current) == null ? void 0 : Ce.detectForVideo(m.current, Ae).detections[0]) == null ? void 0 : ge.keypoints) || [], (p == null ? void 0 : p.length) > 5 && new We({ didDetectNeutralFacePosition: () => { if (y(1), Z > we && !R && (W(!0), w(1)), Z <= we) { Z = Z + 1, f = window.requestAnimationFrame(() => k({ capturedInRow: s, videoDetectedChunkStartingTime: n, isDurationCompleted: l, mediaRecorder: I, capturedVideo: D, minFaceCapturedInRow: X, videoDurationS: Y, setIsRecordingStopped: j, uploadVideo: z })); return; } }, didFailDetectingFaceRotation: () => { U({ logo: "general-error", title: a.error_unsuccessful_attempt_title, description: a.error_unsuccessful_attempt_description, btnText: a.restart_button, ERROR: { cause: "didFailDetectingFaceRotation", keypoints: p, rotationSeen: "no face", expected: "to see a face...", prevDetections: T }, btnAction() { var L; cancelAnimationFrame(f), (L = r.current) == null || L.close(), r.current = null, ne.handleRetry(() => i()); } }); }, didDetectFaceRotation: (L, _) => { if (l.current) { f = window.requestAnimationFrame(() => k({ capturedInRow: s, videoDetectedChunkStartingTime: n, isDurationCompleted: l, mediaRecorder: I, capturedVideo: D, minFaceCapturedInRow: X, videoDurationS: Y, setIsRecordingStopped: j, uploadVideo: z })); return; } L.toUpperCase() === v[u] ? (y(_), E = !0, g.current[u] === 0 && _ > 70 && (g.current[u] = (/* @__PURE__ */ new Date()).getTime() - N), _ === 100 && !l.current && (S(!0), l.current = !0, E = !1, setTimeout(async () => { var pe, ve; if (u < v.length - 1) u++, S(!1), w((se) => se + 1), l.current = !1, y(1); else { for (j(!0), I.stop(); (((pe = D.current) == null ? void 0 : pe.size) || 0) === 0; ) await new Promise((se) => setTimeout(se, 100)); (((ve = D.current) == null ? void 0 : ve.size) || 0) > 0 ? (z(D.current, g.current), cancelAnimationFrame(f)) : U({ logo: "general-error", title: a.error_unsuccessful_attempt_title, description: a.error_unsuccessful_attempt_description, btnText: a.restart_button, ERROR: { cause: "upload failed", keypoints: p, rotationSeen: L.toUpperCase(), expected: v[u], confidence: _, wasCorrectOnce: E, prevDetections: T }, btnAction() { cancelAnimationFrame(f), ne.handleRetry(() => i()); } }); } }, o))) : L.toUpperCase() !== v[u] && _ >= M.config.maxRotationError && E ? U({ logo: "general-error", title: a.error_unsuccessful_attempt_title, description: a.error_unsuccessful_attempt_description, btnText: a.restart_button, ERROR: { cause: "unknown", keypoints: p, rotationSeen: L.toUpperCase(), expected: v[u], confidence: _, wasCorrectOnce: E, prevDetections: T }, btnAction() { var re; cancelAnimationFrame(f), (re = r.current) == null || re.close(), r.current = null, ne.handleRetry(() => i()); } }) : _ === 0 && (g.current[u] = 0); } }).analyzeHeadMovement(p); } f = window.requestAnimationFrame(() => k({ capturedInRow: s, videoDetectedChunkStartingTime: n, isDurationCompleted: l, mediaRecorder: I, capturedVideo: D, minFaceCapturedInRow: X, videoDurationS: Y, setIsRecordingStopped: j, uploadVideo: z })); }, [R, C, i]), Q = [ { instruction: { icon: h.jsx(Ee, { width: 48, hanging: 48 }), text: a.liveness_check_action_position_face }, animateTo: { startAnimationTo: R, strokeDasharray: "0", strokeWidth: "4" }, outline: "idle", dimension: "interactive-face" }, ...Re ], Le = P(() => { W(!1), B(!1), F(!1), w(0), u = 0, N = 0, g.current = [], S(!1), window.cancelAnimationFrame(f); }, []); return ce(() => () => { var s; (s = r.current) == null || s.close(), r.current = null, u = 0, N = 0, Z = 0, te = -1, l.current = !1, E = !1, cancelAnimationFrame(f); }, []), h.jsxs(h.Fragment, { children: [h.jsx(Se, { className: `tw-w-full tw-h-full sm:tw-h-auto ${C && "tw-opacity-0"}`, children: h.jsx(ye, { idPrefix: "face-rotation-liveness-camera", onBack: i, title: a.liveness_check_selfie_flow_title, instructions: Q[u + (R ? 1 : 0)].instruction, hideInstructions: H, children: h.jsx(be, { dimension: Q[c].dimension, outline: Q[c].outline, startAnimation: ie && !H, animateTo: Q[c].animateTo, isSuccessful: H, faceRotationSetting: { direction: b[u], percentage: q }, children: h.jsx(Oe, { initializeDetector: K, videoRef: m, videoDurationS: G, minFaceCapturedInRow: oe, detectorRef: r, handleIsUploading: $, onNext: t, detectionLoop: k, handleAnimationSteps: J, resetStates: Le }) }) }) }), h.jsx(Ve, { isUploading: C })] }); }; export { tt as default };