@neofaceid/web-sdk 1.41.1 → 1.42.1
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.ts +253 -2
- package/dist/neoface-id-sdk.es.js +1033 -314
- package/dist/neoface-id-sdk.umd.js +1 -1
- package/package.json +1 -1
|
@@ -4311,9 +4311,16 @@ function refine(fn, _params = {}) {
|
|
|
4311
4311
|
function superRefine(fn) {
|
|
4312
4312
|
return /* @__PURE__ */ _superRefine(fn);
|
|
4313
4313
|
}
|
|
4314
|
+
const AuthMethodSchema = _enum(["face", "password"]);
|
|
4314
4315
|
object({
|
|
4315
4316
|
success: boolean(),
|
|
4316
4317
|
accessToken: string().optional(),
|
|
4318
|
+
/**
|
|
4319
|
+
* Só chega quando `application.can_issue_user_tokens` está ligado no core.
|
|
4320
|
+
* Sessões longas (o console) dependem dele; fluxos curtos podem ignorá-lo.
|
|
4321
|
+
*/
|
|
4322
|
+
refreshToken: string().optional(),
|
|
4323
|
+
method: AuthMethodSchema.optional(),
|
|
4317
4324
|
alias: string().optional(),
|
|
4318
4325
|
user: object({
|
|
4319
4326
|
id: string(),
|
|
@@ -4547,6 +4554,10 @@ const ENVIRONMENT_URLS = {
|
|
|
4547
4554
|
sandbox: "https://sandbox-core.neofaceid.com",
|
|
4548
4555
|
production: "https://core.neofaceid.com.br"
|
|
4549
4556
|
};
|
|
4557
|
+
const DEFAULT_AUTO_FALLBACK = {
|
|
4558
|
+
toPhone: false,
|
|
4559
|
+
toPassword: true
|
|
4560
|
+
};
|
|
4550
4561
|
const DEFAULT_LOCALE = "pt-BR";
|
|
4551
4562
|
const DEFAULT_RADIUS = 16;
|
|
4552
4563
|
const DEFAULT_THEME = "light";
|
|
@@ -4563,13 +4574,31 @@ function makeDefaultConfig() {
|
|
|
4563
4574
|
theme: DEFAULT_THEME,
|
|
4564
4575
|
locale: DEFAULT_LOCALE,
|
|
4565
4576
|
resolvedTheme: null,
|
|
4566
|
-
consent: { ...DEFAULT_CONSENT }
|
|
4577
|
+
consent: { ...DEFAULT_CONSENT },
|
|
4578
|
+
autoFallback: { ...DEFAULT_AUTO_FALLBACK }
|
|
4567
4579
|
};
|
|
4568
4580
|
}
|
|
4569
4581
|
let globalConfig = makeDefaultConfig();
|
|
4570
4582
|
let consentWarningShown = false;
|
|
4571
4583
|
function init(options = {}) {
|
|
4572
|
-
const {
|
|
4584
|
+
const {
|
|
4585
|
+
environment,
|
|
4586
|
+
baseUrl,
|
|
4587
|
+
applicationToken,
|
|
4588
|
+
appName,
|
|
4589
|
+
accent,
|
|
4590
|
+
radius,
|
|
4591
|
+
theme,
|
|
4592
|
+
locale,
|
|
4593
|
+
consent,
|
|
4594
|
+
autoFallback
|
|
4595
|
+
} = options;
|
|
4596
|
+
if (autoFallback) {
|
|
4597
|
+
globalConfig.autoFallback = {
|
|
4598
|
+
toPhone: autoFallback.toPhone ?? DEFAULT_AUTO_FALLBACK.toPhone,
|
|
4599
|
+
toPassword: autoFallback.toPassword ?? DEFAULT_AUTO_FALLBACK.toPassword
|
|
4600
|
+
};
|
|
4601
|
+
}
|
|
4573
4602
|
if (consent) {
|
|
4574
4603
|
globalConfig.consent = consent;
|
|
4575
4604
|
} else {
|
|
@@ -4667,6 +4696,9 @@ function getAppName() {
|
|
|
4667
4696
|
function getAccent() {
|
|
4668
4697
|
return globalConfig.accent;
|
|
4669
4698
|
}
|
|
4699
|
+
function getAutoFallback() {
|
|
4700
|
+
return { ...globalConfig.autoFallback };
|
|
4701
|
+
}
|
|
4670
4702
|
function getRadius() {
|
|
4671
4703
|
return globalConfig.radius;
|
|
4672
4704
|
}
|
|
@@ -5132,6 +5164,9 @@ const loginWithBiometric = async (image, applicationToken) => {
|
|
|
5132
5164
|
return {
|
|
5133
5165
|
success: true,
|
|
5134
5166
|
accessToken: data.accessToken || data.access_token || "",
|
|
5167
|
+
// Só vem quando `can_issue_user_tokens` está ligado na aplicação.
|
|
5168
|
+
refreshToken: data.refreshToken || data.refresh_token || void 0,
|
|
5169
|
+
method: "face",
|
|
5135
5170
|
alias: data.alias,
|
|
5136
5171
|
user: {
|
|
5137
5172
|
id: ((_a2 = data.user) == null ? void 0 : _a2.id) || "",
|
|
@@ -5618,6 +5653,8 @@ const loginWithEmail = async (email2, password, applicationToken) => {
|
|
|
5618
5653
|
success: true,
|
|
5619
5654
|
// Compatível com diferentes formatos de resposta do backend
|
|
5620
5655
|
accessToken: data.access_token || data.access,
|
|
5656
|
+
refreshToken: data.refresh_token || data.refresh || void 0,
|
|
5657
|
+
method: "password",
|
|
5621
5658
|
alias: data.user && data.user.alias || data.alias,
|
|
5622
5659
|
user: {
|
|
5623
5660
|
id: data.user && data.user.id || "",
|
|
@@ -5640,6 +5677,98 @@ const loginWithEmail = async (email2, password, applicationToken) => {
|
|
|
5640
5677
|
throw new NeoFaceError("Unknown error occurred", ErrorType.NETWORK);
|
|
5641
5678
|
}
|
|
5642
5679
|
};
|
|
5680
|
+
const requestDeviceEnrollmentToken = async (userAccessToken, applicationToken) => {
|
|
5681
|
+
var _a2, _b, _c;
|
|
5682
|
+
if (!userAccessToken) {
|
|
5683
|
+
throw new NeoFaceError(
|
|
5684
|
+
"Inscrição de aparelho exige um usuário autenticado (access token ausente).",
|
|
5685
|
+
ErrorType.INVALID_TOKEN
|
|
5686
|
+
);
|
|
5687
|
+
}
|
|
5688
|
+
const controller = createTimeoutController();
|
|
5689
|
+
try {
|
|
5690
|
+
const response = await fetch(`${getApiBaseUrl()}/api/v1/devices/enrollment-token/`, {
|
|
5691
|
+
method: "POST",
|
|
5692
|
+
headers: {
|
|
5693
|
+
"Content-Type": "application/json",
|
|
5694
|
+
"X-App-Token": applicationToken,
|
|
5695
|
+
Authorization: `Bearer ${userAccessToken}`
|
|
5696
|
+
},
|
|
5697
|
+
signal: controller.signal
|
|
5698
|
+
});
|
|
5699
|
+
if (!response.ok) {
|
|
5700
|
+
if (response.status === 401 || response.status === 403) {
|
|
5701
|
+
throw new NeoFaceError(
|
|
5702
|
+
"Não foi possível inscrever o aparelho: sessão expirada ou conta sem permissão. Faça login novamente.",
|
|
5703
|
+
ErrorType.INVALID_TOKEN
|
|
5704
|
+
);
|
|
5705
|
+
}
|
|
5706
|
+
throw new NeoFaceError(`API Error ${response.status}`, ErrorType.API_ERROR);
|
|
5707
|
+
}
|
|
5708
|
+
const data = await response.json();
|
|
5709
|
+
const token = data.token ?? ((_a2 = data.data) == null ? void 0 : _a2.token);
|
|
5710
|
+
if (!token) {
|
|
5711
|
+
throw new NeoFaceError("Resposta sem token de inscrição", ErrorType.API_ERROR);
|
|
5712
|
+
}
|
|
5713
|
+
return {
|
|
5714
|
+
token,
|
|
5715
|
+
expiresIn: data.expires_in ?? ((_b = data.data) == null ? void 0 : _b.expires_in) ?? 300,
|
|
5716
|
+
purpose: data.purpose ?? ((_c = data.data) == null ? void 0 : _c.purpose) ?? "device-enrollment"
|
|
5717
|
+
};
|
|
5718
|
+
} catch (error) {
|
|
5719
|
+
if (error instanceof NeoFaceError) throw error;
|
|
5720
|
+
if (error instanceof Error) {
|
|
5721
|
+
if (error.name === "AbortError") {
|
|
5722
|
+
throw new NeoFaceError("Request timed out", ErrorType.NETWORK);
|
|
5723
|
+
}
|
|
5724
|
+
throw new NeoFaceError(error.message, ErrorType.NETWORK);
|
|
5725
|
+
}
|
|
5726
|
+
throw new NeoFaceError("Unknown error occurred", ErrorType.NETWORK);
|
|
5727
|
+
}
|
|
5728
|
+
};
|
|
5729
|
+
const refreshSession = async (refreshToken, applicationToken) => {
|
|
5730
|
+
const controller = createTimeoutController();
|
|
5731
|
+
try {
|
|
5732
|
+
const response = await fetch(`${getApiBaseUrl()}/api/v1/token/refresh/`, {
|
|
5733
|
+
method: "POST",
|
|
5734
|
+
headers: {
|
|
5735
|
+
"Content-Type": "application/json",
|
|
5736
|
+
"X-App-Token": applicationToken
|
|
5737
|
+
},
|
|
5738
|
+
body: JSON.stringify({ refresh: refreshToken }),
|
|
5739
|
+
signal: controller.signal
|
|
5740
|
+
});
|
|
5741
|
+
if (!response.ok) {
|
|
5742
|
+
if (response.status === 401 || response.status === 403) {
|
|
5743
|
+
throw new NeoFaceError(
|
|
5744
|
+
"Sessão expirada — faça login novamente",
|
|
5745
|
+
ErrorType.INVALID_TOKEN
|
|
5746
|
+
);
|
|
5747
|
+
}
|
|
5748
|
+
throw new NeoFaceError(`API Error ${response.status}`, ErrorType.API_ERROR);
|
|
5749
|
+
}
|
|
5750
|
+
const data = await response.json();
|
|
5751
|
+
const access = data.access ?? data.access_token;
|
|
5752
|
+
if (!access) {
|
|
5753
|
+
throw new NeoFaceError("Resposta de refresh sem access token", ErrorType.API_ERROR);
|
|
5754
|
+
}
|
|
5755
|
+
return {
|
|
5756
|
+
accessToken: access,
|
|
5757
|
+
// Com rotação ligada o core devolve refresh novo. Se algum ambiente
|
|
5758
|
+
// estiver sem rotação, o refresh atual segue valendo.
|
|
5759
|
+
refreshToken: data.refresh ?? data.refresh_token ?? refreshToken
|
|
5760
|
+
};
|
|
5761
|
+
} catch (error) {
|
|
5762
|
+
if (error instanceof NeoFaceError) throw error;
|
|
5763
|
+
if (error instanceof Error) {
|
|
5764
|
+
if (error.name === "AbortError") {
|
|
5765
|
+
throw new NeoFaceError("Request timed out", ErrorType.NETWORK);
|
|
5766
|
+
}
|
|
5767
|
+
throw new NeoFaceError(error.message, ErrorType.NETWORK);
|
|
5768
|
+
}
|
|
5769
|
+
throw new NeoFaceError("Unknown error occurred", ErrorType.NETWORK);
|
|
5770
|
+
}
|
|
5771
|
+
};
|
|
5643
5772
|
const identifyPerson = async (image, applicationToken) => {
|
|
5644
5773
|
var _a2, _b, _c, _d;
|
|
5645
5774
|
ensureSecureContext();
|
|
@@ -5952,7 +6081,7 @@ const recordFaceVideo = async (options = {}) => {
|
|
|
5952
6081
|
});
|
|
5953
6082
|
};
|
|
5954
6083
|
const pollTaskStatus = async (taskId, applicationToken, options = {}) => {
|
|
5955
|
-
var _a2, _b, _c, _d, _e, _f;
|
|
6084
|
+
var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
5956
6085
|
const { maxAttempts = 60, intervalMs = 1e3, onStatusChange } = options;
|
|
5957
6086
|
let attempts = 0;
|
|
5958
6087
|
while (attempts < maxAttempts) {
|
|
@@ -5984,6 +6113,10 @@ const pollTaskStatus = async (taskId, applicationToken, options = {}) => {
|
|
|
5984
6113
|
if (status === "revoked") {
|
|
5985
6114
|
throw new NeoFaceError("Task was cancelled", ErrorType.RECOGNITION_FAILED);
|
|
5986
6115
|
}
|
|
6116
|
+
if (data.success === false) {
|
|
6117
|
+
const reason = ((_h = (_g = data.data) == null ? void 0 : _g.result) == null ? void 0 : _h.message) || ((_i = data.data) == null ? void 0 : _i.error) || ((_j = data.data) == null ? void 0 : _j.message) || data.message || "Task failed";
|
|
6118
|
+
throw new NeoFaceError(reason, ErrorType.RECOGNITION_FAILED);
|
|
6119
|
+
}
|
|
5987
6120
|
await new Promise((resolve) => setTimeout(resolve, intervalMs));
|
|
5988
6121
|
} catch (error) {
|
|
5989
6122
|
if (error instanceof NeoFaceError) {
|
|
@@ -6242,11 +6375,13 @@ const api = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty(
|
|
|
6242
6375
|
recognizeBiometric,
|
|
6243
6376
|
recognizeByPurpose,
|
|
6244
6377
|
recordFaceVideo,
|
|
6378
|
+
refreshSession,
|
|
6245
6379
|
registerApplication,
|
|
6246
6380
|
registerBiometric,
|
|
6247
6381
|
registerDocumentByImage,
|
|
6248
6382
|
registerPersonWithBiometric,
|
|
6249
6383
|
registerPersonWithoutFace,
|
|
6384
|
+
requestDeviceEnrollmentToken,
|
|
6250
6385
|
requestPasswordReset,
|
|
6251
6386
|
simpleIdentification,
|
|
6252
6387
|
startProofOfLife,
|
|
@@ -8732,8 +8867,8 @@ function BiometricRegistrationModal({
|
|
|
8732
8867
|
/* @__PURE__ */ jsx("canvas", { ref: canvasRef })
|
|
8733
8868
|
] });
|
|
8734
8869
|
}
|
|
8735
|
-
const VERSION = "1.
|
|
8736
|
-
const RELEASE_DATE = "2026-09-
|
|
8870
|
+
const VERSION = "1.42.1";
|
|
8871
|
+
const RELEASE_DATE = "2026-09-13";
|
|
8737
8872
|
const CONSENT_TRAIL_STORAGE_KEY = "neoface_consent_trail_v1";
|
|
8738
8873
|
const CONSENT_TRAIL_MAX_LIMIT = 100;
|
|
8739
8874
|
async function hashString(inputStr) {
|
|
@@ -8810,8 +8945,6 @@ const COPY = {
|
|
|
8810
8945
|
bullet1Body: "Você vê a imagem o tempo todo e pode encerrar quando quiser.",
|
|
8811
8946
|
bullet2Title: "Pediremos dois movimentos simples",
|
|
8812
8947
|
bullet2Body: "Virar o rosto ou piscar — é assim que sabemos que há alguém ali.",
|
|
8813
|
-
bullet3Title: "A imagem não fica guardada",
|
|
8814
|
-
bullet3Body: "Ela é usada para a verificação e descartada em seguida.",
|
|
8815
8948
|
primary: "Começar verificação"
|
|
8816
8949
|
},
|
|
8817
8950
|
registration: {
|
|
@@ -8821,11 +8954,26 @@ const COPY = {
|
|
|
8821
8954
|
bullet1Body: "Você vê a imagem o tempo todo e pode encerrar quando quiser.",
|
|
8822
8955
|
bullet2Title: "Pediremos dois movimentos simples",
|
|
8823
8956
|
bullet2Body: "Virar o rosto ou piscar — é assim que sabemos que há alguém ali.",
|
|
8824
|
-
bullet3Title: "Guardamos um vetor matemático do seu rosto",
|
|
8825
|
-
bullet3Body: "Não a foto. A imagem é descartada.",
|
|
8826
8957
|
primary: "Começar cadastro"
|
|
8827
8958
|
}
|
|
8828
8959
|
};
|
|
8960
|
+
const plural = (n) => n === 1 ? "dia" : "dias";
|
|
8961
|
+
function terceiroMarcador(flow, retentionDays) {
|
|
8962
|
+
const prazoDeclarado = Number.isFinite(retentionDays) && retentionDays > 0;
|
|
8963
|
+
if (flow === "registration") {
|
|
8964
|
+
return {
|
|
8965
|
+
title: "Guardamos um vetor matemático do seu rosto",
|
|
8966
|
+
body: prazoDeclarado ? `Não a foto. A imagem fica guardada por até ${retentionDays} ${plural(retentionDays)} e é apagada no fim desse prazo.` : "Não a foto. O prazo de guarda da imagem está na política de privacidade."
|
|
8967
|
+
};
|
|
8968
|
+
}
|
|
8969
|
+
return prazoDeclarado ? {
|
|
8970
|
+
title: `A imagem fica guardada por até ${retentionDays} ${plural(retentionDays)}`,
|
|
8971
|
+
body: "Ela é usada para a verificação e apagada no fim desse prazo."
|
|
8972
|
+
} : {
|
|
8973
|
+
title: "A imagem é tratada conforme a política de privacidade",
|
|
8974
|
+
body: "Ela é usada para a verificação; o prazo de guarda está descrito lá."
|
|
8975
|
+
};
|
|
8976
|
+
}
|
|
8829
8977
|
const IconCamera = () => /* @__PURE__ */ jsxs(
|
|
8830
8978
|
"svg",
|
|
8831
8979
|
{
|
|
@@ -8890,6 +9038,8 @@ function ConsentModalComponent({
|
|
|
8890
9038
|
onDecline
|
|
8891
9039
|
}) {
|
|
8892
9040
|
const copy = COPY[flow];
|
|
9041
|
+
const marcador3 = terceiroMarcador(flow, retentionDays);
|
|
9042
|
+
const prazoDeclarado = Number.isFinite(retentionDays) && retentionDays > 0;
|
|
8893
9043
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
8894
9044
|
/* @__PURE__ */ jsx("style", { children: `
|
|
8895
9045
|
@keyframes neofaceidConsentFadeIn { from { opacity: 0 } to { opacity: 1 } }
|
|
@@ -9066,23 +9216,19 @@ function ConsentModalComponent({
|
|
|
9066
9216
|
/* @__PURE__ */ jsxs("div", { className: "neofaceid-consent-bullet", children: [
|
|
9067
9217
|
/* @__PURE__ */ jsx("div", { className: "neofaceid-consent-bullet-icon", children: /* @__PURE__ */ jsx(IconShield, {}) }),
|
|
9068
9218
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
9069
|
-
/* @__PURE__ */ jsx("p", { className: "neofaceid-consent-bullet-title", children:
|
|
9070
|
-
/* @__PURE__ */ jsx("p", { className: "neofaceid-consent-bullet-body", children:
|
|
9219
|
+
/* @__PURE__ */ jsx("p", { className: "neofaceid-consent-bullet-title", children: marcador3.title }),
|
|
9220
|
+
/* @__PURE__ */ jsx("p", { className: "neofaceid-consent-bullet-body", children: marcador3.body })
|
|
9071
9221
|
] })
|
|
9072
9222
|
] })
|
|
9073
9223
|
] }),
|
|
9074
|
-
/* @__PURE__ */
|
|
9224
|
+
/* @__PURE__ */ jsx(
|
|
9075
9225
|
"a",
|
|
9076
9226
|
{
|
|
9077
9227
|
href: privacyPolicyUrl,
|
|
9078
9228
|
target: "_blank",
|
|
9079
9229
|
rel: "noopener noreferrer",
|
|
9080
9230
|
className: "neofaceid-consent-link",
|
|
9081
|
-
children:
|
|
9082
|
-
"Ver política de privacidade (retenção de até ",
|
|
9083
|
-
retentionDays,
|
|
9084
|
-
" dias)"
|
|
9085
|
-
]
|
|
9231
|
+
children: prazoDeclarado ? `Ver política de privacidade (retenção de até ${retentionDays} ${plural(retentionDays)})` : "Ver política de privacidade"
|
|
9086
9232
|
}
|
|
9087
9233
|
),
|
|
9088
9234
|
/* @__PURE__ */ jsxs("div", { className: "neofaceid-consent-actions", children: [
|
|
@@ -9178,112 +9324,808 @@ const DEFAULT_CONSENT_INFO = {
|
|
|
9178
9324
|
privacyPolicyUrl: DEFAULT_PRIVACY_URL,
|
|
9179
9325
|
retentionDays: DEFAULT_RETENTION_DAYS
|
|
9180
9326
|
};
|
|
9181
|
-
function
|
|
9182
|
-
|
|
9183
|
-
|
|
9184
|
-
|
|
9185
|
-
|
|
9186
|
-
|
|
9187
|
-
|
|
9188
|
-
|
|
9189
|
-
|
|
9190
|
-
};
|
|
9191
|
-
case "too-far":
|
|
9192
|
-
case "too-close":
|
|
9193
|
-
case "off-center":
|
|
9194
|
-
return {
|
|
9195
|
-
borderColor: "#F59E0B",
|
|
9196
|
-
boxShadow: "0 0 0 4px rgba(245, 158, 11, 0.7), 0 0 35px rgba(245, 158, 11, 0.35)",
|
|
9197
|
-
svgStroke: "#F59E0B",
|
|
9198
|
-
badgeBg: "rgba(245, 158, 11, 0.95)",
|
|
9199
|
-
badgeColor: "#1F2937"
|
|
9200
|
-
};
|
|
9201
|
-
case "searching":
|
|
9202
|
-
default:
|
|
9203
|
-
return {
|
|
9204
|
-
borderColor: "rgba(156, 163, 175, 0.5)",
|
|
9205
|
-
boxShadow: "0 0 0 4px rgba(156, 163, 175, 0.3), 0 0 20px rgba(156, 163, 175, 0.15)",
|
|
9206
|
-
svgStroke: "#9CA3AF",
|
|
9207
|
-
badgeBg: "rgba(55, 65, 81, 0.9)",
|
|
9208
|
-
badgeColor: "#FFFFFF"
|
|
9209
|
-
};
|
|
9210
|
-
}
|
|
9211
|
-
}
|
|
9212
|
-
function CameraOvalGuide({
|
|
9213
|
-
stream,
|
|
9214
|
-
faceState,
|
|
9215
|
-
instruction,
|
|
9216
|
-
className = "",
|
|
9217
|
-
style = {}
|
|
9327
|
+
function Sheet({
|
|
9328
|
+
open,
|
|
9329
|
+
onDismiss,
|
|
9330
|
+
dismissOnOverlay = true,
|
|
9331
|
+
ariaLabel,
|
|
9332
|
+
ariaLabelledBy,
|
|
9333
|
+
children,
|
|
9334
|
+
className,
|
|
9335
|
+
style
|
|
9218
9336
|
}) {
|
|
9219
|
-
const videoRef = useRef(null);
|
|
9220
9337
|
useEffect(() => {
|
|
9221
|
-
|
|
9222
|
-
|
|
9223
|
-
|
|
9224
|
-
|
|
9225
|
-
|
|
9226
|
-
|
|
9227
|
-
|
|
9228
|
-
videoEl.srcObject = null;
|
|
9229
|
-
}
|
|
9230
|
-
return () => {
|
|
9231
|
-
if (stream) {
|
|
9232
|
-
stream.getTracks().forEach((track) => track.stop());
|
|
9233
|
-
}
|
|
9234
|
-
if (videoEl) {
|
|
9235
|
-
videoEl.srcObject = null;
|
|
9236
|
-
}
|
|
9237
|
-
};
|
|
9238
|
-
}, [stream]);
|
|
9239
|
-
const halo = getHaloStyles(faceState);
|
|
9240
|
-
return /* @__PURE__ */ jsxs(
|
|
9338
|
+
injectThemeStyles();
|
|
9339
|
+
}, []);
|
|
9340
|
+
if (!open) return null;
|
|
9341
|
+
const handleOverlay = () => {
|
|
9342
|
+
if (dismissOnOverlay && onDismiss) onDismiss();
|
|
9343
|
+
};
|
|
9344
|
+
return /* @__PURE__ */ jsx(
|
|
9241
9345
|
"div",
|
|
9242
9346
|
{
|
|
9243
|
-
className:
|
|
9347
|
+
className: "neofaceid-root",
|
|
9348
|
+
role: "presentation",
|
|
9244
9349
|
style: {
|
|
9350
|
+
position: "fixed",
|
|
9351
|
+
inset: 0,
|
|
9352
|
+
zIndex: 10001,
|
|
9245
9353
|
display: "flex",
|
|
9246
|
-
flexDirection: "column",
|
|
9247
9354
|
alignItems: "center",
|
|
9248
9355
|
justifyContent: "center",
|
|
9249
|
-
|
|
9250
|
-
|
|
9251
|
-
|
|
9252
|
-
|
|
9253
|
-
boxSizing: "border-box",
|
|
9254
|
-
...style
|
|
9356
|
+
padding: 20,
|
|
9357
|
+
background: `var(${CSS_VAR.overlay})`,
|
|
9358
|
+
backdropFilter: "blur(3px)",
|
|
9359
|
+
WebkitBackdropFilter: "blur(3px)"
|
|
9255
9360
|
},
|
|
9256
|
-
|
|
9257
|
-
|
|
9258
|
-
|
|
9259
|
-
|
|
9260
|
-
|
|
9261
|
-
|
|
9262
|
-
|
|
9263
|
-
|
|
9264
|
-
|
|
9265
|
-
|
|
9361
|
+
onClick: handleOverlay,
|
|
9362
|
+
children: /* @__PURE__ */ jsx(
|
|
9363
|
+
"div",
|
|
9364
|
+
{
|
|
9365
|
+
role: "dialog",
|
|
9366
|
+
"aria-modal": "true",
|
|
9367
|
+
"aria-label": ariaLabel,
|
|
9368
|
+
"aria-labelledby": ariaLabelledBy,
|
|
9369
|
+
className,
|
|
9370
|
+
onClick: (e) => e.stopPropagation(),
|
|
9371
|
+
style: {
|
|
9372
|
+
background: `var(${CSS_VAR.surface})`,
|
|
9373
|
+
color: `var(${CSS_VAR.text})`,
|
|
9374
|
+
borderRadius: `var(${CSS_VAR.radius}, 16px)`,
|
|
9375
|
+
padding: 28,
|
|
9376
|
+
maxWidth: 440,
|
|
9377
|
+
width: "100%",
|
|
9378
|
+
boxShadow: "0 1px 3px rgba(10,19,32,.08)",
|
|
9379
|
+
boxSizing: "border-box",
|
|
9380
|
+
...style
|
|
9381
|
+
},
|
|
9382
|
+
children
|
|
9266
9383
|
}
|
|
9267
|
-
|
|
9268
|
-
|
|
9269
|
-
|
|
9270
|
-
|
|
9271
|
-
|
|
9272
|
-
|
|
9273
|
-
|
|
9384
|
+
)
|
|
9385
|
+
}
|
|
9386
|
+
);
|
|
9387
|
+
}
|
|
9388
|
+
const NON_TERMINAL_STATUSES = /* @__PURE__ */ new Set(["connected", "heartbeat", "processing"]);
|
|
9389
|
+
const DEFAULT_TIMEOUT_MS = 31e4;
|
|
9390
|
+
const DEFAULT_MAX_RECONNECTS = 5;
|
|
9391
|
+
const RECONNECT_BASE_DELAY_MS = 500;
|
|
9392
|
+
const RECONNECT_MAX_DELAY_MS = 8e3;
|
|
9393
|
+
function delay(ms, signal) {
|
|
9394
|
+
return new Promise((resolve) => {
|
|
9395
|
+
const id = setTimeout(resolve, ms);
|
|
9396
|
+
signal == null ? void 0 : signal.addEventListener(
|
|
9397
|
+
"abort",
|
|
9398
|
+
() => {
|
|
9399
|
+
clearTimeout(id);
|
|
9400
|
+
resolve();
|
|
9401
|
+
},
|
|
9402
|
+
{ once: true }
|
|
9403
|
+
);
|
|
9404
|
+
});
|
|
9405
|
+
}
|
|
9406
|
+
async function consumeSseStream(options) {
|
|
9407
|
+
const {
|
|
9408
|
+
requestTicket,
|
|
9409
|
+
buildUrl,
|
|
9410
|
+
classify,
|
|
9411
|
+
timeoutMs = DEFAULT_TIMEOUT_MS,
|
|
9412
|
+
maxReconnects = DEFAULT_MAX_RECONNECTS,
|
|
9413
|
+
signal,
|
|
9414
|
+
eventSourceFactory,
|
|
9415
|
+
onProgress
|
|
9416
|
+
} = options;
|
|
9417
|
+
const makeEventSource = eventSourceFactory ?? ((url) => {
|
|
9418
|
+
const Ctor = globalThis.EventSource;
|
|
9419
|
+
if (!Ctor) {
|
|
9420
|
+
throw new NeoFaceError(
|
|
9421
|
+
"EventSource indisponível neste ambiente",
|
|
9422
|
+
ErrorType.INITIALIZATION_ERROR
|
|
9423
|
+
);
|
|
9424
|
+
}
|
|
9425
|
+
return new Ctor(url);
|
|
9426
|
+
});
|
|
9427
|
+
const startedAt = Date.now();
|
|
9428
|
+
let reconnects = 0;
|
|
9429
|
+
for (; ; ) {
|
|
9430
|
+
if (signal == null ? void 0 : signal.aborted) {
|
|
9431
|
+
throw new NeoFaceError("Fluxo cancelado", ErrorType.UNKNOWN);
|
|
9432
|
+
}
|
|
9433
|
+
const remaining = timeoutMs - (Date.now() - startedAt);
|
|
9434
|
+
if (remaining <= 0) {
|
|
9435
|
+
throw new NeoFaceError("Tempo esgotado aguardando resposta", ErrorType.NETWORK);
|
|
9436
|
+
}
|
|
9437
|
+
const ticket = await requestTicket();
|
|
9438
|
+
const outcome = await new Promise((resolve, reject) => {
|
|
9439
|
+
let source;
|
|
9440
|
+
try {
|
|
9441
|
+
source = makeEventSource(buildUrl(ticket));
|
|
9442
|
+
} catch (err) {
|
|
9443
|
+
reject(err);
|
|
9444
|
+
return;
|
|
9445
|
+
}
|
|
9446
|
+
let settled = false;
|
|
9447
|
+
let timerId;
|
|
9448
|
+
let onAbort;
|
|
9449
|
+
const cleanup = () => {
|
|
9450
|
+
if (timerId !== void 0) clearTimeout(timerId);
|
|
9451
|
+
if (onAbort) signal == null ? void 0 : signal.removeEventListener("abort", onAbort);
|
|
9452
|
+
source.close();
|
|
9453
|
+
};
|
|
9454
|
+
timerId = setTimeout(() => {
|
|
9455
|
+
if (settled) return;
|
|
9456
|
+
settled = true;
|
|
9457
|
+
cleanup();
|
|
9458
|
+
reject(new NeoFaceError("Tempo esgotado aguardando resposta", ErrorType.NETWORK));
|
|
9459
|
+
}, remaining);
|
|
9460
|
+
onAbort = () => {
|
|
9461
|
+
if (settled) return;
|
|
9462
|
+
settled = true;
|
|
9463
|
+
cleanup();
|
|
9464
|
+
reject(new NeoFaceError("Fluxo cancelado", ErrorType.UNKNOWN));
|
|
9465
|
+
};
|
|
9466
|
+
signal == null ? void 0 : signal.addEventListener("abort", onAbort, { once: true });
|
|
9467
|
+
source.onmessage = (event) => {
|
|
9468
|
+
if (settled) return;
|
|
9469
|
+
let frame;
|
|
9470
|
+
try {
|
|
9471
|
+
frame = JSON.parse(event.data);
|
|
9472
|
+
} catch {
|
|
9473
|
+
return;
|
|
9274
9474
|
}
|
|
9275
|
-
|
|
9276
|
-
|
|
9277
|
-
|
|
9278
|
-
inset: 0;
|
|
9279
|
-
width: 100%;
|
|
9280
|
-
height: 100%;
|
|
9281
|
-
pointer-events: none;
|
|
9282
|
-
z-index: 2;
|
|
9475
|
+
if (frame.status && NON_TERMINAL_STATUSES.has(frame.status)) {
|
|
9476
|
+
if (onProgress) onProgress(frame);
|
|
9477
|
+
return;
|
|
9283
9478
|
}
|
|
9284
|
-
|
|
9285
|
-
.
|
|
9286
|
-
|
|
9479
|
+
const verdict = classify(frame);
|
|
9480
|
+
if (verdict.kind === "pending") {
|
|
9481
|
+
if (onProgress) onProgress(frame);
|
|
9482
|
+
return;
|
|
9483
|
+
}
|
|
9484
|
+
settled = true;
|
|
9485
|
+
cleanup();
|
|
9486
|
+
resolve({ type: "settled", verdict });
|
|
9487
|
+
};
|
|
9488
|
+
source.onerror = () => {
|
|
9489
|
+
if (settled) return;
|
|
9490
|
+
settled = true;
|
|
9491
|
+
cleanup();
|
|
9492
|
+
resolve({ type: "transport" });
|
|
9493
|
+
};
|
|
9494
|
+
});
|
|
9495
|
+
if (outcome.type === "settled") {
|
|
9496
|
+
const { verdict } = outcome;
|
|
9497
|
+
if (verdict.kind === "resolve") return verdict.value;
|
|
9498
|
+
throw verdict.error;
|
|
9499
|
+
}
|
|
9500
|
+
reconnects += 1;
|
|
9501
|
+
if (reconnects > maxReconnects) {
|
|
9502
|
+
throw new NeoFaceError(
|
|
9503
|
+
`Conexão perdida após ${maxReconnects} tentativas de reconexão`,
|
|
9504
|
+
ErrorType.NETWORK
|
|
9505
|
+
);
|
|
9506
|
+
}
|
|
9507
|
+
const backoff = Math.min(
|
|
9508
|
+
RECONNECT_BASE_DELAY_MS * 2 ** (reconnects - 1),
|
|
9509
|
+
RECONNECT_MAX_DELAY_MS
|
|
9510
|
+
);
|
|
9511
|
+
await delay(backoff, signal);
|
|
9512
|
+
}
|
|
9513
|
+
}
|
|
9514
|
+
const BASE_STYLE = {
|
|
9515
|
+
minHeight: 44,
|
|
9516
|
+
minWidth: 44,
|
|
9517
|
+
padding: "12px 20px",
|
|
9518
|
+
borderRadius: 16,
|
|
9519
|
+
border: "none",
|
|
9520
|
+
fontSize: 15,
|
|
9521
|
+
fontWeight: 600,
|
|
9522
|
+
fontFamily: "inherit",
|
|
9523
|
+
cursor: "pointer",
|
|
9524
|
+
transition: "background 120ms ease-out",
|
|
9525
|
+
display: "inline-flex",
|
|
9526
|
+
alignItems: "center",
|
|
9527
|
+
justifyContent: "center",
|
|
9528
|
+
gap: 8
|
|
9529
|
+
};
|
|
9530
|
+
const Button = forwardRef(
|
|
9531
|
+
({ variant = "primary", style, type = "button", ...rest }, ref) => {
|
|
9532
|
+
const variantStyle = variant === "primary" ? {
|
|
9533
|
+
background: `var(${CSS_VAR.action})`,
|
|
9534
|
+
color: `var(${CSS_VAR.actionText})`
|
|
9535
|
+
} : variant === "secondary" ? {
|
|
9536
|
+
background: `var(${CSS_VAR.surfaceMuted})`,
|
|
9537
|
+
color: `var(${CSS_VAR.text})`
|
|
9538
|
+
} : {
|
|
9539
|
+
background: "transparent",
|
|
9540
|
+
color: `var(${CSS_VAR.textMuted})`
|
|
9541
|
+
};
|
|
9542
|
+
return (
|
|
9543
|
+
// eslint-disable-next-line react/button-has-type
|
|
9544
|
+
/* @__PURE__ */ jsx(
|
|
9545
|
+
"button",
|
|
9546
|
+
{
|
|
9547
|
+
ref,
|
|
9548
|
+
type,
|
|
9549
|
+
...rest,
|
|
9550
|
+
style: { ...BASE_STYLE, ...variantStyle, ...style }
|
|
9551
|
+
}
|
|
9552
|
+
)
|
|
9553
|
+
);
|
|
9554
|
+
}
|
|
9555
|
+
);
|
|
9556
|
+
Button.displayName = "Button";
|
|
9557
|
+
function StatusPill({ tone, children, icon, className }) {
|
|
9558
|
+
const palette = SEMANTIC[tone];
|
|
9559
|
+
return /* @__PURE__ */ jsxs(
|
|
9560
|
+
"span",
|
|
9561
|
+
{
|
|
9562
|
+
className,
|
|
9563
|
+
style: {
|
|
9564
|
+
display: "inline-flex",
|
|
9565
|
+
alignItems: "center",
|
|
9566
|
+
gap: 6,
|
|
9567
|
+
padding: "4px 10px",
|
|
9568
|
+
borderRadius: 9999,
|
|
9569
|
+
background: palette.bg,
|
|
9570
|
+
color: palette.fg,
|
|
9571
|
+
fontSize: 13,
|
|
9572
|
+
fontWeight: 600,
|
|
9573
|
+
fontFamily: "inherit",
|
|
9574
|
+
lineHeight: 1.3
|
|
9575
|
+
},
|
|
9576
|
+
children: [
|
|
9577
|
+
icon,
|
|
9578
|
+
children
|
|
9579
|
+
]
|
|
9580
|
+
}
|
|
9581
|
+
);
|
|
9582
|
+
}
|
|
9583
|
+
const STYLE_ID$2 = "neofaceid-awaiting-push-styles";
|
|
9584
|
+
const CSS$1 = `
|
|
9585
|
+
.neofaceid-root .nfid-push {
|
|
9586
|
+
display: flex; flex-direction: column; align-items: center; text-align: center; gap: 10px;
|
|
9587
|
+
padding: 8px 8px 4px;
|
|
9588
|
+
}
|
|
9589
|
+
.neofaceid-root .nfid-push h2 {
|
|
9590
|
+
margin: 6px 0 0; font-size: 20px; font-weight: 700; color: var(--nfid-text); line-height: 1.25;
|
|
9591
|
+
letter-spacing: -0.015em;
|
|
9592
|
+
}
|
|
9593
|
+
.neofaceid-root .nfid-push p {
|
|
9594
|
+
margin: 0; font-size: 14px; color: var(--nfid-text-muted); line-height: 1.5;
|
|
9595
|
+
}
|
|
9596
|
+
.neofaceid-root .nfid-push-phone-icon {
|
|
9597
|
+
width: 56px; height: 56px; color: var(--nfid-action);
|
|
9598
|
+
}
|
|
9599
|
+
.neofaceid-root .nfid-push-code {
|
|
9600
|
+
display: flex; flex-direction: column; align-items: center; gap: 6px;
|
|
9601
|
+
margin-top: 14px; padding: 16px 28px;
|
|
9602
|
+
background: var(--nfid-surface-muted); border-radius: 16px; width: 100%;
|
|
9603
|
+
}
|
|
9604
|
+
.neofaceid-root .nfid-push-code-label {
|
|
9605
|
+
font-size: 11px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase;
|
|
9606
|
+
color: var(--nfid-text-subtle);
|
|
9607
|
+
}
|
|
9608
|
+
.neofaceid-root .nfid-push-code-value {
|
|
9609
|
+
font-size: 52px; font-weight: 800; line-height: 1; letter-spacing: 0.08em;
|
|
9610
|
+
color: var(--nfid-text); font-variant-numeric: tabular-nums;
|
|
9611
|
+
}
|
|
9612
|
+
.neofaceid-root .nfid-push-countdown {
|
|
9613
|
+
font-size: 13px; color: var(--nfid-text-muted); font-variant-numeric: tabular-nums;
|
|
9614
|
+
margin-top: 12px;
|
|
9615
|
+
}
|
|
9616
|
+
.neofaceid-root .nfid-push-actions {
|
|
9617
|
+
display: flex; flex-direction: column; gap: 10px; width: 100%; margin-top: 16px;
|
|
9618
|
+
}
|
|
9619
|
+
.neofaceid-root .nfid-push-footer {
|
|
9620
|
+
display: flex; justify-content: center; margin-top: 16px; padding-top: 12px;
|
|
9621
|
+
border-top: 1px solid var(--nfid-line);
|
|
9622
|
+
width: 100%;
|
|
9623
|
+
}
|
|
9624
|
+
.neofaceid-root .nfid-push-pulse {
|
|
9625
|
+
animation: nfidPushPulse 1.8s ease-in-out infinite;
|
|
9626
|
+
}
|
|
9627
|
+
@keyframes nfidPushPulse {
|
|
9628
|
+
0%, 100% { opacity: 1; }
|
|
9629
|
+
50% { opacity: 0.45; }
|
|
9630
|
+
}
|
|
9631
|
+
@media (prefers-reduced-motion: reduce) {
|
|
9632
|
+
.neofaceid-root .nfid-push-pulse { animation: none; }
|
|
9633
|
+
}
|
|
9634
|
+
`;
|
|
9635
|
+
function formatRemaining(seconds) {
|
|
9636
|
+
const safe = Math.max(0, seconds);
|
|
9637
|
+
const mm = Math.floor(safe / 60);
|
|
9638
|
+
const ss = safe % 60;
|
|
9639
|
+
return `${mm}:${String(ss).padStart(2, "0")}`;
|
|
9640
|
+
}
|
|
9641
|
+
function AwaitingPushView({
|
|
9642
|
+
appName,
|
|
9643
|
+
numericCode,
|
|
9644
|
+
remainingSeconds,
|
|
9645
|
+
onCancel
|
|
9646
|
+
}) {
|
|
9647
|
+
useEffect(() => {
|
|
9648
|
+
injectThemeStyles();
|
|
9649
|
+
injectScopedStyles(STYLE_ID$2, CSS$1);
|
|
9650
|
+
}, []);
|
|
9651
|
+
return /* @__PURE__ */ jsxs("div", { className: "nfid-push", role: "status", "aria-live": "polite", children: [
|
|
9652
|
+
/* @__PURE__ */ jsx(StatusPill, { tone: "attention", children: "Aguardando confirmação" }),
|
|
9653
|
+
/* @__PURE__ */ jsxs(
|
|
9654
|
+
"svg",
|
|
9655
|
+
{
|
|
9656
|
+
className: "nfid-push-phone-icon nfid-push-pulse",
|
|
9657
|
+
viewBox: "0 0 24 24",
|
|
9658
|
+
fill: "none",
|
|
9659
|
+
stroke: "currentColor",
|
|
9660
|
+
strokeWidth: "1.75",
|
|
9661
|
+
strokeLinecap: "round",
|
|
9662
|
+
strokeLinejoin: "round",
|
|
9663
|
+
"aria-hidden": "true",
|
|
9664
|
+
children: [
|
|
9665
|
+
/* @__PURE__ */ jsx("rect", { x: "6", y: "2", width: "12", height: "20", rx: "3" }),
|
|
9666
|
+
/* @__PURE__ */ jsx("path", { d: "M11 18h2" })
|
|
9667
|
+
]
|
|
9668
|
+
}
|
|
9669
|
+
),
|
|
9670
|
+
/* @__PURE__ */ jsx("h2", { children: "Confirme no seu celular" }),
|
|
9671
|
+
/* @__PURE__ */ jsxs("p", { children: [
|
|
9672
|
+
"Enviamos um pedido de confirmação para o seu aparelho. Abra o NeoFaceID Push e confirme com o seu rosto para continuar no ",
|
|
9673
|
+
appName,
|
|
9674
|
+
"."
|
|
9675
|
+
] }),
|
|
9676
|
+
numericCode && /* @__PURE__ */ jsxs("div", { className: "nfid-push-code", children: [
|
|
9677
|
+
/* @__PURE__ */ jsx("span", { className: "nfid-push-code-label", children: "Digite este número no celular" }),
|
|
9678
|
+
/* @__PURE__ */ jsx(
|
|
9679
|
+
"span",
|
|
9680
|
+
{
|
|
9681
|
+
className: "nfid-push-code-value",
|
|
9682
|
+
"aria-label": `Código de confirmação: ${numericCode.split("").join(" ")}`,
|
|
9683
|
+
children: numericCode
|
|
9684
|
+
}
|
|
9685
|
+
)
|
|
9686
|
+
] }),
|
|
9687
|
+
/* @__PURE__ */ jsxs("p", { className: "nfid-push-countdown", children: [
|
|
9688
|
+
"Expira em ",
|
|
9689
|
+
formatRemaining(remainingSeconds)
|
|
9690
|
+
] }),
|
|
9691
|
+
/* @__PURE__ */ jsx("div", { className: "nfid-push-actions", children: /* @__PURE__ */ jsx(Button, { variant: "ghost", onClick: onCancel, children: "Cancelar" }) }),
|
|
9692
|
+
/* @__PURE__ */ jsx("div", { className: "nfid-push-footer", children: /* @__PURE__ */ jsx(BrandFooter, {}) })
|
|
9693
|
+
] });
|
|
9694
|
+
}
|
|
9695
|
+
function PushExpiredView({ onFallback, onCancel }) {
|
|
9696
|
+
useEffect(() => {
|
|
9697
|
+
injectThemeStyles();
|
|
9698
|
+
injectScopedStyles(STYLE_ID$2, CSS$1);
|
|
9699
|
+
}, []);
|
|
9700
|
+
return /* @__PURE__ */ jsxs("div", { className: "nfid-push", role: "alert", "aria-live": "assertive", children: [
|
|
9701
|
+
/* @__PURE__ */ jsxs(
|
|
9702
|
+
"svg",
|
|
9703
|
+
{
|
|
9704
|
+
className: "nfid-push-phone-icon",
|
|
9705
|
+
viewBox: "0 0 24 24",
|
|
9706
|
+
fill: "none",
|
|
9707
|
+
stroke: "currentColor",
|
|
9708
|
+
strokeWidth: "1.75",
|
|
9709
|
+
strokeLinecap: "round",
|
|
9710
|
+
strokeLinejoin: "round",
|
|
9711
|
+
"aria-hidden": "true",
|
|
9712
|
+
style: { color: "var(--nfid-text-muted)" },
|
|
9713
|
+
children: [
|
|
9714
|
+
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "9" }),
|
|
9715
|
+
/* @__PURE__ */ jsx("path", { d: "M12 7v5l3 2" })
|
|
9716
|
+
]
|
|
9717
|
+
}
|
|
9718
|
+
),
|
|
9719
|
+
/* @__PURE__ */ jsx("h2", { children: "O tempo esgotou" }),
|
|
9720
|
+
/* @__PURE__ */ jsx("p", { children: "Não recebemos a confirmação do seu celular a tempo." }),
|
|
9721
|
+
/* @__PURE__ */ jsx("div", { className: "nfid-push-actions", children: onFallback ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
9722
|
+
/* @__PURE__ */ jsx(Button, { variant: "primary", onClick: onFallback, children: "Entrar de outro jeito" }),
|
|
9723
|
+
/* @__PURE__ */ jsx(Button, { variant: "ghost", onClick: onCancel, children: "Agora não" })
|
|
9724
|
+
] }) : /* @__PURE__ */ jsx(Button, { variant: "primary", onClick: onCancel, children: "Entendi" }) }),
|
|
9725
|
+
/* @__PURE__ */ jsx("div", { className: "nfid-push-footer", children: /* @__PURE__ */ jsx(BrandFooter, {}) })
|
|
9726
|
+
] });
|
|
9727
|
+
}
|
|
9728
|
+
function PushDeniedView({ appName, onCancel }) {
|
|
9729
|
+
useEffect(() => {
|
|
9730
|
+
injectThemeStyles();
|
|
9731
|
+
injectScopedStyles(STYLE_ID$2, CSS$1);
|
|
9732
|
+
}, []);
|
|
9733
|
+
return /* @__PURE__ */ jsxs("div", { className: "nfid-push", role: "alert", "aria-live": "assertive", children: [
|
|
9734
|
+
/* @__PURE__ */ jsxs(
|
|
9735
|
+
"svg",
|
|
9736
|
+
{
|
|
9737
|
+
className: "nfid-push-phone-icon",
|
|
9738
|
+
viewBox: "0 0 24 24",
|
|
9739
|
+
fill: "none",
|
|
9740
|
+
stroke: "currentColor",
|
|
9741
|
+
strokeWidth: "1.75",
|
|
9742
|
+
strokeLinecap: "round",
|
|
9743
|
+
strokeLinejoin: "round",
|
|
9744
|
+
"aria-hidden": "true",
|
|
9745
|
+
style: { color: "#D64545" },
|
|
9746
|
+
children: [
|
|
9747
|
+
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "9" }),
|
|
9748
|
+
/* @__PURE__ */ jsx("path", { d: "M15 9l-6 6M9 9l6 6" })
|
|
9749
|
+
]
|
|
9750
|
+
}
|
|
9751
|
+
),
|
|
9752
|
+
/* @__PURE__ */ jsx("h2", { children: "Confirmação recusada" }),
|
|
9753
|
+
/* @__PURE__ */ jsxs("p", { children: [
|
|
9754
|
+
"O pedido foi recusado no celular. Se não foi você, procure o suporte do ",
|
|
9755
|
+
appName,
|
|
9756
|
+
"."
|
|
9757
|
+
] }),
|
|
9758
|
+
/* @__PURE__ */ jsx("div", { className: "nfid-push-actions", children: /* @__PURE__ */ jsx(Button, { variant: "primary", onClick: onCancel, children: "Entendi" }) }),
|
|
9759
|
+
/* @__PURE__ */ jsx("div", { className: "nfid-push-footer", children: /* @__PURE__ */ jsx(BrandFooter, {}) })
|
|
9760
|
+
] });
|
|
9761
|
+
}
|
|
9762
|
+
const CONTAINER_ID = "neofaceid-push-approval-container";
|
|
9763
|
+
function classifyAuthorizationFrame(frame) {
|
|
9764
|
+
var _a2, _b;
|
|
9765
|
+
switch (frame.status) {
|
|
9766
|
+
case "approved":
|
|
9767
|
+
case "success":
|
|
9768
|
+
return { kind: "resolve", value: { status: "approved", data: frame.data ?? {} } };
|
|
9769
|
+
case "denied":
|
|
9770
|
+
return {
|
|
9771
|
+
kind: "resolve",
|
|
9772
|
+
value: { status: "denied", reason: ((_a2 = frame.data) == null ? void 0 : _a2.reason) ?? frame.message }
|
|
9773
|
+
};
|
|
9774
|
+
case "expired":
|
|
9775
|
+
return { kind: "resolve", value: { status: "expired" } };
|
|
9776
|
+
case "failed":
|
|
9777
|
+
case "error":
|
|
9778
|
+
return {
|
|
9779
|
+
kind: "reject",
|
|
9780
|
+
error: new NeoFaceError(
|
|
9781
|
+
frame.message ?? ((_b = frame.data) == null ? void 0 : _b.message) ?? "Falha na confirmação",
|
|
9782
|
+
ErrorType.API_ERROR
|
|
9783
|
+
)
|
|
9784
|
+
};
|
|
9785
|
+
default:
|
|
9786
|
+
return { kind: "pending" };
|
|
9787
|
+
}
|
|
9788
|
+
}
|
|
9789
|
+
function PushApprovalModal({
|
|
9790
|
+
requestId,
|
|
9791
|
+
applicationToken,
|
|
9792
|
+
expiresIn,
|
|
9793
|
+
numericCode,
|
|
9794
|
+
appName,
|
|
9795
|
+
onFallback,
|
|
9796
|
+
onSettle
|
|
9797
|
+
}) {
|
|
9798
|
+
const headerAppName = appName ?? getAppName() ?? "sua aplicação";
|
|
9799
|
+
const [remaining, setRemaining] = useState(expiresIn);
|
|
9800
|
+
const [phase, setPhase] = useState({ kind: "waiting" });
|
|
9801
|
+
useEffect(() => {
|
|
9802
|
+
if (phase.kind !== "waiting") return void 0;
|
|
9803
|
+
const id = setInterval(() => {
|
|
9804
|
+
setRemaining((r) => r > 0 ? r - 1 : 0);
|
|
9805
|
+
}, 1e3);
|
|
9806
|
+
return () => clearInterval(id);
|
|
9807
|
+
}, [phase.kind]);
|
|
9808
|
+
useEffect(() => {
|
|
9809
|
+
const controller = new AbortController();
|
|
9810
|
+
let done = false;
|
|
9811
|
+
const base = getBaseUrl();
|
|
9812
|
+
const ticketUrl = `${base}/api/v1/authorization/events/${encodeURIComponent(requestId)}/ticket/`;
|
|
9813
|
+
consumeSseStream({
|
|
9814
|
+
signal: controller.signal,
|
|
9815
|
+
timeoutMs: (expiresIn + 30) * 1e3,
|
|
9816
|
+
requestTicket: async () => {
|
|
9817
|
+
var _a2;
|
|
9818
|
+
const res = await fetch(ticketUrl, {
|
|
9819
|
+
method: "POST",
|
|
9820
|
+
headers: { "Content-Type": "application/json", "X-App-Token": applicationToken }
|
|
9821
|
+
});
|
|
9822
|
+
if (!res.ok) {
|
|
9823
|
+
throw new NeoFaceError(
|
|
9824
|
+
`Falha ao abrir canal de confirmação: ${res.status}`,
|
|
9825
|
+
res.status === 401 || res.status === 403 ? ErrorType.INVALID_TOKEN : ErrorType.NETWORK
|
|
9826
|
+
);
|
|
9827
|
+
}
|
|
9828
|
+
const body = await res.json();
|
|
9829
|
+
const ticket = ((_a2 = body == null ? void 0 : body.data) == null ? void 0 : _a2.ticket) ?? (body == null ? void 0 : body.ticket);
|
|
9830
|
+
if (!ticket) {
|
|
9831
|
+
throw new NeoFaceError("Canal de confirmação sem ticket", ErrorType.API_ERROR);
|
|
9832
|
+
}
|
|
9833
|
+
return ticket;
|
|
9834
|
+
},
|
|
9835
|
+
buildUrl: (ticket) => `${base}/api/v1/authorization/events/${encodeURIComponent(requestId)}/?ticket=${encodeURIComponent(ticket)}`,
|
|
9836
|
+
classify: classifyAuthorizationFrame
|
|
9837
|
+
}).then((outcome) => {
|
|
9838
|
+
if (done) return;
|
|
9839
|
+
done = true;
|
|
9840
|
+
if (outcome.status === "denied") {
|
|
9841
|
+
setPhase({ kind: "denied" });
|
|
9842
|
+
return;
|
|
9843
|
+
}
|
|
9844
|
+
if (outcome.status === "expired") {
|
|
9845
|
+
setPhase({ kind: "expired" });
|
|
9846
|
+
return;
|
|
9847
|
+
}
|
|
9848
|
+
onSettle(outcome);
|
|
9849
|
+
}).catch(() => {
|
|
9850
|
+
if (done || controller.signal.aborted) return;
|
|
9851
|
+
done = true;
|
|
9852
|
+
setPhase({ kind: "expired" });
|
|
9853
|
+
});
|
|
9854
|
+
return () => {
|
|
9855
|
+
done = true;
|
|
9856
|
+
controller.abort();
|
|
9857
|
+
};
|
|
9858
|
+
}, [requestId]);
|
|
9859
|
+
if (phase.kind === "denied") {
|
|
9860
|
+
return /* @__PURE__ */ jsx(Sheet, { open: true, dismissOnOverlay: false, ariaLabel: "Confirmação recusada", children: /* @__PURE__ */ jsx(PushDeniedView, { appName: headerAppName, onCancel: () => onSettle({ status: "denied" }) }) });
|
|
9861
|
+
}
|
|
9862
|
+
if (phase.kind === "expired") {
|
|
9863
|
+
return /* @__PURE__ */ jsx(Sheet, { open: true, dismissOnOverlay: false, ariaLabel: "Tempo esgotado", children: /* @__PURE__ */ jsx(
|
|
9864
|
+
PushExpiredView,
|
|
9865
|
+
{
|
|
9866
|
+
onFallback: onFallback ? () => {
|
|
9867
|
+
onFallback();
|
|
9868
|
+
onSettle({ status: "expired" });
|
|
9869
|
+
} : void 0,
|
|
9870
|
+
onCancel: () => onSettle({ status: "expired" })
|
|
9871
|
+
}
|
|
9872
|
+
) });
|
|
9873
|
+
}
|
|
9874
|
+
return /* @__PURE__ */ jsx(Sheet, { open: true, dismissOnOverlay: false, ariaLabel: "Aguardando confirmação no celular", children: /* @__PURE__ */ jsx(
|
|
9875
|
+
AwaitingPushView,
|
|
9876
|
+
{
|
|
9877
|
+
appName: headerAppName,
|
|
9878
|
+
numericCode,
|
|
9879
|
+
remainingSeconds: remaining,
|
|
9880
|
+
onCancel: () => onSettle({ status: "cancelled" })
|
|
9881
|
+
}
|
|
9882
|
+
) });
|
|
9883
|
+
}
|
|
9884
|
+
function awaitPushApproval(options) {
|
|
9885
|
+
return new Promise((resolve) => {
|
|
9886
|
+
const container = document.createElement("div");
|
|
9887
|
+
container.id = CONTAINER_ID;
|
|
9888
|
+
document.body.appendChild(container);
|
|
9889
|
+
const root = createRoot(container);
|
|
9890
|
+
const settle = (outcome) => {
|
|
9891
|
+
root.unmount();
|
|
9892
|
+
if (document.body.contains(container)) document.body.removeChild(container);
|
|
9893
|
+
resolve(outcome);
|
|
9894
|
+
};
|
|
9895
|
+
root.render(/* @__PURE__ */ jsx(PushApprovalModal, { ...options, onSettle: settle }));
|
|
9896
|
+
});
|
|
9897
|
+
}
|
|
9898
|
+
function evaluateFacePosition(box, videoWidth, videoHeight) {
|
|
9899
|
+
if (!box || !videoWidth || !videoHeight) {
|
|
9900
|
+
return {
|
|
9901
|
+
faceState: "searching",
|
|
9902
|
+
instruction: "Centralize o rosto"
|
|
9903
|
+
};
|
|
9904
|
+
}
|
|
9905
|
+
const faceCenterX = box.x + box.width / 2;
|
|
9906
|
+
const faceCenterY = box.y + box.height / 2;
|
|
9907
|
+
const frameCenterX = videoWidth / 2;
|
|
9908
|
+
const frameCenterY = videoHeight / 2;
|
|
9909
|
+
const offsetX = Math.abs(faceCenterX - frameCenterX) / videoWidth;
|
|
9910
|
+
const offsetY = Math.abs(faceCenterY - frameCenterY) / videoHeight;
|
|
9911
|
+
const faceArea = box.width * box.height;
|
|
9912
|
+
const frameArea = videoWidth * videoHeight;
|
|
9913
|
+
const faceAreaRatio = faceArea / frameArea;
|
|
9914
|
+
if (faceAreaRatio < 0.08) {
|
|
9915
|
+
return {
|
|
9916
|
+
faceState: "too-far",
|
|
9917
|
+
instruction: "Aproxime-se"
|
|
9918
|
+
};
|
|
9919
|
+
}
|
|
9920
|
+
if (faceAreaRatio > 0.45) {
|
|
9921
|
+
return {
|
|
9922
|
+
faceState: "too-close",
|
|
9923
|
+
instruction: "Afaste-se"
|
|
9924
|
+
};
|
|
9925
|
+
}
|
|
9926
|
+
if (offsetX > 0.18 || offsetY > 0.18) {
|
|
9927
|
+
return {
|
|
9928
|
+
faceState: "off-center",
|
|
9929
|
+
instruction: "Centralize o rosto"
|
|
9930
|
+
};
|
|
9931
|
+
}
|
|
9932
|
+
return {
|
|
9933
|
+
faceState: "centered",
|
|
9934
|
+
instruction: "Perfeito, mantenha"
|
|
9935
|
+
};
|
|
9936
|
+
}
|
|
9937
|
+
function showCameraOvalGuideModal(initialOptions = {}) {
|
|
9938
|
+
const overlayDiv = document.createElement("div");
|
|
9939
|
+
overlayDiv.className = "neofaceid-camera-oval-guide-overlay-root";
|
|
9940
|
+
Object.assign(overlayDiv.style, {
|
|
9941
|
+
position: "fixed",
|
|
9942
|
+
top: "0",
|
|
9943
|
+
left: "0",
|
|
9944
|
+
width: "100vw",
|
|
9945
|
+
height: "100vh",
|
|
9946
|
+
backgroundColor: "rgba(0, 0, 0, 0.85)",
|
|
9947
|
+
backdropFilter: "blur(8px)",
|
|
9948
|
+
zIndex: "99999",
|
|
9949
|
+
display: "flex",
|
|
9950
|
+
flexDirection: "column",
|
|
9951
|
+
alignItems: "center",
|
|
9952
|
+
justifyContent: "center"
|
|
9953
|
+
});
|
|
9954
|
+
document.body.appendChild(overlayDiv);
|
|
9955
|
+
let root = createRoot(overlayDiv);
|
|
9956
|
+
let currentStream = initialOptions.stream || null;
|
|
9957
|
+
let currentFaceState = initialOptions.faceState || "searching";
|
|
9958
|
+
let currentInstruction = initialOptions.instruction || "Centralize o rosto";
|
|
9959
|
+
const renderModal = (stream, faceState, instruction) => {
|
|
9960
|
+
if (!root) return;
|
|
9961
|
+
root.render(
|
|
9962
|
+
/* @__PURE__ */ jsxs("div", { style: { position: "relative", width: "100%", height: "100%", display: "flex", alignItems: "center", justifyContent: "center" }, children: [
|
|
9963
|
+
initialOptions.onCancel && /* @__PURE__ */ jsx(
|
|
9964
|
+
"button",
|
|
9965
|
+
{
|
|
9966
|
+
onClick: () => {
|
|
9967
|
+
var _a2;
|
|
9968
|
+
handle.close();
|
|
9969
|
+
(_a2 = initialOptions.onCancel) == null ? void 0 : _a2.call(initialOptions);
|
|
9970
|
+
},
|
|
9971
|
+
style: {
|
|
9972
|
+
position: "absolute",
|
|
9973
|
+
top: "20px",
|
|
9974
|
+
right: "20px",
|
|
9975
|
+
background: "rgba(255, 255, 255, 0.2)",
|
|
9976
|
+
border: "none",
|
|
9977
|
+
color: "#fff",
|
|
9978
|
+
fontSize: "24px",
|
|
9979
|
+
width: "40px",
|
|
9980
|
+
height: "40px",
|
|
9981
|
+
borderRadius: "50%",
|
|
9982
|
+
cursor: "pointer",
|
|
9983
|
+
zIndex: 10,
|
|
9984
|
+
display: "flex",
|
|
9985
|
+
alignItems: "center",
|
|
9986
|
+
justifyContent: "center"
|
|
9987
|
+
},
|
|
9988
|
+
"aria-label": "Cancelar",
|
|
9989
|
+
children: "✕"
|
|
9990
|
+
}
|
|
9991
|
+
),
|
|
9992
|
+
/* @__PURE__ */ jsx(
|
|
9993
|
+
CameraOvalGuide,
|
|
9994
|
+
{
|
|
9995
|
+
stream,
|
|
9996
|
+
faceState,
|
|
9997
|
+
instruction
|
|
9998
|
+
}
|
|
9999
|
+
)
|
|
10000
|
+
] })
|
|
10001
|
+
);
|
|
10002
|
+
};
|
|
10003
|
+
renderModal(currentStream, currentFaceState, currentInstruction);
|
|
10004
|
+
const handle = {
|
|
10005
|
+
update: (stream, faceState, instruction) => {
|
|
10006
|
+
currentStream = stream;
|
|
10007
|
+
currentFaceState = faceState;
|
|
10008
|
+
currentInstruction = instruction;
|
|
10009
|
+
renderModal(stream, faceState, instruction);
|
|
10010
|
+
},
|
|
10011
|
+
close: () => {
|
|
10012
|
+
if (root) {
|
|
10013
|
+
root.unmount();
|
|
10014
|
+
root = null;
|
|
10015
|
+
}
|
|
10016
|
+
if (overlayDiv.parentElement) {
|
|
10017
|
+
overlayDiv.parentElement.removeChild(overlayDiv);
|
|
10018
|
+
}
|
|
10019
|
+
}
|
|
10020
|
+
};
|
|
10021
|
+
return handle;
|
|
10022
|
+
}
|
|
10023
|
+
function getHaloStyles(state) {
|
|
10024
|
+
switch (state) {
|
|
10025
|
+
case "centered":
|
|
10026
|
+
return {
|
|
10027
|
+
borderColor: "#0E9F6E",
|
|
10028
|
+
boxShadow: "0 0 0 4px rgba(14, 159, 110, 0.8), 0 0 45px rgba(14, 159, 110, 0.45)",
|
|
10029
|
+
svgStroke: "#0E9F6E",
|
|
10030
|
+
badgeBg: "rgba(14, 159, 110, 0.95)",
|
|
10031
|
+
badgeColor: "#FFFFFF"
|
|
10032
|
+
};
|
|
10033
|
+
case "too-far":
|
|
10034
|
+
case "too-close":
|
|
10035
|
+
case "off-center":
|
|
10036
|
+
return {
|
|
10037
|
+
borderColor: "#F59E0B",
|
|
10038
|
+
boxShadow: "0 0 0 4px rgba(245, 158, 11, 0.7), 0 0 35px rgba(245, 158, 11, 0.35)",
|
|
10039
|
+
svgStroke: "#F59E0B",
|
|
10040
|
+
badgeBg: "rgba(245, 158, 11, 0.95)",
|
|
10041
|
+
badgeColor: "#1F2937"
|
|
10042
|
+
};
|
|
10043
|
+
case "searching":
|
|
10044
|
+
default:
|
|
10045
|
+
return {
|
|
10046
|
+
borderColor: "rgba(156, 163, 175, 0.5)",
|
|
10047
|
+
boxShadow: "0 0 0 4px rgba(156, 163, 175, 0.3), 0 0 20px rgba(156, 163, 175, 0.15)",
|
|
10048
|
+
svgStroke: "#9CA3AF",
|
|
10049
|
+
badgeBg: "rgba(55, 65, 81, 0.9)",
|
|
10050
|
+
badgeColor: "#FFFFFF"
|
|
10051
|
+
};
|
|
10052
|
+
}
|
|
10053
|
+
}
|
|
10054
|
+
function CameraOvalGuide({
|
|
10055
|
+
stream,
|
|
10056
|
+
faceState,
|
|
10057
|
+
instruction,
|
|
10058
|
+
className = "",
|
|
10059
|
+
style = {}
|
|
10060
|
+
}) {
|
|
10061
|
+
const videoRef = useRef(null);
|
|
10062
|
+
useEffect(() => {
|
|
10063
|
+
const videoEl = videoRef.current;
|
|
10064
|
+
if (!videoEl) return;
|
|
10065
|
+
if (stream) {
|
|
10066
|
+
videoEl.srcObject = stream;
|
|
10067
|
+
videoEl.play().catch(() => {
|
|
10068
|
+
});
|
|
10069
|
+
} else {
|
|
10070
|
+
videoEl.srcObject = null;
|
|
10071
|
+
}
|
|
10072
|
+
return () => {
|
|
10073
|
+
if (stream) {
|
|
10074
|
+
stream.getTracks().forEach((track) => track.stop());
|
|
10075
|
+
}
|
|
10076
|
+
if (videoEl) {
|
|
10077
|
+
videoEl.srcObject = null;
|
|
10078
|
+
}
|
|
10079
|
+
};
|
|
10080
|
+
}, [stream]);
|
|
10081
|
+
const halo = getHaloStyles(faceState);
|
|
10082
|
+
return /* @__PURE__ */ jsxs(
|
|
10083
|
+
"div",
|
|
10084
|
+
{
|
|
10085
|
+
className: `neofaceid-camera-oval-guide-container ${className}`,
|
|
10086
|
+
style: {
|
|
10087
|
+
display: "flex",
|
|
10088
|
+
flexDirection: "column",
|
|
10089
|
+
alignItems: "center",
|
|
10090
|
+
justifyContent: "center",
|
|
10091
|
+
position: "relative",
|
|
10092
|
+
width: "100%",
|
|
10093
|
+
maxHeight: "100%",
|
|
10094
|
+
padding: "16px",
|
|
10095
|
+
boxSizing: "border-box",
|
|
10096
|
+
...style
|
|
10097
|
+
},
|
|
10098
|
+
children: [
|
|
10099
|
+
/* @__PURE__ */ jsx("style", { children: `
|
|
10100
|
+
.neofaceid-oval-frame {
|
|
10101
|
+
width: 320px;
|
|
10102
|
+
height: 400px;
|
|
10103
|
+
border-radius: 50%;
|
|
10104
|
+
overflow: hidden;
|
|
10105
|
+
position: relative;
|
|
10106
|
+
background: #000000;
|
|
10107
|
+
transition: box-shadow 0.3s ease, border-color 0.3s ease;
|
|
10108
|
+
}
|
|
10109
|
+
|
|
10110
|
+
.neofaceid-oval-video {
|
|
10111
|
+
width: 100%;
|
|
10112
|
+
height: 100%;
|
|
10113
|
+
object-fit: cover;
|
|
10114
|
+
transform: scaleX(-1);
|
|
10115
|
+
display: block;
|
|
10116
|
+
}
|
|
10117
|
+
|
|
10118
|
+
.neofaceid-oval-svg-overlay {
|
|
10119
|
+
position: absolute;
|
|
10120
|
+
inset: 0;
|
|
10121
|
+
width: 100%;
|
|
10122
|
+
height: 100%;
|
|
10123
|
+
pointer-events: none;
|
|
10124
|
+
z-index: 2;
|
|
10125
|
+
}
|
|
10126
|
+
|
|
10127
|
+
.neofaceid-oval-instruction-badge {
|
|
10128
|
+
margin-top: 20px;
|
|
9287
10129
|
padding: 10px 20px;
|
|
9288
10130
|
border-radius: 20px;
|
|
9289
10131
|
font-size: 15px;
|
|
@@ -10789,7 +11631,6 @@ const CAMERA_READY_DELAY = 200;
|
|
|
10789
11631
|
const CAMERA_STABILITY_DELAY = 100;
|
|
10790
11632
|
const FACE_DETECTION_TIME = 5e3;
|
|
10791
11633
|
const DETECTION_INTERVAL = 100;
|
|
10792
|
-
const SUCCESS_DELAY = 200;
|
|
10793
11634
|
let modelsLoaded = false;
|
|
10794
11635
|
let modelsLoading = null;
|
|
10795
11636
|
async function preloadFaceDetectionModels() {
|
|
@@ -10946,14 +11787,13 @@ async function captureFaceSilently() {
|
|
|
10946
11787
|
});
|
|
10947
11788
|
});
|
|
10948
11789
|
}
|
|
10949
|
-
async function
|
|
11790
|
+
async function detectFaceWithPosition(video, stream, guideModal, maxTime = FACE_DETECTION_TIME, interval = DETECTION_INTERVAL) {
|
|
10950
11791
|
return new Promise((resolve) => {
|
|
10951
11792
|
let attempts = 0;
|
|
10952
11793
|
const maxAttempts = Math.ceil(maxTime / interval);
|
|
10953
11794
|
let timeoutId = null;
|
|
10954
11795
|
let isResolved = false;
|
|
10955
|
-
let
|
|
10956
|
-
const ATTEMPTS_BEFORE_WAITING = Math.ceil(3e3 / interval);
|
|
11796
|
+
let centeredDurationMs = 0;
|
|
10957
11797
|
const finish = (success) => {
|
|
10958
11798
|
if (isResolved) return;
|
|
10959
11799
|
isResolved = true;
|
|
@@ -10964,11 +11804,7 @@ async function detectFaceQuickly(video, maxTime = FACE_DETECTION_TIME, interval
|
|
|
10964
11804
|
if (isResolved) return;
|
|
10965
11805
|
attempts++;
|
|
10966
11806
|
if (!modelsLoaded) {
|
|
10967
|
-
|
|
10968
|
-
overlay.updateStatus("waiting-for-face");
|
|
10969
|
-
overlayShowingWaiting = true;
|
|
10970
|
-
console.log("⏳ Models not loaded - waiting for face...");
|
|
10971
|
-
}
|
|
11807
|
+
guideModal.update(stream, "searching", "Carregando modelos de detecção...");
|
|
10972
11808
|
if (attempts >= maxAttempts) {
|
|
10973
11809
|
finish(false);
|
|
10974
11810
|
return;
|
|
@@ -10981,33 +11817,29 @@ async function detectFaceQuickly(video, maxTime = FACE_DETECTION_TIME, interval
|
|
|
10981
11817
|
video,
|
|
10982
11818
|
new faceapi.TinyFaceDetectorOptions({ inputSize: 160, scoreThreshold: 0.3 })
|
|
10983
11819
|
);
|
|
10984
|
-
|
|
10985
|
-
|
|
10986
|
-
|
|
10987
|
-
|
|
10988
|
-
|
|
11820
|
+
const { faceState, instruction } = evaluateFacePosition(
|
|
11821
|
+
detection ? detection.box : null,
|
|
11822
|
+
video.videoWidth,
|
|
11823
|
+
video.videoHeight
|
|
11824
|
+
);
|
|
11825
|
+
guideModal.update(stream, faceState, instruction);
|
|
11826
|
+
if (faceState === "centered") {
|
|
11827
|
+
centeredDurationMs += interval;
|
|
11828
|
+
if (centeredDurationMs >= 1e3) {
|
|
11829
|
+
console.log("✅ Rosto mantido centralizado por 1s consecutivo");
|
|
11830
|
+
finish(true);
|
|
11831
|
+
return;
|
|
10989
11832
|
}
|
|
10990
|
-
|
|
10991
|
-
|
|
10992
|
-
return;
|
|
10993
|
-
}
|
|
10994
|
-
if (overlay && !overlayShowingWaiting && attempts >= ATTEMPTS_BEFORE_WAITING) {
|
|
10995
|
-
overlay.updateStatus("waiting-for-face");
|
|
10996
|
-
overlayShowingWaiting = true;
|
|
10997
|
-
console.log("⏳ Waiting for face...");
|
|
11833
|
+
} else {
|
|
11834
|
+
centeredDurationMs = 0;
|
|
10998
11835
|
}
|
|
10999
11836
|
if (attempts >= maxAttempts) {
|
|
11000
|
-
console.warn("⏱️ Face detection timeout - no face found");
|
|
11001
11837
|
finish(false);
|
|
11002
11838
|
return;
|
|
11003
11839
|
}
|
|
11004
11840
|
timeoutId = window.setTimeout(checkFace, interval);
|
|
11005
11841
|
} catch (error) {
|
|
11006
|
-
console.error("❌
|
|
11007
|
-
if (overlay && !overlayShowingWaiting && attempts >= ATTEMPTS_BEFORE_WAITING) {
|
|
11008
|
-
overlay.updateStatus("waiting-for-face");
|
|
11009
|
-
overlayShowingWaiting = true;
|
|
11010
|
-
}
|
|
11842
|
+
console.error("❌ Erro na detecção facial:", error);
|
|
11011
11843
|
if (attempts >= maxAttempts) {
|
|
11012
11844
|
finish(false);
|
|
11013
11845
|
return;
|
|
@@ -11017,19 +11849,19 @@ async function detectFaceQuickly(video, maxTime = FACE_DETECTION_TIME, interval
|
|
|
11017
11849
|
};
|
|
11018
11850
|
window.setTimeout(() => {
|
|
11019
11851
|
if (!isResolved) {
|
|
11020
|
-
console.warn("⏱️ Face detection safety timeout reached");
|
|
11021
11852
|
finish(false);
|
|
11022
11853
|
}
|
|
11023
11854
|
}, maxTime + 500);
|
|
11024
11855
|
checkFace();
|
|
11025
11856
|
});
|
|
11026
11857
|
}
|
|
11027
|
-
async function attemptLogin(applicationToken,
|
|
11028
|
-
|
|
11029
|
-
|
|
11030
|
-
|
|
11031
|
-
|
|
11032
|
-
|
|
11858
|
+
async function attemptLogin(applicationToken, fastMode = false, isRetry = false, onCancel) {
|
|
11859
|
+
const guideModal = showCameraOvalGuideModal({
|
|
11860
|
+
stream: null,
|
|
11861
|
+
faceState: "searching",
|
|
11862
|
+
instruction: "Iniciando câmera...",
|
|
11863
|
+
onCancel
|
|
11864
|
+
});
|
|
11033
11865
|
const video = document.createElement("video");
|
|
11034
11866
|
video.style.position = "fixed";
|
|
11035
11867
|
video.style.top = "-9999px";
|
|
@@ -11060,6 +11892,7 @@ async function attemptLogin(applicationToken, overlay, fastMode = false, isRetry
|
|
|
11060
11892
|
});
|
|
11061
11893
|
}
|
|
11062
11894
|
video.srcObject = stream;
|
|
11895
|
+
guideModal.update(stream, "searching", "Centralize o rosto");
|
|
11063
11896
|
await new Promise((resolve) => {
|
|
11064
11897
|
if (video.readyState >= 1) {
|
|
11065
11898
|
resolve();
|
|
@@ -11088,18 +11921,19 @@ async function attemptLogin(applicationToken, overlay, fastMode = false, isRetry
|
|
|
11088
11921
|
checkSize();
|
|
11089
11922
|
}
|
|
11090
11923
|
});
|
|
11091
|
-
overlay.updateStatus("detecting");
|
|
11092
11924
|
await new Promise((resolve) => setTimeout(resolve, CAMERA_STABILITY_DELAY));
|
|
11093
11925
|
let faceDetected = true;
|
|
11094
11926
|
if (!fastMode) {
|
|
11095
|
-
faceDetected = await
|
|
11927
|
+
faceDetected = await detectFaceWithPosition(
|
|
11096
11928
|
video,
|
|
11929
|
+
stream,
|
|
11930
|
+
guideModal,
|
|
11097
11931
|
FACE_DETECTION_TIME,
|
|
11098
|
-
DETECTION_INTERVAL
|
|
11099
|
-
overlay
|
|
11932
|
+
DETECTION_INTERVAL
|
|
11100
11933
|
);
|
|
11101
11934
|
}
|
|
11102
11935
|
if (!faceDetected) {
|
|
11936
|
+
guideModal.close();
|
|
11103
11937
|
if (stream) {
|
|
11104
11938
|
stream.getTracks().forEach((track) => track.stop());
|
|
11105
11939
|
}
|
|
@@ -11107,16 +11941,17 @@ async function attemptLogin(applicationToken, overlay, fastMode = false, isRetry
|
|
|
11107
11941
|
video.parentElement.removeChild(video);
|
|
11108
11942
|
}
|
|
11109
11943
|
throw new NeoFaceError(
|
|
11110
|
-
"Nenhum rosto detectado. Por favor,
|
|
11944
|
+
"Nenhum rosto centralizado detectado. Por favor, tente novamente.",
|
|
11111
11945
|
ErrorType.VALIDATION_ERROR
|
|
11112
11946
|
);
|
|
11113
11947
|
}
|
|
11114
|
-
|
|
11948
|
+
guideModal.update(stream, "centered", "Capturando imagem...");
|
|
11115
11949
|
const canvas = document.createElement("canvas");
|
|
11116
11950
|
canvas.width = video.videoWidth;
|
|
11117
11951
|
canvas.height = video.videoHeight;
|
|
11118
11952
|
const ctx = canvas.getContext("2d");
|
|
11119
11953
|
if (!ctx) {
|
|
11954
|
+
guideModal.close();
|
|
11120
11955
|
if (stream) {
|
|
11121
11956
|
stream.getTracks().forEach((track) => track.stop());
|
|
11122
11957
|
}
|
|
@@ -11126,12 +11961,6 @@ async function attemptLogin(applicationToken, overlay, fastMode = false, isRetry
|
|
|
11126
11961
|
throw new NeoFaceError("Erro ao capturar imagem", ErrorType.CAPTURE_ERROR);
|
|
11127
11962
|
}
|
|
11128
11963
|
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
|
|
11129
|
-
if (stream) {
|
|
11130
|
-
stream.getTracks().forEach((track) => track.stop());
|
|
11131
|
-
}
|
|
11132
|
-
if (video.parentElement) {
|
|
11133
|
-
video.parentElement.removeChild(video);
|
|
11134
|
-
}
|
|
11135
11964
|
const imageBlob = await new Promise((resolve, reject) => {
|
|
11136
11965
|
canvas.toBlob(
|
|
11137
11966
|
(blob) => {
|
|
@@ -11146,13 +11975,21 @@ async function attemptLogin(applicationToken, overlay, fastMode = false, isRetry
|
|
|
11146
11975
|
0.85
|
|
11147
11976
|
);
|
|
11148
11977
|
});
|
|
11149
|
-
|
|
11978
|
+
guideModal.update(stream, "centered", "Verificando com o servidor...");
|
|
11150
11979
|
const result = await loginWithBiometric(imageBlob, applicationToken);
|
|
11980
|
+
guideModal.close();
|
|
11981
|
+
if (stream) {
|
|
11982
|
+
stream.getTracks().forEach((track) => track.stop());
|
|
11983
|
+
}
|
|
11984
|
+
if (video.parentElement) {
|
|
11985
|
+
video.parentElement.removeChild(video);
|
|
11986
|
+
}
|
|
11151
11987
|
if (!result.success) {
|
|
11152
11988
|
throw new NeoFaceError("Login falhou", ErrorType.LOGIN_FAILED);
|
|
11153
11989
|
}
|
|
11154
11990
|
return result;
|
|
11155
11991
|
} catch (error) {
|
|
11992
|
+
guideModal.close();
|
|
11156
11993
|
if (stream) {
|
|
11157
11994
|
stream.getTracks().forEach((track) => track.stop());
|
|
11158
11995
|
}
|
|
@@ -11177,7 +12014,6 @@ async function executeBiometricLoginFlow(options) {
|
|
|
11177
12014
|
onCancel,
|
|
11178
12015
|
fastMode = false
|
|
11179
12016
|
} = options;
|
|
11180
|
-
const overlay = new BiometricStatusOverlay();
|
|
11181
12017
|
const fallbackPrompt = new FallbackPrompt();
|
|
11182
12018
|
let attempts = 0;
|
|
11183
12019
|
let lastError;
|
|
@@ -11185,34 +12021,26 @@ async function executeBiometricLoginFlow(options) {
|
|
|
11185
12021
|
preloadFaceDetectionModels().catch(() => {
|
|
11186
12022
|
});
|
|
11187
12023
|
}
|
|
11188
|
-
overlay.show("preparing");
|
|
11189
12024
|
const tryLogin = async () => {
|
|
11190
12025
|
try {
|
|
11191
12026
|
attempts++;
|
|
11192
|
-
const result = await attemptLogin(applicationToken,
|
|
11193
|
-
|
|
11194
|
-
setTimeout(() => {
|
|
11195
|
-
overlay.close();
|
|
11196
|
-
onSuccess(result);
|
|
11197
|
-
}, SUCCESS_DELAY);
|
|
12027
|
+
const result = await attemptLogin(applicationToken, fastMode, attempts > 1, onCancel);
|
|
12028
|
+
onSuccess(result);
|
|
11198
12029
|
} catch (error) {
|
|
11199
12030
|
lastError = error instanceof NeoFaceError ? error : new NeoFaceError(
|
|
11200
12031
|
error instanceof Error ? error.message : "Erro desconhecido",
|
|
11201
12032
|
ErrorType.UNKNOWN
|
|
11202
12033
|
);
|
|
11203
|
-
overlay.updateStatus("error");
|
|
11204
12034
|
if (attempts < MAX_ATTEMPTS$1) {
|
|
11205
12035
|
setTimeout(() => {
|
|
11206
12036
|
tryLogin();
|
|
11207
12037
|
}, RETRY_DELAY);
|
|
11208
12038
|
} else {
|
|
11209
12039
|
setTimeout(() => {
|
|
11210
|
-
overlay.close();
|
|
11211
12040
|
fallbackPrompt.show(
|
|
11212
12041
|
lastError,
|
|
11213
12042
|
() => {
|
|
11214
12043
|
attempts = 0;
|
|
11215
|
-
overlay.show("preparing");
|
|
11216
12044
|
setTimeout(() => tryLogin(), RETRY_DELAY);
|
|
11217
12045
|
},
|
|
11218
12046
|
() => {
|
|
@@ -11234,9 +12062,7 @@ async function executeBiometricLoginFlow(options) {
|
|
|
11234
12062
|
}
|
|
11235
12063
|
}
|
|
11236
12064
|
};
|
|
11237
|
-
|
|
11238
|
-
tryLogin();
|
|
11239
|
-
}
|
|
12065
|
+
tryLogin();
|
|
11240
12066
|
}
|
|
11241
12067
|
const biometricLoginFlow = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
11242
12068
|
__proto__: null,
|
|
@@ -11245,6 +12071,25 @@ const biometricLoginFlow = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.
|
|
|
11245
12071
|
preloadFaceDetectionModels
|
|
11246
12072
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
11247
12073
|
const CONSENT_DENIED_MESSAGE$1 = "Consentimento recusado pelo usuário.";
|
|
12074
|
+
function openPasswordFallback(options) {
|
|
12075
|
+
if (!getAutoFallback().toPassword) {
|
|
12076
|
+
options.onError(
|
|
12077
|
+
new NeoFaceError(
|
|
12078
|
+
"Biometria não reconhecida e a queda automática para senha está desligada.",
|
|
12079
|
+
ErrorType.LOGIN_FAILED
|
|
12080
|
+
)
|
|
12081
|
+
);
|
|
12082
|
+
return;
|
|
12083
|
+
}
|
|
12084
|
+
const fallbackOptions = {
|
|
12085
|
+
applicationToken: options.applicationToken,
|
|
12086
|
+
onSuccess: options.onSuccess,
|
|
12087
|
+
onError: options.onError,
|
|
12088
|
+
title: "Login Alternativo",
|
|
12089
|
+
subtitle: "Biometria não reconhecida. Por favor, informe email e senha."
|
|
12090
|
+
};
|
|
12091
|
+
new EmailPasswordModal(fallbackOptions).open();
|
|
12092
|
+
}
|
|
11248
12093
|
async function startFaceLogin(options) {
|
|
11249
12094
|
const consentAccepted = await requestConsent({
|
|
11250
12095
|
appName: options.appName,
|
|
@@ -11259,17 +12104,7 @@ async function startFaceLogin(options) {
|
|
|
11259
12104
|
applicationToken: options.applicationToken,
|
|
11260
12105
|
onSuccess: options.onSuccess,
|
|
11261
12106
|
onError: options.onError,
|
|
11262
|
-
onFallbackRequest: options.onFallbackRequest || (() =>
|
|
11263
|
-
const fallbackOptions = {
|
|
11264
|
-
applicationToken: options.applicationToken,
|
|
11265
|
-
onSuccess: options.onSuccess,
|
|
11266
|
-
onError: options.onError,
|
|
11267
|
-
title: "Login Alternativo",
|
|
11268
|
-
subtitle: "Biometria não reconhecida. Por favor, informe email e senha."
|
|
11269
|
-
};
|
|
11270
|
-
const modal = new EmailPasswordModal(fallbackOptions);
|
|
11271
|
-
modal.open();
|
|
11272
|
-
}),
|
|
12107
|
+
onFallbackRequest: options.onFallbackRequest || (() => openPasswordFallback(options)),
|
|
11273
12108
|
onCancel: options.onCancel
|
|
11274
12109
|
});
|
|
11275
12110
|
} catch (error) {
|
|
@@ -12438,15 +13273,23 @@ const authorizeOperation = async (applicationToken, cpf, options) => {
|
|
|
12438
13273
|
resolve();
|
|
12439
13274
|
};
|
|
12440
13275
|
});
|
|
13276
|
+
const guideModal = showCameraOvalGuideModal({
|
|
13277
|
+
stream,
|
|
13278
|
+
faceState: "centered",
|
|
13279
|
+
instruction: PHOTO_INSTRUCTIONS[0]
|
|
13280
|
+
});
|
|
12441
13281
|
const canvas = document.createElement("canvas");
|
|
12442
13282
|
canvas.width = video.videoWidth;
|
|
12443
13283
|
canvas.height = video.videoHeight;
|
|
12444
13284
|
const ctx = canvas.getContext("2d");
|
|
12445
13285
|
if (!ctx) {
|
|
13286
|
+
guideModal.close();
|
|
13287
|
+
stream.getTracks().forEach((track) => track.stop());
|
|
12446
13288
|
throw new NeoFaceError("Failed to get canvas context", ErrorType.CAPTURE_ERROR);
|
|
12447
13289
|
}
|
|
12448
13290
|
for (let i = 0; i < TOTAL_PHOTOS; i++) {
|
|
12449
13291
|
const instruction = PHOTO_INSTRUCTIONS[i];
|
|
13292
|
+
guideModal.update(stream, "centered", instruction);
|
|
12450
13293
|
if (options == null ? void 0 : options.onProgress) {
|
|
12451
13294
|
options.onProgress(i + 1, TOTAL_PHOTOS, instruction);
|
|
12452
13295
|
}
|
|
@@ -12472,6 +13315,7 @@ const authorizeOperation = async (applicationToken, cpf, options) => {
|
|
|
12472
13315
|
options.onPhotoTaken(i + 1, blob);
|
|
12473
13316
|
}
|
|
12474
13317
|
}
|
|
13318
|
+
guideModal.close();
|
|
12475
13319
|
stream.getTracks().forEach((track) => track.stop());
|
|
12476
13320
|
const lastPhoto = capturedPhotos[TOTAL_PHOTOS - 1];
|
|
12477
13321
|
const sessionData = {
|
|
@@ -12519,110 +13363,6 @@ const authorizeOperation = async (applicationToken, cpf, options) => {
|
|
|
12519
13363
|
throw new NeoFaceError("Unknown error during authorization", ErrorType.UNKNOWN);
|
|
12520
13364
|
}
|
|
12521
13365
|
};
|
|
12522
|
-
function Sheet({
|
|
12523
|
-
open,
|
|
12524
|
-
onDismiss,
|
|
12525
|
-
dismissOnOverlay = true,
|
|
12526
|
-
ariaLabel,
|
|
12527
|
-
ariaLabelledBy,
|
|
12528
|
-
children,
|
|
12529
|
-
className,
|
|
12530
|
-
style
|
|
12531
|
-
}) {
|
|
12532
|
-
useEffect(() => {
|
|
12533
|
-
injectThemeStyles();
|
|
12534
|
-
}, []);
|
|
12535
|
-
if (!open) return null;
|
|
12536
|
-
const handleOverlay = () => {
|
|
12537
|
-
if (dismissOnOverlay && onDismiss) onDismiss();
|
|
12538
|
-
};
|
|
12539
|
-
return /* @__PURE__ */ jsx(
|
|
12540
|
-
"div",
|
|
12541
|
-
{
|
|
12542
|
-
className: "neofaceid-root",
|
|
12543
|
-
role: "presentation",
|
|
12544
|
-
style: {
|
|
12545
|
-
position: "fixed",
|
|
12546
|
-
inset: 0,
|
|
12547
|
-
zIndex: 10001,
|
|
12548
|
-
display: "flex",
|
|
12549
|
-
alignItems: "center",
|
|
12550
|
-
justifyContent: "center",
|
|
12551
|
-
padding: 20,
|
|
12552
|
-
background: `var(${CSS_VAR.overlay})`,
|
|
12553
|
-
backdropFilter: "blur(3px)",
|
|
12554
|
-
WebkitBackdropFilter: "blur(3px)"
|
|
12555
|
-
},
|
|
12556
|
-
onClick: handleOverlay,
|
|
12557
|
-
children: /* @__PURE__ */ jsx(
|
|
12558
|
-
"div",
|
|
12559
|
-
{
|
|
12560
|
-
role: "dialog",
|
|
12561
|
-
"aria-modal": "true",
|
|
12562
|
-
"aria-label": ariaLabel,
|
|
12563
|
-
"aria-labelledby": ariaLabelledBy,
|
|
12564
|
-
className,
|
|
12565
|
-
onClick: (e) => e.stopPropagation(),
|
|
12566
|
-
style: {
|
|
12567
|
-
background: `var(${CSS_VAR.surface})`,
|
|
12568
|
-
color: `var(${CSS_VAR.text})`,
|
|
12569
|
-
borderRadius: `var(${CSS_VAR.radius}, 16px)`,
|
|
12570
|
-
padding: 28,
|
|
12571
|
-
maxWidth: 440,
|
|
12572
|
-
width: "100%",
|
|
12573
|
-
boxShadow: "0 1px 3px rgba(10,19,32,.08)",
|
|
12574
|
-
boxSizing: "border-box",
|
|
12575
|
-
...style
|
|
12576
|
-
},
|
|
12577
|
-
children
|
|
12578
|
-
}
|
|
12579
|
-
)
|
|
12580
|
-
}
|
|
12581
|
-
);
|
|
12582
|
-
}
|
|
12583
|
-
const BASE_STYLE = {
|
|
12584
|
-
minHeight: 44,
|
|
12585
|
-
minWidth: 44,
|
|
12586
|
-
padding: "12px 20px",
|
|
12587
|
-
borderRadius: 16,
|
|
12588
|
-
border: "none",
|
|
12589
|
-
fontSize: 15,
|
|
12590
|
-
fontWeight: 600,
|
|
12591
|
-
fontFamily: "inherit",
|
|
12592
|
-
cursor: "pointer",
|
|
12593
|
-
transition: "background 120ms ease-out",
|
|
12594
|
-
display: "inline-flex",
|
|
12595
|
-
alignItems: "center",
|
|
12596
|
-
justifyContent: "center",
|
|
12597
|
-
gap: 8
|
|
12598
|
-
};
|
|
12599
|
-
const Button = forwardRef(
|
|
12600
|
-
({ variant = "primary", style, type = "button", ...rest }, ref) => {
|
|
12601
|
-
const variantStyle = variant === "primary" ? {
|
|
12602
|
-
background: `var(${CSS_VAR.action})`,
|
|
12603
|
-
color: `var(${CSS_VAR.actionText})`
|
|
12604
|
-
} : variant === "secondary" ? {
|
|
12605
|
-
background: `var(${CSS_VAR.surfaceMuted})`,
|
|
12606
|
-
color: `var(${CSS_VAR.text})`
|
|
12607
|
-
} : {
|
|
12608
|
-
background: "transparent",
|
|
12609
|
-
color: `var(${CSS_VAR.textMuted})`
|
|
12610
|
-
};
|
|
12611
|
-
return (
|
|
12612
|
-
// eslint-disable-next-line react/button-has-type
|
|
12613
|
-
/* @__PURE__ */ jsx(
|
|
12614
|
-
"button",
|
|
12615
|
-
{
|
|
12616
|
-
ref,
|
|
12617
|
-
type,
|
|
12618
|
-
...rest,
|
|
12619
|
-
style: { ...BASE_STYLE, ...variantStyle, ...style }
|
|
12620
|
-
}
|
|
12621
|
-
)
|
|
12622
|
-
);
|
|
12623
|
-
}
|
|
12624
|
-
);
|
|
12625
|
-
Button.displayName = "Button";
|
|
12626
13366
|
function FocusFrame({
|
|
12627
13367
|
size = 96,
|
|
12628
13368
|
color,
|
|
@@ -12850,32 +13590,6 @@ function pointsFor(g) {
|
|
|
12850
13590
|
return ["24 24", "24 24", "24 24"];
|
|
12851
13591
|
}
|
|
12852
13592
|
}
|
|
12853
|
-
function StatusPill({ tone, children, icon, className }) {
|
|
12854
|
-
const palette = SEMANTIC[tone];
|
|
12855
|
-
return /* @__PURE__ */ jsxs(
|
|
12856
|
-
"span",
|
|
12857
|
-
{
|
|
12858
|
-
className,
|
|
12859
|
-
style: {
|
|
12860
|
-
display: "inline-flex",
|
|
12861
|
-
alignItems: "center",
|
|
12862
|
-
gap: 6,
|
|
12863
|
-
padding: "4px 10px",
|
|
12864
|
-
borderRadius: 9999,
|
|
12865
|
-
background: palette.bg,
|
|
12866
|
-
color: palette.fg,
|
|
12867
|
-
fontSize: 13,
|
|
12868
|
-
fontWeight: 600,
|
|
12869
|
-
fontFamily: "inherit",
|
|
12870
|
-
lineHeight: 1.3
|
|
12871
|
-
},
|
|
12872
|
-
children: [
|
|
12873
|
-
icon,
|
|
12874
|
-
children
|
|
12875
|
-
]
|
|
12876
|
-
}
|
|
12877
|
-
);
|
|
12878
|
-
}
|
|
12879
13593
|
const DEFAULT = {
|
|
12880
13594
|
title: "Não deu certo desta vez",
|
|
12881
13595
|
hint: "Tente se posicionar em um ambiente mais estável.",
|
|
@@ -14646,15 +15360,18 @@ export {
|
|
|
14646
15360
|
VERSION,
|
|
14647
15361
|
authorize,
|
|
14648
15362
|
authorizeOperation,
|
|
15363
|
+
awaitPushApproval,
|
|
14649
15364
|
checkUserExistence,
|
|
14650
15365
|
clearConsentTrail,
|
|
14651
15366
|
completeOnboarding,
|
|
14652
15367
|
completeOnboardingWithData,
|
|
14653
15368
|
confirmPasswordReset,
|
|
15369
|
+
consumeSseStream,
|
|
14654
15370
|
detectBiometricType,
|
|
14655
15371
|
getAccent,
|
|
14656
15372
|
getAppName,
|
|
14657
15373
|
getApplicationToken,
|
|
15374
|
+
getAutoFallback,
|
|
14658
15375
|
getBaseUrl,
|
|
14659
15376
|
getCachedCaptureSession,
|
|
14660
15377
|
getConfig,
|
|
@@ -14679,10 +15396,12 @@ export {
|
|
|
14679
15396
|
recognizeBiometric,
|
|
14680
15397
|
recognizeByPurpose,
|
|
14681
15398
|
recordConsent,
|
|
15399
|
+
refreshSession,
|
|
14682
15400
|
registerBiometric,
|
|
14683
15401
|
registerPersonWithBiometric,
|
|
14684
15402
|
registerPersonWithoutFace,
|
|
14685
15403
|
requestConsent,
|
|
15404
|
+
requestDeviceEnrollmentToken,
|
|
14686
15405
|
requestLivenessChallenge,
|
|
14687
15406
|
requestLivenessChallengeWithSession,
|
|
14688
15407
|
requestPasswordReset,
|