@mesob/auth-react 0.0.3

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 (46) hide show
  1. package/dist/components/auth-card.d.ts +9 -0
  2. package/dist/components/auth-card.js +11 -0
  3. package/dist/components/auth-card.js.map +1 -0
  4. package/dist/components/auth-page-layout.d.ts +14 -0
  5. package/dist/components/auth-page-layout.js +28 -0
  6. package/dist/components/auth-page-layout.js.map +1 -0
  7. package/dist/components/countdown.d.ts +10 -0
  8. package/dist/components/countdown.js +57 -0
  9. package/dist/components/countdown.js.map +1 -0
  10. package/dist/components/forgot-password.d.ts +13 -0
  11. package/dist/components/forgot-password.js +67 -0
  12. package/dist/components/forgot-password.js.map +1 -0
  13. package/dist/components/pages/forgot-password-page.d.ts +17 -0
  14. package/dist/components/pages/forgot-password-page.js +224 -0
  15. package/dist/components/pages/forgot-password-page.js.map +1 -0
  16. package/dist/components/pages/reset-password-page.d.ts +19 -0
  17. package/dist/components/pages/reset-password-page.js +357 -0
  18. package/dist/components/pages/reset-password-page.js.map +1 -0
  19. package/dist/components/pages/sign-in-page.d.ts +19 -0
  20. package/dist/components/pages/sign-in-page.js +343 -0
  21. package/dist/components/pages/sign-in-page.js.map +1 -0
  22. package/dist/components/pages/sign-up-page.d.ts +18 -0
  23. package/dist/components/pages/sign-up-page.js +360 -0
  24. package/dist/components/pages/sign-up-page.js.map +1 -0
  25. package/dist/components/pages/verify-email-page.d.ts +19 -0
  26. package/dist/components/pages/verify-email-page.js +356 -0
  27. package/dist/components/pages/verify-email-page.js.map +1 -0
  28. package/dist/components/pages/verify-phone-page.d.ts +20 -0
  29. package/dist/components/pages/verify-phone-page.js +368 -0
  30. package/dist/components/pages/verify-phone-page.js.map +1 -0
  31. package/dist/components/reset-password-form.d.ts +16 -0
  32. package/dist/components/reset-password-form.js +142 -0
  33. package/dist/components/reset-password-form.js.map +1 -0
  34. package/dist/components/sign-in.d.ts +16 -0
  35. package/dist/components/sign-in.js +128 -0
  36. package/dist/components/sign-in.js.map +1 -0
  37. package/dist/components/sign-up.d.ts +17 -0
  38. package/dist/components/sign-up.js +179 -0
  39. package/dist/components/sign-up.js.map +1 -0
  40. package/dist/components/verification-form.d.ts +15 -0
  41. package/dist/components/verification-form.js +155 -0
  42. package/dist/components/verification-form.js.map +1 -0
  43. package/dist/index.d.ts +222 -0
  44. package/dist/index.js +1640 -0
  45. package/dist/index.js.map +1 -0
  46. package/package.json +48 -0
package/dist/index.js ADDED
@@ -0,0 +1,1640 @@
1
+ // src/client.ts
2
+ var validErrorCodes = [
3
+ "USER_NOT_FOUND",
4
+ "INVALID_PASSWORD",
5
+ "USER_EXISTS",
6
+ "VERIFICATION_EXPIRED",
7
+ "VERIFICATION_MISMATCH",
8
+ "VERIFICATION_NOT_FOUND",
9
+ "TOO_MANY_ATTEMPTS",
10
+ "REQUIRES_VERIFICATION",
11
+ "UNAUTHORIZED",
12
+ "ACCESS_DENIED",
13
+ "HAS_NO_PASSWORD"
14
+ ];
15
+ var AuthError = class extends Error {
16
+ code;
17
+ status;
18
+ details;
19
+ constructor(message, code, status, details) {
20
+ super(message);
21
+ this.name = "AuthError";
22
+ this.code = code;
23
+ this.status = status;
24
+ this.details = details;
25
+ }
26
+ };
27
+ var AuthClient = class {
28
+ baseURL;
29
+ constructor(config) {
30
+ this.baseURL = config.baseURL.replace(/\/$/, "");
31
+ }
32
+ async request(endpoint, options = {}) {
33
+ const url = `${this.baseURL}${endpoint}`;
34
+ const response = await fetch(url, {
35
+ ...options,
36
+ credentials: "include",
37
+ headers: {
38
+ "Content-Type": "application/json",
39
+ ...options.headers
40
+ }
41
+ });
42
+ if (!response.ok) {
43
+ const text = await response.text();
44
+ let errorData;
45
+ try {
46
+ errorData = JSON.parse(text);
47
+ } catch {
48
+ errorData = { error: "Unknown error", message: text };
49
+ }
50
+ const potentialCode = errorData.code || (typeof errorData.error === "string" ? errorData.error : null) || (typeof errorData.message === "string" ? errorData.message : null);
51
+ const upperCode = potentialCode?.toUpperCase().trim();
52
+ const errorCode = upperCode && validErrorCodes.includes(upperCode) ? upperCode : void 0;
53
+ const errorMessage = errorData.message || errorData.error || "Request failed";
54
+ throw new AuthError(
55
+ errorMessage,
56
+ errorCode,
57
+ response.status,
58
+ errorData.details
59
+ );
60
+ }
61
+ const data = await response.json();
62
+ return data;
63
+ }
64
+ signUpWithEmail(data) {
65
+ return this.request("/sign-up", {
66
+ method: "POST",
67
+ body: JSON.stringify({
68
+ email: data.email,
69
+ password: data.password,
70
+ fullName: data.fullName,
71
+ handle: data.handle
72
+ })
73
+ });
74
+ }
75
+ signUpWithPhone(data) {
76
+ return this.request("/sign-up", {
77
+ method: "POST",
78
+ body: JSON.stringify({
79
+ phone: data.phone,
80
+ password: data.password,
81
+ fullName: data.fullName,
82
+ handle: data.handle
83
+ })
84
+ });
85
+ }
86
+ checkUser(data) {
87
+ return this.request("/check-user", {
88
+ method: "POST",
89
+ body: JSON.stringify(data)
90
+ });
91
+ }
92
+ signInWithPassword(data) {
93
+ return this.request("/sign-in", {
94
+ method: "POST",
95
+ body: JSON.stringify(data)
96
+ });
97
+ }
98
+ signOut() {
99
+ return this.request("/sign-out", {
100
+ method: "POST"
101
+ });
102
+ }
103
+ requestEmailVerification(data) {
104
+ return this.request(
105
+ "/email/verification/request",
106
+ {
107
+ method: "POST",
108
+ body: JSON.stringify(data || {})
109
+ }
110
+ );
111
+ }
112
+ verifyEmail(data) {
113
+ return this.request("/email/verification/confirm", {
114
+ method: "POST",
115
+ body: JSON.stringify(data)
116
+ });
117
+ }
118
+ resendVerification(_verificationId) {
119
+ return this.requestEmailVerification();
120
+ }
121
+ requestPhoneOtp(data) {
122
+ return this.request(
123
+ "/phone/verification/request",
124
+ {
125
+ method: "POST",
126
+ body: JSON.stringify(data)
127
+ }
128
+ );
129
+ }
130
+ verifyPhoneOtp(data) {
131
+ return this.request("/phone/verification/confirm", {
132
+ method: "POST",
133
+ body: JSON.stringify(data)
134
+ });
135
+ }
136
+ forgotPassword(data) {
137
+ return this.request("/password/forgot", {
138
+ method: "POST",
139
+ body: JSON.stringify(data)
140
+ });
141
+ }
142
+ resetPassword(data) {
143
+ return this.request("/password/reset", {
144
+ method: "POST",
145
+ body: JSON.stringify(data)
146
+ });
147
+ }
148
+ changePassword(data) {
149
+ return this.request("/password/change", {
150
+ method: "POST",
151
+ body: JSON.stringify(data)
152
+ });
153
+ }
154
+ getSession() {
155
+ return this.request("/session", {
156
+ method: "GET"
157
+ });
158
+ }
159
+ };
160
+
161
+ // src/components/auth-card.tsx
162
+ import { jsx } from "react/jsx-runtime";
163
+ var AuthCard = ({ children }) => {
164
+ return /* @__PURE__ */ jsx("div", { className: "flex min-h-screen items-center justify-center bg-gradient-to-br from-slate-50 to-slate-100 p-4 dark:from-slate-900 dark:to-slate-800", children: /* @__PURE__ */ jsx("div", { className: "w-full max-w-md", children: /* @__PURE__ */ jsx("div", { className: "rounded-xl border bg-card p-8 shadow-lg", children }) }) });
165
+ };
166
+
167
+ // src/components/auth-page-layout.tsx
168
+ import { Alert, AlertDescription } from "@mesob/ui/components/alert";
169
+ import { jsx as jsx2, jsxs } from "react/jsx-runtime";
170
+ var AuthPageLayout = ({
171
+ title,
172
+ description,
173
+ children,
174
+ error,
175
+ footer,
176
+ logoImage
177
+ }) => {
178
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
179
+ /* @__PURE__ */ jsx2("div", { className: "flex size-8 mb-6 w-full items-center justify-center rounded-md", children: /* @__PURE__ */ jsx2("img", { src: logoImage || "", alt: "Jiret", width: 42, height: 42 }) }),
180
+ /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
181
+ /* @__PURE__ */ jsx2("h1", { className: "text-2xl font-bold tracking-tight", children: title }),
182
+ description && /* @__PURE__ */ jsx2("p", { className: "mt-2 text-sm text-muted-foreground", children: description })
183
+ ] }),
184
+ children,
185
+ error && /* @__PURE__ */ jsx2(Alert, { variant: "destructive", children: /* @__PURE__ */ jsx2(AlertDescription, { children: error }) }),
186
+ /* @__PURE__ */ jsx2("div", { className: "mt-2 w-full", children: footer && /* @__PURE__ */ jsx2("div", { className: "w-full text-center text-sm text-muted-foreground", children: footer }) })
187
+ ] });
188
+ };
189
+
190
+ // src/components/countdown.tsx
191
+ import { Button } from "@mesob/ui/components/button";
192
+ import { useTranslations } from "next-intl";
193
+ import { useEffect, useState } from "react";
194
+ import { jsx as jsx3 } from "react/jsx-runtime";
195
+ var Countdown = ({
196
+ initialSeconds = 60,
197
+ onResend,
198
+ resending = false
199
+ }) => {
200
+ const t = useTranslations("Common");
201
+ const [seconds, setSeconds] = useState(initialSeconds);
202
+ const [isResending, setIsResending] = useState(false);
203
+ useEffect(() => {
204
+ if (seconds <= 0) {
205
+ return;
206
+ }
207
+ const timer = setInterval(() => {
208
+ setSeconds((prev) => {
209
+ if (prev <= 1) {
210
+ clearInterval(timer);
211
+ return 0;
212
+ }
213
+ return prev - 1;
214
+ });
215
+ }, 1e3);
216
+ return () => clearInterval(timer);
217
+ }, [seconds]);
218
+ const handleResend = async () => {
219
+ setIsResending(true);
220
+ try {
221
+ await onResend();
222
+ setSeconds(initialSeconds);
223
+ } catch (_error) {
224
+ } finally {
225
+ setIsResending(false);
226
+ }
227
+ };
228
+ if (seconds > 0) {
229
+ return /* @__PURE__ */ jsx3(Button, { variant: "ghost", disabled: true, children: t("resendIn", { seconds }) });
230
+ }
231
+ return /* @__PURE__ */ jsx3(
232
+ Button,
233
+ {
234
+ variant: "ghost",
235
+ onClick: handleResend,
236
+ disabled: isResending || resending,
237
+ children: isResending || resending ? t("resending") : t("resend")
238
+ }
239
+ );
240
+ };
241
+
242
+ // src/components/forgot-password.tsx
243
+ import { zodResolver } from "@hookform/resolvers/zod";
244
+ import { Button as Button2 } from "@mesob/ui/components/button";
245
+ import {
246
+ Form,
247
+ FormControl,
248
+ FormField,
249
+ FormItem,
250
+ FormLabel,
251
+ FormMessage
252
+ } from "@mesob/ui/components/form";
253
+ import { Input } from "@mesob/ui/components/input";
254
+ import { useTranslations as useTranslations2 } from "next-intl";
255
+ import { useMemo } from "react";
256
+ import { useForm } from "react-hook-form";
257
+ import { z } from "zod";
258
+ import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
259
+ var ForgotPassword = ({
260
+ onSubmit,
261
+ isLoading = false,
262
+ onBack
263
+ }) => {
264
+ const t = useTranslations2("Auth.forgotPassword");
265
+ const forgotPasswordSchema = useMemo(
266
+ () => z.object({
267
+ account: z.string().min(1, t("errors.accountRequired"))
268
+ }),
269
+ [t]
270
+ );
271
+ const form = useForm({
272
+ resolver: zodResolver(forgotPasswordSchema),
273
+ defaultValues: {
274
+ account: ""
275
+ }
276
+ });
277
+ const handleSubmit = form.handleSubmit(async (values) => {
278
+ await onSubmit(values);
279
+ });
280
+ return /* @__PURE__ */ jsx4(Form, { ...form, children: /* @__PURE__ */ jsxs2("form", { onSubmit: handleSubmit, className: "space-y-5", children: [
281
+ /* @__PURE__ */ jsx4(
282
+ FormField,
283
+ {
284
+ control: form.control,
285
+ name: "account",
286
+ render: ({ field }) => /* @__PURE__ */ jsxs2(FormItem, { children: [
287
+ /* @__PURE__ */ jsx4(FormLabel, { children: t("form.accountLabel") }),
288
+ /* @__PURE__ */ jsx4(FormControl, { children: /* @__PURE__ */ jsx4(
289
+ Input,
290
+ {
291
+ type: "text",
292
+ placeholder: t("form.accountPlaceholder"),
293
+ ...field
294
+ }
295
+ ) }),
296
+ /* @__PURE__ */ jsx4(FormMessage, {})
297
+ ] })
298
+ }
299
+ ),
300
+ /* @__PURE__ */ jsx4(Button2, { type: "submit", className: "w-full", disabled: isLoading, children: isLoading ? t("form.submitting") : t("form.submit") })
301
+ ] }) });
302
+ };
303
+
304
+ // src/components/pages/forgot-password-page.tsx
305
+ import { useTranslations as useTranslations3 } from "next-intl";
306
+ import { useState as useState3 } from "react";
307
+
308
+ // src/context/auth-provider.tsx
309
+ import {
310
+ createContext,
311
+ useCallback,
312
+ useContext,
313
+ useEffect as useEffect2,
314
+ useState as useState2
315
+ } from "react";
316
+ import { jsx as jsx5 } from "react/jsx-runtime";
317
+ var AuthContext = createContext(null);
318
+ var useAuth = () => {
319
+ const context = useContext(AuthContext);
320
+ if (!context) {
321
+ throw new Error("useAuth must be used within AuthProvider");
322
+ }
323
+ return context;
324
+ };
325
+ var AuthProvider = ({ client, children }) => {
326
+ const [user, setUser] = useState2(null);
327
+ const [session, setSession] = useState2(null);
328
+ const [loading, setLoading] = useState2(true);
329
+ const [error, setError] = useState2(null);
330
+ const refresh = useCallback(async () => {
331
+ try {
332
+ setLoading(true);
333
+ setError(null);
334
+ const data = await client.getSession();
335
+ setUser(data.user);
336
+ setSession(data.session);
337
+ } catch (err) {
338
+ setError(
339
+ err instanceof Error ? err : new Error("Failed to fetch session")
340
+ );
341
+ setUser(null);
342
+ setSession(null);
343
+ } finally {
344
+ setLoading(false);
345
+ }
346
+ }, [client]);
347
+ const setAuth = useCallback((data) => {
348
+ setUser(data.user);
349
+ setSession(data.session);
350
+ setError(null);
351
+ setLoading(false);
352
+ }, []);
353
+ useEffect2(() => {
354
+ refresh();
355
+ }, [refresh]);
356
+ return /* @__PURE__ */ jsx5(
357
+ AuthContext.Provider,
358
+ {
359
+ value: {
360
+ user,
361
+ session,
362
+ loading,
363
+ error,
364
+ client,
365
+ refresh,
366
+ setAuth
367
+ },
368
+ children
369
+ }
370
+ );
371
+ };
372
+
373
+ // src/constants/auth.error.codes.ts
374
+ var validCodes = [
375
+ "USER_NOT_FOUND",
376
+ "INVALID_PASSWORD",
377
+ "USER_EXISTS",
378
+ "VERIFICATION_EXPIRED",
379
+ "VERIFICATION_MISMATCH",
380
+ "VERIFICATION_NOT_FOUND",
381
+ "TOO_MANY_ATTEMPTS",
382
+ "REQUIRES_VERIFICATION",
383
+ "UNAUTHORIZED",
384
+ "ACCESS_DENIED",
385
+ "HAS_NO_PASSWORD"
386
+ ];
387
+
388
+ // src/utils/handle-error.ts
389
+ var handleError = (err, setError, t) => {
390
+ if (err instanceof AuthError) {
391
+ let errorKey = "errors.fallback";
392
+ if (err.code) {
393
+ errorKey = `errors.${err.code.toLowerCase()}`;
394
+ } else if (err.message) {
395
+ const messageUpper = err.message.toUpperCase().trim();
396
+ if (validCodes.includes(messageUpper)) {
397
+ errorKey = `errors.${messageUpper.toLowerCase()}`;
398
+ }
399
+ }
400
+ setError(t(errorKey, { defaultValue: err.message }));
401
+ } else {
402
+ setError(err instanceof Error ? err.message : t("errors.fallback"));
403
+ }
404
+ };
405
+
406
+ // src/components/pages/forgot-password-page.tsx
407
+ import { jsx as jsx6 } from "react/jsx-runtime";
408
+ var ForgotPasswordPage = ({
409
+ onNavigate,
410
+ linkComponent: Link,
411
+ links,
412
+ logoImage
413
+ }) => {
414
+ const t = useTranslations3("Auth.forgotPassword");
415
+ const { client } = useAuth();
416
+ const [isLoading, setIsLoading] = useState3(false);
417
+ const [error, setError] = useState3(null);
418
+ const signInLink = links?.signIn || "/auth/sign-in";
419
+ const handleSubmit = async (values) => {
420
+ setIsLoading(true);
421
+ setError(null);
422
+ try {
423
+ const res = await client.forgotPassword({ identifier: values.account });
424
+ if ("verificationId" in res && res.verificationId) {
425
+ onNavigate(`/auth/reset-password?verificationId=${res.verificationId}`);
426
+ } else {
427
+ onNavigate(
428
+ `/auth/reset-password?identifier=${encodeURIComponent(values.account)}`
429
+ );
430
+ }
431
+ } catch (err) {
432
+ handleError(err, setError, t);
433
+ } finally {
434
+ setIsLoading(false);
435
+ }
436
+ };
437
+ const handleBack = () => {
438
+ onNavigate(signInLink);
439
+ };
440
+ return /* @__PURE__ */ jsx6(
441
+ AuthPageLayout,
442
+ {
443
+ title: t("title"),
444
+ description: t("description"),
445
+ error,
446
+ logoImage,
447
+ footer: Link ? /* @__PURE__ */ jsx6(Link, { href: signInLink, className: "text-primary hover:underline", children: t("footer.backToSignIn") }) : /* @__PURE__ */ jsx6(
448
+ "a",
449
+ {
450
+ href: signInLink,
451
+ onClick: (e) => {
452
+ e.preventDefault();
453
+ onNavigate(signInLink);
454
+ },
455
+ className: "text-primary hover:underline",
456
+ children: t("footer.backToSignIn")
457
+ }
458
+ ),
459
+ children: /* @__PURE__ */ jsx6(
460
+ ForgotPassword,
461
+ {
462
+ onSubmit: handleSubmit,
463
+ isLoading,
464
+ onBack: handleBack
465
+ }
466
+ )
467
+ }
468
+ );
469
+ };
470
+
471
+ // src/components/pages/reset-password-page.tsx
472
+ import { useTranslations as useTranslations5 } from "next-intl";
473
+ import { useState as useState5 } from "react";
474
+
475
+ // src/components/reset-password-form.tsx
476
+ import { zodResolver as zodResolver2 } from "@hookform/resolvers/zod";
477
+ import { Button as Button3 } from "@mesob/ui/components/button";
478
+ import {
479
+ Form as Form2,
480
+ FormControl as FormControl2,
481
+ FormField as FormField2,
482
+ FormItem as FormItem2,
483
+ FormLabel as FormLabel2,
484
+ FormMessage as FormMessage2
485
+ } from "@mesob/ui/components/form";
486
+ import { Input as Input2 } from "@mesob/ui/components/input";
487
+ import {
488
+ InputOTP,
489
+ InputOTPGroup,
490
+ InputOTPSlot
491
+ } from "@mesob/ui/components/input-otp";
492
+ import { Eye, EyeOff } from "lucide-react";
493
+ import { useTranslations as useTranslations4 } from "next-intl";
494
+ import { useMemo as useMemo2, useState as useState4 } from "react";
495
+ import { useForm as useForm2 } from "react-hook-form";
496
+ import { z as z2 } from "zod";
497
+ import { jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
498
+ var ResetPasswordForm = ({
499
+ verificationId,
500
+ onSubmit,
501
+ isLoading = false,
502
+ error
503
+ }) => {
504
+ const t = useTranslations4("Auth.resetPassword");
505
+ const [showPassword, setShowPassword] = useState4(false);
506
+ const resetPasswordSchema = useMemo2(
507
+ () => z2.object({
508
+ code: z2.string().length(6, t("errors.codeLength")),
509
+ password: z2.string().min(8, t("errors.passwordLength")),
510
+ confirmPassword: z2.string()
511
+ }).refine((data) => data.password === data.confirmPassword, {
512
+ message: t("errors.passwordsMismatch"),
513
+ path: ["confirmPassword"]
514
+ }),
515
+ [t]
516
+ );
517
+ const form = useForm2({
518
+ resolver: zodResolver2(resetPasswordSchema),
519
+ defaultValues: {
520
+ code: "",
521
+ password: "",
522
+ confirmPassword: ""
523
+ }
524
+ });
525
+ const handleSubmit = form.handleSubmit(async (values) => {
526
+ await onSubmit(values);
527
+ });
528
+ return /* @__PURE__ */ jsx7(Form2, { ...form, children: /* @__PURE__ */ jsxs3("form", { onSubmit: handleSubmit, className: "space-y-4", children: [
529
+ /* @__PURE__ */ jsx7(
530
+ FormField2,
531
+ {
532
+ control: form.control,
533
+ name: "code",
534
+ render: ({ field }) => /* @__PURE__ */ jsxs3(FormItem2, { children: [
535
+ /* @__PURE__ */ jsx7("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx7(FormLabel2, { children: t("form.codeLabel") }) }),
536
+ /* @__PURE__ */ jsx7(FormControl2, { children: /* @__PURE__ */ jsx7("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx7(InputOTP, { maxLength: 6, ...field, children: /* @__PURE__ */ jsxs3(InputOTPGroup, { children: [
537
+ /* @__PURE__ */ jsx7(InputOTPSlot, { index: 0 }),
538
+ /* @__PURE__ */ jsx7(InputOTPSlot, { index: 1 }),
539
+ /* @__PURE__ */ jsx7(InputOTPSlot, { index: 2 }),
540
+ /* @__PURE__ */ jsx7(InputOTPSlot, { index: 3 }),
541
+ /* @__PURE__ */ jsx7(InputOTPSlot, { index: 4 }),
542
+ /* @__PURE__ */ jsx7(InputOTPSlot, { index: 5 })
543
+ ] }) }) }) }),
544
+ /* @__PURE__ */ jsx7(FormMessage2, {})
545
+ ] })
546
+ }
547
+ ),
548
+ /* @__PURE__ */ jsx7(
549
+ FormField2,
550
+ {
551
+ control: form.control,
552
+ name: "password",
553
+ render: ({ field }) => /* @__PURE__ */ jsxs3(FormItem2, { children: [
554
+ /* @__PURE__ */ jsx7(FormLabel2, { children: t("form.passwordLabel") }),
555
+ /* @__PURE__ */ jsx7(FormControl2, { children: /* @__PURE__ */ jsxs3("div", { className: "relative", children: [
556
+ /* @__PURE__ */ jsx7(
557
+ Input2,
558
+ {
559
+ type: showPassword ? "text" : "password",
560
+ placeholder: t("form.passwordPlaceholder"),
561
+ ...field
562
+ }
563
+ ),
564
+ /* @__PURE__ */ jsx7(
565
+ "button",
566
+ {
567
+ type: "button",
568
+ onClick: () => setShowPassword(!showPassword),
569
+ className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground",
570
+ children: showPassword ? /* @__PURE__ */ jsx7(EyeOff, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx7(Eye, { className: "h-4 w-4" })
571
+ }
572
+ )
573
+ ] }) }),
574
+ /* @__PURE__ */ jsx7(FormMessage2, {})
575
+ ] })
576
+ }
577
+ ),
578
+ /* @__PURE__ */ jsx7(
579
+ FormField2,
580
+ {
581
+ control: form.control,
582
+ name: "confirmPassword",
583
+ render: ({ field }) => /* @__PURE__ */ jsxs3(FormItem2, { children: [
584
+ /* @__PURE__ */ jsx7(FormLabel2, { children: t("form.confirmPasswordLabel") }),
585
+ /* @__PURE__ */ jsx7(FormControl2, { children: /* @__PURE__ */ jsxs3("div", { className: "relative", children: [
586
+ /* @__PURE__ */ jsx7(
587
+ Input2,
588
+ {
589
+ type: showPassword ? "text" : "password",
590
+ placeholder: t("form.passwordPlaceholder"),
591
+ ...field
592
+ }
593
+ ),
594
+ /* @__PURE__ */ jsx7(
595
+ "button",
596
+ {
597
+ type: "button",
598
+ onClick: () => setShowPassword(!showPassword),
599
+ className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground",
600
+ children: showPassword ? /* @__PURE__ */ jsx7(EyeOff, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx7(Eye, { className: "h-4 w-4" })
601
+ }
602
+ )
603
+ ] }) }),
604
+ /* @__PURE__ */ jsx7(FormMessage2, {})
605
+ ] })
606
+ }
607
+ ),
608
+ /* @__PURE__ */ jsx7(Button3, { type: "submit", className: "w-full", disabled: isLoading, children: isLoading ? t("form.submitting") : t("form.submit") })
609
+ ] }) });
610
+ };
611
+
612
+ // src/components/pages/reset-password-page.tsx
613
+ import { jsx as jsx8, jsxs as jsxs4 } from "react/jsx-runtime";
614
+ var ResetPasswordPage = ({
615
+ verificationId,
616
+ onNavigate,
617
+ linkComponent: Link,
618
+ links,
619
+ logoImage
620
+ }) => {
621
+ const t = useTranslations5("Auth.resetPassword");
622
+ const common = useTranslations5("Common");
623
+ const { client, refresh } = useAuth();
624
+ const [isLoading, setIsLoading] = useState5(false);
625
+ const [error, setError] = useState5(null);
626
+ const signInLink = links?.signIn || "/auth/sign-in";
627
+ const forgotPasswordLink = links?.forgotPassword || "/auth/forgot-password";
628
+ const handleSubmit = async (values) => {
629
+ if (!verificationId) {
630
+ setError(t("errors.missingVerificationId"));
631
+ return;
632
+ }
633
+ setIsLoading(true);
634
+ setError(null);
635
+ try {
636
+ await client.resetPassword({
637
+ verificationId,
638
+ code: values.code,
639
+ password: values.password
640
+ });
641
+ await refresh();
642
+ onNavigate("/dashboard");
643
+ } catch (err) {
644
+ handleError(err, setError, t);
645
+ } finally {
646
+ setIsLoading(false);
647
+ }
648
+ };
649
+ if (!verificationId) {
650
+ return /* @__PURE__ */ jsx8(
651
+ AuthPageLayout,
652
+ {
653
+ title: common("invalidLinkTitle"),
654
+ description: common("invalidLinkDescription"),
655
+ logoImage,
656
+ footer: Link ? /* @__PURE__ */ jsx8(
657
+ Link,
658
+ {
659
+ href: forgotPasswordLink,
660
+ className: "text-primary hover:underline",
661
+ children: t("footer.requestNew")
662
+ }
663
+ ) : /* @__PURE__ */ jsx8(
664
+ "a",
665
+ {
666
+ href: forgotPasswordLink,
667
+ onClick: (e) => {
668
+ e.preventDefault();
669
+ onNavigate(forgotPasswordLink);
670
+ },
671
+ className: "text-primary hover:underline",
672
+ children: t("footer.requestNew")
673
+ }
674
+ ),
675
+ children: /* @__PURE__ */ jsx8("div", {})
676
+ }
677
+ );
678
+ }
679
+ return /* @__PURE__ */ jsx8(
680
+ AuthPageLayout,
681
+ {
682
+ title: t("title"),
683
+ description: t("description"),
684
+ error,
685
+ logoImage,
686
+ footer: Link ? /* @__PURE__ */ jsxs4("div", { className: "flex items-center justify-between w-full gap-2", children: [
687
+ /* @__PURE__ */ jsx8(Link, { href: signInLink, className: "text-primary hover:underline", children: t("footer.backToSignIn") }),
688
+ /* @__PURE__ */ jsx8(
689
+ Link,
690
+ {
691
+ href: forgotPasswordLink,
692
+ className: "text-primary hover:underline",
693
+ children: t("footer.changeAccount")
694
+ }
695
+ )
696
+ ] }) : /* @__PURE__ */ jsxs4("div", { className: "flex items-center justify-between w-full gap-2", children: [
697
+ /* @__PURE__ */ jsx8(
698
+ "a",
699
+ {
700
+ href: forgotPasswordLink,
701
+ onClick: (e) => {
702
+ e.preventDefault();
703
+ onNavigate(forgotPasswordLink);
704
+ },
705
+ className: "text-primary hover:underline",
706
+ children: t("footer.backToSignIn")
707
+ }
708
+ ),
709
+ /* @__PURE__ */ jsx8(
710
+ "a",
711
+ {
712
+ href: forgotPasswordLink,
713
+ onClick: (e) => {
714
+ e.preventDefault();
715
+ onNavigate(forgotPasswordLink);
716
+ },
717
+ className: "text-primary hover:underline",
718
+ children: t("footer.changeAccount")
719
+ }
720
+ )
721
+ ] }),
722
+ children: /* @__PURE__ */ jsx8(
723
+ ResetPasswordForm,
724
+ {
725
+ verificationId,
726
+ onSubmit: handleSubmit,
727
+ isLoading,
728
+ error
729
+ }
730
+ )
731
+ }
732
+ );
733
+ };
734
+
735
+ // src/components/pages/sign-in-page.tsx
736
+ import { useTranslations as useTranslations7 } from "next-intl";
737
+ import { useState as useState7 } from "react";
738
+
739
+ // src/components/sign-in.tsx
740
+ import { zodResolver as zodResolver3 } from "@hookform/resolvers/zod";
741
+ import { Button as Button4 } from "@mesob/ui/components/button";
742
+ import {
743
+ Form as Form3,
744
+ FormControl as FormControl3,
745
+ FormField as FormField3,
746
+ FormItem as FormItem3,
747
+ FormLabel as FormLabel3,
748
+ FormMessage as FormMessage3
749
+ } from "@mesob/ui/components/form";
750
+ import { Input as Input3 } from "@mesob/ui/components/input";
751
+ import { Eye as Eye2, EyeOff as EyeOff2 } from "lucide-react";
752
+ import { useTranslations as useTranslations6 } from "next-intl";
753
+ import { useMemo as useMemo3, useState as useState6 } from "react";
754
+ import { useForm as useForm3 } from "react-hook-form";
755
+ import { z as z3 } from "zod";
756
+ import { jsx as jsx9, jsxs as jsxs5 } from "react/jsx-runtime";
757
+ var SignIn = ({
758
+ onSubmit,
759
+ isLoading = false,
760
+ identifier = "",
761
+ step = "identifier",
762
+ onBack: _onBack
763
+ }) => {
764
+ const t = useTranslations6("Auth.signIn");
765
+ const [showPassword, setShowPassword] = useState6(false);
766
+ const identifierSchema = useMemo3(
767
+ () => z3.object({
768
+ account: z3.string().min(1, t("errors.accountRequired")).email(t("errors.invalidEmail"))
769
+ }),
770
+ [t]
771
+ );
772
+ const passwordSchema = useMemo3(
773
+ () => z3.object({
774
+ password: z3.string().min(8, t("errors.passwordLength")).max(128, t("errors.longPasswordError"))
775
+ }),
776
+ [t]
777
+ );
778
+ const identifierForm = useForm3({
779
+ resolver: zodResolver3(identifierSchema),
780
+ defaultValues: {
781
+ account: identifier
782
+ }
783
+ });
784
+ const passwordForm = useForm3({
785
+ resolver: zodResolver3(passwordSchema),
786
+ defaultValues: {
787
+ password: ""
788
+ }
789
+ });
790
+ const handleIdentifierSubmit = identifierForm.handleSubmit(async (values) => {
791
+ await onSubmit({ account: values.account, password: "" }, "identifier");
792
+ });
793
+ const handlePasswordSubmit = passwordForm.handleSubmit(async (values) => {
794
+ await onSubmit(
795
+ { account: identifier, password: values.password },
796
+ "password"
797
+ );
798
+ });
799
+ if (step === "password") {
800
+ return /* @__PURE__ */ jsx9(Form3, { ...passwordForm, children: /* @__PURE__ */ jsxs5("form", { onSubmit: handlePasswordSubmit, className: "space-y-4", children: [
801
+ /* @__PURE__ */ jsxs5("div", { className: "text-center", children: [
802
+ /* @__PURE__ */ jsx9("p", { className: "text-sm text-muted-foreground mb-2", children: t("form.enterPasswordFor") }),
803
+ /* @__PURE__ */ jsx9("p", { className: "font-bold", children: identifier })
804
+ ] }),
805
+ /* @__PURE__ */ jsx9(
806
+ FormField3,
807
+ {
808
+ control: passwordForm.control,
809
+ name: "password",
810
+ render: ({ field }) => /* @__PURE__ */ jsxs5(FormItem3, { children: [
811
+ /* @__PURE__ */ jsx9(FormLabel3, { children: t("form.passwordLabel") }),
812
+ /* @__PURE__ */ jsx9(FormControl3, { children: /* @__PURE__ */ jsxs5("div", { className: "relative", children: [
813
+ /* @__PURE__ */ jsx9(
814
+ Input3,
815
+ {
816
+ type: showPassword ? "text" : "password",
817
+ placeholder: t("form.passwordPlaceholder"),
818
+ ...field
819
+ }
820
+ ),
821
+ /* @__PURE__ */ jsx9(
822
+ "button",
823
+ {
824
+ type: "button",
825
+ onClick: () => setShowPassword(!showPassword),
826
+ className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground",
827
+ children: showPassword ? /* @__PURE__ */ jsx9(EyeOff2, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx9(Eye2, { className: "h-4 w-4" })
828
+ }
829
+ )
830
+ ] }) }),
831
+ /* @__PURE__ */ jsx9(FormMessage3, {})
832
+ ] })
833
+ }
834
+ ),
835
+ /* @__PURE__ */ jsx9(Button4, { type: "submit", className: "w-full", disabled: isLoading, children: isLoading ? t("form.submitting") : t("form.submit") })
836
+ ] }) });
837
+ }
838
+ return /* @__PURE__ */ jsx9(Form3, { ...identifierForm, children: /* @__PURE__ */ jsxs5("form", { onSubmit: handleIdentifierSubmit, className: "space-y-4", children: [
839
+ /* @__PURE__ */ jsx9(
840
+ FormField3,
841
+ {
842
+ control: identifierForm.control,
843
+ name: "account",
844
+ render: ({ field }) => /* @__PURE__ */ jsxs5(FormItem3, { children: [
845
+ /* @__PURE__ */ jsx9(FormLabel3, { children: t("form.accountLabel") }),
846
+ /* @__PURE__ */ jsx9(FormControl3, { children: /* @__PURE__ */ jsx9(
847
+ Input3,
848
+ {
849
+ type: "text",
850
+ placeholder: t("form.accountPlaceholder"),
851
+ ...field
852
+ }
853
+ ) }),
854
+ /* @__PURE__ */ jsx9(FormMessage3, {})
855
+ ] })
856
+ }
857
+ ),
858
+ /* @__PURE__ */ jsx9(Button4, { type: "submit", className: "w-full", disabled: isLoading, children: isLoading ? t("form.submitting") : t("form.continue") })
859
+ ] }) });
860
+ };
861
+
862
+ // src/components/pages/sign-in-page.tsx
863
+ import { jsx as jsx10, jsxs as jsxs6 } from "react/jsx-runtime";
864
+ var isPhone = (s) => /^\+?[0-9()[\]\s-]{6,}$/.test(s);
865
+ var SignInPage = ({
866
+ redirectUrl,
867
+ onNavigate,
868
+ linkComponent: Link,
869
+ links,
870
+ logoImage
871
+ }) => {
872
+ const t = useTranslations7("Auth.signIn");
873
+ const { client, setAuth } = useAuth();
874
+ const [isLoading, setIsLoading] = useState7(false);
875
+ const [error, setError] = useState7(null);
876
+ const [step, setStep] = useState7("identifier");
877
+ const [identifier, setIdentifier] = useState7("");
878
+ const defaultRedirect = redirectUrl || "/dashboard";
879
+ const forgotPasswordLink = links?.forgotPassword || "/auth/forgot-password";
880
+ const signUpLink = links?.signUp || "/auth/sign-up";
881
+ const handleSubmit = async (values, currentStep) => {
882
+ setIsLoading(true);
883
+ setError(null);
884
+ try {
885
+ if (currentStep === "identifier") {
886
+ const checkResult = await client.checkUser({
887
+ identifier: values.account
888
+ });
889
+ if (checkResult.exists) {
890
+ setIdentifier(values.account);
891
+ setStep("password");
892
+ } else {
893
+ const email = isPhone(values.account) ? "" : values.account;
894
+ if (email) {
895
+ onNavigate(`${signUpLink}?email=${encodeURIComponent(email)}`);
896
+ } else {
897
+ onNavigate(
898
+ `${signUpLink}?phone=${encodeURIComponent(values.account)}`
899
+ );
900
+ }
901
+ return;
902
+ }
903
+ } else {
904
+ const res = await client.signInWithPassword({
905
+ identifier,
906
+ password: values.password
907
+ });
908
+ if ("verificationId" in res && res.verificationId) {
909
+ const verifyPath = isPhone(identifier) ? `/auth/verify-phone?context=sign-in&verificationId=${res.verificationId}&identifier=${encodeURIComponent(identifier)}` : `/auth/verify-email?verificationId=${res.verificationId}`;
910
+ onNavigate(verifyPath);
911
+ return;
912
+ }
913
+ if ("user" in res && "session" in res) {
914
+ setAuth(res);
915
+ }
916
+ onNavigate(defaultRedirect);
917
+ }
918
+ } catch (err) {
919
+ handleError(err, setError, t);
920
+ } finally {
921
+ setIsLoading(false);
922
+ }
923
+ };
924
+ const handleBack = () => {
925
+ setStep("identifier");
926
+ setIdentifier("");
927
+ setError(null);
928
+ };
929
+ const isStepPassword = step === "password";
930
+ return /* @__PURE__ */ jsx10("div", { className: "space-y-4", children: /* @__PURE__ */ jsx10(
931
+ AuthPageLayout,
932
+ {
933
+ title: t("title"),
934
+ description: isStepPassword ? void 0 : t("description"),
935
+ error,
936
+ logoImage,
937
+ footer: /* @__PURE__ */ jsxs6(
938
+ "div",
939
+ {
940
+ className: "flex items-center justify-center w-full gap-2",
941
+ style: {
942
+ justifyContent: isStepPassword ? "space-between" : "center"
943
+ },
944
+ children: [
945
+ isStepPassword && // biome-ignore lint/a11y/useKeyWithClickEvents: change account
946
+ /* @__PURE__ */ jsx10(
947
+ "p",
948
+ {
949
+ className: "text-primary inline-block cursor-pointer hover:underline",
950
+ onClick: handleBack,
951
+ children: t("changeAccount")
952
+ }
953
+ ),
954
+ Link ? /* @__PURE__ */ jsx10(
955
+ Link,
956
+ {
957
+ href: forgotPasswordLink,
958
+ className: "text-primary inline-block hover:underline",
959
+ children: t("footer.forgotPassword")
960
+ }
961
+ ) : /* @__PURE__ */ jsx10(
962
+ "a",
963
+ {
964
+ href: forgotPasswordLink,
965
+ className: "text-primary inline-block hover:underline",
966
+ children: t("footer.forgotPassword")
967
+ }
968
+ )
969
+ ]
970
+ }
971
+ ),
972
+ children: /* @__PURE__ */ jsx10(
973
+ SignIn,
974
+ {
975
+ onSubmit: handleSubmit,
976
+ isLoading,
977
+ identifier,
978
+ step
979
+ }
980
+ )
981
+ }
982
+ ) });
983
+ };
984
+
985
+ // src/components/pages/sign-up-page.tsx
986
+ import { useTranslations as useTranslations9 } from "next-intl";
987
+ import { useState as useState9 } from "react";
988
+
989
+ // src/components/sign-up.tsx
990
+ import { zodResolver as zodResolver4 } from "@hookform/resolvers/zod";
991
+ import { Button as Button5 } from "@mesob/ui/components/button";
992
+ import {
993
+ Form as Form4,
994
+ FormControl as FormControl4,
995
+ FormField as FormField4,
996
+ FormItem as FormItem4,
997
+ FormLabel as FormLabel4,
998
+ FormMessage as FormMessage4
999
+ } from "@mesob/ui/components/form";
1000
+ import { Input as Input4 } from "@mesob/ui/components/input";
1001
+ import { Eye as Eye3, EyeOff as EyeOff3 } from "lucide-react";
1002
+ import { useTranslations as useTranslations8 } from "next-intl";
1003
+ import { useEffect as useEffect3, useMemo as useMemo4, useState as useState8 } from "react";
1004
+ import { useForm as useForm4 } from "react-hook-form";
1005
+ import { z as z4 } from "zod";
1006
+ import { jsx as jsx11, jsxs as jsxs7 } from "react/jsx-runtime";
1007
+ var isPhone2 = (s) => /^\+?[0-9()[\]\s-]{6,}$/.test(s);
1008
+ var SignUp = ({
1009
+ onSubmit,
1010
+ isLoading = false,
1011
+ initialIdentifier
1012
+ }) => {
1013
+ const t = useTranslations8("Auth.signUp");
1014
+ const hasInitialIdentifier = !!initialIdentifier;
1015
+ const [showPassword, setShowPassword] = useState8(false);
1016
+ const [showConfirmPassword, setShowConfirmPassword] = useState8(false);
1017
+ const signUpSchema = useMemo4(
1018
+ () => z4.object({
1019
+ fullName: z4.string().min(1, t("errors.fullNameRequired")),
1020
+ identifier: z4.string().min(1, t("errors.contactRequired")).refine(
1021
+ (val) => {
1022
+ if (!val) {
1023
+ return false;
1024
+ }
1025
+ return val.includes("@") || isPhone2(val);
1026
+ },
1027
+ {
1028
+ message: t("errors.invalidEmailOrPhone")
1029
+ }
1030
+ ),
1031
+ password: z4.string().min(8, t("errors.passwordLength")).max(128, t("errors.longPasswordError")),
1032
+ confirmPassword: z4.string()
1033
+ }).refine((data) => data.password === data.confirmPassword, {
1034
+ message: t("errors.passwordsMismatch"),
1035
+ path: ["confirmPassword"]
1036
+ }),
1037
+ [t]
1038
+ );
1039
+ const form = useForm4({
1040
+ resolver: zodResolver4(signUpSchema),
1041
+ defaultValues: {
1042
+ fullName: "",
1043
+ identifier: initialIdentifier || "",
1044
+ password: "",
1045
+ confirmPassword: ""
1046
+ }
1047
+ });
1048
+ useEffect3(() => {
1049
+ if (initialIdentifier) {
1050
+ form.setValue("identifier", initialIdentifier);
1051
+ }
1052
+ }, [initialIdentifier, form]);
1053
+ const handleSubmit = form.handleSubmit(async (values) => {
1054
+ await onSubmit(values);
1055
+ });
1056
+ const getIdentifierLabel = () => {
1057
+ if (!hasInitialIdentifier) {
1058
+ return t("form.accountLabel") || "Email/Phone";
1059
+ }
1060
+ if (initialIdentifier?.includes("@")) {
1061
+ return t("form.emailLabel");
1062
+ }
1063
+ return t("form.phoneLabel");
1064
+ };
1065
+ const identifierLabel = getIdentifierLabel();
1066
+ return /* @__PURE__ */ jsx11(Form4, { ...form, children: /* @__PURE__ */ jsxs7("form", { onSubmit: handleSubmit, className: "space-y-4", children: [
1067
+ /* @__PURE__ */ jsx11(
1068
+ FormField4,
1069
+ {
1070
+ control: form.control,
1071
+ name: "fullName",
1072
+ render: ({ field }) => /* @__PURE__ */ jsxs7(FormItem4, { children: [
1073
+ /* @__PURE__ */ jsx11(FormLabel4, { children: t("form.fullNameLabel") }),
1074
+ /* @__PURE__ */ jsx11(FormControl4, { children: /* @__PURE__ */ jsx11(Input4, { placeholder: t("form.fullNamePlaceholder"), ...field }) }),
1075
+ /* @__PURE__ */ jsx11(FormMessage4, {})
1076
+ ] })
1077
+ }
1078
+ ),
1079
+ /* @__PURE__ */ jsx11(
1080
+ FormField4,
1081
+ {
1082
+ control: form.control,
1083
+ name: "identifier",
1084
+ render: ({ field }) => /* @__PURE__ */ jsxs7(FormItem4, { children: [
1085
+ /* @__PURE__ */ jsx11(FormLabel4, { className: hasInitialIdentifier ? "block" : void 0, children: identifierLabel }),
1086
+ /* @__PURE__ */ jsx11(FormControl4, { children: /* @__PURE__ */ jsx11(
1087
+ Input4,
1088
+ {
1089
+ type: field.value.includes("@") ? "email" : "tel",
1090
+ placeholder: hasInitialIdentifier ? void 0 : t("form.accountPlaceholder") || "Email or phone number",
1091
+ ...field,
1092
+ disabled: hasInitialIdentifier
1093
+ }
1094
+ ) }),
1095
+ /* @__PURE__ */ jsx11(FormMessage4, {})
1096
+ ] })
1097
+ }
1098
+ ),
1099
+ /* @__PURE__ */ jsx11(
1100
+ FormField4,
1101
+ {
1102
+ control: form.control,
1103
+ name: "password",
1104
+ render: ({ field }) => /* @__PURE__ */ jsxs7(FormItem4, { children: [
1105
+ /* @__PURE__ */ jsx11(FormLabel4, { children: t("form.passwordLabel") }),
1106
+ /* @__PURE__ */ jsx11(FormControl4, { children: /* @__PURE__ */ jsxs7("div", { className: "relative", children: [
1107
+ /* @__PURE__ */ jsx11(
1108
+ Input4,
1109
+ {
1110
+ type: showPassword ? "text" : "password",
1111
+ placeholder: t("form.passwordPlaceholder"),
1112
+ ...field
1113
+ }
1114
+ ),
1115
+ /* @__PURE__ */ jsx11(
1116
+ "button",
1117
+ {
1118
+ type: "button",
1119
+ onClick: () => setShowPassword(!showPassword),
1120
+ className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground",
1121
+ children: showPassword ? /* @__PURE__ */ jsx11(EyeOff3, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx11(Eye3, { className: "h-4 w-4" })
1122
+ }
1123
+ )
1124
+ ] }) }),
1125
+ /* @__PURE__ */ jsx11(FormMessage4, {})
1126
+ ] })
1127
+ }
1128
+ ),
1129
+ /* @__PURE__ */ jsx11(
1130
+ FormField4,
1131
+ {
1132
+ control: form.control,
1133
+ name: "confirmPassword",
1134
+ render: ({ field }) => /* @__PURE__ */ jsxs7(FormItem4, { children: [
1135
+ /* @__PURE__ */ jsx11(FormLabel4, { children: t("form.confirmPasswordLabel") }),
1136
+ /* @__PURE__ */ jsx11(FormControl4, { children: /* @__PURE__ */ jsxs7("div", { className: "relative", children: [
1137
+ /* @__PURE__ */ jsx11(
1138
+ Input4,
1139
+ {
1140
+ type: showConfirmPassword ? "text" : "password",
1141
+ placeholder: t("form.passwordPlaceholder"),
1142
+ ...field
1143
+ }
1144
+ ),
1145
+ /* @__PURE__ */ jsx11(
1146
+ "button",
1147
+ {
1148
+ type: "button",
1149
+ onClick: () => setShowConfirmPassword(!showConfirmPassword),
1150
+ className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground",
1151
+ children: showConfirmPassword ? /* @__PURE__ */ jsx11(EyeOff3, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx11(Eye3, { className: "h-4 w-4" })
1152
+ }
1153
+ )
1154
+ ] }) }),
1155
+ /* @__PURE__ */ jsx11(FormMessage4, {})
1156
+ ] })
1157
+ }
1158
+ ),
1159
+ /* @__PURE__ */ jsx11(Button5, { type: "submit", className: "w-full", disabled: isLoading, children: isLoading ? t("form.submitting") : t("form.submit") })
1160
+ ] }) });
1161
+ };
1162
+
1163
+ // src/components/pages/sign-up-page.tsx
1164
+ import { jsx as jsx12, jsxs as jsxs8 } from "react/jsx-runtime";
1165
+ var isPhone3 = (s) => /^\+?[0-9()[\]\s-]{6,}$/.test(s);
1166
+ var SignUpPage = ({
1167
+ onNavigate,
1168
+ linkComponent: Link,
1169
+ links,
1170
+ initialIdentifier,
1171
+ logoImage
1172
+ }) => {
1173
+ const t = useTranslations9("Auth.signUp");
1174
+ const { client, setAuth } = useAuth();
1175
+ const [isLoading, setIsLoading] = useState9(false);
1176
+ const [error, setError] = useState9(null);
1177
+ const signInLink = links?.signIn || "/auth/sign-in";
1178
+ const handleSubmit = async (values) => {
1179
+ setIsLoading(true);
1180
+ setError(null);
1181
+ try {
1182
+ const identifier = values.identifier;
1183
+ const usingPhone = isPhone3(identifier);
1184
+ const res = usingPhone ? await client.signUpWithPhone({
1185
+ phone: identifier,
1186
+ password: values.password,
1187
+ fullName: values.fullName,
1188
+ handle: values.handle
1189
+ }) : await client.signUpWithEmail({
1190
+ email: identifier,
1191
+ password: values.password,
1192
+ fullName: values.fullName,
1193
+ handle: values.handle
1194
+ });
1195
+ if ("verificationId" in res && res.verificationId) {
1196
+ if (usingPhone) {
1197
+ onNavigate(
1198
+ `/auth/verify-phone?context=sign-up&verificationId=${res.verificationId}&phone=${encodeURIComponent(identifier)}`
1199
+ );
1200
+ } else {
1201
+ onNavigate(
1202
+ `/auth/verify-email?verificationId=${res.verificationId}&email=${encodeURIComponent(identifier)}`
1203
+ );
1204
+ }
1205
+ return;
1206
+ }
1207
+ if ("user" in res && "session" in res) {
1208
+ setAuth(res);
1209
+ }
1210
+ onNavigate("/dashboard");
1211
+ } catch (err) {
1212
+ handleError(err, setError, t);
1213
+ } finally {
1214
+ setIsLoading(false);
1215
+ }
1216
+ };
1217
+ return /* @__PURE__ */ jsx12(
1218
+ AuthPageLayout,
1219
+ {
1220
+ title: t("title"),
1221
+ description: t("description"),
1222
+ error,
1223
+ logoImage,
1224
+ footer: /* @__PURE__ */ jsxs8("p", { children: [
1225
+ t("footer.hasAccount"),
1226
+ " ",
1227
+ Link ? /* @__PURE__ */ jsx12(Link, { href: signInLink, className: "text-primary hover:underline", children: t("footer.signInCta") }) : /* @__PURE__ */ jsx12(
1228
+ "a",
1229
+ {
1230
+ href: signInLink,
1231
+ onClick: (e) => {
1232
+ e.preventDefault();
1233
+ onNavigate(signInLink);
1234
+ },
1235
+ className: "text-primary hover:underline",
1236
+ children: t("footer.signInCta")
1237
+ }
1238
+ )
1239
+ ] }),
1240
+ children: /* @__PURE__ */ jsx12(
1241
+ SignUp,
1242
+ {
1243
+ onSubmit: handleSubmit,
1244
+ isLoading,
1245
+ initialIdentifier
1246
+ }
1247
+ )
1248
+ }
1249
+ );
1250
+ };
1251
+
1252
+ // src/components/pages/verify-email-page.tsx
1253
+ import { useTranslations as useTranslations11 } from "next-intl";
1254
+ import { useState as useState10 } from "react";
1255
+
1256
+ // src/components/verification-form.tsx
1257
+ import { zodResolver as zodResolver5 } from "@hookform/resolvers/zod";
1258
+ import { Button as Button6 } from "@mesob/ui/components/button";
1259
+ import {
1260
+ Form as Form5,
1261
+ FormControl as FormControl5,
1262
+ FormField as FormField5,
1263
+ FormItem as FormItem5,
1264
+ FormMessage as FormMessage5
1265
+ } from "@mesob/ui/components/form";
1266
+ import {
1267
+ InputOTP as InputOTP2,
1268
+ InputOTPGroup as InputOTPGroup2,
1269
+ InputOTPSlot as InputOTPSlot2
1270
+ } from "@mesob/ui/components/input-otp";
1271
+ import { useTranslations as useTranslations10 } from "next-intl";
1272
+ import { useMemo as useMemo5 } from "react";
1273
+ import { useForm as useForm5 } from "react-hook-form";
1274
+ import { z as z5 } from "zod";
1275
+ import { jsx as jsx13, jsxs as jsxs9 } from "react/jsx-runtime";
1276
+ var VerificationForm = ({
1277
+ onSubmit,
1278
+ onResend,
1279
+ isLoading = false
1280
+ }) => {
1281
+ const t = useTranslations10("Auth.verification");
1282
+ const verificationSchema = useMemo5(
1283
+ () => z5.object({
1284
+ code: z5.string().length(6, t("form.codeLength"))
1285
+ }),
1286
+ [t]
1287
+ );
1288
+ const form = useForm5({
1289
+ resolver: zodResolver5(verificationSchema),
1290
+ defaultValues: {
1291
+ code: ""
1292
+ }
1293
+ });
1294
+ const handleComplete = async (value) => {
1295
+ const valid = await form.trigger("code");
1296
+ if (valid) {
1297
+ await onSubmit({ code: value });
1298
+ }
1299
+ };
1300
+ return /* @__PURE__ */ jsx13(Form5, { ...form, children: /* @__PURE__ */ jsxs9("form", { className: "space-y-4", children: [
1301
+ /* @__PURE__ */ jsx13(
1302
+ FormField5,
1303
+ {
1304
+ control: form.control,
1305
+ name: "code",
1306
+ render: ({ field }) => /* @__PURE__ */ jsxs9(FormItem5, { children: [
1307
+ /* @__PURE__ */ jsx13(FormControl5, { children: /* @__PURE__ */ jsx13("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx13(
1308
+ InputOTP2,
1309
+ {
1310
+ maxLength: 6,
1311
+ value: field.value,
1312
+ onChange: (value) => {
1313
+ field.onChange(value);
1314
+ if (value.length === 6) {
1315
+ handleComplete(value);
1316
+ }
1317
+ },
1318
+ disabled: isLoading,
1319
+ children: /* @__PURE__ */ jsxs9(InputOTPGroup2, { children: [
1320
+ /* @__PURE__ */ jsx13(InputOTPSlot2, { index: 0 }),
1321
+ /* @__PURE__ */ jsx13(InputOTPSlot2, { index: 1 }),
1322
+ /* @__PURE__ */ jsx13(InputOTPSlot2, { index: 2 }),
1323
+ /* @__PURE__ */ jsx13(InputOTPSlot2, { index: 3 }),
1324
+ /* @__PURE__ */ jsx13(InputOTPSlot2, { index: 4 }),
1325
+ /* @__PURE__ */ jsx13(InputOTPSlot2, { index: 5 })
1326
+ ] })
1327
+ }
1328
+ ) }) }),
1329
+ /* @__PURE__ */ jsx13(FormMessage5, {})
1330
+ ] })
1331
+ }
1332
+ ),
1333
+ /* @__PURE__ */ jsxs9("div", { className: "flex justify-between items-center", children: [
1334
+ /* @__PURE__ */ jsx13(Countdown, { onResend, resending: isLoading }),
1335
+ /* @__PURE__ */ jsx13(
1336
+ Button6,
1337
+ {
1338
+ type: "button",
1339
+ onClick: () => {
1340
+ form.handleSubmit(async (values) => {
1341
+ await onSubmit(values);
1342
+ })();
1343
+ },
1344
+ disabled: isLoading || form.watch("code").length !== 6,
1345
+ children: t("form.confirm")
1346
+ }
1347
+ )
1348
+ ] })
1349
+ ] }) });
1350
+ };
1351
+
1352
+ // src/components/pages/verify-email-page.tsx
1353
+ import { jsx as jsx14 } from "react/jsx-runtime";
1354
+ var VerifyEmailPage = ({
1355
+ verificationId,
1356
+ onNavigate,
1357
+ linkComponent: Link,
1358
+ links,
1359
+ email,
1360
+ logoImage
1361
+ }) => {
1362
+ const t = useTranslations11("Auth.verification");
1363
+ const common = useTranslations11("Common");
1364
+ const footer = useTranslations11("Auth.forgotPassword.footer");
1365
+ const { client, setAuth } = useAuth();
1366
+ const [isLoading, setIsLoading] = useState10(false);
1367
+ const [error, setError] = useState10(null);
1368
+ const signInLink = links?.signIn || "/auth/sign-in";
1369
+ const handleSubmit = async (values) => {
1370
+ if (!verificationId) {
1371
+ setError(t("errors.missingVerificationId"));
1372
+ return;
1373
+ }
1374
+ setIsLoading(true);
1375
+ setError(null);
1376
+ try {
1377
+ const res = await client.verifyEmail({
1378
+ verificationId,
1379
+ code: values.code
1380
+ });
1381
+ if ("user" in res && "session" in res) {
1382
+ setAuth(res);
1383
+ }
1384
+ onNavigate("/dashboard");
1385
+ } catch (err) {
1386
+ handleError(err, setError, t);
1387
+ } finally {
1388
+ setIsLoading(false);
1389
+ }
1390
+ };
1391
+ const handleResend = async () => {
1392
+ setError(null);
1393
+ try {
1394
+ const res = await client.requestEmailVerification({ email });
1395
+ if (res.verificationId) {
1396
+ onNavigate(
1397
+ `/auth/verify-email?verificationId=${res.verificationId}&email=${encodeURIComponent(email)}`
1398
+ );
1399
+ } else {
1400
+ setError(t("errors.resendFailed"));
1401
+ }
1402
+ } catch (err) {
1403
+ handleError(err, setError, t);
1404
+ }
1405
+ };
1406
+ if (!verificationId) {
1407
+ return /* @__PURE__ */ jsx14(
1408
+ AuthPageLayout,
1409
+ {
1410
+ title: common("invalidLinkTitle"),
1411
+ description: common("invalidLinkDescription"),
1412
+ footer: Link ? /* @__PURE__ */ jsx14(Link, { href: signInLink, className: "text-primary hover:underline", children: footer("backToSignIn") }) : /* @__PURE__ */ jsx14(
1413
+ "a",
1414
+ {
1415
+ href: signInLink,
1416
+ onClick: (e) => {
1417
+ e.preventDefault();
1418
+ onNavigate(signInLink);
1419
+ },
1420
+ className: "text-primary hover:underline",
1421
+ children: footer("backToSignIn")
1422
+ }
1423
+ ),
1424
+ children: /* @__PURE__ */ jsx14("div", {})
1425
+ }
1426
+ );
1427
+ }
1428
+ return /* @__PURE__ */ jsx14(
1429
+ AuthPageLayout,
1430
+ {
1431
+ title: t("email.title"),
1432
+ description: t("email.description"),
1433
+ error,
1434
+ logoImage,
1435
+ footer: Link ? /* @__PURE__ */ jsx14(Link, { href: signInLink, className: "text-primary hover:underline", children: footer("backToSignIn") }) : /* @__PURE__ */ jsx14(
1436
+ "a",
1437
+ {
1438
+ href: signInLink,
1439
+ onClick: (e) => {
1440
+ e.preventDefault();
1441
+ onNavigate(signInLink);
1442
+ },
1443
+ className: "text-primary hover:underline",
1444
+ children: footer("backToSignIn")
1445
+ }
1446
+ ),
1447
+ children: /* @__PURE__ */ jsx14(
1448
+ VerificationForm,
1449
+ {
1450
+ verificationId,
1451
+ onSubmit: handleSubmit,
1452
+ onResend: handleResend,
1453
+ isLoading,
1454
+ error
1455
+ }
1456
+ )
1457
+ }
1458
+ );
1459
+ };
1460
+
1461
+ // src/components/pages/verify-phone-page.tsx
1462
+ import { useTranslations as useTranslations12 } from "next-intl";
1463
+ import { useState as useState11 } from "react";
1464
+ import { jsx as jsx15 } from "react/jsx-runtime";
1465
+ var VerifyPhonePage = ({
1466
+ verificationId,
1467
+ context,
1468
+ phone = "",
1469
+ onNavigate,
1470
+ linkComponent: Link,
1471
+ links,
1472
+ logoImage
1473
+ }) => {
1474
+ const t = useTranslations12("Auth.verification");
1475
+ const common = useTranslations12("Common");
1476
+ const footer = useTranslations12("Auth.forgotPassword.footer");
1477
+ const { client, refresh, setAuth } = useAuth();
1478
+ const [isLoading, setIsLoading] = useState11(false);
1479
+ const [error, setError] = useState11(null);
1480
+ const signInLink = links?.signIn || "/auth/sign-in";
1481
+ const handleSubmit = async (values) => {
1482
+ if (!verificationId) {
1483
+ setError(t("errors.fallback"));
1484
+ return;
1485
+ }
1486
+ setIsLoading(true);
1487
+ setError(null);
1488
+ try {
1489
+ const res = await client.verifyPhoneOtp({
1490
+ verificationId,
1491
+ code: values.code,
1492
+ context
1493
+ });
1494
+ if (res && "user" in res && "session" in res && res.session) {
1495
+ setAuth(res);
1496
+ onNavigate("/dashboard");
1497
+ return;
1498
+ }
1499
+ await refresh();
1500
+ onNavigate("/dashboard");
1501
+ } catch (err) {
1502
+ handleError(err, setError, t);
1503
+ } finally {
1504
+ setIsLoading(false);
1505
+ }
1506
+ };
1507
+ const handleResend = async () => {
1508
+ setError(null);
1509
+ try {
1510
+ const targetPhone = context === "sign-up" ? phone : null;
1511
+ if (!targetPhone) {
1512
+ setError(t("phone.missingPhone"));
1513
+ return;
1514
+ }
1515
+ const res = await client.requestPhoneOtp({ phone: targetPhone, context });
1516
+ if (res && "verificationId" in res && res.verificationId) {
1517
+ onNavigate(
1518
+ `/auth/verify-phone?context=${context}&verificationId=${res.verificationId}&phone=${targetPhone}`
1519
+ );
1520
+ return;
1521
+ }
1522
+ setError(t("phone.resendFailed"));
1523
+ } catch (err) {
1524
+ handleError(err, setError, t);
1525
+ }
1526
+ };
1527
+ if (!verificationId) {
1528
+ return /* @__PURE__ */ jsx15(
1529
+ AuthPageLayout,
1530
+ {
1531
+ title: common("invalidLinkTitle"),
1532
+ description: common("invalidLinkDescription"),
1533
+ footer: Link ? /* @__PURE__ */ jsx15(Link, { href: signInLink, className: "text-primary hover:underline", children: footer("backToSignIn") }) : /* @__PURE__ */ jsx15(
1534
+ "a",
1535
+ {
1536
+ href: signInLink,
1537
+ onClick: (e) => {
1538
+ e.preventDefault();
1539
+ onNavigate(signInLink);
1540
+ },
1541
+ className: "text-primary hover:underline",
1542
+ children: footer("backToSignIn")
1543
+ }
1544
+ ),
1545
+ children: /* @__PURE__ */ jsx15("div", {})
1546
+ }
1547
+ );
1548
+ }
1549
+ return /* @__PURE__ */ jsx15(
1550
+ AuthPageLayout,
1551
+ {
1552
+ title: t("phone.title"),
1553
+ description: t("phone.description", {
1554
+ target: phone || t("phone.missingPhone")
1555
+ }),
1556
+ error,
1557
+ logoImage,
1558
+ footer: Link ? /* @__PURE__ */ jsx15(Link, { href: signInLink, className: "text-primary hover:underline", children: footer("backToSignIn") }) : /* @__PURE__ */ jsx15(
1559
+ "a",
1560
+ {
1561
+ href: signInLink,
1562
+ onClick: (e) => {
1563
+ e.preventDefault();
1564
+ onNavigate(signInLink);
1565
+ },
1566
+ className: "text-primary hover:underline",
1567
+ children: footer("backToSignIn")
1568
+ }
1569
+ ),
1570
+ children: /* @__PURE__ */ jsx15(
1571
+ VerificationForm,
1572
+ {
1573
+ verificationId,
1574
+ onSubmit: handleSubmit,
1575
+ onResend: handleResend,
1576
+ isLoading,
1577
+ error
1578
+ }
1579
+ )
1580
+ }
1581
+ );
1582
+ };
1583
+
1584
+ // src/factory.ts
1585
+ var createAuthClient = (config) => {
1586
+ const client = new AuthClient(config);
1587
+ return {
1588
+ signUpWithEmail: client.signUpWithEmail.bind(client),
1589
+ signUpWithPhone: client.signUpWithPhone.bind(client),
1590
+ signInWithPassword: client.signInWithPassword.bind(client),
1591
+ signOut: client.signOut.bind(client),
1592
+ requestEmailVerification: client.requestEmailVerification.bind(client),
1593
+ verifyEmail: client.verifyEmail.bind(client),
1594
+ resendVerification: client.resendVerification.bind(client),
1595
+ requestPhoneOtp: client.requestPhoneOtp.bind(client),
1596
+ verifyPhoneOtp: client.verifyPhoneOtp.bind(client),
1597
+ forgotPassword: client.forgotPassword.bind(client),
1598
+ resetPassword: client.resetPassword.bind(client),
1599
+ changePassword: client.changePassword.bind(client),
1600
+ getSession: client.getSession.bind(client),
1601
+ useSession: () => {
1602
+ throw new Error("useSession must be used within AuthProvider");
1603
+ }
1604
+ };
1605
+ };
1606
+
1607
+ // src/hooks/use-session.ts
1608
+ var useSession = () => {
1609
+ const { user, session, loading, error, refresh } = useAuth();
1610
+ return {
1611
+ user,
1612
+ session,
1613
+ isLoading: loading,
1614
+ isAuthenticated: !!user && !!session,
1615
+ error,
1616
+ refresh
1617
+ };
1618
+ };
1619
+ export {
1620
+ AuthCard,
1621
+ AuthClient,
1622
+ AuthPageLayout,
1623
+ AuthProvider,
1624
+ Countdown,
1625
+ ForgotPassword,
1626
+ ForgotPasswordPage,
1627
+ ResetPasswordForm,
1628
+ ResetPasswordPage,
1629
+ SignIn,
1630
+ SignInPage,
1631
+ SignUp,
1632
+ SignUpPage,
1633
+ VerificationForm,
1634
+ VerifyEmailPage,
1635
+ VerifyPhonePage,
1636
+ createAuthClient,
1637
+ useAuth,
1638
+ useSession
1639
+ };
1640
+ //# sourceMappingURL=index.js.map