@fayz-ai/plugin-auth 0.12.25 → 0.13.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/index.d.ts +28 -12
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -853
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
- package/dist/components/AmbassadorBubbles.d.ts +0 -9
- package/dist/components/AmbassadorBubbles.d.ts.map +0 -1
- package/dist/components/forms.d.ts +0 -71
- package/dist/components/forms.d.ts.map +0 -1
- package/dist/lib/runtime.d.ts +0 -6
- package/dist/lib/runtime.d.ts.map +0 -1
- package/dist/types.d.ts +0 -64
- package/dist/types.d.ts.map +0 -1
- package/dist/views/pages.d.ts +0 -52
- package/dist/views/pages.d.ts.map +0 -1
- package/dist/views/set-password.d.ts +0 -32
- package/dist/views/set-password.d.ts.map +0 -1
- package/dist/views/verify-email.d.ts +0 -15
- package/dist/views/verify-email.d.ts.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,856 +1,17 @@
|
|
|
1
|
-
|
|
1
|
+
export { createAuthPlugin, createAuthRuntime, resolveAuthAdapter } from '@fayz-ai/auth/lib/runtime';
|
|
2
|
+
export { AuthGate } from '@fayz-ai/auth/views/AuthGate';
|
|
3
|
+
export { LoginPage } from '@fayz-ai/auth/views/LoginPage';
|
|
4
|
+
export { AuthCallbackPage } from '@fayz-ai/auth/views/AuthCallbackPage';
|
|
5
|
+
export { ResetPasswordPage } from '@fayz-ai/auth/views/ResetPasswordPage';
|
|
6
|
+
export { VerifyEmailNotice } from '@fayz-ai/auth/views/VerifyEmailNotice';
|
|
7
|
+
export { SetPasswordPage } from '@fayz-ai/auth/views/SetPasswordPage';
|
|
8
|
+
export { usePasswordSetupGate } from '@fayz-ai/auth/views/usePasswordSetupGate';
|
|
9
|
+
export { AmbassadorBubbles } from '@fayz-ai/auth/components/AmbassadorBubbles';
|
|
10
|
+
export { LoginForm } from '@fayz-ai/auth/views/LoginForm';
|
|
11
|
+
export { SignupForm } from '@fayz-ai/auth/views/SignupForm';
|
|
12
|
+
export { ForgotPasswordForm } from '@fayz-ai/auth/views/ForgotPasswordForm';
|
|
13
|
+
export { ResetPasswordForm } from '@fayz-ai/auth/views/ResetPasswordForm';
|
|
14
|
+
export { OAuthButtons } from '@fayz-ai/auth/views/OAuthButtons';
|
|
2
15
|
export { AuthProvider, clearAuthUrlTokens, createMockAuthAdapter, createSupabaseAuthAdapter, readAuthUrlIntent, useAuth, useAuthStore } from '@fayz-ai/auth';
|
|
3
|
-
import * as React from 'react';
|
|
4
|
-
import { tl, useTranslation } from '@fayz-ai/core';
|
|
5
|
-
import { EyeOff, Eye, MailCheck, Gift } from 'lucide-react';
|
|
6
|
-
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
7
|
-
|
|
8
|
-
// src/lib/runtime.ts
|
|
9
|
-
function absoluteUrl(path) {
|
|
10
|
-
if (typeof window === "undefined") return void 0;
|
|
11
|
-
if (/^https?:\/\//.test(path)) return path;
|
|
12
|
-
return `${window.location.origin}${path.startsWith("/") ? path : `/${path}`}`;
|
|
13
|
-
}
|
|
14
|
-
function resolveAuthAdapter(options = {}) {
|
|
15
|
-
const configured = options.adapter ?? options.provider;
|
|
16
|
-
if (configured && typeof configured === "object") return configured;
|
|
17
|
-
const provider = configured ?? (options.supabase?.url ? "supabase" : "mock");
|
|
18
|
-
if (provider === "supabase") {
|
|
19
|
-
const url = options.supabase?.url;
|
|
20
|
-
const anonKey = options.supabase?.anonKey;
|
|
21
|
-
if (!url || !anonKey) {
|
|
22
|
-
throw new Error('plugin-auth provider="supabase" requires supabase.url and supabase.anonKey.');
|
|
23
|
-
}
|
|
24
|
-
return createSupabaseAuthAdapter({
|
|
25
|
-
supabaseUrl: url,
|
|
26
|
-
supabaseAnonKey: anonKey,
|
|
27
|
-
supabaseClient: options.supabase?.client,
|
|
28
|
-
callbackUrl: options.supabase?.callbackUrl ?? absoluteUrl(options.routes?.callback ?? "/auth/callback"),
|
|
29
|
-
// Only when the host asked for a specific URL. Left undefined, the adapter
|
|
30
|
-
// points recovery at the app root, which needs no route and no extra entry
|
|
31
|
-
// in Supabase's redirect allow-list.
|
|
32
|
-
resetPasswordUrl: options.supabase?.resetPasswordUrl ?? (options.routes?.resetPassword ? absoluteUrl(options.routes.resetPassword) : void 0)
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
return createMockAuthAdapter();
|
|
36
|
-
}
|
|
37
|
-
function createAuthRuntime(options = {}) {
|
|
38
|
-
return {
|
|
39
|
-
kind: "auth",
|
|
40
|
-
adapter: resolveAuthAdapter(options),
|
|
41
|
-
requireAuth: options.requireAuth ?? true,
|
|
42
|
-
layout: options.layout ?? "split",
|
|
43
|
-
logo: options.logo,
|
|
44
|
-
tagline: options.tagline,
|
|
45
|
-
description: options.description,
|
|
46
|
-
loginAmbassadors: options.loginAmbassadors,
|
|
47
|
-
loginAmbassadorsLabel: options.loginAmbassadorsLabel,
|
|
48
|
-
oauth: {
|
|
49
|
-
enabled: options.oauth?.enabled ?? false,
|
|
50
|
-
providers: options.oauth?.providers ?? ["google"],
|
|
51
|
-
// Disabled until the grant is wired; an app that has it working passes [].
|
|
52
|
-
comingSoon: options.oauth?.comingSoon ?? ["google"]
|
|
53
|
-
},
|
|
54
|
-
routes: {
|
|
55
|
-
login: options.routes?.login ?? "/login",
|
|
56
|
-
callback: options.routes?.callback ?? "/auth/callback",
|
|
57
|
-
// The app root — recovery links are recognised by their own params, not by
|
|
58
|
-
// the path they land on. See resetPassword() in the Supabase adapter.
|
|
59
|
-
resetPassword: options.routes?.resetPassword ?? "/",
|
|
60
|
-
afterSignIn: options.routes?.afterSignIn ?? "/"
|
|
61
|
-
}
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
|
-
function createAuthPlugin(options = {}) {
|
|
65
|
-
return createAuthRuntime(options);
|
|
66
|
-
}
|
|
67
|
-
function providerLabel(provider) {
|
|
68
|
-
return provider.charAt(0).toUpperCase() + provider.slice(1);
|
|
69
|
-
}
|
|
70
|
-
function fieldClass() {
|
|
71
|
-
return "h-10 w-full rounded-input border border-input bg-background px-3 py-2 text-sm outline-none focus:ring-2 focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50";
|
|
72
|
-
}
|
|
73
|
-
function buttonClass(variant = "primary") {
|
|
74
|
-
if (variant === "outline") {
|
|
75
|
-
return "inline-flex h-10 w-full items-center justify-center rounded-input border border-input bg-background px-4 py-2 text-sm font-medium transition-colors hover:bg-muted disabled:pointer-events-none disabled:opacity-50";
|
|
76
|
-
}
|
|
77
|
-
if (variant === "ghost") return "text-sm font-medium text-primary hover:underline";
|
|
78
|
-
return "inline-flex h-10 w-full items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground transition-colors hover:bg-primary/90 disabled:pointer-events-none disabled:opacity-50";
|
|
79
|
-
}
|
|
80
|
-
function GoogleMark({ className }) {
|
|
81
|
-
return /* @__PURE__ */ jsxs("svg", { className, viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", "aria-hidden": true, children: [
|
|
82
|
-
/* @__PURE__ */ jsx("path", { d: "M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92a5.06 5.06 0 01-2.2 3.32v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.1z", fill: "#4285F4" }),
|
|
83
|
-
/* @__PURE__ */ jsx("path", { d: "M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z", fill: "#34A853" }),
|
|
84
|
-
/* @__PURE__ */ jsx("path", { d: "M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z", fill: "#FBBC05" }),
|
|
85
|
-
/* @__PURE__ */ jsx("path", { d: "M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z", fill: "#EA4335" })
|
|
86
|
-
] });
|
|
87
|
-
}
|
|
88
|
-
var PROVIDER_MARKS = {
|
|
89
|
-
google: GoogleMark
|
|
90
|
-
};
|
|
91
|
-
function OAuthButtons({ providers = ["google"], disabled, comingSoon, onProviderClick }) {
|
|
92
|
-
const { signInWithOAuth } = useAuth();
|
|
93
|
-
return /* @__PURE__ */ jsx("div", { className: "space-y-2", children: providers.map((provider) => {
|
|
94
|
-
const soon = comingSoon?.includes(provider) ?? false;
|
|
95
|
-
const Mark = PROVIDER_MARKS[provider];
|
|
96
|
-
return /* @__PURE__ */ jsxs(
|
|
97
|
-
"button",
|
|
98
|
-
{
|
|
99
|
-
type: "button",
|
|
100
|
-
className: `${buttonClass("outline")} gap-2`,
|
|
101
|
-
disabled: disabled || soon,
|
|
102
|
-
title: soon ? "Ainda n\xE3o dispon\xEDvel" : void 0,
|
|
103
|
-
onClick: () => {
|
|
104
|
-
if (soon) return;
|
|
105
|
-
void (onProviderClick ? onProviderClick(provider) : signInWithOAuth(provider));
|
|
106
|
-
},
|
|
107
|
-
children: [
|
|
108
|
-
Mark && /* @__PURE__ */ jsx(Mark, { className: "h-4 w-4 shrink-0" }),
|
|
109
|
-
"Continuar com ",
|
|
110
|
-
providerLabel(provider)
|
|
111
|
-
]
|
|
112
|
-
},
|
|
113
|
-
provider
|
|
114
|
-
);
|
|
115
|
-
}) });
|
|
116
|
-
}
|
|
117
|
-
function LoginForm({
|
|
118
|
-
onSuccess,
|
|
119
|
-
onForgotPassword,
|
|
120
|
-
showOAuth,
|
|
121
|
-
oauthProviders,
|
|
122
|
-
oauthComingSoon,
|
|
123
|
-
initialEmail = "",
|
|
124
|
-
onEmailChange
|
|
125
|
-
}) {
|
|
126
|
-
const { signIn, error, isLoading } = useAuth();
|
|
127
|
-
const [email, setEmail] = React.useState(initialEmail);
|
|
128
|
-
const [password, setPassword] = React.useState("");
|
|
129
|
-
const [reveal, setReveal] = React.useState(false);
|
|
130
|
-
const [busy, setBusy] = React.useState(false);
|
|
131
|
-
const disabled = busy || isLoading;
|
|
132
|
-
async function submit(event) {
|
|
133
|
-
event.preventDefault();
|
|
134
|
-
setBusy(true);
|
|
135
|
-
try {
|
|
136
|
-
await signIn(email, password);
|
|
137
|
-
onSuccess?.();
|
|
138
|
-
} finally {
|
|
139
|
-
setBusy(false);
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
return /* @__PURE__ */ jsxs("form", { onSubmit: submit, className: "space-y-4", children: [
|
|
143
|
-
/* @__PURE__ */ jsxs("label", { className: "block space-y-1.5 text-sm font-medium", children: [
|
|
144
|
-
/* @__PURE__ */ jsx("span", { children: tl("Email", "E-mail") }),
|
|
145
|
-
/* @__PURE__ */ jsx(
|
|
146
|
-
"input",
|
|
147
|
-
{
|
|
148
|
-
className: fieldClass(),
|
|
149
|
-
type: "email",
|
|
150
|
-
autoComplete: "username",
|
|
151
|
-
required: true,
|
|
152
|
-
value: email,
|
|
153
|
-
onChange: (e) => {
|
|
154
|
-
setEmail(e.target.value);
|
|
155
|
-
onEmailChange?.(e.target.value);
|
|
156
|
-
},
|
|
157
|
-
disabled
|
|
158
|
-
}
|
|
159
|
-
)
|
|
160
|
-
] }),
|
|
161
|
-
/* @__PURE__ */ jsxs("label", { className: "block space-y-1.5 text-sm font-medium", children: [
|
|
162
|
-
/* @__PURE__ */ jsx("span", { children: tl("Password", "Senha") }),
|
|
163
|
-
/* @__PURE__ */ jsxs("span", { className: "relative block", children: [
|
|
164
|
-
/* @__PURE__ */ jsx("input", { className: `${fieldClass()} pr-10`, type: reveal ? "text" : "password", autoComplete: "current-password", required: true, value: password, onChange: (e) => setPassword(e.target.value), disabled }),
|
|
165
|
-
/* @__PURE__ */ jsx(
|
|
166
|
-
"button",
|
|
167
|
-
{
|
|
168
|
-
type: "button",
|
|
169
|
-
onClick: () => setReveal((v) => !v),
|
|
170
|
-
"aria-label": reveal ? tl("Hide password", "Ocultar senha") : tl("Show password", "Mostrar senha"),
|
|
171
|
-
"aria-pressed": reveal,
|
|
172
|
-
tabIndex: -1,
|
|
173
|
-
className: "absolute inset-y-0 right-0 flex w-10 items-center justify-center rounded-r-md text-muted-foreground transition-colors hover:text-foreground",
|
|
174
|
-
children: reveal ? /* @__PURE__ */ jsx(EyeOff, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx(Eye, { className: "h-4 w-4" })
|
|
175
|
-
}
|
|
176
|
-
)
|
|
177
|
-
] })
|
|
178
|
-
] }),
|
|
179
|
-
onForgotPassword && /* @__PURE__ */ jsx("div", { className: "-mt-1 flex justify-end", children: /* @__PURE__ */ jsx("button", { type: "button", className: buttonClass("ghost"), onClick: onForgotPassword, children: tl("Forgot password?", "Esqueceu a senha?") }) }),
|
|
180
|
-
error && /* @__PURE__ */ jsx("p", { className: "text-sm text-destructive", children: error.message }),
|
|
181
|
-
/* @__PURE__ */ jsx("button", { className: buttonClass(), type: "submit", disabled, children: disabled ? tl("Signing in...", "Entrando...") : tl("Sign in", "Entrar") }),
|
|
182
|
-
showOAuth && /* @__PURE__ */ jsx(OAuthButtons, { providers: oauthProviders, disabled, comingSoon: oauthComingSoon })
|
|
183
|
-
] });
|
|
184
|
-
}
|
|
185
|
-
var MIN_PASSWORD = 8;
|
|
186
|
-
function SignupForm({
|
|
187
|
-
onSuccess,
|
|
188
|
-
showOAuth,
|
|
189
|
-
oauthProviders,
|
|
190
|
-
oauthComingSoon,
|
|
191
|
-
requireConfirmation = false,
|
|
192
|
-
termsUrl,
|
|
193
|
-
privacyUrl
|
|
194
|
-
}) {
|
|
195
|
-
const { signUp, error, isLoading } = useAuth();
|
|
196
|
-
const [fullName, setFullName] = React.useState("");
|
|
197
|
-
const [email, setEmail] = React.useState("");
|
|
198
|
-
const [password, setPassword] = React.useState("");
|
|
199
|
-
const [confirmPassword, setConfirmPassword] = React.useState("");
|
|
200
|
-
const [reveal, setReveal] = React.useState(false);
|
|
201
|
-
const [localError, setLocalError] = React.useState(null);
|
|
202
|
-
const [busy, setBusy] = React.useState(false);
|
|
203
|
-
const disabled = busy || isLoading;
|
|
204
|
-
const passwordRef = React.useRef(null);
|
|
205
|
-
async function submit(event) {
|
|
206
|
-
event.preventDefault();
|
|
207
|
-
setLocalError(null);
|
|
208
|
-
if (password.length < MIN_PASSWORD) {
|
|
209
|
-
setLocalError(tl(
|
|
210
|
-
`Use at least ${MIN_PASSWORD} characters.`,
|
|
211
|
-
`Use pelo menos ${MIN_PASSWORD} caracteres.`
|
|
212
|
-
));
|
|
213
|
-
passwordRef.current?.focus();
|
|
214
|
-
return;
|
|
215
|
-
}
|
|
216
|
-
if (requireConfirmation && password !== confirmPassword) {
|
|
217
|
-
setLocalError(tl("The passwords do not match.", "As senhas n\xE3o conferem."));
|
|
218
|
-
return;
|
|
219
|
-
}
|
|
220
|
-
setBusy(true);
|
|
221
|
-
try {
|
|
222
|
-
await signUp(email, password, fullName);
|
|
223
|
-
onSuccess?.();
|
|
224
|
-
} finally {
|
|
225
|
-
setBusy(false);
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
const tooShort = password.length > 0 && password.length < MIN_PASSWORD;
|
|
229
|
-
return /* @__PURE__ */ jsxs("form", { onSubmit: submit, className: "space-y-4", children: [
|
|
230
|
-
/* @__PURE__ */ jsxs("label", { className: "block space-y-1.5 text-sm font-medium", children: [
|
|
231
|
-
/* @__PURE__ */ jsx("span", { children: tl("Full name", "Nome completo") }),
|
|
232
|
-
/* @__PURE__ */ jsx(
|
|
233
|
-
"input",
|
|
234
|
-
{
|
|
235
|
-
className: fieldClass(),
|
|
236
|
-
autoComplete: "name",
|
|
237
|
-
required: true,
|
|
238
|
-
value: fullName,
|
|
239
|
-
onChange: (e) => setFullName(e.target.value),
|
|
240
|
-
disabled
|
|
241
|
-
}
|
|
242
|
-
)
|
|
243
|
-
] }),
|
|
244
|
-
/* @__PURE__ */ jsxs("label", { className: "block space-y-1.5 text-sm font-medium", children: [
|
|
245
|
-
/* @__PURE__ */ jsx("span", { children: tl("Email", "E-mail") }),
|
|
246
|
-
/* @__PURE__ */ jsx(
|
|
247
|
-
"input",
|
|
248
|
-
{
|
|
249
|
-
className: fieldClass(),
|
|
250
|
-
type: "email",
|
|
251
|
-
inputMode: "email",
|
|
252
|
-
autoComplete: "username",
|
|
253
|
-
required: true,
|
|
254
|
-
value: email,
|
|
255
|
-
onChange: (e) => setEmail(e.target.value),
|
|
256
|
-
disabled
|
|
257
|
-
}
|
|
258
|
-
)
|
|
259
|
-
] }),
|
|
260
|
-
/* @__PURE__ */ jsxs("div", { className: "space-y-1.5 text-sm font-medium", children: [
|
|
261
|
-
/* @__PURE__ */ jsxs("label", { className: "block space-y-1.5", htmlFor: "signup-password", children: [
|
|
262
|
-
/* @__PURE__ */ jsx("span", { children: tl("Password", "Senha") }),
|
|
263
|
-
/* @__PURE__ */ jsxs("span", { className: "relative block", children: [
|
|
264
|
-
/* @__PURE__ */ jsx(
|
|
265
|
-
"input",
|
|
266
|
-
{
|
|
267
|
-
id: "signup-password",
|
|
268
|
-
ref: passwordRef,
|
|
269
|
-
className: `${fieldClass()} pr-10`,
|
|
270
|
-
type: reveal ? "text" : "password",
|
|
271
|
-
autoComplete: "new-password",
|
|
272
|
-
minLength: MIN_PASSWORD,
|
|
273
|
-
required: true,
|
|
274
|
-
value: password,
|
|
275
|
-
onChange: (e) => setPassword(e.target.value),
|
|
276
|
-
disabled,
|
|
277
|
-
"aria-describedby": "signup-password-hint"
|
|
278
|
-
}
|
|
279
|
-
),
|
|
280
|
-
/* @__PURE__ */ jsx(
|
|
281
|
-
"button",
|
|
282
|
-
{
|
|
283
|
-
type: "button",
|
|
284
|
-
onClick: () => setReveal((v) => !v),
|
|
285
|
-
"aria-label": reveal ? tl("Hide password", "Ocultar senha") : tl("Show password", "Mostrar senha"),
|
|
286
|
-
"aria-pressed": reveal,
|
|
287
|
-
className: "absolute inset-y-0 right-0 flex w-10 items-center justify-center rounded-r-md text-muted-foreground transition-colors hover:text-foreground",
|
|
288
|
-
children: reveal ? /* @__PURE__ */ jsx(EyeOff, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx(Eye, { className: "h-4 w-4" })
|
|
289
|
-
}
|
|
290
|
-
)
|
|
291
|
-
] })
|
|
292
|
-
] }),
|
|
293
|
-
/* @__PURE__ */ jsx(
|
|
294
|
-
"p",
|
|
295
|
-
{
|
|
296
|
-
id: "signup-password-hint",
|
|
297
|
-
className: `text-xs font-normal ${tooShort ? "text-warning" : "text-muted-foreground"}`,
|
|
298
|
-
children: tl(`At least ${MIN_PASSWORD} characters.`, `Pelo menos ${MIN_PASSWORD} caracteres.`)
|
|
299
|
-
}
|
|
300
|
-
)
|
|
301
|
-
] }),
|
|
302
|
-
requireConfirmation && /* @__PURE__ */ jsxs("label", { className: "block space-y-1.5 text-sm font-medium", children: [
|
|
303
|
-
/* @__PURE__ */ jsx("span", { children: tl("Confirm password", "Confirme a senha") }),
|
|
304
|
-
/* @__PURE__ */ jsx(
|
|
305
|
-
"input",
|
|
306
|
-
{
|
|
307
|
-
className: fieldClass(),
|
|
308
|
-
type: reveal ? "text" : "password",
|
|
309
|
-
autoComplete: "new-password",
|
|
310
|
-
required: true,
|
|
311
|
-
value: confirmPassword,
|
|
312
|
-
onChange: (e) => setConfirmPassword(e.target.value),
|
|
313
|
-
disabled
|
|
314
|
-
}
|
|
315
|
-
)
|
|
316
|
-
] }),
|
|
317
|
-
(localError || error) && /* @__PURE__ */ jsx("p", { role: "alert", className: "text-sm text-destructive", children: localError ?? error?.message }),
|
|
318
|
-
/* @__PURE__ */ jsx("button", { className: buttonClass(), type: "submit", disabled, children: disabled ? tl("Creating account...", "Criando conta...") : tl("Create account", "Criar conta") }),
|
|
319
|
-
(termsUrl || privacyUrl) && /* @__PURE__ */ jsxs("p", { className: "text-center text-xs leading-relaxed text-muted-foreground", children: [
|
|
320
|
-
tl("By continuing you agree to our", "Ao continuar, voc\xEA concorda com os"),
|
|
321
|
-
" ",
|
|
322
|
-
termsUrl && /* @__PURE__ */ jsx("a", { href: termsUrl, target: "_blank", rel: "noopener noreferrer", className: "underline hover:text-foreground", children: tl("terms of service", "termos de uso") }),
|
|
323
|
-
termsUrl && privacyUrl && tl(" and ", " e a "),
|
|
324
|
-
privacyUrl && /* @__PURE__ */ jsx("a", { href: privacyUrl, target: "_blank", rel: "noopener noreferrer", className: "underline hover:text-foreground", children: tl("privacy policy", "pol\xEDtica de privacidade") }),
|
|
325
|
-
"."
|
|
326
|
-
] }),
|
|
327
|
-
showOAuth && /* @__PURE__ */ jsx(OAuthButtons, { providers: oauthProviders, disabled, comingSoon: oauthComingSoon })
|
|
328
|
-
] });
|
|
329
|
-
}
|
|
330
|
-
function ForgotPasswordForm({
|
|
331
|
-
redirectTo,
|
|
332
|
-
onSent,
|
|
333
|
-
onBackToLogin,
|
|
334
|
-
initialEmail = "",
|
|
335
|
-
onEmailChange,
|
|
336
|
-
emailLabel = tl("Email", "E-mail"),
|
|
337
|
-
submitLabel = tl("Send reset link", "Enviar link de redefini\xE7\xE3o"),
|
|
338
|
-
sendingLabel = tl("Sending...", "Enviando..."),
|
|
339
|
-
sentLabel = tl("Password reset instructions sent.", "Instru\xE7\xF5es de redefini\xE7\xE3o enviadas."),
|
|
340
|
-
backLabel = tl("Back to login", "Voltar para o login")
|
|
341
|
-
}) {
|
|
342
|
-
const { resetPassword, error, isLoading } = useAuth();
|
|
343
|
-
const [email, setEmail] = React.useState(initialEmail);
|
|
344
|
-
const [sent, setSent] = React.useState(false);
|
|
345
|
-
const [busy, setBusy] = React.useState(false);
|
|
346
|
-
const disabled = busy || isLoading;
|
|
347
|
-
async function submit(event) {
|
|
348
|
-
event.preventDefault();
|
|
349
|
-
setBusy(true);
|
|
350
|
-
try {
|
|
351
|
-
await resetPassword(email, { redirectTo });
|
|
352
|
-
setSent(true);
|
|
353
|
-
onSent?.(email);
|
|
354
|
-
} finally {
|
|
355
|
-
setBusy(false);
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
return /* @__PURE__ */ jsxs("form", { onSubmit: submit, className: "space-y-4", children: [
|
|
359
|
-
/* @__PURE__ */ jsxs("label", { className: "block space-y-1.5 text-sm font-medium", children: [
|
|
360
|
-
/* @__PURE__ */ jsx("span", { children: emailLabel }),
|
|
361
|
-
/* @__PURE__ */ jsx(
|
|
362
|
-
"input",
|
|
363
|
-
{
|
|
364
|
-
className: fieldClass(),
|
|
365
|
-
type: "email",
|
|
366
|
-
autoComplete: "username",
|
|
367
|
-
required: true,
|
|
368
|
-
autoFocus: !email,
|
|
369
|
-
value: email,
|
|
370
|
-
onChange: (e) => {
|
|
371
|
-
setEmail(e.target.value);
|
|
372
|
-
onEmailChange?.(e.target.value);
|
|
373
|
-
},
|
|
374
|
-
disabled
|
|
375
|
-
}
|
|
376
|
-
)
|
|
377
|
-
] }),
|
|
378
|
-
error && /* @__PURE__ */ jsx("p", { className: "text-sm text-destructive", children: error.message }),
|
|
379
|
-
sent && /* @__PURE__ */ jsx("p", { className: "text-sm text-emerald-600", children: sentLabel }),
|
|
380
|
-
/* @__PURE__ */ jsx("button", { className: buttonClass(), type: "submit", disabled, children: disabled ? sendingLabel : submitLabel }),
|
|
381
|
-
onBackToLogin && /* @__PURE__ */ jsx("button", { type: "button", className: buttonClass("ghost"), onClick: onBackToLogin, children: backLabel })
|
|
382
|
-
] });
|
|
383
|
-
}
|
|
384
|
-
function ResetPasswordForm({ onSuccess }) {
|
|
385
|
-
const { updatePassword, error, isLoading } = useAuth();
|
|
386
|
-
const [password, setPassword] = React.useState("");
|
|
387
|
-
const [confirmPassword, setConfirmPassword] = React.useState("");
|
|
388
|
-
const [localError, setLocalError] = React.useState(null);
|
|
389
|
-
const [busy, setBusy] = React.useState(false);
|
|
390
|
-
const disabled = busy || isLoading;
|
|
391
|
-
async function submit(event) {
|
|
392
|
-
event.preventDefault();
|
|
393
|
-
setLocalError(null);
|
|
394
|
-
if (password.length < 8) {
|
|
395
|
-
setLocalError(tl("Password must be at least 8 characters.", "A senha precisa ter pelo menos 8 caracteres."));
|
|
396
|
-
return;
|
|
397
|
-
}
|
|
398
|
-
if (password !== confirmPassword) {
|
|
399
|
-
setLocalError(tl("Passwords do not match.", "As senhas n\xE3o conferem."));
|
|
400
|
-
return;
|
|
401
|
-
}
|
|
402
|
-
setBusy(true);
|
|
403
|
-
try {
|
|
404
|
-
await updatePassword(password);
|
|
405
|
-
onSuccess?.();
|
|
406
|
-
} finally {
|
|
407
|
-
setBusy(false);
|
|
408
|
-
}
|
|
409
|
-
}
|
|
410
|
-
return /* @__PURE__ */ jsxs("form", { onSubmit: submit, className: "space-y-4", children: [
|
|
411
|
-
/* @__PURE__ */ jsxs("label", { className: "block space-y-1.5 text-sm font-medium", children: [
|
|
412
|
-
/* @__PURE__ */ jsx("span", { children: tl("New password", "Nova senha") }),
|
|
413
|
-
/* @__PURE__ */ jsx("input", { className: fieldClass(), type: "password", autoComplete: "new-password", required: true, value: password, onChange: (e) => setPassword(e.target.value), disabled })
|
|
414
|
-
] }),
|
|
415
|
-
/* @__PURE__ */ jsxs("label", { className: "block space-y-1.5 text-sm font-medium", children: [
|
|
416
|
-
/* @__PURE__ */ jsx("span", { children: tl("Confirm password", "Confirme a senha") }),
|
|
417
|
-
/* @__PURE__ */ jsx("input", { className: fieldClass(), type: "password", autoComplete: "new-password", required: true, value: confirmPassword, onChange: (e) => setConfirmPassword(e.target.value), disabled })
|
|
418
|
-
] }),
|
|
419
|
-
(localError || error) && /* @__PURE__ */ jsx("p", { className: "text-sm text-destructive", children: localError ?? error?.message }),
|
|
420
|
-
/* @__PURE__ */ jsx("button", { className: buttonClass(), type: "submit", disabled, children: disabled ? tl("Saving...", "Salvando...") : tl("Update password", "Atualizar senha") })
|
|
421
|
-
] });
|
|
422
|
-
}
|
|
423
|
-
var MIN_LENGTH = 8;
|
|
424
|
-
function fieldClass2() {
|
|
425
|
-
return "h-10 w-full rounded-input border border-input bg-background px-3 py-2 text-sm outline-none focus:ring-2 focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50";
|
|
426
|
-
}
|
|
427
|
-
function buttonClass2() {
|
|
428
|
-
return "inline-flex h-10 w-full items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground transition-colors hover:bg-primary/90 disabled:pointer-events-none disabled:opacity-50";
|
|
429
|
-
}
|
|
430
|
-
function useTr() {
|
|
431
|
-
const t = useTranslation();
|
|
432
|
-
return React.useCallback(
|
|
433
|
-
(key, fallback, params) => {
|
|
434
|
-
const value = t(key, params);
|
|
435
|
-
return !value || value === key ? fallback : value;
|
|
436
|
-
},
|
|
437
|
-
[t]
|
|
438
|
-
);
|
|
439
|
-
}
|
|
440
|
-
function usePasswordSetupGate() {
|
|
441
|
-
const { user, isLoading, isAuthenticated } = useAuth();
|
|
442
|
-
const [done, setDone] = React.useState(false);
|
|
443
|
-
const intent = React.useMemo(() => readAuthUrlIntent(), []);
|
|
444
|
-
const complete = React.useCallback(() => {
|
|
445
|
-
clearAuthUrlTokens();
|
|
446
|
-
setDone(true);
|
|
447
|
-
}, []);
|
|
448
|
-
if (done) return { reason: null, expired: false, checking: false, complete };
|
|
449
|
-
const decision = decidePasswordSetup({
|
|
450
|
-
intent,
|
|
451
|
-
isLoading,
|
|
452
|
-
isAuthenticated,
|
|
453
|
-
mustSetPassword: user?.mustSetPassword
|
|
454
|
-
});
|
|
455
|
-
return { ...decision, complete };
|
|
456
|
-
}
|
|
457
|
-
function SetPasswordPage({
|
|
458
|
-
reason,
|
|
459
|
-
appName = "App",
|
|
460
|
-
logo,
|
|
461
|
-
expired,
|
|
462
|
-
checking,
|
|
463
|
-
onSuccess
|
|
464
|
-
}) {
|
|
465
|
-
const tr = useTr();
|
|
466
|
-
const { user, updatePassword, signOut, error, isLoading } = useAuth();
|
|
467
|
-
const [password, setPassword] = React.useState("");
|
|
468
|
-
const [confirmPassword, setConfirmPassword] = React.useState("");
|
|
469
|
-
const [localError, setLocalError] = React.useState(null);
|
|
470
|
-
const [busy, setBusy] = React.useState(false);
|
|
471
|
-
const disabled = busy || isLoading;
|
|
472
|
-
const invite = reason === "invite";
|
|
473
|
-
const title = invite ? tr("auth.setPassword.welcomeTitle", `Welcome to ${appName}`, { appName }) : tr("auth.setPassword.recoveryTitle", "Choose a new password");
|
|
474
|
-
const subtitle = invite ? tr("auth.setPassword.welcomeSubtitle", "Choose a password to finish setting up your access.") : tr("auth.setPassword.recoverySubtitle", "Set a new password to get back into your account.");
|
|
475
|
-
async function submit(event) {
|
|
476
|
-
event.preventDefault();
|
|
477
|
-
setLocalError(null);
|
|
478
|
-
if (password.length < MIN_LENGTH) {
|
|
479
|
-
setLocalError(tr("auth.setPassword.tooShort", `Password must be at least ${MIN_LENGTH} characters.`));
|
|
480
|
-
return;
|
|
481
|
-
}
|
|
482
|
-
if (password !== confirmPassword) {
|
|
483
|
-
setLocalError(tr("auth.setPassword.mismatch", "Passwords do not match."));
|
|
484
|
-
return;
|
|
485
|
-
}
|
|
486
|
-
setBusy(true);
|
|
487
|
-
try {
|
|
488
|
-
await updatePassword(password);
|
|
489
|
-
onSuccess?.();
|
|
490
|
-
} catch {
|
|
491
|
-
} finally {
|
|
492
|
-
setBusy(false);
|
|
493
|
-
}
|
|
494
|
-
}
|
|
495
|
-
return /* @__PURE__ */ jsx("div", { className: "flex min-h-screen items-center justify-center bg-sidebar p-4", children: /* @__PURE__ */ jsxs("div", { className: "w-full max-w-md rounded-2xl border border-border/50 bg-card p-8 shadow-2xl sm:p-10", children: [
|
|
496
|
-
logo && /* @__PURE__ */ jsx("div", { className: "mb-6 flex justify-center", children: logo }),
|
|
497
|
-
checking ? /* @__PURE__ */ jsx("p", { className: "py-6 text-center text-sm text-muted-foreground", children: tr("auth.setPassword.checking", "Checking your link...") }) : expired ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
498
|
-
/* @__PURE__ */ jsxs("div", { className: "mb-6", children: [
|
|
499
|
-
/* @__PURE__ */ jsx("h1", { className: "text-2xl font-bold text-foreground", children: tr("auth.setPassword.expiredTitle", "This link has expired") }),
|
|
500
|
-
/* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-muted-foreground", children: tr(
|
|
501
|
-
"auth.setPassword.expiredSubtitle",
|
|
502
|
-
"Reset links can only be used once. Enter your e-mail and we will send a new one."
|
|
503
|
-
) })
|
|
504
|
-
] }),
|
|
505
|
-
/* @__PURE__ */ jsx(
|
|
506
|
-
ForgotPasswordForm,
|
|
507
|
-
{
|
|
508
|
-
initialEmail: user?.email,
|
|
509
|
-
submitLabel: tr("auth.setPassword.sendNewLink", "Send new link"),
|
|
510
|
-
sendingLabel: tr("auth.setPassword.sending", "Sending..."),
|
|
511
|
-
sentLabel: tr("auth.setPassword.sent", "Check your inbox \u2014 a new link is on the way."),
|
|
512
|
-
emailLabel: tr("auth.setPassword.email", "E-mail"),
|
|
513
|
-
backLabel: tr("auth.setPassword.backToLogin", "Back to sign in"),
|
|
514
|
-
onBackToLogin: onSuccess
|
|
515
|
-
}
|
|
516
|
-
)
|
|
517
|
-
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
518
|
-
/* @__PURE__ */ jsxs("div", { className: "mb-6", children: [
|
|
519
|
-
/* @__PURE__ */ jsx("h1", { className: "text-2xl font-bold text-foreground", children: title }),
|
|
520
|
-
/* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-muted-foreground", children: subtitle })
|
|
521
|
-
] }),
|
|
522
|
-
/* @__PURE__ */ jsxs("form", { onSubmit: submit, className: "space-y-4", children: [
|
|
523
|
-
/* @__PURE__ */ jsxs("label", { className: "block space-y-1.5 text-sm font-medium", children: [
|
|
524
|
-
/* @__PURE__ */ jsx("span", { children: tr("auth.setPassword.newPassword", "New password") }),
|
|
525
|
-
/* @__PURE__ */ jsx(
|
|
526
|
-
"input",
|
|
527
|
-
{
|
|
528
|
-
className: fieldClass2(),
|
|
529
|
-
type: "password",
|
|
530
|
-
autoComplete: "new-password",
|
|
531
|
-
autoFocus: true,
|
|
532
|
-
required: true,
|
|
533
|
-
value: password,
|
|
534
|
-
onChange: (e) => setPassword(e.target.value),
|
|
535
|
-
disabled
|
|
536
|
-
}
|
|
537
|
-
)
|
|
538
|
-
] }),
|
|
539
|
-
/* @__PURE__ */ jsxs("label", { className: "block space-y-1.5 text-sm font-medium", children: [
|
|
540
|
-
/* @__PURE__ */ jsx("span", { children: tr("auth.setPassword.confirmPassword", "Confirm password") }),
|
|
541
|
-
/* @__PURE__ */ jsx(
|
|
542
|
-
"input",
|
|
543
|
-
{
|
|
544
|
-
className: fieldClass2(),
|
|
545
|
-
type: "password",
|
|
546
|
-
autoComplete: "new-password",
|
|
547
|
-
required: true,
|
|
548
|
-
value: confirmPassword,
|
|
549
|
-
onChange: (e) => setConfirmPassword(e.target.value),
|
|
550
|
-
disabled
|
|
551
|
-
}
|
|
552
|
-
)
|
|
553
|
-
] }),
|
|
554
|
-
(localError || error) && /* @__PURE__ */ jsx("p", { className: "text-sm text-destructive", children: localError ?? error?.message }),
|
|
555
|
-
/* @__PURE__ */ jsx("button", { className: buttonClass2(), type: "submit", disabled, children: disabled ? tr("auth.setPassword.saving", "Saving...") : tr("auth.setPassword.submit", "Save password") })
|
|
556
|
-
] }),
|
|
557
|
-
/* @__PURE__ */ jsx(
|
|
558
|
-
"button",
|
|
559
|
-
{
|
|
560
|
-
type: "button",
|
|
561
|
-
className: "mt-4 w-full text-center text-sm text-muted-foreground hover:text-foreground",
|
|
562
|
-
onClick: () => {
|
|
563
|
-
void signOut().finally(() => onSuccess?.());
|
|
564
|
-
},
|
|
565
|
-
children: tr("auth.setPassword.backToLogin", "Back to sign in")
|
|
566
|
-
}
|
|
567
|
-
)
|
|
568
|
-
] })
|
|
569
|
-
] }) });
|
|
570
|
-
}
|
|
571
|
-
var RESEND_COOLDOWN_SECONDS = 60;
|
|
572
|
-
function VerifyEmailNotice({ email, onUseAnotherEmail }) {
|
|
573
|
-
const { resendConfirmation, clearPendingVerification, error } = useAuth();
|
|
574
|
-
const [cooldown, setCooldown] = React.useState(0);
|
|
575
|
-
const [sent, setSent] = React.useState(false);
|
|
576
|
-
const [busy, setBusy] = React.useState(false);
|
|
577
|
-
const [unsupported, setUnsupported] = React.useState(false);
|
|
578
|
-
React.useEffect(() => {
|
|
579
|
-
if (cooldown <= 0) return;
|
|
580
|
-
const timer = setTimeout(() => setCooldown((s) => s - 1), 1e3);
|
|
581
|
-
return () => clearTimeout(timer);
|
|
582
|
-
}, [cooldown]);
|
|
583
|
-
const resend = async () => {
|
|
584
|
-
setBusy(true);
|
|
585
|
-
setSent(false);
|
|
586
|
-
try {
|
|
587
|
-
const ok = await resendConfirmation(email);
|
|
588
|
-
if (!ok) {
|
|
589
|
-
setUnsupported(true);
|
|
590
|
-
return;
|
|
591
|
-
}
|
|
592
|
-
setSent(true);
|
|
593
|
-
setCooldown(RESEND_COOLDOWN_SECONDS);
|
|
594
|
-
} catch {
|
|
595
|
-
} finally {
|
|
596
|
-
setBusy(false);
|
|
597
|
-
}
|
|
598
|
-
};
|
|
599
|
-
return /* @__PURE__ */ jsxs("div", { className: "space-y-6 text-center", children: [
|
|
600
|
-
/* @__PURE__ */ jsx("div", { className: "mx-auto flex h-12 w-12 items-center justify-center rounded-full bg-primary/10", children: /* @__PURE__ */ jsx(MailCheck, { className: "h-6 w-6 text-primary" }) }),
|
|
601
|
-
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
602
|
-
/* @__PURE__ */ jsx("h1", { className: "text-2xl font-bold text-foreground", children: tl("Check your email", "Verifique seu e-mail") }),
|
|
603
|
-
/* @__PURE__ */ jsxs("p", { className: "text-sm leading-relaxed text-muted-foreground", children: [
|
|
604
|
-
tl("We sent a confirmation link to", "Enviamos um link de confirma\xE7\xE3o para"),
|
|
605
|
-
" ",
|
|
606
|
-
/* @__PURE__ */ jsx("span", { className: "font-medium text-foreground", children: email }),
|
|
607
|
-
".",
|
|
608
|
-
" ",
|
|
609
|
-
tl(
|
|
610
|
-
"Open it to finish creating your account.",
|
|
611
|
-
"Abra o link para terminar de criar sua conta."
|
|
612
|
-
)
|
|
613
|
-
] }),
|
|
614
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: tl(
|
|
615
|
-
"Not there? It may have landed in spam or promotions.",
|
|
616
|
-
"N\xE3o chegou? Pode ter ca\xEDdo no spam ou em promo\xE7\xF5es."
|
|
617
|
-
) })
|
|
618
|
-
] }),
|
|
619
|
-
sent && /* @__PURE__ */ jsx("p", { className: "text-sm text-emerald-600", children: tl("Link sent again.", "Link reenviado.") }),
|
|
620
|
-
unsupported && /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: tl(
|
|
621
|
-
"Resending is not available here \u2014 try signing up again in a moment.",
|
|
622
|
-
"O reenvio n\xE3o est\xE1 dispon\xEDvel aqui \u2014 tente cadastrar de novo em instantes."
|
|
623
|
-
) }),
|
|
624
|
-
error && /* @__PURE__ */ jsx("p", { className: "text-sm text-destructive", children: error.message }),
|
|
625
|
-
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
626
|
-
/* @__PURE__ */ jsx(
|
|
627
|
-
"button",
|
|
628
|
-
{
|
|
629
|
-
type: "button",
|
|
630
|
-
onClick: () => void resend(),
|
|
631
|
-
disabled: busy || cooldown > 0,
|
|
632
|
-
className: "inline-flex h-10 w-full items-center justify-center rounded-input border border-input bg-background px-4 text-sm font-medium transition-colors hover:bg-muted disabled:pointer-events-none disabled:opacity-50",
|
|
633
|
-
children: cooldown > 0 ? tl(`Resend in ${cooldown}s`, `Reenviar em ${cooldown}s`) : busy ? tl("Sending...", "Enviando...") : tl("Resend the link", "Reenviar o link")
|
|
634
|
-
}
|
|
635
|
-
),
|
|
636
|
-
/* @__PURE__ */ jsx(
|
|
637
|
-
"button",
|
|
638
|
-
{
|
|
639
|
-
type: "button",
|
|
640
|
-
onClick: () => {
|
|
641
|
-
clearPendingVerification();
|
|
642
|
-
onUseAnotherEmail?.();
|
|
643
|
-
},
|
|
644
|
-
className: "text-sm font-medium text-primary hover:underline",
|
|
645
|
-
children: tl("Use a different email", "Usar outro e-mail")
|
|
646
|
-
}
|
|
647
|
-
)
|
|
648
|
-
] })
|
|
649
|
-
] });
|
|
650
|
-
}
|
|
651
|
-
var FLOAT_STYLES = `
|
|
652
|
-
@keyframes fayz-amb-drift {
|
|
653
|
-
0%, 100% { transform: translateY(0); }
|
|
654
|
-
50% { transform: translateY(-2px); }
|
|
655
|
-
}
|
|
656
|
-
@media (prefers-reduced-motion: reduce) {
|
|
657
|
-
.fayz-amb-avatar { animation: none !important; }
|
|
658
|
-
}
|
|
659
|
-
`;
|
|
660
|
-
function AmbassadorBubbles({ ambassadors, label }) {
|
|
661
|
-
const items = (ambassadors ?? []).filter((a) => a && typeof a.image === "string" && a.image.trim() !== "");
|
|
662
|
-
if (items.length === 0) return null;
|
|
663
|
-
const shown = items.slice(0, 5);
|
|
664
|
-
return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
665
|
-
/* @__PURE__ */ jsx("style", { children: FLOAT_STYLES }),
|
|
666
|
-
/* @__PURE__ */ jsx("div", { className: "flex -space-x-2", children: shown.map((ambassador, index) => /* @__PURE__ */ jsx(
|
|
667
|
-
"div",
|
|
668
|
-
{
|
|
669
|
-
title: ambassador.role ? `${ambassador.name} \xB7 ${ambassador.role}` : ambassador.name,
|
|
670
|
-
className: "fayz-amb-avatar relative h-10 w-10 shrink-0 overflow-hidden rounded-full border-2 border-sidebar bg-sidebar-accent shadow-md ring-1 ring-sidebar-foreground/10 transition-transform duration-200 hover:z-10 hover:scale-110",
|
|
671
|
-
style: { animation: `fayz-amb-drift 4s ease-in-out ${index * 0.4}s infinite` },
|
|
672
|
-
children: /* @__PURE__ */ jsx(
|
|
673
|
-
"img",
|
|
674
|
-
{
|
|
675
|
-
src: ambassador.image,
|
|
676
|
-
alt: ambassador.name,
|
|
677
|
-
className: "h-full w-full object-cover",
|
|
678
|
-
loading: "lazy",
|
|
679
|
-
draggable: false
|
|
680
|
-
}
|
|
681
|
-
)
|
|
682
|
-
},
|
|
683
|
-
`${ambassador.name}-${index}`
|
|
684
|
-
)) }),
|
|
685
|
-
label ? /* @__PURE__ */ jsx("p", { className: "text-xs font-medium text-sidebar-foreground/80", children: label }) : null
|
|
686
|
-
] });
|
|
687
|
-
}
|
|
688
|
-
function TrialPromise({ days }) {
|
|
689
|
-
return /* @__PURE__ */ jsxs("p", { className: "mt-3 inline-flex items-center gap-2 rounded-full border border-primary/25 bg-primary/10 px-3 py-1.5 text-[12.5px] font-medium text-primary", children: [
|
|
690
|
-
/* @__PURE__ */ jsx(Gift, { className: "h-3.5 w-3.5 shrink-0", "aria-hidden": true }),
|
|
691
|
-
/* @__PURE__ */ jsxs("span", { children: [
|
|
692
|
-
tl(`${days} days free`, `${days} dias gr\xE1tis`),
|
|
693
|
-
/* @__PURE__ */ jsx("span", { className: "font-normal", children: tl(" \xB7 no credit card", " \xB7 sem cart\xE3o de cr\xE9dito") })
|
|
694
|
-
] })
|
|
695
|
-
] });
|
|
696
|
-
}
|
|
697
|
-
function initialViewFromLocation() {
|
|
698
|
-
if (typeof window === "undefined") return "login";
|
|
699
|
-
return /^#\/?signup\/?$/i.test(window.location.hash) ? "signup" : "login";
|
|
700
|
-
}
|
|
701
|
-
function LoginPage({
|
|
702
|
-
appName = "App",
|
|
703
|
-
logo,
|
|
704
|
-
loginLogo,
|
|
705
|
-
layout = "split",
|
|
706
|
-
tagline,
|
|
707
|
-
description,
|
|
708
|
-
loginAmbassadors,
|
|
709
|
-
loginAmbassadorsLabel,
|
|
710
|
-
showOAuth,
|
|
711
|
-
oauthProviders,
|
|
712
|
-
oauthComingSoon,
|
|
713
|
-
resetPasswordUrl,
|
|
714
|
-
trialDays,
|
|
715
|
-
termsUrl,
|
|
716
|
-
privacyUrl,
|
|
717
|
-
onSuccess
|
|
718
|
-
}) {
|
|
719
|
-
const [view, setView] = React.useState(initialViewFromLocation);
|
|
720
|
-
React.useEffect(() => {
|
|
721
|
-
if (/^#\/?signup\/?$/i.test(window.location.hash)) {
|
|
722
|
-
window.history.replaceState(null, "", window.location.pathname + window.location.search);
|
|
723
|
-
}
|
|
724
|
-
}, []);
|
|
725
|
-
const [email, setEmail] = React.useState("");
|
|
726
|
-
const pendingVerification = useAuth().pendingVerification;
|
|
727
|
-
const brandLogo = loginLogo ?? logo;
|
|
728
|
-
const heading = view === "login" ? tl("Welcome back", "Bem-vindo de volta") : view === "signup" ? tl("Create account", "Criar conta") : tl("Reset password", "Redefinir senha");
|
|
729
|
-
const subtitle = view === "login" ? tl("Enter your credentials to continue", "Entre com seus dados para continuar") : view === "signup" ? tl("Create your account to get started", "Crie sua conta para come\xE7ar") : tl(
|
|
730
|
-
"Enter your email and we will send reset instructions",
|
|
731
|
-
"Informe seu e-mail e enviaremos as instru\xE7\xF5es"
|
|
732
|
-
);
|
|
733
|
-
const form = view === "login" ? /* @__PURE__ */ jsx(
|
|
734
|
-
LoginForm,
|
|
735
|
-
{
|
|
736
|
-
onSuccess,
|
|
737
|
-
onForgotPassword: () => setView("recovery"),
|
|
738
|
-
showOAuth,
|
|
739
|
-
oauthProviders,
|
|
740
|
-
oauthComingSoon,
|
|
741
|
-
initialEmail: email,
|
|
742
|
-
onEmailChange: setEmail
|
|
743
|
-
}
|
|
744
|
-
) : view === "signup" ? /* @__PURE__ */ jsx(
|
|
745
|
-
SignupForm,
|
|
746
|
-
{
|
|
747
|
-
onSuccess,
|
|
748
|
-
showOAuth,
|
|
749
|
-
oauthProviders,
|
|
750
|
-
oauthComingSoon,
|
|
751
|
-
termsUrl,
|
|
752
|
-
privacyUrl
|
|
753
|
-
}
|
|
754
|
-
) : /* @__PURE__ */ jsx(
|
|
755
|
-
ForgotPasswordForm,
|
|
756
|
-
{
|
|
757
|
-
redirectTo: resetPasswordUrl,
|
|
758
|
-
onBackToLogin: () => setView("login"),
|
|
759
|
-
initialEmail: email,
|
|
760
|
-
onEmailChange: setEmail
|
|
761
|
-
}
|
|
762
|
-
);
|
|
763
|
-
const switcher = view === "login" ? /* @__PURE__ */ jsxs("p", { className: "text-center text-sm text-muted-foreground", children: [
|
|
764
|
-
tl("Do not have an account?", "Ainda n\xE3o tem conta?"),
|
|
765
|
-
" ",
|
|
766
|
-
/* @__PURE__ */ jsx("button", { type: "button", className: "font-medium text-primary hover:underline", onClick: () => setView("signup"), children: tl("Sign up", "Cadastre-se") })
|
|
767
|
-
] }) : /* @__PURE__ */ jsxs("p", { className: "text-center text-sm text-muted-foreground", children: [
|
|
768
|
-
view === "signup" ? tl("Already have an account?", "J\xE1 tem uma conta?") : tl("Remembered your password?", "Lembrou a senha?"),
|
|
769
|
-
" ",
|
|
770
|
-
/* @__PURE__ */ jsx("button", { type: "button", className: "font-medium text-primary hover:underline", onClick: () => setView("login"), children: tl("Sign in", "Entrar") })
|
|
771
|
-
] });
|
|
772
|
-
const panel = pendingVerification ? /* @__PURE__ */ jsx(
|
|
773
|
-
VerifyEmailNotice,
|
|
774
|
-
{
|
|
775
|
-
email: pendingVerification.email,
|
|
776
|
-
onUseAnotherEmail: () => setView("signup")
|
|
777
|
-
}
|
|
778
|
-
) : null;
|
|
779
|
-
if (layout === "centered") {
|
|
780
|
-
return /* @__PURE__ */ jsx("div", { className: "flex min-h-screen items-center justify-center bg-sidebar p-4", children: /* @__PURE__ */ jsx("div", { className: "w-full max-w-md rounded-2xl border border-border/50 bg-card p-8 shadow-2xl sm:p-10", children: panel ?? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
781
|
-
/* @__PURE__ */ jsxs("div", { className: "mb-8 text-center", children: [
|
|
782
|
-
brandLogo && /* @__PURE__ */ jsx("div", { className: "mb-4 flex justify-center", children: brandLogo }),
|
|
783
|
-
/* @__PURE__ */ jsx("h1", { className: "text-2xl font-bold text-foreground", children: heading }),
|
|
784
|
-
/* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-muted-foreground", children: subtitle }),
|
|
785
|
-
view === "signup" && trialDays ? /* @__PURE__ */ jsx(TrialPromise, { days: trialDays }) : null
|
|
786
|
-
] }),
|
|
787
|
-
/* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
|
|
788
|
-
form,
|
|
789
|
-
switcher
|
|
790
|
-
] })
|
|
791
|
-
] }) }) });
|
|
792
|
-
}
|
|
793
|
-
return /* @__PURE__ */ jsxs("div", { className: "flex min-h-screen bg-sidebar", children: [
|
|
794
|
-
/* @__PURE__ */ jsxs("div", { className: "relative hidden w-1/2 overflow-hidden lg:block", children: [
|
|
795
|
-
/* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-gradient-to-br from-sidebar-accent/50 via-transparent to-sidebar/80" }),
|
|
796
|
-
/* @__PURE__ */ jsx("div", { className: "relative z-20 flex h-full flex-col justify-end p-12", children: /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
797
|
-
/* @__PURE__ */ jsx(AmbassadorBubbles, { ambassadors: loginAmbassadors, label: loginAmbassadorsLabel }),
|
|
798
|
-
/* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-sidebar-muted", children: appName }),
|
|
799
|
-
/* @__PURE__ */ jsx("h2", { className: "text-3xl font-bold text-sidebar-foreground", children: tagline ?? `Welcome to ${appName}` }),
|
|
800
|
-
description && /* @__PURE__ */ jsx("p", { className: "max-w-md text-sm leading-relaxed text-sidebar-muted", children: description })
|
|
801
|
-
] }) })
|
|
802
|
-
] }),
|
|
803
|
-
/* @__PURE__ */ jsx("div", { className: "flex flex-1 flex-col lg:p-3 lg:pl-3", children: /* @__PURE__ */ jsx("div", { className: "flex flex-1 flex-col justify-center bg-background px-6 py-12 lg:rounded-[1.25rem] lg:px-16", children: /* @__PURE__ */ jsxs("div", { className: "mx-auto w-full max-w-sm", children: [
|
|
804
|
-
brandLogo && /* @__PURE__ */ jsx("div", { className: "mb-8", children: brandLogo }),
|
|
805
|
-
panel ?? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
806
|
-
/* @__PURE__ */ jsxs("div", { className: "mb-8", children: [
|
|
807
|
-
/* @__PURE__ */ jsx("h1", { className: "text-2xl font-bold text-foreground", children: heading }),
|
|
808
|
-
/* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-muted-foreground", children: subtitle }),
|
|
809
|
-
view === "signup" && trialDays ? /* @__PURE__ */ jsx(TrialPromise, { days: trialDays }) : null
|
|
810
|
-
] }),
|
|
811
|
-
/* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
|
|
812
|
-
form,
|
|
813
|
-
switcher
|
|
814
|
-
] })
|
|
815
|
-
] })
|
|
816
|
-
] }) }) })
|
|
817
|
-
] });
|
|
818
|
-
}
|
|
819
|
-
function AuthGate({ requireAuth = true, loadingFallback, children, ...loginProps }) {
|
|
820
|
-
const { isAuthenticated, isLoading } = useAuth();
|
|
821
|
-
if (!requireAuth || isAuthenticated) return /* @__PURE__ */ jsx(Fragment, { children });
|
|
822
|
-
if (isLoading) {
|
|
823
|
-
return /* @__PURE__ */ jsx(Fragment, { children: loadingFallback ?? /* @__PURE__ */ jsx("div", { className: "flex min-h-screen items-center justify-center bg-background", children: /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: "Loading..." }) }) });
|
|
824
|
-
}
|
|
825
|
-
return /* @__PURE__ */ jsx(LoginPage, { ...loginProps });
|
|
826
|
-
}
|
|
827
|
-
function AuthCallbackPage({ onSuccess, onError }) {
|
|
828
|
-
const { handleCallback } = useAuth();
|
|
829
|
-
const [error, setError] = React.useState(null);
|
|
830
|
-
React.useEffect(() => {
|
|
831
|
-
let cancelled = false;
|
|
832
|
-
handleCallback(typeof window === "undefined" ? void 0 : window.location.href).then(() => {
|
|
833
|
-
if (!cancelled) onSuccess?.();
|
|
834
|
-
}).catch((err) => {
|
|
835
|
-
const errorObject = err instanceof Error ? err : new Error(String(err));
|
|
836
|
-
if (!cancelled) {
|
|
837
|
-
setError(errorObject.message);
|
|
838
|
-
onError?.(errorObject);
|
|
839
|
-
}
|
|
840
|
-
});
|
|
841
|
-
return () => {
|
|
842
|
-
cancelled = true;
|
|
843
|
-
};
|
|
844
|
-
}, [handleCallback, onError, onSuccess]);
|
|
845
|
-
return /* @__PURE__ */ jsx("div", { className: "flex min-h-screen items-center justify-center bg-background p-6 text-center", children: /* @__PURE__ */ jsxs("div", { children: [
|
|
846
|
-
/* @__PURE__ */ jsx("h1", { className: "text-xl font-semibold text-foreground", children: error ? "Authentication failed" : "Completing sign in..." }),
|
|
847
|
-
error && /* @__PURE__ */ jsx("p", { className: "mt-2 text-sm text-destructive", children: error })
|
|
848
|
-
] }) });
|
|
849
|
-
}
|
|
850
|
-
function ResetPasswordPage({ onSuccess }) {
|
|
851
|
-
return /* @__PURE__ */ jsx(SetPasswordPage, { reason: "recovery", onSuccess });
|
|
852
|
-
}
|
|
853
|
-
|
|
854
|
-
export { AmbassadorBubbles, AuthCallbackPage, AuthGate, ForgotPasswordForm, LoginForm, LoginPage, OAuthButtons, ResetPasswordForm, ResetPasswordPage, SetPasswordPage, SignupForm, VerifyEmailNotice, createAuthPlugin, createAuthRuntime, resolveAuthAdapter, usePasswordSetupGate };
|
|
855
16
|
//# sourceMappingURL=index.js.map
|
|
856
17
|
//# sourceMappingURL=index.js.map
|