@neofaceid/web-sdk 1.17.0 → 1.19.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.
|
@@ -3428,7 +3428,16 @@ const CALIBRATION = {
|
|
|
3428
3428
|
YAW_LEFT_THRESHOLD: 15,
|
|
3429
3429
|
YAW_RIGHT_THRESHOLD: -15,
|
|
3430
3430
|
CAPTURE_HOLD_TIME: 1500,
|
|
3431
|
-
DETECTION_INTERVAL:
|
|
3431
|
+
DETECTION_INTERVAL: 150,
|
|
3432
|
+
// Um pouco mais rápido para melhor resposta
|
|
3433
|
+
MIN_FACE_WIDTH: 160,
|
|
3434
|
+
// Rosto deve ocupar boa parte do oval (era ~120 implícito)
|
|
3435
|
+
MAX_FACE_WIDTH: 280,
|
|
3436
|
+
// Evita rosto "colado" na câmera
|
|
3437
|
+
CENTER_X_THRESHOLD: 0.15,
|
|
3438
|
+
// Rosto deve estar centralizado (desvio max 15%)
|
|
3439
|
+
CENTER_Y_THRESHOLD: 0.2
|
|
3440
|
+
// Rosto deve estar centralizado verticalmente
|
|
3432
3441
|
};
|
|
3433
3442
|
function BiometricRegistrationModal({
|
|
3434
3443
|
personData,
|
|
@@ -3450,7 +3459,8 @@ function BiometricRegistrationModal({
|
|
|
3450
3459
|
const captureStateRef = useRef(null);
|
|
3451
3460
|
const [state, dispatch] = useReducer(modalReducer, initialState);
|
|
3452
3461
|
const [faceDetected, setFaceDetected] = useState(false);
|
|
3453
|
-
const [
|
|
3462
|
+
const [faceDistance, setFaceDistance] = useState("ok");
|
|
3463
|
+
const [cameraReady, setCameraReady] = useState(false);
|
|
3454
3464
|
useEffect(() => {
|
|
3455
3465
|
if (state.status === "liveness") {
|
|
3456
3466
|
const newStep = state.step;
|
|
@@ -3512,6 +3522,18 @@ function BiometricRegistrationModal({
|
|
|
3512
3522
|
return null;
|
|
3513
3523
|
}
|
|
3514
3524
|
};
|
|
3525
|
+
const checkFacePosition = (box, videoWidth, videoHeight) => {
|
|
3526
|
+
if (box.width < CALIBRATION.MIN_FACE_WIDTH) return "too-far";
|
|
3527
|
+
if (box.width > CALIBRATION.MAX_FACE_WIDTH) return "too-close";
|
|
3528
|
+
const faceCenterX = box.x + box.width / 2;
|
|
3529
|
+
const faceCenterY = box.y + box.height / 2;
|
|
3530
|
+
const deviationX = Math.abs(faceCenterX - videoWidth / 2) / videoWidth;
|
|
3531
|
+
const deviationY = Math.abs(faceCenterY - videoHeight / 2) / videoHeight;
|
|
3532
|
+
if (deviationX > CALIBRATION.CENTER_X_THRESHOLD || deviationY > CALIBRATION.CENTER_Y_THRESHOLD) {
|
|
3533
|
+
return "not-centered";
|
|
3534
|
+
}
|
|
3535
|
+
return "ok";
|
|
3536
|
+
};
|
|
3515
3537
|
const checkPositionMatch = (pitch, yaw, step) => {
|
|
3516
3538
|
switch (step) {
|
|
3517
3539
|
case "center":
|
|
@@ -3652,7 +3674,11 @@ function BiometricRegistrationModal({
|
|
|
3652
3674
|
}
|
|
3653
3675
|
video.srcObject = stream;
|
|
3654
3676
|
streamRef.current = stream;
|
|
3655
|
-
|
|
3677
|
+
video.onloadedmetadata = () => {
|
|
3678
|
+
video.play().then(() => {
|
|
3679
|
+
if (mounted) setCameraReady(true);
|
|
3680
|
+
});
|
|
3681
|
+
};
|
|
3656
3682
|
} catch (error) {
|
|
3657
3683
|
if (!mounted) return;
|
|
3658
3684
|
if (watchdogTimerRef.current) {
|
|
@@ -3722,14 +3748,17 @@ function BiometricRegistrationModal({
|
|
|
3722
3748
|
const hasFace = !!detection;
|
|
3723
3749
|
setFaceDetected(hasFace);
|
|
3724
3750
|
if (hasFace && detection.detection) {
|
|
3725
|
-
const
|
|
3726
|
-
const
|
|
3727
|
-
|
|
3728
|
-
|
|
3729
|
-
|
|
3730
|
-
|
|
3731
|
-
|
|
3732
|
-
|
|
3751
|
+
const video2 = videoRef.current;
|
|
3752
|
+
const positionStatus = checkFacePosition(
|
|
3753
|
+
detection.detection.box,
|
|
3754
|
+
video2.videoWidth,
|
|
3755
|
+
video2.videoHeight
|
|
3756
|
+
);
|
|
3757
|
+
setFaceDistance(positionStatus);
|
|
3758
|
+
if (positionStatus !== "ok") {
|
|
3759
|
+
manageHoldAndCapture(false);
|
|
3760
|
+
requestAnimationFrame(detectFace2);
|
|
3761
|
+
return;
|
|
3733
3762
|
}
|
|
3734
3763
|
}
|
|
3735
3764
|
if (hasFace && detection.landmarks) {
|
|
@@ -3911,12 +3940,26 @@ function BiometricRegistrationModal({
|
|
|
3911
3940
|
const stepProgress = state.stepProgress;
|
|
3912
3941
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "liveness-container", children: [
|
|
3913
3942
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "progress-indicator", children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "progress-text", children: progress }) }),
|
|
3943
|
+
faceDetected && faceDistance !== "ok" && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: `face-badge ${faceDistance === "not-centered" ? "warning" : "error"}`, children: [
|
|
3944
|
+
faceDistance === "too-far" && "Aproxime-se mais",
|
|
3945
|
+
faceDistance === "too-close" && "Rosto muito perto",
|
|
3946
|
+
faceDistance === "not-centered" && "Centralize seu rosto"
|
|
3947
|
+
] }),
|
|
3914
3948
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "video-wrapper", children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
3915
3949
|
"div",
|
|
3916
3950
|
{
|
|
3917
3951
|
className: `video-circle ${faceDetected ? "face-detected" : ""} ${stepProgress > 0 ? "capturing" : ""}`,
|
|
3918
3952
|
children: [
|
|
3919
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
3953
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
3954
|
+
"video",
|
|
3955
|
+
{
|
|
3956
|
+
ref: videoRef,
|
|
3957
|
+
className: `video-feed ${cameraReady ? "ready" : ""}`,
|
|
3958
|
+
autoPlay: true,
|
|
3959
|
+
muted: true,
|
|
3960
|
+
playsInline: true
|
|
3961
|
+
}
|
|
3962
|
+
),
|
|
3920
3963
|
faceDetected && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "face-badge", children: [
|
|
3921
3964
|
/* @__PURE__ */ jsxRuntimeExports.jsx("svg", { width: "16", height: "16", viewBox: "0 0 20 20", fill: "none", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
3922
3965
|
"path",
|
|
@@ -4387,8 +4430,9 @@ function BiometricRegistrationModal({
|
|
|
4387
4430
|
border-radius: 50%;
|
|
4388
4431
|
overflow: hidden;
|
|
4389
4432
|
position: relative;
|
|
4390
|
-
|
|
4433
|
+
/* Removida transição 'all' para evitar salto de zoom no início */
|
|
4391
4434
|
box-shadow: 0 0 0 4px rgba(124, 58, 237, 0.3);
|
|
4435
|
+
background: #000;
|
|
4392
4436
|
}
|
|
4393
4437
|
|
|
4394
4438
|
.video-circle.face-detected {
|
|
@@ -4405,6 +4449,12 @@ function BiometricRegistrationModal({
|
|
|
4405
4449
|
height: 100%;
|
|
4406
4450
|
object-fit: cover;
|
|
4407
4451
|
transform: scaleX(-1);
|
|
4452
|
+
opacity: 0;
|
|
4453
|
+
transition: opacity 0.4s ease;
|
|
4454
|
+
}
|
|
4455
|
+
|
|
4456
|
+
.video-feed.ready {
|
|
4457
|
+
opacity: 1;
|
|
4408
4458
|
}
|
|
4409
4459
|
|
|
4410
4460
|
.face-badge {
|
|
@@ -6835,7 +6885,7 @@ const biometricDetection = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.
|
|
|
6835
6885
|
initializeBiometricDetection,
|
|
6836
6886
|
isAdvancedDetectionAvailable
|
|
6837
6887
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
6838
|
-
const VERSION = "1.
|
|
6888
|
+
const VERSION = "1.19.0";
|
|
6839
6889
|
const RELEASE_DATE = "2026-03-13";
|
|
6840
6890
|
class OnboardingCaptureModal {
|
|
6841
6891
|
constructor(options) {
|