@fayz-ai/auth 0.47.0 → 0.48.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (136) hide show
  1. package/README.md +4 -0
  2. package/dist/chunk-2MO4QTQA.js +78 -0
  3. package/dist/chunk-2MO4QTQA.js.map +1 -0
  4. package/dist/chunk-2S7KVJQO.js +18 -0
  5. package/dist/chunk-2S7KVJQO.js.map +1 -0
  6. package/dist/chunk-4HVM2UJS.js +30 -0
  7. package/dist/chunk-4HVM2UJS.js.map +1 -0
  8. package/dist/chunk-55RFOMW5.js +15 -0
  9. package/dist/chunk-55RFOMW5.js.map +1 -0
  10. package/dist/chunk-7JYNJQJJ.js +138 -0
  11. package/dist/chunk-7JYNJQJJ.js.map +1 -0
  12. package/dist/chunk-BGCCXJJA.js +174 -0
  13. package/dist/chunk-BGCCXJJA.js.map +1 -0
  14. package/dist/chunk-CV4LQYNX.js +109 -0
  15. package/dist/chunk-CV4LQYNX.js.map +1 -0
  16. package/dist/chunk-ERIPMYL2.js +137 -0
  17. package/dist/chunk-ERIPMYL2.js.map +1 -0
  18. package/dist/chunk-HKILBDG2.js +158 -0
  19. package/dist/chunk-HKILBDG2.js.map +1 -0
  20. package/dist/chunk-KLQDHFVS.js +11 -0
  21. package/dist/chunk-KLQDHFVS.js.map +1 -0
  22. package/dist/chunk-OI74ER2Z.js +31 -0
  23. package/dist/chunk-OI74ER2Z.js.map +1 -0
  24. package/dist/chunk-Q6DFI35B.js +187 -0
  25. package/dist/chunk-Q6DFI35B.js.map +1 -0
  26. package/dist/chunk-QJRTW7Q3.js +90 -0
  27. package/dist/chunk-QJRTW7Q3.js.map +1 -0
  28. package/dist/chunk-REU4D5UF.js +44 -0
  29. package/dist/chunk-REU4D5UF.js.map +1 -0
  30. package/dist/chunk-SMFXGZN7.js +18 -0
  31. package/dist/chunk-SMFXGZN7.js.map +1 -0
  32. package/dist/chunk-W35GQEGU.js +80 -0
  33. package/dist/chunk-W35GQEGU.js.map +1 -0
  34. package/dist/chunk-W7565FXD.js +64 -0
  35. package/dist/chunk-W7565FXD.js.map +1 -0
  36. package/dist/chunk-WZVZMNLB.js +48 -0
  37. package/dist/chunk-WZVZMNLB.js.map +1 -0
  38. package/dist/components/AmbassadorBubbles.d.ts +9 -0
  39. package/dist/components/AmbassadorBubbles.d.ts.map +1 -0
  40. package/dist/components/AmbassadorBubbles.js +3 -0
  41. package/dist/components/AmbassadorBubbles.js.map +1 -0
  42. package/dist/components/TrialPromise.d.ts +12 -0
  43. package/dist/components/TrialPromise.d.ts.map +1 -0
  44. package/dist/components/TrialPromise.js +3 -0
  45. package/dist/components/TrialPromise.js.map +1 -0
  46. package/dist/components/form-classes.d.ts +3 -0
  47. package/dist/components/form-classes.d.ts.map +1 -0
  48. package/dist/components/form-classes.js +3 -0
  49. package/dist/components/form-classes.js.map +1 -0
  50. package/dist/context.js +5 -0
  51. package/dist/context.js.map +1 -0
  52. package/dist/data/mock.d.ts.map +1 -0
  53. package/dist/data/mock.js +3 -0
  54. package/dist/data/mock.js.map +1 -0
  55. package/dist/data/supabase.d.ts.map +1 -0
  56. package/dist/data/supabase.js +4 -0
  57. package/dist/data/supabase.js.map +1 -0
  58. package/dist/domain/auth-config.d.ts +71 -0
  59. package/dist/domain/auth-config.d.ts.map +1 -0
  60. package/dist/domain/auth-config.js +3 -0
  61. package/dist/domain/auth-config.js.map +1 -0
  62. package/dist/domain/auth-link.d.ts +26 -0
  63. package/dist/domain/auth-link.d.ts.map +1 -0
  64. package/dist/domain/auth-link.js +3 -0
  65. package/dist/domain/auth-link.js.map +1 -0
  66. package/dist/domain/password.d.ts +5 -0
  67. package/dist/domain/password.d.ts.map +1 -0
  68. package/dist/domain/password.js +3 -0
  69. package/dist/domain/password.js.map +1 -0
  70. package/dist/index.d.ts +8 -6
  71. package/dist/index.d.ts.map +1 -1
  72. package/dist/index.js +6 -573
  73. package/dist/index.js.map +1 -1
  74. package/dist/lib/runtime.d.ts +6 -0
  75. package/dist/lib/runtime.d.ts.map +1 -0
  76. package/dist/lib/runtime.js +51 -0
  77. package/dist/lib/runtime.js.map +1 -0
  78. package/dist/lib/url-intent.d.ts +1 -25
  79. package/dist/lib/url-intent.d.ts.map +1 -1
  80. package/dist/lib/url-intent.js +3 -0
  81. package/dist/lib/url-intent.js.map +1 -0
  82. package/dist/store.js +3 -0
  83. package/dist/store.js.map +1 -0
  84. package/dist/views/AuthCallbackPage.d.ts +7 -0
  85. package/dist/views/AuthCallbackPage.d.ts.map +1 -0
  86. package/dist/views/AuthCallbackPage.js +33 -0
  87. package/dist/views/AuthCallbackPage.js.map +1 -0
  88. package/dist/views/AuthGate.d.ts +9 -0
  89. package/dist/views/AuthGate.d.ts.map +1 -0
  90. package/dist/views/AuthGate.js +28 -0
  91. package/dist/views/AuthGate.js.map +1 -0
  92. package/dist/views/ForgotPasswordForm.d.ts +18 -0
  93. package/dist/views/ForgotPasswordForm.d.ts.map +1 -0
  94. package/dist/views/ForgotPasswordForm.js +7 -0
  95. package/dist/views/ForgotPasswordForm.js.map +1 -0
  96. package/dist/views/LoginForm.d.ts +16 -0
  97. package/dist/views/LoginForm.d.ts.map +1 -0
  98. package/dist/views/LoginForm.js +8 -0
  99. package/dist/views/LoginForm.js.map +1 -0
  100. package/dist/views/LoginPage.d.ts +34 -0
  101. package/dist/views/LoginPage.d.ts.map +1 -0
  102. package/dist/views/LoginPage.js +16 -0
  103. package/dist/views/LoginPage.js.map +1 -0
  104. package/dist/views/OAuthButtons.d.ts +18 -0
  105. package/dist/views/OAuthButtons.d.ts.map +1 -0
  106. package/dist/views/OAuthButtons.js +7 -0
  107. package/dist/views/OAuthButtons.js.map +1 -0
  108. package/dist/views/ResetPasswordForm.d.ts +6 -0
  109. package/dist/views/ResetPasswordForm.d.ts.map +1 -0
  110. package/dist/views/ResetPasswordForm.js +53 -0
  111. package/dist/views/ResetPasswordForm.js.map +1 -0
  112. package/dist/views/ResetPasswordPage.d.ts +7 -0
  113. package/dist/views/ResetPasswordPage.d.ts.map +1 -0
  114. package/dist/views/ResetPasswordPage.js +16 -0
  115. package/dist/views/ResetPasswordPage.js.map +1 -0
  116. package/dist/views/SetPasswordPage.d.ts +15 -0
  117. package/dist/views/SetPasswordPage.d.ts.map +1 -0
  118. package/dist/views/SetPasswordPage.js +9 -0
  119. package/dist/views/SetPasswordPage.js.map +1 -0
  120. package/dist/views/SignupForm.d.ts +24 -0
  121. package/dist/views/SignupForm.d.ts.map +1 -0
  122. package/dist/views/SignupForm.js +9 -0
  123. package/dist/views/SignupForm.js.map +1 -0
  124. package/dist/views/VerifyEmailNotice.d.ts +15 -0
  125. package/dist/views/VerifyEmailNotice.d.ts.map +1 -0
  126. package/dist/views/VerifyEmailNotice.js +6 -0
  127. package/dist/views/VerifyEmailNotice.js.map +1 -0
  128. package/dist/views/usePasswordSetupGate.d.ts +20 -0
  129. package/dist/views/usePasswordSetupGate.d.ts.map +1 -0
  130. package/dist/views/usePasswordSetupGate.js +27 -0
  131. package/dist/views/usePasswordSetupGate.js.map +1 -0
  132. package/package.json +14 -3
  133. package/dist/adapters/mock.d.ts.map +0 -1
  134. package/dist/adapters/supabase.d.ts.map +0 -1
  135. /package/dist/{adapters → data}/mock.d.ts +0 -0
  136. /package/dist/{adapters → data}/supabase.d.ts +0 -0
@@ -0,0 +1,187 @@
1
+ import { useAuthStore } from './chunk-OI74ER2Z.js';
2
+ import { readAppHandoff, clearAuthUrlTokens } from './chunk-2MO4QTQA.js';
3
+ import { createContext, useRef, useEffect, useContext } from 'react';
4
+ import { jsx } from 'react/jsx-runtime';
5
+
6
+ var AuthContext = createContext(null);
7
+ function AuthProvider({ adapter, children }) {
8
+ const { setSession, setLoading, setError, setPendingVerification, reset } = useAuthStore();
9
+ const adapterRef = useRef(adapter);
10
+ adapterRef.current = adapter;
11
+ useEffect(() => {
12
+ let unsubscribe;
13
+ async function init() {
14
+ try {
15
+ setLoading(true);
16
+ const handoff = readAppHandoff();
17
+ const adopt = adapterRef.current.adoptSession;
18
+ let adopted = null;
19
+ if (handoff && typeof adopt === "function") {
20
+ adopted = await adopt.call(adapterRef.current, handoff.accessToken, handoff.refreshToken);
21
+ clearAuthUrlTokens();
22
+ }
23
+ const result = adopted ? { session: adopted } : await adapterRef.current.getSession();
24
+ setSession(result?.session ?? null);
25
+ } catch (err) {
26
+ setError(err instanceof Error ? err : new Error(String(err)));
27
+ } finally {
28
+ setLoading(false);
29
+ }
30
+ unsubscribe = adapterRef.current.onAuthStateChange((user) => {
31
+ if (!user) {
32
+ reset();
33
+ setLoading(false);
34
+ return;
35
+ }
36
+ void adapterRef.current.getSession().then((result) => setSession(result?.session ?? null)).catch(() => {
37
+ });
38
+ });
39
+ }
40
+ void init();
41
+ return () => {
42
+ unsubscribe?.();
43
+ };
44
+ }, []);
45
+ const value = {
46
+ async signIn(email, password) {
47
+ setError(null);
48
+ try {
49
+ const session = await adapterRef.current.signIn(email, password);
50
+ setSession(session);
51
+ return session;
52
+ } catch (err) {
53
+ const error = err instanceof Error ? err : new Error(String(err));
54
+ setError(error);
55
+ throw error;
56
+ }
57
+ },
58
+ async signUp(email, password, fullName) {
59
+ setError(null);
60
+ try {
61
+ const session = await adapterRef.current.signUp(email, password, fullName);
62
+ if (!session.accessToken) {
63
+ setPendingVerification({ email });
64
+ return session;
65
+ }
66
+ setSession(session);
67
+ return session;
68
+ } catch (err) {
69
+ const error = err instanceof Error ? err : new Error(String(err));
70
+ setError(error);
71
+ throw error;
72
+ }
73
+ },
74
+ async signOut() {
75
+ setError(null);
76
+ try {
77
+ await adapterRef.current.signOut();
78
+ reset();
79
+ setLoading(false);
80
+ } catch (err) {
81
+ const error = err instanceof Error ? err : new Error(String(err));
82
+ setError(error);
83
+ throw error;
84
+ }
85
+ },
86
+ async signInWithOAuth(provider) {
87
+ setError(null);
88
+ try {
89
+ await adapterRef.current.signInWithOAuth(provider);
90
+ } catch (err) {
91
+ const error = err instanceof Error ? err : new Error(String(err));
92
+ setError(error);
93
+ throw error;
94
+ }
95
+ },
96
+ async resetPassword(email, options) {
97
+ setError(null);
98
+ try {
99
+ await adapterRef.current.resetPassword(email, options);
100
+ } catch (err) {
101
+ const error = err instanceof Error ? err : new Error(String(err));
102
+ setError(error);
103
+ throw error;
104
+ }
105
+ },
106
+ async updatePassword(password) {
107
+ setError(null);
108
+ try {
109
+ const session = await adapterRef.current.updatePassword?.(password);
110
+ if (session) setSession(session);
111
+ return session;
112
+ } catch (err) {
113
+ const error = err instanceof Error ? err : new Error(String(err));
114
+ setError(error);
115
+ throw error;
116
+ }
117
+ },
118
+ async handleCallback(url) {
119
+ setError(null);
120
+ try {
121
+ const session = await adapterRef.current.handleCallback?.(url) ?? null;
122
+ if (session) setSession(session);
123
+ return session;
124
+ } catch (err) {
125
+ const error = err instanceof Error ? err : new Error(String(err));
126
+ setError(error);
127
+ throw error;
128
+ }
129
+ },
130
+ async inviteUser(email, options) {
131
+ setError(null);
132
+ try {
133
+ await adapterRef.current.inviteUser?.(email, options);
134
+ } catch (err) {
135
+ const error = err instanceof Error ? err : new Error(String(err));
136
+ setError(error);
137
+ throw error;
138
+ }
139
+ },
140
+ async resendConfirmation(email, options) {
141
+ setError(null);
142
+ if (!adapterRef.current.resendConfirmation) return false;
143
+ try {
144
+ await adapterRef.current.resendConfirmation(email, options);
145
+ return true;
146
+ } catch (err) {
147
+ const error = err instanceof Error ? err : new Error(String(err));
148
+ setError(error);
149
+ throw error;
150
+ }
151
+ },
152
+ clearPendingVerification() {
153
+ setPendingVerification(null);
154
+ setError(null);
155
+ }
156
+ };
157
+ return /* @__PURE__ */ jsx(AuthContext.Provider, { value, children });
158
+ }
159
+ function useAuth() {
160
+ const ctx = useContext(AuthContext);
161
+ if (!ctx) {
162
+ throw new Error("useAuth must be used inside <AuthProvider>");
163
+ }
164
+ const { user, session, isLoading, isAuthenticated, error, pendingVerification } = useAuthStore();
165
+ return {
166
+ user,
167
+ session,
168
+ isLoading,
169
+ isAuthenticated,
170
+ error,
171
+ pendingVerification,
172
+ signIn: ctx.signIn,
173
+ signUp: ctx.signUp,
174
+ signOut: ctx.signOut,
175
+ signInWithOAuth: ctx.signInWithOAuth,
176
+ resetPassword: ctx.resetPassword,
177
+ updatePassword: ctx.updatePassword,
178
+ handleCallback: ctx.handleCallback,
179
+ inviteUser: ctx.inviteUser,
180
+ resendConfirmation: ctx.resendConfirmation,
181
+ clearPendingVerification: ctx.clearPendingVerification
182
+ };
183
+ }
184
+
185
+ export { AuthProvider, useAuth };
186
+ //# sourceMappingURL=chunk-Q6DFI35B.js.map
187
+ //# sourceMappingURL=chunk-Q6DFI35B.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/context.tsx"],"names":[],"mappings":"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","file":"chunk-Q6DFI35B.js","sourcesContent":["import React, { createContext, useContext, useEffect, useRef } from 'react'\nimport type { AuthAdapter, AuthProvider as OAuthProvider, AuthSession } from '@fayz-ai/core'\nimport { useAuthStore } from './store'\nimport { readAppHandoff, clearAuthUrlTokens } from './lib/url-intent'\n\n/** Adapters that can adopt a session a sibling app handed over. Optional by\n * design: the mock adapter and any third-party one simply do not have it. */\ninterface HandoffCapableAdapter {\n adoptSession(accessToken: string, refreshToken: string): Promise<AuthSession | null>\n}\n\n// ---------------------------------------------------------------------------\n// Context\n// ---------------------------------------------------------------------------\n\ninterface AuthContextValue {\n signIn: (email: string, password: string) => Promise<AuthSession>\n signUp: (email: string, password: string, fullName: string) => Promise<AuthSession>\n signOut: () => Promise<void>\n signInWithOAuth: (provider: OAuthProvider) => Promise<void>\n resetPassword: (email: string, options?: { redirectTo?: string }) => Promise<void>\n updatePassword: (password: string) => Promise<AuthSession | void>\n handleCallback: (url?: string) => Promise<AuthSession | null>\n inviteUser: (email: string, options?: { redirectTo?: string; data?: Record<string, unknown> }) => Promise<void>\n /** Re-send the sign-up confirmation. Resolves `false` when the adapter has no such path. */\n resendConfirmation: (email: string, options?: { redirectTo?: string }) => Promise<boolean>\n /** Abandon the pending sign-up so the login screen goes back to its form. */\n clearPendingVerification: () => void\n}\n\nconst AuthContext = createContext<AuthContextValue | null>(null)\n\n// ---------------------------------------------------------------------------\n// Provider\n// ---------------------------------------------------------------------------\n\nexport interface AuthProviderProps {\n adapter: AuthAdapter\n children: React.ReactNode\n}\n\nexport function AuthProvider({ adapter, children }: AuthProviderProps) {\n const { setSession, setLoading, setError, setPendingVerification, reset } = useAuthStore()\n\n // Keep a stable ref to the adapter so the effect only runs once on mount\n const adapterRef = useRef(adapter)\n adapterRef.current = adapter\n\n useEffect(() => {\n let unsubscribe: (() => void) | undefined\n\n async function init() {\n try {\n setLoading(true)\n\n // Arriving from a sibling app's switcher: adopt the session it handed\n // over BEFORE asking for our own, because this origin has none. Adapters\n // without the capability (mock, tests) simply fall through, and a\n // handoff GoTrue rejects also falls through — to the login screen, which\n // is the correct answer for tokens that do not verify.\n const handoff = readAppHandoff()\n const adopt = (adapterRef.current as Partial<HandoffCapableAdapter>).adoptSession\n let adopted: AuthSession | null = null\n if (handoff && typeof adopt === 'function') {\n adopted = await adopt.call(adapterRef.current, handoff.accessToken, handoff.refreshToken)\n clearAuthUrlTokens()\n }\n\n // Falling through on a failed adoption is deliberate: getSession() then\n // finds nothing and the user meets the login screen, which is the right\n // answer for tokens that did not verify.\n const result = adopted ? { session: adopted } : await adapterRef.current.getSession()\n setSession(result?.session ?? null)\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)))\n } finally {\n setLoading(false)\n }\n\n // Subscribe to future auth state changes\n unsubscribe = adapterRef.current.onAuthStateChange((user) => {\n if (!user) {\n reset()\n // Keep isLoading false after an explicit sign-out\n setLoading(false)\n return\n }\n // Positive change (adapter-driven sign-in — e.g. an external callback,\n // another tab, or a direct adapter.signUp bridge) — sync the session so\n // consumers reflect it even when the call didn't go through ctx.signIn.\n void adapterRef.current.getSession().then((result) => setSession(result?.session ?? null)).catch(() => {})\n })\n }\n\n void init()\n\n return () => {\n unsubscribe?.()\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n\n const value: AuthContextValue = {\n async signIn(email, password) {\n setError(null)\n try {\n const session = await adapterRef.current.signIn(email, password)\n setSession(session)\n return session\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err))\n setError(error)\n throw error\n }\n },\n\n async signUp(email, password, fullName) {\n setError(null)\n try {\n const session = await adapterRef.current.signUp(email, password, fullName)\n // A project with \"confirm email\" on returns a session with no access\n // token — the account exists but cannot do anything yet. Storing it as\n // a session marked the user authenticated, the AuthGate waved them into\n // the app, and every request 401'd. Park it as pending instead.\n if (!session.accessToken) {\n setPendingVerification({ email })\n return session\n }\n setSession(session)\n return session\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err))\n setError(error)\n throw error\n }\n },\n\n async signOut() {\n setError(null)\n try {\n await adapterRef.current.signOut()\n reset()\n setLoading(false)\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err))\n setError(error)\n throw error\n }\n },\n\n async signInWithOAuth(provider) {\n setError(null)\n try {\n await adapterRef.current.signInWithOAuth(provider)\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err))\n setError(error)\n throw error\n }\n },\n\n async resetPassword(email, options) {\n setError(null)\n try {\n await adapterRef.current.resetPassword(email, options)\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err))\n setError(error)\n throw error\n }\n },\n\n async updatePassword(password) {\n setError(null)\n try {\n const session = await adapterRef.current.updatePassword?.(password)\n if (session) setSession(session)\n return session\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err))\n setError(error)\n throw error\n }\n },\n\n async handleCallback(url) {\n setError(null)\n try {\n const session = await adapterRef.current.handleCallback?.(url) ?? null\n if (session) setSession(session)\n return session\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err))\n setError(error)\n throw error\n }\n },\n\n async inviteUser(email, options) {\n setError(null)\n try {\n await adapterRef.current.inviteUser?.(email, options)\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err))\n setError(error)\n throw error\n }\n },\n\n async resendConfirmation(email, options) {\n setError(null)\n if (!adapterRef.current.resendConfirmation) return false\n try {\n await adapterRef.current.resendConfirmation(email, options)\n return true\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err))\n setError(error)\n throw error\n }\n },\n\n clearPendingVerification() {\n setPendingVerification(null)\n setError(null)\n },\n }\n\n return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>\n}\n\n// ---------------------------------------------------------------------------\n// Hook\n// ---------------------------------------------------------------------------\n\nexport function useAuth() {\n const ctx = useContext(AuthContext)\n if (!ctx) {\n throw new Error('useAuth must be used inside <AuthProvider>')\n }\n\n const { user, session, isLoading, isAuthenticated, error, pendingVerification } = useAuthStore()\n\n return {\n user,\n session,\n isLoading,\n isAuthenticated,\n error,\n pendingVerification,\n signIn: ctx.signIn,\n signUp: ctx.signUp,\n signOut: ctx.signOut,\n signInWithOAuth: ctx.signInWithOAuth,\n resetPassword: ctx.resetPassword,\n updatePassword: ctx.updatePassword,\n handleCallback: ctx.handleCallback,\n inviteUser: ctx.inviteUser,\n resendConfirmation: ctx.resendConfirmation,\n clearPendingVerification: ctx.clearPendingVerification,\n }\n}\n"]}
@@ -0,0 +1,90 @@
1
+ import { useAuth } from './chunk-Q6DFI35B.js';
2
+ import * as React from 'react';
3
+ import { MailCheck } from 'lucide-react';
4
+ import { tl } from '@fayz-ai/core';
5
+ import { jsxs, jsx } from 'react/jsx-runtime';
6
+
7
+ var RESEND_COOLDOWN_SECONDS = 60;
8
+ function VerifyEmailNotice({ email, onUseAnotherEmail }) {
9
+ const { resendConfirmation, clearPendingVerification, error } = useAuth();
10
+ const [cooldown, setCooldown] = React.useState(0);
11
+ const [sent, setSent] = React.useState(false);
12
+ const [busy, setBusy] = React.useState(false);
13
+ const [unsupported, setUnsupported] = React.useState(false);
14
+ React.useEffect(() => {
15
+ if (cooldown <= 0) return;
16
+ const timer = setTimeout(() => setCooldown((s) => s - 1), 1e3);
17
+ return () => clearTimeout(timer);
18
+ }, [cooldown]);
19
+ const resend = async () => {
20
+ setBusy(true);
21
+ setSent(false);
22
+ try {
23
+ const ok = await resendConfirmation(email);
24
+ if (!ok) {
25
+ setUnsupported(true);
26
+ return;
27
+ }
28
+ setSent(true);
29
+ setCooldown(RESEND_COOLDOWN_SECONDS);
30
+ } catch {
31
+ } finally {
32
+ setBusy(false);
33
+ }
34
+ };
35
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-6 text-center", children: [
36
+ /* @__PURE__ */ jsx("div", { className: "mx-auto flex h-12 w-12 items-center justify-center rounded-full bg-primary/10", children: /* @__PURE__ */ jsx(MailCheck, { className: "h-6 w-6 text-primary" }) }),
37
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
38
+ /* @__PURE__ */ jsx("h1", { className: "text-2xl font-bold text-foreground", children: tl("Check your email", "Verifique seu e-mail") }),
39
+ /* @__PURE__ */ jsxs("p", { className: "text-sm leading-relaxed text-muted-foreground", children: [
40
+ tl("We sent a confirmation link to", "Enviamos um link de confirma\xE7\xE3o para"),
41
+ " ",
42
+ /* @__PURE__ */ jsx("span", { className: "font-medium text-foreground", children: email }),
43
+ ".",
44
+ " ",
45
+ tl(
46
+ "Open it to finish creating your account.",
47
+ "Abra o link para terminar de criar sua conta."
48
+ )
49
+ ] }),
50
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: tl(
51
+ "Not there? It may have landed in spam or promotions.",
52
+ "N\xE3o chegou? Pode ter ca\xEDdo no spam ou em promo\xE7\xF5es."
53
+ ) })
54
+ ] }),
55
+ sent && /* @__PURE__ */ jsx("p", { className: "text-sm text-emerald-600", children: tl("Link sent again.", "Link reenviado.") }),
56
+ unsupported && /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: tl(
57
+ "Resending is not available here \u2014 try signing up again in a moment.",
58
+ "O reenvio n\xE3o est\xE1 dispon\xEDvel aqui \u2014 tente cadastrar de novo em instantes."
59
+ ) }),
60
+ error && /* @__PURE__ */ jsx("p", { className: "text-sm text-destructive", children: error.message }),
61
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
62
+ /* @__PURE__ */ jsx(
63
+ "button",
64
+ {
65
+ type: "button",
66
+ onClick: () => void resend(),
67
+ disabled: busy || cooldown > 0,
68
+ className: "inline-flex h-10 w-full items-center justify-center rounded-input border border-input bg-background px-4 text-sm font-medium transition-colors hover:bg-muted disabled:pointer-events-none disabled:opacity-50",
69
+ children: cooldown > 0 ? tl(`Resend in ${cooldown}s`, `Reenviar em ${cooldown}s`) : busy ? tl("Sending...", "Enviando...") : tl("Resend the link", "Reenviar o link")
70
+ }
71
+ ),
72
+ /* @__PURE__ */ jsx(
73
+ "button",
74
+ {
75
+ type: "button",
76
+ onClick: () => {
77
+ clearPendingVerification();
78
+ onUseAnotherEmail?.();
79
+ },
80
+ className: "text-sm font-medium text-primary hover:underline",
81
+ children: tl("Use a different email", "Usar outro e-mail")
82
+ }
83
+ )
84
+ ] })
85
+ ] });
86
+ }
87
+
88
+ export { VerifyEmailNotice };
89
+ //# sourceMappingURL=chunk-QJRTW7Q3.js.map
90
+ //# sourceMappingURL=chunk-QJRTW7Q3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/views/VerifyEmailNotice.tsx"],"names":[],"mappings":"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","file":"chunk-QJRTW7Q3.js","sourcesContent":["import * as React from 'react'\nimport { MailCheck } from 'lucide-react'\nimport { useAuth } from '../context'\nimport { tl } from '@fayz-ai/core'\n\n/** How long before the resend button is offered again. */\nconst RESEND_COOLDOWN_SECONDS = 60\n\nexport interface VerifyEmailNoticeProps {\n email: string\n /** Back to the sign-up form with the pending account abandoned. */\n onUseAnotherEmail?: () => void\n}\n\n/**\n * \"We sent you a link.\"\n *\n * The screen that has to exist for a confirm-email project: sign-up succeeds,\n * but the account has no session until the link is clicked. Without it the flow\n * ended on a form that appeared to do nothing.\n */\nexport function VerifyEmailNotice({ email, onUseAnotherEmail }: VerifyEmailNoticeProps) {\n const { resendConfirmation, clearPendingVerification, error } = useAuth()\n const [cooldown, setCooldown] = React.useState(0)\n const [sent, setSent] = React.useState(false)\n const [busy, setBusy] = React.useState(false)\n const [unsupported, setUnsupported] = React.useState(false)\n\n React.useEffect(() => {\n if (cooldown <= 0) return\n const timer = setTimeout(() => setCooldown((s) => s - 1), 1000)\n return () => clearTimeout(timer)\n }, [cooldown])\n\n const resend = async () => {\n setBusy(true)\n setSent(false)\n try {\n const ok = await resendConfirmation(email)\n if (!ok) { setUnsupported(true); return }\n setSent(true)\n setCooldown(RESEND_COOLDOWN_SECONDS)\n } catch {\n // The message is already in the auth store's `error` and rendered below.\n } finally {\n setBusy(false)\n }\n }\n\n return (\n <div className=\"space-y-6 text-center\">\n <div className=\"mx-auto flex h-12 w-12 items-center justify-center rounded-full bg-primary/10\">\n <MailCheck className=\"h-6 w-6 text-primary\" />\n </div>\n <div className=\"space-y-2\">\n <h1 className=\"text-2xl font-bold text-foreground\">\n {tl('Check your email', 'Verifique seu e-mail')}\n </h1>\n <p className=\"text-sm leading-relaxed text-muted-foreground\">\n {tl('We sent a confirmation link to', 'Enviamos um link de confirmação para')}{' '}\n <span className=\"font-medium text-foreground\">{email}</span>.{' '}\n {tl(\n 'Open it to finish creating your account.',\n 'Abra o link para terminar de criar sua conta.',\n )}\n </p>\n <p className=\"text-xs text-muted-foreground\">\n {tl(\n 'Not there? It may have landed in spam or promotions.',\n 'Não chegou? Pode ter caído no spam ou em promoções.',\n )}\n </p>\n </div>\n\n {sent && (\n <p className=\"text-sm text-emerald-600\">{tl('Link sent again.', 'Link reenviado.')}</p>\n )}\n {unsupported && (\n <p className=\"text-sm text-muted-foreground\">\n {tl(\n 'Resending is not available here — try signing up again in a moment.',\n 'O reenvio não está disponível aqui — tente cadastrar de novo em instantes.',\n )}\n </p>\n )}\n {error && <p className=\"text-sm text-destructive\">{error.message}</p>}\n\n <div className=\"space-y-2\">\n <button\n type=\"button\"\n onClick={() => void resend()}\n disabled={busy || cooldown > 0}\n className=\"inline-flex h-10 w-full items-center justify-center rounded-input border border-input bg-background px-4 text-sm font-medium transition-colors hover:bg-muted disabled:pointer-events-none disabled:opacity-50\"\n >\n {cooldown > 0\n ? tl(`Resend in ${cooldown}s`, `Reenviar em ${cooldown}s`)\n : busy\n ? tl('Sending...', 'Enviando...')\n : tl('Resend the link', 'Reenviar o link')}\n </button>\n <button\n type=\"button\"\n onClick={() => { clearPendingVerification(); onUseAnotherEmail?.() }}\n className=\"text-sm font-medium text-primary hover:underline\"\n >\n {tl('Use a different email', 'Usar outro e-mail')}\n </button>\n </div>\n </div>\n )\n}\n"]}
@@ -0,0 +1,44 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+
3
+ // src/components/AmbassadorBubbles.tsx
4
+ var FLOAT_STYLES = `
5
+ @keyframes fayz-amb-drift {
6
+ 0%, 100% { transform: translateY(0); }
7
+ 50% { transform: translateY(-2px); }
8
+ }
9
+ @media (prefers-reduced-motion: reduce) {
10
+ .fayz-amb-avatar { animation: none !important; }
11
+ }
12
+ `;
13
+ function AmbassadorBubbles({ ambassadors, label }) {
14
+ const items = (ambassadors ?? []).filter((a) => a && typeof a.image === "string" && a.image.trim() !== "");
15
+ if (items.length === 0) return null;
16
+ const shown = items.slice(0, 5);
17
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
18
+ /* @__PURE__ */ jsx("style", { children: FLOAT_STYLES }),
19
+ /* @__PURE__ */ jsx("div", { className: "flex -space-x-2", children: shown.map((ambassador, index) => /* @__PURE__ */ jsx(
20
+ "div",
21
+ {
22
+ title: ambassador.role ? `${ambassador.name} \xB7 ${ambassador.role}` : ambassador.name,
23
+ 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",
24
+ style: { animation: `fayz-amb-drift 4s ease-in-out ${index * 0.4}s infinite` },
25
+ children: /* @__PURE__ */ jsx(
26
+ "img",
27
+ {
28
+ src: ambassador.image,
29
+ alt: ambassador.name,
30
+ className: "h-full w-full object-cover",
31
+ loading: "lazy",
32
+ draggable: false
33
+ }
34
+ )
35
+ },
36
+ `${ambassador.name}-${index}`
37
+ )) }),
38
+ label ? /* @__PURE__ */ jsx("p", { className: "text-xs font-medium text-sidebar-foreground/80", children: label }) : null
39
+ ] });
40
+ }
41
+
42
+ export { AmbassadorBubbles };
43
+ //# sourceMappingURL=chunk-REU4D5UF.js.map
44
+ //# sourceMappingURL=chunk-REU4D5UF.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/AmbassadorBubbles.tsx"],"names":[],"mappings":";;;AAeA,IAAM,YAAA,GAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AAgBd,SAAS,iBAAA,CAAkB,EAAE,WAAA,EAAa,KAAA,EAAM,EAA2B;AAChF,EAAA,MAAM,SAAS,WAAA,IAAe,EAAC,EAAG,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,IAAK,OAAO,CAAA,CAAE,UAAU,QAAA,IAAY,CAAA,CAAE,KAAA,CAAM,IAAA,OAAW,EAAE,CAAA;AACzG,EAAA,IAAI,KAAA,CAAM,MAAA,KAAW,CAAA,EAAG,OAAO,IAAA;AAC/B,EAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,KAAA,CAAM,CAAA,EAAG,CAAC,CAAA;AAE9B,EAAA,uBACE,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,yBAAA,EACb,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,WAAO,QAAA,EAAA,YAAA,EAAa,CAAA;AAAA,oBACrB,GAAA,CAAC,SAAI,SAAA,EAAU,iBAAA,EACZ,gBAAM,GAAA,CAAI,CAAC,YAAY,KAAA,qBACtB,GAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QAEC,KAAA,EAAO,UAAA,CAAW,IAAA,GAAO,CAAA,EAAG,UAAA,CAAW,IAAI,CAAA,MAAA,EAAM,UAAA,CAAW,IAAI,CAAA,CAAA,GAAK,UAAA,CAAW,IAAA;AAAA,QAChF,SAAA,EAAU,6NAAA;AAAA,QACV,OAAO,EAAE,SAAA,EAAW,CAAA,8BAAA,EAAiC,KAAA,GAAQ,GAAG,CAAA,UAAA,CAAA,EAAa;AAAA,QAE7E,QAAA,kBAAA,GAAA;AAAA,UAAC,KAAA;AAAA,UAAA;AAAA,YACC,KAAK,UAAA,CAAW,KAAA;AAAA,YAChB,KAAK,UAAA,CAAW,IAAA;AAAA,YAChB,SAAA,EAAU,4BAAA;AAAA,YACV,OAAA,EAAQ,MAAA;AAAA,YACR,SAAA,EAAW;AAAA;AAAA;AACb,OAAA;AAAA,MAXK,CAAA,EAAG,UAAA,CAAW,IAAI,CAAA,CAAA,EAAI,KAAK,CAAA;AAAA,KAanC,CAAA,EACH,CAAA;AAAA,IACC,wBAAQ,GAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,gDAAA,EAAkD,iBAAM,CAAA,GAAO;AAAA,GAAA,EACvF,CAAA;AAEJ","file":"chunk-REU4D5UF.js","sourcesContent":["import * as React from 'react'\nimport type { LoginAmbassador } from '../domain/auth-config'\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"]}
@@ -0,0 +1,18 @@
1
+ import { tl } from '@fayz-ai/core';
2
+ import { Gift } from 'lucide-react';
3
+ import { jsxs, jsx } from 'react/jsx-runtime';
4
+
5
+ // src/components/TrialPromise.tsx
6
+ function TrialPromise({ days }) {
7
+ return /* @__PURE__ */ jsxs("p", { className: "mt-3 inline-flex items-center gap-2 rounded-full border border-primary/25 bg-primary/10 px-3 py-1.5 text-[12.5px] font-medium text-primary", children: [
8
+ /* @__PURE__ */ jsx(Gift, { className: "h-3.5 w-3.5 shrink-0", "aria-hidden": true }),
9
+ /* @__PURE__ */ jsxs("span", { children: [
10
+ tl(`${days} days free`, `${days} dias gr\xE1tis`),
11
+ /* @__PURE__ */ jsx("span", { className: "font-normal", children: tl(" \xB7 no credit card", " \xB7 sem cart\xE3o de cr\xE9dito") })
12
+ ] })
13
+ ] });
14
+ }
15
+
16
+ export { TrialPromise };
17
+ //# sourceMappingURL=chunk-SMFXGZN7.js.map
18
+ //# sourceMappingURL=chunk-SMFXGZN7.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/TrialPromise.tsx"],"names":[],"mappings":";;;;;AAWO,SAAS,YAAA,CAAa,EAAE,IAAA,EAAK,EAAqB;AACvD,EAAA,uBACE,IAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,4IAAA,EACX,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,IAAA,EAAA,EAAK,SAAA,EAAU,sBAAA,EAAuB,aAAA,EAAW,IAAA,EAAC,CAAA;AAAA,yBAClD,MAAA,EAAA,EACE,QAAA,EAAA;AAAA,MAAA,EAAA,CAAG,CAAA,EAAG,IAAI,CAAA,UAAA,CAAA,EAAc,CAAA,EAAG,IAAI,CAAA,eAAA,CAAc,CAAA;AAAA,0BAG7C,MAAA,EAAA,EAAK,SAAA,EAAU,eAAe,QAAA,EAAA,EAAA,CAAG,sBAAA,EAAqB,mCAA0B,CAAA,EAAE;AAAA,KAAA,EACrF;AAAA,GAAA,EACF,CAAA;AAEJ","file":"chunk-SMFXGZN7.js","sourcesContent":["import { tl } from '@fayz-ai/core'\nimport { Gift } from 'lucide-react'\n\n/**\n * The promise, where the form asks for the work.\n *\n * A sign-up screen with no reason on it is a form; the reason is the trial, and\n * \"sem cartão de crédito\" is the half that removes the hesitation. One line, on\n * the sign-up view only — over the sign-in form it would be selling something\n * to somebody who already bought.\n */\nexport function TrialPromise({ days }: { days: number }) {\n return (\n <p className=\"mt-3 inline-flex items-center gap-2 rounded-full border border-primary/25 bg-primary/10 px-3 py-1.5 text-[12.5px] font-medium text-primary\">\n <Gift className=\"h-3.5 w-3.5 shrink-0\" aria-hidden />\n <span>\n {tl(`${days} days free`, `${days} dias grátis`)}\n {/* Same colour, lighter weight. Fading the second half was the version\n that failed contrast — a promise nobody can read sells nothing. */}\n <span className=\"font-normal\">{tl(' · no credit card', ' · sem cartão de crédito')}</span>\n </span>\n </p>\n )\n}\n"]}
@@ -0,0 +1,80 @@
1
+ import { OAuthButtons } from './chunk-WZVZMNLB.js';
2
+ import { useAuth } from './chunk-Q6DFI35B.js';
3
+ import { fieldClass, buttonClass } from './chunk-55RFOMW5.js';
4
+ import * as React from 'react';
5
+ import { tl } from '@fayz-ai/core';
6
+ import { EyeOff, Eye } from 'lucide-react';
7
+ import { jsxs, jsx } from 'react/jsx-runtime';
8
+
9
+ function LoginForm({
10
+ onSuccess,
11
+ onForgotPassword,
12
+ showOAuth,
13
+ oauthProviders,
14
+ oauthComingSoon,
15
+ initialEmail = "",
16
+ onEmailChange
17
+ }) {
18
+ const { signIn, error, isLoading } = useAuth();
19
+ const [email, setEmail] = React.useState(initialEmail);
20
+ const [password, setPassword] = React.useState("");
21
+ const [reveal, setReveal] = React.useState(false);
22
+ const [busy, setBusy] = React.useState(false);
23
+ const disabled = busy || isLoading;
24
+ async function submit(event) {
25
+ event.preventDefault();
26
+ setBusy(true);
27
+ try {
28
+ await signIn(email, password);
29
+ onSuccess?.();
30
+ } finally {
31
+ setBusy(false);
32
+ }
33
+ }
34
+ return /* @__PURE__ */ jsxs("form", { onSubmit: submit, className: "space-y-4", children: [
35
+ /* @__PURE__ */ jsxs("label", { className: "block space-y-1.5 text-sm font-medium", children: [
36
+ /* @__PURE__ */ jsx("span", { children: tl("Email", "E-mail") }),
37
+ /* @__PURE__ */ jsx(
38
+ "input",
39
+ {
40
+ className: fieldClass(),
41
+ type: "email",
42
+ autoComplete: "username",
43
+ required: true,
44
+ value: email,
45
+ onChange: (e) => {
46
+ setEmail(e.target.value);
47
+ onEmailChange?.(e.target.value);
48
+ },
49
+ disabled
50
+ }
51
+ )
52
+ ] }),
53
+ /* @__PURE__ */ jsxs("label", { className: "block space-y-1.5 text-sm font-medium", children: [
54
+ /* @__PURE__ */ jsx("span", { children: tl("Password", "Senha") }),
55
+ /* @__PURE__ */ jsxs("span", { className: "relative block", children: [
56
+ /* @__PURE__ */ jsx("input", { className: `${fieldClass()} pr-10`, type: reveal ? "text" : "password", autoComplete: "current-password", required: true, value: password, onChange: (e) => setPassword(e.target.value), disabled }),
57
+ /* @__PURE__ */ jsx(
58
+ "button",
59
+ {
60
+ type: "button",
61
+ onClick: () => setReveal((v) => !v),
62
+ "aria-label": reveal ? tl("Hide password", "Ocultar senha") : tl("Show password", "Mostrar senha"),
63
+ "aria-pressed": reveal,
64
+ tabIndex: -1,
65
+ className: "absolute inset-y-0 right-0 flex w-10 items-center justify-center rounded-r-md text-muted-foreground transition-colors hover:text-foreground",
66
+ children: reveal ? /* @__PURE__ */ jsx(EyeOff, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx(Eye, { className: "h-4 w-4" })
67
+ }
68
+ )
69
+ ] })
70
+ ] }),
71
+ onForgotPassword && /* @__PURE__ */ jsx("div", { className: "-mt-1 flex justify-end", children: /* @__PURE__ */ jsx("button", { type: "button", className: buttonClass("ghost"), onClick: onForgotPassword, children: tl("Forgot password?", "Esqueceu a senha?") }) }),
72
+ error && /* @__PURE__ */ jsx("p", { className: "text-sm text-destructive", children: error.message }),
73
+ /* @__PURE__ */ jsx("button", { className: buttonClass(), type: "submit", disabled, children: disabled ? tl("Signing in...", "Entrando...") : tl("Sign in", "Entrar") }),
74
+ showOAuth && /* @__PURE__ */ jsx(OAuthButtons, { providers: oauthProviders, disabled, comingSoon: oauthComingSoon })
75
+ ] });
76
+ }
77
+
78
+ export { LoginForm };
79
+ //# sourceMappingURL=chunk-W35GQEGU.js.map
80
+ //# sourceMappingURL=chunk-W35GQEGU.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/views/LoginForm.tsx"],"names":[],"mappings":"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","file":"chunk-W35GQEGU.js","sourcesContent":["import * as React from 'react'\nimport { tl } from '@fayz-ai/core'\nimport { Eye, EyeOff } from 'lucide-react'\nimport { useAuth } from '../context'\nimport type { OAuthProviderKey } from '../domain/auth-config'\nimport { buttonClass, fieldClass } from '../components/form-classes'\nimport { OAuthButtons } from './OAuthButtons'\n\nexport interface LoginFormProps {\n onSuccess?: () => void\n onForgotPassword?: () => void\n showOAuth?: boolean\n oauthProviders?: OAuthProviderKey[]\n /** Providers rendered as \"em breve\" — declared but not wired yet. */\n oauthComingSoon?: OAuthProviderKey[]\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 oauthComingSoon,\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 [reveal, setReveal] = 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 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>{tl('Email', 'E-mail')}</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>{tl('Password', 'Senha')}</span>\n <span className=\"relative block\">\n <input className={`${fieldClass()} pr-10`} type={reveal ? 'text' : 'password'} autoComplete=\"current-password\" required value={password} onChange={(e) => setPassword(e.target.value)} disabled={disabled} />\n {/* Same toggle as the signup form: you catch the typo by reading it. */}\n <button\n type=\"button\"\n onClick={() => setReveal((v) => !v)}\n aria-label={reveal ? tl('Hide password', 'Ocultar senha') : tl('Show password', 'Mostrar senha')}\n aria-pressed={reveal}\n tabIndex={-1}\n className=\"absolute inset-y-0 right-0 flex w-10 items-center justify-center rounded-r-md text-muted-foreground transition-colors hover:text-foreground\"\n >\n {reveal ? <EyeOff className=\"h-4 w-4\" /> : <Eye className=\"h-4 w-4\" />}\n </button>\n </span>\n </label>\n {onForgotPassword && (\n <div className=\"-mt-1 flex justify-end\">\n <button type=\"button\" className={buttonClass('ghost')} onClick={onForgotPassword}>\n {tl('Forgot password?', 'Esqueceu a senha?')}\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 ? tl('Signing in...', 'Entrando...') : tl('Sign in', 'Entrar')}\n </button>\n {showOAuth && (\n <OAuthButtons providers={oauthProviders} disabled={disabled} comingSoon={oauthComingSoon} />\n )}\n </form>\n )\n}\n"]}
@@ -0,0 +1,64 @@
1
+ import { useAuth } from './chunk-Q6DFI35B.js';
2
+ import { fieldClass, buttonClass } from './chunk-55RFOMW5.js';
3
+ import * as React from 'react';
4
+ import { tl } from '@fayz-ai/core';
5
+ import { jsxs, jsx } from 'react/jsx-runtime';
6
+
7
+ function ForgotPasswordForm({
8
+ redirectTo,
9
+ onSent,
10
+ onBackToLogin,
11
+ initialEmail = "",
12
+ onEmailChange,
13
+ emailLabel = tl("Email", "E-mail"),
14
+ submitLabel = tl("Send reset link", "Enviar link de redefini\xE7\xE3o"),
15
+ sendingLabel = tl("Sending...", "Enviando..."),
16
+ sentLabel = tl("Password reset instructions sent.", "Instru\xE7\xF5es de redefini\xE7\xE3o enviadas."),
17
+ backLabel = tl("Back to login", "Voltar para o login")
18
+ }) {
19
+ const { resetPassword, error, isLoading } = useAuth();
20
+ const [email, setEmail] = React.useState(initialEmail);
21
+ const [sent, setSent] = React.useState(false);
22
+ const [busy, setBusy] = React.useState(false);
23
+ const disabled = busy || isLoading;
24
+ async function submit(event) {
25
+ event.preventDefault();
26
+ setBusy(true);
27
+ try {
28
+ await resetPassword(email, { redirectTo });
29
+ setSent(true);
30
+ onSent?.(email);
31
+ } finally {
32
+ setBusy(false);
33
+ }
34
+ }
35
+ return /* @__PURE__ */ jsxs("form", { onSubmit: submit, className: "space-y-4", children: [
36
+ /* @__PURE__ */ jsxs("label", { className: "block space-y-1.5 text-sm font-medium", children: [
37
+ /* @__PURE__ */ jsx("span", { children: emailLabel }),
38
+ /* @__PURE__ */ jsx(
39
+ "input",
40
+ {
41
+ className: fieldClass(),
42
+ type: "email",
43
+ autoComplete: "username",
44
+ required: true,
45
+ autoFocus: !email,
46
+ value: email,
47
+ onChange: (e) => {
48
+ setEmail(e.target.value);
49
+ onEmailChange?.(e.target.value);
50
+ },
51
+ disabled
52
+ }
53
+ )
54
+ ] }),
55
+ error && /* @__PURE__ */ jsx("p", { className: "text-sm text-destructive", children: error.message }),
56
+ sent && /* @__PURE__ */ jsx("p", { className: "text-sm text-emerald-600", children: sentLabel }),
57
+ /* @__PURE__ */ jsx("button", { className: buttonClass(), type: "submit", disabled, children: disabled ? sendingLabel : submitLabel }),
58
+ onBackToLogin && /* @__PURE__ */ jsx("button", { type: "button", className: buttonClass("ghost"), onClick: onBackToLogin, children: backLabel })
59
+ ] });
60
+ }
61
+
62
+ export { ForgotPasswordForm };
63
+ //# sourceMappingURL=chunk-W7565FXD.js.map
64
+ //# sourceMappingURL=chunk-W7565FXD.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/views/ForgotPasswordForm.tsx"],"names":[],"mappings":"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","file":"chunk-W7565FXD.js","sourcesContent":["import * as React from 'react'\nimport { tl } from '@fayz-ai/core'\nimport { useAuth } from '../context'\nimport { buttonClass, fieldClass } from '../components/form-classes'\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 = tl('Email', 'E-mail'),\n submitLabel = tl('Send reset link', 'Enviar link de redefinição'),\n sendingLabel = tl('Sending...', 'Enviando...'),\n sentLabel = tl('Password reset instructions sent.', 'Instruções de redefinição enviadas.'),\n backLabel = tl('Back to login', 'Voltar para o 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"]}
@@ -0,0 +1,48 @@
1
+ import { useAuth } from './chunk-Q6DFI35B.js';
2
+ import { buttonClass } from './chunk-55RFOMW5.js';
3
+ import { jsx, jsxs } from 'react/jsx-runtime';
4
+
5
+ function providerLabel(provider) {
6
+ return provider.charAt(0).toUpperCase() + provider.slice(1);
7
+ }
8
+ function GoogleMark({ className }) {
9
+ return /* @__PURE__ */ jsxs("svg", { className, viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", "aria-hidden": true, children: [
10
+ /* @__PURE__ */ jsx("path", { d: "M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92a5.06 5.06 0 01-2.2 3.32v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.1z", fill: "#4285F4" }),
11
+ /* @__PURE__ */ jsx("path", { d: "M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z", fill: "#34A853" }),
12
+ /* @__PURE__ */ jsx("path", { d: "M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z", fill: "#FBBC05" }),
13
+ /* @__PURE__ */ jsx("path", { d: "M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z", fill: "#EA4335" })
14
+ ] });
15
+ }
16
+ var PROVIDER_MARKS = {
17
+ google: GoogleMark
18
+ };
19
+ function OAuthButtons({ providers = ["google"], disabled, comingSoon, onProviderClick }) {
20
+ const { signInWithOAuth } = useAuth();
21
+ return /* @__PURE__ */ jsx("div", { className: "space-y-2", children: providers.map((provider) => {
22
+ const soon = comingSoon?.includes(provider) ?? false;
23
+ const Mark = PROVIDER_MARKS[provider];
24
+ return /* @__PURE__ */ jsxs(
25
+ "button",
26
+ {
27
+ type: "button",
28
+ className: `${buttonClass("outline")} gap-2`,
29
+ disabled: disabled || soon,
30
+ title: soon ? "Ainda n\xE3o dispon\xEDvel" : void 0,
31
+ onClick: () => {
32
+ if (soon) return;
33
+ void (onProviderClick ? onProviderClick(provider) : signInWithOAuth(provider));
34
+ },
35
+ children: [
36
+ Mark && /* @__PURE__ */ jsx(Mark, { className: "h-4 w-4 shrink-0" }),
37
+ "Continuar com ",
38
+ providerLabel(provider)
39
+ ]
40
+ },
41
+ provider
42
+ );
43
+ }) });
44
+ }
45
+
46
+ export { OAuthButtons };
47
+ //# sourceMappingURL=chunk-WZVZMNLB.js.map
48
+ //# sourceMappingURL=chunk-WZVZMNLB.js.map