@better-auth-ui/heroui 1.6.8 → 1.6.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (195) hide show
  1. package/dist/components/auth/api-key/api-key.d.ts +5 -1
  2. package/dist/components/auth/api-key/api-keys-empty.d.ts +3 -1
  3. package/dist/components/auth/api-key/api-keys.d.ts +9 -1
  4. package/dist/components/auth/api-key/create-api-key-dialog.d.ts +3 -1
  5. package/dist/components/auth/api-key/delete-api-key-dialog.d.ts +3 -1
  6. package/dist/components/auth/api-key/organization-api-keys.d.ts +14 -0
  7. package/dist/components/auth/delete-user/danger-zone.d.ts +1 -1
  8. package/dist/components/auth/delete-user/{delete-user.d.ts → delete-account.d.ts} +2 -2
  9. package/dist/components/auth/email/organization-invitation-email.d.ts +3 -0
  10. package/dist/components/auth/multi-session/switch-account-submenu-content.d.ts +3 -1
  11. package/dist/components/auth/multi-session/switch-account-submenu-item.d.ts +2 -1
  12. package/dist/components/auth/multi-session/switch-account-submenu.d.ts +2 -1
  13. package/dist/components/auth/organization/change-organization-logo.d.ts +4 -0
  14. package/dist/components/auth/organization/create-organization-dialog.d.ts +13 -0
  15. package/dist/components/auth/organization/delete-organization-dialog.d.ts +7 -0
  16. package/dist/components/auth/organization/delete-organization-skeleton.d.ts +4 -0
  17. package/dist/components/auth/organization/delete-organization.d.ts +5 -0
  18. package/dist/components/auth/organization/invite-member-dialog.d.ts +13 -0
  19. package/dist/components/auth/organization/leave-organization-dialog.d.ts +7 -0
  20. package/dist/components/auth/organization/leave-organization.d.ts +4 -0
  21. package/dist/components/auth/organization/organization-danger-zone.d.ts +16 -0
  22. package/dist/components/auth/organization/organization-invitation-row-skeleton.d.ts +5 -0
  23. package/dist/components/auth/organization/organization-invitation-row.d.ts +5 -0
  24. package/dist/components/auth/organization/organization-invitations-empty.d.ts +8 -0
  25. package/dist/components/auth/organization/organization-invitations.d.ts +9 -0
  26. package/dist/components/auth/organization/organization-logo.d.ts +15 -0
  27. package/dist/components/auth/organization/organization-member-row-skeleton.d.ts +4 -0
  28. package/dist/components/auth/organization/organization-member-row.d.ts +9 -0
  29. package/dist/components/auth/organization/organization-members.d.ts +9 -0
  30. package/dist/components/auth/organization/organization-people.d.ts +10 -0
  31. package/dist/components/auth/organization/organization-profile.d.ts +9 -0
  32. package/dist/components/auth/organization/organization-row.d.ts +8 -0
  33. package/dist/components/auth/organization/organization-settings.d.ts +12 -0
  34. package/dist/components/auth/organization/organization-switcher.d.ts +20 -0
  35. package/dist/components/auth/organization/organization-view-skeleton.d.ts +6 -0
  36. package/dist/components/auth/organization/organization-view.d.ts +15 -0
  37. package/dist/components/auth/organization/organization.d.ts +17 -0
  38. package/dist/components/auth/organization/organizations-empty.d.ts +4 -0
  39. package/dist/components/auth/organization/organizations-settings.d.ts +17 -0
  40. package/dist/components/auth/organization/organizations.d.ts +10 -0
  41. package/dist/components/auth/organization/remove-member-dialog.d.ts +9 -0
  42. package/dist/components/auth/organization/slug-field.d.ts +19 -0
  43. package/dist/components/auth/organization/user-invitation-row-skeleton.d.ts +4 -0
  44. package/dist/components/auth/organization/user-invitation-row.d.ts +10 -0
  45. package/dist/components/auth/organization/user-invitations-empty.d.ts +4 -0
  46. package/dist/components/auth/organization/user-invitations.d.ts +10 -0
  47. package/dist/components/auth/settings/settings.d.ts +1 -1
  48. package/dist/components/auth/user/user-avatar.d.ts +1 -1
  49. package/dist/components/auth/user/user-button.d.ts +4 -5
  50. package/dist/components/auth/user/user-view.d.ts +10 -4
  51. package/dist/email.d.ts +1 -0
  52. package/dist/email.js +211 -8
  53. package/dist/index.js +1682 -22
  54. package/dist/lib/auth/api-key-plugin.d.ts +5 -2
  55. package/dist/lib/auth/auth-plugin.d.ts +6 -2
  56. package/dist/lib/auth/delete-user-plugin.d.ts +4 -4
  57. package/dist/lib/auth/magic-link-plugin.d.ts +2 -2
  58. package/dist/lib/auth/multi-session-plugin.d.ts +2 -2
  59. package/dist/lib/auth/organization-plugin.d.ts +37 -0
  60. package/dist/lib/auth/passkey-plugin.d.ts +2 -2
  61. package/dist/lib/auth/theme-plugin.d.ts +3 -3
  62. package/dist/lib/auth/username-plugin.d.ts +8 -8
  63. package/dist/plugins.d.ts +25 -1
  64. package/dist/plugins.js +2824 -22
  65. package/dist/user-view--47tVtJ3.js +113 -0
  66. package/package.json +23 -18
  67. package/src/components/auth/api-key/api-key.tsx +25 -16
  68. package/src/components/auth/api-key/api-keys-empty.tsx +8 -4
  69. package/src/components/auth/api-key/api-keys.tsx +52 -14
  70. package/src/components/auth/api-key/create-api-key-dialog.tsx +15 -2
  71. package/src/components/auth/api-key/delete-api-key-dialog.tsx +10 -2
  72. package/src/components/auth/api-key/organization-api-keys.tsx +55 -0
  73. package/src/components/auth/delete-user/danger-zone.tsx +3 -3
  74. package/src/components/auth/delete-user/{delete-user.tsx → delete-account.tsx} +9 -9
  75. package/src/components/auth/email/organization-invitation-email.tsx +38 -0
  76. package/src/components/auth/error-toaster.tsx +28 -10
  77. package/src/components/auth/forgot-password.tsx +10 -2
  78. package/src/components/auth/multi-session/manage-accounts.tsx +1 -1
  79. package/src/components/auth/multi-session/switch-account-submenu-content.tsx +7 -2
  80. package/src/components/auth/multi-session/switch-account-submenu-item.tsx +4 -2
  81. package/src/components/auth/multi-session/switch-account-submenu.tsx +8 -4
  82. package/src/components/auth/organization/change-organization-logo.tsx +171 -0
  83. package/src/components/auth/organization/create-organization-dialog.tsx +133 -0
  84. package/src/components/auth/organization/delete-organization-dialog.tsx +97 -0
  85. package/src/components/auth/organization/delete-organization-skeleton.tsx +17 -0
  86. package/src/components/auth/organization/delete-organization.tsx +77 -0
  87. package/src/components/auth/organization/invite-member-dialog.tsx +177 -0
  88. package/src/components/auth/organization/leave-organization-dialog.tsx +95 -0
  89. package/src/components/auth/organization/leave-organization.tsx +59 -0
  90. package/src/components/auth/organization/organization-danger-zone.tsx +68 -0
  91. package/src/components/auth/organization/organization-invitation-row-skeleton.tsx +29 -0
  92. package/src/components/auth/organization/organization-invitation-row.tsx +97 -0
  93. package/src/components/auth/organization/organization-invitations-empty.tsx +39 -0
  94. package/src/components/auth/organization/organization-invitations.tsx +351 -0
  95. package/src/components/auth/organization/organization-logo.tsx +64 -0
  96. package/src/components/auth/organization/organization-member-row-skeleton.tsx +24 -0
  97. package/src/components/auth/organization/organization-member-row.tsx +157 -0
  98. package/src/components/auth/organization/organization-members.tsx +284 -0
  99. package/src/components/auth/organization/organization-people.tsx +26 -0
  100. package/src/components/auth/organization/organization-profile.tsx +141 -0
  101. package/src/components/auth/organization/organization-row.tsx +66 -0
  102. package/src/components/auth/organization/organization-settings.tsx +38 -0
  103. package/src/components/auth/organization/organization-switcher.tsx +233 -0
  104. package/src/components/auth/organization/organization-view-skeleton.tsx +36 -0
  105. package/src/components/auth/organization/organization-view.tsx +109 -0
  106. package/src/components/auth/organization/organization.tsx +162 -0
  107. package/src/components/auth/organization/organizations-empty.tsx +35 -0
  108. package/src/components/auth/organization/organizations-settings.tsx +36 -0
  109. package/src/components/auth/organization/organizations.tsx +80 -0
  110. package/src/components/auth/organization/remove-member-dialog.tsx +95 -0
  111. package/src/components/auth/organization/slug-field.tsx +111 -0
  112. package/src/components/auth/organization/user-invitation-row-skeleton.tsx +17 -0
  113. package/src/components/auth/organization/user-invitation-row.tsx +90 -0
  114. package/src/components/auth/organization/user-invitations-empty.tsx +30 -0
  115. package/src/components/auth/organization/user-invitations.tsx +59 -0
  116. package/src/components/auth/settings/account/change-email.tsx +1 -1
  117. package/src/components/auth/settings/account/user-profile.tsx +5 -5
  118. package/src/components/auth/settings/security/active-sessions.tsx +6 -4
  119. package/src/components/auth/settings/security/linked-accounts.tsx +2 -2
  120. package/src/components/auth/settings/settings.tsx +77 -14
  121. package/src/components/auth/user/user-avatar.tsx +4 -1
  122. package/src/components/auth/user/user-button.tsx +14 -11
  123. package/src/components/auth/user/user-view.tsx +32 -12
  124. package/src/email.ts +1 -0
  125. package/src/lib/auth/api-key-plugin.ts +10 -4
  126. package/src/lib/auth/auth-plugin.ts +6 -1
  127. package/src/lib/auth/organization-plugin.tsx +32 -0
  128. package/src/plugins.ts +25 -1
  129. package/dist/components/auth/additional-field.js +0 -270
  130. package/dist/components/auth/api-key/api-key-skeleton.js +0 -21
  131. package/dist/components/auth/api-key/api-key.js +0 -55
  132. package/dist/components/auth/api-key/api-keys-empty.js +0 -35
  133. package/dist/components/auth/api-key/api-keys.js +0 -41
  134. package/dist/components/auth/api-key/create-api-key-dialog.js +0 -74
  135. package/dist/components/auth/api-key/delete-api-key-dialog.js +0 -51
  136. package/dist/components/auth/api-key/new-api-key-dialog.js +0 -60
  137. package/dist/components/auth/auth-provider.js +0 -17
  138. package/dist/components/auth/auth.js +0 -63
  139. package/dist/components/auth/delete-user/danger-zone.js +0 -18
  140. package/dist/components/auth/delete-user/delete-user.js +0 -95
  141. package/dist/components/auth/email/email-changed-email.js +0 -30
  142. package/dist/components/auth/email/email-verification-email.js +0 -30
  143. package/dist/components/auth/email/magic-link-email.js +0 -30
  144. package/dist/components/auth/email/new-device-email.js +0 -30
  145. package/dist/components/auth/email/otp-email.js +0 -29
  146. package/dist/components/auth/email/password-changed-email.js +0 -30
  147. package/dist/components/auth/email/reset-password-email.js +0 -30
  148. package/dist/components/auth/error-toaster.js +0 -17
  149. package/dist/components/auth/field-separator.js +0 -18
  150. package/dist/components/auth/forgot-password.js +0 -89
  151. package/dist/components/auth/magic-link/magic-link-button.js +0 -20
  152. package/dist/components/auth/magic-link/magic-link.js +0 -87
  153. package/dist/components/auth/multi-session/manage-account.js +0 -49
  154. package/dist/components/auth/multi-session/manage-accounts.js +0 -34
  155. package/dist/components/auth/multi-session/switch-account-submenu-content.js +0 -28
  156. package/dist/components/auth/multi-session/switch-account-submenu-item.js +0 -20
  157. package/dist/components/auth/multi-session/switch-account-submenu.js +0 -24
  158. package/dist/components/auth/passkey/add-passkey-dialog.js +0 -65
  159. package/dist/components/auth/passkey/delete-passkey-dialog.js +0 -47
  160. package/dist/components/auth/passkey/passkey-button.js +0 -24
  161. package/dist/components/auth/passkey/passkey-skeleton.js +0 -17
  162. package/dist/components/auth/passkey/passkey.js +0 -48
  163. package/dist/components/auth/passkey/passkeys-empty.js +0 -35
  164. package/dist/components/auth/passkey/passkeys.js +0 -42
  165. package/dist/components/auth/provider-button.js +0 -25
  166. package/dist/components/auth/provider-buttons.js +0 -19
  167. package/dist/components/auth/reset-password.js +0 -147
  168. package/dist/components/auth/settings/account/account-settings.js +0 -20
  169. package/dist/components/auth/settings/account/change-avatar.js +0 -89
  170. package/dist/components/auth/settings/account/change-email.js +0 -54
  171. package/dist/components/auth/settings/account/user-profile.js +0 -86
  172. package/dist/components/auth/settings/security/active-session.js +0 -59
  173. package/dist/components/auth/settings/security/active-sessions.js +0 -34
  174. package/dist/components/auth/settings/security/change-password.js +0 -189
  175. package/dist/components/auth/settings/security/linked-account.js +0 -56
  176. package/dist/components/auth/settings/security/linked-accounts.js +0 -45
  177. package/dist/components/auth/settings/security/security-settings.js +0 -22
  178. package/dist/components/auth/settings/settings.js +0 -45
  179. package/dist/components/auth/sign-in.js +0 -133
  180. package/dist/components/auth/sign-out.js +0 -27
  181. package/dist/components/auth/sign-up.js +0 -212
  182. package/dist/components/auth/theme/appearance.js +0 -72
  183. package/dist/components/auth/theme/theme-toggle-item.js +0 -62
  184. package/dist/components/auth/user/user-avatar.js +0 -29
  185. package/dist/components/auth/user/user-button.js +0 -74
  186. package/dist/components/auth/user/user-view.js +0 -37
  187. package/dist/components/auth/username/sign-in-username.js +0 -148
  188. package/dist/components/auth/username/username-field.js +0 -53
  189. package/dist/lib/auth/api-key-plugin.js +0 -10
  190. package/dist/lib/auth/delete-user-plugin.js +0 -10
  191. package/dist/lib/auth/magic-link-plugin.js +0 -13
  192. package/dist/lib/auth/multi-session-plugin.js +0 -12
  193. package/dist/lib/auth/passkey-plugin.js +0 -12
  194. package/dist/lib/auth/theme-plugin.js +0 -23
  195. package/dist/lib/auth/username-plugin.js +0 -18
@@ -46,16 +46,15 @@ export type UserButtonLink = {
46
46
  export type UserButtonProps = {
47
47
  className?: string
48
48
  size?: "default" | "icon"
49
- /**
50
- * The placement of the element with respect to its anchor element.
51
- * @default "bottom"
52
- */
49
+ /** The placement of the element with respect to its anchor element. */
53
50
  placement?: DropdownPopoverProps["placement"]
54
51
  variant?: ButtonProps["variant"]
55
52
  /** Additional menu entries rendered above the built-in items. */
56
53
  links?: (UserButtonLink | ReactElement)[]
57
54
  /** Hide the built-in "Settings" link. Useful when replacing it via `links`. */
58
55
  hideSettings?: boolean
56
+ /** When true, the subtitle line (email when name/username is shown) is hidden. */
57
+ hideSubtitle?: boolean
59
58
  }
60
59
 
61
60
  function renderUserLink(
@@ -91,11 +90,12 @@ function renderUserLink(
91
90
  */
92
91
  export function UserButton({
93
92
  className,
94
- placement = "bottom",
93
+ placement,
95
94
  size = "default",
96
95
  variant = "ghost",
97
96
  links,
98
- hideSettings = false
97
+ hideSettings,
98
+ hideSubtitle
99
99
  }: UserButtonProps) {
100
100
  const { authClient, basePaths, viewPaths, localization, plugins } = useAuth()
101
101
 
@@ -104,7 +104,10 @@ export function UserButton({
104
104
  const userMenuItems = plugins.flatMap(
105
105
  (plugin) =>
106
106
  plugin.userMenuItems?.map((Item, index) => (
107
- <Item key={`${plugin.id}-${index.toString()}`} />
107
+ <Item
108
+ key={`${plugin.id}-${index.toString()}`}
109
+ hideSubtitle={hideSubtitle}
110
+ />
108
111
  )) ?? []
109
112
  )
110
113
 
@@ -127,12 +130,12 @@ export function UserButton({
127
130
  <Button
128
131
  variant={variant}
129
132
  className={cn(
130
- "h-auto font-normal justify-start px-3 py-2 text-left",
133
+ "h-auto font-normal justify-start px-2 py-2 text-left",
131
134
  className
132
135
  )}
133
136
  >
134
137
  {session || sessionPending ? (
135
- <UserView isPending={sessionPending} />
138
+ <UserView isPending={sessionPending} hideSubtitle={hideSubtitle} />
136
139
  ) : (
137
140
  <>
138
141
  <UserAvatar />
@@ -141,7 +144,7 @@ export function UserButton({
141
144
  </>
142
145
  )}
143
146
 
144
- <ChevronsExpandVertical className="ml-auto size-3.5" />
147
+ <ChevronsExpandVertical className="ml-auto size-3 text-muted" />
145
148
  </Button>
146
149
  )}
147
150
 
@@ -151,7 +154,7 @@ export function UserButton({
151
154
  >
152
155
  {session && (
153
156
  <div className="px-3 pt-3 pb-1">
154
- <UserView />
157
+ <UserView hideSubtitle={hideSubtitle} />
155
158
  </div>
156
159
  )}
157
160
 
@@ -12,22 +12,32 @@ export type UserViewProps = {
12
12
  className?: string
13
13
  isPending?: boolean
14
14
  size?: AvatarProps["size"]
15
+ /**
16
+ * When true, the subtitle line (email when name/username is shown) is hidden.
17
+ * @default false
18
+ */
19
+ hideSubtitle?: boolean
15
20
  /** @remarks `User` */
16
- user?: User & { username?: string | null; displayUsername?: string | null }
21
+ user?: Partial<User> & {
22
+ username?: string | null
23
+ displayUsername?: string | null
24
+ }
17
25
  }
18
26
 
19
27
  /**
20
- * Render a compact user item with an avatar, a primary label (display username, name, or email), and an optional secondary email line.
28
+ * Render a compact user item with an avatar, a primary label (display username, name, or email), and an optional subtitle (email).
21
29
  *
22
30
  * @param isPending - If true and no `user` prop is provided, renders a loading skeleton instead of user details
23
- * @param size - Avatar size variant; defaults to `"sm"`
31
+ * @param size - Avatar size variant; defaults to `"md"`
32
+ * @param hideSubtitle - When true, omits the muted subtitle row under the primary label
24
33
  * @param user - Optional user to display; when omitted the current session user is used if available
25
34
  * @returns A React element containing the user's avatar and text labels
26
35
  */
27
36
  export function UserView({
28
37
  className,
29
38
  isPending,
30
- size = "sm",
39
+ size = "md",
40
+ hideSubtitle = false,
31
41
  user,
32
42
  ...props
33
43
  }: UserViewProps & ComponentProps<"div">) {
@@ -47,11 +57,16 @@ export function UserView({
47
57
  className={cn("flex items-center gap-2 min-w-0", className)}
48
58
  {...props}
49
59
  >
50
- <UserAvatar isPending size={size} />
60
+ <UserAvatar
61
+ isPending
62
+ className={size === "sm" ? "size-5 [&>span]:text-xs" : undefined}
63
+ size={size === "lg" ? "md" : "sm"}
64
+ />
51
65
 
52
66
  <div className="flex flex-col gap-1 min-w-0">
53
67
  <Skeleton className="h-3.5 w-24 rounded-lg" />
54
- <Skeleton className="h-3 w-32 rounded-lg" />
68
+
69
+ {!hideSubtitle ? <Skeleton className="h-3 w-32 rounded-lg" /> : null}
55
70
  </div>
56
71
  </div>
57
72
  )
@@ -62,20 +77,25 @@ export function UserView({
62
77
  className={cn("flex items-center gap-2 min-w-0", className)}
63
78
  {...props}
64
79
  >
65
- <UserAvatar user={resolvedUser} size={size} />
80
+ <UserAvatar
81
+ className={size === "sm" ? "size-5 [&>span]:text-xs" : undefined}
82
+ user={resolvedUser}
83
+ size={size === "lg" ? "md" : "sm"}
84
+ />
66
85
 
67
- <div className="min-w-0">
68
- <p className="text-sm font-medium truncate leading-tight">
86
+ <div className="flex flex-col min-w-0">
87
+ <p className="text-foreground text-sm font-medium leading-tight truncate">
69
88
  {resolvedUser?.displayUsername ||
70
89
  resolvedUser?.name ||
71
90
  resolvedUser?.email}
72
91
  </p>
73
92
 
74
- {(resolvedUser?.displayUsername || resolvedUser?.name) && (
75
- <p className="text-muted text-xs mb-0.5 truncate overflow-x-hidden">
93
+ {!hideSubtitle &&
94
+ (resolvedUser?.displayUsername || resolvedUser?.name) ? (
95
+ <p className="text-muted text-xs leading-tight truncate overflow-x-hidden">
76
96
  {resolvedUser?.email}
77
97
  </p>
78
- )}
98
+ ) : null}
79
99
  </div>
80
100
  </div>
81
101
  )
package/src/email.ts CHANGED
@@ -4,6 +4,7 @@ export * from "./components/auth/email/email-changed-email"
4
4
  export * from "./components/auth/email/email-verification-email"
5
5
  export * from "./components/auth/email/magic-link-email"
6
6
  export * from "./components/auth/email/new-device-email"
7
+ export * from "./components/auth/email/organization-invitation-email"
7
8
  export * from "./components/auth/email/otp-email"
8
9
  export * from "./components/auth/email/password-changed-email"
9
10
  export * from "./components/auth/email/reset-password-email"
@@ -5,11 +5,17 @@ import {
5
5
  } from "@better-auth-ui/core/plugins"
6
6
 
7
7
  import { ApiKeys } from "../../components/auth/api-key/api-keys"
8
+ import { OrganizationApiKeys } from "../../components/auth/api-key/organization-api-keys"
8
9
 
9
10
  export const apiKeyPlugin = createAuthPlugin(
10
11
  coreApiKeyPlugin.id,
11
- (options: ApiKeyPluginOptions = {}) => ({
12
- ...coreApiKeyPlugin(options),
13
- securityCards: [ApiKeys]
14
- })
12
+ (options: ApiKeyPluginOptions = {}) => {
13
+ const core = coreApiKeyPlugin(options)
14
+
15
+ return {
16
+ ...core,
17
+ securityCards: [ApiKeys],
18
+ ...(core.organization ? { organizationCards: [OrganizationApiKeys] } : {})
19
+ }
20
+ }
15
21
  )
@@ -3,6 +3,7 @@ import type {
3
3
  AccountCardProps,
4
4
  AuthPlugin as AuthPluginPrimitive,
5
5
  AuthPluginComponents as BaseAuthPluginComponents,
6
+ OrganizationCardProps,
6
7
  SecurityCardProps,
7
8
  UserMenuItemProps
8
9
  } from "@better-auth-ui/react"
@@ -36,7 +37,7 @@ declare module "@better-auth-ui/core" {
36
37
  /** Heroui slot component shapes — inherits from the framework-agnostic defaults and narrows slots that receive a heroui variant from the host. */
37
38
  export type AuthPluginComponents = Omit<
38
39
  BaseAuthPluginComponents,
39
- "securityCards" | "accountCards"
40
+ "securityCards" | "accountCards" | "organizationCards"
40
41
  > & {
41
42
  /** Rendered as cards inside security settings */
42
43
  securityCards?: ComponentType<
@@ -46,6 +47,10 @@ export type AuthPluginComponents = Omit<
46
47
  accountCards?: ComponentType<
47
48
  AccountCardProps & { variant?: CardProps["variant"] }
48
49
  >[]
50
+ /** Rendered as cards inside the active organization's settings */
51
+ organizationCards?: ComponentType<
52
+ OrganizationCardProps & { variant?: CardProps["variant"] }
53
+ >[]
49
54
  /** Rendered as items inside the `UserButton` dropdown (e.g. account switcher). */
50
55
  userMenuItems?: ComponentType<UserMenuItemProps>[]
51
56
  }
@@ -0,0 +1,32 @@
1
+ import { createAuthPlugin } from "@better-auth-ui/core"
2
+ import {
3
+ organizationPlugin as coreOrganizationPlugin,
4
+ type OrganizationLocalization,
5
+ type OrganizationPluginOptions
6
+ } from "@better-auth-ui/core/plugins"
7
+ import { Briefcase } from "@gravity-ui/icons"
8
+ import { OrganizationsSettings } from "../../components/auth/organization/organizations-settings"
9
+
10
+ export const organizationPlugin = createAuthPlugin(
11
+ coreOrganizationPlugin.id,
12
+ (options: OrganizationPluginOptions = {}) => {
13
+ const coreOptions = coreOrganizationPlugin(options)
14
+
15
+ return {
16
+ ...coreOptions,
17
+ localization: coreOptions.localization as OrganizationLocalization,
18
+ settingsTabs: [
19
+ {
20
+ view: "organizations",
21
+ label: (
22
+ <>
23
+ <Briefcase className="text-muted" />
24
+ {coreOptions.localization.organizations}
25
+ </>
26
+ ),
27
+ component: OrganizationsSettings
28
+ }
29
+ ]
30
+ }
31
+ }
32
+ )
package/src/plugins.ts CHANGED
@@ -1,8 +1,9 @@
1
1
  "use client"
2
2
 
3
3
  export * from "./components/auth/api-key/api-keys"
4
+ export * from "./components/auth/api-key/organization-api-keys"
4
5
  export * from "./components/auth/delete-user/danger-zone"
5
- export * from "./components/auth/delete-user/delete-user"
6
+ export * from "./components/auth/delete-user/delete-account"
6
7
  // Plugin-contributed components that may be used standalone
7
8
  export * from "./components/auth/magic-link/magic-link"
8
9
  export * from "./components/auth/multi-session/manage-account"
@@ -10,6 +11,28 @@ export * from "./components/auth/multi-session/manage-accounts"
10
11
  export * from "./components/auth/multi-session/switch-account-submenu"
11
12
  export * from "./components/auth/multi-session/switch-account-submenu-content"
12
13
  export * from "./components/auth/multi-session/switch-account-submenu-item"
14
+ export * from "./components/auth/organization/change-organization-logo"
15
+ export * from "./components/auth/organization/create-organization-dialog"
16
+ export * from "./components/auth/organization/delete-organization"
17
+ export * from "./components/auth/organization/delete-organization-skeleton"
18
+ export * from "./components/auth/organization/invite-member-dialog"
19
+ export * from "./components/auth/organization/leave-organization"
20
+ export * from "./components/auth/organization/organization"
21
+ export * from "./components/auth/organization/organization-danger-zone"
22
+ export * from "./components/auth/organization/organization-invitations"
23
+ export * from "./components/auth/organization/organization-invitations-empty"
24
+ export * from "./components/auth/organization/organization-logo"
25
+ export * from "./components/auth/organization/organization-members"
26
+ export * from "./components/auth/organization/organization-people"
27
+ export * from "./components/auth/organization/organization-profile"
28
+ export * from "./components/auth/organization/organization-row"
29
+ export * from "./components/auth/organization/organization-settings"
30
+ export * from "./components/auth/organization/organization-switcher"
31
+ export * from "./components/auth/organization/organization-view"
32
+ export * from "./components/auth/organization/organization-view-skeleton"
33
+ export * from "./components/auth/organization/organizations"
34
+ export * from "./components/auth/organization/organizations-settings"
35
+ export * from "./components/auth/organization/user-invitations"
13
36
  export * from "./components/auth/passkey/passkeys"
14
37
  export * from "./components/auth/theme/appearance"
15
38
  export * from "./components/auth/theme/theme-toggle-item"
@@ -20,6 +43,7 @@ export * from "./lib/auth/auth-plugin"
20
43
  export * from "./lib/auth/delete-user-plugin"
21
44
  export * from "./lib/auth/magic-link-plugin"
22
45
  export * from "./lib/auth/multi-session-plugin"
46
+ export * from "./lib/auth/organization-plugin"
23
47
  export * from "./lib/auth/passkey-plugin"
24
48
  export * from "./lib/auth/theme-plugin"
25
49
  export * from "./lib/auth/username-plugin"
@@ -1,270 +0,0 @@
1
- import { resolveInputType as e } from "@better-auth-ui/core";
2
- import { useAuth as t } from "@better-auth-ui/react";
3
- import { Check as n, Copy as r } from "@gravity-ui/icons";
4
- import { Button as i, Calendar as a, Checkbox as o, ComboBox as s, DateField as c, DatePicker as l, FieldError as u, Input as d, InputGroup as f, Label as p, ListBox as m, NumberField as h, Select as g, Slider as _, Switch as v, TextArea as y, TextField as b, TimeField as x, toast as S } from "@heroui/react";
5
- import { fromDate as C, getLocalTimeZone as w, parseDate as T, parseDateTime as E, toCalendarDate as D, toCalendarDateTime as O } from "@internationalized/date";
6
- import { useRef as k, useState as A } from "react";
7
- import { Fragment as j, jsx as M, jsxs as N } from "react/jsx-runtime";
8
- //#region src/components/auth/additional-field.tsx
9
- function P(e) {
10
- if (e instanceof Date) return D(C(e, w()));
11
- if (typeof e == "string") try {
12
- return T(e.slice(0, 10));
13
- } catch {
14
- return;
15
- }
16
- }
17
- function F(e) {
18
- if (e instanceof Date) return O(C(e, w()));
19
- if (typeof e == "string") try {
20
- return E(e.replace(/(Z|[+-]\d{2}:?\d{2})$/, ""));
21
- } catch {
22
- return;
23
- }
24
- }
25
- function I({ getValue: e, isDisabled: a }) {
26
- let { localization: o } = t(), [s, c] = A(!1);
27
- async function l() {
28
- let t = e();
29
- if (t) try {
30
- await navigator.clipboard.writeText(t), c(!0), setTimeout(() => c(!1), 1500);
31
- } catch (e) {
32
- S.danger(e instanceof Error ? e.message : String(e));
33
- }
34
- }
35
- return /* @__PURE__ */ M(i, {
36
- isIconOnly: !0,
37
- "aria-label": o.settings.copyToClipboard,
38
- size: "sm",
39
- variant: "ghost",
40
- isDisabled: a,
41
- onPress: l,
42
- children: M(s ? n : r, { className: "size-4" })
43
- });
44
- }
45
- function L({ name: n, field: r, isPending: i, variant: S }) {
46
- let { localization: C } = t(), w = e(r), T = S === "transparent" ? "primary" : "secondary", E = k(null);
47
- if (r.render) return /* @__PURE__ */ M(j, { children: r.render({
48
- name: n,
49
- field: r,
50
- isPending: i,
51
- variant: S
52
- }) });
53
- if (w === "hidden") return /* @__PURE__ */ M("input", {
54
- type: "hidden",
55
- name: n,
56
- value: r.defaultValue == null ? "" : r.defaultValue instanceof Date ? r.defaultValue.toISOString() : String(r.defaultValue)
57
- });
58
- if (w === "textarea") return /* @__PURE__ */ N(b, {
59
- name: n,
60
- defaultValue: r.defaultValue == null ? void 0 : String(r.defaultValue),
61
- isDisabled: i,
62
- isReadOnly: r.readOnly,
63
- children: [
64
- /* @__PURE__ */ M(p, { children: r.label }),
65
- /* @__PURE__ */ M(y, {
66
- placeholder: r.placeholder,
67
- required: r.required,
68
- variant: T
69
- }),
70
- /* @__PURE__ */ M(u, {})
71
- ]
72
- });
73
- if (w === "number") {
74
- let e = r.formatOptions?.maximumFractionDigits;
75
- return /* @__PURE__ */ N(h, {
76
- name: n,
77
- defaultValue: typeof r.defaultValue == "number" ? r.defaultValue : r.defaultValue != null && r.defaultValue !== "" ? Number(r.defaultValue) : void 0,
78
- minValue: r.min,
79
- maxValue: r.max,
80
- step: r.step ?? (e ? 1 / 10 ** e : 1),
81
- formatOptions: r.formatOptions,
82
- isDisabled: i,
83
- isReadOnly: r.readOnly,
84
- variant: T,
85
- children: [
86
- /* @__PURE__ */ M(p, { children: r.label }),
87
- /* @__PURE__ */ N(h.Group, { children: [
88
- /* @__PURE__ */ M(h.DecrementButton, {}),
89
- /* @__PURE__ */ M(h.Input, {
90
- placeholder: r.placeholder,
91
- required: r.required
92
- }),
93
- /* @__PURE__ */ M(h.IncrementButton, {})
94
- ] }),
95
- /* @__PURE__ */ M(u, {})
96
- ]
97
- });
98
- }
99
- if (w === "slider") {
100
- let e = r.formatOptions?.maximumFractionDigits;
101
- return /* @__PURE__ */ N(_, {
102
- defaultValue: typeof r.defaultValue == "number" ? r.defaultValue : r.defaultValue == null ? void 0 : Number(r.defaultValue),
103
- minValue: r.min ?? 0,
104
- maxValue: r.max ?? 100,
105
- step: r.step ?? (e ? 1 / 10 ** e : 1),
106
- formatOptions: r.formatOptions,
107
- isDisabled: i || r.readOnly,
108
- className: "flex flex-col gap-2",
109
- children: [/* @__PURE__ */ N("div", {
110
- className: "flex items-center justify-between gap-2",
111
- children: [/* @__PURE__ */ M(p, { children: r.label }), /* @__PURE__ */ M(_.Output, { className: "text-sm text-muted" })]
112
- }), /* @__PURE__ */ N(_.Track, { children: [/* @__PURE__ */ M(_.Fill, {}), /* @__PURE__ */ M(_.Thumb, { name: n })] })]
113
- });
114
- }
115
- if (w === "switch") return /* @__PURE__ */ N(v, {
116
- name: n,
117
- defaultSelected: r.defaultValue === !0 || r.defaultValue === "true",
118
- isDisabled: i,
119
- isReadOnly: r.readOnly,
120
- children: [/* @__PURE__ */ M(v.Control, { children: /* @__PURE__ */ M(v.Thumb, {}) }), /* @__PURE__ */ M(p, { children: r.label })]
121
- });
122
- if (w === "checkbox") return /* @__PURE__ */ N(o, {
123
- name: n,
124
- defaultSelected: r.defaultValue === !0 || r.defaultValue === "true",
125
- isDisabled: i,
126
- isReadOnly: r.readOnly,
127
- isRequired: r.required,
128
- variant: T,
129
- children: [/* @__PURE__ */ M(o.Control, { children: /* @__PURE__ */ M(o.Indicator, {}) }), /* @__PURE__ */ M(o.Content, { children: /* @__PURE__ */ M(p, { children: r.label }) })]
130
- });
131
- if (w === "select") return /* @__PURE__ */ N(g, {
132
- className: "[&[data-required=true]>.label]:after:content-none",
133
- name: n,
134
- defaultValue: r.defaultValue == null ? void 0 : String(r.defaultValue),
135
- placeholder: r.placeholder,
136
- isDisabled: i || r.readOnly,
137
- isRequired: r.required,
138
- variant: T,
139
- fullWidth: !0,
140
- children: [
141
- /* @__PURE__ */ M(p, { children: r.label }),
142
- /* @__PURE__ */ N(g.Trigger, { children: [/* @__PURE__ */ M(g.Value, {}), /* @__PURE__ */ M(g.Indicator, {})] }),
143
- /* @__PURE__ */ M(g.Popover, { children: /* @__PURE__ */ M(m, { children: r.options?.map((e) => /* @__PURE__ */ N(m.Item, {
144
- id: e.value,
145
- textValue: typeof e.label == "string" ? e.label : e.value,
146
- children: [e.label, /* @__PURE__ */ M(m.ItemIndicator, {})]
147
- }, e.value)) }) }),
148
- /* @__PURE__ */ M(u, {})
149
- ]
150
- });
151
- if (w === "combobox") return /* @__PURE__ */ N(s, {
152
- className: "[&[data-required=true]>.label]:after:content-none",
153
- name: n,
154
- defaultSelectedKey: r.defaultValue == null ? void 0 : String(r.defaultValue),
155
- isDisabled: i,
156
- isReadOnly: r.readOnly,
157
- isRequired: r.required,
158
- variant: T,
159
- fullWidth: !0,
160
- children: [
161
- /* @__PURE__ */ M(p, { children: r.label }),
162
- /* @__PURE__ */ N(s.InputGroup, { children: [/* @__PURE__ */ M(d, { placeholder: r.placeholder }), /* @__PURE__ */ M(s.Trigger, {})] }),
163
- /* @__PURE__ */ M(s.Popover, { children: /* @__PURE__ */ M(m, { children: r.options?.map((e) => /* @__PURE__ */ N(m.Item, {
164
- id: e.value,
165
- textValue: typeof e.label == "string" ? e.label : e.value,
166
- children: [e.label, /* @__PURE__ */ M(m.ItemIndicator, {})]
167
- }, e.value)) }) }),
168
- /* @__PURE__ */ M(u, {})
169
- ]
170
- });
171
- if (w === "date" || w === "datetime") {
172
- let e = w === "datetime";
173
- return /* @__PURE__ */ M(l, {
174
- className: "w-full [&[data-required=true]>.label]:after:content-none",
175
- name: n,
176
- defaultValue: e ? F(r.defaultValue) : P(r.defaultValue),
177
- granularity: e ? "minute" : "day",
178
- isDisabled: i,
179
- isReadOnly: r.readOnly,
180
- isRequired: r.required,
181
- children: ({ state: t }) => /* @__PURE__ */ N(j, { children: [
182
- /* @__PURE__ */ M(p, { children: r.label }),
183
- /* @__PURE__ */ N(c.Group, {
184
- variant: T,
185
- fullWidth: !0,
186
- children: [/* @__PURE__ */ M(c.Input, { children: (e) => /* @__PURE__ */ M(c.Segment, { segment: e }) }), /* @__PURE__ */ M(c.Suffix, { children: /* @__PURE__ */ M(l.Trigger, { children: /* @__PURE__ */ M(l.TriggerIndicator, {}) }) })]
187
- }),
188
- /* @__PURE__ */ M(u, {}),
189
- /* @__PURE__ */ N(l.Popover, {
190
- className: "flex flex-col gap-3",
191
- children: [/* @__PURE__ */ N(a, {
192
- "aria-label": typeof r.label == "string" ? r.label : n,
193
- children: [
194
- /* @__PURE__ */ N(a.Header, { children: [
195
- /* @__PURE__ */ N(a.YearPickerTrigger, { children: [/* @__PURE__ */ M(a.YearPickerTriggerHeading, {}), /* @__PURE__ */ M(a.YearPickerTriggerIndicator, {})] }),
196
- /* @__PURE__ */ M(a.NavButton, { slot: "previous" }),
197
- /* @__PURE__ */ M(a.NavButton, { slot: "next" })
198
- ] }),
199
- /* @__PURE__ */ N(a.Grid, { children: [/* @__PURE__ */ M(a.GridHeader, { children: (e) => /* @__PURE__ */ M(a.HeaderCell, { children: e }) }), /* @__PURE__ */ M(a.GridBody, { children: (e) => /* @__PURE__ */ M(a.Cell, { date: e }) })] }),
200
- /* @__PURE__ */ M(a.YearPickerGrid, { children: /* @__PURE__ */ M(a.YearPickerGridBody, { children: ({ year: e }) => /* @__PURE__ */ M(a.YearPickerCell, { year: e }) }) })
201
- ]
202
- }), e && /* @__PURE__ */ N("div", {
203
- className: "flex items-center justify-between",
204
- children: [/* @__PURE__ */ M(p, { children: C.settings.time }), /* @__PURE__ */ M(x, {
205
- "aria-label": C.settings.time,
206
- granularity: "minute",
207
- value: t.timeValue,
208
- onChange: (e) => t.setTimeValue(e),
209
- children: /* @__PURE__ */ M(x.Group, {
210
- variant: "secondary",
211
- children: /* @__PURE__ */ M(x.Input, { children: (e) => /* @__PURE__ */ M(x.Segment, { segment: e }) })
212
- })
213
- })]
214
- })]
215
- })
216
- ] })
217
- });
218
- }
219
- let D = r.prefix != null, O = r.suffix != null || r.copyable, A = r.type === "number", L = r.formatOptions?.maximumFractionDigits, R = A ? "number" : void 0, z = A ? L ? "decimal" : "numeric" : void 0, B = L ? 1 / 10 ** L : void 0;
220
- return D || O ? /* @__PURE__ */ N(b, {
221
- name: n,
222
- defaultValue: r.defaultValue == null ? void 0 : String(r.defaultValue),
223
- isDisabled: i,
224
- isReadOnly: r.readOnly,
225
- children: [
226
- /* @__PURE__ */ M(p, { children: r.label }),
227
- /* @__PURE__ */ N(f, {
228
- variant: T,
229
- children: [
230
- D && /* @__PURE__ */ M(f.Prefix, { children: r.prefix }),
231
- /* @__PURE__ */ M(f.Input, {
232
- ref: E,
233
- placeholder: r.placeholder,
234
- required: r.required,
235
- type: R,
236
- inputMode: z,
237
- step: B
238
- }),
239
- r.copyable ? /* @__PURE__ */ M(f.Suffix, {
240
- className: "px-0",
241
- children: /* @__PURE__ */ M(I, {
242
- getValue: () => E.current?.value,
243
- isDisabled: i
244
- })
245
- }) : r.suffix != null && /* @__PURE__ */ M(f.Suffix, { children: r.suffix })
246
- ]
247
- }),
248
- /* @__PURE__ */ M(u, {})
249
- ]
250
- }) : /* @__PURE__ */ N(b, {
251
- name: n,
252
- defaultValue: r.defaultValue == null ? void 0 : String(r.defaultValue),
253
- isDisabled: i,
254
- isReadOnly: r.readOnly,
255
- children: [
256
- /* @__PURE__ */ M(p, { children: r.label }),
257
- /* @__PURE__ */ M(d, {
258
- placeholder: r.placeholder,
259
- required: r.required,
260
- variant: T,
261
- type: R,
262
- inputMode: z,
263
- step: B
264
- }),
265
- /* @__PURE__ */ M(u, {})
266
- ]
267
- });
268
- }
269
- //#endregion
270
- export { L as AdditionalField };
@@ -1,21 +0,0 @@
1
- import { Skeleton as e } from "@heroui/react";
2
- import { jsx as t, jsxs as n } from "react/jsx-runtime";
3
- //#region src/components/auth/api-key/api-key-skeleton.tsx
4
- function r() {
5
- return /* @__PURE__ */ t("div", {
6
- className: "flex items-center justify-between",
7
- children: /* @__PURE__ */ n("div", {
8
- className: "flex items-center gap-3",
9
- children: [/* @__PURE__ */ t(e, { className: "size-10 rounded-xl" }), /* @__PURE__ */ n("div", {
10
- className: "flex flex-col gap-1",
11
- children: [
12
- /* @__PURE__ */ t(e, { className: "h-4 w-28 rounded-lg" }),
13
- /* @__PURE__ */ t(e, { className: "h-3 w-36 rounded-lg" }),
14
- /* @__PURE__ */ t(e, { className: "h-3 w-32 rounded-lg" })
15
- ]
16
- })]
17
- })
18
- });
19
- }
20
- //#endregion
21
- export { r as ApiKeySkeleton };
@@ -1,55 +0,0 @@
1
- import { apiKeyPlugin as e } from "../../../lib/auth/api-key-plugin.js";
2
- import { DeleteApiKeyDialog as t } from "./delete-api-key-dialog.js";
3
- import { useAuth as n, useAuthPlugin as r } from "@better-auth-ui/react";
4
- import { Key as i, Xmark as a } from "@gravity-ui/icons";
5
- import { Button as o } from "@heroui/react";
6
- import { useState as s } from "react";
7
- import { jsx as c, jsxs as l } from "react/jsx-runtime";
8
- //#region src/components/auth/api-key/api-key.tsx
9
- function u({ apiKey: u }) {
10
- let { localization: d } = n(), { localization: f } = r(e), [p, m] = s(!1), h = `${u.start}${"*".repeat(16)}`;
11
- return /* @__PURE__ */ l("div", {
12
- className: "flex items-center gap-3",
13
- children: [
14
- /* @__PURE__ */ c("div", {
15
- className: "flex size-10 shrink-0 items-center justify-center rounded-xl bg-surface-secondary",
16
- children: /* @__PURE__ */ c(i, { className: "size-4.5" })
17
- }),
18
- /* @__PURE__ */ l("div", {
19
- className: "flex flex-col min-w-0",
20
- children: [
21
- /* @__PURE__ */ c("span", {
22
- className: "text-sm font-medium leading-tight truncate",
23
- children: u.name || f.apiKey
24
- }),
25
- /* @__PURE__ */ c("span", {
26
- className: "text-xs text-muted font-mono truncate",
27
- children: h
28
- }),
29
- /* @__PURE__ */ c("span", {
30
- className: "text-xs text-muted",
31
- children: new Date(u.createdAt).toLocaleString(void 0, {
32
- dateStyle: "medium",
33
- timeStyle: "short"
34
- })
35
- })
36
- ]
37
- }),
38
- /* @__PURE__ */ l(o, {
39
- className: "ml-auto shrink-0",
40
- variant: "outline",
41
- size: "sm",
42
- onPress: () => m(!0),
43
- "aria-label": f.deleteApiKey,
44
- children: [/* @__PURE__ */ c(a, {}), d.settings.delete]
45
- }),
46
- /* @__PURE__ */ c(t, {
47
- isOpen: p,
48
- onOpenChange: m,
49
- apiKey: u
50
- })
51
- ]
52
- });
53
- }
54
- //#endregion
55
- export { u as ApiKey };