@mesob/auth-react 0.0.3 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/auth/auth-card.js +11 -0
- package/dist/components/auth/auth-card.js.map +1 -0
- package/dist/components/{auth-page-layout.d.ts → auth/auth-page-layout.d.ts} +2 -1
- package/dist/components/{auth-page-layout.js → auth/auth-page-layout.js} +16 -3
- package/dist/components/auth/auth-page-layout.js.map +1 -0
- package/dist/components/{countdown.js → auth/countdown.js} +8 -4
- package/dist/components/auth/countdown.js.map +1 -0
- package/dist/components/{forgot-password.d.ts → auth/forgot-password.d.ts} +1 -1
- package/dist/components/{forgot-password.js → auth/forgot-password.js} +7 -4
- package/dist/components/auth/forgot-password.js.map +1 -0
- package/dist/components/{pages → auth/pages}/forgot-password-page.js +94 -28
- package/dist/components/auth/pages/forgot-password-page.js.map +1 -0
- package/dist/components/{pages → auth/pages}/reset-password-page.d.ts +2 -1
- package/dist/components/{pages → auth/pages}/reset-password-page.js +111 -42
- package/dist/components/auth/pages/reset-password-page.js.map +1 -0
- package/dist/components/{pages → auth/pages}/sign-in-page.js +130 -30
- package/dist/components/auth/pages/sign-in-page.js.map +1 -0
- package/dist/components/{pages → auth/pages}/sign-up-page.d.ts +2 -1
- package/dist/components/{pages → auth/pages}/sign-up-page.js +93 -29
- package/dist/components/auth/pages/sign-up-page.js.map +1 -0
- package/dist/components/{pages → auth/pages}/verify-email-page.d.ts +2 -1
- package/dist/components/{pages → auth/pages}/verify-email-page.js +131 -61
- package/dist/components/auth/pages/verify-email-page.js.map +1 -0
- package/dist/components/{pages → auth/pages}/verify-phone-page.d.ts +2 -1
- package/dist/components/{pages → auth/pages}/verify-phone-page.js +136 -63
- package/dist/components/auth/pages/verify-phone-page.js.map +1 -0
- package/dist/components/{reset-password-form.d.ts → auth/reset-password-form.d.ts} +3 -2
- package/dist/components/{reset-password-form.js → auth/reset-password-form.js} +17 -15
- package/dist/components/auth/reset-password-form.js.map +1 -0
- package/dist/components/{sign-in.js → auth/sign-in.js} +43 -6
- package/dist/components/auth/sign-in.js.map +1 -0
- package/dist/components/{sign-up.js → auth/sign-up.js} +4 -4
- package/dist/components/auth/sign-up.js.map +1 -0
- package/dist/components/{verification-form.d.ts → auth/verification-form.d.ts} +2 -1
- package/dist/components/{verification-form.js → auth/verification-form.js} +33 -33
- package/dist/components/auth/verification-form.js.map +1 -0
- package/dist/handle-error-H0iqQxJ5.d.ts +6 -0
- package/dist/index.d.ts +49 -15
- package/dist/index.js +304 -142
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/dist/components/auth-card.js +0 -11
- package/dist/components/auth-card.js.map +0 -1
- package/dist/components/auth-page-layout.js.map +0 -1
- package/dist/components/countdown.js.map +0 -1
- package/dist/components/forgot-password.js.map +0 -1
- package/dist/components/pages/forgot-password-page.js.map +0 -1
- package/dist/components/pages/reset-password-page.js.map +0 -1
- package/dist/components/pages/sign-in-page.js.map +0 -1
- package/dist/components/pages/sign-up-page.js.map +0 -1
- package/dist/components/pages/verify-email-page.js.map +0 -1
- package/dist/components/pages/verify-phone-page.js.map +0 -1
- package/dist/components/reset-password-form.js.map +0 -1
- package/dist/components/sign-in.js.map +0 -1
- package/dist/components/sign-up.js.map +0 -1
- package/dist/components/verification-form.js.map +0 -1
- /package/dist/components/{auth-card.d.ts → auth/auth-card.d.ts} +0 -0
- /package/dist/components/{countdown.d.ts → auth/countdown.d.ts} +0 -0
- /package/dist/components/{pages → auth/pages}/forgot-password-page.d.ts +0 -0
- /package/dist/components/{pages → auth/pages}/sign-in-page.d.ts +0 -0
- /package/dist/components/{sign-in.d.ts → auth/sign-in.d.ts} +0 -0
- /package/dist/components/{sign-up.d.ts → auth/sign-up.d.ts} +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
// src/components/pages/verify-email-page.tsx
|
|
3
|
+
// src/components/auth/pages/verify-email-page.tsx
|
|
4
4
|
import { useTranslations as useTranslations3 } from "next-intl";
|
|
5
5
|
import { useState as useState3 } from "react";
|
|
6
6
|
|
|
@@ -37,40 +37,95 @@ var AuthError = class extends Error {
|
|
|
37
37
|
};
|
|
38
38
|
|
|
39
39
|
// src/constants/auth.error.codes.ts
|
|
40
|
-
var
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
40
|
+
var AUTH_ERROR_MAPPING = {
|
|
41
|
+
USER_NOT_FOUND: {
|
|
42
|
+
title: "Account Not Found",
|
|
43
|
+
description: "We could not find an account with that identifier. Please check your spelling or sign up."
|
|
44
|
+
},
|
|
45
|
+
INVALID_PASSWORD: {
|
|
46
|
+
title: "Invalid Password",
|
|
47
|
+
description: "The password you entered is incorrect. Please try again."
|
|
48
|
+
},
|
|
49
|
+
USER_EXISTS: {
|
|
50
|
+
title: "Account Already Exists",
|
|
51
|
+
description: "An account with this identifier already exists. Please sign in instead."
|
|
52
|
+
},
|
|
53
|
+
VERIFICATION_EXPIRED: {
|
|
54
|
+
title: "Verification Expired",
|
|
55
|
+
description: "The verification code or link has expired. Please request a new one."
|
|
56
|
+
},
|
|
57
|
+
VERIFICATION_MISMATCH: {
|
|
58
|
+
title: "Invalid Code",
|
|
59
|
+
description: "The verification code you entered is invalid. Please double-check and try again."
|
|
60
|
+
},
|
|
61
|
+
VERIFICATION_NOT_FOUND: {
|
|
62
|
+
title: "Verification Not Found",
|
|
63
|
+
description: "We could not find a pending verification request. Please restart the process."
|
|
64
|
+
},
|
|
65
|
+
TOO_MANY_ATTEMPTS: {
|
|
66
|
+
title: "Too Many Attempts",
|
|
67
|
+
description: "You have made too many requests recently. Please wait a moment before trying again."
|
|
68
|
+
},
|
|
69
|
+
REQUIRES_VERIFICATION: {
|
|
70
|
+
title: "Verification Required",
|
|
71
|
+
description: "You need to verify your account before you can continue. Please check your email or phone."
|
|
72
|
+
},
|
|
73
|
+
UNAUTHORIZED: {
|
|
74
|
+
title: "Unauthorized",
|
|
75
|
+
description: "You are not authorized to perform this action. Please sign in again."
|
|
76
|
+
},
|
|
77
|
+
ACCESS_DENIED: {
|
|
78
|
+
title: "Access Denied",
|
|
79
|
+
description: "You do not have permission to access this resource. Please contact support if you believe this is an error."
|
|
80
|
+
},
|
|
81
|
+
HAS_NO_PASSWORD: {
|
|
82
|
+
title: "No Password Set",
|
|
83
|
+
description: "Your account does not have a password set (e.g. social login). Please sign in with your provider or reset your password."
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
var validCodes = Object.keys(AUTH_ERROR_MAPPING);
|
|
53
87
|
|
|
54
88
|
// src/utils/handle-error.ts
|
|
55
89
|
var handleError = (err, setError, t) => {
|
|
56
90
|
if (err instanceof AuthError) {
|
|
57
|
-
let
|
|
58
|
-
if (err.code) {
|
|
59
|
-
|
|
91
|
+
let errorCode = "";
|
|
92
|
+
if (err.code && validCodes.includes(err.code)) {
|
|
93
|
+
errorCode = err.code;
|
|
60
94
|
} else if (err.message) {
|
|
61
95
|
const messageUpper = err.message.toUpperCase().trim();
|
|
62
96
|
if (validCodes.includes(messageUpper)) {
|
|
63
|
-
|
|
97
|
+
errorCode = messageUpper;
|
|
64
98
|
}
|
|
65
99
|
}
|
|
66
|
-
|
|
100
|
+
if (errorCode && AUTH_ERROR_MAPPING[errorCode]) {
|
|
101
|
+
const mapping = AUTH_ERROR_MAPPING[errorCode];
|
|
102
|
+
setError({
|
|
103
|
+
title: mapping.title,
|
|
104
|
+
description: mapping.description
|
|
105
|
+
});
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
setError({
|
|
109
|
+
title: t("errors.fallback"),
|
|
110
|
+
// or 'Error'
|
|
111
|
+
description: err.message || t("errors.fallback")
|
|
112
|
+
});
|
|
67
113
|
} else {
|
|
68
|
-
|
|
114
|
+
const message = err instanceof Error ? err.message : t("errors.fallback");
|
|
115
|
+
setError({
|
|
116
|
+
title: "Error",
|
|
117
|
+
description: message
|
|
118
|
+
});
|
|
69
119
|
}
|
|
70
120
|
};
|
|
71
121
|
|
|
72
|
-
// src/components/auth-page-layout.tsx
|
|
73
|
-
import {
|
|
122
|
+
// src/components/auth/auth-page-layout.tsx
|
|
123
|
+
import {
|
|
124
|
+
Alert,
|
|
125
|
+
AlertDescription,
|
|
126
|
+
AlertTitle
|
|
127
|
+
} from "@mesob/ui/components/alert";
|
|
128
|
+
import { IconAlertCircle } from "@tabler/icons-react";
|
|
74
129
|
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
75
130
|
var AuthPageLayout = ({
|
|
76
131
|
title,
|
|
@@ -80,6 +135,10 @@ var AuthPageLayout = ({
|
|
|
80
135
|
footer,
|
|
81
136
|
logoImage
|
|
82
137
|
}) => {
|
|
138
|
+
const errorContent = error ? (
|
|
139
|
+
// biome-ignore lint/style/noNestedTernary: <explanation>
|
|
140
|
+
typeof error === "string" ? { title: "Error", description: error } : error
|
|
141
|
+
) : null;
|
|
83
142
|
return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
84
143
|
/* @__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 }) }),
|
|
85
144
|
/* @__PURE__ */ jsxs("div", { className: "text-center", children: [
|
|
@@ -87,12 +146,16 @@ var AuthPageLayout = ({
|
|
|
87
146
|
description && /* @__PURE__ */ jsx2("p", { className: "mt-2 text-sm text-muted-foreground", children: description })
|
|
88
147
|
] }),
|
|
89
148
|
children,
|
|
90
|
-
|
|
149
|
+
errorContent && /* @__PURE__ */ jsxs(Alert, { variant: "destructive", children: [
|
|
150
|
+
/* @__PURE__ */ jsx2(IconAlertCircle, { className: "h-4 w-4" }),
|
|
151
|
+
/* @__PURE__ */ jsx2(AlertTitle, { children: errorContent.title }),
|
|
152
|
+
/* @__PURE__ */ jsx2(AlertDescription, { children: errorContent.description })
|
|
153
|
+
] }),
|
|
91
154
|
/* @__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 }) })
|
|
92
155
|
] });
|
|
93
156
|
};
|
|
94
157
|
|
|
95
|
-
// src/components/verification-form.tsx
|
|
158
|
+
// src/components/auth/verification-form.tsx
|
|
96
159
|
import { zodResolver } from "@hookform/resolvers/zod";
|
|
97
160
|
import { Button as Button2 } from "@mesob/ui/components/button";
|
|
98
161
|
import {
|
|
@@ -107,16 +170,18 @@ import {
|
|
|
107
170
|
InputOTPGroup,
|
|
108
171
|
InputOTPSlot
|
|
109
172
|
} from "@mesob/ui/components/input-otp";
|
|
173
|
+
import { Spinner as Spinner2 } from "@mesob/ui/components/spinner";
|
|
110
174
|
import { useTranslations as useTranslations2 } from "next-intl";
|
|
111
175
|
import { useMemo } from "react";
|
|
112
176
|
import { useForm } from "react-hook-form";
|
|
113
177
|
import { z } from "zod";
|
|
114
178
|
|
|
115
|
-
// src/components/countdown.tsx
|
|
179
|
+
// src/components/auth/countdown.tsx
|
|
116
180
|
import { Button } from "@mesob/ui/components/button";
|
|
181
|
+
import { Spinner } from "@mesob/ui/components/spinner";
|
|
117
182
|
import { useTranslations } from "next-intl";
|
|
118
183
|
import { useEffect as useEffect2, useState as useState2 } from "react";
|
|
119
|
-
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
184
|
+
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
120
185
|
var Countdown = ({
|
|
121
186
|
initialSeconds = 60,
|
|
122
187
|
onResend,
|
|
@@ -153,19 +218,22 @@ var Countdown = ({
|
|
|
153
218
|
if (seconds > 0) {
|
|
154
219
|
return /* @__PURE__ */ jsx3(Button, { variant: "ghost", disabled: true, children: t("resendIn", { seconds }) });
|
|
155
220
|
}
|
|
156
|
-
return /* @__PURE__ */
|
|
221
|
+
return /* @__PURE__ */ jsxs2(
|
|
157
222
|
Button,
|
|
158
223
|
{
|
|
159
224
|
variant: "ghost",
|
|
160
225
|
onClick: handleResend,
|
|
161
226
|
disabled: isResending || resending,
|
|
162
|
-
children:
|
|
227
|
+
children: [
|
|
228
|
+
isResending || resending && /* @__PURE__ */ jsx3(Spinner, {}),
|
|
229
|
+
t("resend")
|
|
230
|
+
]
|
|
163
231
|
}
|
|
164
232
|
);
|
|
165
233
|
};
|
|
166
234
|
|
|
167
|
-
// src/components/verification-form.tsx
|
|
168
|
-
import { jsx as jsx4, jsxs as
|
|
235
|
+
// src/components/auth/verification-form.tsx
|
|
236
|
+
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
169
237
|
var VerificationForm = ({
|
|
170
238
|
onSubmit,
|
|
171
239
|
onResend,
|
|
@@ -184,38 +252,30 @@ var VerificationForm = ({
|
|
|
184
252
|
code: ""
|
|
185
253
|
}
|
|
186
254
|
});
|
|
187
|
-
|
|
188
|
-
const valid = await form.trigger("code");
|
|
189
|
-
if (valid) {
|
|
190
|
-
await onSubmit({ code: value });
|
|
191
|
-
}
|
|
192
|
-
};
|
|
193
|
-
return /* @__PURE__ */ jsx4(Form, { ...form, children: /* @__PURE__ */ jsxs2("form", { className: "space-y-4", children: [
|
|
255
|
+
return /* @__PURE__ */ jsx4(Form, { ...form, children: /* @__PURE__ */ jsxs3("form", { className: "space-y-4", children: [
|
|
194
256
|
/* @__PURE__ */ jsx4(
|
|
195
257
|
FormField,
|
|
196
258
|
{
|
|
197
259
|
control: form.control,
|
|
198
260
|
name: "code",
|
|
199
|
-
render: ({ field }) => /* @__PURE__ */
|
|
261
|
+
render: ({ field }) => /* @__PURE__ */ jsxs3(FormItem, { children: [
|
|
200
262
|
/* @__PURE__ */ jsx4(FormControl, { children: /* @__PURE__ */ jsx4("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx4(
|
|
201
263
|
InputOTP,
|
|
202
264
|
{
|
|
203
265
|
maxLength: 6,
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
/* @__PURE__ */ jsx4(InputOTPSlot, { index:
|
|
214
|
-
/* @__PURE__ */ jsx4(InputOTPSlot, { index:
|
|
215
|
-
/* @__PURE__ */ jsx4(InputOTPSlot, { index:
|
|
216
|
-
/* @__PURE__ */ jsx4(InputOTPSlot, { index:
|
|
217
|
-
/* @__PURE__ */ jsx4(InputOTPSlot, { index: 4 }),
|
|
218
|
-
/* @__PURE__ */ jsx4(InputOTPSlot, { index: 5 })
|
|
266
|
+
id: "otp",
|
|
267
|
+
required: true,
|
|
268
|
+
value: field.value ?? "",
|
|
269
|
+
onChange: field.onChange,
|
|
270
|
+
onBlur: field.onBlur,
|
|
271
|
+
containerClassName: "gap-4 justify-center mb-2 flex items-center",
|
|
272
|
+
children: /* @__PURE__ */ jsxs3(InputOTPGroup, { className: "gap-3 *:data-[slot=input-otp-slot]:h-12 *:data-[slot=input-otp-slot]:w-12 *:data-[slot=input-otp-slot]:rounded-md *:data-[slot=input-otp-slot]:border *:data-[slot=input-otp-slot]:text-xl", children: [
|
|
273
|
+
/* @__PURE__ */ jsx4(InputOTPSlot, { className: "h-12", index: 0 }),
|
|
274
|
+
/* @__PURE__ */ jsx4(InputOTPSlot, { className: "h-12", index: 1 }),
|
|
275
|
+
/* @__PURE__ */ jsx4(InputOTPSlot, { className: "h-12", index: 2 }),
|
|
276
|
+
/* @__PURE__ */ jsx4(InputOTPSlot, { className: "h-12", index: 3 }),
|
|
277
|
+
/* @__PURE__ */ jsx4(InputOTPSlot, { className: "h-12", index: 4 }),
|
|
278
|
+
/* @__PURE__ */ jsx4(InputOTPSlot, { className: "h-12", index: 5 })
|
|
219
279
|
] })
|
|
220
280
|
}
|
|
221
281
|
) }) }),
|
|
@@ -223,9 +283,9 @@ var VerificationForm = ({
|
|
|
223
283
|
] })
|
|
224
284
|
}
|
|
225
285
|
),
|
|
226
|
-
/* @__PURE__ */
|
|
286
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex justify-between items-center", children: [
|
|
227
287
|
/* @__PURE__ */ jsx4(Countdown, { onResend, resending: isLoading }),
|
|
228
|
-
/* @__PURE__ */
|
|
288
|
+
/* @__PURE__ */ jsxs3(
|
|
229
289
|
Button2,
|
|
230
290
|
{
|
|
231
291
|
type: "button",
|
|
@@ -235,14 +295,17 @@ var VerificationForm = ({
|
|
|
235
295
|
})();
|
|
236
296
|
},
|
|
237
297
|
disabled: isLoading || form.watch("code").length !== 6,
|
|
238
|
-
children:
|
|
298
|
+
children: [
|
|
299
|
+
isLoading && /* @__PURE__ */ jsx4(Spinner2, {}),
|
|
300
|
+
t("form.confirm")
|
|
301
|
+
]
|
|
239
302
|
}
|
|
240
303
|
)
|
|
241
304
|
] })
|
|
242
305
|
] }) });
|
|
243
306
|
};
|
|
244
307
|
|
|
245
|
-
// src/components/pages/verify-email-page.tsx
|
|
308
|
+
// src/components/auth/pages/verify-email-page.tsx
|
|
246
309
|
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
247
310
|
var VerifyEmailPage = ({
|
|
248
311
|
verificationId,
|
|
@@ -250,7 +313,8 @@ var VerifyEmailPage = ({
|
|
|
250
313
|
linkComponent: Link,
|
|
251
314
|
links,
|
|
252
315
|
email,
|
|
253
|
-
logoImage
|
|
316
|
+
logoImage,
|
|
317
|
+
redirectUrl
|
|
254
318
|
}) => {
|
|
255
319
|
const t = useTranslations3("Auth.verification");
|
|
256
320
|
const common = useTranslations3("Common");
|
|
@@ -261,7 +325,10 @@ var VerifyEmailPage = ({
|
|
|
261
325
|
const signInLink = links?.signIn || "/auth/sign-in";
|
|
262
326
|
const handleSubmit = async (values) => {
|
|
263
327
|
if (!verificationId) {
|
|
264
|
-
setError(
|
|
328
|
+
setError({
|
|
329
|
+
title: t("errors.fallback"),
|
|
330
|
+
description: t("errors.missingVerificationId")
|
|
331
|
+
});
|
|
265
332
|
return;
|
|
266
333
|
}
|
|
267
334
|
setIsLoading(true);
|
|
@@ -274,7 +341,7 @@ var VerifyEmailPage = ({
|
|
|
274
341
|
if ("user" in res && "session" in res) {
|
|
275
342
|
setAuth(res);
|
|
276
343
|
}
|
|
277
|
-
onNavigate("/
|
|
344
|
+
onNavigate(redirectUrl || "/");
|
|
278
345
|
} catch (err) {
|
|
279
346
|
handleError(err, setError, t);
|
|
280
347
|
} finally {
|
|
@@ -290,7 +357,10 @@ var VerifyEmailPage = ({
|
|
|
290
357
|
`/auth/verify-email?verificationId=${res.verificationId}&email=${encodeURIComponent(email)}`
|
|
291
358
|
);
|
|
292
359
|
} else {
|
|
293
|
-
setError(
|
|
360
|
+
setError({
|
|
361
|
+
title: t("errors.fallback"),
|
|
362
|
+
description: t("errors.resendFailed")
|
|
363
|
+
});
|
|
294
364
|
}
|
|
295
365
|
} catch (err) {
|
|
296
366
|
handleError(err, setError, t);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/auth/pages/verify-email-page.tsx","../../../../src/context/auth-provider.tsx","../../../../src/client.ts","../../../../src/constants/auth.error.codes.ts","../../../../src/utils/handle-error.ts","../../../../src/components/auth/auth-page-layout.tsx","../../../../src/components/auth/verification-form.tsx","../../../../src/components/auth/countdown.tsx"],"sourcesContent":["'use client';\n\nimport { useTranslations } from 'next-intl';\nimport type { ComponentProps } from 'react';\nimport { useState } from 'react';\nimport { useAuth } from '../../../context/auth-provider';\nimport type { AuthErrorContent } from '../../../utils/handle-error';\nimport { handleError } from '../../../utils/handle-error';\n\nimport { AuthPageLayout } from '../auth-page-layout';\nimport { VerificationForm } from '../verification-form';\n\ntype VerifyEmailPageProps = {\n locale?: string;\n verificationId: string;\n email: string;\n onNavigate: (path: string) => void;\n linkComponent?: React.ComponentType<ComponentProps<'a'> & { href: string }>;\n links?: {\n signIn?: string;\n };\n logoImage?: string;\n redirectUrl: string;\n};\n\nexport const VerifyEmailPage = ({\n verificationId,\n onNavigate,\n linkComponent: Link,\n links,\n email,\n logoImage,\n redirectUrl,\n}: VerifyEmailPageProps) => {\n const t = useTranslations('Auth.verification');\n const common = useTranslations('Common');\n const footer = useTranslations('Auth.forgotPassword.footer');\n const { client, setAuth } = useAuth();\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<AuthErrorContent | null>(null);\n\n const signInLink = links?.signIn || '/auth/sign-in';\n\n const handleSubmit = async (values: { code: string }) => {\n if (!verificationId) {\n setError({\n title: t('errors.fallback'),\n description: t('errors.missingVerificationId'),\n });\n return;\n }\n\n setIsLoading(true);\n setError(null);\n\n try {\n const res = await client.verifyEmail({\n verificationId,\n code: values.code,\n });\n if ('user' in res && 'session' in res) {\n setAuth(res);\n }\n onNavigate(redirectUrl || '/');\n } catch (err) {\n handleError(err, setError, t);\n } finally {\n setIsLoading(false);\n }\n };\n\n const handleResend = async () => {\n setError(null);\n try {\n const res = await client.requestEmailVerification({ email });\n if (res.verificationId) {\n onNavigate(\n `/auth/verify-email?verificationId=${res.verificationId}&email=${encodeURIComponent(email)}`,\n );\n } else {\n setError({\n title: t('errors.fallback'),\n description: t('errors.resendFailed'),\n });\n }\n } catch (err) {\n handleError(err, setError, t);\n }\n };\n\n if (!verificationId) {\n return (\n <AuthPageLayout\n title={common('invalidLinkTitle')}\n description={common('invalidLinkDescription')}\n footer={\n Link ? (\n <Link href={signInLink} className=\"text-primary hover:underline\">\n {footer('backToSignIn')}\n </Link>\n ) : (\n <a\n href={signInLink}\n onClick={(e) => {\n e.preventDefault();\n onNavigate(signInLink);\n }}\n className=\"text-primary hover:underline\"\n >\n {footer('backToSignIn')}\n </a>\n )\n }\n >\n <div />\n </AuthPageLayout>\n );\n }\n\n return (\n <AuthPageLayout\n title={t('email.title')}\n description={t('email.description')}\n error={error}\n logoImage={logoImage}\n footer={\n Link ? (\n <Link href={signInLink} className=\"text-primary hover:underline\">\n {footer('backToSignIn')}\n </Link>\n ) : (\n <a\n href={signInLink}\n onClick={(e) => {\n e.preventDefault();\n onNavigate(signInLink);\n }}\n className=\"text-primary hover:underline\"\n >\n {footer('backToSignIn')}\n </a>\n )\n }\n >\n <VerificationForm\n verificationId={verificationId}\n onSubmit={handleSubmit}\n onResend={handleResend}\n isLoading={isLoading}\n error={error}\n />\n </AuthPageLayout>\n );\n};\n","'use client';\n\nimport {\n createContext,\n type ReactNode,\n useCallback,\n useContext,\n useEffect,\n useState,\n} from 'react';\nimport type { AuthClient } from '../client';\nimport type { AuthResponse, Session, User } from '../types';\n\ntype AuthContextValue = {\n user: User | null;\n session: Session | null;\n loading: boolean;\n error: Error | null;\n client: AuthClient;\n refresh: () => Promise<void>;\n setAuth: (data: AuthResponse) => void;\n};\n\nconst AuthContext = createContext<AuthContextValue | null>(null);\n\nexport const useAuth = () => {\n const context = useContext(AuthContext);\n if (!context) {\n throw new Error('useAuth must be used within AuthProvider');\n }\n return context;\n};\n\ntype AuthProviderProps = {\n client: AuthClient;\n children: ReactNode;\n};\n\nexport const AuthProvider = ({ client, children }: AuthProviderProps) => {\n const [user, setUser] = useState<User | null>(null);\n const [session, setSession] = useState<Session | null>(null);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n const refresh = useCallback(async () => {\n try {\n setLoading(true);\n setError(null);\n const data = await client.getSession();\n setUser(data.user);\n setSession(data.session);\n } catch (err) {\n setError(\n err instanceof Error ? err : new Error('Failed to fetch session'),\n );\n setUser(null);\n setSession(null);\n } finally {\n setLoading(false);\n }\n }, [client]);\n\n const setAuth = useCallback((data: AuthResponse) => {\n setUser(data.user);\n setSession(data.session);\n setError(null);\n setLoading(false);\n }, []);\n\n useEffect(() => {\n refresh();\n }, [refresh]);\n\n return (\n <AuthContext.Provider\n value={{\n user,\n session,\n loading,\n error,\n client,\n refresh,\n setAuth,\n }}\n >\n {children}\n </AuthContext.Provider>\n );\n};\n","import type {\n AuthErrorCode,\n AuthErrorResponse,\n AuthResponse,\n PendingAccountChangeResponse,\n SessionResponse,\n User,\n VerificationResponse,\n} from './types';\n\n// Backend returns error code in 'error' field (AUTH_ERRORS values)\n// or in 'code' field, message in 'message' or 'error' field\nconst validErrorCodes: readonly AuthErrorCode[] = [\n 'USER_NOT_FOUND',\n 'INVALID_PASSWORD',\n 'USER_EXISTS',\n 'VERIFICATION_EXPIRED',\n 'VERIFICATION_MISMATCH',\n 'VERIFICATION_NOT_FOUND',\n 'TOO_MANY_ATTEMPTS',\n 'REQUIRES_VERIFICATION',\n 'UNAUTHORIZED',\n 'ACCESS_DENIED',\n 'HAS_NO_PASSWORD',\n] as const;\n\nexport class AuthError extends Error {\n code?: AuthErrorCode;\n status?: number;\n details?: Record<string, unknown>;\n\n constructor(\n message: string,\n code?: AuthErrorCode,\n status?: number,\n details?: Record<string, unknown>,\n ) {\n super(message);\n this.name = 'AuthError';\n this.code = code;\n this.status = status;\n this.details = details;\n }\n}\n\nexport type AuthClientConfig = {\n baseURL: string;\n};\n\nexport class AuthClient {\n private baseURL: string;\n\n constructor(config: AuthClientConfig) {\n this.baseURL = config.baseURL.replace(/\\/$/, '');\n }\n\n private async request<T>(\n endpoint: string,\n options: RequestInit = {},\n ): Promise<T> {\n const url = `${this.baseURL}${endpoint}`;\n const response = await fetch(url, {\n ...options,\n credentials: 'include',\n headers: {\n 'Content-Type': 'application/json',\n ...options.headers,\n },\n });\n if (!response.ok) {\n const text = await response.text();\n let errorData: AuthErrorResponse;\n try {\n errorData = JSON.parse(text);\n } catch {\n errorData = { error: 'Unknown error', message: text };\n }\n\n // Extract error code from code, error, or message field\n // Backend returns error codes in 'error' field (e.g., { error: 'INVALID_PASSWORD' })\n const potentialCode =\n errorData.code ||\n (typeof errorData.error === 'string' ? errorData.error : null) ||\n (typeof errorData.message === 'string' ? errorData.message : null);\n const upperCode = potentialCode?.toUpperCase().trim();\n const errorCode =\n upperCode && validErrorCodes.includes(upperCode as AuthErrorCode)\n ? (upperCode as AuthErrorCode)\n : undefined;\n const errorMessage =\n errorData.message || errorData.error || 'Request failed';\n\n throw new AuthError(\n errorMessage,\n errorCode as AuthErrorCode | undefined,\n response.status,\n errorData.details,\n );\n }\n\n const data = await response.json();\n return data;\n }\n\n signUpWithEmail(data: {\n email: string;\n password: string;\n fullName: string;\n handle?: string;\n }): Promise<AuthResponse | VerificationResponse> {\n return this.request<AuthResponse | VerificationResponse>('/sign-up', {\n method: 'POST',\n body: JSON.stringify({\n email: data.email,\n password: data.password,\n fullName: data.fullName,\n handle: data.handle,\n }),\n });\n }\n\n signUpWithPhone(data: {\n phone: string;\n password: string;\n fullName: string;\n handle?: string;\n }): Promise<AuthResponse | VerificationResponse> {\n return this.request<AuthResponse | VerificationResponse>('/sign-up', {\n method: 'POST',\n body: JSON.stringify({\n phone: data.phone,\n password: data.password,\n fullName: data.fullName,\n handle: data.handle,\n }),\n });\n }\n\n checkUser(data: { identifier: string }): Promise<{ exists: boolean }> {\n return this.request<{ exists: boolean }>('/check-user', {\n method: 'POST',\n body: JSON.stringify(data),\n });\n }\n\n signInWithPassword(data: {\n identifier: string;\n password: string;\n }): Promise<AuthResponse | VerificationResponse> {\n return this.request<AuthResponse | VerificationResponse>('/sign-in', {\n method: 'POST',\n body: JSON.stringify(data),\n });\n }\n\n signOut(): Promise<{ message: string }> {\n return this.request<{ message: string }>('/sign-out', {\n method: 'POST',\n });\n }\n\n requestEmailVerification(data?: {\n email?: string;\n }): Promise<{ verificationId: string }> {\n return this.request<{ verificationId: string }>(\n '/email/verification/request',\n {\n method: 'POST',\n body: JSON.stringify(data || {}),\n },\n );\n }\n\n verifyEmail(data: {\n verificationId: string;\n code: string;\n }): Promise<AuthResponse> {\n return this.request<AuthResponse>('/email/verification/confirm', {\n method: 'POST',\n body: JSON.stringify(data),\n });\n }\n\n resendVerification(_verificationId: string): Promise<{\n verificationId: string;\n }> {\n // For email, request new verification\n return this.requestEmailVerification();\n }\n\n requestPhoneOtp(data: {\n phone: string;\n context: 'sign-up' | 'sign-in' | 'change-phone';\n }): Promise<{ verificationId: string }> {\n return this.request<{ verificationId: string }>(\n '/phone/verification/request',\n {\n method: 'POST',\n body: JSON.stringify(data),\n },\n );\n }\n\n verifyPhoneOtp(data: {\n verificationId: string;\n code: string;\n context: 'sign-up' | 'sign-in' | 'change-phone';\n }): Promise<\n AuthResponse | { user: User | null; session: null; verified: boolean }\n > {\n return this.request('/phone/verification/confirm', {\n method: 'POST',\n body: JSON.stringify(data),\n });\n }\n\n forgotPassword(data: { identifier: string }): Promise<{\n message: string;\n }> {\n return this.request<{ message: string }>('/password/forgot', {\n method: 'POST',\n body: JSON.stringify(data),\n });\n }\n\n resetPassword(data: {\n verificationId: string;\n code: string;\n password: string;\n }): Promise<AuthResponse> {\n return this.request<AuthResponse>('/password/reset', {\n method: 'POST',\n body: JSON.stringify(data),\n });\n }\n\n verifyPassword(data: { password: string }): Promise<{ message: string }> {\n return this.request<{ message: string }>('/password/verify', {\n method: 'POST',\n body: JSON.stringify(data),\n });\n }\n\n changePassword(data: {\n currentPassword: string;\n newPassword: string;\n }): Promise<{ message: string }> {\n return this.request<{ message: string }>('/password/change', {\n method: 'POST',\n body: JSON.stringify(data),\n });\n }\n\n getSession(): Promise<SessionResponse> {\n return this.request<SessionResponse>('/session', {\n method: 'GET',\n });\n }\n\n getPendingAccountChange(): Promise<PendingAccountChangeResponse> {\n return this.request<PendingAccountChangeResponse>(\n '/account-change/pending',\n {\n method: 'GET',\n },\n );\n }\n\n updateProfile(data: { fullName?: string }): Promise<{ user: User }> {\n return this.request<{ user: User }>('/profile', {\n method: 'PUT',\n body: JSON.stringify(data),\n });\n }\n\n updateEmail(data: { email: string }): Promise<{ user: User }> {\n return this.request<{ user: User }>('/profile/email', {\n method: 'PUT',\n body: JSON.stringify(data),\n });\n }\n\n updatePhone(data: { phone: string }): Promise<{ user: User }> {\n return this.request<{ user: User }>('/profile/phone', {\n method: 'PUT',\n body: JSON.stringify(data),\n });\n }\n}\n","export const AUTH_ERROR_MAPPING: Record<\n string,\n { title: string; description: string }\n> = {\n USER_NOT_FOUND: {\n title: 'Account Not Found',\n description:\n 'We could not find an account with that identifier. Please check your spelling or sign up.',\n },\n INVALID_PASSWORD: {\n title: 'Invalid Password',\n description: 'The password you entered is incorrect. Please try again.',\n },\n USER_EXISTS: {\n title: 'Account Already Exists',\n description:\n 'An account with this identifier already exists. Please sign in instead.',\n },\n VERIFICATION_EXPIRED: {\n title: 'Verification Expired',\n description:\n 'The verification code or link has expired. Please request a new one.',\n },\n VERIFICATION_MISMATCH: {\n title: 'Invalid Code',\n description:\n 'The verification code you entered is invalid. Please double-check and try again.',\n },\n VERIFICATION_NOT_FOUND: {\n title: 'Verification Not Found',\n description:\n 'We could not find a pending verification request. Please restart the process.',\n },\n TOO_MANY_ATTEMPTS: {\n title: 'Too Many Attempts',\n description:\n 'You have made too many requests recently. Please wait a moment before trying again.',\n },\n REQUIRES_VERIFICATION: {\n title: 'Verification Required',\n description:\n 'You need to verify your account before you can continue. Please check your email or phone.',\n },\n UNAUTHORIZED: {\n title: 'Unauthorized',\n description:\n 'You are not authorized to perform this action. Please sign in again.',\n },\n ACCESS_DENIED: {\n title: 'Access Denied',\n description:\n 'You do not have permission to access this resource. Please contact support if you believe this is an error.',\n },\n HAS_NO_PASSWORD: {\n title: 'No Password Set',\n description:\n 'Your account does not have a password set (e.g. social login). Please sign in with your provider or reset your password.',\n },\n};\n\nexport const validCodes = Object.keys(AUTH_ERROR_MAPPING);\n","import type { _Translator } from 'next-intl';\nimport { AuthError } from '../client';\nimport { AUTH_ERROR_MAPPING, validCodes } from '../constants/auth.error.codes';\n\nexport type AuthErrorContent = {\n title: string;\n description: string;\n};\n\nexport const handleError = (\n err: any,\n setError: (error: AuthErrorContent | null) => void,\n t: _Translator<Record<string, any>, string>,\n) => {\n if (err instanceof AuthError) {\n let errorCode = '';\n\n if (err.code && validCodes.includes(err.code)) {\n errorCode = err.code;\n } else if (err.message) {\n const messageUpper = err.message.toUpperCase().trim();\n if (validCodes.includes(messageUpper)) {\n errorCode = messageUpper;\n }\n }\n\n if (errorCode && AUTH_ERROR_MAPPING[errorCode]) {\n const mapping = AUTH_ERROR_MAPPING[errorCode];\n // Try to translate the description if a key exists, otherwise use English fallback\n // Since mapping.description is English text, we might want to check if there is a translation key\n // But for now, let's use the provided English mapping or try to find a translation if the key matches 'errors.code'\n\n // We can try to lookup translation, if it returns the key (or fallback), we might prefer the mapping text (which is nice English).\n // However, usually we prefer translation.\n // Let's rely on the mapping text primarily as per the request to \"Generate a description and title...\".\n // But if we want i18n support, we should probably add keys.\n // Given the prompt \"Generate a description... for each error code... and display\",\n // I will prioritize the static mapping I just created, but allows future i18n improvement.\n\n setError({\n title: mapping.title,\n description: mapping.description,\n });\n return;\n }\n\n // Fallback for AuthError without known code\n setError({\n title: t('errors.fallback'), // or 'Error'\n description: err.message || t('errors.fallback'),\n });\n } else {\n // Generic error\n const message = err instanceof Error ? err.message : t('errors.fallback');\n setError({\n title: 'Error',\n description: message,\n });\n }\n};\n","'use client';\n\nimport {\n Alert,\n AlertDescription,\n AlertTitle,\n} from '@mesob/ui/components/alert';\nimport { IconAlertCircle } from '@tabler/icons-react';\nimport type { ReactNode } from 'react';\nimport type { AuthErrorContent } from '../../utils/handle-error';\n\ntype AuthPageLayoutProps = {\n title: string;\n description?: string;\n children: ReactNode;\n error?: AuthErrorContent | string | null;\n footer?: ReactNode;\n logoImage?: string;\n};\n\nexport const AuthPageLayout = ({\n title,\n description,\n children,\n error,\n footer,\n logoImage,\n}: AuthPageLayoutProps) => {\n const errorContent: AuthErrorContent | null = error\n ? // biome-ignore lint/style/noNestedTernary: <explanation>\n typeof error === 'string'\n ? { title: 'Error', description: error }\n : error\n : null;\n\n return (\n <div className=\"space-y-4\">\n <div className=\"flex size-8 mb-6 w-full items-center justify-center rounded-md\">\n {/** biome-ignore lint/performance/noImgElement: logo image */}\n <img src={logoImage || ''} alt=\"Jiret\" width={42} height={42} />\n </div>\n <div className=\"text-center\">\n <h1 className=\"text-2xl font-bold tracking-tight\">{title}</h1>\n {description && (\n <p className=\"mt-2 text-sm text-muted-foreground\">{description}</p>\n )}\n </div>\n\n {children}\n\n {errorContent && (\n <Alert variant=\"destructive\">\n <IconAlertCircle className=\"h-4 w-4\" />\n <AlertTitle>{errorContent.title}</AlertTitle>\n <AlertDescription>{errorContent.description}</AlertDescription>\n </Alert>\n )}\n <div className=\"mt-2 w-full\">\n {footer && (\n <div className=\"w-full text-center text-sm text-muted-foreground\">\n {footer}\n </div>\n )}\n </div>\n </div>\n );\n};\n","'use client';\n\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport { Button } from '@mesob/ui/components/button';\nimport {\n Form,\n FormControl,\n FormField,\n FormItem,\n FormMessage,\n} from '@mesob/ui/components/form';\nimport {\n InputOTP,\n InputOTPGroup,\n InputOTPSlot,\n} from '@mesob/ui/components/input-otp';\nimport { Spinner } from '@mesob/ui/components/spinner';\nimport { useTranslations } from 'next-intl';\nimport { useMemo } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { z } from 'zod';\nimport type { AuthErrorContent } from '../../utils/handle-error';\nimport { Countdown } from './countdown';\n\ntype VerificationFormValues = {\n code: string;\n};\n\ntype VerificationFormProps = {\n verificationId: string;\n onSubmit: (values: VerificationFormValues) => Promise<void> | void;\n onResend: () => Promise<void> | void;\n isLoading?: boolean;\n error?: AuthErrorContent | string | null;\n};\n\nexport const VerificationForm = ({\n onSubmit,\n onResend,\n isLoading = false,\n}: VerificationFormProps) => {\n const t = useTranslations('Auth.verification');\n const verificationSchema = useMemo(\n () =>\n z.object({\n code: z.string().length(6, t('form.codeLength')),\n }),\n [t],\n );\n const form = useForm<VerificationFormValues>({\n resolver: zodResolver(verificationSchema),\n defaultValues: {\n code: '',\n },\n });\n\n return (\n <Form {...form}>\n <form className=\"space-y-4\">\n <FormField\n control={form.control}\n name=\"code\"\n render={({ field }) => (\n <FormItem>\n <FormControl>\n <div className=\"flex justify-center\">\n <InputOTP\n maxLength={6}\n id=\"otp\"\n required\n value={field.value ?? ''}\n onChange={field.onChange}\n onBlur={field.onBlur}\n containerClassName=\"gap-4 justify-center mb-2 flex items-center\"\n >\n <InputOTPGroup className=\"gap-3 *:data-[slot=input-otp-slot]:h-12 *:data-[slot=input-otp-slot]:w-12 *:data-[slot=input-otp-slot]:rounded-md *:data-[slot=input-otp-slot]:border *:data-[slot=input-otp-slot]:text-xl\">\n <InputOTPSlot className=\"h-12\" index={0} />\n <InputOTPSlot className=\"h-12\" index={1} />\n <InputOTPSlot className=\"h-12\" index={2} />\n <InputOTPSlot className=\"h-12\" index={3} />\n <InputOTPSlot className=\"h-12\" index={4} />\n <InputOTPSlot className=\"h-12\" index={5} />\n </InputOTPGroup>\n </InputOTP>\n </div>\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n\n <div className=\"flex justify-between items-center\">\n <Countdown onResend={onResend} resending={isLoading} />\n <Button\n type=\"button\"\n onClick={() => {\n form.handleSubmit(async (values) => {\n await onSubmit(values);\n })();\n }}\n disabled={isLoading || form.watch('code').length !== 6}\n >\n {isLoading && <Spinner />}\n {t('form.confirm')}\n </Button>\n </div>\n </form>\n </Form>\n );\n};\n","'use client';\n\nimport { Button } from '@mesob/ui/components/button';\nimport { Spinner } from '@mesob/ui/components/spinner';\nimport { useTranslations } from 'next-intl';\nimport { useEffect, useState } from 'react';\n\ntype CountdownProps = {\n initialSeconds?: number;\n onResend: () => Promise<void> | void;\n resending?: boolean;\n};\n\nexport const Countdown = ({\n initialSeconds = 60,\n onResend,\n resending = false,\n}: CountdownProps) => {\n const t = useTranslations('Common');\n const [seconds, setSeconds] = useState(initialSeconds);\n const [isResending, setIsResending] = useState(false);\n\n useEffect(() => {\n if (seconds <= 0) {\n return;\n }\n\n const timer = setInterval(() => {\n setSeconds((prev) => {\n if (prev <= 1) {\n clearInterval(timer);\n return 0;\n }\n return prev - 1;\n });\n }, 1000);\n\n return () => clearInterval(timer);\n }, [seconds]);\n\n const handleResend = async () => {\n setIsResending(true);\n try {\n await onResend();\n setSeconds(initialSeconds);\n } catch (_error) {\n // Error handling is done by parent\n } finally {\n setIsResending(false);\n }\n };\n\n if (seconds > 0) {\n return (\n <Button variant=\"ghost\" disabled>\n {t('resendIn', { seconds })}\n </Button>\n );\n }\n\n return (\n <Button\n variant=\"ghost\"\n onClick={handleResend}\n disabled={isResending || resending}\n >\n {isResending || (resending && <Spinner />)}\n {t('resend')}\n </Button>\n );\n};\n"],"mappings":";;;AAEA,SAAS,mBAAAA,wBAAuB;AAEhC,SAAS,YAAAC,iBAAgB;;;ACFzB;AAAA,EACE;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAiEH;AAnDJ,IAAM,cAAc,cAAuC,IAAI;AAExD,IAAM,UAAU,MAAM;AAC3B,QAAM,UAAU,WAAW,WAAW;AACtC,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,MAAM,0CAA0C;AAAA,EAC5D;AACA,SAAO;AACT;;;ACLO,IAAM,YAAN,cAAwB,MAAM;AAAA,EACnC;AAAA,EACA;AAAA,EACA;AAAA,EAEA,YACE,SACA,MACA,QACA,SACA;AACA,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,OAAO;AACZ,SAAK,SAAS;AACd,SAAK,UAAU;AAAA,EACjB;AACF;;;AC3CO,IAAM,qBAGT;AAAA,EACF,gBAAgB;AAAA,IACd,OAAO;AAAA,IACP,aACE;AAAA,EACJ;AAAA,EACA,kBAAkB;AAAA,IAChB,OAAO;AAAA,IACP,aAAa;AAAA,EACf;AAAA,EACA,aAAa;AAAA,IACX,OAAO;AAAA,IACP,aACE;AAAA,EACJ;AAAA,EACA,sBAAsB;AAAA,IACpB,OAAO;AAAA,IACP,aACE;AAAA,EACJ;AAAA,EACA,uBAAuB;AAAA,IACrB,OAAO;AAAA,IACP,aACE;AAAA,EACJ;AAAA,EACA,wBAAwB;AAAA,IACtB,OAAO;AAAA,IACP,aACE;AAAA,EACJ;AAAA,EACA,mBAAmB;AAAA,IACjB,OAAO;AAAA,IACP,aACE;AAAA,EACJ;AAAA,EACA,uBAAuB;AAAA,IACrB,OAAO;AAAA,IACP,aACE;AAAA,EACJ;AAAA,EACA,cAAc;AAAA,IACZ,OAAO;AAAA,IACP,aACE;AAAA,EACJ;AAAA,EACA,eAAe;AAAA,IACb,OAAO;AAAA,IACP,aACE;AAAA,EACJ;AAAA,EACA,iBAAiB;AAAA,IACf,OAAO;AAAA,IACP,aACE;AAAA,EACJ;AACF;AAEO,IAAM,aAAa,OAAO,KAAK,kBAAkB;;;ACnDjD,IAAM,cAAc,CACzB,KACA,UACA,MACG;AACH,MAAI,eAAe,WAAW;AAC5B,QAAI,YAAY;AAEhB,QAAI,IAAI,QAAQ,WAAW,SAAS,IAAI,IAAI,GAAG;AAC7C,kBAAY,IAAI;AAAA,IAClB,WAAW,IAAI,SAAS;AACtB,YAAM,eAAe,IAAI,QAAQ,YAAY,EAAE,KAAK;AACpD,UAAI,WAAW,SAAS,YAAY,GAAG;AACrC,oBAAY;AAAA,MACd;AAAA,IACF;AAEA,QAAI,aAAa,mBAAmB,SAAS,GAAG;AAC9C,YAAM,UAAU,mBAAmB,SAAS;AAY5C,eAAS;AAAA,QACP,OAAO,QAAQ;AAAA,QACf,aAAa,QAAQ;AAAA,MACvB,CAAC;AACD;AAAA,IACF;AAGA,aAAS;AAAA,MACP,OAAO,EAAE,iBAAiB;AAAA;AAAA,MAC1B,aAAa,IAAI,WAAW,EAAE,iBAAiB;AAAA,IACjD,CAAC;AAAA,EACH,OAAO;AAEL,UAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,EAAE,iBAAiB;AACxE,aAAS;AAAA,MACP,OAAO;AAAA,MACP,aAAa;AAAA,IACf,CAAC;AAAA,EACH;AACF;;;ACzDA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,uBAAuB;AAgCxB,gBAAAC,MAEF,YAFE;AAnBD,IAAM,iBAAiB,CAAC;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAA2B;AACzB,QAAM,eAAwC;AAAA;AAAA,IAE1C,OAAO,UAAU,WACf,EAAE,OAAO,SAAS,aAAa,MAAM,IACrC;AAAA,MACF;AAEJ,SACE,qBAAC,SAAI,WAAU,aACb;AAAA,oBAAAA,KAAC,SAAI,WAAU,kEAEb,0BAAAA,KAAC,SAAI,KAAK,aAAa,IAAI,KAAI,SAAQ,OAAO,IAAI,QAAQ,IAAI,GAChE;AAAA,IACA,qBAAC,SAAI,WAAU,eACb;AAAA,sBAAAA,KAAC,QAAG,WAAU,qCAAqC,iBAAM;AAAA,MACxD,eACC,gBAAAA,KAAC,OAAE,WAAU,sCAAsC,uBAAY;AAAA,OAEnE;AAAA,IAEC;AAAA,IAEA,gBACC,qBAAC,SAAM,SAAQ,eACb;AAAA,sBAAAA,KAAC,mBAAgB,WAAU,WAAU;AAAA,MACrC,gBAAAA,KAAC,cAAY,uBAAa,OAAM;AAAA,MAChC,gBAAAA,KAAC,oBAAkB,uBAAa,aAAY;AAAA,OAC9C;AAAA,IAEF,gBAAAA,KAAC,SAAI,WAAU,eACZ,oBACC,gBAAAA,KAAC,SAAI,WAAU,oDACZ,kBACH,GAEJ;AAAA,KACF;AAEJ;;;AChEA,SAAS,mBAAmB;AAC5B,SAAS,UAAAC,eAAc;AACvB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,WAAAC,gBAAe;AACxB,SAAS,mBAAAC,wBAAuB;AAChC,SAAS,eAAe;AACxB,SAAS,eAAe;AACxB,SAAS,SAAS;;;AClBlB,SAAS,cAAc;AACvB,SAAS,eAAe;AACxB,SAAS,uBAAuB;AAChC,SAAS,aAAAC,YAAW,YAAAC,iBAAgB;AAiD9B,gBAAAC,MAOF,QAAAC,aAPE;AAzCC,IAAM,YAAY,CAAC;AAAA,EACxB,iBAAiB;AAAA,EACjB;AAAA,EACA,YAAY;AACd,MAAsB;AACpB,QAAM,IAAI,gBAAgB,QAAQ;AAClC,QAAM,CAAC,SAAS,UAAU,IAAIF,UAAS,cAAc;AACrD,QAAM,CAAC,aAAa,cAAc,IAAIA,UAAS,KAAK;AAEpD,EAAAD,WAAU,MAAM;AACd,QAAI,WAAW,GAAG;AAChB;AAAA,IACF;AAEA,UAAM,QAAQ,YAAY,MAAM;AAC9B,iBAAW,CAAC,SAAS;AACnB,YAAI,QAAQ,GAAG;AACb,wBAAc,KAAK;AACnB,iBAAO;AAAA,QACT;AACA,eAAO,OAAO;AAAA,MAChB,CAAC;AAAA,IACH,GAAG,GAAI;AAEP,WAAO,MAAM,cAAc,KAAK;AAAA,EAClC,GAAG,CAAC,OAAO,CAAC;AAEZ,QAAM,eAAe,YAAY;AAC/B,mBAAe,IAAI;AACnB,QAAI;AACF,YAAM,SAAS;AACf,iBAAW,cAAc;AAAA,IAC3B,SAAS,QAAQ;AAAA,IAEjB,UAAE;AACA,qBAAe,KAAK;AAAA,IACtB;AAAA,EACF;AAEA,MAAI,UAAU,GAAG;AACf,WACE,gBAAAE,KAAC,UAAO,SAAQ,SAAQ,UAAQ,MAC7B,YAAE,YAAY,EAAE,QAAQ,CAAC,GAC5B;AAAA,EAEJ;AAEA,SACE,gBAAAC;AAAA,IAAC;AAAA;AAAA,MACC,SAAQ;AAAA,MACR,SAAS;AAAA,MACT,UAAU,eAAe;AAAA,MAExB;AAAA,uBAAgB,aAAa,gBAAAD,KAAC,WAAQ;AAAA,QACtC,EAAE,QAAQ;AAAA;AAAA;AAAA,EACb;AAEJ;;;ADKoB,SACE,OAAAE,MADF,QAAAC,aAAA;AAvCb,IAAM,mBAAmB,CAAC;AAAA,EAC/B;AAAA,EACA;AAAA,EACA,YAAY;AACd,MAA6B;AAC3B,QAAM,IAAIC,iBAAgB,mBAAmB;AAC7C,QAAM,qBAAqB;AAAA,IACzB,MACE,EAAE,OAAO;AAAA,MACP,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,EAAE,iBAAiB,CAAC;AAAA,IACjD,CAAC;AAAA,IACH,CAAC,CAAC;AAAA,EACJ;AACA,QAAM,OAAO,QAAgC;AAAA,IAC3C,UAAU,YAAY,kBAAkB;AAAA,IACxC,eAAe;AAAA,MACb,MAAM;AAAA,IACR;AAAA,EACF,CAAC;AAED,SACE,gBAAAF,KAAC,QAAM,GAAG,MACR,0BAAAC,MAAC,UAAK,WAAU,aACd;AAAA,oBAAAD;AAAA,MAAC;AAAA;AAAA,QACC,SAAS,KAAK;AAAA,QACd,MAAK;AAAA,QACL,QAAQ,CAAC,EAAE,MAAM,MACf,gBAAAC,MAAC,YACC;AAAA,0BAAAD,KAAC,eACC,0BAAAA,KAAC,SAAI,WAAU,uBACb,0BAAAA;AAAA,YAAC;AAAA;AAAA,cACC,WAAW;AAAA,cACX,IAAG;AAAA,cACH,UAAQ;AAAA,cACR,OAAO,MAAM,SAAS;AAAA,cACtB,UAAU,MAAM;AAAA,cAChB,QAAQ,MAAM;AAAA,cACd,oBAAmB;AAAA,cAEnB,0BAAAC,MAAC,iBAAc,WAAU,8LACvB;AAAA,gCAAAD,KAAC,gBAAa,WAAU,QAAO,OAAO,GAAG;AAAA,gBACzC,gBAAAA,KAAC,gBAAa,WAAU,QAAO,OAAO,GAAG;AAAA,gBACzC,gBAAAA,KAAC,gBAAa,WAAU,QAAO,OAAO,GAAG;AAAA,gBACzC,gBAAAA,KAAC,gBAAa,WAAU,QAAO,OAAO,GAAG;AAAA,gBACzC,gBAAAA,KAAC,gBAAa,WAAU,QAAO,OAAO,GAAG;AAAA,gBACzC,gBAAAA,KAAC,gBAAa,WAAU,QAAO,OAAO,GAAG;AAAA,iBAC3C;AAAA;AAAA,UACF,GACF,GACF;AAAA,UACA,gBAAAA,KAAC,eAAY;AAAA,WACf;AAAA;AAAA,IAEJ;AAAA,IAEA,gBAAAC,MAAC,SAAI,WAAU,qCACb;AAAA,sBAAAD,KAAC,aAAU,UAAoB,WAAW,WAAW;AAAA,MACrD,gBAAAC;AAAA,QAACE;AAAA,QAAA;AAAA,UACC,MAAK;AAAA,UACL,SAAS,MAAM;AACb,iBAAK,aAAa,OAAO,WAAW;AAClC,oBAAM,SAAS,MAAM;AAAA,YACvB,CAAC,EAAE;AAAA,UACL;AAAA,UACA,UAAU,aAAa,KAAK,MAAM,MAAM,EAAE,WAAW;AAAA,UAEpD;AAAA,yBAAa,gBAAAH,KAACI,UAAA,EAAQ;AAAA,YACtB,EAAE,cAAc;AAAA;AAAA;AAAA,MACnB;AAAA,OACF;AAAA,KACF,GACF;AAEJ;;;ANZY,gBAAAC,YAAA;AAxEL,IAAM,kBAAkB,CAAC;AAAA,EAC9B;AAAA,EACA;AAAA,EACA,eAAe;AAAA,EACf;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAA4B;AAC1B,QAAM,IAAIC,iBAAgB,mBAAmB;AAC7C,QAAM,SAASA,iBAAgB,QAAQ;AACvC,QAAM,SAASA,iBAAgB,4BAA4B;AAC3D,QAAM,EAAE,QAAQ,QAAQ,IAAI,QAAQ;AACpC,QAAM,CAAC,WAAW,YAAY,IAAIC,UAAS,KAAK;AAChD,QAAM,CAAC,OAAO,QAAQ,IAAIA,UAAkC,IAAI;AAEhE,QAAM,aAAa,OAAO,UAAU;AAEpC,QAAM,eAAe,OAAO,WAA6B;AACvD,QAAI,CAAC,gBAAgB;AACnB,eAAS;AAAA,QACP,OAAO,EAAE,iBAAiB;AAAA,QAC1B,aAAa,EAAE,8BAA8B;AAAA,MAC/C,CAAC;AACD;AAAA,IACF;AAEA,iBAAa,IAAI;AACjB,aAAS,IAAI;AAEb,QAAI;AACF,YAAM,MAAM,MAAM,OAAO,YAAY;AAAA,QACnC;AAAA,QACA,MAAM,OAAO;AAAA,MACf,CAAC;AACD,UAAI,UAAU,OAAO,aAAa,KAAK;AACrC,gBAAQ,GAAG;AAAA,MACb;AACA,iBAAW,eAAe,GAAG;AAAA,IAC/B,SAAS,KAAK;AACZ,kBAAY,KAAK,UAAU,CAAC;AAAA,IAC9B,UAAE;AACA,mBAAa,KAAK;AAAA,IACpB;AAAA,EACF;AAEA,QAAM,eAAe,YAAY;AAC/B,aAAS,IAAI;AACb,QAAI;AACF,YAAM,MAAM,MAAM,OAAO,yBAAyB,EAAE,MAAM,CAAC;AAC3D,UAAI,IAAI,gBAAgB;AACtB;AAAA,UACE,qCAAqC,IAAI,cAAc,UAAU,mBAAmB,KAAK,CAAC;AAAA,QAC5F;AAAA,MACF,OAAO;AACL,iBAAS;AAAA,UACP,OAAO,EAAE,iBAAiB;AAAA,UAC1B,aAAa,EAAE,qBAAqB;AAAA,QACtC,CAAC;AAAA,MACH;AAAA,IACF,SAAS,KAAK;AACZ,kBAAY,KAAK,UAAU,CAAC;AAAA,IAC9B;AAAA,EACF;AAEA,MAAI,CAAC,gBAAgB;AACnB,WACE,gBAAAF;AAAA,MAAC;AAAA;AAAA,QACC,OAAO,OAAO,kBAAkB;AAAA,QAChC,aAAa,OAAO,wBAAwB;AAAA,QAC5C,QACE,OACE,gBAAAA,KAAC,QAAK,MAAM,YAAY,WAAU,gCAC/B,iBAAO,cAAc,GACxB,IAEA,gBAAAA;AAAA,UAAC;AAAA;AAAA,YACC,MAAM;AAAA,YACN,SAAS,CAAC,MAAM;AACd,gBAAE,eAAe;AACjB,yBAAW,UAAU;AAAA,YACvB;AAAA,YACA,WAAU;AAAA,YAET,iBAAO,cAAc;AAAA;AAAA,QACxB;AAAA,QAIJ,0BAAAA,KAAC,SAAI;AAAA;AAAA,IACP;AAAA,EAEJ;AAEA,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC,OAAO,EAAE,aAAa;AAAA,MACtB,aAAa,EAAE,mBAAmB;AAAA,MAClC;AAAA,MACA;AAAA,MACA,QACE,OACE,gBAAAA,KAAC,QAAK,MAAM,YAAY,WAAU,gCAC/B,iBAAO,cAAc,GACxB,IAEA,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACC,MAAM;AAAA,UACN,SAAS,CAAC,MAAM;AACd,cAAE,eAAe;AACjB,uBAAW,UAAU;AAAA,UACvB;AAAA,UACA,WAAU;AAAA,UAET,iBAAO,cAAc;AAAA;AAAA,MACxB;AAAA,MAIJ,0BAAAA;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA,UAAU;AAAA,UACV,UAAU;AAAA,UACV;AAAA,UACA;AAAA;AAAA,MACF;AAAA;AAAA,EACF;AAEJ;","names":["useTranslations","useState","jsx","Button","Spinner","useTranslations","useEffect","useState","jsx","jsxs","jsx","jsxs","useTranslations","Button","Spinner","jsx","useTranslations","useState"]}
|
|
@@ -14,7 +14,8 @@ type VerifyPhonePageProps = {
|
|
|
14
14
|
signIn?: string;
|
|
15
15
|
};
|
|
16
16
|
logoImage?: string;
|
|
17
|
+
redirectUrl?: string;
|
|
17
18
|
};
|
|
18
|
-
declare const VerifyPhonePage: ({ verificationId, context, phone, onNavigate, linkComponent: Link, links, logoImage, }: VerifyPhonePageProps) => react_jsx_runtime.JSX.Element;
|
|
19
|
+
declare const VerifyPhonePage: ({ verificationId, context, phone, onNavigate, linkComponent: Link, links, logoImage, redirectUrl, }: VerifyPhonePageProps) => react_jsx_runtime.JSX.Element;
|
|
19
20
|
|
|
20
21
|
export { VerifyPhonePage };
|