@better-auth-ui/heroui 1.6.7 → 1.6.9

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 (280) hide show
  1. package/dist/components/auth/additional-field.d.ts +2 -2
  2. package/dist/components/auth/additional-field.js +133 -266
  3. package/dist/components/auth/api-key/api-key-skeleton.js +4 -20
  4. package/dist/components/auth/api-key/api-key.d.ts +6 -2
  5. package/dist/components/auth/api-key/api-key.js +16 -54
  6. package/dist/components/auth/api-key/api-keys-empty.d.ts +3 -1
  7. package/dist/components/auth/api-key/api-keys-empty.js +8 -34
  8. package/dist/components/auth/api-key/api-keys.d.ts +10 -2
  9. package/dist/components/auth/api-key/api-keys.js +21 -40
  10. package/dist/components/auth/api-key/create-api-key-dialog.d.ts +3 -1
  11. package/dist/components/auth/api-key/create-api-key-dialog.js +43 -73
  12. package/dist/components/auth/api-key/delete-api-key-dialog.d.ts +4 -2
  13. package/dist/components/auth/api-key/delete-api-key-dialog.js +16 -50
  14. package/dist/components/auth/api-key/new-api-key-dialog.js +23 -59
  15. package/dist/components/auth/api-key/organization-api-keys.d.ts +14 -0
  16. package/dist/components/auth/api-key/organization-api-keys.js +22 -0
  17. package/dist/components/auth/auth-provider.d.ts +1 -1
  18. package/dist/components/auth/auth-provider.js +10 -16
  19. package/dist/components/auth/auth.d.ts +3 -3
  20. package/dist/components/auth/auth.js +86 -61
  21. package/dist/components/auth/delete-user/danger-zone.d.ts +3 -3
  22. package/dist/components/auth/delete-user/danger-zone.js +11 -17
  23. package/dist/components/auth/delete-user/delete-account.d.ts +9 -0
  24. package/dist/components/auth/delete-user/delete-account.js +50 -0
  25. package/dist/components/auth/email/email-changed-email.d.ts +2 -2
  26. package/dist/components/auth/email/email-changed-email.js +22 -29
  27. package/dist/components/auth/email/email-verification-email.d.ts +2 -2
  28. package/dist/components/auth/email/email-verification-email.js +22 -29
  29. package/dist/components/auth/email/magic-link-email.d.ts +2 -2
  30. package/dist/components/auth/email/magic-link-email.js +22 -29
  31. package/dist/components/auth/email/new-device-email.d.ts +2 -2
  32. package/dist/components/auth/email/new-device-email.js +22 -29
  33. package/dist/components/auth/email/organization-invitation-email.d.ts +3 -0
  34. package/dist/components/auth/email/organization-invitation-email.js +23 -0
  35. package/dist/components/auth/email/otp-email.d.ts +2 -2
  36. package/dist/components/auth/email/otp-email.js +21 -28
  37. package/dist/components/auth/email/password-changed-email.d.ts +2 -2
  38. package/dist/components/auth/email/password-changed-email.js +22 -29
  39. package/dist/components/auth/email/reset-password-email.d.ts +2 -2
  40. package/dist/components/auth/email/reset-password-email.js +22 -29
  41. package/dist/components/auth/error-toaster.js +32 -16
  42. package/dist/components/auth/field-separator.d.ts +1 -1
  43. package/dist/components/auth/field-separator.js +4 -17
  44. package/dist/components/auth/forgot-password.d.ts +1 -1
  45. package/dist/components/auth/forgot-password.js +36 -88
  46. package/dist/components/auth/magic-link/magic-link-button.d.ts +1 -1
  47. package/dist/components/auth/magic-link/magic-link-button.js +33 -19
  48. package/dist/components/auth/magic-link/magic-link.d.ts +2 -2
  49. package/dist/components/auth/magic-link/magic-link.js +39 -86
  50. package/dist/components/auth/multi-session/manage-account.d.ts +1 -1
  51. package/dist/components/auth/multi-session/manage-account.js +32 -48
  52. package/dist/components/auth/multi-session/manage-accounts.d.ts +1 -1
  53. package/dist/components/auth/multi-session/manage-accounts.js +32 -33
  54. package/dist/components/auth/multi-session/switch-account-submenu-content.d.ts +3 -1
  55. package/dist/components/auth/multi-session/switch-account-submenu-content.js +24 -27
  56. package/dist/components/auth/multi-session/switch-account-submenu-item.d.ts +3 -2
  57. package/dist/components/auth/multi-session/switch-account-submenu-item.js +16 -19
  58. package/dist/components/auth/multi-session/switch-account-submenu.d.ts +2 -1
  59. package/dist/components/auth/multi-session/switch-account-submenu.js +23 -23
  60. package/dist/components/auth/organization/change-organization-logo.d.ts +4 -0
  61. package/dist/components/auth/organization/change-organization-logo.js +69 -0
  62. package/dist/components/auth/organization/create-organization-dialog.d.ts +13 -0
  63. package/dist/components/auth/organization/create-organization-dialog.js +37 -0
  64. package/dist/components/auth/organization/delete-organization-dialog.d.ts +7 -0
  65. package/dist/components/auth/organization/delete-organization-dialog.js +25 -0
  66. package/dist/components/auth/organization/delete-organization-skeleton.d.ts +4 -0
  67. package/dist/components/auth/organization/delete-organization-skeleton.js +8 -0
  68. package/dist/components/auth/organization/delete-organization.d.ts +5 -0
  69. package/dist/components/auth/organization/delete-organization.js +27 -0
  70. package/dist/components/auth/organization/invite-member-dialog.d.ts +13 -0
  71. package/dist/components/auth/organization/invite-member-dialog.js +47 -0
  72. package/dist/components/auth/organization/leave-organization-dialog.d.ts +7 -0
  73. package/dist/components/auth/organization/leave-organization-dialog.js +21 -0
  74. package/dist/components/auth/organization/leave-organization.d.ts +4 -0
  75. package/dist/components/auth/organization/leave-organization.js +16 -0
  76. package/dist/components/auth/organization/organization-danger-zone.d.ts +16 -0
  77. package/dist/components/auth/organization/organization-danger-zone.js +23 -0
  78. package/dist/components/auth/organization/organization-invitation-row-skeleton.d.ts +5 -0
  79. package/dist/components/auth/organization/organization-invitation-row-skeleton.js +9 -0
  80. package/dist/components/auth/organization/organization-invitation-row.d.ts +5 -0
  81. package/dist/components/auth/organization/organization-invitation-row.js +31 -0
  82. package/dist/components/auth/organization/organization-invitations-empty.d.ts +8 -0
  83. package/dist/components/auth/organization/organization-invitations-empty.js +13 -0
  84. package/dist/components/auth/organization/organization-invitations.d.ts +9 -0
  85. package/dist/components/auth/organization/organization-invitations.js +66 -0
  86. package/dist/components/auth/organization/organization-logo.d.ts +15 -0
  87. package/dist/components/auth/organization/organization-logo.js +14 -0
  88. package/dist/components/auth/organization/organization-member-row-skeleton.d.ts +4 -0
  89. package/dist/components/auth/organization/organization-member-row-skeleton.js +9 -0
  90. package/dist/components/auth/organization/organization-member-row.d.ts +9 -0
  91. package/dist/components/auth/organization/organization-member-row.js +34 -0
  92. package/dist/components/auth/organization/organization-members.d.ts +9 -0
  93. package/dist/components/auth/organization/organization-members.js +67 -0
  94. package/dist/components/auth/organization/organization-people.d.ts +10 -0
  95. package/dist/components/auth/organization/organization-people.js +11 -0
  96. package/dist/components/auth/organization/organization-profile.d.ts +9 -0
  97. package/dist/components/auth/organization/organization-profile.js +34 -0
  98. package/dist/components/auth/organization/organization-row.d.ts +8 -0
  99. package/dist/components/auth/organization/organization-row.js +31 -0
  100. package/dist/components/auth/organization/organization-settings.d.ts +12 -0
  101. package/dist/components/auth/organization/organization-settings.js +13 -0
  102. package/dist/components/auth/organization/organization-switcher.d.ts +20 -0
  103. package/dist/components/auth/organization/organization-switcher.js +48 -0
  104. package/dist/components/auth/organization/organization-view-skeleton.d.ts +6 -0
  105. package/dist/components/auth/organization/organization-view-skeleton.js +9 -0
  106. package/dist/components/auth/organization/organization-view.d.ts +15 -0
  107. package/dist/components/auth/organization/organization-view.js +31 -0
  108. package/dist/components/auth/organization/organization.d.ts +17 -0
  109. package/dist/components/auth/organization/organization.js +60 -0
  110. package/dist/components/auth/organization/organizations-empty.d.ts +4 -0
  111. package/dist/components/auth/organization/organizations-empty.js +9 -0
  112. package/dist/components/auth/organization/organizations-settings.d.ts +17 -0
  113. package/dist/components/auth/organization/organizations-settings.js +17 -0
  114. package/dist/components/auth/organization/organizations.d.ts +10 -0
  115. package/dist/components/auth/organization/organizations.js +21 -0
  116. package/dist/components/auth/organization/remove-member-dialog.d.ts +9 -0
  117. package/dist/components/auth/organization/remove-member-dialog.js +20 -0
  118. package/dist/components/auth/organization/slug-field.d.ts +19 -0
  119. package/dist/components/auth/organization/slug-field.js +38 -0
  120. package/dist/components/auth/organization/user-invitation-row-skeleton.d.ts +4 -0
  121. package/dist/components/auth/organization/user-invitation-row-skeleton.js +8 -0
  122. package/dist/components/auth/organization/user-invitation-row.d.ts +10 -0
  123. package/dist/components/auth/organization/user-invitation-row.js +22 -0
  124. package/dist/components/auth/organization/user-invitations-empty.d.ts +4 -0
  125. package/dist/components/auth/organization/user-invitations-empty.js +12 -0
  126. package/dist/components/auth/organization/user-invitations.d.ts +10 -0
  127. package/dist/components/auth/organization/user-invitations.js +18 -0
  128. package/dist/components/auth/passkey/add-passkey-dialog.d.ts +5 -0
  129. package/dist/components/auth/passkey/add-passkey-dialog.js +22 -0
  130. package/dist/components/auth/passkey/delete-passkey-dialog.d.ts +11 -0
  131. package/dist/components/auth/passkey/delete-passkey-dialog.js +14 -0
  132. package/dist/components/auth/passkey/passkey-button.d.ts +1 -1
  133. package/dist/components/auth/passkey/passkey-button.js +24 -23
  134. package/dist/components/auth/passkey/passkey-skeleton.d.ts +1 -0
  135. package/dist/components/auth/passkey/passkey-skeleton.js +5 -0
  136. package/dist/components/auth/passkey/passkey.d.ts +2 -5
  137. package/dist/components/auth/passkey/passkey.js +16 -44
  138. package/dist/components/auth/passkey/passkeys-empty.d.ts +4 -0
  139. package/dist/components/auth/passkey/passkeys-empty.js +9 -0
  140. package/dist/components/auth/passkey/passkeys.d.ts +1 -1
  141. package/dist/components/auth/passkey/passkeys.js +15 -105
  142. package/dist/components/auth/provider-button.d.ts +2 -2
  143. package/dist/components/auth/provider-button.js +28 -24
  144. package/dist/components/auth/provider-buttons.js +28 -18
  145. package/dist/components/auth/reset-password.d.ts +1 -1
  146. package/dist/components/auth/reset-password.js +56 -146
  147. package/dist/components/auth/settings/account/account-settings.d.ts +2 -2
  148. package/dist/components/auth/settings/account/account-settings.js +21 -19
  149. package/dist/components/auth/settings/account/change-avatar.js +53 -88
  150. package/dist/components/auth/settings/account/change-email.d.ts +1 -1
  151. package/dist/components/auth/settings/account/change-email.js +27 -53
  152. package/dist/components/auth/settings/account/user-profile.d.ts +1 -1
  153. package/dist/components/auth/settings/account/user-profile.js +64 -85
  154. package/dist/components/auth/settings/security/active-session.d.ts +1 -1
  155. package/dist/components/auth/settings/security/active-session.js +50 -57
  156. package/dist/components/auth/settings/security/active-sessions.d.ts +1 -1
  157. package/dist/components/auth/settings/security/active-sessions.js +21 -32
  158. package/dist/components/auth/settings/security/change-password.d.ts +1 -1
  159. package/dist/components/auth/settings/security/change-password.js +76 -186
  160. package/dist/components/auth/settings/security/linked-account.d.ts +1 -1
  161. package/dist/components/auth/settings/security/linked-account.js +37 -55
  162. package/dist/components/auth/settings/security/linked-accounts.d.ts +1 -1
  163. package/dist/components/auth/settings/security/linked-accounts.js +34 -43
  164. package/dist/components/auth/settings/security/security-settings.d.ts +2 -2
  165. package/dist/components/auth/settings/security/security-settings.js +19 -21
  166. package/dist/components/auth/settings/settings.d.ts +4 -4
  167. package/dist/components/auth/settings/settings.js +52 -44
  168. package/dist/components/auth/sign-in.d.ts +2 -2
  169. package/dist/components/auth/sign-in.js +63 -132
  170. package/dist/components/auth/sign-out.js +32 -26
  171. package/dist/components/auth/sign-up.d.ts +2 -2
  172. package/dist/components/auth/sign-up.js +97 -211
  173. package/dist/components/auth/theme/appearance.d.ts +1 -1
  174. package/dist/components/auth/theme/appearance.js +23 -71
  175. package/dist/components/auth/theme/theme-toggle-item.js +56 -61
  176. package/dist/components/auth/user/user-avatar.d.ts +4 -4
  177. package/dist/components/auth/user/user-avatar.js +31 -28
  178. package/dist/components/auth/user/user-button.d.ts +6 -7
  179. package/dist/components/auth/user/user-button.js +38 -72
  180. package/dist/components/auth/user/user-view.d.ts +13 -7
  181. package/dist/components/auth/user/user-view.js +26 -36
  182. package/dist/components/auth/username/sign-in-username.d.ts +2 -2
  183. package/dist/components/auth/username/sign-in-username.js +87 -147
  184. package/dist/components/auth/username/username-field.d.ts +1 -1
  185. package/dist/components/auth/username/username-field.js +44 -52
  186. package/dist/email.d.ts +8 -7
  187. package/dist/email.js +8 -8
  188. package/dist/index.d.ts +21 -21
  189. package/dist/index.js +21 -22
  190. package/dist/lib/auth/api-key-plugin.d.ts +7 -4
  191. package/dist/lib/auth/api-key-plugin.js +12 -10
  192. package/dist/lib/auth/auth-plugin.d.ts +10 -6
  193. package/dist/lib/auth/auth-plugin.js +1 -0
  194. package/dist/lib/auth/delete-user-plugin.d.ts +6 -6
  195. package/dist/lib/auth/delete-user-plugin.js +6 -9
  196. package/dist/lib/auth/magic-link-plugin.d.ts +5 -5
  197. package/dist/lib/auth/magic-link-plugin.js +17 -12
  198. package/dist/lib/auth/multi-session-plugin.d.ts +5 -5
  199. package/dist/lib/auth/multi-session-plugin.js +8 -11
  200. package/dist/lib/auth/organization-plugin.d.ts +37 -0
  201. package/dist/lib/auth/organization-plugin.js +19 -0
  202. package/dist/lib/auth/passkey-plugin.d.ts +9 -6
  203. package/dist/lib/auth/passkey-plugin.js +8 -11
  204. package/dist/lib/auth/theme-plugin.d.ts +6 -6
  205. package/dist/lib/auth/theme-plugin.js +25 -22
  206. package/dist/lib/auth/username-plugin.d.ts +11 -11
  207. package/dist/lib/auth/username-plugin.js +18 -17
  208. package/dist/plugins.d.ts +46 -22
  209. package/dist/plugins.js +47 -22
  210. package/package.json +25 -19
  211. package/src/components/auth/api-key/api-key.tsx +25 -16
  212. package/src/components/auth/api-key/api-keys-empty.tsx +8 -4
  213. package/src/components/auth/api-key/api-keys.tsx +52 -14
  214. package/src/components/auth/api-key/create-api-key-dialog.tsx +17 -4
  215. package/src/components/auth/api-key/delete-api-key-dialog.tsx +10 -2
  216. package/src/components/auth/api-key/organization-api-keys.tsx +55 -0
  217. package/src/components/auth/delete-user/danger-zone.tsx +3 -3
  218. package/src/components/auth/delete-user/{delete-user.tsx → delete-account.tsx} +9 -9
  219. package/src/components/auth/email/organization-invitation-email.tsx +38 -0
  220. package/src/components/auth/error-toaster.tsx +28 -10
  221. package/src/components/auth/forgot-password.tsx +10 -2
  222. package/src/components/auth/multi-session/manage-accounts.tsx +1 -1
  223. package/src/components/auth/multi-session/switch-account-submenu-content.tsx +7 -2
  224. package/src/components/auth/multi-session/switch-account-submenu-item.tsx +4 -2
  225. package/src/components/auth/multi-session/switch-account-submenu.tsx +8 -4
  226. package/src/components/auth/organization/change-organization-logo.tsx +171 -0
  227. package/src/components/auth/organization/create-organization-dialog.tsx +133 -0
  228. package/src/components/auth/organization/delete-organization-dialog.tsx +97 -0
  229. package/src/components/auth/organization/delete-organization-skeleton.tsx +17 -0
  230. package/src/components/auth/organization/delete-organization.tsx +77 -0
  231. package/src/components/auth/organization/invite-member-dialog.tsx +177 -0
  232. package/src/components/auth/organization/leave-organization-dialog.tsx +95 -0
  233. package/src/components/auth/organization/leave-organization.tsx +59 -0
  234. package/src/components/auth/organization/organization-danger-zone.tsx +68 -0
  235. package/src/components/auth/organization/organization-invitation-row-skeleton.tsx +29 -0
  236. package/src/components/auth/organization/organization-invitation-row.tsx +97 -0
  237. package/src/components/auth/organization/organization-invitations-empty.tsx +39 -0
  238. package/src/components/auth/organization/organization-invitations.tsx +351 -0
  239. package/src/components/auth/organization/organization-logo.tsx +64 -0
  240. package/src/components/auth/organization/organization-member-row-skeleton.tsx +24 -0
  241. package/src/components/auth/organization/organization-member-row.tsx +157 -0
  242. package/src/components/auth/organization/organization-members.tsx +284 -0
  243. package/src/components/auth/organization/organization-people.tsx +26 -0
  244. package/src/components/auth/organization/organization-profile.tsx +141 -0
  245. package/src/components/auth/organization/organization-row.tsx +66 -0
  246. package/src/components/auth/organization/organization-settings.tsx +38 -0
  247. package/src/components/auth/organization/organization-switcher.tsx +233 -0
  248. package/src/components/auth/organization/organization-view-skeleton.tsx +36 -0
  249. package/src/components/auth/organization/organization-view.tsx +109 -0
  250. package/src/components/auth/organization/organization.tsx +162 -0
  251. package/src/components/auth/organization/organizations-empty.tsx +35 -0
  252. package/src/components/auth/organization/organizations-settings.tsx +36 -0
  253. package/src/components/auth/organization/organizations.tsx +80 -0
  254. package/src/components/auth/organization/remove-member-dialog.tsx +95 -0
  255. package/src/components/auth/organization/slug-field.tsx +111 -0
  256. package/src/components/auth/organization/user-invitation-row-skeleton.tsx +17 -0
  257. package/src/components/auth/organization/user-invitation-row.tsx +90 -0
  258. package/src/components/auth/organization/user-invitations-empty.tsx +30 -0
  259. package/src/components/auth/organization/user-invitations.tsx +59 -0
  260. package/src/components/auth/passkey/add-passkey-dialog.tsx +109 -0
  261. package/src/components/auth/passkey/delete-passkey-dialog.tsx +95 -0
  262. package/src/components/auth/passkey/passkey-skeleton.tsx +16 -0
  263. package/src/components/auth/passkey/passkey.tsx +23 -22
  264. package/src/components/auth/passkey/passkeys-empty.tsx +35 -0
  265. package/src/components/auth/passkey/passkeys.tsx +33 -154
  266. package/src/components/auth/settings/account/change-email.tsx +1 -1
  267. package/src/components/auth/settings/account/user-profile.tsx +5 -5
  268. package/src/components/auth/settings/security/active-sessions.tsx +6 -4
  269. package/src/components/auth/settings/security/linked-accounts.tsx +2 -2
  270. package/src/components/auth/settings/settings.tsx +77 -14
  271. package/src/components/auth/user/user-avatar.tsx +4 -1
  272. package/src/components/auth/user/user-button.tsx +14 -11
  273. package/src/components/auth/user/user-view.tsx +32 -12
  274. package/src/email.ts +1 -0
  275. package/src/lib/auth/api-key-plugin.ts +10 -4
  276. package/src/lib/auth/auth-plugin.ts +6 -1
  277. package/src/lib/auth/organization-plugin.tsx +32 -0
  278. package/src/plugins.ts +25 -1
  279. package/dist/components/auth/delete-user/delete-user.d.ts +0 -9
  280. package/dist/components/auth/delete-user/delete-user.js +0 -95
@@ -0,0 +1,97 @@
1
+ import {
2
+ type OrganizationAuthClient,
3
+ useAuth,
4
+ useAuthPlugin,
5
+ useDeleteOrganization
6
+ } from "@better-auth-ui/react"
7
+ import { TriangleExclamation } from "@gravity-ui/icons"
8
+ import { AlertDialog, Button, Card, Form, Spinner, toast } from "@heroui/react"
9
+ import type { Organization } from "better-auth/client"
10
+ import type { SyntheticEvent } from "react"
11
+
12
+ import { organizationPlugin } from "../../../lib/auth/organization-plugin"
13
+ import { OrganizationView } from "./organization-view"
14
+
15
+ export type DeleteOrganizationDialogProps = {
16
+ isOpen: boolean
17
+ onOpenChange: (open: boolean) => void
18
+ organization: Organization
19
+ }
20
+
21
+ export function DeleteOrganizationDialog({
22
+ isOpen,
23
+ onOpenChange,
24
+ organization
25
+ }: DeleteOrganizationDialogProps) {
26
+ const { authClient, basePaths, localization, navigate } = useAuth()
27
+ const {
28
+ localization: organizationLocalization,
29
+ viewPaths: organizationPluginViewPaths
30
+ } = useAuthPlugin(organizationPlugin)
31
+
32
+ const { mutate: deleteOrganization, isPending } = useDeleteOrganization(
33
+ authClient as OrganizationAuthClient,
34
+ {
35
+ onSuccess: () => {
36
+ onOpenChange(false)
37
+ toast.success(organizationLocalization.organizationDeleted)
38
+
39
+ navigate({
40
+ to: `${basePaths.settings}/${organizationPluginViewPaths.settings.organizations}`,
41
+ replace: true
42
+ })
43
+ }
44
+ }
45
+ )
46
+
47
+ function handleSubmit(e: SyntheticEvent<HTMLFormElement>) {
48
+ e.preventDefault()
49
+ deleteOrganization({ organizationId: organization.id })
50
+ }
51
+
52
+ return (
53
+ <AlertDialog.Backdrop isOpen={isOpen} onOpenChange={onOpenChange}>
54
+ <AlertDialog.Container>
55
+ <AlertDialog.Dialog>
56
+ <Form onSubmit={handleSubmit}>
57
+ <AlertDialog.CloseTrigger />
58
+
59
+ <AlertDialog.Header>
60
+ <AlertDialog.Icon status="danger">
61
+ <TriangleExclamation />
62
+ </AlertDialog.Icon>
63
+
64
+ <AlertDialog.Heading>
65
+ {organizationLocalization.deleteOrganization}
66
+ </AlertDialog.Heading>
67
+ </AlertDialog.Header>
68
+
69
+ <AlertDialog.Body className="flex flex-col gap-4 overflow-visible">
70
+ <p className="text-muted text-sm">
71
+ {organizationLocalization.deleteOrganizationDescription}
72
+ </p>
73
+
74
+ <Card variant="secondary">
75
+ <Card.Content>
76
+ <OrganizationView organization={organization} hideRole />
77
+ </Card.Content>
78
+ </Card>
79
+ </AlertDialog.Body>
80
+
81
+ <AlertDialog.Footer>
82
+ <Button slot="close" variant="tertiary" isDisabled={isPending}>
83
+ {localization.settings.cancel}
84
+ </Button>
85
+
86
+ <Button type="submit" variant="danger" isPending={isPending}>
87
+ {isPending && <Spinner color="current" size="sm" />}
88
+
89
+ {organizationLocalization.deleteOrganization}
90
+ </Button>
91
+ </AlertDialog.Footer>
92
+ </Form>
93
+ </AlertDialog.Dialog>
94
+ </AlertDialog.Container>
95
+ </AlertDialog.Backdrop>
96
+ )
97
+ }
@@ -0,0 +1,17 @@
1
+ import { Skeleton } from "@heroui/react"
2
+
3
+ /**
4
+ * Placeholder matching {@link DeleteOrganization} while the delete permission resolves.
5
+ */
6
+ export function DeleteOrganizationSkeleton() {
7
+ return (
8
+ <div className="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
9
+ <div className="flex flex-col gap-1">
10
+ <Skeleton className="h-3.5 w-40 rounded-lg" />
11
+ <Skeleton className="h-3 w-64 rounded-lg" />
12
+ </div>
13
+
14
+ <Skeleton className="h-8 w-36 shrink-0 rounded-full" />
15
+ </div>
16
+ )
17
+ }
@@ -0,0 +1,77 @@
1
+ import {
2
+ type OrganizationAuthClient,
3
+ useActiveOrganization,
4
+ useAuth,
5
+ useAuthPlugin,
6
+ useHasPermission
7
+ } from "@better-auth-ui/react"
8
+ import { AlertDialog, Button } from "@heroui/react"
9
+ import { useState } from "react"
10
+
11
+ import { organizationPlugin } from "../../../lib/auth/organization-plugin"
12
+ import { DeleteOrganizationDialog } from "./delete-organization-dialog"
13
+ import { DeleteOrganizationSkeleton } from "./delete-organization-skeleton"
14
+
15
+ /**
16
+ * Danger-zone row to delete the active organization. Hidden for members without
17
+ * the `organization:delete` permission.
18
+ */
19
+ export function DeleteOrganization() {
20
+ const { authClient } = useAuth()
21
+ const { localization: organizationLocalization } =
22
+ useAuthPlugin(organizationPlugin)
23
+
24
+ const { data: activeOrganization } = useActiveOrganization(
25
+ authClient as OrganizationAuthClient
26
+ )
27
+
28
+ const { data: permission, isPending: permissionPending } = useHasPermission(
29
+ authClient as OrganizationAuthClient,
30
+ {
31
+ permissions: { organization: ["delete"] }
32
+ }
33
+ )
34
+
35
+ const [confirmOpen, setConfirmOpen] = useState(false)
36
+
37
+ if (permissionPending) {
38
+ return <DeleteOrganizationSkeleton />
39
+ }
40
+
41
+ if (!permission?.success) {
42
+ return null
43
+ }
44
+
45
+ return (
46
+ <div className="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
47
+ <div>
48
+ <p className="text-sm font-medium leading-tight">
49
+ {organizationLocalization.deleteOrganization}
50
+ </p>
51
+
52
+ <p className="text-muted mt-0.5 text-xs">
53
+ {organizationLocalization.deleteOrganizationDescription}
54
+ </p>
55
+ </div>
56
+
57
+ <AlertDialog>
58
+ <Button
59
+ isDisabled={!activeOrganization}
60
+ size="sm"
61
+ variant="danger-soft"
62
+ onPress={() => setConfirmOpen(true)}
63
+ >
64
+ {organizationLocalization.deleteOrganization}
65
+ </Button>
66
+
67
+ {activeOrganization && (
68
+ <DeleteOrganizationDialog
69
+ isOpen={confirmOpen}
70
+ onOpenChange={setConfirmOpen}
71
+ organization={activeOrganization}
72
+ />
73
+ )}
74
+ </AlertDialog>
75
+ </div>
76
+ )
77
+ }
@@ -0,0 +1,177 @@
1
+ import {
2
+ type OrganizationAuthClient,
3
+ useAuth,
4
+ useAuthPlugin,
5
+ useInviteMember
6
+ } from "@better-auth-ui/react"
7
+ import { PersonPlus } from "@gravity-ui/icons"
8
+ import {
9
+ AlertDialog,
10
+ Button,
11
+ FieldError,
12
+ Form,
13
+ Input,
14
+ Label,
15
+ ListBox,
16
+ Select,
17
+ Spinner,
18
+ TextField,
19
+ toast
20
+ } from "@heroui/react"
21
+ import { type SyntheticEvent, useEffect, useState } from "react"
22
+
23
+ import { organizationPlugin } from "../../../lib/auth/organization-plugin"
24
+
25
+ /** Props for the {@link InviteMemberDialog} component. */
26
+ export type InviteMemberDialogProps = {
27
+ isOpen: boolean
28
+ onOpenChange: (open: boolean) => void
29
+ }
30
+
31
+ const pickDefaultRole = (keys: string[]) =>
32
+ keys.includes("member") ? "member" : (keys.at(-1) ?? "")
33
+
34
+ /**
35
+ * Render a dialog for inviting a member to the organization.
36
+ *
37
+ * @param isOpen - Whether the dialog is open
38
+ * @param onOpenChange - Callback for when the dialog open state changes
39
+ * @returns The invite member dialog as a JSX element
40
+ */
41
+ export function InviteMemberDialog({
42
+ isOpen,
43
+ onOpenChange
44
+ }: InviteMemberDialogProps) {
45
+ const { authClient, localization } = useAuth()
46
+ const { localization: organizationLocalization, roles } =
47
+ useAuthPlugin(organizationPlugin)
48
+
49
+ const [role, setRole] = useState(() => pickDefaultRole(Object.keys(roles)))
50
+
51
+ useEffect(() => {
52
+ setRole((current) => {
53
+ const keys = Object.keys(roles)
54
+ return keys.includes(current) ? current : pickDefaultRole(keys)
55
+ })
56
+ }, [roles])
57
+
58
+ const { mutate: inviteMember, isPending: isInviting } = useInviteMember(
59
+ authClient as OrganizationAuthClient,
60
+ {
61
+ onSuccess: () => {
62
+ onOpenChange(false)
63
+ toast.success(organizationLocalization.inviteMemberSuccess)
64
+ }
65
+ }
66
+ )
67
+
68
+ const isRoleValid = Object.keys(roles).includes(role)
69
+
70
+ const handleSubmit = (e: SyntheticEvent<HTMLFormElement>) => {
71
+ e.preventDefault()
72
+
73
+ if (!isRoleValid) return
74
+
75
+ const formData = new FormData(e.target as HTMLFormElement)
76
+ const email = formData.get("email") as string
77
+
78
+ inviteMember({
79
+ email: email.trim(),
80
+ role: role as Parameters<typeof inviteMember>[0]["role"]
81
+ })
82
+ }
83
+
84
+ return (
85
+ <AlertDialog.Backdrop isOpen={isOpen} onOpenChange={onOpenChange}>
86
+ <AlertDialog.Container>
87
+ <AlertDialog.Dialog>
88
+ <Form onSubmit={handleSubmit}>
89
+ <AlertDialog.CloseTrigger />
90
+
91
+ <AlertDialog.Header>
92
+ <AlertDialog.Icon status="default">
93
+ <PersonPlus />
94
+ </AlertDialog.Icon>
95
+
96
+ <AlertDialog.Heading>
97
+ {organizationLocalization.inviteMember}
98
+ </AlertDialog.Heading>
99
+ </AlertDialog.Header>
100
+
101
+ <AlertDialog.Body className="flex flex-col gap-4 overflow-visible">
102
+ <p className="text-muted text-sm">
103
+ {organizationLocalization.inviteMemberDescription}
104
+ </p>
105
+
106
+ <TextField
107
+ id="email"
108
+ name="email"
109
+ type="email"
110
+ isDisabled={isInviting}
111
+ >
112
+ <Label>{localization.auth.email}</Label>
113
+
114
+ <Input
115
+ autoFocus
116
+ placeholder={localization.auth.email}
117
+ variant="secondary"
118
+ required
119
+ />
120
+
121
+ <FieldError />
122
+ </TextField>
123
+
124
+ <Select
125
+ name="role"
126
+ value={role}
127
+ onChange={(value) => {
128
+ if (typeof value === "string") setRole(value)
129
+ }}
130
+ isDisabled={isInviting}
131
+ variant="secondary"
132
+ fullWidth
133
+ >
134
+ <Label>{organizationLocalization.role}</Label>
135
+
136
+ <Select.Trigger>
137
+ <Select.Value />
138
+ <Select.Indicator />
139
+ </Select.Trigger>
140
+
141
+ <Select.Popover>
142
+ <ListBox>
143
+ {Object.entries(roles).map(([key, label]) => (
144
+ <ListBox.Item key={key} id={key} textValue={label}>
145
+ {label}
146
+
147
+ <ListBox.ItemIndicator />
148
+ </ListBox.Item>
149
+ ))}
150
+ </ListBox>
151
+ </Select.Popover>
152
+
153
+ <FieldError />
154
+ </Select>
155
+ </AlertDialog.Body>
156
+
157
+ <AlertDialog.Footer>
158
+ <Button slot="close" variant="tertiary" isDisabled={isInviting}>
159
+ {localization.settings.cancel}
160
+ </Button>
161
+
162
+ <Button
163
+ type="submit"
164
+ isPending={isInviting}
165
+ isDisabled={!isRoleValid}
166
+ >
167
+ {isInviting && <Spinner color="current" size="sm" />}
168
+
169
+ {organizationLocalization.inviteMember}
170
+ </Button>
171
+ </AlertDialog.Footer>
172
+ </Form>
173
+ </AlertDialog.Dialog>
174
+ </AlertDialog.Container>
175
+ </AlertDialog.Backdrop>
176
+ )
177
+ }
@@ -0,0 +1,95 @@
1
+ import {
2
+ type OrganizationAuthClient,
3
+ useAuth,
4
+ useAuthPlugin,
5
+ useLeaveOrganization
6
+ } from "@better-auth-ui/react"
7
+ import { ArrowRightFromSquare } from "@gravity-ui/icons"
8
+ import { AlertDialog, Button, Card, Spinner, toast } from "@heroui/react"
9
+ import type { Organization } from "better-auth/client"
10
+
11
+ import { organizationPlugin } from "../../../lib/auth/organization-plugin"
12
+ import { OrganizationView } from "./organization-view"
13
+
14
+ export type LeaveOrganizationDialogProps = {
15
+ isOpen: boolean
16
+ onOpenChange: (open: boolean) => void
17
+ organization: Organization
18
+ }
19
+
20
+ export function LeaveOrganizationDialog({
21
+ isOpen,
22
+ onOpenChange,
23
+ organization
24
+ }: LeaveOrganizationDialogProps) {
25
+ const { authClient, basePaths, localization, navigate } = useAuth()
26
+ const {
27
+ localization: organizationLocalization,
28
+ viewPaths: organizationPluginViewPaths
29
+ } = useAuthPlugin(organizationPlugin)
30
+
31
+ const { mutate: leaveOrganization, isPending } = useLeaveOrganization(
32
+ authClient as OrganizationAuthClient,
33
+ {
34
+ onSuccess: () => {
35
+ onOpenChange(false)
36
+ toast.success(organizationLocalization.leftOrganization)
37
+
38
+ navigate({
39
+ to: `${basePaths.settings}/${organizationPluginViewPaths.settings.organizations}`,
40
+ replace: true
41
+ })
42
+ }
43
+ }
44
+ )
45
+
46
+ return (
47
+ <AlertDialog.Backdrop isOpen={isOpen} onOpenChange={onOpenChange}>
48
+ <AlertDialog.Container>
49
+ <AlertDialog.Dialog>
50
+ <AlertDialog.CloseTrigger />
51
+
52
+ <AlertDialog.Header>
53
+ <AlertDialog.Icon status="danger">
54
+ <ArrowRightFromSquare />
55
+ </AlertDialog.Icon>
56
+
57
+ <AlertDialog.Heading>
58
+ {organizationLocalization.leaveOrganization}
59
+ </AlertDialog.Heading>
60
+ </AlertDialog.Header>
61
+
62
+ <AlertDialog.Body className="flex flex-col gap-4 overflow-visible">
63
+ <p className="text-muted text-sm">
64
+ {organizationLocalization.leaveOrganizationDescription}
65
+ </p>
66
+
67
+ <Card variant="secondary">
68
+ <Card.Content>
69
+ <OrganizationView organization={organization} hideRole />
70
+ </Card.Content>
71
+ </Card>
72
+ </AlertDialog.Body>
73
+
74
+ <AlertDialog.Footer>
75
+ <Button slot="close" variant="tertiary" isDisabled={isPending}>
76
+ {localization.settings.cancel}
77
+ </Button>
78
+
79
+ <Button
80
+ variant="danger"
81
+ isPending={isPending}
82
+ onPress={() =>
83
+ leaveOrganization({ organizationId: organization.id })
84
+ }
85
+ >
86
+ {isPending && <Spinner color="current" size="sm" />}
87
+
88
+ {organizationLocalization.leaveOrganization}
89
+ </Button>
90
+ </AlertDialog.Footer>
91
+ </AlertDialog.Dialog>
92
+ </AlertDialog.Container>
93
+ </AlertDialog.Backdrop>
94
+ )
95
+ }
@@ -0,0 +1,59 @@
1
+ import {
2
+ type OrganizationAuthClient,
3
+ useActiveOrganization,
4
+ useAuth,
5
+ useAuthPlugin
6
+ } from "@better-auth-ui/react"
7
+ import { AlertDialog, Button } from "@heroui/react"
8
+ import { useState } from "react"
9
+
10
+ import { organizationPlugin } from "../../../lib/auth/organization-plugin"
11
+ import { LeaveOrganizationDialog } from "./leave-organization-dialog"
12
+
13
+ /**
14
+ * Danger-zone row to leave the active organization.
15
+ */
16
+ export function LeaveOrganization() {
17
+ const { authClient } = useAuth()
18
+ const { localization: organizationLocalization } =
19
+ useAuthPlugin(organizationPlugin)
20
+
21
+ const { data: activeOrganization } = useActiveOrganization(
22
+ authClient as OrganizationAuthClient
23
+ )
24
+
25
+ const [confirmOpen, setConfirmOpen] = useState(false)
26
+
27
+ return (
28
+ <div className="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
29
+ <div>
30
+ <p className="text-sm font-medium leading-tight">
31
+ {organizationLocalization.leaveOrganization}
32
+ </p>
33
+
34
+ <p className="text-muted mt-0.5 text-xs">
35
+ {organizationLocalization.leaveOrganizationDescription}
36
+ </p>
37
+ </div>
38
+
39
+ <AlertDialog>
40
+ <Button
41
+ isDisabled={!activeOrganization}
42
+ size="sm"
43
+ variant="danger-soft"
44
+ onPress={() => setConfirmOpen(true)}
45
+ >
46
+ {organizationLocalization.leaveOrganization}
47
+ </Button>
48
+
49
+ {activeOrganization && (
50
+ <LeaveOrganizationDialog
51
+ isOpen={confirmOpen}
52
+ onOpenChange={setConfirmOpen}
53
+ organization={activeOrganization}
54
+ />
55
+ )}
56
+ </AlertDialog>
57
+ </div>
58
+ )
59
+ }
@@ -0,0 +1,68 @@
1
+ import {
2
+ type OrganizationAuthClient,
3
+ useAuth,
4
+ useHasPermission
5
+ } from "@better-auth-ui/react"
6
+ import { Card, type CardProps, cn } from "@heroui/react"
7
+ import type { ComponentProps } from "react"
8
+
9
+ import { DeleteOrganization } from "./delete-organization"
10
+ import { DeleteOrganizationSkeleton } from "./delete-organization-skeleton"
11
+ import { LeaveOrganization } from "./leave-organization"
12
+
13
+ export type OrganizationDangerZoneProps = {
14
+ className?: string
15
+ variant?: CardProps["variant"]
16
+ }
17
+
18
+ /**
19
+ * Danger zone heading with {@link LeaveOrganization} and {@link DeleteOrganization}
20
+ * for the active organization in a single card.
21
+ *
22
+ * Resolves the `organization:delete` permission before rendering anything to
23
+ * avoid flashing {@link LeaveOrganization} (and a stray separator) before the
24
+ * delete row appears or disappears. Inner {@link DeleteOrganization} also
25
+ * self-gates so it stays safe to use standalone.
26
+ */
27
+ export function OrganizationDangerZone({
28
+ className,
29
+ variant,
30
+ ...props
31
+ }: OrganizationDangerZoneProps & ComponentProps<"div">) {
32
+ const { authClient, localization } = useAuth()
33
+
34
+ const { data: deletePermission, isPending: deletePermissionPending } =
35
+ useHasPermission(authClient as OrganizationAuthClient, {
36
+ permissions: { organization: ["delete"] }
37
+ })
38
+
39
+ const canDelete = !!deletePermission?.success
40
+
41
+ return (
42
+ <div className={cn("flex w-full flex-col", className)} {...props}>
43
+ <h2 className={cn("mb-3 text-sm font-semibold text-danger")}>
44
+ {localization.settings.dangerZone}
45
+ </h2>
46
+
47
+ <Card variant={variant}>
48
+ <Card.Content className="gap-0">
49
+ {deletePermissionPending ? (
50
+ <DeleteOrganizationSkeleton />
51
+ ) : (
52
+ <>
53
+ <LeaveOrganization />
54
+
55
+ {canDelete && (
56
+ <>
57
+ <div className="border-b border-dashed -mx-4 my-4" />
58
+
59
+ <DeleteOrganization />
60
+ </>
61
+ )}
62
+ </>
63
+ )}
64
+ </Card.Content>
65
+ </Card>
66
+ </div>
67
+ )
68
+ }
@@ -0,0 +1,29 @@
1
+ import { Skeleton, Table } from "@heroui/react"
2
+
3
+ /**
4
+ * Placeholder row matching {@link OrganizationInvitationTableRow} while
5
+ * invitations load.
6
+ */
7
+ export function OrganizationInvitationRowSkeleton() {
8
+ return (
9
+ <Table.Row>
10
+ <Table.Cell>
11
+ <Skeleton className="h-4 w-48 rounded-lg" />
12
+ </Table.Cell>
13
+
14
+ <Table.Cell>
15
+ <Skeleton className="h-4 w-36 rounded-lg" />
16
+ </Table.Cell>
17
+
18
+ <Table.Cell>
19
+ <Skeleton className="h-4 w-16 rounded-lg" />
20
+ </Table.Cell>
21
+
22
+ <Table.Cell>
23
+ <Skeleton className="h-4 w-14 rounded-full" />
24
+ </Table.Cell>
25
+
26
+ <Table.Cell />
27
+ </Table.Row>
28
+ )
29
+ }