gbc-kyc-kit 2.3.5 → 2.3.6

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.
@@ -39414,6 +39414,109 @@ const DocumentReaderController = (dataDocument, clientId, authorize, eventId, so
39414
39414
  const validateErrorMessageOCR = (message) => {
39415
39415
  return message === "Tipo de documento no v\xE1lido" || message === "Datos de la imagen no reconocidas" || message === "Dato no reconocido(Primer Nombre)" || message == "Dato no reconocido(Primer Apellido)" || message == "";
39416
39416
  };
39417
+ const DocumentGuide = ({
39418
+ documentType = "id"
39419
+ }) => {
39420
+ const getGuideDimensions = () => {
39421
+ switch (documentType) {
39422
+ case "passport":
39423
+ return {
39424
+ width: "85%",
39425
+ height: "60%",
39426
+ aspectRatio: "1.4"
39427
+ };
39428
+ case "driverLicense":
39429
+ return {
39430
+ width: "85%",
39431
+ height: "55%",
39432
+ aspectRatio: "1.6"
39433
+ };
39434
+ case "id":
39435
+ default:
39436
+ return {
39437
+ width: "85%",
39438
+ height: "55%",
39439
+ aspectRatio: "1.6"
39440
+ };
39441
+ }
39442
+ };
39443
+ const dimensions = getGuideDimensions();
39444
+ return /* @__PURE__ */ jsxs(Box$1, {
39445
+ sx: {
39446
+ position: "absolute",
39447
+ top: "50%",
39448
+ left: "50%",
39449
+ transform: "translate(-50%, -50%)",
39450
+ width: dimensions.width,
39451
+ height: dimensions.height,
39452
+ border: "2px dashed rgba(255, 255, 255, 0.7)",
39453
+ borderRadius: "8px",
39454
+ display: "flex",
39455
+ flexDirection: "column",
39456
+ justifyContent: "center",
39457
+ alignItems: "center",
39458
+ zIndex: 5,
39459
+ pointerEvents: "none"
39460
+ },
39461
+ children: [/* @__PURE__ */ jsx$1(Box$1, {
39462
+ sx: {
39463
+ position: "absolute",
39464
+ top: 0,
39465
+ left: 0,
39466
+ width: "20px",
39467
+ height: "20px",
39468
+ borderTop: "3px solid #4CAF50",
39469
+ borderLeft: "3px solid #4CAF50",
39470
+ borderTopLeftRadius: "8px"
39471
+ }
39472
+ }), /* @__PURE__ */ jsx$1(Box$1, {
39473
+ sx: {
39474
+ position: "absolute",
39475
+ top: 0,
39476
+ right: 0,
39477
+ width: "20px",
39478
+ height: "20px",
39479
+ borderTop: "3px solid #4CAF50",
39480
+ borderRight: "3px solid #4CAF50",
39481
+ borderTopRightRadius: "8px"
39482
+ }
39483
+ }), /* @__PURE__ */ jsx$1(Box$1, {
39484
+ sx: {
39485
+ position: "absolute",
39486
+ bottom: 0,
39487
+ left: 0,
39488
+ width: "20px",
39489
+ height: "20px",
39490
+ borderBottom: "3px solid #4CAF50",
39491
+ borderLeft: "3px solid #4CAF50",
39492
+ borderBottomLeftRadius: "8px"
39493
+ }
39494
+ }), /* @__PURE__ */ jsx$1(Box$1, {
39495
+ sx: {
39496
+ position: "absolute",
39497
+ bottom: 0,
39498
+ right: 0,
39499
+ width: "20px",
39500
+ height: "20px",
39501
+ borderBottom: "3px solid #4CAF50",
39502
+ borderRight: "3px solid #4CAF50",
39503
+ borderBottomRightRadius: "8px"
39504
+ }
39505
+ }), /* @__PURE__ */ jsx$1(Typography$1, {
39506
+ variant: "body2",
39507
+ sx: {
39508
+ color: "white",
39509
+ textShadow: "0px 0px 3px rgba(0,0,0,0.8)",
39510
+ textAlign: "center",
39511
+ padding: "0 10px",
39512
+ backgroundColor: "rgba(0,0,0,0.5)",
39513
+ borderRadius: "4px",
39514
+ marginTop: "10px"
39515
+ },
39516
+ children: "Coloca el documento dentro del marco"
39517
+ })]
39518
+ });
39519
+ };
39417
39520
  function UploadDocument2({
39418
39521
  setActivateCamera,
39419
39522
  activateCamera,
@@ -39422,13 +39525,25 @@ function UploadDocument2({
39422
39525
  videoRef,
39423
39526
  streamRef,
39424
39527
  onTapToFocus,
39425
- title
39528
+ title,
39529
+ documentType = "id"
39426
39530
  }) {
39531
+ const [focusing, setFocusing] = useState(false);
39532
+ const [focusIndicator, setFocusIndicator] = useState(false);
39427
39533
  useEffect(() => {
39428
39534
  if (activateCamera && videoRef.current) {
39429
39535
  navigator.mediaDevices.getUserMedia({
39430
- video: videoConstraints || {
39431
- facingMode: "environment"
39536
+ video: {
39537
+ ...videoConstraints || {
39538
+ facingMode: "environment"
39539
+ },
39540
+ advanced: [{
39541
+ focusMode: "continuous"
39542
+ }, {
39543
+ exposureMode: "continuous"
39544
+ }, {
39545
+ whiteBalanceMode: "continuous"
39546
+ }]
39432
39547
  },
39433
39548
  audio: false
39434
39549
  }).then((stream) => {
@@ -39448,6 +39563,20 @@ function UploadDocument2({
39448
39563
  }
39449
39564
  };
39450
39565
  }, [activateCamera, videoConstraints]);
39566
+ const handleTapToFocus = async (e2) => {
39567
+ setFocusing(true);
39568
+ setFocusIndicator(true);
39569
+ const rect = e2.currentTarget.getBoundingClientRect();
39570
+ (e2.clientX - rect.left) / rect.width;
39571
+ (e2.clientY - rect.top) / rect.height;
39572
+ await onTapToFocus();
39573
+ setTimeout(() => {
39574
+ setFocusing(false);
39575
+ setTimeout(() => {
39576
+ setFocusIndicator(false);
39577
+ }, 500);
39578
+ }, 1e3);
39579
+ };
39451
39580
  return /* @__PURE__ */ jsx$1("div", {
39452
39581
  className: "drag-zone",
39453
39582
  children: /* @__PURE__ */ jsx$1(Box$1, {
@@ -39462,8 +39591,11 @@ function UploadDocument2({
39462
39591
  display: "flex",
39463
39592
  justifyContent: "center",
39464
39593
  alignItems: "center",
39465
- children: activateCamera ? /* @__PURE__ */ jsx$1(Box$1, {
39466
- children: /* @__PURE__ */ jsx$1("video", {
39594
+ children: activateCamera ? /* @__PURE__ */ jsxs(Box$1, {
39595
+ position: "relative",
39596
+ width: "100%",
39597
+ height: "100%",
39598
+ children: [/* @__PURE__ */ jsx$1("video", {
39467
39599
  ref: videoRef,
39468
39600
  style: {
39469
39601
  width: "100%",
@@ -39475,11 +39607,61 @@ function UploadDocument2({
39475
39607
  transform: "translate(-50%, -50%)",
39476
39608
  borderRadius: "5px"
39477
39609
  },
39478
- onClick: onTapToFocus,
39610
+ onClick: handleTapToFocus,
39479
39611
  playsInline: true,
39480
39612
  muted: true,
39481
39613
  autoPlay: true
39482
- })
39614
+ }), /* @__PURE__ */ jsx$1(DocumentGuide, {
39615
+ documentType
39616
+ }), focusIndicator && /* @__PURE__ */ jsx$1(Box$1, {
39617
+ sx: {
39618
+ position: "absolute",
39619
+ top: "50%",
39620
+ left: "50%",
39621
+ transform: "translate(-50%, -50%)",
39622
+ width: "80px",
39623
+ height: "80px",
39624
+ border: "2px solid white",
39625
+ borderRadius: "50%",
39626
+ display: "flex",
39627
+ justifyContent: "center",
39628
+ alignItems: "center",
39629
+ zIndex: 10,
39630
+ animation: focusing ? "pulse 1s" : "none",
39631
+ "@keyframes pulse": {
39632
+ "0%": {
39633
+ transform: "translate(-50%, -50%) scale(1)",
39634
+ opacity: 1
39635
+ },
39636
+ "50%": {
39637
+ transform: "translate(-50%, -50%) scale(1.2)",
39638
+ opacity: 0.7
39639
+ },
39640
+ "100%": {
39641
+ transform: "translate(-50%, -50%) scale(1)",
39642
+ opacity: 1
39643
+ }
39644
+ }
39645
+ },
39646
+ children: focusing && /* @__PURE__ */ jsx$1(CircularProgress$1, {
39647
+ size: 40,
39648
+ color: "primary"
39649
+ })
39650
+ }), /* @__PURE__ */ jsx$1(Box$1, {
39651
+ sx: {
39652
+ position: "absolute",
39653
+ bottom: "10px",
39654
+ left: "50%",
39655
+ transform: "translateX(-50%)",
39656
+ backgroundColor: "rgba(0, 0, 0, 0.6)",
39657
+ color: "white",
39658
+ padding: "8px 16px",
39659
+ borderRadius: "20px",
39660
+ fontSize: "14px",
39661
+ zIndex: 10
39662
+ },
39663
+ children: "Toca la pantalla para enfocar en el documento"
39664
+ })]
39483
39665
  }) : /* @__PURE__ */ jsxs(Box$1, {
39484
39666
  children: [/* @__PURE__ */ jsx$1(CloudUploadIcon, {}), /* @__PURE__ */ jsx$1(Typography$1, {
39485
39667
  variant: "h6",
@@ -39618,6 +39800,46 @@ const createCanvasFromSource = (source2) => {
39618
39800
  ctx == null ? void 0 : ctx.drawImage(source2, 0, 0, width2, height2);
39619
39801
  return { canvas, ctx };
39620
39802
  };
39803
+ const analyzeFocusQuality = async (imageData) => {
39804
+ return new Promise((resolve) => {
39805
+ if (typeof imageData === "string") {
39806
+ const img = new Image();
39807
+ img.onload = () => {
39808
+ const { canvas, ctx } = createCanvasFromSource(img);
39809
+ const result = calculateSharpness(canvas, ctx);
39810
+ resolve(result);
39811
+ };
39812
+ img.src = imageData;
39813
+ } else {
39814
+ const result = calculateSharpness(imageData, imageData.getContext("2d"));
39815
+ resolve(result);
39816
+ }
39817
+ });
39818
+ };
39819
+ const calculateSharpness = (canvas, ctx) => {
39820
+ if (!ctx) {
39821
+ return { isFocused: false, sharpness: 0 };
39822
+ }
39823
+ const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
39824
+ const data2 = imageData.data;
39825
+ let sum = 0;
39826
+ let sumSquared = 0;
39827
+ let count = 0;
39828
+ for (let i = 0; i < data2.length; i += 4) {
39829
+ const luminance = (data2[i] + data2[i + 1] + data2[i + 2]) / 3;
39830
+ sum += luminance;
39831
+ sumSquared += luminance * luminance;
39832
+ count++;
39833
+ }
39834
+ const mean = sum / count;
39835
+ const variance = sumSquared / count - mean * mean;
39836
+ const normalizedVariance = Math.min(variance / 1e3, 1);
39837
+ const isFocused = normalizedVariance > 0.3;
39838
+ return {
39839
+ isFocused,
39840
+ sharpness: normalizedVariance
39841
+ };
39842
+ };
39621
39843
  const isLowEndDevice = () => {
39622
39844
  const cores = navigator.hardwareConcurrency || 2;
39623
39845
  const memory = navigator.deviceMemory || 2;
@@ -39681,11 +39903,12 @@ function SideDocsSelector({
39681
39903
  uploadDocumentByPhone,
39682
39904
  uploadByGallery,
39683
39905
  setUploadDocumentByPhone,
39684
- onSendSubmitDocument
39906
+ onSendSubmitDocument,
39907
+ documentType = "id"
39685
39908
  }) {
39686
39909
  const [value, setValue] = React$2.useState(0);
39687
39910
  const [showZoom, setShowZoom] = React$2.useState(false);
39688
- useState(0);
39911
+ const [countAnalyzedImage, setCountAnalyzedImage] = useState(0);
39689
39912
  const [hideCaptureButton, setHideCaptureButton] = useState(false);
39690
39913
  const [startUpload, setStartUpload] = useState(false);
39691
39914
  const handleChange = (event, newValue) => {
@@ -39703,16 +39926,6 @@ function SideDocsSelector({
39703
39926
  };
39704
39927
  const videoRef = useRef(null);
39705
39928
  const streamRef = useRef(null);
39706
- const takeScreenshot = async (side) => {
39707
- const video = videoRef.current;
39708
- if (!video)
39709
- return;
39710
- const {
39711
- canvas
39712
- } = createCanvasFromSource(video);
39713
- const imageData = canvas.toDataURL("image/jpeg");
39714
- onUploadImage2(side, imageData);
39715
- };
39716
39929
  const handleTapToFocus = async () => {
39717
39930
  var _a, _b;
39718
39931
  if (!streamRef.current)
@@ -39722,12 +39935,12 @@ function SideDocsSelector({
39722
39935
  const settings = (_b = track.getSettings) == null ? void 0 : _b.call(track);
39723
39936
  console.log("focus capabilities:", capabilities);
39724
39937
  console.log("focus settings:", settings);
39725
- if (!capabilities || !capabilities.focusMode) {
39726
- console.warn("No se puede acceder a las capacidades de enfoque");
39938
+ if (!capabilities) {
39939
+ console.warn("No se puede acceder a las capacidades de la c\xE1mara");
39727
39940
  return;
39728
39941
  }
39729
39942
  try {
39730
- if (capabilities.focusMode.includes("continuous")) {
39943
+ if (capabilities.focusMode && capabilities.focusMode.includes("continuous")) {
39731
39944
  await track.applyConstraints({
39732
39945
  frameRate: {
39733
39946
  ideal: 30
@@ -39736,7 +39949,8 @@ function SideDocsSelector({
39736
39949
  focusMode: "continuous"
39737
39950
  }]
39738
39951
  });
39739
- } else if (capabilities.focusMode.includes("single-shot")) {
39952
+ console.log("Enfoque continuo aplicado");
39953
+ } else if (capabilities.focusMode && capabilities.focusMode.includes("single-shot")) {
39740
39954
  await track.applyConstraints({
39741
39955
  frameRate: {
39742
39956
  ideal: 30
@@ -39745,23 +39959,77 @@ function SideDocsSelector({
39745
39959
  focusMode: "single-shot"
39746
39960
  }]
39747
39961
  });
39748
- } else if (capabilities.focusMode.includes("manual") && capabilities.focusDistance) {
39962
+ console.log("Enfoque de disparo \xFAnico aplicado");
39963
+ } else if (capabilities.focusMode && capabilities.focusMode.includes("manual") && capabilities.focusDistance) {
39964
+ const midDistance = (capabilities.focusDistance.min + capabilities.focusDistance.max) / 2;
39749
39965
  await track.applyConstraints({
39750
39966
  frameRate: {
39751
39967
  ideal: 30
39752
39968
  },
39753
39969
  advanced: [{
39754
39970
  focusMode: "manual",
39755
- focusDistance: capabilities.focusDistance.min
39971
+ focusDistance: midDistance
39756
39972
  }]
39757
39973
  });
39974
+ console.log("Enfoque manual aplicado a distancia media");
39758
39975
  } else {
39759
39976
  console.warn("No hay modo de enfoque compatible");
39760
39977
  }
39978
+ if (capabilities.exposureMode && capabilities.exposureMode.includes("continuous")) {
39979
+ await track.applyConstraints({
39980
+ advanced: [{
39981
+ exposureMode: "continuous"
39982
+ }]
39983
+ });
39984
+ console.log("Exposici\xF3n continua aplicada");
39985
+ }
39986
+ if (capabilities.whiteBalanceMode && capabilities.whiteBalanceMode.includes("continuous")) {
39987
+ await track.applyConstraints({
39988
+ advanced: [{
39989
+ whiteBalanceMode: "continuous"
39990
+ }]
39991
+ });
39992
+ console.log("Balance de blancos continuo aplicado");
39993
+ }
39994
+ setTimeout(async () => {
39995
+ var _a2;
39996
+ const newSettings = (_a2 = track.getSettings) == null ? void 0 : _a2.call(track);
39997
+ console.log("Nuevos ajustes despu\xE9s del enfoque:", newSettings);
39998
+ }, 1e3);
39761
39999
  } catch (err) {
39762
40000
  console.error("Error al aplicar constraints de enfoque:", err);
39763
40001
  }
39764
40002
  };
40003
+ const checkFocusQuality = async (imageData) => {
40004
+ return await analyzeFocusQuality(imageData);
40005
+ };
40006
+ const takeScreenshot = async (side) => {
40007
+ const video = videoRef.current;
40008
+ if (!video)
40009
+ return;
40010
+ const {
40011
+ canvas
40012
+ } = createCanvasFromSource(video);
40013
+ const imageData = canvas.toDataURL("image/jpeg");
40014
+ const {
40015
+ isFocused,
40016
+ sharpness
40017
+ } = await checkFocusQuality(imageData);
40018
+ if (isFocused && sharpness > 0.3) {
40019
+ onUploadImage2(side, imageData);
40020
+ } else {
40021
+ setCountAnalyzedImage((prevState) => {
40022
+ return prevState + 1;
40023
+ });
40024
+ if (countAnalyzedImage >= 1) {
40025
+ setUploadDocumentByPhone(true);
40026
+ setHideCaptureButton(true);
40027
+ setCountAnalyzedImage(0);
40028
+ } else {
40029
+ alert("La imagen no est\xE1 bien enfocada. Por favor, toca la pantalla para enfocar en el documento y vuelve a intentarlo.");
40030
+ }
40031
+ }
40032
+ };
39765
40033
  const fileInputRef = useRef(null);
39766
40034
  const handleFileChange = async (e2) => {
39767
40035
  const imageData = e2.target.files[0];
@@ -39900,7 +40168,8 @@ function SideDocsSelector({
39900
40168
  videoConstraints,
39901
40169
  detail: "Subir frontal del documento",
39902
40170
  onTapToFocus: handleTapToFocus,
39903
- title: "Cargar documento"
40171
+ title: "Cargar documento",
40172
+ documentType
39904
40173
  }), /* @__PURE__ */ jsxs(Box$1, {
39905
40174
  width: "100%",
39906
40175
  children: [activateCamera && !hideCaptureButton && /* @__PURE__ */ jsx$1(CustomButton, {
@@ -40015,7 +40284,8 @@ function SideDocsSelector({
40015
40284
  videoConstraints,
40016
40285
  title: "Bien ahora carguemos el reverso",
40017
40286
  detail: "Asegurate de que sea legible",
40018
- onTapToFocus: handleTapToFocus
40287
+ onTapToFocus: handleTapToFocus,
40288
+ documentType
40019
40289
  }), /* @__PURE__ */ jsxs(Box$1, {
40020
40290
  width: "100%",
40021
40291
  children: [activateCamera && !hideCaptureButton && /* @__PURE__ */ jsx$1(CustomButton, {