@better-auth-ui/heroui 1.6.3 → 1.6.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 (204) hide show
  1. package/dist/components/auth/additional-field.d.ts +4 -0
  2. package/dist/components/auth/additional-field.js +270 -0
  3. package/dist/components/auth/auth-provider.d.ts +4 -6
  4. package/dist/components/auth/auth.d.ts +1 -1
  5. package/dist/components/auth/auth.js +54 -28
  6. package/dist/components/{settings/security → auth/delete-user}/danger-zone.d.ts +1 -1
  7. package/dist/components/{settings/security → auth/delete-user}/danger-zone.js +1 -1
  8. package/dist/components/auth/delete-user/delete-user.js +95 -0
  9. package/dist/components/{email → auth/email}/email-changed-email.d.ts +2 -2
  10. package/dist/components/{email → auth/email}/email-changed-email.js +7 -7
  11. package/dist/components/{email → auth/email}/email-verification-email.d.ts +2 -2
  12. package/dist/components/{email → auth/email}/email-verification-email.js +7 -7
  13. package/dist/components/auth/email/magic-link-email.d.ts +3 -0
  14. package/dist/components/{email → auth/email}/magic-link-email.js +7 -7
  15. package/dist/components/auth/email/new-device-email.d.ts +3 -0
  16. package/dist/components/{email → auth/email}/new-device-email.js +7 -7
  17. package/dist/components/auth/email/otp-email.d.ts +3 -0
  18. package/dist/components/{email → auth/email}/otp-email.js +6 -6
  19. package/dist/components/{email → auth/email}/password-changed-email.d.ts +2 -2
  20. package/dist/components/{email → auth/email}/password-changed-email.js +7 -7
  21. package/dist/components/{email → auth/email}/reset-password-email.d.ts +2 -2
  22. package/dist/components/{email → auth/email}/reset-password-email.js +7 -7
  23. package/dist/components/auth/forgot-password.d.ts +1 -1
  24. package/dist/components/auth/forgot-password.js +70 -48
  25. package/dist/components/auth/magic-link/magic-link-button.d.ts +11 -0
  26. package/dist/components/auth/magic-link/magic-link-button.js +20 -0
  27. package/dist/components/auth/magic-link/magic-link.d.ts +16 -0
  28. package/dist/components/auth/magic-link/magic-link.js +87 -0
  29. package/dist/components/{settings/account → auth/multi-session}/manage-account.d.ts +2 -6
  30. package/dist/components/auth/multi-session/manage-account.js +49 -0
  31. package/dist/components/auth/multi-session/manage-accounts.js +34 -0
  32. package/dist/components/{user/switch-account-menu.d.ts → auth/multi-session/switch-account-submenu-content.d.ts} +3 -3
  33. package/dist/components/auth/multi-session/switch-account-submenu-content.js +29 -0
  34. package/dist/components/{user/switch-account-item.d.ts → auth/multi-session/switch-account-submenu-item.d.ts} +2 -2
  35. package/dist/components/auth/multi-session/switch-account-submenu-item.js +20 -0
  36. package/dist/components/auth/multi-session/switch-account-submenu.d.ts +13 -0
  37. package/dist/components/auth/multi-session/switch-account-submenu.js +24 -0
  38. package/dist/components/auth/passkey/passkey-button.d.ts +6 -0
  39. package/dist/components/auth/passkey/passkey-button.js +24 -0
  40. package/dist/components/auth/passkey/passkey.js +45 -0
  41. package/dist/components/auth/passkey/passkeys.js +106 -0
  42. package/dist/components/auth/provider-button.d.ts +6 -8
  43. package/dist/components/auth/provider-button.js +16 -20
  44. package/dist/components/auth/provider-buttons.d.ts +3 -4
  45. package/dist/components/auth/provider-buttons.js +9 -10
  46. package/dist/components/auth/reset-password.js +110 -107
  47. package/dist/components/{settings → auth/settings}/account/account-settings.d.ts +5 -2
  48. package/dist/components/auth/settings/account/account-settings.js +20 -0
  49. package/dist/components/auth/settings/account/change-avatar.js +89 -0
  50. package/dist/components/{settings → auth/settings}/account/change-email.js +17 -17
  51. package/dist/components/{settings → auth/settings}/account/user-profile.d.ts +2 -3
  52. package/dist/components/auth/settings/account/user-profile.js +86 -0
  53. package/dist/components/auth/settings/security/active-session.js +59 -0
  54. package/dist/components/{settings → auth/settings}/security/active-sessions.js +4 -4
  55. package/dist/components/auth/settings/security/change-password.js +189 -0
  56. package/dist/components/auth/settings/security/linked-account.js +56 -0
  57. package/dist/components/{settings → auth/settings}/security/linked-accounts.js +5 -5
  58. package/dist/components/{settings → auth/settings}/security/security-settings.d.ts +1 -1
  59. package/dist/components/auth/settings/security/security-settings.js +22 -0
  60. package/dist/components/auth/settings/settings.js +45 -0
  61. package/dist/components/auth/sign-in.js +66 -85
  62. package/dist/components/auth/sign-out.js +11 -11
  63. package/dist/components/auth/sign-up.js +128 -148
  64. package/dist/components/{settings/account → auth/theme}/appearance.d.ts +3 -6
  65. package/dist/components/auth/theme/appearance.js +72 -0
  66. package/dist/components/auth/theme/theme-toggle-item.d.ts +5 -0
  67. package/dist/components/auth/theme/theme-toggle-item.js +58 -0
  68. package/dist/components/auth/user/user-avatar.js +29 -0
  69. package/dist/components/{user → auth/user}/user-button.d.ts +2 -6
  70. package/dist/components/auth/user/user-button.js +55 -0
  71. package/dist/components/auth/user/user-view.js +37 -0
  72. package/dist/components/auth/username/sign-in-username.d.ts +14 -0
  73. package/dist/components/auth/username/sign-in-username.js +148 -0
  74. package/dist/components/auth/username/username-field.d.ts +8 -0
  75. package/dist/components/auth/username/username-field.js +53 -0
  76. package/dist/email.d.ts +7 -0
  77. package/dist/email.js +9 -0
  78. package/dist/index.d.ts +12 -27
  79. package/dist/index.js +20 -35
  80. package/dist/lib/auth/auth-plugin.d.ts +44 -0
  81. package/dist/lib/auth/delete-user-plugin.d.ts +17 -0
  82. package/dist/lib/auth/delete-user-plugin.js +10 -0
  83. package/dist/lib/auth/magic-link-plugin.d.ts +31 -0
  84. package/dist/lib/auth/magic-link-plugin.js +13 -0
  85. package/dist/lib/auth/multi-session-plugin.d.ts +18 -0
  86. package/dist/lib/auth/multi-session-plugin.js +12 -0
  87. package/dist/lib/auth/passkey-plugin.d.ts +20 -0
  88. package/dist/lib/auth/passkey-plugin.js +12 -0
  89. package/dist/lib/auth/theme-plugin.d.ts +68 -0
  90. package/dist/lib/auth/theme-plugin.js +23 -0
  91. package/dist/lib/auth/username-plugin.d.ts +63 -0
  92. package/dist/lib/auth/username-plugin.js +18 -0
  93. package/dist/plugins.d.ts +20 -0
  94. package/dist/plugins.js +21 -0
  95. package/package.json +19 -21
  96. package/src/components/auth/additional-field.tsx +554 -0
  97. package/src/components/auth/auth-provider.tsx +5 -6
  98. package/src/components/auth/auth.tsx +99 -35
  99. package/src/components/{settings/security → auth/delete-user}/danger-zone.tsx +1 -1
  100. package/src/components/{settings/security → auth/delete-user}/delete-user.tsx +30 -20
  101. package/src/components/{email → auth/email}/email-changed-email.tsx +2 -2
  102. package/src/components/{email → auth/email}/email-verification-email.tsx +2 -2
  103. package/src/components/{email → auth/email}/magic-link-email.tsx +2 -2
  104. package/src/components/{email → auth/email}/new-device-email.tsx +2 -2
  105. package/src/components/{email → auth/email}/otp-email.tsx +2 -2
  106. package/src/components/{email → auth/email}/password-changed-email.tsx +2 -2
  107. package/src/components/{email → auth/email}/reset-password-email.tsx +2 -2
  108. package/src/components/auth/forgot-password.tsx +42 -17
  109. package/src/components/auth/magic-link/magic-link-button.tsx +61 -0
  110. package/src/components/auth/{magic-link.tsx → magic-link/magic-link.tsx} +55 -40
  111. package/src/components/{settings/account → auth/multi-session}/manage-account.tsx +16 -13
  112. package/src/components/{settings/account → auth/multi-session}/manage-accounts.tsx +14 -5
  113. package/src/components/{user/switch-account-menu.tsx → auth/multi-session/switch-account-submenu-content.tsx} +18 -11
  114. package/src/components/{user/switch-account-item.tsx → auth/multi-session/switch-account-submenu-item.tsx} +17 -5
  115. package/src/components/auth/multi-session/switch-account-submenu.tsx +50 -0
  116. package/src/components/auth/passkey/passkey-button.tsx +56 -0
  117. package/src/components/{settings/security → auth/passkey}/passkey.tsx +20 -6
  118. package/src/components/auth/passkey/passkeys.tsx +196 -0
  119. package/src/components/auth/provider-button.tsx +27 -29
  120. package/src/components/auth/provider-buttons.tsx +6 -11
  121. package/src/components/auth/reset-password.tsx +13 -7
  122. package/src/components/{settings → auth/settings}/account/account-settings.tsx +15 -13
  123. package/src/components/{settings → auth/settings}/account/change-avatar.tsx +4 -3
  124. package/src/components/{settings → auth/settings}/account/change-email.tsx +3 -3
  125. package/src/components/auth/settings/account/user-profile.tsx +171 -0
  126. package/src/components/{settings → auth/settings}/security/active-session.tsx +8 -5
  127. package/src/components/{settings → auth/settings}/security/active-sessions.tsx +3 -3
  128. package/src/components/{settings → auth/settings}/security/change-password.tsx +14 -9
  129. package/src/components/{settings → auth/settings}/security/linked-account.tsx +12 -8
  130. package/src/components/{settings → auth/settings}/security/linked-accounts.tsx +2 -2
  131. package/src/components/{settings → auth/settings}/security/security-settings.tsx +7 -6
  132. package/src/components/{settings → auth/settings}/settings.tsx +2 -2
  133. package/src/components/auth/sign-in.tsx +50 -61
  134. package/src/components/auth/sign-out.tsx +2 -2
  135. package/src/components/auth/sign-up.tsx +119 -131
  136. package/src/components/{settings/account → auth/theme}/appearance.tsx +17 -24
  137. package/src/components/auth/theme/theme-toggle-item.tsx +110 -0
  138. package/src/components/{user → auth/user}/user-avatar.tsx +12 -4
  139. package/src/components/{user → auth/user}/user-button.tsx +15 -88
  140. package/src/components/{user → auth/user}/user-view.tsx +12 -4
  141. package/src/components/auth/username/sign-in-username.tsx +299 -0
  142. package/src/components/auth/username/username-field.tsx +124 -0
  143. package/src/email.ts +9 -0
  144. package/src/index.tsx +12 -27
  145. package/src/lib/auth/auth-plugin.ts +67 -0
  146. package/src/lib/auth/delete-user-plugin.ts +15 -0
  147. package/src/lib/auth/magic-link-plugin.ts +26 -0
  148. package/src/lib/auth/multi-session-plugin.ts +17 -0
  149. package/src/lib/auth/passkey-plugin.ts +17 -0
  150. package/src/lib/auth/theme-plugin.ts +86 -0
  151. package/src/lib/auth/username-plugin.tsx +30 -0
  152. package/src/plugins.ts +23 -0
  153. package/dist/components/auth/magic-link-button.d.ts +0 -13
  154. package/dist/components/auth/magic-link-button.js +0 -16
  155. package/dist/components/auth/magic-link.d.ts +0 -17
  156. package/dist/components/auth/magic-link.js +0 -99
  157. package/dist/components/auth/passkey-button.d.ts +0 -4
  158. package/dist/components/auth/passkey-button.js +0 -21
  159. package/dist/components/email/magic-link-email.d.ts +0 -3
  160. package/dist/components/email/new-device-email.d.ts +0 -3
  161. package/dist/components/email/otp-email.d.ts +0 -3
  162. package/dist/components/settings/account/account-settings.js +0 -23
  163. package/dist/components/settings/account/appearance.js +0 -71
  164. package/dist/components/settings/account/change-avatar.js +0 -89
  165. package/dist/components/settings/account/manage-account.js +0 -48
  166. package/dist/components/settings/account/manage-accounts.js +0 -33
  167. package/dist/components/settings/account/user-profile.js +0 -103
  168. package/dist/components/settings/security/active-session.js +0 -59
  169. package/dist/components/settings/security/change-password.js +0 -189
  170. package/dist/components/settings/security/delete-user.js +0 -92
  171. package/dist/components/settings/security/linked-account.js +0 -56
  172. package/dist/components/settings/security/passkey.js +0 -43
  173. package/dist/components/settings/security/passkeys.js +0 -53
  174. package/dist/components/settings/security/security-settings.js +0 -25
  175. package/dist/components/settings/settings.js +0 -45
  176. package/dist/components/user/switch-account-item.js +0 -20
  177. package/dist/components/user/switch-account-menu.js +0 -28
  178. package/dist/components/user/user-avatar.js +0 -29
  179. package/dist/components/user/user-button.js +0 -91
  180. package/dist/components/user/user-view.js +0 -37
  181. package/dist/core.d.ts +0 -1
  182. package/dist/core.js +0 -1
  183. package/dist/react-exports.d.ts +0 -1
  184. package/dist/react-exports.js +0 -1
  185. package/src/components/auth/magic-link-button.tsx +0 -43
  186. package/src/components/auth/passkey-button.tsx +0 -35
  187. package/src/components/settings/account/user-profile.tsx +0 -217
  188. package/src/components/settings/security/passkeys.tsx +0 -96
  189. package/src/core.ts +0 -1
  190. package/src/react-exports.ts +0 -1
  191. /package/dist/components/{settings/security → auth/delete-user}/delete-user.d.ts +0 -0
  192. /package/dist/components/{settings/account → auth/multi-session}/manage-accounts.d.ts +0 -0
  193. /package/dist/components/{settings/security → auth/passkey}/passkey.d.ts +0 -0
  194. /package/dist/components/{settings/security → auth/passkey}/passkeys.d.ts +0 -0
  195. /package/dist/components/{settings → auth/settings}/account/change-avatar.d.ts +0 -0
  196. /package/dist/components/{settings → auth/settings}/account/change-email.d.ts +0 -0
  197. /package/dist/components/{settings → auth/settings}/security/active-session.d.ts +0 -0
  198. /package/dist/components/{settings → auth/settings}/security/active-sessions.d.ts +0 -0
  199. /package/dist/components/{settings → auth/settings}/security/change-password.d.ts +0 -0
  200. /package/dist/components/{settings → auth/settings}/security/linked-account.d.ts +0 -0
  201. /package/dist/components/{settings → auth/settings}/security/linked-accounts.d.ts +0 -0
  202. /package/dist/components/{settings → auth/settings}/settings.d.ts +0 -0
  203. /package/dist/components/{user → auth/user}/user-avatar.d.ts +0 -0
  204. /package/dist/components/{user → auth/user}/user-view.d.ts +0 -0
@@ -0,0 +1,67 @@
1
+ import type { AdditionalField as AdditionalFieldConfig } from "@better-auth-ui/core"
2
+ import type {
3
+ AccountCardProps,
4
+ AuthPlugin as AuthPluginPrimitive,
5
+ AuthPluginComponents as BaseAuthPluginComponents,
6
+ SecurityCardProps,
7
+ UserMenuItemProps
8
+ } from "@better-auth-ui/react"
9
+ import type { CardProps } from "@heroui/react"
10
+ import type { ComponentType, ReactNode } from "react"
11
+
12
+ import type { SocialLayout } from "../../components/auth/provider-buttons"
13
+
14
+ /** Props for the heroui `<AdditionalField>` component and `field.render` callbacks. */
15
+ export type AdditionalFieldProps = {
16
+ name: string
17
+ field: AdditionalFieldConfig
18
+ isPending?: boolean
19
+ variant?: CardProps["variant"]
20
+ }
21
+
22
+ // Lives here (rather than next to `<AdditionalField>`) so the augmentation
23
+ // is picked up by consumers who only import from `/plugins`.
24
+ declare module "@better-auth-ui/core" {
25
+ interface AuthPluginRegister {
26
+ heroui: AuthPlugin
27
+ }
28
+
29
+ interface AdditionalFieldRegister {
30
+ label: ReactNode
31
+ renderProps: AdditionalFieldProps
32
+ renderResult: ReactNode
33
+ }
34
+ }
35
+
36
+ /** Heroui slot component shapes — inherits from the framework-agnostic defaults and narrows slots that receive a heroui variant from the host. */
37
+ export type AuthPluginComponents = Omit<
38
+ BaseAuthPluginComponents,
39
+ "securityCards" | "accountCards"
40
+ > & {
41
+ /** Rendered as cards inside security settings */
42
+ securityCards?: ComponentType<
43
+ SecurityCardProps & { variant?: CardProps["variant"] }
44
+ >[]
45
+ /** Rendered as cards inside account settings */
46
+ accountCards?: ComponentType<
47
+ AccountCardProps & { variant?: CardProps["variant"] }
48
+ >[]
49
+ /** Rendered as items inside the `UserButton` dropdown (e.g. account switcher). */
50
+ userMenuItems?: ComponentType<UserMenuItemProps>[]
51
+ }
52
+
53
+ /** Props the heroui `<Auth>` router spreads onto plugin-contributed auth views. */
54
+ export type AuthViewProps = Omit<CardProps, "children"> & {
55
+ socialLayout?: SocialLayout
56
+ socialPosition?: "top" | "bottom"
57
+ }
58
+
59
+ /** Props the heroui `<Settings>` router spreads onto plugin-contributed settings views. */
60
+ export type SettingsViewProps = Omit<CardProps, "children">
61
+
62
+ /** Heroui plugin type. Plugin authors import this from `@better-auth-ui/heroui`. */
63
+ export type AuthPlugin = AuthPluginPrimitive<
64
+ AuthPluginComponents,
65
+ AuthViewProps,
66
+ SettingsViewProps
67
+ >
@@ -0,0 +1,15 @@
1
+ import { createAuthPlugin } from "@better-auth-ui/core"
2
+ import {
3
+ deleteUserPlugin as coreDeleteUserPlugin,
4
+ type DeleteUserPluginOptions
5
+ } from "@better-auth-ui/core/plugins"
6
+
7
+ import { DangerZone } from "../../components/auth/delete-user/danger-zone"
8
+
9
+ export const deleteUserPlugin = createAuthPlugin(
10
+ coreDeleteUserPlugin.id,
11
+ (options: DeleteUserPluginOptions = {}) => ({
12
+ ...coreDeleteUserPlugin(options),
13
+ securityCards: [DangerZone]
14
+ })
15
+ )
@@ -0,0 +1,26 @@
1
+ import { createAuthPlugin } from "@better-auth-ui/core"
2
+ import {
3
+ magicLinkPlugin as coreMagicLinkPlugin,
4
+ type MagicLinkPluginOptions
5
+ } from "@better-auth-ui/core/plugins"
6
+
7
+ import { MagicLink } from "../../components/auth/magic-link/magic-link"
8
+ import { MagicLinkButton } from "../../components/auth/magic-link/magic-link-button"
9
+
10
+ export const magicLinkPlugin = createAuthPlugin(
11
+ coreMagicLinkPlugin.id,
12
+ (options: MagicLinkPluginOptions = {}) => ({
13
+ ...coreMagicLinkPlugin(options),
14
+ authButtons: [MagicLinkButton],
15
+ views: {
16
+ auth: { magicLink: MagicLink }
17
+ },
18
+ // Conditional, not an override: when `emailAndPassword.enabled === false`
19
+ // the `<Auth>` router renders this at `/auth/sign-in` instead of the
20
+ // disabled password form. With password auth on, the built-in `SignIn`
21
+ // still wins.
22
+ fallbackViews: {
23
+ auth: { signIn: MagicLink }
24
+ }
25
+ })
26
+ )
@@ -0,0 +1,17 @@
1
+ import { createAuthPlugin } from "@better-auth-ui/core"
2
+ import {
3
+ multiSessionPlugin as coreMultiSessionPlugin,
4
+ type MultiSessionPluginOptions
5
+ } from "@better-auth-ui/core/plugins"
6
+
7
+ import { ManageAccounts } from "../../components/auth/multi-session/manage-accounts"
8
+ import { SwitchAccountSubmenu } from "../../components/auth/multi-session/switch-account-submenu"
9
+
10
+ export const multiSessionPlugin = createAuthPlugin(
11
+ coreMultiSessionPlugin.id,
12
+ (options: MultiSessionPluginOptions = {}) => ({
13
+ ...coreMultiSessionPlugin(options),
14
+ accountCards: [ManageAccounts],
15
+ userMenuItems: [SwitchAccountSubmenu]
16
+ })
17
+ )
@@ -0,0 +1,17 @@
1
+ import { createAuthPlugin } from "@better-auth-ui/core"
2
+ import {
3
+ passkeyPlugin as corePasskeyPlugin,
4
+ type PasskeyPluginOptions
5
+ } from "@better-auth-ui/core/plugins"
6
+
7
+ import { PasskeyButton } from "../../components/auth/passkey/passkey-button"
8
+ import { Passkeys } from "../../components/auth/passkey/passkeys"
9
+
10
+ export const passkeyPlugin = createAuthPlugin(
11
+ corePasskeyPlugin.id,
12
+ (options: PasskeyPluginOptions = {}) => ({
13
+ ...corePasskeyPlugin(options),
14
+ authButtons: [PasskeyButton],
15
+ securityCards: [Passkeys]
16
+ })
17
+ )
@@ -0,0 +1,86 @@
1
+ import { createAuthPlugin } from "@better-auth-ui/core"
2
+ import {
3
+ themePlugin as coreThemePlugin,
4
+ type ThemeLocalization
5
+ } from "@better-auth-ui/core/plugins"
6
+
7
+ import { Appearance } from "../../components/auth/theme/appearance"
8
+ import { ThemeToggleItem } from "../../components/auth/theme/theme-toggle-item"
9
+
10
+ /**
11
+ * Hook shape compatible with `next-themes`' `useTheme` and similar APIs. The
12
+ * hook is invoked inside the plugin factory so consumers can register the
13
+ * plugin in the same component as their `<ThemeProvider>` without an extra
14
+ * inner component.
15
+ */
16
+ export type UseThemeHook = () => {
17
+ theme?: string
18
+ setTheme: (theme: string) => void
19
+ themes?: string[]
20
+ }
21
+
22
+ type CommonThemeOptions = {
23
+ /**
24
+ * Override the plugin's default localization strings.
25
+ * @remarks `ThemeLocalization`
26
+ */
27
+ localization?: Partial<ThemeLocalization>
28
+ /**
29
+ * Available theme options.
30
+ * @default ["system", "light", "dark"]
31
+ */
32
+ themes?: string[]
33
+ }
34
+
35
+ export type ThemePluginOptions = CommonThemeOptions &
36
+ (
37
+ | {
38
+ /**
39
+ * A theme hook (e.g. next-themes' `useTheme`) called inside the
40
+ * plugin's slot components on every render. The hook owns the live
41
+ * theme value, so `theme`/`setTheme` are not accepted in this form.
42
+ */
43
+ useTheme: UseThemeHook
44
+ theme?: never
45
+ setTheme?: never
46
+ }
47
+ | {
48
+ /**
49
+ * Current theme value. Required when not using a hook so slot
50
+ * components can highlight the active option. Pass it from a
51
+ * stateful source (e.g. `useState`, Context) so updates flow
52
+ * through `<AuthProvider>` and re-render slot components.
53
+ */
54
+ theme: string
55
+ /** Setter that updates the value `theme` is read from. */
56
+ setTheme: (theme: string) => void
57
+ useTheme?: never
58
+ }
59
+ )
60
+
61
+ export const themePlugin = createAuthPlugin(
62
+ coreThemePlugin.id,
63
+ ({ useTheme, ...rest }: ThemePluginOptions) => {
64
+ // No-op `setTheme` baseline keeps core's required option satisfied on the
65
+ // hook branch (where the consumer doesn't pass a setter); on the static
66
+ // branch the spread overrides it with the consumer's real setter.
67
+ const base = coreThemePlugin({ setTheme: () => {}, ...rest })
68
+ return {
69
+ ...base,
70
+ // Slot components always call `plugin.useTheme()` — invoking the hook
71
+ // inside their render keeps it in scope of any `<ThemeProvider>` the
72
+ // consumer mounts. On the static branch the factory re-runs on every
73
+ // parent render, so the synthesized closure stays in sync with the
74
+ // consumer's `theme` state.
75
+ useTheme:
76
+ useTheme ??
77
+ (() => ({
78
+ theme: base.theme,
79
+ setTheme: base.setTheme,
80
+ themes: base.themes
81
+ })),
82
+ userMenuItems: [ThemeToggleItem],
83
+ accountCards: [Appearance]
84
+ }
85
+ }
86
+ )
@@ -0,0 +1,30 @@
1
+ import { createAuthPlugin } from "@better-auth-ui/core"
2
+ import {
3
+ usernamePlugin as coreUsernamePlugin,
4
+ type UsernamePluginOptions
5
+ } from "@better-auth-ui/core/plugins"
6
+
7
+ import { SignInUsername } from "../../components/auth/username/sign-in-username"
8
+ import { UsernameField } from "../../components/auth/username/username-field"
9
+
10
+ export const usernamePlugin = createAuthPlugin(
11
+ coreUsernamePlugin.id,
12
+ (options: UsernamePluginOptions = {}) => {
13
+ const core = coreUsernamePlugin(options)
14
+
15
+ return {
16
+ ...core,
17
+ additionalFields: core.additionalFields?.map((field) =>
18
+ field.name === "username"
19
+ ? {
20
+ ...field,
21
+ render: UsernameField
22
+ }
23
+ : field
24
+ ),
25
+ views: {
26
+ auth: { signIn: SignInUsername }
27
+ }
28
+ }
29
+ }
30
+ )
package/src/plugins.ts ADDED
@@ -0,0 +1,23 @@
1
+ "use client"
2
+
3
+ export * from "./components/auth/delete-user/danger-zone"
4
+ export * from "./components/auth/delete-user/delete-user"
5
+ // Plugin-contributed components that may be used standalone
6
+ export * from "./components/auth/magic-link/magic-link"
7
+ export * from "./components/auth/multi-session/manage-account"
8
+ export * from "./components/auth/multi-session/manage-accounts"
9
+ export * from "./components/auth/multi-session/switch-account-submenu"
10
+ export * from "./components/auth/multi-session/switch-account-submenu-content"
11
+ export * from "./components/auth/multi-session/switch-account-submenu-item"
12
+ export * from "./components/auth/passkey/passkeys"
13
+ export * from "./components/auth/theme/appearance"
14
+ export * from "./components/auth/theme/theme-toggle-item"
15
+ export * from "./components/auth/username/sign-in-username"
16
+ export * from "./components/auth/username/username-field"
17
+ export * from "./lib/auth/auth-plugin"
18
+ export * from "./lib/auth/delete-user-plugin"
19
+ export * from "./lib/auth/magic-link-plugin"
20
+ export * from "./lib/auth/multi-session-plugin"
21
+ export * from "./lib/auth/passkey-plugin"
22
+ export * from "./lib/auth/theme-plugin"
23
+ export * from "./lib/auth/username-plugin"
@@ -1,13 +0,0 @@
1
- import { AuthView } from '@better-auth-ui/core';
2
- export type MagicLinkButtonProps = {
3
- isPending: boolean;
4
- view?: AuthView;
5
- };
6
- /**
7
- * Renders a full-width tertiary link-style button that navigates to either the magic-link or sign-in route.
8
- *
9
- * @param isPending - If true, applies disabled styling and prevents interaction
10
- * @param view - Current auth view; when `"magicLink"`, the button targets the sign-in/password variant
11
- * @returns The rendered Link element with the appropriate href, icon, and label
12
- */
13
- export declare function MagicLinkButton({ isPending, view }: MagicLinkButtonProps): import("react/jsx-runtime").JSX.Element;
@@ -1,16 +0,0 @@
1
- import { useAuth as e } from "@better-auth-ui/react";
2
- import { Link as t, cn as n } from "@heroui/react";
3
- import { jsx as r, jsxs as i } from "react/jsx-runtime";
4
- import { Envelope as a, Lock as o } from "@gravity-ui/icons";
5
- import { buttonVariants as s } from "@heroui/styles";
6
- //#region src/components/auth/magic-link-button.tsx
7
- function c({ isPending: c, view: l }) {
8
- let { basePaths: u, viewPaths: d, localization: f } = e(), p = l === "magicLink";
9
- return /* @__PURE__ */ i(t, {
10
- href: `${u.auth}/${p ? d.auth.signIn : d.auth.magicLink}`,
11
- className: n(s({ variant: "tertiary" }), "w-full gap-2", c && "status-disabled pointer-events-none"),
12
- children: [r(p ? o : a, {}), f.auth.continueWith.replace("{{provider}}", p ? f.auth.password : f.auth.magicLink)]
13
- });
14
- }
15
- //#endregion
16
- export { c as MagicLinkButton };
@@ -1,17 +0,0 @@
1
- import { CardProps } from '@heroui/react';
2
- import { SocialLayout } from './provider-buttons';
3
- export type MagicLinkProps = {
4
- className?: string;
5
- socialLayout?: SocialLayout;
6
- socialPosition?: "top" | "bottom";
7
- variant?: CardProps["variant"];
8
- };
9
- /**
10
- * Render a card-based sign-in form that sends an email magic link and optionally shows social provider buttons.
11
- *
12
- * @param className - Additional CSS class names applied to the card container
13
- * @param socialLayout - Layout style for social provider buttons
14
- * @param socialPosition - Position of social provider buttons; `"top"` or `"bottom"`. Defaults to `"bottom"`.
15
- * @returns The magic-link sign-in UI as a JSX element
16
- */
17
- export declare function MagicLink({ className, socialLayout, socialPosition, variant, ...props }: MagicLinkProps & Omit<CardProps, "children">): import("react/jsx-runtime").JSX.Element;
@@ -1,99 +0,0 @@
1
- import { FieldSeparator as e } from "./field-separator.js";
2
- import { MagicLinkButton as t } from "./magic-link-button.js";
3
- import { PasskeyButton as n } from "./passkey-button.js";
4
- import { ProviderButtons as r } from "./provider-buttons.js";
5
- import { useAuth as i, useSignInMagicLink as a } from "@better-auth-ui/react";
6
- import { Button as o, Card as s, Description as c, FieldError as l, Form as u, Input as d, Label as f, Link as p, Spinner as m, TextField as h, cn as g, toast as _ } from "@heroui/react";
7
- import { Fragment as v, jsx as y, jsxs as b } from "react/jsx-runtime";
8
- import { useState as x } from "react";
9
- //#region src/components/auth/magic-link.tsx
10
- function S({ className: S, socialLayout: C, socialPosition: w = "bottom", variant: T, ...E }) {
11
- let { basePaths: D, baseURL: O, localization: k, passkey: A, redirectTo: j, socialProviders: M, viewPaths: N } = i(), [P, F] = x(""), { mutate: I, isPending: L } = a({ onSuccess: () => {
12
- F(""), _.success(k.auth.magicLinkSent);
13
- } }), R = L, z = (e) => {
14
- e.preventDefault(), I({
15
- email: P,
16
- callbackURL: `${O}${j}`
17
- });
18
- }, B = !!M?.length;
19
- return /* @__PURE__ */ b(s, {
20
- className: g("w-full max-w-sm p-4 md:p-6", S),
21
- variant: T,
22
- ...E,
23
- children: [
24
- /* @__PURE__ */ y(s.Header, { children: /* @__PURE__ */ y(s.Title, {
25
- className: "text-xl font-semibold mb-1",
26
- children: k.auth.signIn
27
- }) }),
28
- /* @__PURE__ */ b(s.Content, {
29
- className: "gap-4",
30
- children: [
31
- w === "top" && /* @__PURE__ */ b(v, { children: [!!M?.length && /* @__PURE__ */ y(r, {
32
- socialLayout: C,
33
- isPending: R
34
- }), B && /* @__PURE__ */ y(e, { children: k.auth.or })] }),
35
- /* @__PURE__ */ b(u, {
36
- onSubmit: z,
37
- className: "flex flex-col gap-4",
38
- children: [/* @__PURE__ */ b(h, {
39
- name: "email",
40
- type: "email",
41
- autoComplete: "email",
42
- isDisabled: R,
43
- value: P,
44
- onChange: F,
45
- children: [
46
- /* @__PURE__ */ y(f, { children: k.auth.email }),
47
- /* @__PURE__ */ y(d, {
48
- placeholder: k.auth.emailPlaceholder,
49
- required: !0,
50
- variant: T === "transparent" ? "primary" : "secondary"
51
- }),
52
- /* @__PURE__ */ y(l, {})
53
- ]
54
- }), /* @__PURE__ */ b("div", {
55
- className: "flex flex-col gap-3",
56
- children: [
57
- /* @__PURE__ */ b(o, {
58
- type: "submit",
59
- className: "w-full",
60
- isPending: R,
61
- children: [R && /* @__PURE__ */ y(m, {
62
- color: "current",
63
- size: "sm"
64
- }), k.auth.sendMagicLink]
65
- }),
66
- /* @__PURE__ */ y(t, {
67
- view: "magicLink",
68
- isPending: R
69
- }),
70
- A && /* @__PURE__ */ y(n, { isPending: R })
71
- ]
72
- })]
73
- }),
74
- w === "bottom" && /* @__PURE__ */ b(v, { children: [B && /* @__PURE__ */ y(e, { children: k.auth.or }), !!M?.length && /* @__PURE__ */ y(r, {
75
- socialLayout: C,
76
- isPending: R
77
- })] })
78
- ]
79
- }),
80
- /* @__PURE__ */ y(s.Footer, {
81
- className: "flex-col",
82
- children: /* @__PURE__ */ b(c, {
83
- className: "text-sm",
84
- children: [
85
- k.auth.needToCreateAnAccount,
86
- " ",
87
- /* @__PURE__ */ y(p, {
88
- href: `${D.auth}/${N.auth.signUp}`,
89
- className: "text-accent decoration-accent no-underline hover:underline",
90
- children: k.auth.signUp
91
- })
92
- ]
93
- })
94
- })
95
- ]
96
- });
97
- }
98
- //#endregion
99
- export { S as MagicLink };
@@ -1,4 +0,0 @@
1
- export type PasskeyButtonProps = {
2
- isPending: boolean;
3
- };
4
- export declare function PasskeyButton({ isPending }: PasskeyButtonProps): import("react/jsx-runtime").JSX.Element;
@@ -1,21 +0,0 @@
1
- import { useAuth as e, useSignInPasskey as t } from "@better-auth-ui/react";
2
- import { Button as n, Spinner as r } from "@heroui/react";
3
- import { jsx as i, jsxs as a } from "react/jsx-runtime";
4
- import { Fingerprint as o } from "@gravity-ui/icons";
5
- //#region src/components/auth/passkey-button.tsx
6
- function s({ isPending: s }) {
7
- let { localization: c, redirectTo: l, navigate: u } = e(), { mutate: d, isPending: f } = t({ onSuccess: () => u({ to: l }) });
8
- return /* @__PURE__ */ a(n, {
9
- className: "w-full",
10
- variant: "tertiary",
11
- isDisabled: s || f,
12
- isPending: f,
13
- onPress: () => d(),
14
- children: [f ? /* @__PURE__ */ i(r, {
15
- color: "current",
16
- size: "sm"
17
- }) : /* @__PURE__ */ i(o, {}), c.auth.continueWith.replace("{{provider}}", c.auth.passkey)]
18
- });
19
- }
20
- //#endregion
21
- export { s as PasskeyButton };
@@ -1,3 +0,0 @@
1
- import { MagicLinkEmailProps } from '@better-auth-ui/react';
2
- export type { MagicLinkEmailProps } from '@better-auth-ui/react';
3
- export declare function MagicLinkEmail({ colors, classNames, ...props }: MagicLinkEmailProps): import("react/jsx-runtime").JSX.Element;
@@ -1,3 +0,0 @@
1
- import { NewDeviceEmailProps } from '@better-auth-ui/react';
2
- export type { NewDeviceEmailProps } from '@better-auth-ui/react';
3
- export declare function NewDeviceEmail({ colors, classNames, ...props }: NewDeviceEmailProps): import("react/jsx-runtime").JSX.Element;
@@ -1,3 +0,0 @@
1
- import { OtpEmailProps } from '@better-auth-ui/react';
2
- export type { OtpEmailProps } from '@better-auth-ui/react';
3
- export declare function OtpEmail({ colors, classNames, ...props }: OtpEmailProps): import("react/jsx-runtime").JSX.Element;
@@ -1,23 +0,0 @@
1
- import { Appearance as e } from "./appearance.js";
2
- import { ChangeEmail as t } from "./change-email.js";
3
- import { ManageAccounts as n } from "./manage-accounts.js";
4
- import { UserProfile as r } from "./user-profile.js";
5
- import { useAuth as i } from "@better-auth-ui/react";
6
- import { cn as a } from "@heroui/react";
7
- import { jsx as o, jsxs as s } from "react/jsx-runtime";
8
- //#region src/components/settings/account/account-settings.tsx
9
- function c({ className: c, variant: l, ...u }) {
10
- let { multiSession: d, emailAndPassword: f, magicLink: p, appearance: { setTheme: m } } = i();
11
- return /* @__PURE__ */ s("div", {
12
- className: a("flex w-full flex-col gap-4 md:gap-6", c),
13
- ...u,
14
- children: [
15
- /* @__PURE__ */ o(r, { variant: l }),
16
- (f?.enabled || p) && /* @__PURE__ */ o(t, { variant: l }),
17
- m && /* @__PURE__ */ o(e, { variant: l }),
18
- d && /* @__PURE__ */ o(n, { variant: l })
19
- ]
20
- });
21
- }
22
- //#endregion
23
- export { c as AccountSettings };
@@ -1,71 +0,0 @@
1
- import { ThemePreviewDark as e, ThemePreviewLight as t, ThemePreviewSystem as n, useAuth as r, useSession as i } from "@better-auth-ui/react";
2
- import { Card as a, Label as o, Radio as s, RadioGroup as c, cn as l } from "@heroui/react";
3
- import { jsx as u, jsxs as d } from "react/jsx-runtime";
4
- import { Display as f, Moon as p, Sun as m } from "@gravity-ui/icons";
5
- //#region src/components/settings/account/appearance.tsx
6
- function h({ className: h, variant: g, ..._ }) {
7
- let { localization: v, appearance: { theme: y, setTheme: b, themes: x } } = r(), { data: S } = i();
8
- return !b || !x?.length ? null : /* @__PURE__ */ d("div", { children: [/* @__PURE__ */ u("h2", {
9
- className: l("text-sm font-semibold mb-3"),
10
- children: v.settings.appearance
11
- }), /* @__PURE__ */ u(a, {
12
- className: l("p-4 gap-4", h),
13
- variant: g,
14
- ..._,
15
- children: /* @__PURE__ */ d(a.Content, { children: [/* @__PURE__ */ u(o, { children: v.settings.theme }), /* @__PURE__ */ u(c, {
16
- variant: g === "transparent" ? "secondary" : "primary",
17
- value: S ? y : "",
18
- onChange: b,
19
- isDisabled: !S || !y,
20
- children: /* @__PURE__ */ d("div", {
21
- className: "grid gap-3 grid-cols-2 sm:grid-cols-3",
22
- children: [
23
- x.includes("system") && /* @__PURE__ */ u(s, {
24
- value: "system",
25
- className: l("mt-0 px-4 pb-4 pt-3 rounded-xl", "border border-transparent data-[selected=true]:border-accent data-[selected=true]:bg-accent/10", "data-[focus-visible=true]:border-accent data-[focus-visible=true]:bg-accent/10", g === "transparent" ? "bg-surface" : "bg-surface-secondary"),
26
- children: /* @__PURE__ */ d(s.Content, {
27
- className: "gap-2",
28
- children: [/* @__PURE__ */ d("div", {
29
- className: "flex gap-2 justify-between",
30
- children: [/* @__PURE__ */ d(o, {
31
- className: "flex gap-2 items-center",
32
- children: [/* @__PURE__ */ u(f, { className: "text-muted" }), v.settings.system]
33
- }), /* @__PURE__ */ u(s.Control, { children: /* @__PURE__ */ u(s.Indicator, {}) })]
34
- }), /* @__PURE__ */ u(n, { className: "w-full" })]
35
- })
36
- }),
37
- x.includes("light") && /* @__PURE__ */ u(s, {
38
- value: "light",
39
- className: l("mt-0 px-4 pb-4 pt-3 rounded-xl", "border border-transparent data-[selected=true]:border-accent data-[selected=true]:bg-accent/10", "data-[focus-visible=true]:border-accent data-[focus-visible=true]:bg-accent/10", g === "transparent" ? "bg-surface" : "bg-surface-secondary"),
40
- children: /* @__PURE__ */ d(s.Content, {
41
- className: "gap-2",
42
- children: [/* @__PURE__ */ d("div", {
43
- className: "flex gap-2 justify-between",
44
- children: [/* @__PURE__ */ d(o, {
45
- className: "flex gap-2 items-center",
46
- children: [/* @__PURE__ */ u(m, { className: "text-muted" }), v.settings.light]
47
- }), /* @__PURE__ */ u(s.Control, { children: /* @__PURE__ */ u(s.Indicator, {}) })]
48
- }), /* @__PURE__ */ u(t, { className: "w-full" })]
49
- })
50
- }),
51
- x.includes("dark") && /* @__PURE__ */ u(s, {
52
- value: "dark",
53
- className: l("mt-0 px-4 pb-4 pt-3 rounded-xl", "border border-transparent data-[selected=true]:border-accent data-[selected=true]:bg-accent/10", "data-[focus-visible=true]:border-accent data-[focus-visible=true]:bg-accent/10", g === "transparent" ? "bg-surface" : "bg-surface-secondary"),
54
- children: /* @__PURE__ */ d(s.Content, {
55
- className: "gap-2",
56
- children: [/* @__PURE__ */ d("div", {
57
- className: "flex gap-2 justify-between",
58
- children: [/* @__PURE__ */ d(o, {
59
- className: "flex gap-2 items-center",
60
- children: [/* @__PURE__ */ u(p, { className: "text-muted" }), v.settings.dark]
61
- }), /* @__PURE__ */ u(s.Control, { children: /* @__PURE__ */ u(s.Indicator, {}) })]
62
- }), /* @__PURE__ */ u(e, { className: "w-full" })]
63
- })
64
- })
65
- ]
66
- })
67
- })] })
68
- })] });
69
- }
70
- //#endregion
71
- export { h as Appearance };