@swan-admin/swan-web-component 1.0.121 → 1.0.122

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 (169) hide show
  1. package/dist/BodyScan-B5BvnBHj.js +3 -0
  2. package/dist/BodyScan-B5BvnBHj.js.map +1 -0
  3. package/dist/BodyScan-CL9reolN.mjs +3 -0
  4. package/dist/BodyScan-CL9reolN.mjs.map +1 -0
  5. package/dist/FaceScan-BdcqQIJ5.mjs +3 -0
  6. package/dist/FaceScan-BdcqQIJ5.mjs.map +1 -0
  7. package/dist/{FaceScan-BRdpV_Yn.js → FaceScan-lUHosRqk.js} +3 -2
  8. package/dist/{FaceScan-BRdpV_Yn.js.map → FaceScan-lUHosRqk.js.map} +1 -1
  9. package/dist/{Modal-HTYYx7sM.js → Modal-DxgejzjH.js} +3 -2
  10. package/dist/{Modal-YZScjwEm.js.map → Modal-DxgejzjH.js.map} +1 -1
  11. package/dist/{Modal-BPtRtRVC.js → Modal-TzaSySDr.mjs} +3 -2
  12. package/dist/Modal-TzaSySDr.mjs.map +1 -0
  13. package/dist/bodyScan.d.ts +2 -2
  14. package/dist/bodyScan.js +2 -1
  15. package/dist/bodyScan.mjs +2 -1
  16. package/dist/faceScan.js +2 -1
  17. package/dist/faceScan.mjs +2 -1
  18. package/dist/index.css +1 -1
  19. package/dist/index.js +2 -1
  20. package/dist/index.js.map +1 -1
  21. package/dist/index.mjs +2 -1
  22. package/dist/index.mjs.map +1 -1
  23. package/dist/{pose-detection.esm-Bc8T4UAD.js → pose-detection.esm-BV7VgekA.js} +2 -1
  24. package/dist/{pose-detection.esm-Bc8T4UAD.js.map → pose-detection.esm-BV7VgekA.js.map} +1 -1
  25. package/dist/{pose-detection.esm-DC0_P6R7.js → pose-detection.esm-D8r1CbkV.mjs} +2 -1
  26. package/dist/pose-detection.esm-D8r1CbkV.mjs.map +1 -0
  27. package/package.json +3 -2
  28. package/dist/BodyScan-3YoMZG7n.js +0 -2
  29. package/dist/BodyScan-8qgqyl5-.js +0 -2
  30. package/dist/BodyScan-B0qqqK3C.js +0 -2
  31. package/dist/BodyScan-B1VBoA6S.js +0 -2
  32. package/dist/BodyScan-B1afPG1Q.js +0 -2
  33. package/dist/BodyScan-B1afPG1Q.js.map +0 -1
  34. package/dist/BodyScan-B4-sO3R2.js +0 -2
  35. package/dist/BodyScan-B87W6dpH.js +0 -2
  36. package/dist/BodyScan-B8pglBAp.js +0 -2
  37. package/dist/BodyScan-BEFwluXG.js +0 -2
  38. package/dist/BodyScan-BHgnqB6A.js +0 -2
  39. package/dist/BodyScan-BLvWlYnA.js +0 -2
  40. package/dist/BodyScan-BMAkl5Iw.js +0 -2
  41. package/dist/BodyScan-BMTK6e-E.js +0 -2
  42. package/dist/BodyScan-BQri8pAO.js +0 -2
  43. package/dist/BodyScan-BVNPC7bJ.js +0 -2
  44. package/dist/BodyScan-BfLKF5PU.js +0 -2
  45. package/dist/BodyScan-BjYHCskz.js +0 -2
  46. package/dist/BodyScan-BoAbG01d.js +0 -2
  47. package/dist/BodyScan-Bq64fsmL.js +0 -2
  48. package/dist/BodyScan-Bre1BIHK.js +0 -2
  49. package/dist/BodyScan-BsDJmy0G.js +0 -2
  50. package/dist/BodyScan-ByMGumuH.js +0 -2
  51. package/dist/BodyScan-C0V-EDdB.js +0 -2
  52. package/dist/BodyScan-C1dWJ2qu.js +0 -2
  53. package/dist/BodyScan-C43x2o2T.js +0 -2
  54. package/dist/BodyScan-C57PuQgF.js +0 -2
  55. package/dist/BodyScan-C9hQU-dK.js +0 -2
  56. package/dist/BodyScan-CA4rNyqL.js +0 -2
  57. package/dist/BodyScan-CH-_x55M.js +0 -2
  58. package/dist/BodyScan-CKH_WyTt.js +0 -2
  59. package/dist/BodyScan-CKmPcrkx.js +0 -2
  60. package/dist/BodyScan-CLpL3Uwx.js +0 -2
  61. package/dist/BodyScan-CM12T_-T.js +0 -2
  62. package/dist/BodyScan-CNhb6UOX.js +0 -2
  63. package/dist/BodyScan-CWsaPB8W.js +0 -2
  64. package/dist/BodyScan-CXwtxfOd.js +0 -2
  65. package/dist/BodyScan-CYn7eLoz.js +0 -2
  66. package/dist/BodyScan-CYnHFqsR.js +0 -2
  67. package/dist/BodyScan-CZTiQzpy.js +0 -2
  68. package/dist/BodyScan-Cc68SnU1.js +0 -2
  69. package/dist/BodyScan-CfS4bPCN.js +0 -2
  70. package/dist/BodyScan-CiG19l_n.js +0 -2
  71. package/dist/BodyScan-CjvyMLT9.js +0 -2
  72. package/dist/BodyScan-CkmrPAq9.js +0 -2
  73. package/dist/BodyScan-CoObDhac.js +0 -2
  74. package/dist/BodyScan-Cyfo46EK.js +0 -2
  75. package/dist/BodyScan-Cz9ggKm6.js +0 -2
  76. package/dist/BodyScan-D6Y_W5e2.js +0 -2
  77. package/dist/BodyScan-DCEgmVbG.js +0 -2
  78. package/dist/BodyScan-DEDdENv7.js +0 -2
  79. package/dist/BodyScan-DEdrK-ld.js +0 -2
  80. package/dist/BodyScan-DHMf2V5R.js +0 -2
  81. package/dist/BodyScan-DK9UmNBr.js +0 -2
  82. package/dist/BodyScan-DPCd26i-.js +0 -2
  83. package/dist/BodyScan-DPCd26i-.js.map +0 -1
  84. package/dist/BodyScan-DPSQ1hKh.js +0 -2
  85. package/dist/BodyScan-DVKnmJuJ.js +0 -2
  86. package/dist/BodyScan-DX_KbG5U.js +0 -2
  87. package/dist/BodyScan-DbfP9-G3.js +0 -2
  88. package/dist/BodyScan-DeBJWo0L.js +0 -2
  89. package/dist/BodyScan-DgZpiChn.js +0 -2
  90. package/dist/BodyScan-DkPwUgVu.js +0 -2
  91. package/dist/BodyScan-DntA0MBx.js +0 -2
  92. package/dist/BodyScan-DxidLEhk.js +0 -2
  93. package/dist/BodyScan-DyDxGqfI.js +0 -2
  94. package/dist/BodyScan-Dysj7b77.js +0 -2
  95. package/dist/BodyScan-DzyamZmb.js +0 -2
  96. package/dist/BodyScan-Ehsr_cYc.js +0 -2
  97. package/dist/BodyScan-MSB66I12.js +0 -2
  98. package/dist/BodyScan-Ot6nAH1j.js +0 -2
  99. package/dist/BodyScan-Srq29PK8.js +0 -2
  100. package/dist/BodyScan-SzaquTgH.js +0 -2
  101. package/dist/BodyScan-TPpfyief.js +0 -2
  102. package/dist/BodyScan-XW2vsiE3.js +0 -2
  103. package/dist/BodyScan-eUuIC3jY.js +0 -2
  104. package/dist/BodyScan-enDyqSjO.js +0 -2
  105. package/dist/BodyScan-iOXndWaO.js +0 -2
  106. package/dist/BodyScan-qVHOWabf.js +0 -2
  107. package/dist/BodyScan-t9qdQAL-.js +0 -2
  108. package/dist/BodyScan-twE2YOwy.js +0 -2
  109. package/dist/BodyScan-z6h5fueJ.js +0 -2
  110. package/dist/FaceScan-3rVSqkKB.js +0 -2
  111. package/dist/FaceScan-6Aoz5uUy.js +0 -2
  112. package/dist/FaceScan-7fl5pLnb.js +0 -2
  113. package/dist/FaceScan-9kUfXRSv.js +0 -2
  114. package/dist/FaceScan-AHZ-ajep.js +0 -2
  115. package/dist/FaceScan-B0pFv4Us.js +0 -2
  116. package/dist/FaceScan-BE0PB0fZ.js +0 -2
  117. package/dist/FaceScan-BWSeJEqI.js +0 -2
  118. package/dist/FaceScan-BdjT7nMG.js +0 -2
  119. package/dist/FaceScan-Bji5lGcQ.js +0 -2
  120. package/dist/FaceScan-Bji5lGcQ.js.map +0 -1
  121. package/dist/FaceScan-BmDNM8tt.js +0 -2
  122. package/dist/FaceScan-CNoW9DIE.js +0 -2
  123. package/dist/FaceScan-CPf6-siO.js +0 -2
  124. package/dist/FaceScan-CQayY4q-.js +0 -2
  125. package/dist/FaceScan-CQkfSMC2.js +0 -2
  126. package/dist/FaceScan-CaxQ6fGF.js +0 -2
  127. package/dist/FaceScan-CxDcvM4f.js +0 -2
  128. package/dist/FaceScan-D2PL8KpZ.js +0 -2
  129. package/dist/FaceScan-D3T_l4nN.js +0 -2
  130. package/dist/FaceScan-DCm43Nrq.js +0 -2
  131. package/dist/FaceScan-DKP93c3l.js +0 -2
  132. package/dist/FaceScan-DW6Ix1a1.js +0 -2
  133. package/dist/FaceScan-DYJVZoZ4.js +0 -2
  134. package/dist/FaceScan-Da2XEApH.js +0 -2
  135. package/dist/FaceScan-DrW2yUSA.js +0 -2
  136. package/dist/FaceScan-DxnydFcx.js +0 -2
  137. package/dist/FaceScan-Gm4F4cO1.js +0 -2
  138. package/dist/FaceScan-Nhc7myLG.js +0 -2
  139. package/dist/FaceScan-VFLJ9h_T.js +0 -2
  140. package/dist/FaceScan-iUXyDuza.js +0 -2
  141. package/dist/LoadingScreen-BILrJVZm.js +0 -2
  142. package/dist/LoadingScreen-FKDLJRUj.js +0 -2
  143. package/dist/Modal-4T_aWWPQ.js +0 -2
  144. package/dist/Modal-BHfJVhRi.js +0 -2
  145. package/dist/Modal-BitizIvu.js +0 -2
  146. package/dist/Modal-BpgpPVxR.js +0 -2
  147. package/dist/Modal-BzH-_ch3.js +0 -2
  148. package/dist/Modal-CB_MHF7l.js +0 -2
  149. package/dist/Modal-CDiBoVXR.js +0 -2
  150. package/dist/Modal-CWoUZTh4.js +0 -2
  151. package/dist/Modal-CaPtqgjI.js +0 -2
  152. package/dist/Modal-CbZJwbLZ.js +0 -2
  153. package/dist/Modal-DRjJKUrw.js +0 -2
  154. package/dist/Modal-DU2Jymve.js +0 -2
  155. package/dist/Modal-D_XGokez.js +0 -2
  156. package/dist/Modal-DnweWp6L.js +0 -2
  157. package/dist/Modal-Do--CErH.js +0 -2
  158. package/dist/Modal-Do--CErH.js.map +0 -1
  159. package/dist/Modal-YZScjwEm.js +0 -2
  160. package/dist/fonts/Switzer-Regular.eot +0 -0
  161. package/dist/fonts/Switzer-Regular.svg +0 -0
  162. package/dist/fonts/Switzer-Regular.ttf +0 -0
  163. package/dist/fonts/Switzer-Regular.woff +0 -0
  164. package/dist/fonts/Switzer-Regular.woff2 +0 -0
  165. package/dist/interfaces-B5ysRXpa.d.ts +0 -209
  166. package/dist/interfaces-CaaERZjZ.d.ts +0 -209
  167. package/dist/pose-detection.esm-D08ZA0zl.js +0 -18
  168. package/dist/pose-detection.esm-DejsYGYM.js +0 -18
  169. package/dist/pose-detection.esm-DejsYGYM.js.map +0 -1
@@ -1,2 +0,0 @@
1
- import{jsx as e,jsxs as t,Fragment as a}from"react/jsx-runtime";import{useRef as n,useState as o,useMemo as r,useCallback as c,useEffect as i,useContext as s}from"react";import{p as l,s as d,v as u,a as m,L as h,u as f,H as g,b as p,S as y,m as S,g as b,G as w,d as v,F as x,P as F,c as N,e as _,f as I,h as k,i as M,j as C,k as D,l as E,n as P,o as T,q as R,r as z,C as $,t as L,w as j,x as V}from"./LoadingScreen-FKDLJRUj.js";import{ArrowRight as O}from"lucide-react";import{Drawer as W}from"@mui/material";let U=null,B=!1;function A({faceScanId:e,onValidPose:t,onScanComplete:a,onModelReady:s,onStartRecording:h,shopDomain:f,isError:g,isSuccess:p}){const y=n(null),[S,b]=o(0),[w,v]=o(0),[x,F]=o(!1),[N,_]=o(!1),I=n(null),k=n(S),M=n(w),C=n([]),D=n(""),E=n(0),P=n(!1),T=n(0),R="undefined"!=typeof navigator&&(/iPad|iPhone|iPod/.test(navigator.userAgent)||"MacIntel"===navigator.platform&&navigator.maxTouchPoints>1),z=r(()=>["Face front","Turn head fully left","Turn head fully right","Smile facing front"],[]),$=r(()=>function(e,t){let a;return(...n)=>{a&&clearTimeout(a),a=setTimeout(()=>e(...n),t)}}(e=>{l.capture(`${f}/face_scan_pose_detection`,e)},4e3),[f]),L=c((t,a,n,o,r,c)=>{const i=Date.now();if(!(i-T.current<4e3)){T.current=i;try{const i=t[0]||[0,0,0],s=t[2]||[0,0,0],l=t[5]||[0,0,0],d=t[9]||[0,0,0],u=t[10]||[0,0,0],m=t.map(e=>e[2]).filter(e=>e>0),h=m.length>0?m.reduce((e,t)=>e+t,0)/m.length:0,f=a.map(e=>e[2]).filter(e=>e>0),g=f.length>0?f.reduce((e,t)=>e+t,0)/f.length:0,p=Math.abs(s[0]-l[0]),y=i[0]-l[0],S=s[0]-i[0];let b="frontal";1===n?b="left":2===n?b="right":3===n&&(b="frontal_smile");const w={faceScanId:e,stage:n,timestamp:(new Date).toISOString(),data:JSON.stringify({headValid:o,bodyInvalid:r,consecutiveValid:c,avgFaceScore:parseFloat(h.toFixed(3)),avgBodyScore:parseFloat(g.toFixed(3)),faceKeypointsDetected:m.length,bodyKeypointsDetected:f.length,eyeDistance:parseFloat(p.toFixed(2)),noseToRightRatio:parseFloat((y/p).toFixed(3)),noseToLeftRatio:parseFloat((S/p).toFixed(3)),noseScore:parseFloat(i[2].toFixed(3)),leftEyeScore:parseFloat(s[2].toFixed(3)),rightEyeScore:parseFloat(l[2].toFixed(3)),leftMouthScore:parseFloat(d[2].toFixed(3)),rightMouthScore:parseFloat(u[2].toFixed(3)),expectedPosition:b})};$(w)}catch(e){console.warn("Failed to track pose detection:",e)}}},[e,$]),j=()=>{l.capture(`${f}/face_scan_detection_started`,{faceScanId:e,stage:k.current,timestamp:(new Date).toISOString(),stageName:z[k.current]}),setTimeout(()=>{_(!0)},1500)},V=async()=>{if("undefined"!=typeof window)try{console.log("Initializing Face Scan...");const e=await(async()=>{if("undefined"==typeof window)return null;if(U)return U;if(B)for(;B;)if(await new Promise(e=>setTimeout(e,100)),U)return U;B=!0;try{const[e,t]=await Promise.all([import("@tensorflow/tfjs"),import("./pose-detection.esm-DejsYGYM.js")]);await e.setBackend("webgl"),await e.ready();const a=await t.createDetector(t.SupportedModels.BlazePose,{runtime:"tfjs",modelType:"full"}),n=document.createElement("canvas");n.width="number"==typeof m.width?m.width:m.width.ideal??m.width.max??1280,n.height="number"==typeof m.height?m.height:m.height.ideal??m.height.max??720;const o=n.getContext("2d");if(o){o.fillStyle="black",o.fillRect(0,0,n.width,n.height);try{await a.estimatePoses(n)}catch(e){console.warn("Warmup frame failed (non-fatal):",e)}}return U=a,a}catch(e){return console.error("Failed to preload detector:",e),null}finally{B=!1}})();e&&(y.current=e,console.log("Face scan model loaded successfully"),F(!0),s?.())}catch(e){console.error("Error initializing face scan:",e)}};return i(()=>{if(!g&&!p)return V(),()=>{(async()=>{try{F(!1)}catch(e){console.error("Error disposing resources:",e)}finally{b(0),v(0),k.current=0,M.current=0,C.current=[]}})()}},[g,p]),i(()=>{k.current=S},[S]),i(()=>{M.current=w},[w]),{faceScanDetector:async(n,o)=>{if(y.current&&n.current&&x&&N&&!(n.current.readyState<2))try{const r=await y.current.estimatePoses(n.current);if(r.length>0){const n=[],c=[];if(r[0].keypoints.forEach((e,t)=>{const a=e.score??0,o=[e.x??-1,e.y??-1,a];t<=10?n.push(o):c.push(o)}),o?.current){const e=o.current.getContext("2d"),{width:t,height:a}=o.current;if(e){e.clearRect(0,0,t,a);const n=Math.min(M.current/2,1),o=.35*a;e.beginPath(),e.strokeStyle="#00ff00",e.lineWidth=6,e.arc(t/2,a/2,o+10,-Math.PI/2,-Math.PI/2+2*n*Math.PI),e.stroke()}}const i=((e,t)=>{if(!t[0]||!t[2]||!t[5]||t[0][2]<.2||t[2][2]<.2||t[5][2]<.2)return!1;const a=.5*(t[10][1]+t[9][1])-.5*(t[5][1]+t[2][1]),n=(.5*(t[10][1]+t[9][1])-t[0][1])/a,o=n>.7||n<.3,r=Math.abs(t[2][1]-t[5][1])<.5*a&&Math.abs(t[9][1]-t[10][1])<.5*a,c=t[2][0]-t[5][0],i=t[0][0]-t[5][0],s=i>.4*c&&i<.6*c,l=i>.85*c,d=t[2][0]-t[0][0]>.85*c;switch(e){case 0:case 3:return!o&&r&&s;case 1:return!o&&r&&l;case 2:return!o&&r&&d;default:return!1}})(k.current,n),s=c.slice(2).filter(e=>e[2]>.7).length<=2;C.current.push(i&&s),C.current.length>10&&C.current.shift();if(C.current.filter(Boolean).length>=2){const e=M.current+1;v(e)}else v(Math.max(0,M.current-1));if(M.current>=2){t?.();const n=k.current+1;v(0),C.current=[],b(n),_(!1),(async()=>{if(await d.playAudio(`${u}face-scan-vos/Sound-effect.mp3`),l.capture(`${f}/face_scan_detection_stage_completed`,{faceScanId:e,completedStage:k.current,nextStage:n,timestamp:(new Date).toISOString(),totalStages:4,stageName:z[k.current]}),1===n&&h&&h(),n>=4)a?.();else{let e=null;switch(n){case 1:e="Left.mp3";break;case 2:e="Right.mp3";break;case 3:e="Smile.mp3"}e&&await d.playAudio(`${u}face-scan-vos/${e}`),j()}})()}L(n,c,k.current,i,s,M.current)}}catch(e){console.error("Pose detection error:",e)}},scanStage:S,setScanStage:b,consecutiveValid:w,isModelLoaded:x,resetScan:()=>{l.capture(`${f}/face_scan_reset`,{faceScanId:e,stage:k.current,timestamp:(new Date).toISOString(),stageName:z[k.current],consecutiveValid:M.current}),b(0),v(0),_(!1),k.current=0,M.current=0,C.current=[],D.current="",E.current=0,P.current=!1,I.current&&(speechSynthesis.cancel(),I.current=null)},enableVoiceCommands:()=>{if(P.current=!0,"undefined"!=typeof window&&R&&"speechSynthesis"in window){const e=new SpeechSynthesisUtterance("");e.volume=0,speechSynthesis.speak(e)}},startScanSequence:j,isScanningActive:N}}function q({onRetry:a,loading:n}){const{translate:o}=s(h)||{},r=f();return e("div",{className:"fixed common-ui-main top-[0] left-[0] z-[999] flex justify-center items-center w-full h-full",style:{background:r?.style?.base?.backgroundColor},children:t("div",{className:"flex flex-col w-full items-center p-[1rem] rounded-lg ",children:[e(g,{noTitle:!0}),t("div",{className:"flex flex-col items-center w-full",children:[e("h2",{className:"text-xl font-semibold text-gray-800 ",style:{fontFamily:r?.style?.heading?.headingFontFamily||"SeriouslyNostalgic Fn",fontSize:r?.style?.heading?.headingFontSize||"32px",color:r?.style?.heading?.headingColor||"#000",fontWeight:r?.style?.heading?.headingFontWeight||"normal"},children:o?.(p.scanFailed)}),e("p",{className:"mb-[1.5rem]",style:{fontFamily:r?.style?.subheading?.subheadingFontFamily||"'Inter', sans-serif",fontSize:r?.style?.subheading?.subheadingFontSize||"14px",color:r?.style?.subheading?.subheadingColor||"#4b5563",fontWeight:r?.style?.subheading?.subheadingFontWeight||"normal"},children:o?.(p.clickToResetScan)}),e(y,{disabled:n,className:"w-full h-[45px] shadow-[0px_1px_2px_0px_#00000040] text-[16px]",buttonText:o?.(p.resetScan),postfixIcon:e(O,{}),buttonFunc:()=>a?.()})]})]})})}function J({stage:a,videoLoading:n,setVideoLoading:o,videoError:r,setVideoError:c,gender:i,btnConfig:l}){const{translate:d}=s(h)||{},u=f();return-1===a?t("div",{className:"text-center common-ui-main p-[16px] w-full h-full",style:{background:u?.style?.base?.backgroundColor},children:[t("div",{className:"w-full",children:[e(g,{noTitle:!0}),e("h2",{style:{fontFamily:u?.style?.heading?.headingFontFamily||"SeriouslyNostalgic Fn",fontSize:u?.style?.heading?.headingFontSize||"32px",color:u?.style?.heading?.headingColor||"#000",fontWeight:u?.style?.heading?.headingFontWeight||"normal"},children:d?.(p.faceVisible)}),n&&e("div",{className:"mb-4 flex items-center justify-center",style:{fontFamily:u?.style?.subheading?.subheadingFontFamily||"'Inter', sans-serif",fontSize:u?.style?.subheading?.subheadingFontSize||"14px",color:u?.style?.subheading?.subheadingColor||"#4b5563",fontWeight:u?.style?.subheading?.subheadingFontWeight||"normal"},children:d?.(p.loadingVideo)}),r&&e("div",{className:"mb-4 text-red-600",style:{fontFamily:u?.style?.subheading?.subheadingFontFamily||"'Inter', sans-serif",fontSize:u?.style?.subheading?.subheadingFontSize||"14px",color:"#ff0000",fontWeight:u?.style?.subheading?.subheadingFontWeight||"normal"},children:d?.(p.videoLoadFailed)}),!r&&e("div",{className:" w-[100px] mx-auto",children:e("video",{src:i===w.Male?S:b,autoPlay:!0,loop:!0,controls:!1,muted:!0,playsInline:!0,className:"h-full w-full object-contain border-none",onCanPlay:()=>o(!1),onLoadStart:()=>o(!0),onError:()=>c(!0),"aria-label":"Instructional video: Please remove your glasses before starting the scan."})})]}),e("div",{className:"flex justify-center w-full p-[1rem]",children:e(y,{disabled:l.isDisabled,className:"!w-[60px] !h-[35px] !py-0 !px-0",buttonText:d?.(l.label),postfixIcon:l?.icon,buttonFunc:l.onClick})})]}):e("div",{className:"text-center common-ui-main p-[16px] w-full h-full",style:{background:u?.style?.base?.backgroundColor},children:t("div",{className:"w-full",children:[e(g,{noTitle:!0}),e("h3",{className:"mb-[0.5rem]",style:{fontFamily:u?.style?.heading?.headingFontFamily||"SeriouslyNostalgic Fn",fontSize:u?.style?.heading?.headingFontSize||"32px",color:u?.style?.heading?.headingColor||"#000",fontWeight:u?.style?.heading?.headingFontWeight||"normal"},children:d?.(v[a])}),t("div",{className:"max-w-[400px] justify-center gap-1 mx-auto flex items-center",children:[e("div",{className:` w-[120px] overflow-hidden ${0===a?"opacity-100":"opacity-0 hidden"} `,children:e("video",{className:"h-full w-full object-contain border-none",muted:!0,loop:!0,autoPlay:!0,playsInline:!0,children:e("source",{src:i===w.Male?x.male.forward:x.female.forward,type:"video/mp4"})})}),e("div",{className:` w-[120px] overflow-hidden ${1===a?"opacity-100":"opacity-0 hidden"} `,children:e("video",{className:"h-full w-full object-contain border-none",muted:!0,loop:!0,autoPlay:!0,playsInline:!0,children:e("source",{src:i===w.Male?x.male.left:x.female.left,type:"video/mp4"})})}),e("div",{className:` w-[120px] overflow-hidden ${2===a?"opacity-100":"opacity-0 hidden"} `,children:e("video",{className:"h-full w-full object-contain border-none",muted:!0,loop:!0,autoPlay:!0,playsInline:!0,children:e("source",{src:i===w.Male?x.male.right:x.female.right,type:"video/mp4"})})}),e("div",{className:` w-[120px] overflow-hidden ${3===a?"opacity-100":"opacity-0 hidden"} `,children:e("video",{className:"h-full w-full object-contain border-none",muted:!0,loop:!0,autoPlay:!0,playsInline:!0,children:e("source",{src:i===w.Male?x.male.smile:x.female.smile,type:"video/mp4"})})})]})]})})}const G=({webcamRef:n,canvasRef:o})=>{const{isError:r,isSuccess:c,showLoader:i,hasError:l,resetScanState:d,showGuideCard:u,scanStage:h,videoLoading:g,setVideoLoading:p,videoError:y,setVideoError:S,gender:b,getButtonText:w,isScanning:v,startScan:x,isModelLoaded:_,onRetry:I}=s(F),k=f();return r?e(q,{onRetry:I}):c?e("div",{className:"fixed z-[9] common-ui-main w-full h-full",style:{background:k?.style?.base?.backgroundColor},children:e(N,{url:k?.loader,loaderType:"black"})}):t(a,{children:[e("audio",{id:"audioElement",crossOrigin:"anonymous",preload:"auto",style:{position:"absolute",zIndex:-99999},src:void 0}),i&&!l&&e("div",{className:"fixed z-[9] common-ui-main w-full h-full",style:{background:k?.style?.base?.backgroundColor},children:e(N,{url:k?.loader,loaderType:"black"})}),e("div",{className:"h-full flex-col common-ui-main relative w-full flex justify-center items-center text-center rounded-t-[20px]",style:{background:k?.style?.base?.backgroundColor},children:e("div",{className:"flex-1 w-full max-w-md overflow-hidden",children:t("div",{className:"w-full h-full",children:[e("video",{ref:n,autoPlay:!0,playsInline:!0,muted:!0,width:m.width.ideal,height:m.height.ideal,className:"w-full h-full object-cover fixed left-0 top-0 z-0",style:{transform:"scaleX(-1)"}}),e("canvas",{ref:o,width:m.width.ideal,height:m.height.ideal,style:{transform:"scaleX(-1)",opacity:"0"}})]})})}),!i&&l&&e(q,{loading:i,onRetry:d}),u&&!l&&!i&&e(W,{open:!0,className:"face-scan-small camera-draw",anchor:"bottom",onClose:(e,t)=>{},hideBackdrop:!0,children:e(J,{stage:h,videoLoading:g,setVideoLoading:p,videoError:y,setVideoError:S,gender:b,btnConfig:{label:w(),onClick:v?d:x,isDisabled:i||!_,icon:e(v?O:a,{})}})})]})},K=t=>{const{onScanSuccess:a,onScanError:s,onRetry:l,onScanStart:m,onCaptureComplete:h,onUploadStart:f,onUploadEnd:g,onMeasurementSocketStart:y,onMeasurementSocketClose:S,config:b,isError:w,isSuccess:v}=t,x=t.userDetails??{email:"",gender:"male",deviceFocalLength:0,shopDomain:"",bodyScanId:""},N=t.token??"",O=n(null),W=n(null),U=n(null),B=n([]),q=n(null),J=n(null),[K,H]=o(!1),[X,Q]=o(!1),[Y,Z]=o(!1),[ee,te]=o(!0),[ae,ne]=o(!1),[oe,re]=o(!1),[ce,ie]=o(!1),[se,le]=o(_()),de=r(()=>I(N),[N]),{email:ue,gender:me,deviceFocalLength:he,shopDomain:fe,callbackUrl:ge,bodyScanId:pe}=x,[ye,Se]=o([]),[be,we]=o(k),ve=r(()=>M(),[]),xe=C(ye),Fe=D(xe);E();const Ne=c(()=>{console.log("Stopping recording..."),U.current&&"recording"===U.current.state&&U.current.stop(),U.current=null},[]),_e=async()=>{if(h?.(),B.current){if(0===B.current.length)return console.error("No video data recorded"),ie(!0),void H(!1);f?.(),H(!0);const e=new File(B.current,`${se}.${Fe}`,{type:xe}),t=J.current??await L(e),a=e.size,n=(a/1048576).toFixed(2),o=Math.round(a/1e4),r={video_size_mb:parseFloat(n),video_size_bytes:a,video_fps:t||0,blob_count:B.current.length,estimated_duration_seconds:o},c=[{gender:me},{face_scan_id:se},{focal_length:`${he}`},{customer_store_url:fe},{scan_type:"face_scan"},{body_scan_id:pe}];ge&&c.push({callback_url:ge}),j({eventName:`${fe}/face_scan_meta_data`,faceScanId:se,email:ue,data:JSON.stringify({metaData:c,videoData:r})});const i=Date.now();j({eventName:`${fe}/face_scan_upload_start`,faceScanId:se,email:ue,startTime:i});try{const t=await de.fileUpload.faceScanFileUploader({file:e,arrayMetaData:c,objectKey:se,email:ue,contentType:e.type}),a=Date.now();j({eventName:`${fe}/face_scan_upload_complete`,faceScanId:se,email:ue,completionTime:a,uploadDuration:a-i}),g?.(),console.log("✅ Upload successful",t),de.measurement.handlFaceScaneSocket({onPreopen:()=>{y?.(),V({eventName:`${fe}/webSocket`,faceScanID:se,connection:"pre_open",type:"faceScan_recommendation",email:ue})},faceScanId:se,onOpen:()=>{V({eventName:`${fe}/webSocket`,faceScanID:se,connection:"open",type:"faceScan_recommendation",email:ue}),console.log("websocket connect open")},onError:e=>{V({eventName:`${fe}/webSocket`,faceScanID:se,connection:"error",type:"faceScan_recommendation",email:ue}),ze(e)},onSuccess:e=>{V({eventName:`${fe}/webSocket`,faceScanID:se,connection:"success",type:"faceScan_recommendation",email:ue}),$e(e)},onClose:()=>{S?.(),console.log("websocket connect close"),V({eventName:`${fe}/webSocket`,faceScanID:se,connection:"close",type:"faceScan_recommendation",email:ue})}})}catch(e){g?.(),ze(e)}}},Ie=c(()=>{const e=O.current?.srcObject;if(!e)return;const t=e.getVideoTracks()[0].getSettings(),{width:a=1280,height:n=720}=t,o=document.createElement("canvas"),r=o.getContext("2d");a>n?(o.width=n,o.height=a):(o.width=a,o.height=n);const c=document.createElement("video");c.srcObject=e,c.muted=!0,c.playsInline=!0,c.play();const i=()=>{a>n?(r?.save(),r?.translate(o.width,0),r?.rotate(Math.PI/2),r?.drawImage(c,0,0,n,a),r?.restore()):r?.drawImage(c,0,0,a,n),requestAnimationFrame(i)};i();const s=t.frameRate??10;J.current=s;const l=o.captureStream(s),d={videoBitsPerSecond:15e5};let u;ye.length>0&&(d.mimeType=ye[0]);try{u=new MediaRecorder(l,d)}catch(e){return console.error("MediaRecorder init failed:",e),ie(!0),void H(!1)}B.current=[],u.ondataavailable=e=>{e?.data&&e.data.size>0&&B.current&&B.current.push(e.data)},u.onstop=()=>{console.log("Recording stopped, total blobs:",B?.current?.length),_e()},u.start(100),U.current=u,console.log("Recording started successfully (portrait normalized)")},[ye,_e]),{faceScanDetector:ke,scanStage:Me,setScanStage:Ce,resetScan:De,isModelLoaded:Ee,startScanSequence:Pe}=A({faceScanId:se,shopDomain:fe,isError:w,isSuccess:v,onScanComplete:()=>{Ne()},onModelReady:()=>{Q(!0)},onStartRecording:()=>{console.log("Stage 0 completed - starting recording for stages 1-3"),Ie()}}),Te=c(()=>{Ee&&(m?.(),Ce(0),d.playAudio(`${u}face-scan-vos/Face-forward.mp3`),setTimeout(()=>{Z(!0),setTimeout(()=>{Pe()},200)},200))},[Ce,Z,Pe,Ee,m]),Re=c(()=>{Z(!1),te(!0),Ne(),De(),l?.(),B.current=[],J.current=null,U.current&&(U.current=null),ie(!1),Ce(-1),le(_()),O.current&&q.current&&(O.current.srcObject=q.current,console.log("Camera stream restored after reset"))},[Ce,Z,te,Ne,De,le]),ze=e=>{console.log(e,"ws error"),s?.(e),ie(!0),H(!1),te(!1),j({eventName:`${fe}/faceScan`,faceScanId:se,status:"failed",email:ue,data:JSON.stringify(e)})},$e=e=>{console.log(e,"ws success"),e&&"intermediate"===e?.resultType&&j({eventName:`${fe}/faceScan_success/intermediate`,faceScanId:se,status:"success",email:ue,data:JSON.stringify(e)}),a?.(e)};i(()=>{if(!w&&!v)return navigator.mediaDevices.getUserMedia&&navigator.mediaDevices.getUserMedia({video:be}).then(e=>{q.current=e,O.current&&(O.current.srcObject=e)}).catch(e=>{console.error("Error accessing webcam:",e),be!==k?ie(!0):we(P)}),()=>{q.current&&q.current.getTracks().forEach(e=>e.stop())}},[w,v,be]),i(()=>{if(!X||!Y)return;const e=setInterval(()=>{ke(O,W)},500);return()=>clearInterval(e)},[ke,X,Y]);return console.log("Model ready:",X,"Has error:",ce,"Is scanning:",Y,"showLoader",K),i(()=>{const e=T(ve,R);Se(e)},[ve]),i(()=>{Ce(-1)},[]),e(z,{children:e($,{config:b,children:e(F.Provider,{value:{isError:w,isSuccess:v,showLoader:K,hasError:ce,resetScanState:Re,showGuideCard:ee,scanStage:Me,videoLoading:ae,setVideoLoading:ne,videoError:oe,setVideoError:re,gender:me,getButtonText:()=>Y?p.reset:Ee?p.start:p.loading,isScanning:Y,startScan:Te,isModelLoaded:Ee,onRetry:l},children:e(G,{webcamRef:O,canvasRef:W})})})})};export{K as F};
2
- //# sourceMappingURL=FaceScan-CQkfSMC2.js.map
@@ -1,2 +0,0 @@
1
- "use strict";var e=require("react/jsx-runtime"),t=require("react"),a=require("./Modal-DU2Jymve.js"),n=require("lucide-react"),r=require("@mui/material");let o=null,s=!1;const c=async()=>{if("undefined"==typeof window)return null;if(o)return o;if(s)for(;s;)if(await new Promise(e=>setTimeout(e,100)),o)return o;s=!0;try{const[e,t]=await Promise.all([import("@tensorflow/tfjs"),Promise.resolve().then(function(){return require("./pose-detection.esm-D08ZA0zl.js")})]);await e.setBackend("webgl"),await e.ready();const n=await t.createDetector(t.SupportedModels.BlazePose,{runtime:"tfjs",modelType:"full"}),r=document.createElement("canvas");r.width="number"==typeof a.videoConstraints.width?a.videoConstraints.width:a.videoConstraints.width.ideal??a.videoConstraints.width.max??1280,r.height="number"==typeof a.videoConstraints.height?a.videoConstraints.height:a.videoConstraints.height.ideal??a.videoConstraints.height.max??720;const s=r.getContext("2d");if(s){s.fillStyle="black",s.fillRect(0,0,r.width,r.height);try{await n.estimatePoses(r)}catch(e){console.warn("Warmup frame failed (non-fatal):",e)}}return o=n,n}catch(e){return console.error("Failed to preload detector:",e),null}finally{s=!1}};function i({faceScanId:e,onValidPose:n,onScanComplete:r,onModelReady:o,onStartRecording:s,shopDomain:i,isError:l,isSuccess:d}){const u=t.useRef(null),[f,m]=t.useState(0),[g,h]=t.useState(0),[p,y]=t.useState(!1),[S,x]=t.useState(!1),v=t.useRef(!1),b=t.useRef(null),w=t.useRef(null),F=t.useRef(f),C=t.useRef(g),j=t.useRef([]),E=t.useRef(""),N=t.useRef(0),_=t.useRef(!1),T=t.useRef(0),k="undefined"!=typeof navigator&&(/iPad|iPhone|iPod/.test(navigator.userAgent)||"MacIntel"===navigator.platform&&navigator.maxTouchPoints>1),R=t.useMemo(()=>["Face front","Turn head fully left","Turn head fully right","Smile facing front"],[]),I=t.useMemo(()=>function(e,t){let a;return(...n)=>{a&&clearTimeout(a),a=setTimeout(()=>e(...n),t)}}(e=>{a.posthog.capture(`${i}/face_scan_pose_detection`,e)},4e3),[i]),M=t.useCallback((t,a,n,r,o,s)=>{const c=Date.now();if(!(c-T.current<4e3)){T.current=c;try{const c=t[0]||[0,0,0],i=t[2]||[0,0,0],l=t[5]||[0,0,0],d=t[9]||[0,0,0],u=t[10]||[0,0,0],f=t.map(e=>e[2]).filter(e=>e>0),m=f.length>0?f.reduce((e,t)=>e+t,0)/f.length:0,g=a.map(e=>e[2]).filter(e=>e>0),h=g.length>0?g.reduce((e,t)=>e+t,0)/g.length:0,p=Math.abs(i[0]-l[0]),y=c[0]-l[0],S=i[0]-c[0];let x="frontal";1===n?x="left":2===n?x="right":3===n&&(x="frontal_smile");const v={faceScanId:e,stage:n,timestamp:(new Date).toISOString(),data:JSON.stringify({headValid:r,bodyInvalid:o,consecutiveValid:s,avgFaceScore:parseFloat(m.toFixed(3)),avgBodyScore:parseFloat(h.toFixed(3)),faceKeypointsDetected:f.length,bodyKeypointsDetected:g.length,eyeDistance:parseFloat(p.toFixed(2)),noseToRightRatio:parseFloat((y/p).toFixed(3)),noseToLeftRatio:parseFloat((S/p).toFixed(3)),noseScore:parseFloat(c[2].toFixed(3)),leftEyeScore:parseFloat(i[2].toFixed(3)),rightEyeScore:parseFloat(l[2].toFixed(3)),leftMouthScore:parseFloat(d[2].toFixed(3)),rightMouthScore:parseFloat(u[2].toFixed(3)),expectedPosition:x})};I(v)}catch(e){console.warn("Failed to track pose detection:",e)}}},[e,I]),D=()=>{a.posthog.capture(`${i}/face_scan_detection_started`,{faceScanId:e,stage:F.current,timestamp:(new Date).toISOString(),stageName:R[F.current]}),setTimeout(()=>{x(!0)},1500)};return t.useEffect(()=>{if(!l&&!d)return(async()=>{if("undefined"!=typeof window)try{console.log("Initializing Face Scan...");const e=await c();e&&(u.current=e,console.log("Face scan model loaded successfully"),y(!0),o?.())}catch(e){console.error("Error initializing face scan:",e)}})(),()=>{(async()=>{try{y(!1)}catch(e){console.error("Error disposing resources:",e)}finally{m(0),h(0),F.current=0,C.current=0,j.current=[]}})()}},[l,d]),t.useEffect(()=>{F.current=f},[f]),t.useEffect(()=>{C.current=g},[g]),{faceScanDetector:async(t,o)=>{if(u.current&&t.current&&p&&S&&!(t.current.readyState<2||v.current)){v.current=!0;try{const c=t.current.videoWidth||720,l=t.current.videoHeight||1280;b.current||(b.current=document.createElement("canvas"),b.current.width=c,b.current.height=l);const d=b.current.getContext("2d");d&&d.drawImage(t.current,0,0,c,l);const f=await u.current.estimatePoses(d?b.current:t.current);if(f.length>0){const t=[],c=[];if(f[0].keypoints.forEach((e,a)=>{const n=e.score??0,r=[e.x??-1,e.y??-1,n];a<=10?t.push(r):c.push(r)}),o?.current){const e=o.current.getContext("2d"),{width:t,height:a}=o.current;if(e){e.clearRect(0,0,t,a);const n=Math.min(C.current/2,1),r=.35*a;e.beginPath(),e.strokeStyle="#00ff00",e.lineWidth=6,e.arc(t/2,a/2,r+10,-Math.PI/2,-Math.PI/2+2*n*Math.PI),e.stroke()}}const l=((e,t)=>{if(!t[0]||!t[2]||!t[5]||t[0][2]<.2||t[2][2]<.2||t[5][2]<.2)return!1;const a=.5*(t[10][1]+t[9][1])-.5*(t[5][1]+t[2][1]),n=(.5*(t[10][1]+t[9][1])-t[0][1])/a,r=n>.7||n<.3,o=Math.abs(t[2][1]-t[5][1])<.5*a&&Math.abs(t[9][1]-t[10][1])<.5*a,s=t[2][0]-t[5][0],c=t[0][0]-t[5][0],i=c>.4*s&&c<.6*s,l=c>.85*s,d=t[2][0]-t[0][0]>.85*s;switch(e){case 0:case 3:return!r&&o&&i;case 1:return!r&&o&&l;case 2:return!r&&o&&d;default:return!1}})(F.current,t),d=c.slice(2).filter(e=>e[2]>.7).length<=2;j.current.push(l&&d),j.current.length>10&&j.current.shift();if(j.current.filter(Boolean).length>=2){const e=C.current+1;h(e)}else h(Math.max(0,C.current-1));if(C.current>=2){n?.();const t=F.current+1;h(0),j.current=[],m(t),x(!1),(async()=>{if(await a.speechService.playAudio(`${a.voiceOverAssetsPath}face-scan-vos/Sound-effect.mp3`),a.posthog.capture(`${i}/face_scan_detection_stage_completed`,{faceScanId:e,completedStage:F.current,nextStage:t,timestamp:(new Date).toISOString(),totalStages:4,stageName:R[F.current]}),1===t&&s&&s(),t>=4)r?.();else{let e=null;switch(t){case 1:e="Left.mp3";break;case 2:e="Right.mp3";break;case 3:e="Smile.mp3"}e&&await a.speechService.playAudio(`${a.voiceOverAssetsPath}face-scan-vos/${e}`),D()}})()}M(t,c,F.current,l,d,C.current)}}catch(e){console.error("Pose detection error:",e)}finally{v.current=!1}}},scanStage:f,setScanStage:m,consecutiveValid:g,isModelLoaded:p,resetScan:()=>{a.posthog.capture(`${i}/face_scan_reset`,{faceScanId:e,stage:F.current,timestamp:(new Date).toISOString(),stageName:R[F.current],consecutiveValid:C.current}),m(0),h(0),x(!1),F.current=0,C.current=0,j.current=[],E.current="",N.current=0,_.current=!1,w.current&&(speechSynthesis.cancel(),w.current=null)},enableVoiceCommands:()=>{if(_.current=!0,"undefined"!=typeof window&&k&&"speechSynthesis"in window){const e=new SpeechSynthesisUtterance("");e.volume=0,speechSynthesis.speak(e)}},startScanSequence:D,isScanningActive:S}}function l({onRetry:r,loading:o}){const{translate:s}=t.useContext(a.LanguageContext)||{},c=a.useConfig();return e.jsx("div",{"data-testid":"face-scan-error-screen",className:"fixed common-ui-main top-[0] left-[0] z-[999] flex justify-center items-center w-full h-full",style:{background:c?.style?.base?.backgroundColor},children:e.jsxs("div",{className:"flex flex-col w-full items-center p-[1rem] rounded-lg ",children:[e.jsx(a.Header,{noTitle:!0}),e.jsxs("div",{className:"flex flex-col items-center w-full",children:[e.jsx("h2",{className:"text-xl my-[0] font-semibold text-gray-800 ",style:{fontFamily:c?.style?.heading?.headingFontFamily||"SeriouslyNostalgic Fn",fontSize:c?.style?.heading?.headingFontSize||"32px",color:c?.style?.heading?.headingColor||"#000",fontWeight:c?.style?.heading?.headingFontWeight||"normal"},children:s?.(a.LanguageKeys.scanFailed)}),e.jsx("p",{className:"mb-[1.5rem]",style:{fontFamily:c?.style?.subheading?.subheadingFontFamily||"'Inter', sans-serif",fontSize:c?.style?.subheading?.subheadingFontSize||"14px",color:c?.style?.subheading?.subheadingColor||"#4b5563",fontWeight:c?.style?.subheading?.subheadingFontWeight||"normal"},children:s?.(a.LanguageKeys.clickToResetScan)}),e.jsx(a.SpecificButton,{"data-testid":"face-scan-retry-btn",disabled:o,className:"w-full h-[45px] shadow-[0px_1px_2px_0px_#00000040] text-[16px]",buttonText:s?.(a.LanguageKeys.resetScan),postfixIcon:e.jsx(n.ArrowRight,{}),buttonFunc:()=>r?.()})]})]})})}function d({stage:n,videoLoading:r,setVideoLoading:o,videoError:s,setVideoError:c,gender:i,btnConfig:l}){const{translate:d}=t.useContext(a.LanguageContext)||{},u=a.useConfig();return-1===n?e.jsxs("div",{"data-testid":"face-scan-guide",className:"text-center common-ui-main p-[16px] w-full h-full",style:{background:u?.style?.base?.backgroundColor},children:[e.jsxs("div",{className:"w-full",children:[e.jsx(a.Header,{noTitle:!0}),e.jsx("h2",{className:"my-[0]",style:{fontFamily:u?.style?.heading?.headingFontFamily||"SeriouslyNostalgic Fn",fontSize:u?.style?.heading?.headingFontSize||"32px",color:u?.style?.heading?.headingColor||"#000",fontWeight:u?.style?.heading?.headingFontWeight||"normal"},children:d?.(a.LanguageKeys.faceVisible)}),r&&e.jsx("div",{className:"mb-4 flex items-center justify-center",style:{fontFamily:u?.style?.subheading?.subheadingFontFamily||"'Inter', sans-serif",fontSize:u?.style?.subheading?.subheadingFontSize||"14px",color:u?.style?.subheading?.subheadingColor||"#4b5563",fontWeight:u?.style?.subheading?.subheadingFontWeight||"normal"},children:d?.(a.LanguageKeys.loadingVideo)}),s&&e.jsx("div",{className:"mb-4 text-red-600",style:{fontFamily:u?.style?.subheading?.subheadingFontFamily||"'Inter', sans-serif",fontSize:u?.style?.subheading?.subheadingFontSize||"14px",color:"#ff0000",fontWeight:u?.style?.subheading?.subheadingFontWeight||"normal"},children:d?.(a.LanguageKeys.videoLoadFailed)}),!s&&e.jsx("div",{className:" w-[100px] mx-auto",children:e.jsx("video",{src:i===a.GenderType.Male?a.maleGlassesOffVideo:a.glassesOffVideo,autoPlay:!0,loop:!0,controls:!1,muted:!0,playsInline:!0,className:"h-full w-full object-contain border-none",onCanPlay:()=>o(!1),onLoadStart:()=>o(!0),onError:()=>c(!0),"aria-label":"Instructional video: Please remove your glasses before starting the scan."})})]}),e.jsx("div",{className:"flex justify-center w-full p-[1rem]",children:e.jsx(a.SpecificButton,{"data-testid":"face-scan-start-btn",disabled:l.isDisabled,className:"!w-[60px] !h-[35px] !py-0 !px-0",buttonText:d?.(l.label),postfixIcon:l?.icon,buttonFunc:l.onClick})})]}):e.jsx("div",{className:"text-center common-ui-main p-[16px] w-full h-full",style:{background:u?.style?.base?.backgroundColor},children:e.jsxs("div",{className:"w-full",children:[e.jsx(a.Header,{noTitle:!0}),e.jsx("h3",{className:"mb-[0.5rem] mt-[0]",style:{fontFamily:u?.style?.heading?.headingFontFamily||"SeriouslyNostalgic Fn",fontSize:u?.style?.heading?.headingFontSize||"32px",color:u?.style?.heading?.headingColor||"#000",fontWeight:u?.style?.heading?.headingFontWeight||"normal"},children:d?.(a.directionMessages[n])}),e.jsxs("div",{className:"max-w-[400px] justify-center gap-1 mx-auto flex items-center",children:[e.jsx("div",{className:` w-[120px] overflow-hidden ${0===n?"opacity-100":"opacity-0 hidden"} `,children:e.jsx("video",{className:"h-full w-full object-contain border-none",muted:!0,loop:!0,autoPlay:!0,playsInline:!0,children:e.jsx("source",{src:i===a.GenderType.Male?a.FACE_SCAN_HEADSHOT.male.forward:a.FACE_SCAN_HEADSHOT.female.forward,type:"video/mp4"})})}),e.jsx("div",{className:` w-[120px] overflow-hidden ${1===n?"opacity-100":"opacity-0 hidden"} `,children:e.jsx("video",{className:"h-full w-full object-contain border-none",muted:!0,loop:!0,autoPlay:!0,playsInline:!0,children:e.jsx("source",{src:i===a.GenderType.Male?a.FACE_SCAN_HEADSHOT.male.left:a.FACE_SCAN_HEADSHOT.female.left,type:"video/mp4"})})}),e.jsx("div",{className:` w-[120px] overflow-hidden ${2===n?"opacity-100":"opacity-0 hidden"} `,children:e.jsx("video",{className:"h-full w-full object-contain border-none",muted:!0,loop:!0,autoPlay:!0,playsInline:!0,children:e.jsx("source",{src:i===a.GenderType.Male?a.FACE_SCAN_HEADSHOT.male.right:a.FACE_SCAN_HEADSHOT.female.right,type:"video/mp4"})})}),e.jsx("div",{className:` w-[120px] overflow-hidden ${3===n?"opacity-100":"opacity-0 hidden"} `,children:e.jsx("video",{className:"h-full w-full object-contain border-none",muted:!0,loop:!0,autoPlay:!0,playsInline:!0,children:e.jsx("source",{src:i===a.GenderType.Male?a.FACE_SCAN_HEADSHOT.male.smile:a.FACE_SCAN_HEADSHOT.female.smile,type:"video/mp4"})})})]})]})})}const u=({webcamRef:o,canvasRef:s})=>{const{isError:c,isSuccess:i,showLoader:u,hasError:f,errorType:m,resetScanState:g,showGuideCard:h,scanStage:p,videoLoading:y,setVideoLoading:S,videoError:x,setVideoError:v,gender:b,getButtonText:w,isScanning:F,startScan:C,isModelLoaded:j,isLandscape:E,onRetry:N}=t.useContext(a.ParamsContext),_=a.useConfig();return c?e.jsx(l,{onRetry:N}):i?e.jsx("div",{className:"fixed z-[9] common-ui-main w-full h-full",style:{background:_?.style?.base?.backgroundColor},children:e.jsx(a.LoadingScreen,{url:_?.loader,loaderType:"black"})}):e.jsxs(e.Fragment,{children:[e.jsx("audio",{id:"audioElement",crossOrigin:"anonymous",preload:"auto",style:{position:"absolute",zIndex:-99999},src:void 0}),E&&!u&&!f&&e.jsx("div",{className:"fixed inset-0 z-[9999] common-ui-main",style:{background:"#fff"},children:e.jsx(a.Modal,{variant:"portrait",config:_})}),u&&!f&&e.jsx("div",{className:"fixed z-[9] common-ui-main w-full h-full",style:{background:_?.style?.base?.backgroundColor},children:e.jsx(a.LoadingScreen,{url:_?.loader,loaderType:"black"})}),e.jsx("div",{className:"h-full flex-col common-ui-main relative w-full flex justify-center items-center text-center rounded-t-[20px]",style:{background:_?.style?.base?.backgroundColor},children:e.jsx("div",{className:"flex-1 w-full max-w-md overflow-hidden",children:e.jsxs("div",{className:"w-full h-full",children:[e.jsx("video",{ref:o,autoPlay:!0,playsInline:!0,muted:!0,width:a.videoConstraints.width.ideal,height:a.videoConstraints.height.ideal,className:"w-full h-full object-cover fixed left-0 top-0 z-0",style:{transform:"scaleX(-1)",visibility:E?"hidden":"visible"}}),e.jsx("canvas",{ref:s,width:a.videoConstraints.width.ideal,height:a.videoConstraints.height.ideal,style:{transform:"scaleX(-1)",opacity:"0"}})]})})}),!u&&f&&m===a.FaceScanErrorType.Camera&&e.jsx(a.Modal,{testId:"face-scan-camera-error-screen",config:_}),!u&&f&&m!==a.FaceScanErrorType.Camera&&e.jsx(l,{loading:u,onRetry:g}),h&&!f&&!u&&!E&&e.jsx(r.Drawer,{open:!0,className:"face-scan-small camera-draw",anchor:"bottom",onClose:(e,t)=>{},disablePortal:!0,hideBackdrop:!0,children:e.jsx(d,{stage:p,videoLoading:y,setVideoLoading:S,videoError:x,setVideoError:v,gender:b,btnConfig:{label:w(),onClick:F?g:C,isDisabled:u||!j,icon:F?e.jsx(n.ArrowRight,{}):e.jsx(e.Fragment,{})}})})]})};exports.FaceScan=n=>{const{onScanSuccess:r,onScanError:o,onRetry:s,onScanStart:c,onCaptureComplete:l,onUploadStart:d,onUploadEnd:f,onMeasurementSocketStart:m,onMeasurementSocketClose:g,config:h,isError:p,isSuccess:y}=n,S=n.userDetails??{email:"",gender:"male",deviceFocalLength:0,shopDomain:"",bodyScanId:"",callbackUrl:null},x=n.token??"",v=t.useRef(null),b=t.useRef(null),w=t.useRef(null),F=t.useRef([]),C=t.useRef(null),j=t.useRef(null),E=t.useRef(0),N=t.useRef(null),[_,T]=t.useState(!1),[k,R]=t.useState(!1),[I,M]=t.useState(!1),[D,P]=t.useState(!0),[A,L]=t.useState(!1),[O,z]=t.useState(!1),[$,H]=t.useState(!1),[V,W]=t.useState(null),[K,U]=t.useState(a.generateUuid()),q=t.useMemo(()=>a.getSwanService(x),[x]),{isLandscape:B}=a.usePortraitLock(),{email:G,gender:J,deviceFocalLength:X,shopDomain:Q,callbackUrl:Y,bodyScanId:Z}=S,[ee,te]=t.useState([]),[ae,ne]=t.useState(a.videoConstraintsExact),re=t.useMemo(()=>a.getPreferredMediaRecorderTypes(),[]),oe=a.getRecordingMimeType(ee),se=a.getRecordingExtension(oe);a.usePosthogPageview();const ce=t.useCallback(()=>{console.log("Stopping recording..."),cancelAnimationFrame(E.current),N.current&&(N.current.pause(),N.current.srcObject=null,N.current=null),w.current&&"recording"===w.current.state&&w.current.stop(),w.current=null},[]),ie=async()=>{if(l?.(),F.current){if(0===F.current.length)return console.error("No video data recorded"),W(a.FaceScanErrorType.Scan),H(!0),void T(!1);d?.(),T(!0);const e=new File(F.current,`${K}.${se}`,{type:oe}),t=j.current??await a.getVideoFPS(e),n=e.size,r=(n/1048576).toFixed(2),o=Math.round(n/1e4),s={video_size_mb:parseFloat(r),video_size_bytes:n,video_fps:t||0,blob_count:F.current.length,estimated_duration_seconds:o},c=[{gender:J},{face_scan_id:K},{focal_length:`${X}`},{customer_store_url:Q},{scan_type:"face_scan"},{body_scan_id:Z}];Y&&c.push({callback_url:Y}),a.handleScanTimeCapture({eventName:`${Q}/face_scan_meta_data`,faceScanId:K,email:G,data:JSON.stringify({metaData:c,videoData:s})});const i=Date.now();a.handleScanTimeCapture({eventName:`${Q}/face_scan_upload_start`,faceScanId:K,email:G,startTime:i});try{const t=await q.fileUpload.faceScanFileUploader({file:e,arrayMetaData:c,objectKey:K,email:G,contentType:e.type}),n=Date.now(),r=n-i;a.handleScanTimeCapture({eventName:`${Q}/face_scan_upload_complete`,faceScanId:K,email:G,completionTime:n,uploadDuration:r}),f?.(),console.log("✅ Upload successful",t),q.measurement.handlFaceScaneSocket({onPreopen:()=>{m?.(),a.handleWebSocketCapture({eventName:`${Q}/webSocket`,faceScanID:K,connection:"pre_open",type:"faceScan_recommendation",email:G})},faceScanId:K,onOpen:()=>{a.handleWebSocketCapture({eventName:`${Q}/webSocket`,faceScanID:K,connection:"open",type:"faceScan_recommendation",email:G}),console.log("websocket connect open")},onError:e=>{a.handleWebSocketCapture({eventName:`${Q}/webSocket`,faceScanID:K,connection:"error",type:"faceScan_recommendation",email:G}),xe(e)},onSuccess:e=>{a.handleWebSocketCapture({eventName:`${Q}/webSocket`,faceScanID:K,connection:"success",type:"faceScan_recommendation",email:G}),ve(e)},onClose:()=>{g?.(),console.log("websocket connect close"),a.handleWebSocketCapture({eventName:`${Q}/webSocket`,faceScanID:K,connection:"close",type:"faceScan_recommendation",email:G})}})}catch(e){f?.(),xe(e)}}},le=t.useCallback(()=>{const e=v.current?.srcObject;if(!e)return;const t=e.getVideoTracks()[0].getSettings(),{width:n=1280,height:r=720}=t,o=document.createElement("canvas"),s=o.getContext("2d");n>r?(o.width=r,o.height=n):(o.width=n,o.height=r);const c=document.createElement("video");c.srcObject=e,c.muted=!0,c.playsInline=!0,c.play(),N.current=c;const i=()=>{n>r?(s?.save(),s?.translate(o.width,0),s?.rotate(Math.PI/2),s?.drawImage(c,0,0,r,n),s?.restore()):s?.drawImage(c,0,0,n,r),E.current=requestAnimationFrame(i)};E.current=requestAnimationFrame(i);const l=t.frameRate??10;j.current=l;const d=o.captureStream(l),u={videoBitsPerSecond:15e5};let f;ee.length>0&&(u.mimeType=ee[0]);try{f=new MediaRecorder(d,u)}catch(e){return console.error("MediaRecorder init failed:",e),W(a.FaceScanErrorType.Scan),H(!0),void T(!1)}F.current=[],f.ondataavailable=e=>{e?.data&&e.data.size>0&&F.current&&F.current.push(e.data)},f.onstop=()=>{console.log("Recording stopped, total blobs:",F?.current?.length),ie()},f.start(100),w.current=f,console.log("Recording started successfully (portrait normalized)")},[ee,ie]),{faceScanDetector:de,scanStage:ue,setScanStage:fe,resetScan:me,isModelLoaded:ge,startScanSequence:he}=i({faceScanId:K,shopDomain:Q,isError:p,isSuccess:y,onScanComplete:()=>{ce()},onModelReady:()=>{R(!0)},onStartRecording:()=>{console.log("Stage 0 completed - starting recording for stages 1-3"),le()}}),pe=t.useCallback(()=>{ge&&(c?.(),fe(0),a.speechService.playAudio(`${a.voiceOverAssetsPath}face-scan-vos/Face-forward.mp3`),setTimeout(()=>{M(!0),setTimeout(()=>{he()},200)},200))},[fe,M,he,ge,c]),ye=t.useCallback(()=>{M(!1),P(!0),ce(),me(),s?.(),F.current=[],j.current=null,w.current&&(w.current=null),H(!1),W(null),fe(-1),U(a.generateUuid()),v.current&&C.current&&(v.current.srcObject=C.current,console.log("Camera stream restored after reset"))},[fe,M,P,ce,me,U]),Se=t.useRef(!1);t.useEffect(()=>{!B||Se.current||_||p||y||$||(a.speechService.stopAudio(),w.current&&(w.current.onstop=null,"recording"===w.current.state&&w.current.stop(),w.current=null),F.current=[],j.current=null,ye()),Se.current=B},[B,_,p,y,$,ye]);const xe=e=>{console.log(e,"ws error"),o?.(e),W(a.FaceScanErrorType.Scan),H(!0),T(!1),P(!1),a.handleScanTimeCapture({eventName:`${Q}/faceScan`,faceScanId:K,status:"failed",email:G,data:JSON.stringify(e)})},ve=e=>{console.log(e,"ws success"),e&&"intermediate"===e?.resultType&&a.handleScanTimeCapture({eventName:`${Q}/faceScan_success/intermediate`,faceScanId:K,status:"success",email:G,data:JSON.stringify(e)}),r?.(e)};t.useEffect(()=>{if(!p&&!y)return navigator.mediaDevices.getUserMedia&&navigator.mediaDevices.getUserMedia({video:ae}).then(e=>{C.current=e,v.current&&(v.current.srcObject=e)}).catch(e=>{if(console.error("Error accessing webcam:",e),ae===a.videoConstraintsExact)return void ne(a.videoConstraintsFallback);const t=["NotAllowedError","PermissionDeniedError","NotFoundError","DevicesNotFoundError","NotReadableError","TrackStartError"].includes(e?.name);W(t?a.FaceScanErrorType.Camera:a.FaceScanErrorType.Scan),H(!0)}),()=>{C.current&&C.current.getTracks().forEach(e=>e.stop())}},[p,y,ae]),t.useEffect(()=>{if(!k||!I)return;const e=setInterval(()=>{de(v,b)},500);return()=>clearInterval(e)},[de,k,I]);return console.log("Model ready:",k,"Has error:",$,"Is scanning:",I,"showLoader",_),t.useEffect(()=>{const e=a.getSupportedMediaRecorderTypes(re,a.videoTypes);te(e)},[re]),t.useEffect(()=>{fe(-1)},[]),e.jsx("div",{"data-face-scan-stage":ue,children:e.jsx(a.LanguageContextProvider,{children:e.jsx(a.ConfigProvider,{config:h,children:e.jsx(a.ParamsContext.Provider,{value:{isError:p,isSuccess:y,showLoader:_,hasError:$,errorType:V,resetScanState:ye,showGuideCard:D,scanStage:ue,videoLoading:A,setVideoLoading:L,videoError:O,setVideoError:z,gender:J,getButtonText:()=>I?a.LanguageKeys.reset:ge?a.LanguageKeys.start:a.LanguageKeys.loading,isScanning:I,startScan:pe,isModelLoaded:ge,isLandscape:B,onRetry:s},children:e.jsx(a.ShadowRoot,{children:e.jsx(u,{webcamRef:v,canvasRef:b})})})})})})},exports.preloadDetector=c;
2
- //# sourceMappingURL=FaceScan-CaxQ6fGF.js.map
@@ -1,2 +0,0 @@
1
- import{jsx as e,jsxs as t,Fragment as a}from"react/jsx-runtime";import{useRef as n,useState as r,useMemo as o,useCallback as c,useEffect as i,useContext as s}from"react";import{v as l,p as d,s as u,a as m,L as f,u as h,H as g,b as p,S as y,m as S,g as b,G as v,d as w,F as x,P as F,c as N,M as _,e as I,f as k,h as E,i as C,j as M,k as D,l as P,n as T,o as z,q as R,r as $,t as L,w as j,C as V,x as W,y as O,z as A,A as U}from"./Modal-BzH-_ch3.js";import{ArrowRight as B}from"lucide-react";import{Drawer as q}from"@mui/material";let J=null,G=!1;const H=async()=>{if("undefined"==typeof window)return null;if(J)return J;if(G)for(;G;)if(await new Promise(e=>setTimeout(e,100)),J)return J;G=!0;try{const[e,t]=await Promise.all([import("@tensorflow/tfjs"),import("./pose-detection.esm-DC0_P6R7.js")]);await e.setBackend("webgl"),await e.ready();const a=await t.createDetector(t.SupportedModels.BlazePose,{runtime:"tfjs",modelType:"full"}),n=document.createElement("canvas");n.width="number"==typeof l.width?l.width:l.width.ideal??l.width.max??1280,n.height="number"==typeof l.height?l.height:l.height.ideal??l.height.max??720;const r=n.getContext("2d");if(r){r.fillStyle="black",r.fillRect(0,0,n.width,n.height);try{await a.estimatePoses(n)}catch(e){console.warn("Warmup frame failed (non-fatal):",e)}}return J=a,a}catch(e){return console.error("Failed to preload detector:",e),null}finally{G=!1}};function K({faceScanId:e,onValidPose:t,onScanComplete:a,onModelReady:s,onStartRecording:l,shopDomain:f,isError:h,isSuccess:g}){const p=n(null),[y,S]=r(0),[b,v]=r(0),[w,x]=r(!1),[F,N]=r(!1),_=n(!1),I=n(null),k=n(null),E=n(y),C=n(b),M=n([]),D=n(""),P=n(0),T=n(!1),z=n(0),R="undefined"!=typeof navigator&&(/iPad|iPhone|iPod/.test(navigator.userAgent)||"MacIntel"===navigator.platform&&navigator.maxTouchPoints>1),$=o(()=>["Face front","Turn head fully left","Turn head fully right","Smile facing front"],[]),L=o(()=>function(e,t){let a;return(...n)=>{a&&clearTimeout(a),a=setTimeout(()=>e(...n),t)}}(e=>{d.capture(`${f}/face_scan_pose_detection`,e)},4e3),[f]),j=c((t,a,n,r,o,c)=>{const i=Date.now();if(!(i-z.current<4e3)){z.current=i;try{const i=t[0]||[0,0,0],s=t[2]||[0,0,0],l=t[5]||[0,0,0],d=t[9]||[0,0,0],u=t[10]||[0,0,0],m=t.map(e=>e[2]).filter(e=>e>0),f=m.length>0?m.reduce((e,t)=>e+t,0)/m.length:0,h=a.map(e=>e[2]).filter(e=>e>0),g=h.length>0?h.reduce((e,t)=>e+t,0)/h.length:0,p=Math.abs(s[0]-l[0]),y=i[0]-l[0],S=s[0]-i[0];let b="frontal";1===n?b="left":2===n?b="right":3===n&&(b="frontal_smile");const v={faceScanId:e,stage:n,timestamp:(new Date).toISOString(),data:JSON.stringify({headValid:r,bodyInvalid:o,consecutiveValid:c,avgFaceScore:parseFloat(f.toFixed(3)),avgBodyScore:parseFloat(g.toFixed(3)),faceKeypointsDetected:m.length,bodyKeypointsDetected:h.length,eyeDistance:parseFloat(p.toFixed(2)),noseToRightRatio:parseFloat((y/p).toFixed(3)),noseToLeftRatio:parseFloat((S/p).toFixed(3)),noseScore:parseFloat(i[2].toFixed(3)),leftEyeScore:parseFloat(s[2].toFixed(3)),rightEyeScore:parseFloat(l[2].toFixed(3)),leftMouthScore:parseFloat(d[2].toFixed(3)),rightMouthScore:parseFloat(u[2].toFixed(3)),expectedPosition:b})};L(v)}catch(e){console.warn("Failed to track pose detection:",e)}}},[e,L]),V=()=>{d.capture(`${f}/face_scan_detection_started`,{faceScanId:e,stage:E.current,timestamp:(new Date).toISOString(),stageName:$[E.current]}),setTimeout(()=>{N(!0)},1500)};return i(()=>{if(!h&&!g)return(async()=>{if("undefined"!=typeof window)try{console.log("Initializing Face Scan...");const e=await H();e&&(p.current=e,console.log("Face scan model loaded successfully"),x(!0),s?.())}catch(e){console.error("Error initializing face scan:",e)}})(),()=>{(async()=>{try{x(!1)}catch(e){console.error("Error disposing resources:",e)}finally{S(0),v(0),E.current=0,C.current=0,M.current=[]}})()}},[h,g]),i(()=>{E.current=y},[y]),i(()=>{C.current=b},[b]),{faceScanDetector:async(n,r)=>{if(p.current&&n.current&&w&&F&&!(n.current.readyState<2||_.current)){_.current=!0;try{const o=n.current.videoWidth||720,c=n.current.videoHeight||1280;I.current||(I.current=document.createElement("canvas"),I.current.width=o,I.current.height=c);const i=I.current.getContext("2d");i&&i.drawImage(n.current,0,0,o,c);const s=await p.current.estimatePoses(i?I.current:n.current);if(s.length>0){const n=[],o=[];if(s[0].keypoints.forEach((e,t)=>{const a=e.score??0,r=[e.x??-1,e.y??-1,a];t<=10?n.push(r):o.push(r)}),r?.current){const e=r.current.getContext("2d"),{width:t,height:a}=r.current;if(e){e.clearRect(0,0,t,a);const n=Math.min(C.current/2,1),r=.35*a;e.beginPath(),e.strokeStyle="#00ff00",e.lineWidth=6,e.arc(t/2,a/2,r+10,-Math.PI/2,-Math.PI/2+2*n*Math.PI),e.stroke()}}const c=((e,t)=>{if(!t[0]||!t[2]||!t[5]||t[0][2]<.2||t[2][2]<.2||t[5][2]<.2)return!1;const a=.5*(t[10][1]+t[9][1])-.5*(t[5][1]+t[2][1]),n=(.5*(t[10][1]+t[9][1])-t[0][1])/a,r=n>.7||n<.3,o=Math.abs(t[2][1]-t[5][1])<.5*a&&Math.abs(t[9][1]-t[10][1])<.5*a,c=t[2][0]-t[5][0],i=t[0][0]-t[5][0],s=i>.4*c&&i<.6*c,l=i>.85*c,d=t[2][0]-t[0][0]>.85*c;switch(e){case 0:case 3:return!r&&o&&s;case 1:return!r&&o&&l;case 2:return!r&&o&&d;default:return!1}})(E.current,n),i=o.slice(2).filter(e=>e[2]>.7).length<=2;M.current.push(c&&i),M.current.length>10&&M.current.shift();if(M.current.filter(Boolean).length>=2){const e=C.current+1;v(e)}else v(Math.max(0,C.current-1));if(C.current>=2){t?.();const n=E.current+1;v(0),M.current=[],S(n),N(!1),(async()=>{if(await u.playAudio(`${m}face-scan-vos/Sound-effect.mp3`),d.capture(`${f}/face_scan_detection_stage_completed`,{faceScanId:e,completedStage:E.current,nextStage:n,timestamp:(new Date).toISOString(),totalStages:4,stageName:$[E.current]}),1===n&&l&&l(),n>=4)a?.();else{let e=null;switch(n){case 1:e="Left.mp3";break;case 2:e="Right.mp3";break;case 3:e="Smile.mp3"}e&&await u.playAudio(`${m}face-scan-vos/${e}`),V()}})()}j(n,o,E.current,c,i,C.current)}}catch(e){console.error("Pose detection error:",e)}finally{_.current=!1}}},scanStage:y,setScanStage:S,consecutiveValid:b,isModelLoaded:w,resetScan:()=>{d.capture(`${f}/face_scan_reset`,{faceScanId:e,stage:E.current,timestamp:(new Date).toISOString(),stageName:$[E.current],consecutiveValid:C.current}),S(0),v(0),N(!1),E.current=0,C.current=0,M.current=[],D.current="",P.current=0,T.current=!1,k.current&&(speechSynthesis.cancel(),k.current=null)},enableVoiceCommands:()=>{if(T.current=!0,"undefined"!=typeof window&&R&&"speechSynthesis"in window){const e=new SpeechSynthesisUtterance("");e.volume=0,speechSynthesis.speak(e)}},startScanSequence:V,isScanningActive:F}}function X({onRetry:a,loading:n}){const{translate:r}=s(f)||{},o=h();return e("div",{"data-testid":"face-scan-error-screen",className:"fixed common-ui-main top-[0] left-[0] z-[999] flex justify-center items-center w-full h-full",style:{background:o?.style?.base?.backgroundColor},children:t("div",{className:"flex flex-col w-full items-center p-[1rem] rounded-lg ",children:[e(g,{noTitle:!0}),t("div",{className:"flex flex-col items-center w-full",children:[e("h2",{className:"text-xl my-[0] font-semibold text-gray-800 ",style:{fontFamily:o?.style?.heading?.headingFontFamily||"SeriouslyNostalgic Fn",fontSize:o?.style?.heading?.headingFontSize||"32px",color:o?.style?.heading?.headingColor||"#000",fontWeight:o?.style?.heading?.headingFontWeight||"normal"},children:r?.(p.scanFailed)}),e("p",{className:"mb-[1.5rem]",style:{fontFamily:o?.style?.subheading?.subheadingFontFamily||"'Inter', sans-serif",fontSize:o?.style?.subheading?.subheadingFontSize||"14px",color:o?.style?.subheading?.subheadingColor||"#4b5563",fontWeight:o?.style?.subheading?.subheadingFontWeight||"normal"},children:r?.(p.clickToResetScan)}),e(y,{"data-testid":"face-scan-retry-btn",disabled:n,className:"w-full h-[45px] shadow-[0px_1px_2px_0px_#00000040] text-[16px]",buttonText:r?.(p.resetScan),postfixIcon:e(B,{}),buttonFunc:()=>a?.()})]})]})})}function Q({stage:a,videoLoading:n,setVideoLoading:r,videoError:o,setVideoError:c,gender:i,btnConfig:l}){const{translate:d}=s(f)||{},u=h();return-1===a?t("div",{"data-testid":"face-scan-guide",className:"text-center common-ui-main p-[16px] w-full h-full",style:{background:u?.style?.base?.backgroundColor},children:[t("div",{className:"w-full",children:[e(g,{noTitle:!0}),e("h2",{className:"my-[0]",style:{fontFamily:u?.style?.heading?.headingFontFamily||"SeriouslyNostalgic Fn",fontSize:u?.style?.heading?.headingFontSize||"32px",color:u?.style?.heading?.headingColor||"#000",fontWeight:u?.style?.heading?.headingFontWeight||"normal"},children:d?.(p.faceVisible)}),n&&e("div",{className:"mb-4 flex items-center justify-center",style:{fontFamily:u?.style?.subheading?.subheadingFontFamily||"'Inter', sans-serif",fontSize:u?.style?.subheading?.subheadingFontSize||"14px",color:u?.style?.subheading?.subheadingColor||"#4b5563",fontWeight:u?.style?.subheading?.subheadingFontWeight||"normal"},children:d?.(p.loadingVideo)}),o&&e("div",{className:"mb-4 text-red-600",style:{fontFamily:u?.style?.subheading?.subheadingFontFamily||"'Inter', sans-serif",fontSize:u?.style?.subheading?.subheadingFontSize||"14px",color:"#ff0000",fontWeight:u?.style?.subheading?.subheadingFontWeight||"normal"},children:d?.(p.videoLoadFailed)}),!o&&e("div",{className:" w-[100px] mx-auto",children:e("video",{src:i===v.Male?S:b,autoPlay:!0,loop:!0,controls:!1,muted:!0,playsInline:!0,className:"h-full w-full object-contain border-none",onCanPlay:()=>r(!1),onLoadStart:()=>r(!0),onError:()=>c(!0),"aria-label":"Instructional video: Please remove your glasses before starting the scan."})})]}),e("div",{className:"flex justify-center w-full p-[1rem]",children:e(y,{"data-testid":"face-scan-start-btn",disabled:l.isDisabled,className:"!w-[60px] !h-[35px] !py-0 !px-0",buttonText:d?.(l.label),postfixIcon:l?.icon,buttonFunc:l.onClick})})]}):e("div",{className:"text-center common-ui-main p-[16px] w-full h-full",style:{background:u?.style?.base?.backgroundColor},children:t("div",{className:"w-full",children:[e(g,{noTitle:!0}),e("h3",{className:"mb-[0.5rem] mt-[0]",style:{fontFamily:u?.style?.heading?.headingFontFamily||"SeriouslyNostalgic Fn",fontSize:u?.style?.heading?.headingFontSize||"32px",color:u?.style?.heading?.headingColor||"#000",fontWeight:u?.style?.heading?.headingFontWeight||"normal"},children:d?.(w[a])}),t("div",{className:"max-w-[400px] justify-center gap-1 mx-auto flex items-center",children:[e("div",{className:` w-[120px] overflow-hidden ${0===a?"opacity-100":"opacity-0 hidden"} `,children:e("video",{className:"h-full w-full object-contain border-none",muted:!0,loop:!0,autoPlay:!0,playsInline:!0,children:e("source",{src:i===v.Male?x.male.forward:x.female.forward,type:"video/mp4"})})}),e("div",{className:` w-[120px] overflow-hidden ${1===a?"opacity-100":"opacity-0 hidden"} `,children:e("video",{className:"h-full w-full object-contain border-none",muted:!0,loop:!0,autoPlay:!0,playsInline:!0,children:e("source",{src:i===v.Male?x.male.left:x.female.left,type:"video/mp4"})})}),e("div",{className:` w-[120px] overflow-hidden ${2===a?"opacity-100":"opacity-0 hidden"} `,children:e("video",{className:"h-full w-full object-contain border-none",muted:!0,loop:!0,autoPlay:!0,playsInline:!0,children:e("source",{src:i===v.Male?x.male.right:x.female.right,type:"video/mp4"})})}),e("div",{className:` w-[120px] overflow-hidden ${3===a?"opacity-100":"opacity-0 hidden"} `,children:e("video",{className:"h-full w-full object-contain border-none",muted:!0,loop:!0,autoPlay:!0,playsInline:!0,children:e("source",{src:i===v.Male?x.male.smile:x.female.smile,type:"video/mp4"})})})]})]})})}const Y=({webcamRef:n,canvasRef:r})=>{const{isError:o,isSuccess:c,showLoader:i,hasError:d,errorType:u,resetScanState:m,showGuideCard:f,scanStage:g,videoLoading:p,setVideoLoading:y,videoError:S,setVideoError:b,gender:v,getButtonText:w,isScanning:x,startScan:k,isModelLoaded:E,isLandscape:C,onRetry:M}=s(F),D=h();return o?e(X,{onRetry:M}):c?e("div",{className:"fixed z-[9] common-ui-main w-full h-full",style:{background:D?.style?.base?.backgroundColor},children:e(N,{url:D?.loader,loaderType:"black"})}):t(a,{children:[e("audio",{id:"audioElement",crossOrigin:"anonymous",preload:"auto",style:{position:"absolute",zIndex:-99999},src:void 0}),C&&!i&&!d&&e("div",{className:"fixed inset-0 z-[9999] common-ui-main",style:{background:"#fff"},children:e(_,{variant:"portrait",config:D})}),i&&!d&&e("div",{className:"fixed z-[9] common-ui-main w-full h-full",style:{background:D?.style?.base?.backgroundColor},children:e(N,{url:D?.loader,loaderType:"black"})}),e("div",{className:"h-full flex-col common-ui-main relative w-full flex justify-center items-center text-center rounded-t-[20px]",style:{background:D?.style?.base?.backgroundColor},children:e("div",{className:"flex-1 w-full max-w-md overflow-hidden",children:t("div",{className:"w-full h-full",children:[e("video",{ref:n,autoPlay:!0,playsInline:!0,muted:!0,width:l.width.ideal,height:l.height.ideal,className:"w-full h-full object-cover fixed left-0 top-0 z-0",style:{transform:"scaleX(-1)",visibility:C?"hidden":"visible"}}),e("canvas",{ref:r,width:l.width.ideal,height:l.height.ideal,style:{transform:"scaleX(-1)",opacity:"0"}})]})})}),!i&&d&&u===I.Camera&&e(_,{testId:"face-scan-camera-error-screen",config:D}),!i&&d&&u!==I.Camera&&e(X,{loading:i,onRetry:m}),f&&!d&&!i&&!C&&e(q,{open:!0,className:"face-scan-small camera-draw",anchor:"bottom",onClose:(e,t)=>{},disablePortal:!0,hideBackdrop:!0,children:e(Q,{stage:g,videoLoading:p,setVideoLoading:y,videoError:S,setVideoError:b,gender:v,btnConfig:{label:w(),onClick:x?m:k,isDisabled:i||!E,icon:e(x?B:a,{})}})})]})},Z=t=>{const{onScanSuccess:a,onScanError:s,onRetry:l,onScanStart:f,onCaptureComplete:h,onUploadStart:g,onUploadEnd:y,onMeasurementSocketStart:S,onMeasurementSocketClose:b,config:v,isError:w,isSuccess:x}=t,N=t.userDetails??{email:"",gender:"male",deviceFocalLength:0,shopDomain:"",bodyScanId:"",callbackUrl:null},_=t.token??"",B=n(null),q=n(null),J=n(null),G=n([]),H=n(null),X=n(null),Q=n(0),Z=n(null),[ee,te]=r(!1),[ae,ne]=r(!1),[re,oe]=r(!1),[ce,ie]=r(!0),[se,le]=r(!1),[de,ue]=r(!1),[me,fe]=r(!1),[he,ge]=r(null),[pe,ye]=r(k()),Se=o(()=>E(_),[_]),{isLandscape:be}=C(),{email:ve,gender:we,deviceFocalLength:xe,shopDomain:Fe,callbackUrl:Ne,bodyScanId:_e}=N,[Ie,ke]=r([]),[Ee,Ce]=r(M),Me=o(()=>D(),[]),De=P(Ie),Pe=T(De);z();const Te=c(()=>{console.log("Stopping recording..."),cancelAnimationFrame(Q.current),Z.current&&(Z.current.pause(),Z.current.srcObject=null,Z.current=null),J.current&&"recording"===J.current.state&&J.current.stop(),J.current=null},[]),ze=async()=>{if(h?.(),G.current){if(0===G.current.length)return console.error("No video data recorded"),ge(I.Scan),fe(!0),void te(!1);g?.(),te(!0);const e=new File(G.current,`${pe}.${Pe}`,{type:De}),t=X.current??await O(e),a=e.size,n=(a/1048576).toFixed(2),r=Math.round(a/1e4),o={video_size_mb:parseFloat(n),video_size_bytes:a,video_fps:t||0,blob_count:G.current.length,estimated_duration_seconds:r},c=[{gender:we},{face_scan_id:pe},{focal_length:`${xe}`},{customer_store_url:Fe},{scan_type:"face_scan"},{body_scan_id:_e}];Ne&&c.push({callback_url:Ne}),A({eventName:`${Fe}/face_scan_meta_data`,faceScanId:pe,email:ve,data:JSON.stringify({metaData:c,videoData:o})});const i=Date.now();A({eventName:`${Fe}/face_scan_upload_start`,faceScanId:pe,email:ve,startTime:i});try{const t=await Se.fileUpload.faceScanFileUploader({file:e,arrayMetaData:c,objectKey:pe,email:ve,contentType:e.type}),a=Date.now();A({eventName:`${Fe}/face_scan_upload_complete`,faceScanId:pe,email:ve,completionTime:a,uploadDuration:a-i}),y?.(),console.log("✅ Upload successful",t);let n=!1;Se.measurement.handlFaceScaneSocket({onPreopen:()=>{S?.(),U({eventName:`${Fe}/webSocket`,faceScanID:pe,connection:"pre_open",type:"faceScan_recommendation",email:ve})},faceScanId:pe,onOpen:()=>{U({eventName:`${Fe}/webSocket`,faceScanID:pe,connection:"open",type:"faceScan_recommendation",email:ve})},onError:e=>{n=!0,U({eventName:`${Fe}/webSocket`,faceScanID:pe,connection:"error",type:"faceScan_recommendation",email:ve}),qe(e)},onSuccess:e=>{n=!0,U({eventName:`${Fe}/webSocket`,faceScanID:pe,connection:"success",type:"faceScan_recommendation",email:ve}),Je(e)},onClose:()=>{b?.(),U({eventName:`${Fe}/webSocket`,faceScanID:pe,connection:"close",type:"faceScan_recommendation",email:ve}),n||(d.capture(`${Fe}/face_scan_ws_closed_without_result`,{faceScanID:pe,email:ve,type:"ws_close_no_result",reason:"Face scan WebSocket closed before delivering a result"}),qe({message:"Connection closed. Please try again."}))}})}catch(e){y?.(),qe(e)}}},Re=c(()=>{const e=B.current?.srcObject;if(!e)return;const t=e.getVideoTracks()[0].getSettings(),{width:a=1280,height:n=720}=t,r=document.createElement("canvas"),o=r.getContext("2d");a>n?(r.width=n,r.height=a):(r.width=a,r.height=n);const c=document.createElement("video");c.srcObject=e,c.muted=!0,c.playsInline=!0,c.play(),Z.current=c;const i=()=>{a>n?(o?.save(),o?.translate(r.width,0),o?.rotate(Math.PI/2),o?.drawImage(c,0,0,n,a),o?.restore()):o?.drawImage(c,0,0,a,n),Q.current=requestAnimationFrame(i)};Q.current=requestAnimationFrame(i);const s=t.frameRate??10;X.current=s;const l=r.captureStream(s),d={videoBitsPerSecond:15e5};let u;Ie.length>0&&(d.mimeType=Ie[0]);try{u=new MediaRecorder(l,d)}catch(e){return console.error("MediaRecorder init failed:",e),ge(I.Scan),fe(!0),void te(!1)}G.current=[],u.ondataavailable=e=>{e?.data&&e.data.size>0&&G.current&&G.current.push(e.data)},u.onstop=()=>{console.log("Recording stopped, total blobs:",G?.current?.length),ze()},u.start(100),J.current=u,console.log("Recording started successfully (portrait normalized)")},[Ie,ze]),{faceScanDetector:$e,scanStage:Le,setScanStage:je,resetScan:Ve,isModelLoaded:We,startScanSequence:Oe}=K({faceScanId:pe,shopDomain:Fe,isError:w,isSuccess:x,onScanComplete:()=>{Te()},onModelReady:()=>{ne(!0)},onStartRecording:()=>{console.log("Stage 0 completed - starting recording for stages 1-3"),Re()}}),Ae=c(()=>{We&&(f?.(),je(0),u.playAudio(`${m}face-scan-vos/Face-forward.mp3`),setTimeout(()=>{oe(!0),setTimeout(()=>{Oe()},200)},200))},[je,oe,Oe,We,f]),Ue=c(()=>{oe(!1),ie(!0),Te(),Ve(),l?.(),G.current=[],X.current=null,J.current&&(J.current=null),fe(!1),ge(null),je(-1),ye(k()),B.current&&H.current&&(B.current.srcObject=H.current,console.log("Camera stream restored after reset"))},[je,oe,ie,Te,Ve,ye]),Be=n(!1);i(()=>{!be||Be.current||ee||w||x||me||(u.stopAudio(),J.current&&(J.current.onstop=null,"recording"===J.current.state&&J.current.stop(),J.current=null),G.current=[],X.current=null,Ue()),Be.current=be},[be,ee,w,x,me,Ue]);const qe=e=>{console.log(e,"ws error"),s?.(e),ge(I.Scan),fe(!0),te(!1),ie(!1),A({eventName:`${Fe}/faceScan`,faceScanId:pe,status:"failed",email:ve,data:JSON.stringify(e)})},Je=e=>{console.log(e,"ws success"),e&&"intermediate"===e?.resultType&&A({eventName:`${Fe}/faceScan_success/intermediate`,faceScanId:pe,status:"success",email:ve,data:JSON.stringify(e)}),a?.(e)};i(()=>{if(!w&&!x)return navigator.mediaDevices.getUserMedia&&navigator.mediaDevices.getUserMedia({video:Ee}).then(e=>{H.current=e,B.current&&(B.current.srcObject=e)}).catch(e=>{if(console.error("Error accessing webcam:",e),Ee===M)return void Ce(R);const t=["NotAllowedError","PermissionDeniedError","NotFoundError","DevicesNotFoundError","NotReadableError","TrackStartError"].includes(e?.name);ge(t?I.Camera:I.Scan),fe(!0)}),()=>{H.current&&H.current.getTracks().forEach(e=>e.stop())}},[w,x,Ee]),i(()=>{if(!ae||!re)return;const e=setInterval(()=>{$e(B,q)},500);return()=>clearInterval(e)},[$e,ae,re]);return console.log("Model ready:",ae,"Has error:",me,"Is scanning:",re,"showLoader",ee),i(()=>{const e=$(Me,L);ke(e)},[Me]),i(()=>{je(-1)},[]),e("div",{"data-face-scan-stage":Le,children:e(j,{children:e(V,{config:v,children:e(F.Provider,{value:{isError:w,isSuccess:x,showLoader:ee,hasError:me,errorType:he,resetScanState:Ue,showGuideCard:ce,scanStage:Le,videoLoading:se,setVideoLoading:le,videoError:de,setVideoError:ue,gender:we,getButtonText:()=>re?p.reset:We?p.start:p.loading,isScanning:re,startScan:Ae,isModelLoaded:We,isLandscape:be,onRetry:l},children:e(W,{children:e(Y,{webcamRef:B,canvasRef:q})})})})})})};export{Z as F,H as p};
2
- //# sourceMappingURL=FaceScan-CxDcvM4f.js.map
@@ -1,2 +0,0 @@
1
- "use strict";var e=require("react/jsx-runtime"),t=require("react"),a=require("./Modal-HTYYx7sM.js"),n=require("lucide-react"),r=require("@mui/material");let o=null,s=!1;function c({faceScanId:e,onValidPose:n,onScanComplete:r,onModelReady:c,onStartRecording:i,shopDomain:l,isError:d,isSuccess:u}){const f=t.useRef(null),[g,h]=t.useState(0),[m,p]=t.useState(0),[y,S]=t.useState(!1),[x,v]=t.useState(!1),b=t.useRef(!1),w=t.useRef(null),F=t.useRef(null),C=t.useRef(g),j=t.useRef(m),E=t.useRef([]),_=t.useRef(""),N=t.useRef(0),T=t.useRef(!1),k=t.useRef(0),R="undefined"!=typeof navigator&&(/iPad|iPhone|iPod/.test(navigator.userAgent)||"MacIntel"===navigator.platform&&navigator.maxTouchPoints>1),I=t.useMemo(()=>["Face front","Turn head fully left","Turn head fully right","Smile facing front"],[]),M=t.useMemo(()=>function(e,t){let a;return(...n)=>{a&&clearTimeout(a),a=setTimeout(()=>e(...n),t)}}(e=>{a.posthog.capture(`${l}/face_scan_pose_detection`,e)},4e3),[l]),D=t.useCallback((t,a,n,r,o,s)=>{const c=Date.now();if(!(c-k.current<4e3)){k.current=c;try{const c=t[0]||[0,0,0],i=t[2]||[0,0,0],l=t[5]||[0,0,0],d=t[9]||[0,0,0],u=t[10]||[0,0,0],f=t.map(e=>e[2]).filter(e=>e>0),g=f.length>0?f.reduce((e,t)=>e+t,0)/f.length:0,h=a.map(e=>e[2]).filter(e=>e>0),m=h.length>0?h.reduce((e,t)=>e+t,0)/h.length:0,p=Math.abs(i[0]-l[0]),y=c[0]-l[0],S=i[0]-c[0];let x="frontal";1===n?x="left":2===n?x="right":3===n&&(x="frontal_smile");const v={faceScanId:e,stage:n,timestamp:(new Date).toISOString(),data:JSON.stringify({headValid:r,bodyInvalid:o,consecutiveValid:s,avgFaceScore:parseFloat(g.toFixed(3)),avgBodyScore:parseFloat(m.toFixed(3)),faceKeypointsDetected:f.length,bodyKeypointsDetected:h.length,eyeDistance:parseFloat(p.toFixed(2)),noseToRightRatio:parseFloat((y/p).toFixed(3)),noseToLeftRatio:parseFloat((S/p).toFixed(3)),noseScore:parseFloat(c[2].toFixed(3)),leftEyeScore:parseFloat(i[2].toFixed(3)),rightEyeScore:parseFloat(l[2].toFixed(3)),leftMouthScore:parseFloat(d[2].toFixed(3)),rightMouthScore:parseFloat(u[2].toFixed(3)),expectedPosition:x})};M(v)}catch(e){console.warn("Failed to track pose detection:",e)}}},[e,M]),P=()=>{a.posthog.capture(`${l}/face_scan_detection_started`,{faceScanId:e,stage:C.current,timestamp:(new Date).toISOString(),stageName:I[C.current]}),setTimeout(()=>{v(!0)},1500)},A=async()=>{if("undefined"!=typeof window)try{console.log("Initializing Face Scan...");const e=await(async()=>{if("undefined"==typeof window)return null;if(o)return o;if(s)for(;s;)if(await new Promise(e=>setTimeout(e,100)),o)return o;s=!0;try{const[e,t]=await Promise.all([import("@tensorflow/tfjs"),Promise.resolve().then(function(){return require("./pose-detection.esm-Bc8T4UAD.js")})]);await e.setBackend("webgl"),await e.ready();const n=await t.createDetector(t.SupportedModels.BlazePose,{runtime:"tfjs",modelType:"full"}),r=document.createElement("canvas");r.width="number"==typeof a.videoConstraints.width?a.videoConstraints.width:a.videoConstraints.width.ideal??a.videoConstraints.width.max??1280,r.height="number"==typeof a.videoConstraints.height?a.videoConstraints.height:a.videoConstraints.height.ideal??a.videoConstraints.height.max??720;const s=r.getContext("2d");if(s){s.fillStyle="black",s.fillRect(0,0,r.width,r.height);try{await n.estimatePoses(r)}catch(e){console.warn("Warmup frame failed (non-fatal):",e)}}return o=n,n}catch(e){return console.error("Failed to preload detector:",e),null}finally{s=!1}})();e&&(f.current=e,console.log("Face scan model loaded successfully"),S(!0),c?.())}catch(e){console.error("Error initializing face scan:",e)}};return t.useEffect(()=>{if(!d&&!u)return A(),()=>{(async()=>{try{S(!1)}catch(e){console.error("Error disposing resources:",e)}finally{h(0),p(0),C.current=0,j.current=0,E.current=[]}})()}},[d,u]),t.useEffect(()=>{C.current=g},[g]),t.useEffect(()=>{j.current=m},[m]),{faceScanDetector:async(t,o)=>{if(f.current&&t.current&&y&&x&&!(t.current.readyState<2||b.current)){b.current=!0;try{const s=t.current.videoWidth||720,c=t.current.videoHeight||1280;w.current||(w.current=document.createElement("canvas"),w.current.width=s,w.current.height=c);const d=w.current.getContext("2d");d&&d.drawImage(t.current,0,0,s,c);const u=await f.current.estimatePoses(d?w.current:t.current);if(u.length>0){const t=[],s=[];if(u[0].keypoints.forEach((e,a)=>{const n=e.score??0,r=[e.x??-1,e.y??-1,n];a<=10?t.push(r):s.push(r)}),o?.current){const e=o.current.getContext("2d"),{width:t,height:a}=o.current;if(e){e.clearRect(0,0,t,a);const n=Math.min(j.current/2,1),r=.35*a;e.beginPath(),e.strokeStyle="#00ff00",e.lineWidth=6,e.arc(t/2,a/2,r+10,-Math.PI/2,-Math.PI/2+2*n*Math.PI),e.stroke()}}const c=((e,t)=>{if(!t[0]||!t[2]||!t[5]||t[0][2]<.2||t[2][2]<.2||t[5][2]<.2)return!1;const a=.5*(t[10][1]+t[9][1])-.5*(t[5][1]+t[2][1]),n=(.5*(t[10][1]+t[9][1])-t[0][1])/a,r=n>.7||n<.3,o=Math.abs(t[2][1]-t[5][1])<.5*a&&Math.abs(t[9][1]-t[10][1])<.5*a,s=t[2][0]-t[5][0],c=t[0][0]-t[5][0],i=c>.4*s&&c<.6*s,l=c>.85*s,d=t[2][0]-t[0][0]>.85*s;switch(e){case 0:case 3:return!r&&o&&i;case 1:return!r&&o&&l;case 2:return!r&&o&&d;default:return!1}})(C.current,t),d=s.slice(2).filter(e=>e[2]>.7).length<=2;E.current.push(c&&d),E.current.length>10&&E.current.shift();if(E.current.filter(Boolean).length>=2){const e=j.current+1;p(e)}else p(Math.max(0,j.current-1));if(j.current>=2){n?.();const t=C.current+1;p(0),E.current=[],h(t),v(!1),(async()=>{if(await a.speechService.playAudio(`${a.voiceOverAssetsPath}face-scan-vos/Sound-effect.mp3`),a.posthog.capture(`${l}/face_scan_detection_stage_completed`,{faceScanId:e,completedStage:C.current,nextStage:t,timestamp:(new Date).toISOString(),totalStages:4,stageName:I[C.current]}),1===t&&i&&i(),t>=4)r?.();else{let e=null;switch(t){case 1:e="Left.mp3";break;case 2:e="Right.mp3";break;case 3:e="Smile.mp3"}e&&await a.speechService.playAudio(`${a.voiceOverAssetsPath}face-scan-vos/${e}`),P()}})()}D(t,s,C.current,c,d,j.current)}}catch(e){console.error("Pose detection error:",e)}finally{b.current=!1}}},scanStage:g,setScanStage:h,consecutiveValid:m,isModelLoaded:y,resetScan:()=>{a.posthog.capture(`${l}/face_scan_reset`,{faceScanId:e,stage:C.current,timestamp:(new Date).toISOString(),stageName:I[C.current],consecutiveValid:j.current}),h(0),p(0),v(!1),C.current=0,j.current=0,E.current=[],_.current="",N.current=0,T.current=!1,F.current&&(speechSynthesis.cancel(),F.current=null)},enableVoiceCommands:()=>{if(T.current=!0,"undefined"!=typeof window&&R&&"speechSynthesis"in window){const e=new SpeechSynthesisUtterance("");e.volume=0,speechSynthesis.speak(e)}},startScanSequence:P,isScanningActive:x}}function i({onRetry:r,loading:o}){const{translate:s}=t.useContext(a.LanguageContext)||{},c=a.useConfig();return e.jsx("div",{"data-testid":"face-scan-error-screen",className:"fixed common-ui-main top-[0] left-[0] z-[999] flex justify-center items-center w-full h-full",style:{background:c?.style?.base?.backgroundColor},children:e.jsxs("div",{className:"flex flex-col w-full items-center p-[1rem] rounded-lg ",children:[e.jsx(a.Header,{noTitle:!0}),e.jsxs("div",{className:"flex flex-col items-center w-full",children:[e.jsx("h2",{className:"text-xl font-semibold text-gray-800 ",style:{fontFamily:c?.style?.heading?.headingFontFamily||"SeriouslyNostalgic Fn",fontSize:c?.style?.heading?.headingFontSize||"32px",color:c?.style?.heading?.headingColor||"#000",fontWeight:c?.style?.heading?.headingFontWeight||"normal"},children:s?.(a.LanguageKeys.scanFailed)}),e.jsx("p",{className:"mb-[1.5rem]",style:{fontFamily:c?.style?.subheading?.subheadingFontFamily||"'Inter', sans-serif",fontSize:c?.style?.subheading?.subheadingFontSize||"14px",color:c?.style?.subheading?.subheadingColor||"#4b5563",fontWeight:c?.style?.subheading?.subheadingFontWeight||"normal"},children:s?.(a.LanguageKeys.clickToResetScan)}),e.jsx(a.SpecificButton,{"data-testid":"face-scan-retry-btn",disabled:o,className:"w-full h-[45px] shadow-[0px_1px_2px_0px_#00000040] text-[16px]",buttonText:s?.(a.LanguageKeys.resetScan),postfixIcon:e.jsx(n.ArrowRight,{}),buttonFunc:()=>r?.()})]})]})})}function l({stage:n,videoLoading:r,setVideoLoading:o,videoError:s,setVideoError:c,gender:i,btnConfig:l}){const{translate:d}=t.useContext(a.LanguageContext)||{},u=a.useConfig();return-1===n?e.jsxs("div",{"data-testid":"face-scan-guide",className:"text-center common-ui-main p-[16px] w-full h-full",style:{background:u?.style?.base?.backgroundColor},children:[e.jsxs("div",{className:"w-full",children:[e.jsx(a.Header,{noTitle:!0}),e.jsx("h2",{style:{fontFamily:u?.style?.heading?.headingFontFamily||"SeriouslyNostalgic Fn",fontSize:u?.style?.heading?.headingFontSize||"32px",color:u?.style?.heading?.headingColor||"#000",fontWeight:u?.style?.heading?.headingFontWeight||"normal"},children:d?.(a.LanguageKeys.faceVisible)}),r&&e.jsx("div",{className:"mb-4 flex items-center justify-center",style:{fontFamily:u?.style?.subheading?.subheadingFontFamily||"'Inter', sans-serif",fontSize:u?.style?.subheading?.subheadingFontSize||"14px",color:u?.style?.subheading?.subheadingColor||"#4b5563",fontWeight:u?.style?.subheading?.subheadingFontWeight||"normal"},children:d?.(a.LanguageKeys.loadingVideo)}),s&&e.jsx("div",{className:"mb-4 text-red-600",style:{fontFamily:u?.style?.subheading?.subheadingFontFamily||"'Inter', sans-serif",fontSize:u?.style?.subheading?.subheadingFontSize||"14px",color:"#ff0000",fontWeight:u?.style?.subheading?.subheadingFontWeight||"normal"},children:d?.(a.LanguageKeys.videoLoadFailed)}),!s&&e.jsx("div",{className:" w-[100px] mx-auto",children:e.jsx("video",{src:i===a.GenderType.Male?a.maleGlassesOffVideo:a.glassesOffVideo,autoPlay:!0,loop:!0,controls:!1,muted:!0,playsInline:!0,className:"h-full w-full object-contain border-none",onCanPlay:()=>o(!1),onLoadStart:()=>o(!0),onError:()=>c(!0),"aria-label":"Instructional video: Please remove your glasses before starting the scan."})})]}),e.jsx("div",{className:"flex justify-center w-full p-[1rem]",children:e.jsx(a.SpecificButton,{"data-testid":"face-scan-start-btn",disabled:l.isDisabled,className:"!w-[60px] !h-[35px] !py-0 !px-0",buttonText:d?.(l.label),postfixIcon:l?.icon,buttonFunc:l.onClick})})]}):e.jsx("div",{className:"text-center common-ui-main p-[16px] w-full h-full",style:{background:u?.style?.base?.backgroundColor},children:e.jsxs("div",{className:"w-full",children:[e.jsx(a.Header,{noTitle:!0}),e.jsx("h3",{className:"mb-[0.5rem]",style:{fontFamily:u?.style?.heading?.headingFontFamily||"SeriouslyNostalgic Fn",fontSize:u?.style?.heading?.headingFontSize||"32px",color:u?.style?.heading?.headingColor||"#000",fontWeight:u?.style?.heading?.headingFontWeight||"normal"},children:d?.(a.directionMessages[n])}),e.jsxs("div",{className:"max-w-[400px] justify-center gap-1 mx-auto flex items-center",children:[e.jsx("div",{className:` w-[120px] overflow-hidden ${0===n?"opacity-100":"opacity-0 hidden"} `,children:e.jsx("video",{className:"h-full w-full object-contain border-none",muted:!0,loop:!0,autoPlay:!0,playsInline:!0,children:e.jsx("source",{src:i===a.GenderType.Male?a.FACE_SCAN_HEADSHOT.male.forward:a.FACE_SCAN_HEADSHOT.female.forward,type:"video/mp4"})})}),e.jsx("div",{className:` w-[120px] overflow-hidden ${1===n?"opacity-100":"opacity-0 hidden"} `,children:e.jsx("video",{className:"h-full w-full object-contain border-none",muted:!0,loop:!0,autoPlay:!0,playsInline:!0,children:e.jsx("source",{src:i===a.GenderType.Male?a.FACE_SCAN_HEADSHOT.male.left:a.FACE_SCAN_HEADSHOT.female.left,type:"video/mp4"})})}),e.jsx("div",{className:` w-[120px] overflow-hidden ${2===n?"opacity-100":"opacity-0 hidden"} `,children:e.jsx("video",{className:"h-full w-full object-contain border-none",muted:!0,loop:!0,autoPlay:!0,playsInline:!0,children:e.jsx("source",{src:i===a.GenderType.Male?a.FACE_SCAN_HEADSHOT.male.right:a.FACE_SCAN_HEADSHOT.female.right,type:"video/mp4"})})}),e.jsx("div",{className:` w-[120px] overflow-hidden ${3===n?"opacity-100":"opacity-0 hidden"} `,children:e.jsx("video",{className:"h-full w-full object-contain border-none",muted:!0,loop:!0,autoPlay:!0,playsInline:!0,children:e.jsx("source",{src:i===a.GenderType.Male?a.FACE_SCAN_HEADSHOT.male.smile:a.FACE_SCAN_HEADSHOT.female.smile,type:"video/mp4"})})})]})]})})}const d=({webcamRef:o,canvasRef:s})=>{const{isError:c,isSuccess:d,showLoader:u,hasError:f,errorType:g,resetScanState:h,showGuideCard:m,scanStage:p,videoLoading:y,setVideoLoading:S,videoError:x,setVideoError:v,gender:b,getButtonText:w,isScanning:F,startScan:C,isModelLoaded:j,onRetry:E}=t.useContext(a.ParamsContext),_=a.useConfig();return c?e.jsx(i,{onRetry:E}):d?e.jsx("div",{className:"fixed z-[9] common-ui-main w-full h-full",style:{background:_?.style?.base?.backgroundColor},children:e.jsx(a.LoadingScreen,{url:_?.loader,loaderType:"black"})}):e.jsxs(e.Fragment,{children:[e.jsx("audio",{id:"audioElement",crossOrigin:"anonymous",preload:"auto",style:{position:"absolute",zIndex:-99999},src:void 0}),u&&!f&&e.jsx("div",{className:"fixed z-[9] common-ui-main w-full h-full",style:{background:_?.style?.base?.backgroundColor},children:e.jsx(a.LoadingScreen,{url:_?.loader,loaderType:"black"})}),e.jsx("div",{className:"h-full flex-col common-ui-main relative w-full flex justify-center items-center text-center rounded-t-[20px]",style:{background:_?.style?.base?.backgroundColor},children:e.jsx("div",{className:"flex-1 w-full max-w-md overflow-hidden",children:e.jsxs("div",{className:"w-full h-full",children:[e.jsx("video",{ref:o,autoPlay:!0,playsInline:!0,muted:!0,width:a.videoConstraints.width.ideal,height:a.videoConstraints.height.ideal,className:"w-full h-full object-cover fixed left-0 top-0 z-0",style:{transform:"scaleX(-1)"}}),e.jsx("canvas",{ref:s,width:a.videoConstraints.width.ideal,height:a.videoConstraints.height.ideal,style:{transform:"scaleX(-1)",opacity:"0"}})]})})}),!u&&f&&g===a.FaceScanErrorType.Camera&&e.jsx(a.Modal,{testId:"face-scan-camera-error-screen",config:_}),!u&&f&&g!==a.FaceScanErrorType.Camera&&e.jsx(i,{loading:u,onRetry:h}),m&&!f&&!u&&e.jsx(r.Drawer,{open:!0,className:"face-scan-small camera-draw",anchor:"bottom",onClose:(e,t)=>{},hideBackdrop:!0,children:e.jsx(l,{stage:p,videoLoading:y,setVideoLoading:S,videoError:x,setVideoError:v,gender:b,btnConfig:{label:w(),onClick:F?h:C,isDisabled:u||!j,icon:F?e.jsx(n.ArrowRight,{}):e.jsx(e.Fragment,{})}})})]})};exports.FaceScan=n=>{const{onScanSuccess:r,onScanError:o,onRetry:s,onScanStart:i,onCaptureComplete:l,onUploadStart:u,onUploadEnd:f,onMeasurementSocketStart:g,onMeasurementSocketClose:h,config:m,isError:p,isSuccess:y}=n,S=n.userDetails??{email:"",gender:"male",deviceFocalLength:0,shopDomain:"",bodyScanId:""},x=n.token??"",v=t.useRef(null),b=t.useRef(null),w=t.useRef(null),F=t.useRef([]),C=t.useRef(null),j=t.useRef(null),E=t.useRef(0),_=t.useRef(null),[N,T]=t.useState(!1),[k,R]=t.useState(!1),[I,M]=t.useState(!1),[D,P]=t.useState(!0),[A,L]=t.useState(!1),[O,z]=t.useState(!1),[$,H]=t.useState(!1),[V,W]=t.useState(null),[K,U]=t.useState(a.generateUuid()),q=t.useMemo(()=>a.getSwanService(x),[x]),{email:B,gender:G,deviceFocalLength:J,shopDomain:X,callbackUrl:Q,bodyScanId:Y}=S,[Z,ee]=t.useState([]),[te,ae]=t.useState(a.videoConstraintsExact),ne=t.useMemo(()=>a.getPreferredMediaRecorderTypes(),[]),re=a.getRecordingMimeType(Z),oe=a.getRecordingExtension(re);a.usePosthogPageview();const se=t.useCallback(()=>{console.log("Stopping recording..."),cancelAnimationFrame(E.current),_.current&&(_.current.pause(),_.current.srcObject=null,_.current=null),w.current&&"recording"===w.current.state&&w.current.stop(),w.current=null},[]),ce=async()=>{if(l?.(),F.current){if(0===F.current.length)return console.error("No video data recorded"),W(a.FaceScanErrorType.Scan),H(!0),void T(!1);u?.(),T(!0);const e=new File(F.current,`${K}.${oe}`,{type:re}),t=j.current??await a.getVideoFPS(e),n=e.size,r=(n/1048576).toFixed(2),o=Math.round(n/1e4),s={video_size_mb:parseFloat(r),video_size_bytes:n,video_fps:t||0,blob_count:F.current.length,estimated_duration_seconds:o},c=[{gender:G},{face_scan_id:K},{focal_length:`${J}`},{customer_store_url:X},{scan_type:"face_scan"},{body_scan_id:Y}];Q&&c.push({callback_url:Q}),a.handleScanTimeCapture({eventName:`${X}/face_scan_meta_data`,faceScanId:K,email:B,data:JSON.stringify({metaData:c,videoData:s})});const i=Date.now();a.handleScanTimeCapture({eventName:`${X}/face_scan_upload_start`,faceScanId:K,email:B,startTime:i});try{const t=await q.fileUpload.faceScanFileUploader({file:e,arrayMetaData:c,objectKey:K,email:B,contentType:e.type}),n=Date.now(),r=n-i;a.handleScanTimeCapture({eventName:`${X}/face_scan_upload_complete`,faceScanId:K,email:B,completionTime:n,uploadDuration:r}),f?.(),console.log("✅ Upload successful",t),q.measurement.handlFaceScaneSocket({onPreopen:()=>{g?.(),a.handleWebSocketCapture({eventName:`${X}/webSocket`,faceScanID:K,connection:"pre_open",type:"faceScan_recommendation",email:B})},faceScanId:K,onOpen:()=>{a.handleWebSocketCapture({eventName:`${X}/webSocket`,faceScanID:K,connection:"open",type:"faceScan_recommendation",email:B}),console.log("websocket connect open")},onError:e=>{a.handleWebSocketCapture({eventName:`${X}/webSocket`,faceScanID:K,connection:"error",type:"faceScan_recommendation",email:B}),ye(e)},onSuccess:e=>{a.handleWebSocketCapture({eventName:`${X}/webSocket`,faceScanID:K,connection:"success",type:"faceScan_recommendation",email:B}),Se(e)},onClose:()=>{h?.(),console.log("websocket connect close"),a.handleWebSocketCapture({eventName:`${X}/webSocket`,faceScanID:K,connection:"close",type:"faceScan_recommendation",email:B})}})}catch(e){f?.(),ye(e)}}},ie=t.useCallback(()=>{const e=v.current?.srcObject;if(!e)return;const t=e.getVideoTracks()[0].getSettings(),{width:n=1280,height:r=720}=t,o=document.createElement("canvas"),s=o.getContext("2d");n>r?(o.width=r,o.height=n):(o.width=n,o.height=r);const c=document.createElement("video");c.srcObject=e,c.muted=!0,c.playsInline=!0,c.play(),_.current=c;const i=()=>{n>r?(s?.save(),s?.translate(o.width,0),s?.rotate(Math.PI/2),s?.drawImage(c,0,0,r,n),s?.restore()):s?.drawImage(c,0,0,n,r),E.current=requestAnimationFrame(i)};E.current=requestAnimationFrame(i);const l=t.frameRate??10;j.current=l;const d=o.captureStream(l),u={videoBitsPerSecond:15e5};let f;Z.length>0&&(u.mimeType=Z[0]);try{f=new MediaRecorder(d,u)}catch(e){return console.error("MediaRecorder init failed:",e),W(a.FaceScanErrorType.Scan),H(!0),void T(!1)}F.current=[],f.ondataavailable=e=>{e?.data&&e.data.size>0&&F.current&&F.current.push(e.data)},f.onstop=()=>{console.log("Recording stopped, total blobs:",F?.current?.length),ce()},f.start(100),w.current=f,console.log("Recording started successfully (portrait normalized)")},[Z,ce]),{faceScanDetector:le,scanStage:de,setScanStage:ue,resetScan:fe,isModelLoaded:ge,startScanSequence:he}=c({faceScanId:K,shopDomain:X,isError:p,isSuccess:y,onScanComplete:()=>{se()},onModelReady:()=>{R(!0)},onStartRecording:()=>{console.log("Stage 0 completed - starting recording for stages 1-3"),ie()}}),me=t.useCallback(()=>{ge&&(i?.(),ue(0),a.speechService.playAudio(`${a.voiceOverAssetsPath}face-scan-vos/Face-forward.mp3`),setTimeout(()=>{M(!0),setTimeout(()=>{he()},200)},200))},[ue,M,he,ge,i]),pe=t.useCallback(()=>{M(!1),P(!0),se(),fe(),s?.(),F.current=[],j.current=null,w.current&&(w.current=null),H(!1),W(null),ue(-1),U(a.generateUuid()),v.current&&C.current&&(v.current.srcObject=C.current,console.log("Camera stream restored after reset"))},[ue,M,P,se,fe,U]),ye=e=>{console.log(e,"ws error"),o?.(e),W(a.FaceScanErrorType.Scan),H(!0),T(!1),P(!1),a.handleScanTimeCapture({eventName:`${X}/faceScan`,faceScanId:K,status:"failed",email:B,data:JSON.stringify(e)})},Se=e=>{console.log(e,"ws success"),e&&"intermediate"===e?.resultType&&a.handleScanTimeCapture({eventName:`${X}/faceScan_success/intermediate`,faceScanId:K,status:"success",email:B,data:JSON.stringify(e)}),r?.(e)};t.useEffect(()=>{if(!p&&!y)return navigator.mediaDevices.getUserMedia&&navigator.mediaDevices.getUserMedia({video:te}).then(e=>{C.current=e,v.current&&(v.current.srcObject=e)}).catch(e=>{if(console.error("Error accessing webcam:",e),te===a.videoConstraintsExact)return void ae(a.videoConstraintsFallback);const t=["NotAllowedError","PermissionDeniedError","NotFoundError","DevicesNotFoundError","NotReadableError","TrackStartError"].includes(e?.name);W(t?a.FaceScanErrorType.Camera:a.FaceScanErrorType.Scan),H(!0)}),()=>{C.current&&C.current.getTracks().forEach(e=>e.stop())}},[p,y,te]),t.useEffect(()=>{if(!k||!I)return;const e=setInterval(()=>{le(v,b)},500);return()=>clearInterval(e)},[le,k,I]);return console.log("Model ready:",k,"Has error:",$,"Is scanning:",I,"showLoader",N),t.useEffect(()=>{const e=a.getSupportedMediaRecorderTypes(ne,a.videoTypes);ee(e)},[ne]),t.useEffect(()=>{ue(-1)},[]),e.jsx("div",{"data-face-scan-stage":de,children:e.jsx(a.LanguageContextProvider,{children:e.jsx(a.ConfigProvider,{config:m,children:e.jsx(a.ParamsContext.Provider,{value:{isError:p,isSuccess:y,showLoader:N,hasError:$,errorType:V,resetScanState:pe,showGuideCard:D,scanStage:de,videoLoading:A,setVideoLoading:L,videoError:O,setVideoError:z,gender:G,getButtonText:()=>I?a.LanguageKeys.reset:ge?a.LanguageKeys.start:a.LanguageKeys.loading,isScanning:I,startScan:me,isModelLoaded:ge,onRetry:s},children:e.jsx(d,{webcamRef:v,canvasRef:b})})})})})};
2
- //# sourceMappingURL=FaceScan-D2PL8KpZ.js.map
@@ -1,2 +0,0 @@
1
- "use strict";var e=require("react/jsx-runtime"),t=require("react"),a=require("./Modal-CDiBoVXR.js"),n=require("lucide-react"),r=require("@mui/material");let o=null,s=!1;const c=async()=>{if("undefined"==typeof window)return null;if(o)return o;if(s)for(;s;)if(await new Promise(e=>setTimeout(e,100)),o)return o;s=!0;try{const[e,t]=await Promise.all([import("@tensorflow/tfjs"),Promise.resolve().then(function(){return require("./pose-detection.esm-Bc8T4UAD.js")})]);await e.setBackend("webgl"),await e.ready();const n=await t.createDetector(t.SupportedModels.BlazePose,{runtime:"tfjs",modelType:"full"}),r=document.createElement("canvas");r.width="number"==typeof a.videoConstraints.width?a.videoConstraints.width:a.videoConstraints.width.ideal??a.videoConstraints.width.max??1280,r.height="number"==typeof a.videoConstraints.height?a.videoConstraints.height:a.videoConstraints.height.ideal??a.videoConstraints.height.max??720;const s=r.getContext("2d");if(s){s.fillStyle="black",s.fillRect(0,0,r.width,r.height);try{await n.estimatePoses(r)}catch(e){console.warn("Warmup frame failed (non-fatal):",e)}}return o=n,n}catch(e){return console.error("Failed to preload detector:",e),null}finally{s=!1}};function i({faceScanId:e,onValidPose:n,onScanComplete:r,onModelReady:o,onStartRecording:s,shopDomain:i,isError:l,isSuccess:d}){const u=t.useRef(null),[f,g]=t.useState(0),[h,m]=t.useState(0),[p,y]=t.useState(!1),[S,x]=t.useState(!1),v=t.useRef(!1),b=t.useRef(null),w=t.useRef(null),F=t.useRef(f),C=t.useRef(h),j=t.useRef([]),E=t.useRef(""),_=t.useRef(0),N=t.useRef(!1),T=t.useRef(0),k="undefined"!=typeof navigator&&(/iPad|iPhone|iPod/.test(navigator.userAgent)||"MacIntel"===navigator.platform&&navigator.maxTouchPoints>1),R=t.useMemo(()=>["Face front","Turn head fully left","Turn head fully right","Smile facing front"],[]),I=t.useMemo(()=>function(e,t){let a;return(...n)=>{a&&clearTimeout(a),a=setTimeout(()=>e(...n),t)}}(e=>{a.posthog.capture(`${i}/face_scan_pose_detection`,e)},4e3),[i]),D=t.useCallback((t,a,n,r,o,s)=>{const c=Date.now();if(!(c-T.current<4e3)){T.current=c;try{const c=t[0]||[0,0,0],i=t[2]||[0,0,0],l=t[5]||[0,0,0],d=t[9]||[0,0,0],u=t[10]||[0,0,0],f=t.map(e=>e[2]).filter(e=>e>0),g=f.length>0?f.reduce((e,t)=>e+t,0)/f.length:0,h=a.map(e=>e[2]).filter(e=>e>0),m=h.length>0?h.reduce((e,t)=>e+t,0)/h.length:0,p=Math.abs(i[0]-l[0]),y=c[0]-l[0],S=i[0]-c[0];let x="frontal";1===n?x="left":2===n?x="right":3===n&&(x="frontal_smile");const v={faceScanId:e,stage:n,timestamp:(new Date).toISOString(),data:JSON.stringify({headValid:r,bodyInvalid:o,consecutiveValid:s,avgFaceScore:parseFloat(g.toFixed(3)),avgBodyScore:parseFloat(m.toFixed(3)),faceKeypointsDetected:f.length,bodyKeypointsDetected:h.length,eyeDistance:parseFloat(p.toFixed(2)),noseToRightRatio:parseFloat((y/p).toFixed(3)),noseToLeftRatio:parseFloat((S/p).toFixed(3)),noseScore:parseFloat(c[2].toFixed(3)),leftEyeScore:parseFloat(i[2].toFixed(3)),rightEyeScore:parseFloat(l[2].toFixed(3)),leftMouthScore:parseFloat(d[2].toFixed(3)),rightMouthScore:parseFloat(u[2].toFixed(3)),expectedPosition:x})};I(v)}catch(e){console.warn("Failed to track pose detection:",e)}}},[e,I]),M=()=>{a.posthog.capture(`${i}/face_scan_detection_started`,{faceScanId:e,stage:F.current,timestamp:(new Date).toISOString(),stageName:R[F.current]}),setTimeout(()=>{x(!0)},1500)};return t.useEffect(()=>{if(!l&&!d)return(async()=>{if("undefined"!=typeof window)try{console.log("Initializing Face Scan...");const e=await c();e&&(u.current=e,console.log("Face scan model loaded successfully"),y(!0),o?.())}catch(e){console.error("Error initializing face scan:",e)}})(),()=>{(async()=>{try{y(!1)}catch(e){console.error("Error disposing resources:",e)}finally{g(0),m(0),F.current=0,C.current=0,j.current=[]}})()}},[l,d]),t.useEffect(()=>{F.current=f},[f]),t.useEffect(()=>{C.current=h},[h]),{faceScanDetector:async(t,o)=>{if(u.current&&t.current&&p&&S&&!(t.current.readyState<2||v.current)){v.current=!0;try{const c=t.current.videoWidth||720,l=t.current.videoHeight||1280;b.current||(b.current=document.createElement("canvas"),b.current.width=c,b.current.height=l);const d=b.current.getContext("2d");d&&d.drawImage(t.current,0,0,c,l);const f=await u.current.estimatePoses(d?b.current:t.current);if(f.length>0){const t=[],c=[];if(f[0].keypoints.forEach((e,a)=>{const n=e.score??0,r=[e.x??-1,e.y??-1,n];a<=10?t.push(r):c.push(r)}),o?.current){const e=o.current.getContext("2d"),{width:t,height:a}=o.current;if(e){e.clearRect(0,0,t,a);const n=Math.min(C.current/2,1),r=.35*a;e.beginPath(),e.strokeStyle="#00ff00",e.lineWidth=6,e.arc(t/2,a/2,r+10,-Math.PI/2,-Math.PI/2+2*n*Math.PI),e.stroke()}}const l=((e,t)=>{if(!t[0]||!t[2]||!t[5]||t[0][2]<.2||t[2][2]<.2||t[5][2]<.2)return!1;const a=.5*(t[10][1]+t[9][1])-.5*(t[5][1]+t[2][1]),n=(.5*(t[10][1]+t[9][1])-t[0][1])/a,r=n>.7||n<.3,o=Math.abs(t[2][1]-t[5][1])<.5*a&&Math.abs(t[9][1]-t[10][1])<.5*a,s=t[2][0]-t[5][0],c=t[0][0]-t[5][0],i=c>.4*s&&c<.6*s,l=c>.85*s,d=t[2][0]-t[0][0]>.85*s;switch(e){case 0:case 3:return!r&&o&&i;case 1:return!r&&o&&l;case 2:return!r&&o&&d;default:return!1}})(F.current,t),d=c.slice(2).filter(e=>e[2]>.7).length<=2;j.current.push(l&&d),j.current.length>10&&j.current.shift();if(j.current.filter(Boolean).length>=2){const e=C.current+1;m(e)}else m(Math.max(0,C.current-1));if(C.current>=2){n?.();const t=F.current+1;m(0),j.current=[],g(t),x(!1),(async()=>{if(await a.speechService.playAudio(`${a.voiceOverAssetsPath}face-scan-vos/Sound-effect.mp3`),a.posthog.capture(`${i}/face_scan_detection_stage_completed`,{faceScanId:e,completedStage:F.current,nextStage:t,timestamp:(new Date).toISOString(),totalStages:4,stageName:R[F.current]}),1===t&&s&&s(),t>=4)r?.();else{let e=null;switch(t){case 1:e="Left.mp3";break;case 2:e="Right.mp3";break;case 3:e="Smile.mp3"}e&&await a.speechService.playAudio(`${a.voiceOverAssetsPath}face-scan-vos/${e}`),M()}})()}D(t,c,F.current,l,d,C.current)}}catch(e){console.error("Pose detection error:",e)}finally{v.current=!1}}},scanStage:f,setScanStage:g,consecutiveValid:h,isModelLoaded:p,resetScan:()=>{a.posthog.capture(`${i}/face_scan_reset`,{faceScanId:e,stage:F.current,timestamp:(new Date).toISOString(),stageName:R[F.current],consecutiveValid:C.current}),g(0),m(0),x(!1),F.current=0,C.current=0,j.current=[],E.current="",_.current=0,N.current=!1,w.current&&(speechSynthesis.cancel(),w.current=null)},enableVoiceCommands:()=>{if(N.current=!0,"undefined"!=typeof window&&k&&"speechSynthesis"in window){const e=new SpeechSynthesisUtterance("");e.volume=0,speechSynthesis.speak(e)}},startScanSequence:M,isScanningActive:S}}function l({onRetry:r,loading:o}){const{translate:s}=t.useContext(a.LanguageContext)||{},c=a.useConfig();return e.jsx("div",{"data-testid":"face-scan-error-screen",className:"fixed common-ui-main top-[0] left-[0] z-[999] flex justify-center items-center w-full h-full",style:{background:c?.style?.base?.backgroundColor},children:e.jsxs("div",{className:"flex flex-col w-full items-center p-[1rem] rounded-lg ",children:[e.jsx(a.Header,{noTitle:!0}),e.jsxs("div",{className:"flex flex-col items-center w-full",children:[e.jsx("h2",{className:"text-xl font-semibold text-gray-800 ",style:{fontFamily:c?.style?.heading?.headingFontFamily||"SeriouslyNostalgic Fn",fontSize:c?.style?.heading?.headingFontSize||"32px",color:c?.style?.heading?.headingColor||"#000",fontWeight:c?.style?.heading?.headingFontWeight||"normal"},children:s?.(a.LanguageKeys.scanFailed)}),e.jsx("p",{className:"mb-[1.5rem]",style:{fontFamily:c?.style?.subheading?.subheadingFontFamily||"'Inter', sans-serif",fontSize:c?.style?.subheading?.subheadingFontSize||"14px",color:c?.style?.subheading?.subheadingColor||"#4b5563",fontWeight:c?.style?.subheading?.subheadingFontWeight||"normal"},children:s?.(a.LanguageKeys.clickToResetScan)}),e.jsx(a.SpecificButton,{"data-testid":"face-scan-retry-btn",disabled:o,className:"w-full h-[45px] shadow-[0px_1px_2px_0px_#00000040] text-[16px]",buttonText:s?.(a.LanguageKeys.resetScan),postfixIcon:e.jsx(n.ArrowRight,{}),buttonFunc:()=>r?.()})]})]})})}function d({stage:n,videoLoading:r,setVideoLoading:o,videoError:s,setVideoError:c,gender:i,btnConfig:l}){const{translate:d}=t.useContext(a.LanguageContext)||{},u=a.useConfig();return-1===n?e.jsxs("div",{"data-testid":"face-scan-guide",className:"text-center common-ui-main p-[16px] w-full h-full",style:{background:u?.style?.base?.backgroundColor},children:[e.jsxs("div",{className:"w-full",children:[e.jsx(a.Header,{noTitle:!0}),e.jsx("h2",{style:{fontFamily:u?.style?.heading?.headingFontFamily||"SeriouslyNostalgic Fn",fontSize:u?.style?.heading?.headingFontSize||"32px",color:u?.style?.heading?.headingColor||"#000",fontWeight:u?.style?.heading?.headingFontWeight||"normal"},children:d?.(a.LanguageKeys.faceVisible)}),r&&e.jsx("div",{className:"mb-4 flex items-center justify-center",style:{fontFamily:u?.style?.subheading?.subheadingFontFamily||"'Inter', sans-serif",fontSize:u?.style?.subheading?.subheadingFontSize||"14px",color:u?.style?.subheading?.subheadingColor||"#4b5563",fontWeight:u?.style?.subheading?.subheadingFontWeight||"normal"},children:d?.(a.LanguageKeys.loadingVideo)}),s&&e.jsx("div",{className:"mb-4 text-red-600",style:{fontFamily:u?.style?.subheading?.subheadingFontFamily||"'Inter', sans-serif",fontSize:u?.style?.subheading?.subheadingFontSize||"14px",color:"#ff0000",fontWeight:u?.style?.subheading?.subheadingFontWeight||"normal"},children:d?.(a.LanguageKeys.videoLoadFailed)}),!s&&e.jsx("div",{className:" w-[100px] mx-auto",children:e.jsx("video",{src:i===a.GenderType.Male?a.maleGlassesOffVideo:a.glassesOffVideo,autoPlay:!0,loop:!0,controls:!1,muted:!0,playsInline:!0,className:"h-full w-full object-contain border-none",onCanPlay:()=>o(!1),onLoadStart:()=>o(!0),onError:()=>c(!0),"aria-label":"Instructional video: Please remove your glasses before starting the scan."})})]}),e.jsx("div",{className:"flex justify-center w-full p-[1rem]",children:e.jsx(a.SpecificButton,{"data-testid":"face-scan-start-btn",disabled:l.isDisabled,className:"!w-[60px] !h-[35px] !py-0 !px-0",buttonText:d?.(l.label),postfixIcon:l?.icon,buttonFunc:l.onClick})})]}):e.jsx("div",{className:"text-center common-ui-main p-[16px] w-full h-full",style:{background:u?.style?.base?.backgroundColor},children:e.jsxs("div",{className:"w-full",children:[e.jsx(a.Header,{noTitle:!0}),e.jsx("h3",{className:"mb-[0.5rem]",style:{fontFamily:u?.style?.heading?.headingFontFamily||"SeriouslyNostalgic Fn",fontSize:u?.style?.heading?.headingFontSize||"32px",color:u?.style?.heading?.headingColor||"#000",fontWeight:u?.style?.heading?.headingFontWeight||"normal"},children:d?.(a.directionMessages[n])}),e.jsxs("div",{className:"max-w-[400px] justify-center gap-1 mx-auto flex items-center",children:[e.jsx("div",{className:` w-[120px] overflow-hidden ${0===n?"opacity-100":"opacity-0 hidden"} `,children:e.jsx("video",{className:"h-full w-full object-contain border-none",muted:!0,loop:!0,autoPlay:!0,playsInline:!0,children:e.jsx("source",{src:i===a.GenderType.Male?a.FACE_SCAN_HEADSHOT.male.forward:a.FACE_SCAN_HEADSHOT.female.forward,type:"video/mp4"})})}),e.jsx("div",{className:` w-[120px] overflow-hidden ${1===n?"opacity-100":"opacity-0 hidden"} `,children:e.jsx("video",{className:"h-full w-full object-contain border-none",muted:!0,loop:!0,autoPlay:!0,playsInline:!0,children:e.jsx("source",{src:i===a.GenderType.Male?a.FACE_SCAN_HEADSHOT.male.left:a.FACE_SCAN_HEADSHOT.female.left,type:"video/mp4"})})}),e.jsx("div",{className:` w-[120px] overflow-hidden ${2===n?"opacity-100":"opacity-0 hidden"} `,children:e.jsx("video",{className:"h-full w-full object-contain border-none",muted:!0,loop:!0,autoPlay:!0,playsInline:!0,children:e.jsx("source",{src:i===a.GenderType.Male?a.FACE_SCAN_HEADSHOT.male.right:a.FACE_SCAN_HEADSHOT.female.right,type:"video/mp4"})})}),e.jsx("div",{className:` w-[120px] overflow-hidden ${3===n?"opacity-100":"opacity-0 hidden"} `,children:e.jsx("video",{className:"h-full w-full object-contain border-none",muted:!0,loop:!0,autoPlay:!0,playsInline:!0,children:e.jsx("source",{src:i===a.GenderType.Male?a.FACE_SCAN_HEADSHOT.male.smile:a.FACE_SCAN_HEADSHOT.female.smile,type:"video/mp4"})})})]})]})})}const u=({webcamRef:o,canvasRef:s})=>{const{isError:c,isSuccess:i,showLoader:u,hasError:f,errorType:g,resetScanState:h,showGuideCard:m,scanStage:p,videoLoading:y,setVideoLoading:S,videoError:x,setVideoError:v,gender:b,getButtonText:w,isScanning:F,startScan:C,isModelLoaded:j,onRetry:E}=t.useContext(a.ParamsContext),_=a.useConfig();return c?e.jsx(l,{onRetry:E}):i?e.jsx("div",{className:"fixed z-[9] common-ui-main w-full h-full",style:{background:_?.style?.base?.backgroundColor},children:e.jsx(a.LoadingScreen,{url:_?.loader,loaderType:"black"})}):e.jsxs(e.Fragment,{children:[e.jsx("audio",{id:"audioElement",crossOrigin:"anonymous",preload:"auto",style:{position:"absolute",zIndex:-99999},src:void 0}),u&&!f&&e.jsx("div",{className:"fixed z-[9] common-ui-main w-full h-full",style:{background:_?.style?.base?.backgroundColor},children:e.jsx(a.LoadingScreen,{url:_?.loader,loaderType:"black"})}),e.jsx("div",{className:"h-full flex-col common-ui-main relative w-full flex justify-center items-center text-center rounded-t-[20px]",style:{background:_?.style?.base?.backgroundColor},children:e.jsx("div",{className:"flex-1 w-full max-w-md overflow-hidden",children:e.jsxs("div",{className:"w-full h-full",children:[e.jsx("video",{ref:o,autoPlay:!0,playsInline:!0,muted:!0,width:a.videoConstraints.width.ideal,height:a.videoConstraints.height.ideal,className:"w-full h-full object-cover fixed left-0 top-0 z-0",style:{transform:"scaleX(-1)"}}),e.jsx("canvas",{ref:s,width:a.videoConstraints.width.ideal,height:a.videoConstraints.height.ideal,style:{transform:"scaleX(-1)",opacity:"0"}})]})})}),!u&&f&&g===a.FaceScanErrorType.Camera&&e.jsx(a.Modal,{testId:"face-scan-camera-error-screen",config:_}),!u&&f&&g!==a.FaceScanErrorType.Camera&&e.jsx(l,{loading:u,onRetry:h}),m&&!f&&!u&&e.jsx(r.Drawer,{open:!0,className:"face-scan-small camera-draw",anchor:"bottom",onClose:(e,t)=>{},hideBackdrop:!0,children:e.jsx(d,{stage:p,videoLoading:y,setVideoLoading:S,videoError:x,setVideoError:v,gender:b,btnConfig:{label:w(),onClick:F?h:C,isDisabled:u||!j,icon:F?e.jsx(n.ArrowRight,{}):e.jsx(e.Fragment,{})}})})]})};exports.FaceScan=n=>{const{onScanSuccess:r,onScanError:o,onRetry:s,onScanStart:c,onCaptureComplete:l,onUploadStart:d,onUploadEnd:f,onMeasurementSocketStart:g,onMeasurementSocketClose:h,config:m,isError:p,isSuccess:y}=n,S=n.userDetails??{email:"",gender:"male",deviceFocalLength:0,shopDomain:"",bodyScanId:"",callbackUrl:null},x=n.token??"",v=t.useRef(null),b=t.useRef(null),w=t.useRef(null),F=t.useRef([]),C=t.useRef(null),j=t.useRef(null),E=t.useRef(0),_=t.useRef(null),[N,T]=t.useState(!1),[k,R]=t.useState(!1),[I,D]=t.useState(!1),[M,P]=t.useState(!0),[A,L]=t.useState(!1),[O,z]=t.useState(!1),[$,H]=t.useState(!1),[V,W]=t.useState(null),[K,U]=t.useState(a.generateUuid()),q=t.useMemo(()=>a.getSwanService(x),[x]),{email:B,gender:G,deviceFocalLength:J,shopDomain:X,callbackUrl:Q,bodyScanId:Y}=S,[Z,ee]=t.useState([]),[te,ae]=t.useState(a.videoConstraintsExact),ne=t.useMemo(()=>a.getPreferredMediaRecorderTypes(),[]),re=a.getRecordingMimeType(Z),oe=a.getRecordingExtension(re);a.usePosthogPageview();const se=t.useCallback(()=>{console.log("Stopping recording..."),cancelAnimationFrame(E.current),_.current&&(_.current.pause(),_.current.srcObject=null,_.current=null),w.current&&"recording"===w.current.state&&w.current.stop(),w.current=null},[]),ce=async()=>{if(l?.(),F.current){if(0===F.current.length)return console.error("No video data recorded"),W(a.FaceScanErrorType.Scan),H(!0),void T(!1);d?.(),T(!0);const e=new File(F.current,`${K}.${oe}`,{type:re}),t=j.current??await a.getVideoFPS(e),n=e.size,r=(n/1048576).toFixed(2),o=Math.round(n/1e4),s={video_size_mb:parseFloat(r),video_size_bytes:n,video_fps:t||0,blob_count:F.current.length,estimated_duration_seconds:o},c=[{gender:G},{face_scan_id:K},{focal_length:`${J}`},{customer_store_url:X},{scan_type:"face_scan"},{body_scan_id:Y}];Q&&c.push({callback_url:Q}),a.handleScanTimeCapture({eventName:`${X}/face_scan_meta_data`,faceScanId:K,email:B,data:JSON.stringify({metaData:c,videoData:s})});const i=Date.now();a.handleScanTimeCapture({eventName:`${X}/face_scan_upload_start`,faceScanId:K,email:B,startTime:i});try{const t=await q.fileUpload.faceScanFileUploader({file:e,arrayMetaData:c,objectKey:K,email:B,contentType:e.type}),n=Date.now(),r=n-i;a.handleScanTimeCapture({eventName:`${X}/face_scan_upload_complete`,faceScanId:K,email:B,completionTime:n,uploadDuration:r}),f?.(),console.log("✅ Upload successful",t),q.measurement.handlFaceScaneSocket({onPreopen:()=>{g?.(),a.handleWebSocketCapture({eventName:`${X}/webSocket`,faceScanID:K,connection:"pre_open",type:"faceScan_recommendation",email:B})},faceScanId:K,onOpen:()=>{a.handleWebSocketCapture({eventName:`${X}/webSocket`,faceScanID:K,connection:"open",type:"faceScan_recommendation",email:B}),console.log("websocket connect open")},onError:e=>{a.handleWebSocketCapture({eventName:`${X}/webSocket`,faceScanID:K,connection:"error",type:"faceScan_recommendation",email:B}),ye(e)},onSuccess:e=>{a.handleWebSocketCapture({eventName:`${X}/webSocket`,faceScanID:K,connection:"success",type:"faceScan_recommendation",email:B}),Se(e)},onClose:()=>{h?.(),console.log("websocket connect close"),a.handleWebSocketCapture({eventName:`${X}/webSocket`,faceScanID:K,connection:"close",type:"faceScan_recommendation",email:B})}})}catch(e){f?.(),ye(e)}}},ie=t.useCallback(()=>{const e=v.current?.srcObject;if(!e)return;const t=e.getVideoTracks()[0].getSettings(),{width:n=1280,height:r=720}=t,o=document.createElement("canvas"),s=o.getContext("2d");n>r?(o.width=r,o.height=n):(o.width=n,o.height=r);const c=document.createElement("video");c.srcObject=e,c.muted=!0,c.playsInline=!0,c.play(),_.current=c;const i=()=>{n>r?(s?.save(),s?.translate(o.width,0),s?.rotate(Math.PI/2),s?.drawImage(c,0,0,r,n),s?.restore()):s?.drawImage(c,0,0,n,r),E.current=requestAnimationFrame(i)};E.current=requestAnimationFrame(i);const l=t.frameRate??10;j.current=l;const d=o.captureStream(l),u={videoBitsPerSecond:15e5};let f;Z.length>0&&(u.mimeType=Z[0]);try{f=new MediaRecorder(d,u)}catch(e){return console.error("MediaRecorder init failed:",e),W(a.FaceScanErrorType.Scan),H(!0),void T(!1)}F.current=[],f.ondataavailable=e=>{e?.data&&e.data.size>0&&F.current&&F.current.push(e.data)},f.onstop=()=>{console.log("Recording stopped, total blobs:",F?.current?.length),ce()},f.start(100),w.current=f,console.log("Recording started successfully (portrait normalized)")},[Z,ce]),{faceScanDetector:le,scanStage:de,setScanStage:ue,resetScan:fe,isModelLoaded:ge,startScanSequence:he}=i({faceScanId:K,shopDomain:X,isError:p,isSuccess:y,onScanComplete:()=>{se()},onModelReady:()=>{R(!0)},onStartRecording:()=>{console.log("Stage 0 completed - starting recording for stages 1-3"),ie()}}),me=t.useCallback(()=>{ge&&(c?.(),ue(0),a.speechService.playAudio(`${a.voiceOverAssetsPath}face-scan-vos/Face-forward.mp3`),setTimeout(()=>{D(!0),setTimeout(()=>{he()},200)},200))},[ue,D,he,ge,c]),pe=t.useCallback(()=>{D(!1),P(!0),se(),fe(),s?.(),F.current=[],j.current=null,w.current&&(w.current=null),H(!1),W(null),ue(-1),U(a.generateUuid()),v.current&&C.current&&(v.current.srcObject=C.current,console.log("Camera stream restored after reset"))},[ue,D,P,se,fe,U]),ye=e=>{console.log(e,"ws error"),o?.(e),W(a.FaceScanErrorType.Scan),H(!0),T(!1),P(!1),a.handleScanTimeCapture({eventName:`${X}/faceScan`,faceScanId:K,status:"failed",email:B,data:JSON.stringify(e)})},Se=e=>{console.log(e,"ws success"),e&&"intermediate"===e?.resultType&&a.handleScanTimeCapture({eventName:`${X}/faceScan_success/intermediate`,faceScanId:K,status:"success",email:B,data:JSON.stringify(e)}),r?.(e)};t.useEffect(()=>{if(!p&&!y)return navigator.mediaDevices.getUserMedia&&navigator.mediaDevices.getUserMedia({video:te}).then(e=>{C.current=e,v.current&&(v.current.srcObject=e)}).catch(e=>{if(console.error("Error accessing webcam:",e),te===a.videoConstraintsExact)return void ae(a.videoConstraintsFallback);const t=["NotAllowedError","PermissionDeniedError","NotFoundError","DevicesNotFoundError","NotReadableError","TrackStartError"].includes(e?.name);W(t?a.FaceScanErrorType.Camera:a.FaceScanErrorType.Scan),H(!0)}),()=>{C.current&&C.current.getTracks().forEach(e=>e.stop())}},[p,y,te]),t.useEffect(()=>{if(!k||!I)return;const e=setInterval(()=>{le(v,b)},500);return()=>clearInterval(e)},[le,k,I]);return console.log("Model ready:",k,"Has error:",$,"Is scanning:",I,"showLoader",N),t.useEffect(()=>{const e=a.getSupportedMediaRecorderTypes(ne,a.videoTypes);ee(e)},[ne]),t.useEffect(()=>{ue(-1)},[]),e.jsx("div",{"data-face-scan-stage":de,children:e.jsx(a.LanguageContextProvider,{children:e.jsx(a.ConfigProvider,{config:m,children:e.jsx(a.ParamsContext.Provider,{value:{isError:p,isSuccess:y,showLoader:N,hasError:$,errorType:V,resetScanState:pe,showGuideCard:M,scanStage:de,videoLoading:A,setVideoLoading:L,videoError:O,setVideoError:z,gender:G,getButtonText:()=>I?a.LanguageKeys.reset:ge?a.LanguageKeys.start:a.LanguageKeys.loading,isScanning:I,startScan:me,isModelLoaded:ge,onRetry:s},children:e.jsx(u,{webcamRef:v,canvasRef:b})})})})})},exports.preloadDetector=c;
2
- //# sourceMappingURL=FaceScan-D3T_l4nN.js.map
@@ -1,2 +0,0 @@
1
- "use strict";var e=require("react/jsx-runtime"),t=require("react"),a=require("./Modal-CWoUZTh4.js"),n=require("lucide-react"),r=require("@mui/material");let o=null,s=!1;const c=async()=>{if("undefined"==typeof window)return null;if(o)return o;if(s)for(;s;)if(await new Promise(e=>setTimeout(e,100)),o)return o;s=!0;try{const[e,t]=await Promise.all([import("@tensorflow/tfjs"),Promise.resolve().then(function(){return require("./pose-detection.esm-Bc8T4UAD.js")})]);await e.setBackend("webgl"),await e.ready();const n=await t.createDetector(t.SupportedModels.BlazePose,{runtime:"tfjs",modelType:"full"}),r=document.createElement("canvas");r.width="number"==typeof a.videoConstraints.width?a.videoConstraints.width:a.videoConstraints.width.ideal??a.videoConstraints.width.max??1280,r.height="number"==typeof a.videoConstraints.height?a.videoConstraints.height:a.videoConstraints.height.ideal??a.videoConstraints.height.max??720;const s=r.getContext("2d");if(s){s.fillStyle="black",s.fillRect(0,0,r.width,r.height);try{await n.estimatePoses(r)}catch(e){console.warn("Warmup frame failed (non-fatal):",e)}}return o=n,n}catch(e){return console.error("Failed to preload detector:",e),null}finally{s=!1}};function i({faceScanId:e,onValidPose:n,onScanComplete:r,onModelReady:o,onStartRecording:s,shopDomain:i,isError:l,isSuccess:d}){const u=t.useRef(null),[f,g]=t.useState(0),[h,m]=t.useState(0),[p,y]=t.useState(!1),[S,x]=t.useState(!1),v=t.useRef(!1),b=t.useRef(null),w=t.useRef(null),F=t.useRef(f),C=t.useRef(h),j=t.useRef([]),E=t.useRef(""),_=t.useRef(0),N=t.useRef(!1),T=t.useRef(0),k="undefined"!=typeof navigator&&(/iPad|iPhone|iPod/.test(navigator.userAgent)||"MacIntel"===navigator.platform&&navigator.maxTouchPoints>1),R=t.useMemo(()=>["Face front","Turn head fully left","Turn head fully right","Smile facing front"],[]),I=t.useMemo(()=>function(e,t){let a;return(...n)=>{a&&clearTimeout(a),a=setTimeout(()=>e(...n),t)}}(e=>{a.posthog.capture(`${i}/face_scan_pose_detection`,e)},4e3),[i]),D=t.useCallback((t,a,n,r,o,s)=>{const c=Date.now();if(!(c-T.current<4e3)){T.current=c;try{const c=t[0]||[0,0,0],i=t[2]||[0,0,0],l=t[5]||[0,0,0],d=t[9]||[0,0,0],u=t[10]||[0,0,0],f=t.map(e=>e[2]).filter(e=>e>0),g=f.length>0?f.reduce((e,t)=>e+t,0)/f.length:0,h=a.map(e=>e[2]).filter(e=>e>0),m=h.length>0?h.reduce((e,t)=>e+t,0)/h.length:0,p=Math.abs(i[0]-l[0]),y=c[0]-l[0],S=i[0]-c[0];let x="frontal";1===n?x="left":2===n?x="right":3===n&&(x="frontal_smile");const v={faceScanId:e,stage:n,timestamp:(new Date).toISOString(),data:JSON.stringify({headValid:r,bodyInvalid:o,consecutiveValid:s,avgFaceScore:parseFloat(g.toFixed(3)),avgBodyScore:parseFloat(m.toFixed(3)),faceKeypointsDetected:f.length,bodyKeypointsDetected:h.length,eyeDistance:parseFloat(p.toFixed(2)),noseToRightRatio:parseFloat((y/p).toFixed(3)),noseToLeftRatio:parseFloat((S/p).toFixed(3)),noseScore:parseFloat(c[2].toFixed(3)),leftEyeScore:parseFloat(i[2].toFixed(3)),rightEyeScore:parseFloat(l[2].toFixed(3)),leftMouthScore:parseFloat(d[2].toFixed(3)),rightMouthScore:parseFloat(u[2].toFixed(3)),expectedPosition:x})};I(v)}catch(e){console.warn("Failed to track pose detection:",e)}}},[e,I]),M=()=>{a.posthog.capture(`${i}/face_scan_detection_started`,{faceScanId:e,stage:F.current,timestamp:(new Date).toISOString(),stageName:R[F.current]}),setTimeout(()=>{x(!0)},1500)};return t.useEffect(()=>{if(!l&&!d)return(async()=>{if("undefined"!=typeof window)try{console.log("Initializing Face Scan...");const e=await c();e&&(u.current=e,console.log("Face scan model loaded successfully"),y(!0),o?.())}catch(e){console.error("Error initializing face scan:",e)}})(),()=>{(async()=>{try{y(!1)}catch(e){console.error("Error disposing resources:",e)}finally{g(0),m(0),F.current=0,C.current=0,j.current=[]}})()}},[l,d]),t.useEffect(()=>{F.current=f},[f]),t.useEffect(()=>{C.current=h},[h]),{faceScanDetector:async(t,o)=>{if(u.current&&t.current&&p&&S&&!(t.current.readyState<2||v.current)){v.current=!0;try{const c=t.current.videoWidth||720,l=t.current.videoHeight||1280;b.current||(b.current=document.createElement("canvas"),b.current.width=c,b.current.height=l);const d=b.current.getContext("2d");d&&d.drawImage(t.current,0,0,c,l);const f=await u.current.estimatePoses(d?b.current:t.current);if(f.length>0){const t=[],c=[];if(f[0].keypoints.forEach((e,a)=>{const n=e.score??0,r=[e.x??-1,e.y??-1,n];a<=10?t.push(r):c.push(r)}),o?.current){const e=o.current.getContext("2d"),{width:t,height:a}=o.current;if(e){e.clearRect(0,0,t,a);const n=Math.min(C.current/2,1),r=.35*a;e.beginPath(),e.strokeStyle="#00ff00",e.lineWidth=6,e.arc(t/2,a/2,r+10,-Math.PI/2,-Math.PI/2+2*n*Math.PI),e.stroke()}}const l=((e,t)=>{if(!t[0]||!t[2]||!t[5]||t[0][2]<.2||t[2][2]<.2||t[5][2]<.2)return!1;const a=.5*(t[10][1]+t[9][1])-.5*(t[5][1]+t[2][1]),n=(.5*(t[10][1]+t[9][1])-t[0][1])/a,r=n>.7||n<.3,o=Math.abs(t[2][1]-t[5][1])<.5*a&&Math.abs(t[9][1]-t[10][1])<.5*a,s=t[2][0]-t[5][0],c=t[0][0]-t[5][0],i=c>.4*s&&c<.6*s,l=c>.85*s,d=t[2][0]-t[0][0]>.85*s;switch(e){case 0:case 3:return!r&&o&&i;case 1:return!r&&o&&l;case 2:return!r&&o&&d;default:return!1}})(F.current,t),d=c.slice(2).filter(e=>e[2]>.7).length<=2;j.current.push(l&&d),j.current.length>10&&j.current.shift();if(j.current.filter(Boolean).length>=2){const e=C.current+1;m(e)}else m(Math.max(0,C.current-1));if(C.current>=2){n?.();const t=F.current+1;m(0),j.current=[],g(t),x(!1),(async()=>{if(await a.speechService.playAudio(`${a.voiceOverAssetsPath}face-scan-vos/Sound-effect.mp3`),a.posthog.capture(`${i}/face_scan_detection_stage_completed`,{faceScanId:e,completedStage:F.current,nextStage:t,timestamp:(new Date).toISOString(),totalStages:4,stageName:R[F.current]}),1===t&&s&&s(),t>=4)r?.();else{let e=null;switch(t){case 1:e="Left.mp3";break;case 2:e="Right.mp3";break;case 3:e="Smile.mp3"}e&&await a.speechService.playAudio(`${a.voiceOverAssetsPath}face-scan-vos/${e}`),M()}})()}D(t,c,F.current,l,d,C.current)}}catch(e){console.error("Pose detection error:",e)}finally{v.current=!1}}},scanStage:f,setScanStage:g,consecutiveValid:h,isModelLoaded:p,resetScan:()=>{a.posthog.capture(`${i}/face_scan_reset`,{faceScanId:e,stage:F.current,timestamp:(new Date).toISOString(),stageName:R[F.current],consecutiveValid:C.current}),g(0),m(0),x(!1),F.current=0,C.current=0,j.current=[],E.current="",_.current=0,N.current=!1,w.current&&(speechSynthesis.cancel(),w.current=null)},enableVoiceCommands:()=>{if(N.current=!0,"undefined"!=typeof window&&k&&"speechSynthesis"in window){const e=new SpeechSynthesisUtterance("");e.volume=0,speechSynthesis.speak(e)}},startScanSequence:M,isScanningActive:S}}function l({onRetry:r,loading:o}){const{translate:s}=t.useContext(a.LanguageContext)||{},c=a.useConfig();return e.jsx("div",{"data-testid":"face-scan-error-screen",className:"fixed common-ui-main top-[0] left-[0] z-[999] flex justify-center items-center w-full h-full",style:{background:c?.style?.base?.backgroundColor},children:e.jsxs("div",{className:"flex flex-col w-full items-center p-[1rem] rounded-lg ",children:[e.jsx(a.Header,{noTitle:!0}),e.jsxs("div",{className:"flex flex-col items-center w-full",children:[e.jsx("h2",{className:"text-xl font-semibold text-gray-800 ",style:{fontFamily:c?.style?.heading?.headingFontFamily||"SeriouslyNostalgic Fn",fontSize:c?.style?.heading?.headingFontSize||"32px",color:c?.style?.heading?.headingColor||"#000",fontWeight:c?.style?.heading?.headingFontWeight||"normal"},children:s?.(a.LanguageKeys.scanFailed)}),e.jsx("p",{className:"mb-[1.5rem]",style:{fontFamily:c?.style?.subheading?.subheadingFontFamily||"'Inter', sans-serif",fontSize:c?.style?.subheading?.subheadingFontSize||"14px",color:c?.style?.subheading?.subheadingColor||"#4b5563",fontWeight:c?.style?.subheading?.subheadingFontWeight||"normal"},children:s?.(a.LanguageKeys.clickToResetScan)}),e.jsx(a.SpecificButton,{"data-testid":"face-scan-retry-btn",disabled:o,className:"w-full h-[45px] shadow-[0px_1px_2px_0px_#00000040] text-[16px]",buttonText:s?.(a.LanguageKeys.resetScan),postfixIcon:e.jsx(n.ArrowRight,{}),buttonFunc:()=>r?.()})]})]})})}function d({stage:n,videoLoading:r,setVideoLoading:o,videoError:s,setVideoError:c,gender:i,btnConfig:l}){const{translate:d}=t.useContext(a.LanguageContext)||{},u=a.useConfig();return-1===n?e.jsxs("div",{"data-testid":"face-scan-guide",className:"text-center common-ui-main p-[16px] w-full h-full",style:{background:u?.style?.base?.backgroundColor},children:[e.jsxs("div",{className:"w-full",children:[e.jsx(a.Header,{noTitle:!0}),e.jsx("h2",{style:{fontFamily:u?.style?.heading?.headingFontFamily||"SeriouslyNostalgic Fn",fontSize:u?.style?.heading?.headingFontSize||"32px",color:u?.style?.heading?.headingColor||"#000",fontWeight:u?.style?.heading?.headingFontWeight||"normal"},children:d?.(a.LanguageKeys.faceVisible)}),r&&e.jsx("div",{className:"mb-4 flex items-center justify-center",style:{fontFamily:u?.style?.subheading?.subheadingFontFamily||"'Inter', sans-serif",fontSize:u?.style?.subheading?.subheadingFontSize||"14px",color:u?.style?.subheading?.subheadingColor||"#4b5563",fontWeight:u?.style?.subheading?.subheadingFontWeight||"normal"},children:d?.(a.LanguageKeys.loadingVideo)}),s&&e.jsx("div",{className:"mb-4 text-red-600",style:{fontFamily:u?.style?.subheading?.subheadingFontFamily||"'Inter', sans-serif",fontSize:u?.style?.subheading?.subheadingFontSize||"14px",color:"#ff0000",fontWeight:u?.style?.subheading?.subheadingFontWeight||"normal"},children:d?.(a.LanguageKeys.videoLoadFailed)}),!s&&e.jsx("div",{className:" w-[100px] mx-auto",children:e.jsx("video",{src:i===a.GenderType.Male?a.maleGlassesOffVideo:a.glassesOffVideo,autoPlay:!0,loop:!0,controls:!1,muted:!0,playsInline:!0,className:"h-full w-full object-contain border-none",onCanPlay:()=>o(!1),onLoadStart:()=>o(!0),onError:()=>c(!0),"aria-label":"Instructional video: Please remove your glasses before starting the scan."})})]}),e.jsx("div",{className:"flex justify-center w-full p-[1rem]",children:e.jsx(a.SpecificButton,{"data-testid":"face-scan-start-btn",disabled:l.isDisabled,className:"!w-[60px] !h-[35px] !py-0 !px-0",buttonText:d?.(l.label),postfixIcon:l?.icon,buttonFunc:l.onClick})})]}):e.jsx("div",{className:"text-center common-ui-main p-[16px] w-full h-full",style:{background:u?.style?.base?.backgroundColor},children:e.jsxs("div",{className:"w-full",children:[e.jsx(a.Header,{noTitle:!0}),e.jsx("h3",{className:"mb-[0.5rem]",style:{fontFamily:u?.style?.heading?.headingFontFamily||"SeriouslyNostalgic Fn",fontSize:u?.style?.heading?.headingFontSize||"32px",color:u?.style?.heading?.headingColor||"#000",fontWeight:u?.style?.heading?.headingFontWeight||"normal"},children:d?.(a.directionMessages[n])}),e.jsxs("div",{className:"max-w-[400px] justify-center gap-1 mx-auto flex items-center",children:[e.jsx("div",{className:` w-[120px] overflow-hidden ${0===n?"opacity-100":"opacity-0 hidden"} `,children:e.jsx("video",{className:"h-full w-full object-contain border-none",muted:!0,loop:!0,autoPlay:!0,playsInline:!0,children:e.jsx("source",{src:i===a.GenderType.Male?a.FACE_SCAN_HEADSHOT.male.forward:a.FACE_SCAN_HEADSHOT.female.forward,type:"video/mp4"})})}),e.jsx("div",{className:` w-[120px] overflow-hidden ${1===n?"opacity-100":"opacity-0 hidden"} `,children:e.jsx("video",{className:"h-full w-full object-contain border-none",muted:!0,loop:!0,autoPlay:!0,playsInline:!0,children:e.jsx("source",{src:i===a.GenderType.Male?a.FACE_SCAN_HEADSHOT.male.left:a.FACE_SCAN_HEADSHOT.female.left,type:"video/mp4"})})}),e.jsx("div",{className:` w-[120px] overflow-hidden ${2===n?"opacity-100":"opacity-0 hidden"} `,children:e.jsx("video",{className:"h-full w-full object-contain border-none",muted:!0,loop:!0,autoPlay:!0,playsInline:!0,children:e.jsx("source",{src:i===a.GenderType.Male?a.FACE_SCAN_HEADSHOT.male.right:a.FACE_SCAN_HEADSHOT.female.right,type:"video/mp4"})})}),e.jsx("div",{className:` w-[120px] overflow-hidden ${3===n?"opacity-100":"opacity-0 hidden"} `,children:e.jsx("video",{className:"h-full w-full object-contain border-none",muted:!0,loop:!0,autoPlay:!0,playsInline:!0,children:e.jsx("source",{src:i===a.GenderType.Male?a.FACE_SCAN_HEADSHOT.male.smile:a.FACE_SCAN_HEADSHOT.female.smile,type:"video/mp4"})})})]})]})})}const u=({webcamRef:o,canvasRef:s})=>{const{isError:c,isSuccess:i,showLoader:u,hasError:f,errorType:g,resetScanState:h,showGuideCard:m,scanStage:p,videoLoading:y,setVideoLoading:S,videoError:x,setVideoError:v,gender:b,getButtonText:w,isScanning:F,startScan:C,isModelLoaded:j,onRetry:E}=t.useContext(a.ParamsContext),_=a.useConfig();return c?e.jsx(l,{onRetry:E}):i?e.jsx("div",{className:"fixed z-[9] common-ui-main w-full h-full",style:{background:_?.style?.base?.backgroundColor},children:e.jsx(a.LoadingScreen,{url:_?.loader,loaderType:"black"})}):e.jsxs(e.Fragment,{children:[e.jsx("audio",{id:"audioElement",crossOrigin:"anonymous",preload:"auto",style:{position:"absolute",zIndex:-99999},src:void 0}),u&&!f&&e.jsx("div",{className:"fixed z-[9] common-ui-main w-full h-full",style:{background:_?.style?.base?.backgroundColor},children:e.jsx(a.LoadingScreen,{url:_?.loader,loaderType:"black"})}),e.jsx("div",{className:"h-full flex-col common-ui-main relative w-full flex justify-center items-center text-center rounded-t-[20px]",style:{background:_?.style?.base?.backgroundColor},children:e.jsx("div",{className:"flex-1 w-full max-w-md overflow-hidden",children:e.jsxs("div",{className:"w-full h-full",children:[e.jsx("video",{ref:o,autoPlay:!0,playsInline:!0,muted:!0,width:a.videoConstraints.width.ideal,height:a.videoConstraints.height.ideal,className:"w-full h-full object-cover fixed left-0 top-0 z-0",style:{transform:"scaleX(-1)"}}),e.jsx("canvas",{ref:s,width:a.videoConstraints.width.ideal,height:a.videoConstraints.height.ideal,style:{transform:"scaleX(-1)",opacity:"0"}})]})})}),!u&&f&&g===a.FaceScanErrorType.Camera&&e.jsx(a.Modal,{testId:"face-scan-camera-error-screen",config:_}),!u&&f&&g!==a.FaceScanErrorType.Camera&&e.jsx(l,{loading:u,onRetry:h}),m&&!f&&!u&&e.jsx(r.Drawer,{open:!0,className:"face-scan-small camera-draw",anchor:"bottom",onClose:(e,t)=>{},hideBackdrop:!0,children:e.jsx(d,{stage:p,videoLoading:y,setVideoLoading:S,videoError:x,setVideoError:v,gender:b,btnConfig:{label:w(),onClick:F?h:C,isDisabled:u||!j,icon:F?e.jsx(n.ArrowRight,{}):e.jsx(e.Fragment,{})}})})]})};exports.FaceScan=n=>{const{onScanSuccess:r,onScanError:o,onRetry:s,onScanStart:c,onCaptureComplete:l,onUploadStart:d,onUploadEnd:f,onMeasurementSocketStart:g,onMeasurementSocketClose:h,config:m,isError:p,isSuccess:y}=n,S=n.userDetails??{email:"",gender:"male",deviceFocalLength:0,shopDomain:"",bodyScanId:"",callbackUrl:null},x=n.token??"",v=t.useRef(null),b=t.useRef(null),w=t.useRef(null),F=t.useRef([]),C=t.useRef(null),j=t.useRef(null),E=t.useRef(0),_=t.useRef(null),[N,T]=t.useState(!1),[k,R]=t.useState(!1),[I,D]=t.useState(!1),[M,P]=t.useState(!0),[A,L]=t.useState(!1),[O,z]=t.useState(!1),[$,H]=t.useState(!1),[V,W]=t.useState(null),[K,U]=t.useState(a.generateUuid()),q=t.useMemo(()=>a.getSwanService(x),[x]),{email:B,gender:G,deviceFocalLength:J,shopDomain:X,callbackUrl:Q,bodyScanId:Y}=S,[Z,ee]=t.useState([]),[te,ae]=t.useState(a.videoConstraintsExact),ne=t.useMemo(()=>a.getPreferredMediaRecorderTypes(),[]),re=a.getRecordingMimeType(Z),oe=a.getRecordingExtension(re);a.usePosthogPageview();const se=t.useCallback(()=>{console.log("Stopping recording..."),cancelAnimationFrame(E.current),_.current&&(_.current.pause(),_.current.srcObject=null,_.current=null),w.current&&"recording"===w.current.state&&w.current.stop(),w.current=null},[]),ce=async()=>{if(l?.(),F.current){if(0===F.current.length)return console.error("No video data recorded"),W(a.FaceScanErrorType.Scan),H(!0),void T(!1);d?.(),T(!0);const e=new File(F.current,`${K}.${oe}`,{type:re}),t=j.current??await a.getVideoFPS(e),n=e.size,r=(n/1048576).toFixed(2),o=Math.round(n/1e4),s={video_size_mb:parseFloat(r),video_size_bytes:n,video_fps:t||0,blob_count:F.current.length,estimated_duration_seconds:o},c=[{gender:G},{face_scan_id:K},{focal_length:`${J}`},{customer_store_url:X},{scan_type:"face_scan"},{body_scan_id:Y}];Q&&c.push({callback_url:Q}),a.handleScanTimeCapture({eventName:`${X}/face_scan_meta_data`,faceScanId:K,email:B,data:JSON.stringify({metaData:c,videoData:s})});const i=Date.now();a.handleScanTimeCapture({eventName:`${X}/face_scan_upload_start`,faceScanId:K,email:B,startTime:i});try{const t=await q.fileUpload.faceScanFileUploader({file:e,arrayMetaData:c,objectKey:K,email:B,contentType:e.type}),n=Date.now(),r=n-i;a.handleScanTimeCapture({eventName:`${X}/face_scan_upload_complete`,faceScanId:K,email:B,completionTime:n,uploadDuration:r}),f?.(),console.log("✅ Upload successful",t),q.measurement.handlFaceScaneSocket({onPreopen:()=>{g?.(),a.handleWebSocketCapture({eventName:`${X}/webSocket`,faceScanID:K,connection:"pre_open",type:"faceScan_recommendation",email:B})},faceScanId:K,onOpen:()=>{a.handleWebSocketCapture({eventName:`${X}/webSocket`,faceScanID:K,connection:"open",type:"faceScan_recommendation",email:B}),console.log("websocket connect open")},onError:e=>{a.handleWebSocketCapture({eventName:`${X}/webSocket`,faceScanID:K,connection:"error",type:"faceScan_recommendation",email:B}),ye(e)},onSuccess:e=>{a.handleWebSocketCapture({eventName:`${X}/webSocket`,faceScanID:K,connection:"success",type:"faceScan_recommendation",email:B}),Se(e)},onClose:()=>{h?.(),console.log("websocket connect close"),a.handleWebSocketCapture({eventName:`${X}/webSocket`,faceScanID:K,connection:"close",type:"faceScan_recommendation",email:B})}})}catch(e){f?.(),ye(e)}}},ie=t.useCallback(()=>{const e=v.current?.srcObject;if(!e)return;const t=e.getVideoTracks()[0].getSettings(),{width:n=1280,height:r=720}=t,o=document.createElement("canvas"),s=o.getContext("2d");n>r?(o.width=r,o.height=n):(o.width=n,o.height=r);const c=document.createElement("video");c.srcObject=e,c.muted=!0,c.playsInline=!0,c.play(),_.current=c;const i=()=>{n>r?(s?.save(),s?.translate(o.width,0),s?.rotate(Math.PI/2),s?.drawImage(c,0,0,r,n),s?.restore()):s?.drawImage(c,0,0,n,r),E.current=requestAnimationFrame(i)};E.current=requestAnimationFrame(i);const l=t.frameRate??10;j.current=l;const d=o.captureStream(l),u={videoBitsPerSecond:15e5};let f;Z.length>0&&(u.mimeType=Z[0]);try{f=new MediaRecorder(d,u)}catch(e){return console.error("MediaRecorder init failed:",e),W(a.FaceScanErrorType.Scan),H(!0),void T(!1)}F.current=[],f.ondataavailable=e=>{e?.data&&e.data.size>0&&F.current&&F.current.push(e.data)},f.onstop=()=>{console.log("Recording stopped, total blobs:",F?.current?.length),ce()},f.start(100),w.current=f,console.log("Recording started successfully (portrait normalized)")},[Z,ce]),{faceScanDetector:le,scanStage:de,setScanStage:ue,resetScan:fe,isModelLoaded:ge,startScanSequence:he}=i({faceScanId:K,shopDomain:X,isError:p,isSuccess:y,onScanComplete:()=>{se()},onModelReady:()=>{R(!0)},onStartRecording:()=>{console.log("Stage 0 completed - starting recording for stages 1-3"),ie()}}),me=t.useCallback(()=>{ge&&(c?.(),ue(0),a.speechService.playAudio(`${a.voiceOverAssetsPath}face-scan-vos/Face-forward.mp3`),setTimeout(()=>{D(!0),setTimeout(()=>{he()},200)},200))},[ue,D,he,ge,c]),pe=t.useCallback(()=>{D(!1),P(!0),se(),fe(),s?.(),F.current=[],j.current=null,w.current&&(w.current=null),H(!1),W(null),ue(-1),U(a.generateUuid()),v.current&&C.current&&(v.current.srcObject=C.current,console.log("Camera stream restored after reset"))},[ue,D,P,se,fe,U]),ye=e=>{console.log(e,"ws error"),o?.(e),W(a.FaceScanErrorType.Scan),H(!0),T(!1),P(!1),a.handleScanTimeCapture({eventName:`${X}/faceScan`,faceScanId:K,status:"failed",email:B,data:JSON.stringify(e)})},Se=e=>{console.log(e,"ws success"),e&&"intermediate"===e?.resultType&&a.handleScanTimeCapture({eventName:`${X}/faceScan_success/intermediate`,faceScanId:K,status:"success",email:B,data:JSON.stringify(e)}),r?.(e)};t.useEffect(()=>{if(!p&&!y)return navigator.mediaDevices.getUserMedia&&navigator.mediaDevices.getUserMedia({video:te}).then(e=>{C.current=e,v.current&&(v.current.srcObject=e)}).catch(e=>{if(console.error("Error accessing webcam:",e),te===a.videoConstraintsExact)return void ae(a.videoConstraintsFallback);const t=["NotAllowedError","PermissionDeniedError","NotFoundError","DevicesNotFoundError","NotReadableError","TrackStartError"].includes(e?.name);W(t?a.FaceScanErrorType.Camera:a.FaceScanErrorType.Scan),H(!0)}),()=>{C.current&&C.current.getTracks().forEach(e=>e.stop())}},[p,y,te]),t.useEffect(()=>{if(!k||!I)return;const e=setInterval(()=>{le(v,b)},500);return()=>clearInterval(e)},[le,k,I]);return console.log("Model ready:",k,"Has error:",$,"Is scanning:",I,"showLoader",N),t.useEffect(()=>{const e=a.getSupportedMediaRecorderTypes(ne,a.videoTypes);ee(e)},[ne]),t.useEffect(()=>{ue(-1)},[]),e.jsx("div",{"data-face-scan-stage":de,children:e.jsx(a.LanguageContextProvider,{children:e.jsx(a.ConfigProvider,{config:m,children:e.jsx(a.ParamsContext.Provider,{value:{isError:p,isSuccess:y,showLoader:N,hasError:$,errorType:V,resetScanState:pe,showGuideCard:M,scanStage:de,videoLoading:A,setVideoLoading:L,videoError:O,setVideoError:z,gender:G,getButtonText:()=>I?a.LanguageKeys.reset:ge?a.LanguageKeys.start:a.LanguageKeys.loading,isScanning:I,startScan:me,isModelLoaded:ge,onRetry:s},children:e.jsx(u,{webcamRef:v,canvasRef:b})})})})})},exports.preloadDetector=c;
2
- //# sourceMappingURL=FaceScan-DCm43Nrq.js.map
@@ -1,2 +0,0 @@
1
- import{jsx as e,jsxs as t,Fragment as a}from"react/jsx-runtime";import{useRef as n,useState as r,useMemo as o,useCallback as c,useEffect as i,useContext as s}from"react";import{v as l,p as d,s as u,a as m,L as f,u as h,H as g,b as p,S as y,m as S,g as b,G as v,d as w,F as x,P as F,c as N,M as I,e as _,f as k,h as E,i as C,j as M,k as D,l as T,n as P,o as z,q as R,r as L,t as $,w as j,C as V,x as O,y as W,z as A,A as U}from"./Modal-BitizIvu.js";import{ArrowRight as B}from"lucide-react";import{Drawer as q}from"@mui/material";let J=null,G=!1;const H=async()=>{if("undefined"==typeof window)return null;if(J)return J;if(G)for(;G;)if(await new Promise(e=>setTimeout(e,100)),J)return J;G=!0;try{const[e,t]=await Promise.all([import("@tensorflow/tfjs"),import("./pose-detection.esm-DC0_P6R7.js")]);await e.setBackend("webgl"),await e.ready();const a=await t.createDetector(t.SupportedModels.BlazePose,{runtime:"tfjs",modelType:"full"}),n=document.createElement("canvas");n.width="number"==typeof l.width?l.width:l.width.ideal??l.width.max??1280,n.height="number"==typeof l.height?l.height:l.height.ideal??l.height.max??720;const r=n.getContext("2d");if(r){r.fillStyle="black",r.fillRect(0,0,n.width,n.height);try{await a.estimatePoses(n)}catch(e){console.warn("Warmup frame failed (non-fatal):",e)}}return J=a,a}catch(e){return console.error("Failed to preload detector:",e),null}finally{G=!1}};function K({faceScanId:e,onValidPose:t,onScanComplete:a,onModelReady:s,onStartRecording:l,shopDomain:f,isError:h,isSuccess:g}){const p=n(null),[y,S]=r(0),[b,v]=r(0),[w,x]=r(!1),[F,N]=r(!1),I=n(!1),_=n(null),k=n(null),E=n(y),C=n(b),M=n([]),D=n(""),T=n(0),P=n(!1),z=n(0),R="undefined"!=typeof navigator&&(/iPad|iPhone|iPod/.test(navigator.userAgent)||"MacIntel"===navigator.platform&&navigator.maxTouchPoints>1),L=o(()=>["Face front","Turn head fully left","Turn head fully right","Smile facing front"],[]),$=o(()=>function(e,t){let a;return(...n)=>{a&&clearTimeout(a),a=setTimeout(()=>e(...n),t)}}(e=>{d.capture(`${f}/face_scan_pose_detection`,e)},4e3),[f]),j=c((t,a,n,r,o,c)=>{const i=Date.now();if(!(i-z.current<4e3)){z.current=i;try{const i=t[0]||[0,0,0],s=t[2]||[0,0,0],l=t[5]||[0,0,0],d=t[9]||[0,0,0],u=t[10]||[0,0,0],m=t.map(e=>e[2]).filter(e=>e>0),f=m.length>0?m.reduce((e,t)=>e+t,0)/m.length:0,h=a.map(e=>e[2]).filter(e=>e>0),g=h.length>0?h.reduce((e,t)=>e+t,0)/h.length:0,p=Math.abs(s[0]-l[0]),y=i[0]-l[0],S=s[0]-i[0];let b="frontal";1===n?b="left":2===n?b="right":3===n&&(b="frontal_smile");const v={faceScanId:e,stage:n,timestamp:(new Date).toISOString(),data:JSON.stringify({headValid:r,bodyInvalid:o,consecutiveValid:c,avgFaceScore:parseFloat(f.toFixed(3)),avgBodyScore:parseFloat(g.toFixed(3)),faceKeypointsDetected:m.length,bodyKeypointsDetected:h.length,eyeDistance:parseFloat(p.toFixed(2)),noseToRightRatio:parseFloat((y/p).toFixed(3)),noseToLeftRatio:parseFloat((S/p).toFixed(3)),noseScore:parseFloat(i[2].toFixed(3)),leftEyeScore:parseFloat(s[2].toFixed(3)),rightEyeScore:parseFloat(l[2].toFixed(3)),leftMouthScore:parseFloat(d[2].toFixed(3)),rightMouthScore:parseFloat(u[2].toFixed(3)),expectedPosition:b})};$(v)}catch(e){console.warn("Failed to track pose detection:",e)}}},[e,$]),V=()=>{d.capture(`${f}/face_scan_detection_started`,{faceScanId:e,stage:E.current,timestamp:(new Date).toISOString(),stageName:L[E.current]}),setTimeout(()=>{N(!0)},1500)};return i(()=>{if(!h&&!g)return(async()=>{if("undefined"!=typeof window)try{console.log("Initializing Face Scan...");const e=await H();e&&(p.current=e,console.log("Face scan model loaded successfully"),x(!0),s?.())}catch(e){console.error("Error initializing face scan:",e)}})(),()=>{(async()=>{try{x(!1)}catch(e){console.error("Error disposing resources:",e)}finally{S(0),v(0),E.current=0,C.current=0,M.current=[]}})()}},[h,g]),i(()=>{E.current=y},[y]),i(()=>{C.current=b},[b]),{faceScanDetector:async(n,r)=>{if(p.current&&n.current&&w&&F&&!(n.current.readyState<2||I.current)){I.current=!0;try{const o=n.current.videoWidth||720,c=n.current.videoHeight||1280;_.current||(_.current=document.createElement("canvas"),_.current.width=o,_.current.height=c);const i=_.current.getContext("2d");i&&i.drawImage(n.current,0,0,o,c);const s=await p.current.estimatePoses(i?_.current:n.current);if(s.length>0){const n=[],o=[];if(s[0].keypoints.forEach((e,t)=>{const a=e.score??0,r=[e.x??-1,e.y??-1,a];t<=10?n.push(r):o.push(r)}),r?.current){const e=r.current.getContext("2d"),{width:t,height:a}=r.current;if(e){e.clearRect(0,0,t,a);const n=Math.min(C.current/2,1),r=.35*a;e.beginPath(),e.strokeStyle="#00ff00",e.lineWidth=6,e.arc(t/2,a/2,r+10,-Math.PI/2,-Math.PI/2+2*n*Math.PI),e.stroke()}}const c=((e,t)=>{if(!t[0]||!t[2]||!t[5]||t[0][2]<.2||t[2][2]<.2||t[5][2]<.2)return!1;const a=.5*(t[10][1]+t[9][1])-.5*(t[5][1]+t[2][1]),n=(.5*(t[10][1]+t[9][1])-t[0][1])/a,r=n>.7||n<.3,o=Math.abs(t[2][1]-t[5][1])<.5*a&&Math.abs(t[9][1]-t[10][1])<.5*a,c=t[2][0]-t[5][0],i=t[0][0]-t[5][0],s=i>.4*c&&i<.6*c,l=i>.85*c,d=t[2][0]-t[0][0]>.85*c;switch(e){case 0:case 3:return!r&&o&&s;case 1:return!r&&o&&l;case 2:return!r&&o&&d;default:return!1}})(E.current,n),i=o.slice(2).filter(e=>e[2]>.7).length<=2;M.current.push(c&&i),M.current.length>10&&M.current.shift();if(M.current.filter(Boolean).length>=2){const e=C.current+1;v(e)}else v(Math.max(0,C.current-1));if(C.current>=2){t?.();const n=E.current+1;v(0),M.current=[],S(n),N(!1),(async()=>{if(await u.playAudio(`${m}face-scan-vos/Sound-effect.mp3`),d.capture(`${f}/face_scan_detection_stage_completed`,{faceScanId:e,completedStage:E.current,nextStage:n,timestamp:(new Date).toISOString(),totalStages:4,stageName:L[E.current]}),1===n&&l&&l(),n>=4)a?.();else{let e=null;switch(n){case 1:e="Left.mp3";break;case 2:e="Right.mp3";break;case 3:e="Smile.mp3"}e&&await u.playAudio(`${m}face-scan-vos/${e}`),V()}})()}j(n,o,E.current,c,i,C.current)}}catch(e){console.error("Pose detection error:",e)}finally{I.current=!1}}},scanStage:y,setScanStage:S,consecutiveValid:b,isModelLoaded:w,resetScan:()=>{d.capture(`${f}/face_scan_reset`,{faceScanId:e,stage:E.current,timestamp:(new Date).toISOString(),stageName:L[E.current],consecutiveValid:C.current}),S(0),v(0),N(!1),E.current=0,C.current=0,M.current=[],D.current="",T.current=0,P.current=!1,k.current&&(speechSynthesis.cancel(),k.current=null)},enableVoiceCommands:()=>{if(P.current=!0,"undefined"!=typeof window&&R&&"speechSynthesis"in window){const e=new SpeechSynthesisUtterance("");e.volume=0,speechSynthesis.speak(e)}},startScanSequence:V,isScanningActive:F}}function X({onRetry:a,loading:n}){const{translate:r}=s(f)||{},o=h();return e("div",{"data-testid":"face-scan-error-screen",className:"fixed common-ui-main top-[0] left-[0] z-[999] flex justify-center items-center w-full h-full",style:{background:o?.style?.base?.backgroundColor},children:t("div",{className:"flex flex-col w-full items-center p-[1rem] rounded-lg ",children:[e(g,{noTitle:!0}),t("div",{className:"flex flex-col items-center w-full",children:[e("h2",{className:"text-xl my-[0] font-semibold text-gray-800 ",style:{fontFamily:o?.style?.heading?.headingFontFamily||"SeriouslyNostalgic Fn",fontSize:o?.style?.heading?.headingFontSize||"32px",color:o?.style?.heading?.headingColor||"#000",fontWeight:o?.style?.heading?.headingFontWeight||"normal"},children:r?.(p.scanFailed)}),e("p",{className:"mb-[1.5rem]",style:{fontFamily:o?.style?.subheading?.subheadingFontFamily||"'Inter', sans-serif",fontSize:o?.style?.subheading?.subheadingFontSize||"14px",color:o?.style?.subheading?.subheadingColor||"#4b5563",fontWeight:o?.style?.subheading?.subheadingFontWeight||"normal"},children:r?.(p.clickToResetScan)}),e(y,{"data-testid":"face-scan-retry-btn",disabled:n,className:"w-full h-[45px] shadow-[0px_1px_2px_0px_#00000040] text-[16px]",buttonText:r?.(p.resetScan),postfixIcon:e(B,{}),buttonFunc:()=>a?.()})]})]})})}function Q({stage:a,videoLoading:n,setVideoLoading:r,videoError:o,setVideoError:c,gender:i,btnConfig:l}){const{translate:d}=s(f)||{},u=h();return-1===a?t("div",{"data-testid":"face-scan-guide",className:"text-center common-ui-main p-[16px] w-full h-full",style:{background:u?.style?.base?.backgroundColor},children:[t("div",{className:"w-full",children:[e(g,{noTitle:!0}),e("h2",{className:"my-[0]",style:{fontFamily:u?.style?.heading?.headingFontFamily||"SeriouslyNostalgic Fn",fontSize:u?.style?.heading?.headingFontSize||"32px",color:u?.style?.heading?.headingColor||"#000",fontWeight:u?.style?.heading?.headingFontWeight||"normal"},children:d?.(p.faceVisible)}),n&&e("div",{className:"mb-4 flex items-center justify-center",style:{fontFamily:u?.style?.subheading?.subheadingFontFamily||"'Inter', sans-serif",fontSize:u?.style?.subheading?.subheadingFontSize||"14px",color:u?.style?.subheading?.subheadingColor||"#4b5563",fontWeight:u?.style?.subheading?.subheadingFontWeight||"normal"},children:d?.(p.loadingVideo)}),o&&e("div",{className:"mb-4 text-red-600",style:{fontFamily:u?.style?.subheading?.subheadingFontFamily||"'Inter', sans-serif",fontSize:u?.style?.subheading?.subheadingFontSize||"14px",color:"#ff0000",fontWeight:u?.style?.subheading?.subheadingFontWeight||"normal"},children:d?.(p.videoLoadFailed)}),!o&&e("div",{className:" w-[100px] mx-auto",children:e("video",{src:i===v.Male?S:b,autoPlay:!0,loop:!0,controls:!1,muted:!0,playsInline:!0,className:"h-full w-full object-contain border-none",onCanPlay:()=>r(!1),onLoadStart:()=>r(!0),onError:()=>c(!0),"aria-label":"Instructional video: Please remove your glasses before starting the scan."})})]}),e("div",{className:"flex justify-center w-full p-[1rem]",children:e(y,{"data-testid":"face-scan-start-btn",disabled:l.isDisabled,className:"!w-[60px] !h-[35px] !py-0 !px-0",buttonText:d?.(l.label),postfixIcon:l?.icon,buttonFunc:l.onClick})})]}):e("div",{className:"text-center common-ui-main p-[16px] w-full h-full",style:{background:u?.style?.base?.backgroundColor},children:t("div",{className:"w-full",children:[e(g,{noTitle:!0}),e("h3",{className:"mb-[0.5rem] mt-[0]",style:{fontFamily:u?.style?.heading?.headingFontFamily||"SeriouslyNostalgic Fn",fontSize:u?.style?.heading?.headingFontSize||"32px",color:u?.style?.heading?.headingColor||"#000",fontWeight:u?.style?.heading?.headingFontWeight||"normal"},children:d?.(w[a])}),t("div",{className:"max-w-[400px] justify-center gap-1 mx-auto flex items-center",children:[e("div",{className:` w-[120px] overflow-hidden ${0===a?"opacity-100":"opacity-0 hidden"} `,children:e("video",{className:"h-full w-full object-contain border-none",muted:!0,loop:!0,autoPlay:!0,playsInline:!0,children:e("source",{src:i===v.Male?x.male.forward:x.female.forward,type:"video/mp4"})})}),e("div",{className:` w-[120px] overflow-hidden ${1===a?"opacity-100":"opacity-0 hidden"} `,children:e("video",{className:"h-full w-full object-contain border-none",muted:!0,loop:!0,autoPlay:!0,playsInline:!0,children:e("source",{src:i===v.Male?x.male.left:x.female.left,type:"video/mp4"})})}),e("div",{className:` w-[120px] overflow-hidden ${2===a?"opacity-100":"opacity-0 hidden"} `,children:e("video",{className:"h-full w-full object-contain border-none",muted:!0,loop:!0,autoPlay:!0,playsInline:!0,children:e("source",{src:i===v.Male?x.male.right:x.female.right,type:"video/mp4"})})}),e("div",{className:` w-[120px] overflow-hidden ${3===a?"opacity-100":"opacity-0 hidden"} `,children:e("video",{className:"h-full w-full object-contain border-none",muted:!0,loop:!0,autoPlay:!0,playsInline:!0,children:e("source",{src:i===v.Male?x.male.smile:x.female.smile,type:"video/mp4"})})})]})]})})}const Y=({webcamRef:n,canvasRef:r})=>{const{isError:o,isSuccess:c,showLoader:i,hasError:d,errorType:u,resetScanState:m,showGuideCard:f,scanStage:g,videoLoading:p,setVideoLoading:y,videoError:S,setVideoError:b,gender:v,getButtonText:w,isScanning:x,startScan:k,isModelLoaded:E,isLandscape:C,onRetry:M}=s(F),D=h();return o?e(X,{onRetry:M}):c?e("div",{className:"fixed z-[9] common-ui-main w-full h-full",style:{background:D?.style?.base?.backgroundColor},children:e(N,{url:D?.loader,loaderType:"black"})}):t(a,{children:[e("audio",{id:"audioElement",crossOrigin:"anonymous",preload:"auto",style:{position:"absolute",zIndex:-99999},src:void 0}),C&&!i&&!d&&e("div",{className:"fixed inset-0 z-[9999] common-ui-main",style:{background:"#fff"},children:e(I,{variant:"portrait",config:D})}),i&&!d&&e("div",{className:"fixed z-[9] common-ui-main w-full h-full",style:{background:D?.style?.base?.backgroundColor},children:e(N,{url:D?.loader,loaderType:"black"})}),e("div",{className:"h-full flex-col common-ui-main relative w-full flex justify-center items-center text-center rounded-t-[20px]",style:{background:D?.style?.base?.backgroundColor},children:e("div",{className:"flex-1 w-full max-w-md overflow-hidden",children:t("div",{className:"w-full h-full",children:[e("video",{ref:n,autoPlay:!0,playsInline:!0,muted:!0,width:l.width.ideal,height:l.height.ideal,className:"w-full h-full object-cover fixed left-0 top-0 z-0",style:{transform:"scaleX(-1)",visibility:C?"hidden":"visible"}}),e("canvas",{ref:r,width:l.width.ideal,height:l.height.ideal,style:{transform:"scaleX(-1)",opacity:"0"}})]})})}),!i&&d&&u===_.Camera&&e(I,{testId:"face-scan-camera-error-screen",config:D}),!i&&d&&u!==_.Camera&&e(X,{loading:i,onRetry:m}),f&&!d&&!i&&!C&&e(q,{open:!0,className:"face-scan-small camera-draw",anchor:"bottom",onClose:(e,t)=>{},disablePortal:!0,hideBackdrop:!0,children:e(Q,{stage:g,videoLoading:p,setVideoLoading:y,videoError:S,setVideoError:b,gender:v,btnConfig:{label:w(),onClick:x?m:k,isDisabled:i||!E,icon:e(x?B:a,{})}})})]})},Z=t=>{const{onScanSuccess:a,onScanError:s,onRetry:l,onScanStart:d,onCaptureComplete:f,onUploadStart:h,onUploadEnd:g,onMeasurementSocketStart:y,onMeasurementSocketClose:S,config:b,isError:v,isSuccess:w}=t,x=t.userDetails??{email:"",gender:"male",deviceFocalLength:0,shopDomain:"",bodyScanId:"",callbackUrl:null},N=t.token??"",I=n(null),B=n(null),q=n(null),J=n([]),G=n(null),H=n(null),X=n(0),Q=n(null),[Z,ee]=r(!1),[te,ae]=r(!1),[ne,re]=r(!1),[oe,ce]=r(!0),[ie,se]=r(!1),[le,de]=r(!1),[ue,me]=r(!1),[fe,he]=r(null),[ge,pe]=r(k()),ye=o(()=>E(N),[N]),{isLandscape:Se}=C(),{email:be,gender:ve,deviceFocalLength:we,shopDomain:xe,callbackUrl:Fe,bodyScanId:Ne}=x,[Ie,_e]=r([]),[ke,Ee]=r(M),Ce=o(()=>D(),[]),Me=T(Ie),De=P(Me);z();const Te=c(()=>{console.log("Stopping recording..."),cancelAnimationFrame(X.current),Q.current&&(Q.current.pause(),Q.current.srcObject=null,Q.current=null),q.current&&"recording"===q.current.state&&q.current.stop(),q.current=null},[]),Pe=async()=>{if(f?.(),J.current){if(0===J.current.length)return console.error("No video data recorded"),he(_.Scan),me(!0),void ee(!1);h?.(),ee(!0);const e=new File(J.current,`${ge}.${De}`,{type:Me}),t=H.current??await W(e),a=e.size,n=(a/1048576).toFixed(2),r=Math.round(a/1e4),o={video_size_mb:parseFloat(n),video_size_bytes:a,video_fps:t||0,blob_count:J.current.length,estimated_duration_seconds:r},c=[{gender:ve},{face_scan_id:ge},{focal_length:`${we}`},{customer_store_url:xe},{scan_type:"face_scan"},{body_scan_id:Ne}];Fe&&c.push({callback_url:Fe}),A({eventName:`${xe}/face_scan_meta_data`,faceScanId:ge,email:be,data:JSON.stringify({metaData:c,videoData:o})});const i=Date.now();A({eventName:`${xe}/face_scan_upload_start`,faceScanId:ge,email:be,startTime:i});try{const t=await ye.fileUpload.faceScanFileUploader({file:e,arrayMetaData:c,objectKey:ge,email:be,contentType:e.type}),a=Date.now();A({eventName:`${xe}/face_scan_upload_complete`,faceScanId:ge,email:be,completionTime:a,uploadDuration:a-i}),g?.(),console.log("✅ Upload successful",t),ye.measurement.handlFaceScaneSocket({onPreopen:()=>{y?.(),U({eventName:`${xe}/webSocket`,faceScanID:ge,connection:"pre_open",type:"faceScan_recommendation",email:be})},faceScanId:ge,onOpen:()=>{U({eventName:`${xe}/webSocket`,faceScanID:ge,connection:"open",type:"faceScan_recommendation",email:be}),console.log("websocket connect open")},onError:e=>{U({eventName:`${xe}/webSocket`,faceScanID:ge,connection:"error",type:"faceScan_recommendation",email:be}),Be(e)},onSuccess:e=>{U({eventName:`${xe}/webSocket`,faceScanID:ge,connection:"success",type:"faceScan_recommendation",email:be}),qe(e)},onClose:()=>{S?.(),console.log("websocket connect close"),U({eventName:`${xe}/webSocket`,faceScanID:ge,connection:"close",type:"faceScan_recommendation",email:be})}})}catch(e){g?.(),Be(e)}}},ze=c(()=>{const e=I.current?.srcObject;if(!e)return;const t=e.getVideoTracks()[0].getSettings(),{width:a=1280,height:n=720}=t,r=document.createElement("canvas"),o=r.getContext("2d");a>n?(r.width=n,r.height=a):(r.width=a,r.height=n);const c=document.createElement("video");c.srcObject=e,c.muted=!0,c.playsInline=!0,c.play(),Q.current=c;const i=()=>{a>n?(o?.save(),o?.translate(r.width,0),o?.rotate(Math.PI/2),o?.drawImage(c,0,0,n,a),o?.restore()):o?.drawImage(c,0,0,a,n),X.current=requestAnimationFrame(i)};X.current=requestAnimationFrame(i);const s=t.frameRate??10;H.current=s;const l=r.captureStream(s),d={videoBitsPerSecond:15e5};let u;Ie.length>0&&(d.mimeType=Ie[0]);try{u=new MediaRecorder(l,d)}catch(e){return console.error("MediaRecorder init failed:",e),he(_.Scan),me(!0),void ee(!1)}J.current=[],u.ondataavailable=e=>{e?.data&&e.data.size>0&&J.current&&J.current.push(e.data)},u.onstop=()=>{console.log("Recording stopped, total blobs:",J?.current?.length),Pe()},u.start(100),q.current=u,console.log("Recording started successfully (portrait normalized)")},[Ie,Pe]),{faceScanDetector:Re,scanStage:Le,setScanStage:$e,resetScan:je,isModelLoaded:Ve,startScanSequence:Oe}=K({faceScanId:ge,shopDomain:xe,isError:v,isSuccess:w,onScanComplete:()=>{Te()},onModelReady:()=>{ae(!0)},onStartRecording:()=>{console.log("Stage 0 completed - starting recording for stages 1-3"),ze()}}),We=c(()=>{Ve&&(d?.(),$e(0),u.playAudio(`${m}face-scan-vos/Face-forward.mp3`),setTimeout(()=>{re(!0),setTimeout(()=>{Oe()},200)},200))},[$e,re,Oe,Ve,d]),Ae=c(()=>{re(!1),ce(!0),Te(),je(),l?.(),J.current=[],H.current=null,q.current&&(q.current=null),me(!1),he(null),$e(-1),pe(k()),I.current&&G.current&&(I.current.srcObject=G.current,console.log("Camera stream restored after reset"))},[$e,re,ce,Te,je,pe]),Ue=n(!1);i(()=>{!Se||Ue.current||Z||v||w||ue||(u.stopAudio(),q.current&&(q.current.onstop=null,"recording"===q.current.state&&q.current.stop(),q.current=null),J.current=[],H.current=null,Ae()),Ue.current=Se},[Se,Z,v,w,ue,Ae]);const Be=e=>{console.log(e,"ws error"),s?.(e),he(_.Scan),me(!0),ee(!1),ce(!1),A({eventName:`${xe}/faceScan`,faceScanId:ge,status:"failed",email:be,data:JSON.stringify(e)})},qe=e=>{console.log(e,"ws success"),e&&"intermediate"===e?.resultType&&A({eventName:`${xe}/faceScan_success/intermediate`,faceScanId:ge,status:"success",email:be,data:JSON.stringify(e)}),a?.(e)};i(()=>{if(!v&&!w)return navigator.mediaDevices.getUserMedia&&navigator.mediaDevices.getUserMedia({video:ke}).then(e=>{G.current=e,I.current&&(I.current.srcObject=e)}).catch(e=>{if(console.error("Error accessing webcam:",e),ke===M)return void Ee(R);const t=["NotAllowedError","PermissionDeniedError","NotFoundError","DevicesNotFoundError","NotReadableError","TrackStartError"].includes(e?.name);he(t?_.Camera:_.Scan),me(!0)}),()=>{G.current&&G.current.getTracks().forEach(e=>e.stop())}},[v,w,ke]),i(()=>{if(!te||!ne)return;const e=setInterval(()=>{Re(I,B)},500);return()=>clearInterval(e)},[Re,te,ne]);return console.log("Model ready:",te,"Has error:",ue,"Is scanning:",ne,"showLoader",Z),i(()=>{const e=L(Ce,$);_e(e)},[Ce]),i(()=>{$e(-1)},[]),e("div",{"data-face-scan-stage":Le,children:e(j,{children:e(V,{config:b,children:e(F.Provider,{value:{isError:v,isSuccess:w,showLoader:Z,hasError:ue,errorType:fe,resetScanState:Ae,showGuideCard:oe,scanStage:Le,videoLoading:ie,setVideoLoading:se,videoError:le,setVideoError:de,gender:ve,getButtonText:()=>ne?p.reset:Ve?p.start:p.loading,isScanning:ne,startScan:We,isModelLoaded:Ve,isLandscape:Se,onRetry:l},children:e(O,{children:e(Y,{webcamRef:I,canvasRef:B})})})})})})};export{Z as F,H as p};
2
- //# sourceMappingURL=FaceScan-DKP93c3l.js.map
@@ -1,2 +0,0 @@
1
- "use strict";var e=require("react/jsx-runtime"),t=require("react"),a=require("./Modal-DU2Jymve.js"),n=require("lucide-react"),r=require("@mui/material");let o=null,s=!1;const c=async()=>{if("undefined"==typeof window)return null;if(o)return o;if(s)for(;s;)if(await new Promise(e=>setTimeout(e,100)),o)return o;s=!0;try{const[e,t]=await Promise.all([import("@tensorflow/tfjs"),Promise.resolve().then(function(){return require("./pose-detection.esm-D08ZA0zl.js")})]);await e.setBackend("webgl"),await e.ready();const n=await t.createDetector(t.SupportedModels.BlazePose,{runtime:"tfjs",modelType:"full"}),r=document.createElement("canvas");r.width="number"==typeof a.videoConstraints.width?a.videoConstraints.width:a.videoConstraints.width.ideal??a.videoConstraints.width.max??1280,r.height="number"==typeof a.videoConstraints.height?a.videoConstraints.height:a.videoConstraints.height.ideal??a.videoConstraints.height.max??720;const s=r.getContext("2d");if(s){s.fillStyle="black",s.fillRect(0,0,r.width,r.height);try{await n.estimatePoses(r)}catch(e){console.warn("Warmup frame failed (non-fatal):",e)}}return o=n,n}catch(e){return console.error("Failed to preload detector:",e),null}finally{s=!1}};function i({faceScanId:e,onValidPose:n,onScanComplete:r,onModelReady:o,onStartRecording:s,shopDomain:i,isError:l,isSuccess:d}){const u=t.useRef(null),[f,m]=t.useState(0),[g,h]=t.useState(0),[p,y]=t.useState(!1),[S,x]=t.useState(!1),v=t.useRef(!1),b=t.useRef(null),w=t.useRef(null),F=t.useRef(f),C=t.useRef(g),j=t.useRef([]),E=t.useRef(""),N=t.useRef(0),_=t.useRef(!1),T=t.useRef(0),k="undefined"!=typeof navigator&&(/iPad|iPhone|iPod/.test(navigator.userAgent)||"MacIntel"===navigator.platform&&navigator.maxTouchPoints>1),R=t.useMemo(()=>["Face front","Turn head fully left","Turn head fully right","Smile facing front"],[]),I=t.useMemo(()=>function(e,t){let a;return(...n)=>{a&&clearTimeout(a),a=setTimeout(()=>e(...n),t)}}(e=>{a.posthog.capture(`${i}/face_scan_pose_detection`,e)},4e3),[i]),M=t.useCallback((t,a,n,r,o,s)=>{const c=Date.now();if(!(c-T.current<4e3)){T.current=c;try{const c=t[0]||[0,0,0],i=t[2]||[0,0,0],l=t[5]||[0,0,0],d=t[9]||[0,0,0],u=t[10]||[0,0,0],f=t.map(e=>e[2]).filter(e=>e>0),m=f.length>0?f.reduce((e,t)=>e+t,0)/f.length:0,g=a.map(e=>e[2]).filter(e=>e>0),h=g.length>0?g.reduce((e,t)=>e+t,0)/g.length:0,p=Math.abs(i[0]-l[0]),y=c[0]-l[0],S=i[0]-c[0];let x="frontal";1===n?x="left":2===n?x="right":3===n&&(x="frontal_smile");const v={faceScanId:e,stage:n,timestamp:(new Date).toISOString(),data:JSON.stringify({headValid:r,bodyInvalid:o,consecutiveValid:s,avgFaceScore:parseFloat(m.toFixed(3)),avgBodyScore:parseFloat(h.toFixed(3)),faceKeypointsDetected:f.length,bodyKeypointsDetected:g.length,eyeDistance:parseFloat(p.toFixed(2)),noseToRightRatio:parseFloat((y/p).toFixed(3)),noseToLeftRatio:parseFloat((S/p).toFixed(3)),noseScore:parseFloat(c[2].toFixed(3)),leftEyeScore:parseFloat(i[2].toFixed(3)),rightEyeScore:parseFloat(l[2].toFixed(3)),leftMouthScore:parseFloat(d[2].toFixed(3)),rightMouthScore:parseFloat(u[2].toFixed(3)),expectedPosition:x})};I(v)}catch(e){console.warn("Failed to track pose detection:",e)}}},[e,I]),P=()=>{a.posthog.capture(`${i}/face_scan_detection_started`,{faceScanId:e,stage:F.current,timestamp:(new Date).toISOString(),stageName:R[F.current]}),setTimeout(()=>{x(!0)},1500)};return t.useEffect(()=>{if(!l&&!d)return(async()=>{if("undefined"!=typeof window)try{console.log("Initializing Face Scan...");const e=await c();e&&(u.current=e,console.log("Face scan model loaded successfully"),y(!0),o?.())}catch(e){console.error("Error initializing face scan:",e)}})(),()=>{(async()=>{try{y(!1)}catch(e){console.error("Error disposing resources:",e)}finally{m(0),h(0),F.current=0,C.current=0,j.current=[]}})()}},[l,d]),t.useEffect(()=>{F.current=f},[f]),t.useEffect(()=>{C.current=g},[g]),{faceScanDetector:async(t,o)=>{if(u.current&&t.current&&p&&S&&!(t.current.readyState<2||v.current)){v.current=!0;try{const c=t.current.videoWidth||720,l=t.current.videoHeight||1280;b.current||(b.current=document.createElement("canvas"),b.current.width=c,b.current.height=l);const d=b.current.getContext("2d");d&&d.drawImage(t.current,0,0,c,l);const f=await u.current.estimatePoses(d?b.current:t.current);if(f.length>0){const t=[],c=[];if(f[0].keypoints.forEach((e,a)=>{const n=e.score??0,r=[e.x??-1,e.y??-1,n];a<=10?t.push(r):c.push(r)}),o?.current){const e=o.current.getContext("2d"),{width:t,height:a}=o.current;if(e){e.clearRect(0,0,t,a);const n=Math.min(C.current/2,1),r=.35*a;e.beginPath(),e.strokeStyle="#00ff00",e.lineWidth=6,e.arc(t/2,a/2,r+10,-Math.PI/2,-Math.PI/2+2*n*Math.PI),e.stroke()}}const l=((e,t)=>{if(!t[0]||!t[2]||!t[5]||t[0][2]<.2||t[2][2]<.2||t[5][2]<.2)return!1;const a=.5*(t[10][1]+t[9][1])-.5*(t[5][1]+t[2][1]),n=(.5*(t[10][1]+t[9][1])-t[0][1])/a,r=n>.7||n<.3,o=Math.abs(t[2][1]-t[5][1])<.5*a&&Math.abs(t[9][1]-t[10][1])<.5*a,s=t[2][0]-t[5][0],c=t[0][0]-t[5][0],i=c>.4*s&&c<.6*s,l=c>.85*s,d=t[2][0]-t[0][0]>.85*s;switch(e){case 0:case 3:return!r&&o&&i;case 1:return!r&&o&&l;case 2:return!r&&o&&d;default:return!1}})(F.current,t),d=c.slice(2).filter(e=>e[2]>.7).length<=2;j.current.push(l&&d),j.current.length>10&&j.current.shift();if(j.current.filter(Boolean).length>=2){const e=C.current+1;h(e)}else h(Math.max(0,C.current-1));if(C.current>=2){n?.();const t=F.current+1;h(0),j.current=[],m(t),x(!1),(async()=>{if(await a.speechService.playAudio(`${a.voiceOverAssetsPath}face-scan-vos/Sound-effect.mp3`),a.posthog.capture(`${i}/face_scan_detection_stage_completed`,{faceScanId:e,completedStage:F.current,nextStage:t,timestamp:(new Date).toISOString(),totalStages:4,stageName:R[F.current]}),1===t&&s&&s(),t>=4)r?.();else{let e=null;switch(t){case 1:e="Left.mp3";break;case 2:e="Right.mp3";break;case 3:e="Smile.mp3"}e&&await a.speechService.playAudio(`${a.voiceOverAssetsPath}face-scan-vos/${e}`),P()}})()}M(t,c,F.current,l,d,C.current)}}catch(e){console.error("Pose detection error:",e)}finally{v.current=!1}}},scanStage:f,setScanStage:m,consecutiveValid:g,isModelLoaded:p,resetScan:()=>{a.posthog.capture(`${i}/face_scan_reset`,{faceScanId:e,stage:F.current,timestamp:(new Date).toISOString(),stageName:R[F.current],consecutiveValid:C.current}),m(0),h(0),x(!1),F.current=0,C.current=0,j.current=[],E.current="",N.current=0,_.current=!1,w.current&&(speechSynthesis.cancel(),w.current=null)},enableVoiceCommands:()=>{if(_.current=!0,"undefined"!=typeof window&&k&&"speechSynthesis"in window){const e=new SpeechSynthesisUtterance("");e.volume=0,speechSynthesis.speak(e)}},startScanSequence:P,isScanningActive:S}}function l({onRetry:r,loading:o}){const{translate:s}=t.useContext(a.LanguageContext)||{},c=a.useConfig();return e.jsx("div",{"data-testid":"face-scan-error-screen",className:"fixed common-ui-main top-[0] left-[0] z-[999] flex justify-center items-center w-full h-full",style:{background:c?.style?.base?.backgroundColor},children:e.jsxs("div",{className:"flex flex-col w-full items-center p-[1rem] rounded-lg ",children:[e.jsx(a.Header,{noTitle:!0}),e.jsxs("div",{className:"flex flex-col items-center w-full",children:[e.jsx("h2",{className:"text-xl my-[0] font-semibold text-gray-800 ",style:{fontFamily:c?.style?.heading?.headingFontFamily||"SeriouslyNostalgic Fn",fontSize:c?.style?.heading?.headingFontSize||"32px",color:c?.style?.heading?.headingColor||"#000",fontWeight:c?.style?.heading?.headingFontWeight||"normal"},children:s?.(a.LanguageKeys.scanFailed)}),e.jsx("p",{className:"mb-[1.5rem]",style:{fontFamily:c?.style?.subheading?.subheadingFontFamily||"'Inter', sans-serif",fontSize:c?.style?.subheading?.subheadingFontSize||"14px",color:c?.style?.subheading?.subheadingColor||"#4b5563",fontWeight:c?.style?.subheading?.subheadingFontWeight||"normal"},children:s?.(a.LanguageKeys.clickToResetScan)}),e.jsx(a.SpecificButton,{"data-testid":"face-scan-retry-btn",disabled:o,className:"w-full h-[45px] shadow-[0px_1px_2px_0px_#00000040] text-[16px]",buttonText:s?.(a.LanguageKeys.resetScan),postfixIcon:e.jsx(n.ArrowRight,{}),buttonFunc:()=>r?.()})]})]})})}function d({stage:n,videoLoading:r,setVideoLoading:o,videoError:s,setVideoError:c,gender:i,btnConfig:l}){const{translate:d}=t.useContext(a.LanguageContext)||{},u=a.useConfig();return-1===n?e.jsxs("div",{"data-testid":"face-scan-guide",className:"text-center common-ui-main p-[16px] w-full h-full",style:{background:u?.style?.base?.backgroundColor},children:[e.jsxs("div",{className:"w-full",children:[e.jsx(a.Header,{noTitle:!0}),e.jsx("h2",{className:"my-[0]",style:{fontFamily:u?.style?.heading?.headingFontFamily||"SeriouslyNostalgic Fn",fontSize:u?.style?.heading?.headingFontSize||"32px",color:u?.style?.heading?.headingColor||"#000",fontWeight:u?.style?.heading?.headingFontWeight||"normal"},children:d?.(a.LanguageKeys.faceVisible)}),r&&e.jsx("div",{className:"mb-4 flex items-center justify-center",style:{fontFamily:u?.style?.subheading?.subheadingFontFamily||"'Inter', sans-serif",fontSize:u?.style?.subheading?.subheadingFontSize||"14px",color:u?.style?.subheading?.subheadingColor||"#4b5563",fontWeight:u?.style?.subheading?.subheadingFontWeight||"normal"},children:d?.(a.LanguageKeys.loadingVideo)}),s&&e.jsx("div",{className:"mb-4 text-red-600",style:{fontFamily:u?.style?.subheading?.subheadingFontFamily||"'Inter', sans-serif",fontSize:u?.style?.subheading?.subheadingFontSize||"14px",color:"#ff0000",fontWeight:u?.style?.subheading?.subheadingFontWeight||"normal"},children:d?.(a.LanguageKeys.videoLoadFailed)}),!s&&e.jsx("div",{className:" w-[100px] mx-auto",children:e.jsx("video",{src:i===a.GenderType.Male?a.maleGlassesOffVideo:a.glassesOffVideo,autoPlay:!0,loop:!0,controls:!1,muted:!0,playsInline:!0,className:"h-full w-full object-contain border-none",onCanPlay:()=>o(!1),onLoadStart:()=>o(!0),onError:()=>c(!0),"aria-label":"Instructional video: Please remove your glasses before starting the scan."})})]}),e.jsx("div",{className:"flex justify-center w-full p-[1rem]",children:e.jsx(a.SpecificButton,{"data-testid":"face-scan-start-btn",disabled:l.isDisabled,className:"!w-[60px] !h-[35px] !py-0 !px-0",buttonText:d?.(l.label),postfixIcon:l?.icon,buttonFunc:l.onClick})})]}):e.jsx("div",{className:"text-center common-ui-main p-[16px] w-full h-full",style:{background:u?.style?.base?.backgroundColor},children:e.jsxs("div",{className:"w-full",children:[e.jsx(a.Header,{noTitle:!0}),e.jsx("h3",{className:"mb-[0.5rem] mt-[0]",style:{fontFamily:u?.style?.heading?.headingFontFamily||"SeriouslyNostalgic Fn",fontSize:u?.style?.heading?.headingFontSize||"32px",color:u?.style?.heading?.headingColor||"#000",fontWeight:u?.style?.heading?.headingFontWeight||"normal"},children:d?.(a.directionMessages[n])}),e.jsxs("div",{className:"max-w-[400px] justify-center gap-1 mx-auto flex items-center",children:[e.jsx("div",{className:` w-[120px] overflow-hidden ${0===n?"opacity-100":"opacity-0 hidden"} `,children:e.jsx("video",{className:"h-full w-full object-contain border-none",muted:!0,loop:!0,autoPlay:!0,playsInline:!0,children:e.jsx("source",{src:i===a.GenderType.Male?a.FACE_SCAN_HEADSHOT.male.forward:a.FACE_SCAN_HEADSHOT.female.forward,type:"video/mp4"})})}),e.jsx("div",{className:` w-[120px] overflow-hidden ${1===n?"opacity-100":"opacity-0 hidden"} `,children:e.jsx("video",{className:"h-full w-full object-contain border-none",muted:!0,loop:!0,autoPlay:!0,playsInline:!0,children:e.jsx("source",{src:i===a.GenderType.Male?a.FACE_SCAN_HEADSHOT.male.left:a.FACE_SCAN_HEADSHOT.female.left,type:"video/mp4"})})}),e.jsx("div",{className:` w-[120px] overflow-hidden ${2===n?"opacity-100":"opacity-0 hidden"} `,children:e.jsx("video",{className:"h-full w-full object-contain border-none",muted:!0,loop:!0,autoPlay:!0,playsInline:!0,children:e.jsx("source",{src:i===a.GenderType.Male?a.FACE_SCAN_HEADSHOT.male.right:a.FACE_SCAN_HEADSHOT.female.right,type:"video/mp4"})})}),e.jsx("div",{className:` w-[120px] overflow-hidden ${3===n?"opacity-100":"opacity-0 hidden"} `,children:e.jsx("video",{className:"h-full w-full object-contain border-none",muted:!0,loop:!0,autoPlay:!0,playsInline:!0,children:e.jsx("source",{src:i===a.GenderType.Male?a.FACE_SCAN_HEADSHOT.male.smile:a.FACE_SCAN_HEADSHOT.female.smile,type:"video/mp4"})})})]})]})})}const u=({webcamRef:o,canvasRef:s})=>{const{isError:c,isSuccess:i,showLoader:u,hasError:f,errorType:m,resetScanState:g,showGuideCard:h,scanStage:p,videoLoading:y,setVideoLoading:S,videoError:x,setVideoError:v,gender:b,getButtonText:w,isScanning:F,startScan:C,isModelLoaded:j,isLandscape:E,onRetry:N}=t.useContext(a.ParamsContext),_=a.useConfig();return c?e.jsx(l,{onRetry:N}):i?e.jsx("div",{className:"fixed z-[9] common-ui-main w-full h-full",style:{background:_?.style?.base?.backgroundColor},children:e.jsx(a.LoadingScreen,{url:_?.loader,loaderType:"black"})}):e.jsxs(e.Fragment,{children:[e.jsx("audio",{id:"audioElement",crossOrigin:"anonymous",preload:"auto",style:{position:"absolute",zIndex:-99999},src:void 0}),E&&!u&&!f&&e.jsx("div",{className:"fixed inset-0 z-[9999] common-ui-main",style:{background:"#fff"},children:e.jsx(a.Modal,{variant:"portrait",config:_})}),u&&!f&&e.jsx("div",{className:"fixed z-[9] common-ui-main w-full h-full",style:{background:_?.style?.base?.backgroundColor},children:e.jsx(a.LoadingScreen,{url:_?.loader,loaderType:"black"})}),e.jsx("div",{className:"h-full flex-col common-ui-main relative w-full flex justify-center items-center text-center rounded-t-[20px]",style:{background:_?.style?.base?.backgroundColor},children:e.jsx("div",{className:"flex-1 w-full max-w-md overflow-hidden",children:e.jsxs("div",{className:"w-full h-full",children:[e.jsx("video",{ref:o,autoPlay:!0,playsInline:!0,muted:!0,width:a.videoConstraints.width.ideal,height:a.videoConstraints.height.ideal,className:"w-full h-full object-cover fixed left-0 top-0 z-0",style:{transform:"scaleX(-1)",visibility:E?"hidden":"visible"}}),e.jsx("canvas",{ref:s,width:a.videoConstraints.width.ideal,height:a.videoConstraints.height.ideal,style:{transform:"scaleX(-1)",opacity:"0"}})]})})}),!u&&f&&m===a.FaceScanErrorType.Camera&&e.jsx(a.Modal,{testId:"face-scan-camera-error-screen",config:_}),!u&&f&&m!==a.FaceScanErrorType.Camera&&e.jsx(l,{loading:u,onRetry:g}),h&&!f&&!u&&!E&&e.jsx(r.Drawer,{open:!0,className:"face-scan-small camera-draw",anchor:"bottom",onClose:(e,t)=>{},disablePortal:!0,hideBackdrop:!0,children:e.jsx(d,{stage:p,videoLoading:y,setVideoLoading:S,videoError:x,setVideoError:v,gender:b,btnConfig:{label:w(),onClick:F?g:C,isDisabled:u||!j,icon:F?e.jsx(n.ArrowRight,{}):e.jsx(e.Fragment,{})}})})]})};exports.FaceScan=n=>{const{onScanSuccess:r,onScanError:o,onRetry:s,onScanStart:c,onCaptureComplete:l,onUploadStart:d,onUploadEnd:f,onMeasurementSocketStart:m,onMeasurementSocketClose:g,config:h,isError:p,isSuccess:y}=n,S=n.userDetails??{email:"",gender:"male",deviceFocalLength:0,shopDomain:"",bodyScanId:"",callbackUrl:null},x=n.token??"",v=t.useRef(null),b=t.useRef(null),w=t.useRef(null),F=t.useRef([]),C=t.useRef(null),j=t.useRef(null),E=t.useRef(0),N=t.useRef(null),[_,T]=t.useState(!1),[k,R]=t.useState(!1),[I,M]=t.useState(!1),[P,D]=t.useState(!0),[A,L]=t.useState(!1),[O,z]=t.useState(!1),[$,H]=t.useState(!1),[V,W]=t.useState(null),[K,U]=t.useState(a.generateUuid()),q=t.useMemo(()=>a.getSwanService(x),[x]),{isLandscape:B}=a.usePortraitLock(),{email:G,gender:J,deviceFocalLength:X,shopDomain:Q,callbackUrl:Y,bodyScanId:Z}=S,[ee,te]=t.useState([]),[ae,ne]=t.useState(a.videoConstraintsExact),re=t.useMemo(()=>a.getPreferredMediaRecorderTypes(),[]),oe=a.getRecordingMimeType(ee),se=a.getRecordingExtension(oe);a.usePosthogPageview();const ce=t.useCallback(()=>{console.log("Stopping recording..."),cancelAnimationFrame(E.current),N.current&&(N.current.pause(),N.current.srcObject=null,N.current=null),w.current&&"recording"===w.current.state&&w.current.stop(),w.current=null},[]),ie=async()=>{if(l?.(),F.current){if(0===F.current.length)return console.error("No video data recorded"),W(a.FaceScanErrorType.Scan),H(!0),void T(!1);d?.(),T(!0);const e=new File(F.current,`${K}.${se}`,{type:oe}),t=j.current??await a.getVideoFPS(e),n=e.size,r=(n/1048576).toFixed(2),o=Math.round(n/1e4),s={video_size_mb:parseFloat(r),video_size_bytes:n,video_fps:t||0,blob_count:F.current.length,estimated_duration_seconds:o},c=[{gender:J},{face_scan_id:K},{focal_length:`${X}`},{customer_store_url:Q},{scan_type:"face_scan"},{body_scan_id:Z}];Y&&c.push({callback_url:Y}),a.handleScanTimeCapture({eventName:`${Q}/face_scan_meta_data`,faceScanId:K,email:G,data:JSON.stringify({metaData:c,videoData:s})});const i=Date.now();a.handleScanTimeCapture({eventName:`${Q}/face_scan_upload_start`,faceScanId:K,email:G,startTime:i});try{const t=await q.fileUpload.faceScanFileUploader({file:e,arrayMetaData:c,objectKey:K,email:G,contentType:e.type}),n=Date.now(),r=n-i;a.handleScanTimeCapture({eventName:`${Q}/face_scan_upload_complete`,faceScanId:K,email:G,completionTime:n,uploadDuration:r}),f?.(),console.log("✅ Upload successful",t);let o=!1;q.measurement.handlFaceScaneSocket({onPreopen:()=>{m?.(),a.handleWebSocketCapture({eventName:`${Q}/webSocket`,faceScanID:K,connection:"pre_open",type:"faceScan_recommendation",email:G})},faceScanId:K,onOpen:()=>{a.handleWebSocketCapture({eventName:`${Q}/webSocket`,faceScanID:K,connection:"open",type:"faceScan_recommendation",email:G})},onError:e=>{o=!0,a.handleWebSocketCapture({eventName:`${Q}/webSocket`,faceScanID:K,connection:"error",type:"faceScan_recommendation",email:G}),xe(e)},onSuccess:e=>{o=!0,a.handleWebSocketCapture({eventName:`${Q}/webSocket`,faceScanID:K,connection:"success",type:"faceScan_recommendation",email:G}),ve(e)},onClose:()=>{g?.(),a.handleWebSocketCapture({eventName:`${Q}/webSocket`,faceScanID:K,connection:"close",type:"faceScan_recommendation",email:G}),o||xe({message:"Connection closed. Please try again."})}})}catch(e){f?.(),xe(e)}}},le=t.useCallback(()=>{const e=v.current?.srcObject;if(!e)return;const t=e.getVideoTracks()[0].getSettings(),{width:n=1280,height:r=720}=t,o=document.createElement("canvas"),s=o.getContext("2d");n>r?(o.width=r,o.height=n):(o.width=n,o.height=r);const c=document.createElement("video");c.srcObject=e,c.muted=!0,c.playsInline=!0,c.play(),N.current=c;const i=()=>{n>r?(s?.save(),s?.translate(o.width,0),s?.rotate(Math.PI/2),s?.drawImage(c,0,0,r,n),s?.restore()):s?.drawImage(c,0,0,n,r),E.current=requestAnimationFrame(i)};E.current=requestAnimationFrame(i);const l=t.frameRate??10;j.current=l;const d=o.captureStream(l),u={videoBitsPerSecond:15e5};let f;ee.length>0&&(u.mimeType=ee[0]);try{f=new MediaRecorder(d,u)}catch(e){return console.error("MediaRecorder init failed:",e),W(a.FaceScanErrorType.Scan),H(!0),void T(!1)}F.current=[],f.ondataavailable=e=>{e?.data&&e.data.size>0&&F.current&&F.current.push(e.data)},f.onstop=()=>{console.log("Recording stopped, total blobs:",F?.current?.length),ie()},f.start(100),w.current=f,console.log("Recording started successfully (portrait normalized)")},[ee,ie]),{faceScanDetector:de,scanStage:ue,setScanStage:fe,resetScan:me,isModelLoaded:ge,startScanSequence:he}=i({faceScanId:K,shopDomain:Q,isError:p,isSuccess:y,onScanComplete:()=>{ce()},onModelReady:()=>{R(!0)},onStartRecording:()=>{console.log("Stage 0 completed - starting recording for stages 1-3"),le()}}),pe=t.useCallback(()=>{ge&&(c?.(),fe(0),a.speechService.playAudio(`${a.voiceOverAssetsPath}face-scan-vos/Face-forward.mp3`),setTimeout(()=>{M(!0),setTimeout(()=>{he()},200)},200))},[fe,M,he,ge,c]),ye=t.useCallback(()=>{M(!1),D(!0),ce(),me(),s?.(),F.current=[],j.current=null,w.current&&(w.current=null),H(!1),W(null),fe(-1),U(a.generateUuid()),v.current&&C.current&&(v.current.srcObject=C.current,console.log("Camera stream restored after reset"))},[fe,M,D,ce,me,U]),Se=t.useRef(!1);t.useEffect(()=>{!B||Se.current||_||p||y||$||(a.speechService.stopAudio(),w.current&&(w.current.onstop=null,"recording"===w.current.state&&w.current.stop(),w.current=null),F.current=[],j.current=null,ye()),Se.current=B},[B,_,p,y,$,ye]);const xe=e=>{console.log(e,"ws error"),o?.(e),W(a.FaceScanErrorType.Scan),H(!0),T(!1),D(!1),a.handleScanTimeCapture({eventName:`${Q}/faceScan`,faceScanId:K,status:"failed",email:G,data:JSON.stringify(e)})},ve=e=>{console.log(e,"ws success"),e&&"intermediate"===e?.resultType&&a.handleScanTimeCapture({eventName:`${Q}/faceScan_success/intermediate`,faceScanId:K,status:"success",email:G,data:JSON.stringify(e)}),r?.(e)};t.useEffect(()=>{if(!p&&!y)return navigator.mediaDevices.getUserMedia&&navigator.mediaDevices.getUserMedia({video:ae}).then(e=>{C.current=e,v.current&&(v.current.srcObject=e)}).catch(e=>{if(console.error("Error accessing webcam:",e),ae===a.videoConstraintsExact)return void ne(a.videoConstraintsFallback);const t=["NotAllowedError","PermissionDeniedError","NotFoundError","DevicesNotFoundError","NotReadableError","TrackStartError"].includes(e?.name);W(t?a.FaceScanErrorType.Camera:a.FaceScanErrorType.Scan),H(!0)}),()=>{C.current&&C.current.getTracks().forEach(e=>e.stop())}},[p,y,ae]),t.useEffect(()=>{if(!k||!I)return;const e=setInterval(()=>{de(v,b)},500);return()=>clearInterval(e)},[de,k,I]);return console.log("Model ready:",k,"Has error:",$,"Is scanning:",I,"showLoader",_),t.useEffect(()=>{const e=a.getSupportedMediaRecorderTypes(re,a.videoTypes);te(e)},[re]),t.useEffect(()=>{fe(-1)},[]),e.jsx("div",{"data-face-scan-stage":ue,children:e.jsx(a.LanguageContextProvider,{children:e.jsx(a.ConfigProvider,{config:h,children:e.jsx(a.ParamsContext.Provider,{value:{isError:p,isSuccess:y,showLoader:_,hasError:$,errorType:V,resetScanState:ye,showGuideCard:P,scanStage:ue,videoLoading:A,setVideoLoading:L,videoError:O,setVideoError:z,gender:J,getButtonText:()=>I?a.LanguageKeys.reset:ge?a.LanguageKeys.start:a.LanguageKeys.loading,isScanning:I,startScan:pe,isModelLoaded:ge,isLandscape:B,onRetry:s},children:e.jsx(a.ShadowRoot,{children:e.jsx(u,{webcamRef:v,canvasRef:b})})})})})})},exports.preloadDetector=c;
2
- //# sourceMappingURL=FaceScan-DW6Ix1a1.js.map
@@ -1,2 +0,0 @@
1
- "use strict";var e=require("react/jsx-runtime"),t=require("react"),a=require("./Modal-4T_aWWPQ.js"),n=require("lucide-react"),r=require("@mui/material");let o=null,s=!1;const c=async()=>{if("undefined"==typeof window)return null;if(o)return o;if(s)for(;s;)if(await new Promise(e=>setTimeout(e,100)),o)return o;s=!0;try{const[e,t]=await Promise.all([import("@tensorflow/tfjs"),Promise.resolve().then(function(){return require("./pose-detection.esm-Bc8T4UAD.js")})]);await e.setBackend("webgl"),await e.ready();const n=await t.createDetector(t.SupportedModels.BlazePose,{runtime:"tfjs",modelType:"full"}),r=document.createElement("canvas");r.width="number"==typeof a.videoConstraints.width?a.videoConstraints.width:a.videoConstraints.width.ideal??a.videoConstraints.width.max??1280,r.height="number"==typeof a.videoConstraints.height?a.videoConstraints.height:a.videoConstraints.height.ideal??a.videoConstraints.height.max??720;const s=r.getContext("2d");if(s){s.fillStyle="black",s.fillRect(0,0,r.width,r.height);try{await n.estimatePoses(r)}catch(e){console.warn("Warmup frame failed (non-fatal):",e)}}return o=n,n}catch(e){return console.error("Failed to preload detector:",e),null}finally{s=!1}};function i({faceScanId:e,onValidPose:n,onScanComplete:r,onModelReady:o,onStartRecording:s,shopDomain:i,isError:l,isSuccess:d}){const u=t.useRef(null),[f,g]=t.useState(0),[h,m]=t.useState(0),[p,y]=t.useState(!1),[S,x]=t.useState(!1),v=t.useRef(!1),b=t.useRef(null),w=t.useRef(null),F=t.useRef(f),C=t.useRef(h),j=t.useRef([]),E=t.useRef(""),_=t.useRef(0),N=t.useRef(!1),T=t.useRef(0),k="undefined"!=typeof navigator&&(/iPad|iPhone|iPod/.test(navigator.userAgent)||"MacIntel"===navigator.platform&&navigator.maxTouchPoints>1),R=t.useMemo(()=>["Face front","Turn head fully left","Turn head fully right","Smile facing front"],[]),I=t.useMemo(()=>function(e,t){let a;return(...n)=>{a&&clearTimeout(a),a=setTimeout(()=>e(...n),t)}}(e=>{a.posthog.capture(`${i}/face_scan_pose_detection`,e)},4e3),[i]),D=t.useCallback((t,a,n,r,o,s)=>{const c=Date.now();if(!(c-T.current<4e3)){T.current=c;try{const c=t[0]||[0,0,0],i=t[2]||[0,0,0],l=t[5]||[0,0,0],d=t[9]||[0,0,0],u=t[10]||[0,0,0],f=t.map(e=>e[2]).filter(e=>e>0),g=f.length>0?f.reduce((e,t)=>e+t,0)/f.length:0,h=a.map(e=>e[2]).filter(e=>e>0),m=h.length>0?h.reduce((e,t)=>e+t,0)/h.length:0,p=Math.abs(i[0]-l[0]),y=c[0]-l[0],S=i[0]-c[0];let x="frontal";1===n?x="left":2===n?x="right":3===n&&(x="frontal_smile");const v={faceScanId:e,stage:n,timestamp:(new Date).toISOString(),data:JSON.stringify({headValid:r,bodyInvalid:o,consecutiveValid:s,avgFaceScore:parseFloat(g.toFixed(3)),avgBodyScore:parseFloat(m.toFixed(3)),faceKeypointsDetected:f.length,bodyKeypointsDetected:h.length,eyeDistance:parseFloat(p.toFixed(2)),noseToRightRatio:parseFloat((y/p).toFixed(3)),noseToLeftRatio:parseFloat((S/p).toFixed(3)),noseScore:parseFloat(c[2].toFixed(3)),leftEyeScore:parseFloat(i[2].toFixed(3)),rightEyeScore:parseFloat(l[2].toFixed(3)),leftMouthScore:parseFloat(d[2].toFixed(3)),rightMouthScore:parseFloat(u[2].toFixed(3)),expectedPosition:x})};I(v)}catch(e){console.warn("Failed to track pose detection:",e)}}},[e,I]),M=()=>{a.posthog.capture(`${i}/face_scan_detection_started`,{faceScanId:e,stage:F.current,timestamp:(new Date).toISOString(),stageName:R[F.current]}),setTimeout(()=>{x(!0)},1500)};return t.useEffect(()=>{if(!l&&!d)return(async()=>{if("undefined"!=typeof window)try{console.log("Initializing Face Scan...");const e=await c();e&&(u.current=e,console.log("Face scan model loaded successfully"),y(!0),o?.())}catch(e){console.error("Error initializing face scan:",e)}})(),()=>{(async()=>{try{y(!1)}catch(e){console.error("Error disposing resources:",e)}finally{g(0),m(0),F.current=0,C.current=0,j.current=[]}})()}},[l,d]),t.useEffect(()=>{F.current=f},[f]),t.useEffect(()=>{C.current=h},[h]),{faceScanDetector:async(t,o)=>{if(u.current&&t.current&&p&&S&&!(t.current.readyState<2||v.current)){v.current=!0;try{const c=t.current.videoWidth||720,l=t.current.videoHeight||1280;b.current||(b.current=document.createElement("canvas"),b.current.width=c,b.current.height=l);const d=b.current.getContext("2d");d&&d.drawImage(t.current,0,0,c,l);const f=await u.current.estimatePoses(d?b.current:t.current);if(f.length>0){const t=[],c=[];if(f[0].keypoints.forEach((e,a)=>{const n=e.score??0,r=[e.x??-1,e.y??-1,n];a<=10?t.push(r):c.push(r)}),o?.current){const e=o.current.getContext("2d"),{width:t,height:a}=o.current;if(e){e.clearRect(0,0,t,a);const n=Math.min(C.current/2,1),r=.35*a;e.beginPath(),e.strokeStyle="#00ff00",e.lineWidth=6,e.arc(t/2,a/2,r+10,-Math.PI/2,-Math.PI/2+2*n*Math.PI),e.stroke()}}const l=((e,t)=>{if(!t[0]||!t[2]||!t[5]||t[0][2]<.2||t[2][2]<.2||t[5][2]<.2)return!1;const a=.5*(t[10][1]+t[9][1])-.5*(t[5][1]+t[2][1]),n=(.5*(t[10][1]+t[9][1])-t[0][1])/a,r=n>.7||n<.3,o=Math.abs(t[2][1]-t[5][1])<.5*a&&Math.abs(t[9][1]-t[10][1])<.5*a,s=t[2][0]-t[5][0],c=t[0][0]-t[5][0],i=c>.4*s&&c<.6*s,l=c>.85*s,d=t[2][0]-t[0][0]>.85*s;switch(e){case 0:case 3:return!r&&o&&i;case 1:return!r&&o&&l;case 2:return!r&&o&&d;default:return!1}})(F.current,t),d=c.slice(2).filter(e=>e[2]>.7).length<=2;j.current.push(l&&d),j.current.length>10&&j.current.shift();if(j.current.filter(Boolean).length>=2){const e=C.current+1;m(e)}else m(Math.max(0,C.current-1));if(C.current>=2){n?.();const t=F.current+1;m(0),j.current=[],g(t),x(!1),(async()=>{if(await a.speechService.playAudio(`${a.voiceOverAssetsPath}face-scan-vos/Sound-effect.mp3`),a.posthog.capture(`${i}/face_scan_detection_stage_completed`,{faceScanId:e,completedStage:F.current,nextStage:t,timestamp:(new Date).toISOString(),totalStages:4,stageName:R[F.current]}),1===t&&s&&s(),t>=4)r?.();else{let e=null;switch(t){case 1:e="Left.mp3";break;case 2:e="Right.mp3";break;case 3:e="Smile.mp3"}e&&await a.speechService.playAudio(`${a.voiceOverAssetsPath}face-scan-vos/${e}`),M()}})()}D(t,c,F.current,l,d,C.current)}}catch(e){console.error("Pose detection error:",e)}finally{v.current=!1}}},scanStage:f,setScanStage:g,consecutiveValid:h,isModelLoaded:p,resetScan:()=>{a.posthog.capture(`${i}/face_scan_reset`,{faceScanId:e,stage:F.current,timestamp:(new Date).toISOString(),stageName:R[F.current],consecutiveValid:C.current}),g(0),m(0),x(!1),F.current=0,C.current=0,j.current=[],E.current="",_.current=0,N.current=!1,w.current&&(speechSynthesis.cancel(),w.current=null)},enableVoiceCommands:()=>{if(N.current=!0,"undefined"!=typeof window&&k&&"speechSynthesis"in window){const e=new SpeechSynthesisUtterance("");e.volume=0,speechSynthesis.speak(e)}},startScanSequence:M,isScanningActive:S}}function l({onRetry:r,loading:o}){const{translate:s}=t.useContext(a.LanguageContext)||{},c=a.useConfig();return e.jsx("div",{"data-testid":"face-scan-error-screen",className:"fixed common-ui-main top-[0] left-[0] z-[999] flex justify-center items-center w-full h-full",style:{background:c?.style?.base?.backgroundColor},children:e.jsxs("div",{className:"flex flex-col w-full items-center p-[1rem] rounded-lg ",children:[e.jsx(a.Header,{noTitle:!0}),e.jsxs("div",{className:"flex flex-col items-center w-full",children:[e.jsx("h2",{className:"text-xl font-semibold text-gray-800 ",style:{fontFamily:c?.style?.heading?.headingFontFamily||"SeriouslyNostalgic Fn",fontSize:c?.style?.heading?.headingFontSize||"32px",color:c?.style?.heading?.headingColor||"#000",fontWeight:c?.style?.heading?.headingFontWeight||"normal"},children:s?.(a.LanguageKeys.scanFailed)}),e.jsx("p",{className:"mb-[1.5rem]",style:{fontFamily:c?.style?.subheading?.subheadingFontFamily||"'Inter', sans-serif",fontSize:c?.style?.subheading?.subheadingFontSize||"14px",color:c?.style?.subheading?.subheadingColor||"#4b5563",fontWeight:c?.style?.subheading?.subheadingFontWeight||"normal"},children:s?.(a.LanguageKeys.clickToResetScan)}),e.jsx(a.SpecificButton,{"data-testid":"face-scan-retry-btn",disabled:o,className:"w-full h-[45px] shadow-[0px_1px_2px_0px_#00000040] text-[16px]",buttonText:s?.(a.LanguageKeys.resetScan),postfixIcon:e.jsx(n.ArrowRight,{}),buttonFunc:()=>r?.()})]})]})})}function d({stage:n,videoLoading:r,setVideoLoading:o,videoError:s,setVideoError:c,gender:i,btnConfig:l}){const{translate:d}=t.useContext(a.LanguageContext)||{},u=a.useConfig();return-1===n?e.jsxs("div",{"data-testid":"face-scan-guide",className:"text-center common-ui-main p-[16px] w-full h-full",style:{background:u?.style?.base?.backgroundColor},children:[e.jsxs("div",{className:"w-full",children:[e.jsx(a.Header,{noTitle:!0}),e.jsx("h2",{style:{fontFamily:u?.style?.heading?.headingFontFamily||"SeriouslyNostalgic Fn",fontSize:u?.style?.heading?.headingFontSize||"32px",color:u?.style?.heading?.headingColor||"#000",fontWeight:u?.style?.heading?.headingFontWeight||"normal"},children:d?.(a.LanguageKeys.faceVisible)}),r&&e.jsx("div",{className:"mb-4 flex items-center justify-center",style:{fontFamily:u?.style?.subheading?.subheadingFontFamily||"'Inter', sans-serif",fontSize:u?.style?.subheading?.subheadingFontSize||"14px",color:u?.style?.subheading?.subheadingColor||"#4b5563",fontWeight:u?.style?.subheading?.subheadingFontWeight||"normal"},children:d?.(a.LanguageKeys.loadingVideo)}),s&&e.jsx("div",{className:"mb-4 text-red-600",style:{fontFamily:u?.style?.subheading?.subheadingFontFamily||"'Inter', sans-serif",fontSize:u?.style?.subheading?.subheadingFontSize||"14px",color:"#ff0000",fontWeight:u?.style?.subheading?.subheadingFontWeight||"normal"},children:d?.(a.LanguageKeys.videoLoadFailed)}),!s&&e.jsx("div",{className:" w-[100px] mx-auto",children:e.jsx("video",{src:i===a.GenderType.Male?a.maleGlassesOffVideo:a.glassesOffVideo,autoPlay:!0,loop:!0,controls:!1,muted:!0,playsInline:!0,className:"h-full w-full object-contain border-none",onCanPlay:()=>o(!1),onLoadStart:()=>o(!0),onError:()=>c(!0),"aria-label":"Instructional video: Please remove your glasses before starting the scan."})})]}),e.jsx("div",{className:"flex justify-center w-full p-[1rem]",children:e.jsx(a.SpecificButton,{"data-testid":"face-scan-start-btn",disabled:l.isDisabled,className:"!w-[60px] !h-[35px] !py-0 !px-0",buttonText:d?.(l.label),postfixIcon:l?.icon,buttonFunc:l.onClick})})]}):e.jsx("div",{className:"text-center common-ui-main p-[16px] w-full h-full",style:{background:u?.style?.base?.backgroundColor},children:e.jsxs("div",{className:"w-full",children:[e.jsx(a.Header,{noTitle:!0}),e.jsx("h3",{className:"mb-[0.5rem]",style:{fontFamily:u?.style?.heading?.headingFontFamily||"SeriouslyNostalgic Fn",fontSize:u?.style?.heading?.headingFontSize||"32px",color:u?.style?.heading?.headingColor||"#000",fontWeight:u?.style?.heading?.headingFontWeight||"normal"},children:d?.(a.directionMessages[n])}),e.jsxs("div",{className:"max-w-[400px] justify-center gap-1 mx-auto flex items-center",children:[e.jsx("div",{className:` w-[120px] overflow-hidden ${0===n?"opacity-100":"opacity-0 hidden"} `,children:e.jsx("video",{className:"h-full w-full object-contain border-none",muted:!0,loop:!0,autoPlay:!0,playsInline:!0,children:e.jsx("source",{src:i===a.GenderType.Male?a.FACE_SCAN_HEADSHOT.male.forward:a.FACE_SCAN_HEADSHOT.female.forward,type:"video/mp4"})})}),e.jsx("div",{className:` w-[120px] overflow-hidden ${1===n?"opacity-100":"opacity-0 hidden"} `,children:e.jsx("video",{className:"h-full w-full object-contain border-none",muted:!0,loop:!0,autoPlay:!0,playsInline:!0,children:e.jsx("source",{src:i===a.GenderType.Male?a.FACE_SCAN_HEADSHOT.male.left:a.FACE_SCAN_HEADSHOT.female.left,type:"video/mp4"})})}),e.jsx("div",{className:` w-[120px] overflow-hidden ${2===n?"opacity-100":"opacity-0 hidden"} `,children:e.jsx("video",{className:"h-full w-full object-contain border-none",muted:!0,loop:!0,autoPlay:!0,playsInline:!0,children:e.jsx("source",{src:i===a.GenderType.Male?a.FACE_SCAN_HEADSHOT.male.right:a.FACE_SCAN_HEADSHOT.female.right,type:"video/mp4"})})}),e.jsx("div",{className:` w-[120px] overflow-hidden ${3===n?"opacity-100":"opacity-0 hidden"} `,children:e.jsx("video",{className:"h-full w-full object-contain border-none",muted:!0,loop:!0,autoPlay:!0,playsInline:!0,children:e.jsx("source",{src:i===a.GenderType.Male?a.FACE_SCAN_HEADSHOT.male.smile:a.FACE_SCAN_HEADSHOT.female.smile,type:"video/mp4"})})})]})]})})}const u=({webcamRef:o,canvasRef:s})=>{const{isError:c,isSuccess:i,showLoader:u,hasError:f,errorType:g,resetScanState:h,showGuideCard:m,scanStage:p,videoLoading:y,setVideoLoading:S,videoError:x,setVideoError:v,gender:b,getButtonText:w,isScanning:F,startScan:C,isModelLoaded:j,onRetry:E}=t.useContext(a.ParamsContext),_=a.useConfig();return c?e.jsx(l,{onRetry:E}):i?e.jsx("div",{className:"fixed z-[9] common-ui-main w-full h-full",style:{background:_?.style?.base?.backgroundColor},children:e.jsx(a.LoadingScreen,{url:_?.loader,loaderType:"black"})}):e.jsxs(e.Fragment,{children:[e.jsx("audio",{id:"audioElement",crossOrigin:"anonymous",preload:"auto",style:{position:"absolute",zIndex:-99999},src:void 0}),u&&!f&&e.jsx("div",{className:"fixed z-[9] common-ui-main w-full h-full",style:{background:_?.style?.base?.backgroundColor},children:e.jsx(a.LoadingScreen,{url:_?.loader,loaderType:"black"})}),e.jsx("div",{className:"h-full flex-col common-ui-main relative w-full flex justify-center items-center text-center rounded-t-[20px]",style:{background:_?.style?.base?.backgroundColor},children:e.jsx("div",{className:"flex-1 w-full max-w-md overflow-hidden",children:e.jsxs("div",{className:"w-full h-full",children:[e.jsx("video",{ref:o,autoPlay:!0,playsInline:!0,muted:!0,width:a.videoConstraints.width.ideal,height:a.videoConstraints.height.ideal,className:"w-full h-full object-cover fixed left-0 top-0 z-0",style:{transform:"scaleX(-1)"}}),e.jsx("canvas",{ref:s,width:a.videoConstraints.width.ideal,height:a.videoConstraints.height.ideal,style:{transform:"scaleX(-1)",opacity:"0"}})]})})}),!u&&f&&g===a.FaceScanErrorType.Camera&&e.jsx(a.Modal,{testId:"face-scan-camera-error-screen",config:_}),!u&&f&&g!==a.FaceScanErrorType.Camera&&e.jsx(l,{loading:u,onRetry:h}),m&&!f&&!u&&e.jsx(r.Drawer,{open:!0,className:"face-scan-small camera-draw",anchor:"bottom",onClose:(e,t)=>{},hideBackdrop:!0,children:e.jsx(d,{stage:p,videoLoading:y,setVideoLoading:S,videoError:x,setVideoError:v,gender:b,btnConfig:{label:w(),onClick:F?h:C,isDisabled:u||!j,icon:F?e.jsx(n.ArrowRight,{}):e.jsx(e.Fragment,{})}})})]})};exports.FaceScan=n=>{const{onScanSuccess:r,onScanError:o,onRetry:s,onScanStart:c,onCaptureComplete:l,onUploadStart:d,onUploadEnd:f,onMeasurementSocketStart:g,onMeasurementSocketClose:h,config:m,isError:p,isSuccess:y}=n,S=n.userDetails??{email:"",gender:"male",deviceFocalLength:0,shopDomain:"",bodyScanId:"",callbackUrl:null},x=n.token??"",v=t.useRef(null),b=t.useRef(null),w=t.useRef(null),F=t.useRef([]),C=t.useRef(null),j=t.useRef(null),E=t.useRef(0),_=t.useRef(null),[N,T]=t.useState(!1),[k,R]=t.useState(!1),[I,D]=t.useState(!1),[M,P]=t.useState(!0),[A,L]=t.useState(!1),[O,z]=t.useState(!1),[$,H]=t.useState(!1),[V,W]=t.useState(null),[K,U]=t.useState(a.generateUuid()),q=t.useMemo(()=>a.getSwanService(x),[x]),{email:B,gender:G,deviceFocalLength:J,shopDomain:X,callbackUrl:Q,bodyScanId:Y}=S,[Z,ee]=t.useState([]),[te,ae]=t.useState(a.videoConstraintsExact),ne=t.useMemo(()=>a.getPreferredMediaRecorderTypes(),[]),re=a.getRecordingMimeType(Z),oe=a.getRecordingExtension(re);a.usePosthogPageview();const se=t.useCallback(()=>{console.log("Stopping recording..."),cancelAnimationFrame(E.current),_.current&&(_.current.pause(),_.current.srcObject=null,_.current=null),w.current&&"recording"===w.current.state&&w.current.stop(),w.current=null},[]),ce=async()=>{if(l?.(),F.current){if(0===F.current.length)return console.error("No video data recorded"),W(a.FaceScanErrorType.Scan),H(!0),void T(!1);d?.(),T(!0);const e=new File(F.current,`${K}.${oe}`,{type:re}),t=j.current??await a.getVideoFPS(e),n=e.size,r=(n/1048576).toFixed(2),o=Math.round(n/1e4),s={video_size_mb:parseFloat(r),video_size_bytes:n,video_fps:t||0,blob_count:F.current.length,estimated_duration_seconds:o},c=[{gender:G},{face_scan_id:K},{focal_length:`${J}`},{customer_store_url:X},{scan_type:"face_scan"},{body_scan_id:Y}];Q&&c.push({callback_url:Q}),a.handleScanTimeCapture({eventName:`${X}/face_scan_meta_data`,faceScanId:K,email:B,data:JSON.stringify({metaData:c,videoData:s})});const i=Date.now();a.handleScanTimeCapture({eventName:`${X}/face_scan_upload_start`,faceScanId:K,email:B,startTime:i});try{const t=await q.fileUpload.faceScanFileUploader({file:e,arrayMetaData:c,objectKey:K,email:B,contentType:e.type}),n=Date.now(),r=n-i;a.handleScanTimeCapture({eventName:`${X}/face_scan_upload_complete`,faceScanId:K,email:B,completionTime:n,uploadDuration:r}),f?.(),console.log("✅ Upload successful",t),q.measurement.handlFaceScaneSocket({onPreopen:()=>{g?.(),a.handleWebSocketCapture({eventName:`${X}/webSocket`,faceScanID:K,connection:"pre_open",type:"faceScan_recommendation",email:B})},faceScanId:K,onOpen:()=>{a.handleWebSocketCapture({eventName:`${X}/webSocket`,faceScanID:K,connection:"open",type:"faceScan_recommendation",email:B}),console.log("websocket connect open")},onError:e=>{a.handleWebSocketCapture({eventName:`${X}/webSocket`,faceScanID:K,connection:"error",type:"faceScan_recommendation",email:B}),ye(e)},onSuccess:e=>{a.handleWebSocketCapture({eventName:`${X}/webSocket`,faceScanID:K,connection:"success",type:"faceScan_recommendation",email:B}),Se(e)},onClose:()=>{h?.(),console.log("websocket connect close"),a.handleWebSocketCapture({eventName:`${X}/webSocket`,faceScanID:K,connection:"close",type:"faceScan_recommendation",email:B})}})}catch(e){f?.(),ye(e)}}},ie=t.useCallback(()=>{const e=v.current?.srcObject;if(!e)return;const t=e.getVideoTracks()[0].getSettings(),{width:n=1280,height:r=720}=t,o=document.createElement("canvas"),s=o.getContext("2d");n>r?(o.width=r,o.height=n):(o.width=n,o.height=r);const c=document.createElement("video");c.srcObject=e,c.muted=!0,c.playsInline=!0,c.play(),_.current=c;const i=()=>{n>r?(s?.save(),s?.translate(o.width,0),s?.rotate(Math.PI/2),s?.drawImage(c,0,0,r,n),s?.restore()):s?.drawImage(c,0,0,n,r),E.current=requestAnimationFrame(i)};E.current=requestAnimationFrame(i);const l=t.frameRate??10;j.current=l;const d=o.captureStream(l),u={videoBitsPerSecond:15e5};let f;Z.length>0&&(u.mimeType=Z[0]);try{f=new MediaRecorder(d,u)}catch(e){return console.error("MediaRecorder init failed:",e),W(a.FaceScanErrorType.Scan),H(!0),void T(!1)}F.current=[],f.ondataavailable=e=>{e?.data&&e.data.size>0&&F.current&&F.current.push(e.data)},f.onstop=()=>{console.log("Recording stopped, total blobs:",F?.current?.length),ce()},f.start(100),w.current=f,console.log("Recording started successfully (portrait normalized)")},[Z,ce]),{faceScanDetector:le,scanStage:de,setScanStage:ue,resetScan:fe,isModelLoaded:ge,startScanSequence:he}=i({faceScanId:K,shopDomain:X,isError:p,isSuccess:y,onScanComplete:()=>{se()},onModelReady:()=>{R(!0)},onStartRecording:()=>{console.log("Stage 0 completed - starting recording for stages 1-3"),ie()}}),me=t.useCallback(()=>{ge&&(c?.(),ue(0),a.speechService.playAudio(`${a.voiceOverAssetsPath}face-scan-vos/Face-forward.mp3`),setTimeout(()=>{D(!0),setTimeout(()=>{he()},200)},200))},[ue,D,he,ge,c]),pe=t.useCallback(()=>{D(!1),P(!0),se(),fe(),s?.(),F.current=[],j.current=null,w.current&&(w.current=null),H(!1),W(null),ue(-1),U(a.generateUuid()),v.current&&C.current&&(v.current.srcObject=C.current,console.log("Camera stream restored after reset"))},[ue,D,P,se,fe,U]),ye=e=>{console.log(e,"ws error"),o?.(e),W(a.FaceScanErrorType.Scan),H(!0),T(!1),P(!1),a.handleScanTimeCapture({eventName:`${X}/faceScan`,faceScanId:K,status:"failed",email:B,data:JSON.stringify(e)})},Se=e=>{console.log(e,"ws success"),e&&"intermediate"===e?.resultType&&a.handleScanTimeCapture({eventName:`${X}/faceScan_success/intermediate`,faceScanId:K,status:"success",email:B,data:JSON.stringify(e)}),r?.(e)};t.useEffect(()=>{if(!p&&!y)return navigator.mediaDevices.getUserMedia&&navigator.mediaDevices.getUserMedia({video:te}).then(e=>{C.current=e,v.current&&(v.current.srcObject=e)}).catch(e=>{if(console.error("Error accessing webcam:",e),te===a.videoConstraintsExact)return void ae(a.videoConstraintsFallback);const t=["NotAllowedError","PermissionDeniedError","NotFoundError","DevicesNotFoundError","NotReadableError","TrackStartError"].includes(e?.name);W(t?a.FaceScanErrorType.Camera:a.FaceScanErrorType.Scan),H(!0)}),()=>{C.current&&C.current.getTracks().forEach(e=>e.stop())}},[p,y,te]),t.useEffect(()=>{if(!k||!I)return;const e=setInterval(()=>{le(v,b)},500);return()=>clearInterval(e)},[le,k,I]);return console.log("Model ready:",k,"Has error:",$,"Is scanning:",I,"showLoader",N),t.useEffect(()=>{const e=a.getSupportedMediaRecorderTypes(ne,a.videoTypes);ee(e)},[ne]),t.useEffect(()=>{ue(-1)},[]),e.jsx("div",{"data-face-scan-stage":de,children:e.jsx(a.LanguageContextProvider,{children:e.jsx(a.ConfigProvider,{config:m,children:e.jsx(a.ParamsContext.Provider,{value:{isError:p,isSuccess:y,showLoader:N,hasError:$,errorType:V,resetScanState:pe,showGuideCard:M,scanStage:de,videoLoading:A,setVideoLoading:L,videoError:O,setVideoError:z,gender:G,getButtonText:()=>I?a.LanguageKeys.reset:ge?a.LanguageKeys.start:a.LanguageKeys.loading,isScanning:I,startScan:me,isModelLoaded:ge,onRetry:s},children:e.jsx(u,{webcamRef:v,canvasRef:b})})})})})},exports.preloadDetector=c;
2
- //# sourceMappingURL=FaceScan-DYJVZoZ4.js.map
@@ -1,2 +0,0 @@
1
- import{jsx as e,jsxs as t,Fragment as a}from"react/jsx-runtime";import{useRef as n,useState as r,useMemo as o,useCallback as c,useEffect as i,useContext as s}from"react";import{v as l,p as d,s as u,a as m,L as h,u as f,H as g,b as p,S as y,m as S,g as b,G as w,d as v,F as x,P as F,c as N,e as I,M as _,f as k,h as E,i as C,j as M,k as D,l as T,n as P,o as R,q as z,r as $,t as j,C as L,w as V,x as O,y as W}from"./Modal-DRjJKUrw.js";import{ArrowRight as U}from"lucide-react";import{Drawer as A}from"@mui/material";let B=null,q=!1;const J=async()=>{if("undefined"==typeof window)return null;if(B)return B;if(q)for(;q;)if(await new Promise(e=>setTimeout(e,100)),B)return B;q=!0;try{const[e,t]=await Promise.all([import("@tensorflow/tfjs"),import("./pose-detection.esm-DejsYGYM.js")]);await e.setBackend("webgl"),await e.ready();const a=await t.createDetector(t.SupportedModels.BlazePose,{runtime:"tfjs",modelType:"full"}),n=document.createElement("canvas");n.width="number"==typeof l.width?l.width:l.width.ideal??l.width.max??1280,n.height="number"==typeof l.height?l.height:l.height.ideal??l.height.max??720;const r=n.getContext("2d");if(r){r.fillStyle="black",r.fillRect(0,0,n.width,n.height);try{await a.estimatePoses(n)}catch(e){console.warn("Warmup frame failed (non-fatal):",e)}}return B=a,a}catch(e){return console.error("Failed to preload detector:",e),null}finally{q=!1}};function G({faceScanId:e,onValidPose:t,onScanComplete:a,onModelReady:s,onStartRecording:l,shopDomain:h,isError:f,isSuccess:g}){const p=n(null),[y,S]=r(0),[b,w]=r(0),[v,x]=r(!1),[F,N]=r(!1),I=n(!1),_=n(null),k=n(null),E=n(y),C=n(b),M=n([]),D=n(""),T=n(0),P=n(!1),R=n(0),z="undefined"!=typeof navigator&&(/iPad|iPhone|iPod/.test(navigator.userAgent)||"MacIntel"===navigator.platform&&navigator.maxTouchPoints>1),$=o(()=>["Face front","Turn head fully left","Turn head fully right","Smile facing front"],[]),j=o(()=>function(e,t){let a;return(...n)=>{a&&clearTimeout(a),a=setTimeout(()=>e(...n),t)}}(e=>{d.capture(`${h}/face_scan_pose_detection`,e)},4e3),[h]),L=c((t,a,n,r,o,c)=>{const i=Date.now();if(!(i-R.current<4e3)){R.current=i;try{const i=t[0]||[0,0,0],s=t[2]||[0,0,0],l=t[5]||[0,0,0],d=t[9]||[0,0,0],u=t[10]||[0,0,0],m=t.map(e=>e[2]).filter(e=>e>0),h=m.length>0?m.reduce((e,t)=>e+t,0)/m.length:0,f=a.map(e=>e[2]).filter(e=>e>0),g=f.length>0?f.reduce((e,t)=>e+t,0)/f.length:0,p=Math.abs(s[0]-l[0]),y=i[0]-l[0],S=s[0]-i[0];let b="frontal";1===n?b="left":2===n?b="right":3===n&&(b="frontal_smile");const w={faceScanId:e,stage:n,timestamp:(new Date).toISOString(),data:JSON.stringify({headValid:r,bodyInvalid:o,consecutiveValid:c,avgFaceScore:parseFloat(h.toFixed(3)),avgBodyScore:parseFloat(g.toFixed(3)),faceKeypointsDetected:m.length,bodyKeypointsDetected:f.length,eyeDistance:parseFloat(p.toFixed(2)),noseToRightRatio:parseFloat((y/p).toFixed(3)),noseToLeftRatio:parseFloat((S/p).toFixed(3)),noseScore:parseFloat(i[2].toFixed(3)),leftEyeScore:parseFloat(s[2].toFixed(3)),rightEyeScore:parseFloat(l[2].toFixed(3)),leftMouthScore:parseFloat(d[2].toFixed(3)),rightMouthScore:parseFloat(u[2].toFixed(3)),expectedPosition:b})};j(w)}catch(e){console.warn("Failed to track pose detection:",e)}}},[e,j]),V=()=>{d.capture(`${h}/face_scan_detection_started`,{faceScanId:e,stage:E.current,timestamp:(new Date).toISOString(),stageName:$[E.current]}),setTimeout(()=>{N(!0)},1500)};return i(()=>{if(!f&&!g)return(async()=>{if("undefined"!=typeof window)try{console.log("Initializing Face Scan...");const e=await J();e&&(p.current=e,console.log("Face scan model loaded successfully"),x(!0),s?.())}catch(e){console.error("Error initializing face scan:",e)}})(),()=>{(async()=>{try{x(!1)}catch(e){console.error("Error disposing resources:",e)}finally{S(0),w(0),E.current=0,C.current=0,M.current=[]}})()}},[f,g]),i(()=>{E.current=y},[y]),i(()=>{C.current=b},[b]),{faceScanDetector:async(n,r)=>{if(p.current&&n.current&&v&&F&&!(n.current.readyState<2||I.current)){I.current=!0;try{const o=n.current.videoWidth||720,c=n.current.videoHeight||1280;_.current||(_.current=document.createElement("canvas"),_.current.width=o,_.current.height=c);const i=_.current.getContext("2d");i&&i.drawImage(n.current,0,0,o,c);const s=await p.current.estimatePoses(i?_.current:n.current);if(s.length>0){const n=[],o=[];if(s[0].keypoints.forEach((e,t)=>{const a=e.score??0,r=[e.x??-1,e.y??-1,a];t<=10?n.push(r):o.push(r)}),r?.current){const e=r.current.getContext("2d"),{width:t,height:a}=r.current;if(e){e.clearRect(0,0,t,a);const n=Math.min(C.current/2,1),r=.35*a;e.beginPath(),e.strokeStyle="#00ff00",e.lineWidth=6,e.arc(t/2,a/2,r+10,-Math.PI/2,-Math.PI/2+2*n*Math.PI),e.stroke()}}const c=((e,t)=>{if(!t[0]||!t[2]||!t[5]||t[0][2]<.2||t[2][2]<.2||t[5][2]<.2)return!1;const a=.5*(t[10][1]+t[9][1])-.5*(t[5][1]+t[2][1]),n=(.5*(t[10][1]+t[9][1])-t[0][1])/a,r=n>.7||n<.3,o=Math.abs(t[2][1]-t[5][1])<.5*a&&Math.abs(t[9][1]-t[10][1])<.5*a,c=t[2][0]-t[5][0],i=t[0][0]-t[5][0],s=i>.4*c&&i<.6*c,l=i>.85*c,d=t[2][0]-t[0][0]>.85*c;switch(e){case 0:case 3:return!r&&o&&s;case 1:return!r&&o&&l;case 2:return!r&&o&&d;default:return!1}})(E.current,n),i=o.slice(2).filter(e=>e[2]>.7).length<=2;M.current.push(c&&i),M.current.length>10&&M.current.shift();if(M.current.filter(Boolean).length>=2){const e=C.current+1;w(e)}else w(Math.max(0,C.current-1));if(C.current>=2){t?.();const n=E.current+1;w(0),M.current=[],S(n),N(!1),(async()=>{if(await u.playAudio(`${m}face-scan-vos/Sound-effect.mp3`),d.capture(`${h}/face_scan_detection_stage_completed`,{faceScanId:e,completedStage:E.current,nextStage:n,timestamp:(new Date).toISOString(),totalStages:4,stageName:$[E.current]}),1===n&&l&&l(),n>=4)a?.();else{let e=null;switch(n){case 1:e="Left.mp3";break;case 2:e="Right.mp3";break;case 3:e="Smile.mp3"}e&&await u.playAudio(`${m}face-scan-vos/${e}`),V()}})()}L(n,o,E.current,c,i,C.current)}}catch(e){console.error("Pose detection error:",e)}finally{I.current=!1}}},scanStage:y,setScanStage:S,consecutiveValid:b,isModelLoaded:v,resetScan:()=>{d.capture(`${h}/face_scan_reset`,{faceScanId:e,stage:E.current,timestamp:(new Date).toISOString(),stageName:$[E.current],consecutiveValid:C.current}),S(0),w(0),N(!1),E.current=0,C.current=0,M.current=[],D.current="",T.current=0,P.current=!1,k.current&&(speechSynthesis.cancel(),k.current=null)},enableVoiceCommands:()=>{if(P.current=!0,"undefined"!=typeof window&&z&&"speechSynthesis"in window){const e=new SpeechSynthesisUtterance("");e.volume=0,speechSynthesis.speak(e)}},startScanSequence:V,isScanningActive:F}}function H({onRetry:a,loading:n}){const{translate:r}=s(h)||{},o=f();return e("div",{"data-testid":"face-scan-error-screen",className:"fixed common-ui-main top-[0] left-[0] z-[999] flex justify-center items-center w-full h-full",style:{background:o?.style?.base?.backgroundColor},children:t("div",{className:"flex flex-col w-full items-center p-[1rem] rounded-lg ",children:[e(g,{noTitle:!0}),t("div",{className:"flex flex-col items-center w-full",children:[e("h2",{className:"text-xl font-semibold text-gray-800 ",style:{fontFamily:o?.style?.heading?.headingFontFamily||"SeriouslyNostalgic Fn",fontSize:o?.style?.heading?.headingFontSize||"32px",color:o?.style?.heading?.headingColor||"#000",fontWeight:o?.style?.heading?.headingFontWeight||"normal"},children:r?.(p.scanFailed)}),e("p",{className:"mb-[1.5rem]",style:{fontFamily:o?.style?.subheading?.subheadingFontFamily||"'Inter', sans-serif",fontSize:o?.style?.subheading?.subheadingFontSize||"14px",color:o?.style?.subheading?.subheadingColor||"#4b5563",fontWeight:o?.style?.subheading?.subheadingFontWeight||"normal"},children:r?.(p.clickToResetScan)}),e(y,{"data-testid":"face-scan-retry-btn",disabled:n,className:"w-full h-[45px] shadow-[0px_1px_2px_0px_#00000040] text-[16px]",buttonText:r?.(p.resetScan),postfixIcon:e(U,{}),buttonFunc:()=>a?.()})]})]})})}function K({stage:a,videoLoading:n,setVideoLoading:r,videoError:o,setVideoError:c,gender:i,btnConfig:l}){const{translate:d}=s(h)||{},u=f();return-1===a?t("div",{"data-testid":"face-scan-guide",className:"text-center common-ui-main p-[16px] w-full h-full",style:{background:u?.style?.base?.backgroundColor},children:[t("div",{className:"w-full",children:[e(g,{noTitle:!0}),e("h2",{style:{fontFamily:u?.style?.heading?.headingFontFamily||"SeriouslyNostalgic Fn",fontSize:u?.style?.heading?.headingFontSize||"32px",color:u?.style?.heading?.headingColor||"#000",fontWeight:u?.style?.heading?.headingFontWeight||"normal"},children:d?.(p.faceVisible)}),n&&e("div",{className:"mb-4 flex items-center justify-center",style:{fontFamily:u?.style?.subheading?.subheadingFontFamily||"'Inter', sans-serif",fontSize:u?.style?.subheading?.subheadingFontSize||"14px",color:u?.style?.subheading?.subheadingColor||"#4b5563",fontWeight:u?.style?.subheading?.subheadingFontWeight||"normal"},children:d?.(p.loadingVideo)}),o&&e("div",{className:"mb-4 text-red-600",style:{fontFamily:u?.style?.subheading?.subheadingFontFamily||"'Inter', sans-serif",fontSize:u?.style?.subheading?.subheadingFontSize||"14px",color:"#ff0000",fontWeight:u?.style?.subheading?.subheadingFontWeight||"normal"},children:d?.(p.videoLoadFailed)}),!o&&e("div",{className:" w-[100px] mx-auto",children:e("video",{src:i===w.Male?S:b,autoPlay:!0,loop:!0,controls:!1,muted:!0,playsInline:!0,className:"h-full w-full object-contain border-none",onCanPlay:()=>r(!1),onLoadStart:()=>r(!0),onError:()=>c(!0),"aria-label":"Instructional video: Please remove your glasses before starting the scan."})})]}),e("div",{className:"flex justify-center w-full p-[1rem]",children:e(y,{"data-testid":"face-scan-start-btn",disabled:l.isDisabled,className:"!w-[60px] !h-[35px] !py-0 !px-0",buttonText:d?.(l.label),postfixIcon:l?.icon,buttonFunc:l.onClick})})]}):e("div",{className:"text-center common-ui-main p-[16px] w-full h-full",style:{background:u?.style?.base?.backgroundColor},children:t("div",{className:"w-full",children:[e(g,{noTitle:!0}),e("h3",{className:"mb-[0.5rem]",style:{fontFamily:u?.style?.heading?.headingFontFamily||"SeriouslyNostalgic Fn",fontSize:u?.style?.heading?.headingFontSize||"32px",color:u?.style?.heading?.headingColor||"#000",fontWeight:u?.style?.heading?.headingFontWeight||"normal"},children:d?.(v[a])}),t("div",{className:"max-w-[400px] justify-center gap-1 mx-auto flex items-center",children:[e("div",{className:` w-[120px] overflow-hidden ${0===a?"opacity-100":"opacity-0 hidden"} `,children:e("video",{className:"h-full w-full object-contain border-none",muted:!0,loop:!0,autoPlay:!0,playsInline:!0,children:e("source",{src:i===w.Male?x.male.forward:x.female.forward,type:"video/mp4"})})}),e("div",{className:` w-[120px] overflow-hidden ${1===a?"opacity-100":"opacity-0 hidden"} `,children:e("video",{className:"h-full w-full object-contain border-none",muted:!0,loop:!0,autoPlay:!0,playsInline:!0,children:e("source",{src:i===w.Male?x.male.left:x.female.left,type:"video/mp4"})})}),e("div",{className:` w-[120px] overflow-hidden ${2===a?"opacity-100":"opacity-0 hidden"} `,children:e("video",{className:"h-full w-full object-contain border-none",muted:!0,loop:!0,autoPlay:!0,playsInline:!0,children:e("source",{src:i===w.Male?x.male.right:x.female.right,type:"video/mp4"})})}),e("div",{className:` w-[120px] overflow-hidden ${3===a?"opacity-100":"opacity-0 hidden"} `,children:e("video",{className:"h-full w-full object-contain border-none",muted:!0,loop:!0,autoPlay:!0,playsInline:!0,children:e("source",{src:i===w.Male?x.male.smile:x.female.smile,type:"video/mp4"})})})]})]})})}const X=({webcamRef:n,canvasRef:r})=>{const{isError:o,isSuccess:c,showLoader:i,hasError:d,errorType:u,resetScanState:m,showGuideCard:h,scanStage:g,videoLoading:p,setVideoLoading:y,videoError:S,setVideoError:b,gender:w,getButtonText:v,isScanning:x,startScan:k,isModelLoaded:E,onRetry:C}=s(F),M=f();return o?e(H,{onRetry:C}):c?e("div",{className:"fixed z-[9] common-ui-main w-full h-full",style:{background:M?.style?.base?.backgroundColor},children:e(N,{url:M?.loader,loaderType:"black"})}):t(a,{children:[e("audio",{id:"audioElement",crossOrigin:"anonymous",preload:"auto",style:{position:"absolute",zIndex:-99999},src:void 0}),i&&!d&&e("div",{className:"fixed z-[9] common-ui-main w-full h-full",style:{background:M?.style?.base?.backgroundColor},children:e(N,{url:M?.loader,loaderType:"black"})}),e("div",{className:"h-full flex-col common-ui-main relative w-full flex justify-center items-center text-center rounded-t-[20px]",style:{background:M?.style?.base?.backgroundColor},children:e("div",{className:"flex-1 w-full max-w-md overflow-hidden",children:t("div",{className:"w-full h-full",children:[e("video",{ref:n,autoPlay:!0,playsInline:!0,muted:!0,width:l.width.ideal,height:l.height.ideal,className:"w-full h-full object-cover fixed left-0 top-0 z-0",style:{transform:"scaleX(-1)"}}),e("canvas",{ref:r,width:l.width.ideal,height:l.height.ideal,style:{transform:"scaleX(-1)",opacity:"0"}})]})})}),!i&&d&&u===I.Camera&&e(_,{testId:"face-scan-camera-error-screen",config:M}),!i&&d&&u!==I.Camera&&e(H,{loading:i,onRetry:m}),h&&!d&&!i&&e(A,{open:!0,className:"face-scan-small camera-draw",anchor:"bottom",onClose:(e,t)=>{},hideBackdrop:!0,children:e(K,{stage:g,videoLoading:p,setVideoLoading:y,videoError:S,setVideoError:b,gender:w,btnConfig:{label:v(),onClick:x?m:k,isDisabled:i||!E,icon:e(x?U:a,{})}})})]})},Q=t=>{const{onScanSuccess:a,onScanError:s,onRetry:l,onScanStart:d,onCaptureComplete:h,onUploadStart:f,onUploadEnd:g,onMeasurementSocketStart:y,onMeasurementSocketClose:S,config:b,isError:w,isSuccess:v}=t,x=t.userDetails??{email:"",gender:"male",deviceFocalLength:0,shopDomain:"",bodyScanId:"",callbackUrl:null},N=t.token??"",_=n(null),U=n(null),A=n(null),B=n([]),q=n(null),J=n(null),H=n(0),K=n(null),[Q,Y]=r(!1),[Z,ee]=r(!1),[te,ae]=r(!1),[ne,re]=r(!0),[oe,ce]=r(!1),[ie,se]=r(!1),[le,de]=r(!1),[ue,me]=r(null),[he,fe]=r(k()),ge=o(()=>E(N),[N]),{email:pe,gender:ye,deviceFocalLength:Se,shopDomain:be,callbackUrl:we,bodyScanId:ve}=x,[xe,Fe]=r([]),[Ne,Ie]=r(C),_e=o(()=>M(),[]),ke=D(xe),Ee=T(ke);P();const Ce=c(()=>{console.log("Stopping recording..."),cancelAnimationFrame(H.current),K.current&&(K.current.pause(),K.current.srcObject=null,K.current=null),A.current&&"recording"===A.current.state&&A.current.stop(),A.current=null},[]),Me=async()=>{if(h?.(),B.current){if(0===B.current.length)return console.error("No video data recorded"),me(I.Scan),de(!0),void Y(!1);f?.(),Y(!0);const e=new File(B.current,`${he}.${Ee}`,{type:ke}),t=J.current??await V(e),a=e.size,n=(a/1048576).toFixed(2),r=Math.round(a/1e4),o={video_size_mb:parseFloat(n),video_size_bytes:a,video_fps:t||0,blob_count:B.current.length,estimated_duration_seconds:r},c=[{gender:ye},{face_scan_id:he},{focal_length:`${Se}`},{customer_store_url:be},{scan_type:"face_scan"},{body_scan_id:ve}];we&&c.push({callback_url:we}),O({eventName:`${be}/face_scan_meta_data`,faceScanId:he,email:pe,data:JSON.stringify({metaData:c,videoData:o})});const i=Date.now();O({eventName:`${be}/face_scan_upload_start`,faceScanId:he,email:pe,startTime:i});try{const t=await ge.fileUpload.faceScanFileUploader({file:e,arrayMetaData:c,objectKey:he,email:pe,contentType:e.type}),a=Date.now();O({eventName:`${be}/face_scan_upload_complete`,faceScanId:he,email:pe,completionTime:a,uploadDuration:a-i}),g?.(),console.log("✅ Upload successful",t),ge.measurement.handlFaceScaneSocket({onPreopen:()=>{y?.(),W({eventName:`${be}/webSocket`,faceScanID:he,connection:"pre_open",type:"faceScan_recommendation",email:pe})},faceScanId:he,onOpen:()=>{W({eventName:`${be}/webSocket`,faceScanID:he,connection:"open",type:"faceScan_recommendation",email:pe}),console.log("websocket connect open")},onError:e=>{W({eventName:`${be}/webSocket`,faceScanID:he,connection:"error",type:"faceScan_recommendation",email:pe}),Oe(e)},onSuccess:e=>{W({eventName:`${be}/webSocket`,faceScanID:he,connection:"success",type:"faceScan_recommendation",email:pe}),We(e)},onClose:()=>{S?.(),console.log("websocket connect close"),W({eventName:`${be}/webSocket`,faceScanID:he,connection:"close",type:"faceScan_recommendation",email:pe})}})}catch(e){g?.(),Oe(e)}}},De=c(()=>{const e=_.current?.srcObject;if(!e)return;const t=e.getVideoTracks()[0].getSettings(),{width:a=1280,height:n=720}=t,r=document.createElement("canvas"),o=r.getContext("2d");a>n?(r.width=n,r.height=a):(r.width=a,r.height=n);const c=document.createElement("video");c.srcObject=e,c.muted=!0,c.playsInline=!0,c.play(),K.current=c;const i=()=>{a>n?(o?.save(),o?.translate(r.width,0),o?.rotate(Math.PI/2),o?.drawImage(c,0,0,n,a),o?.restore()):o?.drawImage(c,0,0,a,n),H.current=requestAnimationFrame(i)};H.current=requestAnimationFrame(i);const s=t.frameRate??10;J.current=s;const l=r.captureStream(s),d={videoBitsPerSecond:15e5};let u;xe.length>0&&(d.mimeType=xe[0]);try{u=new MediaRecorder(l,d)}catch(e){return console.error("MediaRecorder init failed:",e),me(I.Scan),de(!0),void Y(!1)}B.current=[],u.ondataavailable=e=>{e?.data&&e.data.size>0&&B.current&&B.current.push(e.data)},u.onstop=()=>{console.log("Recording stopped, total blobs:",B?.current?.length),Me()},u.start(100),A.current=u,console.log("Recording started successfully (portrait normalized)")},[xe,Me]),{faceScanDetector:Te,scanStage:Pe,setScanStage:Re,resetScan:ze,isModelLoaded:$e,startScanSequence:je}=G({faceScanId:he,shopDomain:be,isError:w,isSuccess:v,onScanComplete:()=>{Ce()},onModelReady:()=>{ee(!0)},onStartRecording:()=>{console.log("Stage 0 completed - starting recording for stages 1-3"),De()}}),Le=c(()=>{$e&&(d?.(),Re(0),u.playAudio(`${m}face-scan-vos/Face-forward.mp3`),setTimeout(()=>{ae(!0),setTimeout(()=>{je()},200)},200))},[Re,ae,je,$e,d]),Ve=c(()=>{ae(!1),re(!0),Ce(),ze(),l?.(),B.current=[],J.current=null,A.current&&(A.current=null),de(!1),me(null),Re(-1),fe(k()),_.current&&q.current&&(_.current.srcObject=q.current,console.log("Camera stream restored after reset"))},[Re,ae,re,Ce,ze,fe]),Oe=e=>{console.log(e,"ws error"),s?.(e),me(I.Scan),de(!0),Y(!1),re(!1),O({eventName:`${be}/faceScan`,faceScanId:he,status:"failed",email:pe,data:JSON.stringify(e)})},We=e=>{console.log(e,"ws success"),e&&"intermediate"===e?.resultType&&O({eventName:`${be}/faceScan_success/intermediate`,faceScanId:he,status:"success",email:pe,data:JSON.stringify(e)}),a?.(e)};i(()=>{if(!w&&!v)return navigator.mediaDevices.getUserMedia&&navigator.mediaDevices.getUserMedia({video:Ne}).then(e=>{q.current=e,_.current&&(_.current.srcObject=e)}).catch(e=>{if(console.error("Error accessing webcam:",e),Ne===C)return void Ie(R);const t=["NotAllowedError","PermissionDeniedError","NotFoundError","DevicesNotFoundError","NotReadableError","TrackStartError"].includes(e?.name);me(t?I.Camera:I.Scan),de(!0)}),()=>{q.current&&q.current.getTracks().forEach(e=>e.stop())}},[w,v,Ne]),i(()=>{if(!Z||!te)return;const e=setInterval(()=>{Te(_,U)},500);return()=>clearInterval(e)},[Te,Z,te]);return console.log("Model ready:",Z,"Has error:",le,"Is scanning:",te,"showLoader",Q),i(()=>{const e=z(_e,$);Fe(e)},[_e]),i(()=>{Re(-1)},[]),e("div",{"data-face-scan-stage":Pe,children:e(j,{children:e(L,{config:b,children:e(F.Provider,{value:{isError:w,isSuccess:v,showLoader:Q,hasError:le,errorType:ue,resetScanState:Ve,showGuideCard:ne,scanStage:Pe,videoLoading:oe,setVideoLoading:ce,videoError:ie,setVideoError:se,gender:ye,getButtonText:()=>te?p.reset:$e?p.start:p.loading,isScanning:te,startScan:Le,isModelLoaded:$e,onRetry:l},children:e(X,{webcamRef:_,canvasRef:U})})})})})};export{Q as F,J as p};
2
- //# sourceMappingURL=FaceScan-Da2XEApH.js.map