`\n --cta-button-color: ${(props) => props.ctaButtonColor};\n --cta-button-font-color: ${(props) => props.ctaButtonFontColor};\n --terms-of-service-font-color: ${(props) => props.termsOfServiceFontColor};\n\n input {\n border-color: #cacaca;\n border-radius: 5px;\n height: 50px;\n }\n`;\n\nconst BaseButton = styled(Button)`\n border-color: var(--cta-button-color);\n background-color: var(--cta-button-color);\n color: var(--cta-button-font-color) !important;\n margin-top: 1rem;\n height: 50px;\n border-radius: 5px;\n font-weight: 600;\n font-size: 16px;\n`;\n\nexport const PrimaryButton = styled(BaseButton)`\n &:hover,\n &:active,\n &:focus {\n color: var(--cta-button-color) !important;\n border-color: var(--cta-button-color) !important;\n background-color: transparent !important;\n }\n`;\n\nexport const SecondaryButton = styled(BaseButton)`\n color: #191d48 !important;\n border-color: #191d48 !important;\n background-color: transparent !important;\n position: relative;\n overflow: hidden;\n &:not(.fill):hover,\n &:not(.fill):active,\n &:not(.fill):focus {\n color: var(--cta-button-color) !important;\n border-color: var(--cta-button-color) !important;\n }\n &.fill:before {\n content: '';\n width: 100%;\n height: 100%;\n background-color: rgba(196, 196, 196, 0.6);\n position: absolute;\n transition: all 60s linear;\n top: 0;\n left: 0;\n }\n &.remove-fill:before {\n left: -100%;\n }\n &.disabled,\n [disabled] {\n &:hover,\n &:active,\n &:focus {\n cursor: pointer;\n }\n }\n`;\n\nexport const ThankYouContext = styled.div`\n color: #606270;\n font-size: 14px;\n font-weight: 500;\n margin: 20px auto;\n padding: 8px;\n text-align: center;\n`;\n\nexport const ThankYouMessage = styled.div`\n color: #191d48;\n font-size: 14px;\n font-weight: 500;\n margin: 20px auto;\n padding: 18px;\n text-align: center;\n border: 2px solid #17cc9d;\n border-radius: 9px;\n background-color: #ebf9f7;\n`;\n\nexport const CodeField = styled(Form.Control)`\n -moz-appearance: textfield;\n font-size: 32px;\n margin: 0;\n text-align: center;\n\n &::placeholder {\n text-align: center;\n font-size: 14px;\n }\n\n &::-webkit-outer-spin-button,\n &::-webkit-inner-spin-button {\n -webkit-appearance: none;\n margin: 0;\n }\n`;\n\nexport const AlertContainer = styled.div`\n color: #606270;\n font-size: 12px;\n margin: 18px auto;\n text-align: center;\n`;\n\nexport const OtpContainer = styled.div`\n > div {\n justify-content: space-between;\n }\n\n .inputStyle {\n width: 55px !important;\n height: 55px;\n font-size: 28px;\n font-weight: bold;\n border-radius: 9px;\n border: 2px solid #191d48;\n background-color: #f4f4f4;\n outline-color: var(--cta-button-color);\n }\n\n input[type='number']::-webkit-inner-spin-button,\n input[type='number']::-webkit-outer-spin-button {\n -webkit-appearance: none;\n -moz-appearance: none;\n appearance: none;\n margin: 0;\n }\n\n input[type='number'] {\n -webkit-appearance: textfield;\n -moz-appearance: textfield;\n appearance: textfield;\n }\n\n .error {\n border: 2px solid #ec3d10 !important;\n }\n`;\n","import React, { useState, useEffect } from 'react';\nimport Form from 'react-bootstrap/Form';\nimport PhoneInput from 'react-phone-input-2';\nimport { useForm } from 'react-hook-form';\n\nimport { PublicShop } from '@typings/PublicShop';\n\nimport { PrimaryButton, AlertContainer } from '../components';\nimport TermsOfService from '../components/TermsOfService';\nimport { sendCode } from '../api';\n\ninterface InitialStepProps {\n ctaButtonLabel: string;\n shop: PublicShop;\n setOptInValues?: (values: { email: string; phone: string; country: string }) => void;\n setStep?: (step) => void;\n}\n\nexport function InitialStep({ ctaButtonLabel, shop, setOptInValues, setStep }: InitialStepProps) {\n const [loading, setLoading] = useState(false);\n const [errorAlert, setErrorAlert] = useState(null);\n const urlParams = new URLSearchParams(window.location.search);\n const formProps = useForm({\n defaultValues: {\n email: urlParams.get('email') || '',\n phone: '',\n country: 'us',\n },\n });\n const { register, handleSubmit, setValue, watch, getValues } = formProps;\n\n useEffect(() => {\n // Workaround to show placeholder when default country is selected\n // Set the input value to '' to show the placeholder at the start instead of +1, but keep the default country\n setTimeout(() => {\n const el = document.querySelector('#rsms-opt-in-widget-phone-input') as HTMLInputElement;\n if (el) {\n el.value = '';\n }\n }, 500);\n }, []);\n\n const onSubmit = async (values) => {\n try {\n setLoading(true);\n setOptInValues({ ...values, country: getValues().country });\n await sendCode(shop?.shopifyDomain, values.phone, values.email, 'us');\n setErrorAlert(null);\n setStep('verification_code');\n } catch (error) {\n if (error?.response?.data?.error) {\n setErrorAlert(error.response.data.error);\n } else {\n setErrorAlert('Failed to send verification code.');\n }\n } finally {\n setLoading(false);\n }\n };\n\n function handlePhoneChange(phone, country) {\n setValue('phone', phone);\n setValue('country', country?.countryCode);\n }\n\n return (\n <>\n {errorAlert && {errorAlert}}\n \n \n\n \n {loading ? 'Sending...' : ctaButtonLabel}\n \n\n \n \n >\n );\n}\n","import React from 'react';\nimport styled from '@emotion/styled';\nimport emailDotIcon from '@assets/icons/email-dot-icon.svg';\n\nimport { ThankYouMessage, ThankYouContext } from '../components';\n\ninterface ThankYouStepProps {\n email: string;\n}\n\nexport const ThankYouStep = ({ email }: ThankYouStepProps) => (\n \n Can't find it? Check your spam folder!\n \n \n Verification email sent to {email}\n \n
\n);\n\nconst Icon = styled.img`\n height: 22px;\n width: 26px;\n margin-bottom: 8px;\n margin-right: 8px;\n`;\n","import React, { useState } from 'react';\nimport styled from '@emotion/styled';\n\nimport { PublicShop } from '@typings/PublicShop';\nimport OtpInput from 'react-otp-input';\nimport { sendCode } from '../api';\nimport { PrimaryButton, SecondaryButton, AlertContainer, OtpContainer } from '../components';\n\ninterface VerificationCodeStepProps {\n shop: PublicShop;\n optInValues: {\n phone: string;\n email: string;\n country: string;\n };\n setStep?: (step) => void;\n onVerify?: (smsCode: string) => Promise;\n}\n\nexport const VerificationCodeStep = ({\n shop,\n setStep,\n onVerify,\n optInValues,\n}: VerificationCodeStepProps) => {\n const [loading, setLoading] = useState(false);\n const [lockResend, setLockResend] = useState(false);\n const [beginRemoveLock, setBeginRemoveLock] = useState(false);\n const [code, setCode] = useState('');\n const [codeFailed, setCodeFailed] = useState(false);\n const [alertContent, setAlertContent] = useState('we_sent');\n const RESEND_LOCK_MS = 60000;\n\n const handleSubmit = async () => {\n if (!code || code.length !== 4) {\n return setCodeFailed(true);\n }\n try {\n setLoading(true);\n await onVerify(code);\n setStep('thank_you');\n } catch (error) {\n const errorBody = error.response.data;\n if (errorBody.error === 'too_many') {\n setAlertContent('too_many');\n } else {\n setAlertContent('try_again');\n }\n setCodeFailed(true);\n } finally {\n setLoading(false);\n }\n };\n\n const resendCode = async () => {\n setAlertContent('new_code');\n setLockResend(true);\n await sendCode(shop?.shopifyDomain, optInValues.phone, optInValues.email, optInValues.country);\n setBeginRemoveLock(true);\n setTimeout(() => {\n setBeginRemoveLock(false);\n setLockResend(false);\n }, RESEND_LOCK_MS);\n };\n\n function handleOtpChange(e) {\n setCodeFailed(false);\n setCode(e);\n }\n\n function formatPhoneNumber(phone) {\n // this only works because we only have canadian and american phone numbers\n // need more robust solution when we go international\n const areaCode = phone.slice(1, 4);\n const firstThree = phone.slice(4, 7);\n const lastFour = phone.slice(7, 19);\n return `+1 (${areaCode}) ${firstThree}-${lastFour}`;\n }\n\n const alertContentWeSent = `We sent a verification code to ${formatPhoneNumber(\n optInValues.phone\n )}`;\n\n const alertContentNewCode = `New code sent to ${formatPhoneNumber(optInValues.phone)}`;\n\n const alertContainerTryAgain = `Invalid SMS code. Please try again.`;\n\n const alertContainerTooMany = (\n \n Too many attempts.\n
\n Please resend code and try again.\n
\n );\n\n function renderAlertContent() {\n switch (alertContent) {\n case 'too_many':\n return alertContainerTooMany;\n case 'try_again':\n return alertContainerTryAgain;\n case 'new_code':\n return alertContentNewCode;\n default:\n return alertContentWeSent;\n }\n }\n\n function submitButtonText() {\n if (loading) {\n return 'Verifying...';\n }\n if (alertContent === 'try_again' || alertContent === 'too_many') {\n return 'Try Again';\n }\n return 'Verify';\n }\n\n return (\n <>\n {renderAlertContent()}\n \n \n \n \n
\n \n \n \n Resend Code\n \n
\n \n \n {submitButtonText()}\n \n
\n \n >\n );\n};\n\nconst ButtonContainer = styled.div`\n display: flex;\n gap: 16px;\n .btn-wrap {\n flex: 0 0 calc(50% - 8px);\n }\n`;\n\nconst SubmitButton = styled(PrimaryButton)`\n &[disabled] {\n background-color: var(--cta-button-color) !important;\n color: var(--cta-button-font-color) !important;\n opacity: 0.45 !important;\n }\n`;\n","import { init, setTag } from '@sentry/react';\nimport { Integrations } from '@sentry/tracing';\nimport { PublicShop } from '@typings/PublicShop';\n\nfunction initialize(dsn: string, environment?: string) {\n init({\n dsn,\n environment,\n integrations: [new Integrations.BrowserTracing()],\n });\n}\n\nfunction setShop(shop: PublicShop) {\n setTag('shop_id', shop.id);\n}\n\nexport const sentrySetup = {\n initialize,\n setShop,\n};\n"],"names":["bgColorsByStatus","Offline","Limited","Online","Optimal","Update","waveColorsByStatus","waveHeightsByStatus","waveFreqStatus","size","status","bgColor","colors","heights","freq","WavesContainer","color","className","xmlns","viewBox","preserveAspectRatio","shapeRendering","id","d","map","i","key","xlinkHref","x","y","fill","props","OptInWidget","shop","useState","step","setStep","phone","email","country","optInValues","setOptInValues","urlParams","URLSearchParams","window","location","search","getUrlParam","paramName","defaultParam","prefix","urlParam","get","smsCode","verifySmsCode","useEffect","sentrySetup","ctaButtonColor","ctaButtonFontColor","ctaButtonLabel","termsOfServiceFontColor","steps","initial","InitialStep","verification_code","VerificationCodeStep","onVerify","thank_you","ThankYouStep","Wrapper","shopId","params","axios","phone_number","sms_code","sendCode","shopifyDomain","shop_domain","TermsOfServiceContainer","shopName","href","target","rel","BaseButton","Button","PrimaryButton","SecondaryButton","ThankYouContext","ThankYouMessage","CodeField","Form","AlertContainer","OtpContainer","loading","setLoading","errorAlert","setErrorAlert","formProps","useForm","defaultValues","register","handleSubmit","setValue","watch","getValues","setTimeout","el","document","querySelector","value","onSubmit","values","response","data","error","type","placeholder","required","containerStyle","marginTop","inputStyle","width","height","onlyCountries","inputProps","name","onChange","countryCode","disableDropdown","block","customName","Icon","src","emailDotIcon","lockResend","setLockResend","beginRemoveLock","setBeginRemoveLock","code","setCode","codeFailed","setCodeFailed","alertContent","setAlertContent","length","resendCode","formatPhoneNumber","areaCode","slice","firstThree","lastFour","alertContentWeSent","alertContentNewCode","alertContainerTooMany","renderAlertContent","isInputNum","e","numInputs","hasErrored","errorStyle","shouldAutoFocus","ButtonContainer","onClick","disabled","SubmitButton","initialize","dsn","environment","init","integrations","Integrations","setShop","setTag"],"sourceRoot":""}