@fayz-ai/plugin-auth 0.9.0-next.0 → 0.9.0-next.1

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/forms.d.ts CHANGED
@@ -11,8 +11,12 @@ export interface LoginFormProps {
11
11
  onForgotPassword?: () => void;
12
12
  showOAuth?: boolean;
13
13
  oauthProviders?: Exclude<AuthProvider, 'email'>[];
14
+ /** Seeds the field, so switching between login and recovery never asks for the
15
+ * e-mail the user already typed. */
16
+ initialEmail?: string;
17
+ onEmailChange?: (email: string) => void;
14
18
  }
15
- export declare function LoginForm({ onSuccess, onForgotPassword, showOAuth, oauthProviders }: LoginFormProps): React.JSX.Element;
19
+ export declare function LoginForm({ onSuccess, onForgotPassword, showOAuth, oauthProviders, initialEmail, onEmailChange, }: LoginFormProps): React.JSX.Element;
16
20
  export interface SignupFormProps {
17
21
  onSuccess?: () => void;
18
22
  }
@@ -21,8 +25,18 @@ export interface ForgotPasswordFormProps {
21
25
  redirectTo?: string;
22
26
  onSent?: (email: string) => void;
23
27
  onBackToLogin?: () => void;
28
+ /** Pre-filled with whatever the user already typed on the login form. */
29
+ initialEmail?: string;
30
+ onEmailChange?: (email: string) => void;
31
+ /** Copy overrides — the set-password screen reuses this form to hand out a
32
+ * fresh link, where "Send reset link" is the wrong label. */
33
+ emailLabel?: string;
34
+ submitLabel?: string;
35
+ sendingLabel?: string;
36
+ sentLabel?: string;
37
+ backLabel?: string;
24
38
  }
25
- export declare function ForgotPasswordForm({ redirectTo, onSent, onBackToLogin }: ForgotPasswordFormProps): React.JSX.Element;
39
+ export declare function ForgotPasswordForm({ redirectTo, onSent, onBackToLogin, initialEmail, onEmailChange, emailLabel, submitLabel, sendingLabel, sentLabel, backLabel, }: ForgotPasswordFormProps): React.JSX.Element;
26
40
  export interface ResetPasswordFormProps {
27
41
  onSuccess?: () => void;
28
42
  }
@@ -1 +1 @@
1
- {"version":3,"file":"forms.d.ts","sourceRoot":"","sources":["../src/forms.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAkBjD,MAAM,WAAW,iBAAiB;IAChC,SAAS,CAAC,EAAE,OAAO,CAAC,YAAY,EAAE,OAAO,CAAC,EAAE,CAAA;IAC5C,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,eAAe,CAAC,EAAE,CAAC,QAAQ,EAAE,YAAY,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CACnE;AAED,wBAAgB,YAAY,CAAC,EAAE,SAAsB,EAAE,QAAQ,EAAE,eAAe,EAAE,EAAE,iBAAiB,qBAmBpG;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;IACtB,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAA;IAC7B,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,cAAc,CAAC,EAAE,OAAO,CAAC,YAAY,EAAE,OAAO,CAAC,EAAE,CAAA;CAClD;AAED,wBAAgB,SAAS,CAAC,EAAE,SAAS,EAAE,gBAAgB,EAAE,SAAS,EAAE,cAAc,EAAE,EAAE,cAAc,qBA0CnG;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;CACvB;AAED,wBAAgB,UAAU,CAAC,EAAE,SAAS,EAAE,EAAE,eAAe,qBAsDxD;AAED,MAAM,WAAW,uBAAuB;IACtC,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAChC,aAAa,CAAC,EAAE,MAAM,IAAI,CAAA;CAC3B;AAED,wBAAgB,kBAAkB,CAAC,EAAE,UAAU,EAAE,MAAM,EAAE,aAAa,EAAE,EAAE,uBAAuB,qBAqChG;AAED,MAAM,WAAW,sBAAsB;IACrC,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;CACvB;AAED,wBAAgB,iBAAiB,CAAC,EAAE,SAAS,EAAE,EAAE,sBAAsB,qBA4CtE"}
1
+ {"version":3,"file":"forms.d.ts","sourceRoot":"","sources":["../src/forms.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAkBjD,MAAM,WAAW,iBAAiB;IAChC,SAAS,CAAC,EAAE,OAAO,CAAC,YAAY,EAAE,OAAO,CAAC,EAAE,CAAA;IAC5C,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,eAAe,CAAC,EAAE,CAAC,QAAQ,EAAE,YAAY,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CACnE;AAED,wBAAgB,YAAY,CAAC,EAAE,SAAsB,EAAE,QAAQ,EAAE,eAAe,EAAE,EAAE,iBAAiB,qBAmBpG;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;IACtB,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAA;IAC7B,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,cAAc,CAAC,EAAE,OAAO,CAAC,YAAY,EAAE,OAAO,CAAC,EAAE,CAAA;IACjD;yCACqC;IACrC,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;CACxC;AAED,wBAAgB,SAAS,CAAC,EACxB,SAAS,EACT,gBAAgB,EAChB,SAAS,EACT,cAAc,EACd,YAAiB,EACjB,aAAa,GACd,EAAE,cAAc,qBAqDhB;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;CACvB;AAED,wBAAgB,UAAU,CAAC,EAAE,SAAS,EAAE,EAAE,eAAe,qBAsDxD;AAED,MAAM,WAAW,uBAAuB;IACtC,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAChC,aAAa,CAAC,EAAE,MAAM,IAAI,CAAA;IAC1B,yEAAyE;IACzE,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACvC;kEAC8D;IAC9D,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,wBAAgB,kBAAkB,CAAC,EACjC,UAAU,EACV,MAAM,EACN,aAAa,EACb,YAAiB,EACjB,aAAa,EACb,UAAoB,EACpB,WAA+B,EAC/B,YAA2B,EAC3B,SAA+C,EAC/C,SAA2B,GAC5B,EAAE,uBAAuB,qBAiDzB;AAED,MAAM,WAAW,sBAAsB;IACrC,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;CACvB;AAED,wBAAgB,iBAAiB,CAAC,EAAE,SAAS,EAAE,EAAE,sBAAsB,qBA4CtE"}
package/dist/index.d.ts CHANGED
@@ -1,11 +1,13 @@
1
1
  export { createAuthPlugin, createAuthRuntime, resolveAuthAdapter, } from './runtime';
2
2
  export { AuthGate, LoginPage, AuthCallbackPage, ResetPasswordPage, } from './pages';
3
3
  export type { AuthCallbackPageProps, AuthGateProps, LoginPageProps, ResetPasswordPageProps, } from './pages';
4
+ export { SetPasswordPage, usePasswordSetupGate } from './set-password';
5
+ export type { SetPasswordPageProps, SetPasswordReason, PasswordSetupGate } from './set-password';
4
6
  export { AmbassadorBubbles } from './AmbassadorBubbles';
5
7
  export type { AmbassadorBubblesProps } from './AmbassadorBubbles';
6
8
  export { LoginForm, SignupForm, ForgotPasswordForm, ResetPasswordForm, OAuthButtons, } from './forms';
7
9
  export type { ForgotPasswordFormProps, LoginFormProps, OAuthButtonsProps, ResetPasswordFormProps, SignupFormProps, } from './forms';
8
- export { createMockAuthAdapter, createSupabaseAuthAdapter, AuthProvider, useAuth, useAuthStore, } from '@fayz-ai/auth';
10
+ export { createMockAuthAdapter, createSupabaseAuthAdapter, AuthProvider, useAuth, useAuthStore, readAuthUrlIntent, clearAuthUrlTokens, } from '@fayz-ai/auth';
9
11
  export type { AuthPluginOptions, ResolvedAuthPlugin, AuthRoutesConfig, AuthOAuthConfig, AuthSupabaseConfig, AuthProviderKey, AuthLayout, AuthFormView, LoginAmbassador, } from './types';
10
12
  export type { AuthAdapter, AuthSession, AuthUser, AuthProvider as OAuthProvider } from '@fayz-ai/core';
11
13
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,WAAW,CAAA;AAClB,OAAO,EACL,QAAQ,EACR,SAAS,EACT,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,SAAS,CAAA;AAChB,YAAY,EACV,qBAAqB,EACrB,aAAa,EACb,cAAc,EACd,sBAAsB,GACvB,MAAM,SAAS,CAAA;AAChB,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AACvD,YAAY,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAA;AACjE,OAAO,EACL,SAAS,EACT,UAAU,EACV,kBAAkB,EAClB,iBAAiB,EACjB,YAAY,GACb,MAAM,SAAS,CAAA;AAChB,YAAY,EACV,uBAAuB,EACvB,cAAc,EACd,iBAAiB,EACjB,sBAAsB,EACtB,eAAe,GAChB,MAAM,SAAS,CAAA;AAChB,OAAO,EACL,qBAAqB,EACrB,yBAAyB,EACzB,YAAY,EACZ,OAAO,EACP,YAAY,GACb,MAAM,eAAe,CAAA;AACtB,YAAY,EACV,iBAAiB,EACjB,kBAAkB,EAClB,gBAAgB,EAChB,eAAe,EACf,kBAAkB,EAClB,eAAe,EACf,UAAU,EACV,YAAY,EACZ,eAAe,GAChB,MAAM,SAAS,CAAA;AAChB,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,QAAQ,EAAE,YAAY,IAAI,aAAa,EAAE,MAAM,eAAe,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,WAAW,CAAA;AAClB,OAAO,EACL,QAAQ,EACR,SAAS,EACT,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,SAAS,CAAA;AAChB,YAAY,EACV,qBAAqB,EACrB,aAAa,EACb,cAAc,EACd,sBAAsB,GACvB,MAAM,SAAS,CAAA;AAChB,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAA;AACtE,YAAY,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AAChG,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AACvD,YAAY,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAA;AACjE,OAAO,EACL,SAAS,EACT,UAAU,EACV,kBAAkB,EAClB,iBAAiB,EACjB,YAAY,GACb,MAAM,SAAS,CAAA;AAChB,YAAY,EACV,uBAAuB,EACvB,cAAc,EACd,iBAAiB,EACjB,sBAAsB,EACtB,eAAe,GAChB,MAAM,SAAS,CAAA;AAChB,OAAO,EACL,qBAAqB,EACrB,yBAAyB,EACzB,YAAY,EACZ,OAAO,EACP,YAAY,EACZ,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,eAAe,CAAA;AACtB,YAAY,EACV,iBAAiB,EACjB,kBAAkB,EAClB,gBAAgB,EAChB,eAAe,EACf,kBAAkB,EAClB,eAAe,EACf,UAAU,EACV,YAAY,EACZ,eAAe,GAChB,MAAM,SAAS,CAAA;AAChB,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,QAAQ,EAAE,YAAY,IAAI,aAAa,EAAE,MAAM,eAAe,CAAA"}
package/dist/index.js CHANGED
@@ -1,7 +1,8 @@
1
- import { createSupabaseAuthAdapter, createMockAuthAdapter, useAuth } from '@fayz-ai/auth';
2
- export { AuthProvider, createMockAuthAdapter, createSupabaseAuthAdapter, useAuth, useAuthStore } from '@fayz-ai/auth';
1
+ import { createSupabaseAuthAdapter, createMockAuthAdapter, useAuth, readAuthUrlIntent, clearAuthUrlTokens, decidePasswordSetup } from '@fayz-ai/auth';
2
+ export { AuthProvider, clearAuthUrlTokens, createMockAuthAdapter, createSupabaseAuthAdapter, readAuthUrlIntent, useAuth, useAuthStore } from '@fayz-ai/auth';
3
3
  import * as React from 'react';
4
4
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
5
+ import { useTranslation } from '@fayz-ai/core';
5
6
 
6
7
  // src/runtime.ts
7
8
  function absoluteUrl(path) {
@@ -24,7 +25,10 @@ function resolveAuthAdapter(options = {}) {
24
25
  supabaseAnonKey: anonKey,
25
26
  supabaseClient: options.supabase?.client,
26
27
  callbackUrl: options.supabase?.callbackUrl ?? absoluteUrl(options.routes?.callback ?? "/auth/callback"),
27
- resetPasswordUrl: options.supabase?.resetPasswordUrl ?? absoluteUrl(options.routes?.resetPassword ?? "/auth/reset-password")
28
+ // Only when the host asked for a specific URL. Left undefined, the adapter
29
+ // points recovery at the app root, which needs no route and no extra entry
30
+ // in Supabase's redirect allow-list.
31
+ resetPasswordUrl: options.supabase?.resetPasswordUrl ?? (options.routes?.resetPassword ? absoluteUrl(options.routes.resetPassword) : void 0)
28
32
  });
29
33
  }
30
34
  return createMockAuthAdapter();
@@ -47,7 +51,9 @@ function createAuthRuntime(options = {}) {
47
51
  routes: {
48
52
  login: options.routes?.login ?? "/login",
49
53
  callback: options.routes?.callback ?? "/auth/callback",
50
- resetPassword: options.routes?.resetPassword ?? "/auth/reset-password",
54
+ // The app root — recovery links are recognised by their own params, not by
55
+ // the path they land on. See resetPassword() in the Supabase adapter.
56
+ resetPassword: options.routes?.resetPassword ?? "/",
51
57
  afterSignIn: options.routes?.afterSignIn ?? "/"
52
58
  }
53
59
  };
@@ -87,9 +93,16 @@ function OAuthButtons({ providers = ["google"], disabled, onProviderClick }) {
87
93
  provider
88
94
  )) });
89
95
  }
90
- function LoginForm({ onSuccess, onForgotPassword, showOAuth, oauthProviders }) {
96
+ function LoginForm({
97
+ onSuccess,
98
+ onForgotPassword,
99
+ showOAuth,
100
+ oauthProviders,
101
+ initialEmail = "",
102
+ onEmailChange
103
+ }) {
91
104
  const { signIn, error, isLoading } = useAuth();
92
- const [email, setEmail] = React.useState("");
105
+ const [email, setEmail] = React.useState(initialEmail);
93
106
  const [password, setPassword] = React.useState("");
94
107
  const [busy, setBusy] = React.useState(false);
95
108
  const disabled = busy || isLoading;
@@ -106,7 +119,21 @@ function LoginForm({ onSuccess, onForgotPassword, showOAuth, oauthProviders }) {
106
119
  return /* @__PURE__ */ jsxs("form", { onSubmit: submit, className: "space-y-4", children: [
107
120
  /* @__PURE__ */ jsxs("label", { className: "block space-y-1.5 text-sm font-medium", children: [
108
121
  /* @__PURE__ */ jsx("span", { children: "Email" }),
109
- /* @__PURE__ */ jsx("input", { className: fieldClass(), type: "email", autoComplete: "username", required: true, value: email, onChange: (e) => setEmail(e.target.value), disabled })
122
+ /* @__PURE__ */ jsx(
123
+ "input",
124
+ {
125
+ className: fieldClass(),
126
+ type: "email",
127
+ autoComplete: "username",
128
+ required: true,
129
+ value: email,
130
+ onChange: (e) => {
131
+ setEmail(e.target.value);
132
+ onEmailChange?.(e.target.value);
133
+ },
134
+ disabled
135
+ }
136
+ )
110
137
  ] }),
111
138
  /* @__PURE__ */ jsxs("label", { className: "block space-y-1.5 text-sm font-medium", children: [
112
139
  /* @__PURE__ */ jsx("span", { children: "Password" }),
@@ -167,9 +194,20 @@ function SignupForm({ onSuccess }) {
167
194
  /* @__PURE__ */ jsx("button", { className: buttonClass(), type: "submit", disabled, children: disabled ? "Creating account..." : "Create account" })
168
195
  ] });
169
196
  }
170
- function ForgotPasswordForm({ redirectTo, onSent, onBackToLogin }) {
197
+ function ForgotPasswordForm({
198
+ redirectTo,
199
+ onSent,
200
+ onBackToLogin,
201
+ initialEmail = "",
202
+ onEmailChange,
203
+ emailLabel = "Email",
204
+ submitLabel = "Send reset link",
205
+ sendingLabel = "Sending...",
206
+ sentLabel = "Password reset instructions sent.",
207
+ backLabel = "Back to login"
208
+ }) {
171
209
  const { resetPassword, error, isLoading } = useAuth();
172
- const [email, setEmail] = React.useState("");
210
+ const [email, setEmail] = React.useState(initialEmail);
173
211
  const [sent, setSent] = React.useState(false);
174
212
  const [busy, setBusy] = React.useState(false);
175
213
  const disabled = busy || isLoading;
@@ -186,13 +224,28 @@ function ForgotPasswordForm({ redirectTo, onSent, onBackToLogin }) {
186
224
  }
187
225
  return /* @__PURE__ */ jsxs("form", { onSubmit: submit, className: "space-y-4", children: [
188
226
  /* @__PURE__ */ jsxs("label", { className: "block space-y-1.5 text-sm font-medium", children: [
189
- /* @__PURE__ */ jsx("span", { children: "Email" }),
190
- /* @__PURE__ */ jsx("input", { className: fieldClass(), type: "email", autoComplete: "username", required: true, value: email, onChange: (e) => setEmail(e.target.value), disabled })
227
+ /* @__PURE__ */ jsx("span", { children: emailLabel }),
228
+ /* @__PURE__ */ jsx(
229
+ "input",
230
+ {
231
+ className: fieldClass(),
232
+ type: "email",
233
+ autoComplete: "username",
234
+ required: true,
235
+ autoFocus: !email,
236
+ value: email,
237
+ onChange: (e) => {
238
+ setEmail(e.target.value);
239
+ onEmailChange?.(e.target.value);
240
+ },
241
+ disabled
242
+ }
243
+ )
191
244
  ] }),
192
245
  error && /* @__PURE__ */ jsx("p", { className: "text-sm text-destructive", children: error.message }),
193
- sent && /* @__PURE__ */ jsx("p", { className: "text-sm text-emerald-600", children: "Password reset instructions sent." }),
194
- /* @__PURE__ */ jsx("button", { className: buttonClass(), type: "submit", disabled, children: disabled ? "Sending..." : "Send reset link" }),
195
- onBackToLogin && /* @__PURE__ */ jsx("button", { type: "button", className: buttonClass("ghost"), onClick: onBackToLogin, children: "Back to login" })
246
+ sent && /* @__PURE__ */ jsx("p", { className: "text-sm text-emerald-600", children: sentLabel }),
247
+ /* @__PURE__ */ jsx("button", { className: buttonClass(), type: "submit", disabled, children: disabled ? sendingLabel : submitLabel }),
248
+ onBackToLogin && /* @__PURE__ */ jsx("button", { type: "button", className: buttonClass("ghost"), onClick: onBackToLogin, children: backLabel })
196
249
  ] });
197
250
  }
198
251
  function ResetPasswordForm({ onSuccess }) {
@@ -234,6 +287,154 @@ function ResetPasswordForm({ onSuccess }) {
234
287
  /* @__PURE__ */ jsx("button", { className: buttonClass(), type: "submit", disabled, children: disabled ? "Saving..." : "Update password" })
235
288
  ] });
236
289
  }
290
+ var MIN_LENGTH = 8;
291
+ function fieldClass2() {
292
+ return "h-10 w-full rounded-md 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";
293
+ }
294
+ function buttonClass2() {
295
+ 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";
296
+ }
297
+ function useTr() {
298
+ const t = useTranslation();
299
+ return React.useCallback(
300
+ (key, fallback, params) => {
301
+ const value = t(key, params);
302
+ return !value || value === key ? fallback : value;
303
+ },
304
+ [t]
305
+ );
306
+ }
307
+ function usePasswordSetupGate() {
308
+ const { user, isLoading, isAuthenticated } = useAuth();
309
+ const [done, setDone] = React.useState(false);
310
+ const intent = React.useMemo(() => readAuthUrlIntent(), []);
311
+ const complete = React.useCallback(() => {
312
+ clearAuthUrlTokens();
313
+ setDone(true);
314
+ }, []);
315
+ if (done) return { reason: null, expired: false, checking: false, complete };
316
+ const decision = decidePasswordSetup({
317
+ intent,
318
+ isLoading,
319
+ isAuthenticated,
320
+ mustSetPassword: user?.mustSetPassword
321
+ });
322
+ return { ...decision, complete };
323
+ }
324
+ function SetPasswordPage({
325
+ reason,
326
+ appName = "App",
327
+ logo,
328
+ expired,
329
+ checking,
330
+ onSuccess
331
+ }) {
332
+ const tr = useTr();
333
+ const { user, updatePassword, signOut, error, isLoading } = useAuth();
334
+ const [password, setPassword] = React.useState("");
335
+ const [confirmPassword, setConfirmPassword] = React.useState("");
336
+ const [localError, setLocalError] = React.useState(null);
337
+ const [busy, setBusy] = React.useState(false);
338
+ const disabled = busy || isLoading;
339
+ const invite = reason === "invite";
340
+ const title = invite ? tr("auth.setPassword.welcomeTitle", `Welcome to ${appName}`, { appName }) : tr("auth.setPassword.recoveryTitle", "Choose a new password");
341
+ 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.");
342
+ async function submit(event) {
343
+ event.preventDefault();
344
+ setLocalError(null);
345
+ if (password.length < MIN_LENGTH) {
346
+ setLocalError(tr("auth.setPassword.tooShort", `Password must be at least ${MIN_LENGTH} characters.`));
347
+ return;
348
+ }
349
+ if (password !== confirmPassword) {
350
+ setLocalError(tr("auth.setPassword.mismatch", "Passwords do not match."));
351
+ return;
352
+ }
353
+ setBusy(true);
354
+ try {
355
+ await updatePassword(password);
356
+ onSuccess?.();
357
+ } catch {
358
+ } finally {
359
+ setBusy(false);
360
+ }
361
+ }
362
+ 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: [
363
+ logo && /* @__PURE__ */ jsx("div", { className: "mb-6 flex justify-center", children: logo }),
364
+ 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: [
365
+ /* @__PURE__ */ jsxs("div", { className: "mb-6", children: [
366
+ /* @__PURE__ */ jsx("h1", { className: "text-2xl font-bold text-foreground", children: tr("auth.setPassword.expiredTitle", "This link has expired") }),
367
+ /* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-muted-foreground", children: tr(
368
+ "auth.setPassword.expiredSubtitle",
369
+ "Reset links can only be used once. Enter your e-mail and we will send a new one."
370
+ ) })
371
+ ] }),
372
+ /* @__PURE__ */ jsx(
373
+ ForgotPasswordForm,
374
+ {
375
+ initialEmail: user?.email,
376
+ submitLabel: tr("auth.setPassword.sendNewLink", "Send new link"),
377
+ sendingLabel: tr("auth.setPassword.sending", "Sending..."),
378
+ sentLabel: tr("auth.setPassword.sent", "Check your inbox \u2014 a new link is on the way."),
379
+ emailLabel: tr("auth.setPassword.email", "E-mail"),
380
+ backLabel: tr("auth.setPassword.backToLogin", "Back to sign in"),
381
+ onBackToLogin: onSuccess
382
+ }
383
+ )
384
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
385
+ /* @__PURE__ */ jsxs("div", { className: "mb-6", children: [
386
+ /* @__PURE__ */ jsx("h1", { className: "text-2xl font-bold text-foreground", children: title }),
387
+ /* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-muted-foreground", children: subtitle })
388
+ ] }),
389
+ /* @__PURE__ */ jsxs("form", { onSubmit: submit, className: "space-y-4", children: [
390
+ /* @__PURE__ */ jsxs("label", { className: "block space-y-1.5 text-sm font-medium", children: [
391
+ /* @__PURE__ */ jsx("span", { children: tr("auth.setPassword.newPassword", "New password") }),
392
+ /* @__PURE__ */ jsx(
393
+ "input",
394
+ {
395
+ className: fieldClass2(),
396
+ type: "password",
397
+ autoComplete: "new-password",
398
+ autoFocus: true,
399
+ required: true,
400
+ value: password,
401
+ onChange: (e) => setPassword(e.target.value),
402
+ disabled
403
+ }
404
+ )
405
+ ] }),
406
+ /* @__PURE__ */ jsxs("label", { className: "block space-y-1.5 text-sm font-medium", children: [
407
+ /* @__PURE__ */ jsx("span", { children: tr("auth.setPassword.confirmPassword", "Confirm password") }),
408
+ /* @__PURE__ */ jsx(
409
+ "input",
410
+ {
411
+ className: fieldClass2(),
412
+ type: "password",
413
+ autoComplete: "new-password",
414
+ required: true,
415
+ value: confirmPassword,
416
+ onChange: (e) => setConfirmPassword(e.target.value),
417
+ disabled
418
+ }
419
+ )
420
+ ] }),
421
+ (localError || error) && /* @__PURE__ */ jsx("p", { className: "text-sm text-destructive", children: localError ?? error?.message }),
422
+ /* @__PURE__ */ jsx("button", { className: buttonClass2(), type: "submit", disabled, children: disabled ? tr("auth.setPassword.saving", "Saving...") : tr("auth.setPassword.submit", "Save password") })
423
+ ] }),
424
+ /* @__PURE__ */ jsx(
425
+ "button",
426
+ {
427
+ type: "button",
428
+ className: "mt-4 w-full text-center text-sm text-muted-foreground hover:text-foreground",
429
+ onClick: () => {
430
+ void signOut().finally(() => onSuccess?.());
431
+ },
432
+ children: tr("auth.setPassword.backToLogin", "Back to sign in")
433
+ }
434
+ )
435
+ ] })
436
+ ] }) });
437
+ }
237
438
  var FLOAT_STYLES = `
238
439
  @keyframes fayz-amb-drift {
239
440
  0%, 100% { transform: translateY(0); }
@@ -286,6 +487,7 @@ function LoginPage({
286
487
  onSuccess
287
488
  }) {
288
489
  const [view, setView] = React.useState("login");
490
+ const [email, setEmail] = React.useState("");
289
491
  const brandLogo = loginLogo ?? logo;
290
492
  const heading = view === "login" ? "Welcome back" : view === "signup" ? "Create account" : "Reset password";
291
493
  const subtitle = view === "login" ? "Enter your credentials to continue" : view === "signup" ? "Create your account to get started" : "Enter your email and we will send reset instructions";
@@ -295,9 +497,19 @@ function LoginPage({
295
497
  onSuccess,
296
498
  onForgotPassword: () => setView("recovery"),
297
499
  showOAuth,
298
- oauthProviders
500
+ oauthProviders,
501
+ initialEmail: email,
502
+ onEmailChange: setEmail
503
+ }
504
+ ) : view === "signup" ? /* @__PURE__ */ jsx(SignupForm, { onSuccess }) : /* @__PURE__ */ jsx(
505
+ ForgotPasswordForm,
506
+ {
507
+ redirectTo: resetPasswordUrl,
508
+ onBackToLogin: () => setView("login"),
509
+ initialEmail: email,
510
+ onEmailChange: setEmail
299
511
  }
300
- ) : view === "signup" ? /* @__PURE__ */ jsx(SignupForm, { onSuccess }) : /* @__PURE__ */ jsx(ForgotPasswordForm, { redirectTo: resetPasswordUrl, onBackToLogin: () => setView("login") });
512
+ );
301
513
  const switcher = view === "login" ? /* @__PURE__ */ jsxs("p", { className: "text-center text-sm text-muted-foreground", children: [
302
514
  "Do not have an account?",
303
515
  " ",
@@ -375,15 +587,9 @@ function AuthCallbackPage({ onSuccess, onError }) {
375
587
  ] }) });
376
588
  }
377
589
  function ResetPasswordPage({ onSuccess }) {
378
- return /* @__PURE__ */ jsx("div", { className: "flex min-h-screen items-center justify-center bg-background p-4", children: /* @__PURE__ */ jsxs("div", { className: "w-full max-w-md rounded-2xl border bg-card p-8 shadow-xl", children: [
379
- /* @__PURE__ */ jsxs("div", { className: "mb-6", children: [
380
- /* @__PURE__ */ jsx("h1", { className: "text-2xl font-bold text-foreground", children: "Update password" }),
381
- /* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-muted-foreground", children: "Choose a new password for your account." })
382
- ] }),
383
- /* @__PURE__ */ jsx(ResetPasswordForm, { onSuccess })
384
- ] }) });
590
+ return /* @__PURE__ */ jsx(SetPasswordPage, { reason: "recovery", onSuccess });
385
591
  }
386
592
 
387
- export { AmbassadorBubbles, AuthCallbackPage, AuthGate, ForgotPasswordForm, LoginForm, LoginPage, OAuthButtons, ResetPasswordForm, ResetPasswordPage, SignupForm, createAuthPlugin, createAuthRuntime, resolveAuthAdapter };
593
+ export { AmbassadorBubbles, AuthCallbackPage, AuthGate, ForgotPasswordForm, LoginForm, LoginPage, OAuthButtons, ResetPasswordForm, ResetPasswordPage, SetPasswordPage, SignupForm, createAuthPlugin, createAuthRuntime, resolveAuthAdapter, usePasswordSetupGate };
388
594
  //# sourceMappingURL=index.js.map
389
595
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/runtime.ts","../src/forms.tsx","../src/AmbassadorBubbles.tsx","../src/pages.tsx"],"names":["jsxs","jsx","React2","useAuth"],"mappings":"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","file":"index.js","sourcesContent":["import type { AuthAdapter } from '@fayz-ai/core'\nimport { createMockAuthAdapter, createSupabaseAuthAdapter } from '@fayz-ai/auth'\nimport type { AuthPluginOptions, ResolvedAuthPlugin } from './types'\n\nfunction absoluteUrl(path: string): string | undefined {\n if (typeof window === 'undefined') return undefined\n if (/^https?:\\/\\//.test(path)) return path\n return `${window.location.origin}${path.startsWith('/') ? path : `/${path}`}`\n}\n\nexport function resolveAuthAdapter(options: AuthPluginOptions = {}): AuthAdapter {\n const configured = options.adapter ?? options.provider\n if (configured && typeof configured === 'object') return configured\n\n const provider = configured ?? (options.supabase?.url ? 'supabase' : 'mock')\n if (provider === 'supabase') {\n const url = options.supabase?.url\n const anonKey = options.supabase?.anonKey\n if (!url || !anonKey) {\n throw new Error('plugin-auth provider=\"supabase\" requires supabase.url and supabase.anonKey.')\n }\n return createSupabaseAuthAdapter({\n supabaseUrl: url,\n supabaseAnonKey: anonKey,\n supabaseClient: options.supabase?.client,\n callbackUrl: options.supabase?.callbackUrl ?? absoluteUrl(options.routes?.callback ?? '/auth/callback'),\n resetPasswordUrl:\n options.supabase?.resetPasswordUrl ?? absoluteUrl(options.routes?.resetPassword ?? '/auth/reset-password'),\n })\n }\n\n return createMockAuthAdapter()\n}\n\nexport function createAuthRuntime(options: AuthPluginOptions = {}): ResolvedAuthPlugin {\n return {\n kind: 'auth',\n adapter: resolveAuthAdapter(options),\n requireAuth: options.requireAuth ?? true,\n layout: options.layout ?? 'split',\n logo: options.logo,\n tagline: options.tagline,\n description: options.description,\n loginAmbassadors: options.loginAmbassadors,\n loginAmbassadorsLabel: options.loginAmbassadorsLabel,\n oauth: {\n enabled: options.oauth?.enabled ?? false,\n providers: options.oauth?.providers ?? ['google'],\n },\n routes: {\n login: options.routes?.login ?? '/login',\n callback: options.routes?.callback ?? '/auth/callback',\n resetPassword: options.routes?.resetPassword ?? '/auth/reset-password',\n afterSignIn: options.routes?.afterSignIn ?? '/',\n },\n }\n}\n\nexport function createAuthPlugin(options: AuthPluginOptions = {}): ResolvedAuthPlugin {\n return createAuthRuntime(options)\n}\n","import * as React from 'react'\nimport { useAuth } from '@fayz-ai/auth'\nimport type { AuthProvider } from '@fayz-ai/core'\n\nfunction providerLabel(provider: string): string {\n return provider.charAt(0).toUpperCase() + provider.slice(1)\n}\n\nfunction fieldClass() {\n return 'h-10 w-full rounded-md 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'\n}\n\nfunction buttonClass(variant: 'primary' | 'outline' | 'ghost' = 'primary') {\n if (variant === 'outline') {\n return 'inline-flex h-10 w-full items-center justify-center rounded-md 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'\n }\n if (variant === 'ghost') return 'text-sm font-medium text-primary hover:underline'\n 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'\n}\n\nexport interface OAuthButtonsProps {\n providers?: Exclude<AuthProvider, 'email'>[]\n disabled?: boolean\n onProviderClick?: (provider: AuthProvider) => void | Promise<void>\n}\n\nexport function OAuthButtons({ providers = ['google'], disabled, onProviderClick }: OAuthButtonsProps) {\n const { signInWithOAuth } = useAuth()\n return (\n <div className=\"space-y-2\">\n {providers.map((provider) => (\n <button\n key={provider}\n type=\"button\"\n className={buttonClass('outline')}\n disabled={disabled}\n onClick={() => {\n void (onProviderClick ? onProviderClick(provider) : signInWithOAuth(provider))\n }}\n >\n Continue with {providerLabel(provider)}\n </button>\n ))}\n </div>\n )\n}\n\nexport interface LoginFormProps {\n onSuccess?: () => void\n onForgotPassword?: () => void\n showOAuth?: boolean\n oauthProviders?: Exclude<AuthProvider, 'email'>[]\n}\n\nexport function LoginForm({ onSuccess, onForgotPassword, showOAuth, oauthProviders }: LoginFormProps) {\n const { signIn, error, isLoading } = useAuth()\n const [email, setEmail] = React.useState('')\n const [password, setPassword] = React.useState('')\n const [busy, setBusy] = React.useState(false)\n const disabled = busy || isLoading\n\n async function submit(event: React.FormEvent) {\n event.preventDefault()\n setBusy(true)\n try {\n await signIn(email, password)\n onSuccess?.()\n } finally {\n setBusy(false)\n }\n }\n\n return (\n <form onSubmit={submit} className=\"space-y-4\">\n <label className=\"block space-y-1.5 text-sm font-medium\">\n <span>Email</span>\n <input className={fieldClass()} type=\"email\" autoComplete=\"username\" required value={email} onChange={(e) => setEmail(e.target.value)} disabled={disabled} />\n </label>\n <label className=\"block space-y-1.5 text-sm font-medium\">\n <span>Password</span>\n <input className={fieldClass()} type=\"password\" autoComplete=\"current-password\" required value={password} onChange={(e) => setPassword(e.target.value)} disabled={disabled} />\n </label>\n {onForgotPassword && (\n <div className=\"-mt-1 flex justify-end\">\n <button type=\"button\" className={buttonClass('ghost')} onClick={onForgotPassword}>\n Forgot password?\n </button>\n </div>\n )}\n {error && <p className=\"text-sm text-destructive\">{error.message}</p>}\n <button className={buttonClass()} type=\"submit\" disabled={disabled}>\n {disabled ? 'Signing in...' : 'Sign in'}\n </button>\n {showOAuth && <OAuthButtons providers={oauthProviders} disabled={disabled} />}\n </form>\n )\n}\n\nexport interface SignupFormProps {\n onSuccess?: () => void\n}\n\nexport function SignupForm({ onSuccess }: SignupFormProps) {\n const { signUp, error, isLoading } = useAuth()\n const [fullName, setFullName] = React.useState('')\n const [email, setEmail] = React.useState('')\n const [password, setPassword] = React.useState('')\n const [confirmPassword, setConfirmPassword] = React.useState('')\n const [localError, setLocalError] = React.useState<string | null>(null)\n const [busy, setBusy] = React.useState(false)\n const disabled = busy || isLoading\n\n async function submit(event: React.FormEvent) {\n event.preventDefault()\n setLocalError(null)\n if (password.length < 8) {\n setLocalError('Password must be at least 8 characters.')\n return\n }\n if (password !== confirmPassword) {\n setLocalError('Passwords do not match.')\n return\n }\n setBusy(true)\n try {\n await signUp(email, password, fullName)\n onSuccess?.()\n } finally {\n setBusy(false)\n }\n }\n\n return (\n <form onSubmit={submit} className=\"space-y-4\">\n <label className=\"block space-y-1.5 text-sm font-medium\">\n <span>Full name</span>\n <input className={fieldClass()} required value={fullName} onChange={(e) => setFullName(e.target.value)} disabled={disabled} />\n </label>\n <label className=\"block space-y-1.5 text-sm font-medium\">\n <span>Email</span>\n <input className={fieldClass()} type=\"email\" autoComplete=\"username\" required value={email} onChange={(e) => setEmail(e.target.value)} disabled={disabled} />\n </label>\n <label className=\"block space-y-1.5 text-sm font-medium\">\n <span>Password</span>\n <input className={fieldClass()} type=\"password\" autoComplete=\"new-password\" required value={password} onChange={(e) => setPassword(e.target.value)} disabled={disabled} />\n </label>\n <label className=\"block space-y-1.5 text-sm font-medium\">\n <span>Confirm password</span>\n <input className={fieldClass()} type=\"password\" autoComplete=\"new-password\" required value={confirmPassword} onChange={(e) => setConfirmPassword(e.target.value)} disabled={disabled} />\n </label>\n {(localError || error) && <p className=\"text-sm text-destructive\">{localError ?? error?.message}</p>}\n <button className={buttonClass()} type=\"submit\" disabled={disabled}>\n {disabled ? 'Creating account...' : 'Create account'}\n </button>\n </form>\n )\n}\n\nexport interface ForgotPasswordFormProps {\n redirectTo?: string\n onSent?: (email: string) => void\n onBackToLogin?: () => void\n}\n\nexport function ForgotPasswordForm({ redirectTo, onSent, onBackToLogin }: ForgotPasswordFormProps) {\n const { resetPassword, error, isLoading } = useAuth()\n const [email, setEmail] = React.useState('')\n const [sent, setSent] = React.useState(false)\n const [busy, setBusy] = React.useState(false)\n const disabled = busy || isLoading\n\n async function submit(event: React.FormEvent) {\n event.preventDefault()\n setBusy(true)\n try {\n await resetPassword(email, { redirectTo })\n setSent(true)\n onSent?.(email)\n } finally {\n setBusy(false)\n }\n }\n\n return (\n <form onSubmit={submit} className=\"space-y-4\">\n <label className=\"block space-y-1.5 text-sm font-medium\">\n <span>Email</span>\n <input className={fieldClass()} type=\"email\" autoComplete=\"username\" required value={email} onChange={(e) => setEmail(e.target.value)} disabled={disabled} />\n </label>\n {error && <p className=\"text-sm text-destructive\">{error.message}</p>}\n {sent && <p className=\"text-sm text-emerald-600\">Password reset instructions sent.</p>}\n <button className={buttonClass()} type=\"submit\" disabled={disabled}>\n {disabled ? 'Sending...' : 'Send reset link'}\n </button>\n {onBackToLogin && (\n <button type=\"button\" className={buttonClass('ghost')} onClick={onBackToLogin}>\n Back to login\n </button>\n )}\n </form>\n )\n}\n\nexport interface ResetPasswordFormProps {\n onSuccess?: () => void\n}\n\nexport function ResetPasswordForm({ onSuccess }: ResetPasswordFormProps) {\n const { updatePassword, error, isLoading } = useAuth()\n const [password, setPassword] = React.useState('')\n const [confirmPassword, setConfirmPassword] = React.useState('')\n const [localError, setLocalError] = React.useState<string | null>(null)\n const [busy, setBusy] = React.useState(false)\n const disabled = busy || isLoading\n\n async function submit(event: React.FormEvent) {\n event.preventDefault()\n setLocalError(null)\n if (password.length < 8) {\n setLocalError('Password must be at least 8 characters.')\n return\n }\n if (password !== confirmPassword) {\n setLocalError('Passwords do not match.')\n return\n }\n setBusy(true)\n try {\n await updatePassword(password)\n onSuccess?.()\n } finally {\n setBusy(false)\n }\n }\n\n return (\n <form onSubmit={submit} className=\"space-y-4\">\n <label className=\"block space-y-1.5 text-sm font-medium\">\n <span>New password</span>\n <input className={fieldClass()} type=\"password\" autoComplete=\"new-password\" required value={password} onChange={(e) => setPassword(e.target.value)} disabled={disabled} />\n </label>\n <label className=\"block space-y-1.5 text-sm font-medium\">\n <span>Confirm password</span>\n <input className={fieldClass()} type=\"password\" autoComplete=\"new-password\" required value={confirmPassword} onChange={(e) => setConfirmPassword(e.target.value)} disabled={disabled} />\n </label>\n {(localError || error) && <p className=\"text-sm text-destructive\">{localError ?? error?.message}</p>}\n <button className={buttonClass()} type=\"submit\" disabled={disabled}>\n {disabled ? 'Saving...' : 'Update password'}\n </button>\n </form>\n )\n}\n","import * as React from 'react'\nimport type { LoginAmbassador } from './types'\n\n/**\n * Social-proof \"ambassador\" strip for the split-login brand panel. Restores\n * (modernized) the old login avatar cluster: a short row of small, softly\n * overlapping circular portraits sitting just above the tagline, optionally\n * followed by a microtext label (\"+2 mil profissionais\").\n *\n * Small (40px), subtle, no flashy motion — a very gentle idle float only, which\n * fully disables under prefers-reduced-motion. Degrades to nothing when no\n * usable images are supplied, so it is always safe to render. Purely\n * presentational — never touches the auth flow.\n */\n\nconst FLOAT_STYLES = `\n@keyframes fayz-amb-drift {\n 0%, 100% { transform: translateY(0); }\n 50% { transform: translateY(-2px); }\n}\n@media (prefers-reduced-motion: reduce) {\n .fayz-amb-avatar { animation: none !important; }\n}\n`\n\nexport interface AmbassadorBubblesProps {\n ambassadors?: LoginAmbassador[]\n /** Optional social-proof caption shown beside the avatars, e.g. \"+2 mil profissionais\". */\n label?: string\n}\n\nexport function AmbassadorBubbles({ ambassadors, label }: AmbassadorBubblesProps) {\n const items = (ambassadors ?? []).filter((a) => a && typeof a.image === 'string' && a.image.trim() !== '')\n if (items.length === 0) return null\n const shown = items.slice(0, 5)\n\n return (\n <div className=\"flex items-center gap-3\">\n <style>{FLOAT_STYLES}</style>\n <div className=\"flex -space-x-2\">\n {shown.map((ambassador, index) => (\n <div\n key={`${ambassador.name}-${index}`}\n title={ambassador.role ? `${ambassador.name} · ${ambassador.role}` : ambassador.name}\n 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\"\n style={{ animation: `fayz-amb-drift 4s ease-in-out ${index * 0.4}s infinite` }}\n >\n <img\n src={ambassador.image}\n alt={ambassador.name}\n className=\"h-full w-full object-cover\"\n loading=\"lazy\"\n draggable={false}\n />\n </div>\n ))}\n </div>\n {label ? <p className=\"text-xs font-medium text-sidebar-foreground/80\">{label}</p> : null}\n </div>\n )\n}\n","import * as React from 'react'\nimport { useAuth } from '@fayz-ai/auth'\nimport type { AuthProvider } from '@fayz-ai/core'\nimport { ForgotPasswordForm, LoginForm, ResetPasswordForm, SignupForm } from './forms'\nimport { AmbassadorBubbles } from './AmbassadorBubbles'\nimport type { AuthFormView, AuthLayout, LoginAmbassador } from './types'\n\nexport interface LoginPageProps {\n appName?: string\n logo?: React.ReactNode\n loginLogo?: React.ReactNode\n layout?: AuthLayout\n tagline?: string\n description?: string\n /** Product ambassadors shown as a small social-proof avatar strip above the\n * tagline on the split-layout brand panel. Renders nothing when empty/imageless. */\n loginAmbassadors?: LoginAmbassador[]\n /** Optional microtext beside the ambassador strip, e.g. \"+2 mil profissionais\". */\n loginAmbassadorsLabel?: string\n showOAuth?: boolean\n oauthProviders?: Exclude<AuthProvider, 'email'>[]\n resetPasswordUrl?: string\n onSuccess?: () => void\n}\n\nexport function LoginPage({\n appName = 'App',\n logo,\n loginLogo,\n layout = 'split',\n tagline,\n description,\n loginAmbassadors,\n loginAmbassadorsLabel,\n showOAuth,\n oauthProviders,\n resetPasswordUrl,\n onSuccess,\n}: LoginPageProps) {\n const [view, setView] = React.useState<AuthFormView>('login')\n const brandLogo = loginLogo ?? logo\n const heading = view === 'login' ? 'Welcome back' : view === 'signup' ? 'Create account' : 'Reset password'\n const subtitle =\n view === 'login'\n ? 'Enter your credentials to continue'\n : view === 'signup'\n ? 'Create your account to get started'\n : 'Enter your email and we will send reset instructions'\n const form =\n view === 'login' ? (\n <LoginForm\n onSuccess={onSuccess}\n onForgotPassword={() => setView('recovery')}\n showOAuth={showOAuth}\n oauthProviders={oauthProviders}\n />\n ) : view === 'signup' ? (\n <SignupForm onSuccess={onSuccess} />\n ) : (\n <ForgotPasswordForm redirectTo={resetPasswordUrl} onBackToLogin={() => setView('login')} />\n )\n const switcher =\n view === 'login' ? (\n <p className=\"text-center text-sm text-muted-foreground\">\n Do not have an account?{' '}\n <button type=\"button\" className=\"font-medium text-primary hover:underline\" onClick={() => setView('signup')}>\n Sign up\n </button>\n </p>\n ) : (\n <p className=\"text-center text-sm text-muted-foreground\">\n {view === 'signup' ? 'Already have an account?' : 'Remembered your password?'}{' '}\n <button type=\"button\" className=\"font-medium text-primary hover:underline\" onClick={() => setView('login')}>\n Sign in\n </button>\n </p>\n )\n\n if (layout === 'centered') {\n return (\n <div className=\"flex min-h-screen items-center justify-center bg-sidebar p-4\">\n <div className=\"w-full max-w-md rounded-2xl border border-border/50 bg-card p-8 shadow-2xl sm:p-10\">\n <div className=\"mb-8 text-center\">\n {brandLogo && <div className=\"mb-4 flex justify-center\">{brandLogo}</div>}\n <h1 className=\"text-2xl font-bold text-foreground\">{heading}</h1>\n <p className=\"mt-1 text-sm text-muted-foreground\">{subtitle}</p>\n </div>\n <div className=\"space-y-6\">\n {form}\n {switcher}\n </div>\n </div>\n </div>\n )\n }\n\n return (\n <div className=\"flex min-h-screen bg-sidebar\">\n <div className=\"relative hidden w-1/2 overflow-hidden lg:block\">\n <div className=\"absolute inset-0 bg-gradient-to-br from-sidebar-accent/50 via-transparent to-sidebar/80\" />\n <div className=\"relative z-20 flex h-full flex-col justify-end p-12\">\n <div className=\"space-y-4\">\n <AmbassadorBubbles ambassadors={loginAmbassadors} label={loginAmbassadorsLabel} />\n <p className=\"text-sm font-medium text-sidebar-muted\">{appName}</p>\n <h2 className=\"text-3xl font-bold text-sidebar-foreground\">{tagline ?? `Welcome to ${appName}`}</h2>\n {description && <p className=\"max-w-md text-sm leading-relaxed text-sidebar-muted\">{description}</p>}\n </div>\n </div>\n </div>\n <div className=\"flex flex-1 flex-col lg:p-3 lg:pl-3\">\n <div className=\"flex flex-1 flex-col justify-center bg-background px-6 py-12 lg:rounded-[1.25rem] lg:px-16\">\n <div className=\"mx-auto w-full max-w-sm\">\n {brandLogo && <div className=\"mb-8\">{brandLogo}</div>}\n <div className=\"mb-8\">\n <h1 className=\"text-2xl font-bold text-foreground\">{heading}</h1>\n <p className=\"mt-1 text-sm text-muted-foreground\">{subtitle}</p>\n </div>\n <div className=\"space-y-6\">\n {form}\n {switcher}\n </div>\n </div>\n </div>\n </div>\n </div>\n )\n}\n\nexport interface AuthGateProps extends LoginPageProps {\n requireAuth?: boolean\n loadingFallback?: React.ReactNode\n children: React.ReactNode\n}\n\nexport function AuthGate({ requireAuth = true, loadingFallback, children, ...loginProps }: AuthGateProps) {\n const { isAuthenticated, isLoading } = useAuth()\n if (!requireAuth || isAuthenticated) return <>{children}</>\n if (isLoading) {\n return (\n <>\n {loadingFallback ?? (\n <div className=\"flex min-h-screen items-center justify-center bg-background\">\n <span className=\"text-sm text-muted-foreground\">Loading...</span>\n </div>\n )}\n </>\n )\n }\n return <LoginPage {...loginProps} />\n}\n\nexport interface AuthCallbackPageProps {\n onSuccess?: () => void\n onError?: (error: Error) => void\n}\n\nexport function AuthCallbackPage({ onSuccess, onError }: AuthCallbackPageProps) {\n const { handleCallback } = useAuth()\n const [error, setError] = React.useState<string | null>(null)\n\n React.useEffect(() => {\n let cancelled = false\n handleCallback(typeof window === 'undefined' ? undefined : window.location.href)\n .then(() => {\n if (!cancelled) onSuccess?.()\n })\n .catch((err: unknown) => {\n const errorObject = err instanceof Error ? err : new Error(String(err))\n if (!cancelled) {\n setError(errorObject.message)\n onError?.(errorObject)\n }\n })\n return () => {\n cancelled = true\n }\n }, [handleCallback, onError, onSuccess])\n\n return (\n <div className=\"flex min-h-screen items-center justify-center bg-background p-6 text-center\">\n <div>\n <h1 className=\"text-xl font-semibold text-foreground\">{error ? 'Authentication failed' : 'Completing sign in...'}</h1>\n {error && <p className=\"mt-2 text-sm text-destructive\">{error}</p>}\n </div>\n </div>\n )\n}\n\nexport interface ResetPasswordPageProps {\n onSuccess?: () => void\n}\n\nexport function ResetPasswordPage({ onSuccess }: ResetPasswordPageProps) {\n return (\n <div className=\"flex min-h-screen items-center justify-center bg-background p-4\">\n <div className=\"w-full max-w-md rounded-2xl border bg-card p-8 shadow-xl\">\n <div className=\"mb-6\">\n <h1 className=\"text-2xl font-bold text-foreground\">Update password</h1>\n <p className=\"mt-1 text-sm text-muted-foreground\">Choose a new password for your account.</p>\n </div>\n <ResetPasswordForm onSuccess={onSuccess} />\n </div>\n </div>\n )\n}\n"]}
1
+ {"version":3,"sources":["../src/runtime.ts","../src/forms.tsx","../src/set-password.tsx","../src/AmbassadorBubbles.tsx","../src/pages.tsx"],"names":["fieldClass","buttonClass","React2","useAuth","jsx","jsxs","React3","Fragment"],"mappings":"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","file":"index.js","sourcesContent":["import type { AuthAdapter } from '@fayz-ai/core'\nimport { createMockAuthAdapter, createSupabaseAuthAdapter } from '@fayz-ai/auth'\nimport type { AuthPluginOptions, ResolvedAuthPlugin } from './types'\n\nfunction absoluteUrl(path: string): string | undefined {\n if (typeof window === 'undefined') return undefined\n if (/^https?:\\/\\//.test(path)) return path\n return `${window.location.origin}${path.startsWith('/') ? path : `/${path}`}`\n}\n\nexport function resolveAuthAdapter(options: AuthPluginOptions = {}): AuthAdapter {\n const configured = options.adapter ?? options.provider\n if (configured && typeof configured === 'object') return configured\n\n const provider = configured ?? (options.supabase?.url ? 'supabase' : 'mock')\n if (provider === 'supabase') {\n const url = options.supabase?.url\n const anonKey = options.supabase?.anonKey\n if (!url || !anonKey) {\n throw new Error('plugin-auth provider=\"supabase\" requires supabase.url and supabase.anonKey.')\n }\n return createSupabaseAuthAdapter({\n supabaseUrl: url,\n supabaseAnonKey: anonKey,\n supabaseClient: options.supabase?.client,\n callbackUrl: options.supabase?.callbackUrl ?? absoluteUrl(options.routes?.callback ?? '/auth/callback'),\n // Only when the host asked for a specific URL. Left undefined, the adapter\n // points recovery at the app root, which needs no route and no extra entry\n // in Supabase's redirect allow-list.\n resetPasswordUrl:\n options.supabase?.resetPasswordUrl ??\n (options.routes?.resetPassword ? absoluteUrl(options.routes.resetPassword) : undefined),\n })\n }\n\n return createMockAuthAdapter()\n}\n\nexport function createAuthRuntime(options: AuthPluginOptions = {}): ResolvedAuthPlugin {\n return {\n kind: 'auth',\n adapter: resolveAuthAdapter(options),\n requireAuth: options.requireAuth ?? true,\n layout: options.layout ?? 'split',\n logo: options.logo,\n tagline: options.tagline,\n description: options.description,\n loginAmbassadors: options.loginAmbassadors,\n loginAmbassadorsLabel: options.loginAmbassadorsLabel,\n oauth: {\n enabled: options.oauth?.enabled ?? false,\n providers: options.oauth?.providers ?? ['google'],\n },\n routes: {\n login: options.routes?.login ?? '/login',\n callback: options.routes?.callback ?? '/auth/callback',\n // The app root — recovery links are recognised by their own params, not by\n // the path they land on. See resetPassword() in the Supabase adapter.\n resetPassword: options.routes?.resetPassword ?? '/',\n afterSignIn: options.routes?.afterSignIn ?? '/',\n },\n }\n}\n\nexport function createAuthPlugin(options: AuthPluginOptions = {}): ResolvedAuthPlugin {\n return createAuthRuntime(options)\n}\n","import * as React from 'react'\nimport { useAuth } from '@fayz-ai/auth'\nimport type { AuthProvider } from '@fayz-ai/core'\n\nfunction providerLabel(provider: string): string {\n return provider.charAt(0).toUpperCase() + provider.slice(1)\n}\n\nfunction fieldClass() {\n return 'h-10 w-full rounded-md 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'\n}\n\nfunction buttonClass(variant: 'primary' | 'outline' | 'ghost' = 'primary') {\n if (variant === 'outline') {\n return 'inline-flex h-10 w-full items-center justify-center rounded-md 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'\n }\n if (variant === 'ghost') return 'text-sm font-medium text-primary hover:underline'\n 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'\n}\n\nexport interface OAuthButtonsProps {\n providers?: Exclude<AuthProvider, 'email'>[]\n disabled?: boolean\n onProviderClick?: (provider: AuthProvider) => void | Promise<void>\n}\n\nexport function OAuthButtons({ providers = ['google'], disabled, onProviderClick }: OAuthButtonsProps) {\n const { signInWithOAuth } = useAuth()\n return (\n <div className=\"space-y-2\">\n {providers.map((provider) => (\n <button\n key={provider}\n type=\"button\"\n className={buttonClass('outline')}\n disabled={disabled}\n onClick={() => {\n void (onProviderClick ? onProviderClick(provider) : signInWithOAuth(provider))\n }}\n >\n Continue with {providerLabel(provider)}\n </button>\n ))}\n </div>\n )\n}\n\nexport interface LoginFormProps {\n onSuccess?: () => void\n onForgotPassword?: () => void\n showOAuth?: boolean\n oauthProviders?: Exclude<AuthProvider, 'email'>[]\n /** Seeds the field, so switching between login and recovery never asks for the\n * e-mail the user already typed. */\n initialEmail?: string\n onEmailChange?: (email: string) => void\n}\n\nexport function LoginForm({\n onSuccess,\n onForgotPassword,\n showOAuth,\n oauthProviders,\n initialEmail = '',\n onEmailChange,\n}: LoginFormProps) {\n const { signIn, error, isLoading } = useAuth()\n const [email, setEmail] = React.useState(initialEmail)\n const [password, setPassword] = React.useState('')\n const [busy, setBusy] = React.useState(false)\n const disabled = busy || isLoading\n\n async function submit(event: React.FormEvent) {\n event.preventDefault()\n setBusy(true)\n try {\n await signIn(email, password)\n onSuccess?.()\n } finally {\n setBusy(false)\n }\n }\n\n return (\n <form onSubmit={submit} className=\"space-y-4\">\n <label className=\"block space-y-1.5 text-sm font-medium\">\n <span>Email</span>\n <input\n className={fieldClass()}\n type=\"email\"\n autoComplete=\"username\"\n required\n value={email}\n onChange={(e) => {\n setEmail(e.target.value)\n onEmailChange?.(e.target.value)\n }}\n disabled={disabled}\n />\n </label>\n <label className=\"block space-y-1.5 text-sm font-medium\">\n <span>Password</span>\n <input className={fieldClass()} type=\"password\" autoComplete=\"current-password\" required value={password} onChange={(e) => setPassword(e.target.value)} disabled={disabled} />\n </label>\n {onForgotPassword && (\n <div className=\"-mt-1 flex justify-end\">\n <button type=\"button\" className={buttonClass('ghost')} onClick={onForgotPassword}>\n Forgot password?\n </button>\n </div>\n )}\n {error && <p className=\"text-sm text-destructive\">{error.message}</p>}\n <button className={buttonClass()} type=\"submit\" disabled={disabled}>\n {disabled ? 'Signing in...' : 'Sign in'}\n </button>\n {showOAuth && <OAuthButtons providers={oauthProviders} disabled={disabled} />}\n </form>\n )\n}\n\nexport interface SignupFormProps {\n onSuccess?: () => void\n}\n\nexport function SignupForm({ onSuccess }: SignupFormProps) {\n const { signUp, error, isLoading } = useAuth()\n const [fullName, setFullName] = React.useState('')\n const [email, setEmail] = React.useState('')\n const [password, setPassword] = React.useState('')\n const [confirmPassword, setConfirmPassword] = React.useState('')\n const [localError, setLocalError] = React.useState<string | null>(null)\n const [busy, setBusy] = React.useState(false)\n const disabled = busy || isLoading\n\n async function submit(event: React.FormEvent) {\n event.preventDefault()\n setLocalError(null)\n if (password.length < 8) {\n setLocalError('Password must be at least 8 characters.')\n return\n }\n if (password !== confirmPassword) {\n setLocalError('Passwords do not match.')\n return\n }\n setBusy(true)\n try {\n await signUp(email, password, fullName)\n onSuccess?.()\n } finally {\n setBusy(false)\n }\n }\n\n return (\n <form onSubmit={submit} className=\"space-y-4\">\n <label className=\"block space-y-1.5 text-sm font-medium\">\n <span>Full name</span>\n <input className={fieldClass()} required value={fullName} onChange={(e) => setFullName(e.target.value)} disabled={disabled} />\n </label>\n <label className=\"block space-y-1.5 text-sm font-medium\">\n <span>Email</span>\n <input className={fieldClass()} type=\"email\" autoComplete=\"username\" required value={email} onChange={(e) => setEmail(e.target.value)} disabled={disabled} />\n </label>\n <label className=\"block space-y-1.5 text-sm font-medium\">\n <span>Password</span>\n <input className={fieldClass()} type=\"password\" autoComplete=\"new-password\" required value={password} onChange={(e) => setPassword(e.target.value)} disabled={disabled} />\n </label>\n <label className=\"block space-y-1.5 text-sm font-medium\">\n <span>Confirm password</span>\n <input className={fieldClass()} type=\"password\" autoComplete=\"new-password\" required value={confirmPassword} onChange={(e) => setConfirmPassword(e.target.value)} disabled={disabled} />\n </label>\n {(localError || error) && <p className=\"text-sm text-destructive\">{localError ?? error?.message}</p>}\n <button className={buttonClass()} type=\"submit\" disabled={disabled}>\n {disabled ? 'Creating account...' : 'Create account'}\n </button>\n </form>\n )\n}\n\nexport interface ForgotPasswordFormProps {\n redirectTo?: string\n onSent?: (email: string) => void\n onBackToLogin?: () => void\n /** Pre-filled with whatever the user already typed on the login form. */\n initialEmail?: string\n onEmailChange?: (email: string) => void\n /** Copy overrides — the set-password screen reuses this form to hand out a\n * fresh link, where \"Send reset link\" is the wrong label. */\n emailLabel?: string\n submitLabel?: string\n sendingLabel?: string\n sentLabel?: string\n backLabel?: string\n}\n\nexport function ForgotPasswordForm({\n redirectTo,\n onSent,\n onBackToLogin,\n initialEmail = '',\n onEmailChange,\n emailLabel = 'Email',\n submitLabel = 'Send reset link',\n sendingLabel = 'Sending...',\n sentLabel = 'Password reset instructions sent.',\n backLabel = 'Back to login',\n}: ForgotPasswordFormProps) {\n const { resetPassword, error, isLoading } = useAuth()\n const [email, setEmail] = React.useState(initialEmail)\n const [sent, setSent] = React.useState(false)\n const [busy, setBusy] = React.useState(false)\n const disabled = busy || isLoading\n\n async function submit(event: React.FormEvent) {\n event.preventDefault()\n setBusy(true)\n try {\n await resetPassword(email, { redirectTo })\n setSent(true)\n onSent?.(email)\n } finally {\n setBusy(false)\n }\n }\n\n return (\n <form onSubmit={submit} className=\"space-y-4\">\n <label className=\"block space-y-1.5 text-sm font-medium\">\n <span>{emailLabel}</span>\n <input\n className={fieldClass()}\n type=\"email\"\n autoComplete=\"username\"\n required\n autoFocus={!email}\n value={email}\n onChange={(e) => {\n setEmail(e.target.value)\n onEmailChange?.(e.target.value)\n }}\n disabled={disabled}\n />\n </label>\n {error && <p className=\"text-sm text-destructive\">{error.message}</p>}\n {sent && <p className=\"text-sm text-emerald-600\">{sentLabel}</p>}\n <button className={buttonClass()} type=\"submit\" disabled={disabled}>\n {disabled ? sendingLabel : submitLabel}\n </button>\n {onBackToLogin && (\n <button type=\"button\" className={buttonClass('ghost')} onClick={onBackToLogin}>\n {backLabel}\n </button>\n )}\n </form>\n )\n}\n\nexport interface ResetPasswordFormProps {\n onSuccess?: () => void\n}\n\nexport function ResetPasswordForm({ onSuccess }: ResetPasswordFormProps) {\n const { updatePassword, error, isLoading } = useAuth()\n const [password, setPassword] = React.useState('')\n const [confirmPassword, setConfirmPassword] = React.useState('')\n const [localError, setLocalError] = React.useState<string | null>(null)\n const [busy, setBusy] = React.useState(false)\n const disabled = busy || isLoading\n\n async function submit(event: React.FormEvent) {\n event.preventDefault()\n setLocalError(null)\n if (password.length < 8) {\n setLocalError('Password must be at least 8 characters.')\n return\n }\n if (password !== confirmPassword) {\n setLocalError('Passwords do not match.')\n return\n }\n setBusy(true)\n try {\n await updatePassword(password)\n onSuccess?.()\n } finally {\n setBusy(false)\n }\n }\n\n return (\n <form onSubmit={submit} className=\"space-y-4\">\n <label className=\"block space-y-1.5 text-sm font-medium\">\n <span>New password</span>\n <input className={fieldClass()} type=\"password\" autoComplete=\"new-password\" required value={password} onChange={(e) => setPassword(e.target.value)} disabled={disabled} />\n </label>\n <label className=\"block space-y-1.5 text-sm font-medium\">\n <span>Confirm password</span>\n <input className={fieldClass()} type=\"password\" autoComplete=\"new-password\" required value={confirmPassword} onChange={(e) => setConfirmPassword(e.target.value)} disabled={disabled} />\n </label>\n {(localError || error) && <p className=\"text-sm text-destructive\">{localError ?? error?.message}</p>}\n <button className={buttonClass()} type=\"submit\" disabled={disabled}>\n {disabled ? 'Saving...' : 'Update password'}\n </button>\n </form>\n )\n}\n","import * as React from 'react'\nimport { useAuth, readAuthUrlIntent, clearAuthUrlTokens, decidePasswordSetup } from '@fayz-ai/auth'\nimport { useTranslation } from '@fayz-ai/core'\nimport { ForgotPasswordForm } from './forms'\n\n// ---------------------------------------------------------------------------\n// Set-password surface — the one screen behind two flows:\n//\n// • recovery — the user clicked \"forgot password\" and came back on a recovery\n// link. GoTrue already signed them in from the link, so all that is missing\n// is `updateUser({ password })`. Without this screen they land straight in\n// the app (or on the login form) and are never asked, which is exactly the\n// \"the link does nothing\" bug.\n//\n// • invite — the user was added to an organisation. The invite is a magic link,\n// so the account exists with NO password: unless they choose one here, every\n// future sign-in needs another e-mail.\n//\n// Mounted by the shell above its auth gate, driven by usePasswordSetupGate().\n// ---------------------------------------------------------------------------\n\nexport type SetPasswordReason = 'recovery' | 'invite'\n\nconst MIN_LENGTH = 8\n\nfunction fieldClass() {\n return 'h-10 w-full rounded-md 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'\n}\n\nfunction buttonClass() {\n 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'\n}\n\nfunction useTr() {\n const t = useTranslation()\n return React.useCallback(\n (key: string, fallback: string, params?: Record<string, string | number>) => {\n const value = t(key, params)\n return !value || value === key ? fallback : value\n },\n [t],\n )\n}\n\nexport interface PasswordSetupGate {\n /** null when nothing is pending and the shell should render normally. */\n reason: SetPasswordReason | null\n /** The link is dead (already used / expired) — offer a fresh one instead. */\n expired: boolean\n /** Still resolving the session the link carries. */\n checking: boolean\n /** Called by the screen once the password is set (or the user gives up). */\n complete: () => void\n}\n\n/**\n * Decides whether the user owes us a password before they see the app.\n *\n * The URL intent is read from a snapshot taken at module load: supabase-js wipes\n * the token fragment as soon as it initialises, so the reason the user is here is\n * gone by the time React renders.\n */\nexport function usePasswordSetupGate(): PasswordSetupGate {\n const { user, isLoading, isAuthenticated } = useAuth()\n const [done, setDone] = React.useState(false)\n const intent = React.useMemo(() => readAuthUrlIntent(), [])\n\n const complete = React.useCallback(() => {\n clearAuthUrlTokens()\n setDone(true)\n }, [])\n\n if (done) return { reason: null, expired: false, checking: false, complete }\n\n const decision = decidePasswordSetup({\n intent,\n isLoading,\n isAuthenticated,\n mustSetPassword: user?.mustSetPassword,\n })\n return { ...decision, complete }\n}\n\nexport interface SetPasswordPageProps {\n reason: SetPasswordReason\n appName?: string\n logo?: React.ReactNode\n /** Show the \"ask for a new link\" form instead of the password fields. */\n expired?: boolean\n /** Waiting on the link's session — renders a quiet placeholder. */\n checking?: boolean\n onSuccess?: () => void\n}\n\nexport function SetPasswordPage({\n reason,\n appName = 'App',\n logo,\n expired,\n checking,\n onSuccess,\n}: SetPasswordPageProps) {\n const tr = useTr()\n const { user, updatePassword, signOut, error, isLoading } = useAuth()\n const [password, setPassword] = React.useState('')\n const [confirmPassword, setConfirmPassword] = React.useState('')\n const [localError, setLocalError] = React.useState<string | null>(null)\n const [busy, setBusy] = React.useState(false)\n const disabled = busy || isLoading\n\n const invite = reason === 'invite'\n const title = invite\n ? tr('auth.setPassword.welcomeTitle', `Welcome to ${appName}`, { appName })\n : tr('auth.setPassword.recoveryTitle', 'Choose a new password')\n const subtitle = invite\n ? tr('auth.setPassword.welcomeSubtitle', 'Choose a password to finish setting up your access.')\n : tr('auth.setPassword.recoverySubtitle', 'Set a new password to get back into your account.')\n\n async function submit(event: React.FormEvent) {\n event.preventDefault()\n setLocalError(null)\n if (password.length < MIN_LENGTH) {\n setLocalError(tr('auth.setPassword.tooShort', `Password must be at least ${MIN_LENGTH} characters.`))\n return\n }\n if (password !== confirmPassword) {\n setLocalError(tr('auth.setPassword.mismatch', 'Passwords do not match.'))\n return\n }\n setBusy(true)\n try {\n await updatePassword(password)\n onSuccess?.()\n } catch {\n // useAuth already surfaced it; keep the user on the form.\n } finally {\n setBusy(false)\n }\n }\n\n return (\n <div className=\"flex min-h-screen items-center justify-center bg-sidebar p-4\">\n <div className=\"w-full max-w-md rounded-2xl border border-border/50 bg-card p-8 shadow-2xl sm:p-10\">\n {logo && <div className=\"mb-6 flex justify-center\">{logo}</div>}\n {checking ? (\n <p className=\"py-6 text-center text-sm text-muted-foreground\">\n {tr('auth.setPassword.checking', 'Checking your link...')}\n </p>\n ) : expired ? (\n <>\n <div className=\"mb-6\">\n <h1 className=\"text-2xl font-bold text-foreground\">\n {tr('auth.setPassword.expiredTitle', 'This link has expired')}\n </h1>\n <p className=\"mt-1 text-sm text-muted-foreground\">\n {tr(\n 'auth.setPassword.expiredSubtitle',\n 'Reset links can only be used once. Enter your e-mail and we will send a new one.',\n )}\n </p>\n </div>\n <ForgotPasswordForm\n initialEmail={user?.email}\n submitLabel={tr('auth.setPassword.sendNewLink', 'Send new link')}\n sendingLabel={tr('auth.setPassword.sending', 'Sending...')}\n sentLabel={tr('auth.setPassword.sent', 'Check your inbox — a new link is on the way.')}\n emailLabel={tr('auth.setPassword.email', 'E-mail')}\n backLabel={tr('auth.setPassword.backToLogin', 'Back to sign in')}\n onBackToLogin={onSuccess}\n />\n </>\n ) : (\n <>\n <div className=\"mb-6\">\n <h1 className=\"text-2xl font-bold text-foreground\">{title}</h1>\n <p className=\"mt-1 text-sm text-muted-foreground\">{subtitle}</p>\n </div>\n <form onSubmit={submit} className=\"space-y-4\">\n <label className=\"block space-y-1.5 text-sm font-medium\">\n <span>{tr('auth.setPassword.newPassword', 'New password')}</span>\n <input\n className={fieldClass()}\n type=\"password\"\n autoComplete=\"new-password\"\n autoFocus\n required\n value={password}\n onChange={(e) => setPassword(e.target.value)}\n disabled={disabled}\n />\n </label>\n <label className=\"block space-y-1.5 text-sm font-medium\">\n <span>{tr('auth.setPassword.confirmPassword', 'Confirm password')}</span>\n <input\n className={fieldClass()}\n type=\"password\"\n autoComplete=\"new-password\"\n required\n value={confirmPassword}\n onChange={(e) => setConfirmPassword(e.target.value)}\n disabled={disabled}\n />\n </label>\n {(localError || error) && (\n <p className=\"text-sm text-destructive\">{localError ?? error?.message}</p>\n )}\n <button className={buttonClass()} type=\"submit\" disabled={disabled}>\n {disabled\n ? tr('auth.setPassword.saving', 'Saving...')\n : tr('auth.setPassword.submit', 'Save password')}\n </button>\n </form>\n {/* An invitee who does not want to continue needs a way out that does\n not leave them stuck on this screen with a live session. */}\n <button\n type=\"button\"\n className=\"mt-4 w-full text-center text-sm text-muted-foreground hover:text-foreground\"\n onClick={() => {\n void signOut().finally(() => onSuccess?.())\n }}\n >\n {tr('auth.setPassword.backToLogin', 'Back to sign in')}\n </button>\n </>\n )}\n </div>\n </div>\n )\n}\n","import * as React from 'react'\nimport type { LoginAmbassador } from './types'\n\n/**\n * Social-proof \"ambassador\" strip for the split-login brand panel. Restores\n * (modernized) the old login avatar cluster: a short row of small, softly\n * overlapping circular portraits sitting just above the tagline, optionally\n * followed by a microtext label (\"+2 mil profissionais\").\n *\n * Small (40px), subtle, no flashy motion — a very gentle idle float only, which\n * fully disables under prefers-reduced-motion. Degrades to nothing when no\n * usable images are supplied, so it is always safe to render. Purely\n * presentational — never touches the auth flow.\n */\n\nconst FLOAT_STYLES = `\n@keyframes fayz-amb-drift {\n 0%, 100% { transform: translateY(0); }\n 50% { transform: translateY(-2px); }\n}\n@media (prefers-reduced-motion: reduce) {\n .fayz-amb-avatar { animation: none !important; }\n}\n`\n\nexport interface AmbassadorBubblesProps {\n ambassadors?: LoginAmbassador[]\n /** Optional social-proof caption shown beside the avatars, e.g. \"+2 mil profissionais\". */\n label?: string\n}\n\nexport function AmbassadorBubbles({ ambassadors, label }: AmbassadorBubblesProps) {\n const items = (ambassadors ?? []).filter((a) => a && typeof a.image === 'string' && a.image.trim() !== '')\n if (items.length === 0) return null\n const shown = items.slice(0, 5)\n\n return (\n <div className=\"flex items-center gap-3\">\n <style>{FLOAT_STYLES}</style>\n <div className=\"flex -space-x-2\">\n {shown.map((ambassador, index) => (\n <div\n key={`${ambassador.name}-${index}`}\n title={ambassador.role ? `${ambassador.name} · ${ambassador.role}` : ambassador.name}\n 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\"\n style={{ animation: `fayz-amb-drift 4s ease-in-out ${index * 0.4}s infinite` }}\n >\n <img\n src={ambassador.image}\n alt={ambassador.name}\n className=\"h-full w-full object-cover\"\n loading=\"lazy\"\n draggable={false}\n />\n </div>\n ))}\n </div>\n {label ? <p className=\"text-xs font-medium text-sidebar-foreground/80\">{label}</p> : null}\n </div>\n )\n}\n","import * as React from 'react'\nimport { useAuth } from '@fayz-ai/auth'\nimport type { AuthProvider } from '@fayz-ai/core'\nimport { ForgotPasswordForm, LoginForm, SignupForm } from './forms'\nimport { SetPasswordPage } from './set-password'\nimport { AmbassadorBubbles } from './AmbassadorBubbles'\nimport type { AuthFormView, AuthLayout, LoginAmbassador } from './types'\n\nexport interface LoginPageProps {\n appName?: string\n logo?: React.ReactNode\n loginLogo?: React.ReactNode\n layout?: AuthLayout\n tagline?: string\n description?: string\n /** Product ambassadors shown as a small social-proof avatar strip above the\n * tagline on the split-layout brand panel. Renders nothing when empty/imageless. */\n loginAmbassadors?: LoginAmbassador[]\n /** Optional microtext beside the ambassador strip, e.g. \"+2 mil profissionais\". */\n loginAmbassadorsLabel?: string\n showOAuth?: boolean\n oauthProviders?: Exclude<AuthProvider, 'email'>[]\n resetPasswordUrl?: string\n onSuccess?: () => void\n}\n\nexport function LoginPage({\n appName = 'App',\n logo,\n loginLogo,\n layout = 'split',\n tagline,\n description,\n loginAmbassadors,\n loginAmbassadorsLabel,\n showOAuth,\n oauthProviders,\n resetPasswordUrl,\n onSuccess,\n}: LoginPageProps) {\n const [view, setView] = React.useState<AuthFormView>('login')\n // Lifted out of the forms so switching view carries the e-mail across: someone\n // who typed it and then remembered they forgot the password should not have to\n // type it again (and back on the login form it is still there).\n const [email, setEmail] = React.useState('')\n const brandLogo = loginLogo ?? logo\n const heading = view === 'login' ? 'Welcome back' : view === 'signup' ? 'Create account' : 'Reset password'\n const subtitle =\n view === 'login'\n ? 'Enter your credentials to continue'\n : view === 'signup'\n ? 'Create your account to get started'\n : 'Enter your email and we will send reset instructions'\n const form =\n view === 'login' ? (\n <LoginForm\n onSuccess={onSuccess}\n onForgotPassword={() => setView('recovery')}\n showOAuth={showOAuth}\n oauthProviders={oauthProviders}\n initialEmail={email}\n onEmailChange={setEmail}\n />\n ) : view === 'signup' ? (\n <SignupForm onSuccess={onSuccess} />\n ) : (\n <ForgotPasswordForm\n redirectTo={resetPasswordUrl}\n onBackToLogin={() => setView('login')}\n initialEmail={email}\n onEmailChange={setEmail}\n />\n )\n const switcher =\n view === 'login' ? (\n <p className=\"text-center text-sm text-muted-foreground\">\n Do not have an account?{' '}\n <button type=\"button\" className=\"font-medium text-primary hover:underline\" onClick={() => setView('signup')}>\n Sign up\n </button>\n </p>\n ) : (\n <p className=\"text-center text-sm text-muted-foreground\">\n {view === 'signup' ? 'Already have an account?' : 'Remembered your password?'}{' '}\n <button type=\"button\" className=\"font-medium text-primary hover:underline\" onClick={() => setView('login')}>\n Sign in\n </button>\n </p>\n )\n\n if (layout === 'centered') {\n return (\n <div className=\"flex min-h-screen items-center justify-center bg-sidebar p-4\">\n <div className=\"w-full max-w-md rounded-2xl border border-border/50 bg-card p-8 shadow-2xl sm:p-10\">\n <div className=\"mb-8 text-center\">\n {brandLogo && <div className=\"mb-4 flex justify-center\">{brandLogo}</div>}\n <h1 className=\"text-2xl font-bold text-foreground\">{heading}</h1>\n <p className=\"mt-1 text-sm text-muted-foreground\">{subtitle}</p>\n </div>\n <div className=\"space-y-6\">\n {form}\n {switcher}\n </div>\n </div>\n </div>\n )\n }\n\n return (\n <div className=\"flex min-h-screen bg-sidebar\">\n <div className=\"relative hidden w-1/2 overflow-hidden lg:block\">\n <div className=\"absolute inset-0 bg-gradient-to-br from-sidebar-accent/50 via-transparent to-sidebar/80\" />\n <div className=\"relative z-20 flex h-full flex-col justify-end p-12\">\n <div className=\"space-y-4\">\n <AmbassadorBubbles ambassadors={loginAmbassadors} label={loginAmbassadorsLabel} />\n <p className=\"text-sm font-medium text-sidebar-muted\">{appName}</p>\n <h2 className=\"text-3xl font-bold text-sidebar-foreground\">{tagline ?? `Welcome to ${appName}`}</h2>\n {description && <p className=\"max-w-md text-sm leading-relaxed text-sidebar-muted\">{description}</p>}\n </div>\n </div>\n </div>\n <div className=\"flex flex-1 flex-col lg:p-3 lg:pl-3\">\n <div className=\"flex flex-1 flex-col justify-center bg-background px-6 py-12 lg:rounded-[1.25rem] lg:px-16\">\n <div className=\"mx-auto w-full max-w-sm\">\n {brandLogo && <div className=\"mb-8\">{brandLogo}</div>}\n <div className=\"mb-8\">\n <h1 className=\"text-2xl font-bold text-foreground\">{heading}</h1>\n <p className=\"mt-1 text-sm text-muted-foreground\">{subtitle}</p>\n </div>\n <div className=\"space-y-6\">\n {form}\n {switcher}\n </div>\n </div>\n </div>\n </div>\n </div>\n )\n}\n\nexport interface AuthGateProps extends LoginPageProps {\n requireAuth?: boolean\n loadingFallback?: React.ReactNode\n children: React.ReactNode\n}\n\nexport function AuthGate({ requireAuth = true, loadingFallback, children, ...loginProps }: AuthGateProps) {\n const { isAuthenticated, isLoading } = useAuth()\n if (!requireAuth || isAuthenticated) return <>{children}</>\n if (isLoading) {\n return (\n <>\n {loadingFallback ?? (\n <div className=\"flex min-h-screen items-center justify-center bg-background\">\n <span className=\"text-sm text-muted-foreground\">Loading...</span>\n </div>\n )}\n </>\n )\n }\n return <LoginPage {...loginProps} />\n}\n\nexport interface AuthCallbackPageProps {\n onSuccess?: () => void\n onError?: (error: Error) => void\n}\n\nexport function AuthCallbackPage({ onSuccess, onError }: AuthCallbackPageProps) {\n const { handleCallback } = useAuth()\n const [error, setError] = React.useState<string | null>(null)\n\n React.useEffect(() => {\n let cancelled = false\n handleCallback(typeof window === 'undefined' ? undefined : window.location.href)\n .then(() => {\n if (!cancelled) onSuccess?.()\n })\n .catch((err: unknown) => {\n const errorObject = err instanceof Error ? err : new Error(String(err))\n if (!cancelled) {\n setError(errorObject.message)\n onError?.(errorObject)\n }\n })\n return () => {\n cancelled = true\n }\n }, [handleCallback, onError, onSuccess])\n\n return (\n <div className=\"flex min-h-screen items-center justify-center bg-background p-6 text-center\">\n <div>\n <h1 className=\"text-xl font-semibold text-foreground\">{error ? 'Authentication failed' : 'Completing sign in...'}</h1>\n {error && <p className=\"mt-2 text-sm text-destructive\">{error}</p>}\n </div>\n </div>\n )\n}\n\nexport interface ResetPasswordPageProps {\n onSuccess?: () => void\n}\n\n/** Kept for apps that route `/auth/reset-password` themselves. The shell no\n * longer needs a route: SetPasswordPage is mounted by usePasswordSetupGate. */\nexport function ResetPasswordPage({ onSuccess }: ResetPasswordPageProps) {\n return <SetPasswordPage reason=\"recovery\" onSuccess={onSuccess} />\n}\n"]}
package/dist/pages.d.ts CHANGED
@@ -33,5 +33,7 @@ export declare function AuthCallbackPage({ onSuccess, onError }: AuthCallbackPag
33
33
  export interface ResetPasswordPageProps {
34
34
  onSuccess?: () => void;
35
35
  }
36
+ /** Kept for apps that route `/auth/reset-password` themselves. The shell no
37
+ * longer needs a route: SetPasswordPage is mounted by usePasswordSetupGate. */
36
38
  export declare function ResetPasswordPage({ onSuccess }: ResetPasswordPageProps): React.JSX.Element;
37
39
  //# sourceMappingURL=pages.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"pages.d.ts","sourceRoot":"","sources":["../src/pages.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAGjD,OAAO,KAAK,EAAgB,UAAU,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAExE,MAAM,WAAW,cAAc;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACtB,SAAS,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC3B,MAAM,CAAC,EAAE,UAAU,CAAA;IACnB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;yFACqF;IACrF,gBAAgB,CAAC,EAAE,eAAe,EAAE,CAAA;IACpC,mFAAmF;IACnF,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,cAAc,CAAC,EAAE,OAAO,CAAC,YAAY,EAAE,OAAO,CAAC,EAAE,CAAA;IACjD,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;CACvB;AAED,wBAAgB,SAAS,CAAC,EACxB,OAAe,EACf,IAAI,EACJ,SAAS,EACT,MAAgB,EAChB,OAAO,EACP,WAAW,EACX,gBAAgB,EAChB,qBAAqB,EACrB,SAAS,EACT,cAAc,EACd,gBAAgB,EAChB,SAAS,GACV,EAAE,cAAc,qBAwFhB;AAED,MAAM,WAAW,aAAc,SAAQ,cAAc;IACnD,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,eAAe,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACjC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAC1B;AAED,wBAAgB,QAAQ,CAAC,EAAE,WAAkB,EAAE,eAAe,EAAE,QAAQ,EAAE,GAAG,UAAU,EAAE,EAAE,aAAa,qBAevG;AAED,MAAM,WAAW,qBAAqB;IACpC,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;IACtB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;CACjC;AAED,wBAAgB,gBAAgB,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE,qBAAqB,qBA8B7E;AAED,MAAM,WAAW,sBAAsB;IACrC,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;CACvB;AAED,wBAAgB,iBAAiB,CAAC,EAAE,SAAS,EAAE,EAAE,sBAAsB,qBAYtE"}
1
+ {"version":3,"file":"pages.d.ts","sourceRoot":"","sources":["../src/pages.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAIjD,OAAO,KAAK,EAAgB,UAAU,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAExE,MAAM,WAAW,cAAc;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACtB,SAAS,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC3B,MAAM,CAAC,EAAE,UAAU,CAAA;IACnB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;yFACqF;IACrF,gBAAgB,CAAC,EAAE,eAAe,EAAE,CAAA;IACpC,mFAAmF;IACnF,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,cAAc,CAAC,EAAE,OAAO,CAAC,YAAY,EAAE,OAAO,CAAC,EAAE,CAAA;IACjD,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;CACvB;AAED,wBAAgB,SAAS,CAAC,EACxB,OAAe,EACf,IAAI,EACJ,SAAS,EACT,MAAgB,EAChB,OAAO,EACP,WAAW,EACX,gBAAgB,EAChB,qBAAqB,EACrB,SAAS,EACT,cAAc,EACd,gBAAgB,EAChB,SAAS,GACV,EAAE,cAAc,qBAmGhB;AAED,MAAM,WAAW,aAAc,SAAQ,cAAc;IACnD,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,eAAe,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACjC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAC1B;AAED,wBAAgB,QAAQ,CAAC,EAAE,WAAkB,EAAE,eAAe,EAAE,QAAQ,EAAE,GAAG,UAAU,EAAE,EAAE,aAAa,qBAevG;AAED,MAAM,WAAW,qBAAqB;IACpC,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;IACtB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;CACjC;AAED,wBAAgB,gBAAgB,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE,qBAAqB,qBA8B7E;AAED,MAAM,WAAW,sBAAsB;IACrC,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;CACvB;AAED;gFACgF;AAChF,wBAAgB,iBAAiB,CAAC,EAAE,SAAS,EAAE,EAAE,sBAAsB,qBAEtE"}
@@ -1 +1 @@
1
- {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAEhD,OAAO,KAAK,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAA;AAQpE,wBAAgB,kBAAkB,CAAC,OAAO,GAAE,iBAAsB,GAAG,WAAW,CAsB/E;AAED,wBAAgB,iBAAiB,CAAC,OAAO,GAAE,iBAAsB,GAAG,kBAAkB,CAsBrF;AAED,wBAAgB,gBAAgB,CAAC,OAAO,GAAE,iBAAsB,GAAG,kBAAkB,CAEpF"}
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAEhD,OAAO,KAAK,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAA;AAQpE,wBAAgB,kBAAkB,CAAC,OAAO,GAAE,iBAAsB,GAAG,WAAW,CA0B/E;AAED,wBAAgB,iBAAiB,CAAC,OAAO,GAAE,iBAAsB,GAAG,kBAAkB,CAwBrF;AAED,wBAAgB,gBAAgB,CAAC,OAAO,GAAE,iBAAsB,GAAG,kBAAkB,CAEpF"}
@@ -0,0 +1,32 @@
1
+ import * as React from 'react';
2
+ export type SetPasswordReason = 'recovery' | 'invite';
3
+ export interface PasswordSetupGate {
4
+ /** null when nothing is pending and the shell should render normally. */
5
+ reason: SetPasswordReason | null;
6
+ /** The link is dead (already used / expired) — offer a fresh one instead. */
7
+ expired: boolean;
8
+ /** Still resolving the session the link carries. */
9
+ checking: boolean;
10
+ /** Called by the screen once the password is set (or the user gives up). */
11
+ complete: () => void;
12
+ }
13
+ /**
14
+ * Decides whether the user owes us a password before they see the app.
15
+ *
16
+ * The URL intent is read from a snapshot taken at module load: supabase-js wipes
17
+ * the token fragment as soon as it initialises, so the reason the user is here is
18
+ * gone by the time React renders.
19
+ */
20
+ export declare function usePasswordSetupGate(): PasswordSetupGate;
21
+ export interface SetPasswordPageProps {
22
+ reason: SetPasswordReason;
23
+ appName?: string;
24
+ logo?: React.ReactNode;
25
+ /** Show the "ask for a new link" form instead of the password fields. */
26
+ expired?: boolean;
27
+ /** Waiting on the link's session — renders a quiet placeholder. */
28
+ checking?: boolean;
29
+ onSuccess?: () => void;
30
+ }
31
+ export declare function SetPasswordPage({ reason, appName, logo, expired, checking, onSuccess, }: SetPasswordPageProps): React.JSX.Element;
32
+ //# sourceMappingURL=set-password.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"set-password.d.ts","sourceRoot":"","sources":["../src/set-password.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAqB9B,MAAM,MAAM,iBAAiB,GAAG,UAAU,GAAG,QAAQ,CAAA;AAuBrD,MAAM,WAAW,iBAAiB;IAChC,yEAAyE;IACzE,MAAM,EAAE,iBAAiB,GAAG,IAAI,CAAA;IAChC,6EAA6E;IAC7E,OAAO,EAAE,OAAO,CAAA;IAChB,oDAAoD;IACpD,QAAQ,EAAE,OAAO,CAAA;IACjB,4EAA4E;IAC5E,QAAQ,EAAE,MAAM,IAAI,CAAA;CACrB;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,IAAI,iBAAiB,CAmBxD;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,iBAAiB,CAAA;IACzB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACtB,yEAAyE;IACzE,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,mEAAmE;IACnE,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;CACvB;AAED,wBAAgB,eAAe,CAAC,EAC9B,MAAM,EACN,OAAe,EACf,IAAI,EACJ,OAAO,EACP,QAAQ,EACR,SAAS,GACV,EAAE,oBAAoB,qBA+HtB"}
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "fayz": {
4
4
  "status": "preview"
5
5
  },
6
- "version": "0.9.0-next.0",
6
+ "version": "0.9.0-next.1",
7
7
  "description": "Fayz SDK — reusable auth runtime and UI integration plugin",
8
8
  "type": "module",
9
9
  "sideEffects": false,
@@ -33,9 +33,9 @@
33
33
  },
34
34
  "dependencies": {
35
35
  "@radix-ui/react-dialog": "^1.1.0",
36
- "@fayz-ai/auth": "^0.9.0-next.0",
37
- "@fayz-ai/ui": "^0.9.0-next.0",
38
- "@fayz-ai/core": "^0.9.0-next.0"
36
+ "@fayz-ai/auth": "^0.9.0-next.1",
37
+ "@fayz-ai/ui": "^0.9.0-next.1",
38
+ "@fayz-ai/core": "^0.9.0-next.1"
39
39
  },
40
40
  "devDependencies": {
41
41
  "@types/react": "^18.3.0",
package/src/forms.tsx CHANGED
@@ -50,11 +50,22 @@ export interface LoginFormProps {
50
50
  onForgotPassword?: () => void
51
51
  showOAuth?: boolean
52
52
  oauthProviders?: Exclude<AuthProvider, 'email'>[]
53
+ /** Seeds the field, so switching between login and recovery never asks for the
54
+ * e-mail the user already typed. */
55
+ initialEmail?: string
56
+ onEmailChange?: (email: string) => void
53
57
  }
54
58
 
55
- export function LoginForm({ onSuccess, onForgotPassword, showOAuth, oauthProviders }: LoginFormProps) {
59
+ export function LoginForm({
60
+ onSuccess,
61
+ onForgotPassword,
62
+ showOAuth,
63
+ oauthProviders,
64
+ initialEmail = '',
65
+ onEmailChange,
66
+ }: LoginFormProps) {
56
67
  const { signIn, error, isLoading } = useAuth()
57
- const [email, setEmail] = React.useState('')
68
+ const [email, setEmail] = React.useState(initialEmail)
58
69
  const [password, setPassword] = React.useState('')
59
70
  const [busy, setBusy] = React.useState(false)
60
71
  const disabled = busy || isLoading
@@ -74,7 +85,18 @@ export function LoginForm({ onSuccess, onForgotPassword, showOAuth, oauthProvide
74
85
  <form onSubmit={submit} className="space-y-4">
75
86
  <label className="block space-y-1.5 text-sm font-medium">
76
87
  <span>Email</span>
77
- <input className={fieldClass()} type="email" autoComplete="username" required value={email} onChange={(e) => setEmail(e.target.value)} disabled={disabled} />
88
+ <input
89
+ className={fieldClass()}
90
+ type="email"
91
+ autoComplete="username"
92
+ required
93
+ value={email}
94
+ onChange={(e) => {
95
+ setEmail(e.target.value)
96
+ onEmailChange?.(e.target.value)
97
+ }}
98
+ disabled={disabled}
99
+ />
78
100
  </label>
79
101
  <label className="block space-y-1.5 text-sm font-medium">
80
102
  <span>Password</span>
@@ -160,11 +182,32 @@ export interface ForgotPasswordFormProps {
160
182
  redirectTo?: string
161
183
  onSent?: (email: string) => void
162
184
  onBackToLogin?: () => void
185
+ /** Pre-filled with whatever the user already typed on the login form. */
186
+ initialEmail?: string
187
+ onEmailChange?: (email: string) => void
188
+ /** Copy overrides — the set-password screen reuses this form to hand out a
189
+ * fresh link, where "Send reset link" is the wrong label. */
190
+ emailLabel?: string
191
+ submitLabel?: string
192
+ sendingLabel?: string
193
+ sentLabel?: string
194
+ backLabel?: string
163
195
  }
164
196
 
165
- export function ForgotPasswordForm({ redirectTo, onSent, onBackToLogin }: ForgotPasswordFormProps) {
197
+ export function ForgotPasswordForm({
198
+ redirectTo,
199
+ onSent,
200
+ onBackToLogin,
201
+ initialEmail = '',
202
+ onEmailChange,
203
+ emailLabel = 'Email',
204
+ submitLabel = 'Send reset link',
205
+ sendingLabel = 'Sending...',
206
+ sentLabel = 'Password reset instructions sent.',
207
+ backLabel = 'Back to login',
208
+ }: ForgotPasswordFormProps) {
166
209
  const { resetPassword, error, isLoading } = useAuth()
167
- const [email, setEmail] = React.useState('')
210
+ const [email, setEmail] = React.useState(initialEmail)
168
211
  const [sent, setSent] = React.useState(false)
169
212
  const [busy, setBusy] = React.useState(false)
170
213
  const disabled = busy || isLoading
@@ -184,17 +227,29 @@ export function ForgotPasswordForm({ redirectTo, onSent, onBackToLogin }: Forgot
184
227
  return (
185
228
  <form onSubmit={submit} className="space-y-4">
186
229
  <label className="block space-y-1.5 text-sm font-medium">
187
- <span>Email</span>
188
- <input className={fieldClass()} type="email" autoComplete="username" required value={email} onChange={(e) => setEmail(e.target.value)} disabled={disabled} />
230
+ <span>{emailLabel}</span>
231
+ <input
232
+ className={fieldClass()}
233
+ type="email"
234
+ autoComplete="username"
235
+ required
236
+ autoFocus={!email}
237
+ value={email}
238
+ onChange={(e) => {
239
+ setEmail(e.target.value)
240
+ onEmailChange?.(e.target.value)
241
+ }}
242
+ disabled={disabled}
243
+ />
189
244
  </label>
190
245
  {error && <p className="text-sm text-destructive">{error.message}</p>}
191
- {sent && <p className="text-sm text-emerald-600">Password reset instructions sent.</p>}
246
+ {sent && <p className="text-sm text-emerald-600">{sentLabel}</p>}
192
247
  <button className={buttonClass()} type="submit" disabled={disabled}>
193
- {disabled ? 'Sending...' : 'Send reset link'}
248
+ {disabled ? sendingLabel : submitLabel}
194
249
  </button>
195
250
  {onBackToLogin && (
196
251
  <button type="button" className={buttonClass('ghost')} onClick={onBackToLogin}>
197
- Back to login
252
+ {backLabel}
198
253
  </button>
199
254
  )}
200
255
  </form>
package/src/index.ts CHANGED
@@ -15,6 +15,8 @@ export type {
15
15
  LoginPageProps,
16
16
  ResetPasswordPageProps,
17
17
  } from './pages'
18
+ export { SetPasswordPage, usePasswordSetupGate } from './set-password'
19
+ export type { SetPasswordPageProps, SetPasswordReason, PasswordSetupGate } from './set-password'
18
20
  export { AmbassadorBubbles } from './AmbassadorBubbles'
19
21
  export type { AmbassadorBubblesProps } from './AmbassadorBubbles'
20
22
  export {
@@ -37,6 +39,8 @@ export {
37
39
  AuthProvider,
38
40
  useAuth,
39
41
  useAuthStore,
42
+ readAuthUrlIntent,
43
+ clearAuthUrlTokens,
40
44
  } from '@fayz-ai/auth'
41
45
  export type {
42
46
  AuthPluginOptions,
package/src/pages.tsx CHANGED
@@ -1,7 +1,8 @@
1
1
  import * as React from 'react'
2
2
  import { useAuth } from '@fayz-ai/auth'
3
3
  import type { AuthProvider } from '@fayz-ai/core'
4
- import { ForgotPasswordForm, LoginForm, ResetPasswordForm, SignupForm } from './forms'
4
+ import { ForgotPasswordForm, LoginForm, SignupForm } from './forms'
5
+ import { SetPasswordPage } from './set-password'
5
6
  import { AmbassadorBubbles } from './AmbassadorBubbles'
6
7
  import type { AuthFormView, AuthLayout, LoginAmbassador } from './types'
7
8
 
@@ -38,6 +39,10 @@ export function LoginPage({
38
39
  onSuccess,
39
40
  }: LoginPageProps) {
40
41
  const [view, setView] = React.useState<AuthFormView>('login')
42
+ // Lifted out of the forms so switching view carries the e-mail across: someone
43
+ // who typed it and then remembered they forgot the password should not have to
44
+ // type it again (and back on the login form it is still there).
45
+ const [email, setEmail] = React.useState('')
41
46
  const brandLogo = loginLogo ?? logo
42
47
  const heading = view === 'login' ? 'Welcome back' : view === 'signup' ? 'Create account' : 'Reset password'
43
48
  const subtitle =
@@ -53,11 +58,18 @@ export function LoginPage({
53
58
  onForgotPassword={() => setView('recovery')}
54
59
  showOAuth={showOAuth}
55
60
  oauthProviders={oauthProviders}
61
+ initialEmail={email}
62
+ onEmailChange={setEmail}
56
63
  />
57
64
  ) : view === 'signup' ? (
58
65
  <SignupForm onSuccess={onSuccess} />
59
66
  ) : (
60
- <ForgotPasswordForm redirectTo={resetPasswordUrl} onBackToLogin={() => setView('login')} />
67
+ <ForgotPasswordForm
68
+ redirectTo={resetPasswordUrl}
69
+ onBackToLogin={() => setView('login')}
70
+ initialEmail={email}
71
+ onEmailChange={setEmail}
72
+ />
61
73
  )
62
74
  const switcher =
63
75
  view === 'login' ? (
@@ -190,16 +202,8 @@ export interface ResetPasswordPageProps {
190
202
  onSuccess?: () => void
191
203
  }
192
204
 
205
+ /** Kept for apps that route `/auth/reset-password` themselves. The shell no
206
+ * longer needs a route: SetPasswordPage is mounted by usePasswordSetupGate. */
193
207
  export function ResetPasswordPage({ onSuccess }: ResetPasswordPageProps) {
194
- return (
195
- <div className="flex min-h-screen items-center justify-center bg-background p-4">
196
- <div className="w-full max-w-md rounded-2xl border bg-card p-8 shadow-xl">
197
- <div className="mb-6">
198
- <h1 className="text-2xl font-bold text-foreground">Update password</h1>
199
- <p className="mt-1 text-sm text-muted-foreground">Choose a new password for your account.</p>
200
- </div>
201
- <ResetPasswordForm onSuccess={onSuccess} />
202
- </div>
203
- </div>
204
- )
208
+ return <SetPasswordPage reason="recovery" onSuccess={onSuccess} />
205
209
  }
package/src/runtime.ts CHANGED
@@ -24,8 +24,12 @@ export function resolveAuthAdapter(options: AuthPluginOptions = {}): AuthAdapter
24
24
  supabaseAnonKey: anonKey,
25
25
  supabaseClient: options.supabase?.client,
26
26
  callbackUrl: options.supabase?.callbackUrl ?? absoluteUrl(options.routes?.callback ?? '/auth/callback'),
27
+ // Only when the host asked for a specific URL. Left undefined, the adapter
28
+ // points recovery at the app root, which needs no route and no extra entry
29
+ // in Supabase's redirect allow-list.
27
30
  resetPasswordUrl:
28
- options.supabase?.resetPasswordUrl ?? absoluteUrl(options.routes?.resetPassword ?? '/auth/reset-password'),
31
+ options.supabase?.resetPasswordUrl ??
32
+ (options.routes?.resetPassword ? absoluteUrl(options.routes.resetPassword) : undefined),
29
33
  })
30
34
  }
31
35
 
@@ -50,7 +54,9 @@ export function createAuthRuntime(options: AuthPluginOptions = {}): ResolvedAuth
50
54
  routes: {
51
55
  login: options.routes?.login ?? '/login',
52
56
  callback: options.routes?.callback ?? '/auth/callback',
53
- resetPassword: options.routes?.resetPassword ?? '/auth/reset-password',
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 ?? '/',
54
60
  afterSignIn: options.routes?.afterSignIn ?? '/',
55
61
  },
56
62
  }
@@ -0,0 +1,229 @@
1
+ import * as React from 'react'
2
+ import { useAuth, readAuthUrlIntent, clearAuthUrlTokens, decidePasswordSetup } from '@fayz-ai/auth'
3
+ import { useTranslation } from '@fayz-ai/core'
4
+ import { ForgotPasswordForm } from './forms'
5
+
6
+ // ---------------------------------------------------------------------------
7
+ // Set-password surface — the one screen behind two flows:
8
+ //
9
+ // • recovery — the user clicked "forgot password" and came back on a recovery
10
+ // link. GoTrue already signed them in from the link, so all that is missing
11
+ // is `updateUser({ password })`. Without this screen they land straight in
12
+ // the app (or on the login form) and are never asked, which is exactly the
13
+ // "the link does nothing" bug.
14
+ //
15
+ // • invite — the user was added to an organisation. The invite is a magic link,
16
+ // so the account exists with NO password: unless they choose one here, every
17
+ // future sign-in needs another e-mail.
18
+ //
19
+ // Mounted by the shell above its auth gate, driven by usePasswordSetupGate().
20
+ // ---------------------------------------------------------------------------
21
+
22
+ export type SetPasswordReason = 'recovery' | 'invite'
23
+
24
+ const MIN_LENGTH = 8
25
+
26
+ function fieldClass() {
27
+ return 'h-10 w-full rounded-md 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'
28
+ }
29
+
30
+ function buttonClass() {
31
+ 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'
32
+ }
33
+
34
+ function useTr() {
35
+ const t = useTranslation()
36
+ return React.useCallback(
37
+ (key: string, fallback: string, params?: Record<string, string | number>) => {
38
+ const value = t(key, params)
39
+ return !value || value === key ? fallback : value
40
+ },
41
+ [t],
42
+ )
43
+ }
44
+
45
+ export interface PasswordSetupGate {
46
+ /** null when nothing is pending and the shell should render normally. */
47
+ reason: SetPasswordReason | null
48
+ /** The link is dead (already used / expired) — offer a fresh one instead. */
49
+ expired: boolean
50
+ /** Still resolving the session the link carries. */
51
+ checking: boolean
52
+ /** Called by the screen once the password is set (or the user gives up). */
53
+ complete: () => void
54
+ }
55
+
56
+ /**
57
+ * Decides whether the user owes us a password before they see the app.
58
+ *
59
+ * The URL intent is read from a snapshot taken at module load: supabase-js wipes
60
+ * the token fragment as soon as it initialises, so the reason the user is here is
61
+ * gone by the time React renders.
62
+ */
63
+ export function usePasswordSetupGate(): PasswordSetupGate {
64
+ const { user, isLoading, isAuthenticated } = useAuth()
65
+ const [done, setDone] = React.useState(false)
66
+ const intent = React.useMemo(() => readAuthUrlIntent(), [])
67
+
68
+ const complete = React.useCallback(() => {
69
+ clearAuthUrlTokens()
70
+ setDone(true)
71
+ }, [])
72
+
73
+ if (done) return { reason: null, expired: false, checking: false, complete }
74
+
75
+ const decision = decidePasswordSetup({
76
+ intent,
77
+ isLoading,
78
+ isAuthenticated,
79
+ mustSetPassword: user?.mustSetPassword,
80
+ })
81
+ return { ...decision, complete }
82
+ }
83
+
84
+ export interface SetPasswordPageProps {
85
+ reason: SetPasswordReason
86
+ appName?: string
87
+ logo?: React.ReactNode
88
+ /** Show the "ask for a new link" form instead of the password fields. */
89
+ expired?: boolean
90
+ /** Waiting on the link's session — renders a quiet placeholder. */
91
+ checking?: boolean
92
+ onSuccess?: () => void
93
+ }
94
+
95
+ export function SetPasswordPage({
96
+ reason,
97
+ appName = 'App',
98
+ logo,
99
+ expired,
100
+ checking,
101
+ onSuccess,
102
+ }: SetPasswordPageProps) {
103
+ const tr = useTr()
104
+ const { user, updatePassword, signOut, error, isLoading } = useAuth()
105
+ const [password, setPassword] = React.useState('')
106
+ const [confirmPassword, setConfirmPassword] = React.useState('')
107
+ const [localError, setLocalError] = React.useState<string | null>(null)
108
+ const [busy, setBusy] = React.useState(false)
109
+ const disabled = busy || isLoading
110
+
111
+ const invite = reason === 'invite'
112
+ const title = invite
113
+ ? tr('auth.setPassword.welcomeTitle', `Welcome to ${appName}`, { appName })
114
+ : tr('auth.setPassword.recoveryTitle', 'Choose a new password')
115
+ const subtitle = invite
116
+ ? tr('auth.setPassword.welcomeSubtitle', 'Choose a password to finish setting up your access.')
117
+ : tr('auth.setPassword.recoverySubtitle', 'Set a new password to get back into your account.')
118
+
119
+ async function submit(event: React.FormEvent) {
120
+ event.preventDefault()
121
+ setLocalError(null)
122
+ if (password.length < MIN_LENGTH) {
123
+ setLocalError(tr('auth.setPassword.tooShort', `Password must be at least ${MIN_LENGTH} characters.`))
124
+ return
125
+ }
126
+ if (password !== confirmPassword) {
127
+ setLocalError(tr('auth.setPassword.mismatch', 'Passwords do not match.'))
128
+ return
129
+ }
130
+ setBusy(true)
131
+ try {
132
+ await updatePassword(password)
133
+ onSuccess?.()
134
+ } catch {
135
+ // useAuth already surfaced it; keep the user on the form.
136
+ } finally {
137
+ setBusy(false)
138
+ }
139
+ }
140
+
141
+ return (
142
+ <div className="flex min-h-screen items-center justify-center bg-sidebar p-4">
143
+ <div className="w-full max-w-md rounded-2xl border border-border/50 bg-card p-8 shadow-2xl sm:p-10">
144
+ {logo && <div className="mb-6 flex justify-center">{logo}</div>}
145
+ {checking ? (
146
+ <p className="py-6 text-center text-sm text-muted-foreground">
147
+ {tr('auth.setPassword.checking', 'Checking your link...')}
148
+ </p>
149
+ ) : expired ? (
150
+ <>
151
+ <div className="mb-6">
152
+ <h1 className="text-2xl font-bold text-foreground">
153
+ {tr('auth.setPassword.expiredTitle', 'This link has expired')}
154
+ </h1>
155
+ <p className="mt-1 text-sm text-muted-foreground">
156
+ {tr(
157
+ 'auth.setPassword.expiredSubtitle',
158
+ 'Reset links can only be used once. Enter your e-mail and we will send a new one.',
159
+ )}
160
+ </p>
161
+ </div>
162
+ <ForgotPasswordForm
163
+ initialEmail={user?.email}
164
+ submitLabel={tr('auth.setPassword.sendNewLink', 'Send new link')}
165
+ sendingLabel={tr('auth.setPassword.sending', 'Sending...')}
166
+ sentLabel={tr('auth.setPassword.sent', 'Check your inbox — a new link is on the way.')}
167
+ emailLabel={tr('auth.setPassword.email', 'E-mail')}
168
+ backLabel={tr('auth.setPassword.backToLogin', 'Back to sign in')}
169
+ onBackToLogin={onSuccess}
170
+ />
171
+ </>
172
+ ) : (
173
+ <>
174
+ <div className="mb-6">
175
+ <h1 className="text-2xl font-bold text-foreground">{title}</h1>
176
+ <p className="mt-1 text-sm text-muted-foreground">{subtitle}</p>
177
+ </div>
178
+ <form onSubmit={submit} className="space-y-4">
179
+ <label className="block space-y-1.5 text-sm font-medium">
180
+ <span>{tr('auth.setPassword.newPassword', 'New password')}</span>
181
+ <input
182
+ className={fieldClass()}
183
+ type="password"
184
+ autoComplete="new-password"
185
+ autoFocus
186
+ required
187
+ value={password}
188
+ onChange={(e) => setPassword(e.target.value)}
189
+ disabled={disabled}
190
+ />
191
+ </label>
192
+ <label className="block space-y-1.5 text-sm font-medium">
193
+ <span>{tr('auth.setPassword.confirmPassword', 'Confirm password')}</span>
194
+ <input
195
+ className={fieldClass()}
196
+ type="password"
197
+ autoComplete="new-password"
198
+ required
199
+ value={confirmPassword}
200
+ onChange={(e) => setConfirmPassword(e.target.value)}
201
+ disabled={disabled}
202
+ />
203
+ </label>
204
+ {(localError || error) && (
205
+ <p className="text-sm text-destructive">{localError ?? error?.message}</p>
206
+ )}
207
+ <button className={buttonClass()} type="submit" disabled={disabled}>
208
+ {disabled
209
+ ? tr('auth.setPassword.saving', 'Saving...')
210
+ : tr('auth.setPassword.submit', 'Save password')}
211
+ </button>
212
+ </form>
213
+ {/* An invitee who does not want to continue needs a way out that does
214
+ not leave them stuck on this screen with a live session. */}
215
+ <button
216
+ type="button"
217
+ className="mt-4 w-full text-center text-sm text-muted-foreground hover:text-foreground"
218
+ onClick={() => {
219
+ void signOut().finally(() => onSuccess?.())
220
+ }}
221
+ >
222
+ {tr('auth.setPassword.backToLogin', 'Back to sign in')}
223
+ </button>
224
+ </>
225
+ )}
226
+ </div>
227
+ </div>
228
+ )
229
+ }