JezK
Edit File: sc-login-form.entry.js.map
{"file":"sc-login-form.entry.js","mappings":";;;;;;AAAA,MAAM,cAAc,GAAG,icAAic,CAAC;AACzd,0BAAe,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qCCqDI,UAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iCAoCV,UAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8FAgEd,UAAE,2JAKQ,UAAE,yRASR,UAAE;;;6GAYD,UAAE,qhBAWD,UAAE,0FAGuC,UAAE,iGAGrC,UAAE,mWAUR,UAAE;;2OAmBF,UAAE,2SAQR,UAAE;;;;;;;;;;;;;;;;","names":[],"sources":["src/components/controllers/login/sc-login-form.scss?tag=sc-login-form&encapsulation=shadow","src/components/controllers/login/sc-login-form.tsx"],"sourcesContent":[".login-form {\n font-size: 16px;\n margin: var(--sc-spacing-xx-large) auto;\n max-width: 400px;\n position: relative;\n\n &__title {\n margin-bottom: var(--sc-spacing-medium);\n font-size: var(--sc-font-size-xx-large);\n font-weight: var(--sc-font-weight-bold);\n line-height: var(--sc-line-height-dense);\n text-align: var(--sc-login-text-align, center);\n }\n\n &__back {\n text-align: center;\n font-size: var(--sc-font-size-small);\n }\n}\n\nsc-card {\n --sc-card-padding: var(--sc-spacing-xx-large);\n}\n","import { Component, Fragment, h, State, Watch } from '@stencil/core';\nimport { __ } from '@wordpress/i18n';\nimport apiFetch from '../../../functions/fetch';\nimport { ResponseError, VerificationCode } from '../../../types';\n\n@Component({\n tag: 'sc-login-form',\n styleUrl: 'sc-login-form.scss',\n shadow: true,\n})\nexport class ScLogin {\n private passwordInput: HTMLScInputElement;\n private codeInput: HTMLScInputElement;\n\n @State() step: number = 0;\n @State() email: string = '';\n @State() password: string = '';\n @State() verifyCode: string = '';\n @State() loading: boolean;\n @State() error: ResponseError;\n\n /** Focus the password field automatically on password step. */\n @Watch('step')\n handleStepChange() {\n if (this.step === 1) {\n setTimeout(() => {\n this.passwordInput?.triggerFocus?.();\n }, 50);\n }\n if (this.step === 2) {\n setTimeout(() => {\n this.codeInput?.triggerFocus?.();\n }, 50);\n }\n }\n\n /** Clear out error when loading happens. */\n @Watch('loading')\n handleLoadingChange(val) {\n if (val) {\n this.error = null;\n }\n }\n\n @Watch('verifyCode')\n handleVerifyCodeChange(val) {\n if (val?.length >= 6) {\n this.submitCode();\n }\n }\n\n /** Handle request errors. */\n handleError(e) {\n console.error(this.error);\n this.error = e || { message: __('Something went wrong', 'surecart') };\n }\n\n /** Submit for verification codes */\n async createLoginCode() {\n try {\n this.loading = true;\n await apiFetch({\n method: 'POST',\n path: 'surecart/v1/verification_codes',\n data: {\n login: this.email,\n },\n });\n this.step = this.step + 1;\n } catch (e) {\n this.handleError(e);\n } finally {\n this.loading = false;\n }\n }\n\n /** Get all subscriptions */\n async submitCode() {\n try {\n this.loading = true;\n const { verified, redirect_url } = (await apiFetch({\n method: 'POST',\n path: 'surecart/v1/verification_codes/verify',\n data: {\n login: this.email,\n code: this.verifyCode,\n ...(this.getRedirectTo() ? { redirect_to: this.getRedirectTo() } : {}),\n },\n })) as VerificationCode;\n if (!verified) {\n throw { message: __('Verification code is not valid. Please try again.', 'surecart') };\n }\n if (redirect_url) {\n window.location.replace(redirect_url);\n } else {\n window.location.reload();\n }\n } catch (e) {\n this.handleError(e);\n this.loading = false;\n }\n }\n\n async login() {\n try {\n this.loading = true;\n const { redirect_url } = (await apiFetch({\n method: 'POST',\n path: 'surecart/v1/login',\n data: {\n login: this.email,\n password: this.password,\n ...(this.getRedirectTo() ? { redirect_to: this.getRedirectTo() } : {}),\n },\n })) as any;\n if (redirect_url) {\n window.location.replace(redirect_url);\n } else {\n window.location.reload();\n }\n } catch (e) {\n this.handleError(e);\n this.loading = false;\n }\n }\n\n getRedirectTo() {\n const params = new URLSearchParams(window.location.search);\n return params.get('redirect_to');\n }\n\n async checkEmail() {\n try {\n this.loading = true;\n await apiFetch({\n method: 'POST',\n path: 'surecart/v1/check_email',\n data: {\n login: this.email,\n },\n });\n this.step = this.step + 1;\n } catch (e) {\n this.handleError(e);\n } finally {\n this.loading = false;\n }\n }\n\n renderInner() {\n if (this.step === 2) {\n return (\n <Fragment>\n <div class=\"login-form__title\" part=\"title\">\n {__('Check your email for a confirmation code', 'surecart')}\n </div>\n <div>\n <sc-form onScFormSubmit={() => this.submitCode()}>\n <sc-input\n label={__('Confirmation code', 'surecart')}\n type=\"text\"\n ref={el => (this.codeInput = el as HTMLScInputElement)}\n autofocus\n required\n onScInput={e => (this.verifyCode = (e.target as HTMLScInputElement).value)}\n ></sc-input>\n <sc-button type=\"primary\" submit full>\n <sc-icon name=\"lock\" slot=\"prefix\" />\n {__('Login with Code', 'surecart')}\n </sc-button>\n </sc-form>\n </div>\n </Fragment>\n );\n }\n\n if (this.step === 1 && this.email) {\n return (\n <Fragment>\n <div class=\"login-form__title\" part=\"title\">\n <div>{__('Welcome', 'surecart')}</div>\n <sc-button style={{ fontSize: '18px' }} size=\"small\" pill caret onClick={() => (this.step = this.step - 1)}>\n <sc-icon name=\"user\" slot=\"prefix\"></sc-icon>\n {this.email}\n </sc-button>\n </div>\n <sc-flex flexDirection=\"column\" style={{ '--sc-flex-column-gap': 'var(--sc-spacing-large)' }}>\n <div>\n <sc-form onScFormSubmit={() => this.createLoginCode()}>\n <sc-button class=\"login-code\" type=\"primary\" submit full>\n <sc-icon name=\"mail\" slot=\"prefix\" />\n {__('Send a login code', 'surecart')}\n </sc-button>\n </sc-form>\n <sc-divider style={{ '--spacing': '0.5em' }}>{__('or', 'surecart')}</sc-divider>\n <sc-form onScFormSubmit={() => this.login()}>\n <sc-input\n label={__('Enter your password', 'surecart')}\n type=\"password\"\n ref={el => (this.passwordInput = el as HTMLScInputElement)}\n onKeyDown={e => e.key === 'Enter' && this.login()}\n autofocus\n required\n onScInput={e => (this.password = (e.target as HTMLScInputElement).value)}\n ></sc-input>\n <sc-button type=\"primary\" outline submit full>\n <sc-icon name=\"lock\" slot=\"prefix\" />\n {__('Login', 'surecart')}\n </sc-button>\n </sc-form>\n </div>\n </sc-flex>\n </Fragment>\n );\n }\n\n return (\n <Fragment>\n <div class=\"login-form__title\" part=\"title\">\n <slot name=\"title\"></slot>\n </div>\n\n <sc-form onScFormSubmit={() => this.checkEmail()}>\n <sc-input\n type=\"text\"\n value={this.email}\n label={__('Username or Email Address', 'surecart')}\n onScInput={e => (this.email = (e.target as HTMLScInputElement).value)}\n onKeyDown={e => e.key === 'Enter' && this.checkEmail()}\n required\n autofocus\n />\n <sc-button type=\"primary\" submit full>\n <sc-icon name=\"arrow-right\" slot=\"suffix\" />\n {__('Next', 'surecart')}\n </sc-button>\n </sc-form>\n </Fragment>\n );\n }\n\n render() {\n return (\n <div class=\"login-form\">\n <sc-card>\n {!!this.error && (\n <sc-alert open type=\"danger\" closable onScHide={() => (this.error = null)}>\n <span slot=\"title\" innerHTML={this.error?.message}></span>\n {(this.error?.additional_errors || []).map(({ message }) => (\n <div innerHTML={message}></div>\n ))}\n </sc-alert>\n )}\n {this.renderInner()}\n </sc-card>\n {this.loading && <sc-block-ui spinner style={{ 'zIndex': '9', '--sc-block-ui-opacity': '0.5' }}></sc-block-ui>}\n </div>\n );\n }\n}\n"],"version":3}