@mesob/auth-react 0.0.7 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/dist/components/auth/auth-page-layout.d.ts +1 -3
  2. package/dist/components/auth/auth-page-layout.js +1 -17
  3. package/dist/components/auth/auth-page-layout.js.map +1 -1
  4. package/dist/components/auth/countdown.js +70 -9
  5. package/dist/components/auth/countdown.js.map +1 -1
  6. package/dist/components/auth/forgot-password.js +101 -35
  7. package/dist/components/auth/forgot-password.js.map +1 -1
  8. package/dist/components/auth/pages/forgot-password-page.d.ts +2 -13
  9. package/dist/components/auth/pages/forgot-password-page.js +198 -126
  10. package/dist/components/auth/pages/forgot-password-page.js.map +1 -1
  11. package/dist/components/auth/pages/reset-password-page.d.ts +1 -12
  12. package/dist/components/auth/pages/reset-password-page.js +288 -200
  13. package/dist/components/auth/pages/reset-password-page.js.map +1 -1
  14. package/dist/components/auth/pages/sign-in-page.d.ts +1 -12
  15. package/dist/components/auth/pages/sign-in-page.js +352 -230
  16. package/dist/components/auth/pages/sign-in-page.js.map +1 -1
  17. package/dist/components/auth/pages/sign-up-page.d.ts +1 -11
  18. package/dist/components/auth/pages/sign-up-page.js +310 -216
  19. package/dist/components/auth/pages/sign-up-page.js.map +1 -1
  20. package/dist/components/auth/pages/verify-email-page.d.ts +2 -12
  21. package/dist/components/auth/pages/verify-email-page.js +203 -135
  22. package/dist/components/auth/pages/verify-email-page.js.map +1 -1
  23. package/dist/components/auth/pages/verify-phone-page.d.ts +1 -11
  24. package/dist/components/auth/pages/verify-phone-page.js +206 -137
  25. package/dist/components/auth/pages/verify-phone-page.js.map +1 -1
  26. package/dist/components/auth/reset-password-form.d.ts +1 -1
  27. package/dist/components/auth/reset-password-form.js +188 -106
  28. package/dist/components/auth/reset-password-form.js.map +1 -1
  29. package/dist/components/auth/sign-in.d.ts +3 -3
  30. package/dist/components/auth/sign-in.js +228 -109
  31. package/dist/components/auth/sign-in.js.map +1 -1
  32. package/dist/components/auth/sign-up.js +210 -122
  33. package/dist/components/auth/sign-up.js.map +1 -1
  34. package/dist/components/auth/verification-form.d.ts +1 -1
  35. package/dist/components/auth/verification-form.js +101 -53
  36. package/dist/components/auth/verification-form.js.map +1 -1
  37. package/dist/components/error-boundary.d.ts +27 -0
  38. package/dist/components/error-boundary.js +49 -0
  39. package/dist/components/error-boundary.js.map +1 -0
  40. package/dist/components/iam/permissions/permissions-page.d.ts +5 -0
  41. package/dist/components/iam/permissions/permissions-page.js +201 -0
  42. package/dist/components/iam/permissions/permissions-page.js.map +1 -0
  43. package/dist/components/iam/roles/roles-page.d.ts +5 -0
  44. package/dist/components/iam/roles/roles-page.js +199 -0
  45. package/dist/components/iam/roles/roles-page.js.map +1 -0
  46. package/dist/components/iam/sessions/sessions-page.d.ts +5 -0
  47. package/dist/components/iam/sessions/sessions-page.js +202 -0
  48. package/dist/components/iam/sessions/sessions-page.js.map +1 -0
  49. package/dist/components/iam/tenants/tenants-page.d.ts +5 -0
  50. package/dist/components/iam/tenants/tenants-page.js +202 -0
  51. package/dist/components/iam/tenants/tenants-page.js.map +1 -0
  52. package/dist/components/iam/users/users-page.d.ts +5 -0
  53. package/dist/components/iam/users/users-page.js +211 -0
  54. package/dist/components/iam/users/users-page.js.map +1 -0
  55. package/dist/components/profile/profile-page.d.ts +8 -0
  56. package/dist/components/profile/profile-page.js +163 -0
  57. package/dist/components/profile/profile-page.js.map +1 -0
  58. package/dist/components/shared/data-table/data-table.d.ts +22 -0
  59. package/dist/components/shared/data-table/data-table.js +85 -0
  60. package/dist/components/shared/data-table/data-table.js.map +1 -0
  61. package/dist/components/skeletons/auth-form-skeleton.d.ts +5 -0
  62. package/dist/components/skeletons/auth-form-skeleton.js +32 -0
  63. package/dist/components/skeletons/auth-form-skeleton.js.map +1 -0
  64. package/dist/components/skeletons/profile-skeleton.d.ts +5 -0
  65. package/dist/components/skeletons/profile-skeleton.js +33 -0
  66. package/dist/components/skeletons/profile-skeleton.js.map +1 -0
  67. package/dist/components/skeletons/table-skeleton.d.ts +9 -0
  68. package/dist/components/skeletons/table-skeleton.js +39 -0
  69. package/dist/components/skeletons/table-skeleton.js.map +1 -0
  70. package/dist/handle-error-BqDMxnQZ.d.ts +8 -0
  71. package/dist/index.d.ts +75 -208
  72. package/dist/index.js +2091 -1057
  73. package/dist/index.js.map +1 -1
  74. package/package.json +9 -3
  75. package/dist/handle-error-H0iqQxJ5.d.ts +0 -6
@@ -1,40 +1,75 @@
1
1
  "use client";
2
2
 
3
3
  // src/components/auth/pages/verify-email-page.tsx
4
- import { useTranslations as useTranslations3 } from "next-intl";
5
- import { useState as useState3 } from "react";
6
-
7
- // src/context/auth-provider.tsx
8
4
  import {
9
- createContext,
10
- useCallback,
11
- useContext,
12
- useEffect,
13
- useState
14
- } from "react";
5
+ Alert,
6
+ AlertDescription,
7
+ AlertTitle
8
+ } from "@mesob/ui/components/alert";
9
+ import { toast } from "@mesob/ui/components/sonner";
10
+ import { IconAlertCircle } from "@tabler/icons-react";
11
+ import { useEffect as useEffect3, useState as useState3 } from "react";
12
+
13
+ // src/lib/translations.ts
14
+ function createTranslator(messages, namespace) {
15
+ return (key, params) => {
16
+ const fullKey = namespace ? `${namespace}.${key}` : key;
17
+ const keys = fullKey.split(".");
18
+ let value = messages;
19
+ for (const k of keys) {
20
+ if (value && typeof value === "object" && value !== null) {
21
+ value = value[k];
22
+ } else {
23
+ return fullKey;
24
+ }
25
+ }
26
+ if (typeof value !== "string") {
27
+ return fullKey;
28
+ }
29
+ if (params) {
30
+ return value.replace(
31
+ /\{(\w+)\}/g,
32
+ (_, param) => String(params[param] ?? `{${param}}`)
33
+ );
34
+ }
35
+ return value;
36
+ };
37
+ }
38
+
39
+ // src/provider.tsx
40
+ import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
41
+ import { deepmerge } from "deepmerge-ts";
42
+ import createFetchClient from "openapi-fetch";
43
+ import createClient from "openapi-react-query";
44
+ import { createContext, useContext, useEffect, useState } from "react";
15
45
  import { jsx } from "react/jsx-runtime";
16
- var AuthContext = createContext(null);
17
- var useAuth = () => {
18
- const context = useContext(AuthContext);
46
+ var SessionContext = createContext(null);
47
+ var ApiContext = createContext(null);
48
+ var ConfigContext = createContext(null);
49
+ var queryClient = new QueryClient({
50
+ defaultOptions: {
51
+ queries: {
52
+ staleTime: 1e3 * 60 * 5,
53
+ gcTime: 1e3 * 60 * 10,
54
+ retry: 1,
55
+ refetchOnWindowFocus: false
56
+ }
57
+ }
58
+ });
59
+ function useApi() {
60
+ const context = useContext(ApiContext);
19
61
  if (!context) {
20
- throw new Error("useAuth must be used within AuthProvider");
62
+ throw new Error("useApi must be used within MesobAuthProvider");
21
63
  }
22
64
  return context;
23
- };
24
-
25
- // src/client.ts
26
- var AuthError = class extends Error {
27
- code;
28
- status;
29
- details;
30
- constructor(message, code, status, details) {
31
- super(message);
32
- this.name = "AuthError";
33
- this.code = code;
34
- this.status = status;
35
- this.details = details;
65
+ }
66
+ function useConfig() {
67
+ const context = useContext(ConfigContext);
68
+ if (!context) {
69
+ throw new Error("useConfig must be used within MesobAuthProvider");
36
70
  }
37
- };
71
+ return context;
72
+ }
38
73
 
39
74
  // src/constants/auth.error.codes.ts
40
75
  var AUTH_ERROR_MAPPING = {
@@ -86,71 +121,67 @@ var AUTH_ERROR_MAPPING = {
86
121
  var validCodes = Object.keys(AUTH_ERROR_MAPPING);
87
122
 
88
123
  // src/utils/handle-error.ts
89
- var handleError = (err, setError, t) => {
90
- if (err instanceof AuthError) {
91
- let errorCode = "";
92
- if (err.code && validCodes.includes(err.code)) {
93
- errorCode = err.code;
94
- } else if (err.message) {
95
- const messageUpper = err.message.toUpperCase().trim();
96
- if (validCodes.includes(messageUpper)) {
97
- errorCode = messageUpper;
98
- }
99
- }
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;
124
+ function isAuthError(err) {
125
+ return typeof err === "object" && err !== null && "message" in err && typeof err.message === "string";
126
+ }
127
+ function extractErrorCode(err) {
128
+ if (err.code && validCodes.includes(err.code)) {
129
+ return err.code;
130
+ }
131
+ if (err.message) {
132
+ const messageUpper = err.message.toUpperCase().trim();
133
+ if (validCodes.includes(messageUpper)) {
134
+ return messageUpper;
107
135
  }
136
+ }
137
+ return "";
138
+ }
139
+ function handleAuthError(err, setError, t) {
140
+ const errorCode = extractErrorCode(err);
141
+ if (errorCode && AUTH_ERROR_MAPPING[errorCode]) {
142
+ const mapping = AUTH_ERROR_MAPPING[errorCode];
108
143
  setError({
109
- title: t("errors.fallback"),
110
- // or 'Error'
111
- description: err.message || t("errors.fallback")
144
+ title: mapping.title,
145
+ description: mapping.description
112
146
  });
147
+ return;
148
+ }
149
+ setError({
150
+ title: t("errors.fallback"),
151
+ description: err.message || t("errors.fallback")
152
+ });
153
+ }
154
+ function handleGenericError(err, setError, t) {
155
+ const message = err instanceof Error ? err.message : t("errors.fallback");
156
+ setError({
157
+ title: "Error",
158
+ description: message
159
+ });
160
+ }
161
+ var handleError = (err, setError, t) => {
162
+ if (isAuthError(err)) {
163
+ handleAuthError(err, setError, t);
113
164
  } else {
114
- const message = err instanceof Error ? err.message : t("errors.fallback");
115
- setError({
116
- title: "Error",
117
- description: message
118
- });
165
+ handleGenericError(err, setError, t);
119
166
  }
120
167
  };
121
168
 
122
169
  // 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";
129
170
  import { jsx as jsx2, jsxs } from "react/jsx-runtime";
130
171
  var AuthPageLayout = ({
131
172
  title,
132
173
  description,
133
174
  children,
134
- error,
135
175
  footer,
136
176
  logoImage
137
177
  }) => {
138
- const errorContent = error ? (
139
- // biome-ignore lint/style/noNestedTernary: <explanation>
140
- typeof error === "string" ? { title: "Error", description: error } : error
141
- ) : null;
142
178
  return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
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 }) }),
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: "Mesob", width: 42, height: 42 }) }),
144
180
  /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
145
181
  /* @__PURE__ */ jsx2("h1", { className: "text-2xl font-bold tracking-tight", children: title }),
146
182
  description && /* @__PURE__ */ jsx2("p", { className: "mt-2 text-sm text-muted-foreground", children: description })
147
183
  ] }),
148
184
  children,
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
- ] }),
154
185
  /* @__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 }) })
155
186
  ] });
156
187
  };
@@ -158,28 +189,25 @@ var AuthPageLayout = ({
158
189
  // src/components/auth/verification-form.tsx
159
190
  import { zodResolver } from "@hookform/resolvers/zod";
160
191
  import { Button as Button2 } from "@mesob/ui/components/button";
161
- import {
162
- Form,
163
- FormControl,
164
- FormField,
165
- FormItem,
166
- FormMessage
167
- } from "@mesob/ui/components/form";
192
+ import { Field, FieldError, FieldGroup } from "@mesob/ui/components/field";
168
193
  import {
169
194
  InputOTP,
170
195
  InputOTPGroup,
171
196
  InputOTPSlot
172
197
  } from "@mesob/ui/components/input-otp";
173
198
  import { Spinner as Spinner2 } from "@mesob/ui/components/spinner";
174
- import { useTranslations as useTranslations2 } from "next-intl";
175
- import { useMemo } from "react";
176
- import { useForm } from "react-hook-form";
199
+ import { Controller, useForm } from "react-hook-form";
177
200
  import { z } from "zod";
178
201
 
202
+ // src/hooks/use-translator.ts
203
+ function useTranslator(namespace) {
204
+ const { config } = useConfig();
205
+ return createTranslator(config.messages || {}, namespace);
206
+ }
207
+
179
208
  // src/components/auth/countdown.tsx
180
209
  import { Button } from "@mesob/ui/components/button";
181
210
  import { Spinner } from "@mesob/ui/components/spinner";
182
- import { useTranslations } from "next-intl";
183
211
  import { useEffect as useEffect2, useState as useState2 } from "react";
184
212
  import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
185
213
  var Countdown = ({
@@ -187,7 +215,7 @@ var Countdown = ({
187
215
  onResend,
188
216
  resending = false
189
217
  }) => {
190
- const t = useTranslations("Common");
218
+ const t = useTranslator("Common");
191
219
  const [seconds, setSeconds] = useState2(initialSeconds);
192
220
  const [isResending, setIsResending] = useState2(false);
193
221
  useEffect2(() => {
@@ -234,32 +262,32 @@ var Countdown = ({
234
262
 
235
263
  // src/components/auth/verification-form.tsx
236
264
  import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
265
+ var verificationSchema = (t) => z.object({
266
+ code: z.string().length(6, t("form.codeLength"))
267
+ });
237
268
  var VerificationForm = ({
238
269
  onSubmit,
239
270
  onResend,
240
271
  isLoading = false
241
272
  }) => {
242
- const t = useTranslations2("Auth.verification");
243
- const verificationSchema = useMemo(
244
- () => z.object({
245
- code: z.string().length(6, t("form.codeLength"))
246
- }),
247
- [t]
248
- );
273
+ const t = useTranslator("Auth.verification");
249
274
  const form = useForm({
250
- resolver: zodResolver(verificationSchema),
275
+ resolver: zodResolver(verificationSchema(t)),
251
276
  defaultValues: {
252
277
  code: ""
253
278
  }
254
279
  });
255
- return /* @__PURE__ */ jsx4(Form, { ...form, children: /* @__PURE__ */ jsxs3("form", { className: "space-y-4", children: [
256
- /* @__PURE__ */ jsx4(
257
- FormField,
280
+ const handleSubmit = form.handleSubmit(async (values) => {
281
+ await onSubmit(values);
282
+ });
283
+ return /* @__PURE__ */ jsxs3("form", { id: "verification-form", onSubmit: handleSubmit, children: [
284
+ /* @__PURE__ */ jsx4(FieldGroup, { children: /* @__PURE__ */ jsx4(
285
+ Controller,
258
286
  {
259
- control: form.control,
260
287
  name: "code",
261
- render: ({ field }) => /* @__PURE__ */ jsxs3(FormItem, { children: [
262
- /* @__PURE__ */ jsx4(FormControl, { children: /* @__PURE__ */ jsx4("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx4(
288
+ control: form.control,
289
+ render: ({ field, fieldState }) => /* @__PURE__ */ jsxs3(Field, { "data-invalid": fieldState.invalid, children: [
290
+ /* @__PURE__ */ jsx4("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx4(
263
291
  InputOTP,
264
292
  {
265
293
  maxLength: 6,
@@ -269,6 +297,7 @@ var VerificationForm = ({
269
297
  onChange: field.onChange,
270
298
  onBlur: field.onBlur,
271
299
  containerClassName: "gap-4 justify-center mb-2 flex items-center",
300
+ "aria-invalid": fieldState.invalid,
272
301
  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
302
  /* @__PURE__ */ jsx4(InputOTPSlot, { className: "h-12", index: 0 }),
274
303
  /* @__PURE__ */ jsx4(InputOTPSlot, { className: "h-12", index: 1 }),
@@ -278,22 +307,18 @@ var VerificationForm = ({
278
307
  /* @__PURE__ */ jsx4(InputOTPSlot, { className: "h-12", index: 5 })
279
308
  ] })
280
309
  }
281
- ) }) }),
282
- /* @__PURE__ */ jsx4(FormMessage, {})
310
+ ) }),
311
+ fieldState.invalid && /* @__PURE__ */ jsx4(FieldError, { errors: [fieldState.error] })
283
312
  ] })
284
313
  }
285
- ),
286
- /* @__PURE__ */ jsxs3("div", { className: "flex justify-between items-center", children: [
314
+ ) }),
315
+ /* @__PURE__ */ jsxs3("div", { className: "flex justify-between items-center mt-4", children: [
287
316
  /* @__PURE__ */ jsx4(Countdown, { onResend, resending: isLoading }),
288
317
  /* @__PURE__ */ jsxs3(
289
318
  Button2,
290
319
  {
291
- type: "button",
292
- onClick: () => {
293
- form.handleSubmit(async (values) => {
294
- await onSubmit(values);
295
- })();
296
- },
320
+ type: "submit",
321
+ form: "verification-form",
297
322
  disabled: isLoading || form.watch("code").length !== 6,
298
323
  children: [
299
324
  isLoading && /* @__PURE__ */ jsx4(Spinner2, {}),
@@ -302,27 +327,50 @@ var VerificationForm = ({
302
327
  }
303
328
  )
304
329
  ] })
305
- ] }) });
330
+ ] });
306
331
  };
307
332
 
308
333
  // src/components/auth/pages/verify-email-page.tsx
309
- import { jsx as jsx5 } from "react/jsx-runtime";
334
+ import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
310
335
  var VerifyEmailPage = ({
311
336
  verificationId,
312
- onNavigate,
313
- linkComponent: Link,
314
- links,
315
337
  email,
316
- logoImage,
317
338
  redirectUrl
318
339
  }) => {
319
- const t = useTranslations3("Auth.verification");
320
- const common = useTranslations3("Common");
321
- const footer = useTranslations3("Auth.forgotPassword.footer");
322
- const { client, setAuth } = useAuth();
340
+ const { hooks, setAuth } = useApi();
341
+ const { config } = useConfig();
342
+ const t = createTranslator(config.messages || {}, "Auth.verification");
343
+ const common = createTranslator(config.messages || {}, "Common");
344
+ const footer = createTranslator(
345
+ config.messages || {},
346
+ "Auth.forgotPassword.footer"
347
+ );
323
348
  const [isLoading, setIsLoading] = useState3(false);
324
349
  const [error, setError] = useState3(null);
325
- const signInLink = links?.signIn || "/auth/sign-in";
350
+ const verifyEmailMutation = hooks.useMutation(
351
+ "post",
352
+ "/email/verification/confirm"
353
+ );
354
+ const requestEmailMutation = hooks.useMutation(
355
+ "post",
356
+ "/email/verification/request"
357
+ );
358
+ const signInLink = config.navigation?.links?.signIn || "/auth/sign-in";
359
+ const Link = config.navigation?.linkComponent;
360
+ const onNavigate = config.navigation?.onNavigate || ((path) => {
361
+ if (typeof window !== "undefined") {
362
+ window.location.href = path;
363
+ }
364
+ });
365
+ const logoImage = config.ui.logoImage;
366
+ const defaultRedirect = redirectUrl || config.navigation?.defaultRedirectUrl || "/";
367
+ useEffect3(() => {
368
+ if (error) {
369
+ toast.error(error.title || "Error", {
370
+ description: error.description
371
+ });
372
+ }
373
+ }, [error]);
326
374
  const handleSubmit = async (values) => {
327
375
  if (!verificationId) {
328
376
  setError({
@@ -334,14 +382,16 @@ var VerifyEmailPage = ({
334
382
  setIsLoading(true);
335
383
  setError(null);
336
384
  try {
337
- const res = await client.verifyEmail({
338
- verificationId,
339
- code: values.code
385
+ const res = await verifyEmailMutation.mutateAsync({
386
+ body: {
387
+ verificationId,
388
+ code: values.code
389
+ }
340
390
  });
341
391
  if ("user" in res && "session" in res) {
342
392
  setAuth(res);
343
393
  }
344
- onNavigate(redirectUrl || "/");
394
+ onNavigate(defaultRedirect);
345
395
  } catch (err) {
346
396
  handleError(err, setError, t);
347
397
  } finally {
@@ -351,7 +401,11 @@ var VerifyEmailPage = ({
351
401
  const handleResend = async () => {
352
402
  setError(null);
353
403
  try {
354
- const res = await client.requestEmailVerification({ email });
404
+ const res = await requestEmailMutation.mutateAsync({
405
+ body: {
406
+ email
407
+ }
408
+ });
355
409
  if (res.verificationId) {
356
410
  onNavigate(
357
411
  `/auth/verify-email?verificationId=${res.verificationId}&email=${encodeURIComponent(email)}`
@@ -388,12 +442,19 @@ var VerifyEmailPage = ({
388
442
  }
389
443
  );
390
444
  }
391
- return /* @__PURE__ */ jsx5(
445
+ let errorContent = null;
446
+ if (error) {
447
+ if (typeof error === "string") {
448
+ errorContent = { title: "Error", description: error };
449
+ } else {
450
+ errorContent = error;
451
+ }
452
+ }
453
+ return /* @__PURE__ */ jsxs4(
392
454
  AuthPageLayout,
393
455
  {
394
456
  title: t("email.title"),
395
457
  description: t("email.description"),
396
- error,
397
458
  logoImage,
398
459
  footer: Link ? /* @__PURE__ */ jsx5(Link, { href: signInLink, className: "text-primary hover:underline", children: footer("backToSignIn") }) : /* @__PURE__ */ jsx5(
399
460
  "a",
@@ -407,16 +468,23 @@ var VerifyEmailPage = ({
407
468
  children: footer("backToSignIn")
408
469
  }
409
470
  ),
410
- children: /* @__PURE__ */ jsx5(
411
- VerificationForm,
412
- {
413
- verificationId,
414
- onSubmit: handleSubmit,
415
- onResend: handleResend,
416
- isLoading,
417
- error
418
- }
419
- )
471
+ children: [
472
+ /* @__PURE__ */ jsx5(
473
+ VerificationForm,
474
+ {
475
+ verificationId,
476
+ onSubmit: handleSubmit,
477
+ onResend: handleResend,
478
+ isLoading: isLoading || verifyEmailMutation.isPending || requestEmailMutation.isPending,
479
+ error
480
+ }
481
+ ),
482
+ errorContent && /* @__PURE__ */ jsxs4(Alert, { variant: "destructive", className: "mt-4", children: [
483
+ /* @__PURE__ */ jsx5(IconAlertCircle, { className: "h-4 w-4" }),
484
+ /* @__PURE__ */ jsx5(AlertTitle, { children: errorContent.title }),
485
+ /* @__PURE__ */ jsx5(AlertDescription, { children: errorContent.description })
486
+ ] })
487
+ ]
420
488
  }
421
489
  );
422
490
  };