@better-auth-ui/heroui 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (253) hide show
  1. package/dist/components/account/account.d.ts +18 -0
  2. package/dist/components/account/account.js +24 -0
  3. package/dist/components/account/settings/account-settings.d.ts +5 -0
  4. package/dist/components/account/settings/account-settings.js +6 -0
  5. package/dist/components/account/settings/settings.d.ts +5 -0
  6. package/dist/components/account/settings/settings.js +5 -0
  7. package/dist/components/account/settings/user-profile.d.ts +5 -0
  8. package/dist/components/account/settings/user-profile.js +20 -0
  9. package/dist/components/auth/auth-provider.d.ts +9 -0
  10. package/dist/components/auth/auth-provider.js +12 -0
  11. package/dist/components/auth/auth.d.ts +23 -0
  12. package/dist/components/auth/auth.js +42 -0
  13. package/dist/components/auth/field-separator.d.ts +4 -0
  14. package/dist/components/auth/field-separator.js +5 -0
  15. package/dist/components/auth/forgot-password.d.ts +15 -0
  16. package/dist/components/auth/forgot-password.js +28 -0
  17. package/dist/components/auth/magic-link-button.d.ts +13 -0
  18. package/dist/components/auth/magic-link-button.js +19 -0
  19. package/dist/components/auth/magic-link.d.ts +17 -0
  20. package/dist/components/auth/magic-link.js +43 -0
  21. package/dist/components/auth/provider-buttons.d.ts +19 -0
  22. package/dist/components/auth/provider-buttons.js +34 -0
  23. package/dist/components/auth/reset-password.d.ts +11 -0
  24. package/dist/components/auth/reset-password.js +58 -0
  25. package/dist/components/auth/sign-in.d.ts +14 -0
  26. package/dist/components/auth/sign-in.js +64 -0
  27. package/dist/components/auth/sign-out.d.ts +9 -0
  28. package/dist/components/auth/sign-out.js +33 -0
  29. package/dist/components/auth/sign-up.d.ts +19 -0
  30. package/dist/components/auth/sign-up.js +71 -0
  31. package/dist/components/email/email-changed-email.d.ts +3 -0
  32. package/dist/components/email/email-changed-email.js +23 -0
  33. package/dist/components/email/email-verification-email.d.ts +3 -0
  34. package/dist/components/email/email-verification-email.js +23 -0
  35. package/dist/components/email/magic-link-email.d.ts +3 -0
  36. package/dist/components/email/magic-link-email.js +23 -0
  37. package/dist/components/email/new-device-email.d.ts +3 -0
  38. package/dist/components/email/new-device-email.js +23 -0
  39. package/dist/components/email/otp-email.d.ts +3 -0
  40. package/dist/components/email/otp-email.js +22 -0
  41. package/dist/components/email/password-changed-email.d.ts +3 -0
  42. package/dist/components/email/password-changed-email.js +23 -0
  43. package/dist/components/email/reset-password-email.d.ts +3 -0
  44. package/dist/components/email/reset-password-email.js +23 -0
  45. package/dist/components/settings/account/account-settings.d.ts +16 -0
  46. package/dist/components/settings/account/account-settings.js +20 -0
  47. package/dist/components/settings/account/accounts.d.ts +14 -0
  48. package/dist/components/settings/account/accounts.js +26 -0
  49. package/dist/components/settings/account/appearance.d.ts +16 -0
  50. package/dist/components/settings/account/appearance.js +28 -0
  51. package/dist/components/settings/account/change-avatar.d.ts +4 -0
  52. package/dist/components/settings/account/change-avatar.js +56 -0
  53. package/dist/components/settings/account/change-email.d.ts +15 -0
  54. package/dist/components/settings/account/change-email.js +29 -0
  55. package/dist/components/settings/account/manage-account.d.ts +19 -0
  56. package/dist/components/settings/account/manage-account.js +32 -0
  57. package/dist/components/settings/account/manage-accounts.d.ts +14 -0
  58. package/dist/components/settings/account/manage-accounts.js +37 -0
  59. package/dist/components/settings/account/theme-selector.d.ts +16 -0
  60. package/dist/components/settings/account/theme-selector.js +33 -0
  61. package/dist/components/settings/account/theme-settings.d.ts +16 -0
  62. package/dist/components/settings/account/theme-settings.js +31 -0
  63. package/dist/components/settings/account/user-profile.d.ts +11 -0
  64. package/dist/components/settings/account/user-profile.js +23 -0
  65. package/dist/components/settings/account-settings.d.ts +5 -0
  66. package/dist/components/settings/account-settings.js +6 -0
  67. package/dist/components/settings/account.d.ts +18 -0
  68. package/dist/components/settings/account.js +24 -0
  69. package/dist/components/settings/security/active-session.d.ts +14 -0
  70. package/dist/components/settings/security/active-session.js +53 -0
  71. package/dist/components/settings/security/active-sessions.d.ts +14 -0
  72. package/dist/components/settings/security/active-sessions.js +28 -0
  73. package/dist/components/settings/security/change-password.d.ts +15 -0
  74. package/dist/components/settings/security/change-password.js +79 -0
  75. package/dist/components/settings/security/connected-account.d.ts +16 -0
  76. package/dist/components/settings/security/connected-account.js +46 -0
  77. package/dist/components/settings/security/connected-accounts.d.ts +15 -0
  78. package/dist/components/settings/security/connected-accounts.js +31 -0
  79. package/dist/components/settings/security/danger-zone.d.ts +11 -0
  80. package/dist/components/settings/security/danger-zone.js +12 -0
  81. package/dist/components/settings/security/delete-user.d.ts +9 -0
  82. package/dist/components/settings/security/delete-user.js +47 -0
  83. package/dist/components/settings/security/linked-account.d.ts +16 -0
  84. package/dist/components/settings/security/linked-account.js +48 -0
  85. package/dist/components/settings/security/linked-accounts.d.ts +15 -0
  86. package/dist/components/settings/security/linked-accounts.js +42 -0
  87. package/dist/components/settings/security/security-settings.d.ts +17 -0
  88. package/dist/components/settings/security/security-settings.js +21 -0
  89. package/dist/components/settings/security/sessions.d.ts +14 -0
  90. package/dist/components/settings/security/sessions.js +40 -0
  91. package/dist/components/settings/settings/account-settings.d.ts +5 -0
  92. package/dist/components/settings/settings/account-settings.js +6 -0
  93. package/dist/components/settings/settings/user-profile.d.ts +5 -0
  94. package/dist/components/settings/settings/user-profile.js +20 -0
  95. package/dist/components/settings/settings.d.ts +24 -0
  96. package/dist/components/settings/settings.js +28 -0
  97. package/dist/components/settings/user-profile.d.ts +5 -0
  98. package/dist/components/settings/user-profile.js +20 -0
  99. package/dist/components/user/switch-account-item.d.ts +16 -0
  100. package/dist/components/user/switch-account-item.js +16 -0
  101. package/dist/components/user/switch-account-menu.d.ts +10 -0
  102. package/dist/components/user/switch-account-menu.js +29 -0
  103. package/dist/components/user/switch-account-popover.d.ts +10 -0
  104. package/dist/components/user/switch-account-popover.js +25 -0
  105. package/dist/components/user/switch-account-submenu.d.ts +10 -0
  106. package/dist/components/user/switch-account-submenu.js +25 -0
  107. package/dist/components/user/user-avatar.d.ts +25 -0
  108. package/dist/components/user/user-avatar.js +31 -0
  109. package/dist/components/user/user-button.d.ts +25 -0
  110. package/dist/components/user/user-button.js +24 -0
  111. package/dist/components/user/user-view.d.ts +22 -0
  112. package/dist/components/user/user-view.js +24 -0
  113. package/dist/core.d.ts +1 -0
  114. package/dist/core.js +1 -0
  115. package/dist/hooks/use-auth.d.ts +2 -0
  116. package/dist/hooks/use-auth.js +8 -0
  117. package/dist/hooks/use-redirect-to.d.ts +8 -0
  118. package/dist/hooks/use-redirect-to.js +19 -0
  119. package/dist/hooks/use-sign-in.d.ts +8 -0
  120. package/dist/hooks/use-sign-in.js +53 -0
  121. package/dist/index.d.ts +33 -0
  122. package/dist/index.js +34 -0
  123. package/dist/lib/utils.d.ts +2 -0
  124. package/dist/lib/utils.js +5 -0
  125. package/dist/react-exports.d.ts +1 -0
  126. package/dist/react-exports.js +1 -0
  127. package/dist/server.d.ts +1 -0
  128. package/dist/server.js +1 -0
  129. package/dist/src/components/auth/auth-provider.d.ts +8 -0
  130. package/dist/src/components/auth/auth-provider.js +13 -0
  131. package/dist/src/components/auth/auth.d.ts +22 -0
  132. package/dist/src/components/auth/auth.js +42 -0
  133. package/dist/src/components/auth/field-separator.d.ts +4 -0
  134. package/dist/src/components/auth/field-separator.js +5 -0
  135. package/dist/src/components/auth/forgot-password.d.ts +15 -0
  136. package/dist/src/components/auth/forgot-password.js +29 -0
  137. package/dist/src/components/auth/magic-link-button.d.ts +13 -0
  138. package/dist/src/components/auth/magic-link-button.js +20 -0
  139. package/dist/src/components/auth/magic-link.d.ts +17 -0
  140. package/dist/src/components/auth/magic-link.js +37 -0
  141. package/dist/src/components/auth/provider-buttons.d.ts +19 -0
  142. package/dist/src/components/auth/provider-buttons.js +35 -0
  143. package/dist/src/components/auth/reset-password.d.ts +11 -0
  144. package/dist/src/components/auth/reset-password.js +59 -0
  145. package/dist/src/components/auth/sign-in.d.ts +14 -0
  146. package/dist/src/components/auth/sign-in.js +58 -0
  147. package/dist/src/components/auth/sign-out.d.ts +11 -0
  148. package/dist/src/components/auth/sign-out.js +34 -0
  149. package/dist/src/components/auth/sign-up.d.ts +19 -0
  150. package/dist/src/components/auth/sign-up.js +65 -0
  151. package/dist/src/components/email/email-changed-email.d.ts +3 -0
  152. package/dist/src/components/email/email-changed-email.js +23 -0
  153. package/dist/src/components/email/email-verification-email.d.ts +3 -0
  154. package/dist/src/components/email/email-verification-email.js +23 -0
  155. package/dist/src/components/email/magic-link-email.d.ts +3 -0
  156. package/dist/src/components/email/magic-link-email.js +23 -0
  157. package/dist/src/components/email/new-device-email.d.ts +3 -0
  158. package/dist/src/components/email/new-device-email.js +23 -0
  159. package/dist/src/components/email/otp-email.d.ts +3 -0
  160. package/dist/src/components/email/otp-email.js +22 -0
  161. package/dist/src/components/email/password-changed-email.d.ts +3 -0
  162. package/dist/src/components/email/password-changed-email.js +23 -0
  163. package/dist/src/components/email/reset-password-email.d.ts +3 -0
  164. package/dist/src/components/email/reset-password-email.js +23 -0
  165. package/dist/src/components/settings/account/account-settings.d.ts +13 -0
  166. package/dist/src/components/settings/account/account-settings.js +19 -0
  167. package/dist/src/components/settings/account/appearance.d.ts +16 -0
  168. package/dist/src/components/settings/account/appearance.js +28 -0
  169. package/dist/src/components/settings/account/change-email.d.ts +15 -0
  170. package/dist/src/components/settings/account/change-email.js +35 -0
  171. package/dist/src/components/settings/account/manage-account.d.ts +19 -0
  172. package/dist/src/components/settings/account/manage-account.js +27 -0
  173. package/dist/src/components/settings/account/manage-accounts.d.ts +14 -0
  174. package/dist/src/components/settings/account/manage-accounts.js +27 -0
  175. package/dist/src/components/settings/account/user-profile.d.ts +13 -0
  176. package/dist/src/components/settings/account/user-profile.js +29 -0
  177. package/dist/src/components/settings/security/active-session.d.ts +14 -0
  178. package/dist/src/components/settings/security/active-session.js +35 -0
  179. package/dist/src/components/settings/security/active-sessions.d.ts +14 -0
  180. package/dist/src/components/settings/security/active-sessions.js +29 -0
  181. package/dist/src/components/settings/security/change-password.d.ts +15 -0
  182. package/dist/src/components/settings/security/change-password.js +57 -0
  183. package/dist/src/components/settings/security/linked-account.d.ts +16 -0
  184. package/dist/src/components/settings/security/linked-account.js +46 -0
  185. package/dist/src/components/settings/security/linked-accounts.d.ts +15 -0
  186. package/dist/src/components/settings/security/linked-accounts.js +31 -0
  187. package/dist/src/components/settings/security/security-settings.d.ts +15 -0
  188. package/dist/src/components/settings/security/security-settings.js +18 -0
  189. package/dist/src/components/settings/settings.d.ts +29 -0
  190. package/dist/src/components/settings/settings.js +39 -0
  191. package/dist/src/components/user/switch-account-item.d.ts +16 -0
  192. package/dist/src/components/user/switch-account-item.js +14 -0
  193. package/dist/src/components/user/switch-account-menu.d.ts +10 -0
  194. package/dist/src/components/user/switch-account-menu.js +23 -0
  195. package/dist/src/components/user/user-avatar.d.ts +24 -0
  196. package/dist/src/components/user/user-avatar.js +31 -0
  197. package/dist/src/components/user/user-button.d.ts +21 -0
  198. package/dist/src/components/user/user-button.js +24 -0
  199. package/dist/src/components/user/user-view.d.ts +21 -0
  200. package/dist/src/components/user/user-view.js +24 -0
  201. package/dist/src/core.d.ts +1 -0
  202. package/dist/src/core.js +1 -0
  203. package/dist/src/index.d.ts +31 -0
  204. package/dist/src/index.js +32 -0
  205. package/dist/src/lib/utils.d.ts +2 -0
  206. package/dist/src/lib/utils.js +5 -0
  207. package/dist/src/react-exports.d.ts +1 -0
  208. package/dist/src/react-exports.js +1 -0
  209. package/dist/styles.css +1 -0
  210. package/package.json +63 -0
  211. package/src/components/auth/auth-provider.tsx +27 -0
  212. package/src/components/auth/auth.tsx +87 -0
  213. package/src/components/auth/field-separator.tsx +14 -0
  214. package/src/components/auth/forgot-password.tsx +107 -0
  215. package/src/components/auth/magic-link-button.tsx +43 -0
  216. package/src/components/auth/magic-link.tsx +181 -0
  217. package/src/components/auth/provider-buttons.tsx +85 -0
  218. package/src/components/auth/reset-password.tsx +210 -0
  219. package/src/components/auth/sign-in.tsx +260 -0
  220. package/src/components/auth/sign-out.tsx +44 -0
  221. package/src/components/auth/sign-up.tsx +314 -0
  222. package/src/components/email/email-changed-email.tsx +38 -0
  223. package/src/components/email/email-verification-email.tsx +38 -0
  224. package/src/components/email/magic-link-email.tsx +38 -0
  225. package/src/components/email/new-device-email.tsx +38 -0
  226. package/src/components/email/otp-email.tsx +33 -0
  227. package/src/components/email/password-changed-email.tsx +38 -0
  228. package/src/components/email/reset-password-email.tsx +38 -0
  229. package/src/components/settings/account/account-settings.tsx +48 -0
  230. package/src/components/settings/account/appearance.tsx +157 -0
  231. package/src/components/settings/account/change-avatar.tsx +142 -0
  232. package/src/components/settings/account/change-email.tsx +111 -0
  233. package/src/components/settings/account/manage-account.tsx +123 -0
  234. package/src/components/settings/account/manage-accounts.tsx +78 -0
  235. package/src/components/settings/account/user-profile.tsx +103 -0
  236. package/src/components/settings/security/active-session.tsx +123 -0
  237. package/src/components/settings/security/active-sessions.tsx +77 -0
  238. package/src/components/settings/security/change-password.tsx +335 -0
  239. package/src/components/settings/security/danger-zone.tsx +32 -0
  240. package/src/components/settings/security/delete-user.tsx +187 -0
  241. package/src/components/settings/security/linked-account.tsx +136 -0
  242. package/src/components/settings/security/linked-accounts.tsx +98 -0
  243. package/src/components/settings/security/security-settings.tsx +43 -0
  244. package/src/components/settings/settings.tsx +96 -0
  245. package/src/components/user/switch-account-item.tsx +39 -0
  246. package/src/components/user/switch-account-menu.tsx +64 -0
  247. package/src/components/user/user-avatar.tsx +88 -0
  248. package/src/components/user/user-button.tsx +221 -0
  249. package/src/components/user/user-view.tsx +74 -0
  250. package/src/core.ts +1 -0
  251. package/src/index.tsx +35 -0
  252. package/src/react-exports.ts +1 -0
  253. package/src/styles.css +1 -0
@@ -0,0 +1,29 @@
1
+ import type { SettingsView } from "@better-auth-ui/react/core";
2
+ import { type TabsProps } from "@heroui/react";
3
+ import { type ComponentProps } from "react";
4
+ export type SettingsProps = {
5
+ className?: string;
6
+ hideNav?: boolean;
7
+ path?: string;
8
+ view?: SettingsView;
9
+ };
10
+ /**
11
+ * Renders the settings UI and activates the appropriate settings view based on `view` or `path`.
12
+ *
13
+ * @param className - Additional CSS class names applied to the root container
14
+ * @param path - Route path used to resolve which settings view to activate when `view` is not provided
15
+ * @param view - Explicit settings view to activate, e.g. `"account"` or `"security"`
16
+ * @param hideNav - When `true`, hide the navigation tabs
17
+ * @returns A DOM tree containing the responsive settings tabs and the currently selected settings panel
18
+ *
19
+ * @throws Error if neither `view` nor `path` is provided
20
+ */
21
+ export declare function Settings({ className, hideNav, path, view, ...props }: SettingsProps & ComponentProps<"div">): import("react/jsx-runtime").JSX.Element;
22
+ /**
23
+ * Renders a responsive pair of Tabs components: horizontal on small screens and vertical on medium-and-up screens.
24
+ *
25
+ * @param className - Additional CSS classes applied to both responsive tab containers.
26
+ * @param props - All other props are forwarded to each underlying Tabs component.
27
+ * @returns A JSX element containing the responsive Tabs pair.
28
+ */
29
+ export declare function ResponsiveTabs({ className, ...props }: TabsProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,39 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useAuth, useAuthenticate } from "@better-auth-ui/react";
3
+ import { Person, Shield } from "@gravity-ui/icons";
4
+ import { cn, Tabs, useIsHydrated } from "@heroui/react";
5
+ import { useMemo } from "react";
6
+ import { AccountSettings } from "./account/account-settings";
7
+ import { SecuritySettings } from "./security/security-settings";
8
+ /**
9
+ * Renders the settings UI and activates the appropriate settings view based on `view` or `path`.
10
+ *
11
+ * @param className - Additional CSS class names applied to the root container
12
+ * @param path - Route path used to resolve which settings view to activate when `view` is not provided
13
+ * @param view - Explicit settings view to activate, e.g. `"account"` or `"security"`
14
+ * @param hideNav - When `true`, hide the navigation tabs
15
+ * @returns A DOM tree containing the responsive settings tabs and the currently selected settings panel
16
+ *
17
+ * @throws Error if neither `view` nor `path` is provided
18
+ */
19
+ export function Settings({ className, hideNav, path, view, ...props }) {
20
+ const { basePaths, localization, viewPaths } = useAuth();
21
+ useAuthenticate();
22
+ if (!view && !path) {
23
+ throw new Error("[Better Auth UI] Either `view` or `path` must be provided");
24
+ }
25
+ const settingsPathViews = useMemo(() => Object.fromEntries(Object.entries(viewPaths.settings).map(([k, v]) => [v, k])), [viewPaths.settings]);
26
+ const currentView = view || (path ? settingsPathViews[path] : undefined);
27
+ const isHydrated = useIsHydrated();
28
+ return (_jsxs("div", { className: cn("w-full flex flex-col md:flex-row gap-4 md:gap-6", className), ...props, children: [_jsx(ResponsiveTabs, { selectedKey: currentView, className: cn(hideNav && "hidden"), children: _jsx(Tabs.ListContainer, { children: _jsxs(Tabs.List, { "aria-label": localization.settings.settings, className: "overflow-auto md:w-64 lg:w-72 xl:w-80", children: [_jsxs(Tabs.Tab, { id: "account", href: `${basePaths.settings}/${viewPaths.settings.account}`, className: "gap-2", children: [_jsx(Person, {}), localization.settings.account, _jsx(Tabs.Indicator, {})] }), _jsxs(Tabs.Tab, { id: "security", href: `${basePaths.settings}/${viewPaths.settings.security}`, className: "gap-2", children: [_jsx(Shield, {}), localization.settings.security, _jsx(Tabs.Indicator, {})] })] }) }) }), currentView === "account" && _jsx(AccountSettings, {}), currentView === "security" && _jsx(SecuritySettings, {})] }, `settings-${isHydrated}`));
29
+ }
30
+ /**
31
+ * Renders a responsive pair of Tabs components: horizontal on small screens and vertical on medium-and-up screens.
32
+ *
33
+ * @param className - Additional CSS classes applied to both responsive tab containers.
34
+ * @param props - All other props are forwarded to each underlying Tabs component.
35
+ * @returns A JSX element containing the responsive Tabs pair.
36
+ */
37
+ export function ResponsiveTabs({ className, ...props }) {
38
+ return (_jsxs(_Fragment, { children: [_jsx(Tabs, { className: cn("md:hidden", className), orientation: "horizontal", ...props }), _jsx(Tabs, { className: cn("hidden md:flex", className), orientation: "vertical", ...props })] }));
39
+ }
@@ -0,0 +1,16 @@
1
+ import type { Session, User } from "better-auth";
2
+ type DeviceSession = {
3
+ session: Session;
4
+ user: User;
5
+ };
6
+ export type SwitchAccountItemProps = {
7
+ deviceSession: DeviceSession;
8
+ };
9
+ /**
10
+ * Render a dropdown item for switching to a different authenticated session.
11
+ *
12
+ * @param deviceSession - The device session to display and switch to when pressed
13
+ * @returns The switch account dropdown item as a JSX element
14
+ */
15
+ export declare function SwitchAccountItem({ deviceSession }: SwitchAccountItemProps): import("react/jsx-runtime").JSX.Element;
16
+ export {};
@@ -0,0 +1,14 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useSetActiveSession } from "@better-auth-ui/react";
3
+ import { Dropdown, Spinner } from "@heroui/react";
4
+ import { UserView } from "./user-view";
5
+ /**
6
+ * Render a dropdown item for switching to a different authenticated session.
7
+ *
8
+ * @param deviceSession - The device session to display and switch to when pressed
9
+ * @returns The switch account dropdown item as a JSX element
10
+ */
11
+ export function SwitchAccountItem({ deviceSession }) {
12
+ const { mutate: setActiveSession, isPending } = useSetActiveSession();
13
+ return (_jsxs(Dropdown.Item, { className: "px-2", isDisabled: isPending, onPress: () => setActiveSession({ sessionToken: deviceSession.session.token }), children: [_jsx(UserView, { user: deviceSession.user }), isPending && _jsx(Spinner, { color: "current", size: "sm", className: "ml-auto" })] }));
14
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Render the menu content for switching between multiple authenticated sessions.
3
+ *
4
+ * Shows the current session with a checkmark, lists other device sessions that can be activated,
5
+ * and provides an option to add a new account. This component should be rendered inside a
6
+ * Dropdown.SubmenuTrigger to defer the useListDeviceSessions query until the submenu is opened.
7
+ *
8
+ * @returns The switch account menu content as a JSX element
9
+ */
10
+ export declare function SwitchAccountMenu(): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,23 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useAuth, useListDeviceSessions, useSession } from "@better-auth-ui/react";
3
+ import { Check, CirclePlus } from "@gravity-ui/icons";
4
+ import { Dropdown, Label, Separator } from "@heroui/react";
5
+ import { SwitchAccountItem } from "./switch-account-item";
6
+ import { UserView } from "./user-view";
7
+ /**
8
+ * Render the menu content for switching between multiple authenticated sessions.
9
+ *
10
+ * Shows the current session with a checkmark, lists other device sessions that can be activated,
11
+ * and provides an option to add a new account. This component should be rendered inside a
12
+ * Dropdown.SubmenuTrigger to defer the useListDeviceSessions query until the submenu is opened.
13
+ *
14
+ * @returns The switch account menu content as a JSX element
15
+ */
16
+ export function SwitchAccountMenu() {
17
+ const { basePaths, viewPaths, localization } = useAuth();
18
+ const { data: sessionData } = useSession();
19
+ const { data: deviceSessions, isPending } = useListDeviceSessions();
20
+ return (_jsx(Dropdown.Popover, { className: "min-w-40 md:min-w-56 max-w-[48svw]", children: _jsxs(Dropdown.Menu, { children: [_jsxs(Dropdown.Item, { className: "px-2", children: [_jsx(UserView, { isPending: isPending }), !isPending && _jsx(Check, { className: "ml-auto" })] }), deviceSessions
21
+ ?.filter((deviceSession) => deviceSession.session.id !== sessionData?.session?.id)
22
+ .map((deviceSession) => (_jsx(SwitchAccountItem, { deviceSession: deviceSession }, deviceSession.session.id))), _jsx(Separator, {}), _jsxs(Dropdown.Item, { textValue: localization.auth.addAccount, href: `${basePaths.auth}/${viewPaths.auth.signIn}`, children: [_jsx(CirclePlus, { className: "text-muted" }), _jsx(Label, { children: localization.auth.addAccount })] })] }) }));
23
+ }
@@ -0,0 +1,24 @@
1
+ import { type AvatarProps } from "@heroui/react";
2
+ import type { User } from "better-auth";
3
+ import type { ReactNode } from "react";
4
+ export type UserAvatarProps = {
5
+ className?: string;
6
+ fallback?: ReactNode;
7
+ isPending?: boolean;
8
+ user?: User & {
9
+ username?: string | null;
10
+ displayUsername?: string | null;
11
+ };
12
+ size?: AvatarProps["size"];
13
+ };
14
+ /**
15
+ * Render a user avatar that shows the user's image, initials, or a custom fallback; displays a circular skeleton while the session (or explicit pending flag) is pending.
16
+ *
17
+ * @param className - Additional CSS classes applied to the outer avatar container
18
+ * @param fallback - Custom fallback content to render when no image or initials are available
19
+ * @param isPending - When true, force rendering of the loading skeleton (unless an explicit `user` prop is provided)
20
+ * @param user - Optional user object to display; when omitted the current session user is used if available
21
+ * @param size - Visual size of the avatar; one of `"sm"`, `"md"`, or `"lg"` (default: `"sm"`)
22
+ * @returns A React element that displays the user's avatar image, initials, or the provided fallback; renders a circular skeleton while loading
23
+ */
24
+ export declare function UserAvatar({ className, fallback, isPending, user, size, style, ...props }: UserAvatarProps & AvatarProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,31 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useSession } from "@better-auth-ui/react";
3
+ import { Person } from "@gravity-ui/icons";
4
+ import { Avatar, cn, Skeleton } from "@heroui/react";
5
+ /**
6
+ * Render a user avatar that shows the user's image, initials, or a custom fallback; displays a circular skeleton while the session (or explicit pending flag) is pending.
7
+ *
8
+ * @param className - Additional CSS classes applied to the outer avatar container
9
+ * @param fallback - Custom fallback content to render when no image or initials are available
10
+ * @param isPending - When true, force rendering of the loading skeleton (unless an explicit `user` prop is provided)
11
+ * @param user - Optional user object to display; when omitted the current session user is used if available
12
+ * @param size - Visual size of the avatar; one of `"sm"`, `"md"`, or `"lg"` (default: `"sm"`)
13
+ * @returns A React element that displays the user's avatar image, initials, or the provided fallback; renders a circular skeleton while loading
14
+ */
15
+ export function UserAvatar({ className, fallback, isPending, user, size = "sm", style, ...props }) {
16
+ const { data: sessionData, isPending: sessionPending } = useSession({
17
+ enabled: !user && !isPending
18
+ });
19
+ if ((isPending || sessionPending) && !user) {
20
+ return (_jsx(Skeleton, { className: cn("rounded-full", size === "sm" ? "size-8" : size === "md" ? "size-10" : "size-12", className), style: style }));
21
+ }
22
+ const resolvedUser = user ?? sessionData?.user;
23
+ const initials = (resolvedUser?.username ||
24
+ resolvedUser?.name ||
25
+ resolvedUser?.email)
26
+ ?.slice(0, 2)
27
+ .toUpperCase();
28
+ return (_jsxs(Avatar, { size: size, className: cn("rounded-full", className), style: style, ...props, children: [_jsx(Avatar.Image, { alt: resolvedUser?.displayUsername ||
29
+ resolvedUser?.name ||
30
+ resolvedUser?.email, src: resolvedUser?.image ?? undefined }), _jsx(Avatar.Fallback, { className: cn(size === "lg" ? "text-xl" : size === "md" ? "text-base" : "text-sm"), delayMs: resolvedUser?.image ? 600 : undefined, children: fallback || initials || _jsx(Person, { className: "size-4" }) })] }));
31
+ }
@@ -0,0 +1,21 @@
1
+ import { type ButtonProps, type DropdownPopoverProps } from "@heroui/react";
2
+ export type UserButtonProps = {
3
+ className?: string;
4
+ size?: "default" | "icon";
5
+ placement?: DropdownPopoverProps["placement"];
6
+ themeToggle?: boolean;
7
+ variant?: ButtonProps["variant"];
8
+ };
9
+ /**
10
+ * Render a user account dropdown button that shows account actions, session switching, and theme controls.
11
+ *
12
+ * Renders either an icon-only trigger or a full button showing the current user state; its dropdown contains account settings, multi-session switching (when enabled), theme selection (when enabled), and sign-in/sign-out flows depending on authentication state.
13
+ *
14
+ * @param className - Additional CSS classes applied to the trigger element
15
+ * @param placement - Dropdown popover placement (e.g., "bottom", "top-start", "bottom-end")
16
+ * @param size - "icon" renders an avatar-only trigger; "default" renders a button with label and chevron
17
+ * @param variant - Button visual variant passed to the underlying Button component
18
+ * @param themeToggle - When true and theming is available, show theme selection controls in the menu
19
+ * @returns The user button and its dropdown menu as a JSX element
20
+ */
21
+ export declare function UserButton({ className, placement, size, variant, themeToggle }: UserButtonProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,24 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useAuth, useSession } from "@better-auth-ui/react";
3
+ import { ArrowRightFromSquare, ArrowRightToSquare, ChevronsExpandVertical, Display, Gear, Moon, PersonPlus, Persons, Sun } from "@gravity-ui/icons";
4
+ import { Button, cn, Dropdown, Label, Separator, Tabs } from "@heroui/react";
5
+ import { SwitchAccountMenu } from "./switch-account-menu";
6
+ import { UserAvatar } from "./user-avatar";
7
+ import { UserView } from "./user-view";
8
+ /**
9
+ * Render a user account dropdown button that shows account actions, session switching, and theme controls.
10
+ *
11
+ * Renders either an icon-only trigger or a full button showing the current user state; its dropdown contains account settings, multi-session switching (when enabled), theme selection (when enabled), and sign-in/sign-out flows depending on authentication state.
12
+ *
13
+ * @param className - Additional CSS classes applied to the trigger element
14
+ * @param placement - Dropdown popover placement (e.g., "bottom", "top-start", "bottom-end")
15
+ * @param size - "icon" renders an avatar-only trigger; "default" renders a button with label and chevron
16
+ * @param variant - Button visual variant passed to the underlying Button component
17
+ * @param themeToggle - When true and theming is available, show theme selection controls in the menu
18
+ * @returns The user button and its dropdown menu as a JSX element
19
+ */
20
+ export function UserButton({ className, placement = "bottom", size = "default", variant = "ghost", themeToggle = true }) {
21
+ const { basePaths, viewPaths, localization, multiSession, settings: { theme, setTheme, themes } } = useAuth();
22
+ const { data: sessionData, isPending: sessionPending } = useSession();
23
+ return (_jsxs(Dropdown, { children: [size === "icon" ? (_jsx(Dropdown.Trigger, { className: cn("rounded-full", className), children: _jsx(UserAvatar, {}) })) : (_jsxs(Button, { variant: variant, className: cn("h-auto font-normal justify-start px-3 py-2 text-left", className), children: [sessionData || sessionPending ? (_jsx(UserView, { isPending: sessionPending })) : (_jsxs(_Fragment, { children: [_jsx(UserAvatar, {}), _jsx("p", { className: "text-sm font-medium", children: localization.auth.account })] })), _jsx(ChevronsExpandVertical, { className: "ml-auto size-3.5" })] })), _jsxs(Dropdown.Popover, { placement: placement, className: "min-w-40 md:min-w-56 max-w-[48svw]", children: [sessionData && (_jsx("div", { className: "px-3 pt-3 pb-1", children: _jsx(UserView, {}) })), _jsx(Dropdown.Menu, { children: sessionData ? (_jsxs(_Fragment, { children: [_jsxs(Dropdown.Item, { textValue: localization.settings.settings, href: `${basePaths.settings}/${viewPaths.settings.account}`, children: [_jsx(Gear, { className: "text-muted" }), _jsx(Label, { children: localization.settings.settings })] }), multiSession && (_jsxs(Dropdown.SubmenuTrigger, { children: [_jsxs(Dropdown.Item, { textValue: localization.auth.switchAccount, children: [_jsx(Persons, { className: "text-muted" }), _jsx(Label, { children: localization.auth.switchAccount }), _jsx(Dropdown.SubmenuIndicator, {})] }), _jsx(Dropdown.Popover, { className: "min-w-40 md:min-w-56 max-w-[48svw]", children: _jsx(SwitchAccountMenu, {}) })] })), themeToggle && theme && setTheme && themes?.length && (_jsxs(Dropdown.Item, { className: "py-1 pe-2", children: [_jsx(Label, { children: localization.settings.theme }), _jsx(Tabs, { className: "ml-auto", selectedKey: theme, onSelectionChange: (key) => setTheme(key), children: _jsx(Tabs.ListContainer, { children: _jsxs(Tabs.List, { "aria-label": localization.settings.theme, className: "*:h-5 *:w-5 *:p-0", children: [themes.includes("system") && (_jsxs(Tabs.Tab, { id: "system", "aria-label": localization.settings.system, children: [_jsx(Display, { className: "size-3" }), _jsx(Tabs.Indicator, {})] })), themes.includes("light") && (_jsxs(Tabs.Tab, { id: "light", "aria-label": localization.settings.light, children: [_jsx(Sun, { className: "size-3" }), _jsx(Tabs.Indicator, {})] })), themes.includes("dark") && (_jsxs(Tabs.Tab, { id: "dark", "aria-label": localization.settings.dark, children: [_jsx(Moon, { className: "size-3" }), _jsx(Tabs.Indicator, {})] }))] }) }) })] })), _jsx(Separator, {}), _jsxs(Dropdown.Item, { textValue: localization.auth.signOut, href: `${basePaths.auth}/${viewPaths.auth.signOut}`, children: [_jsx(ArrowRightFromSquare, { className: "text-muted" }), _jsx(Label, { children: localization.auth.signOut })] })] })) : (_jsxs(_Fragment, { children: [_jsxs(Dropdown.Item, { textValue: localization.auth.signIn, href: `${basePaths.auth}/${viewPaths.auth.signIn}`, children: [_jsx(ArrowRightToSquare, { className: "text-muted" }), _jsx(Label, { children: localization.auth.signIn })] }), _jsxs(Dropdown.Item, { textValue: localization.auth.signUp, href: `${basePaths.auth}/${viewPaths.auth.signUp}`, children: [_jsx(PersonPlus, { className: "text-muted" }), _jsx(Label, { children: localization.auth.signUp })] })] })) })] })] }));
24
+ }
@@ -0,0 +1,21 @@
1
+ import { type AvatarProps } from "@heroui/react";
2
+ import type { User } from "better-auth";
3
+ import type { ComponentProps } from "react";
4
+ export type UserViewProps = {
5
+ className?: string;
6
+ isPending?: boolean;
7
+ size?: AvatarProps["size"];
8
+ user?: User & {
9
+ username?: string | null;
10
+ displayUsername?: string | null;
11
+ };
12
+ };
13
+ /**
14
+ * Render a compact user item with an avatar, a primary label (display username, name, or email), and an optional secondary email line.
15
+ *
16
+ * @param isPending - If true and no `user` prop is provided, renders a loading skeleton instead of user details
17
+ * @param size - Avatar size variant; defaults to `"sm"`
18
+ * @param user - Optional user to display; when omitted the current session user is used if available
19
+ * @returns A React element containing the user's avatar and text labels
20
+ */
21
+ export declare function UserView({ className, isPending, size, user, ...props }: UserViewProps & ComponentProps<"div">): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,24 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useSession } from "@better-auth-ui/react";
3
+ import { cn, Skeleton } from "@heroui/react";
4
+ import { UserAvatar } from "./user-avatar";
5
+ /**
6
+ * Render a compact user item with an avatar, a primary label (display username, name, or email), and an optional secondary email line.
7
+ *
8
+ * @param isPending - If true and no `user` prop is provided, renders a loading skeleton instead of user details
9
+ * @param size - Avatar size variant; defaults to `"sm"`
10
+ * @param user - Optional user to display; when omitted the current session user is used if available
11
+ * @returns A React element containing the user's avatar and text labels
12
+ */
13
+ export function UserView({ className, isPending, size = "sm", user, ...props }) {
14
+ const { data: sessionData, isPending: sessionPending } = useSession({
15
+ enabled: !user && !isPending
16
+ });
17
+ const resolvedUser = user ?? sessionData?.user;
18
+ if ((isPending || sessionPending) && !user) {
19
+ return (_jsxs("div", { className: cn("flex items-center gap-2 min-w-0", className), ...props, children: [_jsx(UserAvatar, { isPending: true, size: size }), _jsxs("div", { className: "flex flex-col gap-1 min-w-0", children: [_jsx(Skeleton, { className: "h-3.5 w-24 rounded-lg" }), _jsx(Skeleton, { className: "h-3 w-32 rounded-lg" })] })] }));
20
+ }
21
+ return (_jsxs("div", { className: cn("flex items-center gap-2 min-w-0", className), ...props, children: [_jsx(UserAvatar, { user: resolvedUser, size: size }), _jsxs("div", { className: "min-w-0", children: [_jsx("p", { className: "text-sm font-medium truncate leading-tight", children: resolvedUser?.displayUsername ||
22
+ resolvedUser?.name ||
23
+ resolvedUser?.email }), (resolvedUser?.displayUsername || resolvedUser?.name) && (_jsx("p", { className: "text-muted text-xs mb-0.5 truncate overflow-x-hidden", children: resolvedUser?.email }))] })] }));
24
+ }
@@ -0,0 +1 @@
1
+ export * from "@better-auth-ui/react/core";
@@ -0,0 +1 @@
1
+ export * from "@better-auth-ui/react/core";
@@ -0,0 +1,31 @@
1
+ export * from "./components/auth/auth";
2
+ export * from "./components/auth/auth-provider";
3
+ export * from "./components/auth/forgot-password";
4
+ export * from "./components/auth/magic-link";
5
+ export * from "./components/auth/magic-link-button";
6
+ export * from "./components/auth/provider-buttons";
7
+ export * from "./components/auth/reset-password";
8
+ export * from "./components/auth/sign-in";
9
+ export * from "./components/auth/sign-out";
10
+ export * from "./components/auth/sign-up";
11
+ export * from "./components/email/email-changed-email";
12
+ export * from "./components/email/email-verification-email";
13
+ export * from "./components/email/magic-link-email";
14
+ export * from "./components/email/new-device-email";
15
+ export * from "./components/email/otp-email";
16
+ export * from "./components/email/password-changed-email";
17
+ export * from "./components/email/reset-password-email";
18
+ export * from "./components/settings/account/account-settings";
19
+ export * from "./components/settings/account/appearance";
20
+ export * from "./components/settings/account/change-email";
21
+ export * from "./components/settings/account/manage-account";
22
+ export * from "./components/settings/account/manage-accounts";
23
+ export * from "./components/settings/account/user-profile";
24
+ export * from "./components/settings/security/active-sessions";
25
+ export * from "./components/settings/security/change-password";
26
+ export * from "./components/settings/security/linked-accounts";
27
+ export * from "./components/settings/security/security-settings";
28
+ export * from "./components/settings/settings";
29
+ export * from "./components/user/user-avatar";
30
+ export * from "./components/user/user-button";
31
+ export * from "./components/user/user-view";
@@ -0,0 +1,32 @@
1
+ "use client";
2
+ export * from "./components/auth/auth";
3
+ export * from "./components/auth/auth-provider";
4
+ export * from "./components/auth/forgot-password";
5
+ export * from "./components/auth/magic-link";
6
+ export * from "./components/auth/magic-link-button";
7
+ export * from "./components/auth/provider-buttons";
8
+ export * from "./components/auth/reset-password";
9
+ export * from "./components/auth/sign-in";
10
+ export * from "./components/auth/sign-out";
11
+ export * from "./components/auth/sign-up";
12
+ export * from "./components/email/email-changed-email";
13
+ export * from "./components/email/email-verification-email";
14
+ export * from "./components/email/magic-link-email";
15
+ export * from "./components/email/new-device-email";
16
+ export * from "./components/email/otp-email";
17
+ export * from "./components/email/password-changed-email";
18
+ export * from "./components/email/reset-password-email";
19
+ export * from "./components/settings/account/account-settings";
20
+ export * from "./components/settings/account/appearance";
21
+ export * from "./components/settings/account/change-email";
22
+ export * from "./components/settings/account/manage-account";
23
+ export * from "./components/settings/account/manage-accounts";
24
+ export * from "./components/settings/account/user-profile";
25
+ export * from "./components/settings/security/active-sessions";
26
+ export * from "./components/settings/security/change-password";
27
+ export * from "./components/settings/security/linked-accounts";
28
+ export * from "./components/settings/security/security-settings";
29
+ export * from "./components/settings/settings";
30
+ export * from "./components/user/user-avatar";
31
+ export * from "./components/user/user-button";
32
+ export * from "./components/user/user-view";
@@ -0,0 +1,2 @@
1
+ import { type ClassValue } from "clsx";
2
+ export declare function cn(...inputs: ClassValue[]): string;
@@ -0,0 +1,5 @@
1
+ import { clsx } from "clsx";
2
+ import { twMerge } from "tailwind-merge";
3
+ export function cn(...inputs) {
4
+ return twMerge(clsx(inputs));
5
+ }
@@ -0,0 +1 @@
1
+ export * from "@better-auth-ui/react";
@@ -0,0 +1 @@
1
+ export * from "@better-auth-ui/react";
@@ -0,0 +1 @@
1
+ @source ".";
package/package.json ADDED
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "@better-auth-ui/heroui",
3
+ "version": "1.6.0",
4
+ "type": "module",
5
+ "scripts": {
6
+ "build": "tsc && bun styles",
7
+ "dev": "bun styles && tsc --watch",
8
+ "styles": "cpy src/styles.css dist/ --flat",
9
+ "test": "vitest"
10
+ },
11
+ "files": [
12
+ "src",
13
+ "dist"
14
+ ],
15
+ "exports": {
16
+ ".": {
17
+ "import": "./dist/index.js",
18
+ "types": "./dist/index.d.ts"
19
+ },
20
+ "./core": {
21
+ "import": "./dist/core.js",
22
+ "types": "./dist/core.d.ts"
23
+ },
24
+ "./react": {
25
+ "import": "./dist/react-exports.js",
26
+ "types": "./dist/react-exports.d.ts"
27
+ },
28
+ "./styles": "./dist/styles.css"
29
+ },
30
+ "devDependencies": {
31
+ "@gravity-ui/icons": "^2.18.0",
32
+ "@heroui/react": "^3.0.2",
33
+ "@heroui/styles": "^3.0.2",
34
+ "@testing-library/react": "^16.3.2",
35
+ "@testing-library/user-event": "^14.5.2",
36
+ "@types/react": "^19.2.14",
37
+ "@vitejs/plugin-react": "^6.0.1",
38
+ "@vitest/browser-playwright": "^4.1.4",
39
+ "better-auth": "^1.6.4",
40
+ "cpy-cli": "^7.0.0",
41
+ "playwright": "^1.59.1",
42
+ "react": "^19.2.5",
43
+ "react-dom": "^19.2.5",
44
+ "bowser": "^2.11.0",
45
+ "vitest": "^4.1.4"
46
+ },
47
+ "dependencies": {
48
+ "@better-auth-ui/core": "*",
49
+ "@better-auth-ui/react": "*"
50
+ },
51
+ "peerDependencies": {
52
+ "@gravity-ui/icons": ">=2.18.0",
53
+ "@heroui/react": ">=3.0.2",
54
+ "@heroui/styles": ">=3.0.2",
55
+ "better-auth": ">=1.6.4",
56
+ "react": ">=19.2.5",
57
+ "react-dom": ">=19.2.5",
58
+ "bowser": ">=2.11.0"
59
+ },
60
+ "publishConfig": {
61
+ "access": "public"
62
+ }
63
+ }
@@ -0,0 +1,27 @@
1
+ import {
2
+ AuthProvider as AuthProviderPrimitive,
3
+ type AuthProviderProps as AuthProviderPropsPrimitive
4
+ } from "@better-auth-ui/react"
5
+ import { RouterProvider } from "@heroui/react"
6
+
7
+ export type AuthProviderProps = Omit<AuthProviderPropsPrimitive, "Link">
8
+
9
+ /**
10
+ * Provides an authentication context by rendering an auth provider with the sonner toast handler injected, forwarding remaining configuration and rendering `children` inside it.
11
+ *
12
+ * @param children - React nodes to render inside the authentication provider
13
+ * @returns A React element that renders an authentication provider configured with the provided props and toast handler
14
+ */
15
+ export function AuthProvider({
16
+ children,
17
+ navigate,
18
+ ...config
19
+ }: AuthProviderProps) {
20
+ return (
21
+ <AuthProviderPrimitive navigate={navigate} {...config}>
22
+ <RouterProvider navigate={(path) => navigate({ to: path })}>
23
+ {children}
24
+ </RouterProvider>
25
+ </AuthProviderPrimitive>
26
+ )
27
+ }
@@ -0,0 +1,87 @@
1
+ import { useAuth } from "@better-auth-ui/react"
2
+ import type { AuthView } from "@better-auth-ui/react/core"
3
+ import type { CardProps } from "@heroui/react"
4
+ import { ForgotPassword } from "./forgot-password"
5
+ import { MagicLink } from "./magic-link"
6
+ import type { SocialLayout } from "./provider-buttons"
7
+ import { ResetPassword } from "./reset-password"
8
+ import { SignIn } from "./sign-in"
9
+ import { SignOut } from "./sign-out"
10
+ import { SignUp } from "./sign-up"
11
+
12
+ export type AuthProps = {
13
+ className?: string
14
+ path?: string
15
+ socialLayout?: SocialLayout
16
+ socialPosition?: "top" | "bottom"
17
+ variant?: CardProps["variant"]
18
+ /** @remarks `AuthView` */
19
+ view?: AuthView
20
+ }
21
+
22
+ /**
23
+ * Render the appropriate authentication view based on the provided `view` or `path`.
24
+ *
25
+ * @param path - Route path used to resolve an auth view when `view` is not provided
26
+ * @param socialLayout - Social layout to apply to sign-in/sign-up/magic-link views
27
+ * @param socialPosition - Position for social buttons ("top" or "bottom")
28
+ * @param variant - Variant to apply to the card
29
+ * @param view - Explicit auth view to render (e.g., "signIn", "signUp")
30
+ * @returns The React element for the resolved authentication view
31
+ */
32
+ export function Auth({
33
+ path,
34
+ socialLayout,
35
+ socialPosition,
36
+ view,
37
+ ...props
38
+ }: AuthProps & CardProps) {
39
+ const { viewPaths } = useAuth()
40
+
41
+ if (!view && !path) {
42
+ throw new Error("[Better Auth UI] Either `view` or `path` must be provided")
43
+ }
44
+
45
+ const authPathViews = Object.fromEntries(
46
+ Object.entries(viewPaths.auth).map(([k, v]) => [v, k])
47
+ ) as Record<string, AuthView>
48
+
49
+ const currentView = view || (path ? authPathViews[path] : undefined)
50
+
51
+ switch (currentView) {
52
+ case "signIn":
53
+ return (
54
+ <SignIn
55
+ socialLayout={socialLayout}
56
+ socialPosition={socialPosition}
57
+ {...props}
58
+ />
59
+ )
60
+ case "signUp":
61
+ return (
62
+ <SignUp
63
+ socialLayout={socialLayout}
64
+ socialPosition={socialPosition}
65
+ {...props}
66
+ />
67
+ )
68
+ case "magicLink":
69
+ return (
70
+ <MagicLink
71
+ socialLayout={socialLayout}
72
+ socialPosition={socialPosition}
73
+ {...props}
74
+ />
75
+ )
76
+ case "forgotPassword":
77
+ return <ForgotPassword {...props} />
78
+ case "resetPassword":
79
+ return <ResetPassword {...props} />
80
+ case "signOut":
81
+ return <SignOut {...props} />
82
+ default:
83
+ throw new Error(
84
+ `[Better Auth UI] Valid views are: ${Object.keys(viewPaths.auth).join(", ")}`
85
+ )
86
+ }
87
+ }
@@ -0,0 +1,14 @@
1
+ import { Separator } from "@heroui/react"
2
+ import type { ReactNode } from "react"
3
+
4
+ export function FieldSeparator({ children }: { children: ReactNode }) {
5
+ return (
6
+ <div className="flex items-center gap-4">
7
+ <Separator className="flex-1" />
8
+
9
+ <p className="text-xs text-muted shrink-0">{children}</p>
10
+
11
+ <Separator className="flex-1" />
12
+ </div>
13
+ )
14
+ }