@frequencyads/auth 0.1.0
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.
- package/dist/chunk-JIENWB3K.mjs +89 -0
- package/dist/chunk-NS2JRZGO.mjs +38 -0
- package/dist/chunk-OKP757OV.mjs +131 -0
- package/dist/chunk-OUUVIDG6.mjs +63 -0
- package/dist/chunk-P4OKC4U7.mjs +41 -0
- package/dist/chunk-VBLFQXCD.mjs +406 -0
- package/dist/chunk-VQCPN62H.mjs +134 -0
- package/dist/chunk-XJFMS3SM.mjs +21 -0
- package/dist/components/auth-provider.d.mts +24 -0
- package/dist/components/auth-provider.d.ts +24 -0
- package/dist/components/auth-provider.js +107 -0
- package/dist/components/auth-provider.mjs +11 -0
- package/dist/components/login.d.mts +24 -0
- package/dist/components/login.d.ts +24 -0
- package/dist/components/login.js +430 -0
- package/dist/components/login.mjs +9 -0
- package/dist/components/reset-password.d.mts +11 -0
- package/dist/components/reset-password.d.ts +11 -0
- package/dist/components/reset-password.js +283 -0
- package/dist/components/reset-password.mjs +10 -0
- package/dist/components/sign-out-button.d.mts +11 -0
- package/dist/components/sign-out-button.d.ts +11 -0
- package/dist/components/sign-out-button.js +90 -0
- package/dist/components/sign-out-button.mjs +11 -0
- package/dist/components/user-menu.d.mts +5 -0
- package/dist/components/user-menu.d.ts +5 -0
- package/dist/components/user-menu.js +107 -0
- package/dist/components/user-menu.mjs +11 -0
- package/dist/components/verify-code.d.mts +20 -0
- package/dist/components/verify-code.d.ts +20 -0
- package/dist/components/verify-code.js +155 -0
- package/dist/components/verify-code.mjs +9 -0
- package/dist/index.d.mts +44 -0
- package/dist/index.d.ts +44 -0
- package/dist/index.js +1006 -0
- package/dist/index.mjs +159 -0
- package/dist/middleware.d.mts +29 -0
- package/dist/middleware.d.ts +29 -0
- package/dist/middleware.js +114 -0
- package/dist/middleware.mjs +83 -0
- package/dist/proxy.d.mts +9 -0
- package/dist/proxy.d.ts +9 -0
- package/dist/proxy.js +71 -0
- package/dist/proxy.mjs +41 -0
- package/dist/request.d.mts +14 -0
- package/dist/request.d.ts +14 -0
- package/dist/request.js +46 -0
- package/dist/request.mjs +8 -0
- package/package.json +101 -0
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
"use strict";
|
|
3
|
+
"use client";
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
21
|
+
|
|
22
|
+
// src/components/auth-provider.tsx
|
|
23
|
+
var auth_provider_exports = {};
|
|
24
|
+
__export(auth_provider_exports, {
|
|
25
|
+
AuthProvider: () => AuthProvider,
|
|
26
|
+
useAuth: () => useAuth
|
|
27
|
+
});
|
|
28
|
+
module.exports = __toCommonJS(auth_provider_exports);
|
|
29
|
+
var import_react = require("react");
|
|
30
|
+
var import_client = require("@frequencyads/db/client");
|
|
31
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
32
|
+
var Context = (0, import_react.createContext)(void 0);
|
|
33
|
+
function AuthProvider({ children, loginUrl }) {
|
|
34
|
+
var _a, _b, _c, _d;
|
|
35
|
+
const [supabase] = (0, import_react.useState)(() => (0, import_client.createBrowserClient)());
|
|
36
|
+
const [user, setUser] = (0, import_react.useState)(null);
|
|
37
|
+
const [loading, setLoading] = (0, import_react.useState)(true);
|
|
38
|
+
const userIdRef = (0, import_react.useRef)(null);
|
|
39
|
+
const setUserStable = (0, import_react.useCallback)((newUser) => {
|
|
40
|
+
var _a2;
|
|
41
|
+
const newId = (_a2 = newUser == null ? void 0 : newUser.id) != null ? _a2 : null;
|
|
42
|
+
if (newId !== userIdRef.current) {
|
|
43
|
+
userIdRef.current = newId;
|
|
44
|
+
setUser(newUser);
|
|
45
|
+
}
|
|
46
|
+
}, []);
|
|
47
|
+
(0, import_react.useEffect)(() => {
|
|
48
|
+
if (!supabase) {
|
|
49
|
+
setLoading(false);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
const {
|
|
53
|
+
data: { subscription }
|
|
54
|
+
} = supabase.auth.onAuthStateChange((_event, session) => {
|
|
55
|
+
var _a2;
|
|
56
|
+
setUserStable((_a2 = session == null ? void 0 : session.user) != null ? _a2 : null);
|
|
57
|
+
setLoading(false);
|
|
58
|
+
});
|
|
59
|
+
async function checkSession() {
|
|
60
|
+
const {
|
|
61
|
+
data: { session }
|
|
62
|
+
} = await supabase.auth.getSession();
|
|
63
|
+
if (!session) {
|
|
64
|
+
await supabase.auth.signOut({ scope: "local" });
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
const POLL_MS = 3e4;
|
|
68
|
+
const interval = setInterval(checkSession, POLL_MS);
|
|
69
|
+
const handleVisibilityChange = () => {
|
|
70
|
+
if (document.visibilityState === "visible") {
|
|
71
|
+
checkSession();
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
document.addEventListener("visibilitychange", handleVisibilityChange);
|
|
75
|
+
return () => {
|
|
76
|
+
subscription.unsubscribe();
|
|
77
|
+
clearInterval(interval);
|
|
78
|
+
document.removeEventListener("visibilitychange", handleVisibilityChange);
|
|
79
|
+
};
|
|
80
|
+
}, [supabase]);
|
|
81
|
+
(0, import_react.useEffect)(() => {
|
|
82
|
+
if (loading || user) return;
|
|
83
|
+
const url = loginUrl != null ? loginUrl : `${process.env.NEXT_PUBLIC_ACCOUNTS_URL}/login`;
|
|
84
|
+
if (url) {
|
|
85
|
+
window.location.href = `${url}?next=${encodeURIComponent(window.location.href)}`;
|
|
86
|
+
}
|
|
87
|
+
}, [loading, user, loginUrl]);
|
|
88
|
+
const profile = {
|
|
89
|
+
name: (_b = (_a = user == null ? void 0 : user.user_metadata) == null ? void 0 : _a.full_name) != null ? _b : "\u2014",
|
|
90
|
+
email: (_c = user == null ? void 0 : user.email) != null ? _c : "",
|
|
91
|
+
avatarUrl: (_d = user == null ? void 0 : user.user_metadata) == null ? void 0 : _d.avatar_url
|
|
92
|
+
};
|
|
93
|
+
if (loading || !user) return null;
|
|
94
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Context.Provider, { value: { supabase, user, profile, loading }, children });
|
|
95
|
+
}
|
|
96
|
+
function useAuth() {
|
|
97
|
+
const context = (0, import_react.useContext)(Context);
|
|
98
|
+
if (context === void 0) {
|
|
99
|
+
throw new Error("useAuth must be used within an AuthProvider");
|
|
100
|
+
}
|
|
101
|
+
return context;
|
|
102
|
+
}
|
|
103
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
104
|
+
0 && (module.exports = {
|
|
105
|
+
AuthProvider,
|
|
106
|
+
useAuth
|
|
107
|
+
});
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
interface LoginPageProps {
|
|
5
|
+
title?: string;
|
|
6
|
+
description?: ReactNode;
|
|
7
|
+
/** Optional content shown in a HoverCard popover next to the title. */
|
|
8
|
+
info?: ReactNode;
|
|
9
|
+
/** Override the OAuth redirectTo URL. Defaults to `window.location.origin + '/auth/callback'`. */
|
|
10
|
+
redirectTo?: string;
|
|
11
|
+
/** Content rendered above the form card (e.g. a logo). */
|
|
12
|
+
header?: ReactNode;
|
|
13
|
+
/** Content rendered below the sign-in button (e.g. privacy policy link). */
|
|
14
|
+
footer?: ReactNode;
|
|
15
|
+
/** Called after successful signup to navigate to verification screen. */
|
|
16
|
+
onVerifyNeeded?: (email: string) => void;
|
|
17
|
+
/** Called when user clicks "Forgot password?" */
|
|
18
|
+
onResetRequest?: () => void;
|
|
19
|
+
/** Called after successful email/password sign-in or sign-up with immediate session. */
|
|
20
|
+
onSuccess?: () => void;
|
|
21
|
+
}
|
|
22
|
+
declare function LoginPage({ title, description, info, redirectTo, header, footer, onVerifyNeeded, onResetRequest, onSuccess, }: LoginPageProps): react_jsx_runtime.JSX.Element;
|
|
23
|
+
|
|
24
|
+
export { LoginPage };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
interface LoginPageProps {
|
|
5
|
+
title?: string;
|
|
6
|
+
description?: ReactNode;
|
|
7
|
+
/** Optional content shown in a HoverCard popover next to the title. */
|
|
8
|
+
info?: ReactNode;
|
|
9
|
+
/** Override the OAuth redirectTo URL. Defaults to `window.location.origin + '/auth/callback'`. */
|
|
10
|
+
redirectTo?: string;
|
|
11
|
+
/** Content rendered above the form card (e.g. a logo). */
|
|
12
|
+
header?: ReactNode;
|
|
13
|
+
/** Content rendered below the sign-in button (e.g. privacy policy link). */
|
|
14
|
+
footer?: ReactNode;
|
|
15
|
+
/** Called after successful signup to navigate to verification screen. */
|
|
16
|
+
onVerifyNeeded?: (email: string) => void;
|
|
17
|
+
/** Called when user clicks "Forgot password?" */
|
|
18
|
+
onResetRequest?: () => void;
|
|
19
|
+
/** Called after successful email/password sign-in or sign-up with immediate session. */
|
|
20
|
+
onSuccess?: () => void;
|
|
21
|
+
}
|
|
22
|
+
declare function LoginPage({ title, description, info, redirectTo, header, footer, onVerifyNeeded, onResetRequest, onSuccess, }: LoginPageProps): react_jsx_runtime.JSX.Element;
|
|
23
|
+
|
|
24
|
+
export { LoginPage };
|
|
@@ -0,0 +1,430 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
"use strict";
|
|
3
|
+
"use client";
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
21
|
+
|
|
22
|
+
// src/components/login/index.tsx
|
|
23
|
+
var login_exports = {};
|
|
24
|
+
__export(login_exports, {
|
|
25
|
+
LoginPage: () => LoginPage
|
|
26
|
+
});
|
|
27
|
+
module.exports = __toCommonJS(login_exports);
|
|
28
|
+
var import_react3 = require("react");
|
|
29
|
+
var import_core3 = require("@mantine/core");
|
|
30
|
+
var import_icons_react = require("@tabler/icons-react");
|
|
31
|
+
|
|
32
|
+
// src/components/login/email-password-form.tsx
|
|
33
|
+
var import_react = require("react");
|
|
34
|
+
var import_core = require("@mantine/core");
|
|
35
|
+
var import_client = require("@frequencyads/db/client");
|
|
36
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
37
|
+
function EmailPasswordForm({
|
|
38
|
+
isPending,
|
|
39
|
+
startTransition,
|
|
40
|
+
onVerifyNeeded,
|
|
41
|
+
onResetRequest,
|
|
42
|
+
onSuccess
|
|
43
|
+
}) {
|
|
44
|
+
const supabase = (0, import_client.createBrowserClient)();
|
|
45
|
+
const [step, setStep] = (0, import_react.useState)("email");
|
|
46
|
+
const [mode, setMode] = (0, import_react.useState)("signin");
|
|
47
|
+
const [email, setEmail] = (0, import_react.useState)("");
|
|
48
|
+
const [password, setPassword] = (0, import_react.useState)("");
|
|
49
|
+
const [confirmPassword, setConfirmPassword] = (0, import_react.useState)("");
|
|
50
|
+
const [firstName, setFirstName] = (0, import_react.useState)("");
|
|
51
|
+
const [lastName, setLastName] = (0, import_react.useState)("");
|
|
52
|
+
const [error, setError] = (0, import_react.useState)(null);
|
|
53
|
+
const goBack = () => {
|
|
54
|
+
setStep("email");
|
|
55
|
+
setPassword("");
|
|
56
|
+
setConfirmPassword("");
|
|
57
|
+
setError(null);
|
|
58
|
+
};
|
|
59
|
+
const toggleMode = () => {
|
|
60
|
+
setMode((m) => m === "signin" ? "signup" : "signin");
|
|
61
|
+
setStep("email");
|
|
62
|
+
setPassword("");
|
|
63
|
+
setConfirmPassword("");
|
|
64
|
+
setFirstName("");
|
|
65
|
+
setLastName("");
|
|
66
|
+
setError(null);
|
|
67
|
+
};
|
|
68
|
+
const validateEmail = () => {
|
|
69
|
+
const trimmed = email.trim();
|
|
70
|
+
if (!trimmed) {
|
|
71
|
+
setError("Email is required.");
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(trimmed)) {
|
|
75
|
+
setError("Please enter a valid email address.");
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
return true;
|
|
79
|
+
};
|
|
80
|
+
const handleContinue = (e) => {
|
|
81
|
+
e.preventDefault();
|
|
82
|
+
setError(null);
|
|
83
|
+
if (validateEmail()) {
|
|
84
|
+
setStep("credentials");
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
const handleSignIn = (e) => {
|
|
88
|
+
e.preventDefault();
|
|
89
|
+
setError(null);
|
|
90
|
+
if (!validateEmail()) return;
|
|
91
|
+
if (!password.trim()) {
|
|
92
|
+
setError("Password is required.");
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
startTransition(async () => {
|
|
96
|
+
const { error: signInError } = await supabase.auth.signInWithPassword({
|
|
97
|
+
email: email.trim(),
|
|
98
|
+
password: password.trim()
|
|
99
|
+
});
|
|
100
|
+
if (signInError) {
|
|
101
|
+
if (signInError.message === "Email not confirmed") {
|
|
102
|
+
onVerifyNeeded == null ? void 0 : onVerifyNeeded(email);
|
|
103
|
+
} else {
|
|
104
|
+
setError(signInError.message);
|
|
105
|
+
}
|
|
106
|
+
} else {
|
|
107
|
+
onSuccess == null ? void 0 : onSuccess();
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
};
|
|
111
|
+
const handleSignUp = (e) => {
|
|
112
|
+
e.preventDefault();
|
|
113
|
+
setError(null);
|
|
114
|
+
if (!firstName.trim()) {
|
|
115
|
+
setError("First name is required.");
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
if (!lastName.trim()) {
|
|
119
|
+
setError("Last name is required.");
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
if (!password.trim()) {
|
|
123
|
+
setError("Password is required.");
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
if (password.trim().length < 8) {
|
|
127
|
+
setError("Password must be at least 8 characters.");
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
const trimmedPassword = password.trim();
|
|
131
|
+
if (trimmedPassword !== confirmPassword.trim()) {
|
|
132
|
+
setError("Passwords do not match.");
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
startTransition(async () => {
|
|
136
|
+
const fullName = `${firstName.trim()} ${lastName.trim()}`;
|
|
137
|
+
const { data: signUpData, error: signUpError } = await supabase.auth.signUp({
|
|
138
|
+
email: email.trim(),
|
|
139
|
+
password: trimmedPassword,
|
|
140
|
+
options: {
|
|
141
|
+
data: {
|
|
142
|
+
name: fullName,
|
|
143
|
+
full_name: fullName,
|
|
144
|
+
first_name: firstName.trim(),
|
|
145
|
+
last_name: lastName.trim()
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
if (signUpError) {
|
|
150
|
+
setError(signUpError.message);
|
|
151
|
+
} else if (signUpData.session) {
|
|
152
|
+
onSuccess == null ? void 0 : onSuccess();
|
|
153
|
+
} else {
|
|
154
|
+
onVerifyNeeded == null ? void 0 : onVerifyNeeded(email);
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
};
|
|
158
|
+
if (mode === "signin") {
|
|
159
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("form", { onSubmit: handleSignIn, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_core.Stack, { children: [
|
|
160
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
161
|
+
import_core.TextInput,
|
|
162
|
+
{
|
|
163
|
+
label: "Email",
|
|
164
|
+
placeholder: "you@frequency.media",
|
|
165
|
+
type: "email",
|
|
166
|
+
value: email,
|
|
167
|
+
onChange: (e) => setEmail(e.currentTarget.value),
|
|
168
|
+
disabled: isPending,
|
|
169
|
+
required: true
|
|
170
|
+
}
|
|
171
|
+
),
|
|
172
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
173
|
+
import_core.PasswordInput,
|
|
174
|
+
{
|
|
175
|
+
label: "Password",
|
|
176
|
+
placeholder: "Your password",
|
|
177
|
+
value: password,
|
|
178
|
+
onChange: (e) => setPassword(e.currentTarget.value),
|
|
179
|
+
disabled: isPending,
|
|
180
|
+
required: true
|
|
181
|
+
}
|
|
182
|
+
),
|
|
183
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_core.Text, { size: "sm", c: "red", children: error }),
|
|
184
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_core.Button, { fullWidth: true, size: "md", type: "submit", loading: isPending, children: "Sign in" }),
|
|
185
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_core.Group, { justify: "space-between", children: [
|
|
186
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
187
|
+
import_core.Anchor,
|
|
188
|
+
{
|
|
189
|
+
component: "button",
|
|
190
|
+
type: "button",
|
|
191
|
+
size: "sm",
|
|
192
|
+
onClick: toggleMode,
|
|
193
|
+
disabled: isPending,
|
|
194
|
+
children: "Don't have an account?"
|
|
195
|
+
}
|
|
196
|
+
),
|
|
197
|
+
onResetRequest && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
198
|
+
import_core.Anchor,
|
|
199
|
+
{
|
|
200
|
+
component: "button",
|
|
201
|
+
type: "button",
|
|
202
|
+
size: "sm",
|
|
203
|
+
onClick: onResetRequest,
|
|
204
|
+
disabled: isPending,
|
|
205
|
+
children: "Forgot password?"
|
|
206
|
+
}
|
|
207
|
+
)
|
|
208
|
+
] })
|
|
209
|
+
] }) });
|
|
210
|
+
}
|
|
211
|
+
if (step === "email") {
|
|
212
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("form", { onSubmit: handleContinue, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_core.Stack, { children: [
|
|
213
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
214
|
+
import_core.TextInput,
|
|
215
|
+
{
|
|
216
|
+
label: "Email",
|
|
217
|
+
placeholder: "you@frequency.media",
|
|
218
|
+
type: "email",
|
|
219
|
+
value: email,
|
|
220
|
+
onChange: (e) => setEmail(e.currentTarget.value),
|
|
221
|
+
required: true
|
|
222
|
+
}
|
|
223
|
+
),
|
|
224
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_core.Text, { size: "sm", c: "red", children: error }),
|
|
225
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_core.Button, { fullWidth: true, size: "md", type: "submit", children: "Continue" }),
|
|
226
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_core.Anchor, { component: "button", type: "button", size: "sm", onClick: toggleMode, children: "Already have an account?" })
|
|
227
|
+
] }) });
|
|
228
|
+
}
|
|
229
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("form", { onSubmit: handleSignUp, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_core.Stack, { children: [
|
|
230
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_core.Group, { gap: "xs", align: "baseline", children: [
|
|
231
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_core.Text, { size: "sm", c: "dimmed", children: email }),
|
|
232
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_core.Anchor, { component: "button", type: "button", size: "sm", onClick: goBack, disabled: isPending, children: "Change" })
|
|
233
|
+
] }),
|
|
234
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_core.Group, { grow: true, children: [
|
|
235
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
236
|
+
import_core.TextInput,
|
|
237
|
+
{
|
|
238
|
+
label: "First name",
|
|
239
|
+
placeholder: "Jane",
|
|
240
|
+
value: firstName,
|
|
241
|
+
onChange: (e) => setFirstName(e.currentTarget.value),
|
|
242
|
+
disabled: isPending,
|
|
243
|
+
required: true
|
|
244
|
+
}
|
|
245
|
+
),
|
|
246
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
247
|
+
import_core.TextInput,
|
|
248
|
+
{
|
|
249
|
+
label: "Last name",
|
|
250
|
+
placeholder: "Doe",
|
|
251
|
+
value: lastName,
|
|
252
|
+
onChange: (e) => setLastName(e.currentTarget.value),
|
|
253
|
+
disabled: isPending,
|
|
254
|
+
required: true
|
|
255
|
+
}
|
|
256
|
+
)
|
|
257
|
+
] }),
|
|
258
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
259
|
+
import_core.PasswordInput,
|
|
260
|
+
{
|
|
261
|
+
label: "Password",
|
|
262
|
+
placeholder: "At least 8 characters",
|
|
263
|
+
value: password,
|
|
264
|
+
onChange: (e) => setPassword(e.currentTarget.value),
|
|
265
|
+
disabled: isPending,
|
|
266
|
+
required: true
|
|
267
|
+
}
|
|
268
|
+
),
|
|
269
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
270
|
+
import_core.PasswordInput,
|
|
271
|
+
{
|
|
272
|
+
label: "Confirm password",
|
|
273
|
+
placeholder: "Repeat your password",
|
|
274
|
+
value: confirmPassword,
|
|
275
|
+
onChange: (e) => setConfirmPassword(e.currentTarget.value),
|
|
276
|
+
disabled: isPending,
|
|
277
|
+
required: true
|
|
278
|
+
}
|
|
279
|
+
),
|
|
280
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_core.Text, { size: "sm", c: "red", children: error }),
|
|
281
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_core.Button, { fullWidth: true, size: "md", type: "submit", loading: isPending, children: "Create account" }),
|
|
282
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
283
|
+
import_core.Anchor,
|
|
284
|
+
{
|
|
285
|
+
component: "button",
|
|
286
|
+
type: "button",
|
|
287
|
+
size: "sm",
|
|
288
|
+
onClick: toggleMode,
|
|
289
|
+
disabled: isPending,
|
|
290
|
+
children: "Already have an account?"
|
|
291
|
+
}
|
|
292
|
+
)
|
|
293
|
+
] }) });
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// src/components/login/google-sign-in.tsx
|
|
297
|
+
var import_react2 = require("react");
|
|
298
|
+
var import_core2 = require("@mantine/core");
|
|
299
|
+
var import_client2 = require("@frequencyads/db/client");
|
|
300
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
301
|
+
function GoogleIcon() {
|
|
302
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { width: "18", height: "18", viewBox: "0 0 18 18", xmlns: "http://www.w3.org/2000/svg", children: [
|
|
303
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
304
|
+
"path",
|
|
305
|
+
{
|
|
306
|
+
d: "M17.64 9.2c0-.637-.057-1.251-.164-1.84H9v3.481h4.844a4.14 4.14 0 0 1-1.796 2.716v2.259h2.908c1.702-1.567 2.684-3.875 2.684-6.615z",
|
|
307
|
+
fill: "#4285F4"
|
|
308
|
+
}
|
|
309
|
+
),
|
|
310
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
311
|
+
"path",
|
|
312
|
+
{
|
|
313
|
+
d: "M9 18c2.43 0 4.467-.806 5.956-2.18l-2.908-2.259c-.806.54-1.837.86-3.048.86-2.344 0-4.328-1.584-5.036-3.711H.957v2.332A8.997 8.997 0 0 0 9 18z",
|
|
314
|
+
fill: "#34A853"
|
|
315
|
+
}
|
|
316
|
+
),
|
|
317
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
318
|
+
"path",
|
|
319
|
+
{
|
|
320
|
+
d: "M3.964 10.71A5.41 5.41 0 0 1 3.682 9c0-.593.102-1.17.282-1.71V4.958H.957A8.997 8.997 0 0 0 0 9c0 1.452.348 2.827.957 4.042l3.007-2.332z",
|
|
321
|
+
fill: "#FBBC05"
|
|
322
|
+
}
|
|
323
|
+
),
|
|
324
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
325
|
+
"path",
|
|
326
|
+
{
|
|
327
|
+
d: "M9 3.58c1.321 0 2.508.454 3.44 1.345l2.582-2.58C13.463.891 11.426 0 9 0A8.997 8.997 0 0 0 .957 4.958L3.964 7.29C4.672 5.163 6.656 3.58 9 3.58z",
|
|
328
|
+
fill: "#EA4335"
|
|
329
|
+
}
|
|
330
|
+
)
|
|
331
|
+
] });
|
|
332
|
+
}
|
|
333
|
+
function GoogleSignIn({ redirectTo, isPending }) {
|
|
334
|
+
const supabase = (0, import_client2.createBrowserClient)();
|
|
335
|
+
const [loading, setLoading] = (0, import_react2.useState)(false);
|
|
336
|
+
const handleGoogleLogin = async () => {
|
|
337
|
+
setLoading(true);
|
|
338
|
+
await supabase.auth.signInWithOAuth({
|
|
339
|
+
provider: "google",
|
|
340
|
+
options: {
|
|
341
|
+
redirectTo: redirectTo != null ? redirectTo : `${window.location.origin}/auth/callback`,
|
|
342
|
+
queryParams: { prompt: "select_account" }
|
|
343
|
+
}
|
|
344
|
+
});
|
|
345
|
+
};
|
|
346
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
347
|
+
import_core2.Button,
|
|
348
|
+
{
|
|
349
|
+
type: "button",
|
|
350
|
+
fullWidth: true,
|
|
351
|
+
size: "md",
|
|
352
|
+
variant: "default",
|
|
353
|
+
leftSection: loading ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_core2.Loader, { size: 18 }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(GoogleIcon, {}),
|
|
354
|
+
onClick: handleGoogleLogin,
|
|
355
|
+
disabled: isPending || loading,
|
|
356
|
+
styles: {
|
|
357
|
+
root: {
|
|
358
|
+
fontWeight: 500,
|
|
359
|
+
height: 44,
|
|
360
|
+
backgroundColor: "var(--mantine-color-white)",
|
|
361
|
+
color: "var(--mantine-color-gray-9)",
|
|
362
|
+
borderColor: "var(--mantine-color-gray-3)"
|
|
363
|
+
}
|
|
364
|
+
},
|
|
365
|
+
children: "Sign in with Google"
|
|
366
|
+
}
|
|
367
|
+
);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// src/components/login/index.tsx
|
|
371
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
372
|
+
function LoginPage({
|
|
373
|
+
title = "Sign in",
|
|
374
|
+
description = "Authenticate once. Operate everywhere.",
|
|
375
|
+
info,
|
|
376
|
+
redirectTo,
|
|
377
|
+
header,
|
|
378
|
+
footer,
|
|
379
|
+
onVerifyNeeded,
|
|
380
|
+
onResetRequest,
|
|
381
|
+
onSuccess
|
|
382
|
+
}) {
|
|
383
|
+
const [isPending, startTransition] = (0, import_react3.useTransition)();
|
|
384
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_core3.Box, { w: "100%", children: [
|
|
385
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_core3.Box, { maw: 460, children: [
|
|
386
|
+
header && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_core3.Box, { mb: "lg", ta: "center", children: header }),
|
|
387
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_core3.Title, { order: 3, fw: 600, c: "gray.7", mb: "xs", children: [
|
|
388
|
+
title,
|
|
389
|
+
info && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_core3.Box, { component: "span", style: { whiteSpace: "nowrap" }, children: [
|
|
390
|
+
"\xA0",
|
|
391
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_core3.HoverCard, { width: 300, shadow: "md", withArrow: true, position: "bottom-start", openDelay: 100, children: [
|
|
392
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_core3.HoverCard.Target, { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
393
|
+
import_core3.ActionIcon,
|
|
394
|
+
{
|
|
395
|
+
variant: "subtle",
|
|
396
|
+
color: "gray",
|
|
397
|
+
size: "sm",
|
|
398
|
+
display: "inline-flex",
|
|
399
|
+
style: { verticalAlign: "middle" },
|
|
400
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_icons_react.IconInfoCircle, { size: 16 })
|
|
401
|
+
}
|
|
402
|
+
) }),
|
|
403
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_core3.HoverCard.Dropdown, { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_core3.Text, { size: "xs", c: "dimmed", lh: 1.6, children: info }) })
|
|
404
|
+
] })
|
|
405
|
+
] })
|
|
406
|
+
] }),
|
|
407
|
+
description && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_core3.Text, { size: "sm", c: "gray.6", mb: "lg", children: description }),
|
|
408
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
409
|
+
EmailPasswordForm,
|
|
410
|
+
{
|
|
411
|
+
isPending,
|
|
412
|
+
startTransition,
|
|
413
|
+
onVerifyNeeded,
|
|
414
|
+
onResetRequest,
|
|
415
|
+
onSuccess
|
|
416
|
+
}
|
|
417
|
+
),
|
|
418
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_core3.Divider, { my: "lg", label: "or continue with", labelPosition: "center", color: "gray.3" }),
|
|
419
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(GoogleSignIn, { redirectTo, isPending })
|
|
420
|
+
] }),
|
|
421
|
+
footer && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
422
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_core3.Divider, { my: "lg", color: "gray.3" }),
|
|
423
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_core3.Box, { ta: "left", w: "100%", children: footer })
|
|
424
|
+
] })
|
|
425
|
+
] });
|
|
426
|
+
}
|
|
427
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
428
|
+
0 && (module.exports = {
|
|
429
|
+
LoginPage
|
|
430
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
|
|
3
|
+
interface ResetPasswordFormProps {
|
|
4
|
+
onComplete: () => void;
|
|
5
|
+
onBackToLogin?: () => void;
|
|
6
|
+
/** Content rendered above the form (e.g. a logo). */
|
|
7
|
+
header?: React.ReactNode;
|
|
8
|
+
}
|
|
9
|
+
declare function ResetPasswordForm({ onComplete, onBackToLogin, header }: ResetPasswordFormProps): react_jsx_runtime.JSX.Element;
|
|
10
|
+
|
|
11
|
+
export { ResetPasswordForm };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
|
|
3
|
+
interface ResetPasswordFormProps {
|
|
4
|
+
onComplete: () => void;
|
|
5
|
+
onBackToLogin?: () => void;
|
|
6
|
+
/** Content rendered above the form (e.g. a logo). */
|
|
7
|
+
header?: React.ReactNode;
|
|
8
|
+
}
|
|
9
|
+
declare function ResetPasswordForm({ onComplete, onBackToLogin, header }: ResetPasswordFormProps): react_jsx_runtime.JSX.Element;
|
|
10
|
+
|
|
11
|
+
export { ResetPasswordForm };
|