UNPKG

alinea

Version:

[![npm](https://img.shields.io/npm/v/alinea.svg)](https://npmjs.org/package/alinea) [![install size](https://packagephobia.com/badge?p=alinea)](https://packagephobia.com/result?p=alinea)

183 lines (179 loc) 7.02 kB
import "../../chunks/chunk-U5RRZUYZ.js"; // src/auth/passwordless/PasswordLessLogin.tsx import { Connection } from "alinea/core"; import { Client } from "alinea/core/Client"; import { decode } from "alinea/core/util/JWT"; import { joinPaths } from "alinea/core/util/Urls"; import { useDashboard } from "alinea/dashboard/hook/UseDashboard"; import { Head } from "alinea/dashboard/util/Head"; import { Button, Loader, Typo, fromModule, px } from "alinea/ui"; import { HStack, VStack } from "alinea/ui/Stack"; import { LogoShape } from "alinea/ui/branding/LogoShape"; import { IcRoundArrowBack } from "alinea/ui/icons/IcRoundArrowBack"; import { IcRoundArrowForward } from "alinea/ui/icons/IcRoundArrowForward"; import { RiFlashlightFill } from "alinea/ui/icons/RiFlashlightFill"; import { useLayoutEffect, useState } from "react"; // src/auth/passwordless/PasswordLessLogin.module.scss var PasswordLessLogin_module_default = { "root-email": "alinea-PasswordLessLogin-email", "rootEmail": "alinea-PasswordLessLogin-email", "root-email-input": "alinea-PasswordLessLogin-email-input", "rootEmailInput": "alinea-PasswordLessLogin-email-input" }; // src/auth/passwordless/PasswordLessLogin.tsx import { Fragment, jsx, jsxs } from "react/jsx-runtime"; var styles = fromModule(PasswordLessLogin_module_default); function LoginBox({ children }) { return /* @__PURE__ */ jsx("div", { style: { width: px(320) }, children: /* @__PURE__ */ jsx(VStack, { gap: 16, children }) }); } function LoginHeader({ children }) { return /* @__PURE__ */ jsxs(HStack, { center: true, gap: 16, children: [ /* @__PURE__ */ jsx(LogoShape, { children: /* @__PURE__ */ jsx(RiFlashlightFill, {}) }), /* @__PURE__ */ jsx(Typo.H1, { flat: true, children }) ] }); } function LoginForm({ onSubmit, email, setEmail }) { function handleSubmit(e) { e.preventDefault(); onSubmit(); } return /* @__PURE__ */ jsx("form", { onSubmit: handleSubmit, children: /* @__PURE__ */ jsxs(LoginBox, { children: [ /* @__PURE__ */ jsx(LoginHeader, { children: "Log in" }), /* @__PURE__ */ jsxs(VStack, { gap: 10, children: [ /* @__PURE__ */ jsx(Typo.P, { flat: true, children: "We'll send you a login link by mail." }), /* @__PURE__ */ jsxs(HStack, { center: true, gap: 16, children: [ /* @__PURE__ */ jsx("div", { className: styles.root.email(), children: /* @__PURE__ */ jsx( "input", { className: styles.root.email.input(), type: "email", placeholder: "Email address", required: true, value: email, onChange: (e) => setEmail(e.target.value) } ) }), /* @__PURE__ */ jsx(Button, { size: "large", type: "submit", children: /* @__PURE__ */ jsxs(HStack, { center: true, gap: 8, children: [ /* @__PURE__ */ jsx("span", { children: "Sign in" }), /* @__PURE__ */ jsx(IcRoundArrowForward, {}) ] }) }) ] }) ] }) ] }) }); } function LoginScreen(props) { switch (props.state) { case 0 /* Loading */: return /* @__PURE__ */ jsx(Loader, {}); case 1 /* Input */: return /* @__PURE__ */ jsx(LoginForm, { ...props }); case 2 /* Sent */: return /* @__PURE__ */ jsxs(LoginBox, { children: [ /* @__PURE__ */ jsx(LoginHeader, { children: "Check your email" }), /* @__PURE__ */ jsxs(Typo.P, { children: [ "We've sent you link at ", props.email ] }) ] }); case 3 /* NotFound */: return /* @__PURE__ */ jsxs(LoginBox, { children: [ /* @__PURE__ */ jsx(LoginHeader, { children: "Oops" }), /* @__PURE__ */ jsxs(Typo.P, { flat: true, children: [ 'The email adress "', props.email, '" is not known' ] }), /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Button, { onClick: () => props.setState(1 /* Input */), children: /* @__PURE__ */ jsxs(HStack, { center: true, gap: 8, children: [ /* @__PURE__ */ jsx(IcRoundArrowBack, {}), /* @__PURE__ */ jsx("span", { children: "Try again" }) ] }) }) }) ] }); case 4 /* Error */: return /* @__PURE__ */ jsxs(LoginBox, { children: [ /* @__PURE__ */ jsx(LoginHeader, { children: "Oops" }), /* @__PURE__ */ jsx(Typo.P, { children: "Something went wrong, please try again later" }) ] }); } } function useResolveToken(setSession) { const { client } = useDashboard(); useLayoutEffect(() => { const params = new URLSearchParams(window.location.search); const isTokenFromUrl = params.has("token"); const token = params.get("token") || localStorage.getItem("@alinea/auth.passwordless"); if (token) { let logout2 = function() { localStorage.removeItem("@alinea/auth.passwordless"); setSession(void 0); }, applyAuth2 = function(init) { return { ...init, headers: { ...init?.headers, authorization: `Bearer ${token}` } }; }; var logout = logout2, applyAuth = applyAuth2; const user = token && decode(token); if (!(client instanceof Client)) throw new Error(`Cannot authenticate with non http client`); setSession({ user, cnx: client.authenticate(applyAuth2, logout2), end: async () => logout2() }); if (isTokenFromUrl) { localStorage.setItem("@alinea/auth.passwordless", token); history.pushState(null, "", window.location.pathname); } } }, []); } function PasswordLessLogin({ setSession }) { const { client } = useDashboard(); const [state, setState] = useState(1 /* Input */); const [email, setEmail] = useState(""); useResolveToken(setSession); function handleSubmit() { setState(0 /* Loading */); if (!(client instanceof Client)) throw new Error(`Cannot authenticate with non http client`); fetch( joinPaths( client.options.url, Connection.routes.base, `/auth.passwordless` ), { headers: { "content-type": "application/json" }, method: "POST", body: JSON.stringify({ email }) } ).then((res) => { switch (res.status) { case 200: return setState(2 /* Sent */); case 404: return setState(3 /* NotFound */); default: return setState(4 /* Error */); } }).catch(() => { setState(4 /* Error */); }); } return /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx(Head, { children: /* @__PURE__ */ jsx("title", { children: "Log in" }) }), /* @__PURE__ */ jsx("div", { style: { display: "flex", height: "100%", width: "100%" }, children: /* @__PURE__ */ jsx("div", { style: { margin: "auto", padding: px(20) }, children: /* @__PURE__ */ jsx( LoginScreen, { state, setState, onSubmit: handleSubmit, email, setEmail } ) }) }) ] }); } export { PasswordLessLogin };