@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/reset-password-page.tsx
4
- import { useTranslations as useTranslations2 } 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 useEffect2, 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
  };
@@ -159,13 +190,11 @@ var AuthPageLayout = ({
159
190
  import { zodResolver } from "@hookform/resolvers/zod";
160
191
  import { Button } from "@mesob/ui/components/button";
161
192
  import {
162
- Form,
163
- FormControl,
164
- FormField,
165
- FormItem,
166
- FormLabel,
167
- FormMessage
168
- } from "@mesob/ui/components/form";
193
+ Field,
194
+ FieldError,
195
+ FieldGroup,
196
+ FieldLabel
197
+ } from "@mesob/ui/components/field";
169
198
  import { Input } from "@mesob/ui/components/input";
170
199
  import {
171
200
  InputOTP,
@@ -174,30 +203,34 @@ import {
174
203
  } from "@mesob/ui/components/input-otp";
175
204
  import { Spinner } from "@mesob/ui/components/spinner";
176
205
  import { IconEye, IconEyeOff } from "@tabler/icons-react";
177
- import { useTranslations } from "next-intl";
178
- import { useMemo, useState as useState2 } from "react";
179
- import { useForm } from "react-hook-form";
206
+ import { useState as useState2 } from "react";
207
+ import { Controller, useForm } from "react-hook-form";
180
208
  import { z } from "zod";
209
+
210
+ // src/hooks/use-translator.ts
211
+ function useTranslator(namespace) {
212
+ const { config } = useConfig();
213
+ return createTranslator(config.messages || {}, namespace);
214
+ }
215
+
216
+ // src/components/auth/reset-password-form.tsx
181
217
  import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
218
+ var resetPasswordSchema = (t) => z.object({
219
+ code: z.string().length(6, t("errors.codeLength")),
220
+ password: z.string().min(8, t("errors.passwordLength")),
221
+ confirmPassword: z.string()
222
+ }).refine((data) => data.password === data.confirmPassword, {
223
+ message: t("errors.passwordsMismatch"),
224
+ path: ["confirmPassword"]
225
+ });
182
226
  var ResetPasswordForm = ({
183
227
  onSubmit,
184
228
  isLoading = false
185
229
  }) => {
186
- const t = useTranslations("Auth.resetPassword");
230
+ const t = useTranslator("Auth.resetPassword");
187
231
  const [showPassword, setShowPassword] = useState2(false);
188
- const resetPasswordSchema = useMemo(
189
- () => z.object({
190
- code: z.string().length(6, t("errors.codeLength")),
191
- password: z.string().min(8, t("errors.passwordLength")),
192
- confirmPassword: z.string()
193
- }).refine((data) => data.password === data.confirmPassword, {
194
- message: t("errors.passwordsMismatch"),
195
- path: ["confirmPassword"]
196
- }),
197
- [t]
198
- );
199
232
  const form = useForm({
200
- resolver: zodResolver(resetPasswordSchema),
233
+ resolver: zodResolver(resetPasswordSchema(t)),
201
234
  defaultValues: {
202
235
  code: "",
203
236
  password: "",
@@ -207,110 +240,149 @@ var ResetPasswordForm = ({
207
240
  const handleSubmit = form.handleSubmit(async (values) => {
208
241
  await onSubmit(values);
209
242
  });
210
- return /* @__PURE__ */ jsx3(Form, { ...form, children: /* @__PURE__ */ jsxs2("form", { onSubmit: handleSubmit, className: "space-y-4", children: [
211
- /* @__PURE__ */ jsx3(
212
- FormField,
213
- {
214
- control: form.control,
215
- name: "code",
216
- render: ({ field }) => /* @__PURE__ */ jsxs2(FormItem, { children: [
217
- /* @__PURE__ */ jsx3("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx3(FormLabel, { children: t("form.codeLabel") }) }),
218
- /* @__PURE__ */ jsx3(FormControl, { children: /* @__PURE__ */ jsx3("div", { className: "flex mt-2 justify-center", children: /* @__PURE__ */ jsx3(InputOTP, { maxLength: 6, ...field, containerClassName: "gap-4", children: /* @__PURE__ */ jsxs2(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: [
219
- /* @__PURE__ */ jsx3(InputOTPSlot, { className: "h-12", index: 0 }),
220
- /* @__PURE__ */ jsx3(InputOTPSlot, { className: "h-12", index: 1 }),
221
- /* @__PURE__ */ jsx3(InputOTPSlot, { className: "h-12", index: 2 }),
222
- /* @__PURE__ */ jsx3(InputOTPSlot, { className: "h-12", index: 3 }),
223
- /* @__PURE__ */ jsx3(InputOTPSlot, { className: "h-12", index: 4 }),
224
- /* @__PURE__ */ jsx3(InputOTPSlot, { className: "h-12", index: 5 })
225
- ] }) }) }) }),
226
- /* @__PURE__ */ jsx3(FormMessage, {})
227
- ] })
228
- }
229
- ),
230
- /* @__PURE__ */ jsx3(
231
- FormField,
232
- {
233
- control: form.control,
234
- name: "password",
235
- render: ({ field }) => /* @__PURE__ */ jsxs2(FormItem, { children: [
236
- /* @__PURE__ */ jsx3(FormLabel, { children: t("form.passwordLabel") }),
237
- /* @__PURE__ */ jsx3(FormControl, { children: /* @__PURE__ */ jsxs2("div", { className: "relative", children: [
238
- /* @__PURE__ */ jsx3(
239
- Input,
240
- {
241
- type: showPassword ? "text" : "password",
242
- placeholder: t("form.passwordPlaceholder"),
243
- ...field
244
- }
245
- ),
246
- /* @__PURE__ */ jsx3(
247
- "button",
243
+ return /* @__PURE__ */ jsxs2("form", { id: "reset-password-form", onSubmit: handleSubmit, children: [
244
+ /* @__PURE__ */ jsxs2(FieldGroup, { children: [
245
+ /* @__PURE__ */ jsx3(
246
+ Controller,
247
+ {
248
+ name: "code",
249
+ control: form.control,
250
+ render: ({ field, fieldState }) => /* @__PURE__ */ jsxs2(Field, { "data-invalid": fieldState.invalid, children: [
251
+ /* @__PURE__ */ jsx3("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx3(FieldLabel, { children: t("form.codeLabel") }) }),
252
+ /* @__PURE__ */ jsx3("div", { className: "flex mt-2 justify-center", children: /* @__PURE__ */ jsx3(
253
+ InputOTP,
248
254
  {
249
- type: "button",
250
- onClick: () => setShowPassword(!showPassword),
251
- className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground",
252
- children: showPassword ? /* @__PURE__ */ jsx3(IconEyeOff, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx3(IconEye, { className: "h-4 w-4" })
255
+ maxLength: 6,
256
+ value: field.value,
257
+ onChange: field.onChange,
258
+ onBlur: field.onBlur,
259
+ containerClassName: "gap-4",
260
+ "aria-invalid": fieldState.invalid,
261
+ children: /* @__PURE__ */ jsxs2(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: [
262
+ /* @__PURE__ */ jsx3(InputOTPSlot, { className: "h-12", index: 0 }),
263
+ /* @__PURE__ */ jsx3(InputOTPSlot, { className: "h-12", index: 1 }),
264
+ /* @__PURE__ */ jsx3(InputOTPSlot, { className: "h-12", index: 2 }),
265
+ /* @__PURE__ */ jsx3(InputOTPSlot, { className: "h-12", index: 3 }),
266
+ /* @__PURE__ */ jsx3(InputOTPSlot, { className: "h-12", index: 4 }),
267
+ /* @__PURE__ */ jsx3(InputOTPSlot, { className: "h-12", index: 5 })
268
+ ] })
253
269
  }
254
- )
255
- ] }) }),
256
- /* @__PURE__ */ jsx3(FormMessage, {})
257
- ] })
258
- }
259
- ),
260
- /* @__PURE__ */ jsx3(
261
- FormField,
270
+ ) }),
271
+ fieldState.invalid && /* @__PURE__ */ jsx3(FieldError, { errors: [fieldState.error] })
272
+ ] })
273
+ }
274
+ ),
275
+ /* @__PURE__ */ jsx3(
276
+ Controller,
277
+ {
278
+ name: "password",
279
+ control: form.control,
280
+ render: ({ field, fieldState }) => /* @__PURE__ */ jsxs2(Field, { "data-invalid": fieldState.invalid, children: [
281
+ /* @__PURE__ */ jsx3(FieldLabel, { htmlFor: "reset-password-password", children: t("form.passwordLabel") }),
282
+ /* @__PURE__ */ jsxs2("div", { className: "relative", children: [
283
+ /* @__PURE__ */ jsx3(
284
+ Input,
285
+ {
286
+ ...field,
287
+ id: "reset-password-password",
288
+ type: showPassword ? "text" : "password",
289
+ placeholder: t("form.passwordPlaceholder"),
290
+ "aria-invalid": fieldState.invalid
291
+ }
292
+ ),
293
+ /* @__PURE__ */ jsx3(
294
+ "button",
295
+ {
296
+ type: "button",
297
+ onClick: () => setShowPassword(!showPassword),
298
+ className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground",
299
+ children: showPassword ? /* @__PURE__ */ jsx3(IconEyeOff, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx3(IconEye, { className: "h-4 w-4" })
300
+ }
301
+ )
302
+ ] }),
303
+ fieldState.invalid && /* @__PURE__ */ jsx3(FieldError, { errors: [fieldState.error] })
304
+ ] })
305
+ }
306
+ ),
307
+ /* @__PURE__ */ jsx3(
308
+ Controller,
309
+ {
310
+ name: "confirmPassword",
311
+ control: form.control,
312
+ render: ({ field, fieldState }) => /* @__PURE__ */ jsxs2(Field, { "data-invalid": fieldState.invalid, children: [
313
+ /* @__PURE__ */ jsx3(FieldLabel, { htmlFor: "reset-password-confirmPassword", children: t("form.confirmPasswordLabel") }),
314
+ /* @__PURE__ */ jsxs2("div", { className: "relative", children: [
315
+ /* @__PURE__ */ jsx3(
316
+ Input,
317
+ {
318
+ ...field,
319
+ id: "reset-password-confirmPassword",
320
+ type: showPassword ? "text" : "password",
321
+ placeholder: t("form.passwordPlaceholder"),
322
+ "aria-invalid": fieldState.invalid
323
+ }
324
+ ),
325
+ /* @__PURE__ */ jsx3(
326
+ "button",
327
+ {
328
+ type: "button",
329
+ onClick: () => setShowPassword(!showPassword),
330
+ className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground",
331
+ children: showPassword ? /* @__PURE__ */ jsx3(IconEyeOff, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx3(IconEye, { className: "h-4 w-4" })
332
+ }
333
+ )
334
+ ] }),
335
+ fieldState.invalid && /* @__PURE__ */ jsx3(FieldError, { errors: [fieldState.error] })
336
+ ] })
337
+ }
338
+ )
339
+ ] }),
340
+ /* @__PURE__ */ jsx3("div", { className: "mt-4", children: /* @__PURE__ */ jsxs2(
341
+ Button,
262
342
  {
263
- control: form.control,
264
- name: "confirmPassword",
265
- render: ({ field }) => /* @__PURE__ */ jsxs2(FormItem, { children: [
266
- /* @__PURE__ */ jsx3(FormLabel, { children: t("form.confirmPasswordLabel") }),
267
- /* @__PURE__ */ jsx3(FormControl, { children: /* @__PURE__ */ jsxs2("div", { className: "relative", children: [
268
- /* @__PURE__ */ jsx3(
269
- Input,
270
- {
271
- type: showPassword ? "text" : "password",
272
- placeholder: t("form.passwordPlaceholder"),
273
- ...field
274
- }
275
- ),
276
- /* @__PURE__ */ jsx3(
277
- "button",
278
- {
279
- type: "button",
280
- onClick: () => setShowPassword(!showPassword),
281
- className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground",
282
- children: showPassword ? /* @__PURE__ */ jsx3(IconEyeOff, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx3(IconEye, { className: "h-4 w-4" })
283
- }
284
- )
285
- ] }) }),
286
- /* @__PURE__ */ jsx3(FormMessage, {})
287
- ] })
343
+ type: "submit",
344
+ form: "reset-password-form",
345
+ className: "w-full",
346
+ disabled: isLoading,
347
+ children: [
348
+ isLoading && /* @__PURE__ */ jsx3(Spinner, {}),
349
+ isLoading ? t("form.submitting") : t("form.submit")
350
+ ]
288
351
  }
289
- ),
290
- /* @__PURE__ */ jsxs2(Button, { type: "submit", className: "w-full", disabled: isLoading, children: [
291
- isLoading && /* @__PURE__ */ jsx3(Spinner, {}),
292
- isLoading ? t("form.submitting") : t("form.submit")
293
- ] })
294
- ] }) });
352
+ ) })
353
+ ] });
295
354
  };
296
355
 
297
356
  // src/components/auth/pages/reset-password-page.tsx
298
357
  import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
299
358
  var ResetPasswordPage = ({
300
359
  verificationId,
301
- onNavigate,
302
- linkComponent: Link,
303
- links,
304
- logoImage,
305
360
  redirectUrl
306
361
  }) => {
307
- const t = useTranslations2("Auth.resetPassword");
308
- const common = useTranslations2("Common");
309
- const { client, refresh } = useAuth();
362
+ const { hooks, refresh } = useApi();
363
+ const { config } = useConfig();
364
+ const t = createTranslator(config.messages || {}, "Auth.resetPassword");
365
+ const common = createTranslator(config.messages || {}, "Common");
310
366
  const [isLoading, setIsLoading] = useState3(false);
311
367
  const [error, setError] = useState3(null);
312
- const signInLink = links?.signIn || "/auth/sign-in";
313
- const forgotPasswordLink = links?.forgotPassword || "/auth/forgot-password";
368
+ const resetPasswordMutation = hooks.useMutation("post", "/password/reset");
369
+ const signInLink = config.navigation?.links?.signIn || "/auth/sign-in";
370
+ const forgotPasswordLink = config.navigation?.links?.forgotPassword || "/auth/forgot-password";
371
+ const Link = config.navigation?.linkComponent;
372
+ const onNavigate = config.navigation?.onNavigate || ((path) => {
373
+ if (typeof window !== "undefined") {
374
+ window.location.href = path;
375
+ }
376
+ });
377
+ const logoImage = config.ui.logoImage;
378
+ const defaultRedirect = redirectUrl || config.navigation?.defaultRedirectUrl || "/";
379
+ useEffect2(() => {
380
+ if (error) {
381
+ toast.error(error.title || "Error", {
382
+ description: error.description
383
+ });
384
+ }
385
+ }, [error]);
314
386
  const handleSubmit = async (values) => {
315
387
  if (!verificationId) {
316
388
  setError({
@@ -322,13 +394,15 @@ var ResetPasswordPage = ({
322
394
  setIsLoading(true);
323
395
  setError(null);
324
396
  try {
325
- await client.resetPassword({
326
- verificationId,
327
- code: values.code,
328
- password: values.password
397
+ await resetPasswordMutation.mutateAsync({
398
+ body: {
399
+ verificationId,
400
+ code: values.code,
401
+ password: values.password
402
+ }
329
403
  });
330
404
  await refresh();
331
- onNavigate(redirectUrl || "/");
405
+ onNavigate(defaultRedirect);
332
406
  } catch (err) {
333
407
  handleError(err, setError, t);
334
408
  } finally {
@@ -365,12 +439,19 @@ var ResetPasswordPage = ({
365
439
  }
366
440
  );
367
441
  }
368
- return /* @__PURE__ */ jsx4(
442
+ let errorContent = null;
443
+ if (error) {
444
+ if (typeof error === "string") {
445
+ errorContent = { title: "Error", description: error };
446
+ } else {
447
+ errorContent = error;
448
+ }
449
+ }
450
+ return /* @__PURE__ */ jsxs3(
369
451
  AuthPageLayout,
370
452
  {
371
453
  title: t("title"),
372
454
  description: t("description"),
373
- error,
374
455
  logoImage,
375
456
  footer: Link ? /* @__PURE__ */ jsxs3("div", { className: "flex items-center justify-between w-full gap-2", children: [
376
457
  /* @__PURE__ */ jsx4(Link, { href: signInLink, className: "text-primary hover:underline", children: t("footer.backToSignIn") }),
@@ -408,15 +489,22 @@ var ResetPasswordPage = ({
408
489
  }
409
490
  )
410
491
  ] }),
411
- children: /* @__PURE__ */ jsx4(
412
- ResetPasswordForm,
413
- {
414
- verificationId,
415
- onSubmit: handleSubmit,
416
- isLoading,
417
- error
418
- }
419
- )
492
+ children: [
493
+ /* @__PURE__ */ jsx4(
494
+ ResetPasswordForm,
495
+ {
496
+ verificationId,
497
+ onSubmit: handleSubmit,
498
+ isLoading: isLoading || resetPasswordMutation.isPending,
499
+ error
500
+ }
501
+ ),
502
+ errorContent && /* @__PURE__ */ jsxs3(Alert, { variant: "destructive", className: "mt-4", children: [
503
+ /* @__PURE__ */ jsx4(IconAlertCircle, { className: "h-4 w-4" }),
504
+ /* @__PURE__ */ jsx4(AlertTitle, { children: errorContent.title }),
505
+ /* @__PURE__ */ jsx4(AlertDescription, { children: errorContent.description })
506
+ ] })
507
+ ]
420
508
  }
421
509
  );
422
510
  };