@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.
734 lines (733 loc) • 27.4 kB
JavaScript
var De = (t) => {
throw TypeError(t);
};
var le = (t, e, s) => e.has(t) || De("Cannot " + s);
var r = (t, e, s) => (le(t, e, "read from private field"), s ? s.call(t) : e.get(t)), _ = (t, e, s) => e.has(t) ? De("Cannot add the same private member more than once") : e instanceof WeakSet ? e.add(t) : e.set(t, s), v = (t, e, s, n) => (le(t, e, "write to private field"), n ? n.call(t, s) : e.set(t, s), s), x = (t, e, s) => (le(t, e, "access private method"), s);
import { f as Be, p as Ie, r as V, s as fe, g as ce, n as pe, h as me, k as Me, m as Xe, o as Ye, q as Ge, u as Fe, v as ze, w as Ke, x as Je, y as Ze, z as et, t as Qe, A as tt, C as st, j as P, D as rt, a as Ce, l as j } from "./index-oGnhSncZ.mjs";
import { C as nt, a as it } from "./CameraCard-DCtEAYmX.mjs";
import { s as Te, X as ot, E as at, I as ct, U as lt, S as ut, L as ht, a as Le } from "./UploadLivenessVideo-ia7J-Ak0.mjs";
import * as q from "react";
import { useRef as U, useState as Y, useEffect as Z, useCallback as B, useMemo as dt } from "react";
import { S as ft } from "./SelectInput-D_egVIuA.mjs";
var T, u, oe, D, G, ee, N, H, ae, te, se, K, J, W, re, m, ie, ye, ge, ve, be, we, xe, Re, je, $e, pt = ($e = class extends Be {
constructor(e, s) {
super();
_(this, m);
_(this, T);
_(this, u);
_(this, oe);
_(this, D);
_(this, G);
_(this, ee);
_(this, N);
_(this, H);
_(this, ae);
_(this, te);
// This property keeps track of the last query with defined data.
// It will be used to pass the previous data and query to the placeholder function between renders.
_(this, se);
_(this, K);
_(this, J);
_(this, W);
_(this, re, /* @__PURE__ */ new Set());
this.options = s, v(this, T, e), v(this, H, null), v(this, N, Ie()), this.options.experimental_prefetchInRender || r(this, N).reject(
new Error("experimental_prefetchInRender feature flag is not enabled")
), this.bindMethods(), this.setOptions(s);
}
bindMethods() {
this.refetch = this.refetch.bind(this);
}
onSubscribe() {
this.listeners.size === 1 && (r(this, u).addObserver(this), Pe(r(this, u), this.options) ? x(this, m, ie).call(this) : this.updateResult(), x(this, m, be).call(this));
}
onUnsubscribe() {
this.hasListeners() || this.destroy();
}
shouldFetchOnReconnect() {
return Oe(
r(this, u),
this.options,
this.options.refetchOnReconnect
);
}
shouldFetchOnWindowFocus() {
return Oe(
r(this, u),
this.options,
this.options.refetchOnWindowFocus
);
}
destroy() {
this.listeners = /* @__PURE__ */ new Set(), x(this, m, we).call(this), x(this, m, xe).call(this), r(this, u).removeObserver(this);
}
setOptions(e) {
const s = this.options, n = r(this, u);
if (this.options = r(this, T).defaultQueryOptions(e), this.options.enabled !== void 0 && typeof this.options.enabled != "boolean" && typeof this.options.enabled != "function" && typeof V(this.options.enabled, r(this, u)) != "boolean")
throw new Error(
"Expected enabled to be a boolean or a callback that returns a boolean"
);
x(this, m, Re).call(this), r(this, u).setOptions(this.options), s._defaulted && !fe(this.options, s) && r(this, T).getQueryCache().notify({
type: "observerOptionsUpdated",
query: r(this, u),
observer: this
});
const o = this.hasListeners();
o && Ue(
r(this, u),
n,
this.options,
s
) && x(this, m, ie).call(this), this.updateResult(), o && (r(this, u) !== n || V(this.options.enabled, r(this, u)) !== V(s.enabled, r(this, u)) || ce(this.options.staleTime, r(this, u)) !== ce(s.staleTime, r(this, u))) && x(this, m, ye).call(this);
const i = x(this, m, ge).call(this);
o && (r(this, u) !== n || V(this.options.enabled, r(this, u)) !== V(s.enabled, r(this, u)) || i !== r(this, W)) && x(this, m, ve).call(this, i);
}
getOptimisticResult(e) {
const s = r(this, T).getQueryCache().build(r(this, T), e), n = this.createResult(s, e);
return yt(this, n) && (v(this, D, n), v(this, ee, this.options), v(this, G, r(this, u).state)), n;
}
getCurrentResult() {
return r(this, D);
}
trackResult(e, s) {
return new Proxy(e, {
get: (n, o) => (this.trackProp(o), s == null || s(o), Reflect.get(n, o))
});
}
trackProp(e) {
r(this, re).add(e);
}
getCurrentQuery() {
return r(this, u);
}
refetch({ ...e } = {}) {
return this.fetch({
...e
});
}
fetchOptimistic(e) {
const s = r(this, T).defaultQueryOptions(e), n = r(this, T).getQueryCache().build(r(this, T), s);
return n.fetch().then(() => this.createResult(n, s));
}
fetch(e) {
return x(this, m, ie).call(this, {
...e,
cancelRefetch: e.cancelRefetch ?? !0
}).then(() => (this.updateResult(), r(this, D)));
}
createResult(e, s) {
var ne;
const n = r(this, u), o = this.options, i = r(this, D), a = r(this, G), p = r(this, ee), h = e !== n ? e.state : r(this, oe), { state: b } = e;
let c = { ...b }, S = !1, d;
if (s._optimisticResults) {
const O = this.hasListeners(), A = !O && Pe(e, s), z = O && Ue(e, n, s, o);
(A || z) && (c = {
...c,
...Ge(b.data, e.options)
}), s._optimisticResults === "isRestoring" && (c.fetchStatus = "idle");
}
let { error: C, errorUpdatedAt: w, status: f } = c;
d = c.data;
let I = !1;
if (s.placeholderData !== void 0 && d === void 0 && f === "pending") {
let O;
i != null && i.isPlaceholderData && s.placeholderData === (p == null ? void 0 : p.placeholderData) ? (O = i.data, I = !0) : O = typeof s.placeholderData == "function" ? s.placeholderData(
(ne = r(this, se)) == null ? void 0 : ne.state.data,
r(this, se)
) : s.placeholderData, O !== void 0 && (f = "success", d = Fe(
i == null ? void 0 : i.data,
O,
s
), S = !0);
}
if (s.select && d !== void 0 && !I)
if (i && d === (a == null ? void 0 : a.data) && s.select === r(this, ae))
d = r(this, te);
else
try {
v(this, ae, s.select), d = s.select(d), d = Fe(i == null ? void 0 : i.data, d, s), v(this, te, d), v(this, H, null);
} catch (O) {
v(this, H, O);
}
r(this, H) && (C = r(this, H), d = r(this, te), w = Date.now(), f = "error");
const y = c.fetchStatus === "fetching", M = f === "pending", k = f === "error", g = M && y, F = d !== void 0, L = {
status: f,
fetchStatus: c.fetchStatus,
isPending: M,
isSuccess: f === "success",
isError: k,
isInitialLoading: g,
isLoading: g,
data: d,
dataUpdatedAt: c.dataUpdatedAt,
error: C,
errorUpdatedAt: w,
failureCount: c.fetchFailureCount,
failureReason: c.fetchFailureReason,
errorUpdateCount: c.errorUpdateCount,
isFetched: c.dataUpdateCount > 0 || c.errorUpdateCount > 0,
isFetchedAfterMount: c.dataUpdateCount > h.dataUpdateCount || c.errorUpdateCount > h.errorUpdateCount,
isFetching: y,
isRefetching: y && !M,
isLoadingError: k && !F,
isPaused: c.fetchStatus === "paused",
isPlaceholderData: S,
isRefetchError: k && F,
isStale: Ee(e, s),
refetch: this.refetch,
promise: r(this, N)
};
if (this.options.experimental_prefetchInRender) {
const O = (X) => {
L.status === "error" ? X.reject(L.error) : L.data !== void 0 && X.resolve(L.data);
}, A = () => {
const X = v(this, N, L.promise = Ie());
O(X);
}, z = r(this, N);
switch (z.status) {
case "pending":
e.queryHash === n.queryHash && O(z);
break;
case "fulfilled":
(L.status === "error" || L.data !== z.value) && A();
break;
case "rejected":
(L.status !== "error" || L.error !== z.reason) && A();
break;
}
}
return L;
}
updateResult() {
const e = r(this, D), s = this.createResult(r(this, u), this.options);
if (v(this, G, r(this, u).state), v(this, ee, this.options), r(this, G).data !== void 0 && v(this, se, r(this, u)), fe(s, e))
return;
v(this, D, s);
const n = () => {
if (!e)
return !0;
const { notifyOnChangeProps: o } = this.options, i = typeof o == "function" ? o() : o;
if (i === "all" || !i && !r(this, re).size)
return !0;
const a = new Set(
i ?? r(this, re)
);
return this.options.throwOnError && a.add("error"), Object.keys(r(this, D)).some((p) => {
const l = p;
return r(this, D)[l] !== e[l] && a.has(l);
});
};
x(this, m, je).call(this, { listeners: n() });
}
onQueryUpdate() {
this.updateResult(), this.hasListeners() && x(this, m, be).call(this);
}
}, T = new WeakMap(), u = new WeakMap(), oe = new WeakMap(), D = new WeakMap(), G = new WeakMap(), ee = new WeakMap(), N = new WeakMap(), H = new WeakMap(), ae = new WeakMap(), te = new WeakMap(), se = new WeakMap(), K = new WeakMap(), J = new WeakMap(), W = new WeakMap(), re = new WeakMap(), m = new WeakSet(), ie = function(e) {
x(this, m, Re).call(this);
let s = r(this, u).fetch(
this.options,
e
);
return e != null && e.throwOnError || (s = s.catch(pe)), s;
}, ye = function() {
x(this, m, we).call(this);
const e = ce(
this.options.staleTime,
r(this, u)
);
if (me || r(this, D).isStale || !Me(e))
return;
const n = Xe(r(this, D).dataUpdatedAt, e) + 1;
v(this, K, setTimeout(() => {
r(this, D).isStale || this.updateResult();
}, n));
}, ge = function() {
return (typeof this.options.refetchInterval == "function" ? this.options.refetchInterval(r(this, u)) : this.options.refetchInterval) ?? !1;
}, ve = function(e) {
x(this, m, xe).call(this), v(this, W, e), !(me || V(this.options.enabled, r(this, u)) === !1 || !Me(r(this, W)) || r(this, W) === 0) && v(this, J, setInterval(() => {
(this.options.refetchIntervalInBackground || Ye.isFocused()) && x(this, m, ie).call(this);
}, r(this, W)));
}, be = function() {
x(this, m, ye).call(this), x(this, m, ve).call(this, x(this, m, ge).call(this));
}, we = function() {
r(this, K) && (clearTimeout(r(this, K)), v(this, K, void 0));
}, xe = function() {
r(this, J) && (clearInterval(r(this, J)), v(this, J, void 0));
}, Re = function() {
const e = r(this, T).getQueryCache().build(r(this, T), this.options);
if (e === r(this, u))
return;
const s = r(this, u);
v(this, u, e), v(this, oe, e.state), this.hasListeners() && (s == null || s.removeObserver(this), e.addObserver(this));
}, je = function(e) {
ze.batch(() => {
e.listeners && this.listeners.forEach((s) => {
s(r(this, D));
}), r(this, T).getQueryCache().notify({
query: r(this, u),
type: "observerResultsUpdated"
});
});
}, $e);
function mt(t, e) {
return V(e.enabled, t) !== !1 && t.state.data === void 0 && !(t.state.status === "error" && e.retryOnMount === !1);
}
function Pe(t, e) {
return mt(t, e) || t.state.data !== void 0 && Oe(t, e, e.refetchOnMount);
}
function Oe(t, e, s) {
if (V(e.enabled, t) !== !1) {
const n = typeof s == "function" ? s(t) : s;
return n === "always" || n !== !1 && Ee(t, e);
}
return !1;
}
function Ue(t, e, s, n) {
return (t !== e || V(n.enabled, t) === !1) && (!s.suspense || t.state.status !== "error") && Ee(t, s);
}
function Ee(t, e) {
return V(e.enabled, t) !== !1 && t.isStaleByTime(ce(e.staleTime, t));
}
function yt(t, e) {
return !fe(t.getCurrentResult(), e);
}
var qe = q.createContext(!1), gt = () => q.useContext(qe);
qe.Provider;
function vt() {
let t = !1;
return {
clearReset: () => {
t = !1;
},
reset: () => {
t = !0;
},
isReset: () => t
};
}
var bt = q.createContext(vt()), wt = () => q.useContext(bt), xt = (t, e) => {
(t.suspense || t.throwOnError || t.experimental_prefetchInRender) && (e.isReset() || (t.retryOnMount = !1));
}, Rt = (t) => {
q.useEffect(() => {
t.clearReset();
}, [t]);
}, Ot = ({
result: t,
errorResetBoundary: e,
throwOnError: s,
query: n,
suspense: o
}) => t.isError && !e.isReset() && !t.isFetching && n && (o && t.data === void 0 || Ke(s, [t.error, n])), Ct = (t) => {
const e = t.staleTime;
t.suspense && (t.staleTime = typeof e == "function" ? (...s) => Math.max(e(...s), 1e3) : Math.max(e ?? 1e3, 1e3), typeof t.gcTime == "number" && (t.gcTime = Math.max(t.gcTime, 1e3)));
}, Et = (t, e) => t.isLoading && t.isFetching && !e, _t = (t, e) => (t == null ? void 0 : t.suspense) && e.isPending, Ae = (t, e, s) => e.fetchOptimistic(t).catch(() => {
s.clearReset();
});
function St(t, e, s) {
var c, S, d, C, w;
if (process.env.NODE_ENV !== "production" && (typeof t != "object" || Array.isArray(t)))
throw new Error(
'Bad argument type. Starting with v5, only the "Object" form is allowed when calling query related functions. Please use the error stack to find the culprit call. More info here: https://tanstack.com/query/latest/docs/react/guides/migrating-to-v5#supports-a-single-signature-one-object'
);
const n = Je(), o = gt(), i = wt(), a = n.defaultQueryOptions(t);
(S = (c = n.getDefaultOptions().queries) == null ? void 0 : c._experimental_beforeQuery) == null || S.call(
c,
a
), process.env.NODE_ENV !== "production" && (a.queryFn || console.error(
`[${a.queryHash}]: No queryFn was passed as an option, and no default queryFn was found. The queryFn parameter is only optional when using a default queryFn. More info here: https://tanstack.com/query/latest/docs/framework/react/guides/default-query-function`
)), a._optimisticResults = o ? "isRestoring" : "optimistic", Ct(a), xt(a, i), Rt(i);
const p = !n.getQueryCache().get(a.queryHash), [l] = q.useState(
() => new e(
n,
a
)
), h = l.getOptimisticResult(a), b = !o && t.subscribed !== !1;
if (q.useSyncExternalStore(
q.useCallback(
(f) => {
const I = b ? l.subscribe(ze.batchCalls(f)) : pe;
return l.updateResult(), I;
},
[l, b]
),
() => l.getCurrentResult(),
() => l.getCurrentResult()
), q.useEffect(() => {
l.setOptions(a);
}, [a, l]), _t(a, h))
throw Ae(a, l, i);
if (Ot({
result: h,
errorResetBoundary: i,
throwOnError: a.throwOnError,
query: n.getQueryCache().get(a.queryHash),
suspense: a.suspense
}))
throw h.error;
if ((C = (d = n.getDefaultOptions().queries) == null ? void 0 : d._experimental_afterQuery) == null || C.call(
d,
a,
h
), a.experimental_prefetchInRender && !me && Et(h, o)) {
const f = p ? (
// Fetch immediately on render in order to ensure `.promise` is resolved even if the component is unmounted
Ae(a, l, i)
) : (
// subscribe to the "cache promise" so that we can finalize the currentThenable once data comes in
(w = n.getQueryCache().get(a.queryHash)) == null ? void 0 : w.promise
);
f == null || f.catch(pe).finally(() => {
l.updateResult();
});
}
return a.notifyOnChangeProps ? h : l.trackResult(h);
}
function kt(t, e) {
return St(t, pt);
}
const Dt = async () => (await rt()).map((s) => ({
value: s.deviceId,
text: s.label
})), It = ({ onDataLoaded: t }) => {
const e = U(null), [s, n] = Y(null), [o, i] = Y(null), { data: a, error: p } = kt({
queryKey: ["cameraList"],
initialData: [],
queryFn: Dt
}), l = U(!1);
Z(() => {
if (s)
return () => {
s.getTracks().forEach((c) => {
c.stop();
}), Ze();
};
}, [s]), Z(() => {
}, [p]);
const h = B(async (c) => {
if (!et()) {
Qe({ ERROR: "Camera access denied" });
return;
}
l.current = !0;
const S = {
video: {
deviceId: {
exact: c || (await tt()).deviceId
}
}
};
navigator.mediaDevices.getUserMedia(S).then(async (d) => {
if (!o)
return;
const C = await st(d);
n(C.stream), o.srcObject = C.stream;
}).catch((d) => {
console.error(d);
});
}, [o]);
Z(() => {
if (!o) {
l.current = !1;
return;
}
l.current || h();
const c = () => {
t == null || t();
};
return o.addEventListener("loadeddata", c), () => {
o.removeEventListener("loadeddata", c);
};
}, [h, t, o]);
const b = P.jsxs(P.Fragment, { children: [a.length <= 1 ? null : P.jsx("div", { className: "tw-absolute tw-z-[9999] tw-top-[-36px] hover:tw-top-1 tw-opacity-100 hover:tw-opacity-75 tw-transition-all tw-duration-300", children: P.jsx(ft, { idPrefix: "liveness-camera", onChange: (c) => {
o && h(c.value);
}, options: a, placeholder: a[0], chevronPosition: "bottom" }) }), P.jsx("video", { id: "liveness-webcam", ref: i, className: "tw-bg-black tw-object-cover tw-object-center tw-max-w-none tw-w-full tw-h-full sm:tw-h-auto", autoPlay: !0, playsInline: !0 }), !1] });
return {
videoMarkupRef: e,
videoComponent: b,
videoStream: s,
videoElement: o
};
}, Mt = [
"video/mp4",
"video/webm",
"video/webm;codecs=vp8",
"video/webm;codecs=daala",
"video/webm;codecs=h264"
], Ve = Mt.find((t) => MediaRecorder.isTypeSupported(t)) || "video/webm", Ft = ({ stream: t, onRecordingFinished: e }) => {
const s = U(null), n = U([]), o = U(!1);
Z(() => {
if (!t)
return;
const p = (b) => {
b.data.size > 0 && n.current.push(b.data);
}, l = async () => {
const b = new Blob(n.current, {
type: Ve
});
n.current = [], o.current && e(b);
}, h = new MediaRecorder(t, {
mimeType: Ve
});
return h.addEventListener("dataavailable", p), h.addEventListener("stop", l), s.current = h, () => {
h.removeEventListener("dataavailable", p), h.removeEventListener("stop", l), h.stop();
};
}, [t, e]);
const i = B(() => !s.current || s.current.state === "recording" ? !1 : (o.current = !1, n.current = [], s.current.start(), !0), []), a = B((p) => !s.current || s.current.state === "inactive" ? !1 : (o.current = p, s.current.stop(), !0), []);
return {
startRecording: i,
stopRecording: a
};
}, Tt = (t) => {
const e = Math.sqrt(t.x ** 2 + t.y ** 2);
if (e === 0)
throw new Error("Direction vector cannot be zero");
return { x: t.x / e, y: t.y / e };
}, Lt = (t, e) => ({
x: e.x - t.x,
y: e.y - t.y
}), Pt = (t, e) => {
const s = {
x: e.x - t.x,
y: e.y - t.y
};
return {
x: -s.y,
y: s.x
};
}, Ut = (t, e, s) => {
const n = s.x, o = s.y;
return (n * (t.x - e.x) + o * (t.y - e.y)) / Math.sqrt(n * n + o * o);
}, ue = (t, e) => Math.sqrt(Math.pow(t.x - e.x, 2) + Math.pow(t.y - e.y, 2)), he = (t, e) => {
const s = {
x: e.x - t.x,
y: e.y - t.y
};
return Math.atan2(s.y, s.x) * 180 / Math.PI;
}, At = (t, e, s) => {
const n = Tt(e), o = { x: s.x - t.x, y: s.y - t.y }, i = o.x * n.x + o.y * n.y;
return {
x: t.x + n.x * i,
y: t.y + n.y * i
};
}, Vt = ({ boundingBox: t, videoHeight: e, videoWidth: s }) => {
const n = t.width / s, o = t.height / e, i = Math.max(n, o), a = t.originX / s, p = t.originY / e, l = 1 - (a + n), h = 1 - (p + o), { faceTopEdgeMin: b, faceRightEdgeMin: c, faceBottomEdgeMin: S, faceLeftEdgeMin: d, minFaceArea: C } = Ce.config.livenessCheckSettings.thresholdConfiguration || {}, w = {
top: b ?? 0.3,
right: c ?? 0.2,
bottom: S ?? 0.1,
left: d ?? 0.2,
size: C ?? 0.4
}, f = p > w.top, I = a > w.right, y = h > w.bottom, M = l > w.left, k = i > w.size;
return {
top: p,
bottom: h,
right: a,
left: l,
width: n,
height: o,
size: i,
topOk: f,
rightOk: I,
bottomOk: y,
leftOk: M,
sizeOk: k,
overallOk: f && I && y && M && k
};
}, $t = ({ keypoints: t }) => {
const [e, s, n, o, i, a] = t, p = Lt(i, a), l = At(i, p, n), h = ue(i, a), b = ue(i, l), c = b ? (b / h - 0.5) * 2 * 45 : 0, { rollAbsMaxDeg: S, pitchMin: d, pitchMax: C, yawAbsMaxDeg: w } = Ce.config.livenessCheckSettings.thresholdConfiguration || {}, f = {
roll: S ?? 10,
pitchMin: d ?? -0.12,
pitchMax: C ?? 0.45,
yaw: w ?? 15
}, I = !!b && Math.abs(c) < f.yaw, y = ue(i, a), M = Pt(i, a), k = Ut(n, i, M), g = y ? k / y : 0, F = y > 0 && g > f.pitchMin && g < f.pitchMax, $ = he(e, s), L = he(n, o) - 90, ne = he(i, a), O = ($ + L + ne) / 3, A = Math.abs(O) < f.roll;
return {
eyeLeft: e,
eyeRight: s,
nose: n,
mouth: o,
earLeft: i,
earRight: a,
yawReference: l,
yaw: c,
yawOk: I,
pitch: g,
pitchOk: F,
roll: O,
rollOk: A,
overallOk: I && F && A
};
}, zt = 10, de = at.mediaPipe.CFaceDetectionConfig, Qt = ({ setDetectionInfo: t, videoMarkupRef: e, videoElement: s }) => {
const n = U(null), o = U(0), i = U(null), a = U(null), p = U(null), [l, h] = Y(!1), [b, c] = Y(!1), [S, d] = Y(null), [C, w] = Y(!1), f = B(async () => {
var O, A;
if (a.current && cancelAnimationFrame(a.current), p.current && clearTimeout(p.current), !(s != null && s.srcObject) || !i.current || !(i.current instanceof Te)) {
p.current = setTimeout(() => f(), 1e3);
return;
}
const y = performance.now(), M = i.current.detectForVideo(s, y).detections;
let k = !1, g = "", F = "position_face";
if (M.length === 1) {
const z = M[0], { keypoints: X, boundingBox: _e } = z;
if (_e) {
const E = s.videoWidth, Q = s.videoHeight, R = Vt({
boundingBox: _e,
videoWidth: E,
videoHeight: Q
});
g += `Position: ${R.overallOk ? "" : "!!!"}
`, g += ` top: ${(R.top * 100).toFixed(2)}% ${R.topOk ? "" : "!!!"}
`, g += ` bottom: ${(R.bottom * 100).toFixed(2)}% ${R.bottomOk ? "" : "!!!"}
`, g += ` right: ${(R.right * 100).toFixed(2)}% ${R.rightOk ? "" : "!!!"}
`, g += ` left: ${(R.left * 100).toFixed(2)}% ${R.leftOk ? "" : "!!!"}
`, g += ` size: ${(R.size * 100).toFixed(2)}% ${R.sizeOk ? "" : "!!!"}
`, (A = (O = e.current) == null ? void 0 : O.querySelector("#face")) == null || A.setAttribute("style", `top: ${R.top * 100}%; right: ${R.right * 100}%; width: ${R.width * 100}%; height: ${R.height * 100}%;`), R.overallOk || (F = R.sizeOk ? "center_face" : "move_closer", k = !0);
} else
g += `No bounding box detected
`;
if (X.length === 6) {
const E = $t({
keypoints: X
}), Q = (R, { x: Ne, y: He }, We = "red") => {
var Se, ke;
(ke = (Se = e.current) == null ? void 0 : Se.querySelector(R)) == null || ke.setAttribute("style", `top: ${He * 100}%; right: ${Ne * 100}%; background: ${We};`);
};
Q("#left_eye", E.eyeLeft), Q("#right_eye", E.eyeRight), Q("#nose", E.nose), Q("#mouth", E.mouth), Q("#left_ear", E.earLeft), Q("#right_ear", E.earRight), Q("#yaw_reference", E.yawReference, "green"), g += `
Rotation: ${E.overallOk ? "" : "!!!"}
`, g += ` yaw: ${E.yaw.toFixed(2)}° ${E.yawOk ? "" : "!!!"}
`, g += ` pitch: ${(E.pitch * 100).toFixed(2)}% ${E.pitchOk ? "" : "!!!"}
`, g += ` roll: ${E.roll.toFixed(2)}° ${E.rollOk ? "" : "!!!"}
`, E.overallOk || (F = "straighten_face", k = !0);
} else
g += `No keypoints detected
`;
} else
g = M.length ? "Multiple faces detected" : "No face detected", k = !0;
t(g), d(k ? F : "hold"), k ? (h(!1), o.current = 0, n.current = null) : (o.current = o.current + 1, o.current === zt && (h(!0), n.current = y));
const $ = Ce.config.promptLength;
if ((n.current ? y - n.current : 0) > $ * 1e3) {
a.current && cancelAnimationFrame(a.current), c(!0);
return;
}
a.current = window.requestAnimationFrame(() => f());
}, [s, t, e]);
return Z(() => (ot.forVisionTasks(de.forVisionTasks).then((y) => Te.createFromOptions(y, {
baseOptions: {
modelAssetPath: de.modelAssetPath,
delegate: "GPU"
},
minDetectionConfidence: de.minDetectionConfidence,
runningMode: "VIDEO"
})).then((y) => {
i.current = y, w(!0);
}), () => {
var y;
(y = i.current) == null || y.close(), i.current = null;
}), []), {
startDetector: B(() => {
f();
}, [f]),
isFaceDetected: l,
isCompleted: b,
instruction: S,
initialized: C
};
}, jt = ({ onSucess: t, onFail: e }) => {
const [s, n] = Y(!1), o = B(async (i, a = []) => {
n(!0);
try {
if (!i)
throw new Error("Video blob is null");
if (!((i == null ? void 0 : i.size) || 0))
throw new Error("Video blob size is 0");
const l = await new ct(a).getUploadUrl();
if (!(l != null && l.ok))
throw new Error("Error getting video upload url");
if ((await new lt({
url: l.videoUploadUrl,
video: i,
mimeType: i.type
}).startUploadLivenessVideo()).ok === !1)
throw new Error("Error uploading video");
t();
} catch (p) {
e(p);
} finally {
n(!1);
}
}, [t, e]);
return {
isUploading: s,
uploadVideo: o
};
}, qt = (t) => {
Qe({
title: j.error_liveness_upload_title,
description: j.error_liveness_upload_description,
btnText: j.restart_button,
ERROR: t
});
}, Gt = ({ onNext: t, onBack: e }) => {
const s = U(null), n = U(null), o = B(($) => {
n.current && (n.current.innerText = $);
}, []), i = B(() => {
var $;
o("Camera loaded"), ($ = s.current) == null || $.call(s);
}, [o]), { isUploading: a, uploadVideo: p } = jt({
onFail: qt,
onSucess: t
}), { videoComponent: l, videoStream: h, videoElement: b, videoMarkupRef: c } = It({
onDataLoaded: i
}), { startRecording: S, stopRecording: d } = Ft({
onRecordingFinished: p,
stream: h
}), { startDetector: C, isCompleted: w, isFaceDetected: f, instruction: I, initialized: y } = Qt({
videoMarkupRef: c,
setDetectionInfo: o,
videoElement: b
}), M = dt(() => {
switch (I) {
case "center_face":
return {
text: j.liveness_check_action_center_face
};
case "move_closer":
return {
text: j.liveness_check_action_move_closer
};
case "straighten_face":
return {
text: j.liveness_check_action_straighten_face
};
case "hold":
return {
text: j.liveness_check_action_hold
};
}
return {
icon: P.jsx(ut, { width: 48, hanging: 48 }),
text: j.liveness_check_action_position_face
};
}, [I]);
Z(() => (s.current = C, () => {
s.current = null;
}), [C]), Z(() => {
w ? d(!0) : f ? S() : d(!1);
}, [f, w, S, d]);
const F = [
{
animateTo: {
startAnimationTo: f,
strokeDasharray: "0",
strokeWidth: "4"
},
outline: "idle",
dimension: "face-only"
},
{
outline: "countdown",
dimension: "face-only",
startAnimation: f
}
][f || w ? 1 : 0];
return P.jsxs(P.Fragment, { children: [P.jsx(nt, { className: `tw-w-full tw-h-full sm:tw-h-auto ${a && "tw-opacity-0"}`, children: P.jsxs(it, { idPrefix: "selfie-liveness-camera", onBack: e, title: j.liveness_check_selfie_flow_title, instructions: M, children: [P.jsxs(ht, { dimension: F.dimension, outline: F.outline, startAnimation: F.startAnimation, animateTo: F.animateTo, isSuccessful: w, children: [l, !y && P.jsx(Le, { isUploading: !0 })] }), !1] }) }), P.jsx(Le, { isUploading: a })] });
};
export {
Gt as default
};