@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
package/dist/index.js CHANGED
@@ -1,428 +1,260 @@
1
1
  "use client";
2
2
 
3
- // src/client.ts
4
- var validErrorCodes = [
5
- "USER_NOT_FOUND",
6
- "INVALID_PASSWORD",
7
- "USER_EXISTS",
8
- "VERIFICATION_EXPIRED",
9
- "VERIFICATION_MISMATCH",
10
- "VERIFICATION_NOT_FOUND",
11
- "TOO_MANY_ATTEMPTS",
12
- "REQUIRES_VERIFICATION",
13
- "UNAUTHORIZED",
14
- "ACCESS_DENIED",
15
- "HAS_NO_PASSWORD"
16
- ];
17
- var AuthError = class extends Error {
18
- code;
19
- status;
20
- details;
21
- constructor(message, code, status, details) {
22
- super(message);
23
- this.name = "AuthError";
24
- this.code = code;
25
- this.status = status;
26
- this.details = details;
27
- }
28
- };
29
- var AuthClient = class {
30
- baseURL;
31
- constructor(config) {
32
- this.baseURL = config.baseURL.replace(/\/$/, "");
33
- }
34
- async request(endpoint, options = {}) {
35
- const url = `${this.baseURL}${endpoint}`;
36
- const response = await fetch(url, {
37
- ...options,
38
- credentials: "include",
39
- headers: {
40
- "Content-Type": "application/json",
41
- ...options.headers
42
- }
43
- });
44
- if (!response.ok) {
45
- const text = await response.text();
46
- let errorData;
47
- try {
48
- errorData = JSON.parse(text);
49
- } catch {
50
- errorData = { error: "Unknown error", message: text };
51
- }
52
- const potentialCode = errorData.code || (typeof errorData.error === "string" ? errorData.error : null) || (typeof errorData.message === "string" ? errorData.message : null);
53
- const upperCode = potentialCode?.toUpperCase().trim();
54
- const errorCode = upperCode && validErrorCodes.includes(upperCode) ? upperCode : void 0;
55
- const errorMessage = errorData.message || errorData.error || "Request failed";
56
- throw new AuthError(
57
- errorMessage,
58
- errorCode,
59
- response.status,
60
- errorData.details
61
- );
62
- }
63
- const data = await response.json();
64
- return data;
65
- }
66
- signUpWithEmail(data) {
67
- return this.request("/sign-up", {
68
- method: "POST",
69
- body: JSON.stringify({
70
- email: data.email,
71
- password: data.password,
72
- fullName: data.fullName,
73
- handle: data.handle
74
- })
75
- });
76
- }
77
- signUpWithPhone(data) {
78
- return this.request("/sign-up", {
79
- method: "POST",
80
- body: JSON.stringify({
81
- phone: data.phone,
82
- password: data.password,
83
- fullName: data.fullName,
84
- handle: data.handle
85
- })
86
- });
87
- }
88
- checkUser(data) {
89
- return this.request("/check-user", {
90
- method: "POST",
91
- body: JSON.stringify(data)
92
- });
93
- }
94
- signInWithPassword(data) {
95
- return this.request("/sign-in", {
96
- method: "POST",
97
- body: JSON.stringify(data)
98
- });
99
- }
100
- signOut() {
101
- return this.request("/sign-out", {
102
- method: "POST"
103
- });
104
- }
105
- requestEmailVerification(data) {
106
- return this.request(
107
- "/email/verification/request",
108
- {
109
- method: "POST",
110
- body: JSON.stringify(data || {})
111
- }
112
- );
113
- }
114
- verifyEmail(data) {
115
- return this.request("/email/verification/confirm", {
116
- method: "POST",
117
- body: JSON.stringify(data)
118
- });
119
- }
120
- resendVerification(_verificationId) {
121
- return this.requestEmailVerification();
122
- }
123
- requestPhoneOtp(data) {
124
- return this.request(
125
- "/phone/verification/request",
126
- {
127
- method: "POST",
128
- body: JSON.stringify(data)
129
- }
130
- );
131
- }
132
- verifyPhoneOtp(data) {
133
- return this.request("/phone/verification/confirm", {
134
- method: "POST",
135
- body: JSON.stringify(data)
136
- });
137
- }
138
- forgotPassword(data) {
139
- return this.request("/password/forgot", {
140
- method: "POST",
141
- body: JSON.stringify(data)
142
- });
143
- }
144
- resetPassword(data) {
145
- return this.request("/password/reset", {
146
- method: "POST",
147
- body: JSON.stringify(data)
148
- });
149
- }
150
- verifyPassword(data) {
151
- return this.request("/password/verify", {
152
- method: "POST",
153
- body: JSON.stringify(data)
154
- });
155
- }
156
- changePassword(data) {
157
- return this.request("/password/change", {
158
- method: "POST",
159
- body: JSON.stringify(data)
160
- });
161
- }
162
- getSession() {
163
- return this.request("/session", {
164
- method: "GET"
165
- });
166
- }
167
- getPendingAccountChange() {
168
- return this.request(
169
- "/account-change/pending",
170
- {
171
- method: "GET"
172
- }
173
- );
174
- }
175
- updateProfile(data) {
176
- return this.request("/profile", {
177
- method: "PUT",
178
- body: JSON.stringify(data)
179
- });
180
- }
181
- updateEmail(data) {
182
- return this.request("/profile/email", {
183
- method: "PUT",
184
- body: JSON.stringify(data)
185
- });
186
- }
187
- updatePhone(data) {
188
- return this.request("/profile/phone", {
189
- method: "PUT",
190
- body: JSON.stringify(data)
191
- });
192
- }
193
- };
194
-
195
3
  // src/components/auth/auth-card.tsx
196
4
  import { jsx } from "react/jsx-runtime";
197
5
  var AuthCard = ({ children }) => {
198
6
  return /* @__PURE__ */ jsx("div", { className: "flex min-h-screen p-4 items-center justify-center", children: /* @__PURE__ */ jsx("div", { className: "w-full max-w-md", children: /* @__PURE__ */ jsx("div", { className: "rounded-xl border bg-card p-8 shadow-lg", children }) }) });
199
7
  };
200
8
 
201
- // src/components/auth/auth-page-layout.tsx
9
+ // src/components/auth/pages/forgot-password-page.tsx
202
10
  import {
203
11
  Alert,
204
12
  AlertDescription,
205
13
  AlertTitle
206
14
  } from "@mesob/ui/components/alert";
15
+ import { toast } from "@mesob/ui/components/sonner";
207
16
  import { IconAlertCircle } from "@tabler/icons-react";
208
- import { jsx as jsx2, jsxs } from "react/jsx-runtime";
209
- var AuthPageLayout = ({
210
- title,
211
- description,
212
- children,
213
- error,
214
- footer,
215
- logoImage
216
- }) => {
217
- const errorContent = error ? (
218
- // biome-ignore lint/style/noNestedTernary: <explanation>
219
- typeof error === "string" ? { title: "Error", description: error } : error
220
- ) : null;
221
- return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
222
- /* @__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 }) }),
223
- /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
224
- /* @__PURE__ */ jsx2("h1", { className: "text-2xl font-bold tracking-tight", children: title }),
225
- description && /* @__PURE__ */ jsx2("p", { className: "mt-2 text-sm text-muted-foreground", children: description })
226
- ] }),
227
- children,
228
- errorContent && /* @__PURE__ */ jsxs(Alert, { variant: "destructive", children: [
229
- /* @__PURE__ */ jsx2(IconAlertCircle, { className: "h-4 w-4" }),
230
- /* @__PURE__ */ jsx2(AlertTitle, { children: errorContent.title }),
231
- /* @__PURE__ */ jsx2(AlertDescription, { children: errorContent.description })
232
- ] }),
233
- /* @__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 }) })
234
- ] });
235
- };
17
+ import { useEffect as useEffect2, useState as useState2 } from "react";
236
18
 
237
- // src/components/auth/countdown.tsx
238
- import { Button } from "@mesob/ui/components/button";
239
- import { Spinner } from "@mesob/ui/components/spinner";
240
- import { useTranslations } from "next-intl";
241
- import { useEffect, useState } from "react";
242
- import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
243
- var Countdown = ({
244
- initialSeconds = 60,
245
- onResend,
246
- resending = false
247
- }) => {
248
- const t = useTranslations("Common");
249
- const [seconds, setSeconds] = useState(initialSeconds);
250
- const [isResending, setIsResending] = useState(false);
251
- useEffect(() => {
252
- if (seconds <= 0) {
253
- return;
19
+ // src/lib/translations.ts
20
+ function createTranslator(messages, namespace) {
21
+ return (key, params) => {
22
+ const fullKey = namespace ? `${namespace}.${key}` : key;
23
+ const keys = fullKey.split(".");
24
+ let value = messages;
25
+ for (const k of keys) {
26
+ if (value && typeof value === "object" && value !== null) {
27
+ value = value[k];
28
+ } else {
29
+ return fullKey;
30
+ }
254
31
  }
255
- const timer = setInterval(() => {
256
- setSeconds((prev) => {
257
- if (prev <= 1) {
258
- clearInterval(timer);
259
- return 0;
260
- }
261
- return prev - 1;
262
- });
263
- }, 1e3);
264
- return () => clearInterval(timer);
265
- }, [seconds]);
266
- const handleResend = async () => {
267
- setIsResending(true);
268
- try {
269
- await onResend();
270
- setSeconds(initialSeconds);
271
- } catch (_error) {
272
- } finally {
273
- setIsResending(false);
32
+ if (typeof value !== "string") {
33
+ return fullKey;
274
34
  }
275
- };
276
- if (seconds > 0) {
277
- return /* @__PURE__ */ jsx3(Button, { variant: "ghost", disabled: true, children: t("resendIn", { seconds }) });
278
- }
279
- return /* @__PURE__ */ jsxs2(
280
- Button,
281
- {
282
- variant: "ghost",
283
- onClick: handleResend,
284
- disabled: isResending || resending,
285
- children: [
286
- isResending || resending && /* @__PURE__ */ jsx3(Spinner, {}),
287
- t("resend")
288
- ]
35
+ if (params) {
36
+ return value.replace(
37
+ /\{(\w+)\}/g,
38
+ (_, param) => String(params[param] ?? `{${param}}`)
39
+ );
289
40
  }
290
- );
41
+ return value;
42
+ };
43
+ }
44
+
45
+ // src/provider.tsx
46
+ import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
47
+ import { deepmerge } from "deepmerge-ts";
48
+ import createFetchClient from "openapi-fetch";
49
+ import createClient from "openapi-react-query";
50
+ import { createContext, useContext, useEffect, useState } from "react";
51
+
52
+ // src/types.ts
53
+ var defaultAuthClientConfig = {
54
+ features: {
55
+ enableSignup: true,
56
+ enablePasswordReset: true,
57
+ enableEmailSignup: true,
58
+ enablePhoneSignup: true,
59
+ enableSocialSignup: false,
60
+ socialProviders: []
61
+ },
62
+ navigation: {
63
+ locale: "en"
64
+ },
65
+ cookiePrefix: "msb"
291
66
  };
292
67
 
293
- // src/components/auth/forgot-password.tsx
294
- import { zodResolver } from "@hookform/resolvers/zod";
295
- import { Button as Button2 } from "@mesob/ui/components/button";
296
- import {
297
- Form,
298
- FormControl,
299
- FormField,
300
- FormItem,
301
- FormLabel,
302
- FormMessage
303
- } from "@mesob/ui/components/form";
304
- import { Input } from "@mesob/ui/components/input";
305
- import { Spinner as Spinner2 } from "@mesob/ui/components/spinner";
306
- import { useTranslations as useTranslations2 } from "next-intl";
307
- import { useMemo } from "react";
308
- import { useForm } from "react-hook-form";
309
- import { z } from "zod";
310
- import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
311
- var ForgotPassword = ({
312
- onSubmit,
313
- isLoading = false
314
- }) => {
315
- const t = useTranslations2("Auth.forgotPassword");
316
- const forgotPasswordSchema = useMemo(
317
- () => z.object({
318
- account: z.string().min(1, t("errors.accountRequired"))
319
- }),
320
- [t]
321
- );
322
- const form = useForm({
323
- resolver: zodResolver(forgotPasswordSchema),
324
- defaultValues: {
325
- account: ""
326
- }
327
- });
328
- const handleSubmit = form.handleSubmit(async (values) => {
329
- await onSubmit(values);
330
- });
331
- return /* @__PURE__ */ jsx4(Form, { ...form, children: /* @__PURE__ */ jsxs3("form", { onSubmit: handleSubmit, className: "space-y-4", children: [
332
- /* @__PURE__ */ jsx4(
333
- FormField,
334
- {
335
- control: form.control,
336
- name: "account",
337
- render: ({ field }) => /* @__PURE__ */ jsxs3(FormItem, { children: [
338
- /* @__PURE__ */ jsx4(FormLabel, { children: t("form.accountLabel") }),
339
- /* @__PURE__ */ jsx4(FormControl, { children: /* @__PURE__ */ jsx4(
340
- Input,
341
- {
342
- type: "text",
343
- placeholder: t("form.accountPlaceholder"),
344
- ...field
345
- }
346
- ) }),
347
- /* @__PURE__ */ jsx4(FormMessage, {})
348
- ] })
68
+ // src/utils/custom-fetch.ts
69
+ var createCustomFetch = (config) => {
70
+ return (input, init) => {
71
+ const baseUrl = config.baseURL;
72
+ if (input instanceof Request) {
73
+ const originalUrl = input.url;
74
+ const fullUrl2 = originalUrl.startsWith("http") ? originalUrl : `${baseUrl}${originalUrl}`;
75
+ if (originalUrl === fullUrl2) {
76
+ return fetch(input, {
77
+ credentials: "include"
78
+ });
349
79
  }
350
- ),
351
- /* @__PURE__ */ jsxs3(Button2, { type: "submit", className: "w-full", disabled: isLoading, children: [
352
- isLoading && /* @__PURE__ */ jsx4(Spinner2, {}),
353
- isLoading ? t("form.submitting") : t("form.submit")
354
- ] })
355
- ] }) });
80
+ const clonedRequest = input.clone();
81
+ const requestInit = {
82
+ method: clonedRequest.method,
83
+ headers: clonedRequest.headers,
84
+ credentials: "include"
85
+ };
86
+ if (clonedRequest.body !== null) {
87
+ requestInit.body = clonedRequest.body;
88
+ requestInit.duplex = "half";
89
+ }
90
+ return fetch(fullUrl2, requestInit);
91
+ }
92
+ const urlString = typeof input === "string" ? input : input.toString();
93
+ const fullUrl = urlString.startsWith("http") ? urlString : `${baseUrl}${urlString}`;
94
+ return fetch(fullUrl, {
95
+ ...init,
96
+ headers: {
97
+ "Content-Type": "application/json",
98
+ ...init?.headers
99
+ },
100
+ credentials: "include"
101
+ });
102
+ };
356
103
  };
357
104
 
358
- // src/components/auth/pages/forgot-password-page.tsx
359
- import { useTranslations as useTranslations3 } from "next-intl";
360
- import { useState as useState3 } from "react";
361
-
362
- // src/context/auth-provider.tsx
363
- import {
364
- createContext,
365
- useCallback,
366
- useContext,
367
- useEffect as useEffect2,
368
- useState as useState2
369
- } from "react";
370
- import { jsx as jsx5 } from "react/jsx-runtime";
371
- var AuthContext = createContext(null);
372
- var useAuth = () => {
373
- const context = useContext(AuthContext);
105
+ // src/provider.tsx
106
+ import { jsx as jsx2 } from "react/jsx-runtime";
107
+ var SessionContext = createContext(null);
108
+ var ApiContext = createContext(null);
109
+ var ConfigContext = createContext(null);
110
+ var queryClient = new QueryClient({
111
+ defaultOptions: {
112
+ queries: {
113
+ staleTime: 1e3 * 60 * 5,
114
+ gcTime: 1e3 * 60 * 10,
115
+ retry: 1,
116
+ refetchOnWindowFocus: false
117
+ }
118
+ }
119
+ });
120
+ function useSession() {
121
+ const context = useContext(SessionContext);
374
122
  if (!context) {
375
- throw new Error("useAuth must be used within AuthProvider");
123
+ throw new Error("useSession must be used within MesobAuthProvider");
376
124
  }
377
125
  return context;
378
- };
379
- var AuthProvider = ({ client, children }) => {
380
- const [user, setUser] = useState2(null);
381
- const [session, setSession] = useState2(null);
382
- const [loading, setLoading] = useState2(true);
383
- const [error, setError] = useState2(null);
384
- const refresh = useCallback(async () => {
126
+ }
127
+ function useApi() {
128
+ const context = useContext(ApiContext);
129
+ if (!context) {
130
+ throw new Error("useApi must be used within MesobAuthProvider");
131
+ }
132
+ return context;
133
+ }
134
+ function useConfig() {
135
+ const context = useContext(ConfigContext);
136
+ if (!context) {
137
+ throw new Error("useConfig must be used within MesobAuthProvider");
138
+ }
139
+ return context;
140
+ }
141
+ function MesobAuthProvider({
142
+ config,
143
+ children
144
+ }) {
145
+ const mergedConfig = deepmerge(
146
+ { ...defaultAuthClientConfig },
147
+ config
148
+ );
149
+ const api = createFetchClient({
150
+ baseUrl: mergedConfig.baseURL,
151
+ fetch: createCustomFetch(mergedConfig)
152
+ });
153
+ const hooks = createClient(api);
154
+ return /* @__PURE__ */ jsx2(QueryClientProvider, { client: queryClient, children: /* @__PURE__ */ jsx2(AuthStateProvider, { config: mergedConfig, hooks, children }) });
155
+ }
156
+ function AuthStateProvider({
157
+ config,
158
+ hooks,
159
+ children
160
+ }) {
161
+ const [authState, setAuthState] = useState({
162
+ user: null,
163
+ session: null,
164
+ isLoading: false,
165
+ error: null
166
+ });
167
+ const {
168
+ data: sessionData,
169
+ isLoading: sessionLoading,
170
+ error: sessionError,
171
+ refetch
172
+ } = hooks.useQuery(
173
+ "get",
174
+ "/session",
175
+ {},
176
+ {
177
+ enabled: true,
178
+ refetchOnMount: true,
179
+ refetchOnWindowFocus: false,
180
+ refetchOnReconnect: false,
181
+ retry: false
182
+ }
183
+ );
184
+ useEffect(() => {
185
+ if (sessionLoading) {
186
+ setAuthState((prev) => ({ ...prev, isLoading: true }));
187
+ return;
188
+ }
189
+ if (sessionError) {
190
+ setAuthState({
191
+ user: null,
192
+ session: null,
193
+ isLoading: false,
194
+ error: sessionError
195
+ });
196
+ return;
197
+ }
198
+ if (sessionData) {
199
+ setAuthState({
200
+ user: sessionData.user,
201
+ session: sessionData.session,
202
+ isLoading: false,
203
+ error: null
204
+ });
205
+ return;
206
+ }
207
+ setAuthState({
208
+ user: null,
209
+ session: null,
210
+ isLoading: false,
211
+ error: null
212
+ });
213
+ }, [sessionData, sessionLoading, sessionError]);
214
+ const refresh = async () => {
215
+ await refetch();
216
+ };
217
+ const setAuth = (auth) => {
218
+ setAuthState({
219
+ user: auth.user,
220
+ session: auth.session,
221
+ isLoading: false,
222
+ error: null
223
+ });
224
+ };
225
+ const clearAuth = () => {
226
+ setAuthState({
227
+ user: null,
228
+ session: null,
229
+ isLoading: false,
230
+ error: null
231
+ });
232
+ };
233
+ const signOutMutation = hooks.useMutation("post", "/sign-out");
234
+ const signOut = async () => {
385
235
  try {
386
- setLoading(true);
387
- setError(null);
388
- const data = await client.getSession();
389
- setUser(data.user);
390
- setSession(data.session);
391
- } catch (err) {
392
- setError(
393
- err instanceof Error ? err : new Error("Failed to fetch session")
394
- );
395
- setUser(null);
396
- setSession(null);
236
+ await signOutMutation.mutateAsync({});
397
237
  } finally {
398
- setLoading(false);
238
+ clearAuth();
399
239
  }
400
- }, [client]);
401
- const setAuth = useCallback((data) => {
402
- setUser(data.user);
403
- setSession(data.session);
404
- setError(null);
405
- setLoading(false);
406
- }, []);
407
- useEffect2(() => {
408
- refresh();
409
- }, [refresh]);
410
- return /* @__PURE__ */ jsx5(
411
- AuthContext.Provider,
240
+ };
241
+ const t = createTranslator(config.messages || {});
242
+ return /* @__PURE__ */ jsx2(ConfigContext.Provider, { value: { config, t }, children: /* @__PURE__ */ jsx2(ApiContext.Provider, { value: { hooks, setAuth, clearAuth, refresh }, children: /* @__PURE__ */ jsx2(
243
+ SessionContext.Provider,
412
244
  {
413
245
  value: {
414
- user,
415
- session,
416
- loading,
417
- error,
418
- client,
246
+ user: authState.user,
247
+ session: authState.session,
248
+ isLoading: authState.isLoading,
249
+ isAuthenticated: !!authState.user && !!authState.session,
250
+ error: authState.error,
419
251
  refresh,
420
- setAuth
252
+ signOut
421
253
  },
422
254
  children
423
255
  }
424
- );
425
- };
256
+ ) }) });
257
+ }
426
258
 
427
259
  // src/constants/auth.error.codes.ts
428
260
  var AUTH_ERROR_MAPPING = {
@@ -474,57 +306,181 @@ var AUTH_ERROR_MAPPING = {
474
306
  var validCodes = Object.keys(AUTH_ERROR_MAPPING);
475
307
 
476
308
  // src/utils/handle-error.ts
477
- var handleError = (err, setError, t) => {
478
- if (err instanceof AuthError) {
479
- let errorCode = "";
480
- if (err.code && validCodes.includes(err.code)) {
481
- errorCode = err.code;
482
- } else if (err.message) {
483
- const messageUpper = err.message.toUpperCase().trim();
484
- if (validCodes.includes(messageUpper)) {
485
- errorCode = messageUpper;
486
- }
487
- }
488
- if (errorCode && AUTH_ERROR_MAPPING[errorCode]) {
489
- const mapping = AUTH_ERROR_MAPPING[errorCode];
490
- setError({
491
- title: mapping.title,
492
- description: mapping.description
493
- });
494
- return;
309
+ function isAuthError(err) {
310
+ return typeof err === "object" && err !== null && "message" in err && typeof err.message === "string";
311
+ }
312
+ function extractErrorCode(err) {
313
+ if (err.code && validCodes.includes(err.code)) {
314
+ return err.code;
315
+ }
316
+ if (err.message) {
317
+ const messageUpper = err.message.toUpperCase().trim();
318
+ if (validCodes.includes(messageUpper)) {
319
+ return messageUpper;
495
320
  }
321
+ }
322
+ return "";
323
+ }
324
+ function handleAuthError(err, setError, t) {
325
+ const errorCode = extractErrorCode(err);
326
+ if (errorCode && AUTH_ERROR_MAPPING[errorCode]) {
327
+ const mapping = AUTH_ERROR_MAPPING[errorCode];
496
328
  setError({
497
- title: t("errors.fallback"),
498
- // or 'Error'
499
- description: err.message || t("errors.fallback")
329
+ title: mapping.title,
330
+ description: mapping.description
500
331
  });
332
+ return;
333
+ }
334
+ setError({
335
+ title: t("errors.fallback"),
336
+ description: err.message || t("errors.fallback")
337
+ });
338
+ }
339
+ function handleGenericError(err, setError, t) {
340
+ const message = err instanceof Error ? err.message : t("errors.fallback");
341
+ setError({
342
+ title: "Error",
343
+ description: message
344
+ });
345
+ }
346
+ var handleError = (err, setError, t) => {
347
+ if (isAuthError(err)) {
348
+ handleAuthError(err, setError, t);
501
349
  } else {
502
- const message = err instanceof Error ? err.message : t("errors.fallback");
503
- setError({
504
- title: "Error",
505
- description: message
506
- });
350
+ handleGenericError(err, setError, t);
507
351
  }
508
352
  };
509
353
 
510
- // src/components/auth/pages/forgot-password-page.tsx
511
- import { jsx as jsx6 } from "react/jsx-runtime";
512
- var ForgotPasswordPage = ({
513
- onNavigate,
514
- linkComponent: Link,
515
- links,
354
+ // src/components/auth/auth-page-layout.tsx
355
+ import { jsx as jsx3, jsxs } from "react/jsx-runtime";
356
+ var AuthPageLayout = ({
357
+ title,
358
+ description,
359
+ children,
360
+ footer,
516
361
  logoImage
517
362
  }) => {
518
- const t = useTranslations3("Auth.forgotPassword");
519
- const { client } = useAuth();
520
- const [isLoading, setIsLoading] = useState3(false);
521
- const [error, setError] = useState3(null);
522
- const signInLink = links?.signIn || "/auth/sign-in";
363
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
364
+ /* @__PURE__ */ jsx3("div", { className: "flex size-8 mb-6 w-full items-center justify-center rounded-md", children: /* @__PURE__ */ jsx3("img", { src: logoImage || "", alt: "Mesob", width: 42, height: 42 }) }),
365
+ /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
366
+ /* @__PURE__ */ jsx3("h1", { className: "text-2xl font-bold tracking-tight", children: title }),
367
+ description && /* @__PURE__ */ jsx3("p", { className: "mt-2 text-sm text-muted-foreground", children: description })
368
+ ] }),
369
+ children,
370
+ /* @__PURE__ */ jsx3("div", { className: "mt-2 w-full", children: footer && /* @__PURE__ */ jsx3("div", { className: "w-full text-center text-sm text-muted-foreground", children: footer }) })
371
+ ] });
372
+ };
373
+
374
+ // src/components/auth/forgot-password.tsx
375
+ import { zodResolver } from "@hookform/resolvers/zod";
376
+ import { Button } from "@mesob/ui/components/button";
377
+ import {
378
+ Field,
379
+ FieldError,
380
+ FieldGroup,
381
+ FieldLabel
382
+ } from "@mesob/ui/components/field";
383
+ import { Input } from "@mesob/ui/components/input";
384
+ import { Spinner } from "@mesob/ui/components/spinner";
385
+ import { Controller, useForm } from "react-hook-form";
386
+ import { z } from "zod";
387
+
388
+ // src/hooks/use-translator.ts
389
+ function useTranslator(namespace) {
390
+ const { config } = useConfig();
391
+ return createTranslator(config.messages || {}, namespace);
392
+ }
393
+
394
+ // src/components/auth/forgot-password.tsx
395
+ import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
396
+ var forgotPasswordSchema = (t) => z.object({
397
+ account: z.string().min(1, t("errors.accountRequired"))
398
+ });
399
+ var ForgotPassword = ({
400
+ onSubmit,
401
+ isLoading = false
402
+ }) => {
403
+ const t = useTranslator("Auth.forgotPassword");
404
+ const form = useForm({
405
+ resolver: zodResolver(forgotPasswordSchema(t)),
406
+ defaultValues: {
407
+ account: ""
408
+ }
409
+ });
410
+ const handleSubmit = form.handleSubmit(async (values) => {
411
+ await onSubmit(values);
412
+ });
413
+ return /* @__PURE__ */ jsxs2("form", { id: "forgot-password-form", onSubmit: handleSubmit, children: [
414
+ /* @__PURE__ */ jsx4(FieldGroup, { children: /* @__PURE__ */ jsx4(
415
+ Controller,
416
+ {
417
+ name: "account",
418
+ control: form.control,
419
+ render: ({ field, fieldState }) => /* @__PURE__ */ jsxs2(Field, { "data-invalid": fieldState.invalid, children: [
420
+ /* @__PURE__ */ jsx4(FieldLabel, { htmlFor: "forgot-password-account", children: t("form.accountLabel") }),
421
+ /* @__PURE__ */ jsx4(
422
+ Input,
423
+ {
424
+ ...field,
425
+ id: "forgot-password-account",
426
+ type: "text",
427
+ placeholder: t("form.accountPlaceholder"),
428
+ "aria-invalid": fieldState.invalid
429
+ }
430
+ ),
431
+ fieldState.invalid && /* @__PURE__ */ jsx4(FieldError, { errors: [fieldState.error] })
432
+ ] })
433
+ }
434
+ ) }),
435
+ /* @__PURE__ */ jsx4("div", { className: "mt-4", children: /* @__PURE__ */ jsxs2(
436
+ Button,
437
+ {
438
+ type: "submit",
439
+ form: "forgot-password-form",
440
+ className: "w-full",
441
+ disabled: isLoading,
442
+ children: [
443
+ isLoading && /* @__PURE__ */ jsx4(Spinner, {}),
444
+ isLoading ? t("form.submitting") : t("form.submit")
445
+ ]
446
+ }
447
+ ) })
448
+ ] });
449
+ };
450
+
451
+ // src/components/auth/pages/forgot-password-page.tsx
452
+ import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
453
+ var ForgotPasswordPage = (_props = {}) => {
454
+ const { hooks } = useApi();
455
+ const { config } = useConfig();
456
+ const t = createTranslator(config.messages || {}, "Auth.forgotPassword");
457
+ const [isLoading, setIsLoading] = useState2(false);
458
+ const [error, setError] = useState2(null);
459
+ const forgotPasswordMutation = hooks.useMutation("post", "/password/forgot");
460
+ const signInLink = config.navigation?.links?.signIn || "/auth/sign-in";
461
+ const Link = config.navigation?.linkComponent;
462
+ const onNavigate = config.navigation?.onNavigate || ((path) => {
463
+ if (typeof window !== "undefined") {
464
+ window.location.href = path;
465
+ }
466
+ });
467
+ const logoImage = config.ui.logoImage;
468
+ useEffect2(() => {
469
+ if (error) {
470
+ toast.error(error.title || "Error", {
471
+ description: error.description
472
+ });
473
+ }
474
+ }, [error]);
523
475
  const handleSubmit = async (values) => {
524
476
  setIsLoading(true);
525
477
  setError(null);
526
478
  try {
527
- const res = await client.forgotPassword({ identifier: values.account });
479
+ const res = await forgotPasswordMutation.mutateAsync({
480
+ body: {
481
+ identifier: values.account
482
+ }
483
+ });
528
484
  if ("verificationId" in res && res.verificationId) {
529
485
  onNavigate(`/auth/reset-password?verificationId=${res.verificationId}`);
530
486
  } else {
@@ -541,14 +497,21 @@ var ForgotPasswordPage = ({
541
497
  const handleBack = () => {
542
498
  onNavigate(signInLink);
543
499
  };
544
- return /* @__PURE__ */ jsx6(
500
+ let errorContent = null;
501
+ if (error) {
502
+ if (typeof error === "string") {
503
+ errorContent = { title: "Error", description: error };
504
+ } else {
505
+ errorContent = error;
506
+ }
507
+ }
508
+ return /* @__PURE__ */ jsxs3(
545
509
  AuthPageLayout,
546
510
  {
547
511
  title: t("title"),
548
512
  description: t("description"),
549
- error,
550
513
  logoImage,
551
- footer: Link ? /* @__PURE__ */ jsx6(Link, { href: signInLink, className: "text-primary hover:underline", children: t("footer.backToSignIn") }) : /* @__PURE__ */ jsx6(
514
+ footer: Link ? /* @__PURE__ */ jsx5(Link, { href: signInLink, className: "text-primary hover:underline", children: t("footer.backToSignIn") }) : /* @__PURE__ */ jsx5(
552
515
  "a",
553
516
  {
554
517
  href: signInLink,
@@ -560,65 +523,72 @@ var ForgotPasswordPage = ({
560
523
  children: t("footer.backToSignIn")
561
524
  }
562
525
  ),
563
- children: /* @__PURE__ */ jsx6(
564
- ForgotPassword,
565
- {
566
- onSubmit: handleSubmit,
567
- isLoading,
568
- onBack: handleBack
569
- }
570
- )
526
+ children: [
527
+ /* @__PURE__ */ jsx5(
528
+ ForgotPassword,
529
+ {
530
+ onSubmit: handleSubmit,
531
+ isLoading: isLoading || forgotPasswordMutation.isPending,
532
+ onBack: handleBack
533
+ }
534
+ ),
535
+ errorContent && /* @__PURE__ */ jsxs3(Alert, { variant: "destructive", className: "mt-4", children: [
536
+ /* @__PURE__ */ jsx5(IconAlertCircle, { className: "h-4 w-4" }),
537
+ /* @__PURE__ */ jsx5(AlertTitle, { children: errorContent.title }),
538
+ /* @__PURE__ */ jsx5(AlertDescription, { children: errorContent.description })
539
+ ] })
540
+ ]
571
541
  }
572
542
  );
573
543
  };
574
544
 
575
545
  // src/components/auth/pages/reset-password-page.tsx
576
- import { useTranslations as useTranslations5 } from "next-intl";
577
- import { useState as useState5 } from "react";
546
+ import {
547
+ Alert as Alert2,
548
+ AlertDescription as AlertDescription2,
549
+ AlertTitle as AlertTitle2
550
+ } from "@mesob/ui/components/alert";
551
+ import { toast as toast2 } from "@mesob/ui/components/sonner";
552
+ import { IconAlertCircle as IconAlertCircle2 } from "@tabler/icons-react";
553
+ import { useEffect as useEffect3, useState as useState4 } from "react";
578
554
 
579
555
  // src/components/auth/reset-password-form.tsx
580
556
  import { zodResolver as zodResolver2 } from "@hookform/resolvers/zod";
581
- import { Button as Button3 } from "@mesob/ui/components/button";
557
+ import { Button as Button2 } from "@mesob/ui/components/button";
582
558
  import {
583
- Form as Form2,
584
- FormControl as FormControl2,
585
- FormField as FormField2,
586
- FormItem as FormItem2,
587
- FormLabel as FormLabel2,
588
- FormMessage as FormMessage2
589
- } from "@mesob/ui/components/form";
559
+ Field as Field2,
560
+ FieldError as FieldError2,
561
+ FieldGroup as FieldGroup2,
562
+ FieldLabel as FieldLabel2
563
+ } from "@mesob/ui/components/field";
590
564
  import { Input as Input2 } from "@mesob/ui/components/input";
591
565
  import {
592
566
  InputOTP,
593
567
  InputOTPGroup,
594
568
  InputOTPSlot
595
569
  } from "@mesob/ui/components/input-otp";
596
- import { Spinner as Spinner3 } from "@mesob/ui/components/spinner";
570
+ import { Spinner as Spinner2 } from "@mesob/ui/components/spinner";
597
571
  import { IconEye, IconEyeOff } from "@tabler/icons-react";
598
- import { useTranslations as useTranslations4 } from "next-intl";
599
- import { useMemo as useMemo2, useState as useState4 } from "react";
600
- import { useForm as useForm2 } from "react-hook-form";
572
+ import { useState as useState3 } from "react";
573
+ import { Controller as Controller2, useForm as useForm2 } from "react-hook-form";
601
574
  import { z as z2 } from "zod";
602
- import { jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
575
+ import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
576
+ var resetPasswordSchema = (t) => z2.object({
577
+ code: z2.string().length(6, t("errors.codeLength")),
578
+ password: z2.string().min(8, t("errors.passwordLength")),
579
+ confirmPassword: z2.string()
580
+ }).refine((data) => data.password === data.confirmPassword, {
581
+ message: t("errors.passwordsMismatch"),
582
+ path: ["confirmPassword"]
583
+ });
603
584
  var ResetPasswordForm = ({
604
585
  onSubmit,
605
586
  isLoading = false
606
587
  }) => {
607
- const t = useTranslations4("Auth.resetPassword");
608
- const [showPassword, setShowPassword] = useState4(false);
609
- const resetPasswordSchema = useMemo2(
610
- () => z2.object({
611
- code: z2.string().length(6, t("errors.codeLength")),
612
- password: z2.string().min(8, t("errors.passwordLength")),
613
- confirmPassword: z2.string()
614
- }).refine((data) => data.password === data.confirmPassword, {
615
- message: t("errors.passwordsMismatch"),
616
- path: ["confirmPassword"]
617
- }),
618
- [t]
619
- );
588
+ const t = useTranslator("Auth.resetPassword");
589
+ const [showPassword, setShowPassword] = useState3(false);
620
590
  const form = useForm2({
621
- resolver: zodResolver2(resetPasswordSchema),
591
+ resolver: zodResolver2(resetPasswordSchema(t)),
622
592
  defaultValues: {
623
593
  code: "",
624
594
  password: "",
@@ -628,110 +598,149 @@ var ResetPasswordForm = ({
628
598
  const handleSubmit = form.handleSubmit(async (values) => {
629
599
  await onSubmit(values);
630
600
  });
631
- return /* @__PURE__ */ jsx7(Form2, { ...form, children: /* @__PURE__ */ jsxs4("form", { onSubmit: handleSubmit, className: "space-y-4", children: [
632
- /* @__PURE__ */ jsx7(
633
- FormField2,
634
- {
635
- control: form.control,
636
- name: "code",
637
- render: ({ field }) => /* @__PURE__ */ jsxs4(FormItem2, { children: [
638
- /* @__PURE__ */ jsx7("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx7(FormLabel2, { children: t("form.codeLabel") }) }),
639
- /* @__PURE__ */ jsx7(FormControl2, { children: /* @__PURE__ */ jsx7("div", { className: "flex mt-2 justify-center", children: /* @__PURE__ */ jsx7(InputOTP, { maxLength: 6, ...field, containerClassName: "gap-4", children: /* @__PURE__ */ jsxs4(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: [
640
- /* @__PURE__ */ jsx7(InputOTPSlot, { className: "h-12", index: 0 }),
641
- /* @__PURE__ */ jsx7(InputOTPSlot, { className: "h-12", index: 1 }),
642
- /* @__PURE__ */ jsx7(InputOTPSlot, { className: "h-12", index: 2 }),
643
- /* @__PURE__ */ jsx7(InputOTPSlot, { className: "h-12", index: 3 }),
644
- /* @__PURE__ */ jsx7(InputOTPSlot, { className: "h-12", index: 4 }),
645
- /* @__PURE__ */ jsx7(InputOTPSlot, { className: "h-12", index: 5 })
646
- ] }) }) }) }),
647
- /* @__PURE__ */ jsx7(FormMessage2, {})
648
- ] })
649
- }
650
- ),
651
- /* @__PURE__ */ jsx7(
652
- FormField2,
653
- {
654
- control: form.control,
655
- name: "password",
656
- render: ({ field }) => /* @__PURE__ */ jsxs4(FormItem2, { children: [
657
- /* @__PURE__ */ jsx7(FormLabel2, { children: t("form.passwordLabel") }),
658
- /* @__PURE__ */ jsx7(FormControl2, { children: /* @__PURE__ */ jsxs4("div", { className: "relative", children: [
659
- /* @__PURE__ */ jsx7(
660
- Input2,
661
- {
662
- type: showPassword ? "text" : "password",
663
- placeholder: t("form.passwordPlaceholder"),
664
- ...field
665
- }
666
- ),
667
- /* @__PURE__ */ jsx7(
668
- "button",
601
+ return /* @__PURE__ */ jsxs4("form", { id: "reset-password-form", onSubmit: handleSubmit, children: [
602
+ /* @__PURE__ */ jsxs4(FieldGroup2, { children: [
603
+ /* @__PURE__ */ jsx6(
604
+ Controller2,
605
+ {
606
+ name: "code",
607
+ control: form.control,
608
+ render: ({ field, fieldState }) => /* @__PURE__ */ jsxs4(Field2, { "data-invalid": fieldState.invalid, children: [
609
+ /* @__PURE__ */ jsx6("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx6(FieldLabel2, { children: t("form.codeLabel") }) }),
610
+ /* @__PURE__ */ jsx6("div", { className: "flex mt-2 justify-center", children: /* @__PURE__ */ jsx6(
611
+ InputOTP,
669
612
  {
670
- type: "button",
671
- onClick: () => setShowPassword(!showPassword),
672
- className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground",
673
- children: showPassword ? /* @__PURE__ */ jsx7(IconEyeOff, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx7(IconEye, { className: "h-4 w-4" })
613
+ maxLength: 6,
614
+ value: field.value,
615
+ onChange: field.onChange,
616
+ onBlur: field.onBlur,
617
+ containerClassName: "gap-4",
618
+ "aria-invalid": fieldState.invalid,
619
+ children: /* @__PURE__ */ jsxs4(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: [
620
+ /* @__PURE__ */ jsx6(InputOTPSlot, { className: "h-12", index: 0 }),
621
+ /* @__PURE__ */ jsx6(InputOTPSlot, { className: "h-12", index: 1 }),
622
+ /* @__PURE__ */ jsx6(InputOTPSlot, { className: "h-12", index: 2 }),
623
+ /* @__PURE__ */ jsx6(InputOTPSlot, { className: "h-12", index: 3 }),
624
+ /* @__PURE__ */ jsx6(InputOTPSlot, { className: "h-12", index: 4 }),
625
+ /* @__PURE__ */ jsx6(InputOTPSlot, { className: "h-12", index: 5 })
626
+ ] })
674
627
  }
675
- )
676
- ] }) }),
677
- /* @__PURE__ */ jsx7(FormMessage2, {})
678
- ] })
679
- }
680
- ),
681
- /* @__PURE__ */ jsx7(
682
- FormField2,
628
+ ) }),
629
+ fieldState.invalid && /* @__PURE__ */ jsx6(FieldError2, { errors: [fieldState.error] })
630
+ ] })
631
+ }
632
+ ),
633
+ /* @__PURE__ */ jsx6(
634
+ Controller2,
635
+ {
636
+ name: "password",
637
+ control: form.control,
638
+ render: ({ field, fieldState }) => /* @__PURE__ */ jsxs4(Field2, { "data-invalid": fieldState.invalid, children: [
639
+ /* @__PURE__ */ jsx6(FieldLabel2, { htmlFor: "reset-password-password", children: t("form.passwordLabel") }),
640
+ /* @__PURE__ */ jsxs4("div", { className: "relative", children: [
641
+ /* @__PURE__ */ jsx6(
642
+ Input2,
643
+ {
644
+ ...field,
645
+ id: "reset-password-password",
646
+ type: showPassword ? "text" : "password",
647
+ placeholder: t("form.passwordPlaceholder"),
648
+ "aria-invalid": fieldState.invalid
649
+ }
650
+ ),
651
+ /* @__PURE__ */ jsx6(
652
+ "button",
653
+ {
654
+ type: "button",
655
+ onClick: () => setShowPassword(!showPassword),
656
+ className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground",
657
+ children: showPassword ? /* @__PURE__ */ jsx6(IconEyeOff, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx6(IconEye, { className: "h-4 w-4" })
658
+ }
659
+ )
660
+ ] }),
661
+ fieldState.invalid && /* @__PURE__ */ jsx6(FieldError2, { errors: [fieldState.error] })
662
+ ] })
663
+ }
664
+ ),
665
+ /* @__PURE__ */ jsx6(
666
+ Controller2,
667
+ {
668
+ name: "confirmPassword",
669
+ control: form.control,
670
+ render: ({ field, fieldState }) => /* @__PURE__ */ jsxs4(Field2, { "data-invalid": fieldState.invalid, children: [
671
+ /* @__PURE__ */ jsx6(FieldLabel2, { htmlFor: "reset-password-confirmPassword", children: t("form.confirmPasswordLabel") }),
672
+ /* @__PURE__ */ jsxs4("div", { className: "relative", children: [
673
+ /* @__PURE__ */ jsx6(
674
+ Input2,
675
+ {
676
+ ...field,
677
+ id: "reset-password-confirmPassword",
678
+ type: showPassword ? "text" : "password",
679
+ placeholder: t("form.passwordPlaceholder"),
680
+ "aria-invalid": fieldState.invalid
681
+ }
682
+ ),
683
+ /* @__PURE__ */ jsx6(
684
+ "button",
685
+ {
686
+ type: "button",
687
+ onClick: () => setShowPassword(!showPassword),
688
+ className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground",
689
+ children: showPassword ? /* @__PURE__ */ jsx6(IconEyeOff, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx6(IconEye, { className: "h-4 w-4" })
690
+ }
691
+ )
692
+ ] }),
693
+ fieldState.invalid && /* @__PURE__ */ jsx6(FieldError2, { errors: [fieldState.error] })
694
+ ] })
695
+ }
696
+ )
697
+ ] }),
698
+ /* @__PURE__ */ jsx6("div", { className: "mt-4", children: /* @__PURE__ */ jsxs4(
699
+ Button2,
683
700
  {
684
- control: form.control,
685
- name: "confirmPassword",
686
- render: ({ field }) => /* @__PURE__ */ jsxs4(FormItem2, { children: [
687
- /* @__PURE__ */ jsx7(FormLabel2, { children: t("form.confirmPasswordLabel") }),
688
- /* @__PURE__ */ jsx7(FormControl2, { children: /* @__PURE__ */ jsxs4("div", { className: "relative", children: [
689
- /* @__PURE__ */ jsx7(
690
- Input2,
691
- {
692
- type: showPassword ? "text" : "password",
693
- placeholder: t("form.passwordPlaceholder"),
694
- ...field
695
- }
696
- ),
697
- /* @__PURE__ */ jsx7(
698
- "button",
699
- {
700
- type: "button",
701
- onClick: () => setShowPassword(!showPassword),
702
- className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground",
703
- children: showPassword ? /* @__PURE__ */ jsx7(IconEyeOff, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx7(IconEye, { className: "h-4 w-4" })
704
- }
705
- )
706
- ] }) }),
707
- /* @__PURE__ */ jsx7(FormMessage2, {})
708
- ] })
701
+ type: "submit",
702
+ form: "reset-password-form",
703
+ className: "w-full",
704
+ disabled: isLoading,
705
+ children: [
706
+ isLoading && /* @__PURE__ */ jsx6(Spinner2, {}),
707
+ isLoading ? t("form.submitting") : t("form.submit")
708
+ ]
709
709
  }
710
- ),
711
- /* @__PURE__ */ jsxs4(Button3, { type: "submit", className: "w-full", disabled: isLoading, children: [
712
- isLoading && /* @__PURE__ */ jsx7(Spinner3, {}),
713
- isLoading ? t("form.submitting") : t("form.submit")
714
- ] })
715
- ] }) });
710
+ ) })
711
+ ] });
716
712
  };
717
713
 
718
714
  // src/components/auth/pages/reset-password-page.tsx
719
- import { jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
715
+ import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
720
716
  var ResetPasswordPage = ({
721
717
  verificationId,
722
- onNavigate,
723
- linkComponent: Link,
724
- links,
725
- logoImage,
726
718
  redirectUrl
727
719
  }) => {
728
- const t = useTranslations5("Auth.resetPassword");
729
- const common = useTranslations5("Common");
730
- const { client, refresh } = useAuth();
731
- const [isLoading, setIsLoading] = useState5(false);
732
- const [error, setError] = useState5(null);
733
- const signInLink = links?.signIn || "/auth/sign-in";
734
- const forgotPasswordLink = links?.forgotPassword || "/auth/forgot-password";
720
+ const { hooks, refresh } = useApi();
721
+ const { config } = useConfig();
722
+ const t = createTranslator(config.messages || {}, "Auth.resetPassword");
723
+ const common = createTranslator(config.messages || {}, "Common");
724
+ const [isLoading, setIsLoading] = useState4(false);
725
+ const [error, setError] = useState4(null);
726
+ const resetPasswordMutation = hooks.useMutation("post", "/password/reset");
727
+ const signInLink = config.navigation?.links?.signIn || "/auth/sign-in";
728
+ const forgotPasswordLink = config.navigation?.links?.forgotPassword || "/auth/forgot-password";
729
+ const Link = config.navigation?.linkComponent;
730
+ const onNavigate = config.navigation?.onNavigate || ((path) => {
731
+ if (typeof window !== "undefined") {
732
+ window.location.href = path;
733
+ }
734
+ });
735
+ const logoImage = config.ui.logoImage;
736
+ const defaultRedirect = redirectUrl || config.navigation?.defaultRedirectUrl || "/";
737
+ useEffect3(() => {
738
+ if (error) {
739
+ toast2.error(error.title || "Error", {
740
+ description: error.description
741
+ });
742
+ }
743
+ }, [error]);
735
744
  const handleSubmit = async (values) => {
736
745
  if (!verificationId) {
737
746
  setError({
@@ -743,13 +752,15 @@ var ResetPasswordPage = ({
743
752
  setIsLoading(true);
744
753
  setError(null);
745
754
  try {
746
- await client.resetPassword({
747
- verificationId,
748
- code: values.code,
749
- password: values.password
755
+ await resetPasswordMutation.mutateAsync({
756
+ body: {
757
+ verificationId,
758
+ code: values.code,
759
+ password: values.password
760
+ }
750
761
  });
751
762
  await refresh();
752
- onNavigate(redirectUrl || "/");
763
+ onNavigate(defaultRedirect);
753
764
  } catch (err) {
754
765
  handleError(err, setError, t);
755
766
  } finally {
@@ -757,20 +768,20 @@ var ResetPasswordPage = ({
757
768
  }
758
769
  };
759
770
  if (!verificationId) {
760
- return /* @__PURE__ */ jsx8(
771
+ return /* @__PURE__ */ jsx7(
761
772
  AuthPageLayout,
762
773
  {
763
774
  title: common("invalidLinkTitle"),
764
775
  description: common("invalidLinkDescription"),
765
776
  logoImage,
766
- footer: Link ? /* @__PURE__ */ jsx8(
777
+ footer: Link ? /* @__PURE__ */ jsx7(
767
778
  Link,
768
779
  {
769
780
  href: forgotPasswordLink,
770
781
  className: "text-primary hover:underline",
771
782
  children: t("footer.requestNew")
772
783
  }
773
- ) : /* @__PURE__ */ jsx8(
784
+ ) : /* @__PURE__ */ jsx7(
774
785
  "a",
775
786
  {
776
787
  href: forgotPasswordLink,
@@ -782,20 +793,27 @@ var ResetPasswordPage = ({
782
793
  children: t("footer.requestNew")
783
794
  }
784
795
  ),
785
- children: /* @__PURE__ */ jsx8("div", {})
796
+ children: /* @__PURE__ */ jsx7("div", {})
786
797
  }
787
798
  );
788
799
  }
789
- return /* @__PURE__ */ jsx8(
800
+ let errorContent = null;
801
+ if (error) {
802
+ if (typeof error === "string") {
803
+ errorContent = { title: "Error", description: error };
804
+ } else {
805
+ errorContent = error;
806
+ }
807
+ }
808
+ return /* @__PURE__ */ jsxs5(
790
809
  AuthPageLayout,
791
810
  {
792
811
  title: t("title"),
793
812
  description: t("description"),
794
- error,
795
813
  logoImage,
796
814
  footer: Link ? /* @__PURE__ */ jsxs5("div", { className: "flex items-center justify-between w-full gap-2", children: [
797
- /* @__PURE__ */ jsx8(Link, { href: signInLink, className: "text-primary hover:underline", children: t("footer.backToSignIn") }),
798
- /* @__PURE__ */ jsx8(
815
+ /* @__PURE__ */ jsx7(Link, { href: signInLink, className: "text-primary hover:underline", children: t("footer.backToSignIn") }),
816
+ /* @__PURE__ */ jsx7(
799
817
  Link,
800
818
  {
801
819
  href: forgotPasswordLink,
@@ -804,7 +822,7 @@ var ResetPasswordPage = ({
804
822
  }
805
823
  )
806
824
  ] }) : /* @__PURE__ */ jsxs5("div", { className: "flex items-center justify-between w-full gap-2", children: [
807
- /* @__PURE__ */ jsx8(
825
+ /* @__PURE__ */ jsx7(
808
826
  "a",
809
827
  {
810
828
  href: forgotPasswordLink,
@@ -816,7 +834,7 @@ var ResetPasswordPage = ({
816
834
  children: t("footer.backToSignIn")
817
835
  }
818
836
  ),
819
- /* @__PURE__ */ jsx8(
837
+ /* @__PURE__ */ jsx7(
820
838
  "a",
821
839
  {
822
840
  href: forgotPasswordLink,
@@ -829,40 +847,50 @@ var ResetPasswordPage = ({
829
847
  }
830
848
  )
831
849
  ] }),
832
- children: /* @__PURE__ */ jsx8(
833
- ResetPasswordForm,
834
- {
835
- verificationId,
836
- onSubmit: handleSubmit,
837
- isLoading,
838
- error
839
- }
840
- )
850
+ children: [
851
+ /* @__PURE__ */ jsx7(
852
+ ResetPasswordForm,
853
+ {
854
+ verificationId,
855
+ onSubmit: handleSubmit,
856
+ isLoading: isLoading || resetPasswordMutation.isPending,
857
+ error
858
+ }
859
+ ),
860
+ errorContent && /* @__PURE__ */ jsxs5(Alert2, { variant: "destructive", className: "mt-4", children: [
861
+ /* @__PURE__ */ jsx7(IconAlertCircle2, { className: "h-4 w-4" }),
862
+ /* @__PURE__ */ jsx7(AlertTitle2, { children: errorContent.title }),
863
+ /* @__PURE__ */ jsx7(AlertDescription2, { children: errorContent.description })
864
+ ] })
865
+ ]
841
866
  }
842
867
  );
843
868
  };
844
869
 
845
870
  // src/components/auth/pages/sign-in-page.tsx
846
- import { useTranslations as useTranslations7 } from "next-intl";
847
- import { useState as useState7 } from "react";
871
+ import {
872
+ Alert as Alert3,
873
+ AlertDescription as AlertDescription3,
874
+ AlertTitle as AlertTitle3
875
+ } from "@mesob/ui/components/alert";
876
+ import { toast as toast3 } from "@mesob/ui/components/sonner";
877
+ import { IconAlertCircle as IconAlertCircle3 } from "@tabler/icons-react";
878
+ import { useEffect as useEffect5, useState as useState6 } from "react";
848
879
 
849
880
  // src/components/auth/sign-in.tsx
850
881
  import { zodResolver as zodResolver3 } from "@hookform/resolvers/zod";
851
- import { Button as Button4 } from "@mesob/ui/components/button";
882
+ import { Button as Button3 } from "@mesob/ui/components/button";
852
883
  import {
853
- Form as Form3,
854
- FormControl as FormControl3,
855
- FormField as FormField3,
856
- FormItem as FormItem3,
857
- FormLabel as FormLabel3,
858
- FormMessage as FormMessage3
859
- } from "@mesob/ui/components/form";
884
+ Field as Field3,
885
+ FieldError as FieldError3,
886
+ FieldGroup as FieldGroup3,
887
+ FieldLabel as FieldLabel3
888
+ } from "@mesob/ui/components/field";
860
889
  import { Input as Input3 } from "@mesob/ui/components/input";
861
- import { Spinner as Spinner4 } from "@mesob/ui/components/spinner";
890
+ import { Spinner as Spinner3 } from "@mesob/ui/components/spinner";
862
891
  import { IconEye as IconEye2, IconEyeOff as IconEyeOff2 } from "@tabler/icons-react";
863
- import { useTranslations as useTranslations6 } from "next-intl";
864
- import { useMemo as useMemo3, useState as useState6 } from "react";
865
- import { useForm as useForm3 } from "react-hook-form";
892
+ import { useEffect as useEffect4, useState as useState5 } from "react";
893
+ import { Controller as Controller3, useForm as useForm3 } from "react-hook-form";
866
894
  import { z as z3 } from "zod";
867
895
 
868
896
  // src/utils/normalize-phone.ts
@@ -884,183 +912,256 @@ function normalizePhone(phone) {
884
912
  }
885
913
 
886
914
  // src/components/auth/sign-in.tsx
887
- import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
915
+ import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
916
+ var identifierSchema = (t) => z3.object({
917
+ identifier: z3.string().trim().min(1, { message: t("errors.requiredField") }).refine(
918
+ (val) => {
919
+ const isEmail = z3.email().safeParse(val).success;
920
+ const phoneRegex = /^(\+2519|2519|09)\d{8}$/;
921
+ const isPhone4 = phoneRegex.test(val);
922
+ return isEmail || isPhone4;
923
+ },
924
+ {
925
+ message: t("errors.invalidEmailOrPhone")
926
+ }
927
+ )
928
+ });
929
+ var passwordSchema = (t) => z3.object({
930
+ password: z3.string().min(8, t("errors.passwordLength")).max(128, t("errors.longPasswordError"))
931
+ });
888
932
  var SignIn = ({
889
933
  onSubmit,
890
934
  isLoading = false,
891
- identifier = "",
935
+ identifier: initialIdentifier = "",
892
936
  step = "identifier",
893
937
  onBack: _onBack
894
938
  }) => {
895
- const t = useTranslations6("Auth.signIn");
896
- const [showPassword, setShowPassword] = useState6(false);
897
- const identifierSchema = useMemo3(
898
- () => z3.object({
899
- account: z3.string().trim().min(1, { message: t("errors.requiredField") }).refine(
900
- (val) => {
901
- const isEmail = z3.string().email().safeParse(val).success;
902
- const phoneRegex = /^(\+2519|2519|09)\d{8}$/;
903
- const isPhone4 = phoneRegex.test(val);
904
- return isEmail || isPhone4;
905
- },
906
- {
907
- message: t("errors.invalidEmailOrPhone")
908
- }
909
- )
910
- }),
911
- [t]
912
- );
913
- const passwordSchema = useMemo3(
914
- () => z3.object({
915
- password: z3.string().min(8, t("errors.passwordLength")).max(128, t("errors.longPasswordError"))
916
- }),
917
- [t]
918
- );
939
+ const { hooks } = useApi();
940
+ const t = useTranslator("Auth.signIn");
941
+ const [showPassword, setShowPassword] = useState5(false);
942
+ const [currentIdentifier, setCurrentIdentifier] = useState5(initialIdentifier);
919
943
  const identifierForm = useForm3({
920
- resolver: zodResolver3(identifierSchema),
944
+ resolver: zodResolver3(identifierSchema(t)),
921
945
  defaultValues: {
922
- account: identifier
923
- }
946
+ identifier: initialIdentifier
947
+ },
948
+ mode: "onChange"
924
949
  });
925
950
  const passwordForm = useForm3({
926
- resolver: zodResolver3(passwordSchema),
951
+ resolver: zodResolver3(passwordSchema(t)),
927
952
  defaultValues: {
928
953
  password: ""
929
- }
954
+ },
955
+ mode: "onChange"
930
956
  });
931
- const handleIdentifierSubmit = identifierForm.handleSubmit(async (values) => {
957
+ const signInMutation = hooks.useMutation("post", "/sign-in");
958
+ useEffect4(() => {
959
+ if (initialIdentifier) {
960
+ identifierForm.setValue("identifier", initialIdentifier);
961
+ setCurrentIdentifier(initialIdentifier);
962
+ }
963
+ }, [initialIdentifier, identifierForm]);
964
+ const handleIdentifierSubmit = async (values) => {
932
965
  const phoneRegex = /^(\+2519|2519|09)\d{8}$/;
933
- const normalizedAccount = phoneRegex.test(values.account) ? normalizePhone(values.account) : values.account;
934
- await onSubmit({ account: normalizedAccount, password: "" }, "identifier");
935
- });
936
- const handlePasswordSubmit = passwordForm.handleSubmit(async (values) => {
966
+ const normalizedIdentifier = phoneRegex.test(values.identifier) ? normalizePhone(values.identifier) : values.identifier;
967
+ setCurrentIdentifier(normalizedIdentifier);
968
+ identifierForm.setValue("identifier", normalizedIdentifier);
937
969
  await onSubmit(
938
- { account: identifier, password: values.password },
939
- "password"
970
+ { identifier: normalizedIdentifier, password: "" },
971
+ "identifier"
940
972
  );
941
- });
942
- if (step === "password") {
943
- return /* @__PURE__ */ jsx9(Form3, { ...passwordForm, children: /* @__PURE__ */ jsxs6("form", { onSubmit: handlePasswordSubmit, className: "space-y-4", children: [
944
- /* @__PURE__ */ jsxs6("div", { className: "text-center", children: [
945
- /* @__PURE__ */ jsx9("p", { className: "text-sm text-muted-foreground mb-2", children: t("form.enterPasswordFor") }),
946
- /* @__PURE__ */ jsx9("p", { className: "font-bold", children: identifier })
947
- ] }),
948
- /* @__PURE__ */ jsx9(
949
- FormField3,
973
+ };
974
+ const handlePasswordSubmit = async (values) => {
975
+ try {
976
+ await signInMutation.mutateAsync({
977
+ body: {
978
+ identifier: currentIdentifier || identifierForm.getValues("identifier"),
979
+ password: values.password
980
+ }
981
+ });
982
+ await onSubmit(
950
983
  {
951
- control: passwordForm.control,
952
- name: "password",
953
- render: ({ field }) => /* @__PURE__ */ jsxs6(FormItem3, { children: [
954
- /* @__PURE__ */ jsx9(FormLabel3, { children: t("form.passwordLabel") }),
955
- /* @__PURE__ */ jsx9(FormControl3, { children: /* @__PURE__ */ jsxs6("div", { className: "relative", children: [
956
- /* @__PURE__ */ jsx9(
984
+ identifier: currentIdentifier || identifierForm.getValues("identifier"),
985
+ password: values.password
986
+ },
987
+ "password"
988
+ );
989
+ } catch {
990
+ await onSubmit(
991
+ {
992
+ identifier: currentIdentifier || identifierForm.getValues("identifier"),
993
+ password: values.password
994
+ },
995
+ "password"
996
+ );
997
+ }
998
+ };
999
+ const isPasswordStep = step === "password";
1000
+ const isSubmitting = isLoading || signInMutation.isPending;
1001
+ if (isPasswordStep) {
1002
+ return /* @__PURE__ */ jsxs6(
1003
+ "form",
1004
+ {
1005
+ id: "sign-in-password-form",
1006
+ onSubmit: passwordForm.handleSubmit(handlePasswordSubmit),
1007
+ children: [
1008
+ /* @__PURE__ */ jsxs6(FieldGroup3, { children: [
1009
+ /* @__PURE__ */ jsxs6("div", { className: "text-center", children: [
1010
+ /* @__PURE__ */ jsx8("p", { className: "text-sm text-muted-foreground mb-2", children: t("form.enterPasswordFor") }),
1011
+ /* @__PURE__ */ jsx8("p", { className: "font-bold", children: currentIdentifier || identifierForm.getValues("identifier") })
1012
+ ] }),
1013
+ /* @__PURE__ */ jsx8(
1014
+ Controller3,
1015
+ {
1016
+ name: "password",
1017
+ control: passwordForm.control,
1018
+ render: ({ field, fieldState }) => /* @__PURE__ */ jsxs6(Field3, { "data-invalid": fieldState.invalid, children: [
1019
+ /* @__PURE__ */ jsx8(FieldLabel3, { htmlFor: "sign-in-password", children: t("form.passwordLabel") }),
1020
+ /* @__PURE__ */ jsxs6("div", { className: "relative", children: [
1021
+ /* @__PURE__ */ jsx8(
1022
+ Input3,
1023
+ {
1024
+ ...field,
1025
+ id: "sign-in-password",
1026
+ type: showPassword ? "text" : "password",
1027
+ placeholder: t("form.passwordPlaceholder"),
1028
+ autoComplete: "current-password",
1029
+ "aria-invalid": fieldState.invalid
1030
+ }
1031
+ ),
1032
+ /* @__PURE__ */ jsx8(
1033
+ "button",
1034
+ {
1035
+ type: "button",
1036
+ onClick: () => setShowPassword(!showPassword),
1037
+ className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground",
1038
+ children: showPassword ? /* @__PURE__ */ jsx8(IconEyeOff2, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx8(IconEye2, { className: "h-4 w-4" })
1039
+ }
1040
+ )
1041
+ ] }),
1042
+ fieldState.invalid && /* @__PURE__ */ jsx8(FieldError3, { errors: [fieldState.error] })
1043
+ ] })
1044
+ }
1045
+ )
1046
+ ] }),
1047
+ /* @__PURE__ */ jsx8("div", { className: "mt-4", children: /* @__PURE__ */ jsxs6(Button3, { type: "submit", className: "w-full", disabled: isSubmitting, children: [
1048
+ isSubmitting && /* @__PURE__ */ jsx8(Spinner3, {}),
1049
+ isSubmitting ? t("form.submitting") : t("form.submit")
1050
+ ] }) })
1051
+ ]
1052
+ }
1053
+ );
1054
+ }
1055
+ return /* @__PURE__ */ jsxs6(
1056
+ "form",
1057
+ {
1058
+ id: "sign-in-identifier-form",
1059
+ onSubmit: identifierForm.handleSubmit(handleIdentifierSubmit),
1060
+ children: [
1061
+ /* @__PURE__ */ jsx8(FieldGroup3, { children: /* @__PURE__ */ jsx8(
1062
+ Controller3,
1063
+ {
1064
+ name: "identifier",
1065
+ control: identifierForm.control,
1066
+ render: ({ field, fieldState }) => /* @__PURE__ */ jsxs6(Field3, { "data-invalid": fieldState.invalid, children: [
1067
+ /* @__PURE__ */ jsx8(FieldLabel3, { htmlFor: "sign-in-identifier", children: t("form.accountLabel") }),
1068
+ /* @__PURE__ */ jsx8(
957
1069
  Input3,
958
1070
  {
959
- type: showPassword ? "text" : "password",
960
- placeholder: t("form.passwordPlaceholder"),
961
- autoComplete: "current-password",
962
- ...field
1071
+ ...field,
1072
+ id: "sign-in-identifier",
1073
+ type: "text",
1074
+ placeholder: t("form.accountPlaceholder"),
1075
+ autoComplete: "username",
1076
+ "aria-invalid": fieldState.invalid
963
1077
  }
964
1078
  ),
965
- /* @__PURE__ */ jsx9(
966
- "button",
967
- {
968
- type: "button",
969
- onClick: () => setShowPassword(!showPassword),
970
- className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground",
971
- children: showPassword ? /* @__PURE__ */ jsx9(IconEyeOff2, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx9(IconEye2, { className: "h-4 w-4" })
972
- }
973
- )
974
- ] }) }),
975
- /* @__PURE__ */ jsx9(FormMessage3, {})
976
- ] })
977
- }
978
- ),
979
- /* @__PURE__ */ jsx9(Button4, { type: "submit", className: "w-full", disabled: isLoading, children: isLoading ? t("form.submitting") : t("form.submit") })
980
- ] }) });
981
- }
982
- return /* @__PURE__ */ jsx9(Form3, { ...identifierForm, children: /* @__PURE__ */ jsxs6("form", { onSubmit: handleIdentifierSubmit, className: "space-y-4", children: [
983
- /* @__PURE__ */ jsx9(
984
- FormField3,
985
- {
986
- control: identifierForm.control,
987
- name: "account",
988
- render: ({ field }) => /* @__PURE__ */ jsxs6(FormItem3, { children: [
989
- /* @__PURE__ */ jsx9(FormLabel3, { children: t("form.accountLabel") }),
990
- /* @__PURE__ */ jsx9(FormControl3, { children: /* @__PURE__ */ jsx9(
991
- Input3,
992
- {
993
- type: "text",
994
- placeholder: t("form.accountPlaceholder"),
995
- ...field
996
- }
997
- ) }),
998
- /* @__PURE__ */ jsx9(FormMessage3, {})
999
- ] })
1000
- }
1001
- ),
1002
- /* @__PURE__ */ jsxs6(Button4, { type: "submit", className: "w-full", disabled: isLoading, children: [
1003
- isLoading && /* @__PURE__ */ jsx9(Spinner4, {}),
1004
- isLoading ? t("form.submitting") : t("form.continue")
1005
- ] })
1006
- ] }) });
1079
+ fieldState.invalid && /* @__PURE__ */ jsx8(FieldError3, { errors: [fieldState.error] })
1080
+ ] })
1081
+ }
1082
+ ) }),
1083
+ /* @__PURE__ */ jsx8("div", { className: "mt-4", children: /* @__PURE__ */ jsxs6(Button3, { type: "submit", className: "w-full", disabled: isSubmitting, children: [
1084
+ isSubmitting && /* @__PURE__ */ jsx8(Spinner3, {}),
1085
+ isSubmitting ? t("form.submitting") : t("form.continue")
1086
+ ] }) })
1087
+ ]
1088
+ }
1089
+ );
1007
1090
  };
1008
1091
 
1009
1092
  // src/components/auth/pages/sign-in-page.tsx
1010
- import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
1093
+ import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
1011
1094
  var isPhone = (s) => /^\+?[0-9()[\]\s-]{6,}$/.test(s);
1012
- var SignInPage = ({
1013
- redirectUrl,
1014
- onNavigate,
1015
- linkComponent: Link,
1016
- links,
1017
- logoImage
1018
- }) => {
1019
- const t = useTranslations7("Auth.signIn");
1020
- const { client, setAuth } = useAuth();
1021
- const [isLoading, setIsLoading] = useState7(false);
1022
- const [error, setError] = useState7(null);
1023
- const [step, setStep] = useState7("identifier");
1024
- const [identifier, setIdentifier] = useState7("");
1025
- const defaultRedirect = redirectUrl || "/dashboard";
1026
- const forgotPasswordLink = links?.forgotPassword || "/auth/forgot-password";
1027
- const signUpLink = links?.signUp || "/auth/sign-up";
1095
+ var SignInPage = ({ redirectUrl } = {}) => {
1096
+ const { hooks, setAuth } = useApi();
1097
+ const { config } = useConfig();
1098
+ const t = createTranslator(config.messages || {}, "Auth.signIn");
1099
+ const [isLoading, setIsLoading] = useState6(false);
1100
+ const [error, setError] = useState6(null);
1101
+ const [step, setStep] = useState6("identifier");
1102
+ const [identifier, setIdentifier] = useState6("");
1103
+ const checkUserMutation = hooks.useMutation("post", "/check-user");
1104
+ const signInMutation = hooks.useMutation("post", "/sign-in");
1105
+ const defaultRedirect = redirectUrl || config.navigation?.defaultRedirectUrl || "/dashboard";
1106
+ const forgotPasswordLink = config.navigation?.links?.forgotPassword || "/auth/forgot-password";
1107
+ const signUpLink = config.navigation?.links?.signUp || "/auth/sign-up";
1108
+ const Link = config.navigation?.linkComponent;
1109
+ const onNavigate = config.navigation?.onNavigate || ((path) => {
1110
+ if (typeof window !== "undefined") {
1111
+ window.location.href = path;
1112
+ }
1113
+ });
1114
+ const logoImage = config.ui.logoImage;
1115
+ useEffect5(() => {
1116
+ if (error) {
1117
+ toast3.error(error.title || "Error", {
1118
+ description: error.description
1119
+ });
1120
+ }
1121
+ }, [error]);
1122
+ const handleIdentifierStep = async (identifierValue) => {
1123
+ const checkResult = await checkUserMutation.mutateAsync({
1124
+ body: {
1125
+ identifier: identifierValue
1126
+ }
1127
+ });
1128
+ if (checkResult.exists) {
1129
+ setIdentifier(identifierValue);
1130
+ setStep("password");
1131
+ return;
1132
+ }
1133
+ const email = isPhone(identifierValue) ? "" : identifierValue;
1134
+ if (email) {
1135
+ onNavigate(`${signUpLink}?email=${encodeURIComponent(email)}`);
1136
+ } else {
1137
+ onNavigate(`${signUpLink}?phone=${encodeURIComponent(identifierValue)}`);
1138
+ }
1139
+ };
1140
+ const handlePasswordStep = async (passwordValue) => {
1141
+ const res = await signInMutation.mutateAsync({
1142
+ body: {
1143
+ identifier,
1144
+ password: passwordValue
1145
+ }
1146
+ });
1147
+ if ("verificationId" in res && res.verificationId) {
1148
+ const verifyPath = isPhone(identifier) ? `/auth/verify-phone?context=sign-in&verificationId=${res.verificationId}&identifier=${encodeURIComponent(identifier)}` : `/auth/verify-email?verificationId=${res.verificationId}`;
1149
+ onNavigate(verifyPath);
1150
+ return;
1151
+ }
1152
+ if ("user" in res && "session" in res) {
1153
+ setAuth(res);
1154
+ }
1155
+ onNavigate(defaultRedirect);
1156
+ };
1028
1157
  const handleSubmit = async (values, currentStep) => {
1029
1158
  setIsLoading(true);
1030
1159
  setError(null);
1031
1160
  try {
1032
1161
  if (currentStep === "identifier") {
1033
- const checkResult = await client.checkUser({
1034
- identifier: values.account
1035
- });
1036
- if (checkResult.exists) {
1037
- setIdentifier(values.account);
1038
- setStep("password");
1039
- } else {
1040
- const email = isPhone(values.account) ? "" : values.account;
1041
- if (email) {
1042
- onNavigate(`${signUpLink}?email=${encodeURIComponent(email)}`);
1043
- } else {
1044
- onNavigate(
1045
- `${signUpLink}?phone=${encodeURIComponent(values.account)}`
1046
- );
1047
- }
1048
- return;
1049
- }
1162
+ await handleIdentifierStep(values.identifier);
1050
1163
  } else {
1051
- const res = await client.signInWithPassword({
1052
- identifier,
1053
- password: values.password
1054
- });
1055
- if ("verificationId" in res && res.verificationId) {
1056
- const verifyPath = isPhone(identifier) ? `/auth/verify-phone?context=sign-in&verificationId=${res.verificationId}&identifier=${encodeURIComponent(identifier)}` : `/auth/verify-email?verificationId=${res.verificationId}`;
1057
- onNavigate(verifyPath);
1058
- return;
1059
- }
1060
- if ("user" in res && "session" in res) {
1061
- setAuth(res);
1062
- }
1063
- onNavigate(defaultRedirect);
1164
+ await handlePasswordStep(values.password || "");
1064
1165
  }
1065
1166
  } catch (err) {
1066
1167
  handleError(err, setError, t);
@@ -1068,18 +1169,26 @@ var SignInPage = ({
1068
1169
  setIsLoading(false);
1069
1170
  }
1070
1171
  };
1172
+ const isSubmitting = isLoading || checkUserMutation.isPending || signInMutation.isPending;
1071
1173
  const handleBack = () => {
1072
1174
  setStep("identifier");
1073
1175
  setIdentifier("");
1074
1176
  setError(null);
1075
1177
  };
1076
1178
  const isStepPassword = step === "password";
1077
- return /* @__PURE__ */ jsx10("div", { className: "space-y-4", children: /* @__PURE__ */ jsx10(
1179
+ let errorContent = null;
1180
+ if (error) {
1181
+ if (typeof error === "string") {
1182
+ errorContent = { title: "Error", description: error };
1183
+ } else {
1184
+ errorContent = error;
1185
+ }
1186
+ }
1187
+ return /* @__PURE__ */ jsx9("div", { className: "space-y-4", children: /* @__PURE__ */ jsxs7(
1078
1188
  AuthPageLayout,
1079
1189
  {
1080
1190
  title: t("title"),
1081
1191
  description: isStepPassword ? void 0 : t("description"),
1082
- error,
1083
1192
  logoImage,
1084
1193
  footer: /* @__PURE__ */ jsxs7(
1085
1194
  "div",
@@ -1090,7 +1199,7 @@ var SignInPage = ({
1090
1199
  },
1091
1200
  children: [
1092
1201
  isStepPassword && // biome-ignore lint/a11y/useKeyWithClickEvents: change account
1093
- /* @__PURE__ */ jsx10(
1202
+ /* @__PURE__ */ jsx9(
1094
1203
  "p",
1095
1204
  {
1096
1205
  className: "text-primary inline-block cursor-pointer hover:underline",
@@ -1098,14 +1207,14 @@ var SignInPage = ({
1098
1207
  children: t("changeAccount")
1099
1208
  }
1100
1209
  ),
1101
- Link ? /* @__PURE__ */ jsx10(
1210
+ Link ? /* @__PURE__ */ jsx9(
1102
1211
  Link,
1103
1212
  {
1104
1213
  href: forgotPasswordLink,
1105
1214
  className: "text-primary inline-block hover:underline",
1106
1215
  children: t("footer.forgotPassword")
1107
1216
  }
1108
- ) : /* @__PURE__ */ jsx10(
1217
+ ) : /* @__PURE__ */ jsx9(
1109
1218
  "a",
1110
1219
  {
1111
1220
  href: forgotPasswordLink,
@@ -1116,75 +1225,82 @@ var SignInPage = ({
1116
1225
  ]
1117
1226
  }
1118
1227
  ),
1119
- children: /* @__PURE__ */ jsx10(
1120
- SignIn,
1121
- {
1122
- onSubmit: handleSubmit,
1123
- isLoading,
1124
- identifier,
1125
- step
1126
- }
1127
- )
1228
+ children: [
1229
+ /* @__PURE__ */ jsx9(
1230
+ SignIn,
1231
+ {
1232
+ onSubmit: handleSubmit,
1233
+ isLoading: isSubmitting,
1234
+ identifier,
1235
+ step
1236
+ }
1237
+ ),
1238
+ errorContent && /* @__PURE__ */ jsxs7(Alert3, { variant: "destructive", className: "mt-4", children: [
1239
+ /* @__PURE__ */ jsx9(IconAlertCircle3, { className: "h-4 w-4" }),
1240
+ /* @__PURE__ */ jsx9(AlertTitle3, { children: errorContent.title }),
1241
+ /* @__PURE__ */ jsx9(AlertDescription3, { children: errorContent.description })
1242
+ ] })
1243
+ ]
1128
1244
  }
1129
1245
  ) });
1130
1246
  };
1131
1247
 
1132
1248
  // src/components/auth/pages/sign-up-page.tsx
1133
- import { useTranslations as useTranslations9 } from "next-intl";
1134
- import { useState as useState9 } from "react";
1249
+ import {
1250
+ Alert as Alert4,
1251
+ AlertDescription as AlertDescription4,
1252
+ AlertTitle as AlertTitle4
1253
+ } from "@mesob/ui/components/alert";
1254
+ import { toast as toast4 } from "@mesob/ui/components/sonner";
1255
+ import { IconAlertCircle as IconAlertCircle4 } from "@tabler/icons-react";
1256
+ import { useEffect as useEffect7, useState as useState8 } from "react";
1135
1257
 
1136
1258
  // src/components/auth/sign-up.tsx
1137
1259
  import { zodResolver as zodResolver4 } from "@hookform/resolvers/zod";
1138
- import { Button as Button5 } from "@mesob/ui/components/button";
1260
+ import { Button as Button4 } from "@mesob/ui/components/button";
1139
1261
  import {
1140
- Form as Form4,
1141
- FormControl as FormControl4,
1142
- FormField as FormField4,
1143
- FormItem as FormItem4,
1144
- FormLabel as FormLabel4,
1145
- FormMessage as FormMessage4
1146
- } from "@mesob/ui/components/form";
1262
+ Field as Field4,
1263
+ FieldError as FieldError4,
1264
+ FieldGroup as FieldGroup4,
1265
+ FieldLabel as FieldLabel4
1266
+ } from "@mesob/ui/components/field";
1147
1267
  import { Input as Input4 } from "@mesob/ui/components/input";
1148
1268
  import { IconEye as IconEye3, IconEyeOff as IconEyeOff3 } from "@tabler/icons-react";
1149
- import { useTranslations as useTranslations8 } from "next-intl";
1150
- import { useEffect as useEffect3, useMemo as useMemo4, useState as useState8 } from "react";
1151
- import { useForm as useForm4 } from "react-hook-form";
1269
+ import { useEffect as useEffect6, useState as useState7 } from "react";
1270
+ import { Controller as Controller4, useForm as useForm4 } from "react-hook-form";
1152
1271
  import { z as z4 } from "zod";
1153
- import { jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
1272
+ import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
1154
1273
  var isPhone2 = (s) => /^\+?[0-9()[\]\s-]{6,}$/.test(s);
1274
+ var signUpSchema = (t) => z4.object({
1275
+ fullName: z4.string().min(1, t("errors.fullNameRequired")),
1276
+ identifier: z4.string().min(1, t("errors.contactRequired")).refine(
1277
+ (val) => {
1278
+ if (!val) {
1279
+ return false;
1280
+ }
1281
+ return val.includes("@") || isPhone2(val);
1282
+ },
1283
+ {
1284
+ message: t("errors.invalidEmailOrPhone")
1285
+ }
1286
+ ),
1287
+ password: z4.string().min(8, t("errors.passwordLength")).max(128, t("errors.longPasswordError")),
1288
+ confirmPassword: z4.string()
1289
+ }).refine((data) => data.password === data.confirmPassword, {
1290
+ message: t("errors.passwordsMismatch"),
1291
+ path: ["confirmPassword"]
1292
+ });
1155
1293
  var SignUp = ({
1156
1294
  onSubmit,
1157
1295
  isLoading = false,
1158
1296
  initialIdentifier
1159
1297
  }) => {
1160
- const t = useTranslations8("Auth.signUp");
1298
+ const t = useTranslator("Auth.signUp");
1161
1299
  const hasInitialIdentifier = !!initialIdentifier;
1162
- const [showPassword, setShowPassword] = useState8(false);
1163
- const [showConfirmPassword, setShowConfirmPassword] = useState8(false);
1164
- const signUpSchema = useMemo4(
1165
- () => z4.object({
1166
- fullName: z4.string().min(1, t("errors.fullNameRequired")),
1167
- identifier: z4.string().min(1, t("errors.contactRequired")).refine(
1168
- (val) => {
1169
- if (!val) {
1170
- return false;
1171
- }
1172
- return val.includes("@") || isPhone2(val);
1173
- },
1174
- {
1175
- message: t("errors.invalidEmailOrPhone")
1176
- }
1177
- ),
1178
- password: z4.string().min(8, t("errors.passwordLength")).max(128, t("errors.longPasswordError")),
1179
- confirmPassword: z4.string()
1180
- }).refine((data) => data.password === data.confirmPassword, {
1181
- message: t("errors.passwordsMismatch"),
1182
- path: ["confirmPassword"]
1183
- }),
1184
- [t]
1185
- );
1300
+ const [showPassword, setShowPassword] = useState7(false);
1301
+ const [showConfirmPassword, setShowConfirmPassword] = useState7(false);
1186
1302
  const form = useForm4({
1187
- resolver: zodResolver4(signUpSchema),
1303
+ resolver: zodResolver4(signUpSchema(t)),
1188
1304
  defaultValues: {
1189
1305
  fullName: "",
1190
1306
  identifier: initialIdentifier || "",
@@ -1192,7 +1308,7 @@ var SignUp = ({
1192
1308
  confirmPassword: ""
1193
1309
  }
1194
1310
  });
1195
- useEffect3(() => {
1311
+ useEffect6(() => {
1196
1312
  if (initialIdentifier) {
1197
1313
  form.setValue("identifier", initialIdentifier);
1198
1314
  }
@@ -1210,135 +1326,182 @@ var SignUp = ({
1210
1326
  return t("form.phoneLabel");
1211
1327
  };
1212
1328
  const identifierLabel = getIdentifierLabel();
1213
- return /* @__PURE__ */ jsx11(Form4, { ...form, children: /* @__PURE__ */ jsxs8("form", { onSubmit: handleSubmit, className: "space-y-4", children: [
1214
- /* @__PURE__ */ jsx11(
1215
- FormField4,
1216
- {
1217
- control: form.control,
1218
- name: "fullName",
1219
- render: ({ field }) => /* @__PURE__ */ jsxs8(FormItem4, { children: [
1220
- /* @__PURE__ */ jsx11(FormLabel4, { children: t("form.fullNameLabel") }),
1221
- /* @__PURE__ */ jsx11(FormControl4, { children: /* @__PURE__ */ jsx11(Input4, { placeholder: t("form.fullNamePlaceholder"), ...field }) }),
1222
- /* @__PURE__ */ jsx11(FormMessage4, {})
1223
- ] })
1224
- }
1225
- ),
1226
- /* @__PURE__ */ jsx11(
1227
- FormField4,
1228
- {
1229
- control: form.control,
1230
- name: "identifier",
1231
- render: ({ field }) => /* @__PURE__ */ jsxs8(FormItem4, { children: [
1232
- /* @__PURE__ */ jsx11(FormLabel4, { className: hasInitialIdentifier ? "block" : void 0, children: identifierLabel }),
1233
- /* @__PURE__ */ jsx11(FormControl4, { children: /* @__PURE__ */ jsx11(
1234
- Input4,
1235
- {
1236
- type: field.value.includes("@") ? "email" : "tel",
1237
- placeholder: hasInitialIdentifier ? void 0 : t("form.accountPlaceholder") || "Email or phone number",
1238
- ...field,
1239
- disabled: hasInitialIdentifier
1240
- }
1241
- ) }),
1242
- /* @__PURE__ */ jsx11(FormMessage4, {})
1243
- ] })
1244
- }
1245
- ),
1246
- /* @__PURE__ */ jsx11(
1247
- FormField4,
1248
- {
1249
- control: form.control,
1250
- name: "password",
1251
- render: ({ field }) => /* @__PURE__ */ jsxs8(FormItem4, { children: [
1252
- /* @__PURE__ */ jsx11(FormLabel4, { children: t("form.passwordLabel") }),
1253
- /* @__PURE__ */ jsx11(FormControl4, { children: /* @__PURE__ */ jsxs8("div", { className: "relative", children: [
1254
- /* @__PURE__ */ jsx11(
1329
+ return /* @__PURE__ */ jsxs8("form", { id: "sign-up-form", onSubmit: handleSubmit, children: [
1330
+ /* @__PURE__ */ jsxs8(FieldGroup4, { children: [
1331
+ /* @__PURE__ */ jsx10(
1332
+ Controller4,
1333
+ {
1334
+ name: "fullName",
1335
+ control: form.control,
1336
+ render: ({ field, fieldState }) => /* @__PURE__ */ jsxs8(Field4, { "data-invalid": fieldState.invalid, children: [
1337
+ /* @__PURE__ */ jsx10(FieldLabel4, { htmlFor: "sign-up-fullName", children: t("form.fullNameLabel") }),
1338
+ /* @__PURE__ */ jsx10(
1255
1339
  Input4,
1256
1340
  {
1257
- type: showPassword ? "text" : "password",
1258
- placeholder: t("form.passwordPlaceholder"),
1259
- ...field
1341
+ ...field,
1342
+ id: "sign-up-fullName",
1343
+ placeholder: t("form.fullNamePlaceholder"),
1344
+ "aria-invalid": fieldState.invalid
1260
1345
  }
1261
1346
  ),
1262
- /* @__PURE__ */ jsx11(
1263
- "button",
1347
+ fieldState.invalid && /* @__PURE__ */ jsx10(FieldError4, { errors: [fieldState.error] })
1348
+ ] })
1349
+ }
1350
+ ),
1351
+ /* @__PURE__ */ jsx10(
1352
+ Controller4,
1353
+ {
1354
+ name: "identifier",
1355
+ control: form.control,
1356
+ render: ({ field, fieldState }) => /* @__PURE__ */ jsxs8(Field4, { "data-invalid": fieldState.invalid, children: [
1357
+ /* @__PURE__ */ jsx10(
1358
+ FieldLabel4,
1264
1359
  {
1265
- type: "button",
1266
- onClick: () => setShowPassword(!showPassword),
1267
- className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground",
1268
- children: showPassword ? /* @__PURE__ */ jsx11(IconEyeOff3, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx11(IconEye3, { className: "h-4 w-4" })
1360
+ htmlFor: "sign-up-identifier",
1361
+ className: hasInitialIdentifier ? "block" : void 0,
1362
+ children: identifierLabel
1269
1363
  }
1270
- )
1271
- ] }) }),
1272
- /* @__PURE__ */ jsx11(FormMessage4, {})
1273
- ] })
1274
- }
1275
- ),
1276
- /* @__PURE__ */ jsx11(
1277
- FormField4,
1278
- {
1279
- control: form.control,
1280
- name: "confirmPassword",
1281
- render: ({ field }) => /* @__PURE__ */ jsxs8(FormItem4, { children: [
1282
- /* @__PURE__ */ jsx11(FormLabel4, { children: t("form.confirmPasswordLabel") }),
1283
- /* @__PURE__ */ jsx11(FormControl4, { children: /* @__PURE__ */ jsxs8("div", { className: "relative", children: [
1284
- /* @__PURE__ */ jsx11(
1364
+ ),
1365
+ /* @__PURE__ */ jsx10(
1285
1366
  Input4,
1286
1367
  {
1287
- type: showConfirmPassword ? "text" : "password",
1288
- placeholder: t("form.passwordPlaceholder"),
1289
- ...field
1368
+ ...field,
1369
+ id: "sign-up-identifier",
1370
+ type: field.value.includes("@") ? "email" : "tel",
1371
+ placeholder: hasInitialIdentifier ? void 0 : t("form.accountPlaceholder") || "Email or phone number",
1372
+ disabled: hasInitialIdentifier,
1373
+ "aria-invalid": fieldState.invalid
1290
1374
  }
1291
1375
  ),
1292
- /* @__PURE__ */ jsx11(
1293
- "button",
1294
- {
1295
- type: "button",
1296
- onClick: () => setShowConfirmPassword(!showConfirmPassword),
1297
- className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground",
1298
- children: showConfirmPassword ? /* @__PURE__ */ jsx11(IconEyeOff3, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx11(IconEye3, { className: "h-4 w-4" })
1299
- }
1300
- )
1301
- ] }) }),
1302
- /* @__PURE__ */ jsx11(FormMessage4, {})
1303
- ] })
1376
+ fieldState.invalid && /* @__PURE__ */ jsx10(FieldError4, { errors: [fieldState.error] })
1377
+ ] })
1378
+ }
1379
+ ),
1380
+ /* @__PURE__ */ jsx10(
1381
+ Controller4,
1382
+ {
1383
+ name: "password",
1384
+ control: form.control,
1385
+ render: ({ field, fieldState }) => /* @__PURE__ */ jsxs8(Field4, { "data-invalid": fieldState.invalid, children: [
1386
+ /* @__PURE__ */ jsx10(FieldLabel4, { htmlFor: "sign-up-password", children: t("form.passwordLabel") }),
1387
+ /* @__PURE__ */ jsxs8("div", { className: "relative", children: [
1388
+ /* @__PURE__ */ jsx10(
1389
+ Input4,
1390
+ {
1391
+ ...field,
1392
+ id: "sign-up-password",
1393
+ type: showPassword ? "text" : "password",
1394
+ placeholder: t("form.passwordPlaceholder"),
1395
+ "aria-invalid": fieldState.invalid
1396
+ }
1397
+ ),
1398
+ /* @__PURE__ */ jsx10(
1399
+ "button",
1400
+ {
1401
+ type: "button",
1402
+ onClick: () => setShowPassword(!showPassword),
1403
+ className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground",
1404
+ children: showPassword ? /* @__PURE__ */ jsx10(IconEyeOff3, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx10(IconEye3, { className: "h-4 w-4" })
1405
+ }
1406
+ )
1407
+ ] }),
1408
+ fieldState.invalid && /* @__PURE__ */ jsx10(FieldError4, { errors: [fieldState.error] })
1409
+ ] })
1410
+ }
1411
+ ),
1412
+ /* @__PURE__ */ jsx10(
1413
+ Controller4,
1414
+ {
1415
+ name: "confirmPassword",
1416
+ control: form.control,
1417
+ render: ({ field, fieldState }) => /* @__PURE__ */ jsxs8(Field4, { "data-invalid": fieldState.invalid, children: [
1418
+ /* @__PURE__ */ jsx10(FieldLabel4, { htmlFor: "sign-up-confirmPassword", children: t("form.confirmPasswordLabel") }),
1419
+ /* @__PURE__ */ jsxs8("div", { className: "relative", children: [
1420
+ /* @__PURE__ */ jsx10(
1421
+ Input4,
1422
+ {
1423
+ ...field,
1424
+ id: "sign-up-confirmPassword",
1425
+ type: showConfirmPassword ? "text" : "password",
1426
+ placeholder: t("form.passwordPlaceholder"),
1427
+ "aria-invalid": fieldState.invalid
1428
+ }
1429
+ ),
1430
+ /* @__PURE__ */ jsx10(
1431
+ "button",
1432
+ {
1433
+ type: "button",
1434
+ onClick: () => setShowConfirmPassword(!showConfirmPassword),
1435
+ className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground",
1436
+ children: showConfirmPassword ? /* @__PURE__ */ jsx10(IconEyeOff3, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx10(IconEye3, { className: "h-4 w-4" })
1437
+ }
1438
+ )
1439
+ ] }),
1440
+ fieldState.invalid && /* @__PURE__ */ jsx10(FieldError4, { errors: [fieldState.error] })
1441
+ ] })
1442
+ }
1443
+ )
1444
+ ] }),
1445
+ /* @__PURE__ */ jsx10("div", { className: "mt-4", children: /* @__PURE__ */ jsx10(
1446
+ Button4,
1447
+ {
1448
+ type: "submit",
1449
+ form: "sign-up-form",
1450
+ className: "w-full",
1451
+ disabled: isLoading,
1452
+ children: isLoading ? t("form.submitting") : t("form.submit")
1304
1453
  }
1305
- ),
1306
- /* @__PURE__ */ jsx11(Button5, { type: "submit", className: "w-full", disabled: isLoading, children: isLoading ? t("form.submitting") : t("form.submit") })
1307
- ] }) });
1454
+ ) })
1455
+ ] });
1308
1456
  };
1309
1457
 
1310
1458
  // src/components/auth/pages/sign-up-page.tsx
1311
- import { jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
1459
+ import { jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
1312
1460
  var isPhone3 = (s) => /^\+?[0-9()[\]\s-]{6,}$/.test(s);
1313
1461
  var SignUpPage = ({
1314
1462
  redirectUrl,
1315
- onNavigate,
1316
- linkComponent: Link,
1317
- links,
1318
- initialIdentifier,
1319
- logoImage
1320
- }) => {
1321
- const t = useTranslations9("Auth.signUp");
1322
- const { client, setAuth } = useAuth();
1323
- const [isLoading, setIsLoading] = useState9(false);
1324
- const [error, setError] = useState9(null);
1325
- const signInLink = links?.signIn || "/auth/sign-in";
1463
+ initialIdentifier
1464
+ } = {}) => {
1465
+ const { hooks, setAuth } = useApi();
1466
+ const { config } = useConfig();
1467
+ const t = createTranslator(config.messages || {}, "Auth.signUp");
1468
+ const [isLoading, setIsLoading] = useState8(false);
1469
+ const [error, setError] = useState8(null);
1470
+ const signUpMutation = hooks.useMutation("post", "/sign-up");
1471
+ const signInLink = config.navigation?.links?.signIn || "/auth/sign-in";
1472
+ const Link = config.navigation?.linkComponent;
1473
+ const onNavigate = config.navigation?.onNavigate || ((path) => {
1474
+ if (typeof window !== "undefined") {
1475
+ window.location.href = path;
1476
+ }
1477
+ });
1478
+ const logoImage = config.ui.logoImage;
1479
+ const defaultRedirect = redirectUrl || config.navigation?.defaultRedirectUrl || "/";
1480
+ useEffect7(() => {
1481
+ if (error) {
1482
+ toast4.error(error.title || "Error", {
1483
+ description: error.description
1484
+ });
1485
+ }
1486
+ }, [error]);
1326
1487
  const handleSubmit = async (values) => {
1327
1488
  setIsLoading(true);
1328
1489
  setError(null);
1329
1490
  try {
1330
1491
  const identifier = values.identifier;
1331
1492
  const usingPhone = isPhone3(identifier);
1332
- const res = usingPhone ? await client.signUpWithPhone({
1333
- phone: identifier,
1334
- password: values.password,
1335
- fullName: values.fullName,
1336
- handle: values.handle
1337
- }) : await client.signUpWithEmail({
1338
- email: identifier,
1339
- password: values.password,
1340
- fullName: values.fullName,
1341
- handle: values.handle
1493
+ const res = await signUpMutation.mutateAsync({
1494
+ body: usingPhone ? {
1495
+ phone: identifier,
1496
+ password: values.password,
1497
+ fullName: values.fullName,
1498
+ handle: values.handle
1499
+ } : {
1500
+ email: identifier,
1501
+ password: values.password,
1502
+ fullName: values.fullName,
1503
+ handle: values.handle
1504
+ }
1342
1505
  });
1343
1506
  if ("verificationId" in res && res.verificationId) {
1344
1507
  if (usingPhone) {
@@ -1355,24 +1518,31 @@ var SignUpPage = ({
1355
1518
  if ("user" in res && "session" in res) {
1356
1519
  setAuth(res);
1357
1520
  }
1358
- onNavigate(redirectUrl || "/");
1521
+ onNavigate(defaultRedirect);
1359
1522
  } catch (err) {
1360
1523
  handleError(err, setError, t);
1361
1524
  } finally {
1362
1525
  setIsLoading(false);
1363
1526
  }
1364
1527
  };
1365
- return /* @__PURE__ */ jsx12(
1528
+ let errorContent = null;
1529
+ if (error) {
1530
+ if (typeof error === "string") {
1531
+ errorContent = { title: "Error", description: error };
1532
+ } else {
1533
+ errorContent = error;
1534
+ }
1535
+ }
1536
+ return /* @__PURE__ */ jsxs9(
1366
1537
  AuthPageLayout,
1367
1538
  {
1368
1539
  title: t("title"),
1369
1540
  description: t("description"),
1370
- error,
1371
1541
  logoImage,
1372
1542
  footer: /* @__PURE__ */ jsxs9("p", { children: [
1373
1543
  t("footer.hasAccount"),
1374
1544
  " ",
1375
- Link ? /* @__PURE__ */ jsx12(Link, { href: signInLink, className: "text-primary hover:underline", children: t("footer.signInCta") }) : /* @__PURE__ */ jsx12(
1545
+ Link ? /* @__PURE__ */ jsx11(Link, { href: signInLink, className: "text-primary hover:underline", children: t("footer.signInCta") }) : /* @__PURE__ */ jsx11(
1376
1546
  "a",
1377
1547
  {
1378
1548
  href: signInLink,
@@ -1385,69 +1555,131 @@ var SignUpPage = ({
1385
1555
  }
1386
1556
  )
1387
1557
  ] }),
1388
- children: /* @__PURE__ */ jsx12(
1389
- SignUp,
1390
- {
1391
- onSubmit: handleSubmit,
1392
- isLoading,
1393
- initialIdentifier
1394
- }
1395
- )
1558
+ children: [
1559
+ /* @__PURE__ */ jsx11(
1560
+ SignUp,
1561
+ {
1562
+ onSubmit: handleSubmit,
1563
+ isLoading: isLoading || signUpMutation.isPending,
1564
+ initialIdentifier
1565
+ }
1566
+ ),
1567
+ errorContent && /* @__PURE__ */ jsxs9(Alert4, { variant: "destructive", className: "mt-4", children: [
1568
+ /* @__PURE__ */ jsx11(IconAlertCircle4, { className: "h-4 w-4" }),
1569
+ /* @__PURE__ */ jsx11(AlertTitle4, { children: errorContent.title }),
1570
+ /* @__PURE__ */ jsx11(AlertDescription4, { children: errorContent.description })
1571
+ ] })
1572
+ ]
1396
1573
  }
1397
1574
  );
1398
1575
  };
1399
1576
 
1400
1577
  // src/components/auth/pages/verify-email-page.tsx
1401
- import { useTranslations as useTranslations11 } from "next-intl";
1402
- import { useState as useState10 } from "react";
1578
+ import {
1579
+ Alert as Alert5,
1580
+ AlertDescription as AlertDescription5,
1581
+ AlertTitle as AlertTitle5
1582
+ } from "@mesob/ui/components/alert";
1583
+ import { toast as toast5 } from "@mesob/ui/components/sonner";
1584
+ import { IconAlertCircle as IconAlertCircle5 } from "@tabler/icons-react";
1585
+ import { useEffect as useEffect9, useState as useState10 } from "react";
1403
1586
 
1404
1587
  // src/components/auth/verification-form.tsx
1405
1588
  import { zodResolver as zodResolver5 } from "@hookform/resolvers/zod";
1406
1589
  import { Button as Button6 } from "@mesob/ui/components/button";
1407
- import {
1408
- Form as Form5,
1409
- FormControl as FormControl5,
1410
- FormField as FormField5,
1411
- FormItem as FormItem5,
1412
- FormMessage as FormMessage5
1413
- } from "@mesob/ui/components/form";
1590
+ import { Field as Field5, FieldError as FieldError5, FieldGroup as FieldGroup5 } from "@mesob/ui/components/field";
1414
1591
  import {
1415
1592
  InputOTP as InputOTP2,
1416
1593
  InputOTPGroup as InputOTPGroup2,
1417
1594
  InputOTPSlot as InputOTPSlot2
1418
1595
  } from "@mesob/ui/components/input-otp";
1419
1596
  import { Spinner as Spinner5 } from "@mesob/ui/components/spinner";
1420
- import { useTranslations as useTranslations10 } from "next-intl";
1421
- import { useMemo as useMemo5 } from "react";
1422
- import { useForm as useForm5 } from "react-hook-form";
1597
+ import { Controller as Controller5, useForm as useForm5 } from "react-hook-form";
1423
1598
  import { z as z5 } from "zod";
1424
- import { jsx as jsx13, jsxs as jsxs10 } from "react/jsx-runtime";
1599
+
1600
+ // src/components/auth/countdown.tsx
1601
+ import { Button as Button5 } from "@mesob/ui/components/button";
1602
+ import { Spinner as Spinner4 } from "@mesob/ui/components/spinner";
1603
+ import { useEffect as useEffect8, useState as useState9 } from "react";
1604
+ import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
1605
+ var Countdown = ({
1606
+ initialSeconds = 60,
1607
+ onResend,
1608
+ resending = false
1609
+ }) => {
1610
+ const t = useTranslator("Common");
1611
+ const [seconds, setSeconds] = useState9(initialSeconds);
1612
+ const [isResending, setIsResending] = useState9(false);
1613
+ useEffect8(() => {
1614
+ if (seconds <= 0) {
1615
+ return;
1616
+ }
1617
+ const timer = setInterval(() => {
1618
+ setSeconds((prev) => {
1619
+ if (prev <= 1) {
1620
+ clearInterval(timer);
1621
+ return 0;
1622
+ }
1623
+ return prev - 1;
1624
+ });
1625
+ }, 1e3);
1626
+ return () => clearInterval(timer);
1627
+ }, [seconds]);
1628
+ const handleResend = async () => {
1629
+ setIsResending(true);
1630
+ try {
1631
+ await onResend();
1632
+ setSeconds(initialSeconds);
1633
+ } catch (_error) {
1634
+ } finally {
1635
+ setIsResending(false);
1636
+ }
1637
+ };
1638
+ if (seconds > 0) {
1639
+ return /* @__PURE__ */ jsx12(Button5, { variant: "ghost", disabled: true, children: t("resendIn", { seconds }) });
1640
+ }
1641
+ return /* @__PURE__ */ jsxs10(
1642
+ Button5,
1643
+ {
1644
+ variant: "ghost",
1645
+ onClick: handleResend,
1646
+ disabled: isResending || resending,
1647
+ children: [
1648
+ isResending || resending && /* @__PURE__ */ jsx12(Spinner4, {}),
1649
+ t("resend")
1650
+ ]
1651
+ }
1652
+ );
1653
+ };
1654
+
1655
+ // src/components/auth/verification-form.tsx
1656
+ import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
1657
+ var verificationSchema = (t) => z5.object({
1658
+ code: z5.string().length(6, t("form.codeLength"))
1659
+ });
1425
1660
  var VerificationForm = ({
1426
1661
  onSubmit,
1427
1662
  onResend,
1428
1663
  isLoading = false
1429
1664
  }) => {
1430
- const t = useTranslations10("Auth.verification");
1431
- const verificationSchema = useMemo5(
1432
- () => z5.object({
1433
- code: z5.string().length(6, t("form.codeLength"))
1434
- }),
1435
- [t]
1436
- );
1665
+ const t = useTranslator("Auth.verification");
1437
1666
  const form = useForm5({
1438
- resolver: zodResolver5(verificationSchema),
1667
+ resolver: zodResolver5(verificationSchema(t)),
1439
1668
  defaultValues: {
1440
1669
  code: ""
1441
1670
  }
1442
1671
  });
1443
- return /* @__PURE__ */ jsx13(Form5, { ...form, children: /* @__PURE__ */ jsxs10("form", { className: "space-y-4", children: [
1444
- /* @__PURE__ */ jsx13(
1445
- FormField5,
1672
+ const handleSubmit = form.handleSubmit(async (values) => {
1673
+ await onSubmit(values);
1674
+ });
1675
+ return /* @__PURE__ */ jsxs11("form", { id: "verification-form", onSubmit: handleSubmit, children: [
1676
+ /* @__PURE__ */ jsx13(FieldGroup5, { children: /* @__PURE__ */ jsx13(
1677
+ Controller5,
1446
1678
  {
1447
- control: form.control,
1448
1679
  name: "code",
1449
- render: ({ field }) => /* @__PURE__ */ jsxs10(FormItem5, { children: [
1450
- /* @__PURE__ */ jsx13(FormControl5, { children: /* @__PURE__ */ jsx13("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx13(
1680
+ control: form.control,
1681
+ render: ({ field, fieldState }) => /* @__PURE__ */ jsxs11(Field5, { "data-invalid": fieldState.invalid, children: [
1682
+ /* @__PURE__ */ jsx13("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx13(
1451
1683
  InputOTP2,
1452
1684
  {
1453
1685
  maxLength: 6,
@@ -1457,7 +1689,8 @@ var VerificationForm = ({
1457
1689
  onChange: field.onChange,
1458
1690
  onBlur: field.onBlur,
1459
1691
  containerClassName: "gap-4 justify-center mb-2 flex items-center",
1460
- children: /* @__PURE__ */ jsxs10(InputOTPGroup2, { 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: [
1692
+ "aria-invalid": fieldState.invalid,
1693
+ children: /* @__PURE__ */ jsxs11(InputOTPGroup2, { 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: [
1461
1694
  /* @__PURE__ */ jsx13(InputOTPSlot2, { className: "h-12", index: 0 }),
1462
1695
  /* @__PURE__ */ jsx13(InputOTPSlot2, { className: "h-12", index: 1 }),
1463
1696
  /* @__PURE__ */ jsx13(InputOTPSlot2, { className: "h-12", index: 2 }),
@@ -1466,22 +1699,18 @@ var VerificationForm = ({
1466
1699
  /* @__PURE__ */ jsx13(InputOTPSlot2, { className: "h-12", index: 5 })
1467
1700
  ] })
1468
1701
  }
1469
- ) }) }),
1470
- /* @__PURE__ */ jsx13(FormMessage5, {})
1702
+ ) }),
1703
+ fieldState.invalid && /* @__PURE__ */ jsx13(FieldError5, { errors: [fieldState.error] })
1471
1704
  ] })
1472
1705
  }
1473
- ),
1474
- /* @__PURE__ */ jsxs10("div", { className: "flex justify-between items-center", children: [
1706
+ ) }),
1707
+ /* @__PURE__ */ jsxs11("div", { className: "flex justify-between items-center mt-4", children: [
1475
1708
  /* @__PURE__ */ jsx13(Countdown, { onResend, resending: isLoading }),
1476
- /* @__PURE__ */ jsxs10(
1709
+ /* @__PURE__ */ jsxs11(
1477
1710
  Button6,
1478
1711
  {
1479
- type: "button",
1480
- onClick: () => {
1481
- form.handleSubmit(async (values) => {
1482
- await onSubmit(values);
1483
- })();
1484
- },
1712
+ type: "submit",
1713
+ form: "verification-form",
1485
1714
  disabled: isLoading || form.watch("code").length !== 6,
1486
1715
  children: [
1487
1716
  isLoading && /* @__PURE__ */ jsx13(Spinner5, {}),
@@ -1490,27 +1719,50 @@ var VerificationForm = ({
1490
1719
  }
1491
1720
  )
1492
1721
  ] })
1493
- ] }) });
1722
+ ] });
1494
1723
  };
1495
1724
 
1496
1725
  // src/components/auth/pages/verify-email-page.tsx
1497
- import { jsx as jsx14 } from "react/jsx-runtime";
1726
+ import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
1498
1727
  var VerifyEmailPage = ({
1499
1728
  verificationId,
1500
- onNavigate,
1501
- linkComponent: Link,
1502
- links,
1503
1729
  email,
1504
- logoImage,
1505
1730
  redirectUrl
1506
1731
  }) => {
1507
- const t = useTranslations11("Auth.verification");
1508
- const common = useTranslations11("Common");
1509
- const footer = useTranslations11("Auth.forgotPassword.footer");
1510
- const { client, setAuth } = useAuth();
1732
+ const { hooks, setAuth } = useApi();
1733
+ const { config } = useConfig();
1734
+ const t = createTranslator(config.messages || {}, "Auth.verification");
1735
+ const common = createTranslator(config.messages || {}, "Common");
1736
+ const footer = createTranslator(
1737
+ config.messages || {},
1738
+ "Auth.forgotPassword.footer"
1739
+ );
1511
1740
  const [isLoading, setIsLoading] = useState10(false);
1512
1741
  const [error, setError] = useState10(null);
1513
- const signInLink = links?.signIn || "/auth/sign-in";
1742
+ const verifyEmailMutation = hooks.useMutation(
1743
+ "post",
1744
+ "/email/verification/confirm"
1745
+ );
1746
+ const requestEmailMutation = hooks.useMutation(
1747
+ "post",
1748
+ "/email/verification/request"
1749
+ );
1750
+ const signInLink = config.navigation?.links?.signIn || "/auth/sign-in";
1751
+ const Link = config.navigation?.linkComponent;
1752
+ const onNavigate = config.navigation?.onNavigate || ((path) => {
1753
+ if (typeof window !== "undefined") {
1754
+ window.location.href = path;
1755
+ }
1756
+ });
1757
+ const logoImage = config.ui.logoImage;
1758
+ const defaultRedirect = redirectUrl || config.navigation?.defaultRedirectUrl || "/";
1759
+ useEffect9(() => {
1760
+ if (error) {
1761
+ toast5.error(error.title || "Error", {
1762
+ description: error.description
1763
+ });
1764
+ }
1765
+ }, [error]);
1514
1766
  const handleSubmit = async (values) => {
1515
1767
  if (!verificationId) {
1516
1768
  setError({
@@ -1522,14 +1774,16 @@ var VerifyEmailPage = ({
1522
1774
  setIsLoading(true);
1523
1775
  setError(null);
1524
1776
  try {
1525
- const res = await client.verifyEmail({
1526
- verificationId,
1527
- code: values.code
1777
+ const res = await verifyEmailMutation.mutateAsync({
1778
+ body: {
1779
+ verificationId,
1780
+ code: values.code
1781
+ }
1528
1782
  });
1529
1783
  if ("user" in res && "session" in res) {
1530
1784
  setAuth(res);
1531
1785
  }
1532
- onNavigate(redirectUrl || "/");
1786
+ onNavigate(defaultRedirect);
1533
1787
  } catch (err) {
1534
1788
  handleError(err, setError, t);
1535
1789
  } finally {
@@ -1539,7 +1793,11 @@ var VerifyEmailPage = ({
1539
1793
  const handleResend = async () => {
1540
1794
  setError(null);
1541
1795
  try {
1542
- const res = await client.requestEmailVerification({ email });
1796
+ const res = await requestEmailMutation.mutateAsync({
1797
+ body: {
1798
+ email
1799
+ }
1800
+ });
1543
1801
  if (res.verificationId) {
1544
1802
  onNavigate(
1545
1803
  `/auth/verify-email?verificationId=${res.verificationId}&email=${encodeURIComponent(email)}`
@@ -1576,12 +1834,19 @@ var VerifyEmailPage = ({
1576
1834
  }
1577
1835
  );
1578
1836
  }
1579
- return /* @__PURE__ */ jsx14(
1837
+ let errorContent = null;
1838
+ if (error) {
1839
+ if (typeof error === "string") {
1840
+ errorContent = { title: "Error", description: error };
1841
+ } else {
1842
+ errorContent = error;
1843
+ }
1844
+ }
1845
+ return /* @__PURE__ */ jsxs12(
1580
1846
  AuthPageLayout,
1581
1847
  {
1582
1848
  title: t("email.title"),
1583
1849
  description: t("email.description"),
1584
- error,
1585
1850
  logoImage,
1586
1851
  footer: Link ? /* @__PURE__ */ jsx14(Link, { href: signInLink, className: "text-primary hover:underline", children: footer("backToSignIn") }) : /* @__PURE__ */ jsx14(
1587
1852
  "a",
@@ -1595,41 +1860,77 @@ var VerifyEmailPage = ({
1595
1860
  children: footer("backToSignIn")
1596
1861
  }
1597
1862
  ),
1598
- children: /* @__PURE__ */ jsx14(
1599
- VerificationForm,
1600
- {
1601
- verificationId,
1602
- onSubmit: handleSubmit,
1603
- onResend: handleResend,
1604
- isLoading,
1605
- error
1606
- }
1607
- )
1863
+ children: [
1864
+ /* @__PURE__ */ jsx14(
1865
+ VerificationForm,
1866
+ {
1867
+ verificationId,
1868
+ onSubmit: handleSubmit,
1869
+ onResend: handleResend,
1870
+ isLoading: isLoading || verifyEmailMutation.isPending || requestEmailMutation.isPending,
1871
+ error
1872
+ }
1873
+ ),
1874
+ errorContent && /* @__PURE__ */ jsxs12(Alert5, { variant: "destructive", className: "mt-4", children: [
1875
+ /* @__PURE__ */ jsx14(IconAlertCircle5, { className: "h-4 w-4" }),
1876
+ /* @__PURE__ */ jsx14(AlertTitle5, { children: errorContent.title }),
1877
+ /* @__PURE__ */ jsx14(AlertDescription5, { children: errorContent.description })
1878
+ ] })
1879
+ ]
1608
1880
  }
1609
1881
  );
1610
1882
  };
1611
1883
 
1612
1884
  // src/components/auth/pages/verify-phone-page.tsx
1613
- import { useTranslations as useTranslations12 } from "next-intl";
1614
- import { useState as useState11 } from "react";
1615
- import { jsx as jsx15 } from "react/jsx-runtime";
1885
+ import {
1886
+ Alert as Alert6,
1887
+ AlertDescription as AlertDescription6,
1888
+ AlertTitle as AlertTitle6
1889
+ } from "@mesob/ui/components/alert";
1890
+ import { toast as toast6 } from "@mesob/ui/components/sonner";
1891
+ import { IconAlertCircle as IconAlertCircle6 } from "@tabler/icons-react";
1892
+ import { useEffect as useEffect10, useState as useState11 } from "react";
1893
+ import { jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
1616
1894
  var VerifyPhonePage = ({
1617
1895
  verificationId,
1618
1896
  context,
1619
1897
  phone = "",
1620
- onNavigate,
1621
- linkComponent: Link,
1622
- links,
1623
- logoImage,
1624
1898
  redirectUrl
1625
1899
  }) => {
1626
- const t = useTranslations12("Auth.verification");
1627
- const common = useTranslations12("Common");
1628
- const footer = useTranslations12("Auth.forgotPassword.footer");
1629
- const { client, refresh, setAuth } = useAuth();
1900
+ const { hooks, refresh, setAuth } = useApi();
1901
+ const { config } = useConfig();
1902
+ const t = createTranslator(config.messages || {}, "Auth.verification");
1903
+ const common = createTranslator(config.messages || {}, "Common");
1904
+ const footer = createTranslator(
1905
+ config.messages || {},
1906
+ "Auth.forgotPassword.footer"
1907
+ );
1630
1908
  const [isLoading, setIsLoading] = useState11(false);
1631
1909
  const [error, setError] = useState11(null);
1632
- const signInLink = links?.signIn || "/auth/sign-in";
1910
+ const verifyPhoneMutation = hooks.useMutation(
1911
+ "post",
1912
+ "/phone/verification/confirm"
1913
+ );
1914
+ const requestPhoneMutation = hooks.useMutation(
1915
+ "post",
1916
+ "/phone/verification/request"
1917
+ );
1918
+ const signInLink = config.navigation?.links?.signIn || "/auth/sign-in";
1919
+ const Link = config.navigation?.linkComponent;
1920
+ const onNavigate = config.navigation?.onNavigate || ((path) => {
1921
+ if (typeof window !== "undefined") {
1922
+ window.location.href = path;
1923
+ }
1924
+ });
1925
+ const logoImage = config.ui.logoImage;
1926
+ const defaultRedirect = redirectUrl || config.navigation?.defaultRedirectUrl || "/";
1927
+ useEffect10(() => {
1928
+ if (error) {
1929
+ toast6.error(error.title || "Error", {
1930
+ description: error.description
1931
+ });
1932
+ }
1933
+ }, [error]);
1633
1934
  const handleSubmit = async (values) => {
1634
1935
  if (!verificationId) {
1635
1936
  setError({
@@ -1641,18 +1942,20 @@ var VerifyPhonePage = ({
1641
1942
  setIsLoading(true);
1642
1943
  setError(null);
1643
1944
  try {
1644
- const res = await client.verifyPhoneOtp({
1645
- verificationId,
1646
- code: values.code,
1647
- context
1945
+ const res = await verifyPhoneMutation.mutateAsync({
1946
+ body: {
1947
+ verificationId,
1948
+ code: values.code,
1949
+ context
1950
+ }
1648
1951
  });
1649
1952
  if (res && "user" in res && "session" in res && res.session) {
1650
1953
  setAuth(res);
1651
- onNavigate(redirectUrl || "/");
1954
+ onNavigate(defaultRedirect);
1652
1955
  return;
1653
1956
  }
1654
1957
  await refresh();
1655
- onNavigate(redirectUrl || "/");
1958
+ onNavigate(defaultRedirect);
1656
1959
  } catch (err) {
1657
1960
  handleError(err, setError, t);
1658
1961
  } finally {
@@ -1670,7 +1973,12 @@ var VerifyPhonePage = ({
1670
1973
  });
1671
1974
  return;
1672
1975
  }
1673
- const res = await client.requestPhoneOtp({ phone: targetPhone, context });
1976
+ const res = await requestPhoneMutation.mutateAsync({
1977
+ body: {
1978
+ phone: targetPhone,
1979
+ context
1980
+ }
1981
+ });
1674
1982
  if (res && "verificationId" in res && res.verificationId) {
1675
1983
  onNavigate(
1676
1984
  `/auth/verify-phone?context=${context}&verificationId=${res.verificationId}&phone=${targetPhone}`
@@ -1707,14 +2015,21 @@ var VerifyPhonePage = ({
1707
2015
  }
1708
2016
  );
1709
2017
  }
1710
- return /* @__PURE__ */ jsx15(
2018
+ let errorContent = null;
2019
+ if (error) {
2020
+ if (typeof error === "string") {
2021
+ errorContent = { title: "Error", description: error };
2022
+ } else {
2023
+ errorContent = error;
2024
+ }
2025
+ }
2026
+ return /* @__PURE__ */ jsxs13(
1711
2027
  AuthPageLayout,
1712
2028
  {
1713
2029
  title: t("phone.title"),
1714
2030
  description: t("phone.description", {
1715
2031
  target: phone || t("phone.missingPhone")
1716
2032
  }),
1717
- error,
1718
2033
  logoImage,
1719
2034
  footer: Link ? /* @__PURE__ */ jsx15(Link, { href: signInLink, className: "text-primary hover:underline", children: footer("backToSignIn") }) : /* @__PURE__ */ jsx15(
1720
2035
  "a",
@@ -1728,75 +2043,794 @@ var VerifyPhonePage = ({
1728
2043
  children: footer("backToSignIn")
1729
2044
  }
1730
2045
  ),
1731
- children: /* @__PURE__ */ jsx15(
1732
- VerificationForm,
1733
- {
1734
- verificationId,
1735
- onSubmit: handleSubmit,
1736
- onResend: handleResend,
1737
- isLoading,
1738
- error
1739
- }
1740
- )
2046
+ children: [
2047
+ /* @__PURE__ */ jsx15(
2048
+ VerificationForm,
2049
+ {
2050
+ verificationId,
2051
+ onSubmit: handleSubmit,
2052
+ onResend: handleResend,
2053
+ isLoading: isLoading || verifyPhoneMutation.isPending || requestPhoneMutation.isPending,
2054
+ error
2055
+ }
2056
+ ),
2057
+ errorContent && /* @__PURE__ */ jsxs13(Alert6, { variant: "destructive", className: "mt-4", children: [
2058
+ /* @__PURE__ */ jsx15(IconAlertCircle6, { className: "h-4 w-4" }),
2059
+ /* @__PURE__ */ jsx15(AlertTitle6, { children: errorContent.title }),
2060
+ /* @__PURE__ */ jsx15(AlertDescription6, { children: errorContent.description })
2061
+ ] })
2062
+ ]
1741
2063
  }
1742
2064
  );
1743
2065
  };
1744
2066
 
1745
- // src/factory.ts
1746
- var createAuthClient = (config) => {
1747
- const client = new AuthClient(config);
1748
- return {
1749
- signUpWithEmail: client.signUpWithEmail.bind(client),
1750
- signUpWithPhone: client.signUpWithPhone.bind(client),
1751
- signInWithPassword: client.signInWithPassword.bind(client),
1752
- signOut: client.signOut.bind(client),
1753
- requestEmailVerification: client.requestEmailVerification.bind(client),
1754
- verifyEmail: client.verifyEmail.bind(client),
1755
- resendVerification: client.resendVerification.bind(client),
1756
- requestPhoneOtp: client.requestPhoneOtp.bind(client),
1757
- verifyPhoneOtp: client.verifyPhoneOtp.bind(client),
1758
- forgotPassword: client.forgotPassword.bind(client),
1759
- resetPassword: client.resetPassword.bind(client),
1760
- changePassword: client.changePassword.bind(client),
1761
- getSession: client.getSession.bind(client),
1762
- useSession: () => {
1763
- throw new Error("useSession must be used within AuthProvider");
1764
- }
2067
+ // src/components/error-boundary.tsx
2068
+ import { Button as Button7 } from "@mesob/ui/components/button";
2069
+ import { Component } from "react";
2070
+ import { jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
2071
+ var ErrorBoundary = class extends Component {
2072
+ constructor(props) {
2073
+ super(props);
2074
+ this.state = { hasError: false, error: null };
2075
+ }
2076
+ static getDerivedStateFromError(error) {
2077
+ return { hasError: true, error };
2078
+ }
2079
+ componentDidCatch(_error, _errorInfo) {
2080
+ }
2081
+ reset = () => {
2082
+ this.setState({ hasError: false, error: null });
1765
2083
  };
2084
+ render() {
2085
+ if (this.state.hasError && this.state.error) {
2086
+ if (this.props.fallback) {
2087
+ return this.props.fallback({
2088
+ error: this.state.error,
2089
+ reset: this.reset
2090
+ });
2091
+ }
2092
+ return /* @__PURE__ */ jsx16(ErrorFallback, { error: this.state.error, reset: this.reset });
2093
+ }
2094
+ return this.props.children;
2095
+ }
1766
2096
  };
2097
+ function ErrorFallback({ error, reset }) {
2098
+ return /* @__PURE__ */ jsx16("div", { className: "flex flex-col items-center justify-center min-h-[400px] p-6", children: /* @__PURE__ */ jsxs14("div", { className: "max-w-md w-full space-y-4 text-center", children: [
2099
+ /* @__PURE__ */ jsxs14("div", { className: "space-y-2", children: [
2100
+ /* @__PURE__ */ jsx16("h2", { className: "text-2xl font-bold text-destructive", children: "Something went wrong" }),
2101
+ /* @__PURE__ */ jsx16("p", { className: "text-muted-foreground", children: error.message || "An unexpected error occurred" })
2102
+ ] }),
2103
+ /* @__PURE__ */ jsx16(Button7, { onClick: reset, variant: "outline", children: "Try again" })
2104
+ ] }) });
2105
+ }
2106
+ function AuthErrorBoundary({ children }) {
2107
+ return /* @__PURE__ */ jsx16(ErrorBoundary, { children });
2108
+ }
2109
+
2110
+ // src/components/iam/permissions/permissions-page.tsx
2111
+ import { Badge } from "@mesob/ui/components/badge";
2112
+ import { Button as Button8 } from "@mesob/ui/components/button";
2113
+ import { useState as useState12 } from "react";
2114
+
2115
+ // src/components/shared/data-table/data-table.tsx
2116
+ import {
2117
+ Table,
2118
+ TableBody,
2119
+ TableCell,
2120
+ TableHead,
2121
+ TableHeader,
2122
+ TableRow
2123
+ } from "@mesob/ui/components/table";
2124
+
2125
+ // src/components/skeletons/table-skeleton.tsx
2126
+ import { Skeleton } from "@mesob/ui/components/skeleton";
2127
+ import { jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
2128
+ function TableSkeleton({ columns = 5, rows = 10 }) {
2129
+ const headerKeys = Array.from({ length: columns }, (_, i) => `header-${i}`);
2130
+ const rowKeys = Array.from({ length: rows }, (_, i) => `row-${i}`);
2131
+ const cellKeys = Array.from(
2132
+ { length: rows },
2133
+ (_, rowIdx) => Array.from({ length: columns }, (_2, colIdx) => `cell-${rowIdx}-${colIdx}`)
2134
+ );
2135
+ return /* @__PURE__ */ jsxs15("div", { className: "w-full space-y-4", children: [
2136
+ /* @__PURE__ */ jsxs15("div", { className: "flex justify-between items-center", children: [
2137
+ /* @__PURE__ */ jsx17(Skeleton, { className: "h-8 w-48" }),
2138
+ /* @__PURE__ */ jsx17(Skeleton, { className: "h-10 w-32" })
2139
+ ] }),
2140
+ /* @__PURE__ */ jsxs15("div", { className: "flex gap-4", children: [
2141
+ /* @__PURE__ */ jsx17(Skeleton, { className: "h-10 flex-1 max-w-sm" }),
2142
+ /* @__PURE__ */ jsx17(Skeleton, { className: "h-10 w-24" }),
2143
+ /* @__PURE__ */ jsx17(Skeleton, { className: "h-10 w-24" })
2144
+ ] }),
2145
+ /* @__PURE__ */ jsxs15("div", { className: "border rounded-lg overflow-hidden", children: [
2146
+ /* @__PURE__ */ jsx17("div", { className: "flex gap-4 p-4 bg-muted", children: headerKeys.map((key) => /* @__PURE__ */ jsx17(Skeleton, { className: "h-4 flex-1" }, key)) }),
2147
+ rowKeys.map((rowKey, rowIdx) => /* @__PURE__ */ jsx17("div", { className: "flex gap-4 p-4 border-t", children: cellKeys[rowIdx]?.map((cellKey) => /* @__PURE__ */ jsx17(Skeleton, { className: "h-4 flex-1" }, cellKey)) }, rowKey))
2148
+ ] }),
2149
+ /* @__PURE__ */ jsxs15("div", { className: "flex justify-between items-center", children: [
2150
+ /* @__PURE__ */ jsx17(Skeleton, { className: "h-4 w-32" }),
2151
+ /* @__PURE__ */ jsxs15("div", { className: "flex gap-2", children: [
2152
+ /* @__PURE__ */ jsx17(Skeleton, { className: "h-10 w-20" }),
2153
+ /* @__PURE__ */ jsx17(Skeleton, { className: "h-10 w-20" })
2154
+ ] })
2155
+ ] })
2156
+ ] });
2157
+ }
2158
+
2159
+ // src/components/shared/data-table/data-table.tsx
2160
+ import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
2161
+ function DataTable({
2162
+ data,
2163
+ columns,
2164
+ isLoading,
2165
+ onRowClick,
2166
+ emptyMessage = "No data available",
2167
+ actions
2168
+ }) {
2169
+ if (isLoading) {
2170
+ return /* @__PURE__ */ jsx18(TableSkeleton, { columns: columns.length, rows: 5 });
2171
+ }
2172
+ if (data.length === 0) {
2173
+ return /* @__PURE__ */ jsxs16("div", { className: "flex flex-col items-center justify-center min-h-[400px] p-6", children: [
2174
+ /* @__PURE__ */ jsx18("p", { className: "text-muted-foreground", children: emptyMessage }),
2175
+ actions && /* @__PURE__ */ jsx18("div", { className: "mt-4", children: actions })
2176
+ ] });
2177
+ }
2178
+ return /* @__PURE__ */ jsxs16("div", { className: "w-full space-y-4", children: [
2179
+ actions && /* @__PURE__ */ jsx18("div", { className: "flex justify-end", children: actions }),
2180
+ /* @__PURE__ */ jsx18("div", { className: "border rounded-lg overflow-hidden", children: /* @__PURE__ */ jsxs16(Table, { children: [
2181
+ /* @__PURE__ */ jsx18(TableHeader, { children: /* @__PURE__ */ jsx18(TableRow, { children: columns.map((column) => /* @__PURE__ */ jsx18(TableHead, { children: column.header }, column.key)) }) }),
2182
+ /* @__PURE__ */ jsx18(TableBody, { children: data.map((row) => /* @__PURE__ */ jsx18(
2183
+ TableRow,
2184
+ {
2185
+ onClick: () => onRowClick?.(row),
2186
+ className: onRowClick ? "cursor-pointer hover:bg-muted/50" : "",
2187
+ children: columns.map((column) => /* @__PURE__ */ jsx18(TableCell, { children: column.cell(row) }, `${row.id}-${column.key}`))
2188
+ },
2189
+ row.id
2190
+ )) })
2191
+ ] }) })
2192
+ ] });
2193
+ }
2194
+
2195
+ // src/components/iam/permissions/permissions-page.tsx
2196
+ import { jsx as jsx19, jsxs as jsxs17 } from "react/jsx-runtime";
2197
+ function PermissionsPage() {
2198
+ const { hooks } = useApi();
2199
+ const [page, setPage] = useState12(1);
2200
+ const limit = 20;
2201
+ const { data, isLoading, error } = hooks.useQuery("get", "/permissions", {
2202
+ params: {
2203
+ query: {
2204
+ page: String(page),
2205
+ limit: String(limit)
2206
+ }
2207
+ }
2208
+ });
2209
+ const columns = [
2210
+ {
2211
+ key: "name",
2212
+ header: "Permission",
2213
+ cell: (permission) => /* @__PURE__ */ jsxs17("div", { children: [
2214
+ /* @__PURE__ */ jsx19("p", { className: "font-medium", children: permission.name }),
2215
+ /* @__PURE__ */ jsx19(Badge, { variant: "outline", className: "mt-1 font-mono text-xs", children: permission.code })
2216
+ ] })
2217
+ },
2218
+ {
2219
+ key: "resource",
2220
+ header: "Resource",
2221
+ cell: (permission) => /* @__PURE__ */ jsx19(Badge, { variant: "secondary", children: permission.resource })
2222
+ },
2223
+ {
2224
+ key: "action",
2225
+ header: "Action",
2226
+ cell: (permission) => /* @__PURE__ */ jsx19(Badge, { variant: "outline", children: permission.action })
2227
+ },
2228
+ {
2229
+ key: "description",
2230
+ header: "Description",
2231
+ cell: (permission) => /* @__PURE__ */ jsx19("p", { className: "text-sm text-muted-foreground max-w-xs truncate", children: permission.description })
2232
+ },
2233
+ {
2234
+ key: "actions",
2235
+ header: "Actions",
2236
+ cell: (_permission) => /* @__PURE__ */ jsx19(Button8, { variant: "outline", size: "sm", children: "Edit" })
2237
+ }
2238
+ ];
2239
+ if (error) {
2240
+ return /* @__PURE__ */ jsx19("div", { className: "p-6 text-center", children: /* @__PURE__ */ jsx19("p", { className: "text-destructive", children: "Error loading permissions" }) });
2241
+ }
2242
+ return /* @__PURE__ */ jsxs17("div", { className: "w-full p-6 space-y-4", children: [
2243
+ /* @__PURE__ */ jsxs17("div", { className: "flex justify-between items-center", children: [
2244
+ /* @__PURE__ */ jsxs17("div", { children: [
2245
+ /* @__PURE__ */ jsx19("h1", { className: "text-3xl font-bold", children: "Permissions" }),
2246
+ /* @__PURE__ */ jsx19("p", { className: "text-muted-foreground", children: "Manage system permissions" })
2247
+ ] }),
2248
+ /* @__PURE__ */ jsx19(Button8, { children: "Create Permission" })
2249
+ ] }),
2250
+ /* @__PURE__ */ jsx19(
2251
+ DataTable,
2252
+ {
2253
+ data: data?.permissions || [],
2254
+ columns,
2255
+ isLoading,
2256
+ emptyMessage: "No permissions found"
2257
+ }
2258
+ ),
2259
+ data && "permissions" in data && data.permissions && data.permissions.length >= limit && /* @__PURE__ */ jsxs17("div", { className: "flex justify-between items-center", children: [
2260
+ /* @__PURE__ */ jsx19(
2261
+ Button8,
2262
+ {
2263
+ variant: "outline",
2264
+ disabled: page === 1,
2265
+ onClick: () => setPage(page - 1),
2266
+ children: "Previous"
2267
+ }
2268
+ ),
2269
+ /* @__PURE__ */ jsxs17("span", { className: "text-sm text-muted-foreground", children: [
2270
+ "Page ",
2271
+ page
2272
+ ] }),
2273
+ /* @__PURE__ */ jsx19(Button8, { variant: "outline", onClick: () => setPage(page + 1), children: "Next" })
2274
+ ] })
2275
+ ] });
2276
+ }
2277
+
2278
+ // src/components/iam/roles/roles-page.tsx
2279
+ import { Badge as Badge2 } from "@mesob/ui/components/badge";
2280
+ import { Button as Button9 } from "@mesob/ui/components/button";
2281
+ import { useState as useState13 } from "react";
2282
+ import { jsx as jsx20, jsxs as jsxs18 } from "react/jsx-runtime";
2283
+ function RolesPage() {
2284
+ const { hooks } = useApi();
2285
+ const [page, setPage] = useState13(1);
2286
+ const limit = 20;
2287
+ const { data, isLoading, error } = hooks.useQuery("get", "/roles", {
2288
+ params: {
2289
+ query: {
2290
+ page: String(page),
2291
+ limit: String(limit)
2292
+ }
2293
+ }
2294
+ });
2295
+ const columns = [
2296
+ {
2297
+ key: "name",
2298
+ header: "Role",
2299
+ cell: (role) => /* @__PURE__ */ jsxs18("div", { children: [
2300
+ /* @__PURE__ */ jsx20("p", { className: "font-medium", children: role.name }),
2301
+ /* @__PURE__ */ jsx20(Badge2, { variant: "outline", className: "mt-1", children: role.code })
2302
+ ] })
2303
+ },
2304
+ {
2305
+ key: "description",
2306
+ header: "Description",
2307
+ cell: (role) => /* @__PURE__ */ jsx20("p", { className: "text-sm text-muted-foreground", children: role.description })
2308
+ },
2309
+ {
2310
+ key: "createdAt",
2311
+ header: "Created",
2312
+ cell: (role) => /* @__PURE__ */ jsx20("p", { className: "text-sm", children: new Date(role.createdAt).toLocaleDateString() })
2313
+ },
2314
+ {
2315
+ key: "actions",
2316
+ header: "Actions",
2317
+ cell: (_role) => /* @__PURE__ */ jsxs18("div", { className: "flex gap-2", children: [
2318
+ /* @__PURE__ */ jsx20(Button9, { variant: "outline", size: "sm", children: "Permissions" }),
2319
+ /* @__PURE__ */ jsx20(Button9, { variant: "outline", size: "sm", children: "Edit" })
2320
+ ] })
2321
+ }
2322
+ ];
2323
+ if (error) {
2324
+ return /* @__PURE__ */ jsx20("div", { className: "p-6 text-center", children: /* @__PURE__ */ jsx20("p", { className: "text-destructive", children: "Error loading roles" }) });
2325
+ }
2326
+ return /* @__PURE__ */ jsxs18("div", { className: "w-full p-6 space-y-4", children: [
2327
+ /* @__PURE__ */ jsxs18("div", { className: "flex justify-between items-center", children: [
2328
+ /* @__PURE__ */ jsxs18("div", { children: [
2329
+ /* @__PURE__ */ jsx20("h1", { className: "text-3xl font-bold", children: "Roles" }),
2330
+ /* @__PURE__ */ jsx20("p", { className: "text-muted-foreground", children: "Manage user roles" })
2331
+ ] }),
2332
+ /* @__PURE__ */ jsx20(Button9, { children: "Create Role" })
2333
+ ] }),
2334
+ /* @__PURE__ */ jsx20(
2335
+ DataTable,
2336
+ {
2337
+ data: data?.roles || [],
2338
+ columns,
2339
+ isLoading,
2340
+ emptyMessage: "No roles found"
2341
+ }
2342
+ ),
2343
+ data && "roles" in data && data.roles && data.roles.length >= limit && /* @__PURE__ */ jsxs18("div", { className: "flex justify-between items-center", children: [
2344
+ /* @__PURE__ */ jsx20(
2345
+ Button9,
2346
+ {
2347
+ variant: "outline",
2348
+ disabled: page === 1,
2349
+ onClick: () => setPage(page - 1),
2350
+ children: "Previous"
2351
+ }
2352
+ ),
2353
+ /* @__PURE__ */ jsxs18("span", { className: "text-sm text-muted-foreground", children: [
2354
+ "Page ",
2355
+ page
2356
+ ] }),
2357
+ /* @__PURE__ */ jsx20(Button9, { variant: "outline", onClick: () => setPage(page + 1), children: "Next" })
2358
+ ] })
2359
+ ] });
2360
+ }
1767
2361
 
1768
- // src/hooks/use-session.ts
1769
- var useSession = () => {
1770
- const { user, session, loading, error, refresh } = useAuth();
1771
- return {
1772
- user,
1773
- session,
1774
- isLoading: loading,
1775
- isAuthenticated: !!user && !!session,
1776
- error,
1777
- refresh
2362
+ // src/components/iam/sessions/sessions-page.tsx
2363
+ import { Button as Button10 } from "@mesob/ui/components/button";
2364
+ import { useState as useState14 } from "react";
2365
+ import { jsx as jsx21, jsxs as jsxs19 } from "react/jsx-runtime";
2366
+ function SessionsPage() {
2367
+ const { hooks } = useApi();
2368
+ const [selectedSessionId] = useState14(null);
2369
+ const { data, isLoading, error, refetch } = hooks.useQuery(
2370
+ "get",
2371
+ "/sessions"
2372
+ );
2373
+ const deleteMutation = hooks.useMutation("delete", "/sessions/{id}", {
2374
+ onSuccess: () => {
2375
+ refetch();
2376
+ }
2377
+ });
2378
+ const handleDeleteSession = async (sessionId) => {
2379
+ if (confirm("Are you sure you want to revoke this session?")) {
2380
+ try {
2381
+ await deleteMutation.mutateAsync({
2382
+ params: {
2383
+ path: { id: sessionId }
2384
+ }
2385
+ });
2386
+ } catch (_err) {
2387
+ }
2388
+ }
1778
2389
  };
2390
+ const columns = [
2391
+ {
2392
+ key: "createdAt",
2393
+ header: "Created",
2394
+ cell: (session) => /* @__PURE__ */ jsxs19("div", { children: [
2395
+ /* @__PURE__ */ jsx21("p", { className: "text-sm font-medium", children: new Date(session.createdAt).toLocaleDateString() }),
2396
+ /* @__PURE__ */ jsx21("p", { className: "text-xs text-muted-foreground", children: new Date(session.createdAt).toLocaleTimeString() })
2397
+ ] })
2398
+ },
2399
+ {
2400
+ key: "expiresAt",
2401
+ header: "Expires",
2402
+ cell: (session) => /* @__PURE__ */ jsx21("p", { className: "text-sm", children: new Date(session.expiresAt).toLocaleDateString() })
2403
+ },
2404
+ {
2405
+ key: "userAgent",
2406
+ header: "Device",
2407
+ cell: (session) => /* @__PURE__ */ jsx21("p", { className: "text-sm truncate max-w-xs", children: session.userAgent || "Unknown" })
2408
+ },
2409
+ {
2410
+ key: "ip",
2411
+ header: "IP Address",
2412
+ cell: (session) => /* @__PURE__ */ jsx21("p", { className: "text-sm font-mono", children: session.ip || "Unknown" })
2413
+ },
2414
+ {
2415
+ key: "actions",
2416
+ header: "Actions",
2417
+ cell: (session) => /* @__PURE__ */ jsx21(
2418
+ Button10,
2419
+ {
2420
+ variant: "destructive",
2421
+ size: "sm",
2422
+ onClick: () => handleDeleteSession(session.id),
2423
+ disabled: deleteMutation.isPending && selectedSessionId === session.id,
2424
+ children: deleteMutation.isPending && selectedSessionId === session.id ? "Revoking..." : "Revoke"
2425
+ }
2426
+ )
2427
+ }
2428
+ ];
2429
+ if (error) {
2430
+ return /* @__PURE__ */ jsx21("div", { className: "p-6 text-center", children: /* @__PURE__ */ jsx21("p", { className: "text-destructive", children: "Error loading sessions" }) });
2431
+ }
2432
+ return /* @__PURE__ */ jsxs19("div", { className: "w-full p-6 space-y-4", children: [
2433
+ /* @__PURE__ */ jsxs19("div", { children: [
2434
+ /* @__PURE__ */ jsx21("h1", { className: "text-3xl font-bold", children: "Sessions" }),
2435
+ /* @__PURE__ */ jsx21("p", { className: "text-muted-foreground", children: "View and manage active sessions" })
2436
+ ] }),
2437
+ /* @__PURE__ */ jsx21(
2438
+ DataTable,
2439
+ {
2440
+ data: data?.sessions || [],
2441
+ columns,
2442
+ isLoading,
2443
+ emptyMessage: "No active sessions"
2444
+ }
2445
+ )
2446
+ ] });
2447
+ }
2448
+
2449
+ // src/components/iam/tenants/tenants-page.tsx
2450
+ import { Badge as Badge3 } from "@mesob/ui/components/badge";
2451
+ import { Button as Button11 } from "@mesob/ui/components/button";
2452
+ import { useState as useState15 } from "react";
2453
+ import { jsx as jsx22, jsxs as jsxs20 } from "react/jsx-runtime";
2454
+ function TenantsPage() {
2455
+ const { hooks } = useApi();
2456
+ const [page, setPage] = useState15(1);
2457
+ const limit = 20;
2458
+ const { data, isLoading, error } = hooks.useQuery("get", "/tenants", {
2459
+ params: {
2460
+ query: {
2461
+ page: String(page),
2462
+ limit: String(limit)
2463
+ }
2464
+ }
2465
+ });
2466
+ const columns = [
2467
+ {
2468
+ key: "name",
2469
+ header: "Tenant",
2470
+ cell: (tenant) => /* @__PURE__ */ jsxs20("div", { children: [
2471
+ /* @__PURE__ */ jsx22("p", { className: "font-medium", children: tenant.name }),
2472
+ /* @__PURE__ */ jsxs20("p", { className: "text-sm text-muted-foreground", children: [
2473
+ "/",
2474
+ tenant.slug
2475
+ ] })
2476
+ ] })
2477
+ },
2478
+ {
2479
+ key: "status",
2480
+ header: "Status",
2481
+ cell: (tenant) => /* @__PURE__ */ jsx22(Badge3, { variant: tenant.status === "active" ? "default" : "secondary", children: tenant.status })
2482
+ },
2483
+ {
2484
+ key: "createdAt",
2485
+ header: "Created",
2486
+ cell: (tenant) => /* @__PURE__ */ jsx22("p", { className: "text-sm", children: new Date(tenant.createdAt).toLocaleDateString() })
2487
+ },
2488
+ {
2489
+ key: "actions",
2490
+ header: "Actions",
2491
+ cell: (_tenant) => /* @__PURE__ */ jsxs20("div", { className: "flex gap-2", children: [
2492
+ /* @__PURE__ */ jsx22(Button11, { variant: "outline", size: "sm", children: "Domains" }),
2493
+ /* @__PURE__ */ jsx22(Button11, { variant: "outline", size: "sm", children: "Edit" })
2494
+ ] })
2495
+ }
2496
+ ];
2497
+ if (error) {
2498
+ return /* @__PURE__ */ jsx22("div", { className: "p-6 text-center", children: /* @__PURE__ */ jsx22("p", { className: "text-destructive", children: "Error loading tenants" }) });
2499
+ }
2500
+ return /* @__PURE__ */ jsxs20("div", { className: "w-full p-6 space-y-4", children: [
2501
+ /* @__PURE__ */ jsxs20("div", { className: "flex justify-between items-center", children: [
2502
+ /* @__PURE__ */ jsxs20("div", { children: [
2503
+ /* @__PURE__ */ jsx22("h1", { className: "text-3xl font-bold", children: "Tenants" }),
2504
+ /* @__PURE__ */ jsx22("p", { className: "text-muted-foreground", children: "Manage tenant organizations" })
2505
+ ] }),
2506
+ /* @__PURE__ */ jsx22(Button11, { children: "Create Tenant" })
2507
+ ] }),
2508
+ /* @__PURE__ */ jsx22(
2509
+ DataTable,
2510
+ {
2511
+ data: data?.tenants || [],
2512
+ columns,
2513
+ isLoading,
2514
+ emptyMessage: "No tenants found"
2515
+ }
2516
+ ),
2517
+ data && "tenants" in data && data.tenants && data.tenants.length >= limit && /* @__PURE__ */ jsxs20("div", { className: "flex justify-between items-center", children: [
2518
+ /* @__PURE__ */ jsx22(
2519
+ Button11,
2520
+ {
2521
+ variant: "outline",
2522
+ disabled: page === 1,
2523
+ onClick: () => setPage(page - 1),
2524
+ children: "Previous"
2525
+ }
2526
+ ),
2527
+ /* @__PURE__ */ jsxs20("span", { className: "text-sm text-muted-foreground", children: [
2528
+ "Page ",
2529
+ page
2530
+ ] }),
2531
+ /* @__PURE__ */ jsx22(Button11, { variant: "outline", onClick: () => setPage(page + 1), children: "Next" })
2532
+ ] })
2533
+ ] });
2534
+ }
2535
+
2536
+ // src/components/iam/users/users-page.tsx
2537
+ import { Badge as Badge4 } from "@mesob/ui/components/badge";
2538
+ import { Button as Button12 } from "@mesob/ui/components/button";
2539
+ import { useState as useState16 } from "react";
2540
+ import { jsx as jsx23, jsxs as jsxs21 } from "react/jsx-runtime";
2541
+ function UsersPage() {
2542
+ const { hooks } = useApi();
2543
+ const [page, setPage] = useState16(1);
2544
+ const limit = 20;
2545
+ const { data, isLoading, error } = hooks.useQuery("get", "/users", {
2546
+ params: {
2547
+ query: {
2548
+ page: String(page),
2549
+ limit: String(limit)
2550
+ }
2551
+ }
2552
+ });
2553
+ const columns = [
2554
+ {
2555
+ key: "fullName",
2556
+ header: "Name",
2557
+ cell: (user) => /* @__PURE__ */ jsxs21("div", { children: [
2558
+ /* @__PURE__ */ jsx23("p", { className: "font-medium", children: user.fullName }),
2559
+ /* @__PURE__ */ jsxs21("p", { className: "text-sm text-muted-foreground", children: [
2560
+ "@",
2561
+ user.handle
2562
+ ] })
2563
+ ] })
2564
+ },
2565
+ {
2566
+ key: "contact",
2567
+ header: "Contact",
2568
+ cell: (user) => /* @__PURE__ */ jsxs21("div", { className: "space-y-1", children: [
2569
+ user.email && /* @__PURE__ */ jsxs21("div", { className: "flex items-center gap-2", children: [
2570
+ /* @__PURE__ */ jsx23("p", { className: "text-sm", children: user.email }),
2571
+ user.emailVerified && /* @__PURE__ */ jsx23(Badge4, { variant: "outline", className: "text-xs", children: "Verified" })
2572
+ ] }),
2573
+ user.phone && /* @__PURE__ */ jsxs21("div", { className: "flex items-center gap-2", children: [
2574
+ /* @__PURE__ */ jsx23("p", { className: "text-sm", children: user.phone }),
2575
+ user.phoneVerified && /* @__PURE__ */ jsx23(Badge4, { variant: "outline", className: "text-xs", children: "Verified" })
2576
+ ] })
2577
+ ] })
2578
+ },
2579
+ {
2580
+ key: "lastSignIn",
2581
+ header: "Last Sign In",
2582
+ cell: (user) => /* @__PURE__ */ jsx23("p", { className: "text-sm", children: user.lastSignInAt ? new Date(user.lastSignInAt).toLocaleDateString() : "Never" })
2583
+ },
2584
+ {
2585
+ key: "actions",
2586
+ header: "Actions",
2587
+ cell: (_user) => /* @__PURE__ */ jsxs21("div", { className: "flex gap-2", children: [
2588
+ /* @__PURE__ */ jsx23(Button12, { variant: "outline", size: "sm", children: "View" }),
2589
+ /* @__PURE__ */ jsx23(Button12, { variant: "outline", size: "sm", children: "Edit" })
2590
+ ] })
2591
+ }
2592
+ ];
2593
+ if (error) {
2594
+ return /* @__PURE__ */ jsx23("div", { className: "p-6 text-center", children: /* @__PURE__ */ jsx23("p", { className: "text-destructive", children: "Error loading users" }) });
2595
+ }
2596
+ return /* @__PURE__ */ jsxs21("div", { className: "w-full p-6 space-y-4", children: [
2597
+ /* @__PURE__ */ jsxs21("div", { className: "flex justify-between items-center", children: [
2598
+ /* @__PURE__ */ jsxs21("div", { children: [
2599
+ /* @__PURE__ */ jsx23("h1", { className: "text-3xl font-bold", children: "Users" }),
2600
+ /* @__PURE__ */ jsx23("p", { className: "text-muted-foreground", children: "Manage user accounts" })
2601
+ ] }),
2602
+ /* @__PURE__ */ jsx23(Button12, { children: "Create User" })
2603
+ ] }),
2604
+ /* @__PURE__ */ jsx23(
2605
+ DataTable,
2606
+ {
2607
+ data: data?.users || [],
2608
+ columns,
2609
+ isLoading,
2610
+ emptyMessage: "No users found"
2611
+ }
2612
+ ),
2613
+ data && "users" in data && data.users && data.users.length >= limit && /* @__PURE__ */ jsxs21("div", { className: "flex justify-between items-center", children: [
2614
+ /* @__PURE__ */ jsx23(
2615
+ Button12,
2616
+ {
2617
+ variant: "outline",
2618
+ disabled: page === 1,
2619
+ onClick: () => setPage(page - 1),
2620
+ children: "Previous"
2621
+ }
2622
+ ),
2623
+ /* @__PURE__ */ jsxs21("span", { className: "text-sm text-muted-foreground", children: [
2624
+ "Page ",
2625
+ page
2626
+ ] }),
2627
+ /* @__PURE__ */ jsx23(Button12, { variant: "outline", onClick: () => setPage(page + 1), children: "Next" })
2628
+ ] })
2629
+ ] });
2630
+ }
2631
+
2632
+ // src/components/profile/profile-page.tsx
2633
+ import { Button as Button13 } from "@mesob/ui/components/button";
2634
+ import {
2635
+ Card,
2636
+ CardContent,
2637
+ CardDescription,
2638
+ CardHeader,
2639
+ CardTitle
2640
+ } from "@mesob/ui/components/card";
2641
+ import { Separator } from "@mesob/ui/components/separator";
2642
+
2643
+ // src/components/skeletons/profile-skeleton.tsx
2644
+ import { Skeleton as Skeleton2 } from "@mesob/ui/components/skeleton";
2645
+ import { jsx as jsx24, jsxs as jsxs22 } from "react/jsx-runtime";
2646
+ function ProfileSkeleton() {
2647
+ return /* @__PURE__ */ jsxs22("div", { className: "w-full max-w-4xl space-y-8 p-6", children: [
2648
+ /* @__PURE__ */ jsxs22("div", { className: "flex items-center gap-6", children: [
2649
+ /* @__PURE__ */ jsx24(Skeleton2, { className: "h-24 w-24 rounded-full" }),
2650
+ /* @__PURE__ */ jsxs22("div", { className: "space-y-2 flex-1", children: [
2651
+ /* @__PURE__ */ jsx24(Skeleton2, { className: "h-8 w-48" }),
2652
+ /* @__PURE__ */ jsx24(Skeleton2, { className: "h-4 w-64" })
2653
+ ] })
2654
+ ] }),
2655
+ /* @__PURE__ */ jsx24("div", { className: "space-y-6", children: [1, 2, 3].map((i) => /* @__PURE__ */ jsxs22("div", { className: "space-y-4", children: [
2656
+ /* @__PURE__ */ jsx24(Skeleton2, { className: "h-6 w-32" }),
2657
+ /* @__PURE__ */ jsxs22("div", { className: "space-y-3", children: [
2658
+ /* @__PURE__ */ jsxs22("div", { className: "flex justify-between items-center", children: [
2659
+ /* @__PURE__ */ jsx24(Skeleton2, { className: "h-4 w-24" }),
2660
+ /* @__PURE__ */ jsx24(Skeleton2, { className: "h-4 w-32" })
2661
+ ] }),
2662
+ /* @__PURE__ */ jsxs22("div", { className: "flex justify-between items-center", children: [
2663
+ /* @__PURE__ */ jsx24(Skeleton2, { className: "h-4 w-24" }),
2664
+ /* @__PURE__ */ jsx24(Skeleton2, { className: "h-4 w-40" })
2665
+ ] })
2666
+ ] })
2667
+ ] }, i)) })
2668
+ ] });
2669
+ }
2670
+
2671
+ // src/components/profile/profile-page.tsx
2672
+ import { jsx as jsx25, jsxs as jsxs23 } from "react/jsx-runtime";
2673
+ function ProfilePage({ onEditClick }) {
2674
+ const { user, isLoading } = useSession();
2675
+ if (isLoading) {
2676
+ return /* @__PURE__ */ jsx25(ProfileSkeleton, {});
2677
+ }
2678
+ if (!user) {
2679
+ return /* @__PURE__ */ jsx25("div", { className: "flex items-center justify-center min-h-[400px]", children: /* @__PURE__ */ jsx25("p", { className: "text-muted-foreground", children: "Not authenticated" }) });
2680
+ }
2681
+ return /* @__PURE__ */ jsxs23("div", { className: "w-full max-w-4xl mx-auto space-y-6 p-6", children: [
2682
+ /* @__PURE__ */ jsxs23("div", { className: "flex items-center justify-between", children: [
2683
+ /* @__PURE__ */ jsxs23("div", { children: [
2684
+ /* @__PURE__ */ jsx25("h1", { className: "text-3xl font-bold", children: user.fullName }),
2685
+ /* @__PURE__ */ jsxs23("p", { className: "text-muted-foreground", children: [
2686
+ "@",
2687
+ user.handle
2688
+ ] })
2689
+ ] }),
2690
+ onEditClick && /* @__PURE__ */ jsx25(Button13, { onClick: onEditClick, children: "Edit Profile" })
2691
+ ] }),
2692
+ /* @__PURE__ */ jsx25(Separator, {}),
2693
+ /* @__PURE__ */ jsxs23("div", { className: "grid gap-6 md:grid-cols-2", children: [
2694
+ /* @__PURE__ */ jsxs23(Card, { children: [
2695
+ /* @__PURE__ */ jsxs23(CardHeader, { children: [
2696
+ /* @__PURE__ */ jsx25(CardTitle, { children: "Contact Information" }),
2697
+ /* @__PURE__ */ jsx25(CardDescription, { children: "Your contact details" })
2698
+ ] }),
2699
+ /* @__PURE__ */ jsxs23(CardContent, { className: "space-y-4", children: [
2700
+ /* @__PURE__ */ jsxs23("div", { children: [
2701
+ /* @__PURE__ */ jsx25("p", { className: "text-sm font-medium text-muted-foreground", children: "Email" }),
2702
+ /* @__PURE__ */ jsxs23("p", { className: "text-sm", children: [
2703
+ user.email || "Not provided",
2704
+ user.email && /* @__PURE__ */ jsx25(
2705
+ "span",
2706
+ {
2707
+ className: user.emailVerified ? "text-green-600 ml-2" : "text-yellow-600 ml-2",
2708
+ children: user.emailVerified ? "(Verified)" : "(Not verified)"
2709
+ }
2710
+ )
2711
+ ] })
2712
+ ] }),
2713
+ /* @__PURE__ */ jsxs23("div", { children: [
2714
+ /* @__PURE__ */ jsx25("p", { className: "text-sm font-medium text-muted-foreground", children: "Phone" }),
2715
+ /* @__PURE__ */ jsxs23("p", { className: "text-sm", children: [
2716
+ user.phone || "Not provided",
2717
+ user.phone && /* @__PURE__ */ jsx25(
2718
+ "span",
2719
+ {
2720
+ className: user.phoneVerified ? "text-green-600 ml-2" : "text-yellow-600 ml-2",
2721
+ children: user.phoneVerified ? "(Verified)" : "(Not verified)"
2722
+ }
2723
+ )
2724
+ ] })
2725
+ ] })
2726
+ ] })
2727
+ ] }),
2728
+ /* @__PURE__ */ jsxs23(Card, { children: [
2729
+ /* @__PURE__ */ jsxs23(CardHeader, { children: [
2730
+ /* @__PURE__ */ jsx25(CardTitle, { children: "Account Information" }),
2731
+ /* @__PURE__ */ jsx25(CardDescription, { children: "Your account details" })
2732
+ ] }),
2733
+ /* @__PURE__ */ jsxs23(CardContent, { className: "space-y-4", children: [
2734
+ /* @__PURE__ */ jsxs23("div", { children: [
2735
+ /* @__PURE__ */ jsx25("p", { className: "text-sm font-medium text-muted-foreground", children: "Tenant ID" }),
2736
+ /* @__PURE__ */ jsx25("p", { className: "text-sm font-mono", children: user.tenantId })
2737
+ ] }),
2738
+ /* @__PURE__ */ jsxs23("div", { children: [
2739
+ /* @__PURE__ */ jsx25("p", { className: "text-sm font-medium text-muted-foreground", children: "Last Sign In" }),
2740
+ /* @__PURE__ */ jsx25("p", { className: "text-sm", children: user.lastSignInAt ? new Date(user.lastSignInAt).toLocaleString() : "Never" })
2741
+ ] })
2742
+ ] })
2743
+ ] }),
2744
+ user.userRoles && user.userRoles.length > 0 && /* @__PURE__ */ jsxs23(Card, { className: "md:col-span-2", children: [
2745
+ /* @__PURE__ */ jsxs23(CardHeader, { children: [
2746
+ /* @__PURE__ */ jsx25(CardTitle, { children: "Roles" }),
2747
+ /* @__PURE__ */ jsx25(CardDescription, { children: "Your assigned roles" })
2748
+ ] }),
2749
+ /* @__PURE__ */ jsx25(CardContent, { children: /* @__PURE__ */ jsx25("div", { className: "flex flex-wrap gap-2", children: user.userRoles.map((role) => /* @__PURE__ */ jsx25(
2750
+ "div",
2751
+ {
2752
+ className: "px-3 py-1 bg-primary/10 text-primary rounded-full text-sm",
2753
+ children: role.name
2754
+ },
2755
+ role.id
2756
+ )) }) })
2757
+ ] })
2758
+ ] })
2759
+ ] });
2760
+ }
2761
+
2762
+ // src/components/skeletons/auth-form-skeleton.tsx
2763
+ import { Skeleton as Skeleton3 } from "@mesob/ui/components/skeleton";
2764
+ import { jsx as jsx26, jsxs as jsxs24 } from "react/jsx-runtime";
2765
+ function AuthFormSkeleton() {
2766
+ return /* @__PURE__ */ jsxs24("div", { className: "w-full max-w-md space-y-6 p-6", children: [
2767
+ /* @__PURE__ */ jsxs24("div", { className: "space-y-2 text-center", children: [
2768
+ /* @__PURE__ */ jsx26(Skeleton3, { className: "h-8 w-48 mx-auto" }),
2769
+ /* @__PURE__ */ jsx26(Skeleton3, { className: "h-4 w-64 mx-auto" })
2770
+ ] }),
2771
+ /* @__PURE__ */ jsxs24("div", { className: "space-y-4", children: [
2772
+ /* @__PURE__ */ jsxs24("div", { className: "space-y-2", children: [
2773
+ /* @__PURE__ */ jsx26(Skeleton3, { className: "h-4 w-24" }),
2774
+ /* @__PURE__ */ jsx26(Skeleton3, { className: "h-10 w-full" })
2775
+ ] }),
2776
+ /* @__PURE__ */ jsxs24("div", { className: "space-y-2", children: [
2777
+ /* @__PURE__ */ jsx26(Skeleton3, { className: "h-4 w-24" }),
2778
+ /* @__PURE__ */ jsx26(Skeleton3, { className: "h-10 w-full" })
2779
+ ] }),
2780
+ /* @__PURE__ */ jsx26(Skeleton3, { className: "h-10 w-full" })
2781
+ ] }),
2782
+ /* @__PURE__ */ jsxs24("div", { className: "space-y-2", children: [
2783
+ /* @__PURE__ */ jsx26(Skeleton3, { className: "h-px w-full" }),
2784
+ /* @__PURE__ */ jsx26(Skeleton3, { className: "h-4 w-32 mx-auto" })
2785
+ ] })
2786
+ ] });
2787
+ }
2788
+
2789
+ // src/utils/cookie.ts
2790
+ var isProduction = typeof process !== "undefined" && process.env.NODE_ENV === "production";
2791
+ var getSessionCookieName = (config) => {
2792
+ const prefix = config.cookiePrefix || "";
2793
+ const baseName = "session_token";
2794
+ if (prefix) {
2795
+ return `${prefix}_${baseName}`;
2796
+ }
2797
+ return isProduction ? "__Host-session_token" : baseName;
1779
2798
  };
2799
+
2800
+ // src/hooks/use-session-cookie-name.ts
2801
+ function useSessionCookieName() {
2802
+ const { config } = useConfig();
2803
+ return getSessionCookieName(config);
2804
+ }
1780
2805
  export {
1781
2806
  AuthCard,
1782
- AuthClient,
1783
- AuthPageLayout,
1784
- AuthProvider,
1785
- Countdown,
1786
- ForgotPassword,
2807
+ AuthErrorBoundary,
2808
+ AuthFormSkeleton,
2809
+ DataTable,
2810
+ ErrorBoundary,
1787
2811
  ForgotPasswordPage,
1788
- ResetPasswordForm,
2812
+ MesobAuthProvider,
2813
+ PermissionsPage,
2814
+ ProfilePage,
2815
+ ProfileSkeleton,
1789
2816
  ResetPasswordPage,
1790
- SignIn,
2817
+ RolesPage,
2818
+ SessionsPage,
1791
2819
  SignInPage,
1792
- SignUp,
1793
2820
  SignUpPage,
2821
+ TableSkeleton,
2822
+ TenantsPage,
2823
+ UsersPage,
1794
2824
  VerificationForm,
1795
2825
  VerifyEmailPage,
1796
2826
  VerifyPhonePage,
1797
- createAuthClient,
2827
+ getSessionCookieName,
2828
+ handleError,
1798
2829
  normalizePhone,
1799
- useAuth,
1800
- useSession
2830
+ useApi,
2831
+ useConfig,
2832
+ useSession,
2833
+ useSessionCookieName,
2834
+ useTranslator
1801
2835
  };
1802
2836
  //# sourceMappingURL=index.js.map