@mesob/auth-react 0.0.3 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/dist/components/auth/auth-card.js +11 -0
  2. package/dist/components/auth/auth-card.js.map +1 -0
  3. package/dist/components/{auth-page-layout.d.ts → auth/auth-page-layout.d.ts} +2 -1
  4. package/dist/components/{auth-page-layout.js → auth/auth-page-layout.js} +16 -3
  5. package/dist/components/auth/auth-page-layout.js.map +1 -0
  6. package/dist/components/{countdown.js → auth/countdown.js} +8 -4
  7. package/dist/components/auth/countdown.js.map +1 -0
  8. package/dist/components/{forgot-password.d.ts → auth/forgot-password.d.ts} +1 -1
  9. package/dist/components/{forgot-password.js → auth/forgot-password.js} +7 -4
  10. package/dist/components/auth/forgot-password.js.map +1 -0
  11. package/dist/components/{pages → auth/pages}/forgot-password-page.js +94 -28
  12. package/dist/components/auth/pages/forgot-password-page.js.map +1 -0
  13. package/dist/components/{pages → auth/pages}/reset-password-page.d.ts +2 -1
  14. package/dist/components/{pages → auth/pages}/reset-password-page.js +111 -42
  15. package/dist/components/auth/pages/reset-password-page.js.map +1 -0
  16. package/dist/components/{pages → auth/pages}/sign-in-page.js +130 -30
  17. package/dist/components/auth/pages/sign-in-page.js.map +1 -0
  18. package/dist/components/{pages → auth/pages}/sign-up-page.d.ts +2 -1
  19. package/dist/components/{pages → auth/pages}/sign-up-page.js +93 -29
  20. package/dist/components/auth/pages/sign-up-page.js.map +1 -0
  21. package/dist/components/{pages → auth/pages}/verify-email-page.d.ts +2 -1
  22. package/dist/components/{pages → auth/pages}/verify-email-page.js +131 -61
  23. package/dist/components/auth/pages/verify-email-page.js.map +1 -0
  24. package/dist/components/{pages → auth/pages}/verify-phone-page.d.ts +2 -1
  25. package/dist/components/{pages → auth/pages}/verify-phone-page.js +136 -63
  26. package/dist/components/auth/pages/verify-phone-page.js.map +1 -0
  27. package/dist/components/{reset-password-form.d.ts → auth/reset-password-form.d.ts} +3 -2
  28. package/dist/components/{reset-password-form.js → auth/reset-password-form.js} +17 -15
  29. package/dist/components/auth/reset-password-form.js.map +1 -0
  30. package/dist/components/{sign-in.js → auth/sign-in.js} +43 -6
  31. package/dist/components/auth/sign-in.js.map +1 -0
  32. package/dist/components/{sign-up.js → auth/sign-up.js} +4 -4
  33. package/dist/components/auth/sign-up.js.map +1 -0
  34. package/dist/components/{verification-form.d.ts → auth/verification-form.d.ts} +2 -1
  35. package/dist/components/{verification-form.js → auth/verification-form.js} +33 -33
  36. package/dist/components/auth/verification-form.js.map +1 -0
  37. package/dist/handle-error-H0iqQxJ5.d.ts +6 -0
  38. package/dist/index.d.ts +49 -15
  39. package/dist/index.js +304 -142
  40. package/dist/index.js.map +1 -1
  41. package/package.json +3 -3
  42. package/dist/components/auth-card.js +0 -11
  43. package/dist/components/auth-card.js.map +0 -1
  44. package/dist/components/auth-page-layout.js.map +0 -1
  45. package/dist/components/countdown.js.map +0 -1
  46. package/dist/components/forgot-password.js.map +0 -1
  47. package/dist/components/pages/forgot-password-page.js.map +0 -1
  48. package/dist/components/pages/reset-password-page.js.map +0 -1
  49. package/dist/components/pages/sign-in-page.js.map +0 -1
  50. package/dist/components/pages/sign-up-page.js.map +0 -1
  51. package/dist/components/pages/verify-email-page.js.map +0 -1
  52. package/dist/components/pages/verify-phone-page.js.map +0 -1
  53. package/dist/components/reset-password-form.js.map +0 -1
  54. package/dist/components/sign-in.js.map +0 -1
  55. package/dist/components/sign-up.js.map +0 -1
  56. package/dist/components/verification-form.js.map +0 -1
  57. /package/dist/components/{auth-card.d.ts → auth/auth-card.d.ts} +0 -0
  58. /package/dist/components/{countdown.d.ts → auth/countdown.d.ts} +0 -0
  59. /package/dist/components/{pages → auth/pages}/forgot-password-page.d.ts +0 -0
  60. /package/dist/components/{pages → auth/pages}/sign-in-page.d.ts +0 -0
  61. /package/dist/components/{sign-in.d.ts → auth/sign-in.d.ts} +0 -0
  62. /package/dist/components/{sign-up.d.ts → auth/sign-up.d.ts} +0 -0
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
 
3
- // src/components/sign-in.tsx
3
+ // src/components/auth/sign-in.tsx
4
4
  import { zodResolver } from "@hookform/resolvers/zod";
5
5
  import { Button } from "@mesob/ui/components/button";
6
6
  import {
@@ -12,11 +12,32 @@ import {
12
12
  FormMessage
13
13
  } from "@mesob/ui/components/form";
14
14
  import { Input } from "@mesob/ui/components/input";
15
- import { Eye, EyeOff } from "lucide-react";
15
+ import { Spinner } from "@mesob/ui/components/spinner";
16
+ import { IconEye, IconEyeOff } from "@tabler/icons-react";
16
17
  import { useTranslations } from "next-intl";
17
18
  import { useMemo, useState } from "react";
18
19
  import { useForm } from "react-hook-form";
19
20
  import { z } from "zod";
21
+
22
+ // src/utils/normalize-phone.ts
23
+ function normalizePhone(phone) {
24
+ const cleaned = phone.trim().replace(/\s/g, "");
25
+ if (cleaned.startsWith("+2519")) {
26
+ return cleaned;
27
+ }
28
+ if (cleaned.startsWith("2519")) {
29
+ return `+${cleaned}`;
30
+ }
31
+ if (cleaned.startsWith("09")) {
32
+ return `+251${cleaned.slice(1)}`;
33
+ }
34
+ if (cleaned.startsWith("9") && cleaned.length === 9) {
35
+ return `+251${cleaned}`;
36
+ }
37
+ return cleaned;
38
+ }
39
+
40
+ // src/components/auth/sign-in.tsx
20
41
  import { jsx, jsxs } from "react/jsx-runtime";
21
42
  var SignIn = ({
22
43
  onSubmit,
@@ -29,7 +50,17 @@ var SignIn = ({
29
50
  const [showPassword, setShowPassword] = useState(false);
30
51
  const identifierSchema = useMemo(
31
52
  () => z.object({
32
- account: z.string().min(1, t("errors.accountRequired")).email(t("errors.invalidEmail"))
53
+ account: z.string().trim().min(1, { message: t("errors.requiredField") }).refine(
54
+ (val) => {
55
+ const isEmail = z.string().email().safeParse(val).success;
56
+ const phoneRegex = /^(\+2519|2519|09)\d{8}$/;
57
+ const isPhone = phoneRegex.test(val);
58
+ return isEmail || isPhone;
59
+ },
60
+ {
61
+ message: t("errors.invalidEmailOrPhone")
62
+ }
63
+ )
33
64
  }),
34
65
  [t]
35
66
  );
@@ -52,7 +83,9 @@ var SignIn = ({
52
83
  }
53
84
  });
54
85
  const handleIdentifierSubmit = identifierForm.handleSubmit(async (values) => {
55
- await onSubmit({ account: values.account, password: "" }, "identifier");
86
+ const phoneRegex = /^(\+2519|2519|09)\d{8}$/;
87
+ const normalizedAccount = phoneRegex.test(values.account) ? normalizePhone(values.account) : values.account;
88
+ await onSubmit({ account: normalizedAccount, password: "" }, "identifier");
56
89
  });
57
90
  const handlePasswordSubmit = passwordForm.handleSubmit(async (values) => {
58
91
  await onSubmit(
@@ -79,6 +112,7 @@ var SignIn = ({
79
112
  {
80
113
  type: showPassword ? "text" : "password",
81
114
  placeholder: t("form.passwordPlaceholder"),
115
+ autoComplete: "current-password",
82
116
  ...field
83
117
  }
84
118
  ),
@@ -88,7 +122,7 @@ var SignIn = ({
88
122
  type: "button",
89
123
  onClick: () => setShowPassword(!showPassword),
90
124
  className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground",
91
- children: showPassword ? /* @__PURE__ */ jsx(EyeOff, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx(Eye, { className: "h-4 w-4" })
125
+ children: showPassword ? /* @__PURE__ */ jsx(IconEyeOff, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx(IconEye, { className: "h-4 w-4" })
92
126
  }
93
127
  )
94
128
  ] }) }),
@@ -119,7 +153,10 @@ var SignIn = ({
119
153
  ] })
120
154
  }
121
155
  ),
122
- /* @__PURE__ */ jsx(Button, { type: "submit", className: "w-full", disabled: isLoading, children: isLoading ? t("form.submitting") : t("form.continue") })
156
+ /* @__PURE__ */ jsxs(Button, { type: "submit", className: "w-full", disabled: isLoading, children: [
157
+ isLoading && /* @__PURE__ */ jsx(Spinner, {}),
158
+ isLoading ? t("form.submitting") : t("form.continue")
159
+ ] })
123
160
  ] }) });
124
161
  };
125
162
  export {
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/components/auth/sign-in.tsx","../../../src/utils/normalize-phone.ts"],"sourcesContent":["'use client';\n\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport { Button } from '@mesob/ui/components/button';\nimport {\n Form,\n FormControl,\n FormField,\n FormItem,\n FormLabel,\n FormMessage,\n} from '@mesob/ui/components/form';\nimport { Input } from '@mesob/ui/components/input';\nimport { Spinner } from '@mesob/ui/components/spinner';\nimport { IconEye, IconEyeOff } from '@tabler/icons-react';\nimport { useTranslations } from 'next-intl';\nimport { useMemo, useState } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { z } from 'zod';\nimport { normalizePhone } from '../../utils/normalize-phone';\n\ntype SignInFormValues = {\n account: string;\n password: string;\n};\n\ntype SignInProps = {\n onSubmit: (\n values: SignInFormValues,\n step: 'identifier' | 'password',\n ) => Promise<void> | void;\n isLoading?: boolean;\n identifier?: string;\n step?: 'identifier' | 'password';\n onBack?: () => void;\n};\n\nexport const SignIn = ({\n onSubmit,\n isLoading = false,\n identifier = '',\n step = 'identifier',\n onBack: _onBack,\n}: SignInProps) => {\n const t = useTranslations('Auth.signIn');\n const [showPassword, setShowPassword] = useState(false);\n\n const identifierSchema = useMemo(\n () =>\n z.object({\n account: z\n .string()\n .trim()\n .min(1, { message: t('errors.requiredField') })\n .refine(\n (val) => {\n const isEmail = z.string().email().safeParse(val).success;\n const phoneRegex = /^(\\+2519|2519|09)\\d{8}$/;\n const isPhone = phoneRegex.test(val);\n return isEmail || isPhone;\n },\n {\n message: t('errors.invalidEmailOrPhone'),\n },\n ),\n }),\n [t],\n );\n\n const passwordSchema = useMemo(\n () =>\n z.object({\n password: z\n .string()\n .min(8, t('errors.passwordLength'))\n .max(128, t('errors.longPasswordError')),\n }),\n [t],\n );\n\n const identifierForm = useForm<{ account: string }>({\n resolver: zodResolver(identifierSchema),\n defaultValues: {\n account: identifier,\n },\n });\n\n const passwordForm = useForm<{ password: string }>({\n resolver: zodResolver(passwordSchema),\n defaultValues: {\n password: '',\n },\n });\n\n const handleIdentifierSubmit = identifierForm.handleSubmit(async (values) => {\n const phoneRegex = /^(\\+2519|2519|09)\\d{8}$/;\n const normalizedAccount = phoneRegex.test(values.account)\n ? normalizePhone(values.account)\n : values.account;\n await onSubmit({ account: normalizedAccount, password: '' }, 'identifier');\n });\n\n const handlePasswordSubmit = passwordForm.handleSubmit(async (values) => {\n await onSubmit(\n { account: identifier, password: values.password },\n 'password',\n );\n });\n\n if (step === 'password') {\n return (\n <Form {...passwordForm}>\n <form onSubmit={handlePasswordSubmit} className=\"space-y-4\">\n <div className=\"text-center\">\n <p className=\"text-sm text-muted-foreground mb-2\">\n {t('form.enterPasswordFor')}\n </p>\n <p className=\"font-bold\">{identifier}</p>\n </div>\n <FormField\n control={passwordForm.control}\n name=\"password\"\n render={({ field }) => (\n <FormItem>\n <FormLabel>{t('form.passwordLabel')}</FormLabel>\n <FormControl>\n <div className=\"relative\">\n <Input\n type={showPassword ? 'text' : 'password'}\n placeholder={t('form.passwordPlaceholder')}\n autoComplete=\"current-password\"\n {...field}\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 </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n <Button type=\"submit\" className=\"w-full\" disabled={isLoading}>\n {isLoading ? t('form.submitting') : t('form.submit')}\n </Button>\n </form>\n </Form>\n );\n }\n\n return (\n <Form {...identifierForm}>\n <form onSubmit={handleIdentifierSubmit} className=\"space-y-4\">\n <FormField\n control={identifierForm.control}\n name=\"account\"\n render={({ field }) => (\n <FormItem>\n <FormLabel>{t('form.accountLabel')}</FormLabel>\n <FormControl>\n <Input\n type=\"text\"\n placeholder={t('form.accountPlaceholder')}\n {...field}\n />\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n <Button type=\"submit\" className=\"w-full\" disabled={isLoading}>\n {isLoading && <Spinner />}\n {isLoading ? t('form.submitting') : t('form.continue')}\n </Button>\n </form>\n </Form>\n );\n};\n","export function normalizePhone(phone: string): string {\n const cleaned = phone.trim().replace(/\\s/g, '');\n if (cleaned.startsWith('+2519')) {\n return cleaned;\n }\n if (cleaned.startsWith('2519')) {\n return `+${cleaned}`;\n }\n if (cleaned.startsWith('09')) {\n return `+251${cleaned.slice(1)}`;\n }\n if (cleaned.startsWith('9') && cleaned.length === 9) {\n return `+251${cleaned}`;\n }\n return cleaned;\n}\n"],"mappings":";;;AAEA,SAAS,mBAAmB;AAC5B,SAAS,cAAc;AACvB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,aAAa;AACtB,SAAS,eAAe;AACxB,SAAS,SAAS,kBAAkB;AACpC,SAAS,uBAAuB;AAChC,SAAS,SAAS,gBAAgB;AAClC,SAAS,eAAe;AACxB,SAAS,SAAS;;;AClBX,SAAS,eAAe,OAAuB;AACpD,QAAM,UAAU,MAAM,KAAK,EAAE,QAAQ,OAAO,EAAE;AAC9C,MAAI,QAAQ,WAAW,OAAO,GAAG;AAC/B,WAAO;AAAA,EACT;AACA,MAAI,QAAQ,WAAW,MAAM,GAAG;AAC9B,WAAO,IAAI,OAAO;AAAA,EACpB;AACA,MAAI,QAAQ,WAAW,IAAI,GAAG;AAC5B,WAAO,OAAO,QAAQ,MAAM,CAAC,CAAC;AAAA,EAChC;AACA,MAAI,QAAQ,WAAW,GAAG,KAAK,QAAQ,WAAW,GAAG;AACnD,WAAO,OAAO,OAAO;AAAA,EACvB;AACA,SAAO;AACT;;;ADkGU,SACE,KADF;AA5EH,IAAM,SAAS,CAAC;AAAA,EACrB;AAAA,EACA,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,OAAO;AAAA,EACP,QAAQ;AACV,MAAmB;AACjB,QAAM,IAAI,gBAAgB,aAAa;AACvC,QAAM,CAAC,cAAc,eAAe,IAAI,SAAS,KAAK;AAEtD,QAAM,mBAAmB;AAAA,IACvB,MACE,EAAE,OAAO;AAAA,MACP,SAAS,EACN,OAAO,EACP,KAAK,EACL,IAAI,GAAG,EAAE,SAAS,EAAE,sBAAsB,EAAE,CAAC,EAC7C;AAAA,QACC,CAAC,QAAQ;AACP,gBAAM,UAAU,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,GAAG,EAAE;AAClD,gBAAM,aAAa;AACnB,gBAAM,UAAU,WAAW,KAAK,GAAG;AACnC,iBAAO,WAAW;AAAA,QACpB;AAAA,QACA;AAAA,UACE,SAAS,EAAE,4BAA4B;AAAA,QACzC;AAAA,MACF;AAAA,IACJ,CAAC;AAAA,IACH,CAAC,CAAC;AAAA,EACJ;AAEA,QAAM,iBAAiB;AAAA,IACrB,MACE,EAAE,OAAO;AAAA,MACP,UAAU,EACP,OAAO,EACP,IAAI,GAAG,EAAE,uBAAuB,CAAC,EACjC,IAAI,KAAK,EAAE,0BAA0B,CAAC;AAAA,IAC3C,CAAC;AAAA,IACH,CAAC,CAAC;AAAA,EACJ;AAEA,QAAM,iBAAiB,QAA6B;AAAA,IAClD,UAAU,YAAY,gBAAgB;AAAA,IACtC,eAAe;AAAA,MACb,SAAS;AAAA,IACX;AAAA,EACF,CAAC;AAED,QAAM,eAAe,QAA8B;AAAA,IACjD,UAAU,YAAY,cAAc;AAAA,IACpC,eAAe;AAAA,MACb,UAAU;AAAA,IACZ;AAAA,EACF,CAAC;AAED,QAAM,yBAAyB,eAAe,aAAa,OAAO,WAAW;AAC3E,UAAM,aAAa;AACnB,UAAM,oBAAoB,WAAW,KAAK,OAAO,OAAO,IACpD,eAAe,OAAO,OAAO,IAC7B,OAAO;AACX,UAAM,SAAS,EAAE,SAAS,mBAAmB,UAAU,GAAG,GAAG,YAAY;AAAA,EAC3E,CAAC;AAED,QAAM,uBAAuB,aAAa,aAAa,OAAO,WAAW;AACvE,UAAM;AAAA,MACJ,EAAE,SAAS,YAAY,UAAU,OAAO,SAAS;AAAA,MACjD;AAAA,IACF;AAAA,EACF,CAAC;AAED,MAAI,SAAS,YAAY;AACvB,WACE,oBAAC,QAAM,GAAG,cACR,+BAAC,UAAK,UAAU,sBAAsB,WAAU,aAC9C;AAAA,2BAAC,SAAI,WAAU,eACb;AAAA,4BAAC,OAAE,WAAU,sCACV,YAAE,uBAAuB,GAC5B;AAAA,QACA,oBAAC,OAAE,WAAU,aAAa,sBAAW;AAAA,SACvC;AAAA,MACA;AAAA,QAAC;AAAA;AAAA,UACC,SAAS,aAAa;AAAA,UACtB,MAAK;AAAA,UACL,QAAQ,CAAC,EAAE,MAAM,MACf,qBAAC,YACC;AAAA,gCAAC,aAAW,YAAE,oBAAoB,GAAE;AAAA,YACpC,oBAAC,eACC,+BAAC,SAAI,WAAU,YACb;AAAA;AAAA,gBAAC;AAAA;AAAA,kBACC,MAAM,eAAe,SAAS;AAAA,kBAC9B,aAAa,EAAE,0BAA0B;AAAA,kBACzC,cAAa;AAAA,kBACZ,GAAG;AAAA;AAAA,cACN;AAAA,cACA;AAAA,gBAAC;AAAA;AAAA,kBACC,MAAK;AAAA,kBACL,SAAS,MAAM,gBAAgB,CAAC,YAAY;AAAA,kBAC5C,WAAU;AAAA,kBAET,yBACC,oBAAC,cAAW,WAAU,WAAU,IAEhC,oBAAC,WAAQ,WAAU,WAAU;AAAA;AAAA,cAEjC;AAAA,eACF,GACF;AAAA,YACA,oBAAC,eAAY;AAAA,aACf;AAAA;AAAA,MAEJ;AAAA,MACA,oBAAC,UAAO,MAAK,UAAS,WAAU,UAAS,UAAU,WAChD,sBAAY,EAAE,iBAAiB,IAAI,EAAE,aAAa,GACrD;AAAA,OACF,GACF;AAAA,EAEJ;AAEA,SACE,oBAAC,QAAM,GAAG,gBACR,+BAAC,UAAK,UAAU,wBAAwB,WAAU,aAChD;AAAA;AAAA,MAAC;AAAA;AAAA,QACC,SAAS,eAAe;AAAA,QACxB,MAAK;AAAA,QACL,QAAQ,CAAC,EAAE,MAAM,MACf,qBAAC,YACC;AAAA,8BAAC,aAAW,YAAE,mBAAmB,GAAE;AAAA,UACnC,oBAAC,eACC;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,aAAa,EAAE,yBAAyB;AAAA,cACvC,GAAG;AAAA;AAAA,UACN,GACF;AAAA,UACA,oBAAC,eAAY;AAAA,WACf;AAAA;AAAA,IAEJ;AAAA,IACA,qBAAC,UAAO,MAAK,UAAS,WAAU,UAAS,UAAU,WAChD;AAAA,mBAAa,oBAAC,WAAQ;AAAA,MACtB,YAAY,EAAE,iBAAiB,IAAI,EAAE,eAAe;AAAA,OACvD;AAAA,KACF,GACF;AAEJ;","names":[]}
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
 
3
- // src/components/sign-up.tsx
3
+ // src/components/auth/sign-up.tsx
4
4
  import { zodResolver } from "@hookform/resolvers/zod";
5
5
  import { Button } from "@mesob/ui/components/button";
6
6
  import {
@@ -12,7 +12,7 @@ import {
12
12
  FormMessage
13
13
  } from "@mesob/ui/components/form";
14
14
  import { Input } from "@mesob/ui/components/input";
15
- import { Eye, EyeOff } from "lucide-react";
15
+ import { IconEye, IconEyeOff } from "@tabler/icons-react";
16
16
  import { useTranslations } from "next-intl";
17
17
  import { useEffect, useMemo, useState } from "react";
18
18
  import { useForm } from "react-hook-form";
@@ -132,7 +132,7 @@ var SignUp = ({
132
132
  type: "button",
133
133
  onClick: () => setShowPassword(!showPassword),
134
134
  className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground",
135
- children: showPassword ? /* @__PURE__ */ jsx(EyeOff, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx(Eye, { className: "h-4 w-4" })
135
+ children: showPassword ? /* @__PURE__ */ jsx(IconEyeOff, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx(IconEye, { className: "h-4 w-4" })
136
136
  }
137
137
  )
138
138
  ] }) }),
@@ -162,7 +162,7 @@ var SignUp = ({
162
162
  type: "button",
163
163
  onClick: () => setShowConfirmPassword(!showConfirmPassword),
164
164
  className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground",
165
- children: showConfirmPassword ? /* @__PURE__ */ jsx(EyeOff, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx(Eye, { className: "h-4 w-4" })
165
+ children: showConfirmPassword ? /* @__PURE__ */ jsx(IconEyeOff, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx(IconEye, { className: "h-4 w-4" })
166
166
  }
167
167
  )
168
168
  ] }) }),
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/components/auth/sign-up.tsx"],"sourcesContent":["'use client';\n\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport { Button } from '@mesob/ui/components/button';\nimport {\n Form,\n FormControl,\n FormField,\n FormItem,\n FormLabel,\n FormMessage,\n} from '@mesob/ui/components/form';\nimport { Input } from '@mesob/ui/components/input';\nimport { IconEye, IconEyeOff } from '@tabler/icons-react';\nimport { useTranslations } from 'next-intl';\nimport { useEffect, useMemo, useState } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { z } from 'zod';\n\nconst isPhone = (s: string) => /^\\+?[0-9()[\\]\\s-]{6,}$/.test(s);\n\ntype SignUpFormValues = {\n fullName: string;\n identifier: string;\n handle?: string;\n password: string;\n confirmPassword: string;\n};\n\ntype SignUpProps = {\n onSubmit: (values: SignUpFormValues) => Promise<void> | void;\n isLoading?: boolean;\n initialIdentifier?: string;\n};\n\nexport const SignUp = ({\n onSubmit,\n isLoading = false,\n initialIdentifier,\n}: SignUpProps) => {\n const t = useTranslations('Auth.signUp');\n const hasInitialIdentifier = !!initialIdentifier;\n const [showPassword, setShowPassword] = useState(false);\n const [showConfirmPassword, setShowConfirmPassword] = useState(false);\n\n const signUpSchema = useMemo(\n () =>\n z\n .object({\n fullName: z.string().min(1, t('errors.fullNameRequired')),\n identifier: z\n .string()\n .min(1, t('errors.contactRequired'))\n .refine(\n (val) => {\n if (!val) {\n return false;\n }\n return val.includes('@') || isPhone(val);\n },\n {\n message: t('errors.invalidEmailOrPhone'),\n },\n ),\n password: z\n .string()\n .min(8, t('errors.passwordLength'))\n .max(128, t('errors.longPasswordError')),\n confirmPassword: z.string(),\n })\n .refine((data) => data.password === data.confirmPassword, {\n message: t('errors.passwordsMismatch'),\n path: ['confirmPassword'],\n }),\n [t],\n );\n\n const form = useForm<SignUpFormValues>({\n resolver: zodResolver(signUpSchema),\n defaultValues: {\n fullName: '',\n identifier: initialIdentifier || '',\n password: '',\n confirmPassword: '',\n },\n });\n\n useEffect(() => {\n if (initialIdentifier) {\n form.setValue('identifier', initialIdentifier);\n }\n }, [initialIdentifier, form]);\n\n const handleSubmit = form.handleSubmit(async (values) => {\n await onSubmit(values);\n });\n\n const getIdentifierLabel = () => {\n if (!hasInitialIdentifier) {\n return t('form.accountLabel') || 'Email/Phone';\n }\n if (initialIdentifier?.includes('@')) {\n return t('form.emailLabel');\n }\n return t('form.phoneLabel');\n };\n const identifierLabel = getIdentifierLabel();\n\n return (\n <Form {...form}>\n <form onSubmit={handleSubmit} className=\"space-y-4\">\n <FormField\n control={form.control}\n name=\"fullName\"\n render={({ field }) => (\n <FormItem>\n <FormLabel>{t('form.fullNameLabel')}</FormLabel>\n <FormControl>\n <Input placeholder={t('form.fullNamePlaceholder')} {...field} />\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n <FormField\n control={form.control}\n name=\"identifier\"\n render={({ field }) => (\n <FormItem>\n <FormLabel className={hasInitialIdentifier ? 'block' : undefined}>\n {identifierLabel}\n </FormLabel>\n <FormControl>\n <Input\n type={field.value.includes('@') ? 'email' : 'tel'}\n placeholder={\n hasInitialIdentifier\n ? undefined\n : t('form.accountPlaceholder') || 'Email or phone number'\n }\n {...field}\n disabled={hasInitialIdentifier}\n />\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n <FormField\n control={form.control}\n name=\"password\"\n render={({ field }) => (\n <FormItem>\n <FormLabel>{t('form.passwordLabel')}</FormLabel>\n <FormControl>\n <div className=\"relative\">\n <Input\n type={showPassword ? 'text' : 'password'}\n placeholder={t('form.passwordPlaceholder')}\n {...field}\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 </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n <FormField\n control={form.control}\n name=\"confirmPassword\"\n render={({ field }) => (\n <FormItem>\n <FormLabel>{t('form.confirmPasswordLabel')}</FormLabel>\n <FormControl>\n <div className=\"relative\">\n <Input\n type={showConfirmPassword ? 'text' : 'password'}\n placeholder={t('form.passwordPlaceholder')}\n {...field}\n />\n <button\n type=\"button\"\n onClick={() => setShowConfirmPassword(!showConfirmPassword)}\n className=\"absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground\"\n >\n {showConfirmPassword ? (\n <IconEyeOff className=\"h-4 w-4\" />\n ) : (\n <IconEye className=\"h-4 w-4\" />\n )}\n </button>\n </div>\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n <Button type=\"submit\" className=\"w-full\" disabled={isLoading}>\n {isLoading ? t('form.submitting') : t('form.submit')}\n </Button>\n </form>\n </Form>\n );\n};\n"],"mappings":"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","names":[]}
@@ -1,4 +1,5 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { A as AuthErrorContent } from '../../handle-error-H0iqQxJ5.js';
2
3
 
3
4
  type VerificationFormValues = {
4
5
  code: string;
@@ -8,7 +9,7 @@ type VerificationFormProps = {
8
9
  onSubmit: (values: VerificationFormValues) => Promise<void> | void;
9
10
  onResend: () => Promise<void> | void;
10
11
  isLoading?: boolean;
11
- error?: string | null;
12
+ error?: AuthErrorContent | string | null;
12
13
  };
13
14
  declare const VerificationForm: ({ onSubmit, onResend, isLoading, }: VerificationFormProps) => react_jsx_runtime.JSX.Element;
14
15
 
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
 
3
- // src/components/verification-form.tsx
3
+ // src/components/auth/verification-form.tsx
4
4
  import { zodResolver } from "@hookform/resolvers/zod";
5
5
  import { Button as Button2 } from "@mesob/ui/components/button";
6
6
  import {
@@ -15,16 +15,18 @@ import {
15
15
  InputOTPGroup,
16
16
  InputOTPSlot
17
17
  } from "@mesob/ui/components/input-otp";
18
+ import { Spinner as Spinner2 } from "@mesob/ui/components/spinner";
18
19
  import { useTranslations as useTranslations2 } from "next-intl";
19
20
  import { useMemo } from "react";
20
21
  import { useForm } from "react-hook-form";
21
22
  import { z } from "zod";
22
23
 
23
- // src/components/countdown.tsx
24
+ // src/components/auth/countdown.tsx
24
25
  import { Button } from "@mesob/ui/components/button";
26
+ import { Spinner } from "@mesob/ui/components/spinner";
25
27
  import { useTranslations } from "next-intl";
26
28
  import { useEffect, useState } from "react";
27
- import { jsx } from "react/jsx-runtime";
29
+ import { jsx, jsxs } from "react/jsx-runtime";
28
30
  var Countdown = ({
29
31
  initialSeconds = 60,
30
32
  onResend,
@@ -61,19 +63,22 @@ var Countdown = ({
61
63
  if (seconds > 0) {
62
64
  return /* @__PURE__ */ jsx(Button, { variant: "ghost", disabled: true, children: t("resendIn", { seconds }) });
63
65
  }
64
- return /* @__PURE__ */ jsx(
66
+ return /* @__PURE__ */ jsxs(
65
67
  Button,
66
68
  {
67
69
  variant: "ghost",
68
70
  onClick: handleResend,
69
71
  disabled: isResending || resending,
70
- children: isResending || resending ? t("resending") : t("resend")
72
+ children: [
73
+ isResending || resending && /* @__PURE__ */ jsx(Spinner, {}),
74
+ t("resend")
75
+ ]
71
76
  }
72
77
  );
73
78
  };
74
79
 
75
- // src/components/verification-form.tsx
76
- import { jsx as jsx2, jsxs } from "react/jsx-runtime";
80
+ // src/components/auth/verification-form.tsx
81
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
77
82
  var VerificationForm = ({
78
83
  onSubmit,
79
84
  onResend,
@@ -92,38 +97,30 @@ var VerificationForm = ({
92
97
  code: ""
93
98
  }
94
99
  });
95
- const handleComplete = async (value) => {
96
- const valid = await form.trigger("code");
97
- if (valid) {
98
- await onSubmit({ code: value });
99
- }
100
- };
101
- return /* @__PURE__ */ jsx2(Form, { ...form, children: /* @__PURE__ */ jsxs("form", { className: "space-y-4", children: [
100
+ return /* @__PURE__ */ jsx2(Form, { ...form, children: /* @__PURE__ */ jsxs2("form", { className: "space-y-4", children: [
102
101
  /* @__PURE__ */ jsx2(
103
102
  FormField,
104
103
  {
105
104
  control: form.control,
106
105
  name: "code",
107
- render: ({ field }) => /* @__PURE__ */ jsxs(FormItem, { children: [
106
+ render: ({ field }) => /* @__PURE__ */ jsxs2(FormItem, { children: [
108
107
  /* @__PURE__ */ jsx2(FormControl, { children: /* @__PURE__ */ jsx2("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx2(
109
108
  InputOTP,
110
109
  {
111
110
  maxLength: 6,
112
- value: field.value,
113
- onChange: (value) => {
114
- field.onChange(value);
115
- if (value.length === 6) {
116
- handleComplete(value);
117
- }
118
- },
119
- disabled: isLoading,
120
- children: /* @__PURE__ */ jsxs(InputOTPGroup, { children: [
121
- /* @__PURE__ */ jsx2(InputOTPSlot, { index: 0 }),
122
- /* @__PURE__ */ jsx2(InputOTPSlot, { index: 1 }),
123
- /* @__PURE__ */ jsx2(InputOTPSlot, { index: 2 }),
124
- /* @__PURE__ */ jsx2(InputOTPSlot, { index: 3 }),
125
- /* @__PURE__ */ jsx2(InputOTPSlot, { index: 4 }),
126
- /* @__PURE__ */ jsx2(InputOTPSlot, { index: 5 })
111
+ id: "otp",
112
+ required: true,
113
+ value: field.value ?? "",
114
+ onChange: field.onChange,
115
+ onBlur: field.onBlur,
116
+ containerClassName: "gap-4 justify-center mb-2 flex items-center",
117
+ children: /* @__PURE__ */ jsxs2(InputOTPGroup, { className: "gap-3 *:data-[slot=input-otp-slot]:h-12 *:data-[slot=input-otp-slot]:w-12 *:data-[slot=input-otp-slot]:rounded-md *:data-[slot=input-otp-slot]:border *:data-[slot=input-otp-slot]:text-xl", children: [
118
+ /* @__PURE__ */ jsx2(InputOTPSlot, { className: "h-12", index: 0 }),
119
+ /* @__PURE__ */ jsx2(InputOTPSlot, { className: "h-12", index: 1 }),
120
+ /* @__PURE__ */ jsx2(InputOTPSlot, { className: "h-12", index: 2 }),
121
+ /* @__PURE__ */ jsx2(InputOTPSlot, { className: "h-12", index: 3 }),
122
+ /* @__PURE__ */ jsx2(InputOTPSlot, { className: "h-12", index: 4 }),
123
+ /* @__PURE__ */ jsx2(InputOTPSlot, { className: "h-12", index: 5 })
127
124
  ] })
128
125
  }
129
126
  ) }) }),
@@ -131,9 +128,9 @@ var VerificationForm = ({
131
128
  ] })
132
129
  }
133
130
  ),
134
- /* @__PURE__ */ jsxs("div", { className: "flex justify-between items-center", children: [
131
+ /* @__PURE__ */ jsxs2("div", { className: "flex justify-between items-center", children: [
135
132
  /* @__PURE__ */ jsx2(Countdown, { onResend, resending: isLoading }),
136
- /* @__PURE__ */ jsx2(
133
+ /* @__PURE__ */ jsxs2(
137
134
  Button2,
138
135
  {
139
136
  type: "button",
@@ -143,7 +140,10 @@ var VerificationForm = ({
143
140
  })();
144
141
  },
145
142
  disabled: isLoading || form.watch("code").length !== 6,
146
- children: t("form.confirm")
143
+ children: [
144
+ isLoading && /* @__PURE__ */ jsx2(Spinner2, {}),
145
+ t("form.confirm")
146
+ ]
147
147
  }
148
148
  )
149
149
  ] })
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/components/auth/verification-form.tsx","../../../src/components/auth/countdown.tsx"],"sourcesContent":["'use client';\n\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport { Button } from '@mesob/ui/components/button';\nimport {\n Form,\n FormControl,\n FormField,\n FormItem,\n FormMessage,\n} from '@mesob/ui/components/form';\nimport {\n InputOTP,\n InputOTPGroup,\n InputOTPSlot,\n} from '@mesob/ui/components/input-otp';\nimport { Spinner } from '@mesob/ui/components/spinner';\nimport { useTranslations } from 'next-intl';\nimport { useMemo } from 'react';\nimport { useForm } from 'react-hook-form';\nimport { z } from 'zod';\nimport type { AuthErrorContent } from '../../utils/handle-error';\nimport { Countdown } from './countdown';\n\ntype VerificationFormValues = {\n code: string;\n};\n\ntype VerificationFormProps = {\n verificationId: string;\n onSubmit: (values: VerificationFormValues) => Promise<void> | void;\n onResend: () => Promise<void> | void;\n isLoading?: boolean;\n error?: AuthErrorContent | string | null;\n};\n\nexport const VerificationForm = ({\n onSubmit,\n onResend,\n isLoading = false,\n}: VerificationFormProps) => {\n const t = useTranslations('Auth.verification');\n const verificationSchema = useMemo(\n () =>\n z.object({\n code: z.string().length(6, t('form.codeLength')),\n }),\n [t],\n );\n const form = useForm<VerificationFormValues>({\n resolver: zodResolver(verificationSchema),\n defaultValues: {\n code: '',\n },\n });\n\n return (\n <Form {...form}>\n <form className=\"space-y-4\">\n <FormField\n control={form.control}\n name=\"code\"\n render={({ field }) => (\n <FormItem>\n <FormControl>\n <div className=\"flex justify-center\">\n <InputOTP\n maxLength={6}\n id=\"otp\"\n required\n value={field.value ?? ''}\n onChange={field.onChange}\n onBlur={field.onBlur}\n containerClassName=\"gap-4 justify-center mb-2 flex items-center\"\n >\n <InputOTPGroup className=\"gap-3 *:data-[slot=input-otp-slot]:h-12 *:data-[slot=input-otp-slot]:w-12 *:data-[slot=input-otp-slot]:rounded-md *:data-[slot=input-otp-slot]:border *:data-[slot=input-otp-slot]:text-xl\">\n <InputOTPSlot className=\"h-12\" index={0} />\n <InputOTPSlot className=\"h-12\" index={1} />\n <InputOTPSlot className=\"h-12\" index={2} />\n <InputOTPSlot className=\"h-12\" index={3} />\n <InputOTPSlot className=\"h-12\" index={4} />\n <InputOTPSlot className=\"h-12\" index={5} />\n </InputOTPGroup>\n </InputOTP>\n </div>\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n\n <div className=\"flex justify-between items-center\">\n <Countdown onResend={onResend} resending={isLoading} />\n <Button\n type=\"button\"\n onClick={() => {\n form.handleSubmit(async (values) => {\n await onSubmit(values);\n })();\n }}\n disabled={isLoading || form.watch('code').length !== 6}\n >\n {isLoading && <Spinner />}\n {t('form.confirm')}\n </Button>\n </div>\n </form>\n </Form>\n );\n};\n","'use client';\n\nimport { Button } from '@mesob/ui/components/button';\nimport { Spinner } from '@mesob/ui/components/spinner';\nimport { useTranslations } from 'next-intl';\nimport { useEffect, useState } from 'react';\n\ntype CountdownProps = {\n initialSeconds?: number;\n onResend: () => Promise<void> | void;\n resending?: boolean;\n};\n\nexport const Countdown = ({\n initialSeconds = 60,\n onResend,\n resending = false,\n}: CountdownProps) => {\n const t = useTranslations('Common');\n const [seconds, setSeconds] = useState(initialSeconds);\n const [isResending, setIsResending] = useState(false);\n\n useEffect(() => {\n if (seconds <= 0) {\n return;\n }\n\n const timer = setInterval(() => {\n setSeconds((prev) => {\n if (prev <= 1) {\n clearInterval(timer);\n return 0;\n }\n return prev - 1;\n });\n }, 1000);\n\n return () => clearInterval(timer);\n }, [seconds]);\n\n const handleResend = async () => {\n setIsResending(true);\n try {\n await onResend();\n setSeconds(initialSeconds);\n } catch (_error) {\n // Error handling is done by parent\n } finally {\n setIsResending(false);\n }\n };\n\n if (seconds > 0) {\n return (\n <Button variant=\"ghost\" disabled>\n {t('resendIn', { seconds })}\n </Button>\n );\n }\n\n return (\n <Button\n variant=\"ghost\"\n onClick={handleResend}\n disabled={isResending || resending}\n >\n {isResending || (resending && <Spinner />)}\n {t('resend')}\n </Button>\n );\n};\n"],"mappings":"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","names":["Button","Spinner","useTranslations","jsx","jsxs","useTranslations","Button","Spinner"]}
@@ -0,0 +1,6 @@
1
+ type AuthErrorContent = {
2
+ title: string;
3
+ description: string;
4
+ };
5
+
6
+ export type { AuthErrorContent as A };
package/dist/index.d.ts CHANGED
@@ -1,19 +1,20 @@
1
- export { AuthCard } from './components/auth-card.js';
2
- export { AuthPageLayout } from './components/auth-page-layout.js';
3
- export { Countdown } from './components/countdown.js';
4
- export { ForgotPassword } from './components/forgot-password.js';
5
- export { ForgotPasswordPage } from './components/pages/forgot-password-page.js';
6
- export { ResetPasswordPage } from './components/pages/reset-password-page.js';
7
- export { SignInPage } from './components/pages/sign-in-page.js';
8
- export { SignUpPage } from './components/pages/sign-up-page.js';
9
- export { VerifyEmailPage } from './components/pages/verify-email-page.js';
10
- export { VerifyPhonePage } from './components/pages/verify-phone-page.js';
11
- export { ResetPasswordForm } from './components/reset-password-form.js';
12
- export { SignIn } from './components/sign-in.js';
13
- export { SignUp } from './components/sign-up.js';
14
- export { VerificationForm } from './components/verification-form.js';
1
+ export { AuthCard } from './components/auth/auth-card.js';
2
+ export { AuthPageLayout } from './components/auth/auth-page-layout.js';
3
+ export { Countdown } from './components/auth/countdown.js';
4
+ export { ForgotPassword } from './components/auth/forgot-password.js';
5
+ export { ForgotPasswordPage } from './components/auth/pages/forgot-password-page.js';
6
+ export { ResetPasswordPage } from './components/auth/pages/reset-password-page.js';
7
+ export { SignInPage } from './components/auth/pages/sign-in-page.js';
8
+ export { SignUpPage } from './components/auth/pages/sign-up-page.js';
9
+ export { VerifyEmailPage } from './components/auth/pages/verify-email-page.js';
10
+ export { VerifyPhonePage } from './components/auth/pages/verify-phone-page.js';
11
+ export { ResetPasswordForm } from './components/auth/reset-password-form.js';
12
+ export { SignIn } from './components/auth/sign-in.js';
13
+ export { SignUp } from './components/auth/sign-up.js';
14
+ export { VerificationForm } from './components/auth/verification-form.js';
15
15
  import * as react_jsx_runtime from 'react/jsx-runtime';
16
16
  import { ReactNode } from 'react';
17
+ import './handle-error-H0iqQxJ5.js';
17
18
 
18
19
  type User = {
19
20
  id: string;
@@ -48,6 +49,16 @@ type SessionResponse = {
48
49
  user: User | null;
49
50
  session: Session | null;
50
51
  };
52
+ type PendingAccountChange = {
53
+ changeType: 'email' | 'phone';
54
+ newEmail: string | null;
55
+ newPhone: string | null;
56
+ expiresAt: string;
57
+ };
58
+ type PendingAccountChangeResponse = {
59
+ accountChange: PendingAccountChange | null;
60
+ verificationId: string | null;
61
+ };
51
62
  type AuthErrorCode = 'USER_NOT_FOUND' | 'INVALID_PASSWORD' | 'USER_EXISTS' | 'VERIFICATION_EXPIRED' | 'VERIFICATION_MISMATCH' | 'VERIFICATION_NOT_FOUND' | 'TOO_MANY_ATTEMPTS' | 'REQUIRES_VERIFICATION' | 'UNAUTHORIZED' | 'ACCESS_DENIED' | 'HAS_NO_PASSWORD';
52
63
 
53
64
  type AuthClientConfig = {
@@ -118,6 +129,11 @@ declare class AuthClient {
118
129
  code: string;
119
130
  password: string;
120
131
  }): Promise<AuthResponse>;
132
+ verifyPassword(data: {
133
+ password: string;
134
+ }): Promise<{
135
+ message: string;
136
+ }>;
121
137
  changePassword(data: {
122
138
  currentPassword: string;
123
139
  newPassword: string;
@@ -125,6 +141,22 @@ declare class AuthClient {
125
141
  message: string;
126
142
  }>;
127
143
  getSession(): Promise<SessionResponse>;
144
+ getPendingAccountChange(): Promise<PendingAccountChangeResponse>;
145
+ updateProfile(data: {
146
+ fullName?: string;
147
+ }): Promise<{
148
+ user: User;
149
+ }>;
150
+ updateEmail(data: {
151
+ email: string;
152
+ }): Promise<{
153
+ user: User;
154
+ }>;
155
+ updatePhone(data: {
156
+ phone: string;
157
+ }): Promise<{
158
+ user: User;
159
+ }>;
128
160
  }
129
161
 
130
162
  type AuthContextValue = {
@@ -219,4 +251,6 @@ declare const useSession: () => {
219
251
  refresh: () => Promise<void>;
220
252
  };
221
253
 
222
- export { AuthClient, type AuthErrorCode, AuthProvider, type AuthResponse, type Session, type SessionResponse, type User, type VerificationResponse, createAuthClient, useAuth, useSession };
254
+ declare function normalizePhone(phone: string): string;
255
+
256
+ export { AuthClient, type AuthErrorCode, AuthProvider, type AuthResponse, type PendingAccountChange, type PendingAccountChangeResponse, type Session, type SessionResponse, type User, type VerificationResponse, createAuthClient, normalizePhone, useAuth, useSession };