@mesob/auth-react 0.5.8 → 0.5.10

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 (152) hide show
  1. package/dist/{chunk-YP5V56LW.js → chunk-22KICA5N.js} +3 -3
  2. package/dist/{chunk-XLPPZKU2.js → chunk-22WSB5V2.js} +15 -5
  3. package/dist/chunk-22WSB5V2.js.map +1 -0
  4. package/dist/{chunk-GQFTH5DQ.js → chunk-25DJGLNU.js} +12 -8
  5. package/dist/chunk-25DJGLNU.js.map +1 -0
  6. package/dist/{chunk-W2HMARW4.js → chunk-2BF2JIDK.js} +3 -3
  7. package/dist/{chunk-4LHFPVAY.js → chunk-4YPLJ2P6.js} +7 -13
  8. package/dist/chunk-4YPLJ2P6.js.map +1 -0
  9. package/dist/{chunk-SA6HTWCL.js → chunk-5FNUPWPO.js} +2 -2
  10. package/dist/{chunk-6AV6I5B4.js → chunk-75K2SCNC.js} +3 -3
  11. package/dist/{chunk-YCVDEX5U.js → chunk-7QJBDRTL.js} +6 -5
  12. package/dist/chunk-7QJBDRTL.js.map +1 -0
  13. package/dist/{chunk-FCPN2FD7.js → chunk-B7BS57X7.js} +10 -4
  14. package/dist/chunk-B7BS57X7.js.map +1 -0
  15. package/dist/{chunk-FLGP4ROM.js → chunk-CBR5NTFM.js} +14 -8
  16. package/dist/chunk-CBR5NTFM.js.map +1 -0
  17. package/dist/chunk-DBTKXQV7.js +13 -0
  18. package/dist/chunk-DBTKXQV7.js.map +1 -0
  19. package/dist/{chunk-PUOQX6DR.js → chunk-DQB4WY5T.js} +4 -4
  20. package/dist/{chunk-TPG4RW7H.js → chunk-DRAUYDZ5.js} +2 -2
  21. package/dist/{chunk-IBRB7ABJ.js → chunk-G2RWFKGF.js} +2 -2
  22. package/dist/{chunk-EIJFTUTM.js → chunk-GP4XI5KB.js} +3 -3
  23. package/dist/{chunk-22AQI2FA.js → chunk-GWRMQSME.js} +5 -5
  24. package/dist/{chunk-XO5LLEGV.js → chunk-HOROLWBY.js} +2 -2
  25. package/dist/{chunk-YVHMCTLM.js → chunk-I46PN4JU.js} +2 -2
  26. package/dist/{chunk-VS5FEGMX.js → chunk-IUCTHMVY.js} +2 -2
  27. package/dist/{chunk-IFFWIROT.js → chunk-J7NROVB4.js} +2 -2
  28. package/dist/{chunk-FU4K62DS.js → chunk-KL2XZKDU.js} +2 -2
  29. package/dist/{chunk-VMAGFUOK.js → chunk-LI7WPOVY.js} +3 -3
  30. package/dist/{chunk-I34SXFQJ.js → chunk-LYCBL2W3.js} +4 -4
  31. package/dist/{chunk-A5ON3RKH.js → chunk-M2K6O5CN.js} +2 -2
  32. package/dist/chunk-M2K6O5CN.js.map +1 -0
  33. package/dist/{chunk-G4VPR4UC.js → chunk-M677DPBR.js} +2 -2
  34. package/dist/{chunk-BX75EFF3.js → chunk-MPZAPUVR.js} +4 -4
  35. package/dist/{chunk-V7HCZDJ4.js → chunk-NJGVOQIU.js} +4 -4
  36. package/dist/{chunk-HBQK5PAH.js → chunk-NPA7L57G.js} +2 -2
  37. package/dist/{chunk-TAJQ7O3U.js → chunk-ORQZZUVL.js} +2 -2
  38. package/dist/{chunk-5B6GREDA.js → chunk-OT2H5EHA.js} +2 -2
  39. package/dist/{chunk-NTDVUVZO.js → chunk-QNPK2H5A.js} +3 -3
  40. package/dist/{chunk-MDM3QYPM.js → chunk-QRYUUXNJ.js} +7 -6
  41. package/dist/chunk-QRYUUXNJ.js.map +1 -0
  42. package/dist/{chunk-Z4FXOZEJ.js → chunk-R7VVXH5U.js} +3 -3
  43. package/dist/{chunk-3GFTD46V.js → chunk-SLIIENXJ.js} +2 -2
  44. package/dist/{chunk-VWYJI2FU.js → chunk-TT3V6PC7.js} +4 -4
  45. package/dist/{chunk-ZOKBN5H4.js → chunk-UIXR5GF3.js} +2 -2
  46. package/dist/{chunk-XZAYLXLS.js → chunk-UV7JR3YU.js} +2 -2
  47. package/dist/{chunk-SX6WAVQS.js → chunk-VTANFZKG.js} +5 -5
  48. package/dist/{chunk-5XCUGCW7.js → chunk-VWGOCWRF.js} +9 -6
  49. package/dist/chunk-VWGOCWRF.js.map +1 -0
  50. package/dist/{chunk-WOJ3HM5R.js → chunk-WAMZL5CS.js} +4 -4
  51. package/dist/{chunk-DCWKYK3D.js → chunk-WY2F7475.js} +18 -10
  52. package/dist/chunk-WY2F7475.js.map +1 -0
  53. package/dist/{chunk-OMTV6IOB.js → chunk-XTLFZ77E.js} +2 -2
  54. package/dist/chunk-XTLFZ77E.js.map +1 -0
  55. package/dist/{chunk-H2W42KYL.js → chunk-Y6KURGWG.js} +2 -2
  56. package/dist/chunk-YR6SS2CC.js +11 -0
  57. package/dist/chunk-YR6SS2CC.js.map +1 -0
  58. package/dist/{chunk-BM3YKYGC.js → chunk-ZIUAYN37.js} +2 -2
  59. package/dist/components/auth/countdown.js +3 -3
  60. package/dist/components/auth/forgot-password.js +5 -3
  61. package/dist/components/auth/reset-password-form.js +3 -3
  62. package/dist/components/auth/set-password.js +5 -4
  63. package/dist/components/auth/sign-in.js +5 -4
  64. package/dist/components/auth/sign-up.js +5 -3
  65. package/dist/components/auth/verification-form.js +4 -4
  66. package/dist/components/auth/verify-email.js +5 -5
  67. package/dist/components/auth/verify-phone.js +5 -5
  68. package/dist/components/authorization/deny.js +2 -2
  69. package/dist/components/authorization/grant.js +2 -2
  70. package/dist/components/iam/domains-page.js +6 -6
  71. package/dist/components/iam/iam-guard.js +3 -3
  72. package/dist/components/iam/permission-selector.js +2 -2
  73. package/dist/components/iam/permissions-page.js +4 -4
  74. package/dist/components/iam/permissions.js +2 -2
  75. package/dist/components/iam/role-detail-layout.js +2 -2
  76. package/dist/components/iam/role-detail-page.js +4 -4
  77. package/dist/components/iam/role-permissions-page.js +5 -5
  78. package/dist/components/iam/roles-page.js +6 -6
  79. package/dist/components/iam/roles.js +2 -2
  80. package/dist/components/iam/sessions-page.js +6 -6
  81. package/dist/components/iam/sessions.js +2 -2
  82. package/dist/components/iam/tenants-page.js +6 -6
  83. package/dist/components/iam/tenants.js +2 -2
  84. package/dist/components/iam/users-page.js +7 -7
  85. package/dist/components/iam/users.js +2 -2
  86. package/dist/components/profile/account.js +2 -2
  87. package/dist/components/profile/change-email-form.js +8 -8
  88. package/dist/components/profile/change-password-form.js +2 -2
  89. package/dist/components/profile/change-phone-form.js +9 -9
  90. package/dist/components/profile/otp-verification-modal.js +5 -5
  91. package/dist/components/profile/profile-layout.js +3 -3
  92. package/dist/components/profile/request-change-email-form.js +2 -2
  93. package/dist/components/profile/request-change-phone-form.js +3 -3
  94. package/dist/components/profile/security.js +14 -14
  95. package/dist/components/profile/verify-change-email-form.js +6 -6
  96. package/dist/components/profile/verify-change-phone-form.js +6 -6
  97. package/dist/index.d.ts +1 -0
  98. package/dist/index.js +48 -44
  99. package/dist/index.js.map +1 -1
  100. package/dist/pages/auth/layout.js +1 -1
  101. package/dist/pages/iam/tenants/tenant-selector.js +3 -3
  102. package/dist/pages/iam/users/user-selector.js +4 -4
  103. package/dist/pages/profile/account.js +1 -1
  104. package/dist/pages/profile/security.js +1 -1
  105. package/dist/utils/normalize-email.d.ts +2 -0
  106. package/dist/utils/normalize-phone.d.ts +1 -0
  107. package/package.json +4 -4
  108. package/dist/chunk-4LHFPVAY.js.map +0 -1
  109. package/dist/chunk-5XCUGCW7.js.map +0 -1
  110. package/dist/chunk-A5ON3RKH.js.map +0 -1
  111. package/dist/chunk-DCWKYK3D.js.map +0 -1
  112. package/dist/chunk-FCPN2FD7.js.map +0 -1
  113. package/dist/chunk-FLGP4ROM.js.map +0 -1
  114. package/dist/chunk-GQFTH5DQ.js.map +0 -1
  115. package/dist/chunk-MDM3QYPM.js.map +0 -1
  116. package/dist/chunk-OMTV6IOB.js.map +0 -1
  117. package/dist/chunk-V2W3WPCZ.js +0 -22
  118. package/dist/chunk-V2W3WPCZ.js.map +0 -1
  119. package/dist/chunk-XLPPZKU2.js.map +0 -1
  120. package/dist/chunk-YCVDEX5U.js.map +0 -1
  121. /package/dist/{chunk-YP5V56LW.js.map → chunk-22KICA5N.js.map} +0 -0
  122. /package/dist/{chunk-W2HMARW4.js.map → chunk-2BF2JIDK.js.map} +0 -0
  123. /package/dist/{chunk-SA6HTWCL.js.map → chunk-5FNUPWPO.js.map} +0 -0
  124. /package/dist/{chunk-6AV6I5B4.js.map → chunk-75K2SCNC.js.map} +0 -0
  125. /package/dist/{chunk-PUOQX6DR.js.map → chunk-DQB4WY5T.js.map} +0 -0
  126. /package/dist/{chunk-TPG4RW7H.js.map → chunk-DRAUYDZ5.js.map} +0 -0
  127. /package/dist/{chunk-IBRB7ABJ.js.map → chunk-G2RWFKGF.js.map} +0 -0
  128. /package/dist/{chunk-EIJFTUTM.js.map → chunk-GP4XI5KB.js.map} +0 -0
  129. /package/dist/{chunk-22AQI2FA.js.map → chunk-GWRMQSME.js.map} +0 -0
  130. /package/dist/{chunk-XO5LLEGV.js.map → chunk-HOROLWBY.js.map} +0 -0
  131. /package/dist/{chunk-YVHMCTLM.js.map → chunk-I46PN4JU.js.map} +0 -0
  132. /package/dist/{chunk-VS5FEGMX.js.map → chunk-IUCTHMVY.js.map} +0 -0
  133. /package/dist/{chunk-IFFWIROT.js.map → chunk-J7NROVB4.js.map} +0 -0
  134. /package/dist/{chunk-FU4K62DS.js.map → chunk-KL2XZKDU.js.map} +0 -0
  135. /package/dist/{chunk-VMAGFUOK.js.map → chunk-LI7WPOVY.js.map} +0 -0
  136. /package/dist/{chunk-I34SXFQJ.js.map → chunk-LYCBL2W3.js.map} +0 -0
  137. /package/dist/{chunk-G4VPR4UC.js.map → chunk-M677DPBR.js.map} +0 -0
  138. /package/dist/{chunk-BX75EFF3.js.map → chunk-MPZAPUVR.js.map} +0 -0
  139. /package/dist/{chunk-V7HCZDJ4.js.map → chunk-NJGVOQIU.js.map} +0 -0
  140. /package/dist/{chunk-HBQK5PAH.js.map → chunk-NPA7L57G.js.map} +0 -0
  141. /package/dist/{chunk-TAJQ7O3U.js.map → chunk-ORQZZUVL.js.map} +0 -0
  142. /package/dist/{chunk-5B6GREDA.js.map → chunk-OT2H5EHA.js.map} +0 -0
  143. /package/dist/{chunk-NTDVUVZO.js.map → chunk-QNPK2H5A.js.map} +0 -0
  144. /package/dist/{chunk-Z4FXOZEJ.js.map → chunk-R7VVXH5U.js.map} +0 -0
  145. /package/dist/{chunk-3GFTD46V.js.map → chunk-SLIIENXJ.js.map} +0 -0
  146. /package/dist/{chunk-VWYJI2FU.js.map → chunk-TT3V6PC7.js.map} +0 -0
  147. /package/dist/{chunk-ZOKBN5H4.js.map → chunk-UIXR5GF3.js.map} +0 -0
  148. /package/dist/{chunk-XZAYLXLS.js.map → chunk-UV7JR3YU.js.map} +0 -0
  149. /package/dist/{chunk-SX6WAVQS.js.map → chunk-VTANFZKG.js.map} +0 -0
  150. /package/dist/{chunk-WOJ3HM5R.js.map → chunk-WAMZL5CS.js.map} +0 -0
  151. /package/dist/{chunk-H2W42KYL.js.map → chunk-Y6KURGWG.js.map} +0 -0
  152. /package/dist/{chunk-BM3YKYGC.js.map → chunk-ZIUAYN37.js.map} +0 -0
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  AppLink
3
- } from "./chunk-3GFTD46V.js";
3
+ } from "./chunk-SLIIENXJ.js";
4
4
  import {
5
5
  useSession
6
- } from "./chunk-A5ON3RKH.js";
6
+ } from "./chunk-M2K6O5CN.js";
7
7
 
8
8
  // src/pages/profile/_components/profile-sidebar.tsx
9
9
  import { Avatar, AvatarFallback, AvatarImage } from "@mesob/ui/components";
@@ -92,4 +92,4 @@ export {
92
92
  ProfileSidebar,
93
93
  ProfileLayout
94
94
  };
95
- //# sourceMappingURL=chunk-YP5V56LW.js.map
95
+ //# sourceMappingURL=chunk-22KICA5N.js.map
@@ -1,3 +1,9 @@
1
+ import {
2
+ normalizeEmail
3
+ } from "./chunk-YR6SS2CC.js";
4
+ import {
5
+ normalizePhone
6
+ } from "./chunk-DBTKXQV7.js";
1
7
  import {
2
8
  handleError
3
9
  } from "./chunk-W7UHDTBI.js";
@@ -6,11 +12,11 @@ import {
6
12
  } from "./chunk-DPH2PHK3.js";
7
13
  import {
8
14
  useTranslator
9
- } from "./chunk-HBQK5PAH.js";
15
+ } from "./chunk-NPA7L57G.js";
10
16
  import {
11
17
  useApi,
12
18
  useConfig
13
- } from "./chunk-A5ON3RKH.js";
19
+ } from "./chunk-M2K6O5CN.js";
14
20
 
15
21
  // src/components/auth/forgot-password.tsx
16
22
  import { zodResolver } from "@hookform/resolvers/zod";
@@ -53,6 +59,7 @@ var ForgotPassword = () => {
53
59
  }
54
60
  });
55
61
  const logoImage = config.ui.logoImage;
62
+ const phoneRegex = typeof config.phoneRegex === "string" ? new RegExp(config.phoneRegex) : config.phoneRegex || /^\+251[79]\d{8}$/;
56
63
  const form = useForm({
57
64
  resolver: zodResolver(forgotPasswordSchema(t)),
58
65
  defaultValues: {
@@ -70,16 +77,19 @@ var ForgotPassword = () => {
70
77
  setIsLoading(true);
71
78
  setError(null);
72
79
  try {
80
+ const raw = values.account.trim();
81
+ const asPhone = normalizePhone(raw);
82
+ const identifier = phoneRegex.test(asPhone) ? asPhone : normalizeEmail(raw);
73
83
  const res = await forgotPasswordMutation.mutateAsync({
74
84
  body: {
75
- identifier: values.account
85
+ identifier
76
86
  }
77
87
  });
78
88
  if ("verificationId" in res && res.verificationId) {
79
89
  onNavigate(`/auth/reset-password?verificationId=${res.verificationId}`);
80
90
  } else {
81
91
  onNavigate(
82
- `/auth/reset-password?identifier=${encodeURIComponent(values.account)}`
92
+ `/auth/reset-password?identifier=${encodeURIComponent(identifier)}`
83
93
  );
84
94
  }
85
95
  } catch (err) {
@@ -161,4 +171,4 @@ var ForgotPassword = () => {
161
171
  export {
162
172
  ForgotPassword
163
173
  };
164
- //# sourceMappingURL=chunk-XLPPZKU2.js.map
174
+ //# sourceMappingURL=chunk-22WSB5V2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/auth/forgot-password.tsx"],"sourcesContent":["'use client';\n\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport {\n Alert,\n AlertDescription,\n AlertTitle,\n Button,\n Form,\n FormControl,\n FormField,\n FormItem,\n FormLabel,\n FormMessage,\n Input,\n} from '@mesob/ui/components';\nimport { useMesob } from '@mesob/ui/providers';\nimport { IconAlertCircle } from '@tabler/icons-react';\nimport { useEffect, useState } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { toast } from 'sonner';\nimport { z } from 'zod';\nimport { useTranslator } from '../../hooks/use-translator';\nimport { useApi, useConfig } from '../../provider';\nimport type { AuthErrorContent } from '../../utils/handle-error';\nimport { handleError } from '../../utils/handle-error';\nimport { normalizeEmail } from '../../utils/normalize-email';\nimport { normalizePhone } from '../../utils/normalize-phone';\nimport { AuthLayout } from './auth-layout';\n\ntype ForgotPasswordFormValues = {\n account: string;\n};\n\nconst forgotPasswordSchema = (t: (key: string) => string) =>\n z.object({\n account: z.string().min(1, t('errors.accountRequired')),\n });\n\nexport const ForgotPassword = () => {\n const { hooks } = useApi();\n const { config } = useConfig();\n const mesob = useMesob();\n const t = useTranslator('Auth.forgotPassword');\n const Link = mesob?.navigation?.Link;\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<AuthErrorContent | null>(null);\n\n const forgotPasswordMutation = hooks.useMutation('post', '/password/forgot');\n\n const signInLink = config.navigation?.links?.signIn || '/auth/sign-in';\n const onNavigate =\n config.navigation?.onNavigate ||\n ((path: string) => {\n if (typeof window !== 'undefined') {\n window.location.href = path;\n }\n });\n const logoImage = config.ui.logoImage;\n const phoneRegex =\n typeof config.phoneRegex === 'string'\n ? new RegExp(config.phoneRegex)\n : config.phoneRegex || /^\\+251[79]\\d{8}$/;\n\n const form = useForm<ForgotPasswordFormValues>({\n resolver: zodResolver(forgotPasswordSchema(t)),\n defaultValues: {\n account: '',\n },\n });\n\n useEffect(() => {\n if (error) {\n toast.error(error.title || 'Error', {\n description: error.description,\n });\n }\n }, [error]);\n\n const handleSubmit = form.handleSubmit(async (values) => {\n setIsLoading(true);\n setError(null);\n\n try {\n const raw = values.account.trim();\n const asPhone = normalizePhone(raw);\n const identifier = phoneRegex.test(asPhone)\n ? asPhone\n : normalizeEmail(raw);\n const res = await forgotPasswordMutation.mutateAsync({\n body: {\n identifier,\n },\n });\n\n if ('verificationId' in res && res.verificationId) {\n onNavigate(`/auth/reset-password?verificationId=${res.verificationId}`);\n } else {\n onNavigate(\n `/auth/reset-password?identifier=${encodeURIComponent(identifier)}`,\n );\n }\n } catch (err) {\n handleError(err, setError, t);\n } finally {\n setIsLoading(false);\n }\n });\n\n let errorContent: AuthErrorContent | null = null;\n if (error) {\n if (typeof error === 'string') {\n errorContent = { title: 'Error', description: error };\n } else {\n errorContent = error;\n }\n }\n\n return (\n <AuthLayout\n title={config.ui.name}\n description={t('description')}\n logoImage={logoImage}\n footer={\n Link ? (\n <Link href={signInLink} className=\"text-primary hover:underline\">\n {t('footer.backToSignIn')}\n </Link>\n ) : (\n <a\n href={signInLink}\n onClick={(e) => {\n e.preventDefault();\n onNavigate(signInLink);\n }}\n className=\"text-primary hover:underline\"\n >\n {t('footer.backToSignIn')}\n </a>\n )\n }\n >\n <Form {...form}>\n <form\n id=\"forgot-password-form\"\n onSubmit={handleSubmit}\n className=\"space-y-4\"\n >\n <FormField\n control={form.control}\n name=\"account\"\n render={({ field }) => (\n <FormItem>\n <FormLabel>{t('form.accountLabel')}</FormLabel>\n <FormControl>\n <Input {...field} type=\"text\" />\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n <Button\n type=\"submit\"\n form=\"forgot-password-form\"\n className=\"w-full\"\n disabled={isLoading || forgotPasswordMutation.isPending}\n loading={isLoading || forgotPasswordMutation.isPending}\n >\n {isLoading || forgotPasswordMutation.isPending\n ? t('form.submitting')\n : t('form.submit')}\n </Button>\n </form>\n </Form>\n {errorContent && (\n <Alert variant=\"destructive\" className=\"mt-4\">\n <IconAlertCircle className=\"h-4 w-4\" />\n <AlertTitle>{errorContent.title}</AlertTitle>\n <AlertDescription>{errorContent.description}</AlertDescription>\n </Alert>\n )}\n </AuthLayout>\n );\n};\n"],"mappings":"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","names":[]}
@@ -1,6 +1,9 @@
1
+ import {
2
+ normalizeEmail
3
+ } from "./chunk-YR6SS2CC.js";
1
4
  import {
2
5
  normalizePhone
3
- } from "./chunk-V2W3WPCZ.js";
6
+ } from "./chunk-DBTKXQV7.js";
4
7
  import {
5
8
  handleError,
6
9
  normalizeOpenapiErrorBody
@@ -10,11 +13,11 @@ import {
10
13
  } from "./chunk-DPH2PHK3.js";
11
14
  import {
12
15
  useTranslator
13
- } from "./chunk-HBQK5PAH.js";
16
+ } from "./chunk-NPA7L57G.js";
14
17
  import {
15
18
  useApi,
16
19
  useConfig
17
- } from "./chunk-A5ON3RKH.js";
20
+ } from "./chunk-M2K6O5CN.js";
18
21
 
19
22
  // src/components/auth/sign-in.tsx
20
23
  import { zodResolver } from "@hookform/resolvers/zod";
@@ -70,8 +73,8 @@ function PasswordInput({ field, show, onToggle }) {
70
73
  }
71
74
  var signInSchema = (t, options) => z.object({
72
75
  username: z.string().trim().min(1, { message: t("errors.requiredField") }).superRefine((value, ctx) => {
73
- const emailInput = z.email().safeParse(value).success;
74
- const phoneInput = options.phoneRegex.test(value);
76
+ const emailInput = z.email().safeParse(normalizeEmail(value)).success;
77
+ const phoneInput = !emailInput && options.phoneRegex.test(normalizePhone(value));
75
78
  if (!(emailInput || phoneInput)) {
76
79
  ctx.addIssue({
77
80
  code: z.ZodIssueCode.custom,
@@ -112,7 +115,7 @@ var SignIn = ({ redirectUrl } = {}) => {
112
115
  const [isChecking, setIsChecking] = useState(false);
113
116
  const checkUserMutation = hooks.useMutation("post", "/check-account");
114
117
  const signInMutation = hooks.useMutation("post", "/sign-in");
115
- const phoneRegex = typeof config.phoneRegex === "string" ? new RegExp(config.phoneRegex) : config.phoneRegex || /^(\+2519|\+2517|2519|2517|09|07)\d{8}$/;
118
+ const phoneRegex = typeof config.phoneRegex === "string" ? new RegExp(config.phoneRegex) : config.phoneRegex || /^\+251[79]\d{8}$/;
116
119
  const allowEmailSignIn = config.features?.enableEmailSignIn !== false;
117
120
  const allowPhoneSignIn = config.features?.enablePhoneSignIn !== false;
118
121
  const enableSignup = config.features?.enableSignup !== false;
@@ -157,7 +160,8 @@ var SignIn = ({ redirectUrl } = {}) => {
157
160
  }
158
161
  setIsChecking(true);
159
162
  try {
160
- const normalizedUsername = phoneRegex.test(usernameValue) ? normalizePhone(usernameValue) : usernameValue;
163
+ const asPhone = normalizePhone(usernameValue);
164
+ const normalizedUsername = phoneRegex.test(asPhone) ? asPhone : normalizeEmail(usernameValue);
161
165
  const emailInput = z.email().safeParse(normalizedUsername).success;
162
166
  if (emailInput) {
163
167
  if (!allowEmailSignIn) {
@@ -425,4 +429,4 @@ var SignIn = ({ redirectUrl } = {}) => {
425
429
  export {
426
430
  SignIn
427
431
  };
428
- //# sourceMappingURL=chunk-GQFTH5DQ.js.map
432
+ //# sourceMappingURL=chunk-25DJGLNU.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/auth/sign-in.tsx"],"sourcesContent":["'use client';\n\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport {\n Alert,\n AlertDescription,\n AlertTitle,\n Button,\n Form,\n FormControl,\n FormField,\n FormItem,\n FormLabel,\n FormMessage,\n Input,\n useFormField,\n} from '@mesob/ui/components';\nimport { useMesob } from '@mesob/ui/providers';\nimport { IconAlertCircle, IconEye, IconEyeOff } from '@tabler/icons-react';\nimport type { ChangeEvent, ComponentProps } from 'react';\nimport { useEffect, useState } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { toast } from 'sonner';\nimport { z } from 'zod';\nimport { useTranslator } from '../../hooks/use-translator';\nimport { useApi, useConfig } from '../../provider';\nimport type { AuthErrorContent } from '../../utils/handle-error';\nimport {\n handleError,\n normalizeOpenapiErrorBody,\n} from '../../utils/handle-error';\nimport { normalizeEmail } from '../../utils/normalize-email';\nimport { normalizePhone } from '../../utils/normalize-phone';\nimport { AuthLayout } from './auth-layout';\n\nconst isPhone = (s: string) => /^\\+?[0-9()[\\]\\s-]{6,}$/.test(s);\n\ntype PasswordInputProps = {\n field: ComponentProps<'input'> & {\n value: string;\n onChange: (e: ChangeEvent<HTMLInputElement>) => void;\n onBlur: () => void;\n };\n show: boolean;\n onToggle: () => void;\n};\n\nfunction PasswordInput({ field, show, onToggle }: PasswordInputProps) {\n const { formItemId, error } = useFormField();\n return (\n <div className=\"relative\">\n <Input\n {...field}\n id={formItemId}\n type={show ? 'text' : 'password'}\n autoComplete=\"current-password\"\n aria-invalid={!!error}\n className=\"pr-10\"\n />\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className=\"absolute right-0 top-0 h-full px-3 text-muted-foreground hover:text-foreground\"\n onClick={onToggle}\n aria-label={show ? 'Hide password' : 'Show password'}\n >\n {show ? (\n <IconEyeOff className=\"h-4 w-4\" />\n ) : (\n <IconEye className=\"h-4 w-4\" />\n )}\n </Button>\n </div>\n );\n}\n\ntype SignInProps = {\n redirectUrl?: string;\n};\n\ntype SignInValidationOptions = {\n phoneRegex: RegExp;\n allowEmailSignIn: boolean;\n allowPhoneSignIn: boolean;\n};\n\nconst signInSchema = (\n t: (key: string) => string,\n options: SignInValidationOptions,\n) =>\n z.object({\n username: z\n .string()\n .trim()\n .min(1, { message: t('errors.requiredField') })\n .superRefine((value, ctx) => {\n const emailInput = z.email().safeParse(normalizeEmail(value)).success;\n const phoneInput =\n !emailInput && options.phoneRegex.test(normalizePhone(value));\n if (!(emailInput || phoneInput)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: t('errors.invalidEmailOrPhone'),\n });\n return;\n }\n if (emailInput && !options.allowEmailSignIn) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: 'Email sign in is disabled',\n });\n return;\n }\n if (phoneInput && !options.allowPhoneSignIn) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: 'Phone sign in is disabled',\n });\n }\n }),\n password: z\n .union([\n z.literal(''),\n z\n .string()\n .min(8, t('errors.passwordLength'))\n .max(128, t('errors.longPasswordError')),\n ])\n .optional(),\n });\n\ntype SignInFormValues = z.infer<ReturnType<typeof signInSchema>>;\n\nexport const SignIn = ({ redirectUrl }: SignInProps = {}) => {\n const { hooks, setAuth } = useApi();\n const { config } = useConfig();\n const mesob = useMesob();\n const t = useTranslator('Auth.signIn');\n const Link = mesob?.navigation?.Link;\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<AuthErrorContent | null>(null);\n const [showPasswordField, setShowPasswordField] = useState(false);\n const [showPassword, setShowPassword] = useState(false);\n const [username, setUsername] = useState('');\n const [isChecking, setIsChecking] = useState(false);\n\n const checkUserMutation = hooks.useMutation('post', '/check-account');\n const signInMutation = hooks.useMutation('post', '/sign-in');\n\n const phoneRegex =\n typeof config.phoneRegex === 'string'\n ? new RegExp(config.phoneRegex)\n : config.phoneRegex || /^\\+251[79]\\d{8}$/;\n const allowEmailSignIn = config.features?.enableEmailSignIn !== false;\n const allowPhoneSignIn = config.features?.enablePhoneSignIn !== false;\n const enableSignup = config.features?.enableSignup !== false;\n const allowEmailSignup = config.features?.enableEmailSignup !== false;\n const allowPhoneSignup = config.features?.enablePhoneSignup !== false;\n const hasSignInIdentifierChannel = allowEmailSignIn || allowPhoneSignIn;\n\n const defaultRedirect =\n redirectUrl || config.navigation?.defaultRedirectUrl || '/';\n const forgotPasswordLink =\n config.navigation?.links?.forgotPassword || '/auth/forgot-password';\n const signUpLink = config.navigation?.links?.signUp || '/auth/sign-up';\n const setPasswordLink =\n config.navigation?.links?.setPassword || '/auth/set-password';\n const onNavigate =\n config.navigation?.onNavigate ||\n ((path: string) => {\n if (typeof window !== 'undefined') {\n window.location.href = path;\n }\n });\n const logoImage = config.ui.logoImage;\n\n const form = useForm<SignInFormValues>({\n resolver: zodResolver(\n signInSchema(t, {\n phoneRegex,\n allowEmailSignIn,\n allowPhoneSignIn,\n }),\n ),\n defaultValues: { username: '', password: '' },\n mode: 'onSubmit',\n reValidateMode: 'onSubmit',\n });\n\n useEffect(() => {\n if (error) {\n toast.error(error.title || 'Error', {\n description: error.description,\n });\n }\n }, [error]);\n\n const handleCheckAccount = async (usernameValue: string) => {\n if (!hasSignInIdentifierChannel) {\n form.setError('username', {\n message: 'Sign in is unavailable for email and phone',\n });\n return;\n }\n setIsChecking(true);\n try {\n const asPhone = normalizePhone(usernameValue);\n const normalizedUsername = phoneRegex.test(asPhone)\n ? asPhone\n : normalizeEmail(usernameValue);\n const emailInput = z.email().safeParse(normalizedUsername).success;\n if (emailInput) {\n if (!allowEmailSignIn) {\n form.setError('username', { message: 'Email sign in is disabled' });\n return;\n }\n } else if (!allowPhoneSignIn) {\n form.setError('username', { message: 'Phone sign in is disabled' });\n return;\n }\n\n const result = await checkUserMutation.mutateAsync({\n body: {\n username: normalizedUsername,\n },\n });\n\n if (result.exists) {\n if (result.requiresPasswordSetup) {\n const redirectParam = defaultRedirect\n ? `&redirect=${encodeURIComponent(defaultRedirect)}`\n : '';\n onNavigate(\n `${setPasswordLink}?identifier=${encodeURIComponent(normalizedUsername)}${redirectParam}`,\n );\n return;\n }\n\n if (\n !result.verified &&\n result.needsVerification &&\n result.verificationId\n ) {\n const redirectParam = defaultRedirect\n ? `&redirect=${encodeURIComponent(defaultRedirect)}`\n : '';\n const verifyPath = isPhone(normalizedUsername)\n ? `/auth/verify-phone?context=sign-in&verificationId=${result.verificationId}&identifier=${encodeURIComponent(normalizedUsername)}${redirectParam}`\n : `/auth/verify-email?verificationId=${result.verificationId}&email=${encodeURIComponent(normalizedUsername)}${redirectParam}`;\n onNavigate(verifyPath);\n return;\n }\n\n setUsername(normalizedUsername);\n form.setValue('username', normalizedUsername);\n setShowPasswordField(true);\n } else {\n if (!enableSignup) {\n form.setError('username', { message: 'Sign up is disabled' });\n return;\n }\n const email = isPhone(normalizedUsername) ? '' : normalizedUsername;\n if (email) {\n if (!allowEmailSignup) {\n form.setError('username', { message: 'Email sign up is disabled' });\n return;\n }\n } else if (!allowPhoneSignup) {\n form.setError('username', { message: 'Phone sign up is disabled' });\n return;\n }\n const redirectParam = defaultRedirect\n ? `&redirect=${encodeURIComponent(defaultRedirect)}`\n : '';\n if (email) {\n onNavigate(\n `${signUpLink}?email=${encodeURIComponent(email)}${redirectParam}`,\n );\n } else {\n onNavigate(\n `${signUpLink}?phone=${encodeURIComponent(normalizedUsername)}${redirectParam}`,\n );\n }\n }\n } catch (err) {\n if (normalizeOpenapiErrorBody(err)) {\n handleError(err, setError, t);\n } else {\n form.setError('username', { message: t('errors.checkAccountFailed') });\n }\n } finally {\n setIsChecking(false);\n }\n };\n\n const onSubmit = async (values: SignInFormValues) => {\n if (showPasswordField) {\n const pwd = values.password;\n if (!pwd || pwd.length < 8) {\n form.setError('password', { message: t('errors.passwordLength') });\n return;\n }\n await handlePasswordSubmit({ password: pwd });\n } else {\n await handleCheckAccount(values.username);\n }\n };\n\n const handlePasswordSubmit = async (values: { password: string }) => {\n setIsLoading(true);\n setError(null);\n\n try {\n const res = await signInMutation.mutateAsync({\n body: {\n identifier: username,\n password: values.password,\n },\n });\n\n if ('verificationId' in res && res.verificationId) {\n const redirectParam = defaultRedirect\n ? `&redirect=${encodeURIComponent(defaultRedirect)}`\n : '';\n const verifyPath = isPhone(username)\n ? `/auth/verify-phone?context=sign-in&verificationId=${res.verificationId}&identifier=${encodeURIComponent(username)}${redirectParam}`\n : `/auth/verify-email?verificationId=${res.verificationId}${redirectParam}`;\n onNavigate(verifyPath);\n return;\n }\n\n if ('user' in res && 'session' in res) {\n setAuth(res);\n }\n onNavigate(defaultRedirect);\n } catch (err) {\n const authError = err as { code?: string; message?: string };\n const errorCode = authError.code || authError.message;\n if (errorCode === 'HAS_NO_PASSWORD') {\n const redirectParam = defaultRedirect\n ? `&redirect=${encodeURIComponent(defaultRedirect)}`\n : '';\n onNavigate(\n `${setPasswordLink}?identifier=${encodeURIComponent(username)}${redirectParam}`,\n );\n return;\n }\n handleError(err, setError, t, { signIn: true });\n } finally {\n setIsLoading(false);\n }\n };\n\n const handleBack = () => {\n setShowPasswordField(false);\n setUsername('');\n form.setValue('password', '');\n };\n\n const isSubmitting =\n isLoading ||\n checkUserMutation.isPending ||\n signInMutation.isPending ||\n isChecking;\n\n let submitLabel = t('form.continue');\n if (isSubmitting) {\n submitLabel = showPasswordField ? t('form.submitting') : t('form.checking');\n } else if (showPasswordField) {\n submitLabel = t('form.submit');\n }\n\n let accountLabel = t('form.accountLabel');\n if (allowEmailSignIn && !allowPhoneSignIn) {\n accountLabel = 'Email';\n } else if (!allowEmailSignIn && allowPhoneSignIn) {\n accountLabel = 'Phone';\n }\n\n let errorContent: AuthErrorContent | null = null;\n if (error) {\n if (typeof error === 'string') {\n errorContent = { title: 'Error', description: error };\n } else {\n errorContent = error;\n }\n }\n\n const formContent = (\n <Form {...form}>\n <form\n id=\"sign-in-form\"\n autoComplete=\"on\"\n onSubmit={form.handleSubmit(onSubmit)}\n className=\"space-y-4\"\n >\n {showPasswordField ? (\n <>\n <FormItem>\n <FormLabel className=\"flex justify-between items-center\">\n {accountLabel}\n <Button\n type=\"button\"\n variant=\"link\"\n size=\"sm\"\n className=\"p-0 m-0 h-auto\"\n onClick={handleBack}\n >\n {t('changeAccount')}\n </Button>\n </FormLabel>\n <Input\n id=\"sign-in-username\"\n type=\"text\"\n value={username}\n autoComplete=\"username\"\n disabled\n />\n </FormItem>\n <FormField\n control={form.control}\n name=\"password\"\n render={({ field }) => (\n <FormItem>\n <FormLabel>{t('form.passwordLabel')}</FormLabel>\n <PasswordInput\n field={{ ...field, value: field.value ?? '' }}\n show={showPassword}\n onToggle={() => setShowPassword(!showPassword)}\n />\n <FormMessage />\n </FormItem>\n )}\n />\n </>\n ) : (\n <FormField\n control={form.control}\n name=\"username\"\n render={({ field }) => (\n <FormItem>\n <FormLabel>{accountLabel}</FormLabel>\n <FormControl>\n <Input\n {...field}\n type={\n allowEmailSignIn && !allowPhoneSignIn ? 'email' : 'text'\n }\n autoComplete={\n allowEmailSignIn && !allowPhoneSignIn\n ? 'email'\n : 'username'\n }\n />\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n )}\n <Button\n type=\"submit\"\n className=\"w-full\"\n disabled={isSubmitting}\n loading={isSubmitting}\n >\n {submitLabel}\n </Button>\n </form>\n </Form>\n );\n\n return (\n <div className=\"space-y-4\">\n <AuthLayout\n title={config.ui.name}\n description={t('description')}\n logoImage={logoImage}\n footer={\n showPasswordField ? (\n <div className=\"flex items-center justify-center w-full\">\n {Link ? (\n <Link\n href={forgotPasswordLink}\n className=\"text-primary inline-block hover:underline\"\n >\n {t('footer.forgotPassword')}\n </Link>\n ) : (\n <a\n href={forgotPasswordLink}\n onClick={(e) => {\n e.preventDefault();\n onNavigate(forgotPasswordLink);\n }}\n className=\"text-primary inline-block hover:underline\"\n >\n {t('footer.forgotPassword')}\n </a>\n )}\n </div>\n ) : undefined\n }\n >\n {formContent}\n {errorContent && (\n <Alert variant=\"destructive\" className=\"mt-4\">\n <IconAlertCircle className=\"h-4 w-4\" />\n <AlertTitle>{errorContent.title}</AlertTitle>\n <AlertDescription>{errorContent.description}</AlertDescription>\n </Alert>\n )}\n </AuthLayout>\n </div>\n );\n};\n"],"mappings":"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","names":[]}
@@ -6,11 +6,11 @@ import {
6
6
  } from "./chunk-DPH2PHK3.js";
7
7
  import {
8
8
  useTranslator
9
- } from "./chunk-HBQK5PAH.js";
9
+ } from "./chunk-NPA7L57G.js";
10
10
  import {
11
11
  useApi,
12
12
  useConfig
13
- } from "./chunk-A5ON3RKH.js";
13
+ } from "./chunk-M2K6O5CN.js";
14
14
 
15
15
  // src/components/auth/reset-password-form.tsx
16
16
  import { zodResolver } from "@hookform/resolvers/zod";
@@ -283,4 +283,4 @@ var ResetPasswordForm = ({
283
283
  export {
284
284
  ResetPasswordForm
285
285
  };
286
- //# sourceMappingURL=chunk-W2HMARW4.js.map
286
+ //# sourceMappingURL=chunk-2BF2JIDK.js.map
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  normalizePhone
3
- } from "./chunk-V2W3WPCZ.js";
3
+ } from "./chunk-DBTKXQV7.js";
4
4
  import {
5
5
  useApi,
6
6
  useConfig,
7
7
  useSession
8
- } from "./chunk-A5ON3RKH.js";
8
+ } from "./chunk-M2K6O5CN.js";
9
9
 
10
10
  // src/components/profile/request-change-phone-form.tsx
11
11
  import { zodResolver } from "@hookform/resolvers/zod";
@@ -17,15 +17,9 @@ import { toast } from "sonner";
17
17
  import { z } from "zod";
18
18
  import { jsx, jsxs } from "react/jsx-runtime";
19
19
  var phonePasswordSchema = (phoneRegex) => z.object({
20
- phone: z.string().trim().min(1, { message: "Phone number is required" }).refine(
21
- (val) => {
22
- const isPhone = phoneRegex.test(val);
23
- return isPhone;
24
- },
25
- {
26
- message: "Invalid phone number"
27
- }
28
- ),
20
+ phone: z.string().trim().min(1, { message: "Phone number is required" }).refine((val) => phoneRegex.test(normalizePhone(val)), {
21
+ message: "Invalid phone number"
22
+ }),
29
23
  password: z.string().min(8, "Password must be at least 8 characters").max(128, "Password too long")
30
24
  });
31
25
  function isAuthError(error) {
@@ -85,7 +79,7 @@ function RequestChangePhoneForm({
85
79
  const [isSubmitting, setIsSubmitting] = useState(false);
86
80
  const [isChecking, setIsChecking] = useState(true);
87
81
  const [showPassword, setShowPassword] = useState(false);
88
- const phoneRegex = typeof config.phoneRegex === "string" ? new RegExp(config.phoneRegex) : config.phoneRegex || /^(\+2519|\+2517|2519|2517|09|07)\d{8}$/;
82
+ const phoneRegex = typeof config.phoneRegex === "string" ? new RegExp(config.phoneRegex) : config.phoneRegex || /^\+251[79]\d{8}$/;
89
83
  const getPendingAccountChangeQuery = hooks.useQuery(
90
84
  "get",
91
85
  "/account-change/pending",
@@ -269,4 +263,4 @@ function RequestChangePhoneForm({
269
263
  export {
270
264
  RequestChangePhoneForm
271
265
  };
272
- //# sourceMappingURL=chunk-4LHFPVAY.js.map
266
+ //# sourceMappingURL=chunk-4YPLJ2P6.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/profile/request-change-phone-form.tsx"],"sourcesContent":["'use client';\n\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport { Button, Input, Label, Spinner } from '@mesob/ui/components';\nimport { IconEye, IconEyeOff } from '@tabler/icons-react';\nimport { useEffect, useState } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { toast } from 'sonner';\nimport { z } from 'zod';\nimport { useApi, useConfig, useSession } from '../../provider';\nimport { normalizePhone } from '../../utils/normalize-phone';\n\nconst phonePasswordSchema = (phoneRegex: RegExp) =>\n z.object({\n phone: z\n .string()\n .trim()\n .min(1, { message: 'Phone number is required' })\n .refine((val) => phoneRegex.test(normalizePhone(val)), {\n message: 'Invalid phone number',\n }),\n password: z\n .string()\n .min(8, 'Password must be at least 8 characters')\n .max(128, 'Password too long'),\n });\n\ntype PhonePasswordFormData = z.infer<ReturnType<typeof phonePasswordSchema>>;\n\ntype AuthErrorLike = {\n code?: string;\n message?: string;\n name?: string;\n};\n\nfunction isAuthError(error: unknown): error is AuthErrorLike {\n return (\n typeof error === 'object' &&\n error !== null &&\n ('code' in error || 'message' in error || 'name' in error)\n );\n}\n\nfunction getErrorCode(error: AuthErrorLike): string | undefined {\n if (error.code) {\n return error.code;\n }\n if (error.message) {\n const upperMessage = error.message.toUpperCase().trim();\n const validCodes = [\n 'USER_NOT_FOUND',\n 'USER_EXISTS',\n 'INVALID_PASSWORD',\n 'VERIFICATION_EXPIRED',\n 'VERIFICATION_MISMATCH',\n 'VERIFICATION_NOT_FOUND',\n 'TOO_MANY_ATTEMPTS',\n 'UNAUTHORIZED',\n ];\n if (validCodes.includes(upperMessage)) {\n return upperMessage;\n }\n }\n return undefined;\n}\n\nfunction getErrorMessage(error: unknown): string {\n if (isAuthError(error)) {\n const errorCode = getErrorCode(error);\n switch (errorCode) {\n case 'USER_EXISTS':\n return 'This phone number is already taken. Please use a different number.';\n case 'VERIFICATION_EXPIRED':\n return 'Verification code has expired. Please request a new one.';\n case 'VERIFICATION_MISMATCH':\n return 'Invalid verification code. Please try again.';\n case 'VERIFICATION_NOT_FOUND':\n return 'Verification not found. Please request a new code.';\n default:\n return error.message || 'An error occurred. Please try again.';\n }\n }\n if (error instanceof Error) {\n return error.message;\n }\n return 'An error occurred. Please try again.';\n}\n\ninterface RequestChangePhoneFormProps {\n onSuccess: (verificationId: string, phone: string) => void;\n onCancel: () => void;\n buttonText: string;\n}\n\nexport function RequestChangePhoneForm({\n onSuccess,\n onCancel,\n buttonText,\n}: RequestChangePhoneFormProps) {\n const { user } = useSession();\n const { hooks } = useApi();\n const { config } = useConfig();\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [isChecking, setIsChecking] = useState(true);\n const [showPassword, setShowPassword] = useState(false);\n\n const phoneRegex =\n typeof config.phoneRegex === 'string'\n ? new RegExp(config.phoneRegex)\n : config.phoneRegex || /^\\+251[79]\\d{8}$/;\n\n const getPendingAccountChangeQuery = hooks.useQuery(\n 'get',\n '/account-change/pending',\n {},\n { enabled: false },\n );\n const verifyPasswordMutation = hooks.useMutation('post', '/password/verify');\n const checkUserMutation = hooks.useMutation('post', '/check-account');\n const requestPhoneOtpMutation = hooks.useMutation(\n 'post',\n '/phone/verification/request',\n );\n\n const phonePasswordForm = useForm<PhonePasswordFormData>({\n resolver: zodResolver(phonePasswordSchema(phoneRegex)),\n defaultValues: {\n phone: '',\n password: '',\n },\n });\n\n const {\n register,\n handleSubmit,\n getValues,\n setValue,\n formState: { errors },\n } = phonePasswordForm;\n\n useEffect(() => {\n let active = true;\n const run = async () => {\n try {\n const data = await getPendingAccountChangeQuery.refetch();\n if (!active) {\n return;\n }\n const accountChange = data.data?.accountChange;\n const verificationId = data.data?.verificationId;\n if (accountChange?.changeType !== 'phone') {\n setIsChecking(false);\n return;\n }\n if (!accountChange.newPhone) {\n setIsChecking(false);\n return;\n }\n if (getValues('phone')) {\n setIsChecking(false);\n return;\n }\n setValue('phone', accountChange.newPhone, { shouldValidate: true });\n\n if (verificationId) {\n toast.message('Resuming verification…');\n onSuccess(verificationId, accountChange.newPhone);\n return;\n }\n\n setIsChecking(false);\n } catch {\n setIsChecking(false);\n }\n };\n run().catch(() => undefined);\n return () => {\n active = false;\n };\n }, [getPendingAccountChangeQuery.refetch, getValues, onSuccess, setValue]);\n\n const onPhonePasswordSubmit = async (data: PhonePasswordFormData) => {\n if (!user) {\n toast.error('User not found');\n return;\n }\n\n try {\n setIsSubmitting(true);\n\n const normalizedPhone = normalizePhone(data.phone);\n\n // Verify password first\n await verifyPasswordMutation.mutateAsync({\n body: { password: data.password },\n });\n\n // Check if phone exists\n const checkResult = await checkUserMutation.mutateAsync({\n body: { identifier: normalizedPhone },\n });\n if (checkResult.data?.exists) {\n // Check if it belongs to current user\n if (\n user?.phone?.replace(/\\s/g, '') === normalizedPhone.replace(/\\s/g, '')\n ) {\n toast.error('This is already your current phone number.');\n return;\n }\n toast.error(\n 'This phone number is already taken. Please use a different number.',\n );\n return;\n }\n\n // Request OTP\n const verification = await requestPhoneOtpMutation.mutateAsync({\n body: {\n phone: normalizedPhone,\n context: 'change-phone',\n },\n });\n\n toast.success('Verification code sent to your phone');\n onSuccess(verification.data?.verificationId ?? '', normalizedPhone);\n } catch (error) {\n const errorMessage = getErrorMessage(error);\n if (isAuthError(error)) {\n const errorCode = getErrorCode(error);\n if (\n errorCode === 'INVALID_PASSWORD' ||\n errorCode === 'USER_NOT_FOUND'\n ) {\n toast.error('Incorrect password. Please try again.');\n return;\n }\n }\n toast.error(errorMessage);\n } finally {\n setIsSubmitting(false);\n }\n };\n\n const isLoading = isSubmitting || isChecking;\n\n return (\n <form\n onSubmit={handleSubmit(onPhonePasswordSubmit)}\n className=\"p-4 space-y-4 border-t\"\n >\n <div className=\"space-y-4 w-full md:w-1/2\">\n <div className=\"space-y-2\">\n <Label htmlFor=\"phone\">Phone Number</Label>\n <Input\n id=\"phone\"\n type=\"tel\"\n placeholder=\"Enter your new phone number\"\n {...register('phone')}\n disabled={isLoading}\n />\n {errors.phone && (\n <p className=\"text-sm text-destructive\">{errors.phone.message}</p>\n )}\n </div>\n <div className=\"space-y-2\">\n <Label htmlFor=\"password\">Password</Label>\n <div className=\"relative\">\n <Input\n id=\"password\"\n type={showPassword ? 'text' : 'password'}\n autoComplete=\"current-password\"\n placeholder=\"Enter your password\"\n {...register('password')}\n disabled={isLoading}\n />\n <button\n type=\"button\"\n onClick={() => setShowPassword(!showPassword)}\n className=\"absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground\"\n >\n {showPassword ? (\n <IconEyeOff className=\"h-4 w-4\" />\n ) : (\n <IconEye className=\"h-4 w-4\" />\n )}\n </button>\n </div>\n {errors.password && (\n <p className=\"text-sm text-destructive\">\n {errors.password.message}\n </p>\n )}\n </div>\n </div>\n\n <div className=\"flex justify-end gap-2\">\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={onCancel}\n disabled={isLoading}\n >\n Cancel\n </Button>\n <Button type=\"submit\" disabled={isLoading}>\n {isLoading && <Spinner className=\"mr-2 h-4 w-4\" />}\n {isChecking ? 'Checking…' : buttonText}\n </Button>\n </div>\n </form>\n );\n}\n"],"mappings":"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","names":[]}
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  useApi,
3
3
  useConfig
4
- } from "./chunk-A5ON3RKH.js";
4
+ } from "./chunk-M2K6O5CN.js";
5
5
 
6
6
  // src/components/iam/role-detail-layout.tsx
7
7
  import {
@@ -100,4 +100,4 @@ function RoleDetailLayout({
100
100
  export {
101
101
  RoleDetailLayout
102
102
  };
103
- //# sourceMappingURL=chunk-SA6HTWCL.js.map
103
+ //# sourceMappingURL=chunk-5FNUPWPO.js.map
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  OtpVerificationModal
3
- } from "./chunk-ZOKBN5H4.js";
3
+ } from "./chunk-UIXR5GF3.js";
4
4
  import {
5
5
  useApi,
6
6
  useSession
7
- } from "./chunk-A5ON3RKH.js";
7
+ } from "./chunk-M2K6O5CN.js";
8
8
 
9
9
  // src/components/profile/verify-change-email-form.tsx
10
10
  import { useState } from "react";
@@ -136,4 +136,4 @@ function VerifyChangeEmailForm({
136
136
  export {
137
137
  VerifyChangeEmailForm
138
138
  };
139
- //# sourceMappingURL=chunk-6AV6I5B4.js.map
139
+ //# sourceMappingURL=chunk-75K2SCNC.js.map
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  IAMGuard
3
- } from "./chunk-BM3YKYGC.js";
3
+ } from "./chunk-ZIUAYN37.js";
4
4
  import {
5
5
  useApi,
6
6
  useConfig
7
- } from "./chunk-A5ON3RKH.js";
7
+ } from "./chunk-M2K6O5CN.js";
8
8
 
9
9
  // src/components/iam/role-detail-page.tsx
10
10
  import { zodResolver } from "@hookform/resolvers/zod";
@@ -90,6 +90,7 @@ function RoleDetailPageContent({
90
90
  defaultValues: defaults
91
91
  });
92
92
  const { reset, formState, control, register } = form;
93
+ const registerForLocaleFields = register;
93
94
  useEffect(() => {
94
95
  if (!data?.role) {
95
96
  return;
@@ -138,7 +139,7 @@ function RoleDetailPageContent({
138
139
  label: "Name",
139
140
  field: "name",
140
141
  required: true,
141
- register,
142
+ register: registerForLocaleFields,
142
143
  errors: formState.errors,
143
144
  placeholder: "e.g. Administrator",
144
145
  disabled: !editable
@@ -171,7 +172,7 @@ function RoleDetailPageContent({
171
172
  {
172
173
  label: "Description",
173
174
  field: "description",
174
- register,
175
+ register: registerForLocaleFields,
175
176
  errors: formState.errors,
176
177
  placeholder: "Description",
177
178
  rows: 3,
@@ -200,4 +201,4 @@ function RoleDetailSkeleton() {
200
201
  export {
201
202
  RoleDetailPage
202
203
  };
203
- //# sourceMappingURL=chunk-YCVDEX5U.js.map
204
+ //# sourceMappingURL=chunk-7QJBDRTL.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/iam/role-detail-page.tsx"],"sourcesContent":["'use client';\n\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport {\n EntityFormActions,\n Form,\n FormControl,\n FormField,\n FormItem,\n FormLabel,\n FormMessage,\n Input,\n LocaleInputText,\n LocaleInputTextarea,\n Section,\n Skeleton,\n} from '@mesob/ui/components';\nimport { useLocaleSchemas } from '@mesob/ui/providers';\nimport { useQueryClient } from '@tanstack/react-query';\nimport { useEffect, useMemo } from 'react';\nimport type { FieldValues, Resolver, UseFormRegister } from 'react-hook-form';\nimport { useForm } from 'react-hook-form';\nimport { toast } from 'sonner';\nimport { z } from 'zod';\nimport { useApi, useConfig } from '../../provider';\nimport { IAMGuard } from './iam-guard';\n\ntype RoleFormData = {\n name: Record<string, string>;\n code: string;\n description: Record<string, string>;\n};\n\ntype RoleDetailPageProps = {\n roleId: string;\n basePath?: string;\n};\n\nexport function RoleDetailPage({\n roleId,\n basePath = '/iam/roles',\n}: RoleDetailPageProps) {\n return (\n <IAMGuard>\n <RoleDetailPageContent roleId={roleId} basePath={basePath} />\n </IAMGuard>\n );\n}\n\nfunction RoleDetailPageContent({\n roleId,\n basePath = '/iam/roles',\n}: RoleDetailPageProps) {\n const { hooks } = useApi();\n const { config } = useConfig();\n const qc = useQueryClient();\n const { localeInputDefault, requiredSchema, optionalSchema } =\n useLocaleSchemas();\n const schema = useMemo(\n () =>\n z.object({\n name: requiredSchema,\n code: z.string().min(1, 'Code is required'),\n description: optionalSchema,\n }),\n [requiredSchema, optionalSchema],\n );\n const defaults: RoleFormData = useMemo(\n () => ({\n name: { ...localeInputDefault },\n code: '',\n description: { ...localeInputDefault },\n }),\n [localeInputDefault],\n );\n\n const { data, isLoading } = hooks.useQuery(\n 'get',\n '/roles/{id}',\n { params: { path: { id: roleId } } },\n { enabled: !!roleId },\n );\n\n const update = hooks.useMutation('put', '/roles/{id}', {\n onSuccess: () => {\n qc.invalidateQueries({ queryKey: ['get', '/roles'] });\n qc.invalidateQueries({ queryKey: ['get', '/roles/{id}'] });\n toast.success('Role updated');\n },\n onError: () => {\n toast.error('Failed to update role');\n },\n });\n const remove = hooks.useMutation('delete', '/roles/{id}', {\n onSuccess: () => {\n qc.invalidateQueries({ queryKey: ['get', '/roles'] });\n toast.success('Role deleted');\n config.navigation?.onNavigate?.(basePath);\n },\n onError: () => {\n toast.error('Failed to delete role');\n },\n });\n\n const form = useForm<RoleFormData>({\n resolver: zodResolver(schema) as Resolver<RoleFormData>,\n defaultValues: defaults,\n });\n\n const { reset, formState, control, register } = form;\n /** Locale inputs are typed with `FieldValues`; narrow cast avoids RHF `deps` mismatch. */\n const registerForLocaleFields =\n register as unknown as UseFormRegister<FieldValues>;\n\n useEffect(() => {\n if (!data?.role) {\n return;\n }\n const r = data.role;\n reset({\n name: (r.name ?? {}) as RoleFormData['name'],\n code: r.code,\n description: (r.description ?? {}) as RoleFormData['description'],\n });\n }, [data?.role, reset]);\n\n if (!roleId) {\n return null;\n }\n\n const role = data?.role;\n const editable = role?.isEditable !== false;\n const deletable = role?.isDeletable !== false;\n const onSubmit = form.handleSubmit(async (d) => {\n await update.mutateAsync({\n params: { path: { id: roleId } },\n body: {\n name: d.name,\n code: d.code,\n description: d.description ?? undefined,\n },\n });\n });\n\n const footer = role ? (\n <EntityFormActions\n mode=\"edit\"\n onSubmit={onSubmit}\n onDelete={\n deletable\n ? () =>\n remove.mutate({\n params: { path: { id: roleId } },\n })\n : undefined\n }\n isSubmitting={update.isPending}\n isDeleting={remove.isPending}\n disabled={!editable}\n itemName=\"role\"\n />\n ) : null;\n\n return (\n <Section title=\"Role details\" footer={footer} defaultOpen>\n {isLoading || !role ? (\n <RoleDetailSkeleton />\n ) : (\n <Form {...form}>\n <form onSubmit={onSubmit} className=\"space-y-4\">\n <LocaleInputText\n label=\"Name\"\n field=\"name\"\n required\n register={registerForLocaleFields}\n errors={formState.errors}\n placeholder=\"e.g. Administrator\"\n disabled={!editable}\n />\n <FormField\n control={control}\n name=\"code\"\n render={({ field }) => (\n <FormItem>\n <FormLabel>\n Code <span className=\"text-destructive\">*</span>\n </FormLabel>\n <FormControl>\n <Input\n placeholder=\"e.g. admin\"\n disabled={!editable}\n {...field}\n />\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n <LocaleInputTextarea\n label=\"Description\"\n field=\"description\"\n register={registerForLocaleFields}\n errors={formState.errors}\n placeholder=\"Description\"\n rows={3}\n disabled={!editable}\n />\n </form>\n </Form>\n )}\n </Section>\n );\n}\n\nfunction RoleDetailSkeleton() {\n return (\n <div className=\"space-y-4\">\n <div className=\"space-y-2\">\n <Skeleton className=\"h-4 w-16\" />\n <Skeleton className=\"h-10 w-full\" />\n </div>\n <div className=\"space-y-2\">\n <Skeleton className=\"h-4 w-14\" />\n <Skeleton className=\"h-10 w-full\" />\n </div>\n <div className=\"space-y-2\">\n <Skeleton className=\"h-4 w-24\" />\n <Skeleton className=\"h-20 w-full\" />\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":[]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  VerificationForm
3
- } from "./chunk-EIJFTUTM.js";
3
+ } from "./chunk-GP4XI5KB.js";
4
4
  import {
5
5
  handleError
6
6
  } from "./chunk-W7UHDTBI.js";
@@ -9,11 +9,11 @@ import {
9
9
  } from "./chunk-DPH2PHK3.js";
10
10
  import {
11
11
  useTranslator
12
- } from "./chunk-HBQK5PAH.js";
12
+ } from "./chunk-NPA7L57G.js";
13
13
  import {
14
14
  useApi,
15
15
  useConfig
16
- } from "./chunk-A5ON3RKH.js";
16
+ } from "./chunk-M2K6O5CN.js";
17
17
 
18
18
  // src/components/auth/verify-phone.tsx
19
19
  import { Alert, AlertDescription, AlertTitle } from "@mesob/ui/components";
@@ -114,6 +114,12 @@ var VerifyPhone = ({
114
114
  );
115
115
  return;
116
116
  }
117
+ if (res && "message" in res && typeof res.message === "string") {
118
+ toast.info(t("errors.resendAmbiguousTitle"), {
119
+ description: t("errors.resendAmbiguousDescription")
120
+ });
121
+ return;
122
+ }
117
123
  setError({
118
124
  title: t("errors.fallback"),
119
125
  description: t("phone.resendFailed")
@@ -185,4 +191,4 @@ var VerifyPhone = ({
185
191
  export {
186
192
  VerifyPhone
187
193
  };
188
- //# sourceMappingURL=chunk-FCPN2FD7.js.map
194
+ //# sourceMappingURL=chunk-B7BS57X7.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/auth/verify-phone.tsx"],"sourcesContent":["'use client';\n\nimport { Alert, AlertDescription, AlertTitle } from '@mesob/ui/components';\nimport { useMesob } from '@mesob/ui/providers';\nimport { IconAlertCircle } from '@tabler/icons-react';\nimport { useEffect, useState } from 'react';\nimport { toast } from 'sonner';\nimport { useTranslator } from '../../hooks/use-translator';\nimport { useApi, useConfig } from '../../provider';\nimport type { AuthResponse } from '../../types';\nimport type { AuthErrorContent } from '../../utils/handle-error';\nimport { handleError } from '../../utils/handle-error';\nimport { AuthLayout } from './auth-layout';\nimport { VerificationForm } from './verification-form';\n\ntype VerifyPhoneProps = {\n verificationId: string;\n context: 'sign-in' | 'sign-up';\n phone?: string;\n redirectUrl?: string;\n};\n\nexport const VerifyPhone = ({\n verificationId,\n context,\n phone = '',\n redirectUrl,\n}: VerifyPhoneProps) => {\n const { hooks, refresh, setAuth } = useApi();\n const { config } = useConfig();\n const mesob = useMesob();\n const Link = mesob?.navigation?.Link;\n const t = useTranslator('Auth.verification');\n const common = useTranslator('Common');\n const footer = useTranslator('Auth.forgotPassword.footer');\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<AuthErrorContent | null>(null);\n\n const verifyPhoneMutation = hooks.useMutation(\n 'post',\n '/phone/verification/confirm',\n );\n const requestPhoneMutation = hooks.useMutation(\n 'post',\n '/phone/verification/request',\n );\n\n const signInLink = config.navigation?.links?.signIn || '/auth/sign-in';\n const onNavigate =\n config.navigation?.onNavigate ||\n ((path: string) => {\n if (typeof window !== 'undefined') {\n window.location.href = path;\n }\n });\n const logoImage = config.ui.logoImage;\n const defaultRedirect =\n redirectUrl || config.navigation?.defaultRedirectUrl || '/';\n\n useEffect(() => {\n if (error) {\n toast.error(error.title || 'Error', {\n description: error.description,\n });\n }\n }, [error]);\n\n const handleSubmit = async (values: { code: string }) => {\n if (!verificationId) {\n setError({\n title: t('errors.fallback'),\n description: t('errors.fallback'),\n });\n return;\n }\n\n setIsLoading(true);\n setError(null);\n\n try {\n const res = await verifyPhoneMutation.mutateAsync({\n body: {\n verificationId,\n code: values.code,\n context,\n },\n });\n if (res && 'user' in res && 'session' in res && res.session) {\n setAuth(res as AuthResponse);\n onNavigate(defaultRedirect);\n return;\n }\n await refresh();\n onNavigate(defaultRedirect);\n } catch (err) {\n handleError(err, setError, t);\n } finally {\n setIsLoading(false);\n }\n };\n\n const handleResend = async () => {\n setError(null);\n try {\n const targetPhone = context === 'sign-up' ? phone : null;\n if (!targetPhone) {\n setError({\n title: t('errors.fallback'),\n description: t('phone.missingPhone'),\n });\n return;\n }\n const res = await requestPhoneMutation.mutateAsync({\n body: {\n phone: targetPhone,\n context,\n },\n });\n if (res && 'verificationId' in res && res.verificationId) {\n onNavigate(\n `/auth/verify-phone?context=${context}&verificationId=${res.verificationId}&phone=${targetPhone}`,\n );\n return;\n }\n if (res && 'message' in res && typeof res.message === 'string') {\n toast.info(t('errors.resendAmbiguousTitle'), {\n description: t('errors.resendAmbiguousDescription'),\n });\n return;\n }\n setError({\n title: t('errors.fallback'),\n description: t('phone.resendFailed'),\n });\n } catch (err) {\n handleError(err, setError, t);\n }\n };\n\n if (!verificationId) {\n return (\n <AuthLayout\n title={common('invalidLinkTitle')}\n description={common('invalidLinkDescription')}\n footer={\n <Link href={signInLink} className=\"text-primary hover:underline\">\n {footer('backToSignIn')}\n </Link>\n }\n >\n <div />\n </AuthLayout>\n );\n }\n\n let errorContent: AuthErrorContent | null = null;\n if (error) {\n if (typeof error === 'string') {\n errorContent = { title: 'Error', description: error };\n } else {\n errorContent = error;\n }\n }\n\n return (\n <AuthLayout\n title={config.ui.name}\n description={t('phone.description', {\n target: phone || t('phone.missingPhone'),\n })}\n logoImage={logoImage}\n footer={\n Link ? (\n <Link href={signInLink} className=\"text-primary hover:underline\">\n {footer('backToSignIn')}\n </Link>\n ) : (\n <a\n href={signInLink}\n onClick={(e) => {\n e.preventDefault();\n onNavigate(signInLink);\n }}\n className=\"text-primary hover:underline\"\n >\n {footer('backToSignIn')}\n </a>\n )\n }\n >\n <VerificationForm\n verificationId={verificationId}\n onSubmit={handleSubmit}\n onResend={handleResend}\n isLoading={\n isLoading ||\n verifyPhoneMutation.isPending ||\n requestPhoneMutation.isPending\n }\n error={error}\n />\n {errorContent && (\n <Alert variant=\"destructive\" className=\"mt-4\">\n <IconAlertCircle className=\"h-4 w-4\" />\n <AlertTitle>{errorContent.title}</AlertTitle>\n <AlertDescription>{errorContent.description}</AlertDescription>\n </Alert>\n )}\n </AuthLayout>\n );\n};\n"],"mappings":"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","names":[]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  VerificationForm
3
- } from "./chunk-EIJFTUTM.js";
3
+ } from "./chunk-GP4XI5KB.js";
4
4
  import {
5
5
  handleError
6
6
  } from "./chunk-W7UHDTBI.js";
@@ -9,11 +9,11 @@ import {
9
9
  } from "./chunk-DPH2PHK3.js";
10
10
  import {
11
11
  useTranslator
12
- } from "./chunk-HBQK5PAH.js";
12
+ } from "./chunk-NPA7L57G.js";
13
13
  import {
14
14
  useApi,
15
15
  useConfig
16
- } from "./chunk-A5ON3RKH.js";
16
+ } from "./chunk-M2K6O5CN.js";
17
17
 
18
18
  // src/components/auth/verify-email.tsx
19
19
  import { Alert, AlertDescription, AlertTitle } from "@mesob/ui/components";
@@ -98,12 +98,18 @@ var VerifyEmail = ({
98
98
  onNavigate(
99
99
  `/auth/verify-email?verificationId=${res.verificationId}&email=${encodeURIComponent(email)}`
100
100
  );
101
- } else {
102
- setError({
103
- title: t("errors.fallback"),
104
- description: t("errors.resendFailed")
101
+ return;
102
+ }
103
+ if (res.message) {
104
+ toast.info(t("errors.resendAmbiguousTitle"), {
105
+ description: t("errors.resendAmbiguousDescription")
105
106
  });
107
+ return;
106
108
  }
109
+ setError({
110
+ title: t("errors.fallback"),
111
+ description: t("errors.resendFailed")
112
+ });
107
113
  } catch (err) {
108
114
  handleError(err, setError, t);
109
115
  }
@@ -180,4 +186,4 @@ var VerifyEmail = ({
180
186
  export {
181
187
  VerifyEmail
182
188
  };
183
- //# sourceMappingURL=chunk-FLGP4ROM.js.map
189
+ //# sourceMappingURL=chunk-CBR5NTFM.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/auth/verify-email.tsx"],"sourcesContent":["'use client';\n\nimport { Alert, AlertDescription, AlertTitle } from '@mesob/ui/components';\nimport { useMesob } from '@mesob/ui/providers';\nimport { IconAlertCircle } from '@tabler/icons-react';\nimport { useEffect, useState } from 'react';\nimport { toast } from 'sonner';\nimport { useTranslator } from '../../hooks/use-translator';\nimport { useApi, useConfig } from '../../provider';\nimport type { AuthErrorContent } from '../../utils/handle-error';\nimport { handleError } from '../../utils/handle-error';\nimport { AuthLayout } from './auth-layout';\nimport { VerificationForm } from './verification-form';\n\ntype VerifyEmailProps = {\n verificationId: string;\n email: string;\n redirectUrl?: string;\n};\n\nexport const VerifyEmail = ({\n verificationId,\n email,\n redirectUrl,\n}: VerifyEmailProps) => {\n const { hooks, setAuth } = useApi();\n const { config } = useConfig();\n const mesob = useMesob();\n const t = useTranslator('Auth.verification');\n const common = useTranslator('Common');\n const footer = useTranslator('Auth.forgotPassword.footer');\n const Link = mesob?.navigation?.Link;\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<AuthErrorContent | null>(null);\n\n const verifyEmailMutation = hooks.useMutation(\n 'post',\n '/email/verification/confirm',\n );\n const requestEmailMutation = hooks.useMutation(\n 'post',\n '/email/verification/request',\n );\n\n const signInLink = config.navigation?.links?.signIn || '/auth/sign-in';\n const onNavigate =\n config.navigation?.onNavigate ||\n ((path: string) => {\n if (typeof window !== 'undefined') {\n window.location.href = path;\n }\n });\n const logoImage = config.ui.logoImage;\n const defaultRedirect =\n redirectUrl || config.navigation?.defaultRedirectUrl || '/';\n\n useEffect(() => {\n if (error) {\n toast.error(error.title || 'Error', {\n description: error.description,\n });\n }\n }, [error]);\n\n const handleSubmit = async (values: { code: string }) => {\n if (!verificationId) {\n setError({\n title: t('errors.fallback'),\n description: t('errors.missingVerificationId'),\n });\n return;\n }\n\n setIsLoading(true);\n setError(null);\n\n try {\n const res = await verifyEmailMutation.mutateAsync({\n body: {\n verificationId,\n code: values.code,\n },\n });\n if ('user' in res && 'session' in res) {\n setAuth(res);\n }\n onNavigate(defaultRedirect);\n } catch (err) {\n handleError(err, setError, t);\n } finally {\n setIsLoading(false);\n }\n };\n\n const handleResend = async () => {\n setError(null);\n try {\n const res = await requestEmailMutation.mutateAsync({\n body: {\n email,\n },\n });\n if (res.verificationId) {\n onNavigate(\n `/auth/verify-email?verificationId=${res.verificationId}&email=${encodeURIComponent(email)}`,\n );\n return;\n }\n if (res.message) {\n toast.info(t('errors.resendAmbiguousTitle'), {\n description: t('errors.resendAmbiguousDescription'),\n });\n return;\n }\n setError({\n title: t('errors.fallback'),\n description: t('errors.resendFailed'),\n });\n } catch (err) {\n handleError(err, setError, t);\n }\n };\n\n if (!verificationId) {\n return (\n <AuthLayout\n title={common('invalidLinkTitle')}\n description={common('invalidLinkDescription')}\n footer={\n Link ? (\n <Link href={signInLink} className=\"text-primary hover:underline\">\n {footer('backToSignIn')}\n </Link>\n ) : (\n <a\n href={signInLink}\n onClick={(e) => {\n e.preventDefault();\n onNavigate(signInLink);\n }}\n className=\"text-primary hover:underline\"\n >\n {footer('backToSignIn')}\n </a>\n )\n }\n >\n <div />\n </AuthLayout>\n );\n }\n\n let errorContent: AuthErrorContent | null = null;\n if (error) {\n if (typeof error === 'string') {\n errorContent = { title: 'Error', description: error };\n } else {\n errorContent = error;\n }\n }\n\n return (\n <AuthLayout\n title={config.ui.name}\n description={t('email.description')}\n logoImage={logoImage}\n footer={\n Link ? (\n <Link href={signInLink} className=\"text-primary hover:underline\">\n {footer('backToSignIn')}\n </Link>\n ) : (\n <a\n href={signInLink}\n onClick={(e) => {\n e.preventDefault();\n onNavigate(signInLink);\n }}\n className=\"text-primary hover:underline\"\n >\n {footer('backToSignIn')}\n </a>\n )\n }\n >\n <VerificationForm\n verificationId={verificationId}\n onSubmit={handleSubmit}\n onResend={handleResend}\n isLoading={\n isLoading ||\n verifyEmailMutation.isPending ||\n requestEmailMutation.isPending\n }\n error={error}\n />\n {errorContent && (\n <Alert variant=\"destructive\" className=\"mt-4\">\n <IconAlertCircle className=\"h-4 w-4\" />\n <AlertTitle>{errorContent.title}</AlertTitle>\n <AlertDescription>{errorContent.description}</AlertDescription>\n </Alert>\n )}\n </AuthLayout>\n );\n};\n"],"mappings":"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","names":[]}
@@ -0,0 +1,13 @@
1
+ // src/utils/normalize-phone.ts
2
+ function normalizePhone(phone) {
3
+ const digits = phone.replace(/\D/g, "");
4
+ if (digits.length < 9) {
5
+ return phone.trim();
6
+ }
7
+ return `+251${digits.slice(-9)}`;
8
+ }
9
+
10
+ export {
11
+ normalizePhone
12
+ };
13
+ //# sourceMappingURL=chunk-DBTKXQV7.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/normalize-phone.ts"],"sourcesContent":["/** Last 9 digits → `+251…` (matches @mesob/auth-hono `normalizeEthiopiaPhone`). */\nexport function normalizePhone(phone: string): string {\n const digits = phone.replace(/\\D/g, '');\n if (digits.length < 9) {\n return phone.trim();\n }\n return `+251${digits.slice(-9)}`;\n}\n"],"mappings":";AACO,SAAS,eAAe,OAAuB;AACpD,QAAM,SAAS,MAAM,QAAQ,OAAO,EAAE;AACtC,MAAI,OAAO,SAAS,GAAG;AACrB,WAAO,MAAM,KAAK;AAAA,EACpB;AACA,SAAO,OAAO,OAAO,MAAM,EAAE,CAAC;AAChC;","names":[]}
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  VerifyChangeEmailForm
3
- } from "./chunk-6AV6I5B4.js";
3
+ } from "./chunk-75K2SCNC.js";
4
4
  import {
5
5
  RequestChangeEmailForm
6
- } from "./chunk-G4VPR4UC.js";
6
+ } from "./chunk-M677DPBR.js";
7
7
  import {
8
8
  useSession
9
- } from "./chunk-A5ON3RKH.js";
9
+ } from "./chunk-M2K6O5CN.js";
10
10
 
11
11
  // src/components/profile/change-email-form.tsx
12
12
  import {
@@ -91,4 +91,4 @@ function ChangeEmailForm() {
91
91
  export {
92
92
  ChangeEmailForm
93
93
  };
94
- //# sourceMappingURL=chunk-PUOQX6DR.js.map
94
+ //# sourceMappingURL=chunk-DQB4WY5T.js.map
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-TFVBER3Y.js";
4
4
  import {
5
5
  useApi
6
- } from "./chunk-A5ON3RKH.js";
6
+ } from "./chunk-M2K6O5CN.js";
7
7
 
8
8
  // src/components/iam/permissions.tsx
9
9
  import { Badge, Button } from "@mesob/ui/components";
@@ -95,4 +95,4 @@ function Permissions() {
95
95
  export {
96
96
  Permissions
97
97
  };
98
- //# sourceMappingURL=chunk-TPG4RW7H.js.map
98
+ //# sourceMappingURL=chunk-DRAUYDZ5.js.map