@neofaceid/web-sdk 1.15.2 → 1.17.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.
@@ -1623,7 +1623,7 @@ const loginWithBiometric = async (image, applicationToken) => {
1623
1623
  }
1624
1624
  return {
1625
1625
  success: true,
1626
- accessToken: data.accessToken,
1626
+ accessToken: data.accessToken || data.access_token || "",
1627
1627
  alias: data.alias,
1628
1628
  user: {
1629
1629
  id: ((_a = data.user) == null ? void 0 : _a.id) || "",
@@ -1633,6 +1633,7 @@ const loginWithBiometric = async (image, applicationToken) => {
1633
1633
  active: ((_e = data.user) == null ? void 0 : _e.active) || false
1634
1634
  },
1635
1635
  person: data.person ? {
1636
+ id: data.person.id || "",
1636
1637
  name: data.person.name || "",
1637
1638
  birth_date: data.person.birth_date || ""
1638
1639
  } : void 0,
@@ -1838,7 +1839,8 @@ const registerPersonWithoutFace = async (personData, applicationToken, options)
1838
1839
  cpf: personData.cpf,
1839
1840
  email: personData.email,
1840
1841
  password: personData.password,
1841
- password_confirm: personData.password
1842
+ password_confirm: personData.password,
1843
+ is_pep: personData.is_pep ?? false
1842
1844
  };
1843
1845
  if (documentFrontBase64) {
1844
1846
  body.document_images = [
@@ -1879,6 +1881,43 @@ const registerPersonWithoutFace = async (personData, applicationToken, options)
1879
1881
  throw new NeoFaceError("Unknown error occurred", ErrorType.NETWORK);
1880
1882
  }
1881
1883
  };
1884
+ const checkUserExistence = async (params) => {
1885
+ const controller = createTimeoutController();
1886
+ const queryParams = new URLSearchParams();
1887
+ if (params.email) queryParams.append("email", params.email);
1888
+ if (params.cpf) queryParams.append("cpf", params.cpf);
1889
+ try {
1890
+ const response = await fetch(
1891
+ `${getApiBaseUrl()}/api/v1/verify/user/?${queryParams.toString()}`,
1892
+ {
1893
+ method: "GET",
1894
+ headers: {
1895
+ "Content-Type": "application/json"
1896
+ },
1897
+ signal: controller.signal
1898
+ }
1899
+ );
1900
+ if (!response.ok) {
1901
+ const errorData = await response.json().catch(() => ({}));
1902
+ throw new NeoFaceError(
1903
+ errorData.message || `Server returned status ${response.status}`,
1904
+ ErrorType.NETWORK
1905
+ );
1906
+ }
1907
+ return await response.json();
1908
+ } catch (error) {
1909
+ if (error instanceof Error) {
1910
+ if (error.name === "AbortError") {
1911
+ throw new NeoFaceError("Request timed out", ErrorType.NETWORK);
1912
+ }
1913
+ if (error instanceof NeoFaceError) {
1914
+ throw error;
1915
+ }
1916
+ throw new NeoFaceError(error.message, ErrorType.NETWORK);
1917
+ }
1918
+ throw new NeoFaceError("Unknown error occurred", ErrorType.NETWORK);
1919
+ }
1920
+ };
1882
1921
  const registerPersonWithBiometric = async (personData, facePhotos, applicationToken, options) => {
1883
1922
  var _a, _b, _c, _d, _e, _f, _g, _h;
1884
1923
  ensureSecureContext();
@@ -1934,7 +1973,8 @@ const registerPersonWithBiometric = async (personData, facePhotos, applicationTo
1934
1973
  email: personData.email,
1935
1974
  password: personData.password,
1936
1975
  password_confirm: personData.password,
1937
- face_photos: facePhotosBase64
1976
+ face_photos: facePhotosBase64,
1977
+ is_pep: personData.is_pep ?? false
1938
1978
  };
1939
1979
  if (documentFrontBase64) {
1940
1980
  body.document_images = [
@@ -2028,7 +2068,6 @@ const registerPersonWithBiometric = async (personData, facePhotos, applicationTo
2028
2068
  }
2029
2069
  };
2030
2070
  const loginWithEmail = async (email, password, applicationToken) => {
2031
- ensureSecureContext();
2032
2071
  const controller = createTimeoutController();
2033
2072
  try {
2034
2073
  const response = await fetch(`${getApiBaseUrl()}/api/v1/auth/login/`, {
@@ -2074,10 +2113,10 @@ const loginWithEmail = async (email, password, applicationToken) => {
2074
2113
  }
2075
2114
  };
2076
2115
  const identifyPerson = async (image, applicationToken) => {
2077
- var _a, _b;
2116
+ var _a, _b, _c, _d;
2078
2117
  ensureSecureContext();
2079
2118
  const controller = createTimeoutController();
2080
- const compressedImage = await compressImage(image);
2119
+ const compressedImage = await compressDocumentImage(image);
2081
2120
  const base64Image = await new Promise((resolve, reject) => {
2082
2121
  const reader = new FileReader();
2083
2122
  reader.onload = () => {
@@ -2088,7 +2127,7 @@ const identifyPerson = async (image, applicationToken) => {
2088
2127
  reader.readAsDataURL(compressedImage);
2089
2128
  });
2090
2129
  try {
2091
- const response = await fetch(`${getApiBaseUrl()}/api/v1/external/recognition/face/`, {
2130
+ const response = await fetch(`${getApiBaseUrl()}/api/v1/auth/recognition/face/external/`, {
2092
2131
  method: "POST",
2093
2132
  headers: {
2094
2133
  "Content-Type": "application/json",
@@ -2107,30 +2146,26 @@ const identifyPerson = async (image, applicationToken) => {
2107
2146
  throw new NeoFaceError(`Server returned status ${response.status}`, ErrorType.NETWORK);
2108
2147
  }
2109
2148
  const data = await response.json();
2149
+ if (response.status === 202 || data.data && data.data.task_id) {
2150
+ return {
2151
+ success: true,
2152
+ taskId: ((_a = data.data) == null ? void 0 : _a.task_id) || data.task_id,
2153
+ status: ((_b = data.data) == null ? void 0 : _b.status) || "processing",
2154
+ message: data.message || "Identification scheduled"
2155
+ };
2156
+ }
2110
2157
  if (!data.success) {
2111
2158
  throw new NeoFaceError(
2112
2159
  data.message || "Person identification failed",
2113
2160
  ErrorType.RECOGNITION_FAILED
2114
2161
  );
2115
2162
  }
2116
- const personName = ((_a = data.person) == null ? void 0 : _a.name) || "";
2117
- const birthDateStr = (_b = data.person) == null ? void 0 : _b.birth_date;
2118
- if (!personName) {
2119
- throw new NeoFaceError("Person name not found in response", ErrorType.PERSON_NOT_FOUND);
2120
- }
2121
- if (!birthDateStr) {
2122
- throw new NeoFaceError("Birth date not found in response", ErrorType.PERSON_NOT_FOUND);
2123
- }
2124
- const birthDate = new Date(birthDateStr);
2125
- const today = /* @__PURE__ */ new Date();
2126
- let age = today.getFullYear() - birthDate.getFullYear();
2127
- const monthDiff = today.getMonth() - birthDate.getMonth();
2128
- if (monthDiff < 0 || monthDiff === 0 && today.getDate() < birthDate.getDate()) {
2129
- age--;
2130
- }
2131
2163
  return {
2132
- name: personName,
2133
- age
2164
+ success: true,
2165
+ person: {
2166
+ name: ((_c = data.person) == null ? void 0 : _c.name) || "",
2167
+ birth_date: ((_d = data.person) == null ? void 0 : _d.birth_date) || ""
2168
+ }
2134
2169
  };
2135
2170
  } catch (error) {
2136
2171
  if (error instanceof Error) {
@@ -2564,6 +2599,135 @@ const registerDocumentByImage = async (personId, jwtToken, images) => {
2564
2599
  throw new NeoFaceError("Unknown error occurred", ErrorType.NETWORK_ERROR);
2565
2600
  }
2566
2601
  };
2602
+ const getTaskStatus = async (taskId) => {
2603
+ const controller = createTimeoutController();
2604
+ try {
2605
+ const response = await fetch(`${getApiBaseUrl()}/api/v1/tasks/status/?task_id=${taskId}`, {
2606
+ method: "GET",
2607
+ headers: {
2608
+ "Content-Type": "application/json"
2609
+ },
2610
+ signal: controller.signal
2611
+ });
2612
+ const data = await response.json();
2613
+ if (!response.ok) {
2614
+ throw new NeoFaceError(
2615
+ (data == null ? void 0 : data.message) || `API Error ${response.status}`,
2616
+ ErrorType.NETWORK_ERROR
2617
+ );
2618
+ }
2619
+ return {
2620
+ success: data.success,
2621
+ status: data.data.status,
2622
+ result: data.data.result,
2623
+ error: data.data.error
2624
+ };
2625
+ } catch (error) {
2626
+ if (error instanceof NeoFaceError) throw error;
2627
+ throw new NeoFaceError("Failed to fetch task status", ErrorType.NETWORK_ERROR);
2628
+ }
2629
+ };
2630
+ const identifyPersonAsync = async (image, applicationToken, options = {}) => {
2631
+ var _a, _b;
2632
+ const { maxRetries = 30, interval = 2e3 } = options;
2633
+ const initialResponse = await identifyPerson(image, applicationToken);
2634
+ if (initialResponse.person) {
2635
+ return {
2636
+ personFound: true,
2637
+ person: initialResponse.person
2638
+ };
2639
+ }
2640
+ const taskId = initialResponse.taskId;
2641
+ if (!taskId) {
2642
+ return { personFound: false };
2643
+ }
2644
+ for (let i = 0; i < maxRetries; i++) {
2645
+ const status = await getTaskStatus(taskId);
2646
+ if (status.status === "success") {
2647
+ if (status.result && status.result.success) {
2648
+ return {
2649
+ personFound: true,
2650
+ person: {
2651
+ name: ((_a = status.result.person) == null ? void 0 : _a.name) || "Pessoa identificada",
2652
+ birth_date: ((_b = status.result.person) == null ? void 0 : _b.birth_date) || ""
2653
+ }
2654
+ };
2655
+ }
2656
+ return { personFound: false };
2657
+ }
2658
+ if (status.status === "failure") {
2659
+ return { personFound: false };
2660
+ }
2661
+ await new Promise((resolve) => setTimeout(resolve, interval));
2662
+ }
2663
+ throw new NeoFaceError("Timed out waiting for identification", ErrorType.NETWORK_ERROR);
2664
+ };
2665
+ async function requestPasswordReset(email, applicationToken) {
2666
+ const baseUrl = getBaseUrl();
2667
+ const response = await fetch(`${baseUrl}/api/v1/user/password/reset/request/`, {
2668
+ method: "POST",
2669
+ headers: {
2670
+ "Content-Type": "application/json",
2671
+ "X-App-Token": applicationToken
2672
+ },
2673
+ body: JSON.stringify({ email })
2674
+ });
2675
+ if (!response.ok) {
2676
+ const errorData = await response.json();
2677
+ throw new NeoFaceError(
2678
+ errorData.message || "Erro ao solicitar recuperação de senha",
2679
+ ErrorType.API_ERROR
2680
+ );
2681
+ }
2682
+ return response.json();
2683
+ }
2684
+ async function confirmPasswordReset(token, new_password) {
2685
+ const baseUrl = getBaseUrl();
2686
+ const response = await fetch(`${baseUrl}/api/v1/user/password/reset/confirm/`, {
2687
+ method: "POST",
2688
+ headers: {
2689
+ "Content-Type": "application/json"
2690
+ },
2691
+ body: JSON.stringify({ token, new_password })
2692
+ });
2693
+ if (!response.ok) {
2694
+ const errorData = await response.json();
2695
+ throw new NeoFaceError(
2696
+ errorData.error || errorData.message || "Erro ao redefinir senha",
2697
+ ErrorType.API_ERROR
2698
+ );
2699
+ }
2700
+ return response.json();
2701
+ }
2702
+ const api = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
2703
+ __proto__: null,
2704
+ checkUserExistence,
2705
+ completeOnboarding,
2706
+ completeOnboardingWithData,
2707
+ confirmPasswordReset,
2708
+ getOnboardingDetails,
2709
+ getTaskStatus,
2710
+ identifyPerson,
2711
+ identifyPersonAsync,
2712
+ loginWithBiometric,
2713
+ loginWithEmail,
2714
+ pollTaskStatus,
2715
+ recognize,
2716
+ recognizeBiometric,
2717
+ recognizeByPurpose,
2718
+ recordFaceVideo,
2719
+ registerApplication,
2720
+ registerBiometric,
2721
+ registerDocumentByImage,
2722
+ registerPersonWithBiometric,
2723
+ registerPersonWithoutFace,
2724
+ requestPasswordReset,
2725
+ simpleIdentification,
2726
+ startProofOfLife,
2727
+ validateOnboardingToken,
2728
+ validateToken,
2729
+ videoToBase64
2730
+ }, Symbol.toStringTag, { value: "Module" }));
2567
2731
  const modalReducer$1 = (state, action) => {
2568
2732
  switch (action.type) {
2569
2733
  case "PERMISSION_GRANTED":
@@ -2857,6 +3021,336 @@ function FaceCaptureModal({ accessToken, onClose, onSuccess }) {
2857
3021
  ] })
2858
3022
  ] });
2859
3023
  }
3024
+ class ForgotPasswordModal {
3025
+ constructor(applicationToken) {
3026
+ __publicField(this, "applicationToken");
3027
+ __publicField(this, "modalElement", null);
3028
+ this.applicationToken = applicationToken;
3029
+ }
3030
+ open() {
3031
+ if (this.modalElement) return;
3032
+ this.addStyles();
3033
+ this.modalElement = document.createElement("div");
3034
+ this.modalElement.className = "neoface-forgot-modal";
3035
+ this.renderEmailForm();
3036
+ document.body.appendChild(this.modalElement);
3037
+ }
3038
+ close() {
3039
+ if (this.modalElement && document.body.contains(this.modalElement)) {
3040
+ document.body.removeChild(this.modalElement);
3041
+ this.modalElement = null;
3042
+ }
3043
+ }
3044
+ renderEmailForm() {
3045
+ if (!this.modalElement) return;
3046
+ this.modalElement.innerHTML = `
3047
+ <div class="neoface-forgot-overlay">
3048
+ <div class="neoface-forgot-content">
3049
+ <div class="neoface-forgot-icon">
3050
+ <svg viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
3051
+ <circle cx="32" cy="32" r="28" stroke="#7c3aed" stroke-width="3" fill="none"/>
3052
+ <rect x="22" y="28" width="20" height="16" rx="3" stroke="#7c3aed" stroke-width="2.5" fill="none"/>
3053
+ <path d="M26 28v-4a6 6 0 0 1 12 0v4" stroke="#7c3aed" stroke-width="2.5" stroke-linecap="round"/>
3054
+ <circle cx="32" cy="36" r="2" fill="#7c3aed"/>
3055
+ </svg>
3056
+ </div>
3057
+
3058
+ <h2 class="neoface-forgot-title">Recuperar senha</h2>
3059
+ <p class="neoface-forgot-subtitle">Informe seu email e enviaremos um link para redefinir sua senha.</p>
3060
+
3061
+ <div id="neoface-forgot-error" class="neoface-forgot-error" style="display:none"></div>
3062
+
3063
+ <form id="neoface-forgot-form">
3064
+ <input
3065
+ type="email"
3066
+ id="neoface-forgot-email"
3067
+ class="neoface-forgot-input"
3068
+ placeholder="seu@email.com"
3069
+ autocomplete="email"
3070
+ required
3071
+ />
3072
+ <button type="submit" class="neoface-forgot-btn-primary">
3073
+ Enviar link
3074
+ </button>
3075
+ </form>
3076
+
3077
+ <button class="neoface-forgot-btn-ghost neoface-forgot-back">
3078
+ Voltar
3079
+ </button>
3080
+
3081
+ <div class="neoface-forgot-branding">
3082
+ <img src="/logo-icone-no-background.png" alt="NeoFaceId" class="neoface-forgot-brand-logo" onerror="this.style.display='none'" />
3083
+ <span>NeoFaceId by</span>
3084
+ <span class="neoface-forgot-brand-name">OCTA</span>
3085
+ </div>
3086
+ </div>
3087
+ </div>
3088
+ `;
3089
+ const form = this.modalElement.querySelector("#neoface-forgot-form");
3090
+ form.addEventListener("submit", this.handleSubmit.bind(this));
3091
+ const backBtn = this.modalElement.querySelector(".neoface-forgot-back");
3092
+ backBtn.addEventListener("click", this.close.bind(this));
3093
+ }
3094
+ renderSuccess() {
3095
+ if (!this.modalElement) return;
3096
+ const content = this.modalElement.querySelector(".neoface-forgot-content");
3097
+ content.innerHTML = `
3098
+ <div class="neoface-forgot-success-icon">
3099
+ <svg viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
3100
+ <circle cx="32" cy="32" r="28" stroke="#10b981" stroke-width="3" fill="none"/>
3101
+ <path d="M20 32 L28 40 L44 24" stroke="#10b981" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
3102
+ </svg>
3103
+ </div>
3104
+
3105
+ <h2 class="neoface-forgot-title">Email enviado!</h2>
3106
+ <p class="neoface-forgot-subtitle">
3107
+ Verifique sua caixa de entrada e siga as instruções para redefinir sua senha.
3108
+ <br/><br/>
3109
+ <span style="color: rgba(255,255,255,0.5); font-size: 13px;">Não recebeu? Verifique também sua pasta de spam.</span>
3110
+ </p>
3111
+
3112
+ <button class="neoface-forgot-btn-primary neoface-forgot-close-success" style="margin-top: 8px;">
3113
+ Fechar
3114
+ </button>
3115
+
3116
+ <div class="neoface-forgot-branding">
3117
+ <img src="/logo-icone-no-background.png" alt="NeoFaceId" class="neoface-forgot-brand-logo" onerror="this.style.display='none'" />
3118
+ <span>NeoFaceId by</span>
3119
+ <span class="neoface-forgot-brand-name">OCTA</span>
3120
+ </div>
3121
+ `;
3122
+ const closeBtn = content.querySelector(".neoface-forgot-close-success");
3123
+ closeBtn.addEventListener("click", this.close.bind(this));
3124
+ }
3125
+ async handleSubmit(e) {
3126
+ var _a, _b, _c, _d;
3127
+ e.preventDefault();
3128
+ const emailInput = (_a = this.modalElement) == null ? void 0 : _a.querySelector(
3129
+ "#neoface-forgot-email"
3130
+ );
3131
+ const submitBtn = (_b = this.modalElement) == null ? void 0 : _b.querySelector(
3132
+ ".neoface-forgot-btn-primary"
3133
+ );
3134
+ const errorEl = (_c = this.modalElement) == null ? void 0 : _c.querySelector("#neoface-forgot-error");
3135
+ const email = (_d = emailInput == null ? void 0 : emailInput.value) == null ? void 0 : _d.trim();
3136
+ if (!email) return;
3137
+ submitBtn.disabled = true;
3138
+ submitBtn.textContent = "Enviando...";
3139
+ errorEl.style.display = "none";
3140
+ try {
3141
+ await requestPasswordReset(email, this.applicationToken);
3142
+ this.renderSuccess();
3143
+ } catch (error) {
3144
+ submitBtn.disabled = false;
3145
+ submitBtn.textContent = "Enviar link";
3146
+ errorEl.style.display = "block";
3147
+ errorEl.textContent = error instanceof NeoFaceError ? error.message : "Erro ao enviar email. Tente novamente.";
3148
+ }
3149
+ }
3150
+ addStyles() {
3151
+ const styleId = "neoface-forgot-password-modal-styles";
3152
+ if (document.getElementById(styleId)) return;
3153
+ const style = document.createElement("style");
3154
+ style.id = styleId;
3155
+ style.textContent = `
3156
+ .neoface-forgot-modal {
3157
+ position: fixed;
3158
+ top: 0;
3159
+ left: 0;
3160
+ width: 100%;
3161
+ height: 100%;
3162
+ z-index: 10003;
3163
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
3164
+ }
3165
+
3166
+ .neoface-forgot-overlay {
3167
+ position: absolute;
3168
+ inset: 0;
3169
+ background: rgba(0, 0, 0, 0.65);
3170
+ backdrop-filter: blur(8px);
3171
+ display: flex;
3172
+ align-items: center;
3173
+ justify-content: center;
3174
+ padding: 20px;
3175
+ animation: neoface-forgot-fadeIn 0.3s ease-out;
3176
+ }
3177
+
3178
+ @keyframes neoface-forgot-fadeIn {
3179
+ from { opacity: 0; }
3180
+ to { opacity: 1; }
3181
+ }
3182
+
3183
+ @keyframes neoface-forgot-slideUp {
3184
+ from { opacity: 0; transform: translateY(20px); }
3185
+ to { opacity: 1; transform: translateY(0); }
3186
+ }
3187
+
3188
+ .neoface-forgot-content {
3189
+ background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
3190
+ border-radius: 20px;
3191
+ padding: 32px;
3192
+ max-width: 400px;
3193
+ width: 100%;
3194
+ box-shadow: 0 24px 48px rgba(0, 0, 0, 0.4), 0 0 0 1px rgba(255, 255, 255, 0.1);
3195
+ animation: neoface-forgot-slideUp 0.4s ease-out;
3196
+ text-align: center;
3197
+ }
3198
+
3199
+ .neoface-forgot-icon {
3200
+ width: 64px;
3201
+ height: 64px;
3202
+ margin: 0 auto 20px;
3203
+ }
3204
+
3205
+ .neoface-forgot-success-icon {
3206
+ width: 64px;
3207
+ height: 64px;
3208
+ margin: 0 auto 20px;
3209
+ animation: neoface-forgot-scaleIn 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
3210
+ }
3211
+
3212
+ @keyframes neoface-forgot-scaleIn {
3213
+ 0% { transform: scale(0); opacity: 0; }
3214
+ 50% { transform: scale(1.1); }
3215
+ 100% { transform: scale(1); opacity: 1; }
3216
+ }
3217
+
3218
+ .neoface-forgot-title {
3219
+ font-size: 22px;
3220
+ font-weight: 700;
3221
+ color: white;
3222
+ margin: 0 0 10px 0;
3223
+ }
3224
+
3225
+ .neoface-forgot-subtitle {
3226
+ font-size: 15px;
3227
+ color: rgba(255, 255, 255, 0.7);
3228
+ margin: 0 0 24px 0;
3229
+ line-height: 1.5;
3230
+ }
3231
+
3232
+ .neoface-forgot-error {
3233
+ background: rgba(239, 68, 68, 0.15);
3234
+ border: 1px solid rgba(239, 68, 68, 0.4);
3235
+ color: #fca5a5;
3236
+ border-radius: 10px;
3237
+ padding: 10px 14px;
3238
+ font-size: 14px;
3239
+ margin-bottom: 16px;
3240
+ text-align: left;
3241
+ }
3242
+
3243
+ #neoface-forgot-form {
3244
+ display: flex;
3245
+ flex-direction: column;
3246
+ gap: 14px;
3247
+ margin-bottom: 12px;
3248
+ }
3249
+
3250
+ .neoface-forgot-input {
3251
+ width: 100%;
3252
+ padding: 14px 16px;
3253
+ border: 2px solid rgba(255, 255, 255, 0.2);
3254
+ border-radius: 12px;
3255
+ font-size: 15px;
3256
+ background: rgba(255, 255, 255, 0.08);
3257
+ color: white;
3258
+ font-family: inherit;
3259
+ transition: all 0.2s;
3260
+ box-sizing: border-box;
3261
+ }
3262
+
3263
+ .neoface-forgot-input::placeholder {
3264
+ color: rgba(255, 255, 255, 0.4);
3265
+ }
3266
+
3267
+ .neoface-forgot-input:focus {
3268
+ outline: none;
3269
+ border-color: #7c3aed;
3270
+ box-shadow: 0 0 0 3px rgba(124, 58, 237, 0.2);
3271
+ background: rgba(255, 255, 255, 0.12);
3272
+ }
3273
+
3274
+ .neoface-forgot-btn-primary {
3275
+ width: 100%;
3276
+ padding: 14px 24px;
3277
+ border-radius: 12px;
3278
+ border: none;
3279
+ background: linear-gradient(135deg, #7c3aed 0%, #6d28d9 100%);
3280
+ color: white;
3281
+ font-size: 16px;
3282
+ font-weight: 600;
3283
+ cursor: pointer;
3284
+ transition: all 0.2s;
3285
+ box-shadow: 0 4px 16px rgba(124, 58, 237, 0.3);
3286
+ font-family: inherit;
3287
+ }
3288
+
3289
+ .neoface-forgot-btn-primary:hover:not(:disabled) {
3290
+ transform: translateY(-2px);
3291
+ box-shadow: 0 8px 24px rgba(124, 58, 237, 0.4);
3292
+ }
3293
+
3294
+ .neoface-forgot-btn-primary:disabled {
3295
+ opacity: 0.6;
3296
+ cursor: not-allowed;
3297
+ }
3298
+
3299
+ .neoface-forgot-btn-ghost {
3300
+ background: transparent;
3301
+ border: none;
3302
+ color: rgba(255, 255, 255, 0.5);
3303
+ font-size: 14px;
3304
+ font-weight: 500;
3305
+ cursor: pointer;
3306
+ padding: 10px 16px;
3307
+ border-radius: 8px;
3308
+ transition: all 0.2s;
3309
+ font-family: inherit;
3310
+ width: 100%;
3311
+ }
3312
+
3313
+ .neoface-forgot-btn-ghost:hover {
3314
+ color: white;
3315
+ background: rgba(255, 255, 255, 0.05);
3316
+ }
3317
+
3318
+ .neoface-forgot-branding {
3319
+ display: flex;
3320
+ align-items: center;
3321
+ justify-content: center;
3322
+ gap: 6px;
3323
+ margin-top: 20px;
3324
+ color: rgba(255, 255, 255, 0.3);
3325
+ font-size: 12px;
3326
+ }
3327
+
3328
+ .neoface-forgot-brand-logo {
3329
+ width: 18px;
3330
+ height: 18px;
3331
+ object-fit: contain;
3332
+ opacity: 0.5;
3333
+ }
3334
+
3335
+ .neoface-forgot-brand-name {
3336
+ font-weight: 700;
3337
+ letter-spacing: 0.05em;
3338
+ }
3339
+
3340
+ @media (max-width: 640px) {
3341
+ .neoface-forgot-content {
3342
+ padding: 24px;
3343
+ border-radius: 16px;
3344
+ }
3345
+
3346
+ .neoface-forgot-title {
3347
+ font-size: 20px;
3348
+ }
3349
+ }
3350
+ `;
3351
+ document.head.appendChild(style);
3352
+ }
3353
+ }
2860
3354
  const modalReducer = (state, action) => {
2861
3355
  switch (action.type) {
2862
3356
  case "START_LIVENESS":
@@ -2891,10 +3385,10 @@ const modalReducer = (state, action) => {
2891
3385
  return state;
2892
3386
  case "CAMERA_LOADING":
2893
3387
  return { status: "camera-loading" };
2894
- case "START_PROCESSING":
2895
- return { status: "processing" };
2896
3388
  case "SUCCESS":
2897
3389
  return { status: "success" };
3390
+ case "DUPLICATE":
3391
+ return { status: "duplicate", personName: action.personName };
2898
3392
  case "ERROR":
2899
3393
  return { status: "error", message: action.message, retryable: action.retryable ?? true };
2900
3394
  case "RESET":
@@ -3364,7 +3858,24 @@ function BiometricRegistrationModal({
3364
3858
  );
3365
3859
  };
3366
3860
  const processRegistration = async (photos) => {
3861
+ var _a;
3367
3862
  try {
3863
+ dispatch({ type: "START_PROCESSING" });
3864
+ if (applicationToken && photos.length > 0) {
3865
+ try {
3866
+ const { identifyPersonAsync: identifyPersonAsync2 } = await Promise.resolve().then(() => api);
3867
+ const result2 = await identifyPersonAsync2(photos[0], applicationToken);
3868
+ if (result2.personFound) {
3869
+ dispatch({
3870
+ type: "DUPLICATE",
3871
+ personName: ((_a = result2.person) == null ? void 0 : _a.name) || "Pessoa identificada"
3872
+ });
3873
+ return;
3874
+ }
3875
+ } catch (idError) {
3876
+ console.warn("Erro silencioso na identificação preventiva:", idError);
3877
+ }
3878
+ }
3368
3879
  if (onPhotosCaptured) {
3369
3880
  dispatch({ type: "SUCCESS" });
3370
3881
  onPhotosCaptured(photos);
@@ -3520,6 +4031,75 @@ function BiometricRegistrationModal({
3520
4031
  /* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: onPhotosCaptured ? "Suas capturas faciais foram realizadas" : "Sua biometria foi registrada com sucesso" }),
3521
4032
  /* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: "primary-button", onClick: onClose, children: "Continuar" })
3522
4033
  ] });
4034
+ const renderDuplicate = () => {
4035
+ if (state.status !== "duplicate") return null;
4036
+ const greeting = state.personName && state.personName !== "Pessoa identificada" ? `Olá, ${state.personName.split(" ")[0]}!` : "Olá!";
4037
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "result-container duplicate scale-in", children: [
4038
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { style: { marginTop: "0px" }, children: greeting }),
4039
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { style: { marginBottom: "32px", fontSize: "15px" }, children: "Identificamos seu cadastro biométrico em nossa rede. Você já faz parte da NeoFaceId!" }),
4040
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "button-group-vertical", children: [
4041
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
4042
+ "button",
4043
+ {
4044
+ className: "primary-button",
4045
+ onClick: () => {
4046
+ onClose();
4047
+ window.location.href = "/";
4048
+ },
4049
+ children: "Ir para o Login"
4050
+ }
4051
+ ),
4052
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
4053
+ "button",
4054
+ {
4055
+ className: "secondary-button",
4056
+ style: { marginTop: "12px" },
4057
+ onClick: () => {
4058
+ onClose();
4059
+ new ForgotPasswordModal(applicationToken ?? "").open();
4060
+ },
4061
+ children: "Esqueci minha senha"
4062
+ }
4063
+ ),
4064
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "support-section", children: [
4065
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: "Não reconhece esta conta?" }),
4066
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
4067
+ "button",
4068
+ {
4069
+ className: "ghost-button",
4070
+ onClick: () => window.open("https://support.neofaceid.com", "_blank"),
4071
+ children: "Falar com Suporte"
4072
+ }
4073
+ )
4074
+ ] })
4075
+ ] }),
4076
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
4077
+ "div",
4078
+ {
4079
+ className: "branding",
4080
+ style: {
4081
+ marginTop: "32px",
4082
+ paddingTop: "20px",
4083
+ borderTop: "1px solid rgba(255, 255, 255, 0.08)",
4084
+ width: "100%"
4085
+ },
4086
+ children: [
4087
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
4088
+ "img",
4089
+ {
4090
+ src: "/logo-icone.png",
4091
+ alt: "NeoFaceId",
4092
+ className: "brand-logo",
4093
+ style: { height: "18px" }
4094
+ }
4095
+ ),
4096
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "NeoFaceId by" }),
4097
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "brand-name", children: "OCTA" })
4098
+ ]
4099
+ }
4100
+ )
4101
+ ] });
4102
+ };
3523
4103
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
3524
4104
  /* @__PURE__ */ jsxRuntimeExports.jsx("style", { children: `
3525
4105
  @keyframes fadeIn {
@@ -4049,6 +4629,61 @@ function BiometricRegistrationModal({
4049
4629
  background: rgba(255, 255, 255, 0.05);
4050
4630
  }
4051
4631
 
4632
+ /* Duplicate Screen Styles */
4633
+ .profile-icon-wrapper {
4634
+ position: relative;
4635
+ display: inline-block;
4636
+ margin-bottom: 24px;
4637
+ }
4638
+
4639
+ .profile-main-icon {
4640
+ background: rgba(124, 58, 237, 0.1);
4641
+ color: #7c3aed;
4642
+ padding: 20px;
4643
+ border-radius: 50%;
4644
+ border: 2px solid rgba(124, 58, 237, 0.2);
4645
+ box-shadow: 0 0 30px rgba(124, 58, 237, 0.2);
4646
+ }
4647
+
4648
+ .profile-main-icon svg {
4649
+ width: 48px;
4650
+ height: 48px;
4651
+ }
4652
+
4653
+ .verified-badge {
4654
+ position: absolute;
4655
+ bottom: -4px;
4656
+ right: -4px;
4657
+ background: #10b981;
4658
+ border-radius: 50%;
4659
+ padding: 4px;
4660
+ border: 3px solid #16213e;
4661
+ width: 24px;
4662
+ height: 24px;
4663
+ display: flex;
4664
+ align-items: center;
4665
+ justify-content: center;
4666
+ }
4667
+
4668
+ .button-group-vertical {
4669
+ display: flex;
4670
+ flex-direction: column;
4671
+ width: 100%;
4672
+ gap: 8px;
4673
+ }
4674
+
4675
+ .support-section {
4676
+ margin-top: 24px;
4677
+ padding-top: 16px;
4678
+ border-top: 1px solid rgba(255, 255, 255, 0.05);
4679
+ }
4680
+
4681
+ .support-section p {
4682
+ font-size: 13px;
4683
+ color: rgba(255, 255, 255, 0.4);
4684
+ margin-bottom: 8px;
4685
+ }
4686
+
4052
4687
  /* Canvas */
4053
4688
  canvas {
4054
4689
  display: none;
@@ -4086,7 +4721,8 @@ function BiometricRegistrationModal({
4086
4721
  state.status === "camera-loading" && renderCameraLoading(),
4087
4722
  state.status === "processing" && renderProcessing(),
4088
4723
  state.status === "error" && renderError(),
4089
- state.status === "success" && renderSuccess()
4724
+ state.status === "success" && renderSuccess(),
4725
+ state.status === "duplicate" && renderDuplicate()
4090
4726
  ] }) }),
4091
4727
  /* @__PURE__ */ jsxRuntimeExports.jsx("canvas", { ref: canvasRef })
4092
4728
  ] });
@@ -4674,6 +5310,7 @@ class BiometricStatusOverlay {
4674
5310
  /* Cores por estado */
4675
5311
  .neofaceid-state-preparing .neofaceid-logo { filter: drop-shadow(0 0 15px rgba(124, 58, 237, 0.4)); }
4676
5312
  .neofaceid-state-detecting .neofaceid-logo { filter: hue-rotate(180deg) drop-shadow(0 0 15px rgba(59, 130, 246, 0.6)); }
5313
+ .neofaceid-state-waiting-for-face .neofaceid-logo { filter: hue-rotate(30deg) drop-shadow(0 0 15px rgba(251, 146, 60, 0.6)); }
4677
5314
  .neofaceid-state-capturing .neofaceid-logo { filter: hue-rotate(45deg) drop-shadow(0 0 15px rgba(245, 158, 11, 0.6)); }
4678
5315
  .neofaceid-state-verifying .neofaceid-logo { filter: hue-rotate(90deg) drop-shadow(0 0 15px rgba(34, 197, 94, 0.6)); }
4679
5316
 
@@ -4747,6 +5384,8 @@ class BiometricStatusOverlay {
4747
5384
  return "Iniciando câmera";
4748
5385
  case "detecting":
4749
5386
  return "Posicione seu rosto";
5387
+ case "waiting-for-face":
5388
+ return "Aguardando rosto";
4750
5389
  case "capturing":
4751
5390
  return "Capturando";
4752
5391
  case "verifying":
@@ -4760,12 +5399,18 @@ class BiometricStatusOverlay {
4760
5399
  }
4761
5400
  }
4762
5401
  renderContent() {
4763
- const isPulsing = ["detecting", "verifying"].includes(this.currentStatus);
5402
+ const isPulsing = ["detecting", "waiting-for-face", "verifying"].includes(this.currentStatus);
4764
5403
  const showLogo = !["success", "error"].includes(this.currentStatus);
4765
5404
  const showSuccess = this.currentStatus === "success";
4766
5405
  const showError = this.currentStatus === "error";
4767
5406
  const statusText = this.getStatusText();
4768
- const showDots = ["preparing", "detecting", "capturing", "verifying"].includes(this.currentStatus);
5407
+ const showDots = [
5408
+ "preparing",
5409
+ "detecting",
5410
+ "waiting-for-face",
5411
+ "capturing",
5412
+ "verifying"
5413
+ ].includes(this.currentStatus);
4769
5414
  return `
4770
5415
  <style>${this.getStyles()}</style>
4771
5416
  <div class="neofaceid-overlay-container neofaceid-state-${this.currentStatus}">
@@ -4850,8 +5495,13 @@ function FallbackPromptComponent({
4850
5495
  error,
4851
5496
  onRetry,
4852
5497
  onCredentials,
4853
- onCancel
5498
+ onCancel,
5499
+ applicationToken
4854
5500
  }) {
5501
+ const handleForgotPassword = () => {
5502
+ const modal = new ForgotPasswordModal(applicationToken);
5503
+ modal.open();
5504
+ };
4855
5505
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
4856
5506
  /* @__PURE__ */ jsxRuntimeExports.jsx("style", { children: `
4857
5507
  @keyframes slideUp {
@@ -5029,6 +5679,15 @@ function FallbackPromptComponent({
5029
5679
  children: "Entrar com Email e Senha"
5030
5680
  }
5031
5681
  ),
5682
+ applicationToken && /* @__PURE__ */ jsxRuntimeExports.jsx(
5683
+ "button",
5684
+ {
5685
+ type: "button",
5686
+ className: "neofaceid-fallback-button neofaceid-fallback-button-ghost",
5687
+ onClick: handleForgotPassword,
5688
+ children: "Esqueceu sua senha?"
5689
+ }
5690
+ ),
5032
5691
  onCancel && /* @__PURE__ */ jsxRuntimeExports.jsx(
5033
5692
  "button",
5034
5693
  {
@@ -5050,7 +5709,7 @@ class FallbackPrompt {
5050
5709
  /**
5051
5710
  * Exibe o prompt de fallback
5052
5711
  */
5053
- show(error, onRetry, onCredentials, onCancel) {
5712
+ show(error, onRetry, onCredentials, onCancel, applicationToken) {
5054
5713
  if (this.container) {
5055
5714
  return;
5056
5715
  }
@@ -5058,7 +5717,7 @@ class FallbackPrompt {
5058
5717
  this.container.id = "neofaceid-fallback-prompt";
5059
5718
  document.body.appendChild(this.container);
5060
5719
  this.root = clientExports.createRoot(this.container);
5061
- this.render(error, onRetry, onCredentials, onCancel);
5720
+ this.render(error, onRetry, onCredentials, onCancel, applicationToken);
5062
5721
  }
5063
5722
  /**
5064
5723
  * Fecha o prompt
@@ -5076,7 +5735,7 @@ class FallbackPrompt {
5076
5735
  /**
5077
5736
  * Renderiza o componente
5078
5737
  */
5079
- render(error, onRetry, onCredentials, onCancel) {
5738
+ render(error, onRetry, onCredentials, onCancel, applicationToken) {
5080
5739
  if (!this.root || !this.container) return;
5081
5740
  this.root.render(
5082
5741
  /* @__PURE__ */ jsxRuntimeExports.jsx(
@@ -5091,6 +5750,7 @@ class FallbackPrompt {
5091
5750
  this.close();
5092
5751
  onCredentials();
5093
5752
  },
5753
+ applicationToken: applicationToken ?? "",
5094
5754
  onCancel: () => {
5095
5755
  this.close();
5096
5756
  onCancel == null ? void 0 : onCancel();
@@ -5565,12 +6225,14 @@ async function captureFaceSilently() {
5565
6225
  });
5566
6226
  });
5567
6227
  }
5568
- async function detectFaceQuickly(video, maxTime = FACE_DETECTION_TIME, interval = DETECTION_INTERVAL) {
6228
+ async function detectFaceQuickly(video, maxTime = FACE_DETECTION_TIME, interval = DETECTION_INTERVAL, overlay) {
5569
6229
  return new Promise((resolve) => {
5570
6230
  let attempts = 0;
5571
6231
  const maxAttempts = Math.ceil(maxTime / interval);
5572
6232
  let timeoutId = null;
5573
6233
  let isResolved = false;
6234
+ let overlayShowingWaiting = false;
6235
+ const ATTEMPTS_BEFORE_WAITING = Math.ceil(3e3 / interval);
5574
6236
  const finish = (success) => {
5575
6237
  if (isResolved) return;
5576
6238
  isResolved = true;
@@ -5581,7 +6243,16 @@ async function detectFaceQuickly(video, maxTime = FACE_DETECTION_TIME, interval
5581
6243
  if (isResolved) return;
5582
6244
  attempts++;
5583
6245
  if (!modelsLoaded) {
5584
- finish(true);
6246
+ if (overlay && !overlayShowingWaiting && attempts >= ATTEMPTS_BEFORE_WAITING) {
6247
+ overlay.updateStatus("waiting-for-face");
6248
+ overlayShowingWaiting = true;
6249
+ console.log("⏳ Models not loaded - waiting for face...");
6250
+ }
6251
+ if (attempts >= maxAttempts) {
6252
+ finish(false);
6253
+ return;
6254
+ }
6255
+ timeoutId = window.setTimeout(checkFace, interval);
5585
6256
  return;
5586
6257
  }
5587
6258
  try {
@@ -5590,21 +6261,43 @@ async function detectFaceQuickly(video, maxTime = FACE_DETECTION_TIME, interval
5590
6261
  new faceapi.TinyFaceDetectorOptions({ inputSize: 160, scoreThreshold: 0.3 })
5591
6262
  );
5592
6263
  if (detection) {
6264
+ if (overlay && overlayShowingWaiting) {
6265
+ overlay.updateStatus("detecting");
6266
+ overlayShowingWaiting = false;
6267
+ console.log("👤 Face appeared");
6268
+ }
6269
+ console.log("✅ Face detected!");
5593
6270
  finish(true);
5594
6271
  return;
5595
6272
  }
6273
+ if (overlay && !overlayShowingWaiting && attempts >= ATTEMPTS_BEFORE_WAITING) {
6274
+ overlay.updateStatus("waiting-for-face");
6275
+ overlayShowingWaiting = true;
6276
+ console.log("⏳ Waiting for face...");
6277
+ }
5596
6278
  if (attempts >= maxAttempts) {
6279
+ console.warn("⏱️ Face detection timeout - no face found");
5597
6280
  finish(false);
5598
6281
  return;
5599
6282
  }
5600
6283
  timeoutId = window.setTimeout(checkFace, interval);
5601
6284
  } catch (error) {
5602
- finish(true);
6285
+ console.error("❌ Face detection error:", error);
6286
+ if (overlay && !overlayShowingWaiting && attempts >= ATTEMPTS_BEFORE_WAITING) {
6287
+ overlay.updateStatus("waiting-for-face");
6288
+ overlayShowingWaiting = true;
6289
+ }
6290
+ if (attempts >= maxAttempts) {
6291
+ finish(false);
6292
+ return;
6293
+ }
6294
+ timeoutId = window.setTimeout(checkFace, interval);
5603
6295
  }
5604
6296
  };
5605
6297
  window.setTimeout(() => {
5606
6298
  if (!isResolved) {
5607
- finish(true);
6299
+ console.warn("⏱️ Face detection safety timeout reached");
6300
+ finish(false);
5608
6301
  }
5609
6302
  }, maxTime + 500);
5610
6303
  checkFace();
@@ -5678,7 +6371,12 @@ async function attemptLogin(applicationToken, overlay, fastMode = false, isRetry
5678
6371
  await new Promise((resolve) => setTimeout(resolve, CAMERA_STABILITY_DELAY));
5679
6372
  let faceDetected = true;
5680
6373
  if (!fastMode) {
5681
- faceDetected = await detectFaceQuickly(video);
6374
+ faceDetected = await detectFaceQuickly(
6375
+ video,
6376
+ FACE_DETECTION_TIME,
6377
+ DETECTION_INTERVAL,
6378
+ overlay
6379
+ );
5682
6380
  }
5683
6381
  if (!faceDetected) {
5684
6382
  if (stream) {
@@ -5688,7 +6386,7 @@ async function attemptLogin(applicationToken, overlay, fastMode = false, isRetry
5688
6386
  video.parentElement.removeChild(video);
5689
6387
  }
5690
6388
  throw new NeoFaceError(
5691
- "Rosto não detectado. Posicione seu rosto na frente da câmera.",
6389
+ "Nenhum rosto detectado. Por favor, posicione seu rosto na frente da câmera e tente novamente.",
5692
6390
  ErrorType.VALIDATION_ERROR
5693
6391
  );
5694
6392
  }
@@ -5808,7 +6506,8 @@ async function executeBiometricLoginFlow(options) {
5808
6506
  );
5809
6507
  }
5810
6508
  },
5811
- onCancel
6509
+ onCancel,
6510
+ applicationToken
5812
6511
  );
5813
6512
  }, 500);
5814
6513
  }
@@ -6136,8 +6835,8 @@ const biometricDetection = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.
6136
6835
  initializeBiometricDetection,
6137
6836
  isAdvancedDetectionAvailable
6138
6837
  }, Symbol.toStringTag, { value: "Module" }));
6139
- const VERSION = "1.15.2";
6140
- const RELEASE_DATE = "2026-03-04";
6838
+ const VERSION = "1.17.0";
6839
+ const RELEASE_DATE = "2026-03-13";
6141
6840
  class OnboardingCaptureModal {
6142
6841
  constructor(options) {
6143
6842
  __publicField(this, "overlay", null);
@@ -6822,11 +7521,11 @@ const authorizeOperation = async (applicationToken, cpf, options) => {
6822
7521
  };
6823
7522
  const DOCUMENT_INFO = {
6824
7523
  RG: {
6825
- name: "RG / Carteira de Identidade",
7524
+ name: "Documento de Identidade (RG / CIN / CPF)",
6826
7525
  icon: '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="4" width="18" height="16" rx="2"/><circle cx="9" cy="10" r="2"/><path d="M15 8h2M15 12h2M7 16h10"/></svg>',
6827
7526
  hasBack: true,
6828
- frontLabel: "Frente do RG",
6829
- backLabel: "Verso do RG"
7527
+ frontLabel: "Frente do Documento",
7528
+ backLabel: "Verso do Documento"
6830
7529
  },
6831
7530
  CNH: {
6832
7531
  name: "CNH / Carteira de Motorista",
@@ -6836,7 +7535,7 @@ const DOCUMENT_INFO = {
6836
7535
  backLabel: "Verso da CNH"
6837
7536
  },
6838
7537
  CPF: {
6839
- name: "CPF",
7538
+ name: "Cartão CPF (Apenas Frente)",
6840
7539
  icon: '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><path d="M14 2v6h6M16 13H8M16 17H8M10 9H8"/></svg>',
6841
7540
  hasBack: false,
6842
7541
  frontLabel: "Cartão CPF"
@@ -6930,7 +7629,7 @@ class DocumentCaptureModal {
6930
7629
 
6931
7630
  <div class="neoface-doc-body">
6932
7631
  <div class="neoface-doc-select-grid">
6933
- ${Object.entries(DOCUMENT_INFO).map(([type, info]) => `
7632
+ ${Object.entries(DOCUMENT_INFO).filter(([type]) => type !== "CPF").map(([type, info]) => `
6934
7633
  <button class="neoface-doc-select-option" data-type="${type}">
6935
7634
  <span class="neoface-doc-select-icon">${info.icon}</span>
6936
7635
  <span class="neoface-doc-select-name">${info.name}</span>
@@ -7936,6 +8635,7 @@ export {
7936
8635
  ErrorType,
7937
8636
  FaceCaptureModal,
7938
8637
  FallbackPrompt,
8638
+ ForgotPasswordModal,
7939
8639
  NeoFaceError,
7940
8640
  NeoFaceID,
7941
8641
  RELEASE_DATE,
@@ -7943,14 +8643,17 @@ export {
7943
8643
  authorizeOperation,
7944
8644
  biometricLogin,
7945
8645
  biometricLoginWithFallback,
8646
+ checkUserExistence,
7946
8647
  completeOnboarding,
7947
8648
  completeOnboardingWithData,
8649
+ confirmPasswordReset,
7948
8650
  detectBiometricType,
7949
8651
  getApplicationToken,
7950
8652
  getBaseUrl,
7951
8653
  getConfig,
7952
8654
  getEnvironment,
7953
8655
  identifyPerson,
8656
+ identifyPersonAsync,
7954
8657
  init,
7955
8658
  initializeBiometricDetection,
7956
8659
  isAdvancedDetectionAvailable,
@@ -7964,6 +8667,7 @@ export {
7964
8667
  registerBiometric,
7965
8668
  registerPersonWithBiometric,
7966
8669
  registerPersonWithoutFace,
8670
+ requestPasswordReset,
7967
8671
  simpleIdentification,
7968
8672
  start,
7969
8673
  startAutoLogin,