@swan-admin/swan-web-component 1.0.123 → 1.0.124

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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":["../src/atoms/customInput/CustomInput.tsx","../src/components/onboarding/EmailStep.tsx","../src/components/onboarding/NameStep.tsx","../src/components/onboarding/GenderStep.tsx","../src/components/onboarding/HeightStep.tsx","../src/atoms/progressDots/ProgressDots.tsx","../src/components/onboarding/StepsWrapper.tsx","../src/utils/deviceFocalLengthJson/index.ts","../src/components/onboarding/Onboarding.tsx","../src/customHooks/usePhoneDetection.ts","../src/components/focalLength/FocalLengthWrapper.tsx","../src/components/focalLength/FocalLength.tsx","../src/components/educational/MuseSteps/MuseScreenRenderer.tsx","../src/components/educational/MuseSteps/index.tsx","../src/components/educational/MuseSteps/BodyScanAnimation.tsx","../src/components/educational/MuseSteps/FaceScanAnimation.tsx","../src/components/educational/MuseSteps/TypewritterScene.tsx","../src/customHooks/useMuseAnimation.ts","../src/components/educational/VolumeStep.tsx","../src/components/educational/SetupScreen.tsx","../src/components/educational/EducationalStepsWrapper.tsx","../src/components/educational/Educational.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { useConfig } from \"../../utils/context/configContext\";\n\n/** Lightweight classnames helper to avoid depending on ../../utils/utils */\nconst cn = (...classes: Array<string | false | null | undefined>) =>\n classes.filter(Boolean).join(\" \");\n\nexport interface CustomInputProps\n extends React.InputHTMLAttributes<HTMLInputElement> {\n className?: string;\n type?: string;\n}\n\nconst CustomInput = React.forwardRef<HTMLInputElement, CustomInputProps>(\n ({ className, type, ...props }, ref) => {\n const config = useConfig();\n const input = config?.style?.input;\n const priority = input?.priority;\n return (\n <>\n <input\n type={type}\n className={`${className ? className : ''} customInput ` + cn(\n \"flex w-full px-[.75rem] h-[40px] text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed backdrop-blur-sm bg-btn font-medium pl-[1rem] pr-[2.5rem] focus:ring-1 focus:outline-none transition-all duration-200\",\n )}\n autoCapitalize=\"off\"\n autoCorrect=\"off\"\n ref={ref}\n {...props}\n style={{\n background: priority?.inputBackgroundColor || input?.inputBackgroundColor || '#F9FAFC',\n color: priority?.inputTextColor || input?.inputTextColor || '#000',\n fontSize: input?.inputFontSize || '16px',\n fontWeight: input?.inputFontWeight || '400',\n border: `1px solid ${input?.inputBorderColor || 'transparent'}`,\n fontFamily: config?.style?.base?.baseFontFamily || 'Inter, sans-serif',\n borderRadius: input?.inputBorderRadius || '4px',\n }}\n />\n <style>\n {`\n .customInput::placeholder {\n color: ${priority?.inputPlaceholderColor || input?.inputPlaceholderColor || '#000'};\n font-weight: ${input?.inputFontWeight || '500'};\n opacity: 1;\n font-size: ${input?.inputFontSize || '14px'};\n }\n .customInput:focus-visible {\n box-shadow:0 0 0 2px white, 0 0 0 4px rgb(from currentColor r g b / 0.5);\n }\n\n `}\n </style>\n </>\n )}\n );\n\nCustomInput.displayName = \"CustomInput\";\n\nexport default CustomInput;\n","import CustomInput from \"../../atoms/customInput/CustomInput\";\nimport SpecificButton from \"../../atoms/specificButton/SpecificButton\";\nimport { LanguageContext } from \"../../utils/context/languageContext\";\nimport { LanguageKeys } from \"../../utils/languageKeys\";\nimport { handleErrorMessage, isValidEmail } from \"../../utils/utils\";\nimport { ArrowRight } from \"lucide-react\";\nimport React, { useContext } from \"react\";\nimport { useConfig } from \"../../utils/context/configContext\";\n\ninterface EmailStepProps {\n\tonComplete: (value: any) => void;\n\tinitialValue?: any;\n\tonStepComplete?: (value: any) => Promise<void> | void;\n}\n\nconst EmailStep = ({ onComplete, initialValue, onStepComplete }: EmailStepProps) => {\n\tconst [value, setValue] = React.useState(initialValue || \"\");\n\tconst [message, setMessage] = React.useState<string | undefined>(undefined);\n\tconst [loading, setLoading] = React.useState(false);\n\tconst { translate } = useContext(LanguageContext) || {};\n\tconst config = useConfig();\n\tconst handleNext = async (e: React.FormEvent<HTMLFormElement>) => {\n\t\te.preventDefault();\n\t\tsetLoading(true);\n\t\ttry {\n\t\t\tif (!value.trim()) {\n\t\t\t\tsetMessage(translate?.(LanguageKeys.emailRequired));\n\t\t\t\treturn;\n\t\t\t} else if (!isValidEmail(value.trim())) {\n\t\t\t\tsetMessage(translate?.(LanguageKeys.validEmail));\n\t\t\t} else {\n\t\t\t\tawait onStepComplete?.(value);\n\t\t\t\tonComplete?.(value);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tsetMessage(handleErrorMessage(error));\n\t\t} finally {\n\t\t\tsetLoading(false);\n\t\t}\n\t};\n\treturn (\n\t\t<div className=\"w-full max-w-md\">\n\t\t\t<form className=\"mt-[3.5rem]\" onSubmit={handleNext}>\n\t\t\t\t<div>\n\t\t\t\t\t<CustomInput\n\t\t\t\t\t\trequired\n\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\tid=\"name\"\n\t\t\t\t\t\tdata-testid=\"onboarding-email-input\"\n\t\t\t\t\t\tplaceholder={translate?.(LanguageKeys.enterEmail)}\n\t\t\t\t\t\tvalue={value}\n\t\t\t\t\t\tonChange={(e) => {\n\t\t\t\t\t\t\tsetMessage(undefined);\n\t\t\t\t\t\t\tsetValue(e.target.value);\n\t\t\t\t\t\t}}\n\t\t\t\t\t/>\n\t\t\t\t\t{message && (\n\t\t\t\t\t\t<p\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\tcolor: config?.style?.input?.inputErrorColor || \"#000\",\n\t\t\t\t\t\t\t\tfontSize: config?.style?.input?.inputErrorFontSize || \"16px\",\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{message}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t\t<div className=\"flex justify-end mt-[.5rem]\">\n\t\t\t\t\t<SpecificButton type=\"submit\" data-testid=\"onboarding-next-btn\" disabled={!value.trim() || loading} buttonText={translate?.(LanguageKeys.next)} postfixIcon={<ArrowRight size={14} />} />\n\t\t\t\t</div>\n\t\t\t</form>\n\t\t</div>\n\t);\n};\n\nexport default EmailStep;\n","import CustomInput from \"../../atoms/customInput/CustomInput\";\nimport SpecificButton from \"../../atoms/specificButton/SpecificButton\";\nimport { LanguageContext } from \"../../utils/context/languageContext\";\nimport { LanguageKeys } from \"../../utils/languageKeys\";\nimport { handleErrorMessage } from \"../../utils/utils\";\nimport { ArrowRight } from \"lucide-react\";\nimport React, { useContext } from \"react\";\nimport { useConfig } from \"../../utils/context/configContext\";\n\ninterface NameStepProps {\n\tonComplete: (value: any) => void;\n\tinitialValue?: any;\n\tonStepComplete?: (value: any) => Promise<void> | void;\n}\n\nconst NameStep = ({ onComplete, initialValue, onStepComplete }: NameStepProps) => {\n\tconst [value, setValue] = React.useState(initialValue || \"\");\n\tconst [message, setMessage] = React.useState<string | undefined>(undefined);\n\tconst [loading, setLoading] = React.useState(false);\n\tconst { translate } = useContext(LanguageContext) || {};\n\tconst config = useConfig();\n\tconst handleNext = async (e: React.FormEvent<HTMLFormElement>) => {\n\t\te.preventDefault();\n\t\tsetLoading(true);\n\t\ttry {\n\t\t\tif (!value.trim()) {\n\t\t\t\tsetMessage(translate?.(LanguageKeys.nameRequired));\n\t\t\t\treturn;\n\t\t\t} else {\n\t\t\t\tawait onStepComplete?.(value);\n\t\t\t\tonComplete?.(value);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tsetMessage(handleErrorMessage(error));\n\t\t} finally {\n\t\t\tsetLoading(false);\n\t\t}\n\t};\n\treturn (\n\t\t<div className=\"w-full max-w-md\">\n\t\t\t<form onSubmit={handleNext} className=\"mt-[3.5rem] mb-[.75rem]\">\n\t\t\t\t<div>\n\t\t\t\t\t<CustomInput\n\t\t\t\t\t\trequired\n\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\tid=\"name\"\n\t\t\t\t\t\tdata-testid=\"onboarding-name-input\"\n\t\t\t\t\t\tplaceholder={translate?.(LanguageKeys.enterName)}\n\t\t\t\t\t\tonChange={(e) => {\n\t\t\t\t\t\t\tsetValue(e.target.value);\n\t\t\t\t\t\t}}\n\t\t\t\t\t/>\n\t\t\t\t\t{message && (\n\t\t\t\t\t\t<p\n\t\t\t\t\t\t\tclassName=\"mt-[0.2rem] text-[16px]\"\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\tcolor: config?.style?.input?.inputErrorColor || '#000',\n\t\t\t\t\t\t\t\tfontSize: config?.style?.input?.inputErrorFontSize || '16px',\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{message}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t\t<div className=\"flex justify-end mt-[.5rem]\">\n\t\t\t\t\t<SpecificButton disabled={!value.trim() || loading} data-testid=\"onboarding-next-btn\" buttonText={translate?.(LanguageKeys.next)} type=\"submit\" postfixIcon={<ArrowRight size={14} />} />\n\t\t\t\t</div>\n\t\t\t</form>\n\t\t</div>\n\t);\n};\n\nexport default NameStep;\n","import SpecificButton from \"../../atoms/specificButton/SpecificButton\";\nimport { LanguageContext } from \"../../utils/context/languageContext\";\nimport { GenderType } from \"../../utils/enums\";\nimport { LanguageKeys } from \"../../utils/languageKeys\";\nimport { handleErrorMessage } from \"../../utils/utils\";\nimport { ArrowRight } from \"lucide-react\";\nimport React, { useContext, useState } from \"react\";\nimport { useConfig } from \"../../utils/context/configContext\";\n\ninterface GenderStepProps {\n\tonComplete: (value: any) => void;\n\tinitialValue?: any;\n\tonStepComplete?: (value: any) => Promise<void> | void;\n}\n\nconst GenderStep = ({ onComplete, initialValue, onStepComplete }: GenderStepProps) => {\n\tconst [genderType, setGenderType] = useState<GenderType>(initialValue);\n\tconst [message, setMessage] = React.useState<string | undefined>(undefined);\n\tconst [loading, setLoading] = React.useState(false);\n\tconst { translate } = useContext(LanguageContext) || {};\n\tconst config = useConfig();\n\tconst input = config?.style?.input;\n\tconst priority = input?.priority;\n\n\tconst bgColor = priority?.inputBackgroundColor || input?.inputBackgroundColor || \"#F9FAFC\";\n\tconst textColor = priority?.inputTextColor || input?.inputTextColor || \"#000\";\n\tconst selectedBgColor = priority?.inputBackgroundColorSelect;\n\tconst selectedTextColor = priority?.inputBackgroundColorSelectTextColor;\n\n\tconst handleNext = async () => {\n\t\tsetLoading(true);\n\t\tsetMessage(undefined);\n\t\ttry {\n\t\t\tawait onStepComplete?.(genderType);\n\t\t\tonComplete?.(genderType);\n\t\t} catch (error) {\n\t\t\tsetMessage(handleErrorMessage(error));\n\t\t} finally {\n\t\t\tsetLoading(false);\n\t\t}\n\t};\n\n\treturn (\n\t\t<>\n\t\t\t<div className=\" w-full flex flex-col max-w-md mt-[3.5rem] mb-[.75rem] gap-[1rem]\">\n\t\t\t\t<button\n\t\t\t\t\tdata-testid=\"onboarding-gender-male\"\n\t\t\t\t\tclassName={` text-btnSize bg-btn cursor-pointer border leading-none rounded-[.375rem] focus-visible:ring-secondary p-[1rem] ${\n\t\t\t\t\t\tgenderType === GenderType.Male ? ` shadow-[0_1px_1px_rgba(0,0,0,0.251)]` : \"\"\n\t\t\t\t\t}`}\n\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\tsetGenderType(GenderType.Male);\n\t\t\t\t\t\tsetMessage(undefined);\n\t\t\t\t\t}}\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tbackground: genderType === GenderType.Male ? selectedBgColor : bgColor,\n\t\t\t\t\t\tcolor: genderType === GenderType.Male ? selectedTextColor : textColor,\n\t\t\t\t\t\tfontSize: input?.inputFontSize || \"16px\",\n\t\t\t\t\t\tfontWeight: input?.inputFontWeight || \"400\",\n\t\t\t\t\t\tborder: `1px solid ${genderType === GenderType.Male ? config?.style?.base?.primaryColor : `transparent`}`,\n\t\t\t\t\t\tfontFamily: config?.style?.base?.baseFontFamily || \"Inter, sans-serif\",\n\t\t\t\t\t\tborderRadius: input?.inputBorderRadius || \"4px\",\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t{translate?.(LanguageKeys.mens)}\n\t\t\t\t</button>\n\t\t\t\t<button\n\t\t\t\t\tdata-testid=\"onboarding-gender-female\"\n\t\t\t\t\tclassName={`text-btnSize font-btnFont cursor-pointer leading-none rounded-[.375rem] focus-visible:ring-secondary p-[1rem] ${\n\t\t\t\t\t\tgenderType === GenderType.Female ? ` shadow-[0_1px_1px_rgba(0,0,0,0.251)]` : \"\"\n\t\t\t\t\t}`}\n\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\tsetGenderType(GenderType.Female);\n\t\t\t\t\t\tsetMessage(undefined);\n\t\t\t\t\t}}\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tbackground: genderType === GenderType.Female ? selectedBgColor : bgColor,\n\t\t\t\t\t\tcolor: genderType === GenderType.Female ? selectedTextColor : textColor,\n\t\t\t\t\t\tfontSize: input?.inputFontSize || \"16px\",\n\t\t\t\t\t\tfontWeight: input?.inputFontWeight || \"400\",\n\t\t\t\t\t\tborder: `1px solid ${genderType === GenderType.Female ? config?.style?.base?.primaryColor : `transparent`}`,\n\t\t\t\t\t\tfontFamily: config?.style?.base?.baseFontFamily || \"Inter, sans-serif\",\n\t\t\t\t\t\tborderRadius: input?.inputBorderRadius || \"4px\",\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t{translate?.(LanguageKeys.womens)}\n\t\t\t\t</button>\n\t\t\t\t{message && (\n\t\t\t\t\t<p\n\t\t\t\t\t\tclassName=\"mt-[0.2rem]\"\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tcolor: input?.inputErrorColor || \"#000\",\n\t\t\t\t\t\t\tfontSize: input?.inputErrorFontSize || \"16px\",\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t{message}\n\t\t\t\t\t</p>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t\t<div className=\"flex justify-end mt-[.5rem]\">\n\t\t\t\t<SpecificButton\n\t\t\t\t\ttype=\"submit\"\n\t\t\t\t\tdata-testid=\"onboarding-next-btn\"\n\t\t\t\t\tbuttonText={translate?.(LanguageKeys.next)}\n\t\t\t\t\tpostfixIcon={<ArrowRight size={14} />}\n\t\t\t\t\tdisabled={!genderType || loading}\n\t\t\t\t\tbuttonFunc={handleNext}\n\t\t\t\t/>\n\t\t\t</div>\n\t\t</>\n\t);\n};\n\nexport default GenderStep;\n","import CustomInput from \"../../atoms/customInput/CustomInput\";\nimport SpecificButton from \"../../atoms/specificButton/SpecificButton\";\nimport { LanguageContext } from \"../../utils/context/languageContext\";\nimport { LanguageKeys } from \"../../utils/languageKeys\";\nimport { convertToCentimeters, handleErrorMessage } from \"../../utils/utils\";\nimport { MenuItem, Select } from \"@mui/material\";\nimport { ArrowRight } from \"lucide-react\";\nimport { useCallback, useContext, useEffect, useMemo, useState } from \"react\";\nimport { useConfig } from \"../../utils/context/configContext\";\n\ninterface HeightStepProps {\n\tonComplete: (value: any) => void;\n\tinitialValue?: any;\n\tonStepComplete?: (value: any) => Promise<void> | void;\n}\n\nconst HeightStep = ({ onComplete, initialValue, onStepComplete }: HeightStepProps) => {\n\tconst [localHeight, setLocalHeight] = useState({ cm: initialValue ? String(initialValue) : \"\", ft: \"\", inch: \"\" });\n\tconst [measurementUnit, setMeasurementUnit] = useState(\"cm\");\n\tconst [message, setMessage] = useState<string | undefined>(undefined);\n\tconst { translate, preferredLanguage } = useContext(LanguageContext) || {};\n\tconst config = useConfig();\n\tconst input = config?.style?.input;\n\tconst priority = input?.priority;\n\n\tconst inputBg = priority?.inputBackgroundColor || input?.inputBackgroundColor || \"#F9FAFC\";\n\tconst inputText = priority?.inputTextColor || input?.inputTextColor || \"#000\";\n\n\tconst handleSetHeight = useCallback(\n\t\t(event: React.ChangeEvent<HTMLInputElement>) => {\n\t\t\tsetMessage(undefined);\n\t\t\tif (measurementUnit === \"cm\") {\n\t\t\t\tsetLocalHeight((prev) => ({ ...prev, cm: event.target.value, ft: \"\", inch: \"\" }));\n\t\t\t} else if (event.target.id === \"ft\") {\n\t\t\t\tsetLocalHeight((prev) => ({ ...prev, ft: event.target.value, cm: \"\" }));\n\t\t\t} else {\n\t\t\t\tsetLocalHeight((prev) => ({ ...prev, inch: event.target.value, cm: \"\" }));\n\t\t\t}\n\t\t},\n\t\t[measurementUnit],\n\t);\n\n\tconst handleMeasurementUnit = useCallback((event: any) => {\n\t\tconst val = event.target.value;\n\t\tsetMeasurementUnit(val);\n\t\tsetLocalHeight({ cm: \"\", ft: \"\", inch: \"\" });\n\t\tsetMessage(undefined);\n\t}, []);\n\n\tconst validateHeight = useCallback(\n\t\t(height: { cm: string; ft: string; inch: string }) => {\n\t\t\tif (measurementUnit === \"cm\") {\n\t\t\t\treturn !(+height.cm < 152.4 || +height.cm > 213.36);\n\t\t\t}\n\t\t\treturn !(convertToCentimeters(+height.ft, +height.inch) < 152.4 || convertToCentimeters(+height.ft, +height.inch) > 213.36);\n\t\t},\n\t\t[measurementUnit],\n\t);\n\n\tconst checkMeasurement = useCallback(async () => {\n\t\ttry {\n\t\t\tif (!validateHeight(localHeight)) {\n\t\t\t\tsetMessage(translate?.(LanguageKeys.heightError));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst height = { cm: +localHeight.cm, ft: +localHeight.ft, inch: +localHeight.inch };\n\t\t\tawait onStepComplete?.(height);\n\t\t\tonComplete?.(height);\n\t\t} catch (error) {\n\t\t\tsetMessage(handleErrorMessage(error));\n\t\t}\n\t}, [localHeight, validateHeight, onStepComplete]);\n\n\tconst isButtonDisabled = useMemo(() => (!localHeight.cm && !localHeight.ft && !localHeight.inch) || !!message, [localHeight, message]);\n\n\tuseEffect(() => {\n\t\tif (localHeight.cm === \"\" && localHeight.ft !== \"\") {\n\t\t\tsetMeasurementUnit(\"ft\");\n\t\t}\n\t}, [localHeight]);\n\n\tconst renderHeightInput = useCallback(() => {\n\t\tif (measurementUnit === \"cm\") {\n\t\t\treturn (\n\t\t\t\t<div className={`w-full`}>\n\t\t\t\t\t<CustomInput\n\t\t\t\t\t\trequired\n\t\t\t\t\t\ttype=\"number\"\n\t\t\t\t\t\tid=\"cm\"\n\t\t\t\t\t\tdata-testid=\"onboarding-height-input\"\n\t\t\t\t\t\tplaceholder={translate?.(LanguageKeys.height)}\n\t\t\t\t\t\tclassName=\"!pr-[10px]\"\n\t\t\t\t\t\tinputMode=\"numeric\"\n\t\t\t\t\t\tvalue={localHeight.cm}\n\t\t\t\t\t\tonChange={handleSetHeight}\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t);\n\t\t} else {\n\t\t\treturn (\n\t\t\t\t<div className=\"flex gap-[.5rem]\">\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<CustomInput\n\t\t\t\t\t\t\trequired\n\t\t\t\t\t\t\ttype=\"number\"\n\t\t\t\t\t\t\tid=\"ft\"\n\t\t\t\t\t\t\tclassName=\"!pr-[10px]\"\n\t\t\t\t\t\t\tplaceholder={translate?.(LanguageKeys.heightInFt)}\n\t\t\t\t\t\t\tvalue={localHeight.ft}\n\t\t\t\t\t\t\tonChange={handleSetHeight}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<CustomInput\n\t\t\t\t\t\t\trequired\n\t\t\t\t\t\t\ttype=\"number\"\n\t\t\t\t\t\t\tid=\"inch\"\n\t\t\t\t\t\t\tclassName=\"!pr-[10px]\"\n\t\t\t\t\t\t\tplaceholder={translate?.(LanguageKeys.heightInInch)}\n\t\t\t\t\t\t\tvalue={localHeight.inch}\n\t\t\t\t\t\t\tonChange={handleSetHeight}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\t}, [localHeight, preferredLanguage]);\n\n\treturn (\n\t\t<div className=\"h-full w-full\">\n\t\t\t<div className=\"mt-[3.5rem] mb-[.75rem]\">\n\t\t\t\t<div className=\"w-full flex gap-[.5rem]\">\n\t\t\t\t\t{renderHeightInput()}\n\t\t\t\t\t<Select\n\t\t\t\t\t\tclassName=\"bg-btn outline-none h-[40px] [&_svg]:text-base !shadow-none !outline-none !text-base\"\n\t\t\t\t\t\tvalue={measurementUnit}\n\t\t\t\t\t\tonChange={handleMeasurementUnit}\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tbackground: inputBg,\n\t\t\t\t\t\t\tcolor: inputText,\n\t\t\t\t\t\t\tfontSize: input?.inputFontSize || \"16px\",\n\t\t\t\t\t\t\tfontWeight: input?.inputFontWeight || \"400\",\n\t\t\t\t\t\t\tborder: `1px solid ${input?.inputBorderColor || \"transparent\"}`,\n\t\t\t\t\t\t\tfontFamily: config?.style?.base?.baseFontFamily || \"Inter, sans-serif\",\n\t\t\t\t\t\t\tborderRadius: input?.inputBorderRadius || \"4px\",\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t<MenuItem value=\"cm\">{translate?.(LanguageKeys.cmMeasurementUnit)}</MenuItem>\n\t\t\t\t\t\t<MenuItem value=\"ft\">{translate?.(LanguageKeys.ftMeasurementUnit)}</MenuItem>\n\t\t\t\t\t</Select>\n\t\t\t\t\t<style>\n\t\t\t\t\t\t{`\n .MuiOutlinedInput-notchedOutline {\n border: 1px solid ${input?.inputBorderColor || \"transparent\"} !important;\n outline: none;\n }\n .MuiSelect-select{\n outline: none;\n }\n .MuiSvgIcon-root{\n color: ${inputText} !important;\n }\n `}\n\t\t\t\t\t</style>\n\t\t\t\t</div>\n\t\t\t\t<div\n\t\t\t\t\tclassName=\"mt-2\"\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tcolor: input?.inputErrorColor || \"#000\",\n\t\t\t\t\t\tfontSize: input?.inputErrorFontSize || \"16px\",\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t{message}\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div className=\"flex justify-end\">\n\t\t\t\t<SpecificButton disabled={isButtonDisabled} data-testid=\"onboarding-next-btn\" buttonFunc={checkMeasurement} buttonText={translate?.(LanguageKeys.next)} postfixIcon={<ArrowRight size={14} />} />\n\t\t\t</div>\n\t\t</div>\n\t);\n};\n\nexport default HeightStep;\n","import React, { useMemo } from \"react\";\nimport { useConfig } from \"../../utils/context/configContext\";\n\ninterface ProgressDotsProps {\n totalSteps: number;\n currentStepIndex: number;\n}\n\nconst ProgressDots: React.FC<ProgressDotsProps> = ({ totalSteps, currentStepIndex }) => {\n const config = useConfig();\n const activeColor = config?.style?.base?.primaryColor || \"#000\";\n const inactiveColor = config?.style?.base?.secondaryColor || \"#D9D9D9\";\n\n const dots = useMemo(\n () =>\n Array.from({ length: totalSteps }, (_, i) => ({\n index: i,\n isActive: i === currentStepIndex,\n isCompleted: i < currentStepIndex\n })),\n [totalSteps, currentStepIndex]\n );\n\n return (\n <div className=\"flex justify-center items-center gap-[4px] my-[1.5rem]\">\n {dots.map(({ index, isActive, isCompleted }) => (\n <div\n key={index}\n className={`h-[3px] rounded-[9999px] transition-all duration-300 ${\n isActive ? \"w-[50px]\" : \"w-[30px]\"\n }`}\n style={{\n backgroundColor: isCompleted || isActive ? activeColor : inactiveColor\n }}\n />\n ))}\n </div>\n );\n};\n\nexport default ProgressDots;\n","import { useContext } from \"react\";\nimport EmailStep from \"./EmailStep\";\nimport NameStep from \"./NameStep\";\nimport GenderStep from \"./GenderStep\";\nimport HeightStep from \"./HeightStep\";\nimport { OnboardingStep } from \"../../utils/enums\";\nimport { Step } from \"../../types/interfaces\";\nimport { LanguageContext } from \"../../utils/context/languageContext\";\nimport { LanguageKeys } from \"../../utils/languageKeys\";\nimport ProgressDots from \"../../atoms/progressDots/ProgressDots\";\nimport { useConfig } from \"../../utils/context/configContext\";\n\nconst StepsWrapper = ({ currentStep, onStepDone, stepOrder, visibleSteps = [] }: { currentStep: Step; onStepDone: (val: any) => void; stepOrder: any; visibleSteps?: Step[] }) => {\n\tconst { translate } = useContext(LanguageContext) || {};\n\tconst resolvedConfig = useConfig();\n\n\tconst renderStep = () => {\n\t\tif (!currentStep) return null;\n\n\t\tconst commonProps = {\n\t\t\tresolvedConfig,\n\t\t\tinitialValue: currentStep.value,\n\t\t\tonComplete: onStepDone,\n\t\t\tonStepComplete: currentStep?.onStepComplete,\n\t\t};\n\n\t\tswitch (currentStep.type) {\n\t\t\tcase OnboardingStep.Email:\n\t\t\t\treturn <EmailStep {...commonProps} />;\n\t\t\tcase OnboardingStep.Name:\n\t\t\t\treturn <NameStep {...commonProps} />;\n\t\t\tcase OnboardingStep.Gender:\n\t\t\t\treturn <GenderStep {...commonProps} />;\n\t\t\tcase OnboardingStep.Height:\n\t\t\t\treturn <HeightStep {...commonProps} />;\n\t\t\tdefault:\n\t\t\t\treturn (\n\t\t\t\t\t<div>\n\t\t\t\t\t\t{translate?.(LanguageKeys.noValidSteps)} {currentStep.type}\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t}\n\t};\n\n\tif (!visibleSteps.length) return <div>{translate?.(LanguageKeys.unsupportedStep)}</div>;\n\n\t// stepOrder is the resolved visible-only list (from Onboarding.tsx),\n\t// so indexOf gives the correct 0-based position in the actual navigation flow.\n\tconst absoluteIndex = currentStep ? stepOrder.indexOf(currentStep.type) : 0;\n\n\treturn (\n\t\t<div data-testid=\"onboarding-root\" data-onboarding-step={absoluteIndex}>\n\t\t\t<div id=\"swan-onboarding-bg\" style={{ background: resolvedConfig?.style?.base?.backgroundColor }} className=\"fixed common-ui-main w-full h-full z-[0] pointer-events-none top-0 left-0\"></div>\n\n\t\t\t<div className=\"px-[15px] common-ui-main relative pt-[15px] w-full flex items-center flex-col\">\n\t\t\t\t<div className=\"max-w-[28rem] mx-auto w-full\">\n\t\t\t\t\t{/* Logo */}\n\t\t\t\t\t{resolvedConfig?.logo && (\n\t\t\t\t\t\t<div className=\"text-center mb-[1rem] flex justify-center\">\n\t\t\t\t\t\t\t<img\n\t\t\t\t\t\t\t\tsrc={resolvedConfig?.logo}\n\t\t\t\t\t\t\t\talt=\"logo\"\n\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\theight: resolvedConfig?.style?.logo?.logoHeight,\n\t\t\t\t\t\t\t\t\twidth: resolvedConfig?.style?.logo?.logoWidth,\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\tclassName=\"h-10 mx-auto\"\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\n\t\t\t\t\t{/* Progress Dots */}\n\t\t\t\t\t<ProgressDots totalSteps={stepOrder.length} currentStepIndex={absoluteIndex} />\n\n\t\t\t\t\t{/* Heading */}\n\t\t\t\t\t<h1\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tfontFamily: resolvedConfig?.style?.heading?.headingFontFamily || \"SeriouslyNostalgic Fn\",\n\t\t\t\t\t\t\tfontSize: resolvedConfig?.style?.heading?.headingFontSize || \"32px\",\n\t\t\t\t\t\t\tcolor: resolvedConfig?.style?.heading?.headingColor || \"#000\",\n\t\t\t\t\t\t\tfontWeight: resolvedConfig?.style?.heading?.headingFontWeight || \"normal\",\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tclassName=\"text-center pt-[1.5rem]\"\n\t\t\t\t\t>\n\t\t\t\t\t\t{translate?.(LanguageKeys.onboarding[currentStep?.type || \"heading\"])}\n\t\t\t\t\t</h1>\n\n\t\t\t\t\t{/* Step */}\n\t\t\t\t\t{renderStep()}\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t);\n};\n\nexport default StepsWrapper;\n","import Alcatel from \"./Alcatel.json\"\nimport Apple from \"./Apple.json\"\nimport CAT from \"./CAT.json\"\nimport Fairphone from \"./Fairphone.json\"\nimport Fujitsu from \"./Fujitsu.json\"\nimport Google from \"./Google.json\"\nimport Huawei from \"./Huawei.json\"\nimport iTel from \"./iTel.json\"\nimport Lava from \"./Lava.json\"\nimport Lg from \"./Lg.json\"\nimport Motorola from \"./Motorola.json\"\nimport NokiaHmd from \"./NokiaHmd.json\"\nimport Nothing from \"./Nothing.json\"\nimport Olla from \"./Olla.json\"\nimport Oneplus from \"./Oneplus.json\"\nimport Oppo from \"./Oppo.json\"\nimport Realme from \"./Realme.json\"\nimport Samsung from \"./Samsung.json\"\nimport Sharp from \"./Sharp.json\"\nimport Sony from \"./Sony.json\"\nimport Tecno from \"./Tecno.json\"\nimport Vivo from \"./Vivo.json\"\nimport Vsmart from \"./Vsmart.json\"\nimport Wiko from \"./Wiko.json\"\nimport Xiaomi from \"./Xiaomi.json\"\n\n\n\n\nconst DevicesList=[\n Alcatel,Apple,CAT,Fairphone,Fujitsu,Google,Huawei,iTel,Lava,Lg,Motorola,NokiaHmd,Nothing,Olla,Oneplus,Oppo,Realme,Samsung,Sharp,Sony,\n Tecno,Vivo,Vsmart,Wiko,Xiaomi\n\n]\n \n\nexport default DevicesList\n","\"use client\";\nimport React, { useState, useMemo, useCallback } from \"react\";\nimport { OnboardingProps } from \"../../types/interfaces\";\nimport { resolveSteps } from \"../../utils/utils\";\nimport LanguageContextProvider from \"../../utils/context/languageContext\";\nimport { ConfigProvider } from \"../../utils/context/configContext\";\nimport StepsWrapper from \"./StepsWrapper\";\nimport usePhoneDetection from \"../../customHooks/usePhoneDetection\";\n\nexport const Onboarding: React.FC<OnboardingProps> = ({ steps, config, onComplete, onDeviceDetected }) => {\n\tusePhoneDetection({ onDeviceDetected });\n\tconst visibleSteps = useMemo(() => resolveSteps(steps), [steps]);\n\tconst [values, setValues] = useState<Record<string, any>>({});\n\tconst [stepIndex, setStepIndex] = useState(0);\n\tconst currentStep = visibleSteps[stepIndex];\n\t// Hidden steps (isVisible:false) are placed first in stepOrder so they render\n\t// as pre-completed dots at the start of the progress bar. Visible steps follow\n\t// in their resolved (sorted) order. Because currentStep is always a visible step,\n\t// its indexOf position is always >= hiddenSteps.length, which means the first\n\t// N dots are permanently in \"completed\" state — no juggling, no backward jumps.\n\tconst hiddenSteps = steps.filter((s) => s.isVisible === false);\n\tconst stepOrder = [\n\t\t...hiddenSteps.map((s) => s.type),\n\t\t...visibleSteps.map((s) => s.type),\n\t];\n\n\t/** 4️⃣ Handle completion for a step */\n\tconst handleStepComplete = useCallback(\n\t\t(value: any) => {\n\t\t\tif (!currentStep) return;\n\t\t\tconst updated = { ...values, [currentStep.type]: value };\n\t\t\tsetValues(updated);\n\t\t\tif (stepIndex === visibleSteps.length - 1) {\n\t\t\t\tonComplete?.(updated);\n\t\t\t} else {\n\t\t\t\tsetStepIndex((prev) => prev + 1); // 👈 FIX\n\t\t\t}\n\t\t},\n\t\t[currentStep, values, stepIndex, visibleSteps.length, onComplete],\n\t);\n\n\tif (!visibleSteps.length) return <div>No steps configured for onboarding.</div>;\n\n\treturn (\n\t\t<LanguageContextProvider>\n\t\t\t<ConfigProvider config={config}>\n\t\t\t\t<StepsWrapper currentStep={currentStep} onStepDone={handleStepComplete} visibleSteps={visibleSteps} stepOrder={stepOrder} />\n\t\t\t</ConfigProvider>\n\t\t</LanguageContextProvider>\n\t);\n};\n","// Hook that auto-detects the user's phone model and focal length via WURFL.js (loaded dynamically).\n// Looks up the detected brand/model in DevicesList to find the camera focal length.\n// Falls back to manual selection if WURFL doesn't find a match in DevicesList.\n\nimport React, { useEffect } from \"react\";\nimport posthog from \"../utils/posthog\";\nimport DevicesList from \"../utils/deviceFocalLengthJson\";\n\ninterface DeviceInfo {\n brandName: string;\n modelName: string;\n focalLength: number;\n}\n\ninterface UsePhoneDetectionParams {\n onDeviceDetected?: (deviceInfo: { brandName: string; modelName: string; focalLength: number }) => void;\n}\n\nfunction usePhoneDetection({\n onDeviceDetected,\n}: UsePhoneDetectionParams): null {\n const handleWURFLDetectionComplete = () => {\n try {\n const wurfl = window?.WURFL;\n if (!wurfl) return;\n\n let phoneModel: { model_name: string; focal_length: number } | undefined;\n\n if (wurfl.brand_name === \"Apple\") {\n // WURFL returns generic \"iPhone\" for Apple — use a safe default focal length\n phoneModel = { model_name: \"iPhone\", focal_length: 23 };\n } else {\n for (const entry of DevicesList) {\n if (wurfl.brand_name in entry) {\n const models = (entry as Record<string, { model_name: string; focal_length: number }[]>)[wurfl.brand_name];\n phoneModel = models.find(\n (el) => el.model_name === wurfl.model_name || el.model_name === wurfl.marketing_name\n );\n if (phoneModel) break;\n }\n }\n }\n\n if (!phoneModel) return;\n const deviceInfo: DeviceInfo = {\n brandName: wurfl.brand_name,\n modelName: phoneModel.model_name,\n focalLength: phoneModel.focal_length,\n };\n\n onDeviceDetected?.({\n brandName: deviceInfo.brandName,\n modelName: deviceInfo.modelName,\n focalLength: deviceInfo.focalLength,\n });\n\n const payload: Record<string, any> = {\n type: \"auto\",\n data: JSON.stringify(deviceInfo),\n location:\"package\"\n };\n posthog.capture(`Phone Detection`, payload);\n } catch (error) {\n console.log(error, \"wurfl error\");\n }\n };\n\n useEffect(() => {\n try {\n document.addEventListener(\"WurflJSDetectionComplete\", handleWURFLDetectionComplete);\n const script = document.createElement(\"script\");\n script.src = \"//wjs.wurflcloud.com/wurfl.js\";\n script.async = true;\n document.head.appendChild(script);\n } catch (error) {\n console.log(\"error in getting device details\", error);\n }\n return () => {\n document.removeEventListener(\"WurflJSDetectionComplete\", handleWURFLDetectionComplete);\n };\n }, []);\n\n return null;\n}\n\nexport default usePhoneDetection;\n","import { useCallback, useContext, useState } from \"react\";\nimport { LanguageContext } from \"../../utils/context/languageContext\";\nimport Header from \"../Header\";\nimport { MenuItem, Select } from \"@mui/material\";\nimport SpecificButton from \"../../atoms/specificButton/SpecificButton\";\nimport { ArrowRight } from \"lucide-react\";\nimport { useConfig } from \"../../utils/context/configContext\";\nimport { FocalLengthProps } from \"../../types/interfaces\";\nimport DevicesList from \"../../utils/deviceFocalLengthJson\";\nimport { handleErrorMessage } from \"../../utils/utils\";\nimport { LanguageKeys } from \"../../utils/languageKeys\";\n\ntype PhoneModel = {\n\tid: number;\n\tmodel_name: string;\n\tfocal_length: number;\n};\n\ntype DeviceManufacturer = Record<string, PhoneModel[]>;\ntype DevicesListType = DeviceManufacturer[];\n\nconst FocalLengthWrapper = ({ onComplete }: Omit<FocalLengthProps, \"config\">) => {\n\tconst { translate } = useContext(LanguageContext) || {};\n\tconst resolvedConfig = useConfig();\n\tconst [deviceInfo, setDeviceInfo] = useState({\n\t\tbrandName: \"\",\n\t\tmodel: null as PhoneModel | null,\n\t});\n\tconst [message, setMessage] = useState<string | undefined>(undefined);\n\tconst [loading, setLoading] = useState(false);\n\n\t/* ------------ Brand Menu ------------ */\n\tconst manufacturerMenuItems = useCallback(() => {\n\t\treturn (DevicesList as DevicesListType).map((manufacturer) => {\n\t\t\tconst brandName = Object.keys(manufacturer)[0];\n\t\t\treturn (\n\t\t\t\t<MenuItem key={brandName} value={brandName}>\n\t\t\t\t\t{brandName}\n\t\t\t\t</MenuItem>\n\t\t\t);\n\t\t});\n\t}, []);\n\n\t/* ------------ Model Menu ------------ */\n\tconst phoneModelMenuItems = useCallback(() => {\n\t\tconst brandMatch = (DevicesList as DevicesListType).find((manufacturer) => {\n\t\t\tconst key = Object.keys(manufacturer)[0];\n\t\t\treturn key === deviceInfo.brandName;\n\t\t});\n\n\t\tif (!brandMatch) return null;\n\n\t\tconst key = Object.keys(brandMatch)[0];\n\t\tconst models = brandMatch[key];\n\n\t\treturn models.map((phone) => (\n\t\t\t<MenuItem key={phone.id} value={phone.id}>\n\t\t\t\t{phone.model_name}\n\t\t\t</MenuItem>\n\t\t));\n\t}, [deviceInfo.brandName]);\n\n\tconst handleSubmit = useCallback(async () => {\n\t\tsetLoading(true);\n\t\ttry {\n\t\t\tif (deviceInfo.brandName && deviceInfo.model) {\n\t\t\t\tawait onComplete?.({\n\t\t\t\t\tbrandName: deviceInfo.brandName,\n\t\t\t\t\tmodelName: deviceInfo.model.model_name,\n\t\t\t\t\tfocalLength: deviceInfo.model.focal_length,\n\t\t\t\t});\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tsetMessage(handleErrorMessage(error));\n\t\t} finally {\n\t\t\tsetLoading(false);\n\t\t}\n\t}, [deviceInfo]);\n\n\t/* ------------ Brand Change ------------ */\n\tconst handleBrandChange = (event: any) => {\n\t\tsetDeviceInfo({\n\t\t\tbrandName: event.target.value,\n\t\t\tmodel: null,\n\t\t});\n\t};\n\n\t/* ------------ Model Change ------------ */\n\tconst handleModelChange = (event: any) => {\n\t\tconst selectedId = event.target.value;\n\n\t\tconst brandMatch = (DevicesList as DevicesListType).find((m) => {\n\t\t\treturn Object.keys(m)[0] === deviceInfo.brandName;\n\t\t});\n\n\t\tif (!brandMatch) return;\n\n\t\tconst key = Object.keys(brandMatch)[0];\n\t\tconst models = brandMatch[key];\n\n\t\tconst foundModel = models.find((phone) => phone.id === selectedId);\n\n\t\tsetDeviceInfo((prev) => ({\n\t\t\t...prev,\n\t\t\tmodel: foundModel ?? null,\n\t\t}));\n\t};\n\n\n\treturn (\n\t\t<div\n\t\t\tdata-testid=\"focal-length-root\"\n\t\t\tclassName=\"h-full common-ui-main flex-col max-w-md mx-auto pt-[1rem] p-[15px] w-full flex justify-start items-start text-center rounded-t-[20px]\"\n\t\t\tstyle={{ background: resolvedConfig?.style?.base?.backgroundColor }}\n\t\t>\n\t\t\t<div className=\"w-full max-w-[28rem] mx-auto\">\n\t\t\t\t<Header subtitle={translate?.(LanguageKeys.phoneModel)} />\n\t\t\t\t<div className=\"text-left mb-[.25rem] mt-[1rem]\">{translate?.(LanguageKeys.selectPhoneBrand)}</div>\n\n\t\t\t\t<div data-testid=\"focal-length-brand-select\">\n\t\t\t\t\t<Select\n\t\t\t\t\t\tonChange={handleBrandChange}\n\t\t\t\t\t\tclassName=\"w-full h-[40px] !shadow-none !outline-none text-left\"\n\t\t\t\t\t\tvalue={deviceInfo.brandName}\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tbackground: resolvedConfig?.style?.input?.inputBackgroundColor || \"#F9FAFC\",\n\t\t\t\t\t\t\tcolor: resolvedConfig?.style?.input?.inputTextColor || \"#000\",\n\t\t\t\t\t\t\tfontSize: resolvedConfig?.style?.input?.inputFontSize || \"16px\",\n\t\t\t\t\t\t\tfontWeight: resolvedConfig?.style?.input?.inputFontWeight || \"400\",\n\t\t\t\t\t\t\tborder: `1px solid ${resolvedConfig?.style?.input?.inputBorderColor || \"transparent\"}`,\n\t\t\t\t\t\t\tfontFamily: resolvedConfig?.style?.base?.baseFontFamily || \"Inter, sans-serif\",\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t{manufacturerMenuItems()}\n\t\t\t\t\t</Select>\n\t\t\t\t</div>\n\n\t\t\t\t<div className=\"text-left mb-[.25rem] mt-[1rem]\">{translate?.(LanguageKeys.selectPhoneModel)}</div>\n\n\t\t\t\t<div data-testid=\"focal-length-model-select\">\n\t\t\t\t\t<Select\n\t\t\t\t\t\tonChange={handleModelChange}\n\t\t\t\t\t\tclassName=\"w-full bg-btn h-[40px] !shadow-none !outline-none text-left\"\n\t\t\t\t\t\tvalue={deviceInfo.model?.id || \"\"}\n\t\t\t\t\t\tdisabled={!deviceInfo.brandName}\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tbackground: resolvedConfig?.style?.input?.inputBackgroundColor || \"#F9FAFC\",\n\t\t\t\t\t\t\tcolor: resolvedConfig?.style?.input?.inputTextColor || \"#000\",\n\t\t\t\t\t\t\tfontSize: resolvedConfig?.style?.input?.inputFontSize || \"16px\",\n\t\t\t\t\t\t\tfontWeight: resolvedConfig?.style?.input?.inputFontWeight || \"400\",\n\t\t\t\t\t\t\tborder: `1px solid ${resolvedConfig?.style?.input?.inputBorderColor || \"transparent\"}`,\n\t\t\t\t\t\t\tfontFamily: resolvedConfig?.style?.base?.baseFontFamily || \"Inter, sans-serif\",\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t{phoneModelMenuItems()}\n\t\t\t\t\t</Select>\n\t\t\t\t</div>\n\t\t\t\t<style>\n\t\t\t\t\t{`\n .MuiOutlinedInput-notchedOutline {\n border: 1px solid ${resolvedConfig?.style?.input?.inputBorderColor || \"transparent\"} !important;\n outline: none;\n }\n .MuiSelect-select{\n outline: none;\n }\n \n `}\n\t\t\t\t</style>\n\t\t\t\t{message && <p className=\"mt-[0.2rem] text-[16px]\">{message}</p>}\n\t\t\t</div>\n\n\t\t\t<div className=\"mt-[.75rem] mb-[1.25rem] max-w-[28rem] mx-auto w-full flex justify-end\">\n\t\t\t\t<SpecificButton\n\t\t\t\t\tdisabled={!deviceInfo?.brandName || !deviceInfo?.model || loading}\n\t\t\t\t\tdata-testid=\"focal-length-next-btn\"\n\t\t\t\t\tpostfixIcon={<ArrowRight />}\n\t\t\t\t\tbuttonFunc={handleSubmit}\n\t\t\t\t\tbuttonText={translate?.(LanguageKeys.next)}\n\t\t\t\t/>\n\t\t\t</div>\n\t\t</div>\n\t);\n};\n\nexport default FocalLengthWrapper;\n","import React from \"react\";\nimport FocalLengthWrapper from \"./FocalLengthWrapper\";\nimport { FocalLengthProps } from \"../../types/interfaces\";\nimport LanguageContextProvider from \"../../utils/context/languageContext\";\nimport { ConfigProvider } from \"../../utils/context/configContext\";\n\nexport const FocalLength: React.FC<FocalLengthProps> = ({\n onComplete,\n config,\n}: FocalLengthProps) => {\n return (\n <LanguageContextProvider>\n <ConfigProvider config={config}>\n <FocalLengthWrapper\n onComplete={onComplete}\n />\n </ConfigProvider>\n </LanguageContextProvider>\n );\n};\n","import React from \"react\";\nimport { motion, AnimatePresence } from \"framer-motion\";\n\nexport default function MuseScreenRenderer({\n\tscreenIndex,\n\tscanLinePosition,\n\tfaceZoomed,\n\tshowFaceScanLine,\n\tfaceScanLinePosition,\n\tshowLargeS,\n\ttypewriterText,\n\tfullText,\n\tscreens,\n\tvideoToShow,\n\tfaceScanVideo,\n\tsizeVideo,\n\tformFittingVideo,\n}: any) {\n\tconst screen = screens[screenIndex];\n\n\t// Map screen id to props for each component\n\tconst componentProps: any = {\n\t\tbody: { scanLinePosition, videoToShow },\n\t\tface: {\n\t\t\tfaceZoomed,\n\t\t\tshowFaceScanLine,\n\t\t\tfaceScanLinePosition,\n\t\t\tfaceScanVideo,\n\t\t},\n\t\tsizeFit: { showLargeS, typewriterText, fullText, sizeVideo },\n\t};\n\n\tconst hasComponent = !!screen.component;\n\tconst Comp = hasComponent ? screen.component : null;\n\n\tlet content = null;\n\tif (hasComponent) {\n\t\tcontent = React.createElement(Comp.type || Comp, componentProps[screen.id] || {});\n\t} else if (screen.image) {\n\t\tcontent = (\n\t\t\t<video className=\"h-full w-full object-contain border-none\" muted loop autoPlay playsInline preload=\"auto\">\n\t\t\t\t<source src={formFittingVideo} type=\"video/mp4\" />\n\t\t\t</video>\n\t\t);\n\t}\n\n\treturn (\n\t\t<AnimatePresence mode=\"wait\">\n\t\t\t<motion.div key={screenIndex} initial={{ opacity: 0, y: 20 }} animate={{ opacity: 1, y: 0 }} exit={{ opacity: 0, y: -20 }} transition={{ duration: 0.4 }} className=\"w-full h-full\">\n\t\t\t\t{content}\n\t\t\t</motion.div>\n\t\t</AnimatePresence>\n\t);\n}\n","import { ArrowRight } from \"lucide-react\";\nimport BodyScanAnimation from \"./BodyScanAnimation\";\nimport FaceScanAnimation from \"./FaceScanAnimation\";\nimport TypewriterScene from \"./TypewritterScene\";\nimport { useContext, useMemo, useState } from \"react\";\nimport MuseScreenRenderer from \"./MuseScreenRenderer\";\nimport Header from \"../../Header\";\nimport { GenderType, MuseScreenStep } from \"../../../utils/enums\";\nimport {\n\tbodyScanPerson,\n\tfaceScanPerson,\n\tfaceScanVideo,\n\tfemaleScanVideo,\n\tfittingGuide,\n\tformFittingGuide,\n\tfullText,\n\tleSableDress,\n\tmaleFaceScanVideo,\n\tmaleFormFittingGuide,\n\tmaleScanVideo,\n\tmaleSizeSuggestions,\n\tOUTFIT_IMAGES,\n\tsizeSuggestions,\n} from \"../../..//utils/constants\";\nimport { MuseStepsProps } from \"../../../types/interfaces\";\nimport useMuseAnimations from \"../../../customHooks/useMuseAnimation\";\nimport SpecificButton from \"../../../atoms/specificButton/SpecificButton\";\nimport { LanguageKeys } from \"../../../utils/languageKeys\";\nimport { LanguageContext } from \"../../../utils/context/languageContext\";\nimport { useConfig } from \"../../../utils/context/configContext\";\n\nconst screens: {\n\tid: string;\n\ttitle: string;\n\tdescription: string;\n\timage: string;\n\tcomponent?: React.ReactNode;\n}[] = [\n\t{\n\t\tid: MuseScreenStep.Body,\n\t\ttitle: LanguageKeys.bodyScan,\n\t\tdescription: LanguageKeys.bodyScanDescription,\n\t\timage: bodyScanPerson,\n\t\tcomponent: <BodyScanAnimation />,\n\t},\n\t{\n\t\tid: MuseScreenStep.Face,\n\t\ttitle: LanguageKeys.faceScan,\n\t\tdescription: LanguageKeys.faceScanDescription,\n\t\timage: faceScanPerson,\n\t\tcomponent: <FaceScanAnimation />,\n\t},\n\t{\n\t\tid: MuseScreenStep.SizeFit,\n\t\ttitle: LanguageKeys.sizeFit,\n\t\tdescription: \"\",\n\t\timage: leSableDress,\n\t\tcomponent: <TypewriterScene />,\n\t},\n\t{\n\t\tid: MuseScreenStep.Ready,\n\t\ttitle: LanguageKeys.readyToStart,\n\t\tdescription: LanguageKeys.readyToStartDescription,\n\t\timage: fittingGuide,\n\t},\n];\n\nexport default function MuseSteps({ applicableScreens, gender, onNext, isCustom }: Omit<MuseStepsProps, \"config\">) {\n\tconst { translate } = useContext(LanguageContext) || {};\n\tconst config = useConfig();\n\tconst [currentScreen, setCurrentScreen] = useState(0);\n\tconst [scanLinePosition, setScanLinePosition] = useState(0);\n\tconst [faceZoomed, setFaceZoomed] = useState(false);\n\tconst [faceScanLinePosition, setFaceScanLinePosition] = useState(0);\n\tconst [showFaceScanLine, setShowFaceScanLine] = useState(false);\n\tconst [currentOutfit, setCurrentOutfit] = useState(0);\n\tconst [typewriterText, setTypewriterText] = useState(\"\");\n\tconst [showLargeS, setShowLargeS] = useState(false);\n\n\tconst screensToShow = useMemo(() => {\n\t\tif (isCustom) {\n\t\t\treturn screens.reduce((acc: any, el) => {\n\t\t\t\tif ([\"face\", \"sizeFit\"].includes(el.id)) {\n\t\t\t\t\treturn acc;\n\t\t\t\t}\n\t\t\t\tacc.push(el);\n\t\t\t\treturn acc;\n\t\t\t}, []);\n\t\t}\n\t\tif (!applicableScreens?.length) {\n\t\t\treturn screens;\n\t\t}\n\t\treturn screens.filter((screen) => applicableScreens.includes(screen.id));\n\t}, [applicableScreens]);\n\n\tuseMuseAnimations({\n\t\tscreenId: screensToShow[currentScreen].id,\n\t\tsetScanLinePosition,\n\t\tsetFaceZoomed,\n\t\tsetShowFaceScanLine,\n\t\tsetFaceScanLinePosition,\n\t\tsetCurrentOutfit,\n\t\tsetTypewriterText,\n\t\tsetShowLargeS,\n\t\toutfitImages: OUTFIT_IMAGES,\n\t\tfullText,\n\t});\n\n\tconst onNextClick = () => {\n\t\tif (currentScreen < screensToShow.length - 1) {\n\t\t\tsetCurrentScreen((prev) => prev + 1);\n\t\t} else {\n\t\t\tonNext?.();\n\t\t}\n\t};\n\treturn (\n\t\t<div data-testid=\"educational-root\" data-educational-step=\"1\" className=\"relative common-ui-main h-full max-w-[28rem] mx-auto w-full flex justify-center\" style={{ background: config?.style?.base?.backgroundColor }}>\n\t\t\t<div className=\"absolute bottom-0 left-0 right-0 h-full shadow-lg w-full\">\n\t\t\t\t<div className=\"h-full flex flex-col p-[1rem] w-full\">\n\t\t\t\t\t<Header noTitle />\n\t\t\t\t\t<div className=\"text-center pb-[.5rem]\">\n\t\t\t\t\t\t<h1\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\tfontFamily: config?.style?.heading?.headingFontFamily || \"SeriouslyNostalgic Fn\",\n\t\t\t\t\t\t\t\tfontSize: config?.style?.heading?.headingFontSize || \"32px\",\n\t\t\t\t\t\t\t\tcolor: config?.style?.heading?.headingColor || \"#000\",\n\t\t\t\t\t\t\t\tfontWeight: config?.style?.heading?.headingFontWeight || \"normal\",\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{translate?.(screensToShow[currentScreen].title)}\n\t\t\t\t\t\t</h1>\n\t\t\t\t\t\t{screensToShow[currentScreen].description && (\n\t\t\t\t\t\t\t<p\n\t\t\t\t\t\t\t\tclassName=\" mt-[.25rem] max-w-[280px] mx-auto min-h-[40px]\"\n\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\tfontFamily: config?.style?.subheading?.subheadingFontFamily || \"'Inter', sans-serif\",\n\t\t\t\t\t\t\t\t\tfontSize: config?.style?.subheading?.subheadingFontSize || \"14px\",\n\t\t\t\t\t\t\t\t\tcolor: config?.style?.subheading?.subheadingColor || \"#4b5563\",\n\t\t\t\t\t\t\t\t\tfontWeight: config?.style?.subheading?.subheadingFontWeight || \"normal\",\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{translate?.(screensToShow[currentScreen].description)}\n\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t\t<div className=\"flex-1 flex justify-center items-center overflow-hidden py-[1rem] relative\">\n\t\t\t\t\t\t<MuseScreenRenderer\n\t\t\t\t\t\t\tscreenIndex={currentScreen}\n\t\t\t\t\t\t\tscanLinePosition={scanLinePosition}\n\t\t\t\t\t\t\tfaceZoomed={faceZoomed}\n\t\t\t\t\t\t\tshowFaceScanLine={showFaceScanLine}\n\t\t\t\t\t\t\tfaceScanLinePosition={faceScanLinePosition}\n\t\t\t\t\t\t\toutfitImages={OUTFIT_IMAGES}\n\t\t\t\t\t\t\tcurrentOutfit={currentOutfit}\n\t\t\t\t\t\t\tshowLargeS={showLargeS}\n\t\t\t\t\t\t\ttypewriterText={typewriterText}\n\t\t\t\t\t\t\tfullText={fullText}\n\t\t\t\t\t\t\tscreens={screensToShow}\n\t\t\t\t\t\t\tvideoToShow={gender === GenderType.Male ? maleScanVideo : femaleScanVideo}\n\t\t\t\t\t\t\tfaceScanVideo={gender === GenderType.Male ? maleFaceScanVideo : faceScanVideo}\n\t\t\t\t\t\t\tsizeVideo={gender === GenderType.Male ? maleSizeSuggestions : sizeSuggestions}\n\t\t\t\t\t\t\tformFittingVideo={gender === GenderType.Male ? maleFormFittingGuide : formFittingGuide}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<div className=\"pt-[.5rem] flex justify-end\">\n\t\t\t\t\t\t<SpecificButton buttonText={translate?.(LanguageKeys.next)} type=\"submit\" data-testid=\"educational-next-btn\" postfixIcon={<ArrowRight size={14} />} buttonFunc={onNextClick} />\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n","export default function BodyScanAnimation({\n videoToShow,\n}: {\n videoToShow?: string;\n}) {\n return (\n <div className=\"relative w-full h-full common-ui-main\">\n <video\n className=\"h-full w-full object-contain border-none\"\n muted\n autoPlay\n loop\n playsInline\n >\n <source src={videoToShow} type=\"video/mp4\" />\n </video>\n </div>\n );\n}\n","import { FaceScanAnimationProps } from \"../../../types/interfaces\";\n\nexport default function FaceScanAnimation({\n faceZoomed,\n showFaceScanLine,\n faceScanLinePosition,\n faceScanVideo,\n}: FaceScanAnimationProps) {\n return (\n <div className=\"relative h-full w-full common-ui-main\">\n <div className=\"w-full h-full relative\">\n <video\n className=\"h-full w-full object-contain border-none\"\n muted\n autoPlay\n playsInline\n >\n <source src={faceScanVideo} type=\"video/mp4\" />\n </video>\n {showFaceScanLine && faceZoomed && (\n <div\n className=\"absolute w-[1px] bg-[#8B5CF6] shadow-[0_0_8px_rgba(139,92,246,0.8)] z-20\"\n style={{\n left: `${faceScanLinePosition}%`,\n top: \"0%\",\n height: \"40%\",\n opacity:\n faceScanLinePosition && faceScanLinePosition >= 0 ? 1 : 0,\n }}\n />\n )}\n </div>\n </div>\n );\n}\n","export default function TypewriterScene({ sizeVideo }: { sizeVideo?: string }) {\n return (\n <div className=\"relative common-ui-main w-full h-full flex justify-center items-center\">\n <video\n className=\"h-full w-full object-contain border-none\"\n muted\n loop\n autoPlay\n playsInline\n >\n <source src={sizeVideo} type=\"video/mp4\" />\n </video>\n </div>\n );\n}\n","import { useEffect, useRef } from \"react\";\n\nfunction useMuseAnimations({\n screenId,\n setScanLinePosition,\n setFaceZoomed,\n setShowFaceScanLine,\n setFaceScanLinePosition,\n setCurrentOutfit,\n outfitImages,\n setTypewriterText,\n setShowLargeS,\n fullText,\n}: any) {\n const animationRefs = useRef<any>({\n scan: null,\n face: null,\n outfit: null,\n typewriter: null,\n });\n\n const cleanupAnimations = () => {\n Object.values(animationRefs.current).forEach((ref: any) => {\n if (typeof ref === \"number\") {\n cancelAnimationFrame(ref);\n } else if (ref) {\n clearTimeout(ref);\n clearInterval(ref);\n }\n });\n animationRefs.current = {\n scan: null,\n face: null,\n outfit: null,\n typewriter: null,\n };\n };\n\n useEffect(() => {\n cleanupAnimations();\n\n switch (screenId) {\n case \"body\": {\n const startTime = Date.now();\n const duration = 3000;\n\n const animateScanLine = () => {\n const elapsed = Date.now() - startTime;\n const progress = Math.min(elapsed / duration, 1);\n setScanLinePosition(progress * 100);\n if (progress < 1) {\n animationRefs.current.scan = requestAnimationFrame(animateScanLine);\n }\n };\n\n animationRefs.current.scan = requestAnimationFrame(animateScanLine);\n break;\n }\n\n case \"face\": {\n setFaceZoomed(false);\n setShowFaceScanLine(false);\n setFaceScanLinePosition(0);\n\n animationRefs.current.face = setTimeout(() => {\n setFaceZoomed(true);\n\n setTimeout(() => {\n setShowFaceScanLine(true);\n\n const startTime = Date.now();\n const duration = 6000; // ✅ Total 6s (3s for each direction)\n\n const animateFaceScanLine = () => {\n const elapsed = Date.now() - startTime;\n const progress = Math.min(elapsed / duration, 1);\n\n setFaceScanLinePosition(\n progress <= 0.5 ? progress * 2 * 100 : (2 - progress * 2) * 100\n );\n\n if (progress < 1) {\n animationRefs.current.face =\n requestAnimationFrame(animateFaceScanLine);\n }\n };\n\n animationRefs.current.face =\n requestAnimationFrame(animateFaceScanLine);\n }, 2500); // Delay after zoom\n }, 800); // Delay before zoom\n break;\n }\n\n case \"sizeFit\": {\n setCurrentOutfit(0);\n animationRefs.current.outfit = setInterval(() => {\n setCurrentOutfit((prev: any) => (prev + 1) % outfitImages.length);\n }, 1500);\n break;\n }\n\n case \"ready\": {\n setShowLargeS(false);\n setTypewriterText(\"\");\n\n animationRefs.current.typewriter = setTimeout(() => {\n setShowLargeS(true);\n setTimeout(() => {\n let currentIndex = 0;\n const typeNextChar = () => {\n if (currentIndex < fullText.length) {\n setTypewriterText(fullText.slice(0, currentIndex + 1));\n currentIndex++;\n animationRefs.current.typewriter = setTimeout(typeNextChar, 30);\n }\n };\n typeNextChar();\n }, 1000);\n }, 800);\n break;\n }\n\n default:\n break;\n }\n\n return cleanupAnimations;\n }, [screenId]);\n}\n\nexport default useMuseAnimations;\n","import { ArrowRight, Volume2 } from \"lucide-react\";\nimport { useState, useEffect, useContext } from \"react\";\nimport Header from \"../Header\";\nimport { LanguageContext } from \"../../utils/context/languageContext\";\nimport { LanguageKeys } from \"../../utils/languageKeys\";\nimport SpecificButton from \"../../atoms/specificButton/SpecificButton\";\nimport { useConfig } from \"../../utils/context/configContext\";\n\ninterface VolumeStepProps {\n onNext: () => void;\n}\n\nexport default function VolumeScreen({ onNext }: VolumeStepProps) {\n const { translate } = useContext(LanguageContext) || {};\n const config = useConfig();\n const [mousePosition, setMousePosition] = useState({ x: 0, y: 0 });\n const [isAnimationPaused, setIsAnimationPaused] = useState(false);\n\n useEffect(() => {\n const handleMouseMove = (e: any) => {\n setMousePosition({ x: e.clientX, y: e.clientY });\n };\n window.addEventListener(\"mousemove\", handleMouseMove);\n return () => window.removeEventListener(\"mousemove\", handleMouseMove);\n }, []);\n\n const toggleAnimationPause = () => {\n setIsAnimationPaused((prev) => !prev);\n };\n\n function hexToRgba(hex: string, alpha: number = 1): string {\n hex = hex.replace(\"#\", \"\");\n if (hex.length === 3) {\n hex = hex.split(\"\").map((h) => h + h).join(\"\");\n }\n const r = parseInt(hex.substring(0, 2), 16);\n const g = parseInt(hex.substring(2, 4), 16);\n const b = parseInt(hex.substring(4, 6), 16);\n return `rgba(${r}, ${g}, ${b}, ${alpha})`;\n }\n\n const brandColor = config?.style?.base?.brandColor || \"#000\";\n const rgba1 = hexToRgba(brandColor, 0.19);\n const rgba2 = hexToRgba(brandColor, 0.23);\n const rgba3 = hexToRgba(brandColor, 0.24);\n\n const calculateHolographicEffect = () => {\n const windowWidth = typeof window !== \"undefined\" ? window.innerWidth : 1000;\n const windowHeight = typeof window !== \"undefined\" ? window.innerHeight : 1000;\n const normalizedX = (mousePosition.x / windowWidth) * 2 - 1;\n const normalizedY = (mousePosition.y / windowHeight) * 2 - 1;\n const rotateX = normalizedY * 5;\n const rotateY = normalizedX * -5;\n return {\n transform: `perspective(1000px) rotateX(${rotateX}deg) rotateY(${rotateY}deg)`,\n background: \"#fff\",\n boxShadow: `0 0 20px ${rgba1}, 0 0 30px ${rgba2}`,\n };\n };\n\n const holographicStyle = calculateHolographicEffect();\n\n return (\n <div\n data-testid=\"educational-root\"\n data-educational-step=\"2\"\n className=\"flex h-full max-w-[28rem] mx-auto w-full flex-col relative items-center justify-center overflow-hidden max-w-md mx-auto bg-primary text-base\"\n style={{ background: config?.style?.base?.backgroundColor }}\n >\n <div className=\"flex justify-start absolute z-[99] top-[1rem] max-w-md mx-auto w-full px-[1rem]\">\n <Header noTitle />\n </div>\n <div className=\"relative mb-[2rem]\">\n {[...Array(3)].map((_, i) => (\n <div\n key={i}\n className=\"absolute rounded-[9999px]\"\n style={{\n width: \"100px\",\n height: \"100px\",\n minHeight: \"100px\",\n minWidth: \"100px\",\n background: config?.style?.base?.backgroundColor || \"#fff\",\n boxShadow: `0 0 20px 2px ${rgba3}`,\n border: \"none\",\n filter: \"blur(1px)\",\n margin: \"0 auto\",\n left: \"50%\",\n top: \"50%\",\n animation: isAnimationPaused\n ? \"none\"\n : `gentleRipple 15s cubic-bezier(0.1, 0.5, 0.2, 1) ${i * 5}s infinite`,\n opacity: isAnimationPaused ? 1 : 0,\n transform: isAnimationPaused\n ? \"translate(-50%, -50%) scale(0.5)\"\n : \"translate(-50%, -50%)\",\n }}\n />\n ))}\n <div\n className=\"relative z-10 rounded-[9999px] p-[1.5rem] cursor-pointer transition-all backdrop-blur-sm\"\n style={{\n ...holographicStyle,\n transition: \"transform 0.1s ease-out, box-shadow 0.1s ease-out\",\n }}\n onClick={toggleAnimationPause}\n >\n <Volume2\n className=\"w-[3rem] h-[3rem] relative z-10\"\n style={{ filter: \"drop-shadow(0 0 5px rgba(255, 255, 255, 0.7))\" }}\n color={config?.style?.base?.primaryColor || \"#000\"}\n />\n </div>\n </div>\n\n <div className=\"relative z-10 text-center max-w-[20rem]\">\n <div\n className=\" mb-[.5rem]\"\n style={{\n fontFamily: config?.style?.subheading?.subheadingFontFamily || \"'Inter', sans-serif\",\n fontSize: config?.style?.subheading?.subheadingFontSize || \"14px\",\n color: config?.style?.subheading?.subheadingColor || \"#4b5563\",\n fontWeight: config?.style?.subheading?.subheadingFontWeight || \"normal\",\n }}\n >\n {translate?.(LanguageKeys.turnUpVolume)}\n </div>\n </div>\n\n <div className=\"absolute bottom-[1rem] right-0 max-w-[28rem] mx-auto w-full px-[1rem] max-w-md mx-auto\">\n <div className=\"flex justify-end\">\n <SpecificButton\n buttonFunc={() => onNext()}\n data-testid=\"educational-next-btn\"\n postfixIcon={<ArrowRight />}\n buttonText={translate?.(LanguageKeys.continue)}\n />\n </div>\n </div>\n <style>{`\n @keyframes gentleRipple {\n 0% {\n transform: translate(-50%, -50%) scale(0.5) translateZ(0);\n opacity: 0.7;\n }\n 50% {\n opacity: 0.4;\n }\n 100% {\n transform: translate(-50%, -50%) scale(25) translateZ(0);\n opacity: 0;\n }\n }\n`}</style>\n </div>\n );\n}\n","import { useContext } from \"react\";\nimport { ArrowRight } from \"lucide-react\";\nimport Header from \"../Header\";\nimport { maleSetupVideo, setupVideo } from \"../../utils/constants\";\nimport { LanguageContext } from \"../../utils/context/languageContext\";\nimport { LanguageKeys } from \"../../utils/languageKeys\";\nimport { GenderType } from \"../../utils/enums\";\nimport SpecificButton from \"../../atoms/specificButton/SpecificButton\";\nimport { useConfig } from \"../../utils/context/configContext\";\nimport { Gender } from \"../../types/interfaces\";\n\ninterface SetupScreenProps {\n gender: Gender;\n onNext?: () => void;\n}\n\nexport default function SetupScreen({ gender, onNext }: SetupScreenProps) {\n\tconst { translate } = useContext(LanguageContext) || {};\n\tconst config = useConfig();\n\n\treturn (\n\t\t<div\n\t\t\tdata-testid=\"educational-root\"\n\t\t\tdata-educational-step=\"3\"\n\t\t\tclassName=\"flex h-full max-w-[28rem] mx-auto w-full p-[1rem] common-ui-main relative flex-col items-center overflow-hidden max-w-md mx-auto bg-primary text-base\"\n\t\t\tstyle={{ background: config?.style?.base?.backgroundColor }}\n\t\t>\n\t\t\t<div className=\"flex justify-start max-w-md mx-auto w-full \">\n\t\t\t\t<Header noTitle />\n\t\t\t</div>\n\t\t\t<h2\n\t\t\t\tclassName=\"mb-[1rem] text-[32px]\"\n\t\t\t\tstyle={{\n\t\t\t\t\tfontFamily: config?.style?.heading?.headingFontFamily || \"SeriouslyNostalgic Fn\",\n\t\t\t\t\tfontSize: config?.style?.heading?.headingFontSize || \"32px\",\n\t\t\t\t\tcolor: config?.style?.heading?.headingColor || \"#000\",\n\t\t\t\t\tfontWeight: config?.style?.heading?.headingFontWeight || \"normal\",\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t{translate?.(LanguageKeys.phonePlacement)}\n\t\t\t</h2>\n\t\t\t<p\n\t\t\t\tclassName=\"text-center text-gray-600 text-sm mt-1 max-w-[280px] mx-auto min-h-[40px]\"\n\t\t\t\tstyle={{\n\t\t\t\t\tfontFamily: config?.style?.subheading?.subheadingFontFamily || \"'Inter', sans-serif\",\n\t\t\t\t\tfontSize: config?.style?.subheading?.subheadingFontSize || \"14px\",\n\t\t\t\t\tcolor: config?.style?.subheading?.subheadingColor || \"#4b5563\",\n\t\t\t\t\tfontWeight: config?.style?.subheading?.subheadingFontWeight || \"normal\",\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t{translate?.(LanguageKeys.phonePlacementDescription)}\n\t\t\t</p>\n\t\t\t<div className=\"relative w-full h-full flex flex-col items-center max-w-md pt-[1rem]\">\n\t\t\t\t<div className=\"relative w-full h-auto\">\n\t\t\t\t\t<video className=\"h-full w-full object-contain border-none\" muted loop autoPlay playsInline>\n\t\t\t\t\t\t<source src={gender === GenderType.Male ? maleSetupVideo : setupVideo} type=\"video/mp4\" />\n\t\t\t\t\t</video>\n\t\t\t\t</div>\n\n\t\t\t\t<div className=\"absolute bottom-[0] max-w-[28rem] mx-auto w-full left-0 right-0 flex justify-center max-w-md mx-auto\">\n\t\t\t\t\t<div className=\"flex justify-end w-full\">\n\t\t\t\t\t\t<SpecificButton buttonFunc={() => onNext?.()} data-testid=\"educational-next-btn\" buttonText={translate?.(LanguageKeys.continue)} postfixIcon={<ArrowRight />} />\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n","import { useState } from \"react\";\nimport MuseSteps from \"./MuseSteps\";\nimport VolumeStep from \"./VolumeStep\";\nimport SetupScreen from \"./SetupScreen\";\nimport { EducationalProps } from \"../../types/interfaces\";\nimport { GenderType, MuseScreenStep, SectionType } from \"../../utils/enums\";\n\nconst EducationalStepsWrapper = ({ sections, gender, onComplete, isCustom, startStep }: EducationalProps) => {\n\tconst [step, setStep] = useState(startStep ?? 1);\n\n\tswitch (step) {\n\t\tcase 1:\n\t\t\treturn (\n\t\t\t\t<MuseSteps\n\t\t\t\t\tapplicableScreens={\n\t\t\t\t\t\tsections?.[0] === SectionType.Full || !sections || !sections?.length\n\t\t\t\t\t\t\t? undefined\n\t\t\t\t\t\t\t: sections[0] === SectionType.Body\n\t\t\t\t\t\t\t? [MuseScreenStep.Body, MuseScreenStep.SizeFit, MuseScreenStep.Ready]\n\t\t\t\t\t\t\t: [MuseScreenStep.Face, MuseScreenStep.SizeFit]\n\t\t\t\t\t}\n\t\t\t\t\tisCustom={isCustom}\n\t\t\t\t\tgender={gender || GenderType.Male}\n\t\t\t\t\tonNext={() => setStep(2)}\n\t\t\t\t/>\n\t\t\t);\n\n\t\tcase 2:\n\t\t\treturn <VolumeStep onNext={() => (sections?.[0] === SectionType.Face ? onComplete?.() : setStep(3))} />;\n\n\t\tcase 3:\n\t\t\treturn <SetupScreen gender={gender || GenderType.Male} onNext={onComplete} />;\n\n\t\tdefault:\n\t\t\treturn <></>;\n\t}\n};\n\nexport default EducationalStepsWrapper;\n","import { EducationalProps } from \"../../types/interfaces\";\nimport { GenderType } from \"../../utils/enums\";\nimport EducationalStepsWrapper from \"./EducationalStepsWrapper\";\nimport LanguageContextProvider from \"../../utils/context/languageContext\";\nimport { ConfigProvider } from \"../../utils/context/configContext\";\n\nexport const Educational: React.FC<EducationalProps> = ({\n sections = [],\n config,\n gender = GenderType.Male,\n onComplete,\n isCustom,\n startStep,\n}) => {\n return (\n <LanguageContextProvider>\n <ConfigProvider config={config}>\n <EducationalStepsWrapper\n sections={sections}\n gender={gender}\n onComplete={onComplete}\n isCustom={isCustom}\n startStep={startStep}\n />\n </ConfigProvider>\n </LanguageContextProvider>\n );\n};\n"],"names":["cn","classes","filter","Boolean","join","CustomInput","React","forwardRef","className","type","props","ref","config","useConfig","input","style","priority","_jsxs","_Fragment","children","_jsx","autoCapitalize","autoCorrect","background","inputBackgroundColor","color","inputTextColor","fontSize","inputFontSize","fontWeight","inputFontWeight","border","inputBorderColor","fontFamily","base","baseFontFamily","borderRadius","inputBorderRadius","inputPlaceholderColor","displayName","EmailStep","onComplete","initialValue","onStepComplete","value","setValue","useState","message","setMessage","undefined","loading","setLoading","translate","useContext","LanguageContext","onSubmit","async","e","preventDefault","trim","LanguageKeys","emailRequired","isValidEmail","validEmail","error","handleErrorMessage","required","id","placeholder","enterEmail","onChange","target","inputErrorColor","inputErrorFontSize","SpecificButton","disabled","buttonText","next","postfixIcon","ArrowRight","size","NameStep","nameRequired","enterName","GenderStep","genderType","setGenderType","bgColor","textColor","selectedBgColor","inputBackgroundColorSelect","selectedTextColor","inputBackgroundColorSelectTextColor","GenderType","Male","onClick","primaryColor","mens","Female","womens","buttonFunc","HeightStep","localHeight","setLocalHeight","cm","String","ft","inch","measurementUnit","setMeasurementUnit","preferredLanguage","inputBg","inputText","handleSetHeight","useCallback","event","prev","handleMeasurementUnit","val","validateHeight","height","convertToCentimeters","checkMeasurement","heightError","isButtonDisabled","useMemo","useEffect","renderHeightInput","inputMode","heightInFt","heightInInch","Select","MenuItem","cmMeasurementUnit","ftMeasurementUnit","ProgressDots","totalSteps","currentStepIndex","activeColor","inactiveColor","secondaryColor","dots","Array","from","length","_","i","index","isActive","isCompleted","map","backgroundColor","StepsWrapper","currentStep","onStepDone","stepOrder","visibleSteps","resolvedConfig","unsupportedStep","absoluteIndex","indexOf","logo","src","alt","logoHeight","width","logoWidth","heading","headingFontFamily","headingFontSize","headingColor","headingFontWeight","onboarding","commonProps","OnboardingStep","Email","Name","Gender","Height","noValidSteps","renderStep","DevicesList","Onboarding","steps","onDeviceDetected","handleWURFLDetectionComplete","wurfl","window","WURFL","phoneModel","brand_name","model_name","focal_length","entry","find","el","marketing_name","deviceInfo","brandName","modelName","focalLength","payload","data","JSON","stringify","location","posthog","capture","console","log","document","addEventListener","script","createElement","head","appendChild","removeEventListener","usePhoneDetection","resolveSteps","values","setValues","stepIndex","setStepIndex","s","isVisible","handleStepComplete","updated","LanguageContextProvider","ConfigProvider","FocalLengthWrapper","setDeviceInfo","model","manufacturerMenuItems","manufacturer","Object","keys","phoneModelMenuItems","brandMatch","phone","handleSubmit","Header","subtitle","selectPhoneBrand","selectPhoneModel","selectedId","m","foundModel","FocalLength","MuseScreenRenderer","screenIndex","scanLinePosition","faceZoomed","showFaceScanLine","faceScanLinePosition","showLargeS","typewriterText","fullText","screens","videoToShow","faceScanVideo","sizeVideo","formFittingVideo","screen","componentProps","body","face","sizeFit","hasComponent","component","Comp","content","image","muted","loop","autoPlay","playsInline","preload","AnimatePresence","mode","motion","div","initial","opacity","y","animate","exit","transition","duration","MuseScreenStep","Body","title","bodyScan","description","bodyScanDescription","bodyScanPerson","Face","faceScan","faceScanDescription","faceScanPerson","left","top","SizeFit","leSableDress","Ready","readyToStart","readyToStartDescription","fittingGuide","MuseSteps","applicableScreens","gender","onNext","isCustom","currentScreen","setCurrentScreen","setScanLinePosition","setFaceZoomed","setFaceScanLinePosition","setShowFaceScanLine","currentOutfit","setCurrentOutfit","setTypewriterText","setShowLargeS","screensToShow","reduce","acc","includes","push","screenId","outfitImages","animationRefs","useRef","scan","outfit","typewriter","cleanupAnimations","current","forEach","cancelAnimationFrame","clearTimeout","clearInterval","startTime","Date","now","animateScanLine","elapsed","progress","Math","min","requestAnimationFrame","setTimeout","animateFaceScanLine","setInterval","currentIndex","typeNextChar","slice","useMuseAnimations","OUTFIT_IMAGES","noTitle","subheading","subheadingFontFamily","subheadingFontSize","subheadingColor","subheadingFontWeight","maleScanVideo","femaleScanVideo","maleFaceScanVideo","maleSizeSuggestions","sizeSuggestions","maleFormFittingGuide","formFittingGuide","VolumeScreen","mousePosition","setMousePosition","x","isAnimationPaused","setIsAnimationPaused","handleMouseMove","clientX","clientY","hexToRgba","hex","alpha","replace","split","h","parseInt","substring","brandColor","rgba1","rgba2","rgba3","holographicStyle","windowWidth","innerWidth","windowHeight","innerHeight","normalizedX","transform","boxShadow","calculateHolographicEffect","minHeight","minWidth","margin","animation","Volume2","turnUpVolume","continue","SetupScreen","phonePlacement","phonePlacementDescription","maleSetupVideo","setupVideo","EducationalStepsWrapper","sections","startStep","step","setStep","SectionType","Full","VolumeStep","Educational"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","sources":["../src/atoms/customInput/CustomInput.tsx","../src/components/onboarding/EmailStep.tsx","../src/components/onboarding/NameStep.tsx","../src/components/onboarding/GenderStep.tsx","../src/components/onboarding/HeightStep.tsx","../src/atoms/progressDots/ProgressDots.tsx","../src/components/onboarding/StepsWrapper.tsx","../src/utils/deviceFocalLengthJson/index.ts","../src/components/onboarding/Onboarding.tsx","../src/customHooks/usePhoneDetection.ts","../src/components/focalLength/FocalLengthWrapper.tsx","../src/components/focalLength/FocalLength.tsx","../src/components/educational/MuseSteps/MuseScreenRenderer.tsx","../src/components/educational/MuseSteps/index.tsx","../src/components/educational/MuseSteps/BodyScanAnimation.tsx","../src/components/educational/MuseSteps/FaceScanAnimation.tsx","../src/components/educational/MuseSteps/TypewritterScene.tsx","../src/customHooks/useMuseAnimation.ts","../src/components/educational/VolumeStep.tsx","../src/components/educational/SetupScreen.tsx","../src/components/educational/EducationalStepsWrapper.tsx","../src/components/educational/Educational.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { useConfig } from \"../../utils/context/configContext\";\n\n/** Lightweight classnames helper to avoid depending on ../../utils/utils */\nconst cn = (...classes: Array<string | false | null | undefined>) =>\n classes.filter(Boolean).join(\" \");\n\nexport interface CustomInputProps\n extends React.InputHTMLAttributes<HTMLInputElement> {\n className?: string;\n type?: string;\n}\n\nconst CustomInput = React.forwardRef<HTMLInputElement, CustomInputProps>(\n ({ className, type, ...props }, ref) => {\n const config = useConfig();\n const input = config?.style?.input;\n const priority = input?.priority;\n return (\n <>\n <input\n type={type}\n className={`${className ? className : ''} customInput ` + cn(\n \"flex w-full px-[.75rem] h-[40px] text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed backdrop-blur-sm bg-btn font-medium pl-[1rem] pr-[2.5rem] focus:ring-1 focus:outline-none transition-all duration-200\",\n )}\n autoCapitalize=\"off\"\n autoCorrect=\"off\"\n ref={ref}\n {...props}\n style={{\n background: priority?.inputBackgroundColor || input?.inputBackgroundColor || '#F9FAFC',\n color: priority?.inputTextColor || input?.inputTextColor || '#000',\n fontSize: input?.inputFontSize || '16px',\n fontWeight: input?.inputFontWeight || '400',\n border: `1px solid ${input?.inputBorderColor || 'transparent'}`,\n fontFamily: config?.style?.base?.baseFontFamily || 'Inter, sans-serif',\n borderRadius: input?.inputBorderRadius || '4px',\n }}\n />\n <style>\n {`\n .customInput::placeholder {\n color: ${priority?.inputPlaceholderColor || input?.inputPlaceholderColor || '#000'};\n font-weight: ${input?.inputFontWeight || '500'};\n opacity: 1;\n font-size: ${input?.inputFontSize || '14px'};\n }\n .customInput:focus-visible {\n box-shadow:0 0 0 2px white, 0 0 0 4px rgb(from currentColor r g b / 0.5);\n }\n\n `}\n </style>\n </>\n )}\n );\n\nCustomInput.displayName = \"CustomInput\";\n\nexport default CustomInput;\n","import CustomInput from \"../../atoms/customInput/CustomInput\";\nimport SpecificButton from \"../../atoms/specificButton/SpecificButton\";\nimport { LanguageContext } from \"../../utils/context/languageContext\";\nimport { LanguageKeys } from \"../../utils/languageKeys\";\nimport { handleErrorMessage, isValidEmail } from \"../../utils/utils\";\nimport { ArrowRight } from \"lucide-react\";\nimport React, { useContext } from \"react\";\nimport { useConfig } from \"../../utils/context/configContext\";\n\ninterface EmailStepProps {\n\tonComplete: (value: any) => void;\n\tinitialValue?: any;\n\tonStepComplete?: (value: any) => Promise<void> | void;\n}\n\nconst EmailStep = ({ onComplete, initialValue, onStepComplete }: EmailStepProps) => {\n\tconst [value, setValue] = React.useState(initialValue || \"\");\n\tconst [message, setMessage] = React.useState<string | undefined>(undefined);\n\tconst [loading, setLoading] = React.useState(false);\n\tconst { translate } = useContext(LanguageContext) || {};\n\tconst config = useConfig();\n\tconst handleNext = async (e: React.FormEvent<HTMLFormElement>) => {\n\t\te.preventDefault();\n\t\tsetLoading(true);\n\t\ttry {\n\t\t\tif (!value.trim()) {\n\t\t\t\tsetMessage(translate?.(LanguageKeys.emailRequired));\n\t\t\t\treturn;\n\t\t\t} else if (!isValidEmail(value.trim())) {\n\t\t\t\tsetMessage(translate?.(LanguageKeys.validEmail));\n\t\t\t} else {\n\t\t\t\tawait onStepComplete?.(value);\n\t\t\t\tonComplete?.(value);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tsetMessage(handleErrorMessage(error));\n\t\t} finally {\n\t\t\tsetLoading(false);\n\t\t}\n\t};\n\treturn (\n\t\t<div className=\"w-full max-w-md\">\n\t\t\t<form className=\"mt-[3.5rem]\" onSubmit={handleNext}>\n\t\t\t\t<div>\n\t\t\t\t\t<CustomInput\n\t\t\t\t\t\trequired\n\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\tid=\"name\"\n\t\t\t\t\t\tdata-testid=\"onboarding-email-input\"\n\t\t\t\t\t\tplaceholder={translate?.(LanguageKeys.enterEmail)}\n\t\t\t\t\t\tvalue={value}\n\t\t\t\t\t\tonChange={(e) => {\n\t\t\t\t\t\t\tsetMessage(undefined);\n\t\t\t\t\t\t\tsetValue(e.target.value);\n\t\t\t\t\t\t}}\n\t\t\t\t\t/>\n\t\t\t\t\t{message && (\n\t\t\t\t\t\t<p\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\tcolor: config?.style?.input?.inputErrorColor || \"#000\",\n\t\t\t\t\t\t\t\tfontSize: config?.style?.input?.inputErrorFontSize || \"16px\",\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{message}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t\t<div className=\"flex justify-end mt-[.5rem]\">\n\t\t\t\t\t<SpecificButton type=\"submit\" data-testid=\"onboarding-next-btn\" disabled={!value.trim() || loading} buttonText={translate?.(LanguageKeys.next)} postfixIcon={<ArrowRight size={14} />} />\n\t\t\t\t</div>\n\t\t\t</form>\n\t\t</div>\n\t);\n};\n\nexport default EmailStep;\n","import CustomInput from \"../../atoms/customInput/CustomInput\";\nimport SpecificButton from \"../../atoms/specificButton/SpecificButton\";\nimport { LanguageContext } from \"../../utils/context/languageContext\";\nimport { LanguageKeys } from \"../../utils/languageKeys\";\nimport { handleErrorMessage } from \"../../utils/utils\";\nimport { ArrowRight } from \"lucide-react\";\nimport React, { useContext } from \"react\";\nimport { useConfig } from \"../../utils/context/configContext\";\n\ninterface NameStepProps {\n\tonComplete: (value: any) => void;\n\tinitialValue?: any;\n\tonStepComplete?: (value: any) => Promise<void> | void;\n}\n\nconst NameStep = ({ onComplete, initialValue, onStepComplete }: NameStepProps) => {\n\tconst [value, setValue] = React.useState(initialValue || \"\");\n\tconst [message, setMessage] = React.useState<string | undefined>(undefined);\n\tconst [loading, setLoading] = React.useState(false);\n\tconst { translate } = useContext(LanguageContext) || {};\n\tconst config = useConfig();\n\tconst handleNext = async (e: React.FormEvent<HTMLFormElement>) => {\n\t\te.preventDefault();\n\t\tsetLoading(true);\n\t\ttry {\n\t\t\tif (!value.trim()) {\n\t\t\t\tsetMessage(translate?.(LanguageKeys.nameRequired));\n\t\t\t\treturn;\n\t\t\t} else {\n\t\t\t\tawait onStepComplete?.(value);\n\t\t\t\tonComplete?.(value);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tsetMessage(handleErrorMessage(error));\n\t\t} finally {\n\t\t\tsetLoading(false);\n\t\t}\n\t};\n\treturn (\n\t\t<div className=\"w-full max-w-md\">\n\t\t\t<form onSubmit={handleNext} className=\"mt-[3.5rem] mb-[.75rem]\">\n\t\t\t\t<div>\n\t\t\t\t\t<CustomInput\n\t\t\t\t\t\trequired\n\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\tid=\"name\"\n\t\t\t\t\t\tdata-testid=\"onboarding-name-input\"\n\t\t\t\t\t\tplaceholder={translate?.(LanguageKeys.enterName)}\n\t\t\t\t\t\tonChange={(e) => {\n\t\t\t\t\t\t\tsetValue(e.target.value);\n\t\t\t\t\t\t}}\n\t\t\t\t\t/>\n\t\t\t\t\t{message && (\n\t\t\t\t\t\t<p\n\t\t\t\t\t\t\tclassName=\"mt-[0.2rem] text-[16px]\"\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\tcolor: config?.style?.input?.inputErrorColor || '#000',\n\t\t\t\t\t\t\t\tfontSize: config?.style?.input?.inputErrorFontSize || '16px',\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{message}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t\t<div className=\"flex justify-end mt-[.5rem]\">\n\t\t\t\t\t<SpecificButton disabled={!value.trim() || loading} data-testid=\"onboarding-next-btn\" buttonText={translate?.(LanguageKeys.next)} type=\"submit\" postfixIcon={<ArrowRight size={14} />} />\n\t\t\t\t</div>\n\t\t\t</form>\n\t\t</div>\n\t);\n};\n\nexport default NameStep;\n","import SpecificButton from \"../../atoms/specificButton/SpecificButton\";\nimport { LanguageContext } from \"../../utils/context/languageContext\";\nimport { GenderType } from \"../../utils/enums\";\nimport { LanguageKeys } from \"../../utils/languageKeys\";\nimport { handleErrorMessage } from \"../../utils/utils\";\nimport { ArrowRight } from \"lucide-react\";\nimport React, { useContext, useState } from \"react\";\nimport { useConfig } from \"../../utils/context/configContext\";\n\ninterface GenderStepProps {\n\tonComplete: (value: any) => void;\n\tinitialValue?: any;\n\tonStepComplete?: (value: any) => Promise<void> | void;\n}\n\nconst GenderStep = ({ onComplete, initialValue, onStepComplete }: GenderStepProps) => {\n\tconst [genderType, setGenderType] = useState<GenderType>(initialValue);\n\tconst [message, setMessage] = React.useState<string | undefined>(undefined);\n\tconst [loading, setLoading] = React.useState(false);\n\tconst { translate } = useContext(LanguageContext) || {};\n\tconst config = useConfig();\n\tconst input = config?.style?.input;\n\tconst priority = input?.priority;\n\n\tconst bgColor = priority?.inputBackgroundColor || input?.inputBackgroundColor || \"#F9FAFC\";\n\tconst textColor = priority?.inputTextColor || input?.inputTextColor || \"#000\";\n\tconst selectedBgColor = priority?.inputBackgroundColorSelect;\n\tconst selectedTextColor = priority?.inputBackgroundColorSelectTextColor;\n\n\tconst handleNext = async () => {\n\t\tsetLoading(true);\n\t\tsetMessage(undefined);\n\t\ttry {\n\t\t\tawait onStepComplete?.(genderType);\n\t\t\tonComplete?.(genderType);\n\t\t} catch (error) {\n\t\t\tsetMessage(handleErrorMessage(error));\n\t\t} finally {\n\t\t\tsetLoading(false);\n\t\t}\n\t};\n\n\treturn (\n\t\t<>\n\t\t\t<div className=\" w-full flex flex-col max-w-md mt-[3.5rem] mb-[.75rem] gap-[1rem]\">\n\t\t\t\t<button\n\t\t\t\t\tdata-testid=\"onboarding-gender-male\"\n\t\t\t\t\tclassName={` text-btnSize bg-btn cursor-pointer border leading-none rounded-[.375rem] focus-visible:ring-secondary p-[1rem] ${\n\t\t\t\t\t\tgenderType === GenderType.Male ? ` shadow-[0_1px_1px_rgba(0,0,0,0.251)]` : \"\"\n\t\t\t\t\t}`}\n\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\tsetGenderType(GenderType.Male);\n\t\t\t\t\t\tsetMessage(undefined);\n\t\t\t\t\t}}\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tbackground: genderType === GenderType.Male ? selectedBgColor : bgColor,\n\t\t\t\t\t\tcolor: genderType === GenderType.Male ? selectedTextColor : textColor,\n\t\t\t\t\t\tfontSize: input?.inputFontSize || \"16px\",\n\t\t\t\t\t\tfontWeight: input?.inputFontWeight || \"400\",\n\t\t\t\t\t\tborder: `1px solid ${genderType === GenderType.Male ? config?.style?.base?.primaryColor : `transparent`}`,\n\t\t\t\t\t\tfontFamily: config?.style?.base?.baseFontFamily || \"Inter, sans-serif\",\n\t\t\t\t\t\tborderRadius: input?.inputBorderRadius || \"4px\",\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t{translate?.(LanguageKeys.mens)}\n\t\t\t\t</button>\n\t\t\t\t<button\n\t\t\t\t\tdata-testid=\"onboarding-gender-female\"\n\t\t\t\t\tclassName={`text-btnSize font-btnFont cursor-pointer leading-none rounded-[.375rem] focus-visible:ring-secondary p-[1rem] ${\n\t\t\t\t\t\tgenderType === GenderType.Female ? ` shadow-[0_1px_1px_rgba(0,0,0,0.251)]` : \"\"\n\t\t\t\t\t}`}\n\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\tsetGenderType(GenderType.Female);\n\t\t\t\t\t\tsetMessage(undefined);\n\t\t\t\t\t}}\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tbackground: genderType === GenderType.Female ? selectedBgColor : bgColor,\n\t\t\t\t\t\tcolor: genderType === GenderType.Female ? selectedTextColor : textColor,\n\t\t\t\t\t\tfontSize: input?.inputFontSize || \"16px\",\n\t\t\t\t\t\tfontWeight: input?.inputFontWeight || \"400\",\n\t\t\t\t\t\tborder: `1px solid ${genderType === GenderType.Female ? config?.style?.base?.primaryColor : `transparent`}`,\n\t\t\t\t\t\tfontFamily: config?.style?.base?.baseFontFamily || \"Inter, sans-serif\",\n\t\t\t\t\t\tborderRadius: input?.inputBorderRadius || \"4px\",\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t{translate?.(LanguageKeys.womens)}\n\t\t\t\t</button>\n\t\t\t\t{message && (\n\t\t\t\t\t<p\n\t\t\t\t\t\tclassName=\"mt-[0.2rem]\"\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tcolor: input?.inputErrorColor || \"#000\",\n\t\t\t\t\t\t\tfontSize: input?.inputErrorFontSize || \"16px\",\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t{message}\n\t\t\t\t\t</p>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t\t<div className=\"flex justify-end mt-[.5rem]\">\n\t\t\t\t<SpecificButton\n\t\t\t\t\ttype=\"submit\"\n\t\t\t\t\tdata-testid=\"onboarding-next-btn\"\n\t\t\t\t\tbuttonText={translate?.(LanguageKeys.next)}\n\t\t\t\t\tpostfixIcon={<ArrowRight size={14} />}\n\t\t\t\t\tdisabled={!genderType || loading}\n\t\t\t\t\tbuttonFunc={handleNext}\n\t\t\t\t/>\n\t\t\t</div>\n\t\t</>\n\t);\n};\n\nexport default GenderStep;\n","import CustomInput from \"../../atoms/customInput/CustomInput\";\nimport SpecificButton from \"../../atoms/specificButton/SpecificButton\";\nimport { LanguageContext } from \"../../utils/context/languageContext\";\nimport { LanguageKeys } from \"../../utils/languageKeys\";\nimport { convertToCentimeters, handleErrorMessage } from \"../../utils/utils\";\nimport { MenuItem, Select } from \"@mui/material\";\nimport { ArrowRight } from \"lucide-react\";\nimport { useCallback, useContext, useEffect, useMemo, useState } from \"react\";\nimport { useConfig } from \"../../utils/context/configContext\";\n\ninterface HeightStepProps {\n\tonComplete: (value: any) => void;\n\tinitialValue?: any;\n\tonStepComplete?: (value: any) => Promise<void> | void;\n}\n\nconst HeightStep = ({ onComplete, initialValue, onStepComplete }: HeightStepProps) => {\n\tconst [localHeight, setLocalHeight] = useState({ cm: initialValue ? String(initialValue) : \"\", ft: \"\", inch: \"\" });\n\tconst [measurementUnit, setMeasurementUnit] = useState(\"cm\");\n\tconst [message, setMessage] = useState<string | undefined>(undefined);\n\tconst { translate, preferredLanguage } = useContext(LanguageContext) || {};\n\tconst config = useConfig();\n\tconst input = config?.style?.input;\n\tconst priority = input?.priority;\n\n\tconst inputBg = priority?.inputBackgroundColor || input?.inputBackgroundColor || \"#F9FAFC\";\n\tconst inputText = priority?.inputTextColor || input?.inputTextColor || \"#000\";\n\n\tconst handleSetHeight = useCallback(\n\t\t(event: React.ChangeEvent<HTMLInputElement>) => {\n\t\t\tsetMessage(undefined);\n\t\t\tif (measurementUnit === \"cm\") {\n\t\t\t\tsetLocalHeight((prev) => ({ ...prev, cm: event.target.value, ft: \"\", inch: \"\" }));\n\t\t\t} else if (event.target.id === \"ft\") {\n\t\t\t\tsetLocalHeight((prev) => ({ ...prev, ft: event.target.value, cm: \"\" }));\n\t\t\t} else {\n\t\t\t\tsetLocalHeight((prev) => ({ ...prev, inch: event.target.value, cm: \"\" }));\n\t\t\t}\n\t\t},\n\t\t[measurementUnit],\n\t);\n\n\tconst handleMeasurementUnit = useCallback((event: any) => {\n\t\tconst val = event.target.value;\n\t\tsetMeasurementUnit(val);\n\t\tsetLocalHeight({ cm: \"\", ft: \"\", inch: \"\" });\n\t\tsetMessage(undefined);\n\t}, []);\n\n\tconst validateHeight = useCallback(\n\t\t(height: { cm: string; ft: string; inch: string }) => {\n\t\t\tif (measurementUnit === \"cm\") {\n\t\t\t\treturn !(+height.cm < 152.4 || +height.cm > 213.36);\n\t\t\t}\n\t\t\treturn !(convertToCentimeters(+height.ft, +height.inch) < 152.4 || convertToCentimeters(+height.ft, +height.inch) > 213.36);\n\t\t},\n\t\t[measurementUnit],\n\t);\n\n\tconst checkMeasurement = useCallback(async () => {\n\t\ttry {\n\t\t\tif (!validateHeight(localHeight)) {\n\t\t\t\tsetMessage(translate?.(LanguageKeys.heightError));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst height = { cm: +localHeight.cm, ft: +localHeight.ft, inch: +localHeight.inch };\n\t\t\tawait onStepComplete?.(height);\n\t\t\tonComplete?.(height);\n\t\t} catch (error) {\n\t\t\tsetMessage(handleErrorMessage(error));\n\t\t}\n\t}, [localHeight, validateHeight, onStepComplete]);\n\n\tconst isButtonDisabled = useMemo(() => (!localHeight.cm && !localHeight.ft && !localHeight.inch) || !!message, [localHeight, message]);\n\n\tuseEffect(() => {\n\t\tif (localHeight.cm === \"\" && localHeight.ft !== \"\") {\n\t\t\tsetMeasurementUnit(\"ft\");\n\t\t}\n\t}, [localHeight]);\n\n\tconst renderHeightInput = useCallback(() => {\n\t\tif (measurementUnit === \"cm\") {\n\t\t\treturn (\n\t\t\t\t<div className={`w-full`}>\n\t\t\t\t\t<CustomInput\n\t\t\t\t\t\trequired\n\t\t\t\t\t\ttype=\"number\"\n\t\t\t\t\t\tid=\"cm\"\n\t\t\t\t\t\tdata-testid=\"onboarding-height-input\"\n\t\t\t\t\t\tplaceholder={translate?.(LanguageKeys.height)}\n\t\t\t\t\t\tclassName=\"!pr-[10px]\"\n\t\t\t\t\t\tinputMode=\"numeric\"\n\t\t\t\t\t\tvalue={localHeight.cm}\n\t\t\t\t\t\tonChange={handleSetHeight}\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t);\n\t\t} else {\n\t\t\treturn (\n\t\t\t\t<div className=\"flex gap-[.5rem]\">\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<CustomInput\n\t\t\t\t\t\t\trequired\n\t\t\t\t\t\t\ttype=\"number\"\n\t\t\t\t\t\t\tid=\"ft\"\n\t\t\t\t\t\t\tclassName=\"!pr-[10px]\"\n\t\t\t\t\t\t\tplaceholder={translate?.(LanguageKeys.heightInFt)}\n\t\t\t\t\t\t\tvalue={localHeight.ft}\n\t\t\t\t\t\t\tonChange={handleSetHeight}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<CustomInput\n\t\t\t\t\t\t\trequired\n\t\t\t\t\t\t\ttype=\"number\"\n\t\t\t\t\t\t\tid=\"inch\"\n\t\t\t\t\t\t\tclassName=\"!pr-[10px]\"\n\t\t\t\t\t\t\tplaceholder={translate?.(LanguageKeys.heightInInch)}\n\t\t\t\t\t\t\tvalue={localHeight.inch}\n\t\t\t\t\t\t\tonChange={handleSetHeight}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\t}, [localHeight, preferredLanguage]);\n\n\treturn (\n\t\t<div className=\"h-full w-full\">\n\t\t\t<div className=\"mt-[3.5rem] mb-[.75rem]\">\n\t\t\t\t<div className=\"w-full flex gap-[.5rem]\">\n\t\t\t\t\t{renderHeightInput()}\n\t\t\t\t\t<Select\n\t\t\t\t\t\tclassName=\"bg-btn outline-none h-[40px] [&_svg]:text-base !shadow-none !outline-none !text-base\"\n\t\t\t\t\t\tvalue={measurementUnit}\n\t\t\t\t\t\tonChange={handleMeasurementUnit}\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tbackground: inputBg,\n\t\t\t\t\t\t\tcolor: inputText,\n\t\t\t\t\t\t\tfontSize: input?.inputFontSize || \"16px\",\n\t\t\t\t\t\t\tfontWeight: input?.inputFontWeight || \"400\",\n\t\t\t\t\t\t\tborder: `1px solid ${input?.inputBorderColor || \"transparent\"}`,\n\t\t\t\t\t\t\tfontFamily: config?.style?.base?.baseFontFamily || \"Inter, sans-serif\",\n\t\t\t\t\t\t\tborderRadius: input?.inputBorderRadius || \"4px\",\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t<MenuItem value=\"cm\">{translate?.(LanguageKeys.cmMeasurementUnit)}</MenuItem>\n\t\t\t\t\t\t<MenuItem value=\"ft\">{translate?.(LanguageKeys.ftMeasurementUnit)}</MenuItem>\n\t\t\t\t\t</Select>\n\t\t\t\t\t<style>\n\t\t\t\t\t\t{`\n .MuiOutlinedInput-notchedOutline {\n border: 1px solid ${input?.inputBorderColor || \"transparent\"} !important;\n outline: none;\n }\n .MuiSelect-select{\n outline: none;\n }\n .MuiSvgIcon-root{\n color: ${inputText} !important;\n }\n `}\n\t\t\t\t\t</style>\n\t\t\t\t</div>\n\t\t\t\t<div\n\t\t\t\t\tclassName=\"mt-2\"\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tcolor: input?.inputErrorColor || \"#000\",\n\t\t\t\t\t\tfontSize: input?.inputErrorFontSize || \"16px\",\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t{message}\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div className=\"flex justify-end\">\n\t\t\t\t<SpecificButton disabled={isButtonDisabled} data-testid=\"onboarding-next-btn\" buttonFunc={checkMeasurement} buttonText={translate?.(LanguageKeys.next)} postfixIcon={<ArrowRight size={14} />} />\n\t\t\t</div>\n\t\t</div>\n\t);\n};\n\nexport default HeightStep;\n","import React, { useMemo } from \"react\";\nimport { useConfig } from \"../../utils/context/configContext\";\n\ninterface ProgressDotsProps {\n totalSteps: number;\n currentStepIndex: number;\n}\n\nconst ProgressDots: React.FC<ProgressDotsProps> = ({ totalSteps, currentStepIndex }) => {\n const config = useConfig();\n const activeColor = config?.style?.base?.primaryColor || \"#000\";\n const inactiveColor = config?.style?.base?.secondaryColor || \"#D9D9D9\";\n\n const dots = useMemo(\n () =>\n Array.from({ length: totalSteps }, (_, i) => ({\n index: i,\n isActive: i === currentStepIndex,\n isCompleted: i < currentStepIndex\n })),\n [totalSteps, currentStepIndex]\n );\n\n return (\n <div className=\"flex justify-center items-center gap-[4px] my-[1.5rem]\">\n {dots.map(({ index, isActive, isCompleted }) => (\n <div\n key={index}\n className={`h-[3px] rounded-[9999px] transition-all duration-300 ${\n isActive ? \"w-[50px]\" : \"w-[30px]\"\n }`}\n style={{\n backgroundColor: isCompleted || isActive ? activeColor : inactiveColor\n }}\n />\n ))}\n </div>\n );\n};\n\nexport default ProgressDots;\n","import { useContext } from \"react\";\nimport EmailStep from \"./EmailStep\";\nimport NameStep from \"./NameStep\";\nimport GenderStep from \"./GenderStep\";\nimport HeightStep from \"./HeightStep\";\nimport { OnboardingStep } from \"../../utils/enums\";\nimport { Step } from \"../../types/interfaces\";\nimport { LanguageContext } from \"../../utils/context/languageContext\";\nimport { LanguageKeys } from \"../../utils/languageKeys\";\nimport ProgressDots from \"../../atoms/progressDots/ProgressDots\";\nimport { useConfig } from \"../../utils/context/configContext\";\n\nconst StepsWrapper = ({ currentStep, onStepDone, stepOrder, visibleSteps = [] }: { currentStep: Step; onStepDone: (val: any) => void; stepOrder: any; visibleSteps?: Step[] }) => {\n\tconst { translate } = useContext(LanguageContext) || {};\n\tconst resolvedConfig = useConfig();\n\n\tconst renderStep = () => {\n\t\tif (!currentStep) return null;\n\n\t\tconst commonProps = {\n\t\t\tresolvedConfig,\n\t\t\tinitialValue: currentStep.value,\n\t\t\tonComplete: onStepDone,\n\t\t\tonStepComplete: currentStep?.onStepComplete,\n\t\t};\n\n\t\tswitch (currentStep.type) {\n\t\t\tcase OnboardingStep.Email:\n\t\t\t\treturn <EmailStep {...commonProps} />;\n\t\t\tcase OnboardingStep.Name:\n\t\t\t\treturn <NameStep {...commonProps} />;\n\t\t\tcase OnboardingStep.Gender:\n\t\t\t\treturn <GenderStep {...commonProps} />;\n\t\t\tcase OnboardingStep.Height:\n\t\t\t\treturn <HeightStep {...commonProps} />;\n\t\t\tdefault:\n\t\t\t\treturn (\n\t\t\t\t\t<div>\n\t\t\t\t\t\t{translate?.(LanguageKeys.noValidSteps)} {currentStep.type}\n\t\t\t\t\t</div>\n\t\t\t\t);\n\t\t}\n\t};\n\n\tif (!visibleSteps.length) return <div>{translate?.(LanguageKeys.unsupportedStep)}</div>;\n\n\t// stepOrder is the resolved visible-only list (from Onboarding.tsx),\n\t// so indexOf gives the correct 0-based position in the actual navigation flow.\n\tconst absoluteIndex = currentStep ? stepOrder.indexOf(currentStep.type) : 0;\n\n\treturn (\n\t\t<div data-testid=\"onboarding-root\" data-onboarding-step={absoluteIndex}>\n\t\t\t<div id=\"swan-onboarding-bg\" style={{ background: resolvedConfig?.style?.base?.backgroundColor }} className=\"fixed common-ui-main w-full h-full z-[0] pointer-events-none top-0 left-0\"></div>\n\n\t\t\t<div className=\"px-[15px] common-ui-main relative pt-[15px] w-full flex items-center flex-col\">\n\t\t\t\t<div className=\"max-w-[28rem] mx-auto w-full\">\n\t\t\t\t\t{/* Logo */}\n\t\t\t\t\t{resolvedConfig?.logo && (\n\t\t\t\t\t\t<div className=\"text-center mb-[1rem] flex justify-center\">\n\t\t\t\t\t\t\t<img\n\t\t\t\t\t\t\t\tsrc={resolvedConfig?.logo}\n\t\t\t\t\t\t\t\talt=\"logo\"\n\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\theight: resolvedConfig?.style?.logo?.logoHeight,\n\t\t\t\t\t\t\t\t\twidth: resolvedConfig?.style?.logo?.logoWidth,\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\tclassName=\"h-10 mx-auto\"\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\n\t\t\t\t\t{/* Progress Dots */}\n\t\t\t\t\t<ProgressDots totalSteps={stepOrder.length} currentStepIndex={absoluteIndex} />\n\n\t\t\t\t\t{/* Heading */}\n\t\t\t\t\t<h1\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tfontFamily: resolvedConfig?.style?.heading?.headingFontFamily || \"SeriouslyNostalgic Fn\",\n\t\t\t\t\t\t\tfontSize: resolvedConfig?.style?.heading?.headingFontSize || \"32px\",\n\t\t\t\t\t\t\tcolor: resolvedConfig?.style?.heading?.headingColor || \"#000\",\n\t\t\t\t\t\t\tfontWeight: resolvedConfig?.style?.heading?.headingFontWeight || \"normal\",\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tclassName=\"text-center pt-[1.5rem]\"\n\t\t\t\t\t>\n\t\t\t\t\t\t{translate?.(LanguageKeys.onboarding[currentStep?.type || \"heading\"])}\n\t\t\t\t\t</h1>\n\n\t\t\t\t\t{/* Step */}\n\t\t\t\t\t{renderStep()}\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t);\n};\n\nexport default StepsWrapper;\n","import Alcatel from \"./Alcatel.json\"\nimport Apple from \"./Apple.json\"\nimport CAT from \"./CAT.json\"\nimport Fairphone from \"./Fairphone.json\"\nimport Fujitsu from \"./Fujitsu.json\"\nimport Google from \"./Google.json\"\nimport Huawei from \"./Huawei.json\"\nimport iTel from \"./iTel.json\"\nimport Lava from \"./Lava.json\"\nimport Lg from \"./Lg.json\"\nimport Motorola from \"./Motorola.json\"\nimport NokiaHmd from \"./NokiaHmd.json\"\nimport Nothing from \"./Nothing.json\"\nimport Olla from \"./Olla.json\"\nimport Oneplus from \"./Oneplus.json\"\nimport Oppo from \"./Oppo.json\"\nimport Realme from \"./Realme.json\"\nimport Samsung from \"./Samsung.json\"\nimport Sharp from \"./Sharp.json\"\nimport Sony from \"./Sony.json\"\nimport Tecno from \"./Tecno.json\"\nimport Vivo from \"./Vivo.json\"\nimport Vsmart from \"./Vsmart.json\"\nimport Wiko from \"./Wiko.json\"\nimport Xiaomi from \"./Xiaomi.json\"\n\n\n\n\nconst DevicesList=[\n Alcatel,Apple,CAT,Fairphone,Fujitsu,Google,Huawei,iTel,Lava,Lg,Motorola,NokiaHmd,Nothing,Olla,Oneplus,Oppo,Realme,Samsung,Sharp,Sony,\n Tecno,Vivo,Vsmart,Wiko,Xiaomi\n\n]\n \n\nexport default DevicesList\n","\"use client\";\nimport React, { useState, useMemo, useCallback } from \"react\";\nimport { OnboardingProps } from \"../../types/interfaces\";\nimport { resolveSteps } from \"../../utils/utils\";\nimport LanguageContextProvider from \"../../utils/context/languageContext\";\nimport { ConfigProvider } from \"../../utils/context/configContext\";\nimport StepsWrapper from \"./StepsWrapper\";\nimport usePhoneDetection from \"../../customHooks/usePhoneDetection\";\n\nexport const Onboarding: React.FC<OnboardingProps> = ({ steps, config, onComplete, onDeviceDetected }) => {\n\tusePhoneDetection({ onDeviceDetected });\n\tconst visibleSteps = useMemo(() => resolveSteps(steps), [steps]);\n\tconst [values, setValues] = useState<Record<string, any>>({});\n\tconst [stepIndex, setStepIndex] = useState(0);\n\tconst currentStep = visibleSteps[stepIndex];\n\t// Hidden steps (isVisible:false) are placed first in stepOrder so they render\n\t// as pre-completed dots at the start of the progress bar. Visible steps follow\n\t// in their resolved (sorted) order. Because currentStep is always a visible step,\n\t// its indexOf position is always >= hiddenSteps.length, which means the first\n\t// N dots are permanently in \"completed\" state — no juggling, no backward jumps.\n\tconst hiddenSteps = steps.filter((s) => s.isVisible === false);\n\tconst stepOrder = [\n\t\t...hiddenSteps.map((s) => s.type),\n\t\t...visibleSteps.map((s) => s.type),\n\t];\n\n\t/** 4️⃣ Handle completion for a step */\n\tconst handleStepComplete = useCallback(\n\t\t(value: any) => {\n\t\t\tif (!currentStep) return;\n\t\t\tconst updated = { ...values, [currentStep.type]: value };\n\t\t\tsetValues(updated);\n\t\t\tif (stepIndex === visibleSteps.length - 1) {\n\t\t\t\tonComplete?.(updated);\n\t\t\t} else {\n\t\t\t\tsetStepIndex((prev) => prev + 1); // 👈 FIX\n\t\t\t}\n\t\t},\n\t\t[currentStep, values, stepIndex, visibleSteps.length, onComplete],\n\t);\n\n\tif (!visibleSteps.length) return <div>No steps configured for onboarding.</div>;\n\n\treturn (\n\t\t<LanguageContextProvider>\n\t\t\t<ConfigProvider config={config}>\n\t\t\t\t<StepsWrapper currentStep={currentStep} onStepDone={handleStepComplete} visibleSteps={visibleSteps} stepOrder={stepOrder} />\n\t\t\t</ConfigProvider>\n\t\t</LanguageContextProvider>\n\t);\n};\n","// Hook that auto-detects the user's phone model and focal length via WURFL.js (loaded dynamically).\n// Looks up the detected brand/model in DevicesList to find the camera focal length.\n// Falls back to manual selection if WURFL doesn't find a match in DevicesList.\n\nimport React, { useEffect } from \"react\";\nimport posthog from \"../utils/posthog\";\nimport DevicesList from \"../utils/deviceFocalLengthJson\";\n\ninterface DeviceInfo {\n brandName: string;\n modelName: string;\n focalLength: number;\n}\n\ninterface UsePhoneDetectionParams {\n onDeviceDetected?: (deviceInfo: { brandName: string; modelName: string; focalLength: number }) => void;\n}\n\nfunction usePhoneDetection({\n onDeviceDetected,\n}: UsePhoneDetectionParams): null {\n const handleWURFLDetectionComplete = () => {\n try {\n const wurfl = window?.WURFL;\n if (!wurfl) return;\n\n let phoneModel: { model_name: string; focal_length: number } | undefined;\n\n if (wurfl.brand_name === \"Apple\") {\n // WURFL returns generic \"iPhone\" for Apple — use a safe default focal length\n phoneModel = { model_name: \"iPhone\", focal_length: 23 };\n } else {\n for (const entry of DevicesList) {\n if (wurfl.brand_name in entry) {\n const models = (entry as Record<string, { model_name: string; focal_length: number }[]>)[wurfl.brand_name];\n phoneModel = models.find(\n (el) => el.model_name === wurfl.model_name || el.model_name === wurfl.marketing_name\n );\n if (phoneModel) break;\n }\n }\n }\n\n if (!phoneModel) return;\n const deviceInfo: DeviceInfo = {\n brandName: wurfl.brand_name,\n modelName: phoneModel.model_name,\n focalLength: phoneModel.focal_length,\n };\n\n onDeviceDetected?.({\n brandName: deviceInfo.brandName,\n modelName: deviceInfo.modelName,\n focalLength: deviceInfo.focalLength,\n });\n\n const payload: Record<string, any> = {\n type: \"auto\",\n data: JSON.stringify(deviceInfo),\n location:\"package\"\n };\n posthog.capture(`Phone Detection`, payload);\n } catch (error) {\n console.log(error, \"wurfl error\");\n }\n };\n\n useEffect(() => {\n try {\n document.addEventListener(\"WurflJSDetectionComplete\", handleWURFLDetectionComplete);\n const script = document.createElement(\"script\");\n script.src = \"//wjs.wurflcloud.com/wurfl.js\";\n script.async = true;\n document.head.appendChild(script);\n } catch (error) {\n console.log(\"error in getting device details\", error);\n }\n return () => {\n document.removeEventListener(\"WurflJSDetectionComplete\", handleWURFLDetectionComplete);\n };\n }, []);\n\n return null;\n}\n\nexport default usePhoneDetection;\n","import { useCallback, useContext, useState } from \"react\";\nimport { LanguageContext } from \"../../utils/context/languageContext\";\nimport Header from \"../Header\";\nimport { MenuItem, Select } from \"@mui/material\";\nimport SpecificButton from \"../../atoms/specificButton/SpecificButton\";\nimport { ArrowRight } from \"lucide-react\";\nimport { useConfig } from \"../../utils/context/configContext\";\nimport { FocalLengthProps } from \"../../types/interfaces\";\nimport DevicesList from \"../../utils/deviceFocalLengthJson\";\nimport { handleErrorMessage } from \"../../utils/utils\";\nimport { LanguageKeys } from \"../../utils/languageKeys\";\n\ntype PhoneModel = {\n\tid: number;\n\tmodel_name: string;\n\tfocal_length: number;\n};\n\ntype DeviceManufacturer = Record<string, PhoneModel[]>;\ntype DevicesListType = DeviceManufacturer[];\n\nconst FocalLengthWrapper = ({ onComplete }: Omit<FocalLengthProps, \"config\">) => {\n\tconst { translate } = useContext(LanguageContext) || {};\n\tconst resolvedConfig = useConfig();\n\tconst [deviceInfo, setDeviceInfo] = useState({\n\t\tbrandName: \"\",\n\t\tmodel: null as PhoneModel | null,\n\t});\n\tconst [message, setMessage] = useState<string | undefined>(undefined);\n\tconst [loading, setLoading] = useState(false);\n\n\t/* ------------ Brand Menu ------------ */\n\tconst manufacturerMenuItems = useCallback(() => {\n\t\treturn (DevicesList as DevicesListType).map((manufacturer) => {\n\t\t\tconst brandName = Object.keys(manufacturer)[0];\n\t\t\treturn (\n\t\t\t\t<MenuItem key={brandName} value={brandName}>\n\t\t\t\t\t{brandName}\n\t\t\t\t</MenuItem>\n\t\t\t);\n\t\t});\n\t}, []);\n\n\t/* ------------ Model Menu ------------ */\n\tconst phoneModelMenuItems = useCallback(() => {\n\t\tconst brandMatch = (DevicesList as DevicesListType).find((manufacturer) => {\n\t\t\tconst key = Object.keys(manufacturer)[0];\n\t\t\treturn key === deviceInfo.brandName;\n\t\t});\n\n\t\tif (!brandMatch) return null;\n\n\t\tconst key = Object.keys(brandMatch)[0];\n\t\tconst models = brandMatch[key];\n\n\t\treturn models.map((phone) => (\n\t\t\t<MenuItem key={phone.id} value={phone.id}>\n\t\t\t\t{phone.model_name}\n\t\t\t</MenuItem>\n\t\t));\n\t}, [deviceInfo.brandName]);\n\n\tconst handleSubmit = useCallback(async () => {\n\t\tsetLoading(true);\n\t\ttry {\n\t\t\tif (deviceInfo.brandName && deviceInfo.model) {\n\t\t\t\tawait onComplete?.({\n\t\t\t\t\tbrandName: deviceInfo.brandName,\n\t\t\t\t\tmodelName: deviceInfo.model.model_name,\n\t\t\t\t\tfocalLength: deviceInfo.model.focal_length,\n\t\t\t\t});\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tsetMessage(handleErrorMessage(error));\n\t\t} finally {\n\t\t\tsetLoading(false);\n\t\t}\n\t}, [deviceInfo]);\n\n\t/* ------------ Brand Change ------------ */\n\tconst handleBrandChange = (event: any) => {\n\t\tsetDeviceInfo({\n\t\t\tbrandName: event.target.value,\n\t\t\tmodel: null,\n\t\t});\n\t};\n\n\t/* ------------ Model Change ------------ */\n\tconst handleModelChange = (event: any) => {\n\t\tconst selectedId = event.target.value;\n\n\t\tconst brandMatch = (DevicesList as DevicesListType).find((m) => {\n\t\t\treturn Object.keys(m)[0] === deviceInfo.brandName;\n\t\t});\n\n\t\tif (!brandMatch) return;\n\n\t\tconst key = Object.keys(brandMatch)[0];\n\t\tconst models = brandMatch[key];\n\n\t\tconst foundModel = models.find((phone) => phone.id === selectedId);\n\n\t\tsetDeviceInfo((prev) => ({\n\t\t\t...prev,\n\t\t\tmodel: foundModel ?? null,\n\t\t}));\n\t};\n\n\n\treturn (\n\t\t<div\n\t\t\tdata-testid=\"focal-length-root\"\n\t\t\tclassName=\"h-full common-ui-main flex-col max-w-md mx-auto pt-[1rem] p-[15px] w-full flex justify-start items-start text-center rounded-t-[20px]\"\n\t\t\tstyle={{ background: resolvedConfig?.style?.base?.backgroundColor }}\n\t\t>\n\t\t\t<div className=\"w-full max-w-[28rem] mx-auto\">\n\t\t\t\t<Header subtitle={translate?.(LanguageKeys.phoneModel)} />\n\t\t\t\t<div className=\"text-left mb-[.25rem] mt-[1rem]\">{translate?.(LanguageKeys.selectPhoneBrand)}</div>\n\n\t\t\t\t<div data-testid=\"focal-length-brand-select\">\n\t\t\t\t\t<Select\n\t\t\t\t\t\tonChange={handleBrandChange}\n\t\t\t\t\t\tclassName=\"w-full h-[40px] !shadow-none !outline-none text-left\"\n\t\t\t\t\t\tvalue={deviceInfo.brandName}\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tbackground: resolvedConfig?.style?.input?.inputBackgroundColor || \"#F9FAFC\",\n\t\t\t\t\t\t\tcolor: resolvedConfig?.style?.input?.inputTextColor || \"#000\",\n\t\t\t\t\t\t\tfontSize: resolvedConfig?.style?.input?.inputFontSize || \"16px\",\n\t\t\t\t\t\t\tfontWeight: resolvedConfig?.style?.input?.inputFontWeight || \"400\",\n\t\t\t\t\t\t\tborder: `1px solid ${resolvedConfig?.style?.input?.inputBorderColor || \"transparent\"}`,\n\t\t\t\t\t\t\tfontFamily: resolvedConfig?.style?.base?.baseFontFamily || \"Inter, sans-serif\",\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t{manufacturerMenuItems()}\n\t\t\t\t\t</Select>\n\t\t\t\t</div>\n\n\t\t\t\t<div className=\"text-left mb-[.25rem] mt-[1rem]\">{translate?.(LanguageKeys.selectPhoneModel)}</div>\n\n\t\t\t\t<div data-testid=\"focal-length-model-select\">\n\t\t\t\t\t<Select\n\t\t\t\t\t\tonChange={handleModelChange}\n\t\t\t\t\t\tclassName=\"w-full bg-btn h-[40px] !shadow-none !outline-none text-left\"\n\t\t\t\t\t\tvalue={deviceInfo.model?.id || \"\"}\n\t\t\t\t\t\tdisabled={!deviceInfo.brandName}\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tbackground: resolvedConfig?.style?.input?.inputBackgroundColor || \"#F9FAFC\",\n\t\t\t\t\t\t\tcolor: resolvedConfig?.style?.input?.inputTextColor || \"#000\",\n\t\t\t\t\t\t\tfontSize: resolvedConfig?.style?.input?.inputFontSize || \"16px\",\n\t\t\t\t\t\t\tfontWeight: resolvedConfig?.style?.input?.inputFontWeight || \"400\",\n\t\t\t\t\t\t\tborder: `1px solid ${resolvedConfig?.style?.input?.inputBorderColor || \"transparent\"}`,\n\t\t\t\t\t\t\tfontFamily: resolvedConfig?.style?.base?.baseFontFamily || \"Inter, sans-serif\",\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t{phoneModelMenuItems()}\n\t\t\t\t\t</Select>\n\t\t\t\t</div>\n\t\t\t\t<style>\n\t\t\t\t\t{`\n .MuiOutlinedInput-notchedOutline {\n border: 1px solid ${resolvedConfig?.style?.input?.inputBorderColor || \"transparent\"} !important;\n outline: none;\n }\n .MuiSelect-select{\n outline: none;\n }\n \n `}\n\t\t\t\t</style>\n\t\t\t\t{message && <p className=\"mt-[0.2rem] text-[16px]\">{message}</p>}\n\t\t\t</div>\n\n\t\t\t<div className=\"mt-[.75rem] mb-[1.25rem] max-w-[28rem] mx-auto w-full flex justify-end\">\n\t\t\t\t<SpecificButton\n\t\t\t\t\tdisabled={!deviceInfo?.brandName || !deviceInfo?.model || loading}\n\t\t\t\t\tdata-testid=\"focal-length-next-btn\"\n\t\t\t\t\tpostfixIcon={<ArrowRight />}\n\t\t\t\t\tbuttonFunc={handleSubmit}\n\t\t\t\t\tbuttonText={translate?.(LanguageKeys.next)}\n\t\t\t\t/>\n\t\t\t</div>\n\t\t</div>\n\t);\n};\n\nexport default FocalLengthWrapper;\n","import React from \"react\";\nimport FocalLengthWrapper from \"./FocalLengthWrapper\";\nimport { FocalLengthProps } from \"../../types/interfaces\";\nimport LanguageContextProvider from \"../../utils/context/languageContext\";\nimport { ConfigProvider } from \"../../utils/context/configContext\";\n\nexport const FocalLength: React.FC<FocalLengthProps> = ({\n onComplete,\n config,\n}: FocalLengthProps) => {\n return (\n <LanguageContextProvider>\n <ConfigProvider config={config}>\n <FocalLengthWrapper\n onComplete={onComplete}\n />\n </ConfigProvider>\n </LanguageContextProvider>\n );\n};\n","import React from \"react\";\nimport { motion, AnimatePresence } from \"framer-motion\";\n\nexport default function MuseScreenRenderer({\n\tscreenIndex,\n\tscanLinePosition,\n\tfaceZoomed,\n\tshowFaceScanLine,\n\tfaceScanLinePosition,\n\tshowLargeS,\n\ttypewriterText,\n\tfullText,\n\tscreens,\n\tvideoToShow,\n\tfaceScanVideo,\n\tsizeVideo,\n\tformFittingVideo,\n}: any) {\n\tconst screen = screens[screenIndex];\n\n\t// Map screen id to props for each component\n\tconst componentProps: any = {\n\t\tbody: { scanLinePosition, videoToShow },\n\t\tface: {\n\t\t\tfaceZoomed,\n\t\t\tshowFaceScanLine,\n\t\t\tfaceScanLinePosition,\n\t\t\tfaceScanVideo,\n\t\t},\n\t\tsizeFit: { showLargeS, typewriterText, fullText, sizeVideo },\n\t};\n\n\tconst hasComponent = !!screen.component;\n\tconst Comp = hasComponent ? screen.component : null;\n\n\tlet content = null;\n\tif (hasComponent) {\n\t\tcontent = React.createElement(Comp.type || Comp, componentProps[screen.id] || {});\n\t} else if (screen.image) {\n\t\tcontent = (\n\t\t\t<video className=\"h-full w-full object-contain border-none\" muted loop autoPlay playsInline preload=\"auto\">\n\t\t\t\t<source src={formFittingVideo} type=\"video/mp4\" />\n\t\t\t</video>\n\t\t);\n\t}\n\n\treturn (\n\t\t<AnimatePresence mode=\"wait\">\n\t\t\t<motion.div key={screenIndex} initial={{ opacity: 0, y: 20 }} animate={{ opacity: 1, y: 0 }} exit={{ opacity: 0, y: -20 }} transition={{ duration: 0.4 }} className=\"w-full h-full\">\n\t\t\t\t{content}\n\t\t\t</motion.div>\n\t\t</AnimatePresence>\n\t);\n}\n","import { ArrowRight } from \"lucide-react\";\nimport BodyScanAnimation from \"./BodyScanAnimation\";\nimport FaceScanAnimation from \"./FaceScanAnimation\";\nimport TypewriterScene from \"./TypewritterScene\";\nimport { useContext, useMemo, useState } from \"react\";\nimport MuseScreenRenderer from \"./MuseScreenRenderer\";\nimport Header from \"../../Header\";\nimport { GenderType, MuseScreenStep } from \"../../../utils/enums\";\nimport {\n\tbodyScanPerson,\n\tfaceScanPerson,\n\tfaceScanVideo,\n\tfemaleScanVideo,\n\tfittingGuide,\n\tformFittingGuide,\n\tfullText,\n\tleSableDress,\n\tmaleFaceScanVideo,\n\tmaleFormFittingGuide,\n\tmaleScanVideo,\n\tmaleSizeSuggestions,\n\tOUTFIT_IMAGES,\n\tsizeSuggestions,\n} from \"../../..//utils/constants\";\nimport { MuseStepsProps } from \"../../../types/interfaces\";\nimport useMuseAnimations from \"../../../customHooks/useMuseAnimation\";\nimport SpecificButton from \"../../../atoms/specificButton/SpecificButton\";\nimport { LanguageKeys } from \"../../../utils/languageKeys\";\nimport { LanguageContext } from \"../../../utils/context/languageContext\";\nimport { useConfig } from \"../../../utils/context/configContext\";\n\nconst screens: {\n\tid: string;\n\ttitle: string;\n\tdescription: string;\n\timage: string;\n\tcomponent?: React.ReactNode;\n}[] = [\n\t{\n\t\tid: MuseScreenStep.Body,\n\t\ttitle: LanguageKeys.bodyScan,\n\t\tdescription: LanguageKeys.bodyScanDescription,\n\t\timage: bodyScanPerson,\n\t\tcomponent: <BodyScanAnimation />,\n\t},\n\t{\n\t\tid: MuseScreenStep.Face,\n\t\ttitle: LanguageKeys.faceScan,\n\t\tdescription: LanguageKeys.faceScanDescription,\n\t\timage: faceScanPerson,\n\t\tcomponent: <FaceScanAnimation />,\n\t},\n\t{\n\t\tid: MuseScreenStep.SizeFit,\n\t\ttitle: LanguageKeys.sizeFit,\n\t\tdescription: \"\",\n\t\timage: leSableDress,\n\t\tcomponent: <TypewriterScene />,\n\t},\n\t{\n\t\tid: MuseScreenStep.Ready,\n\t\ttitle: LanguageKeys.readyToStart,\n\t\tdescription: LanguageKeys.readyToStartDescription,\n\t\timage: fittingGuide,\n\t},\n];\n\nexport default function MuseSteps({ applicableScreens, gender, onNext, isCustom }: Omit<MuseStepsProps, \"config\">) {\n\tconst { translate } = useContext(LanguageContext) || {};\n\tconst config = useConfig();\n\tconst [currentScreen, setCurrentScreen] = useState(0);\n\tconst [scanLinePosition, setScanLinePosition] = useState(0);\n\tconst [faceZoomed, setFaceZoomed] = useState(false);\n\tconst [faceScanLinePosition, setFaceScanLinePosition] = useState(0);\n\tconst [showFaceScanLine, setShowFaceScanLine] = useState(false);\n\tconst [currentOutfit, setCurrentOutfit] = useState(0);\n\tconst [typewriterText, setTypewriterText] = useState(\"\");\n\tconst [showLargeS, setShowLargeS] = useState(false);\n\n\tconst screensToShow = useMemo(() => {\n\t\tif (isCustom) {\n\t\t\treturn screens.reduce((acc: any, el) => {\n\t\t\t\tif ([\"face\", \"sizeFit\"].includes(el.id)) {\n\t\t\t\t\treturn acc;\n\t\t\t\t}\n\t\t\t\tacc.push(el);\n\t\t\t\treturn acc;\n\t\t\t}, []);\n\t\t}\n\t\tif (!applicableScreens?.length) {\n\t\t\treturn screens;\n\t\t}\n\t\treturn screens.filter((screen) => applicableScreens.includes(screen.id));\n\t}, [applicableScreens]);\n\n\tuseMuseAnimations({\n\t\tscreenId: screensToShow[currentScreen].id,\n\t\tsetScanLinePosition,\n\t\tsetFaceZoomed,\n\t\tsetShowFaceScanLine,\n\t\tsetFaceScanLinePosition,\n\t\tsetCurrentOutfit,\n\t\tsetTypewriterText,\n\t\tsetShowLargeS,\n\t\toutfitImages: OUTFIT_IMAGES,\n\t\tfullText,\n\t});\n\n\tconst onNextClick = () => {\n\t\tif (currentScreen < screensToShow.length - 1) {\n\t\t\tsetCurrentScreen((prev) => prev + 1);\n\t\t} else {\n\t\t\tonNext?.();\n\t\t}\n\t};\n\treturn (\n\t\t<div data-testid=\"educational-root\" data-educational-step=\"1\" className=\"relative common-ui-main h-full max-w-[28rem] mx-auto w-full flex justify-center\" style={{ background: config?.style?.base?.backgroundColor }}>\n\t\t\t<div className=\"absolute bottom-0 left-0 right-0 h-full shadow-lg w-full\">\n\t\t\t\t<div className=\"h-full flex flex-col p-[1rem] w-full\">\n\t\t\t\t\t<Header noTitle />\n\t\t\t\t\t<div className=\"text-center pb-[.5rem]\">\n\t\t\t\t\t\t<h1\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\tfontFamily: config?.style?.heading?.headingFontFamily || \"SeriouslyNostalgic Fn\",\n\t\t\t\t\t\t\t\tfontSize: config?.style?.heading?.headingFontSize || \"32px\",\n\t\t\t\t\t\t\t\tcolor: config?.style?.heading?.headingColor || \"#000\",\n\t\t\t\t\t\t\t\tfontWeight: config?.style?.heading?.headingFontWeight || \"normal\",\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{translate?.(screensToShow[currentScreen].title)}\n\t\t\t\t\t\t</h1>\n\t\t\t\t\t\t{screensToShow[currentScreen].description && (\n\t\t\t\t\t\t\t<p\n\t\t\t\t\t\t\t\tclassName=\" mt-[.25rem] max-w-[280px] mx-auto min-h-[40px]\"\n\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\tfontFamily: config?.style?.subheading?.subheadingFontFamily || \"'Inter', sans-serif\",\n\t\t\t\t\t\t\t\t\tfontSize: config?.style?.subheading?.subheadingFontSize || \"14px\",\n\t\t\t\t\t\t\t\t\tcolor: config?.style?.subheading?.subheadingColor || \"#4b5563\",\n\t\t\t\t\t\t\t\t\tfontWeight: config?.style?.subheading?.subheadingFontWeight || \"normal\",\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{translate?.(screensToShow[currentScreen].description)}\n\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t\t<div className=\"flex-1 flex justify-center items-center overflow-hidden py-[1rem] relative\">\n\t\t\t\t\t\t<MuseScreenRenderer\n\t\t\t\t\t\t\tscreenIndex={currentScreen}\n\t\t\t\t\t\t\tscanLinePosition={scanLinePosition}\n\t\t\t\t\t\t\tfaceZoomed={faceZoomed}\n\t\t\t\t\t\t\tshowFaceScanLine={showFaceScanLine}\n\t\t\t\t\t\t\tfaceScanLinePosition={faceScanLinePosition}\n\t\t\t\t\t\t\toutfitImages={OUTFIT_IMAGES}\n\t\t\t\t\t\t\tcurrentOutfit={currentOutfit}\n\t\t\t\t\t\t\tshowLargeS={showLargeS}\n\t\t\t\t\t\t\ttypewriterText={typewriterText}\n\t\t\t\t\t\t\tfullText={fullText}\n\t\t\t\t\t\t\tscreens={screensToShow}\n\t\t\t\t\t\t\tvideoToShow={gender === GenderType.Male ? maleScanVideo : femaleScanVideo}\n\t\t\t\t\t\t\tfaceScanVideo={gender === GenderType.Male ? maleFaceScanVideo : faceScanVideo}\n\t\t\t\t\t\t\tsizeVideo={gender === GenderType.Male ? maleSizeSuggestions : sizeSuggestions}\n\t\t\t\t\t\t\tformFittingVideo={gender === GenderType.Male ? maleFormFittingGuide : formFittingGuide}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<div className=\"pt-[.5rem] flex justify-end\">\n\t\t\t\t\t\t<SpecificButton buttonText={translate?.(LanguageKeys.next)} type=\"submit\" data-testid=\"educational-next-btn\" postfixIcon={<ArrowRight size={14} />} buttonFunc={onNextClick} />\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n","export default function BodyScanAnimation({\n videoToShow,\n}: {\n videoToShow?: string;\n}) {\n return (\n <div className=\"relative w-full h-full common-ui-main\">\n <video\n className=\"h-full w-full object-contain border-none\"\n muted\n autoPlay\n loop\n playsInline\n >\n <source src={videoToShow} type=\"video/mp4\" />\n </video>\n </div>\n );\n}\n","import { FaceScanAnimationProps } from \"../../../types/interfaces\";\n\nexport default function FaceScanAnimation({\n faceZoomed,\n showFaceScanLine,\n faceScanLinePosition,\n faceScanVideo,\n}: FaceScanAnimationProps) {\n return (\n <div className=\"relative h-full w-full common-ui-main\">\n <div className=\"w-full h-full relative\">\n <video\n className=\"h-full w-full object-contain border-none\"\n muted\n autoPlay\n playsInline\n >\n <source src={faceScanVideo} type=\"video/mp4\" />\n </video>\n {showFaceScanLine && faceZoomed && (\n <div\n className=\"absolute w-[1px] bg-[#8B5CF6] shadow-[0_0_8px_rgba(139,92,246,0.8)] z-20\"\n style={{\n left: `${faceScanLinePosition}%`,\n top: \"0%\",\n height: \"40%\",\n opacity:\n faceScanLinePosition && faceScanLinePosition >= 0 ? 1 : 0,\n }}\n />\n )}\n </div>\n </div>\n );\n}\n","export default function TypewriterScene({ sizeVideo }: { sizeVideo?: string }) {\n return (\n <div className=\"relative common-ui-main w-full h-full flex justify-center items-center\">\n <video\n className=\"h-full w-full object-contain border-none\"\n muted\n loop\n autoPlay\n playsInline\n >\n <source src={sizeVideo} type=\"video/mp4\" />\n </video>\n </div>\n );\n}\n","import { useEffect, useRef } from \"react\";\n\nfunction useMuseAnimations({\n screenId,\n setScanLinePosition,\n setFaceZoomed,\n setShowFaceScanLine,\n setFaceScanLinePosition,\n setCurrentOutfit,\n outfitImages,\n setTypewriterText,\n setShowLargeS,\n fullText,\n}: any) {\n const animationRefs = useRef<any>({\n scan: null,\n face: null,\n outfit: null,\n typewriter: null,\n });\n\n const cleanupAnimations = () => {\n Object.values(animationRefs.current).forEach((ref: any) => {\n if (typeof ref === \"number\") {\n cancelAnimationFrame(ref);\n } else if (ref) {\n clearTimeout(ref);\n clearInterval(ref);\n }\n });\n animationRefs.current = {\n scan: null,\n face: null,\n outfit: null,\n typewriter: null,\n };\n };\n\n useEffect(() => {\n cleanupAnimations();\n\n switch (screenId) {\n case \"body\": {\n const startTime = Date.now();\n const duration = 3000;\n\n const animateScanLine = () => {\n const elapsed = Date.now() - startTime;\n const progress = Math.min(elapsed / duration, 1);\n setScanLinePosition(progress * 100);\n if (progress < 1) {\n animationRefs.current.scan = requestAnimationFrame(animateScanLine);\n }\n };\n\n animationRefs.current.scan = requestAnimationFrame(animateScanLine);\n break;\n }\n\n case \"face\": {\n setFaceZoomed(false);\n setShowFaceScanLine(false);\n setFaceScanLinePosition(0);\n\n animationRefs.current.face = setTimeout(() => {\n setFaceZoomed(true);\n\n setTimeout(() => {\n setShowFaceScanLine(true);\n\n const startTime = Date.now();\n const duration = 6000; // ✅ Total 6s (3s for each direction)\n\n const animateFaceScanLine = () => {\n const elapsed = Date.now() - startTime;\n const progress = Math.min(elapsed / duration, 1);\n\n setFaceScanLinePosition(\n progress <= 0.5 ? progress * 2 * 100 : (2 - progress * 2) * 100\n );\n\n if (progress < 1) {\n animationRefs.current.face =\n requestAnimationFrame(animateFaceScanLine);\n }\n };\n\n animationRefs.current.face =\n requestAnimationFrame(animateFaceScanLine);\n }, 2500); // Delay after zoom\n }, 800); // Delay before zoom\n break;\n }\n\n case \"sizeFit\": {\n setCurrentOutfit(0);\n animationRefs.current.outfit = setInterval(() => {\n setCurrentOutfit((prev: any) => (prev + 1) % outfitImages.length);\n }, 1500);\n break;\n }\n\n case \"ready\": {\n setShowLargeS(false);\n setTypewriterText(\"\");\n\n animationRefs.current.typewriter = setTimeout(() => {\n setShowLargeS(true);\n setTimeout(() => {\n let currentIndex = 0;\n const typeNextChar = () => {\n if (currentIndex < fullText.length) {\n setTypewriterText(fullText.slice(0, currentIndex + 1));\n currentIndex++;\n animationRefs.current.typewriter = setTimeout(typeNextChar, 30);\n }\n };\n typeNextChar();\n }, 1000);\n }, 800);\n break;\n }\n\n default:\n break;\n }\n\n return cleanupAnimations;\n }, [screenId]);\n}\n\nexport default useMuseAnimations;\n","import { ArrowRight, Volume2 } from \"lucide-react\";\nimport { useState, useEffect, useContext } from \"react\";\nimport Header from \"../Header\";\nimport { LanguageContext } from \"../../utils/context/languageContext\";\nimport { LanguageKeys } from \"../../utils/languageKeys\";\nimport SpecificButton from \"../../atoms/specificButton/SpecificButton\";\nimport { useConfig } from \"../../utils/context/configContext\";\n\ninterface VolumeStepProps {\n onNext: () => void;\n}\n\nexport default function VolumeScreen({ onNext }: VolumeStepProps) {\n const { translate } = useContext(LanguageContext) || {};\n const config = useConfig();\n const [mousePosition, setMousePosition] = useState({ x: 0, y: 0 });\n const [isAnimationPaused, setIsAnimationPaused] = useState(false);\n\n useEffect(() => {\n const handleMouseMove = (e: any) => {\n setMousePosition({ x: e.clientX, y: e.clientY });\n };\n window.addEventListener(\"mousemove\", handleMouseMove);\n return () => window.removeEventListener(\"mousemove\", handleMouseMove);\n }, []);\n\n const toggleAnimationPause = () => {\n setIsAnimationPaused((prev) => !prev);\n };\n\n function hexToRgba(hex: string, alpha: number = 1): string {\n hex = hex.replace(\"#\", \"\");\n if (hex.length === 3) {\n hex = hex.split(\"\").map((h) => h + h).join(\"\");\n }\n const r = parseInt(hex.substring(0, 2), 16);\n const g = parseInt(hex.substring(2, 4), 16);\n const b = parseInt(hex.substring(4, 6), 16);\n return `rgba(${r}, ${g}, ${b}, ${alpha})`;\n }\n\n const brandColor = config?.style?.base?.brandColor || \"#000\";\n const rgba1 = hexToRgba(brandColor, 0.19);\n const rgba2 = hexToRgba(brandColor, 0.23);\n const rgba3 = hexToRgba(brandColor, 0.24);\n\n const calculateHolographicEffect = () => {\n const windowWidth = typeof window !== \"undefined\" ? window.innerWidth : 1000;\n const windowHeight = typeof window !== \"undefined\" ? window.innerHeight : 1000;\n const normalizedX = (mousePosition.x / windowWidth) * 2 - 1;\n const normalizedY = (mousePosition.y / windowHeight) * 2 - 1;\n const rotateX = normalizedY * 5;\n const rotateY = normalizedX * -5;\n return {\n transform: `perspective(1000px) rotateX(${rotateX}deg) rotateY(${rotateY}deg)`,\n background: \"#fff\",\n boxShadow: `0 0 20px ${rgba1}, 0 0 30px ${rgba2}`,\n };\n };\n\n const holographicStyle = calculateHolographicEffect();\n\n return (\n <div\n data-testid=\"educational-root\"\n data-educational-step=\"2\"\n className=\"flex h-full max-w-[28rem] mx-auto w-full flex-col relative items-center justify-center overflow-hidden max-w-md mx-auto bg-primary text-base\"\n style={{ background: config?.style?.base?.backgroundColor }}\n >\n <div className=\"flex justify-start absolute z-[99] top-[1rem] max-w-md mx-auto w-full px-[1rem]\">\n <Header noTitle />\n </div>\n <div className=\"relative mb-[2rem]\">\n {[...Array(3)].map((_, i) => (\n <div\n key={i}\n className=\"absolute rounded-[9999px]\"\n style={{\n width: \"100px\",\n height: \"100px\",\n minHeight: \"100px\",\n minWidth: \"100px\",\n background: config?.style?.base?.backgroundColor || \"#fff\",\n boxShadow: `0 0 20px 2px ${rgba3}`,\n border: \"none\",\n filter: \"blur(1px)\",\n margin: \"0 auto\",\n left: \"50%\",\n top: \"50%\",\n animation: isAnimationPaused\n ? \"none\"\n : `gentleRipple 15s cubic-bezier(0.1, 0.5, 0.2, 1) ${i * 5}s infinite`,\n opacity: isAnimationPaused ? 1 : 0,\n transform: isAnimationPaused\n ? \"translate(-50%, -50%) scale(0.5)\"\n : \"translate(-50%, -50%)\",\n }}\n />\n ))}\n <div\n className=\"relative z-10 rounded-[9999px] p-[1.5rem] cursor-pointer transition-all backdrop-blur-sm\"\n style={{\n ...holographicStyle,\n transition: \"transform 0.1s ease-out, box-shadow 0.1s ease-out\",\n }}\n onClick={toggleAnimationPause}\n >\n <Volume2\n className=\"w-[3rem] h-[3rem] relative z-10\"\n style={{ filter: \"drop-shadow(0 0 5px rgba(255, 255, 255, 0.7))\" }}\n color={config?.style?.base?.primaryColor || \"#000\"}\n />\n </div>\n </div>\n\n <div className=\"relative z-10 text-center max-w-[20rem]\">\n <div\n className=\" mb-[.5rem]\"\n style={{\n fontFamily: config?.style?.subheading?.subheadingFontFamily || \"'Inter', sans-serif\",\n fontSize: config?.style?.subheading?.subheadingFontSize || \"14px\",\n color: config?.style?.subheading?.subheadingColor || \"#4b5563\",\n fontWeight: config?.style?.subheading?.subheadingFontWeight || \"normal\",\n }}\n >\n {translate?.(LanguageKeys.turnUpVolume)}\n </div>\n </div>\n\n <div className=\"absolute bottom-[1rem] right-0 max-w-[28rem] mx-auto w-full px-[1rem] max-w-md mx-auto\">\n <div className=\"flex justify-end\">\n <SpecificButton\n buttonFunc={() => onNext()}\n data-testid=\"educational-next-btn\"\n postfixIcon={<ArrowRight />}\n buttonText={translate?.(LanguageKeys.continue)}\n />\n </div>\n </div>\n <style>{`\n @keyframes gentleRipple {\n 0% {\n transform: translate(-50%, -50%) scale(0.5) translateZ(0);\n opacity: 0.7;\n }\n 50% {\n opacity: 0.4;\n }\n 100% {\n transform: translate(-50%, -50%) scale(25) translateZ(0);\n opacity: 0;\n }\n }\n`}</style>\n </div>\n );\n}\n","import { useContext } from \"react\";\nimport { ArrowRight } from \"lucide-react\";\nimport Header from \"../Header\";\nimport { maleSetupVideo, setupVideo } from \"../../utils/constants\";\nimport { LanguageContext } from \"../../utils/context/languageContext\";\nimport { LanguageKeys } from \"../../utils/languageKeys\";\nimport { GenderType } from \"../../utils/enums\";\nimport SpecificButton from \"../../atoms/specificButton/SpecificButton\";\nimport { useConfig } from \"../../utils/context/configContext\";\nimport { Gender } from \"../../types/interfaces\";\n\ninterface SetupScreenProps {\n gender: Gender;\n onNext?: () => void;\n}\n\nexport default function SetupScreen({ gender, onNext }: SetupScreenProps) {\n\tconst { translate } = useContext(LanguageContext) || {};\n\tconst config = useConfig();\n\n\treturn (\n\t\t<div\n\t\t\tdata-testid=\"educational-root\"\n\t\t\tdata-educational-step=\"3\"\n\t\t\tclassName=\"flex h-full max-w-[28rem] mx-auto w-full p-[1rem] common-ui-main relative flex-col items-center overflow-hidden max-w-md mx-auto bg-primary text-base\"\n\t\t\tstyle={{ background: config?.style?.base?.backgroundColor }}\n\t\t>\n\t\t\t<div className=\"flex justify-start max-w-md mx-auto w-full \">\n\t\t\t\t<Header noTitle />\n\t\t\t</div>\n\t\t\t<h2\n\t\t\t\tclassName=\"mb-[1rem] text-[32px]\"\n\t\t\t\tstyle={{\n\t\t\t\t\tfontFamily: config?.style?.heading?.headingFontFamily || \"SeriouslyNostalgic Fn\",\n\t\t\t\t\tfontSize: config?.style?.heading?.headingFontSize || \"32px\",\n\t\t\t\t\tcolor: config?.style?.heading?.headingColor || \"#000\",\n\t\t\t\t\tfontWeight: config?.style?.heading?.headingFontWeight || \"normal\",\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t{translate?.(LanguageKeys.phonePlacement)}\n\t\t\t</h2>\n\t\t\t<p\n\t\t\t\tclassName=\"text-center text-gray-600 text-sm mt-1 max-w-[280px] mx-auto min-h-[40px]\"\n\t\t\t\tstyle={{\n\t\t\t\t\tfontFamily: config?.style?.subheading?.subheadingFontFamily || \"'Inter', sans-serif\",\n\t\t\t\t\tfontSize: config?.style?.subheading?.subheadingFontSize || \"14px\",\n\t\t\t\t\tcolor: config?.style?.subheading?.subheadingColor || \"#4b5563\",\n\t\t\t\t\tfontWeight: config?.style?.subheading?.subheadingFontWeight || \"normal\",\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t{translate?.(LanguageKeys.phonePlacementDescription)}\n\t\t\t</p>\n\t\t\t<div className=\"relative w-full h-full flex flex-col items-center max-w-md pt-[1rem]\">\n\t\t\t\t<div className=\"relative w-full h-auto\">\n\t\t\t\t\t<video className=\"h-full w-full object-contain border-none\" muted loop autoPlay playsInline>\n\t\t\t\t\t\t<source src={gender === GenderType.Male ? maleSetupVideo : setupVideo} type=\"video/mp4\" />\n\t\t\t\t\t</video>\n\t\t\t\t</div>\n\n\t\t\t\t<div className=\"absolute bottom-[0] max-w-[28rem] mx-auto w-full left-0 right-0 flex justify-center max-w-md mx-auto\">\n\t\t\t\t\t<div className=\"flex justify-end w-full\">\n\t\t\t\t\t\t<SpecificButton buttonFunc={() => onNext?.()} data-testid=\"educational-next-btn\" buttonText={translate?.(LanguageKeys.continue)} postfixIcon={<ArrowRight />} />\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n","import { useState } from \"react\";\nimport MuseSteps from \"./MuseSteps\";\nimport VolumeStep from \"./VolumeStep\";\nimport SetupScreen from \"./SetupScreen\";\nimport { EducationalProps } from \"../../types/interfaces\";\nimport { GenderType, MuseScreenStep, SectionType } from \"../../utils/enums\";\n\nconst EducationalStepsWrapper = ({ sections, gender, onComplete, isCustom, startStep }: EducationalProps) => {\n\tconst [step, setStep] = useState(startStep ?? 1);\n\n\tswitch (step) {\n\t\tcase 1:\n\t\t\treturn (\n\t\t\t\t<MuseSteps\n\t\t\t\t\tapplicableScreens={\n\t\t\t\t\t\tsections?.[0] === SectionType.Full || !sections || !sections?.length\n\t\t\t\t\t\t\t? undefined\n\t\t\t\t\t\t\t: sections[0] === SectionType.Body\n\t\t\t\t\t\t\t? [MuseScreenStep.Body, MuseScreenStep.SizeFit, MuseScreenStep.Ready]\n\t\t\t\t\t\t\t: [MuseScreenStep.Face, MuseScreenStep.SizeFit]\n\t\t\t\t\t}\n\t\t\t\t\tisCustom={isCustom}\n\t\t\t\t\tgender={gender || GenderType.Male}\n\t\t\t\t\tonNext={() => setStep(2)}\n\t\t\t\t/>\n\t\t\t);\n\n\t\tcase 2:\n\t\t\treturn <VolumeStep onNext={() => (sections?.[0] === SectionType.Face ? onComplete?.() : setStep(3))} />;\n\n\t\tcase 3:\n\t\t\treturn <SetupScreen gender={gender || GenderType.Male} onNext={onComplete} />;\n\n\t\tdefault:\n\t\t\treturn <></>;\n\t}\n};\n\nexport default EducationalStepsWrapper;\n","import { EducationalProps } from \"../../types/interfaces\";\nimport { GenderType } from \"../../utils/enums\";\nimport EducationalStepsWrapper from \"./EducationalStepsWrapper\";\nimport LanguageContextProvider from \"../../utils/context/languageContext\";\nimport { ConfigProvider } from \"../../utils/context/configContext\";\n\nexport const Educational: React.FC<EducationalProps> = ({\n sections = [],\n config,\n gender = GenderType.Male,\n onComplete,\n isCustom,\n startStep,\n}) => {\n return (\n <LanguageContextProvider>\n <ConfigProvider config={config}>\n <EducationalStepsWrapper\n sections={sections}\n gender={gender}\n onComplete={onComplete}\n isCustom={isCustom}\n startStep={startStep}\n />\n </ConfigProvider>\n </LanguageContextProvider>\n );\n};\n"],"names":["cn","classes","filter","Boolean","join","CustomInput","React","forwardRef","className","type","props","ref","config","useConfig","input","style","priority","_jsxs","_Fragment","children","_jsx","autoCapitalize","autoCorrect","background","inputBackgroundColor","color","inputTextColor","fontSize","inputFontSize","fontWeight","inputFontWeight","border","inputBorderColor","fontFamily","base","baseFontFamily","borderRadius","inputBorderRadius","inputPlaceholderColor","displayName","EmailStep","onComplete","initialValue","onStepComplete","value","setValue","useState","message","setMessage","undefined","loading","setLoading","translate","useContext","LanguageContext","onSubmit","async","e","preventDefault","trim","LanguageKeys","emailRequired","isValidEmail","validEmail","error","handleErrorMessage","required","id","placeholder","enterEmail","onChange","target","inputErrorColor","inputErrorFontSize","SpecificButton","disabled","buttonText","next","postfixIcon","ArrowRight","size","NameStep","nameRequired","enterName","GenderStep","genderType","setGenderType","bgColor","textColor","selectedBgColor","inputBackgroundColorSelect","selectedTextColor","inputBackgroundColorSelectTextColor","GenderType","Male","onClick","primaryColor","mens","Female","womens","buttonFunc","HeightStep","localHeight","setLocalHeight","cm","String","ft","inch","measurementUnit","setMeasurementUnit","preferredLanguage","inputBg","inputText","handleSetHeight","useCallback","event","prev","handleMeasurementUnit","val","validateHeight","height","convertToCentimeters","checkMeasurement","heightError","isButtonDisabled","useMemo","useEffect","renderHeightInput","inputMode","heightInFt","heightInInch","Select","MenuItem","cmMeasurementUnit","ftMeasurementUnit","ProgressDots","totalSteps","currentStepIndex","activeColor","inactiveColor","secondaryColor","dots","Array","from","length","_","i","index","isActive","isCompleted","map","backgroundColor","StepsWrapper","currentStep","onStepDone","stepOrder","visibleSteps","resolvedConfig","unsupportedStep","absoluteIndex","indexOf","logo","src","alt","logoHeight","width","logoWidth","heading","headingFontFamily","headingFontSize","headingColor","headingFontWeight","onboarding","commonProps","OnboardingStep","Email","Name","Gender","Height","noValidSteps","renderStep","DevicesList","Onboarding","steps","onDeviceDetected","handleWURFLDetectionComplete","wurfl","window","WURFL","phoneModel","brand_name","model_name","focal_length","entry","find","el","marketing_name","deviceInfo","brandName","modelName","focalLength","payload","data","JSON","stringify","location","posthog","capture","console","log","document","addEventListener","script","createElement","head","appendChild","removeEventListener","usePhoneDetection","resolveSteps","values","setValues","stepIndex","setStepIndex","s","isVisible","handleStepComplete","updated","LanguageContextProvider","ConfigProvider","FocalLengthWrapper","setDeviceInfo","model","manufacturerMenuItems","manufacturer","Object","keys","phoneModelMenuItems","brandMatch","phone","handleSubmit","Header","subtitle","selectPhoneBrand","selectPhoneModel","selectedId","m","foundModel","FocalLength","MuseScreenRenderer","screenIndex","scanLinePosition","faceZoomed","showFaceScanLine","faceScanLinePosition","showLargeS","typewriterText","fullText","screens","videoToShow","faceScanVideo","sizeVideo","formFittingVideo","screen","componentProps","body","face","sizeFit","hasComponent","component","Comp","content","image","muted","loop","autoPlay","playsInline","preload","AnimatePresence","mode","motion","div","initial","opacity","y","animate","exit","transition","duration","MuseScreenStep","Body","title","bodyScan","description","bodyScanDescription","bodyScanPerson","Face","faceScan","faceScanDescription","faceScanPerson","left","top","SizeFit","leSableDress","Ready","readyToStart","readyToStartDescription","fittingGuide","MuseSteps","applicableScreens","gender","onNext","isCustom","currentScreen","setCurrentScreen","setScanLinePosition","setFaceZoomed","setFaceScanLinePosition","setShowFaceScanLine","currentOutfit","setCurrentOutfit","setTypewriterText","setShowLargeS","screensToShow","reduce","acc","includes","push","screenId","outfitImages","animationRefs","useRef","scan","outfit","typewriter","cleanupAnimations","current","forEach","cancelAnimationFrame","clearTimeout","clearInterval","startTime","Date","now","animateScanLine","elapsed","progress","Math","min","requestAnimationFrame","setTimeout","animateFaceScanLine","setInterval","currentIndex","typeNextChar","slice","useMuseAnimations","OUTFIT_IMAGES","noTitle","subheading","subheadingFontFamily","subheadingFontSize","subheadingColor","subheadingFontWeight","maleScanVideo","femaleScanVideo","maleFaceScanVideo","maleSizeSuggestions","sizeSuggestions","maleFormFittingGuide","formFittingGuide","VolumeScreen","mousePosition","setMousePosition","x","isAnimationPaused","setIsAnimationPaused","handleMouseMove","clientX","clientY","hexToRgba","hex","alpha","replace","split","h","parseInt","substring","brandColor","rgba1","rgba2","rgba3","holographicStyle","windowWidth","innerWidth","windowHeight","innerHeight","normalizedX","transform","boxShadow","calculateHolographicEffect","minHeight","minWidth","margin","animation","Volume2","turnUpVolume","continue","SetupScreen","phonePlacement","phonePlacementDescription","maleSetupVideo","setupVideo","EducationalStepsWrapper","sections","startStep","step","setStep","SectionType","Full","VolumeStep","Educational"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@swan-admin/swan-web-component",
3
- "version": "1.0.123",
3
+ "version": "1.0.124",
4
4
  "description": "Cross-framework Onboarding component (React + Angular compatible)",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -1,3 +0,0 @@
1
- 'use client';
2
- import{jsx as e,jsxs as t,Fragment as n}from"react/jsx-runtime";import r,{useState as a,useCallback as s,useEffect as o,createContext as c,useLayoutEffect as i,useMemo as l,useContext as u,useRef as d}from"react";import{L as m,u as p,H as f,b as h,S as g,z as y,a as v,i as w,P as b,p as x,o as S,s as D,j as C,k as N,l as I,x as k,A as T,q as F,r as _,f as E,B as M,D as $,c as L,M as U,v as j,E as A,I as P,V as z,J as V,K as R,N as B,G as q,O as K,Q as O,R as W,h as H,n as J,w as G,T as Q,t as Y,C as X,y as Z}from"./Modal-CZgyeNwW.mjs";import ee from"clsx";import te from"react-webcam";import{X as ne}from"lucide-react";import{Dialog as re,Box as ae,Drawer as se}from"@mui/material";import oe from"video.js";const ce="DESKTOP",ie="TAB",le="MOBILE",ue=c(void 0);function de({children:t}){const[n,r]=a([window?.innerWidth,window?.innerHeight]),[s,c]=a(!1),u=()=>{r([window?.innerWidth,window?.innerHeight])};o(()=>{u()},[]),i(()=>(window.addEventListener("resize",u),()=>window.removeEventListener("resize",u)),[u]);let d=ce;n[0]>768&&n[0]<1024&&(d=ie),n[0]<768&&(d=le);const m=l(()=>({size:n,setSize:r,clearInputs:s,setClearInputs:c,media:d}),[n,s,d]);return e(ue.Provider,{value:m,children:t})}var me=r.memo(function({size:n=16}){return t("svg",{width:n,height:n,viewBox:"0 0 25 25",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[e("path",{d:"M22.6968 14.6968C22.6968 16.8185 21.8539 18.8533 20.3536 20.3536C18.8533 21.8539 16.8185 22.6968 14.6968 22.6968",stroke:"white",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"}),e("path",{d:"M18.6968 11.6968V10.6968C18.6968 10.1663 18.4861 9.65764 18.111 9.28256C17.7359 8.90749 17.2272 8.69678 16.6968 8.69678C16.1663 8.69678 15.6576 8.90749 15.2826 9.28256C14.9075 9.65764 14.6968 10.1663 14.6968 10.6968",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"}),e("path",{d:"M14.6968 10.6968V9.69678C14.6968 9.16634 14.4861 8.65764 14.111 8.28256C13.7359 7.90749 13.2272 7.69678 12.6968 7.69678C12.1663 7.69678 11.6576 7.90749 11.2826 8.28256C10.9075 8.65764 10.6968 9.16634 10.6968 9.69678V10.6968",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"}),e("path",{d:"M10.6968 10.1968V4.69678C10.6968 4.16634 10.4861 3.65764 10.111 3.28256C9.73592 2.90749 9.22721 2.69678 8.69678 2.69678C8.16634 2.69678 7.65764 2.90749 7.28256 3.28256C6.90749 3.65764 6.69678 4.16634 6.69678 4.69678V14.6968",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"}),e("path",{d:"M18.6969 11.6968C18.6969 11.1663 18.9076 10.6576 19.2827 10.2826C19.6577 9.90749 20.1664 9.69678 20.6969 9.69678C21.2273 9.69678 21.736 9.90749 22.1111 10.2826C22.4862 10.6576 22.6969 11.1663 22.6969 11.6968V14.6968C22.6969 16.8185 21.854 18.8533 20.3537 20.3536C18.8534 21.8539 16.8186 22.6968 14.6969 22.6968H12.6969C9.89688 22.6968 8.19688 21.8368 6.70688 20.3568L3.10688 16.7568C2.76282 16.3757 2.57847 15.8769 2.592 15.3637C2.60554 14.8505 2.81593 14.3621 3.1796 13.9997C3.54327 13.6373 4.03238 13.4287 4.54565 13.417C5.05892 13.4053 5.55704 13.5914 5.93688 13.9368L7.69688 15.6968",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})]})});var pe=r.memo(function({angle:n,countdown:r,isScanning:a,isInTargetRange:o,stabilityScore:c,children:i}){const{translate:d}=u(m)||{},g=p(),y=s(()=>n<80?Math.max(0,Math.min(100,10*(n-60))):n>95?Math.max(0,Math.min(100,10*(105-n))):100,[n]),v=l(()=>{if(a)return g?.style?.angleDetector?.successAngleBackground||"#4f46e5";const e=y();if(0===e)return g?.style?.angleDetector?.successAngleLowBackground||"#ffffff";if(100===e)return g?.style?.angleDetector?.successAngleBackground||"#4f46e5";return`rgb(${Math.round(255-e/100*116)}, ${Math.round(255-e/100*163)}, ${Math.round(255-e/100*9)})`},[a,y]),w=s((e,t)=>t>70?e?`text-[${g?.style?.angleDetector?.successAngleTextLightColor}]/70`:`text-[${g?.style?.angleDetector?.successAngleTextLightColor}]`:e?`text-[${g?.style?.angleDetector?.successAngleTextLightColor}]/40`:`text-[${g?.style?.angleDetector?.successAngleTextDarkColor}]/70`,[]),b=s((e=!1)=>{const t=y();return a?`text-[${g?.style?.angleDetector?.successAngleTextLightColor}]`:w(e,t)},[a,y]),x=s((e,t)=>t>70||e?g?.style?.angleDetector?.successAngleTextLightColor:g?.style?.angleDetector?.successAngleTextDarkColor,[]),S=s((e=!1)=>{const t=y();return a?g?.style?.angleDetector?.successAngleTextLightColor:x(e,t)},[a,y]),D=r;function C(){document.documentElement.style.setProperty("--real-vh",window.innerHeight+"px")}return C(),window.addEventListener("resize",C),t("div",{className:"flex common-ui-main w-screen flex-col items-center h-[var(--real-vh)] overflow-hidden touch-none justify-center transition-all duration-300 max-w-[28rem] mx-auto",style:{backgroundColor:v},"data-testid":"level-screen","data-angle-state":a?"locked":o?"target":"adjusting",children:[e("div",{className:"flex justify-start fixed top-[.5rem] max-w-[28rem] mx-auto w-full px-[1rem]",children:e("div",{className:"flex justify-start ",children:e(f,{noTitle:!0})})}),null!==D?e("div",{className:"relative flex h-[6rem] w-[6rem] items-center justify-center rounded-[9999px] bg-[#fff]/20 transition-all duration-300",style:{border:`2px solid ${S()}`},children:e("div",{className:`text-[3rem] font-bold text-[${S()}]`,style:{fontFamily:g?.style?.base?.baseFontFamily||"Inter, sans-serif",color:S()},children:D})}):t("div",a?{className:"relative flex flex-col items-center justify-center",children:[e("div",{className:"relative flex h-16 w-16 items-center justify-center rounded-[9999px] border-2 bg-[#fff]/30 border-[#fff]",children:e("div",{className:"h-4 w-4 rounded-[9999px] animate-pulse bg-[#fff]/80"})}),i]}:{className:ee("relative flex h-[4rem] w-[4rem] items-center justify-center rounded-[9999px] ",o?"bg-[#fff]/20 border-[#fff]":"bg-[#fff]/10 border-[#fff]"),style:{transform:`translateY(${3*(90-n)}px)`,transition:"transform 0.2s ease-out",border:`2px solid ${S()}`},children:[e("div",{className:`h-[1rem] w-[1rem] rounded-[9999px] bg-[${S()}]/80`,style:{backgroundColor:`${S()}B3`}}),t("div",{className:ee("mt-[.5rem] text-center w-[180px] flex-col flex items-center absolute top-[60px]",b()),style:{color:S()},children:[e(me,{size:30}),t("p",{style:{fontFamily:g?.style?.base?.baseFontFamily||"Inter, sans-serif"},children:[" ",d?.(h.startLevelCheck),e("br",{})]})]})]}),null!==D&&e("div",{className:"absolute bottom-[8rem] text-center",children:e("div",{className:ee("text-sm font-medium px-4 py-1.5 bg-black/20 rounded-[9999px] mt-8",b()),style:{fontFamily:g?.style?.base?.baseFontFamily||"Inter, sans-serif",color:S()},children:d?.(h.leavePhone)})}),o&&null===D&&!a&&e("div",{className:"absolute bottom-[8rem] w-[12rem]",children:e("div",{className:`h-[.375rem] w-full bg-[${S()}]/20 rounded-[9999px] overflow-hidden`,style:{backgroundColor:`${S()}33`},children:e("div",{className:`h-full bg-[${S()}]/70 transition-all duration-300 rounded-[9999px]`,style:{width:`${n}%`,backgroundColor:`${S()}B3`}})})}),null===D&&!a&&e("div",{className:"absolute bottom-[5rem] text-center",children:t("div",{className:ee("text-[1.5rem] font-light",b()),style:{color:S()},children:[Math.round(n),"°"]})}),null===D&&!a&&e("div",{className:"absolute bottom-[2rem] text-center max-w-[20rem] mx-auto",children:e("div",{className:ee("text-[.75rem] opacity-50",b()),style:{fontFamily:g?.style?.base?.baseFontFamily||"Inter, sans-serif",color:S()},children:d?.(h.placePhoneUpright)})})]})});function fe({resetScan:n,loadingCam:r,onUserMedia:a,onPause:s,pause:o,onReScan:c,recordingStarted:i,startSendingVideoFrames:l,showPause:d,webcamRef:p,onUserMediaError:f,resetDetector:w,videoConstraints:b,webcamKey:x,faceDone:S,isScanning:D}){const{media:C}=u(ue)||{},{translate:N}=u(m)||{};return t("div",{className:"App w-screen h-[100vh] relative common-ui-main","data-testid":"camera-scan","data-scan-phase":S?"spinning":i?"pose-detecting":D?"starting":"ready",children:[e("span",{onClick:()=>{n(),w()},className:"fixed right-[20px] top-[20px] z-[999]",children:e(ne,{className:"text-[#fff]"})}),e("div",{className:"w-full h-full overflow-hidden ",children:C===le&&e(te,{audio:!1,ref:p,screenshotQuality:1,videoConstraints:b,mirrored:!0,screenshotFormat:"image/jpeg",onUserMedia:a,onUserMediaError:f,style:{position:"fixed",top:0,bottom:0,zIndex:0,width:"100%",height:"100%",objectFit:"cover"}},x)}),t("div",{className:"fixed bottom-[30px] w-full z-[999] flex flex-col gap-4 items-center justify-center",children:[d&&e(g,{className:"!w-[180px] !h-[40px] !py-[0] mx-auto ",prefix:y,buttonText:N?.(h.pause),buttonFunc:s,btnSecondary:!0}),o?e("div",{children:e(g,{className:"!w-[180px] !h-[40px] !py-[0] mx-auto",buttonText:N?.(h.restart),buttonFunc:c,btnSecondary:!0})}):i?null:e(g,{"data-testid":"start-scan-btn",className:"!w-[180px] !h-[40px] !py-[0] mx-auto !bg-[#ffffff] !text-[#000000] "+(r?"!opacity-50":""),buttonText:N?.(h.startScan),buttonFunc:l,disabled:r})]}),e("audio",{id:"audioElement",crossOrigin:"anonymous",preload:"auto",style:{position:"absolute",zIndex:-99999},src:`${v}scanAudioInstructions/silence.mp3`})]})}let he=null,ge=null,ye=null;let ve,we=null;var be=r.memo(function({setIsScanLocked:t,resetDetector:n,scanID:r,setIsVideoUploaded:c,setScanFailsError:i,setScanStartTime:m,setScanUniqueKey:p,userDetails:f}){const{email:h,shopDomain:g,gender:y,heightInCm:$}=f,L=d(null),U=d(null),j=d(null),[A,P]=a([]),[z,V]=a(!0),[R,B]=a(!1),[q,K]=a(!1),[O,W]=a(!0),[H,J]=a(!1),G=d(null),[Q,Y]=a(""),[X,Z]=a([]),[ee,te]=a(""),[ne,re]=a(!1),[ae,se]=a(!1),[oe,ce]=a(!1),[ie,le]=a([]),[ue,de]=a(!1),me=d(!0),{poseDetector:pe}=function(){const[e,t]=a(0),[n,r]=a(0),[s,c]=a(!1),i=d(0),l=d(0),u=d(!0);async function m(){if("undefined"==typeof window||"undefined"==typeof navigator)return!1;try{console.log("Starting TensorFlow preload...");const[e,t,n]=await Promise.all([import("./pose-detection.esm-EvS-BndH.mjs"),import("@tensorflow/tfjs-core"),import("@tensorflow/tfjs-backend-webgl")]);ye=e,await t.setBackend("webgl"),await t.ready(),console.log("TensorFlow backend ready (WebGL)");const r={runtime:"mediapipe",modelType:"full",solutionPath:"https://cdn.jsdelivr.net/npm/@mediapipe/pose"};try{ge=await ye.createDetector(ye.SupportedModels.BlazePose,r),console.log("MediaPipe detector created successfully")}catch(e){console.warn("MediaPipe failed, falling back to TFJS runtime:",e),ge=await ye.createDetector(ye.SupportedModels.BlazePose,{runtime:"tfjs",modelType:"full"}),console.log("TFJS detector created successfully")}return!0}catch(e){return console.error("Failed to load TensorFlow dependencies:",e),he=null,!1}}function p(e){return!(!e||0===e.length)&&22===e.filter(e=>e[2]>.7).length}return o(()=>{if(u.current=!0,!ge)return he||(he=m()),he.then(e=>{e&&u.current&&c(!0)}),()=>{u.current=!1};c(!0)},[]),o(()=>{l.current=e,e>6&&i.current<2&&(r(e=>e+1),t(0))},[e]),o(()=>{i.current=n},[n]),{poseDetector:async(e,n)=>{if(!ge||!u.current||!n?.current?.video)return;const r=n.current.video;if(!(r.readyState<2))try{const n=await ge.estimatePoses(r,{flipHorizontal:!1});if(!n||!n.length)return;const a=n[0].keypoints.slice(11).map(e=>[e.x>0&&e.x<720?e.x:-1,e.y>0&&e.y<1280?e.y:-1,e.score??0]);0!==i.current||p(a)||t(e=>e+1),1===i.current&&p(a)&&t(e=>e+1),2===i.current&&e()}catch(e){console.error("Pose detection error:",e)}},isLoaded:s,spinPhase:n,resetDetector:()=>{i.current=0,l.current=0,t(0),r(0)},retryLoading:async()=>{ge||he||(he=m(),await he&&u.current&&c(!0))}}}(),be=d(!0),xe=d(!1),Se=d(0),De=d(0),Ce=d(0),Ne=d(0),Ie=d(!1),ke=d(!1),Te=d(!1),Fe=d(()=>{}),_e=d(()=>{}),Ee=d(null),[Me,$e]=a([]),[Le,Ue]=a(0),[je,Ae]=a(w),{setStartGyro:Pe,uploadScanFile:ze,setUploadLoading:Ve,swan:Re,onScanStart:Be,onCaptureComplete:qe}=u(b),Ke=d(r);o(()=>{Ke.current=r},[r]);const Oe=d(ie);o(()=>{Oe.current=ie},[ie]);const We=function({timeoutMs:e,onTimeout:t}){const n=d(null),r=d(t);o(()=>{r.current=t},[t]);const a=s(()=>{n.current&&(clearTimeout(n.current),n.current=null)},[]),c=s(()=>{n.current&&clearTimeout(n.current),n.current=setTimeout(()=>{n.current=null,r.current()},e)},[e]);return o(()=>a,[a]),{start:c,pet:c,stop:a}}({timeoutMs:12e3,onTimeout:s(()=>{x.capture(`${g}/pose_feedback_timeout`,{scanID:Ke.current,email:h,framesSent:Ce.current,id:Ee.current})},[g,h])}),He=()=>{xe.current=!1,We.stop(),clearTimeout(ve),G.current&&clearTimeout(G.current),p(E()),i(""),Ve?.(!1),P([]),j.current=null,V(!0),B(!1),K(!1),W(!0),J(!1),G.current=null,Y(""),Z([]),te(""),re(!ne),Pe(!1),D.stopAudio(),se(!1),ce(!1),Se.current=0,De.current=0,Ce.current=0,Ne.current=0,Ie.current=!1,Te.current=!1,null!==U.current&&U.current.stop(),ie.forEach(e=>{U.current&&U.current.removeEventListener("dataavailable",e)}),le([]),me.current=!0,de(!1),c(!1),L.current?.stream&&V(!1)},Je=s(()=>{setTimeout(()=>{V(!1)},1e3)},[]),Ge=s(e=>{if(console.log("camera error",e),je===w)return Ae(S),void Ue(e=>e+1);V(!1)},[je]),Qe=s(()=>{me.current=!1,We.stop(),ce(!0),de(!1),G.current&&clearTimeout(G.current),U.current&&U.current.pause(),D.stopAudio(),Re.poseDetection.disconnect(),x.capture(`${g}/pose_detection_disconnected`,{scanID:r,email:h,id:Ee.current,reason:"pause"}),Se.current=0,De.current=0,Ie.current=!1,Te.current=!1,U.current&&U.current.stop(),ie.forEach(e=>{U.current&&U.current.removeEventListener("dataavailable",e)}),le([]),clearTimeout(ve)},[U,ie,D,me]),Ye=l(()=>C(),[]),Xe=N(Me),Ze=I(Xe),et=s(async()=>{me.current=!0,await D.playAudio(`${v}SpotOn.mp3`),ce(!1),de(!1),G.current&&clearTimeout(G.current),B(!1)},[G,D]),tt=s(async()=>{if(!ke.current&&!Ee.current){ke.current=!0;try{Ee.current=await Re.poseDetection.connect(),x.capture(`${g}/pose_detection_connected`,{scanID:Ke.current,email:h,id:Ee.current})}catch(e){console.log(e,"while connecting websocket"),x.capture(`${g}/pose_detection_connect_failed`,{scanID:r,email:h,error:String(e)})}finally{ke.current=!1}}},[r,g,h]),nt=s(({data:e})=>{e&&e.size>0&&me.current&&(P(t=>t.concat(e)),!xe.current&&L.current&&(xe.current=!0,pe(()=>{et(),k({eventName:`${g}/tensorFlow`,scanID:Ke.current,email:h,message:"recording stopped by tensorflow "})},L)))},[et,k,g,h,L]),rt=s(async()=>{const e=X[X.length-1];e&&me.current&&(await D.playAudio(v+e),me.current&&(ve=setTimeout(rt,2e3)))},[X,me]),at=s(()=>{U&&U.current&&U.current.stop(),B(!0);try{if(L&&L.current&&L.current.stream){const e=L.current.stream.getVideoTracks()[0];if(e){const t=e.getSettings();j.current=t.frameRate||null}const t={videoBitsPerSecond:15e5};Me[0]&&(t.mimeType=Me[0]),U.current=new MediaRecorder(L.current.stream,t),U.current.addEventListener("dataavailable",nt),U.current.addEventListener("stop",()=>{W(!0)}),le([...ie,nt]),U.current.start(1e3),W(!1)}}catch(e){console.log("error while using media recorder",e)}},[L,Me,nt,ie]),st=s(async()=>{G.current&&clearTimeout(G.current),at(),me.current&&(G.current=setTimeout(async()=>{me.current&&(await D.playAudio(`${v}SpotOn.mp3`),B(!1))},15e3)),K(!0),me.current&&await D.playAudio(`${v}Spin.mp3`)},[at,me,D]);o(()=>{Fe.current=st},[st]);const ot=s(({data:e})=>{const t=Re.poseDetection.connected();if(e.size>0&&t){Ie.current||(Ie.current=!0,Re.poseDetection.poseStatus(async e=>{if(We.pet(),x.capture(`${g}/pose_instruction_received`,{scanID:Ke.current,email:h,audio:e?.audio??"",audioEmpty:!(e?.audio&&e.audio.length>0),status:e?.status,sid:e?.sid,sidMatchesConnection:e?.sid===Ee.current,counter:Se.current,consecutiveFalse:De.current,type:"body_scan_instruction"}),e&&e.audio&&e.audio.length>0){const t=document.querySelector("#audioElement");!0===e.status&&e.sid===Ee.current?(De.current=0,Se.current<2?(Se.current+=1,1!==Se.current||Te.current?2===Se.current&&t?.paused&&(clearTimeout(ve),D.playAudio(v+e.audio)):(Te.current=!0,clearTimeout(ve),D.stopAudio(),await D.playAudio(v+e.audio))):(We.stop(),te(e.audio),clearTimeout(ve),Re.poseDetection.disconnect(),x.capture(`${g}/pose_detection_disconnected`,{scanID:r,email:h,id:Ee.current,reason:"pose_confirmed"}),Ie.current=!1,setTimeout(()=>Fe.current(),1e3))):(De.current+=1,De.current>=3&&(Se.current=0,Te.current=!1),!t?.paused||we&&we?.audioName===e.audio?we?.audioName===e.audio&&t?.paused&&(we&&we.no_of_times_skipped>=we.skipCount?(we.no_of_times_skipped=0,D.playAudio(v+e.audio)):we&&(we.no_of_times_skipped+=1)):(we={skipCount:2,no_of_times_skipped:0,audioName:e.audio},D.playAudio(v+e.audio)))}}));const e=L?.current?L.current.getScreenshot():null;e?(Ce.current+=1,1===Ce.current&&We.start(),Re.poseDetection.videoEmit({image:e,scanId:Ke.current}),1!==Ce.current&&Ce.current%5!=0||x.capture(`${g}/pose_frame_sent`,{scanID:Ke.current,email:h,sid:Ee.current,framesSent:Ce.current})):(Ne.current+=1,1!==Ne.current&&Ne.current%5!=0||x.capture(`${g}/pose_frame_skipped_null`,{scanID:Ke.current,email:h,framesSkipped:Ne.current}))}},[L,r,Re,D,g,h]),ct=s(async()=>{J(!0),Pe(!0),Be?.(),be.current&&(be.current=!1,k({eventName:"scan started",scanID:Ke.current,status:"success",email:h})),m(T()),V(!0),me.current&&await D.playAudio(`${v}StartScan.mp3`),me.current&&await D.playAudio(`${v}LiftArmsAndHoldAtHip.mp3`),me.current&&(J(!1),B(!0),se(!0),de(!0),Je());try{if(L&&L.current&&L.current.stream&&me.current){const e=L.current.stream.getVideoTracks()[0];if(e){const t=e.getSettings();j.current=t.frameRate||null}const t={videoBitsPerSecond:15e5};Me[0]&&(t.mimeType=Me[0]),me.current&&(U.current=new MediaRecorder(L.current.stream,t)),me.current&&U.current&&U.current.addEventListener("dataavailable",ot),le([...Oe.current,ot]),U.current&&U.current.start(1e3),W(!1),me.current&&(ve=setTimeout(rt,2e3))}}catch(e){console.log("error ----------",e)}},[L,Me,ot,rt,me,Be]);return o(()=>{_e.current=ct},[ct]),o(()=>(g&&(t(!0),tt()),()=>{const e=Ee.current;Ee.current=null,e&&(Re.poseDetection.disconnect(),x.capture(`${g}/pose_detection_disconnected`,{scanID:Ke.current,email:h,id:e,reason:"unmount"})),ie.forEach(e=>{U?.current?.removeEventListener("dataavailable",e)})}),[g]),o(()=>{X.push(Q)},[Q]),o(()=>{Z([])},[ee]),o(()=>{const e=A.length&&A.length>0;O||!e||R||!me.current||oe||U&&U.current&&(R||U.current.stop())},[O,R,A,oe]),o(()=>{const e=A.length&&A.length>0;if(O&&e&&!R&&U&&U.current&&me.current&&!oe&&!R){const e=new File(A,`${r}.${Ze}`,{type:Xe});qe?.(),Ve?.(!0),i(""),ze?.(e,j.current)}},[O,R,A,oe,U,me]),o(()=>{_e.current=ct},[ct]),o(()=>{const e=F(Ye,_);$e(e)},[Ye]),o(()=>{He()},[]),e(fe,{resetDetector:n,resetScan:He,loadingCam:z,onPause:Qe,showRestart:ae,pause:oe,onReScan:async()=>{M({eventName:`${g}/rescan`,email:h,scanID:Ke.current,height:$,gender:y,status:!1}),Re.poseDetection.disconnect(),He(),await tt()},recordingStarted:R,isScanning:H,startSendingVideoFrames:ct,faceDone:q,stopRecording:et,showPause:ue,webcamRef:L,onUserMedia:Je,onUserMediaError:Ge,videoConstraints:je,webcamKey:Le})});function xe({scanID:t,userDetails:n,setIsVideoUploaded:r,setScanFailsError:s,setScanStartTime:c,setScanUniqueKey:i}){const[l,u]=a(90),[m,p]=a(0),[f,h]=a(null),[g,y]=a(!1),[v,w]=a(0),b=d([]),[x,S]=a(!1),D=l-m,C=D>=80&&D<=95;o(()=>{if("undefined"!=typeof window&&window.DeviceOrientationEvent){const e=e=>{if(null!==e.beta){let t=Math.abs(e.beta);null!==e.gamma&&(t*=Math.cos(e.gamma*Math.PI/180)),t=Math.max(0,Math.min(180,t)),u(t)}},t=async()=>{const t=DeviceOrientationEvent;if(t&&"function"==typeof t.requestPermission)try{"granted"===await t.requestPermission()&&window.addEventListener("deviceorientation",e)}catch(e){console.error("Permission error",e)}else window.addEventListener("deviceorientation",e);return()=>{e&&window.removeEventListener("deviceorientation",e)}};document.addEventListener("click",t,{once:!0})}},[]),o(()=>{if(b.current=[...b.current.slice(-4),D],b.current.length>=5){const e=Math.max(...b.current)-Math.min(...b.current);w(C&&e<2?e=>Math.min(100,e+10):e=>Math.max(0,e-20))}C||null===f&&!g||I()},[D,C,f,g]),o(()=>{v>=100&&null===f&&!g&&N(),v<50&&null!==f&&I()},[v,f,g]);const N=()=>{h(3);const e=setInterval(()=>{h(t=>null===t||t<=1?(clearInterval(e),y(!0),null):t-1)},1e3)},I=()=>{h(null),x||y(!1)};return e(pe,{angle:D,countdown:f,isScanning:g,isInTargetRange:C,stabilityScore:v,children:g&&e(be,{setIsScanLocked:S,resetDetector:()=>{u(90),p(0),h(null),y(!1),w(0),S(!1),b.current=[]},scanID:t,userDetails:n,setIsVideoUploaded:r,setScanFailsError:s,setScanStartTime:c,setScanUniqueKey:i})})}function Se({setShowDrawer:t,config:n,loader:r}){const[c,i]=a({disabled:!1,message:""}),[l,u]=a(!0),m=d(null),p=s(async()=>{const e=await $();i(e),u(!1)},[]);return o(()=>{p()},[]),l?e(L,{url:r,loaderType:"black"}):c?.disabled?e(U,{config:n,message:c?.message}):e(te,{audio:!1,ref:m,screenshotQuality:1,videoConstraints:j,mirrored:!0,onUserMedia:()=>t?.(!0),screenshotFormat:"image/jpeg",style:{position:"relative",top:0,bottom:0,zIndex:0,width:"100%",height:"100%",objectFit:"cover"}})}function De({link:t,onReady:n,wrapperClassName:r="[&_video]:rounded-t-[20px] w-full h-full"}){const a=d(null),s=d(null);let c={autoplay:!0,controls:!1,responsive:!0,fluid:!0,muted:!0,navigationUI:"hide",preload:"metadata",poster:A};return o(()=>{if(!s.current&&t&&a?.current){const e=oe(a.current,{...c});e.ready(()=>{s.current=e;const r={...c,sources:[{src:t,type:"application/x-mpegURL"}]};e.autoplay(r.autoplay),e.src(r.sources),n?.(e)})}},[t,a]),o(()=>{const e=s.current;return()=>{e&&!e.isDisposed()&&(e.dispose(),s.current=null)}},[s]),e("div",{className:r,children:e("video",{ref:a,muted:!0,className:"video-js",playsInline:!0,onDrag:e=>e.preventDefault()})})}function Ce({scanFailsError:r,onNext:s,gender:o,setScanUniqueKey:c,setIsVideoUploaded:i}){const{translate:l}=u(m)||{},d=p(),[y,v]=a(!1),w=()=>{v(!y)};return t(n,{children:[t("div",{"data-testid":"scan-error-message",className:"flex common-ui-main flex-col h-full max-w-[28rem] mx-auto w-full rounded-t-[20px] overflow-y-auto",style:{background:d?.style?.base?.backgroundColor},children:[e("div",{className:"w-full max-w-[28rem] mx-auto pt-[1rem] px-[1rem]",children:e(f,{noTitle:!0})}),e("div",{className:"flex-1",children:r&&t("div",{className:"px-[1rem]",children:[e("h2",{className:"text-center",style:{fontFamily:d?.style?.heading?.headingFontFamily||"SeriouslyNostalgic Fn",fontSize:d?.style?.heading?.headingFontSize||"32px",color:d?.style?.heading?.headingColor||"#000",fontWeight:d?.style?.heading?.headingFontWeight||"normal"},children:l?.(h.issueWithScan)}),e("p",{style:{fontFamily:d?.style?.base?.baseFontFamily||"Inter, sans-serif",fontSize:d?.style?.base?.baseFontSize||"16px",color:d?.style?.base?.baseTextColor||"#1E1E1E"},children:l?.(h.reason)}),e("p",{style:{fontFamily:d?.style?.base?.baseFontFamily||"Inter, sans-serif",fontSize:d?.style?.base?.baseFontSize||"16px",color:d?.style?.base?.baseTextColor||"#1E1E1E"},children:P(r)}),e("img",{className:"my-[0.5rem] aspect-[2/1.4] w-full object-cover",onClick:w,src:z[o],alt:"icon"})]})}),r&&e("div",{className:"p-[1rem] flex gap-[0.5rem]",children:e(g,{"data-testid":"scan-again-btn",disabled:!1,buttonText:l?.(h.scanAgain),className:"!shadow-none",buttonFunc:()=>{s?s?.():c?.(E()),i?.(!1)}})})]}),y&&t(re,{className:"w-screen h-screen video-modal",onClose:w,open:y,children:[e("div",{className:"flex justifyEnd ",children:e("span",{className:"closeBtn",onClick:w,children:e(ne,{className:"absolute right-[8px] top-[8px] text-white z-[9]"})})}),e("div",{className:"aspect-video object-cover rounded-[20px] ",children:e(De,{link:o?V[o].PRE_LINK:V.male.PRE_LINK,wrapperClassName:"w-screen h-screen fixed top-[0] left-[0]"})})]})]})}function Ne({scanId:n,userDetails:r,config:c,isVideoUploadedCorrect:i,isMeasurementAvailable:l,onComplete:d,isSuccess:p,onCustomScanSuccess:y,swan:v}){const{gender:w,shopDomain:b,heightInCm:S,deviceFocalLength:D,userName:C,email:N,scanType:I}=r||{},k=[K,O,W].includes(I??""),[T,F]=a(!0),_=s(async()=>{try{k&&(await(v?.auth.addUser({scanId:n,email:N,name:C,gender:w,height:S})),y?.()),x.capture(b??"",{scanID:n,email:N,height:S,focalLength:D,clothesFit:"0",gender:w})}catch(e){console.log(e)}},[k]),{translate:E}=u(m)||{};o(()=>{(i||l)&&_()},[i,l]);const M=(p||i||l)&&!k;return e(ae,{className:"flex h-full w-full flex-col common-ui-main",children:t("div",{className:"h-full w-full flex-col items-center justify-center flex",children:[e(Se,{loader:c?.loader,setShowDrawer:F}),e(se,{open:T,onClose:(e,t)=>{},className:"camera-drawer",anchor:"bottom",children:e("div",{className:"max-w-[28rem] mx-auto w-full h-full flex text-center flex-col justify-between items-center bg-primary rounded-t-[30px] p-[1rem]",style:{background:c?.style?.base?.backgroundColor},children:t("div",{className:"w-full h-full flex flex-col",children:[e(f,{title:E?.(h.measurementsBeingTaken)}),e("div",{className:"flex items-center justify-center flex-1",children:e("video",{preload:"auto",className:"max-h-[calc(100vh-450px)] mx-auto w-full object-contain border-none",muted:!0,loop:!0,autoPlay:!0,playsInline:!0,children:e("source",{src:w===q.Male?R:B,type:"video/mp4"})})}),M&&e(g,{className:"!w-[180px] mx-auto",buttonText:E?.(h.next),buttonFunc:()=>{d?.()}})]})})})]})})}const Ie=()=>{const{userDetails:n,onRetry:r,isError:a,isSuccess:s,gender:o,scanUniqueKey:c,scanFailsError:i,setScanUniqueKey:l,setIsVideoUploaded:d,isMeasurementAvailable:m,isVideoUploadedCorrect:f,loading:h,showDeniedModal:g,uploadLoading:y,setScanFailsError:v,setScanStartTime:w,resetScan:x,onCustomScanSuccess:S,swan:D,onComplete:C}=u(b),N=p();return a?t("div",{"data-scan-state":"error",children:[e(Se,{}),e(se,{anchor:"bottom",open:!0,className:"camera-drawer",onClose:(e,t)=>{},children:e(Ce,{scanFailsError:!0,onNext:r,gender:o})})]}):s?e("div",{"data-scan-state":"success",children:e(Ne,{isSuccess:!0,onComplete:C})}):h?e("div",{"data-scan-state":"loading",className:"flex top-0 !mt-0 left-0 z-[999] absolute justify-center items-center w-full h-full",style:{background:N?.style?.base?.backgroundColor},children:e(L,{url:N?.loader,loaderType:"black"})}):g.disabled?e("div",{"data-scan-state":"camera-denied",children:e(U,{})}):y||i||m||f?(y||m||f)&&!i?e("div",{"data-scan-state":"processing",children:e(Ne,{scanId:c,isMeasurementAvailable:m,userDetails:n,isVideoUploadedCorrect:f,onCustomScanSuccess:S,swan:D,onComplete:C,config:N})}):t("div",{"data-scan-state":"error-retry",children:[e(Se,{}),e(se,{anchor:"bottom",open:!0,className:"camera-drawer",onClose:(e,t)=>{},children:e(Ce,{scanFailsError:i,onNext:()=>{r?.(),x()},setScanUniqueKey:l,gender:o,setIsVideoUploaded:d})})]}):e("div",{"data-scan-state":"scanning",children:e(xe,{scanID:c,userDetails:n,setIsVideoUploaded:d,setScanFailsError:v,setScanStartTime:w,setScanUniqueKey:l})})},ke=t=>{const{config:n,onRetry:r,onScanStart:c,onCaptureComplete:i,onUploadStart:u,onUploadEnd:d,onMeasurementSocketStart:m,onMeasurementSocketClose:p,onIntermediateScanSuccess:f,onScanError:h,onScanSuccess:g,onCustomScanSuccess:y,onComplete:v,isError:w,isSuccess:x}=t,S={email:"",shopDomain:"",gender:"male",heightInCm:0,scanType:"",deviceFocalLength:0,deviceModelName:"",sourceTag:"",callbackUrl:null,...t.userDetails??{}},D=t.token??"",{gender:C,scanType:N,shopDomain:I,heightInCm:F,email:_,deviceFocalLength:M,deviceModelName:L,callbackUrl:U,sourceTag:j}=S,A=l(()=>H(D),[D]),[z,V]=a(!1),[R,B]=a(!1),[q,K]=a(!1),[O,W]=a({disabled:!1,message:""}),[ee,te]=a(""),[ne,re]=a(!1),[ae,se]=a(!0),[oe,ce]=a(!1),[ie,le]=a(""),[ue,me]=a(T()),{gyroData:pe}=function(e){const[t,n]=a([]),[r,c]=a(!1),i=s(e=>{try{const{alpha:t,beta:r,gamma:a}=e;n(e=>[...e,{alpha:t?.toString()||void 0,beta:r?.toString()||void 0,gamma:a?.toString()||void 0,timestamp:(new Date).toISOString()}])}catch(e){console.log(e)}},[]),l=s(async()=>{const e=DeviceOrientationEvent;if(void 0!==e&&"function"==typeof e.requestPermission)try{"granted"===await e.requestPermission()?c(!0):console.warn("Device orientation permission denied.")}catch(e){console.error("Error requesting device orientation permission:",e)}else c(!0)},[]);return o(()=>(e&&r?window.addEventListener("deviceorientation",i):n([]),()=>{window.removeEventListener("deviceorientation",i)}),[e,r,i]),o(()=>{e&&l()},[e,l]),{gyroData:t}}(oe);J();const fe=s(()=>{le(E()),te(""),V(!1),re(!1)},[]),he=()=>{me(null),le("")},ge=s(async e=>{if(e&&"success"===e?.scanStatus&&"intermediate"===e?.resultType&&200===e?.code)return k({eventName:`${I}/measurement_success/intermediate`,scanID:ie,status:"success",email:_}),B(!0),void f?.(e);g?.(e),B(!0),he();const t=ie;K(!0),k({eventName:`${I}/measurement_success/fit-view`,scanID:t,status:"success",email:_}),ue&&k({eventName:`${I}/scan_completion_time`,scanID:t,status:"success",completionTime:T()-ue,email:_})},[N,I,ie]),ye=e=>{K(!1),te(""),B(!1),A.measurement.handleMeasurementSocket({scanId:ie,onPreopen:()=>{Z({eventName:`${I}/webSocket`,scanID:ie,connection:"pre_open",type:"measurement_recommendation",email:_})},onOpen:()=>{m?.(),Z({eventName:`${I}/webSocket`,scanID:ie,connection:"open",type:"measurement_recommendation",email:_})},onClose:()=>{p?.(),Z({eventName:`${I}/webSocket`,scanID:ie,connection:"close",type:"measurement_recommendation",email:_})},onError:e=>{var t;t=e,h?.({...t,message:P(t)}),he(),K(!1),te(t),B(!1),k({eventName:`${I}/measurement_failed/fit-view`,scanID:ie,status:"failed",email:_,message:P(t)}),ue&&k({eventName:`${I}/scan_completion_time`,scanID:ie,status:"failed",completionTime:T()-ue,email:_}),Z({eventName:`${I}/webSocket`,scanID:ie,connection:"error",type:"measurement_recommendation",email:_})},onSuccess:e=>{Z({eventName:`${I}/webSocket`,scanID:ie,connection:"success",type:"measurement_recommendation",email:_}),ge(e)}})},ve=s(async(e,t)=>{const n=Number((e.size/1048576).toFixed(2)),r=null!=t?t:await G(e),a=Q({gender:C,focal_length:`${M}`,height:`${F}`,customer_store_url:I,clothes_fit:"0",scan_type:N,callback_url:U,source_tag:j});k({eventName:`${I}/body_scan_meta_data`,scanID:ie,email:_,data:JSON.stringify([...a,{fileSizeInMB:n,video_fps:r||0}])}),u?.();try{await A.fileUpload.uploadFileFrontend({file:e,arrayMetaData:a,scanId:ie,email:_}),await A.fileUpload.setDeviceInfo({model:L,detection:"manual",gyro:pe,scanId:ie}),console.log("video successfully uploaded"),re(!1),k({eventName:`${I}/scan_success`,scanID:ie,status:"success",email:_,data:JSON.stringify(a)}),k({eventName:"scan finished",scanID:ie,status:"success",email:_}),me(T()),setTimeout(()=>{re(!0)},3e3)}catch(e){k({eventName:"scan finished",scanID:ie,status:"failed",email:_,message:P(e)}),k({eventName:`${I}/scan_failed`,scanID:ie,status:"failed",email:_,message:P(e),data:JSON.stringify(a)}),te(P(e)),re(!1),h?.({...e,message:P(e)}),he()}finally{ce(!1),d?.()}},[ie,pe,u,d]),we=s(async()=>{if(+F<152.4||+F>213.36)return void h?.({message:"Height must be between 152.4cm (5ft) and 213.36cm (7ft)"});const e=await $();e.disabled?(k({eventName:`${I}/camera_activation`,scanID:ie,status:"failed",email:_}),se(!1)):(se(!1),k({eventName:`${I}/camera_activation`,scanID:ie,status:"success",email:_})),W(e),te(""),re(!1)},[_,ie,le,I]);return o(()=>{w||x||I&&we()},[I,F,w,x]),o(()=>{w||x||ne&&I&&ie&&ye()},[ne,I,ie,w,x]),e("div",{"data-testid":"body-scan-root",children:e(Y,{children:e(X,{config:n,children:e(de,{children:e(b.Provider,{value:{userDetails:S,onRetry:r,onScanError:h,isError:w,isSuccess:x,onScanSuccess:g,gender:C,scanUniqueKey:ie,scanFailsError:ee,setScanUniqueKey:le,setIsVideoUploaded:re,isMeasurementAvailable:q,isVideoUploadedCorrect:R,loading:ae,showDeniedModal:O,uploadLoading:z,setStartGyro:ce,uploadScanFile:ve,setUploadLoading:V,resetScan:fe,setScanFailsError:te,setScanStartTime:me,onScanStart:c,onCaptureComplete:i,onCustomScanSuccess:y,onComplete:v,swan:A},children:e(Ie,{})})})})})})},Te=t=>{const[n,r]=a(!1);return o(()=>{r(!0)},[]),n?e(ke,{...t}):e("div",{"data-testid":"body-scan-root"})};export{Te as B};
3
- //# sourceMappingURL=BodyScan-CCRXkFFL.mjs.map