alinea
Version:
[](https://npmjs.org/package/alinea) [](https://packagephobia.com/result?p=alinea)
183 lines (179 loc) • 7.02 kB
JavaScript
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
};