vesant-sdk 1.3.0 → 1.4.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.
Files changed (45) hide show
  1. package/dist/compliance/index.js +23 -4
  2. package/dist/compliance/index.js.map +1 -1
  3. package/dist/compliance/index.mjs +23 -4
  4. package/dist/compliance/index.mjs.map +1 -1
  5. package/dist/decisions/index.js +10 -3
  6. package/dist/decisions/index.js.map +1 -1
  7. package/dist/decisions/index.mjs +10 -3
  8. package/dist/decisions/index.mjs.map +1 -1
  9. package/dist/geolocation/index.js +23 -4
  10. package/dist/geolocation/index.js.map +1 -1
  11. package/dist/geolocation/index.mjs +23 -4
  12. package/dist/geolocation/index.mjs.map +1 -1
  13. package/dist/index.d.mts +2 -2
  14. package/dist/index.d.ts +2 -2
  15. package/dist/index.js +58 -4
  16. package/dist/index.js.map +1 -1
  17. package/dist/index.mjs +58 -4
  18. package/dist/index.mjs.map +1 -1
  19. package/dist/kyc/core.d.mts +1 -1
  20. package/dist/kyc/core.d.ts +1 -1
  21. package/dist/kyc/core.js +45 -3
  22. package/dist/kyc/core.js.map +1 -1
  23. package/dist/kyc/core.mjs +45 -3
  24. package/dist/kyc/core.mjs.map +1 -1
  25. package/dist/kyc/index.d.mts +43 -1
  26. package/dist/kyc/index.d.ts +43 -1
  27. package/dist/kyc/index.js +45 -3
  28. package/dist/kyc/index.js.map +1 -1
  29. package/dist/kyc/index.mjs +45 -3
  30. package/dist/kyc/index.mjs.map +1 -1
  31. package/dist/react.d.mts +5 -2
  32. package/dist/react.d.ts +5 -2
  33. package/dist/react.js +441 -102
  34. package/dist/react.js.map +1 -1
  35. package/dist/react.mjs +342 -8
  36. package/dist/react.mjs.map +1 -1
  37. package/dist/risk-profile/index.js +10 -3
  38. package/dist/risk-profile/index.js.map +1 -1
  39. package/dist/risk-profile/index.mjs +10 -3
  40. package/dist/risk-profile/index.mjs.map +1 -1
  41. package/dist/scores/index.js +10 -3
  42. package/dist/scores/index.js.map +1 -1
  43. package/dist/scores/index.mjs +10 -3
  44. package/dist/scores/index.mjs.map +1 -1
  45. package/package.json +10 -2
package/dist/react.mjs CHANGED
@@ -1,9 +1,10 @@
1
- import { useState, useRef, useCallback, useEffect } from 'react';
1
+ import React, { useState, useRef, useCallback, useEffect, createElement } from 'react';
2
+ import { createRoot } from 'react-dom/client';
2
3
 
3
4
  // src/geolocation/hooks.ts
4
5
 
5
6
  // src/core/version.ts
6
- var SDK_VERSION = "1.3.0";
7
+ var SDK_VERSION = "1.4.0";
7
8
 
8
9
  // src/shared/browser-utils.ts
9
10
  function generateUUID() {
@@ -198,9 +199,13 @@ function encodePayload(payload) {
198
199
  async function generateCipherText(options, config) {
199
200
  const warnings = [];
200
201
  let requestLocation = options.requestLocation ?? false;
202
+ let gpsRequiredByConfig = false;
201
203
  if (config?.require_gps) {
202
204
  const reason = options.reason;
203
205
  if (reason === "login" && config.require_gps.login || reason === "registration" && config.require_gps.registration || reason === "transaction" && config.require_gps.transaction) {
206
+ if (!requestLocation) {
207
+ gpsRequiredByConfig = true;
208
+ }
204
209
  requestLocation = true;
205
210
  }
206
211
  }
@@ -213,6 +218,10 @@ async function generateCipherText(options, config) {
213
218
  );
214
219
  if (location) {
215
220
  locationData = location;
221
+ } else if (gpsRequiredByConfig) {
222
+ throw new Error(
223
+ `GPS location is required for ${options.reason} by tenant configuration, but GPS was not available or permission was denied`
224
+ );
216
225
  } else {
217
226
  warnings.push("GPS location not available or permission denied");
218
227
  }
@@ -367,18 +376,19 @@ function createDeviceFingerprint() {
367
376
  };
368
377
  }
369
378
  function useCipherText(client) {
370
- const [config, setConfig] = useState(void 0);
371
379
  const [configLoading, setConfigLoading] = useState(!!client);
372
380
  const [configError, setConfigError] = useState(null);
373
381
  const configRef = useRef(void 0);
374
- configRef.current = config;
382
+ const configPromiseRef = useRef(null);
375
383
  useEffect(() => {
376
384
  if (!client) return;
377
385
  let cancelled = false;
378
386
  setConfigLoading(true);
379
- client.getGPSConfig().then((cfg) => {
387
+ const promise = client.getGPSConfig();
388
+ configPromiseRef.current = promise;
389
+ promise.then((cfg) => {
380
390
  if (!cancelled) {
381
- setConfig(cfg);
391
+ configRef.current = cfg;
382
392
  setConfigLoading(false);
383
393
  }
384
394
  }).catch((err) => {
@@ -394,6 +404,13 @@ function useCipherText(client) {
394
404
  const generate = useCallback(
395
405
  async (options) => {
396
406
  try {
407
+ if (configPromiseRef.current) {
408
+ try {
409
+ const cfg = await configPromiseRef.current;
410
+ configRef.current = cfg;
411
+ } catch {
412
+ }
413
+ }
397
414
  return await generateCipherText(options, configRef.current);
398
415
  } catch (error) {
399
416
  console.error("[CGS SDK] Failed to generate cipherText:", error);
@@ -847,6 +864,288 @@ function useCustomerProfile(client, customerId, options = {}) {
847
864
  refresh: fetchProfile
848
865
  };
849
866
  }
867
+
868
+ // src/kyc/images.ts
869
+ var Camera = "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCg0KPCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjAvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvVFIvMjAwMS9SRUMtU1ZHLTIwMDEwOTA0L0RURC9zdmcxMC5kdGQiPg0KPCEtLSBVcGxvYWRlZCB0bzogU1ZHIFJlcG8sIHd3dy5zdmdyZXBvLmNvbSwgR2VuZXJhdG9yOiBTVkcgUmVwbyBNaXhlciBUb29scyAtLT4NCjxzdmcgdmVyc2lvbj0iMS4wIiBpZD0iTGF5ZXJfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgDQoJIHdpZHRoPSI4MDBweCIgaGVpZ2h0PSI4MDBweCIgdmlld0JveD0iMCAwIDY0IDY0IiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDAgMCA2NCA2NCIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+DQo8Zz4NCgk8cGF0aCBmaWxsPSIjMjMxRjIwIiBkPSJNNjAsMTBINDkuNjU2bC02LjgyOC02LjgyOEM0Mi4wNzgsMi40MjIsNDEuMDYyLDIsNDAsMkgyNGMtMS4wNjIsMC0yLjA3OCwwLjQyMi0yLjgyOCwxLjE3MkwxNC4zNDQsMTBINA0KCQljLTIuMjExLDAtNCwxLjc4OS00LDR2NDRjMCwyLjIxMSwxLjc4OSw0LDQsNGg1NmMyLjIxMSwwLDQtMS43ODksNC00VjE0QzY0LDExLjc4OSw2Mi4yMTEsMTAsNjAsMTB6IE0zMiw1MA0KCQljLTguODM2LDAtMTYtNy4xNjQtMTYtMTZzNy4xNjQtMTYsMTYtMTZzMTYsNy4xNjQsMTYsMTZTNDAuODM2LDUwLDMyLDUweiIvPg0KCTxjaXJjbGUgZmlsbD0iIzIzMUYyMCIgY3g9IjMyIiBjeT0iMzQiIHI9IjgiLz4NCjwvZz4NCjwvc3ZnPg==";
870
+ var Done = "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48IS0tIFVwbG9hZGVkIHRvOiBTVkcgUmVwbywgd3d3LnN2Z3JlcG8uY29tLCBHZW5lcmF0b3I6IFNWRyBSZXBvIE1peGVyIFRvb2xzIC0tPg0KPHN2ZyB3aWR0aD0iODAwcHgiIGhlaWdodD0iODAwcHgiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4NCjxwYXRoIGQ9Ik04LjUgMTIuNUwxMC41IDE0LjVMMTUuNSA5LjUiIHN0cm9rZT0iIzFDMjc0QyIgc3Ryb2tlLXdpZHRoPSIxLjUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPg0KPHBhdGggZD0iTTcgMy4zMzc4MkM4LjQ3MDg3IDIuNDg2OTcgMTAuMTc4NiAyIDEyIDJDMTcuNTIyOCAyIDIyIDYuNDc3MTUgMjIgMTJDMjIgMTcuNTIyOCAxNy41MjI4IDIyIDEyIDIyQzYuNDc3MTUgMjIgMiAxNy41MjI4IDIgMTJDMiAxMC4xNzg2IDIuNDg2OTcgOC40NzA4NyAzLjMzNzgyIDciIHN0cm9rZT0iIzFDMjc0QyIgc3Ryb2tlLXdpZHRoPSIxLjUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPg0KPC9zdmc+";
871
+ var Close = "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48IS0tIFVwbG9hZGVkIHRvOiBTVkcgUmVwbywgd3d3LnN2Z3JlcG8uY29tLCBHZW5lcmF0b3I6IFNWRyBSZXBvIE1peGVyIFRvb2xzIC0tPg0KPHN2ZyB3aWR0aD0iODAwcHgiIGhlaWdodD0iODAwcHgiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4NCjxwYXRoIGQ9Ik0xNC41IDkuNTAwMDJMOS41IDE0LjVNOS40OTk5OCA5LjVMMTQuNSAxNC41IiBzdHJva2U9IiMxQzI3NEMiIHN0cm9rZS13aWR0aD0iMS41IiBzdHJva2UtbGluZWNhcD0icm91bmQiLz4NCjxwYXRoIGQ9Ik03IDMuMzM3ODJDOC40NzA4NyAyLjQ4Njk3IDEwLjE3ODYgMiAxMiAyQzE3LjUyMjggMiAyMiA2LjQ3NzE1IDIyIDEyQzIyIDE3LjUyMjggMTcuNTIyOCAyMiAxMiAyMkM2LjQ3NzE1IDIyIDIgMTcuNTIyOCAyIDEyQzIgMTAuMTc4NiAyLjQ4Njk3IDguNDcwODcgMy4zMzc4MiA3IiBzdHJva2U9IiMxQzI3NEMiIHN0cm9rZS13aWR0aD0iMS41IiBzdHJva2UtbGluZWNhcD0icm91bmQiLz4NCjwvc3ZnPg==";
872
+ var Upload = "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48IS0tIFVwbG9hZGVkIHRvOiBTVkcgUmVwbywgd3d3LnN2Z3JlcG8uY29tLCBHZW5lcmF0b3I6IFNWRyBSZXBvIE1peGVyIFRvb2xzIC0tPg0KPHN2ZyB3aWR0aD0iODAwcHgiIGhlaWdodD0iODAwcHgiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4NCjxwYXRoIGQ9Ik0xNyAxN0gxNy4wMU0xNS42IDE0SDE4QzE4LjkzMTkgMTQgMTkuMzk3OCAxNCAxOS43NjU0IDE0LjE1MjJDMjAuMjU1NCAxNC4zNTUyIDIwLjY0NDggMTQuNzQ0NiAyMC44NDc4IDE1LjIzNDZDMjEgMTUuNjAyMiAyMSAxNi4wNjgxIDIxIDE3QzIxIDE3LjkzMTkgMjEgMTguMzk3OCAyMC44NDc4IDE4Ljc2NTRDMjAuNjQ0OCAxOS4yNTU0IDIwLjI1NTQgMTkuNjQ0OCAxOS43NjU0IDE5Ljg0NzhDMTkuMzk3OCAyMCAxOC45MzE5IDIwIDE4IDIwSDZDNS4wNjgxMiAyMCA0LjYwMjE4IDIwIDQuMjM0NjMgMTkuODQ3OEMzLjc0NDU4IDE5LjY0NDggMy4zNTUyMyAxOS4yNTU0IDMuMTUyMjQgMTguNzY1NEMzIDE4LjM5NzggMyAxNy45MzE5IDMgMTdDMyAxNi4wNjgxIDMgMTUuNjAyMiAzLjE1MjI0IDE1LjIzNDZDMy4zNTUyMyAxNC43NDQ2IDMuNzQ0NTggMTQuMzU1MiA0LjIzNDYzIDE0LjE1MjJDNC42MDIxOCAxNCA1LjA2ODEyIDE0IDYgMTRIOC40TTEyIDE1VjRNMTIgNEwxNSA3TTEyIDRMOSA3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+DQo8L3N2Zz4=";
873
+
874
+ // src/kyc/FaceCaptureModal.tsx
875
+ var fileToBase64 = (file) => {
876
+ return new Promise((resolve, reject) => {
877
+ const reader = new FileReader();
878
+ reader.readAsDataURL(file);
879
+ reader.onload = () => resolve(reader.result);
880
+ reader.onerror = (error) => reject(error);
881
+ });
882
+ };
883
+ function FaceCaptureModal({
884
+ onCapture,
885
+ onCancel
886
+ }) {
887
+ const inputRef = useRef(null);
888
+ const [isProcessing, setIsProcessing] = useState(false);
889
+ const [isHoveringPrimary, setIsHoveringPrimary] = useState(false);
890
+ const [isHoveringCancel, setIsHoveringCancel] = useState(false);
891
+ const [isHoveringClose, setIsHoveringClose] = useState(false);
892
+ const isMobile = /Mobi|Android/i.test(navigator.userAgent);
893
+ const handleFileChange = async (e) => {
894
+ const file = e.target.files?.[0];
895
+ if (!file) return;
896
+ setIsProcessing(true);
897
+ try {
898
+ const base64 = await fileToBase64(file);
899
+ setTimeout(() => {
900
+ onCapture(base64);
901
+ }, 300);
902
+ } catch (error) {
903
+ console.error("Error processing image:", error);
904
+ setIsProcessing(false);
905
+ }
906
+ };
907
+ const overlayStyle = {
908
+ position: "fixed",
909
+ inset: 0,
910
+ background: "rgba(0, 0, 0, 0.6)",
911
+ backdropFilter: "blur(4px)",
912
+ display: "flex",
913
+ alignItems: "center",
914
+ justifyContent: "center",
915
+ zIndex: 999999,
916
+ padding: "16px",
917
+ animation: "fadeIn 0.2s ease-out"
918
+ };
919
+ const modalStyle = {
920
+ background: "#ffffff",
921
+ borderRadius: "16px",
922
+ boxShadow: "0 25px 50px -12px rgba(0, 0, 0, 0.25)",
923
+ width: "100%",
924
+ maxWidth: "448px",
925
+ animation: "zoomIn 0.2s ease-out"
926
+ };
927
+ const headerStyle = {
928
+ position: "relative",
929
+ padding: "24px 24px 16px",
930
+ borderBottom: "1px solid #f3f4f6"
931
+ };
932
+ const closeButtonStyle = {
933
+ position: "absolute",
934
+ top: "16px",
935
+ right: "16px",
936
+ padding: "8px",
937
+ background: isHoveringClose ? "#f3f4f6" : "transparent",
938
+ border: "none",
939
+ borderRadius: "9999px",
940
+ cursor: "pointer",
941
+ transition: "background-color 0.2s",
942
+ display: "flex",
943
+ alignItems: "center",
944
+ justifyContent: "center"
945
+ };
946
+ const titleStyle = {
947
+ fontSize: "24px",
948
+ fontWeight: 600,
949
+ color: "#111827",
950
+ margin: 0
951
+ };
952
+ const subtitleStyle = {
953
+ fontSize: "14px",
954
+ color: "#6b7280",
955
+ marginTop: "4px"
956
+ };
957
+ const contentStyle = {
958
+ padding: "32px 24px"
959
+ };
960
+ const visualGuideContainerStyle = {
961
+ marginBottom: "32px",
962
+ display: "flex",
963
+ justifyContent: "center"
964
+ };
965
+ const visualGuideStyle = {
966
+ position: "relative"
967
+ };
968
+ const circleStyle = {
969
+ width: "128px",
970
+ height: "128px",
971
+ borderRadius: "50%",
972
+ background: "linear-gradient(135deg, rgba(0, 188, 125, 0.2) 0%, rgba(0, 188, 125, 0.05) 100%)",
973
+ display: "flex",
974
+ alignItems: "center",
975
+ justifyContent: "center"
976
+ };
977
+ const badgeStyle = {
978
+ position: "absolute",
979
+ top: "-4px",
980
+ right: "-4px",
981
+ width: "32px",
982
+ height: "32px",
983
+ background: "#ffffff",
984
+ borderRadius: "50%",
985
+ boxShadow: "0 4px 6px -1px rgba(0, 0, 0, 0.1)",
986
+ display: "flex",
987
+ alignItems: "center",
988
+ justifyContent: "center"
989
+ };
990
+ const instructionsBoxStyle = {
991
+ background: "linear-gradient(135deg, #f9fafb 0%, rgba(243, 244, 246, 0.5) 100%)",
992
+ borderRadius: "12px",
993
+ padding: "16px",
994
+ marginBottom: "24px"
995
+ };
996
+ const instructionsTitleStyle = {
997
+ fontSize: "14px",
998
+ fontWeight: 500,
999
+ color: "#111827",
1000
+ marginBottom: "8px"
1001
+ };
1002
+ const instructionsListStyle = {
1003
+ fontSize: "12px",
1004
+ color: "#6b7280",
1005
+ listStyle: "none",
1006
+ padding: 0,
1007
+ margin: 0
1008
+ };
1009
+ const instructionItemStyle = {
1010
+ display: "flex",
1011
+ alignItems: "flex-start",
1012
+ marginBottom: "6px"
1013
+ };
1014
+ const bulletStyle = {
1015
+ color: "#00bc7d",
1016
+ marginRight: "8px",
1017
+ flexShrink: 0
1018
+ };
1019
+ const buttonsContainerStyle = {
1020
+ display: "flex",
1021
+ flexDirection: "column",
1022
+ gap: "12px"
1023
+ };
1024
+ const primaryButtonStyle = {
1025
+ width: "100%",
1026
+ background: isProcessing ? "#d1d5db" : isHoveringPrimary ? "#00a86d" : "#00bc7d",
1027
+ color: "#ffffff",
1028
+ fontWeight: 500,
1029
+ padding: "14px 24px",
1030
+ borderRadius: "12px",
1031
+ border: "none",
1032
+ cursor: isProcessing ? "not-allowed" : "pointer",
1033
+ transition: "all 0.2s",
1034
+ display: "flex",
1035
+ alignItems: "center",
1036
+ justifyContent: "center",
1037
+ gap: "12px",
1038
+ boxShadow: isProcessing ? "none" : isHoveringPrimary ? "0 20px 25px -5px rgba(0, 188, 125, 0.3)" : "0 10px 15px -3px rgba(0, 188, 125, 0.2)",
1039
+ fontSize: "16px"
1040
+ };
1041
+ const cancelButtonStyle = {
1042
+ width: "100%",
1043
+ background: isProcessing ? "#f3f4f6" : isHoveringCancel ? "#f9fafb" : "#ffffff",
1044
+ color: "#374151",
1045
+ fontWeight: 500,
1046
+ padding: "14px 24px",
1047
+ borderRadius: "12px",
1048
+ border: "2px solid #e5e7eb",
1049
+ cursor: isProcessing ? "not-allowed" : "pointer",
1050
+ transition: "all 0.2s",
1051
+ fontSize: "16px"
1052
+ };
1053
+ const footerStyle = {
1054
+ padding: "0 24px 24px"
1055
+ };
1056
+ const footerTextStyle = {
1057
+ fontSize: "12px",
1058
+ textAlign: "center",
1059
+ color: "#9ca3af",
1060
+ margin: 0
1061
+ };
1062
+ const spinnerStyle = {
1063
+ width: "20px",
1064
+ height: "20px",
1065
+ border: "2px solid rgba(255, 255, 255, 0.3)",
1066
+ borderTopColor: "#ffffff",
1067
+ borderRadius: "50%",
1068
+ animation: "spin 0.6s linear infinite"
1069
+ };
1070
+ const hiddenInputStyle = {
1071
+ display: "none"
1072
+ };
1073
+ const styleTag = /* @__PURE__ */ React.createElement("style", null, `
1074
+ @keyframes fadeIn {
1075
+ from {
1076
+ opacity: 0;
1077
+ }
1078
+ to {
1079
+ opacity: 1;
1080
+ }
1081
+ }
1082
+
1083
+ @keyframes zoomIn {
1084
+ from {
1085
+ opacity: 0;
1086
+ transform: scale(0.95);
1087
+ }
1088
+ to {
1089
+ opacity: 1;
1090
+ transform: scale(1);
1091
+ }
1092
+ }
1093
+
1094
+ @keyframes spin {
1095
+ from {
1096
+ transform: rotate(0deg);
1097
+ }
1098
+ to {
1099
+ transform: rotate(360deg);
1100
+ }
1101
+ }
1102
+ `);
1103
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, styleTag, /* @__PURE__ */ React.createElement("div", { style: overlayStyle }, /* @__PURE__ */ React.createElement("div", { style: modalStyle }, /* @__PURE__ */ React.createElement("div", { style: headerStyle }, /* @__PURE__ */ React.createElement(
1104
+ "button",
1105
+ {
1106
+ onClick: onCancel,
1107
+ onMouseEnter: () => setIsHoveringClose(true),
1108
+ onMouseLeave: () => setIsHoveringClose(false),
1109
+ style: closeButtonStyle,
1110
+ "aria-label": "Close"
1111
+ },
1112
+ /* @__PURE__ */ React.createElement("img", { src: Close, alt: "Close Icon", width: 16, height: 16 })
1113
+ ), /* @__PURE__ */ React.createElement("h2", { style: titleStyle }, "Face Verification"), /* @__PURE__ */ React.createElement("p", { style: subtitleStyle }, "Please capture or upload a clear photo of your face")), /* @__PURE__ */ React.createElement("div", { style: contentStyle }, /* @__PURE__ */ React.createElement("div", { style: visualGuideContainerStyle }, /* @__PURE__ */ React.createElement("div", { style: visualGuideStyle }, /* @__PURE__ */ React.createElement("div", { style: circleStyle }, /* @__PURE__ */ React.createElement("img", { src: Camera, alt: "Camera Icon", width: 48, height: 48 })), /* @__PURE__ */ React.createElement("div", { style: badgeStyle }, /* @__PURE__ */ React.createElement("img", { src: Done, alt: "Check Icon", width: 16, height: 16 })))), /* @__PURE__ */ React.createElement("div", { style: instructionsBoxStyle }, /* @__PURE__ */ React.createElement("h3", { style: instructionsTitleStyle }, "Tips for best results:"), /* @__PURE__ */ React.createElement("ul", { style: instructionsListStyle }, /* @__PURE__ */ React.createElement("li", { style: instructionItemStyle }, /* @__PURE__ */ React.createElement("span", { style: bulletStyle }, "\u2022"), /* @__PURE__ */ React.createElement("span", null, "Ensure good lighting on your face")), /* @__PURE__ */ React.createElement("li", { style: instructionItemStyle }, /* @__PURE__ */ React.createElement("span", { style: bulletStyle }, "\u2022"), /* @__PURE__ */ React.createElement("span", null, "Remove glasses or accessories if possible")), /* @__PURE__ */ React.createElement("li", { style: instructionItemStyle }, /* @__PURE__ */ React.createElement("span", { style: bulletStyle }, "\u2022"), /* @__PURE__ */ React.createElement("span", null, "Look directly at the camera")))), /* @__PURE__ */ React.createElement(
1114
+ "input",
1115
+ {
1116
+ ref: inputRef,
1117
+ type: "file",
1118
+ accept: "image/*",
1119
+ capture: isMobile ? "user" : void 0,
1120
+ style: hiddenInputStyle,
1121
+ onChange: handleFileChange,
1122
+ disabled: isProcessing
1123
+ }
1124
+ ), /* @__PURE__ */ React.createElement("div", { style: buttonsContainerStyle }, /* @__PURE__ */ React.createElement(
1125
+ "button",
1126
+ {
1127
+ onClick: () => inputRef.current?.click(),
1128
+ onMouseEnter: () => setIsHoveringPrimary(true),
1129
+ onMouseLeave: () => setIsHoveringPrimary(false),
1130
+ disabled: isProcessing,
1131
+ style: primaryButtonStyle
1132
+ },
1133
+ isProcessing ? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", { style: spinnerStyle }), /* @__PURE__ */ React.createElement("span", null, "Processing...")) : /* @__PURE__ */ React.createElement(React.Fragment, null, isMobile ? /* @__PURE__ */ React.createElement("img", { src: Camera, alt: "Camera Icon", width: 20, height: 20 }) : /* @__PURE__ */ React.createElement("img", { src: Upload, alt: "Upload Icon", width: 20, height: 20 }), /* @__PURE__ */ React.createElement("span", null, isMobile ? "Capture Photo" : "Upload Photo"))
1134
+ ), /* @__PURE__ */ React.createElement(
1135
+ "button",
1136
+ {
1137
+ onClick: onCancel,
1138
+ onMouseEnter: () => setIsHoveringCancel(true),
1139
+ onMouseLeave: () => setIsHoveringCancel(false),
1140
+ disabled: isProcessing,
1141
+ style: cancelButtonStyle
1142
+ },
1143
+ "Cancel"
1144
+ ))), /* @__PURE__ */ React.createElement("div", { style: footerStyle }, /* @__PURE__ */ React.createElement("p", { style: footerTextStyle }, "Your photo will be securely processed and used only for verification purposes")))));
1145
+ }
1146
+ var FaceCaptureModal_default = FaceCaptureModal;
1147
+
1148
+ // src/kyc/hooks.ts
850
1149
  function useAutoFetch(autoFetch, fetchFn) {
851
1150
  useEffect(() => {
852
1151
  if (autoFetch) {
@@ -1127,7 +1426,7 @@ function useKycPreferences(client, autoFetch = true) {
1127
1426
  refresh: fetchPreferences
1128
1427
  };
1129
1428
  }
1130
- function fileToBase64(file) {
1429
+ function fileToBase642(file) {
1131
1430
  return new Promise((resolve, reject) => {
1132
1431
  const reader = new FileReader();
1133
1432
  reader.onload = () => {
@@ -1183,7 +1482,42 @@ function getRiskColor(risk) {
1183
1482
  };
1184
1483
  return colorMap[risk] || "#6b7280";
1185
1484
  }
1485
+ function useReuseKYCSubmission(client) {
1486
+ const verifyFace = (reference, token) => {
1487
+ return new Promise((resolve, reject) => {
1488
+ const container = document.createElement("div");
1489
+ document.body.appendChild(container);
1490
+ const root = createRoot(container);
1491
+ const cleanup = () => {
1492
+ root.unmount();
1493
+ document.body.removeChild(container);
1494
+ };
1495
+ const modal = createElement(FaceCaptureModal_default, {
1496
+ onCapture: async (base64) => {
1497
+ try {
1498
+ const resp = await client.submitReuseKycSession({
1499
+ proof: base64,
1500
+ reference,
1501
+ token
1502
+ });
1503
+ resolve(resp);
1504
+ } catch (error) {
1505
+ reject(error instanceof Error ? error : new Error("Face verification failed"));
1506
+ } finally {
1507
+ cleanup();
1508
+ }
1509
+ },
1510
+ onCancel: () => {
1511
+ cleanup();
1512
+ resolve(null);
1513
+ }
1514
+ });
1515
+ root.render(modal);
1516
+ });
1517
+ };
1518
+ return { verifyFace };
1519
+ }
1186
1520
 
1187
- export { createDeviceFingerprint, fileToBase64, formatKycStatus, getBrowserInfo, getRiskColor, getStatusColor, isValidFileSize, isValidFileType, useCipherText, useCustomerProfile, useGeolocation, useKycAlerts, useKycOverview, useKycPreferences, useKycRequests, useKycSubmission, useLocationCapture, useLocationRequests, useLoginVerification, useRegistration, useTransactionVerification };
1521
+ export { createDeviceFingerprint, fileToBase642 as fileToBase64, formatKycStatus, getBrowserInfo, getRiskColor, getStatusColor, isValidFileSize, isValidFileType, useCipherText, useCustomerProfile, useGeolocation, useKycAlerts, useKycOverview, useKycPreferences, useKycRequests, useKycSubmission, useLocationCapture, useLocationRequests, useLoginVerification, useRegistration, useReuseKYCSubmission, useTransactionVerification };
1188
1522
  //# sourceMappingURL=react.mjs.map
1189
1523
  //# sourceMappingURL=react.mjs.map